Skip to content

feat(cli): make the automation surface machine-readable - #361

Merged
prisis merged 13 commits into
alphafrom
integrate/wave-20
Aug 8, 2026
Merged

feat(cli): make the automation surface machine-readable#361
prisis merged 13 commits into
alphafrom
integrate/wave-20

Conversation

@prisis

@prisis prisis commented Aug 8, 2026

Copy link
Copy Markdown
Member

Four related changes to the surface an automated consumer — a CI job, a coding agent, a deploy pipeline — actually talks to. The capabilities were mostly already here; the machine-readable edges were inconsistent.

What changes

lunora doctor becomes consumable. It was the only preflight command with options: [] and findings identified solely by an English sentence. Now --format json with an { ok, code, summary, findings } envelope, a required code on every finding drawn from a 17-entry literal union (a typo fails lint:types), and a new cli-shadowed check for a global binary shadowing the project's. The docs table is the fixture — a test parses the code column out of docs/index.mdx and asserts it equals DOCTOR_CODES, so adding a code without documenting it fails the suite.

lunora deploy reports what it deployed. It already parsed the deployed URL out of wrangler's output, but the gate turned that off for --format json and --preview — the two paths automation uses. DeployCommandResult now carries deployment (url, workerName, env, dryRun, preview, deployedAt); json mode captures via captureStdoutSilently and replays wrangler's log to stderr so stdout stays exactly one document. Links refresh on every real deploy: write when absent, no-op when equal, warn-and-keep when different — a stale link silently misrouting --migrate at a decommissioned URL is worse than the overwrite it avoids. New --health-check probes /_lunora/health/ready (falling back to the aggregate) with a bounded retry before --migrate runs; verify now shares that probe.

MCP gains the reads an agent needs to debug. It could call a deployment but not see what happened. Five token-gated read tools — lunora_get_logs, _get_issues, _get_advisories, _get_query_insights, _get_migration_status — plus outputSchema/structuredContent alongside the retained text block. These are read-only but privileged, so they are omitted from ListTools without an admin token and refused at dispatch, independent of --allow-writes.

The deployed Worker gets weighed. Nothing measured it. lunora build now reports raw + gzip size (gzipSync reproduces wrangler's own Total Upload line to the byte), and a worker-size CI job gates a reference template against a committed baseline. It is its own job, deliberately not in postinstall, where one failure turns every job red in its setup step.

BREAKING CHANGE

lunora build --format json now emits its own result document instead of deploy's. There was nowhere to put the size field otherwise. Consumers reading build's json output see a different shape.

Notable findings

35% of a hello-world Worker is an English NLP library. @visulima/redact hard-depends on compromise@^14.15.1 — 606 KiB raw in the bundle, larger than any first-party package — reached from packages/observability/src/request-log.ts:30. Every app carries it. Not fixed here; recorded as a follow-up.

A reference worker measures 412.9 KiB gzipped against a 3 MB Free / 10 MB Paid ceiling — 13.4%. That is why only the CI gate shipped and the planned user-facing warning was dropped: it would have been an alarm nobody could legitimately trip, at a threshold nobody could justify.

Three of the four plans were wrong about something, corrected in-flight and recorded in plans/README.md. The one worth repeating: the planned pnpm shadow-detection would have warned on every pnpm project, because pnpm writes a shell shim where the design assumed a symlink.

Verification

Run against the merged tree, not the individual branches:

CLI        88 files / 1203 tests passed
MCP        11 files /  181 tests passed
api:check  47/47 snapshots
lint:types clean (cli + mcp)

dist:check's jsxDEV findings reproduce on untouched alpha — a dev-vs-prod build artifact, not from this branch.

🤖 Generated with Claude Code

https://claude.ai/code/session_01KBeSX2o4sTCPjVDRDWkVQG

Summary by CodeRabbit

  • New Features

    • Added optional post-deployment health checks with retries and readiness-route fallback.
    • Added structured JSON output for lunora doctor and lunora deploy.
    • Added stable diagnostic codes and clearer environment diagnostics.
    • Added read-only observability tools for logs, issues, advisories, query insights, and migration status, protected by admin tokens.
    • Improved deployment URL reporting and automatic project linking.
    • Added automated Worker bundle size checks against compressed and raw size limits.
  • Documentation

    • Documented Worker size limits, health checks, JSON output, deployment linking, and observability tools.

prisis and others added 8 commits August 8, 2026 02:22
`lunora doctor` was the only project-preflight command with no options and
no identifier on its findings, so an agent or CI job had to scrape English
prose off stderr to learn what was wrong — and the prose is not a contract.

Every finding now carries a stable kebab-case `code` drawn from a single
`DOCTOR_CODES` const, and `--format json` emits the findings as one JSON
document on stdout (`{ ok, code, summary, findings }`) with the human report
routed to stderr, the same envelope `deploy` and `verify` already use. Exit
codes and the default pretty output are unchanged. `pass`-level findings are
included so the document describes everything that was checked, not only what
failed.

Adds a `cli-shadowed` check: a globally-installed `lunora` running against a
project with its own pinned install makes every other finding describe a
project this CLI may be the wrong version for, and no existing check can see
it — the version-skew check reads the manifest, which is exactly the file the
shadowing binary ignores. The comparison asks whether the running module lives
inside the project's installed CLI package rather than comparing bin paths,
because pnpm writes `node_modules/.bin/*` as a shell shim rather than a
symlink, and path equality would warn on every pnpm project.

The code table in the CLI docs is asserted against `DOCTOR_CODES` by a test,
so a new or renamed code cannot ship undocumented.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBeSX2o4sTCPjVDRDWkVQG
`lunora deploy --format json` returned a document that could not tell a
caller where the thing it just deployed lives, and `--preview` told the
operator to "see the preview URL in the wrangler output above" — a
machine-readable command handing its answer back to a human to read with
their eyes. The URL parser already existed; the gate that enabled it was
off in exactly those two cases.

- `DeployCommandResult.deployment` carries `{ deployedAt, dryRun, env?,
  preview, url?, workerName? }` on every run that reached wrangler. No
  version id: the pinned wrangler has no structured deploy output, and
  the id only appears in prose.
- Capture wrangler's stdout on every publishing run — with
  `captureStdoutSilently` in json mode (replayed to stderr afterwards),
  so stdout stays exactly one JSON document.
- Re-check the link on every real deploy instead of only the first: a
  changed URL used to leave a stale link that `run`/`logs`/`--migrate`
  silently targeted. An existing link is never rewritten — a mismatch
  warns and names the `lunora link --url` to run. `--temporary` writes
  no link (that account is gone in an hour).
- New `--health-check`: after a live deploy, probe
  `/_lunora/health/ready` (falling back to the aggregate route), 5
  attempts 2s apart, before any `--migrate`. A red probe exits non-zero
  and says the deploy succeeded and the probe did not.
- Extract the probe to `util/health-probe.ts`; `verify --health-url`
  now shares it, unchanged in behaviour.

BREAKING CHANGE: `autoLinkFromDeployOutput` takes the parsed `url`
instead of raw wrangler `output`, and `HealthFetch` moved from
`commands/verify/handler` to `util/health-probe`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBeSX2o4sTCPjVDRDWkVQG
Nothing measured how large the Worker a user deploys is, so the first
signal of a size regression would have been Cloudflare rejecting someone's
deploy for a dependency added weeks earlier.

`lunora build` now reports what it wrote — raw and gzipped, counting only
the files that are uploaded (the sourcemap and the esbuild metafile in the
same out-dir are not) — as a line of pretty output and a `bundle` field in
the `--format json` document. Measuring never changes the exit code. An
out-dir with nothing uploadable in it warns instead of reporting 0 bytes,
since a silent zero is what a changed wrangler layout looks like.

`scripts/check-worker-size.js` builds `templates/standalone` against the
workspace and fails when it exceeds the ceiling committed in
`worker-size.json` (422,840 B gzipped + a 50 KiB allowance), naming the
delta and pointing at `pnpm run worker-size:update`. It runs as its own
`worker-size` job in test.yml, not from postinstall.

BREAKING CHANGE: `lunora build --format json` now prints the build result
rather than the deploy result — same fields, plus `bundle`.

Measured for the baseline: 1684.9 KiB raw / 412.9 KiB gzipped, against
Cloudflare's 3 MB (Free) and 10 MB (Paid) compressed script limits.
An agent could call a deployment but not see what happened: no logs, no
grouped errors, no advisories, no query insights, no migration status.
Every one already existed as an admin RPC backing the Studio and the CLI;
only the MCP surface over them was missing.

Adds five read tools — lunora_get_logs, lunora_get_issues,
lunora_get_advisories, lunora_get_query_insights,
lunora_get_migration_status — as a third tier. They are read-only but
PRIVILEGED (production log lines and error messages reach the model's
provider), so they are exposed only when an admin token resolved: omitted
from ListTools without one, and refused at dispatch, the same
omit-don't-refuse rule the write gate uses. The tier is independent of
--allow-writes, which is about changing data, not reading operational
data. In the composed local server the advertised list is a build-time
snapshot of the resolved deployment's token (fail-closed), while dispatch
re-checks the live one.

Op paths come from ADMIN_FUNCTIONS rather than hand-written
"__lunora_admin__:" literals, so a renamed op cannot ship a 404 to one
consumer and not another; @lunora/shard-engine becomes a dependency for
that constant. The reads go through client.query, since these ops ride
the ordinary /_lunora/rpc envelope — the bearer, error envelope and wire
decode are all the client's existing behaviour.

Tool results now carry structuredContent described by each tool's
outputSchema, alongside the existing text block so clients on an MCP
revision older than 2025-06-18 are unaffected. structuredContent is
serialized by the transport, so it goes through the same bigint -> string
and bytes -> base64 mapping the text block already used; an unmapped
bigint there would fail the whole response rather than one field.

BREAKING CHANGE: toolDefinitions and callTool take an additional
hasAdminToken argument (defaulting to false, so existing callers keep the
read-only surface they had).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBeSX2o4sTCPjVDRDWkVQG
All four wave-20 plans shipped. Per the plans/ convention the plan
files are removed once complete; the index carries what shipped, what
each plan got wrong, and the follow-ups the wave opened.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBeSX2o4sTCPjVDRDWkVQG
@netlify

netlify Bot commented Aug 8, 2026

Copy link
Copy Markdown

Deploy Preview for lunorash ready!

Name Link
🔨 Latest commit a2f54dd
🔍 Latest deploy log https://app.netlify.com/projects/lunorash/deploys/6a76c9ec571d990008664f35
😎 Deploy Preview https://deploy-preview-361--lunorash.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Thank you for following the naming conventions! 🙏

@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Thank you for confirming the Contributor License Agreement! 🙏

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@prisis, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 1 minute

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

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 for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: c87d9ff6-47e4-4320-b32a-b4c3bbfe2d78

📥 Commits

Reviewing files that changed from the base of the PR and between bf34e65 and a2f54dd.

📒 Files selected for processing (3)
  • .github/file-filters.yml
  • packages/cli/docs/index.mdx
  • packages/cli/src/commands/verify/handler.ts

Walkthrough

The CLI adds deploy health checks, deployment metadata, URL linking updates, and structured doctor output. MCP adds admin-token-gated observability tools. CI adds a Worker size budget check and related documentation.

Changes

CLI deployment flow

Layer / File(s) Summary
Shared health probing
packages/cli/src/util/health-probe.ts, packages/cli/src/commands/verify/handler.ts
Adds reusable readiness and health probing with retries, fallback routes, and injectable transport functions.
Deploy completion and health checks
packages/cli/src/commands/deploy/...
Captures deploy output, records deployment identity, runs optional health checks before migrations, and reports health failures separately.
Deployment URLs and linking
packages/cli/src/util/auto-link.ts, packages/cli/src/util/deploy-summary.ts
Parses current deployment URLs, revalidates links, preserves mismatches, and uses current URLs in summaries.
Deployment CLI documentation
packages/cli/docs/index.mdx
Documents health checks, links, previews, structured output, and CI URL extraction.

CLI doctor diagnostics

Layer / File(s) Summary
Diagnostic result contract
packages/cli/src/commands/doctor/handler.ts
Adds stable finding codes, status fields, severity counts, and executable-path configuration.
CLI-shadow detection and aggregation
packages/cli/src/commands/doctor/handler.ts
Detects non-local CLI executables and aggregates doctor findings by severity.
Doctor command output
packages/cli/src/commands/doctor/handler.ts, packages/cli/src/commands/doctor/index.ts, packages/cli/docs/index.mdx
Adds validated pretty or JSON output and documents the diagnostic contract.

MCP observability tools

Layer / File(s) Summary
Tool schemas and result contracts
packages/mcp/src/tool-types.ts, packages/mcp/src/tool-result.ts
Adds output schemas, structured content, JSON-safe serialization, and shared result helpers.
Observability tool definitions and dispatch
packages/mcp/src/observability-tools.ts, packages/mcp/package.json
Adds five read-only tools with input validation, shard routing, filtering, pagination, and RPC dispatch.
Admin-token advertisement and enforcement
packages/mcp/src/tools.ts, packages/mcp/src/server.ts, packages/mcp/src/local.ts, packages/mcp/src/index.ts
Gates observability tool advertisement and execution on admin-token availability.
MCP observability documentation
packages/mcp/README.md, packages/cli/src/commands/mcp/index.ts
Documents privileged tools, token requirements, structured output, limits, and shard reads.

Worker size budget

Layer / File(s) Summary
Worker size measurement and enforcement
scripts/check-worker-size.js
Builds a temporary reference project, measures bundle sizes, updates baselines, and enforces the gzipped ceiling.
Worker size CI gate
.github/file-filters.yml, .github/workflows/test.yml
Runs the size check for relevant path changes and adds it to required checks.
Worker size documentation
apps/docs/src/content/docs/deployment.mdx
Documents Worker size limits, measurements, excluded artifacts, and investigation steps.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the primary change: making CLI and related automation surfaces machine-readable.
Description check ✅ Passed The description provides a detailed summary, breaking-change notice, verification results, follow-ups, and scope across the affected surfaces.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch integrate/wave-20

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai 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.

Actionable comments posted: 6

🧹 Nitpick comments (2)
packages/cli/docs/index.mdx (1)

184-185: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the blank line before this bullet.

Line 183 is blank and separates this bullet from the list above it. The list stays intact, but Markdown renders it as a loose list, so this item gets extra vertical spacing that the other items do not have.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli/docs/index.mdx` around lines 184 - 185, Remove the blank line
immediately before the “CLI shadowing” bullet so it remains contiguous with the
preceding Markdown list and renders consistently with the other items.
packages/cli/src/commands/verify/handler.ts (1)

96-99: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use probe.url in the success message.

probeHealth returns the URL the verdict came from. Line 99 rebuilds the same URL with joinHealthUrl. The two agree only while verify keeps the default paths. Read the value the probe reports instead, and the joinHealthUrl import can be dropped.

♻️ Proposed refactor
-        logger.success(`verify: health probe ok (${joinHealthUrl(options.healthUrl)})`);
+        logger.success(`verify: health probe ok (${probe.url})`);

Then update the import at line 14:

-import { joinHealthUrl, probeHealth } from "../../util/health-probe";
+import { probeHealth } from "../../util/health-probe";
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli/src/commands/verify/handler.ts` around lines 96 - 99, Update the
success message in the verify handler to use the URL returned by probeHealth via
probe.url instead of rebuilding it with joinHealthUrl, and remove the now-unused
joinHealthUrl import.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/test.yml:
- Around line 318-321: Add the worker-size-related paths
scripts/check-worker-size.js, worker-size.json, and .github/workflows/test.yml
to an existing packages/templates filter in .github/file-filters.yml, or create
a dedicated size-specific filter and wire it into the worker-size job’s if
condition so changes to any of these files run the gate.

In `@packages/cli/docs/index.mdx`:
- Around line 365-373: Update the CI shell snippet around the lunora deploy
command to enable strict failure handling with set -euo pipefail, then validate
the extracted deployment URL before invoking curl. Ensure a failed deploy or
missing/invalid deployment.url causes the pipeline to stop at the deploy/URL
validation step rather than requesting a null smoke-test URL.
- Around line 201-219: Make the JSON example self-consistent by changing its
fence to jsonc and adding a trailing comment entry in the findings array
indicating that the pass- and info-level findings are omitted, matching the
truncated deploy example pattern while preserving the summary counts.

In `@packages/cli/src/util/health-probe.ts`:
- Around line 105-125: Update the default fetch implementation in probeHealth to
enforce a per-attempt timeout using AbortSignal.timeout, while preserving any
caller-provided fetchImpl unchanged. Pass the timeout signal through the global
fetch call and use the existing probe timeout configuration or an appropriate
bounded duration so stalled requests abort and continue through probeOnce’s
transport-error handling.

In `@packages/mcp/README.md`:
- Around line 84-88: Update the README tool-parameter description around
lunora_get_migration_status to exclude migration status from the statement that
tools accept a limit. Document that migration status accepts only shardKey and
intentionally returns all migrations, while preserving the existing limit and
per-shard behavior for the other tools.

In `@scripts/check-worker-size.js`:
- Around line 143-169: Update scripts/check-worker-size.js lines 143-169 to add
an independent hard-failure check for bundle.rawBytes against Cloudflare’s 64 MB
pre-compression limit, without relying on the gzip ceiling check. Update
apps/docs/src/content/docs/deployment.mdx lines 150-169 to document the 64 MB
raw limit and instruct users to check both raw and gzip measurements.

---

Nitpick comments:
In `@packages/cli/docs/index.mdx`:
- Around line 184-185: Remove the blank line immediately before the “CLI
shadowing” bullet so it remains contiguous with the preceding Markdown list and
renders consistently with the other items.

In `@packages/cli/src/commands/verify/handler.ts`:
- Around line 96-99: Update the success message in the verify handler to use the
URL returned by probeHealth via probe.url instead of rebuilding it with
joinHealthUrl, and remove the now-unused joinHealthUrl import.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f8c928c5-a310-463d-83ef-b3b4d13dc67f

📥 Commits

Reviewing files that changed from the base of the PR and between c5222d8 and ebef816.

⛔ Files ignored due to path filters (17)
  • api-snapshots/cli.api.md is excluded by none and included by none
  • api-snapshots/mcp.api.md is excluded by none and included by none
  • package.json is excluded by none and included by none
  • packages/cli/__tests__/commands/build.test.ts is excluded by !**/__tests__/**, !**/*.test.ts and included by packages/**
  • packages/cli/__tests__/commands/deploy.test.ts is excluded by !**/__tests__/**, !**/*.test.ts and included by packages/**
  • packages/cli/__tests__/commands/doctor.test.ts is excluded by !**/__tests__/**, !**/*.test.ts and included by packages/**
  • packages/cli/__tests__/util/auto-link.test.ts is excluded by !**/__tests__/**, !**/*.test.ts and included by packages/**
  • packages/cli/__tests__/util/health-probe.test.ts is excluded by !**/__tests__/**, !**/*.test.ts and included by packages/**
  • packages/cli/src/commands/build/bundle-size.ts is excluded by !**/build/** and included by packages/**
  • packages/cli/src/commands/build/handler.ts is excluded by !**/build/** and included by packages/**
  • packages/mcp/__tests__/local.test.ts is excluded by !**/__tests__/**, !**/*.test.ts and included by packages/**
  • packages/mcp/__tests__/observability-tools.test.ts is excluded by !**/__tests__/**, !**/*.test.ts and included by packages/**
  • packages/mcp/__tests__/server.test.ts is excluded by !**/__tests__/**, !**/*.test.ts and included by packages/**
  • packages/mcp/__tests__/tools.test.ts is excluded by !**/__tests__/**, !**/*.test.ts and included by packages/**
  • plans/README.md is excluded by none and included by none
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml and included by none
  • worker-size.json is excluded by none and included by none
📒 Files selected for processing (23)
  • .github/workflows/test.yml
  • apps/docs/src/content/docs/deployment.mdx
  • packages/cli/docs/index.mdx
  • packages/cli/src/commands/deploy/handler.ts
  • packages/cli/src/commands/deploy/index.ts
  • packages/cli/src/commands/doctor/handler.ts
  • packages/cli/src/commands/doctor/index.ts
  • packages/cli/src/commands/mcp/index.ts
  • packages/cli/src/commands/verify/handler.ts
  • packages/cli/src/index.ts
  • packages/cli/src/util/auto-link.ts
  • packages/cli/src/util/deploy-summary.ts
  • packages/cli/src/util/health-probe.ts
  • packages/mcp/README.md
  • packages/mcp/package.json
  • packages/mcp/src/index.ts
  • packages/mcp/src/local.ts
  • packages/mcp/src/observability-tools.ts
  • packages/mcp/src/server.ts
  • packages/mcp/src/tool-result.ts
  • packages/mcp/src/tool-types.ts
  • packages/mcp/src/tools.ts
  • scripts/check-worker-size.js

Comment thread .github/workflows/test.yml
Comment thread packages/cli/docs/index.mdx Outdated
Comment thread packages/cli/docs/index.mdx
Comment thread packages/cli/src/util/health-probe.ts
Comment thread packages/mcp/README.md Outdated
Comment thread scripts/check-worker-size.js
prisis and others added 3 commits August 8, 2026 07:32
Review fixes on the wave-20 branch.

- health-probe: Node's `fetch` has no timeout, so a worker that accepts the
  connection and goes quiet would hang `deploy --health-check` until CI's job
  timeout killed it — defeating the fixed attempt budget. Each attempt now
  carries an `AbortSignal.timeout`; an injected `fetchImpl` still owns its own
  deadline.
- worker-size: the gate was reachable only via the `packages`/`templates`
  filters, so a PR touching just the checker, the baseline, or the job skipped
  it — the gate could be switched off by editing the gate. Adds a `worker_size`
  filter, the matching `files-changed` output, and the `if` clause.
- worker-size: Cloudflare enforces a 64 MB pre-compression limit as well as the
  per-plan gzip one. A bundle that compresses unusually well can pass a gzip
  baseline check and still be rejected at upload, so the raw size gets its own
  absolute check. Documented both limits.
- docs: the doctor JSON example counted three findings and showed one; the CI
  snippet had no exit-code guard, so a failed deploy sent `curl` at
  `null/api/smoke` and failed at the wrong step.
- mcp: `lunora_get_migration_status` takes no `limit`, unlike the other four.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBeSX2o4sTCPjVDRDWkVQG
Every other consumer moved to @lunora/shard-engine@1.0.0-alpha.16 in the
release; this pin was left at alpha.15 because the dependency did not exist
when the release ran. The workspace `overrides:` block forces `workspace:*`
locally, so the stale pin is invisible in the repo — but it is what the
published manifest would carry.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBeSX2o4sTCPjVDRDWkVQG
@prisis

prisis commented Aug 8, 2026

Copy link
Copy Markdown
Member Author

All six review comments addressed in d5ac5fb, plus one thing the alpha merge surfaced.

health-probe.ts — per-attempt timeout. Correct and the most serious of the six. Node's fetch has no timeout, so a worker that accepts the connection and then goes quiet would have hung deploy --health-check until CI's job timeout killed it — which defeats the fixed attempt budget the probe exists to provide. Each attempt now carries AbortSignal.timeout (default 10s, timeoutMs overridable); an injected fetchImpl still owns its own deadline. Covered by a test that asserts the signal reaches fetch, rather than waiting on a real timeout.

file-filters.yml — the gate could be switched off by editing the gate. Correct. Added a worker_size filter covering the checker, the baseline, and the workflow. One thing the comment did not mention and would have made the fix a no-op: files-changed declares its outputs explicitly, so worker_size also had to be added there — otherwise the new if clause reads an always-empty output and never fires. Wired all three.

64 MB pre-compression limit. Correct, and I verified it against the Cloudflare limits page rather than taking it on trust: 3 MB Free / 10 MB Paid after gzip, and 64 MB before compression on both plans. The gzip check is a baseline comparison, so it cannot see a bundle that compresses unusually well — a large generated table is tiny gzipped and enormous raw, passes the gate, and is rejected at upload. Raw now gets its own absolute check with a message saying worker-size:update will not help, since it is a platform limit rather than a budget. Docs updated to state both limits and to stop telling readers gzip is the only figure to compare.

Doctor JSON example, CI snippet, MCP README. All three fixed as described — jsonc with a truncation comment, set -euo pipefail plus a URL guard, and the lunora_get_migration_status exception documented.

Separately: merging alpha down showed @lunora/mcp was the only one of ten consumers still pinning @lunora/shard-engine@1.0.0-alpha.15 while the release moved everything else to alpha.16. The overrides: block forces workspace:* locally so it is invisible in the repo, but it is what the published manifest would carry. Fixed in bf34e65. Lockfile regenerated after the merge rather than text-merged; it came back with zero drift.

Verification on the merged tree: CLI 1204/1204, MCP 181/181, lint:types clean, prettier clean, lint:package-json 74/74 sorted.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
scripts/check-worker-size.js (1)

150-164: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Enforce the raw limit before --update writes the baseline.

In update mode, the script writes and then calls process.exit(0) before the bundle.rawBytes > RAW_LIMIT_BYTES check runs, so an oversized reference Worker is accepted into worker-size.json. Move the raw-limit check before the update write and early return; keep the gzip-baseline update but require bundle.rawBytes <= RAW_LIMIT_BYTES first.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/check-worker-size.js` around lines 150 - 164, The update path
currently writes a baseline before enforcing the raw-size limit. In the
worker-size check flow, move the bundle.rawBytes versus RAW_LIMIT_BYTES
validation ahead of the update write and process.exit(0), while preserving the
gzip-baseline update for bundles whose raw size is within the limit.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/file-filters.yml:
- Around line 81-88: Update the worker_size filter definition to include
.github/file-filters.yml, ensuring changes to the filter configuration trigger
the worker-size gate while preserving the existing entries and behavior.

---

Outside diff comments:
In `@scripts/check-worker-size.js`:
- Around line 150-164: The update path currently writes a baseline before
enforcing the raw-size limit. In the worker-size check flow, move the
bundle.rawBytes versus RAW_LIMIT_BYTES validation ahead of the update write and
process.exit(0), while preserving the gzip-baseline update for bundles whose raw
size is within the limit.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6948b33a-5462-41ea-b601-103b24291ceb

📥 Commits

Reviewing files that changed from the base of the PR and between ebef816 and bf34e65.

⛔ Files ignored due to path filters (2)
  • packages/cli/__tests__/util/health-probe.test.ts is excluded by !**/__tests__/**, !**/*.test.ts and included by packages/**
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml and included by none
📒 Files selected for processing (8)
  • .github/file-filters.yml
  • .github/workflows/test.yml
  • apps/docs/src/content/docs/deployment.mdx
  • packages/cli/docs/index.mdx
  • packages/cli/src/util/health-probe.ts
  • packages/mcp/README.md
  • packages/mcp/package.json
  • scripts/check-worker-size.js
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/mcp/package.json
  • apps/docs/src/content/docs/deployment.mdx
  • packages/mcp/README.md
  • packages/cli/docs/index.mdx

Comment thread .github/file-filters.yml
@codecov-commenter

codecov-commenter commented Aug 8, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.72822% with 18 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (alpha@c5222d8). Learn more about missing BASE report.

Files with missing lines Patch % Lines
packages/cli/src/commands/doctor/handler.ts 86.36% 6 Missing ⚠️
packages/cli/src/commands/build/handler.ts 80.00% 4 Missing and 1 partial ⚠️
packages/cli/src/util/health-probe.ts 90.90% 3 Missing ⚠️
packages/mcp/src/observability-tools.ts 96.66% 1 Missing and 1 partial ⚠️
packages/cli/src/commands/deploy/handler.ts 97.95% 0 Missing and 1 partial ⚠️
packages/cli/src/util/auto-link.ts 92.30% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##             alpha     #361   +/-   ##
========================================
  Coverage         ?   87.08%           
========================================
  Files            ?     1170           
  Lines            ?    63259           
  Branches         ?    15350           
========================================
  Hits             ?    55087           
  Misses           ?     7643           
  Partials         ?      529           
Files with missing lines Coverage Δ
packages/cli/src/commands/build/bundle-size.ts 100.00% <100.00%> (ø)
packages/cli/src/commands/deploy/index.ts 25.00% <ø> (ø)
packages/cli/src/commands/doctor/index.ts 25.00% <ø> (ø)
packages/cli/src/commands/mcp/index.ts 100.00% <ø> (ø)
packages/cli/src/commands/verify/handler.ts 92.95% <100.00%> (ø)
packages/cli/src/util/deploy-summary.ts 100.00% <100.00%> (ø)
packages/mcp/src/local.ts 91.30% <100.00%> (ø)
packages/mcp/src/server.ts 88.37% <100.00%> (ø)
packages/mcp/src/tool-result.ts 100.00% <100.00%> (ø)
packages/mcp/src/tools.ts 97.70% <100.00%> (ø)
... and 6 more
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@codspeed-hq

codspeed-hq Bot commented Aug 8, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 20.54%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

❌ 1 regressed benchmark
✅ 252 untouched benchmarks
⏩ 10 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
batched: one IN-list UNION-ALL probe across all tables (locateTablesByIds) 1.4 ms 1.8 ms -20.54%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing integrate/wave-20 (a2f54dd) with alpha (3709940)2

Open in CodSpeed

Footnotes

  1. 10 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

  2. No successful run was found on alpha (c5222d8) during the generation of this report, so 3709940 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

Second round of review fixes.

- file-filters: the worker_size filter did not list the filter file itself, so
  a PR editing the filter definition still skipped the gate — and
  test-required-check passes on skipped jobs. Same hole as the one the filter
  was added to close, one level up.
- verify: report the URL probeHealth returned instead of rebuilding it. The two
  agree only while verify keeps the default paths; passing more would name a
  URL the verdict did not come from. Drops the joinHealthUrl import.
- docs: a stray blank line rendered one doctor-check bullet as a loose list item.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KBeSX2o4sTCPjVDRDWkVQG
@prisis

prisis commented Aug 8, 2026

Copy link
Copy Markdown
Member Author

Correction to my previous comment: it claimed all six review comments were addressed, which was true of the six actionable ones but not of everything outstanding. Three more were open, now fixed in a2f54dd.

.github/file-filters.yml not listed in its own filter (the 7th inline comment, from the re-review after my push — I had not re-fetched). Correct, and it is the same hole as the one the filter was added to close, one level up: a PR editing the filter definition would not match the filter, the gate would skip, and test-required-check passes on skipped jobs. Added the file to its own filter.

verify rebuilt the health URL instead of reading probe.url. The two agree only while verify keeps the default paths; the moment it passes more, the success message names a URL the verdict did not come from. Fixed, joinHealthUrl import dropped.

Loose list item in the doctor-checks list — stray blank line removed.

CLI 1204/1204, lint:types clean, prettier clean.

@prisis
prisis merged commit 850f31d into alpha Aug 8, 2026
42 of 43 checks passed
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Please note this issue tracker is not a help forum. We recommend using our GitHub Discussions tab for questions.

@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Sep 8, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants