Skip to content

fix: inherit records, not every trailer paragraph, on squash-preserve - #1154

Merged
MongLong0214 merged 1 commit into
mainfrom
fix-1153-nonrecord-blocks
Oct 3, 2026
Merged

MongLong0214 merged 1 commit into
mainfrom
fix-1153-nonrecord-blocks

Conversation

@MongLong0214

Copy link
Copy Markdown
Owner

Closes #1153

What happened

squash-preserve collected a merge commit whose final paragraph held one
Claude-Session: line as an inherited record, stamped it with
Provenance: inherited <sha>, and the composed message was then refused:

shape failed · 169: unknown-key Claude-Session — got "Claude-Session", want "a key from SPEC §3, or X-Claude-Session if this is your own metadata"

git decides what a trailer block is, and a message's last paragraph qualifies
whatever its keys mean — so the paragraph cannot be refused at parse time. The
filter has to run on what the parse returns, which is the question
types.ts isCommitLoreKey already answers for the index, where paragraphs like
sha256: and Tests: were served to agents as recorded decisions (#335).

The change

  • core/squash.ts — an inherited block carries only the keys this protocol
    defines, and a block left with none contributes nothing. Applied where both
    channels become candidate records, before mergeCommitBlocks matches them,
    so neither channel can reintroduce what the other dropped.
  • core/stale.ts — the inherited-copy comparison in the collision check
    compares the record's own content and ignores keys outside the vocabulary.
    Without this the mixed case stops failing on unknown-key and starts failing
    on duplicate-id: stripping the foreign keys makes a faithful copy differ
    from its origin.

Per trailer rather than per block, because a paragraph mixing Limit: with a
foreign key is a real record — dropping the whole block would lose it, and
inheriting it whole would still fail validate. A Signed-off-by: on the
origin goes the same way: it is an attestation about that commit, and
inheriting it would assert a sign-off on a commit nobody signed.

Verification

  • Two new tests in test/squash.test.ts: the reported paragraph, and the mixed
    block. Run against the unfixed build first — both fail, the first with exactly
    the reported {"rule": "unknown-key", "key": "Claude-Session"}.
  • Negative control per half: with only the squash.ts change the mixed case
    fails on duplicate-id; both halves are load-bearing.
  • Full suite green (212 files, 4614 tests), tsc --noEmit clean.

Known residual

A commit that already landed with an inherited non-record block re-squashes to
a block whose only key is Provenance: — it validates, and it says nothing.
Recorded as a Warn: on the commit rather than filtered, since nothing reported
that shape and the output is valid.

dist/ is deliberately absent: canonical-merge.yml rebuilds it and
regenerates the manifest.

git decides what a trailer block is, and a message's last paragraph qualifies
whatever its keys mean. A merge commit whose final paragraph held one
`Claude-Session:` line was therefore collected as an inherited record, stamped
with `Provenance: inherited <sha>`, and the composed squash message was refused
by `commitlore validate` with `unknown-key Claude-Session` -- blocking the merge
that `squash-preserve` had been run to protect.

An inherited block now carries only the keys this protocol defines, and a block
left with none contributes nothing. The filter is per trailer rather than per
block because a paragraph mixing `Limit:` with a foreign key is a real record:
dropping the block would lose it, and inheriting it whole would still fail
validate on the foreign key.

The collision check had to agree. Stripping those keys makes a faithful copy
differ from its origin, and the mixed case stopped failing on `unknown-key` and
started failing on `duplicate-id` -- so the inherited-copy comparison compares
the record's own content and ignores what the vocabulary does not cover, the
same exemption #1148 made for the transport stamp.

Both halves are load-bearing: the new tests were run with each change absent in
turn and fail without it.

Limit: git's grammar makes a message's last paragraph a trailer block whatever its keys mean, so the paragraph cannot be refused at parse time
Limit: the inherited-copy comparison now ignores keys outside the vocabulary, so a copy carrying a different value for one than its origin did is no longer reported as a collision
Ruled-out: dropping only the blocks whose every key is foreign | a paragraph mixing `Limit:` with `Claude-Session:` is a real record, and inheriting it whole still composes a message validate refuses on the foreign key
Ruled-out: comparing an inherited copy against its origin in full | stripping the foreign keys makes every faithful copy read as a divergent re-declaration, the false refusal #1148 removed for the provenance stamp
Warn: a commit that already landed with an inherited non-record block re-squashes to a block whose only key is `Provenance:` -- it validates, and it says nothing
Blast: module
Undo: easy
Certainty: firm
Record-Id: r-nonrecordblock1153
Provenance: drafted
@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown

CommitLore — record lint

Trailers: clean — 1 commit in origin/main..95a197b3418b0a22b746a33abaaad6ab2d74df7b
Active constraints: 37 limits · 58 ruled-out · 26 warnings — from 29 records over 3 changed paths

Active constraints for the paths this PR touches

Limits (37)

  • r-nonrecordblock1153 95a197b — git's grammar makes a message's last paragraph a trailer block whatever its keys mean, so the paragraph cannot be refused at parse time
  • r-nonrecordblock1153 95a197b — the inherited-copy comparison now ignores keys outside the vocabulary, so a copy carrying a different value for one than its origin did is no longer reported as a collision
  • r-foldedrivalweakens 3e8f454 — this follows from reading the predicate rather than from a measurement -- two attempts to build the shape produced blocks that split instead of folding, so the escape was reasoned about and never reproduced
  • r-foldedblockrival 9d03112 — the window opened at Squash merge destroys every record on the branch — measured 0/20 survival #60 which introduced multi-block inheritance, and A Record-Id declared in both the commit message and the note blocks the whole record, over a trailer the note itself dropped #1020 only narrowed the consequence from the whole record to the diverging keys
  • r-foldedblockrival 9d03112 — the reporter read the note through git interpret-trailers --parse, which reads only the last block, so their count of one Record-Id was two
  • r-peraxiscollision1020 5cf992c — the trailer loss that produced the divergence is unexplained and untouched, so a note can still be written that disagrees with its commit -- this changes what a reader is told about that, not whether it happens
  • r-peraxiscollision1020 5cf992c — a divergence on a content axis still withholds that axis entirely, so a reader whose Limit: diverged sees no Limit: at all rather than both candidates
  • r-peraxiscollision1020 5cf992c — the per-key comparison is by exact value, so two declarations differing only in whitespace under one key diverge on it
  • r-declaredids1012 176644f — the lifecycle fold has the same one-id-per-record assumption and is not touched here -- on the reporting repository 52 distinct commit-declared ids fold to 32 states, so about twenty records have no lifecycle at all and cannot be reported superseded, expired or for review; filed separately rather than guessed at, because the fix is either splitting a block at each Record-Id or making squash inheritance separate its blocks, and that is a decision
  • r-declaredids1012 176644f — nothing here stops a block carrying several ids from being written; this makes the reference check read one correctly, it does not decide whether that shape is well-formed
  • r-warmbeforewalk975 2ea7432 — the remaining 30 are notes and the index scan, not this row, which is now one process; a note's own block still costs one apiece because %(trailers) parses the annotated commit and there is no atom for a note body
  • r-probeconsumers975 adcbd50 — the block cache lives on CollectCache and therefore for one invocation only -- hoisting it to module scope would serve a rewritten message from memory, which is the staleness r-staleonepass names
  • r-probeconsumers975 adcbd50 — doctor still spends 71 parses against a complete index, through its own short per-branch ranges; batching within a range trades N parses for one batch and a short range has few, so the batch has to span ranges to help there
  • r-samequestiontwice d3ebb3d — the pending memo cannot see a git-dir that moves mid-process, which is not a thing a worktree does while something is reading it
  • r-samequestiontwice d3ebb3d — doctor is still 731 spawns on that repository; this removed the duplicated reads, not the walks, and the remaining cost is one range walk per candidate branch
  • r-staleonepass c7a606a — the equivalence is proven over this repository's history and 23 constructed hazards, not over every message git can parse; the guard covers the one framing failure found, and a second would need its own
  • r-staleonepass c7a606a — the cache holds one entry per commit and one per note for the life of the invocation -- memory traded for spawns, paid by whatever range is being walked
  • r-staleonepass c7a606a — a note whose last paragraph is prose after a record block used to yield nothing and now yields the earlier blocks, which is the index's behaviour and a change in what such a note reports
  • r-mirrorprov890 f4c2f46 — the notes branch of hasAmbiguousGroup still never checks that a note's sha matches another member's, so a note sharing an id with an unrelated commit is separated only by payload divergence
  • r-mirrorprov890 f4c2f46 — the mirror is recognised by content rather than by a marker, so a note that coincidentally matches a commit's block modulo provenance is treated as its mirror
  • r-833multiblocknotice fe84c6b — this makes the cost audible, it does not remove it. A merge commit written from a multi-block draft still carries records that git-native tooling will not report as trailers, and --target remains the only way to have every record visible on both channels
  • r-provsha1 6d82fcc — is a git object id — 4 hex digits (git's shortest abbreviation) through 64 (a full SHA-256), either case
  • r-amendid430 4c450eb — commit-msg gets no argument, environment variable or ref that distinguishes an amend from an ordinary commit
  • 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-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-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-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-merge66 40e7987 — Generated dist files were resolved only by npm run build and npm run bundle
  • r-refint74 572f573 — validate cannot perform conservation checks because it has no before state
  • r-1b7d94 736ef92 — git reads ambient configuration, so a suite that does not neutralise it is testing the developer's machine as much as the code
  • 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

Ruled out (58)

  • r-nonrecordblock1153 95a197b — dropping only the blocks whose every key is foreign | a paragraph mixing Limit: with Claude-Session: is a real record, and inheriting it whole still composes a message validate refuses on the foreign key
  • r-nonrecordblock1153 95a197b — comparing an inherited copy against its origin in full | stripping the foreign keys makes every faithful copy read as a divergent re-declaration, the false refusal fix: validate preserved squash drafts and prepare 1.7.2 #1148 removed for the provenance stamp
  • r-foldedrivalweakens 3e8f454 — rewriting the merged commit to carry the Limit | published history is baselined, and a force-push over a merged commit is the one thing this repository's own records forbid
  • r-foldedrivalweakens 3e8f454 — leaving the Limit only in the closed pull request | a reader of the predicate finds the source and not the pull request
  • r-foldedrivalweakens 3e8f454 — tightening the predicate to close the shape instead | that returns every squash-merged repository to withholding records that agree, which is the defect being fixed
  • r-foldedblockrival 9d03112 — forgiving any note that is a subset of its message | a single-record note dropping a key is the omission A Record-Id declared in both the commit message and the note blocks the whole record, over a trailer the note itself dropped #1020 decided to withhold, and overturning that decision was not in scope
  • r-foldedblockrival 9d03112 — splitting a folded block into per-record blocks positionally | serializeTrailers orders by vocabulary rather than by record, so no positional rule recovers the boundary reliably
  • r-foldedblockrival 9d03112 — blaming renderMessage | it frames blocks correctly, and running it was what showed that
  • r-peraxiscollision1020 5cf992c — keeping the whole-record block and adding the two git commands to its message | the reporter already had to find those commands; being told where to look does not return the axes that never diverged
  • r-peraxiscollision1020 5cf992c — serving the divergent axis with both values and letting the reader choose | a note is remote-reachable, so that hands an unapproved claim to the agent under an approved identity, which is the rule this preserves
  • r-peraxiscollision1020 5cf992c — treating a metadata axis as always safe to serve | it is safe because the declarations agree, not because the key is metadata; a diverged Blast: is as unapproved as a diverged Limit:
  • r-declaredids1012 176644f — skipping trailer-shaped lines inside fenced code blocks, as the report suggested | measured on the reporting commit, git's trailer atom already yields nothing from that block, so the rule would guard a path nothing takes while moving a boundary git owns
  • r-declaredids1012 176644f — refusing a Follows: value that does not match the id grammar | findDanglingRefs already skips those and validateRecord reports them as format; reporting one line under two rules makes the repair loop chase it twice
  • r-warmbeforewalk975 2ea7432 — probing the last paragraph in the same batch as the earlier ones | the last block's framing depends on the whole message, and an isolated single-paragraph probe is not the same question -- the shape that fabricated a record once already
  • r-warmbeforewalk975 2ea7432 — a six-branch fixture for the budget test | it measured 7 against 2, and a ceiling between them is one an unrelated change crosses by accident; the first version of this test used six and passed against the defect
  • r-probeconsumers975 adcbd50 — batching inside collectRange | it is squash-preserve's reader and doctor's, not validate's, and batching there changed neither command -- the stack attribution is what found the reader that mattered
  • r-probeconsumers975 adcbd50 — memoising the note blocks by sha alone | the reference pass sees sources with no sha yet, which is the case the commit-msg hook takes, so the cache is keyed on the message text
  • r-probeconsumers975 adcbd50 — pairing noteMessages with readRecordBlocks | both call showNote, so the batch would have read every note twice and spent more processes than it saved
  • r-probeconsumers975 adcbd50 — writing the measurement rule down without a harness | I had noticed this failure three times before making it a fourth, so noticing is demonstrably not the mechanism
  • r-samequestiontwice d3ebb3d — a process-global pending directory cache | one process answers for several worktrees in a long-lived server, and a global memo would hand one repository's path to another
  • r-samequestiontwice d3ebb3d — passing the resolved directory down through every pending call site | it threads a parameter through a dozen signatures to avoid a lookup whose answer is fixed, where a keyed memo says the same thing in one place
  • r-samequestiontwice d3ebb3d — reading the note bodies eagerly for every candidate up front | most candidates share few commits, so it pays for notes no range asks about
  • r-staleonepass c7a606a — serving collectRecords from the SQLite index | it is HEAD-only and stores stripped trailers and a different note set, so a walk over an arbitrary revision cannot be answered from it, and closing that would rebuild the window and the mirror filter somewhere new
  • r-staleonepass c7a606a — collapsing the per-commit walks into one | each walk's reachable set decides whether a reference resolves at that commit, and one walk answers a different question
  • r-staleonepass c7a606a — a module-level cache | it would outlive the invocation, and a long-lived MCP server is where a rewritten sha or a fetched mirror would then be served from memory
  • r-staleonepass c7a606a — taking the atom without proving it equals the process parser | the index asserted the equivalence in a comment and nothing tested it; a faster parser that is wrong anywhere is worse than a slow one everywhere
  • r-staleonepass c7a606a — widening readRecord itself | it has callers that want exactly one record, and changing what it returns would move them all silently
  • r-mirrorprov890 f4c2f46 — treat any note on a commit as one declaration with that commit's message | it discards the ability to notice a note that diverged from the message it mirrors, which is the case r-refint74 made collide because notes are remote-reachable
  • r-mirrorprov890 f4c2f46 — stop squash-preserve writing a note when the target's message already carries the record | it fixes the producer and leaves every repository that already has these notes withholding, including the reporter's
  • r-mirrorprov890 f4c2f46 — exclude Provenance from payloadSignature everywhere | it would also excuse a provenance-only difference between two different commits, where which declaration is current is a real question
  • r-833multiblocknotice fe84c6b — folding every record into the final paragraph | it satisfies git by collapsing the records for CommitLore, and the boundary rule that would split them back has no clean form while Record-Id is emitted before Provenance
  • r-833multiblocknotice fe84c6b — refusing to write a multi-block draft | it disables the documented repair for most branches to prevent a loss that is real for other tooling and not for this one, and the notes path was already available for callers who need git-visible fidelity
  • r-833multiblocknotice fe84c6b — changing SPEC 2.4's record boundary here | the docstring already says a record is "terminated by Record-Id" while the code splits on paragraphs, and reconciling those is a format decision that belongs with the owner rather than inside a bug fix
  • 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-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-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
  • r-secondtie 998bf18 — Reusing trailers.id as that ordinal | rebuildIndex inserts in git rev-list HEAD order, newest first, and updateIndex appends newer batches after it, so the rowid runs backwards within a rebuild and forwards across them
  • r-secondtie 998bf18 — Sorting both serving paths by (committed_ts, commit_sha) so they agree exactly | it buys symmetry by discarding the one real topological signal available, the order of the git log walk, making the path that has a signal as arbitrary as the path that has none
  • r-secondtie 998bf18 — Resolving the conflict deterministically and saying nothing | determinism only makes two commands agree on an answer neither of them earned, and this repository treats a confident wrong answer as worse than a declared unknown
  • r-secondtie 998bf18 — Adding a fourth Lifecycle value for the undecidable case | active plus the existing review flag already says a human must decide, and a new enum member is a resolution-contract change every consumer would have to be taught
  • 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-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-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-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-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-1b7d94 736ef92 — pass -c flags everywhere | they cover the test's own git calls and miss every call made by the code under test
  • r-1b7d94 736ef92 — give notes.ts a fallback identity | it would hide a real misconfiguration in a user's repository behind a fake author
  • r-9a5e17 6d68703 — let each command edit src/cli.ts | guaranteed conflict, and the conflict surfaces only after every worker has finished
  • r-9a5e17 6d68703 — npx fallback in the hook stub | a network call on every commit, and offline commits start failing

Warnings (26)

  • r-nonrecordblock1153 95a197b (claim) — a commit that already landed with an inherited non-record block re-squashes to a block whose only key is Provenance: -- it validates, and it says nothing
  • r-caeffdf409dc e809c8f (claim) — 원본과 복사본의 관계는 충돌 판단에 사용하고, notes 작성자 검증과 trust grading은 별도로 유지한다.
  • r-foldedrivalweakens 3e8f454 (claim) — a folded block carries both records' pairs, so a note that attributes the second record's content to the first record's identity is still a subset and is now served rather than withheld -- before the fix it was withheld, and that is the shape r-refint74 cares about because notes are remote-reachable
  • r-foldedrivalweakens 3e8f454 (claim) — a watcher that merges on green and an amend of the commit it is watching cannot both be in flight -- the canonical for the pre-amend commit merged before the close took effect, so main carries the fix with the incomplete record
  • r-foldedblockrival 9d03112 (claim) — the framing is broken by the forge, not by commitlore -- the reported commit has committer GitHub and one parent, so the message was composed by the squash merge while writeRecordBlocks wrote the note, and only one of them frames blocks
  • r-foldedblockrival 9d03112 (claim) — I first read renderMessage's join as contradicting its own doc comment and that was wrong -- serializeTrailers ends every block with a newline, so joining with one more produces the blank line; running it was what showed that
  • r-foldedblockrival 9d03112 (claim) — the folded case also serves the second record twice, once from each channel, because the message block is grouped under its first Record-Id only; same root cause, different symptom, not fixed here
  • r-peraxiscollision1020 5cf992c (claim) — GradedRecord gains collisionKeys, and a consumer branching on identityCollision alone now sees records that carry it while still serving trailers
  • r-peraxiscollision1020 5cf992c (claim) — inject reads collisionKeys to decide whether to withhold the whole record, so a future caller that sets identityCollision without it gets the old blanket behaviour rather than a crash -- which is the safe direction and is easy to reach by accident
  • r-declaredids1012 176644f (claim) — declared is now a superset of what it was, so a reference that was reported dangling on a real defect would also stop being reported -- the control for that is the case asserting an undeclared id is still caught
  • r-warmbeforewalk975 2ea7432 (claim) — the revisions go on stdin because 200 candidates is about 16 KiB of argv against Windows' 32 KiB, and a range containing a newline is dropped rather than allowed to inject another revision
  • r-probeconsumers975 adcbd50 (claim) — the harness refuses to run without --index cold or --index complete. That is deliberate: the index state changed doctor's count by more than most changes do, and a measurement that does not name it is not comparable with any other
  • r-samequestiontwice d3ebb3d (claim) — RangeCache now has two maps and a set, and the next read added to collectRange needs the same question asked of it -- the two halves were added in separate releases because the first one was not asked
  • r-staleonepass c7a606a (claim) — CollectCache and RangeCache must never be shared across invocations; only the caller creating them keeps that true, and hoisting one to module scope reintroduces exactly the staleness they avoid
  • r-staleonepass c7a606a (claim) — readRecord still returns the last block only, and a future reader picking it for a records question rebuilds this defect -- the corrected comment is the only thing standing there
  • r-mirrorprov890 f4c2f46 (claim) — forgiving anything beyond Provenance here starts trading a tamper signal for quieter output; the asymmetry is the safety property
  • r-provsha1 6d82fcc (claim) — do not retighten the schema pattern independently of PROVENANCE_VALUE_PATTERN — test/provenance-sha.test.ts is the lock
  • r-amendid430 4c450eb (claim) — this relaxes identity, not content -- a re-declaration differing in any trailer, carrying no payload at all, or following a supersession of the same id is still a collision
  • r-dupsuccorder f46c02d (claim) — preserve chronological ordering when changing duplicate detection
  • r-dupsucc729 5a6b238 (claim) — a successor must remain later than the duplicate declaration
  • r-multirec01 92aeb24 (claim) — index-db.ts SCHEMA_VERSION is now 2 for the added block column — bump it again, not the shape in place, the next time the trailers table changes.
  • r-merge66 40e7987 (claim) — test/hooks.test.ts must keep both worktree git-path resolution and reference-integrity assertions
  • r-refint74 572f573 (claim) — exact commit and note mirrors remain one logical record; only divergent note payloads collide
  • r-1a63f5 2bb4993 (claim) — "CI is green" was said five times today against a red CI, including in the commit that introduced the rule saying to check CI before saying it. The rule is in docs/RELEASE-GATE.md §5 and it was not followed by its own author. This commit is not claiming CI is green; that claim comes after the run reports
  • r-1b7d94 736ef92 (claim) — keep the GIT_CONFIG_* overrides in vitest.config.ts -- removing them makes the suite pass on developer machines and fail in CI, with a message that points at git rather than at the test
  • r-9a5e17 6d68703 (claim) — commands are advertised in --help only once they work -- test/cli.test.ts holds the landed and unlanded lists, and moving a name between them belongs in the commit that wires it

git log --follow accepts exactly one pathspec, so renames are not followed for 3 paths; query one path at a time to follow its rename chain

withheld the content of 1 record(s) graded blocked: a Ruled-out, Verified trailers matching an injection pattern is reported, never quoted (SPEC §7)

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

MongLong0214 added a commit that referenced this pull request Oct 3, 2026
@MongLong0214
MongLong0214 merged commit c5df520 into main Oct 3, 2026
10 of 13 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.

squash-preserve turns a non-record trailer paragraph into an inherited record that validate rejects

1 participant