release: v1.4.0 - #8
Merged
Merged
Conversation
…ndows fixes) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…iscovery Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…n contract, node 24 tooling, CI dedupe) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…de/signal expectations) - .gitattributes forces LF; scripts/run-tests.mjs lists tests/*.test.mjs explicitly (Node 18/22/24, cmd.exe) and forwards extra CLI args. - prebuild uses node's mkdirSync instead of POSIX mkdir -p. - run() no longer defaults to a shell; tests spawn process.execPath. - test-env uses fileURLToPath; commands.test normalises CRLF; transfer tests fake USERPROFILE via homeEnv(); broker-endpoint expectation uses the host path.join; the torn-state writer runs from a temp module. - POSIX-only scenarios (mode bits, SIGTERM-immune/graceful-SIGTERM, pgrep, kill(-pid), npm-less PATH) are skipped or guarded on win32; awaited cancel accepts the documented cancellationPending on win32. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Group-kill cleanups (kill(-pid)) fall back to kill(pid) so a missing process group (win32) never leaks the child. The awaited-cancel test keeps the text cancel output on POSIX and uses --json only for the win32 assertion. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
On win32 a record without a worker identity is never signalled until v1.4.1: cancel answers cancellationPending/identity-unavailable with exit 1, SessionEnd keeps the record and says why, and ensureBrokerSession kills nothing. The affected tests assert that documented outcome on win32; the POSIX expectations are unchanged. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…en reader Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…xpectation on win32 - state: the torn-state test is skipped on win32 (rename over an open reader is EPERM there); the product retry lands in Task 7, which un-skips it. - runtime: the running job's own file now says `running`, as a live worker's does; the status-less fixture read as terminal on disk and the reaper reconciled that into the record SessionEnd kept on win32. The win32 branch asserts the kept record exactly; the awaited-cancel win32 branch asserts the whole refusal payload. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ndabot, SECURITY.md, changelog gate - eslint flat config, tsconfig.tests.json (extends tsconfig.app-server.json; checkJs off for now: 54 errors in tests/) - check:changelog accepts `## 1.3.0 — date` headings and requires CHANGELOG.md and plugins/codex/CHANGELOG.md to be identical - c8 coverage via .c8rc.json (thresholds = measured - 2), Stryker critical shard over args.mjs and model-catalog.mjs with a weekly workflow - model-catalog unit tests for source fallback, normalisation and caching - pre-commit hook, dependabot, SECURITY.md, README Development section - quality CI jobs run changelog, lint and tests typecheck; PR CI adds coverage Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…f the Stryker sandbox - the erroring-codex case now carries a real catalogue so the error path is what is asserted; timeoutMs no longer pinned - stryker ignorePatterns for .worktrees/docs/.superpowers/reports - README: setup:git-hooks writes the shared .git/config and needs the codex CLI Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A backslash escapes only a following quote, backslash or whitespace. Before any other character it stays literal, so Windows paths survive. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A trailing backslash is now appended inside the loop (nothing follows it to escape), so the post-loop branch could never run. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
….exe launch for .cmd shims, direct taskkill/powershell
On win32 nothing runs through a shell any more. Git Bash as $SHELL (the
usual case on GitHub runners) mangled `taskkill /PID` and PowerShell
arguments.
- resolveExecutable: raw spawnSync("where.exe") (shell:false, 5s timeout),
first hit whose extension is in PATHEXT (.com/.exe/.bat/.cmd); the
extensionless bash shim is skipped; nothing found -> null, and the bare
name is spawned so ENOENT surfaces as before.
- buildLaunch: .exe/.com run directly; .cmd/.bat run as
`cmd.exe /d /s /c "<line>"` with windowsVerbatimArguments. quoteForCmd
applies CRT quoting, then caret-escapes the cmd metacharacters twice (once
for cmd /c, once for the shim's %* re-parse), as cross-spawn does for
cmd-shims, so `a&b` and `%PATH%` stay literal.
- runCommand: shell:false on win32; paths and explicit extensions skip
where.exe. Posix is unchanged.
- terminateProcessTree spawns taskkill.exe with shell:false; its flags,
missing-process detection and ENOENT fallback are unchanged.
- app-server spawns the resolved codex launch with shell:false; the
terminateChild comment now names the cmd.exe -> node -> codex tree.
- spawnBrokerProcess sets windowsHide.
- Fake codex fixture on win32: codex.cjs + codex.cmd shim pointing at it.
- README: codex/npm reachable only inside Git Bash are no longer found.
Co-authored-by: mohammad-malik <mohammad-malik@users.noreply.github.com>
Co-authored-by: mittalpk <mittalpk@users.noreply.github.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- where.exe searches $PATH: only, never the current directory, and shares the caller's timeout budget instead of adding up to 5 s to it - cmd.exe runs with /v:off so a literal ! survives; a line break in an argument is refused instead of silently truncating the command line - %VAR:a=b% substitution stays a documented ceiling: every caller passes literals - round-trip test adds ^, ! and a path with parentheses Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…eview prompt via stdin New lib/hook-input.mjs readHookInput(): streams stdin with a deadline (2 s default, CODEX_HOOK_STDIN_TIMEOUT_MS for tests), a 1 MiB byte limit and a StringDecoder across chunk boundaries. EOF parses the whole input; at the deadline a buffer that is already a complete JSON object is accepted (only the EOF was late), anything else is `timeout`; over the limit is `overflow` without parsing; bad JSON is `invalid-json`. Listeners and the timer are removed and stdin destroyed, so the hook exits right after deciding. Stop hook: any read error blocks as before (fail-closed), except a timeout with nothing received while the workspace gate (CLAUDE_PROJECT_DIR / cwd) is off, which allows (openai#530/openai#544). With the gate on, a timeout blocks naming "hook input did not arrive". The review prompt now reaches the companion via `task --prompt-stdin`, not argv, lifting the Windows/Linux argv limits. SessionStart/SessionEnd hook: reads with a 1 s deadline before the 12 s SessionEnd budget starts; on any read error it prints one stderr line and returns without cleanup. The hooks.json timeout test now asserts 15 s > budget + read. readStdinIfPiped (companion): readSync loop that keeps accumulated bytes across EAGAIN on a non-blocking stdin (up to 50 x 20 ms consecutive) and throws on exhaustion instead of returning a partial prompt (openai#120/openai#247/openai#123/openai#150/openai#165). Co-authored-by: stantheman0128 <stantheman0128@users.noreply.github.com> Co-authored-by: tmchow <tmchow@users.noreply.github.com> Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…put; unreadable state keeps the gate closed 1. A stdin stream error is a distinct read-error outcome, never the deadline. 2. The deadline path flushes the UTF-8 decoder before the completeness check. 3. gateEnabledForProject reads state.json itself; an unreadable or corrupt file keeps the gate on instead of reading as defaults (gate off). 4. A no-op error listener stays after the read so a failing destroy() cannot crash the hook. 5. SessionStart reads stdin with a 5 s deadline; SessionEnd keeps 1 s. 6. Open-stdin tests carry a 30 s timeout and SIGKILL the child after 20 s. 7. Overflowing hook input with the gate off allows the stop; gate on blocks. 8. EAGAIN test gap 2500 ms; README names the always-blocked case and the escape hatch. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Mirrors the local gate (sleep 10; pgrep -f codex-plugin-test-) on every matrix job; Windows lists matching Win32_Process rows. Reported only until the Windows kill path lands in v1.4.1. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…nded EPERM retries on Windows - state.mjs: resolveFallbackStateRoot takes a `platform` option; on win32 with LOCALAPPDATA set the root is %LOCALAPPDATA%\codex-companion\<hash> (the per-user profile ACL stands in for the POSIX owner/mode check, which is unchanged). A pre-1.4.0 <tmpdir>\codex-companion-user\<hash> root keeps being used, without migration, while the new one does not exist; one stderr notice per process. - state.mjs: new retryOnWindows(op, codes) helper: win32 only, listed codes only, 20 attempts 15 ms apart, then rethrows the last error unchanged. writeFileAtomic retries the rename on EPERM/EBUSY/EACCES (rename over an open reader); readLockEntryOwner retries the ticket read on EPERM/EBUSY (read racing a peer's rename/unlink); loadState retries its read on EBUSY. Lock and kill semantics are unchanged. - tests: un-skip "concurrent writers never leave a torn state.json" on Windows; helper tests with a fake op (recovers after 19, rethrows the 20th, no retry on posix or ENOENT); fallback root with/without LOCALAPPDATA and the transitional legacy-root case. - README: Windows section names %LOCALAPPDATA%\codex-companion and the transitional policy. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A reader racing a writer's rename over state.json sees EPERM as well as EBUSY, as the lock-ticket reader did on CI. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- model catalogue fixture: catalogue-only `nova` alias (gpt-7-nova / gpt-6-nova,
priority 0) proves resolution comes from the catalogue, not FALLBACK_ALIASES,
and that a priority tie picks the newest family
- state: refusal test chmods 0o755 explicitly (umask-independent); new
foreign-uid refusal test
- stop gate: CODEX_REVIEW_GATE_MAX_ROUNDS accepts only a non-negative integer
(0 = unlimited); anything else falls back to 3 with one stderr warning;
tests for =0, =5 and =0.5
- setup: an empty --review-gate-model / --review-gate-effort is rejected
("use inherit to clear") before anything is written
- broker teardown: document the reason enum including kill-failed (JSDoc +
README table)
- workerCommandLine escapes the job id (strictly narrower matching)
- runtime G1 test kills the SIGTERM-immune worker group in t.after; fresh-broker
test title/comment say "killed as a process group"
- README transfer: one clause for ~/.claude/projects / $CLAUDE_CONFIG_DIR/projects;
registerThread comment on the single-tenant broker assumption
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…retries and identity-match Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The duplicate added in dfd941d failed under pipefail when pgrep found nothing; the existing step now covers Windows with a Win32_Process listing and runs after a red suite too. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… wording - fixture lists the older family first and the test also checks the reversed catalogue, so a stable sort by priority alone fails it - identity-mismatch and command-line-match rows describe what the code does - max-rounds warning says "plain digit string" Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The same single test measured 6.6 s on one hosted VM and 33 s on another with identical code, so the turn-timeout assertion is now relative to a 20 s fake turn, the cancel test waits up to 30 s for the running job, and the matrix jobs get 40 minutes. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
CI runners set LOCALAPPDATA, so since 35f6bed the fallback root lives there, not under the temp dir. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
README: drop the demo video element; rewrite the Windows section to reflect v1.4.0 as shipped (spawn no longer goes through $SHELL, bounded hook stdin, %LOCALAPPDATA% fallback root and its transitional notice, bounded EPERM/EBUSY/EACCES retries) and correct the stale "identity lands in v1.4.0" claim to v1.4.1. CHANGELOG: add the 1.4.0 section (Added/Changed/Fixed/Known limitations) and copy it to plugins/codex/CHANGELOG.md. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…w second spawn - the refusal case no longer races a real writer against the retry budget: the child's readSync throws EAGAIN forever and the call count is asserted - the shared app-server test gives the broker a 15 s idle timeout so a slow runner cannot let it exit between the two CLI runs Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
libuv searches the child cwd before PATH, so a bare where.exe/cmd.exe/ taskkill.exe would run a same-named file planted in the reviewed repo. Also: gate state read tolerates a transient EPERM; hook timing pins 10 s; release-verify gets the cross-platform leak step and a 20-min quality job; changelog names the cmd.exe quoting ceilings and lock-ticket reads. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…dir keeps the gate closed - runCommand and the app-server launch report ENOENT without spawning when where.exe finds nothing, so libuv never searches the workspace for a same-named .exe - gateEnabledForProject reads state.json directly: only ENOENT means "never configured"; EACCES on the file or a parent (where existsSync says false) keeps the gate closed Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…m the cwd npm .cmd shims run a bare `node`; cmd.exe looks it up in the current directory (the reviewed repo) before PATH. Both cmd.exe launch paths now set NoDefaultCurrentDirectoryInExePath=1, and the Windows round-trip test plants a node.cmd sentinel in the cwd. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Draft one English comment per upstream issue closed by v1.4.0 (Windows spawn/taskkill cluster, windowsHide, stop-hook stdin deadline, EAGAIN retries), and update the triage doc's statuses/queue buckets to match: fixed-in v1.4.0 for those 9 issues plus their reference PRs and openai#326/openai#735, planned v1.4.1 for openai#336/openai#423/openai#577 (Windows process-identity work deferred from v1.4.0), and a note on openai#743 that the Windows kill-from-record refusal now targets v1.4.1. Docs only, nothing posted upstream. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The test harness, spawn path and state retries now pass on windows-latest, so the continue-on-error escape hatch from the CI spike is removed in both workflows. Only the Windows leak report stays advisory until v1.4.1. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
openai#626/openai#633 were fixed in v1.3.0 (comment drafts added); openai#70/openai#416/openai#487/openai#718 move to v1.4.1 (kill from stored records), openai#57/openai#349 to v1.5.0 (sandbox surface), the rest to verify after a reporter retest. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ere.exe where.exe output is in the console code page, so a non-ASCII install path came back mangled under UTF-8 decoding. The lookup now walks PATH and PATHEXT with fs: no child process, no decoding, relative entries and the cwd are never searched, extensionless shims are never hits. Docs: the Windows kill limitation no longer promises an interrupt on SessionEnd or a bounded leak; cancel interrupts best-effort, a leaked broker exits on idle once every client has disconnected. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
NoDefaultCurrentDirectoryInExePath only removes the implicit cwd; an explicit "." or relative "tools" entry in PATH would still let the shim's bare node resolve inside the reviewed repo. cmd.exe now gets the same absolute-only PATH the resolver walks, under the caller's own PATH key. The Windows round-trip test plants node.cmd in the cwd and under a relative entry. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…he turn A plain turn always gets turn/completed. Inferring completion 250 ms after the final answer let a delayed terminal notification with status "failed" be recorded as "completed" on slow hosts (openai#757 test flaked twice on CI). The fake codex can now delay that notification to reproduce it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…rn as failed captureTurn now observes the client's exit and finalizes the turn as failed with the captured output, standing down while the turn-timeout path owns the outcome. The broker shuts down when its shared app-server exits so every client sees its socket close. The fake codex can exit right after the final answer; direct and brokered regressions added. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…worker's broker alive The test has failed twice on ubuntu/node 18 in CI with "still serving another session"; the socket accounting in the broker log is what explains that. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
CBEPX
added a commit
that referenced
this pull request
Sep 28, 2026
- CI leak check and cimTree helper follow the PowerShell launch rules: absolute in-box path (helper via runPowerShell), ASCII protocol on stdout, table on stderr - parseProtocolLines checks exact lines without trim; TAB/NBSP/empty-line junk tests - renderCancelPending/emitCancelPending given in full with survivors.length > 0; emit test with injected stdout/stderr/log writers - hook keeps main().catch inside the direct-execution guard - Task 6 README: file-based resolver, no where.exe, CR/LF and %VAR:a=b% ceilings - ROOT is local to runtime.test.mjs; fileTimeAt everywhere Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Release v1.4.0: engineering maturity plus Windows without
$SHELL. The Windows CI matrix is now required.Fixed
$SHELL(usually Git Bash under Claude Code, which mangledtaskkill /PID /T /Fand other arguments); executables are resolved withwhere.exe,.exe/.comfiles run directly, and.cmd/.batshims (including a globalnpm install -g @openai/codex) run throughcmd.exewith every argument escaped for bothcmd /cand the shim's own%*re-parse (%VAR:a=b%substitution is the one documented ceiling; an argument containing CR/LF is refused) (Windows: taskkill /PID is mangled by MSYS path conversion when SHELL is set (Git Bash under Claude Code) — cancel and SessionEnd cleanup never kill the process tree openai/codex-plugin-cc#525, Windows: SHELL env var (Git Bash) breaks taskkill; handleCancel swallows terminateProcessTree exceptions, leaving jobs stuck in running/finalizing openai/codex-plugin-cc#647, fix: Windows SHELL env var breaks taskkill; handleCancel aborts before updating job state on a partial kill failure openai/codex-plugin-cc#656, fix: resolve executables instead of shell-wrapping SHELL on Windows spawns openai/codex-plugin-cc#669, Windows:cancelsilently fails — Git Bash manglestaskkill /PID /T /Fflags, leaving jobs stuck asrunningopenai/codex-plugin-cc#708, Windows: spawn("codex") in app-server.mjs throws ENOENT (Node does not try PATHEXT for .cmd shims) openai/codex-plugin-cc#287, [Windows] POSIX path conversion mangles slash-prefixed CLI args under Git Bash openai/codex-plugin-cc#409, Do not run taskkill through a shell on Windows openai/codex-plugin-cc#735).windowsHide: true) (spawnBrokerProcess() missing windowsHide: true — leftover spawn site from #67 openai/codex-plugin-cc#440, fix: hide detached broker window on Windows openai/codex-plugin-cc#451).Stop,SessionStartandSessionEndhooks read stdin with a bounded deadline (2 s / 5 s / 1 s respectively) and a 1 MiB limit instead of a blockingreadFileSync(0); a disabled Stop review gate no longer hangs until the 900 s hook timeout when stdin never arrives, and the companion no longer crashes withEAGAINreading a non-blocking stdin under concurrent sessions (Stop hook hangs until 900s timeout on Windows even when review gate is disabled (stdin EOF never arrives) openai/codex-plugin-cc#530, fix: bound Stop hook stdin read so disabled gate cannot hang on Windows (#530) openai/codex-plugin-cc#544, EAGAIN crash in hook scripts: readFileSync(0) fails when stdin is non-blocking openai/codex-plugin-cc#120, codex-companion crashes with EAGAIN on concurrent sessions (readStdinIfPiped sync read) openai/codex-plugin-cc#247, fix: handle EAGAIN in hook readFileSync(0) for non-blocking stdin openai/codex-plugin-cc#123, fix: handle EAGAIN in hook scripts readHookInput (#120) openai/codex-plugin-cc#150, fix: handle EAGAIN in hook scripts when stdin is non-blocking openai/codex-plugin-cc#165).--args-stdin(and$ARGUMENTS) no longer eats a backslash that does not escape a quote, another backslash or whitespace, so Windows paths such asC:\Users\me\project\file.mjssurvive;\\server\shareis a documented limitation, and--prompt-stdinremains available for byte-exact text.state.jsonreads and writes and lock-ticket reads retry briefly (bounded, roughly 300 ms worst case) onEPERM/EBUSY/EACCESinstead of failing outright when another process holds the file open.Added
SECURITY.md(supported versions, GitHub Security Advisories reporting) (Create SECURITY.md for security policy openai/codex-plugin-cc#326).typecheck:testsscript overtests/**andscripts/**(checkJsis off for now — turning it on surfaced 54 pre-existing findings, deferred),c8coverage (npm run test:coverage, thresholds in.c8rc.json), Stryker mutation testing over the criticalargs.mjs/model-catalog.mjspair (npm run test:mutation:critical), acheck:changeloggate that keepsCHANGELOG.mdandplugins/codex/CHANGELOG.mdbyte-identical, Dependabot, andnpm run setup:git-hooks(pre-commit lint + typecheck).main, release branches checked via manualworkflow_dispatch, with aconcurrencygroup cancelling superseded runs) and a newqualityjob on Node 24 alongside the existing OS × Node matrix.Changed
CLAUDE_PLUGIN_DATAis unset is now%LOCALAPPDATA%\codex-companionon Windows. A pre-1.4.0 root under%TEMP%\codex-companion-userkeeps being used, with a one-line stderr notice, until it is removed by hand — nothing is migrated automatically. This transitional notice only applies to an unversioned/dev checkout: a marketplace install's state-root hash is derived fromCLAUDE_PLUGIN_ROOT, which already includes the plugin version in the marketplace cache, so a normal upgrade never sees the legacy root.BROKER_BUSY_RETRY_MSwidened from 1000 to 3000 ms; the "teardown only after the broker confirmed idle" invariant is unchanged.CODEX_REVIEW_GATE_MAX_ROUNDSrejects a non-integer, negative or otherwise malformed value (falls back to 3 with a warning) instead of misreading it;setup --review-gate-model ""/--review-gate-effort ""now fails with--<flag> needs a value; use inherit to clear it.instead of writing anything; a job id used to build theworkerCommandLinematch is now regex-escaped; thekill-failedbroker-teardown reason is documented in the README's reason table. Also added (test coverage only, no behavior change): a catalogue-only model alias resolving correctly on a priority tie, and the fallback-root refusal covering a non-standard directory mode.Known limitations
/codex:cancel,SessionEndcleanup, stale-broker replacement, broker teardown) are still refused on Windows (identity-unavailable); process identity verification is now targeted for v1.4.1, not v1.4.0 as previously stated./codex:cancelstill sends the turn interrupt on a best-effort basis;SessionEndonly refuses. A worker or broker left behind exits when its turn ends and, for the broker, once every client has disconnected and its idle timeout elapses — an unbounded turn is not reaped on Windows until v1.4.1.Ported with reference to upstream PRs by mohammad-malik, mittalpk, stantheman0128, tmchow, D2758695161, ikbear, e345ee, tanakauo.
Gates
--effort max), passes 1-5 found real Windows executable-resolution paths (bare where.exe/taskkill/cmd via cwd, unresolved-name fallback, shim interpreter via cwd, where.exe code-page decoding, relative PATH entries) - all fixed; pass 6 = SHIP.npm run check357 tests / 356 pass / 1 win32-only skip, 0 leaked test processes,claude plugin validate . --strict,npm audit --omit=dev0 vulnerabilities,npm pack --dry-run101 files..superpowers/sdd/2026-09-28-codex-plugin-cc-v1.4.0/in the release worktree (archived underdocs/superpowers/reports/v1.4.0/after merge).🤖 Generated with Claude Code