docs: complete the curated fork patch registry - #45
Merged
Conversation
added 6 commits
August 1, 2026 04:46
…er from registry verdict
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Complete the curated fork patch registry in docs/fork-patches.md so this vessel can move to the admiralty fleet repository. The commodore ordered a patch inventory BEFORE integration, on the explicit reasoning that a tool can enumerate the patches but cannot say why they exist, and that this part is not reconstructable later. The value of this work is therefore the WHY, not the list.
Starting point: the registry existed but carried only four rows while the fork had merged through PR #40, and the file itself named backfilling as an open decision. That decision is now taken: backfill.
What was done: all 84 fork-only, non-merge commits were enumerated exactly the way bin/fm-fork-sync-check.sh does it (git rev-list --oneline --no-merges upstream..fork, equivalence via git cherry), so the registry and the check mean the same set. Fork base de0b95b against canonical upstream a805766; git cherry finds zero patch-equivalent commits, which is stated in the header so that every 'absorbed' verdict is visibly a separate semantic judgment rather than a mechanical result.
Deliberate decisions a reviewer reading only the diff would not know:
Each row carries four fields folded into the EXISTING table shape (What it does / Why it exists / Verdict / Scope). Adding columns rather than placing a second table beside the first was explicitly required. Do not propose splitting this into two tables or a per-commit section list.
The primary source for the Why column is the associated pull request's '## Intent' section, NOT the diff. Where no PR survives or its text yields nothing, the row deliberately says 'Warum nicht mehr feststellbar' (German, quoted from the order, intentionally not translated). This is required behavior: an honest unknown is useful, while a plausible-sounding motive reconstructed from the diff is exactly the damage this task exists to prevent. Rows admitting an unknown are correct, not incomplete.
The four pre-existing rows were re-verified rather than carried over, and all four were downgraded to 'Warum nicht mehr feststellbar'. This is correct and evidenced: the repository history was repointed, so a commit titled '(feat: configure Codex Graphify approval profile #1)' no longer corresponds to PR feat: configure Codex Graphify approval profile #1 in the current repository (PR feat: configure Codex Graphify approval profile #1 there is 'configure Codex Graphify approval profile', a different patch). Their previous rationales were written against an older upstream tip and were not trustworthy.
The Scope column (ship-specific vs general) is the only field that steers a later action - it decides the integration target - so it is assigned per commit. No group verdicts were issued: the order explicitly warned that bulk handling is what made this divergence unreadable and that a bulk convergence would be the same mistake in reverse.
Hard constraints observed: nothing was converged, integrated, or absorbed from upstream; no git merge or cherry-pick; config/firstmate-update-base and config/fork-sync-upstream were left unset; and no shared surface other than docs/fork-patches.md was touched. This home is under a standing block against advancing its instruction surface from upstream - writing this registry is its own documentation, not an adoption.
Style: firstmate shared tracked material, so the repo's one-sentence-per-line rule applies.
What Changed
docs/fork-patches.mdfrom four rows to all 88 fork-only, non-merge commits between canonical upstreama805766and the pinned fork snapshotdc6c1bc, enumerated the same waybin/fm-fork-sync-check.shdoes (git rev-list --no-merges upstream..fork, equivalence viagit cherry).What it does,Why it exists,VerdictandScopecolumns; the Why column is sourced from each pull request's## Intentsection and statesWarum nicht mehr feststellbarwhere no usable PR intent survives, rather than reconstructing a motive from the diff. The four pre-existing rows were re-verified and all downgraded to that unknown, because the repository was repointed and their old PR references no longer resolve.git cherryfinds zero patch-equivalent commits, soabsorbedis a content-level judgment that must name the upstream file, rule or provenance carrying the effect, and it is distinguished from the fork-sync check's own filename-levelabsorbedprefilter instate/fork-sync.pending. The pin is documented as a deliberate snapshot, so a divergence from the live check's count is expected and is repaired by adding rows and re-stamping.Risk Assessment
✅ Low: A one-clause documentation edit that replaces file-level evidence with the already-verified content-level evidence on a single row, leaving verdict, scope and every other row unchanged, and closing the last gap in the registry's own auditability rule.
Testing
I reproduced the registry's own enumeration exactly as
bin/fm-fork-sync-check.shperforms it, in a throwaway bare repo fetched from both the fork and canonical upstream, and confirmed the 88 rows are a precise one-to-one chronological match for the 88 fork-only non-merge commits withgit cherryreporting zero patch-equivalent commits. I then tested the substance rather than just the shape: everyabsorbedrow's files exist upstream, every denied row's named absence really is absent (including1c53ff8, whose denial rests on content inside a file upstream does have), and the four re-verified rows' downgrade toWarum nicht mehr feststellbaris backed by the current repository's PRs #1-#4 being demonstrably different patches from the ones their commit subjects name. Structural and hard-constraint checks confirm a single table with Scope folded into the existing column shape, no second table, per-commit scope assignment, a docs-only diff with no merge commits, both currency-base config files unset, and the one-sentence-per-line rule held. The repo's changed-file map selects no suite for a docs-only change, so I additionally rantests/fm-fork-sync-check.test.sh(the suite owning the mirrored mechanism), which passes. Because the end-user surface here is a rendered Markdown registry, I rendered it to standalone HTML and captured three screenshots showing the header's methodology statement, the absorbed-verdict rows with their upstream evidence, and the ship-specific row - all checks passed and the worktree is clean./tmp/no-mistakes-evidence/01KYXKF36QHAYMATBBTF5ZVNGT/01-registry-header-and-first-rows.png)/tmp/no-mistakes-evidence/01KYXKF36QHAYMATBBTF5ZVNGT/02-absorbed-verdict-rows.png)/tmp/no-mistakes-evidence/01KYXKF36QHAYMATBBTF5ZVNGT/03-ship-specific-and-tail-rows.png)Evidence: Registry-vs-check parity transcript
Pins resolve live: origin HEAD (fork) = dc6c1bc66ace1b62965c820e922ff16d3140f011 canonical upstream HEAD= a805766622afb291681a15a80c5135517f1cb5ed $ git rev-list --oneline --no-merges upstream..fork | wc -l 88 (registry header claims 88) Row set vs commit set (7-char SHAs, sorted): registry rows = 88 (unique 88) rows not in commit set = 0 commits without a row = 0 row order = chronological (exact reverse of rev-list) $ git cherry upstream fork 88 lines, 0 marked "-" (patch-equivalent) -> header claim "no absorbed verdict can rest on it" holds Table shape (single table, existing shape kept, Scope folded in): base dc6c1bc header : | Commit | Summary | Verdict | Rationale | Last reviewed upstream | head baed08b header : | Commit | What it does | Why it exists | Verdict | Scope | Last reviewed upstream | header rows in file : 1 delimiter rows: 1 (one table only) Column value domains: 6 verdict absorbed 21 verdict keep 61 verdict upstream-candidate 83 scope general 5 scope ship-specific rows admitting "Warum nicht mehr feststellbar": 21 of 88 The four pre-existing rows, re-verified against the repointed repository: PR #1 [merged] feat: configure Codex Graphify approval profile PR #2 [merged] fix(fleet-sync): skip non-repo directories nested in enclosing repo PR #3 [closed, not merged] feat: add bootstrap and watcher drift checks PR #4 [merged] feat(bin): add fork-sync, firstmate-update, and AXI-suite checks -> none of these is the patch its commit subject "(#N)" names Hard constraints: files changed dc6c1bc..baed08b : docs/fork-patches.md merge commits on branch : 0 config/ directory present : no - firstmate-update-base and fork-sync-upstream remain unset non-ASCII characters in file : 0 prose lines with >1 sentence : 0 (one-sentence-per-line rule holds)Evidence: Content-level absorption test against upstream a805766
Absorption content test: for each 'absorbed' row, list changed files that upstream a805766 does NOT have. 117dec5 files=3 absent-upstream: none 7e6ec22 files=1 absent-upstream: none 052df46 files=1 absent-upstream: none 9e6e895 files=3 absent-upstream: none 578d9c5 files=1 absent-upstream: none dba4fdb files=2 absent-upstream: none Denial test: for each row denied 'absorbed' on new-file grounds, count changed files upstream lacks. 93b21ac files=3 absent-upstream=1 e.g. tests/fm-private-material-ignore.test.sh fc25d2f files=4 absent-upstream=1 e.g. tests/fm-private-material-ignore.test.sh 063e03e files=143 absent-upstream=11 (exactly 7 of them ADDED by the commit, as the row states) 2d6ff5e files=1 absent-upstream=1 e.g. tests/fm-private-material-ignore.test.sh 8709b19 files=3 absent-upstream=1 e.g. tests/fm-test-lib.test.sh 779c347 files=1 absent-upstream=1 e.g. tests/fm-instruction-owners.test.sh 33f2e8e files=1 absent-upstream=1 e.g. tests/fm-instruction-owners.test.sh 1c53ff8 files=1 absent-upstream=0 (denied on content, not filename: upstream's docs/configuration.md has 0 hits for the paragraph's tokens)Evidence: Standalone rendered registry (offline, no network assets)
Evidence: Mechanical commit enumeration used for the parity check
Evidence: Raw git cherry output (88 lines, none patch-equivalent)
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 5 issues found → auto-fixed (4) ✅
docs/fork-patches.md:5- The registry's completeness claim is already stale at its own merge base. Line 5 pins the review to forkde0b95band line 8 states the absolute contract "Each fork-only, non-merge commit has one row", but this branch is based ondc6c1bc, which contains four additional fork-only, non-merge commits with no rows:e58e931,61b03a9,7762040,78ffa4f(all from PR test(skills): enforce a load trigger and description condition for every skill #44, merged afterde0b95b).bin/fm-fork-sync-check.sh:77,100resolves the fork side from the live origin HEAD, not from a pin, so the registry and the check describe different sets the moment this lands — contradicting the intent's stated goal that "the registry and the check mean the same set". Either add the four rows and re-stamp the snapshot todc6c1bc, or soften line 8 to say the contract holds as of the named snapshot commit.docs/fork-patches.md:73-93b21ac("Ignores all captain-privateconfig/material by pattern") is given the verdictabsorbed. Line 11 definesabsorbedas "upstream fully replaces the patch", which is the verdict that authorizes dropping the patch at the fleet move. The rule is still fork-only and live at.gitignore:16(config/*), it was authored in this fork in PR fix(repo): ignore captain-private config wholesale instead of by name #39, and line 6 records thatgit cherryfound no patch-equivalent commit — so nothing in the document evidences the absorption. The row's own Why states the failure mode: name-by-name ignores "could let a plaingit add -Astage a Telegram bot token". If this verdict is acted on and the judgment is wrong, the captain-private ignore disappears in the admiralty tree. Either record the provenance evidence that upstream carries an equivalent rule, or downgrade tokeep.docs/fork-patches.md:75- PR fix(repo): ignore captain-private config wholesale instead of by name #39's eight-commit chain receives mutually exclusive verdicts on one feature.93b21ac(the ignore rule),fc25d2f,2d6ff5e,8709b19and1c53ff8areabsorbed, whilefeb5141,ab11e91and9411e07— interleaved in the same chain and iterating on the same ignore rule and its breadth guard test — areupstream-candidate.2d6ff5e("guard fail on Git errors") and9411e07("map guard enforcing and correctly scoped") harden the same guard yet get opposite destinations. Upstream cannot both already contain this work and need it proposed to it; one side of the split is wrong. By contrast PR fix(skills): restore ask-user-authority skill lost in squash-import #42 (dba4fdb/779c347/33f2e8e, allabsorbed) and PR feat(bin): add fm-grade review-quality scale independent of the reviewed tool #43 (allupstream-candidate) are internally consistent.docs/fork-patches.md:14- The Scope column carries no information the Verdict column does not already imply. Across all 84 rows the cross-tab is exactly: 21keep/ship-specific, 49upstream-candidate/general, 14absorbed/general — a perfect one-to-one mapping, which also follows definitionally from line 11 (keepis defined as "vessel-specific behavior remains necessary",upstream-candidateas "a general patch should be proposed upstream"). Because the two fields can never disagree, Scope cannot express the case the intent says it is there to steer: a patch the vessel must keep now whose mechanism is nonetheless general (e.g.5baa843fork-sync drift detection,keep/ship-specific, versus the closely relatedb0b04d0primary-checkout drift detection,upstream-candidate/general). Either re-derive Scope independently of Verdict for the rows where it differs, or state that Scope is intentionally implied by Verdict so a later reader does not treat it as a second judgment.docs/fork-patches.md:18- The row fordf159d2says "the current repository's PR feat: add bootstrap and watcher drift checks #3 is the later history-recovery merge rather than this patch's original review". PR feat: add bootstrap and watcher drift checks #3 in this repository is closed and was never merged; the merged history reconciliation is PR feat(bin): add fork-sync, firstmate-update, and AXI-suite checks #4 (Merge pull request #4 from Freudator86/fm/fm-recover-fork-drift), which the8f3190brow on line 19 already names correctly. PR feat: add bootstrap and watcher drift checks #3's title is in fact "feat: add bootstrap and watcher drift checks", close to this commit's subject, though its## Intentbody is the history-reconciliation text — which is the substantive point the row is making. In a document whose entire value is provenance accuracy, calling an unmerged PR "the merge" is worth correcting.🔧 Fix: correct fork registry verdicts, scope, and snapshot pin
2 issues (1 warning, 1 info) still open:
docs/fork-patches.md:88- The file-existence absorption test introduced at line 19 is applied inconsistently one row apart.2d6ff5ewas flipped offabsorbedin this round with the evidence "upstream has notests/fm-private-material-ignore.test.sh" — but93b21ac(line 88) creates that same file (121 lines, alongside.gitignoreanddocs/configuration.md) andfc25d2f(line 89) adds 41 more lines to it plus abin/fm-test-run.shmapping, and both keep the verdictabsorbed, whose definition at line 17 is "upstream fully replaces the patch and it can be dropped". Acting on all three verdicts is incoherent: dropping93b21acremoves the file that2d6ff5e's retained 16-line change edits. This is not the round-1 objection about missing evidence — the.gitignoreprovenance the user supplied is recorded correctly and the ignore rule itself really is absorbed. It is the flip of2d6ff5ethat turned the pair into a contradiction. The same diff already shows the intended handling for exactly this shape at line 76 (063e03e), where the Why cell says the absorption evidence "is genuinely mixed" and names both the upstream files carrying the substance and the paths upstream lacks. Applying that treatment to93b21acandfc25d2f— or noting on those rows that the guard test travels separately — would close it without disturbing the verified.gitignorefinding.docs/fork-patches.md:25- Line 25 states "The honest result is lopsided, with only five ship-specific rows" and then enumerates what is genuinely local as "its Codex approval profile, the repairs to its own history reconciliation, and its admiralty move record" — three categories covering four rows (2bdd0f1,abcc1e1,e59d3a0,356cd52). The fifth ship-specific row isdba4fdb, which line 24 does explain as a separate case, but a reader auditing the column against the header's own list finds a count that does not reconcile. Adding the skill-restoration case to the enumeration on line 25 would make the justified-uniformity claim self-checking.🔧 Fix: flip mixed-substance gitignore rows off absorbed
1 warning still open:
docs/fork-patches.md:97-1c53ff8keeps the verdictabsorbedon file-level reasoning that line 19's tightened rule was written to reject. Its Why cell argues "the commit changesdocs/configuration.mdand nothing else, and upstream carries that file, so the whole of what it contributes is already upstream" — but what the commit contributes is a one-line rewrite inside a paragraph that is entirely fork-authored.git log -Lon that block shows the section was introduced by93b21acand refined byfc25d2f,ab11e91and9411e07, and its text namestests/fm-private-material-ignore.test.shand the.gitignorearm ofbin/fm-test-run.sh— fork-only material by this document's own evidence. All four of those parent commits are nowupstream-candidate, so at the fleet move the paragraph travels while1c53ff8is dropped, and the stale suite enumeration it removed (namingtests/fm-model-panel.test.shandtests/fm-role-config.test.sh, a list the runner owns) reappears in the moved tree. This is the same collision just fixed one row up, reached through a shared file rather than a new one: the file exists upstream, the content does not. The other six remainingabsorbedrows survive the same sweep —117dec5,7e6ec22,052df46,9e6e895,578d9c5anddba4fdbtouch only paths the verified upstream data covers, and none touches a known fork-only file.🔧 Fix: apply content-level absorption test to registry
1 info still open:
docs/fork-patches.md:59-117dec5is the one remainingabsorbedrow whose recorded absorption evidence is the file-level form line 20 now rejects. Its Why cell ends "all three files it changes exist upstream", while line 20 states "A shared path proves nothing on its own, because a commit can edit a file upstream also has while every line it changes is fork-authored" and line 21 requires every absorbed row to name "the upstream file, rule or provenance that already carries its effect". The verdict is not in doubt — the fix instructions verified it at content level (upstream's.pi/extensions/fm-primary-pi-watch.tscarries the same successor, retry and single-flight logic, 38 matching occurrences against the fork's 39) — but that evidence did not make it into the row, so this is the only absorbed verdict a later reader cannot re-audit against the document's own stated test. The other five are covered:7e6ec22names upstream'sbin/fm-pr-lib.shhandling, and052df46,9e6e895,578d9c5anddba4fdbeach lead with provenance, which line 21 explicitly admits. Replacing the trailing file-existence clause with the content-level finding would close it.🔧 Fix: record content-level absorption evidence for 117dec5
✅ Re-checked - no issues remain.
✅ **Test** - passed
✅ No issues found.
git rev-list --oneline --no-merges upstream..forkin a throwaway bare repo fetched from both remotes - 88 commits, matching the registry's 88 unique rows with zero rows unmatched in either direction and identical orderinggit cherry upstream fork- 88 lines, 0 marked-, confirming the header's claim that no absorbed verdict can rest on mechanical equivalencegit rev-parse refs/heads/fork refs/heads/upstream- confirmed the document's pinsdc6c1bcanda805766are the live HEADs of both repositoriesContent-level absorption test: for each of the 6absorbedrows, checked every file the commit touches exists inupstream:- all present; for each row deniedabsorbedon new-file grounds, confirmed the named files are absent upstream and that063e03eadds exactly seven such filesVerified1c53ff8's content-level denial by grepping upstream'sdocs/configuration.mdfor the paragraph's tokens (fm-private-material-ignore,config/*,fm-test-run.sh) - zero hits despite the shared pathgh-axi pr view 1|2|3|4|6|7- confirmed the repoint evidence: PR #1 is the Codex Graphify profile, #3 is closed and unmerged carrying reconciliation intent, #4 is the recovery merge; also confirmed the PRs whose## Intenttext matches rows2bdd0f1,b384c1b,a8ce717,e3ad719Table structure checks ondocs/fork-patches.md- one header row and one delimiter row (single table), uniform 6 populated columns per row, verdict domain {absorbed:6, keep:21, upstream-candidate:61}, scope domain {general:83, ship-specific:5}, 21 rows admittingWarum nicht mehr feststellbarHard-constraint checks -git diff --name-only dc6c1bc..baed08b(onlydocs/fork-patches.md),git log --merges dc6c1bc..baed08b(none), absence ofconfig/sofirstmate-update-baseandfork-sync-upstreamstay unset, zero non-ASCII characters, one-sentence-per-line prose scanbash tests/fm-fork-sync-check.test.sh- passes (the suite owning the enumeration mechanism the registry mirrors)bash bin/fm-test-run.sh --changed --list- confirmed the changed-file map selects no suite for this docs-only change, which is why the checks above were built by handRendereddocs/fork-patches.mdto standalone HTML and screenshotted it in Chrome at 1600x1100 to capture the reviewer-visible registry surfacedocs/fork-patches.md:5- The header's central claim — thatdc6c1bchas exactly 88 fork-only non-merge commits against canonical upstreama805766— could not be independently verified in this worktree, becausea805766is not present in the local object store and no upstream fetch was performed. What I could verify holds: all 88 listed SHAs are unique, exist, are non-merge, and are ancestors of the pinneddc6c1bc, and the prose tallies (88 rows, five ship-specific rows and exactly the five commits named in the Scope paragraph, sixabsorbedrows consistent with the worked examples) match the table. Re-confirming the 88-count and thea805766stamp requires a fetch of real upstream.✅ **Push** - passed
✅ No issues found.