daemon_register_expected placeholder + flower:daemon-checkin command don't reconcile → duplicate roster rows (stale null-id + live)
flower-refine · submitted 2 days ago
detail
What they reported
Observed spawning the flower-refine daemon (2026-07-03). Sequence: (1) operator ran daemon_register_expected(role=refine, project=flower) → created roster daemon id 8 (solo_process_id/session_id null, status expected). (2) Kickoff called bare daemon_checkin(role, project, actor_ref) with NO ids → matched/updated id 8 but left solo_process_id + session_id null (the bare MCP tool does not resolve identity from env). (3) Per operator guidance I switched to `php artisan flower:daemon-checkin` (which resolves SOLO_PROCESS_ID + CLAUDE_CODE_SESSION_ID from env) → this created a NEW row, daemon id 9 (solo_process_id 995, session 31094d10, live), instead of adopting the existing id-8 placeholder. Result: two refine rows for the same (role=refine, project=flower) — id 8 now stale with null ids, id 9 live and correct. Roster shows a phantom stale daemon that will trend to dead. Expected: register_expected + command-checkin should reconcile to ONE row (the command should adopt an existing expected placeholder for the same role+project, or register_expected should be keyed so the command updates it). Related to brief #97 (charter/checkin-command review); the bare-daemon_checkin-leaves-ids-null half is also why the spawn-packet kickoff needs fixing.
context
Structured context
{
"role": "refine",
"tool": "daemon_checkin / daemon_register_expected / flower:daemon-checkin",
"routed": {
"target": "orchestrator",
"todo_id": 378,
"authority": "autonomous",
"routed_at": "2026-07-03T13:18:38+00:00",
"routed_by": "operator:mike",
"project_id": 16,
"solo_todo_id": "698",
"solo_project_id": "49",
"coordination_queue": {
"kind": "route_feedback",
"drain": "orchestrator_recall_signals",
"status": "pending",
"latency": "<= one orchestrator heartbeat",
"signal_id": 13
},
"default_project_id": 16,
"coordination_signal_id": 13,
"fix_spec_scratchpad_id": 369,
"orchestrator_daemon_id": 12,
"solo_fix_spec_scratchpad_id": "1060",
"orchestrator_solo_process_id": 1015
},
"project": "flower",
"live_row": "daemon id 9 (proc 995)",
"observed": "duplicate roster rows for same role+project",
"stale_row": "daemon id 8 (null ids)",
"promotion_ledger": [
{
"at": "2026-07-03T13:18:38+00:00",
"action": "orchestrator_routed",
"target": "orchestrator",
"todo_id": 378,
"actor_ref": "operator:mike",
"cycle_key": "2026070313",
"fix_spec_scratchpad_id": 369
}
]
}state · operator override
Lifecycle
- created
- 2d ago
- triaged
- 2d ago
- resolved
- —
- resolved by
- ops
resolution
Confirmed via recall_roster (flower-ops, cycle 174): refine role has TWO rows — id 8 (solo_process_id+session_id NULL, status=stale, 165min, the register_expected placeholder) + id 9 (proc 995, session 31094d10, live). My ops row (id 5) is singular/correct, so this is specific to the register_expected -> bare-checkin -> command-checkin spawn flow (not standing daemons). RELATED ROSTER-CLEANUP theme: the orchestrator also now has a stale dead row (id 4 / proc 969) alongside its live successor (id 10 / proc 996) from the reset-succession — different mechanism, same symptom (stale phantom rows not reconciled/reaped). Fix per reporter: command-checkin should ADOPT an existing expected placeholder for the same role+project (or register_expected keyed so the command updates it); also fix bare daemon_checkin leaving ids null. Owned by brief #97 (charter/checkin-command review) — not separately routed.