From fab71d45b6bed7054249a79bddd07003ab0137f0 Mon Sep 17 00:00:00 2001 From: Trillium Smith Date: Fri, 31 Jul 2026 10:12:55 -0700 Subject: [PATCH 1/2] wire lifecycle labels to bd dispatch and claim flow for mg badge rendering - fm-bead-stamp.sh: add lifecycle=sent label on dispatch (alongside dispatch=sent) - fm-brief-hooks.d/beads.sh: add lifecycle=claimed label to Bead Receipt (alongside dispatch=claimed) This enables the mg board to render lifecycle state as gold badges. The dispatch/lifecycle metadata remains for data tracking; set-state labels are the render channel for mg visibility. --- bin/fm-bead-stamp.sh | 46 +++++++++++++++++++++++++++++++++++ bin/fm-brief-hooks.d/beads.sh | 22 +++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100755 bin/fm-bead-stamp.sh create mode 100755 bin/fm-brief-hooks.d/beads.sh diff --git a/bin/fm-bead-stamp.sh b/bin/fm-bead-stamp.sh new file mode 100755 index 0000000000..4238572e63 --- /dev/null +++ b/bin/fm-bead-stamp.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +# Stamp a linked bead as dispatched: sets its dispatch=sent state dimension and +# assigns it to the launched agent. Called by fm-spawn.sh after a successful +# spawn when the task was launched with --beads . +# Fail-open by design: a missing `task` CLI, an empty beads id, or a bead the +# CLI cannot find warns on stderr and exits 0 so a bead-tracking problem never +# blocks or fails a spawn. +# Usage: fm-bead-stamp.sh +set -u + +BEADS_ID=${1-} +AGENT=${2-} + +if [ -z "$BEADS_ID" ]; then + echo "warning: no bead id given, skipping stamp" >&2 + exit 0 +fi + +if ! command -v task >/dev/null 2>&1; then + echo "warning: task CLI not found on PATH, skipping stamp for $BEADS_ID" >&2 + exit 0 +fi + +if [ -z "$AGENT" ]; then + echo "warning: no agent name given, skipping stamp for $BEADS_ID" >&2 + exit 0 +fi + +if ! task show "$BEADS_ID" >/dev/null 2>&1; then + echo "warning: bead $BEADS_ID not found, skipping stamp" >&2 + exit 0 +fi + +if ! task set-state "$BEADS_ID" dispatch=sent --reason "dispatched: agent=$AGENT" >/dev/null 2>&1; then + echo "warning: could not set dispatch=sent on bead $BEADS_ID" >&2 +fi + +if ! task set-state "$BEADS_ID" lifecycle=sent --reason "dispatched: agent=$AGENT" >/dev/null 2>&1; then + echo "warning: could not set lifecycle=sent on bead $BEADS_ID" >&2 +fi + +if ! task assign "$BEADS_ID" "$AGENT" >/dev/null 2>&1; then + echo "warning: could not assign bead $BEADS_ID to $AGENT" >&2 +fi + +exit 0 diff --git a/bin/fm-brief-hooks.d/beads.sh b/bin/fm-brief-hooks.d/beads.sh new file mode 100755 index 0000000000..ab13645df3 --- /dev/null +++ b/bin/fm-brief-hooks.d/beads.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +# fm-brief.sh hook: when FM_HOOK_BEADS_ID is set, emit the Bead Receipt and +# Bead Closure brief sections. Sourced by fm-brief.sh inside a subshell, which +# captures this script's stdout and prepends it to the generated brief. +# A bare `exit 0` below only ends that subshell, never fm-brief.sh itself. +set -u + +[ -n "${FM_HOOK_BEADS_ID:-}" ] || exit 0 + +cat <
Date: Fri, 31 Jul 2026 10:26:17 -0700 Subject: [PATCH 2/2] no-mistakes(document): Synced all documentation with beads lifecycle-tracking feature implementation. --- AGENTS.md | 2 ++ bin/fm-brief.sh | 6 ++++++ bin/fm-spawn.sh | 5 +++++ docs/scripts.md | 3 ++- 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index e9a36aa908..21cb67090a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -259,6 +259,7 @@ Write the task-specific brief under section 11 before spawning. Spawn only through `bin/fm-spawn.sh` after the profile and backend checks in section 4. The spawn must resolve a genuine isolated task worktree distinct from the primary checkout; a failed isolation assertion stops the task. After spawning, confirm the worker is processing the brief, handle any trust dialog through `harness-adapters`, and record ship or scout work as under way. +When spawning with `--beads `, the task is linked to an external bead item for progress tracking on `mg` or similar tools; `fm-bead-stamp.sh` stamps the bead's `dispatch=sent` and `lifecycle=sent` state dimensions, and the generated brief includes instructions for the worker to confirm `dispatch=claimed` and `lifecycle=claimed` after reading, and to close the bead on completion. A persistent secondmate is recorded in the secondmate registry and runtime state, never as a backlog work item. Steer a worker with short single-line messages through fail-closed `fm-send`; put long instructions in a file. @@ -455,6 +456,7 @@ Every ship brief must retain the worktree-isolation assertion and stop if launch If a ship task touches firstmate's shared tracked material, explicitly require `firstmate-coding-guidelines` before editing. If a task will drive Herdr lifecycle behavior, scaffold with `--herdr-lab`; if that need appears after an unguarded scaffold, stop and regenerate rather than adding commands by hand. The generated Herdr contract must use a named non-`default` isolated lab and its guarded helper for every lifecycle action. +When a task is linked to an external bead (via `--beads ` at spawn), set `FM_HOOK_BEADS_ID=` before scaffolding so the brief receives Bead Receipt and Bead Closure sections that guide the worker's interaction with the tracking system. Load `secondmate-provisioning` before creating or using a charter brief and preserve its idle-by-default and marked-return-channel contracts. Status appends are sparse supervisor-actionable events, not routine progress; `bin/fm-classify-lib.sh` owns keyed open and resolved semantics. diff --git a/bin/fm-brief.sh b/bin/fm-brief.sh index 8125aa2e9e..1494d95818 100755 --- a/bin/fm-brief.sh +++ b/bin/fm-brief.sh @@ -26,6 +26,12 @@ # The flag must be explicit because {TASK} is filled after scaffolding and the # caller-supplied repo string cannot reliably identify this repo. Briefs made # without it carry a loud declaration so an omitted contract cannot be silent. +# Hook system: when environment variables like FM_HOOK_BEADS_ID are set, executable +# scripts in fm-brief-hooks.d/ are sourced in a subshell during scaffolding, and their +# stdout is prepended to the generated brief. The beads hook (fm-brief-hooks.d/beads.sh) +# is automatically invoked when FM_HOOK_BEADS_ID is set, adding Bead Receipt and +# Bead Closure sections that ask the worker to confirm dispatch/lifecycle state changes +# and close the bead on completion. # For ship tasks, the definition of done is shaped by the project's delivery mode # (data/projects.md via fm-project-mode.sh; see the project-management skill # and AGENTS.md task lifecycle): diff --git a/bin/fm-spawn.sh b/bin/fm-spawn.sh index 78f8d79846..0c0595827b 100755 --- a/bin/fm-spawn.sh +++ b/bin/fm-spawn.sh @@ -81,6 +81,11 @@ # --scout records kind=scout in the task's meta (report deliverable, scratch worktree; # see AGENTS.md task lifecycle); --secondmate records kind=secondmate and launches in a # provisioned firstmate home; the default is kind=ship. +# --beads links this task to an external bead item for lifecycle tracking: the +# dispatch=sent and lifecycle=sent state dimensions are stamped via fm-bead-stamp.sh +# after spawn, and the brief includes Bead Receipt/Closure sections (when FM_HOOK_BEADS_ID +# is set) asking the worker to confirm dispatch=claimed/lifecycle=claimed and close the +# bead on completion. # Before a secondmate launch, the home is locally fast-forwarded to the primary # default-branch commit when safe; skipped syncs warn and launch unchanged. # Ship/scout spawns refuse to launch unless the resolved task path is a real diff --git a/docs/scripts.md b/docs/scripts.md index 6a10d1310a..d7963725cd 100644 --- a/docs/scripts.md +++ b/docs/scripts.md @@ -18,7 +18,8 @@ The shared no-mistakes gate refusal for fleet lifecycle entrypoints is summarize | `fm-update.sh` | Fast-forward-only self-update of firstmate and secondmate homes from origin | | `fm-backlog-handoff.sh` | Validate and delegate queued backlog-item moves into a secondmate home | | `fm-decision-hold.sh` | Create, verify, complete, and resolve durable captain-held decisions | -| `fm-brief.sh` | Scaffold ship, scout, secondmate-charter, and Herdr-lab briefs | +| `fm-brief.sh` | Scaffold ship, scout, secondmate-charter, and Herdr-lab briefs; load hooks when FM_HOOK_BEADS_ID or other hook env vars are set | +| `fm-bead-stamp.sh` | Stamp a linked bead's dispatch and lifecycle state when a task is spawned with --beads | | `fm-herdr-lab.sh` | Provision and guardedly operate an isolated, never-default Herdr lab session | | `fm-install-herdr.sh` | Install CI's exact-version Herdr pin with official asset URL, SHA-256, and protocol checks | | `fm-install-treehouse.sh`| Install CI's exact-version Treehouse pin for real-Herdr E2E that needs spawn worktrees |