Skip to content

Release 0.5.1 - #348

Merged
MongLong0214 merged 16 commits into
mainfrom
dev
Aug 1, 2026
Merged

Release 0.5.1#348
MongLong0214 merged 16 commits into
mainfrom
dev

Conversation

@MongLong0214

Copy link
Copy Markdown
Owner

Promotes dev to main for 0.5.1. Same path 0.5.0 took.

Merging this releases nothing. release.yml triggers on a pushed v* tag and nothing else. After this merge:

git tag v0.5.1 <this merge commit>
git push origin v0.5.1

The defect this release exists to ship

On a repository with no records, the index accepted any RFC-822-shaped key: value line as a trailer — conventional-commit prefixes, a Homebrew digest, arbitrary body fields. One report had 106 rows where git had zero.

context is wired into the pre-edit hook, so a commit subject reached an agent as a recorded decision, while doctor called the state healthy and stale — which reads git — correctly reported nothing. Two commands in one tool disagreeing about whether the repository had any records at all.

That is the product claim inverted: the thing it exists to do is hand an agent accurate decision context (#335).

Also in

Deliberately unchanged

Verified: is protocol vocabulary. A release note using it as a field is indistinguishable from a record using it for what it means, and guessing from context is how a tool starts discarding records somebody wrote on purpose.

The Windows repair path from 0.5.0 is restated, not assumed inherited: a repository whose hook predates 0.5.0 still needs commitlore hooks install re-run. doctor reports such a repository as outdated.

Verification at this head

  • check-release-version.mjs v0.5.1 — tag, package.json, commitlore --version all 0.5.1
  • check-readme-numbers.mjs — exit 0; npm run typecheck clean
  • Full suite — 78 files, 1935 passed, 1 skipped
  • dev post-merge CI green

MongLong0214 and others added 16 commits August 1, 2026 04:25
`.serena/` is written by an MCP server into whatever directory it was pointed at,
and it records that directory's name. A copy committed from a worktree therefore
ships that worktree's label: v0.5.0 carries `project_name: "t1124"`, which is
meaningless to anyone who clones it and wrong for anyone who uses the same tool.

It entered at `51abef8` -- the T-1124 merge -- because the commit before it staged
with `git add -A` in a worktree where the server had left the directory
untracked. Nothing failed, because nothing looks: the manifest test asserts that
every *declared* file parses in a clean clone, and a file nobody declared is
invisible to that. Distribution here is a clone (ADR-0011), so an undeclared file
ships as surely as a declared one.

Removed and ignored. Ignoring it is the part that lasts: the file will be
recreated in every worktree the server is pointed at, so the next `-A` would
otherwise put it back.

Not a functional defect, and not worth a patch release on its own -- the file is
inert. It is recorded here rather than quietly dropped because the release that
carried it is tagged, and a later reader comparing the v0.5.0 tree against this
one should find the reason rather than a silent deletion.

Record-Id: r-strayserena
Limit: a clean clone is the distribution, so an undeclared file ships; the manifest test checks declared files parse and cannot see a file nobody declared
Ruled-out: Cutting 0.5.1 for this | the file is inert -- it changes no behaviour and breaks no install -- and a release exists to move something a user needs
Ruled-out: Deleting it without a record | the tag that carries it is immutable, and a later reader comparing the two trees deserves the reason rather than an unexplained absence
Ruled-out: Adding a stray-file assertion in this commit | test/manifest.test.ts belongs to another ticket's scope, and the guard is worth its own issue rather than a drive-by edit here
Certainty: firm
Blast: local
Undo: easy
Verified: the manifest and install-script suites pass at 34 with the directory gone; typecheck clean; the tree no longer carries .serena and .gitignore now excludes it
Unverified: nothing executable changed
Remove a tool's local config that a `git add -A` swept into the release
A draft that was prose rather than the contract's JSON object came back as
`missing --transcript`. The transcript was not the problem, and the reporter
spent two invocations finding that out: the first sent them after a file they did
not need yet, for a draft that was never going to parse.

The three options were required together, and the draft was only read afterwards.
It is resolved first now -- present, readable, and actually a draft -- and the
other two are required behind it.

The ordering matters more here than orderings usually do. A session that emits
prose believes it staged records, and nothing contradicts that belief until
somebody verifies. Fifteen files had been staged that way in the report. The
sooner the message says "this is not a draft", the sooner the staging error is
visible at all.

`harvest --draft` was checked and does not share the shape: it routes to draft
mode before touching any other input, and executing it against the same prose
produces the same message. That is measured, not read.

Record-Id: r-draftfirst329
Limit: 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
Ruled-out: Reporting all missing options at once | it would say the draft is unparseable and the transcript missing together, and the second is not true until the first is fixed
Ruled-out: Changing harvest --draft to match | it already resolves the draft first, verified by running it against the same prose rather than by reading the dispatch
Certainty: firm
Blast: local
Undo: easy
Verified: `harvest-verify --draft <prose>` with no other options now reports `draft is not valid JSON` at exit 2, where it reported `missing --transcript` before; a well-formed draft with no transcript still reports `missing --transcript`; an unreadable draft reports `cannot read --draft`; harvest-verify and harvest suites pass at 89; typecheck clean
Unverified: nothing else -- the change is an ordering, and both orderings are asserted
Say the draft is not a draft before asking for a transcript
`.serena/project.yml` reached v0.5.0. A tool writes it into whatever directory it
is pointed at, a `git add -A` in a worktree swept it in, and the released tree
carried that worktree's name as somebody's project label.

Nothing failed, because nothing looks. The manifest suite asserts that every
*declared* file parses in a clean clone, and a file nobody declared is invisible
to it -- it is not on the list being checked. Distribution here is a clone
(ADR-0011), so an undeclared file ships as surely as a declared one.

The guard is deliberately narrow. "No unexpected files" is unimplementable here:
the tree legitimately holds src, test, bench, spec, docs, dist, skills and more,
and a whitelist of everything would fail on every honest addition and teach the
next author to widen it rather than read it. What is checkable is that **no
tool-local state ships** -- state keyed to the machine or the directory that
produced it, and therefore wrong for every clone by construction. That is what
separates it from editor settings a repository may ship on purpose, which this
does not forbid.

The list is short and names what has actually appeared or plausibly would. It is
not a claim to be exhaustive; a guard that pretends to catch everything is the
same false comfort as a check that catches nothing.

Record-Id: r-toolstate334
Limit: a check that only inspects a declared list cannot see an undeclared file, and in a clone-is-the-distribution model the undeclared file ships anyway
Ruled-out: Asserting the clone contains no unexpected path | the legitimate tree is large and grows, so the whitelist would fail on every honest addition and be widened without being read
Ruled-out: Forbidding every dotted directory | some are deliberate -- .github and .claude-plugin are the product -- and a rule that cannot tell those apart is not a rule
Ruled-out: Asserting only against .serena | it names the instance rather than the class, and the next one will have a different name
Certainty: firm
Blast: local
Undo: easy
Verified: the guard passes on the current tree, and fails on a tree where .serena was committed -- proved by committing the defect, running the suite, and resetting; the path construction is checked against files that are genuinely present, so a pass cannot come from looking in the wrong place; typecheck clean
Unverified: the list's completeness, which is not claimed
Notice a file that ships but was never declared
On a repository with zero records, `index` populated 106 rows by accepting any
RFC-822-shaped `key: value` line -- conventional-commit prefixes (`ax:`, `fix:`,
`docs:`), a Homebrew digest (`sha256:`), arbitrary body fields. `doctor` called
that healthy. `context` is wired into the PreToolUse hook, so what an agent was
handed before editing was a commit subject presented as a recorded decision.
`stale` reads git and said 0, so two commands in one tool disagreed about whether
the repository had records at all.

There was already a filter here, and it was not wrong -- it was answering a
different question. `CONVENTIONAL_TRAILER_KEYS` decides which trailers to keep
*inside* a record, and its comment argues for a denylist so a project's own
`Ticket:` survives beside a `Limit:`. That reasoning holds, and SPEC agrees:
an implementation must preserve keys it cannot interpret. What nothing asked was
the prior question -- **is this a record?** -- and a denylist cannot answer it,
because the set of keys nobody has claimed is unbounded.

So the prior question is asked separately. `isCommitLoreKey` is SPEC §3's fifteen
keys plus `X-<Name>:`, which §3 gives a slot of its own; a block with none of them
is dropped rather than indexed. The denylist keeps its job unchanged, and a
`Ticket:` inside a real record is still preserved.

One case cannot be decided and is written down instead of guessed at. `Verified:`
is vocabulary, so a release note using it as a field is indistinguishable from a
record using it for what it means. Reading context to tell them apart is how a
tool starts discarding real records, so the block is a record and both keys are
kept. The test says so, rather than leaving it to be rediscovered as a bug.

Record-Id: r-recordgate335
Limit: 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
Limit: `Verified:` in a release note is indistinguishable from `Verified:` in a record, and no context signal separates them without risking real records
Ruled-out: Adding the observed noise keys to the denylist | `ax`, `sha256` and the rest are one repository's accident, and the next repository invents different ones
Ruled-out: Requiring `Record-Id:` to make a block a record | `stale` needs it for identity, but a commit carrying only `Limit:` is a record SPEC recognises and dropping it would lose real context
Ruled-out: Inferring intent from position or neighbouring lines | that is guessing, and the failure mode is discarding a record somebody wrote on purpose
Certainty: firm
Blast: local
Undo: easy
Verified: the issue's own repro executed against the build -- a repository of conventional commits plus a `sha256:` body now reports 0 trailers from doctor and 0 records from stale, and `context` returns nothing where it previously served a commit subject; index-db suite at 49 including four assertions that failed before the change; full suite 78 files, 1922 passed, 1 skipped
Unverified: the reporter's own repository, where the 106 rows were observed
A block with no CommitLore key is not a record
…ot again

`docs/COMPATIBILITY.md` has called Windows supported since T-1124 established
#71's containment there by execution. Every README went on saying the opposite
five sections later, in four languages, while pointing at that document as the
authority. A Windows user read the plugin install path, then `supported`, then
`unsupported`.

This is the second time. `Alpine and other musl Linux hosts are unsupported`
outlived the executed install that made it false and was removed the same way.
Both sat in a section the compatibility work was forbidden to edit, and both were
found by reading rather than by anything failing -- which is the part worth
fixing.

So the missing direction is asserted now: for every host the table calls
`supported`, no README declares it unsupported. Proved by restoring the bullet and
watching it fail, in the language the reader would see it in.

The oracle that anchored on that bullet moves with it. `readme.test.ts` mutated
`Windows is unsupported` to show an unrelated change does not disturb the guard
assertions -- and a `replace` whose needle is gone is a no-op, so it would have
kept passing while testing nothing. It anchors on a bullet that exists, and
asserts the needle is present before relying on it.

`uninstall` also had no documentation anywhere. It shipped in 0.5.0 and the four
READMEs never mentioned it. The section states what it removes, and what it
deliberately leaves to the commands that own it.

Record-Id: r-readmefinal
Limit: a mutation oracle anchored on a claim that can become false will silently stop testing when the claim is removed; the needle has to be asserted present
Ruled-out: Rewriting the bullet to say Windows is supported | the compatibility document owns the support statement, and a second copy in four READMEs is the duplication the ownership map exists to prevent
Ruled-out: Checking only the English README | the contradiction shipped in four languages, and a reader sees one of them
Ruled-out: Asserting every host row against every README line | only the `supported` direction is decidable from the table; a host the table calls undecided may honestly be described either way
Certainty: firm
Blast: local
Undo: easy
Verified: restoring the Windows bullet fails the new assertion with the offending line quoted, and removing it passes; readme, readme-order, readme-numbers, compatibility-matrix and install-script suites pass at 92; check-readme-numbers exits 0
Unverified: nothing executable changed
The README argued the product well and demonstrated it only on its own corpus. A
field report from a ~768-commit Swift MCP server gives the thing an argument
cannot: a specific moment where a path-scoped query changed what an engineer was
about to build.

The query returned a merged pull request from two weeks earlier that had already
removed eight of the sites he was cataloguing. What it changed was not his task
list but his model of the problem -- the surviving sites were not "the coordinate
problem", they were the residual after a shipped removal campaign, which is a
different engineering problem with a different risk assessment.

The line worth quoting is his: none of it was in any chat history; it was in the
repository, and he got it by naming a file path. That is the whole product claim,
stated by somebody who did not write it.

Attributed as one engineer's report, not presented as a benchmark. The numbers
that travel with it -- one command, 7.4 seconds for 768 commits -- are his
measurements on his machine and are labelled as such. Overstating here would cost
the one property this repository has that most tools in the category do not, and
which the same report singles out: it prints its own weak numbers next to the
feature they belong to.

The three properties in the closing list are his framing too: reviewable, owned
by the repository, travels with a clone. They are the reason the authority is Git
rather than a service, and they read better as consequences of a real session
than as bullet points arriving unprompted.

Record-Id: r-fieldreport
Limit: this section reports one engineer's day on one repository; it is evidence that the mechanism works there, not a measured effect size, and the wording has to keep those apart
Ruled-out: Presenting the 7.4s index and 768 commits as product benchmarks | they are one machine's numbers on one corpus, and bench/ is where measured claims live under ADR-0018's provenance rules
Ruled-out: Paraphrasing his account in the product's voice | the credibility is that somebody outside the project said it, and paraphrase throws exactly that away
Ruled-out: Leading the README with this | the opening claim is the product's own and should stay first; this belongs where a reader who is already interested asks what it looks like in practice
Certainty: firm
Blast: local
Undo: easy
Verified: readme, readme-order, readme-numbers, compatibility-matrix and install-script suites pass at 92 across all four languages; check-readme-numbers.mjs exits 0, so the generated block and the stray-statistic rule are both intact
Unverified: nothing executable changed
The README argued the product accurately and asked a first-time visitor to read a
long way before finding out what it prevents. A conversion review put the gap
plainly: this document explains how CommitLore was built, not why a team using
coding agents already has the problem.

So the hero states the failure first -- an agent proposing a fix the team rejected
six months ago, and somebody spending the review explaining a decision that was
already made. The precise claim stays, one line down, in bold: an agent must not
revive a decision the repository already reversed. Order changed; accuracy did
not.

Then the scene that makes it concrete. A session reuses `calculatePrice` for admin
quotes because the inputs look alike, and the team gains a flag, a wrapper and a
compatibility branch guarding a use case the function never owned. With the record
present the agent shares the calculation primitives and leaves the policy
entrypoint alone. That failure is recognisable to anyone who has reviewed
agent-written code; the installer's musl story, which the field report section
tells, is true but specific to this project.

Four sentences replace three bullets for the comparison, because "which decisions
still apply to this code path" only reads as different from RAG when the two sit
in the same table. Four use cases replace none: a module boundary, a rejected
workaround, temporary compatibility code, a verification gap -- each a sentence a
diff cannot carry and a reviewer would otherwise say twice.

Two recommendations were not taken.

`Keep coding normally` after the install block would be the third time this
repository shipped a document ahead of its code. The skill that ships to Claude
Code still triggers on explicit CommitLore requests and still teaches the manual
harvest path (#340). The sentence becomes true when that lands, not before.

Testimonials from three external teams would need three external teams. One
engineer's field report exists and is quoted as his; inventing the other two is
the one thing that would cost this project the property it has and most tools in
the category do not.

Record-Id: r-convertreadme
Limit: 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
Ruled-out: Adding "Keep coding normally" now | the commit skill still triggers on explicit requests and teaches harvest; shipping the sentence first repeats the doc-ahead-of-code failure this session fixed twice
Ruled-out: Writing testimonials to fill the social-proof section | one real field report exists, and fabricated or padded quotes would cost the claim honesty that is this project's strongest asset
Ruled-out: Moving the benchmark block and protocol detail out of the README now | the generated block is byte-compared by check-readme-numbers and the guard figures are asserted inside the limitations slice; the move is worth doing and is worth its own change
Ruled-out: Dropping "decision authority" everywhere | it is the right term in the architecture sections; it is only the wrong term for a first screen
Certainty: firm
Blast: local
Undo: easy
Verified: readme, readme-order, readme-numbers, compatibility-matrix, install-script and manifest suites pass at 116 across four languages; check-readme-numbers exits 0, so the generated block and the stray-statistic rule are intact; the order test's product anchor moves with the heading it names
Unverified: whether any of this converts a visitor, which is not measurable from here
Stop the README saying Windows is unsupported, and check that it cannot again
"Stop re-reviewing the same bad idea" claimed something this tool does not do.
It does not decide whether an idea is bad. It decides whether a decision still
applies -- and an approach rejected last quarter can be the right one now that
the constraint behind the rejection is gone. That distinction is the product;
the headline erased it.

Worse, it read as a promise about `guard`, which this project measures at
precision 44.8% and recall 22.0% and labels an experimental advisory whose empty
result is not a safety verdict. A headline leaning on the least-proven part, in
a repository whose strongest asset is that it prints its own weak numbers next
to the feature they belong to.

It was also generic. A review bot, an ADR search, an architecture linter could
all have carried that line, which means it identified no mechanism at all.

The replacement names what actually crosses the boundary. Code survives a
session; the constraints, the rejected alternatives, the warnings and the
verification gaps do not, and `inherit` is the one word that covers sessions,
agents and people at once. It claims preservation and delivery -- both of which
are built and tested -- and claims no judgement about any proposal.

The old line keeps a job. As pain copy above the before/after scene it is
accurate, because that scene is a case where the decision genuinely still
stands. It was only wrong as the thing the product is.

Record-Id: r-heroinherit
Limit: a headline that implies detection commits the product to guard's numbers, and guard is an advisory measured at 22% recall
Ruled-out: Keeping "Stop re-reviewing the same bad idea" as the hero | it names a verdict on ideas rather than a lifecycle on decisions, and any review tool could carry it
Ruled-out: "Never let agents make the same mistake twice" | guard cannot support a never, and the sentence sells detection this product does not perform
Ruled-out: Leading with "decision authority" alone | precise in the architecture sections, and not a phrase a first-time reader converts on
Certainty: firm
Blast: local
Undo: easy
Verified: readme, readme-order, readme-numbers, compatibility-matrix, install-script and manifest suites pass at 116 across four languages; check-readme-numbers exits 0; typecheck clean; the install commands and the compatibility pointer survive the rewrite in all four files
Unverified: whether the line converts, which is not measurable here
Sell what the product does, not a verdict it never makes
Patch. No new command, nothing breaking -- one defect that changed what an agent
was handed, and two smaller corrections beside it.

The one that matters: on a repository with no records, the index accepted any
RFC-822-shaped `key: value` line as a trailer. Conventional-commit prefixes, a
Homebrew digest, arbitrary body fields. One report had 106 rows where git had
nothing. `context` is wired into the pre-edit hook, so a commit subject was
reaching an agent as a recorded decision while `doctor` called the state healthy
and `stale`, which reads git, correctly reported zero. Two commands in one tool
disagreeing about whether a repository had any records at all.

That is the product's own claim inverted -- the thing it exists to do is hand an
agent accurate decision context -- so it does not wait for the next minor.

`Verified:` is left alone deliberately, and the notes say so. It is protocol
vocabulary, a release note using it as a field is indistinguishable from a record
using it for what it means, and reading surrounding context to separate them is
how a tool starts discarding records somebody wrote on purpose.

The Windows repair path from 0.5.0 is restated rather than assumed inherited. A
new release invites "this one fixes everything", and a repository whose hook
predates 0.5.0 still needs `commitlore hooks install` re-run.

Record-Id: r-release051
Limit: 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
Ruled-out: Waiting for 0.5.2 to carry #335 | false decision context reaching an agent is the inversion of the product claim, and a stable release should not hold it
Ruled-out: 0.6.0 | no command is added and nothing breaks; calling it minor would hide a correctness fix behind a feature number
Ruled-out: Filtering `Verified:` because a report listed it as noise | it is vocabulary, and separating a release-note use from a record use needs a guess that can discard real records
Certainty: firm
Blast: local
Undo: easy
Verified: check-release-version.mjs reports tag, package.json and `commitlore --version` all at 0.5.1; check-readme-numbers.mjs exits 0; typecheck clean; full suite 78 files, 1931 passed, 1 skipped
Unverified: the release workflow, which runs only on a pushed tag
Write the 0.5.1 notes before tagging
@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown

CommitLore — record lint

Trailers: clean — 16 commits in origin/main..d3a78224d17ea846c21609df669c81fa5bc35a28
Active constraints: 115 limits · 269 ruled-out · 78 warnings — from 155 records over 27 changed paths

Active constraints for the paths this PR touches

Limits (115)

  • 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-heroinherit 89b13ac — a headline that implies detection commits the product to guard's numbers, and guard is an advisory measured at 22% recall
  • 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-fieldreport 753f4e7 — this section reports one engineer's day on one repository; it is evidence that the mechanism works there, not a measured effect size, and the wording has to keep those apart
  • r-readmefinal 40aeae0 — a mutation oracle anchored on a claim that can become false will silently stop testing when the claim is removed; the needle has to be asserted present
  • 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-toolstate334 f4e89ef — a check that only inspects a declared list cannot see an undeclared file, and in a clone-is-the-distribution model the undeclared file ships anyway
  • 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-strayserena 5c7c57a — a clean clone is the distribution, so an undeclared file ships; the manifest test checks declared files parse and cannot see a file nobody declared
  • 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-winsupported1124 6333251 — repositories that installed the hook before Windows: the commit-msg hook hangs instead of returning, and #71's containment can never match there #321 keep the old stub and must re-run commitlore hooks install; a corrected release does not reach them, and this row's claim is about a working install
  • 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-compat1122 e7d8516 — a non-empty guard does not detect deletion; each table's row keys have to be asserted as a set or the statement can silently shrink to one row
  • r-compat1122 e7d8516 — substring comparison hides a narrowing -- ./ is inside ../ and Edit|Write is inside Edit|Write|MultiEdit|NotebookEdit -- so cells are compared as their rendered form
  • r-compat1122 e7d8516 — a sentinel containing \0 makes git treat the file as binary, which costs it diff, blame and log -p permanently
  • r-compat1122 e7d8516 — the plugin path needs bash, because scripts/commitlore-run.sh carries a #!/bin/bash shebang, and no install script checks for it
  • r-muslbullet1126 04ac181 — this ticket owns four bullets and not the tests that read the section around them, so a check that breaks here means a region was taken that was not allocated
  • r-t1120nodeinst 14deeb4 — git and node are hard prerequisites now, so a host without them installs nothing and says which one is missing
  • 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-gateb3rev a2e38b9 — the shipped install.sh downloads a platform asset, so no document may describe it as Node-only until the installer itself changes
  • 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-rel040pins b76c40b — the pin names a tag that does not exist until the tag is pushed; between this merge and that push the documented command refers forward
  • 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-t1016svg 321c6f1 — byte-exactness is verified on this platform; a different platform's Node could in principle render differently, and nothing here proves it does not
  • 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-t1021known 8dfffc1 — the figures are measured against one archived 417-decision corpus, which is deliberately hard and is not deployment prevalence
  • 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-pin030readme 504b54e — install.sh must already support tag-based download for the one-liner to work; verified that the URL resolves to a tagged tree
  • 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-notes030 a289ca5 — the density denominator is named here and in the handoff, not in the harness that emits it, so the next run reproduces the same ambiguity
  • r-hero172a bc0d971 — Stale-exposure benchmark is one corpus, one query, and one pinned embedding model at a fixed two-record budget
  • 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-be140cost 8c01bd5 — no per-turn provider token ledger or observed avoided-work cost exists yet
  • 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-readme129 ab5f210 — the break-even rests on tokens estimated from bytes at the product's own four-characters-per-token constant, so it moves with that assumption
  • 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-m4basis 5e2d2cb — the guard question stays unanswered until the exposure instrument is verified and M4 is rerun on it
  • r-m4withdraw e5f9b73 — the guard question is now unanswered rather than answered null
  • r-readmeux1 b664205 — interactive record building does not exist, so the honest answer is still "an agent writes it or you do"
  • r-rel021a a79e350 — v0.2.0 remains on the remote with no release attached
  • r-expreadme1 9e69abe — bench/VERDICT-M4.md still cites the Fisher figure; the two disagree until the verdict records why the number was withdrawn from the README
  • r-expomerge1 d6ad014 — M4's existing rows have no exposure field and must read as unknown, not as not-exposed — backfilling by inference would erase the finding
  • r-f61a2c 9114cf0 — the matcher remains deterministic and lexical; no embedding or semantic service is available to distinguish paraphrases
  • r-rdme96a 9c9371c — scripts/check-readme-numbers.mjs's withdrawal-notice and stray-statistic checks constrain what can appear outside the (absent, here) generated benchmark block — re-checked after every edit, not just at the end
  • 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-distrace88 d118a73 — the fix insulates bench-ablation.test.ts from the race; it does not remove the underlying design (four test files independently, redundantly rebuilding one shared dist/ in their own beforeAll). A fifth file doing the same thing, or a future check elsewhere that also depends on dist/'s mid-run stability, can still race the same way.
  • 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-6f2a08 4c2d432 — esbuild cannot follow createRequire(import.meta.url)('x'), so any dependency reached that way stays external no matter what the bundle config says
  • r-9c07e2 9c4d25a — the plugin still needs Node for the CLI — the protocol does not, but guard, the index and the MCP server do (T-706 · Bundle the CLI as a single file — run from a clone alone #38)
  • r-9c2f74 d653153 — the ablation arms cannot discriminate on these fixtures -- no-grade and no-lifecycle are byte-identical to the treatment in 9 of 10 tasks, because the seeds carry one reconstructed record and one task with a lifecycle trailer between them
  • r-9c2f74 d653153 — the harness assembles its own projection rather than calling the shipped injector, so what is measured is the harness's rendering of the records, not src/core/inject.ts (issue B-08 · Replace the benchmark harness injector with the actual src/core/inject.ts #36)
  • 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-6e1a72 5e09846npx commitlore is the first thing a reader will try, and it fails until the package is published
  • r-7e5f02 e5f5e00 — npm installs through an engine mismatch, so the ecosystem's own signal cannot be relied on to stop anything
  • r-9a5e17 6d68703 — five workers on one repository share npm test and tsc, so file ownership alone does not prevent one worker from "fixing" another's half-written code -- verification scope had to be split too
  • r-7f0e39 76f3f2d — literal substitution only catches the exact strings you list, so the same term written with a different separator survives
  • 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-9d31b7 4ac6e30 — the example lives in four translated files, so any fix that is not mechanically enforced will drift again on the next edit
  • 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
  • r-a8f3c1 ef48843 — Rename must land before any code exists -- after 27 tickets it would touch spec, fixtures, index, hooks and every doc

Ruled out (269)

  • r-release051 19810d2 — Waiting for 0.5.2 to carry 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 | false decision context reaching an agent is the inversion of the product claim, and a stable release should not hold it
  • r-release051 19810d2 — 0.6.0 | no command is added and nothing breaks; calling it minor would hide a correctness fix behind a feature number
  • r-release051 19810d2 — Filtering Verified: because a report listed it as noise | it is vocabulary, and separating a release-note use from a record use needs a guess that can discard real records
  • r-heroinherit 89b13ac — Keeping "Stop re-reviewing the same bad idea" as the hero | it names a verdict on ideas rather than a lifecycle on decisions, and any review tool could carry it
  • r-heroinherit 89b13ac — "Never let agents make the same mistake twice" | guard cannot support a never, and the sentence sells detection this product does not perform
  • r-heroinherit 89b13ac — Leading with "decision authority" alone | precise in the architecture sections, and not a phrase a first-time reader converts on
  • r-convertreadme e12c816 — Adding "Keep coding normally" now | the commit skill still triggers on explicit requests and teaches harvest; shipping the sentence first repeats the doc-ahead-of-code failure this session fixed twice
  • r-convertreadme e12c816 — Writing testimonials to fill the social-proof section | one real field report exists, and fabricated or padded quotes would cost the claim honesty that is this project's strongest asset
  • r-convertreadme e12c816 — Moving the benchmark block and protocol detail out of the README now | the generated block is byte-compared by check-readme-numbers and the guard figures are asserted inside the limitations slice; the move is worth doing and is worth its own change
  • r-convertreadme e12c816 — Dropping "decision authority" everywhere | it is the right term in the architecture sections; it is only the wrong term for a first screen
  • r-fieldreport 753f4e7 — Presenting the 7.4s index and 768 commits as product benchmarks | they are one machine's numbers on one corpus, and bench/ is where measured claims live under ADR-0018's provenance rules
  • r-fieldreport 753f4e7 — Paraphrasing his account in the product's voice | the credibility is that somebody outside the project said it, and paraphrase throws exactly that away
  • r-fieldreport 753f4e7 — Leading the README with this | the opening claim is the product's own and should stay first; this belongs where a reader who is already interested asks what it looks like in practice
  • r-readmefinal 40aeae0 — Rewriting the bullet to say Windows is supported | the compatibility document owns the support statement, and a second copy in four READMEs is the duplication the ownership map exists to prevent
  • r-readmefinal 40aeae0 — Checking only the English README | the contradiction shipped in four languages, and a reader sees one of them
  • r-readmefinal 40aeae0 — Asserting every host row against every README line | only the supported direction is decidable from the table; a host the table calls undecided may honestly be described either way
  • r-recordgate335 a83ebe3 — Adding the observed noise keys to the denylist | ax, sha256 and the rest are one repository's accident, and the next repository invents different ones
  • r-recordgate335 a83ebe3 — Requiring Record-Id: to make a block a record | stale needs it for identity, but a commit carrying only Limit: is a record SPEC recognises and dropping it would lose real context
  • r-recordgate335 a83ebe3 — Inferring intent from position or neighbouring lines | that is guessing, and the failure mode is discarding a record somebody wrote on purpose
  • r-toolstate334 f4e89ef — Asserting the clone contains no unexpected path | the legitimate tree is large and grows, so the whitelist would fail on every honest addition and be widened without being read
  • r-toolstate334 f4e89ef — Forbidding every dotted directory | some are deliberate -- .github and .claude-plugin are the product -- and a rule that cannot tell those apart is not a rule
  • r-toolstate334 f4e89ef — Asserting only against .serena | it names the instance rather than the class, and the next one will have a different name
  • r-draftfirst329 0506a5d — Reporting all missing options at once | it would say the draft is unparseable and the transcript missing together, and the second is not true until the first is fixed
  • r-draftfirst329 0506a5d — Changing harvest --draft to match | it already resolves the draft first, verified by running it against the same prose rather than by reading the dispatch
  • r-strayserena 5c7c57a — Cutting 0.5.1 for this | the file is inert -- it changes no behaviour and breaks no install -- and a release exists to move something a user needs
  • r-strayserena 5c7c57a — Deleting it without a record | the tag that carries it is immutable, and a later reader comparing the two trees deserves the reason rather than an unexplained absence
  • r-strayserena 5c7c57a — Adding a stray-file assertion in this commit | test/manifest.test.ts belongs to another ticket's scope, and the guard is worth its own issue rather than a drive-by edit here
  • r-release050 ad402c7 — 0.4.2 | a new command and a platform support claim are not a patch, and calling them one hides both from anyone reading version numbers to decide whether to upgrade
  • r-release050 ad402c7 — 1.0.0 | nothing here breaks an existing install, and the milestone that closed is Gate B rather than a stability commitment
  • r-release050 ad402c7 — Describing Windows as supported without the caveat | the word is the one most likely to be read as more than it is, and the release that earns it is the right place to bound it
  • r-uninstall1123 4ddac0d — Removing the entry whose key is commitlore | it takes a server the user named that way and the other install's entry on a two-install machine, and neither loss is reported
  • r-uninstall1123 4ddac0d — Parsing the TOML config and writing it back | the round-trip reformats the whole file, which is the "never reformat beyond the one entry removed" this ticket forbids
  • r-uninstall1123 4ddac0d — Rewriting a config that failed to parse | the failure mode is losing a config we were only supposed to edit one key of
  • r-uninstall1123 4ddac0d — Removing the Claude Code plugin cache | it is thousands of files this command did not write, keyed by plugin version; naming the step is the honest boundary
  • r-winsupported1124 6333251 — Flipping the cell on the throwaway verification head | the ticket requires the attacks to pass in a required job in this ticket's own pull request, and a head that exists to be discarded is not that
  • r-winsupported1124 6333251 — Leaving the assertion pinned and editing only the document | the two contradict each other, so the suite would fail; a guard that blocks the change it was guarding for is a defect in the guard
  • r-winsupported1124 6333251 — Widening this ticket to the hook fix so it could be self-contained | the stop condition sent that to T-1127 for good reason, and this ticket's job was to measure and then say the word once measurement allowed it
  • r-winpath1127 bdf4ac0 — Normalising only the recorded root at write time | it would fix new installs and leave every existing repository comparing a stored win32 string against pwd -P output
  • r-winpath1127 bdf4ac0 — Loosening the containment match so the legitimate bundle runs | that trades Security: commitlore.bin and COMMITLORE_BIN are executed, and the env path lacks the guard the config path has #71's property for a working hook, which is exchanging one defect for another and is what this ticket's forbidden scope names
  • r-winpath1127 bdf4ac0 — Renaming the containment helper to match its new signature | T-1125's invariant asserts the old identifier as its proxy for the property surviving, and that test belongs to another ticket
  • r-winpath1127 bdf4ac0 — Fixing the stub and leaving doctor's mirror alone | the mirror reports no problem in precisely the state where the hook is dead, so the check that should warn would keep saying healthy
  • r-compat1122 e7d8516 — Carrying the README's musl reason into the matrix | it cites glibc-only binaries, and there are no binaries; repeating it would document a mechanism that no longer exists
  • r-compat1122 e7d8516 — Reading the gate's removal as musl support | absence of a check is not evidence of working, which is why it was executed on two architectures instead
  • r-compat1122 e7d8516 — Claiming musl as a class from one image | alpine:3.21 is what ran, so other musl distributions are undecided rather than promised
  • r-compat1122 e7d8516 — One prerequisite column covering both install paths | the plugin path checks nothing, so a shared column would imply an enforcement a user does not get
  • r-compat1122 e7d8516 — Asserting the documented install command as its own string | it is <plugin>@<marketplace>, so deriving it from the two manifests makes a rename of either fail here
  • r-muslbullet1126 04ac181 — Replacing the bullet with "musl is supported" | T-1122 owns the compatibility statement, and a second summary in the README is the duplication the ownership map exists to prevent
  • r-muslbullet1126 04ac181 — Removing the Windows bullet beside it | it is still true, test/readme.test.ts uses its exact wording as a mutation oracle, and T-1124 owns that claim
  • r-muslbullet1126 04ac181 — Folding this into T-1122's pull request | that ticket's forbidden scope is one pointer line per README and nothing else; widening it to fix an adjacent owner's debris is how single-writer discipline decays
  • r-muslbullet1126 04ac181 — Merging T-1122 first and cleaning up afterwards | two ordinary merges are not transactional, and the window where dev contradicts itself has no upper bound
  • r-nobin284 ab2f08f — Keeping the binary classification arm for the installer's wrapper | the wrapper is a shell script that execs node, so trusting it by name would re-admit any extensionless executable called commitlore while the bundle it runs is the thing with an interpreter to check
  • r-nobin284 ab2f08f — Relaxing the dogfood Evidence check to allow a missing path | it exists to catch a citation nobody can follow, and dropping the check to accommodate a deletion would retire the guarantee instead of correcting the question it asked
  • r-nobin284 ab2f08f — Leaving src/core/paths.ts alone because ADR-0026's inventory did not name it | it was the only remaining code that read files out of a compiled artifact, so leaving it would have left the invariant false while the test asserting it passed
  • r-nobin284 ab2f08f — Keeping /dist/commitlore in gitignore in case a binary returns | an ignore rule for an artifact nothing produces is a claim that something might, and the ADR says otherwise
  • r-pending311 4985a3a — Extending capture gc to also list what it would remove | gc answers what is collectable, and the transaction a caller cares about is usually the one gc will never touch
  • r-pending311 4985a3a — Storing stale in the transaction file | it is a fact about HEAD now, so a stored copy is wrong the moment HEAD moves and right only when it is redundant
  • r-pending311 4985a3a — Changing expires_at so verified transactions expire | it silently deletes work a caller may still stage, and this issue asked to see the state rather than to change the retention rule
  • r-pending311 4985a3a — Resolving an ambiguous prefix to the newest match | it guesses at the one moment the caller has proved they do not know which transaction they mean
  • r-query307 3cf3c58 — Testing the working tree with stat | a deleted file has real history and real records, so stat would report a missing path for one of the cases the diagnostic exists to distinguish
  • r-query307 3cf3c58 — A distinct exit code for a path that is not in history | context is on the hook path, where a nonzero exit is a failure to fail open around, and the caller who needs to branch has a diagnostic to read
  • r-query307 3cf3c58 — Emitting the diagnostic unconditionally from runQuery | the PreToolUse path queries a file that is often being created, so it would fire on every new file and break the hook's silence contract
  • r-query307 3cf3c58 — Searching for the nearest rename alias rather than the nearest ancestor | the alias walk is what already ran and found nothing, while the ancestor probe is bounded at four parents and answers the question that actually bit the reporter
  • r-capture309 5a9655d — Printing the reasons without unifying the two draft paths | the envelope path produced no reasons to print, so the output would still have been silent for the reported input
  • r-capture309 5a9655d — Keeping the envelope path unchecked and letting the verifier speak for it | the verifier checks whether a citation holds, not whether a field exists, so an unknown field is invisible to it by design
  • r-capture309 5a9655d — Defaulting the diff to the empty string and documenting that --diff is required | it makes the ordinary invocation useless and contradicts prepare, which needs no --diff to bind the same bytes
  • r-capture309 5a9655d — Comparing hashes leniently so an empty diff passes | the binding exists so a draft cannot be verified against sources other than the ones prepared, and loosening it removes the guarantee rather than the defect
  • r-harvest310 c055467 — Making the plain harvest message conditional on whether a diff exists | it would make the prescription accurate by narrowing it, leaving the contract still unreachable in the case that matters
  • r-harvest310 c055467 — Emitting the contract only when the transcript is also absent | that is what harvest --prompt-only refuses to print the contract without a transcript and a diff #229 landed and what this issue reports as insufficient, since a caller usually has a transcript before they have a diff
  • r-harvest310 c055467 — Keeping the old assertion and adding a new one beside it | two assertions requiring opposite outputs for one input is not a test suite, it is a coin toss
  • r-hooks296 b701559 — Making hooks install re-validate only when the hook file is unchanged | recordBinPath already runs every time, so the short-circuit was never the cause and gating on it would have left the wrong value being rewritten
  • r-hooks296 b701559 — Falling through to commitlore.node in the stub | it changes the file that carries install-root containment, and a stub already written in an affected repository is not re-read, so it would repair nobody who has the problem today
  • r-hooks296 b701559 — Having doctor --fix repoint the config itself | once the prescribed command works, the prescription is true; a second repair path would leave two places able to write the same key
  • r-hooks296 b701559 — Recording resolve(argv[1]) with a warning when it does not exist | the hook cannot act on a warning it never sees, and a recorded dead path is what stops resolution at the first step
  • r-idxhelp303 cd2ac79 — Deleting the better-sqlite3 mentions in index-db.ts as well | those comments explain why node:sqlite was chosen, and removing the reason leaves a future reader wondering whether the native option was considered
  • r-idxhelp303 cd2ac79 — Asserting the package name appears nowhere in src at all | that forbids the explanation along with the defect, so the check reads only lines that reach a user
  • r-idxhelp303 cd2ac79 — Naming node:sqlite in the message | the failure a user hits is that the binding is unavailable, and the module name adds nothing they can act on
  • r-t1120nodeinst 14deeb4 — Hardcoding the release version in install.sh as the default | it would add a bump obligation to every release and a stale default between a tag and the bump; git ls-remote resolves the newest tag with no API token and no rate limit
  • r-t1120nodeinst 14deeb4 — Defaulting to a branch when no tag is given | installing a moving target is what pinning exists to prevent, and the release gate already forbids a dev-referencing one-liner
  • r-t1120nodeinst 14deeb4 — Writing the wrapper with cp over the destination | an in-place overwrite of a file that may be executing is the defect that forced a same-day patch release; the wrapper is written beside the target and renamed
  • r-t1120nodeinst 14deeb4 — Letting post-install verification decide the exit code | that was the other half of the same defect, where a killed --version became the installer's exit status; verification now retries once and reports, and an install that succeeded exits 0
  • r-t1120nodeinst 14deeb4 — Editing the shell profile when the wrapper directory is not on PATH | an active record on this file rejects it, and printing the line is what this script does about PATH
  • r-t1120nodeinst 14deeb4 — A test-only environment hook to force a verification failure | a source repository whose bundle exits non-zero is a real broken release and needs no seam in shipped code
  • r-t1120nodeinst 14deeb4 — Checking for git with command -v alone | a git that cannot execute is as useless here as a missing one, so the check runs git --version and catches both
  • r-hookfailopen 16963dd — asserting the fail-open property against the working tree instead of a clone | this suite exists to test what a real install gets, and a working-tree assertion would pass while a clean clone was broken, which is the failure mode the suite was written to catch
  • r-hookfailopen 16963dd — covering this inside test/inject.test.ts with the other fail-open cases | those exercise the CLI, and this branch is reached only when no CLI can be resolved, so it belongs with the manifest suite that runs the script itself
  • r-mcpdraft291 d4444d5 — Changing the harvest contract to emit a bare array instead | the contract text, harvest's validator and the CLI all implement the object shape, so moving the contract would break two working surfaces to accommodate one broken one
  • r-mcpdraft291 d4444d5 — Accepting only the object shape and dropping bare-array support | the earlier tool description advertised an array, so a caller may exist that sends one; refusing it now would trade this defect for a different one
  • r-mcpdraft291 d4444d5 — Leaving the mismatch and documenting the array shape in the prompt | the prompt is generated by the same code the CLI uses, so the two consumers would then disagree about what the same generated text means
  • r-mcpadv273 0166937 — Omitting guard_advisory when it has no matches | absence on the wire reads as no ruled-out alternative applies, which is exactly the claim ADR-0020 forbids; an empty matches array with the disclosure attached says the true thing
  • r-mcpadv273 0166937 — Leaving the MCP response as the seven binding fields and treating the advisory as CLI-only | MCP is the first-class surface for every agent that is not using the Claude Code plugin, so a CLI-only advisory is an advisory most callers never see
  • r-t1110policy 9e7b37a — Hashing the parsed policy object instead of the file contents | ADR-0021 fixed the input as the contents, and it is the stronger choice: a reformat that changes nothing semantically still changes the identity, and reporting that the file changed is true
  • r-t1110policy 9e7b37a — Supporting a user-global policy file alongside the repository-local one | two locations need a precedence rule, and the user story this answers is repository-scoped, so one location removes the ambiguity rather than documenting it
  • r-t1110policy 9e7b37a — Ignoring an unknown key in the policy file | a silently dropped key lets a user believe a setting applied; rejecting it names the key and the allowed set
  • r-t1110policy 9e7b37a — Falling back to the defaults silently when the file cannot be parsed | the identity hash would then describe a policy the user never asked for, with nothing said about it
  • r-t1110policy 9e7b37a — Bumping the pending format version for the new field | ADR-0021 fixed the migration so no version change is needed, and producing one would falsify that ADR
  • r-gateb3rev a2e38b9 — Keeping the compiled binary as an optional extra alongside the Node path | the entire platform surface exists because of that one artifact, so optional keeps the release matrix, the per-target checksums, the binary-versus-script classification and the target compatibility matrix
  • r-gateb3rev a2e38b9 — Deleting ADR-0015 instead of marking it superseded | ADR-0011 links to it, and a record that vanishes leaves a broken reference and hides that the decision was ever made
  • r-gateb3rev a2e38b9 — Rewriting the README shell install instructions in this change | the shipped installer still downloads a platform asset, so the rewrite would describe behaviour the code does not have
  • r-gateb3rev a2e38b9 — Leading the install documentation with the shell one-liner and mentioning the plugin second | for a Claude Code user the plugin is one step that also registers MCP, the pre-edit hook and the skills, so leading with a CLI-only script hides the shorter path and leaves the agent surfaces unwired
  • r-gateb3rev a2e38b9 — Adding placeholder Gate B rows for the re-planned distribution work | an acceptance row with no approved ticket is the dangling authority the Gate A matrix was written to stop
  • r-gateb3rev a2e38b9 — Removing the compiled-binary code in this change | a scope reversal and a code removal are different reviews, and combining them lets the removal skip its own
  • r-t1109adv 4398856 — Emit raw GuardMatch objects in advisory | renderGuardMatch is the trust-grading boundary that withholds blocked content from model-visible surfaces
  • r-t1109adv 4398856 — Add a policy key to control advisory behavior | ADR-0020 classifies guard as non-blocking with no configuration escape
  • r-t1109adv 4398856 — Bump PendingRecord.version to 2 | ADR-0021 already fixed migration so no version bump is needed
  • r-rel041notes 71efe1f — folding this into the next feature release | the documented install is broken for upgraders now, and every day it stays tagged is a day the one-liner in the README fails for them
  • r-rel041notes 71efe1f — moving the v0.4.0 tag to the fixed commit | a tag users may already have fetched must not change under them; the fix gets its own version
  • r-rel040pins b76c40b — pinning after the tag exists so the reference is never briefly dangling | the notes, the version and the pin have to land together or the release is internally inconsistent at the moment it is cut, and the tag follows within the same promotion
  • r-rel040notes 5d57a72 — describing 0.4.0 as making agents safer | no study here measures agent behaviour, and the recovery protocol is registered and unrun; the release delivers a loop, not an outcome
  • r-rel040notes 5d57a72 — omitting guard's figures from the release notes because they are unflattering | the notes are read by people deciding whether to trust the tool, and a quality limit hidden at release time is discovered in use
  • r-gcwiring f21f28e — dropping --json from the gc subcommand and relying on the parent's | the subcommand would then document a flag it does not declare, and a reader of capture gc --help would not see it
  • r-gcwiring f21f28e — keeping requiredOption and giving gc its own top-level command | gc belongs to capture's surface, and moving it would make the fix a rename rather than a fix
  • r-flake221fix 2b21ed9 — downgrade evaluateInjectRun to warn | doctor.test.ts integration test asserts status=fail for ENOENT
  • r-flake221fix 2b21ed9 — remove trailers from init.test.ts repoWithRemote | weakens inject-probe test coverage without addressing the semantic defect
  • r-lb0xl89a 236229e — parameterising the contract with empty strings | prints a template with empty holes that teaches the session nothing about placeholder handling
  • r-t1009stage b5fcf4e — accepting base_head or a diff hash from the caller for efficiency | the caller is the party the transaction exists to constrain, so taking its word for the binding removes the point of the binding
  • r-t1009stage b5fcf4e — a single write_record tool that skips the transaction | PRD-F9 forbids it, and it would let a draft reach Git without ever being verified
  • r-t1005gates 15421c0 — blocking the commit when a gate fails | the commit is the user's work and the record is ours; failing their commit to protect our bookkeeping inverts whose job this is
  • r-t1005gates 15421c0 — treating a null expires_at as unexpired | null means the record was never staged, so it fails the staged requirement before expiry is consulted; reading it as "no expiry" would apply an unstaged record
  • r-t1016svg 321c6f1 — a terminal recorder dependency | the artifact would then depend on a tool's output format, and reproducing it would mean reproducing that tool's version
  • r-t1016svg 321c6f1 — a frame manifest with tolerance instead of byte comparison | a check that tolerates drift stops detecting the drift it exists to detect
  • r-t1006cli d22580b — exposing prepare, verify and stage as user-facing subcommands | the phases exist for the transaction, not for the user, and three commands is the problem this ticket removes
  • r-t1006cli d22580b — exiting non-zero when verification produces nothing | silence is the expected result for most commits, and a non-zero exit would train people to ignore it
  • r-t1007mcp b6ef112 — readOnlyHint: true | tool persists state under .git/commitlore/pending/ so marking it read-only would be dishonest
  • r-t1022sig e0c641d — keeping the score in text output behind a debug flag | a second flag for a number nobody should act on adds surface without adding information
  • r-t1022sig e0c641d — dropping the score from --json as well | a consumer that has already decided to parse structured output is not the reader being misled
  • r-t1021known 8dfffc1 — stating precision alone | precision without recall reads as a quality score and hides the failure mode that matters, which is silence
  • r-t1021known 8dfffc1 — publishing the point estimates without the Wilson interval | a figure without its interval is the defect this project removed from the README twice already
  • r-t1011demo 1c0fc0c — seeding the demo into the user's repository behind a confirmation | a demo that can modify the thing it is explaining is not a demo, and a confirmation prompt is not a substitute for being unable to
  • r-t1011demo 1c0fc0c — recomputing lifecycle inside the demo to keep it self-contained | a second implementation of the rule would drift from the one under test, and the demo would stop being evidence
  • r-t1020desc dd12b42 — removing the description entirely | the first two sentences carry useful contract information a caller needs
  • r-t1020desc dd12b42 — stating only precision without recall | a caller needs both to judge the signal; recall is the more dangerous gap
  • r-t1030diag 344ada0 — a single generic message that quotes stderr without case distinction | it would still let the old "carries no node" wording survive on the exit-127 path, and would not communicate to the reader whether the probe learned anything
  • r-t1030diag 344ada0 — parsing more than the first line of stderr to classify the cause | false-uncertain is acceptable, false-confident is not; one line is enough to distinguish the obvious cases
  • r-pin030readme 504b54e — referencing main instead of a tag | main is also mutable and does not name a reviewed release
  • r-pin030readme 504b54e — leaving the pin at v0.2.0 until the next release | v0.3.0 is tagged and published; the mismatch with package.json is a documentation defect now, not a timing issue
  • r-fix191amb cb94448 — adding a guard clause only in checkReferences | leaves the predicate willing to say "resolved" about an unresolvable group; any future third caller would silently inherit the same defect
  • r-fix191amb cb94448 — removing the post-filter entirely | the original fix for cross-commit succession is correct and the release gate depends on it
  • r-fix187val 40f2436 — passing tip-scoped records directly to findIdCollisions | chronological ordering by committedAt breaks on same-second commits from git-log's newest-first output; the post-filter avoids reordering entirely
  • r-fix187val 40f2436 — duplicating hasDeclaredSuccession into validate.ts | the drift between two copies of the same predicate was the bug; a second copy would reproduce it
  • r-notes030 a289ca5 — editing the dated benchmark artifact to restate its denominator | it is a provenance-stamped snapshot of one run, and rewriting a past measurement to read better today is the failure this project exists to prevent
  • r-notes030 a289ca5 — tagging first and correcting the notes after | the tag is what users read
  • r-dupsucceed 6f77fcf — adjusting the four expectations to match the new grades | they encode that trust does not depend on the order records appear in the log, which is a property of the protocol rather than of this implementation
  • r-valdup145 bcb9563 — adding a duplicate-id scan to validate on its own | it would have to decide block boundaries again, and a second answer to that question is what let parse and validate disagree in the first place
  • r-convtrail150 57e89d2 — excluding Fixes and Closes with the rest | they carry decision context an agent can use, and discarding them would trade a projection full of attribution for one missing the issue a change answers
  • r-epipe2026 d9ee9ff — error-first spawn result handling | a completed git process can retain a real status after the input-pipe EPIPE race
  • r-doctorepipe 0420f5c — the executable being absent from PATH | the failing run's own message names EPIPE, not ENOENT — the ENOENT branch produces different text than what CI printed, and the executable resolves and runs every time
  • r-init107 f485f07 — treating every doctor warn as actionable | no remote is expected before a repository begins sharing records, while configured remote failures still need action
  • r-init107 f485f07 — promising rename following for several paths | git log --follow accepts one pathspec and the CLI already reports that limit
  • r-survsplit e73aed5 — keeping a single conservation rate with a footnote | the two failures need different fixes and one of them is not a defect in this project at all, so a shared number misdirects the reader on both
  • r-be140cost 8c01bd5 — retaining a modelled break-even figure | a ratio inherits its weakest input, and the denominator is assumed rather than observed
  • r-probepath 51f6446 — prepending the build output to PATH inside the check | it would make CI green by giving the probe an executable no user has, which is the reverse of testing what is configured
  • r-readme129 ab5f210 — writing that CommitLore saves tokens | the cost is measured and the threshold is arithmetic, but nothing here shows the guard clears it, and that gap is the whole reason the section states three things instead of one
  • r-doctorprobe ed94491 — changing what init writes into settings.json | the installed hook was correct in every reported case; the check was reading a different world from the one it was auditing
  • r-m4basis 5e2d2cb — keeping the non-delivery wording as a hedged claim | it asserts something I never established, and a verdict that overstates its own evidence is the defect this repository exists to catch
  • r-m4withdraw e5f9b73 — retracting the dataset or calling M4 invalid | the data is valid and its provenance is clean; what it measured was not the treatment, and those are different words
  • r-readmeux1 b664205 — describing harvest as automatic record creation | it drafts from a transcript and a human still commits, and claiming otherwise is the overreach this project keeps closing issues about
  • r-rel021a a79e350 — retagging v0.2.0 | the tag is already on the remote and moving a published tag breaks anyone who fetched it
  • r-f61a2c 9114cf0 — raising the guard threshold | the frozen corpus puts every true positive in the middle band, so a higher cutoff removes signal without repairing score order
  • r-f61a2c 9114cf0 — dropping keyword evidence | long proposals and diffs dilute Jaccard, while one-token alternatives such as Redis still need lexical containment
  • r-m4docs1 32d5bf1 — keeping the withdrawal notice and only landing the verdict document | bench/report.ts already draws this line -- a provenanced dataset that still shows a withdrawal is a hard failure in check-readme-numbers.mjs (checked here), not a style choice left open
  • r-rel0200b 5870b35 — leaving "21 defects" and fixing only the GitHub Release body | CHANGELOG.md is the permanent record; a release-notes-only fix would leave the canonical file quoting a number two independent checks had already disproven
  • r-rel0200b 5870b35 — re-deriving a fresh defect count from scratch instead of verifying the given one | gh issue list --label bug,security undercounts (misses no-label and epic-labeled defect issues like doctor probed dist/cli.js while distribution ships dist/commitlore.mjs; CI red #40-56), so a bottom-up recount would have been less reliable than confirming the specific claim (Guard fires wrong 5 times out of 8 — precision 37.5% at the shipped threshold #61/commitlore-query skill teaches agents an invocation whose documented property is false #69 reopened) against the issue tracker directly, which matched
  • r-rel0200a a074754 — bumping ci.yml's "v0.1.0 was published with zero attached assets" comments | those describe a historical fact about the actual v0.1.0 release, not a version this project declares; the check they document (releases/latest/download/SHA256SUMS returning 200) is written to start exercising the real path automatically the day any release ships assets, v0.2.0 included, with no workflow edit
  • r-rel0200a a074754 — touching docs/adr/ADR-0001-scope-v010.md, docs/tickets/release.md, bench/VERDICT-M1.md, HANDOFF.md, bench/ROUTE-GAP.md | planning and historical-record prose that names v0.1.0 as a past decision or measurement subject, not a live version carrier
  • r-rel0200a a074754 — changing test/mcp.test.ts's CommitLore-Version: 0.1.0 fixture trailer | that's protocol-version content inside a synthetic seed commit (what an old commit's trailer looked like), unrelated to and never asserted against package.json's version
  • r-instci99a 318b9a2 — pre-installing curl/jq/tar/git in the containers before running install.sh | would hide exactly the gap this work exists to find — Debian ships neither curl nor wget by default, and asserting that failure cleanly is the point of the bare debian:stable-slim step, not an obstacle to route around
  • r-instci99a 318b9a2 — publishing a -musl release target so Alpine could install successfully | a release.yml/build-matrix change, not an install.sh or CI-verification fix; out of scope here (DO NOT: no Docker in the release build matrix) and orthogonal to making the existing failure clear instead of a raw crash
  • r-instci99a 318b9a2 — heuristically detecting musl before download (checking for /lib/ld-musl-*.so.1) | executing the freshly extracted, already checksum-verified binary directly is a stronger, more general check — it catches any reason the binary cannot run on this machine, not only the one musl signature this repository happens to know the path for
  • r-instci99a 318b9a2 — a matrix job splitting debian/alpine | the two images need different assertions (debian: bare failure, then success once curl is added; alpine: one clean failure, nothing more to add) and share one staged release + HTTP server; one job with named, ordered steps keeps that shared setup and reads linearly in the log
  • r-rdme96a 9c9371c — dropping the git-clone / source-build paths from the top entirely | install.sh is the fast path, not a universal one (no Windows binary yet, per ADR-0015) — the detailed section has to stay reachable, just not first
  • r-init96a 913c7e3 — running doctor --fix first, hooks/index after (the old README recipe's order) | doctor's report would open with findings the next two steps are about to fix, which reads as init shipping with a problem it does not have
  • r-init96a 913c7e3 — matching doctor's exit code exactly (0 unless a check is fail) | a warn init cannot resolve itself (no remote, PreToolUse hook) would then sit under a "completed cleanly" summary line — the same silent-success shape doctor's own fix breaks git fetch and git pull, then reports ok #63 and inject --hook-input is byte-identical on malformed input and on no-records: silent fail-open #67 were
  • r-fix92dupid 7f41a6e — flagging every duplicate sha in a group regardless of payload, matching parse's labelRecordBlocks exactly | validate's own collision-check array pairs repositoryRecords (already carrying the message's last block once) with a per-block candidate; an unconditional duplicate-sha rule would flag the message's own single last block against its own re-derived copy, a false positive fixed instead by building ownRecords once per message rather than loosening the predicate past correctness
  • r-fix92dupid 7f41a6e — reverting core/query.ts's collectRows dedup key back to sha+source+seq once findIdCollisions was fixed | that key was already wrong on its own terms (it does not match the trailers table's unique index), and leaving it in place would keep silently dropping a commit's second record block from any scoped-path context query, collision or not
  • r-fix90shape 7f5766d — keeping the parent-count signal and also computing it for --message-file via .git/MERGE_HEAD | that only exists while a merge is in progress (the commit-msg hook's own scenario), not when re-validating an already-made merge commit's extracted message -- which is the issue's own reproduction and stays unreconciled under that approach
  • r-fix93pkg 9c4a396 — repointing bin at dist/commitlore.mjs instead of removing it | that entry exists only to serve a package-manager install ADR-0011 already replaced with a git clone; repointing it keeps maintaining a path to an install mode that will never happen
  • r-fix93pkg 9c4a396 — also removing files now | the issue's own "After B-09 · Single static binary — remove the Node runtime dependency #39" note groups bin/files/dependencies as one cleanup once the static binary lands; files alone is inert without a registry rather than actively broken, so doing it now means doing it twice
  • r-relinstall c6e1d04 — guessing the current version to build the asset URL directly | would need either the GitHub API (rate-limited, needs no-auth headers handled correctly) or trusting a redirect's final Location header parsing. Downloading the fixed-URL SHA256SUMS first and reading the real asset name back out of it needs neither and is what the checksum step has to fetch anyway.
  • r-relinstall c6e1d04local for scoping — not POSIX per se, but supported by dash, bash, and every shell this script is realistically piped into (verified directly, see Verified) | not used in the end; the script has few enough variables that scoping was not needed, only noted here because it was considered.
  • r-distrace88 d118a73 — consolidating the four files' redundant tsc rebuilds into one vitest globalSetup | would remove the race for every file at once and is the more complete root-cause fix, but touches five files' bootstrap plus global config, and mcp.test.ts's beforeAll already tolerates unrelated in-flight tsc errors elsewhere in src/ (OWNED_SOURCES filtering) in a way a single shared build step cannot preserve without its own redesign — bigger blast radius than this issue asked for.
  • r-distrace88 d118a73 — raising bench-ablation's timeout, globally or per-test | proven not to be a timeout problem at all: execFileSync blocks synchronously, so vitest's timeout mechanism cannot even engage against it (verified with a probe test); the actual failure is the runner subprocess legitimately exiting 1.
  • r-parsemulti 6d39d25 — expanding findIdCollisions/index-db to flag a same-message duplicate id generally | reaches into query.ts's lifecycle fold and every consumer route (context, guard, stale) for a case bug-issue-89 only asked parse to surface; the smaller, requested fix is in parse alone.
  • r-multirec01 92aeb24 — minting a fresh Record-Id for an inherited record that never declared one | no other code path in this project invents identity; Record-Id is always author-declared, and doing it here would be new scope beyond what the issue asked for
  • r-multirec01 92aeb24 — a CI step comparing a PR's commits against its post-merge squash commit, as the primary mechanism for finding 1 | needs a GitHub API dependency this tool takes nowhere else, and can only run after the squash is already pushed; doctor catches the same mistake locally, before push, when the source branch is still in refs/heads
  • r-plugman51 db8e2a1 — PreToolUse hook fires twice per edit | Claude Code's plugin loader dedups a manifest.hooks path that resolves (via realpath) to the already-loaded hooks/hooks.json before merging it, so the hooks array is never doubled; the redeclaration instead surfaced as a hook-load-failed PluginError under the loader's default strict mode
  • r-83d43117 8a49ddc — an install-root check for COMMITLORE_BIN | its only reason to exist is aiming the hook at a build outside the install root -- a test harness, a monorepo's local bin. Restricting its location would remove the one thing it is for; doctor's existing COMMITLORE_BIN visibility is the right amount of scrutiny for a channel that is supposed to point anywhere.
  • r-83d43117 8a49ddc — resolving commitlore.bin with an external realpath/readlink -f binary | neither is guaranteed on every machine a hook runs on, the same reasoning 1fd0d53 gave for not shelling out to shasum. cd ... && pwd -P is a POSIX-specified builtin and covers the same physical-resolution need without a new dependency.
  • r-exit065 e545dee — leaving guard's inversion in place and only documenting it | guard and inject are the two commands wired into hooks and CI, so a script written against guard today is already trusting the number; a documented inversion is still an inversion, and it gets load-bearing the longer it sits. The surface is one boolean per command right now — cheaper to fix once than to explain forever.
  • r-fix70a1 d707fc7 — exhaustive per-language phrase enumeration | unbounded phrase lists cannot provide semantic coverage, so this fix documents a bounded lexical policy and independent corpus
  • r-shwt66 5efa206 — checking --git-dir/shallow | linked worktrees keep the shallow marker in the common Git directory
  • r-fix760 fb8ba45 — testing commits with more than one parent in dogfood scope | their platform-generated merge messages carry no authored decision, so requiring a record would require one nobody wrote
  • r-refint74 572f573 — allowing a note to extend a commit record under the same Record-Id | notes are remote-reachable, so divergent content would inherit a human-approved identity
  • r-warn75 24c7cc8 — accepting run-on or indented trailers | Git treats them as prose and accepting them would make records ambiguous
  • r-doctor72 996bcde — choosing either parent doctor list | each drops a runtime check required by the other incident
  • r-fix067 a915af0 — treat an outside-repository file_path as a legitimate no-record result | only an in-repository query can truthfully establish that no records apply; silence would hide a broken matcher
  • r-fix063h f0bb995 — leave hook runtime as a separate contradictory check | a fix-bearing installation check must not report ok or warn when the installed hook demonstrably fails
  • r-fix063 0b8c496 — add the explicit refspec only after confirming the remote ref exists | setup would depend on today’s remote state and require another doctor run after the first notes push
  • r-det058 695cdf6 — add the 100k history suite to CI | CI budget and deterministic local measurement are separate decisions
  • r-fix053 ecc4b90 — add a public mirrored boolean | the per-record sources array already models contributing channels, so a second representation would create drift
  • r-fix055 43b40f8 — infer whether a quote supports Verified | deterministic text matching can prove presence, not that a check ran
  • r-fix055 43b40f8 — downgrade harvested Verified to reconstructed | it preserves a citation-bearing assertion the verifier cannot substantiate
  • r-fix054 664d4e2 — write X-Inherited-From into commit messages too | transport metadata would lengthen every preserved user-facing message merely to restore symmetry
  • r-fix054 664d4e2 — stop squash-preserve from writing notes | it discards the mirror instead of fixing the query seam
  • r-fix056 55cb8bc — reuse the injection omission list for blocked withholding | it includes prose-bearing Evidence and Expires, so it is not a safety boundary
  • r-7b26f1 ec070ec — retrying the read inside the transaction | a write lock held across a subprocess is a worse failure than the one being fixed
  • r-1e58d3 1fd0d53 — removing the recorded-path branch entirely | a clone is on no PATH and in no node_modules (ADR-0011), and that branch is the only thing that finds the CLI there

Truncated: 150 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.

@MongLong0214
MongLong0214 merged commit d76ad0b into main Aug 1, 2026
16 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.

1 participant