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.
- package/README.md +1248 -0
- package/bin/dev.cmd +3 -0
- package/bin/dev.js +16 -0
- package/bin/run.cmd +3 -0
- package/bin/run.js +19 -0
- package/dist/commands/branch.d.ts +45 -0
- package/dist/commands/branch.js +488 -0
- package/dist/commands/clean.d.ts +34 -0
- package/dist/commands/clean.js +186 -0
- package/dist/commands/clear.d.ts +51 -0
- package/dist/commands/clear.js +835 -0
- package/dist/commands/init/index.d.ts +107 -0
- package/dist/commands/init/index.js +565 -0
- package/dist/commands/launch.d.ts +21 -0
- package/dist/commands/launch.js +108 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/lib/base-command.d.ts +114 -0
- package/dist/lib/base-command.js +153 -0
- package/dist/lib/bmad-installer.d.ts +38 -0
- package/dist/lib/bmad-installer.js +145 -0
- package/dist/lib/claude-settings-types.d.ts +102 -0
- package/dist/lib/claude-settings-types.js +5 -0
- package/dist/lib/config.d.ts +25 -0
- package/dist/lib/config.js +46 -0
- package/dist/lib/debug.d.ts +39 -0
- package/dist/lib/debug.js +74 -0
- package/dist/lib/env-compat.d.ts +26 -0
- package/dist/lib/env-compat.js +35 -0
- package/dist/lib/errors.d.ts +126 -0
- package/dist/lib/errors.js +145 -0
- package/dist/lib/generic-merge.d.ts +74 -0
- package/dist/lib/generic-merge.js +105 -0
- package/dist/lib/git/branch.d.ts +67 -0
- package/dist/lib/git/branch.js +155 -0
- package/dist/lib/git/index.d.ts +11 -0
- package/dist/lib/git/index.js +13 -0
- package/dist/lib/git/safety-checks.d.ts +44 -0
- package/dist/lib/git/safety-checks.js +102 -0
- package/dist/lib/git/types.d.ts +31 -0
- package/dist/lib/git/types.js +6 -0
- package/dist/lib/git/worktree.d.ts +67 -0
- package/dist/lib/git/worktree.js +220 -0
- package/dist/lib/gitignore-manager.d.ts +10 -0
- package/dist/lib/gitignore-manager.js +60 -0
- package/dist/lib/hooks-merger.d.ts +28 -0
- package/dist/lib/hooks-merger.js +94 -0
- package/dist/lib/ide-path-resolver.d.ts +102 -0
- package/dist/lib/ide-path-resolver.js +129 -0
- package/dist/lib/index.d.ts +13 -0
- package/dist/lib/index.js +22 -0
- package/dist/lib/output.d.ts +51 -0
- package/dist/lib/output.js +76 -0
- package/dist/lib/paths.d.ts +66 -0
- package/dist/lib/paths.js +136 -0
- package/dist/lib/quiet.d.ts +12 -0
- package/dist/lib/quiet.js +17 -0
- package/dist/lib/settings-hierarchy.d.ts +42 -0
- package/dist/lib/settings-hierarchy.js +105 -0
- package/dist/lib/spawn.d.ts +105 -0
- package/dist/lib/spawn.js +157 -0
- package/dist/lib/spinner.d.ts +19 -0
- package/dist/lib/spinner.js +34 -0
- package/dist/lib/stdin.d.ts +48 -0
- package/dist/lib/stdin.js +60 -0
- package/dist/lib/template-installer.d.ts +92 -0
- package/dist/lib/template-installer.js +375 -0
- package/dist/lib/template-linter.d.ts +49 -0
- package/dist/lib/template-linter.js +173 -0
- package/dist/lib/template-merger.d.ts +47 -0
- package/dist/lib/template-merger.js +173 -0
- package/dist/lib/template-resolver.d.ts +20 -0
- package/dist/lib/template-resolver.js +60 -0
- package/dist/lib/terminal.d.ts +102 -0
- package/dist/lib/terminal.js +245 -0
- package/dist/lib/tty-detection.d.ts +62 -0
- package/dist/lib/tty-detection.js +83 -0
- package/dist/lib/user-utils.d.ts +5 -0
- package/dist/lib/user-utils.js +23 -0
- package/dist/lib/version.d.ts +99 -0
- package/dist/lib/version.js +144 -0
- package/dist/lib/watch-templates.d.ts +6 -0
- package/dist/lib/watch-templates.js +73 -0
- package/dist/lib/windsurf-hooks-hierarchy.d.ts +30 -0
- package/dist/lib/windsurf-hooks-hierarchy.js +66 -0
- package/dist/lib/windsurf-hooks-merger.d.ts +26 -0
- package/dist/lib/windsurf-hooks-merger.js +53 -0
- package/dist/lib/windsurf-hooks-types.d.ts +33 -0
- package/dist/lib/windsurf-hooks-types.js +5 -0
- package/dist/templates/CLAUDE.md +174 -0
- package/dist/templates/_shared/.claude/commands/handoff.md +14 -0
- package/dist/templates/_shared/.claude/settings.json +61 -0
- package/dist/templates/_shared/.codex/workflows/handoff.md +14 -0
- package/dist/templates/_shared/.windsurf/workflows/handoff.md +14 -0
- package/dist/templates/_shared/hooks/__init__.py +16 -0
- package/dist/templates/_shared/hooks/archive_plan.py +270 -0
- package/dist/templates/_shared/hooks/context_enforcer.py +621 -0
- package/dist/templates/_shared/hooks/context_monitor.py +322 -0
- package/dist/templates/_shared/hooks/file-suggestion.py +188 -0
- package/dist/templates/_shared/hooks/task_create_capture.py +194 -0
- package/dist/templates/_shared/hooks/task_update_capture.py +254 -0
- package/dist/templates/_shared/hooks/user_prompt_submit.py +157 -0
- package/dist/templates/_shared/lib/__init__.py +1 -0
- package/dist/templates/_shared/lib/base/__init__.py +49 -0
- package/dist/templates/_shared/lib/base/__pycache__/constants.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/base/atomic_write.py +180 -0
- package/dist/templates/_shared/lib/base/constants.py +299 -0
- package/dist/templates/_shared/lib/base/inference.py +189 -0
- package/dist/templates/_shared/lib/base/utils.py +216 -0
- package/dist/templates/_shared/lib/context/__init__.py +119 -0
- package/dist/templates/_shared/lib/context/__pycache__/__init__.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/context/__pycache__/cache.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/context/__pycache__/context_manager.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/context/__pycache__/event_log.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/context/cache.py +446 -0
- package/dist/templates/_shared/lib/context/context_manager.py +1171 -0
- package/dist/templates/_shared/lib/context/discovery.py +486 -0
- package/dist/templates/_shared/lib/context/event_log.py +308 -0
- package/dist/templates/_shared/lib/context/plan_archive.py +247 -0
- package/dist/templates/_shared/lib/context/task_sync.py +367 -0
- package/dist/templates/_shared/lib/handoff/__init__.py +22 -0
- package/dist/templates/_shared/lib/handoff/document_generator.py +307 -0
- package/dist/templates/_shared/lib/templates/README.md +215 -0
- package/dist/templates/_shared/lib/templates/__init__.py +40 -0
- package/dist/templates/_shared/lib/templates/formatters.py +147 -0
- package/dist/templates/_shared/lib/templates/plan_context.py +119 -0
- package/dist/templates/_shared/scripts/save_handoff.py +99 -0
- package/dist/templates/_shared/workflows/handoff.md +212 -0
- package/dist/templates/cc-native/.claude/agents/cc-native/ACCESSIBILITY-TESTER.md +80 -0
- package/dist/templates/cc-native/.claude/agents/cc-native/ARCHITECT-REVIEWER.md +75 -0
- package/dist/templates/cc-native/.claude/agents/cc-native/ASSUMPTION-CHAIN-TRACER.md +239 -0
- package/dist/templates/cc-native/.claude/agents/cc-native/CLARITY-AUDITOR.md +109 -0
- package/dist/templates/cc-native/.claude/agents/cc-native/CODE-REVIEWER.md +71 -0
- package/dist/templates/cc-native/.claude/agents/cc-native/COMPLETENESS-CHECKER.md +104 -0
- package/dist/templates/cc-native/.claude/agents/cc-native/CONTEXT-EXTRACTOR.md +93 -0
- package/dist/templates/cc-native/.claude/agents/cc-native/DEVILS-ADVOCATE.md +223 -0
- package/dist/templates/cc-native/.claude/agents/cc-native/DOCUMENTATION-REVIEWER.md +73 -0
- package/dist/templates/cc-native/.claude/agents/cc-native/FEASIBILITY-ANALYST.md +93 -0
- package/dist/templates/cc-native/.claude/agents/cc-native/FRESH-PERSPECTIVE.md +103 -0
- package/dist/templates/cc-native/.claude/agents/cc-native/HANDOFF-READINESS.md +145 -0
- package/dist/templates/cc-native/.claude/agents/cc-native/HIDDEN-COMPLEXITY-DETECTOR.md +248 -0
- package/dist/templates/cc-native/.claude/agents/cc-native/INCENTIVE-MAPPER.md +235 -0
- package/dist/templates/cc-native/.claude/agents/cc-native/PENETRATION-TESTER.md +80 -0
- package/dist/templates/cc-native/.claude/agents/cc-native/PERFORMANCE-ENGINEER.md +76 -0
- package/dist/templates/cc-native/.claude/agents/cc-native/PLAN-ORCHESTRATOR.md +141 -0
- package/dist/templates/cc-native/.claude/agents/cc-native/PRECEDENT-FINDER.md +240 -0
- package/dist/templates/cc-native/.claude/agents/cc-native/REVERSIBILITY-ANALYST.md +211 -0
- package/dist/templates/cc-native/.claude/agents/cc-native/RISK-ASSESSOR.md +101 -0
- package/dist/templates/cc-native/.claude/agents/cc-native/SECOND-ORDER-ANALYST.md +197 -0
- package/dist/templates/cc-native/.claude/agents/cc-native/SIMPLICITY-GUARDIAN.md +97 -0
- package/dist/templates/cc-native/.claude/agents/cc-native/SKEPTIC.md +349 -0
- package/dist/templates/cc-native/.claude/agents/cc-native/STAKEHOLDER-ADVOCATE.md +106 -0
- package/dist/templates/cc-native/.claude/agents/cc-native/TRADE-OFF-ILLUMINATOR.md +205 -0
- package/dist/templates/cc-native/.claude/commands/cc-native/fresh-perspective.md +8 -0
- package/dist/templates/cc-native/.claude/commands/cc-native/specdev.md +10 -0
- package/dist/templates/cc-native/.claude/settings.json +119 -0
- package/dist/templates/cc-native/.windsurf/workflows/cc-native/fix.md +8 -0
- package/dist/templates/cc-native/.windsurf/workflows/cc-native/fresh-perspective.md +8 -0
- package/dist/templates/cc-native/.windsurf/workflows/cc-native/implement.md +8 -0
- package/dist/templates/cc-native/.windsurf/workflows/cc-native/research.md +8 -0
- package/dist/templates/cc-native/CC-NATIVE-README.md +192 -0
- package/dist/templates/cc-native/MIGRATION.md +86 -0
- package/dist/templates/cc-native/TEMPLATE-SCHEMA.md +331 -0
- package/dist/templates/cc-native/_cc-native/docs/PERMISSION_REQUEST_VERIFICATION.md +147 -0
- package/dist/templates/cc-native/_cc-native/hooks/__pycache__/add_plan_context.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/hooks/__pycache__/archive_plan.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/hooks/__pycache__/cc-native-agent-review.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/hooks/__pycache__/cc-native-plan-review.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/hooks/__pycache__/test_permission_request.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/hooks/add_plan_context.py +150 -0
- package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.py +746 -0
- package/dist/templates/cc-native/_cc-native/hooks/suggest-fresh-perspective.py +339 -0
- package/dist/templates/cc-native/_cc-native/lib/__init__.py +57 -0
- package/dist/templates/cc-native/_cc-native/lib/__pycache__/__init__.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/lib/__pycache__/orchestrator.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/lib/__pycache__/state.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/lib/__pycache__/utils.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/lib/async_archive.py +68 -0
- package/dist/templates/cc-native/_cc-native/lib/atomic_write.py +98 -0
- package/dist/templates/cc-native/_cc-native/lib/constants.py +45 -0
- package/dist/templates/cc-native/_cc-native/lib/orchestrator.py +273 -0
- package/dist/templates/cc-native/_cc-native/lib/reviewers/__init__.py +28 -0
- package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/__init__.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/agent.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/base.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/codex.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/gemini.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/lib/reviewers/agent.py +164 -0
- package/dist/templates/cc-native/_cc-native/lib/reviewers/base.py +89 -0
- package/dist/templates/cc-native/_cc-native/lib/reviewers/codex.py +119 -0
- package/dist/templates/cc-native/_cc-native/lib/reviewers/gemini.py +103 -0
- package/dist/templates/cc-native/_cc-native/lib/state.py +251 -0
- package/dist/templates/cc-native/_cc-native/lib/utils.py +830 -0
- package/dist/templates/cc-native/_cc-native/plan-review.config.json +76 -0
- package/dist/templates/cc-native/_cc-native/scripts/__pycache__/aggregate_agents.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/scripts/aggregate_agents.py +151 -0
- package/dist/templates/cc-native/_cc-native/workflows/fresh-perspective.md +134 -0
- package/dist/templates/cc-native/_cc-native/workflows/specdev.md +9 -0
- package/dist/types/exit-codes.d.ts +11 -0
- package/dist/types/exit-codes.js +10 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.js +7 -0
- package/oclif.manifest.json +405 -0
- 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()
|