test(repo): verify packed consumers#2149
Conversation
41b6a67 to
d0cdb3c
Compare
cc4229e to
46f7f01
Compare
47513d8 to
c6e0a39
Compare
a78b47e to
d1b91ee
Compare
c6e0a39 to
0d78a2a
Compare
d1b91ee to
cdbd58a
Compare
0d78a2a to
5911119
Compare
cdbd58a to
b765b0b
Compare
5911119 to
11159b7
Compare
b765b0b to
68b3a7a
Compare
3a725e6 to
c33f69e
Compare
77827bd to
b089fff
Compare
c33f69e to
7b7e4b3
Compare
b089fff to
83db364
Compare
7b7e4b3 to
03acdb3
Compare
miga-heygen
left a comment
There was a problem hiding this comment.
Review — test(repo): verify packed consumers
SSOT check: clean. The verification pipeline is a single linear chain: pack → verify manifest → install as consumer → typecheck → runtime smoke → CLI startup. No decision duplication.
packageExportSpecifier / listPackedExportContracts: correctly derive consumer specifiers from the export map. The typechecked flag (Boolean(target?.types)) gates which specifiers go into the TS consumer fixture vs. the runtime-only smoke. Clean separation.
Consumer fixture: installs packed tarballs via file: references (not workspace links — genuine "install as a consumer" simulation), pulls typescript and @types/node from the root devDeps (no version drift). The tsconfig.json uses moduleResolution: "NodeNext" — matches real consumer environments.
Runtime smoke: import.meta.resolve for all specifiers (fast, no side effects), then dynamic import() for specific SDK entry points with typeof assertions. Good — catches broken export maps without running heavy initialization.
CLI startup: hyperframes --help with telemetry disabled. Catches missing bin entry / unresolvable CLI entry point.
Refactoring: verifyWorkspace → packAndVerifyWorkspace returns { workspace, filename, packedPackage } or null for private packages; main() orchestrates pack-all → consumer-verify. The shared packDir is created once and cleaned up in a finally. Clean.
Tests: packageExportSpecifier and listPackedExportContracts unit-tested with the types-present/absent distinction. Good.
LGTM — no issues found.
— Miga
james-russo-rames-d-jusso
left a comment
There was a problem hiding this comment.
Reviewed at 03acdb3.
Solid infra addition. This lifts the pack-verify script from "pack and inspect manifests" to "pack, install into a real consumer fixture, typecheck + smoke-import + CLI-help." That's exactly the layer that catches the shape of bugs where the packed manifest lists an export but the packed tarball is missing the .d.ts (which the R1-flavor assertPublishedExportsMatchSource alone can't catch — it verifies source correctness, not packed availability).
Structural notes:
-
writeConsumerFixture— reasonable shape. Pinstypescript+@types/nodefrom root's devDependencies (verified:^5.0.0/^25.0.10, semver ranges — bun install will resolve from npm, not aworkspace:*protocol issue). The fixture'sconsumer.tsbulk-imports everytypes-carrying export, andconsumer-smoke.mjsruntime-imports every declared export + spot-checks four public function names (openComposition,createMemoryAdapter,createFsAdapter, plus the four core/parsers/lint/studio-server round-trips). Good coverage of both TS surface and runtime surface. -
listPackedExportContracts+packageExportSpecifier— clean extract, unit-tested.typechecked: Boolean(target?.types)correctly handles both string exports (untyped) and object exports with atypesfield.
Two small observations, non-blocking:
-
packages/cli/utils/verify-packed-manifests.mjs:116— the CLI-help assertion iscliOutput.toLowerCase().includes("hyperframes"). SinceexecFileSyncthrows on non-zero exit, the throw path covers CLI failure. The.includes("hyperframes")catches the "ran but printed something unexpected" case, but "hyperframes" is broad enough that error output likehyperframes: command not found(though that would exit non-zero) or a stub help would still pass. A slightly stronger check for a known subcommand token (e.g.,"render"or"snapshot") would tighten this. Not important for correctness, just makes the assert more descriptive of what it's actually checking. -
packages/cli/utils/verify-packed-manifests.mjs:107+:113— mixedprocess.execPath(for tsc) vs bare"node"(for consumer-smoke.mjs). Both work; theprocess.execPathpath is more robust to weird PATH configurations. Cosmetic — probably not worth changing on this PR.
What I didn't verify
- Behavior on packages with wildcard/pattern exports (
"./adapters/*": …) — didn't check whetherObject.entries(packedPackage.exports)handles those cleanly. If HF workspaces don't use wildcard exports today, this is moot.
LGTM.
03acdb3 to
9762677
Compare
9762677 to
979e9d0
Compare
miguel-heygen
left a comment
There was a problem hiding this comment.
Re-review at 979e9d09 after the stack restack. The stable patch-id is identical to the previously reviewed 03acdb38 change, so the own boundary is unchanged.
scripts/verify-packed-manifests.mjs:296-389builds a genuine tarball-backed consumer, then verifies NodeNext type resolution, runtime imports, and CLI startup.scripts/verify-packed-manifests.mjs:404-413keeps the shared temporary pack directory behind a singlefinallycleanup.- All eight required checks are green, including Build, Test, runtime contract, Windows tests/render, and Typecheck.
— Magi / deepwork
Verdict: APPROVE
Reasoning: The exact reviewed patch survived the restack unchanged, the consumer verification boundary is sound, and required CI is green.
Merge activity
|

What
Verify publish artifacts as clean consumers instead of only scanning tarball manifests.
Why
A package can contain all declared files and still fail when installed or imported by Node, TypeScript, or a browser bundler.
How
Pack workspaces, install them into isolated fixtures, validate relative imports, and execute representative consumer entry points.
Test plan