create-pmos 0.52.0 → 0.53.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 (212) hide show
  1. package/package.json +1 -1
  2. package/payload/KIT-VERSION +2 -2
  3. package/payload/mods/pmos-cockpit/README.md +13 -0
  4. package/payload/mods/pmos-cockpit/hooks/lib/commands.mjs +2 -1
  5. package/payload/mods/pmos-cockpit/hooks/lib/grants.mjs +41 -11
  6. package/payload/mods/pmos-cockpit/hooks/lib/guard.mjs +228 -8
  7. package/payload/mods/pmos-cockpit/hooks/register.tsx +11 -3
  8. package/payload/planning/evals/eval-calibration.md +1 -1
  9. package/payload/planning/okrs/health-budgets.md +1 -1
  10. package/payload/scripts/plan-items-stage.js +271 -0
  11. package/payload/scripts/pmos-log.sh +18 -7
  12. package/payload/scripts/workflow-state.js +28 -2
  13. package/payload/state/discoveries.md +1 -1
  14. package/payload/state/log.md +1 -1
  15. package/workspace/bin/pmos.js +15 -1
  16. package/workspace/cut-stub.js +40 -0
  17. package/workspace/first-paint-audit.js +145 -0
  18. package/workspace/fixtures/capture/requirements/capture-2026-10-04-1.md +10 -0
  19. package/workspace/fixtures/initiatives-api/list.json +176 -0
  20. package/workspace/fixtures/initiatives-api/post-403.json +5 -0
  21. package/workspace/fixtures/initiatives-api/post-ok.json +10 -0
  22. package/workspace/fixtures/initiatives-api/roadmap.json +208 -0
  23. package/workspace/fixtures/initiatives-api/sheet.json +112 -0
  24. package/workspace/fixtures/report-api/draft.json +177 -0
  25. package/workspace/fixtures/reports-page/draft-biweekly-2026-10-16.md +97 -0
  26. package/workspace/fixtures/today-api/provider-rows.json +204 -0
  27. package/workspace/fixtures/today-api/seam-probe-kinds.json +5 -0
  28. package/workspace/guide/board.md +81 -0
  29. package/workspace/guide/breakdown.md +154 -0
  30. package/workspace/guide/command-palette.md +75 -0
  31. package/workspace/guide/index.md +27 -17
  32. package/workspace/guide/initiatives-roadmap.md +130 -0
  33. package/workspace/guide/initiatives-screen.md +89 -0
  34. package/workspace/guide/initiatives-timeline.md +57 -0
  35. package/workspace/guide/integrated-work.md +94 -0
  36. package/workspace/guide/knowledge-graph.md +3 -68
  37. package/workspace/guide/layout.md +98 -32
  38. package/workspace/guide/live-notes.md +3 -3
  39. package/workspace/guide/pm-only-acts.md +89 -0
  40. package/workspace/guide/pm-only-lines.md +61 -0
  41. package/workspace/guide/reports-page.md +80 -0
  42. package/workspace/guide/reports.md +73 -0
  43. package/workspace/guide/timeline.md +70 -0
  44. package/workspace/guide/today.md +85 -0
  45. package/workspace/guide/validate-with-typesafe.md +1 -1
  46. package/workspace/lib/actor.js +91 -0
  47. package/workspace/lib/board-cache.js +32 -2
  48. package/workspace/lib/board-cli.js +108 -0
  49. package/workspace/lib/board-fold.js +232 -0
  50. package/workspace/lib/breakdown-export.js +80 -0
  51. package/workspace/lib/capture.js +98 -0
  52. package/workspace/lib/engine/plan-items-stage.js +271 -0
  53. package/workspace/lib/engine/workflow-state.js +28 -2
  54. package/workspace/lib/factory-join.js +158 -0
  55. package/workspace/lib/grant-mint.js +113 -0
  56. package/workspace/lib/health-rules-factory.js +92 -0
  57. package/workspace/lib/health-rules-plan.js +164 -0
  58. package/workspace/lib/health.js +79 -0
  59. package/workspace/lib/initiative-cli.js +222 -0
  60. package/workspace/lib/initiative-display.js +183 -0
  61. package/workspace/lib/initiative-needs.js +127 -0
  62. package/workspace/lib/initiative-rows.js +206 -0
  63. package/workspace/lib/initiative-writer.js +141 -0
  64. package/workspace/lib/issues.js +206 -0
  65. package/workspace/lib/item-cli.js +195 -0
  66. package/workspace/lib/item-spans.js +137 -0
  67. package/workspace/lib/measure-cli.js +100 -0
  68. package/workspace/lib/measurements.js +189 -0
  69. package/workspace/lib/mobile-nav.js +57 -53
  70. package/workspace/lib/needs-providers.js +120 -0
  71. package/workspace/lib/placements.js +440 -0
  72. package/workspace/lib/plan-items.js +922 -0
  73. package/workspace/lib/plan-ledgers.js +85 -0
  74. package/workspace/lib/plan-rules.js +72 -0
  75. package/workspace/lib/plan-tree.js +367 -0
  76. package/workspace/lib/pm-guard.js +174 -0
  77. package/workspace/lib/pm-lines-needs.js +331 -0
  78. package/workspace/lib/pmos-verbs.js +66 -0
  79. package/workspace/lib/proactive.js +7 -4
  80. package/workspace/lib/report-cli.js +152 -0
  81. package/workspace/lib/report-draft.js +579 -0
  82. package/workspace/lib/report-needs.js +213 -0
  83. package/workspace/lib/route-modules.js +128 -0
  84. package/workspace/lib/routes-board.js +91 -0
  85. package/workspace/lib/routes-capture.js +52 -0
  86. package/workspace/lib/routes-initiatives.js +371 -0
  87. package/workspace/lib/routes-reports.js +163 -0
  88. package/workspace/lib/routes-timeline.js +197 -0
  89. package/workspace/lib/routes-today.js +32 -0
  90. package/workspace/lib/today-cli.js +99 -0
  91. package/workspace/lib/today.js +333 -0
  92. package/workspace/lib/triage.js +163 -0
  93. package/workspace/lib/verify-work-cli.js +81 -0
  94. package/workspace/lib/work-check-needs.js +99 -0
  95. package/workspace/package-lock.json +1 -1
  96. package/workspace/package.json +4 -5
  97. package/workspace/public/index.html +29 -19
  98. package/workspace/public/pm/app.js +299 -30
  99. package/workspace/public/pm/bd-board.js +113 -0
  100. package/workspace/public/pm/bd-drag.js +59 -0
  101. package/workspace/public/pm/bd-model.js +152 -0
  102. package/workspace/public/pm/bd-timeline.js +233 -0
  103. package/workspace/public/pm/bd-tree.js +244 -0
  104. package/workspace/public/pm/board-copy.js +57 -0
  105. package/workspace/public/pm/breakdown-api.js +58 -0
  106. package/workspace/public/pm/breakdown-copy.js +138 -0
  107. package/workspace/public/pm/components.css +3054 -0
  108. package/workspace/public/pm/cycle-review.js +125 -0
  109. package/workspace/public/pm/data.js +40 -187
  110. package/workspace/public/pm/dest-board.js +438 -0
  111. package/workspace/public/pm/dest-initiatives.js +134 -0
  112. package/workspace/public/pm/dest-reports.js +270 -0
  113. package/workspace/public/pm/dest-settings.js +217 -0
  114. package/workspace/public/pm/dest-today.js +176 -0
  115. package/workspace/public/pm/dialogs.js +88 -0
  116. package/workspace/public/pm/display-word.js +56 -0
  117. package/workspace/public/pm/dock.js +105 -0
  118. package/workspace/public/pm/fixture.js +8 -227
  119. package/workspace/public/pm/frame-copy.js +94 -0
  120. package/workspace/public/pm/handoff-box.js +82 -0
  121. package/workspace/public/pm/http.js +88 -0
  122. package/workspace/public/pm/icons.js +53 -0
  123. package/workspace/public/pm/initiative-list.js +218 -0
  124. package/workspace/public/pm/initiative-sheet.js +261 -0
  125. package/workspace/public/pm/initiatives-api.js +59 -0
  126. package/workspace/public/pm/initiatives-copy.js +215 -0
  127. package/workspace/public/pm/initiatives-timeline-copy.js +59 -0
  128. package/workspace/public/pm/initiatives-timeline.js +410 -0
  129. package/workspace/public/pm/initiatives-ui.js +123 -0
  130. package/workspace/public/pm/item-sheet.js +251 -0
  131. package/workspace/public/pm/keep-card.js +204 -0
  132. package/workspace/public/pm/lifecycle.js +7 -1
  133. package/workspace/public/pm/mobile.css +49 -20
  134. package/workspace/public/pm/mobile.js +157 -29
  135. package/workspace/public/pm/modes-live.js +7 -883
  136. package/workspace/public/pm/modes.js +32 -1024
  137. package/workspace/public/pm/new-initiative-sheet.js +74 -0
  138. package/workspace/public/pm/next-step-ui.js +3 -2
  139. package/workspace/public/pm/palette-copy.js +51 -0
  140. package/workspace/public/pm/palette.js +312 -0
  141. package/workspace/public/pm/panel-breakdown.js +702 -0
  142. package/workspace/public/pm/panel-cockpit.js +63 -295
  143. package/workspace/public/pm/panel-detail.js +25 -172
  144. package/workspace/public/pm/panel-initiatives.js +1 -19
  145. package/workspace/public/pm/panel-repos.js +31 -81
  146. package/workspace/public/pm/panel-tabs.js +197 -110
  147. package/workspace/public/pm/panel-trees.js +5 -2
  148. package/workspace/public/pm/portfolio-report.js +61 -0
  149. package/workspace/public/pm/primitives.js +656 -0
  150. package/workspace/public/pm/print.css +33 -0
  151. package/workspace/public/pm/provider-cards.js +136 -0
  152. package/workspace/public/pm/registry.js +194 -0
  153. package/workspace/public/pm/release-card.js +110 -0
  154. package/workspace/public/pm/report-view.js +309 -0
  155. package/workspace/public/pm/reports-copy.js +114 -0
  156. package/workspace/public/pm/roadmap.js +271 -0
  157. package/workspace/public/pm/sig-watch.js +41 -0
  158. package/workspace/public/pm/state.js +8 -4
  159. package/workspace/public/pm/status-banner.js +13 -5
  160. package/workspace/public/pm/tab-doc.js +2 -4
  161. package/workspace/public/pm/tab-term.js +12 -2
  162. package/workspace/public/pm/tab-web.js +3 -2
  163. package/workspace/public/pm/timeline-copy.js +48 -0
  164. package/workspace/public/pm/today-cards.js +244 -0
  165. package/workspace/public/pm/today-copy.js +97 -0
  166. package/workspace/public/pm/tokens.css +16 -18
  167. package/workspace/public/pm/topbar.js +102 -0
  168. package/workspace/public/pm/triage-card.js +60 -0
  169. package/workspace/public/pm/undo-hold.js +103 -0
  170. package/workspace/public/pm/view-addrepo.js +2 -1
  171. package/workspace/public/pm/view-livenotes.js +3 -1
  172. package/workspace/public/pm/view-today.js +7 -162
  173. package/workspace/public/vendor/Sortable.min.js +2 -0
  174. package/workspace/public/vendor/lucide-sprite.js +79 -0
  175. package/workspace/replaced-tests.json +2864 -0
  176. package/workspace/run-tests.js +56 -5
  177. package/workspace/server.js +312 -36
  178. package/workspace/sheet-answer.js +61 -0
  179. package/workspace/skills/measure.skill +41 -0
  180. package/workspace/skills/report-biweekly.skill +23 -25
  181. package/workspace/skills/tracker-refresh.skill +50 -0
  182. package/workspace/test-files.json +19 -3
  183. package/workspace/test-lists/base.json +6 -0
  184. package/workspace/test-lists/run2-a.json +6 -0
  185. package/workspace/test-lists/run2-b.json +13 -0
  186. package/workspace/test-lists/run2-c.json +19 -0
  187. package/workspace/test-lists/run2-d.json +22 -0
  188. package/workspace/test-lists/run3-0.json +5 -0
  189. package/workspace/test-lists/run3-a.json +5 -0
  190. package/workspace/test-lists/run3-b.json +6 -0
  191. package/workspace/test-lists/run3-c.json +15 -0
  192. package/workspace/test-lists/run3-d.json +6 -0
  193. package/workspace/test-lists/run4-a.json +8 -0
  194. package/workspace/test-lists/run4-b.json +6 -0
  195. package/workspace/test-lists/run4-c.json +13 -0
  196. package/workspace/test-lists/run4-d.json +9 -0
  197. package/workspace/test-lists/run5-a.json +6 -0
  198. package/workspace/test-lists/run5-b.json +6 -0
  199. package/workspace/test-lists/run5-c.json +15 -0
  200. package/workspace/test-run.js +27 -1
  201. package/workspace/third-party/README.md +44 -0
  202. package/workspace/third-party/lucide-static-1.52.0.LICENSE +43 -0
  203. package/workspace/third-party/sortablejs-1.15.7.LICENSE +21 -0
  204. package/workspace/design-parity.js +0 -673
  205. package/workspace/public/pm/tab-task.js +0 -86
  206. package/workspace/public/pm/view-guide.js +0 -141
  207. package/workspace/public/pm/view-knowledge.js +0 -225
  208. package/workspace/public/pm/view-memory.js +0 -122
  209. package/workspace/public/pm/view-portfolio.js +0 -153
  210. package/workspace/public/pm/view-reports.js +0 -190
  211. package/workspace/public/pm/view-scheduled.js +0 -161
  212. package/workspace/public/pm/view-skills.js +0 -216
@@ -0,0 +1,152 @@
1
+ 'use strict';
2
+ /* report-cli.js — `pmos report …`: draft a cadence report, issue it, list the reports (pm-os-absorb Run 5, PRD R22,
3
+ * R24, R25; D86 points 2 and 3).
4
+ *
5
+ * pmos report draft <cadence> [<slot>] [--now <time>] [--redraft] [--json] [--root <dir>]
6
+ * pmos report issue <cadence> <slot> [--root <dir>]
7
+ * pmos report list [<cadence>] [--json] [--root <dir>]
8
+ *
9
+ * `draft` is the script with no model (R22.1): lib/report-draft.js folds the ledgers since the last issue and writes
10
+ * every number into `<state>/reports/<cadence>/<slot>.md`, with one empty note marker per block. It refuses a slot that
11
+ * has a draft already (X18, from local files only, never a fetch); `--redraft` writes it again and keeps every note.
12
+ * `<slot>` defaults to today; `--now` fixes the clock, so two runs with the same inputs write the same bytes.
13
+ *
14
+ * `issue` is a PM-only act (R25): pm-guard.js requirePmCli({ act: 'issue' }) asks the PM to type `<cadence>-<slot>`
15
+ * at an interactive terminal. An agent session, a call with no terminal and a wrong text are refused, and nothing is
16
+ * written. Then lib/issues.js appendFromCli records the path and the git blob sha, which freezes the report. Nothing
17
+ * is sent: print the file or copy it as markdown.
18
+ *
19
+ * Who writes is decided by the call path, never by an argument (lib/actor.js). The verb never calls the server.
20
+ */
21
+ const fs = require('fs');
22
+ const path = require('path');
23
+ const { execFileSync } = require('child_process');
24
+ const reportDraft = require('./report-draft.js');
25
+ const issues = require('./issues.js');
26
+ const guard = require('./pm-guard.js');
27
+ const actorLib = require('./actor.js');
28
+ const { parseArgs } = require('./schedule-cli');
29
+
30
+ const COMMANDS = { report: ['draft', 'issue', 'list'] };
31
+ const USAGE = [
32
+ 'usage: pmos report draft|issue|list — cadence reports (for example the biweekly)',
33
+ ' pmos report draft <cadence> [<slot>] [--now <time>] [--redraft]',
34
+ ' Write the draft for a slot (default: today) with every number. Refuses a slot that has a draft;',
35
+ ' --redraft writes it again and keeps every note.',
36
+ ' pmos report issue <cadence> <slot>',
37
+ ' Freeze the draft. Only the PM can do this, at a terminal, by typing <cadence>-<slot>. Nothing is sent.',
38
+ ' pmos report list [<cadence>]',
39
+ ' Show the drafts and the issued reports.',
40
+ ' every command: [--json] [--root <dir>]. The cadence is the report skill id without "report-", for example biweekly.',
41
+ ];
42
+ const BOOL = new Set(['json', 'redraft', 'help']);
43
+ const VALUE = new Set(['now', 'root']);
44
+ const ALLOWED = { draft: ['json', 'redraft', 'now', 'root'], issue: ['root'], list: ['json', 'root'] };
45
+ const CADENCE_RE = /^[a-z][a-z0-9-]{0,39}$/;
46
+ const DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
47
+
48
+ function parse(argv) {
49
+ const rest = []; const bools = {};
50
+ for (const a of argv) {
51
+ if (a.startsWith('--') && BOOL.has(a.slice(2))) bools[a.slice(2)] = true;
52
+ else if (a === '-h') bools.help = true;
53
+ else rest.push(a);
54
+ }
55
+ const { pos, flags } = parseArgs(rest);
56
+ return { pos, flags: { ...flags, ...bools } };
57
+ }
58
+
59
+ function repoRoot(cwd) {
60
+ try { return execFileSync('git', ['rev-parse', '--show-toplevel'], { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim() || cwd; }
61
+ catch { return cwd; }
62
+ }
63
+ const isDate = (s) => typeof s === 'string' && DATE_RE.test(s) && new Date(s + 'T00:00:00Z').toISOString().slice(0, 10) === s;
64
+
65
+ async function run(argv, { say = (s) => console.log(s), cwd = process.cwd(), isTTY, env, ask, now } = {}) {
66
+ const args = argv[0] === 'report' ? argv.slice(1) : argv.slice();
67
+ const verb = args[0];
68
+ const { pos, flags } = parse(args.slice(1));
69
+ if (!verb || verb === 'help' || verb === '--help' || verb === '-h' || flags.help) {
70
+ for (const l of USAGE) say(l);
71
+ return verb ? 0 : 1;
72
+ }
73
+ if (!COMMANDS.report.includes(verb)) { say(`unknown report command "${verb}". Use one of: ${COMMANDS.report.join(', ')}`); return 2; }
74
+ if ('by' in flags || 'via' in flags) { say(`the call path sets who writes; --${'by' in flags ? 'by' : 'via'} is not an option`); return 2; }
75
+ for (const k of Object.keys(flags)) {
76
+ if (!BOOL.has(k) && !VALUE.has(k)) { say(`unknown option --${k}`); return 2; }
77
+ if (!ALLOWED[verb].includes(k)) { say(`--${k} is not an option of report ${verb}`); return 2; }
78
+ if (VALUE.has(k) && flags[k] === '') { say(`--${k} needs a value`); return 2; }
79
+ }
80
+ const root = flags.root ? path.resolve(cwd, flags.root) : repoRoot(cwd);
81
+ const json = !!flags.json;
82
+ const fail = (error, code = 1) => { if (json) say(JSON.stringify({ ok: false, error })); else say(`✗ ${error}`); return code; };
83
+
84
+ if (verb === 'list') {
85
+ const cadence = pos[0];
86
+ if (cadence !== undefined && !CADENCE_RE.test(cadence)) { say('usage: pmos report list [<cadence>]'); return 2; }
87
+ let state;
88
+ try { state = reportDraft.stateRel(root); }
89
+ catch (e) { return fail(String((e && e.message) || e).slice(0, 200)); }
90
+ const iss = issues.readIssues(root);
91
+ const rows = [];
92
+ let dirs = [];
93
+ try { dirs = fs.readdirSync(path.join(root, state, 'reports'), { withFileTypes: true }).filter((d) => d.isDirectory() && d.name !== 'definitions').map((d) => d.name); } catch { dirs = []; }
94
+ for (const c of new Set([...dirs, ...iss.issues.map((r) => r.cadence)])) {
95
+ if (cadence && c !== cadence) continue;
96
+ let files = [];
97
+ try { files = fs.readdirSync(path.join(root, state, 'reports', c)).filter((f) => /^\d{4}-\d{2}-\d{2}\.md$/.test(f)); } catch { files = []; }
98
+ const slots = new Set([...files.map((f) => f.slice(0, 10)), ...iss.issues.filter((r) => r.cadence === c).map((r) => r.slot)]);
99
+ for (const slot of slots) {
100
+ const issued = iss.issues.find((r) => r.cadence === c && r.slot === slot) || null;
101
+ rows.push({ cadence: c, slot, path: `${state}/reports/${c}/${slot}.md`,
102
+ issued: issued ? { at: issued.at, by: actorLib.pageName(issued.by), sha: issued.sha } : null });
103
+ }
104
+ }
105
+ rows.sort((a, b) => (a.cadence < b.cadence ? -1 : a.cadence > b.cadence ? 1 : 0) || (a.slot < b.slot ? 1 : a.slot > b.slot ? -1 : 0));
106
+ if (json) { say(JSON.stringify({ ok: true, reports: rows, flags: iss.flags })); return 0; }
107
+ if (!rows.length) say(cadence ? `No ${cadence} report yet. Type: pmos report draft ${cadence}` : 'No report yet. Type: pmos report draft biweekly');
108
+ for (const r of rows) say(`${r.cadence} ${r.slot} ${r.issued ? `issued ${r.issued.at.slice(0, 10)} by ${r.issued.by}` : 'draft'} ${r.path}`);
109
+ for (const f of iss.flags) say(`! issues.jsonl: ${f.why}`);
110
+ return 0;
111
+ }
112
+
113
+ const [cadence, slot] = pos;
114
+ if (!cadence || !CADENCE_RE.test(cadence) || pos.length > 2) { say(`usage: pmos report ${verb} <cadence> ${verb === 'issue' ? '<slot>' : '[<slot>]'}`); return 2; }
115
+ if (slot !== undefined && !isDate(slot)) return fail('the slot must be a date, YYYY-MM-DD', 2);
116
+
117
+ if (verb === 'draft') {
118
+ let clock = now;
119
+ if (flags.now !== undefined) { clock = Date.parse(flags.now); if (!Number.isFinite(clock)) return fail('--now must be a time, for example 2026-10-16T09:00:00Z', 2); }
120
+ const draft = reportDraft.draftOf(root, { cadence, slot, now: clock });
121
+ if (!draft.ok) return fail(draft.error);
122
+ const who = actorLib.fromCli({ ...(isTTY === undefined ? {} : { isTTY }), ...(env === undefined ? {} : { env }) });
123
+ const r = reportDraft.writeDraft(root, draft, { actor: who, fresh: !flags.redraft });
124
+ if (!r.ok) {
125
+ if (r.status === 409 && !flags.redraft && !/issued/.test(r.error)) {
126
+ return fail(`${r.error}. To write it again and keep every note, type: pmos report draft ${cadence} ${draft.slot} --redraft`);
127
+ }
128
+ return fail(r.error);
129
+ }
130
+ if (json) { say(JSON.stringify({ ok: true, path: r.path, sha: r.sha, slot: draft.slot, window: draft.window, blocks: draft.blocks.map((b) => b.id) })); return 0; }
131
+ say(`✓ ${flags.redraft ? 'Drafted again' : 'Drafted'} ${r.path}: ${draft.blocks.length === 1 ? '1 initiative' : `${draft.blocks.length} initiatives`}, ${draft.window.from} to ${draft.window.to}.`);
132
+ say(' Write prose only between the note markers. Type no number: the script writes them.');
133
+ return 0;
134
+ }
135
+
136
+ // issue — the PM types <cadence>-<slot>, so a report is never issued by accident or by an agent.
137
+ if (!slot) { say('usage: pmos report issue <cadence> <slot>'); return 2; }
138
+ const g = await guard.requirePmCli({ act: 'issue', expect: `${cadence}-${slot}`,
139
+ ...(isTTY === undefined ? {} : { isTTY }), ...(env === undefined ? {} : { env }), ask: ask || guard.askAtTerminal });
140
+ if (!g.ok) return fail(g.error);
141
+ let rel;
142
+ try { rel = reportDraft.draftPath(root, cadence, slot); } catch (e) { return fail(String((e && e.message) || e).slice(0, 200)); }
143
+ let buf;
144
+ try { buf = fs.readFileSync(path.join(root, rel)); } catch { return fail(`${rel} does not exist. Draft it first: pmos report draft ${cadence} ${slot}`); }
145
+ const r = issues.appendFromCli(root, [{ ev: 'issued', cadence, slot, path: rel, sha: issues.blobSha(buf) }], { actor: g.actor, now });
146
+ if (!r.ok) return fail(r.error);
147
+ say(`✓ Issued ${rel} (blob ${r.written[0].sha.slice(0, 12)}). It is frozen: a draft of this slot is refused from now on.`);
148
+ say(' Nothing was sent. Print it or copy it as markdown.');
149
+ return 0;
150
+ }
151
+
152
+ module.exports = { run, COMMANDS, USAGE };