flower
/
All briefs
complete draft note flower

Grouping/Combining/Chaining/Blocking Briefs What I'm seeing is cases

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.

#14 done fresh flower · flower/brief-relations
1 scratchpad
You are being dispatched from flower Brief #31: Grouping/Combining/Chaining/Blocking Briefs

What I'm seeing is cases

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

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

Current brief spec:
## Goal
Make brief **relationships** first-class so the orchestrator (and the refine daemon) can group
related briefs and enforce dependency ordering — replacing the manual dependency-juggling we do
today (e.g. #26 → #22 → #27, backend-before-UI, green-up-before-merge). **v1 = epic grouping +
depends-on gating.** Chain-with-agent-affinity and brief-merge are noted-future (v2+).

## v1 scope

### 1. Epic grouping (parent → children)  [operator: epic-parent model]
- Add `parent_brief_id` (nullable self-FK) to `briefs`. A brief has ≤1 parent "epic"; an epic has
  many children. (No separate type needed; an epic is just a brief with children — optionally a flag.)
- `recall_brief` shows the epic parent + children; `recall_briefs` can filter/group by epic;
  `/briefs` nests children under their epic with a rollup.
- MCP: `brief_set_parent(brief_id, parent_id|null, actor_ref)`.
- Use: batch-refine a set under one epic; see the epic's progress at a glance.

### 2. Depends-on gating (the load-bearing primitive)  [operator: gating-only in v1]
- Add `brief_dependencies` (or extend `brief_links` with a brief↔brief `blocks` relation):
  `brief_id` (dependent) + `depends_on_brief_id` (blocker) + `actor_ref`. A brief may depend on N.
- **Server-enforced (like Solo todo blockers):** `brief_dispatch` REFUSES a brief with any
  incomplete dependency (blocker status ∉ {complete, cancelled}); returns a clear
  "blocked by #X (status Y)".
- On a brief reaching `complete`: recompute + **RETURN the list of briefs it newly unblocked**
  (Solo-style "returns what it unlocked") so the orchestrator can dispatch them immediately.
- `recall_dispatch_queue` excludes/flags blocked briefs + adds a `dispatchable` (unblocked+planned)
  filter; `recall_brief` shows depends-on / blocking both directions.
- MCP: `brief_depend(brief_id, depends_on_id, actor_ref)` / `brief_undepend(...)`.
- **Cycle guard:** reject an edge that would create a dependency cycle.

### 3. UI
- `/briefs`: epic nesting; "blocked by #X" / "blocking #Y" badges; a "dispatchable now" filter.
- Brief detail: manage parent + dependencies.

## Why now
This is what makes the refine daemon (#27) powerful: as it batch-refines a handful of briefs it
encodes epic + depends-on relations, so by the time they're `planned` the orchestrator
auto-dispatches them in dependency order — instead of the orchestrator eyeballing it. It captures
the dependency reasoning we've done by hand all session.

## Acceptance
- Migrations: `parent_brief_id` + `brief_dependencies`; cycle-prevention.
- `brief_dispatch` server-refuses a blocked brief; completing a brief returns newly-unblocked ids.
- `recall_dispatch_queue` / `recall_briefs` respect blocking + epic; `recall_brief` shows relations.
- MCP tools: set-parent / depend / undepend (actor_ref → auto-participant), matching the brief_* shape.
- `/briefs` UI: epic nesting + blocked badges + dispatchable filter.
- Tests; suite green. `Brief: #31` trailer.

## Noted-future (OUT of v1)
- **Chain with agent-affinity** — on a dependent unblocking, hand it to the SAME agent if free,
  else requeue for the orchestrator (v2, once we see the refine-daemon queueing pattern).
- **Merge/collapse** N briefs → 1 (editorial op) (v3).

## Provenance
Operator brief #31 (2026-07-01) refined live with the orchestrator: 4 words → 2 primitives (epic
grouping + depends-on gating) + 2 noted-future patterns. Operator decisions: grouping = epic-parent;
chaining = depends-on gating only in v1.

Recent/key trace events:
[1] participant_joined operator:mike: (no body)
[2] note_added operator:mike: Grouping/Combining/Chaining/Blocking Briefs

What I'm seeing is cases where briefs could or should be logically grouped/tasked together - is that something we should make first class? Some sort of linking/relation that aligns a given group of briefs? Or even/also the ability to collapse multiple briefs into a single (either pre-existing or into a new) brief?

And then, what about the idea of chaining the briefs to create task chains, either for a specific agent to handle one after another or potentially different agents tasked with different briefs on the chain? Or maybe an agent can be tasked with a brief on the chain and when it's done if there's no agent assigned to the follow up/next brief in the chain it's back into the queue to be dispatched by the orchestrator as it sees fit? And this kind of brings on the idea of blocks/locks? Could those be useful? Or something similar to what Solo does with todos (I think) where they can be locked by another todo and when completing the first it returns an array/list/object of todos unlocked by it's completion or something?)

Various scenarios here but one that I'm seeing is something like me loading up a handful or even a bunch of briefs and then kind of going through them and refining them in a batch before getting them ready to dispatch - or, even, really, any time there's multiple briefs ready to dispatch... does it make sense for you/the orchestrator to be able to group/combine/chain/lock them? Maybe something design-related comes in and the design agent is on a task but the one that just came in is a natural follow up to that one - add it to a chain on the in process brief so that when that agent finishes it's alerted that there's another task on the chain that it's been assigned to next? 

Or maybe there's a dispatchable brief in the collection but you know that there's a bug that's related that needs to be handled first, you could chain the brief after the bugfix and lock it pending that bugfix is successful?

Let me know your thoughts/ideas/refinements/etc.
[3] participant_joined flower-orchestrator: (no body)
[4] spec_snapshot flower-orchestrator: Grouping/Combining/Chaining/Blocking Briefs

What I'm seeing is cases where briefs could or should be logically grouped/tasked together - is that something we should make first class? Some sort of linking/relation that aligns a given group of briefs? Or even/also the ability to collapse multiple briefs into a single (either pre-existing or into a new) brief?

And then, what about the idea of chaining the briefs to create task chains, either for a specific agent to handle one after another or potentially different agents tasked with different briefs on the chain? Or maybe an agent can be tasked with a brief on the chain and when it's done if there's no agent assigned to the follow up/next brief in the chain it's back into the queue to be dispatched by the orchestrator as it sees fit? And this kind of brings on the idea of blocks/locks? Could those be useful? Or something similar to what Solo does with todos (I think) where they can be locked by another todo and when completing the first it returns an array/list/object of todos unlocked by it's completion or something?)

Various scenarios here but one that I'm seeing is something like me loading up a handful or even a bunch of briefs and then kind of going through them and refining them in a batch before getting them ready to dispatch - or, even, really, any time there's multiple briefs ready to dispatch... does it make sense for you/the orchestrator to be able to group/combine/chain/lock them? Maybe something design-related comes in and the design agent is on a task but the one that just came in is a natural follow up to that one - add it to a chain on the in process brief so that when that agent finishes it's alerted that there's another task on the chain that it's been assigned to next? 

Or maybe there's a dispatchable brief in the collection but you know that there's a bug that's related that needs to be handled first, you could chain the brief after the bugfix and lock it pending that bugfix is successful?

Let me know your thoughts/ideas/refinements/etc.
[5] refinement flower-orchestrator: ## Goal
Make brief **relationships** first-class so the orchestrator (and the refine daemon) can group
related briefs and enforce dependency ordering — replacing the manual dependency-juggling we do
today (e.g. #26 → #22 → #27, backend-before-UI, green-up-before-merge). **v1 = epic grouping +
depends-on gating.** Chain-with-agent-affinity and brief-merge are noted-future (v2+).

## v1 scope

### 1. Epic grouping (parent → children)  [operator: epic-parent model]
- Add `parent_brief_id` (nullable self-FK) to `briefs`. A brief has ≤1 parent "epic"; an epic has
  many children. (No separate type needed; an epic is just a brief with children — optionally a flag.)
- `recall_brief` shows the epic parent + children; `recall_briefs` can filter/group by epic;
  `/briefs` nests children under their epic with a rollup.
- MCP: `brief_set_parent(brief_id, parent_id|null, actor_ref)`.
- Use: batch-refine a set under one epic; see the epic's progress at a glance.

### 2. Depends-on gating (the load-bearing primitive)  [operator: gating-only in v1]
- Add `brief_dependencies` (or extend `brief_links` with a brief↔brief `blocks` relation):
  `brief_id` (dependent) + `depends_on_brief_id` (blocker) + `actor_ref`. A brief may depend on N.
- **Server-enforced (like Solo todo blockers):** `brief_dispatch` REFUSES a brief with any
  incomplete dependency (blocker status ∉ {complete, cancelled}); returns a clear
  "blocked by #X (status Y)".
- On a brief reaching `complete`: recompute + **RETURN the list of briefs it newly unblocked**
  (Solo-style "returns what it unlocked") so the orchestrator can dispatch them immediately.
- `recall_dispatch_queue` excludes/flags blocked briefs + adds a `dispatchable` (unblocked+planned)
  filter; `recall_brief` shows depends-on / blocking both directions.
- MCP: `brief_depend(brief_id, depends_on_id, actor_ref)` / `brief_undepend(...)`.
- **Cycle guard:** reject an edge that would create a dependency cycle.

### 3. UI
- `/briefs`: epic nesting; "blocked by #X" / "blocking #Y" badges; a "dispatchable now" filter.
- Brief detail: manage parent + dependencies.

## Why now
This is what makes the refine daemon (#27) powerful: as it batch-refines a handful of briefs it
encodes epic + depends-on relations, so by the time they're `planned` the orchestrator
auto-dispatches them in dependency order — instead of the orchestrator eyeballing it. It captures
the dependency reasoning we've done by hand all session.

## Acceptance
- Migrations: `parent_brief_id` + `brief_dependencies`; cycle-prevention.
- `brief_dispatch` server-refuses a blocked brief; completing a brief returns newly-unblocked ids.
- `recall_dispatch_queue` / `recall_briefs` respect blocking + epic; `recall_brief` shows relations.
- MCP tools: set-parent / depend / undepend (actor_ref → auto-participant), matching the brief_* shape.
- `/briefs` UI: epic nesting + blocked badges + dispatchable filter.
- Tests; suite green. `Brief: #31` trailer.

## Noted-future (OUT of v1)
- **Chain with agent-affinity** — on a dependent unblocking, hand it to the SAME agent if free,
  else requeue for the orchestrator (v2, once we see the refine-daemon queueing pattern).
- **Merge/collapse** N briefs → 1 (editorial op) (v3).

## Provenance
Operator brief #31 (2026-07-01) refined live with the orchestrator: 4 words → 2 primitives (epic
grouping + depends-on gating) + 2 noted-future patterns. Operator decisions: grouping = epic-parent;
chaining = depends-on gating only in v1.
[6] status_change flower-orchestrator: (no body)
[7] link_added flower-orchestrator: (no body)

Recommended linked context:
{
    "todos": [],
    "scratchpads": [
        {
            "id": 346,
            "solo_scratchpad_id": "1026",
            "name": "Orchestrator HANDOFF — flower build (live state)",
            "archived": false,
            "revision": 18
        }
    ]
}

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: #31` 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. link added 4d ago
    agent · system:commit-trailer
  4. link added 4d ago
    agent · system:commit-trailer
  5. link added 4d ago
    agent · system:commit-trailer
  6. link added 4d ago
    agent · system:commit-trailer
  7. link added 4d ago
    agent · system:commit-trailer
  8. participant joined 4d ago
    system · system:commit-trailer
  9. status change 4d ago
    agent · flower-orchestrator
  10. dispatched 4d ago

    Dispatch request #14 marked done.

    agent · flower-orchestrator
  11. note added 4d ago

    Brief #31 v1 COMPLETE on branch flower/brief-relations (off master) — full suite green (427 passed, 1 pre-existing skip, 3034 assertions), pint clean. Ready for orchestrator review/merge; NOT merged. 7 commits, all with `Brief: #31` trailer: - eb9ec93 schema (parent_brief_id + brief_dependencies) - d65bf87 BriefRelationService + dispatch gating - f94fc5d MCP tools (set_parent/depend/undepend) + newly_unblocked on completion - b32c5da recall_brief/recall_briefs/recall_dispatch_queue exposure - 56357bf UI (Index epic nesting + badges + dispatchable filter; Show relationships card + gated dispatch) - 603ec21 query-budget fix (fold dependents→withCount; /briefs stays 4 queries; Show detail bound 15→19 for the bounded Relationships-card queries) - (final) untrack an accidentally-committed local solo.yml Acceptance check vs spec: ✓ Migrations: parent_brief_id + brief_dependencies; cycle prevention (parent + transitive dependency, both tested). ✓ brief_dispatch server-refuses a blocked brief ("blocked by #X (status Y)"); completing a brief returns newly-unblocked ids (brief_update_status + brief_dispatch_complete + UI setStatus). ✓ recall_dispatch_queue flags blocked requests + dispatchable list + dispatchable_only; recall_briefs parent/dispatchable filters + relation fields; recall_brief relations block (parent/children+rollup/depends_on/blocked_by/blocking/is_blocked/is_dispatchable). ✓ MCP tools brief_set_parent/brief_depend/brief_undepend (actor_ref → auto-participant), registered in FlowerServer, matching Brief*Tool shape. ✓ /briefs UI: epic nesting + blocked/blocking badges + "dispatchable now" filter; Show manages parent + dependencies with a gated-dispatch banner. ✓ Tests (BriefRelationServiceTest, BriefRelationToolsTest, RecallBriefRelationsTest, BriefRelationsUiTest, FoundationTest) + suite green. `Brief: #31` trailer on every commit. Noted-future (correctly OUT of v1, captured as brief #32): chain-with-agent-affinity (v2), merge/collapse (v3). Orchestrator note: Horizon reload not required (no job/pipeline code changed). The two new migrations need `php artisan migrate` on MAIN after merge. New MCP tools appear after the flower MCP server reloads.

    agent · flower-other
  12. note added 4d ago

    Build progress (flower-design, branch flower/brief-relations off master). Backend + MCP + gating + recall exposure DONE and green (php artisan test passing per-unit, pint clean). Commits so far, each with `Brief: #31` trailer: 1. eb9ec93 — schema: briefs.parent_brief_id (nullable self-FK, sqlite-portable) + brief_dependencies table; Brief parent/children + dependsOn/dependents relations; BriefDependency model; BriefStatus::satisfiesDependency()/isTerminal(); BriefEventKind +parent_set/dependency_added/dependency_removed/unblocked; FoundationTest updated. 2. d65bf87 — BriefRelationService (setParent/addDependency/removeDependency with self+cycle guards, blockers/isBlocked/blocking/isDispatchable, recordCompletionUnblocks returning newly-freed dependents idempotently) + DispatchService dispatch gate (refuses blocked brief with "blocked by #X (status Y)"). 3. f94fc5d — MCP tools brief_set_parent / brief_depend / brief_undepend (actor_ref → auto-participant, registered in FlowerServer); brief_update_status + brief_dispatch_complete now return newly_unblocked. 4. b32c5da — recall_brief relations block (parent/children+rollup/depends_on/blocked_by/blocking/is_blocked/is_dispatchable); recall_briefs parent+dispatchable filters + relation fields; recall_dispatch_queue flags blocked requests + dispatchable list (DispatchService::dispatchableBriefs) + dispatchable_only. Tests added: BriefRelationServiceTest, BriefRelationToolsTest, RecallBriefRelationsTest (+FoundationTest). Cycle guards (parent + transitive dependency), idempotency, and the self-join dispatchable filter all verified on sqlite. REMAINING: the /briefs UI (Commit 5) — Index epic nesting + blocked/blocking badges + "dispatchable now" filter; Show relationship panel (manage parent + dependencies) + dispatch-gating banner. Building now, then full-suite green-up + stop for orchestrator review/merge.

    agent · flower-other
  13. participant joined 4d ago
    system · flower-other
  14. comment 4d ago

    Target branch flower/brief-relations is merged to the default branch; suggest marking the brief complete.

    system · system:brief-autolink
  15. participant joined 4d ago
    system · system:brief-autolink
  16. dispatched 4d ago

    Dispatch request #14 queued for flower.

    agent · flower-orchestrator
  17. status change 4d ago
    agent · flower-orchestrator
  18. link added 4d ago
    agent · flower-orchestrator
  19. status change 4d ago
    agent · flower-orchestrator
  20. refinement 4d ago

    ## Goal Make brief **relationships** first-class so the orchestrator (and the refine daemon) can group related briefs and enforce dependency ordering — replacing the manual dependency-juggling we do today (e.g. #26 → #22 → #27, backend-before-UI, green-up-before-merge). **v1 = epic grouping + depends-on gating.** Chain-with-agent-affinity and brief-merge are noted-future (v2+). ## v1 scope ### 1. Epic grouping (parent → children) [operator: epic-parent model] - Add `parent_brief_id` (nullable self-FK) to `briefs`. A brief has ≤1 parent "epic"; an epic has many children. (No separate type needed; an epic is just a brief with children — optionally a flag.) - `recall_brief` shows the epic parent + children; `recall_briefs` can filter/group by epic; `/briefs` nests children under their epic with a rollup. - MCP: `brief_set_parent(brief_id, parent_id|null, actor_ref)`. - Use: batch-refine a set under one epic; see the epic's progress at a glance. ### 2. Depends-on gating (the load-bearing primitive) [operator: gating-only in v1] - Add `brief_dependencies` (or extend `brief_links` with a brief↔brief `blocks` relation): `brief_id` (dependent) + `depends_on_brief_id` (blocker) + `actor_ref`. A brief may depend on N. - **Server-enforced (like Solo todo blockers):** `brief_dispatch` REFUSES a brief with any incomplete dependency (blocker status ∉ {complete, cancelled}); returns a clear "blocked by #X (status Y)". - On a brief reaching `complete`: recompute + **RETURN the list of briefs it newly unblocked** (Solo-style "returns what it unlocked") so the orchestrator can dispatch them immediately. - `recall_dispatch_queue` excludes/flags blocked briefs + adds a `dispatchable` (unblocked+planned) filter; `recall_brief` shows depends-on / blocking both directions. - MCP: `brief_depend(brief_id, depends_on_id, actor_ref)` / `brief_undepend(...)`. - **Cycle guard:** reject an edge that would create a dependency cycle. ### 3. UI - `/briefs`: epic nesting; "blocked by #X" / "blocking #Y" badges; a "dispatchable now" filter. - Brief detail: manage parent + dependencies. ## Why now This is what makes the refine daemon (#27) powerful: as it batch-refines a handful of briefs it encodes epic + depends-on relations, so by the time they're `planned` the orchestrator auto-dispatches them in dependency order — instead of the orchestrator eyeballing it. It captures the dependency reasoning we've done by hand all session. ## Acceptance - Migrations: `parent_brief_id` + `brief_dependencies`; cycle-prevention. - `brief_dispatch` server-refuses a blocked brief; completing a brief returns newly-unblocked ids. - `recall_dispatch_queue` / `recall_briefs` respect blocking + epic; `recall_brief` shows relations. - MCP tools: set-parent / depend / undepend (actor_ref → auto-participant), matching the brief_* shape. - `/briefs` UI: epic nesting + blocked badges + dispatchable filter. - Tests; suite green. `Brief: #31` trailer. ## Noted-future (OUT of v1) - **Chain with agent-affinity** — on a dependent unblocking, hand it to the SAME agent if free, else requeue for the orchestrator (v2, once we see the refine-daemon queueing pattern). - **Merge/collapse** N briefs → 1 (editorial op) (v3). ## Provenance Operator brief #31 (2026-07-01) refined live with the orchestrator: 4 words → 2 primitives (epic grouping + depends-on gating) + 2 noted-future patterns. Operator decisions: grouping = epic-parent; chaining = depends-on gating only in v1.

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

    Grouping/Combining/Chaining/Blocking Briefs What I'm seeing is cases where briefs could or should be logically grouped/tasked together - is that something we should make first class? Some sort of linking/relation that aligns a given group of briefs? Or even/also the ability to collapse multiple briefs into a single (either pre-existing or into a new) brief? And then, what about the idea of chaining the briefs to create task chains, either for a specific agent to handle one after another or potentially different agents tasked with different briefs on the chain? Or maybe an agent can be tasked with a brief on the chain and when it's done if there's no agent assigned to the follow up/next brief in the chain it's back into the queue to be dispatched by the orchestrator as it sees fit? And this kind of brings on the idea of blocks/locks? Could those be useful? Or something similar to what Solo does with todos (I think) where they can be locked by another todo and when completing the first it returns an array/list/object of todos unlocked by it's completion or something?) Various scenarios here but one that I'm seeing is something like me loading up a handful or even a bunch of briefs and then kind of going through them and refining them in a batch before getting them ready to dispatch - or, even, really, any time there's multiple briefs ready to dispatch... does it make sense for you/the orchestrator to be able to group/combine/chain/lock them? Maybe something design-related comes in and the design agent is on a task but the one that just came in is a natural follow up to that one - add it to a chain on the in process brief so that when that agent finishes it's alerted that there's another task on the chain that it's been assigned to next? Or maybe there's a dispatchable brief in the collection but you know that there's a bug that's related that needs to be handled first, you could chain the brief after the bugfix and lock it pending that bugfix is successful? Let me know your thoughts/ideas/refinements/etc.

    system · flower-orchestrator
  22. participant joined 4d ago
    system · flower-orchestrator
  23. note added 4d ago

    Grouping/Combining/Chaining/Blocking Briefs What I'm seeing is cases where briefs could or should be logically grouped/tasked together - is that something we should make first class? Some sort of linking/relation that aligns a given group of briefs? Or even/also the ability to collapse multiple briefs into a single (either pre-existing or into a new) brief? And then, what about the idea of chaining the briefs to create task chains, either for a specific agent to handle one after another or potentially different agents tasked with different briefs on the chain? Or maybe an agent can be tasked with a brief on the chain and when it's done if there's no agent assigned to the follow up/next brief in the chain it's back into the queue to be dispatched by the orchestrator as it sees fit? And this kind of brings on the idea of blocks/locks? Could those be useful? Or something similar to what Solo does with todos (I think) where they can be locked by another todo and when completing the first it returns an array/list/object of todos unlocked by it's completion or something?) Various scenarios here but one that I'm seeing is something like me loading up a handful or even a bunch of briefs and then kind of going through them and refining them in a batch before getting them ready to dispatch - or, even, really, any time there's multiple briefs ready to dispatch... does it make sense for you/the orchestrator to be able to group/combine/chain/lock them? Maybe something design-related comes in and the design agent is on a task but the one that just came in is a natural follow up to that one - add it to a chain on the in process brief so that when that agent finishes it's alerted that there's another task on the chain that it's been assigned to next? Or maybe there's a dispatchable brief in the collection but you know that there's a bug that's related that needs to be handled first, you could chain the brief after the bugfix and lock it pending that bugfix is successful? Let me know your thoughts/ideas/refinements/etc.

    operator · operator:mike
  24. participant joined 4d ago
    system · operator:mike

epic · dependencies

Relationships

epic parent

depends on

No dependencies — dispatchable once planned.

agents · waves

Participants

  • operator:mike participant · active
  • flower-orchestrator participant · active
  • system:brief-autolink participant · active
  • flower-other participant · active
  • system:commit-trailer participant · active

trace · graph

Links

  • Commit #1197 execution
  • Commit #1198 execution
  • Commit #1199 execution
  • Commit #1200 execution
  • Commit #1204 execution
  • Commit #1205 execution
  • Commit #1206 execution
  • Scratchpad #346 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.