S528 census — Lane 2: seeding + propagation
Lane 2 — Seeding, propagation and fixture-generation scripts
Section titled “Lane 2 — Seeding, propagation and fixture-generation scripts”Census only. No file was edited; no seeding script was run.
HEAD c3286753f. Measurements against Platform staging rbwqewalexrzgxtvcqrh and
Platform prod zjqbrdctesqvouboziae, 2026-08-03.
Classification scheme (owner’s, S528):
- (i) DB-reset seed — data seeded to a Platform or client staging DB on reset
- (ii) new-client deploy seed — initial data a brand-new client DB needs
- (iii) test data — fixtures for tests
- (iv) RETIRE — no longer required at all
0. Delete these now — zero ambiguity
Section titled “0. Delete these now — zero ambiguity”Five targets. Each has a ratified anchor or a measured proof, and nothing downstream depends on them.
| # | Target | Why it is unambiguous |
|---|---|---|
| 1 | scripts/staging-reference-refresh.sh (137 lines) + .github/workflows/staging-reference-refresh.yml (weekly cron) | Its 5 real tables are seeded identically by supabase/seed.sql §4. Measured: Platform prod’s contents for all 5 are byte-equal to seed.sql’s hardcoded baseline (7/34/4/14/1), so the copy moves nothing. Its 6th table public.template_requirements has never existed in this schema. Its DELETE FROM step destroys staging-only rows that prod cannot restore. |
| 2 | scripts/generate-purge-path-inventory.ts (569 lines) | Sole purpose was generating the --paths-from-file input for the {68.10} git-filter-repo purge. id-68 is status: archived; {68.10} and {68.29} are both done (purge executed S373/S375). An irreversible one-shot that has fired. |
| 3 | __tests__/scripts/generate-purge-path-inventory.test.ts | Dies with #2. |
| 4 | scripts/generate-entity-aliases-snapshot.ts (97 lines) | DR-121 (accepted 2026-08-03) names it explicitly: “zero callers — absent from package.json scripts, from every workflow, and from deploy/onprem/*”. Independently confirmed below. |
| 5 | canonicalisation.py’s _load_db_entity_aliases() branch + _ENTITY_ALIASES_SNAPSHOT_PATH (scripts/cocoindex_pipeline/canonicalisation.py:276-300) | DR-121: “either wire the generator into deploy or delete generator + loader branch”. The generator cannot be wired — it is TypeScript and onprem-deploy.yml packages only scripts/**/*.py. So the branch is unreachable in production by construction. |
Owner action: git rm items 1–4; excise the loader branch in item 5 (leave the
baseline alias map intact). Also delete the template_requirements line from
supabase/seed.sql:276 and from runbooks/staging-refresh.md §5/§7 (see §3.1).
1. Bucket counts
Section titled “1. Bucket counts”| Bucket | Count | Files |
|---|---|---|
| (i) DB-reset seed | 2 | supabase/seed.sql, scripts/seed-e2e-users.ts (dual (i)/(iii)) |
| (ii) new-client deploy | 4 | seed-tenant-from-bundle.ts, reseed-tenant-instance.ts, fetch-client-branding.ts, set-data-api-exposure.ts |
| (iii) test data | 6 | seed-e2e-users.ts, seed-procurement-test-data.ts, seed-id145-w1f-exemplar.ts, seed-goose-service-actor.ts, mcp-eval/seed-fixtures.ts, mcp-eval/seed-data.ts |
| (iv) RETIRE | 6 | staging-reference-refresh.sh + .yml, generate-purge-path-inventory.ts, generate-entity-aliases-snapshot.ts, seed-platform-from-staging.ts, generate-content-type-values.ts (conditional — see §5.3) |
| Not seeding at all (misfiled by the brief) | 5 | generate-api-views.ts, generate-skills-inline.ts, generate-client-branding-map.ts, generate-taxonomy-snapshot.ts, generate-classification-prompt-taxonomy.ts + sync-plugin-taxonomy.ts |
| REWRITE | 4 | propagate-canonical-content.ts, propagation/payload-contract.ts, seed-platform-workspaces.ts, seed-platform-feed.ts |
2. Main table
Section titled “2. Main table”| Target | Bucket | Verdict | Conf. | Evidence | Blast radius | Owner action |
|---|---|---|---|---|---|---|
scripts/staging-reference-refresh.sh:37-57 | (i) | RETIRE | high | Measured prod == seed.sql §4 baseline for all 5 real tables; template_requirements absent from schema (supabase/types/database.types.ts, all migrations) | .github/workflows/staging-reference-refresh.yml; supabase/seed.sql:272-289 §3 comment; runbooks/staging-refresh.md §5 L132-157 + §7 L219-227; 6 cross-refs in sibling nightly workflows (comment-only) | Delete the script + workflow; delete seed.sql §3’s comment block; rewrite runbook §5/§7 |
.github/workflows/staging-reference-refresh.yml | (i) | RETIRE | high | Same. Weekly cron 0 3 * * 1, last green run 2026-08-03T06:00 (gh run list) — green because nothing verifies the phantom table | 2 GH env secrets (PROD_SUPABASE_DB_URL, STAGING_SUPABASE_DB_URL) become unused | Delete; unregister the two secrets |
supabase/seed.sql §4 (L292-408) | (i) | KEEP | high | The real bucket-(i) surface. Idempotent ON CONFLICT DO NOTHING; declared for the staging branch via config.toml [remotes.staging.db.seed] | — | Keep. Fix :276 (phantom table name) |
scripts/propagate-canonical-content.ts (676 L) | (ii) | REWRITE | high | Propagates taxonomy_domains + taxonomy_subtopics to client DBs — directly contradicts the owner’s stated position. Also content_propagation_version = 0 rows on both Platform DBs → the worker has never run (its own ledger is the proof) | propagation/payload-contract.ts, seed-platform-from-staging.ts, 3 test files, client-app-deploy.md §7 | Cut taxonomy from the contract, then decide whether the worker survives at all (§4) |
scripts/propagation/payload-contract.ts:77-154 | (ii) | REWRITE | high | 7 declared tables; 2 are taxonomy; 1 (reference_items) is self-declared unimplementable (“not resolvable in {95.11}”) and SKIP-LOUD in the worker. Net live payload = 4 tables | __tests__/scripts/propagation/payload-contract.test.ts | Reduce to layer_vocabulary, application_types, form_types, form_requirement_templates; delete the reference_items entry outright |
scripts/seed-tenant-from-bundle.ts (211 L) | (ii) | KEEP | high | client-app-deploy.md §3d + §6 step 4 — the named operator CLI, “proven on staging + prod this session” | — | Keep unchanged |
scripts/reseed-tenant-instance.ts (226 L) | (ii) | KEEP | high | The library half seed-tenant-from-bundle.ts imports (:47). Also the sole creator of the branding bucket per client-app-deploy.md §3d.5 L221 | __tests__/scripts/reseed-tenant-instance.test.ts | Keep. Consider folding into the CLI (§5.1) |
scripts/fetch-client-branding.ts (13 KB) | (ii) | KEEP | high | package.json prebuild + build:vercel; client-app-deploy.md §3f — fail-closed client build | __tests__/scripts/fetch-client-branding.test.ts | Keep |
scripts/set-data-api-exposure.ts | (ii) | KEEP | high | client-app-deploy.md §3b.5 + §6 step 2 | — | Keep |
scripts/seed-platform-from-staging.ts (251 L) | (i) | RETIRE | medium | A direction-locked wrapper reading a client staging DB (STAGING_PROJECT_REF — scripts/lib/project-refs.ts:38-45 documents it as “the CLIENT-staging project, distinct from Platform staging”). Under S528’s “no clients” frame there is no such source. Its 6 payload tables are now covered by seed.sql §4 (3 of them) or arrive with migrations (application_types=6, form_types=7 measured on both DBs). Prior audit already flagged it “RETIRE-or-keep-noted” (docs/reports/jscpd-report/audit-scripts.md:53) | __tests__/scripts/seed-platform-from-staging.test.ts (11.7 KB) | Delete both. Any residual gap is one ON CONFLICT block in seed.sql §4 |
scripts/seed-platform-workspaces.ts (361 L) | (i) | REWRITE | medium | Seeds 6 workspaces (one per application_type). Measured: staging 0, prod 1. Half-applied; neither DB matches what the script describes. Its stated prerequisite (seed-platform-from-staging seeds application_types) is false — those 6 rows arrive with migrations | __tests__/scripts/seed-platform-workspaces.test.ts; verify-platform-promotion-gate.ts:82 and seed-platform-feed.ts:61 both import PLATFORM_TARGETS/SeedDbClient from it | Decide whether Platform needs 6 workspaces or 1; then either run it or fold the six INSERTs into seed.sql §4 and delete the script. Move PLATFORM_TARGETS to scripts/lib/ first |
scripts/seed-platform-feed.ts (292 L) | (i)/(iii) | REWRITE | medium | ID-127 BI-4 cocoindex walk-proof. Measured: prod feed_sources=1 / feed_articles=0; staging 0/0. Never completed on either DB. Depends on seed-platform-workspaces having run (it has not, on staging) | __tests__/scripts/seed-platform-feed.test.ts; scripts/fixtures/platform-feed-seed-*.{html,atom} (DO-NOT-MOVE — their repo path is a live URL, corpus-manifest.json:39) | Same decision as workspaces. The two are one seed, not two |
scripts/seed-e2e-users.ts (977 L) | (i)+(iii) | KEEP / split | high | Genuinely wired: package.json seed:e2e-users; ci.yml:485; e2e-nightly.yml:297; e2e/global-setup.ts:134,199 | — | Keep, but it is three scripts in one (§5.2) |
scripts/seed-procurement-test-data.ts (766 L) | (iii) | KEEP | medium | E2E fixture seed; absorbed the retired wipe-procurement-responses.ts as --reset (bl-361) | — | Keep. Extract loadEnv (§5.4) |
scripts/seed-id145-w1f-exemplar.ts (292 L) | (iii) | KEEP | medium | ID-145 BI-44/BI-45. Its JOB 2 (reseed form_requirement_templates) is still open — measured 0 rows on both DBs, so the {145.6} seed drift it was written to close is unclosed | Already imports scripts/lib/load-env + script-env (good citizen) | Keep. Flag JOB 2 as unfinished |
scripts/seed-goose-service-actor.ts (167 L) | (iii) | UNDECIDABLE | low | ID-71.26 G2 goose-pilot service actor. Zero references anywhere outside itself (only a seeded_by string literal at :125). Not in package.json, CI, or any runbook | — | Settle by asking: is the goose headless pilot still a live workstream? If no → RETIRE |
scripts/generate-entity-aliases-snapshot.ts (97 L) | (iv) | RETIRE | high | DR-121 §Decision. Verified independently: absent from package.json, all .github/workflows/**, deploy/. Output is gitignored (.gitignore:139) | canonicalisation.py:276-300 loader branch | Delete both (§0 items 4+5) |
scripts/generate-purge-path-inventory.ts (569 L) | (iv) | RETIRE | high | id-68 status: archived; {68.10} + {68.29} done | __tests__/scripts/generate-purge-path-inventory.test.ts; 4 corpus-manifest.json refs (L90/119/135/151) | Delete; drop the 4 manifest refs |
scripts/generate-taxonomy-snapshot.ts (199 L) | not seeding | KEEP | high | Misfiled by the brief. DR-121 §Context: taxonomy_snapshot.json is read by extraction.py:129 at module import, in production — a runtime validator source, not a test fixture. Wired via package.json sync:taxonomy | Its output moves to scripts/cocoindex_pipeline/data/ per DR-121, blocking id-416 | Keep. Execute the DR-121 move |
scripts/generate-classification-prompt-taxonomy.ts (395 L) | not seeding | CONSOLIDATE | medium | DB → lib/ai/taxonomy/canonical-taxonomy.generated.md. Wired via sync:taxonomy. Shares 4 jscpd clone pairs / ~95 lines with sync-plugin-taxonomy.ts | __tests__/scripts/generate-classification-prompt-taxonomy.test.ts | Merge with sync-plugin-taxonomy.ts (§5.5) — but Lane 1 owns whether the concept survives |
scripts/sync-plugin-taxonomy.ts (332 L) | not seeding | CONSOLIDATE | medium | Writes into .claude/plugins/knowledge-hub/1.0.0/skills/{classification,search-strategy}/SKILL.md. Wired via sync:plugin-taxonomy + sync:taxonomy. Owner: the knowledge-hub plugin “hasn’t been reviewed since pre-rename to canonical” | __tests__/mcp/plugin-taxonomy-consistency.test.ts (via test:private-docs) | Merge with the above; retire wholesale if Lane 1 retires the plugin’s classification skill |
scripts/generate-api-views.ts (707 L) | not seeding | KEEP | high | Misfiled by the brief. Postgres-catalog → migration codegen. CI-wired (api-view-coverage.yml:35); SURFACE_TABLES imported by check-api-view-coverage.ts:28 | — | Keep |
scripts/generate-skills-inline.ts (66 L) | not seeding | KEEP | high | package.json predev + prebuild + build:vercel | — | Keep |
scripts/generate-client-branding-map.ts (106 L) | not seeding | KEEP | high | predev + prebuild + build:vercel; consumed by lib/client-config.ts | — | Keep |
scripts/generate-content-type-values.ts (109 L) | not seeding | UNDECIDABLE | low | predev/prebuild-wired, so live. But its input is __tests__/fixtures/ontology/ontology-cv-baselines.json — a frozen parity fixture standing in for the real CV register, kept in lockstep by hand. It emits the closed content_type enum | __tests__/lib/ontology/markdown-parity.test.ts; lib/ontology/content-type-values.generated.ts | Lane 3 dependency. If the ontology CV register is restructured, this generator’s source disappears. Do not touch until Lane 3 reports |
tenant_config (table) | (ii) | KEEP | high | 4 consumers, all coherent: fetch-client-branding.ts:48, reseed-tenant-instance.ts:39, seed-tenant-from-bundle.ts:87, generate-api-views.ts:179 (dynamic-only, no api view). 0 rows on Platform staging — correct, Platform is NEXT_PUBLIC_CLIENT_ID=default | — | No action. This surface is clean |
3. Findings that contradict the owner’s framing
Section titled “3. Findings that contradict the owner’s framing”3.1 The owner is right about taxonomy — but the code already does the opposite, in two places
Section titled “3.1 The owner is right about taxonomy — but the code already does the opposite, in two places”The owner: “I don’t believe we would seed entity_aliases, taxonomy data, or canonicalisations to a client, as these would be client-specific.”
Both statements about what is shipped today are false; the should is unchallenged.
propagation/payload-contract.ts:78-106declarestaxonomy_domainsandtaxonomy_subtopicsas the FIRST TWO platform → client payload tables, with a fullfkRemaprule for the domain FK.client-app-deploy.md§7 documents this as the new-client step 9: “Platform-owned canonical knowledge (reference content, taxonomy, catalogue requirements) reaches the isolated client DB.” So the runbook — the bucket-(ii) authority — contradicts the owner directly.supabase/seed.sql§4d seeds 14entity_aliasesrows into every DB the seed runs against, andstaging-reference-refresh.sh:42pg_restores the table too.
Note what is not contradicted: canonicalisation_parity is not a table — it is
scripts/tests/fixtures/canonicalisation_parity.json, a cross-language parity case
table. DR-121 §Decision rules it a genuine test fixture that stays put. Nothing seeds
it anywhere. The owner’s instinct was right but the artefact is not a seed target.
Which half is stale? Applying GROUNDING §2’s read-never-written discriminator:
content_propagation_version has 0 rows on both Platform DBs, so no writer has
ever exercised the contract. There is no migrated writer that deliberately omits
taxonomy — there is no writer at all. The contract is a declaration that was never
run, not a live behaviour that outlived its model. That makes it cheap to correct: cut
taxonomy from the contract and rewrite client-app-deploy.md §7’s parenthetical.
3.2 The weekly reference refresh is a net-negative no-op — measured
Section titled “3.2 The weekly reference refresh is a net-negative no-op — measured”This is the strongest finding in the lane and it was not in the owner’s list.
staging-reference-refresh.sh runs weekly, DELETE FROMs six tables on Platform
staging, then pg_dump | pg_restores them from Platform prod.
| Table | seed.sql §4 seeds | Platform prod | Platform staging | Refresh contributes |
|---|---|---|---|---|
taxonomy_domains | 7 (all baseline) | 7 (all baseline) | 7 (all baseline) | 0 rows |
taxonomy_subtopics | 34 (all baseline) | 34 (all baseline) | 34 (all baseline) | 0 rows |
layer_vocabulary | 4 | 4 | 4 | 0 rows |
entity_aliases | 14 (core) | 14 (core) | 15 (14 core + 1 client) | 0 rows, and deletes 1 |
taxonomy_sync_state | 1 | 1 | 1 | 0 rows |
template_requirements | — | table does not exist | table does not exist | n/a |
Three compounding defects:
- Zero yield. Prod’s contents are byte-identical to what
seed.sql§4 already hardcodes. The job copies data that is already there. - Data loss. The
DELETEstep wipes staging rows prod does not have. Staging currently holds oneprovenance='client'entity_aliasesrow created 2026-08-03 12:36 UTC — after today’s 06:00 run. Next Monday it is gone.seed.sql§4’s own comment (“the staging-reference-refresh workflow still layers any client-provenance rows on top post-reset”) describes the exact opposite of what the script does. - A phantom table, two renames stale.
public.template_requirementswas renamed toform_template_requirements(pre-T2), then toform_requirement_templates(20260712062000_id145_w1c_rename_reshape.sql:115). The refresh script still names the original. It survives because theDELETEloop swallows errors (2>/dev/null || true) and the post-flight verification checks only four tables — not this one. The job has reported green every week (gh run list: 8/8 success) while silently skipping a sixth of its declared work.
The phantom name propagated into two more places: supabase/seed.sql:276 and
runbooks/staging-refresh.md §5 L138 + §7 L227 — the latter re-verified S491
(22/07/2026), ten days after the rename.
3.3 The shared harness the last audit asked for was built, then never adopted
Section titled “3.3 The shared harness the last audit asked for was built, then never adopted”docs/reports/jscpd-report/audit-scripts.md §D proposed four modules. All four now
exist — scripts/lib/load-env.ts, script-env.ts, batch-args.ts,
batch-runner.ts. Adoption:
| Module | Importers |
|---|---|
supabase-script-client.ts | 31 |
project-refs.ts | 17 |
load-env.ts | 3 (catalogue-standard-sq, catalogue-from-instance, seed-id145-w1f-exemplar) |
script-env.ts | 2 |
batch-args.ts | 1 |
batch-runner.ts | 1 |
Meanwhile grep -rl "function loadEnv" scripts/ = 15 copies and
"function assertEnvFlag" = 12 copies still in place. The extraction happened;
the deletion did not. This is textbook half-retirement — the debt this census exists
to clear — and it is the single cheapest win in the lane.
4. Duplication — jscpd over scripts/
Section titled “4. Duplication — jscpd over scripts/”npx jscpd scripts/ --pattern "**/*.{ts,py,sh}" --min-lines 12 --min-tokens 70
| Format | Files | Lines | Clones | Duplicated |
|---|---|---|---|---|
| typescript | 72 | 24,174 | 21 | 547 (2.26%) |
| python | 127 | 46,629 | 31 | 631 (1.35%) |
| Total | 199 | 70,803 | 52 | 1,178 (1.66%) |
The headline number understates the problem. 1.66% looks healthy, but jscpd only counts token-identical blocks ≥12 lines. It does not see the structural duplication — four scripts that each independently implement “resolve target DB, guard the ref, dry-run, upsert, report”. That is the collapse target, and it is invisible to jscpd.
Clone pairs inside this lane’s family (opened and verified by hand):
| Pair | Lines | What it is |
|---|---|---|
generate-classification-prompt-taxonomy.ts ↔ sync-plugin-taxonomy.ts | 30 + 26 + 22 + 17 = 95 | Four separate clones. Both are “fetch taxonomy from DB → render markdown into a tracked artefact”. ~24% of the smaller file. These are one script. |
generate-entity-aliases-snapshot.ts:26-55 ↔ generate-taxonomy-snapshot.ts:21-52 | 30 | 31% of the 97-line file. Moot — the former is being deleted (§0). |
seed-e2e-users.ts:96-135 ↔ verify-user-profiles-parity.ts:52-94 | 40 | loadEnv |
db-row-count-diff.ts:542-587 ↔ seed-procurement-test-data.ts:34-70 | 46 | loadEnv |
db-row-count-diff.ts:542-570 ↔ seed-e2e-users.ts:100-128 | 29 | loadEnv |
seed-e2e-users.ts:115-137 ↔ seed-procurement-test-data.ts:49-71 | 23 | loadEnv |
Four of the six pairs are the same loadEnv block — already extracted to
scripts/lib/load-env.ts and simply not adopted (§3.3).
knip --include files returned no unused files under scripts/. That is a
limitation, not a clean bill of health: the knip config treats scripts/** as entry
points, so nothing there can ever be reported unused. Do not read it as evidence.
5. The collapse proposal
Section titled “5. The collapse proposal”Today: 11 seed/propagate scripts + 8 generate- + 1 shell + 1 seed.sql = 21 files* across the surface. Target: 10.
5.1 Bucket (ii) — new-client deploy: 4 files → 3
Section titled “5.1 Bucket (ii) — new-client deploy: 4 files → 3”The most coherent part of the surface. client-app-deploy.md §6’s eight-step checklist
maps cleanly onto set-data-api-exposure.ts (step 2) → seed-tenant-from-bundle.ts
(step 4) → supabase seed buckets (step 5, a CLI, no script) → fetch-client-branding.ts
(step 7). Keep all four.
One change: fold reseed-tenant-instance.ts into seed-tenant-from-bundle.ts. The
split exists only because the library file’s CLI side-effect guard fires on import —
seed-tenant-from-bundle.ts:15 says so outright: “Filename deliberately avoids the
substring ‘reseed-tenant-instance’ so the imported module’s CLI side-effect guard does
not fire on import.” A file named to dodge its sibling’s process.argv check is a
design smell, not a module boundary. Merging removes the guard and one test file.
Step 9 (propagate-canonical-content.ts) is the one broken step — see 5.6.
5.2 Bucket (iii) — test data: seed-e2e-users.ts is three scripts
Section titled “5.2 Bucket (iii) — test data: seed-e2e-users.ts is three scripts”977 lines under a docblock that says “seeds three users”. Its actual exports:
provisionUser/findUserByEmail/verifyPipelineUserShape— the real job (~340 L)seedPublicationReviewFixture(:398) — ID-71 publication-review rowsseedTaxonomyGovernanceFixture(:496) — taxonomy-governance rows
The two fixture seeders are unrelated to auth provisioning; they landed here because
bun run seed:e2e-users was the hook CI already called. Split into
seed-e2e-users.ts (auth only) + seed-e2e-fixtures.ts (both fixtures), and have CI
call both. Do not do this until Lane 1 reports — if taxonomy governance retires,
seedTaxonomyGovernanceFixture and e2e/tests/settings-mutations.spec.ts go with it.
5.3 Bucket (i) — DB-reset: 3 files → 1
Section titled “5.3 Bucket (i) — DB-reset: 3 files → 1”supabase/seed.sql is the whole of bucket (i). Delete
staging-reference-refresh.sh + its workflow (§0). Delete
seed-platform-from-staging.ts + its test. Anything genuinely missing from
seed.sql §4 is an ON CONFLICT DO NOTHING block, not a script.
seed-platform-workspaces.ts + seed-platform-feed.ts should merge into ONE
seed-platform-pipeline-fixture.ts — feed strictly depends on workspaces
(seed-platform-feed.ts:135 fails loud without it), they share PLATFORM_TARGETS
and SeedDbClient, and neither has ever completed on either DB. Better still: if the
answer to “does Platform need 6 workspaces or 1?” is 1, both collapse into seed.sql
§4 and both files plus both tests are deleted.
5.4 The 15 loadEnv copies
Section titled “5.4 The 15 loadEnv copies”Not a rewrite — a codemod. scripts/lib/load-env.ts and script-env.ts already
exist and already have three adopters proving the shape works. Replace the 15 + 12
copies with imports. This alone removes the four largest clone pairs in the family
and ~400 lines.
5.5 The taxonomy artefact generators: 3 files → 1
Section titled “5.5 The taxonomy artefact generators: 3 files → 1”generate-taxonomy-snapshot.ts (199 L), generate-classification-prompt-taxonomy.ts
(395 L) and sync-plugin-taxonomy.ts (332 L) all do “read taxonomy from DB → write a
tracked artefact”, differing only in output format (JSON / markdown section /
plugin SKILL.md). 95 duplicated lines between the latter two. package.json
sync:taxonomy already chains all three plus build:plugin, which is the tell — it
is one operation split across three files. Collapse to one generator with three
emitters.
Gated on Lane 1. If the classification concept retires, the second and third emitters retire with it and only the snapshot generator survives (DR-121 makes it a production runtime asset, so it survives regardless).
5.6 The propagation worker — the one genuinely open question
Section titled “5.6 The propagation worker — the one genuinely open question”propagate-canonical-content.ts (676 L) + payload-contract.ts (155 L) + 3 test
files ≈ 1,200 lines implementing client-app-deploy.md §6 step 9. It has never run
(content_propagation_version = 0 on both Platform DBs). Of its 7 declared tables,
2 are taxonomy (owner says no), 1 is admittedly unimplementable, leaving 4.
Three options, in order of my preference:
- Trim to 4 tables (
layer_vocabulary,application_types,form_types,form_requirement_templates), delete the taxonomy andreference_itemsentries, fixclient-app-deploy.md§7. ~300 lines out, the mechanism survives for when a real client exists. - Retire entirely and make new-client canonical content a
seed.sqlinclude (\ir seed.<client>.sql— the runbook already contemplates this atstaging-refresh.md:290). ~1,200 lines out. Defensible given zero clients and zero runs, but throws away working, tested fan-out machinery. - Leave it. Not defensible — it currently encodes a model the owner has rejected.
Recommendation: option 1. The contract is a declaration nobody has executed, so correcting it is cheap and reversible; deleting 1,200 tested lines to save a hypothetical is not.
5.7 Net
Section titled “5.7 Net”| Before | After | |
|---|---|---|
| Files | 21 | 10 |
| Deleted outright | — | 8 scripts/workflows + 5 test files |
| Lines removed | — | ~2,400 (deletes) + ~400 (loadEnv codemod) |
6. Tests that die with a retired script
Section titled “6. Tests that die with a retired script”| Test file | Size | Dies with |
|---|---|---|
__tests__/scripts/generate-purge-path-inventory.test.ts | 8.2 KB | generate-purge-path-inventory.ts — unconditional (§0) |
__tests__/scripts/seed-platform-from-staging.test.ts | 11.7 KB | seed-platform-from-staging.ts |
__tests__/scripts/reseed-tenant-instance.test.ts | 6.4 KB | merged into the bundle CLI (§5.1) — assertions move, file goes |
__tests__/scripts/seed-platform-workspaces.test.ts | 10.1 KB | merged (§5.3) — check verify-platform-promotion-gate.test.ts:20 first, it imports PLATFORM_TARGETS from the script under test |
__tests__/scripts/seed-platform-feed.test.ts | 8.5 KB | merged (§5.3) |
__tests__/scripts/propagate-canonical-content.test.ts | 17.9 KB | survives under option 1; shrinks by the taxonomy + reference_items cases |
__tests__/scripts/propagation/payload-contract.test.ts | 3.3 KB | survives; loses 3 of 7 table assertions |
__tests__/scripts/generate-classification-prompt-taxonomy.test.ts | 3.2 KB | folds into the merged generator’s test (§5.5) — Lane 1 gated |
__tests__/mcp/plugin-taxonomy-consistency.test.ts | — | dies only if sync-plugin-taxonomy.ts retires — Lane 1 gated. Runs under test:private-docs, not the default suite |
__tests__/validation/taxonomy-consistency.test.ts | — | survives — asserts snapshot freshness, and DR-121 keeps the snapshot |
e2e/tests/settings-mutations.spec.ts | — | depends on seedTaxonomyGovernanceFixture — Lane 1 gated (§5.2) |
e2e/tests/review-publication-tab.spec.ts | — | depends on seedPublicationReviewFixture; survives the §5.2 split, retarget only |
Unconditional test deletions: 1. Conditional on decisions in this report: 4. Conditional on Lane 1: 3.
Non-test artefacts that must move in the same commit as their script:
docs/reference/testing/corpus-manifest.jsonL90/119/135/151 →generate-purge-path-inventory.tssupabase/seed.sql:272-289(§3 comment block) →staging-reference-refresh.shrunbooks/staging-refresh.md§5 L132-157, §7 L219-227 → samerunbooks/client-app-deploy.md§7 L382-411 → propagation contract rewrite.gitignore:139→generate-entity-aliases-snapshot.ts
7. Comment-to-code ratio — GROUNDING §1 flags
Section titled “7. Comment-to-code ratio — GROUNDING §1 flags”Files where the docblock argues for the file’s own existence at length:
| File | Docblock | Total | Note |
|---|---|---|---|
seed-platform-from-staging.ts | 45 / 251 (18%) | 251 | Includes a “WHY A WRAPPER AND NOT A RAW WORKER INVOCATION” section and a “WHAT IT DOES NOT DO” section. A 251-line file that spends 45 lines justifying being a wrapper is arguing with a reviewer who is not there. |
payload-contract.ts | ~90 / 155 (58%) | 155 | More comment than code. The taxonomy_subtopics entry carries a 20-line comment explaining why its stableKey cannot express its own identity; the reference_items entry carries a 14-line comment explaining that the FK cannot be resolved and is “Flagged for {95.13}; not resolvable in {95.11}” — a contract entry that documents its own unimplementability. Exactly the “forced to fit” shape GROUNDING §1 asks to be flagged. |
seed-id145-w1f-exemplar.ts | ~75 / 292 (26%) | 292 | JOB 2’s comment explains at length why the job is not done here and defers to catalogue-standard-sq.ts. Measured: form_requirement_templates = 0 rows on both DBs, so it is not done anywhere. |
canonicalisation.py:122-140 | 19 lines | — | DR-121 calls this out by name: “the ‘generated at deploy (PI-15)’ story is self-justification; the same comment concedes the wiring is a follow-up.” |
8. What I could not cover
Section titled “8. What I could not cover”scripts/mcp-eval/seed-data.tsandseed-fixtures.ts— inventoried and bucketed (iii), but not audited. They arelib/mcp/-scoped and that directory has its own CLAUDE.md and eval conventions I did not load.scripts/census/,scripts/ci/,scripts/codemods/— swept for seeding content; none found. Not otherwise examined.- Whether
seed.sql§4’s 7/34 taxonomy baseline is correct — I verified it is the sole live source and that the refresh workflow adds nothing. Whether those 7 domains and 34 subtopics should exist at all is Lane 1’s call, and it is the single biggest unknown hanging over this report: if Lane 1 retires the taxonomy tables, §5.5 collapses to one file,seed.sql§4a/§4b/§4e delete, and the §5.6 contract trim becomes moot. - Client staging/prod DBs — not queried. All measurements are Platform staging +
Platform prod. Per GROUNDING §1 client DBs hold no real data, but I did not verify
that;
seed-platform-from-staging.ts’s RETIRE verdict rests on the source concept being stale, not on the client DB’s contents. pg_dumpmulti--tbehaviour with one non-matching pattern — I did not run it. The conclusion thattemplate_requirementsis silently skipped rests on the workflow’s 8/8 green history plus the|| trueon the DELETE plus the post-flight check omitting that table. The table’s non-existence is verified directly; the precise failure mode is inferred.