arcane-cli 0.34.2 โ†’ 0.35.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/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.
@@ -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>