Skip to content

feat(skills): add Großreinschiff, the weekly fleet cleanup sweep - #59

Merged
Freudator86 merged 2 commits into
mainfrom
fm/fleet-grossreinschiff
Aug 3, 2026
Merged

feat(skills): add Großreinschiff, the weekly fleet cleanup sweep#59
Freudator86 merged 2 commits into
mainfrom
fm/fleet-grossreinschiff

Conversation

@Freudator86

Copy link
Copy Markdown
Owner

Intent

Build Großreinschiff: a fleet-wide cleanup sweep that runs every Thursday, shipped as a skill in firstmate's shared instruction surface so it reaches every vessel through the pin. Captain's decision 2026-08-03; first fleet-wide run Thursday 2026-08-06. Spelling is one word - Reinschiff is the seaman's term for cleaning the ship and the intensifier compounds onto it; the prose keeps the ss-ligature per the repo's German-spelling rule while the directory and script stay ASCII.

The sweep's nine-item checklist was dictated by the captain, each item earned by a measured incident in the night of 2026-08-02/03, none hypothetical: (1) merged branches nothing prunes, (2) records whose stated facts no longer hold, (3) no-op instructions that cannot fire, (4) duplicate records for one defect, (5) consolidation pointers into nothing, (6) counts including something that never existed, (7) tool currency outside the managed suite, (8) borrowed material without attribution, (9) leftover workspaces and state. The captain's numbering is preserved deliberately so a later reader can map findings back to the original decision.

The captain specified five safety properties as properties rather than preferences: it reports before it deletes and deletion is a separate authorised step; it never tests landedness by ancestry because this fleet squashes; it never touches unlanded work and a refusal is stop-and-investigate; each finding names its evidence so the next sweep re-measures instead of inheriting a belief; and it states what it did NOT cover, because a sweep implying completeness it lacks is itself the defect class it cleans.

Decisions made while building it:

Cadence - the captain asked me to decide and document whether the reminder is a scheduled wake, a session-start item, or a fleet-wide notice, and explicitly said not to build a second scheduler if one already fits. I chose a session-start item: the due check is one file read and one date comparison, so bin/fm-bootstrap.sh runs it in the detect pass that already happens once per session start. A watcher check: poll was rejected because that mechanism is per-task, registered against a task id and torn down with it, so a fleet-level sweep would need a new registration class and trust binding. An external cron/systemd timer (the pattern fm-firstmate-update-check.sh and fm-fork-sync-check.sh use) was rejected because those make network calls that earn a timer while this makes none, and a timer adds a per-home install step nothing verifies - so a home that never installed it would silently never sweep, which is checklist item 3 built into the thing meant to find item 3. A fleet notice announces but cannot make anything recur. The rejected alternatives are recorded in docs/grossreinschiff.md on purpose.

Cadence rule - due when the last recorded sweep predates the most recent Thursday 00:00 local. An absent record deliberately means never swept and therefore due, rather than hardcoding the 2026-08-06 first-run date into the script, because a hardcoded date is exactly the rotting fact checklist item 2 describes. A corrupt or unparseable record also reads as never swept, so it makes the sweep due rather than silently skipping it. A vessel dark on Thursday sweeps late rather than skipping the week. The week boundary is today's local midnight minus whole days, so DST moves it by an hour twice a year - accepted deliberately and documented, since an hour cannot make a weekly sweep fire twice or skip a week. The clock is read in one date call with six fields so tests can override it portably without needing GNU-only date -d @epoch.

Landedness - building this turned up a real correction to my own first attempt. git merge-tree --write-tree exits non-zero on a conflict, and an old branch whose files the default branch has since edited conflicts routinely; a caller that keeps the tree hash and drops the exit status reads a conflict as adds-content, which reads as not-landed, which puts landed work in a deletion set. So the skill carries a five-rung ladder (ancestry, patch-id, content, content-absent, empty) with patch-id before content, and anything unsettled reported as undetermined and barred from every deletion set. Measured on this repo 2026-08-03 over 52 merged-PR branches: 18 settled by ancestry, 33 by patch-id, 1 by content, 0 undetermined - ancestry alone would have called 34 landed branches unmerged. The per-branch form of the technique comes from data/bridge-branch-sprawl-classify/report.md and is attributed rather than presented as this skill's invention, because checklist item 8 applies to the skill itself.

Test approach - the ladder tests build real git squash fixtures rather than asserting on the skill's prose, because a written belief about how git behaves is precisely what the checklist was assembled from. One test deliberately reproduces the merge-tree conflict trap.

Test isolation - the new bootstrap detect line broke existing bootstrap silence fixtures, which the existing suite caught. Fixed by following the repo's own established pattern (FM_AXI_SUITE_DISABLE): the script honours FM_GROSSREINSCHIFF_DISABLE=1 for the detect mode only, tests/lib.sh exports it suite-wide, and the sweep's own suite sets it back to 0 and drives the real bootstrap so the mechanism is still exercised end to end. The disable is narrowed to detect because --status and --record are never called by bootstrap and can pollute nothing.

Knowledge placement follows .agents/skills/firstmate-coding-guidelines: the sweep procedure and checklist in the skill, the incident evidence and cadence rationale in docs/grossreinschiff.md, exact mechanics in the script header (which is also its --help output so the two cannot drift), and only three short additions to AGENTS.md - one state-file line, one trigger in section 6, and GROSSREINSCHIFF added to section 13's bootstrap-diagnostics prefix list. bootstrap-diagnostics owns the response to the due line, including that it is advisory in a session without the fleet lock.

One claim was corrected during the work: an early draft said all six branches in the bad measurement had landed, but only three of those six are branches of merged pull requests, so the skill now states exactly what was verified. Item 8's open question - whether anything besides the sea chart came from the Wayfinder repository - is deliberately carried forward as still open rather than closed by assumption.

Not in scope for this change, and left for after it lands: the pin bump to the vessels, and the single All-Ships notice announcing the day and what the sweep covers.

What Changed

  • Adds the grossreinschiff skill (.agents/skills/grossreinschiff/SKILL.md), the captain-invocable /grossreinschiff weekly cleanup sweep: a nine-item checklist over records, instructions, branches, tools, and workspaces, five stated safety properties (report before delete, never judge landedness by ancestry, never touch unlanded work, name the evidence behind each finding, state what was not covered), and a five-rung landedness ladder — ancestry A, patch-id P, empty E, content C, content-absent X — where C keys on git merge-tree --write-tree exit status as well as its tree hash, X requires the branch to add at least one path, and anything unsettled is reported undetermined and barred from every deletion set. docs/grossreinschiff.md carries the incident evidence per checklist item, the on-repo ladder measurement, the rejected cadence alternatives, and attribution for the per-branch classification technique.
  • Adds bin/fm-grossreinschiff-due.sh (detect / --status / --record / --help, with the script header as its help text) and calls it from bin/fm-bootstrap.sh's detect pass, so the reminder rides the existing session start rather than a new scheduler. Due means the last recorded sweep predates the most recent local Thursday 00:00; an absent or unparseable state/grossreinschiff.last-sweep reads as never swept and therefore due, and a home dark on Thursday sweeps late instead of skipping the week. FM_GROSSREINSCHIFF_DISABLE=1 silences detect mode only; tests/lib.sh exports it suite-wide so existing bootstrap silence fixtures still hold.
  • Registers the sweep across the instruction surface: a GROSSREINSCHIFF: handling entry in bootstrap-diagnostics (including that it is advisory without the fleet lock, and that staleness is read from the line's last swept: date rather than its bounded window-open count), an AGENTS.md state-file line, section 6 trigger, and section 13 prefix addition, plus README.md and docs/scripts.md rows. New tests/fm-grossreinschiff.test.sh covers the cadence, the disable knob, and each ladder rung against real git squash fixtures — including one that reproduces the merge-tree conflict trap — and drives the real bin/fm-bootstrap.sh for the due line end to end.

Risk Assessment

✅ Low: The follow-up commit resolves all three accepted findings exactly as directed and touches no runtime behavior - the only script change is header comment text that doubles as --help output - while the ladder reorder is provably safe (E implies C for non-ancestors, so it can only relabel landed as landed-vacuous) and the X precondition moves verdicts toward undetermined, which is already barred from every deletion set.

Testing

Ran the dedicated Großreinschiff suite (24 checks, all pass), the bootstrap suite whose silence fixtures the new detect line had broken, the instruction-surface contract tests mapped to the changed AGENTS.md and skill paths, and the runner's coverage guard — all green, nothing to fix. Because passing tests alone would not show the sweep reaching a vessel, I additionally drove the real bin/fm-bootstrap.sh across a simulated week and captured the actual GROSSREINSCHIFF due line, its silence after a recorded sweep, late sweeping after a dark Thursday, the bounded window count on a three-weeks-dark home, and the corrupt-record path; and I applied the skill's documented ladder to the 9 real merged-PR branches in this checkout, where it settles all of them as landed while ancestry alone would call 2 unmerged and the exit-status-dropped content test would call 1 landed branch "adds content" — both rejected shortcuts reproduced on real data. The doc's 52-branch measurement could not be reproduced at that scale here because this gate worktree holds only 9 of those branches; the failure modes it documents were reproduced instead. The change is CLI and instruction-surface only with no rendered UI, so the reviewer-visible evidence is a terminal transcript rather than a screenshot. No transient files were left behind; the worktree is clean.

Evidence: Session-start transcript: what a vessel actually sees across a week

--- Thu 2026-08-06 09:00 (first fleet-wide run day) --- GROSSREINSCHIFF: weekly fleet cleanup sweep is due (last swept: never; this week's window has been open 0 day(s)) - load the grossreinschiff skill --- the vessel runs the sweep and records it --- recorded Grossreinschiff sweep on 2026-08-06 state file: 1786015200 2026-08-06 --- Sat 2026-08-08 11:00 (same week, already swept) --- <silent - nothing printed> --- Wed 2026-08-12 23:59 (last minute before the next window) --- <silent - nothing printed> --- Thu 2026-08-13 00:00 (next window opens) --- GROSSREINSCHIFF: weekly fleet cleanup sweep is due (last swept: 2026-08-06; this week's window has been open 0 day(s)) - load the grossreinschiff skill --- Mon 2026-08-17 08:30 (vessel was dark on Thursday - it sweeps late, not never) --- GROSSREINSCHIFF: weekly fleet cleanup sweep is due (last swept: 2026-08-06; this week's window has been open 4 day(s)) - load the grossreinschiff skill --- Thu 2026-08-27 09:00 (three weeks dark: still due, last-swept date carries the staleness) --- GROSSREINSCHIFF: weekly fleet cleanup sweep is due (last swept: 2026-08-06; this week's window has been open 0 day(s)) - load the grossreinschiff skill --- corrupt record reads as never swept --- GROSSREINSCHIFF: weekly fleet cleanup sweep is due (last swept: never; this week's window has been open 2 day(s)) - load the grossreinschiff skill

=== Großreinschiff end-to-end: what a vessel actually sees at session start ===
fixture home: (temp)   driver: real bin/fm-bootstrap.sh   clock: injected via FM_GROSSREINSCHIFF_CLOCK

--- Wed 2026-08-05 09:00 (before the first fleet-wide run, home has never swept) ---
GROSSREINSCHIFF: weekly fleet cleanup sweep is due (last swept: never; this week's window has been open 6 day(s)) - load the grossreinschiff skill

--- Thu 2026-08-06 09:00 (first fleet-wide run day) ---
GROSSREINSCHIFF: weekly fleet cleanup sweep is due (last swept: never; this week's window has been open 0 day(s)) - load the grossreinschiff skill

--- the vessel runs the sweep and records it ---
recorded Grossreinschiff sweep on 2026-08-06
state file: 1786015200 2026-08-06

--- Sat 2026-08-08 11:00 (same week, already swept) ---
<silent - nothing printed>

--- Wed 2026-08-12 23:59 (last minute before the next window) ---
<silent - nothing printed>

--- Thu 2026-08-13 00:00 (next window opens) ---
GROSSREINSCHIFF: weekly fleet cleanup sweep is due (last swept: 2026-08-06; this week's window has been open 0 day(s)) - load the grossreinschiff skill

--- Mon 2026-08-17 08:30 (vessel was dark on Thursday - it sweeps late, not never) ---
GROSSREINSCHIFF: weekly fleet cleanup sweep is due (last swept: 2026-08-06; this week's window has been open 4 day(s)) - load the grossreinschiff skill

--- Thu 2026-08-27 09:00 (three weeks dark: still due, last-swept date carries the staleness) ---
GROSSREINSCHIFF: weekly fleet cleanup sweep is due (last swept: 2026-08-06; this week's window has been open 0 day(s)) - load the grossreinschiff skill

--- corrupt record reads as never swept, so the sweep is due rather than silently skipped ---
GROSSREINSCHIFF: weekly fleet cleanup sweep is due (last swept: never; this week's window has been open 2 day(s)) - load the grossreinschiff skill
Evidence: Documented ladder applied to this repo's real merged-PR branches

BRANCH PR LADDER VERDICT SETTLED BY fm/fm-context-reset-mechanism #55 landed A fm/fm-sea-chart-attribute-wayfinder #54 landed A fm/fm-transcript-path-record #53 landed A fm/fm-wake-arm-false-failed #51 landed A fm/fleet-sea-chart-build #47 landed A fm/fleet-validation-grading #43 landed A fm/fm-decisionboard-standard #41 landed A fm/fleet-lavish-tailnet-access #38 landed P fm/fm-snapshot-argv-limit-pin-source #37 landed P ladder totals: A=7 P=2 E=0 C=0 X=0 undetermined=0 ancestry alone would have called 2 of these merged-PR branches unmerged the content test with its exit status dropped would have called 1 of these landed branches 'adds content' (i.e. not landed)

BRANCH                                     PR       LADDER VERDICT SETTLED BY            
------                                     --       -------------- ----------            
fm/fm-context-reset-mechanism              #55      landed         A                     
fm/fm-sea-chart-attribute-wayfinder        #54      landed         A                     
fm/fm-transcript-path-record               #53      landed         A                     
fm/fm-wake-arm-false-failed                #51      landed         A                     
fm/fleet-sea-chart-build                   #47      landed         A                     
fm/fleet-validation-grading                #43      landed         A                     
fm/fm-decisionboard-standard               #41      landed         A                     
fm/fleet-lavish-tailnet-access             #38      landed         P                     
fm/fm-snapshot-argv-limit-pin-source       #37      landed         P                     

ladder totals: A=7  P=2  E=0  C=0  X=0  undetermined=0
ancestry alone would have called 2 of these merged-PR branches unmerged
the content test with its exit status dropped would have called 1 of these landed branches 'adds content' (i.e. not landed)
Evidence: Ladder demo script (rows A/P/E/C/X implemented verbatim from SKILL.md)
#!/usr/bin/env bash
# Applies the landedness ladder from .agents/skills/grossreinschiff/SKILL.md
# (rows A, P, E, C, X, in that order) to the real merged-PR branches present in
# this checkout, and compares it against the two rejected shortcuts:
#   ancestry-only, and the content test with its exit status dropped.
set -u
DEF=${DEF:-origin/main}
patchid() { git patch-id --stable | awk '{print $1}'; }

printf '%-42s %-8s %-14s %-22s\n' BRANCH PR 'LADDER VERDICT' 'SETTLED BY'
printf '%-42s %-8s %-14s %-22s\n' '------' '--' '--------------' '----------'
a=0; p=0; e=0; c=0; x=0; u=0; anc_wrong=0; c_naive_wrong=0
while read -r pr branch merge_sha; do
  git rev-parse --verify -q "$branch" >/dev/null || continue
  base=$(git merge-base "$DEF" "$branch")
  verdict=undetermined; code='-'

  # A - ancestry (positive only)
  if git merge-base --is-ancestor "$branch" "$DEF" 2>/dev/null; then
    verdict='landed'; code='A'; a=$((a+1))
  else
    anc_wrong=$((anc_wrong+1))
  fi

  # P - patch-id, merge commit must itself be an ancestor of the default branch
  if [ "$code" = '-' ] && git rev-parse --verify -q "$merge_sha^{commit}" >/dev/null \
     && git merge-base --is-ancestor "$merge_sha" "$DEF" 2>/dev/null; then
    bp=$(git diff "$base" "$branch" | patchid)
    mp=$(git diff "$merge_sha^" "$merge_sha" | patchid)
    if [ -n "$bp" ] && [ "$bp" = "$mp" ]; then verdict='landed'; code='P'; p=$((p+1)); fi
  fi

  # E - tip tree equals merge-base tree (after A and P, before C)
  if [ "$code" = '-' ] && [ "$(git rev-parse "$branch^{tree}")" = "$(git rev-parse "$base^{tree}")" ]; then
    verdict='landed (vacuous)'; code='E'; e=$((e+1))
  fi

  # C - merge-tree exit status AND resulting tree, both read
  cstat=0; merged=$(git merge-tree --write-tree "$DEF" "$branch" 2>/dev/null) || cstat=$?
  if [ "$code" = '-' ] && [ "$cstat" -eq 0 ] \
     && [ "$(printf '%s\n' "$merged" | head -1)" = "$(git rev-parse "$DEF^{tree}")" ]; then
    verdict='landed'; code='C'; c=$((c+1))
  fi

  # X - only with its precondition: the branch adds at least one path
  if [ "$code" = '-' ]; then
    added=$(git diff --name-only --diff-filter=A "$base" "$branch")
    if [ -n "$added" ]; then
      notlanded=yes
      while read -r path; do
        [ -n "$path" ] || continue
        if git cat-file -e "$DEF:$path" 2>/dev/null || [ -n "$(git log --oneline "$DEF" -- "$path")" ]; then
          notlanded=no; break
        fi
      done <<< "$added"
      if [ "$notlanded" = yes ]; then verdict='not landed'; code='X'; x=$((x+1)); fi
    fi
  fi
  [ "$code" = '-' ] && u=$((u+1))

  # the rejected shortcut: keep merge-tree's tree, drop its exit status
  if [ "$(printf '%s\n' "$merged" | head -1)" != "$(git rev-parse "$DEF^{tree}")" ] \
     && [ "$verdict" != 'not landed' ] && [ "$verdict" != 'undetermined' ]; then
    c_naive_wrong=$((c_naive_wrong+1))
  fi

  printf '%-42s %-8s %-14s %-22s\n' "$branch" "#$pr" "$verdict" "$code"
done
echo
echo "ladder totals: A=$a  P=$p  E=$e  C=$c  X=$x  undetermined=$u"
echo "ancestry alone would have called $anc_wrong of these merged-PR branches unmerged"
echo "the content test with its exit status dropped would have called $c_naive_wrong of these landed branches 'adds content' (i.e. not landed)"
Evidence: Operator-facing --help output (rendered from the script header)
Report whether this home's Grossreinschiff cleanup sweep is due, and record a
completed one.

This script owns ONLY the cadence. What the sweep covers, how each item is
tested, and what it may delete live in
.agents/skills/grossreinschiff/SKILL.md; the measured incident behind each
checklist item lives in docs/grossreinschiff.md.

The sweep is due when the last recorded sweep predates the most recent
Thursday 00:00 local. 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. A home
that ran no session on Thursday sweeps late at its next session start rather
than skipping the week.

The due line's window-open count says how far into the CURRENT window this
session start falls. It is bounded to 0 through 6 by construction and does
not measure how long the home has been dark: a home three weeks behind that
wakes on a Thursday reads 0. The "last swept:" date on the same line is what
shows how many weeks were missed.

There is deliberately no scheduler here. The check is one file read and one
date comparison, so bin/fm-bootstrap.sh runs it in the detect pass that
already happens once per session start. An external timer would add a
per-home install step that nothing verifies, so a home that never installed
it would silently never sweep - the no-op-instruction defect the sweep itself
exists to find. docs/grossreinschiff.md records the full comparison against a
scheduled wake and a fleet-wide notice.

Usage:
  fm-grossreinschiff-due.sh           detect: print one GROSSREINSCHIFF line
                                      when the sweep is due, print nothing
                                      when it is not, and always exit 0
  fm-grossreinschiff-due.sh --status  print due=, last-sweep=,
                                      last-sweep-epoch=, and
                                      window-open-days= whether or not the
                                      sweep is due
  fm-grossreinschiff-due.sh --record  record a COMPLETED sweep as of now
  fm-grossreinschiff-due.sh --help

State: FM_HOME/state/grossreinschiff.last-sweep holds one line,
"<epoch> <YYYY-MM-DD>". Both forms are written at record time so no caller
ever has to convert an epoch back to a date, which GNU date and BSD date
spell differently. An absent, empty, or unparseable marker reads as never
swept, so a corrupt record makes the sweep due rather than silently skipping
it.

Environment:
  FM_GROSSREINSCHIFF_CLOCK overrides the current clock with the six fields
    `date '+%s %u %H %M %S %F'` would print (tests only).
  FM_GROSSREINSCHIFF_DISABLE=1 silences the DETECT mode only, so behavior
    suites that compose bin/fm-bootstrap.sh do not have to seed a sweep
    record to assert on bootstrap's other output. --status and --record are
    unaffected, because bootstrap never calls them and they can pollute
    nothing. tests/lib.sh exports this for the whole suite; the sweep's own
    suite sets it back to 0.

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. That is deliberate: an hour of drift cannot make a weekly sweep fire
twice or skip a week.

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

🔧 **Review** - 3 issues found → auto-fixed ✅
  • ⚠️ .agents/skills/bootstrap-diagnostics/SKILL.md:68 - The handling guidance says "a large number [of window-open days] is itself worth reporting to the captain because it means this home has been dark", but that number is structurally bounded to 0-6 and can never be large. In bin/fm-grossreinschiff-due.sh:144, window_open_days = (NOW - window_open) / 86400, and window_open = midnight_today - days_back*86400 with days_back in 0..6 (line 111), so the quotient always equals days_back exactly. Worse, the escalation case it targets reads lowest: a home that last swept 2026-08-06 and starts its next session on Thursday 2026-08-27 has missed two full weeks, yet the line prints "window has been open 0 day(s)". The real staleness signal is the line's own last swept: &lt;date&gt; field, which the guidance does not mention. As written this is a no-op instruction inside the skill assembled to find no-op instructions (checklist item 3). Fix by pointing the escalation at the last swept date (or by having the script also emit days-since-last-sweep) rather than at window-open days.
  • ⚠️ .agents/skills/grossreinschiff/SKILL.md:65 - Ladder rung X ("Every path the branch adds is absent from the default branch's tree and git log &lt;default&gt; -- &lt;path&gt; is empty") is universally quantified over the set of paths the branch adds. For a branch that adds no new paths - one that only modifies or deletes existing files, the common shape of a small fix branch - that set is empty and both conjuncts are vacuously true, so X returns the definitive verdict not landed on zero evidence instead of falling through to undetermined. The state is concretely reachable and is exactly the one the skill documents as 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 (a cherry-pick, a local pipeline mirror with no forge, a closed-unmerged PR), and C is inconclusive because merge-tree conflicts on an old branch whose files the default branch has since edited (the trap documented at docs/grossreinschiff.md and reproduced in tests/fm-grossreinschiff.test.sh:test_content_test_is_inconclusive_once_the_default_branch_moves_on). The failure direction is safe for deletion - not landed keeps the branch - but it violates the skill's own rule that anything unsettled is reported as undetermined, and property 3 makes a not landed verdict a stop-and-investigate result, so landed work gets reported as real unlanded work needing attention. Guard X with "the branch adds at least one path", otherwise fall through to undetermined.
  • ℹ️ .agents/skills/grossreinschiff/SKILL.md:66 - Rung E (branch tip tree equals merge-base tree) can never be reached in the stated A-P-C-X-E order. A branch with no content change relative to its merge base cannot make git merge-tree --write-tree &lt;default&gt; &lt;branch&gt; conflict, so merge-tree always exits 0 and yields exactly the default branch's tree - which is rung C's condition. C therefore settles every content-free branch as plain landed before X or E is ever consulted. The consequence is only a label difference (landed instead of landed (vacuous)), so nothing unsafe follows, but it means the ladder as written cannot reproduce the "2 landed vacuously (empty commits)" split that docs/grossreinschiff.md reports from the bridge measurement, and E is a rung that never fires. Either move E ahead of C or drop it and fold the vacuous case into C's reporting.

🔧 Fix: correct due-line staleness prose and ladder rung X/E order
✅ Re-checked - no issues remain.

✅ **Test** - passed

✅ No issues found.

  • ./bin/fm-test-run.sh tests/fm-grossreinschiff.test.sh — 24/24 ok (cadence, real bootstrap surfacing, disable knob, ladder rungs A/P/E/C/X on real git squash fixtures)
  • ./bin/fm-test-run.sh tests/fm-bootstrap.test.sh — the existing suite the new detect line broke; passes with the tests/lib.sh isolation
  • ./bin/fm-test-run.sh tests/fm-instruction-owners.test.sh tests/fm-supervision-instructions.test.sh tests/fm-ensure-agents-md.test.sh — the pure-contract-unit scripts mapped to the changed AGENTS.md and .agents/skills paths; includes the every-skill load-trigger check now covering grossreinschiff
  • ./bin/fm-test-run.sh --check-coverage — FM_TEST_COVERAGE ok total=122, the new suite is registered
  • Manual end-to-end: drove the real bin/fm-bootstrap.sh against a fixture home with FM_GROSSREINSCHIFF_CLOCK at Wed 08-05, Thu 08-06, Sat 08-08, Wed 08-12 23:59, Thu 08-13, Mon 08-17, Thu 08-27, plus a corrupted record — transcript captured
  • Manual: bin/fm-grossreinschiff-due.sh --record then re-ran bootstrap to confirm the due line stops for the rest of that week, and inspected the written state/grossreinschiff.last-sweep (&lt;epoch&gt; 2026-08-06)
  • Manual: implemented the SKILL.md ladder rows verbatim and ran them over the 9 merged-PR branches present locally against origin/main, alongside the two rejected shortcuts (ancestry-only, merge-tree with exit status dropped)
  • bin/fm-grossreinschiff-due.sh --help — confirmed the operator-facing help is the script header itself
⚠️ **Document** - 1 info
  • ℹ️ bin/fm-session-start.sh:71 - Pre-existing contradiction, not caused by this change and left untouched as out of scope: bin/fm-session-start.sh's header says "five mutating sweeps" (lines 21 and 71) while AGENTS.md section 3 (line 164) and bin/fm-bootstrap.sh (line 87) both say six, and AGENTS.md's own enumeration lists six items. The same header also omits the watcher-service and frequency-monitor convergence steps from its lock-gated set. Worth a follow-up that re-counts the lock-gated sweeps in fm-bootstrap.sh once and corrects the two non-owner statements to match.
✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

Coditan-XO added 2 commits August 3, 2026 14:15
Nine classes of record, instruction, branch, tool, and workspace that were
true when written, are not true now, and that nothing re-measures. Every
item was earned by a measured incident in the night of 2026-08-02/03;
docs/grossreinschiff.md carries the evidence behind each one so a later
reader can re-measure instead of trusting the checklist.

The sweep reports and never deletes. Removal is a separate captain-
authorized step, and inside a project it is a dispatched worker's task,
never firstmate's own write.

Landedness is never judged by ancestry. This fleet squashes, so ancestry
calls landed work unmerged: 152 of 154 branches on coditan-bridge, and 34
of 52 merged-PR branches here. The skill carries a five-rung ladder
(ancestry, patch-id, content, content-absent, empty) whose per-branch form
comes from data/bridge-branch-sprawl-classify/report.md §1, with anything
unsettled reported as undetermined and barred from any deletion set. Two
traps are documented from measurement: git merge-tree conflicts routinely
on old branches, so a caller that drops its exit status reads landed work
as unlanded, and a forge-recorded merge commit proves nothing unless it is
verified as an ancestor of the default branch. tests/ builds real squash
fixtures for each rung rather than asserting on the prose.

Cadence is a session-start item, not a new scheduler. The due check is one
file read and one date comparison, so bin/fm-bootstrap.sh runs it in the
detect pass that already happens once per session start; an external timer
would add a per-home install step that nothing verifies, which is the
no-op-instruction defect this sweep exists to find. A vessel dark on
Thursday sweeps late rather than skipping the week, and the line says how
late. docs/grossreinschiff.md records the rejected alternatives and the
mechanism's own limits.

tests/lib.sh silences the detect line suite-wide, since every suite that
composes bootstrap would otherwise see it; the sweep's own suite sets it
back to 0 and drives the real bootstrap.
@Freudator86
Freudator86 force-pushed the fm/fleet-grossreinschiff branch from fd0c025 to ad84a19 Compare August 3, 2026 14:33
@Freudator86
Freudator86 merged commit 287e5e0 into main Aug 3, 2026
10 checks passed
@Freudator86
Freudator86 deleted the fm/fleet-grossreinschiff branch August 3, 2026 18:50
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