projectinator 0.3.0 → 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.
- package/README.md +30 -11
- package/bin/projectinator.mjs +56 -11
- package/dist/bakeoff.js +163 -0
- package/dist/bakeoff.js.map +1 -0
- package/dist/build-state.js +26 -0
- package/dist/build-state.js.map +1 -0
- package/dist/burndown.js +19 -0
- package/dist/burndown.js.map +1 -0
- package/dist/calibration.js +86 -0
- package/dist/calibration.js.map +1 -0
- package/dist/cli.js +289 -0
- package/dist/cli.js.map +1 -0
- package/dist/cost.js +35 -0
- package/dist/cost.js.map +1 -0
- package/dist/council.js +147 -0
- package/dist/council.js.map +1 -0
- package/dist/demo.js +93 -0
- package/dist/demo.js.map +1 -0
- package/dist/estimate.js +98 -0
- package/dist/estimate.js.map +1 -0
- package/dist/executor.js +118 -0
- package/dist/executor.js.map +1 -0
- package/dist/git.js +82 -0
- package/dist/git.js.map +1 -0
- package/dist/intake.js +98 -0
- package/dist/intake.js.map +1 -0
- package/dist/models.js +171 -0
- package/dist/models.js.map +1 -0
- package/dist/narrate.js +76 -0
- package/dist/narrate.js.map +1 -0
- package/dist/openrouter.js +112 -0
- package/dist/openrouter.js.map +1 -0
- package/dist/orchestrator.js +273 -0
- package/dist/orchestrator.js.map +1 -0
- package/dist/pm.js +245 -0
- package/dist/pm.js.map +1 -0
- package/dist/preview.js +194 -0
- package/dist/preview.js.map +1 -0
- package/dist/registry-store.js +38 -0
- package/dist/registry-store.js.map +1 -0
- package/dist/registry.js +115 -0
- package/dist/registry.js.map +1 -0
- package/dist/research.js +98 -0
- package/dist/research.js.map +1 -0
- package/dist/retro.js +83 -0
- package/dist/retro.js.map +1 -0
- package/dist/roles.js +357 -0
- package/dist/roles.js.map +1 -0
- package/dist/router.js +95 -0
- package/dist/router.js.map +1 -0
- package/dist/run-bakeoff.js +68 -0
- package/dist/run-bakeoff.js.map +1 -0
- package/dist/run-build.js +193 -0
- package/dist/run-build.js.map +1 -0
- package/{src/run-dev.ts → dist/run-dev.js} +23 -39
- package/dist/run-dev.js.map +1 -0
- package/{src/run-pm.ts → dist/run-pm.js} +34 -46
- package/dist/run-pm.js.map +1 -0
- package/{src/run-research.ts → dist/run-research.js} +19 -30
- package/dist/run-research.js.map +1 -0
- package/{src/run-scout.ts → dist/run-scout.js} +17 -27
- package/dist/run-scout.js.map +1 -0
- package/dist/run-web.js +93 -0
- package/dist/run-web.js.map +1 -0
- package/dist/scout.js +81 -0
- package/dist/scout.js.map +1 -0
- package/dist/session-cost.js +15 -0
- package/dist/session-cost.js.map +1 -0
- package/dist/stack.js +34 -0
- package/dist/stack.js.map +1 -0
- package/dist/stuck.js +21 -0
- package/dist/stuck.js.map +1 -0
- package/dist/tui/App.js +1269 -0
- package/dist/tui/App.js.map +1 -0
- package/dist/tui/BakeOff.js +95 -0
- package/dist/tui/BakeOff.js.map +1 -0
- package/dist/tui/BoardEditor.js +183 -0
- package/dist/tui/BoardEditor.js.map +1 -0
- package/dist/tui/EditableBoard.js +140 -0
- package/dist/tui/EditableBoard.js.map +1 -0
- package/dist/tui/Frame.js +78 -0
- package/dist/tui/Frame.js.map +1 -0
- package/dist/tui/Intake.js +59 -0
- package/dist/tui/Intake.js.map +1 -0
- package/dist/tui/Kanban.js +75 -0
- package/dist/tui/Kanban.js.map +1 -0
- package/dist/tui/Settings.js +299 -0
- package/dist/tui/Settings.js.map +1 -0
- package/dist/tui/StackPick.js +44 -0
- package/dist/tui/StackPick.js.map +1 -0
- package/dist/tui/WebAccounts.js +131 -0
- package/dist/tui/WebAccounts.js.map +1 -0
- package/dist/tui/components.js +178 -0
- package/dist/tui/components.js.map +1 -0
- package/dist/tui/config.js +129 -0
- package/dist/tui/config.js.map +1 -0
- package/dist/tui/deploy.js +114 -0
- package/dist/tui/deploy.js.map +1 -0
- package/dist/tui/engine.js +710 -0
- package/dist/tui/engine.js.map +1 -0
- package/dist/tui/notify.js +47 -0
- package/dist/tui/notify.js.map +1 -0
- package/dist/tui/panels.js +42 -0
- package/dist/tui/panels.js.map +1 -0
- package/dist/tui/templates.js +106 -0
- package/dist/tui/templates.js.map +1 -0
- package/dist/tui/theme.js +42 -0
- package/dist/tui/theme.js.map +1 -0
- package/dist/tui/validate.js +51 -0
- package/dist/tui/validate.js.map +1 -0
- package/{src/tui.tsx → dist/tui.js} +23 -33
- package/dist/tui.js.map +1 -0
- package/dist/types.js +19 -0
- package/dist/types.js.map +1 -0
- package/dist/web/oauth-anthropic.js +179 -0
- package/dist/web/oauth-anthropic.js.map +1 -0
- package/dist/web/session.js +274 -0
- package/dist/web/session.js.map +1 -0
- package/package.json +5 -4
- package/src/bakeoff.ts +0 -214
- package/src/build-state.ts +0 -47
- package/src/burndown.ts +0 -35
- package/src/calibration.ts +0 -88
- package/src/cost.ts +0 -43
- package/src/council.ts +0 -175
- package/src/demo.ts +0 -106
- package/src/estimate.ts +0 -111
- package/src/executor.ts +0 -169
- package/src/git.ts +0 -72
- package/src/intake.ts +0 -125
- package/src/models.ts +0 -175
- package/src/narrate.ts +0 -87
- package/src/openrouter.ts +0 -119
- package/src/orchestrator.ts +0 -310
- package/src/pm.ts +0 -302
- package/src/preview.ts +0 -206
- package/src/registry-store.ts +0 -41
- package/src/registry.ts +0 -132
- package/src/research.ts +0 -123
- package/src/retro.ts +0 -99
- package/src/roles.ts +0 -401
- package/src/router.ts +0 -120
- package/src/run-bakeoff.ts +0 -77
- package/src/run-build.ts +0 -203
- package/src/run-web.ts +0 -87
- package/src/scout.ts +0 -121
- package/src/session-cost.ts +0 -17
- package/src/stack.ts +0 -46
- package/src/tui/App.tsx +0 -1760
- package/src/tui/BakeOff.tsx +0 -190
- package/src/tui/BoardEditor.tsx +0 -260
- package/src/tui/EditableBoard.tsx +0 -179
- package/src/tui/Frame.tsx +0 -142
- package/src/tui/Intake.tsx +0 -111
- package/src/tui/Kanban.tsx +0 -158
- package/src/tui/Settings.tsx +0 -513
- package/src/tui/StackPick.tsx +0 -79
- package/src/tui/WebAccounts.tsx +0 -197
- package/src/tui/components.tsx +0 -340
- package/src/tui/config.ts +0 -150
- package/src/tui/deploy.ts +0 -137
- package/src/tui/engine.ts +0 -749
- package/src/tui/notify.ts +0 -21
- package/src/tui/panels.tsx +0 -89
- package/src/tui/templates.ts +0 -119
- package/src/tui/theme.ts +0 -44
- package/src/tui/validate.ts +0 -53
- package/src/types.ts +0 -208
- package/src/web/oauth-anthropic.ts +0 -206
- package/src/web/session.ts +0 -299
package/dist/cli.js
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
// Headless CLI — `projectinator <command>`. Same engine as the cockpit (engine.ts),
|
|
2
|
+
// same workspace root, so builds started here show up in the TUI's project list.
|
|
3
|
+
//
|
|
4
|
+
// doctor check Node, keys, Chromium, Pi catalog, git
|
|
5
|
+
// build "<idea>" [...] plan + build without the TUI
|
|
6
|
+
// projects list past builds
|
|
7
|
+
// models the roster as it will actually run, with prices
|
|
8
|
+
//
|
|
9
|
+
// The launcher (bin/projectinator.mjs) handles --version/--help itself and only
|
|
10
|
+
// spawns this file for a real command, so those stay instant.
|
|
11
|
+
import { createInterface } from "node:readline";
|
|
12
|
+
import { spawnSync } from "node:child_process";
|
|
13
|
+
import { accessSync, constants, mkdirSync } from "node:fs";
|
|
14
|
+
import { homedir } from "node:os";
|
|
15
|
+
import { join } from "node:path";
|
|
16
|
+
import { MODELS, getModel } from "./models.js";
|
|
17
|
+
import { REGISTRY } from "./registry.js";
|
|
18
|
+
import { piRuntime, resolvePiModel } from "./executor.js";
|
|
19
|
+
import { chromiumAvailable, CHROMIUM_INSTALL_HINT } from "./preview.js";
|
|
20
|
+
import { applyKeysToEnv, getPrefs, getWebhookUrl, loadConfig, ENV_VAR } from "./tui/config.js";
|
|
21
|
+
import { postWebhook } from "./tui/notify.js";
|
|
22
|
+
import { availableProviders, effectiveRoster, listProjects, planBuild, startBuild, PROVIDER_LABEL, } from "./tui/engine.js";
|
|
23
|
+
const NODE_MIN = "22.19.0";
|
|
24
|
+
// `projectinator projects | head` closes our stdout early; that's not an error.
|
|
25
|
+
process.stdout.on("error", (e) => { if (e.code === "EPIPE")
|
|
26
|
+
process.exit(0); throw e; });
|
|
27
|
+
const money = (n) => `$${n.toFixed(2)}`;
|
|
28
|
+
export function parseArgv(args) {
|
|
29
|
+
const out = { positional: [], flags: {} };
|
|
30
|
+
for (let i = 0; i < args.length; i++) {
|
|
31
|
+
const a = args[i];
|
|
32
|
+
if (!a.startsWith("--")) {
|
|
33
|
+
out.positional.push(a);
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const eq = a.indexOf("=");
|
|
37
|
+
if (eq > 0) {
|
|
38
|
+
out.flags[a.slice(2, eq)] = a.slice(eq + 1);
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const next = args[i + 1];
|
|
42
|
+
if (next !== undefined && !next.startsWith("--")) {
|
|
43
|
+
out.flags[a.slice(2)] = next;
|
|
44
|
+
i++;
|
|
45
|
+
}
|
|
46
|
+
else
|
|
47
|
+
out.flags[a.slice(2)] = true;
|
|
48
|
+
}
|
|
49
|
+
return out;
|
|
50
|
+
}
|
|
51
|
+
function num(v, fallback) {
|
|
52
|
+
if (v === undefined || v === true)
|
|
53
|
+
return fallback;
|
|
54
|
+
const n = parseFloat(v);
|
|
55
|
+
return Number.isFinite(n) ? n : fallback;
|
|
56
|
+
}
|
|
57
|
+
export function semverGte(a, b) {
|
|
58
|
+
const pa = a.split(".").map(Number);
|
|
59
|
+
const pb = b.split(".").map(Number);
|
|
60
|
+
for (let i = 0; i < 3; i++) {
|
|
61
|
+
if ((pa[i] ?? 0) > (pb[i] ?? 0))
|
|
62
|
+
return true;
|
|
63
|
+
if ((pa[i] ?? 0) < (pb[i] ?? 0))
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
async function doctor() {
|
|
69
|
+
const checks = [];
|
|
70
|
+
const node = process.versions.node;
|
|
71
|
+
checks.push({ label: "Node", ok: semverGte(node, NODE_MIN), detail: `v${node} (need ≥ ${NODE_MIN})`, fatal: true });
|
|
72
|
+
const cfg = loadConfig();
|
|
73
|
+
const providers = availableProviders();
|
|
74
|
+
for (const p of Object.keys(ENV_VAR)) {
|
|
75
|
+
const has = providers.includes(p);
|
|
76
|
+
const src = cfg.keys[p] ? "~/.projectinator/config.json" : has ? "env" : "";
|
|
77
|
+
checks.push({ label: `Key: ${PROVIDER_LABEL[p]}`, ok: has, detail: has ? `set (${src})` : `not set — Settings → API keys, or export ${ENV_VAR[p]}` });
|
|
78
|
+
}
|
|
79
|
+
if (providers.length === 0)
|
|
80
|
+
checks.push({ label: "Any provider key", ok: false, detail: "no keys at all — nothing can run", fatal: true });
|
|
81
|
+
try {
|
|
82
|
+
const runtime = await piRuntime();
|
|
83
|
+
const bad = [];
|
|
84
|
+
for (const e of REGISTRY)
|
|
85
|
+
for (const b of ["api", "web"]) {
|
|
86
|
+
try {
|
|
87
|
+
resolvePiModel(runtime, e.byBackend[b].provider, e.byBackend[b].model);
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
bad.push(`${e.capability}/${e.tier}/${b}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
checks.push({ label: "Pi model catalog", ok: bad.length === 0, detail: bad.length ? `unresolved: ${bad.join(", ")}` : `${Object.keys(MODELS).length} models priced, every registry pick resolves`, fatal: true });
|
|
94
|
+
}
|
|
95
|
+
catch (e) {
|
|
96
|
+
checks.push({ label: "Pi model catalog", ok: false, detail: e instanceof Error ? e.message : String(e), fatal: true });
|
|
97
|
+
}
|
|
98
|
+
const chromium = await chromiumAvailable();
|
|
99
|
+
checks.push({ label: "Headless Chromium", ok: chromium, detail: chromium ? "installed — tester runs the app" : `missing — tests will be code-reading only (PASS*); ${CHROMIUM_INSTALL_HINT}` });
|
|
100
|
+
const git = spawnSync("git", ["--version"], { encoding: "utf8" });
|
|
101
|
+
checks.push({ label: "git", ok: git.status === 0, detail: git.status === 0 ? git.stdout.trim() : "not found — builds won't be versioned (undo/history disabled)" });
|
|
102
|
+
const home = join(homedir(), ".projectinator");
|
|
103
|
+
try {
|
|
104
|
+
mkdirSync(home, { recursive: true });
|
|
105
|
+
accessSync(home, constants.W_OK);
|
|
106
|
+
checks.push({ label: "Data dir", ok: true, detail: home });
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
checks.push({ label: "Data dir", ok: false, detail: `${home} not writable`, fatal: true });
|
|
110
|
+
}
|
|
111
|
+
const prefs = getPrefs();
|
|
112
|
+
checks.push({ label: "Prefs", ok: true, detail: `budget cap ${money(prefs.budgetCapUSD)} · ${prefs.concurrency} at once · task limits ${prefs.taskTimeoutMin || "∞"} min / ${prefs.taskCostCapUSD ? money(prefs.taskCostCapUSD) : "∞"}` });
|
|
113
|
+
console.log("\n projectinator doctor\n");
|
|
114
|
+
for (const c of checks)
|
|
115
|
+
console.log(` ${c.ok ? "✓" : c.fatal ? "✗" : "!"} ${c.label.padEnd(22)} ${c.detail}`);
|
|
116
|
+
const fatal = checks.filter((c) => !c.ok && c.fatal);
|
|
117
|
+
const warn = checks.filter((c) => !c.ok && !c.fatal);
|
|
118
|
+
console.log(`\n ${fatal.length ? `${fatal.length} blocking problem${fatal.length === 1 ? "" : "s"}` : "Ready"}${warn.length ? ` · ${warn.length} warning${warn.length === 1 ? "" : "s"}` : ""}\n`);
|
|
119
|
+
return fatal.length ? 1 : 0;
|
|
120
|
+
}
|
|
121
|
+
// ---- projects ----
|
|
122
|
+
function projects() {
|
|
123
|
+
const list = listProjects();
|
|
124
|
+
if (!list.length) {
|
|
125
|
+
console.log("\n No projects yet. Run `projectinator` or `projectinator build \"an idea\"`.\n");
|
|
126
|
+
return 0;
|
|
127
|
+
}
|
|
128
|
+
console.log("");
|
|
129
|
+
for (const p of list) {
|
|
130
|
+
const done = p.state.outcomes.filter((o) => !o.error).length;
|
|
131
|
+
const mark = p.status === "complete" ? "✓" : p.status === "halted" ? "⚠" : "…";
|
|
132
|
+
console.log(` ${mark} ${p.slug.padEnd(40)} ${p.status.padEnd(9)} ${money(p.totalCost).padStart(8)} ${done}/${p.taskCount} tasks`);
|
|
133
|
+
console.log(` ${p.idea.slice(0, 90)}${p.idea.length > 90 ? "…" : ""}`);
|
|
134
|
+
}
|
|
135
|
+
console.log(`\n ${list.length} project${list.length === 1 ? "" : "s"} · ${money(list.reduce((a, p) => a + p.totalCost, 0))} all time · ${join(homedir(), "…")}\n`);
|
|
136
|
+
return 0;
|
|
137
|
+
}
|
|
138
|
+
// ---- models ----
|
|
139
|
+
function models() {
|
|
140
|
+
const providers = availableProviders();
|
|
141
|
+
console.log(`\n Roster as it will run now${providers.length ? ` (keys: ${providers.join(", ")})` : " (no keys — best-of-breed picks shown)"}\n`);
|
|
142
|
+
for (const r of effectiveRoster()) {
|
|
143
|
+
const m = r.model ? getModel(r.model) : undefined;
|
|
144
|
+
const price = m ? `$${m.cost.input}/$${m.cost.output} per 1M` : "";
|
|
145
|
+
console.log(` ${r.label.padEnd(18)} ${(r.model ?? "—").padEnd(28)} ${(r.provider ?? "").padEnd(11)} ${price}`);
|
|
146
|
+
}
|
|
147
|
+
console.log("\n Change in the app: Settings → Models. Prices are from Pi's catalog; actual cost is measured per run.\n");
|
|
148
|
+
return 0;
|
|
149
|
+
}
|
|
150
|
+
// ---- build ----
|
|
151
|
+
function ask(question) {
|
|
152
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
153
|
+
const { promise, resolve } = Promise.withResolvers();
|
|
154
|
+
rl.question(question, (a) => { rl.close(); resolve(a.trim()); });
|
|
155
|
+
return promise;
|
|
156
|
+
}
|
|
157
|
+
async function build(argv) {
|
|
158
|
+
const idea = argv.positional.join(" ").trim();
|
|
159
|
+
const json = argv.flags.json === true;
|
|
160
|
+
const yes = json || argv.flags.yes === true || argv.flags.y === true;
|
|
161
|
+
const dry = argv.flags["dry-run"] === true;
|
|
162
|
+
const emit = (o) => { if (json)
|
|
163
|
+
process.stdout.write(JSON.stringify(o) + "\n"); };
|
|
164
|
+
const say = (s) => { if (!json)
|
|
165
|
+
console.log(s); };
|
|
166
|
+
if (!idea) {
|
|
167
|
+
console.error(" build: give an idea, e.g. projectinator build \"a tip calculator\"");
|
|
168
|
+
return 2;
|
|
169
|
+
}
|
|
170
|
+
let providers = availableProviders();
|
|
171
|
+
const lock = argv.flags.provider;
|
|
172
|
+
if (typeof lock === "string") {
|
|
173
|
+
if (!(lock in PROVIDER_LABEL)) {
|
|
174
|
+
console.error(` build: unknown provider "${lock}" (anthropic | openai | google | openrouter)`);
|
|
175
|
+
return 2;
|
|
176
|
+
}
|
|
177
|
+
if (!providers.includes(lock)) {
|
|
178
|
+
console.error(` build: no key for ${lock} — export ${ENV_VAR[lock]} or set it in the app`);
|
|
179
|
+
return 1;
|
|
180
|
+
}
|
|
181
|
+
providers = [lock];
|
|
182
|
+
}
|
|
183
|
+
if (!providers.length) {
|
|
184
|
+
console.error(" build: no API key found. Run `projectinator doctor`.");
|
|
185
|
+
return 1;
|
|
186
|
+
}
|
|
187
|
+
const prefs = getPrefs();
|
|
188
|
+
const budget = num(argv.flags.budget, prefs.budgetCapUSD);
|
|
189
|
+
const concurrency = Math.max(1, Math.floor(num(argv.flags.concurrency, prefs.concurrency)));
|
|
190
|
+
const taskLimits = {
|
|
191
|
+
timeoutMs: num(argv.flags["task-timeout"], prefs.taskTimeoutMin) * 60_000,
|
|
192
|
+
costCapUSD: num(argv.flags["task-cap"], prefs.taskCostCapUSD),
|
|
193
|
+
};
|
|
194
|
+
say(`\n Planning with the PM (${providers.join("/")})…`);
|
|
195
|
+
const plan = await planBuild(idea, providers);
|
|
196
|
+
emit({ event: "plan", provider: plan.provider, modelId: plan.modelId, estCost: plan.estCost, tasks: plan.tasks });
|
|
197
|
+
say(`\n ${plan.tasks.length} tasks · estimated ${money(plan.estCost)} · cap ${money(budget)}${plan.lock ? ` · locked to ${plan.lock}` : ""}\n`);
|
|
198
|
+
for (const t of plan.tasks) {
|
|
199
|
+
const dep = t.dependsOn?.length ? ` ← ${t.dependsOn.join(", ")}` : "";
|
|
200
|
+
say(` ${t.id.padEnd(6)} ${t.capability.padEnd(7)} ${t.difficulty.padEnd(8)} ${t.title}${dep}`);
|
|
201
|
+
}
|
|
202
|
+
if (plan.estCost > budget)
|
|
203
|
+
say(`\n ⚠ Estimate exceeds the cap — the build may halt partway.`);
|
|
204
|
+
if (dry) {
|
|
205
|
+
say("\n Dry run — nothing built (the PM call above was the only spend).\n");
|
|
206
|
+
return 0;
|
|
207
|
+
}
|
|
208
|
+
if (!yes) {
|
|
209
|
+
const a = await ask(`\n Build it for ~${money(plan.estCost)}? [y/N] `);
|
|
210
|
+
if (!/^y(es)?$/i.test(a)) {
|
|
211
|
+
say(" Cancelled.\n");
|
|
212
|
+
return 0;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
const onEvent = (e) => {
|
|
216
|
+
emit({ event: e.type, ...e });
|
|
217
|
+
if (json)
|
|
218
|
+
return;
|
|
219
|
+
if (e.type === "task_start")
|
|
220
|
+
console.log(` ▶ ${e.task.id} [${e.task.capability}] → ${e.provider}/${e.modelId}${e.round ? ` (round ${e.round})` : ""}`);
|
|
221
|
+
else if (e.type === "task_done")
|
|
222
|
+
console.log(` ✓ ${e.outcome.taskId} ${money(e.outcome.cost)} running ${money(e.runningTotal)}${e.outcome.verdict ? ` ${e.outcome.verdict.passed ? (e.outcome.verdict.runtimeChecked || e.outcome.capability !== "test" ? "PASS" : "PASS* (app not executed)") : "FAIL"}` : ""}`);
|
|
223
|
+
else if (e.type === "task_failed")
|
|
224
|
+
console.log(` ⛔ ${e.outcome.taskId} aborted: ${e.outcome.error} — billed ${money(e.outcome.cost)}`);
|
|
225
|
+
else if (e.type === "task_skipped")
|
|
226
|
+
console.log(` · ${e.taskId} skipped`);
|
|
227
|
+
else if (e.type === "test_failed")
|
|
228
|
+
console.log(` ✗ ${e.taskId} failed (${e.bugs} bugs) — round ${e.round}`);
|
|
229
|
+
else if (e.type === "retry_dev")
|
|
230
|
+
console.log(` ↻ re-running ${e.taskId} to fix ${e.forTest}`);
|
|
231
|
+
else if (e.type === "budget_halt")
|
|
232
|
+
console.log(` ⚠ budget halt at ${money(e.runningTotal)} (cap ${money(e.cap)})`);
|
|
233
|
+
else if (e.type === "cycle_or_error")
|
|
234
|
+
console.log(` ✗ ${e.message}`);
|
|
235
|
+
};
|
|
236
|
+
say(`\n Building…\n`);
|
|
237
|
+
const handle = startBuild(idea, plan, { concurrency, budgetCapUSD: budget, taskLimits, onEvent, mode: "auto" });
|
|
238
|
+
const r = await handle.promise;
|
|
239
|
+
emit({ event: "done", halted: r.halted, haltReason: r.haltReason, totalCost: r.totalCost, files: r.files, workspace: handle.workspace });
|
|
240
|
+
const hook = getWebhookUrl();
|
|
241
|
+
if (hook) {
|
|
242
|
+
const ok = await postWebhook(hook, { event: "build.finished", status: r.halted ? "halted" : "complete", haltReason: r.haltReason, idea, totalCost: r.totalCost, files: r.files, workspace: handle.workspace, at: new Date().toISOString() });
|
|
243
|
+
emit({ event: "webhook", url: hook, ok });
|
|
244
|
+
if (!ok)
|
|
245
|
+
say(` (webhook ${hook} did not accept the summary)`);
|
|
246
|
+
}
|
|
247
|
+
say(`\n ${r.halted ? `⚠ Halted (${r.haltReason ?? "?"})` : "✓ Complete"} · ${money(r.totalCost)} · ${r.files.length} file${r.files.length === 1 ? "" : "s"}`);
|
|
248
|
+
say(` ${handle.workspace}\n`);
|
|
249
|
+
return r.halted ? 3 : 0;
|
|
250
|
+
}
|
|
251
|
+
// ---- main ----
|
|
252
|
+
const USAGE = `Usage: projectinator <command> [options]
|
|
253
|
+
|
|
254
|
+
doctor check Node, API keys, Chromium, Pi catalog, git
|
|
255
|
+
build "<idea>" [options] plan + build headless (same workspace as the app)
|
|
256
|
+
--dry-run plan and estimate only (spends one PM call)
|
|
257
|
+
--yes, -y don't ask before building
|
|
258
|
+
--json NDJSON events on stdout (implies --yes)
|
|
259
|
+
--budget <usd> cap for this build (default: your prefs)
|
|
260
|
+
--provider <name> anthropic|openai|google|openrouter (default: prefs / keys)
|
|
261
|
+
--concurrency <n> tasks at once (default: your prefs)
|
|
262
|
+
--task-cap <usd> per-task cost ceiling (default: your prefs; 0 = off)
|
|
263
|
+
--task-timeout <min> per-task timeout (default: your prefs; 0 = off)
|
|
264
|
+
projects list past builds with status and cost
|
|
265
|
+
models the roster as it will run, with prices
|
|
266
|
+
|
|
267
|
+
Exit codes: 0 ok · 1 environment problem · 2 bad usage · 3 build halted`;
|
|
268
|
+
export async function main(args) {
|
|
269
|
+
applyKeysToEnv();
|
|
270
|
+
const argv = parseArgv(args);
|
|
271
|
+
const cmd = argv.positional.shift();
|
|
272
|
+
switch (cmd) {
|
|
273
|
+
case "doctor": return doctor();
|
|
274
|
+
case "projects": return projects();
|
|
275
|
+
case "models": return models();
|
|
276
|
+
case "build": return build(argv);
|
|
277
|
+
case undefined:
|
|
278
|
+
case "help":
|
|
279
|
+
console.log(USAGE);
|
|
280
|
+
return cmd ? 0 : 2;
|
|
281
|
+
default:
|
|
282
|
+
console.error(`projectinator: unknown command "${cmd}".\n\n${USAGE}`);
|
|
283
|
+
return 2;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
if (process.argv[1] && import.meta.url === new URL(process.argv[1], "file://").href) {
|
|
287
|
+
process.exitCode = await main(process.argv.slice(2));
|
|
288
|
+
}
|
|
289
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/cost.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// Cost estimation. Pure math over a token estimate + a model's price block.
|
|
2
|
+
const PER_MILLION = 1_000_000;
|
|
3
|
+
/** Resolve the applicable input/output/cache rates, honoring volume tiers.
|
|
4
|
+
* Highest matching `inputTokensAbove` threshold wins (Pi semantics). */
|
|
5
|
+
function ratesFor(model, inputTokens) {
|
|
6
|
+
const base = model.cost;
|
|
7
|
+
let rate = { input: base.input, output: base.output, cacheRead: base.cacheRead ?? base.input };
|
|
8
|
+
for (const tier of base.tiers ?? []) {
|
|
9
|
+
if (inputTokens > tier.inputTokensAbove) {
|
|
10
|
+
rate = {
|
|
11
|
+
input: tier.input,
|
|
12
|
+
output: tier.output,
|
|
13
|
+
cacheRead: tier.cacheRead ?? tier.input,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return rate;
|
|
18
|
+
}
|
|
19
|
+
/** Estimate USD cost for one task on a given model.
|
|
20
|
+
* A fraction of input can be served from cache at the cheaper cacheRead rate.
|
|
21
|
+
* Kept to 4 decimals, not cents: a backlog of sub-cent tasks would otherwise
|
|
22
|
+
* estimate to $0.00 and under-reserve budget in the parallel scheduler. */
|
|
23
|
+
export function estimateCost(est, model) {
|
|
24
|
+
const cachedFraction = clamp01(est.cachedInputFraction ?? 0);
|
|
25
|
+
const rate = ratesFor(model, est.input);
|
|
26
|
+
const freshInput = est.input * (1 - cachedFraction);
|
|
27
|
+
const cachedInput = est.input * cachedFraction;
|
|
28
|
+
const inputCost = (freshInput / PER_MILLION) * rate.input + (cachedInput / PER_MILLION) * rate.cacheRead;
|
|
29
|
+
const outputCost = (est.output / PER_MILLION) * rate.output;
|
|
30
|
+
return Math.round((inputCost + outputCost) * 10_000) / 10_000;
|
|
31
|
+
}
|
|
32
|
+
function clamp01(n) {
|
|
33
|
+
return Math.max(0, Math.min(1, n));
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=cost.js.map
|
package/dist/cost.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cost.js","sourceRoot":"","sources":["../src/cost.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAI5E,MAAM,WAAW,GAAG,SAAS,CAAC;AAE9B;yEACyE;AACzE,SAAS,QAAQ,CAAC,KAAY,EAAE,WAAmB;IACjD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IACxB,IAAI,IAAI,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;IAC/F,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;QACpC,IAAI,WAAW,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxC,IAAI,GAAG;gBACL,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,KAAK;aACxC,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;4EAG4E;AAC5E,MAAM,UAAU,YAAY,CAAC,GAAkB,EAAE,KAAY;IAC3D,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,CAAC,CAAC,CAAC;IAC7D,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;IAExC,MAAM,UAAU,GAAG,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC;IACpD,MAAM,WAAW,GAAG,GAAG,CAAC,KAAK,GAAG,cAAc,CAAC;IAE/C,MAAM,SAAS,GAAG,CAAC,UAAU,GAAG,WAAW,CAAC,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,WAAW,GAAG,WAAW,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC;IACzG,MAAM,UAAU,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,WAAW,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;IAE5D,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,GAAG,UAAU,CAAC,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC;AAChE,CAAC;AAED,SAAS,OAAO,CAAC,CAAS;IACxB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACrC,CAAC"}
|
package/dist/council.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
// Council planning (opt-in "deep plan"). Three perspectives propose epics from
|
|
2
|
+
// different lenses in parallel, then a synthesizer merges them into one ordered
|
|
3
|
+
// epic list. The user approves the epics; expansion into tasks happens after,
|
|
4
|
+
// via the normal decomposer seeded with these epics.
|
|
5
|
+
import { createAgentSession, defineTool, } from "@earendil-works/pi-coding-agent";
|
|
6
|
+
import { Type } from "typebox";
|
|
7
|
+
import { findEntry } from "./registry.js";
|
|
8
|
+
import { piRuntime, resolvePiModel } from "./executor.js";
|
|
9
|
+
import { addSessionCost } from "./session-cost.js";
|
|
10
|
+
const EpicsSchema = Type.Object({
|
|
11
|
+
epics: Type.Array(Type.Object({ name: Type.String(), rationale: Type.String({ description: "one line: why this epic exists" }) }, { additionalProperties: true })),
|
|
12
|
+
}, { additionalProperties: true });
|
|
13
|
+
function buildEpicsTool(toolName) {
|
|
14
|
+
let captured;
|
|
15
|
+
const tool = defineTool({
|
|
16
|
+
name: toolName,
|
|
17
|
+
label: "Submit Epics",
|
|
18
|
+
description: "Submit the epic list. Call exactly once.",
|
|
19
|
+
parameters: EpicsSchema,
|
|
20
|
+
execute: async (_id, params) => {
|
|
21
|
+
captured = params;
|
|
22
|
+
return { content: [{ type: "text", text: `Got ${params.epics.length} epics.` }], details: {} };
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
return { tool, get: () => captured };
|
|
26
|
+
}
|
|
27
|
+
function lastAssistantText(session) {
|
|
28
|
+
const msgs = session.messages;
|
|
29
|
+
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
30
|
+
const m = msgs[i];
|
|
31
|
+
if (m?.role !== "assistant")
|
|
32
|
+
continue;
|
|
33
|
+
const c = m.content;
|
|
34
|
+
if (typeof c === "string")
|
|
35
|
+
return c;
|
|
36
|
+
if (Array.isArray(c))
|
|
37
|
+
return c.map((p) => (p && typeof p === "object" && "text" in p ? String(p.text) : "")).join("");
|
|
38
|
+
}
|
|
39
|
+
return "";
|
|
40
|
+
}
|
|
41
|
+
async function runEpicAgent(idea, system, toolName, ctx) {
|
|
42
|
+
const runtime = await piRuntime();
|
|
43
|
+
const { entry } = findEntry("plan", "mid");
|
|
44
|
+
const pick = ctx.modelOverride ?? entry.byBackend[ctx.backend];
|
|
45
|
+
try {
|
|
46
|
+
const model = resolvePiModel(runtime, pick.provider, pick.model);
|
|
47
|
+
const { tool, get } = buildEpicsTool(toolName);
|
|
48
|
+
const { session } = await createAgentSession({
|
|
49
|
+
model,
|
|
50
|
+
modelRuntime: runtime,
|
|
51
|
+
thinkingLevel: "low",
|
|
52
|
+
noTools: "all",
|
|
53
|
+
customTools: [tool],
|
|
54
|
+
tools: [toolName],
|
|
55
|
+
});
|
|
56
|
+
try {
|
|
57
|
+
await session.prompt(`${system}\n\n--- REQUEST ---\n${idea}`);
|
|
58
|
+
let raw = get();
|
|
59
|
+
if (!raw) {
|
|
60
|
+
await session.prompt(`Call ${toolName} now.`);
|
|
61
|
+
raw = get();
|
|
62
|
+
}
|
|
63
|
+
addSessionCost(session.getSessionStats().cost);
|
|
64
|
+
return (raw?.epics ?? [])
|
|
65
|
+
.map((e) => ({ name: String(e.name ?? "").trim(), rationale: String(e.rationale ?? "").trim() }))
|
|
66
|
+
.filter((e) => e.name);
|
|
67
|
+
}
|
|
68
|
+
finally {
|
|
69
|
+
session.dispose();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const LENSES = [
|
|
77
|
+
{
|
|
78
|
+
key: "architect",
|
|
79
|
+
system: "You are the ARCHITECT on a planning council. Propose the EPICS (big areas of work) for this build " +
|
|
80
|
+
"from a TECHNICAL structure lens — components, data, integration, scaffolding. 3-6 epics, each a short " +
|
|
81
|
+
"name + one-line rationale. Call submit_epics_architect once.",
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
key: "product",
|
|
85
|
+
system: "You are the PRODUCT lead on a planning council. Propose the EPICS from a USER-VALUE lens — the features " +
|
|
86
|
+
"and flows a user needs, in priority order. 3-6 epics, each a short name + one-line rationale. Call " +
|
|
87
|
+
"submit_epics_product once.",
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
key: "risk",
|
|
91
|
+
system: "You are the RISK/QA lead on a planning council. Propose the EPICS from a WHAT-COULD-GO-WRONG lens — " +
|
|
92
|
+
"validation, edge cases, error/empty states, testing, and anything easy to forget. 3-6 epics, each a " +
|
|
93
|
+
"short name + one-line rationale. Call submit_epics_risk once.",
|
|
94
|
+
},
|
|
95
|
+
];
|
|
96
|
+
const SYNTH_SYSTEM = [
|
|
97
|
+
"You are the PROJECT MANAGER chairing a planning council. Three leads proposed epics from different lenses",
|
|
98
|
+
"(architect, product, risk). Merge them into ONE clean, ordered epic list for the build: dedupe overlaps,",
|
|
99
|
+
"keep what matters, drop noise, and order them the way the work should proceed. Aim for 3-7 epics. Each epic:",
|
|
100
|
+
"a short name + a one-line rationale that folds in the strongest point(s) from the leads. Call submit_epics once.",
|
|
101
|
+
].join("\n");
|
|
102
|
+
/** Run the council: 3 lenses in parallel, then synthesize. Falls back to a single
|
|
103
|
+
* lens's epics if synthesis fails; empty only if everything fails. */
|
|
104
|
+
export async function councilEpics(idea, ctx) {
|
|
105
|
+
const proposalsRaw = await Promise.all(LENSES.map((l) => runEpicAgent(idea, l.system, `submit_epics_${l.key}`, ctx).then((epics) => ({ lens: l.key, epics }))));
|
|
106
|
+
const proposals = proposalsRaw.filter((p) => p.epics.length);
|
|
107
|
+
if (!proposals.length)
|
|
108
|
+
return { epics: [], proposals: [] };
|
|
109
|
+
// Synthesize.
|
|
110
|
+
const runtime = await piRuntime();
|
|
111
|
+
const { entry } = findEntry("plan", "mid");
|
|
112
|
+
const pick = ctx.modelOverride ?? entry.byBackend[ctx.backend];
|
|
113
|
+
try {
|
|
114
|
+
const model = resolvePiModel(runtime, pick.provider, pick.model);
|
|
115
|
+
const { tool, get } = buildEpicsTool("submit_epics");
|
|
116
|
+
const { session } = await createAgentSession({
|
|
117
|
+
model, modelRuntime: runtime, thinkingLevel: "low",
|
|
118
|
+
noTools: "all", customTools: [tool], tools: ["submit_epics"],
|
|
119
|
+
});
|
|
120
|
+
try {
|
|
121
|
+
const block = proposals
|
|
122
|
+
.map((p) => `### ${p.lens}\n${p.epics.map((e) => `- ${e.name}: ${e.rationale}`).join("\n")}`)
|
|
123
|
+
.join("\n\n");
|
|
124
|
+
await session.prompt(`${SYNTH_SYSTEM}\n\n--- REQUEST ---\n${idea}\n\n--- LEAD PROPOSALS ---\n${block}`);
|
|
125
|
+
let raw = get();
|
|
126
|
+
if (!raw) {
|
|
127
|
+
await session.prompt("Call submit_epics now.");
|
|
128
|
+
raw = get();
|
|
129
|
+
}
|
|
130
|
+
addSessionCost(session.getSessionStats().cost);
|
|
131
|
+
const epics = (raw?.epics ?? [])
|
|
132
|
+
.map((e) => ({ name: String(e.name ?? "").trim(), rationale: String(e.rationale ?? "").trim() }))
|
|
133
|
+
.filter((e) => e.name);
|
|
134
|
+
// Fall back to the largest single proposal if synthesis produced nothing.
|
|
135
|
+
const best = proposals.slice().sort((a, b) => b.epics.length - a.epics.length)[0].epics;
|
|
136
|
+
return { epics: epics.length ? epics : best, proposals };
|
|
137
|
+
}
|
|
138
|
+
finally {
|
|
139
|
+
session.dispose();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
const best = proposals.slice().sort((a, b) => b.epics.length - a.epics.length)[0].epics;
|
|
144
|
+
return { epics: best, proposals };
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=council.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"council.js","sourceRoot":"","sources":["../src/council.ts"],"names":[],"mappings":"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"}
|
package/dist/demo.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// Phase 1 demo — proves the brain before wiring any agents.
|
|
2
|
+
// Feeds a fake "landing page + contact form" backlog through the router and prints
|
|
3
|
+
// backend, model, and estimated cost per task, plus the total.
|
|
4
|
+
//
|
|
5
|
+
// Run: npm run demo (cost-first / web backend)
|
|
6
|
+
// npm run demo -- api (force API backend)
|
|
7
|
+
// npm run demo -- ask (interactive-style; here stubbed to demonstrate)
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
9
|
+
import { dirname, join } from "node:path";
|
|
10
|
+
import { DEFAULT_POLICY, routeBacklog } from "./router.js";
|
|
11
|
+
import { loadRegistry, OVERRIDES_FILENAME } from "./registry-store.js";
|
|
12
|
+
const BACKLOG = [
|
|
13
|
+
{
|
|
14
|
+
id: "T-01", epic: "E-1", story: "S-1", title: "Break brief into backlog",
|
|
15
|
+
capability: "plan", difficulty: "medium",
|
|
16
|
+
estTokens: { input: 10_000, output: 5_000 },
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
id: "T-02", epic: "E-1", story: "S-2", title: "Design hero + layout system",
|
|
20
|
+
capability: "design", difficulty: "high",
|
|
21
|
+
estTokens: { input: 20_000, output: 15_000 },
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: "T-03", epic: "E-2", story: "S-3", title: "Build page + contact form",
|
|
25
|
+
capability: "code", difficulty: "high", dependsOn: ["T-02"],
|
|
26
|
+
estTokens: { input: 400_000, output: 60_000, cachedInputFraction: 0.6 },
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: "T-04", epic: "E-2", story: "S-4", title: "Wire form handler",
|
|
30
|
+
capability: "code", difficulty: "low", dependsOn: ["T-03"],
|
|
31
|
+
estTokens: { input: 30_000, output: 8_000, cachedInputFraction: 0.5 },
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: "T-05", epic: "E-3", story: "S-5", title: "Review + test the build",
|
|
35
|
+
capability: "test", difficulty: "trivial", dependsOn: ["T-03", "T-04"],
|
|
36
|
+
estTokens: { input: 80_000, output: 15_000 },
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: "T-06", epic: "E-3", story: "S-6", title: "Run it, drive the CI/preview",
|
|
40
|
+
capability: "ops", difficulty: "high", dependsOn: ["T-04"],
|
|
41
|
+
estTokens: { input: 100_000, output: 20_000, cachedInputFraction: 0.4 },
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
const arg = process.argv[2];
|
|
45
|
+
const policy = { ...DEFAULT_POLICY };
|
|
46
|
+
if (arg === "api")
|
|
47
|
+
policy.backendMode = "api";
|
|
48
|
+
if (arg === "web")
|
|
49
|
+
policy.backendMode = "web";
|
|
50
|
+
// For "ask" mode we'd wire real prompts; here we stub a chooser so the demo runs headless.
|
|
51
|
+
const prompts = arg === "ask"
|
|
52
|
+
? {
|
|
53
|
+
chooseBackend: () => "api",
|
|
54
|
+
chooseModel: (_t, _e, _b) => undefined, // accept defaults
|
|
55
|
+
}
|
|
56
|
+
: undefined;
|
|
57
|
+
if (arg === "ask")
|
|
58
|
+
policy.backendMode = "ask";
|
|
59
|
+
// Load the effective registry (seed + any Scout overrides), so applied Scout
|
|
60
|
+
// changes are reflected here.
|
|
61
|
+
const projectRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
62
|
+
const registry = loadRegistry(join(projectRoot, OVERRIDES_FILENAME));
|
|
63
|
+
const decisions = routeBacklog(BACKLOG, { policy, registry, prompts });
|
|
64
|
+
const pad = (s, n) => s.padEnd(n);
|
|
65
|
+
const money = (n) => `$${n.toFixed(2)}`;
|
|
66
|
+
console.log(`\n Projectinator — routing plan [backendMode=${policy.backendMode}, cap=${money(policy.budgetCapUSD)}]\n`);
|
|
67
|
+
console.log(" " +
|
|
68
|
+
pad("TASK", 7) + pad("CAPABILITY", 11) + pad("DIFF", 9) +
|
|
69
|
+
pad("BACKEND", 9) + pad("MODEL", 20) + pad("TIER", 6) + pad("COST", 9) + "RUNNING");
|
|
70
|
+
console.log(" " + "-".repeat(78));
|
|
71
|
+
for (const d of decisions) {
|
|
72
|
+
const task = BACKLOG.find((t) => t.id === d.taskId);
|
|
73
|
+
const flag = d.overCap ? " ⚠ OVER CAP" : "";
|
|
74
|
+
console.log(" " +
|
|
75
|
+
pad(d.taskId, 7) +
|
|
76
|
+
pad(task.capability, 11) +
|
|
77
|
+
pad(task.difficulty, 9) +
|
|
78
|
+
pad(d.backend, 9) +
|
|
79
|
+
pad(d.model.name, 20) +
|
|
80
|
+
pad(d.tier, 6) +
|
|
81
|
+
pad(money(d.cost), 9) +
|
|
82
|
+
money(d.runningTotal) +
|
|
83
|
+
flag);
|
|
84
|
+
}
|
|
85
|
+
const total = decisions.at(-1)?.runningTotal ?? 0;
|
|
86
|
+
console.log(" " + "-".repeat(78));
|
|
87
|
+
console.log(` TOTAL ESTIMATED: ${money(total)}\n`);
|
|
88
|
+
console.log(" Decision trail for T-03 (the developer task):");
|
|
89
|
+
for (const r of decisions.find((d) => d.taskId === "T-03").reasons) {
|
|
90
|
+
console.log(" · " + r);
|
|
91
|
+
}
|
|
92
|
+
console.log("");
|
|
93
|
+
//# sourceMappingURL=demo.js.map
|
package/dist/demo.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demo.js","sourceRoot":"","sources":["../src/demo.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,mFAAmF;AACnF,+DAA+D;AAC/D,EAAE;AACF,0DAA0D;AAC1D,oDAAoD;AACpD,iFAAiF;AAEjF,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEvE,MAAM,OAAO,GAAW;IACtB;QACE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,0BAA0B;QACxE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ;QACxC,SAAS,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE;KAC5C;IACD;QACE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,6BAA6B;QAC3E,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM;QACxC,SAAS,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;KAC7C;IACD;QACE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,2BAA2B;QACzE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,MAAM,CAAC;QAC3D,SAAS,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,mBAAmB,EAAE,GAAG,EAAE;KACxE;IACD;QACE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,mBAAmB;QACjE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,MAAM,CAAC;QAC1D,SAAS,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,EAAE,GAAG,EAAE;KACtE;IACD;QACE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,yBAAyB;QACvE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;QACtE,SAAS,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;KAC7C;IACD;QACE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,8BAA8B;QAC5E,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,MAAM,CAAC;QAC1D,SAAS,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,mBAAmB,EAAE,GAAG,EAAE;KACxE;CACF,CAAC;AAEF,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC5B,MAAM,MAAM,GAAkB,EAAE,GAAG,cAAc,EAAE,CAAC;AACpD,IAAI,GAAG,KAAK,KAAK;IAAE,MAAM,CAAC,WAAW,GAAG,KAAK,CAAC;AAC9C,IAAI,GAAG,KAAK,KAAK;IAAE,MAAM,CAAC,WAAW,GAAG,KAAK,CAAC;AAE9C,2FAA2F;AAC3F,MAAM,OAAO,GACX,GAAG,KAAK,KAAK;IACX,CAAC,CAAC;QACE,aAAa,EAAE,GAAG,EAAE,CAAC,KAAc;QACnC,WAAW,EAAE,CAAC,EAAQ,EAAE,EAAW,EAAE,EAAW,EAAE,EAAE,CAAC,SAAS,EAAE,kBAAkB;KACnF;IACH,CAAC,CAAC,SAAS,CAAC;AAChB,IAAI,GAAG,KAAK,KAAK;IAAE,MAAM,CAAC,WAAW,GAAG,KAAK,CAAC;AAE9C,6EAA6E;AAC7E,8BAA8B;AAC9B,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACrE,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC,CAAC;AAErE,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;AAEvE,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAClD,MAAM,KAAK,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;AAEhD,OAAO,CAAC,GAAG,CAAC,mDAAmD,MAAM,CAAC,WAAW,SAAS,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;AAC3H,OAAO,CAAC,GAAG,CACT,IAAI;IACF,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,YAAY,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IACvD,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,SAAS,CACrF,CAAC;AACF,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;AAEnC,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;IAC1B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,MAAM,CAAE,CAAC;IACrD,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7C,OAAO,CAAC,GAAG,CACT,IAAI;QACF,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QAChB,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;QACxB,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;QACvB,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QACjB,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QACrB,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACd,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACrB,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC;QACrB,IAAI,CACP,CAAC;AACJ,CAAC;AAED,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,YAAY,IAAI,CAAC,CAAC;AAClD,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;AACnC,OAAO,CAAC,GAAG,CAAC,sBAAsB,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAEpD,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;AAC/D,KAAK,MAAM,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAE,CAAC,OAAO,EAAE,CAAC;IACpE,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;AAC5B,CAAC;AACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC"}
|