chore: agent tooling, npm hardening, encoding normalization#252
Merged
Conversation
- Add CLAUDE.md pointing to AGENTS.md and .grok/rules/
- Add .grok/rules/{issue-workflow,fast-iteration,testing,session-validation}.md adapted to TS lib / mocha+c8 stack
- Add scripts/check-encoding.mjs, audit-ci.mjs, git-pull-all.mjs (verbatim from skeletor reference)
- Add .npmrc (fund=false) and .gitattributes (LF enforcement, binary exclusions)
- Update package.json: lint:encoding gate wired into lint, audit:ci replaced with node script, git:pull added, release:patch|minor|major and publish:dry added
- Update scripts/reinstall.js: runs audit:ci gate after fresh install
- Normalize CRLF→LF in .editorconfig, .prettierrc.json, .vscode/extensions.json, .vscode/settings.json
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR tightens repo “agent/tooling” ergonomics by adding encoding and audit gates, introducing helper scripts for common workflows, and normalizing text file line endings / attributes to prevent future encoding drift.
Changes:
- Add CI-/local-friendly gates:
scripts/check-encoding.mjs(UTF-8/LF/control-char checks) andscripts/audit-ci.mjs(fail only on critical/high advisories). - Add convenience tooling and wire-up:
git:pullhelper,lint:encoding, updatedlint/audit:ciscripts, and run the audit gate afternpm:reinstall. - Add agent guidance entrypoints (
CLAUDE.md,.grok/rules/*) plus repo-level normalization (.gitattributes,.npmrc) and LF cleanup in editor config files.
Reviewed changes
Copilot reviewed 13 out of 16 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| scripts/reinstall.js | Runs audit:ci after reinstall to gate on high/critical advisories. |
| scripts/git-pull-all.mjs | Adds a “fetch all + ff-only pull” helper script for safer syncing. |
| scripts/check-encoding.mjs | Adds a tracked-file encoding/line-ending/control-char gate. |
| scripts/audit-ci.mjs | Adds a JSON-driven audit gate that fails only on critical/high and is offline-safe. |
| package.json | Wires new scripts into lint, adds lint:encoding, git:pull, release/publish helpers, and updates audit:ci. |
| CLAUDE.md | Adds a Claude Code entrypoint that references AGENTS.md and .grok/rules/. |
| .vscode/settings.json | LF normalization only. |
| .vscode/extensions.json | LF normalization only. |
| .prettierrc.json | LF normalization only. |
| .npmrc | Disables npm’s funding footer (fund=false). |
| .grok/rules/testing.md | Adds repo-specific testing guidance and validation layering. |
| .grok/rules/session-validation.md | Adds a mandatory closeout checklist / reporting policy for validation. |
| .grok/rules/issue-workflow.md | Adds issue-driven workflow and scoping rules for changes. |
| .grok/rules/fast-iteration.md | Adds guidance for scratch scripts vs durable tests. |
| .gitattributes | Adds LF normalization defaults, explicit per-type rules, and binary exclusions. |
| .editorconfig | LF normalization only. |
Comment on lines
+33
to
+39
| const audit = spawn(isWin ? "npm.cmd" : "npm", ["run", "audit:ci"], { | ||
| stdio: "inherit", | ||
| cwd: rootDir, | ||
| }); | ||
| audit.on("close", (code) => { | ||
| process.exit(code ?? 0); | ||
| }); |
Comment on lines
+11
to
+22
| const branch = gitOut(['rev-parse', '--abbrev-ref', 'HEAD']); | ||
|
|
||
| console.log('▶ Fetching all remotes (prune branches + tags)...'); | ||
| git(['fetch', '--all', '--prune', '--prune-tags', '--tags']); | ||
|
|
||
| console.log(`▶ Fast-forwarding ${branch}...`); | ||
| try { | ||
| git(['pull', '--ff-only']); | ||
| } catch { | ||
| console.error(`✖ ${branch} has diverged from its upstream; cannot fast-forward. Resolve manually (rebase/merge).`); | ||
| process.exit(1); | ||
| } |
| | 2. Audit | `npm run audit:ci` | **Always** — zero critical/high advisories. | | ||
| | 3. Tests | `npm test` | **Always** — typecheck + lint + build + mocha + c8 coverage passes. | | ||
|
|
||
| `npm run lint` runs steps 1–2 together (ESLint + encoding). |
|
|
||
| ## Layered validation | ||
|
|
||
| 1. **Every task** — `npm test` + `npm run lint` (encoding + audit gates). Never skip these. |
Comment on lines
+30
to
+31
| "lint": "eslint src && npm run lint:encoding", | ||
| "lint:encoding": "node scripts/check-encoding.mjs", |
…it workflow, doc accuracy - scripts/check-encoding.mjs: sync verbatim from skeletor — add repoRoot detection (process.chdir), fail loudly on unreadable tracked files instead of silently skipping, deduplicate per-file issue list, add per-file lineEndingFlagged + controlFlagged guards to match reference behaviour - scripts/audit-ci.mjs: sync verbatim from skeletor — capture stderr alongside stdout, add ENOENT hard-failure so a missing npm binary can't masquerade as "no vulns", update comment to match policy note about audit fix lockfile risk - scripts/git-pull-all.mjs: sync verbatim from skeletor — add detached HEAD guard, improve error message on ff-only failure - scripts/reinstall.js: fix null/signal exit-code handling — treat signal kill and null code as process.exit(1) instead of silently exit(0) - .github/workflows/audit.yml: add blocking audit gate workflow (npm ci --ignore-scripts + npm run audit:ci) copied verbatim from skeletor - package.json prepublishOnly: add npm run audit:ci before npm test so publish is always gated on a clean audit - AGENTS.md: clarify npm run lint description to include encoding gate - CLAUDE.md: defer commit/push guidance to AGENTS.md; add audit:ci to before- handing-work-back checklist - .grok/rules/testing.md: correct claim that lint runs the audit gate — lint = ESLint + encoding; audit:ci is a separate gate - .grok/rules/session-validation.md: correct note that lint ran steps 1-2; audit:ci is separate from lint Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ing) Sync audit-ci.mjs with the corrected reference: hard-fail only on critical/high in production dependencies (npm audit --omit=dev); dev-only + moderate/low are reported but never gate the build. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment on lines
+33
to
+43
| const audit = spawn(isWin ? "npm.cmd" : "npm", ["run", "audit:ci"], { | ||
| stdio: "inherit", | ||
| cwd: rootDir, | ||
| }); | ||
| audit.on("close", (code, signal) => { | ||
| if (signal) { | ||
| console.error(`❌ Audit gate killed by signal: ${signal}`); | ||
| process.exit(1); | ||
| } | ||
| process.exit(typeof code === "number" ? code : 1); | ||
| }); |
| | `npm test` | Full gate: typecheck → lint → build → mocha + c8 coverage (90% threshold). | | ||
| | `npm run lint` | ESLint on `src/` + encoding gate. | | ||
| | `npm run lint:encoding` | Fails on non-UTF-8 / BOM / CRLF / control chars in tracked files. | | ||
| | `npm run audit:ci` | Fails only on critical/high advisories (moderate/low ignored). | |
| | Step | Command | When required | | ||
| |------|---------|---------------| | ||
| | 1. Encoding | `npm run lint:encoding` | **Always** — no BOM / CRLF / non-UTF-8 / control chars. | | ||
| | 2. Audit | `npm run audit:ci` | **Always** — zero critical/high advisories. | |
Comment on lines
+19
to
+21
| # --ignore-scripts: install the dependency tree for auditing without | ||
| # running postinstall/native builds/husky. Hard-fails on critical/high. | ||
| - run: npm ci --ignore-scripts |
| "postbuild": "node scripts/postbuild.mjs", | ||
| "clean": "node scripts/prebuild.mjs", | ||
| "prepublishOnly": "npm run build && npm test", | ||
| "prepublishOnly": "npm run build && npm run audit:ci && npm test", |
- scripts/check-encoding.mjs: verbatim from skeletor (ENOENT-aware catch, richer CRLF_OK comment, corrected error message with BOM/CRLF wording) - scripts/audit-ci.mjs: verbatim from skeletor (inCI flag, spawnError for all string err.code not just ENOENT, CI-aware bailOnNoData helper) - scripts/git-pull-all.mjs: verbatim from skeletor (fetch wrapped in try/catch with actionable error message) - .github/workflows/audit.yml: verbatim from skeletor (fuller comment explaining prod-only gate and CI offline-fail behaviour) - CLAUDE.md audit:ci row: note hard-fails on critical/high in production deps (dev-only + moderate/low reported, not gated) - .grok/rules/session-validation.md: audit line → "zero critical/high in production deps (dev-only reported, not gated)" - .grok/rules/testing.md: audit:ci mention notes it gates production deps only - scripts/reinstall.js: add 'error' event handler on spawned audit process so a spawn failure logs clearly and exits 1 instead of unhandled exception - package.json prepublishOnly: drop redundant `npm run build &&` (npm test already builds) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
AGENTS.mdand.grok/rules/; no duplication of AGENTS.md content.grok/rules/— four rule files (issue-workflow,fast-iteration,testing,session-validation) adapted from the skeletor reference to this TS lib / mocha+c8 stack; no CUDA contentscripts/check-encoding.mjs— verbatim from skeletor: fails on non-UTF-8 / BOM / CRLF / control chars in tracked filesscripts/audit-ci.mjs— verbatim from skeletor: gates only on critical/high advisories; moderate/low never break the build; offline-safescripts/git-pull-all.mjs— verbatim from skeletor:fetch --all --prune --prune-tags+pull --ff-only.npmrc—fund=false(suppresses funding footer).gitattributes—* text=auto eol=lfnormalization, explicit per-type rules, binary exclusionspackage.json—lintnow runs ESLint thenlint:encoding;lint:encodingadded;audit:cireplaced withnode scripts/audit-ci.mjs;git:pulladded;release:patch|minor|majorandpublish:dryaddedscripts/reinstall.js— now spawnsnpm run audit:ciafter fresh install (ESM-style, inheriting stdio).editorconfig,.prettierrc.json,.vscode/extensions.json,.vscode/settings.jsonhad CRLF line endings; converted to LF as part of the encoding gate cleanupAudit note
NODE_OPTIONS=--use-system-ca node scripts/audit-ci.mjsreports 1 high advisory:serialize-javascript <=7.0.4viamocha. The installed mocha is 11.7.6 but the lockfile recordsserialize-javascript@6.0.2(a transitive dep that hasn't been re-resolved). Resolving requiresnpm update serialize-javascriptor a full reinstall — left for a follow-up since the instructions prohibited runningnpm installin this PR. Track as a known finding.Test plan
npm run lint:encoding— encoding gate passes (83 files scanned)NODE_OPTIONS=--use-system-ca npm run audit:ci— reports 0 critical, 1 high (serialize-javascript via mocha; see note above)node scripts/check-encoding.mjs— passes after CRLF normalizationmocha test/utils.spec.js) — 13 passingnpm test— typecheck + lint + build + mocha + c8 coverage🤖 Generated with Claude Code