Skip to content

Remove the legacy dynamic invocation surface with teaching errors (narrow phase) - #1065

Merged
kody-bot merged 2 commits into
mainfrom
cursor/static-first-package-model-8ec0
Jul 30, 2026
Merged

kody-bot merged 2 commits into
mainfrom
cursor/static-first-package-model-8ec0

Conversation

@kentcdodds

@kentcdodds kentcdodds commented Jul 30, 2026 •

Copy link
Copy Markdown
Owner

Summary

Executes the narrow phase of the static-first program per #1048, with every gate satisfied: the fleet codemod scan reported zero legacy usage across all production packages (97 clean), the two-rule guidance and metering are deployed, and Kent waived the remaining observation window.

What's removed (and what teaches)

  • packages.check / packages.invokeChecked: gone from the host tool set (PackageInvokeTools is { invoke }), the bridge provider, and the package-app runtime bridge. The sandbox prelude and the package-app packages proxy keep the property names as throwing teaching errors naming the exact replacement — agents learn the current contract from error text, and typeof packages.check === 'function' still holds so feature-detection code fails at call time with the teaching message rather than a TypeError.
  • Literal dynamic import("kody:@..."): the bundler rewrites each call site to a teaching error naming the static-import and packages.invoke replacements; no placeholder modules or dynamic-dependency metadata are produced. The computed-import guard message is updated to the two-rule wording.
  • Publish checks escalate: the widen-phase non-fatal deprecation warnings become failing lint results naming the replacement and the 0002-static-first-invocation codemod. The same collector (deprecated-invocation-usage.ts) backs both the check and the codemod, so they stay in lockstep by construction.
  • Dead code removed: the invoke contract check drops the export-projection branch (description/typeDefinition source loads) that only packages.check consumed — the lean path loses a conditional, not a feature.

Deliberate compatibility net

hydrateKodyRuntimeModules keeps resolving dynamic-import placeholder modules found in already-published bundles: a dependent republished before today may carry a pinned snapshot of an older dependency version that used the pattern, and those artifacts must keep working until the dependent republishes. New bundles can never produce placeholders, so this path is effectively dormant; it can be deleted in a follow-up once pre-narrow artifacts age out.

Testing

  • Workers (real workerd): the prelude teaching errors are proven end-to-end in the lean-invoke test and the ad hoc execute test; the artifact-imports test asserts the dynamic-import teaching error fires while static imports keep working (including from nested modules).
  • Node: publish checks fail with replacements named; invoke rejection messages; the removed check/invokeChecked absence from host tools; module-graph rewrite produces teaching errors while the placeholder-hydration compatibility tests (circular imports, manual placeholders) still pass.
  • Full unit suite green: 1629 tests. Full npm run validate running as the final gate.

Program report

Open in Web Open in Cursor 

Summary by CodeRabbit

  • New Features

    • packages.invoke is now the sole supported dynamic package invocation entrypoint and includes contract checking.
    • Updated guidance for migrating from removed literal dynamic imports to static imports or packages.invoke.
  • Bug Fixes

    • Removed legacy invocation APIs and literal dynamic imports now produce clear teaching errors instead of deprecated behavior.
    • Repo/publish checks now fail when removed invocation patterns are detected.
    • Previously published bundles still resolve the old removed patterns during hydration for backward compatibility.
  • Documentation

    • Refreshed “Execute” and “Packages” docs to reflect the removed dynamic invocation surface and new teaching-error wording.

Narrow phase of the static-first two-rule model (#1048), gated on the
fleet codemod scan showing zero legacy usage across all production
packages:

- packages.check and packages.invokeChecked no longer exist: the host
  tool set carries only invoke, and the sandbox prelude (execute and
  package runtimes, plus the package-app bridge) throws teaching errors
  naming the exact replacement.
- Literal dynamic import("kody:@...") is rewritten at bundle time to a
  teaching error; no placeholder modules or dynamic-dependency metadata
  are produced. Hydration keeps resolving placeholders inside bundles
  published before the removal so pinned snapshots keep working until
  dependents republish.
- Publish checks escalate from non-fatal deprecation warnings to failing
  lint results naming the replacement and the 0002-static-first-invocation
  codemod (same collector keeps codemod findings in lockstep).
- The invoke contract check drops the dead export-projection branch that
  only packages.check consumed.
- Docs flip widen-phase deprecation notes to removed/teaching text.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
@coderabbitai

coderabbitai Bot commented Jul 30, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The change removes packages.check, packages.invokeChecked, and literal dynamic kody:@ imports. Runtime bridges and bundling now emit teaching errors, publish checks fail on removed usage, tests cover the new behavior, and documentation describes migration and legacy-bundle hydration handling.

Changes

Legacy invocation removal

Layer / File(s) Summary
Runtime invocation contract
packages/worker/src/mcp/..., packages/worker/src/package-invocations/..., packages/worker/src/package-runtime/package-app.ts, related tests
Only packages.invoke remains exposed; contract checking and invalid-target validation run through it, while removed helpers throw teaching errors.
Dynamic import rewriting and runtime errors
packages/worker/src/package-runtime/module-graph-import-rewriting.ts, runtime-source-modules.ts, related tests
Literal dynamic Kody imports are rewritten to removal helpers with replacement guidance; bundle, hydration, and execute tests assert the errors.
Publish-check enforcement
packages/worker/src/repo/checks.ts, deprecated-invocation-usage.ts, related tests
Removed invocation usage now produces fatal lint results naming the removed APIs and migration codemod.
Documentation and sandbox guidance
docs/..., packages/worker/src/mcp/instructions/execute-tool-description.ts
Guidance describes the removed APIs, static-import or packages.invoke replacements, publish failures, and legacy bundle hydration behavior.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.52% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed It clearly summarizes the main change: removing the legacy dynamic invocation surface and replacing it with teaching errors.
Linked Issues check ✅ Passed The PR removes the legacy invoke/check APIs, rewrites literal dynamic imports to teaching errors, and makes publish checks fail.
Out of Scope Changes check ✅ Passed The touched docs, runtime code, and tests all relate to legacy dynamic invocation removal; no unrelated changes stand out.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/static-first-package-model-8ec0

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.

@github-actions

github-actions Bot commented Jul 30, 2026 •

Copy link
Copy Markdown
Contributor

🔎 Preview deployed: https://kody-pr-1065.kody-a99.workers.dev

Worker: kody-pr-1065
D1: kody-pr-1065-db
KV: kody-pr-1065-oauth-kv

Mocks:

@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

🧹 Nitpick comments (1)
packages/worker/src/package-runtime/package-app.ts (1)

360-376: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Reuse the shared removed-package teaching-message constants.

createPackagesProxy duplicates removedPackagesCheckMessage and removedPackagesInvokeCheckedMessage, while createPackagesHelperPrelude already embeds the same exported strings. Reuse those strings in package-app.ts via JSON.stringify(...) so the package-app Worker and sandbox VM guidance stay synchronized.

🤖 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/worker/src/package-runtime/package-app.ts` around lines 360 - 376,
Update createPackagesProxy to reuse the shared removedPackagesCheckMessage and
removedPackagesInvokeCheckedMessage constants already used by
createPackagesHelperPrelude, embedding each via JSON.stringify(...) in the
thrown Error messages. Remove the duplicated inline teaching text so package-app
Worker and sandbox VM guidance remain synchronized.
🤖 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 `@docs/use/packages.md`:
- Around line 150-155: Update the legacy import guidance in the package
documentation to remove the contradictory exception that literal dynamic imports
need no kody.dependencies, since publish checks now reject them. Revise the
related “any of them throws” wording to apply only to new source or bundles,
while preserving the documented hydration support for pre-removal bundles and
aligning both affected sections with the package-manifest and execute
documentation.

---

Nitpick comments:
In `@packages/worker/src/package-runtime/package-app.ts`:
- Around line 360-376: Update createPackagesProxy to reuse the shared
removedPackagesCheckMessage and removedPackagesInvokeCheckedMessage constants
already used by createPackagesHelperPrelude, embedding each via
JSON.stringify(...) in the thrown Error messages. Remove the duplicated inline
teaching text so package-app Worker and sandbox VM guidance remain synchronized.
🪄 Autofix (Beta)

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6350b8c7-5c67-45f2-bfc1-2febb6a76de7

📥 Commits

Reviewing files that changed from the base of the PR and between 56e4851 and 459386d.

📒 Files selected for processing (18)
  • docs/contributing/packages-and-manifests.md
  • docs/use/execute.md
  • docs/use/packages.md
  • packages/worker/src/mcp/instructions/execute-tool-description.ts
  • packages/worker/src/mcp/run-kody-registry.node.test.ts
  • packages/worker/src/mcp/runtime-helper-manifest.ts
  • packages/worker/src/package-invocations/http-invoke.ts
  • packages/worker/src/package-invocations/invoke-check.ts
  • packages/worker/src/package-invocations/runtime-tool-factories.ts
  • packages/worker/src/package-invocations/service.node.test.ts
  • packages/worker/src/package-runtime/deprecated-invocation-usage.ts
  • packages/worker/src/package-runtime/module-graph-import-rewriting.ts
  • packages/worker/src/package-runtime/module-graph.node.test.ts
  • packages/worker/src/package-runtime/module-graph.workers.test.ts
  • packages/worker/src/package-runtime/package-app.ts
  • packages/worker/src/package-runtime/runtime-source-modules.ts
  • packages/worker/src/repo/checks.node.test.ts
  • packages/worker/src/repo/checks.ts

Comment thread docs/use/packages.md
… qualify removal wording

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit c03914d. Configure here.

return `
export const ${dynamicPackageImportSpecifierExportName} = ${JSON.stringify(input.specifier)};

throw new Error(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Unused exported message builder

Low Severity

This commit adds exported buildRemovedDynamicKodyImportMessage, but nothing in the repo imports or calls it. Literal dynamic-import teaching errors still come from the inline string inside createRemovedDynamicKodyImportHelperSource, so the new helper is dead surface area and can drift from the runtime message.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit c03914d. Configure here.

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

Caution

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

⚠️ Outside diff range comments (1)
docs/use/packages.md (1)

156-160: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Limit kody.dependencies guidance to saved package code.

“Every direct static import” also covers ad hoc execute imports, but those are bundled per call and do not have a package manifest to update. Qualify this as “Every direct static import in saved package code” to avoid misleading execute users.

🤖 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 `@docs/use/packages.md` around lines 156 - 160, Update the kody.dependencies
guidance in the package documentation to apply only to direct static imports in
saved package code, excluding ad hoc execute imports that are bundled per call
and have no package manifest.
🤖 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.

Outside diff comments:
In `@docs/use/packages.md`:
- Around line 156-160: Update the kody.dependencies guidance in the package
documentation to apply only to direct static imports in saved package code,
excluding ad hoc execute imports that are bundled per call and have no package
manifest.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6d01baa5-4f3c-4616-9821-b4b729d6bc20

📥 Commits

Reviewing files that changed from the base of the PR and between 459386d and c03914d.

📒 Files selected for processing (1)
  • docs/use/packages.md

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.

Narrow phase: eliminate the deprecated dynamic invocation surface (invokeChecked, packages.check, dynamic kody:@ imports)

3 participants