@ai-ecoverse/slicc-bios 1.38.0 → 1.39.4

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
@@ -213,9 +213,9 @@ Below the system rows, Install / Update offers **Optional packages** (spectrum
213
213
  - Anything that isn't `@ai-ecoverse/*` and isn't in the base set is refused; homescoop packages have no third-party dependencies.
214
214
  - **Listing:** each entry's latest goes through the same rules (with its exact `dependencies`) when it's fetched. If latest fails, bios walks back through older versions (in range, not deprecated, at most five; a version whose doc is broken is skipped) and offers the newest that passes, with `newer: { version, reason }` naming latest's blocker. A pinned entry is never walked back. If none passes, the row is `withheld` with that reason, offers no Install or Update, and an installed copy keeps Remove.
215
215
 
216
- Today it offers git, the GitHub CLI, OpenSSH, `slicc` (see [Sevens this kernel follows](#network)), Python, the Python data tools (numpy, pandas and matplotlib), Node.js (slicc-jsh's `node` and `jsh`), `sliccy:browser` for `.jsh` scripts, Ruby, Perl, Biome, the PDF tools (poppler), qpdf, rsync, screen, SQLite, dig, websocat, ntfy, GnuPG, fnox, mcpcat (an MCP client), zip (Info-ZIP's `zip`, `unzip` and `zipinfo`), xxd (vim's hex dump, with `xxd -r`) and ImageMagick. zip's `unzip` refuses an entry whose name isn't UTF-8 (an old Latin-1 or CP437 archive without a Unicode path): it says `cannot create <name>` / `Illegal byte sequence`, extracts the other entries and exits 50, and `unzip -l` still lists the entry. It never extracts it under a changed name, and `unzip -p` still streams its bytes ([homescoop#1174](https://github.com/ai-ecoverse/homescoop/issues/1174)). ImageMagick is homescoop's HEIF build (`wasm-imagemagick-heif`, a superset of the plain build, which isn't offered), with `magick`, `convert`, `mogrify`, `identify` and `magick-open`, and it reads HEIC and AVIF. A failed write leaves an existing target as it was. Its known issues: writing over another user's 0666 file in a sticky directory such as `/tmp` fails with `Operation not permitted`, though writing your own files works ([homescoop#1258](https://github.com/ai-ecoverse/homescoop/issues/1258)); `.mpc` writes fail with `cache resources exhausted` ([homescoop#1208](https://github.com/ai-ecoverse/homescoop/issues/1208)); and the cert's coverage gaps, among them the no-encoder fallback and MPC's two-file write ([homescoop#1209](https://github.com/ai-ecoverse/homescoop/issues/1209)). sudo for `magick`, `convert` or `mogrify` is offered once, never always, since they write files. No two entries' npm `latest` provide the same command, so an install never shadows another entry's; `packages.test` checks that against npm's current `latest`.
216
+ Today it offers git, the GitHub CLI, OpenSSH, `slicc` (see [Sevens this kernel follows](#network)), Python, the Python data tools (numpy, pandas and matplotlib), Node.js (slicc-jsh's `node` and `jsh`), `sliccy:browser` for `.jsh` scripts, Ruby, Perl, Biome, the PDF tools (poppler), qpdf, rsync, screen, SQLite, the BIND tools (`dig`, `host` and `nslookup`), websocat, ntfy, GnuPG, fnox, mcpcat (an MCP client), zip (Info-ZIP's `zip`, `unzip` and `zipinfo`), xxd (vim's hex dump, with `xxd -r`) and ImageMagick. zip's `unzip` refuses an entry whose name isn't UTF-8 (an old Latin-1 or CP437 archive without a Unicode path): it says `cannot create <name>` / `Illegal byte sequence`, extracts the other entries and exits 50, and `unzip -l` still lists the entry. It never extracts it under a changed name, and `unzip -p` still streams its bytes ([homescoop#1174](https://github.com/ai-ecoverse/homescoop/issues/1174)). ImageMagick is homescoop's HEIF build (`wasm-imagemagick-heif`, a superset of the plain build, which isn't offered), with `magick`, `convert`, `mogrify`, `identify` and `magick-open`, and it reads HEIC and AVIF. A failed write leaves an existing target as it was. Its known issues: writing over another user's 0666 file in a sticky directory such as `/tmp` fails with `Operation not permitted`, though writing your own files works ([homescoop#1258](https://github.com/ai-ecoverse/homescoop/issues/1258)); `.mpc` writes fail with `cache resources exhausted` ([homescoop#1208](https://github.com/ai-ecoverse/homescoop/issues/1208)); and the cert's coverage gaps, among them the no-encoder fallback and MPC's two-file write ([homescoop#1209](https://github.com/ai-ecoverse/homescoop/issues/1209)). sudo for `magick`, `convert` or `mogrify` is offered once, never always, since they write files. No two entries' npm `latest` provide the same command, so an install never shadows another entry's; `packages.test` checks that against npm's current `latest`.
217
217
 
218
- - **Install** runs `pnpm add -g <package>@<version>` in the page's kernel, as a user would, under the Web Lock `slicc-optional`, so the commands work at once in every open shell. pnpm 12 gives each global add its own project under `$PNPM_HOME/global/v11/`; bios reads `PNPM_HOME` from the kernel's environment. Afterwards `os/packages.js` reads that project's `pnpm-lock.yaml`, and every package in it, the one added and each dependency, must pass [the gate](#optional-packages). A locked integrity that isn't the registry's for that version (drift) removes the package again and fails the row with *This version doesn't match the tested build*; any other refusal fails it with *Not offered: <reason>.* An Update that fails puts the version it had back (*… stays.*), and an install that fails removes the package, so nothing unchecked stays installed. A row with no version from npm installs nothing, and Install and Update ask npm for the offer again first, so they never act on the OPFS cache's version. An entry's `requires` (uv needs Python) are installed first. A package's kernel command always wins over the same package's Node `bin`. After each install and update, for every name that a package declares both in `slicc.commands` and in `bin`, bios removes the link that pnpm made in `$PNPM_HOME/bin`, but only when that link points into this package, so `mcpcat` runs `/usr/bin/mcpcat`, not a `#!/usr/bin/env node` script with no Node to run it. Another package's bins are never touched, and a package with only a `bin` keeps it. `/opt/user` (Your packages) isn't affected: its bins are not on `PATH`. A certified catalog package's agent skills reach every cone the same way. After the install or update, for each folder its `package.json` lists in `pi.skills`, bios links each skill in it into `/usr/share/skills/<name>`, through the kernel and as root, so no cone can change what the agent loads. The folder has to resolve inside the package; the skill's folder name has to match `^[a-z0-9][a-z0-9-]*$` and equal its `SKILL.md` `name`; and it mustn't collide with a built-in or with an entry it didn't make. The skill files are made readable by everyone (`a+rX`). bios records its links in `var/lib/slicc/optional/<id>/skills`, removes the ones an update drops, and removes all of them on Remove. A skipped skill is logged and never fails the install. The agent's rule stands: it doesn't scan root's global pnpm, so a user's `pnpm add -g` can't add skills. A project entry also **updates** a required package that's older than the catalog's before it installs, since it runs on the catalog's version: the data tools override their own Python away, and their builds need the catalog's Python. A global add brings its own pinned dependencies, so it leaves an older required package as it is.
218
+ - **Install** runs `pnpm add -g <package>@<version>` in the page's kernel, as a user would, under the Web Lock `slicc-optional`, so the commands work at once in every open shell. pnpm 12 gives each global add its own project under `$PNPM_HOME/global/v11/`; bios reads `PNPM_HOME` from the kernel's environment. Afterwards `os/packages.js` reads that project's `pnpm-lock.yaml`, and every package in it, the one added and each dependency, must pass [the gate](#optional-packages). A locked integrity that isn't the registry's for that version (drift) removes the package again and fails the row with *This version doesn't match the tested build*; any other refusal fails it with *Not offered: <reason>.* An Update that fails puts the version it had back (*… stays.*), and an install that fails removes the package, so nothing unchecked stays installed. A row with no version from npm installs nothing, and Install and Update ask npm for the offer again first, so they never act on the OPFS cache's version. An entry's `requires` (uv needs Python) are installed first. A package's kernel command always wins over the same package's Node `bin`. After each install and update, for every name that a package declares both in `slicc.commands` and in `bin`, bios removes the link that pnpm made in `$PNPM_HOME/bin`, but only when that link points into this package, so `mcpcat` runs `/usr/bin/mcpcat`, not a `#!/usr/bin/env node` script with no Node to run it. Another package's bins are never touched, and a package with only a `bin` keeps it. A `pnpm add -g` typed in a shell gets the same pass: bios watches only the `bin` and `global` folders of root's `$PNPM_HOME` (`/usr/local/share/pnpm`) and of each user's `~/.local/share/pnpm`, and `/etc/passwd`, to add a user's when the user appears; about 50 ms after pnpm writes there, it runs that pass over the global's packages, as that user for a user's own global (bios#715). `/opt/user` (Your packages) isn't affected: its bins are not on `PATH`. A certified catalog package's agent skills reach every cone the same way. After the install or update, for each folder its `package.json` lists in `pi.skills`, bios links each skill in it into `/usr/share/skills/<name>`, through the kernel and as root, so no cone can change what the agent loads. The folder has to resolve inside the package; the skill's folder name has to match `^[a-z0-9][a-z0-9-]*$` and equal its `SKILL.md` `name`; and it mustn't collide with a built-in or with an entry it didn't make. The skill files are made readable by everyone (`a+rX`). bios records its links in `var/lib/slicc/optional/<id>/skills`, removes the ones an update drops, and removes all of them on Remove. A skipped skill is logged and never fails the install. The agent's rule stands: it doesn't scan root's global pnpm, so a user's `pnpm add -g` can't add skills. A project entry also **updates** a required package that's older than the catalog's before it installs, since it runs on the catalog's version: the data tools override their own Python away, and their builds need the catalog's Python. A global add brings its own pinned dependencies, so it leaves an older required package as it is.
219
219
  - **Progress:** a row shows pnpm's package counts once pnpm counts more than one package. Before that, a single package, such as Python, still shows its download in bytes, from pnpm's `Downloading` lines (see [Agent](#agent)). Without either the bar is indeterminate.
220
220
  - **State** comes from pnpm's global projects, not from a list of bios's own, so a package installed by hand shows as installed with its version. One older than npm's offered version offers **Update**, which adds that version; one at or above it offers **Remove**. bios never downgrades.
221
221
  - **A user's own installs:** bios also reads each user's own pnpm global (`/home/<user>/.local/share/pnpm/global/v11`, a `pnpm add -g` as `cone`), as root and read-only, straight from the files: it runs no pnpm as the user for that, and with kernel users off it reads none. Each row lists its installs (`installs`, slicc-spectrum#475): the panel's copy as `{ version, where: '/usr/local/share/pnpm', manager: 'panel' }` and each user's as `{ version, where: '/home/<user>/.local/share/pnpm', user, manager: 'pnpm' }`. The version and state follow the panel's copy, or else the user's newest. A row with any install never offers **Install**, and only a panel copy offers **Remove**; a row with only user installs offers **Update** when it's older than npm's offered version, and nothing otherwise. That **Update** runs `pnpm add -g` as each user whose copy is older, with their uid, gid, `HOME`, `PNPM_HOME` and `PATH` in their home, with `--ignore-scripts`, `--ignore-pnpmfile`, the store's integrity check and no release-age wait (the catalog's version is certified), never as root and never with the system's environment, so the files stay theirs and no system copy appears. Their lockfile then passes the same check as a panel install; if it doesn't, bios puts the user's version back and the row says so. bios never touches a user's own bins. A requirement counts only in its own scope: the panel's copy for a panel install or a project, so one only a user has is installed for the system first, and that user's own global, or the panel's, for that user's copy (*Needs …*). The Remove question counts every copy that needs it, a user's included, and the move from the old root global moves a system copy even when a user has the package. The panel's own Install, Update and Remove work on its copy as before, whatever a user has.
@@ -240,7 +240,7 @@ Optional packages never count in the header and never open the panel. The termin
240
240
 
241
241
  Since the kernel has users (slicc-kernel ≥ 1.44.0), root's global pnpm lives in `/usr/local/share/pnpm`, and the panel installs system-wide as root into whatever `PNPM_HOME` root's environment names. Packages installed before that are in the old `/home/.local/share/pnpm`, which the kernel no longer looks in. So on the first boot after the upgrade, bios reads the old global projects and installs every catalog package it finds there again, at its certified version, one after the other in the background. It then records what it found in `var/lib/slicc/optional/moved`, so this happens once. Other leftovers stay where they are; the planned one-time notice about fresh homes will list them.
242
242
 
243
- A package dropped from the catalog is listed in `src/packages/optional/retired.json` (today `wasi-hf`, and `wasm-tar`, which moved into the base set). If one is still installed, its row says it's no longer offered and offers only **Remove**; otherwise it doesn't show.
243
+ A package dropped from the catalog is listed in `src/packages/optional/retired.json` (today `wasi-hf`, and `wasm-tar`, which moved into the base set). If one is still installed, its row says it's no longer offered and offers only **Remove**; otherwise it doesn't show. An entry can name retired packages in `replaces`: installing it removes those first, if present, so both don't link the same command. wasix-bind replaces `wasi-dig`: installing the BIND tools over an earlier `dig` ends with BIND's `dig`, `host` and `nslookup`. With no server argument they look names up through the kernel's DNS stub.
244
244
  ## Modules
245
245
 
246
246
  #### Your packages
@@ -371,8 +371,8 @@ seven can also join a tailnet, with a patched build of Tailscale's wasm client (
371
371
  - **Before HELLO:** each stream channel is its own SCTP stream, so a node's first OPEN can reach the page ahead of its HELLO on the control channel, the order a `slicc prompt`, `abort` or `watch` sometimes arrives in. The page holds up to 64 such frames, 256 KiB in all (one stream's credit window), and serves them in order once the HELLO arrives, as the CLI does for the page's; frames held on a channel that closed meanwhile are dropped. A frame on the control channel before HELLO, a 65th held frame or byte past 256 KiB, a held frame that turns out malformed, and no HELLO within 10 s still close the link: before its HELLO a peer is anonymous.
372
372
  - **Half-open links:** a link that hasn't said HELLO within 30 s of its offer (a follower that gave up on a bootstrap, say) is closed, and its peer connection with it. A device's row follows its link that said HELLO, never a newer half-open one; with only a half-open link left, a known device shows as away. Until a link says HELLO its row shows only that it's connecting, under its bootstrap id: no *Asks to follow*, no Allow and no switches, because its device isn't known yet. So Allow, which keeps the grant with the device's certificate, always finds the device it was clicked for. Unlinking a device drops every link it has and tells the ones that said HELLO.
373
373
  - **Names:** each link gets an address from `198.18.57.0/24` (the first is `.11`) and the name `<host>.slicc.internal`, from the CLI's hostname, made DNS-safe and unique (`lars-mbp-2`). A link keeps its name when it reconnects, also after a reload and in any order, while the name is free: the page remembers each CLI process's name (by device certificate and process id) in `localStorage` (`slicc-os.link-labels`). A CLI that restarts is a new process, so it may come back as `lars-mbp-2` while its old link is still closing; once that link is gone, the new one takes the name back (and its SSH host key is written under it). Port 22 there is the CLI's built-in SSH server, and any other port is the CLI machine's loopback, under the CLI's policy.
374
- - **Into the page (`kernel-in`):** the page's HELLO offers `kernel-in`, so a local CLI serves `http://<port>.kernel.localhost` on its own loopback (port 80, or `--kernel-port`) and carries each connection into the page as `OPEN { kind: 'kernel', port }`. The page answers with `kernel.dial({ port })` and pipes both ways with half-close under the same credit window. It refuses port 9222, the CDP facade, with `EACCES`, and anything but a port 1–65535 with `EINVAL`. A port nothing listens on gets `ECONNREFUSED` (the CLI answers 502). Every other node-opened kind is `EOPNOTSUPP`, and an OPEN without a JSON `kind` is `EPROTO`. This replaces slicc-node's kernel tunnel for a linked CLI.
375
- - **Browsers (`cdp`):** a CLI with `cdp` lists its browsers in HELLO, and later in `OPEN { kind: 'browsers' }` updates (the page offers cap `browsers`, answers OPENED and END, and replaces the list). Each browser is a runtime of the 9222 facade named `<device>/<browser>`, so `playwright-cli --runtime lars-mbp/chrome …`, or `/json/list?runtime=lars-mbp/chrome`, drives it. Each facade connection opens its own `OPEN { kind: 'cdp', browser }` stream, framed as a `u32` length plus one JSON message (at most 64 MiB, otherwise the stream is reset with `EMSGSIZE`). Without a runtime, the facade still prefers slicc-extension, then slicc-node, then a linked browser that hosts this seven (`seven: true`), then the first linked one. The Network panel lists each device's browsers with their runtimes (`devices[].browsers`), and browser automation reads `via: 'link'` when linked browsers are what it drives.
374
+ - **Into the page (`kernel-in`):** the page's HELLO offers `kernel-in`, so a local CLI serves `http://<port>.kernel.localhost` on its own loopback, on the port its HELLO names as `kernel.port` (80 when it names none; see [Kernel servers](#kernel-servers)) and carries each connection into the page as `OPEN { kind: 'kernel', port }`. The page answers with `kernel.dial({ port })` and pipes both ways with half-close under the same credit window. It refuses port 9222, the CDP facade, with `EACCES`, and anything but a port 1–65535 with `EINVAL`. A port nothing listens on gets `ECONNREFUSED` (the CLI answers 502). Every other node-opened kind is `EOPNOTSUPP`, and an OPEN without a JSON `kind` is `EPROTO`. This replaces slicc-node's kernel tunnel for a linked CLI.
375
+ - **Browsers (`cdp`):** a CLI with `cdp` lists its browsers in HELLO, and later in `OPEN { kind: 'browsers' }` updates (the page offers cap `browsers`, answers OPENED and END, and replaces the list). Each browser is a runtime of the 9222 facade named `<device>/<browser>`, so `playwright-cli --runtime lars-mbp/chrome …`, or `/json/list?runtime=lars-mbp/chrome`, drives it. Each facade connection opens its own `OPEN { kind: 'cdp', browser }` stream, framed as a `u32` length plus one JSON message (at most 64 MiB, otherwise the stream is reset with `EMSGSIZE`). Without a runtime, the facade still prefers slicc-extension, then slicc-node, then a linked browser that hosts this seven (`seven: true`), then the first linked one. The Network panel lists each device's browsers with their runtimes (`devices[].browsers`), and browser automation reads `via: 'link'` when linked browsers are what it drives. Seven shares the browsers only of a slicc CLI at **1.47.0 or later** (it relies on slicc-cli #325, #331 and #335), read from its HELLO's `version`: `dev` passes, and otherwise only the numeric `major.minor.patch` counts, so a `-suffix` is ignored (a Go pseudo-version such as `1.47.1-0.2026…-abc123` passes). A HELLO without `version`, or with one that doesn't parse, counts as older. An older CLI that offers `cdp` lists no browsers, on its device row or on the facade, its `OPEN { kind: 'browsers' }` updates are ignored and a `cdp` open to it is refused with `EACCES`; its row says "Update slicc to 1.47.0 or later to share this computer's browsers." Everything else it offers (`net`, `http`, `ssh`, `ws`, `udp`, its folders and `kernel-in`) stays.
376
376
  - **Sync:** the Network panel's Sync section (spectrum's `model.tray`) shows this tray as `os/tray.js` sees it:
377
377
  - **Name and role:** seven's name, `leader` while it leads the tray (`none` when disconnected), and `hosted`.
378
378
  - **Connection:** Live, Connecting, Reconnecting, Error or Offline.
@@ -394,7 +394,7 @@ seven can also join a tailnet, with a patched build of Tailscale's wasm client (
394
394
  - A device that reconnects replaces only its own process's link, so `slicc <join> prompt` doesn't drop that machine's `follow`. Control-only links (`caps: []`) get no `.slicc.internal` name and no exit.
395
395
  - **Folders (`fs`):** a CLI started with `--mount <path>[:<name>][:ro]` lists its folders in HELLO, and later in `OPEN { kind: 'mounts' }` updates; the page offers cap `mounts`. Each is a `hostfs` source named `<device>/<name>`, so `mount -t hostfs lars-mbp/proj /mnt/proj` mounts it, and nothing is mounted unless someone asks. A bare source with no `<device>/`, as slicc-node named its folders (`mount -t hostfs project /mnt/p`, or one remembered from then), is the folder of that name on the CLI linked on this computer, when exactly one local CLI shares one. The device's row in Linked devices lists its folders (`folders`, with a Read-only badge; spectrum ≥ 1.58.0): **Mount** (`mountFolder(source)`) mounts one at `/mnt/<device>/<name>` (a folder named `.` or `..` is never listed), and **Eject** (`ejectFolder(source)`) unmounts it. The Files panel's Mounted strip shows each `hostfs` mount's source (`mountInfo()`), so `/mnt/proj · lars-mbp/proj` reads as another computer's folder. A mounted linked folder stays with the CLI process it was first granted from (`slicc-os.link-sources`), even if that process comes back under another name. If that process isn't linked, the folder goes to whichever process has the name now, but only when no other process with the same host name shares a folder of that name; otherwise it waits. So a remembered `lars-mbp/proj` never lands on another process's `proj`. A remembered linked folder that is mounted again before its CLI is back stays `nomedium`, and fills in when the CLI links. The kernel's `hostfs` hook answers such a source with a `MessagePort` (slicc-kernel ≥ 1.54.9), and the page serves it with `serveHostfsPort` over `OPEN { kind: 'fs', mount, op, … }` streams: `list` collects its NDJSON, a read over 64 KiB and every write get their own channel, and `watch` streams the CLI's change events. A read-only kernel mount, or a read-only export, sends `readonly: true` on every OPEN. A link that drops makes the mount `nomedium` until the CLI is back; files that were open reopen by path and continue if the host didn't change them.
396
396
  - **SSH host key:** the CLI's HELLO carries its host key, and the page writes `<host>.slicc.internal,<address> <key>` into the system-wide `/etc/ssh/ssh_known_hosts`, replacing older entries for that name or address, so `ssh` never trusts a key on first sight, whichever user runs it. Seven manages these keys, not the user, and OpenSSH looks up a user's own file under the passwd home, which isn't always `$HOME`.
397
- - **Tests:** `test/integration/remote.test.mjs` runs the real `slicc watch`, `slicc prompt` and `slicc abort` with `--signal stdio` against seven's real agent and a fake Bedrock. It also leads a fake tray hub and sends a `webhook.event`, which reaches the agent as a webhook lick (without its `authorization` header) and starts a run. `test/integration/tray.test.mjs` leads a fake tray hub and links a follower in the page through it, then rotates and unlinks. `test/integration/link.test.mjs` links a fake node in the page over a real `RTCPeerConnection`, and, with `SLICC_CLI` set, the real `slicc attach --signal stdio`, relaying its NDJSON through the CDP binding: raw TCP and the http kind; kernel `ssh` with strict host-key checking against `--runner sh -c`, after `pnpm add -g @ai-ecoverse/wasix-openssh`; and, with the link as the exit, a name from the CLI's `--hosts` file, then refused under `--deny`; and `<port>.kernel.localhost` through the CLI's listener into a kernel server (`httptest`), with 502 for a closed port and the facade refused; a folder shared with `--mount`, mounted as `ref-node/proj`, read, written, seen changing on the host, and refused for writes when mounted `ro`; a second headless Chromium shared with `--cdp-extra`, listed and driven by `playwright-cli --runtime ref-node/<id>`; and a program WebSocket from kernel `bash` through the proxy to a `ws` echo server on the CLI's loopback: text, binary, the subprotocol, a close from each end, and `EACCES` under `--deny`; kernel `websocat`, installed from the catalog, to a `ws` echo on the CLI's loopback and, without `-k`, to `wss://echo.sliccy.ai/` (SLICC's echo, behind Cloudflare's certificate), so its own TLS checks the chain over raw TCP through the link, then failing at once under Directly and with no exit; and a kernel `python3` UDP socket (after `pnpm add -g @ai-ecoverse/wasix-python`) to a UDP echo server on the CLI's loopback, unconnected and connected, and `EACCES` on a connected socket under `--deny`, as with the fake node's own refusal. CI runs the CLI from npm, the pinned `@ai-ecoverse/slicc` devDependency.
397
+ - **Tests:** `test/integration/remote.test.mjs` runs the real `slicc watch`, `slicc prompt` and `slicc abort` with `--signal stdio` against seven's real agent and a fake Bedrock. It also leads a fake tray hub and sends a `webhook.event`, which reaches the agent as a webhook lick (without its `authorization` header) and starts a run. `test/integration/tray.test.mjs` leads a fake tray hub and links a follower in the page through it, then rotates and unlinks; a remote follower that names kernel port 17180 leaves `SLICC_PAGE_LOOPBACK`, the stored port and the profile script alone. `test/integration/link.test.mjs` links a fake node in the page over a real `RTCPeerConnection`, with a HELLO that names no kernel port, port 80 or 17180, and checks `SLICC_PAGE_LOOPBACK` in login shells and, after a reload, in every program (one that offers `cdp` as version `1.46.9` or without a version shares no browsers while its net and folders still work; `1.47.0`, `dev` and a pseudo-version above share them), and, with `SLICC_CLI` set, the real `slicc attach --signal stdio`, relaying its NDJSON through the CDP binding: raw TCP and the http kind; kernel `ssh` with strict host-key checking against `--runner sh -c`, after `pnpm add -g @ai-ecoverse/wasix-openssh`; and, with the link as the exit, a name from the CLI's `--hosts` file, then refused under `--deny`; and `<port>.kernel.localhost` through the CLI's listener into a kernel server (`httptest`), with 502 for a closed port and the facade refused; a folder shared with `--mount`, mounted as `ref-node/proj`, read, written, seen changing on the host, and refused for writes when mounted `ro`; a second headless Chromium shared with `--cdp-extra`, listed and driven by `playwright-cli --runtime ref-node/<id>`; and a program WebSocket from kernel `bash` through the proxy to a `ws` echo server on the CLI's loopback: text, binary, the subprotocol, a close from each end, and `EACCES` under `--deny`; kernel `websocat`, installed from the catalog, to a `ws` echo on the CLI's loopback and, without `-k`, to `wss://echo.sliccy.ai/` (SLICC's echo, behind Cloudflare's certificate), so its own TLS checks the chain over raw TCP through the link, then failing at once under Directly and with no exit; and a kernel `python3` UDP socket (after `pnpm add -g @ai-ecoverse/wasix-python`) to a UDP echo server on the CLI's loopback, unconnected and connected, and `EACCES` on a connected socket under `--deny`, as with the fake node's own refusal. CI runs the CLI from npm, the pinned `@ai-ecoverse/slicc` devDependency.
398
398
  - **As the exit:** a CLI linked on this computer (`npx sliccy@next`) is the exit by itself until the user chooses one, so the kernel's HTTP and raw TCP get past CORS at once, as slicc-node's proxy did; a Tailscale exit node that is on comes first. A remote device that offers to be a default exit carries other traffic only once it's chosen. The Network panel's **Internet traffic** picker (`setExit`) is one choice across Directly, Tailscale exit nodes and linked devices: choosing a device turns off Tailscale's exit node, and choosing Tailscale clears the device. The choice of a device is kept in `localStorage` (`slicc-os.exit`), and while that device isn't connected, after a reload or while it reconnects, internet traffic **waits**: raw connections get `ENETUNREACH` and HTTP fails, rather than going out directly. Choosing Directly sends it directly again and is kept (`direct`), so a local CLI doesn't take it over, while a Tailscale exit node turned on later still does; unlinking the chosen exit device goes back to the automatic choice.
399
399
  - **What the agent sees:** the transport's `traits` name the default exit while there is one, so the agent can say how its fetches go. `traits.exit` is `{ kind, caps }`:
400
400
  - **`kind`:** `local` (a CLI on this computer), `remote` (a chosen linked device) or `tailnet` (a Tailscale exit node);
@@ -478,8 +478,8 @@ A server running inside the kernel (vite, `python -m http.server`, impeccable `l
478
478
  A second test on its own tailnet sends kernel `bash`'s WebSocket through the proxy (`/dev/tcp/127.0.0.1/3128`) and the Tailscale exit to the peer's echo server (text, binary, the subprotocol and a close from each end), sees a handshake to the silent port answered `502` after a 5 s `handshakeMs`, and sees a vault placeholder in the URL or a header refused before anything reaches the peer.
479
479
 
480
480
  To run it: `HEADSCALE=… TAILSCALED=… TAILSCALE=… TAILSCALE_E2E=1 npm test -- --test-name-pattern 'stage B'` (`TS_SHOTS=<dir>` also saves screenshots of the Network panel and the Install / Update row).
481
- - **Plain `localhost` and `127.0.0.1` stay the real machine.** The service worker passes them through untouched. Inside the kernel it's the other way round: `localhost` is the kernel loopback, and `host.slicc.internal` reaches the machine. The kernel exports the page-visible name as `SLICC_PAGE_LOOPBACK`, so tools can print the right URL.
482
- - **Why the port goes in the name.** `kernel.localhost:8400` would resolve to the machine's real port 8400 whenever the service worker doesn't answer, as for a navigation or a WebSocket, and reach the wrong server. `8400.kernel.localhost` lands on port 80, which is closed or answered by [slicc-node](https://github.com/ai-ecoverse/slicc-node)'s kernel tunnel, and it gives every kernel port its own origin. The service worker routes by the name alone and ignores the URL's port.
481
+ - **Plain `localhost` and `127.0.0.1` stay the real machine.** The service worker passes them through untouched. Inside the kernel it's the other way round: `localhost` is the kernel loopback, and `host.slicc.internal` reaches the machine. The kernel exports the page-visible name as `SLICC_PAGE_LOOPBACK` (`kernel.localhost`) and `SLICC_PAGE_LOOPBACK_URL` (`http://{port}.kernel.localhost`), so tools can print the right URL. With a kernel port (below) other than 80 they carry it: `kernel.localhost:17180` and `http://{port}.kernel.localhost:17180`.
482
+ - **Why the port goes in the name.** `kernel.localhost:8400` would resolve to the machine's real port 8400 whenever the service worker doesn't answer, as for a navigation or a WebSocket, and reach the wrong server. `8400.kernel.localhost` lands on the kernel port, 80 by default (below), which is closed or answered by a local slicc's kernel listener or [slicc-node](https://github.com/ai-ecoverse/slicc-node)'s kernel tunnel, and it gives every kernel port its own origin. The service worker routes by the name alone and ignores the URL's port, so `http://8400.kernel.localhost:17180/` reaches the same kernel server.
483
483
  - **How a request gets there.** A seven page's request to `*.kernel.localhost`, with any method, reaches the service worker. `*.localhost` is potentially trustworthy, so an `https` page loads it without a mixed-content block. The service worker answers it itself, so nothing goes to the network, no Local Network Access prompt is shown, and there's no CORS preflight. It hands the request to the `/os/` tab: the requesting one, or else the most recently focused. That tab calls `kernel.loopbackFetch(request, { port })` and transfers the streamed response body back.
484
484
  - **The response.** Status, headers and body pass through. Bodies stream, so `EventSource` and long-poll work, and closing the `EventSource` closes the kernel socket. seven's pages are cross-origin isolated, so where the server sent none, the service worker adds `access-control-allow-origin: <seven's origin>` with `access-control-allow-credentials: true`, and `cross-origin-resource-policy: cross-origin`. That lets a plain `<script src>` or `fetch` load from a server that knows nothing about CORS.
485
485
  - **When it fails.**
@@ -491,11 +491,16 @@ A server running inside the kernel (vite, `python -m http.server`, impeccable `l
491
491
 
492
492
  What doesn't work through the service worker:
493
493
 
494
- - **WebSockets.** A service worker never sees them, so `ws://<port>.kernel.localhost/` goes to the machine's port 80. Vite's HMR can't connect: the page loads and runs, but needs reloading by hand.
494
+ - **WebSockets.** A service worker never sees them, so `ws://<port>.kernel.localhost/` goes to the machine's port 80, and `ws://<port>.kernel.localhost:<kernel port>/` to the kernel port. Vite's HMR can't connect: the page loads and runs, but needs reloading by hand.
495
495
  - **Opening a kernel server as a page.** A navigation to `http://<port>.kernel.localhost/` is another origin, which seven's service worker doesn't control.
496
496
  - **Cookies.** The responses are built in the page, so `Set-Cookie` is dropped.
497
497
 
498
- **slicc-node's kernel tunnel** carries what the service worker can't. slicc-node listens on `127.0.0.1:80`, or on the port `--kernel-port` gives it, and the URLs then carry that port: `http://8400.kernel.localhost:8080/`. It hands every connection to `*.kernel.localhost` to the page through a WebSocket, as raw bytes, so navigations, keep-alive and WebSocket upgrades (vite HMR) work. A page opened this way is its own origin, isolated from seven's.
498
+ **The kernel port.** A local slicc names the port its kernel listener uses in its HELLO, as `"kernel": { "port": <n> }`: 80 on macOS and Windows, a spare port in 17180–17189 where it can't have 80 (Linux for a normal user, or 80 taken), or its `--kernel-port`. A HELLO without the field (an older slicc, slicc-node) means 80. Kernel URLs then carry any port but 80: `http://8400.kernel.localhost:17180/`. seven keeps the last port a local node named, in `localStorage` (`slicc-kernel-port`); a remote device's or another seven's HELLO never changes it. It then:
499
+
500
+ - writes it to `/etc/profile.d/slicc-kernel.sh`, which sets `SLICC_PAGE_LOOPBACK` and `SLICC_PAGE_LOOPBACK_URL`, so every login shell opened after the HELLO gets it. Every HELLO checks the script itself and rewrites it when it names another port, one HELLO at a time, and the port is kept only once the script is written;
501
+ - hands it to the kernel's `env` when the kernel starts, so every program gets it after a reload. A shell that is already open keeps what it started with.
502
+
503
+ **slicc-node's kernel tunnel** carries what the service worker can't. slicc-node names no kernel port, so it's 80: it listens on `127.0.0.1:80`, or on the port `--kernel-port` gives it, and the URLs then carry that port: `http://8400.kernel.localhost:8080/`. It hands every connection to `*.kernel.localhost` to the page through a WebSocket, as raw bytes, so navigations, keep-alive and WebSocket upgrades (vite HMR) work. A page opened this way is its own origin, isolated from seven's.
499
504
 
500
505
  - **Opening the tunnel.** When the local proxy's probe reports `kernelTunnel`, `os/tunnel.js` opens `ws://<proxy>/api/kernel-tunnel`, with the proxy key as a WebSocket subprotocol.
501
506
  - **Serving streams.** For every stream slicc-node opens, the page calls `kernel.dial({ port })` and pipes the bytes both ways. Each direction may have at most 256 KiB in flight before the other side credits it, so a slow stream doesn't hold up the others.
@@ -615,7 +620,7 @@ On a pull request, the plan first reads the files the pull request changes (`git
615
620
 
616
621
  [`scripts/ci/scopes.json`](scripts/ci/scopes.json) maps each package name or pattern to its rows (`full` for the harness, Playwright and the installer's tar, `vendors` for the slicc CLI). The plan prints its mode and why in the job summary, and `ci / test` passes only when the jobs that mode skips were skipped and every other job passed: `ci: PASS docs plan, 0 shards, skipped integration and vendors`. The merge queue always runs everything, so `main` is never less tested.
617
622
 
618
- A shard also deletes the harness's stall traces (`stall-<n>-trace.json`, often 70–110 MB each) of tests that passed in every attempt, never skipped (in `artifacts/` and, after a retry, in the first attempt's copy too), and lists each one with its size under `trimmed` in its record and in the log. Screenshots, logs, coverage and every file of a test that failed, flipped or timed out in any attempt stay, as does everything from a file that crashed without reporting, and every artifact of a file in any of cert review's classes (`CLASSES` in [`scripts/cert/evidence.mjs`](scripts/cert/evidence.mjs)), or in no list yet, even when it passed. That keeps the `integration-<shard>` artifacts small enough for cert review's evidence.
623
+ A shard also deletes the harness's stall traces (`stall-<n>-trace.json`, often 70–110 MB each) of tests that passed in every attempt, never skipped (in `artifacts/` and, after a retry, in the first attempt's copy too), and lists each one with its size under `trimmed` in its record and in the log. Screenshots, logs, coverage and every file of a test that failed, flipped or timed out in any attempt stay, as does everything from a file that crashed without reporting, and every artifact of a file in any of cert review's classes (`CLASSES` in [`scripts/cert/evidence.mjs`](scripts/cert/evidence.mjs)), or in no list yet, even when it passed. That keeps the `integration-<shard>` artifacts small enough for cert review's evidence. Every stall trace it keeps is then gzipped in place (`stall-<n>-trace.json.gz`) and listed under `compressed` with both sizes, which makes the evidence about ten times smaller.
619
624
 
620
625
  Every shard runs the files with a failing test once more and passes when they pass (`retry`, skipped when it wouldn't fit the shard's 62 minutes), and a shard that still fails cancels the others (`fail-fast`). Both were tested first. From 2026-10-17 to 2026-10-18 a two-by-two experiment by pull request number found that 0 of 28 merge queue runs with retry failed, against 15 of 42 without it. From 2026-10-18 to 2026-10-20 the number's parity picked fail-fast or not, with retry on both sides: over 525 runs, failing runs finished after a median of 29 minutes with fail-fast against 47 without (the first shard went red after about 26 minutes in both), passing runs took the same time (46 and 45 minutes), and the 65 pull requests merged since leaned the same way (mean CI wait 1.8 h against 2.4 h, time to merge 4.0 h against 4.9 h, not yet significant). A run's arm is now always `fail-fast+retry`. The plan, with the arm, the seed and each shard's items, is in the job summary and the `experiment-plan` artifact; each shard's record (`artifacts/experiment/<shard>.json`: its groups, the first run and any retry with their exit codes, counts and failed files) is in its `integration-<shard>` artifact, with each item's time and every test that failed and then passed on the retry. `ci / test` joins them into `summary.json` (the `experiment-summary` artifact), and for each test that flipped it files an issue labeled `flaky-test`, or comments on the open one for that test, with the run, the arm, the shard and the first run's error ([`scripts/ci/summary.mjs`](scripts/ci/summary.mjs)); this step never fails the check, and a fork's read-only token files nothing. `node scripts/ci/durations.mjs` refreshes `durations.json` with the median times of the last 40 runs' summaries.
621
626
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-ecoverse/slicc-bios",
3
- "version": "1.38.0",
3
+ "version": "1.39.4",
4
4
  "description": "Slim loader that boots SLICC into OPFS and serves the UI from there",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -35,6 +35,7 @@
35
35
  "node": ">=26"
36
36
  },
37
37
  "scripts": {
38
+ "prepare": "slicc-install-hooks",
38
39
  "start": "node test/integration/chrome.mjs",
39
40
  "pretest": "playwright-core install --no-shell chromium",
40
41
  "test": "node --test --test-concurrency=1 --test-timeout=900000 --test-global-setup=test/integration/global.mjs ${SLICC_TESTS:-test/integration/*.test.mjs}",
@@ -44,10 +45,10 @@
44
45
  "format": "biome check --write ."
45
46
  },
46
47
  "devDependencies": {
47
- "@ai-ecoverse/slicc": "1.47.0",
48
- "@ai-ecoverse/slicc-browsers": "1.10.3",
48
+ "@ai-ecoverse/slicc": "1.47.2",
49
+ "@ai-ecoverse/slicc-browsers": "1.13.5",
49
50
  "@ai-ecoverse/slicc-node": "2.5.1",
50
- "@ai-ecoverse/slicc-shared-web": "1.24.2",
51
+ "@ai-ecoverse/slicc-shared-web": "1.30.8",
51
52
  "@ai-ecoverse/slicc-spectrum": "1.104.1",
52
53
  "@ai-ecoverse/slicc-vault": "1.15.1",
53
54
  "@biomejs/biome": "2.5.15",
@@ -56,10 +57,10 @@
56
57
  "lefthook": "2.2.1",
57
58
  "modern-tar": "0.8.5",
58
59
  "monocart-coverage-reports": "2.13.2",
59
- "playwright-core": "1.64.0",
60
+ "playwright-core": "1.64.1",
60
61
  "semantic-release": "25.0.9",
61
62
  "semver": "7.8.5",
62
- "wrangler": "4.150.0",
63
+ "wrangler": "4.151.0",
63
64
  "ws": "8.22.0"
64
65
  }
65
66
  }
@@ -4,6 +4,6 @@
4
4
  "description": "SLICC's agent, which the UI installs with pnpm in the background into /opt/agent in OPFS",
5
5
  "dependencies": {
6
6
  "@ai-ecoverse/slicc-agent": "6.18.3",
7
- "@ai-ecoverse/slicc-kernel": "1.138.0"
7
+ "@ai-ecoverse/slicc-kernel": "1.143.5"
8
8
  }
9
9
  }
@@ -15,10 +15,10 @@ importers:
15
15
  dependencies:
16
16
  '@ai-ecoverse/slicc-agent':
17
17
  specifier: 6.18.3
18
- version: 6.18.3(@ai-ecoverse/slicc-kernel@1.138.0)(@aws-sdk/credential-provider-node@3.972.84)(@smithy/signature-v4@5.7.4)(ws@8.22.0)
18
+ version: 6.18.3(@ai-ecoverse/slicc-kernel@1.143.5)(@aws-sdk/credential-provider-node@3.972.84)(@smithy/signature-v4@5.7.4)(ws@8.22.0)
19
19
  '@ai-ecoverse/slicc-kernel':
20
- specifier: 1.138.0
21
- version: 1.138.0
20
+ specifier: 1.143.5
21
+ version: 1.143.5
22
22
 
23
23
  packages:
24
24
 
@@ -36,9 +36,9 @@ packages:
36
36
  resolution: {integrity: sha512-WVaDUiZbd5nwG03+2WoQ8YA8ATC2mkx1DRCWpLuMFBNnyN0cd5IRoGF6KYNjMkXvBQCvZZxP+gwffrpmHYJ/cQ==}
37
37
  engines: {node: '>=24'}
38
38
 
39
- '@ai-ecoverse/slicc-kernel@1.138.0':
40
- resolution: {integrity: sha512-p5cdX1mB6xed1NcRGe0Uifm3NVx8d3YXzA2kLYH2d7HtcSwjvmOU566SUaUKBtbgwXHRAC5gAfW1QoD6/fAiOQ==}
41
- engines: {node: '>=24'}
39
+ '@ai-ecoverse/slicc-kernel@1.143.5':
40
+ resolution: {integrity: sha512-ItE5vaA496NLHEr0HM4QUI8yEeRdUCIVtAFldTKAFdgRK7CdeKsaVbGLla10GxeIv0xNkcny2Ee1VHS1EjnCYQ==}
41
+ engines: {node: '>=26'}
42
42
 
43
43
  '@ai-ecoverse/slicc-vault@1.15.1':
44
44
  resolution: {integrity: sha512-qr1Pmw7lodtjiQgWkKgGcfbG63H61eHba4XBKXPlGYrRkYJ0vLTts1x82wYS6H6V4FaqAtLfdunwNvT0riz2CQ==}
@@ -346,10 +346,10 @@ packages:
346
346
 
347
347
  snapshots:
348
348
 
349
- '@ai-ecoverse/slicc-agent@6.18.3(@ai-ecoverse/slicc-kernel@1.138.0)(@aws-sdk/credential-provider-node@3.972.84)(@smithy/signature-v4@5.7.4)(ws@8.22.0)':
349
+ '@ai-ecoverse/slicc-agent@6.18.3(@ai-ecoverse/slicc-kernel@1.143.5)(@aws-sdk/credential-provider-node@3.972.84)(@smithy/signature-v4@5.7.4)(ws@8.22.0)':
350
350
  dependencies:
351
351
  '@ai-ecoverse/slicc-browsers': 1.9.2
352
- '@ai-ecoverse/slicc-kernel': 1.138.0
352
+ '@ai-ecoverse/slicc-kernel': 1.143.5
353
353
  '@ai-ecoverse/slicc-vault': 1.15.1
354
354
  '@aws-sdk/middleware-websocket': 3.972.54
355
355
  '@earendil-works/chord': 1.3.0
@@ -372,7 +372,7 @@ snapshots:
372
372
 
373
373
  '@ai-ecoverse/slicc-browsers@1.9.2': {}
374
374
 
375
- '@ai-ecoverse/slicc-kernel@1.138.0': {}
375
+ '@ai-ecoverse/slicc-kernel@1.143.5': {}
376
376
 
377
377
  '@ai-ecoverse/slicc-vault@1.15.1': {}
378
378
 
@@ -101,9 +101,10 @@
101
101
  "id": "screen",
102
102
  "label": "screen"
103
103
  },
104
- "@ai-ecoverse/wasi-dig": {
105
- "id": "dig",
106
- "label": "dig"
104
+ "@ai-ecoverse/wasix-bind": {
105
+ "id": "bind",
106
+ "label": "BIND tools (dig, host, nslookup)",
107
+ "replaces": ["@ai-ecoverse/wasi-dig"]
107
108
  },
108
109
  "@ai-ecoverse/wasix-websocat": {
109
110
  "id": "websocat",
@@ -6,16 +6,16 @@
6
6
  "": {
7
7
  "name": "slicc-bios-optional",
8
8
  "dependencies": {
9
- "@ai-ecoverse/mcpcat": "0.17.7",
10
- "@ai-ecoverse/slicc-jsh": "0.45.4",
11
- "@ai-ecoverse/sliccy-browser": "0.1.29",
9
+ "@ai-ecoverse/mcpcat": "0.18.2",
10
+ "@ai-ecoverse/slicc-jsh": "0.52.5",
11
+ "@ai-ecoverse/sliccy-browser": "0.1.34",
12
12
  "@ai-ecoverse/wasi-slicc": "1.47.0"
13
13
  }
14
14
  },
15
15
  "node_modules/@ai-ecoverse/mcpcat": {
16
- "version": "0.17.7",
17
- "resolved": "https://registry.npmjs.org/@ai-ecoverse/mcpcat/-/mcpcat-0.17.7.tgz",
18
- "integrity": "sha512-BunOzrFplONryNwPgLu36vSYQ/K+KqZiuMndFxtjJEj7yJJeqbjyDNYdX0DhQROeezDJ7qbzMMno7P3k0lXGUA==",
16
+ "version": "0.18.2",
17
+ "resolved": "https://registry.npmjs.org/@ai-ecoverse/mcpcat/-/mcpcat-0.18.2.tgz",
18
+ "integrity": "sha512-dYRA4KhV22qVb+SEZJm8xKVQxJqqhg8W3763GT/u1TUnKY4J8ai1j9I6qoqGn8t2bqGnyf/HhuViGuUQrmepGw==",
19
19
  "license": "Apache-2.0",
20
20
  "bin": {
21
21
  "mcpcat": "dist/host/mcpcat.mjs"
@@ -26,9 +26,9 @@
26
26
  }
27
27
  },
28
28
  "node_modules/@ai-ecoverse/slicc-cdp": {
29
- "version": "1.30.10",
30
- "resolved": "https://registry.npmjs.org/@ai-ecoverse/slicc-cdp/-/slicc-cdp-1.30.10.tgz",
31
- "integrity": "sha512-VakByvxkHaUtVRPQaB3o9UOS587H5XewCUDJen/jCmgH0nMxZT1EXPZ/fLyZhgAPtfO28+qaIvnbCisTviPE4g==",
29
+ "version": "1.30.18",
30
+ "resolved": "https://registry.npmjs.org/@ai-ecoverse/slicc-cdp/-/slicc-cdp-1.30.18.tgz",
31
+ "integrity": "sha512-8aty5CgO3hPiZ0H8ikx60j1QzTWJmr6MGRKAFy9DMDrU/nwqPnifx1UXLX6AW6GdvDsZdRR9NpAV2A4hWfj4ZA==",
32
32
  "license": "Apache-2.0",
33
33
  "workspaces": [
34
34
  "packages/sliccy-browser"
@@ -41,9 +41,9 @@
41
41
  }
42
42
  },
43
43
  "node_modules/@ai-ecoverse/slicc-jsh": {
44
- "version": "0.45.4",
45
- "resolved": "https://registry.npmjs.org/@ai-ecoverse/slicc-jsh/-/slicc-jsh-0.45.4.tgz",
46
- "integrity": "sha512-fSHMCOodMnPiSh+XfhiaXVVSVSRAg8at7vmdXFPtaXO3pzJ2A2WArSpaD3jlJife4zB2wZJHeR8buZOGqXyc3A==",
44
+ "version": "0.52.5",
45
+ "resolved": "https://registry.npmjs.org/@ai-ecoverse/slicc-jsh/-/slicc-jsh-0.52.5.tgz",
46
+ "integrity": "sha512-v4S3zHWNCBuWejF8wNlxUwGppCqlYNc+PQpPm9T0LSMOmDTzW/sU3RdIDKSn2wqM1oHNha38CZbnjEHYS+01Gw==",
47
47
  "license": "Apache-2.0",
48
48
  "bin": {
49
49
  "jsh": "dist/host/jsh.mjs"
@@ -54,12 +54,12 @@
54
54
  }
55
55
  },
56
56
  "node_modules/@ai-ecoverse/sliccy-browser": {
57
- "version": "0.1.29",
58
- "resolved": "https://registry.npmjs.org/@ai-ecoverse/sliccy-browser/-/sliccy-browser-0.1.29.tgz",
59
- "integrity": "sha512-alXLJppvnsDqJXyGyo805OyLT3BVBRj+SuwUyEz8akPsilZghKnsYJJm+wrIyKxCXMuDUyaFz5ZMuZWIbmIgOw==",
57
+ "version": "0.1.34",
58
+ "resolved": "https://registry.npmjs.org/@ai-ecoverse/sliccy-browser/-/sliccy-browser-0.1.34.tgz",
59
+ "integrity": "sha512-epSMU6SkUwuhCA6Ods927VtpxbrmsaajJj5o/UZhc6MG0dxj84GpNfExHDGsNvFh+jsM8gwLFFnqsgM4IRCX9w==",
60
60
  "license": "Apache-2.0",
61
61
  "dependencies": {
62
- "@ai-ecoverse/slicc-cdp": "1.30.10"
62
+ "@ai-ecoverse/slicc-cdp": "1.30.18"
63
63
  },
64
64
  "engines": {
65
65
  "node": ">=24"
@@ -3,9 +3,9 @@
3
3
  "private": true,
4
4
  "description": "The optional packages that seven pins because their publisher isn't homescoop's ladder: slicc-jsh, mcpcat, wasi-slicc (slicc-cli) and sliccy-browser (slicc-cdp). Release-state and cert review certify these pins; every other catalog entry is npm's latest behind the runtime gate. Never installed as a project: the panel runs pnpm add -g for each one.",
5
5
  "dependencies": {
6
- "@ai-ecoverse/mcpcat": "0.17.7",
7
- "@ai-ecoverse/slicc-jsh": "0.45.4",
8
- "@ai-ecoverse/sliccy-browser": "0.1.29",
6
+ "@ai-ecoverse/mcpcat": "0.18.2",
7
+ "@ai-ecoverse/slicc-jsh": "0.52.5",
8
+ "@ai-ecoverse/sliccy-browser": "0.1.34",
9
9
  "@ai-ecoverse/wasi-slicc": "1.47.0"
10
10
  }
11
11
  }
@@ -6,10 +6,10 @@
6
6
  "": {
7
7
  "name": "slicc-bios-packages",
8
8
  "dependencies": {
9
- "@ai-ecoverse/slicc-browsers": "1.10.3",
9
+ "@ai-ecoverse/slicc-browsers": "1.13.5",
10
10
  "@ai-ecoverse/slicc-cdp": "1.30.18",
11
11
  "@ai-ecoverse/slicc-clipboard": "1.0.2",
12
- "@ai-ecoverse/slicc-kernel": "1.138.0",
12
+ "@ai-ecoverse/slicc-kernel": "1.143.5",
13
13
  "@ai-ecoverse/slicc-spectrum": "1.104.1",
14
14
  "@ai-ecoverse/wasi-fnox": "1.39.0-6",
15
15
  "@ai-ecoverse/wasi-pnpm": "12.9.1-19",
@@ -38,9 +38,9 @@
38
38
  }
39
39
  },
40
40
  "node_modules/@ai-ecoverse/slicc-browsers": {
41
- "version": "1.10.3",
42
- "resolved": "https://registry.npmjs.org/@ai-ecoverse/slicc-browsers/-/slicc-browsers-1.10.3.tgz",
43
- "integrity": "sha512-xUKkpE0oqtUGjObJSzrk7ny2rU8ZStoUp4Uxw2SPM6f7uw+M7X8MV0NuSyqkWYTzZJ6JPWyVJx0QvynSBXHPOw==",
41
+ "version": "1.13.5",
42
+ "resolved": "https://registry.npmjs.org/@ai-ecoverse/slicc-browsers/-/slicc-browsers-1.13.5.tgz",
43
+ "integrity": "sha512-g1sNUBWX53Rkc26GtYJ2muKQ79nyQ+dK+AJExNBcYqI5JfTF6Ra2q5LSrlFDPFZqKDqDc7q2LIXrFg5ebwvWQg==",
44
44
  "license": "Apache-2.0",
45
45
  "engines": {
46
46
  "node": ">=24"
@@ -72,12 +72,12 @@
72
72
  }
73
73
  },
74
74
  "node_modules/@ai-ecoverse/slicc-kernel": {
75
- "version": "1.138.0",
76
- "resolved": "https://registry.npmjs.org/@ai-ecoverse/slicc-kernel/-/slicc-kernel-1.138.0.tgz",
77
- "integrity": "sha512-p5cdX1mB6xed1NcRGe0Uifm3NVx8d3YXzA2kLYH2d7HtcSwjvmOU566SUaUKBtbgwXHRAC5gAfW1QoD6/fAiOQ==",
75
+ "version": "1.143.5",
76
+ "resolved": "https://registry.npmjs.org/@ai-ecoverse/slicc-kernel/-/slicc-kernel-1.143.5.tgz",
77
+ "integrity": "sha512-ItE5vaA496NLHEr0HM4QUI8yEeRdUCIVtAFldTKAFdgRK7CdeKsaVbGLla10GxeIv0xNkcny2Ee1VHS1EjnCYQ==",
78
78
  "license": "Apache-2.0",
79
79
  "engines": {
80
- "node": ">=24"
80
+ "node": ">=26"
81
81
  }
82
82
  },
83
83
  "node_modules/@ai-ecoverse/slicc-spectrum": {
@@ -3,10 +3,10 @@
3
3
  "private": true,
4
4
  "description": "Packages the BIOS installs from npm into OPFS, pinned by package-lock.json and pnpm-lock.yaml",
5
5
  "dependencies": {
6
- "@ai-ecoverse/slicc-browsers": "1.10.3",
6
+ "@ai-ecoverse/slicc-browsers": "1.13.5",
7
7
  "@ai-ecoverse/slicc-cdp": "1.30.18",
8
8
  "@ai-ecoverse/slicc-clipboard": "1.0.2",
9
- "@ai-ecoverse/slicc-kernel": "1.138.0",
9
+ "@ai-ecoverse/slicc-kernel": "1.143.5",
10
10
  "@ai-ecoverse/slicc-spectrum": "1.104.1",
11
11
  "@ai-ecoverse/wasi-fnox": "1.39.0-6",
12
12
  "@ai-ecoverse/wasi-pnpm": "12.9.1-19",
@@ -9,8 +9,8 @@ importers:
9
9
  .:
10
10
  dependencies:
11
11
  '@ai-ecoverse/slicc-browsers':
12
- specifier: 1.10.3
13
- version: 1.10.3
12
+ specifier: 1.13.5
13
+ version: 1.13.5
14
14
  '@ai-ecoverse/slicc-cdp':
15
15
  specifier: 1.30.18
16
16
  version: 1.30.18
@@ -18,8 +18,8 @@ importers:
18
18
  specifier: 1.0.2
19
19
  version: 1.0.2
20
20
  '@ai-ecoverse/slicc-kernel':
21
- specifier: 1.138.0
22
- version: 1.138.0
21
+ specifier: 1.143.5
22
+ version: 1.143.5
23
23
  '@ai-ecoverse/slicc-spectrum':
24
24
  specifier: 1.104.1
25
25
  version: 1.104.1
@@ -98,8 +98,8 @@ importers:
98
98
 
99
99
  packages:
100
100
 
101
- '@ai-ecoverse/slicc-browsers@1.10.3':
102
- resolution: {integrity: sha512-xUKkpE0oqtUGjObJSzrk7ny2rU8ZStoUp4Uxw2SPM6f7uw+M7X8MV0NuSyqkWYTzZJ6JPWyVJx0QvynSBXHPOw==}
101
+ '@ai-ecoverse/slicc-browsers@1.13.5':
102
+ resolution: {integrity: sha512-g1sNUBWX53Rkc26GtYJ2muKQ79nyQ+dK+AJExNBcYqI5JfTF6Ra2q5LSrlFDPFZqKDqDc7q2LIXrFg5ebwvWQg==}
103
103
  engines: {node: '>=24'}
104
104
 
105
105
  '@ai-ecoverse/slicc-cdp@1.30.18':
@@ -111,9 +111,9 @@ packages:
111
111
  resolution: {integrity: sha512-p7b1h85qkiU0LKjNLCLiU7GVXjGigkyR2+VUCInM1cZo2yjLFxr7tGAOO09e6OG9nB7XKiQn3W88wb3s0gxy+g==}
112
112
  engines: {node: '>=24', slicc-kernel: '>=1.75.0'}
113
113
 
114
- '@ai-ecoverse/slicc-kernel@1.138.0':
115
- resolution: {integrity: sha512-p5cdX1mB6xed1NcRGe0Uifm3NVx8d3YXzA2kLYH2d7HtcSwjvmOU566SUaUKBtbgwXHRAC5gAfW1QoD6/fAiOQ==}
116
- engines: {node: '>=24'}
114
+ '@ai-ecoverse/slicc-kernel@1.143.5':
115
+ resolution: {integrity: sha512-ItE5vaA496NLHEr0HM4QUI8yEeRdUCIVtAFldTKAFdgRK7CdeKsaVbGLla10GxeIv0xNkcny2Ee1VHS1EjnCYQ==}
116
+ engines: {node: '>=26'}
117
117
 
118
118
  '@ai-ecoverse/slicc-spectrum@1.104.1':
119
119
  resolution: {integrity: sha512-/NNo3NmWc8l4+fcVKlynOKzRFbi2N/1H1w8Hkn4N8B51UgjvAW+Y3oykgp0kePQPb11zjithkKmZjC22CdXMkw==}
@@ -207,13 +207,13 @@ packages:
207
207
 
208
208
  snapshots:
209
209
 
210
- '@ai-ecoverse/slicc-browsers@1.10.3': {}
210
+ '@ai-ecoverse/slicc-browsers@1.13.5': {}
211
211
 
212
212
  '@ai-ecoverse/slicc-cdp@1.30.18': {}
213
213
 
214
214
  '@ai-ecoverse/slicc-clipboard@1.0.2': {}
215
215
 
216
- '@ai-ecoverse/slicc-kernel@1.138.0': {}
216
+ '@ai-ecoverse/slicc-kernel@1.143.5': {}
217
217
 
218
218
  '@ai-ecoverse/slicc-spectrum@1.104.1': {}
219
219