aiwcli 0.9.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 (204) hide show
  1. package/README.md +1248 -0
  2. package/bin/dev.cmd +3 -0
  3. package/bin/dev.js +16 -0
  4. package/bin/run.cmd +3 -0
  5. package/bin/run.js +19 -0
  6. package/dist/commands/branch.d.ts +45 -0
  7. package/dist/commands/branch.js +488 -0
  8. package/dist/commands/clean.d.ts +34 -0
  9. package/dist/commands/clean.js +186 -0
  10. package/dist/commands/clear.d.ts +51 -0
  11. package/dist/commands/clear.js +835 -0
  12. package/dist/commands/init/index.d.ts +107 -0
  13. package/dist/commands/init/index.js +565 -0
  14. package/dist/commands/launch.d.ts +21 -0
  15. package/dist/commands/launch.js +108 -0
  16. package/dist/index.d.ts +1 -0
  17. package/dist/index.js +1 -0
  18. package/dist/lib/base-command.d.ts +114 -0
  19. package/dist/lib/base-command.js +153 -0
  20. package/dist/lib/bmad-installer.d.ts +38 -0
  21. package/dist/lib/bmad-installer.js +145 -0
  22. package/dist/lib/claude-settings-types.d.ts +102 -0
  23. package/dist/lib/claude-settings-types.js +5 -0
  24. package/dist/lib/config.d.ts +25 -0
  25. package/dist/lib/config.js +46 -0
  26. package/dist/lib/debug.d.ts +39 -0
  27. package/dist/lib/debug.js +74 -0
  28. package/dist/lib/env-compat.d.ts +26 -0
  29. package/dist/lib/env-compat.js +35 -0
  30. package/dist/lib/errors.d.ts +126 -0
  31. package/dist/lib/errors.js +145 -0
  32. package/dist/lib/generic-merge.d.ts +74 -0
  33. package/dist/lib/generic-merge.js +105 -0
  34. package/dist/lib/git/branch.d.ts +67 -0
  35. package/dist/lib/git/branch.js +155 -0
  36. package/dist/lib/git/index.d.ts +11 -0
  37. package/dist/lib/git/index.js +13 -0
  38. package/dist/lib/git/safety-checks.d.ts +44 -0
  39. package/dist/lib/git/safety-checks.js +102 -0
  40. package/dist/lib/git/types.d.ts +31 -0
  41. package/dist/lib/git/types.js +6 -0
  42. package/dist/lib/git/worktree.d.ts +67 -0
  43. package/dist/lib/git/worktree.js +220 -0
  44. package/dist/lib/gitignore-manager.d.ts +10 -0
  45. package/dist/lib/gitignore-manager.js +60 -0
  46. package/dist/lib/hooks-merger.d.ts +28 -0
  47. package/dist/lib/hooks-merger.js +94 -0
  48. package/dist/lib/ide-path-resolver.d.ts +102 -0
  49. package/dist/lib/ide-path-resolver.js +129 -0
  50. package/dist/lib/index.d.ts +13 -0
  51. package/dist/lib/index.js +22 -0
  52. package/dist/lib/output.d.ts +51 -0
  53. package/dist/lib/output.js +76 -0
  54. package/dist/lib/paths.d.ts +66 -0
  55. package/dist/lib/paths.js +136 -0
  56. package/dist/lib/quiet.d.ts +12 -0
  57. package/dist/lib/quiet.js +17 -0
  58. package/dist/lib/settings-hierarchy.d.ts +42 -0
  59. package/dist/lib/settings-hierarchy.js +105 -0
  60. package/dist/lib/spawn.d.ts +105 -0
  61. package/dist/lib/spawn.js +157 -0
  62. package/dist/lib/spinner.d.ts +19 -0
  63. package/dist/lib/spinner.js +34 -0
  64. package/dist/lib/stdin.d.ts +48 -0
  65. package/dist/lib/stdin.js +60 -0
  66. package/dist/lib/template-installer.d.ts +92 -0
  67. package/dist/lib/template-installer.js +375 -0
  68. package/dist/lib/template-linter.d.ts +49 -0
  69. package/dist/lib/template-linter.js +173 -0
  70. package/dist/lib/template-merger.d.ts +47 -0
  71. package/dist/lib/template-merger.js +173 -0
  72. package/dist/lib/template-resolver.d.ts +20 -0
  73. package/dist/lib/template-resolver.js +60 -0
  74. package/dist/lib/terminal.d.ts +102 -0
  75. package/dist/lib/terminal.js +245 -0
  76. package/dist/lib/tty-detection.d.ts +62 -0
  77. package/dist/lib/tty-detection.js +83 -0
  78. package/dist/lib/user-utils.d.ts +5 -0
  79. package/dist/lib/user-utils.js +23 -0
  80. package/dist/lib/version.d.ts +99 -0
  81. package/dist/lib/version.js +144 -0
  82. package/dist/lib/watch-templates.d.ts +6 -0
  83. package/dist/lib/watch-templates.js +73 -0
  84. package/dist/lib/windsurf-hooks-hierarchy.d.ts +30 -0
  85. package/dist/lib/windsurf-hooks-hierarchy.js +66 -0
  86. package/dist/lib/windsurf-hooks-merger.d.ts +26 -0
  87. package/dist/lib/windsurf-hooks-merger.js +53 -0
  88. package/dist/lib/windsurf-hooks-types.d.ts +33 -0
  89. package/dist/lib/windsurf-hooks-types.js +5 -0
  90. package/dist/templates/CLAUDE.md +174 -0
  91. package/dist/templates/_shared/.claude/commands/handoff.md +14 -0
  92. package/dist/templates/_shared/.claude/settings.json +61 -0
  93. package/dist/templates/_shared/.codex/workflows/handoff.md +14 -0
  94. package/dist/templates/_shared/.windsurf/workflows/handoff.md +14 -0
  95. package/dist/templates/_shared/hooks/__init__.py +16 -0
  96. package/dist/templates/_shared/hooks/archive_plan.py +270 -0
  97. package/dist/templates/_shared/hooks/context_enforcer.py +621 -0
  98. package/dist/templates/_shared/hooks/context_monitor.py +322 -0
  99. package/dist/templates/_shared/hooks/file-suggestion.py +188 -0
  100. package/dist/templates/_shared/hooks/task_create_capture.py +194 -0
  101. package/dist/templates/_shared/hooks/task_update_capture.py +254 -0
  102. package/dist/templates/_shared/hooks/user_prompt_submit.py +157 -0
  103. package/dist/templates/_shared/lib/__init__.py +1 -0
  104. package/dist/templates/_shared/lib/base/__init__.py +49 -0
  105. package/dist/templates/_shared/lib/base/__pycache__/constants.cpython-313.pyc +0 -0
  106. package/dist/templates/_shared/lib/base/atomic_write.py +180 -0
  107. package/dist/templates/_shared/lib/base/constants.py +299 -0
  108. package/dist/templates/_shared/lib/base/inference.py +189 -0
  109. package/dist/templates/_shared/lib/base/utils.py +216 -0
  110. package/dist/templates/_shared/lib/context/__init__.py +119 -0
  111. package/dist/templates/_shared/lib/context/__pycache__/__init__.cpython-313.pyc +0 -0
  112. package/dist/templates/_shared/lib/context/__pycache__/cache.cpython-313.pyc +0 -0
  113. package/dist/templates/_shared/lib/context/__pycache__/context_manager.cpython-313.pyc +0 -0
  114. package/dist/templates/_shared/lib/context/__pycache__/event_log.cpython-313.pyc +0 -0
  115. package/dist/templates/_shared/lib/context/cache.py +446 -0
  116. package/dist/templates/_shared/lib/context/context_manager.py +1171 -0
  117. package/dist/templates/_shared/lib/context/discovery.py +486 -0
  118. package/dist/templates/_shared/lib/context/event_log.py +308 -0
  119. package/dist/templates/_shared/lib/context/plan_archive.py +247 -0
  120. package/dist/templates/_shared/lib/context/task_sync.py +367 -0
  121. package/dist/templates/_shared/lib/handoff/__init__.py +22 -0
  122. package/dist/templates/_shared/lib/handoff/document_generator.py +307 -0
  123. package/dist/templates/_shared/lib/templates/README.md +215 -0
  124. package/dist/templates/_shared/lib/templates/__init__.py +40 -0
  125. package/dist/templates/_shared/lib/templates/formatters.py +147 -0
  126. package/dist/templates/_shared/lib/templates/plan_context.py +119 -0
  127. package/dist/templates/_shared/scripts/save_handoff.py +99 -0
  128. package/dist/templates/_shared/workflows/handoff.md +212 -0
  129. package/dist/templates/cc-native/.claude/agents/cc-native/ACCESSIBILITY-TESTER.md +80 -0
  130. package/dist/templates/cc-native/.claude/agents/cc-native/ARCHITECT-REVIEWER.md +75 -0
  131. package/dist/templates/cc-native/.claude/agents/cc-native/ASSUMPTION-CHAIN-TRACER.md +239 -0
  132. package/dist/templates/cc-native/.claude/agents/cc-native/CLARITY-AUDITOR.md +109 -0
  133. package/dist/templates/cc-native/.claude/agents/cc-native/CODE-REVIEWER.md +71 -0
  134. package/dist/templates/cc-native/.claude/agents/cc-native/COMPLETENESS-CHECKER.md +104 -0
  135. package/dist/templates/cc-native/.claude/agents/cc-native/CONTEXT-EXTRACTOR.md +93 -0
  136. package/dist/templates/cc-native/.claude/agents/cc-native/DEVILS-ADVOCATE.md +223 -0
  137. package/dist/templates/cc-native/.claude/agents/cc-native/DOCUMENTATION-REVIEWER.md +73 -0
  138. package/dist/templates/cc-native/.claude/agents/cc-native/FEASIBILITY-ANALYST.md +93 -0
  139. package/dist/templates/cc-native/.claude/agents/cc-native/FRESH-PERSPECTIVE.md +103 -0
  140. package/dist/templates/cc-native/.claude/agents/cc-native/HANDOFF-READINESS.md +145 -0
  141. package/dist/templates/cc-native/.claude/agents/cc-native/HIDDEN-COMPLEXITY-DETECTOR.md +248 -0
  142. package/dist/templates/cc-native/.claude/agents/cc-native/INCENTIVE-MAPPER.md +235 -0
  143. package/dist/templates/cc-native/.claude/agents/cc-native/PENETRATION-TESTER.md +80 -0
  144. package/dist/templates/cc-native/.claude/agents/cc-native/PERFORMANCE-ENGINEER.md +76 -0
  145. package/dist/templates/cc-native/.claude/agents/cc-native/PLAN-ORCHESTRATOR.md +141 -0
  146. package/dist/templates/cc-native/.claude/agents/cc-native/PRECEDENT-FINDER.md +240 -0
  147. package/dist/templates/cc-native/.claude/agents/cc-native/REVERSIBILITY-ANALYST.md +211 -0
  148. package/dist/templates/cc-native/.claude/agents/cc-native/RISK-ASSESSOR.md +101 -0
  149. package/dist/templates/cc-native/.claude/agents/cc-native/SECOND-ORDER-ANALYST.md +197 -0
  150. package/dist/templates/cc-native/.claude/agents/cc-native/SIMPLICITY-GUARDIAN.md +97 -0
  151. package/dist/templates/cc-native/.claude/agents/cc-native/SKEPTIC.md +349 -0
  152. package/dist/templates/cc-native/.claude/agents/cc-native/STAKEHOLDER-ADVOCATE.md +106 -0
  153. package/dist/templates/cc-native/.claude/agents/cc-native/TRADE-OFF-ILLUMINATOR.md +205 -0
  154. package/dist/templates/cc-native/.claude/commands/cc-native/fresh-perspective.md +8 -0
  155. package/dist/templates/cc-native/.claude/commands/cc-native/specdev.md +10 -0
  156. package/dist/templates/cc-native/.claude/settings.json +119 -0
  157. package/dist/templates/cc-native/.windsurf/workflows/cc-native/fix.md +8 -0
  158. package/dist/templates/cc-native/.windsurf/workflows/cc-native/fresh-perspective.md +8 -0
  159. package/dist/templates/cc-native/.windsurf/workflows/cc-native/implement.md +8 -0
  160. package/dist/templates/cc-native/.windsurf/workflows/cc-native/research.md +8 -0
  161. package/dist/templates/cc-native/CC-NATIVE-README.md +192 -0
  162. package/dist/templates/cc-native/MIGRATION.md +86 -0
  163. package/dist/templates/cc-native/TEMPLATE-SCHEMA.md +331 -0
  164. package/dist/templates/cc-native/_cc-native/docs/PERMISSION_REQUEST_VERIFICATION.md +147 -0
  165. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/add_plan_context.cpython-313.pyc +0 -0
  166. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/archive_plan.cpython-313.pyc +0 -0
  167. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/cc-native-agent-review.cpython-313.pyc +0 -0
  168. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/cc-native-plan-review.cpython-313.pyc +0 -0
  169. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/test_permission_request.cpython-313.pyc +0 -0
  170. package/dist/templates/cc-native/_cc-native/hooks/add_plan_context.py +150 -0
  171. package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.py +746 -0
  172. package/dist/templates/cc-native/_cc-native/hooks/suggest-fresh-perspective.py +339 -0
  173. package/dist/templates/cc-native/_cc-native/lib/__init__.py +57 -0
  174. package/dist/templates/cc-native/_cc-native/lib/__pycache__/__init__.cpython-313.pyc +0 -0
  175. package/dist/templates/cc-native/_cc-native/lib/__pycache__/orchestrator.cpython-313.pyc +0 -0
  176. package/dist/templates/cc-native/_cc-native/lib/__pycache__/state.cpython-313.pyc +0 -0
  177. package/dist/templates/cc-native/_cc-native/lib/__pycache__/utils.cpython-313.pyc +0 -0
  178. package/dist/templates/cc-native/_cc-native/lib/async_archive.py +68 -0
  179. package/dist/templates/cc-native/_cc-native/lib/atomic_write.py +98 -0
  180. package/dist/templates/cc-native/_cc-native/lib/constants.py +45 -0
  181. package/dist/templates/cc-native/_cc-native/lib/orchestrator.py +273 -0
  182. package/dist/templates/cc-native/_cc-native/lib/reviewers/__init__.py +28 -0
  183. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/__init__.cpython-313.pyc +0 -0
  184. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/agent.cpython-313.pyc +0 -0
  185. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/base.cpython-313.pyc +0 -0
  186. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/codex.cpython-313.pyc +0 -0
  187. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/gemini.cpython-313.pyc +0 -0
  188. package/dist/templates/cc-native/_cc-native/lib/reviewers/agent.py +164 -0
  189. package/dist/templates/cc-native/_cc-native/lib/reviewers/base.py +89 -0
  190. package/dist/templates/cc-native/_cc-native/lib/reviewers/codex.py +119 -0
  191. package/dist/templates/cc-native/_cc-native/lib/reviewers/gemini.py +103 -0
  192. package/dist/templates/cc-native/_cc-native/lib/state.py +251 -0
  193. package/dist/templates/cc-native/_cc-native/lib/utils.py +830 -0
  194. package/dist/templates/cc-native/_cc-native/plan-review.config.json +76 -0
  195. package/dist/templates/cc-native/_cc-native/scripts/__pycache__/aggregate_agents.cpython-313.pyc +0 -0
  196. package/dist/templates/cc-native/_cc-native/scripts/aggregate_agents.py +151 -0
  197. package/dist/templates/cc-native/_cc-native/workflows/fresh-perspective.md +134 -0
  198. package/dist/templates/cc-native/_cc-native/workflows/specdev.md +9 -0
  199. package/dist/types/exit-codes.d.ts +11 -0
  200. package/dist/types/exit-codes.js +10 -0
  201. package/dist/types/index.d.ts +5 -0
  202. package/dist/types/index.js +7 -0
  203. package/oclif.manifest.json +405 -0
  204. package/package.json +109 -0
@@ -0,0 +1,215 @@
1
+ # Shared Templates Module
2
+
3
+ Centralized templates and formatters for consistent context management output across discovery, handoff, and hooks.
4
+
5
+ ## Purpose
6
+
7
+ This module eliminates duplication by providing a single source of truth for:
8
+ - Mode displays (planning, implementing, etc.)
9
+ - Status icons (pending, in_progress, completed)
10
+ - Task rendering formatters
11
+ - Context continuation headers
12
+ - Plan context templates
13
+ - Handoff reason formatting
14
+
15
+ ## Modules
16
+
17
+ ### `formatters.py`
18
+
19
+ Core formatters and constants for context management output.
20
+
21
+ #### Constants
22
+
23
+ ```python
24
+ MODE_DISPLAY_MAP = {
25
+ "planning": "[Planning]",
26
+ "pending_implementation": "[Plan Ready]",
27
+ "implementing": "[Implementing]",
28
+ "handoff_pending": "[Handoff Pending]",
29
+ "none": "",
30
+ }
31
+
32
+ STATUS_ICON_MAP = {
33
+ "pending": "⬜",
34
+ "in_progress": "🔄",
35
+ "blocked": "🚫",
36
+ "completed": "✅",
37
+ }
38
+
39
+ REASON_MAP = {
40
+ "low_context": "Context window running low",
41
+ "user_requested": "User requested handoff",
42
+ "error_recovery": "Error recovery",
43
+ "session_end": "Session ending",
44
+ }
45
+ ```
46
+
47
+ #### Functions
48
+
49
+ **`get_mode_display(mode: str) -> str`**
50
+
51
+ Get display string for in-flight mode.
52
+
53
+ ```python
54
+ >>> get_mode_display("planning")
55
+ "[Planning]"
56
+ >>> get_mode_display("none")
57
+ ""
58
+ ```
59
+
60
+ **`get_status_icon(status: str) -> str`**
61
+
62
+ Get emoji icon for task status.
63
+
64
+ ```python
65
+ >>> get_status_icon("pending")
66
+ "⬜"
67
+ >>> get_status_icon("completed")
68
+ "✅"
69
+ ```
70
+
71
+ **`render_task_item(task, show_description=True, max_description_length=100) -> str`**
72
+
73
+ Render single task with status icon and subject.
74
+
75
+ ```python
76
+ task = {"status": "pending", "subject": "Fix bug", "description": "Details"}
77
+ >>> render_task_item(task)
78
+ "- ⬜ [PENDING] Fix bug\n - Details"
79
+ ```
80
+
81
+ **`render_task_list(tasks, header="Active Tasks", show_description=True) -> str`**
82
+
83
+ Render list of tasks with header.
84
+
85
+ ```python
86
+ tasks = [{"status": "pending", "subject": "Task 1", "description": "Details"}]
87
+ >>> render_task_list(tasks, header="My Tasks")
88
+ "### My Tasks\n\n- ⬜ [PENDING] Task 1\n - Details\n"
89
+ ```
90
+
91
+ **`format_continuation_header(header_type: str, context_id: str) -> str`**
92
+
93
+ Format continuation header for various scenarios.
94
+
95
+ ```python
96
+ >>> format_continuation_header("resuming", "my-context")
97
+ "## RESUMING FROM HANDOFF: my-context"
98
+ ```
99
+
100
+ Types: `context`, `resuming`, `implementing`, `handoff`
101
+
102
+ **`format_reason(reason: str) -> str`**
103
+
104
+ Format handoff reason code as human-readable string.
105
+
106
+ ```python
107
+ >>> format_reason("low_context")
108
+ "Context window running low"
109
+ ```
110
+
111
+ ### `plan_context.py`
112
+
113
+ Plan context templates for the add_plan_context hook.
114
+
115
+ **`get_evaluation_context_reminder() -> str`**
116
+
117
+ Returns the evaluation context reminder template that prompts Claude to add evaluation context to plans.
118
+
119
+ **`get_questions_offer_template() -> str`**
120
+
121
+ Returns the clarifying questions offer template shown on first plan write.
122
+
123
+ ## Usage
124
+
125
+ ### In Discovery Functions
126
+
127
+ ```python
128
+ from ..templates.formatters import (
129
+ get_mode_display,
130
+ get_status_icon,
131
+ format_continuation_header,
132
+ )
133
+
134
+ # Display mode status
135
+ mode_display = get_mode_display(context.in_flight.mode)
136
+ status = f"Context: {context.id} {mode_display}"
137
+
138
+ # Render task with icon
139
+ icon = get_status_icon(task.status)
140
+ output = f"{icon} {task.subject}"
141
+
142
+ # Create continuation header
143
+ header = format_continuation_header("implementing", context.id)
144
+ ```
145
+
146
+ ### In Document Generator
147
+
148
+ ```python
149
+ from ..templates.formatters import render_task_list, format_reason
150
+
151
+ # Render task list section
152
+ tasks_md = render_task_list(doc.active_tasks, header="Active Tasks")
153
+ lines.append(tasks_md)
154
+
155
+ # Format handoff reason
156
+ reason_text = format_reason(doc.reason)
157
+ ```
158
+
159
+ ### In Hooks
160
+
161
+ ```python
162
+ from templates.plan_context import (
163
+ get_evaluation_context_reminder,
164
+ get_questions_offer_template,
165
+ )
166
+
167
+ # Get plan context templates
168
+ CONTEXT_REMINDER = get_evaluation_context_reminder()
169
+ QUESTIONS_OFFER = get_questions_offer_template()
170
+ ```
171
+
172
+ ## Dependent Files
173
+
174
+ Files that import from this module:
175
+
176
+ - `.aiwcli/_shared/lib/context/discovery.py`
177
+ - Uses: `get_mode_display`, `get_status_icon`, `format_continuation_header`
178
+
179
+ - `.aiwcli/_shared/lib/handoff/document_generator.py`
180
+ - Uses: `render_task_list`, `format_continuation_header`, `format_reason`
181
+
182
+ - `.aiwcli/_cc-native/hooks/add_plan_context.py`
183
+ - Uses: `get_evaluation_context_reminder`, `get_questions_offer_template`
184
+
185
+ ## Design Principles
186
+
187
+ 1. **Single Source of Truth**: Each constant/function exists in one location only
188
+ 2. **Backward Compatible**: All functions preserve existing output formats
189
+ 3. **Type Flexible**: Functions handle both Task objects and dicts
190
+ 4. **Fail-Safe**: Use `.get()` with defaults for missing keys
191
+
192
+ ## Testing
193
+
194
+ ```bash
195
+ # Test imports
196
+ cd .aiwcli
197
+ python -c "from _shared.lib.templates.formatters import get_mode_display; \
198
+ assert get_mode_display('planning') == '[Planning]'"
199
+
200
+ # Test task rendering
201
+ python -c "from _shared.lib.templates.formatters import get_status_icon; \
202
+ assert get_status_icon('pending') != ''"
203
+ ```
204
+
205
+ ## Synchronization
206
+
207
+ Changes to this module must be synchronized to the template directory:
208
+
209
+ ```bash
210
+ # After editing
211
+ cp .aiwcli/_shared/lib/templates/*.py \
212
+ packages/cli/src/templates/_shared/lib/templates/
213
+ ```
214
+
215
+ See `CLAUDE.md` for template synchronization requirements.
@@ -0,0 +1,40 @@
1
+ """Shared templates and formatters for context management output.
2
+
3
+ This module provides centralized templates for:
4
+ - Mode displays (planning, implementing, etc.)
5
+ - Status icons (pending, in_progress, completed)
6
+ - Task rendering
7
+ - Context continuation headers
8
+
9
+ Used by discovery.py, document_generator.py, and hooks.
10
+ """
11
+
12
+ from .formatters import (
13
+ MODE_DISPLAY_MAP,
14
+ STATUS_ICON_MAP,
15
+ REASON_MAP,
16
+ get_mode_display,
17
+ get_status_icon,
18
+ render_task_item,
19
+ render_task_list,
20
+ format_continuation_header,
21
+ format_reason,
22
+ )
23
+ from .plan_context import (
24
+ get_evaluation_context_reminder,
25
+ get_questions_offer_template,
26
+ )
27
+
28
+ __all__ = [
29
+ "MODE_DISPLAY_MAP",
30
+ "STATUS_ICON_MAP",
31
+ "REASON_MAP",
32
+ "get_mode_display",
33
+ "get_status_icon",
34
+ "render_task_item",
35
+ "render_task_list",
36
+ "format_continuation_header",
37
+ "format_reason",
38
+ "get_evaluation_context_reminder",
39
+ "get_questions_offer_template",
40
+ ]
@@ -0,0 +1,147 @@
1
+ """Formatters for context management templates.
2
+
3
+ Provides constants and helper functions for consistent formatting
4
+ across discovery, handoff, and hook output.
5
+ """
6
+
7
+ from typing import Any, Dict, List, Optional, Union
8
+
9
+ # Mode display mapping for in-flight work states
10
+ MODE_DISPLAY_MAP = {
11
+ "planning": "[Planning]",
12
+ "pending_implementation": "[Plan Ready]",
13
+ "implementing": "[Implementing]",
14
+ "handoff_pending": "[Handoff Pending]",
15
+ "none": "",
16
+ }
17
+
18
+ # Status icon mapping for task states
19
+ STATUS_ICON_MAP = {
20
+ "pending": "⬜",
21
+ "in_progress": "🔄",
22
+ "blocked": "🚫",
23
+ "completed": "✅",
24
+ }
25
+
26
+
27
+ def get_mode_display(mode: str) -> str:
28
+ """Get display string for in-flight mode.
29
+
30
+ Args:
31
+ mode: In-flight mode string (planning, implementing, etc.)
32
+
33
+ Returns:
34
+ Display string like "[Planning]" or empty string for "none"
35
+ """
36
+ return MODE_DISPLAY_MAP.get(mode, "")
37
+
38
+
39
+ def get_status_icon(status: str) -> str:
40
+ """Get emoji icon for task status.
41
+
42
+ Args:
43
+ status: Task status (pending, in_progress, blocked, completed)
44
+
45
+ Returns:
46
+ Emoji icon like "⬜" or "✅"
47
+ """
48
+ return STATUS_ICON_MAP.get(status, "⬜")
49
+
50
+
51
+ def render_task_item(
52
+ task: Union["Task", Dict[str, Any]],
53
+ show_description: bool = True,
54
+ max_description_length: int = 100
55
+ ) -> str:
56
+ """Render single task with status icon and subject.
57
+
58
+ Args:
59
+ task: Task object or dict with status, subject, description
60
+ show_description: Whether to include description
61
+ max_description_length: Maximum length for description before truncating
62
+
63
+ Returns:
64
+ Formatted string: "- {icon} [{STATUS}] {subject}"
65
+ """
66
+ # Handle both Task objects and dicts
67
+ status = task.get("status") if isinstance(task, dict) else task.status
68
+ subject = task.get("subject") if isinstance(task, dict) else task.subject
69
+ description = task.get("description") if isinstance(task, dict) else task.description
70
+
71
+ icon = get_status_icon(status)
72
+ status_text = f"[{status.upper()}]"
73
+ line = f"- {icon} {status_text} {subject}"
74
+
75
+ if show_description and description:
76
+ truncated = description[:max_description_length]
77
+ if len(description) > max_description_length:
78
+ truncated += "..."
79
+ return f"{line}\n - {truncated}"
80
+ return line
81
+
82
+
83
+ def render_task_list(
84
+ tasks: List[Union["Task", Dict[str, Any]]],
85
+ header: Optional[str] = "Active Tasks",
86
+ show_description: bool = True
87
+ ) -> str:
88
+ """Render list of tasks with header.
89
+
90
+ Args:
91
+ tasks: List of Task objects or dicts
92
+ header: Section header text
93
+ show_description: Whether to show task descriptions
94
+
95
+ Returns:
96
+ Formatted markdown section with task list
97
+ """
98
+ lines = [f"### {header}", ""]
99
+
100
+ if not tasks:
101
+ lines.append("No active tasks.")
102
+ else:
103
+ for task in tasks:
104
+ lines.append(render_task_item(task, show_description))
105
+
106
+ lines.append("")
107
+ return "\n".join(lines)
108
+
109
+
110
+ def format_continuation_header(header_type: str, context_id: str) -> str:
111
+ """Format continuation header for various scenarios.
112
+
113
+ Args:
114
+ header_type: Type of continuation (context, resuming, implementing, handoff)
115
+ context_id: Context identifier
116
+
117
+ Returns:
118
+ Formatted markdown header
119
+ """
120
+ headers = {
121
+ "context": f"## CONTINUING CONTEXT: {context_id}",
122
+ "resuming": f"## RESUMING FROM HANDOFF: {context_id}",
123
+ "implementing": f"## CONTINUING IMPLEMENTATION: {context_id}",
124
+ "handoff": f"# Session Handoff: {context_id}",
125
+ }
126
+ return headers.get(header_type, f"## {context_id}")
127
+
128
+
129
+ # Handoff reason display mapping
130
+ REASON_MAP = {
131
+ "low_context": "Context window running low",
132
+ "user_requested": "User requested handoff",
133
+ "error_recovery": "Error recovery",
134
+ "session_end": "Session ending",
135
+ }
136
+
137
+
138
+ def format_reason(reason: str) -> str:
139
+ """Format handoff reason code as human-readable string.
140
+
141
+ Args:
142
+ reason: Reason code (low_context, user_requested, etc.)
143
+
144
+ Returns:
145
+ Human-readable reason string
146
+ """
147
+ return REASON_MAP.get(reason, reason)
@@ -0,0 +1,119 @@
1
+ """Plan context templates for add_plan_context hook.
2
+
3
+ Provides standardized templates for:
4
+ - Evaluation context reminder
5
+ - Clarifying questions offer
6
+ """
7
+
8
+
9
+ def get_evaluation_context_reminder() -> str:
10
+ """Get the plan evaluation context reminder template.
11
+
12
+ Returns:
13
+ Formatted markdown reminder about adding evaluation context
14
+ """
15
+ return """
16
+ ## IMPORTANT: This Plan Will Be Executed in a Fresh Context
17
+
18
+ Your plan will be:
19
+ 1. **Reviewed** by agents who have NO access to this conversation
20
+ 2. **Executed** by a Claude agent starting with a completely fresh context
21
+
22
+ The implementing agent won't have access to your research, file explorations, or any conversation history. Your plan must be **self-contained** and provide everything needed to execute it successfully.
23
+
24
+ ### Required Plan Elements
25
+
26
+ 1. **A title line** at the very top: `# Plan: <descriptive title>`
27
+
28
+ 2. **Context Section** near the top with:
29
+ - **Background**: The bigger picture - why this change is needed and what problem it solves
30
+ - **Task**: What is being built/changed (specific and actionable)
31
+ - **Goal**: The underlying problem the user wants solved
32
+ - **Constraints**: Technical requirements, preferences, or limitations mentioned
33
+
34
+ 3. **Relevant Files** section listing:
35
+ - Files that will be modified (with brief description of what changes)
36
+ - Files to reference for patterns/context (with why they're relevant)
37
+ - Any configuration files that matter
38
+
39
+ 4. **Implementation Details** that are explicit enough for someone unfamiliar with your research:
40
+ - Don't assume the implementer knows what you discovered
41
+ - Include specific function names, patterns, or approaches to use
42
+ - Reference line numbers or code snippets if helpful
43
+
44
+ ### Example
45
+
46
+ ```markdown
47
+ # Plan: Add OAuth2 Authentication
48
+
49
+ ## Context
50
+ **Background**: The app currently only supports username/password auth. Users have requested social login to reduce friction during signup.
51
+ **Task**: Implement OAuth2 flow for user authentication
52
+ **Goal**: Enable secure third-party authentication via Google and GitHub
53
+ **Constraints**: Must integrate with existing session management; no new dependencies preferred
54
+
55
+ ## Relevant Files
56
+ **Modify:**
57
+ - `src/auth/middleware.ts` - Add OAuth callback handlers
58
+ - `src/routes/auth.ts` - Add OAuth routes
59
+
60
+ **Reference for patterns:**
61
+ - `src/auth/password.ts` - Shows existing auth flow pattern
62
+ - `src/config/index.ts` - Where to add OAuth credentials
63
+
64
+ ## Implementation Steps
65
+ [Detailed steps here...]
66
+ ```
67
+
68
+ This context allows reviewers to assess whether your plan addresses the user's needs, AND enables the implementing agent to execute it without needing to re-discover your research.
69
+ """.strip()
70
+
71
+
72
+ def get_questions_offer_template() -> str:
73
+ """Get the clarifying questions offer template.
74
+
75
+ Returns:
76
+ Formatted markdown prompt for offering clarifying questions
77
+ """
78
+ return """
79
+ ## First Plan Write - Optional Clarifying Questions
80
+
81
+ Your initial plan has been saved. Before finalizing, ask the user if they'd like to answer clarifying questions to refine it.
82
+
83
+ **Use AskUserQuestion now with this question:**
84
+
85
+ Header: "Questions?"
86
+ Question: "I've drafted an initial plan. Would you like to answer a few clarifying questions so I can refine it?"
87
+ Options:
88
+ - "Yes, ask me questions" (description: "I'll interview you about technical details, constraints, and preferences, then update the plan")
89
+ - "No, proceed as-is" (description: "Skip questions and proceed with the current plan")
90
+
91
+ ### If user chooses YES - Interview them about:
92
+
93
+ 1. **Technical Implementation**
94
+ - Preferred approaches or patterns?
95
+ - Technologies/libraries to use or avoid?
96
+ - Performance or scalability requirements?
97
+
98
+ 2. **Constraints & Requirements**
99
+ - Hard constraints that must be respected?
100
+ - Deadlines or scope limitations?
101
+ - Dependencies on other systems?
102
+
103
+ 3. **Edge Cases & Concerns**
104
+ - Known edge cases to handle?
105
+ - Security or privacy considerations?
106
+ - Error handling preferences?
107
+
108
+ 4. **Tradeoffs**
109
+ - Speed vs. quality preferences?
110
+ - Simplicity vs. flexibility?
111
+ - What's acceptable to defer to later?
112
+
113
+ Ask focused, **non-obvious** questions using AskUserQuestion (max 12). Questions should surface hidden constraints, unstated assumptions, or preferences that aren't evident from the original request - things that would meaningfully change the plan.
114
+
115
+ After gathering answers, **update the plan file** with the refined content before calling ExitPlanMode.
116
+
117
+ ### If user chooses NO:
118
+ Proceed directly to ExitPlanMode with the current plan.
119
+ """.strip()
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env python3
2
+ """Save a handoff document and set context status to handoff_pending.
3
+
4
+ Usage:
5
+ python .aiwcli/_shared/scripts/save_handoff.py <context_id> <<'EOF'
6
+ # Your handoff markdown content here
7
+ EOF
8
+
9
+ Or with a file:
10
+ python .aiwcli/_shared/scripts/save_handoff.py <context_id> < handoff.md
11
+
12
+ This script:
13
+ 1. Reads handoff markdown content from stdin
14
+ 2. Saves it to _output/contexts/{context_id}/handoffs/HANDOFF-{HHMM}.md
15
+ 3. Sets in_flight.mode = "handoff_pending"
16
+ 4. Records the event in events.jsonl
17
+
18
+ The handoff will be automatically picked up by the next session.
19
+ """
20
+ import sys
21
+ from datetime import datetime
22
+ from pathlib import Path
23
+
24
+ # Add parent directories to path for imports
25
+ SCRIPT_DIR = Path(__file__).resolve().parent
26
+ SHARED_ROOT = SCRIPT_DIR.parent
27
+ sys.path.insert(0, str(SHARED_ROOT))
28
+
29
+ from lib.context.context_manager import update_handoff_status, get_context
30
+ from lib.base.utils import eprint, atomic_write
31
+
32
+
33
+ def main():
34
+ if len(sys.argv) < 2:
35
+ print("Usage: python save_handoff.py <context_id> < content.md", file=sys.stderr)
36
+ print(" python save_handoff.py <context_id> <<'EOF'", file=sys.stderr)
37
+ print(" ... markdown content ...", file=sys.stderr)
38
+ print(" EOF", file=sys.stderr)
39
+ sys.exit(1)
40
+
41
+ context_id = sys.argv[1]
42
+
43
+ # Read content from stdin
44
+ content = sys.stdin.read()
45
+ if not content.strip():
46
+ print("Error: No content provided via stdin", file=sys.stderr)
47
+ sys.exit(1)
48
+
49
+ # Project root is the parent of .aiwcli
50
+ project_root = SHARED_ROOT.parent.parent
51
+
52
+ # Verify context exists
53
+ context = get_context(context_id, project_root)
54
+ if not context:
55
+ print(f"Error: Context not found: {context_id}", file=sys.stderr)
56
+ sys.exit(1)
57
+
58
+ # Create handoffs directory
59
+ handoffs_dir = project_root / "_output" / "contexts" / context_id / "handoffs"
60
+ handoffs_dir.mkdir(parents=True, exist_ok=True)
61
+
62
+ # Generate filename with timestamp
63
+ timestamp = datetime.now().strftime("%H%M")
64
+ filename = f"HANDOFF-{timestamp}.md"
65
+ file_path = handoffs_dir / filename
66
+
67
+ # Handle filename collision (add suffix if file exists)
68
+ counter = 1
69
+ while file_path.exists():
70
+ filename = f"HANDOFF-{timestamp}-{counter}.md"
71
+ file_path = handoffs_dir / filename
72
+ counter += 1
73
+
74
+ # Save the handoff document
75
+ try:
76
+ success, error = atomic_write(file_path, content)
77
+ if not success:
78
+ print(f"Error: Failed to write handoff: {error}", file=sys.stderr)
79
+ sys.exit(1)
80
+ except Exception as e:
81
+ print(f"Error: Failed to write handoff: {e}", file=sys.stderr)
82
+ sys.exit(1)
83
+
84
+ # Update context status
85
+ try:
86
+ update_handoff_status(context_id, str(file_path), project_root)
87
+ except Exception as e:
88
+ eprint(f"[save_handoff] Warning: Status update failed: {e}")
89
+ # Don't exit - file was saved successfully
90
+
91
+ # Output success message
92
+ print(f"✓ Saved handoff: {file_path}")
93
+ print(f"✓ Set status to handoff_pending for context: {context_id}")
94
+ print()
95
+ print("The next session will automatically offer to resume from this handoff.")
96
+
97
+
98
+ if __name__ == "__main__":
99
+ main()