Skip to content

mcpx docs: implement the history renderer and release stamping #1865

Open

Description

@dezren39

Relocated from dezren39/darwin-nix#151 on 2026-10-28 (placement audit): mcpx's single source lives in developing-today/code (pkgs/mcpx); re-home tracked at #309. Original body below; issue references inside it are historical (dezren39/nix numbering).

Parent: #98

Summary

Build what #150 decides:

  • the metadata format;
  • migration of the existing docs/story.md key blocks;
  • a preprocessor that renders release markers and nested, closed-by-default <details> histories;
  • the release-workflow step that stamps versions;
  • the CI check that a changed section has an entry;
  • updates to docs/release-runbook.md.

The steps below assume #150's recommended Approach C (explicit section IDs + since/changed metadata + one change fragment per PR + release stamping + git as a check). If #150 lands differently, re-cut this issue.

Original notes

  • documentation
    • make a book using whatever is the most common and simple modern choice
      • 3 main things, not book sections jsut like levels of detail-
        • the compendium
          • new sections marked with release version during release.yaml?
            • edits start a 'history' openable that is just a sideways triangle out of the way, basically hierarchical updates, md para new version/date->bubbles up through h5 h3 h2 root document version history

Current state

  • Metadata that exists. Key blocks in fenced code blocks directly under h2 entries: 59 in docs/story.md, format in docs/release-runbook.md ("Entry format"). Trailing RFC 3339 timestamp per top-level entry. Some h3 sub-sections carry their own trailing timestamp. Document-level key blocks under the h1 in five other docs, and 34 status-only blocks in proposals.md (🎨 Palette: Add ARIA labels and live regions to search panel #150).
  • Missing pieces.
  • Existing constraints.
    • README.md must stay a symlink to docs/story.md (runbook "Checks": test -L README.md && readlink README.md), so any markup added to story.md must also read well on GitHub.
    • internal/settings/docs_test.go:20 and :53 read ../../docs/configuration.md directly.
    • A workflow already commits back to a branch: .github/workflows/mcpx.yml repairs vendorHash and pushes. That is the precedent for a workflow that edits files and commits.
  • Build. package.nix builds only subPackages = [ "cmd/mcpx" ] (package.nix:56). A new Go main elsewhere under pkgs/mcpx would not ship in the mcpx binary unless it is added there.

Steps

  1. Freeze section IDs. For every heading in the documents docs(id): design plan, research, and n0 relay default #152 puts in scope, record today's slug as the explicit ID, so no existing link breaks. Use heading-attribute syntax if chore(deps): update rust crate actix-files to v0.6.10 - autoclosed #117's generator supports it; otherwise an id: key in the key block or <a id> before the heading. GitHub renders {#id} literally, so for story.md (shown as the README) the id: key or <a id> form may be the better choice. Decide in step 2.

  2. Write down the metadata format. It goes in release-runbook.md next to "Entry format":

    • key-block additions id, since, changed;
    • the compact comment form for headings without a key block (<!-- id: pools-lifetime since: 0.2.0 -->);
    • the fragment file format (docs/changes/<slug>.md: sections, kind from Keep a Changelog, summary);
    • the trivial-edit marker (docs:trivial label or Docs-Trivial: yes).
  3. Migrate story.md. A one-off script, reviewed as a normal diff:

    Other docs: some have no key blocks (exec.md, consumer.md, configuration.md, ...), but five open with a document-level block (protocol.md, elicitation.md, plugin-discovery.md, opencode-plugin.md, container.md; the last three lack the required increment/description) and proposals.md has 34 status-only blocks. Several of these statuses are outside the runbook's list (🎨 Palette: Add ARIA labels and live regions to search panel #150, "Key blocks outside story.md"). The migration normalises those per 🎨 Palette: Add ARIA labels and live regions to search panel #150's open question 10. All other docs get IDs at migration and since metadata the first time they are touched, or all at once. See the open questions.

  4. The preprocessor. A small Go program. The repository's code is Go, it runs under go test, and it can serve as an mdBook-style external preprocessor (book JSON on stdin, book on stdout) or be wrapped by whatever hook chore(deps): update rust crate actix-files to v0.6.10 - autoclosed #117 chooses. Responsibilities:

    • Parse headings and skip fenced code. The key blocks are themselves unlabelled fenced blocks, so recognise "a fence directly under a heading (or under the h1 and its lede, for document-level blocks) whose first line is created: or status:" as metadata, not as a code sample. proposals.md's blocks start with status:.
    • Build the heading tree per page, attach since and changed, and compute the bubble-up per 🎨 Palette: Add ARIA labels and live regions to search panel #150's summarisation rule.
    • Emit the release marker (a badge or a line under the heading) and one <details><summary>History -- N changes, latest X (date)</summary> per heading that has history. Leave a blank line after <summary> so the contents parse as markdown. Omit the disclosure where there is no history (note 86: edits start the history).
    • Emit the page-root document history, and the book-root history if 🎨 Palette: Add ARIA labels and live regions to search panel #150 decides on one.
    • Decide how the key block itself renders. Today it is a raw code block in the published output. Options: leave it, reduce it to a status/since line, or hide it.
    • Render the agent twin per Update module github.com/jackc/pgx/v5 to v5.9.2 [SECURITY] #120: no disclosures, one since/status line per section, a link to the history page.
  5. stamp subcommand. Run by the release workflow:

    • replace since: unreleased with the version;
    • fold fragments into each named section's changed: list with version and date, then delete the fragments;
    • write the root/changelog section.

    It is idempotent and fails if a fragment names an unknown section ID.

  6. check subcommand. Run in CI on PRs. It maps the PR's diff hunks onto section ranges and fails when a section's prose changed with no fragment naming it and no trivial marker. It also fails on a duplicate ID, a fragment naming an unknown ID, or a since that is neither unreleased nor a known version. Docs checks run in CI; see the testing trackers under Bump github/codeql-action from 2 to 3 #91 (CI pipeline Bump golang.org/x/crypto from 0.16.0 to 0.17.0 in /sources/launcher #95, integration/environments Bump golang.org/x/crypto from 0.14.0 to 0.17.0 in /sources/chat #97).

  7. Release step in amd host fails at evaluation: no outputHashes for p2panda-core-0.7.1 #158.

    • Order: stamp -> commit -> tag that commit -> build -> publish, so the tagged tree contains the stamped docs.
    • amd host fails at evaluation: no outputHashes for p2panda-core-0.7.1 #158 recommends GoReleaser run by release.yaml on a tag push. If stamping ran inside that tag-triggered job, the tag would point at an unstamped tree. The fix is to split the release in two:
      • a small "cut release" workflow_dispatch job with a version input runs stamp, commits, and pushes the tag;
      • the tag push then triggers release.yaml / GoReleaser unchanged.
    • The stamping commit goes to main the way mcpx.yml's vendorHash repair already pushes, or through a PR if branch protection forbids direct pushes.
  8. Update docs/release-runbook.md.

    • Per-commit: add "add a change fragment naming the section IDs you changed, or mark the PR trivial".
    • Per-release: step 1 ("Confirm every entry touched since the last release has a current last-updated and a bumped increment") is replaced by the check step; step 4 also sets since; add "run stamp" before tagging.
    • Entry format: document id, since, changed and the compact form.
    • Checks: add the check command.

Approaches (where the tool lives)

The design choice belongs to #150. The one implementation choice left is where the renderer lives.

  • A -- inline script in the workflow (least recommended). awk or shell over the markdown inside release.yaml and the Pages workflow. Nothing to package, but it is untestable, it duplicates the parser between render, stamp and check, and it cannot run locally before a push.
  • B -- a generator-native plugin. A Rust mdBook preprocessor crate, or a Python MkDocs plugin. It integrates tightly and uses the generator's own markdown parser. But it ties the history to one generator: if chore(deps): update rust crate actix-files to v0.6.10 - autoclosed #117 changes, the history is rewritten. It also adds a second language to a Go repository, and the stamp and check commands would still be needed outside the generator.
  • C -- one standalone Go program with render, stamp and check (recommended). It lives beside mcpx (for example under pkgs/mcpx/tools/docs-history/) with its own go test suite. It is exposed to the generator through the generator's external-command hook. A single parser serves all three jobs, so render, stamp and check cannot disagree. It is independent of the generator choice and runs locally. It stays out of the shipped binary unless added to subPackages, which it should not be.

Open questions

  1. Heading-ID syntax that works both in the generator and on GitHub (story.md is the README). Is it {#id} or <a id>?
  2. Do docs without key blocks get since metadata all at once at migration, or lazily on first edit?
  3. How should the key block render in the published book?
  4. Does the stamping commit push to main directly or open a PR?
  5. Does the check run on every PR touching pkgs/mcpx/docs/** only, or on every file in docs(id): design plan, research, and n0 relay default #152's scope, including root-level ASSESSMENT.md, OPENCODE-V2.md and AGENTS.md?

Ease · Impact · Related

Ease L · Impact med · Depends on / related: #150 (design), #117 (generator hook), #158 (release workflow), #118 (build and deploy), #120 (agent twin), #152 (scope of documents), #49 (CI for every package).

Security/auth deferred; see tracker.

Activity

  1. developing-today commented on Oct 28, 2026

    @developing-today
    Contributor
  2. dezren39 commented on Oct 28, 2026

    @dezren39
    MemberAuthor

    History carried over from dezren39/darwin-nix#151 (verbatim, oldest first):


    @dezren39 · 2026-09-30T07:20:39Z

    Integration pass. Placed in the DAG rooted at #181.


    @dezren39 · 2026-09-30T11:49:17Z

    Issues pass (2026-09-30, at 05c78b2).

    • Corrected step 3. It said "Other docs (protocol.md, exec.md, elicitation.md, ...) have no key blocks". protocol.md and elicitation.md do, as do plugin-discovery.md, opencode-plugin.md and container.md, and proposals.md has 34 status-only blocks (see 🎨 Palette: Add ARIA labels and live regions to search panel #150). The migration now normalises them.
    • Step 4's parser rule now also recognises document-level blocks and blocks that start with status:. Otherwise proposals.md's blocks would render as code samples.
  3. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · cross-reference from #1863 triage (queue task 2751, 2026-10-29)

  4. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Oct 29, 2026
  5. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  6. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done — triage verdict: scope CONFIRMED; design #1863's forwarded questions SETTLED below with reasons; ungated core routed as queue task 3081, release wiring recorded as SET-REMAINDER gated on #1881

  7. added
    queue/queuedHas a queued task in the Supabase agent queue
    and removed on Oct 29, 2026
  8. 130 remaining items

  9. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

    • Agent: fleet monitor (repo-fleet-monitor)
    • Session / ID: task 7938 · repo-fleet-monitor run 2026-11-03 20:12 CST
    • Found via: monitor reconciliation
    • Task: Claim evaporated — task 7938 returned to queued and unclaimed in repo-health-code-pilot after the holding run ended without a terminal verb (checkpoint stage: handed_off). Labels reset to the truth: queue/queued + status/needs-triage. The task cap was also raised this run where it had sat dead-in-queue, so it is claimable again.
    • Expectation: next claimant picks up from the checkpoint stage named above.
  10. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · bound

  11. added
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 4, 2026
  12. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    state: picked-up (resume)
    queue: repo-health-code-pilot
    task: 7938 (small_fix, worker repo-worker-code, lane 262eb403-3347-4a7c-ba6b-e7bc263ca853)
    by: openchamber-scheduled-lane
    at: 2026-11-04T04:18Z

    Resumed task 7938 from the CI-wait handoff. Fresh issue state: #1865 OPEN; PR #5208 is the linked implementation for this task and remains OPEN. Checks are green on head fdf2498; the PR author is dezren39 (repo owner), so I will not modify, respond on, or merge this PR under the no-touch rule for owner-owned PRs. I’m routing the remaining review/merge decision to the owner rather than duplicating the implementation.

  13. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    state: blocked (escalated to owner)
    queue: repo-health-code-pilot
    task: 7938 (small_fix, worker repo-worker-code, lane 262eb403-3347-4a7c-ba6b-e7bc263ca853)
    by: openchamber-scheduled-lane
    at: 2026-11-04T04:19Z

    The implementation PR #5208 is already open on head fdf249866cff0fa4baf23f844278f2a1ece59d45; fresh checks are green and the PR still has one unresolved review item. The PR is authored by dezren39 (repo owner). Per the no-touch rule for Drew-owned PRs, this lane will not inspect or modify its diff/review threads, reply, or merge. Escalating the remaining review disposition and merge decision to the owner; task is blocked until the owner handles the PR. Resume by revalidating PR #5208 and completing the queue task after the owner’s disposition. Existing branch: queue/7938-1865-docs-history-render; no worktree was created in this resume.

  14. added
    queue/blockedQueue or user escalation state
    status/blockedQueue or user escalation state
    user/escalatedQueue or user escalation state
    and removed
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    on Nov 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

queue/blockedQueue or user escalation statesource/creatorFiled by the new-issue-creator jobstatus/blockedQueue or user escalation statetask/triageQueue packet kind: verify, reproduce, and route this itemuser/escalatedQueue or user escalation state

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions