Reconcile upstream 888871de (September 17, 2026) - #68
Conversation
kunchenguid#4627) * fix: restore published contribution follow-up (Fixes kunchenguid#4469) * fix(review): Fix contribution freshness and merge actor routing * fix(review): Restore issue triage and scope contribution follow-up * fix(test): test: assert one wake per contribution signal * fix(document): Document contribution follow-up * fix: restore truthful terminal delivery evidence * fix(review): Disclose unsupported contributions and deduplicate watcher wakes * fix(review): Preserve unmeasured unsupported contributions across Bearings * fix(review): Deduplicate shared contribution wakes and isolate diagnostics * fix(ci): Captain, fixed the CI failure by updating the PR-security fake GitHub interface to support the contribution observer’s API reads. Verified with shellcheck, git diff --check, the full contribution suite, and a focused merged-poll retirement reproduction. The full PR-security script was not allowed to complete locally after its expanded observer path made it substantially slower
…nguid#4658) * fix(bin): make a remote-reply document gap self-clearing and re-attemptable A remote mate's undelivered document raised a keyed `blocked` decision that nothing could ever resolve, and any `data/*.md` substring in any mirrored line was an unconditional fetch instruction. A mate announcing a report it had not written yet therefore manufactured a permanent, factually false blocker, and its own explanation of the false alarm manufactured more. The reader has no permanence vocabulary: a report still being written refuses exactly like a path that will never exist. So an undelivered document is now a durable, re-attemptable obligation under `state/remote-replies/<id>.pending-docs`, re-attempted on the next delta and on the channel's own quiet poll, and retired with a matching `resolved` line naming the local copy once it arrives. The cursor still advances and no delta stalls on one bad pointer. Only a structured `report=data/....md` pointer now offers a document, so a path merely mentioned in prose - including one under another home's mirror tree, which is provably not that mate's to serve - is never fetched. Offers are deduplicated across the whole delta, the escalation names each missing document once and carries the reader's own reason instead of discarding it, and a strictly increasing notice ordinal keeps a later escalation from being swallowed as duplicate bytes. A mirrored line still lands once whichever pointer form it was first written under. * no-mistakes(review): Require structured pointer token boundaries * no-mistakes(review): Unify boundary-safe pointer extraction and rewriting * fix(bin): identify a mirrored line independently of its delivery state Two defects in the boundary-safe pointer work. The at-most-once check compared only the all-remote and all-local renderings of a line, so it could not recognize a mixed one. A line offering two documents where only the first was deliverable mirrored as local-plus-remote; once the second arrived, a cursor-loss whole-log recapture rendered the same line all-local, matched neither alternate, and mirrored a second time. A line's identity is now the canonical form every boundary-valid pointer would take once delivered, derived by the same parser that does extraction and rewriting, so it no longer depends on which documents happened to be deliverable at the time. The pointer map was passed to awk through the process environment. A delta may carry up to the configured 1 MiB bound, and an expanded map of delivered pointers can exceed the platform's exec argument limit, so awk would fail to start; because no caller checked, the empty result would have been appended as blank lines while the cursor advanced past dropped status content. The map now travels in a file, and every call site checks the exit status and stops the ingest rather than committing a delta it could not render. Both passes now run once per stream instead of twice per line. * no-mistakes(review): Abort ingest when document pointer extraction fails * no-mistakes(review): Exclude structured cross-home pointers from document transfer * fix(bin): fail open on an undeliverable remote document instead of tracking it Narrow the remote-reply document fix to the scope the diagnosis actually requires, as decided after measuring a simpler alternative. A document the reader cannot deliver now fails open. The mate's line is mirrored with its own pointer, the cursor advances, and one unkeyed note carries the reader's reason. A note never enters the open-decision fold, so it cannot stand open the way the original keyed block did - which removes the never-clearing false blocker by construction rather than by resolving it. That makes the durable self-clearing obligation unnecessary, so it goes: the per-mate pending-documents record, its notice ordinal and resolved announcements, and the poll-side retry. Canonical line identity goes too, and with it a way to silently drop a genuine status line; mirroring is back to at-most-once on exact bytes. The cross-home exclusion goes as well: under fail-open a cross-home report= either fails harmlessly or is a nested remote report this mate genuinely holds, which is now relayed again. Kept: fetching only on a structured report= pointer, the boundary-correct parser, the file-based rewrite map, and checked extraction and rewrite exit status. The parser now scans behind a sentinel byte so a rejected candidate can no longer give the text right after it a false leading boundary. The reported incident is covered end to end: a report path announced in prose before it exists raises no decision, and the report still arrives through the ledger publisher's structured offer once written. * no-mistakes(review): Preserve source-line identity across remote reply replays * no-mistakes(document): Document remote reply transfer and replay semantics * no-mistakes(lint): Fix staging truncation lint checks
* Preserve substantive Calm mid-turn text * no-mistakes(review): Distinguish newline-preserved replies from short narration * no-mistakes(document): Document Calm mid-turn preservation boundaries * no-mistakes(ci): Fixed the flaky contribution watcher test by increasing its bounded checkpoint from 5 to 15 seconds, allowing diagnostics to surface under slower CI load. Verified with `bash tests/fm-contributions.test.sh` and `git diff --check`
…#4656) * fix(bin): re-record PR poll identity after a volume device renumber (Fixes kunchenguid#4260) A volume remount can renumber the state filesystem's st_dev while every inode and byte stays the same; APFS does this across a reboot. A poll registration records its sidecar and check as device:inode, so every poll armed before the remount failed strict validation and the watcher refused all of them as unauthenticated state checks until each was re-armed by hand. There are two device comparisons. fm_pr_private_file_valid compares a live file's device with the state directory's device read in the same invocation: it refuses a file that is not on the state directory's own filesystem and already survives a renumber, so it is unchanged. The registration's recorded identity versus the live identity (from kunchenguid#556, reused by the kunchenguid#932 retirement receipt) binds the registration to the exact files published in its own transaction; its device part is what breaks. When strict capture fails, the watcher now proves the device is the only difference: every other artifact check passes (template bytes, both hashes, private mode, single link, live device, metadata), both recorded identities name one device, and each recorded inode equals its live inode. Only then, under the task's control lock, does it rewrite the two identity lines, repeating the whole proof and comparing the registration's file identity and bytes just before the rename, and then capture strictly again. A swapped, altered, re-moded, relinked, split-device, or foreign-device artifact still fails a proof and is still refused, and a pending retirement receipt blocks the rewrite. Reproduction: on macOS a poll armed on an APFS disk image that was detached and re-attached behind another image moved st_dev 16777239 -> 16777243 with inodes, bytes, mode, and link count unchanged; the real watcher refused it on main and reports its merge with this change. The portable regression test rewrites a real registration's recorded device and drives the watcher. Not changed here: the status presentation cursor keys rows by its own device:inode identity in bin/fm-classify-lib.sh, a different helper that needs its own fix; a retirement receipt left by a reboot between its publication and removal still names the old device and stays refused; custom check trust binds only a content hash and is unaffected. * fix(review): Serialize PR poll publication writers * fix(review): Bound PR poll publication lock scope
…llow-up to kunchenguid#4627) (kunchenguid#4661) A budget that expires partway through an observation no longer records an error or prints the unavailable wake; the URL keeps its prior record and is observed first next poll. forge() flags budget exhaustion at the point it refuses, or when a read is killed at the budget's own deadline, so a genuine forge failure still records the error and wakes. Each distinct URL is now observed once per poll and applied to every owning task.
…kunchenguid#4680) * fix(bin): clear parent pending-replies on local secondmate retirement Local secondmate teardown left resolved parent pending-reply records behind after home removal (seen after papa-hdds / pxmx retirement). Refuse non-forced retirement while any reply for that id is still unresolved, and delete every matching record plus its delivery confirmation after a successful local or remote retirement, matching the remote cleanup path. * no-mistakes(document): Align secondmate retirement docs with pending-reply cleanup * no-mistakes(review): Lokale Pending-replies-Sicherheitsprüfung vor Home-Entfernung * no-mistakes(review): Pending-replies-corr_id auf 16-Hex absichern * no-mistakes(review): Pending-replies Basename und corr_id abgleichen * no-mistakes(document): Clarify forced retirement pending-reply cleanup --------- Co-authored-by: ladwein <ladwein@firstmate.bost8.thelad.loc>
kunchenguid#4677) * fix(bin): accept Orca's composite worktree id at teardown Teardown refused every Orca-backed task because the endpoint validator checked orca_worktree_id with the simple-atom rule meant for tmux-style window names, which rejects any character outside [A-Za-z0-9._@%+-]. Orca returns that id as `<orca id>::<absolute worktree path>`, so the colon and slashes in every real value made validation fail and finished Orca tasks could never be cleaned up. Validate the field as the composite it is: both halves of the first `::` split present, the path half absolute, and no embedded newline, carriage return, or tab. The terminal field keeps the atom check, which is correct for it, and no other backend's validation changes. The existing Orca fixtures recorded ids like `wt-teardown`, a shape Orca never returns, which is why the suite passed a check the real value fails. They now carry the composite form, so the tests exercise the real value. * no-mistakes(document): name Orca's repo id in the composite worktree id * no-mistakes(document): list teardown endpoint safety suite in Orca regression entry points
* feat(bin): add opt-in typed dispatch resolution through typesafe.ai Add bin/fm-dispatch-resolve.sh, which resolves one concrete crewmate or scout profile from a written brief with typesafe.ai's System One model: one Choice question over the rules' `when` texts, then the confidence floor, the rule's `approval` and `floor`, each profile's `provider` and `floor`, one quota-axi snapshot, and the spendPriority argmax all in code. It is off unless TYPESAFE_API_KEY is in the environment or the home's gitignored .env; off means one stderr line, exit 0, and no network call, so firstmate dispatches exactly as before. The key reaches curl on a file descriptor, never argv. Extract fmx_env_get into bin/fm-env-lib.sh as the one .env accessor and the harness-to-provider table into bin/fm-quota-axi-lib.sh so the new tool and bin/fm-quota-choose.sh share one owner each. Bootstrap validates the four new optional dispatch fields. Document the schema, the operator contract, the AGENTS.md intake step, and the live and benchmark evidence. * no-mistakes(review): Harden typed dispatch resolution and quota bounds * no-mistakes(review): Validate dispatch floors and ranking evidence * no-mistakes(review): Tighten dispatch response and floor evidence * no-mistakes(review): Neutralize none matching and resolve defaults locally * no-mistakes(review): Preserve providerless profiles outside typed resolution * no-mistakes(review): Validate response usage and reject duplicate profiles * no-mistakes(review): Escalate unverifiable floors and validate probabilities * no-mistakes(review): Validate probability mass and unknown profile floors * no-mistakes(review): Simplify resolver interface and preserve fallback routing * no-mistakes(review): Fix constants and rank partial quota evidence * no-mistakes(review): Add authoritative provider mapping and enforce explicit providers * no-mistakes(review): Declare provider for documented Pi profile * no-mistakes(review): Validate provider identifiers and support Gemini dispatch * no-mistakes(review): Strictly anchor provider identifiers * no-mistakes(review): Validate selectors and preserve fallback candidate evidence * no-mistakes(review): Gate typed validation and harden resolver evidence * no-mistakes(review): Preserve opt-in routing and harden candidate evidence * no-mistakes(review): Prioritize known exhaustion over quota uncertainty * no-mistakes(review): Isolate API secrets and preserve no-key diagnostics * no-mistakes(review): Fallback safely when dispatch rules are absent * no-mistakes(review): Prioritize quota vetoes and isolate bootstrap secrets * no-mistakes(document): Document typed dispatch safety and fallback behavior
…n decisions aren't lost (kunchenguid#3753) * test: reproduce buried status declarations in shared readers * fix: share status event reads and preserve open blockers * fix: retain terminal scout and ship status declarations * no-mistakes(review): Fix status chronology, legacy completions, and reader performance * no-mistakes(review): Share terminal decision reconciliation across fleet snapshots * no-mistakes(review): Unify terminal supersession across cached folds and consumers * no-mistakes(review): Filter per-key status history while preserving terminal chronology * no-mistakes(test): Preserve parent lock ownership in Bash 3.2 subshells * no-mistakes(review): Anchor legacy status tokens so prose cannot hide pauses * no-mistakes(document): Document latest-event status read and kind-scoped fold cursor * no-mistakes(lint): Quote literal done in test for-lists for SC1010 * ci: expect 19 snapshot/fleet-view tests This branch adds a fleet-snapshot regression, so the stock macOS Bash lane's hardcoded guard of 18 'ok - ' lines fails on the new count. Bump the guard and its message to 19. * no-mistakes(review): Restore multiline child outcome reporting * no-mistakes(review): Select ledger terminal events through bounded shared reader * no-mistakes(review): Report newest open decision instead of preferring blocked * no-mistakes(review): Require colon before ship/scout terminal supersession in fold * no-mistakes(review): Gate socket-down override on latest event; drop lock matrix * no-mistakes(review): Fold only colon-bearing or keyed lines as decision transitions * no-mistakes(review): Pre-select candidate lines before per-key closing-verb fold * no-mistakes(test): Update fleet-view expectations to newest-open-decision rule * no-mistakes(document): Align status-read docs with fold-resolved crew state * no-mistakes(document): Correct status-reader contracts in classify-lib and crew-state headers * no-mistakes(ci): Greptile P1 (bin/fm-crew-state.sh:729, "Stale socket blocker survives") was a real defect introduced by commit b7c2183 on this branch, and is fixed. Root cause: the daemon-socket-down override took its verb check from `last_status_line "$LOG"` but its evidence and emitted detail from `$LOG_LINE` (status_current_line = the fold's newest still-open decision). Those are different lines whenever a later recognized `blocked:` event is one the decision fold declines. Reproduced by sourcing bin/fm-classify-lib.sh on `blocked: no-mistakes daemon socket is missing` followed by `blocked [key=pending-reply-t3]: still waiting on the answer` (reserved-namespace key whose note does not speak that vocabulary, so _fm_decision_key_transition_allowed rejects it): open set still holds the socket blocker, last_status_line returns the newer line, its verb is blocked, so the gate passed and the stale daemon-down evidence overrode a healthy attributed run. Fix (bin/fm-crew-state.sh): capture LOG_LATEST=$(last_status_line "$LOG") once and read verb, socket-down evidence, and the emitted note all off that same line, so the override fires only while the socket-down declaration is itself the log's latest recognized event — preserving the narrow override the prior round's user instruction asked for. Comment updated to state that contract. No new machinery; the two-line conflation was removed rather than papered over. Regression: extended tests/fm-crew-state.test.sh:test_socket_refusal_override_expires_when_the_crew_moves_on with the reproduced sequence, asserting the run-step reading (state: working, source: run-step) and absence of the override detail. It fails before the fix ("not ok - a later unfolded blocked event also hands the reading back to the run (missing: 'state: working')") and passes after. Verified locally: tests/fm-crew-state.test.sh, tests/fm-fleet-snapshot-view.test.sh, tests/fm-classify-decision-key.test.sh, tests/fm-watch-triage.test.sh, tests/fm-captain-hold-lifecycle.test.sh all pass; bin/fm-lint.sh (shellcheck 0.11.0 + actionlint) exits 0. Changes left uncommitted in the worktree * test: fold terminal-cleanup snapshot coverage into the completed-scout case Keep the ship/scout/secondmate supersession assertions without adding a nineteenth top-level fleet-view test, so CI can stay at the upstream suite count. * no-mistakes(document): Clarify socket-down override expiry in architecture doc * ci: retrigger flaky contribution check
…nchenguid#4689) * fix(spawn): launch codex crewmates with codex's hook layer disabled A freshly launched Codex worker never reached its instructions. Codex stopped it on an interactive "Hooks need review" modal whose selection sits on "Review hooks", which is neither trusting nor declining. Firstmate's key plane carries only Enter, Escape and Ctrl-C with no arrow navigation, so the selection cannot be moved, and pre-accepting the prompt by writing Codex's own trust store would record an operator consent that was never given. The hooks are the machine's own ~/.codex/hooks.json plus any project's .codex/hooks.json. A crewmate needs neither: its turn-end signal is the -c notify= program on the same launch, and Firstmate's project hooks are primary-session infrastructure that stands down in a child worktree. Crewmate and scout launches now pass --disable hooks. That is the opposite of --dangerously-bypass-hook-trust, which RUNS the untrusted hooks; disabling the feature runs none of them and leaves the operator's ~/.codex untouched. An unknown feature name is a hard Codex error, so a release that drops the flag fails the launch loudly instead of silently restoring the modal. A secondmate is a primary in its own home and keeps the project hooks its turn-end guard and session-start digest ride on. Verified on codex-cli 0.151.0: the modal is gone and the turn-end notification still lands. This unblocks the second review that every finished pull request is supposed to get. Fixes kunchenguid#4673 * no-mistakes(review): Fix contradictory hook count in Codex verification record
…d#4669, Fixes kunchenguid#4670) (kunchenguid#4710) * fix(bin): settle terminal contributions and wake once per read-failure episode A contribution whose last good observation is merged or closed is final: poll no longer re-reads it, projection keeps it fresh, and a stale error recorded beside it is cleared once. A genuine forge-read failure on an open contribution still records its error on every cycle but prints the unavailable wake only when it starts a failure episode; a successful read ends the episode. Open PRs linked from done tasks keep being observed. The false unavailable beside a complete observation was budget exhaustion mid-observation, already fixed by kunchenguid#4661. * fix(review): Settle terminal contribution owners * fix(review): Deduplicate shared contribution failure episodes * fix(test): Preserve settled terminal contribution records
* fix(crew-state): select authoritative validation runs by identity Use the AXI run overview and id-addressed status reads to preserve replacement review gates, report competing live runs as unknown, and retain newer failures. Keep the coarse ledger in creation order rather than preferring an older live row. Refs: kunchenguid#3215 * fix(review): Resolve same-branch run identities beyond capped history * fix(review): Fix run-selection compatibility, races, and worker-state fallbacks * fix(review): Limit run validation to the requested branch * fix(test): Anchor AXI fixtures and document remaining live evidence gaps * fix(document): Clarify run selection documentation and capture ownership * fix(lint): Fix ShellCheck diagnostics while preserving fixture isolation
* fix(AGENTS): send a captain-facing outcome instead of shipshape for finished requested work MAIN answered a supervision-branch outcome for completed captain-requested work (implementation done, PR ready for review and merge approval) with "Captain, shipshape.", reading section 9's no-action reply as covering it and reading the Pi protocol's "do not re-emit the anchor verbatim" as "no captain-facing response is owed". Section 9 now limits the shipshape reply to true no-ops (idle re-read, empty heartbeat, consequence-free acknowledgement) and requires a short outcome response naming what finished and what word is needed whenever requested work finishes or a result needs the captain's word, even when a transcript entry already shows the substance. The Pi protocol's re-emit rule now says it bounds repetition only, and carries a worked example of the ready-for-review outcome whose correct processing turn a shipshape reply fails. No executable contract evaluates the content of MAIN's captain-facing reply, so the regression is the protocol example in the owner doc rather than a text-match test. * no-mistakes(document): Clarify captain-facing outcomes versus no-ops * docs(pi): restore the ready-for-review regression example as a preserved-verbatim contract line The document step condensed the Pi protocol's re-emit rule and dropped the worked example of a finished, ready-for-review outcome whose correct processing turn a "Captain, shipshape." reply fails. That example is the contract's regression: no executable contract evaluates the content of MAIN's captain-facing reply, so the owner doc's example is the test case. Restore it directly under the re-emit rule, prefixed as a regression example that is kept verbatim and never condensed or summarized away. * no-mistakes(review): Clarify captain outcome and decision-word requirements * no-mistakes(document): Clarify captain-facing completion outcomes * docs(pi): require the PR URL in the visible captain-facing outcome reply Captain review on the regression example: drop the sample reply string and say only that the ready-for-review outcome requires relaying a captain-facing outcome response, not just "Captain, shipshape.". Fold in the visible-PR-handoff failure seen this session: after the branch outcome reporting this fix green, MAIN's visible reply was only "Awaiting your merge call." with no PR URL, leaning on the dim anchor. Section 9's URL rule now also covers a review or merge ask and names the visible reply as where the URL goes, sourced from the ready status, pr= metadata, or the supervision branch's summary and never left to a transcript entry. The Pi protocol adds the same-way failure and places the captain-facing text in the final visible assistant reply after the fm_branch_processed call, because Calm hides assistant text emitted in the same step as a tool call as a working note. Investigation verdict, evidence in the PR comment: no recent PR caused the handoff failure; Pi has hidden same-step pre-tool assistant text since kunchenguid#2339 (2026-08-13), kunchenguid#4655 changed only the Claude Code mod, and kunchenguid#4658 touched only remote report transfer. * no-mistakes(review): Restore safe outcome ordering and consolidate PR URLs * no-mistakes(document): Clarify captain-facing supervision outcomes * docs(AGENTS): keep the whenever-a-PR-is-mentioned trigger on the consolidated URL rule The consolidated section 9 URL rule narrowed its trigger to a review or merge ask, dropping the "whenever a PR is mentioned" catch-all from kunchenguid#3648 that keeps every PR URL copied from a durable record and never assembled from memory. Restore that trigger as a union with the review or merge ask so the one consolidated rule covers both.
* Fix foreign-owner turn-end supervision loop * no-mistakes(review): Scope foreign-owner safe exit to Claude guard * no-mistakes(document): Document Claude foreign-owner safe exit
…orb (kunchenguid#4778) Under set -u, stock macOS bash 3.2.57 treats "${arr[@]}" on an empty indexed array as an unbound variable and aborts the shell. In signal_turnend_panes_churned() the missing_keys loop was reachable with an empty array whenever every churned key already held a fresh .churn-since-* marker (a second churning turn-end inside an open deferral window), so each watcher cycle died about half a minute in and supervision restarted endlessly. The created_keys rollback loops had the same latent crash on their error paths. Audit of bin/ for the same pattern found one more confirmed-reachable case: remote_handoff's noncanonical-body scan iterates to_move, which is empty when a retried remote handoff finds every key already staged in the outbox. All other "${arr[@]}" sites are either count-guarded, guaranteed non-empty by construction, or unreachable while empty. Guard the three reachable expansions with the repo's existing "${arr[@]+...}" idiom. New regression test drives a real watcher through the all-marked churn path; the macos-stock-bash CI lane runs it under real /bin/bash 3.2 via FM_TEST_ONLY.
… lock. (kunchenguid#4783) The synthetic harness was named synthetic-claude, which Linux procps truncates to synthetic-claud so fm-lock.sh never matched a harness or wrote state/.lock before the test read it. Co-authored-by: Cursor <cursoragent@cursor.com>
* docs: require complete final responses across harnesses * no-mistakes(document): Document complete final replies for Grok Bot * docs: point Grok replies to the shared contract owner * no-mistakes(review): Clarify final recap without batching decision asks
* fix(calm): preserve substantive Pi mid-turn text * no-mistakes(review): Preserve substantive Pi Calm text per block * no-mistakes(test): Cover shared Calm preservation boundaries behaviorally * no-mistakes(document): Consolidate Calm preservation documentation
Merge the frozen canonical snapshot while retaining the fork's pilot, native-path, process, Azure completion, and startup-cost boundaries. Compose kind-aware status decisions with in-process readers, retain single-pass snapshot metadata, and secure device re-recording through the native private-path owner. Carry typed dispatch through the pilot capability seam, disable Codex worker hooks without changing primary launches, and preserve the shared Calm module's repository-relative fixture dependencies. Transfer runner metadata to the catalogs without granting concurrency admission. Firstmate-Upstream-SHA: 888871d
Register the classifier's existing cases with the shared named-case interface while preserving their full-suite order. This permits bounded serial diagnosis of the new long-history and terminal-declaration cases. Export the isolated PR fixture's home and state for its sourced lock owner and subprocesses, satisfying the full source-aware lint contract without suppressing warnings or weakening private-path assertions. Firstmate-Upstream-SHA: 888871d
Final exact-head CI resultVerified at 2026-09-18T01:32:06.774614+00:00 for
All four final local repository gates pass, together with source-aware lint and 14 successful focused behavior invocations after the approved continuation. Known incoming limitations, including canonical kunchenguid#4476's capped-overview rerun race and the optional live-vendor coverage gaps, remain explicitly documented in the PR body; a green matrix is not a claim that those limitations were fixed. |
Integrate PR #69's missing-terminal recovery and PR-poll publication serialization without advancing the canonical upstream snapshot. Keep metadata locked through publication, retain the upstream publication lock, and release both before contribution or parent-channel reporting. Capture watcher snapshots under metadata authority, release it before lifecycle acquisition, and repeat the protected capture after remount re-recording. Recovery takes control, metadata, then publication locks. Preserve both sides' recovery, tamper, publication and remount regressions. The separate capped no-mistakes rerun-selection race remains unchanged. Firstmate-Upstream-SHA: 888871d
Fork-base conflict resolution: 460aca8Resolved and pushed Conflict decisions
Two different racesPR #69 fixes the partial PR-poll publication/authentication race. Fresh local verification on the committed treeAll 11 commands below passed with cache disabled and the new literal base in validation context.
set -e
inventory=$(bin/fm-lint.sh --list-files)
while IFS= read -r script; do
[ -z "$script" ] || /bin/bash -n "$script" || exit
done <<< "$inventory"
set -euo pipefail
bin/fm-test-run.sh --list --changed --base 6e220fcb3ad2eaf2a469ac2f4556a0544f7d4afe > "$EVIDENCE/changed-inventory.txt"
printf 'FM_RECONCILE_NEW_BASE_INVENTORY count='
wc -l < "$EVIDENCE/changed-inventory.txt"Prerequisites were probed: recorded Bash, Git, standard text/file utilities, Perl, pinned ShellCheck/actionlint, Python, jq and PowerShell, plus host Git signing/hook/bare-repository policy without changing it. Coverage remains 239 = 24 parallel + 199 serial + 16 Herdr; documentation validation now checks 108 surfaces / 478 local links. The fresh exact-head CI runs are CI and Fork CI. |
Base-update CI complete: 460aca8At 2026-09-18T04:22:40.544574+00:00, all 20 automatic checks passed on
The conflict decisions and fresh local command evidence include all four gates, source-aware lint, five focused cases and refreshed routing against the new base. PR #69's partial poll-publication race is fixed and preserved here. |
Frozen upstream reconciliation
Normal merge of 18 canonical commits, followed by a test-only verification fix and a merge of fork main after PR #69.
Use a merge commit, not squash or rebase. Merge commits are enabled; this non-draft PR stays unmerged with auto-merge off until separately approved.
All 20 automatic checks passed on the current base-update head, with one verified producer each. Known incoming limitations below are not claimed fixed.
GitHub Actions owns the complete cross-platform matrix.
332c1dc320c689c7b096c7a0eccb290621a5195c6e220fcb3ad2eaf2a469ac2f4556a0544f7d4afe7111081cc10ad8cafcd5a8c7eef75d2b1f724026888871de5cdf875ba4f4c0d231da6efdf7bad9a8460aca84d171cc64a1132fece6228910150d4456dce299f9920d553b4b08168d2e9fc8a8750af0f0Firstmate-Upstream-SHA: 888871d
The latest valid reachable prior trailer is on
bc6720ddee8931803c04c44edb1186bf670fb9c9, whose second parent is the proven prior upstream.That object exists and is an ancestor of both frozen inputs; merged fork PR #58 records the exact head/tree/snapshot.
The matching merge base is supporting ancestry evidence, not the sole synchronization proof.
Upstream was fetched exactly once.
Reconciliation merge
7384915341171f7895a823db165e08b6c2064051retains both frozen parents and remains reachable; no reconstruction or ancestry-only anchor was needed.Git's trailer formatter, tree, parents, clean state, modes and unchanged 102-path manifest were verified after the base-update merge too.
All maintained work is in
C:/src/firstmate2; localmainstill points at332c1dc320c689c7b096c7a0eccb290621a5195c.No other project checkout or live Firstmate home was used.
Rerere was initially unset and is now local enabled=true/autoupdate=false; global Git settings and repository policy are unchanged.
Evidence lives outside the repository under
%TEMP%/firstmate2-reconcile-20260917T233944Z.Fork-base update and fresh verification
Fork PR #69 advanced main after this PR's previous green run.
Only origin/main was fetched; canonical upstream was not advanced.
The two content conflicts,
bin/fm-pr-check.shandbin/fm-watch.sh, now compose metadata-locked publication/snapshot capture with upstream's publication lock, strict remount repair and contribution arming.Read locks are released before lifecycle acquisition; remount recovery orders control → metadata → publication, and both snapshot attempts are protected.
Both publication locks are released before contribution or parent-channel work.
Incoming missing-terminal recovery and both sides' regressions remain intact.
All four repository gates, source-aware lint and five focused cases pass on the current committed tree.
The cases cover re-registration during publication, tamper refusal, watcher remount recovery, native privacy and missing-terminal recovery.
Every fresh command, result, duration, prerequisite, fixture-only timeout setting and limitation is recorded here.
The base-update work touched exactly its 11 incoming paths; refreshed selection is byte-identical at 205 scripts, and unchanged workflow/catalog/runner/proof bytes retain all 20 CI producers.
Documentation now checks 108 surfaces / 478 links.
PR #69 fixes the PR-poll publication race, not the capped no-mistakes rerun-selection race disclosed below; neither run-selection owner changed in this base merge.
The original local ledger is preserved: cumulative 3,849,341 ms, including 1,411,919 ms for this update, with no new timeout.
The registration fixtures explicitly left contribution observation unarmed because their restricted PATH lacks jq; contribution behavior remains CI-owned.
Original conflict and owner decisions
All 13 conflicted paths were resolved from saved base/fork/upstream stages, path history and originating PRs.
Rerere recorded reviewed resolutions with autoupdate disabled; none was accepted automatically.
bin/fm-bootstrap.sh,bin/fm-control-lib.shbin/fm-classify-lib.sh,bin/fm-fleet-snapshot.shbin/fm-pr-lib.shbin/fm-spawn.sh--disable hooksflag and rationale. Apply it to the fork template without restoring inline pilots, changing signed Pi, manufacturing hook trust or disabling primary/secondmate hooks.bin/fm-test-run.sh.env/secret probes. Explicit legacy modes keep no-key expectations separate from typed activation.Unconflicted intent is retained at its real owner: task-owned contribution freshness/failure episodes/terminal settlement (kunchenguid#4627/kunchenguid#4661/kunchenguid#4710); structured remote document offers and documented legacy/retry limits (kunchenguid#4658); pending-reply retirement (kunchenguid#4680); composite Orca identity (kunchenguid#4677); run selection (kunchenguid#4476); Claude foreign-owner Stop through native identity (kunchenguid#4777/kunchenguid#4783); Bash empty-array repair (kunchenguid#4778); shared Calm text preservation (kunchenguid#4655/kunchenguid#4788); and complete final responses (kunchenguid#4738/kunchenguid#4779).
The contribution observer remains GitHub-only; unsupported forges stay unmeasured there, while Azure completion/retirement remains intact.
Maintained prose was reviewed for audience, owner, anchors and safety facts; the initial documentation gate reported 108 surfaces / 477 links.
Earlier local evidence and limits (through f1640f0)
This section preserves the pre-base-update history; fresh current-head evidence is linked above.
PR readiness is not merge readiness. GitHub Actions owns the complete cross-platform matrix.
The initial 2,400-second window charged 1,337,275 ms and hit two timeouts.
The maintainer explicitly authorized ignoring token and other aggregate budgets; cumulative accounting was retained, not reset.
At that prior head, the local ledger charged 2,437,422 ms, with the same two initial timeouts and 14 subsequent successful focused behavior invocations.
Individual commands remained cancellable; runtime deadlines, live-test gates, frozen inputs, repository scope and no-merge authority were not changed.
GROK_BOT.md; explicit catalog routes and executable routing coverage fix it. Final selection is unchanged at 205 scripts. Coverage passes: 239 = 24 parallel + 199 serial + 16 Herdr, five serial shards, 20 unhinted serial scripts, zero missing parallel hints.tscremains absent locally; strict types are CI-owned (portable parallel 1 / Harness package compatibility, both successful on the first head, also successful on that prior head). Preflight and partial output are never credited as suite passes.Known incoming limitation: canonical #4476 retains a capped-overview rerun race that can report an older cancellation while its replacement becomes live, plus up to three sequential bounded status calls.
Upstream rates the race high risk and does not claim fresh live no-mistakes validation.
This snapshot does not fix it; portable parallel 2 owns deterministic selection coverage, not proof that the race is gone.
Verification surface and retained boundaries
Shared paths were compared with frozen upstream; fork-only owners with frozen fork.
Runner, catalog loader, independent proof owner, pilot/native/process/path implementations, timeout library and pinned remote doctor retain fork bytes.
New test registration grants no concurrency; existing hints/weights/caps remain, with only two incoming serial hints added.
Shared CI adds upstream's stock-Bash churn case; Fork CI adds native private re-recording to the existing PR-completion job.
All triggers, permissions, matrix members, pins, deadlines and artifact dependencies remain; 20 automatic producers are expected and the Windows Herdr experiment stays manual.
Pins/prerequisites: ShellCheck 0.11.0, actionlint 1.7.12; checkout v6, setup-node v7, upload v7/download v8; tasks-axi 0.2.5; portable Pi/TypeScript 5.9.3 with required typecheck prerequisites, full history, tmux and C compiler where used.
Herdr retains 0.7.4/protocol >=16, Treehouse 2.0.1, Node 24/Pi 0.84.3, isolated labs, default-server tripwire, 20-minute family bound, always-run cleanup and timing artifacts feeding the always-run aggregate.
macOS retains Bash 3.2.57, 19 snapshot/59 Bearings cases, startup/busy/path/recovery/public-followup and new churn coverage.
Windows retains core/launch/rollback/Azure/management contracts with FM_LIVE=0; PR completion keeps its 600-second main case and adds remount at 180 seconds.
Package compatibility retains Node 24, Pi 0.84.3, OpenCode 1.18.23 and TypeScript 5.9.3 without vendor credentials.
Retained patches follow
docs/fork/architecture.mdremoval conditions: pilot calls/errors need equivalent upstream capabilities; native/process/path wrappers need equivalent identity/privacy/transport and lifecycle bounds; Azure consumers need equivalent canonical identity/freshness/replay/cleanup; startup/reporting/management needs output, freshness, safety and comparable Windows cost proof; catalogs need equivalent loading/routing with independent admission; fixtures/lint need complete dependency closure; workflows need every unique producer/gate/pin/artifact; signed-Pi/remote-doctor exceptions need separately reviewed migration/integrity work; guidance needs equivalent anchors and safety ownership.No reduction in apparent divergence is treated as behavior or cost proof.
Earlier exact local checks (through f1640f0)
The following 36 outcomes are historical, not substituted for the fresh base-update checks linked above.
All commands used the recorded Git-for-Windows Bash,
FM_LIVE=0, serial selected behavior execution and cache=false.No interrupted, failed, skipped, preflight-only or prior-head result is reused as a pass.
Observed: Bash 5.3.15, Git 2.55.0.windows.5, Node 24.19.0, jq 1.8.2, Perl 5.42.3, Python 3.13.15, PowerShell 5.1.26100.9444, ShellCheck 0.11.0 and actionlint 1.7.12.
Exact command notation (not a new runner):
ISL(default)DCISL(default)CT(fm-classify-decision-key, FULL)T(fm-startup-performance, FULL)T(fm-harness-contract, FULL)T(fm-pr-check-security, test_device_rerecord_preserves_private_policy)T(fm-pi-primary-types, FULL)LIST T(fm-classify-decision-key, FULL)T(fm-classify-decision-key, test_closing_verb_filters_unrelated_history_without_subshell_growth)T(fm-startup-performance, test_transition_history_stays_in_process_and_keeps_open_keys)T(fm-startup-performance, test_snapshot_projection_bounds_json_tool_launches)T(fm-harness-contract, FULL)T(fm-pr-check-security, test_device_rerecord_preserves_private_policy)T(fm-spawn-dispatch-profile, test_codex_crewmate_launch_disables_the_hook_layer)T(fm-spawn-dispatch-profile, test_codex_secondmate_launch_keeps_the_hook_layer)T(fm-test-run, test_reconciled_modules_select_their_consumers)T(fm-pr-local-cost, FULL)L(bin/fm-bootstrap.sh bin/fm-classify-lib.sh bin/fm-control-lib.sh bin/fm-fleet-snapshot.sh bin/fm-pr-lib.sh bin/fm-dispatch-resolve.sh bin/fm-contributions.sh tests/fm-pi-primary-types.test.sh tests/fm-bootstrap.test.sh)T(fm-classify-decision-key, test_closing_verb_honors_overridden_transition_verbs)T(fm-classify-decision-key, test_closing_verb_filter_preserves_terminal_chronology)T(fm-classify-decision-key, test_bare_prose_cannot_impersonate_a_terminal_declaration)T(fm-classify-decision-key, test_bare_prose_cannot_open_or_close_a_decision)L(tests/fm-pr-check-security.test.sh tests/fm-classify-decision-key.test.sh)SL(default)DCI-finalT(fm-pr-check-security, test_device_rerecord_preserves_private_policy)Preflight-only runs: 19,857 ms and 16,886 ms, exit 75; they executed probes only, not the planned gates/tests.
The second proved
tscabsent; no dependency was installed and the subsequent package prerequisite/check was not credited.The initial two timeouts are retained above; no frozen-upstream differential was needed after the representative cases passed unchanged.
S:Iis inspection only:I-finalrepeatsbin/fm-test-run.sh --list --changed --base 332c1dc320c689c7b096c7a0eccb290621a5195cintoinventory/changed-final.txt, requires byte identity with the original selection viacmp, and prints its 205-line count withwc -l.The lane/catalog/runner inputs are unchanged by the two-file follow-up.
Prerequisite commands
Successful probes establish capability, not test passes.
Signing/hooks/safe.bareRepository were inspected without host changes; fixture Git isolation remains with the existing helper.
All actual per-invocation probe logs and environment/context digests are retained.
No-renames divergence and locality
50 incoming files are upstream-exact in bytes/mode: 31 existing paths and 19 additions.
The other 45 incoming paths compose intentional fork behavior or catalog/fixture integration.
All 21 branch additions originate upstream; resolver pilot integration and contribution staging's native privacy make two non-equivalent.
Fork-only additive paths remain 69 and intentional deletions remain two; renames are disabled.
Calm preservation is physically Claude-owned with a Pi symlink, and environment parsing moves to its shared upstream owner; relocation is not vanished behavior.
Before/after inventories, moved implementation, retained caller hunks and owner/removal conditions are archived for the actual base and head above.
The final path-manifest SHA-256 remains
b53808985415e2f0617ae45739e26216923712f56d90df97d1ae48746f5f8cd2: exactly 102 paths, with no existing-mode change or broad line-ending renormalization.The source manifest had 95 paths; the runner returns to fork bytes and eight explicit integration paths yield the final 102.
Expected automatic CI producers
The manual-only Windows Herdr automation spike (
workflow_dispatch,measure, windows-latest, 20 minutes, unpinned official preview installer plus jq) was not dispatched.Skipped/cancelled required lanes, missing or duplicate producers, unresolved regressions and missing native coverage are not passes.
PR creation used
gh-axiafter its live help; the initial oversized-body client error created nothing, and the compact retry created this PR.For the completed failed Lint job only, the installed underlying
gh apiretrieved the complete log aftergh-axirefused in-progress-workflow logs and truncated the direct job response; no dependency/auth change was made.History, PR mutations, mergeability and check status otherwise remain through
gh-axi.Exact-head status
At 2026-09-18T04:22:40.544574+00:00: 20 successful, 0 pending, 0 failed, 0 absent; duplicate/unexpected producers: 0.
Complete changed-script routing
Each entry expands to
tests/<name>.test.shwith the named existing primary Linux producer.Untagged subjects are CI-only for the current context; earlier local outcomes remain historical above.
Native/macOS/package contracts retain their additional producers, and live subjects retain their capability gates.
The 205-script inventory was never a local full-suite execution plan.
All selected scripts and current local disposition
Behavior tests (Herdr) (16)
Behavior portable serial 5 (33)
Behavior portable serial 2 (36)
Behavior portable serial 4 (33)
Behavior portable parallel 2 (13)
Behavior portable serial 1 (25)
Behavior portable serial 3 (38)
Behavior portable parallel 1 (11)