arcane-cli 0.34.2 โ 0.35.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/README.md +4 -1
- package/dist/assets/.github/prompts/spell-close-session.prompt.md +2 -0
- package/dist/assets/.github/prompts/spell-commit-work.prompt.md +6 -0
- package/dist/assets/.github/prompts/spell-create-pull-request.prompt.md +20 -0
- package/dist/assets/report/show-report.template.html +382 -0
- package/dist/index.js +680 -7
- package/dist/index.js.map +1 -1
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -116,7 +116,7 @@ Arcane isn't a prompt snippet โ it's a full framework. Everything installs int
|
|
|
116
116
|
| ๐ **Spells** | **<!--count:spells-->41<!--/count:spells-->** prompt-driven workflows spanning the entire lifecycle โ planning, architecture, implementation, testing, review, shipping, session management, and ops. |
|
|
117
117
|
| โ๏ธ **Governance** | **<!--count:governance-->25<!--/count:governance-->** battle-tested standards as drop-in templates: git conventions, testing standards, CI/CD, threat model, ADR format, naming, security hardening, and more. |
|
|
118
118
|
| ๐ค **Agents** | **<!--count:agents-->12<!--/count:agents-->** ready-made agent personas with roles, clusters, and a gamified autonomy model โ assign work and power levels per repo. |
|
|
119
|
-
| ๐ ๏ธ **CLI** | `spell init / add / update / status / uninstall` โ install by profile or ร la carte, and keep everything in sync as new versions ship. |
|
|
119
|
+
| ๐ ๏ธ **CLI** | `spell init / add / update / status / uninstall` โ install by profile or ร la carte, and keep everything in sync as new versions ship. `spell report` turns a program's `PLAN.md` into a Show Report โ a generated completion page โ offline. |
|
|
120
120
|
|
|
121
121
|
<!-- arcane:start -->
|
|
122
122
|
<details>
|
|
@@ -195,6 +195,9 @@ spell agents init
|
|
|
195
195
|
# Keep your installed governance current
|
|
196
196
|
spell status # what's installed + available updates
|
|
197
197
|
spell update # pull the latest
|
|
198
|
+
|
|
199
|
+
# When a program in docs/plans/<slug>/ has shipped, generate its Show Report -- offline
|
|
200
|
+
spell report # writes docs/plans/<slug>/show-report.{json,html}
|
|
198
201
|
```
|
|
199
202
|
|
|
200
203
|
> **`spell` or `arcane`?** Both commands invoke the same CLI. `spell` ties to the Spell Loop; `arcane` is there for when you reach for the brand name. Use whichever you like.
|
|
@@ -71,6 +71,8 @@ Workflow:
|
|
|
71
71
|
|
|
72
72
|
4c. **Follow-up promotion sweep (LH-09; only when this repo has its own `scripts/check-followups.ts` โ Arcane's own repo, or one that adopted the same convention; skip gracefully otherwise).** Run `npm run check:followups` (or the closest journal-scoped equivalent) and check whether this session's own journal entry or closure notes contain a deferral phrase ("filed as a separate", "follow-up", "out of scope", "not fixed here", "left open", "deferred", "revisit", "future work") with no tracker token nearby (`TODO`, `IDEAS`, `Q-NNN`, `ARC-NNN`, `EF-NN`, `RCA-NNN`, a PR URL) and no explicit `(untracked: <reason>)` opt-out. Promote each real hit to `TODO.md`/`IDEAS.md` before writing the handoff, or add the opt-out inline. Report-only tool โ a hit is a prompt to check, not proof of an untracked gap; skip anything that's already tracked elsewhere in the same document.
|
|
73
73
|
|
|
74
|
+
4d. **Record the epic's reader-facing line (only when this session shipped an epic of a tracked program โ one with a `docs/plans/<slug>/PLAN.md`; skip entirely otherwise).** Copy the `## For the record` sentence from the epic's own PR description verbatim into that epic's `PLAN.md` entry as its `**Report:**` line, in the format `**Report:** <sentence> ยท category: <spell|feature|governance|decision|fix|process|docs|platform> ยท glyph: <emoji>`, alongside the PR number the epic ticked with. Authored at PR time (see `spell-create-pull-request` Step 4) and copied here โ never re-invented at close, and never substituted with the commit subject, which describes the change to an engineer rather than to the program's reader. **If the PR carried no such section**, leave the line absent rather than writing one from memory: the generator renders a missing description visibly as `unwritten`, and a visible gap someone can fill later is worth more than a plausible sentence nobody verified. Where a completion report is generated (`npm run check:report` / `spell report`), regenerate it after this edit so the committed artifact matches its sources.
|
|
75
|
+
|
|
74
76
|
5. **Update [ai-context/system-prompt-context.md](../../ai-context/system-prompt-context.md).**
|
|
75
77
|
- If priorities, environment state, or agent rules changed during the session, update the file to reflect current reality.
|
|
76
78
|
- If no changes are needed, skip this step.
|
|
@@ -205,6 +205,12 @@ Workflow:
|
|
|
205
205
|
- Structured `###` sections for each logical change area.
|
|
206
206
|
- A `### Testing` checklist (`- [x]` / `- [ ]`).
|
|
207
207
|
- Tables/code blocks where they improve clarity.
|
|
208
|
+
- `## For the record` โ **only when this PR is one epic of a tracked program** (one with a
|
|
209
|
+
`docs/plans/<slug>/PLAN.md`); omit the heading entirely otherwise. One plain sentence a
|
|
210
|
+
non-engineer reading the finished program would understand, plus `ยท category: <โฆ> ยท glyph: <โฆ>`.
|
|
211
|
+
It is copied verbatim into the epic's `PLAN.md` entry as its `**Report:**` line when the epic
|
|
212
|
+
is recorded. See `spell-create-pull-request`'s Step 4 for the full convention โ defined there,
|
|
213
|
+
referenced here.
|
|
208
214
|
|
|
209
215
|
g. Capture PR ID/URL from command output.
|
|
210
216
|
- Always render PRs as clickable markdown links with the full URL.
|
|
@@ -125,6 +125,12 @@ Standard template:
|
|
|
125
125
|
## Testing
|
|
126
126
|
|
|
127
127
|
- <coverage / test status if known, else "See CI pipeline results.">
|
|
128
|
+
|
|
129
|
+
## For the record
|
|
130
|
+
|
|
131
|
+
<One plain sentence a non-engineer reviewing the finished program would read โ what changed for
|
|
132
|
+
them, not how it was built. Omit this section entirely when the PR is not one epic of a tracked
|
|
133
|
+
program.> ยท category: <spell|feature|governance|decision|fix|process|docs|platform> ยท glyph: <emoji>
|
|
128
134
|
```
|
|
129
135
|
|
|
130
136
|
`--docs-only` template (skip Testing):
|
|
@@ -138,8 +144,22 @@ Standard template:
|
|
|
138
144
|
|
|
139
145
|
## Notes
|
|
140
146
|
Documentation-only PR. No functional code changed.
|
|
147
|
+
|
|
148
|
+
## For the record
|
|
149
|
+
|
|
150
|
+
<Same as above โ include only when this PR is one epic of a tracked program.> ยท category: docs ยท glyph: <emoji>
|
|
141
151
|
```
|
|
142
152
|
|
|
153
|
+
**About `## For the record`** โ include it **only when this PR is one epic of a tracked program**
|
|
154
|
+
(one with a `docs/plans/<slug>/PLAN.md`); omit the heading entirely otherwise, since an empty
|
|
155
|
+
section is worse than none. Write the sentence that program's completion report will show for this
|
|
156
|
+
epic, in the reader's language rather than the implementation's โ what changed for someone reading
|
|
157
|
+
the finished program, not how it was built. Authoring it here, while the work is fresh, is the
|
|
158
|
+
point: it is copied verbatim into the epic's `PLAN.md` entry as its `**Report:**` line when the
|
|
159
|
+
epic is recorded (`spell-close-session` step 4d). An epic that never gets one renders visibly as
|
|
160
|
+
**unwritten** in the report โ never as a pasted commit subject โ so a missing line stays a visible
|
|
161
|
+
gap rather than a silently fabricated one.
|
|
162
|
+
|
|
143
163
|
## Step 5 โ Create the PR
|
|
144
164
|
|
|
145
165
|
- **GitHub:**
|
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<!--
|
|
3
|
+
show-report template v0 (interim) -- SR-02.
|
|
4
|
+
The hand-written completion-ledger CSS/markup from this repository's own
|
|
5
|
+
two prior programs, converted to the Mustache grammar so the data contract
|
|
6
|
+
and the --check/--fix automation are real today. The v0 look is a
|
|
7
|
+
placeholder: the shipped design comes from arcane-ui's static-export
|
|
8
|
+
build (SR-05b) and drops into this same file slot in SR-06, at which point
|
|
9
|
+
the header below records the arcane-ui version and license notice it was
|
|
10
|
+
compiled from. Nothing here is arcane-ui source; this CSS was authored in
|
|
11
|
+
this MIT repository.
|
|
12
|
+
Rendered by: src/modules/show-report/render.ts (mustache). Zero runtime JS.
|
|
13
|
+
-->
|
|
14
|
+
<html lang="en">
|
|
15
|
+
<head>
|
|
16
|
+
<meta charset="utf-8">
|
|
17
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
18
|
+
<title>{{masthead.title}}</title>
|
|
19
|
+
<style>
|
|
20
|
+
:root {
|
|
21
|
+
--bg: #eef0f4;
|
|
22
|
+
--surface: #ffffff;
|
|
23
|
+
--ink: #1a1d2b;
|
|
24
|
+
--ink-soft: #565b72;
|
|
25
|
+
--ink-faint: #8a8fa3;
|
|
26
|
+
--accent: #b8802e;
|
|
27
|
+
--accent-2: #3e7a72;
|
|
28
|
+
--line: #dadde3;
|
|
29
|
+
--row-alt: #f6f7f9;
|
|
30
|
+
--shadow: rgba(26, 29, 43, 0.06);
|
|
31
|
+
--needs: #a6503a;
|
|
32
|
+
--needs-bg: #f7e6e1;
|
|
33
|
+
|
|
34
|
+
--cat-spell: #b8802e; --cat-spell-bg: #f6ead6;
|
|
35
|
+
--cat-feature: #3e7a72; --cat-feature-bg: #dcede9;
|
|
36
|
+
--cat-governance: #7a5c8a; --cat-governance-bg: #ece2f0;
|
|
37
|
+
--cat-decision: #4a5d8a; --cat-decision-bg: #e0e4f0;
|
|
38
|
+
--cat-fix: #a6503a; --cat-fix-bg: #f3ded8;
|
|
39
|
+
--cat-process: #6b7a3f; --cat-process-bg: #e6ead9;
|
|
40
|
+
--cat-docs: #6b7290; --cat-docs-bg: #e6e7ee;
|
|
41
|
+
--cat-platform: #39525a; --cat-platform-bg: #dde4e5;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@media (prefers-color-scheme: dark) {
|
|
45
|
+
:root:not([data-theme="light"]) {
|
|
46
|
+
--bg: #12141c;
|
|
47
|
+
--surface: #181b26;
|
|
48
|
+
--ink: #ede9e0;
|
|
49
|
+
--ink-soft: #9da3b8;
|
|
50
|
+
--ink-faint: #6c728a;
|
|
51
|
+
--accent: #d9a44e;
|
|
52
|
+
--accent-2: #6fafa5;
|
|
53
|
+
--line: #2a2e3d;
|
|
54
|
+
--row-alt: #1d202c;
|
|
55
|
+
--shadow: rgba(0, 0, 0, 0.35);
|
|
56
|
+
--needs: #e08a71;
|
|
57
|
+
--needs-bg: #3a2620;
|
|
58
|
+
|
|
59
|
+
--cat-spell: #e0b064; --cat-spell-bg: #3a2e1a;
|
|
60
|
+
--cat-feature: #7fc2b8; --cat-feature-bg: #17322e;
|
|
61
|
+
--cat-governance: #c19bd4; --cat-governance-bg: #2f2438;
|
|
62
|
+
--cat-decision: #8fa3d6; --cat-decision-bg: #202942;
|
|
63
|
+
--cat-fix: #e08a71; --cat-fix-bg: #3a2620;
|
|
64
|
+
--cat-process: #a3b876; --cat-process-bg: #2a3020;
|
|
65
|
+
--cat-docs: #adb2c9; --cat-docs-bg: #262a38;
|
|
66
|
+
--cat-platform: #7fa3ac; --cat-platform-bg: #1c2c2f;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
:root[data-theme="dark"] {
|
|
71
|
+
--bg: #12141c;
|
|
72
|
+
--surface: #181b26;
|
|
73
|
+
--ink: #ede9e0;
|
|
74
|
+
--ink-soft: #9da3b8;
|
|
75
|
+
--ink-faint: #6c728a;
|
|
76
|
+
--accent: #d9a44e;
|
|
77
|
+
--accent-2: #6fafa5;
|
|
78
|
+
--line: #2a2e3d;
|
|
79
|
+
--row-alt: #1d202c;
|
|
80
|
+
--shadow: rgba(0, 0, 0, 0.35);
|
|
81
|
+
--needs: #e08a71;
|
|
82
|
+
--needs-bg: #3a2620;
|
|
83
|
+
|
|
84
|
+
--cat-spell: #e0b064; --cat-spell-bg: #3a2e1a;
|
|
85
|
+
--cat-feature: #7fc2b8; --cat-feature-bg: #17322e;
|
|
86
|
+
--cat-governance: #c19bd4; --cat-governance-bg: #2f2438;
|
|
87
|
+
--cat-decision: #8fa3d6; --cat-decision-bg: #202942;
|
|
88
|
+
--cat-fix: #e08a71; --cat-fix-bg: #3a2620;
|
|
89
|
+
--cat-process: #a3b876; --cat-process-bg: #2a3020;
|
|
90
|
+
--cat-docs: #adb2c9; --cat-docs-bg: #262a38;
|
|
91
|
+
--cat-platform: #7fa3ac; --cat-platform-bg: #1c2c2f;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
* { box-sizing: border-box; }
|
|
95
|
+
|
|
96
|
+
body {
|
|
97
|
+
margin: 0;
|
|
98
|
+
background: var(--bg);
|
|
99
|
+
color: var(--ink);
|
|
100
|
+
font-family: "IBM Plex Sans", -apple-system, "Segoe UI", sans-serif;
|
|
101
|
+
line-height: 1.5;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
a { color: var(--accent-2); }
|
|
105
|
+
a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }
|
|
106
|
+
code { font-family: "IBM Plex Mono", monospace; font-size: 0.92em; }
|
|
107
|
+
|
|
108
|
+
.page { max-width: 920px; margin: 0 auto; padding: 3rem 1.5rem 5rem; }
|
|
109
|
+
|
|
110
|
+
header.masthead { margin-bottom: 2.25rem; }
|
|
111
|
+
|
|
112
|
+
.eyebrow {
|
|
113
|
+
font-family: "IBM Plex Mono", monospace;
|
|
114
|
+
font-size: 0.72rem;
|
|
115
|
+
letter-spacing: 0.14em;
|
|
116
|
+
text-transform: uppercase;
|
|
117
|
+
color: var(--accent);
|
|
118
|
+
margin: 0 0 0.6rem;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
h1 {
|
|
122
|
+
font-family: "Fraunces", Georgia, serif;
|
|
123
|
+
font-weight: 600;
|
|
124
|
+
font-size: clamp(2rem, 5vw, 2.85rem);
|
|
125
|
+
letter-spacing: -0.01em;
|
|
126
|
+
margin: 0 0 0.5rem;
|
|
127
|
+
text-wrap: balance;
|
|
128
|
+
color: var(--ink);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.dek { font-size: 1.02rem; color: var(--ink-soft); max-width: 62ch; margin: 0 0 1.5rem; }
|
|
132
|
+
|
|
133
|
+
dl.stat-rail {
|
|
134
|
+
display: flex;
|
|
135
|
+
flex-wrap: wrap;
|
|
136
|
+
gap: 0.5rem 1.75rem;
|
|
137
|
+
margin: 0;
|
|
138
|
+
padding: 1rem 1.25rem;
|
|
139
|
+
background: var(--surface);
|
|
140
|
+
border: 1px solid var(--line);
|
|
141
|
+
border-radius: 10px;
|
|
142
|
+
box-shadow: 0 1px 2px var(--shadow);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.stat { display: flex; flex-direction: column; gap: 0.15rem; margin: 0; }
|
|
146
|
+
|
|
147
|
+
.stat dd {
|
|
148
|
+
margin: 0;
|
|
149
|
+
font-family: "IBM Plex Mono", monospace;
|
|
150
|
+
font-variant-numeric: tabular-nums;
|
|
151
|
+
font-size: 1.3rem;
|
|
152
|
+
font-weight: 600;
|
|
153
|
+
color: var(--ink);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.stat dt { font-size: 0.72rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-faint); }
|
|
157
|
+
|
|
158
|
+
.needs-you {
|
|
159
|
+
margin-top: 1.25rem;
|
|
160
|
+
padding: 0.9rem 1.1rem;
|
|
161
|
+
border-radius: 10px;
|
|
162
|
+
border: 1px solid var(--needs);
|
|
163
|
+
background: var(--needs-bg);
|
|
164
|
+
}
|
|
165
|
+
.needs-you h2 { margin: 0 0 0.4rem; font-size: 0.95rem; color: var(--needs); font-family: "IBM Plex Sans", sans-serif; }
|
|
166
|
+
.needs-you ul { margin: 0; padding-left: 1.1rem; font-size: 0.88rem; }
|
|
167
|
+
.needs-you li { margin: 0.2rem 0; }
|
|
168
|
+
.needs-you.none { border-color: var(--line); background: var(--surface); color: var(--ink-soft); }
|
|
169
|
+
.needs-you.none h2 { color: var(--accent-2); }
|
|
170
|
+
|
|
171
|
+
.outcome { margin: 1rem 0 0; font-size: 0.92rem; color: var(--ink-soft); }
|
|
172
|
+
|
|
173
|
+
.legend {
|
|
174
|
+
display: flex;
|
|
175
|
+
flex-wrap: wrap;
|
|
176
|
+
gap: 0.5rem 1rem;
|
|
177
|
+
margin: 1.75rem 0 0.25rem;
|
|
178
|
+
padding: 1.5rem 0 0;
|
|
179
|
+
border-top: 1px solid var(--line);
|
|
180
|
+
list-style: none;
|
|
181
|
+
}
|
|
182
|
+
.legend-item { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.76rem; color: var(--ink-soft); }
|
|
183
|
+
.swatch { width: 0.6rem; height: 0.6rem; border-radius: 50%; flex: none; }
|
|
184
|
+
|
|
185
|
+
section.phase { margin-top: 2.5rem; }
|
|
186
|
+
|
|
187
|
+
.phase-label { display: flex; align-items: baseline; gap: 0.75rem; margin-bottom: 0.9rem; }
|
|
188
|
+
.phase-label h2 {
|
|
189
|
+
font-family: "Fraunces", Georgia, serif;
|
|
190
|
+
font-weight: 600;
|
|
191
|
+
font-size: 1.15rem;
|
|
192
|
+
color: var(--ink);
|
|
193
|
+
margin: 0;
|
|
194
|
+
white-space: nowrap;
|
|
195
|
+
}
|
|
196
|
+
.phase-label .rule { flex: 1; height: 1px; background: var(--line); }
|
|
197
|
+
.phase-note { font-size: 0.82rem; color: var(--ink-faint); margin: -0.4rem 0 0.9rem; }
|
|
198
|
+
|
|
199
|
+
ol.ledger {
|
|
200
|
+
list-style: none;
|
|
201
|
+
margin: 0;
|
|
202
|
+
padding: 0;
|
|
203
|
+
background: var(--surface);
|
|
204
|
+
border: 1px solid var(--line);
|
|
205
|
+
border-radius: 10px;
|
|
206
|
+
overflow: hidden;
|
|
207
|
+
box-shadow: 0 1px 2px var(--shadow);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.row {
|
|
211
|
+
display: grid;
|
|
212
|
+
grid-template-columns: minmax(180px, 26%) 1fr auto;
|
|
213
|
+
gap: 1rem;
|
|
214
|
+
padding: 0.85rem 1.1rem;
|
|
215
|
+
border-top: 1px solid var(--line);
|
|
216
|
+
align-items: center;
|
|
217
|
+
}
|
|
218
|
+
.row:first-child { border-top: none; }
|
|
219
|
+
.row:nth-child(even) { background: var(--row-alt); }
|
|
220
|
+
|
|
221
|
+
.item-title { display: flex; align-items: flex-start; gap: 0.55rem; font-weight: 600; font-size: 0.94rem; color: var(--ink); }
|
|
222
|
+
.item-title .emoji { font-size: 1.05rem; line-height: 1.3; flex: none; }
|
|
223
|
+
.item-title a { color: inherit; text-decoration: none; }
|
|
224
|
+
.item-title a:hover { text-decoration: underline; }
|
|
225
|
+
.item-id { font-family: "IBM Plex Mono", monospace; font-size: 0.7rem; color: var(--ink-faint); margin-left: 0.4rem; font-weight: 500; }
|
|
226
|
+
|
|
227
|
+
.item-desc { font-size: 0.87rem; color: var(--ink-soft); max-width: 58ch; }
|
|
228
|
+
.item-desc.unwritten { color: var(--ink-faint); font-style: italic; }
|
|
229
|
+
|
|
230
|
+
.pill {
|
|
231
|
+
justify-self: end;
|
|
232
|
+
font-size: 0.7rem;
|
|
233
|
+
font-weight: 600;
|
|
234
|
+
letter-spacing: 0.02em;
|
|
235
|
+
padding: 0.28rem 0.6rem;
|
|
236
|
+
border-radius: 999px;
|
|
237
|
+
white-space: nowrap;
|
|
238
|
+
}
|
|
239
|
+
.pill.spell { color: var(--cat-spell); background: var(--cat-spell-bg); }
|
|
240
|
+
.pill.feature { color: var(--cat-feature); background: var(--cat-feature-bg); }
|
|
241
|
+
.pill.governance { color: var(--cat-governance); background: var(--cat-governance-bg); }
|
|
242
|
+
.pill.decision { color: var(--cat-decision); background: var(--cat-decision-bg); }
|
|
243
|
+
.pill.fix { color: var(--cat-fix); background: var(--cat-fix-bg); }
|
|
244
|
+
.pill.process { color: var(--cat-process); background: var(--cat-process-bg); }
|
|
245
|
+
.pill.docs { color: var(--cat-docs); background: var(--cat-docs-bg); }
|
|
246
|
+
.pill.platform { color: var(--cat-platform); background: var(--cat-platform-bg); }
|
|
247
|
+
|
|
248
|
+
.parked-list, .cast-list { margin: 0; padding-left: 1.1rem; font-size: 0.87rem; color: var(--ink-soft); }
|
|
249
|
+
.parked-list li, .cast-list li { margin: 0.3rem 0; }
|
|
250
|
+
.parked-list strong { color: var(--ink); }
|
|
251
|
+
|
|
252
|
+
footer.colophon {
|
|
253
|
+
margin-top: 3rem;
|
|
254
|
+
padding-top: 1.5rem;
|
|
255
|
+
border-top: 1px solid var(--line);
|
|
256
|
+
font-size: 0.8rem;
|
|
257
|
+
color: var(--ink-faint);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
@media (max-width: 640px) {
|
|
261
|
+
.row { grid-template-columns: 1fr; gap: 0.4rem; }
|
|
262
|
+
.pill { justify-self: start; }
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
@media print {
|
|
266
|
+
body { background: #fff; color: #000; }
|
|
267
|
+
.page { padding: 0; max-width: none; }
|
|
268
|
+
ol.ledger, dl.stat-rail, .needs-you { box-shadow: none; }
|
|
269
|
+
a { color: inherit; }
|
|
270
|
+
}
|
|
271
|
+
</style>
|
|
272
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
273
|
+
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,500;9..144,600&family=IBM+Plex+Sans:wght@400;500;600&family=IBM+Plex+Mono:wght@500;600&display=swap">
|
|
274
|
+
</head>
|
|
275
|
+
<body>
|
|
276
|
+
<div class="page">
|
|
277
|
+
<main>
|
|
278
|
+
|
|
279
|
+
<header class="masthead">
|
|
280
|
+
<p class="eyebrow">{{masthead.eyebrow}}</p>
|
|
281
|
+
<h1>{{masthead.title}}</h1>
|
|
282
|
+
<p class="dek">{{masthead.dek}}</p>
|
|
283
|
+
|
|
284
|
+
<dl class="stat-rail">
|
|
285
|
+
{{#stats}}
|
|
286
|
+
<div class="stat"><dd>{{value}}</dd><dt>{{label}}</dt></div>
|
|
287
|
+
{{/stats}}
|
|
288
|
+
</dl>
|
|
289
|
+
|
|
290
|
+
{{#needsYouCount}}
|
|
291
|
+
<section class="needs-you" aria-labelledby="needs-you-heading">
|
|
292
|
+
<h2 id="needs-you-heading">Needs you: {{needsYouCount}}</h2>
|
|
293
|
+
<ul>
|
|
294
|
+
{{#needsYou}}
|
|
295
|
+
<li><strong>{{id}}</strong> โ {{title}}{{#href}} ยท <a href="{{href}}">open</a>{{/href}}</li>
|
|
296
|
+
{{/needsYou}}
|
|
297
|
+
</ul>
|
|
298
|
+
</section>
|
|
299
|
+
{{/needsYouCount}}
|
|
300
|
+
{{^needsYouCount}}
|
|
301
|
+
<section class="needs-you none" aria-labelledby="needs-you-heading">
|
|
302
|
+
<h2 id="needs-you-heading">Nothing needs you</h2>
|
|
303
|
+
</section>
|
|
304
|
+
{{/needsYouCount}}
|
|
305
|
+
|
|
306
|
+
{{#hasOutcome}}<p class="outcome">{{outcome}}</p>{{/hasOutcome}}
|
|
307
|
+
|
|
308
|
+
<ul class="legend" aria-label="Category legend">
|
|
309
|
+
{{#legend}}
|
|
310
|
+
<li class="legend-item"><span class="swatch" style="background:var(--cat-{{key}})" aria-hidden="true"></span>{{label}}</li>
|
|
311
|
+
{{/legend}}
|
|
312
|
+
</ul>
|
|
313
|
+
</header>
|
|
314
|
+
|
|
315
|
+
{{#sections}}
|
|
316
|
+
<section class="phase" aria-labelledby="{{id}}-heading">
|
|
317
|
+
<div class="phase-label"><h2 id="{{id}}-heading">{{title}}</h2><span class="rule" aria-hidden="true"></span></div>
|
|
318
|
+
{{#hasNote}}<p class="phase-note">{{note}}</p>{{/hasNote}}
|
|
319
|
+
<ol class="ledger">
|
|
320
|
+
{{#rows}}
|
|
321
|
+
<li class="row">
|
|
322
|
+
<div class="item-title">{{#hasGlyph}}<span class="emoji" aria-hidden="true">{{glyph}}</span>{{/hasGlyph}}<span>{{#hasHref}}<a href="{{href}}">{{title}}</a>{{/hasHref}}{{^hasHref}}{{title}}{{/hasHref}}<span class="item-id">{{id}}</span></span></div>
|
|
323
|
+
{{#isUnwritten}}<div class="item-desc unwritten">unwritten</div>{{/isUnwritten}}
|
|
324
|
+
{{^isUnwritten}}<div class="item-desc">{{{descriptionHtml}}}</div>{{/isUnwritten}}
|
|
325
|
+
<span class="pill {{category}}">{{categoryLabel}}</span>
|
|
326
|
+
</li>
|
|
327
|
+
{{/rows}}
|
|
328
|
+
</ol>
|
|
329
|
+
</section>
|
|
330
|
+
{{/sections}}
|
|
331
|
+
|
|
332
|
+
{{#hasCorrections}}
|
|
333
|
+
{{#corrections}}
|
|
334
|
+
<section class="phase" aria-labelledby="corrections-heading">
|
|
335
|
+
<div class="phase-label"><h2 id="corrections-heading">Calibration</h2><span class="rule" aria-hidden="true"></span></div>
|
|
336
|
+
<p class="phase-note">{{checked}} claims checked ยท {{corrected}} corrected ยท {{unverifiable}} unverifiable. {{scopeNote}}</p>
|
|
337
|
+
<ol class="ledger">
|
|
338
|
+
{{#highlights}}
|
|
339
|
+
<li class="row">
|
|
340
|
+
<div class="item-title"><span>{{title}}</span></div>
|
|
341
|
+
{{#isUnwritten}}<div class="item-desc unwritten">unwritten</div>{{/isUnwritten}}
|
|
342
|
+
{{^isUnwritten}}<div class="item-desc">{{{descriptionHtml}}}</div>{{/isUnwritten}}
|
|
343
|
+
<span class="pill {{category}}">{{categoryLabel}}</span>
|
|
344
|
+
</li>
|
|
345
|
+
{{/highlights}}
|
|
346
|
+
</ol>
|
|
347
|
+
</section>
|
|
348
|
+
{{/corrections}}
|
|
349
|
+
{{/hasCorrections}}
|
|
350
|
+
|
|
351
|
+
{{#hasParked}}
|
|
352
|
+
<section class="phase" aria-labelledby="parked-heading">
|
|
353
|
+
<div class="phase-label"><h2 id="parked-heading">Parked โ needs operator</h2><span class="rule" aria-hidden="true"></span></div>
|
|
354
|
+
<ul class="parked-list">
|
|
355
|
+
{{#parked}}
|
|
356
|
+
<li><strong>{{title}}</strong> โ {{reason}}</li>
|
|
357
|
+
{{/parked}}
|
|
358
|
+
</ul>
|
|
359
|
+
</section>
|
|
360
|
+
{{/hasParked}}
|
|
361
|
+
|
|
362
|
+
{{#hasCast}}
|
|
363
|
+
<section class="phase" aria-labelledby="cast-heading">
|
|
364
|
+
<div class="phase-label"><h2 id="cast-heading">Cast</h2><span class="rule" aria-hidden="true"></span></div>
|
|
365
|
+
<p class="phase-note">Self-reported from commit trailers in this program's version window.</p>
|
|
366
|
+
<ul class="cast-list">
|
|
367
|
+
{{#cast}}
|
|
368
|
+
<li>{{name}} โ {{commits}} commits</li>
|
|
369
|
+
{{/cast}}
|
|
370
|
+
</ul>
|
|
371
|
+
</section>
|
|
372
|
+
{{/hasCast}}
|
|
373
|
+
|
|
374
|
+
</main>
|
|
375
|
+
|
|
376
|
+
<footer class="colophon">
|
|
377
|
+
Compiled {{compiledAtDate}} from <code>{{sourcesJoined}}</code>. Program <code>{{program.slug}}</code>, status <code>{{program.status}}</code>{{#hasVersionSpan}}, <code>{{program.versionSpan.from}}</code> โ <code>{{program.versionSpan.to}}</code>{{/hasVersionSpan}}. Template <code>{{colophon.templateVersion}}</code>. Every stat above is derived, never hand-typed.
|
|
378
|
+
</footer>
|
|
379
|
+
|
|
380
|
+
</div>
|
|
381
|
+
</body>
|
|
382
|
+
</html>
|