flower
/
All briefs
complete note flower

Feedback triage funnels — ops promotes feedback → brief or → orchestrator (or self-handles)

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.

#16 done fresh flower · flower/feedback-funnels
You are being dispatched from flower Brief #13: Feedback triage funnels — ops promotes feedback → brief or → orchestrator (or self-handles)

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

Target:
- project: flower (/Users/mikeferrara/Documents/code/flower)
- branch: flower/feedback-funnels
- worktree: not specified
- kind: fresh

Current brief spec:
## Spec: Feedback triage funnels — ops promotes feedback → brief (approval-gated) or → orchestrator index (autonomous)

**Origin:** flower-ops, from an operator (Mike) conversation 2026-07-01. Today ops triages the `feedback` table each cycle (sets status) but **actionable items dead-end at `triaged`** — there is no wired path from a feedback item to the work that resolves it. This brief builds that path so the feedback table becomes a real intake, not a graveyard. Operator re-raised it 2026-07-01 ("the ops daemon has no real way to promote a feedback item to a brief or have it addressed by the orchestrator/an agent — so they just sit in triaged") and gave the authority decision below.

### Current state (verified)
- ops pulls open feedback each cycle and sets `status` (`open|triaged|planned|addressed|wontfix|duplicate`).
- **bugs** ops can confirm+scope → already routed like a Sentry issue (todo + fix-spec + wake orchestrator). ✅
- **ideas / features / capability-gaps** → triaged + noted, then **sit idle** — no promotion into the briefs pipeline. ❌
- No `feedback_id` link on briefs; `briefs.origin` only ever `note`; `BriefOrigin` has no `feedback` case → traceability lost. Feedback model already has `STATUS_PLANNED`/`STATUS_ADDRESSED` ready for this.

## Authority model (OPERATOR-DECIDED 2026-07-01) — the gating rule
Split promotion authority by kind/source. **Defects flow; features wait for sign-off.**
- **Autonomous (NO operator approval):** `kind=bug`, `kind=mcp_issue` (confirmed defects), and **Sentry-sourced issues**. ops routes/promotes these itself with the existing Sentry discipline (dedup vs kv ledger, ≤2 promotions/cycle cap, ledger every disposition). Scoped bug w/ clear fix → **Funnel B** (orchestrator index: todo + fix-spec + wake orchestrator). This formalizes what ops already does for Sentry bugs.
- **Operator-approved (GATED):** `kind=idea` / feature requests / capability-gaps / anything that is **new or changed functionality**. ops MAY create the brief (draft) + link the feedback + place it in an **operator-approval queue**, but it MUST NOT advance to dispatch until the operator approves. Feedback marked `planned` (brief id) + flagged pending-approval.
- `kind=note` (praise/observation) → self-handle → `addressed` (no promotion).
- Ambiguous/needs-design bug → treat as feature-class (approval-gated), not autonomous.

## The dispositions
1. **Funnel A — feedback → BRIEF** (design/build; ideas/features). Promote to a brief (Capture), link them, mark feedback `planned` w/ brief id. For feature-class items the brief is **approval-gated** (above). Brief then enters capture→refine→dispatch.
2. **Funnel B — feedback → ORCHESTRATOR index** (confirmed scoped fixes: bug/mcp_issue/sentry). Route like a Sentry bug — Solo todo + fix-spec scratchpad + kv `routed_pending` + active-wake the orchestrator. **Autonomous.**
3. **Self-handle** (small/simple/in-scope): resolve directly → `addressed`. Role firewall: no app-code edits / no merge. When unsure, prefer a funnel.

## Mechanism (what to build)
1. **feedback ↔ brief link:** add nullable `feedback_id` FK to `briefs` (prefer a real FK for traceability + the inbox UI). Add **`BriefOrigin::feedback`**. Store the routed todo/fix-spec ids on the feedback (`feedback.context.routed = {todo, spec}`) so "what happened to this feedback" is answerable.
2. **Approval gate:** a brief born from feature-class feedback is created in an approval-pending state (stays `idea`/`refining` + a `needs_operator_approval` flag, surfaced in the operator inbox / a `/briefs` pending-approval filter + a `/feedback` badge). It CANNOT be dispatched until the operator approves (approve action → `planned`). bug/mcp_issue/sentry skip the gate.
3. **Promote surface:** `flower:feedback-promote {id} --to=brief|orchestrator` command **+ a `feedback_promote` MCP tool so the OPS DAEMON can promote programmatically** (this is the missing piece — no more tinker) **+ a `/feedback` "Promote" button** (operator). The tool enforces the authority model.
4. **Status semantics:** promote → `planned` (brief/route ref); shipped → `addressed`; declined → `wontfix`; merged-into-another → `duplicate`.
5. **Reverse flow:** when a feedback-born brief reaches `complete`, auto-mark the source feedback `addressed` (link the completing dispatch/commit).
6. **Guardrails:** dedup before promoting (existing brief/todo on the same idea — mirror kv `sentry:triaged`); ≤2 promotions/cycle cap; ledger every disposition; digest each cycle.

## Project scope of a feedback-born brief
feedback has no project column today (→ related to #25). Default the brief's primary project to **flower (id 16)**; allow re-scope during refinement. If #25 adds a project to feedback first, inherit it. Don't block on #25.

## Relationship to Brief 11 / #25
- The approval queue IS Brief 11's operator inbox — if 11's inbox is built, land gated briefs there; else ship a minimal pending-approval surface and let 11 absorb it.
- Project scope depends on #25 (feedback project column) — default to flower until then.

## Acceptance
- `feedback_id` FK on briefs + `BriefOrigin::feedback`; migration; suite green.
- `feedback_promote` MCP tool + `flower:feedback-promote` command + `/feedback` Promote button.
- **Authority enforced:** bug/mcp_issue/sentry → autonomous (Funnel B or auto-advanced brief); idea/feature → an approval-GATED brief that cannot dispatch until operator approval.
- Reverse flow: completing a feedback-born brief marks the source feedback `addressed`.
- Dedup + ≤2/cycle cap + ledger. ops charter §7 (scratchpad 1023) updated to the built mechanism (retire the tinker workaround).
- `Brief: #13` trailer.

## Sequencing (orchestrator note)
Dispatch AFTER Brief #31 (brief-relations) merges — both touch the `briefs` migrations + `BriefService` + recall briefs surface, so serialize to avoid conflict. #31 is in its final stage.

## Provenance
flower-ops created this from an operator conversation (first "ops creates a brief"). Operator authority decision 2026-07-01: bug/mcp_issue/sentry autonomous, features/changed-functionality operator-approved. Refined by orchestrator 2026-07-01 into a build-ready spec.

Recent/key trace events:
[1] participant_joined flower-orchestrator: (no body)
[2] spec_snapshot flower-orchestrator: ## Spec: Feedback triage funnels — ops promotes feedback → brief or → orchestrator (or self-handles)

**Origin:** flower-ops, from an operator (Mike) conversation on 2026-07-01, after ~63 triage cycles. Today the ops agent triages the `feedback` table each cycle (sets status), but **actionable items dead-end at `triaged`** — there is no wired path from a feedback item to the work that resolves it. This brief designs that path so a feedback item can be **routed into the right funnel** (or handled in place), turning the feedback table into a real intake, not a graveyard.

Refine with the orchestrator; then fold into **Brief 11** (operator-inbox + per-project daemons) or ship independently after 11.

### The problem (current state, verified)
- ops pulls open feedback each cycle and sets `status` (`open|triaged|planned|addressed|wontfix|duplicate`) via `flower:feedback-status`.
- **Bugs** that ops can confirm+scope → ops already routes them like a Sentry issue (todo + fix-spec + wake orchestrator). ✅
- **Ideas / feature requests / capability-gaps** (e.g. #23 resume-picker, #24 tabbed spec markdown, #25 brief project-scoping) → ops **triages + notes**, and then they **sit idle** — no promotion into the briefs pipeline. ❌
- There is **no `feedback_id` link on briefs** and `briefs.origin` is only ever `"note"` — so nothing connects a feedback item to a brief or a routed fix. Traceability is lost.

### Proposal — three dispositions ops can apply to a triaged feedback item
1. **Funnel A — feedback → BRIEF** (design/build work: ideas, features, capability-gaps, anything non-trivial that needs refinement before building). ops **promotes** the item to a brief (Capture), links them, and marks the feedback `planned` with the brief id. The brief then enters the normal capture → refine → dispatch loop (this is the briefs pipeline's whole purpose).
2. **Funnel B — feedback → ORCHESTRATOR index** (confirmed, scoped fixes: a real code defect with a clear fix). ops routes it exactly like a Sentry bug — Solo todo + fix-spec scratchpad + kv `routed_pending` + active-wake the orchestrator, which dispatches to a worker and merges after review. (This is the existing route model; this brief just names it as the "orchestrator index/funnel" for feedback.)
3. **Self-handle** (small / simple / straightforward, inside ops' safe scope): ops resolves it directly and marks `addressed` — e.g. a docs/scratchpad note, a ledger/registry cleanup, filing a clarifying sub-item, answering a question. **Role firewall:** self-handle does NOT include editing app code or merging (unless the operating model explicitly widens ops' scope). When in doubt between self-handle and a funnel, prefer the funnel.

### Routing table (starting point — refine this)
| feedback.kind | Nature | Disposition |
|---|---|---|
| `bug` | Confirmed code defect, clear fix, low risk | **Funnel B** (orchestrator) — or **self-handle** if trivial + in ops scope |
| `bug` | Real but ambiguous / risky / needs design | **Funnel A** (brief) or REPORT to orchestrator |
| `idea` / feature | Needs design + build | **Funnel A** (brief) |
| `idea` | Tiny, obvious, low-risk enhancement | **Funnel B** or self-handle (operator's call on threshold) |
| `note` (praise / observation) | No action | **self-handle**: acknowledge → `addressed` |
| `mcp_issue` | Recall/MCP defect | **Funnel B** (orchestrator) or self-handle if config |
| duplicate / empty / noise | — | `duplicate` / `wontfix` |

### Mechanism (what to build)
- **feedback ↔ brief link:** add `feedback_id` (nullable FK) to `briefs`, OR a `brief_feedback` link table (1 brief ← many feedback), OR store `brief_id` in `feedback.context`. Prefer a real FK for traceability + the roster/inbox UI.
- **feedback ↔ routed-fix link:** store the Solo `todo_id` / fix-spec id on the feedback (e.g. `feedback.context.routed = {todo, spec}`) so "what happened to this feedback" is answerable.
- **Status semantics:** promote → `planned` (with the brief/todo ref); resolved/shipped → `addressed`; declined → `wontfix`; merged-into-another → `duplicate`.
- **Promote action/command:** a `flower:feedback-promote {id} --to=brief|orchestrator` command (and a roster/inbox UI button), so ops (and the operator) can promote with one call. **Until it exists, ops promotes via tinker/script** (create the brief row / todo, set the link, set status).
- **Dedup:** before promoting, check for an existing brief/todo covering the same idea (don't spawn duplicates — mirror the kv `sentry:triaged` dedup discipline).

### Relationship to Brief 11
- Brief 11's **operator inbox** is where the orchestrator drains routed items; this brief defines what ops *puts into* that inbox and how. The **feedback → brief** funnel is the intake side of the per-project briefs loop.
- Natural home: fold the routing table + promote-mechanism into Brief 11, or ship this as a focused follow-up once 11's roster/inbox lands.

### Open questions for refinement (with the orchestrator)
- Where exactly is the **ops self-handle boundary**? (docs/registry cleanups yes; app code no — but is there a "trivial config/one-liner" middle ground ops may own?)
- **Auto-promote vs operator-approved?** Should ops promote autonomously, or queue promotions for operator sign-off (at least initially, like the current routing model's "first pass = digest only")?
- **Project scope of a feedback-born brief** — inherit the feedback's project? (feedback has no project column today — related to #25.)
- **Reverse flow:** when a brief born from feedback ships, auto-mark the source feedback `addressed`?
- Volume/rate limits so a burst of feedback can't flood the brief queue (mirror the ≤2 routings/cycle cap).

### Build notes
- Reuse the ops routing discipline (scratchpad 1023 §1–§2): ledger every disposition, cap promotions/cycle, dedup before promoting, digest each cycle.
- Meta-dogfood: this brief was itself created by ops from an operator conversation — the first exercise of "ops creates a brief." The worktree-graceful-handling feedback item filed alongside it is the first candidate for **Funnel A**.
[3] refinement flower-orchestrator: ## Spec: Feedback triage funnels — ops promotes feedback → brief (approval-gated) or → orchestrator index (autonomous)

**Origin:** flower-ops, from an operator (Mike) conversation 2026-07-01. Today ops triages the `feedback` table each cycle (sets status) but **actionable items dead-end at `triaged`** — there is no wired path from a feedback item to the work that resolves it. This brief builds that path so the feedback table becomes a real intake, not a graveyard. Operator re-raised it 2026-07-01 ("the ops daemon has no real way to promote a feedback item to a brief or have it addressed by the orchestrator/an agent — so they just sit in triaged") and gave the authority decision below.

### Current state (verified)
- ops pulls open feedback each cycle and sets `status` (`open|triaged|planned|addressed|wontfix|duplicate`).
- **bugs** ops can confirm+scope → already routed like a Sentry issue (todo + fix-spec + wake orchestrator). ✅
- **ideas / features / capability-gaps** → triaged + noted, then **sit idle** — no promotion into the briefs pipeline. ❌
- No `feedback_id` link on briefs; `briefs.origin` only ever `note`; `BriefOrigin` has no `feedback` case → traceability lost. Feedback model already has `STATUS_PLANNED`/`STATUS_ADDRESSED` ready for this.

## Authority model (OPERATOR-DECIDED 2026-07-01) — the gating rule
Split promotion authority by kind/source. **Defects flow; features wait for sign-off.**
- **Autonomous (NO operator approval):** `kind=bug`, `kind=mcp_issue` (confirmed defects), and **Sentry-sourced issues**. ops routes/promotes these itself with the existing Sentry discipline (dedup vs kv ledger, ≤2 promotions/cycle cap, ledger every disposition). Scoped bug w/ clear fix → **Funnel B** (orchestrator index: todo + fix-spec + wake orchestrator). This formalizes what ops already does for Sentry bugs.
- **Operator-approved (GATED):** `kind=idea` / feature requests / capability-gaps / anything that is **new or changed functionality**. ops MAY create the brief (draft) + link the feedback + place it in an **operator-approval queue**, but it MUST NOT advance to dispatch until the operator approves. Feedback marked `planned` (brief id) + flagged pending-approval.
- `kind=note` (praise/observation) → self-handle → `addressed` (no promotion).
- Ambiguous/needs-design bug → treat as feature-class (approval-gated), not autonomous.

## The dispositions
1. **Funnel A — feedback → BRIEF** (design/build; ideas/features). Promote to a brief (Capture), link them, mark feedback `planned` w/ brief id. For feature-class items the brief is **approval-gated** (above). Brief then enters capture→refine→dispatch.
2. **Funnel B — feedback → ORCHESTRATOR index** (confirmed scoped fixes: bug/mcp_issue/sentry). Route like a Sentry bug — Solo todo + fix-spec scratchpad + kv `routed_pending` + active-wake the orchestrator. **Autonomous.**
3. **Self-handle** (small/simple/in-scope): resolve directly → `addressed`. Role firewall: no app-code edits / no merge. When unsure, prefer a funnel.

## Mechanism (what to build)
1. **feedback ↔ brief link:** add nullable `feedback_id` FK to `briefs` (prefer a real FK for traceability + the inbox UI). Add **`BriefOrigin::feedback`**. Store the routed todo/fix-spec ids on the feedback (`feedback.context.routed = {todo, spec}`) so "what happened to this feedback" is answerable.
2. **Approval gate:** a brief born from feature-class feedback is created in an approval-pending state (stays `idea`/`refining` + a `needs_operator_approval` flag, surfaced in the operator inbox / a `/briefs` pending-approval filter + a `/feedback` badge). It CANNOT be dispatched until the operator approves (approve action → `planned`). bug/mcp_issue/sentry skip the gate.
3. **Promote surface:** `flower:feedback-promote {id} --to=brief|orchestrator` command **+ a `feedback_promote` MCP tool so the OPS DAEMON can promote programmatically** (this is the missing piece — no more tinker) **+ a `/feedback` "Promote" button** (operator). The tool enforces the authority model.
4. **Status semantics:** promote → `planned` (brief/route ref); shipped → `addressed`; declined → `wontfix`; merged-into-another → `duplicate`.
5. **Reverse flow:** when a feedback-born brief reaches `complete`, auto-mark the source feedback `addressed` (link the completing dispatch/commit).
6. **Guardrails:** dedup before promoting (existing brief/todo on the same idea — mirror kv `sentry:triaged`); ≤2 promotions/cycle cap; ledger every disposition; digest each cycle.

## Project scope of a feedback-born brief
feedback has no project column today (→ related to #25). Default the brief's primary project to **flower (id 16)**; allow re-scope during refinement. If #25 adds a project to feedback first, inherit it. Don't block on #25.

## Relationship to Brief 11 / #25
- The approval queue IS Brief 11's operator inbox — if 11's inbox is built, land gated briefs there; else ship a minimal pending-approval surface and let 11 absorb it.
- Project scope depends on #25 (feedback project column) — default to flower until then.

## Acceptance
- `feedback_id` FK on briefs + `BriefOrigin::feedback`; migration; suite green.
- `feedback_promote` MCP tool + `flower:feedback-promote` command + `/feedback` Promote button.
- **Authority enforced:** bug/mcp_issue/sentry → autonomous (Funnel B or auto-advanced brief); idea/feature → an approval-GATED brief that cannot dispatch until operator approval.
- Reverse flow: completing a feedback-born brief marks the source feedback `addressed`.
- Dedup + ≤2/cycle cap + ledger. ops charter §7 (scratchpad 1023) updated to the built mechanism (retire the tinker workaround).
- `Brief: #13` trailer.

## Sequencing (orchestrator note)
Dispatch AFTER Brief #31 (brief-relations) merges — both touch the `briefs` migrations + `BriefService` + recall briefs surface, so serialize to avoid conflict. #31 is in its final stage.

## Provenance
flower-ops created this from an operator conversation (first "ops creates a brief"). Operator authority decision 2026-07-01: bug/mcp_issue/sentry autonomous, features/changed-functionality operator-approved. Refined by orchestrator 2026-07-01 into a build-ready spec.
[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.
- Add a git commit trailer `Brief: #13` 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 4d ago
    agent · system:commit-trailer
  2. link added 4d ago
    agent · system:commit-trailer
  3. participant joined 4d ago
    system · system:commit-trailer
  4. status change 4d ago
    agent · flower-orchestrator
  5. dispatched 4d ago

    Dispatch request #16 marked done.

    agent · flower-orchestrator
  6. link added 4d ago
    agent · system:brief-autolink
  7. link added 4d ago
    agent · system:brief-autolink
  8. link added 4d ago
    agent · system:brief-autolink
  9. participant joined 4d ago
    system · system:brief-autolink
  10. comment 4d ago

    Progress: implemented Brief #13 feedback funnels backend on branch flower/feedback-funnels. Added feedback_id and needs_operator_approval on briefs, feedback_promote MCP tool, flower:feedback-promote command, /feedback promote controls, autonomous Funnel B Solo todo+fix-spec routing, operator-gated feedback-born briefs, note self-handle, dedup/cycle ledger, dispatch approval guards, reverse feedback addressed-on-brief-complete, and tests. Commits: 90080cd, cf02928.

    agent · agent:codex
  11. participant joined 4d ago
    system · agent:codex
  12. link added 4d ago
    agent · flower-orchestrator
  13. dispatched 4d ago

    Dispatch request #16 queued for flower.

    agent · flower-orchestrator
  14. status change 4d ago
    agent · flower-orchestrator
  15. status change 4d ago
    agent · flower-orchestrator
  16. refinement 4d ago

    ## Spec: Feedback triage funnels — ops promotes feedback → brief (approval-gated) or → orchestrator index (autonomous) **Origin:** flower-ops, from an operator (Mike) conversation 2026-07-01. Today ops triages the `feedback` table each cycle (sets status) but **actionable items dead-end at `triaged`** — there is no wired path from a feedback item to the work that resolves it. This brief builds that path so the feedback table becomes a real intake, not a graveyard. Operator re-raised it 2026-07-01 ("the ops daemon has no real way to promote a feedback item to a brief or have it addressed by the orchestrator/an agent — so they just sit in triaged") and gave the authority decision below. ### Current state (verified) - ops pulls open feedback each cycle and sets `status` (`open|triaged|planned|addressed|wontfix|duplicate`). - **bugs** ops can confirm+scope → already routed like a Sentry issue (todo + fix-spec + wake orchestrator). ✅ - **ideas / features / capability-gaps** → triaged + noted, then **sit idle** — no promotion into the briefs pipeline. ❌ - No `feedback_id` link on briefs; `briefs.origin` only ever `note`; `BriefOrigin` has no `feedback` case → traceability lost. Feedback model already has `STATUS_PLANNED`/`STATUS_ADDRESSED` ready for this. ## Authority model (OPERATOR-DECIDED 2026-07-01) — the gating rule Split promotion authority by kind/source. **Defects flow; features wait for sign-off.** - **Autonomous (NO operator approval):** `kind=bug`, `kind=mcp_issue` (confirmed defects), and **Sentry-sourced issues**. ops routes/promotes these itself with the existing Sentry discipline (dedup vs kv ledger, ≤2 promotions/cycle cap, ledger every disposition). Scoped bug w/ clear fix → **Funnel B** (orchestrator index: todo + fix-spec + wake orchestrator). This formalizes what ops already does for Sentry bugs. - **Operator-approved (GATED):** `kind=idea` / feature requests / capability-gaps / anything that is **new or changed functionality**. ops MAY create the brief (draft) + link the feedback + place it in an **operator-approval queue**, but it MUST NOT advance to dispatch until the operator approves. Feedback marked `planned` (brief id) + flagged pending-approval. - `kind=note` (praise/observation) → self-handle → `addressed` (no promotion). - Ambiguous/needs-design bug → treat as feature-class (approval-gated), not autonomous. ## The dispositions 1. **Funnel A — feedback → BRIEF** (design/build; ideas/features). Promote to a brief (Capture), link them, mark feedback `planned` w/ brief id. For feature-class items the brief is **approval-gated** (above). Brief then enters capture→refine→dispatch. 2. **Funnel B — feedback → ORCHESTRATOR index** (confirmed scoped fixes: bug/mcp_issue/sentry). Route like a Sentry bug — Solo todo + fix-spec scratchpad + kv `routed_pending` + active-wake the orchestrator. **Autonomous.** 3. **Self-handle** (small/simple/in-scope): resolve directly → `addressed`. Role firewall: no app-code edits / no merge. When unsure, prefer a funnel. ## Mechanism (what to build) 1. **feedback ↔ brief link:** add nullable `feedback_id` FK to `briefs` (prefer a real FK for traceability + the inbox UI). Add **`BriefOrigin::feedback`**. Store the routed todo/fix-spec ids on the feedback (`feedback.context.routed = {todo, spec}`) so "what happened to this feedback" is answerable. 2. **Approval gate:** a brief born from feature-class feedback is created in an approval-pending state (stays `idea`/`refining` + a `needs_operator_approval` flag, surfaced in the operator inbox / a `/briefs` pending-approval filter + a `/feedback` badge). It CANNOT be dispatched until the operator approves (approve action → `planned`). bug/mcp_issue/sentry skip the gate. 3. **Promote surface:** `flower:feedback-promote {id} --to=brief|orchestrator` command **+ a `feedback_promote` MCP tool so the OPS DAEMON can promote programmatically** (this is the missing piece — no more tinker) **+ a `/feedback` "Promote" button** (operator). The tool enforces the authority model. 4. **Status semantics:** promote → `planned` (brief/route ref); shipped → `addressed`; declined → `wontfix`; merged-into-another → `duplicate`. 5. **Reverse flow:** when a feedback-born brief reaches `complete`, auto-mark the source feedback `addressed` (link the completing dispatch/commit). 6. **Guardrails:** dedup before promoting (existing brief/todo on the same idea — mirror kv `sentry:triaged`); ≤2 promotions/cycle cap; ledger every disposition; digest each cycle. ## Project scope of a feedback-born brief feedback has no project column today (→ related to #25). Default the brief's primary project to **flower (id 16)**; allow re-scope during refinement. If #25 adds a project to feedback first, inherit it. Don't block on #25. ## Relationship to Brief 11 / #25 - The approval queue IS Brief 11's operator inbox — if 11's inbox is built, land gated briefs there; else ship a minimal pending-approval surface and let 11 absorb it. - Project scope depends on #25 (feedback project column) — default to flower until then. ## Acceptance - `feedback_id` FK on briefs + `BriefOrigin::feedback`; migration; suite green. - `feedback_promote` MCP tool + `flower:feedback-promote` command + `/feedback` Promote button. - **Authority enforced:** bug/mcp_issue/sentry → autonomous (Funnel B or auto-advanced brief); idea/feature → an approval-GATED brief that cannot dispatch until operator approval. - Reverse flow: completing a feedback-born brief marks the source feedback `addressed`. - Dedup + ≤2/cycle cap + ledger. ops charter §7 (scratchpad 1023) updated to the built mechanism (retire the tinker workaround). - `Brief: #13` trailer. ## Sequencing (orchestrator note) Dispatch AFTER Brief #31 (brief-relations) merges — both touch the `briefs` migrations + `BriefService` + recall briefs surface, so serialize to avoid conflict. #31 is in its final stage. ## Provenance flower-ops created this from an operator conversation (first "ops creates a brief"). Operator authority decision 2026-07-01: bug/mcp_issue/sentry autonomous, features/changed-functionality operator-approved. Refined by orchestrator 2026-07-01 into a build-ready spec.

    agent · flower-orchestrator
  17. spec snapshot 4d ago

    ## Spec: Feedback triage funnels — ops promotes feedback → brief or → orchestrator (or self-handles) **Origin:** flower-ops, from an operator (Mike) conversation on 2026-07-01, after ~63 triage cycles. Today the ops agent triages the `feedback` table each cycle (sets status), but **actionable items dead-end at `triaged`** — there is no wired path from a feedback item to the work that resolves it. This brief designs that path so a feedback item can be **routed into the right funnel** (or handled in place), turning the feedback table into a real intake, not a graveyard. Refine with the orchestrator; then fold into **Brief 11** (operator-inbox + per-project daemons) or ship independently after 11. ### The problem (current state, verified) - ops pulls open feedback each cycle and sets `status` (`open|triaged|planned|addressed|wontfix|duplicate`) via `flower:feedback-status`. - **Bugs** that ops can confirm+scope → ops already routes them like a Sentry issue (todo + fix-spec + wake orchestrator). ✅ - **Ideas / feature requests / capability-gaps** (e.g. #23 resume-picker, #24 tabbed spec markdown, #25 brief project-scoping) → ops **triages + notes**, and then they **sit idle** — no promotion into the briefs pipeline. ❌ - There is **no `feedback_id` link on briefs** and `briefs.origin` is only ever `"note"` — so nothing connects a feedback item to a brief or a routed fix. Traceability is lost. ### Proposal — three dispositions ops can apply to a triaged feedback item 1. **Funnel A — feedback → BRIEF** (design/build work: ideas, features, capability-gaps, anything non-trivial that needs refinement before building). ops **promotes** the item to a brief (Capture), links them, and marks the feedback `planned` with the brief id. The brief then enters the normal capture → refine → dispatch loop (this is the briefs pipeline's whole purpose). 2. **Funnel B — feedback → ORCHESTRATOR index** (confirmed, scoped fixes: a real code defect with a clear fix). ops routes it exactly like a Sentry bug — Solo todo + fix-spec scratchpad + kv `routed_pending` + active-wake the orchestrator, which dispatches to a worker and merges after review. (This is the existing route model; this brief just names it as the "orchestrator index/funnel" for feedback.) 3. **Self-handle** (small / simple / straightforward, inside ops' safe scope): ops resolves it directly and marks `addressed` — e.g. a docs/scratchpad note, a ledger/registry cleanup, filing a clarifying sub-item, answering a question. **Role firewall:** self-handle does NOT include editing app code or merging (unless the operating model explicitly widens ops' scope). When in doubt between self-handle and a funnel, prefer the funnel. ### Routing table (starting point — refine this) | feedback.kind | Nature | Disposition | |---|---|---| | `bug` | Confirmed code defect, clear fix, low risk | **Funnel B** (orchestrator) — or **self-handle** if trivial + in ops scope | | `bug` | Real but ambiguous / risky / needs design | **Funnel A** (brief) or REPORT to orchestrator | | `idea` / feature | Needs design + build | **Funnel A** (brief) | | `idea` | Tiny, obvious, low-risk enhancement | **Funnel B** or self-handle (operator's call on threshold) | | `note` (praise / observation) | No action | **self-handle**: acknowledge → `addressed` | | `mcp_issue` | Recall/MCP defect | **Funnel B** (orchestrator) or self-handle if config | | duplicate / empty / noise | — | `duplicate` / `wontfix` | ### Mechanism (what to build) - **feedback ↔ brief link:** add `feedback_id` (nullable FK) to `briefs`, OR a `brief_feedback` link table (1 brief ← many feedback), OR store `brief_id` in `feedback.context`. Prefer a real FK for traceability + the roster/inbox UI. - **feedback ↔ routed-fix link:** store the Solo `todo_id` / fix-spec id on the feedback (e.g. `feedback.context.routed = {todo, spec}`) so "what happened to this feedback" is answerable. - **Status semantics:** promote → `planned` (with the brief/todo ref); resolved/shipped → `addressed`; declined → `wontfix`; merged-into-another → `duplicate`. - **Promote action/command:** a `flower:feedback-promote {id} --to=brief|orchestrator` command (and a roster/inbox UI button), so ops (and the operator) can promote with one call. **Until it exists, ops promotes via tinker/script** (create the brief row / todo, set the link, set status). - **Dedup:** before promoting, check for an existing brief/todo covering the same idea (don't spawn duplicates — mirror the kv `sentry:triaged` dedup discipline). ### Relationship to Brief 11 - Brief 11's **operator inbox** is where the orchestrator drains routed items; this brief defines what ops *puts into* that inbox and how. The **feedback → brief** funnel is the intake side of the per-project briefs loop. - Natural home: fold the routing table + promote-mechanism into Brief 11, or ship this as a focused follow-up once 11's roster/inbox lands. ### Open questions for refinement (with the orchestrator) - Where exactly is the **ops self-handle boundary**? (docs/registry cleanups yes; app code no — but is there a "trivial config/one-liner" middle ground ops may own?) - **Auto-promote vs operator-approved?** Should ops promote autonomously, or queue promotions for operator sign-off (at least initially, like the current routing model's "first pass = digest only")? - **Project scope of a feedback-born brief** — inherit the feedback's project? (feedback has no project column today — related to #25.) - **Reverse flow:** when a brief born from feedback ships, auto-mark the source feedback `addressed`? - Volume/rate limits so a burst of feedback can't flood the brief queue (mirror the ≤2 routings/cycle cap). ### Build notes - Reuse the ops routing discipline (scratchpad 1023 §1–§2): ledger every disposition, cap promotions/cycle, dedup before promoting, digest each cycle. - Meta-dogfood: this brief was itself created by ops from an operator conversation — the first exercise of "ops creates a brief." The worktree-graceful-handling feedback item filed alongside it is the first candidate for **Funnel A**.

    system · flower-orchestrator
  18. participant joined 4d ago
    system · flower-orchestrator

epic · dependencies

Relationships

epic parent

depends on

No dependencies — dispatchable once planned.

agents · waves

Participants

  • flower-orchestrator participant · active
  • agent:codex participant · active
  • system:brief-autolink participant · active
  • system:commit-trailer participant · active

trace · graph

Links

  • Commit #1222 execution
  • Commit #1223 execution
  • Commit #1196 result
  • Commit #1201 result
  • Commit #1202 result
  • Scratchpad #346 execution

scope

Projects

No project yet

Assign one so this brief appears in project-scoped queues, lists, and refine loops.

dogfood · read-only

Agent’s-eye view

The literal recall_brief payload an agent gets — same service path as the MCP tool.