aiwcli 0.10.2 → 0.11.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 (249) hide show
  1. package/bin/run.js +1 -1
  2. package/dist/commands/clear.d.ts +11 -6
  3. package/dist/commands/clear.js +229 -381
  4. package/dist/commands/init/index.d.ts +1 -17
  5. package/dist/commands/init/index.js +22 -107
  6. package/dist/lib/gitignore-manager.d.ts +32 -0
  7. package/dist/lib/gitignore-manager.js +141 -2
  8. package/dist/lib/template-installer.d.ts +7 -12
  9. package/dist/lib/template-installer.js +69 -193
  10. package/dist/lib/template-settings-reconstructor.d.ts +35 -0
  11. package/dist/lib/template-settings-reconstructor.js +130 -0
  12. package/dist/templates/CLAUDE.md +8 -8
  13. package/dist/templates/_shared/.claude/commands/handoff-resume.md +64 -0
  14. package/dist/templates/_shared/.claude/commands/handoff.md +16 -10
  15. package/dist/templates/_shared/.claude/settings.json +7 -7
  16. package/dist/templates/_shared/hooks-ts/_utils/git-state.ts +2 -0
  17. package/dist/templates/_shared/hooks-ts/archive_plan.ts +159 -0
  18. package/dist/templates/_shared/hooks-ts/context_monitor.ts +147 -0
  19. package/dist/templates/_shared/hooks-ts/file-suggestion.ts +130 -0
  20. package/dist/templates/_shared/hooks-ts/pre_compact.ts +49 -0
  21. package/dist/templates/_shared/hooks-ts/session_end.ts +104 -0
  22. package/dist/templates/_shared/hooks-ts/session_start.ts +144 -0
  23. package/dist/templates/_shared/hooks-ts/task_create_capture.ts +48 -0
  24. package/dist/templates/_shared/hooks-ts/task_update_capture.ts +74 -0
  25. package/dist/templates/_shared/hooks-ts/user_prompt_submit.ts +83 -0
  26. package/dist/templates/_shared/lib-ts/CLAUDE.md +318 -0
  27. package/dist/templates/_shared/lib-ts/base/atomic-write.ts +138 -0
  28. package/dist/templates/_shared/lib-ts/base/constants.ts +306 -0
  29. package/dist/templates/_shared/lib-ts/base/git-state.ts +58 -0
  30. package/dist/templates/_shared/lib-ts/base/hook-utils.ts +439 -0
  31. package/dist/templates/_shared/lib-ts/base/inference.ts +252 -0
  32. package/dist/templates/_shared/lib-ts/base/logger.ts +250 -0
  33. package/dist/templates/_shared/lib-ts/base/state-io.ts +116 -0
  34. package/dist/templates/_shared/lib-ts/base/stop-words.ts +184 -0
  35. package/dist/templates/_shared/lib-ts/base/subprocess-utils.ts +162 -0
  36. package/dist/templates/_shared/lib-ts/base/utils.ts +184 -0
  37. package/dist/templates/_shared/lib-ts/context/context-formatter.ts +438 -0
  38. package/dist/templates/_shared/lib-ts/context/context-selector.ts +515 -0
  39. package/dist/templates/_shared/lib-ts/context/context-store.ts +707 -0
  40. package/dist/templates/_shared/lib-ts/context/plan-manager.ts +316 -0
  41. package/dist/templates/_shared/lib-ts/context/task-tracker.ts +185 -0
  42. package/dist/templates/_shared/lib-ts/handoff/document-generator.ts +216 -0
  43. package/dist/templates/_shared/lib-ts/handoff/handoff-reader.ts +159 -0
  44. package/dist/templates/_shared/lib-ts/package.json +21 -0
  45. package/dist/templates/_shared/lib-ts/templates/formatters.ts +104 -0
  46. package/dist/templates/_shared/{lib/templates/plan_context.py → lib-ts/templates/plan-context.ts} +14 -22
  47. package/dist/templates/_shared/lib-ts/tsconfig.json +13 -0
  48. package/dist/templates/_shared/lib-ts/types.ts +164 -0
  49. package/dist/templates/_shared/scripts/resolve_context.ts +24 -0
  50. package/dist/templates/_shared/scripts/resume_handoff.ts +321 -0
  51. package/dist/templates/_shared/scripts/save_handoff.ts +359 -0
  52. package/dist/templates/_shared/scripts/status_line.ts +733 -0
  53. package/dist/templates/cc-native/.claude/settings.json +175 -185
  54. package/dist/templates/cc-native/TEMPLATE-SCHEMA.md +15 -17
  55. package/dist/templates/cc-native/_cc-native/agents/ARCH-EVOLUTION.md +63 -0
  56. package/dist/templates/cc-native/_cc-native/agents/ARCH-PATTERNS.md +62 -0
  57. package/dist/templates/cc-native/_cc-native/agents/ARCH-STRUCTURE.md +63 -0
  58. package/dist/templates/cc-native/_cc-native/agents/{ASSUMPTION-CHAIN-TRACER.md → ASSUMPTION-TRACER.md} +6 -10
  59. package/dist/templates/cc-native/_cc-native/agents/CLARITY-AUDITOR.md +6 -10
  60. package/dist/templates/cc-native/_cc-native/agents/CLAUDE.md +74 -3
  61. package/dist/templates/cc-native/_cc-native/agents/COMPLETENESS-FEASIBILITY.md +67 -0
  62. package/dist/templates/cc-native/_cc-native/agents/COMPLETENESS-GAPS.md +71 -0
  63. package/dist/templates/cc-native/_cc-native/agents/COMPLETENESS-ORDERING.md +63 -0
  64. package/dist/templates/cc-native/_cc-native/agents/CONSTRAINT-VALIDATOR.md +73 -0
  65. package/dist/templates/cc-native/_cc-native/agents/DESIGN-ADR-VALIDATOR.md +62 -0
  66. package/dist/templates/cc-native/_cc-native/agents/DESIGN-SCALE-MATCHER.md +65 -0
  67. package/dist/templates/cc-native/_cc-native/agents/DEVILS-ADVOCATE.md +6 -9
  68. package/dist/templates/cc-native/_cc-native/agents/DOCUMENTATION-PHILOSOPHY.md +87 -0
  69. package/dist/templates/cc-native/_cc-native/agents/HANDOFF-READINESS.md +5 -9
  70. package/dist/templates/cc-native/_cc-native/agents/{HIDDEN-COMPLEXITY-DETECTOR.md → HIDDEN-COMPLEXITY.md} +6 -10
  71. package/dist/templates/cc-native/_cc-native/agents/INCREMENTAL-DELIVERY.md +67 -0
  72. package/dist/templates/cc-native/_cc-native/agents/PLAN-ORCHESTRATOR.md +91 -18
  73. package/dist/templates/cc-native/_cc-native/agents/RISK-DEPENDENCY.md +63 -0
  74. package/dist/templates/cc-native/_cc-native/agents/RISK-FMEA.md +67 -0
  75. package/dist/templates/cc-native/_cc-native/agents/RISK-PREMORTEM.md +72 -0
  76. package/dist/templates/cc-native/_cc-native/agents/RISK-REVERSIBILITY.md +75 -0
  77. package/dist/templates/cc-native/_cc-native/agents/SCOPE-BOUNDARY.md +78 -0
  78. package/dist/templates/cc-native/_cc-native/agents/SIMPLICITY-GUARDIAN.md +5 -9
  79. package/dist/templates/cc-native/_cc-native/agents/SKEPTIC.md +16 -12
  80. package/dist/templates/cc-native/_cc-native/agents/TESTDRIVEN-BEHAVIOR-AUDITOR.md +62 -0
  81. package/dist/templates/cc-native/_cc-native/agents/TESTDRIVEN-CHARACTERIZATION.md +72 -0
  82. package/dist/templates/cc-native/_cc-native/agents/TESTDRIVEN-FIRST-VALIDATOR.md +62 -0
  83. package/dist/templates/cc-native/_cc-native/agents/TESTDRIVEN-PYRAMID-ANALYZER.md +62 -0
  84. package/dist/templates/cc-native/_cc-native/agents/TRADEOFF-COSTS.md +68 -0
  85. package/dist/templates/cc-native/_cc-native/agents/TRADEOFF-STAKEHOLDERS.md +66 -0
  86. package/dist/templates/cc-native/_cc-native/agents/VERIFY-COVERAGE.md +75 -0
  87. package/dist/templates/cc-native/_cc-native/agents/VERIFY-STRENGTH.md +70 -0
  88. package/dist/templates/cc-native/_cc-native/hooks/CLAUDE.md +109 -135
  89. package/dist/templates/cc-native/_cc-native/hooks/add_plan_context.ts +119 -0
  90. package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.ts +921 -0
  91. package/dist/templates/cc-native/_cc-native/hooks/plan_questions_early.ts +61 -0
  92. package/dist/templates/cc-native/_cc-native/lib-ts/aggregate-agents.ts +157 -0
  93. package/dist/templates/cc-native/_cc-native/lib-ts/artifacts.ts +709 -0
  94. package/dist/templates/cc-native/_cc-native/lib-ts/cc-native-state.ts +199 -0
  95. package/dist/templates/cc-native/_cc-native/lib-ts/cli-output-parser.ts +124 -0
  96. package/dist/templates/cc-native/_cc-native/lib-ts/config.ts +57 -0
  97. package/dist/templates/cc-native/_cc-native/lib-ts/constants.ts +83 -0
  98. package/dist/templates/cc-native/_cc-native/lib-ts/debug.ts +80 -0
  99. package/dist/templates/cc-native/_cc-native/lib-ts/index.ts +119 -0
  100. package/dist/templates/cc-native/_cc-native/lib-ts/json-parser.ts +162 -0
  101. package/dist/templates/cc-native/_cc-native/lib-ts/nul +3 -0
  102. package/dist/templates/cc-native/_cc-native/lib-ts/orchestrator.ts +249 -0
  103. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/agent.ts +155 -0
  104. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/codex.ts +130 -0
  105. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/gemini.ts +106 -0
  106. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/index.ts +10 -0
  107. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/types.ts +23 -0
  108. package/dist/templates/cc-native/_cc-native/lib-ts/state.ts +243 -0
  109. package/dist/templates/cc-native/_cc-native/lib-ts/tsconfig.json +18 -0
  110. package/dist/templates/cc-native/_cc-native/lib-ts/types.ts +310 -0
  111. package/dist/templates/cc-native/_cc-native/lib-ts/verdict.ts +72 -0
  112. package/dist/templates/cc-native/_cc-native/plan-review.config.json +12 -16
  113. package/oclif.manifest.json +1 -1
  114. package/package.json +1 -1
  115. package/dist/lib/template-merger.d.ts +0 -47
  116. package/dist/lib/template-merger.js +0 -162
  117. package/dist/templates/_shared/hooks/__init__.py +0 -16
  118. package/dist/templates/_shared/hooks/__pycache__/__init__.cpython-313.pyc +0 -0
  119. package/dist/templates/_shared/hooks/__pycache__/archive_plan.cpython-313.pyc +0 -0
  120. package/dist/templates/_shared/hooks/__pycache__/context_enforcer.cpython-313.pyc +0 -0
  121. package/dist/templates/_shared/hooks/__pycache__/context_monitor.cpython-313.pyc +0 -0
  122. package/dist/templates/_shared/hooks/__pycache__/file-suggestion.cpython-313.pyc +0 -0
  123. package/dist/templates/_shared/hooks/__pycache__/pre_compact.cpython-313.pyc +0 -0
  124. package/dist/templates/_shared/hooks/__pycache__/session_end.cpython-313.pyc +0 -0
  125. package/dist/templates/_shared/hooks/__pycache__/session_start.cpython-313.pyc +0 -0
  126. package/dist/templates/_shared/hooks/__pycache__/task_create_atomicity.cpython-313.pyc +0 -0
  127. package/dist/templates/_shared/hooks/__pycache__/task_create_capture.cpython-313.pyc +0 -0
  128. package/dist/templates/_shared/hooks/__pycache__/task_update_capture.cpython-313.pyc +0 -0
  129. package/dist/templates/_shared/hooks/__pycache__/user_prompt_submit.cpython-313.pyc +0 -0
  130. package/dist/templates/_shared/hooks/archive_plan.py +0 -169
  131. package/dist/templates/_shared/hooks/context_monitor.py +0 -270
  132. package/dist/templates/_shared/hooks/file-suggestion.py +0 -215
  133. package/dist/templates/_shared/hooks/pre_compact.py +0 -104
  134. package/dist/templates/_shared/hooks/session_end.py +0 -173
  135. package/dist/templates/_shared/hooks/session_start.py +0 -206
  136. package/dist/templates/_shared/hooks/task_create_capture.py +0 -108
  137. package/dist/templates/_shared/hooks/task_update_capture.py +0 -145
  138. package/dist/templates/_shared/hooks/user_prompt_submit.py +0 -139
  139. package/dist/templates/_shared/lib/__init__.py +0 -1
  140. package/dist/templates/_shared/lib/__pycache__/__init__.cpython-313.pyc +0 -0
  141. package/dist/templates/_shared/lib/base/__init__.py +0 -65
  142. package/dist/templates/_shared/lib/base/__pycache__/__init__.cpython-313.pyc +0 -0
  143. package/dist/templates/_shared/lib/base/__pycache__/atomic_write.cpython-313.pyc +0 -0
  144. package/dist/templates/_shared/lib/base/__pycache__/constants.cpython-313.pyc +0 -0
  145. package/dist/templates/_shared/lib/base/__pycache__/hook_utils.cpython-313.pyc +0 -0
  146. package/dist/templates/_shared/lib/base/__pycache__/inference.cpython-313.pyc +0 -0
  147. package/dist/templates/_shared/lib/base/__pycache__/logger.cpython-313.pyc +0 -0
  148. package/dist/templates/_shared/lib/base/__pycache__/stop_words.cpython-313.pyc +0 -0
  149. package/dist/templates/_shared/lib/base/__pycache__/subprocess_utils.cpython-313.pyc +0 -0
  150. package/dist/templates/_shared/lib/base/__pycache__/utils.cpython-313.pyc +0 -0
  151. package/dist/templates/_shared/lib/base/atomic_write.py +0 -180
  152. package/dist/templates/_shared/lib/base/constants.py +0 -358
  153. package/dist/templates/_shared/lib/base/hook_utils.py +0 -341
  154. package/dist/templates/_shared/lib/base/inference.py +0 -318
  155. package/dist/templates/_shared/lib/base/logger.py +0 -291
  156. package/dist/templates/_shared/lib/base/stop_words.py +0 -213
  157. package/dist/templates/_shared/lib/base/subprocess_utils.py +0 -46
  158. package/dist/templates/_shared/lib/base/utils.py +0 -242
  159. package/dist/templates/_shared/lib/context/__init__.py +0 -102
  160. package/dist/templates/_shared/lib/context/__pycache__/__init__.cpython-313.pyc +0 -0
  161. package/dist/templates/_shared/lib/context/__pycache__/cache.cpython-313.pyc +0 -0
  162. package/dist/templates/_shared/lib/context/__pycache__/context_extractor.cpython-313.pyc +0 -0
  163. package/dist/templates/_shared/lib/context/__pycache__/context_formatter.cpython-313.pyc +0 -0
  164. package/dist/templates/_shared/lib/context/__pycache__/context_manager.cpython-313.pyc +0 -0
  165. package/dist/templates/_shared/lib/context/__pycache__/context_selector.cpython-313.pyc +0 -0
  166. package/dist/templates/_shared/lib/context/__pycache__/context_store.cpython-313.pyc +0 -0
  167. package/dist/templates/_shared/lib/context/__pycache__/discovery.cpython-313.pyc +0 -0
  168. package/dist/templates/_shared/lib/context/__pycache__/event_log.cpython-313.pyc +0 -0
  169. package/dist/templates/_shared/lib/context/__pycache__/plan_archive.cpython-313.pyc +0 -0
  170. package/dist/templates/_shared/lib/context/__pycache__/plan_manager.cpython-313.pyc +0 -0
  171. package/dist/templates/_shared/lib/context/__pycache__/task_sync.cpython-313.pyc +0 -0
  172. package/dist/templates/_shared/lib/context/__pycache__/task_tracker.cpython-313.pyc +0 -0
  173. package/dist/templates/_shared/lib/context/context_formatter.py +0 -317
  174. package/dist/templates/_shared/lib/context/context_selector.py +0 -508
  175. package/dist/templates/_shared/lib/context/context_store.py +0 -653
  176. package/dist/templates/_shared/lib/context/plan_manager.py +0 -204
  177. package/dist/templates/_shared/lib/context/task_tracker.py +0 -188
  178. package/dist/templates/_shared/lib/handoff/__init__.py +0 -22
  179. package/dist/templates/_shared/lib/handoff/__pycache__/__init__.cpython-313.pyc +0 -0
  180. package/dist/templates/_shared/lib/handoff/__pycache__/document_generator.cpython-313.pyc +0 -0
  181. package/dist/templates/_shared/lib/handoff/document_generator.py +0 -278
  182. package/dist/templates/_shared/lib/templates/README.md +0 -206
  183. package/dist/templates/_shared/lib/templates/__init__.py +0 -36
  184. package/dist/templates/_shared/lib/templates/__pycache__/__init__.cpython-313.pyc +0 -0
  185. package/dist/templates/_shared/lib/templates/__pycache__/formatters.cpython-313.pyc +0 -0
  186. package/dist/templates/_shared/lib/templates/__pycache__/persona_questions.cpython-313.pyc +0 -0
  187. package/dist/templates/_shared/lib/templates/__pycache__/plan_context.cpython-313.pyc +0 -0
  188. package/dist/templates/_shared/lib/templates/formatters.py +0 -146
  189. package/dist/templates/_shared/scripts/__pycache__/save_handoff.cpython-313.pyc +0 -0
  190. package/dist/templates/_shared/scripts/__pycache__/status_line.cpython-313.pyc +0 -0
  191. package/dist/templates/_shared/scripts/save_handoff.py +0 -357
  192. package/dist/templates/_shared/scripts/status_line.py +0 -701
  193. package/dist/templates/cc-native/.claude/commands/cc-native/fresh-perspective.md +0 -8
  194. package/dist/templates/cc-native/.windsurf/workflows/cc-native/fresh-perspective.md +0 -8
  195. package/dist/templates/cc-native/MIGRATION.md +0 -86
  196. package/dist/templates/cc-native/_cc-native/agents/ACCESSIBILITY-TESTER.md +0 -79
  197. package/dist/templates/cc-native/_cc-native/agents/ARCHITECT-REVIEWER.md +0 -48
  198. package/dist/templates/cc-native/_cc-native/agents/CODE-REVIEWER.md +0 -70
  199. package/dist/templates/cc-native/_cc-native/agents/COMPLETENESS-CHECKER.md +0 -59
  200. package/dist/templates/cc-native/_cc-native/agents/CONTEXT-EXTRACTOR.md +0 -92
  201. package/dist/templates/cc-native/_cc-native/agents/DOCUMENTATION-REVIEWER.md +0 -51
  202. package/dist/templates/cc-native/_cc-native/agents/FEASIBILITY-ANALYST.md +0 -57
  203. package/dist/templates/cc-native/_cc-native/agents/FRESH-PERSPECTIVE.md +0 -54
  204. package/dist/templates/cc-native/_cc-native/agents/INCENTIVE-MAPPER.md +0 -61
  205. package/dist/templates/cc-native/_cc-native/agents/PENETRATION-TESTER.md +0 -79
  206. package/dist/templates/cc-native/_cc-native/agents/PERFORMANCE-ENGINEER.md +0 -75
  207. package/dist/templates/cc-native/_cc-native/agents/PRECEDENT-FINDER.md +0 -70
  208. package/dist/templates/cc-native/_cc-native/agents/REVERSIBILITY-ANALYST.md +0 -61
  209. package/dist/templates/cc-native/_cc-native/agents/RISK-ASSESSOR.md +0 -58
  210. package/dist/templates/cc-native/_cc-native/agents/SECOND-ORDER-ANALYST.md +0 -61
  211. package/dist/templates/cc-native/_cc-native/agents/STAKEHOLDER-ADVOCATE.md +0 -55
  212. package/dist/templates/cc-native/_cc-native/agents/TRADE-OFF-ILLUMINATOR.md +0 -204
  213. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/add_plan_context.cpython-313.pyc +0 -0
  214. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/cc-native-plan-review.cpython-313.pyc +0 -0
  215. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/mark_questions_asked.cpython-313.pyc +0 -0
  216. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/plan_accepted.cpython-313.pyc +0 -0
  217. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/plan_questions_early.cpython-313.pyc +0 -0
  218. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/suggest-fresh-perspective.cpython-313.pyc +0 -0
  219. package/dist/templates/cc-native/_cc-native/hooks/add_plan_context.py +0 -130
  220. package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.py +0 -869
  221. package/dist/templates/cc-native/_cc-native/hooks/plan_questions_early.py +0 -81
  222. package/dist/templates/cc-native/_cc-native/hooks/suggest-fresh-perspective.py +0 -340
  223. package/dist/templates/cc-native/_cc-native/lib/CLAUDE.md +0 -265
  224. package/dist/templates/cc-native/_cc-native/lib/__init__.py +0 -53
  225. package/dist/templates/cc-native/_cc-native/lib/__pycache__/__init__.cpython-313.pyc +0 -0
  226. package/dist/templates/cc-native/_cc-native/lib/__pycache__/atomic_write.cpython-313.pyc +0 -0
  227. package/dist/templates/cc-native/_cc-native/lib/__pycache__/constants.cpython-313.pyc +0 -0
  228. package/dist/templates/cc-native/_cc-native/lib/__pycache__/debug.cpython-313.pyc +0 -0
  229. package/dist/templates/cc-native/_cc-native/lib/__pycache__/orchestrator.cpython-313.pyc +0 -0
  230. package/dist/templates/cc-native/_cc-native/lib/__pycache__/state.cpython-313.pyc +0 -0
  231. package/dist/templates/cc-native/_cc-native/lib/__pycache__/utils.cpython-313.pyc +0 -0
  232. package/dist/templates/cc-native/_cc-native/lib/constants.py +0 -45
  233. package/dist/templates/cc-native/_cc-native/lib/debug.py +0 -139
  234. package/dist/templates/cc-native/_cc-native/lib/orchestrator.py +0 -362
  235. package/dist/templates/cc-native/_cc-native/lib/reviewers/__init__.py +0 -28
  236. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/__init__.cpython-313.pyc +0 -0
  237. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/agent.cpython-313.pyc +0 -0
  238. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/base.cpython-313.pyc +0 -0
  239. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/codex.cpython-313.pyc +0 -0
  240. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/gemini.cpython-313.pyc +0 -0
  241. package/dist/templates/cc-native/_cc-native/lib/reviewers/agent.py +0 -215
  242. package/dist/templates/cc-native/_cc-native/lib/reviewers/base.py +0 -88
  243. package/dist/templates/cc-native/_cc-native/lib/reviewers/codex.py +0 -124
  244. package/dist/templates/cc-native/_cc-native/lib/reviewers/gemini.py +0 -108
  245. package/dist/templates/cc-native/_cc-native/lib/state.py +0 -268
  246. package/dist/templates/cc-native/_cc-native/lib/utils.py +0 -1027
  247. package/dist/templates/cc-native/_cc-native/scripts/__pycache__/aggregate_agents.cpython-313.pyc +0 -0
  248. package/dist/templates/cc-native/_cc-native/scripts/aggregate_agents.py +0 -168
  249. package/dist/templates/cc-native/_cc-native/workflows/fresh-perspective.md +0 -134
@@ -1,318 +0,0 @@
1
- """Inference utility for AI-powered text processing.
2
-
3
- Provides a unified interface for Claude API calls using the claude CLI.
4
- Supports multiple model tiers: fast (Haiku), standard (Sonnet), smart (Opus).
5
- """
6
- import re
7
- import subprocess
8
- import sys
9
- import os
10
- from typing import Optional
11
-
12
- from .logger import log_debug, log_info, log_warn, log_error
13
- from dataclasses import dataclass
14
-
15
-
16
- @dataclass
17
- class InferenceResult:
18
- """Result from an inference call."""
19
- success: bool
20
- output: str
21
- error: Optional[str] = None
22
- latency_ms: int = 0
23
-
24
-
25
- # Model configurations
26
- MODELS = {
27
- "fast": "claude-3-haiku-20240307",
28
- "standard": "claude-sonnet-4-20250514",
29
- "smart": "claude-opus-4-20250514",
30
- }
31
-
32
- TIMEOUTS = {
33
- "fast": 15, # 15 seconds
34
- "standard": 30, # 30 seconds
35
- "smart": 90, # 90 seconds
36
- }
37
-
38
-
39
- def inference(
40
- system_prompt: str,
41
- user_prompt: str,
42
- level: str = "fast",
43
- timeout: Optional[int] = None,
44
- ) -> InferenceResult:
45
- """
46
- Run inference using the claude CLI.
47
-
48
- Args:
49
- system_prompt: System instructions for the model
50
- user_prompt: User message to process
51
- level: Model level - "fast" (Haiku), "standard" (Sonnet), "smart" (Opus)
52
- timeout: Custom timeout in seconds (uses level default if not specified)
53
-
54
- Returns:
55
- InferenceResult with success status, output, and any error
56
- """
57
- import time
58
- start_time = time.time()
59
-
60
- model = MODELS.get(level, MODELS["fast"])
61
- timeout_sec = timeout or TIMEOUTS.get(level, TIMEOUTS["fast"])
62
-
63
- # Combine prompts
64
- full_prompt = f"{system_prompt}\n\n{user_prompt}"
65
-
66
- # Build command
67
- cmd = [
68
- "claude",
69
- "--model", model,
70
- "--print",
71
- "--no-hooks",
72
- "-p", full_prompt,
73
- ]
74
-
75
- # Remove ANTHROPIC_API_KEY to force subscription auth
76
- env = os.environ.copy()
77
- env.pop("ANTHROPIC_API_KEY", None)
78
-
79
- try:
80
- result = subprocess.run(
81
- cmd,
82
- capture_output=True,
83
- text=True,
84
- timeout=timeout_sec,
85
- env=env,
86
- # Windows needs shell=True for command resolution
87
- shell=(sys.platform == "win32"),
88
- )
89
-
90
- latency_ms = int((time.time() - start_time) * 1000)
91
-
92
- if result.returncode != 0:
93
- return InferenceResult(
94
- success=False,
95
- output=result.stdout.strip() if result.stdout else "",
96
- error=result.stderr.strip() if result.stderr else f"Exit code: {result.returncode}",
97
- latency_ms=latency_ms,
98
- )
99
-
100
- return InferenceResult(
101
- success=True,
102
- output=result.stdout.strip(),
103
- latency_ms=latency_ms,
104
- )
105
-
106
- except subprocess.TimeoutExpired:
107
- latency_ms = int((time.time() - start_time) * 1000)
108
- return InferenceResult(
109
- success=False,
110
- output="",
111
- error=f"Timeout after {timeout_sec}s",
112
- latency_ms=latency_ms,
113
- )
114
- except FileNotFoundError:
115
- latency_ms = int((time.time() - start_time) * 1000)
116
- return InferenceResult(
117
- success=False,
118
- output="",
119
- error="claude CLI not found",
120
- latency_ms=latency_ms,
121
- )
122
- except Exception as e:
123
- latency_ms = int((time.time() - start_time) * 1000)
124
- return InferenceResult(
125
- success=False,
126
- output="",
127
- error=str(e),
128
- latency_ms=latency_ms,
129
- )
130
-
131
-
132
- # Stop words for filtering (from corpus analysis of 1,424 documents)
133
- from .stop_words import STOP_WORDS
134
-
135
-
136
- def filter_stop_words(text: str) -> str:
137
- """Remove stop words from text, keeping only content keywords."""
138
- words = text.lower().split()
139
- filtered = [w for w in words if w not in STOP_WORDS and len(w) > 1]
140
- return ' '.join(filtered)
141
-
142
-
143
- # System prompt for generating context ID summaries (keyword extraction for recognition)
144
- CONTEXT_ID_SYSTEM_PROMPT = """Extract 6-12 keywords from what the user wants to do.
145
-
146
- Rules:
147
- - Output 6-12 keywords only
148
- - Keywords: nouns, verbs, adjectives, technical terms, proper names
149
- - NO function words: the, to, with, for, in, a, an, of, on, is, it, and, or, that, this, be, as, at, by, from
150
- - Most important/specific words preferred
151
- - No punctuation, no quotes
152
-
153
- Examples:
154
- - "I want to add user authentication" -> "add user authentication login security JWT tokens webapp service"
155
- - "Fix the bug in the login flow" -> "fix bug login flow validation error redirect session auth handler"
156
- - "Can you help me refactor this code" -> "refactor code cleanup architecture maintainability legacy modules structure patterns"
157
- - "Update the README with new instructions" -> "update README documentation instructions setup configuration install guide steps"
158
-
159
- Output ONLY the keywords separated by spaces, nothing else."""
160
-
161
-
162
- def generate_semantic_summary(prompt: str, timeout: int = 15) -> Optional[str]:
163
- """
164
- Generate a keyword summary of a user prompt.
165
-
166
- Uses Sonnet for quality inference. Returns None if inference fails.
167
-
168
- Args:
169
- prompt: User prompt to summarize
170
- timeout: Timeout in seconds (default 15)
171
-
172
- Returns:
173
- Keyword summary string (5-10 words) or None if failed
174
- """
175
- result = inference(
176
- system_prompt=CONTEXT_ID_SYSTEM_PROMPT,
177
- user_prompt=prompt,
178
- level="standard",
179
- timeout=timeout,
180
- )
181
-
182
- if not result.success or not result.output:
183
- return None
184
-
185
- # Clean up the output
186
- summary = result.output.strip()
187
- # Remove any quotes
188
- summary = summary.strip('"\'')
189
- # Remove trailing punctuation
190
- summary = summary.rstrip('.!?')
191
-
192
- # Filter stop words
193
- summary = filter_stop_words(summary)
194
-
195
- # Validate 6-12 words for sufficient context
196
- words = summary.split()
197
- if len(words) < 6 or len(words) > 12:
198
- return None
199
-
200
- return summary
201
-
202
-
203
- # System prompt for generating context ID slugs (3-12 keyword tags for folder names)
204
- CONTEXT_ID_SLUG_PROMPT = """You are extracting keyword tags from a user's request to create a **folder name** for a work session.
205
-
206
- ## Why This Matters
207
-
208
- These tags become part of a context ID like `260206-1959-refactor-webhook-retry-logic`. Users scan lists of 50-100+ such folder names to find past work sessions. Your job is to extract the 3-12 words that make THIS session instantly recognizable among hundreds of others.
209
-
210
- Think: "If someone had 100 folders and needed to find this one by scanning names, which words would make it jump out?"
211
-
212
- ## First Word: Action Verb (REQUIRED)
213
-
214
- The first word MUST be a specific action verb. Choose the most precise verb available:
215
-
216
- Common: fix, add, implement, refactor, update, create, remove, replace, optimize, debug
217
- Specific (preferred when they fit): scaffold, instrument, serialize, throttle, migrate, integrate, extract, redesign, restructure, decouple, consolidate, parallelize, configure, deploy, benchmark, normalize, validate, document, deprecate, upstream
218
-
219
- ## Word Selection: Rarity = Quality
220
-
221
- The less common a word is in everyday language, the better it is as an identifier. Apply this mental filter:
222
-
223
- BEST (+3): Proper nouns, brand names, unique identifiers (PostgreSQL, Webpack, OAuth, JWT, CICD)
224
- GOOD (+2): Domain-specific technical terms (middleware, pooling, webhook, serialization, throttle)
225
- OKAY (+1): Specific common nouns (authentication, redirect, navbar, pagination, dropdown)
226
- WEAK (-1): Generic nouns that appear in most prompts (code, file, app, feature, issue, project, stuff, thing)
227
- BANNED: See banned list below — these must NEVER appear in output
228
-
229
- Select the 3-12 highest-value words. When choosing between two words that mean similar things, always pick the rarer/more specific one.
230
-
231
- ## Banned Words (NEVER include these)
232
-
233
- Greetings/social: sure, okay, ok, hi, hello, hey, thanks, yeah, yes, no, well, right, um, uh
234
- Pronouns/articles: I, my, me, we, our, you, your, he, she, it, they, the, a, an, this, that, these, those
235
- Auxiliaries/modals: is, are, was, were, be, been, being, can, could, would, should, will, shall, may, might, must, do, does, did, have, has, had
236
- Prepositions: to, with, for, in, of, on, at, by, from, into, about, through, between, after, before, during
237
- Conjunctions: and, or, but, so, because, if, when, while, although, since
238
- Filler/hedging: want, need, help, try, think, know, look, going, trying, looking, basically, actually, really, just, some, also, please, maybe, probably, kind, sort, pretty, very, quite, like
239
- Generic: code, file, app, stuff, thing, feature, issue, problem, way, part, bit, lot, something
240
-
241
- ## Bad vs Good Examples
242
-
243
- BAD: sure help refactor code cleanup -> starts with filler, "code" is generic
244
- GOOD: refactor database queries connection pooling
245
-
246
- BAD: want add feature authentication -> "want" is filler, "feature" is noise
247
- GOOD: add authentication Express JWT middleware
248
-
249
- BAD: looking fix issue login page -> gerund opener, "issue" is generic
250
- GOOD: fix login redirect blank page session
251
-
252
- BAD: improve things make better setup -> vague nouns, no technical specificity
253
- GOOD: improve CI pipeline GitHub Actions caching
254
-
255
- BAD: help update documentation readme stuff -> "help" opener, "stuff" is noise
256
- GOOD: update README API endpoints documentation
257
-
258
- BAD: thinking about maybe changing prompt -> hedging words, no specificity
259
- GOOD: optimize context ID extraction prompting Opus
260
-
261
- ## Output
262
-
263
- Output ONLY the keyword tags separated by spaces. Nothing else. No reasoning, no labels, no punctuation, no quotes, no hyphens, no markdown."""
264
-
265
-
266
- def generate_context_id_slug(prompt: str, timeout: int = 3) -> Optional[str]:
267
- """
268
- Generate a 3-12 word context ID slug from a user prompt using AI inference.
269
-
270
- Uses Haiku (fast tier) for low-latency keyword extraction within hook timeout budgets.
271
- Returns a cleaned, validated slug or None on failure.
272
-
273
- Args:
274
- prompt: Raw user prompt to extract keywords from
275
- timeout: Timeout in seconds (default 3, fits within 5-10s hook budget)
276
-
277
- Returns:
278
- Space-separated keyword slug (3-12 words) or None if failed
279
- """
280
- # Truncate input to 500 chars to keep inference fast
281
- truncated = prompt[:500] if len(prompt) > 500 else prompt
282
-
283
- result = inference(
284
- system_prompt=CONTEXT_ID_SLUG_PROMPT,
285
- user_prompt=truncated,
286
- level="fast",
287
- timeout=timeout,
288
- )
289
-
290
- if not result.success or not result.output:
291
- log_warn("inference", f"Context ID slug inference failed: {result.error}")
292
- return None
293
-
294
- slug = result.output.strip()
295
-
296
- # Clean: strip quotes, punctuation, hyphens
297
- slug = slug.strip('"\'`')
298
- slug = slug.rstrip('.!?')
299
- slug = slug.replace('-', ' ')
300
-
301
- # Remove non-alphanumeric chars (except spaces)
302
- slug = re.sub(r'[^a-zA-Z0-9 ]', '', slug)
303
-
304
- # Normalize whitespace
305
- slug = re.sub(r'\s+', ' ', slug).strip()
306
-
307
- words = slug.split()
308
-
309
- # Validate word count: truncate if over 12, reject if under 3
310
- if len(words) > 12:
311
- words = words[:12]
312
- if len(words) < 3:
313
- log_debug("inference", f"Context ID slug too short ({len(words)} words): '{slug}'")
314
- return None
315
-
316
- result_slug = ' '.join(words)
317
- log_debug("inference", f"Generated context ID slug: '{result_slug}' ({result.latency_ms}ms)")
318
- return result_slug
@@ -1,291 +0,0 @@
1
- """Unified logging for all hooks and libraries.
2
-
3
- Provides a single logging interface that replaces:
4
- - log_hook_error() from hook_utils.py (error-only, plain text)
5
- - debug.py from cc-native (per-context, plain text)
6
- - eprint() for diagnostic output (stderr-only, no persistence)
7
-
8
- Log format: JSONL (one JSON object per line)
9
- Log locations:
10
- - With context: _output/contexts/<context-id>/debug/hook-log.jsonl
11
- - Without context (fallback): _output/hook-log.jsonl
12
-
13
- Environment variables:
14
- - HOOK_LOG_DISABLE=1: Disable all file logging
15
- - HOOK_LOG_LEVEL=warn: Minimum level to log (default: debug)
16
- - HOOK_ERROR_LOG_DISABLE=1: Legacy alias for HOOK_LOG_DISABLE
17
-
18
- Never raises — all errors silently swallowed.
19
- No buffering — each call is one open+write+close.
20
- Stdlib only — json, os, sys, datetime, pathlib.
21
- """
22
-
23
- import json
24
- import os
25
- import sys
26
- from datetime import datetime, timezone
27
- from pathlib import Path
28
- from typing import Any, Dict, Optional
29
-
30
- _LEVELS = {"debug": 0, "info": 1, "warn": 2, "error": 3}
31
-
32
- _MAX_LOG_SIZE = 1024 * 1024 # 1MB
33
- _TRUNCATE_TO = 512 * 1024 # 512KB
34
-
35
- # Module-level context path cache.
36
- # Set once per hook process via set_context_path() or auto-resolved on first use.
37
- _cached_context_path: Optional[Path] = None
38
- _context_resolved: bool = False
39
-
40
-
41
- def set_context_path(path: Optional[Path]) -> None:
42
- """Set the context path for this process. All subsequent log calls use it.
43
-
44
- Call this once in your hook after resolving the context:
45
- from lib.base.logger import set_context_path
46
- set_context_path(get_context_dir(context_id, project_root))
47
-
48
- Args:
49
- path: Path to context folder (e.g., _output/contexts/<context-id>/)
50
- or None to force global-only logging.
51
- """
52
- global _cached_context_path, _context_resolved
53
- _cached_context_path = path
54
- _context_resolved = True
55
-
56
-
57
- def _auto_resolve_context_path() -> Optional[Path]:
58
- """Try to auto-resolve context path from session_id. Called once per process.
59
-
60
- Uses the context store to look up which context owns this session,
61
- then returns its directory path. Falls back to None (global log).
62
- """
63
- global _cached_context_path, _context_resolved
64
- _context_resolved = True # Don't retry on failure
65
-
66
- try:
67
- from ..context.context_store import get_context_by_session_id
68
- from .constants import get_context_dir
69
-
70
- # Hook input isn't available here, but we can check if a recent
71
- # context dir exists by scanning _output/contexts/ for one that
72
- # has a state.json with a matching session
73
- # This is too expensive for a logger. Instead, rely on set_context_path().
74
- except Exception:
75
- pass
76
-
77
- return None
78
-
79
-
80
- def _get_context_path() -> Optional[Path]:
81
- """Get the cached context path, auto-resolving on first call."""
82
- global _context_resolved
83
- if not _context_resolved:
84
- _auto_resolve_context_path()
85
- return _cached_context_path
86
-
87
-
88
- def _get_min_level() -> int:
89
- """Get minimum log level from environment."""
90
- env = os.environ.get("HOOK_LOG_LEVEL", "debug").lower()
91
- return _LEVELS.get(env, 0)
92
-
93
-
94
- def _is_disabled() -> bool:
95
- """Check if file logging is disabled."""
96
- if os.environ.get("HOOK_LOG_DISABLE") == "1":
97
- return True
98
- if os.environ.get("HOOK_ERROR_LOG_DISABLE") == "1":
99
- return True
100
- return False
101
-
102
-
103
- def _get_project_root() -> Path:
104
- """Get project root from environment or cwd."""
105
- env_dir = os.environ.get("CLAUDE_PROJECT_DIR", "")
106
- return Path(env_dir) if env_dir else Path.cwd()
107
-
108
-
109
- def hook_log(
110
- level: str,
111
- hook_name: str,
112
- message: str,
113
- *,
114
- component: str = "",
115
- data: Any = None,
116
- traceback_str: str = "",
117
- context_path: Optional[Path] = None,
118
- stderr: bool = True,
119
- ) -> None:
120
- """Write a structured log entry.
121
-
122
- Args:
123
- level: "debug" | "info" | "warn" | "error"
124
- hook_name: Hook or module name (e.g., "session_end")
125
- message: Log message
126
- component: Sub-component (e.g., "git", "parse")
127
- data: Optional structured data (must be JSON-serializable)
128
- traceback_str: Optional traceback string
129
- context_path: If provided, logs to context debug dir
130
- stderr: Also write to stderr (default: True)
131
- """
132
- try:
133
- level_lower = level.lower()
134
- level_num = _LEVELS.get(level_lower, 0)
135
-
136
- # Write to stderr if requested
137
- if stderr:
138
- prefix = f"[{hook_name}]"
139
- if component:
140
- prefix = f"[{hook_name}:{component}]"
141
- print(f"{prefix} {message}", file=sys.stderr)
142
- if traceback_str:
143
- print(traceback_str, file=sys.stderr)
144
-
145
- # Check if file logging is enabled
146
- if _is_disabled():
147
- return
148
-
149
- # Check minimum level
150
- if level_num < _get_min_level():
151
- return
152
-
153
- # Build JSONL entry
154
- ts = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3]
155
- entry = {
156
- "ts": ts,
157
- "level": level_lower,
158
- "hook": hook_name,
159
- "msg": message,
160
- }
161
- if component:
162
- entry["component"] = component
163
- if data is not None:
164
- try:
165
- json.dumps(data, default=str) # Validate serializable
166
- entry["data"] = data
167
- except (TypeError, ValueError):
168
- entry["data"] = str(data)
169
- if traceback_str:
170
- entry["tb"] = traceback_str.rstrip()
171
-
172
- line = json.dumps(entry, ensure_ascii=True, default=str) + "\n"
173
-
174
- # Determine log path: explicit > cached > global
175
- resolved_ctx = context_path or _get_context_path()
176
- if resolved_ctx and resolved_ctx.exists():
177
- log_path = resolved_ctx / "debug" / "hook-log.jsonl"
178
- else:
179
- project_root = _get_project_root()
180
- log_path = project_root / "_output" / "hook-log.jsonl"
181
-
182
- log_path.parent.mkdir(parents=True, exist_ok=True)
183
-
184
- # Size guard (global log only, not per-context)
185
- if not resolved_ctx and log_path.exists():
186
- try:
187
- if log_path.stat().st_size > _MAX_LOG_SIZE:
188
- file_data = log_path.read_bytes()
189
- log_path.write_bytes(file_data[-_TRUNCATE_TO:])
190
- except OSError:
191
- pass
192
-
193
- with open(log_path, "a", encoding="utf-8") as f:
194
- f.write(line)
195
-
196
- except Exception:
197
- pass # Never crash
198
-
199
-
200
- def log_debug(hook_name: str, message: str, **kwargs: Any) -> None:
201
- """Log a debug-level message."""
202
- hook_log("debug", hook_name, message, **kwargs)
203
-
204
-
205
- def log_info(hook_name: str, message: str, **kwargs: Any) -> None:
206
- """Log an info-level message."""
207
- hook_log("info", hook_name, message, **kwargs)
208
-
209
-
210
- def log_warn(hook_name: str, message: str, **kwargs: Any) -> None:
211
- """Log a warn-level message."""
212
- hook_log("warn", hook_name, message, **kwargs)
213
-
214
-
215
- def log_error(hook_name: str, message: str, **kwargs: Any) -> None:
216
- """Log an error-level message."""
217
- hook_log("error", hook_name, message, **kwargs)
218
-
219
-
220
- def log_diagnostic(
221
- hook_name: str,
222
- phase: str,
223
- summary: str,
224
- *,
225
- inputs: Any = None,
226
- decision: Any = None,
227
- reasoning: Any = None,
228
- component: str = "diag",
229
- data: Any = None,
230
- ) -> None:
231
- """Log a structured diagnostic entry at a hook decision point.
232
-
233
- Emits a debug-level JSONL entry with tagged, filterable data.
234
- Use at key decision points: receive (what came in), decide (what was chosen),
235
- result (what happened).
236
-
237
- Args:
238
- hook_name: Hook or module name (e.g., "session_start")
239
- phase: Decision phase — "receive", "decide", or "result"
240
- summary: One-line description (e.g., "source=clear, session=a1b2c3d4")
241
- inputs: Input data relevant to this phase
242
- decision: The decision made (for "decide" phase)
243
- reasoning: Why this decision was made
244
- component: Log component tag (default: "diag")
245
- data: Extra data to merge into the structured entry
246
- """
247
- diag_data: Dict[str, Any] = {"phase": phase}
248
- if inputs is not None:
249
- diag_data["inputs"] = inputs
250
- if decision is not None:
251
- diag_data["decision"] = decision
252
- if reasoning is not None:
253
- diag_data["reasoning"] = reasoning
254
- if data is not None and isinstance(data, dict):
255
- diag_data.update(data)
256
- hook_log(
257
- "debug",
258
- hook_name,
259
- f"[DIAG:{phase}] {summary}",
260
- component=component,
261
- data=diag_data,
262
- )
263
-
264
-
265
- def log_hook_error(
266
- hook_name: str,
267
- error: Exception,
268
- hook_event: str = "unknown",
269
- traceback_str: str = "",
270
- ) -> None:
271
- """Backward-compatible wrapper matching the old hook_utils.log_hook_error signature.
272
-
273
- Delegates to hook_log("error", ...) with the same behavior:
274
- - Message capped at 200 chars, newlines stripped
275
- - Never raises
276
-
277
- Args:
278
- hook_name: Name of the hook
279
- error: The exception that occurred
280
- hook_event: Hook event type (e.g., "PreToolUse")
281
- traceback_str: Optional formatted traceback
282
- """
283
- msg = str(error).replace("\n", " ").replace("\r", "")[:200]
284
- err_type = type(error).__name__
285
- hook_log(
286
- "error",
287
- hook_name,
288
- f"[{hook_event}] {err_type}: {msg}",
289
- traceback_str=traceback_str,
290
- stderr=True,
291
- )