Skip to content

Enable knip unused-exports detection; rename gate to lint:unused (#425)#441

Open
geevensingh wants to merge 1 commit into
mainfrom
infra/lint-unused-exports
Open

Enable knip unused-exports detection; rename gate to lint:unused (#425)#441
geevensingh wants to merge 1 commit into
mainfrom
infra/lint-unused-exports

Conversation

@geevensingh
Copy link
Copy Markdown
Owner

Summary

Closes #425. Enables knip's unused-exports / unused-types / unused-ns-exports
/ unused-ns-types detection (flipping rules.exports, rules.types,
rules.nsExports, rules.nsTypes from off -> error in
knip.jsonc) and renames the script from lint:unused-deps ->
lint:unused to match the broader behavior.

Empirical pre-flight showed 30 unused exports + 28 unused exported
types + 0 ns* findings concentrated in ~12 files. All 58 findings
fit DELETE / INLINE without needing @public tagging (so the
follow-up @public convention work flagged in the plan is NOT
required for this PR).

What this adds

  • 4 rule severities flipped in knip.jsonc. Header comment updated.
  • Script + CI rename: lint:unused-deps -> lint:unused;
    CI step "Lint - Unused dependencies" -> "Lint - Unused code";
    outcome env var, summary emit label, fix-hint string all updated.

What this removes

  • 8 DELETEs (genuinely dead code).
  • 50 INLINEs across 16 files (drops the unnecessary export keyword
    from declarations whose only consumers live in the same file).

What this deliberately does NOT change

Per-file dispositions (58 findings)

File Exports Types Disposition
api/src/shared/blobs.ts 8 0 All INLINE
api/src/shared/ruleSets.ts 9 8 INLINE; bottom re-export block partially DELETE (3 names had 0 importers); RuleMatchType alias DELETE'd as unused-internally too
api/src/shared/history.ts 4 1 INLINE; HISTORY_ACTIONS DELETE'd
api/src/shared/users.ts 1 0 INLINE
api/src/shared/preferences.ts 0 4 All INLINE
api/src/shared/auth.ts 0 1 JwtPayload re-export DELETE'd
src/app/core/api/models.ts 0 1 INLINE (verified no feature-module consumer)
src/app/core/json/json-extractor.core.ts 3 3 All INLINE
src/app/core/telemetry/noise-filter.ts 1 2 INLINE + DELETE SUPPRESSED_EVENT_ID
src/app/core/telemetry/telemetry-message-ids.ts 1 0 INLINE (public surface is the derived type, per skeptic-2)
src/app/core/telemetry/msal-bridge.ts 0 1 INLINE
src/app/core/telemetry/sw-registration.ts 0 2 INLINE + DELETE SwEventName
src/app/core/title-suggester/types.ts 0 1 INLINE
src/app/shared/components/json-tree/** 0 3 All INLINE
src/app/shared/utils/contrast.ts 0 1 DELETE
src/testing/a11y.ts 3 0 DELETE OVERLAY_EXCLUDES; INLINE 2 helpers (used at L254/L255)

Final tally: 8 DELETEs, 50 INLINEs, 0 ENTRY-GRAPH-FIX, 0
TEST-COUPLING-ACCEPTED, 0 TAG
.

Verification

Check Result
npm run lint:all exit 0 in ~60s (all 13 gates green)
npx vitest run 3206/3208 pass (2 skipped, baseline)
npm --prefix api test 474/474 pass
npm run build clean; all expected chunks emit

Coordination

No file-overlap with in-flight PRs. #417 + #435 + #438 (perf-bench
Vitest migration tail) all landed during plan iteration; pre-flight
finding count is identical pre/post.

SemVer

No bump. Tooling/CI + internal-code-cleanup only. Touches
api/src/shared/** utility exports, not api/src/functions/**
route handlers.

New CI gate message (observability)

After this PR, the lint-summary row contributors see for knip
findings is "Unused code" (was "Unused dependencies"). Fix-hint:

npm run lint:unused - either remove the unused export/dep or add
it to knip.jsonc ignoreDependencies with a rationale comment
naming the specific (not generic) mechanism by which the dep is
used

Rubber-duck

Three-agent panel (skeptic + advocate + architect, parallel,
2026-05-31). 12 distinct findings: 9 adopted, 3 set aside.

Set-aside findings:

Adoptions caused 4 structural plan revisions:

  • TAG / @public category removed entirely
  • Script + CI rename added to scope
  • TELEMETRY_MESSAGE_IDS pre-classified as INLINE with a new rubric
    sub-rule
  • Per-file test runs after each workspace's edits

Full transcripts in the session folder
(plan.critic-skeptic.md, plan.critic-advocate.md,
plan.critic-architect.md).

Follow-ups

After this PR lands, #425 closes. Remaining open follow-ups from
#431's panel:


Session

  • AI-Local: bb6ac642-dd57-4c49-aded-df3395b91e3e
  • AI-Cloud: 76f32c00-92fd-4ecf-9232-0fc432d1e119

Flips `rules.exports`, `rules.types`, `rules.nsExports`, `rules.nsTypes`
from `off` to `error` in `knip.jsonc` so the existing knip gate also
catches unused exports + type exports across the root SPA and api/
workspaces. Renames `lint:unused-deps` -> `lint:unused` (and the CI
step + summary row + fix-hint) so the name matches the broader
behavior (per the rubber-duck architect-2 finding: deferring the
rename on cosmetic-churn grounds violates AGENTS.md §11's
"don't default to the minimal change" rule).

## Rubber-duck panel

Three-agent panel (skeptic + advocate + architect, parallel) flagged
12 distinct findings: 9 adopted, 3 set aside.

Set aside:
- skeptic-1 (blocker on entry-graph contamination) - empirically
  refuted: `git ls-tree origin/main` confirms 132 *.test.ts, 0
  *.spec.ts, vitest configs present. The `src/testing/a11y.ts`
  flagged names are post-#418 leftovers.
- skeptic-5 (split bundle by risk profile) - advocate's
  `ruleSets.ts has both 9 unused exports + 8 unused types`
  cross-file overlap concrete evidence wins.
- architect-4 (block on #417 perf-bench Vitest migration) -
  pre-flight distribution shows zero perf-bench files; #417 +
  #435 + #438 have all since landed without affecting the
  finding distribution.

Adopted (major):
- TAG / `@public` category removed entirely (skeptic-3 +
  architect-1). Pre-flight categorization confirmed all 58
  findings fit DELETE/INLINE; no `@public` taxonomy work
  needed.
- Script + CI rename to `lint:unused` (architect-2).
- TELEMETRY_MESSAGE_IDS pre-classified as INLINE (skeptic-2):
  public surface is the derived `TelemetryMessageId` type.
- Per-file test run after each workspace's edits (skeptic-4).

Full transcripts in the session folder
(plan.critic-skeptic.md, plan.critic-advocate.md,
plan.critic-architect.md).

## Per-file dispositions (58 findings)

Final tally: 8 DELETEs, 50 INLINEs, 0 ENTRY-GRAPH-FIX,
0 TEST-COUPLING-ACCEPTED, 0 TAG. Detailed disposition table in
the PR description.

## SemVer

No bump. Tooling/CI + internal-code-cleanup only. No public API,
stored shape, user-visible behavior, deployed artifact, or
package.json `main`/`exports` change. Touches `api/src/shared/**`
utility exports, not `api/src/functions/**` route handlers.

## Verification

- `npm run lint:all`: exit 0 in ~60s (all 13 gates green; knip
  finds 0 issues with the broader rule scope).
- `npx vitest run`: 3206/3208 pass (2 skipped).
- `npm --prefix api test`: 474/474 pass.
- `npm run build`: clean production build, all expected chunks.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 1, 2026 00:44
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enables knip's unused-exports / unused-types / unused-nsExports / unused-nsTypes detection (flipping each from off to error in knip.jsonc) and renames the lint script from lint:unused-deps to lint:unused to reflect the broader scope. It then resolves the resulting 58 findings via 8 deletions and 50 inlinings (dropping the export keyword from declarations consumed only within the same file).

Changes:

  • Flip 4 knip rule severities (exports, types, nsExports, nsTypes) from off to error; update the config header comment.
  • Rename lint:unused-deps to lint:unused in package.json and update CI step ID, outcome env var, summary label, and fix-hint accordingly.
  • De-export or delete 58 unused symbols across 16 files (api shared modules, core json/telemetry/title-suggester, json-tree, contrast, a11y test helpers).

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated no comments.

Show a summary per file
File Description
knip.jsonc Flip exports/types/nsExports/nsTypes severities to error; rewrite header comment; update script name in run instructions.
package.json Rename lint:unused-deps -> lint:unused.
.github/workflows/ci.yml Rename CI step, id, outcome env var, summary label, and fix-hint to "Unused code" / lint:unused.
api/src/shared/blobs.ts Drop export on 8 file-local helpers/constants.
api/src/shared/ruleSets.ts Drop export on 9 names + 8 types; remove unused RuleMatchType alias and trim bottom re-export block to just MAX_RULE_SETS_PER_USER.
api/src/shared/history.ts Inline HistoryAction, DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE, getHistoryContainer; delete unused HISTORY_ACTIONS.
api/src/shared/users.ts Inline getUsersContainer.
api/src/shared/preferences.ts Inline 4 file-local types.
api/src/shared/auth.ts Remove JwtPayload re-export.
src/app/core/api/models.ts Inline HistoryAction.
src/app/core/json/json-extractor.core.ts Inline 3 interfaces and 3 functions.
src/app/core/telemetry/noise-filter.ts Inline 2 types; drop unused import + SUPPRESSED_EVENT_ID.
src/app/core/telemetry/telemetry-message-ids.ts Inline TELEMETRY_MESSAGE_IDS (derived type stays public).
src/app/core/telemetry/msal-bridge.ts Inline MsalBridgeEntry.
src/app/core/telemetry/sw-registration.ts Inline BuildIdentity; delete unused SwEventName.
src/app/core/title-suggester/types.ts Inline SuggestionSource.
src/app/shared/components/json-tree/build-tree.ts Drop JsonValueType from re-export list.
src/app/shared/components/json-tree/flatten.ts Inline FlatItemKind.
src/app/shared/components/json-tree/formatting-rules-engine.ts Inline 3 interfaces.
src/app/shared/utils/contrast.ts Delete unused Theme type.
src/testing/a11y.ts Delete OVERLAY_EXCLUDES; inline runA11yScan + assertNoStrictA11yViolations; update docblocks to drop Karma/Jasmine references.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 1, 2026

Azure Static Web Apps: Your stage site is ready! Visit it here: https://calm-flower-01969880f-441.eastus2.7.azurestaticapps.net

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 1, 2026

Preview environment deployed

Limitations:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enable knip unused-exports detection (flip rule severity off -> error)

2 participants