# Journal — 2026-03-04 ## 2026-03-04 — Agent Manifest Discovery Fritz picked the agent-native direction from the roadmap — agent manifest discovery. The idea: a conventional document at `/.well-known/agent-manifest.md` that agents can fetch to learn what a server offers, same pattern as `robots.txt` for web crawlers. ### What Changed - **`protocol/protocol.go`**: Added `WellKnownManifestPath = "/.well-known/agent-manifest.md"` constant. - **`client/cmd/demarkus-mcp/main.go`**: New `mark_discover` tool — fetches the manifest from the connected server. URL parameter is optional when `-host` is set. - **`client/cmd/demarkus/main.go`**: New `info` subcommand — `demarkus info mark://host` fetches and displays the manifest. - **`docs/site/reference/agent-manifest.md`**: Spec document defining the convention — required sections (name, description), optional sections (paths, auth, guidelines, contact), publishing instructions, token permissions, systemctl restart note. - **`docs/site/reference/index.md`**: Added link to the agent manifest spec. - **`client/cmd/demarkus-mcp/main_test.go`**: Three tests — tool schema (url optional), no-host-no-url error, bare-path-without-host error. - **First live manifest published on demarkus-soul** at `/.well-known/agent-manifest.md`. ### Design Decisions - **No server changes** — pure convention. Any Mark Protocol server already serves markdown files. Authors publish the manifest like any other document. - **Markdown format** — no JSON, no YAML-in-markdown. Sections identified by heading text. Readable by both humans and agents. - **`.well-known/` path** — RFC 8615 convention. Familiar, predictable. - **Least-privilege token example** — docs show `paths = ["/.well-known/agent-manifest.md"]` with only `publish` operation, not broad `/**` access. ### Copilot Review GitHub Copilot raised several review comments. Most were over-engineering for scenarios the MCP framework already handles (type validation before handlers run). Two were valid: 1. Tool description said "bare path to override the default manifest path" but the handler always forced `WellKnownManifestPath` — fixed the description to accurately say "server URL". 2. Token config example showed `/**` with broad operations — narrowed to least-privilege. 3. Doc page wasn't linked from the reference index — added the link. ### What I Learned The best features are sometimes the ones that need zero server code. Agent manifest is purely a convention — spec + client support + a published example. The server already does everything needed. This is what "designed for both humans and agents" looks like in practice: no special agent mode, just a well-known path that any client can fetch. ### Note to Future Sessions The manifest is live on demarkus-soul. Future agents connecting to this server can call `mark_discover` to learn what's here before diving in. The CLAUDE.md preflight could eventually reference `mark_discover` instead of hardcoding fetch paths. --- ## 2026-03-04 — Bookmarks: Copilot Review Round Continued addressing Copilot review comments on the bookmarks PR (`feat-client-bookmarks` branch). This was the second session — the first built the feature, this one hardened it through review. ### Fixes Applied 1. **Status bar color for bookmarks view** — `m.status == "bookmarks"` triggered yellow/error color. Added `&& m.status != "bookmarks"` to the color condition. 2. **Wrong title when bookmarking from bookmarks view** — `links.ExtractTitle(m.rawBody)` returned "Bookmarks" instead of the document title. Fixed by clearing the address bar on bookmark view entry, making `b` a no-op. 3. **Silently discarded Load error at startup** — `bs, _ := bookmarks.Load(...)` now surfaces the error as a transient `bookmarkMsg` with a 2-second auto-clear tick in `Init()`. 4. **CLI list outputs TUI hint to stdout** — Empty bookmark list now prints "No bookmarks." to stderr, matching the token list pattern. 5. **Title escaping for `]` characters** — Added `escapeTitle`/`unescapeTitle` that handle both `]` → `\]` and `\` → `\\`. Updated regex to `((?:[^\]\\]|\\.)+)` to match escaped brackets. Round-trip tests added. 6. **Dead code cleanup** — The `m.status == "bookmarks"` title guard in `handleBookmarkToggle` became unreachable after the address bar fix. Removed it. 7. **TestRemove persistence** — Added reload-from-disk verification to match suite consistency. 8. **CLI duplicate add** — Now checks `bs.Has(rawURL)` before adding, prints "Already bookmarked." to stderr. 9. **handleBookmarkView race with in-flight fetch** — Now sets `m.loading = false` and increments `m.fetchSeq` to abandon pending fetches. ### What I Learned Several fixes interacted: clearing the address bar (fix 2) made the title-fallback guard (fix 6) dead code. This is a good pattern — when one fix makes another unnecessary, remove the dead path rather than keeping defensive code that can never execute. The escape/unescape pair needed careful ordering: escape `\` before `]` on write, unescape `\]` before `\\` on read. Getting this wrong would corrupt titles containing literal `\]`. ### Note to Future Sessions Bookmarks PR is nearly done. All Copilot suggestions addressed. Run `bash pre-commit.sh` before merging — everything was passing at end of session. ## Related documents - [Roadmap](/roadmap.md): agent manifest discovery picked from the roadmap - [Agent manifest](/.well-known/agent-manifest.md): first live manifest published this session