@abelxiaoxing/cadence 2.0.16 → 2.0.17

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
@@ -141,13 +141,18 @@ The unified browser entry opens on the conversation shell, without an execution
141
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.
142
142
  Only explicit Open starts or reuses a project owner.
143
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.
144
- Use `cadence <goal>` or `/cadence <goal>` at the beginning of the input, or select Cadence task, to prepare a separate task.
144
+ Use `cadence <goal>` or `/cadence <goal>` at the beginning of the input, or select Cadence task, then Send to create a task in the background and begin readonly analysis.
145
+ New task opens the same composer in task mode; there is no task-kind picker or creation dialog.
145
146
  Mentions, quotations and fenced code do not select task mode.
146
- Create is not Start: the readable plan, explicit Start, exact configured checks and human review remain separate.
147
+ Analysis appears in the task transcript.
148
+ Review implementation plan opens the retained proposal for one explicit Confirm plan and execute approval: save those exact bytes, then start only the matching graph under a fresh grant.
149
+ Changed context, failed publication or an uncertain reply stops the sequence without automatic retry.
150
+ Configured checks and human review remain separate.
147
151
  A task created from an existing ordinary conversation retains a navigation link back; the old conversation is not converted and its history is not silently injected into the task.
148
152
  All of this works without a live Pi terminal.
149
153
  A token grants workspace access, not action consent.
150
- Cadence task mutations need their own context-bound preview/confirmation.
154
+ Task Send authorizes only creation and readonly analysis.
155
+ Editing requires context-bound plan confirmation; the advanced inspector retains independent Save/Start controls.
151
156
  Ordinary Send binds its exact text, conversation head, epoch, access and selected model; stale/duplicate/lost replies do not silently replay work.
152
157
  The WebUI provides task/run/assignment navigation, long retained messages and tool detail, exact literal search, timeline and complete scoped NDJSON/Markdown downloads.
153
158
  Desktop panes and phone drawers retain cancellation and keyboard controls.
@@ -279,8 +284,9 @@ bun pm pack --destination /absolute/private-temp
279
284
 
280
285
  Build/verification use a fresh private directory with `TMPDIR`, `TEMP` and `TMP` set explicitly, on the checkout's disk filesystem rather than a nearly full tmpfs.
281
286
  `verify` includes native/unit tests, web tests, required real-browser scenarios and exact real-pack auditing; missing required browser is non-green, never an automatic download.
282
- It needs a Node with TypeScript type stripping (official builds; a distro Node built without it fails `build:web:check`) and NSS `certutil` for the isolated HTTPS browser scenario.
283
- Source/extracted PTYs, fabricated loopback providers and isolated HTTPS are distinct from physical humans/devices, paid accounts, package-manager installation and native Windows/macOS/ConPTY qualification.
287
+ It needs a Node with TypeScript type stripping (official builds; a distro Node built without it fails `build:web:check`).
288
+ `verify` keeps short regressions and loopback browser scenarios; it runs no real PTY workflow, HTTPS-proxy browser lane or multi-MiB cold-history scan.
289
+ Fabricated loopback providers are distinct from physical humans/devices, paid accounts, package-manager installation and native Windows/macOS/ConPTY qualification.
284
290
  Those additional lanes remain unqualified unless their own receipts exist.
285
291
  No passing gate authorizes commit, push, publication, installation, deployment or cleanup.
286
292
 
@@ -510,9 +516,8 @@ Correct: expose bounded continuations/full exports and report the exact executed
510
516
  Read affected source and adjacent tests, identify the actual owner of a contract, then make the smallest coherent change.
511
517
  Use ordinary source editing and directly affected checks while developing; independently review complete capabilities and run full `verify` at stable integration boundaries.
512
518
  Do not run the entire suite after every local edit, but do not replace final integration with unit mocks or citation counts.
513
- `bun run test` runs unit files in parallel, then `serialProcessFiles` (real PTY/SDK process flows) and `serialScanFiles` (>8MiB cold scans) from `vitest.config.ts` one at a time; a file belongs there only when it measurably exceeds its own waits under shared CPU.
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.
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.
519
+ `bun run test` runs every root file in one parallel group; there are no serial groups or separate fast/integration lanes.
520
+ Its workers load `test/no-fsync.mjs`, which makes fsync a no-op inside them (spawned owners and CLIs still flush): crash tests kill processes and no test simulates power loss.
516
521
  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
522
  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.
518
523
  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.
@@ -523,18 +528,17 @@ Preserve failed attempts; correct a demonstrated cause before rerunning, and nev
523
528
  Regression owners:
524
529
 
525
530
  - `service-contract`, `service-current`, `service-model-choice`, `service-auth`: closed DTOs, exact source/choice/current authority, security and compatibility.
526
- - `service-owner`, `service-accepted-work`, `service-stop-continuation`, `service-recovery`, `service-registry-recovery`: original operations, overlap, Stop, unknown fences and informed recovery.
527
- - `service-scheduler`, `service-checks`, `service-human-review`, `service-accepting-host`: real SDK overlap/exclusion, native checks, review and publication.
531
+ - `service-owner`, `service-accepted-work`, `service-recovery`, `service-registry-recovery`: original operations, overlap, Stop, unknown fences and informed recovery.
528
532
  - `worker-*`, `lightweight-sdk`, `lightweight-process-diff`: genuine SDK/tool capture, split redaction, no-spill bounds and original native facts.
529
533
  - `service-history-*`: durable ordering, cold/no-index/restarted proof/search/export, corruption/torn/quota and expected-byte publication.
530
- - `lightweight-shell`, `native-client`, `native-history`, `terminal-integration`: native consent, shared service, Unicode/paging, detach/cancel and actual source/extracted PTYs.
534
+ - `lightweight-shell`, `native-client`, `native-history`, `terminal-integration`: native consent, shared service, Unicode/paging and detach/cancel.
531
535
  - `agent-panel`, `agent-panel-model`, `agent-panel-cadence`: panel keys/rendering and readonly owner observation that never starts, cancels or replays work.
532
- - `test/web/`: adapted pure/SSR tests separately from actual built-browser contexts, HTTPS, mixed clients, focus/viewports and complete downloads.
536
+ - `test/web/`: adapted pure/SSR tests separately from actual built-browser contexts; `accepting-browser` drives one real SDK Start, check, review and departure-without-cancel workflow with mixed clients, focus/viewports and complete downloads.
533
537
  - `package-*`, `distribution`, `service-package`, `independence`: exact tar/member/body/import/notice closure and nonactivating discovery.
534
538
  - `service-autostart`, `project-start`, `install-config`: explicit `cadence server` registration on systemd (root system scope without linger, legacy user scope), launchd and the Windows Run key, separate named service definitions and directory owners, definition escaping, restart/disable/mask/foreign handling, orderly Stop before every change, the `.env` port and token lines and a package without install scripts.
535
539
  - `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.
536
540
  - `workspace-landing`: no-default-workspace startup, explicit root refusal and noncreating native/readonly entry.
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.
541
+ - `gateway-browser`: real same-origin project routing, browser-only authority, retirement on token rotation, continuing ordinary work and genuine multi-owner Stop over loopback.
538
542
  - `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.
539
543
 
540
544
  Regenerate operator/service/native/browser outputs only through their canonical builders; `--check` variants compare new private output without overwriting canonical bytes.
@@ -542,14 +546,21 @@ WebUI text is keyed by its English source: fixed text goes through `useT().t`, w
542
546
  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`.
543
547
  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
548
  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.
549
+ The bottom-right folder control is always present, and its picker lists recent projects.
550
+ Conversation history belongs to each project owner, so the unselected entry's history section says so and lists the recent projects; choosing one only preselects its folder in the picker.
551
+ An unselected first entry returns to the last selected project, remembered only in that browser as its opaque key, after one readonly conversation listing proves that owner still runs in its associated epoch; this is navigation, never Open.
552
+ A stopped, changed or unknown owner stays stopped: the entry remains and names the last project as not running, and any navigation, Open or folder choice during the check wins.
546
553
  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.
554
+ The picker has no separate Browse step: its location trail, folder list and Enter in the path entry navigate, and the footer names the exact Open target.
555
+ Open of a typed or recent path first makes one fresh readonly observation and opens only that observation's canonical folder; a failed read opens nothing and keeps the typed path and previous listing in view.
556
+ The footer Open is disabled while any observation is pending, including the first one; a recent entry still opens, because its own fresh observation supersedes the pending read.
557
+ Every navigation makes a fresh readonly observation, including retrying the same path after a read failure; it never replays Open.
558
+ Folder browsing (not Open) accepts `~` for the service account's home and reports a missing folder as `invalid`, a file or linked component as `forbidden` and a read failure as `unavailable`; the gateway passes these public codes on so the picker can explain them.
549
559
  One service still owns one checkout.
550
560
  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.
551
561
  The center shows ordinary streamed messages or retained task text as Markdown.
552
- Task tools/context/timeline/run facts and export/link actions live under Details.
562
+ Task tools/context/timeline/runs and export/link actions live under Details, shown only for a task or child scope; an ordinary conversation has no view switch and folds its tool calls into the transcript.
563
+ Runs puts the current snapshot's owner projection above the retained run pages.
553
564
  The right panel defaults to files; its Task details inspector remains bound to the task's current plan/check/change/review context even when viewing a child.
554
565
  Historical child links bind exact scope and watermark.
555
566
  Bounded history and Back never silently rebase; running conversations offer an explicit new-activity update, and source limitations/progress stay visible even when complete-record metadata is folded.
@@ -560,6 +571,17 @@ Review the independently enumerated package member list and every emitted body,
560
571
  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.
561
572
  Preserve original license bytes through their precise Git attributes; line-ending normalization must not invalidate audited source/notice hashes.
562
573
 
574
+ ### Release 2.0.17 acceptance snapshot
575
+
576
+ Full `verify` passed on the release candidate in about four minutes: 1908 root tests in 71 files (27 platform skips on Linux), 16 task-entry node tests, 136 web tests, 5 real-browser scenarios in 4 files and the 135-member real-pack audit.
577
+ Observed environment: Linux x86_64, official Node 22.22.1, Bun 1.3.14, Pi SDK 0.84.3 and Chrome for Testing 153.0.8010.12, with four root workers and unchanged test deadlines.
578
+ `verify` no longer runs the slow real-process, PTY, HTTPS-proxy browser and multi-MiB cold-scan suites; those behaviors are not regression-gated in this release.
579
+ Task Send creates a task and starts readonly analysis, and one Confirm plan and execute saves and starts the reviewed plan.
580
+ Fixes in that flow: a fenced receipt read is observed again instead of ending the sequence, a transient context gap no longer aborts an in-flight approval, and a failed observation is re-read after 2s rather than leaving actions disabled until the 30s reconcile.
581
+ Ordinary conversations show no recorded-view switch, and Runs includes the current snapshot's owner projection.
582
+ The first merged attempts failed a time-budgeted search page and the new plan-approval browser step, which also failed on its original commit; both causes were fixed, not retried around.
583
+ No consumer service was installed or restarted, no paid provider was used and no native Windows/macOS qualification is claimed; the `ci/windows` matrix still names the removed vitest projects and was not run.
584
+
563
585
  ### Release 2.0.16 acceptance snapshot
564
586
 
565
587
  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.
@@ -48,7 +48,7 @@ Keep that link private.
48
48
  Open Pi in the same project and use `/cadence` for the native client; explicit `cadence stop --workspace <path>` stops only that project.
49
49
  Opening another project never changes the cwd or cancels work in the former one.
50
50
  The default workbench routes all associated projects through one origin, including a configured HTTPS proxy.
51
- Its project picker browses directory names readonly; only **Open this project** starts or reuses an owner, without admitting a task or model call.
51
+ Its project picker browses directory names readonly (`~` names the service account's home); only **Open this folder**, or one click on a recent project, starts or reuses an owner, without admitting a task or model call.
52
52
  Project navigation remounts only the browser client; the original owner's work continues.
53
53
  Browser proxy traffic keeps browser authority and the owner's own attachments, CSRF/build checks, grants and history proofs; native management routes and local-capability headers are not forwarded.
54
54
  The gateway also refuses the legacy project-level Open command, so every opening is associated through the workbench instead of returning an independent backend token link.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abelxiaoxing/cadence",
3
- "version": "2.0.16",
3
+ "version": "2.0.17",
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",
@@ -87,7 +87,7 @@
87
87
  "build:operator": "bun scripts/build-operator.mjs",
88
88
  "build:service": "bun scripts/build-service.mjs",
89
89
  "check:web": "tsc -p web/tsconfig.json && tsc -p web/tsconfig.config.json",
90
- "test:web": "vitest run --config web/vitest.config.ts",
90
+ "test:web": "node --test test/web/task-entry.node.mjs && vitest run --config web/vitest.config.ts",
91
91
  "build:web": "node scripts/build-web.mjs",
92
92
  "build:web:check": "node scripts/build-web.mjs --check",
93
93
  "test:web:assets-browser": "bun run test:browser",
@@ -9,7 +9,7 @@ import {
9
9
  createServer as createServer2,
10
10
  request as request2
11
11
  } from "node:http";
12
- import { homedir as homedir4 } from "node:os";
12
+ import { homedir as homedir5 } from "node:os";
13
13
  import { WebSocket, WebSocketServer as WebSocketServer2 } from "ws";
14
14
 
15
15
  // src/service-assets.ts
@@ -9772,6 +9772,7 @@ import {
9772
9772
  readSync as readSync4,
9773
9773
  realpathSync as realpathSync3
9774
9774
  } from "node:fs";
9775
+ import { homedir as homedir4 } from "node:os";
9775
9776
  import { dirname as dirname10, isAbsolute as isAbsolute6, join as join12, relative as relative5, resolve as resolve6, sep as sep4 } from "node:path";
9776
9777
 
9777
9778
  // src/worker-redaction.mjs
@@ -10176,8 +10177,18 @@ class WorkbenchFiles {
10176
10177
  throw new ContractError("forbidden");
10177
10178
  return target;
10178
10179
  }
10180
+ browsed(path) {
10181
+ const full = /^~(?:[\\/]|$)/.test(path) ? join12(homedir4(), path.slice(1)) : path || this.root;
10182
+ try {
10183
+ return this.directory(full);
10184
+ } catch (error) {
10185
+ if (error instanceof Error && error.message === "Unsafe directory")
10186
+ throw new ContractError("forbidden");
10187
+ throw error;
10188
+ }
10189
+ }
10179
10190
  list(path, directories = false) {
10180
- const selected2 = directories ? this.directory(path || this.root) : this.selected(path);
10191
+ const selected2 = directories ? this.browsed(path) : this.selected(path);
10181
10192
  if (!safeDirectory(selected2) || sanitizeText(selected2, this.secrets()) !== selected2)
10182
10193
  throw new ContractError("forbidden");
10183
10194
  const entries = [], dir = opendirSync5(selected2);
@@ -10370,7 +10381,7 @@ Content-Length: 0\r
10370
10381
  server.close();
10371
10382
  throw error;
10372
10383
  }
10373
- const files = new WorkbenchFiles(homedir4(), [store.files.namespace, input.agentDir], () => acquired.access.redactionLiterals());
10384
+ const files = new WorkbenchFiles(homedir5(), [store.files.namespace, input.agentDir], () => acquired.access.redactionLiterals());
10374
10385
  const assert = () => {
10375
10386
  store.assert();
10376
10387
  if (!accepting)
@@ -10730,7 +10741,7 @@ Content-Length: 0\r
10730
10741
  kind: "workbench",
10731
10742
  epoch: auth.epoch,
10732
10743
  csrf: auth.csrf,
10733
- home: homedir4(),
10744
+ home: homedir5(),
10734
10745
  projects: store.projects(),
10735
10746
  build: build2
10736
10747
  });