aiwcli 0.9.8 → 0.10.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 (116) hide show
  1. package/bin/run.js +5 -2
  2. package/dist/lib/claude-settings-types.d.ts +2 -0
  3. package/dist/templates/CLAUDE.md +3 -3
  4. package/dist/templates/_shared/.claude/settings.json +4 -0
  5. package/dist/templates/_shared/hooks/__pycache__/__init__.cpython-313.pyc +0 -0
  6. package/dist/templates/_shared/hooks/__pycache__/archive_plan.cpython-313.pyc +0 -0
  7. package/dist/templates/_shared/hooks/__pycache__/context_enforcer.cpython-313.pyc +0 -0
  8. package/dist/templates/_shared/hooks/__pycache__/context_monitor.cpython-313.pyc +0 -0
  9. package/dist/templates/_shared/hooks/__pycache__/file-suggestion.cpython-313.pyc +0 -0
  10. package/dist/templates/_shared/hooks/__pycache__/pre_compact.cpython-313.pyc +0 -0
  11. package/dist/templates/_shared/hooks/__pycache__/session_end.cpython-313.pyc +0 -0
  12. package/dist/templates/_shared/hooks/__pycache__/session_start.cpython-313.pyc +0 -0
  13. package/dist/templates/_shared/hooks/__pycache__/task_create_capture.cpython-313.pyc +0 -0
  14. package/dist/templates/_shared/hooks/__pycache__/task_update_capture.cpython-313.pyc +0 -0
  15. package/dist/templates/_shared/hooks/__pycache__/user_prompt_submit.cpython-313.pyc +0 -0
  16. package/dist/templates/_shared/hooks/archive_plan.py +87 -178
  17. package/dist/templates/_shared/hooks/context_monitor.py +104 -247
  18. package/dist/templates/_shared/hooks/file-suggestion.py +26 -23
  19. package/dist/templates/_shared/hooks/pre_compact.py +47 -32
  20. package/dist/templates/_shared/hooks/session_end.py +103 -60
  21. package/dist/templates/_shared/hooks/session_start.py +110 -81
  22. package/dist/templates/_shared/hooks/task_create_capture.py +26 -50
  23. package/dist/templates/_shared/hooks/task_update_capture.py +42 -115
  24. package/dist/templates/_shared/hooks/user_prompt_submit.py +61 -61
  25. package/dist/templates/_shared/lib/base/__init__.py +16 -0
  26. package/dist/templates/_shared/lib/base/__pycache__/__init__.cpython-313.pyc +0 -0
  27. package/dist/templates/_shared/lib/base/__pycache__/hook_utils.cpython-313.pyc +0 -0
  28. package/dist/templates/_shared/lib/base/__pycache__/inference.cpython-313.pyc +0 -0
  29. package/dist/templates/_shared/lib/base/__pycache__/logger.cpython-313.pyc +0 -0
  30. package/dist/templates/_shared/lib/base/__pycache__/utils.cpython-313.pyc +0 -0
  31. package/dist/templates/_shared/lib/base/hook_utils.py +199 -11
  32. package/dist/templates/_shared/lib/base/inference.py +121 -0
  33. package/dist/templates/_shared/lib/base/logger.py +291 -0
  34. package/dist/templates/_shared/lib/base/utils.py +42 -9
  35. package/dist/templates/_shared/lib/context/__init__.py +72 -80
  36. package/dist/templates/_shared/lib/context/__pycache__/__init__.cpython-313.pyc +0 -0
  37. package/dist/templates/_shared/lib/context/__pycache__/context_formatter.cpython-313.pyc +0 -0
  38. package/dist/templates/_shared/lib/context/__pycache__/context_manager.cpython-313.pyc +0 -0
  39. package/dist/templates/_shared/lib/context/__pycache__/context_selector.cpython-313.pyc +0 -0
  40. package/dist/templates/_shared/lib/context/__pycache__/context_store.cpython-313.pyc +0 -0
  41. package/dist/templates/_shared/lib/context/__pycache__/discovery.cpython-313.pyc +0 -0
  42. package/dist/templates/_shared/lib/context/__pycache__/plan_manager.cpython-313.pyc +0 -0
  43. package/dist/templates/_shared/lib/context/__pycache__/task_tracker.cpython-313.pyc +0 -0
  44. package/dist/templates/_shared/lib/context/context_formatter.py +316 -0
  45. package/dist/templates/_shared/lib/context/context_selector.py +491 -0
  46. package/dist/templates/_shared/lib/context/context_store.py +636 -0
  47. package/dist/templates/_shared/lib/context/plan_manager.py +204 -0
  48. package/dist/templates/_shared/lib/context/task_tracker.py +188 -0
  49. package/dist/templates/_shared/lib/handoff/__pycache__/__init__.cpython-313.pyc +0 -0
  50. package/dist/templates/_shared/lib/handoff/__pycache__/document_generator.cpython-313.pyc +0 -0
  51. package/dist/templates/_shared/lib/handoff/document_generator.py +14 -40
  52. package/dist/templates/_shared/lib/templates/README.md +5 -13
  53. package/dist/templates/_shared/lib/templates/__init__.py +2 -6
  54. package/dist/templates/_shared/lib/templates/__pycache__/__init__.cpython-313.pyc +0 -0
  55. package/dist/templates/_shared/lib/templates/__pycache__/formatters.cpython-313.pyc +0 -0
  56. package/dist/templates/_shared/lib/templates/__pycache__/plan_context.cpython-313.pyc +0 -0
  57. package/dist/templates/_shared/lib/templates/plan_context.py +1 -38
  58. package/dist/templates/_shared/scripts/__pycache__/save_handoff.cpython-313.pyc +0 -0
  59. package/dist/templates/_shared/scripts/__pycache__/status_line.cpython-313.pyc +0 -0
  60. package/dist/templates/_shared/scripts/save_handoff.py +39 -19
  61. package/dist/templates/_shared/scripts/status_line.py +701 -0
  62. package/dist/templates/_shared/workflows/handoff.md +9 -3
  63. package/dist/templates/cc-native/.claude/settings.json +41 -8
  64. package/dist/templates/cc-native/CC-NATIVE-README.md +25 -28
  65. package/dist/templates/cc-native/MIGRATION.md +1 -1
  66. package/dist/templates/cc-native/TEMPLATE-SCHEMA.md +14 -39
  67. package/dist/templates/cc-native/_cc-native/hooks/CLAUDE.md +49 -21
  68. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/add_plan_context.cpython-313.pyc +0 -0
  69. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/cc-native-plan-review.cpython-313.pyc +0 -0
  70. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/mark_questions_asked.cpython-313.pyc +0 -0
  71. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/plan_accepted.cpython-313.pyc +0 -0
  72. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/plan_questions_early.cpython-313.pyc +0 -0
  73. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/suggest-fresh-perspective.cpython-313.pyc +0 -0
  74. package/dist/templates/cc-native/_cc-native/hooks/add_plan_context.py +57 -55
  75. package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.py +163 -131
  76. package/dist/templates/cc-native/_cc-native/hooks/plan_accepted.py +127 -0
  77. package/dist/templates/cc-native/_cc-native/hooks/plan_questions_early.py +81 -0
  78. package/dist/templates/cc-native/_cc-native/hooks/suggest-fresh-perspective.py +26 -25
  79. package/dist/templates/cc-native/_cc-native/lib/CLAUDE.md +6 -4
  80. package/dist/templates/cc-native/_cc-native/lib/__pycache__/__init__.cpython-313.pyc +0 -0
  81. package/dist/templates/cc-native/_cc-native/lib/__pycache__/constants.cpython-313.pyc +0 -0
  82. package/dist/templates/cc-native/_cc-native/lib/__pycache__/debug.cpython-313.pyc +0 -0
  83. package/dist/templates/cc-native/_cc-native/lib/__pycache__/orchestrator.cpython-313.pyc +0 -0
  84. package/dist/templates/cc-native/_cc-native/lib/__pycache__/state.cpython-313.pyc +0 -0
  85. package/dist/templates/cc-native/_cc-native/lib/__pycache__/utils.cpython-313.pyc +0 -0
  86. package/dist/templates/cc-native/_cc-native/lib/debug.py +37 -22
  87. package/dist/templates/cc-native/_cc-native/lib/orchestrator.py +34 -29
  88. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/__init__.cpython-313.pyc +0 -0
  89. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/agent.cpython-313.pyc +0 -0
  90. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/base.cpython-313.pyc +0 -0
  91. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/codex.cpython-313.pyc +0 -0
  92. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/gemini.cpython-313.pyc +0 -0
  93. package/dist/templates/cc-native/_cc-native/lib/reviewers/agent.py +26 -21
  94. package/dist/templates/cc-native/_cc-native/lib/reviewers/codex.py +12 -7
  95. package/dist/templates/cc-native/_cc-native/lib/reviewers/gemini.py +12 -7
  96. package/dist/templates/cc-native/_cc-native/lib/state.py +31 -16
  97. package/dist/templates/cc-native/_cc-native/lib/utils.py +207 -40
  98. package/dist/templates/cc-native/_cc-native/plan-review.config.json +1 -2
  99. package/oclif.manifest.json +1 -1
  100. package/package.json +1 -1
  101. package/dist/templates/_shared/hooks/context_enforcer.py +0 -625
  102. package/dist/templates/_shared/hooks/task_create_atomicity.py +0 -177
  103. package/dist/templates/_shared/lib/context/auto_state.py +0 -167
  104. package/dist/templates/_shared/lib/context/cache.py +0 -444
  105. package/dist/templates/_shared/lib/context/context_extractor.py +0 -115
  106. package/dist/templates/_shared/lib/context/context_manager.py +0 -1057
  107. package/dist/templates/_shared/lib/context/discovery.py +0 -554
  108. package/dist/templates/_shared/lib/context/event_log.py +0 -316
  109. package/dist/templates/_shared/lib/context/plan_archive.py +0 -101
  110. package/dist/templates/_shared/lib/context/task_sync.py +0 -407
  111. package/dist/templates/_shared/lib/templates/persona_questions.py +0 -113
  112. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/archive_plan.cpython-313.pyc +0 -0
  113. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/cc-native-agent-review.cpython-313.pyc +0 -0
  114. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/test_permission_request.cpython-313.pyc +0 -0
  115. package/dist/templates/cc-native/_cc-native/lib/async_archive.py +0 -68
  116. package/dist/templates/cc-native/_cc-native/lib/atomic_write.py +0 -98
@@ -1,19 +1,20 @@
1
1
  #!/usr/bin/env python3
2
2
  """
3
- PreToolUse hook for Write - offers clarifying questions on first plan write.
3
+ Plan context hook - handles both question marking and plan write enforcement.
4
4
 
5
- On the first plan write in a session:
6
- 1. Allow the write to succeed (plan file is created)
7
- 2. Inject context offering clarifying questions
8
- 3. If user wants questions, Claude asks and writes an updated plan
5
+ Registered for two PostToolUse/PreToolUse events:
6
+ - PostToolUse: AskUserQuestion marks that questions were asked this session.
7
+ - PreToolUse: Write enforces questions before plan write.
9
8
 
10
- Subsequent writes inject the evaluation context reminder only.
9
+ Phase B of two-phase question system:
10
+ - If AskUserQuestion was NOT called this session: BLOCK the Write
11
+ and inject the non-obvious questions prompt.
12
+ - If AskUserQuestion WAS called: ALLOW and inject evaluation context.
11
13
 
12
- Fail-safe: Any error skips the questions feature and allows the write.
14
+ Fail-safe: Any error skips enforcement and allows the write.
13
15
  """
14
16
 
15
17
  import json
16
- import os
17
18
  import sys
18
19
  from pathlib import Path
19
20
  from typing import Any, Dict
@@ -26,15 +27,13 @@ sys.path.insert(0, str(_cc_native_lib_dir))
26
27
  sys.path.insert(0, str(_shared_lib_dir))
27
28
 
28
29
  from utils import (
29
- eprint,
30
- was_questions_offered,
31
- mark_questions_offered,
30
+ mark_questions_asked,
31
+ was_questions_asked,
32
32
  project_dir,
33
33
  )
34
- from templates.plan_context import (
35
- get_evaluation_context_reminder,
36
- get_questions_offer_template,
37
- )
34
+ from base.hook_utils import emit_context, emit_context_and_block
35
+ from base.logger import log_debug, log_info, log_warn, log_error, log_diagnostic
36
+ from templates.plan_context import get_evaluation_context_reminder
38
37
 
39
38
 
40
39
  def is_plan_file_write(payload: Dict[str, Any]) -> bool:
@@ -47,7 +46,7 @@ def is_plan_file_write(payload: Dict[str, Any]) -> bool:
47
46
  def load_plan_context_config(proj_dir: Path) -> Dict[str, Any]:
48
47
  """Load planContext config with defaults."""
49
48
  config_path = proj_dir / "_cc-native" / "config.json"
50
- defaults = {"enabled": True, "offerClarifyingQuestions": True}
49
+ defaults = {"enabled": True}
51
50
 
52
51
  if not config_path.exists():
53
52
  return defaults
@@ -60,29 +59,26 @@ def load_plan_context_config(proj_dir: Path) -> Dict[str, Any]:
60
59
 
61
60
 
62
61
  CONTEXT_REMINDER = get_evaluation_context_reminder()
63
- QUESTIONS_OFFER_CONTEXT = get_questions_offer_template()
62
+ PHASE_B_ENFORCEMENT = (
63
+ "You must ask non-obvious questions via AskUserQuestion before writing the plan. "
64
+ "See the question guidance injected earlier in this session by plan_questions_early. "
65
+ "This surfaces trade-offs and constraints that code exploration alone cannot reveal."
66
+ )
64
67
 
65
68
 
66
69
  def inject_evaluation_context() -> int:
67
70
  """Inject evaluation context reminder without blocking."""
68
- out = {
69
- "hookSpecificOutput": {
70
- "additionalContext": CONTEXT_REMINDER
71
- }
72
- }
73
- print(json.dumps(out, ensure_ascii=False))
71
+ emit_context(CONTEXT_REMINDER)
74
72
  return 0
75
73
 
76
74
 
77
- def offer_questions_nonblocking() -> int:
78
- """Inject questions offer without blocking - plan Write succeeds."""
79
- context = CONTEXT_REMINDER + "\n\n---\n\n" + QUESTIONS_OFFER_CONTEXT
80
- out = {
81
- "hookSpecificOutput": {
82
- "additionalContext": context
83
- }
84
- }
85
- print(json.dumps(out, ensure_ascii=False))
75
+ def block_with_questions_prompt() -> int:
76
+ """Block Write until non-obvious questions have been asked this session."""
77
+ emit_context_and_block(
78
+ PHASE_B_ENFORCEMENT,
79
+ "Ask non-obvious questions via AskUserQuestion before writing the plan. "
80
+ "This surfaces trade-offs and constraints that code exploration alone cannot reveal."
81
+ )
86
82
  return 0
87
83
 
88
84
 
@@ -92,7 +88,20 @@ def main() -> int:
92
88
  except json.JSONDecodeError:
93
89
  return 0 # Fail-safe
94
90
 
95
- if payload.get("tool_name") != "Write":
91
+ tool_name = payload.get("tool_name")
92
+ hook_event = payload.get("hook_event_name", "unknown")
93
+ log_diagnostic("add_plan_context", "receive", f"tool={tool_name}, event={hook_event}",
94
+ inputs={"tool_name": tool_name, "hook_event": hook_event})
95
+
96
+ # PostToolUse: AskUserQuestion — mark that questions were asked
97
+ if tool_name == "AskUserQuestion":
98
+ session_id = str(payload.get("session_id", ""))
99
+ if session_id:
100
+ mark_questions_asked(session_id)
101
+ log_info("add_plan_context", f"Marked questions asked for session {session_id[:8]}...")
102
+ return 0
103
+
104
+ if tool_name != "Write":
96
105
  return 0
97
106
 
98
107
  if not is_plan_file_write(payload):
@@ -104,40 +113,33 @@ def main() -> int:
104
113
 
105
114
  # Check if feature is disabled
106
115
  if not config.get("enabled", True):
107
- eprint("[add_plan_context] planContext disabled in config")
116
+ log_debug("add_plan_context", "planContext disabled in config")
108
117
  return 0
109
118
 
110
- if not config.get("offerClarifyingQuestions", True):
111
- eprint("[add_plan_context] Config: offerClarifyingQuestions=false, skipping")
112
- return inject_evaluation_context()
113
-
114
119
  # Get session_id
115
120
  session_id = payload.get("session_id")
116
121
 
117
- # Fail-safe: skip feature if no session_id
122
+ # Fail-safe: skip enforcement if no session_id
118
123
  if not session_id:
119
- eprint("[add_plan_context] No session_id, skipping questions offer")
124
+ log_debug("add_plan_context", "No session_id, skipping enforcement")
120
125
  return inject_evaluation_context()
121
126
 
122
127
  session_id_str = str(session_id)
123
128
 
124
- # Check if questions already offered this session
125
- if was_questions_offered(session_id_str):
126
- eprint("[add_plan_context] Questions already offered, injecting eval context")
127
- return inject_evaluation_context()
128
-
129
- # First plan write: offer questions (non-blocking - Write succeeds)
130
- eprint("[add_plan_context] First plan write - offering questions (non-blocking)")
131
-
132
- # Mark as offered so subsequent writes only get eval context
133
- if not mark_questions_offered(session_id_str):
134
- # If marking fails, skip feature (fail-safe)
135
- eprint("[add_plan_context] Failed to mark, skipping questions offer")
129
+ # Check if questions were asked this session
130
+ if was_questions_asked(session_id_str):
131
+ log_info("add_plan_context", "Questions asked, allowing write with eval context")
132
+ log_diagnostic("add_plan_context", "decide", "Questions asked, allowing with eval context",
133
+ decision="allow_with_context", reasoning="was_questions_asked=True")
136
134
  return inject_evaluation_context()
137
135
 
138
- # Inject questions offer without blocking - Write succeeds
139
- return offer_questions_nonblocking()
136
+ # Questions NOT asked: block and inject Phase B prompt
137
+ log_info("add_plan_context", "Questions not asked yet - blocking plan write")
138
+ log_diagnostic("add_plan_context", "decide", "Questions not asked, blocking plan write",
139
+ decision="block", reasoning="was_questions_asked=False, enforcing Phase B")
140
+ return block_with_questions_prompt()
140
141
 
141
142
 
142
143
  if __name__ == "__main__":
143
- raise SystemExit(main())
144
+ from base.hook_utils import run_hook
145
+ run_hook(main, "add_plan_context")