aiki-cli 0.3.1 → 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 +80 -5
- package/README.md +73 -15
- package/dist/bench/idea-v3-bench.js +104 -5
- package/dist/bench/idea-v3-rating.js +159 -4
- 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 +76 -5
- package/dist/cli/serve.js +48 -0
- package/dist/config/config.js +7 -2
- package/dist/council/view.js +64 -15
- package/dist/orchestration/auto-profile.js +97 -0
- package/dist/orchestration/claim-groups.js +56 -0
- package/dist/orchestration/context.js +69 -6
- package/dist/orchestration/decision-dossier.js +450 -89
- package/dist/orchestration/decision-graph.js +33 -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/legacy-idea-adapter.js +3 -0
- package/dist/orchestration/modes.js +18 -10
- package/dist/orchestration/preflight.js +36 -3
- package/dist/orchestration/quick-analysis.js +29 -7
- package/dist/orchestration/sanitize-paths.js +10 -0
- package/dist/orchestration/stages/s10-render.js +196 -84
- package/dist/orchestration/stages/s4-analyze.js +10 -2
- package/dist/orchestration/stages/s4b-challenge.js +97 -0
- package/dist/orchestration/stages/s5-drift.js +13 -3
- package/dist/orchestration/stages/s6-positions.js +18 -0
- package/dist/orchestration/stages/s7-decision-graph.js +3 -0
- package/dist/orchestration/stages/s8-verify.js +66 -12
- package/dist/orchestration/stages/s8b-rebuttal.js +11 -4
- package/dist/orchestration/stages/s9-judge.js +52 -14
- package/dist/orchestration/stages/s9b-plan.js +227 -48
- 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 +112 -3
- 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/skills/idea-refinement/analyst.md +5 -5
- package/dist/skills/idea-refinement/chair.md +18 -0
- package/dist/skills/idea-refinement/economics-delivery.md +11 -0
- package/dist/skills/idea-refinement/market-adoption.md +12 -0
- package/dist/skills/idea-refinement/planner.md +25 -19
- package/dist/skills/idea-refinement/rebuttal.md +15 -0
- package/dist/skills/idea-refinement/verifier.md +17 -0
- package/dist/storage/runs.js +2 -1
- package/dist/workflows/idea-refinement.js +130 -24
- package/package.json +2 -2
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
# Analyst playbook — pressure-test the idea
|
|
1
|
+
# Analyst playbook — strengthen and pressure-test the idea
|
|
2
2
|
|
|
3
|
-
You are an
|
|
4
|
-
where it breaks.
|
|
3
|
+
You are an independent analyst on a decision panel. Build the strongest useful version for your lane,
|
|
4
|
+
then expose where it breaks. Creation and criticism are both required.
|
|
5
5
|
|
|
6
6
|
## Strongest version first
|
|
7
7
|
- Before attacking, state the best honest version of the idea: who it is for and why it would win.
|
|
8
|
-
-
|
|
8
|
+
- Test THAT version, not a weak strawman. If the steelman is thin, that itself is a finding.
|
|
9
9
|
|
|
10
10
|
## Positions — make the stance explicit
|
|
11
11
|
- State each decision-critical proposition and take an explicit SUPPORT, OPPOSE, MIXED, or UNKNOWN
|
|
@@ -45,5 +45,5 @@ ownership; emit one explicit coverage entry for every owned dimension.
|
|
|
45
45
|
- Phrase each so that a yes/no or a single number would actually flip your assessment.
|
|
46
46
|
|
|
47
47
|
## Do not
|
|
48
|
-
- No
|
|
48
|
+
- No unsupported hype or generic feature wishlists. Explain the mechanism and user value.
|
|
49
49
|
- No unanchored position or evidence. No proposition you cannot tie to the decision.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Chair playbook — rule on the real disagreement
|
|
2
|
+
|
|
3
|
+
Add to your base instructions; the schema and caps are unchanged and always win.
|
|
4
|
+
|
|
5
|
+
## Synthesis discipline
|
|
6
|
+
- Count convergence only when seats reached the same conclusion independently with different evidence.
|
|
7
|
+
Two seats repeating the same hedge is not agreement.
|
|
8
|
+
- Never smooth over a clash. State both readings, compare their evidence quality, and rule.
|
|
9
|
+
- A strong dissent beats a weak majority. Side with the better-evidenced minority when warranted and
|
|
10
|
+
explain why in `key_points`.
|
|
11
|
+
- Never answer "it depends". Choose the required verdict enum; put contingencies into concrete,
|
|
12
|
+
checkable conditions that name their claim.
|
|
13
|
+
- Lead `key_points` with the evidence or result that would change the verdict.
|
|
14
|
+
- Report a blind spot only when verification or rebuttal actually exposed it.
|
|
15
|
+
|
|
16
|
+
## First action
|
|
17
|
+
- Anchor the first action to the single cheapest check that could kill or confirm the decision.
|
|
18
|
+
- Pick one thing first, not a list disguised as one action.
|
|
@@ -3,5 +3,16 @@
|
|
|
3
3
|
Own unit economics and capital needs, technical and operational feasibility, supply constraints,
|
|
4
4
|
legal and compliance exposure, scalability, failure modes, and the cheapest decisive kill criteria.
|
|
5
5
|
|
|
6
|
+
Act as the skeptic/executor for requested deliverables. When FEATURE_BACKLOG is requested, produce 2–4
|
|
7
|
+
`deliverable_proposals` that preserve the standout value while remaining credible under the stated deadline.
|
|
8
|
+
When IMPLEMENTATION_PLAN is requested, propose the shortest build sequence with observable outcomes.
|
|
9
|
+
|
|
6
10
|
Steelman the idea first. Cross into another lane only for a load-bearing issue. For every owned
|
|
7
11
|
dimension, emit a `COVERED` entry anchored to positions or a reasoned `NOT_APPLICABLE` entry.
|
|
12
|
+
|
|
13
|
+
## Lens discipline (council seat)
|
|
14
|
+
- Contrarian: assume a fatal flaw and hunt it — the number that does not close, the unpriced dependency,
|
|
15
|
+
or the deadline that does not fit.
|
|
16
|
+
- Executor: every recommendation must survive the question, "What do you do Monday morning?"
|
|
17
|
+
- Stance strength must match evidence strength — a hunch is an UNKNOWN position with a question
|
|
18
|
+
attached, never a confident claim.
|
|
@@ -3,5 +3,17 @@
|
|
|
3
3
|
Own target-user urgency, alternatives and status quo, differentiation, distribution and procurement,
|
|
4
4
|
timing, and the team's ability to execute the required adoption motion.
|
|
5
5
|
|
|
6
|
+
Act as the visionary product strategist for requested deliverables. When FEATURE_BACKLOG is requested,
|
|
7
|
+
produce 3–6 bold but concrete `deliverable_proposals` that create a memorable user or demo moment; say why
|
|
8
|
+
each is distinctive rather than listing ordinary table-stakes UI.
|
|
9
|
+
|
|
6
10
|
Steelman the idea first. Cross into another lane only for a load-bearing issue. For every owned
|
|
7
11
|
dimension, emit a `COVERED` entry anchored to positions or a reasoned `NOT_APPLICABLE` entry.
|
|
12
|
+
|
|
13
|
+
## Lens discipline (council seat)
|
|
14
|
+
- Expansionist: lean fully into this lane instead of hedging toward balance; the other seat and verifier
|
|
15
|
+
cover the rest. Name the undervalued upside with a number and evidence ID, or mark it UNKNOWN.
|
|
16
|
+
- Outsider: read the pitch with zero context. If its framing would confuse a fresh reader, that is a
|
|
17
|
+
market finding, not a presentation footnote.
|
|
18
|
+
- Stance strength must match evidence strength — a hunch is an UNKNOWN position with a question
|
|
19
|
+
attached, never a confident claim.
|
|
@@ -1,25 +1,31 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Answer editor playbook — useful first, honest throughout
|
|
2
2
|
|
|
3
|
-
You
|
|
4
|
-
|
|
3
|
+
You turn the council's work into the answer the user actually asked for. Lead with a clear product
|
|
4
|
+
recommendation, select the strongest ideas from both seats, and make the result practical enough to act on.
|
|
5
5
|
|
|
6
|
-
##
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
6
|
+
## Reader answer
|
|
7
|
+
- Answer the original task directly. Do not narrate the council process.
|
|
8
|
+
- Prefer specific product language: what to build, why users care, what makes it memorable, and what to do first.
|
|
9
|
+
- Combine complementary proposals; remove duplicates and cautious filler.
|
|
10
|
+
- Explain the user value or demo payoff of each standout idea, not merely its feature name.
|
|
11
|
+
- Keep facts inside supported findings and sources. Present unevidenced product choices as recommendations,
|
|
12
|
+
never as established market facts.
|
|
13
|
+
- Chair output is decision reasoning, not evidence. Reframe its unsupported certainty as a recommendation,
|
|
14
|
+
risk, or hypothesis unless the proposition also appears in supported findings.
|
|
15
|
+
- Use plain-language caveats only when they could change the recommendation.
|
|
10
16
|
|
|
11
|
-
##
|
|
12
|
-
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
-
|
|
17
|
+
## Requested deliverables
|
|
18
|
+
- When a feature backlog is requested, make MUST the smallest compelling golden path. Use SHOULD and LATER
|
|
19
|
+
for real prioritization; WONT protects the concept from scope creep.
|
|
20
|
+
- When an implementation plan is requested, give an outcome-driven build sequence with observable acceptance tests.
|
|
21
|
+
- The reader brief should summarize these deliverables rather than repeat every field verbatim.
|
|
16
22
|
|
|
17
|
-
##
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
|
|
23
|
+
## Validation actions
|
|
24
|
+
- Keep 1–4 actions. Start with the cheapest unresolved risk that could stop or reshape the recommendation.
|
|
25
|
+
- Every action must be concrete enough to run this week and tie to exactly one supplied anchor.
|
|
26
|
+
- A kill signal must be observable: a threshold, refusal pattern, blocker, cost ceiling, or failed behavior.
|
|
21
27
|
|
|
22
28
|
## Do not
|
|
23
|
-
- No
|
|
24
|
-
- No
|
|
25
|
-
- No
|
|
29
|
+
- No graph ids, verification labels, confidence formulas, audit vocabulary, or model-process commentary in reader_brief.
|
|
30
|
+
- No generic "do more research" action.
|
|
31
|
+
- No invented source or unsupported hype.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Rebuttal playbook — answer the strongest opposition
|
|
2
|
+
|
|
3
|
+
Add to your base instructions; the schema and caps are unchanged and always win.
|
|
4
|
+
|
|
5
|
+
## Review in this order
|
|
6
|
+
1. Steelman the opposing position in one line before answering it.
|
|
7
|
+
2. Name its biggest blind spot: the assumption it never checks. Attack that assumption with supplied
|
|
8
|
+
evidence IDs.
|
|
9
|
+
3. Name what both sides missed. Use NARROW or UNRESOLVED instead of pretending it was covered.
|
|
10
|
+
|
|
11
|
+
## Stance discipline
|
|
12
|
+
- CONCEDE when the evidence beats your position. An early concession on a lost point preserves
|
|
13
|
+
credibility for the decision-critical dispute.
|
|
14
|
+
- Never change a stance word without a supplied evidence ID.
|
|
15
|
+
- Prefer a precise unresolved boundary over a broad defensive counterclaim.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Verifier playbook — try to disprove the claim
|
|
2
|
+
|
|
3
|
+
Add to your base instructions; the schema and caps are unchanged and always win.
|
|
4
|
+
|
|
5
|
+
## Refute first
|
|
6
|
+
- Assume each claim is wrong. Hunt for the disconfirming reading of the same supplied evidence.
|
|
7
|
+
- Confirm only after a serious refutation attempt fails.
|
|
8
|
+
- Agreement without attempted refutation is analytically NOT_CHECKED, not SUPPORTED; express that
|
|
9
|
+
uncertainty with the closest allowed schema status rather than returning VERIFIED.
|
|
10
|
+
- Judge the evidence, never its author.
|
|
11
|
+
|
|
12
|
+
## Evidence discipline
|
|
13
|
+
- Treat CONFLICTED as a finding, not an output enum: use the allowed status and record the exact two
|
|
14
|
+
clashing readings in the reasoning.
|
|
15
|
+
- Never verify a value judgment as fact. Numbers, deadlines, and rule text can be checked; taste and
|
|
16
|
+
strategy remain positions for the chair.
|
|
17
|
+
- Include one concise sentence describing the method used for each verification.
|
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. */
|
|
@@ -42,7 +46,7 @@ export function buildIdeaRubric(domainDimensions = []) {
|
|
|
42
46
|
}
|
|
43
47
|
/** Idea S4 analyst template. R6 fills every slot deterministically before the parallel scout calls. */
|
|
44
48
|
export const IDEA_S4_ANALYST_TEMPLATE = `ROLE: Independent analyst on a decision panel. You work ALONE; you will not see
|
|
45
|
-
other analysts' output.
|
|
49
|
+
other analysts' output. Improve the strongest version and pressure-test it honestly within your assigned lane.
|
|
46
50
|
|
|
47
51
|
TASK CONTRACT: {{INTENT_CONTRACT_JSON}}
|
|
48
52
|
INPUT DOCUMENT: read the file at {{INPUT_PATH}}{{SKILL}}
|
|
@@ -54,7 +58,10 @@ Produce ONLY JSON matching {{S4_SCHEMA_REF}} with:
|
|
|
54
58
|
- task_echo: restate the task in ≤2 sentences (drift check).
|
|
55
59
|
- strongest_version: the best honest version of this idea in ≤150 words.
|
|
56
60
|
- positions: explicit claim positions with local_id, proposition, rubric dimension_id, stance
|
|
57
|
-
SUPPORT|OPPOSE|MIXED|UNKNOWN, basis EVIDENCE|INFERENCE|ASSUMPTION,
|
|
61
|
+
SUPPORT|OPPOSE|MIXED|UNKNOWN, basis EVIDENCE|INFERENCE|ASSUMPTION, nature FACTUAL when the position
|
|
62
|
+
asserts something independently checkable about the world (rules, deadlines, prices, observed CLI
|
|
63
|
+
behavior, published numbers) or JUDGMENT for a design choice, recommendation, prioritization, or
|
|
64
|
+
prediction (when unsure use JUDGMENT), load_bearing, if_false
|
|
58
65
|
STOP|PIVOT|CONDITION|MINOR, concise reasoning, evidence_ids, and depends_on position ids.
|
|
59
66
|
- evidence: evidence cards {id, claim_supported, source_kind USER|PRIMARY|SECONDARY|MODEL_KNOWLEDGE,
|
|
60
67
|
support SUPPORTS|CONTRADICTS|CONTEXT_ONLY (exact token, no extra words), freshness CURRENT|DATED|UNKNOWN,
|
|
@@ -66,8 +73,11 @@ Produce ONLY JSON matching {{S4_SCHEMA_REF}} with:
|
|
|
66
73
|
- coverage: one entry per rubric dimension {dimension_id, status COVERED|NOT_APPLICABLE,
|
|
67
74
|
position_ids ([] when none), rationale (required for NOT_APPLICABLE)}.
|
|
68
75
|
- decision_questions: questions {question, claim_ids} whose answers could change the verdict.
|
|
69
|
-
|
|
70
|
-
|
|
76
|
+
- deliverable_proposals: when requested_outputs includes FEATURE_BACKLOG or IMPLEMENTATION_PLAN, propose
|
|
77
|
+
concrete user-facing work as {output,title,detail,user_value,why_distinctive,evidence_ids}; otherwise [].
|
|
78
|
+
Proposals are recommendations, not factual claims. Use evidence_ids only when evidence directly supports them.
|
|
79
|
+
Caps: at most 12 positions, 20 evidence cards, 8 calculations, 8 decision_questions, 8 deliverable_proposals.
|
|
80
|
+
Rules: no unsupported hype, no summaries of your own output, no markdown, JSON only.`;
|
|
71
81
|
/**
|
|
72
82
|
* Resolve the {{SKILL}} slot before deterministic structural fill. An empty skill collapses the slot
|
|
73
83
|
* to the pre-skill baseline.
|
|
@@ -77,11 +87,11 @@ export function buildAnalystTemplate(skill) {
|
|
|
77
87
|
}
|
|
78
88
|
/** R6 deterministic S4 prompt fill. No model-authored prompt generation remains. */
|
|
79
89
|
export function buildAnalystPrompt(contract, inputPath, evidencePack, mode, skill) {
|
|
80
|
-
const modeRules = mode
|
|
81
|
-
? `\n\nMODE:
|
|
90
|
+
const modeRules = mode !== 'quick'
|
|
91
|
+
? `\n\nMODE: full council. Use provider-native read-only source investigation when available. Every current
|
|
82
92
|
fact must have an independently checkable locator and access date. If investigation is unavailable,
|
|
83
93
|
leave the claim unverified; never invent a source.`
|
|
84
|
-
: `\n\nMODE:
|
|
94
|
+
: `\n\nMODE: quick. Analyze independently and keep unsupported claims visibly unverified.`;
|
|
85
95
|
const prompt = buildAnalystTemplate(skill)
|
|
86
96
|
.replace('{{INTENT_CONTRACT_JSON}}', JSON.stringify(contract))
|
|
87
97
|
.replace('{{INPUT_PATH}}', inputPath)
|
|
@@ -107,27 +117,122 @@ export const IDEA_STAGES = [
|
|
|
107
117
|
{ id: 'S9b', label: 'Validation plan', role: 'judge' },
|
|
108
118
|
{ id: 'S10', label: 'Report', role: null },
|
|
109
119
|
];
|
|
120
|
+
/** Record guarantees observed at the surviving typed S4 boundary; never infer them from prompts. */
|
|
121
|
+
export function recordIdeaOutcomeFlags(ctx, contract, seats) {
|
|
122
|
+
if (ctx.mode === 'quick')
|
|
123
|
+
return;
|
|
124
|
+
const requested = (contract.requested_outputs ?? [])
|
|
125
|
+
.filter((output) => output === 'FEATURE_BACKLOG' || output === 'IMPLEMENTATION_PLAN');
|
|
126
|
+
if (requested.some((output) => seats.some((seat) => !seat.output.deliverable_proposals.some((proposal) => proposal.output === output)))) {
|
|
127
|
+
ctx.addFlag('deliverable_gap');
|
|
128
|
+
}
|
|
129
|
+
const grounded = seats.some((seat) => {
|
|
130
|
+
const cited = new Set(seat.output.positions.flatMap((position) => position.evidence_ids));
|
|
131
|
+
return seat.output.evidence.some((card) => cited.has(card.id)
|
|
132
|
+
&& (card.source_kind === 'PRIMARY' || card.source_kind === 'SECONDARY')
|
|
133
|
+
&& card.freshness === 'CURRENT'
|
|
134
|
+
&& Boolean(card.accessed_at && (card.url || card.locator))
|
|
135
|
+
&& card.support !== 'CONTEXT_ONLY');
|
|
136
|
+
});
|
|
137
|
+
if (!grounded)
|
|
138
|
+
ctx.addFlag('research_ungrounded');
|
|
139
|
+
}
|
|
110
140
|
/** Runs the full idea-refinement pipeline S0–S10. Throws on any fatal condition; the engine's
|
|
111
141
|
* `executeRun` wrapper turns that into a graceful failure + meta. Each stage is wrapped in
|
|
112
142
|
* `runStage` so the TUI timeline (T8) gets start/end events; headless, that's a no-op. */
|
|
113
143
|
export async function runIdeaRefinement(ctx, input) {
|
|
114
144
|
if (ctx.evidencePack)
|
|
115
145
|
await ctx.writer.writeInput('evidence-pack.json', JSON.stringify(ctx.evidencePack, null, 2));
|
|
116
|
-
|
|
146
|
+
// v6 T10b: the CLI may have already snapshotted (and interactively cleared) the sources.
|
|
147
|
+
const urlSources = ctx.urlSources ?? await snapshotUrlSources(input);
|
|
117
148
|
await ctx.writer.writeJson('url-sources', urlSources);
|
|
118
149
|
const unreadableSources = urlSources.sources.filter((source) => source.status !== 'FETCHED');
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
150
|
+
const needsSourceFallback = ctx.mode !== 'quick' && unreadableSources.length > 0;
|
|
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);
|
|
122
170
|
}
|
|
123
|
-
const { contract, brief } = await runStage(ctx, 'S0', () => preflight(ctx, input, IDEA_RUBRIC.map((item) => item.label), urlSources));
|
|
124
|
-
const grilledInput = renderDecisionInput(input, brief, urlSources);
|
|
125
171
|
// Persist the input as a file so S4's "read the file at {{INPUT_PATH}}" resolves (not a stage).
|
|
126
172
|
await ctx.writer.writeInput('idea.md', input);
|
|
127
173
|
await ctx.writer.writeInput('idea-brief.md', grilledInput);
|
|
128
174
|
const inputPath = resolve(ctx.writer.dir, 'inputs', 'idea-brief.md');
|
|
129
175
|
const rubric = buildIdeaRubric(contract.domain_dimensions);
|
|
130
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
|
+
}
|
|
131
236
|
if (ctx.mode === 'quick') {
|
|
132
237
|
ctx.addFlag('single_model');
|
|
133
238
|
const quickPrompt = buildQuickPrompt(contract, inputPath, ctx.evidencePack, analystSkill);
|
|
@@ -159,19 +264,20 @@ export async function runIdeaRefinement(ctx, input) {
|
|
|
159
264
|
await runStage(ctx, 'S10', () => s10Render(ctx, { contract, seats: kept, graph, verifications, rebuttals, judgeReport, actionPlan, rubric, original: input }));
|
|
160
265
|
return;
|
|
161
266
|
}
|
|
162
|
-
if (ctx.mode === 'research' && !ctx.evidencePack && !ctx.available().includes('codex')) {
|
|
163
|
-
ctx.addFlag('research_ungrounded');
|
|
164
|
-
}
|
|
165
267
|
const analystPrompt = buildAnalystPrompt(contract, inputPath, ctx.evidencePack, ctx.mode, analystSkill);
|
|
166
268
|
await ctx.writer.writePrompt('analyst.md', analystPrompt);
|
|
167
269
|
const lanePrompts = buildLanePrompts(analystPrompt, rubric);
|
|
168
|
-
const seats = await runStage(ctx, 'S4', () => s4Analyze(ctx, lanePrompts));
|
|
270
|
+
const seats = await runStage(ctx, 'S4', () => s4Analyze(ctx, lanePrompts, needsSourceFallback));
|
|
169
271
|
const { kept } = await runStage(ctx, 'S5', () => s5Drift(ctx, contract, seats));
|
|
272
|
+
recordIdeaOutcomeFlags(ctx, contract, kept);
|
|
170
273
|
const positions = await runStage(ctx, 'S6', () => s6Positions(ctx, kept));
|
|
171
274
|
const graph = await runStage(ctx, 'S7', () => s7DecisionGraph(ctx, positions, rubric, contract.task));
|
|
172
275
|
const verifications = await runStage(ctx, 'S8', () => s8Verify(ctx, graph));
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
const
|
|
176
|
-
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 }));
|
|
177
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",
|