sync: merge upstream kunchenguid/firstmate main (7 commits) - #35
Merged
Merged
Conversation
…nguid#3079) * feat(pi): let /supervision-model pick the branch's reasoning effort Supervision is an easier job than the captain's own conversation, so the Pi supervision branch does not need main's reasoning effort any more than it needs main's model. /supervision-model now settles both in one flow: the existing model picker, then a follow-up effort picker built from Pi's own supported thinking levels for the model just chosen. Firstmate keeps no effort catalog of its own; the menu, the clamp, and the vocabulary all come from Pi. The pick persists as one line in this home's gitignored config/supervision-branch-effort, independent of the model pin: a captain may pin a model, an effort, both, or neither. The effort pin's current state decides the branch effort on every branch build - the first wake of a cold start and the reopen after /new, /resume, /fork, or reload - and overrides Pi's restore of whatever level a reopened branch session recorded, which is what keeps "Follow main" honest. With no pin, main's own current effort is applied explicitly and followed live through Pi's thinking_level_select event, the same way an unpinned branch already follows main's model, and the two selections now share one build revision so either change invalidates an in-flight build. The branch is never refused over effort. Pi owns the clamp, so a pinned level the branch's model cannot run becomes that model's nearest supported level while the captain's raw pick is kept for a model that supports it, and the command reports the level the branch will really run at rather than the raw pin. A token Pi would not recognize at all is treated as no pin rather than passed to that clamp, which would otherwise collapse a typo into the model's lowest level. Only when main's effort cannot be read either does a build pass no effort override at all, which is the behavior from before this file existed. Pi's own effort vocabulary is pinned by a bidirectional type assertion against Pi's getThinkingLevel return type, so the tracked strict typecheck against the installed package fails the moment Pi adds or removes a level. docs/configuration.md owns the operator-facing schema for both pins. Portable regressions cover the pin on create and reopen, model-only and effort-only pins working independently, clearing a pin returning the branch to main's effort, live-follow of a mid-session change, the clamp, an unrecognized token, the unknown-main-effort fallback, and the command's two-step flow, persistence, cancellation, and honest reporting. The opt-in real-SDK guard proves the vendor surface all of that rests on, and also repairs a pre-existing gap that left it unable to load the extension at all. * no-mistakes(review): Resolve effective branch effort honestly * no-mistakes(document): Clarify Pi-owned effort picker behavior
…3093) * fix(supervision): silence empty board closes and decouple the heartbeat Two unrelated sources of noise put routine supervision events in the captain's chat. An empty Lavish board close - the captain reads a review surface, says nothing, and closes it - became a check wake whose entire content was that nothing happened. Suppress it at its source instead of routing it anywhere: the generic runner gains a `silent` adapter seam mirroring the existing `terminal` one, and the Lavish adapter answers it for exactly one positively-determined shape, an `ended` session carrying no queued content block. A silenced result is recorded durably handled so it does not return on a later reconcile. Everything else announces unchanged - a `Send & End` close carrying the captain's real answer, an `ended` result still carrying content, a waiting or missing session, an unreadable result, and every adapter that implements no `silent` command at all. The keyed-answer feed is untouched, so suppressing an announcement never suppresses the captain's own answer. A fleet heartbeat was deferred to main merely because some unrelated check row happened to be sitting unread, which put a routine fleet review in the chat for a reason that had nothing to do with the fleet. A check row is permanently main-owned, so it is now excluded from a heartbeat claim rather than vetoing the scan, exactly as in every other mode. What all-or-nothing guarantees is unchanged: the branch takes every branch-ownable unread row or none of them, and an unresolvable task-local row, an unknown row kind, or an unreadable queue still defers the whole review to main. Main is still woken for the check on that check's own triggering close, so nothing starves. Main-only classes are unchanged and now each covered by a test: Relay mentions, credential failures, merge confirmations, real board answers, and watcher-failure repair. The per-actor acknowledgement and no-cross-swallow properties are untouched. * no-mistakes(review): Fail closed on all Lavish content headers * no-mistakes(review): Suppress false unacknowledged status for silenced results
kunchenguid#1967) * fix(classify): read the decision fold through a correlation token status_line_verb stripped a trailing [key=...] from a status line's prefix but left everything else glued to the verb, so a line carrying the correlation token bin/fm-pending-reply-lib.sh embeds and a secondmate echoes back matched no arm of _fm_decision_fold_line. Such a line folded as ordinary status in both directions: a needs-decision or blocked opener never opened its key, and a resolved or captain-held closer never closed one. The same glued verb also hid correlated done and blocked lines from status_is_captain_relevant and status_is_terminal_verb, and let correlated working and resolved lines leak through the free-text fallback the nonterminal guard was meant to stop. The verb parse now walks whole words and drops only a token of the exact shape a firstmate library writes - corr=<16 hex>, plus the bracketed form bin/fm-secondmate-report.sh emits - before or after the key token, unkeyed, or doubled. An arbitrary name=value word is deliberately NOT skipped: skipping unknown tokens would let free text carrying an equals sign reduce to a bare verb and impersonate a transition, which is the takeover the strict parse and _fm_decision_key_transition_allowed exist to prevent. A prefix with no corr= substring is returned byte-for-byte as before, so every line without a token keeps its exact historical verb. FM_OPEN_DECISIONS_FOLD_VERSION goes to 3, because every cursor persisted under the previous reading carries an open set computed while correlated lines were invisible and must be rebuilt from byte 0. Measured over a real 383-line status log: 254 lines keep byte-identical captain-relevance, pause, terminal-verb and captain-held verdicts, and all 129 changed lines carry a valid token - 14 correlated done/blocked/ needs-decision lines become captain-visible, and 20 correlated working/resolved lines stop being escalated on prose alone. * fix(review): Captain, block token-first decision impersonation * fix(document): Clarify normalized status verb ownership * fix(classify): reconcile the correlation-token read with the tag-stop parser Rebasing onto main put this change beside kunchenguid#2280, which made verb parsing stop at the first "[name=value]" tag. Both edit status_line_verb with different intents, so the resolution keeps both rules rather than letting one overwrite the other: - kunchenguid#2280's tag stop is kept verbatim and now owns every BRACKETED tag, including the "[corr=...]" form fm-secondmate-report.sh writes. The bracket-unwrapping arm this branch had added to the token test is therefore removed as unreachable. - This branch's token walk is kept and narrowed to the UNBRACKETED token fm-pending-reply-lib.sh writes, which the tag stop does not reach. Two consequences of standing beside kunchenguid#2280 rather than before it: The fold version had collided at 4: kunchenguid#2280 spent it on the tag-stop parser and this branch had spent it on the token read. A cursor persisted under kunchenguid#2280's reading predates this one and must still be rebuilt, so the version moves to 5. A bracketed impostor is dropped from the malformed-token list. On main today "resolved [corr=deadbeef] [key=victim]:" already reads as the bare verb, as does "resolved [anything at all] [key=victim]:", because the tag stop ends the parse at the opening bracket regardless of content. That is kunchenguid#2280's reviewed contract; asserting otherwise here would narrow it. The unbracketed impostors it owns stay strict and still fold as prose. Adds a consumer test for the two verb-string case arms that postdate this branch: fm-supervise-daemon.sh's transient-stale arm and fm-crew-state.sh's map_log_state. * fix(review): Captain: Seed cursor migration fixture with version four * fix(document): Clarify voice status normalization ownership
Rebuilt from the current fork main (c3a2490), which had independently absorbed 4 of the original 7 upstream commits via its own kunchenguid:main merge while this sync was in progress. This merges the 3 that remained: - 9ce69ac fix(bin): stop a correlation token from hiding and stranding decisions (kunchenguid#1967) - 07bf0c8 fix: keep routine supervision noise out of captain chat (kunchenguid#3093) - f7a387f feat(pi): let /supervision-model pick branch reasoning effort (kunchenguid#3079) Conflict resolution (2 files), both from upstream kunchenguid#3093 adding a new adapter "silent" no-op suppression path, against the process-event adapter this fork renamed lavish -> atelier in df367d7: - bin/fm-procevent-atelier.sh: adopted upstream's new `silent` subcommand, its doc block, and the extended usage() range, keeping the fork's Atelier naming and Atelier-specific header notes. Auto-merged cmd_silent() body and dispatch retained; the one leftover upstream "Lavish" mention renamed. - .agents/skills/process-event-sources/SKILL.md: kept the fork's two Atelier guidance lines and inserted upstream's new "routine no-op" line rewritten for Atelier. Renamed upstream-introduced Lavish/lavish orphans to Atelier/atelier in docs/configuration.md, docs/verification/process-event-sources.md, tests/fm-procevent.test.sh, tests/fm-pi-watch-extension.test.sh so nothing references the nonexistent fm-procevent-lavish.sh. Full-tree grep confirms zero lavish references remain. Verified: bin/fm-lint.sh clean (shellcheck 0.11.0, actionlint 1.7.12); fm-procevent, fm-pi-watch-extension, fm-classify-corr-token all green. One flaky timing failure in an fm-pi-watch-extension watcher-lock case passed on re-run and passes identically on plain main, so it is pre-existing flakiness, not a merge regression.
knowttl
force-pushed
the
fm/fm-upstream-sync-15
branch
from
August 26, 2026 17:03
8299348 to
b735641
Compare
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.
Brings the fork up to date with its upstream parent, absorbing 7 commits.
Absorbed
Conflicts resolved (2)
Both stem from upstream kunchenguid#3093 adding a new adapter
silentno-op suppression path to the process-event adapter, which this fork renamed lavish -> atelier in df367d7.silentsubcommand, its doc block, and the extendedusage()range, while keeping the fork's Atelier naming and Atelier-specific header notes (verified against 0.3.3, the--fullflag). Auto-mergedcmd_silent()body and dispatch retained; the one leftover upstream "Lavish" mention renamed.Orphan cleanup
Renamed upstream-introduced
Lavish/lavishreferences in auto-merged additions so nothing points at the nonexistentfm-procevent-lavish.sh:docs/configuration.md,docs/verification/process-event-sources.md,tests/fm-procevent.test.sh,tests/fm-pi-watch-extension.test.sh. Full-tree grep confirms zerolavishreferences remain.Verification
bin/fm-lint.shclean (shellcheck 0.11.0, actionlint 1.7.12)