chore(cli): make the module CLI publishable (HT-121) - #189
Conversation
The package could not be installed from npm: its source imported the shared verifier by repo-relative path, which resolves only inside this monorepo, and its bin executed TypeScript through tsx. Either alone made an install fail before a command could run. esbuild (pinned exactly, no caret) now bundles the CLI and the src/modules/artifact verifier into one package-contained file. Bundling copies bytes at publish time, which keeps the CLI and the engine on ONE implementation of verification policy; a hand-maintained second copy would let them drift, which is the failure the shared library exists to prevent. The pinned publisher key stays a compiled-in literal, unreachable from any flag, env var, or catalog response — asserted by a test rather than assumed. Published name is @helpthread/module; the command stays helpthread-module. The scope protects the namespace without making the command harder to type, and publishConfig.access is public because a scoped package would otherwise publish restricted by default. The package remains private:true — this ticket makes publishing possible, it does not publish. Verified by packing and installing, not by reasoning: npm pack, install the tarball into a directory outside this repo, then run both commands and a real offline verify of the published draft-assistant 0.3.0 assets from that isolated install — OK for the genuine artifact, sha256-mismatch and non-zero exit after flipping one byte. That step earned its keep: the first build emitted a shebang from both the source file and the esbuild banner, and a second shebang is a SyntaxError under Node's ESM loader. Only running the built artifact surfaces that. The packed tarball contains exactly LICENSE, dist/main.js, package.json, README.md — no TypeScript, no tests, nothing outside the files allowlist. A test pins that list so it cannot silently grow. 2004 tests, typecheck clean, Biome 364 files. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
files admits the whole dist/ directory and npm publish runs no tests, so anything that ever landed there — a bundle from an older entry point, a sourcemap from a debugging session, a file dropped by hand — would ship silently to every operator. The build now starts from an empty directory, making the published contents a function of the build script alone. Pinned by a test that plants a stray file, rebuilds, and asserts it is gone; verified failing against the un-cleaned build. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
Next review available in: 50 minutes 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 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 configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (7)
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. Comment |
🟢 SAFE TO MERGE
All gates green on head
3fb44f1d: Quality (typecheck/lint/test/coverage), CodeQL, gitleaks, and CodeRabbit with zero inline findings. Maintainer instructed merge, 2026-08-04: "merge 189".Codex (adversarial, in place of CodeRabbit for the pre-review): 1 finding, real, fixed and pinned by a test verified failing against the unfixed build.
Still true after merge:
private: trueremains on — this ticket makes publishing possible and does not publish. The package name stays a maintainer decision until the first publish makes it permanent.Original verdict at open — 🟡 NEEDS YOUR DECISION
Makes the CLI publishable and proves it by packing. Publishes nothing —
private: truestays on, and the first publish is a deliberate act that's yours. One decision below is mine and is near-irreversible once exercised.Codex (adversarial, in place of CodeRabbit): 1 finding, real, fixed. Gates green: 2005 tests, typecheck, Biome 364 files.
Decision provenance
@helpthread/module; the command stayshelpthread-modulehelpthreadorg is real (ownerzaridan), so scoping became the better option. An npm name is permanent after first publish (no unpublish past 72h), so confirm it before that day. Changing it now is one line.publishConfig.access: "public"What was broken
The package could not be installed from npm at all. Its source imported the shared verifier by repo-relative path (resolves only inside this monorepo), and its bin executed TypeScript through
tsx. Either alone fails before a command can run.What changed
esbuild (pinned exactly, no caret) bundles the CLI plus the
src/modules/artifactverifier into one package-contained file. Bundling copies bytes at publish time, which keeps the CLI and the engine on one implementation of verification policy — a hand-maintained second copy would let them drift, which is the failure the shared library exists to prevent. The pinned publisher key stays a compiled-in literal, unreachable from any flag, env var, or catalog response; asserted by a test rather than assumed.Verified by packing and installing, not by reasoning
npm pack -w cli→ tarballnpm install <tgz>into a directory outside this repoinstall --helpandverify --helpboth run on plain Node, notsxpresenttar tzf→ exactlyLICENSE,dist/main.js,package.json,README.md. No TypeScript, no tests, nothing outside the allowlist. (I re-ran 1 and 6 independently.)That discipline caught two real bugs config-reading would not have. The first build emitted a shebang from both the source file and the esbuild banner — a second
#!/usr/bin/env nodeis aSyntaxErroron line 2 under Node's ESM loader. And Codex founddist/was never cleaned before a build: withfilesadmitting the whole directory andnpm publishrunning no tests, any stale artifact would have shipped silently. Both are now pinned by tests I watched fail against the unfixed code.Note on the test numbers
Two intermediate runs of mine reported 4 and then 12 failures in webauthn/queue/gmail code this PR never touches. Those were my own resource contention — I had stacked concurrent full-suite runs and drove load average to 93; the tests each spin up an in-memory Postgres and starved. On a settled machine: 2005/2005, exit 0, duration halved. Recording it here because the intermediate numbers are in the session history and shouldn't be mistaken for a real regression.
🤖 Generated with Claude Code