Conversation
khaneight
force-pushed
the
feat/publish-sources
branch
from
August 27, 2026 02:23
846a0b8 to
3e3f7bc
Compare
One self-contained HTML file plus its bundle. `sentinel export --ui <dir>` writes both; copy them anywhere static. No build step, no dependencies, one network read — its own `bundle.json` — so it works offline, under a strict content policy, and in five years when whatever framework was fashionable today is not. It shows what a static site generator cannot show from markdown alone: the link graph, the persona traits the clone writes from, what is still in flight (unpublished drafts, work awaiting approval, unconfirmed traits, concepts the wiki has named and not written), and the growth curve from `meta/progress.jsonl`. **Articles the clone wrote are never rendered as though their author wrote them.** Different colour, a count called out above the panel, and on selection a note naming the claims the piece was written from. The bundle carries `extrapolated` on every node for exactly this, and the page branches on it in words rather than only in a hue. A front end is the easiest thing in a repository to let rot — nothing compiles it, and a renamed field turns a panel blank rather than failing anything. So the page declares the fields it reads in one `CONTRACT` object, uses it at runtime to say which key is missing instead of rendering an empty panel, and `tests/ui.rs` asserts it against a bundle generated by the real command. Checked that the guard bites: renaming `extrapolated` to `extrapolatd` in the contract fails the test naming the field and listing what the bundle actually publishes. The page is `include_str!`d rather than a file the user is told to copy, so a released binary always writes a page matching the bundle it produces. `--ui` writes its own `bundle.json` beside it, since a flag that wrote the page without its data would produce a site whose only content is an error message. Two layout defects found by opening it rather than by asserting on it. Five nodes huddled in the middle of a 1400px canvas, because the ideal edge length was a constant tuned against one archive; it is now derived from the space and the node count. Then the fix overshot and strung five nodes across the whole stage, which fills the space and is much harder to read than a compact cluster — so the spacing is bounded above as well. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #74. The interface: published work, the graph, and the work in flight.
Two files. Copy them to a subdomain, an S3 bucket, a
docs/folder — no buildstep, no dependencies, one network read (its own JSON). It works offline, under
a strict content policy, and in five years.
Why one HTML file rather than a Vite/React app
You said the host should be flexible. A build toolchain in a Rust repository is
a second dependency tree to keep alive, and this is a graph viewer over a few
hundred nodes — canvas and forty lines of Fruchterman-Reingold do it. If you'd
rather have React, say so and I'll build it;
--dataalready emits the bundlefor anyone who wants to render it themselves.
What it shows
what has been written from it
traits, concepts the wiki has named and not written
meta/progress.jsonlWork the clone wrote is never rendered as though you wrote it. Different
colour, a count called out at the top, and on selection a note naming the claims
it was written from. The bundle carries
extrapolatedon every node for exactlythis, and the page branches on it in words, not only in a hue.
Keeping a front end from rotting
Nothing compiles a page like this, and a renamed field in the exporter turns a
panel blank rather than failing anything. So the page declares every field it
reads in one
CONTRACTobject; it uses that at runtime to say which key ismissing instead of rendering an empty panel, and
tests/ui.rsparses it out ofthe HTML and asserts it against a bundle from the real command.
I checked the guard bites — renaming
extrapolatedtoextrapolatd:Also asserted: the page is self-contained (no external URL, exactly one
fetch),--uiwrites both files, the written page is byte-identical to theone in the tree,
--dry-runwrites nothing, and the bundle respects theapproval gate — an unapproved article never appears in the graph.
Two defects found by opening it, not by testing it
Five nodes huddled in the middle of a 1400px canvas: the ideal edge length was a
constant tuned against one archive. Deriving it from the available area and node
count fixed that and then overshot, stringing five nodes across the whole
stage — which fills the space and is much harder to read than a compact cluster.
Bounded above as well as derived.
531 tests (+6), clippy and fmt clean.
🤖 Generated with Claude Code