Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 136 additions & 0 deletions scripts/generate-template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#!/usr/bin/env python3
"""Generate a quality-verified HTML artifact from a pre-built template YAML."""

from __future__ import annotations
import argparse, json, subprocess, sys, tempfile, re
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
TEMPLATES_DIR = ROOT / "templates" / "prebuilt"

def validate(data: dict, schema: dict) -> list[str]:
errors = []
for key, spec in schema.items():
if spec.get("required") and key not in data:
errors.append(f"Missing required field: {key}")
if key in data:
if spec["type"] == "array" and not isinstance(data[key], list):
errors.append(f"{key} must be an array")
if spec["type"] == "integer" and not isinstance(data[key], int):
errors.append(f"{key} must be an integer")
return errors

def generate(artifact_path: Path, template_data: dict) -> str:
"""Generate HTML from template data. Returns artifact path."""
title = template_data.get("title", "Generated Artifact")
options = template_data.get("options", [])
recommendation = template_data.get("recommendation", "")
next_action = template_data.get("next_action", "")

rows = ""
for opt in options:
risk_list = "<ul>" + "".join(f"<li>{r}</li>" for r in opt.get("risks", [])) + "</ul>"
evidence_list = "<ul>" + "".join(f"<li>{e}</li>" for e in opt.get("evidence", [])) + "</ul>"
rows += f"""<tr>
<td>{opt.get("name", "")}</td>
<td style="font-weight:900;font-size:1.4em;color:var(--good,#166534)">{opt.get("score", 0)}</td>
<td>{risk_list}</td>
<td>{evidence_list}</td>
</tr>"""

html = f"""<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{title}</title>
<style>
:root{{--bg:#f8fafc;--panel:#fff;--ink:#111827;--muted:#64748b;--line:#cbd5e1;--good:#166534}}
@media(prefers-color-scheme:dark){{:root{{--bg:#0f172a;--panel:#111827;--ink:#e5e7eb;--muted:#94a3b8;--line:#334155;--good:#86efac}}}}
*{{box-sizing:border-box}}body{{margin:0;background:var(--bg);color:var(--ink);font-family:system-ui,sans-serif}}
.wrap{{max-width:900px;margin:auto;padding:24px}}
header{{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:20px;margin:16px 0}}
table{{width:100%;border-collapse:collapse;background:var(--panel);border-radius:12px;overflow:hidden}}
th{{background:var(--ink);color:var(--panel);padding:10px 14px;text-align:left;font-size:.85em;text-transform:uppercase;letter-spacing:.05em}}
td{{padding:12px 14px;border-bottom:1px solid var(--line);vertical-align:top}}
tr:last-child td{{border-bottom:none}}
</style>
</head>
<body>
<div class="wrap">
<header>
<h1>{title}</h1>
</header>
<table>
<thead><tr><th>Option</th><th>Score</th><th>Risks</th><th>Evidence</th></tr></thead>
<tbody>{rows}</tbody>
</table>
<section style="background:#dcfce7;padding:16px;border-radius:12px;margin:16px 0">
<strong>Recommendation:</strong> {recommendation}
</section>
<section style="background:#fef3c7;padding:16px;border-radius:12px;margin:16px 0">
<strong>Next action:</strong> {next_action}
</section>
</div>
</body></html>"""

out = artifact_path or Path(tempfile.mktemp(suffix=".html", prefix="template-"))
out.write_text(html)
return out

def main() -> int:
parser = argparse.ArgumentParser(description="Generate artifact from pre-built template YAML")
parser.add_argument("action", choices=["generate", "validate", "list-templates"])
parser.add_argument("template", nargs="?", help="Template name (e.g. decision-deck)")
parser.add_argument("data", nargs="?", help="Path to data YAML file")
args = parser.parse_args()

if args.action == "list-templates":
for f in sorted(TEMPLATES_DIR.glob("*.yaml")):
data = json.loads(f.read_text())
print(f" {data[\"name\"]}: {data[\"description\"]}")
return 0

if args.action == "validate":
if not args.template or not args.data:
print("Usage: generate-template.py validate <template> <data.yaml>")
return 1
tmpl_path = TEMPLATES_DIR / f"{args.template}.yaml"
if not tmpl_path.exists():
print(f"Template not found: {args.template}")
return 1
tmpl = json.loads(tmpl_path.read_text())
data = json.loads(Path(args.data).read_text())
errors = validate(data, tmpl.get("schema", {}))
if errors:
for e in errors: print(f"ERROR: {e}")
return 1
print("Validation passed")
return 0

if args.action == "generate":
if not args.template or not args.data:
print("Usage: generate-template.py generate <template> <data.yaml>")
return 1
tmpl_path = TEMPLATES_DIR / f"{args.template}.yaml"
if not tmpl_path.exists():
print(f"Template not found: {args.template}")
return 1
tmpl = json.loads(tmpl_path.read_text())
data = json.loads(Path(args.data).read_text())
errors = validate(data, tmpl.get("schema", {}))
if errors:
for e in errors: print(f"ERROR: {e}")
return 1
out_path = generate(None, data)
# Run deliver-artifact.py
result = subprocess.run([sys.executable, str(ROOT/"scripts/deliver-artifact.py"),
str(out_path), "--json"], capture_output=True, text=True)
score = json.loads(result.stdout)["score"] if result.returncode == 0 else 0
print(f"Generated: {out_path} (score: {score}/100)")
return 0

return 0

if __name__ == "__main__":
raise SystemExit(main())
17 changes: 17 additions & 0 deletions scripts/validate-templates.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash
# Validate all pre-built templates
set -e
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ROOT="$(dirname "$SCRIPT_DIR")"
TEMPLATES="$ROOT/templates/prebuilt"

echo "Validating pre-built templates..."

for yaml in "$TEMPLATES"/*.yaml; do
name=$(basename "$yaml" .yaml)
echo "Checking: $name"
# Verify template has required schema fields
python3 -c "import json,sys; d=json.load(open('$yaml')); assert 'name' in d; assert 'schema' in d; print(f' OK: {d[\"name\"]} - {d[\"description\"]}')"
done

echo "All templates validated."
46 changes: 46 additions & 0 deletions templates/prebuilt/architecture-review.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: architecture-review
version: "1.0"
description: "System or module architecture with connections, boundaries, and trade-offs"

input_schema:
title:
type: string
required: true
components:
type: array
required: true
items: string
connections:
type: array
required: true
items: string
trade_offs:
type: array
required: true
items: string
next_action:
type: string
required: true

example:
title: "E-commerce Platform Architecture v2"
components:
- "Frontend (React, CDN-distributed)"
- "API Gateway (Kong, handles auth/rate-limit)"
- "Order Service (Node.js, event-driven)"
- "Inventory Service (Go, CRDT-based)"
- "Payment Service (External, PCI-DSS compliant)"
- "Postgres (primary DB, async replication)"
- "Redis (cache + session store)"
connections:
- "Frontend -> API Gateway (HTTPS, REST)"
- "API Gateway -> Order Service (HTTP, REST)"
- "Order Service -> Inventory Service (Event bus: Kafka)"
- "Order Service -> Payment Service (gRPC, sync)"
- "Order Service -> Postgres (SQL)"
- "All services -> Redis (caching)"
trade_offs:
- "Event-driven inventory (consistency) vs eventual consistency model"
- "Microservices (scalability) vs operational complexity"
- "PCI-DSS external payment (compliance) vs vendor lock-in risk"
next_action: "Add integration tests for Order -> Inventory event flow before Q3 launch"
38 changes: 38 additions & 0 deletions templates/prebuilt/audit-report.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: audit-report
version: "1.0"
description: "Security or process audit with findings, severity levels, and recommended actions"

input_schema:
title:
type: string
required: true
scope:
type: string
required: true
findings:
type: array
required: true
items: string
severity:
type: string
required: true
description: "Overall severity: critical/high/medium/low"
recommended_actions:
type: array
required: true
items: string

example:
title: "Q2 Security Audit: Authentication System"
scope: "Auth service, token storage, session management, OAuth flows"
findings:
- "Refresh token rotation not implemented - tokens valid for 30 days without rotation"
- "Session invalidation endpoint missing - no way to revoke sessions on password change"
- "Rate limiting on /auth endpoint is 1000 req/min per IP - no per-user limiting"
- "Token storage uses local filesystem - not suitable for multi-instance deployments"
severity: "high"
recommended_actions:
- "Implement refresh token rotation within 2 weeks (CRITICAL)"
- "Add session invalidation endpoint before next release"
- "Add per-user rate limiting as defense-in-depth"
- "Move token storage to Redis for multi-instance support"
49 changes: 49 additions & 0 deletions templates/prebuilt/decision-deck.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: decision-deck
version: "1.0"
description: "Compare 2-4 options with scores, risks, evidence, and a recommendation"

input_schema:
title:
type: string
required: true
description: "Decision question or title"
options:
type: array
required: true
min_items: 2
max_items: 4
items:
name: string
score: integer
risks: list
evidence: list
recommendation:
type: string
required: true
description: "Recommended option with rationale"
next_action:
type: string
required: true
description: "What to do next"

example:
title: "Which deployment strategy for the new API gateway?"
options:
- name: "Blue-green"
score: 88
risks:
- "Cost of standby environment"
- "Traffic routing complexity"
evidence:
- "Industry standard for zero-downtime"
- "Netflix uses this"
- name: "Canary"
score: 92
risks:
- "Requires traffic splitting infrastructure"
- "Harder to roll back quickly"
evidence:
- "GitHub uses canary"
- "Lower blast radius on failure"
recommendation: "Use canary - lower risk, better observability, fits our infra"
next_action: "Create infra ticket for traffic splitting, estimate 2 weeks"
45 changes: 45 additions & 0 deletions templates/prebuilt/diff-review.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: diff-review
version: "1.0"
description: "PR or change review with annotated files, inline comments, and approval signals"

input_schema:
title:
type: string
required: true
description: "PR title or change description"
pr_number:
type: integer
required: true
description: "Pull request or issue number"
files_changed:
type: array
required: true
description: "List of files modified"
items: string
summary:
type: string
required: true
description: "What this change does"
risks:
type: array
required: true
description: "Potential risks or concerns"
items: string
approval:
type: string
required: true
description: "Approval recommendation"

example:
title: "Refactor auth module to support OAuth 2.0"
pr_number: 142
files_changed:
- "src/auth/index.ts"
- "src/auth/oauth.ts"
- "src/auth/token-store.ts"
- "tests/auth/oauth.test.ts"
summary: "Replaces legacy session-based auth with OAuth 2.0 + refresh token rotation. Maintains backward compatibility via feature flag."
risks:
- "Token rotation logic is complex - edge cases around concurrent refresh requests"
- "Session invalidation may affect existing logged-in users during rollout"
approval: "LGTM with conditions: (1) Add integration test for concurrent refresh, (2) Staged rollout via feature flag, (3) Monitor error rate for first 24h"
47 changes: 47 additions & 0 deletions templates/prebuilt/project-recap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: project-recap
version: "1.0"
description: "Sprint or milestone recap with progress, blockers, and next steps"

input_schema:
title:
type: string
required: true
description: "Project or team name"
sprint:
type: string
required: true
description: "Sprint or time period"
completed:
type: array
required: true
description: "Things completed this period"
items: string
blocked:
type: array
required: true
description: "Things blocked or at risk"
items: string
next_steps:
type: array
required: true
description: "Next actions for next period"
items: string
team:
type: string
required: false
description: "Team or team members"

example:
title: "Platform Engineering Q2 Recap"
sprint: "Sprint 14-15 (June 2026)"
completed:
- "Migrated auth service to OAuth 2.0"
- "Reduced API p99 latency from 450ms to 120ms"
- "Deployed feature flag infrastructure"
blocked:
- "Database migration blocked by vendor dependency (ETA: July)"
- "Mobile SDK v3 delayed by iOS signing certificate issues"
next_steps:
- "Complete database migration in Sprint 16"
- "Ship mobile SDK v3 by July 15"
team: "Platform Engineering (5 engineers)"
Loading