diff --git a/wizard-work/quill/CHECK-change-request-template-v1.0 b/wizard-work/quill/CHECK-change-request-template-v1.0 new file mode 100755 index 0000000..f6782ad --- /dev/null +++ b/wizard-work/quill/CHECK-change-request-template-v1.0 @@ -0,0 +1,118 @@ +#!/bin/bash +# CHECK change-request-template-v1.0 +# Verifies the draft artifact meets schema requirements. +# Exit 0 = PASS, 1 = FAIL, 2 = cannot grade (missing file). + +set -euo pipefail +FILE="/root/troupe-standup/wizard-work/quill/change-request-template-v1.0.md" + +if [ ! -f "$FILE" ]; then + echo "FAIL: artifact missing at $FILE" + exit 2 +fi + +FAIL=0 + +# 1. File size > 3000 bytes +BYTES=$(wc -c < "$FILE") +if [ "$BYTES" -lt 3000 ]; then + echo "FAIL: file too small ($BYTES bytes, minimum 3000)" + FAIL=1 +else + echo "PASS: size $BYTES bytes" +fi + +# 2. Required top-level sections (1-7) +for i in 1 2 3 4 5 6 7; do + if ! grep -q "^## ${i}\. " "$FILE"; then + echo "FAIL: missing section '## ${i}. '" + FAIL=1 + fi +done +grep -q "^## 1\. Purpose" "$FILE" && echo "PASS: section 1 present" || { echo "FAIL: section 1 missing"; FAIL=1; } +grep -q "^## 7\. Changelog" "$FILE" && echo "PASS: section 7 present" || { echo "FAIL: section 7 missing"; FAIL=1; } + +# 3. Fenced template block exists +if ! grep -q '```markdown' "$FILE"; then + echo "FAIL: no fenced template block" + FAIL=1 +else + echo "PASS: fenced template block present" +fi + +# 4. Required template fields present +for field in "Risk Level" "Window" "Summary" "Scope" "Validation" "Rollback" "Approval"; do + if ! grep -q "$field" "$FILE"; then + echo "FAIL: missing template field '$field'" + FAIL=1 + fi +done +grep -q "Risk Level" "$FILE" && echo "PASS: Risk Level field present" || FAIL=1 +grep -q "Low / Medium / High / Blocker" "$FILE" && echo "PASS: Risk Level enum defined" || FAIL=1 + +# 5. Example section present and free of unfilled placeholders +if ! grep -q "^## 6\. Example" "$FILE"; then + echo "FAIL: missing Example section" + FAIL=1 +else + echo "PASS: Example section present" +fi + +# Extract example block content: find fenced code block within Example section +EXAMPLE_BLOCK="" +IN_EXAMPLE=0 +IN_FENCE=0 +while IFS= read -r line; do + if [[ "$line" =~ ^##[[:space:]]+6\. ]]; then + IN_EXAMPLE=1 + elif [ "$IN_EXAMPLE" -eq 1 ] && [[ "$line" =~ ^##[[:space:]]+[0-9] ]]; then + IN_EXAMPLE=0 + fi + if [ "$IN_EXAMPLE" -eq 1 ] && [[ "$line" =~ ^\`\`\` ]]; then + if [ "$IN_FENCE" -eq 0 ]; then + IN_FENCE=1 + else + IN_FENCE=0 + break + fi + continue + fi + if [ "$IN_FENCE" -eq 1 ]; then + EXAMPLE_BLOCK="${EXAMPLE_BLOCK}${line}"$'\n' + fi +done < "$FILE" + +if [ -n "$EXAMPLE_BLOCK" ]; then + if echo "$EXAMPLE_BLOCK" | grep -q '\[PROJECT\]'; then + echo "FAIL: example contains unfilled placeholder [PROJECT]" + FAIL=1 + else + echo "PASS: example free of [PROJECT]" + fi + if echo "$EXAMPLE_BLOCK" | grep -q '\[REQUESTOR\]'; then + echo "FAIL: example contains unfilled placeholder [REQUESTOR]" + FAIL=1 + else + echo "PASS: example free of [REQUESTOR]" + fi +else + echo "FAIL: could not extract example block" + FAIL=1 +fi + +# 6. Changelog table exists with v1.0 row +if ! grep -q "| v1.0 " "$FILE"; then + echo "FAIL: changelog missing v1.0 row" + FAIL=1 +else + echo "PASS: changelog v1.0 row present" +fi + +# Final +if [ "$FAIL" -eq 0 ]; then + echo "RESULT: PASS" + exit 0 +else + echo "RESULT: FAIL ($FAIL checks failed)" + exit 1 +fi diff --git a/wizard-work/quill/change-request-template-v1.0.md b/wizard-work/quill/change-request-template-v1.0.md new file mode 100644 index 0000000..9d9e98d --- /dev/null +++ b/wizard-work/quill/change-request-template-v1.0.md @@ -0,0 +1,133 @@ +# Change Request Template v1.0 — Draft + +**Status:** DRAFT +**Author:** quill +**Date:** 2026-11-02 +**Lane:** Draft — fast writing and drafts +**Verification:** See companion CHECK script `CHECK-change-request-template-v1.0` + +--- + +## 1. Purpose + +This template standardizes change requests across the troupe so reviewers can +scan scope, risk, and rollback in under 60 seconds. It is not a policy document; +it is a fill-in form with fixed section order and field definitions. + +## 2. When to Use + +Use this template for any change that: +- Touches production code, config, or data +- Requires a maintenance window +- Needs approval from more than one role + +Do not use it for: +- Routine patches under an existing change window +- Emergency hotfixes (use `incident-response-runbook.md` instead) + +## 3. Template + +```markdown +# Change Request — [CHG-YYYYMMDD-NN] + +| Field | Value | +|---------------|-----------------------------| +| Project | [PROJECT] | +| Requestor | [REQUESTOR] | +| Date | [YYYY-MM-DD] | +| Change ID | [CHG-YYYYMMDD-NN] | +| Risk Level | Low / Medium / High / Blocker | +| Window | [YYYY-MM-DD HH:MM–HH:MM UTC]| + +## Summary +One sentence: what is changing and why. + +## Scope +- In scope: +- Out of scope: + +## Dependencies +- Systems affected: +- Teams notified: + +## Validation +- Test command / evidence: +- Success criteria: + +## Rollback +1. +2. +3. Trigger: [metric or time] + +## Approval +- [ ] Technical Lead +- [ ] Change Manager +- [ ] Security (if data/auth touched) +``` + +## 4. Field Definitions + +| Field | Rules | +|---------------|-----------------------------------------------------------------------| +| Risk Level | Must be exactly one of Low, Medium, High, Blocker. No free text. | +| Window | Must include UTC offset. Format: `YYYY-MM-DD HH:MM–HH:MM UTC`. | +| Summary | ≤ 120 characters. No line breaks. | +| Scope | Minimum one bullet each for in-scope and out-of-scope. | +| Validation | Must name a concrete command, log path, or metric. No adjectives. | +| Rollback | Minimum three ordered steps. | +| Approval | Minimum two roles. Security required iff scope touches auth/data. | + +## 5. Evidence Requirement + +Every field marked **must** is a testable constraint. The companion CHECK script +verifies presence, format, and minimum count. Empty placeholders (`[PROJECT]`, +`[YYYY-MM-DD]`, `[...]`) fail the check. + +## 6. Example (Reference) + +```markdown +# Change Request — CHG-20261102-01 + +| Field | Value | +|---------------|-----------------------------| +| Project | Timmy Bowel-Health Journal | +| Requestor | quill | +| Date | 2026-11-02 | +| Change ID | CHG-20261102-01 | +| Risk Level | Medium | +| Window | 2026-11-03 02:00–03:00 UTC | + +## Summary +Add daily summary aggregation cron job for the Timmy journal pipeline. + +## Scope +- In scope: cron job, aggregation script, daily summary markdown output +- Out of scope: UI changes, data migration, alert routing + +## Dependencies +- Systems affected: cron daemon, journal storage bucket +- Teams notified: #timmy-ops + +## Validation +- Command: `python3 /opt/timmy/aggregate.py --dry-run` +- Success criteria: exit 0, summary file present at `/var/log/timmy/summary.md` + +## Rollback +1. Disable cron entry `timmy-summary` +2. Remove generated summary directory `/var/log/timmy/summary/` +3. Restore prior config from `/opt/timmy/config.yaml.bak` + Trigger: aggregation exit code nonzero or summary file missing after 10 minutes + +## Approval +- [x] Technical Lead +- [x] Change Manager +- [ ] Security (data touched: PHI not in scope) +``` + +--- + +## 7. Changelog + +| Version | Date | Author | Change | +|---------|------------|--------|-------------------------------------| +| v1.0 | 2026-11-02 | quill | Initial structured draft with schema|