# 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.