From 6ecf55ee25f17fedea9b2098e401343c1fb986a2 Mon Sep 17 00:00:00 2001 From: Yuto Nishida Date: Sat, 24 Oct 2026 11:28:00 -0700 Subject: [PATCH] papyrus: use explicit Silverwood listing targets --- experimental/papyrus/DESIGN.md | 2 +- experimental/papyrus/TODO.md | 2 +- experimental/papyrus/client/src/stores/useStore.ts | 2 +- experimental/papyrus/server-tests/api.e2e.test.ts | 4 ++-- .../papyrus/server-tests/silverwood-contract.test.ts | 2 +- experimental/papyrus/server/routes/api.ts | 2 +- experimental/papyrus/server/services/silverwood.ts | 6 +++--- experimental/papyrus/server/services/tabOrder.ts | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/experimental/papyrus/DESIGN.md b/experimental/papyrus/DESIGN.md index bacdbb8..842fd4b 100644 --- a/experimental/papyrus/DESIGN.md +++ b/experimental/papyrus/DESIGN.md @@ -50,7 +50,7 @@ papyrus's own direction. ## The silverwood seam (how papyrus works) -A canvas **node is a silverwood workstream** (1:1). `silverwood --json ls` drives the +A canvas **node is a silverwood workstream** (1:1). `silverwood --json ls workstream` drives the canvas; creating a node runs `silverwood new` (which clones the checkout); deleting it `archive`s the workstream. Every per-node property lives in silverwood — papyrus keeps no private state of its own: diff --git a/experimental/papyrus/TODO.md b/experimental/papyrus/TODO.md index fec9be9..fe298e1 100644 --- a/experimental/papyrus/TODO.md +++ b/experimental/papyrus/TODO.md @@ -12,7 +12,7 @@ Legend: `[ ]` pending · `[~]` in progress · `[x]` done - [x] soup re-export (`git+file` input + `pkgs/papyrus.nix` + `extraPackages.nix`) ## Part 1 — silverwood integration (the point of papyrus) — DONE -- [x] A canvas node IS a silverwood workstream; `silverwood --json ls` drives the canvas +- [x] A canvas node IS a silverwood workstream; `silverwood --json ls workstream` drives the canvas - [x] All state in silverwood: coordinate/color/notes in `app.andref.papyrus` KV, name via `silverwood rename`, agent runs as silverwood sessions - [x] Replace openui's `.openui/state.json` model — `server/services/silverwood.ts` is the diff --git a/experimental/papyrus/client/src/stores/useStore.ts b/experimental/papyrus/client/src/stores/useStore.ts index 6b1ce97..98a52a5 100644 --- a/experimental/papyrus/client/src/stores/useStore.ts +++ b/experimental/papyrus/client/src/stores/useStore.ts @@ -43,7 +43,7 @@ export interface Agent { icon: string; } -// One attached silverwood session = one tab. Projected from `session ls` + the +// One attached silverwood session = one tab. Projected from `ls session` + the // server's live-PTY overlay + the advisory lock. Normally `sessionId` is durable; // during a fresh Codex launch it is temporarily the stable live WebSocket key. export interface SessionTab { diff --git a/experimental/papyrus/server-tests/api.e2e.test.ts b/experimental/papyrus/server-tests/api.e2e.test.ts index 30613d2..5afaf11 100644 --- a/experimental/papyrus/server-tests/api.e2e.test.ts +++ b/experimental/papyrus/server-tests/api.e2e.test.ts @@ -70,7 +70,7 @@ describe("papyrus routes → silverwood (in-process, skip-mode)", () => { expect(ns[0].customName).toBe("web"); expect(ns[0].position).toEqual({ x: 10, y: 20 }); // Ground truth: it's a real workstream in silverwood. - expect((cli(["ls"]).json as any[]).length).toBe(1); + expect((cli(["ls", "workstream"]).json as any[]).length).toBe(1); }); // A checkout-less `local-blank` node: the route creates it with no checkout mode and @@ -122,7 +122,7 @@ describe("papyrus routes → silverwood (in-process, skip-mode)", () => { expect(res.status).toBe(200); expect(await nodes()).toEqual([]); // hidden from the active canvas - const all = cli(["ls", "--all"]).json as Array<{ id: string; status: string }>; + const all = cli(["ls", "workstream", "--all"]).json as Array<{ id: string; status: string }>; expect(all.find((w) => w.id === id)?.status).toBe("archived"); }); diff --git a/experimental/papyrus/server-tests/silverwood-contract.test.ts b/experimental/papyrus/server-tests/silverwood-contract.test.ts index c729396..bba929e 100644 --- a/experimental/papyrus/server-tests/silverwood-contract.test.ts +++ b/experimental/papyrus/server-tests/silverwood-contract.test.ts @@ -47,7 +47,7 @@ describe("silverwood wrapper contract (skip-mode, no network)", () => { await sw.archive(ws.id); expect((await sw.list()).map((w) => w.id)).not.toContain(ws.id); // Ground truth straight from silverwood: still present, tombstoned. - const all = cli(["ls", "--all"]).json as Array<{ id: string; status: string }>; + const all = cli(["ls", "workstream", "--all"]).json as Array<{ id: string; status: string }>; expect(all.find((w) => w.id === ws.id)?.status).toBe("archived"); }); diff --git a/experimental/papyrus/server/routes/api.ts b/experimental/papyrus/server/routes/api.ts index 5eb7fc0..ef9b74e 100644 --- a/experimental/papyrus/server/routes/api.ts +++ b/experimental/papyrus/server/routes/api.ts @@ -202,7 +202,7 @@ async function buildNode(ws: sw.Workstream) { // List active workstreams as nodes; prune runtime PTYs for workstreams that no // longer exist (archived/deleted, possibly by another process). Re-reads // silverwood fresh every call, so the projection tracks concurrent external -// mutations. One `session ls` per workstream — fine at personal scale. +// mutations. One `ls session` per workstream — fine at personal scale. async function hydrateNodes() { const wss = await sw.list(); pruneWorkstreams(new Set(wss.map((w) => w.id))); diff --git a/experimental/papyrus/server/services/silverwood.ts b/experimental/papyrus/server/services/silverwood.ts index 95cda4d..c0be1c1 100644 --- a/experimental/papyrus/server/services/silverwood.ts +++ b/experimental/papyrus/server/services/silverwood.ts @@ -120,7 +120,7 @@ async function run(args: string[]): Promise { // ---- reads ---- export function list(includeArchived = false): Promise { - return run(includeArchived ? ["ls", "--all"] : ["ls"]); + return run(includeArchived ? ["ls", "workstream", "--all"] : ["ls", "workstream"]); } export function get(id: string): Promise { @@ -138,11 +138,11 @@ export function sessionSchema(): Promise { } export async function getPapyrusKv(id: string): Promise> { - return (await run(["kv", "ls", "--workstream-id", id, PAPYRUS_NS])) || {}; + return (await run(["ls", "kv", "--workstream-id", id, PAPYRUS_NS])) || {}; } export async function sessionLs(id: string): Promise> { - return (await run(["session", "ls", "--workstream-id", id])) || {}; + return (await run(["ls", "session", "--workstream-id", id])) || {}; } // Shared by JSON preflight and PTY execution; only preflight adds `--json`. diff --git a/experimental/papyrus/server/services/tabOrder.ts b/experimental/papyrus/server/services/tabOrder.ts index f51ade9..9887569 100644 --- a/experimental/papyrus/server/services/tabOrder.ts +++ b/experimental/papyrus/server/services/tabOrder.ts @@ -3,7 +3,7 @@ // user's stored arrangement is preserved (minus ids of sessions that no longer exist), and every // session missing from it — a just-created tab, or one made outside papyrus — is appended in // CREATION order (oldest first; session id as a stable tiebreak). So a new session always lands -// at the end rather than at silverwood's arbitrary `session ls` map position. The result is +// at the end rather than at silverwood's arbitrary `ls session` map position. The result is // deterministic, so callers persist it lazily (only when it differs from what's stored). export interface OrderedSession { -- 2.54.0