Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
fbe37e9
feat(bin): add a spoken interface that answers from records and hands…
Inthuson Aug 22, 2026
dc0172c
fix(bin): preserve Relay follow-up loops until explicit disposition (…
kunchenguid Aug 22, 2026
5b6d0fb
feat(bin): merge GitLab merge requests through the guarded PR merge p…
Inthuson Aug 22, 2026
1231b6a
fix(bin): record a lost relay connection instead of an unanswered tur…
Inthuson Aug 22, 2026
8714c9a
fix(composer): stop a blocked pi pane from proving an empty composer …
karotkriss Aug 23, 2026
801c083
fix(bin): require project clone roots during fleet sync (#2849)
karotkriss Aug 23, 2026
505c819
fix(bin): retry transient Lavish poll interruptions (#2846)
karotkriss Aug 23, 2026
86dd2f6
fix(brief): stop the documented {TASK} fill from corrupting the Herdr…
karotkriss Aug 23, 2026
266fdb9
fix(bin): resolve the busy-state lock mtime with the platform's own s…
karotkriss Aug 23, 2026
f170ced
fix(stow): add opt-in pass horizon for memory decay (#2850)
karotkriss Aug 23, 2026
2f250c7
test(watcher): stop fixture confirmation budgets racing real child st…
karotkriss Aug 23, 2026
197afbb
fix(bin): deterministically order remote tool paths (#2870)
karotkriss Aug 23, 2026
52f62ab
fix(bin): prevent routed secondmate work from stranding (#2848)
kunchenguid Aug 23, 2026
822a990
fix: make macOS inbox test path portable (#2857)
kunchenguid Aug 23, 2026
e46df1a
feat(bin): deliver local steers through durable task inboxes (#2856)
kunchenguid Aug 23, 2026
8d8362c
feat(bin): add fast local lint mode (#2891)
kunchenguid Aug 23, 2026
ddf74ef
feat(bin): deliver remote steers through durable inboxes (#2901)
kunchenguid Aug 23, 2026
7b88520
feat: add persistent Pi supervision branch (#2858)
kunchenguid Aug 23, 2026
fb2ce5b
fix(bin): parallelize startup network sweeps (#2927)
kunchenguid Aug 24, 2026
8b21c99
test: handle absent watcher wake queues (#2845)
karotkriss Aug 24, 2026
52ff62e
style(pi): distinguish routine and captain supervision merge notes by…
kunchenguid Aug 24, 2026
d55e00a
docs(pi): add the approved multi-brain architecture poster (#2938)
kunchenguid Aug 24, 2026
8fa0505
feat(pi): default branch supervision and route heartbeats (#2939)
kunchenguid Aug 24, 2026
038d0f7
fix(bin): bound remote job worker supervisor restarts (#2942)
stanzhang Aug 24, 2026
85d6c72
fix: safely split supervision wake handling by actor (#2953)
kunchenguid Aug 25, 2026
6a2cd6c
fix(pi): hide branch outcomes tool rows in Calm (#3024)
kunchenguid Aug 25, 2026
3e5577b
fix: bind no-mistakes attestations to PR head (#3027)
kunchenguid Aug 25, 2026
9a01dea
feat(pi): add persistent supervision branch model selection (#3028)
kunchenguid Aug 25, 2026
f7a387f
feat(pi): let /supervision-model pick branch reasoning effort (#3079)
kunchenguid Aug 26, 2026
07bf0c8
fix: keep routine supervision noise out of captain chat (#3093)
kunchenguid Aug 26, 2026
9ce69ac
fix(bin): stop a correlation token from hiding and stranding decision…
mremond Aug 26, 2026
b0ca8f5
fix(bin): Cursor-Park unter Pi-Host ohne Cursor-Identität stilllegen …
thelad-dev Aug 26, 2026
5aed873
fix(pi): make supervision model picker searchable and scrollable (#3099)
kunchenguid Aug 26, 2026
662a8c7
fix(bin): durably report merged pull requests (#3104)
kunchenguid Aug 26, 2026
60bedde
fix(bearings): preserve projections through inventory mismatches (#3129)
kunchenguid Aug 26, 2026
22fa6ed
fix(bin): reconcile markerless remote secondmates safely (#3140)
kunchenguid Aug 27, 2026
99c1a0d
fix(bin): hand a busy declared pause to the away-mode daemon once, un…
3264studios Aug 27, 2026
524994c
fix(bin): name the stale submodule pin behind a pooled slot refusal (…
mkurt Aug 27, 2026
d63b0e2
fix(pi): prevent stale captain outcome re-emissions (#3154)
kunchenguid Aug 27, 2026
5953e9b
fix(bin): keep a declared wait on the pause cadence under a busy pane…
3264studios Aug 27, 2026
10b93b2
fix(bin): recover Claude auto-arm from hung claims (#3156)
kunchenguid Aug 27, 2026
7ee0c19
fix(bin): verify the real GitHub merge outcome instead of reporting a…
wjkawecki-jt Aug 27, 2026
4f89f5b
fix(pi): prevent duplicate captain outcome reports (#3184)
kunchenguid Aug 27, 2026
bca584a
fix(bin): prioritize active pipeline-owned crew runs (#3194)
kunchenguid Aug 27, 2026
c651b59
fix(pi): surface requested outcomes without replaying fleet events (#…
kunchenguid Aug 28, 2026
1fd7ea2
feat(bin): add concurrent bounded remote transport lanes (#3210)
kunchenguid Aug 28, 2026
4207214
fix(bin): accelerate and bound changed test runs (#3250)
kunchenguid Aug 28, 2026
a390659
feat(bin): publish per-home summary ledgers (#3222)
kunchenguid Aug 29, 2026
52b59a1
fix(pi): gate first provider call on startup context (#3158)
M00NLIG7 Aug 29, 2026
f66be0f
fix(pi): restore Pi 0.84.4 renderer compatibility (#3261)
stanzhang Aug 29, 2026
5f31097
fix(bin): keep home-summary publication from starving supervision (#3…
kunchenguid Aug 29, 2026
4eb587d
fix(bin): prevent routine updates from hiding actionable status (#3268)
kunchenguid Aug 29, 2026
c731c36
docs(skills): split harness adapter operations reference (#3289)
M00NLIG7 Aug 29, 2026
0ace60a
test: centralize shared shell fixtures (#3296)
kunchenguid Aug 29, 2026
9e3df47
refactor: retire legacy PR-check migration machinery (#3299)
kunchenguid Aug 29, 2026
1fbc7bb
feat(bin): add trusted process-event extension bindings (#3247)
M00NLIG7 Aug 29, 2026
c7fdef9
fix(bin): deliver safety rules to promoted workers (#3269)
kunchenguid Aug 30, 2026
debe4bf
fix(bin): present Lavish feedback as structured output (#3321)
kunchenguid Aug 30, 2026
1260adc
fix: keep task records and backlog transitions atomic (#3322)
kunchenguid Aug 30, 2026
d71f4b9
fix(bin): contain promote and Relay metadata publishing (#3342)
kunchenguid Aug 30, 2026
a56a78a
fix(bin): absorb turn-end wakes during bounded pane churn (#2877)
karotkriss Aug 30, 2026
64ef20c
Merge upstream/main into the fork, preserving deliberate fork adjustm…
Aug 31, 2026
44f0364
Merge main into the upstream sync branch
Aug 31, 2026
e2100dd
fix(tests): stop the runner's own fixtures inheriting the developer's…
Aug 31, 2026
60542d7
fix(test-run): keep the fork's captured output instead of upstream's …
Aug 31, 2026
23f184d
fix(herdr): assert presentation-order serialization instead of a wall…
Aug 31, 2026
2bfda17
fix(lint): annotate the two caller-read signals the new guard introduced
Aug 31, 2026
e8fa0fb
fix(lint): put the caller-read disable on the flagged assignments
Aug 31, 2026
a1ddeb1
test: adopt upstream inbox delivery in the fork's own steer assertions
Sep 1, 2026
53efbad
no-mistakes(document): Document new FM_HERDR_PRESENTATION_LOCK_WAIT_S…
digbycampbell Sep 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions .agents/skills/afk/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,7 @@ For tmux that confirmation is normally a proven cleared composer from the shared
Without that baseline, busy state never converts an `unknown` composer into confirmation.
For herdr, idle-baseline submits first seek native agent-state showing a real turn started, then use the shared classifier when native state remains idle: a cleared composer confirms delivery, while pending text retries Enter and reaches the shared busy-queue verdict only after the retry budget.
A bordered-empty or ghost-only composer is recognized as empty where that backend uses composer confirmation, rather than mistaken for a swallowed Enter.
`fm-send.sh` uses the same primitive and exits non-zero
when a steer's Enter is positively swallowed, so firstmate learns an instruction
did not land instead of leaving it unsubmitted.
`fm-send.sh` uses the same primitive only on its typed plane and exits non-zero when that plane's Enter is positively swallowed; ordinary local text steers use the durable inbox and do not treat doorbell submission as delivery proof.

**Busy-queued Enter exception (opencode 1.18.4).** OpenCode keeps queued text visible while it is mid-turn, so tmux and herdr delegate the final delivery decision to `fm_composer_queued_enter_verdict` in `bin/fm-composer-lib.sh` rather than treating visible text alone as a swallowed Enter.
The daemon still clears its buffer only on the backend's `empty` success verdict; [`docs/tmux-backend.md`](../../../docs/tmux-backend.md) and [`docs/herdr-backend.md`](../../../docs/herdr-backend.md) own the backend-specific confirmation signals.
Expand All @@ -135,28 +133,30 @@ The daemon still clears its buffer only on the backend's `empty` success verdict

The daemon wraps `fm-watch.sh`, runs the watcher as a child, presents every durable wake after each actionable watcher close, classifies each presented record in bash, and acknowledges the presented generation only after routing completes.
It self-handles the routine majority without consuming a firstmate turn.
Captain-relevant events, plus a bounded recheck of a declared wait that remains idle, escalate to firstmate's context as one pre-read, single-line, batched digest.
The classification predicates (the captain-relevant verb set, declared-wait vocabulary, signal/stale tests, and fleet-scan) live in the shared `bin/fm-classify-lib.sh`, the same library the always-on watcher uses for its own triage when afk is off, so the two modes apply one identical policy.
Captain-relevant events, plus a bounded recheck of a declared wait that is still declared, escalate to firstmate's context as one pre-read, single-line, batched digest.
The captain-relevant verb set, declared-wait vocabulary, status-span classifier, and presentation-marker contract live in shared `bin/fm-classify-lib.sh`, while each supervisor owns its routing and fleet scan as a consumer of that policy.
While `state/.afk` exists the daemon owns the watcher, so the watcher reverts to one-shot and lets the daemon do the triage - the two never run their triage at the same time.

Classify each wake this way:

- `signal` with a terminal captain verb (`done:`, `needs-decision:`, `blocked:`, or `failed:`) -> escalate.
- `signal` whose newly classified status span contains captain-relevant events -> escalate every event in source order.
A nonterminal progress verb remains nonterminal even when its prose contains a legacy free-text token such as `PR ready`, `checks green`, `ready in branch`, or `merged`; only a bare legacy line with such a token escalates.
Other signals with no captain-relevant status -> self-handle.
- `signal` or `stale` for a declared wait, either a `paused:` external wait or a verified `captain-held` transfer -> self-handle and track the pause rather than a wedge.
If it remains declared and idle past `FM_PAUSE_RESURFACE_SECS` (default 3600s), housekeeping sends one recheck and resets the pause window.
Other signals with no captain-relevant event in the span -> self-handle.
- `signal` or `stale` whose latest status declares a wait, either a `paused:` external wait or a verified `captain-held` transfer, tracks the pause rather than a wedge whether its pane reads idle or busy.
An unreported captain-relevant event in the newly classified span still escalates immediately while the current declaration independently keeps the pause cadence.
With no unreported actionable event, the wake self-handles, and the current declaration outranks an enriched possible-wedge reason so it never escalates on the `FM_STALE_ESCALATE_SECS` cadence.
If it is still declared past `FM_PAUSE_RESURFACE_SECS` (default 3600s), housekeeping sends one recheck and resets the pause window.
The window ages against the crew's own latest status line, so only a status append that stops declaring the wait ends this routing and restores wedge detection.
That recheck names which human the wait is on: the external dependency for `paused:`, and the captain themself for a `captain-held` transfer, who can answer the held decision or release the hold.
- `check` -> always escalate. Check scripts print only when firstmate should wake.
- `stale` with a terminal status or bare legacy captain-relevant line -> escalate.
Nonterminal progress remains transient even when its prose contains a legacy free-text token or its seen-status marker already matches, so record a marker and self-handle.
If the pane is still idle past `FM_STALE_ESCALATE_SECS` (default 240s), housekeeping escalates it as a possible wedge.
This bounds wedge-detection latency to the threshold plus a tick: a delay, never a loss.
Healthy crewmates are autonomous and do not wait on firstmate mid-task.
- `heartbeat` -> self-handle. The daemon runs its own cheap bash fleet scan
every `FM_HEARTBEAT_SCAN_SECS` (default 300s) as the catch-all for a
captain-relevant status line the per-wake classifier might miss.
- Unknown reason, or any uncertainty -> escalate fail-safe.
- `heartbeat` -> self-handle.
The daemon runs its own cheap bash fleet scan every `FM_HEARTBEAT_SCAN_SECS` (default 300s) as the catch-all for captain-relevant events still unread by the per-wake classifier.
- An unknown wake reason escalates fail-safe, while status-read uncertainty follows the shared one-report-without-position-advance contract referenced under Dedupe below.

Escalations are buffered up to `FM_ESCALATE_BATCH_SECS` (default 90s; 0 =
immediate) and flushed as one single-line digest prefixed with the current
Expand Down Expand Up @@ -198,8 +198,8 @@ the operational prefix lets firstmate distinguish it from a real captain message
text firstmate sees is clean.
- **Portable singleton lock** - the daemon uses the repo's portable lock helper
(`fm-wake-lib.sh`) instead of `flock`, which is absent on macOS.
- **Dedupe across signal/stale/scan** - `classify_signal` and terminal `classify_stale` paths check the seen-status marker before escalating, so a captain-relevant status escalated by one path is not re-escalated by another in the same digest.
The marker does not clear or suppress possible-wedge aging for a nonterminal progress line.
- **Dedupe across signal/stale/scan** - all three paths use the shared status presentation markers defined by `bin/fm-classify-lib.sh`, so a successfully classified span is not re-escalated by another path in the same digest.
Never treat a reported unreadable state as classified; the shared library header owns that marker contract, and the marker does not clear or suppress possible-wedge aging for a nonterminal progress line.
- **Auto-discovered supervisor pane** - the daemon resolves its own BACKEND
(tmux vs herdr) and TARGET independently, mirroring
`bin/fm-backend.sh`'s own runtime auto-detection. Backend: `FM_SUPERVISOR_BACKEND`
Expand Down
29 changes: 20 additions & 9 deletions .agents/skills/bearings/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ Generate a complete current snapshot from the fleet's current state, so the capt
Plain `/bearings` returns only the concise four-section chat digest.
Only `/bearings file` writes the dated markdown report artifact and then returns the concise four-section chat digest linked to that report.
Only `/bearings lavish` builds the interactive fleet board beside that digest, through `bin/fm-bearings-board.sh` (its header owns every board mechanic and the fm-bearings-board.v1 payload contract).
A digest/build invocation is operationally read-only apart from those explicit per-mode artifacts: the dated report in file mode, and in lavish mode the board file plus the answer binding and source registration that `bin/fm-bearings-board.sh build` records through their own owners.
During that invocation it never tears down a task, merges a PR, dispatches new work, steers a worker, answers a decision, cleans up work, or mutates backlog or task state.
A digest/build invocation is operationally read-only apart from the cooldown-limited reconcile instruction and its `state/<id>.reconcile-nudged` record, plus the explicit per-mode artifacts: the dated report in file mode, and in lavish mode the board file plus the answer binding and source registration that `bin/fm-bearings-board.sh build` records through their own owners.
During that invocation it never tears down a task, merges a PR, dispatches new work, steers a worker except through that reconcile hook, answers a decision, cleans up work, or mutates backlog or task state beyond the reconcile record.
Board answers are acted on later under the normal authority rules; this skill's board-wake section explicitly owns the guarded routing at that time.

## Invocation modes
Expand All @@ -33,8 +33,8 @@ Board answers are acted on later under the normal authority rules; this skill's
## What it does

1. **Gather live fleet state with one deterministic command.**
Run `bin/fm-bearings-snapshot.sh` at invocation time and read its compact output.
It is the single bounded, deterministic fleet-state source for Bearings and renders TOON by default.
Run `snapshot=$(bin/fm-bearings-snapshot.sh --json)` at invocation time and read that compact output.
It is the single bounded, deterministic fleet-state source for Bearings.
Do not create or consult a second fleet-state reader, parser contract, status-event-tail interpretation, visible-session recap, ad-hoc project probe, or ad-hoc `gh-axi`/`gh` query.
The command's header and `--help` output own its exact fields, bounds, opt-ins, and output contract.
Keep the default local-only read unless the captain asks to include PRs.
Expand All @@ -47,13 +47,22 @@ Board answers are acted on later under the normal authority rules; this skill's
Until then it stays queued with the reason.
The `(main-inventory)` gate is an action-free integrity warning rather than queued work.
Render it under Charted Next with the related `omitted` disclosure, never invent an Underway row from backlog-only state, and never move it into Captain's Call.
The same holds for a secondmate home whose current state is unavailable, and for a readable home whose `invalidity` reports a backlog-vs-metadata mismatch: the mismatch is a repair notice about that home's own books, not a reason to drop its separately projected decisions, queued, landed, or live work.

2. **Compose the four-section chat digest from the fresh snapshot.**
2. **Ask any home whose own books disagree to reconcile them.**
When the snapshot reports a secondmate home whose `invalidity` is `orphan_in_flight`, `unowned_current`, or `terminal_in_flight`, that home's backlog and its own task metadata disagree and only that home may fix it.
Run `printf '%s\n' "$snapshot" | bin/fm-secondmate-reconcile.sh notify --snapshot -` inline immediately after gathering the snapshot, so the durable fire-and-forget enqueue finishes before digest composition without spawning any child or second snapshot.
The script header owns the cooldown window, non-blocking lock skips, stale-endpoint checks, retry, and fire-and-forget delivery contract; this hook arms no reply recovery or inbox escalation.
If the hook reports a skip or failure, continue composing the digest from the captured snapshot; a lock skip or known-undelivered send leaves the cooldown unset for a later recap.
A home is asked at most once per four-hour window, so running this on every recap costs nothing and cannot nag, while a mismatch still sitting there after the window earns one gentle re-nudge.
Never edit another home's backlog or metadata from here, and never expect or wait on a reply: the mate acts asynchronously from its durable inbox while the digest is composed from the snapshot already in hand.

3. **Compose the four-section chat digest from the fresh snapshot.**
The gather step is deterministic; your judgment is scoped to ranking the command's facts by what matters right now and writing scannable captain-facing prose.
The chat response uses the four complete sections in the chat-response contract below, in the same order, each always present.
Plain mode stops here and writes no report artifact.

3. **In explicit file mode only, compose and replace the detailed report file.**
4. **In explicit file mode only, compose and replace the detailed report file.**
The report uses the same four complete sections as the chat, in the same order, and adds the detail the chat omits.
Never read an earlier `data/status-report-*.md` to decide what to omit, include, describe as changed, or call current.
Write the full report to `data/status-report-<YYYY-MM-DD>.md` using today's date.
Expand All @@ -80,6 +89,8 @@ Compose the payload from the same snapshot with the same ranking judgment as the
- Decision cards carry agent-authored copy: a short noun-phrase title, one-line `about` and `decide` context rows, and option labels with hints, with the recommended option marked.
- Card `type` (decision, merge, credential) is your composing judgment from the row's content; no backlog field types a card for you.
- When the card's task is a captain-gated WORK item (the answer should free it to proceed rather than complete it), set the card's `close: "release"` so the answer lifts the hold instead of closing the task; question-shaped items omit it.
- A Charted Next row's optional `kind` separates work from alarms: omit it (or set `"queued"`) for real queued work, and set `"warning"` on every action-free fleet-integrity notice - the `(main-inventory)` gate, an unavailable secondmate home, and an inventory-mismatch repair notice. The board badges a warning row `needs repair` instead of `waiting` and leaves it out of the Charted Next count, so those rows never read as dispatchable queued work.
- `charted_more` counts omitted queued rows only, while `charted_warning_more` counts omitted warning rows only; keep both counts separate whenever the board payload truncates Charted Next.
- Every Captain's Call item and every Underway, Recently Landed, and Charted Next row carries an explicit `repo` field. Fill it from the snapshot and task records wherever known; use null or an empty string only as the deliberate genuinely-no-repo marker, in which case the template may show the internal id. Ids otherwise stay in the payload only as the routing channel, and composed reasons name blockers in plain words.

Run `build` once after composing the payload.
Expand Down Expand Up @@ -126,7 +137,7 @@ Rules that keep the contract unambiguous:
- The four buckets are mutually exclusive, so every item is forced into exactly one: needs-your-action is Captain's Call, done is Recently Landed, self-progressing is Underway, and not-yet-started work or an action-free fleet-integrity warning is Charted Next.
- The strict boundary keeps action-free items OUT of Captain's Call: a working or validating task, a queued item blocked on another task or a date, landed work, a completed scout's report pointer, a declared `paused:` external wait, and a bare recorded PR with no merge-ready signal each belong to one of the other three sections, never Captain's Call.
- A secondmate's own row appears Underway only for `active_child_work`; `externally_held` belongs in Charted Next, and `unknown` belongs there as an unavailable-state gate unless its reason requires the captain's action.
- Do not suppress separately projected decisions, landed records, or gates from a `partial-structured` home merely because that secondmate's own row is `unknown`.
- Do not suppress separately projected decisions, landed records, or gates from a `partial-structured` home merely because that secondmate's own row is `unknown` or its `invalidity` reports an inventory mismatch.
- Include the required direct address to the captain inside one item or empty-state sentence.
- Every PR appears as the full `https://...` URL; a shorthand `#number` is fine only as a back-reference after the full URL has already appeared in the same digest.
- The chat follows `AGENTS.md` section 9 and carries one scannable line per item.
Expand All @@ -143,7 +154,7 @@ Rules that keep the contract unambiguous:

## Supervision discipline

During a digest/build invocation, this skill changes no fleet state beyond its explicit report or board artifacts, binding, and source registration.
Do not tear down a task, merge a PR, dispatch queued work, steer a worker, answer a queued decision, clean up work, or mutate any other `state/` or `data/` file during that invocation.
During a digest/build invocation, this skill changes no fleet state beyond its reconcile instruction and cooldown record, explicit report or board artifacts, binding, and source registration.
Do not tear down a task, merge a PR, dispatch queued work, steer a worker except through the reconcile hook, answer a queued decision, clean up work, or mutate any other `state/` or `data/` file during that invocation.
If the state gathered for the digest suggests an action, name it in its section and leave it to the normal lifecycle and configured authority.
On a later board wake, this read-only invocation rule yields to "Handling a board wake" and its guarded authority for captain-selected dispatches and merges.
Loading
Loading