Merge upstream: verified Kimi adapter, Claude Stop auto-arm cooperation, tmux composer rewrite - #34
Merged
Merged
Conversation
* fix(session-start): relaunch missing second mates * fix(test): detect completed parallel workers * no-mistakes(review): Isolate session-start recovery test cleanup * no-mistakes(review): Complete backend-safe secondmate session recovery * no-mistakes(review): Resolve Zellij task ownership before recovery * no-mistakes(review): Recover relocated Zellij ghost tabs safely * no-mistakes(review): Restore conservative Zellij recovery boundary * no-mistakes(review): Reject malformed tmux recovery targets * no-mistakes(document): Align secondmate recovery documentation * no-mistakes: apply CI fixes
…id#967) * fix(herdr): reclaim resumed task projections safely * no-mistakes(review): Enforce safe Herdr reclaim close boundaries * no-mistakes(document): docs: clarify Herdr restart projection contract
…id#994) * docs: separate current guides from verification * no-mistakes(review): Restore Herdr 0.7.5 restart-reclaim verification evidence
…d#997) * feat(claude): Stop-owned tokenless watcher continuity via asyncRewake auto-arm Claude primaries (main home and marked secondmate homes) no longer depend on the model remembering to re-arm the watcher after each wake. A tracked Stop asyncRewake hook (bin/fm-claude-stop-autoarm.sh, timeout 28800s) fires on every turn end, claims one home-scoped single-flight owner, foregrounds bin/fm-watch-arm.sh inside the hook-owned process tree, and translates an actionable close or typed watcher failure into exactly one exit-2 rewake. The hook scopes to genuine primary checkouts, requires the session lock to be held by its own harness ancestor, stays inert while AFK owns triage or the home is idle, and hands AFK transitions mid-cycle to the daemon without rewaking. The synchronous turn-end guard gains a --claude cooperative mode: it ignores stop_hook_active (true on every post-continuation stop, which is what re-opened the 2026-07-21 blind window), waits briefly for a watcher health proof, a live auto-arm owner claim, or a fresh rewake epoch, and re-blocks only when the auto-arm genuinely failed to establish - bounded to 3 consecutive blocks per session, safely below Claude Code's 8-block override, then a degraded allow with a visible systemMessage. Codex keeps the previous one-block loop guard byte-identically, and Pi, OpenCode, and Grok adapters are untouched. Continuity PreToolUse gate and durable wake queue are preserved; the gate's recovery guidance now names the Stop-owned re-arm and reserves manual background arms for auto-arm failure. Claude supervision protocol, harness-adapters facts, architecture, configuration, and continuity docs updated; docs/turnend-guard.md records the 2026-07-24 Claude 2.1.218 contract revalidation (tokenless multi-cycle rewake, no-dedup, timeout process-group kill, 8-block cap, interactive non-stall) and the 2.1.219 product live E2Es. Regression matrix: hermetic tests cover scope, identity, AFK, need, single-flight, translation, guard cooperation, budget, and registration; the new live E2E proves two full tokenless auto-arm rewake cycles with zero model arm commands; Pi and OpenCode Option B live E2Es pass unchanged. * no-mistakes(review): Fix Claude X-mode auto-arm continuity backstop * no-mistakes(review): Remove unsupported Claude contract-lab verification claims * no-mistakes(document): Update Claude auto-arm continuity documentation
* Clean stale Herdr projections at session start * no-mistakes(document): Document stale Herdr session-start projection cleanup * no-mistakes(review): Enforce locked exact Herdr projection cleanup * no-mistakes(review): Fail closed on unverified session lock ownership * no-mistakes(review): Serialize session lock acquisition atomically * no-mistakes(document): Align session-start and Herdr cleanup documentation * no-mistakes(document): Generalize lock-refusal diagnostics * no-mistakes(lint): Avoid reserved keyword in concurrency test * no-mistakes: apply CI fixes * no-mistakes: apply CI fixes
…uid#1001) * fix: recover Claude supervision at session start * fix: remove Claude watcher-status command gate * no-mistakes(document): docs: remove stale continuity gate references
* Replace quota dispatch selector instructions * no-mistakes(review): Align bootstrap docs with agent-owned dispatch selection
* remove vestigial dispatch selector * no-mistakes(review): Synchronize isolation proof and portable shard evidence * no-mistakes(review): Correct shard history and proof archive date * no-mistakes(review): Remove reintroduced selector documentation reference * no-mistakes(document): Remove stale dispatch strategy documentation
…1039) quota-axi 0.1.13 emits schemaVersion 2 with a quotaSemantics object per provider, so the successor named in the interim rule has landed and the rule's own removal condition is satisfied. Keep the ownership clause so quota-axi remains the single owner of how model or product windows relate to bounding account windows, and drop the interim weakest-headroom instruction. The unknown-semantics case is already covered by the existing requirement to stop and report a candidate whose applicable quota data or interpretation cannot be established. Drop the matching assertion phrase from tests/fm-instruction-owners.test.sh; the retained ownership phrase still asserts.
…unchenguid#1049) * fix(tmux): scope Claude busy detection by harness * no-mistakes(review): Separate verified and fallback busy signatures * no-mistakes(test): Scope busy signatures to supplied harnesses * no-mistakes(document): Document harness-scoped busy detection
* Add verified Kimi crewmate harness adapter * no-mistakes(review): Scope Kimi moon detection to spinner lines * no-mistakes(review): Match only complete Kimi spinner rows * no-mistakes(review): Resolve Kimi binary portably before pane creation * no-mistakes(document): Align Kimi adapter documentation * no-mistakes(lint): Suppress false-positive ShellCheck warning for sourced watcher override * Fix Kimi busy spinner detection * no-mistakes(review): Recognize Kimi session-lock ancestry and holders * no-mistakes(review): Scope pending-reply Kimi busy detection by harness * no-mistakes(document): Correct Kimi spinner capture documentation * no-mistakes(document): Clarify optional Kimi spinner whitespace * no-mistakes(lint): Silence intentional pending-reply test stub warnings * test: align rebased Kimi busy fixtures * no-mistakes: apply CI fixes * Reconcile Kimi busy detection after per-harness scoping * no-mistakes(review): Clarify observed Kimi spinner whitespace contract * no-mistakes(document): Clarify Kimi harness documentation
* fix kimi pointer submission and spinner conformance * no-mistakes(review): Preserve Kimi submit target ownership guard
* Add guarded Kimi turn-end hook * no-mistakes(review): Require jq before installing Kimi turn-end hook * no-mistakes(review): Expose jq inside isolated Kimi test fixtures * no-mistakes(review): Preserve Kimi config boundaries during hook removal * no-mistakes(review): Document Kimi removal newline safeguard * no-mistakes(document): Document Kimi shared-home preservation
) * Fix structural tmux composer reading * Verify Calm compatibility with Pi 0.82 * no-mistakes(review): Harden structural composer classification boundaries * no-mistakes(review): Refresh composer and Kimi regression fixtures * no-mistakes(review): Fail closed on unbounded composer edges * no-mistakes(review): Enforce aligned composer geometry safely * no-mistakes(review): Make composer ambiguity locale-safe * no-mistakes(review): Preserve ambiguity through composer submission * no-mistakes(review): Carry composer proof through retries * no-mistakes(document): Document structural tmux composer delivery guarantees * no-mistakes: apply CI fixes
…grate-0727 # Conflicts: # bin/fm-spawn.sh # bin/fm-tmux-lib.sh # bin/fm-turnend-guard.sh # bin/fm-watch.sh # docs/architecture.md # docs/configuration.md # docs/herdr-backend.md # docs/turnend-guard.md
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
upstream/main(kunchenguid/firstmate, 16 commits) into the fork'smainvia a true merge commit.fm-turnend-guard.sh --claudenow cooperates with a Stop-owned re-arm instead of the old one-shotstop_hook_activeallow, which Claude Code'sasyncRewakehad started re-opening.fm_busy_lines_match) to stop cross-harness false positives (e.g. Kimi's idle tip borrowing Grok's busy token).docs/herdr-backend.mdsplit into current guidance (that file) plus dated empirical evidence (docs/verification/runtime-backends.md,docs/verification/supervision.md), with a paralleldocs/documentation-audiences.jsoninventory andbin/fm-doc-audience-check.shgate enforcing every tracked doc is classified.Conflict resolution (8 files)
Every conflict was resolved by combining both intents; no fork-only file or behavior was dropped.
bin/fm-spawn.sh- two independent function additions collided at the same insertion point: the fork's per-crewsystemd --usermemory cap (crew_memory_cap_available,wrap_launch_with_memory_cap) and upstream'sresolve_kimi_binary. Kept both as sibling functions.bin/fm-tmux-lib.sh- the fork's simple single-cursor-rowfm_tmux_composer_statecollided with upstream's generalizedfm_tmux_composer_row_stateat the same spot. Upstream's own later structural rewrite (already auto-merged elsewhere in the file) fully supersedes the fork's simple version, so kept upstream's row classifier and dropped the now-dead duplicate definition.bin/fm-turnend-guard.sh- the fork's watcher re-arm grace tolerance (FM_TURNEND_REARM_GRACE: don't block on a fresh beacon with no live lock, since the watcher may just be mid-restart) collided with upstream's whole--claudeauto-arm cooperation rewrite (budget, epoch, cooperative wait). Kept upstream's structure and inserted the re-arm grace check as a shared early-exit after the commonfm_watcher_healthycheck, applying to both the default and--claudepaths.bin/fm-watch.sh- same shape asbin/fm-spawn.sh's: the fork'sbusy_state_is_busy(bs, tail40)(resolves the backend busy state once and shares it with the stale-dedup signal, so herdr'sagent.getisn't called twice per pane per poll) collided with upstream'swindow_is_busy(window, tail40)(harness-scopedfm_busy_lines_matchfallback, replacing the old combined-pattern-only regex). Kept the fork's name/signature and folded upstream's harness-scoped fallback into it, adding a<window>parameter for the harness lookup.docs/architecture.md,docs/configuration.md- narrow prose/config-var collisions describing the two features above from opposite sides. Merged into one paragraph covering both facts, and kept both sides' new env vars.docs/herdr-backend.md- the conflict was almost entirely upstream's doc-restructure commit (docs: separate current guidance from verification evidence kunchenguid/firstmate#994) deleting/relocating content the fork had never touched, plus five genuinely fork-only incident write-ups (NBSP composer fix,--sourceCLI bug, SGR-90 ghost-text + away-daemon-outlived-afk fix, queued-message-hint fix, watcher stale-dedup semantic signal) anchored nearby in the old monolithic file. Adopted upstream's file wholesale and relocated the five fork-only sections intodocs/verification/runtime-backends.mdunder the existing## Herdrsection, fixing their cross-references to sections that moved or no longer exist.docs/turnend-guard.md- same shape: merged the re-arm-grace prose into upstream's rewritten invariant section, and relocated the fork's two watcher-lock-race incident write-ups (2026-07-15 write-side and read-side races) intodocs/verification/supervision.md's## Turn-end guardsection, matching upstream's own doc-restructure pattern.Fixes for silent (non-textual) integration gaps
Three problems surfaced only by running the suite - each an upstream change interacting with fork-only code that never textually overlapped, so the merge produced no conflict but the tree broke at runtime or the doc gate failed:
bin/fm-doc-audience-check.sh(new upstream gate): flagged 8 fork-only docs as unclassified (betterstack/clickstackwebhook receiver docs, skills, and examples, plusdocs/crew-memory-cap.mdanddocs/fork-only-delivery.md). Added all 8 todocs/documentation-audiences.jsonwith the audience that matches their closest existing analogue (agent-runtimefor the two alert-response skills,operator-currentfor the webhook/fork-only-delivery docs,operator-examplefor the.envexamples,maintainer-verificationfor the memory-cap evidence doc).tests/fm-turnend-guard.test.sh:test_hook_claude_mode_allow_resets_budgetremoves the watch lock but left.last-watcher-beatfresh from an earlier step, expecting the next call to re-block - but the fork's new re-arm grace tolerance (above) now correctly reads a fresh beacon with no lock as "re-arm plausibly in flight" and allows. Aged the beacon past the grace window before the "later unhealthy chain" assertion, matching how every other genuinely-dead-watcher case in the same file is set up.tests/fm-kimi-harness.test.sh(new upstream): two gaps. (1)test_kimi_launch_then_send_is_verifiedasserts the exact unwrapped launch text, but an ambient realsystemd-run --useron this host made the fork's memory-cap wrapper (above) actually wrap it - stubbedsystemd-rununavailable in this test's fake bin, mirroringtests/fm-backend.test.sh's existing precedent for the same interaction. (2)test_watcher_scopes_moon_spinner_to_recorded_kimi_taskcalled the pre-mergewindow_is_busy <window> <tail>signature directly; updated all six call sites to the mergedbusy_state_is_busy <bs> <tail> <window>signature with the test's already-overridden constantbs=unknown.Validation
bin/fm-lint.sh(pinned ShellCheck 0.11.0) - clean.bin/fm-doc-audience-check.sh- clean (surfaces=63 local_links=153).fm-backend-herdr,fm-composer-ghost,fm-composer-lib,fm-tmux-submit-busy,fm-turnend-guard,fm-watch-checkpoint,fm-watcher-lock,fm-watch-triage,fm-spawn-dispatch-profile,fm-spawn-batch,fm-spawn-worktree-settle,fm-backend-tmux-smoke- all green after the turnend-guard test fix above.bin/fm-test-run.sh --family:pure-contract-unit(31/0, includingfm-kimi-harnessafter both fixes above andfm-documentation-audiencesafter the inventory fix),session-bootstrap(8/0),secondmate(8/0).