Development record
main's Unreleased section carries a hand-written entry the derived cut refuses. Commit 3dc7aba3 (round-7 resolutions, PR #511) added a '### Fixed' entry under '## [Unreleased]' on a branch parallel to 5897a85d, the commit that adopted the derived-changelog rule (Unreleased must be EMPTY or the launch ship ingest refuses); neither author could see the other, and the collision only exists on merged main. As written, the next 'launch ship' refuses the cut. The entry's content is already carried by the two resolved records it cites (iss-2608261040378346, iss-2608261041020040), so the remedy is removing the hand-written entry, not relocating it. Structural half: nothing gates Unreleased emptiness at merge time, so any two parallel branches can recreate this class silently until release; a compose-time or CI check on '## [Unreleased]' being empty is the durable fix (same family as iss-220's compose-time-prevention finding). Rounds 8a/8b (#512/#513) were checked and touch no CHANGELOG.
main's Unreleased section carries a hand-written entry the derived cut refuses. Commit 3dc7aba3 (round-7 resolutions, PR #511) added a '### Fixed' entry under '## [Unreleased]' on a branch parallel to 5897a85d, the commit that adopted the derived-changelog rule (Unreleased must be EMPTY or the launch ship ingest refuses); neither author could see the other, and the collision only exists on merged main. As written, the next 'launch ship' refuses the cut. The entry's content is already carried by the two resolved records it cites (iss-2608261040378346, iss-2608261041020040), so the remedy is removing the hand-written entry, not relocating it. Structural half: nothing gates Unreleased emptiness at merge time, so any two parallel branches can recreate this class silently until release; a compose-time or CI check on '## [Unreleased]' being empty is the durable fix (same family as iss-220's compose-time-prevention finding). Rounds 8a/8b (#512/#513) were checked and touch no CHANGELOG.
Frontmatter
| id | iss-2608261312157721 |
|---|---|
| type | issue |
| lifecycle | resolved |
| severity | major |
.abcd/work/issues/resolved/iss-2608261312157721-unreleased-hand-entry-vs-derived-cut.md
open on GitHub ↗ · commit history ↗
mentions3
- iss-220simple deterministic CI failures have no compose-time prevention or self-repair path: the attribution gate detects a missing PR-body Assisted-by trailer post-hoc (PR 230), but nothing composes or verifies the body at creation time and no loop is authorised to apply the mechanical fix. PR-body composition is facilitator-owned manual work and therefore automation backlog: abcd should compose/verify the PR surfaces it requires for managed repos, and an allowlisted class of deterministic check failures (trailer append, formatting) should be self-repairing
- iss-2608261040378346check-issue-resolution.sh scans cwd-relative and dies silently on a non-iss path, and RS002 reachability-checks a commit: line in a record body. Three sibling holes in the new issue-resolution gate: (1) it never cd's to the repo toplevel like check-reviews.sh does, so a git pathspec run from a subdirectory matches nothing and the gate reports a clean pass having scanned zero records — RS003, the drift detector with no other check, passes vacuously; (2) under set -euo pipefail the id extractors end a matched case with 'basename | grep ^iss-', which exits 1 on a non-iss filename, so when that is the last diff entry the while-loop and the closed= assignment inherit the failure and the script dies exit 1 with no diagnostic, RS001/RS002 never running; (3) RS002 greps the raw range diff for a '+ commit:' line with no frontmatter boundary, so a commit: example in a record's prose body is reachability-checked and raises a false violation — the exact boundary RS003 already draws. Fix: cd to toplevel; make the id extraction non-fatal; read the frontmatter per changed record via a helper RS003 shares.
- iss-2608261041020040check-issue-resolution-cases.sh runs its scratch-repo git commands under the inherited environment, so an ambient GIT_DIR or global core.hooksPath corrupts the caller's repo or breaks the gate. The harness builds ~60 'git -C $d' fixtures but omits the hermetic-env scrub its sibling check-attribution-cases.sh carries (iss-28, iss-313, resolved four days before this script was authored): an inherited absolute GIT_DIR overrides -C and redirects the fixture commits and config onto the ambient repository while every case still prints ok (green-while-corrupting, reachable on a direct make preflight under a git alias / rebase -x / bisect run); and an inherited GIT_CONFIG_GLOBAL / core.hooksPath — which this repo's .githooks/pre-push documents the maintainer uses — fires the developer's global pre-commit hook inside the scratch repos and turns make lint-issues red with no gate diagnostic. Fix: hoist the same unset GIT_DIR family + export GIT_CONFIG_GLOBAL=/dev/null scrub before the first git call.