@ai-ecoverse/slicc-bios 1.32.0 → 1.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -182,6 +182,21 @@ The Files panel lists `/opt/grammars/node_modules` but doesn't scan it.
182
182
 
183
183
  `os/updates.js` is spectrum's `UpdatesPort` (`model.updates`, spectrum ≥ 1.27.0), with one row per component: **Agent** (`/opt/agent`), **Kernel** (`slicc-kernel`), **UI** (`slicc-spectrum`), **BIOS packages** (the other root packages) and **Syntax grammars**. Each row shows its version, when it was last checked, pnpm's download or link count while it installs, and pnpm's output under *Install log*. A component that isn't installed yet is *Waiting* (`queued`, spectrum ≥ 1.29.0) until its install starts. A failed row leads with one sentence on what failed and what to do, and keeps pnpm's output in the log. `ready()` is false at every boot until the agent's model is in place, or until the check finds no agent to start. While it is false, spectrum opens the Install / Update panel, so it shows while the agent installs or loads; while an installed agent starts, its row reads *Starting* (`starting`, spectrum ≥ 1.37.0). It closes once the agent is up without failures, and a new failure opens it again. An installed agent that doesn't start fails its row with **Retry**. Background updates show in the header. Each row's actions go back to the installers: **Retry** runs that installer again, **Restart agent** restarts the agent worker and **Reload** reloads through the BIOS.
184
184
 
185
+ #### Developer mode and agent betas
186
+
187
+ **Developer mode** (`os/beta.js`, #641) lets the owner try a newer slicc-agent from npm before it's certified. It's off by default, and with it off nothing changes: the deployment's lockfiles are the only source. Only the agent (`/opt/agent`) gets betas for now.
188
+
189
+ - **The switch:** `model.updates.developer()` and `setDeveloper(on)`, rendered in Settings by spectrum. Only the owner tab's own port has them. Other tabs' mirrored ports, remote followers and guests don't, and the owner tab refuses `install-beta` and `back-to-certified` from other tabs. The setting is `slicc-os.developer` in the owner page's `localStorage`, which no kernel process and no agent worker can reach (and the guard keeps the agent's CDP off seven's tabs). No file, URL, hash or environment variable turns it on.
190
+ - **The check:** at every update check with developer mode on, bios reads `https://registry.npmjs.org/@ai-ecoverse/slicc-agent/latest`. When that version is newer than both the certified pin and what's installed, it's offered only if:
191
+ - it has npm's `dist.integrity` and an SLSA v1 provenance attestation whose subject is this release with that sha512, built from `github.com/ai-ecoverse/slicc-agent` (otherwise the row says *not offered: no provenance*) by its `.github/workflows/release.yml` on `refs/heads/main` or `refs/tags/v<version>` (otherwise *not offered: built outside the release workflow*). bios trusts the attestation npm stores: npm verified its Sigstore signature when the version was published, and bios checks the statement's subject, repository, workflow and ref but not the signature again, so it trusts the registry as much as pnpm already does for the tarball;
192
+ - its peer ranges and `engines.slicc-kernel` accept seven's kernel and spectrum;
193
+ - `pnpm install --lockfile-only` in `/opt/slicc/beta/agent`, started from the deployment's lock with only the agent's pin changed, resolves the agent with npm's integrity, and every gated package that changes (see [Certified packages](#certified-packages)) is in `certs.json`.
194
+
195
+ The row's `npm` field says what it found (`offered` with how many packages change and which gated ones, `not-offered` with the reason, `current`, `failed`).
196
+ - **Install beta** asks first, naming the version, the certified version and what changes in `/opt/agent`'s lockfile. Then it keeps the resolved lockfile and manifest in `slicc-os.beta` in `localStorage`, and the agent installs from them with `--frozen-lockfile` as usual. Afterwards bios checks that the installed lock is exactly the approved one and that `/opt/agent` has that version; otherwise it goes back to the certified pin and says why. Later checks install the same beta, so it isn't "repaired" back.
197
+ - **Always marked:** the row's `beta` field (`{ version, certified }`) and a warning notice in the chat panels, *The agent runs a beta*, with **Back to certified**. Dismissing the notice hides it for the session, and it comes back at the next boot.
198
+ - **Back to certified** drops the record, installs the certified lock again and restarts a running agent (once it's idle), so the uncertified worker doesn't keep running unmarked. When the deployment's agent lock changes, the beta goes too, with a notice. If seven now ships the beta's version or a newer one, the notice says the beta is no longer needed; otherwise it says to install the beta again. Turning developer mode off asks whether to return a beta to certified (**Keep beta** keeps it marked) and stops the offers.
199
+
185
200
  #### Optional packages
186
201
 
187
202
  Below the system rows, Install / Update offers **Optional packages** (spectrum ≥ 1.42.0): tools that seven doesn't preinstall, each at the version the homescoop coordinator certified. The catalog is [`src/packages/optional/`](src/packages/optional/): `package.json` pins each package exactly, `package-lock.json` (made with `npm install --package-lock-only --ignore-scripts`, never installed) holds its integrity, and `catalog.json` gives its id, label, description, commands, tarball size and `requires`. A test keeps the three in step. 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 catalog entries provide the same command, so an install never shadows another entry's.
@@ -574,7 +589,7 @@ No test calls a real model. Every test serves an empty `packages/agent/` project
574
589
 
575
590
  ### CI
576
591
 
577
- `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 guard-set file with its variants (the other files join the first), counting a test the guard-set helper reports for that run's guard-set file, 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.
592
+ `ci.yml` runs on pull requests, the merge queue and pushes to `main`. Its jobs run on the Cloud Run pools (`CERT_RUNNER` for the shards, `CERT_LIGHT_RUNNER` for the rest) for same-repo pull requests, the merge queue, dispatches and `main`, and on `ubuntu-latest` for forks; until 2026-10-20 the merge queue ran on `ubuntu-latest`, where its shards waited for GitHub's runners. 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 guard-set file with its variants (the other files join the first), counting a test the guard-set helper reports for that run's guard-set file, 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.
578
593
 
579
594
  On a pull request, the plan first reads the files the pull request changes (`git diff HEAD^1 HEAD` on its merge commit) and picks a mode ([`scripts/ci/scope.mjs`](scripts/ci/scope.mjs)):
580
595
 
@@ -586,7 +601,7 @@ On a pull request, the plan first reads the files the pull request changes (`git
586
601
 
587
602
  [`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.
588
603
 
589
- 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). From 2026-10-17 to 2026-10-18 a two-by-two experiment compared that with control: 0 of 28 merge queue runs with retry failed, against 15 of 42 without it, so the arms without retry were retired. The pull request's number mod 2 still picks whether a failing shard also cancels the others (`fail-fast+retry` for odd numbers, `retry` for even ones and pushes to `main`), for its runs and its merge queue runs alike, to measure what fail-fast does to the time a pull request waits on CI and its time to merge. 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.
604
+ 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.
590
605
 
591
606
  ## Hosting
592
607
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-ecoverse/slicc-bios",
3
- "version": "1.32.0",
3
+ "version": "1.33.0",
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",
@@ -46,7 +46,7 @@
46
46
  "@ai-ecoverse/slicc-browsers": "1.10.3",
47
47
  "@ai-ecoverse/slicc-node": "2.5.1",
48
48
  "@ai-ecoverse/slicc-shared-web": "1.24.2",
49
- "@ai-ecoverse/slicc-spectrum": "1.100.0",
49
+ "@ai-ecoverse/slicc-spectrum": "1.101.0",
50
50
  "@ai-ecoverse/slicc-vault": "1.15.1",
51
51
  "@biomejs/biome": "2.5.15",
52
52
  "es-module-lexer": "3.0.3",
@@ -10,7 +10,7 @@
10
10
  "@ai-ecoverse/slicc-cdp": "1.30.14",
11
11
  "@ai-ecoverse/slicc-clipboard": "1.0.2",
12
12
  "@ai-ecoverse/slicc-kernel": "1.136.1",
13
- "@ai-ecoverse/slicc-spectrum": "1.100.0",
13
+ "@ai-ecoverse/slicc-spectrum": "1.101.0",
14
14
  "@ai-ecoverse/wasi-fnox": "1.39.0-5",
15
15
  "@ai-ecoverse/wasi-pnpm": "12.9.1-17",
16
16
  "@ai-ecoverse/wasi-ripgrep": "15.2.0-5",
@@ -81,9 +81,9 @@
81
81
  }
82
82
  },
83
83
  "node_modules/@ai-ecoverse/slicc-spectrum": {
84
- "version": "1.100.0",
85
- "resolved": "https://registry.npmjs.org/@ai-ecoverse/slicc-spectrum/-/slicc-spectrum-1.100.0.tgz",
86
- "integrity": "sha512-AT96NjcXRpjK2snrdgwFZoKWz3ndCAKI3D3Ce3tU9tI8gv8jOjonFK5rlvcsutlm+cJdFURhMottViGlB+ErPQ==",
84
+ "version": "1.101.0",
85
+ "resolved": "https://registry.npmjs.org/@ai-ecoverse/slicc-spectrum/-/slicc-spectrum-1.101.0.tgz",
86
+ "integrity": "sha512-m2+lFTgPvaY2zl0ITxxPOZJOSBmGThZneeNj5GbiJvGuM0rhil1xF61Htetz6nob6xRXm9titmXXfi3DuQ0WUQ==",
87
87
  "license": "Apache-2.0",
88
88
  "engines": {
89
89
  "node": ">=24"
@@ -7,7 +7,7 @@
7
7
  "@ai-ecoverse/slicc-cdp": "1.30.14",
8
8
  "@ai-ecoverse/slicc-clipboard": "1.0.2",
9
9
  "@ai-ecoverse/slicc-kernel": "1.136.1",
10
- "@ai-ecoverse/slicc-spectrum": "1.100.0",
10
+ "@ai-ecoverse/slicc-spectrum": "1.101.0",
11
11
  "@ai-ecoverse/wasi-fnox": "1.39.0-5",
12
12
  "@ai-ecoverse/wasi-pnpm": "12.9.1-17",
13
13
  "@ai-ecoverse/wasi-ripgrep": "15.2.0-5",
@@ -21,8 +21,8 @@ importers:
21
21
  specifier: 1.136.1
22
22
  version: 1.136.1
23
23
  '@ai-ecoverse/slicc-spectrum':
24
- specifier: 1.100.0
25
- version: 1.100.0
24
+ specifier: 1.101.0
25
+ version: 1.101.0
26
26
  '@ai-ecoverse/wasi-fnox':
27
27
  specifier: 1.39.0-5
28
28
  version: 1.39.0-5
@@ -115,8 +115,8 @@ packages:
115
115
  resolution: {integrity: sha512-OIrL7sWfPIM+uyUQxqpwfYKiMX+lc58kcR8gx1zYi9R0I8UTcsMCKXJsW+VrFHcCqXY/7G3YE/9LB9I0VTJtXQ==}
116
116
  engines: {node: '>=24'}
117
117
 
118
- '@ai-ecoverse/slicc-spectrum@1.100.0':
119
- resolution: {integrity: sha512-AT96NjcXRpjK2snrdgwFZoKWz3ndCAKI3D3Ce3tU9tI8gv8jOjonFK5rlvcsutlm+cJdFURhMottViGlB+ErPQ==}
118
+ '@ai-ecoverse/slicc-spectrum@1.101.0':
119
+ resolution: {integrity: sha512-m2+lFTgPvaY2zl0ITxxPOZJOSBmGThZneeNj5GbiJvGuM0rhil1xF61Htetz6nob6xRXm9titmXXfi3DuQ0WUQ==}
120
120
  engines: {node: '>=24'}
121
121
  peerDependencies:
122
122
  '@shikijs/langs': 4.5.0
@@ -215,7 +215,7 @@ snapshots:
215
215
 
216
216
  '@ai-ecoverse/slicc-kernel@1.136.1': {}
217
217
 
218
- '@ai-ecoverse/slicc-spectrum@1.100.0': {}
218
+ '@ai-ecoverse/slicc-spectrum@1.101.0': {}
219
219
 
220
220
  '@ai-ecoverse/wasi-fnox@1.39.0-5': {}
221
221