aiwcli 0.9.1 → 0.9.2

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 (63) hide show
  1. package/dist/templates/_shared/hooks/__pycache__/context_enforcer.cpython-313.pyc +0 -0
  2. package/dist/templates/_shared/hooks/__pycache__/session_start.cpython-313.pyc +0 -0
  3. package/dist/templates/_shared/hooks/__pycache__/task_create_atomicity.cpython-313.pyc +0 -0
  4. package/dist/templates/_shared/hooks/__pycache__/user_prompt_submit.cpython-313.pyc +0 -0
  5. package/dist/templates/_shared/hooks/context_enforcer.py +65 -15
  6. package/dist/templates/_shared/hooks/session_start.py +108 -0
  7. package/dist/templates/_shared/hooks/task_create_atomicity.py +199 -0
  8. package/dist/templates/_shared/hooks/task_create_capture.py +2 -2
  9. package/dist/templates/_shared/hooks/task_update_capture.py +2 -2
  10. package/dist/templates/_shared/hooks/user_prompt_submit.py +58 -13
  11. package/dist/templates/_shared/lib/base/__pycache__/inference.cpython-313.pyc +0 -0
  12. package/dist/templates/_shared/lib/base/__pycache__/stop_words.cpython-313.pyc +0 -0
  13. package/dist/templates/_shared/lib/base/__pycache__/utils.cpython-313.pyc +0 -0
  14. package/dist/templates/_shared/lib/base/inference.py +20 -35
  15. package/dist/templates/_shared/lib/base/stop_words.py +158 -0
  16. package/dist/templates/_shared/lib/base/utils.py +3 -2
  17. package/dist/templates/_shared/lib/context/__init__.py +0 -2
  18. package/dist/templates/_shared/lib/context/__pycache__/__init__.cpython-313.pyc +0 -0
  19. package/dist/templates/_shared/lib/context/__pycache__/context_manager.cpython-313.pyc +0 -0
  20. package/dist/templates/_shared/lib/context/__pycache__/task_sync.cpython-313.pyc +0 -0
  21. package/dist/templates/_shared/lib/context/context_manager.py +2 -2
  22. package/dist/templates/_shared/lib/context/task_sync.py +5 -82
  23. package/dist/templates/_shared/lib/templates/__pycache__/persona_questions.cpython-313.pyc +0 -0
  24. package/dist/templates/_shared/lib/templates/__pycache__/plan_context.cpython-313.pyc +0 -0
  25. package/dist/templates/_shared/lib/templates/persona_questions.py +113 -0
  26. package/dist/templates/_shared/lib/templates/plan_context.py +13 -27
  27. package/dist/templates/cc-native/.claude/agents/cc-native/ACCESSIBILITY-TESTER.md +1 -1
  28. package/dist/templates/cc-native/.claude/agents/cc-native/ARCHITECT-REVIEWER.md +1 -1
  29. package/dist/templates/cc-native/.claude/agents/cc-native/ASSUMPTION-CHAIN-TRACER.md +1 -1
  30. package/dist/templates/cc-native/.claude/agents/cc-native/CLARITY-AUDITOR.md +1 -1
  31. package/dist/templates/cc-native/.claude/agents/cc-native/CODE-REVIEWER.md +1 -1
  32. package/dist/templates/cc-native/.claude/agents/cc-native/COMPLETENESS-CHECKER.md +1 -1
  33. package/dist/templates/cc-native/.claude/agents/cc-native/CONTEXT-EXTRACTOR.md +1 -1
  34. package/dist/templates/cc-native/.claude/agents/cc-native/DEVILS-ADVOCATE.md +1 -1
  35. package/dist/templates/cc-native/.claude/agents/cc-native/FEASIBILITY-ANALYST.md +1 -1
  36. package/dist/templates/cc-native/.claude/agents/cc-native/FRESH-PERSPECTIVE.md +1 -1
  37. package/dist/templates/cc-native/.claude/agents/cc-native/HANDOFF-READINESS.md +1 -1
  38. package/dist/templates/cc-native/.claude/agents/cc-native/HIDDEN-COMPLEXITY-DETECTOR.md +1 -1
  39. package/dist/templates/cc-native/.claude/agents/cc-native/INCENTIVE-MAPPER.md +1 -1
  40. package/dist/templates/cc-native/.claude/agents/cc-native/PENETRATION-TESTER.md +1 -1
  41. package/dist/templates/cc-native/.claude/agents/cc-native/PERFORMANCE-ENGINEER.md +1 -1
  42. package/dist/templates/cc-native/.claude/agents/cc-native/PLAN-ORCHESTRATOR.md +1 -1
  43. package/dist/templates/cc-native/.claude/agents/cc-native/PRECEDENT-FINDER.md +1 -1
  44. package/dist/templates/cc-native/.claude/agents/cc-native/REVERSIBILITY-ANALYST.md +1 -1
  45. package/dist/templates/cc-native/.claude/agents/cc-native/RISK-ASSESSOR.md +1 -1
  46. package/dist/templates/cc-native/.claude/agents/cc-native/SECOND-ORDER-ANALYST.md +1 -1
  47. package/dist/templates/cc-native/.claude/agents/cc-native/SIMPLICITY-GUARDIAN.md +1 -1
  48. package/dist/templates/cc-native/.claude/agents/cc-native/SKEPTIC.md +1 -1
  49. package/dist/templates/cc-native/.claude/agents/cc-native/STAKEHOLDER-ADVOCATE.md +1 -1
  50. package/dist/templates/cc-native/.claude/agents/cc-native/TRADE-OFF-ILLUMINATOR.md +1 -1
  51. package/dist/templates/cc-native/.claude/settings.json +21 -0
  52. package/dist/templates/cc-native/_cc-native/hooks/CLAUDE.md +211 -0
  53. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/cc-native-plan-review.cpython-313.pyc +0 -0
  54. package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.py +48 -9
  55. package/dist/templates/cc-native/_cc-native/lib/CLAUDE.md +240 -0
  56. package/dist/templates/cc-native/_cc-native/lib/__pycache__/orchestrator.cpython-313.pyc +0 -0
  57. package/dist/templates/cc-native/_cc-native/lib/orchestrator.py +1 -0
  58. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/agent.cpython-313.pyc +0 -0
  59. package/dist/templates/cc-native/_cc-native/lib/reviewers/agent.py +1 -0
  60. package/dist/templates/cc-native/_cc-native/plan-review.config.json +6 -0
  61. package/oclif.manifest.json +1 -1
  62. package/package.json +1 -1
  63. package/dist/templates/cc-native/_cc-native/docs/PERMISSION_REQUEST_VERIFICATION.md +0 -147
@@ -0,0 +1,240 @@
1
+ # CC-Native Library Development Guide
2
+
3
+ > **Keep this document updated.** When you solve an issue related to library code, add the solution to the relevant section and log it in the Changelog. This document should grow with discovered patterns and fixes—don't wait to be asked.
4
+
5
+ ---
6
+
7
+ ## Module Overview
8
+
9
+ | Module | Purpose |
10
+ |--------|---------|
11
+ | `utils.py` | Core utilities: eprint, sanitize, JSON parsing, artifact writing |
12
+ | `state.py` | Plan state file management and iteration tracking |
13
+ | `orchestrator.py` | Plan complexity analysis and agent selection |
14
+ | `reviewers.py` | CLI and agent-based plan review implementations |
15
+ | `atomic_write.py` | Atomic file writes for crash safety |
16
+ | `constants.py` | Shared constants and configuration |
17
+ | `async_archive.py` | Async plan archival operations |
18
+ | `__init__.py` | Package exports |
19
+
20
+ ---
21
+
22
+ ## Dependency Graph
23
+
24
+ ```
25
+ Hooks (cc-native-plan-review.py, etc.)
26
+
27
+ ├── lib/utils.py (core utilities)
28
+ │ └── lib/atomic_write.py
29
+ │ └── lib/constants.py
30
+
31
+ ├── lib/state.py (state management)
32
+ │ └── lib/utils.py (eprint)
33
+
34
+ ├── lib/orchestrator.py (agent selection)
35
+ │ └── lib/utils.py (ReviewerResult, etc.)
36
+
37
+ └── _shared/lib/ (shared across all methods)
38
+ ├── lib/base/subprocess_utils.py
39
+ ├── lib/base/constants.py
40
+ └── lib/context/context_manager.py
41
+ ```
42
+
43
+ **Import direction:** Hooks → cc-native lib → shared lib. Never the reverse.
44
+
45
+ ---
46
+
47
+ ## Key Data Classes
48
+
49
+ ### ReviewerResult
50
+
51
+ ```python
52
+ @dataclass
53
+ class ReviewerResult:
54
+ name: str # Reviewer name (e.g., "codex", "architect-reviewer")
55
+ ok: bool # True if review completed successfully
56
+ verdict: str # "pass" | "warn" | "fail" | "error" | "skip"
57
+ data: Dict[str, Any] # Structured review data (summary, issues, etc.)
58
+ raw: str # Raw response text
59
+ err: str # Error message if any
60
+ ```
61
+
62
+ ### OrchestratorResult
63
+
64
+ ```python
65
+ @dataclass
66
+ class OrchestratorResult:
67
+ complexity: str # "simple" | "medium" | "high"
68
+ category: str # "code" | "infrastructure" | "documentation" | etc.
69
+ selected_agents: List[str] # Agent names to run
70
+ reasoning: str # Why these agents were selected
71
+ skip_reason: Optional[str] # Why review was skipped (if applicable)
72
+ error: Optional[str] # Error message if orchestrator failed
73
+ ```
74
+
75
+ ### CombinedReviewResult
76
+
77
+ ```python
78
+ @dataclass
79
+ class CombinedReviewResult:
80
+ plan_hash: str # SHA256 hash (first 16 chars)
81
+ overall_verdict: str # Worst verdict across all reviewers
82
+ cli_reviewers: Dict[str, ReviewerResult] # Codex, Gemini results
83
+ orchestration: Optional[OrchestratorResult]
84
+ agents: Dict[str, ReviewerResult] # Agent review results
85
+ timestamp: str # ISO format
86
+ ```
87
+
88
+ ---
89
+
90
+ ## Windows Path Handling
91
+
92
+ Windows uses backslashes in paths. Always normalize when comparing:
93
+
94
+ ```python
95
+ # CORRECT - works on Windows and Unix
96
+ if ".claude/plans/" in file_path.replace("\\", "/"):
97
+ # Found a plan file
98
+
99
+ # Also correct - use Path for comparisons
100
+ from pathlib import Path
101
+ if Path(".claude/plans") in Path(file_path).parents:
102
+ # Found a plan file
103
+ ```
104
+
105
+ ```python
106
+ # WRONG - fails on Windows
107
+ if ".claude/plans/" in file_path: # Windows path: ".claude\\plans\\"
108
+ # Never matches on Windows!
109
+ ```
110
+
111
+ This is a recurring issue. Any path string comparison must handle both separators.
112
+
113
+ ---
114
+
115
+ ## Atomic Writes
116
+
117
+ For critical files (state, reviews), use atomic writes to prevent corruption on crash:
118
+
119
+ ```python
120
+ from atomic_write import atomic_write
121
+
122
+ # CORRECT - atomic write
123
+ success, error = atomic_write(path, content)
124
+ if not success:
125
+ eprint(f"[module] Write failed: {error}")
126
+ ```
127
+
128
+ ```python
129
+ # RISKY - can leave partial file on crash
130
+ path.write_text(content, encoding="utf-8")
131
+ ```
132
+
133
+ Atomic writes use a temp file + rename pattern. Check `constants.ENABLE_ROBUST_PLAN_WRITES` for the feature flag.
134
+
135
+ ---
136
+
137
+ ## Adding New Reviewers
138
+
139
+ 1. **Create reviewer function** in `reviewers.py`:
140
+ ```python
141
+ def run_myreviewer_review(
142
+ plan: str,
143
+ schema: Dict[str, Any],
144
+ settings: Dict[str, Any],
145
+ ) -> ReviewerResult:
146
+ # Implementation
147
+ return ReviewerResult(
148
+ name="myreviewer",
149
+ ok=True,
150
+ verdict="pass",
151
+ data=parsed_data,
152
+ raw=raw_response,
153
+ err="",
154
+ )
155
+ ```
156
+
157
+ 2. **Export in `__init__.py`** (if needed for external use)
158
+
159
+ 3. **Add config** in `plan-review.config.json`:
160
+ ```json
161
+ {
162
+ "planReview": {
163
+ "reviewers": {
164
+ "myreviewer": {"enabled": true, "timeout": 120}
165
+ }
166
+ }
167
+ }
168
+ ```
169
+
170
+ 4. **Wire in hook** (`cc-native-plan-review.py`):
171
+ ```python
172
+ from reviewers import run_myreviewer_review
173
+
174
+ if myreviewer_enabled:
175
+ phase1_tasks.append(("myreviewer", lambda: run_myreviewer_review(...)))
176
+ ```
177
+
178
+ ---
179
+
180
+ ## JSON Parsing
181
+
182
+ Use `parse_json_maybe` for LLM responses - it handles markdown code blocks and extraction:
183
+
184
+ ```python
185
+ from utils import parse_json_maybe, coerce_to_review
186
+
187
+ # Parse with field validation
188
+ obj = parse_json_maybe(raw_response, require_fields=["verdict", "summary"])
189
+
190
+ # Normalize to expected structure
191
+ ok, verdict, data = coerce_to_review(obj)
192
+ ```
193
+
194
+ The parser tries:
195
+ 1. Strict JSON parse
196
+ 2. Extract `{...}` block from text (handles ```json blocks)
197
+
198
+ ---
199
+
200
+ ## Encoding
201
+
202
+ Always specify encoding on file operations:
203
+
204
+ ```python
205
+ # CORRECT
206
+ content = path.read_text(encoding="utf-8")
207
+ path.write_text(content, encoding="utf-8")
208
+
209
+ with open(path, "r", encoding="utf-8") as f:
210
+ data = json.load(f)
211
+ ```
212
+
213
+ ```python
214
+ # WRONG - uses system default (can fail on Windows)
215
+ content = path.read_text() # May use cp1252 on Windows
216
+ ```
217
+
218
+ ---
219
+
220
+ ## DO NOT
221
+
222
+ These are reminders based on past issues. Not enforcement rules.
223
+
224
+ - **Don't import from `_cc-native/lib/` in `_shared/lib/`** - wrong direction, creates circular deps
225
+ - **Don't use `print()` for debugging** - use `eprint()` to avoid corrupting stdout
226
+ - **Don't modify data class fields** without updating all consumers (hooks, formatters, tests)
227
+ - **Don't hardcode paths** - use `Path(__file__)`, env vars, or config
228
+ - **Don't forget `encoding="utf-8"`** on file operations - Windows defaults are unsafe
229
+ - **Don't assume forward slashes** in file paths - Windows uses backslashes
230
+ - **Don't skip atomic writes** for critical state files - use `atomic_write` function
231
+
232
+ ---
233
+
234
+ ## Changelog
235
+
236
+ <!-- Add dated entries as new issues are discovered -->
237
+
238
+ | Date | Change |
239
+ |------|--------|
240
+ | 2026-02-03 | Initial creation |
@@ -193,6 +193,7 @@ PLAN:
193
193
 
194
194
  cmd_args = [
195
195
  claude_path,
196
+ "-p", # Enable print mode to read prompt from stdin
196
197
  "--agent", "plan-orchestrator",
197
198
  "--model", config.model,
198
199
  "--permission-mode", "bypassPermissions",
@@ -119,6 +119,7 @@ PLAN:
119
119
  schema_json = json.dumps(schema, ensure_ascii=False)
120
120
  cmd_args = [
121
121
  claude_path,
122
+ "-p", # Enable print mode to read prompt from stdin
122
123
  "--agent", agent.name,
123
124
  "--model", agent.model,
124
125
  "--permission-mode", "bypassPermissions",
@@ -32,6 +32,12 @@
32
32
  "maxTurns": 6
33
33
  },
34
34
  "legacyMode": false,
35
+ "mandatoryAgents": ["handoff-readiness", "clarity-auditor", "skeptic"],
36
+ "fallbackByComplexity": {
37
+ "simple": 0,
38
+ "medium": 5,
39
+ "high": 9
40
+ },
35
41
  "reviewIterations": {
36
42
  "simple": 1,
37
43
  "medium": 1,
@@ -401,5 +401,5 @@
401
401
  ]
402
402
  }
403
403
  },
404
- "version": "0.9.1"
404
+ "version": "0.9.2"
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.1",
4
+ "version": "0.9.2",
5
5
  "author": "jofu-tofu",
6
6
  "bin": {
7
7
  "aiw": "./bin/run.js"
@@ -1,147 +0,0 @@
1
- # PermissionRequest Hook Verification Plan
2
-
3
- ## Objective
4
-
5
- Verify that `PermissionRequest` event can be used for plan archiving instead of the current `PreToolUse` + state file approach.
6
-
7
- ## Current Implementation (v1.5.0+)
8
-
9
- ```
10
- PreToolUse: ExitPlanMode
11
- └── cc-native-plan-review.py (runs agent reviews, saves to context reviews folder)
12
-
13
- PostToolUse: ExitPlanMode
14
- └── archive_plan.py (archives plan to context plans folder)
15
- ```
16
-
17
- **Note:** As of v1.5.0, `set_plan_state.py` has been removed. Plan review now integrates with the shared context system, storing reviews in `_output/contexts/{context_id}/reviews/`.
18
-
19
- ## Original Proposed Simplification (Historical)
20
-
21
- ```
22
- PreToolUse: ExitPlanMode
23
- └── cc-native-plan-review.py (runs reviews, saves to context folder)
24
-
25
- PermissionRequest: ExitPlanMode ← Tested approach
26
- └── archive_plan.py (archives immediately after reviews complete)
27
- ```
28
-
29
- ## Verification Steps
30
-
31
- ### Step 1: Deploy Test Hook
32
-
33
- The test hook has been added:
34
- - **Hook:** `_cc-native/hooks/test_permission_request.py`
35
- - **Config:** `PermissionRequest` entry in `.claude/settings.json`
36
- - **Output:** `~/.claude/permission_request_payload.json`
37
-
38
- ### Step 2: Trigger Plan Mode
39
-
40
- 1. Start Claude Code with cc-native template:
41
- ```bash
42
- cd /path/to/project-with-cc-native
43
- claude --plan
44
- ```
45
-
46
- 2. Create a simple plan (any task works)
47
-
48
- 3. When plan is ready, Claude calls `ExitPlanMode`
49
-
50
- ### Step 3: Check Results
51
-
52
- After Claude calls `ExitPlanMode`, check:
53
-
54
- ```bash
55
- # Check if payload was logged
56
- cat ~/.claude/permission_request_payload.json
57
- ```
58
-
59
- Expected output:
60
- ```json
61
- {
62
- "received_at": "2026-01-20T...",
63
- "payload": {
64
- "tool_name": "ExitPlanMode",
65
- "session_id": "...",
66
- "cwd": "...",
67
- "tool_input": {...}
68
- },
69
- "analysis": {
70
- "has_tool_name": true,
71
- "has_session_id": true,
72
- "has_cwd": true,
73
- "has_tool_input": true,
74
- "tool_name": "ExitPlanMode",
75
- "payload_keys": ["tool_name", "session_id", "cwd", "tool_input", ...]
76
- }
77
- }
78
- ```
79
-
80
- ### Step 4: Verify Timing
81
-
82
- Check stderr logs during plan mode exit:
83
-
84
- ```
85
- [cc-native-plan-review] Unified hook started (PreToolUse)
86
- [cc-native-plan-review] Using context reviews dir: ...
87
- [cc-native-plan-review] Review complete...
88
- [test_permission_request] Hook started (PermissionRequest) ← Should appear AFTER reviews
89
- [test_permission_request] SUCCESS: All required fields present
90
- ```
91
-
92
- **Critical timing requirement:** PermissionRequest must fire:
93
- 1. AFTER PreToolUse hooks complete (reviews done)
94
- 2. BEFORE user sees the approval prompt
95
-
96
- ## Decision Checklist
97
-
98
- After verification, update this checklist:
99
-
100
- - [ ] PermissionRequest fires for ExitPlanMode
101
- - [ ] Payload contains `tool_name`
102
- - [ ] Payload contains `session_id`
103
- - [ ] Payload contains `cwd`
104
- - [ ] Timing: fires AFTER PreToolUse
105
- - [ ] Timing: fires BEFORE user prompt shown
106
- - [ ] `archive_plan.py` works with PermissionRequest payload (or minimal changes needed)
107
-
108
- ## Phase 2: Migration (if verified)
109
-
110
- If all checks pass:
111
-
112
- 1. Modify `archive_plan.py` if needed for PermissionRequest payload
113
- 2. Add production PermissionRequest entry for archive_plan.py
114
- 3. Remove `Edit|Write|Bash` PreToolUse entry for archive_plan.py
115
- 4. Remove `Stop` entry for archive_plan.py
116
- 5. Remove test_permission_request.py hook
117
- 6. Test full flow end-to-end
118
-
119
- ## Potential Issues
120
-
121
- ### Issue 1: PermissionRequest may not fire for ExitPlanMode
122
-
123
- ExitPlanMode is a special tool that shows the plan approval prompt. It's possible that:
124
- - PermissionRequest only fires for dangerous tools (Bash, Write, etc.)
125
- - ExitPlanMode uses a different permission flow
126
-
127
- **Mitigation:** The test hook will confirm whether it fires or not.
128
-
129
- ### Issue 2: Different payload structure
130
-
131
- PermissionRequest may have different fields than PreToolUse.
132
-
133
- **Mitigation:** The test hook logs all payload keys for analysis.
134
-
135
- ### Issue 3: Timing may be wrong
136
-
137
- PermissionRequest might fire BEFORE PreToolUse hooks complete (before reviews).
138
-
139
- **Mitigation:** Check stderr log ordering during test.
140
-
141
- ## Cleanup
142
-
143
- After verification:
144
- 1. Remove `test_permission_request.py` hook
145
- 2. Remove PermissionRequest test entry from settings.json
146
- 3. Delete `~/.claude/permission_request_payload.json`
147
- 4. Document findings in this file