Skip to content
Merged
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
30 changes: 30 additions & 0 deletions .agents/skills/aside/SKILL.md
Original file line number Diff line number Diff line change
@@ -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-<topic>`) 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 <id> <repo-name> --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/<id>.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/<id>/report.md`, then append `done: <one-line outcome>` to `state/<id>.status`.
3. Spawn it: `bin/fm-spawn.sh <id> <working-dir> --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/<id>/report.md`, relay the outcome to the captain, and tear the window down with `bin/fm-teardown.sh <id>`.

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:`.
4 changes: 4 additions & 0 deletions docs/documentation-audiences.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
4 changes: 3 additions & 1 deletion tests/fm-send-popup-settle.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -79,7 +80,8 @@ first_settle() { # <expected> <label> <harness|--explicit> <message> [selector-
local expected=$1 label=$2 harness=$3 msg=$4
local selector_form=${5:-legacy}
local dir fb log home target rc first meta_id
dir="$TMP_ROOT/case-$RANDOM"; mkdir -p "$dir/state"
POPUP_CASE_INDEX=$((POPUP_CASE_INDEX + 1))
dir="$TMP_ROOT/case-$POPUP_CASE_INDEX"; mkdir -p "$dir/state"
fb=$(make_stubs "$dir"); log="$dir/sleep.log"; home="$dir"
if [ "$harness" = --explicit ]; then
target="sess:win"
Expand Down
Loading