fix(voyage): inject plan_critic via Phase 9 readAndUpdate (906f155d)
This commit is contained in:
parent
13a83e5a95
commit
5f26de2f0d
2 changed files with 62 additions and 0 deletions
|
|
@ -726,6 +726,47 @@ After both complete:
|
|||
- If only **minor** issues or clean: proceed without changes. Note the
|
||||
review result in the plan.
|
||||
|
||||
### Inject plan_critic verdict into plan frontmatter (post-dedup, post-revise)
|
||||
|
||||
After the dedup pass completes and any blocker/major revisions are folded
|
||||
in, atomically update the plan's frontmatter with the plan-critic verdict
|
||||
so downstream surfaces (notably `playground/voyage-playground.html`
|
||||
`buildArtifactKeyStat`) can read it without re-parsing the review JSON.
|
||||
|
||||
Phase 8 (write plan) precedes Phase 9 (adversarial review), so the
|
||||
verdict cannot be in Phase 8's frontmatter template — it must be
|
||||
injected here, after the verdict exists.
|
||||
|
||||
Read the verdict from `/tmp/plan-critic-out.json` and apply it via
|
||||
`lib/util/markdown-write.mjs` `readAndUpdate`:
|
||||
|
||||
```js
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { readAndUpdate } from `${CLAUDE_PLUGIN_ROOT}/lib/util/markdown-write.mjs`;
|
||||
|
||||
const criticVerdict = JSON.parse(readFileSync('/tmp/plan-critic-out.json', 'utf-8')).verdict;
|
||||
const result = readAndUpdate(planPath, ({ frontmatter, body }) => {
|
||||
frontmatter.plan_critic = criticVerdict;
|
||||
return { frontmatter, body };
|
||||
});
|
||||
if (!result.valid) {
|
||||
// Non-fatal: log warning. plan.md already exists from Phase 8;
|
||||
// missing plan_critic is degraded UX, not blocking.
|
||||
console.warn('plan_critic injection failed:', result.errors);
|
||||
}
|
||||
```
|
||||
|
||||
Field semantics:
|
||||
- `plan_critic` — string. One of `APPROVE`, `APPROVE_WITH_NOTES`,
|
||||
`REVISE`, or `BLOCK`. Matches the rubric in `plan-critic` agent
|
||||
output. Omitted when the inject failed (Phase 9 surfaces a warning
|
||||
in that case but does not abort).
|
||||
|
||||
Schema compatibility: `plan_critic` is **additive and optional**. The
|
||||
plan validator (`lib/validators/plan-validator.mjs`) tolerates unknown
|
||||
frontmatter keys, so this addition does NOT require a `plan_version`
|
||||
bump. Plans written before this field was added validate identically.
|
||||
|
||||
## Phase 10 — Present and refine
|
||||
|
||||
Present a summary to the user:
|
||||
|
|
|
|||
|
|
@ -625,3 +625,24 @@ test('docs/annotation-quickstart.md exists with ≤7 numbered steps and example-
|
|||
`${path} must reference the canonical example fixture for hands-on verification`,
|
||||
);
|
||||
});
|
||||
|
||||
test('commands/trekplan.md Phase 9 documents plan_critic injection via readAndUpdate (906f155d)', () => {
|
||||
// Phase 9 (adversarial review) writes the plan-critic verdict back into
|
||||
// plan.md frontmatter AFTER plan-review-dedup completes. The inject must
|
||||
// happen post-Phase-8 (write) because Phase 8 precedes Phase 9 in the
|
||||
// pipeline — the value cannot be in Phase 8's frontmatter template.
|
||||
// Both the field name (plan_critic) and the inject mechanism
|
||||
// (readAndUpdate from lib/util/markdown-write.mjs) must be documented
|
||||
// so future maintainers can trace the contract.
|
||||
const text = read('commands/trekplan.md');
|
||||
assert.match(
|
||||
text,
|
||||
/plan_critic/,
|
||||
'commands/trekplan.md must document plan_critic frontmatter field (906f155d)',
|
||||
);
|
||||
assert.match(
|
||||
text,
|
||||
/readAndUpdate/,
|
||||
'commands/trekplan.md must reference readAndUpdate from lib/util/markdown-write.mjs (906f155d)',
|
||||
);
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue