aiki-cli 0.2.2 → 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.
Files changed (59) hide show
  1. package/CHANGELOG.md +98 -7
  2. package/README.md +109 -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 +63 -8
  17. package/dist/council/view.js +378 -109
  18. package/dist/orchestration/calculations.js +97 -0
  19. package/dist/orchestration/context.js +37 -9
  20. package/dist/orchestration/decision-dossier.js +262 -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 +33 -0
  28. package/dist/orchestration/preflight.js +183 -0
  29. package/dist/orchestration/quick-analysis.js +81 -0
  30. package/dist/orchestration/stages/cr-ladder.js +80 -0
  31. package/dist/orchestration/stages/s10-render.js +562 -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 +85 -75
  40. package/dist/providers/codex.js +2 -1
  41. package/dist/providers/spawn.js +5 -0
  42. package/dist/schemas/index.js +572 -13
  43. package/dist/skills/idea-refinement/analyst.md +18 -14
  44. package/dist/skills/idea-refinement/economics-delivery.md +7 -0
  45. package/dist/skills/idea-refinement/market-adoption.md +7 -0
  46. package/dist/storage/runs.js +11 -4
  47. package/dist/tui/app.js +37 -13
  48. package/dist/tui/format.js +4 -5
  49. package/dist/tui/smart-entry.js +17 -1
  50. package/dist/tui/timeline.js +2 -4
  51. package/dist/workflows/code-review.js +4 -2
  52. package/dist/workflows/idea-refinement.js +110 -46
  53. package/package.json +12 -4
  54. package/dist/orchestration/stages/s0-grill.js +0 -79
  55. package/dist/orchestration/stages/s1-intent.js +0 -25
  56. package/dist/orchestration/stages/s2-misread.js +0 -76
  57. package/dist/orchestration/stages/s3-prompts.js +0 -55
  58. package/dist/orchestration/stages/s6-claims.js +0 -56
  59. package/dist/orchestration/stages/s7-disagreement.js +0 -134
package/CHANGELOG.md CHANGED
@@ -1,23 +1,114 @@
1
1
  # Changelog
2
2
 
3
- ## Unreleased
3
+ ## 0.3.0 — 2026-07-15 — evidence-grounded decision council
4
+
5
+ This release turns idea refinement into a bounded, evidence-linked decision workflow with explicit modes,
6
+ selective rebuttal, a reader-first dossier, and stronger recovery from malformed provider output. The frozen
7
+ code-review result remains unchanged: 100% vs 77% seeded-bug recall at equal precision on the pre-registered
8
+ 10-case holdout. The idea-v3 evaluation harness ships here, but its paid benchmark is still pending and no
9
+ idea-quality lift is claimed yet.
4
10
 
5
11
  ### 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.
12
+ - **Explicit idea modes and adaptive budgets (R6)** `aiki run idea-refinement --mode
13
+ quick|council|research` defaults to council without a learned router. Quick is one structured analyst and
14
+ never presents itself as a council; council uses a 6-call base with at most two graph-triggered extras;
15
+ research permits up to four extras and enables the verified `codex --search exec ...` capability only on
16
+ Codex scout calls while retaining `-s read-only`. Mode-aware defaults are 4/10/12 calls respectively.
17
+ - **Two-view decision preflight (R6)** — two readings run in parallel and deterministically merge into one
18
+ user-confirmed or visibly headless/defaulted decision contract. The old S1/S2/S3 model calls are gone;
19
+ analyst prompts are filled deterministically. Receipts split calls into discovery, verification, repair,
20
+ and planning, and resume preserves the original mode.
21
+ - **Evidence and calculation integrity (R4)** — idea runs accept `--evidence <file|directory>` and persist
22
+ only source paths + SHA-256 hashes; evidence cards enforce source/freshness rules; derived numeric claims
23
+ can carry a pure arithmetic ledger whose values/units are recomputed; S8 emits typed claim verification;
24
+ and invalid evidence references are rejected before the chair call.
25
+ - **Selective rebuttal and evidence-linked chair (R5)** — only verdict-flipping graph nodes enter one
26
+ anonymous rebuttal round; council coverage-fill and rebuttal share a two-call cap while chair/planner
27
+ budget stays reserved; responses append as immutable `08b-rebuttals.json` events; and the chair must emit
28
+ graph-linked rulings, recommendation reasons, conditions, pivots, and strongest counter-cases. A judge-
29
+ authored node is excluded before the chair prompt and remains unresolved under degradation.
30
+ - **Startup preflight** — typing bare `aiki` now runs the full doctor before the home screen: per-provider
31
+ progress rows checking CLI presence, version, and auth/quota (smoke, cached 6h). Fewer than 2 providers
32
+ ready shows a failure screen with the exact fix per provider; a single degraded provider shows a warning
33
+ on the home screen and the council continues with the remaining quorum.
34
+ - **Idea-lane bench resume** — `aiki bench idea-refinement --set build --resume [--yes]` continues the
35
+ latest campaign file in `bench/results/`: completed case×rotation pairs are kept (never re-paid), missing
36
+ or failed pairs re-run, and new observations append to the same file. The dry-run estimate reflects only
37
+ what is left to run. `--case <id>` restricts the metered run to one build case (an unknown id fails loud
38
+ with the list of valid cases), and a run that completes `low_diversity` (a scout seat died mid-run) is
39
+ rejected instead of being recorded — it is not a valid rotation sample.
40
+ - **Adjudication import** — `aiki bench idea-refinement --import <file>` (offline, no provider calls)
41
+ imports blind adjudications: each `{ case_id, rotation, adjudication }` entry flows through the frozen R0
42
+ scorer and fills that pair's null recall/precision in the campaign file. Unknown pairs fail loud;
43
+ re-scoring an already-scored pair is refused (blind adjudication is one pass); when every pair is scored
44
+ it prints the lane default selection.
9
45
  - **Idea report v3** — idea-refinement reports now emit an explicit BLUF recommendation
10
46
  (`PROCEED`, `PROCEED_WITH_CONDITIONS`, `PIVOT`, `STOP`), conditions when needed, a best-effort
11
47
  12-dimension scorecard, assumption audit table in HTML, deterministic debate narrative, anchored
12
48
  validation plan with kill signals (`09b-action-plan.json`), open questions, red-team note, and a
13
49
  call/provider receipt. The Markdown copy button includes the expanded brief.
50
+ - **R7 decision dossier** — `10-decision-report.json` now persists the graph-anchored recommendation chain,
51
+ evidence source/date/freshness/verification table, genuine disagreement and append-only position-change
52
+ events, coverage and sensitivity ledgers, executable experiments, strongest counter-case, strictly
53
+ verified unique-provider contributions, categorized receipt, and technical graph fold. Final Markdown,
54
+ HTML, and Copy-Markdown render from that same dossier; R6-era and older runs retain their legacy HTML. It
55
+ provides the canonical report foundation refined by the reader-first snapshot below.
56
+ - **Reader-first decision snapshot (report v3.1)** — terminal, Markdown, and HTML lead with the council
57
+ recommendation, independently verified evidence coverage, decisive facts, first action, strongest
58
+ counter-case, and three critical unknowns. Financial and threshold-heavy chairs can emit strict
59
+ graph-anchored decisive numbers, explicit payback, option commitments marked `KNOWN`, `TARGET_CAP`, or
60
+ `UNKNOWN`, and one go/no-go tripwire. Invalid claim anchors remove the snapshot instead of presenting
61
+ unsupported numbers.
62
+ - **Idea-v3 benchmark harness** — the frozen B/C/D2/R protocol now has an eight-case build set, a
63
+ 12-case/tag/provenance holdout contract that remains closed until freeze, checkpoint/resume for successes
64
+ and failures, isolated baseline-provider campaigns, three independently shuffled blind-rating packets,
65
+ one-pass scoring, and hash-locked freeze and holdout guards. Build tuning, blind ratings, and the paid
66
+ holdout evaluation remain pending.
14
67
 
15
68
  ### 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.
69
+ - **Three-level decision report** idea-refinement's final report is restructured: (1) a one-screen
70
+ terminal summary (recommendation, decision state, verified evidence coverage, decisive result, dissent,
71
+ next action, and optional tripwire) printed after `aiki run`; (2) a 10-section reader-first graph-backed
72
+ Decision Report markdown (`final-report.md`) ordered as decision, action plan, reasoning, what could change
73
+ the decision, evidence, risks/gaps, dissent, council value, run details, and technical audit; (3)
74
+ machine-readable `10-decision-report.json` that Markdown and HTML render from, so the
75
+ surfaces cannot disagree. Statuses are ACCEPTED / ACCEPTED_WITH_CONDITIONS / INCONCLUSIVE / REJECTED
76
+ (mapped from the judge's recommendation). The structural score is moved behind technical detail and never
77
+ presented as decision accuracy: 40% verification coverage + 25%
78
+ independent convergence + 20% evidence quality + 15% stability − critical-risk penalty; model
79
+ self-confidence never enters it and consensus alone can never reach the High band. Labeled a heuristic in
80
+ the report until benchmark-calibrated.
81
+ - Idea-refinement estimates are mode-aware: quick ≈3 calls / 1 Claude-Opus; council 6–8 / ~2 Opus; research
82
+ 8–10 / ~2 Opus. Chair and planner calls are reserved before optional graph work.
83
+ - **Mode-aware time limits** — quick and council retain a 20-minute run deadline; research uses 45 minutes.
84
+ The per-provider-call ceiling is 15 minutes, so legitimate deep scout work can finish while the overall
85
+ deadline still bounds the run.
19
86
 
20
87
  ### Fixed
88
+ - Idea analyst outputs now canonicalize observed Gemini evidence-enum variants before strict validation:
89
+ freshness accepts case-insensitive canonical words, while evidence support accepts a leading known token
90
+ (`SUPPORT`, `OPPOSE`, or `OPPOSES`) and maps it to the canonical enum. Arbitrary prose and unknown values
91
+ still fail the schema boundary.
92
+ - A failed S4 repair no longer kills the run for recoverable shape damage: deterministic salvage strips
93
+ unknown keys, drops invalid evidence/calculation/coverage/question entries, removes only individually
94
+ invalid positions, and scrubs their references. It never invents content and an empty claim set remains
95
+ fatal. The same fallback applies when the repair call itself dies (for example, quota).
96
+ - All schema-validated model stages now attempt lossless coercion before a paid repair (for example, wrapping
97
+ a lone array item) and bounded lossy coercion only after repair failure (for example, truncating beyond a
98
+ declared maximum). The full zod schema still decides whether data may cross the stage boundary.
99
+ - Provider timeouts now resolve immediately after killing the process group and unref a surviving detached
100
+ child, preventing one escaped subprocess from blocking the CLI long after the configured timeout.
101
+ - Idea prose containing ordinary words such as `class`, `export`, or `import` no longer misroutes to code
102
+ review; routing now requires actual code structure such as a diff, fence, code file path, declaration, or
103
+ import/export syntax.
104
+ - Decisive warnings no longer echo an unresolved affirmative claim as reassurance, and the calculation
105
+ checker now canonicalizes ordinary plurals, dimensionless ratios, and currency-margin units without
106
+ weakening arithmetic validation.
107
+ - Benchmark safeguards now redact receipt costs and degradation tokens from blind packets, refuse accidental
108
+ same-day campaign overwrites, and honor the frozen baseline provider when a holdout run does not pass an
109
+ explicit override.
110
+ - Release builds now clean `dist/` before compiling, so removed stages cannot survive as stale JavaScript in
111
+ the npm tarball.
21
112
  - Codex provider smoke no longer crashes in non-git folders; Aiki now passes Codex's verified
22
113
  `--skip-git-repo-check` flag while keeping `-s read-only`.
23
114
  - `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 explicit modes.** Use `quick` for one structured analyst, `council` for bounded multi-model
54
+ deliberation, or `research` for current-fact work with Codex search. Aiki never hides this choice behind a
55
+ learned router.
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,10 @@ 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
+
181
252
  ## The two workflows
182
253
 
183
254
  <p align="center">
@@ -188,17 +259,23 @@ An idea run **auto-opens** its report in your browser when it finishes.
188
259
  real line in the diff) → mutual adversarial cross-examination → consensus/dispute map → the judge adjudicates
189
260
  only the disputes → report.
190
261
 
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)
262
+ **Idea refinement** — two independent preflight readings one confirmed/defaulted decision contract
263
+ complementary analyst lanes deterministic claim/evidence graph auditonly decision-critical verification
264
+ or rebuttal evidence-linked chair → validation planner. The report is a graph-backed **decision dossier**,
265
+ not an essay.
266
+ Choose `--mode quick` for one structured analyst, `--mode council` (default) for the full decision council,
267
+ or `--mode research` for source-grounded current-fact work. Aiki never chooses a mode with a learned router:
268
+
269
+ - a **reader-first decision card** recommendation, verified evidence coverage, decisive facts, first action,
270
+ strongest counter-case, and critical unknowns before audit detail
271
+ - a **numeric decision snapshot when relevant** — graph-anchored decisive numbers, explicit payback, option
272
+ commitments labeled `KNOWN` / `TARGET_CAP` / `UNKNOWN`, and a go/no-go tripwire
273
+ - a **graph-anchored recommendation and claim chain** — every decisive statement links to stored claim IDs
274
+ - an **evidence and coverage ledger** — source, date, freshness, verification, `NOT_APPLICABLE`, and missing evidence
275
+ - **genuine disagreements and position changes** — explicit `CONCEDE` / `COUNTER` / `NARROW` events
276
+ - **decision sensitivity and an executable experiment plan** — anchored tests with effort and kill signals
277
+ - a **verified contribution ledger** — unique provider claims count only after independent verification
278
+ - an **orchestration receipt and technical fold** — calls, degradation, submissions, edges, and graph events
202
279
 
203
280
  ## Example: a real idea run
204
281
 
@@ -218,7 +295,8 @@ The council's verdict on that one:
218
295
 
219
296
  …followed by **7 anchored validation actions**, e.g. *"Pull the last 90 days of churned users and tag each
220
297
  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.
298
+ your browser and has a **Copy report (Markdown)** button backed by the same persisted dossier as the HTML,
299
+ so the copied claims, evidence statuses, experiments, and receipt cannot drift from the page.
222
300
 
223
301
  ## Configuration
224
302
 
@@ -271,9 +349,10 @@ This is the part that makes aiki trustworthy to point at a real repo:
271
349
 
272
350
  ## Costs & limits
273
351
 
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`).
352
+ - **Runs cost real model calls** against your existing CLI subscriptions/quota. Idea refinement is nominally
353
+ **3 calls in quick**, **6–8 in council**, or **8–10 in research** (schema repairs can add calls within the
354
+ mode-aware budget); code review is about **5**. `aiki run` shows the mode, range, budget, and reserved
355
+ chair/planner calls before asking to confirm (skip with `--yes`).
277
356
  - **Not a general assistant.** Questions and "explore my whole codebase" requests are redirected, not answered
278
357
  — aiki reviews a *diff* and vets a *stated idea*.
279
358
  - **Analysis, not advice.** Every report is a decision aid. Verify before acting.
@@ -287,7 +366,7 @@ This is the part that makes aiki trustworthy to point at a real repo:
287
366
  - Anywhere else → `~/.aiki/`. `$AIKI_HOME` overrides the global home.
288
367
  - The global session registry always lives in `~/.aiki/`.
289
368
 
290
- ## How it works
369
+ ## Implementation notes
291
370
 
292
371
  Every stage is a small, independently-testable unit with a zod-validated output contract. Model text lives in
293
372
  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>`).');