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.
Files changed (28) hide show
  1. package/README.md +19 -35
  2. package/dist/lib/template-installer.js +38 -0
  3. package/dist/templates/_shared/.claude/commands/handoff.md +219 -7
  4. package/dist/templates/_shared/.codex/workflows/handoff.md +219 -7
  5. package/dist/templates/_shared/.windsurf/workflows/handoff.md +219 -7
  6. package/dist/templates/_shared/hooks/context_enforcer.py +9 -5
  7. package/dist/templates/_shared/hooks/context_monitor.py +28 -10
  8. package/dist/templates/_shared/hooks/file-suggestion.py +45 -15
  9. package/dist/templates/_shared/hooks/user_prompt_submit.py +0 -10
  10. package/dist/templates/_shared/lib/base/constants.py +45 -0
  11. package/dist/templates/_shared/lib/base/inference.py +44 -21
  12. package/dist/templates/_shared/lib/base/subprocess_utils.py +46 -0
  13. package/dist/templates/_shared/lib/base/utils.py +5 -3
  14. package/dist/templates/_shared/lib/context/__init__.py +0 -8
  15. package/dist/templates/_shared/lib/context/cache.py +2 -4
  16. package/dist/templates/_shared/lib/context/context_manager.py +1 -118
  17. package/dist/templates/_shared/lib/context/discovery.py +8 -50
  18. package/dist/templates/_shared/lib/handoff/document_generator.py +2 -5
  19. package/dist/templates/_shared/lib/templates/README.md +0 -1
  20. package/dist/templates/_shared/lib/templates/formatters.py +0 -1
  21. package/dist/templates/_shared/scripts/save_handoff.py +289 -43
  22. package/dist/templates/_shared/workflows/handoff.md +30 -16
  23. package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.py +41 -20
  24. package/dist/templates/cc-native/_cc-native/lib/orchestrator.py +9 -0
  25. package/dist/templates/cc-native/_cc-native/lib/reviewers/agent.py +9 -0
  26. package/dist/templates/cc-native/_cc-native/lib/utils.py +123 -10
  27. package/oclif.manifest.json +1 -1
  28. 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=60)
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
- base_id = sanitize_title(summary[:50])
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
- context.in_flight.mode = "handoff_pending"
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
- # Restore to "implementing" if artifact exists, otherwise "none"
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", "handoff_pending"}
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, handoff, etc.).
45
+ Get context with any in-flight work (plan, etc.).
46
46
 
47
47
  Priority order:
48
- 1. handoff_pending - highest priority (user was interrupted)
49
- 2. pending_implementation - plan ready for implementation
50
- 3. implementing - implementation in progress
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
- "handoff_pending": 0,
64
- "pending_implementation": 1,
65
- "implementing": 2,
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 = {"handoff_pending", "pending_implementation"}
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, update_handoff_status
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
 
@@ -25,7 +25,6 @@ MODE_DISPLAY_MAP = {
25
25
  "planning": "[Planning]",
26
26
  "pending_implementation": "[Plan Ready]",
27
27
  "implementing": "[Implementing]",
28
- "handoff_pending": "[Handoff Pending]",
29
28
  "none": "",
30
29
  }
31
30
 
@@ -11,7 +11,6 @@ MODE_DISPLAY_MAP = {
11
11
  "planning": "[Planning]",
12
12
  "pending_implementation": "[Plan Ready]",
13
13
  "implementing": "[Implementing]",
14
- "handoff_pending": "[Handoff Pending]",
15
14
  "none": "",
16
15
  }
17
16