aiki-cli 0.2.2 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/CHANGELOG.md +113 -6
  2. package/README.md +119 -30
  3. package/dist/bench/arms.js +10 -9
  4. package/dist/bench/harness.js +13 -10
  5. package/dist/bench/idea-lane-rotation.js +237 -0
  6. package/dist/bench/idea-v3-bench.js +506 -0
  7. package/dist/bench/idea-v3-rating.js +582 -0
  8. package/dist/bench/results.js +10 -3
  9. package/dist/bench/scoring/decision-insights.js +112 -0
  10. package/dist/bench/scoring/seeded-bugs.js +4 -0
  11. package/dist/cli/bench.js +180 -3
  12. package/dist/cli/doctor.js +56 -24
  13. package/dist/cli/index.js +31 -6
  14. package/dist/cli/resolve.js +7 -6
  15. package/dist/cli/resume.js +18 -0
  16. package/dist/cli/run.js +66 -8
  17. package/dist/council/view.js +446 -117
  18. package/dist/orchestration/calculations.js +97 -0
  19. package/dist/orchestration/context.js +37 -9
  20. package/dist/orchestration/decision-dossier.js +320 -0
  21. package/dist/orchestration/decision-graph.js +256 -0
  22. package/dist/orchestration/engine.js +5 -2
  23. package/dist/orchestration/evidence-pack.js +46 -0
  24. package/dist/orchestration/idea-lanes.js +20 -0
  25. package/dist/orchestration/jsonStage.js +72 -0
  26. package/dist/orchestration/legacy-idea-adapter.js +102 -0
  27. package/dist/orchestration/modes.js +39 -0
  28. package/dist/orchestration/preflight.js +203 -0
  29. package/dist/orchestration/quick-analysis.js +93 -0
  30. package/dist/orchestration/stages/cr-ladder.js +80 -0
  31. package/dist/orchestration/stages/s10-render.js +574 -150
  32. package/dist/orchestration/stages/s4-analyze.js +12 -7
  33. package/dist/orchestration/stages/s5-drift.js +9 -9
  34. package/dist/orchestration/stages/s6-positions.js +10 -0
  35. package/dist/orchestration/stages/s7-decision-graph.js +76 -0
  36. package/dist/orchestration/stages/s8-verify.js +153 -46
  37. package/dist/orchestration/stages/s8b-rebuttal.js +208 -0
  38. package/dist/orchestration/stages/s9-judge.js +329 -108
  39. package/dist/orchestration/stages/s9b-plan.js +118 -85
  40. package/dist/orchestration/url-sources.js +200 -0
  41. package/dist/providers/codex.js +2 -1
  42. package/dist/providers/spawn.js +5 -0
  43. package/dist/schemas/index.js +638 -15
  44. package/dist/skills/idea-refinement/analyst.md +18 -14
  45. package/dist/skills/idea-refinement/economics-delivery.md +7 -0
  46. package/dist/skills/idea-refinement/market-adoption.md +7 -0
  47. package/dist/storage/runs.js +12 -4
  48. package/dist/tui/app.js +53 -14
  49. package/dist/tui/format.js +4 -5
  50. package/dist/tui/smart-entry.js +17 -1
  51. package/dist/tui/timeline.js +2 -4
  52. package/dist/workflows/code-review.js +4 -2
  53. package/dist/workflows/idea-refinement.js +118 -46
  54. package/package.json +12 -4
  55. package/dist/orchestration/stages/s0-grill.js +0 -79
  56. package/dist/orchestration/stages/s1-intent.js +0 -25
  57. package/dist/orchestration/stages/s2-misread.js +0 -76
  58. package/dist/orchestration/stages/s3-prompts.js +0 -55
  59. package/dist/orchestration/stages/s6-claims.js +0 -56
  60. 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, inferIdeaMode } 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
- return { calls: 12, opus: 4 }; // idea-refinement (S0/S1/S3 on agy; S2 has claude; S7 + S9 + S9b run on the claude judge)
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,24 @@ 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
+ if (opts.mode !== undefined) {
95
+ const parsed = IdeaModeSchema.safeParse(opts.mode);
96
+ if (!parsed.success) {
97
+ process.stderr.write(`unknown idea mode "${opts.mode}". Available: quick, council, research\n`);
98
+ return 1;
99
+ }
100
+ mode = parsed.data;
101
+ }
102
+ }
103
+ else if (opts.mode) {
104
+ process.stderr.write('--mode only applies to idea-refinement.\n');
105
+ return 1;
106
+ }
82
107
  let text;
83
108
  let cwd;
109
+ let evidencePack;
84
110
  if (workflow === 'code-review') {
85
111
  const r = await resolveCodeReview(opts);
86
112
  if ('done' in r)
@@ -94,6 +120,20 @@ export async function runCommand(workflow, input, opts = {}) {
94
120
  return 1;
95
121
  }
96
122
  text = resolved;
123
+ mode ??= inferIdeaMode(text);
124
+ }
125
+ if (opts.evidence) {
126
+ if (workflow !== 'idea-refinement') {
127
+ process.stderr.write('--evidence only applies to idea-refinement.\n');
128
+ return 1;
129
+ }
130
+ try {
131
+ evidencePack = await buildEvidencePack(opts.evidence);
132
+ }
133
+ catch (error) {
134
+ process.stderr.write(`cannot load evidence pack: ${error instanceof Error ? error.message : String(error)}\n`);
135
+ return 1;
136
+ }
97
137
  }
98
138
  // Precedence (§10/T9): --budget flag > config.budget > built-in default. roles/deadline/models are
99
139
  // config-only (layered: global ~/.aiki base, project .aiki override).
@@ -118,8 +158,12 @@ export async function runCommand(workflow, input, opts = {}) {
118
158
  process.stderr.write('--cheap only applies to code-review; ignoring for this workflow.\n');
119
159
  }
120
160
  // Run-cost preview (V5): show the estimate; confirm interactively unless --yes or non-interactive.
121
- const est = estimateRun(workflow, { cheap: opts.cheap });
122
- const note = ` ≈${est.calls} provider call(s), ~${est.opus} on Claude/Opus (the metered part).`;
161
+ const est = estimateRun(workflow, { cheap: opts.cheap, mode });
162
+ const callEstimate = est.minCalls !== undefined && est.minCalls !== est.calls ? `${est.minCalls}–${est.calls}` : `${est.calls}`;
163
+ const resolvedBudget = opts.budget ?? cfg.budget ?? defaultBudgetFor(workflow, mode);
164
+ const reservation = est.reserved ? `; ${est.reserved} call(s) reserved for chair + planner` : '';
165
+ const modeLabel = mode ? ` in ${mode} mode` : '';
166
+ const note = ` ≈${callEstimate} provider call(s)${modeLabel}, ~${est.opus} on Claude/Opus; budget ${resolvedBudget}${reservation}.`;
123
167
  if (!opts.yes && process.stdin.isTTY && process.stdout.isTTY) {
124
168
  if (!(await confirm(`${note}\n Continue? [Y/n] `))) {
125
169
  process.stdout.write(' cancelled.\n');
@@ -130,15 +174,29 @@ export async function runCommand(workflow, input, opts = {}) {
130
174
  process.stdout.write(`${note}\n`);
131
175
  }
132
176
  const outcome = await runEngine(workflow, text, {
133
- budget: opts.budget ?? cfg.budget,
134
- deadlineMs: cfg.deadlineMs,
177
+ mode,
178
+ budget: resolvedBudget,
179
+ deadlineMs: cfg.deadlineMs ?? defaultDeadlineFor(workflow, mode),
135
180
  roleOverrides,
136
181
  cwd, // code-review: repo root; idea-refinement: undefined → run dir
137
182
  runsRoot: await resolveRunsRoot(), // hybrid: repo .aiki when in a repo, else ~/.aiki
138
183
  providerModels: cfg.models, // V8: per-provider model → CLI --model
184
+ evidencePack,
139
185
  });
140
186
  if (outcome.ok) {
141
- process.stdout.write(`\n ✔ run ${outcome.runId} complete — ${outcome.callCount} provider call(s)\n artifacts: ${outcome.dir}\n`);
187
+ process.stdout.write(`\n ✔ run ${outcome.runId} complete — ${outcome.callCount} provider call(s)\n artifacts: ${outcome.dir}\n\n`);
188
+ // Level-1 terminal summary from the machine-readable report (idea runs; absent for code-review).
189
+ try {
190
+ const report = JSON.parse(await readFile(join(outcome.dir, '10-decision-report.json'), 'utf8'));
191
+ const summary = renderTerminalSummary(report, {
192
+ markdownPath: join(outcome.dir, 'final-report.md'),
193
+ jsonPath: join(outcome.dir, '10-decision-report.json'),
194
+ });
195
+ process.stdout.write(summary.split('\n').map((line) => ` ${line}`).join('\n') + '\n');
196
+ }
197
+ catch {
198
+ /* code-review runs and pre-v4 artifacts have no decision report — the line above already links artifacts */
199
+ }
142
200
  // Auto-open the readable report in the browser (interactive terminals only; skipped in pipes/CI).
143
201
  if (process.stdout.isTTY) {
144
202
  const html = await openCouncilHtml(outcome.runId, outcome.dir);