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.
Files changed (108) hide show
  1. package/dist/commands/clear.d.ts +8 -0
  2. package/dist/commands/clear.js +86 -0
  3. package/dist/lib/bmad-installer.d.ts +2 -27
  4. package/dist/lib/bmad-installer.js +3 -43
  5. package/dist/lib/claude-settings-types.d.ts +2 -1
  6. package/dist/lib/env-compat.d.ts +0 -8
  7. package/dist/lib/env-compat.js +0 -12
  8. package/dist/lib/git/index.d.ts +0 -1
  9. package/dist/lib/gitignore-manager.d.ts +0 -2
  10. package/dist/lib/gitignore-manager.js +1 -1
  11. package/dist/lib/hooks-merger.d.ts +1 -15
  12. package/dist/lib/hooks-merger.js +1 -1
  13. package/dist/lib/index.d.ts +3 -7
  14. package/dist/lib/index.js +3 -11
  15. package/dist/lib/output.d.ts +2 -1
  16. package/dist/lib/settings-hierarchy.d.ts +1 -13
  17. package/dist/lib/settings-hierarchy.js +1 -1
  18. package/dist/lib/template-installer.d.ts +5 -9
  19. package/dist/lib/template-installer.js +2 -12
  20. package/dist/lib/template-linter.d.ts +3 -10
  21. package/dist/lib/template-linter.js +2 -2
  22. package/dist/lib/template-resolver.d.ts +6 -0
  23. package/dist/lib/template-resolver.js +10 -0
  24. package/dist/lib/template-settings-reconstructor.d.ts +1 -1
  25. package/dist/lib/template-settings-reconstructor.js +17 -24
  26. package/dist/lib/terminal.d.ts +3 -14
  27. package/dist/lib/terminal.js +0 -4
  28. package/dist/lib/version.d.ts +2 -11
  29. package/dist/lib/version.js +2 -2
  30. package/dist/lib/windsurf-hooks-merger.d.ts +1 -15
  31. package/dist/lib/windsurf-hooks-merger.js +1 -1
  32. package/dist/templates/_shared/.codex/workflows/handoff.md +1 -1
  33. package/dist/templates/_shared/.windsurf/workflows/handoff.md +1 -1
  34. package/dist/templates/_shared/hooks-ts/session_start.ts +15 -20
  35. package/dist/templates/_shared/hooks-ts/user_prompt_submit.ts +12 -14
  36. package/dist/templates/_shared/lib-ts/CLAUDE.md +56 -7
  37. package/dist/templates/_shared/lib-ts/base/hook-utils.ts +174 -43
  38. package/dist/templates/_shared/lib-ts/base/state-io.ts +11 -2
  39. package/dist/templates/_shared/lib-ts/base/subprocess-utils.ts +181 -165
  40. package/dist/templates/_shared/lib-ts/package.json +1 -2
  41. package/dist/templates/_shared/lib-ts/templates/plan-context.ts +27 -34
  42. package/dist/templates/_shared/lib-ts/types.ts +17 -2
  43. package/dist/templates/_shared/scripts/status_line.ts +1 -1
  44. package/dist/templates/_shared/workflows/handoff.md +1 -1
  45. package/dist/templates/cc-native/.claude/settings.json +183 -175
  46. package/dist/templates/cc-native/_cc-native/agents/CLAUDE.md +23 -1
  47. package/dist/templates/cc-native/_cc-native/agents/plan-questions/PLAN-QUESTIONER.md +70 -0
  48. package/dist/templates/cc-native/_cc-native/hooks/CLAUDE.md +6 -1
  49. package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.ts +91 -57
  50. package/dist/templates/cc-native/_cc-native/hooks/enhance_plan_post_subagent.ts +38 -0
  51. package/dist/templates/cc-native/_cc-native/hooks/enhance_plan_post_write.ts +51 -0
  52. package/dist/templates/cc-native/_cc-native/hooks/mark_questions_asked.ts +53 -0
  53. package/dist/templates/cc-native/_cc-native/hooks/plan_questions_early.ts +15 -15
  54. package/dist/templates/cc-native/_cc-native/lib-ts/artifacts.ts +95 -65
  55. package/dist/templates/cc-native/_cc-native/lib-ts/cc-native-state.ts +64 -16
  56. package/dist/templates/cc-native/_cc-native/lib-ts/cli-output-parser.ts +1 -1
  57. package/dist/templates/cc-native/_cc-native/lib-ts/corroboration.ts +6 -2
  58. package/dist/templates/cc-native/_cc-native/lib-ts/index.ts +0 -4
  59. package/dist/templates/cc-native/_cc-native/lib-ts/orchestrator.ts +40 -219
  60. package/dist/templates/cc-native/_cc-native/lib-ts/plan-enhancement.ts +41 -0
  61. package/dist/templates/cc-native/_cc-native/lib-ts/plan-questions.ts +101 -0
  62. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/agent.ts +22 -226
  63. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/base/base-agent.ts +217 -0
  64. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/index.ts +5 -3
  65. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/providers/claude-agent.ts +65 -0
  66. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/providers/codex-agent.ts +184 -0
  67. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/providers/gemini-agent.ts +39 -0
  68. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/providers/orchestrator-claude-agent.ts +195 -0
  69. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/schemas.ts +201 -0
  70. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/types.ts +3 -5
  71. package/dist/templates/cc-native/_cc-native/lib-ts/types.ts +4 -107
  72. package/dist/templates/cc-native/_cc-native/plan-review.config.json +2 -14
  73. package/oclif.manifest.json +1 -1
  74. package/package.json +1 -2
  75. package/dist/templates/cc-native/_cc-native/hooks/add_plan_context.ts +0 -119
  76. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/codex.ts +0 -130
  77. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/gemini.ts +0 -107
  78. /package/dist/templates/cc-native/_cc-native/agents/{ARCH-EVOLUTION.md → plan-review/ARCH-EVOLUTION.md} +0 -0
  79. /package/dist/templates/cc-native/_cc-native/agents/{ARCH-PATTERNS.md → plan-review/ARCH-PATTERNS.md} +0 -0
  80. /package/dist/templates/cc-native/_cc-native/agents/{ARCH-STRUCTURE.md → plan-review/ARCH-STRUCTURE.md} +0 -0
  81. /package/dist/templates/cc-native/_cc-native/agents/{ASSUMPTION-TRACER.md → plan-review/ASSUMPTION-TRACER.md} +0 -0
  82. /package/dist/templates/cc-native/_cc-native/agents/{CLARITY-AUDITOR.md → plan-review/CLARITY-AUDITOR.md} +0 -0
  83. /package/dist/templates/cc-native/_cc-native/agents/{COMPLETENESS-FEASIBILITY.md → plan-review/COMPLETENESS-FEASIBILITY.md} +0 -0
  84. /package/dist/templates/cc-native/_cc-native/agents/{COMPLETENESS-GAPS.md → plan-review/COMPLETENESS-GAPS.md} +0 -0
  85. /package/dist/templates/cc-native/_cc-native/agents/{COMPLETENESS-ORDERING.md → plan-review/COMPLETENESS-ORDERING.md} +0 -0
  86. /package/dist/templates/cc-native/_cc-native/agents/{CONSTRAINT-VALIDATOR.md → plan-review/CONSTRAINT-VALIDATOR.md} +0 -0
  87. /package/dist/templates/cc-native/_cc-native/agents/{DESIGN-ADR-VALIDATOR.md → plan-review/DESIGN-ADR-VALIDATOR.md} +0 -0
  88. /package/dist/templates/cc-native/_cc-native/agents/{DESIGN-SCALE-MATCHER.md → plan-review/DESIGN-SCALE-MATCHER.md} +0 -0
  89. /package/dist/templates/cc-native/_cc-native/agents/{DEVILS-ADVOCATE.md → plan-review/DEVILS-ADVOCATE.md} +0 -0
  90. /package/dist/templates/cc-native/_cc-native/agents/{DOCUMENTATION-PHILOSOPHY.md → plan-review/DOCUMENTATION-PHILOSOPHY.md} +0 -0
  91. /package/dist/templates/cc-native/_cc-native/agents/{HANDOFF-READINESS.md → plan-review/HANDOFF-READINESS.md} +0 -0
  92. /package/dist/templates/cc-native/_cc-native/agents/{HIDDEN-COMPLEXITY.md → plan-review/HIDDEN-COMPLEXITY.md} +0 -0
  93. /package/dist/templates/cc-native/_cc-native/agents/{INCREMENTAL-DELIVERY.md → plan-review/INCREMENTAL-DELIVERY.md} +0 -0
  94. /package/dist/templates/cc-native/_cc-native/agents/{RISK-DEPENDENCY.md → plan-review/RISK-DEPENDENCY.md} +0 -0
  95. /package/dist/templates/cc-native/_cc-native/agents/{RISK-FMEA.md → plan-review/RISK-FMEA.md} +0 -0
  96. /package/dist/templates/cc-native/_cc-native/agents/{RISK-PREMORTEM.md → plan-review/RISK-PREMORTEM.md} +0 -0
  97. /package/dist/templates/cc-native/_cc-native/agents/{RISK-REVERSIBILITY.md → plan-review/RISK-REVERSIBILITY.md} +0 -0
  98. /package/dist/templates/cc-native/_cc-native/agents/{SCOPE-BOUNDARY.md → plan-review/SCOPE-BOUNDARY.md} +0 -0
  99. /package/dist/templates/cc-native/_cc-native/agents/{SIMPLICITY-GUARDIAN.md → plan-review/SIMPLICITY-GUARDIAN.md} +0 -0
  100. /package/dist/templates/cc-native/_cc-native/agents/{SKEPTIC.md → plan-review/SKEPTIC.md} +0 -0
  101. /package/dist/templates/cc-native/_cc-native/agents/{TESTDRIVEN-BEHAVIOR-AUDITOR.md → plan-review/TESTDRIVEN-BEHAVIOR-AUDITOR.md} +0 -0
  102. /package/dist/templates/cc-native/_cc-native/agents/{TESTDRIVEN-CHARACTERIZATION.md → plan-review/TESTDRIVEN-CHARACTERIZATION.md} +0 -0
  103. /package/dist/templates/cc-native/_cc-native/agents/{TESTDRIVEN-FIRST-VALIDATOR.md → plan-review/TESTDRIVEN-FIRST-VALIDATOR.md} +0 -0
  104. /package/dist/templates/cc-native/_cc-native/agents/{TESTDRIVEN-PYRAMID-ANALYZER.md → plan-review/TESTDRIVEN-PYRAMID-ANALYZER.md} +0 -0
  105. /package/dist/templates/cc-native/_cc-native/agents/{TRADEOFF-COSTS.md → plan-review/TRADEOFF-COSTS.md} +0 -0
  106. /package/dist/templates/cc-native/_cc-native/agents/{TRADEOFF-STAKEHOLDERS.md → plan-review/TRADEOFF-STAKEHOLDERS.md} +0 -0
  107. /package/dist/templates/cc-native/_cc-native/agents/{VERIFY-COVERAGE.md → plan-review/VERIFY-COVERAGE.md} +0 -0
  108. /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 { ReviewData, ReviewerResult, Verdict } from "../types.js";
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> | ReviewData,
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
- /** JSON schema for review structured output */
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": 1,
57
- "high": 2
44
+ "medium": 3,
45
+ "high": 5
58
46
  },
59
47
  "highIssueThreshold": 2,
60
48
  "earlyExitOnAllPass": true,
@@ -416,5 +416,5 @@
416
416
  ]
417
417
  }
418
418
  },
419
- "version": "0.11.1"
419
+ "version": "0.12.0"
420
420
  }
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.11.1",
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
-