arcane-cli 0.35.0 → 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.
@@ -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:**
package/dist/index.js CHANGED
@@ -5675,8 +5675,11 @@ async function runReportGeneration(options) {
5675
5675
  const templateHtml = await readFile13(options.templatePath, "utf8");
5676
5676
  const drifted = [];
5677
5677
  const repaired = [];
5678
+ const unwritten = [];
5678
5679
  for (const program2 of options.programs) {
5679
5680
  const generated = await generateReport(options.rootDir, program2, templateHtml);
5681
+ const missing = JSON.parse(generated.json).sections.flatMap((section) => section.rows).filter((row) => row.descriptionState === "unwritten").map((row) => row.id);
5682
+ if (missing.length > 0) unwritten.push({ slug: program2.slug, ids: missing });
5680
5683
  const outAbs = options.outDir ? isAbsolute(options.outDir) ? options.outDir : resolve3(options.rootDir, options.outDir) : resolve3(options.rootDir, dirname4(program2.planRelPath));
5681
5684
  const outRel = toPosix(relative3(options.rootDir, outAbs));
5682
5685
  const outputs = [
@@ -5695,7 +5698,7 @@ async function runReportGeneration(options) {
5695
5698
  }
5696
5699
  }
5697
5700
  }
5698
- return { drifted, repaired };
5701
+ return { drifted, repaired, unwritten };
5699
5702
  }
5700
5703
 
5701
5704
  // src/commands/report.ts
@@ -5746,6 +5749,11 @@ async function runReport(targetDir, options = {}, assetsDir) {
5746
5749
  programs,
5747
5750
  outDir: options.out
5748
5751
  });
5752
+ for (const u of result.unwritten) {
5753
+ console.warn(
5754
+ `\u26A0 arcane: ${u.slug} has ${u.ids.length} epic(s) with no \`**Report:**\` line in PLAN.md -- they render as "unwritten": ${u.ids.join(", ")}.`
5755
+ );
5756
+ }
5749
5757
  if (result.repaired.length === 0) {
5750
5758
  console.log(`Show report: ${programs.length} program(s) already up to date.`);
5751
5759
  return;