diff --git a/.agents/skills/aside/SKILL.md b/.agents/skills/aside/SKILL.md new file mode 100644 index 0000000000..d94e9f0c3b --- /dev/null +++ b/.agents/skills/aside/SKILL.md @@ -0,0 +1,30 @@ +--- +name: aside +description: >- + Open a dedicated interactive window the captain talks to directly for ad-hoc, multi-turn context-gathering, then hand the outcome back to the main firstmate. + Invoke when the captain says /aside, wants a side conversation or scratch space for a topic, or asks to work something out interactively instead of loading it into the main chat. +user-invocable: true +metadata: + internal: true +--- + +# aside + +An aside is an interactive scout: a scout-shaped window the captain converses with DIRECTLY to gather context, that concludes back to the main firstmate. +This is a deliberate captain opt-in that bends hard rule 4 (a crewmate never addresses the captain) for this one session only; every other supervision and safety rule still holds. +Keep it minimal - this is a chat space, not project work, so no PR and no lavish unless the captain asks. + +1. Resolve a short task id (e.g. `aside-`) and a working directory: the relevant project clone under `projects/` if the aside is about one, otherwise this firstmate repo so the window still gets an isolated scratch worktree. +2. Scaffold a scout brief: `bin/fm-brief.sh --scout`. + Replace `{TASK}` with the aside contract: this is an INTERACTIVE, captain-facing session; talk to the captain directly in this window (a deliberate bend of hard rule 4); gather context on the topic through as many turns as the captain wants; do NOT do project work or open a PR. + Replace the scaffold's `Work on your own; do not wait for a human` clause with an explicit override: this session MUST wait for the captain and converse with the captain directly across turns. + Replace the scaffold's external-wait-only `paused:` clause with an explicit override: append `paused: awaiting captain` to `state/.status` after every turn that awaits the captain's reply, treating that bounded human-wait as healthy idle. + Replace the scout's self-determined completion trigger with an explicit override: the session MUST NOT conclude because it judges the topic settled, complete, or resolved. + Only the captain explicitly saying they are done triggers handback: write the outcome to `data//report.md`, then append `done: ` to `state/.status`. +3. Spawn it: `bin/fm-spawn.sh --scout`. +4. Tell the captain, in plain language, which window to switch to (the `window=` value the spawn printed) to start the conversation. + Then resume ordinary supervision; the aside runs on its own and wakes firstmate through its status line. +5. On the `done:` status, read `data//report.md`, relay the outcome to the captain, and tear the window down with `bin/fm-teardown.sh `. + +Steer the session only if needed with a short `bin/fm-send.sh` line; the captain drives it directly, so firstmate normally stays out of the way until it concludes. +Reconcile an aside's `paused: awaiting captain` idle as healthy: it is a captain conversation in progress, not a stalled worker, so leave the window alone and recheck on the long paused cadence until it reports `done:`. diff --git a/docs/documentation-audiences.json b/docs/documentation-audiences.json index 9e3d4432a1..d7d606c85f 100644 --- a/docs/documentation-audiences.json +++ b/docs/documentation-audiences.json @@ -116,6 +116,10 @@ "path": ".agents/skills/ahoy/SKILL.md", "audience": "agent-runtime" }, + { + "path": ".agents/skills/aside/SKILL.md", + "audience": "agent-runtime" + }, { "path": ".agents/skills/ask-user-authority/SKILL.md", "audience": "agent-runtime" diff --git a/tests/fm-send-popup-settle.test.sh b/tests/fm-send-popup-settle.test.sh index f9d5552807..e180a7333f 100755 --- a/tests/fm-send-popup-settle.test.sh +++ b/tests/fm-send-popup-settle.test.sh @@ -37,6 +37,7 @@ set -u SEND="$ROOT/bin/fm-send.sh" TMP_ROOT=$(fm_test_tmproot fm-send-popup-settle) +POPUP_CASE_INDEX=0 # Same stub shape as fm-send-settle.test.sh: a fake tmux that drives the submit # path to a clean "empty" verdict on the first Enter, and a fake sleep that records @@ -79,7 +80,8 @@ first_settle() { #