Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
92856fd
fix: pre-register Claude trust for secondmate homes (#4262)
kunchenguid Sep 12, 2026
c191eac
fix: ignore superseded failed GitHub check runs (#4258)
kunchenguid Sep 12, 2026
de00521
fix(bin): persist merge authority for poll-detected outcomes (#4266)
kunchenguid Sep 12, 2026
83c63cc
ci: supersede superseded PR CI and bound unbounded jobs (#4281)
kunchenguid Sep 12, 2026
fa65b5d
test(watch): gate backlog-hold away-record fixture on tasks-axi (#4288)
cipherholdingsllc Sep 12, 2026
fb19dd9
fix(backlog): bound per-item backlog row reads so a wedged backend ca…
RooseveltAdvisors Sep 12, 2026
76d4405
fix(merge): serialize away authority with synchronous merges (#4285)
kunchenguid Sep 12, 2026
3576148
feat(bin): add Antigravity CLI (agy) as third worker/scout adapter (#…
AnPod Sep 12, 2026
b518a25
feat(afk): add quiet supervision mode for a present captain (#4337)
NewAiCoder-bot Sep 13, 2026
0962d4a
fix(bin): let verified harness ancestry outrank retained markers (#3)…
NewAiCoder Sep 13, 2026
305dfff
fix(bin): pre-approve external CLAUDE.md import dialog for spawned wo…
NewAiCoder-bot Sep 13, 2026
ecfe071
fix(afk-return): treat an acked watcher-down marker as no gap (#4355)
NewAiCoder-bot Sep 13, 2026
b182d0f
fix(bin): rebind fm-procevent-when trust bindings after a self-update…
NewAiCoder-bot Sep 13, 2026
e3bd750
fix(pr-merge): treat plan-gated 403 on branch rules as no merge queue…
NewAiCoder Sep 14, 2026
036fec0
fix(bin): select suites that read a changed top-level test fixture (#…
tiago-peixoto Sep 14, 2026
267441d
fix(bin): treat Claude Code's default external-imports flags as never…
Rangezi Sep 14, 2026
287f41e
fix(bin): keep operator-address labels out of no-mistakes intent (#4445)
tiago-peixoto Sep 14, 2026
18fe6e9
fix: classify OpenCode ellipsis hint as idle (#4451)
pablontiv Sep 14, 2026
80556bc
fix(composer): recognize Grok 1.0.5's oversized titled bottom border …
pablontiv Sep 14, 2026
c1103a1
fix(bin): translate Stop hook timeout signals into durable auto-arm f…
pablontiv Sep 14, 2026
0b9de13
fix(spawn): establish Claude task channel authority (#4464)
pablontiv Sep 14, 2026
a6618dd
fix(bin): refuse fm-control.sh exit when the composer holds unproven …
pablontiv Sep 14, 2026
c806c6a
fix(spawn): establish crewmate identity first (#4481)
pablontiv Sep 15, 2026
d499323
fix(bin): reconcile redundant secondmate divergence during updates (#…
pablontiv Sep 15, 2026
da5e658
feat: enable gpt-5.6-luna max reasoning for crew dispatch (#4497)
umeranjum17 Sep 15, 2026
616049a
feat(calm): render smooth Unicode swell with asymmetric two-color sai…
yasuhito Sep 15, 2026
aa92177
fix(bin): supersede stale scout delivery text in brief.md on promotio…
pablontiv Sep 15, 2026
b85e28b
fix(bin): make captain holds work on hosts with an older JSON::PP, an…
Marsjohn-11 Sep 15, 2026
8b10b61
fix(bin): read codex 0.154's idle braille starfield rows as composer …
tbillings28 Sep 15, 2026
2da3c5e
fix(bin): refuse empty text steers in fm-send (#4259)
pablontiv Sep 15, 2026
0f242b9
fix(calm): paint the working ship one yellow over all-blue water (#4554)
kunchenguid Sep 15, 2026
a8dd08d
fix(bin): stop aging a second mate's active turn from its launch (#4270)
tiago-peixoto Sep 15, 2026
8b944a1
feat(bin): add read-only PR blocker and reviewer discovery commands (…
tiago-peixoto Sep 15, 2026
db645b8
fix(bin): teach validation-round pauses in generated briefs (#2752)
tiago-peixoto Sep 15, 2026
9ad5fc4
docs(readme): add star history chart (#4558)
kunchenguid Sep 15, 2026
f411479
chore: sync fork to kunchenguid/firstmate main at 9ad5fc42
jjtylr Sep 15, 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
2 changes: 2 additions & 0 deletions .agents/skills/afk/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ No `/back` is needed. The first genuine message is the return signal:
- Re-invoking `/afk` while already away -> stay away (refresh); this does **not** trigger an exit.

Bias ambiguous cases toward exit: a present captain beats token savings, and a false exit is self-correcting (the captain re-runs `/afk`).
When the captain wants this same token-saving supervision while staying present and chatting - ordinary messages should NOT exit it - that is `/quiet` (kunchenguid/firstmate#2356), not `/afk`.

## Orthogonal to approval authority

Expand All @@ -86,6 +87,7 @@ A PR ready for merge keeps the merge authority from `AGENTS.md` section 7, and a
While the away-posture record exists, a merge proceeds only when that task's recorded yolo posture is on or its id is in the record's merge-grant list; otherwise it is held for the captain's return.
A merge grant never releases a captain hold, and it expires when the away record is archived.
`--allow-red` remains attended-only and is 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.
A mandate clause is the captain's explicit instruction given before leaving, recorded with its named object and condition; a clause is never inferred, never applied by analogy, and expires at return.
Forbidden, destructive, irreversible, and security-sensitive actions are never pre-authorizable regardless of clause text, and no recorded clause is authority by itself.
This release records clauses and does not execute them.
Expand Down
2 changes: 1 addition & 1 deletion .agents/skills/firstmate-coding-guidelines/SKILL.md
Original file line number Diff line number Diff line change
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 stub": it keeps only the marker format, the ownership-transfer rule, and the exit condition inline, and points everything else at the `/afk` skill.
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.

## Size discipline

Expand Down
10 changes: 6 additions & 4 deletions .agents/skills/harness-adapters/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: harness-adapters
description: >-
Agent-only reference for firstmate harness operations.
Use 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.
Contains verified facts for claude, codex, opencode, pi, pi-signed, grok, kimi, cursor, gemini, muse, rovo, and omp.
Contains verified facts for claude, codex, opencode, pi, pi-signed, grok, kimi, cursor, gemini, muse, rovo, omp, and agy.
user-invocable: false
metadata:
internal: true
Expand Down Expand Up @@ -35,11 +35,12 @@ For recovery and control, use the exact `harness=` in `state/<id>.meta`; never i
Deliver lifecycle actions only through `../../../bin/fm-control.sh <task-id> interrupt|exit|relaunch`.
Never type an interrupt key or exit command through `fm-send`, where routing-marked lifecycle text becomes chat.
Trust handling is complete only when inspection proves the target started processing its instructions; delivery success alone is not proof.
Muse and Gemini are verified only for crewmate and scout work, never a secondmate or primary.
Muse, Gemini, and AGY are verified only for crewmate and scout work, never a secondmate or primary.

## Detection

`../../../bin/fm-harness.sh` prints firstmate's own harness from verified environment markers, then process ancestry.
`../../../bin/fm-harness.sh` prints firstmate's own harness from verified environment markers and process ancestry, and owns how they combine.
A marker names its harness, but a structural ancestor of a different harness outranks it, because a marker is ordinary environment state a child or a multiplexer can retain while ancestry is what proves who owns the process tree.
Only `FM_PI_HARNESS=pi-signed` at the launch boundary together with `PI_CODING_AGENT=true` selects Pi-signed; shared unmarked launcher ancestry remains Pi.
omp publishes no marker of its own; `FM_OMP_HARNESS=omp` is Firstmate's launch marker and the anchored process name `omp` is its ancestry evidence, as `references/harness/omp.md` records.
`../../../bin/fm-spawn.sh` owns worker marker establishment, while the README launch command owns the signed-primary boundary.
Expand Down Expand Up @@ -93,7 +94,8 @@ A new tool remains undispatchable until the `verify` plan, its harness entry, ev
"gemini": "references/harness/gemini.md",
"muse": "references/harness/muse.md",
"rovo": "references/harness/rovo.md",
"omp": "references/harness/omp.md"
"omp": "references/harness/omp.md",
"agy": "references/harness/agy.md"
}
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,12 @@ Select only its documented trust choice from the active Firstmate home, binding
No observed dialog proves only that launch.

Each supported harness handles its folder-trust gate differently, and the tool reference owns the detail.
Claude gates a fresh worktree and cannot be answered by key, so the spawn pre-registers the path in Claude's own store.
For Claude, load `references/harness/claude.md`; its workspace-trust section owns the non-key-answerable gate and spawn-time pre-registration for every spawn kind.
agy gates every fresh worktree too; the spawn pre-registers it in agy's own store the same way, and a strict post-launch gate answers any dialog that still renders before the spawn reports success.
Cursor suppresses its dialog with launch-time `--trust`, and Muse suppresses its own with `--yolo`.
Grok dodges its gate instead of granting trust, because its project picker appears only outside a project and the spawn starts in the isolated git root.
Pi gates the fresh-worktree case too, but unlike Claude its dialog is answered with Enter, and `references/harness/pi.md` owns that recipe and where the decision persists.
Codex shows a directory-trust dialog on the first run for a repository root.
A Claude secondmate is deliberately not pre-registered, because `../../../bin/fm-spawn.sh` runs its per-harness pre-launch setup only for non-secondmate kinds, so the registration is never invoked for one.
That kind guard is the whole exclusion, because a treehouse-leased secondmate home is itself a linked worktree that the scope test would accept, and only a plain-clone home would be refused as a primary checkout.
The consequence is that a claude secondmate whose home Claude has never trusted meets the workspace-trust dialog itself, and firstmate cannot answer it any more than it can for a crewmate.
This is rarely seen because a secondmate home is persistent and reused, so its trust decision is made once and survives, unlike a per-task worktree that is new every time.

Use the tool's exact skill form, or natural language only when no separate command is verified or the form remains uncertain.
A successful send or key return is not proof of submission; require the tool-specific postcondition.
Expand Down
55 changes: 55 additions & 0 deletions .agents/skills/harness-adapters/references/harness/agy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Antigravity CLI

Antigravity's `agy` TUI, verified end to end on 2026-09-10 with agy 1.2.0 on Linux through the Herdr backend.
Verified as a CREWMATE and SCOUT adapter only; `../../../../../bin/fm-spawn.sh` refuses a secondmate launch on it because `../../../../../docs/supervision-protocols/` carries no agy wake protocol.
`../../../../../docs/verification/agy.md` owns how every fact below was established and what is still unproven.

## Operating facts

| Fact | Value |
|---|---|
| Binary | Absolute `agy` from `PATH`, refused if absent; a Go-compiled single binary, so the live process name is exactly `agy` with `argv[0]=agy`. |
| Launch | `agy --prompt-interactive "<brief>" --model <id> --effort <level> --dangerously-skip-permissions`, with the resolved absolute binary; the brief auto-submits with no extra Enter. The spawn pre-registers the worktree in agy's trust store first, then waits for a busy turn (answering the folder-trust dialog if it renders anyway) before reporting success. |
| Busy state | No hook or plugin writer, so nothing is armed and no record is seeded; on Herdr the native `working` status classifies busy, and everywhere else the `agy-regex` rendered-tail fallback in `../../../../../bin/fm-busy-lib.sh` does. |
| Rendered tail | Busy status row carries `esc to cancel` on the left; the idle row shows `? for shortcuts` instead. The `Generating...` word beside the braille spinner is free-floating output and is not a signal. |
| Turn end | No turn-end hook or notification touch exists; completion arrives through the worker status protocol and, on Herdr, the native return to `idle`. |
| Exit | `/quit`, one Enter; the process exits. |
| Interrupt | Single `Escape`, which prints the Interrupted row and leaves an idle composer with no repollution, so no clear key follows. |
| Skill | No verified slash-skill form; use natural language. |
| Autonomy | `--dangerously-skip-permissions` auto-approves tool calls for the run. |
| Marker | None; a live TUI carries no `AGY_*` or `ANTIGRAVITY_*` variable. |
| Resume | `--continue` and `--conversation` exist but carry no verified pane-resume contract; use deterministic relaunch. |
| Model | `--model <id>` with the bare catalog id from `agy models` (for example `gemini-3.8-flash-high`); `bin/fm-spawn.sh` refuses a requested id a reachable listing omits. The listing is a remote fetch, so the probe runs stdin-detached under the shared hard bound and an unreachable or hung listing launches unvalidated with a notice. |
| Effort | `--effort low\|medium\|high`; `xhigh` and `max` stay in task metadata under the record-and-omit contract. |
| Composer | Borderless bare `>` row, which the shared classifier reads as `unknown` under the dead-shell rule, never `empty`; steering confirms delivery through native agent-state and the delivery footer instead, the cursor precedent. |

## Trust, and where the decision persists

Every task worktree is a path agy has never seen, so an unregistered launch stops on `Do you trust the contents of this project?` with the safe choice `Yes, I trust this folder` preselected, and an unanswered dialog sends the turn into agy's scratch directory instead of the worktree.
There is no launch flag that suppresses the dialog, but agy honours a `trustedWorkspaces` entry in the captain's own `~/.gemini/antigravity-cli/settings.json` written ahead of launch (verified live), so `../../../../../bin/fm-spawn.sh` pre-registers the worktree through `../../../../../bin/fm-agy-trust.sh` before launch, the claude shape: the helper refuses anything but a linked worktree of the spawning project, records both the logical pane path and its resolved form because agy compares the logical cwd, and preserves every other key in the store.
The post-launch readiness gate is the backstop: it answers a dialog that renders anyway with a single Enter, then requires a busy verdict (Herdr's native `working` status or the pinned `esc to cancel` row) before the spawn reports success, and on a path that was not pre-registered it never counts a busy verdict as ready until the dialog has been answered, because Herdr's native verdict can precede the dialog.
A pane whose brief cannot be confirmed to run in the worktree fails the spawn, records the failure in the task status, and closes the endpoint.
Never steer into a pane still showing the dialog; a spawn that reported success has already cleared it.

## Credential precondition

A verified agy worker ran under a signed-in Google account with no key export and no dialog.
The unauthenticated failure mode was not observed, so treat any auth prompt or refusal as a credential blocker under `../../../../../AGENTS.md` section 9, fix the environment, and retire the endpoint rather than typing into it.

## Detection

Detected by ancestry alone: `../../../../../bin/fm-harness.sh` matches the anchored process name `agy`, never `*agy*`.
No environment marker is promoted: `AGENT=1` observed on a live TUI is an inherited launcher value, not an agy identity, and agy does not clear an inherited `CLAUDECODE` - but a structural agy ancestor now outranks that retained marker, which `../../../../../bin/fm-harness.sh` decides without depending on the spawn's own launch-boundary marker clearing.
agy is deliberately absent from the session-lock name vocabulary in `../../../../../bin/fm-session-lock-lib.sh`, where muse, gemini, and rovo are also absent: a crewmate-only adapter must never own a home session lock.

## Worker busy state and turn end

`../../../../../bin/fm-spawn.sh` arms no busy generation for agy and writes no sidecar, exactly because no writer could ever clear a seeded record.
`fm_busy_agy_tail_busy` matches the pinned `esc to cancel` status row alone, hardcoded with no environment override, and `fm_busy_classify` reports `unknown agy-regex` rather than idle when it is absent, because a long turn can scroll the marker out of the captured tail.
Teardown removes nothing agy-specific because the spawn leaves nothing behind.

## Primary integration

Unsupported and unverified.
`../../../../../docs/supervision-protocols/` carries no agy protocol, no turn-end guard adapter exists for it, and this adapter verified only the crewmate-side launch, busy state, interrupt, and exit.
`references/common/primary-hooks.md`'s unsupported-boundary rule applies: never invent a wake protocol from a similar TUI.
Loading
Loading