@henryqw/pi-subagent 15.1.3 → 16.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -33,7 +33,6 @@ import {
33
33
  type WorktreePayload,
34
34
  } from "@henryqw/pi-subagent";
35
35
  import { DEFAULT_TIMEOUT_CONFIG, readSubagentConfig, type SubagentTimeoutConfig } from "./config.ts";
36
- import { registerDelegateFlow } from "./delegate-flow.ts";
37
36
  import { MODEL_CLASS_GUIDANCE } from "./model-class-policy.ts";
38
37
  import {
39
38
  formatBackgroundWorkflowResult,
@@ -54,8 +53,6 @@ import {
54
53
  type ParsedWorkflow,
55
54
  type WorkflowEntry,
56
55
  } from "./workflow.ts";
57
- import { TASK_NAME_CONTRACT } from "./task-name.ts";
58
-
59
56
  const WIDGET_KEY = "subagent-status";
60
57
  const WIDGET_INTERVAL_MS = 80;
61
58
  const MAX_WIDGET_ITEMS = 8;
@@ -274,7 +271,6 @@ export default function subagentExtension(
274
271
  ].join("\n"), outputPad, 0);
275
272
  });
276
273
  const widgetItems = new Map<string, WidgetItem>();
277
- const retainedWidgetTaskIds = new Set<string>();
278
274
  // Each child is a full Pi process issuing its own model calls; cap parallel
279
275
  // spend. Precedence: PI_SUBAGENT_MAX_SUBAGENTS env > config/pi-subagent/config.json
280
276
  // maxSubagents > default 5. Invalid present config falls back to the default
@@ -314,7 +310,6 @@ export default function subagentExtension(
314
310
  // Bumped by session_start and session_shutdown; background tasks may only
315
311
  // deliver into the exact session that launched them.
316
312
  let sessionEpoch = 0;
317
- let invalidateDelegateFlow = () => {};
318
313
  let widgetInstalled = false;
319
314
  let widgetTimer: ReturnType<typeof setInterval> | undefined;
320
315
  let spinnerIndex = 0;
@@ -327,11 +322,6 @@ export default function subagentExtension(
327
322
 
328
323
  const requestWidgetRender = () => activeTui?.requestRender();
329
324
 
330
- const setWidgetTaskRetained = (taskId: string, retained: boolean) => {
331
- if (retained) retainedWidgetTaskIds.add(taskId);
332
- else retainedWidgetTaskIds.delete(taskId);
333
- };
334
-
335
325
  const startWidgetTimer = () => {
336
326
  if (widgetTimer) return;
337
327
  widgetTimer = setInterval(() => {
@@ -366,7 +356,7 @@ export default function subagentExtension(
366
356
  ensureWidget(ctx);
367
357
  if (!widgetItems.has(id) && widgetItems.size >= MAX_WIDGET_ITEMS) {
368
358
  for (const [oldestId, item] of widgetItems) {
369
- if (item.status === "working" || retainedWidgetTaskIds.has(item.taskId) || item.taskId === taskId) continue;
359
+ if (item.status === "working" || item.taskId === taskId) continue;
370
360
  widgetItems.delete(oldestId);
371
361
  if (widgetItems.size < MAX_WIDGET_ITEMS) break;
372
362
  }
@@ -451,7 +441,6 @@ export default function subagentExtension(
451
441
 
452
442
  pi.on("session_start", (_event, ctx) => {
453
443
  sessionEpoch += 1;
454
- invalidateDelegateFlow();
455
444
  latestCtx = ctx;
456
445
  ensureWidget(ctx);
457
446
  if (loadedConfig.error !== undefined) ctx.ui.notify(loadedConfig.error, "warning");
@@ -467,14 +456,12 @@ export default function subagentExtension(
467
456
  failedToolPatches.clear();
468
457
  stopWidgetTimer();
469
458
  widgetItems.clear();
470
- retainedWidgetTaskIds.clear();
471
459
  activeTui = undefined;
472
460
  widgetInstalled = false;
473
461
  if (ctx.hasUI) ctx.ui.setWidget(WIDGET_KEY, undefined);
474
462
  // Invalidate ordinary outcomes, abort children, then let preserved isolated
475
463
  // work report into the outgoing session before Pi tears it down.
476
464
  sessionEpoch += 1;
477
- invalidateDelegateFlow();
478
465
  const tasks = [...backgroundTasks.values()];
479
466
  for (const { controller } of tasks) controller.abort();
480
467
  await Promise.allSettled(tasks.map(({ settled }) => settled));
@@ -485,7 +472,7 @@ export default function subagentExtension(
485
472
  pi.on("input", (event) => {
486
473
  if (event.source === "extension") return;
487
474
  for (const [id, item] of widgetItems) {
488
- if (item.status !== "working" && !retainedWidgetTaskIds.has(item.taskId)) widgetItems.delete(id);
475
+ if (item.status !== "working") widgetItems.delete(id);
489
476
  }
490
477
  requestWidgetRender();
491
478
  });
@@ -573,34 +560,16 @@ export default function subagentExtension(
573
560
  }
574
561
  };
575
562
 
576
- invalidateDelegateFlow = registerDelegateFlow(pi, {
577
- executor,
578
- maxRuntimeMs: timeoutPolicy.maxMs,
579
- getSessionGeneration: () => sessionEpoch,
580
- loadRoles,
581
- resolveLaunch: (role, modelClass, ctx) => resolveRoleLaunch(pi, latestCtx ?? ctx, {
582
- role,
583
- task: DELEGATE_TASK,
584
- ...(modelClass === undefined ? {} : { modelClass }),
585
- }),
586
- startWidget: startWidgetItem,
587
- setWidgetTaskRetained,
588
- updateWidgetTokens,
589
- updateWidgetActivity,
590
- finishWidget: finishWidgetItem,
591
- });
592
-
593
563
  pi.registerTool({
594
564
  name: "delegate_task",
595
565
  label: "Subagent",
596
566
  description: `Delegate one selected single, parallel, or chain workflow of bounded tasks to isolated Pi Subagents. Roles: ${roleSummary()}.`,
597
567
  promptSnippet: "Delegate one bounded single, parallel, or chain workflow to isolated roles",
598
568
  promptGuidelines: [
599
- "Call delegate_task with exactly one mode: role+name+task in single mode for one atomic task, tasks for 1–8 independent parallel tasks, or chain for 1–8 dependent sequential tasks using {previous} for the immediately preceding assistant output; prefer parallel mode whenever at least two independent outcomes exist and each is independently deliverable and independently verifiable; do not combine independent outcomes merely to reduce child count. Sequence dependent work in chain entries, and never divide one invariant across multiple entries.",
600
- `${TASK_NAME_CONTRACT.promptGuidance} Every delegate_task entry must own one concrete outcome with one focused validation story: state its objective, exact scope and exclusions, relevant context and constraints, expected deliverable, and validation; if the affected flow or scope is not yet known, perform bounded read-only discovery first; never pass the parent request unchanged. For naturally multi-part delegate_task work, you may look for roughly 3–5 useful entries, but do not manufacture entries or enforce a quota.`,
601
- `For each delegate_task entry, ${MODEL_CLASS_GUIDANCE} A direct model replaces only the selected route's model; its thinking level stays unchanged.`,
602
- "Parallel mutating delegate_task entries must own non-overlapping files and changes. Read-only delegate_task entries may inspect overlapping sources when their questions and deliverables differ. Keep integration and cross-cutting decisions in Main.",
603
- "delegate_task background applies to the whole selected workflow and returns before results exist; use it only when the user explicitly asks for non-blocking work.",
569
+ "Use delegate_task with exactly one mode: role+name+task for one task, tasks for 1–8 independent tasks, or chain for 1–8 dependent tasks using {previous}. Prefer parallel whenever at least two outcomes are independently deliverable and verifiable; never split one invariant.",
570
+ "Each delegate_task entry needs one bounded outcome, scope and exclusions, context and constraints, deliverable, and focused validation. Discover unclear scope first; never pass the parent request unchanged. Parallel mutations need non-overlapping ownership; read-only tasks may overlap only for distinct questions. Keep integration and cross-cutting decisions in Main.",
571
+ `For delegate_task, ${MODEL_CLASS_GUIDANCE} A direct model replaces only the selected route's model; its thinking level stays unchanged.`,
572
+ "Use delegate_task background only when the user explicitly requests non-blocking work.",
604
573
  ],
605
574
  parameters: WorkflowSchema,
606
575
  prepareArguments(args) {
@@ -3,13 +3,11 @@ import { Type, type Static } from "typebox";
3
3
 
4
4
  const TASK_NAME_MAX_LENGTH = 29 as const;
5
5
  const TASK_NAME_LIMIT_WORDING = `about five words and fewer than ${TASK_NAME_MAX_LENGTH + 1} characters`;
6
- const TASK_NAME_WORDING = `short descriptive name of ${TASK_NAME_LIMIT_WORDING}`;
7
6
 
8
7
  export const TASK_NAME_CONTRACT = {
9
8
  minLength: 1,
10
9
  maxLength: TASK_NAME_MAX_LENGTH,
11
10
  description: `Short descriptive task name, ${TASK_NAME_LIMIT_WORDING}; C0/C1 control characters are rejected.`,
12
- promptGuidance: `Use a ${TASK_NAME_WORDING} without C0/C1 control characters.`,
13
11
  controlRanges: DISPLAY_TEXT_CONTRACT.controlRanges,
14
12
  pattern: DISPLAY_TEXT_CONTRACT.pattern,
15
13
  } as const;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@henryqw/pi-subagent",
3
- "version": "15.1.3",
3
+ "version": "16.0.1",
4
4
  "description": "Delegate bounded single, parallel, or chained tasks to isolated Pi roles.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -19,7 +19,6 @@
19
19
  "extensions",
20
20
  "docs",
21
21
  "examples",
22
- "skills",
23
22
  "README.md",
24
23
  "CONTEXT.md"
25
24
  ],
@@ -59,9 +58,6 @@
59
58
  "extensions": [
60
59
  "./extensions/subagent.ts"
61
60
  ],
62
- "skills": [
63
- "./skills"
64
- ],
65
61
  "image": "https://raw.githubusercontent.com/HenryQW/pi-harness/main/extensions/pi-subagent/example.png"
66
62
  },
67
63
  "dependencies": {
@@ -1,22 +0,0 @@
1
- # Package-owned `delegate_flow` orchestration
2
-
3
- ## Decision
4
-
5
- `delegate_task` remains the generic bounded Role tool described by [ADR 001](./001-composable-ephemeral-execution.md). Main plans and orchestrates; `delegate_flow` is a separate package-owned Git workflow with this fixed interface:
6
-
7
- ```ts
8
- delegate_flow({ units: [{ id, task, modelClass?, validation: [{ command, args }], review? }] });
9
- delegate_flow_continue({ guidance, modelClass? });
10
- ```
11
-
12
- A Flow accepts 1–8 independent units with unique IDs. Route precedence is explicit unit or continuation `modelClass` > Role `modelClass` > configured `pi-subagent/delegateTask` assignment or declared default. An omitted unit class lets the frozen Implementer and, when applicable, Reviewer use their own Role defaults. The selected class resolves through the existing `pi-task-models` profile model-and-thinking route. `review` is optional non-empty text for the explicit judgment that declared validation cannot establish.
13
-
14
- Only one memory-only Flow may be active. At start it resolves/freezes the effective `implementer` Role, including a same-named user override. It resolves/freezes the effective `reviewer` Role only when at least one requested unit has `review`. It requires a clean committed attached Main branch and creates one Unit Worktree per unit before launching Implementers in parallel. All started Implementers settle; Flow then processes units in declared order.
15
-
16
- For each unit, Flow verifies Main, rebases the Unit Worktree in place when earlier Flow units advanced Main, inspects committed Git state, and runs declared validation. Validation is authoritative for objective verification. Without `review`, Flow skips exact evidence and Reviewer launch, then fast-forwards the exact validated tip through the existing guarded `git merge --ff-only` path. With `review`, it gives the Reviewer the exact `{base, tip, patchPath}` packet in that same worktree; only trimmed output exactly equal to `PASS` permits the same full-OID fast-forward. Cleanup uses non-forced worktree removal and branch deletion; cleanup refusal does not undo integration and returns completion with retained-work warnings.
17
-
18
- If rebase drops all unit commits, `base === tip` is a no-op. Flow validates the state, skips Reviewer and merge, then cleans up ordinarily. Implementer failure, dirty or missing committed work, validation failure, and reviewer findings block the first affected declared unit. `delegate_flow_continue({ guidance, modelClass? })` launches a fresh ephemeral child with the frozen Implementer Role in that same Unit Worktree once, with original requirements, authoritative validation, previous block evidence, and Main guidance. Omitted continuation class retains a supplied Unit class and otherwise lets each frozen Role use its own default; a supplied class replaces both defaults for that repair and any subsequent Reviewer launch. A second block is terminal. Failed rebase, evidence/Reviewer, and other infrastructure failures retain worktrees. A reported fast-forward failure completes with its diagnostic as a warning only when Main is clean at the exact integrated tip; otherwise it is terminal. Earlier integrations are never rolled back.
19
-
20
- ## Consequences
21
-
22
- Flow owns narrow deterministic Git mechanics while allowing user-owned Implementer and conditional Reviewer policy through same-named Role overrides. Overrides do not change validation authority, exact review protocol, approval, integration, or cleanup. Flow has no dependency graph, saved recovery, automatic retry, aggregate review, post-merge validation, Planner Role, or generic-role restriction. Units that overlap files, APIs, schemas, generated output, package metadata, lockfiles, or invariants must be combined or sequenced outside Flow.
@@ -1,202 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Delegate Flow lifecycle</title>
7
- <link href="https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&amp;family=Geist+Mono:wght@400;500;600&amp;display=swap" rel="stylesheet">
8
- <style>
9
- *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
10
- body { min-height: 100vh; display: grid; place-items: center; padding: 32px; background: #f0eee9; color: #101828; }
11
- .frame { width: min(1280px, 100%); }
12
- .eyebrow { margin-bottom: 8px; color: #4c5665; font: 500 8px/1 'Geist Mono', monospace; letter-spacing: .18em; text-transform: uppercase; }
13
- h1 { margin-bottom: 24px; font: 600 28px/1.15 'Geist', sans-serif; letter-spacing: -.03em; }
14
- svg { display: block; width: 100%; min-width: 960px; }
15
- </style>
16
- </head>
17
- <body>
18
- <main class="frame">
19
- <p class="eyebrow">Flowchart · @henryqw/pi-subagent</p>
20
- <h1>Delegate Flow lifecycle</h1>
21
- <svg viewBox="0 0 1280 720" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="delegate-flow-title delegate-flow-desc">
22
- <title id="delegate-flow-title">Delegate Flow lifecycle</title>
23
- <desc id="delegate-flow-desc">Flowchart showing setup, implementation, validation, optional exact review, one repair attempt, integration, cleanup, and retained-worktree failure outcomes.</desc>
24
- <defs>
25
- <style>
26
- .zone { fill: #e6e4de; stroke: rgba(16,24,40,.141); stroke-width: 1; }
27
- .zone-label { fill: #6a7282; font: 500 8px 'Geist Mono', monospace; letter-spacing: .18em; }
28
- .node { fill: #fff; stroke: #101828; stroke-width: 1; }
29
- .node-soft { fill: rgba(16,24,40,.03); stroke: rgba(16,24,40,.32); stroke-width: 1; }
30
- .node-focal { fill: rgba(29,78,216,.08); stroke: #1d4ed8; stroke-width: 1.2; }
31
- .node-failure { fill: rgba(16,24,40,.02); stroke: rgba(16,24,40,.42); stroke-width: 1; stroke-dasharray: 4 4; }
32
- .name { fill: #101828; font: 600 12px 'Geist', sans-serif; text-anchor: middle; }
33
- .sub { fill: #4c5665; font: 400 8px 'Geist Mono', monospace; text-anchor: middle; }
34
- .edge { fill: none; stroke: #4c5665; stroke-width: 1.2; marker-end: url(#arrow); }
35
- .edge-failure { fill: none; stroke: #6a7282; stroke-width: 1.2; stroke-dasharray: 5 4; marker-end: url(#arrow); }
36
- .edge-success { fill: none; stroke: #1d4ed8; stroke-width: 1.4; marker-end: url(#arrow-accent); }
37
- .label-mask { fill: #f0eee9; }
38
- .label { fill: #4c5665; font: 500 8px 'Geist Mono', monospace; text-anchor: middle; letter-spacing: .04em; }
39
- .label-success { fill: #1d4ed8; font: 500 8px 'Geist Mono', monospace; text-anchor: middle; letter-spacing: .04em; }
40
- .legend { fill: #4c5665; font: 400 8px 'Geist', sans-serif; }
41
- </style>
42
- <marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="#4c5665"/></marker>
43
- <marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="#1d4ed8"/></marker>
44
- <marker id="arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="#1d4ed8"/></marker>
45
- </defs>
46
-
47
- <rect width="1280" height="720" fill="#f0eee9"/>
48
-
49
- <!-- Zones -->
50
- <rect class="zone" x="40" y="40" width="760" height="280" rx="8"/>
51
- <text class="zone-label" x="56" y="64">INITIAL RUN</text>
52
- <rect class="zone" x="40" y="340" width="760" height="260" rx="8"/>
53
- <text class="zone-label" x="56" y="364">ONE REPAIR MAXIMUM</text>
54
- <rect class="zone" x="840" y="40" width="400" height="560" rx="8"/>
55
- <text class="zone-label" x="856" y="64">OUTCOMES</text>
56
-
57
- <!-- Initial-run edges -->
58
- <path class="edge" d="M248 128 H288"/>
59
- <path class="edge" d="M464 128 H504"/>
60
- <path class="edge" d="M600 128 H624"/>
61
- <path class="edge" d="M784 128 H872"/>
62
- <path class="edge" d="M704 176 V216"/>
63
- <path class="edge-success" d="M784 248 H812 Q820 248 820 240 V152 Q820 144 828 144 H856 Q864 144 864 136 V128 H872"/>
64
-
65
- <!-- Blocked initial-run paths to repair -->
66
- <path class="edge" d="M376 160 V304 Q376 312 368 312 H160 Q152 312 152 320 V412"/>
67
- <path class="edge" d="M552 160 V288 Q552 296 544 296 H136 Q128 296 128 304 V412"/>
68
- <path class="edge" d="M664 280 V320 Q664 328 656 328 H184 Q176 328 176 336 V412"/>
69
-
70
- <!-- Repair path -->
71
- <path class="edge" d="M272 444 H320"/>
72
- <path class="edge" d="M520 444 H592"/>
73
- <path class="edge-success" d="M384 412 V384 Q384 376 392 376 H808 Q816 376 816 368 V120 Q816 112 824 112 H856 Q864 112 864 120 V128 H872"/>
74
- <path class="edge-success" d="M768 444 H824 Q832 444 832 436 V168 Q832 160 840 160 H856 Q864 160 864 152 V128 H872"/>
75
-
76
- <!-- Success outcome -->
77
- <path class="edge-success" d="M880 128 H912"/>
78
- <path class="edge-success" d="M1012 160 V216"/>
79
- <path class="edge" d="M552 96 V80 Q552 72 560 72 H1144 Q1152 72 1152 80 V240 Q1152 248 1144 248 H1112"/>
80
-
81
- <!-- Failure paths, fanned into one merge -->
82
- <path class="edge-failure" d="M584 160 V304 Q584 312 592 312 H808 Q816 312 816 320 V488 Q816 496 824 496 H872"/>
83
- <path class="edge-failure" d="M232 476 V568 Q232 576 240 576 H856 Q864 576 864 568 V512 Q864 504 872 504"/>
84
- <path class="edge-failure" d="M472 476 V536 Q472 544 480 544 H840 Q848 544 848 536 V520 Q848 512 856 512 H872"/>
85
- <path class="edge-failure" d="M768 460 H808 Q816 460 816 468 V512 Q816 520 824 520 H856 Q864 520 864 512 V504 H872"/>
86
- <path class="edge-failure" d="M880 504 H912"/>
87
-
88
- <!-- Completion-warning and integration-failure outcomes -->
89
- <path class="edge-failure" d="M1012 280 V336"/>
90
- <path class="edge-failure" d="M1112 136 H1184 Q1192 136 1192 144 V356 Q1192 364 1184 364 H1152"/>
91
- <path class="edge-failure" d="M1112 112 H1208 Q1216 112 1216 120 V496 Q1216 504 1208 504 H1152"/>
92
-
93
- <!-- Edge labels -->
94
- <rect class="label-mask" x="272" y="252" width="128" height="12" rx="2"/>
95
- <text class="label" x="336" y="261">IMPLEMENTER BLOCK</text>
96
- <rect class="label-mask" x="416" y="276" width="120" height="12" rx="2"/>
97
- <text class="label" x="476" y="285">VALIDATION BLOCK</text>
98
- <rect class="label-mask" x="504" y="316" width="96" height="12" rx="2"/>
99
- <text class="label" x="552" y="325">REVIEW BLOCK</text>
100
- <rect class="label-mask" x="800" y="100" width="32" height="12" rx="2"/>
101
- <text class="label" x="816" y="109">NO</text>
102
- <rect class="label-mask" x="688" y="188" width="32" height="12" rx="2"/>
103
- <text class="label" x="704" y="197">YES</text>
104
- <rect class="label-mask" x="828" y="224" width="40" height="12" rx="2"/>
105
- <text class="label-success" x="848" y="233">PASS</text>
106
- <rect class="label-mask" x="520" y="364" width="144" height="12" rx="2"/>
107
- <text class="label-success" x="592" y="373">NO REVIEW REQUESTED</text>
108
- <rect class="label-mask" x="528" y="424" width="56" height="12" rx="2"/>
109
- <text class="label" x="556" y="433">REVIEW</text>
110
- <rect class="label-mask" x="800" y="404" width="40" height="12" rx="2"/>
111
- <text class="label-success" x="820" y="413">PASS</text>
112
- <rect class="label-mask" x="816" y="292" width="160" height="12" rx="2"/>
113
- <text class="label" x="896" y="301">REBASE / INFRA FAILURE</text>
114
- <rect class="label-mask" x="336" y="556" width="136" height="12" rx="2"/>
115
- <text class="label" x="404" y="565">INFRASTRUCTURE FAILURE</text>
116
- <rect class="label-mask" x="560" y="524" width="96" height="12" rx="2"/>
117
- <text class="label" x="608" y="533">SECOND BLOCK</text>
118
- <rect class="label-mask" x="748" y="476" width="96" height="12" rx="2"/>
119
- <text class="label" x="796" y="485">SECOND BLOCK</text>
120
- <rect class="label-mask" x="920" y="60" width="128" height="12" rx="2"/>
121
- <text class="label" x="984" y="69">POST-REBASE NO-OP</text>
122
- <rect class="label-mask" x="1024" y="296" width="120" height="12" rx="2"/>
123
- <text class="label" x="1084" y="305">CLEANUP REFUSAL</text>
124
- <rect class="label-mask" x="1024" y="312" width="152" height="12" rx="2"/>
125
- <text class="label" x="1100" y="321">FF DIAGNOSTIC / CLEAN TIP</text>
126
- <rect class="label-mask" x="1064" y="432" width="136" height="12" rx="2"/>
127
- <text class="label" x="1132" y="441">OTHER FF FAILURE</text>
128
-
129
- <!-- Nodes -->
130
- <rect class="node-soft" x="72" y="96" width="176" height="64" rx="32"/>
131
- <text class="name" x="160" y="124">Resolve roles</text>
132
- <text class="sub" x="160" y="140">CREATE UNIT WORKTREES</text>
133
-
134
- <rect class="node" x="288" y="96" width="176" height="64" rx="6"/>
135
- <text class="name" x="376" y="124">Implement in parallel</text>
136
- <text class="sub" x="376" y="140">EACH UNIT ISOLATED</text>
137
-
138
- <rect class="node" x="504" y="96" width="96" height="64" rx="6"/>
139
- <text class="name" x="552" y="120">Rebase</text>
140
- <text class="sub" x="552" y="136">INSPECT</text>
141
- <text class="sub" x="552" y="148">VALIDATE</text>
142
-
143
- <polygon class="node" points="704,80 784,128 704,176 624,128"/>
144
- <text class="name" x="704" y="124">Review</text>
145
- <text class="sub" x="704" y="140">REQUESTED?</text>
146
-
147
- <rect class="node" x="624" y="216" width="160" height="64" rx="6"/>
148
- <text class="name" x="704" y="240">Exact review packet</text>
149
- <text class="sub" x="704" y="256">BASE · TIP · PATCH</text>
150
- <text class="sub" x="704" y="268">REQUIRE PASS</text>
151
-
152
- <rect class="node-focal" x="912" y="96" width="200" height="64" rx="6"/>
153
- <text class="name" x="1012" y="124">Integrate in order</text>
154
- <text class="sub" x="1012" y="140">FAST-FORWARD EXACT TIP</text>
155
-
156
- <rect class="node-soft" x="912" y="216" width="200" height="64" rx="32"/>
157
- <text class="name" x="1012" y="244">Cleanup</text>
158
- <text class="sub" x="1012" y="260">REMOVE WORKTREE + BRANCH</text>
159
-
160
- <rect class="node-soft" x="912" y="336" width="240" height="72" rx="32"/>
161
- <text class="name" x="1032" y="364">Completion warning</text>
162
- <text class="sub" x="1032" y="380">CLEAN TIP · OR CLEANUP REFUSAL</text>
163
- <text class="sub" x="1032" y="392">RETAIN REPORTED RESOURCES</text>
164
-
165
- <rect class="node" x="72" y="412" width="200" height="64" rx="6"/>
166
- <text class="name" x="172" y="440">One repair</text>
167
- <text class="sub" x="172" y="456">DELEGATE_FLOW_CONTINUE</text>
168
-
169
- <rect class="node" x="320" y="412" width="200" height="64" rx="6"/>
170
- <text class="name" x="420" y="440">Revalidate repair</text>
171
- <text class="sub" x="420" y="456">SAME UNIT WORKTREE</text>
172
-
173
- <rect class="node" x="592" y="412" width="176" height="64" rx="6"/>
174
- <text class="name" x="680" y="440">Re-review packet</text>
175
- <text class="sub" x="680" y="456">REQUIRE PASS AGAIN</text>
176
-
177
- <rect class="node-failure" x="912" y="472" width="240" height="64" rx="32"/>
178
- <text class="name" x="1032" y="500">Terminal failure</text>
179
- <text class="sub" x="1032" y="516">RETAIN UNIT WORKTREE</text>
180
-
181
- <!-- Merge points -->
182
- <circle cx="876" cy="128" r="4" fill="#1d4ed8"/>
183
- <circle cx="876" cy="504" r="4" fill="#6a7282"/>
184
-
185
- <!-- Legend -->
186
- <line x1="40" y1="636" x2="1240" y2="636" stroke="rgba(16,24,40,.141)" stroke-width="0.8"/>
187
- <text class="zone-label" x="40" y="656">LEGEND</text>
188
- <rect class="node" x="120" y="648" width="24" height="12" rx="2"/>
189
- <text class="legend" x="152" y="658">Step</text>
190
- <polygon class="node" points="236,654 248,648 260,654 248,660"/>
191
- <text class="legend" x="272" y="658">Decision</text>
192
- <circle cx="380" cy="654" r="4" fill="#4c5665"/>
193
- <text class="legend" x="392" y="658">Branch merge</text>
194
- <line x1="512" y1="654" x2="548" y2="654" stroke="#1d4ed8" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
195
- <text class="legend" x="560" y="658">Validated path</text>
196
- <line x1="696" y1="654" x2="732" y2="654" stroke="#6a7282" stroke-width="1.2" stroke-dasharray="5 4" marker-end="url(#arrow)"/>
197
- <text class="legend" x="744" y="658">Terminal path</text>
198
- <text class="sub" x="1120" y="658">ONE REPAIR · NO AUTOMATIC RETRY</text>
199
- </svg>
200
- </main>
201
- </body>
202
- </html>
@@ -1,181 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <svg width="1280" height="720" viewBox="0 0 1280 720" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="delegate-flow-title delegate-flow-desc">
3
- <title id="delegate-flow-title">Delegate Flow lifecycle</title>
4
- <desc id="delegate-flow-desc">Flowchart showing setup, implementation, validation, optional exact review, one repair attempt, integration, cleanup, and retained-worktree failure outcomes.</desc>
5
- <defs>
6
- <style>
7
- @import url(&quot;https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&amp;family=Geist+Mono:wght@400;500;600&amp;display=swap&quot;);
8
- .zone { fill: #e6e4de; stroke: rgba(16,24,40,.141); stroke-width: 1; }
9
- .zone-label { fill: #6a7282; font: 500 8px 'Geist Mono', monospace; letter-spacing: .18em; }
10
- .node { fill: #fff; stroke: #101828; stroke-width: 1; }
11
- .node-soft { fill: rgba(16,24,40,.03); stroke: rgba(16,24,40,.32); stroke-width: 1; }
12
- .node-focal { fill: rgba(29,78,216,.08); stroke: #1d4ed8; stroke-width: 1.2; }
13
- .node-failure { fill: rgba(16,24,40,.02); stroke: rgba(16,24,40,.42); stroke-width: 1; stroke-dasharray: 4 4; }
14
- .name { fill: #101828; font: 600 12px 'Geist', sans-serif; text-anchor: middle; }
15
- .sub { fill: #4c5665; font: 400 8px 'Geist Mono', monospace; text-anchor: middle; }
16
- .edge { fill: none; stroke: #4c5665; stroke-width: 1.2; marker-end: url(#arrow); }
17
- .edge-failure { fill: none; stroke: #6a7282; stroke-width: 1.2; stroke-dasharray: 5 4; marker-end: url(#arrow); }
18
- .edge-success { fill: none; stroke: #1d4ed8; stroke-width: 1.4; marker-end: url(#arrow-accent); }
19
- .label-mask { fill: #f0eee9; }
20
- .label { fill: #4c5665; font: 500 8px 'Geist Mono', monospace; text-anchor: middle; letter-spacing: .04em; }
21
- .label-success { fill: #1d4ed8; font: 500 8px 'Geist Mono', monospace; text-anchor: middle; letter-spacing: .04em; }
22
- .legend { fill: #4c5665; font: 400 8px 'Geist', sans-serif; }
23
- </style>
24
- <marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="#4c5665"/></marker>
25
- <marker id="arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="#1d4ed8"/></marker>
26
- <marker id="arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto"><polygon points="0 0,8 3,0 6" fill="#1d4ed8"/></marker>
27
- </defs>
28
-
29
- <rect width="1280" height="720" fill="#f0eee9"/>
30
-
31
- <!-- Zones -->
32
- <rect class="zone" x="40" y="40" width="760" height="280" rx="8"/>
33
- <text class="zone-label" x="56" y="64">INITIAL RUN</text>
34
- <rect class="zone" x="40" y="340" width="760" height="260" rx="8"/>
35
- <text class="zone-label" x="56" y="364">ONE REPAIR MAXIMUM</text>
36
- <rect class="zone" x="840" y="40" width="400" height="560" rx="8"/>
37
- <text class="zone-label" x="856" y="64">OUTCOMES</text>
38
-
39
- <!-- Initial-run edges -->
40
- <path class="edge" d="M248 128 H288"/>
41
- <path class="edge" d="M464 128 H504"/>
42
- <path class="edge" d="M600 128 H624"/>
43
- <path class="edge" d="M784 128 H872"/>
44
- <path class="edge" d="M704 176 V216"/>
45
- <path class="edge-success" d="M784 248 H812 Q820 248 820 240 V152 Q820 144 828 144 H856 Q864 144 864 136 V128 H872"/>
46
-
47
- <!-- Blocked initial-run paths to repair -->
48
- <path class="edge" d="M376 160 V304 Q376 312 368 312 H160 Q152 312 152 320 V412"/>
49
- <path class="edge" d="M552 160 V288 Q552 296 544 296 H136 Q128 296 128 304 V412"/>
50
- <path class="edge" d="M664 280 V320 Q664 328 656 328 H184 Q176 328 176 336 V412"/>
51
-
52
- <!-- Repair path -->
53
- <path class="edge" d="M272 444 H320"/>
54
- <path class="edge" d="M520 444 H592"/>
55
- <path class="edge-success" d="M384 412 V384 Q384 376 392 376 H808 Q816 376 816 368 V120 Q816 112 824 112 H856 Q864 112 864 120 V128 H872"/>
56
- <path class="edge-success" d="M768 444 H824 Q832 444 832 436 V168 Q832 160 840 160 H856 Q864 160 864 152 V128 H872"/>
57
-
58
- <!-- Success outcome -->
59
- <path class="edge-success" d="M880 128 H912"/>
60
- <path class="edge-success" d="M1012 160 V216"/>
61
- <path class="edge" d="M552 96 V80 Q552 72 560 72 H1144 Q1152 72 1152 80 V240 Q1152 248 1144 248 H1112"/>
62
-
63
- <!-- Failure paths, fanned into one merge -->
64
- <path class="edge-failure" d="M584 160 V304 Q584 312 592 312 H808 Q816 312 816 320 V488 Q816 496 824 496 H872"/>
65
- <path class="edge-failure" d="M232 476 V568 Q232 576 240 576 H856 Q864 576 864 568 V512 Q864 504 872 504"/>
66
- <path class="edge-failure" d="M472 476 V536 Q472 544 480 544 H840 Q848 544 848 536 V520 Q848 512 856 512 H872"/>
67
- <path class="edge-failure" d="M768 460 H808 Q816 460 816 468 V512 Q816 520 824 520 H856 Q864 520 864 512 V504 H872"/>
68
- <path class="edge-failure" d="M880 504 H912"/>
69
-
70
- <!-- Completion-warning and integration-failure outcomes -->
71
- <path class="edge-failure" d="M1012 280 V336"/>
72
- <path class="edge-failure" d="M1112 136 H1184 Q1192 136 1192 144 V356 Q1192 364 1184 364 H1152"/>
73
- <path class="edge-failure" d="M1112 112 H1208 Q1216 112 1216 120 V496 Q1216 504 1208 504 H1152"/>
74
-
75
- <!-- Edge labels -->
76
- <rect class="label-mask" x="272" y="252" width="128" height="12" rx="2"/>
77
- <text class="label" x="336" y="261">IMPLEMENTER BLOCK</text>
78
- <rect class="label-mask" x="416" y="276" width="120" height="12" rx="2"/>
79
- <text class="label" x="476" y="285">VALIDATION BLOCK</text>
80
- <rect class="label-mask" x="504" y="316" width="96" height="12" rx="2"/>
81
- <text class="label" x="552" y="325">REVIEW BLOCK</text>
82
- <rect class="label-mask" x="800" y="100" width="32" height="12" rx="2"/>
83
- <text class="label" x="816" y="109">NO</text>
84
- <rect class="label-mask" x="688" y="188" width="32" height="12" rx="2"/>
85
- <text class="label" x="704" y="197">YES</text>
86
- <rect class="label-mask" x="828" y="224" width="40" height="12" rx="2"/>
87
- <text class="label-success" x="848" y="233">PASS</text>
88
- <rect class="label-mask" x="520" y="364" width="144" height="12" rx="2"/>
89
- <text class="label-success" x="592" y="373">NO REVIEW REQUESTED</text>
90
- <rect class="label-mask" x="528" y="424" width="56" height="12" rx="2"/>
91
- <text class="label" x="556" y="433">REVIEW</text>
92
- <rect class="label-mask" x="800" y="404" width="40" height="12" rx="2"/>
93
- <text class="label-success" x="820" y="413">PASS</text>
94
- <rect class="label-mask" x="816" y="292" width="160" height="12" rx="2"/>
95
- <text class="label" x="896" y="301">REBASE / INFRA FAILURE</text>
96
- <rect class="label-mask" x="336" y="556" width="136" height="12" rx="2"/>
97
- <text class="label" x="404" y="565">INFRASTRUCTURE FAILURE</text>
98
- <rect class="label-mask" x="560" y="524" width="96" height="12" rx="2"/>
99
- <text class="label" x="608" y="533">SECOND BLOCK</text>
100
- <rect class="label-mask" x="748" y="476" width="96" height="12" rx="2"/>
101
- <text class="label" x="796" y="485">SECOND BLOCK</text>
102
- <rect class="label-mask" x="920" y="60" width="128" height="12" rx="2"/>
103
- <text class="label" x="984" y="69">POST-REBASE NO-OP</text>
104
- <rect class="label-mask" x="1024" y="296" width="120" height="12" rx="2"/>
105
- <text class="label" x="1084" y="305">CLEANUP REFUSAL</text>
106
- <rect class="label-mask" x="1024" y="312" width="152" height="12" rx="2"/>
107
- <text class="label" x="1100" y="321">FF DIAGNOSTIC / CLEAN TIP</text>
108
- <rect class="label-mask" x="1064" y="432" width="136" height="12" rx="2"/>
109
- <text class="label" x="1132" y="441">OTHER FF FAILURE</text>
110
-
111
- <!-- Nodes -->
112
- <rect class="node-soft" x="72" y="96" width="176" height="64" rx="32"/>
113
- <text class="name" x="160" y="124">Resolve roles</text>
114
- <text class="sub" x="160" y="140">CREATE UNIT WORKTREES</text>
115
-
116
- <rect class="node" x="288" y="96" width="176" height="64" rx="6"/>
117
- <text class="name" x="376" y="124">Implement in parallel</text>
118
- <text class="sub" x="376" y="140">EACH UNIT ISOLATED</text>
119
-
120
- <rect class="node" x="504" y="96" width="96" height="64" rx="6"/>
121
- <text class="name" x="552" y="120">Rebase</text>
122
- <text class="sub" x="552" y="136">INSPECT</text>
123
- <text class="sub" x="552" y="148">VALIDATE</text>
124
-
125
- <polygon class="node" points="704,80 784,128 704,176 624,128"/>
126
- <text class="name" x="704" y="124">Review</text>
127
- <text class="sub" x="704" y="140">REQUESTED?</text>
128
-
129
- <rect class="node" x="624" y="216" width="160" height="64" rx="6"/>
130
- <text class="name" x="704" y="240">Exact review packet</text>
131
- <text class="sub" x="704" y="256">BASE · TIP · PATCH</text>
132
- <text class="sub" x="704" y="268">REQUIRE PASS</text>
133
-
134
- <rect class="node-focal" x="912" y="96" width="200" height="64" rx="6"/>
135
- <text class="name" x="1012" y="124">Integrate in order</text>
136
- <text class="sub" x="1012" y="140">FAST-FORWARD EXACT TIP</text>
137
-
138
- <rect class="node-soft" x="912" y="216" width="200" height="64" rx="32"/>
139
- <text class="name" x="1012" y="244">Cleanup</text>
140
- <text class="sub" x="1012" y="260">REMOVE WORKTREE + BRANCH</text>
141
-
142
- <rect class="node-soft" x="912" y="336" width="240" height="72" rx="32"/>
143
- <text class="name" x="1032" y="364">Completion warning</text>
144
- <text class="sub" x="1032" y="380">CLEAN TIP · OR CLEANUP REFUSAL</text>
145
- <text class="sub" x="1032" y="392">RETAIN REPORTED RESOURCES</text>
146
-
147
- <rect class="node" x="72" y="412" width="200" height="64" rx="6"/>
148
- <text class="name" x="172" y="440">One repair</text>
149
- <text class="sub" x="172" y="456">DELEGATE_FLOW_CONTINUE</text>
150
-
151
- <rect class="node" x="320" y="412" width="200" height="64" rx="6"/>
152
- <text class="name" x="420" y="440">Revalidate repair</text>
153
- <text class="sub" x="420" y="456">SAME UNIT WORKTREE</text>
154
-
155
- <rect class="node" x="592" y="412" width="176" height="64" rx="6"/>
156
- <text class="name" x="680" y="440">Re-review packet</text>
157
- <text class="sub" x="680" y="456">REQUIRE PASS AGAIN</text>
158
-
159
- <rect class="node-failure" x="912" y="472" width="240" height="64" rx="32"/>
160
- <text class="name" x="1032" y="500">Terminal failure</text>
161
- <text class="sub" x="1032" y="516">RETAIN UNIT WORKTREE</text>
162
-
163
- <!-- Merge points -->
164
- <circle cx="876" cy="128" r="4" fill="#1d4ed8"/>
165
- <circle cx="876" cy="504" r="4" fill="#6a7282"/>
166
-
167
- <!-- Legend -->
168
- <line x1="40" y1="636" x2="1240" y2="636" stroke="rgba(16,24,40,.141)" stroke-width="0.8"/>
169
- <text class="zone-label" x="40" y="656">LEGEND</text>
170
- <rect class="node" x="120" y="648" width="24" height="12" rx="2"/>
171
- <text class="legend" x="152" y="658">Step</text>
172
- <polygon class="node" points="236,654 248,648 260,654 248,660"/>
173
- <text class="legend" x="272" y="658">Decision</text>
174
- <circle cx="380" cy="654" r="4" fill="#4c5665"/>
175
- <text class="legend" x="392" y="658">Branch merge</text>
176
- <line x1="512" y1="654" x2="548" y2="654" stroke="#1d4ed8" stroke-width="1.4" marker-end="url(#arrow-accent)"/>
177
- <text class="legend" x="560" y="658">Validated path</text>
178
- <line x1="696" y1="654" x2="732" y2="654" stroke="#6a7282" stroke-width="1.2" stroke-dasharray="5 4" marker-end="url(#arrow)"/>
179
- <text class="legend" x="744" y="658">Terminal path</text>
180
- <text class="sub" x="1120" y="658">ONE REPAIR · NO AUTOMATIC RETRY</text>
181
- </svg>