@ai-ecoverse/slicc-bios 1.13.0 → 1.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -73,7 +73,7 @@ The kernel runs with users on (slicc-kernel ≥ 1.81.0): files have owners and m
73
73
  - **Folders** bios mounts (picked in the Files panel, remembered, or linked) belong to the first cone, so the agent can write them, and to root while users are off.
74
74
  - **Files from before users:** agents start on the new layout; nothing is moved. On the first boot with users on, bios runs `chmod -R go-rwx` as root, once, on what earlier versions left readable to everyone: `/home/.pi`, `/home/.slicc`, `/home/sprinkles`, `/home/.gelatiere`, `/home/.welcomed`, `/home/.welcome.json`, `/home/sessions`, `/home/.local` and `/scoops`. So no cone or scoop reads an old `mcp.json` with its tokens, and root still reads everything. The marker `var/lib/slicc/legacy-locked` keeps it from running again; cone and scoop homes and other files in `/home` aren't touched.
75
75
  - **The agent's `KernelSource`** (`os/users.js`) passes `connect({ user, agentId })`, `users` and `groups` to the kernel, only for agent users. It refuses root and any user but `cone`, `cone-<n>` and `scoop-<folder>`, requires the agentId to match the user exactly (`cone:cone`, `cone:cone-2`, `scoop:<folder>`), and allows groups only of cones and `sudo` only for cones. A cone is always added to `sudo`, even when the caller leaves it out, since sudo membership is what makes a cone (the vault's J2 rule). The tag is `{"kind":"agent","agentId":…}` as JSON, and the agent's root client carries `{"kind":"agent","agentId":"root"}`; a panel terminal's is `{"kind":"user","where":"terminal:<tab>"}`.
76
- - **Protected code paths:** under `'enforce'`, the kernel gets `protect: { paths: ['/node_modules', '/opt/agent', '/opt/grammars', '/opt/tailscale', '/opt/slicc', '/os'], writers: ['bios-installer'] }` (slicc-kernel ≥ 1.81.0), the install kernels too. No process changes them, root included (`EROFS`; a cone sees `EACCES` first), and nothing mounts at, under or above them.
76
+ - **Protected code paths:** under `'enforce'`, the kernel gets `protect: { paths: ['/node_modules', '/opt/agent', '/opt/grammars', '/opt/tailscale', '/opt/slicc', '/os'], writers: ['bios-installer'] }` (slicc-kernel ≥ 1.81.0). No process changes them, root included (`EROFS`; a cone sees `EACCES` first), and nothing mounts at, under or above them.
77
77
  - **bios's installs** (pnpm into the base set, `/opt/*` and `/opt/slicc/<project>`, and the `chmod -R a+rX` pass) run as `kernel.run(argv, { cwd, tag: 'bios-installer', env })`. The env is clean: `HOME=/opt/slicc/.installer`, its own config and cache, the system `PNPM_HOME` and `PATH`, and an empty `NODE_OPTIONS`.
78
78
  - **pnpm runs with** `--ignore-scripts --ignore-pnpmfile --config.userconfig=/dev/null --config.store-dir=/opt/slicc/.store --config.verify-store-integrity=true`. No locked package in the base set, `/opt/agent`, `/opt/grammars`, `/opt/tailscale` or the data tools has an install script.
79
79
  - **The base project** moves out of `/`: its `package.json`, `pnpm-lock.yaml` and `pnpm-workspace.yaml` are in `/opt/slicc/base`, written by the BIOS installer and the in-place update, and pnpm installs it with `--modules-dir=/node_modules` from there. So everything pnpm reads is inside a protected path, and a root process that writes `/package.json`, `/pnpm-lock.yaml`, `/.npmrc` or `/pnpm-workspace.yaml` changes nothing; bios removes those at every boot. A protected project without its own `pnpm-workspace.yaml` gets one, so pnpm's search for a workspace stops inside the tree. The service worker's resolver no longer reads a `package.json` at `/` for `browser` mappings.
@@ -160,6 +160,8 @@ Spectrum bundles 16 syntax languages; the rest come from `@shikijs/langs` and `@
160
160
 
161
161
  1. **Until they're installed,** the UI loads grammars from jsDelivr.
162
162
  2. **After every update check,** `os/grammars.js` compares the deployed `packages/grammars/pnpm-lock.yaml` with `var/lib/slicc/grammars/pnpm-lock.yaml`. If they differ, it writes the manifest (merged with the user's layer, see [Your packages](#your-packages)) and lockfile to `/opt/grammars` and runs `pnpm install --frozen-lockfile --trust-lockfile` there, under its own Web Lock, `slicc-grammars`, so a long install never holds up the BIOS in another tab. Only once pnpm succeeds does it record the lockfile.
163
+
164
+ It runs in the page's own kernel, like the agent and Tailscale installs and the `chmod -R a+rX` pass, never in a second kernel on the same OPFS root. A second kernel on one root makes both pay for keeping their files in step (slicc-kernel ≥ 1.119.0 made a cold agent install about 3× slower that way). Every bios pnpm run, these installs and the optional packages' `pnpm add -g` and `remove -g`, also takes the Web Lock `slicc-pnpm-store`, so only one pnpm uses the store at a time, in this tab or another.
163
165
  3. **Once they're installed,** `grammarBase` points at `/opt/grammars/node_modules/@shikijs/`. On later loads the page sets it as soon as the recorded lockfile is there, before any network check, so highlighting works offline. If pnpm fails, the page stays on jsDelivr, the **Syntax grammars** row shows the error with **Retry**, and the next check tries again.
164
166
 
165
167
  The Files panel lists `/opt/grammars/node_modules` but doesn't scan it.
@@ -475,7 +477,7 @@ Limits:
475
477
 
476
478
  [`.github/workflows/canary.yml`](.github/workflows/canary.yml) answers "is bios main green with these candidate versions?" before anyone asks for a pin. It never pushes, pins or opens a PR: it reports.
477
479
 
478
- - **Triggers:** `workflow_dispatch` and `workflow_call` with `overrides`, a JSON list of `name@version` (`["@ai-ecoverse/slicc-kernel@1.81.0"]`), and optionally `runner`, `shards` (names from [`scripts/canary/shards.json`](scripts/canary/shards.json); ci.yml's `follow-chat`, `remote-pydata`, `users-agent-ui`, `packages-update-cdp`, `guard`, `guard-set-extension-prompt`, `guard-set-extension-lagging`, `guard-set-proxy-prompt`, `guard-set-proxy-lagging`, `k4-link`, `user-packages-keys-favicon` and `rest` by default; a shard's `env` in that file, such as `GUARD_VARIANTS`, is set for its tests, or `sweep` for just the base-set sweep and the certs check), `expect` and `bios-ref` (any branch or sha of slicc-bios: the shard jobs check it out and lay this ref's `scripts/canary`, and `sweep.test.mjs` if it has none, over it; a ref whose `pins.test.mjs` has no canary mode gets the candidates in its working copy of `certs.json` instead, and the report still lists them as candidates). A proof in `proofs.json` can name its own `ref` the same way. An hourly `schedule` checks npm's `latest` of every kernel, jsh, cdp, agent, `wasm-*`, `wasi-*`, `wasix-*` and `py-*` package that a `src/packages/**/package.json` pins, and runs once with every newer one as the overrides, only when that list differs from the last scheduled canary's (its inputs are kept in the Actions cache). A `pull_request` trigger, filtered to the canary's own files, runs the proof in [`scripts/canary/proofs.json`](scripts/canary/proofs.json) from one plan job, cancelling a superseded run: kernel 1.78.0 on the `sweep` shard must regress grep, sed, jq, xz, findutils, diffutils and patch with exit 70 (kernel #483). A second proof packs `@ai-ecoverse/slicc-cdp@1.26.2` with `npm pack`, uploads it from the plan job, and runs it as a candidate artifact on `packages-update-cdp` and `guard` with `repeat: 3`.
480
+ - **Triggers:** `workflow_dispatch` and `workflow_call` with `overrides`, a JSON list of `name@version` (`["@ai-ecoverse/slicc-kernel@1.81.0"]`), and optionally `runner`, `shards` (names from [`scripts/canary/shards.json`](scripts/canary/shards.json); `follow-chat`, `remote-pydata`, `users-agent-ui`, `packages-update-cdp`, `guard`, `guard-set-extension-prompt`, `guard-set-extension-lagging`, `guard-set-proxy-prompt`, `guard-set-proxy-lagging`, `k4-link`, `user-packages-keys-favicon` and `rest` by default; a shard's `env` in that file, such as `GUARD_VARIANTS`, is set for its tests, or `sweep` for just the base-set sweep and the certs check), `expect` and `bios-ref` (any branch or sha of slicc-bios: the shard jobs check it out and lay this ref's `scripts/canary`, and `sweep.test.mjs` if it has none, over it; a ref whose `pins.test.mjs` has no canary mode gets the candidates in its working copy of `certs.json` instead, and the report still lists them as candidates). A proof in `proofs.json` can name its own `ref` the same way. An hourly `schedule` checks npm's `latest` of every kernel, jsh, cdp, agent, `wasm-*`, `wasi-*`, `wasix-*` and `py-*` package that a `src/packages/**/package.json` pins, and runs once with every newer one as the overrides, only when that list differs from the last scheduled canary's (its inputs are kept in the Actions cache). A `pull_request` trigger, filtered to the canary's own files, runs the proof in [`scripts/canary/proofs.json`](scripts/canary/proofs.json) from one plan job, cancelling a superseded run: kernel 1.78.0 on the `sweep` shard must regress grep, sed, jq, xz, findutils, diffutils and patch with exit 70 (kernel #483). A second proof packs `@ai-ecoverse/slicc-cdp@1.26.2` with `npm pack`, uploads it from the plan job, and runs it as a candidate artifact on `packages-update-cdp` and `guard` with `repeat: 3`.
479
481
  - **A candidate from another repo's run:** `candidate-package` (the package it replaces, `@ai-ecoverse/slicc-cdp`), `candidate-artifact` (an artifact holding one `npm pack` tarball of it), `candidate-run` (the run that uploaded it), `candidate-sha256` and optionally `candidate-repo` (the caller's repository by default). Each shard job downloads the artifact with `github.token`, which under `workflow_call` is the caller's, so the caller's job needs `actions: read`. [`override-pins.mjs`](scripts/canary/override-pins.mjs) checks the tarball's sha256 before it reads anything and refuses a mismatch, then checks the tarball is that package with an exact version. It seeds the harness download cache with the bytes at the npm URL of that version, and rewrites the pins and locks through a local registry that serves npm's packuments with that version added, so an unpublished `x.y.z-pr.N.M` locks like a published one (npm's lock gets the registry URL back). Everything else stays a registry version. The report lists it as `candidate (artifact <run>/<name>, sha256 …)`.
480
482
  - **`repeat`** (1 to 10, default 1): each selected test file runs that many times with the candidates, and the files with a failure run that many times on main's pins. A test failing in every candidate run and no baseline run is a regression, one failing in every run of both is a failure on both, and anything mixed is flaky. Each row carries its counts, `candidate 2/3, baseline 0/3`.
481
483
  - **`result`**, a `workflow_call` output next to `ok`: the JSON summary (`ok`, `counts`, `regressions`, `both`, `flaky`, `failures`, `missingShards`, `unexplainedExits`, `candidates`, `overrides`, `repeat`) plus the `canary` artifact's name and URL.
@@ -484,7 +486,7 @@ Limits:
484
486
  - **Runner:** fork code never runs on the org's Cloud Run pools. A same-repo `pull_request` (the proofs from our own branches), or a `schedule`, `workflow_dispatch`, `workflow_run` or `release` run on `main` (any `bios-ref`), puts the shard jobs on the `runner` input, else the `CERT_RUNNER` repository variable (`cloud-run-bench`), and the light plan and report jobs on `CERT_LIGHT_RUNNER` (`cloud-run`). Everything else runs on `ubuntu-latest`, and the `runner` input is ignored: fork pull requests, and dispatches from any other branch. Under `workflow_call` the same check reads the caller's event. The pools run with "no new privileges", so `sudo` can't become root there: the shard job installs Chromium's system libraries only when `sudo -n true` works, and otherwise relies on the image's.
485
487
  - **Pins:** [`scripts/canary/override-pins.mjs`](scripts/canary/override-pins.mjs) `name@version …` fetches each tarball through the harness download cache (so the tests find it there), checks it against npm's sha512 and records its sha256. It sets the version in every `package.json` under `src/packages` that pins the package and lets npm (`--package-lock-only`) and pnpm 12 (`--lockfile-only`) rewrite that directory's lockfiles, so a dependency that moves with the package (an agent release taking a newer slicc-browsers) moves in the lock too. A package that is only a dependency in a pnpm lock is forced with an `overrides` entry in that directory's `pnpm-workspace.yaml`. One that is only a dependency in an npm lock (wasm-git's own wasm-bash in the optional catalog) is left alone and reported as held. It writes `node_modules/.cache/slicc-canary/pins.json`, whose `candidates` are the gated packages the locks now pin that `certs.json` doesn't certify.
486
488
  - **Certs check:** with `SLICC_CANARY` set to that file, `pins.test.mjs` reports those candidates as "candidate, not certified" instead of failing on them; anything else uncertified still fails. Without it (normal CI) the check is unchanged.
487
- - **Tests:** the same integration shards as `ci.yml`, run by [`scripts/canary/shard.mjs`](scripts/canary/shard.mjs) with the overrides. The test files with a failure run again on main's pins, and the ones that passed there run once more with the overrides, so each failure is a regression (passes on main's pins, fails with the overrides), a failure on both, or flaky. Tests that assert a pinned version by value (`jsh.test.mjs` for slicc-jsh, `update.test.mjs` and `reuse.test.mjs` for wasm-bash) regress whenever that package is overridden.
489
+ - **Tests:** the named shards in `shards.json` (`ci.yml` assigns files to shards at random instead, see [CI](#ci)), run by [`scripts/canary/shard.mjs`](scripts/canary/shard.mjs) with the overrides. The test files with a failure run again on main's pins, and the ones that passed there run once more with the overrides, so each failure is a regression (passes on main's pins, fails with the overrides), a failure on both, or flaky. Tests that assert a pinned version by value (`jsh.test.mjs` for slicc-jsh, `update.test.mjs` and `reuse.test.mjs` for wasm-bash) regress whenever that package is overridden.
488
490
  - **Output:** a `canary` artifact with `canary.json` (`<proof>/canary.json` for the proofs), `{ biosRef, overrides: [{ name, version, sha256 }], candidates, held, shards: [{ shard, wallMs, phases }], results: [{ test, status, baseline, retry, verdict, log }] }`, and a job summary with the overrides, a note when a slicc-kernel override of 1.78.0 or later meets a ref whose `src/` calls `createKernel` without a `users` mode (that kernel then defaults to `enforce`, and `i`, `npm` and `npx` by path exit 126 until #405 and kernel #495; [`scripts/canary/users.mjs`](scripts/canary/users.mjs) finds the calls, and `canary.json` lists them as `kernels`), the wall time of each shard and the failures split into regressions, failures on both, and flaky ones. The report job fails on a failure without overrides, on a missing shard, on a shard that exited nonzero with no failing test (a crash or a throwing teardown), when an `expect` entry (a `{ test, log }` pair of substrings) matches no regression, or on a regression no `expect` entry matches, unless the run sets `strict: false`. `test/integration/canary.test.mjs` checks these rules.
489
491
 
490
492
  `test/integration/sweep.test.mjs`, the base-set sweep, runs in both workflows. It boots the BIOS, checks that each base-set package in OPFS has the version `package-lock.json` pins, and runs every command its `slicc.commands` lists with `--version` or a trivial call under `timeout 60`, then real grep, egrep, sed -i, xz, jq, find, xargs, diff, cmp, patch, awk, gzip, bzip2 and tar work. Each command is its own subtest named `<package> · <call>`. The clipboard commands run `--help` (`xclip -help`). Known exits: `false` 1, `bunzip2`/`bzcat --version` 2 (upstream), `i --version` 2 (argument parsing; 126 is #495), and `chcon`/`runcon` 1 (listed by coreutils, not built: "unknown program"). `[` runs as bash's builtin, since `timeout` can't exec it.
@@ -514,6 +516,12 @@ CPU profiling is off by default, in CI too: V8's sampler interrupts every page a
514
516
 
515
517
  No test calls a real model. Every test serves an empty `packages/agent/` project (`emptyAgent` in `test/integration/chrome.mjs`), so only the chat test installs the agent in the background. In it, `test/integration/fake-proxy.mjs` plays a local proxy and answers Bedrock's `converse-stream` with a scripted event stream, so the turn runs through the real agent worker, pi-ai's Bedrock client and the kernel's transport. The test also signs in to Adobe against a fake IMS (`--host-resolver-rules` maps `ims-na1.adobelogin.com` to a local HTTPS server) and the fake proxy's `oauth-state`/`oauth-result` endpoints, cancelling once first.
516
518
 
519
+ ### CI
520
+
521
+ `ci.yml` runs on pull requests, the merge queue and pushes to `main`. A `ci / plan` job ([`scripts/ci/plan.mjs`](scripts/ci/plan.mjs)) splits the integration tests into 14 shards: each `guard-set-*.test.mjs` becomes one item per detach variant of the pinned guard vectors (run with `GUARD_VARIANTS`), every other test file is one item, and the items go in a random order, seeded with the run id, to the least-loaded shard by the times in [`scripts/ci/durations.json`](scripts/ci/durations.json), the longest items first. Each shard (`ci / integration (s01)` …) runs its items with [`scripts/ci/shard.mjs`](scripts/ci/shard.mjs), one `node --test` per set of variants, keeps the harness's artifacts and coverage from every run, and writes its verdict line. `ci / test`, the required check, fails without a passing verdict from every shard the plan named.
522
+
523
+ The pull request's number mod 4 picks an arm of a two-by-two experiment, for its runs and its merge queue runs alike (pushes to `main` are control): 0 is control, 1 cancels the other shards when one fails (`fail-fast`), 2 runs the files with a failing test once more and passes the shard when they pass (`retry`, skipped when it wouldn't fit the shard's 62 minutes), and 3 does both. 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. After 100 pull requests the arms are compared on time to merge, merge queue failures, and the time a pull request waits on CI.
524
+
517
525
  ## Hosting
518
526
 
519
527
  `main` is live at <https://seven.sliccy.ai/>, and every other branch at `https://<branch>.sliccy.ai/`, where the branch name is lowercased and runs of anything but letters and digits become `-` (`feat/edge-hosting` → <https://feat-edge-hosting.sliccy.ai/>). Each host is its own origin, so a branch gets its own OPFS and service worker and can't disturb `seven`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-ecoverse/slicc-bios",
3
- "version": "1.13.0",
3
+ "version": "1.13.1",
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",
@@ -43,7 +43,7 @@
43
43
  },
44
44
  "devDependencies": {
45
45
  "@ai-ecoverse/slicc": "1.42.4",
46
- "@ai-ecoverse/slicc-browsers": "1.7.6",
46
+ "@ai-ecoverse/slicc-browsers": "1.7.10",
47
47
  "@ai-ecoverse/slicc-node": "2.5.1",
48
48
  "@ai-ecoverse/slicc-shared-web": "1.23.1",
49
49
  "@ai-ecoverse/slicc-spectrum": "1.84.2",
@@ -6,7 +6,7 @@
6
6
  "": {
7
7
  "name": "slicc-bios-packages",
8
8
  "dependencies": {
9
- "@ai-ecoverse/slicc-browsers": "1.7.6",
9
+ "@ai-ecoverse/slicc-browsers": "1.7.10",
10
10
  "@ai-ecoverse/slicc-cdp": "1.26.2",
11
11
  "@ai-ecoverse/slicc-clipboard": "1.0.2",
12
12
  "@ai-ecoverse/slicc-kernel": "1.113.0",
@@ -37,9 +37,9 @@
37
37
  }
38
38
  },
39
39
  "node_modules/@ai-ecoverse/slicc-browsers": {
40
- "version": "1.7.6",
41
- "resolved": "https://registry.npmjs.org/@ai-ecoverse/slicc-browsers/-/slicc-browsers-1.7.6.tgz",
42
- "integrity": "sha512-clzlvrVLjmWEiKXhuK/Lez7y3Dwmo+FJ8POUs5GYqLJy5u8cOAiXyliQlNUNOVkNx9EoPm0RVvdfFkSTgv/isg==",
40
+ "version": "1.7.10",
41
+ "resolved": "https://registry.npmjs.org/@ai-ecoverse/slicc-browsers/-/slicc-browsers-1.7.10.tgz",
42
+ "integrity": "sha512-D0UZs7HCX1V43fb6hPafaFwNCOE7DTbVsDraIoJ2mER14LN2tOraSuLomcSENWaeEQl+m+KeKSPOewnKHEc4xw==",
43
43
  "license": "Apache-2.0",
44
44
  "engines": {
45
45
  "node": ">=24"
@@ -3,7 +3,7 @@
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.7.6",
6
+ "@ai-ecoverse/slicc-browsers": "1.7.10",
7
7
  "@ai-ecoverse/slicc-cdp": "1.26.2",
8
8
  "@ai-ecoverse/slicc-clipboard": "1.0.2",
9
9
  "@ai-ecoverse/slicc-kernel": "1.113.0",
@@ -9,8 +9,8 @@ importers:
9
9
  .:
10
10
  dependencies:
11
11
  '@ai-ecoverse/slicc-browsers':
12
- specifier: 1.7.6
13
- version: 1.7.6
12
+ specifier: 1.7.10
13
+ version: 1.7.10
14
14
  '@ai-ecoverse/slicc-cdp':
15
15
  specifier: 1.26.2
16
16
  version: 1.26.2
@@ -95,8 +95,8 @@ importers:
95
95
 
96
96
  packages:
97
97
 
98
- '@ai-ecoverse/slicc-browsers@1.7.6':
99
- resolution: {integrity: sha512-clzlvrVLjmWEiKXhuK/Lez7y3Dwmo+FJ8POUs5GYqLJy5u8cOAiXyliQlNUNOVkNx9EoPm0RVvdfFkSTgv/isg==}
98
+ '@ai-ecoverse/slicc-browsers@1.7.10':
99
+ resolution: {integrity: sha512-D0UZs7HCX1V43fb6hPafaFwNCOE7DTbVsDraIoJ2mER14LN2tOraSuLomcSENWaeEQl+m+KeKSPOewnKHEc4xw==}
100
100
  engines: {node: '>=24'}
101
101
 
102
102
  '@ai-ecoverse/slicc-cdp@1.26.2':
@@ -200,7 +200,7 @@ packages:
200
200
 
201
201
  snapshots:
202
202
 
203
- '@ai-ecoverse/slicc-browsers@1.7.6': {}
203
+ '@ai-ecoverse/slicc-browsers@1.7.10': {}
204
204
 
205
205
  '@ai-ecoverse/slicc-cdp@1.26.2': {}
206
206