aiki-cli 0.2.1 → 0.3.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/CHANGELOG.md +99 -7
- package/README.md +109 -30
- package/dist/bench/arms.js +10 -9
- package/dist/bench/harness.js +13 -10
- package/dist/bench/idea-lane-rotation.js +237 -0
- package/dist/bench/idea-v3-bench.js +506 -0
- package/dist/bench/idea-v3-rating.js +582 -0
- package/dist/bench/results.js +10 -3
- package/dist/bench/scoring/decision-insights.js +112 -0
- package/dist/bench/scoring/seeded-bugs.js +4 -0
- package/dist/cli/bench.js +180 -3
- package/dist/cli/doctor.js +56 -24
- package/dist/cli/index.js +32 -7
- package/dist/cli/resolve.js +7 -6
- package/dist/cli/resume.js +18 -0
- package/dist/cli/run.js +63 -8
- package/dist/cli/version.js +8 -0
- package/dist/council/view.js +378 -109
- package/dist/orchestration/calculations.js +97 -0
- package/dist/orchestration/context.js +37 -9
- package/dist/orchestration/decision-dossier.js +262 -0
- package/dist/orchestration/decision-graph.js +256 -0
- package/dist/orchestration/engine.js +5 -2
- package/dist/orchestration/evidence-pack.js +46 -0
- package/dist/orchestration/idea-lanes.js +20 -0
- package/dist/orchestration/jsonStage.js +72 -0
- package/dist/orchestration/legacy-idea-adapter.js +102 -0
- package/dist/orchestration/modes.js +33 -0
- package/dist/orchestration/preflight.js +183 -0
- package/dist/orchestration/quick-analysis.js +81 -0
- package/dist/orchestration/stages/cr-ladder.js +80 -0
- package/dist/orchestration/stages/s10-render.js +562 -150
- package/dist/orchestration/stages/s4-analyze.js +12 -7
- package/dist/orchestration/stages/s5-drift.js +9 -9
- package/dist/orchestration/stages/s6-positions.js +10 -0
- package/dist/orchestration/stages/s7-decision-graph.js +76 -0
- package/dist/orchestration/stages/s8-verify.js +153 -46
- package/dist/orchestration/stages/s8b-rebuttal.js +208 -0
- package/dist/orchestration/stages/s9-judge.js +329 -108
- package/dist/orchestration/stages/s9b-plan.js +85 -75
- package/dist/providers/codex.js +2 -1
- package/dist/providers/spawn.js +5 -0
- package/dist/schemas/index.js +572 -13
- package/dist/skills/idea-refinement/analyst.md +18 -14
- package/dist/skills/idea-refinement/economics-delivery.md +7 -0
- package/dist/skills/idea-refinement/market-adoption.md +7 -0
- package/dist/storage/runs.js +11 -4
- package/dist/tui/app.js +37 -13
- package/dist/tui/format.js +4 -5
- package/dist/tui/smart-entry.js +17 -1
- package/dist/tui/timeline.js +2 -4
- package/dist/workflows/code-review.js +4 -2
- package/dist/workflows/idea-refinement.js +110 -46
- package/package.json +12 -4
- package/dist/orchestration/stages/s0-grill.js +0 -79
- package/dist/orchestration/stages/s1-intent.js +0 -25
- package/dist/orchestration/stages/s2-misread.js +0 -76
- package/dist/orchestration/stages/s3-prompts.js +0 -55
- package/dist/orchestration/stages/s6-claims.js +0 -56
- package/dist/orchestration/stages/s7-disagreement.js +0 -134
package/dist/cli/run.js
CHANGED
|
@@ -1,19 +1,29 @@
|
|
|
1
1
|
// `aiki run <workflow> [input]` (§5) — headless run. idea-refinement takes inline text or a file path;
|
|
2
2
|
// code-review computes a git diff from --base/--head (or reads --diff) and reviews it at the repo root.
|
|
3
3
|
import { readFile } from 'node:fs/promises';
|
|
4
|
+
import { join } from 'node:path';
|
|
4
5
|
import { createInterface } from 'node:readline';
|
|
6
|
+
import { renderTerminalSummary } from '../orchestration/stages/s10-render.js';
|
|
5
7
|
import { run as runEngine } from '../orchestration/engine.js';
|
|
6
8
|
import { ConfigError, loadLayeredConfig } from '../config/config.js';
|
|
7
9
|
import { computeDiff, detectDefaultBranch, GitError, repoToplevel } from '../orchestration/git.js';
|
|
8
10
|
import { resolveRunsRoot } from '../storage/paths.js';
|
|
9
11
|
import { openCouncilHtml } from '../council/open.js';
|
|
12
|
+
import { buildEvidencePack } from '../orchestration/evidence-pack.js';
|
|
13
|
+
import { IdeaModeSchema } from '../schemas/index.js';
|
|
14
|
+
import { defaultBudgetFor, defaultDeadlineFor, IDEA_MODE_PLANS } from '../orchestration/modes.js';
|
|
10
15
|
const WORKFLOWS = ['idea-refinement', 'code-review'];
|
|
11
|
-
/** Rough provider-call estimate for the run-cost preview (V5). Approximate — the real count varies with
|
|
12
|
-
* §14 repairs, cross-exam skips, and quorum. `opus` = the Claude/Opus subset (the metered-cost driver). */
|
|
13
16
|
export function estimateRun(workflow, opts = {}) {
|
|
14
17
|
if (workflow === 'code-review')
|
|
15
18
|
return { calls: 5, opus: opts.cheap ? 1 : 2 };
|
|
16
|
-
|
|
19
|
+
const mode = opts.mode ?? 'council';
|
|
20
|
+
const plan = IDEA_MODE_PLANS[mode];
|
|
21
|
+
return {
|
|
22
|
+
calls: plan.maxCalls,
|
|
23
|
+
opus: mode === 'quick' ? 1 : 2,
|
|
24
|
+
minCalls: mode === 'research' ? 8 : plan.baseCalls,
|
|
25
|
+
reserved: plan.reservedCalls,
|
|
26
|
+
};
|
|
17
27
|
}
|
|
18
28
|
/** Thin y/N prompt (default yes). Only used on an interactive TTY. */
|
|
19
29
|
function confirm(question) {
|
|
@@ -79,8 +89,22 @@ export async function runCommand(workflow, input, opts = {}) {
|
|
|
79
89
|
process.stderr.write(`unknown workflow "${workflow}". Available: ${WORKFLOWS.join(', ')}\n`);
|
|
80
90
|
return 1;
|
|
81
91
|
}
|
|
92
|
+
let mode;
|
|
93
|
+
if (workflow === 'idea-refinement') {
|
|
94
|
+
const parsed = IdeaModeSchema.safeParse(opts.mode ?? 'council');
|
|
95
|
+
if (!parsed.success) {
|
|
96
|
+
process.stderr.write(`unknown idea mode "${opts.mode}". Available: quick, council, research\n`);
|
|
97
|
+
return 1;
|
|
98
|
+
}
|
|
99
|
+
mode = parsed.data;
|
|
100
|
+
}
|
|
101
|
+
else if (opts.mode) {
|
|
102
|
+
process.stderr.write('--mode only applies to idea-refinement.\n');
|
|
103
|
+
return 1;
|
|
104
|
+
}
|
|
82
105
|
let text;
|
|
83
106
|
let cwd;
|
|
107
|
+
let evidencePack;
|
|
84
108
|
if (workflow === 'code-review') {
|
|
85
109
|
const r = await resolveCodeReview(opts);
|
|
86
110
|
if ('done' in r)
|
|
@@ -95,6 +119,19 @@ export async function runCommand(workflow, input, opts = {}) {
|
|
|
95
119
|
}
|
|
96
120
|
text = resolved;
|
|
97
121
|
}
|
|
122
|
+
if (opts.evidence) {
|
|
123
|
+
if (workflow !== 'idea-refinement') {
|
|
124
|
+
process.stderr.write('--evidence only applies to idea-refinement.\n');
|
|
125
|
+
return 1;
|
|
126
|
+
}
|
|
127
|
+
try {
|
|
128
|
+
evidencePack = await buildEvidencePack(opts.evidence);
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
process.stderr.write(`cannot load evidence pack: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
132
|
+
return 1;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
98
135
|
// Precedence (§10/T9): --budget flag > config.budget > built-in default. roles/deadline/models are
|
|
99
136
|
// config-only (layered: global ~/.aiki base, project .aiki override).
|
|
100
137
|
let cfg;
|
|
@@ -118,8 +155,12 @@ export async function runCommand(workflow, input, opts = {}) {
|
|
|
118
155
|
process.stderr.write('--cheap only applies to code-review; ignoring for this workflow.\n');
|
|
119
156
|
}
|
|
120
157
|
// Run-cost preview (V5): show the estimate; confirm interactively unless --yes or non-interactive.
|
|
121
|
-
const est = estimateRun(workflow, { cheap: opts.cheap });
|
|
122
|
-
const
|
|
158
|
+
const est = estimateRun(workflow, { cheap: opts.cheap, mode });
|
|
159
|
+
const callEstimate = est.minCalls !== undefined && est.minCalls !== est.calls ? `${est.minCalls}–${est.calls}` : `${est.calls}`;
|
|
160
|
+
const resolvedBudget = opts.budget ?? cfg.budget ?? defaultBudgetFor(workflow, mode);
|
|
161
|
+
const reservation = est.reserved ? `; ${est.reserved} call(s) reserved for chair + planner` : '';
|
|
162
|
+
const modeLabel = mode ? ` in ${mode} mode` : '';
|
|
163
|
+
const note = ` ≈${callEstimate} provider call(s)${modeLabel}, ~${est.opus} on Claude/Opus; budget ${resolvedBudget}${reservation}.`;
|
|
123
164
|
if (!opts.yes && process.stdin.isTTY && process.stdout.isTTY) {
|
|
124
165
|
if (!(await confirm(`${note}\n Continue? [Y/n] `))) {
|
|
125
166
|
process.stdout.write(' cancelled.\n');
|
|
@@ -130,15 +171,29 @@ export async function runCommand(workflow, input, opts = {}) {
|
|
|
130
171
|
process.stdout.write(`${note}\n`);
|
|
131
172
|
}
|
|
132
173
|
const outcome = await runEngine(workflow, text, {
|
|
133
|
-
|
|
134
|
-
|
|
174
|
+
mode,
|
|
175
|
+
budget: resolvedBudget,
|
|
176
|
+
deadlineMs: cfg.deadlineMs ?? defaultDeadlineFor(workflow, mode),
|
|
135
177
|
roleOverrides,
|
|
136
178
|
cwd, // code-review: repo root; idea-refinement: undefined → run dir
|
|
137
179
|
runsRoot: await resolveRunsRoot(), // hybrid: repo .aiki when in a repo, else ~/.aiki
|
|
138
180
|
providerModels: cfg.models, // V8: per-provider model → CLI --model
|
|
181
|
+
evidencePack,
|
|
139
182
|
});
|
|
140
183
|
if (outcome.ok) {
|
|
141
|
-
process.stdout.write(`\n ✔ run ${outcome.runId} complete — ${outcome.callCount} provider call(s)\n artifacts: ${outcome.dir}\n`);
|
|
184
|
+
process.stdout.write(`\n ✔ run ${outcome.runId} complete — ${outcome.callCount} provider call(s)\n artifacts: ${outcome.dir}\n\n`);
|
|
185
|
+
// Level-1 terminal summary from the machine-readable report (idea runs; absent for code-review).
|
|
186
|
+
try {
|
|
187
|
+
const report = JSON.parse(await readFile(join(outcome.dir, '10-decision-report.json'), 'utf8'));
|
|
188
|
+
const summary = renderTerminalSummary(report, {
|
|
189
|
+
markdownPath: join(outcome.dir, 'final-report.md'),
|
|
190
|
+
jsonPath: join(outcome.dir, '10-decision-report.json'),
|
|
191
|
+
});
|
|
192
|
+
process.stdout.write(summary.split('\n').map((line) => ` ${line}`).join('\n') + '\n');
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
/* code-review runs and pre-v4 artifacts have no decision report — the line above already links artifacts */
|
|
196
|
+
}
|
|
142
197
|
// Auto-open the readable report in the browser (interactive terminals only; skipped in pipes/CI).
|
|
143
198
|
if (process.stdout.isTTY) {
|
|
144
199
|
const html = await openCouncilHtml(outcome.runId, outcome.dir);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
export function readPackageVersion(metaUrl = import.meta.url) {
|
|
3
|
+
const pkg = JSON.parse(readFileSync(new URL('../../package.json', metaUrl), 'utf8'));
|
|
4
|
+
if (typeof pkg.version !== 'string')
|
|
5
|
+
throw new Error('package.json version missing');
|
|
6
|
+
return pkg.version;
|
|
7
|
+
}
|
|
8
|
+
export const VERSION = readPackageVersion();
|