Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
4fdd73a
fix(tmux): target sessions with a trailing colon so numeric session n…
sandersjdd Jul 7, 2026
d5f70ae
no-mistakes(review): locale-safe herdr bare-prompt regex plus LC_ALL=…
sandersjdd Jul 7, 2026
9ddfd9d
feat(bin): add a durable dispatch log across spawn and teardown
sctru Jul 29, 2026
5198d49
fix(bin): blank dispatch-log repo field for secondmate spawns
sctru Aug 2, 2026
526b9a9
no-mistakes(document): docs(scripts): list fm-dispatch-log.sh in bin …
sctru Aug 2, 2026
45f4066
feat(bin): add a Claude-provider quota gate for crewmate/scout spawns
sctru Aug 2, 2026
ab3dc26
no-mistakes(review): Floor fractional quota percentRemaining; fix sta…
sctru Aug 2, 2026
9719a46
no-mistakes(document): docs(scripts,configuration): document fm-quota…
sctru Aug 2, 2026
b78f280
fix(turnend-guard): advise instead of blocking on another session's home
sctru Aug 24, 2026
aded7d3
no-mistakes(review): Gate foreign-home advisory bypass to --claude mo…
sctru Aug 25, 2026
2b04211
no-mistakes(document): docs(turnend-guard): document foreign-home adv…
sctru Aug 25, 2026
f053337
test: realign quota-gate and turnend-guard fixtures with current upst…
sctru Aug 30, 2026
f97544e
fix: never surface an orphaned status, turn-end, or check marker
sctru Aug 31, 2026
2e76bc3
no-mistakes(review): docs: pair CONTRIBUTING.md smoke test .status wi…
sctru Aug 31, 2026
c29cc99
no-mistakes(review): test: cover unregistered tool-updates orphan-gua…
sctru Aug 31, 2026
3225182
fix(bin): tell crews to pause status across a no-mistakes pipeline st…
sctru Sep 3, 2026
ab359e4
fix(bin): detect and clear a harness's first-launch trust dialog in f…
sctru Sep 3, 2026
2559e9e
Require configured nested dispatch profiles for crewmate child delega…
sctru Sep 19, 2026
87178c8
sync: merge upstream main into fork (#3)
sctru Sep 19, 2026
25b07bc
feat: add typed dispatch and crew safety gates (#4)
sctru Sep 19, 2026
0ac1f60
feat(bin): add opt-in intake classifier
sctru Sep 20, 2026
375410f
fix(test): remove duplicate test family cases
sctru Sep 20, 2026
63e8d46
feat(bin): add opt-in intake classifier
sctru Sep 20, 2026
ecb95b7
fix(test): remove duplicate test family cases
sctru Sep 20, 2026
2b75415
no-mistakes(review): Harden classifier curl and Score parsing
sctru Sep 20, 2026
3ba3f6f
no-mistakes(review): Gate implementation authorization only for ship
sctru Sep 20, 2026
1154fea
no-mistakes(review): Protect traced keys and unblock temporary failures
sctru Sep 20, 2026
030c39c
no-mistakes(review): Keep request I/O failures nonblocking
sctru Sep 20, 2026
724ebf9
no-mistakes(document): Document nonblocking classifier runtime failures
sctru Sep 20, 2026
5eefbbb
no-mistakes(document): Document shared typed-classifier key ownership
sctru Sep 20, 2026
25e633c
merge: preserve intake classifier pipeline fixes
sctru Sep 20, 2026
5877b71
fix: reconcile intake classifier pipeline fixes
sctru Sep 20, 2026
00eba29
no-mistakes(lint): Remove duplicate dispatch-resolve family pattern, …
sctru Sep 21, 2026
0f26f20
Fix CI regressions in intake classifier branch
sctru Sep 21, 2026
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
53 changes: 30 additions & 23 deletions .agents/skills/afk/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name: afk
description: >-
Enter the away posture when the captain invokes /afk, says they are going afk, `state/.afk-contract` or `state/.afk` exists, an incoming message starts with `FM_INJECT_MARK`, or any `state/.subsuper-*` marker is involved.
It records the captain's away words verbatim as the whole mandate, reads them back in plain sentences, writes the durable away-posture record after their go, announces hold-for-return only at entry, keeps the one supervision session running in the away posture (on Pi the supervision branch acts on the words by its own judgment and takes every safe actionable wake with main parked; the daemon still delivers batched digests on the other harnesses for now), and on the first unmarked message renders the return brief from durable records before ordinary work resumes.
It reads the captain's away words back as a mandate, writes the durable away-posture record after their go, announces hold-for-return only at entry, keeps the one supervision session running in the away posture (on Pi the supervision branch takes every safe actionable wake with main parked; the daemon still delivers batched digests on the other harnesses for now), and on the first unmarked message renders the return brief from durable records before ordinary work resumes.
user-invocable: true
metadata:
internal: true
Expand All @@ -11,26 +11,33 @@ metadata:
# afk

Away mode is a POSTURE of the one supervision session, not a second architecture.
Being away changes exactly two things: how the captain is informed, and what happens at a captain-owned decision point (hold for return, or the answer the captain's away words already gave).
Being away changes exactly two things: how the captain is informed, and what happens at a captain-owned decision point (hold for return, or later a pre-answered clause).
It never changes the authority set.
The posture is a file, `state/.afk-contract`, written only by `bin/fm-afk-contract.sh` after the captain confirms a read-back; nothing infers the posture from chat.
Hold-for-return is the default and the only reach profile this release records: there is no phone channel, and the entry announcement says so aloud every time.

## Entering: `/afk [words]`

1. **Record the captain's words, verbatim.**
The words are the whole mandate: `bin/fm-afk-contract.sh` records them exactly as given, with no clause fields, verbs, ids, or merge-grant list, and by the captain's mandate no parser, tokenizer, classifier, or grammar reads them anywhere.
Read `bin/fm-afk-contract.sh --help` for the flags rather than memorizing them.
Plain `/afk` with no words is a valid entry with no mandate.
1. **Translate the captain's words into mandate clauses.**
The words are recorded verbatim; the clauses are your reading of them as explicit fields `bin/fm-afk-contract.sh` records: an action from its fixed verb list, the object in the captain's words, and the stated precondition in the captain's words, plus an optional stop.
Read `bin/fm-afk-contract.sh --help` for the field flags, verb list, and coarse best-effort never-set flag rather than memorizing them.
No static parser reads the object or precondition text, by the captain's mandate: you supply the fields, the script records them verbatim, checks structural presence and the verb list, and may flag obvious never-set concepts without treating that best-effort scan as authoritative.
A flagged clause is still recorded, never refused, and the read-back and return brief show the flag; the flag can miss spellings, including joined compounds such as `oneTimeCode`, never fires on unrelated names such as `ping-service`, and authoritative never-set, forbidden-action, and precondition judgment belongs to the supervision session at execution time in phase 4.
Forbidden, destructive, irreversible, and security-sensitive actions are never pre-authorizable regardless of clause text, and no recorded clause is authority by itself.
Write only clauses the words actually support; a wish with no object or no stated precondition is not a clause.
Plain `/afk` with no words has no clauses.
2. **Propose and read back.**
Run `bin/fm-afk-launch.sh propose --words-file <path> [--expected-return <UTC ISO 8601>] [--spend <n>]` (or `--words <text>`); it writes the proposal and prints the record's read-back.
Then relay your own plain-sentence restatement of the words to the captain in `AGENTS.md` section 9 language - what you read them as asking for, sentence by sentence, never a numbered field list - beside the expected return, the spend cap, and the one-sentence reach announcement, so the captain can catch a misreading before saying go.
Say plainly which sentence, if any, you could not act on while away (a red merge, a discard, anything on the never-set, local-only landing), so the captain can restate it or accept that it waits for their return.
Run `bin/fm-afk-launch.sh propose --words-file <path> [--action <verb> --object <text> --when <text> [--stop <text>]]... [--expected-return <UTC ISO 8601>] [--spend <n>] [--grant <task-id>]...` (or `--words <text>`), and relay its read-back to the captain in `AGENTS.md` section 9 language: the accepted clauses as a numbered list, every refused clause with the part it is missing, the expected return, the spend cap, any merge-when-green task ids, and the one-sentence reach announcement.
When the captain names task ids that may merge while green, pass `--grant <id>` for each named id.
Never infer task ids from clause prose, object text, or the away words.
Red-check exceptions stay in the words or clause `when` text and are not executed.
A refused clause does not fail the proposal; the captain can restate it or leave it refused.
Exit 3 only means a clause was refused; the proposal stands.
3. **Confirm on the captain's go.**
Run `bin/fm-afk-launch.sh confirm`; it promotes the proposal into the record and prints the entry announcement.
Relay that announcement verbatim in spirit: hold-for-return only, no phone channel, your instructions are recorded and the away session will carry them out where it can, anything it is unsure of, or that needs you, waits for your return, and destructive, irreversible, and security-sensitive actions are never pre-authorizable whatever the words say.
With no words, run `propose` and `confirm` back to back; the announcement says no instructions were recorded.
Re-invoking `/afk` while already away with no new words is a refresh and leaves the standing record untouched; new words replace the mandate after the same read-back, preserve the original session entry, and archive the superseded words for the return brief.
Relay that announcement verbatim in spirit: hold-for-return only, no phone channel, anything that needs the captain waits for their return, N clauses recorded and M refused, recorded clauses are held for the return brief and are not executed by this release, and forbidden, destructive, irreversible, and security-sensitive actions are never pre-authorizable regardless of clause text because no recorded clause is authority by itself.
With no words, run `propose` and `confirm` back to back; the announcement is the same.
Re-invoking `/afk` while already away with no new words is a refresh and leaves the standing record untouched; new words replace the mandate after the same read-back, preserve the original session entry, and archive the superseded mandate for the return brief.
4. **Per harness, after the record exists:**
- **Pi and pi-signed**: stop here.
The away daemon is no longer launched on Pi; the ordinary supervision session (`docs/pi-supervision-branch.md`) keeps running with the record present, and `bin/fm-afk-launch.sh start` refuses on these harnesses.
Expand All @@ -51,11 +58,10 @@ Hold-for-return is the default and the only reach profile this release records:

- The record exists, so the watcher never rechecks an item held for the captain, in either supervision shape; the return brief lists it instead.
Declared external waits keep their condition-aware, hours-long recheck cadence (`bin/fm-watch.sh`, `bin/fm-classify-lib.sh`).
- The away session acts on the captain's words.
It reads them at the tail of every wake, decides by its own judgment whether the event in front of it is the moment they name, acts on them only through the guarded scripts under standing authority, never by analogy, holds with verdict captain on doubt, and opens every outcome summary for an action taken under the words with "per your away instructions:" (`bin/fm-branch-prompt.sh` "Postures" owns the execution rules).
Destructive, irreversible, and security-sensitive actions are never pre-authorizable whatever the words say, and ask-user findings keep the `ask-user-authority` policy unless the words pre-answer the exact decision; anything else that needs the captain holds for their return.
- On Pi, main is parked and the supervision branch handles every safe actionable wake under main's standing authority, through the same guarded scripts main would use: any pull request green at its live head may merge (which one the words meant is the branch's reading), queued work whose blockers cleared - already queued, or filed by the branch because the words explicitly call for it - dispatches within the spend cap, and a decision is answered with the captain's own pre-stated answer or under `ask-user-authority`.
Anything else holds for the return, a red merge never proceeds while away, local-only landing always waits for the captain, and only a wake the branch declines (including a broken branch or unsafe scan) or a watcher failure wakes main (`docs/pi-supervision-branch.md` "Postures").
- Recorded clauses are not executed by this release.
Forbidden, destructive, irreversible, and security-sensitive actions are never pre-authorizable regardless of clause text, no recorded clause is authority by itself, and merge authority plus ask-user findings keep exactly the rules they have when attended (`AGENTS.md` section 7 and `ask-user-authority`); anything that needs the captain holds for their return.
- On Pi, main is parked and the supervision branch handles every safe actionable wake under main's standing authority plus the record's merge grants, through the same guarded scripts main would use: a granted or `yolo` task merges only green at its live head, already-queued work whose blockers cleared dispatches within the spend cap, and only a finding `ask-user-authority` lets firstmate decide is answered.
Anything else holds for the return, local-only landing always waits for the captain, and only a wake the branch declines (including a broken branch or unsafe scan) or a watcher failure wakes main (`docs/pi-supervision-branch.md` "Postures").
- The session-start digest reports the posture under its AFK subsection, so a restart re-enters the posture from the record, not from memory.

## How to exit: the return
Expand All @@ -65,9 +71,9 @@ No `/back` is needed. The first genuine message is the return signal:
- A message **without** the current operational prefix or a legacy bare marker, and **not** starting with `/afk` -> the captain is back.
Run `bin/fm-afk-return.sh` before acting on the message that brought the captain back.
That script owns the correct-ordered daemon shutdown where a daemon ran, the archive of the posture record, durable wake presentation and post-handling acknowledgement, escalation and wedge evidence, the return brief, and the return-catch-up gate.
Relay the return brief in section 9 language and in its own order: supervisor health across the away window first (any gap leads), then the captain's instructions verbatim with the away session's account of every action it took under them, then what is waiting on the captain, then what was tried and failed or could not be fixed, then what was handled, then cost.
Relay the return brief in section 9 language and in its own order: supervisor health across the away window first (any gap leads), then every clause and that it was recorded only, then what is waiting on the captain, then what was tried and failed or could not be fixed, then what was handled, then cost.
The gate keeps every open `blocked:` event until that blocker's own resolution is proven: remediate each immediately through the normal lifecycle, or explicitly reclassify it with a durable reason and close its decision key with `resolved [key=...]`, then run `bin/fm-afk-return.sh check`.
Captain-verdict outcomes are listed under "waiting on you", but do not exempt open blockers: per-blocker provenance is deferred with no owner, and the gate fails safe by keeping every open blocker.
Captain-verdict outcomes are listed under "waiting on you", but do not exempt open blockers because per-blocker provenance is deferred to phase 4.
Once the record is archived, resume full per-wake responsiveness through the emitted primary-harness supervision protocol while blocker handling proceeds, so the gate never creates a blind wait.
A Bearings request may be answered while the gate is open, and the digest surfaces the catch-up state as a Charted Next `(return-catchup)` warning row naming what still holds it.
Acting on the fleet - dispatching, steering, merging, or any other ordinary captain work - still waits until the check exits successfully.
Expand All @@ -82,13 +88,14 @@ When the captain wants this same token-saving supervision while staying present
afk changes how the captain is informed and what happens at a captain-owned decision point, **not who approves what**.
"Away" never means "approves more" or "approves less."
A PR ready for merge keeps the merge authority from `AGENTS.md` section 7, and a needs-decision finding keeps the `ask-user-authority` policy; anything requiring the captain still waits for the captain's explicit word.
While the away-posture record exists, any pull request green at its live head may merge under away authority; which one the captain's words meant is the away session's reading, and a merge the words do not call for holds for the return.
Away authority never releases a captain hold, and it expires when the away record is archived.
While the away-posture record exists, a merge proceeds only when that task's recorded yolo posture is on or its id is in the record's merge-grant list; otherwise it is held for the captain's return.
A merge grant never releases a captain hold, and it expires when the away record is archived.
`--allow-red` remains attended-only and is refused while the record exists.
A merge under away authority must be synchronous; `fm-pr-merge.sh` refuses auto-merge and any GitHub queue state that cannot prove an immediate merge while the record exists.
The same gates bind whichever actor performs the action: on Pi the parked main's standing authority relocates to the supervision branch, which meets exactly these rules, and the spend cap recorded at entry is enforced by `fm-spawn.sh` for both actors while the record exists.
The captain's away words are their explicit instruction given before leaving, recorded verbatim and acted on by the away session's judgment at the moment an event makes them relevant; the words cover nothing they do not say, are never applied by analogy, and die at archive.
Destructive, irreversible, and security-sensitive actions are never pre-authorizable whatever the words say.
A mandate clause is the captain's explicit instruction given before leaving, recorded with its named object and condition; a clause is never inferred, never applied by analogy, and expires at return.
Forbidden, destructive, irreversible, and security-sensitive actions are never pre-authorizable regardless of clause text, and no recorded clause is authority by itself.
This release records clauses and does not execute them.

## The daemon, where it still runs

Expand Down
15 changes: 15 additions & 0 deletions .agents/skills/backlog-operations/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
name: backlog-operations
description: >-
Agent-only intake reference for deciding what to do with a captain request.
Load before using the opt-in System One intake classifier.
user-invocable: false
metadata:
internal: true
---

# backlog-operations

Before classifying a captain request, run the opt-in `bin/fm-intake-classify.sh` directly on the request file in the same turn.
Its result recommends only `ship`, `scout`, or `answer_now` with urgency and never authorizes a spawn or replaces your intake judgment.
`docs/configuration.md` "Typed intake classification" owns the complete contract and every status meaning.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Use the router's detection and safety sections for static crew and secondmate ha
`config/crew-dispatch.json` can override that static default for one crewmate or scout with concrete harness, model, and effort axes.
For a profile array, load `quota-array-dispatch` after establishing harness and provider facts here.
When the opt-in `bin/fm-dispatch-resolve.sh` is on, its `clear` answer already names the concrete axes; `docs/configuration.md` "Typed dispatch resolution" owns that contract.
At request intake, `bin/fm-intake-classify.sh` is an advisory disposition recommendation only; `docs/configuration.md` "Typed intake classification" owns its contract.

`../secondmate-provisioning/SKILL.md` owns inherited local material.
Its harness consequence is that a secondmate's workers receive literal `config/crew-harness` and `config/crew-dispatch.json`, while the primary-only `config/secondmate-harness` is never inherited because secondmates do not spawn secondmates.
Expand All @@ -18,7 +19,8 @@ The inherited dispatch file applies the same best-fit profiles there.
## Owners

`../../../bin/fm-spawn.sh` owns launch, autonomy, concrete flags, task-kind compatibility, and worker turn-end wiring.
Natural-language rules stay with firstmate, while scripts receive concrete axes.
Natural-language rules stay with firstmate for fleet intake, while a worker classifies its native child under the generated nested-routing contract and routes any matched profile array back to Firstmate for resolution.
Scripts receive concrete axes.

`../../../bin/fm-busy-lib.sh` owns semantic busy trust.
Composer shapes, glyphs, placeholders, popups, rendered delivery signals, and the `empty` / `pending` / `pending-unproven` / `unknown` decision belong only to `../../../bin/fm-composer-lib.sh`.
Expand Down
Loading