aiwcli 0.11.1 → 0.12.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.
- package/dist/commands/clear.d.ts +8 -0
- package/dist/commands/clear.js +86 -0
- package/dist/lib/bmad-installer.d.ts +2 -27
- package/dist/lib/bmad-installer.js +3 -43
- package/dist/lib/claude-settings-types.d.ts +2 -1
- package/dist/lib/env-compat.d.ts +0 -8
- package/dist/lib/env-compat.js +0 -12
- package/dist/lib/git/index.d.ts +0 -1
- package/dist/lib/gitignore-manager.d.ts +0 -2
- package/dist/lib/gitignore-manager.js +1 -1
- package/dist/lib/hooks-merger.d.ts +1 -15
- package/dist/lib/hooks-merger.js +1 -1
- package/dist/lib/index.d.ts +3 -7
- package/dist/lib/index.js +3 -11
- package/dist/lib/output.d.ts +2 -1
- package/dist/lib/settings-hierarchy.d.ts +1 -13
- package/dist/lib/settings-hierarchy.js +1 -1
- package/dist/lib/template-installer.d.ts +5 -9
- package/dist/lib/template-installer.js +3 -13
- package/dist/lib/template-linter.d.ts +3 -10
- package/dist/lib/template-linter.js +2 -2
- package/dist/lib/template-resolver.d.ts +6 -0
- package/dist/lib/template-resolver.js +10 -0
- package/dist/lib/template-settings-reconstructor.d.ts +1 -1
- package/dist/lib/template-settings-reconstructor.js +17 -24
- package/dist/lib/terminal.d.ts +3 -14
- package/dist/lib/terminal.js +0 -4
- package/dist/lib/version.d.ts +2 -11
- package/dist/lib/version.js +3 -3
- package/dist/lib/windsurf-hooks-merger.d.ts +1 -15
- package/dist/lib/windsurf-hooks-merger.js +1 -1
- package/dist/templates/_shared/.codex/workflows/handoff.md +1 -1
- package/dist/templates/_shared/.windsurf/workflows/handoff.md +1 -1
- package/dist/templates/_shared/hooks-ts/session_end.ts +75 -4
- package/dist/templates/_shared/hooks-ts/session_start.ts +11 -13
- package/dist/templates/_shared/hooks-ts/user_prompt_submit.ts +6 -8
- package/dist/templates/_shared/lib-ts/CLAUDE.md +56 -7
- package/dist/templates/_shared/lib-ts/base/hook-utils.ts +176 -29
- package/dist/templates/_shared/lib-ts/base/logger.ts +1 -1
- package/dist/templates/_shared/lib-ts/base/state-io.ts +11 -2
- package/dist/templates/_shared/lib-ts/base/subprocess-utils.ts +181 -165
- package/dist/templates/_shared/lib-ts/context/plan-manager.ts +14 -13
- package/dist/templates/_shared/lib-ts/handoff/handoff-reader.ts +3 -2
- package/dist/templates/_shared/lib-ts/package.json +1 -2
- package/dist/templates/_shared/lib-ts/templates/plan-context.ts +27 -34
- package/dist/templates/_shared/lib-ts/types.ts +17 -2
- package/dist/templates/_shared/scripts/resume_handoff.ts +4 -4
- package/dist/templates/_shared/scripts/save_handoff.ts +7 -7
- package/dist/templates/_shared/scripts/status_line.ts +104 -71
- package/dist/templates/_shared/workflows/handoff.md +1 -1
- package/dist/templates/cc-native/.claude/settings.json +182 -175
- package/dist/templates/cc-native/_cc-native/agents/CLAUDE.md +23 -1
- package/dist/templates/cc-native/_cc-native/agents/plan-questions/PLAN-QUESTIONER.md +70 -0
- package/dist/templates/cc-native/_cc-native/hooks/CLAUDE.md +6 -1
- package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.ts +142 -111
- package/dist/templates/cc-native/_cc-native/hooks/enhance_plan_post_subagent.ts +54 -0
- package/dist/templates/cc-native/_cc-native/hooks/enhance_plan_post_write.ts +52 -0
- package/dist/templates/cc-native/_cc-native/hooks/mark_questions_asked.ts +53 -0
- package/dist/templates/cc-native/_cc-native/hooks/plan_questions_early.ts +19 -19
- package/dist/templates/cc-native/_cc-native/lib-ts/aggregate-agents.ts +6 -5
- package/dist/templates/cc-native/_cc-native/lib-ts/artifacts.ts +114 -83
- package/dist/templates/cc-native/_cc-native/lib-ts/cc-native-state.ts +107 -10
- package/dist/templates/cc-native/_cc-native/lib-ts/cli-output-parser.ts +1 -1
- package/dist/templates/cc-native/_cc-native/lib-ts/corroboration.ts +6 -2
- package/dist/templates/cc-native/_cc-native/lib-ts/index.ts +0 -4
- package/dist/templates/cc-native/_cc-native/lib-ts/orchestrator.ts +40 -219
- package/dist/templates/cc-native/_cc-native/lib-ts/plan-enhancement.ts +41 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/plan-questions.ts +102 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/agent.ts +26 -227
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/base/base-agent.ts +217 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/index.ts +4 -2
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/providers/claude-agent.ts +65 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/providers/codex-agent.ts +185 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/providers/gemini-agent.ts +39 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/providers/orchestrator-claude-agent.ts +195 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/schemas.ts +201 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/types.ts +2 -2
- package/dist/templates/cc-native/_cc-native/lib-ts/state.ts +17 -16
- package/dist/templates/cc-native/_cc-native/lib-ts/types.ts +13 -108
- package/dist/templates/cc-native/_cc-native/lib-ts/verdict.ts +3 -3
- package/dist/templates/cc-native/_cc-native/plan-review.config.json +2 -14
- package/oclif.manifest.json +1 -1
- package/package.json +1 -2
- package/dist/templates/cc-native/_cc-native/hooks/add_plan_context.ts +0 -119
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/codex.ts +0 -130
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/gemini.ts +0 -107
- /package/dist/templates/cc-native/_cc-native/agents/{ARCH-EVOLUTION.md → plan-review/ARCH-EVOLUTION.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{ARCH-PATTERNS.md → plan-review/ARCH-PATTERNS.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{ARCH-STRUCTURE.md → plan-review/ARCH-STRUCTURE.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{ASSUMPTION-TRACER.md → plan-review/ASSUMPTION-TRACER.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{CLARITY-AUDITOR.md → plan-review/CLARITY-AUDITOR.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{COMPLETENESS-FEASIBILITY.md → plan-review/COMPLETENESS-FEASIBILITY.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{COMPLETENESS-GAPS.md → plan-review/COMPLETENESS-GAPS.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{COMPLETENESS-ORDERING.md → plan-review/COMPLETENESS-ORDERING.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{CONSTRAINT-VALIDATOR.md → plan-review/CONSTRAINT-VALIDATOR.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{DESIGN-ADR-VALIDATOR.md → plan-review/DESIGN-ADR-VALIDATOR.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{DESIGN-SCALE-MATCHER.md → plan-review/DESIGN-SCALE-MATCHER.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{DEVILS-ADVOCATE.md → plan-review/DEVILS-ADVOCATE.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{DOCUMENTATION-PHILOSOPHY.md → plan-review/DOCUMENTATION-PHILOSOPHY.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{HANDOFF-READINESS.md → plan-review/HANDOFF-READINESS.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{HIDDEN-COMPLEXITY.md → plan-review/HIDDEN-COMPLEXITY.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{INCREMENTAL-DELIVERY.md → plan-review/INCREMENTAL-DELIVERY.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{RISK-DEPENDENCY.md → plan-review/RISK-DEPENDENCY.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{RISK-FMEA.md → plan-review/RISK-FMEA.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{RISK-PREMORTEM.md → plan-review/RISK-PREMORTEM.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{RISK-REVERSIBILITY.md → plan-review/RISK-REVERSIBILITY.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{SCOPE-BOUNDARY.md → plan-review/SCOPE-BOUNDARY.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{SIMPLICITY-GUARDIAN.md → plan-review/SIMPLICITY-GUARDIAN.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{SKEPTIC.md → plan-review/SKEPTIC.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{TESTDRIVEN-BEHAVIOR-AUDITOR.md → plan-review/TESTDRIVEN-BEHAVIOR-AUDITOR.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{TESTDRIVEN-CHARACTERIZATION.md → plan-review/TESTDRIVEN-CHARACTERIZATION.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{TESTDRIVEN-FIRST-VALIDATOR.md → plan-review/TESTDRIVEN-FIRST-VALIDATOR.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{TESTDRIVEN-PYRAMID-ANALYZER.md → plan-review/TESTDRIVEN-PYRAMID-ANALYZER.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{TRADEOFF-COSTS.md → plan-review/TRADEOFF-COSTS.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{TRADEOFF-STAKEHOLDERS.md → plan-review/TRADEOFF-STAKEHOLDERS.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{VERIFY-COVERAGE.md → plan-review/VERIFY-COVERAGE.md} +0 -0
- /package/dist/templates/cc-native/_cc-native/agents/{VERIFY-STRENGTH.md → plan-review/VERIFY-STRENGTH.md} +0 -0
|
@@ -1,67 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Plan orchestrator — analyzes complexity and selects reviewer agents.
|
|
3
|
+
* Uses OrchestratorClaudeAgent (BaseCliAgent framework) for subprocess execution.
|
|
3
4
|
* See cc-native-plan-review-spec.md §4.8
|
|
4
5
|
*/
|
|
5
6
|
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import type { AgentConfig, OrchestratorConfig, OrchestratorResult, ComplexityCategory } from "./types.js";
|
|
10
|
-
import { ORCHESTRATOR_SCHEMA } from "./types.js";
|
|
7
|
+
import { OrchestratorClaudeAgent } from "./reviewers/providers/orchestrator-claude-agent.js";
|
|
8
|
+
import type { AgentConfig, OrchestratorConfig, OrchestratorResult } from "./types.js";
|
|
9
|
+
import { logInfo, logWarn } from "../../_shared/lib-ts/base/logger.js";
|
|
11
10
|
|
|
12
|
-
//
|
|
13
|
-
|
|
14
|
-
// ---------------------------------------------------------------------------
|
|
15
|
-
|
|
16
|
-
const DEFAULT_AGENT_SELECTION: Record<string, unknown> = {
|
|
17
|
-
simple: { min: 3, max: 3 },
|
|
18
|
-
medium: { min: 8, max: 8 },
|
|
19
|
-
high: { min: 12, max: 12 },
|
|
20
|
-
fallbackCount: 3,
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const DEFAULT_COMPLEXITY_CATEGORIES = [
|
|
24
|
-
"code",
|
|
25
|
-
"infrastructure",
|
|
26
|
-
"documentation",
|
|
27
|
-
"life",
|
|
28
|
-
"business",
|
|
29
|
-
"design",
|
|
30
|
-
"research",
|
|
31
|
-
];
|
|
32
|
-
|
|
33
|
-
// ---------------------------------------------------------------------------
|
|
34
|
-
// Schema Builder
|
|
35
|
-
// ---------------------------------------------------------------------------
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Build orchestrator JSON schema with enum-constrained agent names.
|
|
39
|
-
*/
|
|
40
|
-
export function buildOrchestratorSchema(
|
|
41
|
-
validAgentNames: string[],
|
|
42
|
-
categories: string[],
|
|
43
|
-
): Record<string, unknown> {
|
|
44
|
-
const itemsSchema: Record<string, unknown> = { type: "string" };
|
|
45
|
-
if (validAgentNames.length > 0) {
|
|
46
|
-
itemsSchema.enum = validAgentNames;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return {
|
|
50
|
-
type: "object",
|
|
51
|
-
properties: {
|
|
52
|
-
complexity: { type: "string", enum: ["simple", "medium", "high"] },
|
|
53
|
-
category: { type: "string", enum: categories },
|
|
54
|
-
selectedAgents: {
|
|
55
|
-
type: "array",
|
|
56
|
-
items: itemsSchema,
|
|
57
|
-
},
|
|
58
|
-
reasoning: { type: "string" },
|
|
59
|
-
skipReason: { type: "string" },
|
|
60
|
-
},
|
|
61
|
-
required: ["complexity", "category", "selectedAgents", "reasoning"],
|
|
62
|
-
additionalProperties: false,
|
|
63
|
-
};
|
|
64
|
-
}
|
|
11
|
+
// Re-export for backward compatibility (moved to reviewers/schemas.ts)
|
|
12
|
+
export { buildOrchestratorSchema } from "./reviewers/schemas.js";
|
|
65
13
|
|
|
66
14
|
// ---------------------------------------------------------------------------
|
|
67
15
|
// Orchestrator
|
|
@@ -81,170 +29,43 @@ export async function runOrchestrator(
|
|
|
81
29
|
logInfo("orchestrator", "Starting plan analysis...");
|
|
82
30
|
|
|
83
31
|
const mandatory = mandatoryNames ?? new Set<string>();
|
|
84
|
-
const selection = (settings.agentSelection as Record<string, unknown>) ?? DEFAULT_AGENT_SELECTION;
|
|
85
|
-
const categories = (settings.complexityCategories as string[]) ?? DEFAULT_COMPLEXITY_CATEGORIES;
|
|
86
|
-
const fallbackCount = (selection.fallbackCount as number) ?? 2;
|
|
87
32
|
|
|
88
|
-
//
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
33
|
+
// Create a synthetic AgentConfig for the orchestrator
|
|
34
|
+
const orchestratorAgent: AgentConfig = {
|
|
35
|
+
name: "orchestrator",
|
|
36
|
+
model: config.model,
|
|
37
|
+
provider: "claude",
|
|
38
|
+
focus: "plan analysis and agent selection",
|
|
39
|
+
enabled: config.enabled,
|
|
40
|
+
categories: [],
|
|
41
|
+
description: "Plan orchestrator",
|
|
42
|
+
system_prompt: "",
|
|
43
|
+
};
|
|
96
44
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
45
|
+
try {
|
|
46
|
+
const agent = new OrchestratorClaudeAgent(
|
|
47
|
+
orchestratorAgent,
|
|
48
|
+
agentLibrary,
|
|
49
|
+
mandatory,
|
|
50
|
+
settings,
|
|
51
|
+
config.timeout,
|
|
102
52
|
);
|
|
103
|
-
return makeFallback(nonMandatory, fallbackCount, "Orchestrator skipped - Claude CLI not found", "claude CLI not found on PATH");
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
logDebug("orchestrator", `Found Claude CLI at: ${claudePath}`);
|
|
107
|
-
|
|
108
|
-
// Build agent list from non-mandatory agents
|
|
109
|
-
const agentList = nonMandatory
|
|
110
|
-
.map(
|
|
111
|
-
(a) =>
|
|
112
|
-
`- ${a.name} [${a.categories.join(", ")}]\n Focus: ${a.focus}\n Expertise: ${a.description}`,
|
|
113
|
-
)
|
|
114
|
-
.join("\n");
|
|
115
|
-
const categoryList = categories.join("/");
|
|
116
|
-
|
|
117
|
-
// Compute additional agent counts
|
|
118
|
-
const mandatoryCount = agentLibrary.filter((a) => mandatory.has(a.name)).length;
|
|
119
|
-
const simpleAdditional = Math.max(0, ((selection.simple as Record<string, number> | undefined)?.max ?? 3) - mandatoryCount);
|
|
120
|
-
const mediumAdditional = Math.max(0, ((selection.medium as Record<string, number> | undefined)?.max ?? 8) - mandatoryCount);
|
|
121
|
-
const highAdditional = Math.max(0, ((selection.high as Record<string, number> | undefined)?.max ?? 12) - mandatoryCount);
|
|
122
|
-
|
|
123
|
-
const systemPrompt = `You are a plan orchestrator for code review. Your job is to analyze plans and select appropriate reviewer agents.
|
|
124
|
-
|
|
125
|
-
You MUST call StructuredOutput immediately with your analysis. Do NOT ask questions or use any other tools.
|
|
126
|
-
|
|
127
|
-
When selecting agents:
|
|
128
|
-
- Match agent expertise to plan requirements
|
|
129
|
-
- Consider what each agent specializes in
|
|
130
|
-
- Only select agents whose categories match the plan category
|
|
131
|
-
- Fewer agents for simple plans, more for complex plans`;
|
|
132
|
-
|
|
133
|
-
const prompt = `Analyze this plan and select appropriate reviewer agents.
|
|
134
|
-
|
|
135
|
-
Available agents (select ONLY from this list):
|
|
136
|
-
${agentList}
|
|
137
|
-
|
|
138
|
-
Selection rules (number of ADDITIONAL agents to select from the list above):
|
|
139
|
-
- simple complexity = ${simpleAdditional} agents
|
|
140
|
-
- medium complexity = ${mediumAdditional} agents
|
|
141
|
-
- high complexity = ${highAdditional} agents
|
|
142
|
-
- Only select agents whose categories match the plan category (${categoryList})
|
|
143
|
-
- Non-technical plans (life, business) typically need 0 code-focused agents
|
|
144
|
-
- Note: mandatory agents run separately and are NOT listed above
|
|
145
|
-
|
|
146
|
-
PLAN:
|
|
147
|
-
<<<
|
|
148
|
-
${plan}
|
|
149
|
-
>>>
|
|
150
53
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
];
|
|
168
|
-
|
|
169
|
-
logInfo("orchestrator", `Running with model: ${config.model}, timeout: ${config.timeout}s`);
|
|
170
|
-
|
|
171
|
-
const env = getInternalSubprocessEnv();
|
|
172
|
-
|
|
173
|
-
const result = await execFileAsync(claudePath, cmdArgs, {
|
|
174
|
-
input: prompt,
|
|
175
|
-
timeout: config.timeout * 1000,
|
|
176
|
-
env: env as Record<string, string>,
|
|
177
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
178
|
-
shell: process.platform === "win32",
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
if (result.killed || result.signal === "SIGTERM") {
|
|
182
|
-
logWarn("orchestrator", `TIMEOUT after ${config.timeout}s, falling back to medium complexity`);
|
|
183
|
-
return makeFallback(nonMandatory, fallbackCount, "Orchestrator timed out - defaulting to medium complexity", `Orchestrator timed out after ${config.timeout}s`);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
const raw = result.stdout.trim();
|
|
187
|
-
if (result.stderr) logDebug("orchestrator", `stderr: ${result.stderr.slice(0, 300)}`);
|
|
188
|
-
|
|
189
|
-
if (!raw && !result.stderr && result.exitCode !== 0) {
|
|
190
|
-
logError("orchestrator", `Process exited with code ${result.exitCode}, falling back to medium complexity`);
|
|
191
|
-
return makeFallback(nonMandatory, fallbackCount, `Orchestrator failed (exit ${result.exitCode})`, `Exit code ${result.exitCode}`);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
const obj = parseCliOutput(raw);
|
|
195
|
-
|
|
196
|
-
logDebug("orchestrator", `Raw output length: ${raw.length} chars`);
|
|
197
|
-
if (raw) logDebug("orchestrator", `Raw output (first 500 chars): ${raw.slice(0, 500)}`);
|
|
198
|
-
logDebug("orchestrator", `Parsed obj: ${JSON.stringify(obj)}`);
|
|
199
|
-
|
|
200
|
-
if (!obj) {
|
|
201
|
-
logWarn("orchestrator", "Failed to parse output, falling back to medium complexity");
|
|
202
|
-
return makeFallback(nonMandatory, fallbackCount, "Orchestrator output could not be parsed", "Failed to parse orchestrator output");
|
|
54
|
+
const result = await agent.review(plan);
|
|
55
|
+
|
|
56
|
+
logInfo("orchestrator", `Result: complexity=${result.complexity}, category=${result.category}, agents=${JSON.stringify(result.selected_agents)}`);
|
|
57
|
+
|
|
58
|
+
return result;
|
|
59
|
+
} catch (error) {
|
|
60
|
+
logWarn("orchestrator", `Unexpected error: ${error}`);
|
|
61
|
+
const nonMandatory = agentLibrary.filter((a) => a.enabled && !mandatory.has(a.name));
|
|
62
|
+
const fallbackCount = ((settings.agentSelection as Record<string, unknown>)?.fallbackCount as number) ?? 2;
|
|
63
|
+
return {
|
|
64
|
+
complexity: "medium",
|
|
65
|
+
category: "code",
|
|
66
|
+
selected_agents: nonMandatory.slice(0, fallbackCount).map((a) => a.name),
|
|
67
|
+
reasoning: `Orchestrator failed: ${error}`,
|
|
68
|
+
error: String(error),
|
|
69
|
+
};
|
|
203
70
|
}
|
|
204
|
-
|
|
205
|
-
// Extract and validate fields
|
|
206
|
-
const rawComplexity = String(obj.complexity ?? "medium");
|
|
207
|
-
const complexity: ComplexityCategory =
|
|
208
|
-
rawComplexity === "simple" || rawComplexity === "medium" || rawComplexity === "high"
|
|
209
|
-
? rawComplexity
|
|
210
|
-
: "medium";
|
|
211
|
-
|
|
212
|
-
let category = (obj.category as string) ?? "code";
|
|
213
|
-
if (!categories.includes(category)) category = "code";
|
|
214
|
-
|
|
215
|
-
let selectedAgents = obj.selectedAgents;
|
|
216
|
-
if (!Array.isArray(selectedAgents)) selectedAgents = [];
|
|
217
|
-
|
|
218
|
-
const reasoning = String(obj.reasoning ?? "").trim() || "No reasoning provided";
|
|
219
|
-
const skipReason = obj.skipReason as string | undefined;
|
|
220
|
-
|
|
221
|
-
logInfo("orchestrator", `Result: complexity=${complexity}, category=${category}, agents=${JSON.stringify(selectedAgents)}`);
|
|
222
|
-
logDebug("orchestrator", `Reasoning: ${reasoning}`);
|
|
223
|
-
|
|
224
|
-
return {
|
|
225
|
-
complexity,
|
|
226
|
-
category,
|
|
227
|
-
selected_agents: selectedAgents as string[],
|
|
228
|
-
reasoning,
|
|
229
|
-
skip_reason: skipReason || undefined,
|
|
230
|
-
};
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// ---------------------------------------------------------------------------
|
|
234
|
-
// Helpers
|
|
235
|
-
// ---------------------------------------------------------------------------
|
|
236
|
-
|
|
237
|
-
function makeFallback(
|
|
238
|
-
nonMandatory: AgentConfig[],
|
|
239
|
-
fallbackCount: number,
|
|
240
|
-
reasoning: string,
|
|
241
|
-
error: string,
|
|
242
|
-
): OrchestratorResult {
|
|
243
|
-
return {
|
|
244
|
-
complexity: "medium",
|
|
245
|
-
category: "code",
|
|
246
|
-
selected_agents: nonMandatory.slice(0, fallbackCount).map((a) => a.name),
|
|
247
|
-
reasoning,
|
|
248
|
-
error,
|
|
249
|
-
};
|
|
250
71
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan quality guidance for context emission.
|
|
3
|
+
*
|
|
4
|
+
* Provides prompt text that guides the main agent to review plans before
|
|
5
|
+
* presenting them to the user. Emitted via emitContext() — NOT appended to plan files.
|
|
6
|
+
*
|
|
7
|
+
* Used by both SubagentStop hook (Plan agents) and PostToolUse:Write hook (direct writes).
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Returns the plan quality review prompt to emit as context after a plan is written.
|
|
12
|
+
* This guides the main agent to review the plan before calling ExitPlanMode.
|
|
13
|
+
*
|
|
14
|
+
* Design principles:
|
|
15
|
+
* - No hardcoded skill names — agent discovers relevant skills from system-reminders
|
|
16
|
+
* - Documentation focuses on WHY (preserve decisions) not WHERE (file paths)
|
|
17
|
+
* - Concise — every token in emitted context costs attention budget
|
|
18
|
+
* - Trusts the agent's judgment — guidance, not mandate
|
|
19
|
+
*/
|
|
20
|
+
export function getPlanQualityReviewContext(): string {
|
|
21
|
+
return `## Plan Quality Review
|
|
22
|
+
|
|
23
|
+
Before presenting this plan, review it from the perspective of an agent with zero conversation history.
|
|
24
|
+
|
|
25
|
+
### Self-Check
|
|
26
|
+
- File paths are absolute and verified (not "the auth file" or "as discussed")
|
|
27
|
+
- Function and class names are exact references (not "the handler" or "it")
|
|
28
|
+
- Each step is specific enough to execute without this conversation's context
|
|
29
|
+
- Verification steps are binary-testable (pass/fail in one check)
|
|
30
|
+
|
|
31
|
+
### Skills Integration
|
|
32
|
+
Review the skills listed in your system-reminder messages. Where a step would benefit from a specific skill, reference it inline (e.g., "Use \`SkillName\` skill for [specific purpose]"). Only reference skills relevant to this plan's domain.
|
|
33
|
+
|
|
34
|
+
### Documentation Reasoning
|
|
35
|
+
Evaluate whether the plan captures decisions that would be lost when this session ends. The implementation agent should understand:
|
|
36
|
+
- What was decided and why alternatives were rejected
|
|
37
|
+
- What constraints exist that aren't obvious from the code
|
|
38
|
+
- What would break if assumptions change
|
|
39
|
+
|
|
40
|
+
If the plan has gaps, address them before presenting to the user.`;
|
|
41
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan question generation — runs a fresh-context agent to identify
|
|
3
|
+
* questions, assumptions, and ambiguities in a plan before review.
|
|
4
|
+
* See cc-native-plan-review.ts for integration point (questions gate).
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as path from "node:path";
|
|
8
|
+
|
|
9
|
+
import { aggregateAgents } from "./aggregate-agents.js";
|
|
10
|
+
import { runAgentReview } from "./reviewers/index.js";
|
|
11
|
+
import { QUESTIONS_SCHEMA } from "./reviewers/schemas.js";
|
|
12
|
+
import type { AgentConfig, ModelsConfig } from "./types.js";
|
|
13
|
+
import { logInfo, logWarn, logError } from "../../_shared/lib-ts/base/logger.js";
|
|
14
|
+
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// Types
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
|
|
19
|
+
export interface PlanQuestionsResult {
|
|
20
|
+
questions: string[];
|
|
21
|
+
assumptions: string[];
|
|
22
|
+
ambiguities: string[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
// Provider assignment (local copy — avoids circular import from hook)
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
|
|
29
|
+
import { findExecutable } from "../../_shared/lib-ts/base/subprocess-utils.js";
|
|
30
|
+
|
|
31
|
+
function assignProvider(agent: AgentConfig): AgentConfig {
|
|
32
|
+
// Default to claude provider with the agent's configured model
|
|
33
|
+
const found = findExecutable("claude");
|
|
34
|
+
if (found) {
|
|
35
|
+
return { ...agent, provider: "claude" };
|
|
36
|
+
}
|
|
37
|
+
logWarn("plan-questions", "Claude CLI not found, using agent defaults");
|
|
38
|
+
return agent;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
// Main
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
|
|
45
|
+
const HOOK = "plan-questions";
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Run the plan-questions agent to generate questions about a plan.
|
|
49
|
+
* Returns structured questions/assumptions/ambiguities, or null on failure.
|
|
50
|
+
*
|
|
51
|
+
* The agent runs in a fresh context (no codebase, no session history)
|
|
52
|
+
* and uses QUESTIONS_SCHEMA instead of REVIEW_SCHEMA — the agent runner
|
|
53
|
+
* is schema-agnostic.
|
|
54
|
+
*/
|
|
55
|
+
export async function runPlanQuestions(
|
|
56
|
+
plan: string,
|
|
57
|
+
aiwcliDir: string,
|
|
58
|
+
timeout: number,
|
|
59
|
+
contextPath?: string,
|
|
60
|
+
sessionName?: string,
|
|
61
|
+
): Promise<PlanQuestionsResult | null> {
|
|
62
|
+
// Load the plan-questions agent from agents/plan-questions/
|
|
63
|
+
const questionsAgentDir = path.join(aiwcliDir, "_cc-native", "agents", "plan-questions");
|
|
64
|
+
const agents = aggregateAgents(questionsAgentDir);
|
|
65
|
+
|
|
66
|
+
if (agents.length === 0) {
|
|
67
|
+
logWarn(HOOK, `No agents found in ${questionsAgentDir}`);
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Use the first agent (PLAN-QUESTIONER)
|
|
72
|
+
let agent = agents[0]!;
|
|
73
|
+
logInfo(HOOK, `Using plan-questions agent: ${agent.name}`);
|
|
74
|
+
|
|
75
|
+
// Assign provider
|
|
76
|
+
agent = assignProvider(agent);
|
|
77
|
+
|
|
78
|
+
// Run the agent with QUESTIONS_SCHEMA
|
|
79
|
+
const result = await runAgentReview(
|
|
80
|
+
plan,
|
|
81
|
+
agent,
|
|
82
|
+
QUESTIONS_SCHEMA,
|
|
83
|
+
timeout,
|
|
84
|
+
contextPath,
|
|
85
|
+
sessionName ?? "unknown",
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
if (!result.ok) {
|
|
89
|
+
logError(HOOK, `Plan-questions agent failed: ${result.err}`);
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Extract structured data
|
|
94
|
+
const data = result.data ?? {};
|
|
95
|
+
const questions = Array.isArray(data.questions) ? (data.questions as string[]) : [];
|
|
96
|
+
const assumptions = Array.isArray(data.assumptions) ? (data.assumptions as string[]) : [];
|
|
97
|
+
const ambiguities = Array.isArray(data.ambiguities) ? (data.ambiguities as string[]) : [];
|
|
98
|
+
|
|
99
|
+
logInfo(HOOK, `Plan-questions result: ${questions.length} questions, ${assumptions.length} assumptions, ${ambiguities.length} ambiguities`);
|
|
100
|
+
|
|
101
|
+
return { questions, assumptions, ambiguities };
|
|
102
|
+
}
|