Skip to content

S528 census — Lane 4: test debt on retired concepts

Lane 4 — tests that assert retired concepts, and skipped tests that should not be repointed

Section titled “Lane 4 — tests that assert retired concepts, and skipped tests that should not be repointed”

Census only. No file was edited. The integration suite was not run. Method: static analysis + targeted reading. Every line number below was opened by hand.

Frame: .user-scratch/s528-census/GROUNDING.md + .user-scratch/stale-codebase-concepts-and-context-rot.md. Target model established from okf-platform/corpus-reframe-review.html R1/R5 and reference/entity-glossary.md before any verdict was formed.

Verdict vocabulary (this lane’s four values, per the lane brief):

VerdictMeaning
DELETEthe test’s subject is retired — there is nothing to repoint it at
REWRITE-FROM-TARGET-MODELsubject is live, framing/naming encodes a retired concept
REPOINTsubject and framing both current — id-415’s scheduled work is correct
KEEPcorrect as-is; no action
UNDECIDABLEevidence insufficient — the settling evidence is named

Counts: DELETE 14 · REWRITE-FROM-TARGET-MODEL 21 · REPOINT 4 · KEEP 6 · UNDECIDABLE 3.


Before anything else, because every “framing” verdict below rests on these:

  • R5 (corpus-reframe-review.html:360): source_documents rows are the permanent provenance register: never deleted (tombstoned for GDPR erasure), meaningful even when bytes are discarded.” A source document is a register entry, a first-class permanent entity — not one half of a compound.
  • R1 (:336): L-raw is redefined as the source bindings + the permanent provenance register. The canonical layers are the client database (records) and the OKF bundle (concepts).
  • reference/entity-glossary.md:15: workspace = LEGACY tier (DR-038, S452), removed from the containment chain. The containment chain (:19) is tenant ⊃ application_type ⊃ activity ⊃ child records; q_a_pairs are corpus-level.
  • reference/entity-glossary.md:16: “‘bid’ is a form_type, not an application.”

“evidence pair” has NO entry in reference/entity-glossary.md and appears nowhere in the whole reference/ tree (grepped reference/ and reference/decisions/: zero hits). Per GROUNDING §2.4, a term that only ever appeared in a task spec is a drift risk, not vocabulary. It originates in the ID-75 TECH spec and has since propagated into production code (scripts/cocoindex_pipeline/flow.py:2656, app/api/ingest/url/route.ts:270,337, lib/source-documents/uploader-attribution.ts:50) and 12 test sites.

The owner’s ruling is correct and better-grounded than the code. A reference item is a first-class entity the same way a source document is. This is DR-104 trap #4 exactly: every identifier in url-landing-set binds a live table, and the concept is still retired.


These have no judgement content. Each is either (a) querying a column that does not exist, or (b) asserting parity with a mint that was ratified retired.

1.1 url-landing-set.integration.test.ts §5.4 — selects a DROPPED column

Section titled “1.1 url-landing-set.integration.test.ts §5.4 — selects a DROPPED column”
FieldValue
Target__tests__/integration/cocoindex/url-landing-set.integration.test.ts:271, :278, :284
VerdictDELETE (the whole it() block)
Confidencehigh
Evidencesupabase/migrations/20260706110000_id131_drops.sql:232ALTER TABLE "public"."feed_articles" DROP COLUMN IF EXISTS "content_item_id"; (STEP 4, ID-131 M6). No later migration re-adds it (feed_articles is touched only by 20260617130000_squash_baseline, …id112, …id115, …id129, …id131_drops, then view-regen files). The test issues .select('id, reference_item_id, content_item_id, passed') against the public table, not an api view.
Blast radiusThe it() block only. reference_item_id (squash_baseline.sql:8930/9656) survives — the backlink half of the assertion is real and should move into a renamed case.
Owner actionDelete lines 271–286; re-add the backlink assertion as it('backlinks every ledger row to the reference item') selecting id, reference_item_id, passed only.

This is a live nightly failure, not a latent one. cocoindex-nightly.yml:975-976 runs vitest run --config vitest.integration.config.ts __tests__/integration/cocoindex — the whole directory. The suite’s gate (:168 ENABLED = HAS_LIVE_DB && HAS_WALK_ENV) is satisfied there (COCOINDEX_STAGING_URL + PIPELINE_TRIGGER_SECRET are set at cocoindex-nightly.yml:342,360). PostgREST returns 42703 for the unknown column, so expect(error).toBeNull() at :280 fails. This is the only live-DB read of a dropped column anywhere in __tests__/integration/, e2e/ or scripts/tests/ — I grepped for it specifically.

1.2 The ci: uuid5 parity case — asserts a mint that was ratified retired

Section titled “1.2 The ci: uuid5 parity case — asserts a mint that was ratified retired”
FieldValue
Target__tests__/integration/cocoindex/url-landing-set.integration.test.ts:126-127 (ciIdFor), :145-148 (it('derives the ci: id'))
VerdictDELETE
Confidencehigh
EvidenceDR-034 / {127.25}: the ci: derived seed is RETIRED. scripts/cocoindex_pipeline/flow.py mints only sd: and ri: (:3961-3962, :2077-2078, :1314) — zero ci: seeds. scripts/tests/test_cocoindex_identity_core.py:293-295 states it verbatim: “the ci: (content_items) derived seed is RETIRED … the formula is dead code, not merely unused”.
Blast radiusTwo consts + one it(). The sd:/ri: derivation cases (:138-143) are load-bearing and stay.
Owner actionDelete ciIdFor and its it().

Why this matters more than its size: this case is in the file’s pure suite — no env gate — so it runs on every bun run test. It is permanently green against a hardcoded expected uuid, proving parity with a formula that no longer exists on either side. It is the purest example in the tree of a test that costs maintenance and buys nothing.

1.3 The vacuous ci: module-source guard (Python)

Section titled “1.3 The vacuous ci: module-source guard (Python)”
FieldValue
Targetscripts/tests/test_cocoindex_url_write_path.py:937-958
VerdictDELETE
Confidencehigh
EvidenceSame DR-034 / {127.25}. The test’s own comment at :948 says it “passes VACUOUSLY because there is no ci: seed left to derive from”. A guard that documents its own vacuity.
Blast radiusOne test fn.
Owner actionDelete the block. Reintroduction is impossible without a new CREATE TABLE, which is a louder signal than this guard.

1.4 The taxonomy snapshot freshness guard — a self-cancelling test

Section titled “1.4 The taxonomy snapshot freshness guard — a self-cancelling test”
FieldValue
Target__tests__/validation/taxonomy-consistency.test.ts:251-266
VerdictDELETE
Confidencehigh
EvidenceThe skip comment is the evidence: “SKIPPED (S435): the committed snapshot fixture is a maintenance artefact; the durable fix is regenerating it … deferred pending the id-131..135 taxonomy/OKF rework.” It asserts a fixture is <30 days old, was skipped because it isn’t, and the rework it defers to is the very thing this census is scoping.
Blast radiusOne it.skip.
Owner actionDelete lines 251–266 regardless of Lane 1’s ruling on the rest of the file.

1.5 plugin-taxonomy-consistency.test.ts — unreachable AND the owner has ruled the subject out

Section titled “1.5 plugin-taxonomy-consistency.test.ts — unreachable AND the owner has ruled the subject out”
FieldValue
Target__tests__/mcp/plugin-taxonomy-consistency.test.ts (whole file, 168 lines); gate at :50-51
VerdictDELETE
Confidencehigh
Evidence(i) RUN_PARITY = process.env.VITEST_PRIVATE_DOCS === '1' && PLUGIN_EXISTS && PROMPT_EXISTS. VITEST_PRIVATE_DOCS is set in exactly one place in the repo — package.json:32 (test:private-docs) — and no workflow under .github/workflows/ invokes it (grepped all 17). The file has never run in CI. (ii) Its subject is parity between .claude/plugins/knowledge-hub/1.0.0/skills/classification/SKILL.md and the private classification-prompt.md. Owner directive (feedback §“knowledge-hub plugin”): “hasn’t been reviewed/updated since pre-rename to canonical, and wouldn’t be a justification for retaining e.g., the taxonomy concepts in their current form.”
Blast radiusThe file; the test:private-docs script (package.json:32) loses one of its two targets; scripts/lib/taxonomy-parser.ts exports parsePluginTaxonomy / parsePluginDomainSlugs / parsePluginContentTypes which may become dead (check with knip).
Owner actionDelete the file. It is a never-run guard over a pre-rename plugin.

1.6 test_cocoindex_stage_5_crossrun_integration.py — gated on an env var set nowhere

Section titled “1.6 test_cocoindex_stage_5_crossrun_integration.py — gated on an env var set nowhere”
FieldValue
Targetscripts/tests/test_cocoindex_stage_5_crossrun_integration.py:54,63
VerdictUNDECIDABLE — see §6.3. Listed here only so the unreachability is on the record.
Confidencehigh on unreachability, low on disposition
Evidence_INTEGRATION_ENABLED = bool(os.getenv("KH_RUN_STAGE5_INTEGRATION")); pytestmark = pytest.mark.skipif(...). KH_RUN_STAGE5_INTEGRATION appears in no workflow, no package.json script, no shell script — only in its own two files. Never executed anywhere, by anyone, ever.
Owner actionDecide: wire it into pytest-nightly.yml with a DSN, or delete it. Do not leave it as-is.

2. content_items — the dropped table, still the vocabulary

Section titled “2. content_items — the dropped table, still the vocabulary”

content_items was DROPPED at ID-131 M6 (S450). The tests were retargeted at the row level and left un-renamed at the concept level. This is the single largest framing debt in the test tree.

2.1 op-id-stamping.integration.test.ts — the owner’s seed example

Section titled “2.1 op-id-stamping.integration.test.ts — the owner’s seed example”
FieldValue
Target__tests__/integration/cocoindex/op-id-stamping.integration.test.ts:12-20 (Inv-11 verbatim), :113 (case name), :133-138, :169-171
VerdictREWRITE-FROM-TARGET-MODEL
Confidencehigh
EvidenceThe subject (op_id stamped on every pipeline-produced row; op_id resolves to exactly one pipeline_runs row) is live — source_documents.op_id and q_a_extractions.op_id both exist, and id-400 HARNESS §4 keeps pipeline_runs telemetry by design (cited at :104-107). The framing is dead: the case is named 'content_items.op_id matches q_a_extractions.op_id…', the Inv-11 quotation at :12-20 opens “Every content_items row produced or updated by a cocoindex pipeline run…”, and the body already reads source_documents (:171-174).
Blast radiusThe case name; the two verbatim invariant quotations (which means specs/id-28-cocoindex-flow-scaffolding/PRODUCT.md Inv-11/Inv-12 need amending too — the test is faithfully quoting a stale spec); the local contentRow / seededContentIds identifiers.
Owner actionRename the case to 'source_documents.op_id matches q_a_extractions.op_id for rows from the same run'; restate Inv-11/Inv-12 in id-28 PRODUCT.md in source_documents terms; rename the locals. Do this in the same change as id-415’s fixture swap — see §5.

2.2 pollContentItemsFor — the retired name, 24 call sites

Section titled “2.2 pollContentItemsFor — the retired name, 24 call sites”
FieldValue
Target__tests__/integration/cocoindex/_helpers/fixture-staging.ts:190,248 (definition), :486 (contentIds field), :500-521 (the retirement note)
VerdictREWRITE-FROM-TARGET-MODEL
Confidencehigh
EvidenceThe helper’s own doc-comment (:17-23) says it: content_items was DROPPED at M6. pollContentItemsFor / dropFixture are retained under their existing names…”. It polls source_documents.filename (:230-231). dropFixture’s contentIds field is documented (:481-486) as “Named contentIds for caller-signature stability” — i.e. the name was knowingly kept to avoid churn. That decision predates this census; the census says take the churn.
Blast radius24 call sites across 23 integration test files (enumerated by grep for pollContentItemsFor). Plus test-helpers.ts:11,103, latency-budget.integration.test.ts:73, and every seededContentIds local in the suite.
Owner actionpollContentItemsForpollSourceDocumentsFor; contentIdssourceDocumentIds; seededContentIdsseededSourceDocumentIds. Use GitNexus rename (DR-071 — it is the rename authority here), not sed. Land it with id-415, which is already opening 16 of these files.

Why this is not cosmetic. The comment at fixture-staging.ts:500-521 is ~22 lines of prose explaining why a name no longer matches what the function does. Per GROUNDING §1, “a comment explaining why something was forced to fit is a finding in itself.” The rename deletes the comment.

2.3 content_items as a live API/response field name — 11 tests mirror it

Section titled “2.3 content_items as a live API/response field name — 11 tests mirror it”
FieldValue
Target__tests__/api/certifications.test.ts:263 · __tests__/api/guides.test.ts:412,414 · __tests__/hooks/use-entity-detail.test.ts:45,469,516,542 · __tests__/mcp/expiring-content.test.ts:99,136,144,152,182,196,214,227,260 · __tests__/components/certification-summary-card.test.tsx:44,69,89,506,531 · __tests__/components/date-extraction-ui.test.tsx:65,87,218 · __tests__/components/entity-management/entity-detail-panel.test.tsx:87,194 · __tests__/app/guide/guide-content.test.tsx:89 · __tests__/app/guide/guide-content-mobile.test.tsx:150 · __tests__/lib/validation/r-wp17-response-schemas.test.ts:301,316
VerdictREWRITE-FROM-TARGET-MODEL (blocked on the prod rename)
Confidencemedium — high that the vocabulary is retired, medium on what the replacement key should be
EvidenceThe key is live on 8 production surfaces: app/api/certifications/route.ts:27,39,49,83,94,103,303,324,334 · app/api/guides/[slug]/route.ts:87,110,116 · app/api/entities/[canonical_name]/route.ts:147 · lib/mcp/formatters/dashboard.ts:32,331-336 · components/dashboard/certification-summary-card.tsx:59,71 · components/dashboard/framework-summary-card.tsx:39,94-99 · components/guide/guide-section.tsx:31,103,137 · app/guide/[slug]/guide-content.tsx:55,270,336,380 · lib/validation/schemas.ts:2640. The payloads are real; the name is the dropped table’s. Note framework-summary-card.tsx:99 builds /documents/${...} from content_items[0].id — the id is a source_documents id wearing the old key.
Blast radius~9 production files + these 11 test files + lib/validation/schemas.ts:2640 (a Zod schema, so the rename is type-checked end to end).
Owner actionOne rename pass: content_itemssource_documents (or documents if you prefer the UI-facing word) across the response shapes, then the tests follow mechanically. Not urgent, but do not let a future task “repoint” one of these files without doing it.

2.4 Negative guards against a table that cannot come back

Section titled “2.4 Negative guards against a table that cannot come back”
FieldValue
Target__tests__/app/api/q-a-pairs/batch/route.test.ts:228,239 · __tests__/hooks/use-batch-create.test.ts:360,374 · __tests__/hooks/use-library-data.test.ts:98 · __tests__/lib/template-coverage.test.ts:493,572 · __tests__/lib/intelligence/pipeline.test.ts:571,707 · __tests__/supabase/migrations/id131-attention-counts-rewrite.test.ts:52,59
VerdictDELETE (the negative assertions only, not the host files)
Confidencemedium
EvidenceEach asserts some code path never calls .from('content_items') or never joins it. The table is gone from every environment (20260706110000_id131_drops.sql). Reintroducing it requires a new CREATE TABLE migration, which schema-parity and the migration review catch far earlier and louder than a mocked expect(mockFrom).not.toHaveBeenCalledWith('content_items').
Blast radius~6 assertions inside otherwise-live tests. id131-attention-counts-rewrite.test.ts may be wholly a migration-era guard — check whether anything else in it is live before deleting the file.
Owner actionStrip the never queries content_items assertions. Keep the host tests.
CaveatThis is the one place where I would accept a KEEP argument (ratchets are cheap). I am calling DELETE because GROUNDING §1 says half-retirement is the debt, and a ratchet against an impossible regression is exactly that. Flagging it as the softest verdict in the report.

3. “Evidence pair” / “half” — retired framing, live subject

Section titled “3. “Evidence pair” / “half” — retired framing, live subject”

3.1 The seed example — url-landing-set.integration.test.ts

Section titled “3.1 The seed example — url-landing-set.integration.test.ts”
FieldValue
Target__tests__/integration/cocoindex/url-landing-set.integration.test.ts:16 (This file asserts the EVIDENCE PAIR…), :191 (lands the source_documents half of the evidence pair), :212 (lands the reference_items half of the evidence pair), :264
VerdictREWRITE-FROM-TARGET-MODEL
Confidencehigh
Evidence”evidence pair” appears nowhere in reference/ — not the glossary, not the decision register, not reference/decisions/. R5 (corpus-reframe-review.html:360) makes source_documents the permanent provenance register, a first-class entity in its own right; R1 (:336) makes the client database (records) and the OKF bundle (concepts) the canonical layers. Neither ruling constructs a two-halves object. Owner ruling, S528: “a reference item is a first-class entity, the same way a source document is.” Every identifier in the file binds a live table — DR-104 trap #4.
Blast radiusTest framing: 4 sites in this file + _helpers/url-landing-seed.ts:7 + __tests__/api/ingest/url-reference.test.ts:4 + e2e/tests/content-ingestion-url.spec.ts:7,67,86,217 + scripts/tests/test_cocoindex_url_write_path.py:279,306 + scripts/tests/test_cocoindex_flow_failure_mode.py:2372. Production framing (out of my lane but load-bearing for the rename): scripts/cocoindex_pipeline/flow.py:2656, app/api/ingest/url/route.ts:270,337, lib/source-documents/uploader-attribution.ts:50.
Owner actionRename the two cases to 'lands the source_documents provenance register row (§5.1)' and 'lands the reference_items record (§5.2)'. Retire the phrase “evidence pair” repo-wide; the honest replacement for the transactional property is “both rows land in one transaction” — say that where atomicity is the point (e.g. content-ingestion-url.spec.ts:86), and say nothing where it isn’t.

What survives the rename, and it is most of the file. §5.1’s assertions (source_url = storage_path = normalisedUrl, populated filename/mime_type/file_size, extraction_method ∈ {trafilatura, docling}) are exactly R5’s register semantics. §5.2’s source_document_id = sdId is id-370 §5’s live FK. §5.5’s idempotency counts are real. This is a REWRITE, not a DELETE — but a rewrite whose §5.4 case must be deleted (§1.1) and whose ci: case must be deleted (§1.2).

3.2 The unreconciled conflict — flagged, NOT resolved

Section titled “3.2 The unreconciled conflict — flagged, NOT resolved”

This is the item the lane brief told me to report and not settle. I have not settled it.

FieldValue
Targeturl-landing-set.integration.test.ts:212-226 — specifically expect(ri.source_document_id).toBe(sdId) at :228
VerdictUNDECIDABLE
Confidencen/a

The two positions, stated exactly:

  • S507 row 4.2 marked this file’s reference_items assertions “not ratified”, on the expectation that reference_items.source_document_id would GO.
  • id-370 RESEARCH §5 (specs/id-370-unanswered-question-routing/RESEARCH.md:102-114, read in full) rules the FK live provenance, with four load-bearing facts:
    • schema: NOT NULL (squash_baseline.sql:7232), FK ON DELETE RESTRICT (:9921)
    • writer: reference_ingest() mints the sd row first, same transaction, explicitly for this FK (20260708160000_id139…:124-152 — the migration comment names it)
    • readers are increasing: reference_list(), app/reference/[id]/page.tsx:104-131, lib/query/fetchers.ts:264,295-296; and “id-392’s M6 retarget moved MORE reads onto reference_items — coupling is increasing”
    • verdict: live FK — provenance, not identity”
  • But id-370 §5 explicitly does not close the question it appears to close. It ends: “The real residual question (‘should a reference_item mint a synthetic 1:1 source_documents row at all’) is id-364 F1’s question, not id-370’s sweep.”

What is genuinely unreconciled: id-370 answered “is the FK live?” (yes). S507 was asking “should the sd row exist?” — which id-370 routed to id-364 F1 and nobody has answered. The two are not in contradiction; they are answering different questions, and the one S507 asked is still open. A verdict on :228 is therefore not available today.

What would settle it — one decision, not a measurement: an owner/DR ruling on id-364 F1: does a URL-ingested reference item mint a synthetic 1:1 source_documents row, or is a reference item’s provenance carried on the reference item itself? Note which way R5 leans without deciding: if source_documents is the permanent provenance register, a synthetic row per reference is the register working as designed, not residue. That is an argument, not a ruling — and I am not making it.

Consequence for id-415 and any repoint: do not touch :228 until id-364 F1 is ruled. It is the one assertion in the file whose disposition is genuinely unknown.


4. workspace as a scoping boundary in the cocoindex suite

Section titled “4. workspace as a scoping boundary in the cocoindex suite”

4.1 cross-workspace-isolation.integration.test.ts — the whole file

Section titled “4.1 cross-workspace-isolation.integration.test.ts — the whole file”
FieldValue
Target__tests__/integration/cocoindex/cross-workspace-isolation.integration.test.ts (whole file, 137 lines); framing at :1-2, :9-15, :90-91, :128-131
VerdictREWRITE-FROM-TARGET-MODEL — and once rewritten it is a duplicate; see the action
Confidencehigh on the framing; medium on the duplication
Evidence(i) entity-glossary.md:15: workspace is the LEGACY tier, removed from the containment chain (DR-038, S452); procurement_workspaces etc. were dropped in ID-145 W1. (ii) There is no workspace anywhere in this test’s mechanism — I read the whole file. W1 and W2 are two directory prefixes (inv-21-w1/, inv-21-w2/, :72,:79) and two markdown fixtures. The assertion chain is: distinct runs → distinct op_id (:112) → Stage-5 resolution is op_id-scoped (:132). (iii) The glossary’s real boundary is tenant = one DB per client (:19) — across which entity merge is impossible by construction, so the “no cross-tenant merge” clause in the header (:1) is not tested and cannot be tested from one database.
Blast radiusThe file. Its Inv-21 statement in specs/id-53-stage-5-entity-resolution/PRODUCT.md needs restating (it is quoted faithfully at :9-15).
Owner actionThe behaviour it actually proves — “Stage-5 UPDATEs only rows carrying the current run’s op_id” — is Inv-5, already covered by op-id-scoping.integration.test.ts (read :1-28: same mechanism, same fixtures pattern, stronger assertion — it snapshots run A’s canonical_name and re-reads it byte-identical after run B). Recommend: DELETE this file and keep op-id-scoping. Rewriting it produces a weaker copy of a test that already exists.

Confidence note. I am calling REWRITE in the table and recommending DELETE in the action because the duplication judgement rests on reading both files’ strategies, not on a ratified anchor. If the owner wants a distinct “two separate walks” case (vs op-id-scoping’s “two runs over one corpus”), rename it two-walk-op-id-isolation and drop every mention of workspace. Either way, “workspace” must go.

4.2 cross_workspace / workspace residue in other cocoindex tests

Section titled “4.2 cross_workspace / workspace residue in other cocoindex tests”

Grepped __tests__/integration/cocoindex/*.ts for workspace: the only hits are in cross-workspace-isolation.integration.test.ts. The rest of the suite is clean. Good news worth stating: the workspace retirement landed properly everywhere except this one file.


5. id-415 COLLISION LIST — scheduled repoints my verdicts change

Section titled “5. id-415 COLLISION LIST — scheduled repoints my verdicts change”

This is the section the lane exists to produce. id-415’s acceptance criteria (read in full from tasks/id-415.md) schedule a fixture repoint over the 16 CSP-staging tests plus sidecar-mime-coverage and cross-document-dedup. All 16 carry the id-412-authored PLANE MISMATCH — id-415's work list marker; I verified the marker and the import { FORM_TEMPLATE } line in each.

5.1 id-415 should NOT repoint these — the file or its case dies instead

Section titled “5.1 id-415 should NOT repoint these — the file or its case dies instead”
Fileid-415’s planMy verdictWhy
cross-workspace-isolation.integration.test.tsnot named, but carries no PLANE MISMATCH marker and is a Stage-5 sibling — in scope under “sweep the sibling Stage-5 files”DELETE (§4.1)Subject retired (workspace) + duplicates op-id-scoping. Repointing its fixture spends effort on a file that should not exist.
url-landing-set.integration.test.ts §5.4 (:271-286)referenced by id-415’s budget sweep (the file’s own :182-183 comment cites “the inverted-budget defect W6/id-415 is fixing elsewhere in this suite”)DELETE the case (§1.1)Selects a dropped column. Fixing its budget makes a broken assertion fail more reliably.
url-landing-set.integration.test.ts ci: case (:145-148)in-file, would survive a budget-only passDELETE (§1.2)Asserts a retired mint.
url-landing-set.integration.test.ts :228in-fileUNDECIDABLE — DO NOT TOUCH (§3.2)id-364 F1 is unruled.

5.2 id-415 SHOULD repoint these, but must rename in the same pass

Section titled “5.2 id-415 SHOULD repoint these, but must rename in the same pass”

Repointing the fixture without renaming leaves a test called content_items.op_id … pointed at a fresh corpus doc — the exact wasted-effort loop this census exists to end.

FileRepoint (id-415)Plus (Lane 4)
op-id-stamping.integration.test.tsFORM_TEMPLATE.cspChecklistXlsxCONTENT.sectorSpendXlsxrename case :113; restate Inv-11/12 (§2.1)
op-id-scoping.integration.test.tssamepollContentItemsFor rename (§2.2)
op-id-round-trip.integration.test.tssameditto
stage-5-attach-point.integration.test.tssameditto
stage-5-op-id-memo.integration.test.tssameditto
stage-5-row-counter.integration.test.tssameditto
stage-5-failure-non-destructive.integration.test.tssameditto
per-doc-canonicalisation.integration.test.tssameditto
pair-resolver-determinism.integration.test.tssameditto
context-snippet-populated.integration.test.tssameditto
unresolved-mention-retains-canonical.integration.test.tssameditto
legacy-alias-preload.integration.test.tssameditto
admin-merge-coexistence.integration.test.tssameditto
idempotency-memo-hit.integration.test.tssameditto
extract-contract-honour.integration.test.tssameditto

Verdict for all 15: REWRITE-FROM-TARGET-MODEL (= id-415’s repoint plus the rename).

5.3 One id-415 target where the subject IS classification — defer to Lane 1

Section titled “5.3 One id-415 target where the subject IS classification — defer to Lane 1”
Fileid-415’s planMy verdict
classify-content-coexistence.integration.test.tsrepoint fixtureUNDECIDABLE pending Lane 1

Its subject is Inv-8: “the classifyContent delete-before-insert path … INSERTs entity_mentions rows with NULL op_id … while a pipeline run is in flight, a classifyContent invocation on a DIFFERENT content_item completes successfully” (:9-14). Two retired concepts in one invariant: content_item, and classifyContent itself if Lane 1 retires the classification path. Its local is literally nullOpContentItemId (:71). If Lane 1 retires classification, this file is DELETE and id-415 should not touch it. If Lane 1 keeps it, it is REWRITE. Do not repoint it speculatively.

5.4 id-415 targets I confirm as clean REPOINT

Section titled “5.4 id-415 targets I confirm as clean REPOINT”
FileVerdictNote
sidecar-mime-coverage.integration.test.tsREPOINTSubject (per-MIME extraction → non-empty content_chunks) is live and correctly framed; id-392’s extracted_text retarget already landed (documented at :26-32). Its four fixtures are still hardcoded literals at :90,:96,:102,:108, three of them under form-templates/ — exactly id-415 AC-1. id-415’s work on this file stands, in full.
cross-document-dedup.integration.test.tsREPOINT (budget only)Already retargeted off the CSP form at S507 to entity-variants/*.md (:60-78) and imports nothing from _helpers/fixtures.ts. So id-415’s fixture claim here is largely spent; what remains is real: the budget inversion at :79 (beforeAll 60_000) vs :84 (afterAll 600_000) — I confirmed both lines. Minor framing residue: // Wait for BOTH content_items to land at :92.
extract-memoisation.integration.test.tsREPOINTNot in the 16; consumes pollContentItemsFor only. Rename-only.
stage5-canonical-name-freshness.integration.test.tsREPOINTSame.

5.5 id-392 / id-415 double-claim on sidecar-mime-coverage — no conflict left

Section titled “5.5 id-392 / id-415 double-claim on sidecar-mime-coverage — no conflict left”

id-415’s Notes say id-392’s AC-2 (content_chunks.content instead of source_documents.extracted_text) merged in PR #148 and that id-398 discharged AC-5. I verified AC-2 in the file (:26-32). The two tasks no longer collide on this file — id-392’s half is done, id-415 owns the fixture half. Nothing to arbitrate.


6. Skipped and never-run tests — the full inventory

Section titled “6. Skipped and never-run tests — the full inventory”

6.1 Never-activated scaffolds — describe.skip with a commented-out or prose-only setup

Section titled “6.1 Never-activated scaffolds — describe.skip with a commented-out or prose-only setup”

These are not “skipped tests”. They are test-shaped documents. Neither has ever executed.

FieldValue
Target__tests__/integration/cocoindex/nested-corpus.integration.test.ts (whole file, 145 lines) — :52-61 (the beforeAll is a commented-out // FUTURE: block), :77 (describe.skip), :141-145 (export const _NESTED_SUFFIX_REF — an export that exists only to silence an unused-const lint)
VerdictDELETE
Confidencemedium-high
EvidenceThe seed step was never written; the skip comment (:72-76) says so: “the beforeAll’s stageFixture call above is still commented out as FUTURE — no nested fixture ever lands.” The behaviour it wants (recursive walk) is already proven elsewhere: scripts/cocoindex_pipeline/flow.py:4291-4297 sets recursive=True with the gotcha named, and scripts/tests/test_file_branch_memo_fingerprint.py:238,345,349 exercises localfs.walk_dir(SRC, live=True, recursive=True) directly. Its Inv-5 quotation (:13) still says “confirm a content_items row is produced”.
Blast radiusThe file. specs/id-28-cocoindex-flow-scaffolding/PRODUCT.md Inv-5 should be marked covered-by-python or retired.
Owner actionDelete. If nested-corpus coverage is wanted at the integration tier, note that the real Platform corpus (scripts/cocoindex_pipeline/fixtures/platform-corpus/) is already nestedcontent/, qa/, edge/ — so a walk of it is a nested-corpus proof for free. Write that as one assertion in an existing walk test rather than reviving 145 lines.
FieldValue
Target__tests__/integration/cocoindex/extract-validation-failure.integration.test.ts:243-249 (describe.skip), and the whole describe body to end of file. :205-208 is the prose-only beforeAll.
VerdictDELETE (the skipped describe; :210-237’s afterAll goes with it)
Confidencemedium-high
EvidenceThe skip comment is explicit: “the beforeAll above is prose-only (Approach A/B harness deferred to 28.18) — observedOpIdRef.current is never assigned and no fixture is ever seeded, so all three cases fail in cascade (the third even sends the literal string "null" to PostgREST → 22P02).” The 28.18 failure-injection harness never landed (S258 → today). Case name at :309: 'no partial extraction rows written for the failed **content_items_id**' — retired vocabulary. Inv-22’s subject is covered: scripts/tests/test_cocoindex_flow_failure_mode.py (~2,400 lines of failure-mode coverage) plus persistent-failure-dlq.integration.test.ts.
Blast radiusThe file (check whether anything above :243 is a live non-skipped case before deleting the whole file — I read :195-330, which is all inside the scaffold).
Owner actionDelete the skipped describe and its afterAll. If an integration-tier Inv-22 proof is wanted later, it needs a failure-injection primitive that does not exist — mint that as a task, not as a permanently-red test body.
TargetVerdictWhy
legacy-mime-coverage.integration.test.ts:141-145it.skip('SKIPPED[no-legacy-adapter-route]: …'), empty bodyKEEPHonest, named, counted-by-the-census marker for a live open decision (legacy OLE adapter route; id-404 owns it per _helpers/fixtures.ts:131-134). The file’s non-skipped case above it is real and asserts containment.
lineage-ingest-once.integration.test.ts:135-138it.skip('SKIPPED[no-corpus-removal-primitive]: …'), empty bodyKEEPSame shape; blocked on a corpus-delete route the harness lacks (id-396/TECH.md:55-59).

One observation, not a verdict: both are empty bodies whose entire content is a TODO string. That is the task ledger’s job (ordna, ${KH_PRIVATE_DOCS_DIR}/tasks/id-N.md), not the test suite’s. They are cheap and the convention is deliberate, so I am not calling them stale — but if the owner wants zero test-shaped documentation, these are the two to cut, and the gaps should land as ledger rows instead.

6.3 Env-gated tests where the env is never set

Section titled “6.3 Env-gated tests where the env is never set”
TargetGateSet anywhere?Verdict
__tests__/mcp/plugin-taxonomy-consistency.test.ts:50-51VITEST_PRIVATE_DOCS=1package.json:32 only, no workflowDELETE — §1.5
__tests__/validation/taxonomy-consistency.test.ts:82 (describePromptParity)SNAPSHOT_EXISTS && PROMPT_EXISTS — both in-repo, so this does runn/asee §7 (Lane 1)
scripts/tests/test_cocoindex_stage_5_crossrun_integration.py:54,63KH_RUN_STAGE5_INTEGRATIONnowhere in the repoUNDECIDABLE
The ~40 __tests__/integration/cocoindex/* filesCOCOINDEX_* + live DBcocoindex-nightly.yml:342,360 only — integration-nightly.yml:136 explicitly excludes them (“COCOINDEX_ here — cocoindex suites stay skipped (128.3 scope)”*)KEEP the gate — correctly scoped

On test_cocoindex_stage_5_crossrun_integration.py: UNDECIDABLE because its subject (cross-run Stage-5 guard behaviour against a real Postgres) is live and non-trivial, and its sibling test_cocoindex_stage_5_crossrun_guard.py:5-7 explicitly exists as the unit half because this one never runs. Settling evidence: whether pytest-nightly.yml can be given a Postgres DSN. If yes → wire it and it becomes KEEP. If no → DELETE, because a test that has never run once has never proven anything.

6.4 Conditional skips that are correct — KEEP

Section titled “6.4 Conditional skips that are correct — KEEP”

Viewport-conditional Playwright skips are legitimate parameterisation, not debt. All verified as isMobileViewport(page) guards: e2e/tests/bid-export.spec.ts:32,58,87,123,170,222,266 · dashboard.spec.ts:412 · content-creation.spec.ts:180 · qa-library.spec.ts:715,746 · bid-pipeline.spec.ts:630 · bid-questions.spec.ts:297 · bid-session.spec.ts:167,195,227,243,263 · provenance.spec.ts:131 · provenance-audit-export.spec.ts:17. Verdict KEEP for all.

e2e/tests/settings-mutations.spec.ts:93,129 are comments recording removed silent conditional skips — i.e. a defect already fixed. KEEP.

6.5 Permanently-skipped tests with an empty body kept as documentation

Section titled “6.5 Permanently-skipped tests with an empty body kept as documentation”
TargetVerdictWhy
e2e/tests/publication-bulk-action.e2e.spec.ts:677-686test.skip(true, '…covered by the component test…') + a no-op test() bodyDELETEAn unconditional test.skip(true, …) whose reason is “this is a duplicate of the component test”. The reason is correct; the correct expression of it is deleting the test, not shipping an empty one plus a 9-line rationale comment (:668-676).
__tests__/scripts/codemods/wrap-define-route.test.ts:1868it.skip('second consecutive apply run produces no further modifications [TODO: PLAN §32.14 …]'), empty bodyDELETEDeferred to “Subtask 32.14” of id-32, a task well below the DR-106 ~130 waterline; the file’s own header (:1762-1764) says the sibling non-skipped case “covers the same contract at the discovery-loop level”. Self-declared duplicate of a live test, blocked on a subtask nobody is doing.

7. Taxonomy / classification test surface — sized, deferred to Lane 1

Section titled “7. Taxonomy / classification test surface — sized, deferred to Lane 1”

Boundary respected: Lane 1 owns whether the taxonomy/classification concept survives. I am not ruling on it. What I owe this census is the test-side blast radius, so the owner can price Lane 1’s ruling.

If Lane 1 retires classification, these die with it (7,276 lines, measured by wc -l):

FileLines
__tests__/lib/ai-classify-entities.test.ts1,366
__tests__/lib/queue/handlers/batch-reclassify.test.ts1,316
__tests__/integration/queue/batch-reclassify.integration.test.ts1,155
__tests__/lib/classify-two-pass.test.ts735
__tests__/lib/ai-classify-skill.test.ts536
__tests__/api/admin/batch-reclassify/route.test.ts527
__tests__/eval/classification-eval.test.ts347
__tests__/lib/topic-inference.test.ts296
__tests__/eval/entity-classification-eval.test.ts292
__tests__/validation/taxonomy-consistency.test.ts266
__tests__/lib/ai-classify-filter-canonicalise.test.ts215
__tests__/mcp/plugin-taxonomy-consistency.test.ts168
__tests__/lib/ai-classify-subtopic-coercion.test.ts57

Plus __tests__/lib/taxonomy/sync-trigger.test.ts and the taxonomy-field fixtures scattered across ~40 further test files (grep for primary_domain|primary_subtopic|classification_confidence).

One I will rule on now, independent of Lane 1:

FieldValue
Target__tests__/lib/ai-classify-subtopic-coercion.test.ts (whole file, 57 lines)
VerdictDELETE
Confidencehigh
EvidenceEvery doc it cites is gone. Header :18-21 cites docs/specs/classifycontent-subtopic-contract-spec.md, docs/audits/si-classification-verification-s156.md, docs/reference/product-roadmap.md §2.1.11all three resolve nowhere, neither in the in-repo docs/ (which contains only reference/, reports/, extend-registry-provenance.md) nor in the docs-site (checked). Its subject (:5-10) is “two content_items rows … with primary_subtopic = '' — a table that no longer exists. Its one-off cleanup migration (20260409164245_backfill_empty_subtopics_to_null.sql) ran in April. Its fixture value is 'school-funding' (:47,:51) — an IMS/sector-intelligence-era subtopic.
Blast radiusThe file. coerceSubtopic in lib/ai/classify.ts keeps whatever coverage classify-two-pass.test.ts gives it; check with knip whether the export survives Lane 1.
Owner actionDelete. This is the canonical specimen of GROUNDING §1’s “forced to fit” artefact: a 57-line regression guard for an S159 empty-string defect on a dropped table, citing three dead documents.

Two coverage tests that die with coverage_targets (DR-034):

TargetVerdictConfidenceEvidence
__tests__/mcp/mcp-app-trigger-tools.test.ts:362-368 (mocks a coverage_targets query returning [])DELETE (assertion + mock arm)mediumDR-034: “the content_items-era coverage feature is RETIRED, not re-pointed.” GROUNDING §3: coverage_targets has 0 rows. Live consumer is lib/mcp/tools/apps.ts:302 — that code is Lane 1/2’s to retire; the mock arm dies with it.
__tests__/scripts/export-user-data.test.ts:401 (coverage_targets in EXPECTED_ATTRIBUTED_CONTENT_TABLES)DELETE (that entry)mediumSame. Live consumer scripts/export-user-data.ts:543,825,844. Note the same list at :403 contains workspaces — legacy tier per the glossary — so this expectation array carries two retired entries.

e2e/tests/coverage-page.spec.tsUNDECIDABLE. Its header (:5-18) claims the DR-034 retirement left /coverage rendering “the single surviving template-completion view directly” with “no tab shell”. The code disagrees: app/coverage/page.tsx:2 still imports and renders CoveragePageTabs from ./coverage-tabs, and e2e/tests/guide-pages.spec.ts:140 calls the tab param “UI-inert post-DR-034”. So either the retirement is incomplete or the comment is stale — I could not tell which from static reading, and the surface is Lane 1/2’s. Settling evidence: open app/coverage/coverage-tabs.tsx and determine whether it renders more than one tab. The test itself (a heading + subtitle smoke check) is harmless either way.


8. Cross-cutting observation: dead citations in test headers

Section titled “8. Cross-cutting observation: dead citations in test headers”

Not a per-file verdict, but a systemic finding the owner should see, because it is how context rot enters the test tree.

Test file headers cite specs as authority. Four cited paths resolve nowhere (checked against both the in-repo docs/ and ${KH_PRIVATE_DOCS_DIR}/src/content/docs/):

Cited pathCited at
docs/plans/phase-0-investigation/architecture/02-data-flow.md §5.1op-id-stamping.integration.test.ts:38-39
docs/specs/classifycontent-subtopic-contract-spec.mdai-classify-subtopic-coercion.test.ts:19
docs/audits/si-classification-verification-s156.mdai-classify-subtopic-coercion.test.ts:20
docs/reference/product-roadmap.md §2.1.11ai-classify-subtopic-coercion.test.ts:21

The first is doubly bad: phase-0-investigation/** is a DR-106 presumed-STALE family, so even had it resolved it could not be cited as authority. A test header citing a stale doc is the same error as citing code (DR-106), and it is the mechanism by which a reader “confirms” a retired invariant is ratified.

Owner action: when the id-28 Inv-11/Inv-12 restatement lands (§2.1), drop the 02-data-flow.md reference rather than repointing it.


Stated plainly so this does not read as full coverage.

  1. I did not execute anything. No vitest, no pytest, no integration suite (per the brief). Every “this would fail” claim is derived from schema + workflow reading, and I name the migration line for each. The url-landing-set:278 breakage (§1.1) is the one I am most confident of and the one worth confirming first on the next nightly.
  2. scripts/tests/ got a vocabulary sweep, not a file-by-file audit. It is ~60 Python files. I swept for content_items / qa_sidecar / evidence pair / ci: / coverage_targets / skip markers and read the hits. I did not assess whether each Python test’s subject is current. Given test_cocoindex_flow_failure_mode.py alone is ~2,400 lines, that is a lane of its own.
  3. e2e bid-* filenames — flagged, not verdicted. Six files (bid-draft-all, bid-draft-stream, bid-export, bid-pipeline, bid-questions, bid-session) are named for a concept the glossary demotes (“‘bid’ is a form_type, not an application”entity-glossary.md:16) while their describe blocks already say “Procurement” (bid-pipeline.spec.ts:623, bid-questions.spec.ts:290). A rename is probably right; I did not read all six bodies, so I am not issuing a verdict on a file I have not opened.
  4. __tests__/validation/no-bid-regression-guard.test.ts — I read it in full and it is a finding, but its disposition needs an owner call. It enforces the S248 rename bid_workspaces → procurement_workspaces (:62-68) and bans bare project_id in favour of workspace_id (:120-141). Both rename targets have since been dropped: procurement_workspaces and form_questions.workspace_id went in ID-145 W1 (glossary :15-16). Its failure message (:115, :139) instructs a future developer to “rename to workspace_id — advice that would reintroduce a dropped column. It also cites specs/id-31-…/TECH.md, a sub-130 spec (DR-106). Verdict REWRITE-FROM-TARGET-MODEL, confidence medium — the guard’s purpose (don’t regress the umbrella rename) may still be worth something, but its targets and its remediation advice are both stale. I flag rather than call DELETE because I have not established whether any live code could regress toward BID_STATES.
  5. The content_items-as-payload-key rename (§2.3) is scoped, not designed. I named the ~9 production files but did not choose the replacement key. That is a product-naming call.
  6. e2e/global-teardown.ts, e2e/helpers/data-factory.ts, e2e/fixtures/test-data*.ts all reference content_items, but these are seeding surfaces — Lane 2’s boundary. I left them alone deliberately; note that they will appear in Lane 2’s report and the verdicts should be reconciled.

10. Anything that contradicted the owner’s framing

Section titled “10. Anything that contradicted the owner’s framing”

Honesty check, per GROUNDING §“a finding that contradicts them and IS well-evidenced is exactly what we want.”

  • Nothing contradicted the owner’s two seed rulings. Both were confirmed and one was stronger than stated: url-landing-set is not merely mis-framed, it queries a dropped column and would fail on the next nightly.
  • One partial qualification on “many skipped tests certainly aren’t required in their current form”: it is true, but the count is smaller than it looks. Of ~60 skip sites, the large majority (§6.4) are legitimate viewport parameterisation. The real skip debt is six items: two never-activated scaffolds (§6.1), two unreachable env gates (§1.5, §6.3), and two empty documentation-tests (§6.5). The bigger debt is not in skipped tests at all — it is in the ~21 running tests whose framing is retired (§2, §3, §4).
  • One thing I expected to find and did not: qa_sidecar (DR-086a) is cleanly retired from the test tree. Every hit (test_cocoindex_flow_fork_routing.py:11,23,24,29, test_cocoindex_flow_live_ingest.py:168, test_cocoindex_flow_failure_mode.py:1303) is a retirement note describing what was deleted, not a live assertion. Worth stating because id-370 §6 flags “Q&A sidecar residue NOT swept for specifically — treat ‘no sidecar code found’ as unverified, not clean.” For the test tree specifically, it is now swept and it is clean. One residue: __tests__/lib/q-a-pairs/promote-corpus.test.ts:7,1368 cites specs/id-59-…/TECH-qa-sidecar-canonical.md — a stale citation on a live test, same class as §8.
  • extracted_text (id-392) is further along than the brief implied. Every hit in the test tree is a “legacy — permanently NULL on the pipeline path” note, not a live read. The retarget landed. No verdicts needed.