Skip to content

v3.13.1

Choose a tag to compare

@cldmv-bot cldmv-bot released this 15 Aug 05:46
· 4 commits to master since this release
v3.13.1
c940669

release: v3.13.1 - detect dev conditions via execArgv and scoped installs… (#280)

Slothlet v3.13.1 Changelog

Release Date: August 2026
Release Type: Patch
Branch: release/3.13.1


Overview

Version 3.13.1 is a maintenance patch centered on devcheck.mjs, the import-time development-environment tripwire that calls process.exit(1) when it believes a source checkout is being run without the slothlet-dev resolver condition. Two ways the guard misjudged its environment are fixed (#270, merged via PR #281): it read the active resolver conditions only from process.env.NODE_OPTIONS and missed the command-line form Node records in process.execArgv — the same channel vitest uses to hand conditions to its workers — so a correctly configured developer could hit a false exit(1); and its installed-package guard inspected only the immediate grandparent directory name, which is the scope directory for slothlet's own scoped install, so a git or tarball install (which ships src/ but no dist/) could trip the guard inside a consumer. A spawn-based regression suite accompanies the fix.

The release also rolls up four routine devDependency bumps and regenerates the committed declaration tree so it matches the source shipped in v3.13.0. No source module changed in this release, and there are no breaking changes.


🐛 Bug Fixes

devcheck.mjs misjudged its environment two ways (#270)

devcheck.mjs runs at import time and only acts inside a narrow window — src/ present, dist/ absent, and not running under CI — where its job is to catch a slothlet source checkout being run without the dev resolver condition set. Two independent misjudgements inside that window are corrected.

Dev-condition detection now reads execArgv, not just NODE_OPTIONS. The guard decided whether the slothlet-dev condition was opted in by scanning process.env.NODE_OPTIONS alone. Node records a condition passed on the command line — node --conditions=slothlet-dev file.mjs — in process.execArgv, not in NODE_OPTIONS, and that CLI form is exactly how vitest forwards conditions to its worker processes. A developer using the CLI or worker form was therefore read as unconfigured, and the guard fired a spurious process.exit(1) that killed the run. Detection now folds process.execArgv into the same haystack as NODE_OPTIONS, so the env form and the CLI/worker form are both recognized.

The installed-package guard now detects a node_modules segment at any depth. The check that suppresses the tripwire for a copy installed under node_modules — where it must never act — tested basename(dirname(__dirname)) === "node_modules". For slothlet's own scoped install the file sits at node_modules/@cldmv/slothlet/devcheck.mjs, whose grandparent is the @cldmv scope directory rather than node_modules, so the guard never recognized the install and never tripped for the common scoped case (harmless there, since an npm install ships dist/ and the outer window stays closed). The real hazard is a git or tarball install: it ships src/ with no built dist/, so the outer window is open, and a scoped layout defeated the node_modules check — a consumer could take a spurious exit(1) at import time. Detection now tests for a node_modules path segment anywhere above the file, so scoped and unscoped installs are recognized regardless of nesting depth.

devcheck.mjs lives at the package root and is outside the coverage include (src/**), so this fix and its tests carry no coverage-gate impact.


🧪 Tests

devcheck guard regression suite (#270)

A new spawn-based suite (tests/vitests/suites/devcheck/devcheck.test.vitest.mjs, 6 tests) launches devcheck.mjs as a child process under controlled execArgv / NODE_OPTIONS / working-directory conditions and asserts on its exit code and emitted message: the baseline exit(1) when no dev condition is set at all; non-firing when --conditions=slothlet-dev arrives via execArgv (the CLI/worker form) and the preserved NODE_OPTIONS path; the generic-dev redirect message for --conditions=development; and non-firing for both a scoped (node_modules/@cldmv/slothlet) and an unscoped (node_modules/slothlet) install layout. Because devcheck.mjs sits outside the coverage include, the suite has no effect on the coverage gate.


📚 Documentation


🔧 Tooling

  • Declaration tree regenerated to match shipped source. No source module changed in this release; the committed .d.mts files under types/ are regenerated so they match the source v3.13.0 actually shipped, whose declarations had been generated from earlier source. The visible deltas — SlothletError's originalError parameter widened from Error to unknown and a private #describeThrown rendering helper, plus declaration updates for the hook / api / permission / version managers and slothlet.d.mts — are that regeneration, not new behavior in 3.13.1.

Dependency updates

  • esbuild 0.28.1 → 0.28.2 (#276)
  • globals 17.8.0 → 17.9.0 (#277)
  • @types/node 26.1.2 → 26.2.0 (#278)
  • eslint 10.8.0 → 10.8.1 (#279)

All four are devDependencies. The Dependabot bumps updated only the lockfile within the existing caret ranges, so the declared devDependencies floors are unchanged and npm ci installs the newly resolved (tested) versions.


Upgrade notes

  • No breaking changes. devcheck.mjs only ever acts in a slothlet source checkout — its guard stays inert once dist/ is present or the copy is installed under node_modules — so this fix removes false positives and requires no consumer action.
👥 Contributors