The plan's data format¶
The Project pages render from one file, plan.yaml, checked against plan.schema.json (JSON Schema 2020-12). Both are included below from the repo at build time, so this page can't drift from them.
Shape¶
The format is chosen so a bee board can be seeded from it later:
itemsis an object keyed by id. An id is opaque and stable, and is never reused. It starts withtask-(a v1 plan task),bee-(a bee issue or PR),kuilt-(kuilt work) orout-(work outside the code). A slice keeps its draft id, such askuilt-3126-d, once it is filed; its GitHub number lives only inlinks.- Each item is replaced whole on write. On a board, that means a concurrent status move and summary edit on the same item keep only one of the two.
orderlists every id exactly once, in display order. On a board it is an Rga of ids.columnshas one entry per status, andcolumn_orderputs them in order. On a board these are aBoardnotion's columns. A column with anowneris shown at the top of the overview as waiting on that owner.parentnames the item this one is part of. A parent depends on its children by definition, so a child is never also in its parent'sdepends_on.startedis when the item's PR opened, or when its issue was filed if it has no PR.landedis when it merged or closed, or for a decision, when it was ruled. Only a done item has one.- Timestamps are quoted UTC strings,
"2026-11-07T01:31Z". The pages show them in America/New_York. - An
estimateis a range,lowtohighinhoursordays, with thebasisit rests on and an optionalconfidence. The pages always label it as an estimate and never draw it on a dated axis. - A relative link URL is relative to
docs/project/, so it works on GitHub and on the site.
The YAML holds plain JSON values only: no anchors, no tags, no unquoted dates. Every item allows
only the fields the schema lists, so an export from a board must bump schema_version before it
adds one, and must drop duplicate and missing ids from order.
Checks¶
The build fails when the file breaks the schema. Beyond the schema, it fails when:
- a mapping repeats a key;
- an
order,depends_onorparententry names an id that isn't an item, or an item is missing fromorder; column_orderandcolumnsname different statuses, or an item's status has no column;depends_onorparenthas a cycle, or a parent'sdepends_onlists its own child;- a timestamp or date isn't a real one, an item lands before it starts, or an item that isn't
done has
landed; - an estimate's
lowis above itshigh; - a title, summary or basis spans more than one line.
The checks live in docs-site/plan_pages.py. Every link on an
item is rendered, so strict mode checks each one.
The schema¶
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://github.com/tractat-us/bee/blob/main/docs/project/plan.schema.json",
"title": "bee project plan",
"description": "The project's plan as data: pieces of work, their status, dependencies and estimates. The docs site renders the Project section from it, and a bee board can be seeded from it: `items` is an object keyed by stable id (one object per item, replaced whole on write) and `order` is a list of ids (an Rga of ids on the board). Replacing an item whole means that on a board, a concurrent status move and summary edit on the same item keep only one of the two. Every value is plain JSON, so the YAML that holds it uses no anchors, tags or unquoted dates. A future export from a board must drop duplicate and missing ids from `order`, and must bump `schema_version` before adding any field, since an item allows no properties beyond those listed here.",
"type": "object",
"additionalProperties": false,
"required": ["schema_version", "as_of", "columns", "column_order", "order", "items"],
"properties": {
"schema_version": { "const": 1 },
"as_of": {
"description": "When the file was last reconciled with GitHub, as an ISO 8601 UTC timestamp.",
"$ref": "#/$defs/timestamp"
},
"sources": {
"description": "Where the data comes from, in reading order.",
"type": "array",
"items": { "$ref": "#/$defs/link" }
},
"columns": {
"description": "One column per status. On a board, these are a Board notion's columns.",
"type": "object",
"propertyNames": { "$ref": "#/$defs/status" },
"additionalProperties": {
"type": "object",
"additionalProperties": false,
"required": ["title"],
"properties": {
"title": { "type": "string" },
"owner": { "description": "Who moves items out of this column, when that is one party.", "type": "string" }
}
}
},
"column_order": {
"type": "array",
"items": { "$ref": "#/$defs/status" },
"uniqueItems": true
},
"order": {
"description": "Every item id exactly once, in display order. The docs build fails on a duplicate, a missing id or an id that is not an item.",
"type": "array",
"items": { "$ref": "#/$defs/id" },
"uniqueItems": true
},
"items": {
"type": "object",
"propertyNames": { "$ref": "#/$defs/id" },
"additionalProperties": { "$ref": "#/$defs/item" }
}
},
"$defs": {
"id": {
"description": "Opaque, stable and never reused. Prefixes: task- (a plan task), bee- (a bee issue or PR), kuilt- (a kuilt issue or PR), out- (work outside the code). A slice keeps its draft id (kuilt-3126-d) once it is filed; its GitHub number lives only in `links`.",
"type": "string",
"pattern": "^(task|bee|kuilt|out)-[a-z0-9]+(-[a-z0-9]+)*$"
},
"status": {
"enum": ["done", "in-flight", "next", "blocked", "waiting-on-iain", "later"]
},
"timestamp": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2})?Z$"
},
"date": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
},
"link": {
"type": "object",
"additionalProperties": false,
"required": ["title", "url"],
"properties": {
"title": { "type": "string" },
"url": { "type": "string", "pattern": "^(https://|\\.\\./|\\./|[A-Za-z0-9_])" }
}
},
"estimate": {
"description": "A range, always labelled as an estimate, with what it rests on. Wall-clock time from start to merge, not counting time waiting on Iain.",
"type": "object",
"additionalProperties": false,
"required": ["low", "high", "unit", "basis"],
"properties": {
"low": { "description": "At most `high`.", "type": "number", "minimum": 0 },
"high": { "type": "number", "minimum": 0 },
"unit": { "enum": ["hours", "days"] },
"basis": { "description": "Why this range: the merge history or plan text it comes from.", "type": "string" },
"confidence": { "enum": ["low", "medium", "high"] }
}
},
"ruling": {
"type": "object",
"additionalProperties": false,
"required": ["date", "summary"],
"properties": {
"date": { "$ref": "#/$defs/date" },
"summary": { "type": "string" },
"url": { "type": "string" }
}
},
"item": {
"type": "object",
"additionalProperties": false,
"required": ["kind", "title", "status"],
"properties": {
"kind": {
"description": "task: a task in the v1 plan. pr: a pull request. issue: a bug or follow-up. decision: a question for Iain. kuilt: kuilt work bee depends on. outside: work outside the code.",
"enum": ["task", "pr", "issue", "decision", "kuilt", "outside"]
},
"title": { "type": "string" },
"status": { "$ref": "#/$defs/status" },
"summary": { "description": "One sentence: what it is, or what it waits for.", "type": "string" },
"parent": { "description": "The item this one is part of. A parent depends on its children by definition, so a child never appears in its parent's `depends_on`; the docs build fails if it does.", "$ref": "#/$defs/id" },
"depends_on": {
"description": "Items that must be done before this one can finish, other than its children. The docs build fails on a cycle.",
"type": "array",
"items": { "$ref": "#/$defs/id" },
"uniqueItems": true
},
"started": { "description": "When its PR opened, or when its issue was filed if there is no PR.", "$ref": "#/$defs/timestamp" },
"landed": { "description": "When it merged or closed; for a decision, when it was ruled. Required when status is done, and allowed only then. Never before `started`.", "$ref": "#/$defs/timestamp" },
"estimate": { "$ref": "#/$defs/estimate" },
"ruling": { "$ref": "#/$defs/ruling" },
"links": {
"type": "array",
"items": { "$ref": "#/$defs/link" }
}
},
"allOf": [
{
"if": { "properties": { "status": { "const": "done" } } },
"then": { "required": ["landed"] }
}
]
}
}
}
The data¶
plan.yaml, in full
# The bee project plan, as data. Schema: plan.schema.json, beside this file.
#
# The docs site's Project section renders from this file, and a bee board can later
# be seeded from it (bee#21). Keep it plain JSON in YAML form: no anchors, no tags,
# every timestamp a quoted UTC string. `items` is keyed by stable id and each item is
# replaced whole on write; `order` lists every id once. The markdown plan
# (docs/superpowers/plans/2026-11-06-bee-v1.md) stays the source of truth for what
# each task is; this file tracks where each one stands.
#
# Estimates are ranges, labelled as estimates, with their basis. They measure
# wall-clock time from start to merge and leave out time waiting on Iain.
schema_version: 1
as_of: "2026-11-08T19:02Z"
sources:
- title: "v1 plan"
url: "../superpowers/plans/2026-11-06-bee-v1.md"
- title: "Epic: bee v1 (bee#6)"
url: "https://github.com/tractat-us/bee/issues/6"
- title: "Merged pull requests"
url: "https://github.com/tractat-us/bee/pulls?q=is%3Apr+is%3Amerged"
columns:
done: { title: "Done" }
in-flight: { title: "In flight" }
waiting-on-iain: { title: "Waiting on Iain", owner: "iain" }
blocked: { title: "Blocked" }
next: { title: "Next" }
later: { title: "Later" }
column_order: [done, in-flight, waiting-on-iain, blocked, next, later]
order:
- task-1
- task-2
- task-3
- task-4
- task-5
- task-6
- bee-11
- task-7
- bee-27
- bee-28
- bee-32
- bee-31
- bee-33
- bee-37
- bee-40
- bee-43
- bee-44
- bee-45
- bee-46
- bee-49
- bee-53
- bee-54
- bee-58
- bee-60
- bee-64
- bee-65
- bee-71
- bee-72
- bee-73
- bee-74
- bee-77
- bee-78
- bee-80
- bee-81
- bee-83
- bee-84
- bee-85
- bee-14
- bee-19
- bee-23
- task-8
- task-9
- task-10
- bee-42-calls
- task-11
- bee-21
- kuilt-3126
- kuilt-3132
- kuilt-3136
- kuilt-3137
- kuilt-3126-d
- kuilt-3126-e
- kuilt-3126-f
- kuilt-3126-g
- kuilt-3133
- kuilt-3134
- kuilt-3129
- kuilt-3142
- kuilt-3143
- kuilt-3144
- kuilt-3145
- kuilt-3146
- kuilt-own-write-ack
- kuilt-3148
- kuilt-3149
- kuilt-3150
- bee-42-hand-check
- bee-auto-close
- out-cla
- out-kuilt-references
items:
# ── The v1 plan's tasks ──────────────────────────────────────────────
task-1:
kind: task
title: "Kotlin/wasm and the renderer in one page (spike 1)"
status: done
summary: "Kotlin/wasm drives the stock A2UI Lit renderer, with the build and CI."
started: "2026-11-07T00:59Z"
landed: "2026-11-07T01:31Z"
links:
- { title: "Plan, Task 1", url: "../superpowers/plans/2026-11-06-bee-v1.md#task-1-kotlinwasm-and-the-renderer-in-one-page-spike-1-plus-all-build-wiring" }
- { title: "bee#8", url: "https://github.com/tractat-us/bee/pull/8" }
- { title: "Spike 1 report", url: "../spikes/2026-11-spike-1-renderer-glue.md" }
task-2:
kind: task
title: "The board lattice and its projection (spike 2, part 1)"
status: done
depends_on: [task-1]
started: "2026-11-07T01:38Z"
landed: "2026-11-07T02:02Z"
links:
- { title: "Plan, Task 2", url: "../superpowers/plans/2026-11-06-bee-v1.md#task-2-the-board-lattice-and-its-projection-spike-2-part-1" }
- { title: "bee#9", url: "https://github.com/tractat-us/bee/pull/9" }
- { title: "Spike 2 report", url: "../spikes/2026-11-spike-2-crdt-behind-a2ui.md" }
task-3:
kind: task
title: "The relay (spike 2, part 2)"
status: done
depends_on: [task-2]
started: "2026-11-07T02:13Z"
landed: "2026-11-07T02:44Z"
links:
- { title: "Plan, Task 3", url: "../superpowers/plans/2026-11-06-bee-v1.md#task-3-the-relay-spike-2-part-2" }
- { title: "bee#15", url: "https://github.com/tractat-us/bee/pull/15" }
- { title: "bee#29, deltas not whole boards", url: "https://github.com/tractat-us/bee/pull/29" }
task-4:
kind: task
title: "The browser driver and two browsers (spike 2, part 3)"
status: done
depends_on: [task-3]
started: "2026-11-07T02:55Z"
landed: "2026-11-07T03:30Z"
links:
- { title: "Plan, Task 4", url: "../superpowers/plans/2026-11-06-bee-v1.md#task-4-the-browser-driver-and-two-browsers-spike-2-part-3" }
- { title: "bee#16", url: "https://github.com/tractat-us/bee/pull/16" }
task-5:
kind: task
title: "Bridge mechanics (spike 3, first half)"
status: done
depends_on: [task-1]
started: "2026-11-07T01:47Z"
landed: "2026-11-07T02:12Z"
links:
- { title: "Plan, Task 5", url: "../superpowers/plans/2026-11-06-bee-v1.md#task-5-bridge-mechanics-spike-3-first-half" }
- { title: "bee#13", url: "https://github.com/tractat-us/bee/pull/13" }
- { title: "Spike 3 report", url: "../spikes/2026-11-spike-3-bridge-mechanics.md" }
task-6:
kind: task
title: "Claims (spike 4)"
status: done
summary: "Exactly-once claims with fencing tokens, through a durable voter that never claims. Held about a day on kuilt learner admission (bee#11)."
depends_on: [task-1]
started: "2026-11-07T01:42Z"
landed: "2026-11-08T00:00Z"
links:
- { title: "Plan, Task 6", url: "../superpowers/plans/2026-11-06-bee-v1.md#task-6-claims-spike-4" }
- { title: "bee#10", url: "https://github.com/tractat-us/bee/pull/10" }
- { title: "bee#26, learner grace", url: "https://github.com/tractat-us/bee/pull/26" }
- { title: "Spike 4 report", url: "../spikes/2026-11-spike-4-claims.md" }
bee-11:
kind: decision
title: "Claims blocked by kuilt learner admission: fix kuilt first, or work around it in bee?"
status: done
parent: task-6
started: "2026-11-07T01:44Z"
landed: "2026-11-07T14:43Z"
ruling:
date: "2026-11-07"
summary: "Fix kuilt first: a learner reconciler, then removal after a grace (kuilt#3120). bee bumps its kuilt pin and finishes Task 6 once kuilt publishes."
url: "https://github.com/tractat-us/bee/issues/11#issuecomment-6708367111"
links:
- { title: "bee#11", url: "https://github.com/tractat-us/bee/issues/11" }
task-7:
kind: task
title: "Join, which completes spikes 3 and 4"
status: done
summary: "A Claude session opens a surface, waits and answers; a second session sees it. Landed as #27, #32 and #33."
depends_on: [task-4, task-5, task-6]
started: "2026-11-07T21:49Z"
landed: "2026-11-08T02:17Z"
ruling:
date: "2026-11-07"
summary: "The post-Task-7 review hold is lifted. #27 lands first, then #32 and #33. Tasks 8, 9 and 10 start in parallel from main once #27 merges, and Iain reviews #27's deviations after the fact."
url: "https://github.com/tractat-us/bee/issues/6#issuecomment-6715926429"
links:
- { title: "Plan, Task 7", url: "../superpowers/plans/2026-11-06-bee-v1.md#task-7-join-which-completes-spikes-3-and-4" }
task-8:
kind: task
title: "Sketch and the companion adapter (spike 5, the acceptance test)"
status: done
summary: "The brainstorming visual companion's screens run through bee: v1's done-when. Landed after Iain's rulings on #60 (page-side commit) and the Sketch size cap (none for v1)."
depends_on: [bee-27, bee-60]
started: "2026-11-08T02:13Z"
landed: "2026-11-08T18:49Z"
estimate:
low: 2
high: 24
unit: hours
basis: "One PR, larger than Tasks 2–5, which took about half an hour each from PR open to merge. The high end is Task 6's 22 h, for a task that meets a kuilt or renderer gap."
confidence: low
links:
- { title: "Plan, Task 8", url: "../superpowers/plans/2026-11-06-bee-v1.md#task-8-sketch-and-the-companion-adapter-spike-5-the-acceptance-test" }
- { title: "bee#38", url: "https://github.com/tractat-us/bee/pull/38" }
task-9:
kind: task
title: "Durability of the board (spike 6)"
status: done
summary: "The board survives host restarts and closed browsers, through a generic Quilter–DurableStore adapter."
depends_on: [bee-27]
started: "2026-11-08T02:15Z"
landed: "2026-11-08T03:21Z"
links:
- { title: "Plan, Task 9", url: "../superpowers/plans/2026-11-06-bee-v1.md#task-9-durability-of-the-board-spike-6" }
- { title: "bee#39", url: "https://github.com/tractat-us/bee/pull/39" }
task-10:
kind: task
title: "A second screen, joined by LAN pairing (spike 7)"
status: done
summary: "A key, with Bluetooth-style passkey pairing; only human peers admit a device. Pairing runs by poll at /pair with a join budget (SSE until bee#211); the keyed sockets take a frame bound (kuilt#3145)."
depends_on: [bee-27]
started: "2026-11-08T02:20Z"
landed: "2026-11-08T03:51Z"
links:
- { title: "Plan, Task 10", url: "../superpowers/plans/2026-11-06-bee-v1.md#task-10-a-second-screen-spike-7" }
- { title: "bee#42", url: "https://github.com/tractat-us/bee/pull/42" }
bee-42-calls:
kind: decision
title: "Task 10's follow-up calls"
status: done
summary: "Four calls from #42, each now an issue: the host's PeerKind (#71), claim-free join records with a bridge refusal (#72), HTTPS on the LAN (#73, after the demo) and a host per writing e2e file (#74)."
started: "2026-11-08T02:35Z"
landed: "2026-11-08T17:26Z"
ruling:
date: "2026-11-08"
summary: "Add PeerKind.Host as a label; accept claim-free admits and have the bridge refuse pairing surfaces; HTTPS on the LAN after the demo; a host per e2e file that writes records."
url: "https://github.com/tractat-us/bee/issues/6#issuecomment-6724665300"
links:
- { title: "bee#42", url: "https://github.com/tractat-us/bee/pull/42" }
task-11:
kind: task
title: "Working-day surfaces: Board, Poll, orphan decisions, history strip"
status: done
summary: "Landed in two halves without bee#19: Poll, Board and the history strip (#70), then orphan decisions and reassigned claims reaching a session's wait (#75). The Board needs no change when #19 makes card order an Rga."
depends_on: [task-7]
started: "2026-11-08T17:44Z"
landed: "2026-11-08T18:59Z"
links:
- { title: "Plan, Task 11", url: "../superpowers/plans/2026-11-06-bee-v1.md#task-11-working-day-surfaces-board-poll-orphan-decisions-history-strip" }
- { title: "bee#70, Notions Poll and Board", url: "https://github.com/tractat-us/bee/pull/70" }
- { title: "bee#75, orphan decisions", url: "https://github.com/tractat-us/bee/pull/75" }
# ── bee pull requests and issues ─────────────────────────────────────
bee-27:
kind: pr
title: "Join the bridge, the board and claims"
status: done
parent: task-7
started: "2026-11-07T21:49Z"
landed: "2026-11-08T02:01Z"
links:
- { title: "bee#27", url: "https://github.com/tractat-us/bee/pull/27" }
bee-28:
kind: decision
title: "Detect a dead board link from the claims link, or from a per-spoke view?"
status: done
parent: task-7
started: "2026-11-07T21:51Z"
landed: "2026-11-07T23:53Z"
ruling:
date: "2026-11-07"
summary: "Detect a crash from the claims link: a node dropped after its learner grace is a PeerLost."
url: "https://github.com/tractat-us/bee/issues/28#issuecomment-6714701528"
links:
- { title: "bee#28", url: "https://github.com/tractat-us/bee/issues/28" }
bee-32:
kind: pr
title: "Detect a crashed agent from its claims link"
status: done
parent: task-7
depends_on: [bee-27, bee-28]
started: "2026-11-08T00:27Z"
landed: "2026-11-08T02:10Z"
links:
- { title: "bee#32", url: "https://github.com/tractat-us/bee/pull/32" }
bee-31:
kind: issue
title: "A late win whose link dies is released only by a later wait on that surface"
status: done
parent: task-7
started: "2026-11-08T00:23Z"
landed: "2026-11-08T02:17Z"
links:
- { title: "bee#31", url: "https://github.com/tractat-us/bee/issues/31" }
bee-33:
kind: pr
title: "Give back a late win whose claims link died, on the next link"
status: done
parent: bee-31
depends_on: [bee-27]
started: "2026-11-08T01:18Z"
landed: "2026-11-08T02:17Z"
links:
- { title: "bee#33", url: "https://github.com/tractat-us/bee/pull/33" }
bee-37:
kind: issue
title: "A wait's reserve can no longer fail, so make it fail loudly"
status: done
summary: "A follow-up from #33's re-review. Fixed by #41."
depends_on: [bee-33]
started: "2026-11-08T02:10Z"
landed: "2026-11-08T02:28Z"
links:
- { title: "bee#37", url: "https://github.com/tractat-us/bee/issues/37" }
- { title: "bee#41", url: "https://github.com/tractat-us/bee/pull/41" }
bee-40:
kind: pr
title: "Move kuilt to 0.7.0-dev.1696"
status: done
summary: "Takes kuilt's LatticeDotFun and CausalMap, slices (a) and (b) of kuilt#3126."
depends_on: [kuilt-3132, kuilt-3136]
started: "2026-11-08T02:15Z"
landed: "2026-11-08T02:19Z"
links:
- { title: "bee#40", url: "https://github.com/tractat-us/bee/pull/40" }
bee-43:
kind: issue
title: "A board change elsewhere may re-create the field someone is typing in"
status: done
summary: "Not a bee bug: the field is never re-created. The caret failures came from Playwright on macOS, and #63 pins the claim."
started: "2026-11-08T02:36Z"
landed: "2026-11-08T19:00Z"
ruling:
date: "2026-11-08"
summary: "Not a bug."
url: "https://github.com/tractat-us/bee/issues/43#issuecomment-6725706047"
links:
- { title: "bee#43", url: "https://github.com/tractat-us/bee/issues/43" }
- { title: "bee#63", url: "https://github.com/tractat-us/bee/pull/63" }
bee-44:
kind: decision
title: "Decision: an agent that dies while the host is down keeps its claims forever"
status: done
summary: "Built in #62: once a 60 s boot grace has passed, the host departs, as Crashed, any agent that holds a claim and has no presence entry."
started: "2026-11-08T02:36Z"
landed: "2026-11-08T17:26Z"
ruling:
date: "2026-11-08"
summary: "Option (a), a boot grace."
url: "https://github.com/tractat-us/bee/issues/44#issuecomment-6724665507"
links:
- { title: "bee#44", url: "https://github.com/tractat-us/bee/issues/44" }
- { title: "bee#62", url: "https://github.com/tractat-us/bee/pull/62" }
bee-45:
kind: issue
title: "Any website open on the laptop can use the board: check Origin and Host on /ws/*"
status: done
summary: "Fixed by #51, which refuses a board socket from another site or a rebinding host name."
started: "2026-11-08T02:44Z"
landed: "2026-11-08T04:40Z"
links:
- { title: "bee#45", url: "https://github.com/tractat-us/bee/issues/45" }
- { title: "bee#51", url: "https://github.com/tractat-us/bee/pull/51" }
bee-46:
kind: issue
title: "A tab left open across a host wipe pushes its old board, claim views included, into the new host"
status: done
summary: "Fixed by #52: every board and claims socket names its board, and the host refuses any other id before the upgrade. The id now lives in claims/ too, so moving claims/ aside starts a new board. Data from before #52 keeps its board, and a refused bridge exits loudly."
started: "2026-11-08T03:07Z"
landed: "2026-11-08T04:49Z"
links:
- { title: "bee#46", url: "https://github.com/tractat-us/bee/issues/46" }
- { title: "bee#52", url: "https://github.com/tractat-us/bee/pull/52" }
bee-53:
kind: issue
title: "ClaimsSmokeTest and FrameBoundTest fail intermittently in the smoke job"
status: done
summary: "Fixed by #57 for ClaimsSmokeTest, which now waits on conditions, not time. FrameBoundTest's missing 1009 close frame is #58."
started: "2026-11-08T04:31Z"
landed: "2026-11-08T05:27Z"
links:
- { title: "bee#53", url: "https://github.com/tractat-us/bee/issues/53" }
- { title: "bee#57", url: "https://github.com/tractat-us/bee/pull/57" }
bee-54:
kind: issue
title: "Refuse cross-site requests by Fetch Metadata: a no-Origin GET can still fill the pairing slots"
status: done
summary: "A follow-up to #51, fixed by #55."
started: "2026-11-08T04:40Z"
landed: "2026-11-08T05:36Z"
links:
- { title: "bee#54", url: "https://github.com/tractat-us/bee/issues/54" }
- { title: "bee#55", url: "https://github.com/tractat-us/bee/pull/55" }
bee-58:
kind: decision
title: "The host can hang up on an over-bound frame without its 1009 close frame"
status: done
summary: "Fixed by #69: bee moves to Ktor 3.6.1, which carries the upstream fixes for the lost last frame."
started: "2026-11-08T05:15Z"
landed: "2026-11-08T17:35Z"
ruling:
date: "2026-11-08"
summary: "The host must deliver the 1009; done by moving Ktor to 3.6.1."
url: "https://github.com/tractat-us/bee/issues/58#issuecomment-6724762759"
links:
- { title: "bee#58", url: "https://github.com/tractat-us/bee/issues/58" }
- { title: "bee#69", url: "https://github.com/tractat-us/bee/pull/69" }
bee-60:
kind: decision
title: "Decision: a Sketch can forge the viewer's choice in Chromium, by focusing itself"
status: done
summary: "Fixed in #38: a Sketch only proposes a choice, and the page records it on a trusted click on its own Send bar."
started: "2026-11-08T06:01Z"
landed: "2026-11-08T17:35Z"
ruling:
date: "2026-11-08"
summary: "Option (a): the page commits the choice, outside the frame."
url: "https://github.com/tractat-us/bee/issues/60#issuecomment-6724762579"
links:
- { title: "bee#60", url: "https://github.com/tractat-us/bee/issues/60" }
- { title: "bee#38", url: "https://github.com/tractat-us/bee/pull/38" }
bee-49:
kind: decision
title: "A Sketch can still reach the network through WebRTC, which CSP doesn't cover"
status: done
started: "2026-11-08T03:41Z"
landed: "2026-11-08T17:30Z"
ruling:
date: "2026-11-08"
summary: "Accepted as a v1 limit and documented in the spec; revisit when an engine ships a control."
url: "https://github.com/tractat-us/bee/issues/49#issuecomment-6724762977"
links:
- { title: "bee#49", url: "https://github.com/tractat-us/bee/issues/49" }
- { title: "bee#66, spec limit", url: "https://github.com/tractat-us/bee/pull/66" }
bee-64:
kind: decision
title: "Decision: any local process can admit a second screen by writing a human-attributed admit"
status: done
summary: "Resolved for v1 by #68, which states the limit in spec section 5.7. Connection-attested authors are kuilt#3149."
started: "2026-11-08T17:33Z"
landed: "2026-11-08T17:42Z"
ruling:
date: "2026-11-08"
summary: "Option A for v1: state the limit. No new gate may rest on peer kind."
url: "https://github.com/tractat-us/bee/issues/64#issuecomment-6724838405"
links:
- { title: "bee#64", url: "https://github.com/tractat-us/bee/issues/64" }
- { title: "bee#68", url: "https://github.com/tractat-us/bee/pull/68" }
bee-65:
kind: issue
title: "A client whose FullState is over the frame bound redials and resends it forever"
status: in-flight
summary: "A board over the bound should stop and say so; the fix is in review as #76."
started: "2026-11-08T17:33Z"
links:
- { title: "bee#65", url: "https://github.com/tractat-us/bee/issues/65" }
- { title: "bee#76", url: "https://github.com/tractat-us/bee/pull/76" }
bee-71:
kind: issue
title: "Give the host its own peer kind, and keep bee_clear off its surfaces"
status: next
summary: "PeerKind.Host as a label only, so bee_clear stops stranding pairing devices (from #42's calls)."
started: "2026-11-08T17:44Z"
links:
- { title: "bee#71", url: "https://github.com/tractat-us/bee/issues/71" }
bee-72:
kind: issue
title: "The bridge refuses wait and list on the host's pairing surfaces"
status: next
summary: "Claim-free admits stay, written into the spec, and the bridge refuses an agent that waits on a pairing surface (from #42's calls)."
started: "2026-11-08T17:44Z"
links:
- { title: "bee#72", url: "https://github.com/tractat-us/bee/issues/72" }
bee-73:
kind: issue
title: "Serve the board over HTTPS on the LAN, so LAN pages are secure contexts"
status: later
summary: "After the demo: plain-HTTP LAN pages keep no local copy and lack microphone, wake lock and clipboard (from #42's calls)."
started: "2026-11-08T17:44Z"
links:
- { title: "bee#73", url: "https://github.com/tractat-us/bee/issues/73" }
bee-74:
kind: issue
title: "Give each e2e spec that writes records its own host, and run two workers"
status: next
summary: "Saves about 45 s per smoke job; the PRs it waited on, #38 and #63, have merged (from #42's calls)."
started: "2026-11-08T17:44Z"
links:
- { title: "bee#74", url: "https://github.com/tractat-us/bee/issues/74" }
bee-77:
kind: issue
title: "The bridge's board socket sends no pings, so a half-open link can outlast the boot grace"
status: next
summary: "Set a client ping on the bridge's board and claims sockets, well under the 60 s grace."
started: "2026-11-08T17:52Z"
links:
- { title: "bee#77", url: "https://github.com/tractat-us/bee/issues/77" }
bee-78:
kind: issue
title: "Boot grace: two survivors holding different stale entries make a dead agent look seen"
status: next
summary: "A narrow window found in #62; count an identity as seen only when its newest entry names a voter member."
started: "2026-11-08T17:52Z"
links:
- { title: "bee#78", url: "https://github.com/tractat-us/bee/issues/78" }
bee-80:
kind: issue
title: "A bee-notions edit can ship a stale bundle while webpack reports up to date"
status: next
summary: "Declare bee-notions/src as an input to the webpack task, so a stale bundle can't read as a false green."
started: "2026-11-08T17:59Z"
links:
- { title: "bee#80", url: "https://github.com/tractat-us/bee/issues/80" }
bee-81:
kind: issue
title: "The bridge can't append to an array, so agent Polls lose their options basis"
status: next
summary: "bee_surface_open writes options as one whole-array leaf, so the bridge needs an append write."
started: "2026-11-08T18:10Z"
links:
- { title: "bee#81", url: "https://github.com/tractat-us/bee/issues/81" }
bee-83:
kind: issue
title: "Fence an orphan decision's proposal by the orphan token"
status: next
summary: "A stale click on an orphan decision applies to whatever orphaning is current; found in #75's re-review."
started: "2026-11-08T18:40Z"
links:
- { title: "bee#83", url: "https://github.com/tractat-us/bee/issues/83" }
bee-84:
kind: issue
title: "Sketch Send bar: close the remaining arming gaps with aria-disabled and a click guard"
status: next
summary: "Narrow holes left after #38's final review found it safe for a demo-stage v1."
started: "2026-11-08T18:49Z"
links:
- { title: "bee#84", url: "https://github.com/tractat-us/bee/issues/84" }
bee-85:
kind: issue
title: "PairingChannelTest's hang-up case fails every time it runs alone"
status: next
summary: "It passes inside a full check and failed once in CI; the pairing ends before the device hangs up."
started: "2026-11-08T18:59Z"
links:
- { title: "bee#85", url: "https://github.com/tractat-us/bee/issues/85" }
bee-14:
kind: decision
title: "Surface data semantics: merge or replace, concurrent card order, leaf encoding"
status: done
started: "2026-11-07T01:51Z"
landed: "2026-11-07T14:43Z"
ruling:
date: "2026-11-07"
summary: "Object writes replace, card order is an Rga of ids, and the prefix leaf encoding stands."
url: "https://github.com/tractat-us/bee/issues/14#issuecomment-6708367416"
links:
- { title: "bee#14", url: "https://github.com/tractat-us/bee/issues/14" }
bee-19:
kind: pr
title: "Surface data semantics: object writes replace, card order is an Rga of ids"
status: blocked
summary: "On hold until kuilt#3126 (d), the JsonCrdt v2 core, publishes."
depends_on: [bee-14, kuilt-3126-d]
started: "2026-11-07T14:51Z"
links:
- { title: "bee#19", url: "https://github.com/tractat-us/bee/pull/19" }
bee-23:
kind: issue
title: "ClaimTable: drop duplicate log entries through kuilt's ClientSessionTable"
status: blocked
summary: "Before production. Can't happen within one incarnation on the pinned kuilt. Closing a session needs kuilt's RoomHost tear contract, kuilt#3129 (bee#30)."
depends_on: [kuilt-3129]
started: "2026-11-07T20:43Z"
links:
- { title: "bee#23", url: "https://github.com/tractat-us/bee/issues/23" }
bee-21:
kind: issue
title: "Dogfood: bee as the board for its own development"
status: later
summary: "A first try is possible now that Task 9 has landed; the full version is Task 11's secondary test. The markdown stays the source of truth for now (ruled 2026-11-07)."
depends_on: [task-7, task-8, task-9, task-11]
links:
- { title: "bee#21", url: "https://github.com/tractat-us/bee/issues/21" }
# ── kuilt dependencies ───────────────────────────────────────────────
kuilt-3126:
kind: kuilt
title: "Shared causal context for JsonCrdt (epic)"
status: in-flight
summary: "Began as an ORMap.remove bug; ruled reset-and-replace, re-seed migration, and every nested use on a shared-context CausalMap. Split into (a)–(g)."
started: "2026-11-07T19:36Z"
estimate:
low: 1
high: 3
unit: days
basis: "From the issue being filed to the last slice merging. (a) and (b) each took about 3 h from PR open to merge. (c) waits on three design calls for Iain, with no PR yet, and (d)–(g) are not filed. What remains is a chain of three: (c), then (d), then (e)–(g) in parallel, at 3–12 h each."
confidence: low
ruling:
date: "2026-11-07"
summary: "Reset and replace; migrate by re-seed; move every nested use to the shared-context CausalMap. The (a)–(g) split is confirmed."
url: "https://github.com/tractat-us/kuilt/issues/3126"
links:
- { title: "kuilt#3126", url: "https://github.com/tractat-us/kuilt/issues/3126" }
kuilt-3132:
kind: kuilt
title: "(a) LatticeDotFun, a dot store that joins its payloads"
status: done
summary: "Published in kuilt 0.7.0-dev.1696."
parent: kuilt-3126
started: "2026-11-07T22:27Z"
landed: "2026-11-08T01:29Z"
links:
- { title: "kuilt#3132", url: "https://github.com/tractat-us/kuilt/pull/3132" }
kuilt-3136:
kind: kuilt
title: "(b) CausalMap, one shared context for a map and its nested stores"
status: done
summary: "Published in kuilt 0.7.0-dev.1696."
parent: kuilt-3126
depends_on: [kuilt-3132]
started: "2026-11-07T23:01Z"
landed: "2026-11-08T01:43Z"
links:
- { title: "kuilt#3136", url: "https://github.com/tractat-us/kuilt/pull/3136" }
kuilt-3137:
kind: kuilt
title: "(c) A dot-store Rga"
status: waiting-on-iain
parent: kuilt-3126
summary: "A design gate is posted, with three calls for Iain before implementation. bee#19 and Task 11 wait on the chain that starts here."
started: "2026-11-07T23:54Z"
links:
- { title: "kuilt#3137", url: "https://github.com/tractat-us/kuilt/issues/3137" }
- { title: "Design gate", url: "https://github.com/tractat-us/kuilt/issues/3137#issuecomment-6716124347" }
kuilt-3126-d:
kind: kuilt
title: "(d) JsonCrdt v2 core and path API"
status: next
parent: kuilt-3126
summary: "Drafted, not filed. bee#19 waits on it."
depends_on: [kuilt-3136, kuilt-3137]
kuilt-3126-e:
kind: kuilt
title: "(e) Migration by re-seed, and a format tag"
status: next
parent: kuilt-3126
summary: "Drafted, not filed."
depends_on: [kuilt-3126-d]
kuilt-3126-f:
kind: kuilt
title: "(f) Quilter frontier wiring (kuilt#2177)"
status: next
parent: kuilt-3126
summary: "Drafted, not filed."
depends_on: [kuilt-3126-d]
kuilt-3126-g:
kind: kuilt
title: "(g) Writerside and sample rewrite, and the ORMap guard"
status: next
parent: kuilt-3126
summary: "Drafted, not filed."
depends_on: [kuilt-3126-d]
kuilt-3133:
kind: kuilt
title: "kuilt-raft: prune a removed peer's replication state, and reset it at election"
status: in-flight
started: "2026-11-07T22:29Z"
links:
- { title: "kuilt#3133", url: "https://github.com/tractat-us/kuilt/pull/3133" }
kuilt-3134:
kind: kuilt
title: "kuilt-raft: a node stops campaigning once its removal is committed"
status: waiting-on-iain
summary: "A spec-critical engine change that departs from the issue's suggested fix; needs Iain's review before merge."
started: "2026-11-07T22:32Z"
links:
- { title: "kuilt#3134", url: "https://github.com/tractat-us/kuilt/pull/3134" }
kuilt-3129:
kind: kuilt
title: "session: the RoomHost contract doesn't say whether onRoom ends when its connection tears"
status: in-flight
summary: "The tear signal bee needs to close a claims session when its learner leaves (bee#23). Slice 1, the conformance suite, is in review."
started: "2026-11-08T01:28Z"
links:
- { title: "kuilt#3129", url: "https://github.com/tractat-us/kuilt/issues/3129" }
- { title: "kuilt#3141, slice 1", url: "https://github.com/tractat-us/kuilt/pull/3141" }
kuilt-3142:
kind: kuilt
title: "quilter: no signal that a replica has caught up with the peer it joined"
status: next
started: "2026-11-08T02:25Z"
links:
- { title: "kuilt#3142", url: "https://github.com/tractat-us/kuilt/issues/3142" }
kuilt-3143:
kind: kuilt
title: "store: IndexedDbDurableStore lets synchronous JS throws escape as JsException, which no catch (Exception) sees"
status: next
summary: "Found in bee#39. bee works around it with a decorator, so it doesn't wait on the fix."
started: "2026-11-08T02:41Z"
links:
- { title: "kuilt#3143", url: "https://github.com/tractat-us/kuilt/issues/3143" }
kuilt-3144:
kind: kuilt
title: "Quilter drops a delta or FullState over the seam's payload budget without a word"
status: next
summary: "bee hit it on its board link in #38, and works around it with WireBudget for now."
started: "2026-11-08T02:58Z"
links:
- { title: "kuilt#3144", url: "https://github.com/tractat-us/kuilt/issues/3144" }
kuilt-3145:
kind: kuilt
title: "WebSocket installs take no frame bound, so one header can allocate 2 GiB"
status: next
summary: "Found in the review of bee#42. bee works around it in the host's socket gate, so it doesn't wait on the fix."
started: "2026-11-08T03:25Z"
links:
- { title: "kuilt#3145", url: "https://github.com/tractat-us/kuilt/issues/3145" }
kuilt-3146:
kind: kuilt
title: "Server looms accept a WebSocket handshake from any web page: no Origin or Host check"
status: next
summary: "bee checks Origin and Host itself since bee#51, so it doesn't wait on the fix."
started: "2026-11-08T04:01Z"
links:
- { title: "kuilt#3146", url: "https://github.com/tractat-us/kuilt/issues/3146" }
kuilt-own-write-ack:
kind: kuilt
title: "Quilter: a caller can't wait until its own write is acknowledged"
status: next
summary: "Quilter.mutate doesn't return its sequence number, so bee counts writes against universalAckFlow instead. Filed as kuilt#3147 and named in #38's KDoc."
started: "2026-11-08T15:02Z"
links:
- { title: "kuilt#3147", url: "https://github.com/tractat-us/kuilt/issues/3147" }
- { title: "bee#38", url: "https://github.com/tractat-us/bee/pull/38" }
kuilt-3148:
kind: kuilt
title: "Star overlays: a spoke's Quilter can't sendTo another spoke, so a mid-stream joiner never heals its cursor"
status: next
summary: "A spoke that joins mid-stream sees another spoke's edits only at the next anti-entropy round."
started: "2026-11-08T17:33Z"
links:
- { title: "kuilt#3148", url: "https://github.com/tractat-us/kuilt/issues/3148" }
kuilt-3149:
kind: kuilt
title: "Relay: attest each record's author by the connection that first delivered it"
status: next
summary: "Behind bee#60 and bee#64; needed before a second person or a keyed agent attaches, and bee states the limit for v1."
started: "2026-11-08T17:42Z"
links:
- { title: "kuilt#3149", url: "https://github.com/tractat-us/kuilt/issues/3149" }
- { title: "bee#68", url: "https://github.com/tractat-us/bee/pull/68" }
kuilt-3150:
kind: kuilt
title: "Move Ktor to 3.6.1: Netty and WebSocket drop a session's last frame on 3.5.2"
status: next
summary: "bee moved itself to 3.6.1 in #69, so it doesn't wait on this."
started: "2026-11-08T18:00Z"
links:
- { title: "kuilt#3150", url: "https://github.com/tractat-us/kuilt/issues/3150" }
# ── Outside the code ─────────────────────────────────────────────────
bee-42-hand-check:
kind: outside
title: "Pair a real phone over the LAN"
status: waiting-on-iain
summary: "The e2e never binds off loopback, so mDNS, the macOS firewall, Wi-Fi isolation and mobile Safari or Chrome are unproven."
started: "2026-11-08T17:26Z"
links:
- { title: "bee#42", url: "https://github.com/tractat-us/bee/pull/42" }
- { title: "Steps: Showing the board on another screen", url: "../setup.md#showing-the-board-on-another-screen" }
bee-auto-close:
kind: outside
title: "Turn off auto-close in bee's settings"
status: waiting-on-iain
summary: "Settings, General, Issues; a UI toggle only, to match the rest of tractat-us."
started: "2026-11-08T17:26Z"
links:
- { title: "Ruling on bee#6", url: "https://github.com/tractat-us/bee/issues/6#issuecomment-6724665300" }
out-cla:
kind: outside
title: "Contributor agreement text and a signing check"
status: waiting-on-iain
summary: "A lawyer writes it, not an agent. Needed before the repo accepts outside contributions."
links:
- { title: "Epic bee#6", url: "https://github.com/tractat-us/bee/issues/6" }
out-kuilt-references:
kind: outside
title: "kuilt References policy: allow references to public tractat-us projects"
status: later
summary: "A kuilt AGENTS.md PR, landed once bee is public."
links:
- { title: "Epic bee#6", url: "https://github.com/tractat-us/bee/issues/6" }