feat(recovery,context): tier-2 intent-holder arbiter + remaining-delta pinning + surfaced signal events

- recovery: two-tier repair ladder — owner then arbiter (recovery stage recast
  as intent-holder, holds initial intent, reconciles cross-file contract disputes)
  with independent INTENT_ROUTE_BUDGET; RecoveryRoutingTest coverage
- context: remaining-delta checklist pinning (RemainingDelta{Pinning,Entry}Test)
- surface write-only events (session name, quality signals) into stats/browse
- parseToolArguments lenient-Json fallback for bare-key drift
- tools: ChildProcess seam
This commit is contained in:
2026-07-11 23:56:52 +04:00
parent 3d5e05c1fb
commit 15248cae8a
55 changed files with 1932 additions and 231 deletions
@@ -79,12 +79,15 @@ Emit a JSON object that validates against the `execution_plan` schema:
decompose tasks here — task creation is out of scope for the plan.
- Keep stages small and single-responsibility. Prefer more stages over large monolithic
prompts.
- **Scaffolding uses `file_write`, never a network installer.** A stage that sets up a project
writes `package.json`, config files, and sources directly with `file_write` — it does not
shell out to `npm create vite`, `create-react-app`, `npx`, or any `create`/`init` scaffolder.
Those fetch remote code and prompt on stdin; the run is unattended (no TTY) so they hang, and
`shell` rejects them outright. `shell` in a scaffold stage is for `npm install` / `npm run
build` on files that already exist, not for generating the project.
- **Prefer the real scaffolder over hand-writing config.** A stage that sets up a project should
use the package manager's own generator — e.g. `npm create vite@latest <dir> -- --template
react-ts` — because it produces a correct, complete, current file set (a hand-written
`package.json` reliably forgets something). Runs are unattended, but the shell forces
non-interactive mode (stdin closed, `CI=true`), so `npm create`/`npm init` no longer hang;
always pass the template/preset arg the generator requires (`-- --template react-ts`) since
there's no prompt to fall back on. `file_write` is the fallback when no generator fits the
stack. Only bare remote runners (`npx`, `bunx`, `pnpx`) stay blocked — they execute arbitrary
remote code; reach them via `npm create` instead.
- **Every stage prompt must describe its exact JSON output structure when using a
structured kind.** The model that runs the stage never sees the raw JSON schema — it only sees
the kind's name (e.g. `analysis`, `research_report`, `review_report`) and the prompt you write