Skip to content

fix(hooks): capability-commit gate no longer false-positives npm overrides keys as new deps - #983

Merged
artyhoo merged 2 commits into
stagingfrom
fix/prior-art-overrides-false-positive
Jul 11, 2026
Merged

fix(hooks): capability-commit gate no longer false-positives npm overrides keys as new deps#983
artyhoo merged 2 commits into
stagingfrom
fix/prior-art-overrides-false-positive

Conversation

@artyhoo

@artyhoo artyhoo commented Jul 11, 2026

Copy link
Copy Markdown
Owner

Follow-up invited by the maintainer after PR #980: the pre-push capability-commit gate false-positived npm overrides entries as new explicit dependencies and demanded a Prior-art: trailer on a pure security-maintenance commit.

Change

  • packages/core/hooks/checks/prior-art.ts:76-118isNewDepAdded() now tracks overrides / resolutions / pnpm blocks in the package.json diff (indent-based, resets at @@ hunk headers) and skips keys inside them: they force versions of packages already in the tree, adding no capability. Documented accepted residual: a hunk editing deep inside an existing overrides block without its opening line in diff context can still false-positive — the existing escape-hatch trailer covers that rare case.
  • packages/core/hooks/checks/prior-art.test.ts — 6 new cases: 3 skip cases (overrides, resolutions, pnpm.overrides) + 3 paired negatives (new dep after the block closes → still detected; nested braces inside overrides don't end the skip early; @@ reset → conservative re-arm). RED observed before the fix (4 failed), 104/104 after.
  • CLAUDE.md:38 — prose definition updated in the same commit, per its own "the prose definition and the hook stay in sync" contract (CLAUDE.md:36).

Incident evidence: PR #980 push was blocked with reason: new explicit dep in package.json on commit whose only package.json additions were the overrides security pins.

§1.7 Self-discipline check (REQUIRED if PR touches discipline-bearing files)

§1.7 Forward-check applied

The refinement itself lands as an executable artifact at the earliest reachable channel, not prose: the skip logic is enforced in the pre-push hook path (packages/core/hooks/checks/prior-art.ts:90-113) and pinned by paired-negative tests (packages/core/hooks/checks/prior-art.test.ts:112-176) that fail if the skip over-reaches (post-block dep still detected, hunk-boundary reset re-arms detection conservatively). The prose (CLAUDE.md:38) changed in the same commit as the hook, honoring the stay-in-sync contract.

§1.7 Backward-check applied

Class of this change = capability-commit detection semantics. Surfaces where the class occurs, each swept: packages/core/hooks/checks/prior-art.ts (the only detection implementation — fixed); .husky/pre-push + packages/core/hooks/ shell entry points (grep for a bash duplicate of the dep-detection: none — the bash predecessor was fully ported per prior-art.ts:2-4 header, SWEPT-CLEAN); CLAUDE.md:38 prose definition (updated in sync); packages/core/principles/11-build-first-reuse-default.test.ts (principle test consumes the SSOT register, not the dep-detection regex — grep shows no isNewDepAdded import outside hooks/checks, SWEPT-CLEAN); .github/workflows/audit-self.yml §7 trailer backstop (validates trailer presence on commits, does not re-implement dep detection — SWEPT-CLEAN). No other surface encodes "what counts as a new dependency".

…es/resolutions keys

isNewDepAdded() parsed the package.json diff line-by-line with no JSON-section
awareness, so keys added inside an "overrides" block matched the dependency-key
regex and flagged the commit as a capability commit. Incident: PR #980 (security
overrides for qs/js-yaml/markdown-it) was blocked at pre-push as "new explicit
dep in package.json" and needed the escape-hatch trailer.

Fix: indent-based block tracking skips keys inside overrides / resolutions /
pnpm blocks (they force versions of packages already in the tree — no new
capability). Tracking resets at @@ hunk headers; a hunk editing deep inside an
existing overrides block without its opening line in context remains a
documented accepted residual. CLAUDE.md prose definition updated in sync per
its own "prose and hook stay in sync" contract.

Tests: 6 new cases (3 skip cases + 3 paired negatives incl. post-block dep,
nested braces, hunk-boundary reset), RED observed before fix, 104/104 green.
prior-art.ts is a shipped file — its hash feeds the byte-identical install
baselines (8 stacks×modes). SNAPSHOT_MODE=capture regen; each baseline diff
is exactly the one prior-art.ts hash line; byte-identical.test.sh 2/0 green.
@artyhoo
artyhoo merged commit 0dede61 into staging Jul 11, 2026
39 checks passed
artyhoo added a commit that referenced this pull request Jul 11, 2026
… attention-only) (#984)

Invited follow-up from the 2026-07-11 reviewer verification: the «prose definition and the hook stay in sync» promise at CLAUDE.md:36 had no enforcement — verified as a `#hope-as-gate` (attention-is-not-a-mechanism.md §1): zero automated checks referenced the capability-commit definition (searched principles/, audit-self/, scripts/, workflows under three phrasings).

## Change

`packages/core/hooks/checks/prior-art.test.ts` — new describe block making the overrides-exclusion clause of the sync executable:

- parses the `nonDepBlockRe` alternation out of `prior-art.ts` source; asserts every skipped block name is present (backticked) in the CLAUDE.md explicit-dependency bullet;
- canonical-trio floor (`overrides`/`resolutions`/`pnpm`) guards against silently narrowing the regex;
- paired negatives: stale prose missing a code block name fails containment; a moved/renamed bullet makes the extractor throw (loud, not silent-pass).

RED observed before trusting the test: mutating CLAUDE.md (dropping `` `resolutions` ``) → 1 failed; restored → 108/108.

Channel: runs inside `test:hooks` → pre-push + CI (audit-self), i.e. the check fires earlier than the human-review channel it replaces.

Scope note: the sync is made executable for the block-exclusion clause specifically (the clause added in PR #983). The rest of the prose bullet (semver-prefix list, LOC thresholds) remains attention-synced — extending coverage is possible but was not invited; noted as future candidate.

## §1.7 Self-discipline check (REQUIRED if PR touches discipline-bearing files)

### §1.7 Forward-check applied
The rule this PR strengthens («prose and hook stay in sync», CLAUDE.md:36) now fails at the earliest reachable channel instead of relying on reviewer attention: `packages/core/hooks/checks/prior-art.test.ts:180-247` executes on every `test:hooks` run (pre-push step + CI audit-self job). Paired negatives are non-vacuous — RED was observed against a real prose mutation before the test was committed.

### §1.7 Backward-check applied
Class of this change = making an attention-only sync promise executable. Sibling surfaces where the same class occurs, swept: CLAUDE.md:38 LOC-thresholds + semver-prefix prose vs `prior-art.ts` `loc()`/dep-regex (GAP-KNOWN — deliberately out of invited scope, recorded above as future candidate); `packages/core/principles/09-doc-authority-hierarchy.test.ts` (doc-structure checks exist but none cover capability-commit definition — confirmed by grep, SWEPT-CLEAN for overlap); `.github/workflows/audit-self.yml` §7 trailer backstop (validates trailers, not the definition text — SWEPT-CLEAN); `packages/core/audit-self/audit-ai-docs.ts` (ai-docs drift scope, no capability-commit references — SWEPT-CLEAN).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants