Skip to content

fix(admin,cli,scraping,testing): two admin actions could share a name and dispatch to the wrong one - #178

Merged
sebyx07 merged 1 commit into
mainfrom
fix/admin-cli-scraping-sweep
Aug 19, 2026
Merged

sebyx07 merged 1 commit into
mainfrom
fix/admin-cli-scraping-sweep

Conversation

@sebyx07

@sebyx07 sebyx07 commented Aug 19, 2026 •

Copy link
Copy Markdown
Contributor

Tier 5 slice of a bug sweep.

One AdminAction.name, two handlers

AdminAction.name addresses one handler in three places at once — the MCP tool name
(admin.action.<name>), the default label key, and callAdminTool's lookup. Two actions sharing it
dispatched to whichever .find() reached first: a call that succeeds against the wrong action and
reports nothing
.

Nothing refused it until adminMcp() was called, so an app that renders the dashboard and never
wires MCP shipped the ambiguity silently. Refused at defineAdmin now — X_ADMIN_ACTION_DUPLICATE,
row added to wiki/Error-Codes.md, manifest regenerated on this branch (453 codes).

Deduplicated by identity, not name: defineAdmin attaches input.actions to the entity each one
names and appends resources[<entity>].actions, so an author who spelled the same object in both
meant one action, not two.

x g migration has never existed

It shipped in two @ultimat3/admin fix: lines. An operator whose admin list named a dropped
column pasted it and got X_CLI_UNKNOWN_COMMAND on top of the bug they already had. The migration
writer is x db gen "<description>".

It passed the errors gate because a command with no subcommands must still declare
positionalChoices, or its second word is unjudged
— fix-command.ts returns undefined for an
absent set. cmd-generate.ts now declares positionalChoices: GENERATORS, from the same constant
readKind validates against, exactly as cmd-test.ts declares TEST_TYPES. fix-command.test.ts
pins x g migration as a finding against the real catalog. Third instance of this class (#131, then
x db branch <name>); the rule is now written down in packages/cli/CLAUDE.md.

The rest

Fix What was wrong
cli/fix-command.ts the citation regex ended a word at :, so x g admin:page — the CLI reference's one admin-page line — was read as x g admin and reported as a standing false finding on an invocation that runs. A : now joins a word only when a letter follows, so x db migrate: the release phase still cites x db migrate
cli/cmd-generate.ts the conflict fix: was x g --force, itself X_CLI_UNKNOWN_COMMAND when run. A fix: is pasted verbatim, and the conflict path has the caller's own invocation in hand
scraping/robots-fetch.ts (new) the production /robots.txt read — the one scrape-run.ts always takes, since it builds the gate with no fetchText — had no deadline, no size cap and no proxy. Every existing gate test injected a fetchText, which is how a read that could park a run forever stayed green. The gate caches one promise per origin, so a hung origin parked every later navigation to that origin, past ctx.signal, the watchdog and the job timeout
scraping/robots.ts patternMatches walks the pattern instead of compiling it, so a wildcard-dense rule from a scraped site is linear rather than catastrophic backtracking on the worker's only thread
admin/widget-value.ts, admin/resource.ts, testing/matchers.ts, cli/i18n-audit.ts, cli/mcp-host.ts, cli/dev-runtime.ts smaller fixes, each with a test that fails without it

Gate

bun run verify — 14/17 green, 3 skipped as always.

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

@coderabbitai

coderabbitai Bot commented Aug 19, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your current included review allowance is based on your included PR review attempts over the past 7 days.

Next review available in: 45 minutes

Limit details: You’ve used the included review currently available. Your 72 included PR review attempts over the past 7 days set your current allowance at 1 review per hour.

You can run this review on demand instead of waiting.

On-demand reviews are free until September 18, 2026. After that, they cost $0.25 per reviewed file.

  • Run review for free
How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 33d13dc1-75c5-49cc-afa8-1392d53f4126

📥 Commits

Reviewing files that changed from the base of the PR and between 77ffd30 and ce3c39e.

📒 Files selected for processing (30)
  • framework.manifest.json
  • packages/admin/CLAUDE.md
  • packages/admin/src/admin.ts
  • packages/admin/src/errors.ts
  • packages/admin/src/index.ts
  • packages/admin/src/mcp.test.ts
  • packages/admin/src/resource.test.ts
  • packages/admin/src/resource.ts
  • packages/admin/src/widget-value.test.ts
  • packages/admin/src/widget-value.ts
  • packages/cli/CLAUDE.md
  • packages/cli/src/cmd-generate.test.ts
  • packages/cli/src/cmd-generate.ts
  • packages/cli/src/dev-runtime.ts
  • packages/cli/src/fix-command.test.ts
  • packages/cli/src/fix-command.ts
  • packages/cli/src/i18n-audit.ts
  • packages/cli/src/mcp-host.ts
  • packages/scraping/CLAUDE.md
  • packages/scraping/src/clock-discipline.test.ts
  • packages/scraping/src/index.ts
  • packages/scraping/src/robots-fetch.test.ts
  • packages/scraping/src/robots-fetch.ts
  • packages/scraping/src/robots.test.ts
  • packages/scraping/src/robots.ts
  • packages/scraping/src/scrape-run.ts
  • packages/testing/CLAUDE.md
  • packages/testing/src/matchers.test.ts
  • packages/testing/src/matchers.ts
  • wiki/Error-Codes.md

Comment @coderabbitai help to get the list of available commands.

… and dispatch to the wrong one

`AdminAction.name` addresses one handler in three places at once — the MCP tool name
(`admin.action.<name>`), the default label key, and the key `callAdminTool` resolves a
handler by. Two actions sharing it dispatched to whichever `.find()` reached first: a call
that SUCCEEDS against the wrong action and reports nothing. Nothing refused it until
`adminMcp()` was called, so an app that renders the dashboard and never wires MCP shipped
the ambiguity silently. Refused at `defineAdmin` now (`X_ADMIN_ACTION_DUPLICATE`), by
identity rather than by name — `defineAdmin` attaches `input.actions` to the entity each
one names AND appends `resources[<entity>].actions`, so an author who spelled the same
object in both meant one action.

**`x g migration` has never been a generator**, and it shipped in two `@ultimat3/admin`
`fix:` lines — so an operator whose admin list named a dropped column got
`X_CLI_UNKNOWN_COMMAND` on top of the bug they already had. The real command is
`x db gen "<description>"`. It reached the `errors` gate untouched because `x g` declares
no subcommands and `fix-command.ts` returns `undefined` for an absent positional set; `g`
now declares `positionalChoices: GENERATORS`, from the same constant `readKind` validates
against. Third instance of this class (#131, then `x db branch <name>`).

- `cli/fix-command`: the citation regex stopped a word at `:`, so `x g admin:page` — the
  CLI reference's one admin-page line — cited `x g admin` and was a standing false
  finding on a documented invocation that runs. A `:` now joins a word only when a letter
  follows it, so a sentence ending `x db migrate:` still cites `x db migrate`.
- `cli/cmd-generate`: the conflict `fix:` was `x g --force`, which is
  `X_CLI_UNKNOWN_COMMAND` when run. A `fix:` is pasted verbatim, and the conflict path has
  the caller's own invocation in hand.
- `scraping/robots-fetch`: new file. The production `/robots.txt` read — the one
  `scrape-run.ts` always takes, since it builds the gate with no `fetchText` — had no
  deadline, no size cap and no proxy. Every existing gate test injected one, which is how
  a read that could park a run forever stayed green. The gate caches one promise per
  origin, so a hung origin parked every later navigation to it, past `ctx.signal`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@sebyx07
sebyx07 force-pushed the fix/admin-cli-scraping-sweep branch from d110e08 to ce3c39e Compare August 19, 2026 16:39
@sebyx07
sebyx07 merged commit 50a9755 into main Aug 19, 2026
5 checks passed
@sebyx07
sebyx07 deleted the fix/admin-cli-scraping-sweep branch August 19, 2026 16:43
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