Repository navigation
test(cli): since tsx 4.23.15 (#21162) oclif cannot register tsx, so the CONTROL leg of published-entry-node-env-source-reroute never arms and its guard passes vacuously #21308
Description
Filing-gate class: ① a defect with a named failing probe and a measured cause. It is fallout of #21162 (card #21094), which this seat landed.
Body last written 2026-10-02T04:49Z: unblocked. #21285 closed completed when PR #21306 merged as dabd1c5be7. Blockers were re-derived with no new one, and the card was dispatched in the same act.
Routing: the maintainer direct-dispatch channel (session_018gA1pE6eJtwHhqx72G8U9X; 「相关卡片你使用项目经理技能派发处理」) routes it to domain:cli; triage grades the priority.
Measured
- The probe.
packages/cli/test/published-entry-node-env-source-reroute.test.ts→it("CONTROL: neutralising the declaration in the child reproduces the card verbatim"). It reproduces finding: theos devcompile child still inherits an ambientNODE_ENV=development— the source-loader pin asserts "no write", which cannot see inheritance #12271 by letting@oclif/core'sts-pathreroute the published entry tosrc/commands. It fails in three independent dev containers, each time also on its own branch point:- chore(deps): move the CLI to @oclif/core 5, with plugin-help 7 and plugin-plugins 7 in one commit (#21125) #21212's dev, base
fbcc05f40; - fix(service-package, metadata-protocol): sys_packages is created and written on MySQL; a refused package write fails install and edit instead of answering success #21273's dev, branch point
434c6c7ca; - fix(cli): drop the never-loaded oclif.plugins entries and correct the text that says
os pluginsworks #21306's dev, base748b24072: "1 failed, 4 passed" with the same AssertionError.
- chore(deps): move the CLI to @oclif/core 5, with plugin-help 7 and plugin-plugins 7 in one commit (#21125) #21212's dev, base
- The cause. Read by the seat from the npm tarballs:
- In
tsx@4.23.15,dist/esm/api/index.cjscallsregister('./esm/index.mjs?…', { parentURL: <its own file> }). That resolves todist/esm/api/esm/index.mjs, which does not exist in the package. - In
tsx@4.23.12the call lives in a separate chunk, where the relative path resolves. - oclif's
ts-pathcatches the failure and logsCould not find tsx. Skipping tsx registration(oclif:config:ts-pathdebug). The rerouted entry then never loads TypeScript, and the CONTROL leg cannot reproduce the card.
- In
- When it started.
tsx4.23.12 → 4.23.15 enteredmainwithf3b16fc2f(chore(deps): take the 2026-10 production-dependency group without the better-auth family (#21094) #21162, 2026-10-01T13:24Z). There is no newer upstream release: 4.23.15 (2026-09-20) is the latest at filing. - Why it matters. The guard's two absence legs ("resolves commands from dist/ under an ambient NODE_ENV …") now pass over a trap that never arms. The finding: the
os devcompile child still inherits an ambientNODE_ENV=development— the source-loader pin asserts "no write", which cannot see inheritance #12271 regression they pin could return unseen. Any oclif-side TypeScript auto-transpile path (linked plugins,ts-pathin development) is also affected. - Not measured. CI's reading.
Test Corewas green on chore(deps): move the CLI to @oclif/core 5, with plugin-help 7 and plugin-plugins 7 in one commit (#21125) #21212's head, but this session's egress refuses the job-log storage, so whether CI's integration tier arms this leg is open. Measure it first, from a CI log or a run that reaches it.
What to do (shapes, not a ruling)
- Establish CI's reading of the CONTROL leg on current
main. - Choose a remedy and report the four-axis reasoning:
- (a) pin
tsxto the newest release whose ESM APIregister()resolves. That is a version DOWN, which needs the maintainer's ruling; - (b) a
pnpm patchoftsx4.23.15'sdist/esm/api/index.cjs, until upstream fixes it; - (c) rework the CONTROL leg so it arms without oclif's tsx registration, if that still reproduces finding: the
os devcompile child still inherits an ambientNODE_ENV=development— the source-loader pin asserts "no write", which cannot see inheritance #12271 faithfully.
- (a) pin
- ⛔ Never delete or skip the leg. Acceptance: the CONTROL leg reproduces the card again, and reverse verification turns the absence legs red when the
NODE_ENVdeclaration is neutralised.
Dedup: 450 objectstack issues and PRs listed over REST (open plus the most recently updated closed), titles and bodies grepped for Could not find tsx, tsx 4.23.15, node-env-source-reroute and esm/api. The hits are only the three PRs whose devs reported it in passing (#21212, #21273, #21306), with no card.
Dedupe words: Could not find tsx · tsx 4.23.15 esm api register · node-env-source-reroute CONTROL · ts-path tsx registration
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 2, 2026
Claim: PM loop round 5
Session:
session_018gA1pE6eJtwHhqx72G8U9XAccount:
os-bill(the seat's linked user asGET /useranswers it; the card's assignee from this act)Branch:
claude/issue-21308-tsx-esm-api-registerWorktree:
objectstack-issue-21308Domain:
domain:cliSeat: domain:devx#3 (the maintainer's direct-dispatch session; it holds no seat post, so #3 collides with no post: objectstack devx seats 1 and 2 are #6023 and #20163)
Provenance:
session_018gA1pE6eJtwHhqx72G8U9X, 2026-10-02.File surface, re-derived at
origin/main6091136e92:packages/cli/test/published-entry-node-env-source-reroute.test.ts, plus the roster inscripts/check-cli-test-child-env.mjsthat names its legs, if a leg changes.pnpm-workspace.yaml/ rootpackage.jsonpatchedDependencies,patches/tsx@4.23.15.patch, andpnpm-lock.yamlregenerated by the tooling (⛔ no hand edit)..changesetonly if something published moves (skip-changesetotherwise).tsxDOWN, needs the maintainer's ruling. The dev stops and reports rather than taking it.packages/cli/README.mdandpackages/cli/package.jsonare cli README: documents-h/-vshort flags that exit 2, and says there is noos plugincommand group whileos plugin build|sign|publishis registered #21310's surface. This card does not touch them.Container & model:
M(a dependency-packaging root-cause plus a test-validity repair, with a remedy choice to justify),mode:subagent,model: opus.dispatch-gates --tier --repo objectstack-ai/objectstackover this surface: no path-derived mandate.Clause-②: no
Thread-read: none
Serial constraints cleared:
origin/main6091136e92.os pluginsworks #21285 is closedcompleted(PR fix(cli): drop the never-loaded oclif.plugins entries and correct the text that saysos pluginsworks #21306 merged asdabd1c5be7). TheBlocked-by:line is removed from the body in this act.pnpm-lock.yaml, the rootpackage.json,pnpm-workspace.yaml,patches/or the reroute test.-h/-vshort flags that exit 2, and says there is noos plugincommand group whileos plugin build|sign|publishis registered #21310 is dispatched in the same act, on a surface made disjoint by the exclusions above.objectstack-fleet commentedon Oct 2, 2026
os-dev-report
{
"issue": 21308,
"status": "done",
"branch": "claude/issue-21308-tsx-esm-api-register",
"pr": "#21356",
"session": "session_018gA1pE6eJtwHhqx72G8U9X (the dispatching session; this run is its subagent)",
"premise_still_valid": true,
"summary": "Remedy (b): a pnpm patch of tsx@4.23.15 (patches/tsx@4.23.15.patch, a pnpm-workspace.yaml patchedDependencies entry with a note, and a lockfile pnpm install regenerated). It rebases three file-relative specifiers in dist/esm/api/index.cjs back to the files 4.23.14 resolved; 3 of 514 comma-separated tokens differ. The test file gains only a docblock pointer: no leg, assertion or bound changes. Premise refinement, measured: the defect is Node-version-gated. tsx takes its registerHooks path, which never reaches the broken specifier, on Node 22.22.3+, 24.11.1+, 25.1.0+ and 26+. So unpatched main is red on v22.22.0 (the dev containers) and 5/5 green on v22.22.3. A second casualty of the same defect, found and fixed by the same patch: on Node below 22.22.3 the source entry bin/run-dev.js also silently loaded dist/commands instead of src/commands, so the CLI's spawning tests measured the build output.",
"h0_ci_reading": "NOT MEASURED: unreachable. Job logs (productionresultssa14.blob.core.windows.net) and the run zip (results-receiver.actions.githubusercontent.com) for run 36964705223 on 6091136 were both refused at CONNECT with gateway 403. scripts/pm/ci-failure.mjs --run 36964705223 exited 2 (job log NOT RETRIEVED). What was measured instead is the deciding mechanism: tsx's version gate [[22,22,3],[24,11,1],[25,1,0],[26,0,0]], Node 22.22.3 released 2026-05-13, and CI setup-node floating on '22'. CI arms the leg if its runner resolved '22' to 22.22.3 or later; that resolution was not read.",
"remedy": {
"chosen": "b",
"a": "Not taken. A DOWN move to 4.23.14 needs a ruling, and measurement does not make it the only sound remedy.",
"c": "Rejected. Arming the leg without oclif's own tsx registration needs a test-only resolution shim (Module._resolveFilename in the preload, or --conditions=import on the child). The absence legs do not load the preload, so with unpatched tsx and the declaration deleted they stay green (measured: 1 failed, 4 passed). That fails acceptance criterion 2, unless every leg carries the shim and so measures a resolution no real install has.",
"four_axes": {
"business_need": "Measured. Two consumers break on Node below 22.22.3: this CONTROL leg, and bin/run-dev.js (104 test files under packages/cli mention it), which silently ran dist/. Published reach is none: bin/run.js sets enableAutoTranspile=false, and no packages/** source imports tsx/esm/api.",
"long_term": "A workaround for an upstream packaging defect, with its cost stated. The patch replaces one 16 KB minified line, reviewable only through the token comparison in the PR body. The exact-version key makes a tsx bump fail pnpm install (ERR_PNPM_UNUSED_PATCH, the same rule as the tsup@8.5.1 entry). Retire it when tsx resolves the three paths itself or the toolchain's Node floor reaches 22.22.3. Option (c) would carry a shim with no such tripwire.",
"ai_mistakes": "(b) gives the probe one meaning in every environment. Today it is green in CI and red in dev containers, and three devs reported that red in passing without a card. (c) adds a second resolution dialect inside a test fixture.",
"startup_focus": "No new gate, no new dependency, no version movement."
}
},
"control_leg": {
"before": "6091136e9, unpatched, v22.22.0: 1 failed (CONTROL: output only '@objectstack/cli/17.6.0 linux-x64 node-v22.22.0'), 4 passed. DEBUG=oclif:config:ts-path shows 'Could not find tsx' plus ERR_MODULE_NOT_FOUND for tsx/dist/esm/api/esm/index.mjs, then 'Cannot find module ts-node'. Same tree on v22.22.3: 5 passed.",
"after": "Patched: 5 passed on v22.22.0 (cc0c05b, 6a22902 in tier batch 1, 8569d5f) and 5 passed on v22.22.3 (cc0c05b, 8569d5f). DEBUG trace: 'Successfully imported tsx', 'Found source directory ... at packages/cli/src/commands', card signature 4x, exit 1."
},
"reverse_verification": "Declaration removed with scripts/ablation-replace.mjs --delete on packages/cli/bin/run.js (anchor 1 to 0, blob 569e6b6f to 40a368ce) and restored by the same tool (blob equals HEAD, git diff HEAD empty). Patched, cc0c05b, v22.22.0: the development and test legs go red, 2 failed / 3 passed, each 'not to contain Cannot find module ./registry'. Same deletion with packages/cli/node_modules/tsx linked to the pristine 4.23.15 under a trapped restore (checked with readlink): 1 failed (CONTROL) / 4 passed, so the absence legs are vacuously green. That is the issue's claim, measured. bin/run.js runs unbuilt, so no dist step was involved.",
"lockfile": "Regenerated by pnpm install. With the tsx patch hash normalised away, removed lines equal added lines except the 3 new patchedDependencies lines. 0 versions moved, 0 DOWN, 0 packages added or removed. 10 snapshot keys renamed only by the hash suffix: tsx, tsup, postcss-load-config, fumadocs-mdx, vite x2, vitest x2, @vitest/mocker x2. pnpm install --frozen-lockfile passes at 8569d5f.",
"tests": "Final head 8569d5f (two merges of origin/main after the fix; the incoming commits touch no CLI file, the lockfile, pnpm-workspace.yaml or tsx; objectql, plugin-auth and rest were rebuilt). dispatch-gates --commands derived 58 commands from 4 paths; all 58 run with exit codes captured before any pipe, all exit 0. --ran: '58 derived famil(ies) accounted for — 58 run, 0 NOT-MEASURED'. check:nul-bytes: OK over 9638 files. Reroute file at 8569d5f: 5 passed on v22.22.0 and 5 passed on v22.22.3. CLI unit tier at 6a22902: 244 files, 3461 tests passed. CLI integration tier at 6a22902, two lock-held runs: 27 + 44 = 71 files, 607 passed, 1 skipped (the existing it.skipIf in test/migrate-meta-default-range.test.ts, a file this branch does not touch). pnpm --filter @objectstack/cli typecheck at 6a22902: exit 0, check:test-typecheck included. An earlier gate pass at 6a22902 got PREREQUISITE NOT MET (exit 3) from check:dual-build-cjs-loads while sibling dist/ were missing; re-run once built, it passed (105 entry points across 66 packages). NOT MEASURED: pnpm lint, repo-wide (CI's run).",
"pr_subscribed": "Subscribed to activity on #21356.",
"changeset": "skip-changeset: nothing published moves. @objectstack/cli files are [dist, README.md, CHANGELOG.md]; the test file, patches/, pnpm-workspace.yaml and pnpm-lock.yaml are not shipped by any package.",
"mcp_calls": "1 — mcp__claude-code-remote__subscribe_pr_activity (a session subscription, not a GitHub write); 0 MCP GitHub tools",
"api_writes": "3 relay strokes, 4 endpoint writes: pr_create POST /repos/objectstack-ai/objectstack/pulls (#21356, draft, body read back byte-identical); label-write labels_add POST /issues/21356/labels (skip-changeset) and assign POST /issues/21356/assignees (os-bill), both read back; this os-dev-report comment POST /issues/21308/comments. Plus git push of the branch (not REST).",
"open_questions": [],
"out_of_scope_findings": [
"carrier: none · noted, not filed · The dev containers run Node v22.22.0 while CI's setup-node floats on '22'; that gap is why the same file reads red locally and green in Test Core. An observation, recorded in the PR Acceptance notes.",
"carrier: none · noted, not filed · An upstream tsx 4.23.15 packaging defect (CommonJS tsx/esm/api register on Node without registerHooks). Not this repo's tracker. The privatenumber/tsx API is unreachable from this session, so whether an upstream issue exists was not read. The retirement condition lives in the pnpm-workspace.yaml note.",
"carrier: none · noted, not filed · Published @objectstack/cli ships tsx ^4.23.15 as a runtime dependency, but no public entry point reaches the defect (bin/run.js disables auto-transpile; no packages/** source imports tsx/esm/api). No reach, so no card."
]
}
Generated by Claude Code
fix(deps): patch tsx 4.23.15 so oclif registers it on every supported…
fix(cli)!: os verify runs the author-time rules first, and a stack th…