Proposal (rationale)
release-changelog-fragment accepts a reasoned changelog-ok: marker anywhere in the current
contents of a changed shipping file. Once such a marker lands on the integration branch, every later
branch that changes an unrelated line in that file can reuse the historical reason without adding
either a fragment or new exemption evidence. The gate is branch-aware for companion fragments and
branch-blind for its escape hatch.
Arena will create the sustained backlog pressure this gate is meant to support. Shipping a reusable exemption before its evidence is scoped to the work being checked would turn one legitimate waiver into a permanent off switch on a hot file.
Decision
accepted — 2026-09-05, during the user-authorised Arena Lab bootstrap. An exemption satisfies
change-requires-file only when the marker has a substantive same-line reason whose wording is new
to the complete current branch/worktree delta against the resolved integration ref. Existing
markers may remain as history, but reusing, duplicating, moving or copying any reason already present
in the merge-base tree supplies no evidence for new shipping work; rewording is the explicit proof.
Plan
Requirements
- Determine exemption provenance against the same exact merge base used to collect changed paths; do not inspect the complete current file as though every line belonged to this branch.
- Include committed, staged, unstaged and non-ignored untracked exemption edits with the same verdict before and after staging/committing.
- Preserve the substantive same-line reason rule; bare markers, wrapper punctuation, next-line text, deleted markers and binary/unreadable evidence remain refusals.
- Reject reason wording inherited anywhere from the integration branch, including duplicates and text carried through a pure rename, copy or line move while unrelated shipping content changes.
- Read candidate evidence only from canonically contained regular UTF-8 text that Git attributes do
not declare binary; aliases, symlinks (including mode
120000entries materialized as ordinary files by Git), invalid text and binary files cannot waive a fragment. - When a candidate has an index entry, require exactly one stage-zero ordinary blob mode; allow an
index-absent candidate only after validating its untracked filesystem leaf. Historical
HEADmode does not override the current index proposal. - Carry block-comment, HTML-comment and quoted-string state across document lines so a marker in a multiline wrapper ends at its actual close token and cannot absorb adjacent implementation text.
- Preserve NUL-safe path handling, deterministic local/origin/sole-remote integration resolution, no-renames changed-path semantics and explicit failure when Git cannot establish provenance.
Impacts
changeRequiresFileand a narrow Git line-provenance helper insrc/engines2.ts.- Git-backed core regressions and the release module’s self-test fixture builder/table cases.
- Release-module version and generated claims only if its shipped table or fixture contract changes; no new gate, marker or consumer parameter is introduced.
Approach
Collect the complete changed-path view against the resolved merge base with argv-based Git calls and
NUL-delimited path discovery; never interpolate a path or ref into a shell command. Extract the
reason text with a document-aware scanner for common comment/string wrappers so adjacent code or
formatting is not mistaken for a reason edit. Read the full matching merge-base blobs rather than
context-free grep lines. Build one conservative set of all substantive reason strings present in
the merge-base tree, then accept only contained regular UTF-8 text whose reason is absent from that
set. When the path is present in the index, accept only a single stage-zero ordinary blob mode, even
when a platform configured with core.symlinks=false exposes a mode 120000 entry as a regular
file. An absent index entry delegates to the already validated untracked leaf. Do not consult
historical HEAD mode: a staged 120000 to 100644 conversion is current ordinary evidence.
This deliberately resolves an unknowable copied-versus-coincidentally-identical sentence the same
way before and after staging: historical wording must be reworded for the current branch.
Keep the existing path-level changed set for deciding whether shipping work and a companion fragment participate. Line provenance narrows only the exemption branch; failure to parse textual provenance means no exemption, not a guessed pass.
Acceptance criteria / tests
- A base-branch file already containing a substantive marker fails when a later branch changes an
unrelated line and supplies no fragment; the exact F-043 reproduction fails in production
runGatesas well as the direct engine. - Adding a marker with new reason wording or modifying inherited reason wording passes in committed, staged, unstaged and untracked files, with the verdict unchanged across those state transitions. Reusing merge-base wording fails consistently in all four states.
- A duplicate, pure rename/copy or line move carrying inherited wording fails; changing the reason during the move passes. Deleted files/markers, aliases, symlinks and binary or unreadable text cannot exempt.
- Bare, next-line, quoted and comment-wrapper-only reasons retain their current failures. Wrapper state spanning lines isolates the reason from adjacent code in block comments, HTML comments and quoted strings, while a genuinely new multiline-wrapped reason passes. A valid branch-local reason still satisfies only a branch that also changes a configured shipping path.
- Git mode
120000evidence fails in staged/index and committed states even when Git checks it out as an ordinary file; ordinary untracked, staged and committed blob evidence remains valid. A120000to100644conversion passes once the ordinary mode is staged and after commit, while the inverse passes only before its proposed120000mode reaches the index and then fails. - Local, exact
originand sole-other-remote bases produce identical provenance decisions; ambiguous or absent refs fail closed with the existing actionable result. - Every release self-test still executes in both directions with zero newly unrun fixtures.
- Focused tests, full
npm test, package dry-run,git diff --checkand all registered Rungs gates pass. The exact pushed SHA passes all six OS/Node matrix cells and the site job.
Out of scope
- Replacing inline exemptions with a separate approval file, judging whether a stated reason is true, requiring a reviewer identity, or changing which paths count as shipping work.
- WI-076 archive containment, WI-077 eject independence, F-034 line-ending normalization, publishing v0.4.0 or Arena’s downstream migration.
Execution
Started from verified green/main at 0833172a780da6377da081e7423c46d7bc370186 after WI-076
landed.
The final review hardening replaces line-local wrapper inference with full-document state and reads
the original matching blobs from the merge-base tree. It also verifies the current index proposal
when present, closing the core.symlinks=false representation gap without letting historical
HEAD mode veto a staged ordinary conversion. Regression fixtures exercise all three multiline
wrapper families and create both directions of 120000/100644 mode transitions through Git
plumbing, so the Windows path requires no symlink privilege.
Local verification after that hardening: 11 focused change-requires-file/exemption groups passed;
the full suite passed 93 of 96 tests with the three expected platform skips; all 30 registered gates
passed; and npm pack --dry-run --json produced 110 entries (360,302-byte archive, 1,227,099 bytes
unpacked). git diff --check was clean.
Exact implementation tip 169553a1 passed CI run 33974024054 across the site job and all six
OS/Node cells. After WI-081, exact main 2c897fd5 merged as e8b1b270; the only code-adjacent
resolution combined independent test fixtures and corrected their aggregate count from seven to
eight. After WI-080, exact main f8089cb1 merged conflict-free as final branch tip afb8cefc.
That tree passed all 11 focused groups, the full suite (137 pass and three expected skips), all 30
gates, a 113-entry 384,448-byte package dry-run, and git diff --check. Exact CI run 33976880904
passed every matrix cell plus site. rungs land then verified 30/30 gates in the merged scratch and
atomically advanced main plus green/main to implementation merge 96f03e99.
Review
Independent final review of fb81f76 found the line-local multiline-wrapper bypass and the missing
Git-object-mode check. Follow-up review of e984004 found that also consulting historical HEAD
incorrectly rejected a currently staged ordinary conversion. The current implementation makes the
index proposal authoritative when present and keeps the canonical untracked-leaf fallback.
Independent final review approved exact tip 169553a1 with no findings after reproducing both
object-mode transitions and verifying conflicted-index, unreadable Git evidence, multiline
wrappers, UTF-8/binary/alias boundaries, global wording reuse, all focused tests, 30 gates, package
contents and exact CI. Both later main integrations changed no production semantics and passed
their own seven-job exact CI runs, completing the acceptance evidence.