flower
/
All briefs
complete draft note flower

Spawn setup polish: naming, concrete cadence/heartbeat config, MIA detection, agent-tool config (pre-refine-daemon gate)

canonical · plan

Spec

markdown

hand-off · dispatch

Dispatch

Auto-dispatch

when it reaches planned

Design-loop

design pass before build

This brief is complete — dispatch is closed.

#15 done fresh flower · flower/spawn-polish
You are being dispatched from flower Brief #34: Spawn setup polish: naming, concrete cadence/heartbeat config, MIA detection, agent-tool config (pre-refine-daemon gate)

Recall pointer:
- Use recall_brief with id 34 for the full folder if you need provenance.

Target:
- project: flower (/Users/mikeferrara/Documents/code/flower)
- branch: flower/spawn-polish
- worktree: not specified
- kind: fresh

Current brief spec:
## Goal
Make the /roster daemon-spawn setup (#22) **fully working + trustworthy** before any autonomous
daemon (esp. the refine daemon #27) is turned loose. All items from the operator's review of the
spawn UI (brief #22 event 266). **This + #22 live-spawn enablement = the gate before #27.**

## Items

### 1. Charter agent-name: double-prefix bug + collision check
- **Bug:** previewing role=refine for project=flower yields `You are flower-flower-refine …` —
  `SpawnPacketService::variables()` builds `AGENT_NAME = 'flower-'.$project->slug.'-'.$role->value`,
  doubling "flower" when the slug is "flower". Fix so it never double-prefixes (don't prepend
  `flower-` when the slug already leads with it, or switch to `{slug}-{role}` / `{role}@{slug}`).
- **Collision check:** before spawning, check Solo for an existing agent/process with that name;
  if one exists, fail with a clear message or auto-suffix — never silently create a duplicate-named
  daemon.

### 2. Heartbeat cadence as config + MIA detection
- Add a flower config key for the daemon **heartbeat interval** (default ≤ 30 min; "checkin on each
  loop/wake AND at least every N min"). The charter must state the CONCRETE cadence, not "when due".
- Use it for **MIA detection**: a daemon with no checkin within its expected window (heartbeat
  interval + grace) reads missing/stale on the roster.
- **GUARD:** a daemon legitimately on a slow/dormant poll must NOT be falsely marked missing — the
  expected window must derive from the daemon's CURRENT cadence, not a fixed short value.

### 3. Polling cadence as concrete config values
- Replace the charter's vague "quickly / slower / slowest" with concrete configured values
  (e.g. fast=Xs, slow=Ymin, dormant=Zmin), so there's no interpretation — and so we can tell whether
  a daemon SHOULD have acted by now (expected-action window per cadence). Reflect in the charter text.

### 4. Agent-tool config for live spawn
- Pre-flight flagged **"SOLO_AGENT_TOOL_ID is not configured"** — the bridge needs a Solo agent tool
  id to spawn. Decide + configure which runtime daemons spawn as (recommend **Claude**, the harness
  that gets the full flower tool surface after the #29 pagination fix), via config/flower.php
  (`SOLO_DAEMON_AGENT_TOOL_ID` / `SOLO_AGENT_TOOL_ID`). Surface a clear config error when unset.
- (Pre-flight also correctly flagged active operator sessions `flower-ops` / `flower-orchestrator` —
  working as intended; the guard blocks spawning into a project with active operator sessions.)

## Acceptance
- Charter agent name correct (no double-prefix) + collision-checked against Solo before spawn.
- Heartbeat + polling cadences are concrete config values reflected in the charter
  (`SpawnPacketService`), with MIA / expected-action detection that respects the daemon's current
  cadence (no false-missing on a long poll).
- `SOLO_(DAEMON_)AGENT_TOOL_ID` configurable + validated; pre-flight clears when set.
- Tests; suite green. `Brief: #34` trailer.

## Gates / relations
Builds on #22 (spawn bridge + UI); belongs to the daemon-roster epic (#11). This + #22 live-spawn
enablement = "spawn setup fully working" — the operator's gate before starting the refine daemon (#27).

## Provenance
Operator #22 UI review (2026-07-01, brief #22 event 266): naming double-prefix + collision, undefined
heartbeat cadence, vague polling cadence, and unconfigured agent-tool id.

Recent/key trace events:
[1] participant_joined flower-orchestrator: (no body)
[2] note_added flower-orchestrator: From operator review of the /roster spawn UI (brief #22 event 266). Makes daemon-spawn fully working + trustworthy. Together with #22 live-spawn enablement, this is the gate the operator set before starting the refine daemon (#27).
[3] plan_proposed flower-orchestrator: ## Goal
Make the /roster daemon-spawn setup (#22) **fully working + trustworthy** before any autonomous
daemon (esp. the refine daemon #27) is turned loose. All items from the operator's review of the
spawn UI (brief #22 event 266). **This + #22 live-spawn enablement = the gate before #27.**

## Items

### 1. Charter agent-name: double-prefix bug + collision check
- **Bug:** previewing role=refine for project=flower yields `You are flower-flower-refine …` —
  `SpawnPacketService::variables()` builds `AGENT_NAME = 'flower-'.$project->slug.'-'.$role->value`,
  doubling "flower" when the slug is "flower". Fix so it never double-prefixes (don't prepend
  `flower-` when the slug already leads with it, or switch to `{slug}-{role}` / `{role}@{slug}`).
- **Collision check:** before spawning, check Solo for an existing agent/process with that name;
  if one exists, fail with a clear message or auto-suffix — never silently create a duplicate-named
  daemon.

### 2. Heartbeat cadence as config + MIA detection
- Add a flower config key for the daemon **heartbeat interval** (default ≤ 30 min; "checkin on each
  loop/wake AND at least every N min"). The charter must state the CONCRETE cadence, not "when due".
- Use it for **MIA detection**: a daemon with no checkin within its expected window (heartbeat
  interval + grace) reads missing/stale on the roster.
- **GUARD:** a daemon legitimately on a slow/dormant poll must NOT be falsely marked missing — the
  expected window must derive from the daemon's CURRENT cadence, not a fixed short value.

### 3. Polling cadence as concrete config values
- Replace the charter's vague "quickly / slower / slowest" with concrete configured values
  (e.g. fast=Xs, slow=Ymin, dormant=Zmin), so there's no interpretation — and so we can tell whether
  a daemon SHOULD have acted by now (expected-action window per cadence). Reflect in the charter text.

### 4. Agent-tool config for live spawn
- Pre-flight flagged **"SOLO_AGENT_TOOL_ID is not configured"** — the bridge needs a Solo agent tool
  id to spawn. Decide + configure which runtime daemons spawn as (recommend **Claude**, the harness
  that gets the full flower tool surface after the #29 pagination fix), via config/flower.php
  (`SOLO_DAEMON_AGENT_TOOL_ID` / `SOLO_AGENT_TOOL_ID`). Surface a clear config error when unset.
- (Pre-flight also correctly flagged active operator sessions `flower-ops` / `flower-orchestrator` —
  working as intended; the guard blocks spawning into a project with active operator sessions.)

## Acceptance
- Charter agent name correct (no double-prefix) + collision-checked against Solo before spawn.
- Heartbeat + polling cadences are concrete config values reflected in the charter
  (`SpawnPacketService`), with MIA / expected-action detection that respects the daemon's current
  cadence (no false-missing on a long poll).
- `SOLO_(DAEMON_)AGENT_TOOL_ID` configurable + validated; pre-flight clears when set.
- Tests; suite green. `Brief: #34` trailer.

## Gates / relations
Builds on #22 (spawn bridge + UI); belongs to the daemon-roster epic (#11). This + #22 live-spawn
enablement = "spawn setup fully working" — the operator's gate before starting the refine daemon (#27).

## Provenance
Operator #22 UI review (2026-07-01, brief #22 event 266): naming double-prefix + collision, undefined
heartbeat cadence, vague polling cadence, and unconfigured agent-tool id.

Recommended linked context:
{
    "todos": [],
    "scratchpads": []
}

Execution notes:
- Treat the brief as the source of truth.
- Keep work scoped to this dispatch request.
- Use brief_append / brief_update_status when reporting material progress.
- Add a git commit trailer `Brief: #34` to every commit for this brief so flower can exact-link commits back to the brief.

provenance · append-only

Trace

live
or paste a screenshot uploading…
  1. link added 4d ago
    agent · system:commit-trailer
  2. participant joined 4d ago
    system · system:commit-trailer
  3. status change 4d ago
    agent · flower-orchestrator
  4. dispatched 4d ago

    Dispatch request #15 marked done.

    agent · flower-orchestrator
  5. comment 4d ago

    Implemented Brief #34 backend polish on branch flower/spawn-polish: daemon names now avoid flower-flower double prefix, spawn pre-flight checks exact Solo process-name collisions, Solo agent tools are discovered from solo-cli agents list with per actor/project last-choice persistence instead of static SOLO_AGENT_TOOL_ID config, daemon_checkin accepts current_cadence, roster MIA windows derive from current cadence plus heartbeat grace, and charters render concrete heartbeat/poll cadence values. Full php artisan test and Pint are green locally.

    agent · codex:flower-backend
  6. participant joined 4d ago
    system · codex:flower-backend
  7. note added 4d ago

    solo-cli BLOCKER RESOLVED (was transient, no code/config change needed). Empirical on MAIN 2026-07-01: live Solo listener = PID 72261 on 127.0.0.1:24678; discovery file ~/.config/soloterm/http-api.json is the CORRECT live one (endpointBaseUrl=http://127.0.0.1:24678). `curl /api/version` → HTTP 200; `solo-cli --json agents list` → {"ok":true} returning real agent tools: Claude=id 3, Codex=id 4, Gemini=1, OpenCode=2, Amp=5, Copilot=8, Kimi=9, Pi(cursor/composer)=10. The earlier `stale_discovery` was a momentary blip during a Solo restart (stale port/token/pid), NOT a wrong app-data dir. SOLO_APP_DATA_DIR stays UNSET — SoloClient.php:155-158 only passes --app-data-dir when non-empty, so the default (~/.config/soloterm) is used and works. => item-4's SoloAgentToolService sync will work against live Solo data; verify at merge on MAIN. Robustness ask: keep degrading gracefully on `stale_discovery` (catch SoloCliException → empty tools + a clear "Solo unreachable / restarting" hint) since it WILL recur briefly on each Solo restart.

    agent · flower-orchestrator
  8. note added 4d ago

    [orchestrator 969, 2026-07-01] Operator direction REVISES item 4 (agent-tool selection): do NOT rely on a static SOLO_AGENT_TOOL_ID .env/config value. Instead: - **Sync** the available Solo agent tools from solo-cli (runtimes list: Claude/Codex/Gemini/Pi/etc. + agent_tool_id + label) — fetched real-time when the /roster "Spawn a daemon" form loads (a flower service method), optionally short-cached. Solo is the source of truth, not a config value. - **Per-spawn harness SELECTOR** in the spawn form: the operator chooses which harness each time. - **Default to the last-chosen** selection (per operator/project); Claude on first use. - The SpawnDaemonBridge takes the chosen agent_tool_id at spawn time. Split: #34 (977) builds the BACKEND — solo-cli agent-tools sync service + expose + last-chosen persistence + pre-flight validation (error only when none available/selected). The **harness-selector dropdown in the /roster spawn form is a #22 UI follow-up** (design lane, after 973 frees from #31). Items 1-3 unchanged.

    agent · flower-orchestrator
  9. link added 4d ago
    agent · flower-orchestrator
  10. link added 4d ago
    agent · system:brief-autolink
  11. comment 4d ago

    Target branch flower/spawn-polish is merged to the default branch; suggest marking the brief complete.

    system · system:brief-autolink
  12. participant joined 4d ago
    system · system:brief-autolink
  13. dispatched 4d ago

    Dispatch request #15 queued for flower.

    agent · flower-orchestrator
  14. status change 4d ago
    agent · flower-orchestrator
  15. plan proposed 4d ago

    ## Goal Make the /roster daemon-spawn setup (#22) **fully working + trustworthy** before any autonomous daemon (esp. the refine daemon #27) is turned loose. All items from the operator's review of the spawn UI (brief #22 event 266). **This + #22 live-spawn enablement = the gate before #27.** ## Items ### 1. Charter agent-name: double-prefix bug + collision check - **Bug:** previewing role=refine for project=flower yields `You are flower-flower-refine …` — `SpawnPacketService::variables()` builds `AGENT_NAME = 'flower-'.$project->slug.'-'.$role->value`, doubling "flower" when the slug is "flower". Fix so it never double-prefixes (don't prepend `flower-` when the slug already leads with it, or switch to `{slug}-{role}` / `{role}@{slug}`). - **Collision check:** before spawning, check Solo for an existing agent/process with that name; if one exists, fail with a clear message or auto-suffix — never silently create a duplicate-named daemon. ### 2. Heartbeat cadence as config + MIA detection - Add a flower config key for the daemon **heartbeat interval** (default ≤ 30 min; "checkin on each loop/wake AND at least every N min"). The charter must state the CONCRETE cadence, not "when due". - Use it for **MIA detection**: a daemon with no checkin within its expected window (heartbeat interval + grace) reads missing/stale on the roster. - **GUARD:** a daemon legitimately on a slow/dormant poll must NOT be falsely marked missing — the expected window must derive from the daemon's CURRENT cadence, not a fixed short value. ### 3. Polling cadence as concrete config values - Replace the charter's vague "quickly / slower / slowest" with concrete configured values (e.g. fast=Xs, slow=Ymin, dormant=Zmin), so there's no interpretation — and so we can tell whether a daemon SHOULD have acted by now (expected-action window per cadence). Reflect in the charter text. ### 4. Agent-tool config for live spawn - Pre-flight flagged **"SOLO_AGENT_TOOL_ID is not configured"** — the bridge needs a Solo agent tool id to spawn. Decide + configure which runtime daemons spawn as (recommend **Claude**, the harness that gets the full flower tool surface after the #29 pagination fix), via config/flower.php (`SOLO_DAEMON_AGENT_TOOL_ID` / `SOLO_AGENT_TOOL_ID`). Surface a clear config error when unset. - (Pre-flight also correctly flagged active operator sessions `flower-ops` / `flower-orchestrator` — working as intended; the guard blocks spawning into a project with active operator sessions.) ## Acceptance - Charter agent name correct (no double-prefix) + collision-checked against Solo before spawn. - Heartbeat + polling cadences are concrete config values reflected in the charter (`SpawnPacketService`), with MIA / expected-action detection that respects the daemon's current cadence (no false-missing on a long poll). - `SOLO_(DAEMON_)AGENT_TOOL_ID` configurable + validated; pre-flight clears when set. - Tests; suite green. `Brief: #34` trailer. ## Gates / relations Builds on #22 (spawn bridge + UI); belongs to the daemon-roster epic (#11). This + #22 live-spawn enablement = "spawn setup fully working" — the operator's gate before starting the refine daemon (#27). ## Provenance Operator #22 UI review (2026-07-01, brief #22 event 266): naming double-prefix + collision, undefined heartbeat cadence, vague polling cadence, and unconfigured agent-tool id.

    agent · flower-orchestrator
  16. note added 4d ago

    From operator review of the /roster spawn UI (brief #22 event 266). Makes daemon-spawn fully working + trustworthy. Together with #22 live-spawn enablement, this is the gate the operator set before starting the refine daemon (#27).

    agent · flower-orchestrator
  17. participant joined 4d ago
    system · flower-orchestrator

epic · dependencies

Relationships

epic parent

depends on

No dependencies — dispatchable once planned.

agents · waves

Participants

  • flower-orchestrator participant · active
  • system:brief-autolink participant · active
  • codex:flower-backend participant · active
  • system:commit-trailer participant · active

trace · graph

Links

  • Commit #1203 execution
  • Scratchpad #346 execution
  • Commit #1194 result

scope

Projects

  • flower · primary

dogfood · read-only

Agent’s-eye view

The literal recall_brief payload an agent gets — same service path as the MCP tool.