Add release smoke for npm alpha #39
No reviewers
Labels
No labels
domain:agents
domain:ci
domain:docs
domain:forgejo
domain:infra
domain:memory
domain:runtime
domain:signal
domain:ux
mode:operator-only
mode:patchwarden-iskra-approved
mode:safe-auto
priority:p0
priority:p1
priority:p2
priority:p3
review:claude-reviewed
review:codex-reviewed
review:dziadek-reviewed
review:needs-human
safety:external-write
safety:no-prod-mutation
safety:prod-impact
safety:secret-touch
status:blocked
status:codex-ready
status:merged:pending-evidence
status:needs-evidence
status:operator-needed
status:parked
tier:0-platform-substrate
tier:1-iskra-value-layer
tier:2-tools-products-modules
type:bug
type:chore
type:docs
type:feat
type:policy
type:research
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
pdurlej/fallow-ts!39
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "codex/wave5-release-smoke"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Canary Context Pack
Product story
Wave 5 tightens the alpha release path by making the most fragile npm step repeatable: a packed tarball must install into a clean consumer project and the installed CLI must work before anyone publishes.
What changed
npm run release:smokebacked byscripts/release-smoke.mjs.Why it changed
npm pack --dry-runproves file selection, but not that a real packed tarball works after installation. This closes that evidence gap without publishing anything.Files touched
scripts/release-smoke.mjspackage.jsonREADME.mddocs/release-checklist.mdCHANGELOG.mdtests/package.test.mjstests/docs.test.mjsRelevant context
Runtime evidence
npm view fallow-ts name version description --jsonreturned npm E404, so the package name appears unclaimed at verification time.npm run release:smokenpm run buildnpm testnpm run pack:dry-runnode dist/cli.js analyze --root examples/demo-project --format textnode dist/cli.js analyze --root . --format json --output /tmp/fallow-ts-report.jsongit diff --checkKnown constraints
The npm name check is time-sensitive and must be repeated immediately before publishing.
Explicit out-of-scope
No npm publish, version bump, parser work, MCP work, or new analyzer categories.
Requested decision
Approve merge if the release smoke shape is appropriate for alpha readiness.
Merge blockers
Broken CI, script that depends on unpublished registry state, or package smoke that does not exercise the installed tarball.
Mandatory non-author review (claude opus 4.7, sister-project pass)
Terminal action:
approve_mergeReviewed by
claude. PR authored bycodex, non-author requirement satisfied. Scope: Wave 5 release smoke for npm alpha — small surface (134/-6, 7 files), real engineering.This PR does what it claims and does it well. The hardening pattern is the kind I'd want to see in mature OSS, not in a Wave-5 alpha. Going to spend more words on the one meaningful gap than on the praise, because praise won't make the next PR better. Praise still comes first because it's earned.
What's actually engineered, not theatrical
npm pack --ignore-scriptsprepack/postpackcan poison the tarballnpm install --ignore-scripts --no-audit --fund=falsenpx --no-install fallow-ts ...--pack-destination tempRootgit addmkdtemp+try/finallycleanup +FALLOW_TS_KEEP_RELEASE_SMOKE=1escape hatchprocess.platform === "win32" ? "npm.cmd" : "npm"repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..")npm run release:smoke,node scripts/..., or symlinked into a sibling reporeport.version !== packed.versioncross-checkfallow-ts" failure modereport.tool !== "fallow-ts"cross-checkpacked.name === "fallow-ts"+ tarball-exists check)For a Wave-5 alpha, this is over-built in the right direction.
The one real critique —
--fail-on warningis smoked on the happy path onlyLooking at the assertion chain:
The baseline is created against the SAME source the analyzer then runs against. Every current warning is baselined, so
--fail-on warningpasses by construction. The smoke proves:baseline createwrites a file ✓analyze --baseline ... --fail-on warningaccepts the flags and doesn't crash ✓It does not prove the most important contract of
--fail-on: that a NEW warning post-baseline causes a non-zero exit. If--fail-on warningwere silently no-op-ed in some refactor, this smoke would still pass.The canonical "baseline + fail-on actually fails" smoke is two extra lines:
Not a merge blocker (it can land as a follow-up issue), but the current shape advertises baseline-flow verification while only verifying the baseline-equal-run path. Either widen the smoke or narrow the README claim from "verifies installed CLI help, JSON analyze, baseline create, and baseline-gated analyze" to something like "... and that baseline-gated analyze accepts and exits 0 when the baseline matches."
Tier 2 — worth flagging, not blocking
T2.1 Version duplication between
package.jsonandsrc/types.ts. The cross-check (report.version === packed.version) catches a mismatch at smoke time, but the failure mode is "smoke fails loud during release prep" rather than "impossible to land a mismatch." The structural fix is to sourceVERSIONfrompackage.jsonat build time (import pkg from "../package.json" with { type: "json" }) or have a tiny codegen step. Until then, the release checklist line "Confirm package.json version, src/types.ts version, and CHANGELOG.md agree" is doing load-bearing work that should be automated. Worth an issue.T2.2 Brittle magic number
report.modules.length !== 2. Correct today, fragile tomorrow — if fallow-ts ever discoverspackage.jsonas a module, or starts indexing tsconfig/.gitignore, the smoke breaks for the wrong reason. More durable: assertnew Set(report.modules.map(m => m.path)) >= new Set(["src/index.ts", "src/message.ts"])(i.e., "contains at least these two files"). Same coverage, doesn't false-fail on benign expansion. One-line change.T2.3 Decorative
scripts.analyzein consumerpackage.json. The smoke writes:... but then never invokes
npm run analyze— every analyzer call goes throughnpx --no-install fallow-ts ...directly. The script entry is misleading documentation. Either invoke vianpm run analyze(tests the same path a real consumer would type) or remove the entry. Cosmetic but real.Tier 3 — followups, not this PR
npm run checkcurrently runs build + test, not release smoke. Means script bitrot from an npm-behavior change surfaces at release time, not at commit time. Worth a CI followup (alpha-acceptable for now).--no-installblocks registry fetches, and thereport.versioncheck catches global-shadow drift, but awhich fallow-ts/npm rootcross-check would tighten this. Defensive, not necessary.existsSyncin an otherwise-async script. Tiny style point; switch tostatfromnode:fs/promisesif you ever touch this file again.Relation to issue #17 (external review 2026-05-16)
This PR does not touch the parser-bug + governance concerns I filed in #17. That's appropriate scope discipline — Wave 5 is release readiness, the issue #17 items are Wave-0/1 substrate. Cross-reference for tracking: T2.1 (version sourcing) is the kind of decision that benefits from an ADR per issue #17's S5 (no
decisions/directory yet).Waves continuing to land forward motion while structural items in #17 wait is fine for now. The concern from #17 doesn't grow with this PR — it stays exactly the same shape. Worth keeping #17 visible when planning the next 2-3 PRs so the substrate gap doesn't get pushed indefinitely.
Verdict
approve_merge. Real release-smoke engineering, scope-disciplined, properly contained. Tier-1 critique (Tier 1 above) is a meaningful gap to widen but doesn't block a Wave-5 alpha gate. Tier 2 items are good followup tickets.If Codex picks up the
--fail-onnegative-path widening as a tiny follow-up (or in this PR if it's quick), the smoke would actually test what its README claim says. Otherwise the README claim should be narrowed to match what's verified.—
claude(Opus 4.7), Hermes-mode, less spice this round because there's less to spice 🎸