projectinator 0.3.1 → 0.4.0

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.
Files changed (171) hide show
  1. package/README.md +7 -6
  2. package/bin/projectinator.mjs +22 -15
  3. package/dist/bakeoff.js +163 -0
  4. package/dist/bakeoff.js.map +1 -0
  5. package/dist/build-state.js +26 -0
  6. package/dist/build-state.js.map +1 -0
  7. package/dist/burndown.js +19 -0
  8. package/dist/burndown.js.map +1 -0
  9. package/dist/calibration.js +86 -0
  10. package/dist/calibration.js.map +1 -0
  11. package/dist/cli.js +289 -0
  12. package/dist/cli.js.map +1 -0
  13. package/dist/cost.js +35 -0
  14. package/dist/cost.js.map +1 -0
  15. package/dist/council.js +147 -0
  16. package/dist/council.js.map +1 -0
  17. package/dist/demo.js +93 -0
  18. package/dist/demo.js.map +1 -0
  19. package/dist/estimate.js +98 -0
  20. package/dist/estimate.js.map +1 -0
  21. package/dist/executor.js +118 -0
  22. package/dist/executor.js.map +1 -0
  23. package/dist/git.js +82 -0
  24. package/dist/git.js.map +1 -0
  25. package/dist/intake.js +98 -0
  26. package/dist/intake.js.map +1 -0
  27. package/dist/models.js +171 -0
  28. package/dist/models.js.map +1 -0
  29. package/dist/narrate.js +76 -0
  30. package/dist/narrate.js.map +1 -0
  31. package/dist/openrouter.js +112 -0
  32. package/dist/openrouter.js.map +1 -0
  33. package/dist/orchestrator.js +273 -0
  34. package/dist/orchestrator.js.map +1 -0
  35. package/dist/pm.js +245 -0
  36. package/dist/pm.js.map +1 -0
  37. package/dist/preview.js +194 -0
  38. package/dist/preview.js.map +1 -0
  39. package/dist/registry-store.js +38 -0
  40. package/dist/registry-store.js.map +1 -0
  41. package/dist/registry.js +115 -0
  42. package/dist/registry.js.map +1 -0
  43. package/dist/research.js +98 -0
  44. package/dist/research.js.map +1 -0
  45. package/dist/retro.js +83 -0
  46. package/dist/retro.js.map +1 -0
  47. package/dist/roles.js +357 -0
  48. package/dist/roles.js.map +1 -0
  49. package/dist/router.js +95 -0
  50. package/dist/router.js.map +1 -0
  51. package/dist/run-bakeoff.js +68 -0
  52. package/dist/run-bakeoff.js.map +1 -0
  53. package/dist/run-build.js +193 -0
  54. package/dist/run-build.js.map +1 -0
  55. package/{src/run-dev.ts → dist/run-dev.js} +23 -39
  56. package/dist/run-dev.js.map +1 -0
  57. package/{src/run-pm.ts → dist/run-pm.js} +34 -46
  58. package/dist/run-pm.js.map +1 -0
  59. package/{src/run-research.ts → dist/run-research.js} +19 -30
  60. package/dist/run-research.js.map +1 -0
  61. package/{src/run-scout.ts → dist/run-scout.js} +17 -27
  62. package/dist/run-scout.js.map +1 -0
  63. package/dist/run-web.js +93 -0
  64. package/dist/run-web.js.map +1 -0
  65. package/dist/scout.js +81 -0
  66. package/dist/scout.js.map +1 -0
  67. package/dist/session-cost.js +15 -0
  68. package/dist/session-cost.js.map +1 -0
  69. package/dist/stack.js +34 -0
  70. package/dist/stack.js.map +1 -0
  71. package/dist/stuck.js +21 -0
  72. package/dist/stuck.js.map +1 -0
  73. package/dist/tui/App.js +1269 -0
  74. package/dist/tui/App.js.map +1 -0
  75. package/dist/tui/BakeOff.js +95 -0
  76. package/dist/tui/BakeOff.js.map +1 -0
  77. package/dist/tui/BoardEditor.js +183 -0
  78. package/dist/tui/BoardEditor.js.map +1 -0
  79. package/dist/tui/EditableBoard.js +140 -0
  80. package/dist/tui/EditableBoard.js.map +1 -0
  81. package/dist/tui/Frame.js +78 -0
  82. package/dist/tui/Frame.js.map +1 -0
  83. package/dist/tui/Intake.js +59 -0
  84. package/dist/tui/Intake.js.map +1 -0
  85. package/dist/tui/Kanban.js +75 -0
  86. package/dist/tui/Kanban.js.map +1 -0
  87. package/dist/tui/Settings.js +299 -0
  88. package/dist/tui/Settings.js.map +1 -0
  89. package/dist/tui/StackPick.js +44 -0
  90. package/dist/tui/StackPick.js.map +1 -0
  91. package/dist/tui/WebAccounts.js +131 -0
  92. package/dist/tui/WebAccounts.js.map +1 -0
  93. package/dist/tui/components.js +178 -0
  94. package/dist/tui/components.js.map +1 -0
  95. package/dist/tui/config.js +129 -0
  96. package/dist/tui/config.js.map +1 -0
  97. package/dist/tui/deploy.js +114 -0
  98. package/dist/tui/deploy.js.map +1 -0
  99. package/dist/tui/engine.js +710 -0
  100. package/dist/tui/engine.js.map +1 -0
  101. package/dist/tui/notify.js +47 -0
  102. package/dist/tui/notify.js.map +1 -0
  103. package/dist/tui/panels.js +42 -0
  104. package/dist/tui/panels.js.map +1 -0
  105. package/dist/tui/templates.js +106 -0
  106. package/dist/tui/templates.js.map +1 -0
  107. package/dist/tui/theme.js +42 -0
  108. package/dist/tui/theme.js.map +1 -0
  109. package/dist/tui/validate.js +51 -0
  110. package/dist/tui/validate.js.map +1 -0
  111. package/{src/tui.tsx → dist/tui.js} +23 -33
  112. package/dist/tui.js.map +1 -0
  113. package/dist/types.js +19 -0
  114. package/dist/types.js.map +1 -0
  115. package/dist/web/oauth-anthropic.js +179 -0
  116. package/dist/web/oauth-anthropic.js.map +1 -0
  117. package/dist/web/session.js +274 -0
  118. package/dist/web/session.js.map +1 -0
  119. package/package.json +5 -4
  120. package/src/bakeoff.ts +0 -214
  121. package/src/build-state.ts +0 -47
  122. package/src/burndown.ts +0 -35
  123. package/src/calibration.ts +0 -88
  124. package/src/cli.ts +0 -263
  125. package/src/cost.ts +0 -43
  126. package/src/council.ts +0 -175
  127. package/src/demo.ts +0 -106
  128. package/src/estimate.ts +0 -111
  129. package/src/executor.ts +0 -169
  130. package/src/git.ts +0 -72
  131. package/src/intake.ts +0 -125
  132. package/src/models.ts +0 -175
  133. package/src/narrate.ts +0 -87
  134. package/src/openrouter.ts +0 -119
  135. package/src/orchestrator.ts +0 -310
  136. package/src/pm.ts +0 -302
  137. package/src/preview.ts +0 -206
  138. package/src/registry-store.ts +0 -41
  139. package/src/registry.ts +0 -132
  140. package/src/research.ts +0 -123
  141. package/src/retro.ts +0 -99
  142. package/src/roles.ts +0 -401
  143. package/src/router.ts +0 -120
  144. package/src/run-bakeoff.ts +0 -77
  145. package/src/run-build.ts +0 -203
  146. package/src/run-web.ts +0 -87
  147. package/src/scout.ts +0 -121
  148. package/src/session-cost.ts +0 -17
  149. package/src/stack.ts +0 -46
  150. package/src/tui/App.tsx +0 -1760
  151. package/src/tui/BakeOff.tsx +0 -190
  152. package/src/tui/BoardEditor.tsx +0 -260
  153. package/src/tui/EditableBoard.tsx +0 -179
  154. package/src/tui/Frame.tsx +0 -142
  155. package/src/tui/Intake.tsx +0 -111
  156. package/src/tui/Kanban.tsx +0 -158
  157. package/src/tui/Settings.tsx +0 -513
  158. package/src/tui/StackPick.tsx +0 -79
  159. package/src/tui/WebAccounts.tsx +0 -197
  160. package/src/tui/components.tsx +0 -340
  161. package/src/tui/config.ts +0 -150
  162. package/src/tui/deploy.ts +0 -137
  163. package/src/tui/engine.ts +0 -749
  164. package/src/tui/notify.ts +0 -21
  165. package/src/tui/panels.tsx +0 -89
  166. package/src/tui/templates.ts +0 -119
  167. package/src/tui/theme.ts +0 -44
  168. package/src/tui/validate.ts +0 -53
  169. package/src/types.ts +0 -208
  170. package/src/web/oauth-anthropic.ts +0 -206
  171. package/src/web/session.ts +0 -299
@@ -0,0 +1,76 @@
1
+ // AI narrative for a build retro. Feeds the data-driven RetroReport to a model
2
+ // and gets back a short "what went well / what to improve" write-up. On-demand
3
+ // (costs a small call) and cached on the build state by the caller.
4
+ import { createAgentSession, } from "@earendil-works/pi-coding-agent";
5
+ import { findEntry } from "./registry.js";
6
+ import { piRuntime, resolvePiModel } from "./executor.js";
7
+ import { addSessionCost } from "./session-cost.js";
8
+ function lastAssistantText(session) {
9
+ const msgs = session.messages;
10
+ for (let i = msgs.length - 1; i >= 0; i--) {
11
+ const m = msgs[i];
12
+ if (m?.role !== "assistant")
13
+ continue;
14
+ const c = m.content;
15
+ if (typeof c === "string")
16
+ return c;
17
+ if (Array.isArray(c)) {
18
+ return c
19
+ .map((p) => (typeof p === "string" ? p : p && typeof p === "object" && "text" in p ? String(p.text) : ""))
20
+ .join("")
21
+ .trim();
22
+ }
23
+ }
24
+ return "";
25
+ }
26
+ /** Compact fact sheet the model reasons over — numbers, not prose. */
27
+ function facts(r) {
28
+ const lines = [
29
+ `Idea: ${r.idea}`,
30
+ `Status: ${r.status}. Tasks done: ${r.doneCount}/${r.taskCount}.`,
31
+ `Cost: predicted $${r.estCost.toFixed(2)}, actual $${r.totalCost.toFixed(2)}.`,
32
+ `Tests: ${r.tests.passed} passed, ${r.tests.failed} failed.`,
33
+ r.retries.length ? `Rebuilds: ${r.retries.map((x) => `${x.taskId}×${x.rounds}`).join(", ")}.` : "Rebuilds: none.",
34
+ `Cost by epic: ${r.byEpic.map((e) => `${e.epic} $${e.cost}`).join(", ") || "n/a"}.`,
35
+ `Cost by model: ${r.byModel.map((m) => `${m.model} $${m.cost} (${m.tasks})`).join(", ") || "n/a"}.`,
36
+ `Priciest tasks: ${r.topCost.map((t) => `${t.taskId} $${t.cost}`).join(", ") || "n/a"}.`,
37
+ r.bugs.length
38
+ ? `Tester flags: ${r.bugs.map((b) => `[${b.severity}] ${b.description}`).slice(0, 6).join("; ")}.`
39
+ : "Tester flags: none.",
40
+ ];
41
+ return lines.join("\n");
42
+ }
43
+ const PROMPT = [
44
+ "You are a pragmatic engineering lead writing a SHORT retro for this build.",
45
+ "Use the facts below — reference the actual numbers. Do not invent anything.",
46
+ "Write exactly three sections, terse bullets, under 140 words total:",
47
+ "**What went well** (2-3 bullets)",
48
+ "**What to improve** (2-3 bullets)",
49
+ "**Next time** (one line)",
50
+ "No preamble, no closing remarks.",
51
+ ].join("\n");
52
+ /** Generate the narrative. Throws on failure (caller shows the error). */
53
+ export async function narrateRetro(report, opts) {
54
+ const runtime = await piRuntime();
55
+ const { entry } = findEntry("plan", "mid");
56
+ const pick = opts.modelOverride ?? entry.byBackend[opts.backend];
57
+ const model = resolvePiModel(runtime, pick.provider, pick.model);
58
+ const { session } = await createAgentSession({
59
+ model,
60
+ modelRuntime: runtime,
61
+ thinkingLevel: "low",
62
+ noTools: "all",
63
+ });
64
+ try {
65
+ await session.prompt(`${PROMPT}\n\n--- FACTS ---\n${facts(report)}`);
66
+ const text = lastAssistantText(session);
67
+ if (!text)
68
+ throw new Error("The model returned no narrative.");
69
+ return text;
70
+ }
71
+ finally {
72
+ addSessionCost(session.getSessionStats().cost);
73
+ session.dispose();
74
+ }
75
+ }
76
+ //# sourceMappingURL=narrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"narrate.js","sourceRoot":"","sources":["../src/narrate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,112 @@
1
+ // The OpenRouter model catalog — so users can pick ANY OpenRouter model by name
2
+ // (Kimi, DeepSeek, Qwen, …) instead of typing slugs.
3
+ //
4
+ // - refreshOpenRouterModels(): live-fetch openrouter.ai/api/v1/models (freshest
5
+ // names + pricing), cache to disk. Falls back to Pi's built-in OR catalog.
6
+ // - openRouterModels() / findOpenRouterModel(): SYNC reads (disk cache, else Pi's
7
+ // built-in list) so cost estimation (getModel) can price any picked model.
8
+ import { piRuntime } from "./executor.js";
9
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
10
+ import { homedir } from "node:os";
11
+ import { join } from "node:path";
12
+ const CACHE = join(homedir(), ".projectinator", "openrouter-models.json");
13
+ let builtinMemo = null;
14
+ let diskMemo; // undefined = not read yet, null = no cache
15
+ /** Pi's built-in OpenRouter catalog — offline, names + pricing. Sync read of the memo;
16
+ * call warmBuiltinOpenRouterModels() once at startup to fill it (Pi's runtime is async). */
17
+ export function builtinOpenRouterModels() {
18
+ return builtinMemo ?? [];
19
+ }
20
+ /** Load Pi's built-in OpenRouter list into the memo. Safe to call repeatedly. */
21
+ export async function warmBuiltinOpenRouterModels() {
22
+ if (builtinMemo)
23
+ return builtinMemo;
24
+ try {
25
+ const runtime = await piRuntime();
26
+ builtinMemo = runtime
27
+ .getModels("openrouter")
28
+ .filter((m) => !!m.cost)
29
+ .map((m) => ({
30
+ id: m.id,
31
+ name: m.name ?? m.id,
32
+ contextWindow: m.contextWindow ?? 200_000,
33
+ cost: m.cost,
34
+ }))
35
+ .sort((a, b) => a.name.localeCompare(b.name));
36
+ }
37
+ catch {
38
+ builtinMemo = [];
39
+ }
40
+ return builtinMemo;
41
+ }
42
+ function readDiskCache() {
43
+ if (diskMemo !== undefined)
44
+ return diskMemo;
45
+ try {
46
+ if (existsSync(CACHE)) {
47
+ const parsed = JSON.parse(readFileSync(CACHE, "utf8"));
48
+ diskMemo = Array.isArray(parsed.models) && parsed.models.length ? parsed.models : null;
49
+ }
50
+ else
51
+ diskMemo = null;
52
+ }
53
+ catch {
54
+ diskMemo = null;
55
+ }
56
+ return diskMemo;
57
+ }
58
+ /** The list to show / price against: live-fetched disk cache if present, else Pi's built-in. */
59
+ export function openRouterModels() {
60
+ const cached = readDiskCache();
61
+ return cached && cached.length ? cached : builtinOpenRouterModels();
62
+ }
63
+ /** Look up one model's pricing/name by slug (cache first, then built-in). Sync. */
64
+ export function findOpenRouterModel(id) {
65
+ return openRouterModels().find((m) => m.id === id) ?? builtinOpenRouterModels().find((m) => m.id === id);
66
+ }
67
+ /** Map OpenRouter's API pricing (USD per token, strings) to our per-1M-token cost. */
68
+ function mapApiModel(m) {
69
+ const p = m.pricing ?? {};
70
+ const input = Number(p.prompt) * 1e6;
71
+ const output = Number(p.completion) * 1e6;
72
+ if (!Number.isFinite(input) || !Number.isFinite(output))
73
+ return null;
74
+ const cacheRead = p.input_cache_read != null ? Number(p.input_cache_read) * 1e6 : input * 0.1;
75
+ const cacheWrite = p.input_cache_write != null ? Number(p.input_cache_write) * 1e6 : input * 1.25;
76
+ return {
77
+ id: m.id,
78
+ name: m.name ?? m.id,
79
+ contextWindow: m.context_length ?? 200_000,
80
+ cost: { input, output, cacheRead, cacheWrite },
81
+ };
82
+ }
83
+ /** Live-fetch the catalog and cache it. Falls back to the current list on any failure. */
84
+ export async function refreshOpenRouterModels(timeoutMs = 8000) {
85
+ const ctrl = new AbortController();
86
+ const timer = setTimeout(() => ctrl.abort(), timeoutMs);
87
+ try {
88
+ const res = await fetch("https://openrouter.ai/api/v1/models", { signal: ctrl.signal });
89
+ if (!res.ok)
90
+ return openRouterModels();
91
+ const json = (await res.json());
92
+ const list = (json.data ?? []).map(mapApiModel).filter((m) => m !== null)
93
+ .sort((a, b) => a.name.localeCompare(b.name));
94
+ if (list.length) {
95
+ try {
96
+ mkdirSync(join(homedir(), ".projectinator"), { recursive: true });
97
+ writeFileSync(CACHE, JSON.stringify({ fetchedAt: Date.now(), models: list }));
98
+ diskMemo = list;
99
+ }
100
+ catch { /* cache write is best-effort */ }
101
+ return list;
102
+ }
103
+ return openRouterModels();
104
+ }
105
+ catch {
106
+ return openRouterModels();
107
+ }
108
+ finally {
109
+ clearTimeout(timer);
110
+ }
111
+ }
112
+ //# sourceMappingURL=openrouter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openrouter.js","sourceRoot":"","sources":["../src/openrouter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,273 @@
1
+ // Phase 4 — the Orchestrator. Runs a whole backlog end to end.
2
+ //
3
+ // - Topologically orders tasks by dependsOn (respects design->code->test->deploy).
4
+ // - Threads handoff context: a task sees the final output of its dependencies.
5
+ // - Runs a Tester -> Developer feedback loop, bounded by maxFeedbackRounds.
6
+ // - Tracks cost and halts on the budget cap.
7
+ //
8
+ // The executor is INJECTED (RoleExecutor), so this entire control flow is testable
9
+ // offline with a fake — no model, no spend. The real Pi executor lives in roles.ts.
10
+ import { TaskLimitError, } from "./types.js";
11
+ import { route } from "./router.js";
12
+ import { REGISTRY } from "./registry.js";
13
+ /** Order tasks so every task comes after its dependencies. Throws on a cycle. */
14
+ export function toposort(tasks) {
15
+ const byId = new Map(tasks.map((t) => [t.id, t]));
16
+ const state = new Map();
17
+ const out = [];
18
+ const visit = (t, trail) => {
19
+ const s = state.get(t.id);
20
+ if (s === "done")
21
+ return;
22
+ if (s === "visiting") {
23
+ throw new Error(`Dependency cycle: ${[...trail, t.id].join(" -> ")}`);
24
+ }
25
+ state.set(t.id, "visiting");
26
+ for (const dep of t.dependsOn ?? []) {
27
+ const d = byId.get(dep);
28
+ if (d)
29
+ visit(d, [...trail, t.id]); // unknown deps already stripped by normalize
30
+ }
31
+ state.set(t.id, "done");
32
+ out.push(t);
33
+ };
34
+ for (const t of tasks)
35
+ visit(t, []);
36
+ return out;
37
+ }
38
+ /** Build handoff text from a task's dependency outcomes. */
39
+ function gatherContext(task, outcomes) {
40
+ const deps = task.dependsOn ?? [];
41
+ if (deps.length === 0)
42
+ return "";
43
+ const parts = [];
44
+ for (const depId of deps) {
45
+ const o = outcomes.get(depId);
46
+ if (!o)
47
+ continue;
48
+ const snippet = o.finalText.trim();
49
+ if (snippet)
50
+ parts.push(`### From ${depId} (${o.capability}):\n${snippet}`);
51
+ if (o.files.length)
52
+ parts.push(`### Files from ${depId}: ${o.files.join(", ")}`);
53
+ }
54
+ return parts.length ? `Context from upstream work:\n\n${parts.join("\n\n")}` : "";
55
+ }
56
+ function bugReport(bugs) {
57
+ return [
58
+ "The tester found these issues. Fix them, then stop:",
59
+ ...bugs.map((b) => `- [${b.severity}]${b.file ? ` (${b.file})` : ""} ${b.description}`),
60
+ ].join("\n");
61
+ }
62
+ export async function runBacklog(tasks, opts) {
63
+ const { policy, execute } = opts;
64
+ const registry = opts.registry ?? REGISTRY;
65
+ const byId = new Map(tasks.map((t) => [t.id, t]));
66
+ const outcomes = new Map();
67
+ const record = [];
68
+ let running = 0;
69
+ // Resume: replay prior outcomes so finished tasks are skipped and cost is restored.
70
+ // A failed attempt is billed but never "done" — it is rebuilt.
71
+ const seed = opts.seedOutcomes ?? [];
72
+ for (const o of seed) {
73
+ record.push(o);
74
+ if (o.error)
75
+ outcomes.delete(o.taskId); // last wins: a later failure voids an earlier pass
76
+ else
77
+ outcomes.set(o.taskId, o);
78
+ running += o.cost;
79
+ }
80
+ running = round2(running);
81
+ const wasDone = new Set(outcomes.keys());
82
+ let halted = false;
83
+ let haltReason;
84
+ const emit = opts.onProgress ?? (() => { });
85
+ const checkpoint = () => opts.onCheckpoint?.(record, round2(running));
86
+ let ordered;
87
+ try {
88
+ ordered = toposort(tasks);
89
+ }
90
+ catch (e) {
91
+ const message = e instanceof Error ? e.message : String(e);
92
+ emit({ type: "cycle_or_error", message });
93
+ return { outcomes: [], totalCost: 0, halted: true, haltReason: message };
94
+ }
95
+ const runOne = async (task, round, contextOverride, tierBump = 0) => {
96
+ const decision = route(task, { policy, registry, runningTotalBefore: running, tierBump });
97
+ emit({ type: "task_start", task, round, provider: decision.provider, modelId: decision.model.id });
98
+ const contextText = contextOverride ?? gatherContext(task, outcomes);
99
+ const meta = { taskId: task.id, capability: task.capability, provider: decision.provider, modelId: decision.model.id, round };
100
+ let outcome;
101
+ try {
102
+ outcome = { ...(await execute({ task, decision, contextText, round, limits: policy.taskLimits })), ...meta };
103
+ }
104
+ catch (e) {
105
+ if (!(e instanceof TaskLimitError))
106
+ throw e;
107
+ // Limit breach: bill what was spent, record the failure, halt the build.
108
+ outcome = { finalText: "", files: [], cost: e.costSoFar, error: e.message, ...meta };
109
+ running += outcome.cost;
110
+ record.push(outcome);
111
+ halted = true;
112
+ haltReason = `${task.id} aborted: ${e.message}`;
113
+ emit({ type: "task_failed", outcome, runningTotal: round2(running) });
114
+ return outcome;
115
+ }
116
+ running += outcome.cost;
117
+ outcomes.set(task.id, outcome);
118
+ record.push(outcome);
119
+ emit({ type: "task_done", outcome, runningTotal: round2(running) });
120
+ return outcome;
121
+ };
122
+ // One task's full lifecycle: run it, then its Reviewer/Tester -> Developer feedback loop.
123
+ const runTaskUnit = async (task) => {
124
+ let outcome = await runOne(task, 0);
125
+ const judges = task.capability === "test" || task.capability === "review";
126
+ if (!outcome.error && judges && outcome.verdict && !outcome.verdict.passed) {
127
+ // The code to fix: direct code deps, plus code deps reached through a review
128
+ // (a test depends on the review, which depends on the code).
129
+ const codeDeps = [];
130
+ for (const id of task.dependsOn ?? []) {
131
+ const dep = byId.get(id);
132
+ if (!dep)
133
+ continue;
134
+ if (dep.capability === "code")
135
+ codeDeps.push(dep);
136
+ else if (dep.capability === "review") {
137
+ for (const id2 of dep.dependsOn ?? []) {
138
+ const d2 = byId.get(id2);
139
+ if (d2?.capability === "code" && !codeDeps.includes(d2))
140
+ codeDeps.push(d2);
141
+ }
142
+ }
143
+ }
144
+ let round = 1;
145
+ fix: while (outcome.verdict && !outcome.verdict.passed && round <= policy.maxFeedbackRounds) {
146
+ emit({ type: "test_failed", taskId: task.id, bugs: outcome.verdict.bugs.length, round });
147
+ const fixContext = bugReport(outcome.verdict.bugs);
148
+ for (const dep of codeDeps) {
149
+ emit({ type: "retry_dev", taskId: dep.id, forTest: task.id, round });
150
+ // Escalation: the developer that just failed review/test retries one tier up.
151
+ // The judge (review/test) stays on its routed model.
152
+ if ((await runOne(dep, round, fixContext, 1)).error)
153
+ break fix;
154
+ }
155
+ outcome = await runOne(task, round); // re-test
156
+ if (outcome.error)
157
+ break;
158
+ round++;
159
+ }
160
+ }
161
+ checkpoint();
162
+ };
163
+ // Human gate: pause once before the first development (code) task begins.
164
+ let gateDone = false;
165
+ const passGate = async () => {
166
+ if (gateDone || !opts.onGate)
167
+ return true;
168
+ gateDone = true;
169
+ emit({ type: "gate", stage: "design→dev" });
170
+ const decision = await opts.onGate({ stage: "design→dev" });
171
+ return decision !== "stop";
172
+ };
173
+ const concurrency = Math.max(1, Math.floor(opts.concurrency ?? 1));
174
+ // ---- sequential path (concurrency 1) — unchanged behavior ----
175
+ if (concurrency === 1) {
176
+ for (const task of ordered) {
177
+ if (wasDone.has(task.id)) {
178
+ emit({ type: "task_skipped", taskId: task.id });
179
+ continue;
180
+ }
181
+ if (task.capability === "code" && !(await passGate())) {
182
+ checkpoint();
183
+ return { outcomes: record, totalCost: round2(running), halted: true, haltReason: "stopped at review gate" };
184
+ }
185
+ const est = route(task, { policy, registry, runningTotalBefore: running });
186
+ if (est.overCap) {
187
+ emit({ type: "budget_halt", runningTotal: round2(running + est.cost), cap: policy.budgetCapUSD });
188
+ checkpoint();
189
+ return { outcomes: record, totalCost: round2(running), halted: true, haltReason: "budget cap" };
190
+ }
191
+ await runTaskUnit(task);
192
+ if (halted)
193
+ return { outcomes: record, totalCost: round2(running), halted, haltReason };
194
+ }
195
+ return { outcomes: record, totalCost: round2(running), halted: false };
196
+ }
197
+ // ---- parallel path (concurrency > 1) — ready-set scheduler ----
198
+ // JS is single-threaded, so mutations between awaits are atomic (no locks needed).
199
+ // Independent tasks (deps satisfied) run concurrently up to `concurrency`. A budget
200
+ // reservation on in-flight estimates prevents launches that could cross the cap.
201
+ const remaining = new Set(ordered.filter((t) => !wasDone.has(t.id)).map((t) => t.id));
202
+ for (const id of wasDone)
203
+ emit({ type: "task_skipped", taskId: id });
204
+ const inFlight = new Map();
205
+ let reserved = 0;
206
+ let codeInFlight = 0; // code tasks are serialized (they share files) even in parallel mode
207
+ let failure; // first task error; rethrown after in-flight work drains
208
+ const depsSatisfied = (t) => (t.dependsOn ?? []).every((d) => !remaining.has(d));
209
+ const readyTasks = () => ordered.filter((t) => remaining.has(t.id) && !inFlight.has(t.id) && depsSatisfied(t));
210
+ while (remaining.size > 0 && !halted) {
211
+ // Gate before any development task launches.
212
+ if (!gateDone && opts.onGate && readyTasks().some((t) => t.capability === "code")) {
213
+ if (!(await passGate())) {
214
+ halted = true;
215
+ haltReason = "stopped at review gate";
216
+ break;
217
+ }
218
+ }
219
+ for (const task of readyTasks()) {
220
+ if (inFlight.size >= concurrency)
221
+ break;
222
+ // Only one code task builds at a time — they write to the shared workspace.
223
+ if (task.capability === "code" && codeInFlight >= 1)
224
+ continue;
225
+ // Reservations keep full precision: rounding each one to cents drops sub-cent
226
+ // estimates entirely, so a wide backlog of cheap tasks would under-reserve.
227
+ const est = route(task, { policy, registry, runningTotalBefore: running + reserved });
228
+ if (running + reserved + est.cost > policy.budgetCapUSD) {
229
+ if (inFlight.size === 0) {
230
+ emit({ type: "budget_halt", runningTotal: round2(running + est.cost), cap: policy.budgetCapUSD });
231
+ halted = true;
232
+ haltReason = "budget cap";
233
+ }
234
+ break; // wait for in-flight tasks to free budget/capacity
235
+ }
236
+ reserved += est.cost;
237
+ const cost = est.cost;
238
+ const isCode = task.capability === "code";
239
+ if (isCode)
240
+ codeInFlight++;
241
+ const settle = () => {
242
+ if (isCode)
243
+ codeInFlight--;
244
+ reserved -= cost;
245
+ remaining.delete(task.id);
246
+ inFlight.delete(task.id);
247
+ };
248
+ // A rejection must NOT escape through Promise.race below: that abandons the
249
+ // sibling promises, and their later rejections would have no handler attached
250
+ // (unhandled rejection -> the host process dies mid-build). Capture the first
251
+ // failure, stop launching, drain what's running, checkpoint, then rethrow.
252
+ const p = runTaskUnit(task).then(settle, (e) => {
253
+ settle();
254
+ halted = true;
255
+ haltReason ??= e instanceof Error ? e.message : String(e);
256
+ failure ??= e;
257
+ });
258
+ inFlight.set(task.id, p);
259
+ }
260
+ if (inFlight.size === 0)
261
+ break; // nothing running and nothing launchable -> done or halted
262
+ await Promise.race(inFlight.values());
263
+ }
264
+ await Promise.all(inFlight.values());
265
+ checkpoint();
266
+ if (failure)
267
+ throw failure;
268
+ return { outcomes: record, totalCost: round2(running), halted, haltReason };
269
+ }
270
+ function round2(n) {
271
+ return Math.round(n * 100) / 100;
272
+ }
273
+ //# sourceMappingURL=orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../src/orchestrator.ts"],"names":[],"mappings":"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"}