paseo-room 0.1.0-alpha.6 → 0.1.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.
Files changed (36) hide show
  1. package/README.md +162 -45
  2. package/dist/index.js +748 -410
  3. package/dist/index.js.map +1 -1
  4. package/dist/prompts/contract/lead/complete-peer-brief.md +10 -0
  5. package/dist/prompts/contract/lead/independent-review.md +9 -0
  6. package/dist/prompts/contract/lead/moving-write-ownership.md +13 -0
  7. package/dist/prompts/contract/lead/peer-seat-lifecycle.md +30 -0
  8. package/dist/prompts/contract/lead/project-technical-ownership.md +12 -0
  9. package/dist/prompts/contract/lead/technical-acceptance.md +6 -0
  10. package/dist/prompts/contract/peer/bounded-outcome.md +5 -0
  11. package/dist/prompts/contract/peer/independent-judgment.md +11 -0
  12. package/dist/prompts/contract/peer/no-orchestration.md +5 -0
  13. package/dist/prompts/contract/peer/no-self-acceptance.md +5 -0
  14. package/dist/prompts/contract/peer/reproducible-handoff.md +5 -0
  15. package/dist/prompts/contract/peer/writing-and-review-scope.md +5 -0
  16. package/dist/prompts/contract/shared/evidence-and-event-waiting.md +7 -0
  17. package/dist/prompts/contract/shared/human-authority.md +8 -0
  18. package/dist/prompts/contract/shared/scope-and-unrelated-work.md +4 -0
  19. package/dist/prompts/contract/shared/workspace-protocol-precedence.md +15 -0
  20. package/dist/prompts/contract/shared-lead-peer/challenge-signals.md +9 -0
  21. package/dist/prompts/contract/supervisor/directive-integrity.md +5 -0
  22. package/dist/prompts/contract/supervisor/escalation-boundaries.md +5 -0
  23. package/dist/prompts/contract/supervisor/lead-discovery-and-recovery.md +52 -0
  24. package/dist/prompts/contract/supervisor/observation-and-advice.md +13 -0
  25. package/dist/prompts/contract/supervisor/technical-non-interference.md +8 -0
  26. package/dist/prompts/documents/lead.md +3 -0
  27. package/dist/prompts/documents/peer.md +3 -0
  28. package/dist/prompts/documents/supervisor.md +3 -0
  29. package/dist/prompts/documents/workspace.md +5 -0
  30. package/dist/prompts/pi/communication-style.md +5 -0
  31. package/dist/prompts/pi/runtime.md +7 -0
  32. package/dist/prompts/workspace/repository-conventions.md +7 -0
  33. package/dist/prompts/workspace/review.md +4 -0
  34. package/dist/prompts/workspace/topology.md +13 -0
  35. package/dist/prompts/workspace/verification.md +8 -0
  36. package/package.json +4 -3
package/README.md CHANGED
@@ -7,7 +7,8 @@ It does three things:
7
7
 
8
8
  1. Reads your existing Codex / Claude Code / Pi configuration.
9
9
  2. Writes one isolated role home per seat under `~/.paseo-room`. Each role owns its mutable
10
- credentials; read-only skills, plugins and other supported resources may be symlinked.
10
+ credentials; read-only skills and other supported resources may be symlinked, and Peer
11
+ receives a narrower set than Supervisor and Lead.
11
12
  3. Registers those role homes with your running Paseo daemon as providers — room tools on for Supervisor and Lead, off for Peer — and adds one agent profile per seat so opening one is a single pick.
12
13
 
13
14
  Everything it manages lives in `$HOME`, under `~/.paseo-room`. Agent runtimes may later
@@ -67,6 +68,8 @@ starts, its exit code is preserved; a signal is returned using the conventional
67
68
  **0.8.0-beta.1 or newer**; any selection containing Pi requires **0.8.0 or newer**.
68
69
  `paseo-room` checks this before touching anything, and never installs or upgrades Paseo.
69
70
  - An initialised Codex home (`~/.codex/config.toml`) and/or Claude Code home (`~/.claude`).
71
+ Codex must be new enough for `codex debug models` to print its JSON model catalog: the room
72
+ seats Codex only if it can generate the scrubbed catalog copy.
70
73
  Setup never copies mutable credential stores or runs login. Use supported environment/static
71
74
  auth, or log in once in each role after setup. For current Claude runtimes, paseo-room
72
75
  pins both `CLAUDE_CONFIG_DIR` and `CLAUDE_SECURESTORAGE_CONFIG_DIR` per role. It does not
@@ -86,22 +89,22 @@ starts, its exit code is preserved; a signal is returned using the conventional
86
89
  roles/codex/<role>/
87
90
  config.toml # your config.toml + the room's overrides
88
91
  role-instructions.md # readable copy of what this seat was told
89
- model-catalog.json # your catalog with native multi-agent metadata removed
92
+ model-catalog.json # generated copy of your catalog, native multi-agent metadata removed
90
93
  auth.json # created and owned by Codex after role login, if file-backed
91
- AGENTS.md, skills, plugins, hooks.json → symlinks into ~/.codex when present
94
+ AGENTS.md, skills, plugins, hooks.json → symlinks into ~/.codex when present (Peer: see below)
92
95
  roles/claude/<role>/
93
96
  CLAUDE.md # your global memory + role instructions
94
97
  settings.json # your settings.json + PASEO_ROOM_ROLE
95
98
  .claude.json # seeded once from yours, then owned by Claude
96
99
  .credentials.json # created and owned by Claude after role login, if file-backed
97
100
  skills, plugins, commands, hooks, rules, output-styles,
98
- keybindings.json, themes → symlinks into ~/.claude when present
101
+ keybindings.json, themes → symlinks into ~/.claude when present (Peer: see below)
99
102
  roles/pi/<role>/
100
103
  settings.json # your settings minus package/extension declarations
101
104
  APPEND_SYSTEM.md # your append + style/runtime capsules + role instructions
102
105
  auth.json # created and owned by Pi after role login, if used
103
106
  models.json, AGENTS.md, skills, prompts, themes,
104
- keybindings.json, mcp.json → symlinks into ~/.pi/agent when present
107
+ keybindings.json, mcp.json → symlinks into ~/.pi/agent when present (Peer: see below)
105
108
  ```
106
109
 
107
110
  Each seat gets its own file-backed credential path, sessions, history and projects inside its
@@ -109,6 +112,42 @@ role home. Current supported runtimes therefore do not share mutable file-backed
109
112
  or conversation state; older-runtime Claude Keychain isolation remains unverifiable. Credential
110
113
  paths are never managed-entry symlinks: setup and update preserve whatever is already there.
111
114
 
115
+ A managed file or symlink only ever replaces an absent path or the same shape, and it is
116
+ written to a temporary sibling and renamed into place, so a seat never reads a half-written
117
+ file. Anything else at a managed path — a directory where a file belongs, an unexpected
118
+ symlink — makes setup stop and name the path for you to move aside. Nothing is deleted
119
+ recursively on your behalf.
120
+
121
+ ### What Peer does not receive
122
+
123
+ Peer has no room tools, so the room also stops handing it orchestration surfaces:
124
+
125
+ - Resources whose contents execute are not shared with Peer at all — Codex `plugins` and
126
+ `hooks.json`, Claude `plugins`, `commands` and `hooks`, Pi `prompts`. Supervisor and Lead
127
+ still get them.
128
+ - Peer's `skills` is not one symlink to your skills directory. It is a room-owned directory
129
+ of links to each of your skills whose name does not start with `paseo` (any capitalization),
130
+ so orchestration skills are not advertised to the seat that cannot orchestrate. Adding or
131
+ removing one of your skills is drift `verify` reports and `setup --apply` reconciles.
132
+
133
+ Your own skills directory is never modified: `paseo*` skills stay exactly where they are.
134
+ An existing room upgrades its one legacy Peer `skills` symlink to that projection on the next
135
+ `setup --apply`; setup only unlinks the alias, never your skills, and stops with an actionable
136
+ message if that path has become something it does not recognize.
137
+
138
+ This is capability hygiene, not a sandbox. Peer still has shell access.
139
+
140
+ ### Paseo MCP servers are refused, never rewritten
141
+
142
+ Paseo is the room's only control plane, so setup and verify read the MCP declarations in your
143
+ Codex `config.toml`, your Claude state, Pi's `mcp.json`, and any already-seeded role
144
+ `.claude.json`, and **fail before applying anything** if a declaration looks Paseo-related.
145
+ Recognition is one bounded rule — `paseo` as a whole identifier or path token, in the server
146
+ name, `command`, `args` or a URL field — and the message quotes the file and the field that
147
+ matched. It is a heuristic, not a scanner: a renamed or obfuscated endpoint passes it. Remove
148
+ or rename the server yourself; `paseo-room` never edits, filters or deletes your MCP
149
+ configuration.
150
+
112
151
  Pi role homes deliberately do not link `extensions`, `npm`, `git`, `trust.json`, runtime
113
152
  caches or session state. Their copied `settings.json` removes `packages` and `extensions`,
114
153
  so startup cannot install configured packages or discover unrelated configured extensions.
@@ -176,13 +215,25 @@ For Codex, the generated `config.toml` is a copy of yours with only these keys o
176
215
  | `sandbox_mode` | `danger-full-access` | A seat that stops to ask for permission cannot be driven headless. |
177
216
  | `approval_policy` | `never` | Same. |
178
217
  | `developer_instructions` | the role contract | This is the room's whole instruction payload. |
179
- | `model_catalog_json` | generated catalog | Strips `multi_agent_version` so the seat is not offered native collaboration. Skipped, with a warning, if your Codex cannot produce a catalog. |
180
- | `[agents].enabled` | `false` | Paseo owns agent lifecycle. |
218
+ | `model_catalog_json` | generated catalog | Strips `multi_agent_version` so the seat is not offered native collaboration. Setup **fails** if your Codex cannot produce a catalog. |
219
+ | `[agents].enabled` | `false` | Paseo owns agent lifecycle. Top-level only: Codex profiles have no such key. |
181
220
  | `features.multi_agent`, `features.multi_agent_v2` | `false` | Same, at the feature-flag level. |
182
221
 
183
- If your config has an active `profile`, the same sandbox and approval overrides are written
184
- into that profile too, because a profile outranks the top-level keys. Your model, reasoning
185
- effort, MCP servers, trusted projects and every other key are copied through untouched.
222
+ If your config has an active `profile`, every one of those keys a profile can also carry —
223
+ sandbox, approval, the catalog path and both multi-agent features — is written into that
224
+ profile too, because a profile outranks the top-level keys. Your model, reasoning effort, MCP
225
+ servers, trusted projects and every other key are copied through untouched.
226
+
227
+ The catalog is a closure, not a nicety, so it fails closed: if `codex debug models` cannot
228
+ run, does not print JSON, or prints JSON that is not a catalog object, no Codex seat is
229
+ planned and the message quotes the exact command it tried. A Codex too old to print that JSON
230
+ catalog cannot be seated.
231
+
232
+ What lands in each role home is a **generated copy** captured at that setup, and it replaces
233
+ Codex's built-in catalog for that seat. New models from a later Codex release therefore do not
234
+ reach a seat until you run `setup --apply` again. `verify` says so explicitly when a drifted
235
+ file is a `model-catalog.json`, because that seat is missing the closure rather than only
236
+ holding older contract text.
186
237
 
187
238
  **The room never replaces an agent's base prompt.** Codex's `model_instructions_file`,
188
239
  Claude's `--system-prompt` and Pi's `SYSTEM.md` / `--system-prompt` all *replace* the vendor
@@ -192,6 +243,13 @@ contract is additive instead: `developer_instructions` for Codex, `CLAUDE.md` fo
192
243
  and the generated Pi `APPEND_SYSTEM.md` passed with `--append-system-prompt` for Pi. Pi keeps
193
244
  normal project `AGENTS.md` / `CLAUDE.md` context loading.
194
245
 
246
+ Claude's carrier is the weakest of the three, and knowingly so. `CLAUDE.md` is user memory,
247
+ which a project-level `CLAUDE.md` can dilute, and Paseo runs Claude through the Claude Agent
248
+ SDK rather than as a plain CLI process — so there is no provider-owned command line to append
249
+ a stronger prompt through, and no CLI flag is proposed here. The real fix is a
250
+ provider-owned SDK append field in Paseo itself. Until that exists, the room keeps the
251
+ contract short and states the limit instead of implying parity with Codex.
252
+
195
253
  Pi providers use a strict command tail:
196
254
 
197
255
  ```text
@@ -224,6 +282,11 @@ agent's own configuration:
224
282
  | strict argv + `PI_MCP_CONFIG_MODE=exclusive` + additive runtime capsule | Pi | Disables extension discovery and project trust, and restricts adapter config to the role-home `mcp.json`; forbids a second agent control plane without claiming sandboxing. |
225
283
  | `paseoTools: {enabled}` | all | Room tools for Supervisor and Lead, never for Peer. |
226
284
 
285
+ `verify` compares each provider's `command`, `env`, `paseoTools` and pins against what the
286
+ room would write, and fails if one has been dropped — a pin that can be silently removed is
287
+ not a guarantee. The `env` map is compared whole rather than as a subset, because an added key
288
+ can re-enable exactly what a pin closes. Unrelated top-level provider fields stay yours.
289
+
227
290
  It also saves one **agent profile** per seat, which is what the Paseo picker lists under
228
291
  Profiles. A profile is a preset, not a constraint: it decides where a seat *starts*.
229
292
 
@@ -242,7 +305,10 @@ Supervisor starts low because it routes rather than reasons. No seat starts on t
242
305
  option — Codex's `ultra` and Claude's `ultracode` advertise automatic task delegation, which
243
306
  is a second control plane. `setup` restores room-owned identity, appearance and mode fields,
244
307
  but leaves your model and reasoning choice alone; profiles you created yourself are never
245
- touched.
308
+ touched. If you do put a room seat on `ultra` or `ultracode`, setup and verify warn and name
309
+ the seats: the room has not verified whether its closed multi-agent paths actually prevent
310
+ that option from delegating, so it reports the selection rather than rejecting or changing it.
311
+ The warning does not fail the command.
246
312
 
247
313
  Pi exposes no selectable Paseo mode, so its profiles omit `modeId`; setup also removes a
248
314
  stale room-owned value from an existing Pi profile. Pi has no sandbox or approval boundary:
@@ -264,24 +330,20 @@ the operator.
264
330
  ### Recognizing a live room seat
265
331
 
266
332
  Names are not identity. A matching cwd, title, or provider label does not make an existing
267
- agent a room Lead or Peer. Before Supervisor reuses a Lead, it reads `list_profiles` and
268
- selects the exact current `room-<agent>-lead` profile for the intended agent implementation.
269
- Because agent creation has no profile parameter, it materializes every field that profile
270
- defines: provider/model, `modeId`, `thinkingOptionId`, and `featureValues`, omitting absent
271
- fields. It uses `list_agents(cwd)` only to discover candidates because that filter also returns
272
- descendant working directories, then rejects anything whose cwd is not the exact project
273
- root, is archived, or runs a bare, wrong-role, or other provider. For every remaining
274
- candidate it reads `get_agent_status`: the provider must equal the selected profile's current
275
- provider, `workspaceId` must equal the intended workspace when that id is available, and
276
- `currentModeId` must equal the profile's `modeId` when the profile defines one. Parentage or
277
- known Human-opened ownership history must corroborate the established owner. An unparented
278
- or ambiguous candidate is not adopted silently; it enters the duplicate-recovery and Human
279
- escalation path in the role contract.
280
-
281
- Lead applies the same rule when creating a Peer: read the exact current
282
- `room-<agent>-peer` profile, materialize every present launch field in the intended workspace,
283
- then require the live seat's daemon-added `paseo.parent-agent-id` to name the current Lead.
284
- A Peer is one fresh brief and receives no room tools or orchestration authority.
333
+ agent a room Lead or Peer. The exact eligibility procedure is model-facing wording and lives
334
+ in the contract itself —
335
+ [Lead Discovery and Recovery](src/room/prompts/contract/supervisor/lead-discovery-and-recovery.md)
336
+ for Supervisor and
337
+ [Peer Seat Lifecycle](src/room/prompts/contract/lead/peer-seat-lifecycle.md) for Lead — rather
338
+ than being restated here. In outline: the seat's evidence is the current live configuration.
339
+ Supervisor reads the exact current `room-<agent>-lead` profile from `list_profiles` and
340
+ materializes every field it defines (agent creation takes no profile id), uses `list_agents(cwd)`
341
+ only to find candidates, then inspects each one's full status for the profile's provider, the
342
+ intended workspace and its mode. For `room-<agent>-peer`, Lead copies provider, mode and
343
+ features exactly, treats model and thinking as protocol-governed defaults, and additionally
344
+ requires the live seat's daemon-added `paseo.parent-agent-id` to name itself. Ownership must be
345
+ corroborated by parentage or known Human-opened history; an ambiguous candidate goes to
346
+ duplicate recovery and Human escalation instead of being adopted.
285
347
 
286
348
  Current Paseo agent sessions do not retain `profileId`. A direct launch with the exact
287
349
  profile provider, mode and workspace is therefore **profile-equivalent**, but literal picker
@@ -291,11 +353,51 @@ provider ids or claim that the daemon enforces this procedural eligibility check
291
353
  ## Keeping the room current
292
354
 
293
355
  Role homes are generated once, at `setup` time. After you edit `~/.codex/config.toml`,
294
- `~/.claude/settings.json`, or Pi's `settings.json` / `APPEND_SYSTEM.md`, run `setup --apply`
295
- again to fold the change into every seat.
296
- The same update regenerates `AUTHENTICATION.md` from the newly resolved binaries. `verify`
297
- reports drift in the meantime, and re-running `setup` is safe: it rewrites only
298
- managed configuration that differs and never replaces role credential paths.
356
+ `~/.claude/settings.json`, or Pi's `settings.json` / `APPEND_SYSTEM.md`, run setup again to
357
+ fold the change into every seat. The same applies after upgrading `paseo-room`; a release
358
+ that changes generated headings or prompt assets produces expected one-time managed-file
359
+ drift.
360
+
361
+ Use the upgraded version with the same repeated `--agent` selection as the installed room:
362
+
363
+ ```bash
364
+ npx paseo-room@<new-version> setup --agent codex --agent claude --agent pi
365
+ npx paseo-room@<new-version> setup --agent codex --agent claude --agent pi --apply
366
+ npx paseo-room@<new-version> verify
367
+ ```
368
+
369
+ First inspect the dry run, then apply it. The apply regenerates managed prompt carriers,
370
+ the Codex model catalogs and `AUTHENTICATION.md` from the newly resolved binaries, but
371
+ preserves role credential paths and the operator agent homes. Stop and restart every affected
372
+ seat after the apply; sending another turn to an already-running seat is not a restart.
373
+ `setup` and `verify` prove the files and live Paseo configuration, not that an existing model
374
+ context reloaded them. Only a newly launched seat context is expected to ingest the
375
+ regenerated instructions.
376
+
377
+ `room.json` records a short `contract` digest of the role documents and workspace protocol
378
+ this room was installed from. When it differs from what the installed package renders — or is
379
+ absent, because the room predates the field — setup and verify warn that the seats are holding
380
+ older text and ask for `setup --apply` plus a restart. It is provenance you compare by eye, not
381
+ a security claim. Rooms written before the field still parse.
382
+
383
+ One migration happens on the first upgraded apply: an existing Peer `skills` symlink becomes
384
+ the room-owned projection described above. Only the alias is unlinked, never your skills, and
385
+ setup stops with an actionable message rather than guessing if that path has become something
386
+ it does not recognize.
387
+
388
+ To roll back, run the prior package version with the same agent selection and `setup --apply`,
389
+ then restart the affected seats again:
390
+
391
+ ```bash
392
+ npx paseo-room@<prior-version> setup --agent codex --agent claude --agent pi --apply
393
+ npx paseo-room@<prior-version> verify
394
+ ```
395
+
396
+ No reverse data migration is needed; a prior package regenerates its own marker, including
397
+ dropping or restoring the contract digest as its own schema requires. Do not use `remove` for a
398
+ version rollback: it deletes the room home, including role-owned credential files. Re-running
399
+ setup is safe because it rewrites only managed configuration that differs and never replaces
400
+ role credential paths.
299
401
 
300
402
  There are three separate evidence boundaries:
301
403
 
@@ -325,17 +427,22 @@ command again.
325
427
 
326
428
  ## The role contract
327
429
 
328
- The exact wording every seat reads lives in [`src/room/clauses.ts`](src/room/clauses.ts).
329
- In short:
430
+ The exact model-facing wording every seat reads lives in the canonical Markdown under
431
+ [`src/room/prompts/`](src/room/prompts/). TypeScript selects those semantic sections with
432
+ `instructionKeys()` and `protocolKeys()`; it does not duplicate their prose. In short:
330
433
 
331
434
  - **Supervisor** routes Human directives to Lead and observes. Before opening a seat it checks
332
- for and reuses the project's existing Lead, including an idle or resumable Lead. It does
333
- not edit project work, run validation, direct Peer, or decide technical acceptance. Room
334
- tools: on.
435
+ for and reuses the project's existing Lead, including an idle or resumable Lead. It observes
436
+ the Lead–Peer process for named failures and advises with evidence, but advice carries no
437
+ technical authority: it does not edit project work, run validation, direct Peer, or decide
438
+ technical acceptance. Room tools: on.
335
439
  - **Lead** is the durable owner of one project across turns. It owns framing, decomposition,
336
- routing, integration and technical acceptance. One moving write scope has exactly one
337
- owner, and at most one Peer is writable at a time. Room tools: on.
338
- - **Peer** owns one bounded outcome, may challenge a failed premise with
440
+ routing, integration and technical acceptance. A brief states the outcome and the evidence
441
+ that settles it rather than pre-solving the work; any plan or file list in it is provisional.
442
+ One moving write scope has exactly one owner, and at most one Peer is writable at a time.
443
+ Room tools: on.
444
+ - **Peer** owns one bounded outcome, forms its own technical position from the code and its own
445
+ verification, may challenge a failed premise with
339
446
  `REOPEN_REQUEST` / `DEPENDENCY_REQUEST` / `BLOCKED`, hands back a reproducible candidate,
340
447
  and never accepts its own difficult change. Room tools: off.
341
448
 
@@ -343,8 +450,9 @@ Human keeps product goals, priority, material cost, external effects and irrever
343
450
 
344
451
  One rule has no runtime enforcement behind it and so is procedural and regression-tested in
345
452
  the contract instead: **one Lead owns one project; Supervisor discovers, verifies and reuses
346
- it, while Lead alone opens verified Peer seats.** The exact eligibility procedure is described
347
- above. A completed turn, idle state, pending permission, or resumable closed session is not an
453
+ it, while Lead alone opens verified Peer seats.** The eligibility evidence is summarized
454
+ above and stated exactly in the contract sections linked there. A completed turn, idle state,
455
+ pending permission, or resumable closed session is not an
348
456
  absent Lead. Fresh independent review means that existing Lead opens a fresh read-only Peer;
349
457
  it never means Supervisor opens another Lead.
350
458
 
@@ -353,6 +461,15 @@ Supervisor stops parallel routing, preserves both histories, keeps the previousl
353
461
  healthy owner, and closes the duplicate only after a stable handoff. Ambiguous ownership,
354
462
  health, or concurrent writes go back to Human rather than being guessed or merged.
355
463
 
464
+ Two further limits are deliberately conservative. **One writable Peer per project**, not one
465
+ per moving scope: the room gives you no writer isolation, so separate scopes are not evidence
466
+ of separate working trees, and no workspace protocol relaxes the limit. Concurrent writable
467
+ Peers in isolated worktrees are a deferred decision, not an oversight. And a seat's **model and
468
+ reasoning effort are defaults**: Lead varies them for a brief only where the repository's
469
+ workspace protocol supplies an explicit task-risk policy, and never up to a tier advertising
470
+ automatic delegation. Provider, mode, workspace, parent and feature values are eligibility
471
+ evidence and copied exactly.
472
+
356
473
  Every seat also carries a **default workspace protocol** — topology by difficulty,
357
474
  verification, review, repository conventions — so a project has that layer without doing
358
475
  anything. Each seat gets the sections that bear on its own work; topology goes to Lead and
@@ -410,7 +527,7 @@ that review; Supervisor must route the request to Lead rather than opening a fre
410
527
  ## Development
411
528
 
412
529
  ```bash
413
- npm run verify # typecheck, lint, test, build — the gate order
530
+ npm run verify # typecheck, lint, test, build, packed-package test — the gate order
414
531
  ```
415
532
 
416
533
  Releases are published to npm from a GitHub Release; see