arcane-cli 0.33.4 → 0.33.6

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.
@@ -78,6 +78,31 @@ stale number is invisible until someone tries.
78
78
  it resolves to, say so and cite the ID as plain text rather than inventing a link that
79
79
  looks real but goes nowhere.
80
80
 
81
+ ### Stable-Locator Citation Grammar
82
+
83
+ The same "don't force the reader to go find it themselves" principle applies to citing a
84
+ specific spot inside a file, not just a Decision-ID. A bare `path:NNN` line-number citation
85
+ drifts the moment either file is edited — confirmed live, repeatedly: 13+ instances in one
86
+ program's own corrections record, and three more caught within 24 hours of being written,
87
+ during the very audit that counted the first 13.
88
+
89
+ **Required format, in a living doc** (anything meant to stay accurate as the tree changes —
90
+ `TODO.md`, `IDEAS.md`, `DECISIONS.md`, `ai-context/`, the verification ledger, an active plan,
91
+ or a shipped governance doc/prompt):
92
+ - `path` — the whole file is the referent, no specific spot claimed.
93
+ - `path#anchor` — a heading anchor that slugifies to a real heading in that file.
94
+ - `path ("unique quoted phrase")` — a phrase that occurs exactly once in that file, so a reader
95
+ (or a script) can always re-locate it even after the file has been edited and re-wrapped.
96
+ - `path:NNN` **alone is never sufficient** in a living doc — only acceptable alongside one of
97
+ the three forms above (a secondary, human-convenience pointer next to a quoted phrase or
98
+ anchor), since a bare line number is exactly the kind of static fact this framework exists to
99
+ stop treating as durable. Enforcement: executable check (ARC-023) — `npm run check:citations`
100
+ scans the living-docs set for a bare `path:NNN` with no accompanying anchor or quoted phrase.
101
+
102
+ **Ephemeral output is exempt** (chat, a PR description, a commit message, a session handoff): a
103
+ bare `path:NNN` there is fine — the reader is looking at the current tree in the same sitting,
104
+ so drift has no time to happen before it is read.
105
+
81
106
  ## Merge Strategy
82
107
 
83
108
  All PRs must use **Rebase and fast-forward**. Never squash. Never merge commit. See
@@ -13,7 +13,7 @@ agent: agent
13
13
  - It enforces the rule from `project.md` → Constraints → Self-hosting: "Anything touching
14
14
  `src/assets/` requires a version bump." (Corrected 2026-08-31, BC-06 — this previously cited
15
15
  CLAUDE.md, which now carries only the working protocol; the rule's live prose home moved to
16
- `project.md:56-58`.)
16
+ `project.md ("requires a version bump"):56-58`.)
17
17
 
18
18
  ---
19
19
 
@@ -21,14 +21,19 @@ Determine the correct semver bump and apply it.
21
21
 
22
22
  ## Step 1 — Check whether a bump is needed
23
23
 
24
- Run the version check gate:
24
+ Run the version check gate in **staged mode** (LH-06a) — this spell runs before the commit that
25
+ will actually contain the change, so the default `merge-base..HEAD` diff can't see it yet; staged
26
+ mode unions that diff with `git diff --cached --name-only` so today's not-yet-committed work is
27
+ checked too, not just history:
25
28
 
26
29
  ```
27
- npm run check:version-bump
30
+ npm run check:version-bump -- --staged
28
31
  ```
29
32
 
30
33
  - If it **passes** → no bump needed. Stop here and report "No version bump required."
31
34
  - If it **fails** → proceed to Step 2.
35
+ - If the changed content isn't staged yet (working-tree edits only), use `-- --working-tree`
36
+ instead, which additionally unions plain `git diff --name-only`.
32
37
 
33
38
  ## Step 2 — Determine semver type
34
39
 
@@ -62,11 +62,11 @@ For each drift finding include:
62
62
  - Severity (`Critical`, `High`, `Medium`, or `Low`)
63
63
  - Severity rationale (one line: why this severity — e.g. work-integrity/duplicate-work risk → HIGH; confidence/correctness gap → MEDIUM; cosmetic → LOW)
64
64
  - Drift statement
65
- - Canonical source file (cite `file:line` — or the nearest locator such as a heading or section — wherever a specific location applies)
66
- - Affected file (cite `file:line` — or the nearest locator — wherever a specific location applies)
65
+ - Canonical source file (cite by stable locator — a heading anchor or a unique quoted phrase, e.g. `path#anchor` or `path ("unique phrase")` — never a bare line number, since findings routinely get promoted into TODO.md or another living doc afterward, where a line number drifts the moment the file is next edited)
66
+ - Affected file (same stable-locator citation)
67
67
  - Exact recommended fix
68
68
 
69
- Every finding that points to a specific location MUST be pinpointable: cite `file:line` (or a line range, e.g. `TODO.md:42-45`). If no precise line exists, cite the nearest available locator (heading, section, or list item) instead of omitting it.
69
+ Every finding that points to a specific location MUST be pinpointable: cite by stable locator (a heading anchor or a unique quoted phrase, e.g. `path#anchor` or `path ("a unique phrase from the target")`). A bare line number may accompany a stable locator as a convenience (this report is read once, in the current tree), but never replace one — a citation promoted into a living doc later must survive on its own. If no precise anchor or phrase exists, cite the nearest available locator (heading, section, or list item) instead of omitting it.
70
70
 
71
71
  Behavior:
72
72
 
@@ -85,7 +85,7 @@ Output format:
85
85
 
86
86
  ## Real Content Drift Findings
87
87
 
88
- - One line per finding with `file:line` references (or nearest locator) and its severity rationale.
88
+ - One line per finding with stable-locator references (heading anchor or unique quoted phrase — nearest locator if neither applies) and its severity rationale.
89
89
 
90
90
  ## Line-Ending-Only Drift
91
91
 
@@ -83,9 +83,9 @@ In `ai-context/system-prompt-context.md`, replace the existing `## Next Session
83
83
  > Auto-generated by spell-close-session. Consumed by spell-open-session. Do not edit manually.
84
84
  > Generated: YYYY-MM-DD
85
85
 
86
- - **Active task:** One-line description of the task that was in progress when this session closed. If incomplete, name where step 4b registered it (e.g. `TODO.md:NNN`).
86
+ - **Active task:** One-line description of the task that was in progress when this session closed. If incomplete, name where step 4b registered it (e.g. `path ("the item's own quoted title")` — a stable locator naming the actual file and its bold title, never a bare line number that drifts the moment that file is next edited).
87
87
  - **Last completed step:** The final concrete action taken — include file path or command text. If that action was async work step 1b classified as anything other than `succeeded`, do not describe it as done here — name the action in `dispatched`/in-progress terms (e.g. "Pushed the fix and opened PR #NN" is fine; "Merged PR #NN" is not, unless step 1b confirmed the merge) and let `Pending Verification` carry the actual state.
88
- - **Next concrete action:** The exact first thing to do at next session start. Be specific: file, command, or decision. Never write "continue work." Name where step 4b registered it (e.g. `TODO.md:NNN`).
88
+ - **Next concrete action:** The exact first thing to do at next session start. Be specific: file, command, or decision. Never write "continue work." Name where step 4b registered it (e.g. `path ("the item's own quoted title")` — a stable locator naming the actual file and its bold title, never a bare line number that drifts the moment that file is next edited).
89
89
  - **Active files:** Files with uncommitted changes or the focus of the last edit (comma-separated).
90
90
  - **Branch:** Output of `git branch --show-current`.
91
91
  - **Blockers:** Known unresolved blockers or dependencies. Write "None" if clear.
@@ -42,6 +42,10 @@ Workflow:
42
42
  - If coverage passes, record the coverage summary for use in the commit body or PR description.
43
43
  - **Never commit code that fails CI locally.** The pipeline is not the first gate — this step is.
44
44
 
45
+ - **Distributable-change halt** (LH-06a; only when this repo has its own `scripts/check-version-bump.ts` — Arcane's own repo, or one that adopted the same convention; skip gracefully otherwise, this is not a general-purpose check every consumer repo can run):
46
+ - Run `npm run check:version-bump -- --staged` before committing. This is the staged-diff mode, not the default CI mode — it can see today's not-yet-committed change, which the default `merge-base..HEAD` diff cannot.
47
+ - **HALT if it fails.** Distributable content (`src/assets/`, `registry.ts`, `profiles.ts`) changed without a version bump. Run `spell-bump` first, then return here.
48
+
45
49
  - **Format before committing** _(stack-aware; runs alongside the test gate above)_:
46
50
  - Detect the configured formatter from the project's own config — do not assume one. Look for the toolchain's standard markers, for example:
47
51
  - JS/TS: `.prettierrc*` / `prettier` in `package.json` → `npx prettier --write .`
@@ -37,7 +37,7 @@ Check `ai-context/system-prompt-context.md` for a `## Next Session Handoff` sect
37
37
 
38
38
  - If present and **not yet marked consumed** (no `> ✓ Consumed:` line): surface it immediately as `## Picking Up From Last Session` at the very top of your output, before all other sections — include `Last completed step`, `Blockers`, and `Notes` verbatim alongside the rest (session handoff durability: these three are written by close-session but were previously never read back). Use the `Next concrete action` field as the first item in `## Next Session Plan`. Use the `Active task`, `Active files`, and `Branch` fields to pre-populate the State Snapshot.
39
39
  - **If the handoff's `Pending Verification` field lists anything other than "None" (EF-21):** surface each listed item explicitly, then actively re-check its current status (per the item's stated verification action) rather than treating the state recorded at close-session time as still current — a `dispatched`/`pending` item may have since succeeded, failed, or still be running, and carrying it forward as inert text would repeat the exact failure mode this field exists to prevent. Report what you found (resolved succeeded / resolved failed / still pending / still unverifiable) before relying on anything downstream that depended on it.
40
- - After surfacing it, apply the Mutation Guard below, then run the **Durability check** (session handoff durability, ARC-040): confirm that an incomplete `Active task`, the `Next concrete action`, and any task-bearing `Notes` content each name a durable location that genuinely exists (the cited `TODO.md` line, or tracker work item). If a named location is missing, or close-session's own step 4b was skipped when it shouldn't have been, register the missing content now — on this session's own branch — before proceeding. Only then append `> ✓ Consumed: YYYY-MM-DD` (today's date); the marker write is a repository mutation. If the Durability check cannot complete, leave the handoff unconsumed so the next open-session retries the same check idempotently, rather than silently losing the gap.
40
+ - After surfacing it, apply the Mutation Guard below, then run the **Durability check** (session handoff durability, ARC-040): confirm that an incomplete `Active task`, the `Next concrete action`, and any task-bearing `Notes` content each name a durable location that genuinely exists (the cited `TODO.md` item — by stable locator, not a line number that may have already drifted — or tracker work item). If a named location is missing, or close-session's own step 4b was skipped when it shouldn't have been, register the missing content now — on this session's own branch — before proceeding. Only then append `> ✓ Consumed: YYYY-MM-DD` (today's date); the marker write is a repository mutation. If the Durability check cannot complete, leave the handoff unconsumed so the next open-session retries the same check idempotently, rather than silently losing the gap.
41
41
  - If the section is absent or already marked consumed: skip this step and proceed with the normal workspace scan.
42
42
 
43
43
  ## Mutation Guard (run lazily before the first repository write)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arcane-cli",
3
- "version": "0.33.4",
3
+ "version": "0.33.6",
4
4
  "description": "Arcane framework CLI — scaffold and manage governance files in consuming repositories",
5
5
  "keywords": [
6
6
  "arcane",
@@ -46,6 +46,7 @@
46
46
  "fix:spell-catalog": "tsx scripts/spell-catalog.ts --fix",
47
47
  "check:adr-references": "tsx scripts/check-distributed-adr-references.ts",
48
48
  "check:version-bump": "tsx scripts/check-version-bump.ts",
49
+ "check:citations": "tsx scripts/check-citations.ts --report",
49
50
  "check:review-round": "tsx scripts/check-review-round.ts",
50
51
  "doctor:leaks": "tsx src/index.ts doctor --leaks",
51
52
  "prepare": "husky"