← The specification

The board snapshot

Rendered from spec at76d46f3 (2026-10-25) · its source · Edit this page

Status: Accepted

The report of where every version stands publishes two files a script reads. state.json holds the verdict on every goal and nothing else. board.json, described here, holds everything the frontpage’s roadmap and board render (REPO-R39): the catalogue of features and requirements, every version manifest with the verdict on each goal, every repository’s tracker, every open pull request and what it cites, the repositories, the releases and the proposals. It is a reading of git at the revisions it names, and nothing in it is kept anywhere else.

Satisfies: OPS-R80, OPS-R81, OPS-R82; read by website-lemonfiber.app.


Where it is published

Each run of the state workflow replaces the assets of a release named board in this repository with board.json, state.json and STATE.md, and board.sha256, the hash of board.json without generated_at; it uploads the first three as the run’s state artifact. A release asset of a public repository downloads without credentials at a fixed address, so the newest snapshot is always at https://github.com/lemonfiber/spec/releases/download/board/board.json (OPS-R81); an artifact needs a token to download, and is kept for ninety days as the history.

When it is written

The report runs when a version manifest, a feature, 30-repos/repos.toml or the report’s own code changes on main here; when a repository announces that its tracker changed on its default branch; when a release is published; and hourly, as the backstop for anything no event announced (OPS-R82). A scheduled run is not relied on to happen on time.

The frontpage is asked to rebuild only when the snapshot’s content changed: the run hashes board.json with generated_at removed and compares it with the board.sha256 the board release holds. A release with no hash yet counts as a change.

A repository it cannot read

A repository whose history or tracker cannot be read is listed under unread with the reason, and a goal it is searched in reads unknown unless the repositories that could be read show it met. The rest of the snapshot is written and published (OPS-R76). The release gate reads the same repositories and still refuses a version it cannot judge (OPS-R75); the report answers more questions than the gate and does not stop at the first it cannot.

Its shape

format names the shape, and is 1. A field removed, renamed or given another meaning raises it; a field added does not, so a reader checks format, refuses one it does not know, and ignores fields it does not know.

Field Holds
format The shape of the file, 1
generated_at When it was written, UTC, YYYY-MM-DDTHH:MM:SSZ
ref The revision each repository was read at
sources The full commit read of spec and of every repository, by name
unread[] Each repository that could not be read: repo, reason
areas[] Each area of the catalogue: id, name, directory
features[] Each feature: id, title, area, audience, kind, status, maturity, shipped, priority, labels, requires, relates, path, and versions (each version locking one of its requirements, with that version’s status)
requirements[] Each requirement the specification defines: id, owner (a feature’s id, or the path of the document defining it), namespace, keyword (MUST, SHOULD or MAY, the strongest it uses), text, status (withdrawn or superseded where its row says so, draft where its feature is Draft or its row opens with *Draft:*, otherwise accepted), replaced_by (the identifier a superseded row names), and versions (each version locking it)
versions[] Each manifest in train order: version, status, milestone, delivers, released_on, released_as, repos, satisfied_in, prereleases, and goals (each with id, verdict and the evidence state.json gives a goal)
trackers[] Each repository a version is satisfied in: repo, present, and rows (each with id, state, evidence, landed, and path, the file in that repository the row is kept in)
pulls[] Each open pull request in those repositories: repo, number, url, title, author, bot, draft, created_at, updated_at, head (its branch), last_commit_at (when its newest commit was made), stale (a draft with no commit for more than claims.stale_days days), and cites (the identifiers its body and commits cite in Spec: lines)
claims The rules the flags below are drawn by: cap (the open pull requests from people and agents a repository may hold, GOV-R58) and stale_days (the days a draft may go without a commit)
contested[] Each goal of a version not released or yanked that more than one open pull request from people or agents cites: id, and pulls (each as repo#number)
repos[] Each repository in 30-repos/repos.toml, the map’s and the ungoverned ones (group ungoverned): name, group, lang, note, pages (its specification pages), open_pulls, counted_pulls (those opened by people and agents, which the cap counts), over_cap (more than claims.cap), the three null where its pull requests were not read, tracker (present, absent or unread, or null where no version is satisfied in it)
releases[] Each release the core’s changelog records: version, tag, released_on, delivers, and groups (each with title and entries, each entry with summary, requirements and reference)
proposals[] Each Draft feature and Draft requirement, and each open rfc issue: kind, id or number, title, url
tools[] Each command of the developer command line, lfdev, as commands.json at the root of tool-lfdev lists them: name, purpose. The commit read is sources["tool-lfdev"]; a list that cannot be read leaves tools empty and names tool-lfdev under unread

A goal’s verdict is one of state.json’s (met, unmarked, uncited, claimed, open) or unknown, where it is searched in a repository listed under unread and the repositories that could be read do not show it met. A field with no value is null, and a list with no members is [], never absent.

The snapshot reads the manifests, the trackers and the citations through the same modules as the release gate and goals.py, so a verdict on the board cannot differ from the gate’s.

Requirements

ID Requirement
OPS-R80 The report from OPS-R76 MUST also publish a board snapshot holding the catalogue (every feature, and every requirement with its text and status), every version manifest with the verdict on each goal, every tracker row, every open pull request with its citations, author, draft state and dates, the repositories and the releases, with the commit of every source, in a documented shape whose format rises when a field is removed, renamed or given another meaning.
OPS-R81 The newest board snapshot MUST be downloadable without credentials at one fixed address.
OPS-R82 The report MUST run when a version manifest, the catalogue or a repository’s tracker changes on its default branch, when a release is published, and on a schedule; it MUST ask the frontpage to rebuild only when the board snapshot’s content changed.