Skip to content

feat(mcp): generate manual SYNOPSIS blocks from the tool registry - #1393

Merged
phernandez merged 5 commits into
mainfrom
feat/610-man-registry-generator
Aug 30, 2026
Merged

feat(mcp): generate manual SYNOPSIS blocks from the tool registry#1393
phernandez merged 5 commits into
mainfrom
feat/610-man-registry-generator

Conversation

@phernandez

Copy link
Copy Markdown
Member

Third slice of #610, following #1389.

What

The MCP SYNOPSIS block on every section-3 manual page is now generated from the tool registry instead of hand-written, and the manual gains its missing page.

  • render_synopsis (in basic_memory.man) renders a tool's call from the JSON schema clients actually receive: required parameters first as bare names, then name=default, both in schema order, wrapped to the code-block width.
  • scripts/update_man_pages.py / just man-regen rewrites the MCP SYNOPSIS block on every section-3 page whose tool this build registers, and flips the page's generated: field to registry — the ownership split docs/manual-pages.md already defines. Curated sections (DESCRIPTION, PARAMETERS, EXAMPLES, GOTCHAS, SEE ALSO) are never touched. Hosted-only pages (cloud-info(3)) stay hand — there's no local schema to render from.
  • The drift test tightens from "SYNOPSIS names every schema parameter" to byte equality with the rendering; a tool change without just man-regen fails CI with a pointer at the fix. A second test pins the generated: ownership split.
  • basic-memory-diagnostics(3) — the one registered tool without a page. TOOLS_WITHOUT_PAGES is now empty; the section-3 corpus and the tool registry match one-to-one.
  • All 20 registered-tool pages regenerated (schema order replaces hand order); the second generator run is a no-op.

Why

Eight rounds of Codex review on #1389 kept finding the same defect class: a hand-written SYNOPSIS disagreeing with the shipped tool (delete_notes, output_format, replace_subsections, workspace, …). This makes that class structurally impossible: the block is rendered from the registry and CI holds the shipped bytes equal to the rendering. Review effort on manual pages now goes where hands are needed — EXAMPLES and GOTCHAS.

This completes the "registry generator" roadmap item for SYNOPSIS (docs/manual-pages.md updated). PARAMETERS-from-schema and section-1-from-Typer remain future slices.

Verification

  • uv run pytest tests/test_man_pages.py tests/mcp/test_man_resources.py tests/cli/test_man_command.py — all green, including byte-equality across the corpus
  • Generator run twice: second run reports "all pages already match the registry"
  • ruff / ty / pyright clean

🤖 Generated with Claude Code

https://claude.ai/code/session_014pmKq6bqCi6Zp6BTHuZjrp

Third slice of #610. Eight rounds of review on #1389 kept finding the
same class of defect: a hand-written SYNOPSIS disagreeing with the
shipped tool. Make that section mechanical:

- basic_memory.man gains render_synopsis (the MCP call rendered from the
  JSON schema clients receive: required parameters first, then defaults,
  in schema order, wrapped to the block width) plus extract/replace
  helpers for the MCP SYNOPSIS block.
- scripts/update_man_pages.py (`just man-regen`) rewrites the block on
  every section-3 page whose tool this build registers and flips the
  page's generated: field to registry. Curated sections are never
  touched; pages for tools this build does not register (cloud_info)
  stay hand-owned.
- The drift test tightens from name-set equality to byte equality with
  the rendering, failing with a pointer at `just man-regen`. A new test
  pins the generated:-field ownership split.
- All 20 registered-tool pages regenerated; the second run is a no-op.
- New page: basic-memory-diagnostics(3), closing the one gap between the
  section-3 corpus and the tool registry (TOOLS_WITHOUT_PAGES is now
  empty). DESCRIPTION and GOTCHAS hand-written from the source; example
  output from a real local run.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014pmKq6bqCi6Zp6BTHuZjrp
Signed-off-by: phernandez <paul@basicmachines.co>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 30, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-08-30T19:48:13.208164Z 398d349 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e460c70340

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/update_man_pages.py Outdated
Codex on #1393: the ownership substitution ran over the whole page, so a
curated body containing a literal 'generated: hand' line (a YAML example)
could be rewritten once the frontmatter already said registry. The flip
now lives in basic_memory.man as declare_registry_ownership, operates on
the frontmatter block only, and is covered by a test with a decoy line
in the body.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014pmKq6bqCi6Zp6BTHuZjrp
Signed-off-by: phernandez <paul@basicmachines.co>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5626d0f007

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/basic_memory/man/__init__.py
Codex on #1393: extract_mcp_synopsis's ValueError path was only covered
via replace_mcp_synopsis; assert it directly so basic_memory.man stays at
100% coverage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014pmKq6bqCi6Zp6BTHuZjrp
Signed-off-by: phernandez <paul@basicmachines.co>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 67b2059238

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/basic_memory/man/__init__.py Outdated
Codex on #1393: a string default containing a newline or tab was embedded
literally, producing an unterminated two-line literal in the rendered
call. String defaults now go through json.dumps, whose double-quoted
output escapes control characters and is also a valid Python literal.
Output for every current tool is unchanged (regen is a no-op).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014pmKq6bqCi6Zp6BTHuZjrp
Signed-off-by: phernandez <paul@basicmachines.co>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 823cc651c6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/basic_memory/man/__init__.py Outdated
Codex on #1393: a parameter with a Pydantic default factory has neither a
schema default nor a required entry, so the renderer showed it as a bare
name — indistinguishable from required. Such parameters now render as
name=..., Python's own spelling for 'optional, default computed'. Current
corpus unchanged (regen stays a no-op).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014pmKq6bqCi6Zp6BTHuZjrp
Signed-off-by: phernandez <paul@basicmachines.co>
@phernandez
phernandez merged commit 8bde8f5 into main Aug 30, 2026
32 checks passed
@phernandez
phernandez deleted the feat/610-man-registry-generator branch August 30, 2026 21:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant