aiwcli 0.9.7 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/bin/run.js +5 -2
  2. package/dist/lib/claude-settings-types.d.ts +2 -0
  3. package/dist/templates/CLAUDE.md +49 -18
  4. package/dist/templates/_shared/.claude/settings.json +4 -0
  5. package/dist/templates/_shared/hooks/__pycache__/__init__.cpython-313.pyc +0 -0
  6. package/dist/templates/_shared/hooks/__pycache__/archive_plan.cpython-313.pyc +0 -0
  7. package/dist/templates/_shared/hooks/__pycache__/context_enforcer.cpython-313.pyc +0 -0
  8. package/dist/templates/_shared/hooks/__pycache__/context_monitor.cpython-313.pyc +0 -0
  9. package/dist/templates/_shared/hooks/__pycache__/file-suggestion.cpython-313.pyc +0 -0
  10. package/dist/templates/_shared/hooks/__pycache__/pre_compact.cpython-313.pyc +0 -0
  11. package/dist/templates/_shared/hooks/__pycache__/session_end.cpython-313.pyc +0 -0
  12. package/dist/templates/_shared/hooks/__pycache__/session_start.cpython-313.pyc +0 -0
  13. package/dist/templates/_shared/hooks/__pycache__/task_create_atomicity.cpython-313.pyc +0 -0
  14. package/dist/templates/_shared/hooks/__pycache__/task_create_capture.cpython-313.pyc +0 -0
  15. package/dist/templates/_shared/hooks/__pycache__/task_update_capture.cpython-313.pyc +0 -0
  16. package/dist/templates/_shared/hooks/__pycache__/user_prompt_submit.cpython-313.pyc +0 -0
  17. package/dist/templates/_shared/hooks/archive_plan.py +87 -178
  18. package/dist/templates/_shared/hooks/context_monitor.py +128 -194
  19. package/dist/templates/_shared/hooks/file-suggestion.py +26 -23
  20. package/dist/templates/_shared/hooks/pre_compact.py +104 -0
  21. package/dist/templates/_shared/hooks/session_end.py +154 -0
  22. package/dist/templates/_shared/hooks/session_start.py +145 -59
  23. package/dist/templates/_shared/hooks/task_create_capture.py +26 -49
  24. package/dist/templates/_shared/hooks/task_update_capture.py +42 -100
  25. package/dist/templates/_shared/hooks/user_prompt_submit.py +63 -77
  26. package/dist/templates/_shared/lib/base/__init__.py +16 -0
  27. package/dist/templates/_shared/lib/base/__pycache__/__init__.cpython-313.pyc +0 -0
  28. package/dist/templates/_shared/lib/base/__pycache__/constants.cpython-313.pyc +0 -0
  29. package/dist/templates/_shared/lib/base/__pycache__/hook_utils.cpython-313.pyc +0 -0
  30. package/dist/templates/_shared/lib/base/__pycache__/inference.cpython-313.pyc +0 -0
  31. package/dist/templates/_shared/lib/base/__pycache__/logger.cpython-313.pyc +0 -0
  32. package/dist/templates/_shared/lib/base/__pycache__/utils.cpython-313.pyc +0 -0
  33. package/dist/templates/_shared/lib/base/constants.py +18 -4
  34. package/dist/templates/_shared/lib/base/hook_utils.py +199 -11
  35. package/dist/templates/_shared/lib/base/inference.py +121 -0
  36. package/dist/templates/_shared/lib/base/logger.py +291 -0
  37. package/dist/templates/_shared/lib/base/utils.py +49 -11
  38. package/dist/templates/_shared/lib/context/__init__.py +72 -80
  39. package/dist/templates/_shared/lib/context/__pycache__/__init__.cpython-313.pyc +0 -0
  40. package/dist/templates/_shared/lib/context/__pycache__/context_formatter.cpython-313.pyc +0 -0
  41. package/dist/templates/_shared/lib/context/__pycache__/context_manager.cpython-313.pyc +0 -0
  42. package/dist/templates/_shared/lib/context/__pycache__/context_selector.cpython-313.pyc +0 -0
  43. package/dist/templates/_shared/lib/context/__pycache__/context_store.cpython-313.pyc +0 -0
  44. package/dist/templates/_shared/lib/context/__pycache__/discovery.cpython-313.pyc +0 -0
  45. package/dist/templates/_shared/lib/context/__pycache__/plan_manager.cpython-313.pyc +0 -0
  46. package/dist/templates/_shared/lib/context/__pycache__/task_tracker.cpython-313.pyc +0 -0
  47. package/dist/templates/_shared/lib/context/context_formatter.py +316 -0
  48. package/dist/templates/_shared/lib/context/context_selector.py +491 -0
  49. package/dist/templates/_shared/lib/context/context_store.py +636 -0
  50. package/dist/templates/_shared/lib/context/plan_manager.py +204 -0
  51. package/dist/templates/_shared/lib/context/task_tracker.py +188 -0
  52. package/dist/templates/_shared/lib/handoff/__pycache__/__init__.cpython-313.pyc +0 -0
  53. package/dist/templates/_shared/lib/handoff/__pycache__/document_generator.cpython-313.pyc +0 -0
  54. package/dist/templates/_shared/lib/handoff/document_generator.py +14 -40
  55. package/dist/templates/_shared/lib/templates/README.md +5 -13
  56. package/dist/templates/_shared/lib/templates/__init__.py +2 -6
  57. package/dist/templates/_shared/lib/templates/__pycache__/__init__.cpython-313.pyc +0 -0
  58. package/dist/templates/_shared/lib/templates/__pycache__/formatters.cpython-313.pyc +0 -0
  59. package/dist/templates/_shared/lib/templates/__pycache__/plan_context.cpython-313.pyc +0 -0
  60. package/dist/templates/_shared/lib/templates/plan_context.py +25 -79
  61. package/dist/templates/_shared/scripts/__pycache__/save_handoff.cpython-313.pyc +0 -0
  62. package/dist/templates/_shared/scripts/__pycache__/status_line.cpython-313.pyc +0 -0
  63. package/dist/templates/_shared/scripts/save_handoff.py +39 -19
  64. package/dist/templates/_shared/scripts/status_line.py +701 -0
  65. package/dist/templates/_shared/workflows/handoff.md +9 -3
  66. package/dist/templates/cc-native/.claude/settings.json +64 -9
  67. package/dist/templates/cc-native/CC-NATIVE-README.md +25 -28
  68. package/dist/templates/cc-native/MIGRATION.md +1 -1
  69. package/dist/templates/cc-native/TEMPLATE-SCHEMA.md +14 -39
  70. package/dist/templates/cc-native/_cc-native/agents/CLAUDE.md +1 -1
  71. package/dist/templates/cc-native/_cc-native/hooks/CLAUDE.md +57 -22
  72. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/add_plan_context.cpython-313.pyc +0 -0
  73. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/cc-native-plan-review.cpython-313.pyc +0 -0
  74. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/mark_questions_asked.cpython-313.pyc +0 -0
  75. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/plan_accepted.cpython-313.pyc +0 -0
  76. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/plan_questions_early.cpython-313.pyc +0 -0
  77. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/suggest-fresh-perspective.cpython-313.pyc +0 -0
  78. package/dist/templates/cc-native/_cc-native/hooks/add_plan_context.py +57 -57
  79. package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.py +208 -158
  80. package/dist/templates/cc-native/_cc-native/hooks/plan_accepted.py +127 -0
  81. package/dist/templates/cc-native/_cc-native/hooks/plan_questions_early.py +81 -0
  82. package/dist/templates/cc-native/_cc-native/hooks/suggest-fresh-perspective.py +26 -25
  83. package/dist/templates/cc-native/_cc-native/lib/CLAUDE.md +35 -10
  84. package/dist/templates/cc-native/_cc-native/lib/__pycache__/__init__.cpython-313.pyc +0 -0
  85. package/dist/templates/cc-native/_cc-native/lib/__pycache__/constants.cpython-313.pyc +0 -0
  86. package/dist/templates/cc-native/_cc-native/lib/__pycache__/debug.cpython-313.pyc +0 -0
  87. package/dist/templates/cc-native/_cc-native/lib/__pycache__/orchestrator.cpython-313.pyc +0 -0
  88. package/dist/templates/cc-native/_cc-native/lib/__pycache__/state.cpython-313.pyc +0 -0
  89. package/dist/templates/cc-native/_cc-native/lib/__pycache__/utils.cpython-313.pyc +0 -0
  90. package/dist/templates/cc-native/_cc-native/lib/debug.py +37 -22
  91. package/dist/templates/cc-native/_cc-native/lib/orchestrator.py +103 -42
  92. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/__init__.cpython-313.pyc +0 -0
  93. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/agent.cpython-313.pyc +0 -0
  94. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/base.cpython-313.pyc +0 -0
  95. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/codex.cpython-313.pyc +0 -0
  96. package/dist/templates/cc-native/_cc-native/lib/reviewers/__pycache__/gemini.cpython-313.pyc +0 -0
  97. package/dist/templates/cc-native/_cc-native/lib/reviewers/agent.py +26 -21
  98. package/dist/templates/cc-native/_cc-native/lib/reviewers/codex.py +12 -7
  99. package/dist/templates/cc-native/_cc-native/lib/reviewers/gemini.py +12 -7
  100. package/dist/templates/cc-native/_cc-native/lib/state.py +31 -16
  101. package/dist/templates/cc-native/_cc-native/lib/utils.py +210 -43
  102. package/dist/templates/cc-native/_cc-native/plan-review.config.json +1 -2
  103. package/oclif.manifest.json +1 -1
  104. package/package.json +1 -1
  105. package/dist/templates/_shared/hooks/context_enforcer.py +0 -625
  106. package/dist/templates/_shared/hooks/task_create_atomicity.py +0 -205
  107. package/dist/templates/_shared/lib/context/cache.py +0 -444
  108. package/dist/templates/_shared/lib/context/context_extractor.py +0 -115
  109. package/dist/templates/_shared/lib/context/context_manager.py +0 -1054
  110. package/dist/templates/_shared/lib/context/discovery.py +0 -444
  111. package/dist/templates/_shared/lib/context/event_log.py +0 -308
  112. package/dist/templates/_shared/lib/context/plan_archive.py +0 -101
  113. package/dist/templates/_shared/lib/context/task_sync.py +0 -290
  114. package/dist/templates/_shared/lib/templates/persona_questions.py +0 -113
  115. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/archive_plan.cpython-313.pyc +0 -0
  116. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/cc-native-agent-review.cpython-313.pyc +0 -0
  117. package/dist/templates/cc-native/_cc-native/hooks/__pycache__/test_permission_request.cpython-313.pyc +0 -0
  118. package/dist/templates/cc-native/_cc-native/lib/async_archive.py +0 -68
  119. package/dist/templates/cc-native/_cc-native/lib/atomic_write.py +0 -98
@@ -1,113 +0,0 @@
1
- """Persona-based question templates for plan clarification.
2
-
3
- Uses distinct reasoning lenses to surface hidden constraints and assumptions.
4
- """
5
-
6
- from dataclasses import dataclass
7
- from typing import List, Dict
8
-
9
-
10
- @dataclass
11
- class PersonaQuestion:
12
- """A clarifying question from a specific persona lens."""
13
-
14
- persona: str
15
- display_name: str
16
- question: str
17
- purpose: str
18
-
19
-
20
- CLARIFICATION_PERSONAS: Dict[str, List[PersonaQuestion]] = {
21
- "problem_validator": [
22
- PersonaQuestion(
23
- persona="problem_validator",
24
- display_name="Questioning the Problem",
25
- question="Can you describe the problem you're trying to solve without mentioning the solution?",
26
- purpose="Separates problem from solution to check alignment",
27
- ),
28
- PersonaQuestion(
29
- persona="problem_validator",
30
- display_name="Challenging the Approach",
31
- question="What's the simplest possible way to achieve this outcome that we haven't considered?",
32
- purpose="Identifies potential over-engineering",
33
- ),
34
- ],
35
- "assumption_validator": [
36
- PersonaQuestion(
37
- persona="assumption_validator",
38
- display_name="Surfacing Assumptions",
39
- question="What must already be true about your users, systems, or constraints for this to succeed?",
40
- purpose="Surfaces foundational assumptions that could invalidate the plan",
41
- ),
42
- PersonaQuestion(
43
- persona="assumption_validator",
44
- display_name="Hidden Dependencies",
45
- question="What are you assuming 'everyone knows' about this problem that might not be documented?",
46
- purpose="Uncovers implicit knowledge that needs to be made explicit",
47
- ),
48
- ],
49
- "user_advocate": [
50
- PersonaQuestion(
51
- persona="user_advocate",
52
- display_name="Understanding Users",
53
- question="Who specifically will use this, and what problem does it solve for them today?",
54
- purpose="Grounds the plan in actual user needs",
55
- ),
56
- PersonaQuestion(
57
- persona="user_advocate",
58
- display_name="Impact Assessment",
59
- question="If we did nothing, what would happen? Who would be affected?",
60
- purpose="Establishes urgency and stakes",
61
- ),
62
- ],
63
- "tradeoff_illuminator": [
64
- PersonaQuestion(
65
- persona="tradeoff_illuminator",
66
- display_name="Revealing Trade-offs",
67
- question="What are you willing to sacrifice (scope, time, quality, features) to make this work?",
68
- purpose="Forces explicit prioritization",
69
- ),
70
- PersonaQuestion(
71
- persona="tradeoff_illuminator",
72
- display_name="Foreclosed Options",
73
- question="What becomes harder or impossible to do later if we proceed this way?",
74
- purpose="Surfaces opportunity costs and lock-in risks",
75
- ),
76
- ],
77
- }
78
-
79
-
80
- def get_all_persona_questions() -> List[PersonaQuestion]:
81
- """Get all persona questions as a flat list."""
82
- questions = []
83
- for persona_qs in CLARIFICATION_PERSONAS.values():
84
- questions.extend(persona_qs)
85
- return questions
86
-
87
-
88
- def format_questions_for_prompt() -> str:
89
- """Format persona questions for injection into Claude prompt."""
90
- lines = [
91
- "### Persona-Based Clarifying Questions",
92
- "",
93
- "Ask 5-8 questions from these perspectives using AskUserQuestion:",
94
- "",
95
- ]
96
-
97
- for persona_qs in CLARIFICATION_PERSONAS.values():
98
- for q in persona_qs:
99
- lines.append(f"**{q.display_name}**")
100
- lines.append(f'- Q: "{q.question}"')
101
- lines.append(f"- Purpose: {q.purpose}")
102
- lines.append("")
103
-
104
- lines.extend(
105
- [
106
- "**Guidance:**",
107
- "- Select questions most relevant to THIS plan (skip if already answered)",
108
- "- Ask one at a time with clear context",
109
- "- Use answers to refine the plan before ExitPlanMode",
110
- ]
111
- )
112
-
113
- return "\n".join(lines)
@@ -1,68 +0,0 @@
1
- """Async background archival to avoid blocking user workflow."""
2
- import threading
3
- import json
4
- from pathlib import Path
5
- from typing import Dict, Any, Callable, Optional
6
- try:
7
- from .atomic_write import atomic_write
8
- from .constants import ENABLE_ROBUST_PLAN_WRITES
9
- except ImportError:
10
- # When imported directly via sys.path (not as a package)
11
- from atomic_write import atomic_write
12
- from constants import ENABLE_ROBUST_PLAN_WRITES
13
-
14
- def archive_plan_async(
15
- out_path: Path,
16
- header: str,
17
- plan: str,
18
- callback: Optional[Callable] = None
19
- ) -> None:
20
- """
21
- Archive plan in background thread. Non-blocking.
22
-
23
- Args:
24
- out_path: Destination file path
25
- header: Plan header with metadata
26
- plan: Plan content
27
- callback: Optional callback(success: bool, error: str) on completion
28
- """
29
- if not ENABLE_ROBUST_PLAN_WRITES:
30
- # Legacy behavior - write directly
31
- try:
32
- out_path.write_text(header + plan + "\n", encoding="utf-8")
33
- if callback:
34
- callback(True, None)
35
- except Exception as e:
36
- if callback:
37
- callback(False, str(e))
38
- return
39
-
40
- def _archive_worker():
41
- success, error = atomic_write(out_path, header + plan + "\n")
42
-
43
- if not success:
44
- # Write sanitized error marker (no stack traces)
45
- error_marker = out_path.with_suffix('.error')
46
- error_content = f"Archive failed: {error}\n"
47
-
48
- try:
49
- # Use atomic write for error marker too
50
- atomic_write(
51
- error_marker,
52
- error_content,
53
- max_attempts=1 # Don't retry error marker
54
- )
55
- except Exception:
56
- pass # Error marker is best-effort
57
-
58
- if callback:
59
- try:
60
- callback(success, error)
61
- except Exception as e:
62
- # Log callback failures (daemon thread would otherwise swallow)
63
- import sys
64
- print(f"[async_archive] Callback failed: {e}", file=sys.stderr)
65
-
66
- # Start background thread
67
- thread = threading.Thread(target=_archive_worker, daemon=False)
68
- thread.start()
@@ -1,98 +0,0 @@
1
- """Cross-platform atomic file writes with security."""
2
- import os
3
- import sys
4
- import tempfile
5
- from pathlib import Path
6
- from typing import Optional
7
-
8
- if sys.platform == 'win32':
9
- import ctypes
10
- from ctypes import wintypes
11
-
12
- # Windows MoveFileEx flags
13
- MOVEFILE_REPLACE_EXISTING = 0x1
14
- MOVEFILE_WRITE_THROUGH = 0x8
15
-
16
- def _atomic_replace_windows(src: Path, dst: Path) -> None:
17
- """Atomic file replacement on Windows using MoveFileEx."""
18
- kernel32 = ctypes.windll.kernel32
19
-
20
- # Set proper function prototypes for 64-bit safety
21
- kernel32.MoveFileExW.argtypes = [wintypes.LPCWSTR, wintypes.LPCWSTR, wintypes.DWORD]
22
- kernel32.MoveFileExW.restype = wintypes.BOOL
23
-
24
- result = kernel32.MoveFileExW(
25
- str(src),
26
- str(dst),
27
- MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH
28
- )
29
- if not result:
30
- error_code = kernel32.GetLastError()
31
- # Use ctypes.WinError for human-readable error messages
32
- raise ctypes.WinError(error_code)
33
-
34
- def atomic_write(
35
- path: Path,
36
- content: str,
37
- max_attempts: int = 2,
38
- backoff_ms: list = None
39
- ) -> tuple:
40
- """
41
- Write file atomically with retry logic.
42
-
43
- Returns:
44
- (success: bool, error_message: Optional[str])
45
- """
46
- import time
47
-
48
- if backoff_ms is None:
49
- backoff_ms = [500, 1000]
50
-
51
- for attempt in range(max_attempts):
52
- try:
53
- # Create temp file in same directory for atomic rename
54
- temp_fd, temp_path_str = tempfile.mkstemp(
55
- dir=path.parent,
56
- prefix=f".{path.stem}_",
57
- suffix=".tmp"
58
- )
59
- temp_path = Path(temp_path_str)
60
-
61
- try:
62
- # Write content to temp file
63
- with os.fdopen(temp_fd, 'w', encoding='utf-8') as f:
64
- f.write(content)
65
- f.flush()
66
- os.fsync(f.fileno()) # Force write to disk
67
-
68
- # Set restrictive permissions before rename (chmod 600)
69
- os.chmod(temp_path, 0o600)
70
-
71
- # Platform-specific atomic rename
72
- if sys.platform == 'win32':
73
- _atomic_replace_windows(temp_path, path)
74
- else:
75
- temp_path.replace(path) # POSIX atomic
76
-
77
- return (True, None)
78
-
79
- except Exception as e:
80
- # Clean up temp file on failure
81
- try:
82
- temp_path.unlink()
83
- except Exception:
84
- pass # Cleanup is best-effort
85
- raise
86
-
87
- except Exception as e:
88
- if attempt < max_attempts - 1:
89
- # Bounds-safe backoff indexing
90
- wait_ms = backoff_ms[min(attempt, len(backoff_ms) - 1)]
91
- time.sleep(wait_ms / 1000.0)
92
- else:
93
- # Sanitize error message (no paths, no stack trace)
94
- error_type = type(e).__name__
95
- error_msg = str(e).split('\n')[0][:200] # First line only, max 200 chars
96
- return (False, f"{error_type}: {error_msg}")
97
-
98
- return (False, "Max retry attempts exceeded")