dev-playbooks-cn 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/LICENSE +21 -0
- package/README.md +466 -0
- package/bin/devbooks.js +987 -0
- package/package.json +43 -0
- package/skills/Skills/344/275/277/347/224/250/350/257/264/346/230/216.md +446 -0
- package/skills/Skill/345/274/200/345/217/221/346/214/207/345/215/227.md +248 -0
- package/skills/_shared/context-detection-template.md +315 -0
- package/skills/_shared/mcp-enhancement-template.md +144 -0
- package/skills/_shared/references//351/200/232/347/224/250/345/256/210/351/227/250/345/215/217/350/256/256.md +114 -0
- package/skills/_template/config-discovery-template.md +126 -0
- package/skills/devbooks-brownfield-bootstrap/SKILL.md +167 -0
- package/skills/devbooks-brownfield-bootstrap/references//344/273/243/347/240/201/345/257/274/350/210/252/347/255/226/347/225/245.md +203 -0
- package/skills/devbooks-brownfield-bootstrap/references//345/255/230/351/207/217/351/241/271/347/233/256/345/210/235/345/247/213/345/214/226.md +96 -0
- package/skills/devbooks-brownfield-bootstrap/references//345/255/230/351/207/217/351/241/271/347/233/256/345/210/235/345/247/213/345/214/226/346/217/220/347/244/272/350/257/215.md +115 -0
- package/skills/devbooks-brownfield-bootstrap/references//346/234/257/350/257/255/350/241/250/346/250/241/346/235/277.md +42 -0
- package/skills/devbooks-brownfield-bootstrap/scripts/cod-update.sh +357 -0
- package/skills/devbooks-brownfield-bootstrap/templates/project-profile-template.md +172 -0
- package/skills/devbooks-c4-map/SKILL.md +151 -0
- package/skills/devbooks-c4-map/references/C4/346/236/266/346/236/204/345/234/260/345/233/276/346/217/220/347/244/272/350/257/215.md +33 -0
- package/skills/devbooks-c4-map/references//345/210/206/345/261/202/347/272/246/346/235/237/346/243/200/346/237/245/346/270/205/345/215/225.md +185 -0
- package/skills/devbooks-code-review/SKILL.md +175 -0
- package/skills/devbooks-code-review/references/PR/346/250/241/346/235/277/344/270/216/346/214/207/345/215/227.md +321 -0
- package/skills/devbooks-code-review/references//344/273/243/347/240/201/350/257/204/345/256/241/346/217/220/347/244/272/350/257/215.md +100 -0
- package/skills/devbooks-code-review/references//345/235/217/345/221/263/351/201/223/351/200/237/346/237/245/350/241/250.md +495 -0
- package/skills/devbooks-code-review/references//350/265/204/346/272/220/347/256/241/347/220/206/345/256/241/346/237/245/346/270/205/345/215/225.md +311 -0
- package/skills/devbooks-coder/SKILL.md +219 -0
- package/skills/devbooks-coder/references//344/273/243/347/240/201/345/256/236/347/216/260/346/217/220/347/244/272/350/257/215.md +70 -0
- package/skills/devbooks-coder/references//344/275/216/351/243/216/351/231/251/346/224/271/345/212/250/346/212/200/346/234/257.md +275 -0
- package/skills/devbooks-coder/references//346/227/245/345/277/227/350/247/204/350/214/203.md +329 -0
- package/skills/devbooks-coder/references//347/274/226/347/240/201/351/243/216/346/240/274/347/273/206/345/210/231.md +351 -0
- package/skills/devbooks-coder/references//351/224/231/350/257/257/347/240/201/350/247/204/350/214/203.md +463 -0
- package/skills/devbooks-delivery-workflow/SKILL.md +217 -0
- package/skills/devbooks-delivery-workflow/references//344/272/244/344/273/230/351/252/214/346/224/266/345/267/245/344/275/234/346/265/201.md +256 -0
- package/skills/devbooks-delivery-workflow/references//345/216/237/345/236/213-/347/224/237/344/272/247/345/217/214/350/275/250/346/250/241/345/274/217.md +168 -0
- package/skills/devbooks-delivery-workflow/references//345/217/230/346/233/264/351/252/214/350/257/201/344/270/216/350/277/275/346/272/257/346/250/241/346/235/277.md +133 -0
- package/skills/devbooks-delivery-workflow/scripts/ac-trace-check.sh +330 -0
- package/skills/devbooks-delivery-workflow/scripts/audit-scope.sh +262 -0
- package/skills/devbooks-delivery-workflow/scripts/change-check.sh +1040 -0
- package/skills/devbooks-delivery-workflow/scripts/change-codemod-scaffold.sh +135 -0
- package/skills/devbooks-delivery-workflow/scripts/change-evidence.sh +152 -0
- package/skills/devbooks-delivery-workflow/scripts/change-scaffold.sh +442 -0
- package/skills/devbooks-delivery-workflow/scripts/change-spec-delta-scaffold.sh +136 -0
- package/skills/devbooks-delivery-workflow/scripts/constitution-check.sh +237 -0
- package/skills/devbooks-delivery-workflow/scripts/env-match-check.sh +128 -0
- package/skills/devbooks-delivery-workflow/scripts/fitness-check.sh +387 -0
- package/skills/devbooks-delivery-workflow/scripts/guardrail-check.sh +519 -0
- package/skills/devbooks-delivery-workflow/scripts/handoff-check.sh +141 -0
- package/skills/devbooks-delivery-workflow/scripts/hygiene-check.sh +340 -0
- package/skills/devbooks-delivery-workflow/scripts/migrate-from-openspec.sh +385 -0
- package/skills/devbooks-delivery-workflow/scripts/migrate-to-v2-gates.sh +202 -0
- package/skills/devbooks-delivery-workflow/scripts/progress-dashboard.sh +319 -0
- package/skills/devbooks-delivery-workflow/scripts/prototype-promote.sh +341 -0
- package/skills/devbooks-delivery-workflow/scripts/spec-preview.sh +203 -0
- package/skills/devbooks-delivery-workflow/scripts/spec-promote.sh +118 -0
- package/skills/devbooks-delivery-workflow/scripts/spec-rollback.sh +124 -0
- package/skills/devbooks-delivery-workflow/scripts/spec-stage.sh +117 -0
- package/skills/devbooks-delivery-workflow/scripts/verify-all.sh +78 -0
- package/skills/devbooks-delivery-workflow/scripts/verify-npm-package.sh +123 -0
- package/skills/devbooks-delivery-workflow/scripts/verify-openspec-free.sh +81 -0
- package/skills/devbooks-delivery-workflow/scripts/verify-slash-commands.sh +146 -0
- package/skills/devbooks-delivery-workflow/templates/handoff.md +50 -0
- package/skills/devbooks-design-backport/SKILL.md +73 -0
- package/skills/devbooks-design-backport/references//345/233/236/345/206/231/350/256/276/350/256/241/346/226/207/346/241/243/346/217/220/347/244/272/350/257/215.md +196 -0
- package/skills/devbooks-design-doc/SKILL.md +121 -0
- package/skills/devbooks-design-doc/references//345/276/256/346/234/215/345/212/241/350/256/276/350/256/241/346/270/205/345/215/225.md +149 -0
- package/skills/devbooks-design-doc/references//350/256/276/350/256/241/346/226/207/346/241/243/346/217/220/347/244/272/350/257/215.md +189 -0
- package/skills/devbooks-design-doc/references//351/232/220/347/247/201/345/220/210/350/247/204/346/243/200/346/237/245/346/270/205/345/215/225.md +240 -0
- package/skills/devbooks-entropy-monitor/SKILL.md +188 -0
- package/skills/devbooks-entropy-monitor/references//347/206/265/345/272/246/351/207/217/346/226/271/346/263/225/350/256/272.md +223 -0
- package/skills/devbooks-entropy-monitor/scripts/entropy-measure.sh +449 -0
- package/skills/devbooks-entropy-monitor/scripts/entropy-report.sh +303 -0
- package/skills/devbooks-entropy-monitor/templates/thresholds.json +99 -0
- package/skills/devbooks-federation/SKILL.md +264 -0
- package/skills/devbooks-federation/scripts/federation-check.sh +144 -0
- package/skills/devbooks-federation/templates/federation.yaml +89 -0
- package/skills/devbooks-impact-analysis/SKILL.md +135 -0
- package/skills/devbooks-impact-analysis/references//345/275/261/345/223/215/345/210/206/346/236/220/346/217/220/347/244/272/350/257/215.md +82 -0
- package/skills/devbooks-impact-analysis/scripts/graph-cache.sh +214 -0
- package/skills/devbooks-implementation-plan/SKILL.md +83 -0
- package/skills/devbooks-implementation-plan/references//347/274/226/347/240/201/350/256/241/345/210/222/346/217/220/347/244/272/350/257/215.md +99 -0
- package/skills/devbooks-index-bootstrap/SKILL.md +240 -0
- package/skills/devbooks-proposal-author/SKILL.md +83 -0
- package/skills/devbooks-proposal-author/references//346/217/220/346/241/210/346/222/260/345/206/231/346/217/220/347/244/272/350/257/215.md +66 -0
- package/skills/devbooks-proposal-challenger/SKILL.md +86 -0
- package/skills/devbooks-proposal-challenger/references//344/274/246/347/220/206/344/270/216/345/220/210/350/247/204/346/243/200/346/237/245/346/270/205/345/215/225.md +176 -0
- package/skills/devbooks-proposal-challenger/references//346/217/220/346/241/210/350/264/250/347/226/221/346/217/220/347/244/272/350/257/215.md +57 -0
- package/skills/devbooks-proposal-debate-workflow/SKILL.md +78 -0
- package/skills/devbooks-proposal-debate-workflow/references//346/217/220/346/241/210/345/257/271/350/276/251/345/267/245/344/275/234/346/265/201.md +24 -0
- package/skills/devbooks-proposal-debate-workflow/references//346/217/220/346/241/210/345/257/271/350/276/251/346/250/241/346/235/277.md +35 -0
- package/skills/devbooks-proposal-debate-workflow/scripts/proposal-debate-check.sh +102 -0
- package/skills/devbooks-proposal-judge/SKILL.md +78 -0
- package/skills/devbooks-proposal-judge/references//346/217/220/346/241/210/350/243/201/345/206/263/346/217/220/347/244/272/350/257/215.md +37 -0
- package/skills/devbooks-router/SKILL.md +346 -0
- package/skills/devbooks-spec-contract/SKILL.md +191 -0
- package/skills/devbooks-spec-contract/references/API/350/256/276/350/256/241/346/214/207/345/215/227.md +349 -0
- package/skills/devbooks-spec-contract/references//345/245/221/347/272/246/344/270/216/346/225/260/346/215/256/345/256/232/344/271/211/346/217/220/347/244/272/350/257/215.md +85 -0
- package/skills/devbooks-spec-contract/references//350/247/204/346/240/274/345/217/230/346/233/264/346/217/220/347/244/272/350/257/215.md +63 -0
- package/skills/devbooks-spec-contract/references//351/232/220/345/274/217/345/217/230/346/233/264/346/243/200/346/265/213/346/217/220/347/244/272/350/257/215.md +183 -0
- package/skills/devbooks-spec-contract/scripts/implicit-change-detect.sh +378 -0
- package/skills/devbooks-spec-gardener/SKILL.md +72 -0
- package/skills/devbooks-spec-gardener/references//350/247/204/346/240/274/345/233/255/344/270/201/346/217/220/347/244/272/350/257/215.md +41 -0
- package/skills/devbooks-test-owner/SKILL.md +172 -0
- package/skills/devbooks-test-owner/references//345/217/230/346/233/264/351/252/214/350/257/201/344/270/216/350/277/275/346/272/257/346/250/241/346/235/277.md +228 -0
- package/skills/devbooks-test-owner/references//345/274/202/346/255/245/347/263/273/347/273/237/346/265/213/350/257/225/347/255/226/347/225/245.md +316 -0
- package/skills/devbooks-test-owner/references//346/265/213/350/257/225/344/273/243/347/240/201/346/217/220/347/244/272/350/257/215.md +208 -0
- package/skills/devbooks-test-owner/references//346/265/213/350/257/225/345/210/206/345/261/202/347/255/226/347/225/245.md +281 -0
- package/skills/devbooks-test-owner/references//346/265/213/350/257/225/351/251/261/345/212/250.md +394 -0
- package/skills/devbooks-test-owner/references//350/247/243/344/276/235/350/265/226/346/212/200/346/234/257/351/200/237/346/237/245/350/241/250.md +432 -0
- package/skills/devbooks-test-reviewer/SKILL.md +189 -0
- package/templates/.devbooks/config.yaml +88 -0
- package/templates/claude-commands/devbooks/apply.md +38 -0
- package/templates/claude-commands/devbooks/archive.md +33 -0
- package/templates/claude-commands/devbooks/backport.md +19 -0
- package/templates/claude-commands/devbooks/bootstrap.md +19 -0
- package/templates/claude-commands/devbooks/c4.md +19 -0
- package/templates/claude-commands/devbooks/challenger.md +19 -0
- package/templates/claude-commands/devbooks/code.md +19 -0
- package/templates/claude-commands/devbooks/debate.md +19 -0
- package/templates/claude-commands/devbooks/delivery.md +19 -0
- package/templates/claude-commands/devbooks/design.md +19 -0
- package/templates/claude-commands/devbooks/entropy.md +19 -0
- package/templates/claude-commands/devbooks/federation.md +19 -0
- package/templates/claude-commands/devbooks/gardener.md +19 -0
- package/templates/claude-commands/devbooks/impact.md +19 -0
- package/templates/claude-commands/devbooks/index.md +19 -0
- package/templates/claude-commands/devbooks/judge.md +19 -0
- package/templates/claude-commands/devbooks/plan.md +19 -0
- package/templates/claude-commands/devbooks/proposal.md +19 -0
- package/templates/claude-commands/devbooks/quick.md +42 -0
- package/templates/claude-commands/devbooks/review.md +19 -0
- package/templates/claude-commands/devbooks/router.md +19 -0
- package/templates/claude-commands/devbooks/spec.md +19 -0
- package/templates/claude-commands/devbooks/test-review.md +19 -0
- package/templates/claude-commands/devbooks/test.md +19 -0
- package/templates/dev-playbooks/README.md +458 -0
- package/templates/dev-playbooks/changes/.gitkeep +1 -0
- package/templates/dev-playbooks/constitution.md +116 -0
- package/templates/dev-playbooks/project.md +96 -0
- package/templates/dev-playbooks/scripts/.gitkeep +1 -0
- package/templates/dev-playbooks/specs/_meta/anti-patterns/.gitkeep +2 -0
- package/templates/dev-playbooks/specs/_meta/glossary.md +47 -0
- package/templates/dev-playbooks/specs/_meta/project-profile.md +79 -0
- package/templates/dev-playbooks/specs/architecture/fitness-rules.md +95 -0
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# progress-dashboard.sh - Provide progress visualization for change packages
|
|
3
|
+
#
|
|
4
|
+
# This script displays a dashboard showing:
|
|
5
|
+
# - Task completion rate
|
|
6
|
+
# - Role status (handoff state)
|
|
7
|
+
# - Evidence status (Red/Green)
|
|
8
|
+
#
|
|
9
|
+
# Reference: harden-devbooks-quality-gates design.md AC-010
|
|
10
|
+
|
|
11
|
+
set -euo pipefail
|
|
12
|
+
|
|
13
|
+
usage() {
|
|
14
|
+
cat <<'EOF' >&2
|
|
15
|
+
usage: progress-dashboard.sh <change-id> [options]
|
|
16
|
+
|
|
17
|
+
Display progress dashboard for a change package:
|
|
18
|
+
- Task completion rate and breakdown
|
|
19
|
+
- Role status (current role, handoff state)
|
|
20
|
+
- Evidence status (Red baseline, Green final)
|
|
21
|
+
|
|
22
|
+
Options:
|
|
23
|
+
--project-root <dir> Project root directory (default: pwd)
|
|
24
|
+
--change-root <dir> Change packages root (default: changes)
|
|
25
|
+
--format <fmt> Output format: text (default), markdown, json
|
|
26
|
+
-h, --help Show this help message
|
|
27
|
+
|
|
28
|
+
Exit Codes:
|
|
29
|
+
0 - Dashboard generated successfully
|
|
30
|
+
1 - Change package not found or error
|
|
31
|
+
2 - Usage error
|
|
32
|
+
|
|
33
|
+
Examples:
|
|
34
|
+
progress-dashboard.sh my-change-001
|
|
35
|
+
progress-dashboard.sh my-change-001 --format markdown
|
|
36
|
+
progress-dashboard.sh my-change-001 --change-root dev-playbooks/changes
|
|
37
|
+
EOF
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if [[ $# -eq 0 ]]; then
|
|
41
|
+
usage
|
|
42
|
+
exit 2
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
|
46
|
+
usage
|
|
47
|
+
exit 0
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
change_id="$1"
|
|
51
|
+
shift
|
|
52
|
+
|
|
53
|
+
project_root="${DEVBOOKS_PROJECT_ROOT:-$(pwd)}"
|
|
54
|
+
change_root="${DEVBOOKS_CHANGE_ROOT:-changes}"
|
|
55
|
+
output_format="text"
|
|
56
|
+
|
|
57
|
+
while [[ $# -gt 0 ]]; do
|
|
58
|
+
case "$1" in
|
|
59
|
+
-h|--help)
|
|
60
|
+
usage
|
|
61
|
+
exit 0
|
|
62
|
+
;;
|
|
63
|
+
--project-root)
|
|
64
|
+
project_root="${2:-}"
|
|
65
|
+
shift 2
|
|
66
|
+
;;
|
|
67
|
+
--change-root)
|
|
68
|
+
change_root="${2:-}"
|
|
69
|
+
shift 2
|
|
70
|
+
;;
|
|
71
|
+
--format)
|
|
72
|
+
output_format="${2:-text}"
|
|
73
|
+
shift 2
|
|
74
|
+
;;
|
|
75
|
+
*)
|
|
76
|
+
echo "error: unknown option: $1" >&2
|
|
77
|
+
usage
|
|
78
|
+
exit 2
|
|
79
|
+
;;
|
|
80
|
+
esac
|
|
81
|
+
done
|
|
82
|
+
|
|
83
|
+
# Validate change-id
|
|
84
|
+
if [[ -z "$change_id" || "$change_id" == "-"* || "$change_id" =~ [[:space:]] ]]; then
|
|
85
|
+
echo "error: invalid change-id: '$change_id'" >&2
|
|
86
|
+
exit 2
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
# Validate format
|
|
90
|
+
case "$output_format" in
|
|
91
|
+
text|markdown|json) ;;
|
|
92
|
+
*)
|
|
93
|
+
echo "error: invalid --format: '$output_format' (use: text, markdown, json)" >&2
|
|
94
|
+
exit 2
|
|
95
|
+
;;
|
|
96
|
+
esac
|
|
97
|
+
|
|
98
|
+
# Build paths
|
|
99
|
+
project_root="${project_root%/}"
|
|
100
|
+
change_root="${change_root%/}"
|
|
101
|
+
|
|
102
|
+
if [[ "$change_root" = /* ]]; then
|
|
103
|
+
change_dir="${change_root}/${change_id}"
|
|
104
|
+
else
|
|
105
|
+
change_dir="${project_root}/${change_root}/${change_id}"
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
# Check change directory exists
|
|
109
|
+
if [[ ! -d "$change_dir" ]]; then
|
|
110
|
+
echo "error: change directory not found: ${change_dir}" >&2
|
|
111
|
+
exit 1
|
|
112
|
+
fi
|
|
113
|
+
|
|
114
|
+
# Define file paths
|
|
115
|
+
tasks_file="${change_dir}/tasks.md"
|
|
116
|
+
handoff_file="${change_dir}/handoff.md"
|
|
117
|
+
proposal_file="${change_dir}/proposal.md"
|
|
118
|
+
design_file="${change_dir}/design.md"
|
|
119
|
+
verification_file="${change_dir}/verification.md"
|
|
120
|
+
red_evidence="${change_dir}/evidence/red-baseline"
|
|
121
|
+
green_evidence="${change_dir}/evidence/green-final"
|
|
122
|
+
|
|
123
|
+
# =============================================================================
|
|
124
|
+
# Collect Data
|
|
125
|
+
# =============================================================================
|
|
126
|
+
|
|
127
|
+
# Task completion
|
|
128
|
+
total_tasks=0
|
|
129
|
+
completed_tasks=0
|
|
130
|
+
p0_total=0
|
|
131
|
+
p0_completed=0
|
|
132
|
+
p1_total=0
|
|
133
|
+
p1_completed=0
|
|
134
|
+
p2_total=0
|
|
135
|
+
p2_completed=0
|
|
136
|
+
|
|
137
|
+
if [[ -f "$tasks_file" ]]; then
|
|
138
|
+
# Count all tasks
|
|
139
|
+
total_tasks=$(grep -cE "^- \[[xX ]\]" "$tasks_file" 2>/dev/null) || total_tasks=0
|
|
140
|
+
completed_tasks=$(grep -cE "^- \[[xX]\]" "$tasks_file" 2>/dev/null) || completed_tasks=0
|
|
141
|
+
|
|
142
|
+
# Count by priority
|
|
143
|
+
p0_total=$(grep -cE "^- \[[xX ]\] \[P0\]" "$tasks_file" 2>/dev/null) || p0_total=0
|
|
144
|
+
p0_completed=$(grep -cE "^- \[[xX]\] \[P0\]" "$tasks_file" 2>/dev/null) || p0_completed=0
|
|
145
|
+
p1_total=$(grep -cE "^- \[[xX ]\] \[P1\]" "$tasks_file" 2>/dev/null) || p1_total=0
|
|
146
|
+
p1_completed=$(grep -cE "^- \[[xX]\] \[P1\]" "$tasks_file" 2>/dev/null) || p1_completed=0
|
|
147
|
+
p2_total=$(grep -cE "^- \[[xX ]\] \[P2\]" "$tasks_file" 2>/dev/null) || p2_total=0
|
|
148
|
+
p2_completed=$(grep -cE "^- \[[xX]\] \[P2\]" "$tasks_file" 2>/dev/null) || p2_completed=0
|
|
149
|
+
fi
|
|
150
|
+
|
|
151
|
+
# Calculate completion rate
|
|
152
|
+
if [[ $total_tasks -gt 0 ]]; then
|
|
153
|
+
completion_rate=$((completed_tasks * 100 / total_tasks))
|
|
154
|
+
else
|
|
155
|
+
completion_rate=100
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
# Role status
|
|
159
|
+
handoff_state="none"
|
|
160
|
+
if [[ -f "$handoff_file" ]]; then
|
|
161
|
+
confirmed=$(grep -cE "^- \[[xX]\]" "$handoff_file" 2>/dev/null || echo "0")
|
|
162
|
+
total_sigs=$(grep -cE "^- \[[xX ]\]" "$handoff_file" 2>/dev/null || echo "0")
|
|
163
|
+
if [[ $confirmed -eq $total_sigs && $total_sigs -gt 0 ]]; then
|
|
164
|
+
handoff_state="complete"
|
|
165
|
+
elif [[ $confirmed -gt 0 ]]; then
|
|
166
|
+
handoff_state="partial"
|
|
167
|
+
else
|
|
168
|
+
handoff_state="pending"
|
|
169
|
+
fi
|
|
170
|
+
fi
|
|
171
|
+
|
|
172
|
+
# Determine current phase
|
|
173
|
+
current_phase="unknown"
|
|
174
|
+
if [[ ! -f "$proposal_file" ]]; then
|
|
175
|
+
current_phase="proposal"
|
|
176
|
+
elif [[ ! -f "$design_file" ]]; then
|
|
177
|
+
current_phase="design"
|
|
178
|
+
elif [[ ! -f "$verification_file" ]]; then
|
|
179
|
+
current_phase="test-owner"
|
|
180
|
+
elif [[ $completion_rate -lt 100 ]]; then
|
|
181
|
+
current_phase="coder"
|
|
182
|
+
else
|
|
183
|
+
current_phase="review"
|
|
184
|
+
fi
|
|
185
|
+
|
|
186
|
+
# Evidence status
|
|
187
|
+
red_exists="no"
|
|
188
|
+
green_exists="no"
|
|
189
|
+
red_count=0
|
|
190
|
+
green_count=0
|
|
191
|
+
|
|
192
|
+
if [[ -d "$red_evidence" ]]; then
|
|
193
|
+
red_count=$(find "$red_evidence" -type f 2>/dev/null | wc -l | tr -d ' ')
|
|
194
|
+
if [[ $red_count -gt 0 ]]; then
|
|
195
|
+
red_exists="yes"
|
|
196
|
+
fi
|
|
197
|
+
fi
|
|
198
|
+
|
|
199
|
+
if [[ -d "$green_evidence" ]]; then
|
|
200
|
+
green_count=$(find "$green_evidence" -type f 2>/dev/null | wc -l | tr -d ' ')
|
|
201
|
+
if [[ $green_count -gt 0 ]]; then
|
|
202
|
+
green_exists="yes"
|
|
203
|
+
fi
|
|
204
|
+
fi
|
|
205
|
+
|
|
206
|
+
# Document status
|
|
207
|
+
proposal_exists=$([[ -f "$proposal_file" ]] && echo "yes" || echo "no")
|
|
208
|
+
design_exists=$([[ -f "$design_file" ]] && echo "yes" || echo "no")
|
|
209
|
+
tasks_exists=$([[ -f "$tasks_file" ]] && echo "yes" || echo "no")
|
|
210
|
+
verification_exists=$([[ -f "$verification_file" ]] && echo "yes" || echo "no")
|
|
211
|
+
|
|
212
|
+
# =============================================================================
|
|
213
|
+
# Output
|
|
214
|
+
# =============================================================================
|
|
215
|
+
|
|
216
|
+
case "$output_format" in
|
|
217
|
+
text)
|
|
218
|
+
echo "=================================================="
|
|
219
|
+
echo "Progress Dashboard: ${change_id}"
|
|
220
|
+
echo "=================================================="
|
|
221
|
+
echo ""
|
|
222
|
+
echo "## Task Completion"
|
|
223
|
+
echo " Total: ${completed_tasks}/${total_tasks} (${completion_rate}%)"
|
|
224
|
+
echo " [P0]: ${p0_completed}/${p0_total}"
|
|
225
|
+
echo " [P1]: ${p1_completed}/${p1_total}"
|
|
226
|
+
echo " [P2]: ${p2_completed}/${p2_total}"
|
|
227
|
+
echo ""
|
|
228
|
+
echo "## Role Status"
|
|
229
|
+
echo " Current Phase: ${current_phase}"
|
|
230
|
+
echo " Handoff State: ${handoff_state}"
|
|
231
|
+
echo ""
|
|
232
|
+
echo "## Evidence Status"
|
|
233
|
+
echo " Red Baseline: ${red_exists} (${red_count} files)"
|
|
234
|
+
echo " Green Final: ${green_exists} (${green_count} files)"
|
|
235
|
+
echo ""
|
|
236
|
+
echo "## Document Status"
|
|
237
|
+
echo " proposal.md: ${proposal_exists}"
|
|
238
|
+
echo " design.md: ${design_exists}"
|
|
239
|
+
echo " tasks.md: ${tasks_exists}"
|
|
240
|
+
echo " verification.md: ${verification_exists}"
|
|
241
|
+
echo ""
|
|
242
|
+
;;
|
|
243
|
+
|
|
244
|
+
markdown)
|
|
245
|
+
echo "# Progress Dashboard: ${change_id}"
|
|
246
|
+
echo ""
|
|
247
|
+
echo "## Task Completion"
|
|
248
|
+
echo ""
|
|
249
|
+
echo "| Priority | Completed | Total | Rate |"
|
|
250
|
+
echo "|----------|-----------|-------|------|"
|
|
251
|
+
echo "| All | ${completed_tasks} | ${total_tasks} | ${completion_rate}% |"
|
|
252
|
+
echo "| P0 | ${p0_completed} | ${p0_total} | - |"
|
|
253
|
+
echo "| P1 | ${p1_completed} | ${p1_total} | - |"
|
|
254
|
+
echo "| P2 | ${p2_completed} | ${p2_total} | - |"
|
|
255
|
+
echo ""
|
|
256
|
+
echo "## Role Status"
|
|
257
|
+
echo ""
|
|
258
|
+
echo "- **Current Phase**: ${current_phase}"
|
|
259
|
+
echo "- **Handoff State**: ${handoff_state}"
|
|
260
|
+
echo ""
|
|
261
|
+
echo "## Evidence Status"
|
|
262
|
+
echo ""
|
|
263
|
+
echo "| Type | Exists | Files |"
|
|
264
|
+
echo "|------|--------|-------|"
|
|
265
|
+
echo "| Red Baseline | ${red_exists} | ${red_count} |"
|
|
266
|
+
echo "| Green Final | ${green_exists} | ${green_count} |"
|
|
267
|
+
echo ""
|
|
268
|
+
echo "## Document Status"
|
|
269
|
+
echo ""
|
|
270
|
+
echo "| Document | Exists |"
|
|
271
|
+
echo "|----------|--------|"
|
|
272
|
+
echo "| proposal.md | ${proposal_exists} |"
|
|
273
|
+
echo "| design.md | ${design_exists} |"
|
|
274
|
+
echo "| tasks.md | ${tasks_exists} |"
|
|
275
|
+
echo "| verification.md | ${verification_exists} |"
|
|
276
|
+
;;
|
|
277
|
+
|
|
278
|
+
json)
|
|
279
|
+
# Convert yes/no to JSON boolean true/false
|
|
280
|
+
red_exists_bool=$([[ "$red_exists" == "yes" ]] && echo "true" || echo "false")
|
|
281
|
+
green_exists_bool=$([[ "$green_exists" == "yes" ]] && echo "true" || echo "false")
|
|
282
|
+
proposal_exists_bool=$([[ "$proposal_exists" == "yes" ]] && echo "true" || echo "false")
|
|
283
|
+
design_exists_bool=$([[ "$design_exists" == "yes" ]] && echo "true" || echo "false")
|
|
284
|
+
tasks_exists_bool=$([[ "$tasks_exists" == "yes" ]] && echo "true" || echo "false")
|
|
285
|
+
verification_exists_bool=$([[ "$verification_exists" == "yes" ]] && echo "true" || echo "false")
|
|
286
|
+
|
|
287
|
+
cat << EOF
|
|
288
|
+
{
|
|
289
|
+
"changeId": "${change_id}",
|
|
290
|
+
"tasks": {
|
|
291
|
+
"total": ${total_tasks},
|
|
292
|
+
"completed": ${completed_tasks},
|
|
293
|
+
"completionRate": ${completion_rate},
|
|
294
|
+
"byPriority": {
|
|
295
|
+
"p0": {"total": ${p0_total}, "completed": ${p0_completed}},
|
|
296
|
+
"p1": {"total": ${p1_total}, "completed": ${p1_completed}},
|
|
297
|
+
"p2": {"total": ${p2_total}, "completed": ${p2_completed}}
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
"role": {
|
|
301
|
+
"currentPhase": "${current_phase}",
|
|
302
|
+
"handoffState": "${handoff_state}"
|
|
303
|
+
},
|
|
304
|
+
"evidence": {
|
|
305
|
+
"redBaseline": {"exists": ${red_exists_bool}, "fileCount": ${red_count}},
|
|
306
|
+
"greenFinal": {"exists": ${green_exists_bool}, "fileCount": ${green_count}}
|
|
307
|
+
},
|
|
308
|
+
"documents": {
|
|
309
|
+
"proposal": ${proposal_exists_bool},
|
|
310
|
+
"design": ${design_exists_bool},
|
|
311
|
+
"tasks": ${tasks_exists_bool},
|
|
312
|
+
"verification": ${verification_exists_bool}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
EOF
|
|
316
|
+
;;
|
|
317
|
+
esac
|
|
318
|
+
|
|
319
|
+
exit 0
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# ============================================================================
|
|
5
|
+
# prototype-promote.sh
|
|
6
|
+
# ============================================================================
|
|
7
|
+
# Promotes a prototype to production track.
|
|
8
|
+
#
|
|
9
|
+
# This script enforces:
|
|
10
|
+
# 1. PROTOTYPE.md checklist is complete
|
|
11
|
+
# 2. Production design.md exists with AC-xxx items
|
|
12
|
+
# 3. Production verification.md exists (Test Owner has produced acceptance tests)
|
|
13
|
+
# 4. All quality gates pass before promotion
|
|
14
|
+
#
|
|
15
|
+
# Reference: "The Mythical Man-Month" Chapter 11 "Plan to Throw One Away"
|
|
16
|
+
# ============================================================================
|
|
17
|
+
|
|
18
|
+
usage() {
|
|
19
|
+
cat <<'EOF' >&2
|
|
20
|
+
usage: prototype-promote.sh <change-id> [--project-root <dir>] [--change-root <dir>] [--archive-dir <dir>] [--force]
|
|
21
|
+
|
|
22
|
+
Promotes a prototype to production track:
|
|
23
|
+
1. Validates prototype/PROTOTYPE.md checklist is complete
|
|
24
|
+
2. Requires design.md to exist with AC-xxx items
|
|
25
|
+
3. Requires verification.md to exist (Test Owner acceptance tests)
|
|
26
|
+
4. Archives characterization tests to <archive-dir>/<change-id>/
|
|
27
|
+
5. Removes prototype/ directory
|
|
28
|
+
|
|
29
|
+
Defaults (can be overridden by flags or env):
|
|
30
|
+
DEVBOOKS_PROJECT_ROOT: pwd
|
|
31
|
+
DEVBOOKS_CHANGE_ROOT: changes
|
|
32
|
+
Archive directory: tests/archived-characterization
|
|
33
|
+
|
|
34
|
+
Options:
|
|
35
|
+
--force Skip confirmation prompt
|
|
36
|
+
--archive-dir Custom archive directory for characterization tests
|
|
37
|
+
|
|
38
|
+
WARNING: This script enforces that:
|
|
39
|
+
- Test Owner has produced NEW acceptance tests (not just characterization tests)
|
|
40
|
+
- All quality gates (design.md, verification.md) exist
|
|
41
|
+
- Prototype checklist is complete
|
|
42
|
+
|
|
43
|
+
Example:
|
|
44
|
+
prototype-promote.sh my-feature-001
|
|
45
|
+
prototype-promote.sh my-feature-001 --project-root /path/to/repo
|
|
46
|
+
EOF
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
# Color output helpers
|
|
50
|
+
red() { printf '\033[0;31m%s\033[0m\n' "$*" >&2; }
|
|
51
|
+
green() { printf '\033[0;32m%s\033[0m\n' "$*" >&2; }
|
|
52
|
+
yellow() { printf '\033[0;33m%s\033[0m\n' "$*" >&2; }
|
|
53
|
+
|
|
54
|
+
err() { red "error: $*"; }
|
|
55
|
+
warn() { yellow "warn: $*"; }
|
|
56
|
+
ok() { green "ok: $*"; }
|
|
57
|
+
|
|
58
|
+
if [[ $# -eq 0 ]]; then
|
|
59
|
+
usage
|
|
60
|
+
exit 2
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
|
64
|
+
usage
|
|
65
|
+
exit 0
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
change_id="$1"
|
|
69
|
+
shift
|
|
70
|
+
|
|
71
|
+
project_root="${DEVBOOKS_PROJECT_ROOT:-$(pwd)}"
|
|
72
|
+
change_root="${DEVBOOKS_CHANGE_ROOT:-changes}"
|
|
73
|
+
archive_dir=""
|
|
74
|
+
force=false
|
|
75
|
+
|
|
76
|
+
while [[ $# -gt 0 ]]; do
|
|
77
|
+
case "$1" in
|
|
78
|
+
-h|--help)
|
|
79
|
+
usage
|
|
80
|
+
exit 0
|
|
81
|
+
;;
|
|
82
|
+
--project-root)
|
|
83
|
+
project_root="${2:-}"
|
|
84
|
+
shift 2
|
|
85
|
+
;;
|
|
86
|
+
--change-root)
|
|
87
|
+
change_root="${2:-}"
|
|
88
|
+
shift 2
|
|
89
|
+
;;
|
|
90
|
+
--archive-dir)
|
|
91
|
+
archive_dir="${2:-}"
|
|
92
|
+
shift 2
|
|
93
|
+
;;
|
|
94
|
+
--force)
|
|
95
|
+
force=true
|
|
96
|
+
shift
|
|
97
|
+
;;
|
|
98
|
+
*)
|
|
99
|
+
usage
|
|
100
|
+
exit 2
|
|
101
|
+
;;
|
|
102
|
+
esac
|
|
103
|
+
done
|
|
104
|
+
|
|
105
|
+
if [[ -z "$change_id" ]]; then
|
|
106
|
+
err "change-id is required"
|
|
107
|
+
exit 2
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
# Normalize paths
|
|
111
|
+
project_root="${project_root%/}"
|
|
112
|
+
change_root="${change_root%/}"
|
|
113
|
+
|
|
114
|
+
if [[ "$change_root" = /* ]]; then
|
|
115
|
+
change_dir="${change_root}/${change_id}"
|
|
116
|
+
else
|
|
117
|
+
change_dir="${project_root}/${change_root}/${change_id}"
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
# Default archive directory
|
|
121
|
+
if [[ -z "$archive_dir" ]]; then
|
|
122
|
+
archive_dir="${project_root}/tests/archived-characterization"
|
|
123
|
+
fi
|
|
124
|
+
|
|
125
|
+
prototype_dir="${change_dir}/prototype"
|
|
126
|
+
prototype_md="${prototype_dir}/PROTOTYPE.md"
|
|
127
|
+
design_md="${change_dir}/design.md"
|
|
128
|
+
verification_md="${change_dir}/verification.md"
|
|
129
|
+
|
|
130
|
+
# ============================================================================
|
|
131
|
+
# Validation checks
|
|
132
|
+
# ============================================================================
|
|
133
|
+
|
|
134
|
+
echo "=== Prototype Promotion Check: ${change_id} ==="
|
|
135
|
+
echo ""
|
|
136
|
+
|
|
137
|
+
errors=0
|
|
138
|
+
|
|
139
|
+
# Check 1: Prototype directory exists
|
|
140
|
+
if [[ ! -d "$prototype_dir" ]]; then
|
|
141
|
+
err "no prototype directory found: ${prototype_dir}"
|
|
142
|
+
err "hint: run 'change-scaffold.sh ${change_id} --prototype' first"
|
|
143
|
+
exit 1
|
|
144
|
+
fi
|
|
145
|
+
|
|
146
|
+
echo "checking: prototype directory exists"
|
|
147
|
+
ok "found: ${prototype_dir}"
|
|
148
|
+
|
|
149
|
+
# Check 2: PROTOTYPE.md exists
|
|
150
|
+
if [[ ! -f "$prototype_md" ]]; then
|
|
151
|
+
err "missing: ${prototype_md}"
|
|
152
|
+
((errors++))
|
|
153
|
+
else
|
|
154
|
+
echo "checking: PROTOTYPE.md exists"
|
|
155
|
+
ok "found: ${prototype_md}"
|
|
156
|
+
|
|
157
|
+
# Check 3: Promotion checklist is complete (no unchecked items in promotion section)
|
|
158
|
+
echo "checking: promotion checklist is complete"
|
|
159
|
+
|
|
160
|
+
# Extract lines between "Promotion Checklist" and next "## " or "Discard Checklist"
|
|
161
|
+
# and check for unchecked items "- [ ]"
|
|
162
|
+
if grep -A 20 "Promotion Checklist" "$prototype_md" 2>/dev/null | \
|
|
163
|
+
grep -B 20 -E "(^## |Discard Checklist)" 2>/dev/null | \
|
|
164
|
+
grep -q "^\- \[ \]"; then
|
|
165
|
+
err "unchecked items in promotion checklist"
|
|
166
|
+
err "hint: complete all items in 'Promotion Checklist' section of PROTOTYPE.md"
|
|
167
|
+
grep -A 20 "Promotion Checklist" "$prototype_md" | grep "^\- \[ \]" | head -5 >&2
|
|
168
|
+
((errors++))
|
|
169
|
+
else
|
|
170
|
+
ok "promotion checklist complete"
|
|
171
|
+
fi
|
|
172
|
+
fi
|
|
173
|
+
|
|
174
|
+
# Check 4: Production design.md exists
|
|
175
|
+
echo "checking: production design.md exists"
|
|
176
|
+
if [[ ! -f "$design_md" ]]; then
|
|
177
|
+
err "missing: ${design_md}"
|
|
178
|
+
err "hint: create production-level design.md with AC-xxx items"
|
|
179
|
+
((errors++))
|
|
180
|
+
else
|
|
181
|
+
ok "found: ${design_md}"
|
|
182
|
+
|
|
183
|
+
# Check 4b: design.md contains AC-xxx items
|
|
184
|
+
echo "checking: design.md contains AC-xxx items"
|
|
185
|
+
if ! grep -qE "AC-[0-9]+" "$design_md" 2>/dev/null; then
|
|
186
|
+
warn "no AC-xxx items found in design.md"
|
|
187
|
+
warn "hint: add acceptance criteria (e.g., AC-001, AC-002)"
|
|
188
|
+
else
|
|
189
|
+
ac_count=$(grep -oE "AC-[0-9]+" "$design_md" | sort -u | wc -l | tr -d ' ')
|
|
190
|
+
ok "found ${ac_count} AC-xxx item(s)"
|
|
191
|
+
fi
|
|
192
|
+
fi
|
|
193
|
+
|
|
194
|
+
# Check 5: Production verification.md exists
|
|
195
|
+
echo "checking: production verification.md exists"
|
|
196
|
+
if [[ ! -f "$verification_md" ]]; then
|
|
197
|
+
err "missing: ${verification_md}"
|
|
198
|
+
err "hint: Test Owner must produce acceptance tests (not just characterization tests)"
|
|
199
|
+
((errors++))
|
|
200
|
+
else
|
|
201
|
+
ok "found: ${verification_md}"
|
|
202
|
+
fi
|
|
203
|
+
|
|
204
|
+
# Check 6: Characterization tests exist (warning only)
|
|
205
|
+
echo "checking: characterization tests exist"
|
|
206
|
+
char_dir="${prototype_dir}/characterization"
|
|
207
|
+
if [[ -d "$char_dir" ]] && [[ -n "$(ls -A "$char_dir" 2>/dev/null)" ]]; then
|
|
208
|
+
char_count=$(find "$char_dir" -type f \( -name "*.py" -o -name "*.ts" -o -name "*.js" -o -name "*.test.*" \) 2>/dev/null | wc -l | tr -d ' ')
|
|
209
|
+
ok "found ${char_count} characterization test file(s)"
|
|
210
|
+
else
|
|
211
|
+
warn "no characterization tests found in ${char_dir}"
|
|
212
|
+
warn "hint: characterization tests help preserve behavior knowledge"
|
|
213
|
+
fi
|
|
214
|
+
|
|
215
|
+
# Check 7: Basic test coverage (P1 - harden-devbooks-quality-gates)
|
|
216
|
+
echo "checking: prototype has basic test coverage"
|
|
217
|
+
proto_src="${prototype_dir}/src"
|
|
218
|
+
if [[ -d "$proto_src" ]]; then
|
|
219
|
+
src_count=$(find "$proto_src" -type f \( -name "*.ts" -o -name "*.js" -o -name "*.py" -o -name "*.sh" \) 2>/dev/null | wc -l | tr -d ' ')
|
|
220
|
+
test_count=$(find "$prototype_dir" -type f \( -name "*.test.*" -o -name "*_test.*" -o -name "*.spec.*" \) 2>/dev/null | wc -l | tr -d ' ')
|
|
221
|
+
|
|
222
|
+
if [[ "$src_count" -gt 0 ]]; then
|
|
223
|
+
if [[ "$test_count" -eq 0 ]]; then
|
|
224
|
+
warn "no test files found for ${src_count} source files in prototype"
|
|
225
|
+
warn "hint: consider adding characterization tests before promotion"
|
|
226
|
+
else
|
|
227
|
+
ratio=$((test_count * 100 / src_count))
|
|
228
|
+
if [[ "$ratio" -lt 50 ]]; then
|
|
229
|
+
warn "low test coverage: ${test_count} test files for ${src_count} source files (${ratio}%)"
|
|
230
|
+
else
|
|
231
|
+
ok "test coverage: ${test_count} test files for ${src_count} source files (${ratio}%)"
|
|
232
|
+
fi
|
|
233
|
+
fi
|
|
234
|
+
fi
|
|
235
|
+
fi
|
|
236
|
+
|
|
237
|
+
# Check 8: Complexity threshold warning (P1 - harden-devbooks-quality-gates)
|
|
238
|
+
echo "checking: prototype complexity"
|
|
239
|
+
if [[ -d "$proto_src" ]]; then
|
|
240
|
+
# Count total lines of code
|
|
241
|
+
total_loc=$(find "$proto_src" -type f \( -name "*.ts" -o -name "*.js" -o -name "*.py" -o -name "*.sh" \) -exec cat {} \; 2>/dev/null | wc -l | tr -d ' ')
|
|
242
|
+
|
|
243
|
+
# Complexity threshold: warn if > 1000 lines (configurable via env)
|
|
244
|
+
complexity_threshold="${PROTOTYPE_COMPLEXITY_THRESHOLD:-1000}"
|
|
245
|
+
|
|
246
|
+
if [[ "$total_loc" -gt "$complexity_threshold" ]]; then
|
|
247
|
+
warn "prototype exceeds complexity threshold: ${total_loc} lines (threshold: ${complexity_threshold})"
|
|
248
|
+
warn "hint: consider breaking into smaller modules before promotion"
|
|
249
|
+
else
|
|
250
|
+
ok "complexity: ${total_loc} lines (threshold: ${complexity_threshold})"
|
|
251
|
+
fi
|
|
252
|
+
fi
|
|
253
|
+
|
|
254
|
+
echo ""
|
|
255
|
+
|
|
256
|
+
# ============================================================================
|
|
257
|
+
# Error summary
|
|
258
|
+
# ============================================================================
|
|
259
|
+
|
|
260
|
+
if [[ $errors -gt 0 ]]; then
|
|
261
|
+
echo "=== Promotion Blocked ==="
|
|
262
|
+
err "${errors} error(s) found"
|
|
263
|
+
echo ""
|
|
264
|
+
echo "Required before promotion:"
|
|
265
|
+
echo " 1. Complete all items in PROTOTYPE.md 'Promotion Checklist'"
|
|
266
|
+
echo " 2. Create production design.md with AC-xxx items"
|
|
267
|
+
echo " 3. Have Test Owner create verification.md with acceptance tests"
|
|
268
|
+
exit 1
|
|
269
|
+
fi
|
|
270
|
+
|
|
271
|
+
# ============================================================================
|
|
272
|
+
# Confirmation
|
|
273
|
+
# ============================================================================
|
|
274
|
+
|
|
275
|
+
echo "=== Ready for Promotion ==="
|
|
276
|
+
echo ""
|
|
277
|
+
echo "This will:"
|
|
278
|
+
echo " 1. Archive characterization tests to: ${archive_dir}/${change_id}/"
|
|
279
|
+
echo " 2. Remove prototype directory: ${prototype_dir}"
|
|
280
|
+
echo ""
|
|
281
|
+
|
|
282
|
+
if [[ "$force" != true ]]; then
|
|
283
|
+
read -r -p "Proceed? [y/N] " response
|
|
284
|
+
case "$response" in
|
|
285
|
+
[yY][eE][sS]|[yY])
|
|
286
|
+
;;
|
|
287
|
+
*)
|
|
288
|
+
echo "aborted"
|
|
289
|
+
exit 0
|
|
290
|
+
;;
|
|
291
|
+
esac
|
|
292
|
+
fi
|
|
293
|
+
|
|
294
|
+
# ============================================================================
|
|
295
|
+
# Execute promotion
|
|
296
|
+
# ============================================================================
|
|
297
|
+
|
|
298
|
+
# Archive characterization tests
|
|
299
|
+
if [[ -d "$char_dir" ]] && [[ -n "$(ls -A "$char_dir" 2>/dev/null)" ]]; then
|
|
300
|
+
mkdir -p "${archive_dir}/${change_id}"
|
|
301
|
+
cp -r "${char_dir}/"* "${archive_dir}/${change_id}/" 2>/dev/null || true
|
|
302
|
+
ok "archived: characterization tests -> ${archive_dir}/${change_id}/"
|
|
303
|
+
fi
|
|
304
|
+
|
|
305
|
+
# Create promotion record
|
|
306
|
+
cat > "${change_dir}/evidence/prototype-promotion.md" <<EOF
|
|
307
|
+
# Prototype Promotion Record
|
|
308
|
+
|
|
309
|
+
- Change ID: ${change_id}
|
|
310
|
+
- Promoted at: $(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
311
|
+
- Characterization tests archived to: ${archive_dir}/${change_id}/
|
|
312
|
+
|
|
313
|
+
## Pre-promotion state
|
|
314
|
+
|
|
315
|
+
- Prototype directory existed: yes
|
|
316
|
+
- PROTOTYPE.md checklist: complete
|
|
317
|
+
- design.md: present
|
|
318
|
+
- verification.md: present
|
|
319
|
+
|
|
320
|
+
## Post-promotion
|
|
321
|
+
|
|
322
|
+
- Prototype directory: removed
|
|
323
|
+
- Production track: active
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
Reference: "The Mythical Man-Month" Chapter 11 - "The first system built is not suitable...plan to throw one away"
|
|
327
|
+
EOF
|
|
328
|
+
ok "created: ${change_dir}/evidence/prototype-promotion.md"
|
|
329
|
+
|
|
330
|
+
# Remove prototype directory
|
|
331
|
+
rm -rf "$prototype_dir"
|
|
332
|
+
ok "removed: ${prototype_dir}"
|
|
333
|
+
|
|
334
|
+
echo ""
|
|
335
|
+
echo "=== Promotion Complete ==="
|
|
336
|
+
ok "prototype promoted for ${change_id}"
|
|
337
|
+
echo ""
|
|
338
|
+
echo "Next steps:"
|
|
339
|
+
echo " 1. Run 'change-check.sh ${change_id} --mode apply' to validate production track"
|
|
340
|
+
echo " 2. Coder implements against verification.md acceptance tests"
|
|
341
|
+
echo " 3. Review characterization tests in ${archive_dir}/${change_id}/ for behavior reference"
|