@abelxiaoxing/cadence 2.0.14 → 2.0.16

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
@@ -137,7 +137,8 @@ For manual checks, `pi -e ./src/index.ts -e ./scripts/agent-panel-demo.ts` adds
137
137
 
138
138
  Open the private link that `cadence server install` printed, or that `cadence token-link --reveal` reveals.
139
139
  Valid bootstrap redirects to a token-free URL and uses an HttpOnly SameSite cookie for subsequent HTTP/WebSocket access; no localStorage token copy.
140
- The unified browser entry first shows projects, without an execution cwd, SDK session or default workspace.
140
+ The unified browser entry opens on the conversation shell, without an execution cwd, SDK session or default workspace.
141
+ Choose a working folder from the lower-right button; before a folder is selected, New conversation offers the same picker and Send stays disabled.
141
142
  Only explicit Open starts or reuses a project owner.
142
143
  Within that project, the browser opens on an ordinary conversation with a real message composer, retained multi-turn context and standard read/write/edit/bash tools; no Cadence task is created by Send.
143
144
  Use `cadence <goal>` or `/cadence <goal>` at the beginning of the input, or select Cadence task, to prepare a separate task.
@@ -151,10 +152,10 @@ Ordinary Send binds its exact text, conversation head, epoch, access and selecte
151
152
  The WebUI provides task/run/assignment navigation, long retained messages and tool detail, exact literal search, timeline and complete scoped NDJSON/Markdown downloads.
152
153
  Desktop panes and phone drawers retain cancellation and keyboard controls.
153
154
  Its chrome follows pi-web-ui: a compact topbar with view tabs and icon actions, a sectioned task sidebar, pill inspector tabs, transcript/tool cards and a bottom statusbar; phones wrap the topbar into an action row and an icon tab row.
154
- The left sidebar lists recent projects and running/retained conversations; a separate lower-left dock observes Cadence subagents and opens their retained transcripts.
155
+ The left sidebar provides New conversation and New task alongside running/retained conversations; a separate lower-left dock observes Cadence subagents and opens their retained transcripts.
155
156
  It is not pi-web-ui's subagent engine.
156
157
  The right sidebar defaults to readonly files, bounded text previews and path-only references; task plan/check/change/review controls occupy its Task details tab.
157
- The lower-right folder button browses directories on the service host and explicitly opens another independent project owner.
158
+ The lower-right folder button contains recent projects, browses directories on the service host and explicitly opens another independent project owner.
158
159
  The unified entry switches project clients on the same origin, including an explicitly configured HTTPS proxy; it never changes a running task's cwd, registers a boot service or cancels the project left behind.
159
160
  Backend cookies and native capabilities never reach the browser; proxied actions remain browser-authority actions, with owner-side consent/build/CSRF checks.
160
161
  The gateway refuses the legacy project-level Open command: all project openings use its own association route, without returning an independent backend token link.
@@ -235,7 +236,9 @@ Storage exhaustion refuses new work rather than silently evicting history.
235
236
  Workbench state lives separately under `<state-home>/cadence-assistant-v1/workbenches-v1/<configuration-hash>/`, not in a hidden substitute workspace.
236
237
  Whole-workbench Stop joins its accepted openings and associated exact-epoch project owners, serializing their final registry releases; unrelated, unassociated owners are not stopped.
237
238
  A changed epoch, uncertain launch or unconfirmed Stop keeps the workbench fenced, but does not prevent Stop from reaching its other known associated owners.
238
- Workbenches never repair missing private state or erase uncertain locks.
239
+ Workbenches never repair missing private state or automatically erase uncertain locks.
240
+ `cadence workbench recover inspect|resolve` offers explicit local recovery after a dead gateway, with exact resources, durable evidence and fresh terminal acknowledgments; it preserves project fences/history and retires only the old workbench associations until another explicit Open.
241
+ Registrations from older versions without a hostname additionally require independent same-host attestation; unknown provenance is not recoverable by guessing a PID.
239
242
  Service restart never resumes the old queue.
240
243
  Uncertain process/auth/storage settlement keeps fences; use documented local informed recovery, not PID-only deletion or automatic cleanup.
241
244
 
@@ -310,7 +313,7 @@ Historical logs are not runtime dependencies, and removing development tooling m
310
313
 
311
314
  `src/service/{gateway,gateway-store,gateway-cli}.ts` owns the no-project entry, private workbench coordination and same-origin project routing, not task execution.
312
315
  A root access rotation retires its proxy attachment IDs and detaches those exact browser viewers at the owners, without cancelling admitted work.
313
- The first version requires a selected project for ordinary Send/tools; the empty workbench is a project selector, not an unbound chat executor.
316
+ The first version requires a selected project for ordinary Send/tools; the empty workbench presents the conversation shell with Send disabled, not an unbound chat executor.
314
317
  `src/service/{workbench,conversations,workbench-files}.ts` owns ordinary conversations, their private retained turns, readonly files and explicit project navigation; `src/service/contracts/workbench.ts` is the portable closed DTO boundary.
315
318
  Conversation auth intents and original settlements use their own flushed private journal, never fabricated task/history receipts.
316
319
  Their original Stop lifetime and exclusive checkout barrier belong to the existing service owner and scheduler.
@@ -332,6 +335,19 @@ Use their current declarations rather than copying DTO parsing, reducers, a seco
332
335
  Ordinary-user Git trust behavior remains unchanged.
333
336
  System services require uid0, bypass user managers/logind entirely and require confirmed native Stop before manager stop or definition replacement; changed state-home inputs, old user units and detached running owners refuse implicit adoption.
334
337
  Registry reservation atomically rejects canonical ancestor/descendant overlaps, including nested Git roots and aliases; a different state-home does not coordinate arbitrary other owners.
338
+ - The short global registry lock never expires or auto-reclaims from PID absence.
339
+ `recover inspect|resolve` handles a valid dead same-host lock explicitly before project recovery, with fresh local-terminal acknowledgments, exact registry/unreserved-project checks and a flushed exclusive evidence receipt.
340
+ Concurrent or interrupted resolvers cannot remove a successor lock; all project reservations, locks and history remain intact.
341
+ Unreserved partial release, unsafe/corrupt registry or receipt bytes, live/remote/ambiguous holders and changed resources stay fenced.
342
+ Readonly diagnosis and project Open name `registry-locked`; see [global registry recovery](docs/service-management.md#residual-global-registry-lock).
343
+ Missing retained project directories do not invalidate the global registry: their exact reservations and private fences remain, while canonical existing ancestors, aliases and overlaps are still checked.
344
+ Unbound `recover` addresses account/workbench state, not cwd; project recovery requires explicit `--workspace`.
345
+ - Workbench recovery is local and interactive, never acquire-on-dead-PID.
346
+ A bounded flushed receipt precedes exact gateway fence release; project registrations, locks, incomplete opening receipts and history are untouched.
347
+ The receipt retires the exact old project-reference incarnations from proxy/Stop association until explicit Open republishes them, preventing a deleted old directory from re-quarantining the next orderly Stop.
348
+ New workbench registrations record their host; legacy hostless registrations require an extra fresh same-host attestation, never automatic host inference.
349
+ Live/foreign/ambiguous owners and changed or unsafe resources refuse.
350
+ Generated Linux units exclude deterministic foreground refusal exit78 from restart; manager acceptance without authenticated readiness is not reported as successful startup.
335
351
  - Native entry requires fresh raw Enter within1500ms, trusted/idle TUI, no pending modal/messages and no child guard.
336
352
  Browser authentication grants access, not task consent; normal mutation ingress also requires independently built compatible client/service/assets identities.
337
353
  - Boot model choice is absent until explicitly selected.
@@ -450,6 +466,7 @@ Byte values are UTF-8/encoded bounds where specified; they are not targets to si
450
466
  | Navigation | 8192 encoded ASCII bytes; encrypted plaintext6000 bytes; no execution authority |
451
467
  | Live/export | 16 viewers,256 messages/1MiB each; two search/two export readers;120s download idle, not total archive timeout |
452
468
  | Storage | 10GiB checkout quota;512MiB reserved per episode;256MiB free-space floor; no TTL cleanup |
469
+ | Registry recovery | 1024 namespace entries; 128 immutable attempts per lock incarnation; no evidence eviction |
453
470
  | Unified workbench | 128 associated projects; 1024 durable opening receipts; 64 connections; bounded proxy frames and bodies; no eviction |
454
471
  | Assets | 16MiB per member/64MiB closure; fixed complete manifest and all font bodies |
455
472
 
@@ -497,6 +514,7 @@ Do not run the entire suite after every local edit, but do not replace final int
497
514
  `vitest run --config test/fast.config.ts` selects only its reviewed short-test allowlist, without inheriting root projects; `test/integration.config.ts` selects the exact complement and retains the serial projects.
498
515
  `test/test-selection.test.ts` compares the runner's actual file discovery across all three configurations, rejecting duplicates, overlap, omissions and moved serial files; new tests belong to integration until explicitly promoted.
499
516
  Create a fresh 0700 root on the checkout's disk filesystem and explicitly set TMPDIR/TEMP/TMP to it; a nearly full tmpfs `/tmp` makes owners refuse at their free-space floor (`receipt-inconclusive`) and `web/dist` publication fail with EXDEV.
517
+ Keep that root's absolute path short: Chromium appends fixture and singleton-socket components, and an overly long path makes it abort before browser scenarios begin.
500
518
  A test waits for the event it needs (both providers contacted, a row settled), not a wall-clock guess at how long process starts take; fixed waits stay only where time is the contract.
501
519
  Use fabricated credentials, isolated browser/profile/state roots and local fixtures; never personal credentials, automatic downloads or unknown process cleanup.
502
520
  Outer command budgets must cover whole suites and preserve original runner waits; existing SDK20s/child15s, PTY90s/interaction15s and browser120s/action15s fixture budgets are not increased to obtain green.
@@ -505,7 +523,7 @@ Preserve failed attempts; correct a demonstrated cause before rerunning, and nev
505
523
  Regression owners:
506
524
 
507
525
  - `service-contract`, `service-current`, `service-model-choice`, `service-auth`: closed DTOs, exact source/choice/current authority, security and compatibility.
508
- - `service-owner`, `service-accepted-work`, `service-stop-continuation`, `service-recovery`: original operations, overlap, Stop, unknown fences and informed recovery.
526
+ - `service-owner`, `service-accepted-work`, `service-stop-continuation`, `service-recovery`, `service-registry-recovery`: original operations, overlap, Stop, unknown fences and informed recovery.
509
527
  - `service-scheduler`, `service-checks`, `service-human-review`, `service-accepting-host`: real SDK overlap/exclusion, native checks, review and publication.
510
528
  - `worker-*`, `lightweight-sdk`, `lightweight-process-diff`: genuine SDK/tool capture, split redaction, no-spill bounds and original native facts.
511
529
  - `service-history-*`: durable ordering, cold/no-index/restarted proof/search/export, corruption/torn/quota and expected-byte publication.
@@ -517,11 +535,17 @@ Regression owners:
517
535
  - `service-cli`: real owners started from the `.env` port and token, reselection of a stopped workspace, edits while running and rotation of the token line.
518
536
  - `workspace-landing`: no-default-workspace startup, explicit root refusal and noncreating native/readonly entry.
519
537
  - `service-gateway` and `gateway-browser`: real same-origin project routing, browser-only authority, retirement on token rotation, continuing ordinary work and genuine multi-owner Stop; loopback and isolated HTTPS browser lanes.
538
+ - `gateway-recovery`: real crashed owners/resolvers, exact gateway-only release, preserved project fences and unfinished openings, retired/reopened associations, live/remote/changed/linked refusals, generated CLI diagnostics and native-TTY host/process/credential/storage acknowledgments.
520
539
 
521
540
  Regenerate operator/service/native/browser outputs only through their canonical builders; `--check` variants compare new private output without overwriting canonical bytes.
522
541
  WebUI text is keyed by its English source: fixed text goes through `useT().t`, whose type requires a `web/src/i18n/zh.ts` entry with the same `{name}` marks, and run-time status words or kept notices through `tx`, which passes unknown text and codes through.
523
542
  The timeline client takes the chosen language from its bridge and is remounted on a switch; browser scenarios pin `locale: "en-US"` so English assertions do not follow the host's `LANG`.
524
- The browser is conversation-first: ordinary chat and explicit Cadence task conversations share its sidebar, while a lower-left dock observes actual Cadence child identities.
543
+ The browser is conversation-first, including before any project is selected: ordinary chat and explicit Cadence task conversations share its sidebar, while a lower-left dock observes actual Cadence child identities.
544
+ The empty entry has no project welcome screen or central Create shortcut; New conversation offers folder selection until a project is explicitly opened.
545
+ The bottom-right folder control is always present, and recent projects live inside its picker rather than in the conversation sidebar.
546
+ Browsing or dismissing the picker never opens a project or sends a message.
547
+ Open is available only for the successfully observed folder while its path input is unchanged; editing the path or refreshing its listing disables Open until Browse settles.
548
+ Browse always makes a fresh readonly observation, including retrying the same path after a read failure; it never replays Open.
525
549
  One service still owns one checkout.
526
550
  The recent-project directory records only explicit project openings in the same private namespace; navigation opens that project's independent authenticated entry rather than changing global cwd, importing Pi sessions or adopting another account's state.
527
551
  The center shows ordinary streamed messages or retained task text as Markdown.
@@ -536,6 +560,51 @@ Review the independently enumerated package member list and every emitted body,
536
560
  Keep public Pi peers external for the extension, the exact Undici/ws runtime edges, the exact optional SDK pins for the standalone owner and all upstream/font/vendor notices.
537
561
  Preserve original license bytes through their precise Git attributes; line-ending normalization must not invalidate audited source/notice hashes.
538
562
 
563
+ ### Release 2.0.16 acceptance snapshot
564
+
565
+ The final code candidate passed all 2070 root tests in 86 files (27 platform skips on Linux), 133 web tests, all 9 real-browser scenarios and the 135-member exact real-pack audit.
566
+ Source/type/build/lint/Agent checks and a separate Bun pack/body audit also passed; this is separate-lane evidence, not a claim that one `verify` invocation was entirely green.
567
+ Observed environment: Linux x86_64, Node26.7.0, Bun1.3.14, Pi SDK0.84.3 and existing Chrome for Testing151.0.7922.34, with `VITEST_MAX_WORKERS=1` and unchanged test deadlines.
568
+ Review added failing-then-passing regressions for a successor lock borrowing a stopped predecessor's PID, unexpected foreground management exceptions being misclassified as exit78, and an accepted Stop abandoning its exact-epoch wait after an inconclusive registration read.
569
+ The stopped-row recovery bridge must belong to the exact current lock; Stop never resends its request or infers closure from a read failure or successor epoch.
570
+ The first full attempt had three pre-existing test deadlines and a workbench Stop with empty CLI output; isolated diagnostics passed the timeout files, and the original timing and empty-output causes remain unconfirmed.
571
+ After the independently reproduced Stop race was fixed, the second full attempt passed root/web checks but every browser launch hit Chromium's explicit singleton-socket path-length refusal because the private temporary root was too long.
572
+ Using a fresh short private root on the same disk, all browser scenarios and the pack audit passed without code changes, larger budgets, skipped tests or downloads.
573
+ Failure logs and isolated receipts remain outside the checkout; no consumer service was installed/restarted, uncertain state cleaned, paid provider used or new native Windows/macOS qualification claimed.
574
+
575
+ ### Workbench recovery review snapshot
576
+
577
+ The recovery review reproduces the still-reserved deleted-project failure, adds gateway-only native recovery (including legacy host attestation), and exercises restart/Stop after retiring old project associations without deleting references or project fences.
578
+ The new gateway recovery file passes 30 tests, including actual owner/resolver exits, concurrent resolvers, interrupted release, unsafe/changed resources, real generated startup refusal/restart/Stop and genuine POSIX TTY confirmation; global registry recovery passes 34 tests.
579
+ Full `verify` passed static/build/lint/Agent checks and reached 2064 passing root tests with 27 platform skips, but one unchanged `service-history-projection` dense-message test exceeded its 15s deadline.
580
+ Its complete 24-test file passed in a subsequent isolated diagnostic run (the affected case took 1.83s); the original timing cause is unconfirmed, not retrospectively successful.
581
+ After the final startup/Stop diagnostic wording correction, 121 targeted CLI/recovery tests, source/generated checks, 133 web tests, all 9 browser scenarios and the 135-member real-pack audit passed.
582
+ A separate Bun pack/body audit also passed; failures and isolated fixture receipts remain outside the checkout, with no increased test budgets, downloaded dependencies, consumer lock cleanup or service installation/restart.
583
+ Actual WSL shutdown, real service-manager installation and new native Windows/macOS recovery qualification were not executed; this is not a full green `verify` claim.
584
+
585
+ ### Conversation-first entry review snapshot
586
+
587
+ The project-less conversation shell and folder-picker review passed 133 web tests, all 9 real-browser scenarios and the 135-member real-pack audit, plus a separate Bun pack/body audit.
588
+ New loopback and HTTPS regressions refuse Open after an unbrowsed path edit, retry the same readonly directory observation after failure, and fence Open while a refresh is pending; the two original picker defects were observed failing before their fixes.
589
+ Full `verify` passed its static/build/lint/Agent checks but stopped in the root suite: 2033 tests passed, 27 platform tests skipped, and the unchanged `service-history-search-export` field-kind/snapshot case exceeded its 5s deadline.
590
+ That complete 16-test file passed in a subsequent isolated diagnostic run (the affected case took 1.16s); the original timing cause is unconfirmed, and this is not a full green `verify` claim.
591
+ Failed logs were retained outside the checkout; no deadline was increased, test skipped to obtain green, dependency downloaded or consumer service installed/restarted.
592
+
593
+ ### Release 2.0.15 acceptance snapshot
594
+
595
+ The release candidate passed the complete root suite: 2034 tests in 85 files, with 27 platform skips on Linux.
596
+ The final browser-only frame-readiness adjustment then passed all 9 real-browser scenarios; 130 web tests and the 135-member real-pack audit also passed.
597
+ This is separate-lane evidence, not a claim that one final `verify` invocation was entirely green.
598
+ Observed environment: Linux x86_64, Node26.7.0, Bun1.3.14, Pi SDK0.84.3 and existing Chrome for Testing151.0.7922.34; root runs used `VITEST_MAX_WORKERS=1` without changing test deadlines.
599
+ New coverage includes actual registry-writer and resolver exits, concurrent resolvers, unchanged project fences/history, changed/linked/remote/live resources, a removed stopped workspace, piped/pasted/canceled refusal, genuine native-TTY confirmation and browser Open after explicit recovery without replay.
600
+
601
+ The first integration command was cut off by its 25-minute outer command budget while tests were still running.
602
+ The next completed root run failed one omitted browser-test provenance pin (updated) and three owner/proxy settlement or timeout cases, which passed separately; their timing cause was not established.
603
+ A later complete root/web pass encountered Chromium's first screenshot-capture failure; the browser fixture now waits for painted frames before that capture, without retrying operations or swallowing capture errors, and all browser scenarios passed afterward.
604
+ The last full attempt hit six history-test deadlines in two files; those unchanged files passed all 45 tests in a subsequent diagnostic run, and the earlier complete root pass remains distinct from that later failure.
605
+ Failed logs and isolated fixture evidence were preserved; no test budget was increased, dependency/browser downloaded, consumer lock deleted or service installed/restarted.
606
+ No paid-provider use or new native Windows/macOS qualification is claimed.
607
+
539
608
  ### Release 2.0.14 acceptance snapshot
540
609
 
541
610
  Full `verify` passed on the release candidate before this evidence-only note, with `VITEST_MAX_WORKERS=1`: 2000 root tests in 84 files (27 skipped on Linux), 130 web tests, 9 real-browser scenarios and the 135-member real-pack audit.
@@ -21,7 +21,8 @@ Defaults are loopback `127.0.0.1:17423`, normal Pi agent configuration, and deta
21
21
  An explicit port0 selects and persists a positive port once; restart uses the selected configuration, not a fallback endpoint.
22
22
  Missing/corrupt existing setup is preserved, not filled in or reset.
23
23
  Commands without `--workspace` address the unified workbench, which has no execution cwd and never creates `~/cadence`.
24
- Use `cadence workbench start|status|diagnose|stop|token-link|token-rotate` to name that target explicitly.
24
+ Use `cadence workbench start|status|diagnose|stop|token-link|token-rotate|recover inspect|recover resolve` to name that target explicitly.
25
+ `recover` without `--workspace` also addresses account/workbench state, never the current directory; project-owner recovery requires an explicit `--workspace`.
25
26
  Its start accepts `--foreground`, `--state-home`, `--agent-dir`, `--server-config` and a private `--config` containing an `HttpPolicy` object (the schema used below for project HTTP policy).
26
27
  The configuration's port/token come from the `.env`; a selected HTTP policy is retained across orderly restarts.
27
28
  A project root containing the private state home is refused, with no alternate directory creation; native `/cadence` also requires a real project selection.
@@ -91,6 +92,8 @@ A reinstall without `--workspace` explicitly selects the unified entry after ord
91
92
  A plain `restart` retains the definition's existing target, including an older explicit project service, rather than silently migrating it.
92
93
  The `.env` [port and token](#port-and-token) select the endpoint (17423 by default) and the token; an occupied endpoint fails instead of falling back.
93
94
  Install and restart print the private entry link once the owner answers; the JSON result on stdout never carries the token.
95
+ A successful manager start request is not owner readiness: an unready owner reports `quarantined` or `unconfirmed`, retains the separate `managerStatus`, exits nonzero and names the recovery inspection command.
96
+ Status also retains the manager's `active`/`activating`/`failed` observation separately when the workbench itself is quarantined.
94
97
  `restart` rewrites an existing definition with the current Node and package paths, keeping its workspace and the user's disable choices, and starts it; run it after an npm upgrade, a Node change or a `models.json` edit.
95
98
  `stop` joins the workbench's accepted openings and associated exact-epoch project owners, then closes the entry; unrelated project owners stay independent.
96
99
  If one associated owner refuses or has a changed epoch, Stop still reaches the other known owners serially, while the workbench remains fenced rather than reporting a successful Stop.
@@ -200,7 +203,10 @@ It carries `ConditionPathExists=` for the CLI; explicit single-project definitio
200
203
  `ExecStop` is the authenticated orderly Stop, so admitted work is stopped, not detached; `stop` and `uninstall` (`disable --now`) use it too.
201
204
  `KillMode=mixed` sends systemd's SIGTERM only to the management client.
202
205
  An owner still settling after `TimeoutStopSec=90` (for example a quarantined one) is SIGKILLed, which is not orderly Stop and can leave recovery fences.
203
- `Restart=on-failure` is bounded to three starts in five minutes; a restart never removes fences, so a crashed owner keeps refusing until informed recovery.
206
+ `Restart=on-failure` is bounded to three starts in five minutes.
207
+ Deterministic foreground startup refusals exit78 (`EX_CONFIG`), and newly generated units use `RestartPreventExitStatus=78` so these refusals do not loop.
208
+ Ordinary unexpected process failures retain the bounded restart policy; a restart never removes fences.
209
+ Existing generated units get this setting on the next successful explicit install/restart, not by package installation or recovery.
204
210
  Without linger, user units start at login and stop at logout through the same Stop.
205
211
  Linger starts the user manager, with every enabled user unit, at boot and keeps it running after logout.
206
212
  `status` reports `linger` as `on` or `off`, and Pi's startup card names `loginctl enable-linger` while an enabled unit is login-only; a disabled or masked unit (also `mask --runtime`) keeps it quiet.
@@ -258,7 +264,7 @@ At sign-out or shutdown Windows ends the owner without orderly Stop, which can l
258
264
  Ctrl-C, SIGTERM, machine crash or terminal destruction is **not** the authenticated orderly Stop route and can leave recovery fences.
259
265
  A recovered `stopped` registration means acknowledged fence release, not retroactive native closure certification.
260
266
 
261
- `diagnose` reports fixed pending/recording facts and `proxyAuth: direct|validated-proxy`.
267
+ `diagnose` reports fixed pending/recording facts and `proxyAuth: direct|validated-proxy` when the owner is reachable; a blocked global registry instead reports its fixed lock reason and local recovery hint.
262
268
  No normal status/diagnosis prints access secrets, provider credentials or outbound proxy URLs.
263
269
  Keep the explicitly revealed token link private.
264
270
  Browser entry redirects to a token-free URL and uses an HttpOnly cookie; that does not retract a link already copied into history, a clipboard or external logs.
@@ -296,12 +302,97 @@ Local fabricated-provider plain/gzip routing tests are not paid-provider, all-ad
296
302
  ## Informed local recovery
297
303
 
298
304
  ```sh
305
+ # Account/workbench recovery (no cwd or project required):
306
+ cadence workbench recover inspect
307
+ cadence workbench recover resolve
308
+ # A specific project owner:
299
309
  cadence recover inspect --workspace /absolute/project
300
310
  cadence recover resolve --workspace /absolute/project
301
311
  ```
302
312
 
303
- Inspection is readonly.
304
- It displays the epoch, exact coordination/history digests, owner PID/host observation and independent process/credential/storage uncertainty.
313
+ Inspection is readonly and handles the global registry lock before the selected workbench or project-owner recovery.
314
+ Use the same account and state home as the service; workbench recovery also accepts `--server-config <path>` for a named or custom configuration.
315
+ A recovery refusal reports a fixed code/stage or `blocked-preserve-state`, never raw state/configuration bytes.
316
+ Do not delete state files or move to a different state home to bypass a refusal.
317
+
318
+ ### Residual global registry lock
319
+
320
+ `status` and `diagnose` report `reason: "registry-locked"` and the lock holder observation (`live`, `absent`, `ambiguous` or `unreadable`).
321
+ Project Open reports `registry-locked` instead of an opaque `unavailable`; the folder picker explains the local recovery command.
322
+ This lock is shared by every project in the selected state home, so trying a different project does not bypass it.
323
+ Use the same account and `--state-home` as the owner; omit that flag only when it uses the default state home:
324
+
325
+ ```sh
326
+ cadence recover inspect --workspace /absolute/project --state-home /absolute/state-home
327
+ cadence recover resolve --workspace /absolute/project --state-home /absolute/state-home
328
+ ```
329
+
330
+ With a registry lock present, inspection reports `scope: "global-registry"`, the exact lock-incarnation digest, holder PID/host, reservation count and any previous resolver's liveness.
331
+ A project with no selected owner can be used to address this global operation; explicit `--workspace` must still name an existing suitable directory.
332
+ Alternatively, `cadence workbench recover inspect|resolve --state-home <path>` addresses the same global lock without any project directory or workbench registration, including from outside a project or when every old project directory is gone.
333
+ Resolve requires the same four fresh local-terminal acknowledgments described below, with the displayed lock-incarnation digest instead of a service epoch.
334
+ The holder must be on this host and its PID probe must specifically report absence; age, a remote host, permission denial or a reused live PID never authorizes release.
335
+
336
+ Recovery validates the registry and checks that unreserved project selections have no remaining owner/checkout fences.
337
+ A normally stopped project whose working directory was later removed is checked through its retained private metadata; recovery neither requires nor reconstructs that directory.
338
+ A still-reserved project whose working directory was removed also remains a valid retained reservation: canonical existing ancestors and overlap/endpoint constraints are checked without requiring the missing tail.
339
+ Its reservation, owner/checkout locks and history remain fenced and unchanged; releasing the global lock only restores access to independent projects.
340
+ Dangling/rebound aliases, permission errors and corrupt entries are not treated as absent directories.
341
+ An interrupted reservation remains reserved even when its project initialization is incomplete: unrelated projects can reopen, but that project's uncertain resources are not repaired.
342
+ An older release interrupted after removing a reservation but before releasing its project locks is unsafe and remains blocked, as do corrupt/partial registry bytes, linked files and changed resources.
343
+ Inspection reports `blocked-preserve-state` when it cannot establish those conditions; preserve that state for manual diagnosis rather than deleting locks.
344
+
345
+ Before releasing only `registry.lock`, the resolver exclusively creates, flushes and closes a private receipt under `service-registry-v1/recovery-v1/<lock-incarnation>/<attempt>.json`, retaining the original lock bytes and acknowledged digest.
346
+ It then rechecks the lock incarnation, registry, unreserved project selections, receipt and terminal authority.
347
+ Concurrent resolvers cannot release a successor lock.
348
+ If a resolver dies after the receipt but before release, a new inspection and fresh terminal confirmation may append the next attempt after that resolver's same-host PID is absent; neither receipt nor lock is silently reclaimed.
349
+ Torn or unsafe receipts remain preserved and refused.
350
+ Inspection is bounded to 1024 namespace entries and 128 attempts for one lock incarnation; it never evicts evidence to make space.
351
+
352
+ All project reservations, owner locks, checkout locks, capabilities, history and unknown outcomes remain unchanged.
353
+ No Open/Start is replayed, no process is signaled, and no service is installed or started by recovery.
354
+ After success, explicitly open the desired project again.
355
+ If its own owner is still fenced, run `recover inspect` again and follow project-owner recovery separately; restoring global registry access does not certify or release that owner's work.
356
+
357
+ ### Workbench recovery
358
+
359
+ After a crash or failed Stop, an `alive`, `stopping` or `quarantined` registration may outlive its gateway process.
360
+ Do not keep restarting it or delete `workbenches-v1`; inspect the exact selection instead:
361
+
362
+ ```sh
363
+ cadence workbench recover inspect --server-config /absolute/cadence.env --state-home /absolute/state-home
364
+ cadence workbench recover resolve --server-config /absolute/cadence.env --state-home /absolute/state-home
365
+ ```
366
+
367
+ If the first inspection reports `scope: "global-registry"`, resolve that lock first, then inspect again for `scope: "workbench"`.
368
+ Prevent the supervisor from repeatedly launching the old process while recovering; use its original account/scope and inspect processes externally.
369
+ A live owner, a known remote host, permission-denied PID probe, changed bytes/incarnations, linked or partial state, or a live/ambiguous resolver refuses release.
370
+ PID absence alone never grants recovery; the same four fresh terminal acknowledgments bind the exact workbench epoch and selected resources.
371
+
372
+ New registrations record their hostname.
373
+ Older registrations did not: inspection explicitly reports `legacyHost: true`, `host: null` and `local-host-confirmation-required`, not proven same-host absence.
374
+ Resolve then additionally requires typing `local-host` after independently establishing that this state originated on this host and was not copied/shared from another host.
375
+ If that provenance cannot be established, do not confirm; preserve the state for manual diagnosis.
376
+ This attestation cannot override a recorded foreign hostname or a live/ambiguous local PID.
377
+ No `--yes`, piped or pasted answers, browser recovery or implicit takeover is supported.
378
+
379
+ Before release, an exclusive immutable receipt under `workbenches-v1/<configuration-hash>/recovery-v1/<lock-incarnation>/<attempt>.json` is flushed and closed.
380
+ The resolver then rechecks the resources, receipt, owner absence and fresh terminal authority, marks only the gateway registration stopped and releases only its exact gateway lock.
381
+ Concurrent resolvers cannot release a successor lock; a resolver that crashed after its receipt can be superseded only after its same-host PID is absent and another fresh confirmation.
382
+ A stopped registration is eligible only when its pinned recovery receipt belongs to that exact lock incarnation; an interrupted new startup cannot borrow the predecessor's dead PID to release its new fence.
383
+ Partial/corrupt receipts remain preserved; there are at most128attempts per lock incarnation, with no evidence eviction.
384
+
385
+ Recovery also acknowledges and retires the gateway's **exact old project associations**, recorded by their reference-file incarnations in that receipt.
386
+ It does not delete those recent-project references or settle/stop their owners: all project registrations, reservations, locks, opening receipts and history remain unchanged, including unknown outcomes and unfinished Open operations.
387
+ This prevents a deleted old project from immediately quarantining the recovered workbench again on its next Stop.
388
+ Old references require a new explicit **Open** before proxy access or whole-workbench Stop associates them again; merely restarting, viewing the recent list or recovering never replays an Open.
389
+ After recovery, explicitly start/restart the workbench.
390
+ Separately inspect/recover any still-fenced project owner before opening it.
391
+ The receipt is operator acknowledgment, not proof of native process closure or credential/storage correctness.
392
+
393
+ ### Project-owner recovery
394
+
395
+ With no registry lock present, inspection displays the epoch, exact coordination/history digests, owner PID/host observation and independent process/credential/storage uncertainty.
305
396
  Those digests identify preserved resources, not successful work or credential validity.
306
397
  A journal with no unmatched intent does not prove every escaped descendant or external credential writer stopped.
307
398
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abelxiaoxing/cadence",
3
- "version": "2.0.14",
3
+ "version": "2.0.16",
4
4
  "description": "Shared Pi task workspace: native terminal and WebUI, persistent service, checks and human review.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -2,5 +2,5 @@
2
2
  export const nativeBuild = {
3
3
  kind: "native",
4
4
  contractHash:
5
- "9c917c085d034e08764de359cee49aea748c395a63ed629fe67d149b97850fa1",
5
+ "944f3b53bd5b7f1d3f30868e0947d900e356ae9a2bcfb9f591edd988b3d5eb3a",
6
6
  } as const;