flower
/
All briefs
complete draft note flower

Feedback↔brief UX: auto-link on create + auto-close feedback when its brief completes (model events)

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.

#64 done fresh flower · flower/175-feedback-brief-autoclose
agent: claude claimed by flower-175
You are being dispatched from flower Brief #175: Feedback↔brief UX: auto-link on create + auto-close feedback when its brief completes (model events)

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

Target:
- project: flower (/Users/mikeferrara/Documents/code/flower)
- branch: flower/175-feedback-brief-autoclose
- 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-orchestrator: (no body)
[2] note_added flower-orchestrator: ## Motivation (first-hand this session: feedback #77 → brief #171)
The feedback→brief flow is awkward to work with:
- **Link not auto-set.** brief_create(origin=feedback) left briefs.feedback_id NULL — the only tie was a hand-typed ref in the spec. brief_create has no feedback_id param.
- **No auto-close.** When #171 completed, feedback #77 did NOT auto-resolve — the worker manually ran the FeedbackStatus artisan command, fiddly because its worktree DB is isolated from MAIN's live feedback store.
- **Not navigable.** /feedback doesn't surface the linked brief + status; the brief doesn't surface the source feedback.

## Proposed scope
### A. First-class, auto-populated feedback↔brief link
- brief_create accepts an optional feedback_id; and/or make feedback_promote the canonical "promote to brief" path that sets briefs.feedback_id + emits a brief_events link_added + attaches provenance. Pass through appropriate links/context from the feedback into the brief.
- Back-reference: feedback → its linked brief(s).

### B. Auto-close feedback when its linked brief completes (Eloquent model event)
- A Brief observer: on status → complete, if a linked feedback exists and isn't already resolved, set feedback → addressed with resolution="Brief #N: <summary>", resolved_by/resolved_at. Idempotent.
- **Recommended defaults (operator-confirmable):**
  1. Cardinality: use existing briefs.feedback_id (many briefs → 1 feedback); auto-address the feedback when a linked brief first reaches complete. No polymorphic needed.
  2. cancelled/abandoned brief → do NOT auto-address the feedback (work didn't ship); leave it open.
  3. Feedback status vocab: 'addressed' (matches what #171's worker used + existing feedback.status).

### C. UX / surfacing
- /feedback: show each item's linked brief(s) (id + status, clickable) + whether it auto-closed.
- Brief detail: show the source feedback (id + link) when feedback_id is set.

## Relationship
Concrete FIRST instance of the model-event-driven automation in #172 (app-wide health/audit-log) — proves the observer pattern before the broader audit log. Motivated by feedback #77 / brief #171.

## Open decisions (confirm or accept the recommended defaults above)
1. Link cardinality (recommend: existing FK, many-briefs→1-feedback).
2. cancelled/abandoned brief behavior (recommend: leave feedback open).
3. status vocab: addressed vs resolved (recommend: addressed).

Status: idea — small refinement to lock the 3 decisions, then dispatchable.
[3] note_added flower-orchestrator: Operator confirmed the 3 recommended defaults (2026-07-04) — decisions LOCKED: (1) cardinality = existing briefs.feedback_id FK (many briefs → 1 feedback); auto-address the feedback when a linked brief FIRST reaches complete; no new polymorphic table. (2) cancelled/abandoned brief → do NOT auto-address the linked feedback (work didn't ship) — leave it open. (3) feedback status vocab = 'addressed'. Proceed with the full proposed scope A (auto-link on create: brief_create optional feedback_id + feedback_promote as canonical promote-to-brief that sets briefs.feedback_id + link_added event/provenance; feedback→brief back-reference) + B (Brief Eloquent observer auto-marks linked feedback 'addressed' on status→complete, idempotent, resolution="Brief #N: <summary>") + C (/feedback surfaces linked brief(s)+status clickable; brief detail surfaces source feedback).
[4] 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: #175` 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

    #175 (feedback↔brief auto-link + auto-close) merged to master (4bcc197). (A) brief_create optional feedback_id → BriefService::linkFeedback (idempotent; stamps briefs.feedback_id + link_added); feedback_promote confirmed canonical. (B) BriefObserver (registered in FlowerServiceProvider, fires on model 'updated' so all write paths caught) + FeedbackAutoCloseService — auto-marks linked feedback 'addressed' on the brief's first transition to complete (idempotent, resolution="Brief #N: <summary>"), never on cancelled/abandoned; removed the prior inline markSourceFeedbackAddressed. (C) /feedback inbox+detail show linked brief(s)+status (clickable, bounded eager-load); brief detail shows source feedback. 18 files +613/-40, no migration (columns existed). Suite 827/825 green, pint clean, build OK. Worker 1069 closed. First live instance of the #172 model-event/observer pattern. Worker filed dogfooding note #82.

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

    Dispatch request #64 marked done.

    agent · flower-175
  7. link added 1d ago
    agent · flower-175
  8. link added 1d ago
    agent · flower-175
  9. link added 1d ago
    agent · flower-175
  10. status change 1d ago
    agent · flower-175
  11. link added 1d ago
    agent · flower-175
  12. link added 1d ago
    agent · flower-175
  13. dispatched 1d ago

    Dispatch request #64 claimed.

    agent · flower-175
  14. participant joined 1d ago
    system · flower-175
  15. dispatched 1d ago

    Dispatch request #64 queued for flower.

    agent · flower-orchestrator
  16. status change 1d ago
    agent · flower-orchestrator
  17. status change 1d ago
    agent · flower-orchestrator
  18. note added 1d ago

    Operator confirmed the 3 recommended defaults (2026-07-04) — decisions LOCKED: (1) cardinality = existing briefs.feedback_id FK (many briefs → 1 feedback); auto-address the feedback when a linked brief FIRST reaches complete; no new polymorphic table. (2) cancelled/abandoned brief → do NOT auto-address the linked feedback (work didn't ship) — leave it open. (3) feedback status vocab = 'addressed'. Proceed with the full proposed scope A (auto-link on create: brief_create optional feedback_id + feedback_promote as canonical promote-to-brief that sets briefs.feedback_id + link_added event/provenance; feedback→brief back-reference) + B (Brief Eloquent observer auto-marks linked feedback 'addressed' on status→complete, idempotent, resolution="Brief #N: <summary>") + C (/feedback surfaces linked brief(s)+status clickable; brief detail surfaces source feedback).

    agent · flower-orchestrator
  19. note added 1d ago

    ## Motivation (first-hand this session: feedback #77 → brief #171) The feedback→brief flow is awkward to work with: - **Link not auto-set.** brief_create(origin=feedback) left briefs.feedback_id NULL — the only tie was a hand-typed ref in the spec. brief_create has no feedback_id param. - **No auto-close.** When #171 completed, feedback #77 did NOT auto-resolve — the worker manually ran the FeedbackStatus artisan command, fiddly because its worktree DB is isolated from MAIN's live feedback store. - **Not navigable.** /feedback doesn't surface the linked brief + status; the brief doesn't surface the source feedback. ## Proposed scope ### A. First-class, auto-populated feedback↔brief link - brief_create accepts an optional feedback_id; and/or make feedback_promote the canonical "promote to brief" path that sets briefs.feedback_id + emits a brief_events link_added + attaches provenance. Pass through appropriate links/context from the feedback into the brief. - Back-reference: feedback → its linked brief(s). ### B. Auto-close feedback when its linked brief completes (Eloquent model event) - A Brief observer: on status → complete, if a linked feedback exists and isn't already resolved, set feedback → addressed with resolution="Brief #N: <summary>", resolved_by/resolved_at. Idempotent. - **Recommended defaults (operator-confirmable):** 1. Cardinality: use existing briefs.feedback_id (many briefs → 1 feedback); auto-address the feedback when a linked brief first reaches complete. No polymorphic needed. 2. cancelled/abandoned brief → do NOT auto-address the feedback (work didn't ship); leave it open. 3. Feedback status vocab: 'addressed' (matches what #171's worker used + existing feedback.status). ### C. UX / surfacing - /feedback: show each item's linked brief(s) (id + status, clickable) + whether it auto-closed. - Brief detail: show the source feedback (id + link) when feedback_id is set. ## Relationship Concrete FIRST instance of the model-event-driven automation in #172 (app-wide health/audit-log) — proves the observer pattern before the broader audit log. Motivated by feedback #77 / brief #171. ## Open decisions (confirm or accept the recommended defaults above) 1. Link cardinality (recommend: existing FK, many-briefs→1-feedback). 2. cancelled/abandoned brief behavior (recommend: leave feedback open). 3. status vocab: addressed vs resolved (recommend: addressed). Status: idea — small refinement to lock the 3 decisions, then dispatchable.

    agent · flower-orchestrator
  20. participant joined 1d ago
    system · flower-orchestrator

epic · dependencies

Relationships

epic parent

depends on

No dependencies — dispatchable once planned.

agents · waves

Participants

  • flower-orchestrator participant · active
  • flower-175 participant · active
  • system:commit-trailer participant · active

trace · graph

Links

  • Commit #1983 execution
  • Commit #1984 execution
  • Session #3455 execution
  • Session #3451 execution
  • Session #3439 execution
  • Session #3453 execution
  • dispatch_request #64 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.