Skip to content

refactor(audiobook-curator): ship the CLI as <tool>.cli.ts projections of the curator tools - #734

Merged
ScriptedAlchemy merged 7 commits into
mainfrom
feat/725-audiobook-cli-dedupe
Sep 7, 2026
Merged

refactor(audiobook-curator): ship the CLI as <tool>.cli.ts projections of the curator tools#734
ScriptedAlchemy merged 7 commits into
mainfrom
feat/725-audiobook-cli-dedupe

Conversation

@ScriptedAlchemy

@ScriptedAlchemy ScriptedAlchemy commented Sep 7, 2026

Copy link
Copy Markdown
Owner

Closes #725.

What

examples/audiobook-curator had two handlers per operation: an MCP tool under src/mcp/curator/tools/ and a routed CLI command under src/cli/, both calling the same src/operations/* function with their own input mapping, confirmation, headline, and progress plumbing. This PR deletes src/cli/ (16 modules, 741 lines) and the bulk routes.mcpCommands: true group, and gives every tool a colocated <tool>.cli.ts projection that owns only what the CLI adds: the command spelling, flag renames (--duration, --cache-dir, --book, --edition, --with-chapters, …), positionals (prepare <plan> <output>), the --regions us,uk list mapping, and confirm: false (the old commands never asked --yes; a mutating command already gates on --apply).

  • One handler per operation: the MCP tool route owns execution and rendering; the projection owns argv. The 16 command names, flag spellings, defaults, required fields, exit codes, and confirmation policy are preserved and pinned by tests.
  • Every CLI/MCP pair was truly equivalent; no aggregate or independent CLI workflow remained, so nothing is left as an explicit src/cli/ route.
  • inputSchema in each tool module is now an inline z.object (the compiler's static argv grammar cannot follow operation.inputSchema; AB4814).
  • Framework: packages/agent-bundle/src/cli-entry.ts defers z.enum choice checks to the canonical schema when the projection exports mapInput, so a mapper can split --regions us,uk; an invalid value still exits 2 as Invalid value for --regions[1]. Fixture + projection test + package-entries.mdx (en/zh) cover it.
  • Workbench: a projected command hangs off its tool leaf (leaf.command) and the CLI group lists the 16 tool leaves under their command spelling; no cli:* identity remains. Route count 50 → 34.

Tests

  • tests/route-unit/cli-dispatch.test.ts: audible-search CLI vs invokeMcpTool parity (one domain call, equal structured result, --duration/--regions us,uk/repeated --regions, invalid region exit 2, unknown option exit 2, defaulted input), convert --apply vs dry run and no --yes prompt, inspect --json routeId, curator <tool> group gone, help output.
  • packages/agent-bundle/tests/examples-contract.test.ts: built bin/audiobook-curator.mjs relocated with sources deleted returns the same inspect result as the MCP client.
  • Workbench surface/e2e tests updated to the tool-leaf identity.

Docs

examples/audiobook-curator/README.md, website/docs/{en,zh}/examples/audiobook-curator.mdx, website/docs/{en,zh}/guide/authoring/package-entries.mdx.

Deletions

src/cli/ 16 files / 741 lines; libraryAuditCliHeadline; cli-rendered.test.ts inventory duplicate; routes.mcpCommands. Net −605 lines.

Local gate (branch contains origin/main @ a2a3fbe, after rebase onto #729)

pnpm install --frozen-lockfile --offline && pnpm build && pnpm typecheck && pnpm lint   # ok
pnpm test:unit                                                     # 4447 passed, 0 failed (rerun after fixes: 4468 passed)
pnpm exec rstest --config rstest.route-unit.config.ts              # 89 passed
pnpm exec rstest --config rstest.projection.config.ts              # 191 passed
pnpm exec rstest --config rstest.integration.config.ts (whole pool) # 1168 passed, 0 failed
pnpm test:packed                                                   # 41 passed
pnpm docs:site:build                                               # parity ok, 0 broken links

After the review fixes (example-only commits): pnpm build && pnpm typecheck && pnpm lint && pnpm test:unit (4468 passed), route-unit (89), examples/audiobook-curator pnpm check, integration subset examples-contract, audiobook-curator.acceptance.e2e, examples-real.e2e, workbench-surface (11 passed), pnpm docs:site:build (0 broken links).

Deslop: Claude, 4 edits (dropped restating // Inline, not operation.inputSchema comments ×14, an orphaned JSDoc, a dead zod import, and the audibleRegionList helper that duplicated the schema's enum check).

Self-review

Reviewer: GPT-5.6 Sol Max (generalPurpose; change-risk-reviewer had no shell/TraceDecay in this session). Two passes.

# Finding Disposition
1 Medium — unused pathSchema / audibleRegionSchema / audibleRegions imports left after deleting the orphaned operation inputSchemas Fixed (e123cef).
2 Low — changeset/docs promise Invalid value for --<option>[<index>], but search_audible.cli.ts threw Unsupported Audible region… from audibleRegionList before the schema ran Fixed: mapper only splits; the tool's z.enum rejects; audibleRegionList deleted; test asserts the promised spelling (e123cef).
3 Low — README said operations keep handler input schemas; docs said "no operation registry" while five handler tables exist Fixed: README rewritten; "no route registry" in en/zh (e123cef).
4 Low — "every projection declares confirm: false" was false for inspect and shelf Fixed: declared explicitly (e123cef).
5 Low (pass 2) — orphaned JSDoc above audibleOperations Fixed (e9a50b0).
Deferred-choices change cannot let an invalid enum through without mapInput; exit code/spelling unchanged for existing projections; inline schemas match handler inputs No findings.

Codex P1s: orphaned operation schemas → deleted (19cecc3); changeset suffix already (#734).

@changeset-bot

changeset-bot Bot commented Sep 7, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: e9a50b0

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
agent-bundle Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 7, 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-09-07T05:09:30.304247Z 0a12602 PR opened
ℹ️ 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: 0a12602d92

ℹ️ 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 examples/audiobook-curator/src/mcp/curator/tools/apply_audiobook_chapters.tsx Outdated
Comment thread .changeset/725-audiobook-curator-cli-projections.md Outdated
@ScriptedAlchemy
ScriptedAlchemy force-pushed the feat/725-audiobook-cli-dedupe branch from 19cecc3 to 35d56c8 Compare September 7, 2026 05:56
@ScriptedAlchemy
ScriptedAlchemy merged commit a2eb7f4 into main Sep 7, 2026
3 checks passed

@ScriptedAlchemy ScriptedAlchemy left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Current-head adoption review — e9a50b0bf653d31fd1afb11ccce6271f86fb8359

The duplication removal is the right implementation of #725. One P2 compatibility/claim correction remains before calling this behavior-preserving. Reviewed the changed-path inventory, shared argv change, projection metadata, migrated tool schemas, deleted CLI paths, parity tests and documentation. No repository or installed-process tests were executed by this reviewer; the full local gate in the PR is author-reported evidence.

P2 — Required report/receipt arguments are not preserved

The summary says the old required fields are preserved, but examples/audiobook-curator/tests/cli.test.ts explicitly changes inventory --report from required to optional and removes receipt from convert's required options. The new convert_audiobook.tsx schema likewise makes receipt optional. The test comment explains this was done because projection flags currently only relax requiredness. That is an intentional observable contract change, not demonstrated equivalence.

It can be a valid product decision to make the canonical tool's optional report behavior the CLI default. Record that decision accurately, including which commands changed and what happens to receipt/report persistence when omitted. Add a deterministic applied-mutation case without a receipt path, alongside a supplied-path case, so successful operation is not accidentally presented as proof that an audit file was written. Alternatively preserve the previous CLI requirement through the smallest supported projection check; do not restore duplicate handlers/schemas or make an optional canonical MCP field required everywhere merely for CLI compatibility.

Update the PR summary and migration/change notes to distinguish preserved command names/mapping/exit policy from relaxed required arguments, removed bulk curator <tool> commands, and formerly plain commands now rendering a document. The README already acknowledges optional report/receipt flags; align the other claims with that rather than deleting this useful honesty.

What is now addressed

  • Equivalent operations have one tool handler and a small .cli.ts projection; domain functions remain ordinary domain code.
  • The orphaned operation input schemas identified by the first review were deleted; do not repeat that as pending work.
  • CSV regions are split by mapInput, with invalid values left for canonical validation. The shared enum defer is scoped to projections declaring mapInput; it is not a general removal of schema validation.
  • Canonical tool identity is retained, and the relocated/source-deleted CLI versus MCP test is the correct proof level.
  • confirm: false preserves the authored CLI's existing explicit-apply policy; this review is not asking to add automatic approval or remove the --apply guard.

The recorded full integration/packed/docsite gates and two self-review passes are substantially stronger than a route-count-only test. Refresh evidence if the head changes again and preserve all negative mapper/unknown-option/exit-code tests. No merge, approval, source change or native-host action is performed by this review.

ScriptedAlchemy added a commit that referenced this pull request Sep 7, 2026
… optional since #734; test both paths (#738)

* docs(audiobook-curator): document optional --report/--receipt migration; test both paths (#725 follow-up)

* changeset: point at #738

* review: report/receipt wording; assert directory contents and identical stderr

* docs: receipt is written when the command succeeds
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.

[P2] Make audiobook-curator's equivalent CLI commands projections of canonical MCP tools, not duplicate handlers

1 participant