superbee 0.2.1-pre.2 → 0.3.0-pre.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "superbee",
3
- "version": "0.2.1-pre.2",
3
+ "version": "0.3.0-pre.1",
4
4
  "type": "module",
5
5
  "description": "Agent-facing Superbee CLI for reading and writing local OKF knowledge bundles: context notes, docs, cross-links, and live bundle Views.",
6
6
  "keywords": [
@@ -54,11 +54,9 @@
54
54
  "scripts": {
55
55
  "build": "node build.mjs local-dev",
56
56
  "build:npm-package": "node build.mjs npm-package",
57
- "typecheck": "tsc --noEmit && tsc -p tsconfig.test.json",
57
+ "typecheck": "tsc --noEmit",
58
58
  "pretest": "node build.mjs local-dev",
59
- "test:host-class": "node scripts/run-test-command.mjs node --test --import ./test/ts-loader.mjs ./test/private-state-bundle-boundary.test.ts ./test/filesystem-cross-process-cas.test.ts ./test/link.test.ts ./test/promote-pull.test.ts ./test/recipe-source.test.ts ./test/command-text.test.ts",
60
- "test": "node scripts/run-test-command.mjs node --test --import ./test/ts-loader.mjs ./test/*.test.ts",
61
- "mutation": "node scripts/run-test-command.mjs npm-exec stryker run",
59
+ "test": "node --test test/*.test.mjs",
62
60
  "gen:skill": "node scripts/gen-skill.mjs",
63
61
  "check:skill": "node scripts/gen-skill.mjs --check",
64
62
  "prepublishOnly": "node -e \"console.error('superbee is released by .github/workflows/release.yml (npm stage publish); do not run npm publish here'); process.exit(1)\""
@@ -73,7 +71,7 @@
73
71
  "@superbee/publication": "*",
74
72
  "@superbee/server": "*",
75
73
  "@superbee/ui-server": "*",
76
- "@toon-format/toon": "2.3.0",
74
+ "@toon-format/toon": "2.3.1",
77
75
  "@types/node": "^22.0.0",
78
76
  "axi-sdk-js": "0.1.8",
79
77
  "esbuild": "0.25.12",
@@ -81,8 +79,13 @@
81
79
  "pako": "2.1.0",
82
80
  "typescript": "^5.4.0",
83
81
  "js-yaml": "3.15.2",
84
- "@types/js-yaml": "3.12.10"
82
+ "@types/js-yaml": "3.12.10",
83
+ "@superbee/cli": "*"
85
84
  },
86
- "readme": "# superbee\n\nShared, versioned, conflict-safe knowledge for AI coding agents, stored as plain markdown in\nyour repo.\n\nSuperbee is pre-1.0. Commands and formats may change between releases.\n\n## What is Superbee?\n\nAgents forget everything between sessions, overwrite each other's work, and keep what they know\ninvisible to the humans they work for. Superbee fixes all three with a **knowledge bundle**: a\nfolder of markdown documents, by convention `.superbee/` at your project root, that agents read\nand write through a small command-line tool.\n\n- **Context that persists.** Agents write context notes, decisions, plans, and research into the\n bundle. The next session, or a different agent, picks up where the last one left off. An\n optional `SessionStart` hook for Claude Code, Codex, and OpenCode orients every new session\n automatically.\n- **Safe for many writers.** Each write can carry the actor that made it. A writer can name the\n version it last read; if anyone changed the document since, the write fails with a typed\n conflict error instead of silently overwriting their work.\n- **Visible to humans.** The bundle is plain markdown. Open it in any editor, render it on\n GitHub, diff it in git. `superbee ui` serves it locally as cross-linked pages with backlinks and\n a live activity feed. No bundle content leaves your machine until you run `superbee sync`, which\n shares the bundle with teammates through the board: a copy of the bundle kept on its own git\n branch, separate from your code.\n- **Views on demand.** Ask your agent for a dashboard, a timeline, a filtered task queue, or a\n reading view of one dense document. It builds a self-contained HTML page, stores it in the bundle\n as a View, and `superbee ui` hosts it in a sandboxed frame. A View reads the bundle live and can\n change it only through a write you confirm. Views are bundle content, so they travel with `sync`.\n- **Built for agents.** Output is structured and token-lean, and errors carry a small, stable set\n of exit codes. Agents act on responses without parsing prose or flooding their context window.\n- **Yours, and portable.** Bundles follow the Open Knowledge Format (OKF), a convention of\n markdown with frontmatter, so they outlive the tool: hand the folder to someone else, or read it\n with anything that speaks markdown. New bundles are written as OKF v0.2, and existing v0.1\n bundles keep working as they are. Reading and writing the bundle works offline; only sharing\n needs a network. The document schemas, called kinds, live inside the bundle, so it describes\n its own structure.\n\nThe npm package is one self-contained executable with zero runtime dependencies, plus an Agent\nSkill, an instruction file your agent loads, that teaches it how to use the tool.\n\n## Install\n\nRequires Node.js 20 or newer on macOS, Linux, or Windows. Native Windows is supported; you do not\nneed WSL or Docker.\n\n```sh\nnpm install -g superbee\n```\n\nStable releases publish on npm's `latest` tag and prereleases on `next`. To try the prerelease:\n\n```sh\nnpm install -g superbee@next\n```\n\nOn Windows, Superbee keeps its private per-user state, such as the workspace catalog and remote\ncredentials, under `%LOCALAPPDATA%\\Superbee`. npm installs `superbee.cmd` alongside the `superbee`\ncommand; if PowerShell's execution policy blocks the `.ps1` wrapper, call `superbee.cmd` instead.\n\nRun `superbee version --check` to compare your install with the current stable release.\n\n## First run: let your agent finish setup\n\n`npm install` gives you the CLI. The integrations (the Agent Skill, the `SessionStart` hook, and\nMCP server registration, where MCP is the Model Context Protocol) are installed by your agent,\nnot by hand. Ask it:\n\n> Run `superbee setup` and follow its instructions.\n\nSetup itself changes nothing. It inspects your configuration and returns one safe next command at\na time, and the agent runs each with your approval. Setup knows Claude Code, Codex, and OpenCode,\nplus Claude Desktop for the MCP registration only.\n\n## Everyday use\n\nYou rarely type Superbee commands yourself. You ask your agent, and the Agent Skill translates the\nrequest into CLI calls:\n\n- \"Set up a Superbee bundle for this project and track our tasks in it.\"\n- \"Write up what we decided about the auth design as a doc, and link it to the task.\"\n- \"What did the last session leave off on? Check the context notes.\"\n- \"Sync the board so my teammate's agent sees this.\"\n- \"Give me a view of the open tasks grouped by owner.\"\n\nBehind those requests the agent uses a small set of commands: `init --dir .superbee` creates the\nbundle, `new` creates a document of a declared kind, `doc write` writes a free-form one,\n`doc update` changes a document, `link add` connects two, `list` and `doc read` query them, and\n`sync` shares the board. `superbee --help` lists the commands, and `superbee <command> --help`\ngives each one's full reference.\n\nThe two commands meant for you are the ones that show you the knowledge:\n\n```sh\nsuperbee ui --open # the whole bundle, rendered in your browser\nsuperbee doc open <id> # one document, by an id from `superbee list`\n```\n\n## Upgrading from aslite\n\nIf you installed the earlier `@holaxis/aslite` package or its marketplace plugin: install\n`superbee` alongside it, have your agent run `superbee setup` to migrate the integrations, then\nrun `npm uninstall -g @holaxis/aslite`. Existing `.agentstate-lite/` bundles and\n`.agentstate.json` bindings keep working with no migration.\n\n## Learn more\n\nThe [repository](https://github.com/Holaxis-ai/superbee) holds the source, the\n[CLI contract](https://github.com/Holaxis-ai/superbee/blob/main/packages/cli/AXI-CONTRACT.md),\nand the [wire protocol](https://github.com/Holaxis-ai/superbee/blob/main/docs/WIRE-PROTOCOL.md).\n\n## License\n\nApache-2.0 © 2026 Holaxis\n",
85
+ "os": [
86
+ "darwin",
87
+ "linux"
88
+ ],
89
+ "readme": "# superbee\n\nShared, versioned, conflict-safe knowledge for AI coding agents, stored as plain markdown in\nyour repo.\n\nSuperbee is pre-1.0. Commands and formats may change between releases.\n\n## What is Superbee?\n\nAgents forget everything between sessions, overwrite each other's work, and keep what they know\ninvisible to the humans they work for. Superbee fixes all three with a **knowledge bundle**: a\nfolder of markdown documents, by convention `.superbee/` at your project root, that agents read\nand write through a small command-line tool.\n\n- **Context that persists.** Agents write context notes, decisions, plans, and research into the\n bundle. The next session, or a different agent, picks up where the last one left off. An\n optional `SessionStart` hook for Claude Code, Codex, and OpenCode orients every new session\n automatically.\n- **Safe for many writers.** Each write can carry the actor that made it. A writer can name the\n version it last read; if anyone changed the document since, the write fails with a typed\n conflict error instead of silently overwriting their work.\n- **Visible to humans.** The bundle is plain markdown. Open it in any editor, render it on\n GitHub, diff it in git. `superbee ui` serves it locally as cross-linked pages with backlinks and\n a live activity feed. No bundle content leaves your machine until you run `superbee sync`, which\n shares the bundle with teammates through the board: a copy of the bundle kept on its own git\n branch, separate from your code.\n- **Views on demand.** Ask your agent for a dashboard, a timeline, a filtered task queue, or a\n reading view of one dense document. It builds a self-contained HTML page, stores it in the bundle\n as a View, and `superbee ui` hosts it in a sandboxed frame. A View reads the bundle live and can\n change it only through a write you confirm. Views are bundle content, so they travel with `sync`.\n- **Built for agents.** Output is structured and token-lean, and errors carry a small, stable set\n of exit codes. Agents act on responses without parsing prose or flooding their context window.\n- **Yours, and portable.** Bundles follow the Open Knowledge Format (OKF), a convention of\n markdown with frontmatter, so they outlive the tool: hand the folder to someone else, or read it\n with anything that speaks markdown. New bundles are written as OKF v0.2, and existing v0.1\n bundles keep working as they are. Reading and writing the bundle works offline; only sharing\n needs a network. The document schemas, called kinds, live inside the bundle, so it describes\n its own structure.\n\nThe npm package is one self-contained executable with zero runtime dependencies, plus an Agent\nSkill, an instruction file your agent loads, that teaches it how to use the tool.\n\n## Install\n\nRequires Node.js 20 or newer on macOS and Linux. Native Windows is not supported by this package.\n\n```sh\nnpm install -g superbee\n```\n\nStable releases publish on npm's `latest` tag and prereleases on `next`. To try the prerelease:\n\n```sh\nnpm install -g superbee@next\n```\n\nWindows adapters and the `superbee-windows` executable live in a separate repository and are\nnot included in `superbee`. Most Windows users should run Superbee in WSL2, where npm sees a\nLinux platform and the normal installation applies. An experimental, unsupported native Windows\nbuild is available as open source, with build-from-source instructions: https://github.com/Holaxis-ai/superbee-windows-cli\n\n### Upgrading an existing Windows installation\n\nThe first release containing the Windows extraction removes native Windows support from this\npackage. Its npm `os` metadata permits only `darwin` and `linux`, so a Windows upgrade to an affected\nversion is rejected with `EBADPLATFORM`. This applies to existing prerelease users too. Forcing the\ninstallation does not restore support: the executable refuses commands on unsupported hosts\nbefore running them (the bare `--version` flag can still identify the installed build).\n\nThere is no supported Windows replacement on npm. The alternatives are WSL2 or the experimental\nbuild from source at https://github.com/Holaxis-ai/superbee-windows-cli; neither carries a\nfirst-party support promise for native Windows. An older installed version is not converted or\nremoved by this source change, and existing bundle files are not migrated by it. Review the affected release's notes before changing an existing\nWindows installation. macOS/Linux users can continue using the normal installation and setup flow.\n\nRun `superbee version --check` to compare your install with the current stable release.\n\n## First run: let your agent finish setup\n\n`npm install` gives you the CLI. The integrations (the Agent Skill, the `SessionStart` hook, and\nMCP server registration, where MCP is the Model Context Protocol) are installed by your agent,\nnot by hand. Ask it:\n\n> Run `superbee setup` and follow its instructions.\n\nSetup itself changes nothing. It inspects your configuration and returns one safe next command at\na time, and the agent runs each with your approval. Setup knows Claude Code, Codex, and OpenCode,\nplus Claude Desktop for the MCP registration only.\n\n## Everyday use\n\nYou rarely type Superbee commands yourself. You ask your agent, and the Agent Skill translates the\nrequest into CLI calls:\n\n- \"Set up a Superbee bundle for this project and track our tasks in it.\"\n- \"Write up what we decided about the auth design as a doc, and link it to the task.\"\n- \"What did the last session leave off on? Check the context notes.\"\n- \"Sync the board so my teammate's agent sees this.\"\n- \"Give me a view of the open tasks grouped by owner.\"\n\nBehind those requests the agent uses a small set of commands: `init --dir .superbee` creates the\nbundle, `new` creates a document of a declared kind, `doc write` writes a free-form one,\n`doc update` changes a document, `link add` connects two, `list` and `doc read` query them, and\n`sync` shares the board. `superbee --help` lists the commands, and `superbee <command> --help`\ngives each one's full reference.\n\nThe two commands meant for you are the ones that show you the knowledge:\n\n```sh\nsuperbee ui --open # the whole bundle, rendered in your browser\nsuperbee doc open <id> # one document, by an id from `superbee list`\n```\n\n## Upgrading from aslite\n\nIf you installed the earlier `@holaxis/aslite` package or its marketplace plugin: install\n`superbee` alongside it, have your agent run `superbee setup` to migrate the integrations, then\nrun `npm uninstall -g @holaxis/aslite`. Existing `.agentstate-lite/` bundles and\n`.agentstate.json` bindings keep working with no migration.\n\n## Learn more\n\nThe [repository](https://github.com/Holaxis-ai/superbee) holds the source, the\n[CLI contract](https://github.com/Holaxis-ai/superbee/blob/main/packages/superbee/AXI-CONTRACT.md),\nand the [wire protocol](https://github.com/Holaxis-ai/superbee/blob/main/docs/WIRE-PROTOCOL.md).\n\n## License\n\nApache-2.0 © 2026 Holaxis\n",
87
90
  "readmeFilename": "README.md"
88
91
  }
@@ -1,190 +1,98 @@
1
1
  ---
2
2
  type: Reference
3
- title: Bundle View authoring — shared web and MCP contract
3
+ title: Bundle View authoring
4
4
  protocol: v0+v1
5
- timestamp: "2026-07-22T00:00:00.000Z"
5
+ timestamp: "2026-09-15T00:00:00.000Z"
6
6
  ---
7
7
 
8
- # Bundle View authoring — shared web and MCP contract
8
+ # Bundle View authoring
9
9
 
10
- Author **one durable View** for both local web and MCP hosts: a self-contained, responsive HTML
11
- blob under `views/…` plus a `type: View` registry doc under `views-registry/…`. Both hosts launch
12
- the same registry id, exact HTML bytes, access declaration, and bridge contract. The host chooses
13
- the available size and may offer expansion; do not create separate inline, expanded, web, or MCP
14
- implementations.
10
+ Author **one durable View** for every host: a self-contained, responsive HTML blob under `views/...`
11
+ plus a `type: View` registry doc under `views-registry/...`. The local web shell, the MCP host, a
12
+ published Portal artifact and the hosted workspace all launch the same registry id, exact HTML
13
+ bytes, access declaration and bridge contract. The host chooses the available size and may offer
14
+ expansion; do not create separate inline, expanded, web or MCP implementations.
15
15
 
16
- Use the bridge for bundle data and `render-document` for canonical Markdown presentation. Style
17
- the returned inert fragment inside the View; do not ship another Markdown parser. The sections
18
- below are the exact protocol contract and copy-paste client. This contract travels with portable
16
+ The protocol a View speaks is owned by one document in the Superbee repository:
17
+ `docs/VIEW-PROTOCOL.md` (https://github.com/Holaxis-ai/superbee/blob/main/docs/VIEW-PROTOCOL.md).
18
+ It holds the exact message shapes, the `field` filter grammar, what `open` means, the host
19
+ descriptor and capability registry, conformance levels, limits and the error table. This reference
20
+ is the short bundle-installed companion: enough to build a View from a bundle, with a copy of the
21
+ reference client. When the two disagree, the protocol document wins. It travels with portable
19
22
  View-bearing recipes, so authoring does not depend on an agent-harness skill.
20
23
 
21
24
  Legacy `Page` and `bridge` are retired authoring names. Use `type: View` and `access`; `superbee status`
22
25
  reports legacy content that needs migration. Legacy wire names such as `open-page` remain stable.
23
26
 
24
- ## Trust model (exact-byte approval + no credential)
25
-
26
- The `ui` server serves two privilege tiers on one loopback origin:
27
-
28
- - **Data API** (`/v0/*`): reachable ONLY with the shell's per-run session token/cookie.
29
- - **View bytes** (`/__page/<nonce>`): a view's static HTML, served for a short-lived **nonce**
30
- the session-authed shell mints (`POST /__page/mint`) for that view's one blob key. The nonce
31
- is not the session token, so it is rejected by every data route; the session token does not
32
- open the page route to arbitrary keys.
33
-
34
- The iframe is `sandbox="allow-scripts"` with **no** `allow-same-origin`, so the view runs at an
35
- **opaque origin**. A strict per-view CSP (`connect-src 'none'`) blocks ordinary direct network APIs
36
- such as fetch, XHR, WebSocket, and EventSource, while the View never receives the shell's credential
37
- or a data endpoint. Those controls are defense-in-depth: a data-bearing View is executable code,
38
- and approving its exact bytes and declared access is the decision to trust that code. Approve only
39
- a View whose source or author you trust; changed bytes or expanded access ask again. The supported
40
- bundle-data channel is `postMessage` to the shell, whose stable v0 bridge is read-only. A View that
41
- declares `bundle-propose` may additionally ask trusted shell chrome to prepare one v1 scalar-field
42
- action; only the human's shell-native Apply choice authorizes the CAS write.
43
-
44
- ## Message shapes
45
-
46
- Every message carries `bridge: "v0"`. A request carries an `id`; the reply echoes it as
47
- `"<type>:result"` (or `"error"`). The shell drops any message whose `event.source` is not the
48
- view's own iframe; the view drops any message whose `event.source` is not `window.parent`.
49
-
50
- ### View → shell (requests)
51
-
52
- | type | payload | reply `result` |
53
- | ----------- | ---------------------------------------------------------- | ---------------------------------------------------------- |
54
- | `hello` | — | `{ bundle: { root, name }, mode, protocol: "v0", grant }` |
55
- | `query` | `{ params: { type?, prefix?, field?, open?, limit? } }` | `{ rows: DocHead[], count }` |
56
- | `read` | `{ docId }` | `{ id, frontmatter, body }` |
57
- | `render-document` | `{ docId }` | `{ document: { id, version }, html, bounded }` |
58
- | `edges` | `{ params: { from?, to?, text? } }` | `{ edges: { from, to, text }[], count }` |
59
- | `subscribe` | — | `{ ok: true }`, then a stream of `change` events |
60
- | `open-page` | `{ pageId: "views-registry/…" }` | none; fire-and-forget shell navigation |
61
-
62
- `hello.result.grant` is `"read"` for `bundle-read` and `"propose"` for `bundle-propose`.
63
-
64
- `open-page` is the sole capability-independent action: `access: none`, `access: bundle-read`, and
65
- `access: bundle-propose` Views may ask the shell to open another usable registered View. The shell
66
- accepts only a conservative `views-registry/…` (or legacy-location `pages-registry/…`) concept
67
- id, validates that it resolves to a `type: View` doc with a safe `views/…`
68
- (or legacy-location `pages/…`) entry, and mounts the target normally with its own sandbox, nonce, and
69
- bridge capability. It returns no target body, frontmatter, entry, HTML, or nonce. A failed
70
- attempt can reveal that one caller-supplied registry id is not usable; this bounded existence
71
- oracle is the only information exposed by navigation.
72
-
73
- `DocHead` is `{ id, version, frontmatter }` — the same **head projection** `list` uses (full
74
- frontmatter, never a body). `query` params:
75
-
76
- `render-document` reads the canonical document and serializes its body with the shell's shared,
77
- bounded Markdown renderer. The returned `html` is inert semantic markup: it contains no scripts,
78
- event handlers, forms, controls, images, or navigable anchors. Internal concept links become
79
- passive elements carrying `data-aslite-doc-id`; the View may delegate clicks on those markers to
80
- its own selection logic and issue another `render-document` request. Insert only the unmodified
81
- `html` returned by this request. The accompanying document `version` is the exact version rendered;
82
- after a matching `change` event, refetch instead of treating old HTML as current. `bounded: true`
83
- means renderer safety limits truncated or collapsed part of the input.
84
-
85
- - `type` / `prefix` — server-side facets (a bundle-relative id prefix, a frontmatter `type`).
86
- - `field` — a client-side `key=value` filter; comma-separated values are OR (`progress_status=todo,blocked`).
87
- Scalar and array-valued fields use the same string-coerced membership rule as CLI `list`.
88
- - `open` — drop terminal rows, derived from the BUNDLE'S OWN kind conventions exactly like
89
- `list --open`: a row is dropped iff the convention governing its `type` declares the row's
90
- current field value(s) terminal (`fields.terminal`, e.g. the Task kind's `done`/`canceled`).
91
- A row with no governing kind is kept; a bundle where no kind declares a terminal set filters
92
- nothing. (The shell loads the registry once per change from the server, which builds it with
93
- core's `loadKinds` — one registry, no bridge-side schema.)
94
- - `limit` — a positive number caps `rows`; `0` or absence is unlimited. `count` remains the total
95
- matched after `field`/`open` filtering and before the cap, matching CLI `list`.
96
-
97
- `edges` is the general graph query — the ONE primitive every edge-shaped question reduces to
98
- (the same `queryEdges` atom `link list` is a CLI face over). `params`:
99
-
100
- - `from` / `to` — each one exact nonblank concept id, a bundle-relative `prefix/` (trailing
101
- slash), or an array of 1–32 such strings (union within the facet; giving both ANDs them). Omit
102
- the property for "no restriction". Supplied empty/all-whitespace strings, empty arrays,
103
- blank/non-string array entries, and arrays above 32 are invalid. Every string is preserved
104
- byte-for-byte and may be at most 1,024 UTF-8 bytes; duplicate entries still count toward 32.
105
- - `text` — one exact nonblank link-display string (never substring/regex), preserved byte-for-byte
106
- and at most 1,024 UTF-8 bytes; an empty/all-whitespace value is invalid.
107
-
108
- Backlinks are `edges({ to: docId })`; a container's contents are `edges({ from: itemId, text:
109
- "contains" })` (or whatever link text a bundle's convention uses) — there is no separate
110
- backlinks-only bridge call. A source linking to the same target twice with different text yields
111
- two rows (no dedup), matching `queryEdges`'s own granularity.
112
-
113
- ### Shell → view (server-initiated)
114
-
115
- | type | payload |
116
- | -------- | --------------------------------------------------- |
117
- | `change` | `{ event: { changes: [{ id, version }], removed: [id] } }` |
118
-
119
- `change` is pushed only to a view that has `subscribe`d. It is a **delta signal** — refetch with
120
- `query` against it rather than trusting it as a full state. Removed ids have been deleted.
121
-
122
- For live data views, prefer `Bridge.watch(refresh)` over assembling the startup sequence yourself.
123
- It subscribes before the first snapshot, passes an ordered batch of raw `change` event payloads to
124
- each refresh, and never overlaps refresh calls. Events arriving during a refresh are coalesced into
125
- one follow-up batch. A failed refresh does not poison later event-driven refreshes; `watch` does not
126
- retry on a timer. Its returned Promise covers subscription plus the first refresh, so handle that
127
- Promise to surface startup failures. Raw `subscribe` remains available when a view needs the
128
- lower-level event stream.
129
-
130
- **There are no mutation messages in v0.** Read-only is enforced *by construction*: the shell
131
- defines no write/delete/update handler, so any such request returns an `error` reply.
132
-
133
- ### Trusted action bridge v1
134
-
135
- `access: bundle-propose` includes the v0 read surface and adds two exact v1 requests:
136
-
137
- - `{ bridge: "v1", type: "read-versioned", id, docId }` returns one canonical document and the
138
- version from the same read.
139
- - `{ bridge: "v1", type: "action.propose", requestId, action: { kind:
140
- "document.set-field", docId, field, value, expectedVersion } }` proposes changing one declared
141
- scalar field on an existing governed document.
142
-
143
- The shell independently re-reads the View registry, exact HTML version, target document, and Kind;
144
- shows canonical before/after values outside the iframe; and commits only after the human chooses
145
- Apply. The approval token and immutable launch identity never enter the iframe. A stale target is a
146
- visible conflict and is never retried behind the human's back. V1 is local `--dir` only and excludes
147
- body writes, links, creation, deletion, remote writes, and persistent grants. Start the shell with
148
- `superbee ui --actor <name>` (or set `SUPERBEE_ACTOR`; `AGENTSTATE_LITE_ACTOR` remains a
149
- supported compatibility input) to enable proposals.
150
-
151
- ## Live updates
152
-
153
- The shell (only) holds one `EventSource('/events')`. The server watches the bundle — `fs.watch`
154
- in `--dir` mode, a poll in `--remote` mode — diffs content-addressed **version tokens**, and pushes
155
- a change delta. The shell fans doc changes into subscribed views as `change` events, and
156
- **hot-reloads** a view's iframe (with a fresh nonce) when the view's own HTML blob changes. (Remote
157
- view-blob hot-reload is a labeled follow-up; live doc updates work in both modes.)
158
-
159
- ## `access` — the enforced data/content split
160
-
161
- The registry doc's `access` field decides whether the shell will answer THIS view's bridge
162
- requests at all — and the shell, not the view, is what enforces it:
163
-
164
- - `access: bundle-read` — a **data view**. The shell answers `hello`/`query`/`read`/
165
- `render-document`/`edges`/`subscribe` as described above.
166
- - `access: bundle-propose` — an **interactive view**. It receives the same read surface and may
167
- submit the narrow v1 proposal above. Each proposal still requires trusted-shell confirmation.
168
- - `access: none` — a **content view**. The shell replies to every bundle-data request with a
169
- `FORBIDDEN` error, before touching any bundle data. It may still use `open-page` navigation.
170
- - `bridge` is the legacy spelling of this field, and it is no longer read: a doc declaring only
171
- the legacy `bridge` field resolves to `access: none` (every bundle-data request is denied).
172
- The repo's `migrate-legacy-view-names` script renames leftover legacy `bridge` fields to
173
- `access` in place, and `superbee status` lists them under its `legacy_naming` finding.
174
- Authoring uses `access`.
175
- - The `View` convention declares `access` REQUIRED — every view is an intentional
176
- classification, not a silent default. At runtime the shell still fails closed for a doc this
177
- convention didn't govern (an external bundle, a hand-edited file that skipped the lint): absent,
178
- malformed, or any other value is treated as `access: none`. A view only gets bundle access by
179
- declaring exactly `bundle-read` or `bundle-propose`.
180
-
181
- The launcher groups views by this same field: "Dashboards" for `bundle-read`, "Interactive" for
27
+ ## Trust model
28
+
29
+ The View runs in an opaque-origin, script-only sandbox with `connect-src 'none'`. It never receives
30
+ a credential, session token or data endpoint; its only channel to bundle data is `postMessage` to
31
+ the shell, which validates every request before touching bundle data. Approving a View means
32
+ approving its exact bytes and declared access; changed bytes or expanded access ask again. Approve
33
+ only a View whose source or author you trust. A View that declares `bundle-propose` may ask the
34
+ trusted shell to prepare one v1 scalar-field action; only the human's shell-native Apply choice
35
+ authorizes the write.
36
+
37
+ ## The requests
38
+
39
+ Every request carries `bridge: "v0"` (or `"v1"` for `read-versioned` and `action.propose`), an
40
+ `id`, and a `type`; the reply echoes the id as `"<type>:result"` or `"error"` with a code. The
41
+ client below wraps all of them.
42
+
43
+ | request | ask | answer |
44
+ | --- | --- | --- |
45
+ | `hello` | who is hosting me | `{ bundle: { root, name }, mode, protocol, grant, host: { kind, capabilities, limits } }` |
46
+ | `query` | `{ type?, prefix?, field?, open?, limit? }` | `{ rows: [{ id, version, frontmatter }], count }` |
47
+ | `read` | `docId` | `{ id, frontmatter, body }` |
48
+ | `read-versioned` | `docId` | `{ doc, version }` |
49
+ | `render-document` | `docId` | `{ document: { id, version }, html, bounded }` |
50
+ | `edges` | `{ from?, to?, text? }` | `{ edges: [{ from, to, text }], count }` |
51
+ | `graph` | `includeBodies?` | `{ okfVersion, documents, relationships, counts }` |
52
+ | `subscribe` | none | `{ ok: true }`, then `change` events |
53
+ | `host` | `capability, input?` | `{ capability, output }` or `FORBIDDEN` |
54
+ | `open-page` | `views-registry/...` id | none; fire-and-forget shell navigation |
55
+
56
+ `hello.result.grant` is `"read"` for `bundle-read` and `"propose"` for `bundle-propose`. Read
57
+ `hello.result.host.capabilities` to learn what this host honors (for example `query.field-or`,
58
+ `query.open`, `edges`, `graph`, `subscribe-deltas`) instead of assuming; every host refuses what it
59
+ does not offer with a `FORBIDDEN` error, never silently.
60
+
61
+ Use `render-document` for canonical Markdown presentation: the returned `html` is inert markup
62
+ whose internal links carry `data-aslite-doc-id`. Style it inside the View and insert it unmodified;
63
+ do not ship another Markdown parser.
64
+
65
+ `change` events are a signal to re-query, never full state. `Bridge.watch(refresh)` subscribes
66
+ before the first snapshot, batches events, never overlaps refreshes, and works the same on a host
67
+ that pushes real deltas and on one that only nudges.
68
+
69
+ ## `access`
70
+
71
+ The registry doc's `access` field decides whether the shell answers this View's bridge requests at
72
+ all, and the shell, not the View, enforces it:
73
+
74
+ - `access: bundle-read`: a **data view**. The read requests above are answered.
75
+ - `access: bundle-propose`: an **interactive view**. The same reads plus the narrow v1 proposal,
76
+ each proposal confirmed in trusted shell chrome. Start the shell with `superbee ui --actor <name>`
77
+ (or set `SUPERBEE_ACTOR`; `AGENTSTATE_LITE_ACTOR` remains a supported compatibility input) to
78
+ enable proposals.
79
+ - `access: none`: a **content view**. Every bundle-data request answers `FORBIDDEN` before any
80
+ bundle data is touched. It may still use `open-page` navigation.
81
+ - `bridge` is the legacy spelling of this field and is no longer read: a doc declaring only the
82
+ legacy `bridge` field resolves to `access: none`. The repo's `migrate-legacy-view-names` script
83
+ renames leftover legacy `bridge` fields to `access` in place, and `superbee status` lists them
84
+ under its `legacy_naming` finding.
85
+ - The `View` convention declares `access` REQUIRED. At runtime the shell still fails closed for a
86
+ doc the convention did not govern: absent, malformed or any other value is treated as
87
+ `access: none`.
88
+
89
+ The launcher groups Views by this field: "Dashboards" for `bundle-read`, "Interactive" for
182
90
  `bundle-propose`, and "Documents" for `none`.
183
91
 
184
92
  ## Authoring a view
185
93
 
186
94
  Start from a working installed View when possible, then adapt it responsively for the space the
187
- host provides. Keep data selection bounded and show empty, partial, over-limit, and unavailable
95
+ host provides. Keep data selection bounded and show empty, partial, over-limit and unavailable
188
96
  states.
189
97
 
190
98
  ```sh
@@ -192,7 +100,7 @@ superbee blobs --prefix views/
192
100
  superbee pull --doc-key views/review-workflow/reviews.html --out my-view.html
193
101
  ```
194
102
 
195
- Keep HTML, CSS, and JavaScript self-contained with no external hosts. A data View embeds the bridge
103
+ Keep HTML, CSS and JavaScript self-contained with no external hosts. A data View embeds the bridge
196
104
  client below. A content View (`access: none`) may use only `openPage`; bundle-data calls return
197
105
  `FORBIDDEN`.
198
106
 
@@ -215,23 +123,21 @@ recipe or promote the supplied `conventions/view.md` once before creating the re
215
123
 
216
124
  Verify the same registered id in both surfaces: open it with `superbee ui`, then have an MCP-capable
217
125
  desktop list and show that View. Confirm narrow and expanded layouts without changing the source.
218
-
219
- The seed views here are working examples: `pulse.html`/`roadmap.html` are `access: bundle-read`
220
- data views — `roadmap.html` is the one that exercises the `edges` request end-to-end (a live graph
221
- view of Roadmap Items and the tasks each one `contains`) — and `about.html` is an `access: none`
222
- content view (no bridge calls at all). `demo.sh` (repo only) wires all of this over a scratch copy
223
- of this repo's own board.
126
+ Startup messages are optional: a View may stay quiet until human input and never has to send
127
+ `hello` to prove it loaded.
224
128
 
225
129
  ## The bridge client (embedded copy)
226
130
 
131
+ A byte-for-byte copy of the reference client in `docs/VIEW-PROTOCOL.md`.
132
+
227
133
  ```js
228
134
  (function () {
229
- var PROTO = "v0", seq = 0, pending = {}, subs = [];
230
- function send(type, extra) {
135
+ var PROTO = "v0", ACTION_PROTO = "v1", seq = 0, pending = {}, subs = [];
136
+ function send(type, extra, proto) {
231
137
  return new Promise(function (resolve, reject) {
232
138
  var id = String(++seq);
233
139
  pending[id] = { resolve: resolve, reject: reject };
234
- var msg = { bridge: PROTO, id: id, type: type };
140
+ var msg = { bridge: proto || PROTO, id: id, type: type };
235
141
  if (extra) for (var k in extra) msg[k] = extra[k];
236
142
  parent.postMessage(msg, "*"); // parent origin is opaque to us; the shell validates by source
237
143
  });
@@ -274,20 +180,28 @@ of this repo's own board.
274
180
  window.addEventListener("message", function (e) {
275
181
  if (e.source !== window.parent) return; // only trust the shell
276
182
  var m = e.data;
277
- if (!m || m.bridge !== PROTO) return;
183
+ if (!m || (m.bridge !== PROTO && m.bridge !== ACTION_PROTO)) return;
278
184
  if (m.type === "change") { subs.forEach(function (cb) { cb(m.event); }); return; }
279
185
  var p = pending[m.id];
280
186
  if (!p) return;
281
187
  delete pending[m.id];
282
- if (m.type === "error") p.reject(new Error((m.error && m.error.message) || "bridge error"));
283
- else p.resolve(m.result);
188
+ if (m.type === "error") {
189
+ var err = new Error((m.error && m.error.message) || "bridge error");
190
+ err.code = m.error && m.error.code; // one of USAGE, FORBIDDEN, REVOKED, TOO_LARGE, RUNTIME, NOT_FOUND
191
+ p.reject(err);
192
+ } else p.resolve(m.result);
284
193
  });
285
194
  window.Bridge = {
286
195
  hello: function () { return send("hello"); },
287
196
  query: function (params) { return send("query", { params: params }); },
288
197
  read: function (docId) { return send("read", { docId: docId }); },
198
+ readVersioned: function (docId) { return send("read-versioned", { docId: docId }, ACTION_PROTO); },
289
199
  renderDocument: function (docId) { return send("render-document", { docId: docId }); },
290
200
  edges: function (params) { return send("edges", { params: params }); },
201
+ graph: function (includeBodies) { return send("graph", includeBodies === undefined ? undefined : { includeBodies: includeBodies === true }); },
202
+ host: function (capability, input) {
203
+ return send("host", input === undefined ? { capability: capability } : { capability: capability, input: input });
204
+ },
291
205
  openPage: openPage,
292
206
  subscribe: function (cb) { subs.push(cb); return send("subscribe"); },
293
207
  watch: watch
@@ -308,12 +222,6 @@ documentPanel.addEventListener("click", function (event) {
308
222
  });
309
223
  ```
310
224
 
311
- ```css
312
- .document-panel [data-aslite-rendered-document] { line-height: 1.6; }
313
- .document-panel h1 { font: 600 1.5rem/1.2 system-ui; }
314
- .document-panel [data-aslite-doc-id] { cursor: pointer; text-decoration: underline; }
315
- ```
316
-
317
225
  A live view supplies only its domain snapshot and render work:
318
226
 
319
227
  ```js
@@ -323,20 +231,7 @@ Bridge.watch(async function (events) {
323
231
  }).catch(showStartupError);
324
232
  ```
325
233
 
326
- ## Quiet startup and transport readiness
327
-
328
- Startup messages are optional. A View may render static content or remain quiet until human input;
329
- it does not have to send `hello`, subscribe, or make any other bridge request merely to prove that
330
- it loaded.
331
-
332
- The local web shell may use a shell-authenticated transport receipt after the iframe load event to
333
- confirm that the nonce response reached the host's completed-response boundary. That receipt stays
334
- outside the iframe and is **not authorization**: it grants no bridge or trusted-action access, and
335
- each data or action request still undergoes its own launch-currentness, capability, and exact-byte
336
- approval checks.
337
-
338
- The receipt proves transport completion, not pixels or script execution. With exact authored bytes
339
- and an opaque-origin iframe, browser cancellation after the response reaches the host's completion
340
- boundary may remain indistinguishable from successful delivery. The shell's bounded load diagnostic
341
- therefore cannot identify every response-stage failure without authored cooperation or a different
342
- isolation contract.
234
+ The seed views shipped beside this reference are working examples: `pulse.html` and `roadmap.html`
235
+ are `access: bundle-read` data views (`roadmap.html` exercises `edges` end to end), `about.html` is
236
+ an `access: none` content view, and `conformance/` is the fixture that exercises every request type
237
+ and reports one row per type.