Skip to content
Closed
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
13 changes: 13 additions & 0 deletions .fm-outward-allow
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Identifiers that bin/fm-outward-text-check.sh would otherwise report, kept
# here because a reader of this repository really can resolve them.
# One token per line; `#` starts a comment. See docs/outward-facing-text.md.
#
# Adding a line is the reviewable act that justifies a new outward reference,
# and it settles REVIEWABLE findings only: an unresolvable object id or a URL
# naming another repository.
#
# A machine-local path, a private task id, or another project's name is
# blocking and can never be settled here. Recording one would publish, in a
# tracked file, the exact identifier the check exists to keep unpublished, so
# the check reports such an entry alongside the finding instead of honoring it.
# Those belong out of the published text, not in this file.
14 changes: 14 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,12 @@ jobs:
name: Repo invariants
runs-on: ubuntu-latest
steps:
# Full history: the outward-text check decides whether an id resolves in
# THIS repository, so a shallow clone would report the repo's own commits
# as foreign.
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Symlinks must stay intact
run: |
set -eu
Expand All @@ -387,3 +392,12 @@ jobs:
printf '%s\n' "$tracked"
exit 1
fi
# Backstop for the prose and the commit messages this branch publishes into
# the repository. This step runs without --home, so a machine-local path is
# the only blocking category that can fail it; private fleet identifiers
# (a foreign task id, another project's name) are caught at the worker's
# pre-publication check, which runs where a firstmate home exists.
# Unresolvable ids are printed for review because a named upstream can make
# one legitimate, and .fm-outward-allow settles those once.
- name: Added prose and commit messages must not carry foreign identifiers
run: bin/fm-outward-text-check.sh --diff --block-only
2 changes: 2 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,8 @@ Preserve durable structured identifiers, dependencies, and completion artifact l
`bin/fm-brief.sh` and its help own scaffold syntax, generated variants, status protocol, delivery-mode definitions of done, and exact safety mechanics.
Use its scaffold as the contract, then replace every `{TASK}` placeholder with a clear task description, acceptance criteria, constraints, and necessary context before dispatch or seeding.
Keep additions task-specific rather than repeating lifecycle instructions, and alter generated sections only when the task genuinely differs from the standard shape.
A ship brief's `# Task` section is the source of the published PR description, so scope every identifier in it to the repository under change and keep another repository's commit ids, another task's name, and machine-local paths out of it, while keeping the accepted requirements whole.
[`docs/outward-facing-text.md`](docs/outward-facing-text.md) owns that contract, and the generated brief carries the worker's own pre-publication check.

Every ship brief must retain the worktree-isolation assertion and stop if launched in the primary checkout.
If a ship task touches firstmate's shared tracked material, explicitly require `firstmate-coding-guidelines` before editing.
Expand Down
2 changes: 2 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ See the [no-mistakes quick start](https://kunchenguid.github.io/no-mistakes/star
- Harness-adapter ownership spans detection in `bin/fm-harness.sh`, launch and hook mechanics in `bin/fm-spawn.sh`, semantic busy sources and trust gates in `bin/fm-busy-lib.sh`, delivery-only rendered guards in `bin/fm-composer-lib.sh`, cleanup in `bin/fm-teardown.sh`, and facts in `.agents/skills/harness-adapters/SKILL.md`; the `firstmate-coding-guidelines` skill owns the validation policy for checks that depend on those harnesses.
- Changes to runtime session backends (`bin/fm-backend.sh`, `bin/backends/`, and the scripts that dispatch through them) keep current setup and limits in the relevant backend guide and active empirical evidence in [`docs/verification/runtime-backends.md`](docs/verification/runtime-backends.md).
- [`docs/documentation-audiences.md`](docs/documentation-audiences.md) and its machine-consumed inventory own prose classification; run `bin/fm-doc-audience-check.sh` after documentation changes.
- [`docs/outward-facing-text.md`](docs/outward-facing-text.md) owns what may appear in text this repository publishes and never retracts - a PR title, a PR description, a commit message, tracked prose.
Every identifier must be resolvable by a reader holding this repository alone; run `bin/fm-outward-text-check.sh --diff` before pushing, and record a genuinely resolvable upstream reference in `.fm-outward-allow` in the same change.
- In Markdown, put each full sentence on its own line.
- `README.md` stays a concise overview plus pointers: it never carries a wall of inline detail.
Route detail to the most specific `docs/` file (architecture, configuration, or a backend guide) and link to it instead.
Expand Down
15 changes: 15 additions & 0 deletions bin/fm-brief.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@
# to launch a ship task whose explicit --mode disagrees, so an adjusted brief and the
# recorded task metadata cannot drift apart.
# Ship briefs begin with a worktree-isolation assertion before the branch step.
# The no-mistakes and direct-PR briefs, the two that publish text outward, require
# the worker to scan the run intent or the PR body with bin/fm-outward-text-check.sh
# before publishing it. The local-only brief carries no such step because it
# publishes nothing outward.
# docs/outward-facing-text.md owns what that scan enforces.
# --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.
# There is no --yolo flag here. The worker never owns approval decisions, so yolo is
Expand Down Expand Up @@ -177,6 +182,10 @@ shell_quote() {
}

STATUS_FILE=$(shell_quote "$STATE/$ID.status")
# The pre-publication scan for the two ship modes that publish text outward.
# --task names this task so its own id, already public through the branch name,
# is not reported back as foreign.
OUTWARD_CHECK="$FM_ROOT/bin/fm-outward-text-check.sh --home $(shell_quote "$FM_HOME") --task $ID"

if [ "$KIND" = secondmate ]; then
SECONDMATE_PROJECTS=""
Expand Down Expand Up @@ -362,6 +371,10 @@ This task ships **direct-PR**: you raise the PR yourself, without the no-mistake
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.
Do NOT run /no-mistakes. The configured merge authority decides whether to merge the PR; firstmate relays the outcome.

Before you open the PR, write its title and description to a file and check that file with \`$OUTWARD_CHECK <file>\`.
A published PR description stays readable even after the PR is closed, so it may carry only what a reader holding this repository alone could resolve.
Clear every finding by removing the identifier, never by dropping accepted requirements - the requirements are exactly what the description is for.
EOF
;;
local-only)
Expand Down Expand Up @@ -391,6 +404,8 @@ 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.
When starting no-mistakes, make \`--intent\` preserve all relevant content from this brief's \`# Task\` section plus every later accepted Firstmate requirement, clarification, constraint, exclusion, and supersession, carrying only each requirement's current accepted form; retain direct requirements instead of substituting a diff summary, and exclude generic operational, status, delivery, and other scaffold boilerplate unless it is task-specific.
no-mistakes publishes that intent as the PR description, and a published description stays readable even after the PR is closed, so write the intent to a file and check that file with \`$OUTWARD_CHECK <file>\` BEFORE you start the run.
The intent may carry only what a reader holding this repository alone could resolve; clear every finding by removing the identifier, never by dropping accepted requirements, which are exactly what the intent is for.
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:
Expand Down
Loading