Skip to content
6 changes: 6 additions & 0 deletions .agents/skills/project-management/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,18 @@ Choose that posture when adding or creating the project:
- `direct-PR` pushes and opens a PR without the no-mistakes pipeline.
- `local-only` has no required remote or PR and lands only through the approved local fast-forward path.
- `no-mistakes-prod-only` is a conditional policy rather than one flat mode: genuinely internal-only tooling, automation, contributor or operator process, and release or submission work ships `direct-PR`, while product-facing, mixed, and uncertain work ships `no-mistakes`.
- `+hardened` is the highest-rigor choice on this list, adding the quality gate that runs before validation; it rides alongside one of the flat modes above rather than replacing it, so a hardened project is registered as `[no-mistakes +hardened]`, `[direct-PR +hardened]`, or `[local-only +hardened]`.

`no-mistakes-prod-only` is the default for a newly added or created remote-backed project when the captain specifies nothing, and a project with no remote defaults to `local-only`.
State that resolved default while confirming the source, local name, and posture instead of asking the captain to choose from scratch, and record a flat mode instead whenever they ask for one.
Existing registry entries keep the meaning they already have and are never migrated or reinterpreted, so a legacy entry with no bracket stays `no-mistakes`.
Registering a conditional policy is a one-time choice and never requires classifying any change; the per-task surface classification happens at each task's intake, and internal-only is never inferred from file location or project name.

`+hardened` is off for every project unless the captain asks for it, so a project registered without it is `standard`.
Refuse `+hardened` together with `no-mistakes-prod-only` and tell the captain to pick a flat delivery mode instead.
A conditional policy decides per task, so a quality standard that covers only part of a project is a posture nobody can state in one sentence.
`AGENTS.md` section 7 owns how each task's quality resolves at intake, and `bin/fm-project-mode.sh --quality` owns how the registered token is read.

The optional `+yolo` posture changes routine approval authority but does not change the delivery mode.
Default it off for every project and every posture, and enable it only on the captain's explicit instruction.
`AGENTS.md` section 7 owns the complete authority boundary and exceptions when it is on.
Expand Down
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ Resolve every ship task's concrete delivery mode and yolo posture at intake, and
A current explicit captain instruction wins; otherwise the project's registry entry is the captain's standing posture, and dropping below its rigor needs a reason you can state.
On a `no-mistakes-prod-only` project, classify the task's surface: internal-only tooling, automation, contributor or operator process, and release or submission work ships `direct-PR`, while product-facing, mixed, and uncertain work ships `no-mistakes`; never infer internal-only from file location or project name.
An unregistered project or absent registry resolves to `no-mistakes` with yolo off, and the registration gap goes to the captain.
A task's quality posture resolves at intake with the same precedence, a current explicit captain instruction first, then the project's registered posture, then `standard`, with the one-line reason for any deviation recorded in the same backlog note.
Record the resulting mode, yolo, and the one-line reason for any deviation in the backlog item note.

Treat file or subsystem overlap as a risk signal rather than an automatic reason to wait, and dispatch isolated work immediately with no concurrency cap when each change can be independently implemented and validated and the selected delivery path can reconcile ordinary rebases or conflicts.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Launching a supported harness inside it instantiates your first mate - and makes
- **A visible crew** - every crewmate works in its own tmux window, experimental herdr/zellij tab, cmux workspace, or Orca terminal you can watch or type into; the first mate reconciles.
- **Disposable worktrees** - each task runs in a clean [treehouse](https://github.com/kunchenguid/treehouse) git worktree, or an Orca-managed worktree when `backend=orca`, so parallel work on one repo never collides.
- **Two task shapes** - ship tasks deliver authorized changes; scout tasks leave standalone investigation reports when the intake contract warrants separate research.
- **Explicit project modes** - each project ships via `no-mistakes`, `direct-PR`, or `local-only`, with an optional `+yolo` autonomy flag.
- **Explicit project modes** - each project ships via `no-mistakes`, `direct-PR`, `local-only`, or one of those plus `+hardened` for the highest-rigor quality gate, with an optional `+yolo` autonomy flag.
- **Optional secondmates** - opt in to persistent second mates that run from isolated firstmate homes with their own `FM_HOME`, state, projects, and session lock, either locally or as a whole home on an SSH-reachable host, with guarded updates and recovery that never turns an unavailable remote route into a local replacement.
- **Event-driven, zero-token supervision** - a bash watcher sleeps on the fleet and wakes the first mate only when something needs you; verified primary harnesses also get a turn-end backstop that blocks or follows up on a blind stop when work is under way and supervision is not live.
- **Optional Relay** - opt in with one local `.env` pairing token so firstmate can answer your public mentions on X and Discord alike, act on normal reversible mention requests through the same lifecycle as chat requests, acknowledge spawned work, and post up to three public-safe completion follow-ups within seven days for genuine milestones and the final outcome without changing non-Relay behavior; a final reply promised in a thread becomes durable state that is reconciled from disk, so a restart or a compacted conversation cannot lose it; dry-run preview records would-be replies and dismissals locally before go-live.
Expand Down
84 changes: 74 additions & 10 deletions bin/fm-brief.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# description, acceptance criteria, and context, and may adjust other sections
# when the task genuinely deviates (e.g. working an existing external PR instead
# of shipping a new one).
# Usage: fm-brief.sh <task-id> <repo-name> --mode <no-mistakes|direct-PR|local-only> [--herdr-lab]
# Usage: fm-brief.sh <task-id> <repo-name> --mode <no-mistakes|direct-PR|local-only> [--quality <standard|hardened>] [--herdr-lab]
# fm-brief.sh <task-id> <repo-name> --scout [--herdr-lab]
# fm-brief.sh <task-id> <repo-name> --dreamer [--herdr-lab]
# fm-brief.sh <task-id> --secondmate {<project>...|--no-projects}
Expand Down Expand Up @@ -48,9 +48,22 @@
# "Delivery contract: mode=<mode>" line. bin/fm-spawn.sh reads that line and refuses
# to launch a ship task whose explicit --mode disagrees, so an adjusted brief and the
# recorded task metadata cannot drift apart.
# --quality is the task's quality posture, resolved at intake the same way (AGENTS.md
# section 7) from the project's registered "+hardened" annotation, and it defaults to
# standard so every existing call site scaffolds exactly as before:
# standard the ordinary path: implement, then the mode's definition of done
# hardened a clean loop then a harden loop, both against the base commit fixed at
# spawn, both before validation, driven by bin/fm-quality.sh
# A hardened brief carries the sibling machine-readable line
# "Quality contract: quality=hardened" plus one short quality-gate section; a standard
# brief carries neither, so an absent line means standard and a standard brief stays
# byte-identical to what this scaffold produced before --quality existed. bin/fm-spawn.sh
# checks that line against its own --quality exactly as it checks the mode line.
# --quality is refused on scout, dreamer and secondmate scaffolds, for the same reason
# --mode is.
# Ship briefs begin with a worktree-isolation assertion before the branch step.
# --mode is refused on scout and secondmate scaffolds: a scout's deliverable is a
# report rather than a merge, and a charter is not a delivery contract.
# --mode is refused on scout, dreamer and secondmate scaffolds: a scout or dreamer
# delivers a report rather than a merge, and a charter is not a delivery contract.
# There is no --yolo flag here. The worker never owns approval decisions, so yolo is
# a spawn-time and firstmate-side input only (AGENTS.md section 7).
# Every scaffold's status protocol distinguishes the configured
Expand Down Expand Up @@ -115,6 +128,8 @@ HERDR_LAB=0
NO_PROJECTS=0
MODE=
MODE_SET=0
QUALITY=standard
QUALITY_SET=0
POS=()
want_value=
for a in "$@"; do
Expand All @@ -124,6 +139,7 @@ for a in "$@"; do
esac
case "$want_value" in
mode) MODE=$a; MODE_SET=1 ;;
quality) QUALITY=$a; QUALITY_SET=1 ;;
*) echo "error: internal parser state for --$want_value" >&2; exit 1 ;;
esac
want_value=
Expand All @@ -137,6 +153,8 @@ for a in "$@"; do
--no-projects) NO_PROJECTS=1 ;;
--mode) want_value=mode ;;
--mode=*) MODE=${a#--mode=}; MODE_SET=1 ;;
--quality) want_value=quality ;;
--quality=*) QUALITY=${a#--quality=}; QUALITY_SET=1 ;;
# yolo never reaches the worker: it is firstmate's approval authority, not a
# brief input. Refuse it loudly so it is never silently dropped here and then
# believed to have been recorded.
Expand Down Expand Up @@ -164,6 +182,19 @@ elif [ "$MODE_SET" -eq 1 ]; then
echo "error: --mode applies only to ship briefs; a scout or dreamer delivers a report and a secondmate charter is not a delivery contract" >&2
exit 1
fi

# Quality posture. Unlike --mode it has a safe default, so it is optional and only
# its VALUE is closed-set validated; a typo must never quietly scaffold a standard
# brief for a task firstmate resolved as hardened.
if [ "$KIND" = ship ]; then
case "$QUALITY" in
standard|hardened) ;;
*) echo "error: --quality must be one of standard, hardened (got '$QUALITY')" >&2; exit 1 ;;
esac
elif [ "$QUALITY_SET" -eq 1 ]; then
echo "error: --quality applies only to ship briefs; a scout or dreamer delivers a report and a secondmate charter is not a delivery contract" >&2
exit 1
fi
[ "${#POS[@]}" -ge 1 ] || { echo "error: task id is required" >&2; exit 1; }
ID=${POS[0]}

Expand Down Expand Up @@ -479,17 +510,40 @@ echo "scaffolded: $BRIEF (dreamer; replace {TASK})"
exit 0
fi

# The DOD's machine-readable contract header, owned in one place so the three
# mode bodies below cannot drift apart. A standard task emits the delivery line
# alone, exactly as this scaffold did before --quality existed; a hardened task
# adds the sibling quality line that bin/fm-spawn.sh checks against its own
# explicit --quality before launching, the same way it checks the delivery line.
CONTRACT_LINES="Delivery contract: mode=$MODE"
if [ "$QUALITY" = hardened ]; then
CONTRACT_LINES="$CONTRACT_LINES
Quality contract: quality=hardened"
fi

# The hardened task's extra instructions. Deliberately short: bin/fm-quality.sh
# and its --help own the loop's mechanics, and a second copy here would drift.
IFS= read -r -d '' QUALITY_SECTION <<EOF || true
# Quality gate
This task ships **hardened**, so an extra quality pass runs before the definition of done below, and \`$FM_ROOT/bin/fm-quality.sh\` drives it.

1. The base commit is fixed when this task starts and is recorded in the task's durable record as \`base_sha=\`. Measure every phase as a diff against THAT commit, never against \`HEAD~1\`: each round of the loop commits, so \`HEAD~1\` would narrow the gate to the last round alone while still reporting success.
2. Run the clean loop first, then the harden loop, and finish both before you start on that definition of done - on a no-mistakes task, that means before the pipeline starts.
3. Do not hand-roll either loop. The rounds, the bounds, the receipt, and the outcome vocabulary belong to that script; \`$FM_ROOT/bin/fm-quality.sh --help\` is authoritative for its mechanics.
4. Only a pass continues. If a surviving mutant exposes a real product defect rather than a missing test, report it (rule 6) instead of writing a test around it - a test that passes against a defect is exactly how a quality gate gets gamed.
EOF
QUALITY_SECTION=${QUALITY_SECTION%$'\n'}

# Ship task: shape Setup / Rule 1 / Definition of done by this task's explicit
# delivery mode, validated above. The generated DOD opens with the fixed
# "Delivery contract: mode=<mode>" line that bin/fm-spawn.sh checks against its own
# explicit --mode before launching.
# delivery mode, validated above. Each body opens with $CONTRACT_LINES, built once
# just above.
case "$MODE" in
direct-PR)
SETUP2=""
RULE1='1. Never push to the default branch (push only your `fm/'"$ID"'` branch). Never merge a PR.'
IFS= read -r -d '' DOD <<EOF || true
# Definition of done
Delivery contract: mode=direct-PR
$CONTRACT_LINES
This task ships **direct-PR**: you raise the PR yourself, without the no-mistakes pipeline.
The task is complete only when committed on your branch.
When it is implemented and committed, push your branch and open a PR with \`gh-axi\`, then append \`done: PR {url}\` to the status file and stop.
Expand All @@ -501,7 +555,7 @@ EOF
RULE1="1. Never push to any remote and never open a PR. Work only on your \`fm/$ID\` branch; firstmate handles the merge into local \`main\`."
IFS= read -r -d '' DOD <<EOF || true
# Definition of done
Delivery contract: mode=local-only
$CONTRACT_LINES
This task ships **local-only**: no remote, no PR, no pipeline.
The task is complete only when committed on your branch \`fm/$ID\`. Do NOT push, do NOT open a PR, do NOT merge.
Keep your branch a clean fast-forward onto the current default branch - if \`main\` has advanced, rebase onto it so the eventual merge stays a fast-forward.
Expand All @@ -515,7 +569,7 @@ EOF
RULE1='1. Never push to the default branch. Never merge a PR.'
IFS= read -r -d '' DOD <<EOF || true
# Definition of done
Delivery contract: mode=no-mistakes
$CONTRACT_LINES
This mode is complete only when the no-mistakes pipeline has shipped a PR whose checks are green.
When implementation is committed on your branch, start the no-mistakes pipeline yourself immediately.
Append \`working: starting no-mistakes validation\` to the status file, then run the \`no-mistakes\` CLI on your \`PATH\`: \`no-mistakes axi run --intent "<...>"\` to start, and \`no-mistakes axi respond\` for each gate.
Expand Down Expand Up @@ -544,6 +598,14 @@ esac
# briefs stay byte-identical to the historical Bash 5 output.
DOD=${DOD%$'\n'}

# A standard task's brief body is unchanged by --quality existing: nothing is
# prepended, so it stays byte-identical to the pre-quality scaffold.
if [ "$QUALITY" = hardened ]; then
DOD="$QUALITY_SECTION

$DOD"
fi

cat > "$BRIEF" <<EOF
You are a crewmate: an autonomous worker agent managed by firstmate. Work on your own; do not wait for a human.

Expand Down Expand Up @@ -598,4 +660,6 @@ Keep it proportionate: skip \`AGENTS.md\` edits for trivial tasks that produced

$DOD
EOF
echo "scaffolded: $BRIEF (ship, mode=$MODE; replace {TASK})"
QUALITY_NOTE=
[ "$QUALITY" = standard ] || QUALITY_NOTE=", quality=$QUALITY"
echo "scaffolded: $BRIEF (ship, mode=$MODE$QUALITY_NOTE; replace {TASK})"
Loading
Loading