Spec: docs/superpowers/specs/2026-08-23-web-ui-rewrite-design.md § Documentation.
Depends on #536 (shell). Fixes a bug already in every release.
The shipped bug
uv_build packages the module root — keel/ — and everything under it (140 entries: the .py files plus keel/templates/*.yaml). docs/ sits at the repository root, outside that tree, so no wheel carries it. As keel/commands/help_console.py:138-146 says in its own docstring:
"an installed deployment has no docs/ checkout, and the help screen renders that notice as its empty state"
Every installed deployment, including the signed bundle, renders an empty Glossary.
docs/ stays in keel — the pipeline runs the other way
keel's docs/ is the source; keeltrading.com is the mirror. engine-docs.manifest.json pins CodeGateSoftware/keel@main, and scripts/fetch-engine-docs.mjs declares itself "the only writer of src/content/engine-docs/", exiting non-zero if a pinned document disappears. Deleting docs/ from keel would fail the website build, loudly, by design.
What changes is that the application code stops carrying documentation prose.
Link out; fetch, bundle and cache nothing
A documentation reference opens https://keeltrading.com/en/docs/{slug}/#{anchor} in a new tab with rel="noopener". Verified against the built site:
docs/glossary.md states its own rule — "Each entry is a ## term heading, a definition, and a Source: line."
- Astro emits the IDs:
dist/en/docs/glossary/index.html contains id="rail", id="attestation", id="instrument-attestation", id="kill-switch", id="qabd", id="riba".
src/pages/en/docs/[slug].astro renders every pinned document at a stable path.
So the anchor contract is kebab-case the ## term heading. Outbound links are navigation, not connections, and are unaffected by connect-src 'self'.
No offline fallback, deliberately: no inline definitions, no cached snapshot. An operator running a trading engine has network by definition, and the least technology that does the job is the correct amount.
Version skew is made visible, not solved
Links carry ?v= from GET /api/config (#534). The site pins main while an operator runs a tagged release, so a link can describe behaviour their build lacks. Per-version paths were rejected — keeltrading.com/en/docs/v0.11.0/glossary#qabd 404s today; building versioned trees is work in the other repository plus a retention policy, across three languages and the sitemap.
The website half is tracked at CodeGateSoftware/keeltrading.com#1.
Deletions
/glossary, render_glossary(), and the web layer's use of load_glossary()/parse_glossary() — a link needs no renderer. help_console.py's reader stays for the TUI until #541 removes it.
Acceptance
Correction — the packaging reason, measured
An earlier version of this issue said the wheel omits docs/ because artifacts lists only the YAML template. That was the wrong reason, and the real one makes the case stronger.
pyproject.toml's artifacts = ["keel/templates/*.yaml"] is inert on the pinned backend (uv_build>=0.10.4,<0.13.0). Measured, not assumed: building with that list and with artifacts = [] produces wheels whose contents are byte-for-byte identical — 140 entries each, both carrying the two YAML templates. uv_build ships the whole module root regardless of the key. The adjacent source comment, "the wheel otherwise contains only .py files", is wrong by the same measurement.
docs/ is absent because it lives at the repository root, outside keel/, which is what uv_build packages.
So the empty glossary cannot be fixed by adding a glob. It is structural. Linking out is not the cheaper option here — it is the only one that reaches an installed deployment.
Credit: found by the agent implementing #535, which was briefed with the incorrect version above and tested the claim rather than inheriting it.
Spec:
docs/superpowers/specs/2026-08-23-web-ui-rewrite-design.md§ Documentation.Depends on #536 (shell). Fixes a bug already in every release.
The shipped bug
uv_buildpackages the module root —keel/— and everything under it (140 entries: the.pyfiles pluskeel/templates/*.yaml).docs/sits at the repository root, outside that tree, so no wheel carries it. Askeel/commands/help_console.py:138-146says in its own docstring:Every installed deployment, including the signed bundle, renders an empty Glossary.
docs/stays in keel — the pipeline runs the other waykeel's
docs/is the source; keeltrading.com is the mirror.engine-docs.manifest.jsonpinsCodeGateSoftware/keel@main, andscripts/fetch-engine-docs.mjsdeclares itself "the only writer ofsrc/content/engine-docs/", exiting non-zero if a pinned document disappears. Deletingdocs/from keel would fail the website build, loudly, by design.What changes is that the application code stops carrying documentation prose.
Link out; fetch, bundle and cache nothing
A documentation reference opens
https://keeltrading.com/en/docs/{slug}/#{anchor}in a new tab withrel="noopener". Verified against the built site:docs/glossary.mdstates its own rule — "Each entry is a## termheading, a definition, and aSource:line."dist/en/docs/glossary/index.htmlcontainsid="rail",id="attestation",id="instrument-attestation",id="kill-switch",id="qabd",id="riba".src/pages/en/docs/[slug].astrorenders every pinned document at a stable path.So the anchor contract is kebab-case the
## termheading. Outbound links are navigation, not connections, and are unaffected byconnect-src 'self'.No offline fallback, deliberately: no inline definitions, no cached snapshot. An operator running a trading engine has network by definition, and the least technology that does the job is the correct amount.
Version skew is made visible, not solved
Links carry
?v=fromGET /api/config(#534). The site pinsmainwhile an operator runs a tagged release, so a link can describe behaviour their build lacks. Per-version paths were rejected —keeltrading.com/en/docs/v0.11.0/glossary#qabd404s today; building versioned trees is work in the other repository plus a retention policy, across three languages and the sitemap.The website half is tracked at CodeGateSoftware/keeltrading.com#1.
Deletions
/glossary,render_glossary(), and the web layer's use ofload_glossary()/parse_glossary()— a link needs no renderer.help_console.py's reader stays for the TUI until #541 removes it.Acceptance
?v=from the running version./glossaryandrender_glossary()are gone.docs/is untouched; the keeltrading.com build still succeeds against this branch'smain.Correction — the packaging reason, measured
An earlier version of this issue said the wheel omits
docs/becauseartifactslists only the YAML template. That was the wrong reason, and the real one makes the case stronger.pyproject.toml'sartifacts = ["keel/templates/*.yaml"]is inert on the pinned backend (uv_build>=0.10.4,<0.13.0). Measured, not assumed: building with that list and withartifacts = []produces wheels whose contents are byte-for-byte identical — 140 entries each, both carrying the two YAML templates.uv_buildships the whole module root regardless of the key. The adjacent source comment, "the wheel otherwise contains only .py files", is wrong by the same measurement.docs/is absent because it lives at the repository root, outsidekeel/, which is whatuv_buildpackages.So the empty glossary cannot be fixed by adding a glob. It is structural. Linking out is not the cheaper option here — it is the only one that reaches an installed deployment.
Credit: found by the agent implementing #535, which was briefed with the incorrect version above and tested the claim rather than inheriting it.