2026-07-24
Durable docs brought current with the last week of merges
Fritz flagged that the knowledge base lagged the repo. Journals were current through 07-23 but the durable docs had not absorbed them:
- /roadmap.md (v63): two new DONE sections. "Five-Minute Appliance & Install Hardening" (PRs #267, #269 install-stack.sh, #270 library HTTPS :443, #271 self-dial probe, #272 cert renewal re-run fix, plus the droplet migration ops note) and "Markdown-Only Content Contract" (PR #273). Also: scope section now notes the contract is enforced, plugin section updated to v0.13.5 current with the #264-#275 pin-bump entries, v0.13.0 join URLs marked shipped (#261), docs-hygiene entry for the website refresh (07-23 pages branch).
- /architecture.md (v17): new "Markdown-Only Content Contract" design decision under Key Design Decisions, recording the layer split (handler owns the .md rule, store owns the UTF-8 invariant via ValidateBody in both backends plus conformance case, MCP owns render refusal, transport stays byte-faithful) and the two invariants (UTF-8 concatenation, lowercase-only .md).
The org knowledge system (knowledge.demarkus.io) needed nothing: its worlds are the mortgage demo content, not demarkus development docs.
Pins bumped and soul droplet upgraded
Deploy repo pins updated on branch chore/bump-pins-markdown-contract (Fritz committed): worlds 0.20.0 to 0.22.0 (markdown-only contract), broker 0.12.4 to 0.14.3, agent 0.21.3 to 0.24.0, library 0.22.0 to 0.23.0. Comment convention in the applicationsets kept (one "why" line per version, checked against the actual git ranges).
soul.demarkus.io droplet upgraded by pushing the repo's current install.sh over scp (GitHub raw was flaky; releases downloaded fine) and re-running install.sh --domain soul.demarkus.io --root /srv/soul --with-library. Server 0.21.0 to 0.22.0, client/tools binaries to 0.24.0/0.14.3, kept tokens/config/certs honored, self-dial OK, library restarted on :443. First live re-run exercising the #272 renewal-hook idempotency: "Certbot renewal cron already configured / already restarts the library" both correct. Contract verified live: mark_publish to /contract-check.png returned bad-request, no version created. The known sshd MaxStartups bot churn caused one connection reset; a retry loop around scp handled it.
Gap carried forward: the broker gateway has no UTF-8 render guard (#273 only guarded local demarkus-mcp); needs a monorepo issue.
Broker render-guard gap filed as monorepo issue #276 (low urgency: worlds at 0.22.0 close the ingress; the guard is the backstop for hand-written store bytes and pre-0.22.0 worlds behind a broker).
Knowledge system rolled (2026-07-25)
Deploy PR #120 merged with all four pins (title omits library but 0.23.0 is on main). Argo synced; verified end to end with the same probe used on the droplet: mark_publish of /contract-check.png against mark://root/ returned bad-request from the world server (after satisfying the client-side policy gate so the request actually reached the wire). Both demarkus surfaces now enforce the markdown-only contract; #276 (broker render guard) is the remaining tail.
Broker render guard implemented (#276, branch fix/broker-render-guard, 2026-07-25)
Hoisted the #273 binary guard into the shared render package: mdoutline.BinaryBody (UTF-8 predicate) and mdoutline.NonMarkdownNotice (notice text), the same one-copy-not-a-mirror move as fetchdedup. demarkus-mcp's three sites now call the shared helpers (private binaryBody/nonMarkdownNotice deleted, notice text moved verbatim so the existing #273 tests double as regression proof). Broker gateway gained the guard at its three render sites, placed identically to the local client: handleMarkFetch (before the anchor slice, mode: binary, force never bypasses), handleMarkExplore (before the outline builder), readResource (text/plain notice). Tests mirror the local ones (fetch notice, force-still-notice, explore no-outline, resource MIME + text) plus a table test on the new mdoutline helpers. All suites green, pre-commit clean. Correction to the issue text discovered while reading the shipped code: #273's guard never had a force=true raw-bytes bypass in mark_fetch ("force bypasses the size gate, never the binary gate"), so the broker mirrors always-notice.