@orchestrator-claude/definitions 3.30.2 → 3.31.1
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/agents/adversarial-reviewer.md +217 -0
- package/agents/azure-devops-engineer.md +805 -0
- package/agents/methodology-researcher.md +190 -0
- package/agents/operational-artifact-builder.md +173 -0
- package/agents/presentation-engineer.md +605 -0
- package/agents/reviewer.md +3 -1
- package/dist/scripts/generate-manifest.js +3 -3
- package/dist/scripts/generate-manifest.js.map +1 -1
- package/hooks/mailbox-listener.ts +246 -0
- package/hooks/pre-agent-dispatch.ts +57 -0
- package/hooks/sprint-registry.ts +85 -0
- package/hooks/verification-before-completion.ts +97 -0
- package/manifest.json +278 -5
- package/package.json +1 -1
- package/skills/artifact-generator/SKILL.md +385 -0
- package/skills/brainstorm-formalize/SKILL.md +272 -0
- package/skills/brainstorming/SKILL.md +167 -0
- package/skills/brainstorming/scripts/frame-template.html +214 -0
- package/skills/brainstorming/scripts/helper.js +88 -0
- package/skills/brainstorming/scripts/server.cjs +354 -0
- package/skills/brainstorming/scripts/start-server.sh +148 -0
- package/skills/brainstorming/scripts/stop-server.sh +56 -0
- package/skills/brainstorming/visual-companion.md +139 -0
- package/skills/compositional-intelligence/SKILL.md +93 -0
- package/skills/design-system-validated-loop/SKILL.md +366 -0
- package/skills/finishing-branch/SKILL.md +184 -0
- package/skills/orchestrator/SKILL.md +158 -0
- package/skills/persona-library/SKILL.md +365 -0
- package/skills/project-management-enterprise/SKILL.md +304 -0
- package/skills/receiving-code-review/SKILL.md +186 -0
- package/skills/release/SKILL.md +41 -0
- package/skills/sprint-launch/SKILL.md +176 -0
- package/skills/sprint-teammate/sprint-teammate.md +107 -0
- package/skills/systematic-debugging/SKILL.md +262 -0
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: artifact-generator
|
|
3
|
+
description: Generate client-facing deliverable files (xlsx schedules, pdf decks, csv issue trees, jinja2-templated docs). Load when: "generate xlsx", "build pdf", "compile deliverable pack", "jinja2 template". Do NOT use for code generation.
|
|
4
|
+
allowed-tools: Read, Write, Bash
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Artifact Generator Skill
|
|
8
|
+
|
|
9
|
+
## When to Use This Skill
|
|
10
|
+
|
|
11
|
+
Load this skill when:
|
|
12
|
+
|
|
13
|
+
- A request contains any of these trigger phrases: "generate xlsx", "build pdf", "compile deliverable pack", "jinja2 template", "export to excel", "produce pdf report", "render template", "convert to docx"
|
|
14
|
+
- An operational-artifact-builder agent dispatches a deliverable generation task
|
|
15
|
+
- A PME workflow enters its **FRAMEWORK**, **OPERATIONAL**, or **DELIVER** phase and requires client-facing output
|
|
16
|
+
- The user requests a multi-format output pack (xlsx + pdf + csv bundled together)
|
|
17
|
+
|
|
18
|
+
**Scope boundary — what this skill does NOT cover:**
|
|
19
|
+
|
|
20
|
+
- Code generation (TypeScript, Python source files for the orchestrator itself)
|
|
21
|
+
- Markdown spec/plan/task artifacts — use `/artifact-production` for those
|
|
22
|
+
- Internal reports stored only in MinIO — use `artifactStore` directly
|
|
23
|
+
- Presentation slide decks authored in Slidev — those live in a separate `slidev-build` skill
|
|
24
|
+
|
|
25
|
+
Client-facing deliverable formats in scope: `.xlsx`, `.pdf`, `.docx`, `.csv`, `.html` (rendered from template).
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Pre-flight Python Environment Check
|
|
30
|
+
|
|
31
|
+
Before running any generation script, verify the runtime stack is present:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# Python version — must be 3.11 or above
|
|
35
|
+
python3 --version
|
|
36
|
+
|
|
37
|
+
# Required libraries
|
|
38
|
+
pip list | grep -E "openpyxl|jinja2"
|
|
39
|
+
|
|
40
|
+
# Pandoc system binary
|
|
41
|
+
pandoc --version | head -1
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**S178-validated versions** (Red Bull Big Battle Consultoria, 10/05/2026):
|
|
45
|
+
|
|
46
|
+
| Tool | Validated version |
|
|
47
|
+
|------|------------------|
|
|
48
|
+
| openpyxl | 3.1.x |
|
|
49
|
+
| jinja2 | 3.1.x |
|
|
50
|
+
| Pandoc | 3.9.0.2 (user-local binary at `~/.local/bin/pandoc`) |
|
|
51
|
+
|
|
52
|
+
**Install missing Python libraries:**
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pip install openpyxl jinja2
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Install Pandoc (choose one):**
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# Debian/Ubuntu
|
|
62
|
+
sudo apt install pandoc
|
|
63
|
+
|
|
64
|
+
# macOS
|
|
65
|
+
brew install pandoc
|
|
66
|
+
|
|
67
|
+
# User-local (no sudo) — download from GitHub releases
|
|
68
|
+
# https://github.com/jgm/pandoc/releases
|
|
69
|
+
# Extract binary to ~/.local/bin/ and add to PATH
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**If `python3` is not found**, the generation script must not proceed. Surface a CRITICAL blocker to the orchestrating agent and halt.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Pattern Catalog
|
|
77
|
+
|
|
78
|
+
### Pattern 1 — xlsx Multi-Sheet (openpyxl)
|
|
79
|
+
|
|
80
|
+
Use for: schedule grids, issue-tree exports, data tables with multiple perspectives.
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
import openpyxl
|
|
84
|
+
from openpyxl.styles import Font, PatternFill, Alignment
|
|
85
|
+
from pathlib import Path
|
|
86
|
+
|
|
87
|
+
def generate_workbook(output_path: str, workflow_id: str) -> None:
|
|
88
|
+
wb = openpyxl.Workbook()
|
|
89
|
+
|
|
90
|
+
# Sheet 1: Overview
|
|
91
|
+
ws_overview = wb.active
|
|
92
|
+
ws_overview.title = "Overview"
|
|
93
|
+
headers = ["ID", "Topic", "Owner", "Status", "Due Date"]
|
|
94
|
+
for col, header in enumerate(headers, start=1):
|
|
95
|
+
cell = ws_overview.cell(row=1, column=col, value=header)
|
|
96
|
+
cell.font = Font(bold=True, name="Calibri", size=11)
|
|
97
|
+
cell.alignment = Alignment(horizontal="center")
|
|
98
|
+
|
|
99
|
+
# Sheet 2: Issue Tree
|
|
100
|
+
ws_tree = wb.create_sheet("Issue Tree")
|
|
101
|
+
tree_headers = ["id", "parent_id", "depth", "branch", "hypothesis", "evidence_status"]
|
|
102
|
+
for col, header in enumerate(tree_headers, start=1):
|
|
103
|
+
cell = ws_tree.cell(row=1, column=col, value=header)
|
|
104
|
+
cell.font = Font(bold=True, name="Calibri", size=11)
|
|
105
|
+
|
|
106
|
+
# Sheet 3: Timeline
|
|
107
|
+
ws_timeline = wb.create_sheet("Timeline")
|
|
108
|
+
ws_timeline.cell(row=1, column=1, value="Sprint").font = Font(bold=True)
|
|
109
|
+
ws_timeline.cell(row=1, column=2, value="Milestone").font = Font(bold=True)
|
|
110
|
+
|
|
111
|
+
out = Path(output_path)
|
|
112
|
+
out.parent.mkdir(parents=True, exist_ok=True)
|
|
113
|
+
wb.save(str(out))
|
|
114
|
+
print(f"Saved: {out}")
|
|
115
|
+
|
|
116
|
+
generate_workbook(f"deliverables/{workflow_id}/main/report.xlsx", "wf-001")
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Font override note:** openpyxl defaults to Calibri 11. Override to match client brand:
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
cell.font = Font(bold=True, name="Inter", size=12, color="1F2937")
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
### Pattern 2 — PDF via Pandoc
|
|
128
|
+
|
|
129
|
+
Use for: narrative reports, executive memos, final deliverable documents.
|
|
130
|
+
|
|
131
|
+
**Primary path (requires LaTeX / xelatex):**
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
pandoc input.md \
|
|
135
|
+
-o deliverables/<workflow-id>/<persona-set>/report.pdf \
|
|
136
|
+
--pdf-engine=xelatex \
|
|
137
|
+
--variable=mainfont:"Inter" \
|
|
138
|
+
--variable=geometry:margin=2.5cm \
|
|
139
|
+
--variable=fontsize:11pt \
|
|
140
|
+
--toc \
|
|
141
|
+
--toc-depth=2
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Alternative path (headless Chrome — no LaTeX dependency):**
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
# Step 1: convert md to self-contained HTML
|
|
148
|
+
pandoc input.md -o /tmp/orchestrator-artifact-gen/report.html --standalone
|
|
149
|
+
|
|
150
|
+
# Step 2: render HTML to PDF with Chromium headless
|
|
151
|
+
chromium-browser --headless --disable-gpu \
|
|
152
|
+
--print-to-pdf=deliverables/<workflow-id>/<persona-set>/report.pdf \
|
|
153
|
+
/tmp/orchestrator-artifact-gen/report.html
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Choose the Chromium alternative when the environment lacks LaTeX or when the client brand uses web fonts unavailable in TeX font registries.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
### Pattern 3 — CSV Issue Tree (Python csv module)
|
|
161
|
+
|
|
162
|
+
Use for: machine-readable issue trees, structured hypothesis logs, evidence tracking.
|
|
163
|
+
|
|
164
|
+
Row schema: `id, parent_id, depth, branch, hypothesis, evidence_status`
|
|
165
|
+
|
|
166
|
+
Valid `evidence_status` values: `validated`, `pending`, `disproven`
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
import csv
|
|
170
|
+
from pathlib import Path
|
|
171
|
+
|
|
172
|
+
ISSUE_TREE_SCHEMA = ["id", "parent_id", "depth", "branch", "hypothesis", "evidence_status"]
|
|
173
|
+
|
|
174
|
+
def write_issue_tree(rows: list[dict], output_path: str) -> None:
|
|
175
|
+
out = Path(output_path)
|
|
176
|
+
out.parent.mkdir(parents=True, exist_ok=True)
|
|
177
|
+
|
|
178
|
+
with out.open("w", newline="", encoding="utf-8") as fh:
|
|
179
|
+
writer = csv.DictWriter(fh, fieldnames=ISSUE_TREE_SCHEMA)
|
|
180
|
+
writer.writeheader()
|
|
181
|
+
for row in rows:
|
|
182
|
+
# Validate evidence_status before writing
|
|
183
|
+
if row["evidence_status"] not in ("validated", "pending", "disproven"):
|
|
184
|
+
raise ValueError(f"Invalid evidence_status: {row['evidence_status']}")
|
|
185
|
+
writer.writerow(row)
|
|
186
|
+
|
|
187
|
+
print(f"Issue tree written: {out} ({len(rows)} rows)")
|
|
188
|
+
|
|
189
|
+
# Example usage
|
|
190
|
+
sample_rows = [
|
|
191
|
+
{"id": "H1", "parent_id": "", "depth": 0, "branch": "root", "hypothesis": "Revenue gap is structural", "evidence_status": "pending"},
|
|
192
|
+
{"id": "H1.1", "parent_id": "H1", "depth": 1, "branch": "market", "hypothesis": "Addressable market is shrinking", "evidence_status": "disproven"},
|
|
193
|
+
{"id": "H1.2", "parent_id": "H1", "depth": 1, "branch": "pricing", "hypothesis": "Price elasticity is negative", "evidence_status": "validated"},
|
|
194
|
+
]
|
|
195
|
+
write_issue_tree(sample_rows, "deliverables/wf-001/squad1/issue-tree.csv")
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
### Pattern 4 — Jinja2 Master Template
|
|
201
|
+
|
|
202
|
+
Use for: parametric Word-like docs, email templates, markdown reports with injected data blocks.
|
|
203
|
+
|
|
204
|
+
```python
|
|
205
|
+
from jinja2 import Environment, FileSystemLoader, StrictUndefined
|
|
206
|
+
from pathlib import Path
|
|
207
|
+
|
|
208
|
+
def render_template(
|
|
209
|
+
template_dir: str,
|
|
210
|
+
template_name: str,
|
|
211
|
+
context: dict,
|
|
212
|
+
output_path: str,
|
|
213
|
+
) -> None:
|
|
214
|
+
# autoescape=False is intentional for markdown/plain-text templates.
|
|
215
|
+
# Set autoescape=True only when rendering HTML destined for a browser.
|
|
216
|
+
env = Environment(
|
|
217
|
+
loader=FileSystemLoader(template_dir),
|
|
218
|
+
undefined=StrictUndefined, # raises on missing variables — no silent blanks
|
|
219
|
+
autoescape=False,
|
|
220
|
+
)
|
|
221
|
+
template = env.get_template(template_name)
|
|
222
|
+
rendered = template.render(**context)
|
|
223
|
+
|
|
224
|
+
out = Path(output_path)
|
|
225
|
+
out.parent.mkdir(parents=True, exist_ok=True)
|
|
226
|
+
out.write_text(rendered, encoding="utf-8")
|
|
227
|
+
print(f"Template rendered: {out}")
|
|
228
|
+
|
|
229
|
+
# Template file convention: .claude/skills/artifact-generator/templates/<name>.md.j2
|
|
230
|
+
render_template(
|
|
231
|
+
template_dir=".claude/skills/artifact-generator/templates",
|
|
232
|
+
template_name="executive-summary.md.j2",
|
|
233
|
+
context={
|
|
234
|
+
"workflow_id": "wf-001",
|
|
235
|
+
"client_name": "Acme Corp",
|
|
236
|
+
"date": "2026-05-12",
|
|
237
|
+
"findings": ["Finding A", "Finding B"],
|
|
238
|
+
},
|
|
239
|
+
output_path="deliverables/wf-001/main/executive-summary.md",
|
|
240
|
+
)
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
**Template file path convention:** `<skill-dir>/templates/<name>.md.j2`
|
|
244
|
+
|
|
245
|
+
**Escaping rules:**
|
|
246
|
+
|
|
247
|
+
| Scenario | `autoescape` setting |
|
|
248
|
+
|----------|---------------------|
|
|
249
|
+
| Markdown / plain text output | `False` |
|
|
250
|
+
| HTML output to browser | `True` |
|
|
251
|
+
| Jinja tags inside strings | Use `{% raw %}...{% endraw %}` blocks |
|
|
252
|
+
|
|
253
|
+
**`StrictUndefined` is mandatory.** It turns missing template variables into errors instead of silent empty strings, which would corrupt client deliverables.
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Validation Post-Generation
|
|
258
|
+
|
|
259
|
+
Run these checks after every generated artifact before calling `artifactStore`.
|
|
260
|
+
|
|
261
|
+
### xlsx integrity
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
python3 -c "
|
|
265
|
+
import openpyxl, sys
|
|
266
|
+
path = sys.argv[1]
|
|
267
|
+
wb = openpyxl.load_workbook(path)
|
|
268
|
+
print(f'Sheets: {wb.sheetnames}')
|
|
269
|
+
print('OK — workbook valid')
|
|
270
|
+
" deliverables/<workflow-id>/<persona-set>/report.xlsx
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
The command must exit 0 and print sheet names. Any exception indicates a corrupt file — regenerate before storing.
|
|
274
|
+
|
|
275
|
+
### PDF integrity
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
# pdfinfo is part of poppler-utils
|
|
279
|
+
pdfinfo deliverables/<workflow-id>/<persona-set>/report.pdf | grep Pages
|
|
280
|
+
# Expected output: Pages: N (where N > 0)
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
If `pdfinfo` is unavailable, fall back to:
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
python3 -c "
|
|
287
|
+
import pathlib, sys
|
|
288
|
+
p = pathlib.Path(sys.argv[1])
|
|
289
|
+
assert p.exists() and p.stat().st_size > 1024, 'PDF missing or suspiciously small'
|
|
290
|
+
print(f'Size: {p.stat().st_size} bytes — plausible PDF')
|
|
291
|
+
" deliverables/<workflow-id>/<persona-set>/report.pdf
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### CSV issue tree completeness
|
|
295
|
+
|
|
296
|
+
```python
|
|
297
|
+
import csv
|
|
298
|
+
|
|
299
|
+
REQUIRED_FIELDS = {"id", "parent_id", "depth", "branch", "hypothesis", "evidence_status"}
|
|
300
|
+
|
|
301
|
+
with open("deliverables/<workflow-id>/<persona-set>/issue-tree.csv", encoding="utf-8") as fh:
|
|
302
|
+
reader = csv.DictReader(fh)
|
|
303
|
+
assert set(reader.fieldnames or []) >= REQUIRED_FIELDS, "Missing required columns"
|
|
304
|
+
rows = list(reader)
|
|
305
|
+
assert len(rows) > 0, "Issue tree is empty"
|
|
306
|
+
print(f"CSV valid — {len(rows)} rows, all required columns present")
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Jinja2 rendered output
|
|
310
|
+
|
|
311
|
+
After rendering, assert that expected section headers are present:
|
|
312
|
+
|
|
313
|
+
```python
|
|
314
|
+
text = pathlib.Path("deliverables/<workflow-id>/main/executive-summary.md").read_text()
|
|
315
|
+
required_sections = ["## Executive Summary", "## Key Findings", "## Recommendations"]
|
|
316
|
+
for section in required_sections:
|
|
317
|
+
assert section in text, f"Missing section: {section}"
|
|
318
|
+
print("All required sections present")
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
## Output Location Conventions
|
|
324
|
+
|
|
325
|
+
| Category | Path pattern |
|
|
326
|
+
|----------|-------------|
|
|
327
|
+
| Client-facing deliverable | `deliverables/<workflow-id>/<persona-set>/<artifact-name>.<ext>` |
|
|
328
|
+
| Working scratch / intermediates | `/tmp/orchestrator-artifact-gen/<workflow-id>/` |
|
|
329
|
+
|
|
330
|
+
**Path rules:**
|
|
331
|
+
|
|
332
|
+
- `<workflow-id>` is the active workflow UUID (e.g., `7c28e523-14c9-4807-be56-f9e1ed52ff38`)
|
|
333
|
+
- `<persona-set>` is a short slug grouping by audience (e.g., `executive`, `squad1`, `main`)
|
|
334
|
+
- `<artifact-name>` is kebab-case, descriptive (e.g., `issue-tree`, `executive-summary`, `sprint-schedule`)
|
|
335
|
+
|
|
336
|
+
**Cleanup scratch directory** at skill completion:
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
rm -rf /tmp/orchestrator-artifact-gen/<workflow-id>/
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
Do not leave intermediate files in `/tmp` after the deliverable is stored in MinIO.
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## Audit Trail Requirements
|
|
347
|
+
|
|
348
|
+
Every generated client-facing artifact MUST be persisted via `mcp__orchestrator-extended__artifactStore` with `artifact_kind: deliverable`. The local file under `deliverables/` is a convenience copy only — it may be deleted; the MinIO record is authoritative.
|
|
349
|
+
|
|
350
|
+
```
|
|
351
|
+
# Step 1: load the tool schema (deferred-load pattern — TD-098)
|
|
352
|
+
ToolSearch("select:mcp__orchestrator-extended__artifactStore")
|
|
353
|
+
|
|
354
|
+
# Step 2: store the artifact
|
|
355
|
+
mcp__orchestrator-extended__artifactStore({
|
|
356
|
+
workflowId: "<workflow-id>",
|
|
357
|
+
phase: "implement", # or the PME phase that produced this artifact
|
|
358
|
+
type: "deliverable",
|
|
359
|
+
content: "<base64 or text content>",
|
|
360
|
+
metadata: {
|
|
361
|
+
artifact_kind: "deliverable",
|
|
362
|
+
format: "xlsx", # or pdf, csv, docx, html
|
|
363
|
+
persona_set: "<persona-set>",
|
|
364
|
+
local_path: "deliverables/<workflow-id>/<persona-set>/<name>.<ext>",
|
|
365
|
+
generated_by: "artifact-generator",
|
|
366
|
+
s178_stack: "openpyxl+pandoc+jinja2"
|
|
367
|
+
}
|
|
368
|
+
})
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
**Never skip this step.** Deliverables that exist only on disk are lost at container restart and leave no traceability in the workflow audit log.
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
## Common Gotchas
|
|
376
|
+
|
|
377
|
+
| Gotcha | Symptom | Fix |
|
|
378
|
+
|--------|---------|-----|
|
|
379
|
+
| Pandoc + non-ASCII chars crash xelatex | PDF generation exits non-zero; log shows `! Package inputenc Error` | Add `--pdf-engine=xelatex` and `--variable=mainfont:"Noto Serif"`. Latin Modern (LaTeX default) chokes on Unicode outside Latin-1. |
|
|
380
|
+
| openpyxl default font differs from brand | Client notices font mismatch (Calibri instead of Inter/Helvetica) | Explicitly set `Font(name="Inter", size=11)` on all header and body cells; openpyxl does not inherit theme fonts. |
|
|
381
|
+
| Jinja2 silently blanks missing variables | Template renders with empty sections, no error thrown | Use `StrictUndefined` — this turns missing vars into `UndefinedError` at render time (see Pattern 4). |
|
|
382
|
+
| jinja2 escaping corrupts Markdown | Underscores and angle brackets get HTML-entity-encoded (`<`, `_`) | Pass `autoescape=False` for Markdown/plain-text templates. Only enable `autoescape=True` for HTML browser output. |
|
|
383
|
+
| Pandoc Chromium path varies by OS | `--print-to-pdf` fails because `chromium-browser` not in PATH | Try `chromium`, `google-chrome`, or `google-chrome-stable` depending on distro; check with `which chromium chromium-browser google-chrome`. |
|
|
384
|
+
| xlsx saved before directory exists | `FileNotFoundError` on `wb.save()` | Always call `Path(output_path).parent.mkdir(parents=True, exist_ok=True)` before saving. |
|
|
385
|
+
| Large xlsx hits memory limit | `MemoryError` on files with 100k+ rows | Use `openpyxl.Workbook(write_only=True)` and `ws.append()` in streaming mode. |
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: brainstorm-formalize
|
|
3
|
+
description: Transform brainstorm output into formal documents (RFC/ADR/TD). Use after brainstorm completion when user approves the design.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Skill: brainstorm-formalize
|
|
7
|
+
|
|
8
|
+
## When to Load
|
|
9
|
+
|
|
10
|
+
Load this skill when:
|
|
11
|
+
- A brainstorm session has just completed AND the user approves formalizing the result
|
|
12
|
+
- The user says "formalize this brainstorm" or "turn this into an RFC/ADR/TD"
|
|
13
|
+
- The user explicitly invokes `/brainstorm-formalize`
|
|
14
|
+
|
|
15
|
+
Do NOT load automatically during a brainstorm — wait for explicit user approval.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Step 1 — Classification
|
|
20
|
+
|
|
21
|
+
Ask the user which document type fits the brainstorm output:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
AskUserQuestion({
|
|
25
|
+
question: "Brainstorm complete. What type of formal document should this become?",
|
|
26
|
+
options: [
|
|
27
|
+
"RFC — Request for Comments (proposal BEFORE implementation, requires community review)",
|
|
28
|
+
"ADR — Architecture Decision Record (documents a decision ALREADY made)",
|
|
29
|
+
"TD — Technical Debt item (tracks a known issue or improvement needed)",
|
|
30
|
+
"Keep as design.md — informal design note, no registry entry needed"
|
|
31
|
+
]
|
|
32
|
+
})
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Wait for user selection before proceeding.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Step 2 — Document Creation
|
|
40
|
+
|
|
41
|
+
### Auto-ID Assignment
|
|
42
|
+
|
|
43
|
+
Before creating any document, check the last used ID:
|
|
44
|
+
- For RFC: Read `project-guidelines/rfcs/index.md`, find the highest `RFC-NNN` in the table, increment by 1
|
|
45
|
+
- For ADR: Read `project-guidelines/adrs/index.md`, find the highest `ADR-NNN` in the Operational ADRs table, increment by 1
|
|
46
|
+
- For TD: Check `project-guidelines/BACKLOG.md` for the highest `TD-NNN` in use
|
|
47
|
+
|
|
48
|
+
### RFC Frontmatter Template
|
|
49
|
+
|
|
50
|
+
```markdown
|
|
51
|
+
---
|
|
52
|
+
type: rfc
|
|
53
|
+
id: RFC-NNN
|
|
54
|
+
title: "[Title from brainstorm]"
|
|
55
|
+
status: PROPOSED
|
|
56
|
+
created: YYYY-MM-DD
|
|
57
|
+
updated: YYYY-MM-DD
|
|
58
|
+
layers:
|
|
59
|
+
- [domain|application|infrastructure|presentation]
|
|
60
|
+
sub_layers:
|
|
61
|
+
- [hooks|skills|agents|memory|api|cli]
|
|
62
|
+
related:
|
|
63
|
+
- [RFC-XXX|ADR-XXX if relevant]
|
|
64
|
+
implements: []
|
|
65
|
+
resolves: []
|
|
66
|
+
supersedes: []
|
|
67
|
+
absorbs: []
|
|
68
|
+
depends_on:
|
|
69
|
+
- [RFC-XXX|ADR-XXX if relevant]
|
|
70
|
+
health:
|
|
71
|
+
last_scan:
|
|
72
|
+
lims: []
|
|
73
|
+
score:
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
# RFC-NNN: [Title]
|
|
77
|
+
|
|
78
|
+
**Status:** PROPOSED
|
|
79
|
+
**Version:** 1.0.0
|
|
80
|
+
**Date:** YYYY-MM-DD
|
|
81
|
+
**Author:** Main Orchestrator + User (brainstorm)
|
|
82
|
+
**Target Version:** vX.Y.Z+
|
|
83
|
+
**Depends On:** [or None]
|
|
84
|
+
**Brainstorm:** `docs/superpowers/specs/YYYY-MM-DD-rfcNNN-[slug].md`
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
File location: `project-guidelines/rfcs/RFC-NNN-TITLE-SLUG.md`
|
|
88
|
+
|
|
89
|
+
### ADR Frontmatter Template
|
|
90
|
+
|
|
91
|
+
```markdown
|
|
92
|
+
---
|
|
93
|
+
type: adr
|
|
94
|
+
id: ADR-NNN
|
|
95
|
+
title: "[Title from brainstorm]"
|
|
96
|
+
status: proposed
|
|
97
|
+
created: YYYY-MM-DD
|
|
98
|
+
updated: YYYY-MM-DD
|
|
99
|
+
layers: []
|
|
100
|
+
sub_layers: []
|
|
101
|
+
related: []
|
|
102
|
+
depends_on: []
|
|
103
|
+
health:
|
|
104
|
+
last_scan:
|
|
105
|
+
lims: []
|
|
106
|
+
score:
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
# ADR-NNN: [Title]
|
|
110
|
+
|
|
111
|
+
**Date:** YYYY-MM-DD
|
|
112
|
+
**Status:** Proposed
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Follow with standard ADR sections: Contexto, Decisão, Consequências (Positivas / Negativas), Alternativas Consideradas.
|
|
116
|
+
|
|
117
|
+
File location: `project-guidelines/adrs/ADR-NNN-TITLE-SLUG.md`
|
|
118
|
+
|
|
119
|
+
### TD Entry Template
|
|
120
|
+
|
|
121
|
+
TD items live in `project-guidelines/BACKLOG.md`. Add a new entry in the appropriate priority section:
|
|
122
|
+
|
|
123
|
+
```markdown
|
|
124
|
+
### TD-NNN — [Short Title] (MEDIUM|HIGH|LOW, Nh)
|
|
125
|
+
**Symptom:** [What is observed]
|
|
126
|
+
**Root cause:** [Why it happens]
|
|
127
|
+
**Fix:** [Proposed solution]
|
|
128
|
+
**Origin:** Brainstorm `docs/superpowers/specs/YYYY-MM-DD-[slug].md`
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### design.md Template
|
|
132
|
+
|
|
133
|
+
If the user chooses to keep it informal:
|
|
134
|
+
|
|
135
|
+
```markdown
|
|
136
|
+
# Design: [Title]
|
|
137
|
+
|
|
138
|
+
**Date:** YYYY-MM-DD
|
|
139
|
+
**Status:** Draft
|
|
140
|
+
**Origin:** `docs/superpowers/specs/YYYY-MM-DD-[slug].md`
|
|
141
|
+
|
|
142
|
+
## Summary
|
|
143
|
+
[Key decisions from the brainstorm]
|
|
144
|
+
|
|
145
|
+
## Open Questions
|
|
146
|
+
[Items that need resolution before implementation]
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
File location: `docs/designs/YYYY-MM-DD-[title-slug].md`
|
|
150
|
+
Create the directory if it does not exist: `mkdir -p docs/designs/`
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Step 3 — Auto-Indexation
|
|
155
|
+
|
|
156
|
+
After creating the document file, add a line to the appropriate index.
|
|
157
|
+
|
|
158
|
+
### RFC Index Line Format
|
|
159
|
+
|
|
160
|
+
Open `project-guidelines/rfcs/index.md` and add a new row to the "RFCs Ativas" table:
|
|
161
|
+
|
|
162
|
+
```
|
|
163
|
+
| [RFC-NNN](./RFC-NNN-TITLE-SLUG.md) | [Title] | **PROPOSED** | vX.Y.Z+ |
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
The table has 4 columns: RFC | Título | Status | Versão Target.
|
|
167
|
+
Add the new row AFTER the last existing RFC row (before the closing `---`).
|
|
168
|
+
|
|
169
|
+
### ADR Index Line Format
|
|
170
|
+
|
|
171
|
+
Open `project-guidelines/adrs/index.md` and add a new row to the "Operational ADRs" table:
|
|
172
|
+
|
|
173
|
+
```
|
|
174
|
+
| [ADR-NNN](./ADR-NNN-TITLE-SLUG.md) | [Title] | YYYY-MM-DD | **Proposed** |
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
The table has 4 columns: ADR | Título | Data | Status.
|
|
178
|
+
|
|
179
|
+
### TD / design.md
|
|
180
|
+
|
|
181
|
+
No index entry needed — TDs live in BACKLOG.md directly, and design.md files are self-contained.
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Step 4 — Sprint Decomposition
|
|
186
|
+
|
|
187
|
+
If the brainstorm produced a multi-sprint implementation plan, add a sprint table to the new document:
|
|
188
|
+
|
|
189
|
+
```markdown
|
|
190
|
+
## Sprint Decomposition
|
|
191
|
+
|
|
192
|
+
| Sprint | Scope | Estimate | Status | Deliverables |
|
|
193
|
+
|--------|-------|----------|--------|--------------|
|
|
194
|
+
| S1 | [Scope of sprint 1] | Xh | PROPOSED | [Key deliverable] |
|
|
195
|
+
| S2 | [Scope of sprint 2] | Xh | PROPOSED | [Key deliverable] |
|
|
196
|
+
| SN | [Scope of sprint N] | Xh | PROPOSED | [Key deliverable] |
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Guidelines for sprint sizing:
|
|
200
|
+
- Target 4-8h per sprint for a single implementer session
|
|
201
|
+
- Each sprint should have at least one concrete, testable deliverable
|
|
202
|
+
- Dependent sprints must be ordered (no circular dependencies)
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## Step 5 — Reference Link
|
|
207
|
+
|
|
208
|
+
Add a `## Brainstorm Reference` section at the END of the new formal document linking back to the brainstorm source:
|
|
209
|
+
|
|
210
|
+
```markdown
|
|
211
|
+
## Brainstorm Reference
|
|
212
|
+
|
|
213
|
+
**Source:** `docs/superpowers/specs/YYYY-MM-DD-[slug].md`
|
|
214
|
+
|
|
215
|
+
The brainstorm session that originated this document is preserved at the path above.
|
|
216
|
+
This allows tracing design decisions back to the original exploration.
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
This creates a bidirectional link: formal doc → brainstorm source.
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## Step 6 — Sprint Context Seed
|
|
224
|
+
|
|
225
|
+
After the formal document is created and indexed, seed the sprint context file so that future brainstorm sessions for this RFC's sprints automatically receive parent document context.
|
|
226
|
+
|
|
227
|
+
Create `.claude/sprint-context/{workflowId}.json` with this exact schema:
|
|
228
|
+
|
|
229
|
+
```json
|
|
230
|
+
{
|
|
231
|
+
"schema": "1.0",
|
|
232
|
+
"parentDocument": "project-guidelines/rfcs/RFC-NNN-TITLE-SLUG.md",
|
|
233
|
+
"sprintIndex": 1,
|
|
234
|
+
"sprintScope": "[Sprint 1 scope from Step 4 table]",
|
|
235
|
+
"previousSprints": [],
|
|
236
|
+
"workflowId": "{currentWorkflowId}",
|
|
237
|
+
"createdAt": "{ISO-8601 timestamp}"
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Field notes:
|
|
242
|
+
- `schema`: always `"1.0"` for this version
|
|
243
|
+
- `parentDocument`: relative path from project root to the RFC/ADR file
|
|
244
|
+
- `sprintIndex`: the NEXT sprint to be executed (start at 1 for a new document)
|
|
245
|
+
- `sprintScope`: copy from the Sprint Decomposition table (Step 4)
|
|
246
|
+
- `previousSprints`: empty array for a brand-new document
|
|
247
|
+
- `workflowId`: the current active workflow ID (from MCP tools or workflow state)
|
|
248
|
+
- `createdAt`: current UTC timestamp in ISO-8601 format
|
|
249
|
+
|
|
250
|
+
The file is written to `.claude/sprint-context/` in the project root. The `writeSprintContext` helper in `.claude/hooks/lib/sprint-context.ts` can be called programmatically if running in a hook context. Otherwise, create the JSON file directly.
|
|
251
|
+
|
|
252
|
+
**Update for subsequent sprints:** When a sprint completes, update this file:
|
|
253
|
+
- Increment `sprintIndex` to the next sprint
|
|
254
|
+
- Update `sprintScope` to the next sprint scope
|
|
255
|
+
- Append the completed sprint to `previousSprints`:
|
|
256
|
+
```json
|
|
257
|
+
{ "index": N, "status": "complete", "deliverables": ["file1.ts", "SKILL.md"] }
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## Completion Checklist
|
|
263
|
+
|
|
264
|
+
Before considering formalization complete:
|
|
265
|
+
|
|
266
|
+
- [ ] Document file created with correct frontmatter
|
|
267
|
+
- [ ] Correct ID assigned (no collision with existing IDs)
|
|
268
|
+
- [ ] Added to index.md (RFC or ADR)
|
|
269
|
+
- [ ] Sprint Decomposition table included (if multi-sprint)
|
|
270
|
+
- [ ] Brainstorm Reference section added
|
|
271
|
+
- [ ] `.claude/sprint-context/{workflowId}.json` seeded
|
|
272
|
+
- [ ] User notified of file path and next step (e.g. "Start Sprint 1 workflow")
|