selfware 0.6.7

Your personal AI workshop — software you own, software that lasts
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
{
  "component": "orchestration",
  "tier": "full",
  "loop_stage": "control",
  "summary": "The orchestration component runs multi-agent loops. Its WorkflowExecutor (src/orchestration/workflows.rs) drives a DAG of WorkflowSteps (Tool, Shell, Llm, Condition, Loop, SubWorkflow, Guardrail) with retries, timeouts, and cycle detection; its Swarm coordinator drives role-typed Agents through task assignment, weighted Votes, and Decisions resolved by a ConflictStrategy over SharedMemory; MultiAgentChat fans one completion out per Agent under a BudgetGuard and a tokio Semaphore; and the VisualFeedbackLoop iterates act-capture-evaluate against a VisualScore quality_threshold. On the loop it is the control driver that spawns, sequences, and reconciles parallel sub-loops.",
  "loop_objects": ["Workflow", "WorkflowStep", "StepType", "WorkflowContext", "StepResult", "WorkflowStatus", "Swarm", "Agent", "AgentRole", "SwarmTask", "Vote", "Decision", "ConflictStrategy", "SharedMemory", "MultiAgentChat", "AgentResult", "MultiAgentEvent", "VisualFeedbackLoop", "VisualScore", "VisualLoopResult"],
  "context_basis": "Recommendations were formed with src/orchestration/ read in the context of the full engine under a ~600k budget framing; fan-out and swarm coordination assume a shared budget that must be guarded across many concurrent sub-agents.",
  "examples": [
    {
      "id": "orchestration-01",
      "title": "Execute a Workflow as a dependency-ordered DAG",
      "loop_stage": "control",
      "pattern": "dag-execution",
      "intent": "Run steps in dependency order so each starts only when its inputs are ready.",
      "how_it_shapes_the_loop": "WorkflowExecutor::execute loads a Workflow, builds a WorkflowContext, and runs WorkflowSteps respecting depends_on, so the control layer sequences the sub-loop deterministically.",
      "loop_objects_touched": ["Workflow", "WorkflowStep", "WorkflowContext", "StepResult"],
      "wiring": {
        "inputs_from": ["workflow definition (crate::orchestration::workflows::Workflow)", "WorkflowInputs"],
        "outputs_to": ["StepResults", "WorkflowStatus"]
      },
      "touch_interaction": {
        "gesture": "draw-connection",
        "canvas_action": "Drawing edges between step nodes declares depends_on links; the executor runs them in the drawn order.",
        "visual": "Step nodes wire up with directed arrows; each lights green as its StepStatus hits Completed, the next arming only when its parents are done."
      },
      "mini_scenario": "The user wires clone before test before review; WorkflowExecutor::execute runs each only after its predecessor's StepResult reads Completed.",
      "pitfall": "depends_on must form a DAG; a dependency cycle stalls the workflow, which is why WorkflowContext tracks an executing_steps stack for cycle detection."
    },
    {
      "id": "orchestration-02",
      "title": "Retry a failing step with backoff and a timeout",
      "loop_stage": "control",
      "pattern": "retry-with-timeout",
      "intent": "Give a flaky step bounded retries without letting it hang the loop.",
      "how_it_shapes_the_loop": "WorkflowExecutor::execute_step_with_retry wraps a step in a tokio::select against its RetryConfig timeout and retries up to max_attempts with delay, so the control layer contains transient failures.",
      "loop_objects_touched": ["WorkflowStep", "StepResult"],
      "wiring": {
        "inputs_from": ["WorkflowStep RetryConfig"],
        "outputs_to": ["StepResult (Completed / Failed)"]
      },
      "touch_interaction": {
        "gesture": "long-press",
        "canvas_action": "Long-pressing a step opens its RetryConfig dial; each attempt animates a countdown against the timeout ring.",
        "visual": "A retry counter ticks and a timeout ring drains; on timeout the ring snaps red and the step marks Failed."
      },
      "mini_scenario": "A network tool step fails once, waits the backoff, succeeds on retry two, and returns a Completed StepResult.",
      "pitfall": "The timeout must actually cancel the step future; a retry loop without cancellation lets a hung step run past its timeout budget."
    },
    {
      "id": "orchestration-03",
      "title": "Branch the loop with a Condition step",
      "loop_stage": "reason",
      "pattern": "conditional-branch",
      "intent": "Choose the next steps based on a runtime condition over the context.",
      "how_it_shapes_the_loop": "A Condition StepType evaluates its 'if' via WorkflowContext::evaluate_condition (success(), failed(), equality) and runs the then or else branch inline, so the reason stage forks the workflow path at runtime.",
      "loop_objects_touched": ["StepType", "WorkflowContext", "StepResult"],
      "wiring": {
        "inputs_from": ["prior StepResults", "WorkflowContext variables"],
        "outputs_to": ["selected branch steps"]
      },
      "touch_interaction": {
        "gesture": "tap",
        "canvas_action": "Tapping a condition node reveals its two branch arms; the arm whose predicate holds lights up.",
        "visual": "A diamond node shows then/else arms; the true arm glows green and the false arm dims when evaluate_condition resolves."
      },
      "mini_scenario": "If tests succeed the condition lights the review branch; if they failed it lights the notify branch instead.",
      "pitfall": "Branch steps are marked control-flow-managed so the top-level pass does not run them twice; forgetting that double-executes both arms."
    },
    {
      "id": "orchestration-04",
      "title": "Iterate a Loop step over a list",
      "loop_stage": "control",
      "pattern": "step-iteration",
      "intent": "Run a body of steps once per item, keyed per iteration.",
      "how_it_shapes_the_loop": "A Loop StepType splits its 'in' list and runs 'do' steps per item, storing each result as step_id@idx in the WorkflowContext, so the control layer expands one node into an indexed sequence.",
      "loop_objects_touched": ["StepType", "WorkflowContext", "StepResult"],
      "wiring": {
        "inputs_from": ["iteration list", "loop variable"],
        "outputs_to": ["per-iteration StepResults", "aggregate result"]
      },
      "touch_interaction": {
        "gesture": "spread",
        "canvas_action": "Spreading a loop node unrolls it into one body-instance per item laid out in a row.",
        "visual": "The loop node fans into indexed instances; each runs and greens in turn, the aggregate node summing their states."
      },
      "mini_scenario": "A loop over three services runs the deploy body for each; results store as deploy@0, deploy@1, deploy@2.",
      "pitfall": "Dependency lookup is iteration-aware (dep@idx first, then plain dep); resolving a dep without the index reads the wrong iteration's result."
    },
    {
      "id": "orchestration-05",
      "title": "Substitute variables shell-safely into a Shell step",
      "loop_stage": "foundation",
      "pattern": "safe-substitution",
      "intent": "Inject context values into a shell command without opening an injection hole.",
      "how_it_shapes_the_loop": "WorkflowContext::substitute_shell_safe POSIX-quotes interpolated values before a Shell StepType runs, so the foundation layer prevents a malicious variable from escaping the command.",
      "loop_objects_touched": ["StepType", "WorkflowContext"],
      "wiring": {
        "inputs_from": ["WorkflowContext variables"],
        "outputs_to": ["safely-quoted shell command"]
      },
      "touch_interaction": {
        "gesture": "long-press",
        "canvas_action": "Long-pressing a shell node highlights each interpolated token wrapped in a quote shield.",
        "visual": "Variable tokens in the command render inside a shield capsule; an unsafe raw value flashes a warning before quoting."
      },
      "mini_scenario": "A step runs 'git clone ${repo_url}'; the URL is POSIX-quoted so a value with a semicolon cannot append a second command.",
      "pitfall": "Plain WorkflowContext::substitute must never feed a Shell step; using it instead of substitute_shell_safe reintroduces command injection."
    },
    {
      "id": "orchestration-06",
      "title": "Enforce a Guardrail step that fails closed",
      "loop_stage": "verify",
      "pattern": "guardrail-fail-closed",
      "intent": "Block the workflow when a safety condition is violated.",
      "how_it_shapes_the_loop": "A Guardrail StepType evaluates its condition via the GuardrailEngine over a GuardrailContext; a block or unknown EvaluationResult returns an error, so the verify stage halts the loop rather than proceeding unsafely.",
      "loop_objects_touched": ["StepType", "WorkflowContext"],
      "wiring": {
        "inputs_from": ["GuardrailContext built from WorkflowContext variables"],
        "outputs_to": ["block (Err) or allow (Ok)"]
      },
      "touch_interaction": {
        "gesture": "long-press",
        "canvas_action": "Long-pressing a guardrail node runs its check; a violation slams a barrier across the outgoing edge.",
        "visual": "A gate node lowers a red barrier on block, an amber caution on warn, and stays open green on pass."
      },
      "mini_scenario": "A guardrail checks the diff stays in scope; a violation returns Err with block severity and the workflow stops.",
      "pitfall": "Unknown must fail closed like block; treating an unresolved guardrail as allow lets an unevaluated safety check pass silently."
    },
    {
      "id": "orchestration-07",
      "title": "Nest a SubWorkflow with cycle detection",
      "loop_stage": "control",
      "pattern": "sub-loop-nesting",
      "intent": "Compose a workflow out of reusable sub-workflows without infinite recursion.",
      "how_it_shapes_the_loop": "A SubWorkflow StepType executes with an appended WorkflowContext::workflow_call_stack and a recursion_depth cap, so the control layer nests sub-loops while detecting call cycles across workflow boundaries.",
      "loop_objects_touched": ["StepType", "WorkflowContext", "Workflow"],
      "wiring": {
        "inputs_from": ["sub-workflow name", "mapped inputs"],
        "outputs_to": ["merged sub-workflow outputs"]
      },
      "touch_interaction": {
        "gesture": "double-tap",
        "canvas_action": "Double-tapping a sub-workflow node dives into its inner canvas; a breadcrumb tracks the workflow_call_stack.",
        "visual": "The node opens into a nested canvas; the breadcrumb trail grows, flashing red if a name repeats in the stack."
      },
      "mini_scenario": "A release workflow calls the build sub-workflow, whose outputs merge back; a self-call would trip the cycle guard.",
      "pitfall": "The call stack must track names across boundaries; depth counting alone misses a cycle between two mutually-calling workflows."
    },
    {
      "id": "orchestration-08",
      "title": "Assign a SwarmTask to the highest-trust idle Agent",
      "loop_stage": "act",
      "pattern": "role-matched-assignment",
      "intent": "Route each task to an available specialist most likely to do it well.",
      "how_it_shapes_the_loop": "Swarm::assign_task matches a SwarmTask's required_roles to idle Agents by highest trust_score and sets them Working, so the act stage dispatches work to the fittest agent per role.",
      "loop_objects_touched": ["Swarm", "SwarmTask", "Agent", "AgentRole"],
      "wiring": {
        "inputs_from": ["queued SwarmTask (crate::orchestration::swarm::coordinator::queue_task)", "idle Agents"],
        "outputs_to": ["assigned agents", "task InProgress"]
      },
      "touch_interaction": {
        "gesture": "drag",
        "canvas_action": "Dragging a task tile onto the swarm auto-snaps it to the idle agent of the required role with the best trust_score.",
        "visual": "The task tile flies to the chosen agent node, which lights Working; passed-over agents dim briefly."
      },
      "mini_scenario": "An architecture task requiring Architect and Security roles snaps to the two idle specialists with the highest trust scores.",
      "pitfall": "Only idle agents are eligible; assigning to a Working agent creates a zombie task, so completion must return agents to Idle."
    },
    {
      "id": "orchestration-09",
      "title": "Recycle Agents back to Idle on task completion",
      "loop_stage": "control",
      "pattern": "agent-recycling",
      "intent": "Return finished agents to the pool so future tasks can use them.",
      "how_it_shapes_the_loop": "Swarm::complete_task records the result, updates the Agent's trust_score and task counts, then sets it Idle, so the control layer keeps the agent pool circulating instead of freezing agents in Completed.",
      "loop_objects_touched": ["Swarm", "Agent", "SwarmTask"],
      "wiring": {
        "inputs_from": ["task result", "success flag"],
        "outputs_to": ["Agent Idle", "task Completed"]
      },
      "touch_interaction": {
        "gesture": "flick",
        "canvas_action": "Flicking a Working agent that just finished sends it back to the idle pool with an updated trust badge.",
        "visual": "The agent node flips from Working amber to Idle green; its trust badge ticks up on success or down on failure."
      },
      "mini_scenario": "A Coder finishes its task; complete_task bumps its trust_score, marks the task Completed, and returns it Idle for the next assignment.",
      "pitfall": "Forgetting to set the agent Idle after completion leaves it stuck Completed forever, starving the pool of that AgentRole."
    },
    {
      "id": "orchestration-10",
      "title": "Open a Decision and collect weighted Votes",
      "loop_stage": "reason",
      "pattern": "weighted-consensus",
      "intent": "Let the swarm decide among options with each vote weighted by expertise and trust.",
      "how_it_shapes_the_loop": "Swarm::create_decision opens a Decision; each Agent's Vote carries weighted_value = confidence x role_priority x trust_score, so the reason stage aggregates opinions by earned authority.",
      "loop_objects_touched": ["Decision", "Vote", "Agent", "AgentRole"],
      "wiring": {
        "inputs_from": ["question + options", "Agent Votes (Swarm::vote)"],
        "outputs_to": ["resolved Decision outcome"]
      },
      "touch_interaction": {
        "gesture": "tap",
        "canvas_action": "Tapping each agent casts its vote onto the decision node; vote bars grow by their weighted_value.",
        "visual": "Option bars fill as votes land, each segment sized by the voter's weight; the leading option pulses ahead."
      },
      "mini_scenario": "On an architecture choice, the Security agent's high-priority high-trust vote outweighs two low-confidence votes for the alternative.",
      "pitfall": "weighted_value is confidence times priority times trust; dropping any factor lets a confident but untrusted agent sway the decision unfairly."
    },
    {
      "id": "orchestration-11",
      "title": "Resolve a conflicted Decision by ConflictStrategy",
      "loop_stage": "verify",
      "pattern": "conflict-resolution",
      "intent": "Break a tie or clash of votes with an explicit resolution rule.",
      "how_it_shapes_the_loop": "Swarm::resolve_conflict applies a ConflictStrategy (PriorityWins, ConfidenceWins, MajorityWins, HumanIntervention, AcceptAll), so the verify stage turns a Conflict Decision into a determinate outcome or escalates it.",
      "loop_objects_touched": ["Decision", "ConflictStrategy", "Vote"],
      "wiring": {
        "inputs_from": ["conflicted Votes"],
        "outputs_to": ["Decision outcome", "human escalation"]
      },
      "touch_interaction": {
        "gesture": "two-finger-rotate",
        "canvas_action": "Rotating the strategy dial on a conflicted decision recomputes the winner under each ConflictStrategy rule.",
        "visual": "The dial cycles strategy labels; the winning option re-highlights per rule, HumanIntervention greys all and raises a hand icon."
      },
      "mini_scenario": "A split vote is resolved by PriorityWins, letting the Security agent's option win; switching to HumanIntervention would escalate instead.",
      "pitfall": "HumanIntervention returns no automatic outcome; treating its None as a default choice silently picks for the human it meant to consult."
    },
    {
      "id": "orchestration-12",
      "title": "Coordinate agents through bounded SharedMemory",
      "loop_stage": "foundation",
      "pattern": "shared-blackboard",
      "intent": "Let agents exchange intermediate results without direct coupling.",
      "how_it_shapes_the_loop": "SharedMemory offers write/read/peek/delete with an access log bounded to a ring buffer, so the foundation layer gives the swarm a common blackboard that cannot grow unbounded.",
      "loop_objects_touched": ["SharedMemory", "Agent", "Swarm"],
      "wiring": {
        "inputs_from": ["agent writes (SharedMemory::write)"],
        "outputs_to": ["other agents' reads (SharedMemory::read)"]
      },
      "touch_interaction": {
        "gesture": "draw-connection",
        "canvas_action": "Drawing from an agent to the memory slab writes a keyed MemoryEntry; drawing from the slab to another agent reads it.",
        "visual": "A memory slab shows keyed cells; writes drop glowing cells, reads pull threads out, the access log scrolling beneath."
      },
      "mini_scenario": "The Architect writes a design key to SharedMemory; the Coder reads it and its access_count increments in the log.",
      "pitfall": "The access log is a bounded ring buffer; relying on it for a full audit trail loses the oldest MemoryAccess records once it rolls over."
    },
    {
      "id": "orchestration-13",
      "title": "Fan one completion out per Agent under a semaphore",
      "loop_stage": "act",
      "pattern": "budget-scoped-fanout",
      "intent": "Run many specialist perspectives in parallel with bounded concurrency.",
      "how_it_shapes_the_loop": "MultiAgentChat::run_task spawns one chat_completion per Agent gated by a tokio Semaphore sized to MultiAgentConfig::max_concurrency, so the act stage parallelizes perspectives without unbounded fan-out.",
      "loop_objects_touched": ["MultiAgentChat", "Agent", "AgentResult"],
      "wiring": {
        "inputs_from": ["task", "MultiAgentConfig roles"],
        "outputs_to": ["AgentResults", "MultiAgentEvent::AllCompleted"]
      },
      "touch_interaction": {
        "gesture": "spread",
        "canvas_action": "Spreading the task node forks one lane per agent; only max_concurrency lanes run at once, the rest queue for a permit.",
        "visual": "Agent lanes light up in parallel up to the concurrency cap; queued lanes wait greyed until a permit frees."
      },
      "mini_scenario": "One prompt fans out to Reviewer, Tester, and Security agents; with concurrency 2, Security waits until a semaphore permit frees.",
      "pitfall": "The semaphore bounds concurrency, not total spend; without the BudgetGuard the parallel fan-out can still blow the token budget."
    },
    {
      "id": "orchestration-14",
      "title": "Guard the fan-out spend with a BudgetGuard",
      "loop_stage": "control",
      "pattern": "shared-budget-guard",
      "intent": "Cap total tokens and cost across all parallel agents.",
      "how_it_shapes_the_loop": "MultiAgentChat wraps the fan-out in a BudgetGuard enforcing max_budget_tokens and max_cost_usd, so the control layer skips agents once the shared budget is exhausted.",
      "loop_objects_touched": ["MultiAgentChat", "Agent", "AgentResult"],
      "wiring": {
        "inputs_from": ["budget limits", "per-agent token estimate"],
        "outputs_to": ["AgentResult or skip (MultiAgentEvent::AgentFailed)"]
      },
      "touch_interaction": {
        "gesture": "long-press",
        "canvas_action": "Long-pressing the budget bar shows it draining as each agent reserves its estimate; agents past the line grey out.",
        "visual": "A shared budget bar depletes with each launch; when it hits zero, remaining agent lanes stamp 'skipped: budget'."
      },
      "mini_scenario": "Four agents fan out but the budget covers three; the fourth is pessimistically skipped and emits AgentFailed instead of overspending.",
      "pitfall": "Estimate pessimistically before launch; a naive optimistic estimate can admit an agent that then overshoots the shared cap."
    },
    {
      "id": "orchestration-15",
      "title": "Cancel remaining agents on first failure (FailFast)",
      "loop_stage": "control",
      "pattern": "fail-fast-cancellation",
      "intent": "Stop wasting budget on siblings once one agent has failed the task.",
      "how_it_shapes_the_loop": "Under MultiAgentFailurePolicy::FailFast, the first agent error signals a shared tokio::sync::Notify that cancels the remaining tasks, so the control layer aborts the fan-out early.",
      "loop_objects_touched": ["MultiAgentChat", "MultiAgentEvent", "AgentResult"],
      "wiring": {
        "inputs_from": ["first agent failure"],
        "outputs_to": ["cancellation of remaining agents"]
      },
      "touch_interaction": {
        "gesture": "flick",
        "canvas_action": "A failing lane flicks a cancel wave across the sibling lanes, halting them mid-run.",
        "visual": "The failed lane flashes red and a cancellation ripple sweeps the row; sibling lanes freeze and grey out."
      },
      "mini_scenario": "With FailFast set, the Tester agent errors; the Notify fires and the still-running Reviewer and Security lanes cancel.",
      "pitfall": "FailFast trades completeness for cost; choosing it when partial results matter throws away work BestEffort would have kept."
    },
    {
      "id": "orchestration-16",
      "title": "Stream MultiAgentEvents as agents progress",
      "loop_stage": "perceive",
      "pattern": "event-streaming",
      "intent": "Observe the fan-out live rather than waiting for the final batch.",
      "how_it_shapes_the_loop": "MultiAgentChat emits MultiAgentEvents (AgentStarted, AgentCompleted, AgentFailed, AllCompleted) over an mpsc channel, so the perceive stage watches the parallel loop unfold in real time.",
      "loop_objects_touched": ["MultiAgentEvent", "AgentResult", "MultiAgentChat"],
      "wiring": {
        "inputs_from": ["agent lifecycle transitions (MultiAgentChat::with_events)"],
        "outputs_to": ["UI stream", "monitoring"]
      },
      "touch_interaction": {
        "gesture": "tap",
        "canvas_action": "Tapping the event stream node opens a live feed of agent lifecycle events scrolling as they fire.",
        "visual": "An event ticker scrolls: green Started/Completed rows, red Failed rows, a final AllCompleted banner summing durations."
      },
      "mini_scenario": "The user taps the stream and watches AgentStarted then AgentCompleted rows arrive per agent, ending in AllCompleted.",
      "pitfall": "Events use non-blocking try_send; if the channel fills, events drop, so the stream is a view, not a guaranteed-complete log."
    },
    {
      "id": "orchestration-17",
      "title": "Iterate a VisualFeedbackLoop to a quality threshold",
      "loop_stage": "verify",
      "pattern": "iterate-to-threshold",
      "intent": "Refine a visual output until a critic scores it good enough.",
      "how_it_shapes_the_loop": "VisualFeedbackLoop runs act-capture-evaluate until VisualScore.overall meets quality_threshold or max_iterations, so the verify stage closes a self-correcting visual sub-loop.",
      "loop_objects_touched": ["VisualFeedbackLoop", "VisualScore", "VisualLoopResult"],
      "wiring": {
        "inputs_from": ["captured render (CaptureMethod)", "vision model critic"],
        "outputs_to": ["VisualLoopResult", "next iteration or stop"]
      },
      "touch_interaction": {
        "gesture": "spread",
        "canvas_action": "Spreading the visual loop unrolls its iterations; each shows a capture thumbnail and its score climbing toward the line.",
        "visual": "A row of iteration thumbnails rises in score; the loop stops and glows green when a thumbnail crosses the threshold line."
      },
      "mini_scenario": "A UI render scores 72 then 81; the second iteration crosses the 0.8 quality_threshold and the loop returns a VisualLoopResult with threshold_met true.",
      "pitfall": "max_iterations must cap the loop; a strict threshold the critic never reaches spins forever without the iteration ceiling."
    },
    {
      "id": "orchestration-18",
      "title": "Parse a critic response into a dimensioned VisualScore",
      "loop_stage": "reason",
      "pattern": "structured-critique",
      "intent": "Turn a vision model's prose into per-dimension scores plus suggestions.",
      "how_it_shapes_the_loop": "parse_critic_response tolerates markdown fences and extracts a VisualScore (composition, hierarchy, readability, consistency, accessibility, weighted overall via compute_overall), so the reason stage gets actionable per-axis feedback.",
      "loop_objects_touched": ["VisualScore", "VisualFeedbackLoop"],
      "wiring": {
        "inputs_from": ["vision model response (build_critic_prompt answer)"],
        "outputs_to": ["VisualScore", "next-iteration prompt"]
      },
      "touch_interaction": {
        "gesture": "double-tap",
        "canvas_action": "Double-tapping a critique node breaks it into five dimension gauges plus a suggestions list.",
        "visual": "Five radial gauges (composition, hierarchy, readability, consistency, accessibility) fill; a suggestions panel lists fixes below."
      },
      "mini_scenario": "The critic returns markdown-fenced JSON; parse_critic_response extracts accessibility 62 and the suggestion 'add focus indicators'.",
      "pitfall": "Overall is a weighted average of the axes (compute_overall weights readability 0.25); recomputing it with equal weights misreports quality the loop then chases wrongly."
    },
    {
      "id": "orchestration-19",
      "title": "Shed load when the Swarm hits resource pressure",
      "loop_stage": "control",
      "pattern": "pressure-backpressure",
      "intent": "Refuse new tasks when the swarm is already saturated.",
      "how_it_shapes_the_loop": "Swarm::queue_task checks crate::resource::ResourcePressure and fails to enqueue when it is High or Critical, so the control layer applies backpressure instead of overcommitting agents.",
      "loop_objects_touched": ["Swarm", "SwarmTask"],
      "wiring": {
        "inputs_from": ["resource pressure signal (set_resource_pressure)"],
        "outputs_to": ["queued task or rejection"]
      },
      "touch_interaction": {
        "gesture": "long-press",
        "canvas_action": "Long-pressing the queue shows a pressure gauge; at Critical the intake slot slams shut and rejects the drop.",
        "visual": "A pressure gauge rides green to red; at High/Critical the queue intake flashes closed and bounces the incoming task tile."
      },
      "mini_scenario": "Under Critical pressure the user tries to queue a task; queue_task rejects it so the overloaded swarm is not pushed further.",
      "pitfall": "Backpressure must reject at intake, not mid-run; admitting a task under Critical pressure just moves the overload downstream."
    },
    {
      "id": "orchestration-20",
      "title": "Sweep timed-out Decisions to keep the swarm live",
      "loop_stage": "control",
      "pattern": "timeout-sweep",
      "intent": "Prevent pending decisions from blocking the swarm indefinitely.",
      "how_it_shapes_the_loop": "Swarm::sweep_timed_out_decisions marks Decisions older than decision_timeout_secs (default 300, set via with_decision_timeout) as TimedOut, so the control layer unblocks agents waiting on a vote that never resolved.",
      "loop_objects_touched": ["Decision", "Swarm"],
      "wiring": {
        "inputs_from": ["pending Decisions", "decision_timeout_secs"],
        "outputs_to": ["TimedOut Decisions", "unblocked agents"]
      },
      "touch_interaction": {
        "gesture": "flick",
        "canvas_action": "Flicking across the decision board sweeps stale pending decisions, stamping the overdue ones TimedOut.",
        "visual": "Pending decision cards past their age flash and stamp a grey 'TimedOut' seal; agents waiting on them release."
      },
      "mini_scenario": "A decision sits unresolved past its 300s timeout; the sweep marks it TimedOut so the agents holding for its outcome move on.",
      "pitfall": "A TimedOut decision has no consensus outcome; downstream logic must handle the timeout branch rather than assume a resolved choice."
    }
  ]
}