paseo-room 0.7.0 → 0.8.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.
- package/README.md +31 -10
- package/dist/index.js +34 -15
- package/dist/index.js.map +1 -1
- package/dist/prompts/contract/lead.md +22 -2
- package/dist/runtime-plugin/client/data.ts +2 -1
- package/dist/runtime-plugin/client/effort-settings.tsx +89 -0
- package/dist/runtime-plugin/client/model.ts +5 -0
- package/dist/runtime-plugin/client/pills.ts +8 -2
- package/dist/runtime-plugin/client/record.tsx +8 -0
- package/dist/runtime-plugin/client/room.tsx +2 -2
- package/dist/runtime-plugin/client/views.tsx +2 -0
- package/dist/runtime-plugin/index.server.ts +17 -0
- package/dist/runtime-plugin/server/attention/delivery.ts +29 -4
- package/dist/runtime-plugin/server/attention/engine.ts +62 -28
- package/dist/runtime-plugin/server/attention/mask.ts +6 -0
- package/dist/runtime-plugin/server/attention/observer.ts +25 -15
- package/dist/runtime-plugin/server/attention/signals.ts +25 -15
- package/dist/runtime-plugin/server/attention/triage.ts +41 -2
- package/dist/runtime-plugin/server/brief.ts +38 -0
- package/dist/runtime-plugin/server/context.ts +22 -2
- package/dist/runtime-plugin/server/contracts/actions.ts +4 -0
- package/dist/runtime-plugin/server/controller.ts +78 -15
- package/dist/runtime-plugin/server/domain/state.ts +20 -2
- package/dist/runtime-plugin/server/domain/views.ts +22 -4
- package/dist/runtime-plugin/server/events/schema.ts +5 -1
- package/dist/runtime-plugin/server/handlers/actions.ts +26 -12
- package/dist/runtime-plugin/server/handlers/peer.ts +5 -3
- package/dist/runtime-plugin/server/handlers/turns.ts +4 -3
- package/dist/runtime-plugin/server/paseo-port.ts +23 -0
- package/dist/runtime-plugin/server/rpc.ts +25 -1
- package/dist/runtime-plugin/server/tools.ts +30 -8
- package/dist/runtime-plugin/shared/effort.ts +27 -0
- package/dist/runtime-plugin/shared/rpc-contracts.ts +20 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -483,7 +483,9 @@ vocabulary for Lead and Peer, and exactly one body per role. TypeScript selects
|
|
|
483
483
|
that settles it rather than pre-solving the work; any plan or file list in it is provisional.
|
|
484
484
|
One moving write scope has exactly one owner, and at most one Peer is writable at a time. It
|
|
485
485
|
explicitly requests native Paseo completion/error/permission notification for Peer creation and
|
|
486
|
-
every background follow-up, then waits for events rather than polling.
|
|
486
|
+
every background follow-up, then waits for events rather than polling. A question only Human can
|
|
487
|
+
answer goes on its own `NEEDS-HUMAN:` line, and an effect beyond the work's intended scope on an
|
|
488
|
+
`INCIDENT:` line, so neither is lost in a long message. Room tools: on.
|
|
487
489
|
- **Peer** owns one bounded assignment — writable inside an assigned scope, or read-only
|
|
488
490
|
against a named candidate, question or area — under exactly one disposition Lead names in the
|
|
489
491
|
brief (Engineer, Architect, Reviewer or Scout), forms its own technical position from the code
|
|
@@ -621,10 +623,23 @@ npx paseo-room verify
|
|
|
621
623
|
working.
|
|
622
624
|
- **Lead** gains room tools such as `assignment_create`, `assignment_dispatch`, `assignment_answer`,
|
|
623
625
|
`assignment_accept`, `gate_run`, and for isolated writers `workspace_close` and `lease_reclaim`.
|
|
626
|
+
`assignment_create` refuses a base that is not a commit of the repository (`base_unknown`).
|
|
624
627
|
**Supervisor** gains `room_status`, `runtime_findings`, `message_lead` (with a `project` for a
|
|
625
|
-
Supervisor of several projects) and `attention_feedback`, and cannot change an assignment.
|
|
626
|
-
|
|
627
|
-
|
|
628
|
+
Supervisor of several projects) and `attention_feedback`, and cannot change an assignment. Its
|
|
629
|
+
status and findings cover only its portfolio and the project it stands in; `room_status` lists
|
|
630
|
+
the assignments still open or still to close, and only counts settled ones.
|
|
631
|
+
- **Peer thinking.** A runtime-dispatched Peer launches on its room profile's model and thinking
|
|
632
|
+
option. In **Settings › Room seats › Thinking Lead may choose** you can allow other thinking
|
|
633
|
+
options per Peer provider, from the ones Paseo lists for its model. Lead may then pass `thinking`
|
|
634
|
+
(with a `thinkingReason`) to `assignment_dispatch`, as the Lead contract directs. The runtime
|
|
635
|
+
refuses anything outside what you allowed or what the model offers, and always refuses `ultra` and
|
|
636
|
+
`ultracode`, which start agents on their own. It records the choice, shows it with the reason to
|
|
637
|
+
Supervisor and in the panel, and keeps it for a reclaimed Peer while you still allow it. The model
|
|
638
|
+
itself is never Lead's to change.
|
|
639
|
+
- **A runtime-dispatched Peer** is titled `<Disposition> · <outcome gist> · <assignment id>` (for
|
|
640
|
+
example `Reviewer · Review the Docker Compose dev env… · asg_…`), and the runtime's notices to Lead
|
|
641
|
+
name the assignment the same way. It gets exactly two tools, `ask` and `handoff`, for its own
|
|
642
|
+
assignment, and still no Paseo room tools. A report exists only once one of those calls is accepted; its
|
|
628
643
|
final message is never read as a report. Claude asks for permission before a Peer's first call
|
|
629
644
|
to `mcp__paseo_room__ask` or `mcp__paseo_room__handoff`: approve it in Paseo, since the runtime
|
|
630
645
|
never answers a permission for a seat. Codex and Pi Peers do not ask.
|
|
@@ -637,8 +652,9 @@ npx paseo-room verify
|
|
|
637
652
|
- **The Room runtime panel** (sidebar item, and a workspace panel that opens on its own project)
|
|
638
653
|
puts what needs you first. Below that come your projects, ordered by status, then your
|
|
639
654
|
Supervisors.
|
|
640
|
-
- A project shows its Supervisor, its Lead and Peer seats (each opens its agent in Paseo
|
|
641
|
-
runtime record: assignments, isolated
|
|
655
|
+
- A project shows its Supervisor, its Lead and Peer seats (each opens its agent in Paseo, and
|
|
656
|
+
shows the model and thinking option it runs with) and its runtime record: assignments, isolated
|
|
657
|
+
writers, findings and recovery.
|
|
642
658
|
- Starting a Supervisor, starting a project and assigning a Supervisor are guided forms.
|
|
643
659
|
- The design notes are in [docs/design/runtime-panel-ux.md](docs/design/runtime-panel-ux.md).
|
|
644
660
|
- **Settings › Room seats** shows which account each seat is signed in to (email, plan and
|
|
@@ -659,15 +675,20 @@ learn only when you ask it to check.
|
|
|
659
675
|
- They report a permission waiting on any seat for 5 minutes, and a Peer result its idle Lead has
|
|
660
676
|
not read for 10 minutes.
|
|
661
677
|
- They report the same failure twice in a row, and possible concurrent writers in one working
|
|
662
|
-
tree.
|
|
678
|
+
tree, naming each seat's files and when its turn ended. A write outside that tree does not
|
|
679
|
+
count.
|
|
663
680
|
- They report a Lead archived while its seats still work, and a Lead's finished turn that the
|
|
664
681
|
Supervisor did not prompt itself.
|
|
682
|
+
- The Lead contract has Lead put a question for you on a line beginning `NEEDS-HUMAN:` and an
|
|
683
|
+
incident on one beginning `INCIDENT:`. The first wakes the Supervisor and the second pages it,
|
|
684
|
+
even for a turn it prompted, once per line, and the letter quotes those lines rather than the
|
|
685
|
+
message's end.
|
|
665
686
|
- Letters are held until the Supervisor is idle, batched into digests, and limited to a few wakes
|
|
666
687
|
an hour. They are never sent while the Supervisor holds a permission, because a send would
|
|
667
688
|
deny it.
|
|
668
|
-
- Each item has an id for `attention_feedback
|
|
669
|
-
Supervisor contract has it ask or nudge the Lead, or
|
|
670
|
-
Peer.
|
|
689
|
+
- Each item has an id for `attention_feedback`, and a letter's own id rates every item in it. A
|
|
690
|
+
letter is evidence, not an instruction: the Supervisor contract has it ask or nudge the Lead, or
|
|
691
|
+
relay a question to you, and never direct a Peer.
|
|
671
692
|
- **Starting seats.** From the **Room** view, **Start Supervisor** opens one in an existing directory
|
|
672
693
|
outside every repository. **Start project** checks a repository, opens its Lead under the
|
|
673
694
|
Supervisor you pick, and sends a fixed kickoff with your first directive verbatim. **Assign
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ var init_package = __esm({
|
|
|
15
15
|
"package.json"() {
|
|
16
16
|
package_default = {
|
|
17
17
|
name: "paseo-room",
|
|
18
|
-
version: "0.
|
|
18
|
+
version: "0.8.0",
|
|
19
19
|
description: "One CLI that configures Codex, Claude Code, and Pi role homes in $HOME and registers them with your local Paseo daemon.",
|
|
20
20
|
keywords: [
|
|
21
21
|
"paseo",
|
|
@@ -691,10 +691,10 @@ async function loginRole(agentValue, roleValue, options, output) {
|
|
|
691
691
|
const childEnv = { ...env, ...invocation.env };
|
|
692
692
|
const launch = options.spawn ?? spawnLogin;
|
|
693
693
|
return new Promise((resolve5) => {
|
|
694
|
-
let
|
|
694
|
+
let settled2 = false;
|
|
695
695
|
const finish = (code2) => {
|
|
696
|
-
if (
|
|
697
|
-
|
|
696
|
+
if (settled2) return;
|
|
697
|
+
settled2 = true;
|
|
698
698
|
resolve5(code2);
|
|
699
699
|
};
|
|
700
700
|
let child;
|
|
@@ -1688,20 +1688,20 @@ function runProbeProcess(executable, adapterEntry, env, options, cwd) {
|
|
|
1688
1688
|
const child = spawn2(executable, args, { cwd, detached: true, env, stdio: ["pipe", "pipe", "pipe"] });
|
|
1689
1689
|
const stdout = [];
|
|
1690
1690
|
let bytes = 0;
|
|
1691
|
-
let
|
|
1691
|
+
let settled2 = false;
|
|
1692
1692
|
const finish = (result) => {
|
|
1693
|
-
if (
|
|
1694
|
-
|
|
1693
|
+
if (settled2) return;
|
|
1694
|
+
settled2 = true;
|
|
1695
1695
|
clearTimeout(timer);
|
|
1696
1696
|
resolveResult(result);
|
|
1697
1697
|
};
|
|
1698
1698
|
const abort = (reason3) => {
|
|
1699
|
-
if (
|
|
1699
|
+
if (settled2) return;
|
|
1700
1700
|
terminateProbe(child);
|
|
1701
1701
|
finish({ ok: false, stdout: Buffer.concat(stdout).toString("utf8"), reason: reason3 });
|
|
1702
1702
|
};
|
|
1703
1703
|
const capture = (chunk, keep) => {
|
|
1704
|
-
if (
|
|
1704
|
+
if (settled2) return;
|
|
1705
1705
|
bytes += chunk.length;
|
|
1706
1706
|
if (bytes > outputLimit) {
|
|
1707
1707
|
abort("overflow");
|
|
@@ -2841,6 +2841,7 @@ function reclaimed(view, event) {
|
|
|
2841
2841
|
delete copy.peerAgentId;
|
|
2842
2842
|
delete copy.observedProviderId;
|
|
2843
2843
|
delete copy.observedModel;
|
|
2844
|
+
delete copy.observedThinking;
|
|
2844
2845
|
return { ...copy, state: "dispatching", reportingState: "consumed", eventIds: [...view.eventIds, event.id] };
|
|
2845
2846
|
}
|
|
2846
2847
|
function applyReport(state, view, event) {
|
|
@@ -2923,7 +2924,13 @@ function applyEvent(state, event) {
|
|
|
2923
2924
|
const id2 = view.id;
|
|
2924
2925
|
switch (event.type) {
|
|
2925
2926
|
case "assignment.dispatch-requested":
|
|
2926
|
-
update(state, id2, {
|
|
2927
|
+
update(state, id2, {
|
|
2928
|
+
state: "dispatching",
|
|
2929
|
+
peerProviderId: event.data.peerProviderId,
|
|
2930
|
+
workspaceId: event.data.workspaceId,
|
|
2931
|
+
...event.data.thinking === void 0 ? {} : { chosenThinking: event.data.thinking },
|
|
2932
|
+
...event.data.thinkingReason === void 0 ? {} : { thinkingReason: event.data.thinkingReason }
|
|
2933
|
+
}, event);
|
|
2927
2934
|
return;
|
|
2928
2935
|
case "ownership.reserved":
|
|
2929
2936
|
state.ownership.set(id2, { assignmentId: id2, workspaceId: event.data.workspaceId, baseCommit: event.data.baseCommit, state: "reserved" });
|
|
@@ -2950,7 +2957,12 @@ function applyEvent(state, event) {
|
|
|
2950
2957
|
update(state, id2, { state: "uncertain" }, event);
|
|
2951
2958
|
return;
|
|
2952
2959
|
case "binding.published":
|
|
2953
|
-
update(state, id2, {
|
|
2960
|
+
update(state, id2, {
|
|
2961
|
+
observedProviderId: event.data.providerId,
|
|
2962
|
+
observedModel: event.data.model,
|
|
2963
|
+
workspaceId: event.data.workspaceId,
|
|
2964
|
+
...event.data.thinking === void 0 ? {} : { observedThinking: event.data.thinking }
|
|
2965
|
+
}, event);
|
|
2954
2966
|
return;
|
|
2955
2967
|
case "ownership.held":
|
|
2956
2968
|
setOwner(state, id2, { state: "held", agentId: event.data.agentId });
|
|
@@ -3281,7 +3293,11 @@ var init_actions = __esm({
|
|
|
3281
3293
|
...assignment,
|
|
3282
3294
|
peerProvider: z6.string().min(1).max(128),
|
|
3283
3295
|
isolation: z6.enum(["lead-workspace", "worktree"]).optional(),
|
|
3284
|
-
serialOnly: boundedArray(boundedString()).optional()
|
|
3296
|
+
serialOnly: boundedArray(boundedString()).optional(),
|
|
3297
|
+
// A thinking option the operator allows for that Peer provider, and why; omitted, the Peer
|
|
3298
|
+
// launches on its profile's option (docs/design/runtime-coordination-peer-effort.md E-D2).
|
|
3299
|
+
thinking: z6.string().min(1).max(64).optional(),
|
|
3300
|
+
thinkingReason: boundedString(1024).optional()
|
|
3285
3301
|
}),
|
|
3286
3302
|
assignment_answer: z6.strictObject({ ...assignment, answer: boundedString() }),
|
|
3287
3303
|
assignment_rework: z6.strictObject({ ...assignment, instructions: boundedString() }),
|
|
@@ -3402,7 +3418,7 @@ function readEvent(value) {
|
|
|
3402
3418
|
const parsed2 = readerSchema.safeParse(value);
|
|
3403
3419
|
return parsed2.success ? { ok: true, event: parsed2.data } : { ok: false, reason: "invalid", detail: z8.prettifyError(parsed2.error) };
|
|
3404
3420
|
}
|
|
3405
|
-
var EVENT_SCHEMA, id, text2, reason2, generation2, digest2, timestamp, workspaceIdSchema, branch, epoch, scopes, gateResultSchema, NOTICE_DISPOSITIONS, NOTICE_CLASSES, EVENT_PAYLOADS, EVENT_TYPES, SUPPORTED_PAYLOAD_VERSIONS, actorSchema, envelope, firstWriter, restWriters, firstReader, restReaders, writerSchema, readerSchema;
|
|
3421
|
+
var EVENT_SCHEMA, id, text2, reason2, thinkingOption, generation2, digest2, timestamp, workspaceIdSchema, branch, epoch, scopes, gateResultSchema, NOTICE_DISPOSITIONS, NOTICE_CLASSES, EVENT_PAYLOADS, EVENT_TYPES, SUPPORTED_PAYLOAD_VERSIONS, actorSchema, envelope, firstWriter, restWriters, firstReader, restReaders, writerSchema, readerSchema;
|
|
3406
3422
|
var init_schema = __esm({
|
|
3407
3423
|
"src/runtime-plugin/server/events/schema.ts"() {
|
|
3408
3424
|
"use strict";
|
|
@@ -3415,6 +3431,7 @@ var init_schema = __esm({
|
|
|
3415
3431
|
id = z8.string().min(1).max(128);
|
|
3416
3432
|
text2 = boundedString();
|
|
3417
3433
|
reason2 = boundedString(1024);
|
|
3434
|
+
thinkingOption = z8.string().min(1).max(64);
|
|
3418
3435
|
generation2 = z8.number().int().min(1);
|
|
3419
3436
|
digest2 = z8.string().regex(/^sha256:[0-9a-f]{64}$/);
|
|
3420
3437
|
timestamp = z8.iso.datetime({ offset: true });
|
|
@@ -3449,7 +3466,8 @@ var init_schema = __esm({
|
|
|
3449
3466
|
"project.ownership-resolved": { keptLeadAgentId: id, decidedBy: z8.enum(["evidence", "human"]) },
|
|
3450
3467
|
// Assignment lifecycle decided by Lead or Human (§5.1).
|
|
3451
3468
|
"assignment.created": { input: assignmentCreateSchema, leadAgentId: id, leadProviderId: id },
|
|
3452
|
-
|
|
3469
|
+
// Lead's thinking choice within the operator's envelope, and why (peer-effort delta E-D2, E-D4).
|
|
3470
|
+
"assignment.dispatch-requested": { peerProviderId: id, workspaceId: id, thinking: thinkingOption.optional(), thinkingReason: reason2.optional() },
|
|
3453
3471
|
"assignment.answered": { answer: text2 },
|
|
3454
3472
|
"assignment.rework-requested": { instructions: text2 },
|
|
3455
3473
|
"assignment.accepted": {
|
|
@@ -3492,7 +3510,8 @@ var init_schema = __esm({
|
|
|
3492
3510
|
model: z8.string().min(1).max(256),
|
|
3493
3511
|
parentAgentId: id,
|
|
3494
3512
|
workspaceId: id,
|
|
3495
|
-
roomGeneration: id
|
|
3513
|
+
roomGeneration: id,
|
|
3514
|
+
thinking: thinkingOption.optional()
|
|
3496
3515
|
},
|
|
3497
3516
|
"reporting.generation-opened": { generation: generation2, capabilityHash: digest2, turn: z8.enum(["initial", "answer", "rework", "follow-up"]) },
|
|
3498
3517
|
"run.requested": { intentId: id, generation: generation2, promptDigest: digest2 },
|