Skip to content

Move what the bundle imports into dependencies, so the blocking audit examines it - #608

Merged
MongLong0214 merged 2 commits into
mainfrom
fix-606-audit-scope
Aug 13, 2026
Merged

Move what the bundle imports into dependencies, so the blocking audit examines it#608
MongLong0214 merged 2 commits into
mainfrom
fix-606-audit-scope

Conversation

@MongLong0214

Copy link
Copy Markdown
Owner

Closes #606.

npm audit --omit=dev is the blocking half of the #545 audit split. The premise: dist/ is what users receive, so that surface must be at zero vulnerabilities. The implementation contradicted it — every runtime package (@modelcontextprotocol/sdk, ajv, ajv-formats, commander) was declared under devDependencies, so --omit=dev audited an empty set.

Moved the four packages src/ actually imports into dependencies. js-yaml stays dev — it is used only by scripts/bench, never bundled.

With the audit examining the real set, it found two real advisories: fast-uri (via ajv, high) and hono (via the MCP SDK's node server, moderate). npm audit fix resolved both, no source change needed.

Verified: npm audit --omit=dev --audit-level=low finds 0 after finding 2; tsc clean; 129/129 across mcp/capture-pipeline-e2e/validate; dist rebuilt on linux/amd64 matches byte for byte.

@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown

CommitLore — record lint

Trailers: clean — 2 commits in origin/main..aa2efcc575850332274ee356507a09b3d7f89ca7
Active constraints: 177 limits · 358 ruled-out · 96 warnings — from 214 records over 4 changed paths

Active constraints for the paths this PR touches

Limits (177)

  • r-provsha1 6d82fcc — is a git object id — 4 hex digits (git's shortest abbreviation) through 64 (a full SHA-256), either case
  • r-cap543ex 2197283 — validate's exit codes shipped in v0.8.1 and must not move
  • r-answerown1 3547382warn distinguishes ours from not-ours by the command string, and does not execute anything -- a wrapper that really is a CommitLore server still reads as unverified, which is the safe direction but not a probe
  • r-pretag01 86e0153registers_commitlore reads the key, so a config that registers under a different key -- a host with its own naming -- still reads as unregistered and is wired again
  • r-engfloor01 fe83524 — the parser covers the range shapes npm packages actually publish -- comparators like >=22 <23, and pre-release identifiers, are read by their first version and not by their bounds
  • r-readyhosts1 9db3c4d — the new jobs establish that an install runs and answers on those hosts, not that every command behaves identically there
  • r-dropfake01 06961d3 — the runtime's presence proves this installer wrote the directory, not that its contents are unmodified since
  • r-secondcopy1 01ebee5 — the budget bounds the two scans, not the command -- process startup, path resolution and rendering still sit outside it
  • r-staleclaim1 59cb5d9 — withholding uses the same pattern table as every other route, so a payload that trips nothing still passes; this closes a route that had no grading at all, not the heuristic behind it
  • r-nodefloor1 f4c924f — this bounds the version, not the feature -- a Node that ships node:sqlite behind a flag, or removes it, is not detected here
  • r-codexunver1 980d747 — presence is read from the marketplace name, so a Codex that reports neither a source nor a listing this can parse is treated as absent and one is added under a name that may already be taken
  • r-release081 ffe702a — the capture half reaches a host that surfaces MCP instructions; one that ignores that field still needs --agents-md, and nothing detects which kind a host is
  • r-mcpproc01 db1363d — this establishes that a host which surfaces MCP instructions can capture without a skill; a host that ignores that field still needs --agents-md, and nothing here detects which kind a host is
  • r-observed01 43cfa5e — existence is not identity -- a path that resolves to something other than this tool still reads as a working registration, which is doctor reports a registered MCP command as working without establishing its identity #572
  • r-ceiling01 543453b — this bounds the scan and not the command -- process startup, path resolution and rendering are outside it, so a repository whose single cheap pass is slower than the budget still exceeds it by that much
  • r-clocktest1 6ac2b44 — the injected clock proves the loop stops and resumes correctly; it does not measure that a real budget corresponds to any particular wall-clock pause, which stays a measurement rather than a test
  • r-hookbudget1 e09014c — the budget bounds the wait, not the answer -- a repository large enough to trip it keeps getting a partial view until somebody runs init, and the notice is the only thing that makes that visible
  • r-scanall1 62a6fbf — the scanner remains a heuristic, so this closes the exemption and not the gap behind it -- a payload that trips no pattern still reaches the agent
  • r-structk1 a7bee10 — this closes the exemption, not the heuristic behind it -- a payload that trips no pattern still passes, and the scanner remains a speed bump rather than a boundary
  • r-ownfail01 8de1326doctor can say the setting is unreadable and cannot say what its author meant by it, so the repository is held to the stronger mode until a person decides
  • r-expwall01 e7ddd92 — the cache cannot notice an expiry that falls between two reads inside the same day -- a record expiring at noon is still delivered until the day rolls over, which is the granularity the determinism is bought with
  • r-codexerr1 a6d0fab — the first line of Codex's output is not always the cause -- a wrapper that prints a banner before its error will have the banner reported instead, and the full output is still only visible by running the command directly
  • r-authdir01 ae2a66f — in the default mode a directive establishes that the commit's author string matched a configured one, and nothing about who produced the commit
  • r-authdir01 ae2a66f — in signature mode a verified signature establishes that a key the verifier trusts signed this commit -- not that its holder has authority over this repository, and not that the record's content is true or safe
  • r-mcpdir01 a9886b5 — neither route can tell a caller whether the trusted-author configuration reflects anyone's actual identity -- it reports what the repository decided, and the decision is a local git config value
  • r-codexplug e5fe95a — a plugin can put a skill in front of a session; it cannot make the session follow it, and nothing here reports whether one did
  • r-hermesx01 2eb8176hermes skills inspect resolves remote sources only in this Hermes version, so discovery was verified through hermes skills list --source all in a fresh isolated profile rather than from inside a live conversation; that a session then follows the procedure is not something an installer can establish
  • r-codexwire 955f290 — an instruction file is guidance, not enforcement -- a host may ignore it, summarise it away, or never read it, and nothing here can tell whether any session followed the procedure
  • r-initmcp1 e601ad3 — this registers for hosts that read a repository-scoped .mcp.json; a host keeping its configuration elsewhere still needs its own installation, and this cannot tell whether any host ever loaded the file
  • r-cdeb10reg 48bd5a8 — wrong-path viability, deterministic oracle feasibility, code disclosure, bounded implementation, and unproven ordinary or benchmark authorship cannot be decided from history and remain undecided for human review
  • r-mintid01 1e5f500 — deterministic minting can reserve only identities visible in this repository; independently diverged history can still introduce a collision
  • r-notes512a ce937c9 — the observation is as old as the last doctor --fix; a mirror pushed upstream after it is not visible here, and an empty answer will read as a true empty until the next probe
  • r-autotrue2 6cc5032 — a host may be registered and never call the tool, or be configured outside the repository entirely, so this distinguishes wired from unwired and never observed from unobserved
  • r-autotrue1 70b7e06 — a host integration may still be installed or selected outside the repository, so operators must ensure it supplies the session transcript before committing; the core cannot observe or enforce that host-side action
  • r-cdeb08an 60db89f — the paired bootstrap describes resampling stability within these five frozen repositories and thirty frozen tasks, and says nothing about any other repository, task or agent population
  • r-coldpath1 0412f81 — a genuinely cold fallback still reads the whole history once, because repository-wide lifecycle folding cannot be scoped to a path without changing what the answer means
  • r-coldpath1 0412f81 — nothing outside index and init builds the index now, so a repository whose derived file was deleted stays on the scan path until one of them is run
  • r-autoswitch b8497b8 — the prompt defaults to yes and a bare Enter takes it, so a reflexive Enter costs a team-wide consent — the file is committed, and every clone captures with nobody in the loop until someone runs auto off
  • r-unattshadow b7b532a — together the two features measure how often an unattended pipeline would have written, and remove the asking from the writing -- neither half can say whether what gets written is worth a reader's attention, so shadow's number for an unattended repository is a volume, not a value
  • r-unattended511 f6679e1 — with nobody in the loop, the pipeline decides on its own what is worth recording, and every record it keeps spends a future reader's attention without asking anyone first -- the switch is a repository consenting to that cost, and nothing in this change reduces it
  • r-shadow511 d093bef — shadow measures commits whose transcripts are gone, so its numbers describe the substitution of a committed message and patch for a transcript -- they say nothing about what capture would record over a live session, and no shadow output may be read as a pipeline baseline
  • r-mcpexit506 f1b1fb0 — a process killed with SIGKILL still writes nothing, so the log shows a start with no exit -- that case is inferred from the absence of a line rather than reported, and stays the way MCP tools for commitlore vanish mid-session (ToolSearch returns zero results despite server reported connected) #424's original observation had to be made
  • r-demostory505 8016424 — the demo is one scenario, so it shows supersession and not expiry, path scope, or trust grading; a reader who wants those still has to read past the image
  • r-filters471 c7572f6 — a filtered run reports honestly about what it ran and says nothing about what it skipped, so a repository whose only failure sits outside the selection reads as healthy-for-the-selection with no hint that the unexamined rows exist
  • r-envelope469 0162b73installSource is declared and derived per surface only where a test asserts that surface; an unasserted surface reports unknown rather than a guess, so the field is honest and incomplete rather than complete and unverified
  • r-effects476 43eb4aaenv and the clock are injected but process.cwd and the filesystem are still reached for directly inside some checks, so a check that reads a path can be pointed at a fixture but not at a purely synthetic tree
  • r-headline470 55b810cinit keeps the checks-only renderer, so the headline a doctor run shows is absent from the install path where a first-time user is most likely to meet a finding
  • r-budget472 8ea15f1 — 13.2x headroom over the measured baseline is sized to survive a contended shared runner, so it catches an order-of-magnitude regression and would not notice doctor becoming three times slower
  • r-dsplit467 b24e371 — the split is by responsibility, not by dependency direction -- runner, registry and renderer all still reach into the model, which is correct for a shared vocabulary and would not catch a model that grew behaviour
  • r-collapse466 d24a284 — only two edges are declared -- inject-version on inject-runtime, and the §2.2 checks on the capture chain -- so a dependency nobody wrote down still surfaces as an independent finding
  • r-evidence465 e1a3c92 — evidence answers what was observed, not whether the observation was the right one to make -- index ingests any key: value line as a trailer; doctor reports 106 records where git has 0, and context serves commit subjects to the agent #335's wrong count would now be visible in a field rather than prevented
  • r-queryroute 4ae1f6f — the sweep covered ?? against an options field in src/commands, which is the shape that produced both defects; an option whose default is consumed some other way would not have shown up
  • r-rel071 af8e0ab — 0.7.0 stays published with its notes amended to name the defect at the top; retracting a tag people may already have installed trades a known-bad version for an unknown one
  • r-rel070 d4a4d8b — the README's behaviour claim now rests on M5 while the generated numbers block beneath it still publishes M4, which is The README's generated numbers block still publishes M4; M5 measured the thing the README leads with #480 rather than a release-time edit
  • r-skipreason 85aa8d6 — the union has six members because ten sites needed six, and the next check that skips will need a seventh rather than one of these stretched to fit
  • r-registry463 ddf5592 — the registry is data but nothing filters it yet, so the ordering guarantees are tested and unused until the --only ticket
  • r-checkmodel 9cbed57 — evidence is {} on every row until the ticket that populates it, so the field exists and proves nothing yet
  • r-doctorpend 458bcec — the check reads staleness, so a capture whose base commit is still HEAD reports ok even if it has been waiting long enough that nobody remembers preparing it
  • r-trust415 a030e93 — this changes what a fresh install delivers, so M1 and M5 remain measurements of [claim]-graded delivery and their numbers do not transfer to the directive path
  • r-cdebver01 ce7b278 — the schemas freeze protocol 1.2.0 constants -- thresholds, matrix size, category names -- so a protocol change is a schema change and CI notices
  • r-mcplife424 8cd3c6d — the tool registration that was lost belongs to the client, so nothing in this repository can detect the loss from inside a session or restore it
  • r-capmode30 40818c2stage cannot check consent, so auto records what is certainly true -- no prompt was shown -- instead of asserting what it cannot know
  • r-drafted30 b126176 — a commit message is immutable, so a drafted record is never upgraded in place -- promotion is a later record that Supersedes it, and that half is not in this change
  • r-amendid430 4c450ebcommit-msg gets no argument, environment variable or ref that distinguishes an amend from an ordinary commit
  • r-hookver433 a3b92d7 — nothing here can update anything -- the plugin cache is the client's, so the only move available is to say what is true
  • r-binx428 b9d1ea8 — the allowlist accepts .mjs/.js paths, which are exactly the files most likely to carry a shebang and no execute bit
  • r-recurse422 418734c — git runs pre-push on every push including one a pre-push hook makes, so any push from inside the hook must opt out of hooks explicitly
  • r-busy420 9555569 — a full rebuild on a large repository takes longer than any timeout a hook can afford to wait, so the scan fallback stays reachable by design
  • r-sync416 deb21d2 — git neither fetches nor pushes notes by default, so a mirror only moves when something configures or invokes it
  • r-mention408 ec314cd — paraphrase space is unbounded and this table cannot see semantic rewording, so blocked remains a speed bump and the grade remains the load-bearing control
  • r-schema406 22b2c35 — an index is derived state with no migration path, so a meaning change can only be handled by discarding the file
  • r-note409 0dff3e4 — the notes ref is an ordinary ref with no signature requirement, so authorship there is a claim about who wrote the text and not proof of it
  • r-backfillclosed 00de5fa — the guard reads the mirror state at invocation, so a fetch completing mid-run is not observed
  • r-initunfetched 889d191 — it reports the state as it was before init ran, so a mirror fetched between the capture and the report would be named wrongly; that window is the four steps of one command
  • r-mirrorunread 8e4bdc5 — the caveat can only fire where notesAvailability returns unfetched, so a refspec added after cloning and never fetched through still builds silently -- the distinction config alone cannot carry, recorded on that function under r-fetchowed
  • r-m5analysis 3450656 — the script enforces the row count, not the identity of the rows; a run that produced 1,160 rows under a changed harness would satisfy it, which is what harness_commit and dist_digest on each row are for
  • r-benchscope 67f4375 — nothing checks the shape of the eight metric-row files. This gate names them and steps over them, and bench/deterministic/types.ts is the only definition that family has -- there is no JSON schema for it, so drift on that side is still invisible
  • r-benchscope 67f4375 — the pre-provenance exemption reads started_at, which is data on the row rather than a fact about the file. A row that misreported it would be held to the shorter list of requirements; that is a deliberate falsification rather than the omission this fixes, and nothing here detects it
  • r-pinskew 007ccbf — the comparison reads the package.json above the recorded path rather than running it with --version, so a pin whose manifest and bundle disagree is reported by its manifest
  • r-3c9d52 dc9e769 — the sweep is two git log calls per path and the delivery phase runs git log --follow on every tracked path, so a full run over the four externals is hours rather than minutes on one machine
  • r-rel060 e999b9d — the install one-liner in all four READMEs now points at a tag that does not exist until this is tagged, so the window between merging to main and pushing v0.6.0 is one where the documented install is broken
  • r-pipesplit b4fa571 — test/dogfood.test.ts validates every record in this history, so a new violation class is only available if it rejects none of the 620 Ruled-out: values already written
  • r-gcunstageable 5cd6b8f — ADR-0021 fixes the pending format and stamps expires_at at stage only, so giving these phases an expiry earlier is a format change rather than a fix
  • r-gcunstageable 5cd6b8f — gc runs only when capture gc is invoked -- nothing schedules it, so a leaked file goes at the next run rather than at the 24-hour mark
  • r-gcunstageable 5cd6b8f — staleness is derived from base_head against HEAD; a transaction whose staged diff moved while HEAD did not is equally unstageable and is still kept, which is the conservative half of the same test
  • r-gcunstageable 5cd6b8f — a staged transaction that is never applied is still kept for ever -- the hook skips it once expires_at passes and gc protects the phase -- which is a separate leak this change deliberately does not touch
  • r-secondtie 998bf18 — committed_ts is %ct at one-second resolution and the index stores no ordinal that orders two commits inside one second, so a tie on that path can be made deterministic but never topological
  • r-dedupviol 18ad9c1 — the key includes line, so two detectors that locate one finding differently -- one with a line, one without -- would still print it twice; today both resolve the line through the same locateTrailerLines/lineForViolation path
  • r-owntmproot 6543870 — the demo still defaults to the shared tmpdir, so concurrent commitlore demo runs still create sibling directories there -- that is deliberate, and it is safe only because nothing now asserts over that namespace
  • r-diffdefault 4ac8163 — the test reads the option string out of the source rather than out of --help output, so a change to how commander renders descriptions would not be caught
  • r-shallowlast 0913821 — the spawn still happens once per validate that has a dangling ref, which is the case where the answer is actually needed
  • r-exitonemeans 89f7af8 — a shallow clone cannot tell a reference that resolves below the boundary from one that resolves nowhere, so neither verdict is available and the check can only name the question it could not answer
  • r-failopen abc54ea — with the gate installed and no CLI resolvable, commits are still refused -- that is the one hook holding a verdict back, and this change does not reach it
  • r-notereach 1e72a28 — reachability is decided against HEAD alone, so a record mirrored onto a live branch that is not checked out is not served until it is
  • r-fetchowed 11f04b4 — config alone cannot separate a refspec that was fetched through from one that was only written, so the availability verdict cannot carry that distinction
  • r-guarddisclose 8a4d0c7 — a disclosure asserted by tool name covers the tool that is named, and the ADR's requirement is about every surface that exposes the behaviour
  • r-refspecfetch 936d206 — configuring a refspec is not fetching through it, and a state machine that conflates the two turns its own remedy into a way of hiding the problem
  • r-actionsleak a6fbb4b — a code path that no test and no first-party workflow exercises is the one an outside adopter takes by default, and its absence from CI is not evidence it is unused
  • r-actionsleak a6fbb4b — a trust label the caller must act on is worthless unless the value it describes is actually withheld at the point the data is built
  • r-release051 19810d2 — the hook is written at install time, so no release repairs a repository that already has one; every release touching hook behaviour has to restate what does
  • r-convertreadme e12c816 — a README claim about the default workflow is only true if the shipped skill performs it, and the skill currently requires the user to name CommitLore first
  • r-recordgate335 a83ebe3 — a denylist cannot decide whether something is a record, because the keys nobody has claimed are unbounded; that question needs the vocabulary, and the two must not be answered by one filter
  • r-recordgate335 a83ebe3Verified: in a release note is indistinguishable from Verified: in a record, and no context signal separates them without risking real records
  • r-draftfirst329 0506a5d — a usage error that names the wrong input costs an invocation and points the reader away from the fault; ordering is part of the message
  • r-release050 ad402c7 — the hook is written at install time, so a corrected release never reaches a repository that already has one; every release fixing hook behaviour has to say what repairs an existing install
  • r-uninstall1123 4ddac0d — the installers write five agent configs, not the four the ticket's measured inventory lists; the fifth is Windsurf at .codeium/windsurf/mcp_config.json
  • r-uninstall1123 4ddac0d — opencode's entry is shaped differently from the other three -- the command is an array -- so one recogniser cannot serve all of them
  • r-uninstall1123 4ddac0d — a checkout is 1366 files at this head, not the 1206 the ticket measured at 6e1d46d; any assertion bound to that count is stale
  • r-winpath1127 bdf4ac0 — the stub is written to .git/hooks at install time, so a repository installed before this fix keeps the old text and must re-run commitlore hooks install; installing a corrected release is not enough
  • r-winpath1127 bdf4ac0${dir%/*} returns its input unchanged when no separator remains, so a loop that tests for emptiness never terminates at a drive root
  • r-winpath1127 bdf4ac0 — neither dirname nor ${var%/*} finds a parent in a backslash-separated path; both answer .
  • r-t1110policy 9e7b37a — only a repository-local policy file is read -- PRD-F13 requirement 11 permits either one location or a stated precedence, and an ambiguous precedence is worse than a missing feature
  • r-rel041notes 71efe1f — 0.4.1 makes the installer honest about a verification it cannot complete rather than fixing the kill, so an upgrading user may still see the unverified message instead of a version
  • r-rel040notes 5d57a72 — the 26.3-point density gap quoted in the notes is measured at this head and will drift with merge volume; it is illustrative of the denominator problem rather than a stable figure
  • r-gcwiring f21f28e — the guard against this class is four CLI-level tests; nothing structurally prevents a future subcommand from colliding with a parent option again
  • r-flake221fix 2b21ed9 — checkInjectRuntime ENOENT does not block init
  • r-lb0xl89a 236229e — the static contract uses explicit placeholder text for TRANSCRIPT and DIFF rather than omitting those sections, because the prompt text references them by name
  • r-c44a1edb 71f5197 — src/core/pending-gc.ts -- gc must never remove a staged or applied file regardless of expiry; T-1018 post-commit may still finalise them
  • r-0ll5sxk0 2853a22 — consumption happens after commit succeeds, exactly once; consuming earlier loses the record on failed commits, consuming twice lets one record attach to two commits
  • r-t1009stage b5fcf4e — the nonce pattern check bounds what a caller can send, but a caller holding a valid nonce for its own repository can stage repeatedly until the record is consumed
  • r-t1005gates 15421c0 — policy identity is compared as a hash, so a policy edit that produces the same hash is indistinguishable from no edit
  • r-t1006cli d22580b — the command composes the phases in one process, so a crash between verify and stage leaves a verified pending record that only garbage collection will clean up
  • r-t1008mcp ab00b54 — src/mcp/server.ts: readOnlyHint must be false for verify_capture — the tool writes verification results to the pending transaction
  • r-t1007mcp b6ef112 — commitlore_prepare_capture uses readOnlyHint: false because it writes a pending transaction
  • r-t1013verbose205 294ec82 — --verbose only selects the formatter; it does not change runInit logic, step order, exit codes, or --json output
  • r-t1022sig e0c641d — the first pushed attempt asserted one header string in the test and built another in the formatter; CI caught the mismatch and the formatter was aligned to the asserted string, which is the one that states the measured figures on the output surface
  • r-t1022sig e0c641d — focused-test evidence for this change is CI's, not local; test/guard.test.ts reports zero tests and stalls on this machine at dev with no changes applied
  • r-t1024bc 023f6d9 — response shape is exactly five fields per CEO amendments and ADR-0020 confidence-separation constraint | adding a sixth field or letting context inherit guard_confidence violates the acceptance criteria
  • r-t1011demo 1c0fc0c — the scene is one fixed pair of decisions, so it demonstrates the mechanism rather than measuring how often it matters
  • r-t1020desc dd12b42 — the test asserts on the exact precision and recall figures; a future re-measurement changes both the description and the test
  • r-t1020desc dd12b42 — the first attempt's Record-Id used hyphens, which the r-[a-z0-9]{6,} format rejects; both the lint action and the dogfood test caught it
  • r-initresult204 ea4a08e — --verbose flag not wired yet (T-1013)
  • r-t1030diag 344ada0 — the heuristic uses a regex on the first line of stderr; an error that prints no stack frame and no "not found" string will be reported as cause unclear even if a human could classify it
  • r-fix191amb cb94448 — the same-message test still passes by accident of collectRecords returning one record per commit; the divergent-notes test is what exercises the actual suppression path
  • r-fix187val 40f2436 — the tip-scan adds one full-history git-log call per range invocation; acceptable for a lint-time check but visible in benchmarks at scale
  • r-dupsucceed 6f77fcf — supersession is resolved within one repository's history, so a record superseded in a fork that was never merged still grades as current here
  • r-dupsuccorder f46c02d — a successor before a later duplicate cannot resolve that later collision
  • r-dupsucc729 5a6b238 — published dev history cannot be rewritten
  • r-valdup145 bcb9563 — the same-message check sees only the message, so two commits each declaring the same id separately are still caught by the reference check rather than here
  • r-convtrail150 57e89d2 — the denylist answers a different question from isRecordKey's allowlist, so a conventional trailer this protocol later claims would need removing from one and adding to the other
  • r-epipe2026 d9ee9ff — spawnSync may report EPIPE after git exits while its input pipe is being written
  • r-doctorepipe 0420f5c — the new deterministic tests exercise evaluateInjectRun with a synthetic spawnSync result rather than forcing the live race, because no payload this check sends is large enough to make the write block deterministically the way an artificially large one does in the reproduction above
  • r-init107 f485f07 — the generated dist artifacts are rebuilt from TypeScript source
  • r-survsplit e73aed5 — path-reachability is measured against git's rename detection, so the figure moves with git's similarity threshold rather than with anything here
  • r-probepath 51f6446 — the probe still only runs a command it recognises, so a hand-edited but equivalent hook reports not-checked rather than a verdict
  • r-doctorprobe ed94491 — the probe runs only a command it recognises, so a user who hand-edits the hook into an equivalent but different form gets not-checked rather than a verdict
  • r-rel021a a79e350 — v0.2.0 remains on the remote with no release attached
  • r-f61a2c 9114cf0 — the matcher remains deterministic and lexical; no embedding or semantic service is available to distinguish paraphrases
  • r-init96a 913c7e3 — doctor's own exit-code contract treats warn as non-fatal by design (SPEC §10, commitlore-setup skill) — init deliberately diverges from it for its own summary, and that divergence is the one thing most likely to look like a bug on a future read of this diff
  • r-fix92dupid 7f41a6e — cross-references between two blocks declared by the same commit (a Follows:/Supersedes: naming a sibling block's id) are still reported as dangling rather than resolved against the sibling -- unchanged from before this fix, and called out in validate.ts's own comment as future work
  • r-fix93pkg 9c4a396 — package.json remains a development artifact (build, typecheck, dependency floor) -- it is not read as a distribution manifest by anything in this repository
  • r-relinstall c6e1d04 — never tested against the real GitHub release infrastructure (no release exists yet — that is the owner's action) — verified against a locally built SEA binary, a hand-made SHA256SUMS, and a local HTTP server standing in for GitHub's release-asset redirects, which is everything this repository lets a change verify before a tag exists.
  • r-parsemulti 6d39d25parse has no git-commit context (no sha, no notes mirror) — its identityCollision check is local to the one message being parsed and cannot detect a Record-Id that collides with something already committed elsewhere in history the way context's fold does.
  • r-multirec01 92aeb24 — parseRecordBlocks only recognizes a non-final block by its declared Record-Id, so an unidentified inherited record beyond the first stays recoverable in the plan that computed it but not in a later re-parse of stored text; squash-preserve orders unidentified blocks last so the common case (at most one) is unaffected.
  • r-multirec01 92aeb24 — multi-block reference checking (Follows:/Supersedes:) does not resolve one block's reference against a sibling block declared by the same commit; each block is still checked against every earlier commit in history.
  • r-exit065 e545dee — any new command's exit codes must be drawn from SPEC §10, not invented locally
  • r-fix70a1 d707fc7 — one encoding layer and explicit lexical forms in the four published languages; semantic paraphrases, nested encodings, and split payloads remain outside coverage
  • r-shwt66 5efa206 — git rev-parse --git-path may return a repository-relative path, so resolve it against cwd
  • r-merge66 40e7987 — Generated dist files were resolved only by npm run build and npm run bundle
  • r-fix760 fb8ba45 — Git remains the authority on trailer recognition; diagnostics must not loosen the parser
  • r-refint74 572f573 — validate cannot perform conservation checks because it has no before state
  • r-warn75 24c7cc8 — exit-code semantics remain owned by guard's exit 2 means blocked; everywhere else in the same CLI exit 2 means bad usage #65
  • r-shallow66 60a8659 — a depth-1 clone can only inspect its reachable commit history
  • r-doctor72 996bcde — generated dist artifacts must come from npm run build and npm run bundle, not a hand merge
  • r-fix067 a915af0 — PreToolUse hook failures must always exit 0 and never change stdout's hookSpecificOutput contract
  • r-fix063 0b8c496 — doctor performs remote probes; an unreachable remote reports could not verify instead of ok
  • r-det058 695cdf6 — the suite must need no model, agent, network or uncommitted benchmark input
  • r-fix053 ecc4b90 — QueryResult.notes remains repository-level availability and is independent from whether one record was mirrored
  • r-fix055 43b40f8 — harvest-verify makes no model call, so semantic entailment is outside its contract
  • r-fix054 664d4e2 — notes-only metadata must survive folding; a mirror is one record, not two
  • r-fix056 55cb8bc — blocked output may retain only validated structural values that cannot carry prose
  • r-7a3e91 cf859e4 — better-sqlite3 stays external because it is native — the bundle degrades to --no-index without it, which only works because r-6f2a08 made that load lazy first
  • r-4a8e15 49e12c7 — git's grammar requires a subject before a trailer block, so a serialized block is not by itself a parseable message
  • r-7e5f02 e5f5e00 — npm installs through an engine mismatch, so the ecosystem's own signal cannot be relied on to stop anything
  • r-5a8c04 c46a577 — git owns the definition of a trailer block, so any behavior we cannot get from interpret-trailers is behavior we must not invent
  • r-c0f4e2 3d249cd — npm gitlore is held by an active same-domain CLI, so the owner's first-choice name was not available
  • r-b2e7f1 00d348d — Parsing must delegate to git interpret-trailers -- reimplementing the block rules would drift from the rest of the git ecosystem

Ruled out (358)

  • r-provsha1 6d82fcc — generating the schema pattern from types.ts at build time | there is no schema codegen step, and verify.sh reads the JSON file directly; a test that the two strings are identical is the lock this repo already uses for SPEC vs types
  • r-provsha1 6d82fcc — making grade.ts load the JSON schema | the hook path must not grow an ajv dependency to answer a question a regex already answers
  • r-cap543ex 2197283 — failing the hook when capture returns 3 or 4 | a hook that aborts a commit because the recorder broke is worse than a missed record
  • r-cap543ex 2197283 — a custom Error subclass for each kind | the repository forbids class X extends Error; a marker property is the same shape as commitloreMissingInstalledFile
  • r-5c84a1 b3eb1b4 — excluding applied alongside consumed | the record hash is stamped before the commit object exists, so an aborted commit leaves an applied transaction whose decision really was lost
  • r-past585 f88193f — add higher than and caused to REJECTION_MARKERS | they match a proposal that names a threshold and an investigation that asks what caused the spike, which is the bar this ticket said not to move
  • r-engfloor01 fe83524 — adding semver as a dependency to parse this | one regex over a handful of published shapes does not justify a runtime dependency in a check that runs before install
  • r-mcpproc01 db1363d — keeping AGENTS.md as the default carrier | it reaches only repositories that adopt the convention, and it puts a hundred lines of protocol into a file the repository owns and commits
  • r-hookbudget1 e09014c — building the index from the hook | that is the unbounded rebuild the recorded design gives to index and init, and doing it on the edit path would trade a bounded pause for an unbounded one
  • r-scanall1 62a6fbf — keeping validateRecord and bundling ajv into the hook path | the hot path should not grow a dependency to answer a question a regex already answers
  • r-structk1 a7bee10 — validating whole records at read time and discarding those that fail | history is not editable, and a reader that drops malformed records would silently lose real decisions instead of grading them cautiously
  • r-ownfail01 8de1326 — treating a malformed value as an error that stops the command | grading runs on the edit path, and refusing to answer there costs more than answering under the stricter rule and saying so
  • r-expwall01 e7ddd92 — documenting that expiry follows repository time | it is honest and it abandons the property, and the property is the reason the field exists
  • r-authdir01 ae2a66f — requiring signatures by default | it would demote every existing repository's records for a risk this project is not currently exposed to, and a silent capability removal on upgrade is its own kind of dishonesty
  • r-authdir01 ae2a66f — deleting the directive tier to make the claims true | the tier is how a record says it is a constraint, and removing it would resolve the wording by removing the feature
  • r-mcpdir01 a9886b5 — having runQuery read the trusted authors itself | it would fix these two call sites and silently change every other one, including tests that mean to grade without trust
  • r-relfix01 96102b4 — keeping "floor, measured" and footnoting it | the sentence is the claim a reader takes away, and a footnote that contradicts it is worse than either alone
  • r-hermesx01 2eb8176 — writing the bundle into the profile directory and regenerating its manifest | it would be undone by the next sync and disagree with the manifest until then
  • r-codexwire 955f290 — a Codex-specific integration | the instruction surface is shared, and writing one integration per host would leave the same gap open for the next five
  • r-initmcp1 e601ad3 — writing into a user's host configuration from init | a repository may describe itself, but reaching into the machine that opened it is not the same act and not one an init should take unasked
  • r-mintid01 1e5f500 — random or clock-based identities | a retried capture would give one decision a different identity
  • r-notes512a ce937c9 — probing the remote from the query path | context runs before every edit and an edit must not wait on a network round trip
  • r-notes512a ce937c9 — treating a covering refspec as evidence the remote was consulted | the refspec says what this clone would fetch, never what a remote has
  • r-autotrue1 70b7e06 — initiating capture from a Git hook with the staged diff | a diff cannot supply the host transcript or establish that a decision was made
  • r-cdeb08an 60db89f — discovering row files under the result directory | an unregistered file contaminates the matrix while leaving every stopping rule looking satisfied
  • r-cdeb08an 60db89f — filling or dropping unavailable usage | both change a token aggregate without evidence, one by inventing a number and one by redefining the population
  • r-coldpath1 0412f81 — applying --limit before the lifecycle fold | it would bound the cold work and silently change which records survive supersession
  • r-coldpath1 0412f81 — serving a stale index when catching it up is not possible | a fast wrong answer is worse here than a slow right one; the fallback stays fail-closed and git remains the authority
  • r-autoswitch b8497b8 — enabling by default where no terminal can answer | the file is committed, so a CI run would hand itself a team-wide flip nobody ever saw asked
  • r-autoswitch b8497b8 — rewriting a policy file whose effective setting already matches | the bytes would change while the policy did not, and the identity hash would report a policy change that never happened — the false positive the hash exists to avoid
  • r-autoswitch b8497b8 — asking the question when a policy file already exists | the answer cannot change anything, and a yes that does nothing reads as consent being taken rather than given
  • r-unattshadow b7b532a — keeping the unattended branch's inline prepare body | the shadow refactor exists so both entry points share one side-effect-free half, and two copies of the same hashing and policy logic would drift the first time either changed
  • r-unattshadow b7b532a — checking unattended consent in the live path only | the refusal for mode "off" already lives in the shared half of prepare, and a consent check that guards one door but not the other is no guard for the next entry point added
  • r-unattended511 f6679e1 — putting unattended into the default policy identity hash | the default is a fixed false, and hashing it would refuse every capture in flight across the upgrade in every repository that never opted in -- a policy change that never happened, the exact false positive the hash exists to avoid
  • r-unattended511 f6679e1 — checking consent at stage instead of prepare | stage receives a nonce and nothing else by design, and cannot observe whether a declaration was made; consent checked nowhere it can be observed is checked nowhere
  • r-unattended511 f6679e1 — ignoring "unattended": true outside auto mode | a consent the mode cannot honour would become a silent no-op, and a user who believes a setting applied is worse than one told it did not
  • r-shadow511 d093bef — quoting the historical-run numbers | they measure a committed message substituted for a missing transcript, and a number from the wrong instrument becomes a baseline the moment anyone repeats it
  • r-shadow511 d093bef — backfilling records from shadow's output | the draft is an approximation no agent judgment ever stood behind, and publishing it as lore would launder a substitution into the thing lore exists to prevent
  • r-shadow511 d093bef — deleting the instrument because its first question failed | the failure belongs to history's missing transcript, not to the pipeline, and a live session supplies what the first run could not
  • r-mcpexit506 f1b1fb0 — adding reconnect logic | the client owns reconnection and stdio transports are documented as not auto-reconnected; this makes the ending legible rather than pretending to prevent it
  • r-mcpexit506 f1b1fb0 — writing the cause to stdout where a client would see it | that stream carries the protocol, and a diagnostic on it corrupts the thing being diagnosed
  • r-demostory505 8016424 — keeping the cache scenario and rewriting the README paragraph to match it | the pricing example is the one that names a cost a reader has paid, and the image should follow the argument rather than the argument follow the image
  • r-demostory505 8016424 — hand-editing the SVG to say pricing | the recording would then be a drawing of output the command does not produce
  • r-filters471 c7572f6 — running every check and filtering the report | the cost and the repository access would remain, and the two would be indistinguishable from outside
  • r-filters471 c7572f6 — reporting an empty run for an unknown selection | zero rows and exit 0 is a command claiming it looked and found nothing wrong
  • r-envelope469 0162b73 — exiting 3 for degraded | that code means "ran but could not see everything" for every other command, and a doctor-private meaning would make the number mean two things
  • r-envelope469 0162b73 — deriving status inside each check | the invariant would then hold only as long as every future check remembered it, which is how the defect this milestone exists to fix was written in the first place
  • r-effects476 43eb4aa — migrating the checks in batches across several changes | a partially injected registry is the state the ticket names as worse than not starting, and it would have been the shipping state between batches
  • r-effects476 43eb4aa — defaulting the effects inside each check rather than in one context | thirteen defaults is thirteen places for the real implementation to leak back in, and nothing would report it
  • r-headline470 55b810c — adding the header to init as well | init's result-line budget is a separate frozen contract, and widening it inside this ticket would move it without its own decision
  • r-headline470 55b810c — capping the fix plan at the first few entries | a cap hides findings, and the two mechanisms that shorten this report -- collapse and dedup -- both do it without dropping one
  • r-budget472 8ea15f1 — lowering the cap now that truncation is visible | the cap is a separate decision with its own evidence, and changing it inside the ticket that made it observable would spend that evidence before anyone read it
  • r-budget472 8ea15f1 — raising status to warn when the scan truncates | this is disclosure, not a new verdict; a warn here would report a finding about the checker rather than about the repository
  • r-dsplit467 b24e371 — splitting the checks by category into subdirectories | the registry is a flat ordered list and a nested tree would suggest a grouping the emission order does not have
  • r-dsplit467 b24e371 — deleting the shim and updating every import | the path is what callers and tests already reference, and a move that also rewrites its callers cannot be verified as a move
  • r-collapse466 d24a284 — declaring commit-msg-hook on hook-runtime to complete the graph | that edge runs backwards against registry order, and a declared edge the emission order cannot satisfy is a lie in the structure the fix plan walks
  • r-collapse466 d24a284 — omitting a blocked row from the report and keeping it only in the JSON | the text report is what a user reads, and a row missing from it is indistinguishable from a check that was never run
  • r-evidence465 e1a3c92 — collapsing stdout and stderr to present or empty, as the reference does | it sanitises against paths and tokens it cannot inspect, while these checks diagnose from the first line and would lose the diagnosis
  • r-evidence465 e1a3c92 — leaving evidence optional on non-ok rows | a conclusion without its observation is the shape every defect above shares, and optional means absent in the row nobody looked at
  • r-queryroute 4ae1f6f — threading a cwd parameter into queryOptions to match inject | this route resolves the repository it was invoked in and has no cwd of its own, so a parameter would exist only to look symmetrical with a function that needs one
  • r-queryroute 4ae1f6f — deleting the comment now that a test enforces it | it explains why the routes must agree, which the test asserts but does not say
  • r-rel071 af8e0ab — deleting the v0.7.0 tag and re-cutting it | rewriting a published ref breaks every clone that already fetched it, and the release notes can carry the truth without that
  • r-rel071 af8e0ab — reading the flag with a nullish check and documenting the commander default | the documentation would sit in this file while the defect sits in every install, which is the arrangement that produced this
  • r-rel070 d4a4d8b — bumping the manifests first and the README pins after | the readme suite pins them to package.json, so the intermediate commit is one where CI is red and the documented install is wrong
  • r-rel070 d4a4d8b — rebuilding dist for the version change | the version is read at runtime, and a rebuild would move the digest every M5 row records without changing a byte of behaviour
  • r-skipreason 85aa8d6 — a catch-all other member | it is the free-text problem with a type annotation, and a consumer branching on other is back to reading the detail string
  • r-skipreason 85aa8d6 — casting the inherited status to satisfy the overload | the cast compiles today and lies the moment hook-runtime gains a skip site, which is exactly when nobody would be looking
  • r-registry463 ddf5592 — declaring commit-msg-hook -> hook-runtime now | the edge points backwards against report order, and a declared dependency that the emission order cannot satisfy is a lie in the structure the fix plan walks
  • r-registry463 ddf5592 — injecting git and spawn alongside the clock in this change | it rewrites every check while the text must stay byte-identical, and partial injection makes a stubbed-context test cover an arbitrary subset
  • r-registry463 ddf5592 — letting a throwing check abort the report | the twelve remaining answers are worth more than the one missing, and the containment row says which subsystem went unreported rather than implying it passed
  • r-checkmodel 9cbed57 — deriving category from a table keyed by check id | it is less code and gives a new check a silent default, which is the failure mode this milestone exists to remove
  • r-checkmodel 9cbed57 — mapping skipped to warning | a check that could not run has reported nothing, and weighting a blind spot above a finding inverts what the report is for
  • r-checkmodel 9cbed57 — repairing the object-literal migration that broke | it had converted a quarter of the sites and quadrupled the error count, and a half-applied mechanical rewrite is harder to audit than a fresh one
  • r-doctorpend 458bcec — lengthening the five-minute expiry | a staged record binds to the tree it was prepared for, and attaching it to a different tree is worse than dropping it -- the defect is the silence, not the expiry
  • r-doctorpend 458bcec — letting gc collect expired staged files | that erases the only evidence a capture was ever prepared, and this repository found the defect precisely because the files were still there
  • r-trust415 a030e93 — dropping [directive] from the injected legend | that resolves the contradiction by deleting the tier that carries SPEC §7's security meaning, and the legend was not the thing that was wrong
  • r-trust415 a030e93 — trusting every committer reachable from HEAD | it reads as "more useful by default" and is exactly the attack -- a contributor who lands one commit could then write directives to a maintainer's agent
  • r-cdebver01 ce7b278 — default-in discovery over the CDEB tree like the legacy gate | that gate's enemy was the unregistered file, CDEB's is the unregistered input, and bench:m5 reads every jsonl in bench/results, so the registered analysis would run over M1, M4 and files marked non-citable #441 showed a glob passing a stopping rule on contamination
  • r-cdebver01 ce7b278 — validating with the draft-07 Ajv entry and downgrading the schemas | the 2020-12 entry ships in the same package, and weakening six schemas to fit a meta-schema is backwards
  • r-mcplife424 8cd3c6d — reporting the loss from doctor by probing the MCP server | the server starts and answers on demand -- measured, 60 protocol requests and 24 tool calls with no crash -- so a probe reports healthy in exactly the situation being investigated
  • r-mcplife424 8cd3c6d — writing the log outside .git/ so it survives a clone | it is evidence about one machine's processes, and a path that can reach a commit is a path that will
  • r-capmode30 40818c2 — stamping drafted at stage instead of verify | verify is where accepted records are written, and stage would have to rewrite a payload whose hash it is simultaneously checking
  • r-capmode30 40818c2 — letting off draft a candidate and drop it | the transcript would be hashed to disk for a feature the repository declined
  • r-capmode30 40818c2 — overwriting provenance in suggest too | that mode's host may have asked, and marking its records unread would be as unsupported as marking them read
  • r-drafted30 b126176 — capping unattended records in the capture pipeline | the writer would own a rule the readers depend on, and any other host staging a record could simply not apply it
  • r-drafted30 b126176 — an X- extension trailer to carry the unread signal | SPEC §3 defines those as never interpreted by the core, so a grading rule reading one would license every reader to invent grading keys
  • r-amendid430 4c450eb — recording the amend in prepare-commit-msg for commit-msg to read | it is cross-hook state in the hooks, needing a marker keyed to HEAD so a stale one cannot suppress a real collision, and the last hook change made at speed hung every push
  • r-amendid430 4c450eb — excluding HEAD from the duplicate walk | it would pass a genuine divergent duplicate whenever the colliding record happened to sit on HEAD
  • r-amendid430 4c450eb — widening the rule to whatever §3.2 might mean by a lifecycle update | that needs deciding which content changes stay updates, and amend needs none of it
  • r-hookver433 a3b92d7 — comparing against the published release over the network | every other check in doctor reads local state, and a version check that needs the internet is one that fails on a plane and tells nobody why
  • r-hookver433 a3b92d7 — making it a fail | an older hook still delivers records, under older rules, which is worth saying and not worth refusing to run over
  • r-hookver433 a3b92d7 — folding it into doctor and hooks status report a stale hook pin as ok: commit-msg still bound to v0.5.0 after upgrading to 0.6.0 #382's pinned-CLI check | that one is about the commit-msg hook's recorded target, and merging the two would report one surface's staleness under the other's name
  • r-binx428 b9d1ea8 — running the value through node instead of exec'ing it | this branch has no recorded interpreter to use, and inventing one would give an environment variable more trust than the recorded path gets, not less
  • r-binx428 b9d1ea8 — reporting the unrunnable value and exiting non-zero | a hook that cannot find its checker has nothing to reject, which is why the unresolved ending already exits 0
  • r-recurse422 418734c — guarding with an environment variable the hook sets and the command checks | it works, but it puts the fix in the caller when the hazard is in the push, and a second caller that forgets the variable reopens it
  • r-recurse422 418734c — moving the publish to post-commit to avoid the nesting | it was ruled out in The notes mirror is written locally and never leaves the machine, so a teammate's clone cannot see a record it holds #416 for adding a network call to an operation that had none, and a hang is not a reason to take a worse design
  • r-busy420 9555569 — a longer timeout that waits out a rebuild | the agent is blocked on this hook, and at 100k commits the rebuild is the same order as the 86s scan it would be waiting to avoid
  • r-busy420 9555569 — serialising injections behind a lock file | it makes every edit wait for the slowest neighbour, where SQLite already lets readers run concurrently under WAL and only writers contend
  • r-sync416 deb21d2 — pushing the mirror from the post-commit hook | it adds a network call and a failure mode to an operation that had neither, on a machine that may be offline and a remote the user has not chosen to write to
  • r-sync416 deb21d2 — fetching the mirror on the read path so it is always current | notes.ts states that availability reads git config with no network, and the PreToolUse hook has a latency budget a fetch would be felt in on every edit
  • r-sync416 deb21d2 — letting the newest side win when two clones diverge | the note is the record, so picking a winner destroys one; the union keeps both and loses nothing
  • r-mention408 ec314cd — leaving the quoted-warning case alone as an acceptable false positive | a blocked record has its content withheld rather than downgraded, so the cost is not one dulled sentence but a safety warning the agent cannot read at all
  • r-mention408 ec314cd — treating quotation marks as the mention signal | an attacker quotes as readily as a defender, and the reporting-verb window at least costs them the imperative form
  • r-schema406 22b2c35 — shipping a release note instead of a version bump | nothing surfaces the staleness for a user to act on -- doctor reported the stale cache as healthy, which is the whole reason the bug is silent
  • r-schema406 22b2c35 — re-applying the classifier when rows are read | the gate belongs at the boundary where raw git output becomes a candidate record, and a second copy at read time is the two-implementations-one-hole shape this codebase already warns about
  • r-note409 0dff3e4 — refusing to grade any notes-sourced record above claim | it passes the same regression test while breaking the notes mirror for repositories that legitimately use it, which is why the control case asserts that a note by a trusted author still grades directive
  • r-note409 0dff3e4 — attributing a note to its most recent writer | a cat_sort_uniq notes merge puts two writers' text in one blob, so the later writer's grade would cover the earlier writer's content -- verified against git, and the test for it fails against this rule
  • r-note409 0dff3e4 — requiring a signature on the notes ref before trusting it | commit authorship is not signature-verified either, so demanding it of notes alone sets an inconsistent bar and is a much larger change than the forgery needs
  • r-backfillclosed 00de5fa — Reporting without refusing | the report does not stop the duplicate, and this is the one command that can create one
  • r-backfillclosed 00de5fa — Refusing the read-only modes too | they are how the state is diagnosed, and they cannot write
  • r-initunfetched 889d191 — Reading notesAvailability at format time | init's own doctor step writes the refspec first, so the read always returns absent and the line never appears -- measured, not assumed
  • r-initunfetched 889d191 — Widening the six-line contract | it was not needed, and a contract loosened to fit one line is loosened for every line after it
  • r-initunfetched 889d191 — Making init exit non-zero | Say the mirror went unread, instead of counting the rebuild as whole #401 settled that an unfetched mirror is not a failure of the command that built the index over it
  • r-mirrorunread 8e4bdc5 — Exiting 3 the way context does | 3 marks an incomplete answer rather than a failed build, this command's documented codes are 0 and 2, and the change would fail init and CI in every unfetched clone over an index that is correct for what git holds
  • r-mirrorunread 8e4bdc5 — Carrying the state through IndexStats and reporting it from core | the data was already right and only the report was wrong, so widening a core type to move one sentence costs every caller of the index a field it must then decide about
  • r-mirrorunread 8e4bdc5 — Adding the same sentence to init and backfill in this change | neither is silent for want of a check -- init collapses its steps to check marks unless --verbose, and backfill prints its own count -- so each is a decision about that command's output contract, which issue 400 does not make
  • r-m5analysis 3450656 — Computing the table now and not looking | the file would exist, and a number that exists is a number someone reads
  • r-m5analysis 3450656 — Leaving the analysis to be written after the run | that is the freedom this document was written to give up, and writing it afterwards is indistinguishable from writing it to fit
  • r-m5analysis 3450656 — Asserting the M1 control in a vitest suite instead of --validate | it belongs to the analyser, and a reader checking the verdict should be able to re-derive the control with the same command that produced the verdict
  • r-benchscope 67f4375 — A declared list of result files, in the gate or in a manifest | opt-in under another name, and a file left off it is silently ungated -- which is precisely the failure bench/verify.mjs is not run by anything, so the result schema drifted unnoticed #392 reports
  • r-benchscope 67f4375 — Validating only the three files that pass today | a description of the present rather than a rule, and it goes stale the first time a matrix is added or the schema moves
  • r-benchscope 67f4375 — A naming convention on results filenames | the runner's default output is an ISO stamp plus hex and the metric writers' is a family name plus an ISO stamp, but every run-record file in the tree was named by hand through --out (t702-m2, m5-off-design-20-tasks), so the convention is enforced nowhere and cannot carry a gate
  • r-benchscope 67f4375 — A marker file dropped beside each gated result | still a step somebody has to remember, and a forgotten step is the defect being fixed
  • r-benchscope 67f4375 — Widening result.schema.json to describe both row families | they share no required field, so the union would accept a run record with no task and a metric row with no metric, which is a schema that rejects nothing
  • r-benchscope 67f4375 — Making harness_commit and dist_digest optional in the schema | weakens the gate for every future row in order to admit six historical files, and Make per-turn token usage observable, and say what it still cannot price #390's drift was an additionalProperties failure that a laxer schema catches later rather than sooner
  • r-benchscope 67f4375 — Skipping the six pre-provenance files whole | cheaper to write, but it stops checking types, patterns and the closed property set on 380 rows in order to excuse two absent fields
  • r-pinskew 007ccbf — Re-pointing the pin from doctor --fix | doctor's --fix boundary is reversible local config only, and the module comment states the commit-msg hook is reported and never written -- rewriting commitlore.bin would also change which binary validates commits, silently, from a diagnostic
  • r-pinskew 007ccbf — Having the upgrade re-point every repository | install.sh cannot enumerate the repositories that ran hooks install, which is why the issue itself proposes reporting as the self-correcting half
  • r-pinskew 007ccbf — Spawning the pinned bundle for --version | the recorded path is by design a value a .git/config edit can change, and hooks status spawns nothing today -- executing it on every status and every doctor is a larger door than the question is worth
  • r-pinskew 007ccbf — Treating a manifest with no version as a match | that is the false green the check exists to remove
  • r-3c9d52 dc9e769 — reimplementing the scorer for the external corpus | two scorers that drift by a line produce two numbers that look comparable and are not, which is the failure No-index query at 100k regressed from 7.7s to 90s — cause not yet identified #163 already recorded here
  • r-3c9d52 dc9e769 — replacing the per-path --follow chain with one forward pass over a rename graph | it is much faster and it is a different attachment predicate from the one DECISION-DELIVERY.md §3 registered, so the two corpora would stop being comparable
  • r-3c9d52 dc9e769 — turning the census notes option on by default | every measurement registered before it existed read commit messages only, and a denominator that silently grew would invalidate them without saying so
  • r-rel060 e999b9d — 0.5.2 | three observable behaviour changes and one narrowed acceptance rule are not a patch, and an upgrader reading the number would not go looking
  • r-rel060 e999b9d — Publishing the delivery figure in the README | the measurement is one corpus and one repository, and the README already carries more numbers than a first-time reader can weigh; docs/evidence.md and bench/ hold it
  • r-pipesplit b4fa571 — Splitting on the last pipe instead of the first | this repository's own records refute the premise that reasons rarely contain a pipe: two of the three multi-pipe values carry it in the reason, so the change would break two correct records to fix one
  • r-pipesplit b4fa571 — Defining a backslash escape for the separator | that is a new grammar rather than a clarification -- parser, renderer and validator would all have to agree on unescaping, and it changes what a conforming record looks like, which needs sign-off this fix does not have
  • r-pipesplit b4fa571 — Making any value with more than one pipe a format violation | it invalidates 616005d and aa68a9a, whose extra pipe sits in the reason and whose split is already correct, and dogfood validates all of history
  • r-pipesplit b4fa571 — Having guard score both the first-pipe and last-pipe splits and keep the better one | it invents an alternative no author wrote and then reports it as recorded, which puts the silent wrong answer in a new place instead of removing it
  • r-pipesplit b4fa571 — Rendering every Ruled-out: value pre-split in the query output | it rewrites 620 lines of output to mark 3, and the annotation is only information where the split is actually in doubt
  • r-pipesplit b4fa571 — Warning on the code-span case rather than refusing it | a span that crosses the separator is provable rather than suspected, and this repository refuses what it can prove instead of hoping the author reads stderr
  • r-gcunstageable 5cd6b8f — Collecting on age alone, without the staleness test | a transaction still sitting on the HEAD it was prepared for can be staged and committed at any time, so age alone would delete work the user is still holding
  • r-gcunstageable 5cd6b8f — Stamping expires_at at prepare or verify | it moves a field ADR-0021 declares normative and whose null-before-stage shape an mcp-capture oracle pins, and it would expire a capture while the user is still being asked about it
  • r-gcunstageable 5cd6b8f — A second staleness rule inside pending-gc.ts | pending ls already computes the same question, and a listing that calls a file collectable while the collector disagrees is worse than either answer alone
  • r-gcunstageable 5cd6b8f — Deleting the transaction where the skill skips it | the skip lives in a skill a host is free not to run, and a leak avoided only on the well-behaved path is not fixed
  • r-gcunstageable 5cd6b8f — A --force for pending rm on a staged or unreadable file | an unreadable file may be a newer format this binary cannot parse and another still can, and the two phases it protects are the ones a hook may be seconds from finalising
  • r-secondtie 998bf18 — Adding a topological ordinal to the trailers table | it bumps SCHEMA_VERSION and changes the index format, which needs an ADR and the representative's approval rather than a silent column

Truncated: 318 lines omitted — the comment hit GitHub's 65000 character limit.

Trailer violations fail this check. Active constraints are informational — they are what the repository already decided, not a verdict on this PR.

… examines it

`npm audit --omit=dev` is the blocking half of the audit split I wrote for
that matters is what is bundled into it, and that must be zero. The
implementation contradicted the premise — every runtime package was declared
under `devDependencies`, so `--omit=dev` selected an empty set:

    npm ls --omit=dev --depth=0
    └── (empty)

`@modelcontextprotocol/sdk`, `ajv`, `ajv-formats` and `commander` are imported
directly by `src/` and end up in `dist/commitlore.mjs`. `js-yaml` is not — it
is used only by scripts and bench — so it stays a dev dependency. Moved the
four that are genuinely runtime; nothing else changed. Closes #606.

With the audit examining the real set, it found something real: `fast-uri`
(via `ajv`) and `hono` (via the MCP SDK's node server) carried two advisories,
high and moderate. `npm audit fix` resolved both to compatible versions with
no source change required.

Verified: `npm audit --omit=dev --audit-level=low` now finds 0 vulnerabilities
  after finding 2 before the fix; `npx tsc --noEmit` clean; 129/129 across
  mcp.test.ts, capture-pipeline-e2e.test.ts and validate.test.ts; dist rebuilt
  on linux/amd64 (the platform CI's blocking check runs on) matches byte for
  byte
Evidence: package.json
Evidence: package-lock.json
Blast: system
Undo: easy
Certainty: firm
Record-Id: r-8e1c40
Provenance: authored
CommitLore-Version: 2.0.0
`manifest.dependencies ?? {}).toEqual({})` was true only because nothing had
`dependencies` yet. #606 moved the four packages the bundle actually imports
there, so the blocking audit would examine them instead of an empty set — and
this test failed on the thing #606 was correcting.

What the test name says it protects is narrower than what it asserted:
`better-sqlite3`, a package this project once used and removed, must not
quietly reappear. That is still checked. The empty-object assertion was
collateral from a time when the two happened to coincide.

Verified: 6/6 in help-text-honesty.test.ts; dist rebuilt on linux/amd64
Evidence: test/help-text-honesty.test.ts
Blast: local
Undo: easy
Certainty: firm
Record-Id: r-2a5f19
Provenance: authored
CommitLore-Version: 2.0.0
@MongLong0214
MongLong0214 merged commit 34d41f6 into main Aug 13, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The blocking audit examines an empty dependency graph, so the bundled runtime is never checked

1 participant