Skip to content

feat: add bounded stop conditions to crewmate briefs#423

Open
stoneymarrow wants to merge 11 commits into
kunchenguid:mainfrom
stoneymarrow:fm/fm-brief-stop-caps
Open

feat: add bounded stop conditions to crewmate briefs#423
stoneymarrow wants to merge 11 commits into
kunchenguid:mainfrom
stoneymarrow:fm/fm-brief-stop-caps

Conversation

@stoneymarrow

@stoneymarrow stoneymarrow commented Jul 10, 2026

Copy link
Copy Markdown

Intent

Add explicit stop conditions and bounded work caps to firstmate's standard ship and scout crewmate brief scaffolds, closing the gap where new obstacles can consume unbounded time without a supervisor-actionable update. Include a default of roughly two hours or 50 significant actions with no supervisor-actionable phase change, while making clear that expected waiting on validation or long test suites is not exhaustion. Add an optional --budget '' task-specific hard cap that renders in the same block. Report early and stop if the task is clearly larger than briefed. Preserve the existing status protocol, isolation assertion, Herdr-lab gate, delivery-mode definitions of done, and shared scaffold structure. Keep the change focused, extend the existing fm-brief tests for ship and scout defaults, the budget override, and unregressed sections, and keep shell scripts shellcheck-clean. Document --budget in AGENTS.md section 11 and docs/scripts.md as an optional per-task control for unattended or long-running task shapes, and fix the fm-brief.sh usage() range so --help includes its entire script contract.

What Changed

Captain, this covers the full branch delta.

  • Add bounded stop conditions to generated ship and scout briefs, including default progress caps, early scope-expansion stops, and an exception for expected validation waits.
  • Add and document --budget '<text>' for task-specific hard caps, with argument validation and expanded brief-rendering coverage.
  • Stabilize worktree readiness and locale-sensitive composer handling, along with related test fixtures and compatibility skips.

Risk Assessment

✅ Low: Captain, the change is well-bounded, preserves existing brief invariants, validates ambiguous budget arguments, and includes focused regression coverage.

Testing

The supplied full tmux-backed baseline and focused brief tests passed; manual CLI generation demonstrated default and custom budget caps, preserved ship/scout contracts, complete help and documentation, with reviewer-visible transcript evidence and no worktree residue.

Evidence: End-user fm-brief CLI transcript
$ bin/fm-brief.sh --help
Scaffold a crewmate brief or persistent secondmate charter at
data/<task-id>/brief.md under the active firstmate home.
For ordinary tasks, the standard Setup/Rules/Definition-of-done contract is
filled in. Firstmate then replaces the {TASK} placeholder with the task
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> [--scout] [--herdr-lab] [--budget '<text>']
       fm-brief.sh <task-id> --secondmate {<project>...|--no-projects}
  --scout writes the scout contract instead: the deliverable is a report at
  data/<task-id>/report.md (no branch, no push, no PR) and the worktree is scratch.
  --secondmate writes a persistent secondmate charter. The project list
  is cloned into the secondmate home, while the natural-language scope
  tells the main firstmate when to route work there; routine churn stays in its own home;
  captain-relevant escalations and marked from-firstmate replies append to this
  home's status file.
  --no-projects writes a project-less charter for a domain whose subject is the
  firstmate repo itself (its home is a firstmate worktree, its crews take pooled
  worktrees of the same repo). It is mutually exclusive with a project list, and
  omitting both still fails loudly so an accidental omission is never silent.
  Set FM_SECONDMATE_CHARTER='<charter>' to fill the charter text.
  Set FM_SECONDMATE_SCOPE='<scope>' to write a routing scope distinct from the charter text.
  --herdr-lab is mandatory when the task will issue Herdr lifecycle commands.
  It adds the hard isolation contract backed by bin/fm-herdr-lab.sh.
  The flag must be explicit because {TASK} is filled after scaffolding and the
  caller-supplied repo string cannot reliably identify this repo. Briefs made
  without it carry a loud declaration so an omitted contract cannot be silent.
  --budget '<text>' adds a task-specific hard stop to a crewmate ship or scout
  brief's standard stop conditions.
For ship tasks, the definition of done is shaped by the project's delivery mode
(data/projects.md via fm-project-mode.sh; see AGENTS.md project management
and task lifecycle):
  no-mistakes  implement -> /no-mistakes pipeline -> PR -> captain merge (default)
  direct-PR    implement -> push + open PR via gh-axi (no pipeline) -> captain merge
  local-only   implement on branch, stop and report "ready in branch" (no push/PR);
               firstmate reviews, captain approves, firstmate merges to local main
Ship briefs begin with a worktree-isolation assertion before the branch step.
Scout tasks ignore mode - their deliverable is a report, not a merge.
Ship tasks include a project-memory section so durable project-intrinsic
learnings can be committed to AGENTS.md through the project's delivery path;
it carries the AGENTS.md authoring bar (widely useful knowledge only, pointers
over copied detail) and has the crewmate add the fm-ensure-agents-md.sh
self-governance section when a touched project AGENTS.md lacks it.
Refuses to overwrite an existing brief.

$ FM_HOME=<evidence-home> bin/fm-brief.sh ship-default default-demo --herdr-lab
warn: project "default-demo" not in registry; defaulting to no-mistakes off
scaffolded: /var/folders/7t/7s3dd555217fnnjq46z87qvc0000gn/T/no-mistakes-evidence/01KX87NY7R2EKA157ZZ6A549AE/fm-brief-e2e/home/data/ship-default/brief.md (ship, mode=no-mistakes; replace {TASK})

$ FM_HOME=<evidence-home> bin/fm-brief.sh ship-direct direct-demo
scaffolded: /var/folders/7t/7s3dd555217fnnjq46z87qvc0000gn/T/no-mistakes-evidence/01KX87NY7R2EKA157ZZ6A549AE/fm-brief-e2e/home/data/ship-direct/brief.md (ship, mode=direct-PR; replace {TASK})

$ FM_HOME=<evidence-home> bin/fm-brief.sh ship-local local-demo
scaffolded: /var/folders/7t/7s3dd555217fnnjq46z87qvc0000gn/T/no-mistakes-evidence/01KX87NY7R2EKA157ZZ6A549AE/fm-brief-e2e/home/data/ship-local/brief.md (ship, mode=local-only; replace {TASK})

$ FM_HOME=<evidence-home> bin/fm-brief.sh scout-budget default-demo --scout --budget "hard stop after 30 minutes"
scaffolded: /var/folders/7t/7s3dd555217fnnjq46z87qvc0000gn/T/no-mistakes-evidence/01KX87NY7R2EKA157ZZ6A549AE/fm-brief-e2e/home/data/scout-budget/brief.md (scout; replace {TASK})

=== SHIP DEFAULT: shared scaffold, status, isolation, Herdr, stop conditions, no-mistakes done ===
3:# Task
6:# Herdr isolation - HARD SAFETY CONTRACT
11:1. Set `HERDR_LAB_HELPER='/Users/varun/.no-mistakes/worktrees/62b0bb08545c/01KX87NY7R2EKA157ZZ6A549AE/bin/fm-herdr-lab.sh'` and generate the session name with `HERDR_LAB_SESSION=$("$HERDR_LAB_HELPER" name ship-default)`.
25:# Setup
28:**Verify isolation before anything else.** Run `pwd -P` and `git rev-parse --show-toplevel`; both must resolve to the disposable task worktree you were launched in, such as a treehouse pool path or an Orca-managed worktree, not the primary checkout firstmate operates from.
33:2. Run `no-mistakes doctor`; if it reports the repo is not initialized here, run `no-mistakes init`.
35:# Rules
40:   `echo "{state}: {one short line}" >> '/var/folders/7t/7s3dd555217fnnjq46z87qvc0000gn/T/no-mistakes-evidence/01KX87NY7R2EKA157ZZ6A549AE/fm-brief-e2e/home/state/ship-default.status'`
41:   States: working, needs-decision, blocked, paused, done, failed.
54:## Stop conditions
56:Expected waiting on a validation run or long test suite does not count as a no-phase-change stretch.
57:If roughly two hours or 50 significant actions pass without a supervisor-actionable phase change, append `blocked: budget - {one-line progress + what remains}` and stop.
58:If the work is clearly larger than this brief, append `blocked: scope - {one-line progress + newly discovered work}` and stop before silently expanding scope.
60:# Project memory
61:If `AGENTS.md` or `CLAUDE.md` already exists, or if this task produced durable project-intrinsic knowledge, run `/Users/varun/.no-mistakes/worktrees/62b0bb08545c/01KX87NY7R2EKA157ZZ6A549AE/bin/fm-ensure-agents-md.sh .` in the worktree.
64:If you touch a project `AGENTS.md` that lacks `## Maintaining this file`, add that short self-governance section from `/Users/varun/.no-mistakes/worktrees/62b0bb08545c/01KX87NY7R2EKA157ZZ6A549AE/bin/fm-ensure-agents-md.sh` in the same pass.
67:# Definition of done
70:Firstmate will then instruct you to run /no-mistakes to validate and ship a PR.
72:You drive no-mistakes by responding to its gates, not by implementing fixes.
73: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.
78:  When the decision comes back, feed it to the gate with `no-mistakes axi respond` and let the pipeline apply it - do not route the question to "the user" or implement the fix yourself.
81:After /no-mistakes reports CI green (the CI-ready return point - do not wait for it to keep monitoring in the background until merge), append `done: PR {url} checks green` and stop. You are finished.

=== DIRECT-PR: delivery-specific done ===
11:# Setup
20:# Rules
39:## Stop conditions
45:# Project memory
52:# Definition of done
53:This project ships **direct-PR**: you raise the PR yourself, without the no-mistakes pipeline.
55: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.

=== LOCAL-ONLY: delivery-specific done ===
11:# Setup
20:# Rules
39:## Stop conditions
45:# Project memory
52:# Definition of done
53:This project ships **local-only**: no remote, no PR, no pipeline.
56:When it is implemented and committed, append `done: ready in branch fm/ship-local` to the status file and stop.

=== SCOUT WITH OVERRIDE: shared scaffold, status, default cap, override, report done ===
3:# Task
6:# Herdr lifecycle declaration - NOT ENABLED
11:# Setup
17:# Rules
23:   States: working, needs-decision, blocked, paused, done, failed.
35:## Stop conditions
37:Expected waiting on a validation run or long test suite does not count as a no-phase-change stretch.
38:If roughly two hours or 50 significant actions pass without a supervisor-actionable phase change, append `blocked: budget - {one-line progress + what remains}` and stop.
39:If the work is clearly larger than this brief, append `blocked: scope - {one-line progress + newly discovered work}` and stop before silently expanding scope.
40:Task-specific budget: hard stop after 30 minutes
41:Treat this as a hard cap, and when it is reached append `blocked: budget - {one-line progress + what remains}` and stop.
43:# Definition of done
44:Write your findings to `/var/folders/7t/7s3dd555217fnnjq46z87qvc0000gn/T/no-mistakes-evidence/01KX87NY7R2EKA157ZZ6A549AE/fm-brief-e2e/home/data/scout-budget/report.md`.
46:When the report is complete, append `done: {one-line conclusion}` to the status file and stop.

=== DOCUMENTED OPERATOR CONTRACT ===
AGENTS.md:874:Scaffold with `bin/fm-brief.sh <id> <repo-name>` - it writes `data/<id>/brief.md` with the standard contract (branch setup, status-reporting protocol, bounded stop conditions, push/merge rules, definition of done) and all paths filled in.
AGENTS.md:875:At intake, recognize when the captain or task shape calls for a task-specific cap and pass `--budget '<text>'` when scaffolding the ship or scout brief.
docs/scripts.md:16:| `fm-brief.sh`            | Scaffold a ship brief with a worktree-isolation assertion and bounded stop conditions, a report-only scout brief with the same stop conditions via `--scout`, or a secondmate charter with `--secondmate` plus either projects or the deliberate `--no-projects` signal; all scaffolds distinguish the configured declared-external-wait status from `blocked:`; optional `--budget '<text>'` adds a task-specific hard stop to ship/scout stop conditions; `--herdr-lab` adds the hard named-session isolation contract and every unguarded ship/scout scaffold carries a loud lifecycle declaration |

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

✅ **Review** - passed

✅ No issues found.

✅ **Test** - passed

✅ No issues found.

  • command -v tmux >/dev/null || { echo "tmux is required for e2e tests" >&2; exit 1; }; tmux -V; rc=0; for t in tests/*.test.sh; do echo "== $t =="; bash "$t" || rc=1; done; exit "$rc"
  • Supplied successful baseline: command -v tmux &gt;/dev/null || { echo &#34;tmux is required for e2e tests&#34; &gt;&amp;2; exit 1; }; tmux -V; rc=0; for t in tests/*.test.sh; do echo &#34;== $t ==&#34;; bash &#34;$t&#34; || rc=1; done; exit &#34;$rc&#34;
  • bash tests/fm-brief.test.sh
  • bin/fm-brief.sh --help
  • Generated default ship, direct-PR, local-only, Herdr-lab, and budgeted scout briefs using bin/fm-brief.sh
  • Verified stop caps, waiting exception, early scope stop, status protocol, isolation, delivery definitions, and documentation in the rendered output
  • git status --short before and after evidence capture
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

@stoneymarrow
stoneymarrow force-pushed the fm/fm-brief-stop-caps branch from 97a028a to 075a3d3 Compare July 10, 2026 16:57
@stoneymarrow stoneymarrow changed the title fix: bound crewmate work and harden task dispatch fix: bound crewmate briefs and stabilize task spawning Jul 10, 2026
@kunchenguid

Copy link
Copy Markdown
Owner

Thanks for the PR! This branch currently has a merge conflict with the base branch.

When you get a chance, please rebase onto (or merge) the latest base branch, resolve the conflict, and push. After that, checks will re-run and the PR will get looked at again.

Noted for firstmate#423 at 32b39b06.

@stoneymarrow stoneymarrow changed the title fix: bound crewmate briefs and stabilize task spawning fix(brief): bound crewmate work and add task budgets Jul 10, 2026
@stoneymarrow
stoneymarrow force-pushed the fm/fm-brief-stop-caps branch from 4cd8433 to 4e1014b Compare July 10, 2026 21:14
@stoneymarrow
stoneymarrow force-pushed the fm/fm-brief-stop-caps branch from 4e1014b to 70ec3d1 Compare July 11, 2026 07:46
@stoneymarrow stoneymarrow changed the title fix(brief): bound crewmate work and add task budgets feat: add bounded stop conditions to crewmate briefs Jul 11, 2026
@kunchenguid

kunchenguid commented Jul 11, 2026

Copy link
Copy Markdown
Owner

Thanks for the PR! This branch currently has a merge conflict with the base branch.

When you get a chance, please rebase onto (or merge) the latest base branch, resolve the conflict, and push. After that, checks will re-run and the PR will get looked at again.

Noted for firstmate#423 at 067f6bbf.

@kunchenguid

kunchenguid commented Jul 13, 2026

Copy link
Copy Markdown
Owner

Thanks for the PR! This branch currently has a merge conflict with the base branch.

When you get a chance, please rebase onto (or merge) the latest base branch, resolve the conflict, and push. After that, checks will re-run and the PR will get looked at again.

Noted for firstmate#423 at f5113f9e.

@kunchenguid kunchenguid left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two concerns with the stop-condition/budget framing:

  1. Naming inconsistency: The feature is called "budget" in some places (e.g. --budget flag, the task-specific budget prose) and "stop condition" in others. If this is purely advisory guidance to the AI agent, the terminology should be consistent throughout — pick one term and use it everywhere. "Stop condition" is the more accurate description for honor-system guidance.

  2. Enforcement gap: If this is intended as a real budget (a hard cap), it must be deterministically enforced — an external watchdog, action counter, or timer — not left to the agent's self-reporting. A purely honor-system instruction is not a budget; it is a guideline. Either rename it to reflect that it is guidance only, or implement deterministic enforcement.

Please either:

  • Rename all uses of "budget" to "stop condition" and remove any implication of hard enforcement, or
  • Implement actual deterministic enforcement and keep the "budget" terminology.

@kunchenguid

Copy link
Copy Markdown
Owner

No description provided.

@stoneymarrow
stoneymarrow force-pushed the fm/fm-brief-stop-caps branch from 59058c1 to e32c45f Compare July 19, 2026 10:01
@stoneymarrow

Copy link
Copy Markdown
Author

Addressed the requested changes and rebased the PR branch onto current origin/main (b2bf95f).

  • Unified the feature terminology on guideline/guidelines throughout: --guideline, ## Guidelines, help text, generated brief prose, status text, docs, and tests.
  • Removed hard-cap and hard-stop implications while preserving the roughly two-hour/50-significant-action no-progress guideline, expected validation-wait exception, early scope-growth guidance, and optional task-specific --guideline <text> addition.
  • Deliberately did not add a watchdog, timer, or action counter. This remains advisory, honor-system guidance by design, following the guidance-only option A.
  • Re-ran the focused and adjacent test suites plus the repository-owned pinned shell lint; all passed.

@kunchenguid kunchenguid removed the wheelhouse:pending-contributor-action Managed by Wheelhouse label Jul 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants