aiwcli 0.11.1 → 0.12.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.
- 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 +2 -12
- 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 +2 -2
- 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_start.ts +15 -20
- package/dist/templates/_shared/hooks-ts/user_prompt_submit.ts +12 -14
- package/dist/templates/_shared/lib-ts/CLAUDE.md +56 -7
- package/dist/templates/_shared/lib-ts/base/hook-utils.ts +174 -43
- 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/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/status_line.ts +1 -1
- package/dist/templates/_shared/workflows/handoff.md +1 -1
- package/dist/templates/cc-native/.claude/settings.json +183 -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 +91 -57
- package/dist/templates/cc-native/_cc-native/hooks/enhance_plan_post_subagent.ts +38 -0
- package/dist/templates/cc-native/_cc-native/hooks/enhance_plan_post_write.ts +51 -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 +15 -15
- package/dist/templates/cc-native/_cc-native/lib-ts/artifacts.ts +95 -65
- package/dist/templates/cc-native/_cc-native/lib-ts/cc-native-state.ts +64 -16
- 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 +101 -0
- package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/agent.ts +22 -226
- 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 +5 -3
- 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 +184 -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 +3 -5
- package/dist/templates/cc-native/_cc-native/lib-ts/types.ts +4 -107
- 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
|
@@ -3,21 +3,19 @@
|
|
|
3
3
|
* See cc-native-plan-review-spec.md §4.9
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type {
|
|
6
|
+
import type { ReviewerResult, ReviewOptions, Reviewer, Verdict, ReviewData } from "../types.js";
|
|
7
7
|
|
|
8
8
|
// Re-export for convenience
|
|
9
|
-
|
|
9
|
+
export type { ReviewerResult, ReviewOptions, Reviewer };
|
|
10
10
|
|
|
11
11
|
/** Create a standard ReviewerResult. Shared by all reviewer implementations. */
|
|
12
12
|
export function makeResult(
|
|
13
13
|
name: string,
|
|
14
14
|
ok: boolean,
|
|
15
15
|
verdict: Verdict,
|
|
16
|
-
data: Record<string, unknown
|
|
16
|
+
data: ReviewData | Record<string, unknown>,
|
|
17
17
|
raw: string,
|
|
18
18
|
err: string,
|
|
19
19
|
): ReviewerResult {
|
|
20
20
|
return { name, ok, verdict, data: data as Record<string, unknown>, raw, err };
|
|
21
21
|
}
|
|
22
|
-
|
|
23
|
-
export {type Reviewer, type ReviewerResult, type ReviewOptions} from "../types.js";
|
|
@@ -65,7 +65,7 @@ export interface CorroborationResult {
|
|
|
65
65
|
blocking: CorroboratedGroup[];
|
|
66
66
|
solo: SoloFinding[];
|
|
67
67
|
unclassified: Array<{ agent: string; issue: ReviewIssue }>;
|
|
68
|
-
verdict: "pass" | "fail";
|
|
68
|
+
verdict: "pass" | "warn" | "fail";
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
/** Normalized review data from any reviewer */
|
|
@@ -102,7 +102,6 @@ export interface OrchestratorResult {
|
|
|
102
102
|
export interface CombinedReviewResult {
|
|
103
103
|
plan_hash: string;
|
|
104
104
|
overall_verdict: Verdict;
|
|
105
|
-
cli_reviewers: Record<string, ReviewerResult>;
|
|
106
105
|
orchestration: OrchestratorResult | null;
|
|
107
106
|
agents: Record<string, ReviewerResult>;
|
|
108
107
|
timestamp: string;
|
|
@@ -262,112 +261,10 @@ export interface Reviewer {
|
|
|
262
261
|
}
|
|
263
262
|
|
|
264
263
|
// ---------------------------------------------------------------------------
|
|
265
|
-
// JSON Schemas
|
|
264
|
+
// JSON Schemas (moved to reviewers/schemas.ts)
|
|
266
265
|
// ---------------------------------------------------------------------------
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
export const REVIEW_SCHEMA: Record<string, unknown> = {
|
|
270
|
-
type: "object",
|
|
271
|
-
properties: {
|
|
272
|
-
verdict: { type: "string", enum: ["pass", "warn", "fail"] },
|
|
273
|
-
summary: { type: "string", minLength: 20 },
|
|
274
|
-
issues: {
|
|
275
|
-
type: "array",
|
|
276
|
-
items: {
|
|
277
|
-
type: "object",
|
|
278
|
-
properties: {
|
|
279
|
-
severity: { type: "string", enum: ["high", "medium", "low"] },
|
|
280
|
-
category: { type: "string" },
|
|
281
|
-
issue: { type: "string" },
|
|
282
|
-
suggested_fix: { type: "string" },
|
|
283
|
-
dimension: {
|
|
284
|
-
type: "string",
|
|
285
|
-
enum: [
|
|
286
|
-
"completeness", "simplicity", "security", "performance",
|
|
287
|
-
"reliability", "maintainability", "testability", "scope",
|
|
288
|
-
"feasibility", "clarity",
|
|
289
|
-
],
|
|
290
|
-
},
|
|
291
|
-
},
|
|
292
|
-
required: ["severity", "category", "issue", "suggested_fix"],
|
|
293
|
-
additionalProperties: false,
|
|
294
|
-
},
|
|
295
|
-
},
|
|
296
|
-
missing_sections: { type: "array", items: { type: "string" } },
|
|
297
|
-
questions: { type: "array", items: { type: "string" } },
|
|
298
|
-
},
|
|
299
|
-
required: ["verdict", "summary", "issues", "missing_sections", "questions"],
|
|
300
|
-
additionalProperties: false,
|
|
301
|
-
};
|
|
302
|
-
|
|
303
|
-
/** JSON schema for orchestrator structured output */
|
|
304
|
-
export const ORCHESTRATOR_SCHEMA: Record<string, unknown> = {
|
|
305
|
-
type: "object",
|
|
306
|
-
properties: {
|
|
307
|
-
complexity: { type: "string", enum: ["simple", "medium", "high"] },
|
|
308
|
-
category: {
|
|
309
|
-
type: "string",
|
|
310
|
-
enum: [
|
|
311
|
-
"code",
|
|
312
|
-
"infrastructure",
|
|
313
|
-
"documentation",
|
|
314
|
-
"life",
|
|
315
|
-
"business",
|
|
316
|
-
"design",
|
|
317
|
-
"research",
|
|
318
|
-
],
|
|
319
|
-
},
|
|
320
|
-
selectedAgents: { type: "array", items: { type: "string" } },
|
|
321
|
-
reasoning: { type: "string" },
|
|
322
|
-
skipReason: { type: "string" },
|
|
323
|
-
},
|
|
324
|
-
required: ["complexity", "category", "selectedAgents", "reasoning"],
|
|
325
|
-
additionalProperties: false,
|
|
326
|
-
};
|
|
327
|
-
|
|
328
|
-
// ---------------------------------------------------------------------------
|
|
329
|
-
// Prompt Constants
|
|
330
|
-
// ---------------------------------------------------------------------------
|
|
331
|
-
|
|
332
|
-
export const REVIEW_PROMPT_PREFIX = `You are a senior staff software engineer acting as a strict plan reviewer.
|
|
333
|
-
|
|
334
|
-
Review the PLAN below. Focus on:
|
|
335
|
-
- missing steps, unclear assumptions, edge cases
|
|
336
|
-
- security/privacy concerns
|
|
337
|
-
- testing/rollout/rollback completeness
|
|
338
|
-
- operational concerns (observability, failure modes)
|
|
339
|
-
`;
|
|
340
|
-
|
|
341
|
-
export const AGENT_REVIEW_PROMPT_PREFIX = `# SINGLE-TURN PLAN REVIEW
|
|
342
|
-
|
|
343
|
-
## CRITICAL: ONE TURN ONLY
|
|
344
|
-
You have exactly ONE response to complete this review. Do NOT attempt multi-step workflows, context queries, or phased analysis. Analyze the plan and output your review immediately.
|
|
345
|
-
|
|
346
|
-
## YOUR TASK
|
|
347
|
-
Review the plan below from your area of expertise. Then call StructuredOutput with your assessment.
|
|
348
|
-
|
|
349
|
-
## REQUIRED OUTPUT (all fields must have content)
|
|
350
|
-
Call StructuredOutput with:
|
|
351
|
-
- **verdict**: "pass" (no concerns), "warn" (some concerns), or "fail" (critical issues)
|
|
352
|
-
- **summary**: 2-3 sentences with your overall assessment and key findings (REQUIRED)
|
|
353
|
-
- **issues**: Array of concerns found. Format each as:
|
|
354
|
-
{"severity": "high/medium/low", "category": "...", "issue": "...", "suggested_fix": "...", "dimension": "..."}
|
|
355
|
-
- **dimension**: Classify each issue into exactly one dimension:
|
|
356
|
-
completeness, simplicity, security, performance, reliability,
|
|
357
|
-
maintainability, testability, scope, feasibility, or clarity.
|
|
358
|
-
Examples: "missing error handling" → reliability, "excessive abstraction" → simplicity,
|
|
359
|
-
"no test strategy" → testability, "missing deployment steps" → completeness,
|
|
360
|
-
"unclear interaction between components" → clarity.
|
|
361
|
-
- **missing_sections**: Topics the plan should address but doesn't
|
|
362
|
-
- **questions**: Things that need clarification before implementation
|
|
363
|
-
|
|
364
|
-
## IMPORTANT RULES
|
|
365
|
-
1. A "warn" verdict MUST include at least one issue explaining why
|
|
366
|
-
2. Summary MUST explain your reasoning, not just "looks good" or empty
|
|
367
|
-
3. Focus on your expertise area (architecture, security, performance, etc.)
|
|
368
|
-
4. Output StructuredOutput NOW - no other tools, no questions, no delays
|
|
369
|
-
5. Return ONLY your top 3 most critical issues. Prioritize high-severity over medium/low. Quality over quantity.
|
|
370
|
-
`;
|
|
266
|
+
// Re-export for backwards compatibility
|
|
267
|
+
export { REVIEW_SCHEMA, ORCHESTRATOR_SCHEMA, REVIEW_PROMPT_PREFIX, AGENT_REVIEW_PROMPT_PREFIX } from "./reviewers/schemas.js";
|
|
371
268
|
|
|
372
269
|
// ---------------------------------------------------------------------------
|
|
373
270
|
// Display Defaults
|
|
@@ -13,18 +13,6 @@
|
|
|
13
13
|
},
|
|
14
14
|
"planReview": {
|
|
15
15
|
"enabled": true,
|
|
16
|
-
"reviewers": {
|
|
17
|
-
"codex": {
|
|
18
|
-
"enabled": true,
|
|
19
|
-
"model": "gpt-5.1-codex-mini",
|
|
20
|
-
"timeout": 120
|
|
21
|
-
},
|
|
22
|
-
"gemini": {
|
|
23
|
-
"enabled": false,
|
|
24
|
-
"model": "",
|
|
25
|
-
"timeout": 120
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
16
|
"display": {
|
|
29
17
|
"maxIssues": 12,
|
|
30
18
|
"maxMissingSections": 12,
|
|
@@ -53,8 +41,8 @@
|
|
|
53
41
|
},
|
|
54
42
|
"reviewIterations": {
|
|
55
43
|
"simple": 1,
|
|
56
|
-
"medium":
|
|
57
|
-
"high":
|
|
44
|
+
"medium": 3,
|
|
45
|
+
"high": 5
|
|
58
46
|
},
|
|
59
47
|
"highIssueThreshold": 2,
|
|
60
48
|
"earlyExitOnAllPass": true,
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aiwcli",
|
|
3
3
|
"description": "AI Workflow CLI - Command-line interface for AI-powered workflows",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.12.0",
|
|
5
5
|
"author": "jofu-tofu",
|
|
6
6
|
"bin": {
|
|
7
7
|
"aiw": "bin/run.js"
|
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@eslint/compat": "^1",
|
|
24
|
-
"@oclif/prettier-config": "^0.2.1",
|
|
25
24
|
"@oclif/test": "^4",
|
|
26
25
|
"@types/chai": "^4",
|
|
27
26
|
"@types/mocha": "^10",
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
/**
|
|
3
|
-
* Plan context hook — handles question marking and advisory question nudges.
|
|
4
|
-
*
|
|
5
|
-
* Registered for two events:
|
|
6
|
-
* - PostToolUse: AskUserQuestion — marks that questions were asked this session.
|
|
7
|
-
* - PreToolUse: Task — nudges Plan subagent to ask questions first (advisory, never blocks).
|
|
8
|
-
*
|
|
9
|
-
* All enforcement is advisory: injects additionalContext to guide Claude toward asking
|
|
10
|
-
* non-obvious questions, but never blocks the tool call. Claude can proceed regardless.
|
|
11
|
-
*
|
|
12
|
-
* Fail-safe: Any error allows the action silently.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import { getProjectRoot } from "../../_shared/lib-ts/base/constants.js";
|
|
16
|
-
import {
|
|
17
|
-
emitContext,
|
|
18
|
-
loadHookInput,
|
|
19
|
-
logDebug,
|
|
20
|
-
logDiagnostic,
|
|
21
|
-
logInfo,
|
|
22
|
-
runHook,
|
|
23
|
-
} from "../../_shared/lib-ts/base/hook-utils.js";
|
|
24
|
-
import { isInternalCall } from "../../_shared/lib-ts/base/subprocess-utils.js";
|
|
25
|
-
import { getEvaluationContextReminder } from "../../_shared/lib-ts/templates/plan-context.js";
|
|
26
|
-
import { markQuestionsAsked, wasQuestionsAsked } from "../lib-ts/cc-native-state.js";
|
|
27
|
-
|
|
28
|
-
const CONTEXT_REMINDER = getEvaluationContextReminder();
|
|
29
|
-
|
|
30
|
-
const TASK_ENFORCEMENT_CONTEXT =
|
|
31
|
-
"Before spawning a Plan agent, consider asking the user non-obvious questions " +
|
|
32
|
-
"via AskUserQuestion. Code exploration reveals WHAT exists — questions reveal WHAT MATTERS.\n\n" +
|
|
33
|
-
"Generate 5+ candidate questions across these categories, then keep only 3-4 where " +
|
|
34
|
-
"different answers would lead to meaningfully different plans:\n\n" +
|
|
35
|
-
"1. INTENT & SUCCESS CRITERIA — What does 'done well' look like? Are there multiple " +
|
|
36
|
-
"interpretations of this request? What's a 10 vs a 6?\n\n" +
|
|
37
|
-
"2. CONSTRAINTS & HISTORY — Has this been attempted before? Are there off-limits areas, " +
|
|
38
|
-
"performance requirements, or security considerations not visible in the code?\n\n" +
|
|
39
|
-
"3. TRADE-OFF PREFERENCES — Speed vs thoroughness? Minimal change vs clean architecture? " +
|
|
40
|
-
"Backward compatibility vs clean break?\n\n" +
|
|
41
|
-
"Frame each question with 2-3 concrete options so the user can choose rather than compose. " +
|
|
42
|
-
"Use AskUserQuestion with structured options — never ask questions as inline text.";
|
|
43
|
-
|
|
44
|
-
function isPlanTask(payload: Record<string, unknown>): boolean {
|
|
45
|
-
const toolInput = payload.tool_input;
|
|
46
|
-
if (!toolInput || typeof toolInput !== "object") return false;
|
|
47
|
-
return String((toolInput as Record<string, unknown>).subagent_type ?? "") === "Plan";
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function main(): void {
|
|
51
|
-
// Guard: skip for internal subprocess calls (prevents recursive hook execution)
|
|
52
|
-
if (isInternalCall()) return;
|
|
53
|
-
|
|
54
|
-
const payload = loadHookInput();
|
|
55
|
-
if (!payload) return;
|
|
56
|
-
|
|
57
|
-
const toolName = payload.tool_name;
|
|
58
|
-
const hookEvent = payload.hook_event_name ?? "unknown";
|
|
59
|
-
logDiagnostic(
|
|
60
|
-
"add_plan_context",
|
|
61
|
-
"receive",
|
|
62
|
-
`tool=${toolName}, event=${hookEvent}`,
|
|
63
|
-
{ inputs: { tool_name: toolName, hook_event: hookEvent } },
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
const projectRoot = getProjectRoot(payload.cwd);
|
|
67
|
-
|
|
68
|
-
// PostToolUse: AskUserQuestion — mark that questions were asked
|
|
69
|
-
if (toolName === "AskUserQuestion") {
|
|
70
|
-
const sessionId = String(payload.session_id ?? "");
|
|
71
|
-
if (sessionId) {
|
|
72
|
-
markQuestionsAsked(sessionId, projectRoot);
|
|
73
|
-
logInfo("add_plan_context", `Marked questions asked for session ${sessionId.slice(0, 8)}...`);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// PreToolUse: Task — nudge Plan subagent to ask questions first (advisory)
|
|
80
|
-
if (toolName === "Task") {
|
|
81
|
-
if (!isPlanTask(payload)) return; // Only gate Plan subagent spawns
|
|
82
|
-
|
|
83
|
-
const permissionMode = payload.permission_mode ?? "";
|
|
84
|
-
if (permissionMode !== "plan") return; // Only enforce during plan mode
|
|
85
|
-
|
|
86
|
-
const sessionId = payload.session_id;
|
|
87
|
-
if (!sessionId) {
|
|
88
|
-
logDebug("add_plan_context", "No session_id for Task gate, skipping enforcement");
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const sessionIdStr = String(sessionId);
|
|
93
|
-
|
|
94
|
-
if (wasQuestionsAsked(sessionIdStr, projectRoot)) {
|
|
95
|
-
logInfo("add_plan_context", "Questions asked, allowing Plan Task with eval context");
|
|
96
|
-
logDiagnostic(
|
|
97
|
-
"add_plan_context",
|
|
98
|
-
"decide",
|
|
99
|
-
"Questions asked, allowing Plan Task",
|
|
100
|
-
{ decision: "allow_with_context", reasoning: "was_questions_asked=True" },
|
|
101
|
-
);
|
|
102
|
-
emitContext(CONTEXT_REMINDER);
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Questions NOT asked: nudge toward asking questions (advisory only)
|
|
107
|
-
logInfo("add_plan_context", "Questions not asked - nudging Plan Task to ask first");
|
|
108
|
-
logDiagnostic(
|
|
109
|
-
"add_plan_context",
|
|
110
|
-
"decide",
|
|
111
|
-
"Questions not asked, nudging Plan Task",
|
|
112
|
-
{ decision: "nudge", reasoning: "was_questions_asked=False, advisory context" },
|
|
113
|
-
);
|
|
114
|
-
emitContext(TASK_ENFORCEMENT_CONTEXT);
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
runHook(main, "add_plan_context");
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Codex CLI plan reviewer.
|
|
3
|
-
* Runs Codex in non-interactive mode with read-only sandbox.
|
|
4
|
-
* See cc-native-plan-review-spec.md §4.11
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import * as fs from "node:fs";
|
|
8
|
-
import * as os from "node:os";
|
|
9
|
-
import * as path from "node:path";
|
|
10
|
-
import { logDebug, logInfo, logWarn, logError } from "../../../_shared/lib-ts/base/logger.js";
|
|
11
|
-
import { findExecutable, execFileAsync } from "../../../_shared/lib-ts/base/subprocess-utils.js";
|
|
12
|
-
import { parseJsonMaybe, coerceToReview } from "../json-parser.js";
|
|
13
|
-
import { REVIEW_PROMPT_PREFIX } from "../types.js";
|
|
14
|
-
import type { ReviewerResult, ReviewOptions } from "../types.js";
|
|
15
|
-
import { makeResult } from "./types.js";
|
|
16
|
-
import type { Reviewer } from "./types.js";
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Codex reviewer — runs codex exec --sandbox read-only.
|
|
20
|
-
*/
|
|
21
|
-
export class CodexReviewer implements Reviewer {
|
|
22
|
-
private settings: Record<string, unknown>;
|
|
23
|
-
|
|
24
|
-
constructor(settings: Record<string, unknown>) {
|
|
25
|
-
this.settings = settings;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async review(
|
|
29
|
-
plan: string,
|
|
30
|
-
schema: Record<string, unknown>,
|
|
31
|
-
options: ReviewOptions,
|
|
32
|
-
): Promise<ReviewerResult> {
|
|
33
|
-
return runCodexReview(plan, schema, this.settings);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Run Codex CLI to review the plan.
|
|
39
|
-
* Never throws — returns error ReviewerResult on failure.
|
|
40
|
-
*/
|
|
41
|
-
export async function runCodexReview(
|
|
42
|
-
plan: string,
|
|
43
|
-
schema: Record<string, unknown>,
|
|
44
|
-
settings: Record<string, unknown>,
|
|
45
|
-
): Promise<ReviewerResult> {
|
|
46
|
-
const codexSettings =
|
|
47
|
-
((settings.reviewers as Record<string, unknown> | undefined)?.codex as
|
|
48
|
-
| Record<string, unknown>
|
|
49
|
-
| undefined) ?? {};
|
|
50
|
-
const timeout = (codexSettings.timeout as number) ?? 120;
|
|
51
|
-
const model = (codexSettings.model as string) ?? "";
|
|
52
|
-
|
|
53
|
-
const codexPath = findExecutable("codex");
|
|
54
|
-
if (!codexPath) {
|
|
55
|
-
logWarn("codex", "CLI not found on PATH");
|
|
56
|
-
return makeResult("codex", false, "skip", {}, "", "codex CLI not found on PATH");
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
logDebug("codex", `Found CLI at: ${codexPath}`);
|
|
60
|
-
|
|
61
|
-
const prompt = `${REVIEW_PROMPT_PREFIX}
|
|
62
|
-
Return ONLY a JSON object that matches this JSON Schema:
|
|
63
|
-
${JSON.stringify(schema)}
|
|
64
|
-
|
|
65
|
-
PLAN:
|
|
66
|
-
<<<
|
|
67
|
-
${plan}
|
|
68
|
-
>>>
|
|
69
|
-
`;
|
|
70
|
-
|
|
71
|
-
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "codex-review-"));
|
|
72
|
-
|
|
73
|
-
try {
|
|
74
|
-
const schemaPath = path.join(tmpDir, "schema.json");
|
|
75
|
-
const outPath = path.join(tmpDir, "codex_review.json");
|
|
76
|
-
|
|
77
|
-
fs.writeFileSync(schemaPath, JSON.stringify(schema, null, 2), "utf-8");
|
|
78
|
-
|
|
79
|
-
const cmdArgs = ["exec", "--sandbox", "read-only"];
|
|
80
|
-
|
|
81
|
-
if (model) {
|
|
82
|
-
cmdArgs.push("--model", model);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
cmdArgs.push("--output-schema", schemaPath, "-o", outPath, "-");
|
|
86
|
-
|
|
87
|
-
logDebug("codex", `Running command: codex ${cmdArgs.join(" ")}`);
|
|
88
|
-
|
|
89
|
-
const result = await execFileAsync(codexPath, cmdArgs, {
|
|
90
|
-
input: prompt,
|
|
91
|
-
timeout: timeout * 1000,
|
|
92
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
93
|
-
shell: process.platform === "win32",
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
if (result.killed || result.signal === "SIGTERM") {
|
|
97
|
-
logWarn("codex", `TIMEOUT after ${timeout}s`);
|
|
98
|
-
return makeResult("codex", false, "error", {}, "", `codex timed out after ${timeout}s`);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (!result.stdout && !result.stderr && !fs.existsSync(outPath) && result.exitCode !== 0) {
|
|
102
|
-
logError("codex", `Process exited with code ${result.exitCode} and no output`);
|
|
103
|
-
return makeResult("codex", false, "error", {}, "", `codex failed to run (exit ${result.exitCode})`);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
logDebug("codex", `Exit code: ${result.exitCode}`);
|
|
107
|
-
|
|
108
|
-
let raw = "";
|
|
109
|
-
if (fs.existsSync(outPath)) {
|
|
110
|
-
raw = fs.readFileSync(outPath, "utf-8");
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const obj = parseJsonMaybe(raw) ?? parseJsonMaybe(result.stdout);
|
|
114
|
-
const [ok, verdict, norm] = coerceToReview(
|
|
115
|
-
obj,
|
|
116
|
-
"Retry or check CLI auth/config.",
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
const err = result.stderr.trim();
|
|
120
|
-
return makeResult("codex", ok, verdict, norm, raw || result.stdout, err);
|
|
121
|
-
} finally {
|
|
122
|
-
// Clean up temp directory
|
|
123
|
-
try {
|
|
124
|
-
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
125
|
-
} catch {
|
|
126
|
-
// Best effort cleanup
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Gemini CLI plan reviewer.
|
|
3
|
-
* Runs Gemini CLI in YOLO mode (auto-approve).
|
|
4
|
-
* See cc-native-plan-review-spec.md §4.12
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { logDebug, logInfo, logWarn, logError } from "../../../_shared/lib-ts/base/logger.js";
|
|
8
|
-
import { findExecutable, execFileAsync } from "../../../_shared/lib-ts/base/subprocess-utils.js";
|
|
9
|
-
import { parseJsonMaybe, coerceToReview } from "../json-parser.js";
|
|
10
|
-
import type { ReviewerResult, ReviewOptions } from "../types.js";
|
|
11
|
-
import { makeResult } from "./types.js";
|
|
12
|
-
import type { Reviewer } from "./types.js";
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Gemini reviewer — runs gemini -y -p <instruction>.
|
|
16
|
-
*/
|
|
17
|
-
export class GeminiReviewer implements Reviewer {
|
|
18
|
-
private settings: Record<string, unknown>;
|
|
19
|
-
|
|
20
|
-
constructor(settings: Record<string, unknown>) {
|
|
21
|
-
this.settings = settings;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async review(
|
|
25
|
-
plan: string,
|
|
26
|
-
schema: Record<string, unknown>,
|
|
27
|
-
options: ReviewOptions,
|
|
28
|
-
): Promise<ReviewerResult> {
|
|
29
|
-
return runGeminiReview(plan, schema, this.settings);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Run Gemini CLI to review the plan.
|
|
35
|
-
* Never throws — returns error ReviewerResult on failure.
|
|
36
|
-
*/
|
|
37
|
-
export async function runGeminiReview(
|
|
38
|
-
plan: string,
|
|
39
|
-
schema: Record<string, unknown>,
|
|
40
|
-
settings: Record<string, unknown>,
|
|
41
|
-
): Promise<ReviewerResult> {
|
|
42
|
-
const geminiSettings =
|
|
43
|
-
((settings.reviewers as Record<string, unknown> | undefined)?.gemini as
|
|
44
|
-
| Record<string, unknown>
|
|
45
|
-
| undefined) ?? {};
|
|
46
|
-
const timeout = (geminiSettings.timeout as number) ?? 120;
|
|
47
|
-
const model = (geminiSettings.model as string) ?? "";
|
|
48
|
-
|
|
49
|
-
const geminiPath = findExecutable("gemini");
|
|
50
|
-
if (!geminiPath) {
|
|
51
|
-
logWarn("gemini", "CLI not found on PATH");
|
|
52
|
-
return makeResult("gemini", false, "skip", {}, "", "gemini CLI not found on PATH");
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
logDebug("gemini", `Found CLI at: ${geminiPath}`);
|
|
56
|
-
|
|
57
|
-
const instruction = `
|
|
58
|
-
|
|
59
|
-
Review the PLAN above as a senior staff software engineer. Focus on:
|
|
60
|
-
- missing steps, unclear assumptions, edge cases
|
|
61
|
-
- security/privacy concerns
|
|
62
|
-
- testing/rollout/rollback completeness
|
|
63
|
-
- operational concerns (observability, failure modes)
|
|
64
|
-
|
|
65
|
-
Return ONLY a JSON object that matches this JSON Schema (no markdown, no code fences):
|
|
66
|
-
${JSON.stringify(schema)}
|
|
67
|
-
`;
|
|
68
|
-
|
|
69
|
-
const cmdArgs = ["-y", "-p", instruction];
|
|
70
|
-
|
|
71
|
-
if (model) {
|
|
72
|
-
cmdArgs.push("--model", model);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
logDebug("gemini", "Running command: gemini -y -p <instruction>");
|
|
76
|
-
|
|
77
|
-
const result = await execFileAsync(geminiPath, cmdArgs, {
|
|
78
|
-
input: plan,
|
|
79
|
-
timeout: timeout * 1000,
|
|
80
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
81
|
-
shell: process.platform === "win32",
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
if (result.killed || result.signal === "SIGTERM") {
|
|
85
|
-
logWarn("gemini", `TIMEOUT after ${timeout}s`);
|
|
86
|
-
return makeResult("gemini", false, "error", {}, "", `gemini timed out after ${timeout}s`);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if (!result.stdout && !result.stderr && result.exitCode !== 0) {
|
|
90
|
-
logError("gemini", `Process exited with code ${result.exitCode}`);
|
|
91
|
-
return makeResult("gemini", false, "error", {}, "", `gemini failed to run (exit ${result.exitCode})`);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
logDebug("gemini", `Exit code: ${result.exitCode}`);
|
|
95
|
-
|
|
96
|
-
const raw = result.stdout.trim();
|
|
97
|
-
const err = result.stderr.trim();
|
|
98
|
-
|
|
99
|
-
const obj = parseJsonMaybe(raw);
|
|
100
|
-
const [ok, verdict, norm] = coerceToReview(
|
|
101
|
-
obj,
|
|
102
|
-
"Retry or check CLI auth/config.",
|
|
103
|
-
);
|
|
104
|
-
|
|
105
|
-
return makeResult("gemini", ok, verdict, norm, raw, err);
|
|
106
|
-
}
|
|
107
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/dist/templates/cc-native/_cc-native/agents/{RISK-FMEA.md → plan-review/RISK-FMEA.md}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|