From d65bc32421ccc7c66cff79978aeea5e214c8ac50 Mon Sep 17 00:00:00 2001 From: Harry Du Date: Wed, 26 Aug 2026 13:46:47 -0700 Subject: [PATCH 1/2] fix(launcher): report signal deaths as 128+signal instead of exit 0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit execFileSync throws with status: null when the child dies from a signal; the launcher's 'status' in e check passed, so process.exit(null) turned SIGTERM/SIGSEGV/OOM-kill/Ctrl-C into exit 0 — any script or agent checking $? saw success from a killed process. npm path only; the direct binary and installer paths were unaffected. Now: numeric status passes through unchanged, signal deaths exit 128+signum per shell convention (SIGTERM -> 143, SIGSEGV -> 139), unknown signals -> 1. Verified with a stub binary: 42/TERM/SEGV/0 -> 42/143/139/0. Version -> 1.0.1 (Cargo.toml + lock) so the release tag matches the version guard. This hand-patches generated ci.yml deliberately: a regeneration would also resurrect the deferred win32 matrix and the unfixed launcher, so the generator-side fix is filed with Fern and this carries us until the next full regen. --- .github/workflows/ci.yml | 16 ++++++++++++++-- Cargo.lock | 2 +- Cargo.toml | 2 +- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 717328f..582039a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -288,8 +288,20 @@ jobs: try { execFileSync(binPath, process.argv.slice(2), { stdio: "inherit" }); } catch (e) { - if (e && typeof e === "object" && "status" in e) { - process.exit(e.status); + if (e && typeof e === "object") { + // Normal non-zero exit: pass the code through. + if (typeof e.status === "number") { + process.exit(e.status); + } + // Signal death (SIGTERM/SIGSEGV/...): execFileSync reports + // status: null + signal. Exiting with e.status here becomes + // process.exit(null) -> 0, turning a killed process into + // "success" for any caller checking $?. Use the shell + // convention 128+signal instead (SIGTERM -> 143). + if (e.signal) { + const signum = (os.constants && os.constants.signals && os.constants.signals[e.signal]) || 0; + process.exit(signum ? 128 + signum : 1); + } } throw e; } diff --git a/Cargo.lock b/Cargo.lock index 3797534..f7b4afb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,7 +10,7 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "agentmail-cli" -version = "1.0.0" +version = "1.0.1" dependencies = [ "agentmail_sdk", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index 9607486..537d8b2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "agentmail-cli" -version = "1.0.0" +version = "1.0.1" edition = "2021" description = "Command-line interface for the AgentMail API. Send, receive, reply, and manage threaded email conversations from your terminal." license = "MIT" From 41466dbec12f3fd8c241b8027053a1562e8a7e49 Mon Sep 17 00:00:00 2001 From: Harry Du Date: Thu, 27 Aug 2026 12:13:15 -0700 Subject: [PATCH 2/2] fix(ci): any SemVer prerelease gets its own dist-tag, never latest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both publish jobs only recognized *-alpha* and *-beta*. A v1.1.0-rc.1 or v1.0.0-next.1 tag fell through to a bare `npm publish`, which would have moved the `latest` dist-tag to a prerelease — every `npm i -g agentmail-cli` user upgraded onto it. Now any identifier after the first "-" becomes the dist-tag (rc, next, alpha, beta, ...), with build metadata stripped and a `prerelease` fallback. Release versions still take the existing latest/backport path. Verified: 1.0.1 -> latest/backport path 1.1.0-rc.1 -> --tag rc 1.1.0-next.1 -> --tag next 2.0.0-alpha.3 -> --tag alpha (unchanged) 1.0.0-beta -> --tag beta (unchanged) 1.0.0+build7 -> latest/backport path 1.0.0-rc.1+meta -> --tag rc 1.0.0- -> --tag prerelease Hand-patch on generated ci.yml, same as the launcher fix; filed with Fern for the template. --- .github/workflows/ci.yml | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 582039a..dc075d7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -189,10 +189,18 @@ jobs: # release tag like v1.0.0 for a package whose version string # happens to contain "alpha"/"beta" as a substring isn't # mis-tagged on npm. - if [[ "${VERSION}" == *-alpha* ]]; then - npm publish --access public --tag alpha - elif [[ "${VERSION}" == *-beta* ]]; then - npm publish --access public --tag beta + # Any SemVer prerelease (identifier after the first "-") publishes + # under its own dist-tag, never "latest": alpha/beta/rc/next/... A + # tag like v1.1.0-rc.1 previously fell through to a bare publish and + # would have moved "latest" to a prerelease. + PRERELEASE="${VERSION#*-}" + if [[ "${PRERELEASE}" != "${VERSION}" ]]; then + DIST_TAG="${PRERELEASE%%.*}" # 1.0.0-rc.1 -> rc + DIST_TAG="${DIST_TAG%%+*}" # strip build metadata + DIST_TAG="$(printf '%s' "${DIST_TAG}" | tr -cd '[:alnum:]-')" + [[ -z "${DIST_TAG}" ]] && DIST_TAG="prerelease" + echo "Publishing prerelease ${VERSION} with --tag ${DIST_TAG}" + npm publish --access public --tag "${DIST_TAG}" else PKG_NAME=$(node -p "require('./package.json').name") PKG_VERSION=$(node -p "require('./package.json').version") @@ -312,10 +320,18 @@ jobs: # release tag like v1.0.0 for a package whose version string # happens to contain "alpha"/"beta" as a substring isn't # mis-tagged on npm. - if [[ "${VERSION}" == *-alpha* ]]; then - npm publish --access public --tag alpha - elif [[ "${VERSION}" == *-beta* ]]; then - npm publish --access public --tag beta + # Any SemVer prerelease (identifier after the first "-") publishes + # under its own dist-tag, never "latest": alpha/beta/rc/next/... A + # tag like v1.1.0-rc.1 previously fell through to a bare publish and + # would have moved "latest" to a prerelease. + PRERELEASE="${VERSION#*-}" + if [[ "${PRERELEASE}" != "${VERSION}" ]]; then + DIST_TAG="${PRERELEASE%%.*}" # 1.0.0-rc.1 -> rc + DIST_TAG="${DIST_TAG%%+*}" # strip build metadata + DIST_TAG="$(printf '%s' "${DIST_TAG}" | tr -cd '[:alnum:]-')" + [[ -z "${DIST_TAG}" ]] && DIST_TAG="prerelease" + echo "Publishing prerelease ${VERSION} with --tag ${DIST_TAG}" + npm publish --access public --tag "${DIST_TAG}" else PKG_NAME=$(node -p "require('./package.json').name") PKG_VERSION=$(node -p "require('./package.json').version")