feat(mcp): generate manual SYNOPSIS blocks from the tool registry - #1393
Conversation
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>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 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".
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>
There was a problem hiding this comment.
💡 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".
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>
There was a problem hiding this comment.
💡 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".
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>
There was a problem hiding this comment.
💡 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".
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>
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(inbasic_memory.man) renders a tool's call from the JSON schema clients actually receive: required parameters first as bare names, thenname=default, both in schema order, wrapped to the code-block width.scripts/update_man_pages.py/just man-regenrewrites the MCP SYNOPSIS block on every section-3 page whose tool this build registers, and flips the page'sgenerated:field toregistry— the ownership splitdocs/manual-pages.mdalready defines. Curated sections (DESCRIPTION, PARAMETERS, EXAMPLES, GOTCHAS, SEE ALSO) are never touched. Hosted-only pages (cloud-info(3)) stayhand— there's no local schema to render from.just man-regenfails CI with a pointer at the fix. A second test pins thegenerated:ownership split.basic-memory-diagnostics(3)— the one registered tool without a page.TOOLS_WITHOUT_PAGESis now empty; the section-3 corpus and the tool registry match one-to-one.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.mdupdated). 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 corpusruff/ty/pyrightclean🤖 Generated with Claude Code
https://claude.ai/code/session_014pmKq6bqCi6Zp6BTHuZjrp