Skip to content

AST + Dataflow Tool — ROADMAP

Status: DRAFT-S8 (kh-ast-S8 Wave 1 — roadmap accuracy review post-S7). Companions: PRODUCT.md (behaviour spec, 12 query surfaces, 30 invariants), TECH.md (data model, library layout, validation, follow-ups; flow-trace-TECH.md folded into TECH.md §Query implementations on 18/05/2026). Counter: track-local kh-ast-sN. This doc is session-agnostic — slip dates, not WP positions, when timelines shift.

S1–S3 shipped the first four queries (callers, importers, references, column-reads) plus the structured error contract. S4 closed the canonical-pipeline rename probe pair (column-reads + column-writes) and added the wildcard confidence tier. S5 shipped the cross-project leverage trio (dead-exports, reexport-chain, type-evolution). S6 shipped the KH-specific surface (string-literal-uses, enum-uses) plus the flow-trace-TECH.md sub-spec. S7 shipped flow-trace (R-WP6) as a three-WP sequence and authored three cross-tool investigation briefs (R-WP10 framework-agnostic, R-WP11 cross-tool integration, R-WP12 type-safety pipeline). With 11 queries shipped and the investigation outputs in hand, the open work in PRODUCT.md plus the new ROADMAP-tracked extensions need sequencing against:

  1. Cross-project leverage. Same Supabase + Next.js stack is shared across Knowledge Hub, sales-proposals, and other Liam-and-Claude projects. Whatever ships here should be portable. R-WP10 (S7) confirmed the tool is 95% portable already; Approach A minimal fix is queued for S8.
  2. Complement vs duplicate. The tool sits next to cocoindex-code (text index), gitnexus (git provenance + framework graph), and bun run knip (unused dependency / export detection). Duplication is dead weight; gap- filling is high-leverage. R-WP11 (S7) catalogued nine cross-tool integration patterns ranked by leverage; top three are now S8/S10 candidates.
  3. The deferred-OQ list is shorter than at S4 but the type-safety pipeline opens a new axis of work. PRODUCT.md invariants 1, 3–10 are shipped (9 of the 12 query surfaces). Invariants 2 (callees), 11 (fixture-uses), and 12 (enum-member-uses) remain unshipped — none have a load-bearing trigger yet (no current rename sweep or audit demands them, and the shipped references + enum-uses + string- literal-uses trio covers most of what 2/11/12 would address). Invariant 28 (MCP wrapper) remains DEFERRED. R-WP12 (S7) identified five type-safety gaps that ast-dataflow can detect or close, with a 20h MVP across five WPs. Cache layer (TECH.md §Cache strategy) and Python sibling remain trigger-driven.

This roadmap is the running answer to “what next, and why.”

id-375 delta (2026-07-27) — productionisation wave

Section titled “id-375 delta (2026-07-27) — productionisation wave”

Supersedes the S7 rows below where they conflict. Landed across id-375 waves 1-5 (specs: specs/id-375-ast-dataflow-productionise/RESEARCH.md, PRODUCT.md §Amendments A1-A7):

ChangeStatusSmoke of record
Spatial truncation (truncateSpatial, inv 14) across all coverage queries; flow-trace + reexport-chain exemptShipped W1string-literal-uses --value created_at --limit 5: 5 rows from 5 distinct files, totalEstimated: 52
detectIsTyped rewrite — structural Row-property proof, no text matching (inv 15 / A4)Shipped W2column-reads source_documents.id: 199 rows before AND after; false-exact rows demoted to indirect
callees query (inv 2 / A1)Shipped W2lib/supabase/safe.ts:sb → 1 row (new SupabaseError), externalCount 0
importers algorithmic fix (P-19 breach closed)Shipped W2durationMs 10.3-16.2 s → 1.6-2.2 s
One-hop .from(CONST) table resolution (A7)Shipped W3 (prior session)Fires on the real corpus: .from(VERSION_TABLE)content_propagation_version at scripts/propagate-canonical-content.ts:486 (in-corpus via transitive import — the corpus boundary is import-reachability, not the tsconfig exclude list). App-side dynamic sites are union-typed (excluded as ambiguous by design)
fixture-uses query (inv 11 / A1)Shipped W3--needle created_at: 354 hits across json/ts
schema-coverage report (A6) — the built-not-wired auditShipped W4807 columns / 70 tables in one 7.4 s pass: wired 310, read-only 225, undecidable 132, unwired 88, write-only 52; all baseline false negatives closed; dropped bid_questions → loud unknown_table
Warm MCP stdio server + dispatch.ts extraction (inv 28 / A2+A3)Shipped W5callers sb over stdio: first call 6.0 s wall, second 204 ms; suite 313/313

Cache pivot: the facts-cache design (R-WP9/OQ-R3, LMDB) is superseded — measurement showed 11 of 12 queries need the live type-checked AST; the warm path is the MCP server process (PRODUCT.md A2, ratified 2026-07-27).

QueryStatusSourceSmoke baseline
callersShipped (S1)PRODUCT.md inv. 1Verified against fixture corpus; 153 rows on sb() smoke.
importersShipped (S2)PRODUCT.md inv. 43 rows on @/lib/ai/change-reports smoke.
referencesShipped (S3)PRODUCT.md inv. 36 kinds (typeReference, jsxComponent, read, write, reexport, typeOnly); 82 rows on BidState smoke.
column-readsShipped (S3) + wildcard tier (S4 WP1)PRODUCT.md inv. 5 + 1548 rows on bid_questions.project_id, 1.8 s warm; wildcard branch detects .select('*'). (historical — bid_questions since dropped; current example: form_questions.question_text, 22 exact rows)
column-writesShipped (S4 WP2)PRODUCT.md inv. 620 rows on bid_questions.project_id, 3.5 s warm; spread-one-hop chase working. (historical — see column-reads note)
dead-exportsShipped (S5 R-WP1)PRODUCT.md inv. 954-symbol Knip-diff batch: 52 confirmed dead, 2 false-positives, 4.3 s warm. OQ-R2 resolved (Shape A per-row JSONL).
reexport-chainShipped (S5 R-WP2)PRODUCT.md inv. 8DialogClose probe: 39 rows (1 declaration + 38 direct importers), 483 ms warm.
type-evolutionShipped (S5 R-WP3)PRODUCT.md inv. 7BidQuestion.project_id probe: 22 rows across 8 files, ~4.0 s cold.
string-literal-usesShipped (S6 R-WP4)PRODUCT.md inv. 10vi.mock('@/lib/supabase/safe') probe: 6 viMock rows, 3.06 s.
enum-usesShipped (S6 R-WP5)ROADMAP extensionFixture-only smoke (KH has zero native enums); 19 rows on OrderStatus fixture, 71 ms warm.
flow-traceShipped (S7 R-WP6, three-WP sequence)ROADMAP extension; see TECH.md §Query implementations → flow-traceHeuristic confirmed: 5-hop warm ≈ 5 ms, 8-hop warm ≈ 4 ms. Real KH smoke (lib/bid/bid-queries.ts:70) ≈ 5 ms warm, ~2 s cold.
Test philosophyAudit + 23 tightenings (S4 WP3); ongoing per-query auditsdocs/reference/test-philosophy.md163/163 AST tests passing (end S7); no weak toBeGreaterThanOrEqual(1) antipatterns.
Structured error contractShipped (S3 WP3)PRODUCT.md inv. 29Four ErrorKind cases (unknown_file, parse_error, ambiguous_symbol, out_of_corpus) plus two flow-trace codes (ORIGIN_NOT_RESOLVABLE, ORIGIN_NOT_VALUE_PRODUCING). CLI exits 0 on structured error.
Open invariantTitlePRODUCT.md refPriority
2calleesinv. 2SHIPPED (id-375 W2, 2026-07-27) — 14 tests, fixture corpus 19-callees; PRODUCT.md A1
11fixture-usesinv. 11SHIPPED (id-375 W3, 2026-07-27) — 21 tests, fixture corpus 20-fixture-uses; PRODUCT.md A1
12enum-member-usesinv. 12DEFERRED (enum-uses shipped as ROADMAP extension covers the enum-rename sweep case; full per-member filter on as const tuples deferred until a concrete audit needs it)
28MCP wrapperinv. 28SHIPPED-OPTIONAL (id-375 W5, 2026-07-27, pending A3 ratification) — single dispatching ast_dataflow tool over a warm ts-morph Project; OQ-R4 trigger fired (importers P-19 breach + rename-sweep 5×-cold-CLI friction); PRODUCT.md A3

With 11 queries shipped, the tool’s complement-vs-duplicate justification shifts from “which gap to fill next” (everything in PRODUCT.md is shipped except invariant 28 MCP wrapper) to “which cross-tool integration pattern gives the most leverage on top of the shipped surface”. R-WP11 (S7) is the authoritative catalogue; the table below summarises the three highest- leverage gap-filling opportunities still open.

PatternGap vs current toolsWhy current tools cannot fill itStatus
gitnexus_rename + string-literal-uses + importers + references (R-WP11 Pattern 4, HIGH leverage)gitnexus_rename’s ast_search fallback is its weakest link — string-matched, not type-checker resolved. Every cross-file rename loses confidence on those candidates.ast-dataflow’s string-literal-uses is the precise complement: it surfaces only AST-anchored string-literal nodes, with parent-kind classification (CallExpression argument, TemplateLiteral, JsxAttribute).Queued: R-WP11a (Wave 4, S8).
gitnexus_context + callers (R-WP11 Pattern 5, HIGH leverage)gitnexus indexes graph edges (CALLS, FETCHES) but misses indirect callers — arrow functions inside Promise.all, callback chains, HOC wrappers.ts-morph’s findReferences() is a full type-checker traversal; it surfaces every reference regardless of call-graph edge type. Closes the indirect-caller gap.Queued: R-WP11b (Wave 7, S11+).
Knip enumMembers + enum-uses (R-WP11 Pattern 8, MEDIUM leverage)Knip has documented false-positive issues (#989, #703) on as const patterns — KH’s dominant enum idiom.enum-uses resolves as const tuple member access via findReferences() on the index position, exactly the case Knip miscounts.Backlog (re-evaluate at next KH enum audit).

Sequencing principle: cross-project queries first, then KH-specific use cases, then cross-tool integrations and orthogonal extensions (framework-agnostic adaptation, type-safety pipeline, packaging). A query is “cross-project” if any Supabase + Next.js project benefits without custom configuration.

Wave 1 — Cross-project leverage (S5) — COMPLETE

Section titled “Wave 1 — Cross-project leverage (S5) — COMPLETE”
WPQueryEffortDepends onStatus / Justification
R-WP1dead-exports (inv. 9)~3hNoneShipped S5 R-WP1 (5fdbd9b7 lineage). Complements Knip directly. 54-symbol Knip-diff batch verified: 52 confirmed dead, 2 false-positives. Cross-project: every TS project has unused exports.
R-WP2reexport-chain (inv. 8)~2hR-WP1 (shared barrel walker)Shipped S5 R-WP2 (5fdbd9b7). Pairs with R-WP1: when dead-exports says “unused”, reexport-chain shows the barrel paths to confirm or refute. Cross-project: every barrel-using codebase.
R-WP3type-evolution (inv. 7)~2-3hNoneShipped S5 R-WP3 (7a3d83ef lineage). The TS-type layer analogue of column-reads/column-writes. Cross-project: any TS project doing rename refactors.

Wave 2 — KH-specific surface (S6) — COMPLETE

Section titled “Wave 2 — KH-specific surface (S6) — COMPLETE”
WPQueryEffortDepends onStatus / Justification
R-WP4string-literal-uses (inv. 10)~2hNoneShipped S6 R-WP4 (d1c45aa7). Catch-all for vi.mock, SQL tags, env-var keys.
R-WP5enum-uses~1-2hreferences (already shipped)Shipped S6 R-WP5 (20bb0b79). Specialisation of references with enum-aware classification. ROADMAP-tracked extension beyond PRODUCT.md’s frozen 12-query surface; a future major PRODUCT.md revision may fold it in.
R-WP6-specflow-trace technical specification~1-2hcolumn-writes, referencesShipped S6 R-WP6-spec (7897a1b3). Authored flow-trace-TECH.md sub-spec locking args, hop taxonomy, termination policy, output schema, and three-WP decomposition ahead of S7 implementation.

Wave 3 — flow-trace + cross-tool integration investigations (S7) — COMPLETE

Section titled “Wave 3 — flow-trace + cross-tool integration investigations (S7) — COMPLETE”
WPItemEffortDepends onStatus / Justification
R-WP6flow-trace (ROADMAP extension; sub-spec flow-trace-TECH.md)~4h (3-WP sequence)column-writes, references, R-WP6-specShipped S7 across three sequential WPs (675ff73afd4dedd8/b31bf148bfc60b5b/4b15204e03d61fbe cleanup). WP1: core walker + 4 hop kinds. WP2: sinks + spread + indirect tier. WP3: cycle detection, depth cutoff, inter-function descent, types union, CLI. OQ-FT2/FT3 locked, OQ-FT5 resolved (heuristic confirmed: warm 5-hop ≈ 5 ms, warm 8-hop ≈ 4 ms), OQ-FT4 deferred.
R-WP10Investigation: framework-agnostic adaptation feasibility (immediate target: Vite).~2hNoneShipped S7 (2e8f1f1d). Brief: investigations/R-WP10-framework-agnostic.md. Finding: tool is 95% portable; minimal 4-file fix (Approach A) achieves Vite support at S effort (2-4h). Approaches B (FrameworkAdaptor interface) and C (config file) deferred until npm-publish scenario surfaces.
R-WP11Investigation: high-value cross-tool integration opportunities (gitnexus-refactoring, gitnexus-debugging, cocoindex-code, Knip).~2hNoneShipped S7 (191c9a38). Brief: investigations/R-WP11-cross-tool-integration.md. Finding: 9 patterns catalogued; top three by leverage are Pattern 4 (gitnexus_rename + string-literal-uses, HIGH), Pattern 5 (gitnexus_context + callers, HIGH), Pattern 8 (Knip enumMembers + enum-uses, MEDIUM). No new queries required — patterns compose the existing 11.
R-WP12Investigation: type-safety pipeline feasibility (ast-dataflow + cocoindex-code + GitNexus + Supabase typegen).~3-4hNoneShipped S7 (ca69d1fb). Brief: investigations/R-WP12-type-safety-pipeline.md. Finding: 5 gaps identified, 20h MVP across WP-A..WP-E. Detection tooling (WP-A + WP-D) recommended before structural fix (OPS-T1 defineRoute() wrapper). DW.14 (Supabase typegen) effectively answered.

Wave 4 — Priority outcomes from cross-tool investigation findings (S8)

Section titled “Wave 4 — Priority outcomes from cross-tool investigation findings (S8)”
WPItemEffortDepends onJustification
R-WP10aFramework-portability minimal fix (R-WP10 Approach A — Vite-ready). Implement: (1) generalised path-alias strip in importers.ts; (2) deduplicated isTestFilePath (single source in resolve.ts, drop local copies in column-reads.ts / column-writes.ts); (3) relative-import refactor in scripts/ast-dataflow-cli.ts; (4) --tsconfig flag on CLI; (5) Vite-style tsconfig fixture under __tests__/lib/ast-dataflow/fixtures/15-vite/.2-4h (S)NoneR-WP10 brief Recommendation §5. Closes the one genuine HIGH-severity portability defect (CLI @/ imports) plus two low-severity hygiene items. Unlocks dogfooding on Liam’s non-KH Vite projects.
R-WP12-WPAMechanical structured-RPC de-cast at three known sites (R-WP12 brief §MVP §WP-B execution path, scoped to S8 sites). Remove as Record<string, unknown> casts at lib/mcp/tools/search.ts:152, lib/bid/bid-queries.ts:83, lib/mcp/tools/content.ts:84. Verify type-checker still passes. No behaviour change.~2h (XS)NoneR-WP12 brief Recommendation: “zero risk and immediate payback”. Disjoint files from R-WP10a so parallelisable.
R-WP11aOperationalise R-WP11 Pattern 4 — gitnexus_rename + ast-dataflow rename-sweep verifier as a skill (.claude/skills/ast-dataflow-rename-sweep/SKILL.md). Form decided in S8 planning: skill (over CLI) per Liam direction, since the skill route gives us an automated skill-efficacy evaluation pattern reusable for R-WP7. Reproduce the worked example end-to-end on a real KH rename; report unmissed sites with line numbers. Document in TECH.md §Cross-tool patterns.3-5h (M)R-WP10a (touches shared library paths)R-WP11 brief Recommendation §1 — “ready to operationalise now”. Closes the single weakest link in every cross-file rename (gitnexus’s ast_search fallback); also establishes the skill-efficacy evaluation pattern feeding R-WP7.
R-WP12-WPBType-evolution sweep / drift-detection tool (R-WP12 brief MVP §WP-B, partial). New scripts/type-safety-sweep.ts (or lib/ast-dataflow/queries/type-evolution-batch.ts) scans app/api/**/route.ts for unsafe response narrowing — fetcher generics not pinned, raw RPC returns without type assertions. Output: JSONL inventory of “needs migration” sites for OPS-T1 to consume.3-4h (M)R-WP12-WPAR-WP12 brief Recommendation: “Build the detection tooling (WP A, WP D) first — before any structural fix.” Produces the empirical evidence Liam needs to decide whether OPS-T1 is worth the 2-3 day spend.

Wave 5 — Type-safety Pipeline (S9) — COMPLETE

Section titled “Wave 5 — Type-safety Pipeline (S9) — COMPLETE”

Spec triple: docs/specs/id-16-ast-dataflow-tool/type-safety-pipeline/{PRODUCT,TECH}.md (authored S8 Wave 1 — PRODUCT.md = WP-D only, TECH.md covers WP-A..WP-F + ESLint rule + JSONB inventory + Supabase types CI plan).

The S8 wave shipped R-WP12 WP-A (Gap 3 detection) + WP-B (Gap 1 detection scaffold). Wave 5 closes out the remaining R-WP12 MVP and gates the OPS-T1 (defineRoute()) structural-fix decision. WP labels start at R-WP17 to avoid collision with the S8 R-WP13/14/15 IDs reserved during the S7 close-out edit.

Per R-WP12 brief Recommendation, WP-D (route/fetcher type-drift detector) was prioritised first in this wave so OPS-T1 had empirical gap-prevalence data before the priority decision. WP-D consumed the WP-B scaffold from S8 and extended it to a full report. S9 outcome: all five Wave 5 WPs shipped (R-WP17 + R-WP18 + R-WP19 + R-WP20 + R-WP21). R-WP21 recommendation is hybrid (b) per-route annotations on intelligence cluster + (c) CI gate; defer (a) OPS-T1 structural rollout. Pending Liam ratification at S9 close-out review.

WPItemEffortDepends onStatus / Justification
R-WP17Route/fetcher type-drift detector — full report (R-WP12 brief §WP-D). For each named response interface in types/*.ts and lib/query/fetchers.ts, run references and classify which appear in fetchers but lack a matching route return-type annotation. Output: docs/generated/type-drift-report.md with JSONL backing.~5hR-WP12-WPB (S8)Shipped S9 Wave 1 (795c4c31 + cleanup 9f91eacd). New query lib/ast-dataflow/queries/type-drift-detect.ts + CLI subcommand bun run ast-dataflow type-drift-detect (flags: --json, --pretty, --ci, --scope, --limit, --interface-pattern, --update-baseline). All 30 PRODUCT invariants D-1..D-30 met (incl. D-25 no-fetchers-found sentinel + D-30 structured parse_error). 22 new tests (191 → 213). KH-wide first-run baseline at docs/generated/type-drift-baseline.json carries 37 fetcher-only rows. Canonical false-negative fixtures both surface: TaxonomySyncStatus + ReviewStatsResponse. Cold ~5s / warm ~4.5s (well under D-22’s 3-min budget).
R-WP18Mechanical cast-removal sweep (R-WP12 brief §WP-B execution; KH-wide) + ESLint rule.~3hR-WP17 (uses report)Shipped S9 Wave 2 (11ade075 + cleanup 09a1e00e). 12 cast sites cleared across lib/bid/, lib/mcp/tools/, app/api/ (full list in change-log §8 T2). New ESLint rule local/no-supabase-record-cast at error level on lib/** + app/api/**; 22-entry JSONB column allowlist + 3 escape hatches; 20 RuleTester cases. Out-of-scope deferral: 3 sites in lib/topic-inference.ts:177,309,322 (file was outside R-WP18 ALLOWED list; backlog item OPS-T2 — see product-backlog.json).
R-WP19Opaque-Json RPC inventory + fix-path (R-WP12 brief §WP-C). For each of the 14 Returns: Json RPCs, determine: (a) TS callers, (b) current return shape, (c) convertibility verdict. Migration scripts NOT executed (feasibility only).~4hNone (parallel with R-WP17)Shipped S9 Wave 1 (78c8330e). Brief at docs/specs/id-16-ast-dataflow-tool/investigations/R-WP12-opaque-json-rpcs.md. Verdict counts: 5 convertible (get_dashboard_attention_counts, get_filter_counts, get_user_tag_counts, get_workspace_counts, merge_entities); 6 requires-design (get_author_analysis, get_content_gaps, get_entity_list_aggregated, get_reading_patterns, get_review_breakdown_stats, get_topic_deep_dive); 2 no-ts-callers (get_bid_summary, get_verification_stats); 1 leave-as-is (hook_restrict_signup_to_allowed_domain — Supabase Auth Hook, protocol-mandated JSONB). Recommended sprint shape: Tier 1+2 (5 convertible) ~7h. Re-runnable audit script scripts/audit-opaque-json-rpcs.ts. Feeds OQ-R9 decision (pending).
R-WP20MCP outputSchema registration scaffold (R-WP12 brief §WP-E). Register Zod outputSchema on the 5 highest-usage MCP tools using corresponding formatter interfaces as schema source. Validate via MCP SDK runtime check.~4hNoneShipped S9 Wave 2 (c98d5f1c). 5 tools registered: search_knowledge_base + search_content_chunks (lib/mcp/tools/search.ts), get_governance_queue + review_governance_item (lib/mcp/tools/governance.ts), get_change_report (lib/mcp/tools/change-report.ts). 10 Zod schemas in lib/mcp/formatters/{search,governance,change-report}.ts. Smoke test __tests__/mcp/output-schema-smoke.test.ts exercises safeParse() known-good + known-bad for all 5 (29 assertions). Full 58-tool rollout queued as R-WP22 in Wave 7 (deferred per Liam OQ-4 until main-track MCP cleanup finalises which tools are retained).
R-WP21OPS-T1 decision gate (uses R-WP17 output). Liam reviews drift-report prevalence; decides: (a) OPS-T1 defineRoute() wrapper now (~2-3 days, closes Gap 1 at root); (b) per-route annotations incrementally; (c) accept gap + rely on R-WP17 detector as lint-like CI check.~30min (decision)R-WP17RATIFIED-(c)-S10 at S10 Wave 0 close. Decision note: docs/specs/id-16-ast-dataflow-tool/type-safety-pipeline/decision-OPS-T1.md (sign-off block updated S10). Binding S10 output: investigations/S10-wave-0-synthesis.md §3.1. Wave-A (b) DROPPED — intelligence-cluster annotations would be partially overwritten by future OPS-T1 + Wave 0-C confirmed OPS-T1 needs a sibling codemod (not mechanisable today). Wave-A’ (a) DEFERRED to S11+ codemod-led rollout; specs reserved for S11 — see Wave 7 R-WP-S11-A. (c) shipped S10 WP1 (c99f5953).

Wave 6 — Packaging + Dev-workflow integration (S10)

Section titled “Wave 6 — Packaging + Dev-workflow integration (S10)”

R-WP11 (S8) is expected to produce the first skill file (ast-dataflow-rename-sweep). R-WP7 is therefore rescoped from “first skill file” to “additional skills covering the remaining query surface + skill efficacy evaluation across the now-multiple ast-dataflow skills”. The create-skill skill remains the authoring tool.

WPItemEffortDepends onJustification
R-WP7Additional ast-dataflow skill files + skill-efficacy evaluation. Beyond the rename-sweep skill from R-WP11a (S8), author skill files for the remaining HIGH-leverage R-WP11 patterns (Pattern 5: gitnexus_context + callers call-chain pinning), and for the general-purpose ast-dataflow query catalogue (.claude/skills/ast-dataflow/SKILL.md). Run the create-skill efficacy evaluation across the now-multiple skills.~3-4hR-WP11a (first skill from S8 establishes the pattern)Shipped S10 WP2 (61413dd3 + cleanup a39ab16f). Catalogue skill at .claude/skills/ast-dataflow/SKILL.md (covers all 12 queries + 9 cross-tool patterns); call-chain-pin skill at .claude/skills/ast-dataflow/ast-dataflow-call-chain-pin/SKILL.md (Pattern 5 anchored to classifyContent UUID gotcha). Efficacy eval at docs/specs/id-16-ast-dataflow-tool/skill-efficacy-S10.md (25/25 trigger phrases routed correctly). CLAUDE.md ast-dataflow section added. Two further skill candidates surfaced (Pattern 6 type-evolution-check + Pattern 8 enum-member-audit) → S11 backlog.
R-WP16Integrate with dev-workflow. RE-FRAMED-S10: Merge ast-dataflow-tooling branch into production-readiness track so 167 commits of ast-dataflow work consolidate before main-track absorption. Wave 0-D dry-run: 12 conflicts of 363 paths; AST-dataflow primitives (135 files) merge clean; moderate difficulty; 4-6h.~4-6hWave 1 close (S10)Per Liam direction at S10 open: “the actual wider task here is to be able to merge the AST data flow worktree back to the production readiness track”. S10 produced Wave 0-D merge plan (investigations/S10-r-wp16-merge-dry-run.md); execution reserved for S11 (final session on this worktree) — see Wave 7 R-WP-S11-D.

Wave 7 — S11 final session on this worktree (codemod specs + cross-track merge)

Section titled “Wave 7 — S11 final session on this worktree (codemod specs + cross-track merge)”

S11 is the last session on ast-dataflow-tooling. Scope per investigations/S10-wave-0-synthesis.md §4: parallel WP-A (codemod specs)

  • WP-B (merge pre-flight) + WP-C (housekeeping), gated by verifier, then sequential WP-D (merge execution). Post-S11, ast-dataflow work is owned by the production-readiness track.
WPItemEffortDepends onJustification
R-WP-S11-AOPS-T1 codemod investigation + spec authoring. Inventory 193-route handler shape variants. write-product-spec + write-tech-spec for scripts/codemods/wrap-define-route.ts ts-morph utility (dry-run + apply modes, idempotency, ast-dataflow type-drift-detect as post-migration verifier). No implementation in S11 — specs land; implementation in a later session aligned with main-track Phase 1 canonical-pipeline migration.~4-6hR-WP21 RATIFIED-S10Wave 0-C finding: OPS-T1 not mechanisable today (no AST-rewrite primitive in any tool). Codemod sibling-utility is the path; ast-dataflow PRODUCT.md scopes the tool away from autofix. Authoring specs now decouples the OPS-T1 timing from canonical-pipeline timing. Status: SHIPPED (fa7ee857 — 3 new files, 1159 lines: PRODUCT.md 265, TECH.md 566, route-shape-inventory.md 328).
R-WP-S11-BCross-track merge pre-flight. Terminology decision (workpackage vs task ID-N) propagation; scratch-file cleanup; roadmap JSON canonicalisation. Target: ≤6 conflicts on the next dry-run (from 12 at S10 close).~1.5-2.5hWave 0-D outputReduces S11 merge wave risk; documents Liam decisions before they propagate to production-readiness. Status: SHIPPED (b4d97ac4 — 9 files: 4 terminology files replaced with production-readiness body, 3 scratch-file cleanups, 2 doc canonicalisations). Original 12 conflicts → 4 remaining from original set + 5 new from production-readiness drift = 9 for WP-D.
R-WP-S11-CHousekeeping. Move R-WP22 row to production-readiness backlog (with S9 provenance); close AST-S9-O1 + AST-S9-O2 from backlog (shipped S10); add Pattern 6 / Pattern 8 skill candidates; ROADMAP edit reflecting all S10 + S11 outcomes; TECH.md test-path-convention note.~1hNone (parallel)Cleans up the “what’s done / what’s deferred / what’s now in production-readiness scope” matrix Liam will need at session close. Status: SHIPPED kh-ast-S11 Wave 1. Commit SHA stamped in front-matter. AST-S9-O1 closed (b2339cee), AST-S9-O2 closed (e07edfc5), Pattern 6 (23) + Pattern 8 (24) added to backlog. TECH.md §Testing and validation test-path note added. R-WP22 MIGRATED-to-production-readiness.
R-WP-S11-DCross-track merge execution (R-WP16 re-framed). Resolve 12 conflicts per S10-r-wp16-merge-dry-run.md §3 recipe; post-merge knip + full vitest + lint + format; push.~2-3hR-WP-S11-A,B,C completion + verifier gateFinal consolidation step before this worktree closes. Production-readiness → main merge is OUT OF SCOPE for S11. Status: IN-PROGRESS — deferred to Wave 2 sequential merge on production-readiness worktree.
R-WP9Cache layer (TECH.md §Cache strategy).~3hObservable warm-cache missCurrently no load-bearing trigger — column-reads smoke at 1.8 s warm, column-writes at 3.5 s warm, flow-trace warm ≈ 5 ms, all well under the 10 s P-19 budget. dead-exports full-corpus scan (4.3 s for 54 symbols) is the slowest warm query but still inside budget. Follow cocoindex-code pattern with local LMDB if/when a smoke breaches the budget. SUPERSEDED-id-375: facts cache rejected by measurement; warm path is the MCP server (PRODUCT.md A2).
R-WP11bOperationalise R-WP11 Pattern 5SUPERSEDED-S10: Pattern 5 skill landed in R-WP7 (S10 WP2 commit 61413dd3). Row retained for cross-reference; no further work.n/an/aR-WP7 absorbed R-WP11b per S8 prompt’s expected overlap.
R-WP22MCP outputSchema full rollout (R-WP12 brief §WP-E continuation). Beyond the 5-tool scaffold in R-WP20, register outputSchema on the remaining ~53 tools. Estimated: ~58 × ~30m ≈ ~29h. Multi-agent parallelisation candidate.~29hR-WP20R-WP12 brief §Open questions OQ-4. Closes Gap 4 across the full MCP surface. Status: MIGRATED-to-production-readiness — sourced from kh-ast-S9, surfaced by R-WP20 commit c98d5f1c. Added to production-readiness backlog as part of R-WP-S11-C housekeeping (kh-ast-S11 Wave 1). See §Carried forward to production-readiness below.
OPS-T1defineRoute() wrapper rollout (R-WP12 §Recommendation, conditional on R-WP21 decision). Per-route typed wrapper closing Gap 1 at the root. Estimated 2-3 days for a full sweep across 193 routes.~16-24hR-WP-S11-A (specs) + main-track Phase 1 timingDEFERRED-TO-S11+. Specs authored S11 (R-WP-S11-A); implementation queued for the session aligned with main-track Phase 1 canonical-pipeline migration. R-WP17 baseline + CI gate (shipped S10) prevent regression in the meantime.
  • Test-philosophy audit, repeat-pass — every new query’s tests audited against docs/reference/test-philosophy.md in the same session it ships. S4 WP3 ran this for the existing 5 test files; S5, S6, S7 inherited the discipline inline.
  • PRODUCT.md / TECH.md sync — every query update locks the canonical naming (S4 WP1 caught inferredwildcard drift; S5 R-WP3 added the type-evolution smoke). The Last verified header bumps in the same commit that changes the body.
  • flow-trace-TECH.md fold-down — completed kh-ast-S9 Wave 1. flow-trace-TECH.md deleted; full content now at TECH.md §Query implementations → flow-trace.

The tool is most useful when chained with other tools. Document patterns explicitly so agents and humans can compose them. The three baseline patterns below shipped alongside the original library. R-WP11 (S7) extended the catalogue with six additional patterns ranked by leverage; the highest are queued as concrete roadmap WPs (R-WP11a in Wave 4, R-WP11b in Wave 7). See docs/specs/id-16-ast-dataflow-tool/investigations/R-WP11-cross-tool-integration.md for the full catalogue with worked examples.

Pattern 1: Knip ↔ ast-dataflow (R-WP1 + R-WP2 — shipped S5)

Section titled “Pattern 1: Knip ↔ ast-dataflow (R-WP1 + R-WP2 — shipped S5)”
# Knip flags unused exports
bun run knip --reporter json | jq -r '.issues[].exports[].name' > /tmp/knip-unused.txt
# ast-dataflow verifies the full batch in a single ts-morph invocation
bun scripts/ast-dataflow-cli.ts dead-exports --symbols /tmp/knip-unused.txt --exclude-tests
# For any false-positive (Knip says unused, ast-dataflow finds importers):
bun scripts/ast-dataflow-cli.ts reexport-chain --symbol "$name" --from <file>

Output: definitive list of exports safe to delete vs. exports that escape Knip via barrel chains. Validated S5: 54-symbol Knip-diff batch → 52 confirmed dead, 2 false-positives, 4.3 s warm. The dead-exports --symbols <file> batch flag keeps a single ts-morph invocation cost amortised across all symbols.

GitNexus answers “which symbols changed in this commit” + framework-aware edge types (HANDLES_ROUTE, FETCHES, QUERIES). ast-dataflow answers “what’s the TS-resolver blast radius of this symbol”.

Compose: gitnexus_impact({target, direction: "upstream"}) first to get the process-level blast radius, then callers/column-reads/references to get the file-and-line-level blast radius. The two answers should agree at the edges; disagreement = a gap in one of the tools.

R-WP11 Pattern 4 (rename-sweep verifier — R-WP11a, S8) and Pattern 5 (call-chain pinning — R-WP11b, Wave 7) operationalise this composition for the rename and the bug-pin scenarios respectively.

Pattern 3: cocoindex-code ↔ ast-dataflow

Section titled “Pattern 3: cocoindex-code ↔ ast-dataflow”

cocoindex-code finds the string (“where does ‘project_id’ appear textually”). ast-dataflow filters to semantically-meaningful sites (string-literal-uses, column-reads, column-writes). Order matters: cocoindex casts the wide net, ast-dataflow refines.

Patterns 4–9 (R-WP11 catalogue, S7 brief)

Section titled “Patterns 4–9 (R-WP11 catalogue, S7 brief)”

Six additional patterns documented in investigations/R-WP11-cross-tool-integration.md:

  • Pattern 4 (HIGH): gitnexus_rename + string-literal-uses + importers + references — rename-sweep verifier closing gitnexus’s ast_search fallback gap.
  • Pattern 5 (HIGH): gitnexus_context + callers — call-chain pinning for indirect callers gitnexus does not index.
  • Pattern 6 (MEDIUM): gitnexus_impact + type-evolution — runtime-vs-type blast radius agreement check before a type rename.
  • Pattern 7 (MEDIUM): ccc guide + callers / string-literal-uses — concept-guide invariant verification (depends on ccc guides being populated).
  • Pattern 8 (MEDIUM): Knip enumMembers + enum-uses — confirms or refutes Knip’s known false positives on as const patterns.
  • Pattern 9 (LOW): ccc search + dead-exports --scope — concept-scoped (not path-scoped) dead-export audit.

R-WP11a (Wave 4) operationalises Pattern 4. R-WP11b (Wave 7) operationalises Pattern 5. Patterns 6, 8, 9 remain documented-only until a concrete trigger fires. Pattern 7 is blocked on ccc guide library population (a separate 30-minute seeding task surfaced as a backlog item).

Status: DEFERRED pending cocoindex canonical-pipeline collapse outcome.

The cocoindex canonical pipeline (docs/plans/phase-0-investigation/architecture/07-collapse-list.md) will retire substantial portions of the existing Python pipeline. Authoring a Python ast-dataflow sibling before the collapse list completes risks building a probe for code that’s about to be deleted.

Re-evaluation triggers (any one):

  1. The collapse-list verifier sign-off lands and the remaining Python surface is named — at that point, evaluate “what’s left worth probing?”.
  2. A KH-Python refactor surfaces that needs cross-file Python symbol-resolution answers (e.g. a Python column rename equivalent to S2-S4’s TS rename).
  3. A second project (sales-proposals, future) introduces a Python pipeline of similar size and shape.

Until any trigger fires, the AST tool stays TS-only and TECH.md §Follow-ups remains the bookmark.

These need a decision before their corresponding WP can start.

OQStatusDecision neededWhen
OQ-R1DECIDED-S4Skill-file name: ast-dataflow (cross-project, matches the roadmap pitch). General-purpose query catalogue skill lands at .claude/skills/ast-dataflow/SKILL.md in R-WP7 (Wave 6). The first sibling skill (ast-dataflow-rename-sweep) ships earlier in R-WP11a (Wave 4).n/a
OQ-R2DECIDED-S5dead-exports output shape: per-row JSONL (Shape A). Each result row in QueryResponse<DeadExportResult>.results is one {file, line, column, symbol, confidence, testOnly, reachableImporters, barrelChain?} object. Rationale: (1) the dominant consumer is a Knip-diff pipe (bun run knip --reporter json | jq … | xargs dead-exports --symbols <file>), where one-row-per-symbol is directly consumable without aggregation; (2) PRODUCT.md inv. 30 already mandates “one row per finding” + “JSONL on stdout”; (3) human reviewers can always jq -s 'group_by(.file)' to get grouped output, but the reverse (splitting a grouped structure for streaming) is much harder; (4) a --format grouped flag is deferred until a concrete consumer need surfaces. Shape A is aligned with every other query in the library. Trial on 54 KH HEAD unused exports confirmed per-row output requires zero post-processing for the pipe scenario.n/a (decided)
OQ-R3SUPERSEDED-id-375LMDB facts cache rejected by measurement — 11 of 12 queries need the live type-checked AST. Warm path is the MCP server process holding the ts-morph Project (PRODUCT.md A2, ratified 2026-07-27).n/a (superseded).
OQ-R4DECIDED-id-375Shape locked: single dispatching ast_dataflow tool (inv 28 option (b)) over shared dispatch.ts consumed by both CLI and server. Trigger fired: importers P-19 breach + rename-sweep 5×-cold-CLI friction (PRODUCT.md A3, ratified 2026-07-27).n/a (decided).
OQ-R5DECIDED-S8Wave 4 (S8) WP composition: R-WP10a (framework-portability) + R-WP12-WPA (mechanical de-cast) parallel in dispatch wave 1; R-WP11a (rename-sweep verifier) + R-WP12-WPB (drift-detector scaffold) in dispatch wave 3. R-WP13/R-WP14/R-WP15 IDs reserved during the S7 close-out edit are NOT used — concrete WP IDs are R-WP10a/R-WP11a/R-WP12-WPA/R-WP12-WPB.n/a (decided)
OQ-R6DECIDED-S8Wave 5 (S9) sequencing: WP-D (type-drift detector full report — R-WP17) runs first so OPS-T1 priority decision (R-WP21) has empirical evidence. Other Wave 5 WPs (R-WP18/19/20) run in parallel where dependencies allow.n/a (decided)
OQ-R7DEFERREDR-WP11a implementation form: CLI (scripts/rename-sweep.ts) vs skill (.claude/skills/ast-dataflow-rename-sweep/SKILL.md). Brief recommends CLI; skill is more agent-discoverable but requires create-skill + skill-efficacy evaluation.S8 Wave 1 planning.
OQ-R8DECIDED-S10CI lint gate. Shipped S10 WP1 (c99f5953) as type-drift-parity job in .github/workflows/ci.yml. Baseline ratchet semantics: PR adding a new fetcher-only interface fails CI unless baseline is explicitly updated in the same PR.n/a (decided)
OQ-R9DEFERREDOpaque-Json RPC migration appetite (R-WP19 input). If WP-C inventory shows ≥8 of 14 RPCs are straightforwardly convertible to RETURNS TABLE(...), is a migration sprint warranted?After R-WP19 inventory lands (Wave 5).
  • ts-morph cold-start is ~3-4 s on KH corpus. Every query inherits this. Iterative invocations (one symbol per call) bear the cost N times. Mitigation: batch-input flags where applicable (dead-exports --symbols <file>, flow-trace and others), keeping the corpus load amortised across the symbol set in a single CLI invocation.
  • Spec drift between PRODUCT.md and TECH.md. S4 WP1 caught the inferredwildcard confidence-name drift. Mitigation: every WP commits PRODUCT.md + TECH.md edits in the same commit as the implementation, and the Last verified header bumps each time. flow-trace-TECH.md was a sub-spec with its own header; folded into TECH.md §Query implementations on 18/05/2026 (kh-ast-S9 Wave 1).
  • Worktree agent baseline drift. S4 WP3 reset to the wrong base SHA and the cherry-pick auto-merged but pinned a stale toHaveLength(8) that S4 WP1 had invalidated. Mitigation: the brief for any worktree agent that touches files modified in earlier waves must explicitly call out the post-wave base SHA; the orchestrator validates git log --oneline -1 in the agent’s response. S5/S6/S7 dispatch all carried this rule forward without recurrence.
  • CWD drift in shell tool calls (S5–S7 recurrence). Worker agents occasionally commit to the parent’s branch via shell CWD drift when they Read cross-worktree files. Mitigation: dispatch with an explicit “commit ONLY to your worktree branch” rule; verify post-dispatch with git log --oneline -1 from both worktree and parent; cherry-pick if needed. Long-standing CLAUDE.md “Bash CWD drifts into worktree dirs” gotcha.

Items migrated from this worktree to the production-readiness track at S11 close. Added to the production-readiness backlog as part of R-WP-S11-D (cross-track merge execution) or as a post-merge commit on that track.

ItemDescriptionEffortProvenanceStatus
R-WP22MCP outputSchema full rollout (~53 remaining tools beyond the 5-tool scaffold in R-WP20). Multi-agent parallelisation candidate.~29hsource-session: kh-ast-S9; surfaced-by: R-WP20 commit c98d5f1cMIGRATED-to-production-readiness (kh-ast-S11 Wave 1 housekeeping). migrated-to: production-readiness backlog (WP-D post-merge commit).
R-WP9Cache layer (TECH.md §Cache strategy). Follow cocoindex-code pattern with local LMDB if/when a smoke query breaches the 10 s P-19 budget.~3hNo current load-bearing trigger; carried from Wave 7.SUPERSEDED-id-375 — facts cache rejected by measurement; warm path is the MCP server (PRODUCT.md A2).
OQ-R9Opaque-Json RPC migration appetite. 5-RPC Tier 1+2 sprint (~7h) queued after Phase 1 canonical-pipeline migration settles.~7hR-WP19 inventory (kh-ast-S9)Carry-forward — production-readiness backlog post-S11 merge.
AST-S3-O1column-reads --exclude-tests extended to cover test-adjacent infrastructure (scripts/mcp-eval/, e2e/fixtures/).~1hkh-ast-S3SHIPPED — chore/outstanding-cleanup-investigation (es2018 + AST follow-ups commit).
AST-S3-O2wildcard confidence tier in column-reads for .select('*') calls.~1hkh-ast-S3SHIPPED — S4 WP1 commit 9fe9b387 (ledger drift corrected at S57).

This doc is updated end-of-session for any session where a roadmap WP ships, where a deferred-OQ decision lands, or where the strategic shape of the work changes (e.g. R-WP10/11/12 outcomes restructuring the wave table). The Last verified header bumps in the same commit. Out-of-session changes (e.g. a new gap surfaces during normal work) are filed as a TODO at the bottom of the relevant section and resolved in the next roadmap-touching session.


Redaction note (04/08/2026, id-377 D7). Client-name tokens in this file were redacted per the ID-115 redaction map (specs/id-115-data-api-schema-isolation/CUTOVER-RUNBOOK.md step 3; full rule set in runbooks/_archive/id68-purge-redaction-map-draft.md). One occurrence: the auth-hook identifier in the R-WP19 row, which now reads hook_restrict_signup_to_allowed_domain — the client-neutral name that superseded it at canonical HEAD (ID-68 {68.21}). No other content was changed by the redaction pass.