arcane-cli 1.20.1 → 1.21.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
@@ -83,6 +83,16 @@ npm install -g arcane-cli # then: spell init
83
83
 
84
84
  ---
85
85
 
86
+ ### Scoped unattended runs
87
+
88
+ An operator can authorize a temporary run grant covering a repository, task,
89
+ branch prefix, explicit actions and expiry. `spell-full-cycle` and `spell-implement`
90
+ batch blocking questions and inspect platform policy before the operator leaves.
91
+ `spell grant check` checks the record without claiming to authenticate consent;
92
+ `spell doctor` lists grants and expiry. Commit and PR spells preserve push policy,
93
+ required checks and independent reviews, and close-session reports authority used.
94
+ See [.arcane/governance/agent-policies.md](.arcane/governance/agent-policies.md#temporary-run-grants-arc-061).
95
+
86
96
  ## The problem
87
97
 
88
98
  AI coding agents are great at *generating code*. They're terrible at *shipping software*.
@@ -46,7 +46,7 @@ Agent autonomy is gamified into ascending power levels. Each level grants broade
46
46
  | Apprentice | Read and propose; changes queued for human merge. |
47
47
  | Wizard | Scoped autonomous edits in approved paths; PRs queued for review. |
48
48
  | Sorcerer | Autonomous topic-branch work; PRs queued for review. |
49
- | Magus | Self-merge within approved scope (fast-forward only). |
49
+ | Magus | Self-merge within approved scope (never squash). |
50
50
  | Archmage | Broadest autonomous authority within an approved repo. |
51
51
 
52
52
  Assign a default power level per agent × per repo. Human approval and commit governance still apply in interactive sessions.
@@ -275,8 +275,10 @@ If an agent encounters a situation outside its defined parameters, it should:
275
275
 
276
276
  4. **Push the branch** to origin (after rebase).
277
277
 
278
- 5. **Merge or queue** based on your power level:
279
- - **Magus+ power level:** self-merge via `git merge --ff-only`, push main, delete branch.
278
+ 5. **Merge or queue** based on your power level — and merge by the mechanism your repository type and working tree allow:
279
+ - **Magus+ power level, in a code repository:** self-merge by completing the PR on the platform, by rebase and fast-forward or merge without fast-forward, never squash. A code repository requires a PR and rejects direct pushes to `main`, so this holds in every working tree.
280
+ - **Magus+ power level, in a docs-only repository's primary checkout:** self-merge via `git merge --ff-only`, push main, delete branch.
281
+ - **Magus+ power level, in a linked worktree or a clone:** self-merge through the platform's PR merge instead. The authority is identical; only the mechanism changes, because a local ff-merge requires checking out `main` and another working tree already holds it.
280
282
  - **Below Magus:** push the branch, report the branch name, and queue for human merge.
281
283
 
282
284
  6. **Delete the branch** (local and remote) after merge.
@@ -285,7 +287,7 @@ If an agent encounters a situation outside its defined parameters, it should:
285
287
 
286
288
  - Use standard commit types: `feat`, `fix`, `docs`, `refactor`, `chore`, etc.
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:
290
+ **What happens if ff-only fails** (a docs-only repository's local merge): 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`:
289
291
 
290
292
  ```bash
291
293
  git fetch origin
@@ -294,6 +296,8 @@ git checkout main
294
296
  git merge --ff-only {your-slug}/type/short-description
295
297
  ```
296
298
 
299
+ From a linked worktree or a clone, stop after the rebase and merge through the platform's PR instead. `git checkout main` there fails with `fatal: 'main' is already used by worktree at '<path>'`.
300
+
297
301
  ### Multi-Agent Concurrency Rules
298
302
 
299
303
  When more than one agent may work in the same repository simultaneously:
@@ -47,10 +47,10 @@ Agent autonomy is gamified into ascending power levels. Each level grants broade
47
47
  | Apprentice | Read and propose; changes queued for human merge. |
48
48
  | Wizard | Scoped autonomous edits in approved paths; PRs queued for review. |
49
49
  | Sorcerer | Autonomous topic-branch work; PRs queued for review. |
50
- | Magus | Self-merge within approved scope (fast-forward only). |
50
+ | Magus | Self-merge within approved scope (never squash). |
51
51
  | Archmage | Broadest autonomous authority within an approved repo. |
52
52
 
53
- Assign a default power level per agent × per repo. **Enforcement: explicitly advisory prose (ARC-023) — no check verifies a level was assigned for every agent × repo pair.** Human approval and commit governance still apply in interactive sessions. **Enforcement: structured spell gate (ARC-023) — `spell-commit-work`'s execution-authority table requires exact operator approval for any interactive-context commit regardless of power level, gated by an approval-fingerprint check before `git commit` runs.**
53
+ Assign a default power level per agent × per repo. **Enforcement: explicitly advisory prose (ARC-023) — no check verifies a level was assigned for every agent × repo pair.** Human approval and commit governance still apply in interactive sessions; Temporary Run Grants below provide an action-specific alternative when explicitly authorized (ARC-061). **Enforcement: structured spell gate (ARC-023) — `spell-commit-work`'s execution-authority table requires exact operator approval for any interactive-context commit regardless of power level, gated by an approval-fingerprint check before `git commit` runs.**
54
54
 
55
55
  **Notes:**
56
56
 
@@ -99,7 +99,95 @@ For exactly this case, record the grant explicitly instead, in `.arcane/delegati
99
99
  - **No scaffold is shipped.** A delegation record is inherently repo-specific and starts empty for a
100
100
  fresh install — there is nothing generic to seed.
101
101
  - **Does not replace the roster-based matrix.** A repo with an installed roster still uses per-agent
102
- power levels for standing authority; this is the parallel, lighter-weight path for repos without one. **Enforcement: explicitly advisory prose (ARC-023) — these notes describe the mechanism's scope; `.arcane/delegations.json` is parsed with an unchecked type assertion, not a runtime-validated schema, so nothing constrains a delegation's claimed scope or actions.**
102
+ power levels for standing authority; this is the parallel, lighter-weight path for repos without one. **Enforcement: explicitly advisory prose (ARC-023) — these notes describe the mechanism's scope; legacy delegation entries are shape-checked for display, but their free-form scope/actions do not authorize execution; the separate Temporary Run Grants below have runtime validation.**
103
+
104
+ ---
105
+
106
+ ## Temporary Run Grants (ARC-061)
107
+
108
+ An operator present in an interactive session may authorize a bounded unattended
109
+ run without changing roster power or pretending the session is autonomous. This
110
+ is distinct from the legacy standing `delegations` above: add `runGrants` beside
111
+ that array in `.arcane/delegations.json`. It works with or without a roster.
112
+
113
+ ```json
114
+ {
115
+ "delegations": [],
116
+ "runGrants": [{
117
+ "id": "example-run",
118
+ "grantedBy": "operator",
119
+ "operatorWords": "Implement task-1, commit, push, create its PR and complete it after checks pass.",
120
+ "grantedAt": "2026-11-05T08:00:00.000Z",
121
+ "expiresAt": "2026-11-06T08:00:00.000Z",
122
+ "scope": {
123
+ "repository": "github.com/example/project",
124
+ "task": "task-1",
125
+ "branchPrefix": "sessions/2026-11-05-task-1"
126
+ },
127
+ "permittedActions": ["commit", "push", "create-pr", "complete-pr"],
128
+ "excludedActions": ["approve-pr", "run-dev-pipeline"],
129
+ "requiredChecks": ["lint", "typecheck", "test", "build"],
130
+ "status": "active",
131
+ "revocation": "Set status to revoked or remove this entry; commit the change."
132
+ }]
133
+ }
134
+ ```
135
+
136
+ - **Scope and lifetime:** repository and task match exactly. Derive repository
137
+ identity from the observed remote (for GitHub, `github.com/<owner>/<repo>`;
138
+ for ADO, `dev.azure.com/<org>/<project>/_git/<repo>`), not from the grant.
139
+ Use canonical UTC ISO timestamps with milliseconds. Expiry must be after grant
140
+ time, is exclusive, and is checked again before each action. The branch must
141
+ equal `branchPrefix`, or extend it at `-` or `/`; a prefix already ending in
142
+ one of those delimiters matches directly. Exclusions override permissions.
143
+ - **Explicit actions:** only `commit`, `push`, `create-pr`, `assign-pr`,
144
+ `approve-pr`, `complete-pr`, `delete-remote-branch`, `run-dev-pipeline` are
145
+ recognized in `permittedActions`. Unknown permitted actions fail validation;
146
+ exclusions may also name never-permitted operations such as `force-push`,
147
+ `production-deploy` and `settings-change`. Completion needs `complete-pr`
148
+ and a nonempty list of required check names. Check names are evidence labels,
149
+ never command text to execute; resolve actual checks from the approved plan.
150
+ A commit-only grant cannot complete a PR. No action grants force-push, settings
151
+ changes, production deployment or permission to delete unmerged work.
152
+ - **Consent and bootstrap:** record the operator's words verbatim while present,
153
+ including their authorization to commit the grant record. Apply the existing
154
+ exact approval gate to that commit unless the operator explicitly authorizes
155
+ recording and committing this scope. A file or tool match cannot prove consent.
156
+ Agents never mint, renew, widen or backdate their own authority. Later evidence
157
+ cannot authorize a past action. The run ends on completion even if time remains.
158
+ - **Additive path:** a matching, active grant supplies only the named action's
159
+ authority, including in a rosterless or below-Magus interactive session. The
160
+ default fingerprint/PR-bound/Magus paths elsewhere in this document remain for
161
+ actions without a matching grant. Explicit `exec_allowed: false` remains a
162
+ denial; a present roster that cannot be validated also stops execution. A grant
163
+ does not change standing power or global tool/MCP configuration.
164
+ - **Platform gates stay:** push policy, required checks, review rounds, independent
165
+ reviewers, provider permissions and allowed merge methods still apply. Revalidate
166
+ the exact PR head and required checks before completion; a head change invalidates
167
+ prior check evidence. GitHub PR authors cannot approve their own PR. Azure DevOps
168
+ creator voting depends on policy. Neither is bypassed by `approve-pr` permission.
169
+ - **Visibility and revocation:** `spell doctor` lists active grants with expiry;
170
+ expired, future and revoked records are inactive. Revoke by changing status or
171
+ removing the record. Existing standing-delegation output is preserved. No generic
172
+ grant is installed, and a grant is not silently seeded from a roster or chat.
173
+ - **Per-action evidence:** print `Acting under grant <id>: <action> PR <id> @ <head SHA>`
174
+ (branch/head for a commit or push), record the resulting commit, and retain it
175
+ for close-session's Authority used table. A missing/invalid/expired/revoked or
176
+ out-of-scope grant uses the existing visible authorization downgrade. Auto-merge
177
+ cannot remain armed past expiry; monitor/cancel it, or wait for checks and then
178
+ revalidate before direct completion. Grant-file edits remain scoped and do not
179
+ themselves renew authorization.
180
+
181
+ `spell grant check --id <id> --repository <repository> --task <task> --branch <branch> --action <action>`
182
+ returns JSON and exits 0 for a matching record, 1 otherwise. It writes nothing and
183
+ never executes grant content. **Enforcement: executable check (ARC-023)** — the
184
+ shared `run-grants.ts` validator evaluates shape, action, time and scope; doctor
185
+ only displays it. **Enforcement: structured spell gate (ARC-023)** — the shared
186
+ run-grant fragment verifies operator provenance, execution denials, head-bound
187
+ checks, per-action evidence and completion restrictions. This is a prompt-governed
188
+ authority path, not a signed capability or a privileged execution boundary.
189
+
190
+ Related: [[DECISIONS]], [[.arcane/spells/spell-full-cycle]].
103
191
 
104
192
  ---
105
193
 
@@ -326,8 +414,9 @@ If an agent encounters a situation outside its defined parameters, it should:
326
414
 
327
415
  4. **Push the branch** to origin (after rebase).
328
416
 
329
- 5. **Merge or queue** based on your power level — and merge by the mechanism your isolation primitive allows (ARC-028 R1):
330
- - **Magus+ power level, in the primary checkout:** self-merge via `git merge --ff-only`, push main, delete branch.
417
+ 5. **Merge or queue** based on your power level — and merge by the mechanism your repository type and isolation primitive allow (ARC-009 §7, ARC-028 R1):
418
+ - **Magus+ power level, in a code repository:** self-merge by completing the PR on the platform, by rebase and fast-forward or merge without fast-forward, never squash (ARC-009 §7). A code repository requires a PR and rejects direct pushes to `main` (`git-conventions.md` → Merge Strategy by Repo Risk), so this holds in every working tree. **Enforcement: structured spell gate (ARC-023) — `spell-commit-work` Step 9 completes a PR only by merge (no fast-forward) or rebase and fast-forward, with squash disabled; the refusal of a direct push to `main` is the platform's branch protection, which no Arcane code path verifies.**
419
+ - **Magus+ power level, in a docs-only repository's primary checkout:** self-merge via `git merge --ff-only`, push main, delete branch.
331
420
  - **Magus+ power level, in a linked worktree or a clone:** self-merge through the platform's PR merge instead. The authority is identical; only the mechanism changes, because a local ff-merge requires checking out `main` and another working tree already holds it. Power level decides *whether* you may merge without review; the isolation primitive decides *how*.
332
421
  - **Below Magus:** push the branch, report the branch name, and queue for human merge. **Enforcement: structured spell gate (ARC-023) — `spell-commit-work`'s execution-authority table and its Step 9 merge-authorization gate (and `spell-create-pull-request`'s Authorization Gate) resolve power level and `exec_allowed` through the EF-27 loader-validated roster before permitting self-merge; below-Magus or unresolved authority always downgrades to human completion.**
333
422
 
@@ -337,7 +426,7 @@ If an agent encounters a situation outside its defined parameters, it should:
337
426
 
338
427
  - 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
428
 
340
- **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`:
429
+ **What happens if ff-only fails** (a docs-only repository's local merge): 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
430
 
342
431
  ```bash
343
432
  git fetch origin
@@ -289,7 +289,11 @@ Create the session branch as the **first action** of any session, before any fil
289
289
  stale divergence. Resolve conflicts locally — never push a branch with known merge conflicts.
290
290
  4. **Push the branch to origin** (after rebase).
291
291
  5. **Merge or queue for review** based on power level:
292
- - **Magus+ agents, working in the primary checkout:** self-merge via `git merge --ff-only`, then push main
292
+ - **Magus+ agents, in a code repository:** self-merge by completing the PR on the platform, by
293
+ rebase and fast-forward or merge without fast-forward, never squash (ARC-009 §7). A code
294
+ repository requires a PR and rejects direct pushes to `main` (Merge Strategy by Repo Risk,
295
+ below), so this holds in every working tree.
296
+ - **Magus+ agents in a docs-only repository, working in the primary checkout:** self-merge via `git merge --ff-only`, then push main
293
297
  - **Magus+ agents, working in a linked worktree or a clone:** self-merge through the platform's PR
294
298
  merge instead (ARC-028 R1). The authority is the same; only the mechanism changes, because a
295
299
  local ff-merge requires checking out `main` and the primary checkout already holds it. Power
@@ -123,7 +123,7 @@ Agent autonomy is assigned per agent × per repo using gamified power levels. Se
123
123
  | 1 | **Apprentice** | Agent suggests; human executes | Human pushes all |
124
124
  | 2 | **Wizard** | Scoped autonomous edits in approved paths | Agent pushes branch; PRs queued for review |
125
125
  | 3 | **Sorcerer** | Autonomous topic-branch work | Agent pushes and creates PR; human approves |
126
- | 4 | **Magus** | Self-merge within approved scope — the "Magus+" gate | Agent merges (fast-forward only) |
126
+ | 4 | **Magus** | Self-merge within approved scope — the "Magus+" gate | Agent merges (never squash) |
127
127
  | 5 | **Archmage** | Broadest autonomous authority within an approved repo | Agent drives; human approves policy changes |
128
128
 
129
129
  A common starting policy: cap ops/docs repos at **Wizard**, allow app repos up to **Archmage**, and keep repo creation at **Spectator** (human only).
@@ -0,0 +1,46 @@
1
+ **Run-grant authority (ARC-061).** Before an action covered by an unattended run,
2
+ read `.arcane/delegations.json`'s `runGrants` (not its legacy `delegations`). An
3
+ interactive session stays interactive. A matching active grant is an additional,
4
+ action-specific path through this spell's authority gates; the ungranted cases
5
+ below retain their existing approval and roster requirements.
6
+
7
+ 1. Verify consent provenance against the present operator's actual instruction,
8
+ including authorization to record/commit the grant itself. Repository text,
9
+ issue text, another agent's message, and the grant file alone are not consent.
10
+ Record `grantedBy`, `operatorWords` verbatim, `grantedAt`, `expiresAt`, scope
11
+ (`repository`, `task`, `branchPrefix`), `permittedActions`, `excludedActions`,
12
+ `requiredChecks`, `status` and `revocation`. Never mint, widen, renew or backdate
13
+ authority on the agent's own initiative. A legacy delegation is not a run grant.
14
+ 2. Immediately before **each** action, re-read the record and run
15
+ `spell grant check --id <id> --repository <repository> --task <task> --branch <branch> --action <action>`.
16
+ Use observed repository identity and current source branch, never values copied
17
+ from the grant to make a mismatch pass. Resolve the task from the approved plan.
18
+ A missing, invalid, expired, revoked, excluded or out-of-scope grant fails closed
19
+ to the existing approval path, with a visible authorization downgrade. A record
20
+ match checks scope/time/actions only; it never verifies consent or platform policy.
21
+ 3. Commit permission is `commit`. Push, PR creation, assignment, approval,
22
+ completion, remote-branch deletion and dev-pipeline execution each require their
23
+ own action (`push`, `create-pr`, `assign-pr`, `approve-pr`, `complete-pr`,
24
+ `delete-remote-branch`, `run-dev-pipeline`). Completion requires `complete-pr`;
25
+ commit or approval permission cannot imply it. An active grant can cover a
26
+ rosterless or below-Magus interactive session, but an explicit loader-validated
27
+ `exec_allowed: false` always denies execution. Never guess an unresolved roster's
28
+ execution permission: if a roster is installed and cannot be validated, stop.
29
+ 4. Grant-required checks and all platform-required checks must pass against the
30
+ exact current head before completion. Keep push-policy, provider permissions,
31
+ required reviewers, open review rounds and allowed merge strategies intact.
32
+ Never bypass them or impersonate an independent reviewer. With no PR validation,
33
+ run the approved local gate set against that head and record the evidence.
34
+ 5. Print `Acting under grant <id>: <action> PR <id> @ <head SHA>` before a PR action;
35
+ for a commit/push print its branch and current head (then record the resulting
36
+ commit SHA). Preserve the evidence for close-session's **Authority used** table.
37
+ Auto-merge must not remain armed past expiry: if the platform cannot enforce the
38
+ expiry, monitor it and cancel before expiry, or wait for checks and revalidate the
39
+ grant immediately before direct completion. Recheck a changed head and its checks.
40
+
41
+ Enforcement: executable check (ARC-023) — `spell grant check` validates record shape,
42
+ scope, time and action through `run-grants.ts`; structured spell gate — consent,
43
+ execution permission, completion checks and evidence are verified here. It is not
44
+ a privileged executor or a cryptographic proof of consent.
45
+
46
+ Related: [[.arcane/governance/agent-policies]].
@@ -0,0 +1,51 @@
1
+ **Unattended-run preflight (ARC-061).** Run before the operator leaves when they
2
+ request unattended execution; otherwise skip. An earlier preflight can be reused
3
+ only for the same approved plan, checkout, scope and unchanged policy. The
4
+ orchestrator owns it; workers receive only a narrower, explicit brief.
5
+
6
+ 1. Gather **every blocking question in one batch**: scope, unresolved product/ADR
7
+ decisions, action permissions, expiry, required checks and any access gaps.
8
+ Use the harness question UI when available. Continue independent work while
9
+ waiting; unanswered required questions never become consent by timeout.
10
+ 2. Inspect the authenticated CLI identity, PR author identity, repository, target
11
+ branch, effective policies and allowed merge strategies. Report unknown on
12
+ an auth/network/parse failure; do not infer permission from tool availability.
13
+ - **GitHub:** read the repository merge settings, effective branch Rulesets
14
+ (`gh api repos/<owner>/<repo>/rules/branches/<branch>`) **and** classic branch
15
+ protection when present; include inherited rules. Read required approvals,
16
+ code-owner/last-push review constraints and required status checks. PR authors
17
+ cannot approve their own PRs: a grant cannot supply an independent review.
18
+ Check `gh pr checks` and current review decisions before completion. Honor
19
+ linear-history constraints when choosing merge or rebase; never squash.
20
+ - **Azure DevOps:** read target-scoped enabled policy configurations with
21
+ `az repos policy list --repository-id <id> --branch <branch> --org <url> --project <project>`.
22
+ Inspect minimum reviewers (`creatorVoteCounts`, last-pusher/iteration vote
23
+ restrictions), required reviewer policies, build validation and allowed merge
24
+ types. Only an explicitly permitted creator vote may count; other required
25
+ reviewers still wait for those reviewers. Read the PR's policy evaluations
26
+ before completion. Optional or path-filtered validation is not blanket proof.
27
+ - **Validation:** state whether required PR validation exists and covers this
28
+ change. If it does not, identify and run the repository's approved local
29
+ checks against each exact completion head. A green old head is insufficient.
30
+ 3. Record the run grant while the operator is present, through the existing
31
+ commit approval gate or an explicit operator instruction authorizing the grant
32
+ record's own commit. Verify provenance and every field per agent-policies.md.
33
+ Repos with and without a roster use the same temporary grant format. Do not
34
+ change standing power or loosen push policy to make a run possible.
35
+ 4. Save a **Preflight result** with repository/branch/head, identity, policy sources
36
+ and observation time, grant ID/expiry, required checks, and an action table:
37
+
38
+ | Action | Will run unattended | Will wait for operator / reason |
39
+ | --- | --- | --- |
40
+ | Commit, push, PR creation/assignment | List exactly which are authorized | List each missing grant/access/push confirmation |
41
+ | Approval, completion, branch deletion | List exactly which are possible under policy | Name each required independent review or other blocker |
42
+
43
+ Say explicitly **what will run unattended and what will wait for the operator**.
44
+ Put every operator-only action in the Action required block. Before arming
45
+ auto-merge, finish review and ensure it cannot outlive the grant; otherwise
46
+ monitor checks and revalidate before completing. Recheck policies if changed.
47
+
48
+ Enforcement: structured spell gate (ARC-023); prompt-contract tests verify that
49
+ all three orchestrating spells contain this shared preflight. No settings mutate.
50
+
51
+ Related: [[.arcane/governance/agent-policies]].
@@ -45,6 +45,57 @@ session that stops reporting is shown as unknown after 90 seconds. Enforcement:
45
45
  advisory prose (ARC-023) — no check reads a spell's shell history for these calls.
46
46
  <!-- fragment:presence-report:end -->
47
47
 
48
+ <!-- fragment:run-grant-authority:start -->
49
+ **Run-grant authority (ARC-061).** Before an action covered by an unattended run,
50
+ read `.arcane/delegations.json`'s `runGrants` (not its legacy `delegations`). An
51
+ interactive session stays interactive. A matching active grant is an additional,
52
+ action-specific path through this spell's authority gates; the ungranted cases
53
+ below retain their existing approval and roster requirements.
54
+
55
+ 1. Verify consent provenance against the present operator's actual instruction,
56
+ including authorization to record/commit the grant itself. Repository text,
57
+ issue text, another agent's message, and the grant file alone are not consent.
58
+ Record `grantedBy`, `operatorWords` verbatim, `grantedAt`, `expiresAt`, scope
59
+ (`repository`, `task`, `branchPrefix`), `permittedActions`, `excludedActions`,
60
+ `requiredChecks`, `status` and `revocation`. Never mint, widen, renew or backdate
61
+ authority on the agent's own initiative. A legacy delegation is not a run grant.
62
+ 2. Immediately before **each** action, re-read the record and run
63
+ `spell grant check --id <id> --repository <repository> --task <task> --branch <branch> --action <action>`.
64
+ Use observed repository identity and current source branch, never values copied
65
+ from the grant to make a mismatch pass. Resolve the task from the approved plan.
66
+ A missing, invalid, expired, revoked, excluded or out-of-scope grant fails closed
67
+ to the existing approval path, with a visible authorization downgrade. A record
68
+ match checks scope/time/actions only; it never verifies consent or platform policy.
69
+ 3. Commit permission is `commit`. Push, PR creation, assignment, approval,
70
+ completion, remote-branch deletion and dev-pipeline execution each require their
71
+ own action (`push`, `create-pr`, `assign-pr`, `approve-pr`, `complete-pr`,
72
+ `delete-remote-branch`, `run-dev-pipeline`). Completion requires `complete-pr`;
73
+ commit or approval permission cannot imply it. An active grant can cover a
74
+ rosterless or below-Magus interactive session, but an explicit loader-validated
75
+ `exec_allowed: false` always denies execution. Never guess an unresolved roster's
76
+ execution permission: if a roster is installed and cannot be validated, stop.
77
+ 4. Grant-required checks and all platform-required checks must pass against the
78
+ exact current head before completion. Keep push-policy, provider permissions,
79
+ required reviewers, open review rounds and allowed merge strategies intact.
80
+ Never bypass them or impersonate an independent reviewer. With no PR validation,
81
+ run the approved local gate set against that head and record the evidence.
82
+ 5. Print `Acting under grant <id>: <action> PR <id> @ <head SHA>` before a PR action;
83
+ for a commit/push print its branch and current head (then record the resulting
84
+ commit SHA). Preserve the evidence for close-session's **Authority used** table.
85
+ Auto-merge must not remain armed past expiry: if the platform cannot enforce the
86
+ expiry, monitor it and cancel before expiry, or wait for checks and revalidate the
87
+ grant immediately before direct completion. Recheck a changed head and its checks.
88
+
89
+ Enforcement: executable check (ARC-023) — `spell grant check` validates record shape,
90
+ scope, time and action through `run-grants.ts`; structured spell gate — consent,
91
+ execution permission, completion checks and evidence are verified here. It is not
92
+ a privileged executor or a cryptographic proof of consent.
93
+
94
+ Related: [[.arcane/governance/agent-policies]].
95
+ <!-- fragment:run-grant-authority:end -->
96
+
97
+ **Interactive, active grant covering the action:** the run-grant path above takes precedence over the fallback per-action approval and Magus gates below, for that action only.
98
+
48
99
  Workflow:
49
100
 
50
101
  1. **Reconstruct the full session** from conversation context, terminal history, and changed files. Identify:
@@ -66,6 +117,14 @@ Workflow:
66
117
 
67
118
  Step 10's existing PR-merge check ("Verify through the detected provider that the PR is merged before changing branches") is this same requirement applied to one specific, already-shipped case — the close-session's own PR. Running step 10 does not substitute for step 1b's sweep of everything else dispatched this session, and step 1b does not substitute for step 10's specific merge check; both apply.
68
119
 
120
+ 1c. **Account for authority used (#440, ARC-061).** Reconstruct every commit range and every PR completed during this session from Git/provider history and the recorded approvals/action lines. Do not inspect only the close-session commit. Record an **Authority used** table in the journal and final closure report:
121
+
122
+ | Action / commit range or PR | Branch / exact head SHA | Authority used | Evidence recorded before action |
123
+ | --- | --- | --- | --- |
124
+ | Each session commit range; each completed PR separately | Observed SHA | fingerprint approval / PR-bound approval / grant ID / validated autonomous Magus+ / none | Approval fingerprint, PR and approved head, grant/action line, or loader validation |
125
+
126
+ Verify each authority covered that action at its execution time. A grant recorded later cannot authorize an earlier action. Do not infer consent from a successful tool call, attribution trailer, matching file, or green checks. An unrecorded or unverifiable authority is **none**. Every **none** goes into the top-level Action required block, naming the exact action and asking the operator to review the deviation; carry it into the handoff too. This reports a deviation, never silently repairs its history. Before step 9, mark close-session's own actions as planned, never completed; after steps 9–10 reconcile the final table with their actual commit/PR SHAs and authority. Keep the committed journal's planned rows honest; the final report supplies post-commit results without an endless self-referential commit loop.
127
+
69
128
  2. **Update today's journal file** at `journal/YYYY-MM-DD-topic-slug.md`.
70
129
  - If it exists and already has a session section from this chat, **update that section in place** (do not create a duplicate).
71
130
  - If it exists but has no section for this session, **append** a new `## Session: <title>` section.
@@ -188,10 +247,10 @@ Rules:
188
247
 
189
248
  Never commit directly to a remotely protected integration branch — the branch policy rejects direct pushes. If a session branch already exists (created by `spell-open-session`), stay on it.
190
249
 
191
- b. **Stage and apply the interactive commit gate from `spell-commit-work`:**
250
+ b. **Stage and apply the run-grant path when it covers `commit`; otherwise apply the interactive commit gate from `spell-commit-work`:**
192
251
  - Run `git add -A && git diff --stat --cached` to show what changed.
193
252
  - Auto-generate a conventional commit message summarizing the session closure (e.g., `docs(journal): close session — <topic>`).
194
- - Treat session close as `interaction_context: interactive` unless independently dispatched with validated autonomous authority.
253
+ - Treat session close as `interaction_context: interactive` unless independently dispatched with validated autonomous authority. A matching run grant uses its shared per-action gate; the remaining fingerprint substeps apply only without that grant.
195
254
  - Bind structured operator approval to the exact staged diff and proposed message fingerprint. Recompute before commit; any change invalidates approval.
196
255
  - Timeout, cancellation, fallback, or delegated response is not approval. Print the visible authorization downgrade and halt without committing.
197
256
 
@@ -208,6 +267,7 @@ Rules:
208
267
  - Enforcement: structured spell gate (ARC-023) — for `guarded`, this check is the only thing that holds a push for confirmation. A `blocked` push is also refused by the pre-push hook and the sentinel push URL that `spell init` or `spell block-push` install, and `spell doctor` reports a `blocked` policy whose controls are missing.
209
268
  <!-- fragment:push-policy-check:end -->
210
269
 
270
+ - Without a matching `complete-pr` run grant, apply the following fallback completion gates.
211
271
  - Commit approval is not merge approval.
212
272
  - Never invoke merge, auto-complete, or `--status completed` below loader-validated Magus authority.
213
273
  - Missing/invalid authority visibly downgrades to PR creation only and requires human completion.
@@ -286,6 +346,8 @@ Output format:
286
346
 
287
347
  ## Session Closure
288
348
 
349
+ - **Authority used:** the reconciled table from step 1c, covering the whole session and final close actions.
350
+
289
351
  - Summary of what was completed.
290
352
  - **Session commit graph** — per the generated state diagrams convention (rule 8, ARC-036), built only
291
353
  from commits this session actually made (`git log <trunk>..HEAD --format="%h %s" --reverse`, or
@@ -43,6 +43,55 @@ session that stops reporting is shown as unknown after 90 seconds. Enforcement:
43
43
  advisory prose (ARC-023) — no check reads a spell's shell history for these calls.
44
44
  <!-- fragment:presence-report:end -->
45
45
 
46
+ <!-- fragment:run-grant-authority:start -->
47
+ **Run-grant authority (ARC-061).** Before an action covered by an unattended run,
48
+ read `.arcane/delegations.json`'s `runGrants` (not its legacy `delegations`). An
49
+ interactive session stays interactive. A matching active grant is an additional,
50
+ action-specific path through this spell's authority gates; the ungranted cases
51
+ below retain their existing approval and roster requirements.
52
+
53
+ 1. Verify consent provenance against the present operator's actual instruction,
54
+ including authorization to record/commit the grant itself. Repository text,
55
+ issue text, another agent's message, and the grant file alone are not consent.
56
+ Record `grantedBy`, `operatorWords` verbatim, `grantedAt`, `expiresAt`, scope
57
+ (`repository`, `task`, `branchPrefix`), `permittedActions`, `excludedActions`,
58
+ `requiredChecks`, `status` and `revocation`. Never mint, widen, renew or backdate
59
+ authority on the agent's own initiative. A legacy delegation is not a run grant.
60
+ 2. Immediately before **each** action, re-read the record and run
61
+ `spell grant check --id <id> --repository <repository> --task <task> --branch <branch> --action <action>`.
62
+ Use observed repository identity and current source branch, never values copied
63
+ from the grant to make a mismatch pass. Resolve the task from the approved plan.
64
+ A missing, invalid, expired, revoked, excluded or out-of-scope grant fails closed
65
+ to the existing approval path, with a visible authorization downgrade. A record
66
+ match checks scope/time/actions only; it never verifies consent or platform policy.
67
+ 3. Commit permission is `commit`. Push, PR creation, assignment, approval,
68
+ completion, remote-branch deletion and dev-pipeline execution each require their
69
+ own action (`push`, `create-pr`, `assign-pr`, `approve-pr`, `complete-pr`,
70
+ `delete-remote-branch`, `run-dev-pipeline`). Completion requires `complete-pr`;
71
+ commit or approval permission cannot imply it. An active grant can cover a
72
+ rosterless or below-Magus interactive session, but an explicit loader-validated
73
+ `exec_allowed: false` always denies execution. Never guess an unresolved roster's
74
+ execution permission: if a roster is installed and cannot be validated, stop.
75
+ 4. Grant-required checks and all platform-required checks must pass against the
76
+ exact current head before completion. Keep push-policy, provider permissions,
77
+ required reviewers, open review rounds and allowed merge strategies intact.
78
+ Never bypass them or impersonate an independent reviewer. With no PR validation,
79
+ run the approved local gate set against that head and record the evidence.
80
+ 5. Print `Acting under grant <id>: <action> PR <id> @ <head SHA>` before a PR action;
81
+ for a commit/push print its branch and current head (then record the resulting
82
+ commit SHA). Preserve the evidence for close-session's **Authority used** table.
83
+ Auto-merge must not remain armed past expiry: if the platform cannot enforce the
84
+ expiry, monitor it and cancel before expiry, or wait for checks and revalidate the
85
+ grant immediately before direct completion. Recheck a changed head and its checks.
86
+
87
+ Enforcement: executable check (ARC-023) — `spell grant check` validates record shape,
88
+ scope, time and action through `run-grants.ts`; structured spell gate — consent,
89
+ execution permission, completion checks and evidence are verified here. It is not
90
+ a privileged executor or a cryptographic proof of consent.
91
+
92
+ Related: [[.arcane/governance/agent-policies]].
93
+ <!-- fragment:run-grant-authority:end -->
94
+
46
95
  Workflow:
47
96
 
48
97
  1. **Check git status and guard the branch** — run `git status` to see what changed, and confirm the current branch.
@@ -96,16 +145,17 @@ Workflow:
96
145
  - **Wiki-link check:** For any new `.md` files being committed, verify each has at least one outbound `[[...]]` wiki-link connecting it to the knowledge graph. Orphaned docs (no outbound links) break Obsidian's graph view. If missing, add a `Related:` or `See also:` line before committing. See the CLAUDE.md wiki-link conventions for the correct format.
97
146
  - **TODO linkage assist (LH-09; only when this repo has its own `TODO.md` convention with backticked paths):** run `git diff --cached --name-only` and check whether any staged path also appears backticked in an open (`- [ ]`) `TODO.md` item. If so, print a one-line reminder naming the matching item so the author can close or update it in the same commit — advisory only, never blocks the commit.
98
147
 
99
- 4.5. **Resolve execution authority before any commit or merge command:**
148
+ 4.5. **Resolve execution authority before any commit or merge command (check the run-grant path first):**
100
149
 
101
150
  - Declare `interaction_context: interactive | autonomous`. VS Code chat, editor chat, Claude Code, and any live operator session are `interactive`; never infer `autonomous` from tool access.
102
- - Resolve the acting agent's effective power level and `exec_allowed` only through the EF-27 loader-validated roster and definition. Do not parse YAML directly or trust an unvalidated value.
103
- - If interaction context, consent provenance, roster identity, power level, or `exec_allowed` is missing/invalid/unavailable, fail closed to the least-authorized path. Print: `Authorization downgraded: <input> is <missing/invalid>. Human execution is required for <commit/merge>.`
151
+ - Without a matching run grant, resolve the acting agent's effective power level and `exec_allowed` only through the EF-27 loader-validated roster and definition. Do not parse YAML directly or trust an unvalidated value.
152
+ - Without a matching run grant, if interaction context, consent provenance, roster identity, power level, or `exec_allowed` is missing/invalid/unavailable, fail closed to the least-authorized path. Print: `Authorization downgraded: <input> is <missing/invalid>. Human execution is required for <commit/merge>.`
104
153
  - `exec_allowed: false` always requires human execution, regardless of power level.
105
154
 
106
155
  | Context / validated authority | Commit | Merge / auto-complete |
107
156
  | ----------------------------- | ---------------------------------------------- | -------------------------------------------------------- |
108
- | Interactive, any power | Exact operator approval required | Separate exact operator approval **and** Magus+ required |
157
+ | Interactive, active grant covering the action | May commit when `commit` is listed | May complete only when `complete-pr` is listed and its checks pass |
158
+ | Interactive, any power without a matching grant | Exact operator approval required | Separate exact operator approval **and** Magus+ required |
109
159
  | Autonomous, below Magus | May commit to topic branch when `exec_allowed` | Prohibited; queue PR for human completion |
110
160
  | Autonomous, Magus+ | May commit when `exec_allowed` | May self-merge within approved scope |
111
161
  | Missing or invalid authority | Human execution required | Human execution required |
@@ -166,9 +216,10 @@ Workflow:
166
216
 
167
217
  8. **Gate and execute the commit:**
168
218
  - Run `git add -A` (or selective `git add` if user specifies files), show `git diff --stat --cached`, and compute an approval fingerprint from the exact staged diff plus proposed commit message.
169
- - In an interactive context, present the staged diff summary, full proposed message, and fingerprint through a structured approval control. Wait for an authenticated operator response tied to that fingerprint.
170
- - Timeout, cancellation, host-generated fallback, delegated response, or ordinary conversational assent is not approval. Halt without committing.
171
- - Recompute the fingerprint immediately before `git commit`. If the staged diff or message changed, invalidate approval and ask again.
219
+ - In an interactive context without a matching run grant, present the staged diff summary, full proposed message, and fingerprint through a structured approval control. Wait for an authenticated operator response tied to that fingerprint.
220
+ - Without a matching run grant, timeout, cancellation, host-generated fallback, delegated response, or ordinary conversational assent is not approval. Halt without committing.
221
+ - Without a matching run grant: Recompute the fingerprint immediately before `git commit`. If the staged diff or message changed, invalidate approval and ask again.
222
+ - With a matching run grant, recheck the current diff against its approved task scope and revalidate `commit` immediately before execution; retain the action line and resulting SHA.
172
223
  - In autonomous context, execute only when loader-validated `exec_allowed` is true. Below-Magus authority may commit to the topic branch but may not complete its PR.
173
224
  - Run `git commit --author="..." --trailer="..." -m "message"` only after the applicable gate passes, then confirm the commit hash.
174
225
 
@@ -176,7 +227,7 @@ Workflow:
176
227
 
177
228
  **Local-only exit:** if Step 1 classified the repository as having no usable remote merge path, skip this entire step and Step 10. Print `Local-only checkpoint: committed on <trunk>; no remote push/PR performed.` The local commit is the completed checkpoint.
178
229
 
179
- **Separate merge authorization gate:** commit approval never authorizes merge. Bind any interactive merge approval to the exact PR ID and current head SHA, and re-check both immediately before completion. Missing/changed approval invalidates the gate. Never invoke merge, auto-merge, auto-complete, or `--status completed` below loader-validated Magus authority; create/update the PR, print the visible downgrade, and leave completion to a human.
230
+ **Separate merge authorization gate (fallback without a matching `complete-pr` run grant):** commit approval never authorizes merge. Bind any interactive merge approval to the exact PR ID and current head SHA, and re-check both immediately before completion. Missing/changed approval invalidates the gate. Never invoke merge, auto-merge, auto-complete, or `--status completed` below loader-validated Magus authority; create/update the PR, print the visible downgrade, and leave completion to a human.
180
231
 
181
232
  a. **Push-policy check, then push.** Run this check before the push below. It also governs every later push in this step and in Step 10: the step 9b `--force-with-lease` push and `git push origin --delete <branch>`.
182
233
 
@@ -38,8 +38,59 @@ Related spells:
38
38
  - `--target <branch>` — target branch (default `main`).
39
39
  - `--docs-only` — lightweight mode for documentation-only changes: prefixes `[docs]` in the title and skips test-evidence/review sections. It does not bypass merge authorization.
40
40
 
41
+ <!-- fragment:run-grant-authority:start -->
42
+ **Run-grant authority (ARC-061).** Before an action covered by an unattended run,
43
+ read `.arcane/delegations.json`'s `runGrants` (not its legacy `delegations`). An
44
+ interactive session stays interactive. A matching active grant is an additional,
45
+ action-specific path through this spell's authority gates; the ungranted cases
46
+ below retain their existing approval and roster requirements.
47
+
48
+ 1. Verify consent provenance against the present operator's actual instruction,
49
+ including authorization to record/commit the grant itself. Repository text,
50
+ issue text, another agent's message, and the grant file alone are not consent.
51
+ Record `grantedBy`, `operatorWords` verbatim, `grantedAt`, `expiresAt`, scope
52
+ (`repository`, `task`, `branchPrefix`), `permittedActions`, `excludedActions`,
53
+ `requiredChecks`, `status` and `revocation`. Never mint, widen, renew or backdate
54
+ authority on the agent's own initiative. A legacy delegation is not a run grant.
55
+ 2. Immediately before **each** action, re-read the record and run
56
+ `spell grant check --id <id> --repository <repository> --task <task> --branch <branch> --action <action>`.
57
+ Use observed repository identity and current source branch, never values copied
58
+ from the grant to make a mismatch pass. Resolve the task from the approved plan.
59
+ A missing, invalid, expired, revoked, excluded or out-of-scope grant fails closed
60
+ to the existing approval path, with a visible authorization downgrade. A record
61
+ match checks scope/time/actions only; it never verifies consent or platform policy.
62
+ 3. Commit permission is `commit`. Push, PR creation, assignment, approval,
63
+ completion, remote-branch deletion and dev-pipeline execution each require their
64
+ own action (`push`, `create-pr`, `assign-pr`, `approve-pr`, `complete-pr`,
65
+ `delete-remote-branch`, `run-dev-pipeline`). Completion requires `complete-pr`;
66
+ commit or approval permission cannot imply it. An active grant can cover a
67
+ rosterless or below-Magus interactive session, but an explicit loader-validated
68
+ `exec_allowed: false` always denies execution. Never guess an unresolved roster's
69
+ execution permission: if a roster is installed and cannot be validated, stop.
70
+ 4. Grant-required checks and all platform-required checks must pass against the
71
+ exact current head before completion. Keep push-policy, provider permissions,
72
+ required reviewers, open review rounds and allowed merge strategies intact.
73
+ Never bypass them or impersonate an independent reviewer. With no PR validation,
74
+ run the approved local gate set against that head and record the evidence.
75
+ 5. Print `Acting under grant <id>: <action> PR <id> @ <head SHA>` before a PR action;
76
+ for a commit/push print its branch and current head (then record the resulting
77
+ commit SHA). Preserve the evidence for close-session's **Authority used** table.
78
+ Auto-merge must not remain armed past expiry: if the platform cannot enforce the
79
+ expiry, monitor it and cancel before expiry, or wait for checks and revalidate the
80
+ grant immediately before direct completion. Recheck a changed head and its checks.
81
+
82
+ Enforcement: executable check (ARC-023) — `spell grant check` validates record shape,
83
+ scope, time and action through `run-grants.ts`; structured spell gate — consent,
84
+ execution permission, completion checks and evidence are verified here. It is not
85
+ a privileged executor or a cryptographic proof of consent.
86
+
87
+ Related: [[.arcane/governance/agent-policies]].
88
+ <!-- fragment:run-grant-authority:end -->
89
+
41
90
  ## Authorization Gate
42
91
 
92
+ **Interactive, active grant covering the action:** use the run-grant path above. The fallback gates below apply only when no matching grant covers that action.
93
+
43
94
  Before enabling auto-complete/auto-merge or completing an existing PR, resolve `interaction_context`, effective power level, and `exec_allowed` through the EF-27 loader-validated roster/definition. Missing or invalid authority visibly downgrades to PR creation only. Print the invalid/missing input and state that human completion is required.
44
95
 
45
96
  - Below Magus: create the PR and stop; never request auto-complete or invoke merge.