fix(review): changed code and instruction files get deep review by default, summary-only is for docs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
b16e39ccd9
commit
761f406faa
6 changed files with 75 additions and 8 deletions
|
|
@ -565,7 +565,7 @@ The history is the `review.md` files your repo already has; no new store.
|
||||||
|
|
||||||
### Triage gate (deterministic)
|
### Triage gate (deterministic)
|
||||||
|
|
||||||
A path-pattern classifier produces `{file → deep-review|summary-only|skip}` before any LLM runs. Hardcoded skip patterns: `*.lock`, `*.svg`, `dist/**`, `build/**`, `node_modules/**`, generated markers. Deep-review patterns: `auth/**`, `crypto/**`, `**/security/**`. Hard refuse-with-suggestion above 100 files / 100K diff tokens.
|
A path-pattern classifier produces `{file → deep-review|summary-only|skip}` before any LLM runs. Hardcoded skip patterns: `*.lock`, `*.svg`, `dist/**`, `build/**`, `node_modules/**`, generated markers. `deep-review`: default for every changed file not in the other two rows — code, tests, `commands/`, `agents/`, `skills/` Markdown, and the instruction files `CLAUDE.md`, `AGENTS.md` and `.claude/rules/**`. `summary-only`: `docs/**`, Markdown files at the repo root other than `CLAUDE.md` and `AGENTS.md` (README, CHANGELOG), `tests/fixtures/**`. Hard refuse-with-suggestion above 100 files / 100K diff tokens.
|
||||||
|
|
||||||
### Feedback loop (Handover 6)
|
### Feedback loop (Handover 6)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -123,8 +123,8 @@ produces a treatment map:
|
||||||
| Treatment | When |
|
| Treatment | When |
|
||||||
|-----------|------|
|
|-----------|------|
|
||||||
| `skip` | Matches `*.lock`, `*.svg`, `dist/**`, `build/**`, `node_modules/**`, generated-file marker present in first 3 lines |
|
| `skip` | Matches `*.lock`, `*.svg`, `dist/**`, `build/**`, `node_modules/**`, generated-file marker present in first 3 lines |
|
||||||
| `deep-review` | Matches `auth/**`, `crypto/**`, `**/security/**`, `hooks/**` |
|
| `deep-review` | Default for every changed file not in the other two rows — code, tests, `commands/`, `agents/`, `skills/` Markdown, and the instruction files `CLAUDE.md`, `AGENTS.md` and `.claude/rules/**` |
|
||||||
| `summary-only` | Default treatment for everything else |
|
| `summary-only` | `docs/**`, Markdown files at the repo root other than `CLAUDE.md` and `AGENTS.md` (README, CHANGELOG), `tests/fixtures/**` |
|
||||||
|
|
||||||
Hard refuse-with-suggestion gates (use AskUserQuestion):
|
Hard refuse-with-suggestion gates (use AskUserQuestion):
|
||||||
- > 100 files in the diff
|
- > 100 files in the diff
|
||||||
|
|
|
||||||
|
|
@ -184,8 +184,8 @@ every file from Phase 3 into a treatment bucket:
|
||||||
| Treatment | When |
|
| Treatment | When |
|
||||||
|-----------|------|
|
|-----------|------|
|
||||||
| `skip` | Matches `*.lock`, `*.svg`, `dist/**`, `build/**`, `node_modules/**`, OR the file's first 3 lines contain a generated-file marker (`@generated`, `Code generated by`, `DO NOT EDIT`). |
|
| `skip` | Matches `*.lock`, `*.svg`, `dist/**`, `build/**`, `node_modules/**`, OR the file's first 3 lines contain a generated-file marker (`@generated`, `Code generated by`, `DO NOT EDIT`). |
|
||||||
| `deep-review` | Matches `auth/**`, `crypto/**`, `**/security/**`, `hooks/**`. |
|
| `deep-review` | Default for every changed file not in the other two rows — code, tests, `commands/`, `agents/`, `skills/` Markdown, and the instruction files `CLAUDE.md`, `AGENTS.md` and `.claude/rules/**`. |
|
||||||
| `summary-only` | Default treatment for everything else. |
|
| `summary-only` | `docs/**`, Markdown files at the repo root other than `CLAUDE.md` and `AGENTS.md` (README, CHANGELOG), `tests/fixtures/**`. |
|
||||||
|
|
||||||
Hard refuse-with-suggestion gates — use `AskUserQuestion`:
|
Hard refuse-with-suggestion gates — use `AskUserQuestion`:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -187,7 +187,7 @@ function reviewerPrompt(kind, a) {
|
||||||
'Only emit findings whose rule_key is in the catalogue. Cite file:line from the diff.',
|
'Only emit findings whose rule_key is in the catalogue. Cite file:line from the diff.',
|
||||||
'',
|
'',
|
||||||
'=== TRIAGE MAP (respect skip decisions) ===',
|
'=== TRIAGE MAP (respect skip decisions) ===',
|
||||||
a.triage || '(no triage map supplied — treat all changed files as summary-only)',
|
a.triage || '(no triage map supplied — deep-review every changed file except docs/**, root Markdown other than CLAUDE.md and AGENTS.md, and tests/fixtures/**)',
|
||||||
].join('\n');
|
].join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,8 @@ should look at first.
|
||||||
|
|
||||||
| File | Treatment | Reason |
|
| File | Treatment | Reason |
|
||||||
|------|-----------|--------|
|
|------|-----------|--------|
|
||||||
| lib/foo.mjs | deep-review | matched deep-review pattern |
|
| lib/foo.mjs | deep-review | default for changed code |
|
||||||
| lib/bar.mjs | summary-only | low-risk, no test patterns matched |
|
| docs/guide.md | summary-only | docs/** is summary-only |
|
||||||
| dist/bundle.js | skip | matches generated-file pattern |
|
| dist/bundle.js | skip | matches generated-file pattern |
|
||||||
| commands/baz.md `[uncommitted]` | deep-review | working-tree change since session_start_sha |
|
| commands/baz.md `[uncommitted]` | deep-review | working-tree change since session_start_sha |
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1256,3 +1256,70 @@ test('[#113] sibling: agents/research-orchestrator.md', () => {
|
||||||
assert.ok(flat(read(RESEARCH_ORCH)).includes('| `contrarian-researcher` | Counter-evidence, overlooked alternatives, reasons to reconsider; runs in wave 2, against wave 1\'s leading answer |'),
|
assert.ok(flat(read(RESEARCH_ORCH)).includes('| `contrarian-researcher` | Counter-evidence, overlooked alternatives, reasons to reconsider; runs in wave 2, against wave 1\'s leading answer |'),
|
||||||
'the agent table does not say the contrarian runs in wave 2');
|
'the agent table does not say the contrarian runs in wave 2');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// --- F9: changed code and instruction files get deep review by default ------
|
||||||
|
// The triage table made `summary-only` the default treatment for everything
|
||||||
|
// else, so changed code outside auth/crypto/security/hooks got a structural
|
||||||
|
// pass only. `deep-review` is now the default for every changed file not in
|
||||||
|
// the other two rows, the instruction files CLAUDE.md, AGENTS.md and
|
||||||
|
// .claude/rules/** among them; `summary-only` is for docs/**, root Markdown
|
||||||
|
// other than CLAUDE.md and AGENTS.md, and tests/fixtures/**. The four copies
|
||||||
|
// (command, orchestrator, README, workflow fallback, template rows) say the
|
||||||
|
// same; each is pinned by its own test against the phrase set below.
|
||||||
|
|
||||||
|
const REVIEW = 'commands/trekreview.md';
|
||||||
|
const F9_DEEP = 'for every changed file not in the other two rows — code, tests, `commands/`, `agents/`, `skills/` Markdown, and the instruction files `CLAUDE.md`, `AGENTS.md` and `.claude/rules/**`';
|
||||||
|
const F9_SUMMARY = '`docs/**`, Markdown files at the repo root other than `CLAUDE.md` and `AGENTS.md` (README, CHANGELOG), `tests/fixtures/**`';
|
||||||
|
const F9_OLD = /Default treatment for everything else/;
|
||||||
|
|
||||||
|
/** The one table row in `text` whose first cell is `cell`. */
|
||||||
|
function f9Row(text, cell) {
|
||||||
|
const hits = text.split('\n').filter((l) => l.startsWith(`| ${cell} |`));
|
||||||
|
assert.equal(hits.length, 1, `expected exactly one "${cell}" row; found ${hits.length}`);
|
||||||
|
return hits[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The deep-review and summary-only rows hold the phrase set; the old default is gone. */
|
||||||
|
function f9Table(text, where) {
|
||||||
|
assert.doesNotMatch(text, F9_OLD, `${where}: summary-only is still the default treatment for everything else`);
|
||||||
|
const deep = f9Row(text, '`deep-review`');
|
||||||
|
assert.match(deep, /\| Default for every changed file/, `${where}: the deep-review row does not name the default`);
|
||||||
|
assert.ok(deep.includes(F9_DEEP), `${where}: the deep-review row does not name code, tests and CLAUDE.md, AGENTS.md, .claude/rules/**`);
|
||||||
|
const summary = f9Row(text, '`summary-only`');
|
||||||
|
assert.ok(summary.includes(F9_SUMMARY), `${where}: the summary-only row is not docs/**, root Markdown, tests/fixtures/**`);
|
||||||
|
assert.doesNotMatch(summary, /[Dd]efault/, `${where}: the summary-only row still claims the default`);
|
||||||
|
assert.match(f9Row(text, '`skip`'), /Matches `\*\.lock`, `\*\.svg`, `dist\/\*\*`, `build\/\*\*`, `node_modules\/\*\*`/, `${where}: the skip row changed`);
|
||||||
|
}
|
||||||
|
|
||||||
|
test('[F9] the trekreview triage table makes deep-review the default, naming CLAUDE.md, AGENTS.md and .claude/rules/**; summary-only is for docs; the size gate is unchanged', () => {
|
||||||
|
const p4 = section(read(REVIEW), '## Phase 4 — Triage gate (deterministic path-pattern classifier)');
|
||||||
|
f9Table(p4, REVIEW);
|
||||||
|
assert.ok(p4.includes('if (reviewed_files_count > 100) → ask user'), 'the file-count gate changed');
|
||||||
|
assert.ok(p4.includes('if (estimated_diff_tokens > 100000) → ask user'), 'the diff-token gate changed');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('[F9] sibling: agents/review-orchestrator.md', () => {
|
||||||
|
f9Table(section(read('agents/review-orchestrator.md'), '### Phase 4 — Triage gate (path-pattern classifier)'), 'agents/review-orchestrator.md');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('[F9] sibling: README.md', () => {
|
||||||
|
const tri = flat(section(read('README.md'), '### Triage gate (deterministic)'));
|
||||||
|
assert.doesNotMatch(tri, /Deep-review patterns: `auth\/\*\*`, `crypto\/\*\*`, `\*\*\/security\/\*\*`\./, 'README.md still limits deep-review to auth/crypto/security');
|
||||||
|
assert.ok(tri.includes(`\`deep-review\`: default ${F9_DEEP}.`), 'README.md does not make deep-review the default with the instruction files');
|
||||||
|
assert.ok(tri.includes(`\`summary-only\`: ${F9_SUMMARY}.`), 'README.md does not limit summary-only to docs/**, root Markdown, tests/fixtures/**');
|
||||||
|
assert.ok(tri.includes('Hard refuse-with-suggestion above 100 files / 100K diff tokens.'), 'README.md size gate changed');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('[F9] sibling: scripts/trekreview-armB.workflow.mjs', () => {
|
||||||
|
const text = read('scripts/trekreview-armB.workflow.mjs');
|
||||||
|
assert.doesNotMatch(text, /treat all changed files as summary-only/, 'the workflow fallback still treats every file as summary-only');
|
||||||
|
assert.ok(text.includes("a.triage || '(no triage map supplied — deep-review every changed file except docs/**, root Markdown other than CLAUDE.md and AGENTS.md, and tests/fixtures/**)',"),
|
||||||
|
'the workflow fallback does not deep-review every changed file except docs/**, root Markdown other than CLAUDE.md and AGENTS.md, and tests/fixtures/**');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('[F9] sibling: templates/trekreview-template.md', () => {
|
||||||
|
const cov = section(read('templates/trekreview-template.md'), '## Coverage');
|
||||||
|
assert.doesNotMatch(cov, /matched deep-review pattern|no test patterns matched/, 'the template rows still show the old pattern reasons');
|
||||||
|
assert.ok(cov.includes('| lib/foo.mjs | deep-review | default for changed code |'), 'the template has no deep-review default row');
|
||||||
|
assert.ok(cov.includes('| docs/guide.md | summary-only | docs/** is summary-only |'), 'the template has no docs summary-only row');
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue