Skip to content

fix(cli): resolve and run hub imports in independent checkup scopes - #1500

Open
oxura wants to merge 2 commits into
bendlang:mainfrom
oxura:fix/1499-checkup-hub-imports-20261011
Open

oxura wants to merge 2 commits into
bendlang:mainfrom
oxura:fix/1499-checkup-hub-imports-20261011

Conversation

@oxura

@oxura oxura commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

Fixes #1499.

--checkup currently turns a documented content-hash or named hub import into a file beside the aggregation. The ordinary checker/runner resolves the same cached package and returns 5n; independent checkup instead fails with ENOENT.

Resolve package names using the existing public name/version grammar, name-cache layout and immutable hash lookup protocol. Hand acquisition and manifest/file digest verification to the unchanged loader. Keep the module's hub namespace while parsing/checking, then select its actual pure or IO main; the shared JS generator now accepts an explicit entry root rather than only rooting main. Ordinary CLI, JS and module entry defaults remain unchanged. Reuse checked Base when source is already present, but do not inject Base into a module that did not import it. Cache confinement is checked before executing an entry.

The permanent installed-CLI consumer uses the gate's existing manifest hash helper to create a valid isolated cache: one content-hash pure entry returns 5n, and a different named effectful entry actually prints hub-io. The exact new assertion fails against unchanged main and passes against the genuinely rebuilt standalone CLI. No wiring/source-shape/diagnostic-text assertion. README documents independent hub scope.

Actual Linux x64 evidence:

  • Four cold source/installed runs fetch real SHA-verified manifest/file responses from an isolated HTTP content server selected by BEND_HUB. Hash imports return 5n; named imports resolve and execute hub-io. This is local HTTP protocol proof, not a claim that a test package was published to the public hub.
  • Twenty-four source/installed boundary runs cover warm hash/name/IO entries, a conflicting local decoy, rejection of a bad proof and missing Base, a quiet exit status 37, continued good execution after a bad module, ordinary local IO, package traversal, invalid version/hash and a missing package.
  • Eight actual source/installed integrity/confinement runs reject corrupt manifests/files without writing the package, and reject warm/cold external-cache symlinks before IO entry execution.
  • Eleven ordinary consumer executions preserve direct root CLI, native C, Bun/Node JS, Bun/Node MJS and actual Bun .bend-loader behavior; two real emission commands built those artifacts.
  • Exact new permanent consumer assertion: fail-before/pass-after with real CLI processes.
  • bun gates/repo.ts: 54/54.

The human-written bend2/bend.ts, GUIDE, CHANGELOG, kernel, gate policy and permanent token limits are untouched. Full installer/archive/hub ping was not run because the sibling site checkout is unavailable; executing its new assertion is not a claim that the complete gate passed. No GPU/platform qualification.

oxura and others added 2 commits October 11, 2026 21:15
…resolves it

--checkup wrote each hub import into a temporary root (import <path> as
Hub) and loads that, so name lookup, fetching, hash checks and library
confinement are the loader's own; the module keeps its hub namespace
and its main becomes the root's main. A first parse with Base marked
seen finds the module's file to see whether it imports Base, so Base
is seeded as for local imports. The entry parameter through io_type,
io_run, js_lib, book_main and book_run and the ns parameter of
book_read go: comp.ts is unchanged, main.ts is +246 tokens over main
instead of +608.
@nicolas-abril

Copy link
Copy Markdown
Collaborator

Unsupervised AI review (Claude, run by @nicolas-abril). Nobody has read this by hand yet, so please double-check it.

I pushed 67d6f8e on top of this PR. It keeps the behavior and lets the loader do all of the resolving:

  • For each hub import (0x…/ or name@version/), --checkup writes a one-line temporary root, import <path> as Hub, and loads that. Name lookup, fetching, SHA checks and library confinement are then exactly what book_load already does, so the copies of NAMED, the name cache, hub/plain/hash and the two realpath checks in cli_checkup go away.
  • The module still loads in its own hub namespace. After loading, book.tlds.main is set to <ns>:main. That removes the entry parameter from io_type, io_run, js_lib, book_main and book_run, and the ns parameter from book_read. comp.ts is back to main's version.
  • To keep the "seed Base only if the module imports it" rule, a first book_load parse runs with Base already marked as seen. This finds the module's real file without parsing Base. Without this step, warm hub checkups were about 40 ms slower each.
  • Tokens: main.ts is +267 over main instead of +608. comp.ts is +0 instead of +18.

Checks on macOS:

  • gates/repo.ts 54/54, gates/ping.ts 48/48 (this includes your hash and named hub checkup), gates/test.ts 1602/1602.
  • I made a local BEND_LIB with a pure hash entry, a named IO entry, a hub file that imports ../../foo.bend, a module with no main, and a local import. The output is byte-identical to this PR's head, including the confinement error.
  • hyperfine on a 3-import checkup: 56.3 ± 1.6 ms (PR) vs 58.0 ± 1.7 ms (this commit).

I left the README line and the ping test unchanged.

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.

CLI: --checkup treats valid hub imports as unrelated local files

2 participants