Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
99c6012
feat(review): run-session ledger and cross-session agent evidence
wenshao Aug 13, 2026
bd3ffe7
fix(review): address review feedback on the session ledger
wenshao Aug 13, 2026
4648428
fix(review): keep the run epoch stable and the continuity note non-ca…
wenshao Aug 13, 2026
6fb01c0
fix(review): contain, bound and supersede the prior-session reads
wenshao Aug 13, 2026
ea40030
docs(review): say what the recoveredAgents bar actually is
wenshao Aug 14, 2026
5186ab8
fix(review): bill a resumed run once, clamp its agents, and say what …
wenshao Aug 14, 2026
c5a4de7
fix(review): refuse mid-flight credit, key the fence exactly, fold th…
wenshao Aug 14, 2026
a67a2db
fix(review): gate prior evidence on an authorized resume, and bound w…
wenshao Aug 14, 2026
e6260ca
fix(review): drop unfinished prior records at the source, and not cou…
wenshao Aug 14, 2026
1004c21
fix(review): bill each attempt from its own start, and require delive…
wenshao Aug 14, 2026
a70ea21
fix(review): close the certification, epoch and supersession gaps the…
wenshao Aug 14, 2026
4ae1c31
fix(review): compare the plan-mtime fence within a millisecond, not e…
wenshao Aug 14, 2026
b39a12d
feat(review): expose the ledger's session count without the evidence …
wenshao Aug 15, 2026
0e41bfe
fix(review): verify against the CURRENT findings digest, and close th…
wenshao Aug 15, 2026
259758b
fix(review): close the round-4 blockers a paginated sweep surfaced
wenshao Aug 15, 2026
e2a088e
fix(review): validate ledger entries before the cap consumes them
wenshao Aug 15, 2026
a15093b
fix(review): work through the round-3-to-6 suggestion backlog
wenshao Aug 15, 2026
84c75ff
fix(review): close round 7 on the ledger — cap order, prior prefix, d…
wenshao Aug 15, 2026
81455da
fix(review): work through the round-7 suggestions on the ledger PR
wenshao Aug 15, 2026
ea2d396
fix(review): round-9 blockers — single-read ledger writers, lifecycle…
wenshao Aug 16, 2026
852b9e8
test(review): give the inode probe an imposter that cannot recycle th…
wenshao Aug 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
622 changes: 622 additions & 0 deletions packages/cli/src/commands/review/check-coverage.test.ts

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions packages/cli/src/commands/review/cleanup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ import { clearReviewWorktreeLease } from '../../services/review-worktree-lease.j
import { currentUser, getGhHost, ghApiAll, setGhHost } from './lib/gh.js';
import { parseReceiptIds } from './lib/receipt.js';
import { refExists, releaseWorktree } from './lib/git.js';
import { readBudgetStopUnfenced, runEpochMs } from './lib/deadline.js';
import { promptRecordDir } from './lib/prompt-record.js';
import { readBudgetStopUnfenced } from './lib/deadline.js';
import { promptRecordDir, runEpochMs } from './lib/prompt-record.js';
import {
worktreePath,
probeWorktreePath,
Expand Down
114 changes: 110 additions & 4 deletions packages/cli/src/commands/review/compose-review.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { tmpdir } from 'node:os';
import { dirname, join } from 'node:path';
import { createHash } from 'node:crypto';
import { promptRecordDir, briefPath } from './lib/prompt-record.js';
import { appendRunSession, recordResume } from './lib/run-ledger.js';
import { writeBudgetStop, writeRoundCapStop } from './lib/deadline.js';
import { getGhHost, setGhHost } from './lib/gh.js';
import { parseLedger } from './lib/ledger.js';
Expand Down Expand Up @@ -339,6 +340,34 @@ function transcript(
);
}

/**
* Move one agent's transcript into a ledgered PRIOR session — the shape a
* resumed run reads.
*
* The records are re-stamped with the owning session (a transcript copied
* into another session's directory is not that session's evidence, and
* production refuses the misplaced shape), and the ledger is written by the
* real writer so the entries carry the plan mtime they are keyed on. The
* current attempt is stamped last and its resume recorded: reading prior
* evidence at all requires that authorization.
*/
function rehomeToPriorSession(planPath: string, file: string): void {
mkdirSync(join(dir, 'subagents', 'S0'), { recursive: true });
const from = join(dir, 'subagents', 'S1', file);
writeFileSync(
join(dir, 'subagents', 'S0', file),
readFileSync(from, 'utf8').replaceAll(
'"sessionId":"S1"',
'"sessionId":"S0"',
),
);
rmSync(from, { force: true });
const now = Date.now();
appendRunSession(planPath, { QWEN_CODE_SESSION_ID: 'S0' }, now);
appendRunSession(planPath, { QWEN_CODE_SESSION_ID: 'S1' }, now + 1500);
recordResume(planPath, ENV, now + 1500);
}

/**
* A prompt the CLI would have built: it names the diff and the read of THIS
* chunk's lines. The offsets are the chunk's own, as `agent-prompt` emits them —
Expand Down Expand Up @@ -548,14 +577,26 @@ describe('composeReview — modeled-system defect-layer cap', () => {
];
const walked = (...ids: string[]) =>
ids.map((id) => `Layer walked: ${id} — clear.`).join('\n');
// A genuine reverse-audit auditor: the identity line, a real diff read
// (so `diffToolCalls > 0`), and the given receipts as its final text.
const auditor = (id: string, receipts: string) =>
transcript(id, `${IDENTITY}\nread_file(file_path="${DIFF}")`, {
// A GENUINE auditor: launched with the prompt the CLI recorded for the
// role, and it opened the brief that prompt points at (plus a real diff
// read, receipts as final text). A receipt only counts from one of these —
// otherwise a compliant sibling's floor could carry a hand-written
// auditor's claims. (The earlier fixture matched on a bare IDENTITY
Comment on lines +583 to +584

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] R7-6: R7-6 re-check — still stands. The compose parrot/ra-off negative fixtures now fail delivered() FIRST (their bare-IDENTITY launches match no recorded prompt), so the t.diffToolCalls > 0 clause they were written to pin is masked; and the new layer-audit-gate fixture 'refuses a delivered auditor with ZERO diff reads' keeps a baked range in its launch, so openedTheTerritory rejects first when the clause is deleted — the clause remains unpinned everywhere (the round-8 filing R8-27 carries the concrete fix). — Failure scenario: Deleting t.diffToolCalls > 0 from the gate's corroborated filter ships green across both suites: an auditor that got the recorded prompt and opened its brief but never read the diff supplies all six Layer-walked receipts toward releasing a modeled-system diff whose layers were never walked.

Suggested fix: Per R8-27: add a whole-diff auditor fixture (range-free launch, brief opened, zero diff calls, six receipts) asserting 6 owed; optionally re-shape the compose parrot to pass delivered() with zero diff calls.

中文说明

R7-6 复核——仍成立。compose 的 parrot/ra-off 负例 fixture 如今先失败在 delivered()(裸 IDENTITY launch 与任何录制 prompt 都不逐字匹配),其原本要钉的 t.diffToolCalls > 0 子句被遮蔽;layer-audit-gate 新 fixture “ZERO diff reads” 的 launch 仍带烘焙范围,删除子句时 openedTheTerritory 先行拒绝——该子句在两处都未钉扎(第 8 轮提交 R8-27 给出具体修复)。后果:拿到录制 prompt、开过 brief 但从未读 diff 的 auditor 可贡献全部六层收据,放行层级从未走过的建模系统 diff。建议:按 R8-27 补 whole-diff auditor fixture;可选地把 compose parrot 改为“通过 delivered() 且零 diff 调用”。

— qwen3.8-max via Qwen Code /review (v0.21.12)

// constant; the gate no longer accepts that shape.)
Comment thread
wenshao marked this conversation as resolved.
const auditor = (id: string, receipts: string) => {
Comment thread
wenshao marked this conversation as resolved.
const planPath = join(dir, 'plan.json');
const brief = briefPath(planPath, 'reverse-audit');
const launch =
'You are review agent `reverse-audit`.\n' +
`read_file(file_path="${brief}")\n` +
`read_file(file_path="${DIFF}")`;
transcript(id, launch, {
toolCalls: 1,
range: [0, 100],
opens: [brief],
text: receipts,
});
};
const markedPlan = (domains: string[]) =>
coveredPlan(['verify', 'reverse-audit'], {
repositoryContext: sentinel(domains),
Expand Down Expand Up @@ -5791,3 +5832,68 @@ describe('composeReview — unresolved-Critical rendering (#8388 readability)',
expect(r.body).toContain('comment 102 (b.ts) — body truncated');
});
});

describe('composeReview — a resumed run is continuity, not a coverage gap', () => {
it('stays APPROVE and renders the non-capping continuity note', () => {
// The interrupted attempt's chunk-1 agent, re-homed into session S0 and
// named by the run ledger; the current session covers the rest. The
// recovered work COUNTS as reviewed: no cap, no "Not reviewed:" entry —
// a capping entry here downgraded every clean resumed run to COMMENT,
// permanently, since the prior records never leave the ledger.
// Build the input FIRST: `base()`'s object literal evaluates its
// `planPath: coveredPlan()` default even when the caller overrides it,
// and `coveredPlan()` rewrites the current session's chunk-1 record —
// which would then supersede the prior one and (correctly) stop counting
// as recovered work.
const input = base({});
rehomeToPriorSession(input.planPath as string, 'agent-a1.jsonl');

const r = composeReview(input);
expect(r.event).toBe('APPROVE');
// The EXACT joined body, not a substring: on the approve path the
// separator is chosen per-render, and continuity is the only block
// present here. Asserted as a whole, a separator that forgot this block
// glues the note onto the verdict sentence with a single space; asserted
// with `toContain`, that reads identically.
expect(r.body).toBe(
'No issues found. LGTM! ✅\n\n' +
'Resumed run (not a gap): 1 agent result(s) from the interrupted ' +
'earlier attempt were re-certified from the harness records and ' +
'counted as reviewed.\n\n' +
'_— test-model via Qwen Code /review (vunknown)_',
);
expect(r.body).not.toContain('Not reviewed: review continuity');
expect(r.body).not.toContain('Partially reviewed');
});
});

describe('composeReview — continuity renders on every verdict', () => {
/**
* A resumed run: chunk-1's agent re-homed to the ledgered prior session.
*
* `base()`'s object literal evaluates its `planPath: coveredPlan()` default
* even when the caller overrides it, and `coveredPlan()` REWRITES
* `subagents/S1/agent-a1.jsonl` — so the move must happen after `base()`
* has been built, not before. Callers pass the input through here.
*/
function resumedInput(
over: Partial<ComposeReviewInput> = {},
): ComposeReviewInput {
const input = base(over);
const p = input.planPath as string;
rehomeToPriorSession(p, 'agent-a1.jsonl');
return input;
}

it('renders on REQUEST_CHANGES', () => {
const r = composeReview(resumedInput({ criticalsInline: 1 }));
expect(r.event).toBe('REQUEST_CHANGES');
expect(r.body).toContain('Resumed run (not a gap): 1 agent result(s)');
});

it('renders on COMMENT', () => {
const r = composeReview(resumedInput({ suggestionsInline: 1 }));
expect(r.event).toBe('COMMENT');
expect(r.body).toContain('Resumed run (not a gap): 1 agent result(s)');
});
});
28 changes: 27 additions & 1 deletion packages/cli/src/commands/review/compose-review.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1051,6 +1051,12 @@ function composeReviewBody(
// on every gap here would make the soft ceiling hard: any large diff's
// routine budget stop would forbid an Approve the review otherwise earned.
const budgetGapNotes: Array<{ agent: string; gaps: string[] }> = [];
// Certified agent results recovered from an interrupted earlier attempt
// (a resumed run). Informational, NEVER capping: recovered work is counted
// AS reviewed, so it must not ride `coverageEntries` — an entry there caps
// the verdict and renders under "Not reviewed:", the exact opposite of the
// fact. Rendered as its own disclosed-but-not-capping block below.
let recoveredFromPriorAttempt = 0;
// Sibling caps MAX_DIMENSIONS and MAX_NOTES bound their lists for the
// same reason; this bounds the one budget-gap sentence.
const MAX_BUDGET_GAP_LINES = 5;
Expand Down Expand Up @@ -1255,6 +1261,7 @@ function composeReviewBody(
);
}
budgetGapNotes.push(...cov.budgetGaps);
recoveredFromPriorAttempt = cov.recoveredAgents;
Comment thread
wenshao marked this conversation as resolved.
// The prompt was built in code and edited on the way to the agent. This caps
// for the same reason the others do: what the agent was actually asked is not
// what this skill's guarantees are written against.
Expand Down Expand Up @@ -2079,6 +2086,19 @@ function composeReviewBody(
]
: [];

// The resumed-run continuity note: the run reused certified work from an
// interrupted earlier attempt. Disclosed on every verdict — Approve
// included — and never capping: the recovered agents were re-certified
// from the harness records and COUNT as reviewed.
const continuityBlock: Bi[] = recoveredFromPriorAttempt
? [
{
en: `Resumed run (not a gap): ${recoveredFromPriorAttempt} agent result(s) from the interrupted earlier attempt were re-certified from the harness records and counted as reviewed.`,
zh: `续跑运行(非缺口):复用了被中断的前一次尝试的 ${recoveredFromPriorAttempt} 个 agent 结果,均已按 harness 记录重新认证并计入审查。`,
},
]
: [];

if (event === 'REQUEST_CHANGES') {
// Empty body, except the disclosures: every clause whose state holds
// appears on every event — a confirmed blocker must not squeeze out the
Expand All @@ -2096,6 +2116,7 @@ function composeReviewBody(
...repositoryContextBlock,
...unlicensedDeferralBlock,
...deferredSuggestionsBlock,
...continuityBlock,
...bodyCriticalBlock,
];
return {
Expand Down Expand Up @@ -2134,12 +2155,14 @@ function composeReviewBody(
...repositoryContextBlock,
...unlicensedDeferralBlock,
...deferredSuggestionsBlock,
...continuityBlock,
],
notReviewedParts.length ||
deferredBlock.length ||
testPlanBlock.length ||
repositoryContextBlock.length ||
deferredSuggestionsBlock.length
deferredSuggestionsBlock.length ||
continuityBlock.length
Comment thread
wenshao marked this conversation as resolved.
? '\n\n'
: ' ',
),
Expand Down Expand Up @@ -2295,6 +2318,9 @@ function composeReviewBody(
// precedes the list (non-capping).
clauses.push(...unlicensedDeferralBlock);
clauses.push(...deferredSuggestionsBlock);
// 6e. Resumed-run continuity (non-capping) — reused work that COUNTS as
// reviewed, disclosed so the author knows two attempts fed this verdict.
clauses.push(...continuityBlock);

// 7. Body Criticals — on a COMMENT that stands where a REQUEST_CHANGES
// would have been: the presubmit carve-out, and the unverified-blockers
Expand Down
Loading
Loading