@kennethsolomon/shipkit 1.0.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.
- package/README.md +321 -0
- package/bin/shipkit.js +146 -0
- package/commands/sk/brainstorm.md +63 -0
- package/commands/sk/branch.md +35 -0
- package/commands/sk/config.md +96 -0
- package/commands/sk/execute-plan.md +85 -0
- package/commands/sk/features.md +238 -0
- package/commands/sk/finish-feature.md +154 -0
- package/commands/sk/help.md +103 -0
- package/commands/sk/hotfix.md +61 -0
- package/commands/sk/plan.md +30 -0
- package/commands/sk/release.md +72 -0
- package/commands/sk/security-check.md +188 -0
- package/commands/sk/set-profile.md +71 -0
- package/commands/sk/status.md +25 -0
- package/commands/sk/update-task.md +35 -0
- package/commands/sk/write-plan.md +72 -0
- package/package.json +23 -0
- package/skills/sk:accessibility/LICENSE.txt +177 -0
- package/skills/sk:accessibility/SKILL.md +150 -0
- package/skills/sk:api-design/LICENSE.txt +177 -0
- package/skills/sk:api-design/SKILL.md +158 -0
- package/skills/sk:brainstorming/SKILL.md +124 -0
- package/skills/sk:debug/SKILL.md +252 -0
- package/skills/sk:debug/debug_conductor.py +177 -0
- package/skills/sk:debug/lib/__init__.py +1 -0
- package/skills/sk:debug/lib/bug_gatherer.py +55 -0
- package/skills/sk:debug/lib/context_reader.py +139 -0
- package/skills/sk:debug/lib/findings_writer.py +76 -0
- package/skills/sk:debug/lib/lessons_writer.py +165 -0
- package/skills/sk:debug/lib/step_runner.py +326 -0
- package/skills/sk:features/SKILL.md +238 -0
- package/skills/sk:frontend-design/LICENSE.txt +177 -0
- package/skills/sk:frontend-design/SKILL.md +191 -0
- package/skills/sk:laravel-init/SKILL.md +37 -0
- package/skills/sk:laravel-new/SKILL.md +68 -0
- package/skills/sk:lint/SKILL.md +113 -0
- package/skills/sk:perf/LICENSE.txt +177 -0
- package/skills/sk:perf/SKILL.md +188 -0
- package/skills/sk:release/SKILL.md +113 -0
- package/skills/sk:release/references/android-checklist.md +269 -0
- package/skills/sk:release/references/ios-checklist.md +339 -0
- package/skills/sk:release/release.sh +378 -0
- package/skills/sk:review/SKILL.md +346 -0
- package/skills/sk:review/references/security-checklist.md +223 -0
- package/skills/sk:schema-migrate/SKILL.md +125 -0
- package/skills/sk:schema-migrate/orms/drizzle.md +546 -0
- package/skills/sk:schema-migrate/orms/laravel.md +367 -0
- package/skills/sk:schema-migrate/orms/prisma.md +357 -0
- package/skills/sk:schema-migrate/orms/rails.md +351 -0
- package/skills/sk:schema-migrate/orms/sqlalchemy.md +385 -0
- package/skills/sk:schema-migrate/references/detection.md +110 -0
- package/skills/sk:setup-claude/SKILL.md +365 -0
- package/skills/sk:setup-claude/references/detection.md +6 -0
- package/skills/sk:setup-claude/references/templates.md +11 -0
- package/skills/sk:setup-claude/scripts/apply_setup_claude.py +443 -0
- package/skills/sk:setup-claude/scripts/detect_arch_changes.py +437 -0
- package/skills/sk:setup-claude/templates/.claude/docs/arch-changelog-guide.md.template +6 -0
- package/skills/sk:setup-claude/templates/.claude/docs/changelog-guide.md.template +12 -0
- package/skills/sk:setup-claude/templates/CHANGELOG.md.template +21 -0
- package/skills/sk:setup-claude/templates/CLAUDE.md.template +299 -0
- package/skills/sk:setup-claude/templates/arch-changelog-guide.md.template +3 -0
- package/skills/sk:setup-claude/templates/changelog-guide.md.template +3 -0
- package/skills/sk:setup-claude/templates/commands/brainstorm.md.template +74 -0
- package/skills/sk:setup-claude/templates/commands/execute-plan.md.template +57 -0
- package/skills/sk:setup-claude/templates/commands/features.md.template +238 -0
- package/skills/sk:setup-claude/templates/commands/finish-feature.md.template +155 -0
- package/skills/sk:setup-claude/templates/commands/plan.md.template +30 -0
- package/skills/sk:setup-claude/templates/commands/re-setup.md.template +38 -0
- package/skills/sk:setup-claude/templates/commands/release.md.template +74 -0
- package/skills/sk:setup-claude/templates/commands/security-check.md.template +172 -0
- package/skills/sk:setup-claude/templates/commands/status.md.template +17 -0
- package/skills/sk:setup-claude/templates/commands/write-plan.md.template +34 -0
- package/skills/sk:setup-claude/templates/finish-feature.md.template +3 -0
- package/skills/sk:setup-claude/templates/plan.md.template +3 -0
- package/skills/sk:setup-claude/templates/status.md.template +3 -0
- package/skills/sk:setup-claude/templates/tasks/findings.md.template +19 -0
- package/skills/sk:setup-claude/templates/tasks/lessons.md.template +26 -0
- package/skills/sk:setup-claude/templates/tasks/progress.md.template +20 -0
- package/skills/sk:setup-claude/templates/tasks/security-findings.md.template +5 -0
- package/skills/sk:setup-claude/templates/tasks/todo.md.template +26 -0
- package/skills/sk:setup-claude/templates/tasks/workflow-status.md.template +31 -0
- package/skills/sk:setup-claude/templates/tasks-findings.md.template +3 -0
- package/skills/sk:setup-claude/templates/tasks-lessons.md.template +3 -0
- package/skills/sk:setup-claude/templates/tasks-progress.md.template +3 -0
- package/skills/sk:setup-claude/templates/tasks-todo.md.template +3 -0
- package/skills/sk:setup-claude/tests/test_apply_setup_claude.py +193 -0
- package/skills/sk:setup-optimizer/SKILL.md +184 -0
- package/skills/sk:setup-optimizer/lib/__init__.py +24 -0
- package/skills/sk:setup-optimizer/lib/detect.py +205 -0
- package/skills/sk:setup-optimizer/lib/discover.py +221 -0
- package/skills/sk:setup-optimizer/lib/enrich.py +163 -0
- package/skills/sk:setup-optimizer/lib/merge.py +277 -0
- package/skills/sk:setup-optimizer/lib/sidecar.py +129 -0
- package/skills/sk:setup-optimizer/optimize_claude.py +174 -0
- package/skills/sk:setup-optimizer/templates/CLAUDE.md.template +105 -0
- package/skills/sk:skill-creator/LICENSE.txt +202 -0
- package/skills/sk:skill-creator/SKILL.md +479 -0
- package/skills/sk:skill-creator/agents/analyzer.md +274 -0
- package/skills/sk:skill-creator/agents/comparator.md +202 -0
- package/skills/sk:skill-creator/agents/grader.md +223 -0
- package/skills/sk:skill-creator/assets/eval_review.html +146 -0
- package/skills/sk:skill-creator/eval-viewer/generate_review.py +471 -0
- package/skills/sk:skill-creator/eval-viewer/viewer.html +1325 -0
- package/skills/sk:skill-creator/references/schemas.md +430 -0
- package/skills/sk:skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/skills/sk:skill-creator/scripts/generate_report.py +326 -0
- package/skills/sk:skill-creator/scripts/improve_description.py +248 -0
- package/skills/sk:skill-creator/scripts/package_skill.py +136 -0
- package/skills/sk:skill-creator/scripts/quick_validate.py +103 -0
- package/skills/sk:skill-creator/scripts/run_eval.py +310 -0
- package/skills/sk:skill-creator/scripts/run_loop.py +332 -0
- package/skills/sk:skill-creator/scripts/utils.py +47 -0
- package/skills/sk:smart-commit/SKILL.md +175 -0
- package/skills/sk:test/SKILL.md +171 -0
- package/skills/sk:write-tests/SKILL.md +195 -0
- package/skills/sk:write-tests/references/patterns.md +209 -0
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Detect architectural changes in git diff and generate arch log entry draft.
|
|
4
|
+
|
|
5
|
+
Analyzes git diff main..HEAD to identify:
|
|
6
|
+
- Control flow changes (skill interactions, execution order)
|
|
7
|
+
- Data flow changes (context threading, new files)
|
|
8
|
+
- Pattern changes (new design patterns)
|
|
9
|
+
- Integration changes (new connections between components)
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
python detect_arch_changes.py # Generate and save arch log
|
|
13
|
+
python detect_arch_changes.py --dry-run # Show what would be generated
|
|
14
|
+
python detect_arch_changes.py --output FILE # Save to specific file
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import sys
|
|
18
|
+
import subprocess
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
from datetime import datetime
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def get_git_diff():
|
|
24
|
+
"""Get git diff main..HEAD"""
|
|
25
|
+
result = subprocess.run(
|
|
26
|
+
["git", "diff", "main..HEAD"],
|
|
27
|
+
capture_output=True,
|
|
28
|
+
text=True
|
|
29
|
+
)
|
|
30
|
+
if result.returncode != 0:
|
|
31
|
+
return None
|
|
32
|
+
return result.stdout
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def get_changed_files():
|
|
36
|
+
"""Get list of changed files"""
|
|
37
|
+
result = subprocess.run(
|
|
38
|
+
["git", "diff", "--name-only", "main..HEAD"],
|
|
39
|
+
capture_output=True,
|
|
40
|
+
text=True
|
|
41
|
+
)
|
|
42
|
+
if result.returncode != 0:
|
|
43
|
+
return []
|
|
44
|
+
return [f for f in result.stdout.strip().split("\n") if f]
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def get_commit_message():
|
|
48
|
+
"""Get the commit message(s) from main..HEAD"""
|
|
49
|
+
result = subprocess.run(
|
|
50
|
+
["git", "log", "--oneline", "main..HEAD"],
|
|
51
|
+
capture_output=True,
|
|
52
|
+
text=True
|
|
53
|
+
)
|
|
54
|
+
return result.stdout.strip()
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def analyze_changes(diff, files):
|
|
58
|
+
"""Analyze diff to detect architectural patterns (universal for any project)"""
|
|
59
|
+
|
|
60
|
+
analysis = {
|
|
61
|
+
"has_schema_changes": False,
|
|
62
|
+
"has_component_changes": False,
|
|
63
|
+
"has_api_changes": False,
|
|
64
|
+
"has_config_changes": False,
|
|
65
|
+
"has_subsystem_changes": False,
|
|
66
|
+
"has_dependency_changes": False,
|
|
67
|
+
"has_context_threading": False,
|
|
68
|
+
"has_documentation": False,
|
|
69
|
+
"schema_files": [],
|
|
70
|
+
"component_files": [],
|
|
71
|
+
"api_files": [],
|
|
72
|
+
"config_files": [],
|
|
73
|
+
"new_directories": [],
|
|
74
|
+
"context_reads": 0,
|
|
75
|
+
"context_writes": 0,
|
|
76
|
+
"lines_added": 0,
|
|
77
|
+
"lines_removed": 0,
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
# Count added/removed lines
|
|
81
|
+
for line in diff.split("\n"):
|
|
82
|
+
if line.startswith("+") and not line.startswith("+++"):
|
|
83
|
+
analysis["lines_added"] += 1
|
|
84
|
+
elif line.startswith("-") and not line.startswith("---"):
|
|
85
|
+
analysis["lines_removed"] += 1
|
|
86
|
+
|
|
87
|
+
# Detect SCHEMA/DATABASE changes
|
|
88
|
+
schema_patterns = [
|
|
89
|
+
"schema.prisma",
|
|
90
|
+
"migrations/",
|
|
91
|
+
"alembic/",
|
|
92
|
+
"models/",
|
|
93
|
+
"db/",
|
|
94
|
+
"database/",
|
|
95
|
+
".sql",
|
|
96
|
+
]
|
|
97
|
+
schema_files = [
|
|
98
|
+
f for f in files if any(pattern in f for pattern in schema_patterns)
|
|
99
|
+
]
|
|
100
|
+
if schema_files:
|
|
101
|
+
analysis["has_schema_changes"] = True
|
|
102
|
+
analysis["schema_files"] = schema_files[:5] # Limit to 5
|
|
103
|
+
|
|
104
|
+
# Detect COMPONENT/MODULE structure changes
|
|
105
|
+
component_patterns = [
|
|
106
|
+
"src/components/",
|
|
107
|
+
"src/pages/",
|
|
108
|
+
"components/",
|
|
109
|
+
"pages/",
|
|
110
|
+
"lib/",
|
|
111
|
+
"utils/",
|
|
112
|
+
"hooks/",
|
|
113
|
+
]
|
|
114
|
+
component_files = [
|
|
115
|
+
f for f in files if any(pattern in f for pattern in component_patterns)
|
|
116
|
+
]
|
|
117
|
+
if len(component_files) > 2: # Multiple component changes
|
|
118
|
+
analysis["has_component_changes"] = True
|
|
119
|
+
analysis["component_files"] = component_files[:5]
|
|
120
|
+
|
|
121
|
+
# Detect API/ROUTE structure changes
|
|
122
|
+
api_patterns = [
|
|
123
|
+
"routes/",
|
|
124
|
+
"api/",
|
|
125
|
+
"endpoints/",
|
|
126
|
+
"controllers/",
|
|
127
|
+
"handlers/",
|
|
128
|
+
"middleware/",
|
|
129
|
+
"/api/",
|
|
130
|
+
]
|
|
131
|
+
api_files = [f for f in files if any(pattern in f for pattern in api_patterns)]
|
|
132
|
+
if api_files:
|
|
133
|
+
analysis["has_api_changes"] = True
|
|
134
|
+
analysis["api_files"] = api_files[:5]
|
|
135
|
+
|
|
136
|
+
# Detect CONFIG file changes
|
|
137
|
+
config_patterns = [
|
|
138
|
+
".env",
|
|
139
|
+
"config/",
|
|
140
|
+
"settings/",
|
|
141
|
+
".yaml",
|
|
142
|
+
".yml",
|
|
143
|
+
"tsconfig",
|
|
144
|
+
"eslintrc",
|
|
145
|
+
"pytest.ini",
|
|
146
|
+
"setup.py",
|
|
147
|
+
]
|
|
148
|
+
config_files = [
|
|
149
|
+
f for f in files if any(pattern in f for pattern in config_patterns)
|
|
150
|
+
]
|
|
151
|
+
if config_files:
|
|
152
|
+
analysis["has_config_changes"] = True
|
|
153
|
+
analysis["config_files"] = config_files[:5]
|
|
154
|
+
|
|
155
|
+
# Detect NEW SUBSYSTEMS (new top-level directories)
|
|
156
|
+
new_dirs = set()
|
|
157
|
+
for f in files:
|
|
158
|
+
if "/" in f:
|
|
159
|
+
top_dir = f.split("/")[0]
|
|
160
|
+
if top_dir not in ["src", "tests", "docs", "public", ".github", ".claude"]:
|
|
161
|
+
new_dirs.add(top_dir)
|
|
162
|
+
if len(new_dirs) >= 2: # Multiple new top-level dirs
|
|
163
|
+
analysis["has_subsystem_changes"] = True
|
|
164
|
+
analysis["new_directories"] = sorted(list(new_dirs))[:5]
|
|
165
|
+
|
|
166
|
+
# Detect DEPENDENCY changes
|
|
167
|
+
if any(f in files for f in ["package.json", "requirements.txt", "Gemfile", "Cargo.toml", "go.mod"]):
|
|
168
|
+
analysis["has_dependency_changes"] = True
|
|
169
|
+
|
|
170
|
+
# Detect CONTEXT THREADING (findings.md, lessons.md)
|
|
171
|
+
if "findings.md" in diff or "lessons.md" in diff:
|
|
172
|
+
analysis["has_context_threading"] = True
|
|
173
|
+
analysis["context_reads"] = diff.count("read")
|
|
174
|
+
analysis["context_writes"] = diff.count("write")
|
|
175
|
+
|
|
176
|
+
# Detect DOCUMENTATION changes
|
|
177
|
+
if any(f in files for f in ["README.md", "CLAUDE.md", ".claude/docs/", "docs/"]):
|
|
178
|
+
if analysis["lines_added"] > 50:
|
|
179
|
+
analysis["has_documentation"] = True
|
|
180
|
+
|
|
181
|
+
return analysis
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def infer_topic(analysis, files):
|
|
185
|
+
"""Infer a good topic/filename from analysis"""
|
|
186
|
+
if analysis["has_schema_changes"]:
|
|
187
|
+
return "data-model-refactor"
|
|
188
|
+
elif analysis["has_api_changes"]:
|
|
189
|
+
return "api-structure-enhancement"
|
|
190
|
+
elif analysis["has_component_changes"]:
|
|
191
|
+
return "component-architecture-update"
|
|
192
|
+
elif analysis["has_subsystem_changes"]:
|
|
193
|
+
return "subsystem-refactor"
|
|
194
|
+
elif analysis["has_context_threading"]:
|
|
195
|
+
return "context-threading-enhancement"
|
|
196
|
+
elif analysis["has_config_changes"]:
|
|
197
|
+
return "configuration-restructuring"
|
|
198
|
+
elif analysis["has_dependency_changes"]:
|
|
199
|
+
return "dependency-upgrade"
|
|
200
|
+
else:
|
|
201
|
+
return "architecture-change"
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def generate_arch_log_draft(analysis, files, topic):
|
|
205
|
+
"""Generate markdown content for arch log entry"""
|
|
206
|
+
|
|
207
|
+
today = datetime.now()
|
|
208
|
+
date_str = today.strftime("%Y-%m-%d")
|
|
209
|
+
|
|
210
|
+
# Build summary based on analysis
|
|
211
|
+
summary_parts = []
|
|
212
|
+
if analysis["has_schema_changes"]:
|
|
213
|
+
summary_parts.append("Modified data model/schema")
|
|
214
|
+
if analysis["has_api_changes"]:
|
|
215
|
+
summary_parts.append("Updated API/route structure")
|
|
216
|
+
if analysis["has_component_changes"]:
|
|
217
|
+
summary_parts.append("Refactored component architecture")
|
|
218
|
+
if analysis["has_subsystem_changes"]:
|
|
219
|
+
summary_parts.append("Added/refactored subsystems")
|
|
220
|
+
if analysis["has_config_changes"]:
|
|
221
|
+
summary_parts.append("Modified configuration affecting architecture")
|
|
222
|
+
if analysis["has_context_threading"]:
|
|
223
|
+
summary_parts.append("Enhanced context threading")
|
|
224
|
+
if analysis["has_dependency_changes"]:
|
|
225
|
+
summary_parts.append("Updated dependencies affecting system design")
|
|
226
|
+
if analysis["has_documentation"]:
|
|
227
|
+
summary_parts.append("Documented architectural changes")
|
|
228
|
+
|
|
229
|
+
summary = (
|
|
230
|
+
". ".join(summary_parts) if summary_parts else "Architectural enhancement"
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
# Categorize change type
|
|
234
|
+
change_type = []
|
|
235
|
+
if analysis["has_schema_changes"]:
|
|
236
|
+
change_type.append("Data Flow")
|
|
237
|
+
if analysis["has_api_changes"]:
|
|
238
|
+
change_type.append("Control Flow")
|
|
239
|
+
if analysis["has_component_changes"]:
|
|
240
|
+
change_type.append("Pattern")
|
|
241
|
+
if analysis["has_subsystem_changes"]:
|
|
242
|
+
change_type.append("Subsystem")
|
|
243
|
+
if analysis["has_config_changes"]:
|
|
244
|
+
change_type.append("Configuration")
|
|
245
|
+
if analysis["has_context_threading"]:
|
|
246
|
+
change_type.append("Integration")
|
|
247
|
+
|
|
248
|
+
change_type_str = " + ".join(change_type) if change_type else "Architecture"
|
|
249
|
+
|
|
250
|
+
# Build file listing sections
|
|
251
|
+
sections = []
|
|
252
|
+
|
|
253
|
+
if analysis["schema_files"]:
|
|
254
|
+
sections.append(
|
|
255
|
+
f"\n**Database/Schema Changes ({len(analysis['schema_files'])}):**\n"
|
|
256
|
+
+ "\n".join([f"- `{f}`" for f in analysis["schema_files"]])
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
if analysis["api_files"]:
|
|
260
|
+
sections.append(
|
|
261
|
+
f"\n**API/Route Changes ({len(analysis['api_files'])}):**\n"
|
|
262
|
+
+ "\n".join([f"- `{f}`" for f in analysis["api_files"]])
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
if analysis["component_files"]:
|
|
266
|
+
sections.append(
|
|
267
|
+
f"\n**Component/Module Changes ({len(analysis['component_files'])}):**\n"
|
|
268
|
+
+ "\n".join([f"- `{f}`" for f in analysis["component_files"]])
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
if analysis["config_files"]:
|
|
272
|
+
sections.append(
|
|
273
|
+
f"\n**Configuration Changes ({len(analysis['config_files'])}):**\n"
|
|
274
|
+
+ "\n".join([f"- `{f}`" for f in analysis["config_files"]])
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
if analysis["new_directories"]:
|
|
278
|
+
sections.append(
|
|
279
|
+
f"\n**New Subsystems/Directories:**\n"
|
|
280
|
+
+ "\n".join([f"- `{d}/`" for d in analysis["new_directories"]])
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
if analysis["has_dependency_changes"]:
|
|
284
|
+
sections.append("\n**Dependency Changes:**\n- Check package.json/requirements.txt for details")
|
|
285
|
+
|
|
286
|
+
file_sections = "".join(sections) if sections else "\n**Files Modified:**\n" + "\n".join(
|
|
287
|
+
[f"- `{f}`" for f in sorted(files)[:10]]
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
# Build impact section
|
|
291
|
+
impact_items = []
|
|
292
|
+
if analysis["has_schema_changes"]:
|
|
293
|
+
impact_items.append("Database/data model structure changed")
|
|
294
|
+
if analysis["has_api_changes"]:
|
|
295
|
+
impact_items.append("API contract or endpoint structure modified")
|
|
296
|
+
if analysis["has_component_changes"]:
|
|
297
|
+
impact_items.append("Component/module organization updated")
|
|
298
|
+
if analysis["has_subsystem_changes"]:
|
|
299
|
+
impact_items.append("New subsystems or major refactoring")
|
|
300
|
+
if analysis["has_dependency_changes"]:
|
|
301
|
+
impact_items.append("Dependencies changed (may affect system design)")
|
|
302
|
+
if analysis["has_context_threading"]:
|
|
303
|
+
impact_items.append(f"Context integration: +{analysis['context_reads']} reads, +{analysis['context_writes']} writes")
|
|
304
|
+
|
|
305
|
+
impact_section = (
|
|
306
|
+
"\n".join([f"- {item}" for item in impact_items])
|
|
307
|
+
if impact_items
|
|
308
|
+
else "- Enhanced system architecture"
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
content = f"""# {topic.replace("-", " ").title()} ({today.strftime("%B %d, %Y")})
|
|
312
|
+
|
|
313
|
+
## Summary
|
|
314
|
+
|
|
315
|
+
{summary}
|
|
316
|
+
|
|
317
|
+
## Type of Architectural Change
|
|
318
|
+
|
|
319
|
+
**{change_type_str}**
|
|
320
|
+
|
|
321
|
+
## What Changed
|
|
322
|
+
{file_sections}
|
|
323
|
+
|
|
324
|
+
**Statistics:**
|
|
325
|
+
- Lines added: {analysis['lines_added']}
|
|
326
|
+
- Lines removed: {analysis['lines_removed']}
|
|
327
|
+
- Files modified: {len(files)}
|
|
328
|
+
|
|
329
|
+
## Impact
|
|
330
|
+
|
|
331
|
+
{impact_section}
|
|
332
|
+
|
|
333
|
+
## Detailed Changes
|
|
334
|
+
|
|
335
|
+
[DESCRIBE: What specifically changed in the architecture? Why was this change necessary?]
|
|
336
|
+
|
|
337
|
+
## Before & After
|
|
338
|
+
|
|
339
|
+
**Before:**
|
|
340
|
+
[OLD DESIGN/STRUCTURE]
|
|
341
|
+
|
|
342
|
+
**After:**
|
|
343
|
+
[NEW DESIGN/STRUCTURE]
|
|
344
|
+
|
|
345
|
+
## Affected Components
|
|
346
|
+
|
|
347
|
+
[LIST: Which parts of the system are affected by this change?]
|
|
348
|
+
|
|
349
|
+
## Migration/Compatibility
|
|
350
|
+
|
|
351
|
+
[IF BREAKING CHANGE: How do users/developers need to adapt?]
|
|
352
|
+
[IF COMPATIBLE: Backward compatibility confirmed ✓]
|
|
353
|
+
|
|
354
|
+
## Verification
|
|
355
|
+
|
|
356
|
+
- [ ] All affected code paths tested
|
|
357
|
+
- [ ] Related documentation updated
|
|
358
|
+
- [ ] No breaking changes (or breaking changes documented)
|
|
359
|
+
- [ ] Dependent systems verified
|
|
360
|
+
"""
|
|
361
|
+
|
|
362
|
+
return content
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
def main():
|
|
366
|
+
import argparse
|
|
367
|
+
|
|
368
|
+
parser = argparse.ArgumentParser(
|
|
369
|
+
description="Detect architectural changes and generate arch log draft"
|
|
370
|
+
)
|
|
371
|
+
parser.add_argument(
|
|
372
|
+
"--dry-run", action="store_true", help="Show generated content without saving"
|
|
373
|
+
)
|
|
374
|
+
parser.add_argument(
|
|
375
|
+
"--output", help="Output file (default: .claude/docs/architectural_change_log/)"
|
|
376
|
+
)
|
|
377
|
+
parser.add_argument(
|
|
378
|
+
"--show-analysis",
|
|
379
|
+
action="store_true",
|
|
380
|
+
help="Show analysis details (debug mode)",
|
|
381
|
+
)
|
|
382
|
+
args = parser.parse_args()
|
|
383
|
+
|
|
384
|
+
try:
|
|
385
|
+
diff = get_git_diff()
|
|
386
|
+
files = get_changed_files()
|
|
387
|
+
|
|
388
|
+
if not diff or not files:
|
|
389
|
+
print("ℹ No changes detected between main and HEAD", file=sys.stderr)
|
|
390
|
+
return 1
|
|
391
|
+
|
|
392
|
+
# Analyze changes
|
|
393
|
+
analysis = analyze_changes(diff, files)
|
|
394
|
+
|
|
395
|
+
if args.show_analysis:
|
|
396
|
+
print("\n=== Analysis ===", file=sys.stderr)
|
|
397
|
+
for key, value in analysis.items():
|
|
398
|
+
print(f"{key}: {value}", file=sys.stderr)
|
|
399
|
+
print()
|
|
400
|
+
|
|
401
|
+
# Infer topic and generate draft
|
|
402
|
+
topic = infer_topic(analysis, files)
|
|
403
|
+
content = generate_arch_log_draft(analysis, files, topic)
|
|
404
|
+
|
|
405
|
+
if args.dry_run:
|
|
406
|
+
print(f"=== Would create: {topic} ===\n", file=sys.stderr)
|
|
407
|
+
print(content)
|
|
408
|
+
return 0
|
|
409
|
+
|
|
410
|
+
# Determine output path
|
|
411
|
+
if args.output:
|
|
412
|
+
output_path = Path(args.output)
|
|
413
|
+
else:
|
|
414
|
+
today = datetime.now()
|
|
415
|
+
date_str = today.strftime("%Y-%m-%d")
|
|
416
|
+
filename = f"{date_str}-{topic}.md"
|
|
417
|
+
arch_dir = Path(".claude/docs/architectural_change_log")
|
|
418
|
+
arch_dir.mkdir(parents=True, exist_ok=True)
|
|
419
|
+
output_path = arch_dir / filename
|
|
420
|
+
|
|
421
|
+
# Create parent directories if needed
|
|
422
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
423
|
+
|
|
424
|
+
# Write file
|
|
425
|
+
output_path.write_text(content)
|
|
426
|
+
print(f"✓ Created draft: {output_path}", file=sys.stderr)
|
|
427
|
+
print(str(output_path)) # stdout for capture by shell
|
|
428
|
+
|
|
429
|
+
return 0
|
|
430
|
+
|
|
431
|
+
except Exception as e:
|
|
432
|
+
print(f"✗ Error: {e}", file=sys.stderr)
|
|
433
|
+
return 1
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
if __name__ == "__main__":
|
|
437
|
+
sys.exit(main())
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# CHANGELOG.md Guide
|
|
2
|
+
|
|
3
|
+
Maintain the project's changelog to track user-facing changes.
|
|
4
|
+
|
|
5
|
+
## Format
|
|
6
|
+
Follow Keep a Changelog:
|
|
7
|
+
- `[Unreleased]` at the top
|
|
8
|
+
- Categories: Added / Changed / Fixed / Deprecated / Removed / Security
|
|
9
|
+
|
|
10
|
+
## Rule of thumb
|
|
11
|
+
If a change is user-visible, add an `[Unreleased]` entry before merging.
|
|
12
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<!-- Generated by /setup-claude -->
|
|
2
|
+
|
|
3
|
+
# Changelog
|
|
4
|
+
|
|
5
|
+
All notable changes to this project will be documented in this file.
|
|
6
|
+
|
|
7
|
+
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
|
|
8
|
+
|
|
9
|
+
## [Unreleased]
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
### Deprecated
|
|
18
|
+
|
|
19
|
+
### Removed
|
|
20
|
+
|
|
21
|
+
### Security
|