flower
/
All briefs
complete draft mcp flower

Daemon self-identity: env-sourced session_id, retire self-reported context_size, check-in command

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.

provenance · append-only

Trace

live
or paste a screenshot uploading…
  1. status change 3d ago
    agent · flower-orchestrator
  2. note added 3d ago

    Build complete on branch flower/daemon-self-identity — commit 1cfe473 (Brief #67 trailer). NOT merged, NOT pushed (orchestrator owns merge + timer/Horizon reload). Files (8, +392/-5): - app/Support/DaemonEnvIdentity.php (new) — harness-portable resolver. resolveSoloProcessId() ← SOLO_PROCESS_ID; resolveSessionId() ← per-harness map (claude ⇒ CLAUDE_CODE_SESSION_ID) with documented EXTENSION POINT (commented codex/pi entries) + null fallback; resolveHarness() for display. - app/Console/Commands/DaemonCheckin.php (new) — `flower:daemon-checkin --role= --actor-ref= [--cadence=fast] [--project=flower] [--window=]`. Self-resolves ids from env, calls DaemonRosterService::checkin(contextSize: null, usage: null, modelContextWindow: window). Prints solo process / session / context / context_source / cadence. Exits non-zero on missing/invalid role, missing actor-ref, or InvalidArgumentException. - .claude/commands/flower-checkin.md (new) — thin `/flower-checkin <role> <actor-ref>` wrapper (runs the artisan cmd, cadence=fast). - app/Support/AgentConventions.php — daemon heartbeat line reframed to the check-in command; drops context_size + the self-reported id/window list. - resources/views/livewire/roster/index.blade.php (~117) — null context now renders "— pending" (mono-caps, title="Awaiting session ingest…") instead of a bare dash. - tests/Feature/Console/DaemonCheckinCommandTest.php (new) — env-sourced identity persists session_id+solo_process_id, context_size null, cadence in meta, window defaults to config; required-option failures; null-session fallback. - tests/Unit/AgentConventionsTest.php — swapped the model_context_window assertion for flower:daemon-checkin + a context_size regression guard. Tests: `php artisan test` → 565 passed, 1 skipped (pre-existing), 0 failures, 3908 assertions. Pint clean on changed files. DECISION TO REVIEW: `.claude/` was fully gitignored ("ephemeral, never commit"). To make the required slash-command deliverable committable I changed the rule to `.claude/*` + `!.claude/commands/` — settings.local.json and ephemeral worktrees stay ignored, only shared commands/ tracks. Verified via git check-ignore. Veto/adjust on merge if you'd rather keep .claude fully ignored (then drop the wrapper or relocate it). Deferred (yours, per spec): Solo timer-body rewrite to call the command, merge to master, `php artisan horizon:terminate` reload, and any Codex/Pi session-env wiring (extension point is in place). Note: modelContextWindow now defaults to config on every check-in (Opus 1M) — intended per spec, but it means model_context_window is always set going forward.

    agent · agent:flower-67-worker(proc-992)
  3. participant joined 3d ago
    system · agent:flower-67-worker(proc-992)
  4. plan proposed 3d ago

    # Daemon self-identity: env-sourced ids, retire self-reported context_size, check-in command ## Problem Daemon heartbeats today carry **hardcoded `solo_process_id` + `session_id` baked into the Solo timer body**, plus an instruction to self-report `context_size`. All three are avoidable liabilities: - The baked ids drift. After this session's `/compact`, timer #1242's body still named the pre-existing ids; separately I mis-trusted a wrong id and checked in against a dead session (context% went null). - Self-reported `context_size` is unreliable — an agent cannot introspect its own token count. That self-estimate is exactly what produced ops's false 100% (self-reported 1,035,000 vs real 762,112). ## Verified facts (this session, MAIN) 1. **Both ids are in the daemon's env and authoritative:** `SOLO_PROCESS_ID=969`, `CLAUDE_CODE_SESSION_ID=0410d7d4-8091-476e-91c0-83e07e92c6fd`. `CLAUDE_CODE_SESSION_ID` = the live transcript actually being appended (27.9MB, growing) and is stable across `/compact` (same OS process, same session). 2. **Session correlation already supersedes self-report (#63):** when the linked session has ingested usage, roster derives `context_used` from `session_usage` (`context_source: session_usage`) and ignores `context_size`. Proven — ops 76% (762112/1M), orchestrator 12% (124164/1M), both session-derived. 3. **Correlation only works against the *transcript* id.** Claude Code ambiguity: the SessionStart hook's additionalContext was filed under a DIFFERENT id (`980d799f…`, a 12KB artifact) than the live transcript (`0410d7d4…` = `CLAUDE_CODE_SESSION_ID`). Checking in with the hook id → `context_percent: null`; checking in with the env id → `context_percent: 12`. **`CLAUDE_CODE_SESSION_ID` is authoritative; the hook-path id must NOT be used for correlation.** ## Changes 1. **Retire self-reported `context_size` from the heartbeat prompt/timer.** Keep the DB column + tool param for back-compat, but stop asking agents to estimate it. `session_usage` is the source of truth. 2. **Stop baking `solo_process_id` / `session_id` into the timer body.** The daemon self-resolves both from env at check-in time (`SOLO_PROCESS_ID`, `CLAUDE_CODE_SESSION_ID`) plus `model_context_window`. 3. **Ship a check-in command/tool** (Claude Code slash command e.g. `/flower-checkin`, or a small script) that reads those env vars and calls `daemon_checkin(role, actor_ref, project, solo_process_id, session_id, model_context_window, current_cadence)`. The timer body collapses to "run the check-in command." Immune to baked-id drift; identity always live. Role + actor_ref remain the only per-daemon constants (supply via the command's args or a per-process config). 4. **Pre-ingest fallback display.** Right after a new session starts, before flower ingests its first usage turn, `session_usage` is empty → `context_percent` null. Roster should render "pending / —" (honest) rather than a stale/guessed number. 5. **Harness-portability note.** `CLAUDE_CODE_SESSION_ID` is Claude-specific. Codex/Pi daemons need the equivalent env/identity source; the check-in command should detect harness and read the right var (or fall back to `whoami`). ## Acceptance - A daemon checks in with **zero hardcoded ids**; roster shows correct `context_percent` from `session_usage`. - No agent is asked to self-estimate `context_size`. - Post-`/compact` heartbeat keeps correlating (proven: env id 0410d7d4 → 12%). - Timer bodies contain no session/process ids. ## Out of scope - The embedded→indexed embedding-backlog drain (159 `embedded` rows unpushed since 06-29/07-01) — separate WARN, tracked apart. - Deep Claude Code internals of why the hook path id differs from the transcript id — document the observed behavior; don't chase the root cause unless it recurs.

    agent · flower-orchestrator
  5. note added 3d ago

    Heartbeat/roster identity hardening. Daemons should self-resolve identity from env (SOLO_PROCESS_ID, CLAUDE_CODE_SESSION_ID) instead of ids hardcoded in the Solo timer body; retire the self-reported context_size (now superseded by session_usage correlation from #63); and provide a check-in command so the timer body is trivial. Full spec to follow. Verified live this session — see spec.

    agent · flower-orchestrator
  6. participant joined 3d ago
    system · flower-orchestrator

epic · dependencies

Relationships

epic parent

depends on

No dependencies — dispatchable once planned.

agents · waves

Participants

  • flower-orchestrator participant · active
  • agent:flower-67-worker(proc-992) participant · active

trace · graph

Links

No links yet — they accrue as agents work the brief.

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.