Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
b822641
fix(spawn): isolate docker-compose project names per worktree
Jul 5, 2026
c893191
no-mistakes(test): waiting for background test run to complete
Jul 5, 2026
c16b512
no-mistakes(test): fix(tests): make herdr fake CLI counter race-safe …
Jul 5, 2026
45ca7af
no-mistakes(document): docs: document per-worktree docker-compose pro…
Jul 5, 2026
7ed4b27
no-mistakes(document): docs already fully synced; added missing docke…
Jul 5, 2026
3082a9c
no-mistakes(lint): Fix unused $out variable flagged by shellcheck in …
Jul 5, 2026
a7f33e6
feat(spawn): auto-compact claude crewmates around 200k tokens
Jul 10, 2026
f2e2098
no-mistakes(test): fix environment-fragile test failures (jq, git, ha…
Jul 10, 2026
91dea1b
feat(spawn): raise claude auto-compact window to 300000
Jul 11, 2026
4e67919
fix(teardown): recognize work fast-forwarded into local main as landed
Jul 11, 2026
11c67e5
test(teardown): drop stale git-2.38 skip gate for content-in-default …
Jul 11, 2026
94e4870
feat(dispatch): add model/effort tiers and mechanical quality guardrails
Jul 9, 2026
609fa34
no-mistakes(review): scope risk-tripwire brief scan, narrow bin path,…
Jul 9, 2026
eac54c8
no-mistakes(review): harden risk-tripwire scans and mechanically wire…
Jul 9, 2026
2a1e409
no-mistakes(review): make risk-tripwire grep portable, give tier-guar…
Jul 9, 2026
dde148f
no-mistakes(review): set exec bit on new tests, fix ultracode marker doc
Jul 10, 2026
7d711ef
no-mistakes(test): fix jq/git-version and test-env portability in fai…
Jul 10, 2026
751107b
no-mistakes(document): sync docs with new resource-tiering guardrail …
Jul 10, 2026
720e10b
no-mistakes(review): exclude herdr-lab brief block from risk-tripwire…
Jul 10, 2026
20b7e0d
no-mistakes(review): clean up orphan .ultracode state marker on teardown
Jul 10, 2026
977f4b5
no-mistakes(review): stop tiering guardrails passing silently when di…
Jul 10, 2026
68f29d4
no-mistakes(review): pass ultracode through dispatch, tighten tiering…
Jul 10, 2026
8229903
no-mistakes(test): skip handoff tests on incompatible tasks-axi; fix …
Jul 10, 2026
3a6ee4d
no-mistakes: apply CI fixes
Jul 10, 2026
6a830fb
fix(teardown): check both origin and local ref for landed content
Jul 11, 2026
9c5aa3d
feat: auto-sync live NAS deployments after a landed ship task
Jul 12, 2026
03400d6
no-mistakes(review): docs: document fm-nas-deploy-sync.sh script and …
Jul 12, 2026
7fac6bd
no-mistakes(review): Sandbox teardown tests' NAS deploy sync lookup file
Jul 12, 2026
6d2f048
no-mistakes(review): Aggregate pm2 cluster status and stub NAS sync i…
Jul 12, 2026
7ff4a11
no-mistakes(review): Bound NAS deploy sync git/fs calls with a timeout
Jul 12, 2026
b0ff754
no-mistakes(review): Guard NAS sync fetch race, document timeout knob…
Jul 12, 2026
8c775b2
no-mistakes(test): placeholder - awaiting background test run completion
Jul 12, 2026
12296a3
no-mistakes(document): Synced AGENTS.md and docs/architecture.md/cmux…
Jul 12, 2026
8a26c28
feat: surface failed critical systemd services at bootstrap
Jul 13, 2026
1e1f262
keep firstmate repo in sync with upstream template
Jul 14, 2026
2c789bc
clarify /updatefirstmate converges to the fork, not the upstream temp…
Jul 14, 2026
a534ed9
fix: reclaim leaked tmp roots in secondmate test suites
Jul 15, 2026
712fea5
no-mistakes(review): harden cleanup manifest naming and reclaim dead-…
Jul 15, 2026
0051359
no-mistakes(test): install afk-launch traps before lock; skip capabil…
Jul 15, 2026
02eae78
no-mistakes(review): Captain, harden teardown temp and deploy safety
Jul 15, 2026
59bc5cc
no-mistakes(review): Captain, fix randomized GOTMP test cleanup
Jul 15, 2026
f197034
no-mistakes(review): Harden cleanup safety guards, captain
Jul 15, 2026
ceebc7f
no-mistakes(review): Captain, validate ultracode dispatch config types
Jul 15, 2026
31271ea
no-mistakes(review): Captain, harden bootstrap and ultracode guards
Jul 15, 2026
82c6d8a
no-mistakes(review): Captain, harden risk and NAS guards
Jul 15, 2026
49b0c86
no-mistakes(review): Captain, harden bounded bootstrap and NAS sync
Jul 15, 2026
af4e536
no-mistakes(document): Synced docs for upstream-drift feature, fm-mer…
Jul 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
11 changes: 10 additions & 1 deletion .agents/skills/bootstrap-diagnostics/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name: bootstrap-diagnostics
description: >-
Agent-only handling playbook for session-start bootstrap diagnostics.
Use whenever the session-start digest's bootstrap section prints any diagnostic or capability line - MISSING, MISSING_MANUAL, BACKEND_INVALID, NEEDS_GH_AUTH, TANGLE, CREW_HARNESS_OVERRIDE, CREW_DISPATCH, FLEET_SYNC, SECONDMATE_SYNC, SECONDMATE_LIVENESS, TASKS_AXI, NUDGE_SECONDMATES, or FMX - or when a standalone bin/fm-bootstrap.sh run prints one.
Use whenever the session-start digest's bootstrap section prints any diagnostic or capability line - MISSING, MISSING_MANUAL, BACKEND_INVALID, NEEDS_GH_AUTH, TANGLE, CREW_HARNESS_OVERRIDE, CREW_DISPATCH, FLEET_SYNC, SECONDMATE_SYNC, SECONDMATE_LIVENESS, TASKS_AXI, NUDGE_SECONDMATES, SERVICE_FAILED, FMX, or UPSTREAM_DRIFT - or when a standalone bin/fm-bootstrap.sh run prints one.
A silent bootstrap section means all good and needs no skill load.
user-invocable: false
metadata:
Expand Down Expand Up @@ -47,3 +47,12 @@ The inline rules in `AGENTS.md` section 3 still bind: detect, then consent, then
A secondmate that was skipped, already current, or whose advance changed no instructions is not listed and must not be disturbed.
- `FMX: X mode on ...` / `FMX: X mode off ...` - bootstrap confirmed or removed the local X-mode poll artifacts (`docs/configuration.md` "X mode (.env)").
Only when a running watcher needs the cadence transition applied immediately, restart the home-scoped watcher through the emitted harness supervision protocol; bootstrap deliberately never restarts the watcher itself.
- `SERVICE_FAILED: <unit> - failed since <timestamp>` - a systemd unit named in the optional local `config/critical-services` file is in the failed state; a pure read-only detection (`systemctl is-failed`, no root), so a read-only session still surfaces it.
Report it to the captain in plain language; never restart the unit yourself - a unit that failed may be unsafe to restart without knowing why.
An absent or empty config file, a host without `systemctl`, or no failed unit all print nothing.
- `UPSTREAM_DRIFT: local main is <ahead> ahead / <behind> behind upstream/main, last reconciled <days>d ago (<date>)` - the always-on FYI variant: firstmate's OWN repo tracking how far it has drifted from its read-only upstream template (`kunchenguid/firstmate`, the `upstream` remote after the remote swap).
It prints every session; record it silently like any capability fact and take no action while the wording stays FYI.
It only reports - the network fetch that refreshes the ref runs in the locked fleet-sync sweep, and reconciling upstream is never a bootstrap side effect.
- `UPSTREAM_DRIFT: this repo's upstream sync needs attention - ...` - the escalated variant (local main more than ~30 commits behind `upstream/main`, or the merge-base older than 10 days).
Surface it to the captain in plain outcome language and, on their go-ahead, dispatch a deliberately-reviewed firstmate-repo reconciliation ship task - fetch `upstream`, merge it into local `main`, resolve conflicts, and land local-only (`AGENTS.md` section 1) - the same shape that reconciled the divergence before.
Never automate the merge; keeping the gap small also keeps the pipeline's opportunistic upstream PR's diff clean (`AGENTS.md` section 1).
7 changes: 7 additions & 0 deletions .agents/skills/harness-adapters/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,13 @@ Its broader dark-TRUECOLOR placeholder handling and dark-theme tradeoff are docu
That styled capture is internal to the boolean detector only.
`fm-peek` and every other human or LLM-facing capture path stays plain `tmux capture-pane` with no escape codes.

**Auto-compaction fact (verified 2026-07-09, Claude Code 2.1.206; shipped constant raised to 300000 2026-07-11).**
`bin/fm-spawn.sh` launches every claude crewmate and secondmate with `CLAUDE_CODE_AUTO_COMPACT_WINDOW=300000`, scoped the same way as `CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION=false` above, so these separately-launched processes auto-compact around 300k tokens the way the primary already does via its own `.claude/settings.local.json` (which they never inherit).
The var is read once at process startup and is capped at the model's real context window, so it can only lower the effective trigger, never raise it past the real ceiling: `min(300000, window)` is `300000` once `window` exceeds it, but a no-op (stays at `window`) below that.
This is not a universal guarantee for every possible future model choice - a differently-configured account/model capped at the plain ~200k window would see no change - but it is true for the window tier crew actually runs on today: `--model sonnet` on this account, the standard crewmate spawn, resolves to the ~1M-context beta, well above 300000.
Verified live in a tmux pane at the original 200000 value (the mechanism is unchanged, only the shipped constant moved to 300000): `claude --model sonnet` on this account resolves to a ~967k-token auto-compact window with no override (`/context` reported `Auto-compact window: 967k tokens`, i.e. the 1M-context beta, not the 200k a plain Sonnet window would imply); relaunched with `CLAUDE_CODE_AUTO_COMPACT_WINDOW=200000` set, `/context` reported `39.5k/200k tokens (20%)` and `Auto-compact window: 200k tokens` - the window pinned to the override as expected.
This is why the primary's own two-var form (`CLAUDE_CODE_AUTO_COMPACT_WINDOW=1000000` + `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE=20`) is not copied here: that pair assumes a 1M window, and would silently cap a smaller-window model/account combination to a far more aggressive trigger.

**Primary-session guard fact (verified 2026-07-04, Claude Code 2.1.201; preserved 2026-07-08, Claude Code 2.1.204).**
This is separate from the per-task crewmate turn-end hook above (that one just `touch`es a marker file in a task's own `.claude/settings.local.json`).
The firstmate PRIMARY's own `.claude/settings.json` registers `bin/fm-turnend-guard.sh` as a Stop hook, and exiting with status 2 plus stderr reliably forces the model to continue.
Expand Down
3 changes: 3 additions & 0 deletions .agents/skills/updatefirstmate/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ It never forces, never creates a merge commit, never stashes, and advances a tar
A tracked-files fast-forward leaves the gitignored operational dirs (data/, state/, config/, projects/, .no-mistakes/) untouched, so a secondmate's in-flight work is never disrupted.
This touches only the firstmate repo and its own worktrees, never anything under `projects/`.

Post-swap, this pull follows `origin`, which is the captain's fork, so `/updatefirstmate` converges the whole fleet onto that fork and does nothing on the primary checkout, which is itself the source every fork tracks.
It deliberately never reaches for the read-only `upstream` template: folding template improvements into local `main` is a separate, reviewed reconciliation ship task, the one the `UPSTREAM_DRIFT:` bootstrap diagnostic surfaces, and it never rides in on a self-update.

## What it does

1. **Run the updater:**
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ config/backend
config/x-mode.env
config/cmux-socket-password
config/wedge-alarm
config/critical-services
21 changes: 20 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ Shared tracked material is `AGENTS.md`, `README.md`, `CONTRIBUTING.md`, `.tasks.
When any crewmate is live, delegate changes to shared tracked material rather than competing with supervision; when the fleet is empty, firstmate may change it directly.
This repo is a shared template, while `.env`, `data/`, `state/`, `config/`, `projects/`, and `.no-mistakes/` are captain-private and gitignored.
Ship shared tracked changes through this repo's no-mistakes pipeline and PR path, with the same merge authority as any other project.
This repo's own upstream (`kunchenguid/firstmate`, the `upstream` remote after the remote swap) is read-only to this fleet with no merge rights, ever, so firstmate-repo ship tasks land local-only: branch, commit, firstmate reviews the diff, the captain approves, and firstmate fast-forwards local `main`.
`bin/fm-merge-local.sh` then also best-effort pushes that fast-forwarded `main` to `origin` (the captain's fork) when a remote is present, so the fork never silently drifts behind local `main`; a push failure is reported but never fails the merge, and a local-only project with no remote at all is skipped silently.
The pipeline still auto-opens a PR against that upstream, but it is a non-blocking, purely opportunistic contribution back - never a merge gate here and never waited on - and its diff stays clean only while the `UPSTREAM_DRIFT:` gap (section 3) is small, since a large gap makes the PR carry a lot of unrelated local-only history.
Never add an agent name as a commit co-author.

## 2. Layout and state
Expand Down Expand Up @@ -85,6 +88,10 @@ Routing precedence is an explicit per-task captain override, then the best-fit c
The generic effort fallback and its precedence are owned by `harness-adapters`: explicit captain and standing configured effort win; otherwise use low for well-understood explicit work, xhigh for ambiguous investigation or design, intermediate levels proportionally, and never max without explicit captain preference.
Do not add model-specific versions of that policy.

A profile's `use.ultracode` marks a task that needs a genuinely independent second pass on its finished diff before PR-ready, launched as its own separately dispatched task, never a sub-task the flagged crewmate spawns itself; run `bin/fm-ultracode-guard.sh flag <id> <ultracode_role>` right after spawn and `check <id>` before PR-ready (section 7's Validate).
Run `bin/fm-risk-tripwire.sh <id>` after resolving the profile and again once the task has a brief or diff; a hit floors the model/effort to `opus`/`xhigh` with ultracode `independent-review` regardless of the matched rule, and also run `bin/fm-ultracode-guard.sh flag <id> independent-review` so the requirement is tracked mechanically even when the matched rule did not set ultracode; a hit discovered only at Validate time still floors the task in place and is never silently downgraded afterward.
The unverified-adapter discipline also covers models: verify a non-default `model` end-to-end on a trivial supervised task, including any sub-agent path its harness exposes, before a dispatch rule may name it, and never copy an unverified model into a live `config/crew-dispatch.json`.

`secondmate-provisioning` owns secondmate harness pins and config inheritance, while `harness-adapters` owns the harness consequences.
Dispatch only on a backend that `fm-spawn` validates as spawn-capable.
A missing dependency, authentication failure, unsupported backend, or version refusal is a blocker; never silently retry on another backend.
Expand Down Expand Up @@ -206,6 +213,15 @@ Running, fixing, or CI states remain working; parked approval or fix-review stat
A worker hand-editing, committing, aborting, or restarting during an active validation run duplicates pipeline ownership; steer it back to the gate response flow.
The worker reports the PR when CI first becomes green rather than waiting for merge monitoring to finish.

**Escalation triggers (mechanical, never rest on self-report alone).**
For a task assigned the trivial tier (Haiku/low), run `bin/fm-tier-guard.sh <id>` during Validate, or whenever a heartbeat review touches it, to check whether its diff or elapsed time has outgrown that tier's envelope; any tier also escalates once its diff crosses the script's general heavy-scale ceiling.
A report escalates the task to at least Sonnet/high in place, without losing its branch or context, mirroring `bin/fm-promote.sh`'s in-place promotion.
A crewmate's own report - it cannot find root cause, a "confirmed" fix touches a shared path, or it raised a tradeoff buried in seemingly mechanical work - is a second, non-mechanical trigger with the same effect.
Either way, escalate the model/effort in place and never silently de-escalate for the rest of that task's life.

**Ultracode confirmation.**
Before advancing an ultracode-flagged task to PR-ready, run `bin/fm-ultracode-guard.sh check <id>`; it refuses until a genuinely separate task - dispatched independently, never a sub-task the flagged crewmate spawned itself - has reviewed the finished diff and its findings were addressed, recorded with `bin/fm-ultracode-guard.sh reviewed <id> <reviewer-task-id>`.

### PR ready, landing, and teardown

For a ready PR, use `bin/fm-pr-check.sh` to record the PR and authoritative head and to arm merge monitoring.
Expand All @@ -215,6 +231,7 @@ A captain instruction to merge is explicit authority; `yolo` is the only standin
Tear down a ship task only after landing is confirmed.
A teardown refusal for uncommitted or unlanded work is a stop-and-investigate result, never an obstacle to bypass.
Never force teardown without explicit discard authority.
Any non-scout, non-secondmate teardown - PR-based or local-only - also best-effort syncs and restarts that project's live NAS deployment, if one is recorded in `data/nas-deployments.md`, through `bin/fm-nas-deploy-sync.sh` (section 2); a project with no recorded deployment is a silent no-op.
After successful teardown, record completion, retain only the configured recent Done history, and re-evaluate queued work whose blockers and time gates have cleared.

A secondmate is persistent and an empty queue is healthy.
Expand Down Expand Up @@ -348,12 +365,14 @@ Firstmate's shared instruction surface reaches running homes only after it lands
Only `AGENTS.md`, `bin/`, and `.agents/skills/` are loaded by a running firstmate; public `skills/` is an installer-facing surface.
When the captain invokes `/updatefirstmate` or asks to update firstmate, load the `/updatefirstmate` skill.
It performs guarded fast-forward updates of firstmate and registered secondmate homes, refreshes instructions, and never touches anything under `projects/`.
Post-swap, `origin` is the captain's fork, so `/updatefirstmate` only ever converges the fleet onto that fork and is a no-op on the primary checkout, which is itself the fleet's source of truth.
It never pulls the read-only `upstream` template; folding upstream-template improvements into local `main` is the separate reviewed reconciliation task the `UPSTREAM_DRIFT:` bootstrap line surfaces (section 3), never a self-update.

## 13. 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 section prints any diagnostic or capability line (`MISSING:`, `MISSING_MANUAL:`, `BACKEND_INVALID:`, `NEEDS_GH_AUTH`, `TANGLE:`, `CREW_HARNESS_OVERRIDE:`, `CREW_DISPATCH:`, `FLEET_SYNC:`, `SECONDMATE_SYNC:`, `SECONDMATE_LIVENESS:`, `TASKS_AXI:`, `NUDGE_SECONDMATES:`, or `FMX:`); silence needs no load.
- `bootstrap-diagnostics` - load whenever the session-start digest's bootstrap section prints any diagnostic or capability line (`MISSING:`, `MISSING_MANUAL:`, `BACKEND_INVALID:`, `NEEDS_GH_AUTH`, `TANGLE:`, `CREW_HARNESS_OVERRIDE:`, `CREW_DISPATCH:`, `FLEET_SYNC:`, `SECONDMATE_SYNC:`, `SECONDMATE_LIVENESS:`, `TASKS_AXI:`, `NUDGE_SECONDMATES:`, `FMX:`, `SERVICE_FAILED:`, or `UPSTREAM_DRIFT:`); silence needs no load.
- `diagnostic-reasoning` - load before scoping a reported bug and before acting on a diagnostic report.
- `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.
Expand Down
2 changes: 2 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ Dependency bots are exempt so their automation keeps working, but regular contri

See the [no-mistakes quick start](https://kunchenguid.github.io/no-mistakes/start-here/quick-start/) for the full first-run walkthrough.

Note: a firstmate maintainer's own working copy uses the inverted remote layout - there `origin` is the maintainer's fork and `upstream` is this parent repo - so if you are ever reading such a copy's git config rather than your own fresh clone, expect `origin` and `upstream` swapped from the step 1 layout above.

## Repo conventions

- This repo is a template for running a firstmate orchestrator agent.
Expand Down
11 changes: 9 additions & 2 deletions bin/backends/cmux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -398,8 +398,15 @@ fm_backend_cmux_parse_target() { # <target>
# (fm_backend_zellij_pane_exists) rather than the design sketch's original
# read-screen-based suggestion.
fm_backend_cmux_surface_exists() { # <workspace_id> <surface_id>
local wsid=$1 sfid=$2
fm_backend_cmux_cli list-panes --workspace "$wsid" --json --id-format uuids 2>/dev/null \
local wsid=$1 sfid=$2 out
# Capture the list-panes call and gate on its OWN exit/output before piping to
# jq: an absent target makes list-panes fail with no output, and `jq -e` on
# empty input exits 0 on jq 1.6 (only 1.7+ reports the no-result exit 4), so
# relying on the pipe's trailing jq status alone would false-positive the
# surface as present on older jq. A failed or empty list-panes means no surface.
out=$(fm_backend_cmux_cli list-panes --workspace "$wsid" --json --id-format uuids 2>/dev/null) || return 1
[ -n "$out" ] || return 1
printf '%s' "$out" \
| jq -e --arg s "$sfid" '[.panes[]? | select(.surface_ids // [] | index($s))] | length > 0' >/dev/null 2>&1
}

Expand Down
10 changes: 9 additions & 1 deletion bin/fm-afk-launch.sh
Original file line number Diff line number Diff line change
Expand Up @@ -603,10 +603,18 @@ fm_afk_launch_stop() {

fm_afk_launch_main() {
local result
fm_afk_launch_lock_acquire || return 1
# Traps go in BEFORE the lock is taken: a TERM/INT landing inside
# fm_afk_launch_lock_acquire (after mkdir, during the pid-identity write)
# would otherwise kill the launcher with the just-created lock left behind.
# fm_afk_launch_lock_release is pid-guarded, so running it without the lock
# (or while another process owns it) is a safe no-op.
trap fm_afk_launch_lock_release EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
if ! fm_afk_launch_lock_acquire; then
trap - EXIT INT TERM
return 1
fi
case "${1:-start}" in
start) fm_afk_launch_start ;;
start-native) fm_afk_launch_start_native ;;
Expand Down
Loading
Loading