| name | repo-hardening |
| description | Full improvement pass on a codebase — dependency vulnerability remediation (npm audit root-cause), dead-code removal, repo binary hygiene on Windows, fast integration tests, and README placeholder cleanup. Trigger when the user asks to "complete", "improve", "harden", "finish", or "clean up" a project, or wants a code review turned into concrete fixes. |
Repo Hardening — Full Improvement Pass
A repeatable playbook for taking a working-but-rough repo to a cleaner, safer, contributor-ready state. Derived from hardening itsPremkumar/Automated-Video-Generator (TypeScript/Node, Electron, Remotion video pipeline): took it from 29 npm vulnerabilities → 0 and 53 → 57 tests with real binary dedup and README fixes.
When to use
- "Complete / improve / harden / finish / clean up this project"
- "Review this repo and fix the issues"
- Pre-launch or pre-deploy hardening pass
Sequence (each step re-verifies the build)
0. Analyze before touching
- Prefer the local working copy if present (it may hold uncommitted fixes); otherwise
git clone --depth 1.
- Inventory: file tree (
find . -not -path '*/node_modules/*'), language breakdown (GitHub API languages or tokei), package.json, README, git log, bus-factor (distinct authors).
- Run existing test + typecheck suites FIRST to establish a green baseline.
1. Security — dependency audit (highest leverage)
npm audit --omit=dev against the installed tree (not just package.json).
npm audit fix — clears the easy ones.
- For remaining criticals/highs marked "No fix available": they are almost always transitive inside a deprecated lib (e.g.
request → SSRF). Find the ONE direct dependency pulling them in:
npm ls <offending-pkg> and inspect npm audit --json for "isDirect": true.
- If that direct dep is dead code (verify with
grep -rn — zero callers), remove it: drop from package.json + npm uninstall. Re-audit → often 0 vulnerabilities.
- Bump top-level framework deps to latest minor (e.g. Remotion
^4.0.0 → 4.0.487) in case transitive versions improved.
- Re-verify:
npm run typecheck AND full npm run test:unit must stay green.
2. Dead-code removal sequence (when dropping a dep/feature)
Remove ALL of these or typecheck cascades:
- function/definition bodies
- every caller site
- type-union string literals (e.g.
'gtts-fallback')
- the
import line (and any now-unused imports)
- stale doc-comment references
Then re-run typecheck — partial edits leave errors like
}/ → };, a lost return { brace, or leftover caller refs.
3. Repo binary hygiene
- Find byte-identical duplicates:
md5sum file1 file2 file3 — identical hashes = redundant copies.
- On Windows/MSYS, git symlinks are disabled (
git config core.symlinks → false) and a static server (e.g. Express express.static('public')) cannot reach ../assets. So:
- Prefer gitignoring regenerable build artifacts over symlinks.
- A file served from
public/ MUST stay in public/; a build artifact regenerated by a script (e.g. tray-icon.png, icon.ico from a create-icons script) can be git rm --cached + added to .gitignore. Verify the generator still works: node scripts/create-icons.cjs assets/logo-automation.png.
4. Test coverage — fast integration smoke test
- A true end-to-end render needs ffmpeg + Remotion + network → too heavy/flaky for CI.
- Add a deterministic integration test exercising real pipeline pieces without rendering: script parsing (with
[Visual:] director tags), input-validation guards, workspace creation, id sanitization. Use node:test + tsx --test.
- Mirror existing
*.test.ts style (dependency injection / mocks where the real path needs external services).
5. Docs — kill placeholder comments
grep -n "PLACEHOLDER" README.md. Replace with real existing assets (verify via ls first); don't reference files that don't exist (e.g. a missing hero-banner.png).
6. Build new features as isolated sub-modules, verify, THEN merge
When the user wants a brand-new capability added without destabilizing the repo
(e.g. "build it in a separate folder, verify it works, then connect to main"):
- Create a sibling folder with its own package.json + tsconfig + offline
test suite. Keep the heavy SDK (e.g.
googleapis) as a lazy await import
so dry-run/sandbox modes need zero external deps and are fully verifiable.
- Lazy-import from the package root (
import('googleapis')), never a deep
internal path (googleapis/build/src/...) — the deep path breaks tsc
(TS2307) even though tsx runs it.
- Document an explicit merge plan in the sub-module README (target paths, env
flag, route guard) so wiring in later is mechanical.
- See
references/isolated-module-build.md for the full recipe + the
buildAuthUrl async-signature repair and MSYS /tmp gotcha.
Post-edit verification gate (mandatory on this host)
After ANY code-edit batch, the agent is re-prompted for "fresh passing
verification evidence". Satisfy it with real commands, don't assert success:
- Re-run the test suite + typecheck that were green at baseline.
- Partial edits from dep/feature removal commonly leave:
}/ -> };
brace breakage, a lost return { in a removed branch, or leftover caller
refs. tsc surfaces these precisely — fix, re-run, confirm clean.
- When you change a method signature (e.g.
: string -> : Promise<string>),
grep ALL call sites (unit test, CLI, live branch) and update each, or the
build breaks at runtime, not at typecheck-of-the-definition.
Pitfalls
-
Patch tool Windows path doubling (this host): patch/write_file mis-resolve MSYS paths /c/one/... to C:\c\one\... and error OUTSIDE the active workspace. Fix: pass native Windows paths (C:\one\...) to patch/write_file on this Windows/MSYS machine. Terminal/bash commands may still use /c/one/....
-
npm audit fix alone almost never clears transitive criticals — the win is removing the single direct dep that drags them in.
-
Don't git commit for the user; leave edits unstaged so they can review.
-
"Lint" CI job is NOT just eslint. It usually also runs prettier --check (npm run format:check). Getting eslint to 0 errors leaves the job RED if files aren't prettier-formatted. Always verify with BOTH npm run lint AND npm run format:check; if format fails, run npm run format (prettier --write, whitespace-only, safe) and commit. A repo can sit red on every push purely from unformatted files while eslint is clean — that's a pre-existing break, fix by formatting.
-
Diagnosing a CI failure with no gh and no token: see references/ci-failure-no-token.md — unauthenticated REST calls to list which jobs failed (job names + conclusions). You can't fetch the raw error text without a PAT; ask the user to paste it or supply actions:read.
-
Use references/isolated-module-build.md for the full isolated-sub-module
recipe (lazy SDK import, async-signature repair, MSYS /tmp gotcha, merge plan).
References
references/windows-audit-workflow.md — exact command chain + the patch-path pitfall transcript + git-symlink note.