Skip to content

Commit ad84a19

Browse files
author
Coditan-XO
committed
no-mistakes(review): correct due-line staleness prose and ladder rung X/E order
1 parent 5287c2b commit ad84a19

5 files changed

Lines changed: 182 additions & 17 deletions

File tree

.agents/skills/bootstrap-diagnostics/SKILL.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ When any diagnostic needs captain attention, report the plain consequence and re
6565
A `config/fork-sync-upstream is unusable` detail is not a network failure: the check refused a configured comparison base, so handle it as `CURRENCY_BASE` below.
6666
- `GROSSREINSCHIFF: weekly fleet cleanup sweep is due (...)` - this home has not completed its Thursday cleanup sweep for the current week; load the `grossreinschiff` skill and run it.
6767
Nothing is broken: the line is a cadence reminder, and it repeats each session start until `bin/fm-grossreinschiff-due.sh --record` marks a sweep that actually produced a report.
68-
The reported window-open days say how late the sweep is, and a large number is itself worth reporting to the captain because it means this home has been dark or the reminder has been passed over.
68+
The reported window-open days say only how far into the current week's window this session start falls; the count is bounded to 0 through 6 and never measures how long the home has been dark.
69+
Judge staleness from the `last swept:` date in the same line: a date more than one week before the current Thursday means whole weeks were missed, and that is what is worth reporting to the captain.
6970
In a session that did not get the fleet lock this line is advisory only: the sweep changes records, so the session holding the lock owns it - note it and leave it.
7071
- `TANGLE: <remediation>` - the primary checkout is stranded on a feature branch instead of its default branch; `AGENTS.md` section 8 explains why this guard exists and what it protects.
7172
The work is safe on that branch ref; restore the primary to its default branch with the printed `git -C <root> checkout <default>`, then re-validate that branch in a proper worktree.

.agents/skills/grossreinschiff/SKILL.md

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ None is hypothetical, and `docs/grossreinschiff.md` carries the incident behind
2222

2323
**Cadence: weekly, on Thursday.**
2424
`bin/fm-grossreinschiff-due.sh` owns it and nothing else - its header states the rule, the state file, and why there is no separate scheduler.
25-
The sweep runs at the first session start on or after Thursday; a vessel that was dark on Thursday sweeps late rather than skipping the week, and the due line says how late.
25+
The sweep runs at the first session start on or after Thursday; a vessel that was dark on Thursday sweeps late rather than skipping the week.
26+
The due line reports how far into the current window the sweep is, a count bounded to 0 through 6; its `last swept:` date is the field that shows how many weeks were missed.
2627

2728
## The five safety properties
2829

@@ -53,27 +54,36 @@ These bind every item below. They are properties, not preferences: each one is a
5354
## The landedness ladder
5455

5556
Item 1 turns entirely on this, and getting it wrong is the one mistake in this skill that destroys work.
56-
Apply the tests in order and stop at the first that settles the branch.
57+
Apply the tests in the table's order - **A**, **P**, **E**, **C**, **X** - and stop at the first that settles the branch.
58+
The order is measured, not a matter of taste: the trap notes below say what moving a rung costs.
5759
The technique is not this skill's invention: the worktree-scoped form is owned by `bin/fm-teardown.sh`, whose header is the authority on what "landed" means for a task's own work, and the per-branch form below was worked out and validated in `data/bridge-branch-sprawl-classify/report.md` §1.
5860
That report is captain-private to the vessel that ran it, so a reader on another home cannot open it - `docs/grossreinschiff.md` carries the measurements and the reproduction, and is tracked.
5961

6062
| Code | Test | Settles |
6163
|:-:|---|---|
6264
| **A** | `git merge-base --is-ancestor <branch> <default>` | landed. Only ever a *positive* result - a negative one means nothing here. |
6365
| **P** | Patch-id equality: `git diff $(git merge-base <default> <branch>) <branch> \| git patch-id --stable` against `git diff <merge_sha>^ <merge_sha> \| git patch-id --stable`, where `<merge_sha>` is the forge's recorded merge commit for that branch's PR *and* is itself an ancestor of the default branch. | landed. This is the test that handles the squash flow, and it does most of the work. |
66+
| **E** | The branch tip's tree equals its merge-base tree. Only meaningful *after* **A** and **P**: for a branch that is already an ancestor of the default branch the merge base **is** the branch, so this holds trivially and would relabel every ordinarily landed branch. | landed vacuously - the branch has commits but changes nothing against its fork point, so there is nothing to land. |
6467
| **C** | `git merge-tree --write-tree <default> <branch>` exits 0 **and** its first line equals `git rev-parse <default>^{tree}`. | landed - the branch adds nothing the default branch does not already have. |
65-
| **X** | Every path the branch adds is absent from the default branch's tree **and** `git log <default> -- <path>` is empty, so it never existed there at any point. | not landed. |
66-
| **E** | The branch tip's tree equals its merge-base tree. | landed vacuously - there is nothing to land. |
68+
| **X** | **Precondition: the branch adds at least one path.** A branch that adds none - a modify-only or delete-only branch, the ordinary shape of a small fix - falls through to `undetermined`, never to `not landed`. With that precondition met: every path the branch adds is absent from the default branch's tree **and** `git log <default> -- <path>` is empty, so it never existed there at any point. | not landed. |
6769
| - | none of the above | **undetermined**. Never a deletion candidate. |
6870

69-
Two traps, both hit in practice:
71+
Four traps.
72+
The first two were hit in practice; the last two were caught by applying this skill's own checklist to this skill before it shipped, and `docs/grossreinschiff.md` records that.
7073

7174
- **C is inconclusive far more often than it looks.**
7275
`git merge-tree` exits non-zero on a conflict, and an old branch whose files the default branch has since edited conflicts routinely.
7376
A caller that reads only the tree hash and drops the exit status reads a conflict as "adds content" - which reads as "not landed" - and that is a delete-real-work bug.
7477
Measured on this repo, 2026-08-03: over 52 merged-PR branches the ladder settled 18 by **A**, 33 by **P**, 1 by **C**, and 0 undetermined. In the same session, **C** applied alone with its exit status dropped reported "adds content" for all six ancestry-unmerged branches it was tried on - and for the three of those six that are branches of merged pull requests, the full ladder settles every one as landed.
7578
- **P needs the merge commit verified as an ancestor of the default branch**, not merely recorded by the forge.
7679
A recorded merge commit that is not on the default branch proves nothing about the default branch.
80+
- **A vacuous universal is a false certainty.**
81+
**X** is quantified over the paths the branch adds, so a branch that adds none satisfies both of its conjuncts on zero evidence and would be handed the definitive verdict `not landed`.
82+
That state is reachable exactly where this ladder is routine: **A** fails because the fleet squashes, **P** fails when no forge merge commit is recorded or it is not an ancestor of the default branch, and **C** goes inconclusive on the conflict above.
83+
Safety property 3 bars promoting an unsettled branch to a definitive verdict, so the precondition in the **X** row is the rule and has no exception.
84+
- **E's place in the order is load-bearing in both directions.**
85+
It must come after **A**, because a branch that is already an ancestor has itself as its merge base and would be relabelled `landed (vacuous)` on a triviality.
86+
It must come before **C**, because a content-free branch cannot make `merge-tree` conflict, so **C** would absorb it as plain `landed` and **E** would never fire at all.
7787

7888
Patch-id is safe for rename-only branches - it hashes the `diff --git a/… b/…` header paths, so a pure rename still produces a distinct hash rather than an empty one.
7989
Before trusting a P result across a large set, check for patch-id collisions across the whole set, as §1 of the sprawl report does; a hash shared by two different pieces of work invalidates every P verdict in the batch.

bin/fm-grossreinschiff-due.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,13 @@
1212
# home that has never swept is the one most likely to have accumulated
1313
# something, and it joins the Thursday rhythm after its first sweep. A home
1414
# that ran no session on Thursday sweeps late at its next session start rather
15-
# than skipping the week, and the due line says how late.
15+
# than skipping the week.
16+
#
17+
# The due line's window-open count says how far into the CURRENT window this
18+
# session start falls. It is bounded to 0 through 6 by construction and does
19+
# not measure how long the home has been dark: a home three weeks behind that
20+
# wakes on a Thursday reads 0. The "last swept:" date on the same line is what
21+
# shows how many weeks were missed.
1622
#
1723
# There is deliberately no scheduler here. The check is one file read and one
1824
# date comparison, so bin/fm-bootstrap.sh runs it in the detect pass that

docs/grossreinschiff.md

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,18 @@ A check registration and its trust binding for `graph-freshness`, with no `state
116116

117117
Measured on `Freudator86/firstmate` at `origin/main` = `d126ea61`, 2026-08-03, over the 52 branches of merged pull requests that still exist on `origin`.
118118

119-
The ladder, applied in order A → P → C, stopping at the first test that settles a branch:
119+
**The applied order is A → P → E → C → X**, stopping at the first test that settles a branch.
120+
121+
The published measurement below ran A → P → C, before E and X were placed in the order.
122+
Inserting E between P and C does not change it: none of the 34 non-ancestor branches was content-free, so E fires on none of them and these counts stand as measured.
120123

121124
=== A(ancestry)=18 P(patch-id)=33 C(content)=1 undetermined=0
122125

126+
E must never be placed before A.
127+
For a branch that is already an ancestor of the default branch, `merge-base(default, branch)` **is** the branch, so E's tree-equality condition holds trivially for every ordinarily landed branch: placed first, it would have relabelled all 18 ancestry-settled branches above as `landed (vacuous)`.
128+
Placed after A it sees only the 34 non-ancestor branches, and fires on none of them.
129+
It must still come before C, because a content-free branch cannot make `merge-tree` conflict, so C would settle it as plain `landed` and E would never fire at all.
130+
123131
**Ancestry alone would have called 34 of 52 landed branches unmerged.** On `coditan-bridge` the same reading was worse: 152 of 154 read as unmerged, because PR #1 is the only pull request in that repository's history merged with a real merge commit - the only merge commit in 7,724 commits on `main`. Everything else was squashed, so branch tips are unreachable from `main` by construction. "152 not merged" is a restatement of "we squash", nothing more.
124132

125133
### The content test is inconclusive far more often than it looks
@@ -163,7 +171,9 @@ Three options were considered.
163171
The rule, owned by the script's header: **due when the last recorded sweep predates the most recent Thursday 00:00 local.**
164172

165173
- An absent record means never swept, which is due. A home that has never swept is the one most likely to have accumulated something, and it joins the Thursday rhythm after its first sweep.
166-
- A home that ran no session on Thursday sweeps at its next session start rather than skipping the week, and the line says how many days into the window it is.
174+
- A home that ran no session on Thursday sweeps at its next session start rather than skipping the week, and the line says how many days into the *current* window it is.
175+
That count is `days_back`, bounded to 0 through 6, so it is a window position and never a measure of lateness: a home three weeks dark that wakes on a Thursday reads 0.
176+
The line's `last swept:` date is the field that carries the staleness, and it is what the reader judges by.
167177
- A corrupt or unparseable record reads as never swept, so it makes the sweep due rather than silently skipping it.
168178
- The week boundary is today's local midnight minus whole days, so a daylight-saving change inside the preceding week moves it by an hour twice a year. An hour of drift cannot make a weekly sweep fire twice or skip a week.
169179

@@ -173,6 +183,24 @@ Through the pin, like every other instruction-surface change: it lands on the de
173183

174184
One All-Ships notice announces the day and what the sweep covers. That is an announcement, not the mechanism - a vessel that never reads the notice still gets the due line from its own session start, and a vessel that reads the notice but never pins never sweeps.
175185

186+
## The sweep's own checklist, applied to the sweep
187+
188+
Before this skill shipped, its own nine-item checklist was run against its own prose.
189+
It got three hits, all the same defect class the sweep exists to clean, and all three were fixed before delivery.
190+
191+
- **The due line's window-open count is bounded to 0 through 6 by construction**, so it can never report a home dark for weeks: a home three weeks behind that wakes on a Thursday reads 0, while one merely four days late reads 4.
192+
The handling guidance told the reader to escalate on a large number, which is an instrument that never fires - checklist item 3.
193+
The `last swept:` date already carried the signal, and the guidance now points there.
194+
- **Ladder rung X returned a definitive `not landed` for a branch that adds no paths**, because a universal over an empty set is vacuously true.
195+
A verdict on zero evidence is a false certainty, and it is exactly what safety property 2 warns about when it bans judging by ancestry - and property 3, which bars promoting an unsettled branch to a definitive verdict.
196+
X now carries the precondition in its own row.
197+
- **Ladder rung E could never be reached** in the A → P → C → X → E order it was first written in, because C absorbs every content-free branch first.
198+
An unreachable rung is dead text - item 3 again.
199+
E now sits between P and C, and the order caveat is recorded above because moving it either way is measurably wrong.
200+
201+
This is recorded plainly because it is evidence the checklist works, not an embarrassment to soften.
202+
The night of 2026-08-02/03 produced the checklist from other people's surfaces; the first thing it was pointed at was its own, and it found three.
203+
176204
## Known limits
177205

178206
Stated here because the skill requires every sweep to state its own, and the mechanism should hold itself to the same rule.

0 commit comments

Comments
 (0)