aiki-cli 0.3.2 → 0.3.3
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 +68 -0
- package/README.md +64 -4
- package/dist/bench/idea-v3-bench.js +104 -5
- package/dist/bench/idea-v3-rating.js +158 -3
- package/dist/cli/bench.js +5 -5
- package/dist/cli/index.js +12 -2
- package/dist/cli/resume.js +20 -0
- package/dist/cli/run.js +75 -4
- package/dist/cli/serve.js +48 -0
- package/dist/config/config.js +7 -2
- package/dist/council/view.js +13 -4
- package/dist/orchestration/auto-profile.js +97 -0
- package/dist/orchestration/claim-groups.js +56 -0
- package/dist/orchestration/context.js +66 -3
- package/dist/orchestration/decision-dossier.js +42 -10
- package/dist/orchestration/decision-graph.js +2 -2
- package/dist/orchestration/engine.js +8 -4
- package/dist/orchestration/evidence-origin.js +17 -0
- package/dist/orchestration/jsonStage.js +47 -5
- package/dist/orchestration/modes.js +4 -2
- package/dist/orchestration/preflight.js +19 -0
- package/dist/orchestration/quick-analysis.js +8 -3
- package/dist/orchestration/sanitize-paths.js +10 -0
- package/dist/orchestration/stages/s10-render.js +31 -7
- package/dist/orchestration/stages/s4-analyze.js +7 -1
- package/dist/orchestration/stages/s4b-challenge.js +97 -0
- package/dist/orchestration/stages/s5-drift.js +13 -3
- package/dist/orchestration/stages/s8-verify.js +44 -7
- package/dist/orchestration/stages/s9-judge.js +20 -5
- package/dist/orchestration/stages/s9b-plan.js +44 -15
- package/dist/orchestration/url-sources.js +21 -0
- package/dist/providers/adapter-core.js +1 -1
- package/dist/providers/claude.js +18 -0
- package/dist/schemas/index.js +45 -0
- package/dist/serve/flight-deck.js +830 -0
- package/dist/serve/followup.js +50 -0
- package/dist/serve/frames.js +168 -0
- package/dist/serve/gates.js +72 -0
- package/dist/serve/projections.js +283 -0
- package/dist/serve/server.js +219 -0
- package/dist/serve/threads.js +145 -0
- package/dist/serve-ui/Five.png +0 -0
- package/dist/serve-ui/app.js +820 -0
- package/dist/serve-ui/index.html +171 -0
- package/dist/serve-ui/workspace.css +662 -0
- package/dist/storage/runs.js +2 -1
- package/dist/workflows/idea-refinement.js +94 -16
- package/package.json +2 -2
package/dist/storage/runs.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
// an invalid payload throws and writes nothing.
|
|
13
13
|
import { mkdir, rename, writeFile } from 'node:fs/promises';
|
|
14
14
|
import { dirname, join } from 'node:path';
|
|
15
|
-
import { ActionPlanArtifact, DecisionContractArtifact, DecisionGraph, DisagreementMap, IdeaRoleOutput, JudgeReport, PreflightArtifact, RebuttalEventSet, ReviewMap, RoleOutput, RunBrief, RunMeta, UrlSourceSet, VerificationArtifact } from '../schemas/index.js';
|
|
15
|
+
import { ActionPlanArtifact, ChallengeDeltaSet, DecisionContractArtifact, DecisionGraph, DisagreementMap, IdeaRoleOutput, JudgeReport, PreflightArtifact, RebuttalEventSet, ReviewMap, RoleOutput, RunBrief, RunMeta, UrlSourceSet, VerificationArtifact } from '../schemas/index.js';
|
|
16
16
|
export class OutOfOrderWriteError extends Error {
|
|
17
17
|
constructor(slot, ord, maxOrd) {
|
|
18
18
|
super(`out-of-order write: "${slot}" (stage ${ord}) after stage ${maxOrd} already written`);
|
|
@@ -33,6 +33,7 @@ const JSON_SLOTS = {
|
|
|
33
33
|
'intent-contract': { ord: 1, path: '01-intent-contract.json', schema: DecisionContractArtifact },
|
|
34
34
|
'preflight-readings': { ord: 2, path: '02-preflight-readings.json', schema: PreflightArtifact },
|
|
35
35
|
'misunderstanding-guard': { ord: 2, path: '02-misunderstanding-guard.json', schema: null },
|
|
36
|
+
'challenge-deltas': { ord: 4.5, path: '04b-challenge-deltas.json', schema: ChallengeDeltaSet },
|
|
36
37
|
'drift-report': { ord: 5, path: '05-drift-report.json', schema: null },
|
|
37
38
|
positions: { ord: 6, path: '06-positions.json', schema: null },
|
|
38
39
|
'coverage-fill': { ord: 6.5, path: '06b-coverage-fill.json', schema: IdeaRoleOutput },
|
|
@@ -7,15 +7,19 @@ import { s5Drift } from '../orchestration/stages/s5-drift.js';
|
|
|
7
7
|
import { s6Positions } from '../orchestration/stages/s6-positions.js';
|
|
8
8
|
import { s7DecisionGraph } from '../orchestration/stages/s7-decision-graph.js';
|
|
9
9
|
import { s8Verify } from '../orchestration/stages/s8-verify.js';
|
|
10
|
+
import { overlayClaimGroups } from '../orchestration/claim-groups.js';
|
|
10
11
|
import { s8bRebuttal } from '../orchestration/stages/s8b-rebuttal.js';
|
|
11
12
|
import { s9Judge } from '../orchestration/stages/s9-judge.js';
|
|
12
13
|
import { s9bPlan } from '../orchestration/stages/s9b-plan.js';
|
|
13
14
|
import { s10Render } from '../orchestration/stages/s10-render.js';
|
|
14
15
|
import { loadSkill } from '../orchestration/skills.js';
|
|
15
16
|
import { buildLanePrompts } from '../orchestration/idea-lanes.js';
|
|
16
|
-
import { preflight, renderDecisionInput } from '../orchestration/preflight.js';
|
|
17
|
-
import { buildQuickPrompt, quickActionPlan, quickJudgeReport, s4QuickAnalyze } from '../orchestration/quick-analysis.js';
|
|
18
|
-
import { snapshotUrlSources } from '../orchestration/url-sources.js';
|
|
17
|
+
import { deterministicContract, preflight, renderDecisionInput } from '../orchestration/preflight.js';
|
|
18
|
+
import { buildAdaptivePrompt, buildQuickPrompt, quickActionPlan, quickJudgeReport, s4QuickAnalyze } from '../orchestration/quick-analysis.js';
|
|
19
|
+
import { blockedSourceStop, snapshotUrlSources } from '../orchestration/url-sources.js';
|
|
20
|
+
import { compileDecisionGraph } from '../orchestration/decision-graph.js';
|
|
21
|
+
import { structuralEscalationGates } from '../orchestration/auto-profile.js';
|
|
22
|
+
import { overlayChallengeDeltas, s4bChallenge } from '../orchestration/stages/s4b-challenge.js';
|
|
19
23
|
/** Idea-vetting core rubric: 13 mandatory coverage items. S0 adds 3-5 domain dimensions per run.
|
|
20
24
|
* Inlined here (like the S4 template) while the skill/`rubric.json` loader (§11)
|
|
21
25
|
* is deferred; it moves to skills/idea-refinement/rubric.json when that loader lands. */
|
|
@@ -139,25 +143,96 @@ export function recordIdeaOutcomeFlags(ctx, contract, seats) {
|
|
|
139
143
|
export async function runIdeaRefinement(ctx, input) {
|
|
140
144
|
if (ctx.evidencePack)
|
|
141
145
|
await ctx.writer.writeInput('evidence-pack.json', JSON.stringify(ctx.evidencePack, null, 2));
|
|
142
|
-
|
|
146
|
+
// v6 T10b: the CLI may have already snapshotted (and interactively cleared) the sources.
|
|
147
|
+
const urlSources = ctx.urlSources ?? await snapshotUrlSources(input);
|
|
143
148
|
await ctx.writer.writeJson('url-sources', urlSources);
|
|
144
149
|
const unreadableSources = urlSources.sources.filter((source) => source.status !== 'FETCHED');
|
|
145
150
|
const needsSourceFallback = ctx.mode !== 'quick' && unreadableSources.length > 0;
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
throw new StageError('S0', 'SOURCE_UNREADABLE', `source investigation stopped before model calls
|
|
151
|
+
// v6 T10: ANY unreadable supplied source stops the run before paid calls unless the user
|
|
152
|
+
// explicitly proceeds (--allow-blocked-sources). Codex search no longer silences the ask —
|
|
153
|
+
// it runs in addition, once the user has chosen to proceed.
|
|
154
|
+
const stop = blockedSourceStop(urlSources, ctx.mode, ctx.allowBlockedSources ?? false);
|
|
155
|
+
if (stop)
|
|
156
|
+
throw new StageError('S0', 'SOURCE_UNREADABLE', `source investigation stopped before model calls: ${stop}`);
|
|
157
|
+
let contract;
|
|
158
|
+
let grilledInput;
|
|
159
|
+
if (ctx.fastPath) {
|
|
160
|
+
contract = await runStage(ctx, 'S0', async () => {
|
|
161
|
+
return deterministicContract(input, IDEA_RUBRIC.map((item) => item.label));
|
|
162
|
+
});
|
|
163
|
+
ctx.addFlag('headless_intent');
|
|
164
|
+
grilledInput = input;
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
const result = await runStage(ctx, 'S0', () => preflight(ctx, input, IDEA_RUBRIC.map((item) => item.label), urlSources));
|
|
168
|
+
contract = result.contract;
|
|
169
|
+
grilledInput = renderDecisionInput(input, result.brief, urlSources);
|
|
152
170
|
}
|
|
153
|
-
const { contract, brief } = await runStage(ctx, 'S0', () => preflight(ctx, input, IDEA_RUBRIC.map((item) => item.label), urlSources));
|
|
154
|
-
const grilledInput = renderDecisionInput(input, brief, urlSources);
|
|
155
171
|
// Persist the input as a file so S4's "read the file at {{INPUT_PATH}}" resolves (not a stage).
|
|
156
172
|
await ctx.writer.writeInput('idea.md', input);
|
|
157
173
|
await ctx.writer.writeInput('idea-brief.md', grilledInput);
|
|
158
174
|
const inputPath = resolve(ctx.writer.dir, 'inputs', 'idea-brief.md');
|
|
159
175
|
const rubric = buildIdeaRubric(contract.domain_dimensions);
|
|
160
176
|
const analystSkill = loadSkill('idea-refinement', 'analyst');
|
|
177
|
+
if (ctx.isAuto) {
|
|
178
|
+
ctx.addFlag('single_model');
|
|
179
|
+
const startedFast = ctx.fastPath;
|
|
180
|
+
const primaryPrompt = startedFast
|
|
181
|
+
? buildQuickPrompt(contract, inputPath, ctx.evidencePack, analystSkill)
|
|
182
|
+
: buildAdaptivePrompt(contract, inputPath, ctx.evidencePack, analystSkill);
|
|
183
|
+
if (!startedFast)
|
|
184
|
+
await ctx.writer.writePrompt('auto-primary.md', primaryPrompt);
|
|
185
|
+
const quick = await runStage(ctx, 'S4', () => s4QuickAnalyze(ctx, primaryPrompt, {
|
|
186
|
+
persist: !startedFast,
|
|
187
|
+
stage: startedFast ? 'Q1' : 'S4-auto-primary',
|
|
188
|
+
}));
|
|
189
|
+
const provisional = compileDecisionGraph([{ provider: quick.seat.provider, submission: quick.seat.output }], rubric);
|
|
190
|
+
const gates = structuralEscalationGates(provisional);
|
|
191
|
+
if (gates.length) {
|
|
192
|
+
ctx.markAutoEscalated(gates.map((gate) => gate.reason));
|
|
193
|
+
if (startedFast) {
|
|
194
|
+
const result = await runStage(ctx, 'S0-auto', () => preflight(ctx, input, IDEA_RUBRIC.map((item) => item.label), urlSources));
|
|
195
|
+
contract = result.contract;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (startedFast) {
|
|
199
|
+
if (gates.length === 0)
|
|
200
|
+
await ctx.writer.writeJson('intent-contract', contract);
|
|
201
|
+
await ctx.writer.writePrompt('quick-analyst.md', primaryPrompt);
|
|
202
|
+
await ctx.writer.writeRoleOutput(quick.seat.provider, quick.seat.output);
|
|
203
|
+
}
|
|
204
|
+
const challenge = gates.length
|
|
205
|
+
? await runStage(ctx, 'S4b', () => s4bChallenge(ctx, provisional, gates, quick.seat.provider))
|
|
206
|
+
: { deltas: [] };
|
|
207
|
+
const { kept } = await runStage(ctx, 'S5', () => s5Drift(ctx, contract, [quick.seat], 1));
|
|
208
|
+
if (ctx.mode !== 'quick')
|
|
209
|
+
recordIdeaOutcomeFlags(ctx, contract, kept);
|
|
210
|
+
const positions = await runStage(ctx, 'S6', () => s6Positions(ctx, kept));
|
|
211
|
+
const graph = await runStage(ctx, 'S7', () => s7DecisionGraph(ctx, positions, rubric, contract.task));
|
|
212
|
+
const challenged = overlayChallengeDeltas(graph, challenge.deltas);
|
|
213
|
+
const verifications = await runStage(ctx, 'S8', async () => {
|
|
214
|
+
const result = { verifications: [] };
|
|
215
|
+
await ctx.writer.writeJson('verifications', result);
|
|
216
|
+
return result;
|
|
217
|
+
});
|
|
218
|
+
const rebuttals = await runStage(ctx, 'S8b', async () => {
|
|
219
|
+
const result = { round: 1, selected_claim_ids: [], events: [], stop_reason: 'NO_ESCALATIONS' };
|
|
220
|
+
await ctx.writer.writeJson('rebuttals', result);
|
|
221
|
+
return result;
|
|
222
|
+
});
|
|
223
|
+
const judgeReport = await runStage(ctx, 'S9', async () => {
|
|
224
|
+
const report = quickJudgeReport(quick.decision, challenged);
|
|
225
|
+
await ctx.writer.writeJson('judge-report', report);
|
|
226
|
+
return report;
|
|
227
|
+
});
|
|
228
|
+
const actionPlan = await runStage(ctx, 'S9b', async () => {
|
|
229
|
+
const plan = quickActionPlan(ctx, quick.seat.provider, quick.decision, challenged, contract);
|
|
230
|
+
await ctx.writer.writeJson('action-plan', plan);
|
|
231
|
+
return plan;
|
|
232
|
+
});
|
|
233
|
+
await runStage(ctx, 'S10', () => s10Render(ctx, { contract, seats: kept, graph: challenged, verifications, rebuttals, judgeReport, actionPlan, rubric, original: input }));
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
161
236
|
if (ctx.mode === 'quick') {
|
|
162
237
|
ctx.addFlag('single_model');
|
|
163
238
|
const quickPrompt = buildQuickPrompt(contract, inputPath, ctx.evidencePack, analystSkill);
|
|
@@ -198,8 +273,11 @@ export async function runIdeaRefinement(ctx, input) {
|
|
|
198
273
|
const positions = await runStage(ctx, 'S6', () => s6Positions(ctx, kept));
|
|
199
274
|
const graph = await runStage(ctx, 'S7', () => s7DecisionGraph(ctx, positions, rubric, contract.task));
|
|
200
275
|
const verifications = await runStage(ctx, 'S8', () => s8Verify(ctx, graph));
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
const
|
|
204
|
-
await runStage(ctx, '
|
|
276
|
+
// v6 semantic join: S8's validated claim_groups upgrade cross-provider paraphrase states
|
|
277
|
+
// (UNIQUE → CONSENSUS/DISAGREEMENT/…) on a derived copy; the stored 07 artifact stays original.
|
|
278
|
+
const joined = overlayClaimGroups(graph, verifications.claim_groups);
|
|
279
|
+
const rebuttals = await runStage(ctx, 'S8b', () => s8bRebuttal(ctx, joined, verifications, ctx.mode));
|
|
280
|
+
const judgeReport = await runStage(ctx, 'S9', () => s9Judge(ctx, contract, joined, verifications, rubric, rebuttals));
|
|
281
|
+
const actionPlan = await runStage(ctx, 'S9b', () => s9bPlan(ctx, contract, kept, joined, judgeReport, input));
|
|
282
|
+
await runStage(ctx, 'S10', () => s10Render(ctx, { contract, seats: kept, graph: joined, verifications, rebuttals, judgeReport, actionPlan, rubric, original: input }));
|
|
205
283
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aiki-cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "Local-first AI model council for code review and idea stress-testing using Claude Code, Codex, and Gemini/Antigravity CLIs. No API keys.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"node": ">=20"
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
|
-
"build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.json && node -e \"require('fs').copyFileSync('src/providers/profiles.json','dist/providers/profiles.json')\" && node -e \"require('fs').cpSync('src/skills','dist/skills',{recursive:true})\"",
|
|
48
|
+
"build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.json && node -e \"require('fs').copyFileSync('src/providers/profiles.json','dist/providers/profiles.json')\" && node -e \"require('fs').cpSync('src/skills','dist/skills',{recursive:true})\" && node -e \"require('fs').cpSync('serve-ui','dist/serve-ui',{recursive:true})\"",
|
|
49
49
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
50
50
|
"test": "vitest run",
|
|
51
51
|
"test:watch": "vitest",
|