@ai-ecoverse/slicc 1.45.0 → 1.46.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 (2) hide show
  1. package/README.md +66 -23
  2. package/package.json +7 -7
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  `slicc` is SLICC's command line for seven, the SLICC on `*.sliccy.ai`. It is one binary for macOS, Windows and Linux. It launches and links browsers, and shares a machine's network, compute and browsers with a running seven over a WebRTC link. `npx sliccy` and Sliccstart.app run this binary. It replaces slicc-node and slicc-swift (see [Coming from slicc-node](#coming-from-slicc-node)).
4
4
 
5
- **Status:** being built. `slicc` (the default flow), `slicc attach` (with the `cdp` capability), `slicc open`, `slicc pair` and `slicc unpair` (seven in your everyday browser, without CDP), `slicc <join-url> follow`, `slicc tray` (on a machine and inside seven), remote control with `prompt`, `watch` and `abort` (also from inside seven's kernel, see [Inside seven](#inside-seven)), host folders with `--mount`, `slicc browsers`, `slicc launch`, `update`, `install`, `--version` and `--help` work so far, plus a hidden diagnostic, `slicc <join-url> follow --signal-only [--timeout 2m]`. It attaches through the tray hub, prints a summary of the leader's offer (its size, media sections, candidate count and DTLS fingerprint) and the ICE server URLs (credentials are never printed), and exits without answering. The link protocol is specified in [Link protocol](#link-protocol).
5
+ **Status:** being built. `slicc` (the default flow), `slicc attach` (with the `cdp` capability), `slicc open`, `slicc pair` and `slicc unpair` (seven in your everyday browser, without CDP), `slicc <join-url> follow`, `slicc tray` (on a machine and inside seven), remote control with `prompt`, `watch`, `wait` and `abort` (also from inside seven's kernel, see [Inside seven](#inside-seven)), host folders with `--mount`, `slicc browsers`, `slicc launch`, `update`, `install`, `--version` and `--help` work so far, plus a hidden diagnostic, `slicc <join-url> follow --signal-only [--timeout 2m]`. It attaches through the tray hub, prints a summary of the leader's offer (its size, media sections, candidate count and DTLS fingerprint) and the ICE server URLs (credentials are never printed), and exits without answering. The link protocol is specified in [Link protocol](#link-protocol).
6
6
 
7
7
  ## Commands (planned)
8
8
 
@@ -15,8 +15,8 @@
15
15
  | `slicc tray [--json] [-q] [-a]` | list the `slicc` processes on this machine that hold a link: mode, seven, device, state and offers (works now; see [Running links](#running-links-slicc-tray)) |
16
16
  | `slicc launch` | launch a browser with CDP in a separate SLICC profile and print its CDP URL |
17
17
  | `slicc <join-url> follow [--exit] [--runner …] [--cdp <url>] [--mount <path>]` | follow a seven's tray from another machine and offer its network, compute (over SSH), browsers or folders (`--exit`, `--runner`, `--cdp` and `--mount` work now; see [Remote setup](#remote-setup-slicc-join-url-follow)). `-` or `@<file>` in place of `<join-url>` reads it from stdin or a file, out of sight of `ps` |
18
- | `slicc <join-url> prompt <text>`, `watch`, `abort` | send a prompt to seven's agent and stream its answer, follow the agent as it works, or abort its run; `--cdp <url>` instead of a join URL links locally (works now; see [Remote control](#remote-control-slicc-prompt-watch-and-abort)) |
19
- | `slicc <join-url> prompt`, `watch`, `abort` inside seven | the same commands from seven's kernel, as `@ai-ecoverse/wasi-slicc` (works now; see [Inside seven](#inside-seven)) |
18
+ | `slicc <join-url> prompt <text>`, `watch`, `wait`, `abort` | send a prompt to seven's agent and stream its answer, follow the agent as it works, wait until it has nothing left to do, or abort its run; `--cdp <url>` instead of a join URL links locally (works now; see [Remote control](#remote-control-slicc-prompt-watch-wait-and-abort)) |
19
+ | `slicc <join-url> prompt`, `watch`, `wait`, `abort` inside seven | the same commands from seven's kernel, as `@ai-ecoverse/wasi-slicc` (works now; see [Inside seven](#inside-seven)) |
20
20
  | `slicc tray [url \| rotate \| unlink <device> \| retry]` inside seven | this seven's tray: its state and devices, the join URL on request, rotate it, drop a device, reconnect (see [Inside seven](#inside-seven)) |
21
21
  | `slicc browsers --json` | list running CDP endpoints and installed browsers, ranked |
22
22
  | `slicc update [--check]` | replace this binary with the latest release (works now; see [Updates](#updates)) |
@@ -299,7 +299,7 @@ Release builds outside npm and app bundles print a notice on stderr when a newer
299
299
  ## Telemetry
300
300
 
301
301
  Release builds (a plain `X.Y.Z` version, linked in or, for `go install`, from the module version) send operational telemetry through [go-optel](https://github.com/ai-ecoverse/go-optel) with the app id `slicc-cli`, sampled once per process (1 in 100 by default):
302
- - `enter`, with the subcommand as `source`, from a fixed list (`abort`, `attach`, `browsers`, `follow`, `install`, `launch`, `open`, `pair`, `prompt`, `unpair`, `update`, `watch`, `default` for no command (no arguments, or only flags), `join` for a bare join URL, otherwise `unknown`). No other argument is ever sent.
302
+ - `enter`, with the subcommand as `source`, from a fixed list (`abort`, `attach`, `browsers`, `follow`, `install`, `launch`, `open`, `pair`, `prompt`, `unpair`, `update`, `wait`, `watch`, `default` for no command (no arguments, or only flags), `join` for a bare join URL, otherwise `unknown`). No other argument is ever sent.
303
303
  - `error`, for operational failures, from a fixed set of sources (`update`, `signal`, `link`, `browser`, `ssh`, `cdp`). Messages pass through go-optel's sanitizer, which strips URLs and paths.
304
304
 
305
305
  `--version`, and any command line with `--help`, `-h` or `-help` (such as `slicc update --help`), send nothing, and development builds never configure a client.
@@ -737,7 +737,7 @@ Link spec §5.14 (J1). slicc-jerk (`jerk`, [Companion tools](#companion-tools))
737
737
  **Offered** when host jerk is found: of the first `jerk` on `PATH` and `jerk` in the data folder's `bin`, in that order, the first whose `jerk --version` names 0.6.0 or later. 0.6.0 is the first slicc-jerk with the `--via-link` calls below. An older jerk counts as absent: slicc says `jerk: host jerk <version> is older than 0.6.0; run slicc install jerk`, and HELLO has neither cap.
738
738
  - `slicc` and `slicc attach`: caps `jerk` and `jerk-seal`, unless `--no-jerk`.
739
739
  - `follow`: only with `--jerk` (cap `jerk`) or `--jerk-seal` (both).
740
- - `prompt`, `watch` and `abort`: never.
740
+ - `prompt`, `watch`, `wait` and `abort`: never.
741
741
  - slicc says `jerk: offering slicc-jerk <version> (jerk, jerk-seal)`, and HELLO adds `"jerk": { "version" }`. Without the cap an OPEN gets `EOPNOTSUPP`.
742
742
 
743
743
  **OPEN** `{ "kind": "jerk", "op", "provider"?, "scope"?, "lease_id"?, "duration"?, "params"? }`. The page sends END right after it. slicc runs jerk as the user, with no terminal and its stderr dropped:
@@ -1089,7 +1089,7 @@ slicc @<file> follow [flags]
1089
1089
 
1090
1090
  `follow` links this machine to a seven on another machine through the tray hub (see [Tray hub signaling](#tray-hub-signaling-remote-setup)). It serves the link until interrupted (`SIGINT`, `SIGTERM`) and reconnects when the link drops. Status lines go to stderr, and `SLICC_DEBUG=1` adds diagnostics. The join URL is never printed.
1091
1091
 
1092
- **The join URL off the command line.** On the command line, `ps` shows the join URL to every user of this machine. In its place, `-` reads it from stdin and `@<file>` from a file: the first non-empty line, trimmed. From stdin slicc reads only up to that line's end, so the rest of stdin is left for `prompt -`. The file must be a regular file, not a symlink. On macOS and Linux it must also belong to you and be readable by no one else (`chmod 600`). Exit 2 follows when there's no join URL, when the file can't be read, breaks those rules or is over 64 KiB, or when what's there isn't a join URL. The message names the file but never shows what it holds, inside seven too. `prompt`, `watch` and `abort` take `-` and `@<file>` the same way, inside seven too. There is no environment variable for it, because `--runner`'s processes would inherit it.
1092
+ **The join URL off the command line.** On the command line, `ps` shows the join URL to every user of this machine. In its place, `-` reads it from stdin and `@<file>` from a file: the first non-empty line, trimmed. From stdin slicc reads only up to that line's end, so the rest of stdin is left for `prompt -`. The file must be a regular file, not a symlink. On macOS and Linux it must also belong to you and be readable by no one else (`chmod 600`). Exit 2 follows when there's no join URL, when the file can't be read, breaks those rules or is over 64 KiB, or when what's there isn't a join URL. The message names the file but never shows what it holds, inside seven too. `prompt`, `watch`, `wait` and `abort` take `-` and `@<file>` the same way, inside seven too. There is no environment variable for it, because `--runner`'s processes would inherit it.
1093
1093
 
1094
1094
  **Flags.**
1095
1095
  - `--exit`: offer this machine's network to seven, as `tcp` and `resolve` streams (cap `net`), `http` streams (cap `http`), `ws` streams (cap `ws`) and `udp` streams (cap `udp`) under the remote policy, so public addresses only by default. Without `--exit`, all five are refused with `EOPNOTSUPP`.
@@ -1113,16 +1113,18 @@ HELLO from `follow`: `{ "v": 1, "role": "node", "name", "host", "version", "mode
1113
1113
 
1114
1114
  **Stops** with exit 1 and says why on `INVALID_JOIN_CAPABILITY`, `TRAY_EXPIRED` or `TRAY_SUPERSEDED_MISSING_JOIN_URL` from the hub, and on `UNTRUSTED`, `UNSUPPORTED_RUNTIME` or `NO_FINGERPRINT` (an internal error: the answer had no SHA-256 fingerprint) from seven. The device's fingerprint is always SHA-256.
1115
1115
 
1116
- ## Remote control: `slicc prompt`, `watch` and `abort`
1116
+ ## Remote control: `slicc prompt`, `watch`, `wait` and `abort`
1117
1117
 
1118
1118
  ```
1119
- slicc <join-url> prompt [--steer | --reject] [--thinking] [--json] [--plain] [--abort-on-interrupt] <text>|@file|-
1119
+ slicc <join-url> prompt [--allsettled <quiet>] [--steer | --reject] [--thinking] [--json] [--plain] [--abort-on-interrupt] <text>|@file|-
1120
1120
  slicc <join-url> watch [--thinking] [--json] [--plain]
1121
+ slicc <join-url> wait [--allsettled <quiet>] [--timeout <limit>] [--json]
1121
1122
  slicc <join-url> abort
1122
1123
  slicc prompt --cdp <url> [--origin <origin>]... [flags] <text>|@file|-
1123
1124
  slicc watch --cdp <url> [--origin <origin>]... [flags]
1125
+ slicc wait --cdp <url> [--origin <origin>]... [flags]
1124
1126
  slicc abort --cdp <url> [--origin <origin>]...
1125
- slicc prompt|watch|abort --signal stdio [flags] …
1127
+ slicc prompt|watch|wait|abort --signal stdio [flags] …
1126
1128
  ```
1127
1129
 
1128
1130
  These commands talk to seven's agent over a link that offers nothing to seven (`caps: []`).
@@ -1152,6 +1154,28 @@ These commands talk to seven's agent over a link that offers nothing to seven (`
1152
1154
  - `130` on Ctrl-C or `SIGTERM`.
1153
1155
  - **Ctrl-C** leaves the run going in seven. With `--abort-on-interrupt`, slicc first opens `abort`.
1154
1156
 
1157
+ **`prompt --allsettled <quiet>`** (for benchmarks and scripts) goes on after the prompt's run until seven has nothing left to do. The cone can end a run while scoops it started are still working, and run again when their results come in. `<quiet>` is a duration such as `2m` or `0s`.
1158
+ - **Needs** a seven whose agent is @ai-ecoverse/slicc-agent 6.15.0 or later, the first that reports `busy`. `wait` needs it too.
1159
+ - **Settled** means seven says it isn't busy (`busy` false, see [`agent`](#agent-page-cap-agent-node--page) below), and nothing has come from seven for `<quiet>`. The quiet period starts once the stream is open, and every line from seven restarts it.
1160
+ - **A seven that doesn't report `busy`:** before sending anything, slicc opens a `watch` with `busy`. When seven's answer doesn't say whether it's busy, slicc says `this seven doesn't report when its agent is idle; update it` and exits 1. The prompt isn't sent.
1161
+ - **Output:** the prompt's run streams as usual. After its `end`, slicc opens `watch` with `busy`, and `since` the last event it showed, so the cone's later runs stream as they would in `watch`, with nothing shown twice.
1162
+ - **`--json`:** the prompt's events up to its `end` line, then the watch's events, as seven sent them. The last line is slicc's own `{"t":"settled"}`.
1163
+ - **Exit status:** the prompt's own run decides. An `end` with `error` or `aborted` exits 1 at once, as without `--allsettled`. Otherwise slicc exits 0 once seven has settled, whatever the later runs did.
1164
+ - A stream or link that ends before seven has settled exits 1 (`lost the link to seven; the run goes on there`).
1165
+ - Bad usage, a missing permission and Ctrl-C exit as for `prompt` above.
1166
+ - **No time limit of its own.** A lick that's held in seven's outbox keeps seven busy, and so does a scoop that never finishes. Bound the wait with the caller's own timeout, or with `wait --timeout`.
1167
+
1168
+ **`wait`** follows the agent without sending anything, and exits once seven has settled, as `prompt --allsettled` does. `--allsettled <quiet>` sets the quiet period (default `0s`: exit as soon as seven isn't busy).
1169
+ - **Output:** `slicc: seven is idle` on stderr, and nothing on stdout. With `--json`, the events as seven sent them, then `{"t":"settled"}`.
1170
+ - **`--timeout <limit>`:** give up after `<limit>` (default: no limit). slicc says `seven didn't settle within <limit>` and exits 124.
1171
+ - **Exit status:**
1172
+ - `0` once seven has settled;
1173
+ - `1` for a seven that doesn't report `busy`, and for a stream or link that ends first;
1174
+ - `2` for bad usage;
1175
+ - `3` without permission;
1176
+ - `124` on timeout;
1177
+ - `130` on Ctrl-C or `SIGTERM`.
1178
+
1155
1179
  **`watch`** follows the agent until Ctrl-C or `SIGTERM`, then exits 0.
1156
1180
  - **Output:** `user` events go to stdout as `> <text>`, on one line. Assistant text goes to stdout as for `prompt`, and a line ends at each run's end. Everything else goes to stderr, as for `prompt`, plus `run ended: <reason>` for a run that didn't end with `stop`. `--json` prints the events instead.
1157
1181
  - **Status lines** on stderr: `slicc: watching <name>`, `slicc: lost the link to <name>; reconnecting`, and for the tray `<reason>; trying again in <wait>`.
@@ -1190,10 +1214,11 @@ Summaries are one line of at most 200 characters. Escape sequences and control c
1190
1214
  - The page then delivers it. Its first line is `{"t":"delivered","delivered"}`, or it resets with `EBUSY` instead.
1191
1215
  - **Aborting:** a RESET from the node, or a closed link, doesn't abort the run. Only `abort` does.
1192
1216
 
1193
- **`watch`:** `OPEN { "kind": "agent", "op": "watch", "since"?: "<entry id>", "thinking"?: true }` on its own channel.
1194
- - **Answer:** OPENED `{ "head": "<entry id>", "gap"?: true }`, then NDJSON events until either side resets.
1217
+ **`watch`:** `OPEN { "kind": "agent", "op": "watch", "since"?: "<entry id>", "thinking"?: true, "busy"?: true }` on its own channel.
1218
+ - **Answer:** OPENED `{ "head": "<entry id>", "gap"?: true, "busy"?: true | false }`, then NDJSON events until either side resets.
1195
1219
  - **Without `since`:** the events start at the next one.
1196
1220
  - **With `since`:** the page first replays `since`'s own entry when it's `text` or `thinking` (its whole text so far, as one `delta`), then every entry after it. `gap: true` means the transcript no longer holds `since`, and the events start at the next one.
1221
+ - **With `busy`** (`prompt --allsettled` and `wait`): OPENED says whether the agent has anything left to do, and a `busy` line follows each time that changes. An OPENED without `busy` means seven doesn't report it.
1197
1222
 
1198
1223
  **`abort`:** `OPEN { "kind": "agent", "op": "abort" }`, answered OPENED `{ "aborted": true | false }` (`false` when nothing was running), then END.
1199
1224
 
@@ -1210,6 +1235,7 @@ Summaries are one line of at most 200 characters. Escape sequences and control c
1210
1235
  | `{"t":"notice","id","text"}` | retries, compactions, rewinds |
1211
1236
  | `{"t":"error","id","message","detail"?}` | an error |
1212
1237
  | `{"t":"delivered","delivered"}` | a long prompt was taken (`prompt` only) |
1238
+ | `{"t":"busy","busy","why"?}` | the agent became busy or idle (`watch` with `busy` only) |
1213
1239
  | `{"t":"end","reason","message"?}` | the last line of a `prompt` stream |
1214
1240
 
1215
1241
  - **Ids:** `id` is the transcript entry id, and `delta` lines for one `id` arrive in order.
@@ -1261,8 +1287,9 @@ PID MODE SEVEN DEVICE STATE OFFERS
1261
1287
  `slicc` also runs inside seven's kernel, so that one seven's agent or user can prompt, watch and abort another seven's agent, and see and manage this seven's own tray. That build is `slicc.wasm`, slicc-cli's client commands compiled with `GOOS=wasip1 GOARCH=wasm` and `CGO_ENABLED=0`, and it ships as the npm package `@ai-ecoverse/wasi-slicc`, at slicc-cli's own version. seven's page holds the WebRTC link; slicc only reaches the page's link facade.
1262
1288
 
1263
1289
  ```
1264
- slicc <join-url> prompt [--steer | --reject] [--thinking] [--json] [--plain] <text>|@file|-
1290
+ slicc <join-url> prompt [--allsettled <quiet>] [--steer | --reject] [--thinking] [--json] [--plain] <text>|@file|-
1265
1291
  slicc <join-url> watch [--thinking] [--json] [--plain]
1292
+ slicc <join-url> wait [--allsettled <quiet>] [--timeout <limit>] [--json]
1266
1293
  slicc <join-url> abort
1267
1294
  slicc tray [--json]
1268
1295
  slicc tray url
@@ -1273,7 +1300,7 @@ slicc --version
1273
1300
  slicc --help
1274
1301
  ```
1275
1302
 
1276
- - **Commands:** `prompt`, `watch` and `abort` with a join URL behave as in [Remote control](#remote-control-slicc-prompt-watch-and-abort): the same flags, output, styling, `--json` events, resuming and exit codes, from the same code. The differences:
1303
+ - **Commands:** `prompt`, `watch`, `wait` and `abort` with a join URL behave as in [Remote control](#remote-control-slicc-prompt-watch-wait-and-abort): the same flags, output, styling, `--json` events, resuming and exit codes, from the same code. The differences:
1277
1304
  - **Ctrl-C** ends slicc with 130 (the kernel's default for `SIGINT`), `watch` included, and a running prompt goes on in the other seven. `--abort-on-interrupt` isn't offered.
1278
1305
  - **Exit 3** covers the facade's own refusals too. When the facade gives a message (`unlock the vault to continue`, or the other seven's refusal), slicc prints it instead of the Linked devices hint.
1279
1306
  - **A terminal** is a standard stream that is a character device. Styling then follows `TERM`, `NO_COLOR` and `--plain` as usual.
@@ -1286,7 +1313,7 @@ slicc --help
1286
1313
  - **`slicc tray retry`** reconnects the tray's links, as the Reconnect button does.
1287
1314
  - **Not here:** choosing the exit (that's routing, not tray state), and SLICC six's `host join` and `host leave`: a seven follower runs no kernel or agent of its own, so following stays with `#follow=` and the UI's Leave.
1288
1315
  - **Exit status:** 0, 1 on failure (`ENOTCONN` when the tray isn't connected, a facade that doesn't answer within 1 minute, or 5 minutes for `rotate` and `unlink`, which seven may ask you to approve), 2 for bad usage, 3 when seven refuses (`EACCES`).
1289
- - **Everything else** exits 2 with `slicc: <command> isn't available inside seven`: `follow`, `attach`, `open`, `browsers`, the default flow, `update`, `install`, and `prompt`, `watch` or `abort` without a join URL. `--help` lists only what works there.
1316
+ - **Everything else** exits 2 with `slicc: <command> isn't available inside seven`: `follow`, `attach`, `open`, `browsers`, the default flow, `update`, `install`, and `prompt`, `watch`, `wait` or `abort` without a join URL. `--help` lists only what works there.
1290
1317
  - **What the build leaves out** (build constraints): pion and the link, CDP, SSH, mounts, the kernel listener, the policy, browser discovery, telemetry and updates.
1291
1318
 
1292
1319
  **The link facade.** slicc reads its address from `SLICC_LINK_URL` only, as `tcp://127.0.0.1:<port>` on the kernel's loopback (any `127.x` address, or `localhost`). Without it, or with another shape, slicc exits 1. Each `agent` stream (see [`agent`](#agent-page-cap-agent-node--page)) is one connection, carrying records of a `u8` type, a `u32` big-endian length and the payload, both ways:
@@ -1657,8 +1684,8 @@ On a [§1.3](#13-local-setup-without-cdp-loopback-signalling) loopback link, `un
1657
1684
  - **Auto-attached targets with no URL yet** (OOPIFs, popups) are held until the URL is known, then detached if protected. After 10 s with no URL they are treated as protected. The node's own setup connection ([§1.1](#11-local-setup-over-cdp)) isn't a `cdp` stream and is the one exception. [`cdp` (browser control)](#cdp-browser-control) has the details.
1658
1685
  - **Protection follows the target's own effective origin. Execution contexts on a protected origin are hidden, not cut,** unless the context is the target's own main-frame default context; that one still cuts the target as above. The typical case is an extension's content-script isolated world (`chrome-extension://<id>`) on an ordinary page. The page stays usable, and the hidden world is invisible and out of reach.
1659
1686
  - **Hidden:** the node learns every context of a touched target on its own guard session, whatever the page enabled. It drops these events from the stream: the world's `Runtime.executionContextCreated` and `executionContextDestroyed`, its `consoleAPICalled`, `exceptionThrown` and `bindingCalled`, and `Debugger.scriptParsed`/`scriptFailedToParse` for scripts in it. It also drops `Debugger.breakpointResolved` in those scripts. A `Debugger.paused` whose top frame is in the world is dropped, and the node resumes the target. The world's frames lower in the stack are removed from the call frames.
1660
- - **Refused** with `slicc: refused: that execution context belongs to a browser extension`: any command that names the world through a `contextId` or `executionContextId`, `uniqueContextId`, an `executionContextName` the world has, a remote `objectId` or `*ObjectId` (call arguments included) or `callFrameId` whose injected-script part is the world, or the `scriptId` of a script in it. So `Runtime.evaluate`, `callFunctionOn`, `compileScript`, `runScript`, `globalLexicalScopeNames`, `queryObjects`, `getProperties`, `addBinding`, `Debugger.evaluateOnCallFrame`, `setVariableValue`, `setScriptSource` and `DOM.resolveNode` there are all refused. The default world, and isolated worlds the page creates itself, are unaffected. On page-like sessions, a `Runtime.addBinding` with neither `executionContextId` nor `executionContextName` is sent with `executionContextName: ""`, so it reaches every frame's main world now and after reloads, but no isolated world.
1661
- - **Lifetime:** a hidden world is forgotten only when Chrome reports it gone (`executionContextDestroyed`, or `executionContextsCleared` on a session that reported it), never to make room. A target with more than 4096 live hidden worlds is refused every command there that names an execution context, object, call frame, script or context name, until its contexts are cleared.
1687
+ - **Refused** with `slicc: refused: that execution context belongs to a browser extension`: any command that names the world through a `contextId` or `executionContextId`, `uniqueContextId`, an `executionContextName` the world has, a remote `objectId` or `*ObjectId` (call arguments included) or `callFrameId` whose injected-script part is the world, or the `scriptId` of a script in it. So `Runtime.evaluate`, `callFunctionOn`, `compileScript`, `runScript`, `globalLexicalScopeNames`, `queryObjects`, `getProperties`, `addBinding`, `Debugger.evaluateOnCallFrame`, `setVariableValue`, `setScriptSource` and `DOM.resolveNode` there are all refused. The default world, and isolated worlds the page creates itself, are unaffected. A `uniqueContextId` on a target's session that names no live context the node has seen announced on that target, on its guard session or the page's (say one from a closed tab or another live tab, or made up), is refused with `slicc: refused: that execution context is not exposed`, rather than passed to Chrome. On page-like sessions, a `Runtime.addBinding` with neither `executionContextId` nor `executionContextName` is sent with `executionContextName: ""`, so it reaches every frame's main world now and after reloads, but no isolated world.
1688
+ - **Lifetime:** a hidden world is forgotten only when Chrome reports it gone (`executionContextDestroyed`, or `executionContextsCleared` on a session that reported it), never to make room. A target with more than 4096 live hidden worlds is refused every command there that names an execution context, object, call frame, script or context name, until its contexts are cleared. Seen contexts follow the same lifetime and bound; once a target passes 4096, the `uniqueContextId`s of contexts announced after that are refused as not exposed until its contexts are cleared, even if some are destroyed in between.
1662
1689
  - **Heap profiling:** a page's heap snapshot covers its whole renderer, other worlds included. So on page, iframe, background page and webview sessions every `HeapProfiler` command except `enable`, `disable`, `collectGarbage` and `getHeapObjectId` is refused with `slicc: refused: HeapProfiler reads the page's whole renderer, browser extensions' worlds included`, whether or not an extension is there.
1663
1690
  - **Breakpoint conditions** run in whatever world the script belongs to, and a breakpoint by URL outlives reloads. So on those sessions a `Debugger.setBreakpointByUrl` with a `condition` needs a non-empty `url`, which can't name a protected script (see above). One by `urlRegex` or `scriptHash` or with an empty `url` is refused with `slicc: refused: a breakpoint condition that could run in a browser extension's world needs a url naming the page's own script`. Breakpoints without a condition are allowed; a pause they cause in a hidden world is resumed out of sight.
1664
1691
  - **Profiles, coverage, stacks and initiators** can name any script in the isolate. So the node scrubs every message it sends the page, events and command results alike, outside opaque values (`value`, `preview`, `customPreview`, `arguments`, `returnValue`). Any `callFrames` list loses the frames on a protected URL or in a hidden world's script. That covers console, exception, pause, async, node-creation and initiator stacks, whatever the method. A coverage or type-profile list (entries with `scriptId` and `functions` or `entries`) also loses its entries for scripts without a URL. A profile node's `callFrame` in such a script becomes `(program)` and loses its `positionTicks`. An `initiator` on a protected `url` loses that `url` and its position.
@@ -1734,14 +1761,14 @@ slicc-node's hostfs ([its README, *Host folders*](https://github.com/ai-ecoverse
1734
1761
  - Paths go through `\\?\`, so device names and 8.3 names are plain names inside the folder.
1735
1762
 
1736
1763
  #### 5.11 `agent` (page cap `agent`), node → page: remote control
1737
- `slicc prompt`, `slicc watch` and `slicc abort` talk to seven's agent, the cone, which slicc-agent hosts. The page serves each stream through `remoteControl(connection)` from `@ai-ecoverse/slicc-agent/page`, on top of its `AgentConnection`, so the CLI never speaks pi's protocol.
1764
+ `slicc prompt`, `slicc watch`, `slicc wait` and `slicc abort` talk to seven's agent, the cone, which slicc-agent hosts. The page serves each stream through `remoteControl(connection)` from `@ai-ecoverse/slicc-agent/page`, on top of its `AgentConnection`, so the CLI never speaks pi's protocol.
1738
1765
 
1739
1766
  - **Who may:** the page advertises `agent` only to links the user allowed to control it.
1740
1767
  - A **local** link ([§1.1](#11-local-setup-over-cdp)) gets it by default, because a CLI holding the browser's CDP can drive the page anyway.
1741
1768
  - A **remote** link gets it only after the user turns on *Allow remote control* for that device in Linked devices. It's off by default, and keyed on the fingerprint.
1742
1769
  - Seven lists every device that has linked once, even one that's offline or offered no caps, so the toggle can be found after a refused `prompt`.
1743
1770
  - Without the cap, the node doesn't open `agent` streams, and the page refuses them with `EACCES`.
1744
- - **Control-only links:** `prompt`, `watch` and `abort` links advertise `caps: []`. The page gives them no `<host>.slicc.internal`, no exit entry, and opens no `kernel` streams to them.
1771
+ - **Control-only links:** `prompt`, `watch`, `wait` and `abort` links advertise `caps: []`. The page gives them no `<host>.slicc.internal`, no exit entry, and opens no `kernel` streams to them.
1745
1772
  - **One device, several processes:** the node's HELLO ([§4](#4-hello)) and the [§1.1](#11-local-setup-over-cdp) hello both carry a random per-process `"node"` id.
1746
1773
  - The page replaces an older link of the same device (local: any local link; remote: the same fingerprint) only when `node` matches.
1747
1774
  - Over the tray, the page learns `node` at HELLO, so any replacement waits for HELLO.
@@ -1761,6 +1788,21 @@ slicc-node's hostfs ([its README, *Host folders*](https://github.com/ai-ecoverse
1761
1788
  - **Without `since`,** the stream starts at the next event.
1762
1789
  - **With `since`,** the page first replays `since`'s own entry when it's `text` or `thinking`, as one `delta` with its whole text so far. Then it replays every entry after it. Clients skip what they already printed.
1763
1790
  - **`gap: true`** means the transcript no longer holds `since` (a new session, or a compaction). The stream then starts at the next event.
1791
+ - **`busy`** (`"busy": true` in the OPEN) is for `slicc prompt --allsettled` and `slicc wait`. The cone can end a run while scoops it started are still working, and run again when their results come in as `scoop-notify` licks. A client that sees only the cone's events can't tell that apart from being done.
1792
+ - **OPENED** carries `"busy": true | false`, the state after any replay. A page that doesn't support it leaves `busy` out, and the node then reports that seven doesn't support it.
1793
+ - **Then** the page sends `{"t":"busy","busy":true|false}` each time the value changes, in order with the other events. It has no `id`, and it's never replayed.
1794
+ - **`busy` is true** while, for the cone the stream belongs to:
1795
+ - the cone has a run or a queued input;
1796
+ - a live scoop of that cone has a run, a queued input or a feed;
1797
+ - a lick for the cone is queued or still to be delivered (a `scoop-notify` result, or a scoop `wait`'s delivery). That includes a lick held in the agent's outbox until its conversation's model is known. If the model never comes, `busy` stays true, so the client bounds its wait.
1798
+ - **It turns false** only when none of that holds. A lick from outside (a cron, a file watch) counts once it's queued, not before.
1799
+ - **`why`:** a `busy: true` line may carry `"why"`, a list of what keeps the agent busy, to be logged. The node doesn't use it, and it's left out when `busy` is false. The values come from a fixed list:
1800
+ - `"cone"`: the cone has a run or a queued input;
1801
+ - `"scoop:<name>"`: that live scoop (its name, as seven shows it) has a run, a queued input or a feed;
1802
+ - `"pending-lick"`: a lick for the cone is queued or still to be delivered.
1803
+ - **Read-only status:** `busy` lines carry only the boolean and `why`. They never carry prompt text, tool arguments or output, and asking for `busy` changes nothing in the agent.
1804
+ - **Ordering:** a `run start` never comes before the `busy: true` that covers it, and the `busy: false` comes after the last `run end`.
1805
+ - **Computed** from the durable documents' subscriptions (the cone's and its scoops' `pi.live`, `ScoopWorkDoc.feeds` and the licks outbox), and a line goes out only when the value flips.
1764
1806
  - **Events:** one JSON object per line, mapped by slicc-agent from pi-durable's agent events (`watchEvents`) and handed to the page by `remoteControl(connection)` from `@ai-ecoverse/slicc-agent/page`.
1765
1807
  - `{"t":"user","id","text","delivered"}`;
1766
1808
  - `{"t":"text","id","delta"}`: assistant text as it streams;
@@ -1768,7 +1810,8 @@ slicc-node's hostfs ([its README, *Host folders*](https://github.com/ai-ecoverse
1768
1810
  - `{"t":"tool","id","call","name","summary"}` and `{"t":"tool-result","id","call","ok","summary"}`;
1769
1811
  - `{"t":"run","state":"start"|"end","reason"?}`. These have no `id`, so a resume doesn't replay a missed `run end`. Clients use them only for layout and notices, and the `end` line or the next `user` event is authoritative.
1770
1812
  - `{"t":"notice","id","text"}`: retries, compactions, rewinds;
1771
- - `{"t":"error","id","message","detail"?}`.
1813
+ - `{"t":"error","id","message","detail"?}`;
1814
+ - `{"t":"busy","busy":true|false,"why"?:[…]}`: only on `watch` streams opened with `busy` (above).
1772
1815
  - **Ids** are opaque strings.
1773
1816
  - `user`, `tool-result`, and a `notice` or `error` that is a transcript entry: the entry id, such as `"42"`.
1774
1817
  - An assistant message's `text`, `thinking` and `tool` blocks: `"a<ts>.<block>"`, where `<ts>` is the message's own timestamp (set when its generation starts, and kept in the committed entry) and `<block>` its content index. An assistant message isn't an entry until it's committed, so this id is stable from the first delta to the committed entry. A second message with the same timestamp gets `"a<ts>~1.<block>"`, a third `~2`, and so on.
@@ -1840,7 +1883,7 @@ jerk ([ai-ecoverse/slicc-jerk](https://github.com/ai-ecoverse/slicc-jerk)) gets
1840
1883
  |---|---|---|
1841
1884
  | `slicc`, `slicc attach` (local) | yes, when `jerk` ≥ the minimum version is on the host's `PATH` or in slicc's data dir. `--no-jerk` turns both off. | yes, by default |
1842
1885
  | `slicc <join> follow` (remote) | only with an explicit `--jerk` | only with an explicit `--jerk-seal`, which implies `--jerk`. A remote seven pulling this machine's tokens into its browser is a bigger grant than starting a sign-in. |
1843
- | `prompt`, `watch`, `abort` | no | no |
1886
+ | `prompt`, `watch`, `wait`, `abort` | no | no |
1844
1887
  | any node without host jerk | no. Host providers are missing in seven. | no |
1845
1888
 
1846
1889
  HELLO adds `"jerk": { "version": "1.0.0" }` next to `caps`.
@@ -1931,7 +1974,7 @@ From [slicc-bios#360](https://github.com/ai-ecoverse/slicc-bios/pull/360) and [s
1931
1974
  How a kernel program in seven reaches [§1.4](#14-a-seven-as-follower-leader-to-leader), and this seven's own tray. This isn't a link stream. It's seven's page serving its own kernel. The page holds the WebRTC; the program never sees the hub, the join state or the peer connection.
1932
1975
 
1933
1976
  - **The program:** `@ai-ecoverse/wasi-slicc`, slicc-cli's client command layer built for `GOOS=wasip1` (published by slicc-cli, offered by bios's catalog).
1934
- - **Commands:** `slicc <join-url> prompt|watch|abort`, with the CLI's own flags, output and `--json` events, and `slicc tray` (below).
1977
+ - **Commands:** `slicc <join-url> prompt|watch|wait|abort`, with the CLI's own flags, output and `--json` events, and `slicc tray` (below).
1935
1978
  - **Anything else** exits 2 with `slicc: <command> isn't available inside seven`. A prompt without a join URL is refused the same way.
1936
1979
  - **How it reaches the facade:** through its host module, at `SLICC_LINK_URL` (below).
1937
1980
  - **Where it's served:** a page-served kernel facade with the caller's stamp on each connection, mirroring the CDP facade on `127.0.0.1:9222`. The mechanism is [slicc-kernel#526](https://github.com/ai-ecoverse/slicc-kernel/issues/526), shipped in [slicc-kernel 1.90.0](https://github.com/ai-ecoverse/slicc-kernel/tree/v1.90.0#page-facades) ([#556](https://github.com/ai-ecoverse/slicc-kernel/pull/556)):
@@ -2088,9 +2131,9 @@ semantic-release cuts releases from `main` in `.github/workflows/release.yml`, o
2088
2131
  6. `scripts/go-warm.sh <version>`, once the tag is on `origin`, asks `proxy.golang.org` for the module at `v<version>` (`go list -m` with a scratch module cache) and asks `pkg.go.dev` to fetch it. The proxy fetch is retried briefly; the `pkg.go.dev` fetch is one attempt of at most 10 s, since the proxy fetch already gets the version indexed. Both only warn, and the step can't fail the release.
2089
2132
 
2090
2133
  **Certification in the pull request** (`.github/workflows/cert-review-pr.yml`, `tools/cert-review/`). Every same-repo pull request gets the commit status `cert-review` on its head, which the merge queue requires beside `ci`. Fork pull requests get none: only Lars merges one. Every tool runs from the pull request's base commit, main's copy, never from the code under test, which is only built and tested; the review uses `refs/pull/N/merge` and records its first parent and the head.
2091
- - **plan** (light runner) runs on opened, synchronize, reopened, and `merge-ok` or `cert-review-approved` being added (or the approval removed), and plans the whole run again, since such an event cancels a run in progress; other labels neither start nor cancel anything. A `pending` status left on the head by a run that ended without a result becomes `error` (re-run the failed jobs), so the check never waits forever. The shared self-guard (`cert-self-guard`, pinned) holds a change to the reviewer's own paths (`REVIEWER_GLOBS` in `tools/cert-review/lib.mjs`: all of `.github/**`, every workflow and action, so no pull request's own workflow can post `cert-review`, and `tools/cert-review/**`) until a coordinator puts `cert-review-approved` on that head. Such pull requests always go to the coordinator before queueing.
2134
+ - **plan** (light runner) runs on opened, synchronize, reopened, ready_for_review, converted_to_draft, and `cert-review-approved` being added or removed, and plans the whole run again, since such an event cancels a run in progress; other labels neither start nor cancel anything. **Draft status replaces the old `merge-ok` label:** a draft is neither built nor reviewed and its `cert-review` is red `draft: not reviewed, mark it ready for review`, so an older result on the same head can't satisfy the check; **mark ready = reviewed, and merges on green**. With the hold rule (held = draft) the order for a PR that needs the coordinator's security or link-spec read is: the coordinator reviews the draft, it is marked ready, the cert runs (with its Claude review), then the queue; a cert finding means a new head, back to draft and a re-read. Renovate's pull requests aren't drafts, so they're reviewed by themselves. A `pending` status left on the head by a run that ended without a result becomes `error` (re-run the failed jobs), so the check never waits forever. The shared self-guard (`cert-self-guard`, pinned) holds a change to the reviewer's own paths (`REVIEWER_GLOBS` in `tools/cert-review/lib.mjs`: all of `.github/**`, every workflow and action, so no pull request's own workflow can post `cert-review`, and `tools/cert-review/**`) until a coordinator puts `cert-review-approved` on that head. Such pull requests always go to the coordinator before queueing.
2092
2135
  - **build** (hosted `ubuntu-latest`, no secrets) builds the merge commit and its first parent the release's way, each in a full clone with its tags: `SLICC_SIGN=0 scripts/package.sh <v>`, `npm-stage.mjs` for every package, and `npm pack`, with one version `X.Y.(Z+1)-pr.N.<run>` on both sides. `outputs.mjs` hashes every release file and tarball.
2093
- - **classify** decides by output where the build can see it: a pull request is behaviour when a binary, the wasm, `SHA256SUMS` or an npm tarball differs from main's build. Paths whose effect the unsigned build never shows are behaviour whatever it outputs: `scripts/**` (signing and notarization, publishing, the release plan, `go-*`, `sliccy-next.mjs`), `install.sh`, `npm/**`, `package.json` and `package-lock.json` (they choose the semantic-release code the release runs), `.releaserc*`, and the reviewer's paths. Otherwise the status is `not behaviour: identical build outputs` (success), so a docs or test change that ships nothing new needs nothing more. Renovate puts `merge-ok` on its pull requests (`renovate.json`), so a dev-pin bump is reviewed by itself and merges on green. A behaviour change without `merge-ok` is `waits for merge-ok to be reviewed` (failure); with it, the review starts.
2136
+ - **classify** decides by output where the build can see it: a pull request is behaviour when a binary, the wasm, `SHA256SUMS` or an npm tarball differs from main's build. Paths whose effect the unsigned build never shows are behaviour whatever it outputs: `scripts/**` (signing and notarization, publishing, the release plan, `go-*`, `sliccy-next.mjs`), `install.sh`, `npm/**`, `package.json` and `package-lock.json` (they choose the semantic-release code the release runs), `.releaserc*`, and the reviewer's paths. Otherwise the status is `not behaviour: identical build outputs` (success), so a docs or test change that ships nothing new needs nothing more. Renovate's pull requests aren't drafts, so a dev-pin bump is reviewed by itself and merges on green. A behaviour change on a draft is `draft: not reviewed, mark it ready for review` (failure); once it's ready, the review starts.
2094
2137
  - **rebuild** (heavy runner) runs [the recipe](#reproducing-a-release) on a `git archive` of the merge commit, in another path on another machine; every release file must be byte-identical to build's.
2095
2138
  - **delta** names the Go tests the pull request adds or changes in `test/integration/*_test.go` (the `func Test…` a hunk falls in). A changed helper counts as changing every test in its file; a helper in a file with no tests is a test gap (`helper <name>`), never a guess.
2096
2139
  - **suite** (heavy runner): the candidate leg runs the whole integration suite on the merge commit on Linux (`go test -json`); the base leg is the NEGATIVE: main's tree with the pull request's whole `test/` diff applied, running only its tests, against main's own binary. A fix whose test fails there and passes on the candidate is `negative`; passing on both is `no-negative`; not compiling or skipping on main is `prev-not-run`. Gaps are known issues, never a FAIL by themselves.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-ecoverse/slicc",
3
- "version": "1.45.0",
3
+ "version": "1.46.0",
4
4
  "description": "SLICC's command line for seven: links a machine's network, compute and browsers to seven over WebRTC",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -18,12 +18,12 @@
18
18
  "node": ">=18"
19
19
  },
20
20
  "optionalDependencies": {
21
- "@ai-ecoverse/slicc-darwin-arm64": "1.45.0",
22
- "@ai-ecoverse/slicc-darwin-amd64": "1.45.0",
23
- "@ai-ecoverse/slicc-linux-arm64": "1.45.0",
24
- "@ai-ecoverse/slicc-linux-amd64": "1.45.0",
25
- "@ai-ecoverse/slicc-windows-arm64": "1.45.0",
26
- "@ai-ecoverse/slicc-windows-amd64": "1.45.0",
21
+ "@ai-ecoverse/slicc-darwin-arm64": "1.46.0",
22
+ "@ai-ecoverse/slicc-darwin-amd64": "1.46.0",
23
+ "@ai-ecoverse/slicc-linux-arm64": "1.46.0",
24
+ "@ai-ecoverse/slicc-linux-amd64": "1.46.0",
25
+ "@ai-ecoverse/slicc-windows-arm64": "1.46.0",
26
+ "@ai-ecoverse/slicc-windows-amd64": "1.46.0",
27
27
  "@ai-ecoverse/slicc-jerk": "^1.0.0"
28
28
  }
29
29
  }