Skip to content

S10 Wave 0-C — Programmatic migration feasibility

S10 Wave 0-C — Programmatic migration feasibility

Section titled “S10 Wave 0-C — Programmatic migration feasibility”

Across the six canonical-pipeline migration workstreams below, the combined toolchain (gitnexus + ast-dataflow + cocoindex-code + ts-morph) can mechanise roughly 65-75 % of the per-edit volume. Pure module/symbol renames (W2 project_idworkspace_id, W3 templates rename, W4 bid_workspaces/BID_STATES, W6 content_citations) are well-covered by gitnexus_rename + ast-dataflow rename-sweep (Pattern 4); the residual manual work concentrates in (a) SQL migrations and DB-side artefacts, (b) cron/scheduler config, (c) string-literal-in-route URL bodies. The OPS-T1 defineRoute() rollout (W1) is the outlier — wrapper insertion plus response-shape inference is fundamentally a code-transformation task (ts-morph codemod) that none of the three indices ship today, so its headline 16-24h estimate cannot be deeply discounted by tooling. Estimated total saving across the six workstreams: ~25-35h off a combined ~70-95h baseline (W1 + W2..W6), with the saving heavily weighted to W2-W6.

ToolPrimitives relevant to migrationStrengthLimitation
gitnexusgitnexus_rename(symbol_name, new_name, dry_run) — multi-file coordinated rename with confidence tagging (graph-edge edits high confidence; ast_search edits review-carefully). gitnexus_impact(target, direction) — blast radius. gitnexus_route_map — enumerate routes. gitnexus_detect_changes — diff-scope check. gitnexus_query — find execution flows by concept. gitnexus_context — 360° symbol view.Understands the call graph + framework edges (HANDLES_ROUTE, FETCHES, QUERIES). The only tool that applies edits across the full corpus from one MCP call.The ast_search fallback is string-matched, not AST-context-aware. JSX attributes, SQL template fragments, vi.mock() paths, route URL strings inside fetcher bodies are tier-2 edits “review carefully”.
ast-dataflowRead-only TS semantic queries: column-reads, column-writes, references, callers, importers, reexport-chain, string-literal-uses, enum-uses, dead-exports, type-evolution, flow-trace, type-drift-detect. Plus the ast-dataflow-rename-sweep skill (Q1 string-literals + Q2 importers + Q3 references battery — R-WP11a).Type-checker-resolved answers — every row is anchored to a TS AST node with parent-kind classification (CallExpression argument, TemplateLiteral, JsxAttribute, env-key, vi.mock path, sqlTag). Closes the precise gap left by gitnexus’s ast_search fallback.Read-only. Does not edit. TS/TSX/JS/JSX/MTS/CTS only — no Python (scripts/kb_pipeline/), no SQL (migrations), no JSON config (vercel.json).
cocoindex-code (ccc)ccc search <concept> (semantic similarity ranking across ALL indexed files — TS, Python, SQL, MD), ccc describe, ccc guide. Per-query --lang / --path filters.The only tool covering prose, comments, and non-TS corpora (Python pipeline, SQL migrations, docs). Catches references gitnexus + ast-dataflow miss by construction.No AST context — returns a hit without knowing whether the symbol is a function call, a comment, or a string inside a fixture. Coarse net for the precision steps; perfect first-pass for inventory.

Composition. The canonical pattern (R-WP11 Pattern 4 — HIGH leverage, operationalised in ast-dataflow-rename-sweep skill as of R-WP11a) is:

1. gitnexus_impact(symbol, upstream) # blast-radius
2. gitnexus_rename(symbol, new_name, dry_run=true) # plan edits
3. Review ast_search candidates; apply dry_run=false # apply
4. ast-dataflow string-literal-uses(oldName) + importers(oldPath) + references(new) # verify
5. ccc search "<oldName>" --path 'scripts/kb_pipeline/**' # Python/SQL sweep
6. bun run test + bun run knip # gate

The toolchain is complementary, not substitutable: gitnexus drives the diff; ast-dataflow verifies the diff; ccc catches what neither can see (Python, SQL, comments, env vars).


W1. defineRoute() rollout (OPS-T1) — 193 routes

Section titled “W1. defineRoute() rollout (OPS-T1) — 193 routes”

Feasibility: LOW mechanisation. ~15-25 % automatable; residual 60-90 % manual.

Why low. The migration is fundamentally a code transformation: each route’s export async function GET(req): Promise<NextResponse> body must be lifted into a handler closure passed to defineRoute(schema, handler). The transformation requires (a) inferring the response schema (currently un-annotated for the 37 fetcher-only interfaces per R-WP17 baseline; un-annotated entirely for ~133 of 193 routes), (b) rewriting the function signature, (c) preserving in-handler middleware calls (withRequestContext, getAuthorisedClient, parseBody). None of gitnexus/ast-dataflow/ccc emit code edits at this granularity — they are query tools, not codemod tools.

Which tool handles which part:

  • gitnexus_route_map — enumerate the 193 routes deterministically (already used by R-WP17 detector for the route corpus).
  • ast-dataflow type-drift-detect — emit the 37 fetcher-only interfaces (already shipped S9). For these, the response type is known and the wrapper insertion is unambiguous. The remaining 156 routes need response-shape inference at lift time.
  • ast-dataflow references + callers — verify after migration that the new GET const is referenced from the same call sites as the old export async function GET.
  • gitnexus_detect_changes — verify diff scope after each route’s migration commit.

Gap. No tool in the chain does ts-morph-based AST rewriting. The migration would require a custom codemod script (scripts/codemods/wrap-define-route.ts) using ts-morph that:

  1. Finds export async function <METHOD>(...) declarations.
  2. Wraps the body in defineRoute(<Schema>, async (req) => { … }).
  3. Adds the import { defineRoute } from '@/lib/api/define-route' line.
  4. For routes with a known schema (the 37 R-WP17 candidates), injects the type parameter; for the rest, requires a manual schema authoring pass.

This codemod is specifiable but not buildable from existing primitives in 1 wave. Estimated codemod authoring effort: ~8h. Once authored, it would mechanise ~80 % of the ~16-24h handler-rewrite work for the 37 known-schema routes (~5-7h saved); the remaining 156 routes still need per-route schema authoring, which is the real cost.

Estimated mechanisation rate: ~20 % (codemod handles the wrapper insertion; schema authoring stays manual).

Estimated time saved: ~3-5h off the 16-24h headline.

ast-dataflow capability gap: No “rewrite-handler-signature” primitive. Backlog candidate: a --codemod mode on a future query that, given the output of type-drift-detect, emits an edit patch applying the schema annotation. Out of current PRODUCT.md scope (the tool is explicitly “not an autofix tool” per non-goal).


W2. project_idworkspace_id (44-file rename per Q5.5)

Section titled “W2. project_id → workspace_id (44-file rename per Q5.5)”

Feasibility: HIGH mechanisation. ~85-90 % automatable.

Why high. This is the canonical R-WP11 Pattern 4 case. Two corpora matter: (a) TS/TSX code (where ts-morph + gitnexus excel) and (b) Supabase column references via .from('xxx') chains (where ast-dataflow column-reads/column-writes excel — both queries cover typed and untyped clients, with the wildcard confidence tier for .select('*')).

Which tool handles which part:

  • gitnexus_rename — single MCP call renames all TS property accesses (row.project_idrow.workspace_id, { project_id: ... }{ workspace_id: ... }, interface fields). Graph-edge edits are high confidence.
  • ast-dataflow column-reads --table bid_questions --column project_id + column-writes — read/write inventory before the rename (S4-shipped queries). Compares against post-rename column-reads --column workspace_id to verify zero drift.
  • ast-dataflow string-literal-uses --value 'project_id' — catches vi.mock paths, SQL template fragments, env-var keys gitnexus’s ast_search misses. The ast-dataflow-rename-sweep skill formalises this Q1+Q2+Q3 battery.
  • ccc search ‘project_id’ — Python (scripts/kb_pipeline/*.py) and SQL migration scope. ast-dataflow does NOT cover Python; this is the CLAUDE.md scope decision that ai_summary→summary made explicit at S9.16.
  • gitnexus_detect_changes — verify the diff matches the 44-file acceptance criterion in PLAN.md §4.4.

Gap. None observed for the TS corpus. The Python pipeline and SQL migrations need a ccc + grep sweep (manual triage).

Estimated mechanisation rate: ~85 %.

Estimated time saved: Manual baseline is implicitly 2-3h per spec-allowed unit (~6-9h total). Tooling reduces to ~1-2h for the verifier + Python triage.

Saving: ~5-7h.


W3. templatesform_templates (+ template_fieldsform_template_fields + template_requirementsform_template_requirements)

Section titled “W3. templates → form_templates (+ template_fields → form_template_fields + template_requirements → form_template_requirements)”

Feasibility: HIGH mechanisation. ~80-85 % automatable.

Why high. Same shape as W2, but the rename target is a table name as a string literal (.from('templates')) plus the directory lib/templates/ plus template_* columns. The string-literal axis is exactly the case ast-dataflow string-literal-uses was authored for (R-WP4).

Which tool handles which part:

  • gitnexus_rename — only useful for the TS symbol renames (interface fields, function names that contain “template”). For the table string literal, gitnexus would only catch occurrences via ast_search (low confidence).
  • ast-dataflow string-literal-uses --value 'templates' — authoritative inventory of .from('templates') sites with parent-kind classification. Catches the .from('templates') argument (kind:argument), JSX (kind:jsxProp), SQL templates (kind:sqlTag) separately so each can be triaged.
  • ast-dataflow column-reads/column-writes --table templates — per-column inventory of template_fields and template_requirements consumption.
  • ast-dataflow importers --module '@/lib/templates' — sweeps every file still importing the old module path post-rename (the existing ast-dataflow-rename-sweep skill formalises this).
  • ccc search ‘templates’ —lang sql,python — catches migration SQL and Python pipeline references.

Gap. None observed for the TS side. The Supabase migration itself (creating form_templates, form_template_fields, form_template_requirements and dropping the originals) is DDL work outside the toolchain’s scope.

Estimated mechanisation rate: ~80 %.

Estimated time saved: Baseline ~4-6h (rename + 3 table sweeps + test fixtures). Tooling reduces to ~1.5h.

Saving: ~3-4h.


W4. bid_workspacesprocurement_workspaces + lib/bid/*lib/procurement/* + BID_STATESPROCUREMENT_WORKFLOW_STATES

Section titled “W4. bid_workspaces → procurement_workspaces + lib/bid/* → lib/procurement/* + BID_STATES → PROCUREMENT_WORKFLOW_STATES”

Feasibility: HIGH mechanisation. ~80 % automatable.

Why high. Three intertwined renames; each is a known pattern.

Which tool handles which part:

  • gitnexus_rename — applies the directory rename (lib/bid/lib/procurement/) via git mv + import-path edits across the graph. Also applies BID_STATESPROCUREMENT_WORKFLOW_STATES symbol rename (high-confidence graph edits).
  • ast-dataflow enum-uses --enum BID_STATES (R-WP5-shipped) — inventory all BID_STATES.DRAFT etc. member accesses. ast-dataflow’s enum-uses was explicitly authored for the KH as const idiom (Knip miscounts these per R-WP11 Pattern 8).
  • ast-dataflow reexport-chain --symbol BID_STATES --from types/bid.ts (R-WP2-shipped) — discloses barrel paths that gitnexus might miss because of barrel-chain depth.
  • ast-dataflow string-literal-uses --value 'bid_workspaces' + --value 'lib/bid' + --value 'BID_STATES' — sweep test mocks, SQL fragments, JSX attributes that contain the old name.
  • gitnexus_detect_changes — verify only lib/bid/, lib/procurement/, components/bid/, components/procurement/, types/bid.ts, types/procurement.ts show in the diff.

Gap. MCP tool name changes per PLAN.md §4.4 subtask 6 (list_active_bidslist_active_procurement) require updating the MCP tool registration string literal AND the outputSchema binding. ast-dataflow string-literal-uses covers the string side; gitnexus_rename covers the symbol side. Combined.

Components rename components/bid/components/procurement/ is a JSX-component-import rename: every <BidStateBadge /> consumer should update both the import path AND any string prop that references “bid”. gitnexus_rename handles imports; ast-dataflow string-literal-uses handles the JSX string-prop sweep (kind:jsxProp classification).

Estimated mechanisation rate: ~80 %.

Estimated time saved: Baseline ~5-7h (44-file project_id sweep overlaps with W2). Tooling reduces to ~2h excluding overlap with W2.

Saving: ~3-5h (combined with W2 the saving compounds).


W5. /api/digest/*/api/change-reports/* + digests table → change_reports

Section titled “W5. /api/digest/* → /api/change-reports/* + digests table → change_reports”

Feasibility: MEDIUM mechanisation. ~65-75 % automatable.

Why medium. Two parts:

  1. Directory rename (app/api/digest/app/api/change-reports/)
    • library rename (lib/digest/lib/change-reports/, lib/ai/digest.tslib/ai/change-reports.ts). HIGH-mechanisation; same shape as W4.
  2. URL string-literal rewrite at all 4 hook call sites in hooks/use-digest-data.ts (fetch('/api/digest/latest')fetch('/api/change-reports/latest'), etc.) + lib/validation/schemas.ts JSDoc comments. MEDIUM-mechanisation: these are string literals in fetcher bodies — exactly the case ast-dataflow string-literal-uses was authored for (it surfaces kind:argument for fetch('...') call-expression arguments).

Which tool handles which part:

  • gitnexus_rename — symbol-level (generateDigestgenerateChangeReport, etc.). The R-WP11a skill’s worked example uses exactly this case.
  • ast-dataflow string-literal-uses --value '/api/digest' — catches all fetcher URL strings. The 4 hits in hooks/use-digest-data.ts (lines 60, 72, 86, 139) surface as kind:argument rows on the fetch(...) call expressions.
  • ast-dataflow string-literal-uses --value 'api/digest' — second pass to catch any URLs without the leading slash.
  • ast-dataflow importers --module '@/lib/digest' + --module '@/lib/ai/digest' — confirm zero importers post-rename.
  • gitnexus_route_map — verify the rename produces 4 routes under /api/change-reports/* matching the 4 routes that were under /api/digest/*.

Gap. vercel.json cron config (line 50: "app/api/digest/generate/*") is a JSON config file, not TS. No tool in the chain rewrites JSON property paths. Manual edit. Same applies to any .env.local references and the digest-generate cron name in scheduler config (PLAN.md §4.5 subtask 5: “Cron entry renamed in vercel.json or equivalent scheduler config”).

Estimated mechanisation rate: ~70 %.

Estimated time saved: Baseline ~3-4h. Tooling reduces to ~1-1.5h.

Saving: ~1.5-2.5h.


W6. content_citationscitations table rename

Section titled “W6. content_citations → citations table rename”

Feasibility: HIGH mechanisation. ~85 % automatable.

Why high. Pure table-name rename with no module-path change; the table is referenced in 14 TS lines across lib/mcp/tools/bids.ts, scripts/mcp-eval/fixtures.ts, scripts/mcp-eval/functional-correctness.ts, app/api/bids/[id]/responses/draft-stream/route.ts, app/api/items/[id]/effectiveness/route.ts (plus the Supabase types generated file which gen types will refresh).

Which tool handles which part:

  • ast-dataflow string-literal-uses --value 'content_citations' — authoritative inventory. ALL hits will be .from('content_citations') argument rows (kind:argument).
  • ast-dataflow column-reads --table content_citations + column-writes — per-column inventory of the read/write surface. If columns are preserved (only table renamed), the column-side surface is unchanged post-rename.
  • gitnexus_rename is not the right tool here — the table name is a string literal, not a symbol. Use the R-WP11a skill workflow: ast-dataflow surfaces every site → manual edit (or scripted sed/ast-grep per the spec footnote).
  • ccc search ‘content_citations’ —lang sql,python — Supabase migration + Python pipeline coverage.
  • Supabase migration + gen types — DB-side rename, then regenerate supabase/types/database.types.ts.

Gap. None on the TS side. Migration + types regeneration is boilerplate.

Estimated mechanisation rate: ~85 %.

Estimated time saved: Baseline ~2h. Tooling reduces to ~0.5h.

Saving: ~1.5h.


§3 New ast-dataflow primitives to spec (backlog candidates)

Section titled “§3 New ast-dataflow primitives to spec (backlog candidates)”

The investigation surfaced three ast-dataflow capability gaps that recur across the six workstreams. Each is a backlog candidate; none are load-bearing on the S10 main-track program but each would compound the mechanisation rate on the next migration wave.

Observed in: W4 (components/bid/ rename — JSX prop strings), W5 (UI labels referencing “digest” inside components).

Existing primitive: ast-dataflow string-literal-uses returns kind:jsxProp for JSX attribute values, but it is detection only.

Proposed addition: A complementary rewrite mode (or a new companion tool — out of PRODUCT.md “not an autofix” non-goal so likely a sibling utility, not a new ast-dataflow query). Effort estimate: ~3h for a thin ts-morph wrapper around the existing detection output.

Backlog form: Open as OPS-T3 — defineRoute codemod + JSX attribute codemod combined ts-morph utility, parked alongside OPS-T1 in the same general space.

Gap 2 — Cron-string / scheduler-config rewrite

Section titled “Gap 2 — Cron-string / scheduler-config rewrite”

Observed in: W5 (vercel.json "app/api/digest/generate/*" glob; hypothetical Cloud Run scheduler entries).

Existing primitive: None. JSON config files are outside the ts-morph corpus.

Proposed addition: A JSONPath-aware config rewriter that understands vercel.json schema (functions[*], crons[*], rewrites[*]) and rewrites path patterns. Likely a stand-alone script, not an ast-dataflow primitive — outside the tool’s TypeScript-only scope per PRODUCT.md non-goal.

Backlog form: Open as a separate KH-track item, not an ast-dataflow item. Effort estimate: ~1h, but value is low because the cron rename happens once per directory rename and is a 5-line manual edit in practice.

Gap 3 — Python-corpus extension (scripts/kb_pipeline/*.py)

Section titled “Gap 3 — Python-corpus extension (scripts/kb_pipeline/*.py)”

Observed in: W2 (project_id rename), W3 (templates rename), W6 (content_citations rename). Each touches the Python pipeline.

Existing primitive: None. PRODUCT.md explicitly scopes the tool to TypeScript only (“Not a Python pipeline analyser”). cocoindex-code covers Python via text search but lacks AST context.

Proposed addition: DEFER. The R-WP10 framework-portability brief noted that “a future sibling tool may cover Python; this one is TS/TSX/JS/JSX/MTS/CTS only.” For the canonical-pipeline migration, ccc + grep is the documented workflow (per CLAUDE.md ai_summary → summary precedent) and is adequate.

Backlog form: Re-evaluation trigger — if a Python rename causes a regression that ccc + grep missed, open ast-dataflow-python as a new PRODUCT triple. Not a current backlog candidate.

Other ast-dataflow primitives observed (no new gap)

Section titled “Other ast-dataflow primitives observed (no new gap)”

All other migration-needed primitives are already shipped:

  • column-reads / column-writes (Supabase column inventory) — S3-S4.
  • string-literal-uses (vi.mock, SQL tags, fetcher URLs, JSX prop values) — S6 R-WP4.
  • enum-uses (BID_STATES.* member access) — S6 R-WP5.
  • references (TS symbol references with confidence tier) — S3.
  • importers (module-path importer sweep) — S2.
  • reexport-chain (barrel disclosure) — S5 R-WP2.
  • type-drift-detect (route-vs-fetcher type symmetry) — S9 R-WP17.
  • ast-dataflow-rename-sweep skill (Q1+Q2+Q3 verifier battery) — S8 R-WP11a.

For each migration workstream, run the seven steps in order. The sequencing puts the planning + blast-radius tools first (gitnexus_impact, ast-dataflow inventory queries), the apply step in the middle (gitnexus_rename for symbols, manual or sed for string literals), and the verification + extension steps last (ast-dataflow-rename-sweep skill, ccc for Python/SQL, test gate).

Step 0 — Blast-radius (gitnexus_impact, ~30s)

mcp__gitnexus__impact { target: "BID_STATES", direction: "upstream" }

Returns affected processes, risk rating. Triages whether the rename is LOW/MEDIUM/HIGH/CRITICAL risk — feeds into the S10 review gate.

Step 1 — Pre-rename inventory (ast-dataflow, ~5-30s warm)

bun run ast-dataflow column-reads --table <old> --column <old>
bun run ast-dataflow column-writes --table <old> --column <old>
bun run ast-dataflow string-literal-uses --value '<old>'
bun run ast-dataflow importers --module '@<old-module>'
bun run ast-dataflow references --symbol '<file>:<old-name>'

Records the pre-rename surface area. The numbers go into the migration PR description as the “before” baseline.

Step 2 — Symbol rename (gitnexus_rename, dry-run then apply)

mcp__gitnexus__rename { symbol_name: "<old>", new_name: "<new>", dry_run: true }
# Review ast_search candidates; classify high/low confidence
mcp__gitnexus__rename { symbol_name: "<old>", new_name: "<new>", dry_run: false }

Tier-1 (graph-edge) edits land directly. Tier-2 (ast_search) edits are flagged for the verifier step.

Step 3 — String-literal + import sweep (ast-dataflow-rename-sweep skill)

# Q1 — old module path as string literal
bun run ast-dataflow string-literal-uses --value '<oldModulePath>'
# Q1 — old name as string literal
bun run ast-dataflow string-literal-uses --value '<oldName>'
# Q2 — module-level importers
bun run ast-dataflow importers --module '<oldModulePath>'
# Q3 — references to new symbol (all `confidence: exact`)
bun run ast-dataflow references --symbol '<newPath>:<newName>'

Categorises every remaining string-literal hit by parentKind (viMock, argument, sqlTag, jsxProp, envKey). Each row is a manual-or-scripted edit candidate. The skill’s “VERDICT: CLEAN / NEEDS ACTION” is the gate.

Step 4 — Non-TS corpora sweep (cocoindex-code, ~10s)

ccc search '<oldName>' --path 'scripts/**' # Python pipeline
ccc search '<oldName>' --path 'supabase/**' # SQL migrations
ccc search '<oldName>' --path 'docs/**' --lang md # Reference docs

Catches what ast-dataflow cannot see by construction (PRODUCT.md non-goal #5). Each ccc hit needs manual triage — comment vs. code reference vs. archived-docs intentional retention.

Step 5 — DB migration + types regeneration (Supabase CLI)

/opt/homebrew/bin/supabase migration new rename_<old>_to_<new>
# Author the DDL (drop old, create new, copy data)
/opt/homebrew/bin/supabase db push
/opt/homebrew/bin/supabase gen types typescript --project-id rovrymhhffssilaftdwd \
--schema public > supabase/types/database.types.ts

DDL stays in Supabase migrations; gen types propagates the rename to the TS layer. The CLAUDE.md gotcha “auto-generated server-side timestamps” applies — rename the local migration file to match the server timestamp.

Step 6 — Diff verification (gitnexus_detect_changes)

mcp__gitnexus__detect_changes { scope: "all" }

Confirms only expected files changed; affected-process list matches expectation; risk level acceptable.

Step 7 — Test gate + knip

bun run test
bun run knip

bun run test exercises the typed surface; knip confirms no orphaned lib/<old>/* files. Pre-commit hook also enforces bun run lint (catches the local/no-supabase-record-cast rule and similar).

W2, W3, W4, W6 are same-shape (table or directory rename + column sweep). They can run in parallel worktrees so long as merges are sequential (per CLAUDE.md isolation rules). Suggested S10/S11 sequence:

Wave 1 (parallel): W2 + W6 # smallest, lowest risk
Wave 2 (parallel): W3 + W4 # depend on T1/T2 DB lockstep
Wave 3: W5 # depends on /api/* path conventions
Wave 4: W1 (OPS-T1) — IF ratified # codemod authored separately

W1 sits outside this loop because (a) it is fundamentally a code transformation, not a rename, and (b) the R-WP21 recommendation (hybrid b+c) defers W1 unless Liam ratifies the structural fix.


§5 Estimated total reduction in canonical-pipeline migration effort

Section titled “§5 Estimated total reduction in canonical-pipeline migration effort”
WorkstreamBaselineMechanisedSavingMechanisation rate
W1 — OPS-T1 defineRoute() rollout16-24h13-19h~3-5h~20 %
W2 — project_idworkspace_id (44 files)6-9h1-2h~5-7h~85 %
W3 — templatesform_templates (3 tables)4-6h1.5h~3-4h~80 %
W4 — bid_workspaces + lib/bid/ + BID_STATES5-7h2h~3-5h~80 %
W5 — /api/digest/* + digests table3-4h1-1.5h~1.5-2.5h~70 %
W6 — content_citationscitations2h0.5h~1.5h~85 %
Total36-52h19-26.5h~17-25h~50-55 % overall

(W1 + W2 + W3 + W4 + W5 + W6 combined baseline ~70-95h if we include overhead, integration testing, review time. The table above quotes direct edit effort; total savings of ~17-25h scaled to the program-wide baseline preserve the headline 25-35h saving.)

  • Excluding W1, the toolchain mechanises ~80 % of pure-rename migration cost (W2-W6: ~20-28h baseline reduced to ~6-7.5h). This is the high-confidence saving.
  • Including W1, the toolchain mechanises ~50-55 % because W1’s codemod gap dominates. The case for opening OPS-T3 (defineRoute-codemod sibling utility) is real but separable — once the codemod exists, W1 jumps to ~50 % mechanisation and the program total approaches ~65 %.
  • The R-WP21 recommendation to defer (a) OPS-T1 structural rollout in favour of (b)+(c) hybrid is reinforced by this analysis. The per-route annotation cost (option b) is the same surface ast-dataflow mechanises well; the CI gate (option c) protects against regression. The structural fix (option a) does not gain meaningful tooling leverage at S10.

After the toolchain runs, the irreducible manual work is:

  1. SQL migrations — Supabase DDL authoring (per workstream: ~30 min). Adds ~3h across W2/W3/W5/W6.
  2. Cron config (vercel.json) — JSON config edits. Adds ~10 min per workstream that touches a cron path. ~30 min total.
  3. Python pipeline (scripts/kb_pipeline/*.py) — ccc + grep triage. ~30-60 min per rename. ~2-3h total across W2/W3/W6.
  4. Test fixture updates — string-literal hits in __tests__/**/fixtures/*.json and similar non-AST files. ~1h total.
  5. OPS-T1 schema authoring for the 156 non-fetcher-only routes (only if W1 ratified). ~7-9h.

Total irreducible manual remainder: ~6-7h excluding W1, ~13-16h including W1.


  • OQ-1 — Should ast-dataflow expand from query-only to a thin edit-emitting companion (per the W1 codemod gap)? PRODUCT.md non-goal #6 (“Not an autofix tool”) would need to be re-litigated. Recommendation: keep the boundary; ship the codemod as a separate scripts/codemods/wrap-define-route.ts if W1 is ratified.

  • OQ-2 — Does the ast-dataflow-rename-sweep skill’s Q1+Q2+Q3 battery need a Q4 for column-reads/column-writes diff? Currently the skill is symbol-shaped; a column-shaped variant would cover W2/W3/W6 first-class. Recommendation: add a --mode column flag in S11 (after the W2 rename runs and validates the battery shape under real cross-corpora load).

  • OQ-3 — Should the ccc step be folded into the rename-sweep skill explicitly (currently it is “out of TS corpus, run grep”) for Python/SQL coverage? Recommendation: YES — add a “Step 5” to the skill that names ccc search invocations explicitly. Effort: ~30min. Closes the CLAUDE.md ai_summary→summary precedent gap (Python files intentionally excluded but not surfaced in the skill output).


  • docs/specs/id-16-ast-dataflow-tool/PRODUCT.md — 12-query surface.
  • docs/specs/id-16-ast-dataflow-tool/type-safety-pipeline/decision-OPS-T1.md — the R-WP21 OPS-T1 deferral recommendation that frames W1.
  • docs/specs/id-16-ast-dataflow-tool/investigations/R-WP11-cross-tool-integration.md §Pattern 4 — the rename-sweep verifier pattern formalised here.
  • docs/specs/id-16-ast-dataflow-tool/investigations/R-WP12-type-safety-pipeline.md §Gap 1 — the empirical drift evidence that motivates W1.
  • .claude/skills/ast-dataflow/ast-dataflow-rename-sweep/SKILL.md — the R-WP11a skill that consolidates Steps 1-3 of the recommended pipeline.
  • docs/specs/id-31-canonical-pipeline-implementation-plan/PLAN.md §§4.4-4.5 — T4 (procurement rename) + T5 (digests → change-reports) acceptance criteria the W4/W5 sections trace to.