arcane-cli 1.11.3 → 1.11.4

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.
@@ -281,9 +281,8 @@ If an agent encounters a situation outside its defined parameters, it should:
281
281
 
282
282
  6. **Delete the branch** (local and remote) after merge.
283
283
 
284
- **Branch naming format:** `{agent-slug}/type/short-description`
284
+ **Branch naming format:** the autonomous roster-agent form of the branch-naming rule in `git-conventions.md` → Branch Naming, stated once there and not restated here. The agent-slug prefix makes ownership obvious and prevents naming collisions.
285
285
 
286
- - The agent-slug prefix makes ownership obvious and prevents naming collisions.
287
286
  - Use standard commit types: `feat`, `fix`, `docs`, `refactor`, `chore`, etc.
288
287
 
289
288
  **What happens if ff-only fails:** Another actor merged to main first. This should not happen if you followed step 3. If it does, rebase and retry:
@@ -332,10 +332,9 @@ If an agent encounters a situation outside its defined parameters, it should:
332
332
 
333
333
  6. **Delete the branch** (local and remote) after merge. **Enforcement: structured spell gate (ARC-023) — `spell-commit-work` Step 10 and `spell-close-session`'s branch-deletion step both require running the Same-Vantage-Point Check before a worktree-adjacent deletion; the vantage-point determination itself remains a manual judgment call, which `git-conventions.md` discloses as "not a code-level gate."**
334
334
 
335
- **Branch naming format:** `{agent-slug}/type/short-description`
335
+ **Branch naming format:** the autonomous roster-agent form of the branch-naming rule in `git-conventions.md` → Branch Naming, stated once there and not restated here. The agent-slug prefix makes ownership obvious and prevents naming collisions.
336
336
 
337
- - The agent-slug prefix makes ownership obvious and prevents naming collisions.
338
- - Use standard commit types: `feat`, `fix`, `docs`, `refactor`, `chore`, etc. **Enforcement: explicitly advisory prose (ARC-023) — no check in this repo validates an agent branch name against this format (unlike session-branch naming, which `spell-open-session` does check).**
337
+ - Use standard commit types: `feat`, `fix`, `docs`, `refactor`, `chore`, etc. **Enforcement: explicitly advisory prose (ARC-023) — no check in this repo validates an autonomous agent's branch name against that rule; the rename gate in `git-conventions.md` → Branch Naming runs only in interactive sessions.**
339
338
 
340
339
  **What happens if ff-only fails:** Another actor merged to main first. This should not happen if you followed step 3. If it does, rebase and retry — **from the primary checkout**, since this block checks out `main`:
341
340
 
@@ -198,34 +198,34 @@ Every unit of work runs in exactly one **session workspace**: one instance of on
198
198
 
199
199
  ### Branch Naming
200
200
 
201
- **Humans:**
201
+ The rule below is the one source for every branch format Arcane names. The spells and the generated client instruction files carry copies that `npm run fix:self-host-parity` keeps identical to it (ARC-039 fragment `branch-naming`); nothing restates a format by hand.
202
202
 
203
- ```
204
- type/short-description
205
- ```
203
+ <!-- fragment:branch-naming:start -->
204
+ **Branch naming (every actor).** `main` is integration-only. All work happens on a topic branch, named by who creates it:
206
205
 
207
- **Session branches (interactive tools — Copilot, Claude Code, etc.):**
206
+ | Who creates the branch | Format | Example |
207
+ | --- | --- | --- |
208
+ | A human | `type/short-description` | `fix/auth-token-regression` |
209
+ | An interactive session (Claude Code, Copilot, Codex chat), including every worktree it opens and every parallel subagent it spawns | `sessions/YYYY-MM-DD-<topic-slug>`; a parallel subagent appends `-<agent>` | `sessions/2026-10-05-branch-naming`, `sessions/2026-10-05-branch-naming-merlin` |
210
+ | An autonomous roster agent on a dispatched job (`spell-full-cycle`, from `stories.json`) | `{agent-slug}/type/short-description` | `lafayette/feat/api-endpoint` |
208
211
 
209
- ```
210
- sessions/YYYY-MM-DD-topic-slug
211
- ```
212
+ The slug comes from the work — the focus, the handoff's active task, the top next action, the story, the pull request title — never from a generator. A tool-generated name (`claude/<adjective>-<surname>-<hash>`, any random adjective-noun name) is noncompliant wherever it appears and is renamed on sight. When a client offers to create a worktree or a parallel agent, supply the branch name yourself: Claude Code's `EnterWorktree` takes a `name`, and `git worktree add <path> -b <branch>` pre-creates the branch for any client; never accept a generated name. **Enforcement: structured spell gate (ARC-023) — `spell-open-session`'s Mutation Guard and `spell-create-pull-request`'s Step 0 run the branch rename gate on the branch they find; `spell agents sync` renders this rule into every client instruction file; no CI check reads a pull request's head-branch name.**
213
+ <!-- fragment:branch-naming:end -->
212
214
 
213
215
  Create the session branch as the **first action** of any session, before any file edits or commits. All session commits land on this branch. At close, push and open a PR. After merge, return to `main` — **in the primary checkout only** (ARC-028 R8). A session running in a linked worktree ends with push → PR → worktree removal instead; it must not check out `main`, because the primary checkout already holds it and Git will refuse the second checkout.
214
216
 
215
- **Examples:**
217
+ **Session branch policy (required):**
216
218
 
217
- - `sessions/2025-11-04-widget-app-implementation` (interactive session)
218
- - `sessions/2025-11-12-payment-webhook-fix` (interactive session)
219
+ <!-- fragment:branch-rename-gate:start -->
220
+ **Branch rename gate.** Applied to the current branch before a session's first mutation (`spell-open-session`) and before a pull request's first push (`spell-create-pull-request`):
219
221
 
220
- **Session branch policy (required):**
222
+ 1. Read `git branch --show-current` and `git worktree list` (a read only: across a bridged or mounted filesystem it can misreport a live worktree, EF-33 — never act on that output alone). Act only on the branch checked out in this worktree; never rename, switch or delete a branch attached to another worktree.
223
+ 2. Judge the name against the branch-naming rule above. A compliant name stays. A noncompliant one is renamed only when no open pull request depends on it — check with the provider (`gh pr list --head <branch> --state open` or `az repos pr list --source-branch <branch> --status active`); if one exists, keep the name, report it, and rename after that pull request merges.
224
+ 3. Derive the deterministic name from the work, in the session form of the rule: today's date, a kebab-case topic from the focus, the handoff's active task, the top next action or the pull request title, and the `-<agent>` suffix only for a parallel subagent.
225
+ 4. `git branch -m <old> <new>`. If `<old>` was already pushed: `git push -u origin <new>`, then `git push origin --delete <old>`, both under the push-policy check (ARC-049). Give each command a per-call timeout: on some Windows filesystems a rename or delete blocks on a file lock (the EF-20 hazard in git-conventions.md).
226
+ 5. Report `Renamed <old> → <new>` in the run's output. If the worktree, the pull-request state or the remote cannot be determined, stop without renaming and ask the operator.
227
+ <!-- fragment:branch-rename-gate:end -->
221
228
 
222
- - Session branches must be deterministic, human-readable, and derived from the active task title. **Enforcement: structured spell gate (ARC-023) — `spell-open-session`'s Mutation Guard renames a noncompliant, unpushed branch to the deterministic `sessions/YYYY-MM-DD-<topic-slug>` format before the first mutation, and its "Session branch naming compliance" check records the required rename when a PR doesn't already depend on the old name.**
223
- - Default format for new interactive sessions: `sessions/YYYY-MM-DD-<topic-slug>`.
224
- - Random adjective-noun branches (for example, `ideal-disco`) are non-compliant and must be renamed.
225
- - If a non-compliant branch was already pushed, migrate it safely:
226
- 1. `git branch -m <old> <new>`
227
- 2. `git push -u origin <new>`
228
- 3. `git push origin --delete <old>` (skip this if an active PR still depends on `<old>`).
229
229
  - **EF-20 hazard:** on some Windows/Git-for-Windows filesystems, a rename or delete can trigger
230
230
  an interactive retry prompt (e.g. a file lock from an editor or antivirus scan) that blocks
231
231
  indefinitely on a terminal with no non-interactive fallback. When running these commands
@@ -234,22 +234,7 @@ Create the session branch as the **first action** of any session, before any fil
234
234
  (`src/modules/git.ts`) applies this as a standing contract — closed stdin plus a
235
235
  command-class timeout — for every `git` invocation the CLI itself makes. **Enforcement: explicitly advisory prose (ARC-023) — the recommendation to set a timeout applies to an agent's own separate shell tool invocations of raw `git`, which nothing here checks. The cited precedent is independently verified: `runGit` (`src/modules/git.ts`) closes stdin immediately and applies a `DEFAULT_TIMEOUTS_MS`-scoped timeout for every git invocation Arcane's own CLI makes internally — a real executable check, but scoped to Arcane's own code path, not to a human's or agent's independent terminal command.**
236
236
 
237
- **Agents:**
238
-
239
- ```
240
- {agent-slug}/type/short-description
241
- ```
242
-
243
- The agent slug prefix makes branch ownership obvious in `git branch -r` output and prevents naming collisions between agents. **Enforcement: explicitly advisory prose (ARC-023) — no check in this repo validates an agent branch name against this format, unlike session-branch naming above (which `spell-open-session` does check and, when noncompliant, rename).**
244
-
245
- **Examples:**
246
-
247
- - `docs/readme-update` (human)
248
- - `feat/spell-commit-work` (human)
249
- - `fix/auth-token-regression` (human)
250
- - `lafayette/feat/api-endpoint` (agent — Lafayette)
251
- - `merlin/docs/architecture-update` (agent — Merlin)
252
- - `lince/fix/test-regression` (agent — Lince)
237
+ **Autonomous agents:** the agent-slug prefix in the rule above makes branch ownership obvious in `git branch -r` output and prevents naming collisions between agents working in parallel. **Enforcement: explicitly advisory prose (ARC-023) — no check in this repo validates an autonomous agent's branch name against the rule; the rename gate above runs only in interactive sessions (`spell-open-session`, `spell-create-pull-request`).**
253
238
 
254
239
  ### Human Workflow
255
240
 
@@ -234,7 +234,10 @@ source under `.arcane/spells/_fragments/` and never shipped on its own. A spell
234
234
  `<!-- fragment:needs-you:start -->` / `<!-- fragment:needs-you:end -->` marker pair placed where the
235
235
  spell describes its final output or report, and `npm run fix:self-host-parity` expands the fragment
236
236
  between the markers. Edit the fragment, never an expanded copy, and never restate its rules by hand
237
- in a spell body. Required actions also survive the end of a session: `spell-close-session` writes
237
+ in a spell body. Any shipped Markdown file can host a fragment the same way, not only a spell: the
238
+ `branch-naming` fragment is expanded into `git-conventions.md` and the Copilot instruction file as
239
+ well as into spells, and `spell agents sync` renders it into every client instruction file, so the
240
+ branch formats are written in exactly one place. Required actions also survive the end of a session: `spell-close-session` writes
238
241
  the open items into the handoff's `Needs you` field, and `spell-open-session` surfaces that field
239
242
  first, above the rest of the handoff, and does not mark the handoff consumed until it has.
240
243
 
@@ -49,7 +49,7 @@ See also: [[README]], [[DECISIONS]], [[governance/git-conventions|Git Convention
49
49
 
50
50
  13. **For runtime config changes. Enforcement: structured spell gate (ARC-023), hedged — `spell-commit-work`'s Step 8 operator-approval gate covers this commit like any other before it can be made, though it verifies diff/message approval rather than a dedicated confirmation that testing occurred.** (anything touching the agent runtime's config files or service restarts): do NOT commit supporting docs until the user has confirmed the change is working. Stage and present — but wait for explicit approval after testing.
51
51
 
52
- 14. **Never commit directly to main. Enforcement: explicitly advisory prose (ARC-023) — `spell doctor`'s `checkPlatformBranchPolicy` verifies only the platform's merge-method policy (squash disallowed), not that direct pushes/commits to main are blocked.** All work — human or agent — happens on topic branches. Humans use `type/short-description`; agents use `{agent-slug}/type/short-description`. Main receives changes only through PR completion, not local direct merges. See [[governance/git-conventions#branch-discipline|Branch Discipline]].
52
+ 14. **Never commit directly to main. Enforcement: explicitly advisory prose (ARC-023) — `spell doctor`'s `checkPlatformBranchPolicy` verifies only the platform's merge-method policy (squash disallowed), not that direct pushes/commits to main are blocked.** All work — human or agent — happens on topic branches, each named in the form the Branch Naming rule in git-conventions.md gives its actor (stated once there). Main receives changes only through PR completion, not local direct merges. See [[governance/git-conventions#branch-discipline|Branch Discipline]].
53
53
 
54
54
  ---
55
55
 
@@ -0,0 +1,9 @@
1
+ **Branch naming (every actor).** `main` is integration-only. All work happens on a topic branch, named by who creates it:
2
+
3
+ | Who creates the branch | Format | Example |
4
+ | --- | --- | --- |
5
+ | A human | `type/short-description` | `fix/auth-token-regression` |
6
+ | An interactive session (Claude Code, Copilot, Codex chat), including every worktree it opens and every parallel subagent it spawns | `sessions/YYYY-MM-DD-<topic-slug>`; a parallel subagent appends `-<agent>` | `sessions/2026-10-05-branch-naming`, `sessions/2026-10-05-branch-naming-merlin` |
7
+ | An autonomous roster agent on a dispatched job (`spell-full-cycle`, from `stories.json`) | `{agent-slug}/type/short-description` | `lafayette/feat/api-endpoint` |
8
+
9
+ The slug comes from the work — the focus, the handoff's active task, the top next action, the story, the pull request title — never from a generator. A tool-generated name (`claude/<adjective>-<surname>-<hash>`, any random adjective-noun name) is noncompliant wherever it appears and is renamed on sight. When a client offers to create a worktree or a parallel agent, supply the branch name yourself: Claude Code's `EnterWorktree` takes a `name`, and `git worktree add <path> -b <branch>` pre-creates the branch for any client; never accept a generated name. **Enforcement: structured spell gate (ARC-023) — `spell-open-session`'s Mutation Guard and `spell-create-pull-request`'s Step 0 run the branch rename gate on the branch they find; `spell agents sync` renders this rule into every client instruction file; no CI check reads a pull request's head-branch name.**
@@ -0,0 +1,7 @@
1
+ **Branch rename gate.** Applied to the current branch before a session's first mutation (`spell-open-session`) and before a pull request's first push (`spell-create-pull-request`):
2
+
3
+ 1. Read `git branch --show-current` and `git worktree list` (a read only: across a bridged or mounted filesystem it can misreport a live worktree, EF-33 — never act on that output alone). Act only on the branch checked out in this worktree; never rename, switch or delete a branch attached to another worktree.
4
+ 2. Judge the name against the branch-naming rule above. A compliant name stays. A noncompliant one is renamed only when no open pull request depends on it — check with the provider (`gh pr list --head <branch> --state open` or `az repos pr list --source-branch <branch> --status active`); if one exists, keep the name, report it, and rename after that pull request merges.
5
+ 3. Derive the deterministic name from the work, in the session form of the rule: today's date, a kebab-case topic from the focus, the handoff's active task, the top next action or the pull request title, and the `-<agent>` suffix only for a parallel subagent.
6
+ 4. `git branch -m <old> <new>`. If `<old>` was already pushed: `git push -u origin <new>`, then `git push origin --delete <old>`, both under the push-policy check (ARC-049). Give each command a per-call timeout: on some Windows filesystems a rename or delete blocks on a file lock (the EF-20 hazard in git-conventions.md).
7
+ 5. Report `Renamed <old> → <new>` in the run's output. If the worktree, the pull-request state or the remote cannot be determined, stop without renaming and ask the operator.
@@ -77,7 +77,7 @@ Workflow:
77
77
 
78
78
  5a. **Validate stories.json schema** — before outputting, self-check every field. Missing fields break `spell-implement`. Required top-level fields:
79
79
  - `feature` (string)
80
- - `branchName` (string, format: `agent/type/description`)
80
+ - `branchName` (string, in the autonomous roster-agent form of the branch-naming rule — `git-conventions.md` → Branch Naming)
81
81
  - `assignedAgent` (string, agent slug)
82
82
  - `trackingMode` (`internal` or `external`)
83
83
  - `externalProvider` (required when `trackingMode=external`)
@@ -28,7 +28,7 @@ Workflow:
28
28
  1. **Check git status and guard the branch** — run `git status` to see what changed, and confirm the current branch.
29
29
  - Classify the Git/remote state before enforcing the protected-branch guard. A usable merge path requires a configured remote on a supported provider (`github.com`, `dev.azure.com`, or `visualstudio.com`) and authenticated provider tooling. A remote URL alone is insufficient.
30
30
  - Apply exactly one path:
31
- - **Supported, authenticated GitHub/ADO remote + `main` or `master` checked out:** **STOP — do not stage or commit directly.** Create and switch the current worktree to a compliant topic branch (for example, `sessions/YYYY-MM-DD-<slug>`), then continue.
31
+ - **Supported, authenticated GitHub/ADO remote + `main` or `master` checked out:** **STOP — do not stage or commit directly.** Create and switch the current worktree to a compliant topic branch (a session branch, named per `git-conventions.md` → Branch Naming), then continue.
32
32
  - **Supported, authenticated GitHub/ADO remote + valid topic/PR branch checked out:** stay on that branch and continue.
33
33
  - **No remote, unsupported remote, or provider authentication unavailable:** remain on the current trunk. Print `Local-only checkpoint: no usable remote merge path; commit remains on <trunk> and no remote push/PR will run.` Continue through the local commit gate, then skip Steps 9 and 10 entirely.
34
34
  - If the current worktree, branch, provider, or authentication state cannot be determined, fail closed before staging and ask the operator. Never strand a local-only commit on a topic branch with no usable merge path.
@@ -58,6 +58,27 @@ Before enabling auto-complete/auto-merge or completing an existing PR, resolve `
58
58
  > This rule is on the **agent**, not on the spell. Calling `az repos pr create` / `gh pr create` directly is **not** an escape hatch — it is a governance violation. See `.arcane/governance/git-conventions.md` → **🛑 Agent-mandatory pre-PR guard**.
59
59
 
60
60
  1. Run `git branch --show-current`. **STOP** if on `main`/`master` — you cannot PR the integration branch into itself. Also **STOP** if detached HEAD (empty output) — check out a named branch first.
61
+ - **Branch rename gate (before any push in this Step 0):** judge the branch you found against the branch-naming rule and rename it when the gate says so — a tool-generated name must not reach a pull request. A branch a worktree or a parallel subagent created is judged the same way.
62
+ <!-- fragment:branch-naming:start -->
63
+ **Branch naming (every actor).** `main` is integration-only. All work happens on a topic branch, named by who creates it:
64
+
65
+ | Who creates the branch | Format | Example |
66
+ | --- | --- | --- |
67
+ | A human | `type/short-description` | `fix/auth-token-regression` |
68
+ | An interactive session (Claude Code, Copilot, Codex chat), including every worktree it opens and every parallel subagent it spawns | `sessions/YYYY-MM-DD-<topic-slug>`; a parallel subagent appends `-<agent>` | `sessions/2026-10-05-branch-naming`, `sessions/2026-10-05-branch-naming-merlin` |
69
+ | An autonomous roster agent on a dispatched job (`spell-full-cycle`, from `stories.json`) | `{agent-slug}/type/short-description` | `lafayette/feat/api-endpoint` |
70
+
71
+ The slug comes from the work — the focus, the handoff's active task, the top next action, the story, the pull request title — never from a generator. A tool-generated name (`claude/<adjective>-<surname>-<hash>`, any random adjective-noun name) is noncompliant wherever it appears and is renamed on sight. When a client offers to create a worktree or a parallel agent, supply the branch name yourself: Claude Code's `EnterWorktree` takes a `name`, and `git worktree add <path> -b <branch>` pre-creates the branch for any client; never accept a generated name. **Enforcement: structured spell gate (ARC-023) — `spell-open-session`'s Mutation Guard and `spell-create-pull-request`'s Step 0 run the branch rename gate on the branch they find; `spell agents sync` renders this rule into every client instruction file; no CI check reads a pull request's head-branch name.**
72
+ <!-- fragment:branch-naming:end -->
73
+ <!-- fragment:branch-rename-gate:start -->
74
+ **Branch rename gate.** Applied to the current branch before a session's first mutation (`spell-open-session`) and before a pull request's first push (`spell-create-pull-request`):
75
+
76
+ 1. Read `git branch --show-current` and `git worktree list` (a read only: across a bridged or mounted filesystem it can misreport a live worktree, EF-33 — never act on that output alone). Act only on the branch checked out in this worktree; never rename, switch or delete a branch attached to another worktree.
77
+ 2. Judge the name against the branch-naming rule above. A compliant name stays. A noncompliant one is renamed only when no open pull request depends on it — check with the provider (`gh pr list --head <branch> --state open` or `az repos pr list --source-branch <branch> --status active`); if one exists, keep the name, report it, and rename after that pull request merges.
78
+ 3. Derive the deterministic name from the work, in the session form of the rule: today's date, a kebab-case topic from the focus, the handoff's active task, the top next action or the pull request title, and the `-<agent>` suffix only for a parallel subagent.
79
+ 4. `git branch -m <old> <new>`. If `<old>` was already pushed: `git push -u origin <new>`, then `git push origin --delete <old>`, both under the push-policy check (ARC-049). Give each command a per-call timeout: on some Windows filesystems a rename or delete blocks on a file lock (the EF-20 hazard in git-conventions.md).
80
+ 5. Report `Renamed <old> → <new>` in the run's output. If the worktree, the pull-request state or the remote cannot be determined, stop without renaming and ask the operator.
81
+ <!-- fragment:branch-rename-gate:end -->
61
82
  2. **Verify the target exists:** `git rev-parse --verify origin/<target>`. If it fails, `git fetch origin <target>`; if still missing, **STOP** and ask the user for the correct `--target`.
62
83
  3. **Ensure the branch is on origin (upstream):** run the push-policy check below before any push in this Step 0 — this item's `git push -u` and item 6's `--force-with-lease` push. If it stops a push, stop the spell: a PR cannot be opened for a branch the remote does not have.
63
84
 
@@ -119,7 +119,7 @@ Execute the `spell-implement` workflow:
119
119
  git fetch --prune origin # origin/main is now current
120
120
  ```
121
121
  and branch from `origin/main` in step 1. Check which primitive you are in with `git rev-parse --path-format=absolute --git-common-dir` vs `--git-dir` — equal means primary checkout. `--path-format=absolute` is required, or every primary checkout looks like a worktree from any subdirectory.
122
- 1. Create the topic branch from `stories.json.branchName` (format: `{agent}/type/description`).
122
+ 1. Create the topic branch from `stories.json.branchName` (the autonomous roster-agent form of the branch-naming rule in `git-conventions.md` → Branch Naming).
123
123
  2. Loop:
124
124
  a. Pick the next story where `passes: false`, ordered by priority.
125
125
  b. Implement the story — minimum code to satisfy acceptance criteria.
@@ -48,8 +48,8 @@ Do not create a branch during a read-only session. Immediately before the first
48
48
 
49
49
  | Observed state | Required action before mutation |
50
50
  | --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
51
- | Supported, authenticated GitHub/ADO remote + trunk checked out | Create and switch the **current worktree only** to `sessions/YYYY-MM-DD-<topic-slug>`, derived deterministically from the focus, handoff active task, or top next action. |
52
- | Already on a compliant `sessions/YYYY-MM-DD-<topic-slug>` branch | Stay on it; do not create or switch branches. |
51
+ | Supported, authenticated GitHub/ADO remote + trunk checked out | Create and switch the **current worktree only** to a session branch named per the branch-naming rule below, derived deterministically from the focus, handoff active task, or top next action. |
52
+ | Already on a compliant session branch | Stay on it; do not create or switch branches. |
53
53
  | Noncompliant unpushed branch with no active PR | Rename it to the deterministic session name before mutation. |
54
54
  | Branch has an active PR | Stay on the PR branch and report it; never rename a branch backing an active PR. |
55
55
  | Current path is a linked worktree | Mutate/switch only the current worktree. Never switch or delete a branch attached to another worktree. |
@@ -59,6 +59,30 @@ A usable merge path requires a configured remote on a supported provider (`githu
59
59
 
60
60
  If branch creation/rename is required, complete it before writing the handoff consumed marker or any other file. If the guard cannot determine the current worktree, active-PR state, or merge capability, fail closed without mutation and ask for operator direction.
61
61
 
62
+ The branch-naming rule the table applies, and the rename gate it runs on a noncompliant branch:
63
+
64
+ <!-- fragment:branch-naming:start -->
65
+ **Branch naming (every actor).** `main` is integration-only. All work happens on a topic branch, named by who creates it:
66
+
67
+ | Who creates the branch | Format | Example |
68
+ | --- | --- | --- |
69
+ | A human | `type/short-description` | `fix/auth-token-regression` |
70
+ | An interactive session (Claude Code, Copilot, Codex chat), including every worktree it opens and every parallel subagent it spawns | `sessions/YYYY-MM-DD-<topic-slug>`; a parallel subagent appends `-<agent>` | `sessions/2026-10-05-branch-naming`, `sessions/2026-10-05-branch-naming-merlin` |
71
+ | An autonomous roster agent on a dispatched job (`spell-full-cycle`, from `stories.json`) | `{agent-slug}/type/short-description` | `lafayette/feat/api-endpoint` |
72
+
73
+ The slug comes from the work — the focus, the handoff's active task, the top next action, the story, the pull request title — never from a generator. A tool-generated name (`claude/<adjective>-<surname>-<hash>`, any random adjective-noun name) is noncompliant wherever it appears and is renamed on sight. When a client offers to create a worktree or a parallel agent, supply the branch name yourself: Claude Code's `EnterWorktree` takes a `name`, and `git worktree add <path> -b <branch>` pre-creates the branch for any client; never accept a generated name. **Enforcement: structured spell gate (ARC-023) — `spell-open-session`'s Mutation Guard and `spell-create-pull-request`'s Step 0 run the branch rename gate on the branch they find; `spell agents sync` renders this rule into every client instruction file; no CI check reads a pull request's head-branch name.**
74
+ <!-- fragment:branch-naming:end -->
75
+
76
+ <!-- fragment:branch-rename-gate:start -->
77
+ **Branch rename gate.** Applied to the current branch before a session's first mutation (`spell-open-session`) and before a pull request's first push (`spell-create-pull-request`):
78
+
79
+ 1. Read `git branch --show-current` and `git worktree list` (a read only: across a bridged or mounted filesystem it can misreport a live worktree, EF-33 — never act on that output alone). Act only on the branch checked out in this worktree; never rename, switch or delete a branch attached to another worktree.
80
+ 2. Judge the name against the branch-naming rule above. A compliant name stays. A noncompliant one is renamed only when no open pull request depends on it — check with the provider (`gh pr list --head <branch> --state open` or `az repos pr list --source-branch <branch> --status active`); if one exists, keep the name, report it, and rename after that pull request merges.
81
+ 3. Derive the deterministic name from the work, in the session form of the rule: today's date, a kebab-case topic from the focus, the handoff's active task, the top next action or the pull request title, and the `-<agent>` suffix only for a parallel subagent.
82
+ 4. `git branch -m <old> <new>`. If `<old>` was already pushed: `git push -u origin <new>`, then `git push origin --delete <old>`, both under the push-policy check (ARC-049). Give each command a per-call timeout: on some Windows filesystems a rename or delete blocks on a file lock (the EF-20 hazard in git-conventions.md).
83
+ 5. Report `Renamed <old> → <new>` in the run's output. If the worktree, the pull-request state or the remote cannot be determined, stop without renaming and ask the operator.
84
+ <!-- fragment:branch-rename-gate:end -->
85
+
62
86
  **Drift Check (run before deep context gathering):**
63
87
 
64
88
  Run the `spell-check-drift` spell first, before building the state snapshot or gathering deep context. Drift compounds the longer a session runs, so catch it early.
@@ -98,10 +122,8 @@ Before anything else, check:
98
122
  - **Otherwise** → **primary checkout on a session branch** (R2). This is the default and it is deliberately the do-nothing path: one actor, one checkout, no new tooling.
99
123
  - **Footprint overlap overrides the choice (R4).** If this session's work touches the same files or the same shared sequence (migration numbers, generated indexes, lockfiles) as work already running in another primitive, do **not** isolate it — serialize instead: wait, or re-scope to a disjoint footprint first. Isolation does not prevent those collisions, it hides them until merge review.
100
124
  - Working in a linked worktree changes two things later in the session and nothing else: `spell-close-session` must not check out `main` (see git-conventions.md's Post-Merge Cleanup section), and the worktree contains no untracked tooling state — budget for `npm install` or equivalent in a code repo. Branch naming, attribution, and the PR gate are identical from every primitive (R8).
101
- - **Session branch naming compliance:** Branch names must be human-readable and policy-compliant:
102
- - Interactive session default: `sessions/YYYY-MM-DD-<topic-slug>` (kebab-case topic from current task/session objective).
103
- - Disallow random adjective-noun generator names (example: `ideal-disco`) as session defaults.
104
- - If current branch is non-compliant and no active PR depends on it, record the required rename for the Mutation Guard. Do not rename during a read-only session.
125
+ - **Session branch naming compliance:** judge the current branch against the branch-naming rule (Mutation Guard section above), including a branch a worktree or a parallel subagent created:
126
+ - If it is noncompliant and no active PR depends on it, record the required rename for the Mutation Guard. Do not rename during a read-only session.
105
127
  - If an active PR uses the old branch name, do not force-delete the old remote branch; flag it and continue with a follow-up rename plan.
106
128
  - **Stale local branches:** Run `git branch --merged main` to list branches already merged that should be deleted — this session's own read-only candidate list (`--merged` also misses every branch landed via this repo's sanctioned rebase-and-fast-forward, so treat a *clean* result as "no ancestry-visible candidates," not "nothing to check"). Open-session only lists; it does not delete. Apply the [Content-Verified Branch Deletion](../../.arcane/governance/git-conventions.md#content-verified-branch-deletion-todomd-merged-branch-cleanup-finding) procedure (git-conventions.md) to any candidate before flagging it as safe, and leave the actual idempotent prune to `spell-close-session`'s sweep.
107
129
  - **Tracker configuration check (early):** resolve active tracking settings before planning, in this order: root `.arcane.json` (if present) -> the committed self-hosted source manifest (`src/assets/.arcane.json`, read only when it declares `selfHosted: true` -- this is EF-14's recorded self-hosting resolution tier, distinct from treating the mere presence of a self-host marker as license to infer other, unrelated config) -> the current feature PRD frontmatter -> ask. Persisted once at `spell init`/`spell update` (EF-14); do not re-ask when any of the first three sources already sets it.
@@ -159,7 +181,7 @@ Before anything else, check:
159
181
  - Provide a 1–4 word, sentence-case, human-meaningful session name.
160
182
  - If a focus/task argument is provided, generate the name deterministically from that focus (never use the generic name `Open session`).
161
183
  - If no focus argument is provided, generate the name from the top recommended action in `## Next Session Plan`.
162
- - Optional helper line: `Branch helper: sessions/YYYY-MM-DD-<kebab-case-slug>`.
184
+ - Optional helper line: `Branch helper: <session branch name>`, in the session form of the branch-naming rule.
163
185
 
164
186
  ## Risks And Gaps
165
187
 
@@ -133,19 +133,16 @@ expected) marks that server down for the rest of the session — fall back to th
133
133
  repos pr` / `gh` / REST), no blind retries, and report the downgrade in output. Full rule and origin
134
134
  incident: `.arcane/governance/git-conventions.md` → Known issues.
135
135
 
136
- ## Branch Naming (Interactive Sessions)
136
+ ## Branch Naming
137
137
 
138
- Interactive tool session branches use:
139
- ```
140
- sessions/YYYY-MM-DD-topic-slug
141
- ```
138
+ <!-- fragment:branch-naming:start -->
139
+ **Branch naming (every actor).** `main` is integration-only. All work happens on a topic branch, named by who creates it:
142
140
 
143
- Agent-autonomous branches use:
144
- ```
145
- {agent-slug}/type/short-description
146
- ```
141
+ | Who creates the branch | Format | Example |
142
+ | --- | --- | --- |
143
+ | A human | `type/short-description` | `fix/auth-token-regression` |
144
+ | An interactive session (Claude Code, Copilot, Codex chat), including every worktree it opens and every parallel subagent it spawns | `sessions/YYYY-MM-DD-<topic-slug>`; a parallel subagent appends `-<agent>` | `sessions/2026-10-05-branch-naming`, `sessions/2026-10-05-branch-naming-merlin` |
145
+ | An autonomous roster agent on a dispatched job (`spell-full-cycle`, from `stories.json`) | `{agent-slug}/type/short-description` | `lafayette/feat/api-endpoint` |
147
146
 
148
- Human topic branches use:
149
- ```
150
- type/short-description
151
- ```
147
+ The slug comes from the work — the focus, the handoff's active task, the top next action, the story, the pull request title — never from a generator. A tool-generated name (`claude/<adjective>-<surname>-<hash>`, any random adjective-noun name) is noncompliant wherever it appears and is renamed on sight. When a client offers to create a worktree or a parallel agent, supply the branch name yourself: Claude Code's `EnterWorktree` takes a `name`, and `git worktree add <path> -b <branch>` pre-creates the branch for any client; never accept a generated name. **Enforcement: structured spell gate (ARC-023) — `spell-open-session`'s Mutation Guard and `spell-create-pull-request`'s Step 0 run the branch rename gate on the branch they find; `spell agents sync` renders this rule into every client instruction file; no CI check reads a pull request's head-branch name.**
148
+ <!-- fragment:branch-naming:end -->