Projection Remediation — Execution Program
Tracker: docs/programs/PROJECTION_REMEDIATION_TRACKER_2026-05-17.md
Source audit: docs/audits/PROJECTION_SYSTEM_AUDIT_2026-05-17.md
Operating principles
-
Severity then impact then cheap-wins-first. Wave 1 = all P0 items ≤30 min, parallel. Wave 2 = P0 items 1–3 h with deps satisfied. Wave 3 = P0 items 2–4 h + P1 hot items. Wave 4 = 1–2 d items (renderer deploy + tenant projector + non-commodity renderers). Wave 5 = remaining P1 + P2.
-
No subagent claims COMPLETED. Subagent returns
state: VERIFYINGper CLAUDE.md §Subagent Orchestration Rules §1. Orchestrator runs the proof verification per §2 before flipping to COMPLETED on the tracker. If verification fails → flip to BLOCKED, surface to user. -
Pixel + click-through proof for every UI-touching task. Backend tasks require curl_response or db_query. Pipeline tasks require event_in_db or replay_output. See tracker’s per-task
Proof type(s)column. -
One worktree per wave. Each wave creates a single git worktree (
claude/proj-remediation-waveN) where all subagents in that wave commit. Orchestrator opens 1 PR per wave, admin-merges to master after all proofs verify. -
Cron + watchdog re-enabled after Wave 1. P0-02 (pnpm fix) is in Wave 1 precisely so the autonomous verification crons resume early, giving us continuous proof signal for later waves.
-
NO dropping back to legacy patterns. Every fix maintains event-sourcing-first + 4-table discipline + portability rules. If a fix requires a new table → P0-15 + projection-registry update required first.
Reusable subagent brief template
Every dispatched subagent receives a brief in this shape. Substitute <TASK_ID>, <TITLE>, <DETAIL>, <PROOF_REQ>, <TIME>:
You are running **<TASK_ID>: <TITLE>** as part of the FIN projection
remediation program. Self-contained brief — no prior conversation context.
# Mission
<DETAIL>
# Context (read first)
- Tracker entry: docs/programs/PROJECTION_REMEDIATION_TRACKER_2026-05-17.md row <TASK_ID>
- Source audit: docs/audits/PROJECTION_SYSTEM_AUDIT_2026-05-17.md
- Relevant WS report: .audit-2026-05-17/wave<N>/ws-<NN>-*.md
# Worktree
You are in worktree `claude/proj-remediation-wave<N>` based on origin/master.
Other subagents may be working in the same worktree — DO NOT touch files
outside your task scope.
# Steps
<numbered fix steps>
# Proof contract (CLAUDE.md §Subagent Orchestration Rules)
You MUST collect ALL the following proof artifacts before returning:
<PROOF_REQ>
Write each artifact to .artifacts/remediation/<TASK_ID>/<filename>
where <filename> is sensible per artifact type:
- code_commit.sha
- curl-<endpoint>.json
- db-query-<purpose>.txt
- screenshot-<scene>.png
- trace.zip
- replay-<command>.log
# Return contract
End your reply with this block ONLY:
===<TASK_ID>-RESULT===
state: VERIFYING
proof_dir: .artifacts/remediation/<TASK_ID>/
files_changed: [<path1>, <path2>]
commit_sha: <sha>
proof_summary: |
code_commit: <sha>
<other proof type>: <inline summary or path>
<other proof type>: <inline summary or path>
followup_blockers: [] # OR list of new issues found that block proof
===END-<TASK_ID>-RESULT===
You may NOT mark this COMPLETED. The orchestrator verifies and flips.
Time budget: ~<TIME>.
Orchestrator verification gate
After each subagent returns VERIFYING, orchestrator runs:
# 1. Confirm commit on origin/master (or wave branch)
gh api repos/fin-platform/fin-agentic/commits/<sha> --jq '.sha' || flip→BLOCKED
# 2. For each proof_type in tracker row:
# code_commit → already verified above
# curl_response → orchestrator re-runs the curl, compares to artifact
# db_query → orchestrator re-runs SQL via mcp__neon__run_sql, compares
# event_in_db → orchestrator queries events, confirms row exists
# replay_output → orchestrator re-runs CLI, compares
# pixel_screenshot → orchestrator opens .artifacts/.../screenshot-*.png, visual sanity
# clickthrough_trace → orchestrator unzips trace.zip via Playwright, replays
# deployment_proof → orchestrator curls /health, confirms version match
# lineage_trace → orchestrator runs walk_provenance, confirms chain
# migration_log → orchestrator runs SQL: SELECT * FROM schema_migrations WHERE version=<N>
# 3. If ALL proofs pass → flip task to COMPLETED on tracker + commit tracker update
# 4. If ANY proof fails → flip to BLOCKED, attach failed-proof reason, surface to userWave 1 — Quick wins (parallel, ~30 min wall time)
Goal: Land 11 small fixes simultaneously. Re-enable autonomous parity cron (P0-02) so later waves get continuous proof signal.
Dispatch model: 11 background subagents at once, single worktree claude/proj-remediation-wave1. Each subagent owns disjoint files.
Tasks:
| ID | Files | Subagent count |
|---|---|---|
| P0-01 | audit/card-window-system/approved-projection-tables.json | 1 |
| P0-02 | .github/workflows/parity-*.yml (5 files) | 1 |
| P0-10 | packages/mcp-server/src/ingestion/upsert-doc.ts:342-356 | 1 |
| P0-09 | packages/mcp-server/src/event-handlers/projection-commodity-360.ts, projection-vendor-360.ts | 1 |
| P0-11 | packages/workspace/src/routes/EntityRoute.tsx:282 | 1 |
| P0-W5-01 | packages/mcp-server/src/index.ts | 1 |
| P1-03 | packages/agent/src/permissions.ts (SPRINT_TOOLS) | 1 |
| P1-04 | packages/mcp-server/src/tools/generate-*-brief.ts (5 tool files) | 1 |
| P1-W5-01 | packages/mcp-server/src/ingestion/renderers/qc-inspection-profile-renderer.ts:13 | 1 |
| P1-W5-04 | nathel-intranet/PROJECTION_INDEX.md + fin-central-intranet mirror | 1 |
| P1-12 | .github/workflows/eval-pipeline.yml | 1 |
Wave 1 close-out gate: All 11 subagents return VERIFYING → orchestrator verifies each → squash-merge wave PR → trigger parity-verify-backend.yml manually → expect 56/56 backend curls pass (baseline before fixes was 8/8 + 1 vendor gap).
Wave 2 — Medium parallel (~3 h wall time)
Goal: Fix the producer + composition layer. After Wave 2, the MD pipeline has working backlinks, working tenant overlay, working staleness flips, working UI drill buttons → CardSpec → drill paths.
Tasks:
| ID | Files | Dep on Wave 1 |
|---|---|---|
| P0-04 | packages/mcp-server/src/index.ts:3480-3760 + wrangler.jsonc triggers.crons | P0-W5-01 (route mount lands first) |
| P0-05 | new event-handlers/projection-doc-backlink.ts + event-handlers/index.ts:113-131 + backfill script | P0-10 (wikilink resolver fix lands first) |
| P0-06 | new event-handlers/projection-entity-doc-staleness.ts | — |
| P0-12 | packages/shared/src/schemas/cardspec.ts + get-entity-profile.ts + explore-commodity.ts | — |
| P0-13 | packages/mcp-server/src/tools/explore-vendor.ts + lookup-vendor.ts + party-table mapper | — |
| P0-W5-02 | packages/mcp-server/src/routes/github-vault-webhook.ts | P0-W5-01 (route mount lands first) |
| P0-W5-04 | packages/mcp-server/src/tools/get-entity-profile.ts (tenant overlay assembly) | — |
| P1-08 | packages/mcp-server/src/tools/walk-provenance.ts + packages/mcp-server/src/ingestion/extract-fact-citations.ts | P0-05 (doc_backlink populated first) |
| P1-11 | packages/mcp-server/src/ingestion/renderers/entity-doc-renderer-worker.ts | — |
Wave 2 close-out gate: Orchestrator runs end-to-end Playwright suite (Playwright loads with @playwright/test) against /entity/commodity/blackberry, /entity/commodity/cucumber, /entity/vendor/000876, /entity/lot/<real>. Expect: tenant overlay visible on cucumber, drill buttons functional, linked_entities sidebar rendered. Pixel + click-through proof bundled per task.
Wave 3 — Larger parallel (~4 h wall time)
Goal: Wake the renderer, ship the agent prompt rewrite, close the self-improvement loop, surface 8 unreachable projections.
Tasks:
| ID | Files | Dep |
|---|---|---|
| P0-03 | new packages/mcp-server/src/workers/fin-central-renderer-worker.ts + Hyperdrive ID + deploy | P0-04 |
| P0-07 | new event-handlers/projection-eval-feedback.ts | — |
| P0-08 | packages/mcp-server/src/intake/intake-classifier.ts + extractor-consumer.ts | — |
| P0-14 | sync mig 048..068 to fin-central staging | — |
| P0-15 | db/migrations/* renumber colliding slots | requires DB sync coord |
| P0-W5-03 | gh api repos/fin-platform/nathel-intranet/hooks | P0-W5-01 + P0-W5-02 |
| P1-01 | packages/agent/src/personas/reasoning.ts:232-305 + exploration-context.ts:707 + MD tool descriptions | P0-12 + P0-05 |
| P1-02 | packages/mcp-server/src/tools/role-tool-catalog.ts | — |
| P1-05 | 8 new packages/mcp-server/src/tools/get-*-360.ts | P0-09 |
| P1-06 | new packages/mcp-server/src/tools/get-pulse-admin.ts | — |
| P1-07 | packages/mcp-server/src/tools/explore-commodity.ts | P0-09 + P1-05 |
| P1-10 | packages/mcp-server/src/ingestion/renderers/entity-doc-renderer-worker.ts + upsertDoc.ts retry/alert | — |
Wave 3 close-out gate: Agent telemetry shows MD tools firing in real-agent calls (not just test harness). Orchestrator triggers eval-baseline.yml + waits for system.scenario_eval_result events on dc2e36a+wave-3 SHA → expects MD-tool fires > 0. Click-through proof: agent answer about blackberry includes FAO citation + 10 named varieties from MD profile.
Wave 4 — Big lifts (1-2 d each)
Goal: Build the missing taproot sync + first tenant projector + 4 non-commodity renderers.
Tasks:
| ID | Subagent isolation |
|---|---|
| P0-W5-05 | Own worktree claude/proj-remediation-wave4-sync |
| P0-W5-06 | Own worktree claude/proj-remediation-wave4-projector |
| P1-09 | Own worktree claude/proj-remediation-wave4-renderers |
These are large enough that giving each its own worktree avoids merge complexity. Orchestrator opens 3 separate PRs and admin-merges each as proofs land.
Wave 4 close-out gate:
- Taproot sync: commit appears on
nathel-intranet:_taproot_mirror/within 5 min of test commit onfin-central-intranet - Projector:
nathel-intranet/docs/arrivals/<today>.mdexists withrenderer_versionfrontmatter +generated_from_event_idslinking to today’sinbound.load_expectedevents - Non-commodity renderers:
entity_doc_projectionrow counts > 0 for vendor/customer/location/lot domains; pixel + click-through proof for each of 4 entity URL types
Wave 5 — Hygiene + remaining P1 (~3 h parallel)
Goal: Close P2 backlog + 2 remaining P1 items.
| ID | Files |
|---|---|
| P2-01 | 3 vault audit md files (add frontmatter) |
| P2-02 | new _scripts/link-resolver.ts in vault |
| P2-03 | 8 README.md files (unique doc_ids) |
| P2-04 | FIN_PLATFORM_DOC_INDEX.md |
| P2-06 | vault rename script + alias map |
| P2-08 | new packages/shared/src/utils/doc-id-normalize.ts |
| P1-W5-03 | packages/mcp-server/src/middleware/auth.ts + new docs |
| P1-W5-05 | Engineering Spec §11.7 (new section) |
Wave 5 close-out gate: No new automated proof; orchestrator runs the link-checker + grep against renamed files. Tracker hits 100% COMPLETED on non-deferred + non-frozen items.
Sign-off ceremony
When every wave’s tasks are COMPLETED on the tracker:
- Orchestrator runs the full backend curl matrix (56 tools per the autonomous Routine A spec) and captures the pass/fail count.
- Orchestrator triggers the 5 parity cron workflows manually for one final verification cycle.
- Orchestrator runs Playwright pixel + click-through suite covering: 5 commodity entity URLs + 3 vendor URLs + 3 lot URLs + 1 customer URL + 1 system-health URL.
- Orchestrator writes
docs/audits/PROJECTION_SYSTEM_RE_AUDIT_2026-05-XX.md(a re-run of the original 15-WS audit) and confirms operational ratio went from 6.4% to >80%. - Orchestrator updates the tracker’s progress snapshot to “PROGRAM CLOSED”.
- Final commit to vault:
docs/handoffs/projection-remediation-complete-2026-05-XX.mdwith cumulative evidence index.
Resumption protocol
If a session ends mid-wave:
- Tracker holds the source of truth — every task has
status+commit_sha+proof_dir - Next session reads tracker first, picks up tasks with
PENDINGorBLOCKEDstatus - Subagents are stateless — every brief is self-contained, so re-dispatch is safe
- Already-COMPLETED tasks are NEVER re-run
Cost discipline
- Subagents in Waves 1, 2, 5 are short-lived; cost dominated by file edits + verification queries
- Wave 3 + 4 require code that runs longer — set subagent time budgets per task in tracker
- Cron workflows continue running on subscription tokens (per existing direction); no API tokens needed
- Pixel proof costs are bounded — Playwright runs against staging, capture per task is ~30 s
Open questions before Wave 1 dispatch
- PR-per-wave vs single trunk? Recommendation: PR-per-wave (5 PRs total) with admin-merge after orchestrator verification. Alternative: single long-running branch (risk: harder to roll back individual fix if proof fails).
- Playwright infra ready on staging? Need to confirm
staging-workspace.fintail.net(or wherever the workspace UI lives) has Playwright-compatible JWT bypass. If not — Wave 1 task to add it. - Renderer worker deploy target? P0-03 will create the Worker. Confirm which Cloudflare account + Hyperdrive config to use (staging vs prod). Current
wrangler.fin-central.jsonchas placeholder. - Tenant projector authorship — bot identity? P0-W5-06 needs to commit to
nathel-intranetas a bot. Need PAT or GitHub App credentials with write access.
Surface these to the user before Wave 1 dispatch if any answers aren’t already implicit.