aiwcli 0.9.0 → 0.9.1
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 +19 -35
- package/dist/lib/template-installer.js +38 -0
- package/dist/templates/_shared/.claude/commands/handoff.md +219 -7
- package/dist/templates/_shared/.codex/workflows/handoff.md +219 -7
- package/dist/templates/_shared/.windsurf/workflows/handoff.md +219 -7
- package/dist/templates/_shared/hooks/context_enforcer.py +9 -5
- package/dist/templates/_shared/hooks/context_monitor.py +28 -10
- package/dist/templates/_shared/hooks/file-suggestion.py +45 -15
- package/dist/templates/_shared/hooks/user_prompt_submit.py +0 -10
- package/dist/templates/_shared/lib/base/constants.py +45 -0
- package/dist/templates/_shared/lib/base/inference.py +44 -21
- package/dist/templates/_shared/lib/base/subprocess_utils.py +46 -0
- package/dist/templates/_shared/lib/base/utils.py +5 -3
- package/dist/templates/_shared/lib/context/__init__.py +0 -8
- package/dist/templates/_shared/lib/context/cache.py +2 -4
- package/dist/templates/_shared/lib/context/context_manager.py +1 -118
- package/dist/templates/_shared/lib/context/discovery.py +8 -50
- package/dist/templates/_shared/lib/handoff/document_generator.py +2 -5
- package/dist/templates/_shared/lib/templates/README.md +0 -1
- package/dist/templates/_shared/lib/templates/formatters.py +0 -1
- package/dist/templates/_shared/scripts/save_handoff.py +289 -43
- package/dist/templates/_shared/workflows/handoff.md +30 -16
- package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.py +41 -20
- package/dist/templates/cc-native/_cc-native/lib/orchestrator.py +9 -0
- package/dist/templates/cc-native/_cc-native/lib/reviewers/agent.py +9 -0
- package/dist/templates/cc-native/_cc-native/lib/utils.py +123 -10
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
|
@@ -157,15 +157,17 @@ def generate_context_id(summary: str, existing_ids: Optional[set] = None) -> str
|
|
|
157
157
|
from .inference import generate_semantic_summary
|
|
158
158
|
semantic = generate_semantic_summary(summary)
|
|
159
159
|
if semantic:
|
|
160
|
-
# Slugify the semantic summary
|
|
161
|
-
base_id = sanitize_title(semantic, max_len=
|
|
160
|
+
# Slugify the semantic summary (word limit already applied in inference)
|
|
161
|
+
base_id = sanitize_title(semantic, max_len=100)
|
|
162
162
|
eprint(f"[utils] Semantic context ID: {base_id}")
|
|
163
163
|
except Exception as e:
|
|
164
164
|
eprint(f"[utils] Inference failed, using fallback: {e}")
|
|
165
165
|
|
|
166
166
|
# Fallback to old method if inference failed
|
|
167
167
|
if not base_id:
|
|
168
|
-
|
|
168
|
+
# Fallback: take first 10 words with 3+ chars, then slugify
|
|
169
|
+
words = [w for w in summary.split() if len(w) >= 3][:10]
|
|
170
|
+
base_id = sanitize_title(' '.join(words), max_len=100)
|
|
169
171
|
|
|
170
172
|
if not existing_ids:
|
|
171
173
|
return base_id
|
|
@@ -12,9 +12,6 @@ from .context_manager import (
|
|
|
12
12
|
update_plan_status,
|
|
13
13
|
get_context_with_pending_plan,
|
|
14
14
|
get_context_with_in_flight_work,
|
|
15
|
-
update_handoff_status,
|
|
16
|
-
clear_handoff_status,
|
|
17
|
-
get_context_with_handoff_pending,
|
|
18
15
|
)
|
|
19
16
|
from .event_log import (
|
|
20
17
|
Task,
|
|
@@ -37,7 +34,6 @@ from .discovery import (
|
|
|
37
34
|
get_in_flight_context,
|
|
38
35
|
format_context_list,
|
|
39
36
|
format_pending_plan_continuation,
|
|
40
|
-
format_handoff_continuation,
|
|
41
37
|
format_implementation_continuation,
|
|
42
38
|
format_context_picker_prompt,
|
|
43
39
|
format_ready_for_new_work,
|
|
@@ -77,9 +73,6 @@ __all__ = [
|
|
|
77
73
|
"update_plan_status",
|
|
78
74
|
"get_context_with_pending_plan",
|
|
79
75
|
"get_context_with_in_flight_work",
|
|
80
|
-
"update_handoff_status",
|
|
81
|
-
"clear_handoff_status",
|
|
82
|
-
"get_context_with_handoff_pending",
|
|
83
76
|
# Event Log
|
|
84
77
|
"append_event",
|
|
85
78
|
"read_events",
|
|
@@ -97,7 +90,6 @@ __all__ = [
|
|
|
97
90
|
"get_in_flight_context",
|
|
98
91
|
"format_context_list",
|
|
99
92
|
"format_pending_plan_continuation",
|
|
100
|
-
"format_handoff_continuation",
|
|
101
93
|
"format_implementation_continuation",
|
|
102
94
|
"format_context_picker_prompt",
|
|
103
95
|
"format_ready_for_new_work",
|
|
@@ -115,13 +115,11 @@ def rebuild_context_from_events(context_dir: Path, project_root: Path = None) ->
|
|
|
115
115
|
context.in_flight.started_at = None
|
|
116
116
|
|
|
117
117
|
elif event_type == "handoff_created":
|
|
118
|
-
|
|
118
|
+
# Handoff events are informational only - no mode change
|
|
119
119
|
context.in_flight.handoff_path = event.get("path")
|
|
120
120
|
|
|
121
121
|
elif event_type == "handoff_cleared":
|
|
122
|
-
#
|
|
123
|
-
restored_mode = event.get("restored_mode", "none")
|
|
124
|
-
context.in_flight.mode = restored_mode
|
|
122
|
+
# Legacy event - just clear handoff_path, no mode change
|
|
125
123
|
context.in_flight.handoff_path = None
|
|
126
124
|
|
|
127
125
|
return context
|
|
@@ -933,122 +933,6 @@ def get_context_with_in_flight_work(project_root: Path = None) -> Optional[Conte
|
|
|
933
933
|
return None
|
|
934
934
|
|
|
935
935
|
|
|
936
|
-
def update_handoff_status(
|
|
937
|
-
context_id: str,
|
|
938
|
-
handoff_path: str,
|
|
939
|
-
project_root: Path = None
|
|
940
|
-
) -> Optional[Context]:
|
|
941
|
-
"""
|
|
942
|
-
Update context to indicate a handoff is pending.
|
|
943
|
-
|
|
944
|
-
Called by handoff document generator after creating handoff document.
|
|
945
|
-
Sets in_flight.mode = "handoff_pending" and in_flight.handoff_path.
|
|
946
|
-
|
|
947
|
-
Args:
|
|
948
|
-
context_id: Context identifier
|
|
949
|
-
handoff_path: Path to the handoff document
|
|
950
|
-
project_root: Project root directory
|
|
951
|
-
|
|
952
|
-
Returns:
|
|
953
|
-
Updated Context or None if not found
|
|
954
|
-
"""
|
|
955
|
-
context = get_context(context_id, project_root)
|
|
956
|
-
if not context:
|
|
957
|
-
return None
|
|
958
|
-
|
|
959
|
-
now = now_iso()
|
|
960
|
-
|
|
961
|
-
# Update in_flight state
|
|
962
|
-
context.in_flight.mode = "handoff_pending"
|
|
963
|
-
context.in_flight.handoff_path = handoff_path
|
|
964
|
-
context.in_flight.started_at = now
|
|
965
|
-
context.last_active = now
|
|
966
|
-
|
|
967
|
-
# Append event (source of truth) - MUST happen before cache updates
|
|
968
|
-
append_event(
|
|
969
|
-
context_id,
|
|
970
|
-
EVENT_HANDOFF_CREATED,
|
|
971
|
-
project_root,
|
|
972
|
-
path=handoff_path
|
|
973
|
-
)
|
|
974
|
-
|
|
975
|
-
# Update caches
|
|
976
|
-
_write_context_cache(context, project_root)
|
|
977
|
-
_update_index_cache(context, project_root)
|
|
978
|
-
|
|
979
|
-
eprint(f"[context_manager] Set handoff pending for: {context_id}")
|
|
980
|
-
return context
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
def clear_handoff_status(context_id: str, project_root: Path = None) -> Optional[Context]:
|
|
984
|
-
"""
|
|
985
|
-
Clear handoff pending status after resumption.
|
|
986
|
-
|
|
987
|
-
Called by SessionStart after successfully resuming from handoff.
|
|
988
|
-
|
|
989
|
-
Args:
|
|
990
|
-
context_id: Context identifier
|
|
991
|
-
project_root: Project root directory
|
|
992
|
-
|
|
993
|
-
Returns:
|
|
994
|
-
Updated Context or None if not found
|
|
995
|
-
"""
|
|
996
|
-
context = get_context(context_id, project_root)
|
|
997
|
-
if not context:
|
|
998
|
-
return None
|
|
999
|
-
|
|
1000
|
-
if context.in_flight.mode != "handoff_pending":
|
|
1001
|
-
return context # Nothing to clear
|
|
1002
|
-
|
|
1003
|
-
now = now_iso()
|
|
1004
|
-
|
|
1005
|
-
# Clear handoff state but preserve any artifact path (plan being implemented)
|
|
1006
|
-
# If artifact_path exists, restore to "implementing" mode; otherwise "none"
|
|
1007
|
-
if context.in_flight.artifact_path:
|
|
1008
|
-
context.in_flight.mode = "implementing"
|
|
1009
|
-
else:
|
|
1010
|
-
context.in_flight.mode = "none"
|
|
1011
|
-
context.in_flight.handoff_path = None
|
|
1012
|
-
# Don't clear started_at if we're still implementing
|
|
1013
|
-
if not context.in_flight.artifact_path:
|
|
1014
|
-
context.in_flight.started_at = None
|
|
1015
|
-
context.last_active = now
|
|
1016
|
-
|
|
1017
|
-
# Append event (source of truth) - MUST happen before cache updates
|
|
1018
|
-
append_event(
|
|
1019
|
-
context_id,
|
|
1020
|
-
EVENT_HANDOFF_CLEARED,
|
|
1021
|
-
project_root,
|
|
1022
|
-
restored_mode=context.in_flight.mode
|
|
1023
|
-
)
|
|
1024
|
-
|
|
1025
|
-
# Update caches
|
|
1026
|
-
_write_context_cache(context, project_root)
|
|
1027
|
-
_update_index_cache(context, project_root)
|
|
1028
|
-
|
|
1029
|
-
eprint(f"[context_manager] Cleared handoff status for: {context_id}")
|
|
1030
|
-
return context
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
def get_context_with_handoff_pending(project_root: Path = None) -> Optional[Context]:
|
|
1034
|
-
"""
|
|
1035
|
-
Find context with handoff pending (highest priority for SessionStart).
|
|
1036
|
-
|
|
1037
|
-
Args:
|
|
1038
|
-
project_root: Project root directory
|
|
1039
|
-
|
|
1040
|
-
Returns:
|
|
1041
|
-
Context with handoff pending, or None if not found
|
|
1042
|
-
"""
|
|
1043
|
-
contexts = get_all_contexts(status="active", project_root=project_root)
|
|
1044
|
-
|
|
1045
|
-
for context in contexts:
|
|
1046
|
-
if context.in_flight and context.in_flight.mode == "handoff_pending":
|
|
1047
|
-
return context
|
|
1048
|
-
|
|
1049
|
-
return None
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
936
|
def get_all_in_flight_contexts(project_root: Path = None) -> List[Context]:
|
|
1053
937
|
"""
|
|
1054
938
|
Return all contexts with truly in-flight work requiring attention.
|
|
@@ -1056,7 +940,6 @@ def get_all_in_flight_contexts(project_root: Path = None) -> List[Context]:
|
|
|
1056
940
|
In-flight modes (require continuation/action):
|
|
1057
941
|
- planning: Active planning session
|
|
1058
942
|
- pending_implementation: Plan created, awaiting implementation
|
|
1059
|
-
- handoff_pending: Handoff document created, awaiting pickup
|
|
1060
943
|
|
|
1061
944
|
NOT in-flight (normal working state):
|
|
1062
945
|
- implementing: Active work, but doesn't block new context creation
|
|
@@ -1073,7 +956,7 @@ def get_all_in_flight_contexts(project_root: Path = None) -> List[Context]:
|
|
|
1073
956
|
Returns:
|
|
1074
957
|
List of contexts with in-flight work requiring attention
|
|
1075
958
|
"""
|
|
1076
|
-
IN_FLIGHT_MODES = {"planning", "pending_implementation"
|
|
959
|
+
IN_FLIGHT_MODES = {"planning", "pending_implementation"}
|
|
1077
960
|
contexts = get_all_contexts(status="active", project_root=project_root)
|
|
1078
961
|
return [c for c in contexts if c.in_flight and c.in_flight.mode in IN_FLIGHT_MODES]
|
|
1079
962
|
|
|
@@ -42,13 +42,12 @@ def discover_contexts_for_session(
|
|
|
42
42
|
|
|
43
43
|
def get_in_flight_context(project_root: Path = None) -> Optional[Context]:
|
|
44
44
|
"""
|
|
45
|
-
Get context with any in-flight work (plan,
|
|
45
|
+
Get context with any in-flight work (plan, etc.).
|
|
46
46
|
|
|
47
47
|
Priority order:
|
|
48
|
-
1.
|
|
49
|
-
2.
|
|
50
|
-
3.
|
|
51
|
-
4. planning - actively planning
|
|
48
|
+
1. pending_implementation - plan ready for implementation
|
|
49
|
+
2. implementing - implementation in progress
|
|
50
|
+
3. planning - actively planning
|
|
52
51
|
|
|
53
52
|
Args:
|
|
54
53
|
project_root: Project root directory
|
|
@@ -60,15 +59,14 @@ def get_in_flight_context(project_root: Path = None) -> Optional[Context]:
|
|
|
60
59
|
|
|
61
60
|
# Sort by in-flight priority
|
|
62
61
|
priority_order = {
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"planning": 3,
|
|
62
|
+
"pending_implementation": 0,
|
|
63
|
+
"implementing": 1,
|
|
64
|
+
"planning": 2,
|
|
67
65
|
"none": 99,
|
|
68
66
|
}
|
|
69
67
|
|
|
70
68
|
# Only auto-continue for high-priority modes (not "implementing", "planning" or "none")
|
|
71
|
-
actionable_modes = {"
|
|
69
|
+
actionable_modes = {"pending_implementation"}
|
|
72
70
|
|
|
73
71
|
in_flight_contexts = [
|
|
74
72
|
c for c in contexts
|
|
@@ -177,46 +175,6 @@ def format_pending_plan_continuation(context: Context) -> str:
|
|
|
177
175
|
return "\n".join(lines)
|
|
178
176
|
|
|
179
177
|
|
|
180
|
-
def format_handoff_continuation(context: Context) -> str:
|
|
181
|
-
"""
|
|
182
|
-
Format output for handoff continuation scenario.
|
|
183
|
-
|
|
184
|
-
This is shown when SessionStart detects a context with
|
|
185
|
-
in_flight.mode = "handoff_pending".
|
|
186
|
-
|
|
187
|
-
Args:
|
|
188
|
-
context: Context with handoff pending
|
|
189
|
-
|
|
190
|
-
Returns:
|
|
191
|
-
Formatted instructions for Claude
|
|
192
|
-
"""
|
|
193
|
-
lines = [
|
|
194
|
-
format_continuation_header("resuming", context.id),
|
|
195
|
-
"",
|
|
196
|
-
f"**Summary:** {context.summary}",
|
|
197
|
-
"",
|
|
198
|
-
]
|
|
199
|
-
|
|
200
|
-
# Add handoff document link
|
|
201
|
-
if context.in_flight and context.in_flight.handoff_path:
|
|
202
|
-
lines.append(f"**Handoff document:**")
|
|
203
|
-
lines.append(f"`{context.in_flight.handoff_path}`")
|
|
204
|
-
lines.append("")
|
|
205
|
-
|
|
206
|
-
lines.extend([
|
|
207
|
-
"---",
|
|
208
|
-
"",
|
|
209
|
-
"**Instructions:**",
|
|
210
|
-
"1. Read the handoff document above",
|
|
211
|
-
"2. Use TaskCreate to restore pending tasks",
|
|
212
|
-
"3. Continue where the previous session left off",
|
|
213
|
-
"",
|
|
214
|
-
"The context has been loaded. You may continue.",
|
|
215
|
-
])
|
|
216
|
-
|
|
217
|
-
return "\n".join(lines)
|
|
218
|
-
|
|
219
|
-
|
|
220
178
|
def format_implementation_continuation(context: Context) -> str:
|
|
221
179
|
"""
|
|
222
180
|
Format output for ongoing implementation scenario.
|
|
@@ -83,7 +83,7 @@ def generate_handoff_document(
|
|
|
83
83
|
Returns:
|
|
84
84
|
HandoffDocument with file_path set, or None on failure
|
|
85
85
|
"""
|
|
86
|
-
from ..context.context_manager import get_context
|
|
86
|
+
from ..context.context_manager import get_context
|
|
87
87
|
|
|
88
88
|
context = get_context(context_id, project_root)
|
|
89
89
|
if not context:
|
|
@@ -141,7 +141,7 @@ def generate_handoff_document(
|
|
|
141
141
|
eprint(f"[handoff] ERROR: Failed to write handoff document: {error}")
|
|
142
142
|
return None
|
|
143
143
|
|
|
144
|
-
# Record event
|
|
144
|
+
# Record event (informational only - no mode change)
|
|
145
145
|
append_event(
|
|
146
146
|
context_id,
|
|
147
147
|
EVENT_HANDOFF_CREATED,
|
|
@@ -151,9 +151,6 @@ def generate_handoff_document(
|
|
|
151
151
|
session_id=session_id
|
|
152
152
|
)
|
|
153
153
|
|
|
154
|
-
# Update context in_flight state
|
|
155
|
-
update_handoff_status(context_id, str(file_path), project_root)
|
|
156
|
-
|
|
157
154
|
eprint(f"[handoff] Created handoff document: {file_path}")
|
|
158
155
|
return doc
|
|
159
156
|
|