aiwcli 0.9.4 → 0.9.6

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 (45) hide show
  1. package/dist/templates/_shared/hooks/__pycache__/user_prompt_submit.cpython-313.pyc +0 -0
  2. package/dist/templates/_shared/hooks/user_prompt_submit.py +1 -1
  3. package/dist/templates/_shared/lib/base/__pycache__/stop_words.cpython-313.pyc +0 -0
  4. package/dist/templates/_shared/lib/base/__pycache__/utils.cpython-313.pyc +0 -0
  5. package/dist/templates/_shared/lib/base/stop_words.py +32 -0
  6. package/dist/templates/_shared/lib/base/utils.py +5 -20
  7. package/dist/templates/cc-native/{.claude/agents/cc-native → _cc-native/agents}/ACCESSIBILITY-TESTER.md +0 -1
  8. package/dist/templates/cc-native/_cc-native/agents/CLAUDE.md +56 -0
  9. package/dist/templates/cc-native/{.claude/agents/cc-native → _cc-native/agents}/CODE-REVIEWER.md +0 -1
  10. package/dist/templates/cc-native/{.claude/agents/cc-native → _cc-native/agents}/CONTEXT-EXTRACTOR.md +0 -1
  11. package/dist/templates/cc-native/{.claude/agents/cc-native → _cc-native/agents}/PENETRATION-TESTER.md +0 -1
  12. package/dist/templates/cc-native/{.claude/agents/cc-native → _cc-native/agents}/PERFORMANCE-ENGINEER.md +0 -1
  13. package/dist/templates/cc-native/{.claude/agents/cc-native → _cc-native/agents}/PLAN-ORCHESTRATOR.md +0 -1
  14. package/dist/templates/cc-native/{.claude/agents/cc-native → _cc-native/agents}/TRADE-OFF-ILLUMINATOR.md +0 -1
  15. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/cc-native-plan-review.cpython-313.pyc +0 -0
  16. package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.py +10 -11
  17. package/dist/templates/cc-native/_cc-native/lib/__pycache__/orchestrator.cpython-313.pyc +0 -0
  18. package/dist/templates/cc-native/_cc-native/lib/orchestrator.py +36 -18
  19. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/agent.cpython-313.pyc +0 -0
  20. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/base.cpython-313.pyc +0 -0
  21. package/dist/templates/cc-native/_cc-native/lib/reviewers/agent.py +11 -9
  22. package/dist/templates/cc-native/_cc-native/lib/reviewers/base.py +1 -2
  23. package/dist/templates/cc-native/_cc-native/plan-review.config.json +2 -4
  24. package/dist/templates/cc-native/_cc-native/scripts/__pycache__/aggregate_agents.cpython-313.pyc +0 -0
  25. package/dist/templates/cc-native/_cc-native/scripts/aggregate_agents.py +25 -8
  26. package/oclif.manifest.json +1 -1
  27. package/package.json +1 -1
  28. /package/dist/templates/cc-native/{.claude/agents/cc-native → _cc-native/agents}/ARCHITECT-REVIEWER.md +0 -0
  29. /package/dist/templates/cc-native/{.claude/agents/cc-native → _cc-native/agents}/ASSUMPTION-CHAIN-TRACER.md +0 -0
  30. /package/dist/templates/cc-native/{.claude/agents/cc-native → _cc-native/agents}/CLARITY-AUDITOR.md +0 -0
  31. /package/dist/templates/cc-native/{.claude/agents/cc-native → _cc-native/agents}/COMPLETENESS-CHECKER.md +0 -0
  32. /package/dist/templates/cc-native/{.claude/agents/cc-native → _cc-native/agents}/DEVILS-ADVOCATE.md +0 -0
  33. /package/dist/templates/cc-native/{.claude/agents/cc-native → _cc-native/agents}/DOCUMENTATION-REVIEWER.md +0 -0
  34. /package/dist/templates/cc-native/{.claude/agents/cc-native → _cc-native/agents}/FEASIBILITY-ANALYST.md +0 -0
  35. /package/dist/templates/cc-native/{.claude/agents/cc-native → _cc-native/agents}/FRESH-PERSPECTIVE.md +0 -0
  36. /package/dist/templates/cc-native/{.claude/agents/cc-native → _cc-native/agents}/HANDOFF-READINESS.md +0 -0
  37. /package/dist/templates/cc-native/{.claude/agents/cc-native → _cc-native/agents}/HIDDEN-COMPLEXITY-DETECTOR.md +0 -0
  38. /package/dist/templates/cc-native/{.claude/agents/cc-native → _cc-native/agents}/INCENTIVE-MAPPER.md +0 -0
  39. /package/dist/templates/cc-native/{.claude/agents/cc-native → _cc-native/agents}/PRECEDENT-FINDER.md +0 -0
  40. /package/dist/templates/cc-native/{.claude/agents/cc-native → _cc-native/agents}/REVERSIBILITY-ANALYST.md +0 -0
  41. /package/dist/templates/cc-native/{.claude/agents/cc-native → _cc-native/agents}/RISK-ASSESSOR.md +0 -0
  42. /package/dist/templates/cc-native/{.claude/agents/cc-native → _cc-native/agents}/SECOND-ORDER-ANALYST.md +0 -0
  43. /package/dist/templates/cc-native/{.claude/agents/cc-native → _cc-native/agents}/SIMPLICITY-GUARDIAN.md +0 -0
  44. /package/dist/templates/cc-native/{.claude/agents/cc-native → _cc-native/agents}/SKEPTIC.md +0 -0
  45. /package/dist/templates/cc-native/{.claude/agents/cc-native → _cc-native/agents}/STAKEHOLDER-ADVOCATE.md +0 -0
@@ -103,7 +103,7 @@ def _update_in_flight_status(context_id: str, hook_input: dict, project_root: Pa
103
103
  elif permission_mode != "plan":
104
104
  # Any non-plan permission mode transitions pending/planning to implementing
105
105
  # This includes "default" (after /clear) and "acceptEdits"/"bypassPermissions"
106
- if current_mode in ["pending_implementation", "planning"]:
106
+ if current_mode in ["pending_implementation", "planning", "none"]:
107
107
  update_plan_status(context_id, "implementing", project_root=project_root)
108
108
  eprint(f"[user_prompt_submit] Set status to 'implementing' (permission_mode={permission_mode})")
109
109
 
@@ -155,4 +155,36 @@ STOP_WORDS = {
155
155
  'part', 'parts', 'point', 'points',
156
156
  'time', 'times', 'next', 'last', 'end',
157
157
  'set', 'list', 'group', 'item', 'items',
158
+
159
+ # ========================================================================
160
+ # PROGRAMMING KEYWORDS (code tokens that leak from pasted code)
161
+ # ========================================================================
162
+ 'self', 'def', 'return', 'import', 'true', 'false', 'none', 'str',
163
+ 'const', 'async', 'class', 'assert', 'except', 'dict', 'len', 'args',
164
+ 'sys', 'eprint', 'elif', 'lambda', 'yield', 'pass',
165
+
166
+ # ========================================================================
167
+ # GENERIC ADJECTIVES (non-specific modifiers)
168
+ # ========================================================================
169
+ 'high', 'low', 'important', 'critical', 'optional', 'manual',
170
+ 'real', 'empty', 'stable', 'active', 'proper', 'correct',
171
+ 'basic', 'main', 'primary', 'secondary', 'general', 'overall',
172
+
173
+ # ========================================================================
174
+ # GENERIC TECHNICAL NOUNS (common but non-specific)
175
+ # ========================================================================
176
+ 'information', 'format', 'status', 'method', 'purpose', 'result',
177
+ 'source', 'value', 'option', 'options', 'feature', 'features', 'issue',
178
+ 'process', 'version', 'mode', 'state',
179
+
180
+ # ========================================================================
181
+ # DOCUMENT/CODE STRUCTURE (generic structural terms)
182
+ # ========================================================================
183
+ 'section', 'lines', 'line', 'folder', 'directory', 'index',
184
+ 'level', 'block', 'chunk', 'region', 'header', 'footer',
185
+
186
+ # ========================================================================
187
+ # FRAGMENT WORDS (artifacts from contractions/tokenization)
188
+ # ========================================================================
189
+ 're', 'pl', 'aiw', 've', 'll', 'doesn', 't', 's',
158
190
  }
@@ -138,8 +138,7 @@ def generate_context_id(summary: str, existing_ids: Optional[set] = None) -> str
138
138
  """
139
139
  Generate a context ID from a summary string.
140
140
 
141
- Uses AI inference to create a semantic 10-word summary, then slugifies it.
142
- Falls back to truncate-and-slugify if inference fails.
141
+ Filters stop words from the summary and slugifies the result.
143
142
 
144
143
  Args:
145
144
  summary: Context summary text
@@ -151,24 +150,10 @@ def generate_context_id(summary: str, existing_ids: Optional[set] = None) -> str
151
150
  if not summary or not summary.strip():
152
151
  base_id = "context"
153
152
  else:
154
- # Try AI-powered semantic summary first
155
- base_id = None
156
- try:
157
- from .inference import generate_semantic_summary
158
- semantic = generate_semantic_summary(summary)
159
- if semantic:
160
- # Slugify the semantic summary (word limit already applied in inference)
161
- base_id = sanitize_title(semantic, max_len=100)
162
- eprint(f"[utils] Semantic context ID: {base_id}")
163
- except Exception as e:
164
- eprint(f"[utils] Inference failed, using fallback: {e}")
165
-
166
- # Fallback to old method if inference failed
167
- if not base_id:
168
- # Fallback: use stop word filter, limit to 12 words
169
- from .stop_words import STOP_WORDS
170
- words = [w for w in summary.lower().split() if w not in STOP_WORDS and len(w) > 1][:12]
171
- base_id = sanitize_title(' '.join(words), max_len=100)
153
+ # Use stop word filter, limit to 12 words
154
+ from .stop_words import STOP_WORDS
155
+ words = [w for w in summary.lower().split() if w not in STOP_WORDS and len(w) > 1][:12]
156
+ base_id = sanitize_title(' '.join(words), max_len=100)
172
157
 
173
158
  if not existing_ids:
174
159
  return base_id
@@ -7,7 +7,6 @@ enabled: false
7
7
  categories:
8
8
  - code
9
9
  - design
10
- tools: Read, Grep, Glob, Bash
11
10
  ---
12
11
 
13
12
  ## Role
@@ -0,0 +1,56 @@
1
+ # CC-Native Plan Review Agents
2
+
3
+ Agent persona definitions for single-turn plan review.
4
+
5
+ ## System Prompt vs Agent Flag
6
+
7
+ **Decision:** Use `--system-prompt` with markdown body content instead of `--agent <name>`
8
+
9
+ **Rationale:**
10
+ - Claude Code's `--agent` flag invokes built-in agents designed for multi-turn agentic workflows with tool access
11
+ - Plan review needs single-turn text analysis: read plan, output structured JSON
12
+ - The `--agent` flag ignores our custom markdown content entirely - it loads Claude Code's built-in agent definitions
13
+ - Using `--system-prompt` lets us inject the full persona (expertise, review approach, output requirements) directly
14
+ - Result: faster execution, no tool overhead, and our rich agent descriptions actually get used
15
+
16
+ **Constraint:** If you switch back to `--agent`, the elaborate persona content in these markdown files will be ignored. The reviews will use Claude Code's generic agent behavior instead of our specialized reviewers.
17
+
18
+ ## File Structure
19
+
20
+ Each agent file has:
21
+ - **Frontmatter (YAML):** name, model, focus, categories, enabled
22
+ - **Body (Markdown):** Full persona content → becomes `system_prompt` for `--system-prompt` flag
23
+
24
+ The `aggregate_agents.py` script extracts both parts. The body becomes `AgentConfig.system_prompt`.
25
+
26
+ ## --setting-sources "" Requirement
27
+
28
+ **Decision:** Use `--setting-sources ""` to disable user/project settings loading
29
+
30
+ **Rationale:**
31
+ - Without this flag, Claude Code loads user settings (~43k cached tokens of PAI context)
32
+ - The PAI Algorithm instructions override the agent's system prompt behavior
33
+ - Model tries to follow PAI format instead of calling StructuredOutput directly
34
+ - Result: 6+ turns, 30+ seconds, often no structured output
35
+
36
+ **Constraint:** If you remove `--setting-sources ""`, agent reviews will be slow and unreliable due to PAI context interference.
37
+
38
+ ## --max-turns 3 Requirement
39
+
40
+ **Decision:** Use `--max-turns 3` with agent invocations
41
+
42
+ **Rationale:**
43
+ - `--max-turns 1` is too restrictive - the model needs turn 1 to call StructuredOutput, turn 2 for the tool result
44
+ - `--max-turns 2` works but leaves no buffer for edge cases
45
+ - `--max-turns 3` gives safety margin while still preventing runaway multi-turn behavior
46
+ - With these settings, reviews complete in ~5-10 seconds
47
+
48
+ **Constraint:** The agent markdown files MUST contain clear instructions to "call StructuredOutput IMMEDIATELY" and "do NOT use any other tools". Without these instructions, the model will try to use its turns for file operations instead of outputting the review.
49
+
50
+ ## enabled: false Convention
51
+
52
+ **Decision:** Set `enabled: false` in frontmatter for all plan review agents
53
+
54
+ **Rationale:** The `enabled` field controls Claude Code's auto-suggestion feature (showing agents in command palette). For plan review agents, we don't want them appearing as general-purpose agents - they're invoked programmatically by the hook. Setting `enabled: false` hides them from auto-suggestion while still allowing the hook to use them.
55
+
56
+ **Constraint:** Don't set `enabled: true` unless you want the agent to appear in Claude Code's agent picker for general use.
@@ -6,7 +6,6 @@ focus: code quality and security
6
6
  enabled: false
7
7
  categories:
8
8
  - code
9
- tools: Read, Write, Edit, Bash, Glob, Grep
10
9
  ---
11
10
 
12
11
  ## Role
@@ -9,7 +9,6 @@ categories:
9
9
  - infrastructure
10
10
  - design
11
11
  - research
12
- tools: ""
13
12
  ---
14
13
 
15
14
  You are a Context Extractor agent that prepares abstracted problem context for the Fresh Perspective agent. Your job is to distill a conversation into its essential elements while **stripping away implementation details** that could bias fresh thinking.
@@ -7,7 +7,6 @@ enabled: false
7
7
  categories:
8
8
  - code
9
9
  - infrastructure
10
- tools: Read, Grep, Glob, Bash
11
10
  ---
12
11
 
13
12
  ## Role
@@ -7,7 +7,6 @@ enabled: false
7
7
  categories:
8
8
  - code
9
9
  - infrastructure
10
- tools: Read, Write, Edit, Bash, Glob, Grep
11
10
  ---
12
11
 
13
12
  ## Role
@@ -6,7 +6,6 @@ focus: plan complexity analysis and agent routing
6
6
  enabled: false
7
7
  categories:
8
8
  - orchestration
9
- tools: Read, Glob, Grep
10
9
  ---
11
10
 
12
11
  You are a plan orchestration agent. Your job is to analyze implementation plans and determine:
@@ -12,7 +12,6 @@ categories:
12
12
  - research
13
13
  - life
14
14
  - business
15
- tools: Read, Glob, Grep
16
15
  ---
17
16
 
18
17
  You are a trade-off illuminator who makes hidden costs explicit. While other agents ask "Is this approach good?", you ask "What are you giving up to get this?" Your focus is exposing the price of every decision—the capabilities sacrificed, the stakeholders who lose, the futures foreclosed.
@@ -118,7 +118,6 @@ DEFAULT_ORCHESTRATOR: Dict[str, Any] = {
118
118
  "enabled": True,
119
119
  "model": "haiku",
120
120
  "timeout": 30,
121
- "maxTurns": 3,
122
121
  }
123
122
 
124
123
  DEFAULT_AGENT_MODEL: str = "sonnet"
@@ -331,10 +330,9 @@ def load_settings(proj_dir: Path) -> Dict[str, Any]:
331
330
  "agentReview": {
332
331
  "enabled": True,
333
332
  "orchestrator": DEFAULT_ORCHESTRATOR.copy(),
334
- "timeout": 120,
333
+ "timeout": 180,
335
334
  "blockOnFail": True,
336
335
  "legacyMode": False,
337
- "maxTurns": 3,
338
336
  "display": DEFAULT_DISPLAY.copy(),
339
337
  "agentSelection": DEFAULT_AGENT_SELECTION.copy(),
340
338
  "agentDefaults": {"model": DEFAULT_AGENT_MODEL},
@@ -383,9 +381,13 @@ def load_settings(proj_dir: Path) -> Dict[str, Any]:
383
381
 
384
382
 
385
383
  def load_agent_library(proj_dir: Path, settings: Optional[Dict[str, Any]] = None) -> List[AgentConfig]:
386
- """Load agent library by auto-detecting from frontmatter."""
387
- agents_dir = proj_dir / ".claude" / "agents" / "cc-native"
388
- agents_data = aggregate_agents(agents_dir)
384
+ """Load agent library by auto-detecting from frontmatter.
385
+
386
+ Agents are loaded from _cc-native/agents/ directory. The markdown body
387
+ of each agent file becomes the system_prompt for --system-prompt invocation.
388
+ """
389
+ # aggregate_agents now defaults to _cc-native/agents/ relative to the script
390
+ agents_data = aggregate_agents()
389
391
 
390
392
  default_model = DEFAULT_AGENT_MODEL
391
393
  if settings:
@@ -415,7 +417,7 @@ def load_agent_library(proj_dir: Path, settings: Optional[Dict[str, Any]] = None
415
417
  enabled=a.get("enabled", True),
416
418
  categories=a.get("categories", ["code"]),
417
419
  description=a.get("description", ""),
418
- tools=a.get("tools", ""),
420
+ system_prompt=a.get("system_prompt", ""),
419
421
  ))
420
422
 
421
423
  return agents
@@ -539,7 +541,6 @@ def main() -> int:
539
541
  enabled=orch_settings.get("enabled", True) and agent_review_enabled,
540
542
  model=orch_settings.get("model", "haiku"),
541
543
  timeout=orch_settings.get("timeout", 30),
542
- max_turns=orch_settings.get("maxTurns", 3),
543
544
  )
544
545
 
545
546
  eprint(f"[cc-native-plan-review] Codex enabled: {codex_enabled}, Gemini enabled: {gemini_enabled}")
@@ -642,7 +643,6 @@ def main() -> int:
642
643
  # PHASE 3: Run selected agents in parallel
643
644
  if selected_agents:
644
645
  eprint("[cc-native-plan-review] === PHASE 3: Agent Reviews ===")
645
- max_turns = agent_settings.get("maxTurns", 3)
646
646
  max_parallel = agent_settings.get("maxParallelAgents", 0) # 0 = unlimited
647
647
  num_workers = len(selected_agents) if max_parallel <= 0 else min(max_parallel, len(selected_agents))
648
648
  eprint(f"[cc-native-plan-review] Launching {len(selected_agents)} agents in parallel (workers={num_workers})")
@@ -651,13 +651,12 @@ def main() -> int:
651
651
  debug_log(context_path, session_id, "hook", "agent_review_start", {
652
652
  "agents": [a.name for a in selected_agents],
653
653
  "timeout": timeout,
654
- "max_turns": max_turns,
655
654
  "complexity": detected_complexity,
656
655
  })
657
656
 
658
657
  with ThreadPoolExecutor(max_workers=num_workers) as executor:
659
658
  futures = {
660
- executor.submit(run_agent_review, plan, agent, REVIEW_SCHEMA, timeout, max_turns, context_path, session_id): agent
659
+ executor.submit(run_agent_review, plan, agent, REVIEW_SCHEMA, timeout, context_path, session_id): agent
661
660
  for agent in selected_agents
662
661
  }
663
662
  for future in as_completed(futures):
@@ -129,7 +129,7 @@ def run_orchestrator(
129
129
  Args:
130
130
  plan: The plan content to analyze
131
131
  agent_library: List of available agents
132
- config: Orchestrator configuration (model, timeout, max_turns)
132
+ config: Orchestrator configuration (model, timeout)
133
133
  settings: Agent review settings (agentSelection, complexityCategories)
134
134
 
135
135
  Returns:
@@ -154,9 +154,11 @@ def run_orchestrator(
154
154
 
155
155
  eprint(f"[orchestrator] Found Claude CLI at: {claude_path}")
156
156
 
157
- # Build agent list for prompt
157
+ # Build agent list for prompt with rich descriptions
158
158
  agent_list = "\n".join([
159
- f"- {a.name}: {a.focus} (categories: {', '.join(a.categories)})"
159
+ f"- {a.name} [{', '.join(a.categories)}]\n"
160
+ f" Focus: {a.focus}\n"
161
+ f" Expertise: {a.description}"
160
162
  for a in agent_library if a.enabled
161
163
  ])
162
164
  category_list = "/".join(categories)
@@ -164,43 +166,48 @@ def run_orchestrator(
164
166
  medium_range = f"{selection.get('medium', {}).get('min', 1)}-{selection.get('medium', {}).get('max', 2)}"
165
167
  high_range = f"{selection.get('high', {}).get('min', 2)}-{selection.get('high', {}).get('max', 4)}"
166
168
 
167
- prompt = f"""IMPORTANT: Analyze this plan and output your decision immediately using StructuredOutput. Do NOT ask questions.
169
+ # System prompt with orchestrator instructions
170
+ system_prompt = """You are a plan orchestrator for code review. Your job is to analyze plans and select appropriate reviewer agents.
168
171
 
169
- You are a plan orchestrator. Analyze the plan below and determine:
170
- 1. Complexity level (simple/medium/high)
171
- 2. Category ({category_list})
172
- 3. Which agents (if any) should review this plan
172
+ You MUST call StructuredOutput immediately with your analysis. Do NOT ask questions or use any other tools.
173
+
174
+ When selecting agents:
175
+ - Match agent expertise to plan requirements
176
+ - Consider what each agent specializes in
177
+ - Only select agents whose categories match the plan category
178
+ - Fewer agents for simple plans, more for complex plans"""
179
+
180
+ # User prompt with plan and agent list
181
+ prompt = f"""Analyze this plan and select appropriate reviewer agents.
173
182
 
174
183
  Available agents:
175
184
  {agent_list}
176
185
 
177
- Rules:
178
- - simple complexity = {simple_range} agents (CLI review sufficient)
186
+ Selection rules:
187
+ - simple complexity = {simple_range} agents
179
188
  - medium complexity = {medium_range} agents
180
189
  - high complexity = {high_range} agents
181
- - Only select agents whose categories match the plan category
190
+ - Only select agents whose categories match the plan category ({category_list})
182
191
  - Non-technical plans (life, business) typically need 0 code-focused agents
183
192
 
184
- Analyze and call StructuredOutput with your decision now.
185
-
186
193
  PLAN:
187
194
  <<<
188
195
  {plan}
189
196
  >>>
190
- """
197
+
198
+ Call StructuredOutput now with: complexity, category, selectedAgents, reasoning"""
191
199
 
192
200
  schema_json = json.dumps(ORCHESTRATOR_SCHEMA, ensure_ascii=False)
193
201
 
194
202
  cmd_args = [
195
203
  claude_path,
196
204
  "-p", # Enable print mode to read prompt from stdin
197
- "--agent", "plan-orchestrator",
198
205
  "--model", config.model,
199
- "--permission-mode", "bypassPermissions",
200
206
  "--output-format", "json",
201
- "--max-turns", str(config.max_turns),
202
207
  "--json-schema", schema_json,
203
- "--settings", "{}",
208
+ "--max-turns", "3", # Single-turn with buffer for tool call + result
209
+ "--setting-sources", "", # Disable PAI context interference
210
+ "--system-prompt", system_prompt,
204
211
  ]
205
212
 
206
213
  eprint(f"[orchestrator] Running with model: {config.model}, timeout: {config.timeout}s")
@@ -245,6 +252,17 @@ PLAN:
245
252
  eprint(f"[orchestrator] stderr: {p.stderr[:300]}")
246
253
 
247
254
  obj = _parse_claude_output(raw)
255
+
256
+ # Debug logging to diagnose empty selectedAgents issue
257
+ eprint(f"[orchestrator:debug] Raw output length: {len(raw)} chars")
258
+ if raw:
259
+ eprint(f"[orchestrator:debug] Raw output (first 500 chars): {raw[:500]}")
260
+ eprint(f"[orchestrator:debug] Parsed obj: {obj}")
261
+ if obj:
262
+ eprint(f"[orchestrator:debug] obj keys: {list(obj.keys())}")
263
+ eprint(f"[orchestrator:debug] selectedAgents value: {obj.get('selectedAgents', 'MISSING')}")
264
+ eprint(f"[orchestrator:debug] reasoning value: {obj.get('reasoning', 'MISSING')}")
265
+
248
266
  if not obj:
249
267
  eprint("[orchestrator] Failed to parse output, falling back to medium complexity")
250
268
  return OrchestratorResult(
@@ -81,7 +81,6 @@ def run_agent_review(
81
81
  agent: AgentConfig,
82
82
  schema: Dict[str, Any],
83
83
  timeout: int,
84
- max_turns: int = 3,
85
84
  context_path: Optional[Path] = None,
86
85
  session_name: str = "unknown",
87
86
  ) -> ReviewerResult:
@@ -92,7 +91,6 @@ def run_agent_review(
92
91
  agent: Agent configuration (name, model, etc.)
93
92
  schema: JSON schema for the review output
94
93
  timeout: Timeout in seconds
95
- max_turns: Maximum agent turns
96
94
  context_path: Optional path to context folder for debug logging
97
95
  session_name: Session name for debug logging
98
96
 
@@ -113,7 +111,8 @@ def run_agent_review(
113
111
 
114
112
  eprint(f"[{agent.name}] Found Claude CLI at: {claude_path}")
115
113
 
116
- prompt = f"""{AGENT_REVIEW_PROMPT_PREFIX}
114
+ # User prompt contains just the task and plan
115
+ prompt = f"""Review the plan below and provide your assessment using StructuredOutput.
117
116
 
118
117
  PLAN:
119
118
  <<<
@@ -122,19 +121,23 @@ PLAN:
122
121
  """
123
122
 
124
123
  schema_json = json.dumps(schema, ensure_ascii=False)
124
+
125
+ # Build command args - use --system-prompt with the markdown body as persona
125
126
  cmd_args = [
126
127
  claude_path,
127
128
  "-p", # Enable print mode to read prompt from stdin
128
- "--agent", agent.name,
129
129
  "--model", agent.model,
130
- "--permission-mode", "plan",
131
130
  "--output-format", "json",
132
- "--max-turns", str(max_turns),
133
131
  "--json-schema", schema_json,
134
- "--settings", "{}",
132
+ "--max-turns", "3", # Allow buffer for tool call + result (usually completes in 2)
133
+ "--setting-sources", "", # Disable user/project settings to avoid PAI context interference
135
134
  ]
136
135
 
137
- eprint(f"[{agent.name}] Running with model: {agent.model}, timeout: {timeout}s, max-turns: {max_turns}")
136
+ # Add system prompt if available (the markdown body with full persona)
137
+ if agent.system_prompt:
138
+ cmd_args.extend(["--system-prompt", agent.system_prompt])
139
+
140
+ eprint(f"[{agent.name}] Running with model: {agent.model}, timeout: {timeout}s")
138
141
 
139
142
  # Get environment for internal subprocess (bypasses hooks)
140
143
  env = get_internal_subprocess_env()
@@ -176,7 +179,6 @@ PLAN:
176
179
  "stderr_len": len(err),
177
180
  "model": agent.model,
178
181
  "timeout": timeout,
179
- "max_turns": max_turns,
180
182
  })
181
183
 
182
184
  if raw:
@@ -39,7 +39,7 @@ class AgentConfig:
39
39
  enabled: bool = True
40
40
  categories: List[str] = field(default_factory=lambda: ["code"])
41
41
  description: str = ""
42
- tools: str = ""
42
+ system_prompt: str = "" # Markdown body content for --system-prompt
43
43
 
44
44
 
45
45
  @dataclass
@@ -48,7 +48,6 @@ class OrchestratorConfig:
48
48
  enabled: bool = True
49
49
  model: str = "haiku"
50
50
  timeout: int = 30
51
- max_turns: int = 3
52
51
 
53
52
 
54
53
  # ---------------------------
@@ -22,14 +22,12 @@
22
22
  },
23
23
  "agentReview": {
24
24
  "enabled": true,
25
- "timeout": 120,
25
+ "timeout": 180,
26
26
  "blockOnFail": true,
27
- "maxTurns": 2,
28
27
  "orchestrator": {
29
28
  "enabled": true,
30
29
  "model": "haiku",
31
- "timeout": 30,
32
- "maxTurns": 6
30
+ "timeout": 30
33
31
  },
34
32
  "legacyMode": false,
35
33
  "mandatoryAgents": ["handoff-readiness", "clarity-auditor", "skeptic"],
@@ -93,16 +93,31 @@ def extract_frontmatter(content: str) -> dict[str, Any] | None:
93
93
  return None
94
94
 
95
95
 
96
+ def extract_body(content: str) -> str:
97
+ """Extract markdown body (after frontmatter) from content.
98
+
99
+ Args:
100
+ content: Raw markdown file content
101
+
102
+ Returns:
103
+ Markdown body content (everything after the closing ---)
104
+ """
105
+ match = re.match(r'^---\s*\n.*?\n---\s*\n(.*)$', content, re.DOTALL)
106
+ if match:
107
+ return match.group(1).strip()
108
+ return content.strip()
109
+
110
+
96
111
  def aggregate_agents(agents_dir: Path | None = None) -> list[dict[str, Any]]:
97
112
  """Read all agent files and return aggregated metadata.
98
-
113
+
99
114
  Scans the agents directory for .md files, extracts frontmatter from each,
100
115
  and returns a list of agent configurations.
101
-
116
+
102
117
  Args:
103
118
  agents_dir: Path to agents directory. If None, uses default
104
- .claude/agents relative to project root.
105
-
119
+ _cc-native/agents/ relative to this script.
120
+
106
121
  Returns:
107
122
  List of agent configuration dicts with fields:
108
123
  - name: Agent identifier (lowercase)
@@ -111,14 +126,14 @@ def aggregate_agents(agents_dir: Path | None = None) -> list[dict[str, Any]]:
111
126
  - focus: Brief focus for orchestrator
112
127
  - enabled: Whether agent is available
113
128
  - categories: Work categories for filtering
114
- - tools: Available tools
129
+ - system_prompt: Full markdown body (persona content)
115
130
  """
116
131
  if agents_dir is None:
117
- # Default to .claude/agents/cc-native relative to this script's location
132
+ # Default to _cc-native/agents/ relative to this script's location
118
133
  # Script is at: _cc-native/scripts/aggregate_agents.py
119
- # Agents are at: .claude/agents/cc-native/
134
+ # Agents are at: _cc-native/agents/
120
135
  script_dir = Path(__file__).parent
121
- agents_dir = script_dir.parent.parent / ".claude" / "agents" / "cc-native"
136
+ agents_dir = script_dir.parent / "agents"
122
137
 
123
138
  agents = []
124
139
 
@@ -135,6 +150,8 @@ def aggregate_agents(agents_dir: Path | None = None) -> list[dict[str, Any]]:
135
150
  frontmatter["categories"] = ["code"]
136
151
  elif isinstance(frontmatter["categories"], str):
137
152
  frontmatter["categories"] = [frontmatter["categories"]]
153
+ # Extract markdown body as system_prompt
154
+ frontmatter["system_prompt"] = extract_body(content)
138
155
  agents.append(frontmatter)
139
156
  except Exception:
140
157
  # Skip files that can't be read or parsed
@@ -401,5 +401,5 @@
401
401
  ]
402
402
  }
403
403
  },
404
- "version": "0.9.4"
404
+ "version": "0.9.6"
405
405
  }
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.9.4",
4
+ "version": "0.9.6",
5
5
  "author": "jofu-tofu",
6
6
  "bin": {
7
7
  "aiw": "./bin/run.js"