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/CHANGELOG.md CHANGED
@@ -3,21 +3,128 @@
3
3
  ## Unreleased
4
4
 
5
5
  ### Added
6
- - **Contextual intent preflight** idea-refinement now starts with an S0 run brief: the analyst generates
7
- 3-4 context-specific questions, the TUI asks them before the main council work, and the answers are
8
- persisted in `00b-run-brief.json` and included in downstream prompts.
6
+ - Public URL snapshots for idea prompts, including an npm registry adapter, private-network rejection,
7
+ auditable `FETCHED` / `BLOCKED` / `FAILED` status, and a research-mode gate that stops before model calls
8
+ when a supplied source cannot be read.
9
+ - Requested-output planning: prompts that ask for a feature list or implementation plan now carry that
10
+ requirement through the decision contract, the existing planner call, machine JSON, Markdown, and HTML.
11
+
12
+ ### Changed
13
+ - Explicit research wording selects research mode deterministically when `--mode` is absent; an explicit
14
+ mode remains authoritative. Preflight asks zero to four questions and may not repeat facts already present
15
+ in the user prompt or a fetched source.
16
+ - Reader-facing report sections use human claim text instead of internal graph ids such as `G1`; raw ids
17
+ remain in machine artifacts and the Markdown technical audit.
18
+
19
+ ## 0.3.0 — 2026-07-15 — evidence-grounded decision council
20
+
21
+ This release turns idea refinement into a bounded, evidence-linked decision workflow with explicit modes,
22
+ selective rebuttal, a reader-first dossier, and stronger recovery from malformed provider output. The frozen
23
+ code-review result remains unchanged: 100% vs 77% seeded-bug recall at equal precision on the pre-registered
24
+ 10-case holdout. The idea-v3 evaluation harness ships here, but its paid benchmark is still pending and no
25
+ idea-quality lift is claimed yet.
26
+
27
+ ### Added
28
+ - **Explicit idea modes and adaptive budgets (R6)** — `aiki run idea-refinement --mode
29
+ quick|council|research` defaults to council without a learned router. Quick is one structured analyst and
30
+ never presents itself as a council; council uses a 6-call base with at most two graph-triggered extras;
31
+ research permits up to four extras and enables the verified `codex --search exec ...` capability only on
32
+ Codex scout calls while retaining `-s read-only`. Mode-aware defaults are 4/10/12 calls respectively.
33
+ - **Two-view decision preflight (R6)** — two readings run in parallel and deterministically merge into one
34
+ user-confirmed or visibly headless/defaulted decision contract. The old S1/S2/S3 model calls are gone;
35
+ analyst prompts are filled deterministically. Receipts split calls into discovery, verification, repair,
36
+ and planning, and resume preserves the original mode.
37
+ - **Evidence and calculation integrity (R4)** — idea runs accept `--evidence <file|directory>` and persist
38
+ only source paths + SHA-256 hashes; evidence cards enforce source/freshness rules; derived numeric claims
39
+ can carry a pure arithmetic ledger whose values/units are recomputed; S8 emits typed claim verification;
40
+ and invalid evidence references are rejected before the chair call.
41
+ - **Selective rebuttal and evidence-linked chair (R5)** — only verdict-flipping graph nodes enter one
42
+ anonymous rebuttal round; council coverage-fill and rebuttal share a two-call cap while chair/planner
43
+ budget stays reserved; responses append as immutable `08b-rebuttals.json` events; and the chair must emit
44
+ graph-linked rulings, recommendation reasons, conditions, pivots, and strongest counter-cases. A judge-
45
+ authored node is excluded before the chair prompt and remains unresolved under degradation.
46
+ - **Startup preflight** — typing bare `aiki` now runs the full doctor before the home screen: per-provider
47
+ progress rows checking CLI presence, version, and auth/quota (smoke, cached 6h). Fewer than 2 providers
48
+ ready shows a failure screen with the exact fix per provider; a single degraded provider shows a warning
49
+ on the home screen and the council continues with the remaining quorum.
50
+ - **Idea-lane bench resume** — `aiki bench idea-refinement --set build --resume [--yes]` continues the
51
+ latest campaign file in `bench/results/`: completed case×rotation pairs are kept (never re-paid), missing
52
+ or failed pairs re-run, and new observations append to the same file. The dry-run estimate reflects only
53
+ what is left to run. `--case <id>` restricts the metered run to one build case (an unknown id fails loud
54
+ with the list of valid cases), and a run that completes `low_diversity` (a scout seat died mid-run) is
55
+ rejected instead of being recorded — it is not a valid rotation sample.
56
+ - **Adjudication import** — `aiki bench idea-refinement --import <file>` (offline, no provider calls)
57
+ imports blind adjudications: each `{ case_id, rotation, adjudication }` entry flows through the frozen R0
58
+ scorer and fills that pair's null recall/precision in the campaign file. Unknown pairs fail loud;
59
+ re-scoring an already-scored pair is refused (blind adjudication is one pass); when every pair is scored
60
+ it prints the lane default selection.
9
61
  - **Idea report v3** — idea-refinement reports now emit an explicit BLUF recommendation
10
62
  (`PROCEED`, `PROCEED_WITH_CONDITIONS`, `PIVOT`, `STOP`), conditions when needed, a best-effort
11
63
  12-dimension scorecard, assumption audit table in HTML, deterministic debate narrative, anchored
12
64
  validation plan with kill signals (`09b-action-plan.json`), open questions, red-team note, and a
13
65
  call/provider receipt. The Markdown copy button includes the expanded brief.
66
+ - **R7 decision dossier** — `10-decision-report.json` now persists the graph-anchored recommendation chain,
67
+ evidence source/date/freshness/verification table, genuine disagreement and append-only position-change
68
+ events, coverage and sensitivity ledgers, executable experiments, strongest counter-case, strictly
69
+ verified unique-provider contributions, categorized receipt, and technical graph fold. Final Markdown,
70
+ HTML, and Copy-Markdown render from that same dossier; R6-era and older runs retain their legacy HTML. It
71
+ provides the canonical report foundation refined by the reader-first snapshot below.
72
+ - **Reader-first decision snapshot (report v3.1)** — terminal, Markdown, and HTML lead with the council
73
+ recommendation, independently verified evidence coverage, decisive facts, first action, strongest
74
+ counter-case, and three critical unknowns. Financial and threshold-heavy chairs can emit strict
75
+ graph-anchored decisive numbers, explicit payback, option commitments marked `KNOWN`, `TARGET_CAP`, or
76
+ `UNKNOWN`, and one go/no-go tripwire. Invalid claim anchors remove the snapshot instead of presenting
77
+ unsupported numbers.
78
+ - **Idea-v3 benchmark harness** — the frozen B/C/D2/R protocol now has an eight-case build set, a
79
+ 12-case/tag/provenance holdout contract that remains closed until freeze, checkpoint/resume for successes
80
+ and failures, isolated baseline-provider campaigns, three independently shuffled blind-rating packets,
81
+ one-pass scoring, and hash-locked freeze and holdout guards. Build tuning, blind ratings, and the paid
82
+ holdout evaluation remain pending.
14
83
 
15
84
  ### Changed
16
- - Idea-refinement run estimate is now ~12 provider calls / ~4 Claude-Opus calls because S0 writes the
17
- intent preflight and the judge seat also writes the validation plan. The default budget is now 13 so
18
- a normal run still has room for one repair without skipping the validation plan.
85
+ - **Three-level decision report** idea-refinement's final report is restructured: (1) a one-screen
86
+ terminal summary (recommendation, decision state, verified evidence coverage, decisive result, dissent,
87
+ next action, and optional tripwire) printed after `aiki run`; (2) a 10-section reader-first graph-backed
88
+ Decision Report markdown (`final-report.md`) ordered as decision, action plan, reasoning, what could change
89
+ the decision, evidence, risks/gaps, dissent, council value, run details, and technical audit; (3)
90
+ machine-readable `10-decision-report.json` that Markdown and HTML render from, so the
91
+ surfaces cannot disagree. Statuses are ACCEPTED / ACCEPTED_WITH_CONDITIONS / INCONCLUSIVE / REJECTED
92
+ (mapped from the judge's recommendation). The structural score is moved behind technical detail and never
93
+ presented as decision accuracy: 40% verification coverage + 25%
94
+ independent convergence + 20% evidence quality + 15% stability − critical-risk penalty; model
95
+ self-confidence never enters it and consensus alone can never reach the High band. Labeled a heuristic in
96
+ the report until benchmark-calibrated.
97
+ - Idea-refinement estimates are mode-aware: quick ≈3 calls / 1 Claude-Opus; council 6–8 / ~2 Opus; research
98
+ 8–10 / ~2 Opus. Chair and planner calls are reserved before optional graph work.
99
+ - **Mode-aware time limits** — quick and council retain a 20-minute run deadline; research uses 45 minutes.
100
+ The per-provider-call ceiling is 15 minutes, so legitimate deep scout work can finish while the overall
101
+ deadline still bounds the run.
19
102
 
20
103
  ### Fixed
104
+ - Idea analyst outputs now canonicalize observed Gemini evidence-enum variants before strict validation:
105
+ freshness accepts case-insensitive canonical words, while evidence support accepts a leading known token
106
+ (`SUPPORT`, `OPPOSE`, or `OPPOSES`) and maps it to the canonical enum. Arbitrary prose and unknown values
107
+ still fail the schema boundary.
108
+ - A failed S4 repair no longer kills the run for recoverable shape damage: deterministic salvage strips
109
+ unknown keys, drops invalid evidence/calculation/coverage/question entries, removes only individually
110
+ invalid positions, and scrubs their references. It never invents content and an empty claim set remains
111
+ fatal. The same fallback applies when the repair call itself dies (for example, quota).
112
+ - All schema-validated model stages now attempt lossless coercion before a paid repair (for example, wrapping
113
+ a lone array item) and bounded lossy coercion only after repair failure (for example, truncating beyond a
114
+ declared maximum). The full zod schema still decides whether data may cross the stage boundary.
115
+ - Provider timeouts now resolve immediately after killing the process group and unref a surviving detached
116
+ child, preventing one escaped subprocess from blocking the CLI long after the configured timeout.
117
+ - Idea prose containing ordinary words such as `class`, `export`, or `import` no longer misroutes to code
118
+ review; routing now requires actual code structure such as a diff, fence, code file path, declaration, or
119
+ import/export syntax.
120
+ - Decisive warnings no longer echo an unresolved affirmative claim as reassurance, and the calculation
121
+ checker now canonicalizes ordinary plurals, dimensionless ratios, and currency-margin units without
122
+ weakening arithmetic validation.
123
+ - Benchmark safeguards now redact receipt costs and degradation tokens from blind packets, refuse accidental
124
+ same-day campaign overwrites, and honor the frozen baseline provider when a holdout run does not pass an
125
+ explicit override.
126
+ - Release builds now clean `dist/` before compiling, so removed stages cannot survive as stale JavaScript in
127
+ the npm tarball.
21
128
  - Codex provider smoke no longer crashes in non-git folders; Aiki now passes Codex's verified
22
129
  `--skip-git-repo-check` flag while keeping `-s read-only`.
23
130
  - `aiki --version` now reads from `package.json`, preventing CLI/package version drift.
package/README.md CHANGED
@@ -7,18 +7,20 @@
7
7
  <p align="center"><em>A local <strong>model council</strong> for code review and idea stress-testing — driven by the AI CLIs you already have.</em></p>
8
8
 
9
9
  <p align="center">
10
+ <a href="https://www.npmjs.com/package/aiki-cli"><img alt="npm: aiki-cli" src="https://img.shields.io/npm/v/aiki-cli.svg"></a>
10
11
  <img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-blue.svg">
11
12
  <img alt="Node ≥ 20" src="https://img.shields.io/badge/node-%E2%89%A5%2020-brightgreen.svg">
12
13
  <img alt="Local-first, no API keys" src="https://img.shields.io/badge/local--first-no%20API%20keys-informational.svg">
13
14
  <img alt="Read-only orchestration" src="https://img.shields.io/badge/orchestration-read--only-success.svg">
14
- <img alt="Tests" src="https://img.shields.io/badge/tests-261%20passing-success.svg">
15
+ <img alt="Tests" src="https://img.shields.io/badge/tests-381%20passing-success.svg">
15
16
  </p>
16
17
 
17
18
  ---
18
19
 
19
- **aiki** runs the AI coding CLIs you already have installed and logged in (Claude Code, Codex, Antigravity/Gemini)
20
- as a **panel that can genuinely disagree** they review independently, cross-examine each other, a judge
21
- adjudicates the disputes, and you get a clear decision brief.
20
+ **aiki** is a local-first AI model council. It does **not** use hosted Aiki APIs, ask for API keys, or ship
21
+ model weights. Instead, it runs the AI coding CLIs you already have installed and logged in — Claude Code,
22
+ Codex, and Antigravity/Gemini as a **panel that can genuinely disagree**. They review independently,
23
+ cross-examine each other, a judge adjudicates the disputes, and you get a clear decision brief.
22
24
 
23
25
  It does two jobs, well:
24
26
 
@@ -28,7 +30,7 @@ It does two jobs, well:
28
30
  aiki is **not** a general assistant. Trivia and chat are routed away, not answered — a council adds cost, not
29
31
  accuracy, when there's one right answer.
30
32
 
31
- **Jump to:** [Why](#why) · [Benchmark](#benchmark) · [Requirements](#requirements) · [Install](#install) · [Quickstart](#quickstart) · [The two workflows](#the-two-workflows) · [Example](#example-a-real-idea-run) · [Configuration](#configuration) · [Sessions & resume](#sessions--resume) · [Safety](#safety-model) · [Costs & limits](#costs--limits) · [How it works](#how-it-works)
33
+ **Jump to:** [Why](#why) · [What's new](#whats-new-in-030) · [How it works](#how-aiki-works-no-apis) · [Benchmarks](#benchmarks) · [Requirements](#requirements) · [Install](#install) · [Quickstart](#quickstart) · [The two workflows](#the-two-workflows) · [Example](#example-a-real-idea-run) · [Configuration](#configuration) · [Sessions & resume](#sessions--resume) · [Safety](#safety-model) · [Costs & limits](#costs--limits)
32
34
 
33
35
  ---
34
36
 
@@ -43,7 +45,41 @@ stop copy-pasting between them by hand.
43
45
  <img src="docs/Three.png" alt="One model's field of view lets bugs slip past; three overlapping fields catch them all" width="820">
44
46
  </p>
45
47
 
46
- ## Benchmark
48
+ ## What's new in 0.3.0
49
+
50
+ - **Evidence-grounded decisions.** Supply local sources with `--evidence`; Aiki records their paths and
51
+ hashes, checks freshness and citations, independently verifies selected load-bearing claims, and shows the
52
+ remaining coverage gaps before the chair.
53
+ - **Three bounded modes.** Use `quick` for one structured analyst, `council` for bounded multi-model
54
+ deliberation, or `research` for current-fact work. Explicit research wording selects `research`
55
+ deterministically; `--mode` always overrides it.
56
+ - **A decision dossier, not an essay.** Reports lead with the recommendation, verified evidence coverage,
57
+ decisive facts, first action, strongest counter-case, and critical unknowns. Financial and threshold-heavy
58
+ decisions can include graph-anchored numbers, payback, option commitments, and a go/no-go tripwire.
59
+ - **More resilient long runs.** Bounded rebuttal, schema-safe output recovery, mode-aware deadlines, startup
60
+ provider checks, and call replay make malformed model output, quotas, and timeouts less likely to waste a
61
+ whole run.
62
+
63
+ The published code-review benchmark result below is unchanged. The new idea-decision benchmark machinery is
64
+ included in 0.3.0, but its paid evaluation is still pending, so no idea-quality improvement claim is made yet.
65
+
66
+ ## How Aiki works (no APIs)
67
+
68
+ Aiki is orchestration, not a hosted AI service:
69
+
70
+ 1. You install and sign in to three provider CLIs: Claude Code (`claude`), Codex (`codex`), and
71
+ Antigravity/Gemini (`agy`).
72
+ 2. Aiki starts those CLIs as local child processes with read-only/sandbox flags.
73
+ 3. Each model gets the same task independently, returns structured JSON, and never sees another model's
74
+ answer until the cross-exam stage.
75
+ 4. Aiki validates every stage with zod, stores the audit trail under `.aiki/` or `~/.aiki/`, and renders the
76
+ final decision brief.
77
+ 5. Your existing provider logins/subscriptions handle model access. Aiki never asks for API keys and never
78
+ reads credential folders.
79
+
80
+ ## Benchmarks
81
+
82
+ ### Code-review benchmark — completed
47
83
 
48
84
  On a **pre-registered, 10-case held-out** code-review benchmark (frozen before the run so it couldn't be
49
85
  tuned post-hoc — see [BENCHMARK.md](BENCHMARK.md) and [RESULTS.md](RESULTS.md)):
@@ -85,20 +121,39 @@ set. It is **not** a claim of beating cheap self-consistency (that comparison is
85
121
  n = 10 cases, single run per arm — directional, not a p-value. Full method and every number in
86
122
  [RESULTS.md §7](RESULTS.md).
87
123
 
124
+ ### Idea-decision benchmark — evaluation pending
125
+
126
+ Version 0.3.0 includes the frozen B/C/D2/R protocol, eight build cases, a 12-case/tag/provenance holdout
127
+ contract that stays closed until the protocol freeze, checkpoint/resume, independently shuffled blind-rating
128
+ packets, a frozen scorer, and post-freeze hash guards. Paid build tuning, blind ratings, and the holdout run
129
+ are not complete, so there is **no published idea-decision performance claim yet**. See
130
+ [BENCHMARK-IDEA-V3.md](BENCHMARK-IDEA-V3.md) for the pre-registration and
131
+ [docs/IDEA_V3_BENCH.md](docs/IDEA_V3_BENCH.md) for the operator workflow.
132
+
88
133
  ## Requirements
89
134
 
90
- > ⚠️ **aiki drives your existing CLIs — it does not ship or host any model.** You must have the provider CLIs
91
- > **installed and already logged in.** aiki never sees, stores, or transmits your credentials.
135
+ > ⚠️ **aiki drives your existing CLIs — it does not ship or host any model.** You should install and log in to
136
+ > all three provider CLIs before judging results. aiki never sees, stores, or transmits your credentials.
92
137
 
93
138
  - **Node ≥ 20.** (Node 16/18 will crash at startup — this is a hard requirement.)
94
139
  - **macOS or Linux** (WSL2 works).
95
140
  - The provider CLIs on your `PATH`, **each already authenticated**:
96
- | CLI | Command | Shown in aiki as |
97
- |---|---|---|
98
- | Claude Code | `claude` | Claude |
99
- | Codex | `codex` | Codex |
100
- | Antigravity | `agy` | Gemini |
101
- - **At least 2 of the 3** must be ready (a council needs a panel). Check anytime with `aiki doctor`.
141
+
142
+ | Provider CLI | Command Aiki runs | Shown in Aiki as | Check |
143
+ |---|---|---|---|
144
+ | Claude Code | `claude` | Claude | `claude --version` |
145
+ | Codex | `codex` | Codex | `codex --version` |
146
+ | Antigravity | `agy` | Gemini | `agy --version` |
147
+
148
+ - **Recommended: 3/3 providers ready.** Aiki can start with 2/3, but full council behavior and benchmarked
149
+ code-review quality expect Claude Code, Codex, and Antigravity/Gemini together.
150
+
151
+ You don't have to remember to check: launching `aiki` runs this preflight automatically — per-provider
152
+ progress rows for CLI presence, version, and auth/quota — and only opens the menu when at least 2 providers
153
+ pass. A failing provider shows its exact fix (install command, `run <binary> once to log in`, or retry
154
+ later). The auth/quota smoke result is cached for 6 hours, so repeat launches are instant and free.
155
+
156
+ Check manually anytime with `aiki doctor`:
102
157
 
103
158
  ```bash
104
159
  aiki doctor # lists each provider: version, ready/not, read-only mode
@@ -111,6 +166,9 @@ keeping the read-only sandbox enabled, so non-git folders do not crash the provi
111
166
  aiki doctor --fresh
112
167
  ```
113
168
 
169
+ `--fresh` bypasses the six-hour cache and can make up to three tiny provider calls; use it only when you need
170
+ to recheck authentication or quota immediately.
171
+
114
172
  ## Install
115
173
 
116
174
  ```bash
@@ -119,6 +177,13 @@ npm install -g aiki-cli
119
177
 
120
178
  The package is `aiki-cli`; it installs the `aiki` command.
121
179
 
180
+ Upgrade an existing installation:
181
+
182
+ ```bash
183
+ npm install -g aiki-cli@latest
184
+ aiki --version # 0.3.0
185
+ ```
186
+
122
187
  From source:
123
188
 
124
189
  ```bash
@@ -169,7 +234,9 @@ Plain text is never charged silently — you get a confirm step before any run s
169
234
 
170
235
  ```bash
171
236
  aiki run idea-refinement "a fridge-photo-to-recipe app for busy parents"
237
+ aiki run idea-refinement "an early idea" --mode quick # one structured analyst; no council claim
172
238
  aiki run idea-refinement ./idea.md
239
+ aiki run idea-refinement ./idea.md --mode research --evidence ./research/ # grounded, source-verifying council
173
240
  aiki run code-review --base main # review this branch vs main
174
241
  aiki run code-review --diff ./changes.patch # review a patch file
175
242
  aiki run code-review --cheap # Gemini+Codex review, Claude judges only disputes (~⅓ the Opus)
@@ -178,6 +245,16 @@ aiki show <run-id> --html --open # open the shareable decision brief
178
245
 
179
246
  An idea run **auto-opens** its report in your browser when it finishes.
180
247
 
248
+ `--evidence` accepts one local file or directory already in your scope. Aiki records absolute paths and
249
+ SHA-256 hashes in the run, gives those paths to the read-only scouts, and never copies the source files or
250
+ reads provider credential directories.
251
+
252
+ Public `http(s)` links in an idea are snapshotted once before model calls and stored in
253
+ `00a-url-sources.json`; every preflight reader and analyst sees that same text. npm package links use the
254
+ registry metadata API. A snapshot records `FETCHED`, `BLOCKED`, or `FAILED` honestly. In research mode,
255
+ an unreadable supplied link stops before paid calls and asks for pasted text or a public export instead of
256
+ letting the council guess or grill you for facts that should have come from the link.
257
+
181
258
  ## The two workflows
182
259
 
183
260
  <p align="center">
@@ -188,17 +265,27 @@ An idea run **auto-opens** its report in your browser when it finishes.
188
265
  real line in the diff) → mutual adversarial cross-examination → consensus/dispute map → the judge adjudicates
189
266
  only the disputes → report.
190
267
 
191
- **Idea refinement** — a contextual preflight (a few sharp questions to pin down what you actually mean)
192
- intent contractmisunderstanding guard parallel adversarial analysis disagreement map → verifier →
193
- judgea validation planner. The report is a **decision brief**, not an essay:
194
-
195
- - a **BLUF recommendation** `PROCEED` / `PROCEED WITH CONDITIONS` / `PIVOT` / `STOP`
196
- - the **chairman's reasoning** (what decided it, where the models split, whose side the judge took)
197
- - a **dimension scorecard** (which of 12 angles were examined, contested, or missed)
198
- - an **assumption audit** (held / failed / unverified, with confidence)
199
- - **the debate** (who argued what, who won)
200
- - an **anchored validation plan** — concrete next actions, each with an effort estimate and a *kill signal*
201
- - a **cost receipt** (calls per provider)
268
+ **Idea refinement** — two independent preflight readings one confirmed/defaulted decision contract
269
+ complementary analyst lanes deterministic claim/evidence graph auditonly decision-critical verification
270
+ or rebuttal evidence-linked chair → validation planner. The report is a graph-backed **decision dossier**,
271
+ not an essay.
272
+ Choose `--mode quick` for one structured analyst, `--mode council` for the full decision council, or
273
+ `--mode research` for source-grounded current-fact work. Without a flag, the default is council unless the
274
+ request explicitly asks to research, browse, look up, or check current sources; that conservative rule is
275
+ deterministic, and an explicit flag wins:
276
+
277
+ - a **reader-first decision card** — recommendation, verified evidence coverage, decisive facts, first action,
278
+ strongest counter-case, and critical unknowns before audit detail
279
+ - a **numeric decision snapshot when relevant** — graph-anchored decisive numbers, explicit payback, option
280
+ commitments labeled `KNOWN` / `TARGET_CAP` / `UNKNOWN`, and a go/no-go tripwire
281
+ - a **graph-anchored recommendation and claim chain** — every decisive statement links to stored claim IDs
282
+ - an **evidence and coverage ledger** — source, date, freshness, verification, `NOT_APPLICABLE`, and missing evidence
283
+ - **genuine disagreements and position changes** — explicit `CONCEDE` / `COUNTER` / `NARROW` events
284
+ - **decision sensitivity and an executable experiment plan** — anchored tests with effort and kill signals
285
+ - **requested product deliverables** — when the prompt asks for them, the same planner call must produce a
286
+ prioritized `MUST / SHOULD / LATER / NOT IN SCOPE` feature list and timeboxed implementation milestones
287
+ - a **verified contribution ledger** — unique provider claims count only after independent verification
288
+ - an **orchestration receipt and technical fold** — calls, degradation, submissions, edges, and graph events
202
289
 
203
290
  ## Example: a real idea run
204
291
 
@@ -218,7 +305,8 @@ The council's verdict on that one:
218
305
 
219
306
  …followed by **7 anchored validation actions**, e.g. *"Pull the last 90 days of churned users and tag each
220
307
  with their primary churn reason"* (effort S, kill signal: churn isn't feature-driven). The full brief opens in
221
- your browser and has a **Copy report (Markdown)** button so you can paste it straight into your coding assistant.
308
+ your browser and has a **Copy report (Markdown)** button backed by the same persisted dossier as the HTML,
309
+ so the copied claims, evidence statuses, experiments, and receipt cannot drift from the page.
222
310
 
223
311
  ## Configuration
224
312
 
@@ -271,9 +359,10 @@ This is the part that makes aiki trustworthy to point at a real repo:
271
359
 
272
360
  ## Costs & limits
273
361
 
274
- - **Runs cost real model calls** against your existing CLI subscriptions/quota. Idea refinement is about
275
- **12 provider calls** (~4 on Claude/Opus); code review is about **5**. `aiki run` shows an estimate and asks
276
- to confirm (skip with `--yes`).
362
+ - **Runs cost real model calls** against your existing CLI subscriptions/quota. Idea refinement is nominally
363
+ **3 calls in quick**, **6–8 in council**, or **8–10 in research** (schema repairs can add calls within the
364
+ mode-aware budget); code review is about **5**. `aiki run` shows the mode, range, budget, and reserved
365
+ chair/planner calls before asking to confirm (skip with `--yes`).
277
366
  - **Not a general assistant.** Questions and "explore my whole codebase" requests are redirected, not answered
278
367
  — aiki reviews a *diff* and vets a *stated idea*.
279
368
  - **Analysis, not advice.** Every report is a decision aid. Verify before acting.
@@ -287,7 +376,7 @@ This is the part that makes aiki trustworthy to point at a real repo:
287
376
  - Anywhere else → `~/.aiki/`. `$AIKI_HOME` overrides the global home.
288
377
  - The global session registry always lives in `~/.aiki/`.
289
378
 
290
- ## How it works
379
+ ## Implementation notes
291
380
 
292
381
  Every stage is a small, independently-testable unit with a zod-validated output contract. Model text lives in
293
382
  bounded, capped fields slotted into deterministic report structure — so the output is a briefing, not a chat
@@ -12,7 +12,7 @@ import { sameFinding } from '../orchestration/stages/cr-map.js';
12
12
  import { s9ReviewJudge } from '../orchestration/stages/cr-s9-judge.js';
13
13
  import { scoreFindings } from '../orchestration/stages/cr-report.js';
14
14
  import { runCodeReview } from '../workflows/code-review.js';
15
- export const ARM_IDS = ['A', 'B', 'C', 'D', 'E'];
15
+ export const ARM_IDS = ['A', 'B', 'C', 'D', 'E', 'L'];
16
16
  const SCHEMA_LINE = 'findings: [{id "F1"..., file, line_start, line_end, severity P0|P1|P2|P3, category CORRECTNESS|SECURITY|CONCURRENCY|ERROR_HANDLING|PERF|MAINTAINABILITY, claim, evidence, suggested_fix, self_confidence 0-1}]';
17
17
  const A_PROMPT = `Review this code diff and report the bugs you find. The diff is at {{DIFF_PATH}} (repo root = your cwd).
18
18
  Output ONLY JSON: {task_echo (≤2 sentences), ${SCHEMA_LINE}}. JSON only.`;
@@ -88,17 +88,18 @@ export const armC = async (ctx, diff) => {
88
88
  const judge = await s9ReviewJudge(ctx, map); // ctx.roles.judge = claude for arm C (harness sets it)
89
89
  return scoreFindings(map, judge).filter((s) => s.disposition === 'kept').map((s) => s.finding);
90
90
  };
91
- /** Arms D and E — the full product pipeline (`runCodeReview`) → read back its kept findings for scoring.
91
+ /** Arms D, E, and L — the product pipeline (`runCodeReview`) → read back kept findings for scoring.
92
92
  * SAME pipeline; the harness injects their differing roles: D = claude+codex reviewers + agy judge;
93
- * E = agy+codex reviewers + claude judge (the Opus-thrift variant claude fires only on disputes). */
94
- const productPipeline = async (ctx, diff) => {
95
- await runCodeReview(ctx, diff);
93
+ * E = agy+codex reviewers + claude judge; L = E plus targeted Claude coverage-hole hunts. */
94
+ async function runProductPipeline(ctx, diff, ladder = false) {
95
+ await runCodeReview(ctx, diff, { ladder });
96
96
  const [map, judge] = await Promise.all([
97
97
  readFile(resolve(ctx.writer.dir, '07-review-map.json'), 'utf8').then(JSON.parse),
98
98
  readFile(resolve(ctx.writer.dir, '09-judge-report.json'), 'utf8').then(JSON.parse),
99
99
  ]);
100
100
  return scoreFindings(map, judge).filter((s) => s.disposition === 'kept').map((s) => s.finding);
101
- };
102
- export const armD = productPipeline;
103
- export const armE = productPipeline;
104
- export const ARMS = { A: armA, B: armB, C: armC, D: armD, E: armE };
101
+ }
102
+ export const armD = (ctx, diff) => runProductPipeline(ctx, diff);
103
+ export const armE = (ctx, diff) => runProductPipeline(ctx, diff);
104
+ export const armL = (ctx, diff) => runProductPipeline(ctx, diff, true);
105
+ export const ARMS = { A: armA, B: armB, C: armC, D: armD, E: armE, L: armL };
@@ -29,12 +29,12 @@ export async function loadCases(suite, set, root = process.cwd()) {
29
29
  }
30
30
  return cases;
31
31
  }
32
- /** A/B/C need claude (the fixed single model); D needs claude+codex reviewers; E needs agy+codex
33
- * reviewers + claude judge (the Opus-thrift variant). */
32
+ /** A/B/C need claude (the fixed single model); D needs claude+codex reviewers; E/L need agy+codex
33
+ * reviewers + claude judge/hole-hunter. */
34
34
  function armAvailable(arm, available) {
35
35
  if (arm === 'D')
36
36
  return available.includes('claude') && available.includes('codex');
37
- if (arm === 'E')
37
+ if (arm === 'E' || arm === 'L')
38
38
  return available.includes('agy') && available.includes('codex') && available.includes('claude');
39
39
  return available.includes('claude');
40
40
  }
@@ -56,10 +56,10 @@ async function readPrecision(runId, reported, root = process.cwd()) {
56
56
  }
57
57
  async function runArmOnCase(arm, c, handles, available, root) {
58
58
  const runId = makeRunId('code-review');
59
- // Arm C's synthesis judge stays same-model; Arm E swaps the product pipeline's roles to the
60
- // Opus-thrift config (agy+codex hunt, claude judge). D uses code-review defaults.
59
+ // Arm C's synthesis judge stays same-model; E/L use the Opus-thrift roles
60
+ // (agy+codex tier-1 hunt, claude judge/hole-hunter). D uses code-review defaults.
61
61
  const overrides = arm === 'C' ? { judge: 'claude' }
62
- : arm === 'E' ? { s4: ['agy', 'codex'], judge: 'claude' }
62
+ : arm === 'E' || arm === 'L' ? { s4: ['agy', 'codex'], judge: 'claude' }
63
63
  : undefined;
64
64
  const roles = resolveRoles('code-review', available, overrides);
65
65
  const ctx = new RunCtx({ runId, workflow: 'code-review', handles, roles, writer: new RunWriter(runId, join(root, '.aiki')), cwd: c.dir });
@@ -91,6 +91,8 @@ async function runArmOnCase(arm, c, handles, available, root) {
91
91
  seeded: s.seeded,
92
92
  matched: s.matched,
93
93
  recall: s.recall,
94
+ matchedRelaxed: s.matchedRelaxed,
95
+ recallRelaxed: s.recallRelaxed,
94
96
  reported: s.reported,
95
97
  unmatched: s.unmatched,
96
98
  precision: await readPrecision(runId, s.reported, root),
@@ -100,7 +102,7 @@ async function runArmOnCase(arm, c, handles, available, root) {
100
102
  }
101
103
  /** Approx claude/Opus calls each arm makes per case — for the pre-run quota estimate (§19). Not exact:
102
104
  * §14 JSON repairs can add a few, and D's cross-exam/judge vary; deliberately a round upper-ish figure. */
103
- export const CLAUDE_CALLS_PER_CASE = { A: 1, B: 1, C: 4, D: 2, E: 1 };
105
+ export const CLAUDE_CALLS_PER_CASE = { A: 1, B: 1, C: 4, D: 2, E: 1, L: 5 };
104
106
  /** ≈ claude/Opus calls for a list of case×arm pairs (the quota-sensitive cost the user cares about). */
105
107
  export function estimateClaudeCalls(pairs) {
106
108
  return pairs.reduce((n, p) => n + (CLAUDE_CALLS_PER_CASE[p.arm] ?? 0), 0);
@@ -238,12 +240,13 @@ export function renderTable(result) {
238
240
  const L = [];
239
241
  L.push(`bench ${result.suite} — set ${result.set} — ${result.cases.length} case(s)`);
240
242
  L.push('');
241
- L.push('| Arm | Recall (micro) | Recall (macro) | Matched/Seeded | Reported | Unmatched(FP?) | Precision | Calls | Wall(s) |');
242
- L.push('|---|---|---|---|---|---|---|---|---|');
243
+ L.push('| Arm | Recall (strict) | Recall (category-relaxed) | Recall (macro) | Matched/Seeded | Reported | Unmatched(FP?) | Precision | Calls | Wall(s) |');
244
+ L.push('|---|---|---|---|---|---|---|---|---|---|');
243
245
  for (const r of result.summary) {
244
246
  const pct = (n) => `${(n * 100).toFixed(0)}%`;
245
247
  const prec = r.precision === null ? '—' : pct(r.precision);
246
- L.push(`| ${r.arm} | ${pct(r.recall)} | ${pct(r.recallMacro)} | ${r.matched}/${r.seeded} | ${r.reported} | ${r.unmatched} | ${prec} | ${r.calls} | ${(r.wallMs / 1000).toFixed(1)} |`);
248
+ const relaxed = r.recallRelaxed === undefined ? '—' : pct(r.recallRelaxed);
249
+ L.push(`| ${r.arm} | ${pct(r.recall)} | ${relaxed} | ${pct(r.recallMacro)} | ${r.matched}/${r.seeded} | ${r.reported} | ${r.unmatched} | ${prec} | ${r.calls} | ${(r.wallMs / 1000).toFixed(1)} |`);
247
250
  }
248
251
  L.push('');
249
252
  L.push('Precision "—" = not yet adjudicated (label false positives with `aiki resolve <run>`).');