flower
/
All briefs
complete draft note flower
epic · Operator-initiated non-resolving "Discuss/Clarify" d...

#229 PR-3 — Discuss bounds, liveness redelivery & reset/handoff hardening

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.

#139 done fresh flower · flower/260-discuss-hardening
agent: codex
You are being dispatched from flower Brief #260: #229 PR-3 — Discuss bounds, liveness redelivery & reset/handoff hardening

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

Target:
- project: flower (/Users/mikeferrara/Documents/code/flower)
- branch: flower/260-discuss-hardening
- worktree: not specified
- kind: fresh

Current brief spec:
(no spec yet)

This is a direct request, not a fully-specced plan. If it's clear, resolve it. If you hit a blocking ambiguity, call brief_ask (or brief_append) with your questions and flip the brief to `refining` before proceeding — don't guess.

Recent/key trace events:
[1] participant_joined flower-229-design: (no body)
[2] note_added flower-229-design: ## PR-3 — Bounds, liveness redelivery & handoff hardening (child of #229; decisions epic #95)
Design: `docs/design/229-discuss-clarify-decision.md` §Bounds/§Liveness/§Reset. **Deps: #258 (PR-1 spine)** — parallel to PR-2. Target ≤~300 lines, `php artisan test` green, pint clean.

Closes the one real gap (mid-discussion calls stranding across a daemon reset) + the discipline that keeps Discuss a clarification, not chat.

### Build
- **Config** `config/flower.php`: `decisions.discussion.soft_round_cap` (default 6), env-overridable. (PR-2's nudge banner already reads `config(…, 6)`, so no hard ordering.)
- **Daemon charter carve-out** (`AgentConventions::daemonLines()` / `DaemonCharterDefaults`): when a pulled decision has `awaiting_turn='daemon'`, reply via `decision_discuss` — **concisely**, answer the operator's clarification, **drive toward resolution**; if it's becoming open-ended, say so and **point to Solo** (the durable chat bus).
- **Reset/handoff redelivery (the real gap):** extend `DecisionService::redeliverTo()` (DecisionService.php:394-415, called from `DaemonRosterService::checkin` → `redeliverInheritedDecisions()`) to ALSO pull `awaitingDiscussionReplyFor(canonical)` (`open ∧ awaiting_turn=daemon ∧ assigned_to=ref`) and re-enqueue a wake per call. This is what rescues a mid-discussion call from the target-scoped-wake reset hazard (`decision_wake` not in `resetLifecycleKinds`; `reset_pending` never cleared on close → a pending wake is hidden from the predecessor forever). Reuses the exact #124 mechanism — no new reset primitive.
- **Orphaned surfacing:** extend `DecisionService::orphaned()` (:429-469) + `HealthService::orphanedDecisionsCheck()` (`app/Services/Health/HealthService.php:78-89`) to also count mid-discussion calls (`open ∧ awaiting_turn=daemon`) with no live assignee, so a stuck discussion surfaces to ops/`recall_health` like a stranded answer.
- **Activation note (doc/handoff):** the orchestrator schedules a daemon reload (`flower:daemon-schema-reload`) after PR-1 merges so standing daemons pick up the reply loop.

### Tests
the soft-cap threshold fires the nudge; a mid-discussion call (`open`, `awaiting_turn=daemon`) re-delivers to a SUCCESSOR after a reset (survives the never-cleared `reset_pending`); the thread + `awaiting_turn` carry over to the successor; `orphaned()`/health counts a stuck discussion with no live assignee.
[3] parent_set flower-229-design: Grouped under epic #229.
[4] dependency_added flower-229-design: Now depends on #258 (#229 PR-1 — Discuss/Clarify spine: decision_messages + discuss() + decision_discuss MCP + pull union).
[5] status_change flower-229-design: (no body)
[6] participant_joined flower-258-discuss-spine: (no body)
[7] unblocked flower-258-discuss-spine: Unblocked — #258 reached complete.

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; as your final dispatched-worker step, call brief_dispatch_complete with dispatch_request_id (or brief_id) and actor_ref.
- Codex workers should verify mutating Flower tools with tool_search query `brief_append brief_dispatch_complete flower_feedback` (limit 20) when tool availability is in doubt; report raw SEE/LOAD vs NOT visible instead of silently using local fallbacks.
- Add a git commit trailer `Brief: #260` to every commit for this brief so flower can exact-link commits back to the brief.
- Need an operator call while working this brief? A question ABOUT THIS BRIEF -> brief_ask(260, ...); a standalone decision not tied to the brief -> decision_ask(...). Both expose the full affordance set (confirm | single_choice | multi_choice | text, options + recommended, allow_write_in); prefer async questions over blocking and set is_blocking only when you truly cannot proceed.
- Cited-refs index (Brief #244): when a report / checkpoint / DONE summary cites numbered entities, append a compact `Refs:` block at the END mapping each `#N` to its REAL stored title + status — `#<num>: <title> (<status>)`, one per line (typed prefixes: bare `#N` = brief, `fb#N` feedback, `dec#N` decision, `sess#N` session, `dr#N` dispatch_request). Resolve any title you did not already pull with recall_refs instead of guessing; skip the block on trivial one-liners.

provenance · append-only

Trace

live
or paste a screenshot uploading…
  1. link added 13h ago
    agent · system:commit-trailer
  2. link added 13h ago
    agent · system:commit-trailer
  3. link added 13h ago
    agent · system:commit-trailer
  4. participant joined 13h ago
    system · system:commit-trailer
  5. merged 14h ago

    Merged flower/260-discuss-hardening → master @ cd72b93 (orchestrator daemon 43). PR-3 hardening: soft_round_cap config (default 6), daemon discussion-reply charter clause in AgentConventions (DaemonCharterDefaults bumped to v6), widened DecisionService::redeliverTo()/orphaned() + HealthService orphaned_decisions to mid-discussion calls (open ∧ awaiting_turn=daemon ∧ assigned_to=ref). Frozen answer path untouched. MAIN verify: full suite GREEN (1272 tests, 1270 passed, 2 skipped, 0 failures); pint clean; PromptTemplateSeeder --force reseeded (charter v6). No migrations. #229 epic now: PR-1 (#258) + PR-3 (#260) MERGED; only PR-2 UI (#259) remains (held pending operator spine review). ACTIVATION: standing daemons pick up the v6 charter discussion-reply clause + decision_discuss on next reset — daemon reload pending at a lull.

    agent · flower-orchestrator
  6. status change 14h ago
    agent · flower-260-discuss-hardening
  7. dispatched 14h ago

    Dispatch request #139 marked done.

    agent · flower-260-discuss-hardening
  8. comment 14h ago

    Implemented PR-3 backend hardening on branch flower/260-discuss-hardening. Summary: - Added config('flower.decisions.discussion.soft_round_cap', 6) via FLOWER_DECISIONS_DISCUSSION_SOFT_ROUND_CAP; no hard cap or answer-path edits. - Added the daemon discussion-reply charter clause in AgentConventions: awaiting_turn=daemon calls are answered via decision_discuss concisely, driven toward resolution, and pushed to Solo if open-ended; bumped DaemonCharterDefaults to version 6 and updated charter tests. - Widened DecisionService::redeliverTo() to redeliver open awaiting_turn=daemon discussions with discuss wakes, alongside released/unacked answer wakes. - Widened DecisionService::orphaned() and HealthService orphaned_decisions to surface mid-discussion calls with no live daemon assignee. - Added regression coverage for reset_pending hidden discuss wakes, successor redelivery, thread/awaiting_turn carryover, orphaned health counts, config default, and charter/seeder expectations. Frozen answer path check: no diff in app/Livewire/Decisions/Concerns/AnswersDecisions.php or resources/views/components/decisions/affordance.blade.php. Commits: - e28c68c Harden discussion decision handoff - 876dd3b Update daemon charter version expectations - a113954 Apply Pint to charter tests Verification: - MEILISEARCH_KEY=LARAVEL-HERD ANTHROPIC_API_KEY= ~/bin/php artisan test => passed (1272 tests, 7731 assertions, 14 skipped) - ~/bin/php ./vendor/bin/pint => passed

    agent · flower-260-discuss-hardening
  9. participant joined 14h ago
    system · flower-260-discuss-hardening
  10. dispatched 14h ago

    Dispatch request #139 queued for flower.

    agent · flower-orchestrator
  11. status change 14h ago
    agent · flower-orchestrator
  12. participant joined 14h ago
    system · flower-orchestrator
  13. unblocked 14h ago

    Unblocked — #258 reached complete.

    system · flower-258-discuss-spine
  14. participant joined 14h ago
    system · flower-258-discuss-spine
  15. status change 19h ago
    agent · flower-229-design
  16. dependency added 19h ago

    Now depends on #258 (#229 PR-1 — Discuss/Clarify spine: decision_messages + discuss() + decision_discuss MCP + pull union).

    agent · flower-229-design
  17. parent set 19h ago

    Grouped under epic #229.

    agent · flower-229-design
  18. note added 19h ago

    ## PR-3 — Bounds, liveness redelivery & handoff hardening (child of #229; decisions epic #95) Design: `docs/design/229-discuss-clarify-decision.md` §Bounds/§Liveness/§Reset. **Deps: #258 (PR-1 spine)** — parallel to PR-2. Target ≤~300 lines, `php artisan test` green, pint clean. Closes the one real gap (mid-discussion calls stranding across a daemon reset) + the discipline that keeps Discuss a clarification, not chat. ### Build - **Config** `config/flower.php`: `decisions.discussion.soft_round_cap` (default 6), env-overridable. (PR-2's nudge banner already reads `config(…, 6)`, so no hard ordering.) - **Daemon charter carve-out** (`AgentConventions::daemonLines()` / `DaemonCharterDefaults`): when a pulled decision has `awaiting_turn='daemon'`, reply via `decision_discuss` — **concisely**, answer the operator's clarification, **drive toward resolution**; if it's becoming open-ended, say so and **point to Solo** (the durable chat bus). - **Reset/handoff redelivery (the real gap):** extend `DecisionService::redeliverTo()` (DecisionService.php:394-415, called from `DaemonRosterService::checkin` → `redeliverInheritedDecisions()`) to ALSO pull `awaitingDiscussionReplyFor(canonical)` (`open ∧ awaiting_turn=daemon ∧ assigned_to=ref`) and re-enqueue a wake per call. This is what rescues a mid-discussion call from the target-scoped-wake reset hazard (`decision_wake` not in `resetLifecycleKinds`; `reset_pending` never cleared on close → a pending wake is hidden from the predecessor forever). Reuses the exact #124 mechanism — no new reset primitive. - **Orphaned surfacing:** extend `DecisionService::orphaned()` (:429-469) + `HealthService::orphanedDecisionsCheck()` (`app/Services/Health/HealthService.php:78-89`) to also count mid-discussion calls (`open ∧ awaiting_turn=daemon`) with no live assignee, so a stuck discussion surfaces to ops/`recall_health` like a stranded answer. - **Activation note (doc/handoff):** the orchestrator schedules a daemon reload (`flower:daemon-schema-reload`) after PR-1 merges so standing daemons pick up the reply loop. ### Tests the soft-cap threshold fires the nudge; a mid-discussion call (`open`, `awaiting_turn=daemon`) re-delivers to a SUCCESSOR after a reset (survives the never-cleared `reset_pending`); the thread + `awaiting_turn` carry over to the successor; `orphaned()`/health counts a stuck discussion with no live assignee.

    agent · flower-229-design
  19. participant joined 19h ago
    system · flower-229-design

epic · dependencies

Relationships

depends on

agents · waves

Participants

  • flower-229-design participant · active
  • flower-258-discuss-spine participant · active
  • flower-orchestrator participant · active
  • flower-260-discuss-hardening participant · active
  • system:commit-trailer participant · active

trace · graph

Links

  • Commit #4071 execution
  • Commit #4072 execution
  • Commit #4073 execution

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.