-
Notifications
You must be signed in to change notification settings - Fork 904
Night Watch Dead Code
Assigned to: Cindy's Navi (cixzhang)
Goal: Keep the codebase free of dead code by detecting unused files, exports, types, and devDependencies and removing the high-confidence ones via PR.
Tooling: knip, run from outside the repo. knip only reads a checkout to resolve the module graph, so the binary, its config (knip.jsonc), and the runner live in the Night Watch operator's workspace, not in facebook/astryx. Nothing is added to the public repo's package.json or lockfile. knip reads each package's exports/bin as entry points, so published API surfaces are never reported as unused.
The tooling ships in this wiki repo under tools/deadcode/, so it travels with the instructions the Night Watch already clones each run (no cross-node file transfer, version-controlled alongside the checklist):
-
knip.jsonc: the public-API-safe config (entry patterns + ignores) -
check-deadcode.mjs: the runner (invokes knip with--directory <checkout> --config knip.jsonc, handles the small-host memory workaround) -
package.json: pinsknip(node_modulesis gitignored, installed on first use) -
bootstrap.sh: installs knip intotools/deadcode/on the node
Each run clones the wiki, bootstraps knip, then runs the detector against a checkout that has node_modules installed. Nothing is written to the facebook/astryx repo toolchain.
Once per night, producing one PR per run (max). Hourly cron with the standard business-hours guard (skip 9am-5pm PST on weekdays); a state gate limits it to one real run per day.
Dead code accumulates silently. A helper no one calls after a refactor, a type left behind, a devDependency for a removed workflow. None of it breaks tests or CI, so nothing catches it. This role runs a real, reproducible tool and turns its high-confidence findings into small, safe removals.
Detect and, for high-confidence categories, remove:
-
Unused files in
packages/*(source files imported by nothing, not reachable from any entry point) -
Unused exports in
packages/*(an exported symbol no other module imports) -
Unused exported types in
packages/* -
Unused
devDependencies(a dev dependency listed in apackage.jsonthat nothing references) - Duplicate exports (the same symbol exported under two names)
Auto-PR only the categories that are safe to delete mechanically. Everything else is flagged in the PR's Needs Review section, not deleted.
| Category | Action |
|---|---|
Unused internal export / type in packages/* not in any package's exports map |
Auto-remove |
Unused file in packages/* not in any exports/bin and not matched by an entry pattern |
Auto-remove |
Unused devDependency
|
Auto-remove (remove the line; verify install/build/test) |
| Duplicate export | Flag (renames are judgment calls) |
Anything in apps/*
|
Flag only. App module graphs need built workspace deps to resolve, so knip under-resolves them and produces false positives. Never auto-delete app code. |
Anything matched by a knip.jsonc entry pattern (*.doc.mjs, stories, Next.js route files) |
Never touch (entry points by design) |
Anything under packages/cli/templates/** or internal/vibe-tests/.baseline/**
|
Never touch (standalone scaffolding / reference fixtures, already ignored in config) |
| Unused / unlisted / unresolved runtime dependencies | Do NOT act. Defer to the Dependencies and Quartermaster roles |
Before deleting any export, type, or file, confirm all of:
- It is reported by the detector's JSON output in an auto-removable category above.
- A repo-wide search (
git grep) for the symbol/file basename returns no references outside its own definition. - It is not a dynamic import, StyleX codegen output, CLI template source, or a name referenced from a non-TS surface (
.md,.mjsdoc, JSON, config). Static analysis misses these. - Removing it leaves
pnpm buildandpnpm testgreen.
If any check fails, flag it, do not delete it.
- Touch runtime dependencies (unused/unlisted/unresolved deps). That is Dependencies + Quartermaster
- Delete anything in
apps/*(flag only) - Component convention fixes (theming, API, a11y, export hygiene). That is Component Auditor
- CI fixes. That is QA
- Merge or approve PRs. Humans do that
- Refactor passing code or restructure modules. Removal only, no rewrites
- Add anything to the repo's own toolchain (
package.json, lockfile, CI). The detector stays out-of-repo - File issues for individual findings. Findings live in the run log and the PR body
- Clone the wiki fresh; confirm this role is still assigned to your human in Night Watch Roles. If not, disable the cron job and stop.
- Apply the business-hours guard. If business hours, NO_REPLY.
- Check
memory/xds-night-watch-state.jsonfordeadCode.lastRunAt. If it is from today (PST), skip and NO_REPLY. - On the
xdsnode, fetch latestorigin/mainand create a worktree from it (for the PR branch). - Bootstrap the tools from the fresh wiki clone:
bash tools/deadcode/bootstrap.sh. This installs knip intotools/deadcode/if needed.
knip needs a checkout with node_modules to resolve imports. The shared main checkout has them; the analysis is read-only, so point the detector at a checkout that is installed:
# from the freshly cloned wiki:
node tools/deadcode/check-deadcode.mjs --repo /vercel/sandbox/repos/xds --reporter json > /tmp/deadcode.jsonParse the JSON. Bucket every finding into the confidence tiers above. Discard the runtime-dependency and apps/* buckets (flag-only).
For each candidate export/type/file, run the four-point high-confidence deletion rule (git grep for references, rule out dynamic/codegen/template/non-TS use). Demote anything that fails to the Needs Review list. Make the actual edits in your worktree, not the shared checkout.
- Delete unused files; remove unused exports/types from their source; drop unused
devDependencieslines. - Run
pnpm install(if a devDependency was removed), thenpnpm build && pnpm testin the worktree. - If the build or tests break, revert the offending removal and keep the rest. One bad removal must not block the batch.
- One PR per night. Branch: a plain semantic name,
chore/dead-code-YYYY-MM-DD(nonavi/prefix; the commit guard blocks agent-named branches on this repo). - Commit with
--no-verify(husky hooks hang in worktrees). Commits use the node's default git author. - Title:
chore: remove dead code (YYYY-MM-DD). Body: list what was removed, grouped by category, with a short justification per group. Put everything flagged (duplicates,apps/*, anything that failed verification) under a Needs Review heading. -
Public-repo hygiene: scrub the branch, commit, and PR body of internal refs and agent fingerprints (see Night Watch Overview Principle 6 and the repo's leak rules). The only permitted footer is
Night Watch — Dead Code. - Publish ready for review (not draft).
- If nothing is auto-removable, do not open a PR. Log findings and update state.
Same as the Component Auditor: record the pushed HEAD sha, schedule a one-shot recheck ~5 min out, check gh pr checks, fix CI failures in place (SHA-collision guard first), max 3 attempts, then hand off to daytime review.
- Log findings and actions to
memory/xds-night-watch/{date}.mdunder a## Dead Codesection. - Update
memory/xds-night-watch-state.json.
{
"deadCode": {
"lastRunAt": "ISO timestamp",
"prsFiled": ["#NNNN"],
"lastRemovedCount": { "files": 0, "exports": 0, "types": 0, "devDependencies": 0 },
"flaggedForReview": ["packages/core/src/foo.ts:Bar (duplicate export)"]
}
}knip.jsonc (in the wiki at tools/deadcode/) is the source of truth for what counts as an entry point. When a finding is a false positive because a legitimate entry pattern is missing (a new codegen file type, a new app route convention), fix knip.jsonc first and commit it to the wiki, then re-run. Do not silence a real category with a blanket ignore.
- knip's parser reserves a large virtual buffer; on small, swapless hosts the runner sets
vm.overcommit_memory=1when permitted. If you see "Array buffer allocation failed", run on a larger host or with privileges to set that sysctl. - The detector is a report, run out-of-repo. It never touches the repo toolchain and never blocks anyone.
- knip needs
node_modulesin the target checkout; a bare worktree without an install will not resolve. Point--repoat an installed checkout.
| Date | Result |
|---|---|
| 2026-07-13 | Role created. Out-of-repo knip tooling built and validated on the xds node (public API, CLI templates, and vibe-test baselines correctly excluded; real findings: unused internal exports, types, and devDependencies). |