Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ Preserve durable structured identifiers, dependencies, and completion artifact l

## 11. Crewmate briefs

`bin/fm-brief.sh` and its help own scaffold syntax, generated variants, status protocol, delivery-mode definitions of done, and exact safety mechanics.
`bin/fm-brief.sh` and its help own scaffold syntax and generated variants; `bin/fm-status-lib.sh` owns the shared generated status-protocol wording; `bin/fm-dod-lib.sh` owns delivery-mode definitions of done; and the relevant script headers own exact safety mechanics.
Use its scaffold as the contract, then fill `## Captain's intent` (`{TASK}`) with the captain's own ask plus the context needed to read it, including the substance of any report, decision, or PR the ask refers to, and fill `## Firstmate spec` (`{FIRSTMATE_SPEC}`) with Firstmate's build instructions.
`bin/fm-dod-lib.sh` owns what a no-mistakes worker may pass as `--intent` and its rule that the string must be self-sufficient.
Keep additions task-specific rather than repeating lifecycle instructions, and alter generated sections only when the task genuinely differs from the standard shape.
Expand Down
33 changes: 24 additions & 9 deletions bin/fm-brief.sh
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,12 @@ esac
. "$SCRIPT_DIR/fm-classify-lib.sh"
# shellcheck source=bin/fm-dod-lib.sh
. "$SCRIPT_DIR/fm-dod-lib.sh"
# shellcheck source=bin/fm-status-lib.sh
. "$SCRIPT_DIR/fm-status-lib.sh"
PAUSED_VERB=${FM_CLASSIFY_PAUSED_VERB:-$FM_CLASSIFY_PAUSED_VERB_DEFAULT}
SILENT_OPERATIONAL_INPUT_RULE=$FM_OPERATIONAL_SILENT_REPLY_RULE
STATUS_WORKING_RULE=
STATUS_NO_PROGRESS_RULE=

resolve_directory_input() {
local name=$1 path=$2 resolved
Expand Down Expand Up @@ -186,6 +190,14 @@ elif [ "$MERGE_AUTHORITY_SET" -eq 1 ]; then
echo "error: --merge-authority applies only to ship briefs; secondmate charters resolve each project from data/projects.md" >&2
exit 1
fi
if [ "$KIND" = scout ]; then
STATUS_WORKING_RULE=$(fm_status_working_rule scout)
elif [ "$KIND" = ship ]; then
STATUS_WORKING_RULE=$(fm_status_working_rule "$MODE")
fi
if [ "$KIND" != secondmate ]; then
STATUS_NO_PROGRESS_RULE=$(fm_status_no_progress_rule)
fi
ID=${POS[0]}

if [ "$KIND" = secondmate ] && [ "$HERDR_LAB" -eq 1 ]; then
Expand Down Expand Up @@ -215,6 +227,8 @@ shell_quote() {

STATUS_FILE=$(shell_quote "$STATE/$ID.status")
INBOX_DIR=$(shell_quote "$STATE/$ID.inbox")
STATUS_WAKE_REMINDER=$(fm_status_wake_reminder)
STATUS_NO_RESOLVED_ECHO_RULE=$(fm_status_no_resolved_echo_rule)

# The receive-and-ack half of the steering-inbox contract, included in every
# scaffold kind. The record format, doorbell line, and re-ring ladder are
Expand All @@ -226,6 +240,7 @@ IFS= read -r -d '' INBOX_SECTION <<EOF || true
Firstmate steers you through durable message files in $INBOX_DIR.
When a terminal message says an instruction is waiting there - and at any natural checkpoint when you are unsure - list $INBOX_DIR/*.msg, read and act on each message in numeric order, then acknowledge each handled message by moving it: \`mv $INBOX_DIR/NNN.msg $INBOX_DIR/handled/\`.
The move IS the acknowledgement: without it firstmate rings again and eventually treats you as stuck. An empty or absent inbox needs no action.
$STATUS_NO_RESOLVED_ECHO_RULE
EOF
INBOX_SECTION=${INBOX_SECTION%$'\n'}

Expand Down Expand Up @@ -342,6 +357,7 @@ Report only true captain-relevant outcomes or a declared external wait by append
\`echo "{state}: {one short line}" >> $STATUS_FILE\`
States: working, needs-decision, blocked, $PAUSED_VERB, done, failed.
$SILENT_OPERATIONAL_INPUT_RULE
$STATUS_WAKE_REMINDER
Use \`$PAUSED_VERB: {why}\` (distinct from \`blocked:\`) only when your domain is deliberately idling on a known external wait you expect to clear on its own; use \`blocked:\` when you are stuck and need firstmate to act.
Use this only for material phase changes, a captain decision, a real blocker, a failure, work ready for review, or work you landed.
Work you landed includes a merge you performed yourself under standing merge authority and one the captain merged on the forge: under that authority nothing is ever \"ready for review\", so a landed merge that goes unreported reaches the captain as silence.
Expand Down Expand Up @@ -454,9 +470,9 @@ The report is the only thing that survives, so anything worth keeping must be in
\`echo "{state}: {one short line}" >> $STATUS_FILE\`
States: working, needs-decision, blocked, $PAUSED_VERB, done, failed.
$SILENT_OPERATIONAL_INPUT_RULE
Each append wakes firstmate, so report sparingly: only phase changes a supervisor
would act on and the needs-decision/blocked/paused/done/failed states. No step-by-step
FYI progress lines; firstmate reads your pane for that.
$STATUS_WAKE_REMINDER
$STATUS_WORKING_RULE
$STATUS_NO_PROGRESS_RULE
Whenever you mention a PR anywhere - a status line, your terminal, a summary - write its full
https:// URL exactly as the forge printed it, never a bare number such as "PR 108"; firstmate
copies that URL from your line rather than assembling one.
Expand All @@ -480,7 +496,7 @@ Write your findings to \`$DATA/$ID/report.md\`.
The report must stand alone: what you did, what you found, the evidence (commands run, output, file:line references), and what you recommend.
If your deliverable is a visual artifact the captain will review and iterate on, you may host the Lavish review loop yourself (poll, revise, re-serve, staying alive) instead of handing it back to firstmate.
Before reporting done, read and follow \`$FM_ROOT/.agents/skills/captain-hold-lifecycle/SKILL.md\` and pass its shared completion gate for the report and any visual review.
When the report is complete, append \`done: {one-line conclusion}\` to the status file and stop.
Only after the report exists and is complete, append \`done: {one-line conclusion}\` to the status file and stop.
If your findings reveal work that should ship (e.g. you reproduced a bug and the fix is clear), say so in the report; firstmate may promote this task in place, and you would then receive mode-specific ship instructions as a follow-up message.
EOF
echo "scaffolded: $BRIEF (scout; replace {TASK} and {FIRSTMATE_SPEC})"
Expand Down Expand Up @@ -538,14 +554,13 @@ $RULE1
\`echo "{state}: {one short line}" >> $STATUS_FILE\`
States: working, needs-decision, blocked, $PAUSED_VERB, done, failed.
$SILENT_OPERATIONAL_INPUT_RULE
Each append wakes firstmate, so report sparingly: only phase changes a supervisor
would act on (setup done, bug reproduced, fix implemented, validation passed) and the
needs-decision/blocked/paused/done/failed states. No step-by-step FYI progress lines;
firstmate reads your pane for that.
$STATUS_WAKE_REMINDER
$STATUS_WORKING_RULE
$STATUS_NO_PROGRESS_RULE
Whenever you mention a PR anywhere - a status line, your terminal, a summary - write its full
https:// URL exactly as the forge printed it, never a bare number such as "PR 108"; firstmate
copies that URL from your line rather than assembling one.
A mid-task \`working:\` line (including setup complete) is nonterminal: do not end the
A mid-task \`working:\` line is nonterminal: do not end the
turn after it; continue the same stage until a defined \`done:\` gate under Definition of done.
Use \`$PAUSED_VERB: {why}\` - distinct from \`blocked:\` - ONLY when you are deliberately idling on a
known external wait you expect to clear on its own (an upstream release, a rate-limit reset,
Expand Down
4 changes: 2 additions & 2 deletions bin/fm-dod-lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,8 @@ EOF
# Definition of done
Delivery contract: mode=no-mistakes
The task is complete only when committed on your branch.
When you believe it is complete, append \`done: {summary}\` to the status file and stop.
Firstmate will then instruct you to run /no-mistakes to validate and ship a PR.
After committing the implementation, append \`working: implementation committed and validation started\` only if that phase change has not already been reported, then run /no-mistakes to validate and ship a PR.
A local commit, local validation pass, or pipeline start is never a \`done:\` event.

You drive no-mistakes by responding to its gates, not by implementing fixes.
Follow the guidance no-mistakes itself provides for the mechanics: it loads when you invoke /no-mistakes, and \`no-mistakes axi run --help\` plus the \`help\` lines in each \`axi\` response are authoritative and version-matched to the installed binary.
Expand Down
12 changes: 11 additions & 1 deletion bin/fm-promote.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ DATA="${FM_DATA_OVERRIDE:-$FM_HOME/data}"

# shellcheck source=bin/fm-dod-lib.sh
. "$SCRIPT_DIR/fm-dod-lib.sh"
# shellcheck source=bin/fm-status-lib.sh
. "$SCRIPT_DIR/fm-status-lib.sh"
# shellcheck source=bin/fm-pr-lib.sh
. "$SCRIPT_DIR/fm-pr-lib.sh"
# shellcheck source=bin/fm-wake-lib.sh
Expand Down Expand Up @@ -194,6 +196,10 @@ PROMOTION_ASK_USER_BLOCK=
if [ "$MODE" = no-mistakes ]; then
PROMOTION_ASK_USER_BLOCK=$(fm_ask_user_escalation_block "$DATA" "$ID")
fi
PROMOTION_STATUS_WAKE_REMINDER=$(fm_status_wake_reminder)
PROMOTION_STATUS_WORKING_RULE=$(fm_status_working_rule "$MODE")
PROMOTION_STATUS_NO_PROGRESS_RULE=$(fm_status_no_progress_rule)
PROMOTION_STATUS_NO_RESOLVED_ECHO_RULE=$(fm_status_no_resolved_echo_rule)
mkdir -p "$DATA/$ID"
[ ! -d "$INSTRUCTIONS" ] || { echo "error: ship instructions path is a directory: $INSTRUCTIONS" >&2; exit 1; }
TMP="$DATA/$ID/.ship-instructions.md.${BASHPID:-$$}"
Expand All @@ -213,7 +219,11 @@ EOF
3. Return to a clean default-branch base, then create your branch: \`git checkout -b fm/$ID\`.
4. Carry over only the intended fix changes. Leave scratch commits, debug edits, and experiment files behind.
5. If you reproduced a bug, turn that reproduction into a regression test.
6. These ship instructions supersede the scout delivery rules and report-based Definition of done. Everything else in your original instructions carries over unchanged: the status protocol; the instruction inbox and its acknowledgement; the escalation rules, including ask-user; and every safety rule.
6. These ship instructions supersede the scout delivery rules and report-based Definition of done. The shared status protocol rules carry over unchanged, but the mode-specific working-phase rule below supersedes the scout wording. The instruction inbox and its acknowledgement; the escalation rules, including ask-user; and every safety rule carry over unchanged.
$PROMOTION_STATUS_WAKE_REMINDER
$PROMOTION_STATUS_WORKING_RULE
$PROMOTION_STATUS_NO_PROGRESS_RULE
$PROMOTION_STATUS_NO_RESOLVED_ECHO_RULE
$PROMOTION_ASK_USER_BLOCK
7. Treat the scout-time Firstmate spec and any unmarked legacy \`# Task\` text as investigation context, not captain intent or ship-time instructions.
EOF
Expand Down
40 changes: 40 additions & 0 deletions bin/fm-status-lib.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/usr/bin/env bash
# Shared generated worker status-protocol wording.

fm_status_wake_reminder() {
printf '%s\n' \
'Each status-file append wakes the supervisor and costs a full supervision turn.' \
'Append only when this protocol requires it; never use status as a progress log.'
}

fm_status_working_rule() { # <scout|no-mistakes|direct-PR|local-only>
local kind=$1
case "$kind" in
scout)
# shellcheck disable=SC2016 # Backticks are literal status-protocol text.
printf '%s\n' 'Append `working:` only for a genuine phase change the supervisor would act on: starting the investigation, entering a distinct research phase, or beginning report writing.'
;;
no-mistakes|direct-PR)
# shellcheck disable=SC2016 # Backticks are literal status-protocol text.
printf '%s\n' 'Append `working:` only for a genuine phase change the supervisor would act on: work started, implementation committed and validation started, or PR opened.'
;;
local-only)
# shellcheck disable=SC2016 # Backticks are literal status-protocol text.
printf '%s\n' 'Append `working:` only for a genuine phase change the supervisor would act on: work started or implementation committed and validation started.'
;;
*)
echo "error: fm_status_working_rule: unknown kind '$kind'" >&2
return 1
;;
esac
}

fm_status_no_progress_rule() {
# shellcheck disable=SC2016 # Backticks are literal status-protocol text.
printf '%s\n' 'Never append `working:` for a sub-step, a verification pass, or the start of re-review.'
}

fm_status_no_resolved_echo_rule() {
# shellcheck disable=SC2016 # Backticks are literal status-protocol text.
printf '%s\n' 'Never append a `resolved:` echo of a firstmate steer; moving its message into `handled/` is the acknowledgement.'
}
5 changes: 3 additions & 2 deletions docs/scripts.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ The shared no-mistakes gate refusal for fleet lifecycle entrypoints is summarize
| `fm-backlog-receive.sh` | Idempotently ingest one confined remote handoff outbox through tasks-axi |
| `fm-captain-hold.sh` | Hold tasks for the captain, record the captain's answers, gate investigation completion, and report record divergence between the status log and the backlog |
| `fm-decision-hold.sh` | One-release compatibility shim mapping the retired decision commands onto fm-captain-hold.sh |
| `fm-brief.sh` | Scaffold ship (explicit `--mode`), scout, secondmate-charter, and Herdr-lab briefs, with Captain's intent and Firstmate spec subsections on ship/scout |
| `fm-brief.sh` | Scaffold ship (explicit `--mode`), scout, secondmate-charter, and Herdr-lab briefs, with mode-specific status protocol and Captain's intent and Firstmate spec subsections on ship/scout |
| `fm-status-lib.sh` | Shared generated worker status-protocol wording for briefs and promotion handoffs |
| `fm-dod-lib.sh` | One owner of the ship definition of done and of the no-mistakes `--intent` contract |
| `fm-herdr-lab.sh` | Provision and guardedly operate an isolated, never-default Herdr lab session |
| `fm-install-herdr.sh` | Install CI's exact-version Herdr pin with official asset URL, SHA-256, and protocol checks |
Expand Down Expand Up @@ -135,7 +136,7 @@ The shared no-mistakes gate refusal for fleet lifecycle entrypoints is summarize
| `fm-pr-merge.sh` | Record PR metadata, merge a task's canonical full GitHub or GitLab URL, then refuse an outcome it cannot prove landed or queued |
| `fm-merge-outcome-lib.sh` | Publish a confirmed merge's durable, role-routed supervision outcome |
| `fm-parent-channel-lib.sh` | Resolve a secondmate home's parent channel and append a captain-facing outcome line to it at most once |
| `fm-promote.sh` | Promote a scout task in place to a protected ship task with an explicit delivery mode, and write the ship instructions carrying that mode's definition of done |
| `fm-promote.sh` | Promote a scout task in place to a protected ship task with an explicit delivery mode, and write ship instructions carrying that mode's status protocol and definition of done |
| `fm-teardown.sh` | Fail-closed teardown: return landed ship worktrees, require completed scout deliverables, retire secondmate homes |
| `fm-harness.sh` | Detect the running harness and resolve crew or secondmate harness, model, and effort |
| `fm-lock.sh` | Per-home firstmate session lock |
Expand Down
Loading
Loading