superbee 0.1.3 → 0.1.5-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/README.md +31 -10
- package/SKILL.md +4 -2
- package/dist/publication/bridge-entry.d.ts +5 -0
- package/dist/publication/bridge.d.ts +9 -0
- package/dist/publication/canonical-json.d.ts +3 -0
- package/dist/publication/capture.d.ts +4 -0
- package/dist/publication/errors.d.ts +22 -0
- package/dist/publication/generated/publication-snapshot-v1.d.ts +125 -0
- package/dist/publication/index.d.ts +7 -0
- package/dist/publication/schema/publication-snapshot-v1.schema.json +146 -0
- package/dist/publication/schema.d.ts +3 -0
- package/dist/publication/snapshot-backend.d.ts +33 -0
- package/dist/publication/types.d.ts +44 -0
- package/dist/publication-bridge.mjs +6222 -0
- package/dist/publication.mjs +44125 -0
- package/dist/superbee.mjs +3621 -1352
- package/package.json +19 -7
- package/references/views/about.html +30 -13
- package/references/views/pulse.html +69 -43
- package/references/views/roadmap.html +48 -33
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "superbee",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5-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": [
|
|
@@ -24,6 +24,17 @@
|
|
|
24
24
|
"bin": {
|
|
25
25
|
"superbee": "dist/superbee.mjs"
|
|
26
26
|
},
|
|
27
|
+
"exports": {
|
|
28
|
+
".": "./dist/superbee.mjs",
|
|
29
|
+
"./publication": {
|
|
30
|
+
"types": "./dist/publication/index.d.ts",
|
|
31
|
+
"default": "./dist/publication.mjs"
|
|
32
|
+
},
|
|
33
|
+
"./publication/bridge": {
|
|
34
|
+
"types": "./dist/publication/bridge-entry.d.ts",
|
|
35
|
+
"default": "./dist/publication-bridge.mjs"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
27
38
|
"files": [
|
|
28
39
|
"dist",
|
|
29
40
|
"SKILL.md",
|
|
@@ -36,16 +47,14 @@
|
|
|
36
47
|
"engines": {
|
|
37
48
|
"node": ">=20"
|
|
38
49
|
},
|
|
39
|
-
"os": [
|
|
40
|
-
"!win32"
|
|
41
|
-
],
|
|
42
50
|
"scripts": {
|
|
43
51
|
"build": "node build.mjs local-dev",
|
|
44
52
|
"build:npm-package": "node build.mjs npm-package",
|
|
45
53
|
"typecheck": "tsc --noEmit",
|
|
46
54
|
"pretest": "node build.mjs local-dev",
|
|
47
|
-
"test": "
|
|
48
|
-
"
|
|
55
|
+
"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",
|
|
56
|
+
"test": "node scripts/run-test-command.mjs node --test --import ./test/ts-loader.mjs ./test/*.test.ts",
|
|
57
|
+
"mutation": "node scripts/run-test-command.mjs npm-exec stryker run",
|
|
49
58
|
"gen:skill": "node scripts/gen-skill.mjs",
|
|
50
59
|
"check:skill": "node scripts/gen-skill.mjs --check",
|
|
51
60
|
"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)\""
|
|
@@ -56,6 +65,7 @@
|
|
|
56
65
|
"@superbee/core": "*",
|
|
57
66
|
"@superbee/markdown-renderer": "*",
|
|
58
67
|
"@superbee/mcp-app": "*",
|
|
68
|
+
"@superbee/publication": "*",
|
|
59
69
|
"@superbee/server": "*",
|
|
60
70
|
"@superbee/ui-server": "*",
|
|
61
71
|
"@toon-format/toon": "2.3.0",
|
|
@@ -65,5 +75,7 @@
|
|
|
65
75
|
"jsonc-parser": "3.3.1",
|
|
66
76
|
"pako": "2.1.0",
|
|
67
77
|
"typescript": "^5.4.0"
|
|
68
|
-
}
|
|
78
|
+
},
|
|
79
|
+
"readme": "# superbee\n\n## What is Superbee?\n\nSuperbee gives AI coding agents shared, versioned, conflict-safe memory — as a folder of\nplain markdown in your repo.\n\nAgents forget everything between sessions, overwrite each other's work, and keep what they\nknow invisible to the humans they work for. Superbee fixes all three:\n\n- **Memory that persists.** Agents write context notes, decisions, plans, and research into a\n knowledge bundle that survives the session. The next session — or a different agent — picks\n up exactly where the last one left off. An optional `SessionStart` hook (Claude Code, Codex,\n OpenCode) orients every new session automatically.\n- **Safe for many writers.** Every document write is compare-and-swap versioned and attributed\n to an actor. Two agents racing on the same document get a clean, typed conflict instead of a\n silent lost update — and `doc history` shows who changed what, when.\n- **Visible to humans.** Everything is plain markdown you can open in any editor, render on\n GitHub, and diff in git. `superbee ui` serves the bundle locally as rendered, cross-linked\n pages with derived backlinks, a live activity feed, and launchable bundle Views. `superbee\n sync` shares the bundle with teammates on a dedicated `board` branch — pulling their changes\n and pushing yours without touching your code.\n- **Views on demand.** Ask your agent to create whatever representation you need and Superbee will\n create it: a self-contained HTML View, registered in the bundle as a typed document, that\n `superbee ui` launches in a sandboxed iframe. A reading surface for one dense document, a board, a\n timeline, a filtered queue, a chart, a dashboard — the shape follows the question rather than a\n fixed set of built-in screens, and a view worth keeping stays. A data View reads live bundle\n content through a narrow read-only bridge and refreshes as documents change. Views are bundle\n content, so they travel with `sync` and open the same way for a teammate's agent.\n- **Agent-native by design.** The CLI follows the AXI principles for agent-facing tools:\n structured, token-lean output; result counts and truncation with explicit escape hatches;\n idempotent mutations; structured errors with a small, stable exit-code taxonomy. Agents get\n predictable responses they can act on without parsing prose or flooding their context window.\n- **Yours, and portable.** Bundles conform to the Open Knowledge Format — new bundles are\n written as OKF v0.2, and existing v0.1 bundles stay supported in place — so they survive the\n tool: hand the folder to someone else, or read it with anything that speaks markdown.\n Everything works offline; the filesystem is the source of truth. Typed document schemas\n (\"kinds\") live in the bundle itself, so the bundle describes its own structure.\n\nThe npm package ships one self-contained executable with zero runtime dependencies, plus an\nAgent Skill that teaches agents how to use it.\n\n## How do I download Superbee on Windows?\n\n**Requirements: Node.js 20 or newer on macOS, Linux, or native Windows.** You do not need WSL,\nUbuntu, or Docker. On Windows, Superbee keeps per-user operational state under\n`%LOCALAPPDATA%\\Superbee`; npm installs the command as `superbee.cmd`.\n\nSuperbee currently has two npm release channels:\n\n- `latest` is the stable channel selected by bare `superbee`. Its current release predates native\n Windows support.\n- `next` is the prerelease channel. It contains the current native-Windows build.\n\nInstall the current prerelease on Windows:\n\n```powershell\nnpm install -g superbee@next\nsuperbee.cmd setup\n```\n\nOn macOS or Linux, the stable channel remains available with `npm install -g superbee`. To test the\nsame prerelease as Windows, install `superbee@next` instead.\n\nAfter installation, ask your AI agent to run `superbee setup` (`superbee.cmd setup` when invoking\nthe Windows shim explicitly). Setup walks the agent through Agent Skill, SessionStart hook, and MCP\nregistration. It is read-only: it inspects your configuration and returns one safe next command at\na time, so the agent performs any actual changes with your approval.\n\nUpgrading from the legacy `@holaxis/aslite` package or the retired marketplace plugin? Install\n`superbee` alongside it, have your agent run `superbee setup` to migrate the exact legacy\nintegrations, then remove the old package with `npm uninstall -g @holaxis/aslite`. Existing\n`.agentstate-lite/` bundles and `.agentstate.json` bindings keep working with no migration.\n\n## How to use Superbee\n\nSuperbee is agent-first: you don't type its commands yourself — you ask your agent for what\nyou need, and the Agent Skill included with this package helps the agent translate your\ninstructions into CLI commands. For example:\n\n- \"Set up a Superbee workspace 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 drives a small, predictable CLI: `init` creates a bundle in a\nconventional `.superbee/` folder (discovered automatically, the way git finds `.git`); `new`,\n`doc write`, `doc update`, and `link add` create and connect typed documents; `list` and\n`doc read` query them; `sync` shares the board with teammates.\n\nWhen you want to see the knowledge yourself, ask the agent to open it — or run the two\nhuman-facing commands directly:\n\n```sh\nsuperbee ui --open # the bundle, rendered: pages, links, backlinks, live Views\nsuperbee doc open <id> # one exact document in the same local browser reader\n```\n\nRun `superbee --help` (or any subcommand with `--help`) for the full command reference.\nDesign and format docs live in the [repository](https://github.com/Holaxis-ai/superbee).\n\n## License\n\nApache-2.0 © 2026 Holaxis\n",
|
|
80
|
+
"readmeFilename": "README.md"
|
|
69
81
|
}
|
|
@@ -5,44 +5,61 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
6
|
<title>About this bundle</title>
|
|
7
7
|
<style>
|
|
8
|
+
/* Superbee View theme — mirrors the launcher shell, so a View framed inside it reads as
|
|
9
|
+
one surface rather than a foreign document.
|
|
10
|
+
|
|
11
|
+
TWO accent roles, not three. --structure carries structure AND state: "active" is the
|
|
12
|
+
same hue at full intensity, never a second colour, because hue should carry kind and
|
|
13
|
+
intensity should carry state. --signal carries liveness and the revealed answer. There
|
|
14
|
+
is deliberately no teal. Quiet metadata takes --slate, not an accent.
|
|
15
|
+
|
|
16
|
+
Fonts: a View is sandboxed under `font-src data:`, so it CANNOT load the shell's
|
|
17
|
+
self-hosted woff2 by URL. The brand faces are named first and resolve for anyone who
|
|
18
|
+
has them installed locally; the stacks behind them are the real fallback. Do not embed
|
|
19
|
+
a data: font — that is ~100KB in every View for a marginal gain. */
|
|
8
20
|
:root {
|
|
9
|
-
--bg
|
|
10
|
-
--
|
|
11
|
-
--
|
|
21
|
+
--bg:#F3F7FA; --card:#FFFFFF; --alt:#E9EFF4; --rule:#DADEE2;
|
|
22
|
+
--ink:#0F1A24; --slate:#4A5D6E; --ghost:#9AAAB8;
|
|
23
|
+
--structure:#0073B0; --signal:#956300; --danger:#B00020;
|
|
24
|
+
--radius:2px;
|
|
25
|
+
--display:"Space Grotesk", system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
26
|
+
--sans:"DM Sans", -apple-system, "Segoe UI", system-ui, sans-serif;
|
|
27
|
+
--mono:"JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
|
|
12
28
|
}
|
|
13
29
|
@media (prefers-color-scheme: dark) {
|
|
14
30
|
:root {
|
|
15
|
-
--bg
|
|
16
|
-
--
|
|
31
|
+
--bg:#0B1926; --card:#0F2A3F; --alt:#12314A; --rule:#26323D;
|
|
32
|
+
--ink:#F8F6F2; --slate:#B7C4D1; --ghost:#7E8FA0;
|
|
33
|
+
--structure:#3CAEF9; --signal:#E09707; --danger:#F2707A;
|
|
17
34
|
}
|
|
18
35
|
}
|
|
19
36
|
* { box-sizing: border-box; margin: 0; }
|
|
20
37
|
html, body { height: 100%; }
|
|
21
38
|
body {
|
|
22
|
-
font: 15px/1.6
|
|
39
|
+
font: 15px/1.6 var(--sans);
|
|
23
40
|
background: var(--bg); color: var(--ink);
|
|
24
41
|
}
|
|
25
42
|
main { max-width: 40rem; margin: 0 auto; padding: 2.5rem 1.5rem 4rem; }
|
|
26
|
-
h1 { font-size: 1.5rem; font-weight: 650; letter-spacing: -0.01em; margin-bottom: 0.4rem; }
|
|
43
|
+
h1 { font-family: var(--display); font-size: 1.5rem; font-weight: 650; letter-spacing: -0.01em; margin-bottom: 0.4rem; }
|
|
27
44
|
.kicker {
|
|
28
|
-
color: var(--
|
|
45
|
+
color: var(--structure); font-family: var(--mono); font-size: 0.8rem;
|
|
29
46
|
text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 0.6rem;
|
|
30
47
|
}
|
|
31
|
-
p { color: var(--
|
|
48
|
+
p { color: var(--slate); margin-bottom: 1rem; }
|
|
32
49
|
p strong { color: var(--ink); font-weight: 600; }
|
|
33
50
|
.card {
|
|
34
|
-
background: var(--
|
|
51
|
+
background: var(--card); border: 1px solid var(--rule); border-radius: 10px;
|
|
35
52
|
padding: 1rem 1.2rem; margin: 1.5rem 0;
|
|
36
53
|
}
|
|
37
54
|
.card h2 { font-size: 0.95rem; margin-bottom: 0.5rem; }
|
|
38
|
-
.card ul { margin: 0; padding-left: 1.2rem; color: var(--
|
|
55
|
+
.card ul { margin: 0; padding-left: 1.2rem; color: var(--slate); }
|
|
39
56
|
.card li { margin-bottom: 0.35rem; }
|
|
40
57
|
code {
|
|
41
|
-
font-family: var(--mono); background: var(--
|
|
58
|
+
font-family: var(--mono); background: var(--alt); color: var(--ink);
|
|
42
59
|
padding: 0.1rem 0.35rem; border-radius: 5px; font-size: 0.85em;
|
|
43
60
|
}
|
|
44
61
|
#toggle, #open-roadmap {
|
|
45
|
-
border: 1px solid var(--
|
|
62
|
+
border: 1px solid var(--rule); background: var(--card); color: var(--ink);
|
|
46
63
|
border-radius: 8px; padding: 0.4rem 0.9rem; font-size: 0.85rem; cursor: pointer;
|
|
47
64
|
}
|
|
48
65
|
#detail { display: none; margin-top: 0.75rem; }
|
|
@@ -5,106 +5,129 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
6
|
<title>Pulse</title>
|
|
7
7
|
<style>
|
|
8
|
+
/* Superbee View theme — mirrors the launcher shell, so a View framed inside it reads as
|
|
9
|
+
one surface rather than a foreign document.
|
|
10
|
+
|
|
11
|
+
TWO accent roles, not three. --structure carries structure AND state: "active" is the
|
|
12
|
+
same hue at full intensity, never a second colour, because hue should carry kind and
|
|
13
|
+
intensity should carry state. --signal carries liveness and the revealed answer. There
|
|
14
|
+
is deliberately no teal. Quiet metadata takes --slate, not an accent.
|
|
15
|
+
|
|
16
|
+
Fonts: a View is sandboxed under `font-src data:`, so it CANNOT load the shell's
|
|
17
|
+
self-hosted woff2 by URL. The brand faces are named first and resolve for anyone who
|
|
18
|
+
has them installed locally; the stacks behind them are the real fallback. Do not embed
|
|
19
|
+
a data: font — that is ~100KB in every View for a marginal gain. */
|
|
8
20
|
:root {
|
|
9
|
-
--bg
|
|
10
|
-
--
|
|
11
|
-
--
|
|
12
|
-
--
|
|
21
|
+
--bg:#F3F7FA; --card:#FFFFFF; --alt:#E9EFF4; --rule:#DADEE2;
|
|
22
|
+
--ink:#0F1A24; --slate:#4A5D6E; --ghost:#9AAAB8;
|
|
23
|
+
--structure:#0073B0; --signal:#956300; --danger:#B00020;
|
|
24
|
+
--radius:2px;
|
|
25
|
+
--display:"Space Grotesk", system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
26
|
+
--sans:"DM Sans", -apple-system, "Segoe UI", system-ui, sans-serif;
|
|
27
|
+
--mono:"JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
|
|
13
28
|
}
|
|
14
29
|
@media (prefers-color-scheme: dark) {
|
|
15
30
|
:root {
|
|
16
|
-
--bg
|
|
17
|
-
--
|
|
18
|
-
--
|
|
31
|
+
--bg:#0B1926; --card:#0F2A3F; --alt:#12314A; --rule:#26323D;
|
|
32
|
+
--ink:#F8F6F2; --slate:#B7C4D1; --ghost:#7E8FA0;
|
|
33
|
+
--structure:#3CAEF9; --signal:#E09707; --danger:#F2707A;
|
|
19
34
|
}
|
|
20
35
|
}
|
|
36
|
+
|
|
37
|
+
/* Functional status colours, NOT brand accents. The kit has no green; these exist so a
|
|
38
|
+
dashboard can say good/warning/bad, and they are deliberately kept out of the palette
|
|
39
|
+
vocabulary above so nobody mistakes them for brand colours. */
|
|
40
|
+
:root { --ok:#0F7B3F; --warn:#956300; --bad:#B00020; }
|
|
41
|
+
@media (prefers-color-scheme: dark) {
|
|
42
|
+
:root { --ok:#3FBF74; --warn:#E09707; --bad:#F2707A; }
|
|
43
|
+
}
|
|
21
44
|
* { box-sizing: border-box; margin: 0; }
|
|
22
45
|
html, body { height: 100%; }
|
|
23
46
|
body {
|
|
24
|
-
font: 14px/1.5
|
|
47
|
+
font: 14px/1.5 var(--sans);
|
|
25
48
|
background: var(--bg); color: var(--ink); display: flex; flex-direction: column;
|
|
26
49
|
}
|
|
27
50
|
header {
|
|
28
51
|
display: flex; align-items: center; gap: 10px; padding: 10px 16px;
|
|
29
|
-
border-bottom: 1px solid var(--
|
|
52
|
+
border-bottom: 1px solid var(--rule); background: var(--card); flex-wrap: wrap;
|
|
30
53
|
}
|
|
31
|
-
header h1 { font-size: 15px; font-weight: 650; letter-spacing: .01em; }
|
|
32
|
-
header .bundle { color: var(--
|
|
54
|
+
header h1 { font-family: var(--display); font-size: 15px; font-weight: 650; letter-spacing: .01em; }
|
|
55
|
+
header .bundle { color: var(--slate); font-size: 12px; font-family: var(--mono); }
|
|
33
56
|
#search {
|
|
34
|
-
margin-left: auto; background: var(--
|
|
57
|
+
margin-left: auto; background: var(--alt); border: 1px solid var(--rule); color: var(--ink);
|
|
35
58
|
border-radius: 8px; padding: 5px 10px; font-size: 13px; width: 200px; outline: none;
|
|
36
59
|
}
|
|
37
|
-
#search:focus { border-color: var(--
|
|
60
|
+
#search:focus { border-color: var(--structure); }
|
|
38
61
|
#follow {
|
|
39
|
-
border: 1px solid var(--
|
|
62
|
+
border: 1px solid var(--rule); background: var(--alt); color: var(--slate); border-radius: 999px;
|
|
40
63
|
padding: 5px 12px; font-size: 12px; cursor: pointer; user-select: none; white-space: nowrap;
|
|
41
64
|
}
|
|
42
|
-
#follow.on { background: var(--
|
|
65
|
+
#follow.on { background: var(--alt); color: var(--structure); border-color: var(--structure); }
|
|
43
66
|
#follow.on .dot { animation: blink 1.2s infinite; }
|
|
44
67
|
#follow .dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: currentColor; margin-right: 6px; }
|
|
45
68
|
@keyframes blink { 50% { opacity: .25; } }
|
|
46
|
-
#typebar { display: flex; gap: 6px; padding: 8px 16px; border-bottom: 1px solid var(--
|
|
69
|
+
#typebar { display: flex; gap: 6px; padding: 8px 16px; border-bottom: 1px solid var(--rule); overflow-x: auto; background: var(--card); }
|
|
47
70
|
.tchip {
|
|
48
|
-
font-size: 12px; padding: 3px 10px; border-radius: 999px; border: 1px solid var(--
|
|
49
|
-
background: var(--
|
|
71
|
+
font-size: 12px; padding: 3px 10px; border-radius: 999px; border: 1px solid var(--rule);
|
|
72
|
+
background: var(--alt); color: var(--slate); cursor: pointer; white-space: nowrap;
|
|
50
73
|
}
|
|
51
|
-
.tchip.on { background: var(--
|
|
74
|
+
.tchip.on { background: var(--alt); color: var(--structure); border-color: var(--structure); font-weight: 600; }
|
|
52
75
|
main { flex: 1; display: flex; min-height: 0; }
|
|
53
|
-
#feed { flex: 0 0 44%; max-width: 560px; overflow-y: auto; border-right: 1px solid var(--
|
|
76
|
+
#feed { flex: 0 0 44%; max-width: 560px; overflow-y: auto; border-right: 1px solid var(--rule); padding: 8px 0 40px; }
|
|
54
77
|
.group-label {
|
|
55
78
|
position: sticky; top: 0; z-index: 1; font-size: 11px; font-weight: 700; text-transform: uppercase;
|
|
56
|
-
letter-spacing: .08em; color: var(--
|
|
79
|
+
letter-spacing: .08em; color: var(--slate); background: var(--bg); padding: 10px 16px 4px;
|
|
57
80
|
}
|
|
58
81
|
.item {
|
|
59
82
|
display: block; width: 100%; text-align: left; border: 0; background: none; color: inherit; font: inherit;
|
|
60
83
|
padding: 9px 16px; cursor: pointer; border-left: 3px solid transparent;
|
|
61
84
|
}
|
|
62
|
-
.item:hover { background: var(--
|
|
63
|
-
.item.sel { background: var(--
|
|
85
|
+
.item:hover { background: var(--alt); }
|
|
86
|
+
.item.sel { background: var(--alt); border-left-color: var(--structure); }
|
|
64
87
|
.item.fresh { animation: land 1.6s ease-out; }
|
|
65
|
-
@keyframes land { 0% { background: var(--
|
|
88
|
+
@keyframes land { 0% { background: var(--alt); transform: translateX(-4px); } 100% { background: none; transform: none; } }
|
|
66
89
|
.item .row1 { display: flex; align-items: baseline; gap: 8px; }
|
|
67
90
|
.item .title { font-weight: 570; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; }
|
|
68
|
-
.item .when { color: var(--
|
|
69
|
-
.item .row2 { display: flex; align-items: center; gap: 8px; margin-top: 2px; font-size: 12px; color: var(--
|
|
91
|
+
.item .when { color: var(--slate); font-size: 11.5px; flex: none; }
|
|
92
|
+
.item .row2 { display: flex; align-items: center; gap: 8px; margin-top: 2px; font-size: 12px; color: var(--slate); }
|
|
70
93
|
.item .id { font-family: var(--mono); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
71
94
|
.dotc { width: 8px; height: 8px; border-radius: 50%; flex: none; display: inline-block; }
|
|
72
|
-
.badge { font-size: 10.5px; font-weight: 650; padding: 1px 7px; border-radius: 999px; background: var(--
|
|
73
|
-
.badge.st-todo { color: var(--
|
|
95
|
+
.badge { font-size: 10.5px; font-weight: 650; padding: 1px 7px; border-radius: 999px; background: var(--alt); color: var(--slate); flex: none; }
|
|
96
|
+
.badge.st-todo { color: var(--slate); }
|
|
74
97
|
.badge.st-in_progress { color: var(--warn); background: color-mix(in srgb, var(--warn) 12%, transparent); }
|
|
75
98
|
.badge.st-blocked, .badge.st-canceled { color: var(--bad); background: color-mix(in srgb, var(--bad) 10%, transparent); }
|
|
76
99
|
.badge.st-done, .badge.st-active { color: var(--ok); background: color-mix(in srgb, var(--ok) 10%, transparent); }
|
|
77
100
|
#detail { flex: 1; overflow-y: auto; padding: 20px 28px 60px; }
|
|
78
|
-
#detail .empty { color: var(--
|
|
101
|
+
#detail .empty { color: var(--slate); text-align: center; margin-top: 18vh; }
|
|
79
102
|
#detail .empty .big { font-size: 40px; margin-bottom: 12px; }
|
|
80
|
-
#crumbs { display: flex; gap: 4px; align-items: center; font-size: 12px; color: var(--
|
|
81
|
-
#crumbs button { border: 0; background: none; color: var(--
|
|
103
|
+
#crumbs { display: flex; gap: 4px; align-items: center; font-size: 12px; color: var(--slate); margin-bottom: 10px; flex-wrap: wrap; }
|
|
104
|
+
#crumbs button { border: 0; background: none; color: var(--structure); cursor: pointer; font: inherit; font-family: var(--mono); padding: 0; }
|
|
82
105
|
#crumbs .sep { opacity: .5; }
|
|
83
106
|
.doc h2 { font-size: 20px; margin-bottom: 2px; }
|
|
84
107
|
.doc .meta { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 8px 0 14px; }
|
|
85
108
|
.kv {
|
|
86
109
|
display: grid; grid-template-columns: max-content 1fr; gap: 3px 14px; font-size: 12.5px;
|
|
87
|
-
background: var(--
|
|
110
|
+
background: var(--card); border: 1px solid var(--rule); border-radius: 10px; padding: 10px 14px; margin-bottom: 16px;
|
|
88
111
|
}
|
|
89
|
-
.kv .k { color: var(--
|
|
112
|
+
.kv .k { color: var(--slate); font-family: var(--mono); }
|
|
90
113
|
.kv .v { word-break: break-word; }
|
|
91
|
-
.kv .v.ver { font-family: var(--mono); font-size: 11px; color: var(--
|
|
114
|
+
.kv .v.ver { font-family: var(--mono); font-size: 11px; color: var(--slate); }
|
|
92
115
|
.body { max-width: 72ch; }
|
|
93
116
|
.body h1, .body h2, .body h3 { margin: 18px 0 6px; line-height: 1.25; }
|
|
94
|
-
.body h1 { font-size: 18px; } .body h2 { font-size: 16px; } .body h3 { font-size: 14.5px; }
|
|
117
|
+
.body h1 { font-family: var(--display); font-size: 18px; } .body h2 { font-size: 16px; } .body h3 { font-size: 14.5px; }
|
|
95
118
|
.body p, .body ul, .body ol { margin: 8px 0; }
|
|
96
119
|
.body li { margin: 3px 0 3px 18px; }
|
|
97
|
-
.body code { font-family: var(--mono); font-size: 12.5px; background: var(--
|
|
98
|
-
.body pre { background: var(--
|
|
120
|
+
.body code { font-family: var(--mono); font-size: 12.5px; background: var(--alt); border-radius: 4px; padding: 1px 5px; }
|
|
121
|
+
.body pre { background: var(--alt); border: 1px solid var(--rule); border-radius: 8px; padding: 10px 12px; overflow-x: auto; margin: 10px 0; }
|
|
99
122
|
.body pre code { background: none; padding: 0; }
|
|
100
|
-
.body a.doclink { color: var(--
|
|
101
|
-
.body .extlink { color: var(--
|
|
123
|
+
.body a.doclink { color: var(--structure); text-decoration: none; border-bottom: 1px dashed var(--structure); cursor: pointer; }
|
|
124
|
+
.body .extlink { color: var(--slate); border-bottom: 1px dotted var(--slate); cursor: help; }
|
|
102
125
|
.doc .live-note {
|
|
103
|
-
font-size: 12px; color: var(--
|
|
126
|
+
font-size: 12px; color: var(--structure); background: var(--alt); border-radius: 8px;
|
|
104
127
|
padding: 6px 10px; margin-bottom: 12px; display: none;
|
|
105
128
|
}
|
|
106
|
-
footer { padding: 6px 16px; border-top: 1px solid var(--
|
|
107
|
-
footer .keys span { font-family: var(--mono); background: var(--
|
|
129
|
+
footer { padding: 6px 16px; border-top: 1px solid var(--rule); background: var(--card); font-size: 11.5px; color: var(--slate); display: flex; gap: 14px; }
|
|
130
|
+
footer .keys span { font-family: var(--mono); background: var(--alt); border-radius: 4px; padding: 0 5px; margin: 0 2px; }
|
|
108
131
|
</style>
|
|
109
132
|
</head>
|
|
110
133
|
<body>
|
|
@@ -191,7 +214,10 @@
|
|
|
191
214
|
"use strict";
|
|
192
215
|
var docs = [], selId = null, typeFilter = null, textFilter = "", follow = false;
|
|
193
216
|
var freshIds = new Set(), crumbs = [];
|
|
194
|
-
|
|
217
|
+
// Categorical series colours. Brand-first: series 1 and 2 are --structure and --signal,
|
|
218
|
+
// so the common case is on-theme; the rest are distinguishable hues, because a chart
|
|
219
|
+
// needs separable series more than it needs a two-colour palette.
|
|
220
|
+
var PALETTE = ["#0073B0","#956300","#0D7A6F","#7A3FA8","#B00020","#0891B2","#4F46E5","#8A6D00"];
|
|
195
221
|
var typeColor = {};
|
|
196
222
|
function colorFor(t) {
|
|
197
223
|
if (!typeColor[t]) typeColor[t] = PALETTE[Object.keys(typeColor).length % PALETTE.length];
|
|
@@ -5,51 +5,66 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
6
|
<title>Roadmap</title>
|
|
7
7
|
<style>
|
|
8
|
+
/* Superbee View theme — mirrors the launcher shell, so a View framed inside it reads as
|
|
9
|
+
one surface rather than a foreign document.
|
|
10
|
+
|
|
11
|
+
TWO accent roles, not three. --structure carries structure AND state: "active" is the
|
|
12
|
+
same hue at full intensity, never a second colour, because hue should carry kind and
|
|
13
|
+
intensity should carry state. --signal carries liveness and the revealed answer. There
|
|
14
|
+
is deliberately no teal. Quiet metadata takes --slate, not an accent.
|
|
15
|
+
|
|
16
|
+
Fonts: a View is sandboxed under `font-src data:`, so it CANNOT load the shell's
|
|
17
|
+
self-hosted woff2 by URL. The brand faces are named first and resolve for anyone who
|
|
18
|
+
has them installed locally; the stacks behind them are the real fallback. Do not embed
|
|
19
|
+
a data: font — that is ~100KB in every View for a marginal gain. */
|
|
8
20
|
:root {
|
|
9
|
-
--
|
|
21
|
+
--bg:#F3F7FA; --card:#FFFFFF; --alt:#E9EFF4; --rule:#DADEE2;
|
|
10
22
|
--ink:#0F1A24; --slate:#4A5D6E; --ghost:#9AAAB8;
|
|
11
|
-
--
|
|
23
|
+
--structure:#0073B0; --signal:#956300; --danger:#B00020;
|
|
12
24
|
--radius:2px;
|
|
13
|
-
--
|
|
14
|
-
--sans: -apple-system, "Segoe UI", system-ui, sans-serif;
|
|
15
|
-
--mono: ui-monospace, "SF Mono", Menlo, monospace;
|
|
25
|
+
--display:"Space Grotesk", system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
26
|
+
--sans:"DM Sans", -apple-system, "Segoe UI", system-ui, sans-serif;
|
|
27
|
+
--mono:"JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
|
|
16
28
|
}
|
|
17
29
|
@media (prefers-color-scheme: dark) {
|
|
18
|
-
:root {
|
|
19
|
-
--
|
|
30
|
+
:root {
|
|
31
|
+
--bg:#0B1926; --card:#0F2A3F; --alt:#12314A; --rule:#26323D;
|
|
32
|
+
--ink:#F8F6F2; --slate:#B7C4D1; --ghost:#7E8FA0;
|
|
33
|
+
--structure:#3CAEF9; --signal:#E09707; --danger:#F2707A;
|
|
34
|
+
}
|
|
20
35
|
}
|
|
21
36
|
* { box-sizing:border-box; margin:0; }
|
|
22
|
-
body { background:var(--
|
|
23
|
-
header { padding:22px 32px 14px; border-bottom:1px solid var(--rule); background:var(--
|
|
24
|
-
header h1 { font-family:var(--
|
|
25
|
-
header h1 .chev { color:var(--
|
|
37
|
+
body { background:var(--bg); color:var(--ink); font:15px/1.55 var(--sans); }
|
|
38
|
+
header { padding:22px 32px 14px; border-bottom:1px solid var(--rule); background:var(--card); }
|
|
39
|
+
header h1 { font-family:var(--display); font-weight:500; font-size:30px; letter-spacing:.01em; display:flex; align-items:baseline; gap:12px; }
|
|
40
|
+
header h1 .chev { color:var(--structure); font-family:var(--sans); font-weight:700; }
|
|
26
41
|
header .sub { color:var(--slate); font-size:13px; margin-top:2px; }
|
|
27
|
-
header .live { float:right; font-size:11.5px; color:var(--
|
|
28
|
-
header .live .dot { display:inline-block; width:7px; height:7px; border-radius:50%; background:var(--
|
|
42
|
+
header .live { float:right; font-size:11.5px; color:var(--signal); font-family:var(--mono); }
|
|
43
|
+
header .live .dot { display:inline-block; width:7px; height:7px; border-radius:50%; background:var(--signal); margin-right:5px; animation:pulse 1.4s infinite; }
|
|
29
44
|
@keyframes pulse { 50%{opacity:.3} }
|
|
30
45
|
main { max-width:900px; margin:0 auto; padding:26px 32px 80px; }
|
|
31
46
|
.group { margin-bottom:34px; }
|
|
32
47
|
.group > h2 { font-family:var(--sans); font-size:12px; font-weight:700; text-transform:uppercase; letter-spacing:.09em; color:var(--slate); display:flex; align-items:center; gap:9px; margin-bottom:4px; }
|
|
33
48
|
.group > h2 .swatch { width:10px; height:10px; border-radius:2px; }
|
|
34
49
|
.group > .note { font-size:12px; color:var(--ghost); margin-bottom:12px; }
|
|
35
|
-
.item { background:var(--
|
|
36
|
-
.item.active { border-left-color:var(--
|
|
37
|
-
.item.committed { border-left-color:var(--
|
|
38
|
-
.item.candidate { border-left-color:var(--
|
|
50
|
+
.item { background:var(--card); border:1px solid var(--rule); border-radius:var(--radius); border-left:3px solid var(--rule); margin-bottom:10px; overflow:hidden; }
|
|
51
|
+
.item.active { border-left-color:var(--structure); }
|
|
52
|
+
.item.committed { border-left-color:var(--structure); }
|
|
53
|
+
.item.candidate { border-left-color:var(--signal); }
|
|
39
54
|
.item .head { display:flex; align-items:center; gap:12px; padding:13px 16px; cursor:pointer; }
|
|
40
|
-
.item .head:hover { background:var(--
|
|
41
|
-
.item .title { font-family:var(--
|
|
55
|
+
.item .head:hover { background:var(--alt); }
|
|
56
|
+
.item .title { font-family:var(--display); font-size:19px; font-weight:500; flex:1; line-height:1.2; }
|
|
42
57
|
.item .caret { color:var(--ghost); font-size:12px; transition:transform .15s; }
|
|
43
58
|
.item.open .caret { transform:rotate(90deg); }
|
|
44
59
|
.badge { font-family:var(--sans); font-size:10.5px; font-weight:600; padding:2px 8px; border-radius:999px; white-space:nowrap; letter-spacing:.02em; }
|
|
45
|
-
.badge.active { color:var(--
|
|
46
|
-
.badge.queued { color:var(--slate); background:var(--
|
|
47
|
-
.badge.candidate { color:var(--
|
|
48
|
-
.badge.done { color:var(--slate); background:var(--
|
|
60
|
+
.badge.active { color:var(--structure); background:color-mix(in srgb,var(--structure) 13%,transparent); }
|
|
61
|
+
.badge.queued { color:var(--slate); background:var(--alt); }
|
|
62
|
+
.badge.candidate { color:var(--signal); background:color-mix(in srgb,var(--signal) 15%,transparent); }
|
|
63
|
+
.badge.done { color:var(--slate); background:var(--alt); }
|
|
49
64
|
.roll { display:flex; align-items:center; gap:9px; padding:0 16px 12px; }
|
|
50
|
-
.bar { flex:1; height:5px; background:var(--
|
|
65
|
+
.bar { flex:1; height:5px; background:var(--alt); border-radius:3px; overflow:hidden; display:flex; }
|
|
51
66
|
.bar i { height:100%; display:block; }
|
|
52
|
-
.bar i.done { background:var(--
|
|
67
|
+
.bar i.done { background:var(--structure); } .bar i.prog { background:var(--signal); } .bar i.open { background:var(--rule); }
|
|
53
68
|
.roll .count { font-family:var(--mono); font-size:11.5px; color:var(--slate); white-space:nowrap; }
|
|
54
69
|
.roll .none { font-size:11.5px; color:var(--ghost); font-style:italic; }
|
|
55
70
|
.body { display:none; padding:2px 16px 14px; border-top:1px solid var(--rule); }
|
|
@@ -57,16 +72,16 @@
|
|
|
57
72
|
.desc { font-size:13.5px; color:var(--slate); margin:12px 0; max-width:70ch; }
|
|
58
73
|
.tasks { display:flex; flex-direction:column; gap:1px; }
|
|
59
74
|
.task { display:flex; align-items:center; gap:10px; padding:6px 8px; border-radius:2px; }
|
|
60
|
-
.task:hover { background:var(--
|
|
75
|
+
.task:hover { background:var(--alt); }
|
|
61
76
|
.task .tdot { width:7px; height:7px; border-radius:50%; flex:none; }
|
|
62
77
|
.task .ttitle { flex:1; font-size:13.5px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
|
|
63
78
|
.task .tid { font-family:var(--mono); font-size:11px; color:var(--ghost); }
|
|
64
|
-
.st-todo{color:var(--slate)} .st-in_progress{color:var(--
|
|
65
|
-
.d-todo{background:var(--ghost)} .d-in_progress{background:var(--
|
|
79
|
+
.st-todo{color:var(--slate)} .st-in_progress{color:var(--signal)} .st-blocked,.st-canceled{color:var(--danger)} .st-done{color:var(--structure)}
|
|
80
|
+
.d-todo{background:var(--ghost)} .d-in_progress{background:var(--signal)} .d-blocked,.d-canceled{background:var(--danger)} .d-done{background:var(--structure)}
|
|
66
81
|
.item.fresh { animation:land 1.8s ease-out; }
|
|
67
|
-
@keyframes land { 0%{background:color-mix(in srgb,var(--
|
|
82
|
+
@keyframes land { 0%{background:color-mix(in srgb,var(--signal) 18%,var(--card))} 100%{background:var(--card)} }
|
|
68
83
|
footer { text-align:center; color:var(--ghost); font-size:11.5px; padding:20px; font-family:var(--mono); }
|
|
69
|
-
.empty { color:var(--ghost); text-align:center; margin-top:16vh; font-family:var(--
|
|
84
|
+
.empty { color:var(--ghost); text-align:center; margin-top:16vh; font-family:var(--display); font-size:20px; }
|
|
70
85
|
</style>
|
|
71
86
|
</head>
|
|
72
87
|
<body>
|
|
@@ -140,9 +155,9 @@
|
|
|
140
155
|
return (fm(it).sequence!=null && String(fm(it).sequence).trim()!=="") ? "committed" : "candidate";
|
|
141
156
|
}
|
|
142
157
|
var GROUPS=[
|
|
143
|
-
{key:"active", label:"In motion", swatch:"var(--
|
|
144
|
-
{key:"committed",label:"Committed", swatch:"var(--
|
|
145
|
-
{key:"candidate",label:"Candidate", swatch:"var(--
|
|
158
|
+
{key:"active", label:"In motion", swatch:"var(--structure)", note:"actively being worked"},
|
|
159
|
+
{key:"committed",label:"Committed", swatch:"var(--structure)", note:"sequenced, not yet started"},
|
|
160
|
+
{key:"candidate",label:"Candidate", swatch:"var(--signal)",note:"recognized direction — not yet committed or sequenced (queued + no sequence). Awaiting a founders' decision."},
|
|
146
161
|
{key:"done", label:"Done", swatch:"var(--slate)",note:""}
|
|
147
162
|
];
|
|
148
163
|
|