soul.demarkus.io:6309/journal/2026-07-05.md/v16 draft reader meta

2026-07-05

Ergonomics release chain completed — all three legs shipped

Finished the release topology for the MCP client ergonomics work (#225):

  • Leg 1: client/v0.15.0 auto-released from the #225 merge.
  • Leg 2 (#226): clientVersion 0.13.2 → 0.15.0 in tools/demarkus-plugin/internal/provision/provision.go → auto-released tools/v0.4.1.
  • Leg 3 (#227): TOOLS_VERSION 0.3.5 → 0.4.1 in all four plugins' bootstrap.sh (lockstep, shared binary) + patch bumps: demarkus-memory 0.12.4, demarkus-knowledge 0.5.4, pi-memory 0.12.5, pi-knowledge 0.5.5, with CHANGELOG entries for the pi pair. Next session start re-provisions demarkus-plugin v0.4.1 → demarkus-mcp v0.15.0; outline mode, #section slicing, session dedup, and mark_explore now reach users.

Also fixed in #227: .claude-plugin/marketplace.json had been desynced since #217/#221 (still 0.12.2/0.5.2 while the plugin manifests were at 0.12.3/0.5.3) — the manual repins bumped the manifests but missed the marketplace. Synced to 0.12.4/0.5.4.

Open observations for later (not blocking):

  • The plugin-pin-bump workflow's daily runs have reported success since 07-02 without opening a PR, despite pins being behind released versions (client 0.14.0/0.15.0, server 0.19.0, tools 0.4.0/0.4.1 all newer than the pins at the time). Either changed=false is mis-computed in .github/scripts/bump-plugin-pins.sh or something in the PR step is short-circuiting — worth a debugging pass.
  • serverVersion pin still 0.18.0 (server/v0.19.0 released 07-02) and fallbackToolsVersion still 0.3.3 — both deliberately left out of the repin PRs to keep them narrow; decide whether to sweep them.

plugin-pin-bump silent failure: root-caused and fixed

The "workflow succeeds but no PR" mystery from this morning's loose ends: gh pr view "$branch" in the workflow's upsert step resolves closed PRs, so after #210 was closed unmerged it edited that dead PR daily instead of creating a new one. Proof: #210 (closed 06-24) carries a title naming server 0.19.0 (released 07-02) and updatedAt 07-03. Fix on branch fix/plugin-pin-bump-closed-pr: look up an OPEN PR via gh pr list --head … --state open and edit by number, else create. Verified both paths read-only against the live repo. Gotcha generalized in /debugging.md.

Once merged, dispatching the workflow will sweep the remaining stale pins (serverVersion 0.18.0 → 0.19.0, fallbackToolsVersion 0.3.3 → 0.4.1) via a proper auto PR — closing this morning's second loose end through the automation instead of another manual repin.

Automation restored — first proper bump PR since 06-24

#228 (the closed-PR upsert fix) merged; dispatched plugin-pin-bump and it opened #229 — the first real auto bump PR since #210 was closed. It sweeps serverVersion 0.18.0 → 0.19.0 and fallbackToolsVersion 0.3.3 → 0.4.1 plus lineage patch bumps; bootstraps stay at 0.4.1 (already current). Both of this morning's loose ends closed.

Merge note for #229: it updates source pins only. Plugin users still provision server 0.18.0 until a new tools release ships the updated provision.go and the bootstraps repin to it — the standing three-leg topology; the now-working daily automation opens that follow-up bump PR when the tools release appears. Script gap (cosmetic): auto bumps don't add pi CHANGELOG entries.

Wrap: #229 merged, loop fully closed

#229 merged (d0d4b2d) and — correcting the earlier merge note — the chore(plugins) commit DID auto-release tools/v0.4.2 (release tooling keys on module changes, not commit type). So server 0.19.0 + fallbackToolsVersion 0.4.1 are now baked into a shipped demarkus-plugin, and the next scheduled plugin-pin-bump run (daily 07:23 UTC) will see tools 0.4.2 ≠ bootstrap pin 0.4.1 and open the bootstrap repin PR on its own. From here the pin pipeline is fully self-driving again: release → auto bump PR → merge → repeat. Day's arc: ergonomics phase shipped to users (#225/#226/#227), pin automation un-wedged (#228), stale pins swept (#229).

Broker gateway ergonomics parity built (feature/broker-ergonomics-parity)

Ported the client ergonomics to the broker MCP gateway so knowledge-system agents get the same surface; awaiting Fritz's commit.

  • Shared code (D4 payoff): the tools module already imports client, so the new client/mdoutline/render.go (OutlineBody, LinkLines, CappedList) is consumed by BOTH client cmd and broker — client's local copies were refactored out, no duplication.
  • W1: broker handleMarkFetch moved to mcp_tools_fetchmode.go with outline mode, #anchor slicing, force. Fragments are cut BEFORE parseToolURL (which rejects them for the other verbs by design — for fetch the fragment now has defined meaning).
  • W3 with the multi-tenant twist: dedup keyed by MCP session ID (ClientSessionFromContext), nested map sessionID → world+path → (version,etag). No session → no dedup, never a cross-user "unchanged". Eviction via Hooks.AddOnUnregisterSession; caps (4096 sessions × 1024 docs) bound memory if a transport never unregisters — beyond cap it degrades to no-dedup, not eviction of someone else's state.
  • W2: mark_explore (16th tool; mcpToolNames + handler map + count test 15→16). Backlinks from the broker's ephemeral per-pod graph store with an honest reset note; siblings via dispatcher LIST, degrades on failure.
  • W4: description pass mirrored (fetch/lookup/list/backlinks + explore).
  • Proof of session scoping end-to-end: a new HTTP-level test drives initialize → Mcp-Session-Id → two tools/call fetches (second returns status: unchanged) → second initialize gets a fresh session and the full body. Not just a hand-attached session in ctx.

The gateway's fidelity contract is untouched — formatToolResult unchanged; the new modes compose via a mirrored formatToolResultWith (cloned metadata, never mutates the response map).

Broker ergonomics parity merged — #230, five review rounds

PR #230 (2d4dab7) landed: the knowledge system's broker MCP gateway now carries the full W1–W4 ergonomics (outline fetch, #section, force, session-scoped dedup, mark_explore as the 16th tool, description pass). The two MCP surfaces are at parity.

The CodeRabbit rounds progressively hardened the dedup identity handling and are worth remembering as a sequence:

  1. Cap-hit observability + the mcp-go session-leak reality (OnUnregisterSession only fires on explicit DELETE, mcp-go#723) → LRU eviction at the session cap instead of refusing new sessions, Warn logs on both cap paths.
  2. changedNote etag-only wording ("still v" with no version).
  3. Asymmetric identity flips (versioned ↔ etag-only) rendered a bare "v" — spelled out as "was etag-only, now vN" / "was vN, now etag-only".
  4. The two-place fixes in rounds 2–3 proved the mirror was the problem → hoisted identity + notice text into the new shared client/fetchdedup package (Doc, Identified, UnchangedNotice, ChangedNote), one test copy; both surfaces now render through it.
  5. Note branch lacked the cur.Identified() guard — a response that loses BOTH identity fields after an identified fetch claimed "now etag-only" with no etag. Guarded at both call sites.

Lesson (pattern for /debugging.md if it recurs): duplicated "mirror" code whose drift is caught by review instead of by the compiler will absorb every fix twice and still leak differences — hoist at the second two-place fix, not the fifth. The formatResult mirror survives only because a byte-for-byte fidelity TEST enforces it; the changedNote mirror had no such test and broke twice in one PR.

Shared-package census after this PR: client/mdoutline (outline/slice + render helpers), client/fetchdedup (dedup identity + notices) — both consumed by client cmd and broker per D4.

Deploy note: this ships with the next broker release/deploy (server-side lane); no plugin repin involved. Remaining deferred follow-ups on the ergonomics plan: MCP resources/prompts, library librarian open adoption of mdoutline.

Broker 0.5.0 deployed — ergonomics live on the knowledge system

Deploy repo PR merged (18d9097, chart+image 0.2.0 → 0.5.0); ArgoCD synced; verified live: #section fetch works (old broker rejected fragments), second fetch of an unchanged doc returns status: unchanged (201 chars). The whole ergonomics arc is now in production on BOTH surfaces — plugin users (demarkus-mcp v0.15.0 via tools 0.4.1) and knowledge-system users (broker 0.5.0). Details in /demarkus-knowledge-system-deploy/journal/2026-07-05.md.

Record correction: versions sharding shipped in April, not "unstarted"

Fritz caught the soul asserting versions sharding was "fully specced; no code yet, unstarted" — it shipped in PR #90 (d7cb68a, 2026-04-08), the same day the plan was written, and the store was later hoisted to protocol/store (#120). The 2026-05-31 index verification pass missed it, likely because the plan doc carried no completion stamp and the commit subject says feat(filestore) while the plan says "sharding". Fixed: plan doc stamped COMPLETE, index entry moved to Completed Plans (and the MCP ergonomics plan added there too — it was never indexed).

Hygiene lesson: stamp the plan doc at ship time, in the same session — grep-based verification passes can't recover intent from mismatched vocabulary. The index is only as good as the completion discipline.

MCP resources + prompts built (feature/mcp-resources-prompts)

The ergonomics follow-up phase, planned and built same-day (/plans/mcp-resources-prompts.md; D1–D4 settled on Fritz's criterion: convenience lowers the bar and raises the joy of using demarkus).

  • resources.go: mark:// URI template + static index/manifest + a best-effort background LIST that populates the picker (20 live entries against the soul, list_changed notification confirmed). Resource reads always return the full body — attach is deliberate — with #anchor URIs for section-sized attach; no outline gate, no dedup.
  • prompts.go: orient / recall / whats-new as server-vended workflows (slash commands in Claude Code, picker entries in Desktop); whats-new rides LOOKUP's modified-after filter.
  • New server option WithResourceCapabilities(false, true) so late registration notifies connected clients.
  • Verified live over stdio: resources/list, templates/list, a guidelines.md#naming section read, prompts/list, prompts/get.
  • Broker deliberately untouched (D4); its capabilities test still pins resources/prompts absent — flipping that test starts the broker follow-up.

Awaiting Fritz's commit. Gotcha: mcp.Resource in mcp-go v0.44 has no size field, so the planned size annotation was dropped (noted in the plan as a D2 amendment).

Resources + prompts merged — #232, client/v0.17.0

The attach-without-turns phase landed same-day as its plan: resources (mark:// URI template with #anchor section attach, static index/manifest, background-LIST picker population with list_changed) and prompts (orient/recall/whats-new as server-vended slash commands). One review comment (log the unreachable resolveURL failure branch). client/v0.17.0 auto-released; the pin automation will carry it to plugin users without manual repins now that #228 fixed the bump workflow.

Day total: ergonomics deployed to both surfaces end-to-end (#225–#227, #230 + broker 0.5.0 deploy), pin automation fixed (#228/#229), stale versions-sharding record corrected, resources+prompts phase planned, built, merged (#232). Next candidates unchanged: broker resources/prompts follow-up, librarian open adoption, TUI external links, plain-dir root warning.

Librarian open adoption merged — the ergonomics plan fully closes

demarkus-library f08abfb: the librarian's open adopted the mdoutline convention (outline ≥8KB, path#anchor sections, force; the blind 16KB truncation replaced — one review round made outline mode own its truncation so the navigation footer always survives). Details in /demarkus-library/journal/2026-07-05.md.

With this, #section means the same thing on every surface in the ecosystem — mark_fetch, mark_explore, MCP resources, the librarian — from one implementation. The MCP client ergonomics plan is now fully closed including all deferred follow-ups; the only descendant left is broker resources/prompts (tracked in /plans/mcp-resources-prompts.md). Deploy tail: the library change rides its next image release + deploy-repo pin bump.

Broker resources + prompts merged — #233, tools/v0.6.0

D4's deferred leg closed same-day: the gateway now advertises resources (mark://{world}/{+path} template + per-world index hubs as picker entries) and prompts (orient / recall / whats-new — world-sweeping variants, deliberately siblings not mirrors of the client's). The capabilities test flip that had pinned their absence was the opening move, as the plan declared. Auth came free (gatewayAuth fronts /mcp); no dynamic listing needed (worlds are config-static per pod). Both resources+prompts phases now fully shipped; deploy-repo broker pin bump 0.5.0 → 0.6.0 is the last leg to the live system.

Broker 0.6.0 deployed — resources + prompts live on the knowledge system

Deploy pin merged (f52adaf), ArgoCD synced, rollout confirmed via the dedup-reset probe (per-pod session state as restart signal). The resources+prompts plan is now fully shipped AND deployed on both surfaces. The whole two-day arc — ergonomics → release chain → pin automation fix → broker parity → resources/prompts → librarian adoption — is closed end to end; no deploy tails remain except the library's next routine image release (librarian outline mode rides it).

trail
  1. soul.demarkus.io:6309 v16