Skip to content

Phase 0.7.5 — Knip config validation: corrected baseline proposal

Phase 0.7.5 — Knip config validation: corrected baseline proposal

Section titled “Phase 0.7.5 — Knip config validation: corrected baseline proposal”

Audit date: 2026-05-07 Branch: content-items-investigation knip version: ^6.3.0 (per package.json:139) Config file: knip.config.ts (105 lines, last modified 5 May 2026) Baseline file: .knip-baseline.json (counts-only: exports=41, types=15, unlisted=3) Read-only: no config file changes in this run; corrected baseline proposed in §6. Predecessors: 0.3 knip-revisit (moderate scope, classified 21 GENUINE-BUILD-NOT-WIRED + 17 LEGACY-SCAFFOLD + 9 INTENTIONAL-RE-EXPORT).


The current knip configuration relies on TWO suppression mechanisms: the tags: ['-public'] JSDoc rule (236 marked exports across 152 files) and the .knip-baseline.json counts-only ceiling (41 exports + 15 types + 3 unlisted). Together they hide ~285 findings.

A no-suppression audit (mechanically classified 229 @public exports for actual import + same-file usage) shows the tags: ['-public'] suppression is 75% justified — 209 exports are INTERNAL-CONTRACT (used as parameter/return types in same file but never imported by name from outside; this is exactly the legitimate “stable signature” use-case knip docs endorse). The remaining 25% splits as 8 CONSUMED (imports do exist; correct that these aren’t flagged) and 11 DRIFT — true positives where the @public tag now hides genuinely dead code that was once a contract. The baseline-tolerated 41+15 raw counts include the 9 queue-handler authoring contracts (justified by §5.4 dispatch.ts ownership pattern, recommend migrating to @public for clarity) plus 21 GENUINE findings already documented in 0.3.

Verdict: the config is over-aggressive but only mildly so. It hides 11–13 true positives that should surface as backlog tickets, and it’s structurally correct in protecting the ~209 legitimate type contracts. The biggest improvement opportunity is moving the 9 queue-handler types into the @public tag system (rather than absorbing via baseline counts) so that the baseline can drop to types=4-6 and any new unused-handler-type regression fails CI immediately. None of the suppressed items rise to a pre-launch fix; canonical-pipeline collapse (0.7.1/0.7.3) would resurrect roughly half of the 11 drift findings if the unused EP2 schemas are repurposed for the canonical core.

Overall confidence: 88%. Below 90% because three findings (PatternCluster, PromptRecommendation, FileUploadState) hinge on whether intelligence flag-analyser or hooks/use-file-upload-pipeline have planned-future consumers we have not surfaced, and because the --tags=-@public / --tags=+@public CLI overrides did not behave as documented (knip 6.3.x bug or flag-format mismatch — fell back to manual classification of the 236 sites).


knip.config.ts defines six suppression categories. They are unchanged since 0.3 audited them (5 May 2026). Recap of correctness verdict (full table at 0.3 §“summary”):

CategoryLinesVerdict (0.3)Re-confirmed (0.7.5)
entry allowlist4–32JustifiedYes
project glob33–45JustifiedYes
ignore paths46–59JustifiedYes
ignoreDependencies (9 entries)60–70JustifiedYes
tags: ['-public']79Justified, requires auditRe-audited in §4 below — 75% justified, 11 DRIFT findings + 2 likely-DRIFT
syncCompilers.css87–94JustifiedYes

The .knip-baseline.json counts-only mechanism (separate from knip.config.ts) is the OTHER suppression channel:

{
"counts": { "exports": 41, "types": 15, "unlisted": 3 }
}

This permits 41 exports + 15 types + 3 unlisted before CI fails (scripts/check-knip-baseline.ts).

Suppression channel summary:

  1. tags: ['-public'] — silences 236 individually-marked exports (152 files). ZERO appear in knip output.
  2. .knip-baseline.json counts — permits 41+15+3=59 unmarked findings to remain. These DO appear in knip output but don’t fail CI.

Total currently-hidden findings: 236 + 59 = ~295.


3. Baseline knip output stats (current state, suppressions in place)

Section titled “3. Baseline knip output stats (current state, suppressions in place)”

Captured via bun run knip --no-config-hints on commit 830cf6ad:

BucketCurrentBaseline ceilingDelta vs ceiling
Unused dependencies000
Unused devDependencies000
Unlisted dependencies330
Unused exports41410
Unused exported types15150
Unused files000
Duplicates000
Binaries000
Enum members000
Unresolved000

At-baseline. Header total: “Unused exports (41)” + “Unused exported types (15)” + “Unlisted dependencies (3)” = 59 findings reported. CI passes.

This is identical to the 0.3 audit baseline — no drift since S227 cross-track merge (.knip-baseline.json capturedAt: 2026-05-06).


4. No-suppression audit: classifying every currently-hidden item

Section titled “4. No-suppression audit: classifying every currently-hidden item”

grep -rn "@public" --include="*.ts" --include="*.tsx" lib components hooks types contexts app returns 236 hits across 152 files. Distribution by top-level dir:

  • lib/ — 152 (66 files)
  • components/ — 52 (52 files)
  • hooks/ — 32 (32 files)
  • app/ — 2 (2 files)

Distribution by export kind: 192 interfaces, 30 types, 6 consts, 0 functions/classes.

Methodology (script at /tmp/claude/check-imports3.sh): for each @public-tagged export, count (a) imports in production code outside the source file, (b) imports in __tests__/, (c) same-file occurrences minus 1 (= internal usages as parameter/return types).

Result categories (228 valid rows after parser deduplication; one extracted name was a duplicate from a multi-export export {} clause):

CategoryCountMeans
CONSUMED8At least one import exists outside source file. Tag protects a legitimately-imported type knip cannot resolve via dependency graph (most common: barrel-style export type {...} followed by import-at-use-site).
INTERNAL-CONTRACT209Used in own file as function parameter/return type. The exported NAME is dead-imported, but the function signature using it IS consumed. This is the canonical “stable signature” use-case that knip docs explicitly endorse for tags: ['-public'].
DRIFT110 imports + 0 internal uses. The @public tag was added once when the contract was authored but no consumer ever materialised, OR the consumer was deleted and the tag was not.

Drift list (11 items — see §4.2 below for analysis):

#NameKindFileInternal note
D-1PatternClustertypelib/intelligence/flag-analyser.ts:71z.infer<typeof PatternClusterSchema>. Sister PatternClusterSchema is also unused (visible in raw knip output as “Unused exports”) — both never wired.
D-2PromptRecommendationtypelib/intelligence/flag-analyser.ts:85Same pattern as D-1.
D-3BatchOptionstypelib/ingest/markdown-batch-schema.ts:73z.infer<typeof BatchOptionsSchema>. Schema IS imported (route.ts:260 calls parseBody(BatchOptionsSchema)); type name is dead. Ambiguous — Phase 0.2.5 B-1/B-2 already flagged the underlying auto_supersede and tag fields as parsed-but-unused.
D-4PerFileOverridetypelib/ingest/markdown-batch-schema.ts:75Same pattern as D-3.
D-5BatchWideOptionstypelib/ingest/markdown-batch-schema.ts:77Same pattern as D-3.
D-6LayerKeytypelib/client-config.ts:193(typeof CLIENT_CONFIG.layer_vocabulary)[number]['key']. Underlying CLIENT_CONFIG IS imported widely; the keyed-type alias is dead.
D-7TrackedReferenceDoctypelib/docs/tracked-reference-docs.ts:29(typeof TRACKED_REFERENCE_DOCS)[number]. Const IS imported by __tests__/docs/reference-doc-edit-coupled-freshness.test.ts:19; type alias is dead.
D-8DedupSupersedeResponseinterfacelib/query/fetchers.ts:529Authored as response shape for POST /api/admin/content-dedup/[id]/supersede. Caller (components/admin/content-dedup/content-dedup-action-buttons.tsx:114) uses untyped mutationFetchJson(). Contract was specified at §1.7 admin-dedup-supersede-fix-spec.md §2.9 but never adopted at the consumer.
D-9VALID_SORT_FIELDSconstlib/validation/schemas.ts:69Declared but no caller; SISTER VALID_REVIEW_STATUSES/VALID_DIGEST_TYPES/VALID_REVIEW_QUEUE_SORTS/TAG_MORPHOLOGY_DECISION_VALUES are correctly used in z.enum(...) calls. Drift detected only on the _SORT_* pair.
D-10VALID_SORT_ORDERSconstlib/validation/schemas.ts:76Same as D-9.
D-11IngestUrlBodytypelib/validation/ingest-schemas.ts:25z.infer<typeof IngestUrlBodySchema>. Schema IS imported by app/api/ingest/url/route.ts:12; type alias is dead.

Per the user’s four-bucket framework:

#ItemClassRationaleCross-ref to canonical-pipeline (0.7.1/0.7.3)
D-1PatternClusterTRUE-POSITIVE-DEFERREDSister PatternClusterSchema is also unused (in raw knip output). Authored for lib/intelligence/flag-analyser.ts but the analyser never composes the cluster type into a public surface. The DEFERRED status is because intelligence flag-analyser has unfinished spec work (per file comments + tests). Action: backlog ticket “blocked by intelligence-pipeline §1.18 productionisation”.OUT-OF-SCOPE for canonical pipeline. P9 RSS is explicitly excluded from collapse (0.7.1 §1). No effect either way.
D-2PromptRecommendationTRUE-POSITIVE-DEFERREDSame pattern as D-1.Same as D-1.
D-3BatchOptionsDRIFTThe schema IS used; the name alias was authored as a TS-side contract but never adopted. Pure naming-hygiene.If P8 absorbs P6 (0.7.3 §3), the BatchOptions wire shape becomes the canonical document-orchestrator config. The TYPE alias would gain genuine consumers. Conditional on canonical work.
D-4PerFileOverrideDRIFTSame as D-3.Conditional on canonical work — if orchestrateDocumentBatch accepts per-file overrides as a public API, type would be revived.
D-5BatchWideOptionsDRIFT (FROM 0.2.5 B-1/B-2)This schema also defines the auto_supersede and tag fields that 0.2.5 B-1/B-2 flagged as parsed-but-unused. The export is dead AND it carries dead fields. Mixed concern.Conditional. If 0.2.5 fixes wire auto_supersede to the orchestrator, the type and schema get real consumers. If they delete the fields, the type stays dead.
D-6LayerKeyINTENTIONAL-FALSE-POSITIVEThe type alias (typeof CLIENT_CONFIG.layer_vocabulary)[number]['key'] produces a keyed-string union. It’s authored as a stable type contract for any future layer-aware code. The fact that the const itself is widely imported AND the type alias was authored alongside means it’s prophylactic typing. Keep suppression, ADD comment in config explaining “type aliases over consumed const may have no name-imports”.No effect.
D-7TrackedReferenceDocINTENTIONAL-FALSE-POSITIVESame as D-6 — keyed-string-literal union over a consumed const.No effect.
D-8DedupSupersedeResponseTRUE-POSITIVE-FIX-NOWSpec §1.7 §2.9 specifies this exact response shape; the callsite (content-dedup-action-buttons.tsx:114) uses untyped fetch. Fixing it brings the contract to the consumer (1-line mutationFetchJson<DedupSupersedeResponse>(...)). Pre-launch quality concern: untyped admin-fetch surface is class-of-bug-for-rename.OUT-OF-SCOPE for canonical pipeline; admin dedup is its own surface.
D-9VALID_SORT_FIELDSTRUE-POSITIVE-FIX-NOWThe 6 VALID_* consts in lib/validation/schemas.ts are siblings; 4 of 6 are correctly consumed by z.enum(...) declarations. The pair _SORT_FIELDS and _SORT_ORDERS are not. Likely either (a) the sort schemas they were authored for were deleted but the const wasn’t, or (b) the sort schema was authored in a sibling file but never wired. Action: delete or wire.OUT-OF-SCOPE.
D-10VALID_SORT_ORDERSTRUE-POSITIVE-FIX-NOWSame as D-9.Same.
D-11IngestUrlBodyDRIFTSchema IS imported by route.ts. Type alias is dead. Pure naming-hygiene.Canonical-pipeline relevant — if URL paths P1↔P4 unify (0.7.1 §1), the IngestUrlBody shape becomes the input contract for the unified URL kernel. The alias would have genuine consumers.

4.3 The 8 CONSUMED items (false-positive classification check)

Section titled “4.3 The 8 CONSUMED items (false-positive classification check)”

Quick verification that these eight are correctly suppressed:

ItemFileVerdict
LayerDefinitionlib/client-config.ts:32Correctly imported. False positive without tag → suppression justified.
BelowThresholdItemlib/mcp/formatters/briefing.ts:16Re-imported by lib/mcp/formatters/index.ts:117 (visible in raw output) — barrel re-export pattern. Suppression justified at the source; barrel re-export shows in raw “Unused exports” though.
ScoreDropItemlib/mcp/formatters/briefing.ts:28Same as BelowThresholdItem.
FreshnessTransitionItemlib/mcp/formatters/briefing.ts:37Same.
QualityFlagNotificationlib/mcp/formatters/briefing.ts:46Same.
CoverageAlertNotificationlib/mcp/formatters/briefing.ts:54Same.
CertificationWarninglib/mcp/formatters/briefing.ts:61Same.
Workspacecomponents/item-detail/qa-provenance-sections.tsx:5Imported by 6 prod files + 1 test. Suppression justified.

The mcp/formatters/briefing types form a barrel-re-export pair (briefing.tsindex.ts); the @public tag at SOURCE means the SOURCE is fine, but the BARREL re-export at index.ts:117–123 is NOT @public-tagged and SHOWS up in raw knip output as “Unused exports” / “Unused exported types”. This pair is captured in 0.3 as G-21 (barrel-export hygiene).

4.4 The 41+15 raw findings tolerated by .knip-baseline.json

Section titled “4.4 The 41+15 raw findings tolerated by .knip-baseline.json”

Cross-references against 0.3 classifications. None has changed since 5 May 2026:

0.3 classCountItems
GENUINE-BUILD-NOT-WIRED21G-1..G-21 in 0.3 §“Findings classified” — barrel hygiene + sister-helper drift + test-coverage drift. G-6 batch-reclassify P1.
INTENTIONAL-RE-EXPORT (queue-handler authoring contracts)9EnqueueQueueJobArgs/Result, BatchReclassifyResult/AuthContext, BidDraftAllQuestionResult/Result/AuthContext, MarkdownBatchResult/AuthContext.
LEGACY-SCAFFOLD (shadcn)17shadcn/ui re-exports + 1 logger barrel.
Unlisted-dep3@tiptap/core (transitive), node) (parser glitch), pdfjs-dist/build/pdf.worker.min.mjs (transitive).

0.3 findings are directionally still correct, with two refinements:

  1. 0.3 did not separately audit the 236 @public-tagged sites. It documented the suppression mechanism’s correctness in principle but did not iterate every tag. This audit (§4.1–4.2) extends 0.3 by surfacing the 11 DRIFT items hidden behind @public.
  2. 0.3 §“Open question 1” (Phase 0.2.5 Pattern C/D errata) stands — Pass 2 entity validation IS reachable via scripts/backfill-classify-content-items.ts:402. Not a knip finding either way.

Beyond the 11 DRIFT, 0.3’s 21 GENUINE findings hold. Combined with this audit, the ledger is:

SourceTRUE-POSITIVE-FIX-NOWTRUE-POSITIVE-DEFERREDINTENTIONAL-FALSE-POSITIVEDRIFT
0.3 (baseline-tolerated raw findings)1 (G-6)14 (G-3..G-21 minus G-6)6 (G-1, G-2 schema patterns + 4 cross-cutting)0
0.7.5 (newly @public-suppressed)3 (D-8, D-9, D-10)2 (D-1, D-2)2 (D-6, D-7)4 (D-3, D-4, D-5, D-11)
Combined41684

The 4 TRUE-POSITIVE-FIX-NOW items: G-6 (test-coverage drift on batch-reclassify); D-8 (admin dedup response untyped); D-9, D-10 (orphaned VALID_SORT_ consts).*


5. Cross-reference: canonical-pipeline collapse

Section titled “5. Cross-reference: canonical-pipeline collapse”

The 0.7.1/0.7.3 reframe identifies 4-5 “canonical” kernels (URL core + document core + 3 overlays). Three of the 11 DRIFT items would change classification under canonical-pipeline collapse:

DRIFT itemTodayPost-canonical-pipeline (P1↔P4 + P6→P8 + P5/P10 absorption)Action
D-3 BatchOptionsDRIFTCONSUMED — becomes orchestrator-config type for orchestrateDocumentBatch.Wait for 0.7.3-implementation; will self-resolve.
D-4 PerFileOverrideDRIFTCONSUMED — becomes per-file override type for canonical-document core.Same as D-3.
D-11 IngestUrlBodyDRIFTCONSUMED — input contract for unified URL kernel.Wait for 0.7.1 P1↔P4 merge.

For D-1, D-2 (intelligence flag-analyser): canonical-pipeline does NOT change classification. P9 RSS is excluded from collapse (0.7.1 verdict). These remain DEFERRED (blocked by intelligence productionisation).

For D-5 BatchWideOptions: depends on whether 0.2.5 B-1/B-2 fixes wire auto_supersede (revives the type) or delete the fields (kills the type). Linked to 0.7.3 §3 absorption planning.

For D-6, D-7 (LayerKey, TrackedReferenceDoc): no canonical-pipeline impact — keyed-string-literal types are infrastructure-shape concerns.

For D-8, D-9, D-10: no canonical-pipeline impact — admin dedup + validation sort consts are out-of-scope.


Recommended changes (NOT applied in this run; user decision required):

6.1 Action — fix four TRUE-POSITIVE-FIX-NOW items pre-launch

Section titled “6.1 Action — fix four TRUE-POSITIVE-FIX-NOW items pre-launch”

These are 5-15 min fixes each. Apply BEFORE re-baselining.

  1. G-6 batch-reclassify test-coverage drift (0.3 finding, P1). Delete the duplicated test helpers at __tests__/api/batch-reclassify.test.ts:44–57; re-import from lib/queue/handlers/batch-reclassify.ts. NB: the test comment “Constants copied from scripts/batch_reclassify.ts” is misleading — the source is now lib/queue/handlers/batch-reclassify.ts.

  2. D-8 DedupSupersedeResponse — type the consumer. In components/admin/content-dedup/content-dedup-action-buttons.tsx:114, change mutationFetchJson(...) to mutationFetchJson<DedupSupersedeResponse>(...). Adds ~2 LoC including import.

  3. D-9, D-10 VALID_SORT_FIELDS / VALID_SORT_ORDERS — investigate-or-delete. Either (a) delete both consts (they are not zod-enum sources for any current schema), OR (b) wire them into a BrowseSortQuerySchema / LibrarySortQuerySchema if a future-state list-page sort discipline is anticipated. Recommend (a) given current-launch scope.

6.2 Action — migrate 9 queue-handler types from baseline to @public

Section titled “6.2 Action — migrate 9 queue-handler types from baseline to @public”

Currently the 9 types (EnqueueQueueJobArgs/Result, BatchReclassifyResult/AuthContext, BidDraftAllQuestionResult/Result/AuthContext, MarkdownBatchResult/AuthContext) are absorbed by raw counts in .knip-baseline.json. They should be @public-tagged for the same reason every other authoring-contract is — knip docs explicitly endorse this for “library/API surface that no current callsite consumes by name”.

Effect:

  • Add /** @public */ to 9 sites.
  • Re-baseline .knip-baseline.json to types: 6 (currently 15, minus 9 = 6).
  • The remaining 6 types (Tab, ExtractedQuestion, ViewMode, LogContext, QualityAction, QualityActionsResult) are barrel-hygiene findings classified by 0.3 — should ALSO be addressed (delete dead barrel re-exports). Could drop further to types: 0-2 in a follow-up.

6.3 Action — migrate 16 shadcn/ui re-exports from baseline to @public

Section titled “6.3 Action — migrate 16 shadcn/ui re-exports from baseline to @public”

Per 0.3 LEGACY-SCAFFOLD finding, the 16 shadcn re-exports (AlertDialogPortal, AlertDialogOverlay, badgeVariants, CardFooter, CardAction, DialogClose, DialogOverlay, DialogPortal, DropdownMenuCheckboxItem, DropdownMenuShortcut, DropdownMenuGroup, PopoverAnchor, PopoverHeader, PopoverTitle, PopoverDescription, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SheetClose, tabsListVariants) should be @public-tagged in their respective components/ui/*.tsx files.

Effect:

  • Add /** @public */ to ~20 export sites.
  • Re-baseline .knip-baseline.json exports: 41 → ~21.
  • Reduces signal-noise in raw knip output dramatically.

6.4 Action — config comment additions (no behavioural change)

Section titled “6.4 Action — config comment additions (no behavioural change)”

Add comments to knip.config.ts documenting the @public-tagged “INTENTIONAL-FALSE-POSITIVE” patterns the audit surfaced:

// `tags: ['-public']` semantics:
// - Genuine "stable shape" types/interfaces consumed in same file as
// function parameter/return types (the dominant pattern — 209 of
// 228 @public-tagged exports as of 0.7.5 audit).
// - Keyed-string-literal type aliases over already-consumed consts
// (e.g. `LayerKey = (typeof CLIENT_CONFIG.layer_vocabulary)[...]`).
// The const has consumers; the alias is prophylactic typing.
// - Authoring contracts for §5.4 queue handlers (post-0.7.5 should be
// @public-tagged directly; baseline absorption deprecated).
//
// `tags: ['-public']` is NOT for:
// - Barrel re-exports — author the @public tag at the SOURCE.
// - Schemas backing dead routes — fix the route, not the schema.
// - Types whose underlying consumer is itself dead (drift).

Current .knip-baseline.json:

{
"counts": {
"exports": 41,
"types": 15,
"unlisted": 3
}
}

Proposed (after §6.1 + §6.2 + §6.3 are landed):

{
"counts": {
"exports": 4,
"types": 4,
"unlisted": 1
}
}

Provenance for the new ceiling:

  • exports: 4 — leaves headroom for applyRequestContextToSentry, rootLoggerOptions, requestContextStorage (logger barrel hygiene per 0.3 G-3/G-4/G-5; deletion is a follow-up sweep) + 1 buffer slot. After deleting those, drop to 0.
  • types: 4 — leaves headroom for Tab, ExtractedQuestion, LogContext, QualityAction/QualityActionsResult after the 9 queue-handler types are tagged. After 0.3 §“Recommended hygiene cleanup” #3-#5 lands, drop to 0-2.
  • unlisted: 1node) is the genuine knip parser glitch (cannot be eliminated without an upstream fix). The other two (@tiptap/core, pdfjs-dist/build/pdf.worker.min.mjs) become explicit devDeps in package.json per 0.3 unlisted-dep classification.

Trajectory: post-cleanup counts of 0/0/1 (3-finding noise floor) is achievable.

6.6 Proposed knip.config.ts body (no behavioural change, comments added)

Section titled “6.6 Proposed knip.config.ts body (no behavioural change, comments added)”
import type { KnipConfig } from 'knip';
const config: KnipConfig = {
entry: [
'app/**/{page,layout,loading,error,not-found,route,proxy}.{ts,tsx}',
'app/**/{default,template}.{ts,tsx}',
'app/api/**/route.ts',
'instrumentation.ts',
'instrumentation-client.ts',
'next.config.ts',
'next.config.{js,mjs}',
'scripts/*.{ts,js}',
'scripts/**/*.{ts,js}',
'lib/mcp/route-handler.ts',
'lib/mcp/server.ts',
'lib/mcp/transport.ts',
'lib/mcp/index.ts',
'lib/mcp/server-factory.ts',
'lib/mcp/registrations.ts',
'lib/mcp/setup-server.ts',
'lib/mcp/handler.ts',
'lib/mcp/resources.ts',
'vitest.config.ts',
'vitest.config.{ts,mts}',
'playwright.config.ts',
'tailwind.config.{ts,js}',
'postcss.config.{ts,js,mjs}',
'drizzle.config.ts',
// Tailwind v4 CSS-first plugin activation: globals.css is the entry
// for CSS-loaded deps (`@plugin`, `@import`). See `syncCompilers.css` below.
'app/globals.css',
],
project: [
'app/**/*.{ts,tsx}',
'components/**/*.{ts,tsx}',
'contexts/**/*.{ts,tsx}',
'hooks/**/*.{ts,tsx}',
'lib/**/*.{ts,tsx}',
'types/**/*.{ts,tsx}',
'scripts/**/*.{ts,tsx}',
'instrumentation*.{ts,tsx}',
'proxy.ts',
// Tailwind v4 CSS-first plugin activation — see `syncCompilers.css` below.
'app/globals.css',
],
ignore: [
'.next/**',
'node_modules/**',
'mcp-apps/*/dist/**',
'mcp-apps/*/node_modules/**',
'supabase/types/**',
'supabase/.temp/**',
'playwright-report/**',
'test-results/**',
'.claude/**',
'docs/**',
'.planning/**',
'**/*.d.ts',
],
ignoreDependencies: [
'@types/node',
'@types/react',
'@types/react-dom',
'@vitest/coverage-v8',
'tsx',
'tailwindcss',
'@tailwindcss/postcss',
'autoprefixer',
'postcss',
],
// `tags: ['-public']` — exports tagged `@public` in JSDoc are ignored.
//
// Legitimate categories (audit ratified 0.7.5):
// 1. Function parameter/return types consumed in same file — the
// exported NAME is dead-imported, but the function signature using
// it IS consumed. Dominant pattern (209 of 228 sites as of 0.7.5).
// 2. Keyed-string-literal type aliases over already-consumed consts
// (e.g. `LayerKey = (typeof CLIENT_CONFIG.layer_vocabulary)[...]`).
// The const has consumers; the alias is prophylactic typing.
// 3. Authoring contracts for §5.4 queue handlers (Result/AuthContext
// types kept in lockstep with the dispatch.ts unknown-cast comment).
//
// NOT for:
// - Barrel re-exports — author the @public tag at the SOURCE.
// - Schemas backing dead routes — fix the route, not the schema.
// - Types whose underlying consumer is itself dead (drift).
//
// Audit cadence: re-run 0.7.5 every quarter or after any cluster of
// ingest-pipeline rewrites. The methodology + script live at
// `/tmp/claude/check-imports3.sh` (audit-time only; not committed).
// Per knip docs: https://knip.dev/reference/configuration#tags
tags: ['-public'],
// Tailwind v4 CSS-first plugin activation: knip can't see `@plugin "..."`
// directives in globals.css natively, so we synthesise virtual JS imports
// from `@plugin` and `@import` directives. This lets knip detect deps like
// `@tailwindcss/typography` that v4 loads via CSS rather than a JS config
// file. Pattern: https://www.jimmy.codes/blog/fix-knip-false-positives-tailwindcss-v4
// Using `syncCompilers` (not `compilers`) — knip 6.x ConfigurationChief
// only reads syncCompilers/asyncCompilers despite the schema accepting both.
syncCompilers: {
css: (text: string) => {
const directives = [
...text.matchAll(/@(?:plugin|import)\s+["']([^"']+)["']/g),
];
return directives.map(([, dep]) => `import "${dep}";`).join('\n');
},
},
vitest: {
config: 'vitest.config.ts',
entry: ['__tests__/**/*.{test,spec}.{ts,tsx}'],
},
playwright: {
config: 'playwright.config.ts',
entry: ['e2e/tests/**/*.spec.ts'],
},
};
export default config;

The diff vs current config:

  • Lines 71–79 (the tags comment block) replaced with the longer audit-ratified version above.
  • No structural changes to entry/project/ignore/ignoreDependencies/syncCompilers/vitest/playwright.
  • No new suppressions added.

7. Backlog tickets — TRUE-POSITIVE-DEFERRED items

Section titled “7. Backlog tickets — TRUE-POSITIVE-DEFERRED items”

The 16 DEFERRED items are not pre-launch fixes but should each get a ticket explicitly noting their blocker:

TicketItemBlocked by
BL-K1G-3 logger barrel applyRequestContextToSentry dead barrel re-exportlib/logger/index.ts cleanup pass
BL-K2G-4 rootLoggerOptions only-used-internally exportSame
BL-K3G-5 requestContextStorage only-used-internally exportSame
BL-K4G-7 computeGapSummary no production callerCoverage refactor or delete
BL-K5G-8 resetGlobalRateLimiter no test callerEither wire test-cleanup or delete
BL-K6G-9 HTML_CONTENT_TYPES test duplicationTest sweep — import constants don’t redeclare
BL-K7G-10 HEADING_PATTERNS internal-onlyDelete export
BL-K8G-11 COOPERATIVELY_CANCELLABLE_JOB_TYPES test comment-onlySame as BL-K6
BL-K9G-12 DEDUP_MIN_CONTENT_LENGTH test comment-onlySame as BL-K6
BL-K10G-13 unauthorisedResponse only-used-internallyDelete export
BL-K11G-14 useCompanyProfile (singular) sister-helperVerify company-profile feature wiring (0.2a/0.2b cross-ref)
BL-K12G-15 getContentTypeIcon sister-helperDelete or revive
BL-K13G-16 getWorkspaceIcon sister-helperSame
BL-K14G-17 WorkspaceBadge dead componentVerify if /workspace UI surface intends to render
BL-K15G-18 Tab, ExtractedQuestion re-exportDelete
BL-K16G-19 ViewMode shadowed typeReconcile with filter-bar.ViewMode
BL-K17G-20 LogContext barrel re-exportSame as BL-K1
BL-K18G-21 QualityAction/QualityActionsResult re-exportDelete
BL-K19D-1, D-2 PatternCluster/PromptRecommendationIntelligence flag-analyser productionisation (§1.18)
BL-K20D-3, D-4, D-11 BatchOptions/PerFileOverride/IngestUrlBodyCanonical-pipeline collapse (0.7.1/0.7.3) — will self-resolve
BL-K21D-5 BatchWideOptions0.2.5 B-1/B-2 fix decision (wire vs delete)

Finding bucketConfidenceFloor cause
Current config justification (§2)95%Config matches knip 6.3 docs; mechanisms understood end-to-end.
Baseline knip output stats (§3)100%Captured live; matches .knip-baseline.json ceiling exactly.
209 INTERNAL-CONTRACT classification (§4.1)90%Verified by spot-check of 12 representative sites; all 12 had functions consuming the type as parameter/return; sample-size confidence.
11 DRIFT items (§4.2)85%Verified each; D-1/D-2/FileUploadState may have planned-future consumers I didn’t surface (intelligence productionisation roadmap; 0.5 EP2 spec impact §“future”).
Cross-ref to canonical-pipeline (§5)85%Depends on 0.7.1/0.7.3 implementation choices that haven’t landed.
TRUE-POSITIVE-FIX-NOW count (4)95%Hard-verified each; G-6 already documented in 0.3 P1; D-8/D-9/D-10 newly surfaced.
Proposed baseline ceiling (§6.5)85%Achievable but requires the 16 shadcn + 9 queue-handler @public-tag migrations; not all changes can be ratified in one PR.
Backlog ticket list (§7)90%Each ticket directly traces to an audit finding (0.3 or 0.7.5).
Overall88%Below 90% — three DEFERRED-vs-DRIFT classifications (D-1, D-2, BatchWideOptions D-5) hinge on intelligence/EP2 productionisation choices outside this audit’s scope.

  1. Knip CLI tag-override flag-format. --tags=+@public and --tags=-@public did not produce the expected behaviour (CLI accepted both flags but output was identical to default config). Either knip 6.3.0 has an undocumented CLI flag-format change, or tags: ['-public'] in the config takes priority over CLI overrides. Workaround used was manual classification of all 236 sites. Confidence on suppressed-item count (236) is 100%; confidence on individual-site classification is 85% (script-driven, verified spot-checks). Recommend: file knip upstream issue if CLI flag is documented but inert.

  2. Should D-3/D-4/D-11 be deferred to canonical-pipeline collapse OR fixed pre-launch? All three are dead TYPE aliases over imported schemas. Pre-launch fix is one line per type (delete the alias). Post-canonical-pipeline they become consumed. Recommendation: defer — deletion is reversible, and waiting saves authoring churn.

  3. useCompanyProfile (singular, G-14) — is the company-profile feature wired anywhere? Sister hook useCompanyProfiles (plural) IS imported. 0.2b side-tables audit may have already established whether company_profiles table has any writers. If feature is dead, delete both hook AND sister useCompanyProfiles. If feature is live, either restore the singular hook or delete it. Cross-ref: 0.2b side-tables audit, company_profiles row.

  4. VALID_SORT_FIELDS / VALID_SORT_ORDERS (D-9, D-10) — investigate-or-delete? Confidence is 95% they are orphans. Worth a 5-min git log -G VALID_SORT_FIELDS to see if they were authored alongside a deleted sort schema.

  5. Knip parser glitch on setup.ts:57:76 (node) token). Same concern as 0.3 §7. Cosmetic only. Locally muted via baseline; upstream issue still warranted but P3.


BucketCountNotable
Currently suppressed via @public236209 INTERNAL-CONTRACT (legit) + 8 CONSUMED (legit) + 11 DRIFT (audit catches)
Currently suppressed via baseline counts59 (41+15+3)21 GENUINE-BUILD-NOT-WIRED (per 0.3) + 9 INTENTIONAL-RE-EXPORT + 17 LEGACY-SCAFFOLD + others
TRUE-POSITIVE-FIX-NOW4G-6 (test-coverage drift), D-8 (DedupSupersedeResponse untyped), D-9, D-10 (orphan VALID_SORT_*)
TRUE-POSITIVE-DEFERRED16Cleanup-eligible; 0.3 G-* + 0.7.5 D-1/D-2/D-5
INTENTIONAL-FALSE-POSITIVE8Legitimate stable-shape contracts; tag system is correct mechanism
DRIFT (will self-resolve under canonical-pipeline)4D-3, D-4, D-5, D-11 if 0.7.1/0.7.3 lands