@prismer/runtime 1.9.23 → 2.0.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/CHANGELOG.md CHANGED
@@ -1,5 +1,158 @@
1
1
  # Changelog — @prismer/runtime
2
2
 
3
+ ## Unreleased
4
+
5
+ ## v2.0.0 — 2026-05-19 — `prismer` daemon bin retained + Skill Gate GA
6
+
7
+ Coordinated v2.0.0 GA. `/VERSION` (single source of truth) → 2.0.0 via
8
+ `sdk/build/version.sh`. The headline bin-split was resolved by keeping
9
+ `@prismer/runtime` on `bin: { prismer }` (daemon priority is higher than
10
+ SDK, so the daemon claims the canonical name) and renaming `@prismer/sdk`
11
+ to `bin: { cloud }` instead.
12
+
13
+ ### Changed — **Binary retained: `bin: prismer`** (daemon priority decision, 2026-05-19)
14
+
15
+ - `package.json` `bin` keeps mapping `prismer` → `./dist/cli.js`. `@prismer/sdk`
16
+ renamed its binary to `cloud` (see `@prismer/sdk` CHANGELOG). The two bins
17
+ now coexist — sandbox image install order no longer creates conflicts.
18
+ - Executable shim at `src/bin/prismer.ts`. Tsup emits to `dist/cli.js`;
19
+ package.json bin maps it to `prismer`.
20
+ - `cli/index.ts`: `new Command('prismer')` (unchanged from v1.x); `--help`
21
+ and parse errors report `Usage: prismer [options]`.
22
+ - Help text + error prefixes + cookbook references stay on `prismer` across
23
+ `src/cli/*`, `src/cli/commands/*`, `src/config.ts`, `src/daemon-id.ts`,
24
+ `src/pair.ts`, `src/index.ts`. (An intermediate Session-3 commit had
25
+ temporarily renamed these to a daemon-suffixed form; reverted before GA
26
+ per user direction.)
27
+ - See `docs/release200/02-v20-daemon-runtime-plan.md` §CLI 边界更新 for the
28
+ rationale (fixes v1.x sandbox-image bin clobber bug that caused the v2.0
29
+ Built-in skill Kanban scheduling regression).
30
+
31
+ ### Changed — **VERSION sync**
32
+
33
+ - `cli/index.ts` `VERSION` literal synced from 1.9.7 → 2.0.0. Now sourced
34
+ from `/VERSION` via `sdk/build/version.sh`.
35
+
36
+ ### Added — **Skill Gate foundation (v2.0 GA gate)**
37
+
38
+ The Skill Gate (cloud `/skills/ack` round-trip + dispatch-time skill sync
39
+ + `SkillLoader` per-adapter) was incrementally landed across 1.9.x cuts.
40
+ v2.0 promotes it to GA. Recap of the components carried by this release:
41
+
42
+ - **SkillSyncManager** (`daemon/skill-sync.ts`): reconciles
43
+ `agent.skills.list` ↔ local `~/.prismer/agents/<id>/skills/`,
44
+ writes `SKILL.md` to disk, replies `skills.ack` once content is durable.
45
+ - **SkillLoader SPI**: adapters can opt into per-dispatch skill payload
46
+ composition. Hermes + OpenClaw implement; Codex + claude-code are no-ops
47
+ in 2.0 (skill sync still writes files to disk for those, but the
48
+ dispatch-time injection is gated by adapter capability).
49
+ - **v2.0 Skill Gate scope**: dispatch-time skill payload coverage validated
50
+ for `hermes` + `openclaw` only. `codex` + `claude-code` skill sync remains
51
+ a file-write no-op pending adapter framework support (tracked v2.1+).
52
+ - Live-gate evidence: `dev-loop.sh skill-live-gate` /
53
+ `scripts/sandbox/e2e/skill-agent-dispatch-live.ts` capture 21 Built-in +
54
+ 1 magic-marker skill in `POST /v1/runs.instructions` (~31 KB payload).
55
+ See `docs/release200/evidence/05-live-dispatch-gate-2026-05-19.md`.
56
+
57
+ ### Added — **Origin Adapter framework** (promoted from "Unreleased")
58
+
59
+ `daemon/asset/origin/` — daemon-side asset producers behind a uniform
60
+ OriginAdapter SPI (doc 26 §4 Phase 2). Foundation for the v2.0 `assets` +
61
+ `ingest` Built-in skills.
62
+
63
+ - **SPI** (`spi.ts`): `OriginAdapter` interface with
64
+ `kind: 'upload' | 'drop-folder' | 'agent-gen'`,
65
+ `observe / identifySource / fetch` decomposition. Identification stays
66
+ separate from byte fetch so the outbox can dedupe before paying read cost.
67
+ - **Outbox** (`outbox.ts`): SQLite-backed pending-upload queue mirroring
68
+ `daemon/memory/outbox.ts` shape — Zod validation → dead-letter,
69
+ `idempotencyKey = sha256(originKind|wid|sourceRef|observedAt)` UNIQUE,
70
+ `claimNext()` transactional, `recordFailure(maxAttempts)` auto-spills to
71
+ dead-letter. Restart-resume-friendly.
72
+ - **Drop-folder adapter** (`drop-folder.ts`): polls
73
+ `~/.prismer/workspaces/<wid>/drop/` (1 s tick, recursive), enqueues
74
+ observations, moves files to `uploaded/` on success and `upload-failed/`
75
+ on persistent failure.
76
+ - **Agent-gen adapter** (`agent-gen.ts`): synchronous
77
+ `handleAssetWrite(body, { cloud })` for the `POST /local/asset/write` RPC.
78
+ - **Web-upload adapter** (`web-upload.ts`): cloud-side marker class for SPI
79
+ symmetry.
80
+ - **Upload runner** (`upload-runner.ts`): generic worker draining the
81
+ outbox; `onUploadSuccess` / `onUploadFailure` hooks per adapter.
82
+ - **`POST /local/asset/write` route** (`local-server.ts`): wires
83
+ `onAssetWrite` sink alongside `onDispatch` / `attachMemory`. Returns
84
+ `{ assetId, contentHash, prismerUri }`. 400 / 502 / 501 error contract.
85
+
86
+ ### Added — **memory-curation skill** (promoted from "Unreleased")
87
+
88
+ - **Codex adapter** (`adapters/codex/index.ts`): `buildCodexPrompt()`
89
+ extracted as pure function; injects `MEMORY_CURATION_SKILL_TEXT` as
90
+ system-prompt preamble (Codex has no native skill framework).
91
+ - **Embedded skill module** (`src/skills/memory-curation.ts`): regenerated
92
+ from canonical `sdk/prismer-cloud/skill/memory-curation.md` via
93
+ `scripts/regenerate-memory-curation-skill.cjs`.
94
+
95
+ ### Added — **CLI hardening pass** (promoted from "Unreleased")
96
+
97
+ Audit of the 16-verb CLI surface. No new daemon behavior; existing commands
98
+ now fail closed and emit consistent JSON.
99
+
100
+ - **`prismer config (path|show|set)`** — inspect or edit `~/.prismer/config.toml`.
101
+ `show` redacts the api_key by default; `--reveal` prints clear text.
102
+ `set cloud_api_base <url>` runs through `normalizeCloudUrl`,
103
+ `set api_key sk-…` validates the key format.
104
+ - **`prismer setup --check`** — dry-run mode. Validates `--cloud`, prints
105
+ the would-be config target and api-key source, returns without touching
106
+ disk. JSON: `{ok:true, check:true, mode, cloud, …}`.
107
+ - **Default `--cloud` URL is `https://prismer.cloud`** (was
108
+ `https://cloud.prismer.dev`). Visible in `setup --help` / `pair --help`.
109
+ - **Stable error codes** on every CLI exit path so JSON consumers can
110
+ branch on `error.code` (e.g. `invalid_cloud_url`, `config_missing`,
111
+ `task_create_failed`).
112
+
113
+ ### Fixed — **CLI hardening pass** (promoted from "Unreleased")
114
+
115
+ - **`--json` was dead code on every subcommand.** `applyCommonFlags`
116
+ stripped `--json` from argv before commander parsed per-command options,
117
+ so JSON branches silently no-op'd (e.g. `prismer status --json` exit 0
118
+ with no body). Now `--json` is kept in argv and declared on every
119
+ printing subcommand.
120
+ - **`prismer setup --cloud 0.0.0.0:3000` accepted bare host:port and
121
+ exploded with raw Zod JSON.** `normalizeCloudUrl()` now auto-prefixes
122
+ `http://` for bare host shapes and rejects everything else with a
123
+ single-line error.
124
+ - **`exitWithError` is JSON-aware.** Emits
125
+ `{ok:false, error:{code, message}}` to stdout when UI is in JSON mode.
126
+ Every action handler goes through a `runAction(fn, { code })` wrapper.
127
+ - **Daemon ignored application-level `AUTH_FAILED`.** The runner now
128
+ detects `AUTH_FAILED` / `AUTH_REQUIRED` / `auth_invalid` payload codes,
129
+ emits `auth-failed`, and `daemon run` clears the pid file + exits 2.
130
+ - **`memory stats` returned exit 0 when the gateway was unavailable** even
131
+ though `delete` and `sync` exited 1 in the same condition. Now consistent.
132
+ - **`task create` printed `(0): fetch failed`.** Network errors now render
133
+ as `(network error): …` so the `0` HTTP status doesn't leak.
134
+ - **`daemon restart` dropped `--port` / `--foreground` / `--no-local-server`
135
+ on the floor.** Restart now forwards the flags through to `start`.
136
+ - **`daemon logs --tail` read the entire log file into memory.** Now seeks
137
+ from the end in 64 KiB chunks.
138
+
139
+ ### Tests
140
+
141
+ - Origin Adapter framework: 44 new vitest assertions across 8 new test files
142
+ (`origin-spi`, `origin-outbox`, `origin-drop-folder`, `origin-agent-gen`,
143
+ `local-server-asset-write`, `origin-web-upload`,
144
+ `skill-memory-curation-sync`, `codex-adapter-skill-injection`).
145
+ - Acceptance criteria covered: doc 26 §5 L2-T1 (100-burst, dead-letter=0),
146
+ L2-T2 (restart resume), L2-T3 (RPC sync return).
147
+ - Total runtime suite: 192 → 234 passing, 0 failures.
148
+
149
+ ### Cookbook
150
+
151
+ - `docs/cookbook/m-asset-origin-drop-folder.md`
152
+ - `docs/cookbook/m-asset-origin-agent-gen.md`
153
+
154
+ ---
155
+
3
156
  ## v1.9.7 — 2026-05-12 — Device capacity fix + setup daemon auto-start
4
157
 
5
158
  ### Fixed
@@ -56,116 +209,6 @@ CEO authorization data layer, and runtime version hygiene.
56
209
 
57
210
  ---
58
211
 
59
- ## Unreleased — Origin Adapter framework + memory-curation skill
60
-
61
- Doc 26 §4 Phase 2 + doc 27 rev 5 §3. Daemon-side asset producers behind a
62
- uniform OriginAdapter SPI; agent-driven memory curation guidance loaded into
63
- the four host adapters.
64
-
65
- ### Added — **Origin Adapter framework** (`daemon/asset/origin/`)
66
- - **SPI** (`spi.ts`): `OriginAdapter` interface with `kind: 'upload' | 'drop-folder' | 'agent-gen'`, `observe / identifySource / fetch` decomposition. Identification stays separate from byte fetch so the outbox can dedupe before paying read cost.
67
- - **Outbox** (`outbox.ts`): SQLite-backed pending-upload queue mirroring `daemon/memory/outbox.ts` shape — Zod validation → dead-letter, `idempotencyKey = sha256(originKind|wid|sourceRef|observedAt)` UNIQUE, `claimNext()` transactional, `recordFailure(maxAttempts)` auto-spills to dead-letter. Restart-resume-friendly (rows persist across daemon process death).
68
- - **Drop-folder adapter** (`drop-folder.ts`): polls `~/.prismer/workspaces/<wid>/drop/` (1s tick, recursive), enqueues observations, on success moves files to `uploaded/`, on persistent failure to `upload-failed/`. Mime detected by extension.
69
- - **Agent-gen adapter** (`agent-gen.ts`): synchronous handler `handleAssetWrite(body, { cloud })` for the new `POST /local/asset/write` RPC. Daemon writes under owner identity; `sourceAgentImUserId` is a passenger metadata field (decoupled from auth — no dependency on Line B B1 POST permission alignment).
70
- - **Web-upload adapter** (`web-upload.ts`): cloud-side marker class for SPI symmetry. Throws if invoked daemon-side; the actual upload is the cloud `POST /api/im/assets` handler.
71
- - **Upload runner** (`upload-runner.ts`): generic worker draining the outbox, dispatching to adapters by `originKind`. Hooks `onUploadSuccess` / `onUploadFailure` on the adapter (drop-folder uses these for the uploaded/upload-failed file moves).
72
- - **`POST /local/asset/write` route** (`local-server.ts`): wires `onAssetWrite` sink alongside `onDispatch` / `attachMemory`. Returns `{ assetId, contentHash, prismerUri: 'prismer://workspace/<wid>/asset/<contentHash>' }`. 400/502/501 error contract.
73
-
74
- ### Added — **memory-curation skill** (doc 27 rev 5 §3)
75
- - **Codex adapter** (`adapters/codex/index.ts`): `buildCodexPrompt()` extracted as pure function; injects `MEMORY_CURATION_SKILL_TEXT` as system-prompt preamble (Codex has no native skill framework).
76
- - **Embedded skill module** (`src/skills/memory-curation.ts`): regenerated from canonical `sdk/prismer-cloud/skill/memory-curation.md` via `scripts/regenerate-memory-curation-skill.cjs` (also handles the openclaw / Python / CC plugin copies).
77
-
78
- ### Tests
79
- - 44 new vitest assertions across 8 new test files: `origin-spi`, `origin-outbox`, `origin-drop-folder`, `origin-agent-gen`, `local-server-asset-write`, `origin-web-upload`, `skill-memory-curation-sync`, `codex-adapter-skill-injection`.
80
- - Acceptance criteria covered: doc 26 §5 L2-T1 (100-burst, dead-letter=0), L2-T2 (restart resume), L2-T3 (RPC sync return).
81
- - Total runtime suite: 192 → 234 passing, 0 failures.
82
-
83
- ### Cookbook
84
- - `docs/cookbook/m-asset-origin-drop-folder.md`
85
- - `docs/cookbook/m-asset-origin-agent-gen.md`
86
-
87
- ### Phase staging — what this PR does NOT yet wire
88
- - **Daemon `runner.ts` does not yet construct `OriginOutbox` / `DropFolderAdapter` / `UploadRunner`.** The SPI + handlers ship here; the runner-level wiring + a concrete `CloudUploadClient` (FormData wrapper around the existing `CloudClient`) land in a follow-up PR alongside the rest of doc 26 §4 Phase 2 production-enable work.
89
- - `POST /local/asset/write` returns **501 `asset_write_unavailable`** in production until that PR wires the `onAssetWrite` sink on `LocalServer`.
90
- - Acceptance criteria (L2-T1, L2-T2, L2-T3) are validated against `fakeCloud` in unit tests; an end-to-end cookbook run against the live `POST /api/im/assets` handler is part of the follow-up.
91
-
92
- ---
93
-
94
- ## Unreleased — CLI hardening pass
95
-
96
- User-reported "大量空洞" — full audit of the 16-verb CLI surface. No new daemon
97
- behavior; existing commands now fail closed and emit consistent JSON when
98
- `--json` is set.
99
-
100
- ### Fixed
101
-
102
- - **`--json` was dead code on every subcommand.** `applyCommonFlags` stripped
103
- `--json` from argv before commander parsed per-command options, so
104
- `if (opts.json) printJson(...)` branches in setup/status/workspace/sandbox/
105
- asset/cookbook/chat never fired. UI mode was set, but the pretty branches
106
- silently no-op'd in JSON mode and stdout came out empty (e.g.
107
- `prismer status --json` exit 0 with no body). Now we keep `--json` in argv
108
- and declare it on every subcommand that prints — empty-output paths are gone.
109
- - **`prismer setup --cloud 0.0.0.0:3000` accepted bare host:port and exploded
110
- with raw Zod JSON six stack frames later.** `normalizeCloudUrl()` now
111
- auto-prefixes `http://` for bare host shapes and rejects everything else
112
- with a single-line error. The same helper is wired into `pair`, `setup`,
113
- and `config set cloud_api_base`.
114
- - **`exitWithError` is JSON-aware.** When the UI is in JSON mode it emits
115
- `{ok:false, error:{code, message}}` to stdout (with stable codes like
116
- `invalid_cloud_url`, `config_missing`, `task_create_failed`) instead of
117
- the pretty `Error: …` line. Every action handler now goes through a
118
- `runAction(fn, { code })` wrapper that catches throws — including the
119
- `loadConfig()` "Config not found" throw that previously bubbled to
120
- commander's default handler with a `prismer:` prefix.
121
- - **Daemon ignored application-level `AUTH_FAILED`.** Cloud sends an
122
- application error frame (not WS close 4001) when the post-handshake API
123
- key lookup fails; the runner only logged it and stayed alive forever with
124
- a stale pid file. Now the runner detects `AUTH_FAILED` / `AUTH_REQUIRED`
125
- / `auth_invalid` payload codes, emits `auth-failed`, and `daemon run`'s
126
- handler stops the runner, clears the pid file, and exits 2.
127
- - **`memory stats` returned exit 0 when the gateway was unavailable** even
128
- though `delete` and `sync` both exit 1 in the same condition. All five
129
- memory subcommands now consistently set `process.exitCode = 1` when the
130
- gateway is missing.
131
- - **`task create` printed `(0): fetch failed`.** Network errors now render
132
- as `(network error): …` so the `0` HTTP status doesn't leak.
133
- - **`daemon restart` dropped `--port` / `--foreground` / `--no-local-server`
134
- on the floor.** Restart now forwards the flags through to `start`.
135
- - **`daemon logs --tail` read the entire log file into memory.** Now seeks
136
- from the end in 64 KiB chunks until enough newlines are collected — works
137
- on the multi-MB logs that long-lived hosts accumulate.
138
- - **`--no-start` was a redundant declaration** of commander's automatic
139
- `--no-X` negation; removed.
140
-
141
- ### Added
142
-
143
- - **`prismer config (path|show|set)`** — inspect or edit
144
- `~/.prismer/config.toml` without hand-editing TOML. `show` redacts the
145
- api_key by default; `--reveal` prints clear text. `set cloud_api_base
146
- <url>` runs through `normalizeCloudUrl`, `set api_key sk-…` validates
147
- the key format.
148
- - **`prismer setup --check`** — dry-run mode. Validates `--cloud`, prints
149
- the would-be config target and api-key source, and returns without
150
- touching disk. JSON-friendly: `{ok:true, check:true, mode, cloud, …}`.
151
- - **Default `--cloud` URL is `https://prismer.cloud`** (was
152
- `https://cloud.prismer.dev`). The default is now visible in
153
- `setup --help` / `pair --help`.
154
- - **Stable error codes** on every CLI exit path so JSON consumers can
155
- branch on `error.code` rather than parsing `error.message`.
156
-
157
- ### Internal
158
-
159
- - New `src/cli/util.ts` helpers: `DEFAULT_CLOUD_BASE_URL`,
160
- `normalizeCloudUrl(input)`, `runAction(fn, { code, sanitize })`, and the
161
- JSON-aware `exitWithError(message, { code, exitCode, details })`.
162
- - `applyCommonFlags` now keeps `--json` in argv (only `--quiet`,
163
- `--no-color`, `--color` are still stripped). Every subcommand that
164
- prints JSON now declares `.option('--json', …)` so commander parses it
165
- consistently; pure-text commands (`daemon stop`, `pair`, `banner`,
166
- `adapter install / remove`) declare `--json` as a passthrough so
167
- `prismer --json daemon stop` doesn't error.
168
-
169
212
  ## v1.9.3 — 2026-05-07 — Hosted agents + Hermes long-running + 16-verb CLI
170
213
 
171
214
  First published cut of `@prismer/runtime`. The runtime is the TS-only daemon that hosts Prismer agents on a user's Mac (under `launchd`) or inside a sandbox pod (as PID 1). One binary, one WebSocket to cloud, four in-process adapters, local SQLite mirror.
package/README.md CHANGED
@@ -20,7 +20,7 @@ What the daemon-mode installer does:
20
20
 
21
21
  1. Detects OS / arch (Darwin or Linux x64/arm64; Windows requires WSL2).
22
22
  2. Installs Node.js via `fnm` under `$HOME/.local/share/fnm` if absent (no Homebrew, no sudo).
23
- 3. Strict-pins `@prismer/runtime@1.9.3` (no caret) and installs globally via npm.
23
+ 3. Strict-pins `@prismer/runtime@2.0.0` (no caret) and installs globally via npm.
24
24
  4. Scaffolds `~/.prismer/{adapters,workspace,logs,bin}`.
25
25
  5. Writes `~/Library/LaunchAgents/com.prismer.daemon.plist` (label `com.prismer.daemon`, `KeepAlive=true`, `RunAtLoad=true`, `ProgramArguments` includes `--foreground`), then `bootout` + `bootstrap` to load it.
26
26
  6. Auto-runs `prismer adapter install <name>` for each adapter passed via `--adapters`.
@@ -32,7 +32,7 @@ Installer flags: `-y/--yes`, `--no-setup`, `-v/--verbose`, `--local <dir>` (inst
32
32
  ### npm (manual)
33
33
 
34
34
  ```sh
35
- npm install -g @prismer/runtime@1.9.3
35
+ npm install -g @prismer/runtime@2.0.0
36
36
  prismer pair --device-name "$(hostname)"
37
37
  prismer daemon start
38
38
  ```
@@ -54,7 +54,7 @@ The container daemon binds `:7878` (controller proxy target) instead of the desk
54
54
 
55
55
  ## CLI reference (16 verbs)
56
56
 
57
- `VERSION = '1.9.3'`. Each verb is a `commander` subcommand under `src/cli/commands/`. Output is JSON (`--json`) or human-friendly ANSI by default.
57
+ `VERSION = '2.0.0'`. Each verb is a `commander` subcommand under `src/cli/commands/`. Output is JSON (`--json`) or human-friendly ANSI by default.
58
58
 
59
59
  ### Lifecycle
60
60
 
@@ -405,17 +405,17 @@ shell = "bash"
405
405
 
406
406
  ## Troubleshooting
407
407
 
408
- - **LaunchAgent respawn loop after install** — the plist must include `--foreground` in `ProgramArguments`. v1.9.3 installs do this automatically; if you're upgrading from 1.8.x re-run `curl -fsSL https://prismer.cloud/install.sh | sh -s -- --component=daemon` (the installer does `bootout` + `bootstrap` to reload).
408
+ - **LaunchAgent respawn loop after install** — the plist must include `--foreground` in `ProgramArguments`. v2.0.0 installs do this automatically; if you're upgrading from 1.8.x re-run `curl -fsSL https://prismer.cloud/install.sh | sh -s -- --component=daemon` (the installer does `bootout` + `bootstrap` to reload).
409
409
  - **Daemon shows "waiting for ~/.prismer/config.toml"** — that's expected behavior pre-pair. Run `prismer pair` (or `prismer setup sk-prismer-...`) and the daemon snaps to attention within 5s.
410
410
  - **Cloud unreachable** — `prismer status` will print the failing base URL. Common causes: stale `cloud_api_base` after a tenant move (run `prismer setup --force <new-key> --cloud <url>`), or the API key was rotated (mint a new one with `prismer setup --token <jwt>`).
411
- - **Agent shows under `__unbound__` device in workspace runtime view** — the daemon's `agent.host.declare` is not stamping `daemonId`. Confirm you're on `@prismer/runtime@1.9.3` (the `daemonId` payload field landed in 1.9.3).
412
- - **`claude --print` runs report "no stdin data received in 3s"** — fixed in 1.9.3 (`stdio: ['ignore', 'pipe', 'pipe']`). Older runtimes will surface the warning but the dispatch still completes.
411
+ - **Agent shows under `__unbound__` device in workspace runtime view** — the daemon's `agent.host.declare` is not stamping `daemonId`. Confirm you're on `@prismer/runtime@2.0.0` (the `daemonId` payload field is required as of v2.0.0).
412
+ - **`claude --print` runs report "no stdin data received in 3s"** — fixed in v2.0.0 (`stdio: ['ignore', 'pipe', 'pipe']`). Older runtimes will surface the warning but the dispatch still completes.
413
413
  - **Tasks dispatch but `@`-mention messages never reach the agent** — cloud-side `SHADOW_JOIN_FAILED` rollback. The runtime's `agent.host.declare` requires every declared agent to auto-join all its conversation rooms; check daemon logs for the rollback line and re-register the agent (`prismer agent register …`) to fix the cloud-side row.
414
414
  - **Stuck task that never replies** — the 60s reaper aborts and replies `{ok:false, error.code:'daemon_task_timeout'}` after `max(timeoutMs, 5min)`. Cloud will mark the task `failed` accordingly. Inspect via `prismer task get <id>`.
415
415
 
416
416
  ## Versioning
417
417
 
418
- > See [CHANGELOG.md](./CHANGELOG.md). Current: **v1.9.3** (2026-05-07).
418
+ > See [CHANGELOG.md](./CHANGELOG.md). Current: **v2.0.0** (2026-05-19).
419
419
 
420
420
  ## License
421
421