Skip to content

Commit 2de2a79

Browse files
feat: add architectural impact preview command with specialized python analyzer
1 parent 32205c3 commit 2de2a79

4 files changed

Lines changed: 23 additions & 22 deletions

File tree

scripts/impact_analyzer.py

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,12 @@
66
load_dotenv()
77

88
def setup_client():
9-
"""
10-
Initializes the AI client using standard environment variables.
11-
Defaults to OpenAI, but can be overridden via AI_BASE_URL.
12-
"""
13-
api_key = os.getenv("AI_API_KEY")
14-
base_url = os.getenv("AI_BASE_URL", "https://api.openai.com/v1")
15-
9+
api_key = os.getenv("AI_API_KEY") or os.getenv("ANTHROPIC_API_KEY") or os.getenv("OPENAI_API_KEY")
10+
base_url = os.getenv("AI_BASE_URL")
1611
if not api_key:
17-
raise ValueError("CRITICAL ERROR: AI_API_KEY environment variable is not set.")
18-
19-
return OpenAI(api_key=api_key, base_url=base_url)
12+
raise ValueError("AI API Key not found. Please set AI_API_KEY or ensure your LLM provider is configured.")
13+
14+
return OpenAI(api_key=api_key, base_url=base_url if base_url else "https://api.openai.com/v1")
2015

2116
def load_project_context(target_dir):
2217
"""
@@ -116,14 +111,19 @@ def render_architect_report(raw_json):
116111
if __name__ == "__main__":
117112
parser = argparse.ArgumentParser(description="Spec-Kit Architectural Impact Previewer")
118113
parser.add_argument("--change", required=True, help="Description of the change request")
119-
parser.add_argument("--model", default=os.getenv("AI_MODEL_ID"), help="Model ID to invoke")
114+
parser.add_argument("--model", default=os.getenv("AI_MODEL_ID", "gpt-4o"), help="Model ID to invoke")
120115

121116
args = parser.parse_args()
122117

123-
# Dynamic path resolution to ensure it works from root
124-
script_dir = os.path.dirname(os.path.abspath(__file__))
125-
default_presets = os.path.abspath(os.path.join(script_dir, "..", "presets", "lean", "commands"))
126-
search_path = os.getenv("SPECKIT_PRESETS_DIR", default_presets)
118+
def get_search_path():
119+
project_specify = os.path.join(os.getcwd(), ".specify", "memory")
120+
if os.path.exists(project_specify):
121+
return project_specify
122+
123+
script_dir = os.path.dirname(os.path.abspath(__file__))
124+
return os.path.abspath(os.path.join(script_dir, "..", "presets", "lean", "commands"))
125+
126+
search_path = os.getenv("SPECKIT_PRESETS_DIR", get_search_path())
127127

128128
try:
129129
ai_client = setup_client()
@@ -132,12 +132,9 @@ def render_architect_report(raw_json):
132132
if not project_context:
133133
print(f"[!] Path Error: No specification files found at {search_path}")
134134
else:
135-
if not args.model:
136-
print("[!] Configuration Error: No Model ID provided via --model or AI_MODEL_ID.")
137-
else:
138-
print(f"[*] Analyzing global impact for: '{args.change[:50]}...'")
139-
raw_report = perform_impact_analysis(ai_client, project_context, args.change, args.model)
140-
render_architect_report(raw_report)
135+
print(f"[*] Analyzing global impact for: '{args.change[:50]}...'")
136+
raw_report = perform_impact_analysis(ai_client, project_context, args.change, args.model)
137+
render_architect_report(raw_report)
141138

142139
except Exception as error:
143140
print(f"[!] Runtime Exception: {error}")

src/specify_cli/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -862,6 +862,7 @@ def _get_skills_dir(project_path: Path, selected_ai: str) -> Path:
862862
"plan": "Generate technical implementation plans from feature specifications.",
863863
"tasks": "Break down implementation plans into actionable task lists.",
864864
"implement": "Execute all tasks from the task breakdown to build the feature.",
865+
"preview": "Predict the architectural impact, complexity, and risks of proposed changes.",
865866
"analyze": "Perform cross-artifact consistency analysis across spec.md, plan.md, and tasks.md.",
866867
"clarify": "Structured clarification workflow for underspecified requirements.",
867868
"constitution": "Create or update project governing principles and development guidelines.",

src/specify_cli/integrations/claude/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"plan": "Optional guidance for the planning phase",
1818
"tasks": "Optional task generation constraints",
1919
"implement": "Optional implementation guidance or task filter",
20+
"preview": "Predict the architectural impact, complexity, and risks of proposed changes.",
2021
"analyze": "Optional focus areas for analysis",
2122
"clarify": "Optional areas to clarify in the spec",
2223
"constitution": "Principles or values for the project constitution",
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
---
22
description: Preview the architectural impact and risks of a proposed change across all specifications.
3+
scripts:
4+
sh: python3 scripts/impact_analyzer.py --change "$ARGUMENTS" --model "${AI_MODEL_ID:-gpt-4o}"
35
---
46

57
## User Input
68

79
```text
8-
$ARGUMENTS (The description of the proposed change)
10+
$ARGUMENTS

0 commit comments

Comments
 (0)