@abelxiaoxing/cadence 2.0.11 → 2.0.13

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
@@ -136,7 +136,10 @@ A token grants workspace access, not action consent.
136
136
  Every mutation needs its own context-bound preview/confirmation; stale/duplicate/lost replies do not silently replay work.
137
137
  The WebUI provides task/run/assignment navigation, long retained messages and tool detail, exact literal search, timeline and complete scoped NDJSON/Markdown downloads.
138
138
  Desktop panes and phone drawers retain cancellation and keyboard controls.
139
- 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.
139
+ Its layout follows pi-web-ui: the topbar shows the connection state, every recorded view as a tab, icon actions, the exact owner model and a **New task** chip; the left sidebar lists the project, running conversations and task history, each task's runs and subagents nested under it; the right panel holds the task's plan, checks, changes and review; a statusbar sits below.
140
+ With no task selected the page is pi's new conversation: a welcome page with starter cards above a composer whose Enter previews Create (kind and model chips beside it), and a confirmed Create opens its new task.
141
+ A selected task shows its conversation and, where the composer sits, a next-step bar (goal → plan → start → check and review) whose buttons only open panels or request previews; every effect still needs its own confirmation.
142
+ Phones wrap the topbar into an action row and an icon tab row, with both panels as drawers.
140
143
  The interface is in English or Simplified Chinese: it follows the browser's first preferred language, and the topbar's globe chip (`中文` / `EN`) switches it, remembered only in that browser.
141
144
  Error codes, identifiers, commands and recorded content stay untranslated.
142
145
 
@@ -323,6 +326,11 @@ Task v1 remains a strict human-readable summary; rich graph/transcript data neve
323
326
  `TaskStore.loadSnapshot` includes raw-byte identity; save/publication requires exact expected bytes and revision.
324
327
  A same-revision external edit conflicts and remains preserved.
325
328
  Summary clipping is labeled and never clips retained detail; a subsequent publication failure remains separate from previously completed execution.
329
+ A retained task may have no live `task.json` (for example after a workspace rebuild).
330
+ Current reads then retain the requested task ID in an unavailable context, with no live task/plan or action authority; history snapshots and retained content remain readable without reconstructing the summary.
331
+ Stable absence is not `stale`; appearance/disappearance or changed identities during an observation still are.
332
+ Generic `stale` requests fresh observation/confirmation, not a diagnosis that `models.json` changed or an instruction to restart; build compatibility is evaluated separately from the session and independently built client identities.
333
+ Local operation errors neither hide an independent observation error nor imply that the service needs to be started.
326
334
 
327
335
  ### Capture, retained history and privacy
328
336
 
@@ -462,9 +470,13 @@ WebUI text is keyed by its English source: fixed text goes through `useT().t`, w
462
470
  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`.
463
471
  The browser is conversation-first: the left panel groups the current service project, the actual active roster and retained task conversations, with run/subagent children under their task.
464
472
  One service still exposes one checkout; the project section is not a cross-project registry, Pi session importer or cwd switcher.
465
- The center shows retained message text as Markdown by default; tools/context/timeline/run facts and export/link actions live under Details, while the collapsible right inspector remains bound to the task's current plan/check/change/review context even when viewing a child.
473
+ The center shows retained message text as Markdown by default; tools/context/timeline/run facts are direct topbar tabs beside export/link actions, while the collapsible right inspector remains bound to the task's current plan/check/change/review context even when viewing a child.
474
+ With no task selected the center is the new-task composer; Enter only requests a Create preview, and a followed Create receipt opens its task once published.
475
+ A selected task's next-step bar derives its step from the saved graph revision, observed runs and the active roster (the Cancel authority); it opens inspector tabs or requests Generate/Start previews.
476
+ An observation poll withholds action capability while it reads, which invalidates an open confirmation, so automatic follow-ups (receipt lookups, roster rereads after a run settles) never poll or navigate while a preview is prepared or confirmed.
477
+ A failed poll is observed again after 2s, doubling to the 30s cadence; the owner can answer a read `receipt-inconclusive` briefly while it publishes.
466
478
  Historical child links bind exact scope and watermark.
467
- 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.
479
+ Bounded history and Back never silently rebase; a conversation that fits its first page follows newer snapshots with one bounded read at a time, paged history offers an explicit new-activity update, and source limitations/progress stay visible even when complete-record metadata is folded.
468
480
  Cancel uses the independent active roster (including the fallback strip when workspace discovery fails); navigation, project selection and hiding panels never cancel or authorize execution.
469
481
 
470
482
  Publish `web/dist` from Node: Vite run under Bun lays out its preload helper differently, so a Bun build fails a Node `build:web:check`.
@@ -472,6 +484,23 @@ Review the independently enumerated package member list and every emitted body,
472
484
  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.
473
485
  Preserve original license bytes through their precise Git attributes; line-ending normalization must not invalidate audited source/notice hashes.
474
486
 
487
+ ### Release 2.0.13 acceptance snapshot
488
+
489
+ Full `verify` passed on the 2.0.13 release candidate before this evidence-only paragraph: 1983 root tests in 80 files (27 skipped on Linux), 133 web tests, 6 real-browser scenarios and the 132-member pack audit.
490
+ Observed environment: Linux x86_64, Node22.22.1, Bun1.3.14, Pi SDK0.84.3 and existing Chrome for Testing153.0.8010.12.
491
+ The WebUI follows pi-web-ui's new-conversation layout: a bottom composer whose Enter only previews Create, starter cards that only fill the draft, a next-step bar per task, direct topbar view tabs and a New task chip; a followed Create receipt opens the created task.
492
+ The accepting-browser scenario first failed with Confirm start disabled because automatic follow-ups polled while a confirmation was open; they now skip while a preview is prepared or confirmed.
493
+ Service contracts are unchanged; no new Windows/macOS, real service-manager installation or paid-provider qualification is claimed.
494
+
495
+ ### Release 2.0.12 acceptance snapshot
496
+
497
+ Full `verify` passed on the 2.0.12 release candidate before this evidence-only paragraph: 1983 root tests in 80 files (27 skipped on Linux), 128 web tests, 6 real-browser scenarios and the 132-member pack audit.
498
+ Observed environment: Linux x86_64, Node26.7.0, Bun1.3.14, Pi SDK0.84.3 and existing Chrome for Testing151.0.7922.34.
499
+ Retained conversations remain readable after their live `task.json` disappears and the owner restarts without a selected model; reads neither reconstruct live state nor grant execution authority, and an unused Start grant from before removal is refused without admission.
500
+ Generic stale guidance asks for fresh observation/confirmation without diagnosing a model-source change; local errors no longer hide that observation or suggest starting the service.
501
+ The local-error banner regression failed against the prior built assets and passed against the rebuilt candidate; a new Chinese assertion was corrected to expect its translated status, and an initial integration attempt stopped at provenance JSON formatting before the final full pass.
502
+ No new Windows/macOS, real service-manager installation or paid-provider qualification is claimed.
503
+
475
504
  ### Release 2.0.11 acceptance snapshot
476
505
 
477
506
  Full `verify` passed on the 2.0.11 release candidate before this evidence-only paragraph: 1976 root tests in 80 files (27 skipped on Linux), 122 web tests, 5 real-browser scenarios and the 132-member pack audit.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abelxiaoxing/cadence",
3
- "version": "2.0.11",
3
+ "version": "2.0.13",
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
- "c2bb81519387005a71e88a64364dff47d5c39dab17812833ca898bc51055e59d",
5
+ "e9b1ea4bb8d1c275a0cb0cf70947f9ac58e5de0cc438d551dc96809f3e82dd7c",
6
6
  } as const;
@@ -55,6 +55,8 @@ export interface CurrentView {
55
55
  epoch: string;
56
56
  committedSeq: string;
57
57
  context: ControlContext;
58
+ /** Null when no live record is available, even for a non-null request.taskId.
59
+ * This conveys no retained membership or permission to recreate the task. */
58
60
  task: CurrentTask | null;
59
61
  roles: RoleSelection[];
60
62
  readablePlan: null | {
@@ -131,8 +133,13 @@ function correlate(v: {
131
133
  context: ControlContext;
132
134
  task: CurrentTask | null;
133
135
  }) {
136
+ // A requested task without a live record (retained-only history) may answer
137
+ // with task: null while its context reports unavailable for that same task.
138
+ const taskMatches = v.task
139
+ ? v.task.id === v.request.taskId
140
+ : v.request.taskId === null || v.context.status === "unavailable";
134
141
  if (
135
- v.request.taskId !== (v.task?.id ?? null) ||
142
+ !taskMatches ||
136
143
  controlWorkspace(v.context) !== v.workspaceId ||
137
144
  controlTask(v.context) !== v.request.taskId
138
145
  )
@@ -3870,7 +3870,8 @@ function savedGraph(v) {
3870
3870
  return { status: "unavailable", error: noEffect2(o.error) };
3871
3871
  }
3872
3872
  function correlate(v) {
3873
- if (v.request.taskId !== (v.task?.id ?? null) || controlWorkspace(v.context) !== v.workspaceId || controlTask(v.context) !== v.request.taskId)
3873
+ const taskMatches = v.task ? v.task.id === v.request.taskId : v.request.taskId === null || v.context.status === "unavailable";
3874
+ if (!taskMatches || controlWorkspace(v.context) !== v.workspaceId || controlTask(v.context) !== v.request.taskId)
3874
3875
  invalid();
3875
3876
  if (v.context.status === "available") {
3876
3877
  const c = v.context.version;
@@ -22190,8 +22191,6 @@ class TaskActions {
22190
22191
  const access = this.currentAccess();
22191
22192
  const committedSeq = snapshot ?? h.writer.committedSeq;
22192
22193
  const selected2 = taskId ? h.coordination.store.loadSnapshot(taskId) : null;
22193
- if (taskId && !selected2)
22194
- throw new ContractError("stale");
22195
22194
  if (selected2 && realpathSync6(selected2.record.cwd) !== this.cwd)
22196
22195
  throw new ContractError("unsupported-context");
22197
22196
  const secrets = this.viewSecrets();
@@ -22204,7 +22203,7 @@ class TaskActions {
22204
22203
  const plan = selected2 ? sanitizeText(selected2.record.plan, secrets) : null;
22205
22204
  const editable = selected2 ? plan === selected2.record.plan : true;
22206
22205
  let descriptor = null;
22207
- let unavailable2 = null;
22206
+ let unavailable2 = taskId && !selected2 ? publicError("unavailable") : null;
22208
22207
  let saved = { status: "none" };
22209
22208
  if (selected2) {
22210
22209
  try {
@@ -22328,6 +22327,8 @@ class TaskActions {
22328
22327
  if (request.storeId !== this.options.host.reader.storeId)
22329
22328
  throw new ContractError("stale");
22330
22329
  const { view, changes, observation, secrets } = this.observeCurrent(request.taskId);
22330
+ if (!view.task)
22331
+ throw new ContractError("unavailable");
22331
22332
  const text2 = sanitizeText(changes.text, secrets);
22332
22333
  return decodeCurrentChanges({
22333
22334
  request,
@@ -22398,7 +22399,7 @@ class TaskActions {
22398
22399
  checkObligations(taskId) {
22399
22400
  const { view, assertCurrent } = this.observeCurrent(taskId);
22400
22401
  if (!view.task)
22401
- throw new ContractError("stale");
22402
+ throw new ContractError("unavailable");
22402
22403
  const checks = this.obligationsFor(taskId, view.task.kind, view.context, view.committedSeq).checks;
22403
22404
  assertCurrent();
22404
22405
  return checks;
@@ -22923,7 +22924,7 @@ function refuseAt(stage, step) {
22923
22924
  }
22924
22925
  }
22925
22926
  async function createServiceHost(value, sourceBuild) {
22926
- const embedded = "c2bb81519387005a71e88a64364dff47d5c39dab17812833ca898bc51055e59d";
22927
+ const embedded = "e9b1ea4bb8d1c275a0cb0cf70947f9ac58e5de0cc438d551dc96809f3e82dd7c";
22927
22928
  if (embedded && sourceBuild)
22928
22929
  throw new ContractError("unsupported-context");
22929
22930
  const contractHash = decodeHash(embedded ?? sourceBuild?.contractHash);