arcane-cli 1.17.3 → 1.19.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 +72 -0
- package/dist/assets/.arcane/governance/threat-model.md +43 -0
- package/dist/assets/.arcane/spells/_fragments/needs-you.md +1 -0
- package/dist/assets/.arcane/spells/_fragments/presence-report.md +16 -0
- package/dist/assets/.arcane/spells/spell-address-review.md +1 -0
- package/dist/assets/.arcane/spells/spell-adopt-docs.md +1 -0
- package/dist/assets/.arcane/spells/spell-app-store-accounts.md +1 -0
- package/dist/assets/.arcane/spells/spell-architect.md +1 -0
- package/dist/assets/.arcane/spells/spell-close-session.md +20 -0
- package/dist/assets/.arcane/spells/spell-commit-work.md +20 -0
- package/dist/assets/.arcane/spells/spell-create-pull-request.md +1 -0
- package/dist/assets/.arcane/spells/spell-eas-store-deploy.md +1 -0
- package/dist/assets/.arcane/spells/spell-full-cycle.md +1 -0
- package/dist/assets/.arcane/spells/spell-implement.md +19 -0
- package/dist/assets/.arcane/spells/spell-make-discoverable.md +1 -0
- package/dist/assets/.arcane/spells/spell-open-session.md +21 -0
- package/dist/assets/.arcane/spells/spell-parallel-workers.md +1 -0
- package/dist/assets/.arcane/spells/spell-plan.md +1 -0
- package/dist/assets/.arcane/spells/spell-review-batch.md +1 -0
- package/dist/assets/.arcane/spells/spell-review.md +1 -0
- package/dist/assets/.arcane/spells/spell-scope.md +1 -0
- package/dist/assets/.arcane/spells/spell-ship.md +1 -0
- package/dist/assets/.arcane/spells/spell-sync-pull-request.md +1 -0
- package/dist/assets/schemas/presence.schema.json +586 -0
- package/dist/index.js +2979 -1239
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -273,6 +273,78 @@ The document is derived, never authoritative, and deterministic: two runs differ
|
|
|
273
273
|
|
|
274
274
|
The shape is the JSON Schema at [`src/assets/schemas/state.schema.json`](src/assets/schemas/state.schema.json) (`$id` `https://arcaneai.net/schemas/state/v1`), shipped in the package as `dist/assets/schemas/state.schema.json`. Schema `1.0.0` is additive-only: a field is never removed or retyped; a breaking change is a new major version and a new decision record ([ARC-044](DECISIONS.md#arc-044--client-architecture-files-first-state-contract-and-a-local-presence-channel)).
|
|
275
275
|
|
|
276
|
+
### Presence
|
|
277
|
+
|
|
278
|
+
`spell presence` is an optional, local presence channel: which session is working on what, right now, and whether it is waiting for you ([ARC-060](DECISIONS.md#arc-060--the-presence-channel-one-package-behind-spell-presence-a-loopback-contract-checkout-keyed-sessions-and-a-prompt-driven-reporting-convention); working name `arcane-mcp`). You start the service; nothing listens until you do. It binds `127.0.0.1` only, keeps sessions in memory only (stale after 90 s without a report, dropped after 24 h), writes nothing but its token and `server.json` under `~/.arcane/presence/`, and never writes a repository file. It is observation only: everything it holds is reconstructable from `spell state --json`, and no route, tool or event steers a session. Spells report through it with one fragment in `spell-open-session`, `spell-close-session`, `spell-commit-work` and `spell-implement`, and every spell's "Needs you" block reports `waiting` with its lines; with no service running they behave exactly as before. `spell-open-session` also lists the sessions reporting from the repository's other checkouts, and `spell doctor` has a "Presence service" row (`--fix` removes a `server.json` left by a service that is gone).
|
|
279
|
+
|
|
280
|
+
| Command | What it does |
|
|
281
|
+
| --- | --- |
|
|
282
|
+
| `spell presence serve [--port <n>] [--rotate]` | Runs the service in the foreground on `127.0.0.1` (port 27226, or `ARCANE_PRESENCE_PORT`) until Ctrl+C. `--rotate` replaces the token |
|
|
283
|
+
| `spell presence status` | Exit 0 when the service answers this machine's token, 1 otherwise |
|
|
284
|
+
| `spell presence sessions [--json]` | The sessions the service holds, as a table or as the `GET /v0/sessions` document; exit 1 when no channel answers |
|
|
285
|
+
| `spell presence stop` | Stops the recorded service; exit 0 either way |
|
|
286
|
+
| `spell presence report --status <s> [--task ...] [--needs-you ...]` | Reports this checkout's session; silent and exit 0 with no service, never blocks |
|
|
287
|
+
| `spell presence end` | Ends this checkout's session |
|
|
288
|
+
| `spell presence mcp` | The same channel as an MCP server over stdio: tools `presence_report` and `presence_end`, resources `arcane://presence/sessions` and `arcane://presence/capabilities`, with update notifications on the sessions resource (`subscriptions/listen` on MCP 2026-07-28, `resources/subscribe` on earlier revisions) |
|
|
289
|
+
|
|
290
|
+
**The token** is `~/.arcane/presence/token` (`0600` in a `0700` directory; restricted to your account on Windows). A subscriber that cannot read the file, such as a dashboard's server, gets it from the `ARCANE_PRESENCE_TOKEN` environment variable instead. No command takes a token as an argument. **Remote access** is only ever a tunnel you put in front of the loopback port, with the token still required. The contract is HTTP plus server-sent events under `/v0/`; its JSON Schema is [`src/assets/schemas/presence.schema.json`](src/assets/schemas/presence.schema.json) (`$id` `https://arcaneai.net/schemas/presence/v0`), shipped as `dist/assets/schemas/presence.schema.json`.
|
|
291
|
+
|
|
292
|
+
**Registering the MCP server** is yours; Arcane writes no client's configuration. The server accepts a `cwd` argument on both tools, because a client may launch it from any directory.
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
claude mcp add --transport stdio --scope user arcane-presence -- spell presence mcp # Claude Code
|
|
296
|
+
codex mcp add arcane-presence -- spell presence mcp # Codex CLI
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
For GitHub Copilot in VS Code, add it to `.vscode/mcp.json` (or your user `mcp.json`):
|
|
300
|
+
|
|
301
|
+
```json
|
|
302
|
+
{ "servers": { "arcane-presence": { "type": "stdio", "command": "spell", "args": ["presence", "mcp"] } } }
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
**Running it as a user service** is optional. Use absolute paths from `which node` and `which spell` (`where` on Windows), because services start without your shell's `PATH`.
|
|
306
|
+
|
|
307
|
+
<details>
|
|
308
|
+
<summary>macOS (launchd), Linux (systemd --user), Windows (Task Scheduler)</summary>
|
|
309
|
+
|
|
310
|
+
macOS: save as `~/Library/LaunchAgents/net.arcaneai.presence.plist`, then `launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/net.arcaneai.presence.plist`.
|
|
311
|
+
|
|
312
|
+
```xml
|
|
313
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
314
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
315
|
+
<plist version="1.0">
|
|
316
|
+
<dict>
|
|
317
|
+
<key>Label</key><string>net.arcaneai.presence</string>
|
|
318
|
+
<key>ProgramArguments</key>
|
|
319
|
+
<array><string>/absolute/path/to/node</string><string>/absolute/path/to/spell</string><string>presence</string><string>serve</string></array>
|
|
320
|
+
<key>RunAtLoad</key><true/>
|
|
321
|
+
<key>KeepAlive</key><true/>
|
|
322
|
+
</dict>
|
|
323
|
+
</plist>
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
Linux: save as `~/.config/systemd/user/arcane-presence.service`, then `systemctl --user daemon-reload` and `systemctl --user enable --now arcane-presence.service`.
|
|
327
|
+
|
|
328
|
+
```ini
|
|
329
|
+
[Unit]
|
|
330
|
+
Description=Arcane presence service (loopback only)
|
|
331
|
+
|
|
332
|
+
[Service]
|
|
333
|
+
ExecStart=/absolute/path/to/node /absolute/path/to/spell presence serve
|
|
334
|
+
Restart=on-failure
|
|
335
|
+
|
|
336
|
+
[Install]
|
|
337
|
+
WantedBy=default.target
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
Windows: a task that starts at logon. If Windows answers "Access is denied", create the same task from an elevated prompt or in Task Scheduler's window.
|
|
341
|
+
|
|
342
|
+
```bat
|
|
343
|
+
schtasks /create /sc onlogon /tn "Arcane presence" /tr "\"C:\path\to\spell.cmd\" presence serve"
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
</details>
|
|
347
|
+
|
|
276
348
|
### Profiles
|
|
277
349
|
|
|
278
350
|
Install everything, or just the slice you want:
|
|
@@ -72,6 +72,49 @@ See also: [Hardening Checklist](hardening-checklist.md), [Authentication Strateg
|
|
|
72
72
|
|
|
73
73
|
---
|
|
74
74
|
|
|
75
|
+
## Local Presence Service (`spell presence`)
|
|
76
|
+
|
|
77
|
+
> **Status:** every row is **Planned** until the operator verifies it against the installed build on each machine that runs the service, and records the result in the security audit log. Decision record: ARC-060 (the presence channel) in the Arcane framework repository.
|
|
78
|
+
|
|
79
|
+
`spell presence serve` is an optional, operator-started foreground process that AI sessions report to (agent, task, repository, status and "needs you" lines) and that dashboards read. Nothing listens until the operator starts it. It adds one listening socket and one secret to the machine. It is **observation only by contract** (capability descriptor `{ observe: true, actions: [] }`) and **never authoritative**: everything it holds is reconstructable from `spell state --json` and the repository's files.
|
|
80
|
+
|
|
81
|
+
| Asset | Value | Location |
|
|
82
|
+
|-------|-------|----------|
|
|
83
|
+
| Presence state | Each session's agent, task, message, needs-you lines, repository name and remote, branch and checkout path. Business-private: it can name ventures, customers and machine paths | Process memory only; gone on restart, dropped after 24 h of silence |
|
|
84
|
+
| Presence token | Bearer capability for every route: read every live session, post or end any session | `~/.arcane/presence/token` (file `0600` in a `0700` directory; on Windows restricted to the current account) or the `ARCANE_PRESENCE_TOKEN` environment variable for a subscriber |
|
|
85
|
+
| `server.json` | URL, process id, port, start time and version of the running service. Not a secret | `~/.arcane/presence/server.json`, removed on a clean exit |
|
|
86
|
+
|
|
87
|
+
**Threat actors added:**
|
|
88
|
+
|
|
89
|
+
- **A local process without the token:** another account on the machine, or a web page in a browser reaching the loopback port, including through DNS rebinding.
|
|
90
|
+
- **A process running as the operator's own account:** a compromised AI session, or any agent runtime that runs under that account, can read the token file like the operator can. It can post forged presence and read every live session.
|
|
91
|
+
- **A tunnel or VPN peer**, only when the operator puts a tunnel in front of the loopback port.
|
|
92
|
+
|
|
93
|
+
| Surface | Status | Mitigation (ARC-060 decision) | How to verify |
|
|
94
|
+
|---------|--------|-------------------------------|---------------|
|
|
95
|
+
| Listening socket | **Planned** | Binds `127.0.0.1` only; no host or bind option exists (decision 2) | `lsof -nP -iTCP:<port> -sTCP:LISTEN` (macOS) or `ss -ltnp 'sport = :<port>'` (Linux) shows `127.0.0.1` only; a connection from another host to the machine's address on that port is refused; `spell presence serve --help` lists no host or bind option |
|
|
96
|
+
| Authentication | **Planned** | Every `/v0/` route requires `Authorization: Bearer <token>`; the only unauthenticated answer is `401` with an empty body; constant-time comparison (decisions 3, 6) | `curl -si http://127.0.0.1:<port>/v0/health` without the token and with a wrong one both answer `401` with no body; with the token, `200` |
|
|
97
|
+
| Token storage | **Planned** | 32 random bytes written on first `serve`, `0600` in `0700`; the write is refused when the restriction fails; `--rotate` replaces it; readers take `ARCANE_PRESENCE_TOKEN` first (decision 6). On Windows inherited entries are removed and the current account granted; SYSTEM and the Administrators group can keep explicit entries | `stat` on `~/.arcane/presence` and its `token` shows `drwx------` and `-rw-------`; on Windows `icacls` on the token shows no inherited entry and no principal other than the current account, SYSTEM and Administrators |
|
|
98
|
+
| Token exposure | **Planned** | No command takes a token as an argument; `server.json` holds none; no log line prints one (decision 6) | `spell presence --help` and every subcommand's help list no token option; a search of a `serve` run's output for the token value finds nothing |
|
|
99
|
+
| Browser and DNS-rebinding reach | **Planned** | No CORS headers, so a cross-origin page cannot read an answer, and the bearer header forces a preflight that is refused. There is no `Host` check (decision 3), so the token is the only control here | A `fetch` to `http://127.0.0.1:<port>/v0/sessions` from any web page fails; a request with a foreign `Host` header and no token answers `401` |
|
|
100
|
+
| Repository and filesystem writes | **Planned** | Writes only `token` and `server.json` under `~/.arcane/presence/`; never a repository file, never a session journal (decisions 2, 7) | A filesystem watch across a `serve` run with reports from two checkouts shows writes under `~/.arcane/presence/` only; `git status` is clean in both checkouts afterwards |
|
|
101
|
+
| State persistence | **Planned** | Memory only; a session silent for 90 s is stale, for 24 h expired and dropped; a restart starts empty (decision 7) | Restart `serve`: `GET /v0/sessions` answers an empty list; a session silent for 90 s shows `stale: true` |
|
|
102
|
+
| Forged or poisoned presence | **Accepted risk** | Any token holder can post or end any session. Bounded: presence is never authoritative and steers nothing (`actions: []`, decision 8); a forged report misleads a dashboard and changes no file, branch or decision | `tools/list` on `spell presence mcp` answers only `presence_report` and `presence_end`; the HTTP surface has six routes, none of which acts |
|
|
103
|
+
| Disclosure to token holders | **Accepted risk** | Every token holder can read every session's task, message and path. A process of the operator's account can already read those repositories, so this adds no new data to that account; it is why the token is never shared beyond it | Review which agent runtimes run under the operator's account and what they may read |
|
|
104
|
+
| Request limits | **Planned** | 64 KiB bodies, 256-character lines, at most 20 needs-you lines and 32 aliases (more is refused), 256 sessions, 32 subscribers, a subscriber that stops reading closed past a 1 MiB backlog, connection and header time limits checked every second (decision 3) | A 65 KiB body and a 21-line needs-you list are each refused; the service keeps answering |
|
|
105
|
+
| Execution and reads | **Planned** | The service runs no process and reads nothing but its own store; it makes no outbound request (decisions 9, 10) | Code review of the release; no outbound connection from the `serve` process during a run (`lsof -p <pid> -i` shows the listener only) |
|
|
106
|
+
| Logging | **Planned** | The service logs an event name, a session reference and a status only; never a task, message, needs-you line, path or token (decision 9) | `serve`'s output across a run contains no task, message, path or token |
|
|
107
|
+
| Remote access | **Planned** | Nothing listens beyond loopback; the only remote path is a tunnel or VPN the operator places in front of the loopback port, with the token still required (decision 6) | Before exposing the port through a tunnel, review which devices the tunnel admits and record them |
|
|
108
|
+
| Git hooks | **Planned** | The reporter is invoked by spell prompts, never by a git hook; `spell presence` is never installed into `.husky/` or `.arcane/hooks/` (decision 10) | A search for `presence` in `.husky/` and `.arcane/hooks/` of each repository after the update that ships it finds nothing |
|
|
109
|
+
| Data leaving the machine | **Planned** | No outbound request; a pushed projection would be a later decision record and strips `repository.root` and `checkout.path` first (decision 9) | Same as the execution row |
|
|
110
|
+
|
|
111
|
+
Two further surfaces, found while designing the service, with their mitigations:
|
|
112
|
+
|
|
113
|
+
- **A port taken by another process after a crash.** If the service dies without removing `server.json`, another local process could bind the port and receive the token from the next reporter. The reporter treats a `server.json` whose process id is not alive as no channel, and `serve` on a port in use fails without touching the token; a reused process id together with a taken port is the residual.
|
|
114
|
+
- **A rewritten `server.json`.** A process of the operator's account can edit it. The client takes only the port from it and always connects to `127.0.0.1`, so the token is never sent to another host; a recorded process id that belongs to another account counts as no service, so the token is not sent to whatever holds the port.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
75
118
|
## Collaborator Access Policy
|
|
76
119
|
|
|
77
120
|
This policy defines which collaborators can access which project data. Enforce boundaries at the source-control/project level and document scope explicitly to prevent drift.
|
|
@@ -11,4 +11,5 @@
|
|
|
11
11
|
- **Never only among optional steps.** An action required for correctness is never listed only under next steps, suggestions, `Carry Forward` or `What's Next?`. It may be repeated there, but it always appears in this block.
|
|
12
12
|
- **Omit it when empty.** When nothing needs the operator, leave the block out entirely: no heading and no "None" line.
|
|
13
13
|
- **Every final report.** The block belongs in whatever report ends the run, including a report written when the spell stops early.
|
|
14
|
+
- **Report it to the presence channel.** When the block is not empty, also run `spell presence report --status waiting --needs-you "<line 1>" --needs-you "<line 2>"`, one flag per line of the block; with no presence channel configured on this machine the command prints nothing and exits 0, so the block itself and the rest of the run are unchanged.
|
|
14
15
|
- Enforcement: explicitly advisory prose (ARC-023) — no check reads a spell's actual output for this block; it holds by these instructions alone.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
**Presence report (ARC-044 decision 3, ARC-060).** When a presence channel is configured on this
|
|
2
|
+
machine, report through it; when none is, this spell behaves exactly as it does without this
|
|
3
|
+
paragraph. Configured means `spell presence status` exits 0: the service is running and the token
|
|
4
|
+
in the user store opens it. Report with the CLI only; never pass a token on the command line, and
|
|
5
|
+
never write a repository file to report.
|
|
6
|
+
|
|
7
|
+
- At the start of this spell: `spell presence report --spell <spell-id> --status working --task "<the task in one line>"`.
|
|
8
|
+
- When this spell's output carries a `## ⚠ Needs you` block: `spell presence report --status waiting --needs-you "<line 1>" --needs-you "<line 2>"`, one flag per line; the block itself is unchanged.
|
|
9
|
+
- At a checkpoint worth showing (a commit made, a story passed): `spell presence report --status working --task "<what is now happening>"`.
|
|
10
|
+
- When the session closes: `spell presence end`.
|
|
11
|
+
|
|
12
|
+
The command is silent and exits 0 when no channel is configured, prints one line to stderr and
|
|
13
|
+
still exits 0 when the channel refuses a report, and never blocks a spell. The service keeps
|
|
14
|
+
presence in memory only, reconstructable from `spell state --json` and never authoritative; a
|
|
15
|
+
session that stops reporting is shown as unknown after 90 seconds. Enforcement: explicitly
|
|
16
|
+
advisory prose (ARC-023) — no check reads a spell's shell history for these calls.
|
|
@@ -130,6 +130,7 @@ Resolve threads via the provider:
|
|
|
130
130
|
- **Never only among optional steps.** An action required for correctness is never listed only under next steps, suggestions, `Carry Forward` or `What's Next?`. It may be repeated there, but it always appears in this block.
|
|
131
131
|
- **Omit it when empty.** When nothing needs the operator, leave the block out entirely: no heading and no "None" line.
|
|
132
132
|
- **Every final report.** The block belongs in whatever report ends the run, including a report written when the spell stops early.
|
|
133
|
+
- **Report it to the presence channel.** When the block is not empty, also run `spell presence report --status waiting --needs-you "<line 1>" --needs-you "<line 2>"`, one flag per line of the block; with no presence channel configured on this machine the command prints nothing and exits 0, so the block itself and the rest of the run are unchanged.
|
|
133
134
|
- Enforcement: explicitly advisory prose (ARC-023) — no check reads a spell's actual output for this block; it holds by these instructions alone.
|
|
134
135
|
<!-- fragment:needs-you:end -->
|
|
135
136
|
|
|
@@ -149,6 +149,7 @@ Hard rules for this phase:
|
|
|
149
149
|
- **Never only among optional steps.** An action required for correctness is never listed only under next steps, suggestions, `Carry Forward` or `What's Next?`. It may be repeated there, but it always appears in this block.
|
|
150
150
|
- **Omit it when empty.** When nothing needs the operator, leave the block out entirely: no heading and no "None" line.
|
|
151
151
|
- **Every final report.** The block belongs in whatever report ends the run, including a report written when the spell stops early.
|
|
152
|
+
- **Report it to the presence channel.** When the block is not empty, also run `spell presence report --status waiting --needs-you "<line 1>" --needs-you "<line 2>"`, one flag per line of the block; with no presence channel configured on this machine the command prints nothing and exits 0, so the block itself and the rest of the run are unchanged.
|
|
152
153
|
- Enforcement: explicitly advisory prose (ARC-023) — no check reads a spell's actual output for this block; it holds by these instructions alone.
|
|
153
154
|
<!-- fragment:needs-you:end -->
|
|
154
155
|
|
|
@@ -401,6 +401,7 @@ questionnaire, uploading documents, paying a fee, phoning Apple — are required
|
|
|
401
401
|
- **Never only among optional steps.** An action required for correctness is never listed only under next steps, suggestions, `Carry Forward` or `What's Next?`. It may be repeated there, but it always appears in this block.
|
|
402
402
|
- **Omit it when empty.** When nothing needs the operator, leave the block out entirely: no heading and no "None" line.
|
|
403
403
|
- **Every final report.** The block belongs in whatever report ends the run, including a report written when the spell stops early.
|
|
404
|
+
- **Report it to the presence channel.** When the block is not empty, also run `spell presence report --status waiting --needs-you "<line 1>" --needs-you "<line 2>"`, one flag per line of the block; with no presence channel configured on this machine the command prints nothing and exits 0, so the block itself and the rest of the run are unchanged.
|
|
404
405
|
- Enforcement: explicitly advisory prose (ARC-023) — no check reads a spell's actual output for this block; it holds by these instructions alone.
|
|
405
406
|
<!-- fragment:needs-you:end -->
|
|
406
407
|
|
|
@@ -125,6 +125,7 @@ Workflow:
|
|
|
125
125
|
- **Never only among optional steps.** An action required for correctness is never listed only under next steps, suggestions, `Carry Forward` or `What's Next?`. It may be repeated there, but it always appears in this block.
|
|
126
126
|
- **Omit it when empty.** When nothing needs the operator, leave the block out entirely: no heading and no "None" line.
|
|
127
127
|
- **Every final report.** The block belongs in whatever report ends the run, including a report written when the spell stops early.
|
|
128
|
+
- **Report it to the presence channel.** When the block is not empty, also run `spell presence report --status waiting --needs-you "<line 1>" --needs-you "<line 2>"`, one flag per line of the block; with no presence channel configured on this machine the command prints nothing and exits 0, so the block itself and the rest of the run are unchanged.
|
|
128
129
|
- Enforcement: explicitly advisory prose (ARC-023) — no check reads a spell's actual output for this block; it holds by these instructions alone.
|
|
129
130
|
<!-- fragment:needs-you:end -->
|
|
130
131
|
|
|
@@ -26,6 +26,25 @@ Use these files first:
|
|
|
26
26
|
- Most recent journal file(s) in [journal/](../../journal/)
|
|
27
27
|
- Any files changed during this session
|
|
28
28
|
|
|
29
|
+
<!-- fragment:presence-report:start -->
|
|
30
|
+
**Presence report (ARC-044 decision 3, ARC-060).** When a presence channel is configured on this
|
|
31
|
+
machine, report through it; when none is, this spell behaves exactly as it does without this
|
|
32
|
+
paragraph. Configured means `spell presence status` exits 0: the service is running and the token
|
|
33
|
+
in the user store opens it. Report with the CLI only; never pass a token on the command line, and
|
|
34
|
+
never write a repository file to report.
|
|
35
|
+
|
|
36
|
+
- At the start of this spell: `spell presence report --spell <spell-id> --status working --task "<the task in one line>"`.
|
|
37
|
+
- When this spell's output carries a `## ⚠ Needs you` block: `spell presence report --status waiting --needs-you "<line 1>" --needs-you "<line 2>"`, one flag per line; the block itself is unchanged.
|
|
38
|
+
- At a checkpoint worth showing (a commit made, a story passed): `spell presence report --status working --task "<what is now happening>"`.
|
|
39
|
+
- When the session closes: `spell presence end`.
|
|
40
|
+
|
|
41
|
+
The command is silent and exits 0 when no channel is configured, prints one line to stderr and
|
|
42
|
+
still exits 0 when the channel refuses a report, and never blocks a spell. The service keeps
|
|
43
|
+
presence in memory only, reconstructable from `spell state --json` and never authoritative; a
|
|
44
|
+
session that stops reporting is shown as unknown after 90 seconds. Enforcement: explicitly
|
|
45
|
+
advisory prose (ARC-023) — no check reads a spell's shell history for these calls.
|
|
46
|
+
<!-- fragment:presence-report:end -->
|
|
47
|
+
|
|
29
48
|
Workflow:
|
|
30
49
|
|
|
31
50
|
1. **Reconstruct the full session** from conversation context, terminal history, and changed files. Identify:
|
|
@@ -249,6 +268,7 @@ Output format:
|
|
|
249
268
|
- **Never only among optional steps.** An action required for correctness is never listed only under next steps, suggestions, `Carry Forward` or `What's Next?`. It may be repeated there, but it always appears in this block.
|
|
250
269
|
- **Omit it when empty.** When nothing needs the operator, leave the block out entirely: no heading and no "None" line.
|
|
251
270
|
- **Every final report.** The block belongs in whatever report ends the run, including a report written when the spell stops early.
|
|
271
|
+
- **Report it to the presence channel.** When the block is not empty, also run `spell presence report --status waiting --needs-you "<line 1>" --needs-you "<line 2>"`, one flag per line of the block; with no presence channel configured on this machine the command prints nothing and exits 0, so the block itself and the rest of the run are unchanged.
|
|
252
272
|
- Enforcement: explicitly advisory prose (ARC-023) — no check reads a spell's actual output for this block; it holds by these instructions alone.
|
|
253
273
|
<!-- fragment:needs-you:end -->
|
|
254
274
|
|
|
@@ -24,6 +24,25 @@ Use these files first:
|
|
|
24
24
|
- [governance/git-conventions.md](../../.arcane/governance/git-conventions.md) — Conventional Commits reference and agent attribution model
|
|
25
25
|
- [DECISIONS.md](../../DECISIONS.md) — for ADR context if relevant
|
|
26
26
|
|
|
27
|
+
<!-- fragment:presence-report:start -->
|
|
28
|
+
**Presence report (ARC-044 decision 3, ARC-060).** When a presence channel is configured on this
|
|
29
|
+
machine, report through it; when none is, this spell behaves exactly as it does without this
|
|
30
|
+
paragraph. Configured means `spell presence status` exits 0: the service is running and the token
|
|
31
|
+
in the user store opens it. Report with the CLI only; never pass a token on the command line, and
|
|
32
|
+
never write a repository file to report.
|
|
33
|
+
|
|
34
|
+
- At the start of this spell: `spell presence report --spell <spell-id> --status working --task "<the task in one line>"`.
|
|
35
|
+
- When this spell's output carries a `## ⚠ Needs you` block: `spell presence report --status waiting --needs-you "<line 1>" --needs-you "<line 2>"`, one flag per line; the block itself is unchanged.
|
|
36
|
+
- At a checkpoint worth showing (a commit made, a story passed): `spell presence report --status working --task "<what is now happening>"`.
|
|
37
|
+
- When the session closes: `spell presence end`.
|
|
38
|
+
|
|
39
|
+
The command is silent and exits 0 when no channel is configured, prints one line to stderr and
|
|
40
|
+
still exits 0 when the channel refuses a report, and never blocks a spell. The service keeps
|
|
41
|
+
presence in memory only, reconstructable from `spell state --json` and never authoritative; a
|
|
42
|
+
session that stops reporting is shown as unknown after 90 seconds. Enforcement: explicitly
|
|
43
|
+
advisory prose (ARC-023) — no check reads a spell's shell history for these calls.
|
|
44
|
+
<!-- fragment:presence-report:end -->
|
|
45
|
+
|
|
27
46
|
Workflow:
|
|
28
47
|
|
|
29
48
|
1. **Check git status and guard the branch** — run `git status` to see what changed, and confirm the current branch.
|
|
@@ -278,6 +297,7 @@ Output format after execution:
|
|
|
278
297
|
- **Never only among optional steps.** An action required for correctness is never listed only under next steps, suggestions, `Carry Forward` or `What's Next?`. It may be repeated there, but it always appears in this block.
|
|
279
298
|
- **Omit it when empty.** When nothing needs the operator, leave the block out entirely: no heading and no "None" line.
|
|
280
299
|
- **Every final report.** The block belongs in whatever report ends the run, including a report written when the spell stops early.
|
|
300
|
+
- **Report it to the presence channel.** When the block is not empty, also run `spell presence report --status waiting --needs-you "<line 1>" --needs-you "<line 2>"`, one flag per line of the block; with no presence channel configured on this machine the command prints nothing and exits 0, so the block itself and the rest of the run are unchanged.
|
|
281
301
|
- Enforcement: explicitly advisory prose (ARC-023) — no check reads a spell's actual output for this block; it holds by these instructions alone.
|
|
282
302
|
<!-- fragment:needs-you:end -->
|
|
283
303
|
|
|
@@ -238,6 +238,7 @@ so they need no edit.
|
|
|
238
238
|
- **Never only among optional steps.** An action required for correctness is never listed only under next steps, suggestions, `Carry Forward` or `What's Next?`. It may be repeated there, but it always appears in this block.
|
|
239
239
|
- **Omit it when empty.** When nothing needs the operator, leave the block out entirely: no heading and no "None" line.
|
|
240
240
|
- **Every final report.** The block belongs in whatever report ends the run, including a report written when the spell stops early.
|
|
241
|
+
- **Report it to the presence channel.** When the block is not empty, also run `spell presence report --status waiting --needs-you "<line 1>" --needs-you "<line 2>"`, one flag per line of the block; with no presence channel configured on this machine the command prints nothing and exits 0, so the block itself and the rest of the run are unchanged.
|
|
241
242
|
- Enforcement: explicitly advisory prose (ARC-023) — no check reads a spell's actual output for this block; it holds by these instructions alone.
|
|
242
243
|
<!-- fragment:needs-you:end -->
|
|
243
244
|
|
|
@@ -479,6 +479,7 @@ release — are required operator actions:
|
|
|
479
479
|
- **Never only among optional steps.** An action required for correctness is never listed only under next steps, suggestions, `Carry Forward` or `What's Next?`. It may be repeated there, but it always appears in this block.
|
|
480
480
|
- **Omit it when empty.** When nothing needs the operator, leave the block out entirely: no heading and no "None" line.
|
|
481
481
|
- **Every final report.** The block belongs in whatever report ends the run, including a report written when the spell stops early.
|
|
482
|
+
- **Report it to the presence channel.** When the block is not empty, also run `spell presence report --status waiting --needs-you "<line 1>" --needs-you "<line 2>"`, one flag per line of the block; with no presence channel configured on this machine the command prints nothing and exits 0, so the block itself and the rest of the run are unchanged.
|
|
482
483
|
- Enforcement: explicitly advisory prose (ARC-023) — no check reads a spell's actual output for this block; it holds by these instructions alone.
|
|
483
484
|
<!-- fragment:needs-you:end -->
|
|
484
485
|
|
|
@@ -200,6 +200,7 @@ Execute the `spell-ship` workflow:
|
|
|
200
200
|
- **Never only among optional steps.** An action required for correctness is never listed only under next steps, suggestions, `Carry Forward` or `What's Next?`. It may be repeated there, but it always appears in this block.
|
|
201
201
|
- **Omit it when empty.** When nothing needs the operator, leave the block out entirely: no heading and no "None" line.
|
|
202
202
|
- **Every final report.** The block belongs in whatever report ends the run, including a report written when the spell stops early.
|
|
203
|
+
- **Report it to the presence channel.** When the block is not empty, also run `spell presence report --status waiting --needs-you "<line 1>" --needs-you "<line 2>"`, one flag per line of the block; with no presence channel configured on this machine the command prints nothing and exits 0, so the block itself and the rest of the run are unchanged.
|
|
203
204
|
- Enforcement: explicitly advisory prose (ARC-023) — no check reads a spell's actual output for this block; it holds by these instructions alone.
|
|
204
205
|
<!-- fragment:needs-you:end -->
|
|
205
206
|
|
|
@@ -26,6 +26,25 @@ Use these files for context:
|
|
|
26
26
|
- The feature's `stories.json` — for the work breakdown
|
|
27
27
|
- The feature's `progress.txt` (in `features/{slug}/`, if present) — accumulated learnings from prior iterations; read it before each iteration and append new learnings as the loop proceeds
|
|
28
28
|
|
|
29
|
+
<!-- fragment:presence-report:start -->
|
|
30
|
+
**Presence report (ARC-044 decision 3, ARC-060).** When a presence channel is configured on this
|
|
31
|
+
machine, report through it; when none is, this spell behaves exactly as it does without this
|
|
32
|
+
paragraph. Configured means `spell presence status` exits 0: the service is running and the token
|
|
33
|
+
in the user store opens it. Report with the CLI only; never pass a token on the command line, and
|
|
34
|
+
never write a repository file to report.
|
|
35
|
+
|
|
36
|
+
- At the start of this spell: `spell presence report --spell <spell-id> --status working --task "<the task in one line>"`.
|
|
37
|
+
- When this spell's output carries a `## ⚠ Needs you` block: `spell presence report --status waiting --needs-you "<line 1>" --needs-you "<line 2>"`, one flag per line; the block itself is unchanged.
|
|
38
|
+
- At a checkpoint worth showing (a commit made, a story passed): `spell presence report --status working --task "<what is now happening>"`.
|
|
39
|
+
- When the session closes: `spell presence end`.
|
|
40
|
+
|
|
41
|
+
The command is silent and exits 0 when no channel is configured, prints one line to stderr and
|
|
42
|
+
still exits 0 when the channel refuses a report, and never blocks a spell. The service keeps
|
|
43
|
+
presence in memory only, reconstructable from `spell state --json` and never authoritative; a
|
|
44
|
+
session that stops reporting is shown as unknown after 90 seconds. Enforcement: explicitly
|
|
45
|
+
advisory prose (ARC-023) — no check reads a spell's shell history for these calls.
|
|
46
|
+
<!-- fragment:presence-report:end -->
|
|
47
|
+
|
|
29
48
|
Workflow (loop until all stories pass):
|
|
30
49
|
|
|
31
50
|
0. **Sync workspace** — before any code changes, ensure the workspace is current:
|
|
@@ -265,6 +265,7 @@ just because nothing threw an error.
|
|
|
265
265
|
- **Never only among optional steps.** An action required for correctness is never listed only under next steps, suggestions, `Carry Forward` or `What's Next?`. It may be repeated there, but it always appears in this block.
|
|
266
266
|
- **Omit it when empty.** When nothing needs the operator, leave the block out entirely: no heading and no "None" line.
|
|
267
267
|
- **Every final report.** The block belongs in whatever report ends the run, including a report written when the spell stops early.
|
|
268
|
+
- **Report it to the presence channel.** When the block is not empty, also run `spell presence report --status waiting --needs-you "<line 1>" --needs-you "<line 2>"`, one flag per line of the block; with no presence channel configured on this machine the command prints nothing and exits 0, so the block itself and the rest of the run are unchanged.
|
|
268
269
|
- Enforcement: explicitly advisory prose (ARC-023) — no check reads a spell's actual output for this block; it holds by these instructions alone.
|
|
269
270
|
<!-- fragment:needs-you:end -->
|
|
270
271
|
|
|
@@ -84,6 +84,25 @@ The slug comes from the work — the focus, the handoff's active task, the top n
|
|
|
84
84
|
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.
|
|
85
85
|
<!-- fragment:branch-rename-gate:end -->
|
|
86
86
|
|
|
87
|
+
<!-- fragment:presence-report:start -->
|
|
88
|
+
**Presence report (ARC-044 decision 3, ARC-060).** When a presence channel is configured on this
|
|
89
|
+
machine, report through it; when none is, this spell behaves exactly as it does without this
|
|
90
|
+
paragraph. Configured means `spell presence status` exits 0: the service is running and the token
|
|
91
|
+
in the user store opens it. Report with the CLI only; never pass a token on the command line, and
|
|
92
|
+
never write a repository file to report.
|
|
93
|
+
|
|
94
|
+
- At the start of this spell: `spell presence report --spell <spell-id> --status working --task "<the task in one line>"`.
|
|
95
|
+
- When this spell's output carries a `## ⚠ Needs you` block: `spell presence report --status waiting --needs-you "<line 1>" --needs-you "<line 2>"`, one flag per line; the block itself is unchanged.
|
|
96
|
+
- At a checkpoint worth showing (a commit made, a story passed): `spell presence report --status working --task "<what is now happening>"`.
|
|
97
|
+
- When the session closes: `spell presence end`.
|
|
98
|
+
|
|
99
|
+
The command is silent and exits 0 when no channel is configured, prints one line to stderr and
|
|
100
|
+
still exits 0 when the channel refuses a report, and never blocks a spell. The service keeps
|
|
101
|
+
presence in memory only, reconstructable from `spell state --json` and never authoritative; a
|
|
102
|
+
session that stops reporting is shown as unknown after 90 seconds. Enforcement: explicitly
|
|
103
|
+
advisory prose (ARC-023) — no check reads a spell's shell history for these calls.
|
|
104
|
+
<!-- fragment:presence-report:end -->
|
|
105
|
+
|
|
87
106
|
**Drift Check (run before deep context gathering):**
|
|
88
107
|
|
|
89
108
|
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.
|
|
@@ -108,6 +127,7 @@ Then produce output in this exact structure:
|
|
|
108
127
|
- **Never only among optional steps.** An action required for correctness is never listed only under next steps, suggestions, `Carry Forward` or `What's Next?`. It may be repeated there, but it always appears in this block.
|
|
109
128
|
- **Omit it when empty.** When nothing needs the operator, leave the block out entirely: no heading and no "None" line.
|
|
110
129
|
- **Every final report.** The block belongs in whatever report ends the run, including a report written when the spell stops early.
|
|
130
|
+
- **Report it to the presence channel.** When the block is not empty, also run `spell presence report --status waiting --needs-you "<line 1>" --needs-you "<line 2>"`, one flag per line of the block; with no presence channel configured on this machine the command prints nothing and exits 0, so the block itself and the rest of the run are unchanged.
|
|
111
131
|
- Enforcement: explicitly advisory prose (ARC-023) — no check reads a spell's actual output for this block; it holds by these instructions alone.
|
|
112
132
|
<!-- fragment:needs-you:end -->
|
|
113
133
|
|
|
@@ -126,6 +146,7 @@ Before anything else, check:
|
|
|
126
146
|
- **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.
|
|
127
147
|
- **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.
|
|
128
148
|
- 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).
|
|
149
|
+
- **Live sessions in this repository's other checkouts (presence):** run `spell presence sessions --json`; when it exits 0, list each session whose `repository.root` is this repository's root and whose `checkout.path` is not this checkout (its path, branch, status, task and `agent.slug`), so the footprint rule (R4 above) weighs work that is running now and not only the worktree list; when it exits 1, no presence channel is configured and this bullet adds nothing to the output.
|
|
129
150
|
- **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:
|
|
130
151
|
- 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.
|
|
131
152
|
- 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.
|
|
@@ -286,6 +286,7 @@ Every report the orchestrator ends a turn with leads with the ledger, then what
|
|
|
286
286
|
- **Never only among optional steps.** An action required for correctness is never listed only under next steps, suggestions, `Carry Forward` or `What's Next?`. It may be repeated there, but it always appears in this block.
|
|
287
287
|
- **Omit it when empty.** When nothing needs the operator, leave the block out entirely: no heading and no "None" line.
|
|
288
288
|
- **Every final report.** The block belongs in whatever report ends the run, including a report written when the spell stops early.
|
|
289
|
+
- **Report it to the presence channel.** When the block is not empty, also run `spell presence report --status waiting --needs-you "<line 1>" --needs-you "<line 2>"`, one flag per line of the block; with no presence channel configured on this machine the command prints nothing and exits 0, so the block itself and the rest of the run are unchanged.
|
|
289
290
|
- Enforcement: explicitly advisory prose (ARC-023) — no check reads a spell's actual output for this block; it holds by these instructions alone.
|
|
290
291
|
<!-- fragment:needs-you:end -->
|
|
291
292
|
|
|
@@ -168,6 +168,7 @@ Workflow:
|
|
|
168
168
|
- **Never only among optional steps.** An action required for correctness is never listed only under next steps, suggestions, `Carry Forward` or `What's Next?`. It may be repeated there, but it always appears in this block.
|
|
169
169
|
- **Omit it when empty.** When nothing needs the operator, leave the block out entirely: no heading and no "None" line.
|
|
170
170
|
- **Every final report.** The block belongs in whatever report ends the run, including a report written when the spell stops early.
|
|
171
|
+
- **Report it to the presence channel.** When the block is not empty, also run `spell presence report --status waiting --needs-you "<line 1>" --needs-you "<line 2>"`, one flag per line of the block; with no presence channel configured on this machine the command prints nothing and exits 0, so the block itself and the rest of the run are unchanged.
|
|
171
172
|
- Enforcement: explicitly advisory prose (ARC-023) — no check reads a spell's actual output for this block; it holds by these instructions alone.
|
|
172
173
|
<!-- fragment:needs-you:end -->
|
|
173
174
|
|
|
@@ -119,6 +119,7 @@ collide, but a PR title inserted verbatim as a label could).
|
|
|
119
119
|
- **Never only among optional steps.** An action required for correctness is never listed only under next steps, suggestions, `Carry Forward` or `What's Next?`. It may be repeated there, but it always appears in this block.
|
|
120
120
|
- **Omit it when empty.** When nothing needs the operator, leave the block out entirely: no heading and no "None" line.
|
|
121
121
|
- **Every final report.** The block belongs in whatever report ends the run, including a report written when the spell stops early.
|
|
122
|
+
- **Report it to the presence channel.** When the block is not empty, also run `spell presence report --status waiting --needs-you "<line 1>" --needs-you "<line 2>"`, one flag per line of the block; with no presence channel configured on this machine the command prints nothing and exits 0, so the block itself and the rest of the run are unchanged.
|
|
122
123
|
- Enforcement: explicitly advisory prose (ARC-023) — no check reads a spell's actual output for this block; it holds by these instructions alone.
|
|
123
124
|
<!-- fragment:needs-you:end -->
|
|
124
125
|
|
|
@@ -136,6 +136,7 @@ Workflow:
|
|
|
136
136
|
- **Never only among optional steps.** An action required for correctness is never listed only under next steps, suggestions, `Carry Forward` or `What's Next?`. It may be repeated there, but it always appears in this block.
|
|
137
137
|
- **Omit it when empty.** When nothing needs the operator, leave the block out entirely: no heading and no "None" line.
|
|
138
138
|
- **Every final report.** The block belongs in whatever report ends the run, including a report written when the spell stops early.
|
|
139
|
+
- **Report it to the presence channel.** When the block is not empty, also run `spell presence report --status waiting --needs-you "<line 1>" --needs-you "<line 2>"`, one flag per line of the block; with no presence channel configured on this machine the command prints nothing and exits 0, so the block itself and the rest of the run are unchanged.
|
|
139
140
|
- Enforcement: explicitly advisory prose (ARC-023) — no check reads a spell's actual output for this block; it holds by these instructions alone.
|
|
140
141
|
<!-- fragment:needs-you:end -->
|
|
141
142
|
|
|
@@ -266,6 +266,7 @@ If `external_provider=jira` or `external_provider=other`, add explicit TODOs in
|
|
|
266
266
|
- **Never only among optional steps.** An action required for correctness is never listed only under next steps, suggestions, `Carry Forward` or `What's Next?`. It may be repeated there, but it always appears in this block.
|
|
267
267
|
- **Omit it when empty.** When nothing needs the operator, leave the block out entirely: no heading and no "None" line.
|
|
268
268
|
- **Every final report.** The block belongs in whatever report ends the run, including a report written when the spell stops early.
|
|
269
|
+
- **Report it to the presence channel.** When the block is not empty, also run `spell presence report --status waiting --needs-you "<line 1>" --needs-you "<line 2>"`, one flag per line of the block; with no presence channel configured on this machine the command prints nothing and exits 0, so the block itself and the rest of the run are unchanged.
|
|
269
270
|
- Enforcement: explicitly advisory prose (ARC-023) — no check reads a spell's actual output for this block; it holds by these instructions alone.
|
|
270
271
|
<!-- fragment:needs-you:end -->
|
|
271
272
|
|
|
@@ -111,6 +111,7 @@ Workflow:
|
|
|
111
111
|
- **Never only among optional steps.** An action required for correctness is never listed only under next steps, suggestions, `Carry Forward` or `What's Next?`. It may be repeated there, but it always appears in this block.
|
|
112
112
|
- **Omit it when empty.** When nothing needs the operator, leave the block out entirely: no heading and no "None" line.
|
|
113
113
|
- **Every final report.** The block belongs in whatever report ends the run, including a report written when the spell stops early.
|
|
114
|
+
- **Report it to the presence channel.** When the block is not empty, also run `spell presence report --status waiting --needs-you "<line 1>" --needs-you "<line 2>"`, one flag per line of the block; with no presence channel configured on this machine the command prints nothing and exits 0, so the block itself and the rest of the run are unchanged.
|
|
114
115
|
- Enforcement: explicitly advisory prose (ARC-023) — no check reads a spell's actual output for this block; it holds by these instructions alone.
|
|
115
116
|
<!-- fragment:needs-you:end -->
|
|
116
117
|
|
|
@@ -186,6 +186,7 @@ report the discrepancy rather than declaring the sync done.
|
|
|
186
186
|
- **Never only among optional steps.** An action required for correctness is never listed only under next steps, suggestions, `Carry Forward` or `What's Next?`. It may be repeated there, but it always appears in this block.
|
|
187
187
|
- **Omit it when empty.** When nothing needs the operator, leave the block out entirely: no heading and no "None" line.
|
|
188
188
|
- **Every final report.** The block belongs in whatever report ends the run, including a report written when the spell stops early.
|
|
189
|
+
- **Report it to the presence channel.** When the block is not empty, also run `spell presence report --status waiting --needs-you "<line 1>" --needs-you "<line 2>"`, one flag per line of the block; with no presence channel configured on this machine the command prints nothing and exits 0, so the block itself and the rest of the run are unchanged.
|
|
189
190
|
- Enforcement: explicitly advisory prose (ARC-023) — no check reads a spell's actual output for this block; it holds by these instructions alone.
|
|
190
191
|
<!-- fragment:needs-you:end -->
|
|
191
192
|
|