Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
9b45d6c
fix: preserve authorized follow-on work for second mates (#44)
knowttl Sep 23, 2026
29f8b97
fix(bin): keep process identity stable across host clock steps (#45)
knowttl Sep 23, 2026
8945562
fix(bin): prevent Linux remote job worker pileups after clock changes…
knowttl Sep 23, 2026
0284318
Merge branch 'kunchenguid:main' into main
knowttl Sep 23, 2026
1c7f81e
fix: surface newly ready gated backlog work (#48)
knowttl Sep 23, 2026
fad8567
fix: prevent away-mode escalation injection wedges (#49)
knowttl Sep 23, 2026
a0f1363
Revert "fix: prevent away-mode escalation injection wedges (#49)"
knowttl Sep 26, 2026
867fb87
Merge upstream kunchenguid/firstmate main into fork main
knowttl Sep 26, 2026
467aaf4
Merge branch 'kunchenguid:main' into main
knowttl Sep 26, 2026
eda9e3f
Merge branch 'kunchenguid:main' into main
knowttl Sep 26, 2026
82cb8d2
fix(bin): pass the dispatch profile effort to OpenCode workers throug…
karotkriss Sep 26, 2026
9f94209
fix: stop cancelled validation runs from reporting false failures (#5…
mremond Sep 26, 2026
2cf51eb
fix: require declared waits for workers awaiting their own work (#5812)
mremond Sep 26, 2026
8c958a4
fix: bound ShellCheck to one canonical root per process (#5770)
kunchenguid Sep 26, 2026
30b7ac3
fix: bound watcher cleanup wait on the downtime-marker lock (#5732)
kunchenguid Sep 26, 2026
28b1cf9
test: stop the remote secondmate e2e watcher before temp-root cleanup…
aminry Sep 26, 2026
8a47393
fix(bin): stop reporting untouched shared-captain copies as drift (#4…
tiago-peixoto Sep 26, 2026
3fe43dc
docs: restructure calm.md for readability (#5604)
tmchow Sep 27, 2026
316c937
docs: restructure turnend-guard.md for readability (#5611)
tmchow Sep 27, 2026
58f1db2
docs: move situational AGENTS.md sections into on-demand skills (#5872)
kunchenguid Sep 27, 2026
53a381f
fix: route second-mate signal wakes by presented status span (#5879)
kunchenguid Sep 27, 2026
58389a4
fix(bin): take the source lock before the lifecycle lock in register-…
FocalFactotum Sep 27, 2026
eeda9dc
fix: chain repository hooks under git -c overrides (#5877)
FocalFactotum Sep 27, 2026
67f5452
fix(bin): withhold never-send values from dispatch resolver requests …
zachlandes Sep 27, 2026
e0d6a8b
feat(jev): add the guard framework contract and the memory RSS/swap t…
RooseveltAdvisors Sep 27, 2026
c08bcf3
fix: prevent contribution poll starvation on slow GitHub reads (#5900)
0x7067 Sep 27, 2026
e58cd0b
feat(bin): add config/keep-ai-trailers opt-out to keep AI co-author t…
kiatng Sep 27, 2026
ce26762
fix(bin): capture the full viewport for Herdr composer reads so a sla…
andrewesweet Sep 27, 2026
f5e17c2
fix(bin): isolate per-task endpoint reads in bounded children with a …
andrewesweet Sep 27, 2026
2acaa18
fix: keep lab tmux sockets private and short under deep worktrees (#5…
kunchenguid Sep 27, 2026
324f324
fix: silence routine no-change supervision outcomes (#5808)
jcpoyser Sep 27, 2026
bc3de08
feat: make /quiet a statement when attended supervision is ready (#5928)
kunchenguid Sep 27, 2026
987d3c5
fix: grant Claude workers access to Firstmate task channels (#5884)
kunchenguid Sep 27, 2026
59c565a
fix(bin): prevent idle recovery loops without stranding wakes (#4819)
jokim1 Sep 27, 2026
4b4e2e9
fix: reduce remote worker and polling helper process churn (#5889)
kunchenguid Sep 27, 2026
eb08dc5
fix: keep remote reply listeners and watcher cycles running (#5941)
kunchenguid Sep 27, 2026
8410563
fix: make attended cutover outcome re-presentation check-first (#5925)
kunchenguid Sep 28, 2026
1317d1e
fix: restore primary rewakes after attended main-only closes (#5961)
kunchenguid Sep 28, 2026
54645df
Clarify live Claude login for opted-in tests (#5975)
kunchenguid Sep 28, 2026
edc819c
fix(bin): ensure resumed worker launches enter their recorded worktre…
mehulbhagwani Sep 28, 2026
6c03ebf
fix(bin): retire task-keyed watcher markers and orphan journals at te…
karotkriss Sep 28, 2026
2b3a226
test: guard the live harness gate against Claude Code's auto-updater …
karotkriss Sep 28, 2026
06a8d24
fix(bin): ring the worker inbox doorbell only for a newly written pro…
karotkriss Sep 28, 2026
492f39a
fix: prevent manual Claude Stop hook calls from arming supervision (#…
kunchenguid Sep 28, 2026
68574df
feat(firstmate-calm): show supervision notes in Claude Code (#6039)
kunchenguid Sep 28, 2026
c4cdc7f
fix: stop quiet mode from holding requested actions for return (#6033)
kunchenguid Sep 28, 2026
b2c75d1
Say ahoy impact order is the first mate's pick. (#6065)
kunchenguid Sep 28, 2026
60ec57e
fix(bin): accept a task's next PR after its bound PR merges in fm-pr-…
karotkriss Sep 28, 2026
14fc151
fix: treat quiet records as attended across supervision (#6064)
kunchenguid Sep 29, 2026
da6da2b
fix(bin): prevent Linux remote job worker pileups after clock changes…
knowttl Sep 23, 2026
f9d1688
fix: drop discarded ready gated backlog work after rebase
knowttl Sep 29, 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
9 changes: 5 additions & 4 deletions .agents/skills/afk/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Away mode is a POSTURE of the one supervision session, not a second architecture
Being away changes exactly two things: how the captain is informed, and what happens at a captain-owned decision point (hold for return, or the answer the captain's away words already gave).
It never changes the authority set.
The posture is a file, `state/.afk-contract`, written only by `bin/fm-afk-contract.sh` in the same turn as `/afk`; nothing infers the posture from chat.
A record carrying quiet mode (`bin/fm-afk-contract.sh mode`) is not this posture: the captain is present, so none of this skill's holds for a return apply to it (the `quiet` skill owns it).
Typing `/afk` is itself the go: the captain may not look at the screen again, so entry never waits for a further human response, and no read-back gates it or asks for a go.
Hold-for-return is the default and the only reach profile this release records: there is no phone channel, and the entry announcement says so aloud every time.

Expand All @@ -34,7 +35,7 @@ Hold-for-return is the default and the only reach profile this release records:
- **Claude, Cursor, OpenCode, omp, Grok, or Codex with `config/supervision-host`**: nothing to launch for `/afk`; go on to the announcement.
The supervision host (`docs/supervision-host.md`) is the away session there: it runs the branch's contract on a headless engine under the record while main is parked, and `bin/fm-afk-launch.sh start` and `start-native` refuse the away daemon on that home.
If `enter` printed a `Supervision host: no engine ...` line, every away wake reaches this conversation instead; say so in the announcement.
`/quiet` is unchanged there and still launches the daemon below.
`/quiet` enters nothing there where the attended host runs, and otherwise still launches the daemon below (the quiet skill's `quiet-check` decides).
- **Harness WITH a native in-pane tracked-background tool** (claude's and grok's, without the supervision host): run `bin/fm-afk-launch.sh start-native`, then run `FM_AFK_STATE_PREPARED=1 bin/fm-afk-start.sh` through that native tool.
This is a deliberate no-separate-terminal exception because the harness-hosted job creates no terminal or layout mutation, and a shell launcher cannot invoke a harness-native background tool.
If the native launch fails, run `bin/fm-afk-launch.sh stop` to roll back the prepared lifecycle.
Expand Down Expand Up @@ -94,9 +95,9 @@ afk changes how the captain is informed and what happens at a captain-owned deci
A PR ready for merge keeps the merge authority from `AGENTS.md` section 7, and a needs-decision finding keeps the `ask-user-authority` policy; anything requiring the captain still waits for the captain's explicit word.
While the away-posture record exists, any pull request green at its live head may merge under away authority; which one the captain's words meant is the away session's reading, and a merge the words do not call for holds for the return.
Away authority never releases a captain hold, and it expires when the away record is archived.
`--allow-red` and `--allow-missing` remain attended-only and are refused while the record exists.
A merge under away authority must be synchronous; `fm-pr-merge.sh` refuses auto-merge and any GitHub queue state that cannot prove an immediate merge while the record exists.
The same gates bind whichever actor performs the action: on Pi the parked main's standing authority relocates to the supervision branch, which meets exactly these rules, and the spend cap recorded at entry is enforced by `fm-spawn.sh` for both actors while the record exists.
`--allow-red` and `--allow-missing` remain attended-only and are refused while the away record exists.
A merge under away authority must be synchronous; `fm-pr-merge.sh` refuses auto-merge and any GitHub queue state that cannot prove an immediate merge while the away record exists.
The same gates bind whichever actor performs the action: on Pi the parked main's standing authority relocates to the supervision branch, which meets exactly these rules, and the spend cap recorded at entry is enforced by `fm-spawn.sh` for both actors while the away record exists.
The captain's away words are their explicit instruction given before leaving, recorded verbatim and acted on by the away session's judgment at the moment an event makes them relevant; the words cover nothing they do not say, are never applied by analogy, and die at archive.
Destructive, irreversible, and security-sensitive actions are never pre-authorizable whatever the words say.

Expand Down
28 changes: 28 additions & 0 deletions .agents/skills/agent-skill-trigger-index/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
name: agent-skill-trigger-index
description: Load only when auditing or maintaining the complete agent-only skill trigger index.
user-invocable: false
metadata:
internal: true
---

# Agent-only reference skills

These skills are not captain-invocable; load them only at their precise triggers.

- `bootstrap-diagnostics` - load whenever the session-start digest's bootstrap or network-checks section prints an actionable diagnostic line (`MISSING:`, `MISSING_MANUAL:`, `PRESENTATION_UNAVAILABLE:`, `BACKEND_INVALID:`, `NEEDS_GH_AUTH`, `TANGLE:`, `STARTUP_MEMORY_BUDGET:`, `CREW_DISPATCH: invalid`, `FLEET_SYNC:`, `NETWORK_CHECKS:`, `HOME_SUMMARY:`, `BACKLOG_RECONCILE:`, `SECONDMATE_SYNC:`, `SECONDMATE_LIVENESS:`, `SECONDMATE_HANDOFF:`, `NUDGE_SECONDMATES:`, or `FMX:`), or when `BOOTSTRAP_INFO:` says an interrupted backlog cleanup may have left an endpoint or local copy; silence and other `BOOTSTRAP_INFO:` facts need no load.
- `diagnostic-reasoning` - load before scoping a reported bug and before acting on a diagnostic report.
- `ask-user-authority` - load before deciding any ask-user finding.
- `quota-array-dispatch` - load before choosing among a matched crew-dispatch profile array from current quota-axi default TOON.
- `harness-adapters` - load before spawning or recovering a crewmate or secondmate, handling a trust dialog, sending a harness-specific skill invocation, interrupting or exiting an agent, resuming an exited agent, or verifying a new harness adapter.
- `firstmate-orca` - load before switching to Orca, spawning or supervising Orca-backed work, smoke-testing Orca backend behavior, debugging Orca task state, or reconciling Orca-backed task metadata.
- `project-management` - load before adding, creating, removing, or initializing a project.
Cloning or registering a project is add intake and uses the same trigger.
- `stuck-crewmate-recovery` - load when the session-start digest reports an ordinary direct report's endpoint dead or its metadata has no window, after a stale wake, looping pane, repeated confusion, an answered-by-brief question, an unresponsive crewmate, or a failed steer, and whenever a live worker reports its no-mistakes pipeline dead, unreachable, or timed out.
- `secondmate-provisioning` - load before creating, seeding, validating, launching, handing backlog to, recovering, pushing inherited local material into, or retiring a secondmate home, and before editing `data/secondmates.md`.
- `captain-hold-lifecycle` - load before treating an investigation or visual review as complete, before ending a visual review that exposed a captain decision, when recording or routing the captain's answer, and on any `RECORD DIVERGENCE` line from the wake drain.
- `process-event-sources` - load before arming a long-polling source, before registering a deterministic condition->action watch (do X as soon as Y is true), on any `procevent <adapter> <source-id> <sequence>` check wake, and on any `process-event source stranded` or `process-event source failed to start` check wake.
Never run a registered source's blocking command yourself in a conversational turn.
- `fmx-respond` - load on an `x-mention <request_id>` `check:` wake to handle the mention, on an `x-mode-error ...` `check:` wake to report the Relay configuration blocker, on a `public-followup ...` `check:` wake or a startup-surfaced public commitment, and on any milestone or terminal wake for a Relay-linked task before posting its completion follow-up; relevant only when Relay is on.
- `firstmate-codexapp` - load before coordinating a visible Codex Desktop thread, evaluating a Codex App backend request, or reconciling Codex Desktop host-tool smoke evidence for Firstmate work.
- `firstmate-coding-guidelines` - load before changing firstmate's shared, tracked material, as defined by section 1's list, whether editing directly or briefing a crewmate for a firstmate-repo task.
2 changes: 1 addition & 1 deletion .agents/skills/ahoy/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Give the captain a concise session-only recap without gathering fresh state.
If neither ordinary events nor visibly open decisions exist, say directly in one sentence that nothing happened after the previous captain message.

8. After the normal recap, when the existing visibly open decision inventory contains decisions, begin a guided decision-clearing flow by presenting only the single open decision judged most impactful by the first mate.
Make clear that impact ordering is the first mate's judgment rather than a mechanical score.
Say the ordering is the first mate's pick.
Give enough escalation-quality context to decide easily: the decision, why it matters, the options, and a recommendation.
9. When the captain answers the presented decision, present the next highest-impact decision from that existing inventory in the same form.
Continue one decision at a time until none remain, without starting this flow when the inventory is empty.
Expand Down
24 changes: 24 additions & 0 deletions .agents/skills/away-quiet-supervision/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
name: away-quiet-supervision
description: Load whenever /afk or /quiet is invoked, an away or quiet record exists, or a marked away-supervisor message arrives.
user-invocable: false
metadata:
internal: true
---

# Away and quiet supervision safety

The `/afk` and `/quiet` skills own their respective entry procedures and share the daemon machinery; [architecture](../../../docs/architecture.md) owns the captain-held recheck difference between their postures.
These safety facts apply to both:

- Every current daemon injection uses the `away-supervisor` kind from `bin/fm-operational-input.sh` after `FM_OPERATIONAL_PREFIX` (U+2063 INVISIBLE SEPARATOR followed by `FIRSTMATE_OP: `), except that a Claude Code primary, which strips U+2063, receives that owner's record-backed doorbell and it counts as marked only when `bin/fm-operational-input.sh open <path>` verifies its record; the `/afk` skill owns legacy bare-marker compatibility.
- `state/.afk-contract` is the away posture, written in the same turn as `/afk` before any other work, because `/afk` is itself the go: no read-back gates entry or waits for a go; entry announces hold-for-return only, and the away session acts on those words by its own judgment through the guarded scripts under standing authority, holding for the return on doubt.
A record carrying quiet mode (`bin/fm-afk-contract.sh mode`) is quiet mode's instead: the captain is present, it holds nothing for a return, and requested actions proceed under ordinary attended authority.
- While `state/.afk` exists, the daemon owns supervision; do not arm a separate watcher.
The daemon is never launched on Pi, where the ordinary supervision session continues under the record with main parked: the branch takes every safe actionable wake it can, and only a declined wake (including a broken branch or unsafe scan) or a watcher failure wakes main.
Away mode on a non-Pi home with `config/supervision-host` works the same way with the supervision host as the branch; a wake it hands back arrives through that harness's own wake path and is never the captain's return.
- A marked message while away or quiet mode is active is internal escalation and does not exit that mode.
- A message beginning `/afk` refreshes away mode; a message beginning `/quiet` refreshes quiet mode.
- Any other unmarked message means the captain returned in away mode (load `/afk`, run the return owner, and do not process that message as ordinary work until its durable catch-up gate clears), or, in quiet mode, is simply answered as ordinary work with the flag and daemon left untouched until an explicit `/quiet off`.
- Away and quiet mode never expand approval authority for merges, ask-user findings, destructive actions, irreversible actions, or security-sensitive choices.
- Bias ambiguous input toward exit because a present captain takes precedence.
2 changes: 1 addition & 1 deletion .agents/skills/bootstrap-diagnostics/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ metadata:

Handle each printed line as below, before dispatching work that depends on it.
The line formats themselves are owned by `bin/fm-bootstrap.sh`'s header; this playbook owns the response to actionable lines.
The inline rules in `AGENTS.md` section 3 still bind: detect, then consent, then install - never install anything the captain has not approved in this session - and no work is dispatched until the tools it needs are present and GitHub auth is good.
The session-start rules in `session-start-recovery` still bind: detect, then consent, then install - never install anything the captain has not approved in this session - and no work is dispatched until the tools it needs are present and GitHub auth is good.
When any diagnostic needs captain attention, report the plain consequence and requested action using `AGENTS.md` section 9's captain-facing translation contract; do not name the diagnostic label unless the captain needs to paste it into a command or issue.

- `MISSING: <tool> (install: <command>)` - list the missing tools to the captain with a one-line purpose each plus the printed install commands, wait for consent (one approval may cover the list), then run `bin/fm-bootstrap.sh install <approved tools...>`.
Expand Down
2 changes: 1 addition & 1 deletion .agents/skills/captain-hold-lifecycle/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Only `answer` with the captain's words or an evidence-backed `reconcile close` m
Never close anything the captain owns without recording what he actually said: `bin/fm-captain-hold.sh answer` writes his exact words into the task and closes a question-shaped call, while `--release` frees a captain-gated work item to proceed.
A merge approval uses that existing release path because approval permits the merge to proceed; cleanup closes the work only after it lands and records what shipped.
Closing a held row at merge approval instead records completion before landing, so the backlog claims completion before the work actually ships.
When the answer changes what a task must build, follow `AGENTS.md` section 7's Validate contract to preserve the captain's words in the brief and steer the worker.
When the answer changes what a task must build, follow `AGENTS.md` section 7's mid-task ask rule to preserve the captain's words in the brief and steer the worker.
When the captain says "later", that is an answer too: re-hold with `bin/fm-captain-hold.sh hold <id> --reason "<reason>" --until <date>` so the item leaves the live Captain's Call and resurfaces on its date, instead of leaving a live-looking card or fabricating a closure.
"A keyed answer resolves its matching captain-held task" is one capability with one owner, `bin/fm-captain-hold.sh answers`, and every channel that carries a captain answer feeds it the same task id and answer; a channel never maps keys to tasks, records a decision, or resolves anything itself.
Chat already feeds it through `bin/fm-send.sh --resolve-key`, and a captured-answer source feeds it once bound with `bin/fm-captain-hold.sh bind <source-id>`; bind before arming the source, and key each structured question by the held task's id.
Expand Down
2 changes: 1 addition & 1 deletion .agents/skills/firstmate-codexapp/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ For a Firstmate-managed task, include an explicit status instruction:
```text
Append supervisor-visible status lines to <absolute-firstmate-home>/state/<task-id>.status.
Use only these prefixes for status changes: working:, needs-decision:, blocked:, paused:, done:, failed:.
Use paused: only for a deliberate known external wait that should be rechecked later, never for a blocker that needs firstmate to act.
Follow the task brief's status-reporting rule for declaring and resolving waits; bin/fm-brief.sh owns that rule.
Before doing substantive work, append "working: Codex Desktop thread started".
```

Expand Down
7 changes: 4 additions & 3 deletions .agents/skills/firstmate-coding-guidelines/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Before writing a new fact anywhere in this repo, ask where it belongs, in this o
1. Does the firstmate AGENT need this on every session or every turn to operate?
If yes: `AGENTS.md`, inline.
2. Does the agent need it only in a nameable situation - a spawn, a recovery, a specific wake type, a specific lifecycle step?
If yes: an agent-only skill under `.agents/skills/`, plus a one-line trigger pointer left inline in `AGENTS.md` (usually section 13).
If yes: an agent-only skill under `.agents/skills/`, whose description states its load trigger; leave a one-line inline pointer in `AGENTS.md` only when an always-loaded rule must name the skill.
3. Is it public product, setup, or user/operator reference?
If yes: the surface classified for that audience in [`docs/documentation-audiences.md`](../../../docs/documentation-audiences.md), limited to current behavior, setup, supported limits, stable invariants, concise rationale, and current verification entry points.
4. Is it contributor/maintainer architecture?
Expand Down Expand Up @@ -53,7 +53,7 @@ That is the trigger condition for loading the skill, plus any safety-critical fa
Everything else - the procedure, the mechanism, the surrounding detail - moves out completely.
Do not leave a partial restatement behind "just in case".
A partial copy is exactly the duplication the one-owner rule forbids.
The model to copy is `AGENTS.md` section 8's "Away-mode and quiet-mode stub": it keeps only the marker format, the ownership-transfer rule, and the exit condition inline, and points everything else at the `/afk` and `/quiet` skills.
The model to copy is `AGENTS.md` section 8's "Away-mode and quiet-mode stub": it keeps only the skill-invocation triggers inline and points everything else at the `/afk`, `/quiet`, and `away-quiet-supervision` skills.

## Size discipline

Expand All @@ -66,7 +66,7 @@ When in doubt, write the fact into the skill or doc first by patching that owner
## Trigger hygiene

A new skill is dead weight if nothing loads it.
Every new skill needs its load trigger declared inline: section 13 for agent-only reference skills, or the relevant operating section for anything else.
Every new skill needs its load trigger declared in its description, which is the always-loaded trigger index; add an inline `AGENTS.md` pointer only in the operating section whose always-loaded rule must name it.
State the trigger as a condition ("load before X", "load on Y wake"), never as a vague pointer.
Briefs for tasks that touch firstmate's own tracked material should tell the crewmate to load this skill.
`bin/fm-brief.sh`'s `REPO` argument is a caller-supplied string with no reliable signal that it names firstmate's own repo, unlike a project registered in `data/projects.md`, so there is no clean point inside the scaffold to detect this case automatically.
Expand Down Expand Up @@ -125,6 +125,7 @@ Firstmate PR #3644 demonstrated the cost: pinning a 75-162-script walk took 32.7
- Plain dash `-`, never an em dash.
- Never add an agent name as a commit co-author.
- `bin/*.sh` and `bin/backends/*.sh` must pass `shellcheck`.
- Run Firstmate production-library tests and commands that source `bin/` scripts under `bash` explicitly, never through the tool shell's default interpreter.
- Run `bin/fm-lint.sh` before treating a script change as done; it is the single owner of the lint definition that CI and the no-mistakes pre-push gate both invoke, its own header owns what that definition covers, and it refuses to run under any other version of either linter.
- When a task names a specific tool, implement the work with that tool, or explicitly flag the substitution and its new dependency footprint for review before shipping.
- Colocate tests with the existing pattern in `tests/`, name them `<subject>.test.sh`, and extend an existing script rather than inventing a new runner.
Expand Down
Loading
Loading