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
package/dist/router.js ADDED
@@ -0,0 +1,95 @@
1
+ // The Router — deterministic dispatch. No LLM, no network. Given a tagged task
2
+ // and a policy, it resolves backend -> model -> cost, and flags budget overruns.
3
+ //
4
+ // User prompts (which backend? which model on API?) are injected as callbacks so
5
+ // the router stays pure and unit-testable. In the CLI they wrap real prompts;
6
+ // in tests they're stubs.
7
+ import { estimateCost } from "./cost.js";
8
+ import { getModel } from "./models.js";
9
+ import { findEntry, REGISTRY } from "./registry.js";
10
+ import { modelCalibratedTokens } from "./calibration.js";
11
+ const TIERS = ["fast", "mid", "high"];
12
+ /** Resolve which backend to use from the policy (and a prompt, if "ask"). */
13
+ export function resolveBackend(policy, task, prompts) {
14
+ switch (policy.backendMode) {
15
+ case "api":
16
+ return "api";
17
+ case "web":
18
+ return "web";
19
+ case "cost-first":
20
+ // Web-login rides the user's existing subscription -> effectively free.
21
+ return "web";
22
+ case "ask":
23
+ if (!prompts?.chooseBackend) {
24
+ throw new Error('backendMode "ask" requires prompts.chooseBackend');
25
+ }
26
+ return prompts.chooseBackend(task);
27
+ }
28
+ }
29
+ export function route(task, ctx) {
30
+ const { policy } = ctx;
31
+ const registry = ctx.registry ?? REGISTRY;
32
+ const reasons = [];
33
+ // 1. Backend.
34
+ const backend = resolveBackend(policy, task, ctx.prompts);
35
+ reasons.push(`backend=${backend} (mode=${policy.backendMode})`);
36
+ // 2. Difficulty -> tier (+ escalation).
37
+ const base = policy.difficultyToTier[task.difficulty];
38
+ const tier = TIERS[Math.min(TIERS.length - 1, TIERS.indexOf(base) + (ctx.tierBump ?? 0))];
39
+ reasons.push(`difficulty=${task.difficulty} -> tier=${tier}${tier !== base ? ` (escalated from ${base})` : ""}`);
40
+ // 3. Registry lookup (with tier fallback).
41
+ const { entry, exactTier } = findEntry(task.capability, tier, registry);
42
+ if (!exactTier)
43
+ reasons.push(`no ${task.capability}/${tier} entry, fell back to ${entry.tier}`);
44
+ // 4. Backend-conditional model, with optional per-role prompt on API.
45
+ let modelId = entry.byBackend[backend].model;
46
+ if (backend === "api" && entry.ask && ctx.prompts?.chooseModel) {
47
+ const picked = ctx.prompts.chooseModel(task, entry, backend);
48
+ if (picked && picked !== modelId) {
49
+ reasons.push(`user overrode model ${modelId} -> ${picked}`);
50
+ modelId = picked;
51
+ }
52
+ }
53
+ const model = getModel(modelId);
54
+ reasons.push(`model=${model.id} (${model.provider})`);
55
+ // 5. Cost. Once real runs exist for this model, their average beats the PM-time estimate.
56
+ const est = modelCalibratedTokens(task.capability, task.difficulty, model.id) ?? task.estTokens;
57
+ const cost = estimateCost(est, model);
58
+ if (est !== task.estTokens)
59
+ reasons.push(`tokens from measured runs on ${model.id}`);
60
+ const runningTotal = Math.round(((ctx.runningTotalBefore ?? 0) + cost) * 10_000) / 10_000;
61
+ const overCap = runningTotal > policy.budgetCapUSD;
62
+ if (overCap)
63
+ reasons.push(`OVER CAP: running $${runningTotal} > cap $${policy.budgetCapUSD}`);
64
+ return {
65
+ taskId: task.id,
66
+ backend,
67
+ provider: model.provider,
68
+ model,
69
+ tier: entry.tier,
70
+ cost,
71
+ runningTotal,
72
+ overCap,
73
+ reasons,
74
+ };
75
+ }
76
+ /** Route a whole backlog in order, threading the running total. */
77
+ export function routeBacklog(tasks, ctx) {
78
+ const out = [];
79
+ let running = ctx.runningTotalBefore ?? 0;
80
+ for (const task of tasks) {
81
+ const decision = route(task, { ...ctx, runningTotalBefore: running });
82
+ running = decision.runningTotal;
83
+ out.push(decision);
84
+ }
85
+ return out;
86
+ }
87
+ /** A sensible default policy. */
88
+ export const DEFAULT_POLICY = {
89
+ backendMode: "cost-first",
90
+ budgetCapUSD: 15,
91
+ difficultyToTier: { trivial: "fast", low: "mid", medium: "mid", high: "high" },
92
+ maxFeedbackRounds: 3,
93
+ taskLimits: { timeoutMs: 10 * 60_000, costCapUSD: 3 },
94
+ };
95
+ //# sourceMappingURL=router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ // Model bake-off CLI — run one task across models, compare cost/latency/quality.
2
+ //
3
+ // npm run bakeoff -- --capability design "Design a pricing page with 3 tiers"
4
+ // npm run bakeoff -- --capability plan "Plan an MVP task list for a URL shortener"
5
+ // npm run bakeoff -- --models claude-opus-4-8,claude-sonnet-4-6,claude-haiku-4-5 "..."
6
+ //
7
+ // Defaults to the three Anthropic tiers (what most people hold a key for). Add
8
+ // --models to compare any model ids; --provider to set their provider.
9
+ import { runBakeoff, bakeoffTask } from "./bakeoff.js";
10
+ const args = process.argv.slice(2);
11
+ function opt(name) {
12
+ const i = args.indexOf(name);
13
+ return i >= 0 ? args[i + 1] : undefined;
14
+ }
15
+ const capability = (opt("--capability") ?? "design");
16
+ const difficulty = (opt("--difficulty") ?? "medium");
17
+ const provider = (opt("--provider") ?? "anthropic");
18
+ const modelsArg = opt("--models");
19
+ const consumed = new Set(["--capability", capability, "--difficulty", difficulty, "--provider", provider, "--models", modelsArg ?? ""].filter(Boolean));
20
+ const prompt = args.filter((a) => !consumed.has(a)).join(" ").trim();
21
+ if (!prompt) {
22
+ console.log('\n Usage: npm run bakeoff -- --capability design "your task"\n');
23
+ process.exit(1);
24
+ }
25
+ if (capability === "code") {
26
+ console.log("\n Code bake-off isn't supported yet (needs a sandbox + real test scoring per model).");
27
+ console.log(" Try --capability design or plan for now.\n");
28
+ process.exit(1);
29
+ }
30
+ const models = (modelsArg ?? "claude-opus-4-8,claude-sonnet-4-6,claude-haiku-4-5").split(",").map((s) => s.trim()).filter(Boolean);
31
+ const candidates = models.map((model) => ({ provider, model }));
32
+ console.log(`\n Bake-off — ${capability}/${difficulty} ${candidates.length} models\n Task: ${prompt}\n`);
33
+ const result = await runBakeoff(bakeoffTask(prompt, capability, difficulty), candidates, {
34
+ onProgress: (m) => console.log(" " + m),
35
+ });
36
+ // ---- report ----
37
+ const scoreOf = new Map(result.scores.map((s) => [s.model, s]));
38
+ const money = (n) => `$${n.toFixed(4)}`;
39
+ console.log("\n --- RESULTS ---");
40
+ console.log(" model".padEnd(30) + "score".padEnd(8) + "cost".padEnd(12) + "time".padEnd(8) + "tokens");
41
+ for (const e of result.entries) {
42
+ const key = `${e.provider}/${e.model}`;
43
+ const sc = scoreOf.get(key);
44
+ const scoreStr = e.error ? "ERR" : sc ? `${sc.score}/10` : "—";
45
+ const line = (" " + e.model).padEnd(30) +
46
+ scoreStr.padEnd(8) +
47
+ (e.error ? "—" : money(e.cost)).padEnd(12) +
48
+ (e.error ? "—" : `${(e.ms / 1000).toFixed(1)}s`).padEnd(8) +
49
+ (e.error ? "" : String(e.outputTokens));
50
+ console.log(line);
51
+ if (e.error)
52
+ console.log(` ↳ ${e.error}`);
53
+ }
54
+ if (result.winner) {
55
+ const w = result.entries.find((e) => `${e.provider}/${e.model}` === result.winner);
56
+ const wc = w?.cost ?? 0;
57
+ const cheapest = result.entries.filter((e) => !e.error).sort((a, b) => a.cost - b.cost)[0];
58
+ console.log(`\n 🏆 Best quality: ${result.winner} (judge: ${result.judge})`);
59
+ if (cheapest && `${cheapest.provider}/${cheapest.model}` !== result.winner) {
60
+ console.log(` 💸 Cheapest: ${cheapest.provider}/${cheapest.model} at ${money(cheapest.cost)} (winner cost ${money(wc)})`);
61
+ }
62
+ for (const s of result.scores.sort((a, b) => b.score - a.score)) {
63
+ console.log(` ${s.score}/10 ${s.model} — ${s.reason}`);
64
+ }
65
+ }
66
+ console.log("");
67
+ process.exit(0);
68
+ //# sourceMappingURL=run-bakeoff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-bakeoff.js","sourceRoot":"","sources":["../src/run-bakeoff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,193 @@
1
+ // Phase 4 entry — run a whole build end to end.
2
+ //
3
+ // npm run build -- "an idea" dry: decompose + toposort + routing plan, NO spend
4
+ // npm run build -- --mini dry: tiny fixed 3-task backlog (design->code->test)
5
+ // npm run build -- --live --mini LIVE: run the mini backlog (cheap end-to-end)
6
+ // npm run build -- --live --lock anthropic "an idea" LIVE: full pipeline on one provider
7
+ //
8
+ // --lock <provider> routes every role to one provider (use the one you hold a key for).
9
+ // Default lock is anthropic.
10
+ import { mkdirSync } from "node:fs";
11
+ import { fileURLToPath } from "node:url";
12
+ import { dirname, join } from "node:path";
13
+ import { DEFAULT_POLICY } from "./router.js";
14
+ import { toposort, runBacklog } from "./orchestrator.js";
15
+ import { lockRegistryToProvider, makePiExecutor } from "./roles.js";
16
+ import { estimateTokens } from "./estimate.js";
17
+ import { route } from "./router.js";
18
+ import { decomposeIdea } from "./pm.js";
19
+ import { newBuildState, saveState, loadState, completedIds } from "./build-state.js";
20
+ import { initRepo, commitTask } from "./git.js";
21
+ const args = process.argv.slice(2);
22
+ const live = args.includes("--live");
23
+ const mini = args.includes("--mini");
24
+ const fan = args.includes("--fan");
25
+ const resume = args.includes("--resume");
26
+ const lockIdx = args.indexOf("--lock");
27
+ const lockProvider = (lockIdx >= 0 ? args[lockIdx + 1] : "anthropic");
28
+ const concIdx = args.indexOf("--concurrency");
29
+ const concurrency = Math.max(1, parseInt((concIdx >= 0 ? args[concIdx + 1] : "1") ?? "1", 10) || 1);
30
+ const capIdx = args.indexOf("--task-cap");
31
+ const tmoIdx = args.indexOf("--task-timeout");
32
+ const consumed = new Set(["--live", "--mini", "--fan", "--resume", "--lock", lockIdx >= 0 ? args[lockIdx + 1] : "",
33
+ "--concurrency", concIdx >= 0 ? args[concIdx + 1] : "",
34
+ "--task-cap", capIdx >= 0 ? args[capIdx + 1] : "",
35
+ "--task-timeout", tmoIdx >= 0 ? args[tmoIdx + 1] : ""].filter(Boolean));
36
+ const idea = args.filter((a) => !consumed.has(a)).join(" ").trim() ||
37
+ "A one-page site with a headline and a contact form.";
38
+ const money = (n) => `$${n.toFixed(2)}`;
39
+ const registry = lockRegistryToProvider(lockProvider);
40
+ // --task-cap USD / --task-timeout MIN override the per-task limits (0 = unlimited).
41
+ const taskLimits = {
42
+ costCapUSD: capIdx >= 0 ? parseFloat(args[capIdx + 1] ?? "") : DEFAULT_POLICY.taskLimits.costCapUSD,
43
+ timeoutMs: tmoIdx >= 0 ? parseFloat(args[tmoIdx + 1] ?? "") * 60_000 : DEFAULT_POLICY.taskLimits.timeoutMs,
44
+ };
45
+ const policy = { ...DEFAULT_POLICY, backendMode: "api", budgetCapUSD: mini ? 10 : 25, taskLimits };
46
+ // --- a tiny fixed backlog for cheap end-to-end proof ---
47
+ function miniBacklog() {
48
+ const mk = (id, cap, diff, title, deps = []) => ({
49
+ id, title, capability: cap, difficulty: diff, dependsOn: deps, estTokens: estimateTokens(cap, diff),
50
+ });
51
+ return [
52
+ mk("D-1", "design", "low", "Write a short design spec for a centered card that says 'Hello from Projectinator' on a soft gradient background."),
53
+ mk("C-1", "code", "low", "Create index.html implementing the design spec exactly. Single self-contained file with embedded CSS.", ["D-1"]),
54
+ mk("R-1", "review", "trivial", "Review index.html against the design spec: file present, no unresolved references, runs on double-click.", ["C-1"]),
55
+ mk("T-1", "test", "trivial", "Open/read index.html and verify it is valid HTML and matches the design spec (centered card, the headline text, a gradient).", ["R-1"]),
56
+ ];
57
+ }
58
+ // A fan-out backlog with independent branches, to show parallel execution:
59
+ // two design tasks (independent) -> two code tasks -> one test that joins them.
60
+ function fanBacklog() {
61
+ const mk = (id, cap, diff, title, deps = []) => ({
62
+ id, title, capability: cap, difficulty: diff, dependsOn: deps, estTokens: estimateTokens(cap, diff),
63
+ });
64
+ return [
65
+ mk("DA", "design", "low", "Design spec for a 'Newsletter signup' card (email input + button)."),
66
+ mk("DB", "design", "low", "Design spec for an 'FAQ' accordion (3 questions)."),
67
+ mk("CA", "code", "low", "Create newsletter.html from the newsletter design spec.", ["DA"]),
68
+ mk("CB", "code", "low", "Create faq.html from the FAQ design spec.", ["DB"]),
69
+ mk("RA", "review", "trivial", "Review newsletter.html against its spec.", ["CA"]),
70
+ mk("RB", "review", "trivial", "Review faq.html against its spec.", ["CB"]),
71
+ mk("TJ", "test", "trivial", "Verify newsletter.html and faq.html are valid and match their specs.", ["RA", "RB"]),
72
+ ];
73
+ }
74
+ async function getTasks() {
75
+ if (fan)
76
+ return fanBacklog();
77
+ if (mini)
78
+ return miniBacklog();
79
+ if (!live) {
80
+ // Dry + full idea: we can't call the PM without spending, so show the mini path.
81
+ console.log(" (Full-idea decomposition needs the PM model. Use --mini for a dry preview, or add --live.)\n");
82
+ return miniBacklog();
83
+ }
84
+ console.log(" Decomposing idea with PM...\n");
85
+ const res = await decomposeIdea(idea, {
86
+ backend: "api",
87
+ modelOverride: { provider: lockProvider, model: lockRegistryToProvider(lockProvider).find((e) => e.capability === "plan").byBackend.api.model },
88
+ });
89
+ console.log(` PM produced ${res.tasks.length} tasks.\n`);
90
+ return res.tasks;
91
+ }
92
+ const variant = fan ? " / fan" : mini ? " / mini" : "";
93
+ console.log(`\n Projectinator — Phase 4 full build [${live ? "LIVE" : "DRY"}${variant}] lock=${lockProvider} concurrency=${concurrency}\n`);
94
+ if (!mini && !fan)
95
+ console.log(` Idea: ${idea}\n`);
96
+ let tasks = await getTasks();
97
+ // Dry: show plan only.
98
+ if (!live) {
99
+ const ordered = toposort(tasks);
100
+ console.log(" Execution order (toposorted):");
101
+ let est = 0;
102
+ for (const t of ordered) {
103
+ const d = route(t, { policy, registry, runningTotalBefore: est });
104
+ est = d.runningTotal;
105
+ const dep = t.dependsOn?.length ? ` <- ${t.dependsOn.join(",")}` : "";
106
+ console.log(` ${t.id.padEnd(6)} [${t.capability}/${t.difficulty}] -> ${d.model.name.padEnd(20)} ${money(d.cost)}${dep}`);
107
+ }
108
+ console.log(`\n Estimated total: ${money(est)} (cap ${money(policy.budgetCapUSD)})`);
109
+ console.log(" Dry run. Add --live to actually build.\n");
110
+ process.exit(0);
111
+ }
112
+ // Live: key check.
113
+ const envKey = {
114
+ anthropic: ["ANTHROPIC_API_KEY"],
115
+ openai: ["OPENAI_API_KEY"],
116
+ google: ["GEMINI_API_KEY", "GOOGLE_API_KEY", "GOOGLE_GENERATIVE_AI_API_KEY"],
117
+ openrouter: ["OPENROUTER_API_KEY"],
118
+ };
119
+ if (!(envKey[lockProvider] ?? []).some((k) => process.env[k])) {
120
+ console.error(` No API key for ${lockProvider}. Set: ${(envKey[lockProvider] ?? []).join(", ")}\n`);
121
+ process.exit(1);
122
+ }
123
+ const projectRoot = dirname(dirname(fileURLToPath(import.meta.url)));
124
+ const workspace = join(projectRoot, ".workspace", fan ? "fan-build" : mini ? "mini-build" : "build");
125
+ mkdirSync(workspace, { recursive: true });
126
+ const statePath = join(workspace, "build-state.json");
127
+ // Resume: load prior state, reuse its saved backlog, seed finished outcomes.
128
+ let state;
129
+ let seedOutcomes = undefined;
130
+ const prior = resume ? loadState(statePath) : undefined;
131
+ if (prior) {
132
+ state = prior;
133
+ state.status = "running";
134
+ tasks = prior.tasks; // authoritative backlog from the interrupted run
135
+ seedOutcomes = prior.outcomes;
136
+ const doneCount = completedIds(prior).size;
137
+ console.log(` Resuming: ${doneCount} task(s) already done, restored ${money(prior.totalCost)}.`);
138
+ }
139
+ else {
140
+ if (resume)
141
+ console.log(" (No prior state found — starting fresh.)");
142
+ state = newBuildState(fan ? "fan-build" : mini ? "mini-build" : "build", tasks);
143
+ }
144
+ console.log(` Workspace: ${workspace}\n Building...\n`);
145
+ // Version the workspace + commit after each task.
146
+ initRepo(workspace);
147
+ const titleById = new Map(tasks.map((t) => [t.id, t.title]));
148
+ const onEvent = (_e) => { };
149
+ const executor = makePiExecutor({
150
+ workspace,
151
+ backend: "api",
152
+ onEvent,
153
+ onFallback: (info) => console.log(` ↪ ${info.taskId}: ${info.from} failed — fell back to ${info.to}/${info.model}`),
154
+ });
155
+ const onProgress = (e) => {
156
+ if (e.type === "task_start")
157
+ console.log(` ▶ ${e.task.id} [${e.task.capability}] -> ${e.provider}/${e.modelId} (round ${e.round})`);
158
+ else if (e.type === "task_done") {
159
+ const hash = commitTask(workspace, e.outcome.taskId, titleById.get(e.outcome.taskId) ?? e.outcome.taskId);
160
+ console.log(` ✓ ${e.outcome.taskId} ${money(e.outcome.cost)} running ${money(e.runningTotal)}${e.outcome.verdict ? ` verdict=${e.outcome.verdict.passed ? (e.outcome.verdict.runtimeChecked ? "PASS" : "PASS* (app not executed — no Chromium)") : "FAIL"}` : ""}${hash ? ` [${hash}]` : ""}`);
161
+ }
162
+ else if (e.type === "task_failed")
163
+ console.log(` ⛔ ${e.outcome.taskId} ABORTED (${e.outcome.error}) — billed ${money(e.outcome.cost)}, halting`);
164
+ else if (e.type === "task_skipped")
165
+ console.log(` · ${e.taskId} skipped (already done)`);
166
+ else if (e.type === "test_failed")
167
+ console.log(` ✗ ${e.taskId} FAILED (${e.bugs} bugs) — round ${e.round}`);
168
+ else if (e.type === "retry_dev")
169
+ console.log(` ↻ re-running ${e.taskId} to fix ${e.forTest}`);
170
+ else if (e.type === "budget_halt")
171
+ console.log(` ⚠ BUDGET HALT at ${money(e.runningTotal)} (cap ${money(e.cap)})`);
172
+ };
173
+ // Checkpoint after every task so a crash/cancel loses at most one task.
174
+ const onCheckpoint = (outcomes, totalCost) => {
175
+ state.outcomes = outcomes;
176
+ state.totalCost = totalCost;
177
+ saveState(state, statePath);
178
+ };
179
+ const result = await runBacklog(tasks, { policy, execute: executor, registry, onProgress, seedOutcomes, onCheckpoint, concurrency });
180
+ state.outcomes = result.outcomes;
181
+ state.totalCost = result.totalCost;
182
+ state.status = result.halted ? "halted" : "complete";
183
+ state.haltReason = result.haltReason;
184
+ saveState(state, statePath);
185
+ console.log(`\n --- BUILD ${result.halted ? "HALTED" : "COMPLETE"} ---`);
186
+ console.log(` Steps run: ${result.outcomes.length}`);
187
+ console.log(` Total cost: ${money(result.totalCost)}`);
188
+ if (result.haltReason)
189
+ console.log(` Halt reason: ${result.haltReason} (re-run with --resume to continue)`);
190
+ const finalFiles = result.outcomes.at(-1)?.files ?? [];
191
+ console.log(` Files in workspace: ${finalFiles.join(", ") || "(none)"}`);
192
+ console.log(` State saved: ${statePath}\n`);
193
+ //# sourceMappingURL=run-build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-build.js","sourceRoot":"","sources":["../src/run-build.ts"],"names":[],"mappings":"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"}
@@ -4,77 +4,61 @@
4
4
  // npm run dev:task -- --live actually run the agent (spends money, needs an API key)
5
5
  //
6
6
  // Dry mode proves the whole wiring offline. Live mode is opt-in and key-gated.
7
-
8
7
  import { mkdirSync } from "node:fs";
9
8
  import { fileURLToPath } from "node:url";
10
9
  import { dirname, join } from "node:path";
11
- import type { AgentSessionEvent } from "@earendil-works/pi-coding-agent";
12
- import type { Task } from "./types.js";
13
10
  import { DEFAULT_POLICY, route } from "./router.js";
14
11
  import { buildDeveloperPrompt, executeTask, piRuntime, resolvePiModel } from "./executor.js";
15
-
16
- const TASK: Task = {
17
- id: "T-DEV1",
18
- story: "S-1",
19
- title: "Create a single-file landing page (index.html) for 'Projectinator' with a hero headline, one-line pitch, and a contact form (name, email, message) styled with embedded CSS. No external assets.",
20
- capability: "code",
21
- difficulty: "high",
22
- estTokens: { input: 40_000, output: 12_000, cachedInputFraction: 0.3 },
12
+ const TASK = {
13
+ id: "T-DEV1",
14
+ story: "S-1",
15
+ title: "Create a single-file landing page (index.html) for 'Projectinator' with a hero headline, one-line pitch, and a contact form (name, email, message) styled with embedded CSS. No external assets.",
16
+ capability: "code",
17
+ difficulty: "high",
18
+ estTokens: { input: 40_000, output: 12_000, cachedInputFraction: 0.3 },
23
19
  };
24
-
25
20
  const live = process.argv.includes("--live");
26
-
27
21
  // Route it. Web-login backend isn't built yet -> use API.
28
- const policy = { ...DEFAULT_POLICY, backendMode: "api" as const };
22
+ const policy = { ...DEFAULT_POLICY, backendMode: "api" };
29
23
  const decision = route(TASK, { policy });
30
-
31
24
  const piModel = resolvePiModel(await piRuntime(), decision.provider, decision.model.id); // offline, free
32
-
33
- const money = (n: number) => `$${n.toFixed(2)}`;
34
-
25
+ const money = (n) => `$${n.toFixed(2)}`;
35
26
  console.log(`\n Projectinator — Phase 2 developer run [${live ? "LIVE" : "DRY"}]\n`);
36
27
  console.log(` Task ${TASK.id}: ${TASK.title.slice(0, 64)}...`);
37
28
  console.log(` Routed ${decision.provider}/${decision.model.id} (tier=${decision.tier}, backend=${decision.backend})`);
38
29
  console.log(` Pi model resolved: ${piModel.id} ctx=${piModel.contextWindow} in/out=${piModel.cost?.input}/${piModel.cost?.output}`);
39
30
  console.log(` Est cost ${money(decision.cost)}\n`);
40
-
41
31
  if (!live) {
42
- console.log(" --- developer prompt (not sent) ---");
43
- console.log(buildDeveloperPrompt(TASK).split("\n").map((l) => " | " + l).join("\n"));
44
- console.log("\n Dry run only. Wiring verified: task routed, Pi model resolved, prompt built.");
45
- console.log(" Re-run with --live (and an API key) to actually build.\n");
46
- process.exit(0);
32
+ console.log(" --- developer prompt (not sent) ---");
33
+ console.log(buildDeveloperPrompt(TASK).split("\n").map((l) => " | " + l).join("\n"));
34
+ console.log("\n Dry run only. Wiring verified: task routed, Pi model resolved, prompt built.");
35
+ console.log(" Re-run with --live (and an API key) to actually build.\n");
36
+ process.exit(0);
47
37
  }
48
-
49
38
  // --- LIVE PATH: spends money ---
50
- const envKey: Record<string, string[]> = {
51
- anthropic: ["ANTHROPIC_API_KEY"],
52
- openai: ["OPENAI_API_KEY"],
53
- google: ["GEMINI_API_KEY", "GOOGLE_API_KEY", "GOOGLE_GENERATIVE_AI_API_KEY"],
39
+ const envKey = {
40
+ anthropic: ["ANTHROPIC_API_KEY"],
41
+ openai: ["OPENAI_API_KEY"],
42
+ google: ["GEMINI_API_KEY", "GOOGLE_API_KEY", "GOOGLE_GENERATIVE_AI_API_KEY"],
54
43
  };
55
44
  const keyPresent = (envKey[decision.provider] ?? []).some((k) => !!process.env[k]);
56
45
  if (!keyPresent) {
57
- console.error(
58
- ` No API key for ${decision.provider}. Set one of: ${(envKey[decision.provider] ?? []).join(", ")}\n`,
59
- );
60
- process.exit(1);
46
+ console.error(` No API key for ${decision.provider}. Set one of: ${(envKey[decision.provider] ?? []).join(", ")}\n`);
47
+ process.exit(1);
61
48
  }
62
-
63
49
  // fileURLToPath decodes %20/%7E etc. — URL.pathname would leave them encoded and
64
50
  // create a literally-named "Mobile%20Documents" directory.
65
51
  const projectRoot = dirname(dirname(fileURLToPath(import.meta.url)));
66
52
  const workspace = join(projectRoot, ".workspace", TASK.id);
67
53
  mkdirSync(workspace, { recursive: true });
68
54
  console.log(` Workspace: ${workspace}\n Running agent...\n`);
69
-
70
- const onEvent = (e: AgentSessionEvent) => {
71
- process.stdout.write(` · ${e.type}\n`);
55
+ const onEvent = (e) => {
56
+ process.stdout.write(` · ${e.type}\n`);
72
57
  };
73
-
74
58
  const result = await executeTask(TASK, decision, { workspace, onEvent });
75
-
76
59
  console.log(`\n --- done ---`);
77
60
  console.log(` Files: ${result.files.join(", ") || "(none)"}`);
78
61
  console.log(` Tokens: in=${result.actual.input} out=${result.actual.output} cacheRead=${result.actual.cacheRead} total=${result.actual.total}`);
79
62
  console.log(` Est: ${money(result.estCost)}`);
80
63
  console.log(` Actual: ${money(result.actualCost)} (delta ${money(result.costDelta)})\n`);
64
+ //# sourceMappingURL=run-dev.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-dev.js","sourceRoot":"","sources":["../src/run-dev.ts"],"names":[],"mappings":"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"}
@@ -4,87 +4,75 @@
4
4
  // npm run pm -- --live "your idea here" live: decompose + route the backlog
5
5
  //
6
6
  // Live decomposition needs an API key (PM routes to an OpenAI model by default).
7
-
8
- import type { AgentSessionEvent } from "@earendil-works/pi-coding-agent";
9
7
  import { DEFAULT_POLICY, routeBacklog } from "./router.js";
10
8
  import { findEntry } from "./registry.js";
11
- import { piRuntime, resolvePiModel } from "./executor.js"
9
+ import { piRuntime, resolvePiModel } from "./executor.js";
12
10
  import { decomposeIdea, pmSystemPrompt } from "./pm.js";
13
-
14
11
  const args = process.argv.slice(2);
15
12
  const live = args.includes("--live");
16
-
17
13
  // Optional PM model override: --pm <provider/id> (e.g. anthropic/claude-sonnet-4-6).
18
14
  // Lets you decompose with whichever provider you hold a key for.
19
15
  const pmIdx = args.indexOf("--pm");
20
16
  const pmOverride = pmIdx >= 0 ? args[pmIdx + 1] : undefined;
21
- const consumed = new Set<string>(["--live", "--pm", pmOverride].filter(Boolean) as string[]);
17
+ const consumed = new Set(["--live", "--pm", pmOverride].filter(Boolean));
22
18
  const idea = args.filter((a) => !consumed.has(a)).join(" ").trim() ||
23
- "A simple personal task tracker web app: add tasks, mark them done, filter by status.";
24
-
25
- const backend = "api" as const; // web-login backend not built yet
26
- const money = (n: number) => `$${n.toFixed(2)}`;
27
-
19
+ "A simple personal task tracker web app: add tasks, mark them done, filter by status.";
20
+ const backend = "api"; // web-login backend not built yet
21
+ const money = (n) => `$${n.toFixed(2)}`;
28
22
  const runtime = await piRuntime();
29
23
  const { entry } = findEntry("plan", "mid");
30
24
  const pick = pmOverride
31
- ? { provider: pmOverride.split("/")[0] as typeof entry.byBackend[typeof backend]["provider"], model: pmOverride.split("/").slice(1).join("/") }
32
- : entry.byBackend[backend];
25
+ ? { provider: pmOverride.split("/")[0], model: pmOverride.split("/").slice(1).join("/") }
26
+ : entry.byBackend[backend];
33
27
  const pm = resolvePiModel(runtime, pick.provider, pick.model); // offline
34
-
35
28
  console.log(`\n Projectinator — Phase 3 PM decomposer [${live ? "LIVE" : "DRY"}]\n`);
36
29
  console.log(` Idea: ${idea}`);
37
30
  console.log(` PM model: ${pick.provider}/${pm.id} (tier=${entry.tier}, backend=${backend})\n`);
38
-
39
31
  if (!live) {
40
- console.log(" --- PM system prompt (not sent) ---");
41
- console.log(pmSystemPrompt().split("\n").map((l) => " | " + l).join("\n"));
42
- console.log("\n Dry run. Re-run with --live (and an API key) to actually decompose.\n");
43
- process.exit(0);
32
+ console.log(" --- PM system prompt (not sent) ---");
33
+ console.log(pmSystemPrompt().split("\n").map((l) => " | " + l).join("\n"));
34
+ console.log("\n Dry run. Re-run with --live (and an API key) to actually decompose.\n");
35
+ process.exit(0);
44
36
  }
45
-
46
- const envKey: Record<string, string[]> = {
47
- anthropic: ["ANTHROPIC_API_KEY"],
48
- openai: ["OPENAI_API_KEY"],
49
- google: ["GEMINI_API_KEY", "GOOGLE_API_KEY", "GOOGLE_GENERATIVE_AI_API_KEY"],
37
+ const envKey = {
38
+ anthropic: ["ANTHROPIC_API_KEY"],
39
+ openai: ["OPENAI_API_KEY"],
40
+ google: ["GEMINI_API_KEY", "GOOGLE_API_KEY", "GOOGLE_GENERATIVE_AI_API_KEY"],
50
41
  };
51
42
  if (!(envKey[pick.provider] ?? []).some((k) => process.env[k])) {
52
- console.error(` No API key for ${pick.provider}. Set: ${(envKey[pick.provider] ?? []).join(", ")}\n`);
53
- process.exit(1);
43
+ console.error(` No API key for ${pick.provider}. Set: ${(envKey[pick.provider] ?? []).join(", ")}\n`);
44
+ process.exit(1);
54
45
  }
55
-
56
46
  console.log(" Decomposing...\n");
57
- const onEvent = (e: AgentSessionEvent) => {
58
- if (e.type === "tool_execution_end" || e.type === "agent_end") process.stdout.write(` · ${e.type}\n`);
47
+ const onEvent = (e) => {
48
+ if (e.type === "tool_execution_end" || e.type === "agent_end")
49
+ process.stdout.write(` · ${e.type}\n`);
59
50
  };
60
-
61
51
  const result = await decomposeIdea(idea, {
62
- backend,
63
- onEvent,
64
- modelOverride: pmOverride ? { provider: pick.provider, model: pick.model } : undefined,
52
+ backend,
53
+ onEvent,
54
+ modelOverride: pmOverride ? { provider: pick.provider, model: pick.model } : undefined,
65
55
  });
66
-
67
56
  console.log(`\n --- BACKLOG (${result.provider}/${result.modelId}) ---`);
68
57
  for (const t of result.backlog.tasks) {
69
- const dep = (t.dependsOn ?? []).length ? ` <- ${(t.dependsOn ?? []).join(",")}` : "";
70
- const grp = t.epic ? `${t.epic}${t.story ? "/" + t.story : ""} ` : "";
71
- console.log(` ${t.id.padEnd(6)} [${t.capability}/${t.difficulty}] ${grp}${t.title}${dep}`);
58
+ const dep = (t.dependsOn ?? []).length ? ` <- ${(t.dependsOn ?? []).join(",")}` : "";
59
+ const grp = t.epic ? `${t.epic}${t.story ? "/" + t.story : ""} ` : "";
60
+ console.log(` ${t.id.padEnd(6)} [${t.capability}/${t.difficulty}] ${grp}${t.title}${dep}`);
72
61
  }
73
62
  if (result.diagnostics.length) {
74
- console.log(`\n Normalizer notes:`);
75
- for (const d of result.diagnostics) console.log(` ! ${d}`);
63
+ console.log(`\n Normalizer notes:`);
64
+ for (const d of result.diagnostics)
65
+ console.log(` ! ${d}`);
76
66
  }
77
-
78
67
  // Route the whole backlog and total the cost.
79
68
  const decisions = routeBacklog(result.tasks, { policy: { ...DEFAULT_POLICY, backendMode: backend } });
80
69
  console.log(`\n --- ROUTING PLAN ---`);
81
70
  console.log(" " + "TASK".padEnd(7) + "CAP/DIFF".padEnd(16) + "MODEL".padEnd(22) + "COST");
82
71
  for (const d of decisions) {
83
- const t = result.tasks.find((x) => x.id === d.taskId)!;
84
- console.log(
85
- " " + d.taskId.padEnd(7) +
86
- `${t.capability}/${t.difficulty}`.padEnd(16) +
87
- d.model.name.padEnd(22) + money(d.cost),
88
- );
72
+ const t = result.tasks.find((x) => x.id === d.taskId);
73
+ console.log(" " + d.taskId.padEnd(7) +
74
+ `${t.capability}/${t.difficulty}`.padEnd(16) +
75
+ d.model.name.padEnd(22) + money(d.cost));
89
76
  }
90
77
  console.log(`\n Tasks: ${result.tasks.length} Estimated total: ${money(decisions.at(-1)?.runningTotal ?? 0)}\n`);
78
+ //# sourceMappingURL=run-pm.js.map