FIN Projection System Remediation — Master Tracker
Source audit: docs/audits/PROJECTION_SYSTEM_AUDIT_2026-05-17.md (20 work streams, 1 PASS / 13 DEGRADED / 6 FAIL)
Execution program: docs/processes/PROJECTION_REMEDIATION_EXECUTION_PROGRAM_2026-05-17.md
Ranking method
Every task carries an Impact Score (1–10) and a Severity (P0/P1/P2). Order of execution = Severity first, then Impact Score descending, then Effort ascending (cheap-wins-first within tier).
Impact Score rubric (evidence-anchored from audit):
| Score | Definition |
|---|---|
| 10 | Single fix that unlocks an entire dead pipeline (e.g., tenant overlay layer goes from null to populated using existing 314+ substrate events) |
| 8–9 | Fix unblocks a whole class of agent behavior (e.g., MD tool surfacing across all entity types, or drill-button functionality across all entity URLs) |
| 6–7 | Fix repairs one critical capability (e.g., one projection table starts being populated; one tool comes off the broken list) |
| 4–5 | Fix removes one silent failure mode (e.g., 24 render fails stop being silent; merge-conflict in registry stops corrupting parses) |
| 2–3 | Hygiene / quality improvements |
| 1 | Cosmetic |
Proof contract (CLAUDE.md §Subagent Orchestration Rules)
Every task requires PROOF before flipping from VERIFYING → COMPLETED. Proof type depends on the task. Pixel + click-through proof is mandatory for any task that surfaces to UI. Backend tasks require curl-response or db-query proof. Pipeline tasks require replay-output or event-in-DB proof.
| Proof type | Format | Verification command |
|---|---|---|
code_commit | git SHA on origin/master | gh api repos/fin-platform/fin-agentic/commits/<sha> returns 200 |
migration_log | schema_migrations row | mcp__neon__run_sql against schema_migrations |
curl_response | HTTP+body | inline JSON capture in proof artifact |
db_query | SQL + result | inline result in proof artifact |
replay_output | CLI stdout | captured to .artifacts/replay/<task>-<ts>.log |
pixel_screenshot | PNG | committed to .artifacts/screenshots/<task>/<ts>/<scene>.png |
clickthrough_trace | Playwright trace.zip | committed to .artifacts/playwright/<task>/<ts>/trace.zip |
deployment_proof | /health JSON | curl staging-api.fintail.net/health matches master SHA |
event_in_db | events table row | SQL query showing the expected event_type with recent timestamp |
lineage_trace | walk_provenance chain | walk_provenance returns terminating chain |
Subagent state lifecycle: PENDING → IN_PROGRESS → VERIFYING (subagent returns) → COMPLETED (orchestrator verifies via proof) | BLOCKED (proof fails or dependency missing).
Subagent NEVER claims COMPLETED. Orchestrator flips only after verifying per §2.
P0 — System-correctness blockers (21 items)
| # | Title | Score | Effort | Wave | Deps | Proof type(s) | Status |
|---|---|---|---|---|---|---|---|
| P0-01 | Resolve git merge conflict in audit/card-window-system/approved-projection-tables.json (lines 167/196/207) — invalid JSON breaks projection registry parse | 7 | 5m | 1 | — | code_commit + replay_output (pnpm exec tsx scripts/audit/projection-registry-validate.ts) | PENDING |
| P0-02 | Fix pnpm/action-setup@v4 version: 10 vs packageManager: pnpm@9.15.4 conflict in 5 parity cron workflows | 7 | 10m | 1 | — | code_commit + workflow_run_pass (manual dispatch of parity-verify-backend.yml) | PENDING |
| P0-10 | Fix extractWikilinkTarget to output commodity_profile_X instead of commodity_X (1-line fix) — 52 wikilinks → 0 backlinks blocker | 6 | 5m | 1 | — | code_commit + db_query (sample backlink count after) | PENDING |
| P0-09 | Fix attribute-key mismatch in commodity_360_projection + vendor_360_projection (events use data.commodity, query uses data.commodity_key) | 8 | 30m | 1 | — | code_commit + replay_output (rebuild 360s; rows go from stub to populated) + db_query | PENDING |
| P0-11 | Wire EntityRoute.tsx:282 to pass onAction prop to <CardRenderer> — every drill button across every entity URL is currently a dead click | 10 | 30m | 1 | — | code_commit + pixel_screenshot (button states) + clickthrough_trace (click drills to next entity) | PENDING |
| P0-W5-01 | Mount vaultWebhookRoutes in packages/mcp-server/src/index.ts — POST /webhooks/github-vault currently returns 404 | 9 | 15m | 1 | — | code_commit + curl_response (POST → 200 not 404) | PENDING |
| P0-W5-04 | Wire get_entity_profile assembly to populate data.tenant overlay from tenant signal events — cucumber has 314 nathel signals already ready | 10 | 2-3h | 2 | — | code_commit + curl_response (cucumber response shows data.tenant.recent_price_observations.length > 0) + pixel_screenshot (EntityRoute renders tenant section) | PENDING |
| P0-12 | Add linked_entities field to CardSpec schema + ensure get_entity_profile/explore_commodity emit it | 9 | 2h | 2 | — | code_commit + curl_response (.data.linked_entities.length >= 3 for blackberry) + pixel_screenshot (UI sidebar) | PENDING |
| P0-04 | Wire runRendererLoopIteration into Cloudflare scheduled() handler + add cron to wrangler.jsonc triggers.crons | 8 | 30m | 2 | P0-W5-01 | code_commit + event_in_db (renderer.iteration_completed event seen on nathel within 5m of next cron) + deployment_proof | PENDING |
| P0-05 | Write event-handlers/projection-doc-backlink.ts + register in dispatchProjectionUpdaters; back-fill from knowledge.content.linked_entities (2,620 existing edges) | 9 | 2-3h | 2 | P0-10 | code_commit + db_query (SELECT COUNT(*) FROM doc_backlink_projection ≥ 2000) + lineage_trace | PENDING |
| P0-06 | Write entity_doc staleness listener — consume knowledge.row_updated/knowledge.domain_stale and flip entity_doc_projection.status='stale' (~30 LOC) | 7 | 1h | 2 | — | code_commit + db_query (write to a knowledge row → see paired entity_doc row flip to status='stale' within 5s) | PENDING |
| P0-07 | Write system.scenario_eval_result consumer → update entity_doc_projection.trust_score + knowledge.confidence from 19,198 archived signals | 8 | 2h | 3 | — | code_commit + db_query (sample knowledge rows show confidence updated after consumer runs over backlog) + replay_output | PENDING |
| P0-08 | Fix attributeEventToInbox() upstream — propagate source_email_inbox/inbox/to_address into event data from EIF S0.5 + S4 consumers | 7 | 2h | 3 | — | code_commit + db_query (intel_inbox_daily_digest_projection row count > 0 after backfill replay) | PENDING |
| P0-13 | Fix explore_vendor/lookup_vendor — currently returns vendor_not_found for vendors visible via lookup_vendor + explore_commodity (vendor 000876 LA MINITA FRESH LLC); fix vendor-actor lookup to use party + relationship tables (0 vendor actors on nathel) | 8 | 2-3h | 2 | — | code_commit + curl_response (vendor 000876 returns 200 with content) + pixel_screenshot (vendor page renders) + clickthrough_trace (commodity → vendor → loads chain) | PENDING |
| P0-W5-02 | Complete the tenant vault webhook handler — wire fetch-from-GitHub + parseDocMarkdown + upsertDoc (handler is skeleton; upsertDoc is fully implemented) | 8 | 2-3h | 2 | P0-W5-01 | code_commit + curl_response (POST sample payload → 200) + db_query (knowledge row appears for sample doc_id) | PENDING |
| P0-14 | Sync fin-central staging — apply migrations 048..068 + create entity_doc_projection + doc_backlink_projection tables + backfill shared-tenant rows | 6 | 1h | 3 | — | migration_log (fin-central schema_migrations head ≥ 068) + db_query (entity_doc_projection table exists + has shared rows mirroring nathel) | PENDING |
| P0-15 | Resolve migration slot collisions on slots 050, 053, 054 (nathel has duplicate-applied; parity-integration missing slot 050) — re-number conflicting migs to new slots | 5 | 2-3h | 3 | — | code_commit + migration_log (clean linear sequence; no duplicates) | PENDING |
| P0-03 | Deploy fin-central-renderer Worker: write entry-point file + replace placeholder Hyperdrive ID + add to deploy pipeline | 8 | 2-3h | 3 | P0-04 | code_commit + deployment_proof (/health reports renderer worker version match) + event_in_db (entity_doc.rendered event flowing) | PENDING |
| P0-W5-03 | Configure GitHub webhook on fin-platform/nathel-intranet to POST to staging Worker /webhooks/github-vault | 6 | 15m | 3 | P0-W5-01, P0-W5-02 | gh_api_response (webhook configured) + curl_response (test push triggers webhook + 200 response) + db_query (knowledge row appears) | PENDING |
| P0-W5-05 | Build Central → Tenant taproot sync (Wave 1 poll OR Wave 4 push) | 7 | 1-2d | 4 | P0-03 | code_commit + event_in_db (taproot.mirror_updated event) + git_log (commits appear on nathel-intranet:_taproot_mirror/ within 5m of central change) | PENDING |
| P0-W5-06 | Implement first tenant projector (daily_arrivals — RP581 ingest is live) — establishes pattern for the other 12 | 7 | 1-2d | 4 | P0-W5-05 | code_commit + git_log (nathel-intranet receives a docs/arrivals/<date>.md commit) + event_in_db (projector.daily_arrivals_rendered) + pixel_screenshot (UI route shows the arrivals digest) | PENDING |
P1 — Quality / agent-effectiveness blockers (17 items)
| # | Title | Score | Effort | Wave | Deps | Proof type(s) | Status |
|---|---|---|---|---|---|---|---|
| P1-03 | Add get_knowledge_health to SPRINT_TOOLS (in toolRegistry but missing → fails authz with TOOL_UNKNOWN) | 5 | 5m | 1 | — | code_commit + curl_response (call returns 200 not TOOL_UNKNOWN) | PENDING |
| P1-04 | Fix 5 generate_*_brief tools failing INVALID_EVENT_PAYLOAD (brief.generated schema requires shift_type + posted_to_slack) | 6 | 1h | 1 | — | code_commit + curl_response (all 5 tools return 200) + event_in_db (brief.generated rows for each) | PENDING |
| P1-W5-01 | Fix misleading comment at qc-inspection-profile-renderer.ts:13 (says writes to vault, actually writes to DB) | 1 | 5m | 1 | — | code_commit | PENDING |
| P1-11 | Fix renderer to populate source_row_version correctly (95.5% of 331 rows have 'unknown' → drift-blind even after P0-06) | 5 | 30m | 2 | — | code_commit + db_query (new rows have version, not ‘unknown’) | PENDING |
| P1-W5-02 | Add FIN_VAULT_TENANT_MAP entry for nathel in wrangler.fin-central.jsonc OR create peer wrangler.tenant.jsonc | 4 | 30m | 2 | P0-03 | code_commit + deployment_proof | PENDING |
| P1-W5-04 | Rename nathel-intranet/PROJECTION_INDEX.md → VAULT_RENDERER_OUTPUTS.md (and mirror in fin-central-intranet) — kills the naming collision masking the absence | 4 | 30m | 1 | — | git_log (rename committed on both repos) + grep (no broken references) | PENDING |
| P1-08 | Fix walk_provenance to query doc_backlink_projection + fix fact_citations to use event_id instead of abstract commodity:<slug> keys | 8 | 3h | 2 | P0-05 | code_commit + lineage_trace (walk from commodity claim terminates in concrete event row, not knowledge_no_provenance) | PENDING |
| P1-12 | Add post-deploy /health version-match gate to eval-pipeline.yml — catches out-of-band wrangler deploys | 5 | 30m | 1 | — | code_commit + workflow_run_pass (artificial mismatch triggers failure) | PENDING |
| P1-01 | Rewrite system prompt to teach MD tools — replace “cross-reference get_commodity_profile for authoritative data” with search_entity_profiles + get_entity_profile + walk_provenance chain; de-jargon descriptions | 10 | 4h | 3 | P0-12, P0-05 | code_commit + curl_response (sample agent query about blackberry shows MD tools fire — verify via events WHERE type='tool.invoked' AND data->>'tool' = 'get_entity_profile' count > 0 after sample query) + clickthrough_trace (agent answer includes MD-content citations) | PENDING |
| P1-02 | Add 5 MD-projection tools (get_entity_profile, search_entity_profiles, walk_provenance, get_doc_graph, get_knowledge_health) to role catalogs | 7 | 1h | 3 | — | code_commit + db_query (sample role tool list contains all 5) + curl_response (qc_inspector role can call get_entity_profile) | PENDING |
| P1-05 | Wire 8 JSONB projections to MCP readers (buyer_team_dashboard, commodity_360, customer_360, daily_company_pulse, location_intel, sales_team_dashboard, supply_chain_position, vendor_360) | 8 | 3-4h | 3 | P0-09 | code_commit + curl_response (8 new tools return 200 with real data) + event_in_db (tool.invoked for each) | PENDING |
| P1-06 | Add MCP reader for pulse_admin_active_holds (currently Hono-only) | 5 | 1h | 3 | — | code_commit + curl_response (get_pulse_admin returns 200) | PENDING |
| P1-07 | Fix explore_commodity p50=7s (3.5x over 2s target) — route through commodity_360_projection instead of wide KB scan | 7 | 2h | 3 | P0-09, P1-05 | code_commit + curl_response with timing (time_total < 2.0) over 5 sequential calls | PENDING |
| P1-10 | Fix 24 silent render failures (19 s01_identity TypeError, 5 embedding_model NOT NULL); raise retry cap 1→3; alert on status='failed' | 5 | 2h | 3 | — | code_commit + db_query (status='failed' rows go from 24 → 0) + event_in_db (alert.fired for any new failure) | PENDING |
| P1-09 | Implement renderer routes for vendor/customer/location/lot domains (routeRenderer() throws RendererNotImplementedError for all 4) | 9 | 1-2d | 4 | P0-03 | code_commit (4 new renderer files) + db_query (entity_doc_projection by_domain shows vendor/customer/location/lot > 0 rows) + pixel_screenshot (4 entity URL types render) | PENDING |
| P1-W5-03 | Document the auth bypass tenant routing footgun (body tenantId returns UNAUTHORIZED while X-Fin-Tenant header silently re-binds) — harmonize contract | 3 | 1h | 5 | — | code_commit + docs file appears + grep (no remaining ambiguous code paths) | PENDING |
| P1-W5-05 | Add Engineering Spec §11.7 covering 3-rung taproot architecture (renderer + sync transport + tenant overlay renderer) | 4 | 2-3h | 5 | — | code_commit (spec file updated) | PENDING |
P2 — Hygiene (8 items)
| # | Title | Score | Effort | Wave | Deps | Proof type(s) | Status |
|---|---|---|---|---|---|---|---|
| P2-01 | Add frontmatter to 3 vault audits (HISTORICAL_DATA_BACKFILL, ROLE_DRILLTHROUGH_DESIGN, PROJECTION_PARITY_AUDIT) | 3 | 15m | 5 | — | code_commit + grep (files have schema_version + doc_kind) | PENDING |
| P2-02 | Build wikilink resolver for vault’s type-prefix shorthand ([[commodity:X]], etc.) — 50 of 52 wikilinks currently broken | 4 | 4h | 5 | — | code_commit + grep (resolver script exists) + test_output | PENDING |
| P2-03 | Fix 8 README.md files sharing doc_id: readme (collide on upsert, silently destroy 7 of 8) | 4 | 20m | 5 | — | code_commit + grep (unique doc_ids across all READMEs) | PENDING |
| P2-04 | Fix FIN_PLATFORM_DOC_INDEX.md — 12 broken absolute links to fin-agentic paths | 3 | 30m | 5 | — | code_commit + link_check_output | PENDING |
| P2-05 | Tag vault docs with appropriate data_plane (currently monovalent → federation gate has no signal) | 3 | ongoing | 5 | — | (ongoing author task) | DEFERRED |
| P2-06 | Fix variety/vendor naming mismatch (commodities link to crimson_sweet but variety files stored as cmd_00057.md) — 98.2% orphan rate | 5 | 2h | 5 | — | code_commit + db_query (orphan rate < 5%) | PENDING |
| P2-07 | Author 9 missing W1/W2 PROJECTION_INDEX types (kb_health_summary, tenant_readiness, region_intelligence, etc.) | 2 | author backlog | — | — | (author work) | DEFERRED |
| P2-08 | Add normalizer for docId shape inconsistency (commodity_profile_X vs commodity_profile/X/v1) | 4 | 1h | 5 | — | code_commit + test_output | PENDING |
Frozen-intentional (do not action)
| # | Item | Reason |
|---|---|---|
| F-01 | EIF Slice 7 federation publisher (gated by FEDERATION_PUBLISH_ENABLED='true') | Single-tenant reality per feedback_federation_publisher_frozen.md |
| F-02 | fin-central tenant fully populated | Intentional — wake when first federation peer onboards |
| F-03 | OpenClaw integration tests | User confirmed out of scope this phase |
| F-W5-01 | Tenant authored content (decisions, runbooks, SOPs) | Phase 2+ author work, not runtime gap |
| F-W5-02 | Aggregate intelligence rollups | Frozen per single-tenant reality |
Wave summary
| Wave | Count | Tasks | Cumulative effort | Parallel-OK? |
|---|---|---|---|---|
| 1 | 11 | P0-01, P0-02, P0-10, P0-09, P0-11, P0-W5-01, P1-03, P1-04, P1-W5-01, P1-W5-04, P1-12 | ~2.5h serial; ~30 min parallel (longest item) | yes |
| 2 | 8 | P0-04, P0-05, P0-06, P0-12, P0-13, P0-W5-02, P0-W5-04, P1-08, P1-11 | ~15h serial; ~3 h parallel | yes |
| 3 | 11 | P0-03, P0-07, P0-08, P0-14, P0-15, P0-W5-03, P1-01, P1-02, P1-05, P1-06, P1-07, P1-10 | ~22h serial; ~4 h parallel | mostly (P1-01 depends on P0-12/P0-05; P0-03 depends on P0-04) |
| 4 | 3 | P0-W5-05, P0-W5-06, P1-09 | ~5d serial; ~2d parallel (largest items) | partial |
| 5 | 8 | P2-01..P2-08 + P1-W5-03 + P1-W5-05 | ~10h serial; ~3 h parallel | yes |
Total ~7–8 days to fully operational (vs ~21 days if done serially) with disciplined subagent parallelization.
Top 6 highest-impact items (cherry-pick for “what unlocks the most”)
| # | Item | Score | Effort | Why |
|---|---|---|---|---|
| P0-W5-04 | Wire data.tenant overlay assembly | 10 | 2-3h | 314 cucumber signals already in substrate; single fix → every commodity gets tenant-specific section |
| P0-11 | EntityRoute onAction wiring | 10 | 30m | Every drill button across every entity URL becomes functional |
| P1-01 | Agent system prompt rewrite | 10 | 4h | Agent finally picks MD tools instead of legacy — unlocks the entire 487-profile knowledge layer for production agent reasoning |
| P0-12 | linked_entities in tool envelope | 9 | 2h | Graph data exists (2,620 edges); UI starts surfacing it |
| P0-05 | doc_backlink updater + back-fill | 9 | 2-3h | Drill-through graph traversal becomes possible |
| P1-09 | vendor/customer/location/lot renderers | 9 | 1-2d | 4 of 5 entity domains stop being empty |
Progress snapshot (auto-update format)
Total tasks: 46 (21 P0 + 17 P1 + 8 P2)
COMPLETED: 0
IN_PROGRESS: 0
VERIFYING: 0
BLOCKED: 0
PENDING: 46
DEFERRED: 2 (P2-05, P2-07)
FROZEN: 5
% done: 0.0%
After each subagent dispatch, this snapshot updates. Orchestrator regenerates from the table above on each session-close.