@grainulation/barn 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.
Files changed (50) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/LICENSE +21 -0
  3. package/README.md +87 -0
  4. package/bin/barn.js +98 -0
  5. package/lib/index.js +93 -0
  6. package/lib/server.js +368 -0
  7. package/package.json +52 -0
  8. package/public/grainulation-tokens.css +321 -0
  9. package/public/index.html +907 -0
  10. package/templates/README.md +48 -0
  11. package/templates/adr.html +223 -0
  12. package/templates/adr.json +29 -0
  13. package/templates/brief.html +297 -0
  14. package/templates/brief.json +26 -0
  15. package/templates/certificate.html +247 -0
  16. package/templates/certificate.json +23 -0
  17. package/templates/changelog.html +239 -0
  18. package/templates/changelog.json +19 -0
  19. package/templates/ci-workflow.yml +52 -0
  20. package/templates/comparison.html +248 -0
  21. package/templates/comparison.json +21 -0
  22. package/templates/conflict-map.html +240 -0
  23. package/templates/conflict-map.json +19 -0
  24. package/templates/dashboard.html +515 -0
  25. package/templates/dashboard.json +22 -0
  26. package/templates/email-digest.html +178 -0
  27. package/templates/email-digest.json +18 -0
  28. package/templates/evidence-matrix.html +232 -0
  29. package/templates/evidence-matrix.json +21 -0
  30. package/templates/explainer.html +342 -0
  31. package/templates/explainer.json +23 -0
  32. package/templates/handoff.html +343 -0
  33. package/templates/handoff.json +24 -0
  34. package/templates/one-pager.html +248 -0
  35. package/templates/one-pager.json +22 -0
  36. package/templates/postmortem.html +303 -0
  37. package/templates/postmortem.json +20 -0
  38. package/templates/rfc.html +199 -0
  39. package/templates/rfc.json +32 -0
  40. package/templates/risk-register.html +231 -0
  41. package/templates/risk-register.json +22 -0
  42. package/templates/slide-deck.html +239 -0
  43. package/templates/slide-deck.json +23 -0
  44. package/templates/template.schema.json +25 -0
  45. package/templates/wiki-page.html +222 -0
  46. package/templates/wiki-page.json +23 -0
  47. package/tools/README.md +31 -0
  48. package/tools/build-pdf.js +43 -0
  49. package/tools/detect-sprints.js +292 -0
  50. package/tools/generate-manifest.js +237 -0
@@ -0,0 +1,24 @@
1
+ {
2
+ "title": "Handoff",
3
+ "description": "Knowledge transfer document for sprint succession. Covers context, decisions, open questions, claim inventory, and continuation guidance for someone with zero prior context.",
4
+ "tags": ["handoff", "transfer", "onboarding", "documentation"],
5
+ "author": "grainulation",
6
+ "version": "1.0.0",
7
+ "exportPresets": [
8
+ { "name": "pdf", "format": "pdf" },
9
+ { "name": "static-site", "format": "html" },
10
+ { "name": "markdown-outline", "format": "md" }
11
+ ],
12
+ "seedPacks": [
13
+ "migration"
14
+ ],
15
+ "scaffoldConfig": {
16
+ "defaultPlaceholders": {
17
+ "TITLE": "Sprint Handoff",
18
+ "SPRINT_NAME": "Untitled Sprint",
19
+ "QUESTION": "",
20
+ "AUDIENCE": "Successor"
21
+ },
22
+ "postInit": ["load-claims", "compile-brief"]
23
+ }
24
+ }
@@ -0,0 +1,248 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>{{SPRINT_NAME}} -- One-Pager</title>
7
+ <style>
8
+ /* barn/templates/one-pager.html — single viewport executive summary
9
+ No scroll, forces ruthless prioritization. Every pixel counts.
10
+ System font stack, no external dependencies, fully self-contained. */
11
+
12
+ :root {
13
+ --bg: #0a0e1a;
14
+ --bg2: #111827;
15
+ --bg3: #1e293b;
16
+ --accent: #3b82f6;
17
+ --accent-light: #60a5fa;
18
+ --green: #22c55e;
19
+ --green-dim: rgba(34,197,94,0.12);
20
+ --orange: #f59e0b;
21
+ --orange-dim: rgba(245,158,11,0.12);
22
+ --red: #e11d48;
23
+ --red-dim: rgba(225,29,72,0.12);
24
+ --purple: #a78bfa;
25
+ --text: #f1f5f9;
26
+ --text-muted: #94a3b8;
27
+ --text-dim: #64748b;
28
+ }
29
+
30
+ * { margin: 0; padding: 0; box-sizing: border-box; }
31
+ html, body { height: 100vh; overflow: hidden; }
32
+
33
+ body {
34
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Inter', sans-serif;
35
+ background: var(--bg);
36
+ color: var(--text);
37
+ -webkit-font-smoothing: antialiased;
38
+ display: flex;
39
+ flex-direction: column;
40
+ height: 100vh;
41
+ padding: 28px 36px 20px;
42
+ }
43
+
44
+ header {
45
+ flex-shrink: 0;
46
+ margin-bottom: 16px;
47
+ border-bottom: 1px solid rgba(255,255,255,0.06);
48
+ padding-bottom: 12px;
49
+ }
50
+
51
+ header h1 {
52
+ font-size: 18pt; font-weight: 700;
53
+ letter-spacing: -0.02em; color: #fff; margin-bottom: 4px;
54
+ }
55
+
56
+ header p {
57
+ font-size: 10pt; color: var(--text-muted);
58
+ line-height: 1.4; max-width: 80%;
59
+ }
60
+
61
+ .sprint-label {
62
+ display: inline-block; font-size: 8pt; font-weight: 600;
63
+ letter-spacing: 0.12em; text-transform: uppercase;
64
+ color: var(--accent-light); background: rgba(59,130,246,0.12);
65
+ padding: 3px 10px; border-radius: 3px; margin-bottom: 8px;
66
+ }
67
+
68
+ main {
69
+ flex: 1;
70
+ display: grid;
71
+ grid-template-columns: 1fr 1fr;
72
+ grid-template-rows: 1fr auto;
73
+ gap: 14px;
74
+ min-height: 0;
75
+ }
76
+
77
+ /* Left column: top 3 findings */
78
+ .findings {
79
+ grid-column: 1; grid-row: 1;
80
+ display: flex; flex-direction: column;
81
+ gap: 10px; min-height: 0; overflow: hidden;
82
+ }
83
+
84
+ .findings h2 {
85
+ font-size: 9pt; font-weight: 600;
86
+ text-transform: uppercase; letter-spacing: 0.1em;
87
+ color: var(--accent-light); flex-shrink: 0;
88
+ }
89
+
90
+ .finding-card {
91
+ background: var(--bg3); border-radius: 8px;
92
+ padding: 12px 14px; border-left: 3px solid var(--accent);
93
+ flex: 1; min-height: 0;
94
+ }
95
+
96
+ .finding-card h3 {
97
+ font-size: 11pt; font-weight: 600;
98
+ color: var(--text); margin-bottom: 4px;
99
+ }
100
+
101
+ .finding-card p {
102
+ font-size: 9pt; color: var(--text-muted); line-height: 1.4;
103
+ }
104
+
105
+ .evidence-badge {
106
+ display: inline-block; font-size: 7pt; font-weight: 600;
107
+ text-transform: uppercase; letter-spacing: 0.08em;
108
+ padding: 2px 6px; border-radius: 3px; margin-top: 4px;
109
+ background: var(--green-dim); color: var(--green);
110
+ }
111
+
112
+ .evidence-badge.web { background: var(--orange-dim); color: var(--orange); }
113
+ .evidence-badge.stated { background: rgba(255,255,255,0.06); color: var(--text-dim); }
114
+ .evidence-badge.tested { background: var(--green-dim); color: var(--green); }
115
+ .evidence-badge.documented { background: rgba(59,130,246,0.12); color: var(--accent-light); }
116
+ .evidence-badge.production { background: rgba(167,139,250,0.12); color: var(--purple); }
117
+
118
+ /* Right column: recommendation + risk */
119
+ .right-col {
120
+ grid-column: 2; grid-row: 1;
121
+ display: flex; flex-direction: column;
122
+ gap: 12px; min-height: 0;
123
+ }
124
+
125
+ .recommendation-box {
126
+ background: var(--bg2); border-radius: 8px;
127
+ padding: 14px 16px; border: 1px solid rgba(59,130,246,0.2);
128
+ flex-shrink: 0;
129
+ }
130
+
131
+ .recommendation-box h2 {
132
+ font-size: 9pt; font-weight: 600;
133
+ text-transform: uppercase; letter-spacing: 0.1em;
134
+ color: var(--accent-light); margin-bottom: 8px;
135
+ }
136
+
137
+ .recommendation-box p {
138
+ font-size: 10pt; color: var(--text); line-height: 1.4;
139
+ }
140
+
141
+ .confidence-meter { margin-top: 10px; }
142
+
143
+ .confidence-meter-label {
144
+ font-size: 8pt; color: var(--text-dim);
145
+ text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 4px;
146
+ }
147
+
148
+ .confidence-track {
149
+ width: 100%; height: 6px;
150
+ background: var(--bg3); border-radius: 3px; overflow: hidden;
151
+ }
152
+
153
+ .confidence-fill {
154
+ height: 100%;
155
+ background: linear-gradient(90deg, var(--accent), var(--green));
156
+ border-radius: 3px; transition: width 0.4s ease;
157
+ }
158
+
159
+ .risk-box {
160
+ background: var(--red-dim); border-radius: 8px;
161
+ padding: 12px 14px; border-left: 3px solid var(--red);
162
+ flex: 1; min-height: 0; overflow: hidden;
163
+ }
164
+
165
+ .risk-box h2 {
166
+ font-size: 9pt; font-weight: 600;
167
+ text-transform: uppercase; letter-spacing: 0.1em;
168
+ color: var(--red); margin-bottom: 6px;
169
+ }
170
+
171
+ .risk-box p { font-size: 9pt; color: var(--text-muted); line-height: 1.4; }
172
+
173
+ /* Footer metadata */
174
+ footer {
175
+ grid-column: 1 / -1; grid-row: 2;
176
+ display: flex; justify-content: space-between; align-items: center;
177
+ padding-top: 8px; border-top: 1px solid rgba(255,255,255,0.06);
178
+ }
179
+
180
+ footer .meta {
181
+ font-size: 8pt; color: var(--text-dim);
182
+ font-family: monospace; letter-spacing: 0.04em;
183
+ }
184
+
185
+ footer .barn-mark { font-size: 8pt; color: var(--text-dim); }
186
+
187
+ @media (max-width: 768px) {
188
+ body { padding: 16px; }
189
+ main { grid-template-columns: 1fr; grid-template-rows: auto auto auto; }
190
+ .right-col { grid-column: 1; grid-row: 2; }
191
+ footer { grid-column: 1; grid-row: 3; }
192
+ header h1 { font-size: 14pt; }
193
+ html, body { height: auto; overflow: auto; }
194
+ }
195
+
196
+ @media print {
197
+ body { background: #fff; color: #111; }
198
+ header h1 { color: #111; }
199
+ header p { color: #333; }
200
+ .finding-card { background: #f5f5f5; border-color: #999; }
201
+ .finding-card h3 { color: #111; }
202
+ .finding-card p, .risk-box p { color: #333; }
203
+ .recommendation-box { background: #f9f9f9; border-color: #ccc; }
204
+ .recommendation-box p { color: #111; }
205
+ .risk-box { background: #fff0f0; }
206
+ .sprint-label { background: #eee; color: #333; }
207
+ footer .meta, footer .barn-mark { color: #999; }
208
+ }
209
+ </style>
210
+ </head>
211
+ <body>
212
+
213
+ <header role="banner" aria-label="Sprint header">
214
+ <span class="sprint-label">{{SPRINT_NAME}}</span>
215
+ <h1>{{QUESTION}}</h1>
216
+ </header>
217
+
218
+ <main role="main" aria-label="One-pager content">
219
+ <section class="findings" aria-label="Top findings">
220
+ <h2>Top Findings</h2>
221
+ {{TOP_FINDINGS}}
222
+ </section>
223
+
224
+ <section class="right-col" aria-label="Recommendation and risk">
225
+ <div class="recommendation-box">
226
+ <h2>Recommendation</h2>
227
+ <p>{{RECOMMENDATION}}</p>
228
+ <div class="confidence-meter">
229
+ <div class="confidence-meter-label">Confidence</div>
230
+ <div class="confidence-track">
231
+ <div class="confidence-fill" style="width: {{CONFIDENCE}}%" aria-label="Confidence level {{CONFIDENCE}} percent"></div>
232
+ </div>
233
+ </div>
234
+ </div>
235
+ <div class="risk-box">
236
+ <h2>Key Risk</h2>
237
+ <p>{{KEY_RISK}}</p>
238
+ </div>
239
+ </section>
240
+
241
+ <footer aria-label="Metadata">
242
+ <span class="meta">{{META}}</span>
243
+ <span class="barn-mark">Built with barn</span>
244
+ </footer>
245
+ </main>
246
+
247
+ </body>
248
+ </html>
@@ -0,0 +1,22 @@
1
+ {
2
+ "title": "One-Pager",
3
+ "description": "Single viewport executive summary. No scroll -- forces ruthless prioritization. Shows top findings, recommendation with confidence meter, and key risk.",
4
+ "tags": ["one-pager", "executive", "summary", "single-page", "mobile"],
5
+ "author": "grainulation",
6
+ "version": "1.0.0",
7
+ "exportPresets": [
8
+ { "name": "pdf", "format": "pdf" },
9
+ { "name": "static-site", "format": "html" }
10
+ ],
11
+ "seedPacks": [],
12
+ "scaffoldConfig": {
13
+ "defaultPlaceholders": {
14
+ "SPRINT_NAME": "Sprint",
15
+ "QUESTION": "Sprint Question",
16
+ "RECOMMENDATION": "",
17
+ "CONFIDENCE": "50",
18
+ "KEY_RISK": ""
19
+ },
20
+ "postInit": ["load-claims", "compile-brief"]
21
+ }
22
+ }
@@ -0,0 +1,303 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>{{TITLE}} — Postmortem</title>
7
+ <style>
8
+ /* barn/templates/postmortem.html — calibration and retrospective document
9
+ System font stack, no external dependencies, fully self-contained. */
10
+
11
+ :root {
12
+ --bg: #0a0e1a;
13
+ --bg2: #111827;
14
+ --bg3: #1e293b;
15
+ --accent: #3b82f6;
16
+ --accent-light: #60a5fa;
17
+ --green: #22c55e;
18
+ --orange: #f59e0b;
19
+ --red: #e11d48;
20
+ --purple: #a78bfa;
21
+ --text: #f1f5f9;
22
+ --text-muted: #94a3b8;
23
+ --text-dim: #64748b;
24
+ --border: rgba(255,255,255,0.06);
25
+ }
26
+
27
+ * { margin: 0; padding: 0; box-sizing: border-box; }
28
+ html { height: 100%; scroll-behavior: smooth; scroll-snap-type: y mandatory; overflow-y: scroll; }
29
+
30
+ body {
31
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Inter', sans-serif;
32
+ background: var(--bg);
33
+ color: var(--text);
34
+ font-size: 11pt;
35
+ line-height: 1.5;
36
+ -webkit-font-smoothing: antialiased;
37
+ }
38
+
39
+ section {
40
+ min-height: 100vh;
41
+ padding: 60px 80px;
42
+ display: flex;
43
+ flex-direction: column;
44
+ justify-content: center;
45
+ scroll-snap-align: start;
46
+ position: relative;
47
+ }
48
+
49
+ section::before {
50
+ content: '';
51
+ position: absolute;
52
+ top: 0; right: 0;
53
+ width: 35%; height: 100%;
54
+ background: radial-gradient(ellipse at top right, rgba(59,130,246,0.06) 0%, transparent 70%);
55
+ pointer-events: none;
56
+ }
57
+
58
+ h1 {
59
+ font-size: 36pt;
60
+ font-weight: 800;
61
+ letter-spacing: -0.03em;
62
+ line-height: 1.1;
63
+ margin-bottom: 12px;
64
+ background: linear-gradient(135deg, #fff 0%, #94a3b8 100%);
65
+ -webkit-background-clip: text;
66
+ -webkit-text-fill-color: transparent;
67
+ }
68
+
69
+ h2 {
70
+ font-size: 24pt;
71
+ font-weight: 700;
72
+ letter-spacing: -0.02em;
73
+ margin-bottom: 20px;
74
+ color: #fff;
75
+ }
76
+
77
+ .section-label {
78
+ display: inline-block;
79
+ font-size: 9pt;
80
+ font-weight: 600;
81
+ letter-spacing: 0.12em;
82
+ text-transform: uppercase;
83
+ color: var(--accent-light);
84
+ background: rgba(59,130,246,0.12);
85
+ padding: 4px 12px;
86
+ border-radius: 4px;
87
+ margin-bottom: 16px;
88
+ }
89
+
90
+ .outcome-block {
91
+ background: var(--bg2);
92
+ border-left: 3px solid var(--accent);
93
+ padding: 16px 24px;
94
+ border-radius: 0 8px 8px 0;
95
+ margin-top: 20px;
96
+ max-width: 80%;
97
+ font-size: 13pt;
98
+ color: var(--text-muted);
99
+ line-height: 1.5;
100
+ }
101
+
102
+ .sprint-label { font-size: 10pt; color: var(--text-dim); margin-top: 12px; }
103
+ .sprint-label strong { color: var(--text-muted); }
104
+
105
+ .comparison-grid {
106
+ display: grid;
107
+ grid-template-columns: 1fr 1fr;
108
+ gap: 0;
109
+ }
110
+
111
+ .comparison-header {
112
+ padding: 12px 20px;
113
+ font-size: 9pt;
114
+ font-weight: 700;
115
+ text-transform: uppercase;
116
+ letter-spacing: 0.1em;
117
+ border-bottom: 2px solid var(--border);
118
+ }
119
+
120
+ .comparison-header.prediction {
121
+ background: var(--bg2);
122
+ color: var(--accent-light);
123
+ border-right: 1px solid var(--border);
124
+ border-radius: 8px 0 0 0;
125
+ }
126
+
127
+ .comparison-header.outcome {
128
+ background: var(--bg2);
129
+ color: var(--green);
130
+ border-radius: 0 8px 0 0;
131
+ }
132
+
133
+ .comparison-cell {
134
+ padding: 14px 20px;
135
+ font-size: 10pt;
136
+ color: var(--text-muted);
137
+ line-height: 1.5;
138
+ border-bottom: 1px solid var(--border);
139
+ }
140
+
141
+ .comparison-cell.prediction {
142
+ background: rgba(17,24,39,0.5);
143
+ border-right: 1px solid var(--border);
144
+ }
145
+
146
+ .comparison-cell.outcome { background: rgba(30,41,59,0.3); }
147
+ .comparison-cell .claim-id { font-family: monospace; font-size: 8pt; color: var(--text-dim); display: block; margin-top: 4px; }
148
+
149
+ .score-panel {
150
+ background: var(--bg2);
151
+ border-radius: 16px;
152
+ padding: 32px;
153
+ border: 1px solid var(--border);
154
+ display: flex;
155
+ gap: 40px;
156
+ align-items: center;
157
+ max-width: 600px;
158
+ }
159
+
160
+ .score-big { font-size: 48pt; font-weight: 800; line-height: 1; }
161
+ .score-big.good { color: var(--green); }
162
+ .score-big.mid { color: var(--orange); }
163
+ .score-big.low { color: var(--red); }
164
+
165
+ .score-details { flex: 1; }
166
+
167
+ .score-row {
168
+ display: flex;
169
+ justify-content: space-between;
170
+ padding: 6px 0;
171
+ border-bottom: 1px solid var(--border);
172
+ font-size: 10pt;
173
+ color: var(--text-muted);
174
+ }
175
+
176
+ .score-row:last-child { border-bottom: none; }
177
+ .score-row .label { color: var(--text-dim); }
178
+
179
+ .surprise-card {
180
+ background: var(--bg2);
181
+ border-radius: 10px;
182
+ padding: 16px 20px;
183
+ border: 1px solid var(--border);
184
+ border-left: 3px solid var(--orange);
185
+ margin-bottom: 12px;
186
+ font-size: 10pt;
187
+ color: var(--text-muted);
188
+ line-height: 1.5;
189
+ }
190
+
191
+ .lesson-card {
192
+ background: var(--bg2);
193
+ border-radius: 10px;
194
+ padding: 16px 20px;
195
+ border: 1px solid var(--border);
196
+ border-left: 3px solid var(--purple);
197
+ margin-bottom: 12px;
198
+ font-size: 10pt;
199
+ color: var(--text-muted);
200
+ line-height: 1.5;
201
+ }
202
+
203
+ .barn-footer {
204
+ position: absolute;
205
+ bottom: 24px; right: 40px;
206
+ font-size: 8pt;
207
+ color: var(--text-dim);
208
+ letter-spacing: 0.05em;
209
+ }
210
+
211
+ nav[aria-label="sections"] {
212
+ position: fixed; right: 24px; top: 50%; transform: translateY(-50%);
213
+ display: flex; flex-direction: column; gap: 8px; z-index: 100;
214
+ }
215
+
216
+ nav[aria-label="sections"] a {
217
+ width: 8px; height: 8px; border-radius: 50%;
218
+ background: var(--text-dim); display: block; transition: all 0.2s;
219
+ }
220
+
221
+ nav[aria-label="sections"] a:hover { background: var(--accent); transform: scale(1.5); }
222
+
223
+ @media (max-width: 768px) {
224
+ section { padding: 32px 20px; height: auto; }
225
+ h1 { font-size: 22pt; } h2 { font-size: 18pt; }
226
+ .outcome-block { max-width: 100%; font-size: 11pt; }
227
+ .comparison-grid { grid-template-columns: 1fr; }
228
+ .comparison-header.prediction { border-right: none; border-radius: 8px 8px 0 0; }
229
+ .comparison-header.outcome { border-radius: 0; }
230
+ .comparison-cell.prediction { border-right: none; }
231
+ .score-panel { flex-direction: column; gap: 16px; text-align: center; }
232
+ .score-big { font-size: 36pt; }
233
+ nav[aria-label="sections"] { display: none; }
234
+ .barn-footer { right: 20px; bottom: 16px; }
235
+ }
236
+
237
+ @media print {
238
+ html { scroll-snap-type: none; }
239
+ section { min-height: auto; height: auto; page-break-after: always; padding: 40px; }
240
+ body { background: #fff; color: #1a1a1a; }
241
+ h1 { background: none; -webkit-text-fill-color: #1a1a1a; }
242
+ h2 { color: #1a1a1a; }
243
+ .outcome-block, .surprise-card, .lesson-card, .score-panel { background: #f5f5f5; border-color: #ddd; }
244
+ .comparison-cell { color: #333; }
245
+ nav[aria-label="sections"], .barn-footer { display: none; }
246
+ }
247
+ </style>
248
+ </head>
249
+ <body>
250
+
251
+ <nav aria-label="sections">
252
+ <a href="#header" title="Overview"></a>
253
+ <a href="#comparison" title="Predictions vs Outcomes"></a>
254
+ <a href="#score" title="Calibration Score"></a>
255
+ <a href="#surprises" title="Surprises"></a>
256
+ <a href="#lessons" title="Lessons Learned"></a>
257
+ </nav>
258
+
259
+ <section id="header" aria-label="Postmortem Overview">
260
+ <span class="section-label">Postmortem</span>
261
+ <h1>{{TITLE}}</h1>
262
+ <div class="sprint-label">Sprint: <strong>{{SPRINT_NAME}}</strong></div>
263
+ <div class="outcome-block">{{OUTCOME}}</div>
264
+ <div class="barn-footer">Built with barn</div>
265
+ </section>
266
+
267
+ <section id="comparison" aria-label="Predictions vs Outcomes">
268
+ <span class="section-label">Calibration</span>
269
+ <h2>Prediction vs Outcome</h2>
270
+ <div class="comparison-grid">
271
+ <div class="comparison-header prediction">What We Predicted</div>
272
+ <div class="comparison-header outcome">What Actually Happened</div>
273
+ {{PREDICTIONS_VS_OUTCOMES}}
274
+ </div>
275
+ </section>
276
+
277
+ <section id="score" aria-label="Calibration Score">
278
+ <span class="section-label">Accuracy</span>
279
+ <h2>Calibration Score</h2>
280
+ <div class="score-panel">
281
+ <div class="score-big" id="scoreValue">{{CALIBRATION_SCORE}}</div>
282
+ <div class="score-details">
283
+ <div class="score-row"><span class="label">Accuracy Rate</span><span>{{ACCURACY_RATE}}</span></div>
284
+ <div class="score-row"><span class="label">Predictions Made</span><span>{{PREDICTION_COUNT}}</span></div>
285
+ <div class="score-row"><span class="label">Correct</span><span>{{CORRECT_COUNT}}</span></div>
286
+ </div>
287
+ </div>
288
+ </section>
289
+
290
+ <section id="surprises" aria-label="Surprises">
291
+ <span class="section-label">Unexpected</span>
292
+ <h2>What We Did Not Predict</h2>
293
+ {{SURPRISES}}
294
+ </section>
295
+
296
+ <section id="lessons" aria-label="Lessons Learned">
297
+ <span class="section-label">Retrospective</span>
298
+ <h2>Lessons Learned</h2>
299
+ {{LESSONS}}
300
+ </section>
301
+
302
+ </body>
303
+ </html>
@@ -0,0 +1,20 @@
1
+ {
2
+ "title": "Postmortem",
3
+ "description": "Calibration and retrospective document for sprint outcomes. Two-column prediction vs outcome comparison, accuracy scoring, surprises, and lessons learned.",
4
+ "tags": ["postmortem", "calibration", "retrospective", "learning"],
5
+ "author": "grainulation",
6
+ "version": "1.0.0",
7
+ "exportPresets": [
8
+ { "name": "pdf", "format": "pdf" },
9
+ { "name": "static-site", "format": "html" }
10
+ ],
11
+ "seedPacks": [],
12
+ "scaffoldConfig": {
13
+ "defaultPlaceholders": {
14
+ "TITLE": "Sprint Postmortem",
15
+ "SPRINT_NAME": "Untitled Sprint",
16
+ "OUTCOME": ""
17
+ },
18
+ "postInit": ["load-claims", "load-calibration"]
19
+ }
20
+ }