Skip to content

A green merge is not evidence your work survived it (overnight-multi-issue-implementation 1.4.0) - #29

Merged
wan-huiyan merged 1 commit into
mainfrom
claude/stale-base-audit
Aug 7, 2026
Merged

A green merge is not evidence your work survived it (overnight-multi-issue-implementation 1.4.0)#29
wan-huiyan merged 1 commit into
mainfrom
claude/stale-base-audit

Conversation

@wan-huiyan

Copy link
Copy Markdown
Owner

Adds a new top-level section to overnight-multi-issue-implementation, placed immediately after "Pre-flight: parallel-branch file-collision audit" as its inward mirror: "Pre-flight: stale-base audit — what your OWN branch deletes". The existing audit looks outward at branches that might conflict with you; this one looks at the branch you are about to merge.

The rule

Two halves, and the second is why nobody looks:

  1. A merged, green pull request is not evidence your work survived it.
  2. A branch built on a stale base can delete other people's work without a single conflict — no marker, no red check, no failing validator. A schema validator cannot tell a deletion from a decision.

The evidence — one incident, 2026-08-07

Every figure below was verified against the host repo's git history and the GitHub API before it was written down, not taken from the brief.

  • Merged from a branch created before several other pull requests landed and never rebased. Its conflict resolution took its own side across the whole tree.
  • 59 files, 1,891 insertions, 5,081 deletions (gh api .../pulls/853, and git show --stat on the merge commit).
  • Reverted 11 files and 15 tracker entries belonging to three other sessions — source modules, their tests, analysis pages, next-session handoff prompts, tracker rows — plus a function two surviving files still imported.
  • Nothing failed. No conflict, green PR, schema validator passed, site still rendered.
  • All three affected sessions had finished a wrap-up that morning and their work was on main — for between 6 and 90 minutes. Fastest discovery: 16 minutes 36 seconds (merge 09:30:23Z, issue filed 09:46:59Z), and it was an accident.
  • The merged content was legitimate — rulings the owner had personally ticked — so git revert was the wrong tool; it would have destroyed everything merged after it.

Two dots, not three — a correction found while drafting

The brief proposed git diff origin/main...HEAD --diff-filter=D --stat. Three dots diffs from the merge base, so on a branch that never took main's newer commits, a file added to main after the branch point is absent from both sides and reports as no change at all.

Verified on a two-commit synthetic repo: three-dot prints nothing, two-dot prints the file. (In this particular incident three-dot did fire, but only because that branch had merged main in and taken its own side, moving its merge base up to current main — an accident of shape, not something to rely on.)

The section ships the two-dot form, rebase-first ordering, and the note that a plain merge of a stale branch is harmless — git keeps what only main has. The damage needs the branch's tree to win wholesale.

The audit-after half: the existence check is the weak one

git cat-file -e asks only whether a path exists. A file can be present with its contents rolled back to a pre-session version, and no existence check, no id check and no validator will report it. So audit for a marker your change added, chosen so a rollback necessarily removes it. Three lines: grep a phrase you added (expect ≥1), grep a phrase you deleted (expect 0), and for a structured record diff its text against the pre-merge version rather than checking its id.

Worked example — measured, not argued

A page of seven interactive widgets whose option lists are single-quoted HTML attributes read by one JSON.parse inside a single forEach. Three options contain an apostrophe behind a one-character '.

Roll that escape back on the fourth widget and the file exists, the HTML is valid, all seven widgets are in the markup, every committed check that touches the page passes — and four of the seven are silently dead, because the truncated attribute throws and the throw aborts the loop.

Loaded the real page in jsdom with each escape rolled back in turn: fourth widget broken leaves 3 working; first widget broken leaves 0; sixth leaves 5. git cat-file -e says the file is fine in every case.

Recovery

Never git revert the offending merge — work has merged on top. Splice each object forward from the last commit where it was intact (git show <sha>:<path>). Plus the three things that bite during a splice: restore what the restored file imports, re-check state before each restore because parallel sessions are repairing at the same time, and re-measure any figure a restored file carries.

Version

1.3.1 → 1.4.0 in SKILL.md frontmatter, plugin.json, and .claude-plugin/marketplace.json.

The four-location list needed correcting. The bundle VERSION file already reads 1.4.0 — set there by the 2026-08-06 release of two other plugins. It is the bundle's own counter, not a mirror of this plugin's version, and the release one day ago (#28) shipped a plugin version bump without touching it. Left unchanged, and the README entry says so explicitly so the next person does not read the coincidence as a copy.

README "Version history" entry added.

Gates

gate result
python3 scripts/check_skill_descriptions.py . --no-color --triggers exit 0
scripts/leak_scan.sh LEAK GATE: clean (exit 0)
python3 .github/scripts/validate_plugins.py OK: marketplace + plugins valid (0 warnings)
--compare main:…/SKILL.md …/SKILL.md 1,463 → 1,463 chars, 8 triggers unchanged, none dropped or narrowed

Description is byte-identical; only the body grew. Listing budget fits at 1M context (30,504 / 40,000 chars).

🤖 Generated with Claude Code

https://claude.ai/code/session_01UCqwdBqETB9SeEVR2fSTfK

…ence your work survived it (1.4.0)

Adds "Pre-flight: stale-base audit — what your OWN branch deletes", placed
immediately after the parallel-branch file-collision audit as its inward mirror.
That audit looks outward at branches that might conflict with you; this one looks
at the branch you are about to merge.

THE EVIDENCE IS ONE INCIDENT, 2026-08-07. A pull request merged from a branch
created before several other pull requests landed and never rebased; its conflict
resolution took its own side across the whole tree. 59 files, 1,891 insertions,
5,081 deletions. It reverted 11 files and 15 tracker entries belonging to three
other sessions -- source modules, their tests, analysis pages, handoff prompts,
tracker rows -- plus a function two surviving files still imported. Nothing
failed: no conflict, green PR, schema validator passed, site still rendered. All
three sessions had finished a wrap-up that morning and their work WAS on main,
for between 6 and 90 minutes. The merged content was legitimate and had to stand,
so git revert was the wrong tool.

TWO DOTS, NOT THREE -- a correction the drafting turned up. The brief for this
change proposed `git diff origin/main...HEAD --diff-filter=D`. Three dots diffs
from the MERGE BASE, so on a branch that never took main's newer commits a file
added to main after the branch point is absent from both sides and reports as no
change at all. Verified on a two-commit synthetic repo: three-dot prints nothing,
two-dot prints the file. The section ships the two-dot form, rebase-first
ordering, and the note that a plain merge of a stale branch is harmless -- the
damage needs the branch's tree to win wholesale.

THE EXISTENCE CHECK IS THE WEAK ONE. `git cat-file -e` asks only whether a path
exists; a file can be present with its contents rolled back and no existence
check, id check or validator will report it. Audit instead for a marker your
change ADDED. Worked example, measured rather than argued: a page of seven
interactive widgets whose option lists are single-quoted HTML attributes, three
holding an apostrophe behind a one-character `&#39;`. Roll that escape back on
the fourth widget and the file exists, the HTML is valid, all seven widgets are
in the markup, every committed check passes -- and four of the seven are silently
dead, because the truncated attribute throws inside the one forEach that builds
them all. Loading the real page with each escape rolled back in turn gives three
working, or none if the first widget is the one broken.

Recovery is a splice-forward (`git show <sha>:<path>`), never a revert.

Version: SKILL frontmatter, plugin.json and marketplace.json all 1.3.1 -> 1.4.0.
Bundle VERSION already reads 1.4.0 from the 2026-08-06 release and is unchanged:
it is the bundle's own counter, not a mirror of this plugin's version, and the
release one day earlier (#28) shipped a plugin bump without touching it.

Gates: check_skill_descriptions --triggers exit 0 (description byte-identical,
1,463 chars, 8 triggers unchanged per --compare); leak_scan clean;
validate_plugins OK, 0 warnings.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UCqwdBqETB9SeEVR2fSTfK
@wan-huiyan
wan-huiyan merged commit 3df43c3 into main Aug 7, 2026
1 check passed
@wan-huiyan
wan-huiyan deleted the claude/stale-base-audit branch August 7, 2026 12:48
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