Skip to content

chore(ci): run the knip dead-code gate for the repository root and every workspace - #4942

Draft
orangeCatDeveloper wants to merge 1 commit into
apache:mainfrom
orangeCatDeveloper:chore/knip-dead-code-gate
Draft

chore(ci): run the knip dead-code gate for the repository root and every workspace#4942
orangeCatDeveloper wants to merge 1 commit into
apache:mainfrom
orangeCatDeveloper:chore/knip-dead-code-gate

Conversation

@orangeCatDeveloper

@orangeCatDeveloper orangeCatDeveloper commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Summary

The dead-code gate ran on two workspaces, so the other nine plus the repository root could accumulate unused files and exports unnoticed. A single plain npx knip now covers all eleven workspaces and the root in about two seconds — a strict superset of the two per-workspace steps it replaces.

Making that run clean needed the dynamic reachability the scan cannot infer declared explicitly, rather than silenced: spawn-loaded test fixtures, the filesystem worker bundle entry, the PowerShell-driven Windows IPC trust fixture, the gated-recovery candidate host-kernel.test.ts forks by argv path, eval's Python-spawned harness, the dynamically dispatched computer-use command modules, and the two modules actions/github-script loads from with: blocks. packages/ui/scripts joins the project set, where a benchmark script had been sitting in the gate's blind zone.

Two exceptions are declared rather than fixed. runtime-host accepts the duplicates finding on three protocol alias files — probe-verified that an injected unused export in artifact.ts is still reported, so only duplicates is silenced and only there. website keeps its cookie pin because astro's prerenderer resolves the bare specifier through the website root.

A new gate fails the step when a workspace exists in package.json but not in knip.json, so a newly added workspace cannot enter the repo ungated, and a stale knip.json key cannot sit there guarding nothing.

Known boundary: files behind a package.json exports map are entry files, so their unused exports stay outside the default report (core exposes 147 of 266 source files this way, runtime 110 of 506). --include-entry-exports surfaces ~250 public-API findings that need their own sweep.

Verification

npx knip (plain)                    0 findings, root + 11 workspaces
check-knip-workspace-coverage       gate exit 0, 3 unit tests pass
gate sensitivity probe              an unimported src/copy file and an unused
                                    packages/mcp file are both reported
duplicates probe                    injected unused export in artifact.ts still
                                    reported with the alias-file exception
npm run format:check                clean

AI use

  • Generative tooling made a substantive contribution

Tool(s) and scope: Claude Code — the knip workspace configuration, the coverage gate, CI wiring, and this description.

Checklist

  • Lint, format, typecheck and the affected suites pass locally
  • Commit carries Generated-by: Claude Code

Does this PR entail a change in behavior?

  • Yes
  • No

@github-actions github-actions Bot added the effort/L Under 1000 readable lines label Sep 7, 2026
@orangeCatDeveloper
orangeCatDeveloper force-pushed the chore/knip-dead-code-gate branch 5 times, most recently from 60c9ec2 to 9580275 Compare September 8, 2026 19:36
…pository root

Extend knip.json to all nine previously-ungated workspaces (runtime,
runtime-host, storage, core, mcp, computer-use, eval, cli, website) plus
the repository root, and replace the eleven per-workspace Knip CI steps
with a single plain 'npx knip' run - a strict superset that also covers
the repository root and respects every workspace's project patterns.
Workspace globs are deliberately avoided: -W 'packages/*' silently skips
per-workspace project patterns (probe-verified). The step fails when a
package.json workspace is missing from knip.json, and when a knip.json
key no longer resolves to a declared workspace.

Dynamic reachability is registered explicitly - spawn-loaded test
fixtures, the filesystem worker bundle entry, the PowerShell-driven
Windows IPC trust fixture, eval's Python-spawned harness entry, the
dynamically dispatched computer-use command modules, and the two
modules that actions/github-script loads from its with: script block
(knip's github-actions plugin only reads run: steps) - so the scan
doesn't guess. The website's entry surface is scoped to the Astro
routes, the config and the executed scripts; components, layouts and
copy modules stay in the project set and are judged by the real import
graph (probe-verified). The root project glob excludes ambient
declarations, which TS resolution consumes without an import statement.

Remove what the scan surfaced and repo-wide greps confirmed unreachable:
unused exports, types and helpers across runtime, runtime-host, storage,
cli, core and the root scripts; the storage readHead registration
plumbing that only fed the deleted readWorkspaceHeadInternal; and export
aliases whose second name had no consumers.

Kept deliberately: the decode/encode and PAGE/RANGE codec alias pairs
whose both names have live consumers. Their aliases become distinct
declarations (thin wrapper functions, an independently declared range
bound asserted against the page bound in the protocol test) so the
duplicates check resolves without exemption tags. The website keeps its
exact cookie@2.0.1 pin as a declared exception: astro's prerenderer
resolves it through the website root. Hoisted build/test tooling that
root scripts import (electron, electron-builder, electron-updater,
app-builder-lib, builder-util, @playwright/test, @babel/parser, ws) is
declared in the root package.json instead of blanket-silenced, and the
CI step asserts the two electron-builder internal-package pins track
electron-builder's own requirement.

The coverage and pin-parity guards live in
scripts/check-knip-workspace-coverage.mjs with node --test coverage
(single-level glob semantics on both sides, the stale-key regression
case, pin parity including the absent-pin case) rather than as untested
inline scripts.

Known coverage boundary, surfaced by review: files listed in a
package.json exports map are entry files, so their unused exports sit
outside the default report (core exposes 147 of 266 source files this
way, runtime 110 of 506, storage 55 of 249); --include-entry-exports
surfaces ~250 public-API findings that need their own sweep with
explicit keep decisions.

No behaviour change.

The knip duplicates finding on the three intentional protocol alias
files (the encode/decode result-codec pairs and the PAGE/RANGE bound
pair, kept as plain aliases by the cleanup PR) is accepted with a
file-scoped ignoreIssues entry in the runtime-host workspace. The
duplicates check stays meaningful elsewhere: probe-verified that an
injected unused export in artifact.ts is still reported, and the
full npx knip run is clean.

Generated-by: Claude Code
@github-actions github-actions Bot added effort/M Under 500 readable lines and removed effort/L Under 1000 readable lines labels Sep 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/M Under 500 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant