Reuse the existing scripts boundary asset and guard for commands-core without hooks. Preflight selected helper scopes and preserve user module metadata, unowned/edited JS interpretation, and boundary ownership through uninstall. Actual installed ESM help/JSON, receipt, reinstall/uninstall and 34 focused cases pass. OpenCode boundary 8/8, adapters 51/51, manifests 43/43; focused coverage exceeds 80%. Two root-owned legacy ESM core-profile fixtures require correction; no unsupported states weakened.
Actual installed skills-health --help fails with require undefined in ESM Claude project and home fixtures. RED evidence: command-runtime-evidence/red-final.log; bounded repair remains pending.
Scoped adaptation from PR #3088. Keep the canonical atomic writer and dispatcher; exclude the broader provider/tool changes.
Co-authored-by: Geronimo <varungore1@gmail.com>
Reproduced issue #3485 on installed Codex CLI 0.162.0. Keep user legacy choices for explicit migration and verify disposable install, repair, reinstall and removal.
Verify PCRE2 on every hosted test platform and coverage runner. Preserve dependency PATH for real scanner delegates and report missing prerequisites explicitly, keeping production fail-closed behavior and hermetic missing/error controls intact.
Three open review findings still pass the gate with a missing dependency,
each reproduced against the real registry:
- const ratio = {} / 2; require('../x') -- `}` is treated as a statement
boundary, so the division reads as a regex that swallows the require.
a.of / 2 does the same through the keyword list.
- [...require('../x')] -- the member-call guard reads the last dot of the
spread as member access and skips the call.
- require('../x', null) -- a literal counts only when the call closes right
after it, so the specifier is demoted to a dynamic warning, which never
fails.
14 cases, 11 failing. Controls that already pass: a regex after a function
body, a class body and a nested block.
Two first-round review findings were never addressed, and both reproduce
on the current head:
- records.require('./label'), obj?.import('./x') and obj . require('./y')
are method calls, but the call pattern's word boundary is satisfied by
the dot, so a self-contained object method fails every projection for a
file the script never loads.
- The dynamic-argument pattern allows one level of nested parentheses, so
require(path.join(__dirname, getName())) produces no dynamic warning
while require(getName()) does.
Control: a genuine require beside the member calls is still a dependency.
Review on dd14493e found four more ways the closure gate misjudges a
carrier, each reproduced against that head:
- require('./helper') resolves when only helper.cjs or helper.mjs is
planned, but Node's CommonJS search tries only .js, .json and .node.
- In `if (ok) {} /"/.test(text); require(...)` the regex after the block
is read as division and its quote swallows the require.
- `obj.\nif(x) / 2` is a method call, but the condition check only saw
the character immediately before `if`, so the division read as a regex
and swallowed a later require. Introduced by the previous fix.
- A tagged template named `from` was recorded as an import; with exact
import resolution it now fails a carrier that never loads that path.
Introduced by the previous fix.
Controls: an extensionless require still resolves to a .json file, and a
template literal passed to import() is still a dependency.
Review on aec97150 found four ways the closure gate passes a carrier that
fails at run time. Each is reproduced here against the current head:
- import('./helper') with only helper.js planned is accepted, but Node's
ESM resolver does no extension search.
- import('./data') with only data/index.json (or index.js) planned is
accepted, but Node rejects directory imports even from CommonJS.
- require('./lib\helper.js') with lib/helper.js planned is accepted
because backslashes were normalized, but Linux and macOS read the
backslash as part of the filename.
- In `if (ok) /['"]/.test(text); require('./missing')` the regex after
the condition's closing paren is read as division, its quote opens a
fake string, and the require disappears.
Controls that must keep passing: an exact import() of a planned file, an
extensionless require through the CommonJS search, and division after a
method named `if` or a call nested inside a condition. extractReferences
gains an `imports` list so the resolver can tell the two forms apart.
Preserve main OpenCode lease and activation gates and native Claude namespace receipts. Detect same-size in-place edits using bigint modification and change times during hashing and before deletion; verify both races and actual public CLI reinstall lifecycles.