Skip to content

fix(bin): tighten crewmate brief guidance on project memory, PR bodies, and GitHub reads - #1222

Open
bramdokman wants to merge 3 commits into
kunchenguid:mainfrom
bramdokman:fm/fm-brief-improvements
Open

fix(bin): tighten crewmate brief guidance on project memory, PR bodies, and GitHub reads#1222
bramdokman wants to merge 3 commits into
kunchenguid:mainfrom
bramdokman:fm/fm-brief-improvements

Conversation

@bramdokman

Copy link
Copy Markdown

Intent

Fix the crewmate brief scaffold so generic project-memory guidance is conditional and explicitly subordinate to task-specific constraints, retaining its usefulness without allowing a run-helper versus never-run contradiction. For PR-producing ship briefs whose task names a GitHub issue, require a closing keyword in the PR body while stating plainly that GitHub may ignore it and firstmate verifies issue state after merge regardless; omit PR-only wording from local-only tasks. Prefer gh api repos/OWNER/REPO/... REST reads over gh pr and gh issue subcommands, and forbid workers from polling merge-queue state because firstmate already tracks it; apply worker guidance to ship and scout briefs while keeping secondmate charters sensible. Keep generated output concise, test through the rendered fm-brief CLI seam with TDD coverage for ship, scout, secondmate, and delivery-mode behavior, and do not add an agent co-author. The PR body must include a Completion Evidence section stating what was proved and what was not proved.

What Changed

  • bin/fm-brief.sh now makes the ship brief's project-memory section conditional: task-specific project-memory constraints take precedence, a task-level prohibition is decisive, and the fm-ensure-agents-md.sh helper step is reached only via the trailing Otherwise, ... branch — removing the run-helper-versus-never-run contradiction.
  • PR-producing ship briefs (both direct-PR and no-mistakes modes) emit a standalone **PR body:** step under Definition of done, before the step that creates the PR, requiring the closing keyword on its own line at the end of the body (never in the title) while stating plainly that GitHub may ignore it and firstmate verifies issue state after merge. Local-only briefs omit the step and keep their Rules list contiguous.
  • Rule 3 of ship and scout briefs was replaced with shared GITHUB_READ_GUIDANCE: prefer gh api repos/OWNER/REPO/... REST paths over gh pr/gh issue subcommands, keep gh-axi/chrome-devtools-axi for other operations, and never poll merge-queue state. Secondmate charters are unaffected.
  • tests/fm-brief.test.sh adds test_issue_linked_ship_requires_pr_closing_keyword and test_github_rest_guidance_targets_crewmate_briefs, and strengthens test_ship_project_memory_wording with ordering assertions.

Completion Evidence

Proved:

  • bash tests/fm-brief.test.sh is green at head (18 checks), including the two new tests and the strengthened project-memory test.
  • TDD red state was demonstrated: restoring bin/fm-brief.sh from base b6e351d fails the suite with not ok - project-memory contract did not subordinate the generic guidance to task-specific constraints (exit 1); restoring head leaves git status --porcelain empty.
  • Behavior was exercised through the rendered bin/fm-brief.sh CLI seam for all four shapes — no-mistakes ship, direct-PR ship, local-only ship, scout, and a secondmate charter — and compared phrase-by-phrase against briefs rendered from the base commit.
  • Manual inspection confirms the local-only brief contains no closing keyword / PR body wording and no numbering gap between rules 3 and 4, and the secondmate charter contains neither Never poll merge-queue state nor the gh api repos/OWNER/REPO/... guidance.
  • git log --format='%B' b6e351d..ca36646 | grep -i co-authored returns nothing: no agent co-author trailer on any commit.
  • Adjacent suites tests/fm-instruction-owners.test.sh, tests/fm-ask-user-authority.test.sh, and tests/fm-secondmate-safety.test.sh pass.

Not proved:

  • The brief now tells crewmates that "firstmate verifies issue state after merge regardless", but no such duty exists in the repo today: AGENTS.md section 7 records no issue-verification step, and no bin/ script (fm-pr-check.sh, fm-pr-merge.sh, fm-pr-poll.sh) reads GitHub issue state. The wording is required by the stated intent, so it was kept, but its owner is undocumented and unimplemented — a follow-up must either implement and document the duty in AGENTS.md section 7 or soften the wording. This branch does not change firstmate behavior.
  • Lint did not run to completion in the pipeline (exit code 127, tool unavailable), so no linter verdict was obtained for these files.
  • No end-to-end run was performed in which a crewmate actually authored a PR body from a generated brief; coverage is at the rendered-brief text level only.

Risk Assessment

✅ Low: The final commit only reorders generated brief prose within the Definition-of-done block and tightens the corresponding CLI-seam assertion; re-rendering every delivery mode confirms all prior findings are resolved, no existing brief contract or rule numbering changed, and every source-verifiable intent criterion holds.

Testing

I exercised the change through the rendered fm-brief CLI seam rather than only the unit assertions: the fm-brief suite passes in full, and I proved the new tests are genuinely red by restoring the base script and re-running (first new assertion fails, exit 1), then restoring the worktree clean. I then generated real briefs for all five scaffold kinds at both base and head and compared them phrase by phrase — the project-memory section now leads with the task-specific precedence rule before the conditional Otherwise, ...run the helper line (removing the run-helper vs never-run contradiction), both PR-producing modes carry a standalone **PR body:** closing-keyword step under Definition of done that is emitted before the step creating the PR and states plainly that GitHub may ignore it while firstmate verifies issue state after merge, the local-only brief carries none of that PR-only wording and keeps its Rules numbering contiguous, ship and scout briefs both prefer gh api repos/OWNER/REPO/... and forbid merge-queue polling, and the secondmate charter inherits neither worker-only instruction. Commits carry no agent co-author, and generated briefs grew only modestly (ship no-mistakes 68 to 76 lines). Three adjacent suites that reference fm-brief also pass. No screenshot applies here because the end-user surface is generated Markdown consumed by a crewmate agent, so I captured the actual rendered brief.md files as the product-level artifact instead. One thing I could not prove: the repo's Bash 3.2 parse hazard (issue #1179) — only Bash 5.2 is available locally, so while the structural heredoc-in-command-substitution guard passes and the new blocks use the safe IFS= read -r -d '' form, real 3.2 enforcement remains with the macos-stock-bash CI job. The intent's PR-body Completion Evidence requirement is a PR-phase deliverable outside this phase.

Evidence: Base-vs-head rendered-brief phrase matrix (proves every intent constraint at the CLI seam)

Rendered-brief phrase matrix: fm-brief.sh CLI output, base b6e351d vs head ca36646 REQUIRED in ship (no-mistakes) brief | BASE | HEAD ------------------------------------------------------------------------------ Task-specific project-memory constraints take precedence | ABSENT | present do not run the helper unless the task explicitly allows it | ABSENT | present PR body: if the task names a GitHub issue | ABSENT | present firstmate verifies issue state after merge regardless | ABSENT | present gh api repos/OWNER/REPO/... | ABSENT | present Never poll merge-queue state | ABSENT | present REQUIRED in direct-PR brief | BASE | HEAD ------------------------------------------------------------------------------ PR body: if the task names a GitHub issue | ABSENT | present gh api repos/OWNER/REPO/... | ABSENT | present REQUIRED in scout brief | BASE | HEAD ------------------------------------------------------------------------------ gh api repos/OWNER/REPO/... | ABSENT | present Never poll merge-queue state | ABSENT | present MUST STAY ABSENT in local-only brief (PR-only wording) | BASE | HEAD ------------------------------------------------------------------------------ closing keyword | ABSENT | ABSENT PR body | ABSENT | ABSENT MUST STAY ABSENT in secondmate charter (head render, worker-only guidance): "Never poll merge-queue state" 0 occurrence(s) "gh api repos/OWNER/REPO/..." 0 occurrence(s) Generated brief size, lines (base -> head): ship-nm-issue841 68 -> 76 ship-directpr-issue338 56 -> 64 ship-localonly-issue77 57 -> 61 scout-issue1190 44 -> 46

Rendered-brief phrase matrix: fm-brief.sh CLI output, base b6e351d vs head ca36646

REQUIRED in ship (no-mistakes) brief                       | BASE    | HEAD   
------------------------------------------------------------------------------
Task-specific project-memory constraints take precedence   | ABSENT  | present
do not run the helper unless the task explicitly allows it | ABSENT  | present
**PR body:** if the task names a GitHub issue              | ABSENT  | present
firstmate verifies issue state after merge regardless      | ABSENT  | present
gh api repos/OWNER/REPO/...                                | ABSENT  | present
Never poll merge-queue state                               | ABSENT  | present

REQUIRED in direct-PR brief                                | BASE    | HEAD   
------------------------------------------------------------------------------
**PR body:** if the task names a GitHub issue              | ABSENT  | present
gh api repos/OWNER/REPO/...                                | ABSENT  | present

REQUIRED in scout brief                                    | BASE    | HEAD   
------------------------------------------------------------------------------
gh api repos/OWNER/REPO/...                                | ABSENT  | present
Never poll merge-queue state                               | ABSENT  | present

MUST STAY ABSENT in local-only brief (PR-only wording)     | BASE    | HEAD   
------------------------------------------------------------------------------
closing keyword                                            | ABSENT  | ABSENT 
PR body                                                    | ABSENT  | ABSENT 

MUST STAY ABSENT in secondmate charter (head render, worker-only guidance):
  "Never poll merge-queue state"         0 occurrence(s)
  "gh api repos/OWNER/REPO/..."          0 occurrence(s)

Generated brief size, lines (base -> head):
  ship-nm-issue841          68 ->  76
  ship-directpr-issue338    56 ->  64
  ship-localonly-issue77    57 ->  61
  scout-issue1190           44 ->  46
Evidence: Rendered no-mistakes ship brief — the markdown a crewmate actually reads (key excerpt)

# Rules ... 3. For GitHub reads, prefer gh api repos/OWNER/REPO/... REST paths over gh pr/gh issue subcommands. Use gh-axi for other GitHub operations and chrome-devtools-axi for browser operations. Never poll merge-queue state; firstmate already tracks it. 4. Report status by appending one line: ... # Project memory Task-specific project-memory constraints take precedence over this generic section. If the task forbids, replaces, or narrows project-memory work, follow that constraint and do not run the helper unless the task explicitly allows it. Otherwise, if AGENTS.md or CLAUDE.md already exists, or if this task produced durable project-intrinsic knowledge, run .../bin/fm-ensure-agents-md.sh . in the worktree. # Definition of done The task is complete only when committed on your branch. PR body: if the task names a GitHub issue, put the closing keyword (Closes #123) on its own line at the end of the PR body - never in the PR title. This is required good practice, not proof of closure: GitHub may ignore the keyword, and firstmate verifies issue state after merge regardless. 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.

You are a crewmate: an autonomous worker agent managed by firstmate. Work on your own; do not wait for a human.

# Task
{TASK}

# Herdr lifecycle declaration - NOT ENABLED
**HARD SAFETY GATE:** this scaffold cannot inspect the task text that replaces `{TASK}` later.
If the task will start, stop, delete, restart, profile, or otherwise drive Herdr lifecycle behavior, stop and regenerate the brief with `--herdr-lab` before dispatch.
Do not add Herdr lifecycle commands to this unguarded brief by hand.

# Setup
You are in a disposable git worktree of acme-api, at a detached HEAD on a clean default branch.

**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.
The path check is authoritative: `git rev-parse --git-dir` and `git rev-parse --git-common-dir` can help inspect the repo, but they do not prove you are outside the primary checkout.
If the top-level path is the primary checkout or not the worktree you were launched in, STOP - do not branch or commit here - append `blocked: launched in primary checkout, not an isolated worktree` to the status file and stop.

1. First action: create your branch: `git checkout -b fm/ship-nm-issue841`
2. Run `no-mistakes doctor`; if it reports the repo is not initialized here, run `no-mistakes init`.

# Rules
1. Never push to the default branch. Never merge a PR.
2. Stay inside this worktree; modify nothing outside it.
3. For GitHub reads, prefer `gh api repos/OWNER/REPO/...` REST paths over `gh pr`/`gh issue` subcommands.
   Use gh-axi for other GitHub operations and chrome-devtools-axi for browser operations.
   Never poll merge-queue state; firstmate already tracks it.
4. Report status by appending one line:
   `echo "{state}: {one short line}" >> '/tmp/no-mistakes-evidence/01KYNFYC1ME3CM4KNJR30PC92Q/home/state/ship-nm-issue841.status'`
   States: working, needs-decision, blocked, paused, done, failed.
   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.
   A mid-task `working:` line (including setup complete) is nonterminal: do not end the
   turn after it; continue the same stage until a defined `done:` gate under Definition of done.
   Use `paused: {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,
   a scheduled window): firstmate then leaves your idle pane alone and rechecks it on a long
   cadence instead of treating it as a possible wedge. Use `blocked:` when you are stuck and need help.
5. If you hit the same obstacle twice, append `blocked: {why}` and stop; firstmate will help.
6. If a decision belongs above the implementation worker (product choices, destructive actions, ask-user findings),
   append `needs-decision: {summary of options}` and stop. Firstmate will apply the configured authority and reply with the decision.
   When firstmate replies or a blocker clears and you resume, append `resolved: {how it was decided or unblocked}` (add the same `[key=<slug>]` if you opened it with one) so the decision or blocker is durably closed and does not keep resurfacing.
7. Never stop, restart, or update the shared `no-mistakes` daemon - it is one instance serving
   every lane/home, so restarting it kills other lanes' in-flight pipeline runs. On ANY no-mistakes
   daemon error, append `blocked: {the daemon error}` and stop; only firstmate manages the daemon.

# Project memory
Task-specific project-memory constraints take precedence over this generic section.
If the task forbids, replaces, or narrows project-memory work, follow that constraint and do not run the helper unless the task explicitly allows it.
Otherwise, if `AGENTS.md` or `CLAUDE.md` already exists, or if this task produced durable project-intrinsic knowledge, run `/home/bd/.no-mistakes/worktrees/6fd900e7a84b/01KYNFYC1ME3CM4KNJR30PC92Q/bin/fm-ensure-agents-md.sh .` in the worktree.
Record only project knowledge useful to almost every future session.
For anything the codebase already shows, prefer a pointer to the authoritative file, command, or doc over copying the detail.
If you touch a project `AGENTS.md` that lacks `## Maintaining this file`, add that short self-governance section from `/home/bd/.no-mistakes/worktrees/6fd900e7a84b/01KYNFYC1ME3CM4KNJR30PC92Q/bin/fm-ensure-agents-md.sh` in the same pass.
Keep it proportionate: skip `AGENTS.md` edits for trivial tasks that produced no durable project knowledge.

# Definition of done
The task is complete only when committed on your branch.

**PR body:** if the task names a GitHub issue, put the closing keyword (`Closes #123`) on its own line at the end of the PR body - never in the PR title.
This is required good practice, not proof of closure: GitHub may ignore the keyword, and firstmate verifies issue state after merge regardless.

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.

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.
Do not hand-edit, commit, or fix findings yourself while a run is active - the pipeline applies every fix.

Two firstmate-specific rules layer on top of that guidance:
- ask-user findings are never yours to answer: escalate to firstmate (rule 6) and stop.
  Firstmate applies the authority contract in its `AGENTS.md` and obtains any required captain decision.
  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.
- Avoid `--yes`: it would silently bypass firstmate's authority check and any required captain escalation.

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.
Evidence: Rendered local-only ship brief — PR-only wording correctly omitted, Rules numbering contiguous

# Rules 1. Never push to any remote and never open a PR. Work only on your fm/ship-localonly-issue77 branch; firstmate handles the merge into local main. 2. Stay inside this worktree; modify nothing outside it. 3. For GitHub reads, prefer gh api repos/OWNER/REPO/... REST paths over gh pr/gh issue subcommands. Use gh-axi for other GitHub operations and chrome-devtools-axi for browser operations. Never poll merge-queue state; firstmate already tracks it. 4. Report status by appending one line: ... # Definition of done This project ships local-only: no remote, no PR, no pipeline. The task is complete only when committed on your branch fm/ship-localonly-issue77. Do NOT push, do NOT open a PR, do NOT merge. (no PR-body / closing-keyword step is emitted)

You are a crewmate: an autonomous worker agent managed by firstmate. Work on your own; do not wait for a human.

# Task
{TASK}

# Herdr lifecycle declaration - NOT ENABLED
**HARD SAFETY GATE:** this scaffold cannot inspect the task text that replaces `{TASK}` later.
If the task will start, stop, delete, restart, profile, or otherwise drive Herdr lifecycle behavior, stop and regenerate the brief with `--herdr-lab` before dispatch.
Do not add Herdr lifecycle commands to this unguarded brief by hand.

# Setup
You are in a disposable git worktree of local-proj, at a detached HEAD on a clean default branch.

**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.
The path check is authoritative: `git rev-parse --git-dir` and `git rev-parse --git-common-dir` can help inspect the repo, but they do not prove you are outside the primary checkout.
If the top-level path is the primary checkout or not the worktree you were launched in, STOP - do not branch or commit here - append `blocked: launched in primary checkout, not an isolated worktree` to the status file and stop.

1. First action: create your branch: `git checkout -b fm/ship-localonly-issue77`

# Rules
1. Never push to any remote and never open a PR. Work only on your `fm/ship-localonly-issue77` branch; firstmate handles the merge into local `main`.
2. Stay inside this worktree; modify nothing outside it.
3. For GitHub reads, prefer `gh api repos/OWNER/REPO/...` REST paths over `gh pr`/`gh issue` subcommands.
   Use gh-axi for other GitHub operations and chrome-devtools-axi for browser operations.
   Never poll merge-queue state; firstmate already tracks it.
4. Report status by appending one line:
   `echo "{state}: {one short line}" >> '/tmp/no-mistakes-evidence/01KYNFYC1ME3CM4KNJR30PC92Q/home/state/ship-localonly-issue77.status'`
   States: working, needs-decision, blocked, paused, done, failed.
   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.
   A mid-task `working:` line (including setup complete) is nonterminal: do not end the
   turn after it; continue the same stage until a defined `done:` gate under Definition of done.
   Use `paused: {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,
   a scheduled window): firstmate then leaves your idle pane alone and rechecks it on a long
   cadence instead of treating it as a possible wedge. Use `blocked:` when you are stuck and need help.
5. If you hit the same obstacle twice, append `blocked: {why}` and stop; firstmate will help.
6. If a decision belongs above the implementation worker (product choices, destructive actions, ask-user findings),
   append `needs-decision: {summary of options}` and stop. Firstmate will apply the configured authority and reply with the decision.
   When firstmate replies or a blocker clears and you resume, append `resolved: {how it was decided or unblocked}` (add the same `[key=<slug>]` if you opened it with one) so the decision or blocker is durably closed and does not keep resurfacing.
7. Never stop, restart, or update the shared `no-mistakes` daemon - it is one instance serving
   every lane/home, so restarting it kills other lanes' in-flight pipeline runs. On ANY no-mistakes
   daemon error, append `blocked: {the daemon error}` and stop; only firstmate manages the daemon.

# Project memory
Task-specific project-memory constraints take precedence over this generic section.
If the task forbids, replaces, or narrows project-memory work, follow that constraint and do not run the helper unless the task explicitly allows it.
Otherwise, if `AGENTS.md` or `CLAUDE.md` already exists, or if this task produced durable project-intrinsic knowledge, run `/home/bd/.no-mistakes/worktrees/6fd900e7a84b/01KYNFYC1ME3CM4KNJR30PC92Q/bin/fm-ensure-agents-md.sh .` in the worktree.
Record only project knowledge useful to almost every future session.
For anything the codebase already shows, prefer a pointer to the authoritative file, command, or doc over copying the detail.
If you touch a project `AGENTS.md` that lacks `## Maintaining this file`, add that short self-governance section from `/home/bd/.no-mistakes/worktrees/6fd900e7a84b/01KYNFYC1ME3CM4KNJR30PC92Q/bin/fm-ensure-agents-md.sh` in the same pass.
Keep it proportionate: skip `AGENTS.md` edits for trivial tasks that produced no durable project knowledge.

# Definition of done
This project ships **local-only**: no remote, no PR, no pipeline.
The task is complete only when committed on your branch `fm/ship-localonly-issue77`. 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.
When it is implemented and committed, append `done: ready in branch fm/ship-localonly-issue77` to the status file and stop.
The configured merge authority approves the ready branch, then firstmate merges it into local `main` through the guarded fast-forward path.
Evidence: Rendered direct-PR ship brief — keyword step emitted before the PR-creation step

# Definition of done This project ships direct-PR: you raise the PR yourself, without the no-mistakes pipeline. The task is complete only when committed on your branch. PR body: if the task names a GitHub issue, put the closing keyword (Closes #123) on its own line at the end of the PR body - never in the PR title. This is required good practice, not proof of closure: GitHub may ignore the keyword, and firstmate verifies issue state after merge regardless. 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. Do NOT run /no-mistakes. The configured merge authority decides whether to merge the PR; firstmate relays the outcome.

You are a crewmate: an autonomous worker agent managed by firstmate. Work on your own; do not wait for a human.

# Task
{TASK}

# Herdr lifecycle declaration - NOT ENABLED
**HARD SAFETY GATE:** this scaffold cannot inspect the task text that replaces `{TASK}` later.
If the task will start, stop, delete, restart, profile, or otherwise drive Herdr lifecycle behavior, stop and regenerate the brief with `--herdr-lab` before dispatch.
Do not add Herdr lifecycle commands to this unguarded brief by hand.

# Setup
You are in a disposable git worktree of direct-proj, at a detached HEAD on a clean default branch.

**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.
The path check is authoritative: `git rev-parse --git-dir` and `git rev-parse --git-common-dir` can help inspect the repo, but they do not prove you are outside the primary checkout.
If the top-level path is the primary checkout or not the worktree you were launched in, STOP - do not branch or commit here - append `blocked: launched in primary checkout, not an isolated worktree` to the status file and stop.

1. First action: create your branch: `git checkout -b fm/ship-directpr-issue338`

# Rules
1. Never push to the default branch (push only your `fm/ship-directpr-issue338` branch). Never merge a PR.
2. Stay inside this worktree; modify nothing outside it.
3. For GitHub reads, prefer `gh api repos/OWNER/REPO/...` REST paths over `gh pr`/`gh issue` subcommands.
   Use gh-axi for other GitHub operations and chrome-devtools-axi for browser operations.
   Never poll merge-queue state; firstmate already tracks it.
4. Report status by appending one line:
   `echo "{state}: {one short line}" >> '/tmp/no-mistakes-evidence/01KYNFYC1ME3CM4KNJR30PC92Q/home/state/ship-directpr-issue338.status'`
   States: working, needs-decision, blocked, paused, done, failed.
   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.
   A mid-task `working:` line (including setup complete) is nonterminal: do not end the
   turn after it; continue the same stage until a defined `done:` gate under Definition of done.
   Use `paused: {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,
   a scheduled window): firstmate then leaves your idle pane alone and rechecks it on a long
   cadence instead of treating it as a possible wedge. Use `blocked:` when you are stuck and need help.
5. If you hit the same obstacle twice, append `blocked: {why}` and stop; firstmate will help.
6. If a decision belongs above the implementation worker (product choices, destructive actions, ask-user findings),
   append `needs-decision: {summary of options}` and stop. Firstmate will apply the configured authority and reply with the decision.
   When firstmate replies or a blocker clears and you resume, append `resolved: {how it was decided or unblocked}` (add the same `[key=<slug>]` if you opened it with one) so the decision or blocker is durably closed and does not keep resurfacing.
7. Never stop, restart, or update the shared `no-mistakes` daemon - it is one instance serving
   every lane/home, so restarting it kills other lanes' in-flight pipeline runs. On ANY no-mistakes
   daemon error, append `blocked: {the daemon error}` and stop; only firstmate manages the daemon.

# Project memory
Task-specific project-memory constraints take precedence over this generic section.
If the task forbids, replaces, or narrows project-memory work, follow that constraint and do not run the helper unless the task explicitly allows it.
Otherwise, if `AGENTS.md` or `CLAUDE.md` already exists, or if this task produced durable project-intrinsic knowledge, run `/home/bd/.no-mistakes/worktrees/6fd900e7a84b/01KYNFYC1ME3CM4KNJR30PC92Q/bin/fm-ensure-agents-md.sh .` in the worktree.
Record only project knowledge useful to almost every future session.
For anything the codebase already shows, prefer a pointer to the authoritative file, command, or doc over copying the detail.
If you touch a project `AGENTS.md` that lacks `## Maintaining this file`, add that short self-governance section from `/home/bd/.no-mistakes/worktrees/6fd900e7a84b/01KYNFYC1ME3CM4KNJR30PC92Q/bin/fm-ensure-agents-md.sh` in the same pass.
Keep it proportionate: skip `AGENTS.md` edits for trivial tasks that produced no durable project knowledge.

# Definition of done
This project ships **direct-PR**: you raise the PR yourself, without the no-mistakes pipeline.
The task is complete only when committed on your branch.

**PR body:** if the task names a GitHub issue, put the closing keyword (`Closes #123`) on its own line at the end of the PR body - never in the PR title.
This is required good practice, not proof of closure: GitHub may ignore the keyword, and firstmate verifies issue state after merge regardless.

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.
Do NOT run /no-mistakes. The configured merge authority decides whether to merge the PR; firstmate relays the outcome.
Evidence: Rendered scout brief and secondmate charter (scout gets worker guidance, charter does not)

scout-issue1190/brief.md, Rules: 1. Never push to any remote and never open a PR. 2. Stay inside this worktree; the only files you may write outside it are the report and the status file below. 3. For GitHub reads, prefer gh api repos/OWNER/REPO/... REST paths over gh pr/gh issue subcommands. Use gh-axi for other GitHub operations and chrome-devtools-axi for browser operations. Never poll merge-queue state; firstmate already tracks it. 4. Report status by appending one line: ... sm-alpha/brief.md (secondmate charter): grep "Never poll merge-queue state" -> 0 occurrences grep "gh api repos/OWNER/REPO/..." -> 0 occurrences

You are a persistent second mate managed by the main firstmate. Work on your own; do not wait for a human.

# Charter
Supervise the alpha domain.

# Routing scope
Supervise the alpha domain.

# Project clones
- acme-api

# Operating model
You are in an isolated firstmate home. The local `AGENTS.md` is your job description, and your local `data/`, `state/`, `config/`, and `projects/` dirs are yours to operate.
The projects above are local clones for work you supervise; they are not an exclusive ownership claim.
Delegate project work to your own crewmates with the normal firstmate lifecycle: brief, spawn, status, watcher, steer, teardown, and recovery.
Do not invent a second delegation system.
You do not generate your own work.
Act only on tasks the main firstmate routes to you.
Never start a survey, audit, or "find improvements" sweep on your own initiative; that is not your job and it is unwanted.

# Requests from the main firstmate
You are a firstmate in your own home, so an incoming message reaches you in your own chat.
You must distinguish who it is from, because the answer goes to a different place.
A request relayed to you by the main firstmate is tagged with a leading `[fm-from-firstmate]` marker followed by an invisible system separator; this marker is untypable, so a human never produces it.
When a message carries that marker, do the work, then respond via the STATUS/ESCALATION path below, never only in this chat: the main firstmate does not read your chat, so a chat-only reply is lost.
Marked requests also carry a privacy-safe `corr=<id>` token after the marker; include that exact token in your parent status reply (or in the status pointer to a detailed doc) so the parent can correlate the answer.
Optional helper: `bin/fm-secondmate-report.sh` can append a correlated status line for you, but a plain `echo` that includes the same `corr=<id>` is equally valid - do not depend on the helper being present.
For a terse result, a status line is the whole answer.
For a detailed answer (an investigation, a plan, an audit), write it to a doc under your home's `data/` and append a status line that points to that doc - the scout-report pattern - so the main firstmate is woken and can read it.
Before treating an investigation or visual review as complete, load `decision-hold-lifecycle` from this home's `.agents/skills/` and pass its shared completion gate.
A message with NO marker is the captain typing directly into your pane: treat it as authoritative captain intervention and stay conversational exactly as you would for any captain message; do not force it onto the status path.

# Escalation to main firstmate
Handle routine work yourself.
Report only true captain-relevant outcomes or a declared external wait by appending one line:
   `echo "{state}: {one short line}" >> '/tmp/no-mistakes-evidence/01KYNFYC1ME3CM4KNJR30PC92Q/home/state/sm-alpha.status'`
States: working, needs-decision, blocked, paused, done, failed.
Use `paused: {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, or work ready for review.
This is also how you return the answer to a marked from-firstmate request above.
A marked request requires one correlated answer after the work; it does not require a separate receipt or start acknowledgement.
Never append `working:` merely to acknowledge receipt or announce that a marked request has started.
When a routed-work phase has a supervisor-actionable material change worth reporting under the rule above, give that reported phase a stable key.
If its first reportable event is `working [key=<work-slug>]: {material phase}`, use the same key on its later `paused`, `done`, `failed`, `needs-decision`, or `blocked` event so the earlier working phase is superseded.
When a keyed phase ends without another reportable state, append `resolved [key=<work-slug>]: {why it is no longer active}`.
When a decision you escalated is answered or a blocker clears and your domain resumes, append `resolved: {how it was decided or unblocked}` (keyed with `[key=<slug>]` if you opened it with one) so it is durably closed instead of resurfacing behind later unrelated events.
Routine internal supervision, heartbeats, retries, and crewmate churn stay inside your own home and must not touch that status file.

# Definition of done
You are persistent by default. Do not exit just because your queue is empty.
On startup and restart, run normal firstmate bootstrap and recovery through `bin/fm-session-start.sh` for your own home, but only to RECONCILE work that is already yours: in-flight crewmates, tracked backlog items, and durable watches recorded in this home.
When you have no assigned or in-flight work after that reconciliation, go idle and wait silently for the main firstmate to route you a task.
An empty queue is a healthy resting state, not a cue to invent work: never spawn a survey, audit, or any self-directed "find work" task on your own initiative.
If this charter cannot be carried out, append `blocked: {why}` or `failed: {why}` to the main status file and stop.
Evidence: TDD red-state proof: new assertions fail against base b6e351d fm-brief.sh

ok - fm-brief.sh: bash -n succeeds ok - fm-brief.sh: no heredoc is nested inside a command substitution (Bash 3.2 parse-safe) ok - fm-brief.sh: --help renders the complete header ok - fm-brief.sh: no-mistakes/direct-PR/local-only briefs generate cleanly ok - fm-brief.sh: faster paths use configured authority without stacked review ok - fm-brief.sh: no-mistakes DOD keeps its apostrophe prose, now parse-safe not ok - project-memory contract did not subordinate the generic guidance to task-specific constraints exit=1

ok - fm-brief.sh: bash -n succeeds
/tmp/fm-brief.dNXoiP/heredoc-in-substitution.sh:2
ok - fm-brief.sh: no heredoc is nested inside a command substitution (Bash 3.2 parse-safe)
ok - fm-brief.sh: --help renders the complete header
ok - fm-brief.sh: no-mistakes/direct-PR/local-only briefs generate cleanly
ok - fm-brief.sh: faster paths use configured authority without stacked review
ok - fm-brief.sh: no-mistakes DOD keeps its apostrophe prose, now parse-safe
not ok - project-memory contract did not subordinate the generic guidance to task-specific constraints
exit=1

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

🔧 **Review** - 4 issues found → auto-fixed (2) ✅
  • ⚠️ bin/fm-brief.sh:381 - For local-only projects PR_BODY_GUIDANCE is empty (lines 346-353), so the bare $PR_BODY_GUIDANCE line at 381 renders as a stray blank line inside the numbered Rules list, between rule 3 and rule 4. Verified by rendering a local-only brief: rules 1-3, blank line, then '4. Report status...'. no-mistakes and direct-PR briefs have no such gap. Fix mechanically by folding the PR guidance into the rule-3 block (e.g. append it to GITHUB_READ_GUIDANCE only when non-empty) and emitting a single variable.
  • ℹ️ bin/fm-brief.sh:349 - The closing-keyword lines are indented three spaces, so they render as a continuation of rule 3 ('For GitHub reads, prefer gh api ... Never poll merge-queue state'). A PR-authoring obligation is therefore presented as part of the GitHub-read preference rule rather than as its own rule, which weakens how a crewmate scans it. Consider giving it its own numbered rule or attaching it to the Definition-of-done PR step.
  • ℹ️ bin/fm-brief.sh:350 - The brief tells crewmates 'firstmate verifies issue state after merge regardless'. The intent requires this wording, so it is authorized, but no such duty exists in the repo: bin/fm-pr-check.sh / fm-pr-poll.sh track PR merge state only, AGENTS.md's post-merge wake handling (line 353) covers clone refresh, and no script or doc reads GitHub issue state. The crewmate is told a verification happens that nothing currently performs.
  • ℹ️ tests/fm-brief.test.sh:279 - assert_no_grep uses grep -F (case-sensitive), and the pattern 'If AGENTS.md or CLAUDE.md already exists...' now differs from the emitted line 'Otherwise, if AGENTS.md or CLAUDE.md already exists...' only by the capital I. The assertion proves a capitalization difference, not that the helper step became conditional; the two positive assertions above it carry the real coverage.

🔧 Fix: move PR closing-keyword step into definition of done
1 info still open:

  • ℹ️ bin/fm-brief.sh:315 - The standalone **PR body:** step is emitted after the sentence it constrains in both PR modes: in direct-PR it follows "push your branch and open a PR with gh-axi, then append done: PR {url} ... and stop" (line 313), and in no-mistakes it follows "Firstmate will then instruct you to run /no-mistakes to validate and ship a PR" (line 340), where the pipeline composes the body and the next paragraph says not to hand-edit while a run is active. A worker reading sequentially meets the body requirement after the step that creates the body. Moving the step above those sentences (or naming who carries the keyword into the pipeline-authored body) would make it unambiguous. Placement was the author's deliberate choice in the previous round, so this is a note, not a defect.

🔧 Fix: emit PR-body keyword step before PR creation
✅ Re-checked - no issues remain.

✅ **Test** - passed

✅ No issues found.

  • bash tests/fm-brief.test.sh — full suite green (18 checks), including the new test_issue_linked_ship_requires_pr_closing_keyword, test_github_rest_guidance_targets_crewmate_briefs, and the strengthened test_ship_project_memory_wording
  • TDD red-state proof: temporarily restored bin/fm-brief.sh from base b6e351d, re-ran bash tests/fm-brief.test.shnot ok - project-memory contract did not subordinate the generic guidance to task-specific constraints, exit 1; then restored head and confirmed git status --porcelain empty
  • Rendered end-user briefs through the CLI at head: FM_HOME=&lt;ev&gt; bin/fm-brief.sh ship-nm-issue841 acme-api, ... ship-directpr-issue338 direct-proj, ... ship-localonly-issue77 local-proj, ... scout-issue1190 acme-api --scout, FM_SECONDMATE_CHARTER=... bin/fm-brief.sh sm-alpha --secondmate acme-api
  • Rendered the same briefs from the base commit's script and built a base-vs-head phrase matrix over every intent-required and intent-forbidden phrase
  • Manually inspected the local-only brief: no closing keyword / PR body wording, and Rules numbering stays contiguous (rule 3 block → rule 4) after the REST guidance replaced the old rule 3
  • Manually inspected the secondmate charter: zero occurrences of Never poll merge-queue state and gh api repos/OWNER/REPO/...
  • git log --format=&#39;%B&#39; b6e351d..ca36646 | grep -i co-authored — no agent co-author trailer on any of the three commits
  • bash tests/fm-instruction-owners.test.sh, bash tests/fm-ask-user-authority.test.sh, bash tests/fm-secondmate-safety.test.sh — adjacent suites that reference fm-brief, all green
⚠️ **Document** - 1 warning
  • ⚠️ bin/fm-brief.sh:301 - Generated PR-producing briefs now tell crewmates "firstmate verifies issue state after merge regardless", but the owner of firstmate's post-merge duties (AGENTS.md section 7, "PR ready, landing, and teardown") records no issue-verification step - AGENTS.md contains zero mentions of GitHub issues, and no bin/ script (fm-pr-check.sh, fm-pr-merge.sh) reads issue state. The promise the scaffold makes to crewmates has no documented or implemented owner. I did not add it to AGENTS.md because recording a post-merge issue-verification duty would create new firstmate operating behavior rather than document an existing fact, which is outside this documentation phase and outside the stated intent. Decide whether firstmate genuinely owns that verification (then document it in AGENTS.md section 7 as a follow-up) or whether the brief wording should be softened.
⚠️ **Lint** - 1 warning
  • ⚠️ linter found issues (exit code 127)
✅ **Push** - passed

✅ No issues found.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ca36646bb8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread bin/fm-brief.sh
Comment on lines +204 to +205
3. For GitHub reads, prefer `gh api repos/OWNER/REPO/...` REST paths over `gh pr`/`gh issue` subcommands.
Use gh-axi for other GitHub operations and chrome-devtools-axi for browser operations.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep REST reads behind gh-axi

Captain, every generated ship and scout brief now explicitly directs workers to invoke raw gh api, contradicting the repository-wide requirement that GitHub operations use gh-axi and the following sentence in the same generated rule. This causes routine REST reads to bypass the required GitHub integration path; retain REST-specific guidance without instructing workers to call raw gh.

AGENTS.md reference: AGENTS.md:L153-L153

Useful? React with 👍 / 👎.

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.

1 participant