Skip to content

sync: merge upstream kunchenguid/firstmate main (7 commits) - #35

Merged
knowttl merged 4 commits into
mainfrom
fm/fm-upstream-sync-15
Aug 26, 2026
Merged

knowttl merged 4 commits into
mainfrom
fm/fm-upstream-sync-15

Conversation

@knowttl

@knowttl knowttl commented Aug 26, 2026

Copy link
Copy Markdown
Owner

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 silent no-op suppression path to the process-event adapter, which 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, while keeping the fork's Atelier naming and Atelier-specific header notes (verified against 0.3.3, the --full flag). 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.

Orphan cleanup

Renamed upstream-introduced Lavish/lavish references in auto-merged additions so nothing points at the nonexistent fm-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 zero lavish references remain.

Verification

  • bin/fm-lint.sh clean (shellcheck 0.11.0, actionlint 1.7.12)
  • All conflict-touched and new upstream suites green: fm-procevent, fm-pi-watch-extension, fm-classify-corr-token, fm-no-mistakes-required, fm-pr-check-security, fm-wake-queue, fm-startup-network (0 failures)

kunchenguid and others added 3 commits August 25, 2026 22:08
…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
@knowttl knowttl closed this Aug 26, 2026
@knowttl knowttl reopened this Aug 26, 2026
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
knowttl force-pushed the fm/fm-upstream-sync-15 branch from 8299348 to b735641 Compare August 26, 2026 17:03
@knowttl
knowttl merged commit 516c8cd into main Aug 26, 2026
@knowttl
knowttl deleted the fm/fm-upstream-sync-15 branch August 26, 2026 17:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants