pi-onlyne 0.8.0 → 0.9.1

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
@@ -189,14 +189,14 @@ The extension also supports `.onlyne/channels/loopback/in` when FIFO IO is enabl
189
189
 
190
190
  ## Swarm mode
191
191
 
192
- Swarm mode lets `onlyne-swarm` own task routing for a generated agent workspace. Enable it in `.onlyne/config.toml`:
192
+ Swarm mode lets `onlyne-swarm >= 0.5.0` own task routing for a generated agent workspace. `pi-onlyne 0.9.1` uses the scheduler's `delivery: scheduler` header for task claims and binds a scheduler-created pane to its `ONLYNE_SWARM_TASK`, so these versions upgrade together. Enable it in `.onlyne/config.toml`:
193
193
 
194
194
  ```toml
195
195
  [swarm]
196
196
  enabled = true
197
197
  ```
198
198
 
199
- A swarm Pi session subscribes to loopback events, reports `swarm_ready`, accepts one hop atomically, spawns continuations with `swarm_send` (fire-and-forget), and writes `swarm_complete` (done signal). Scheduler then sends a header-only recycle control wire; pi-onlyne intercepts it before model delivery, sends `swarm_recycled`, stops the watch, clears the slot, and self-exits. `swarm_quit` sends the same ack with `quit:<reason>` then self-exits, so the scheduler records failed immediately. Downstream results travel through files and the ledger; nothing waits.
199
+ A swarm Pi session subscribes to loopback events, reports `swarm_ready`, accepts one scheduler-delivered hop atomically, spawns continuations with `swarm_send` (fire-and-forget), and writes `swarm_complete` (done signal). A raw `swarm_send` relay carries no `delivery` header and only creates the scheduler task row; the scheduler's second delivery adds `delivery: scheduler`, which pi-onlyne uses as the claim gate. This keeps arbitrary role prose out of transport authentication. Scheduler then sends a header-only recycle control wire; pi-onlyne intercepts it before model delivery, sends `swarm_recycled`, stops the watch, clears the slot, and self-exits. `swarm_quit` sends the same ack with `quit:<reason>` then self-exits, so the scheduler records failed immediately. Downstream results travel through files and the ledger; nothing waits.
200
200
 
201
201
  For automatic startup in a generated workspace, add `.pi/onlyne.json`:
202
202
 
package/SPEC.md CHANGED
@@ -84,14 +84,27 @@ One session sees one toolset. The surface is chosen at `session_start` from
84
84
  - When swarm is on, generic in/out auto-handling is disabled: the scheduler owns
85
85
  input/output. Only loopback messages carrying a `---swarm` body header enter
86
86
  the session, via the `followUp` task queue.
87
- - Session model: one session carries exactly one hop, no exceptions. A new
88
- header claims the slot; any further header while claimed is ignored
89
- (the scheduler always opens a new session, so this guard never fires
90
- on the normal path). No waiting, no callbacks, no parent bookkeeping.
87
+ - Session model: one session carries exactly one scheduler-delivered hop. A
88
+ `delivery: scheduler` header field claims the slot; raw `swarm_send` relay
89
+ wires and out wires omit it and never claim. Any further delivered header
90
+ while claimed is ignored (the scheduler always opens a new session, so this
91
+ guard never fires on the normal path). No waiting, no callbacks, no parent
92
+ bookkeeping.
91
93
  - Startup handshake: swarm watch sends the `swarm_ready` op
92
94
  (`{workspace, terminal_handle}`) so the scheduler can match a pending task.
93
95
  `ONLYNE_SWARM_TASK` env and `ORCA_TERMINAL_HANDLE`/`ONLYNE_TERMINAL_HANDLE`
94
- provide fallback correlation.
96
+ provide fallback correlation. **`ONLYNE_SWARM_TASK` is a hard binding:** a
97
+ newly created terminal may replay history only for that exact task id. If
98
+ its FIFO delivery has not reached history yet, the session waits for the
99
+ live inbound event; it never claims a newest/old workspace-local task.
100
+ Sessions with no env task (manual ready pool) retain newest-unclosed
101
+ fallback replay.
102
+ - Hop activity (v0.9.1, R4): `agent_start` with a live claimed task sends
103
+ `swarm_busy` (`{workspace, terminal_handle, task_id}`); `agent_end` with
104
+ the turn ended and no out sends `swarm_idle` (same fields plus
105
+ `pending_exit`, mirroring whether the hop still awaits `swarm_complete`).
106
+ Both are fire-and-forget over the existing swarm event channel; the
107
+ scheduler treats missing rows as race residue and drives its own TTLs.
95
108
  - Tools: `swarm_complete({text})` writes the out message carrying this hop's
96
109
  header (the scheduler's done signal). Scheduler sends a `---swarm-ctl`
97
110
  recycle wire; pi-onlyne intercepts it, sends `swarm_recycled`, stops the
package/dist/index.d.ts CHANGED
@@ -1,2 +1,27 @@
1
1
  import { type ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ import { type Workspace } from "./workspace.js";
3
+ import { type SwarmReportKind } from "./swarm.js";
4
+ import { type StateContext } from "./session.js";
5
+ /** Swarm task slot: one session carries exactly one hop. No waiting, no callbacks. */
6
+ interface SwarmTask {
7
+ taskId: string;
8
+ from: string;
9
+ transferSendTo: string;
10
+ attempt: number;
11
+ }
2
12
  export default function onlyne(pi: ExtensionAPI): void;
13
+ /** Test seam: drive the lifecycle-report wiring against a stub daemon socket.
14
+ * No live pi session and no real daemon are involved; the seam exposes the
15
+ * same closures the hooks call. Mirrors `__swarmSlotForTest`. */
16
+ export declare function __swarmReportForTest(): {
17
+ setWorkspace: (ws: Workspace | null) => void;
18
+ beginSession: (appendEntry: StateContext["appendEntry"], taskId: string) => {
19
+ generation: number;
20
+ seq: number;
21
+ };
22
+ setTask: (task?: SwarmTask) => void;
23
+ reportTaskId: () => string | null;
24
+ emit: (kind: SwarmReportKind) => Promise<boolean>;
25
+ beat: () => void;
26
+ };
27
+ export {};