@pjmendonca/devflow 1.9.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/CHANGELOG.md +526 -0
- package/LICENSE +21 -0
- package/README.md +620 -0
- package/bin/devflow-checkpoint.js +10 -0
- package/bin/devflow-collab.js +10 -0
- package/bin/devflow-cost.js +10 -0
- package/bin/devflow-create-persona.js +10 -0
- package/bin/devflow-init.js +10 -0
- package/bin/devflow-memory.js +10 -0
- package/bin/devflow-new-doc.js +10 -0
- package/bin/devflow-personalize.js +10 -0
- package/bin/devflow-setup-checkpoint.js +10 -0
- package/bin/devflow-story.js +10 -0
- package/bin/devflow-tech-debt.js +10 -0
- package/bin/devflow-validate-overrides.js +10 -0
- package/bin/devflow-validate.js +10 -0
- package/bin/devflow-version.js +10 -0
- package/lib/constants.js +30 -0
- package/lib/exec-python.js +78 -0
- package/lib/python-check.js +178 -0
- package/package.json +64 -0
- package/tooling/.automation/agents/architect.md +135 -0
- package/tooling/.automation/agents/ba.md +70 -0
- package/tooling/.automation/agents/dev.md +79 -0
- package/tooling/.automation/agents/maintainer.md +97 -0
- package/tooling/.automation/agents/pm.md +116 -0
- package/tooling/.automation/agents/reviewer.md +141 -0
- package/tooling/.automation/agents/sm.md +61 -0
- package/tooling/.automation/agents/writer.md +193 -0
- package/tooling/.automation/config.ps1.template +61 -0
- package/tooling/.automation/config.sh.template +48 -0
- package/tooling/.automation/memory/.gitkeep +6 -0
- package/tooling/.automation/memory/knowledge/kg_integration-test.json +94 -0
- package/tooling/.automation/memory/knowledge/kg_test-story.json +300 -0
- package/tooling/.automation/memory/shared/shared_integration-test.json +30 -0
- package/tooling/.automation/memory/shared/shared_test-story.json +78 -0
- package/tooling/.automation/overrides/templates/README.md +113 -0
- package/tooling/.automation/overrides/templates/architect/README.md +27 -0
- package/tooling/.automation/overrides/templates/architect/cloud-native.yaml +92 -0
- package/tooling/.automation/overrides/templates/architect/enterprise-architect.yaml +85 -0
- package/tooling/.automation/overrides/templates/architect/pragmatic-minimalist.yaml +88 -0
- package/tooling/.automation/overrides/templates/ba/README.md +27 -0
- package/tooling/.automation/overrides/templates/ba/agile-storyteller.yaml +86 -0
- package/tooling/.automation/overrides/templates/ba/domain-expert.yaml +91 -0
- package/tooling/.automation/overrides/templates/ba/requirements-engineer.yaml +89 -0
- package/tooling/.automation/overrides/templates/dev/README.md +32 -0
- package/tooling/.automation/overrides/templates/dev/junior-mentored.yaml +39 -0
- package/tooling/.automation/overrides/templates/dev/performance-engineer.yaml +43 -0
- package/tooling/.automation/overrides/templates/dev/rapid-prototyper.yaml +52 -0
- package/tooling/.automation/overrides/templates/dev/security-focused.yaml +43 -0
- package/tooling/.automation/overrides/templates/dev/senior-fullstack.yaml +39 -0
- package/tooling/.automation/overrides/templates/maintainer/README.md +27 -0
- package/tooling/.automation/overrides/templates/maintainer/devops-maintainer.yaml +113 -0
- package/tooling/.automation/overrides/templates/maintainer/legacy-steward.yaml +94 -0
- package/tooling/.automation/overrides/templates/maintainer/oss-maintainer.yaml +94 -0
- package/tooling/.automation/overrides/templates/pm/README.md +27 -0
- package/tooling/.automation/overrides/templates/pm/agile-pm.yaml +91 -0
- package/tooling/.automation/overrides/templates/pm/hybrid-delivery.yaml +87 -0
- package/tooling/.automation/overrides/templates/pm/traditional-pm.yaml +91 -0
- package/tooling/.automation/overrides/templates/reviewer/README.md +11 -0
- package/tooling/.automation/overrides/templates/reviewer/mentoring-reviewer.yaml +45 -0
- package/tooling/.automation/overrides/templates/reviewer/quick-sanity.yaml +50 -0
- package/tooling/.automation/overrides/templates/reviewer/thorough-critic.yaml +48 -0
- package/tooling/.automation/overrides/templates/sm/README.md +11 -0
- package/tooling/.automation/overrides/templates/sm/agile-coach.yaml +52 -0
- package/tooling/.automation/overrides/templates/sm/startup-pm.yaml +50 -0
- package/tooling/.automation/overrides/templates/sm/technical-lead.yaml +47 -0
- package/tooling/.automation/overrides/templates/user-profile.template.yaml +62 -0
- package/tooling/.automation/overrides/templates/writer/README.md +27 -0
- package/tooling/.automation/overrides/templates/writer/api-documentarian.yaml +99 -0
- package/tooling/.automation/overrides/templates/writer/docs-as-code.yaml +108 -0
- package/tooling/.automation/overrides/templates/writer/user-guide-author.yaml +100 -0
- package/tooling/completions/DevflowCompletion.ps1 +213 -0
- package/tooling/completions/_run-story +116 -0
- package/tooling/completions/run-story-completion.bash +136 -0
- package/tooling/docs/DOC-STANDARD.md +717 -0
- package/tooling/docs/sprint-status.yaml.template +24 -0
- package/tooling/docs/templates/bug-report.md +234 -0
- package/tooling/docs/templates/migration-spec.md +274 -0
- package/tooling/docs/templates/refactor-spec.md +86 -0
- package/tooling/docs/templates/tech-debt.md +86 -0
- package/tooling/scripts/context_checkpoint.py +556 -0
- package/tooling/scripts/cost_dashboard.py +617 -0
- package/tooling/scripts/create-persona.py +690 -0
- package/tooling/scripts/create-persona.sh +435 -0
- package/tooling/scripts/init-project-workflow.ps1 +651 -0
- package/tooling/scripts/init-project-workflow.py +70 -0
- package/tooling/scripts/init-project-workflow.sh +746 -0
- package/tooling/scripts/lib/__init__.py +35 -0
- package/tooling/scripts/lib/agent_handoff.py +526 -0
- package/tooling/scripts/lib/agent_router.py +698 -0
- package/tooling/scripts/lib/checkpoint-integration.ps1 +245 -0
- package/tooling/scripts/lib/checkpoint-integration.sh +191 -0
- package/tooling/scripts/lib/claude-cli.ps1 +952 -0
- package/tooling/scripts/lib/claude-cli.sh +1293 -0
- package/tooling/scripts/lib/cost_config.py +222 -0
- package/tooling/scripts/lib/cost_display.py +443 -0
- package/tooling/scripts/lib/cost_tracker.py +710 -0
- package/tooling/scripts/lib/currency_converter.py +328 -0
- package/tooling/scripts/lib/errors.py +438 -0
- package/tooling/scripts/lib/override-loader.sh +286 -0
- package/tooling/scripts/lib/pair_programming.py +589 -0
- package/tooling/scripts/lib/shared_memory.py +637 -0
- package/tooling/scripts/lib/swarm_orchestrator.py +689 -0
- package/tooling/scripts/memory_summarize.py +324 -0
- package/tooling/scripts/new-doc.ps1 +405 -0
- package/tooling/scripts/new-doc.py +93 -0
- package/tooling/scripts/new-doc.sh +534 -0
- package/tooling/scripts/personalize_agent.py +385 -0
- package/tooling/scripts/rollback-migration.sh +540 -0
- package/tooling/scripts/run-collab.ps1 +251 -0
- package/tooling/scripts/run-collab.py +605 -0
- package/tooling/scripts/run-collab.sh +110 -0
- package/tooling/scripts/run-story.ps1 +490 -0
- package/tooling/scripts/run-story.py +387 -0
- package/tooling/scripts/run-story.sh +467 -0
- package/tooling/scripts/setup-checkpoint-service.ps1 +219 -0
- package/tooling/scripts/setup-checkpoint-service.py +87 -0
- package/tooling/scripts/setup-checkpoint-service.sh +236 -0
- package/tooling/scripts/tech-debt-tracker.py +608 -0
- package/tooling/scripts/update_version.py +244 -0
- package/tooling/scripts/validate-overrides.py +511 -0
- package/tooling/scripts/validate-overrides.sh +432 -0
- package/tooling/scripts/validate_setup.py +539 -0
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Memory Summarization Utility
|
|
4
|
+
|
|
5
|
+
Summarizes agent memory files to prevent unbounded growth.
|
|
6
|
+
Uses simple heuristics to identify and consolidate similar entries.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
python3 memory_summarize.py [agent_name] [--dry-run] [--max-entries 50]
|
|
10
|
+
python3 memory_summarize.py --all [--dry-run] [--max-entries 50]
|
|
11
|
+
|
|
12
|
+
Examples:
|
|
13
|
+
python3 memory_summarize.py dev # Summarize dev agent memory
|
|
14
|
+
python3 memory_summarize.py --all # Summarize all agents
|
|
15
|
+
python3 memory_summarize.py dev --dry-run # Preview without changes
|
|
16
|
+
python3 memory_summarize.py dev --max-entries 30 # Keep max 30 entries
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import argparse
|
|
20
|
+
import re
|
|
21
|
+
import sys
|
|
22
|
+
from collections import defaultdict
|
|
23
|
+
from datetime import datetime
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
from typing import Optional
|
|
26
|
+
|
|
27
|
+
# Find project root
|
|
28
|
+
SCRIPT_DIR = Path(__file__).parent.resolve()
|
|
29
|
+
PROJECT_ROOT = SCRIPT_DIR.parent.parent
|
|
30
|
+
MEMORY_DIR = PROJECT_ROOT / ".automation" / "memory"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def parse_memory_entry(line: str) -> tuple[Optional[datetime], str]:
|
|
34
|
+
"""Parse a memory entry line into timestamp and content."""
|
|
35
|
+
# Format: - YYYY-MM-DD HH:MM: content
|
|
36
|
+
match = re.match(r"^-\s*(\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}):\s*(.+)$", line.strip())
|
|
37
|
+
if match:
|
|
38
|
+
try:
|
|
39
|
+
timestamp = datetime.strptime(match.group(1), "%Y-%m-%d %H:%M")
|
|
40
|
+
return timestamp, match.group(2).strip()
|
|
41
|
+
except ValueError:
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
# Format without timestamp: - content
|
|
45
|
+
match = re.match(r"^-\s*(.+)$", line.strip())
|
|
46
|
+
if match:
|
|
47
|
+
return None, match.group(1).strip()
|
|
48
|
+
|
|
49
|
+
return None, line.strip()
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def categorize_entry(content: str) -> str:
|
|
53
|
+
"""Categorize a memory entry by its content."""
|
|
54
|
+
content_lower = content.lower()
|
|
55
|
+
|
|
56
|
+
# Error/bug related
|
|
57
|
+
if any(word in content_lower for word in ["error", "bug", "fix", "crash", "issue", "fail"]):
|
|
58
|
+
return "errors"
|
|
59
|
+
|
|
60
|
+
# Preference/style related
|
|
61
|
+
if any(
|
|
62
|
+
word in content_lower for word in ["prefer", "style", "convention", "pattern", "approach"]
|
|
63
|
+
):
|
|
64
|
+
return "preferences"
|
|
65
|
+
|
|
66
|
+
# Code/implementation related
|
|
67
|
+
if any(
|
|
68
|
+
word in content_lower
|
|
69
|
+
for word in ["implement", "code", "function", "class", "module", "file"]
|
|
70
|
+
):
|
|
71
|
+
return "implementation"
|
|
72
|
+
|
|
73
|
+
# Testing related
|
|
74
|
+
if any(word in content_lower for word in ["test", "spec", "coverage", "assert"]):
|
|
75
|
+
return "testing"
|
|
76
|
+
|
|
77
|
+
# Architecture/design related
|
|
78
|
+
if any(
|
|
79
|
+
word in content_lower for word in ["architect", "design", "structure", "pattern", "layer"]
|
|
80
|
+
):
|
|
81
|
+
return "architecture"
|
|
82
|
+
|
|
83
|
+
# Performance related
|
|
84
|
+
if any(
|
|
85
|
+
word in content_lower
|
|
86
|
+
for word in ["performance", "optimize", "slow", "fast", "memory", "cache"]
|
|
87
|
+
):
|
|
88
|
+
return "performance"
|
|
89
|
+
|
|
90
|
+
# Documentation related
|
|
91
|
+
if any(word in content_lower for word in ["doc", "readme", "comment", "explain"]):
|
|
92
|
+
return "documentation"
|
|
93
|
+
|
|
94
|
+
return "general"
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def similarity_score(entry1: str, entry2: str) -> float:
|
|
98
|
+
"""Calculate simple similarity between two entries."""
|
|
99
|
+
words1 = set(entry1.lower().split())
|
|
100
|
+
words2 = set(entry2.lower().split())
|
|
101
|
+
|
|
102
|
+
if not words1 or not words2:
|
|
103
|
+
return 0.0
|
|
104
|
+
|
|
105
|
+
intersection = words1 & words2
|
|
106
|
+
union = words1 | words2
|
|
107
|
+
|
|
108
|
+
return len(intersection) / len(union)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def find_duplicates(
|
|
112
|
+
entries: list[tuple[Optional[datetime], str]], threshold: float = 0.7
|
|
113
|
+
) -> list[list[int]]:
|
|
114
|
+
"""Find groups of similar entries."""
|
|
115
|
+
groups = []
|
|
116
|
+
used = set()
|
|
117
|
+
|
|
118
|
+
for i, (_, content1) in enumerate(entries):
|
|
119
|
+
if i in used:
|
|
120
|
+
continue
|
|
121
|
+
|
|
122
|
+
group = [i]
|
|
123
|
+
for j, (_, content2) in enumerate(entries[i + 1 :], start=i + 1):
|
|
124
|
+
if j in used:
|
|
125
|
+
continue
|
|
126
|
+
|
|
127
|
+
if similarity_score(content1, content2) >= threshold:
|
|
128
|
+
group.append(j)
|
|
129
|
+
used.add(j)
|
|
130
|
+
|
|
131
|
+
if len(group) > 1:
|
|
132
|
+
groups.append(group)
|
|
133
|
+
used.add(i)
|
|
134
|
+
|
|
135
|
+
return groups
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def summarize_group(entries: list[tuple[Optional[datetime], str]]) -> str:
|
|
139
|
+
"""Create a summary for a group of similar entries."""
|
|
140
|
+
# Keep the most recent entry's content
|
|
141
|
+
sorted_entries = sorted(entries, key=lambda x: x[0] or datetime.min, reverse=True)
|
|
142
|
+
most_recent = sorted_entries[0][1]
|
|
143
|
+
|
|
144
|
+
if len(entries) > 2:
|
|
145
|
+
return f"{most_recent} (noted {len(entries)} times)"
|
|
146
|
+
return most_recent
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def load_memory_file(agent_name: str) -> list[str]:
|
|
150
|
+
"""Load memory file contents."""
|
|
151
|
+
memory_file = MEMORY_DIR / f"{agent_name}.memory.md"
|
|
152
|
+
|
|
153
|
+
if not memory_file.exists():
|
|
154
|
+
return []
|
|
155
|
+
|
|
156
|
+
with open(memory_file) as f:
|
|
157
|
+
return [line.strip() for line in f.readlines() if line.strip()]
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def save_memory_file(agent_name: str, lines: list[str]) -> None:
|
|
161
|
+
"""Save memory file contents."""
|
|
162
|
+
memory_file = MEMORY_DIR / f"{agent_name}.memory.md"
|
|
163
|
+
|
|
164
|
+
with open(memory_file, "w") as f:
|
|
165
|
+
f.write("\n".join(lines) + "\n")
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def summarize_agent_memory(agent_name: str, max_entries: int = 50, dry_run: bool = False) -> dict:
|
|
169
|
+
"""Summarize an agent's memory file."""
|
|
170
|
+
lines = load_memory_file(agent_name)
|
|
171
|
+
|
|
172
|
+
if not lines:
|
|
173
|
+
return {"agent": agent_name, "status": "empty", "original": 0, "final": 0}
|
|
174
|
+
|
|
175
|
+
# Parse entries
|
|
176
|
+
entries = [parse_memory_entry(line) for line in lines]
|
|
177
|
+
|
|
178
|
+
result = {
|
|
179
|
+
"agent": agent_name,
|
|
180
|
+
"original": len(entries),
|
|
181
|
+
"categories": defaultdict(int),
|
|
182
|
+
"duplicates_found": 0,
|
|
183
|
+
"final": 0,
|
|
184
|
+
"changes": [],
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
# Categorize entries
|
|
188
|
+
for _, content in entries:
|
|
189
|
+
category = categorize_entry(content)
|
|
190
|
+
result["categories"][category] += 1
|
|
191
|
+
|
|
192
|
+
# Find and consolidate duplicates
|
|
193
|
+
duplicate_groups = find_duplicates(entries)
|
|
194
|
+
result["duplicates_found"] = sum(len(g) - 1 for g in duplicate_groups)
|
|
195
|
+
|
|
196
|
+
# Build new entry list
|
|
197
|
+
indices_to_remove = set()
|
|
198
|
+
summaries = []
|
|
199
|
+
|
|
200
|
+
for group in duplicate_groups:
|
|
201
|
+
group_entries = [entries[i] for i in group]
|
|
202
|
+
summary = summarize_group(group_entries)
|
|
203
|
+
most_recent_time = max((e[0] for e in group_entries if e[0]), default=None)
|
|
204
|
+
summaries.append((most_recent_time, summary))
|
|
205
|
+
indices_to_remove.update(group)
|
|
206
|
+
result["changes"].append(f"Consolidated {len(group)} similar entries")
|
|
207
|
+
|
|
208
|
+
# Keep non-duplicate entries
|
|
209
|
+
new_entries = []
|
|
210
|
+
for i, entry in enumerate(entries):
|
|
211
|
+
if i not in indices_to_remove:
|
|
212
|
+
new_entries.append(entry)
|
|
213
|
+
|
|
214
|
+
# Add summaries
|
|
215
|
+
new_entries.extend(summaries)
|
|
216
|
+
|
|
217
|
+
# Sort by timestamp (most recent first for trimming)
|
|
218
|
+
new_entries.sort(key=lambda x: x[0] or datetime.min, reverse=True)
|
|
219
|
+
|
|
220
|
+
# Trim to max entries if needed
|
|
221
|
+
if len(new_entries) > max_entries:
|
|
222
|
+
trimmed_count = len(new_entries) - max_entries
|
|
223
|
+
new_entries = new_entries[:max_entries]
|
|
224
|
+
result["changes"].append(f"Trimmed {trimmed_count} oldest entries")
|
|
225
|
+
|
|
226
|
+
# Sort back to chronological order for output
|
|
227
|
+
new_entries.sort(key=lambda x: x[0] or datetime.min)
|
|
228
|
+
|
|
229
|
+
result["final"] = len(new_entries)
|
|
230
|
+
|
|
231
|
+
# Format output lines
|
|
232
|
+
output_lines = []
|
|
233
|
+
for timestamp, content in new_entries:
|
|
234
|
+
if timestamp:
|
|
235
|
+
output_lines.append(f"- {timestamp.strftime('%Y-%m-%d %H:%M')}: {content}")
|
|
236
|
+
else:
|
|
237
|
+
output_lines.append(f"- {content}")
|
|
238
|
+
|
|
239
|
+
if not dry_run and output_lines != lines:
|
|
240
|
+
save_memory_file(agent_name, output_lines)
|
|
241
|
+
result["status"] = "updated"
|
|
242
|
+
else:
|
|
243
|
+
result["status"] = "dry-run" if dry_run else "no-change"
|
|
244
|
+
|
|
245
|
+
return result
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def get_all_agents() -> list[str]:
|
|
249
|
+
"""Get list of agents with memory files."""
|
|
250
|
+
agents = []
|
|
251
|
+
|
|
252
|
+
if MEMORY_DIR.exists():
|
|
253
|
+
for file in MEMORY_DIR.glob("*.memory.md"):
|
|
254
|
+
agent_name = file.stem.replace(".memory", "")
|
|
255
|
+
agents.append(agent_name)
|
|
256
|
+
|
|
257
|
+
return agents
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def print_result(result: dict) -> None:
|
|
261
|
+
"""Print summarization result."""
|
|
262
|
+
print(f"\n{'=' * 50}")
|
|
263
|
+
print(f"Agent: {result['agent']}")
|
|
264
|
+
print(f"Status: {result['status']}")
|
|
265
|
+
|
|
266
|
+
if result["status"] == "empty":
|
|
267
|
+
print("No memory entries found.")
|
|
268
|
+
return
|
|
269
|
+
|
|
270
|
+
print(f"Original entries: {result['original']}")
|
|
271
|
+
print(f"Final entries: {result['final']}")
|
|
272
|
+
|
|
273
|
+
if result.get("duplicates_found", 0) > 0:
|
|
274
|
+
print(f"Duplicates consolidated: {result['duplicates_found']}")
|
|
275
|
+
|
|
276
|
+
if result.get("categories"):
|
|
277
|
+
print("\nCategories:")
|
|
278
|
+
for cat, count in sorted(result["categories"].items(), key=lambda x: -x[1]):
|
|
279
|
+
print(f" - {cat}: {count}")
|
|
280
|
+
|
|
281
|
+
if result.get("changes"):
|
|
282
|
+
print("\nChanges made:")
|
|
283
|
+
for change in result["changes"]:
|
|
284
|
+
print(f" - {change}")
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def main():
|
|
288
|
+
parser = argparse.ArgumentParser(
|
|
289
|
+
description="Summarize agent memory files to prevent unbounded growth."
|
|
290
|
+
)
|
|
291
|
+
parser.add_argument("agent", nargs="?", help="Agent name to summarize")
|
|
292
|
+
parser.add_argument("--all", action="store_true", help="Summarize all agents")
|
|
293
|
+
parser.add_argument("--dry-run", action="store_true", help="Preview without making changes")
|
|
294
|
+
parser.add_argument(
|
|
295
|
+
"--max-entries", type=int, default=50, help="Maximum entries to keep (default: 50)"
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
args = parser.parse_args()
|
|
299
|
+
|
|
300
|
+
if not args.agent and not args.all:
|
|
301
|
+
parser.print_help()
|
|
302
|
+
print("\nError: Please specify an agent name or use --all")
|
|
303
|
+
sys.exit(1)
|
|
304
|
+
|
|
305
|
+
if args.all:
|
|
306
|
+
agents = get_all_agents()
|
|
307
|
+
if not agents:
|
|
308
|
+
print("No agent memory files found.")
|
|
309
|
+
sys.exit(0)
|
|
310
|
+
|
|
311
|
+
print(f"Summarizing memory for {len(agents)} agents...")
|
|
312
|
+
for agent in agents:
|
|
313
|
+
result = summarize_agent_memory(agent, args.max_entries, args.dry_run)
|
|
314
|
+
print_result(result)
|
|
315
|
+
else:
|
|
316
|
+
result = summarize_agent_memory(args.agent, args.max_entries, args.dry_run)
|
|
317
|
+
print_result(result)
|
|
318
|
+
|
|
319
|
+
if args.dry_run:
|
|
320
|
+
print("\n(Dry run - no changes made)")
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
if __name__ == "__main__":
|
|
324
|
+
main()
|
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
NEW-DOC - Documentation Template Generator for Windows
|
|
4
|
+
|
|
5
|
+
.DESCRIPTION
|
|
6
|
+
Creates new documentation files following the documentation standard.
|
|
7
|
+
|
|
8
|
+
.PARAMETER Type
|
|
9
|
+
Document type: guide, spec, status, reference, example
|
|
10
|
+
|
|
11
|
+
.PARAMETER Name
|
|
12
|
+
Document name (kebab-case)
|
|
13
|
+
|
|
14
|
+
.PARAMETER Author
|
|
15
|
+
Author name (default: current user)
|
|
16
|
+
|
|
17
|
+
.EXAMPLE
|
|
18
|
+
.\new-doc.ps1 -Type guide -Name "checkpoint-setup"
|
|
19
|
+
.\new-doc.ps1 -Type spec -Name "epic-4" -Author "SM Agent"
|
|
20
|
+
|
|
21
|
+
.NOTES
|
|
22
|
+
Version: 1.0.0
|
|
23
|
+
#>
|
|
24
|
+
|
|
25
|
+
#Requires -Version 5.1
|
|
26
|
+
|
|
27
|
+
param(
|
|
28
|
+
[Parameter(Mandatory=$true)]
|
|
29
|
+
[ValidateSet("guide", "spec", "status", "reference", "example")]
|
|
30
|
+
[string]$Type,
|
|
31
|
+
|
|
32
|
+
[Parameter(Mandatory=$true)]
|
|
33
|
+
[string]$Name,
|
|
34
|
+
|
|
35
|
+
[string]$Author = $env:USERNAME
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
$script:ScriptDir = $PSScriptRoot
|
|
39
|
+
$script:ProjectRoot = (Get-Item "$script:ScriptDir\.." -ErrorAction SilentlyContinue).FullName
|
|
40
|
+
$script:DocsDir = Join-Path $script:ProjectRoot "tooling\docs"
|
|
41
|
+
|
|
42
|
+
function Get-GuideTemplate {
|
|
43
|
+
param([string]$Name, [string]$Author, [string]$Date)
|
|
44
|
+
|
|
45
|
+
return @"
|
|
46
|
+
# [Document Title]
|
|
47
|
+
|
|
48
|
+
**Type**: Guide
|
|
49
|
+
**Version**: 1.0
|
|
50
|
+
**Last Updated**: $Date
|
|
51
|
+
**Author**: $Author
|
|
52
|
+
**Status**: Draft
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Purpose
|
|
57
|
+
|
|
58
|
+
[1-2 sentence description of what this guide helps users accomplish]
|
|
59
|
+
|
|
60
|
+
## Table of Contents
|
|
61
|
+
|
|
62
|
+
- [Prerequisites](#prerequisites)
|
|
63
|
+
- [Quick Start](#quick-start)
|
|
64
|
+
- [Step-by-Step Instructions](#step-by-step-instructions)
|
|
65
|
+
- [Examples](#examples)
|
|
66
|
+
- [Troubleshooting](#troubleshooting)
|
|
67
|
+
- [Next Steps](#next-steps)
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Prerequisites
|
|
72
|
+
|
|
73
|
+
Before starting, ensure you have:
|
|
74
|
+
|
|
75
|
+
- [ ] Prerequisite 1
|
|
76
|
+
- [ ] Prerequisite 2
|
|
77
|
+
- [ ] Prerequisite 3
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Quick Start
|
|
82
|
+
|
|
83
|
+
For experienced users:
|
|
84
|
+
|
|
85
|
+
``````powershell
|
|
86
|
+
# Quick command to get started
|
|
87
|
+
``````
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Step-by-Step Instructions
|
|
92
|
+
|
|
93
|
+
### Step 1: [First Step]
|
|
94
|
+
|
|
95
|
+
Description of what to do.
|
|
96
|
+
|
|
97
|
+
``````powershell
|
|
98
|
+
# Command to run
|
|
99
|
+
``````
|
|
100
|
+
|
|
101
|
+
**Expected output**:
|
|
102
|
+
``````
|
|
103
|
+
Output here
|
|
104
|
+
``````
|
|
105
|
+
|
|
106
|
+
### Step 2: [Second Step]
|
|
107
|
+
|
|
108
|
+
Description of what to do.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Examples
|
|
113
|
+
|
|
114
|
+
### Example 1: [Common Use Case]
|
|
115
|
+
|
|
116
|
+
**Problem**: [What problem this solves]
|
|
117
|
+
|
|
118
|
+
**Solution**:
|
|
119
|
+
``````powershell
|
|
120
|
+
# Commands
|
|
121
|
+
``````
|
|
122
|
+
|
|
123
|
+
**Result**: [What happens]
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Troubleshooting
|
|
128
|
+
|
|
129
|
+
### Issue: [Common Problem]
|
|
130
|
+
|
|
131
|
+
**Symptoms**: [What you see]
|
|
132
|
+
|
|
133
|
+
**Cause**: [Why it happens]
|
|
134
|
+
|
|
135
|
+
**Solution**:
|
|
136
|
+
``````powershell
|
|
137
|
+
# Fix commands
|
|
138
|
+
``````
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Next Steps
|
|
143
|
+
|
|
144
|
+
After completing this guide:
|
|
145
|
+
|
|
146
|
+
1. [Next logical step]
|
|
147
|
+
2. [Another option]
|
|
148
|
+
3. [Advanced topics]
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Changelog
|
|
153
|
+
|
|
154
|
+
### 1.0 ($Date)
|
|
155
|
+
- Initial version
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
**Document Control**
|
|
160
|
+
- **Created**: $Date
|
|
161
|
+
- **Owner**: $Author
|
|
162
|
+
"@
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function Get-SpecTemplate {
|
|
166
|
+
param([string]$Name, [string]$Author, [string]$Date)
|
|
167
|
+
|
|
168
|
+
return @"
|
|
169
|
+
# [Technical Specification Title]
|
|
170
|
+
|
|
171
|
+
**Type**: Spec
|
|
172
|
+
**Version**: 1.0
|
|
173
|
+
**Last Updated**: $Date
|
|
174
|
+
**Author**: $Author
|
|
175
|
+
**Status**: Draft
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Overview
|
|
180
|
+
|
|
181
|
+
[High-level description of what is being specified]
|
|
182
|
+
|
|
183
|
+
## Table of Contents
|
|
184
|
+
|
|
185
|
+
- [Objectives and Scope](#objectives-and-scope)
|
|
186
|
+
- [Architecture](#architecture)
|
|
187
|
+
- [Implementation Details](#implementation-details)
|
|
188
|
+
- [Dependencies](#dependencies)
|
|
189
|
+
- [Testing Requirements](#testing-requirements)
|
|
190
|
+
- [Acceptance Criteria](#acceptance-criteria)
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Objectives and Scope
|
|
195
|
+
|
|
196
|
+
### In Scope
|
|
197
|
+
- Feature 1
|
|
198
|
+
- Feature 2
|
|
199
|
+
- Feature 3
|
|
200
|
+
|
|
201
|
+
### Out of Scope
|
|
202
|
+
- Feature A
|
|
203
|
+
- Feature B
|
|
204
|
+
|
|
205
|
+
### Success Criteria
|
|
206
|
+
- [ ] Criterion 1
|
|
207
|
+
- [ ] Criterion 2
|
|
208
|
+
- [ ] Criterion 3
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Architecture
|
|
213
|
+
|
|
214
|
+
### System Components
|
|
215
|
+
|
|
216
|
+
``````
|
|
217
|
+
[ASCII diagram or description]
|
|
218
|
+
``````
|
|
219
|
+
|
|
220
|
+
### Data Flow
|
|
221
|
+
|
|
222
|
+
``````
|
|
223
|
+
[Flow description]
|
|
224
|
+
``````
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Implementation Details
|
|
229
|
+
|
|
230
|
+
### Component 1: [Name]
|
|
231
|
+
|
|
232
|
+
**Purpose**: [What it does]
|
|
233
|
+
|
|
234
|
+
**Files to Create**:
|
|
235
|
+
- ``path/to/file1``
|
|
236
|
+
- ``path/to/file2``
|
|
237
|
+
|
|
238
|
+
**Files to Modify**:
|
|
239
|
+
- ``path/to/existing``
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## Dependencies
|
|
244
|
+
|
|
245
|
+
| Dependency | Version | Purpose |
|
|
246
|
+
|-----------|---------|---------|
|
|
247
|
+
| package_name | ^1.0.0 | Description |
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## Testing Requirements
|
|
252
|
+
|
|
253
|
+
### Unit Tests
|
|
254
|
+
- [ ] Test scenario 1
|
|
255
|
+
- [ ] Test scenario 2
|
|
256
|
+
|
|
257
|
+
### Integration Tests
|
|
258
|
+
- [ ] Test scenario 1
|
|
259
|
+
- [ ] Test scenario 2
|
|
260
|
+
|
|
261
|
+
### Test Coverage Target
|
|
262
|
+
- Minimum: 80%
|
|
263
|
+
- Target: 90%
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## Acceptance Criteria
|
|
268
|
+
|
|
269
|
+
- [ ] AC 1: [Specific, measurable criterion]
|
|
270
|
+
- [ ] AC 2: [Specific, measurable criterion]
|
|
271
|
+
- [ ] AC 3: [Specific, measurable criterion]
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## Changelog
|
|
276
|
+
|
|
277
|
+
### 1.0 ($Date)
|
|
278
|
+
- Initial specification
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
**Document Control**
|
|
283
|
+
- **Created**: $Date
|
|
284
|
+
- **Owner**: $Author
|
|
285
|
+
"@
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function Get-StatusTemplate {
|
|
289
|
+
param([string]$Name, [string]$Author, [string]$Date)
|
|
290
|
+
|
|
291
|
+
return @"
|
|
292
|
+
# [Status Report Title]
|
|
293
|
+
|
|
294
|
+
**Type**: Status
|
|
295
|
+
**Version**: 1.0
|
|
296
|
+
**Last Updated**: $Date
|
|
297
|
+
**Author**: $Author
|
|
298
|
+
**Status**: Active
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## Current Status
|
|
303
|
+
|
|
304
|
+
**Overall**: [Green/Yellow/Red]
|
|
305
|
+
|
|
306
|
+
**Summary**: [1-sentence current state]
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
## Integration Points
|
|
311
|
+
|
|
312
|
+
| Component | Status | Notes |
|
|
313
|
+
|-----------|--------|-------|
|
|
314
|
+
| Component 1 | Complete | Working as expected |
|
|
315
|
+
| Component 2 | In Progress | 75% complete |
|
|
316
|
+
| Component 3 | Not Started | Planned for next week |
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
## What's Working
|
|
321
|
+
|
|
322
|
+
- Feature 1 - Fully operational
|
|
323
|
+
- Feature 2 - Deployed and tested
|
|
324
|
+
- Feature 3 - In production
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## What's Not Working
|
|
329
|
+
|
|
330
|
+
- Issue 1 - Description
|
|
331
|
+
- Issue 2 - Description
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
## Metrics
|
|
336
|
+
|
|
337
|
+
| Metric | Value | Target | Status |
|
|
338
|
+
|--------|-------|--------|--------|
|
|
339
|
+
| Coverage | 85% | 80% | OK |
|
|
340
|
+
| Performance | 200ms | <300ms | OK |
|
|
341
|
+
| Bugs | 3 | <5 | OK |
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
## Next Steps
|
|
346
|
+
|
|
347
|
+
### Immediate (This Week)
|
|
348
|
+
1. [ ] Task 1
|
|
349
|
+
2. [ ] Task 2
|
|
350
|
+
|
|
351
|
+
### Short Term (Next Week)
|
|
352
|
+
1. [ ] Task 3
|
|
353
|
+
2. [ ] Task 4
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
## Changelog
|
|
358
|
+
|
|
359
|
+
### 1.0 ($Date)
|
|
360
|
+
- Initial status report
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
**Document Control**
|
|
365
|
+
- **Created**: $Date
|
|
366
|
+
- **Owner**: $Author
|
|
367
|
+
"@
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
# Main execution
|
|
371
|
+
$date = (Get-Date).ToString("yyyy-MM-dd")
|
|
372
|
+
$filename = "$($Type.ToUpper())-$Name.md"
|
|
373
|
+
$outputFile = Join-Path $script:DocsDir $filename
|
|
374
|
+
|
|
375
|
+
# Check if file exists
|
|
376
|
+
if (Test-Path $outputFile) {
|
|
377
|
+
Write-Host "File already exists: $outputFile" -ForegroundColor Yellow
|
|
378
|
+
$overwrite = Read-Host "Overwrite? (y/n)"
|
|
379
|
+
if ($overwrite -notmatch '^[Yy]') {
|
|
380
|
+
Write-Host "Aborted." -ForegroundColor Blue
|
|
381
|
+
exit 0
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
Write-Host "Creating $Type document: $filename" -ForegroundColor Blue
|
|
386
|
+
|
|
387
|
+
# Generate template
|
|
388
|
+
$template = switch ($Type) {
|
|
389
|
+
"guide" { Get-GuideTemplate -Name $Name -Author $Author -Date $date }
|
|
390
|
+
"spec" { Get-SpecTemplate -Name $Name -Author $Author -Date $date }
|
|
391
|
+
"status" { Get-StatusTemplate -Name $Name -Author $Author -Date $date }
|
|
392
|
+
"reference" { Get-GuideTemplate -Name $Name -Author $Author -Date $date }
|
|
393
|
+
"example" { Get-GuideTemplate -Name $Name -Author $Author -Date $date }
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
# Write file
|
|
397
|
+
Set-Content -Path $outputFile -Value $template
|
|
398
|
+
|
|
399
|
+
Write-Host "[OK] Created: $outputFile" -ForegroundColor Green
|
|
400
|
+
Write-Host ""
|
|
401
|
+
Write-Host "Next steps:" -ForegroundColor Blue
|
|
402
|
+
Write-Host " 1. Edit the document: $outputFile"
|
|
403
|
+
Write-Host " 2. Fill in the template placeholders"
|
|
404
|
+
Write-Host " 3. Review against: tooling\docs\DOC-STANDARD.md"
|
|
405
|
+
Write-Host ""
|