aiwcli 0.9.2 → 0.9.5
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/dist/templates/_shared/hooks/__pycache__/archive_plan.cpython-313.pyc +0 -0
- package/dist/templates/_shared/hooks/__pycache__/context_enforcer.cpython-313.pyc +0 -0
- package/dist/templates/_shared/hooks/__pycache__/context_monitor.cpython-313.pyc +0 -0
- package/dist/templates/_shared/hooks/__pycache__/file-suggestion.cpython-313.pyc +0 -0
- package/dist/templates/_shared/hooks/__pycache__/session_start.cpython-313.pyc +0 -0
- package/dist/templates/_shared/hooks/__pycache__/task_create_atomicity.cpython-313.pyc +0 -0
- package/dist/templates/_shared/hooks/__pycache__/task_create_capture.cpython-313.pyc +0 -0
- package/dist/templates/_shared/hooks/__pycache__/task_update_capture.cpython-313.pyc +0 -0
- package/dist/templates/_shared/hooks/__pycache__/user_prompt_submit.cpython-313.pyc +0 -0
- package/dist/templates/_shared/hooks/archive_plan.py +28 -38
- package/dist/templates/_shared/hooks/context_enforcer.py +6 -6
- package/dist/templates/_shared/hooks/context_monitor.py +4 -8
- package/dist/templates/_shared/hooks/file-suggestion.py +4 -10
- package/dist/templates/_shared/hooks/session_start.py +4 -9
- package/dist/templates/_shared/hooks/task_create_atomicity.py +90 -84
- package/dist/templates/_shared/hooks/task_create_capture.py +83 -146
- package/dist/templates/_shared/hooks/task_update_capture.py +116 -167
- package/dist/templates/_shared/hooks/user_prompt_submit.py +4 -9
- package/dist/templates/_shared/lib/__pycache__/__init__.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/base/__pycache__/__init__.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/base/__pycache__/atomic_write.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/base/__pycache__/constants.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/base/__pycache__/hook_utils.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/base/__pycache__/utils.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/base/hook_utils.py +169 -0
- package/dist/templates/_shared/lib/context/__init__.py +9 -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_extractor.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__/discovery.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/context/__pycache__/plan_archive.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/context/context_extractor.py +115 -0
- package/dist/templates/_shared/lib/context/discovery.py +4 -4
- package/dist/templates/_shared/lib/templates/__pycache__/__init__.cpython-313.pyc +0 -0
- package/dist/templates/_shared/lib/templates/__pycache__/formatters.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/.claude/agents/cc-native/ARCHITECT-REVIEWER.md +20 -47
- package/dist/templates/cc-native/.claude/agents/cc-native/ASSUMPTION-CHAIN-TRACER.md +25 -203
- package/dist/templates/cc-native/.claude/agents/cc-native/CLARITY-AUDITOR.md +24 -75
- package/dist/templates/cc-native/.claude/agents/cc-native/COMPLETENESS-CHECKER.md +31 -76
- package/dist/templates/cc-native/.claude/agents/cc-native/DEVILS-ADVOCATE.md +25 -188
- package/dist/templates/cc-native/.claude/agents/cc-native/DOCUMENTATION-REVIEWER.md +30 -52
- package/dist/templates/cc-native/.claude/agents/cc-native/FEASIBILITY-ANALYST.md +26 -62
- package/dist/templates/cc-native/.claude/agents/cc-native/FRESH-PERSPECTIVE.md +31 -80
- package/dist/templates/cc-native/.claude/agents/cc-native/HANDOFF-READINESS.md +24 -105
- package/dist/templates/cc-native/.claude/agents/cc-native/HIDDEN-COMPLEXITY-DETECTOR.md +23 -208
- package/dist/templates/cc-native/.claude/agents/cc-native/INCENTIVE-MAPPER.md +25 -199
- package/dist/templates/cc-native/.claude/agents/cc-native/PRECEDENT-FINDER.md +35 -205
- package/dist/templates/cc-native/.claude/agents/cc-native/REVERSIBILITY-ANALYST.md +26 -176
- package/dist/templates/cc-native/.claude/agents/cc-native/RISK-ASSESSOR.md +22 -65
- package/dist/templates/cc-native/.claude/agents/cc-native/SECOND-ORDER-ANALYST.md +25 -161
- package/dist/templates/cc-native/.claude/agents/cc-native/SIMPLICITY-GUARDIAN.md +28 -58
- package/dist/templates/cc-native/.claude/agents/cc-native/SKEPTIC.md +27 -311
- package/dist/templates/cc-native/.claude/agents/cc-native/STAKEHOLDER-ADVOCATE.md +22 -73
- 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__/cc-native-plan-review.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/hooks/__pycache__/suggest-fresh-perspective.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.py +17 -3
- package/dist/templates/cc-native/_cc-native/lib/__pycache__/debug.cpython-313.pyc +0 -0
- package/dist/templates/cc-native/_cc-native/lib/debug.py +124 -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/agent.py +33 -1
- package/dist/templates/cc-native/_cc-native/plan-review.config.json +1 -1
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"""Common utilities for hook scripts.
|
|
2
|
+
|
|
3
|
+
Provides standardized boilerplate for:
|
|
4
|
+
- Path setup for imports
|
|
5
|
+
- JSON parsing from stdin
|
|
6
|
+
- Hook payload validation
|
|
7
|
+
- Error handling decorators
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
import sys
|
|
12
|
+
from functools import wraps
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Any, Callable, Dict, Optional, TypeVar
|
|
15
|
+
|
|
16
|
+
from .utils import eprint
|
|
17
|
+
|
|
18
|
+
# Type variable for generic decorators
|
|
19
|
+
F = TypeVar('F', bound=Callable[..., Any])
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def setup_hook_paths() -> Path:
|
|
23
|
+
"""
|
|
24
|
+
Setup import paths for hooks.
|
|
25
|
+
|
|
26
|
+
Call this at module level in hook scripts to ensure
|
|
27
|
+
the shared lib directory is in sys.path.
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
Path to the lib directory
|
|
31
|
+
|
|
32
|
+
Example:
|
|
33
|
+
SCRIPT_DIR = Path(__file__).resolve().parent
|
|
34
|
+
SHARED_LIB = SCRIPT_DIR.parent / "lib"
|
|
35
|
+
sys.path.insert(0, str(SHARED_LIB.parent))
|
|
36
|
+
"""
|
|
37
|
+
# This function exists mainly for documentation
|
|
38
|
+
# Actual path setup must happen at module level before imports
|
|
39
|
+
hook_dir = Path(__file__).resolve().parent.parent.parent / "hooks"
|
|
40
|
+
lib_dir = hook_dir.parent / "lib"
|
|
41
|
+
if str(lib_dir.parent) not in sys.path:
|
|
42
|
+
sys.path.insert(0, str(lib_dir.parent))
|
|
43
|
+
return lib_dir
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def load_hook_input() -> Optional[Dict[str, Any]]:
|
|
47
|
+
"""
|
|
48
|
+
Load and parse JSON from stdin.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
Parsed JSON dict, or None if stdin is empty or invalid JSON
|
|
52
|
+
"""
|
|
53
|
+
try:
|
|
54
|
+
input_data = sys.stdin.read().strip()
|
|
55
|
+
if not input_data:
|
|
56
|
+
return None
|
|
57
|
+
return json.loads(input_data)
|
|
58
|
+
except json.JSONDecodeError:
|
|
59
|
+
return None
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def validate_hook_event(
|
|
63
|
+
payload: Dict[str, Any],
|
|
64
|
+
expected_event: str,
|
|
65
|
+
expected_tool: Optional[str] = None
|
|
66
|
+
) -> bool:
|
|
67
|
+
"""
|
|
68
|
+
Validate hook event type and optional tool name.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
payload: Hook payload from stdin
|
|
72
|
+
expected_event: Expected hook_event_name (e.g., "PostToolUse", "PreToolUse")
|
|
73
|
+
expected_tool: Optional expected tool_name (e.g., "TaskCreate")
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
True if payload matches expected event/tool, False otherwise
|
|
77
|
+
"""
|
|
78
|
+
if payload.get("hook_event_name") != expected_event:
|
|
79
|
+
return False
|
|
80
|
+
if expected_tool and payload.get("tool_name") != expected_tool:
|
|
81
|
+
return False
|
|
82
|
+
return True
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def get_tool_input(payload: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
86
|
+
"""
|
|
87
|
+
Extract and validate tool_input from payload.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
payload: Hook payload from stdin
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
tool_input dict, or None if missing/invalid
|
|
94
|
+
"""
|
|
95
|
+
tool_input = payload.get("tool_input", {})
|
|
96
|
+
return tool_input if isinstance(tool_input, dict) else None
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def check_skip_persistence(payload: Dict[str, Any], hook_name: str = "hook") -> bool:
|
|
100
|
+
"""
|
|
101
|
+
Check if persistence should be skipped based on metadata flags.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
payload: Hook payload from stdin
|
|
105
|
+
hook_name: Name of hook for logging
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
True if skip_persistence flag is set, False otherwise
|
|
109
|
+
"""
|
|
110
|
+
tool_input = get_tool_input(payload)
|
|
111
|
+
if not tool_input:
|
|
112
|
+
return False
|
|
113
|
+
|
|
114
|
+
metadata = tool_input.get("metadata", {})
|
|
115
|
+
if isinstance(metadata, dict) and metadata.get("skip_persistence"):
|
|
116
|
+
eprint(f"[{hook_name}] Skipping persistence (skip_persistence flag set)")
|
|
117
|
+
return True
|
|
118
|
+
return False
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def safe_hook_main(hook_name: str) -> Callable[[F], F]:
|
|
122
|
+
"""
|
|
123
|
+
Decorator for hook main functions with standard error handling.
|
|
124
|
+
|
|
125
|
+
Catches exceptions, logs them to stderr, and returns 0 (non-blocking).
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
hook_name: Name of hook for error messages
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
Decorator function
|
|
132
|
+
|
|
133
|
+
Example:
|
|
134
|
+
@safe_hook_main("my_hook")
|
|
135
|
+
def main() -> int:
|
|
136
|
+
# ... hook logic ...
|
|
137
|
+
return 0
|
|
138
|
+
"""
|
|
139
|
+
def decorator(func: F) -> F:
|
|
140
|
+
@wraps(func)
|
|
141
|
+
def wrapper(*args, **kwargs):
|
|
142
|
+
try:
|
|
143
|
+
return func(*args, **kwargs)
|
|
144
|
+
except json.JSONDecodeError as e:
|
|
145
|
+
eprint(f"[{hook_name}] JSON decode error: {e}")
|
|
146
|
+
return 0
|
|
147
|
+
except Exception as e:
|
|
148
|
+
eprint(f"[{hook_name}] Unexpected error: {e}")
|
|
149
|
+
import traceback
|
|
150
|
+
eprint(traceback.format_exc())
|
|
151
|
+
return 0
|
|
152
|
+
return wrapper # type: ignore
|
|
153
|
+
return decorator
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def run_hook(main_func: Callable[[], int]) -> None:
|
|
157
|
+
"""
|
|
158
|
+
Standard hook entry point wrapper.
|
|
159
|
+
|
|
160
|
+
Calls main function and exits with its return code.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
main_func: Hook main function that returns exit code
|
|
164
|
+
|
|
165
|
+
Example:
|
|
166
|
+
if __name__ == "__main__":
|
|
167
|
+
run_hook(main)
|
|
168
|
+
"""
|
|
169
|
+
raise SystemExit(main_func())
|
|
@@ -37,6 +37,7 @@ from .discovery import (
|
|
|
37
37
|
format_implementation_continuation,
|
|
38
38
|
format_context_picker_prompt,
|
|
39
39
|
format_ready_for_new_work,
|
|
40
|
+
format_relative_time,
|
|
40
41
|
)
|
|
41
42
|
from .task_sync import (
|
|
42
43
|
generate_task_summary,
|
|
@@ -54,6 +55,10 @@ from .plan_archive import (
|
|
|
54
55
|
mark_plan_implementation_started,
|
|
55
56
|
mark_plan_completed,
|
|
56
57
|
)
|
|
58
|
+
from .context_extractor import (
|
|
59
|
+
extract_context_id,
|
|
60
|
+
extract_context_id_for_session,
|
|
61
|
+
)
|
|
57
62
|
|
|
58
63
|
__all__ = [
|
|
59
64
|
# Data Classes
|
|
@@ -92,6 +97,7 @@ __all__ = [
|
|
|
92
97
|
"format_implementation_continuation",
|
|
93
98
|
"format_context_picker_prompt",
|
|
94
99
|
"format_ready_for_new_work",
|
|
100
|
+
"format_relative_time",
|
|
95
101
|
# Task Sync
|
|
96
102
|
"generate_task_summary",
|
|
97
103
|
"record_session_start",
|
|
@@ -106,4 +112,7 @@ __all__ = [
|
|
|
106
112
|
"create_context_from_plan",
|
|
107
113
|
"mark_plan_implementation_started",
|
|
108
114
|
"mark_plan_completed",
|
|
115
|
+
# Context Extractor
|
|
116
|
+
"extract_context_id",
|
|
117
|
+
"extract_context_id_for_session",
|
|
109
118
|
]
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""Context ID extraction from hook payloads.
|
|
2
|
+
|
|
3
|
+
Centralizes the logic for determining which context a hook operation
|
|
4
|
+
belongs to, using multiple fallback strategies.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Any, Dict, Optional
|
|
9
|
+
|
|
10
|
+
from .context_manager import get_context_by_session_id, get_all_contexts
|
|
11
|
+
from ..base.utils import eprint
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def extract_context_id(
|
|
15
|
+
tool_input: Dict[str, Any],
|
|
16
|
+
project_root: Path,
|
|
17
|
+
session_id: Optional[str] = None,
|
|
18
|
+
hook_name: str = "hook",
|
|
19
|
+
check_persistent_id: bool = False
|
|
20
|
+
) -> Optional[str]:
|
|
21
|
+
"""
|
|
22
|
+
Extract context ID from tool input with multiple fallback strategies.
|
|
23
|
+
|
|
24
|
+
Order of precedence:
|
|
25
|
+
1. metadata.context field (explicit context specification)
|
|
26
|
+
2. Session ID lookup (session bound to context)
|
|
27
|
+
3. persistent_id parsing (if check_persistent_id=True, for TaskCreate)
|
|
28
|
+
4. Single active context fallback
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
tool_input: Tool input dict from hook payload
|
|
32
|
+
project_root: Project root directory
|
|
33
|
+
session_id: Optional session ID from hook payload
|
|
34
|
+
hook_name: Name of calling hook for log messages
|
|
35
|
+
check_persistent_id: Whether to check persistent_id for context hint
|
|
36
|
+
(used by task_create_capture for ID format parsing)
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
Context ID string, or None if context cannot be determined
|
|
40
|
+
"""
|
|
41
|
+
# 1. Check metadata.context field (explicit)
|
|
42
|
+
metadata = tool_input.get("metadata", {})
|
|
43
|
+
if isinstance(metadata, dict):
|
|
44
|
+
context = metadata.get("context")
|
|
45
|
+
if context:
|
|
46
|
+
return context
|
|
47
|
+
|
|
48
|
+
# 2. Check session ID (session may be bound to a context)
|
|
49
|
+
if session_id:
|
|
50
|
+
try:
|
|
51
|
+
session_context = get_context_by_session_id(session_id, project_root)
|
|
52
|
+
if session_context:
|
|
53
|
+
eprint(f"[{hook_name}] Found context via session_id: {session_context.id}")
|
|
54
|
+
return session_context.id
|
|
55
|
+
except Exception as e:
|
|
56
|
+
eprint(f"[{hook_name}] Failed to lookup context by session: {e}")
|
|
57
|
+
|
|
58
|
+
# 3. Check persistent_id for context hint (task_create only)
|
|
59
|
+
# Format: "context-id-task-N" or similar
|
|
60
|
+
if check_persistent_id and isinstance(metadata, dict):
|
|
61
|
+
persistent_id = metadata.get("persistent_id", "")
|
|
62
|
+
if persistent_id and "-" in persistent_id:
|
|
63
|
+
parts = persistent_id.split("-")
|
|
64
|
+
if len(parts) >= 2:
|
|
65
|
+
# Reconstruct context ID (everything before last two parts)
|
|
66
|
+
context_parts = parts[:-2] if len(parts) > 2 else parts[:1]
|
|
67
|
+
potential_id = "-".join(context_parts)
|
|
68
|
+
if potential_id:
|
|
69
|
+
return potential_id
|
|
70
|
+
|
|
71
|
+
# 4. Check for single active context (fallback)
|
|
72
|
+
try:
|
|
73
|
+
contexts = get_all_contexts(status="active", project_root=project_root)
|
|
74
|
+
if len(contexts) == 1:
|
|
75
|
+
return contexts[0].id
|
|
76
|
+
except Exception as e:
|
|
77
|
+
eprint(f"[{hook_name}] Failed to get active contexts: {e}")
|
|
78
|
+
|
|
79
|
+
return None
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def extract_context_id_for_session(
|
|
83
|
+
session_id: str,
|
|
84
|
+
project_root: Path,
|
|
85
|
+
hook_name: str = "hook"
|
|
86
|
+
) -> Optional[str]:
|
|
87
|
+
"""
|
|
88
|
+
Find context that matches this session_id.
|
|
89
|
+
|
|
90
|
+
Simpler variant for hooks that only need session-based lookup.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
session_id: Session ID to match
|
|
94
|
+
project_root: Project root directory
|
|
95
|
+
hook_name: Name of calling hook for log messages
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
Context ID or None if not found
|
|
99
|
+
"""
|
|
100
|
+
contexts = get_all_contexts(status="active", project_root=project_root)
|
|
101
|
+
|
|
102
|
+
# Primary strategy: Find context with matching session_id
|
|
103
|
+
for ctx in contexts:
|
|
104
|
+
if ctx.in_flight and ctx.in_flight.session_ids and session_id in ctx.in_flight.session_ids:
|
|
105
|
+
eprint(f"[{hook_name}] Found context by session: {ctx.id}")
|
|
106
|
+
return ctx.id
|
|
107
|
+
|
|
108
|
+
# Fallback: If only one context is planning, assume it's the one
|
|
109
|
+
planning_contexts = [c for c in contexts if c.in_flight and c.in_flight.mode == "planning"]
|
|
110
|
+
if len(planning_contexts) == 1:
|
|
111
|
+
eprint(f"[{hook_name}] Fallback: Single planning context: {planning_contexts[0].id}")
|
|
112
|
+
return planning_contexts[0].id
|
|
113
|
+
|
|
114
|
+
eprint(f"[{hook_name}] Could not find context for session {session_id}")
|
|
115
|
+
return None
|
|
@@ -105,7 +105,7 @@ def format_context_list(contexts: List[Context]) -> str:
|
|
|
105
105
|
|
|
106
106
|
for i, ctx in enumerate(contexts, 1):
|
|
107
107
|
# Format last active time
|
|
108
|
-
time_str =
|
|
108
|
+
time_str = format_relative_time(ctx.last_active)
|
|
109
109
|
|
|
110
110
|
# Build status indicator
|
|
111
111
|
status_indicator = ""
|
|
@@ -314,7 +314,7 @@ def format_context_selection_required(contexts: List[Context]) -> str:
|
|
|
314
314
|
]
|
|
315
315
|
|
|
316
316
|
for i, ctx in enumerate(contexts, 1):
|
|
317
|
-
time_str =
|
|
317
|
+
time_str = format_relative_time(ctx.last_active)
|
|
318
318
|
|
|
319
319
|
# Add status indicator for in-flight work
|
|
320
320
|
status = ""
|
|
@@ -345,7 +345,7 @@ def format_active_context_reminder(context: Context) -> str:
|
|
|
345
345
|
Returns:
|
|
346
346
|
Formatted system reminder
|
|
347
347
|
"""
|
|
348
|
-
time_str =
|
|
348
|
+
time_str = format_relative_time(context.last_active)
|
|
349
349
|
|
|
350
350
|
# Build mode display
|
|
351
351
|
mode_display = "Active"
|
|
@@ -392,7 +392,7 @@ def format_context_created(context: Context) -> str:
|
|
|
392
392
|
return "\n".join(lines)
|
|
393
393
|
|
|
394
394
|
|
|
395
|
-
def
|
|
395
|
+
def format_relative_time(iso_timestamp: Optional[str]) -> str:
|
|
396
396
|
"""
|
|
397
397
|
Format ISO timestamp as relative time string.
|
|
398
398
|
|
|
Binary file
|
|
@@ -8,14 +8,13 @@ categories:
|
|
|
8
8
|
- code
|
|
9
9
|
- infrastructure
|
|
10
10
|
- design
|
|
11
|
-
tools: Read, Write, Edit, Bash, Glob, Grep
|
|
12
11
|
---
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
# Architect Reviewer - Plan Review Agent
|
|
15
14
|
|
|
16
|
-
Senior architecture reviewer
|
|
15
|
+
Senior architecture reviewer evaluating system designs, architectural decisions, and technology choices.
|
|
17
16
|
|
|
18
|
-
##
|
|
17
|
+
## Your Expertise
|
|
19
18
|
|
|
20
19
|
### 1. Design Patterns & Structure
|
|
21
20
|
Component boundaries, service contracts, dependency management, coupling/cohesion balance, appropriate pattern selection (microservices, event-driven, layered), and domain-driven design alignment.
|
|
@@ -26,50 +25,24 @@ Horizontal/vertical scaling readiness, data partitioning strategy, caching layer
|
|
|
26
25
|
### 3. Technical Debt & Evolution
|
|
27
26
|
Architecture smells, technology obsolescence risks, complexity metrics, maintenance burden assessment, modernization path clarity, and reversibility of decisions.
|
|
28
27
|
|
|
29
|
-
##
|
|
28
|
+
## CRITICAL: Single-Turn Review
|
|
30
29
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
- Issue: Changes to PaymentService internal implementation will break OrderService
|
|
36
|
-
- Fix: Define PaymentGateway interface in shared contracts, inject implementation
|
|
37
|
-
```
|
|
30
|
+
When reviewing a plan, you MUST:
|
|
31
|
+
1. Analyze the plan content provided directly (do NOT use Read, Write, Edit, Bash, Glob, Grep, or any tools)
|
|
32
|
+
2. Call StructuredOutput IMMEDIATELY with your assessment
|
|
33
|
+
3. Complete your entire review in ONE response
|
|
38
34
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
- Fix: Implement worker pool pattern or use message queue for parallel processing
|
|
45
|
-
```
|
|
35
|
+
Do NOT:
|
|
36
|
+
- Query context managers or external systems
|
|
37
|
+
- Read files from the codebase
|
|
38
|
+
- Request architecture documentation
|
|
39
|
+
- Ask follow-up questions
|
|
46
40
|
|
|
47
|
-
##
|
|
41
|
+
## Required Output
|
|
48
42
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
3
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
Request architecture context when starting:
|
|
57
|
-
```json
|
|
58
|
-
{
|
|
59
|
-
"requesting_agent": "architect-reviewer",
|
|
60
|
-
"request_type": "get_architecture_context",
|
|
61
|
-
"payload": {
|
|
62
|
-
"query": "Architecture context needed: system purpose, scale requirements, constraints, and evolution plans."
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
## Review Completion
|
|
68
|
-
|
|
69
|
-
Report findings structured by impact (architectural → systemic → local) with:
|
|
70
|
-
- Component/service references
|
|
71
|
-
- Clear problem description with trade-off analysis
|
|
72
|
-
- Recommended approach with alternatives considered
|
|
73
|
-
- Migration path if changes required
|
|
74
|
-
|
|
75
|
-
Prioritize long-term sustainability, scalability, and maintainability while providing pragmatic recommendations that balance ideal architecture with practical constraints.
|
|
43
|
+
Call StructuredOutput with exactly these fields:
|
|
44
|
+
- **verdict**: "pass" (architecturally sound), "warn" (some concerns), or "fail" (critical architectural issues)
|
|
45
|
+
- **summary**: 2-3 sentences explaining your architectural assessment (minimum 20 characters)
|
|
46
|
+
- **issues**: Array of architectural concerns, each with: severity (high/medium/low), category (e.g., "coupling", "scalability", "tech-debt"), issue description, suggested_fix
|
|
47
|
+
- **missing_sections**: Architectural considerations the plan should address but doesn't
|
|
48
|
+
- **questions**: Design decisions that need clarification before implementation
|