flower
/
All briefs
complete draft mcp flower
epic · Redesign /decisions feed to deliver decision context...

[#216 PR-3a] /decisions Depth (structured, no AI) — decisionSummary brief-web + grouped linked-context

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.

#103 done fresh flower · flower/222-decisions-depth-structured
agent: claude
You are being dispatched from flower Brief #222: [#216 PR-3a] /decisions Depth (structured, no AI) — decisionSummary brief-web + grouped linked-context

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

Target:
- project: flower (/Users/mikeferrara/Documents/code/flower)
- branch: flower/222-decisions-depth-structured
- 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-216-worker: (no body)
[2] note_added flower-216-worker: Child of Brief #216. Design doc: `docs/design/216-decisions-feed-redesign.md` §"Sequenced delivery" PR-3a. Depends on PR-1 (#220). NO AI, NO columns, NO job — a shippable depth improvement that de-risks PR-3b.

## Scope (≈ ≤300 lines)
1. **Extend `RecallService::decisionSummary()`** (`app/Services/Recall/RecallService.php:922`) with a `brief` sub-object (call `briefDetail()`) + a `links` sub-object (relation + target label per `decision_links` row) so a decision carries its brief web on the wire.
2. **Add a `DecisionBriefContext` assembler** that gathers the decision's full recall web from the TWO RecallService calls that already ship: `decisionSummary($decision)` (card-face shape, now with brief+links) for buckets 1/2/6/7, and **`briefFolder($decision->brief_id)`** for the deeper web (buckets 3/4/5 — parent/children/deps + related sessions from `participants` + commit subjects from `events`). NAMING MATTERS: session summaries + commit subjects live in `briefFolder`'s participants/events, NOT in `briefDetail`/`briefRelations`, so call `briefFolder` (one assembled query), don't lazy-walk relations. This assembler is the shared input PR-3b's "Brief me" prompt consumes.
3. **Regroup the flat link list in `detail.blade.php`** by relation into the labeled web (sessions / commits / feedback / parent / epic), mirroring the `briefs/show` links side card pattern (`class_basename #id` + `<span class="mono-label">{{ relation }}</span>`). This is the ONE detail section PR-1 deliberately left alone — no collision.

## Constraints
- Structured only — no OpenRouter, no `ai_brief*` columns, no `BriefDecision` job.
- Bound the assembler (respect `briefFolder`'s event limit 25; cap sessions/commits) so it's cheap.
- Answer path untouched.

## Acceptance
`decisionSummary()` returns brief+links sub-objects (assert shape in a unit test); `DecisionBriefContext` assembles the 7-bucket web without N+1 (uses briefFolder, not relation-walking); the detail flyout shows a grouped linked-context web instead of a flat list; `php artisan test` green; `pint` clean.
[3] parent_set flower-216-worker: Grouped under epic #216.
[4] dependency_added flower-216-worker: Now depends on #220 ([#216 PR-1] /decisions Display seam — promote provenance + subject + trace onto the card face).
[5] participant_joined flower-220-worker: (no body)
[6] unblocked flower-220-worker: Unblocked — #220 reached complete.
[7] participant_joined flower-orchestrator: (no body)
[8] status_change flower-orchestrator: (no body)

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: #222` 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 1d ago
    agent · system:commit-trailer
  2. link added 1d ago
    agent · system:commit-trailer
  3. participant joined 1d ago
    system · system:commit-trailer
  4. merged 1d ago

    Merged flower/222-decisions-depth-structured into master on MAIN — merge commit **0afe7d3** (worker commit eed5405) + integration-fix commit **80075ac**. #221's files verified intact through the 3-way merge (BackfillDecisionLinks + DecisionAutoLinkService enrichment coexist with DecisionBriefContext). ⚠️ Cross-branch integration catch: the worker's `DecisionBriefWebTest` was green in isolation but hit a `decision_links` UNIQUE violation on master — #221's enriched syncDecision() now auto-creates the subject brief's parent (epic) Reference link, which the test also manually inserted. Fixed by dropping the redundant manual epic link (80075ac). Full suite green on MAIN (1092 passed, 2 skips, 6809 assertions); pint clean; npm build done (detail.blade). No Horizon reload (RecallService inline). Worker proc 1125 closed. #223 (PR-3b "Brief me") now unblocked.

    agent · flower-orchestrator
  5. status change 1d ago
    agent · flower-222-worker
  6. dispatched 1d ago

    Dispatch request #103 marked done.

    agent · flower-222-worker
  7. note added 1d ago

    **PR-3a landed (structured, no AI) — commit `eed5405` on branch `flower/222-decisions-depth-structured` (off master f54c7ac). Not merged — orchestrator merges from MAIN.** Scope shipped, all three seams: 1. **`RecallService::decisionSummary()`** (app/Services/Recall/RecallService.php) now carries the decision's brief web on the wire: a `brief` sub-object (`briefDetail()` for the resolved subject brief, via a new `resolveDecisionBrief()` mirroring the blade's subject resolution) + a flat `links` sub-object (relation + linkable_type/id + friendly label per `decision_links` row). New `decisionLinkSummaries()` uses `loadMissing('links.linkable')` so morph targets batch by type — O(link types), never per-link. Backward-compatible (added keys only; full suite + MCP/decision-payload tests still green). 2. **`DecisionBriefContext` assembler** (new `app/Services/Decisions/DecisionBriefContext.php`) gathers the 7-bucket web from just TWO already-shipping RecallService calls — `decisionSummary($decision)` (buckets 1/2/6/7: decision core w/ normalized options+recommended, subject brief w/ token-budgeted spec, decision links, parent-answer lineage) + `briefFolder($decision->brief_id)` (buckets 3/4/5: epic/children/deps from relations, related sessions from participants, related commit subjects from links.commits — subjects live there, events carry only the link ref). Bounded: 8 sessions / 10 commits / 1200-char spec; reuses briefFolder's 25-event cap. Uses briefFolder's one assembled query, not lazy relation-walking, so `assemble()` is O(1) in queries. 3. **`resources/views/components/decisions/detail.blade.php`**: regrouped the flat linked-context list into the labeled web (sessions / commits / feedback / epic / other), bucketed by linkable type the same way `x-decisions.trace-summary` counts them (subject-brief self-link deduped), each row mirroring the briefs/show links pattern (target label + relation mono-label). This is the one detail section PR-1 (#220) left alone — no collision. Constraints honored: no OpenRouter, no `ai_brief*` columns, no `BriefDecision` job, answer path untouched, assembler bounded. Tests: new `tests/Feature/Recall/DecisionBriefWebTest.php` (4 tests, 49 assertions) asserts decisionSummary's brief+links shape, the standalone-null case, the assembled 7-bucket web, and **no N+1** (query count identical for a 1-record vs 6-record web). **Full suite green: 1081 passed / 3 skipped / 0 failed.** `pint` clean on changed files; blades compile (`view:cache`). One implementation note worth flagging for PR-3b: the design NOTE said "commit subjects from events", but the actual commit messages only live in `briefFolder.links.commits` (events carry just the link reference) — so `related_commits` sources subjects from `links.commits`. Still one assembled briefFolder call, still no N+1, just the honest source for the subject text.

    agent · flower-222-worker
  8. participant joined 1d ago
    system · flower-222-worker
  9. dispatched 1d ago

    Dispatch request #103 queued for flower.

    agent · flower-orchestrator
  10. status change 1d ago
    agent · flower-orchestrator
  11. status change 1d ago
    agent · flower-orchestrator
  12. participant joined 1d ago
    system · flower-orchestrator
  13. unblocked 1d ago

    Unblocked — #220 reached complete.

    system · flower-220-worker
  14. participant joined 1d ago
    system · flower-220-worker
  15. dependency added 1d ago

    Now depends on #220 ([#216 PR-1] /decisions Display seam — promote provenance + subject + trace onto the card face).

    agent · flower-216-worker
  16. parent set 1d ago

    Grouped under epic #216.

    agent · flower-216-worker
  17. note added 1d ago

    Child of Brief #216. Design doc: `docs/design/216-decisions-feed-redesign.md` §"Sequenced delivery" PR-3a. Depends on PR-1 (#220). NO AI, NO columns, NO job — a shippable depth improvement that de-risks PR-3b. ## Scope (≈ ≤300 lines) 1. **Extend `RecallService::decisionSummary()`** (`app/Services/Recall/RecallService.php:922`) with a `brief` sub-object (call `briefDetail()`) + a `links` sub-object (relation + target label per `decision_links` row) so a decision carries its brief web on the wire. 2. **Add a `DecisionBriefContext` assembler** that gathers the decision's full recall web from the TWO RecallService calls that already ship: `decisionSummary($decision)` (card-face shape, now with brief+links) for buckets 1/2/6/7, and **`briefFolder($decision->brief_id)`** for the deeper web (buckets 3/4/5 — parent/children/deps + related sessions from `participants` + commit subjects from `events`). NAMING MATTERS: session summaries + commit subjects live in `briefFolder`'s participants/events, NOT in `briefDetail`/`briefRelations`, so call `briefFolder` (one assembled query), don't lazy-walk relations. This assembler is the shared input PR-3b's "Brief me" prompt consumes. 3. **Regroup the flat link list in `detail.blade.php`** by relation into the labeled web (sessions / commits / feedback / parent / epic), mirroring the `briefs/show` links side card pattern (`class_basename #id` + `<span class="mono-label">{{ relation }}</span>`). This is the ONE detail section PR-1 deliberately left alone — no collision. ## Constraints - Structured only — no OpenRouter, no `ai_brief*` columns, no `BriefDecision` job. - Bound the assembler (respect `briefFolder`'s event limit 25; cap sessions/commits) so it's cheap. - Answer path untouched. ## Acceptance `decisionSummary()` returns brief+links sub-objects (assert shape in a unit test); `DecisionBriefContext` assembles the 7-bucket web without N+1 (uses briefFolder, not relation-walking); the detail flyout shows a grouped linked-context web instead of a flat list; `php artisan test` green; `pint` clean.

    agent · flower-216-worker
  18. participant joined 1d ago
    system · flower-216-worker

epic · dependencies

Relationships

depends on

agents · waves

Participants

  • flower-216-worker participant · active
  • flower-220-worker participant · active
  • flower-orchestrator participant · active
  • flower-222-worker participant · active
  • system:commit-trailer participant · active

trace · graph

Links

  • Commit #4008 execution
  • Commit #4012 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.