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.0auto-released from the #225 merge. - Leg 2 (#226):
clientVersion0.13.2 → 0.15.0 intools/demarkus-plugin/internal/provision/provision.go→ auto-releasedtools/v0.4.1. - Leg 3 (#227):
TOOLS_VERSION0.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-bumpworkflow'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). Eitherchanged=falseis mis-computed in.github/scripts/bump-plugin-pins.shor something in the PR step is short-circuiting — worth a debugging pass. serverVersionpin still 0.18.0 (server/v0.19.0 released 07-02) andfallbackToolsVersionstill 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
handleMarkFetchmoved tomcp_tools_fetchmode.gowith outline mode,#anchorslicing,force. Fragments are cut BEFOREparseToolURL(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 viaHooks.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:
- 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.
changedNoteetag-only wording ("still v" with no version).- Asymmetric identity flips (versioned ↔ etag-only) rendered a bare "v" — spelled out as "was etag-only, now vN" / "was vN, now etag-only".
- The two-place fixes in rounds 2–3 proved the mirror was the problem →
hoisted identity + notice text into the new shared
client/fetchdeduppackage (Doc, Identified, UnchangedNotice, ChangedNote), one test copy; both surfaces now render through it. - 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#anchorURIs 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.