aiwcli 0.10.3 → 0.11.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 (191) hide show
  1. package/bin/run.js +1 -1
  2. package/dist/commands/clear.js +28 -131
  3. package/dist/commands/init/index.js +3 -3
  4. package/dist/lib/gitignore-manager.d.ts +32 -0
  5. package/dist/lib/gitignore-manager.js +141 -2
  6. package/dist/templates/CLAUDE.md +8 -8
  7. package/dist/templates/_shared/.claude/commands/handoff-resume.md +64 -0
  8. package/dist/templates/_shared/.claude/commands/handoff.md +16 -10
  9. package/dist/templates/_shared/.claude/settings.json +7 -7
  10. package/dist/templates/_shared/hooks-ts/_utils/git-state.ts +2 -0
  11. package/dist/templates/_shared/hooks-ts/archive_plan.ts +159 -0
  12. package/dist/templates/_shared/hooks-ts/context_monitor.ts +147 -0
  13. package/dist/templates/_shared/hooks-ts/file-suggestion.ts +130 -0
  14. package/dist/templates/_shared/hooks-ts/pre_compact.ts +49 -0
  15. package/dist/templates/_shared/hooks-ts/session_end.ts +107 -0
  16. package/dist/templates/_shared/hooks-ts/session_start.ts +144 -0
  17. package/dist/templates/_shared/hooks-ts/task_create_capture.ts +48 -0
  18. package/dist/templates/_shared/hooks-ts/task_update_capture.ts +74 -0
  19. package/dist/templates/_shared/hooks-ts/user_prompt_submit.ts +83 -0
  20. package/dist/templates/_shared/lib-ts/CLAUDE.md +318 -0
  21. package/dist/templates/_shared/lib-ts/base/atomic-write.ts +12 -12
  22. package/dist/templates/_shared/lib-ts/base/constants.ts +22 -15
  23. package/dist/templates/_shared/lib-ts/base/git-state.ts +1 -1
  24. package/dist/templates/_shared/lib-ts/base/hook-utils.ts +129 -50
  25. package/dist/templates/_shared/lib-ts/base/inference.ts +28 -21
  26. package/dist/templates/_shared/lib-ts/base/logger.ts +15 -2
  27. package/dist/templates/_shared/lib-ts/base/state-io.ts +9 -7
  28. package/dist/templates/_shared/lib-ts/base/stop-words.ts +131 -131
  29. package/dist/templates/_shared/lib-ts/base/subprocess-utils.ts +142 -0
  30. package/dist/templates/_shared/lib-ts/base/utils.ts +69 -69
  31. package/dist/templates/_shared/lib-ts/context/context-formatter.ts +30 -24
  32. package/dist/templates/_shared/lib-ts/context/context-selector.ts +50 -32
  33. package/dist/templates/_shared/lib-ts/context/context-store.ts +76 -48
  34. package/dist/templates/_shared/lib-ts/context/plan-manager.ts +43 -23
  35. package/dist/templates/_shared/lib-ts/context/task-tracker.ts +10 -6
  36. package/dist/templates/_shared/lib-ts/handoff/document-generator.ts +11 -10
  37. package/dist/templates/_shared/lib-ts/handoff/handoff-reader.ts +158 -0
  38. package/dist/templates/_shared/lib-ts/templates/formatters.ts +6 -4
  39. package/dist/templates/_shared/lib-ts/types.ts +68 -55
  40. package/dist/templates/_shared/scripts/resolve_context.ts +24 -0
  41. package/dist/templates/_shared/scripts/resume_handoff.ts +345 -0
  42. package/dist/templates/_shared/scripts/save_handoff.ts +3 -3
  43. package/dist/templates/_shared/scripts/status_line.ts +687 -0
  44. package/dist/templates/cc-native/.claude/settings.json +175 -185
  45. package/dist/templates/cc-native/TEMPLATE-SCHEMA.md +15 -17
  46. package/dist/templates/cc-native/_cc-native/agents/CLAUDE.md +0 -2
  47. package/dist/templates/cc-native/_cc-native/hooks/CLAUDE.md +109 -135
  48. package/dist/templates/cc-native/_cc-native/hooks/add_plan_context.ts +119 -0
  49. package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.ts +1027 -0
  50. package/dist/templates/cc-native/_cc-native/hooks/plan_questions_early.ts +61 -0
  51. package/dist/templates/cc-native/_cc-native/lib-ts/aggregate-agents.ts +156 -0
  52. package/dist/templates/cc-native/_cc-native/lib-ts/artifacts.ts +792 -0
  53. package/dist/templates/cc-native/_cc-native/lib-ts/cc-native-state.ts +199 -0
  54. package/dist/templates/cc-native/_cc-native/lib-ts/cli-output-parser.ts +144 -0
  55. package/dist/templates/cc-native/_cc-native/lib-ts/config.ts +57 -0
  56. package/dist/templates/cc-native/_cc-native/lib-ts/constants.ts +83 -0
  57. package/dist/templates/cc-native/_cc-native/lib-ts/corroboration.ts +115 -0
  58. package/dist/templates/cc-native/_cc-native/lib-ts/debug.ts +80 -0
  59. package/dist/templates/cc-native/_cc-native/lib-ts/index.ts +120 -0
  60. package/dist/templates/cc-native/_cc-native/lib-ts/json-parser.ts +168 -0
  61. package/dist/templates/cc-native/_cc-native/lib-ts/nul +3 -0
  62. package/dist/templates/cc-native/_cc-native/lib-ts/orchestrator.ts +250 -0
  63. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/agent.ts +275 -0
  64. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/codex.ts +130 -0
  65. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/gemini.ts +107 -0
  66. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/index.ts +10 -0
  67. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/types.ts +23 -0
  68. package/dist/templates/cc-native/_cc-native/lib-ts/state.ts +240 -0
  69. package/dist/templates/cc-native/_cc-native/lib-ts/tsconfig.json +18 -0
  70. package/dist/templates/cc-native/_cc-native/lib-ts/types.ts +385 -0
  71. package/dist/templates/cc-native/_cc-native/lib-ts/verdict.ts +72 -0
  72. package/dist/templates/cc-native/_cc-native/plan-review.config.json +14 -1
  73. package/oclif.manifest.json +1 -1
  74. package/package.json +2 -2
  75. package/dist/templates/_shared/hooks/__init__.py +0 -16
  76. package/dist/templates/_shared/hooks/__pycache__/__init__.cpython-313.pyc +0 -0
  77. package/dist/templates/_shared/hooks/__pycache__/archive_plan.cpython-313.pyc +0 -0
  78. package/dist/templates/_shared/hooks/__pycache__/context_enforcer.cpython-313.pyc +0 -0
  79. package/dist/templates/_shared/hooks/__pycache__/context_monitor.cpython-313.pyc +0 -0
  80. package/dist/templates/_shared/hooks/__pycache__/file-suggestion.cpython-313.pyc +0 -0
  81. package/dist/templates/_shared/hooks/__pycache__/pre_compact.cpython-313.pyc +0 -0
  82. package/dist/templates/_shared/hooks/__pycache__/session_end.cpython-313.pyc +0 -0
  83. package/dist/templates/_shared/hooks/__pycache__/session_start.cpython-313.pyc +0 -0
  84. package/dist/templates/_shared/hooks/__pycache__/task_create_atomicity.cpython-313.pyc +0 -0
  85. package/dist/templates/_shared/hooks/__pycache__/task_create_capture.cpython-313.pyc +0 -0
  86. package/dist/templates/_shared/hooks/__pycache__/task_update_capture.cpython-313.pyc +0 -0
  87. package/dist/templates/_shared/hooks/__pycache__/user_prompt_submit.cpython-313.pyc +0 -0
  88. package/dist/templates/_shared/hooks/archive_plan.py +0 -177
  89. package/dist/templates/_shared/hooks/context_monitor.py +0 -270
  90. package/dist/templates/_shared/hooks/file-suggestion.py +0 -215
  91. package/dist/templates/_shared/hooks/pre_compact.py +0 -104
  92. package/dist/templates/_shared/hooks/session_end.py +0 -173
  93. package/dist/templates/_shared/hooks/session_start.py +0 -206
  94. package/dist/templates/_shared/hooks/task_create_capture.py +0 -108
  95. package/dist/templates/_shared/hooks/task_update_capture.py +0 -145
  96. package/dist/templates/_shared/hooks/user_prompt_submit.py +0 -139
  97. package/dist/templates/_shared/lib/__init__.py +0 -1
  98. package/dist/templates/_shared/lib/__pycache__/__init__.cpython-313.pyc +0 -0
  99. package/dist/templates/_shared/lib/base/__init__.py +0 -65
  100. package/dist/templates/_shared/lib/base/__pycache__/__init__.cpython-313.pyc +0 -0
  101. package/dist/templates/_shared/lib/base/__pycache__/atomic_write.cpython-313.pyc +0 -0
  102. package/dist/templates/_shared/lib/base/__pycache__/constants.cpython-313.pyc +0 -0
  103. package/dist/templates/_shared/lib/base/__pycache__/hook_utils.cpython-313.pyc +0 -0
  104. package/dist/templates/_shared/lib/base/__pycache__/inference.cpython-313.pyc +0 -0
  105. package/dist/templates/_shared/lib/base/__pycache__/logger.cpython-313.pyc +0 -0
  106. package/dist/templates/_shared/lib/base/__pycache__/stop_words.cpython-313.pyc +0 -0
  107. package/dist/templates/_shared/lib/base/__pycache__/subprocess_utils.cpython-313.pyc +0 -0
  108. package/dist/templates/_shared/lib/base/__pycache__/utils.cpython-313.pyc +0 -0
  109. package/dist/templates/_shared/lib/base/atomic_write.py +0 -180
  110. package/dist/templates/_shared/lib/base/constants.py +0 -358
  111. package/dist/templates/_shared/lib/base/hook_utils.py +0 -339
  112. package/dist/templates/_shared/lib/base/inference.py +0 -307
  113. package/dist/templates/_shared/lib/base/logger.py +0 -305
  114. package/dist/templates/_shared/lib/base/stop_words.py +0 -221
  115. package/dist/templates/_shared/lib/base/subprocess_utils.py +0 -46
  116. package/dist/templates/_shared/lib/base/utils.py +0 -263
  117. package/dist/templates/_shared/lib/context/__init__.py +0 -102
  118. package/dist/templates/_shared/lib/context/__pycache__/__init__.cpython-313.pyc +0 -0
  119. package/dist/templates/_shared/lib/context/__pycache__/cache.cpython-313.pyc +0 -0
  120. package/dist/templates/_shared/lib/context/__pycache__/context_extractor.cpython-313.pyc +0 -0
  121. package/dist/templates/_shared/lib/context/__pycache__/context_formatter.cpython-313.pyc +0 -0
  122. package/dist/templates/_shared/lib/context/__pycache__/context_manager.cpython-313.pyc +0 -0
  123. package/dist/templates/_shared/lib/context/__pycache__/context_selector.cpython-313.pyc +0 -0
  124. package/dist/templates/_shared/lib/context/__pycache__/context_store.cpython-313.pyc +0 -0
  125. package/dist/templates/_shared/lib/context/__pycache__/discovery.cpython-313.pyc +0 -0
  126. package/dist/templates/_shared/lib/context/__pycache__/event_log.cpython-313.pyc +0 -0
  127. package/dist/templates/_shared/lib/context/__pycache__/plan_archive.cpython-313.pyc +0 -0
  128. package/dist/templates/_shared/lib/context/__pycache__/plan_manager.cpython-313.pyc +0 -0
  129. package/dist/templates/_shared/lib/context/__pycache__/task_sync.cpython-313.pyc +0 -0
  130. package/dist/templates/_shared/lib/context/__pycache__/task_tracker.cpython-313.pyc +0 -0
  131. package/dist/templates/_shared/lib/context/context_formatter.py +0 -317
  132. package/dist/templates/_shared/lib/context/context_selector.py +0 -508
  133. package/dist/templates/_shared/lib/context/context_store.py +0 -653
  134. package/dist/templates/_shared/lib/context/plan_manager.py +0 -303
  135. package/dist/templates/_shared/lib/context/task_tracker.py +0 -188
  136. package/dist/templates/_shared/lib/handoff/__init__.py +0 -22
  137. package/dist/templates/_shared/lib/handoff/__pycache__/__init__.cpython-313.pyc +0 -0
  138. package/dist/templates/_shared/lib/handoff/__pycache__/document_generator.cpython-313.pyc +0 -0
  139. package/dist/templates/_shared/lib/handoff/document_generator.py +0 -278
  140. package/dist/templates/_shared/lib/templates/README.md +0 -206
  141. package/dist/templates/_shared/lib/templates/__init__.py +0 -36
  142. package/dist/templates/_shared/lib/templates/__pycache__/__init__.cpython-313.pyc +0 -0
  143. package/dist/templates/_shared/lib/templates/__pycache__/formatters.cpython-313.pyc +0 -0
  144. package/dist/templates/_shared/lib/templates/__pycache__/persona_questions.cpython-313.pyc +0 -0
  145. package/dist/templates/_shared/lib/templates/__pycache__/plan_context.cpython-313.pyc +0 -0
  146. package/dist/templates/_shared/lib/templates/formatters.py +0 -146
  147. package/dist/templates/_shared/lib/templates/plan_context.py +0 -73
  148. package/dist/templates/_shared/scripts/__pycache__/save_handoff.cpython-313.pyc +0 -0
  149. package/dist/templates/_shared/scripts/__pycache__/status_line.cpython-313.pyc +0 -0
  150. package/dist/templates/_shared/scripts/save_handoff.py +0 -357
  151. package/dist/templates/_shared/scripts/status_line.py +0 -716
  152. package/dist/templates/cc-native/.claude/commands/cc-native/fresh-perspective.md +0 -8
  153. package/dist/templates/cc-native/.windsurf/workflows/cc-native/fresh-perspective.md +0 -8
  154. package/dist/templates/cc-native/MIGRATION.md +0 -86
  155. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/add_plan_context.cpython-313.pyc +0 -0
  156. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/cc-native-plan-review.cpython-313.pyc +0 -0
  157. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/mark_questions_asked.cpython-313.pyc +0 -0
  158. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/plan_accepted.cpython-313.pyc +0 -0
  159. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/plan_questions_early.cpython-313.pyc +0 -0
  160. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/suggest-fresh-perspective.cpython-313.pyc +0 -0
  161. package/dist/templates/cc-native/_cc-native/hooks/add_plan_context.py +0 -130
  162. package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.py +0 -954
  163. package/dist/templates/cc-native/_cc-native/hooks/plan_questions_early.py +0 -81
  164. package/dist/templates/cc-native/_cc-native/hooks/suggest-fresh-perspective.py +0 -340
  165. package/dist/templates/cc-native/_cc-native/lib/CLAUDE.md +0 -265
  166. package/dist/templates/cc-native/_cc-native/lib/__init__.py +0 -53
  167. package/dist/templates/cc-native/_cc-native/lib/__pycache__/__init__.cpython-313.pyc +0 -0
  168. package/dist/templates/cc-native/_cc-native/lib/__pycache__/atomic_write.cpython-313.pyc +0 -0
  169. package/dist/templates/cc-native/_cc-native/lib/__pycache__/constants.cpython-313.pyc +0 -0
  170. package/dist/templates/cc-native/_cc-native/lib/__pycache__/debug.cpython-313.pyc +0 -0
  171. package/dist/templates/cc-native/_cc-native/lib/__pycache__/orchestrator.cpython-313.pyc +0 -0
  172. package/dist/templates/cc-native/_cc-native/lib/__pycache__/state.cpython-313.pyc +0 -0
  173. package/dist/templates/cc-native/_cc-native/lib/__pycache__/utils.cpython-313.pyc +0 -0
  174. package/dist/templates/cc-native/_cc-native/lib/constants.py +0 -45
  175. package/dist/templates/cc-native/_cc-native/lib/debug.py +0 -139
  176. package/dist/templates/cc-native/_cc-native/lib/orchestrator.py +0 -362
  177. package/dist/templates/cc-native/_cc-native/lib/reviewers/__init__.py +0 -28
  178. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/__init__.cpython-313.pyc +0 -0
  179. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/agent.cpython-313.pyc +0 -0
  180. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/base.cpython-313.pyc +0 -0
  181. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/codex.cpython-313.pyc +0 -0
  182. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/gemini.cpython-313.pyc +0 -0
  183. package/dist/templates/cc-native/_cc-native/lib/reviewers/agent.py +0 -215
  184. package/dist/templates/cc-native/_cc-native/lib/reviewers/base.py +0 -88
  185. package/dist/templates/cc-native/_cc-native/lib/reviewers/codex.py +0 -124
  186. package/dist/templates/cc-native/_cc-native/lib/reviewers/gemini.py +0 -108
  187. package/dist/templates/cc-native/_cc-native/lib/state.py +0 -268
  188. package/dist/templates/cc-native/_cc-native/lib/utils.py +0 -1071
  189. package/dist/templates/cc-native/_cc-native/scripts/__pycache__/aggregate_agents.cpython-313.pyc +0 -0
  190. package/dist/templates/cc-native/_cc-native/scripts/aggregate_agents.py +0 -168
  191. package/dist/templates/cc-native/_cc-native/workflows/fresh-perspective.md +0 -134
@@ -1,263 +0,0 @@
1
- """Core utilities for shared context management.
2
-
3
- Provides common functions used across all shared modules:
4
- - eprint: Print to stderr
5
- - now_local: Get current local datetime
6
- - project_dir: Get project directory from environment
7
- - sanitize_filename: Sanitize string for use in filenames
8
- - generate_context_id: Generate a slug from summary text
9
- """
10
- import os
11
- import re
12
- import sys
13
- from datetime import datetime
14
- from pathlib import Path
15
- from typing import Any, Dict, Optional
16
-
17
- from .logger import log_debug, log_info, log_warn, log_error
18
-
19
-
20
- def eprint(*args: Any) -> None:
21
- """Print to stderr."""
22
- print(*args, file=sys.stderr)
23
-
24
-
25
- def now_local() -> datetime:
26
- """Get current local datetime."""
27
- return datetime.now()
28
-
29
-
30
- def now_iso() -> str:
31
- """Get current time as ISO 8601 string."""
32
- return datetime.now().isoformat()
33
-
34
-
35
- def project_dir(payload: Optional[Dict[str, Any]] = None) -> Path:
36
- """
37
- Get project directory from payload or environment.
38
-
39
- Priority:
40
- 1. CLAUDE_PROJECT_DIR environment variable
41
- 2. 'cwd' from payload (if provided)
42
- 3. Current working directory
43
-
44
- Args:
45
- payload: Optional hook payload with 'cwd' field
46
-
47
- Returns:
48
- Path to project directory
49
-
50
- Note:
51
- CLAUDE_PROJECT_DIR is validated to be an absolute path when provided.
52
- """
53
- p = os.environ.get("CLAUDE_PROJECT_DIR")
54
- if p:
55
- # Validate that CLAUDE_PROJECT_DIR is an absolute path
56
- path = Path(p)
57
- if not path.is_absolute():
58
- log_warn("utils", "CLAUDE_PROJECT_DIR is not absolute, using cwd instead")
59
- p = None
60
- else:
61
- # Check for suspicious patterns
62
- if '..' in str(path):
63
- log_warn("utils", "CLAUDE_PROJECT_DIR contains '..' pattern, using cwd instead")
64
- p = None
65
-
66
- if not p and payload:
67
- p = payload.get("cwd")
68
- if not p:
69
- p = os.getcwd()
70
- return Path(p)
71
-
72
-
73
- # Windows reserved filenames that should be blocked
74
- _WINDOWS_RESERVED = frozenset([
75
- 'CON', 'PRN', 'AUX', 'NUL',
76
- 'COM1', 'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9',
77
- 'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9',
78
- ])
79
-
80
-
81
- def sanitize_filename(s: str, max_len: int = 32, allow_leading_dot: bool = False) -> str:
82
- """
83
- Sanitize string for use in filename.
84
-
85
- Replaces non-alphanumeric characters (except ._-) with underscores,
86
- strips leading/trailing special characters, and truncates.
87
-
88
- Args:
89
- s: Input string
90
- max_len: Maximum length (default: 32)
91
- allow_leading_dot: Whether to allow leading dots (default: False for security)
92
-
93
- Returns:
94
- Sanitized filename-safe string
95
- """
96
- s = re.sub(r"[^A-Za-z0-9._-]+", "_", s)
97
- result = s.strip("._-")[:max_len] or "unknown"
98
-
99
- # Remove leading dots unless explicitly allowed (prevents hidden files)
100
- if not allow_leading_dot:
101
- result = result.lstrip('.')
102
-
103
- # Check for Windows reserved names
104
- base_name = result.split('.')[0].upper()
105
- if base_name in _WINDOWS_RESERVED:
106
- result = f"_{result}"
107
-
108
- return result or "unknown"
109
-
110
-
111
- def sanitize_title(s: str, max_len: int = 50) -> str:
112
- """
113
- Sanitize title for use in context ID or filename.
114
-
115
- Converts spaces to hyphens, replaces special characters,
116
- and normalizes to lowercase.
117
-
118
- Args:
119
- s: Input string
120
- max_len: Maximum length (default: 50)
121
-
122
- Returns:
123
- Sanitized slug-like string
124
- """
125
- s = s.lower().strip()
126
- s = s.replace(' ', '-')
127
- s = re.sub(r"[^a-z0-9._-]+", "_", s)
128
- s = re.sub(r"[-_]+", "-", s)
129
- result = s.strip("._-")[:max_len] or "unknown"
130
-
131
- # Check for Windows reserved names
132
- base_name = result.split('.')[0].upper()
133
- if base_name in _WINDOWS_RESERVED:
134
- result = f"_{result}"
135
-
136
- return result or "unknown"
137
-
138
-
139
- def clean_text_for_slug(text: str) -> str:
140
- """
141
- Clean text for stop-word matching in slug generation.
142
-
143
- Strips apostrophes (i'm -> im), removes punctuation, normalizes whitespace.
144
- This ensures words like "generation," match their stop-word counterparts.
145
- """
146
- if not text:
147
- return ""
148
- text = text.lower()
149
- text = re.sub(r"'", "", text) # i'm -> im, you're -> youre
150
- text = re.sub(r"[^a-z0-9\s]", " ", text) # punctuation -> spaces
151
- text = re.sub(r"\s+", " ", text).strip()
152
- return text
153
-
154
-
155
- def generate_context_id(summary: str, existing_ids: Optional[set] = None) -> str:
156
- """
157
- Generate a context ID from a summary string.
158
-
159
- Prepends a YYMMDD-HHMM local-time timestamp for visual
160
- distinguishability, then filters stop words and slugifies.
161
-
162
- Args:
163
- summary: Context summary text
164
- existing_ids: Optional set of existing context IDs to avoid
165
-
166
- Returns:
167
- Unique context ID string (e.g. '260205-1700-add-user-auth')
168
- """
169
- # Timestamp prefix using local time, to the minute
170
- timestamp = datetime.now().strftime("%y%m%d-%H%M")
171
-
172
- try:
173
- if not summary or not summary.strip():
174
- base_id = f"{timestamp}-context"
175
- else:
176
- slug = None
177
- # Pre-clean for Tier 2/3: strip punctuation so stop words match
178
- cleaned_summary = clean_text_for_slug(summary)
179
-
180
- # Tier 1: AI inference for high-quality keyword slugs
181
- try:
182
- from .inference import generate_context_id_slug
183
- ai_slug = generate_context_id_slug(summary)
184
- if ai_slug:
185
- # Post-inference stop-word filter: remove generic words the AI included
186
- from .stop_words import STOP_WORDS
187
- filtered_words = [w for w in ai_slug.split() if w.lower() not in STOP_WORDS and len(w) > 1]
188
- if len(filtered_words) >= 5:
189
- slug = sanitize_title(' '.join(filtered_words), max_len=150)
190
- else:
191
- log_debug("utils", f"AI slug too generic after stop-word filter ({len(filtered_words)} words remain), using fallback")
192
- except Exception as e:
193
- log_warn("utils", f"AI context ID slug failed, using fallback: {e}")
194
-
195
- # Tier 2: Stop-word filtering on cleaned text
196
- if not slug:
197
- try:
198
- from .stop_words import STOP_WORDS
199
- words = [w for w in cleaned_summary.split() if w not in STOP_WORDS and len(w) > 1][:12]
200
- if len(words) >= 3:
201
- slug = sanitize_title(' '.join(words), max_len=150)
202
- else:
203
- log_debug("utils", f"Tier 2 too few content words ({len(words)}), falling through to Tier 3")
204
- except Exception as e:
205
- log_warn("utils", f"Stop-word fallback failed: {e}")
206
-
207
- # Tier 3: Simple word-length filter on cleaned text (no imports needed)
208
- if not slug or slug == "unknown":
209
- words = [w for w in cleaned_summary.split() if len(w) > 2][:6]
210
- slug = sanitize_title(' '.join(words), max_len=150) if words else "context"
211
-
212
- base_id = f"{timestamp}-{slug}"
213
- except Exception as e:
214
- log_error("utils", f"Context ID generation failed entirely, using timestamp: {e}")
215
- base_id = f"{timestamp}-context"
216
-
217
- if not existing_ids:
218
- return base_id
219
-
220
- # Ensure uniqueness by appending counter if needed
221
- if base_id not in existing_ids:
222
- return base_id
223
-
224
- counter = 2
225
- while f"{base_id}-{counter}" in existing_ids:
226
- counter += 1
227
-
228
- return f"{base_id}-{counter}"
229
-
230
-
231
- def format_timestamp(dt: Optional[datetime] = None) -> str:
232
- """
233
- Format datetime for display.
234
-
235
- Args:
236
- dt: Datetime to format (default: now)
237
-
238
- Returns:
239
- Formatted string like "2026-01-25 10:30:00"
240
- """
241
- if dt is None:
242
- dt = now_local()
243
- return dt.strftime("%Y-%m-%d %H:%M:%S")
244
-
245
-
246
- def parse_iso_timestamp(iso_str: str) -> Optional[datetime]:
247
- """
248
- Parse ISO 8601 timestamp string.
249
-
250
- Args:
251
- iso_str: ISO format timestamp
252
-
253
- Returns:
254
- datetime object or None if parsing fails
255
- """
256
- try:
257
- # Handle both with and without microseconds
258
- if '.' in iso_str:
259
- return datetime.fromisoformat(iso_str)
260
- else:
261
- return datetime.fromisoformat(iso_str.replace('Z', '+00:00'))
262
- except (ValueError, TypeError):
263
- return None
@@ -1,102 +0,0 @@
1
- """Context management for AIW CLI templates.
2
-
3
- New 2-layer architecture:
4
- context_store.py — CRUD for state.json + index.json
5
- context_selector.py — 5-case context selection (session match, caret, plan match, default)
6
- context_formatter.py — All display formatting
7
- plan_manager.py — Plan archival, lookup, path extraction
8
- task_tracker.py — Direct state.json task CRUD
9
- """
10
- from .context_store import (
11
- ContextState,
12
- get_all_contexts,
13
- get_context,
14
- get_context_by_session_id,
15
- create_context,
16
- create_context_from_prompt,
17
- update_context,
18
- complete_context,
19
- reopen_context,
20
- archive_context,
21
- bind_session,
22
- update_mode,
23
- maybe_activate,
24
- load_state,
25
- save_state,
26
- )
27
- from .context_selector import (
28
- determine_context,
29
- BlockRequest,
30
- parse_chained_caret,
31
- resolve_context_by_prefix,
32
- )
33
- from .context_formatter import (
34
- format_context_list,
35
- format_context_created,
36
- format_context_picker_stderr,
37
- format_active_context_reminder,
38
- format_handoff_continuation,
39
- format_plan_continuation,
40
- format_active_continuation,
41
- format_command_feedback,
42
- format_relative_time,
43
- )
44
- from .plan_manager import (
45
- archive_plan,
46
- find_latest_plan,
47
- extract_plan_path_from_result,
48
- )
49
- from .task_tracker import (
50
- add_task,
51
- update_task,
52
- delete_task,
53
- get_tasks,
54
- generate_task_summary,
55
- generate_next_task_id,
56
- )
57
-
58
- __all__ = [
59
- # Data model
60
- "ContextState",
61
- # Context store (CRUD)
62
- "get_all_contexts",
63
- "get_context",
64
- "get_context_by_session_id",
65
- "create_context",
66
- "create_context_from_prompt",
67
- "update_context",
68
- "complete_context",
69
- "reopen_context",
70
- "archive_context",
71
- "bind_session",
72
- "update_mode",
73
- "maybe_activate",
74
- "load_state",
75
- "save_state",
76
- # Context selector
77
- "determine_context",
78
- "BlockRequest",
79
- "parse_chained_caret",
80
- "resolve_context_by_prefix",
81
- # Formatting
82
- "format_context_list",
83
- "format_context_created",
84
- "format_context_picker_stderr",
85
- "format_active_context_reminder",
86
- "format_handoff_continuation",
87
- "format_plan_continuation",
88
- "format_active_continuation",
89
- "format_command_feedback",
90
- "format_relative_time",
91
- # Plan manager
92
- "archive_plan",
93
- "find_latest_plan",
94
- "extract_plan_path_from_result",
95
- # Task tracker
96
- "add_task",
97
- "update_task",
98
- "delete_task",
99
- "get_tasks",
100
- "generate_task_summary",
101
- "generate_next_task_id",
102
- ]