devcheck.mjs correctly namespaces its dev condition to uuid-dev (good — that's the right pattern for a normal module), but the check logic around it has several bugs. These are latent here because uuid's own test suite imports ../src/… directly and never imports the package entry, so devcheck is never actually exercised by CI — but the bugs bite a real developer.
The corrected reference implementation is @cldmv/holdmytask PR #12 (fix/devcheck-normal-module), which fixed the identical issues; this issue is to backport that.
Bugs
1. Trigger keys off NODE_ENV, which doesn't affect resolution
Current:
if (!nodeEnv || (!["", "development"].includes(nodeEnv) && !hasUUIDDev)) { … }
Only --conditions=uuid-dev selects src/ (via the ./main export); NODE_ENV has no effect on which tree resolves. So this logic is wrong in both directions:
- False negative:
NODE_ENV=development with no condition → stays silent, but the package is actually resolving to dist/. This is exactly the misconfiguration devcheck exists to catch, and it's silently allowed.
- False positive: condition set but
NODE_ENV unset → !nodeEnv fires and it nags, even though you're correctly on src/.
Correct trigger is condition-only: if (!hasUUIDDev) { … }.
2. Only checks NODE_OPTIONS, misses execArgv
const hasUUIDDev = process.env.NODE_OPTIONS?.includes("--conditions=uuid-dev");
node --conditions=uuid-dev file.mjs puts the flag in process.execArgv, not NODE_OPTIONS — and that's also how vitest passes conditions to its workers (a worker's NODE_OPTIONS is undefined while execArgv carries --conditions uuid-dev). So the CLI form and the vitest-worker form aren't detected. Check both:
const flags = (process.env.NODE_OPTIONS || "") + " " + process.execArgv.join(" ");
const hasUUIDDev = flags.includes("uuid-dev");
3. No installed-package guard (and the fleet's usual one is broken for scoped packages)
devcheck has no node_modules guard. npm publishes ship neither src/ nor devcheck.mjs, so it's moot for a registry install — but a git/tarball install includes them, and devcheck would then process.exit(1) inside the consumer's app. Add a guard, and make it scoped-aware (the common path.basename(path.dirname(__dirname)) === "node_modules" form misses node_modules/@cldmv/uuid, where the parent is the @cldmv scope dir):
const isInstalledPackage = __dirname.split(path.sep).includes("node_modules");
4. No tests
devcheck has no test coverage, which is how the above drifted. holdmytask PR #12 adds tests/DevCheck.test.vitest.mjs (9 cases: nags without condition; silent with condition via NODE_OPTIONS and via execArgv; NODE_ENV=development alone does not silence; still nags after a dist/ build; generic development condition rejected; skips in CI; skips when installed as a scoped dep; does nothing with no src/). Port it.
5. Minor: stale header
@Project: @cldmv/slothlet in the file header — copy-paste leftover, should be @cldmv/uuid.
Suggested fix
Port holdmytask PR #12's devcheck.mjs + tests/DevCheck.test.vitest.mjs, swapping holdmytask-dev → uuid-dev. No change needed to the uuid-dev condition itself or the ./main export.
devcheck.mjscorrectly namespaces its dev condition touuid-dev(good — that's the right pattern for a normal module), but the check logic around it has several bugs. These are latent here because uuid's own test suite imports../src/…directly and never imports the package entry, so devcheck is never actually exercised by CI — but the bugs bite a real developer.The corrected reference implementation is
@cldmv/holdmytaskPR #12 (fix/devcheck-normal-module), which fixed the identical issues; this issue is to backport that.Bugs
1. Trigger keys off
NODE_ENV, which doesn't affect resolutionCurrent:
Only
--conditions=uuid-devselectssrc/(via the./mainexport);NODE_ENVhas no effect on which tree resolves. So this logic is wrong in both directions:NODE_ENV=developmentwith no condition → stays silent, but the package is actually resolving todist/. This is exactly the misconfiguration devcheck exists to catch, and it's silently allowed.NODE_ENVunset →!nodeEnvfires and it nags, even though you're correctly onsrc/.Correct trigger is condition-only:
if (!hasUUIDDev) { … }.2. Only checks
NODE_OPTIONS, missesexecArgvnode --conditions=uuid-dev file.mjsputs the flag inprocess.execArgv, notNODE_OPTIONS— and that's also how vitest passes conditions to its workers (a worker'sNODE_OPTIONSisundefinedwhileexecArgvcarries--conditions uuid-dev). So the CLI form and the vitest-worker form aren't detected. Check both:3. No installed-package guard (and the fleet's usual one is broken for scoped packages)
devcheck has no
node_modulesguard. npm publishes ship neithersrc/nordevcheck.mjs, so it's moot for a registry install — but a git/tarball install includes them, and devcheck would thenprocess.exit(1)inside the consumer's app. Add a guard, and make it scoped-aware (the commonpath.basename(path.dirname(__dirname)) === "node_modules"form missesnode_modules/@cldmv/uuid, where the parent is the@cldmvscope dir):4. No tests
devcheck has no test coverage, which is how the above drifted. holdmytask PR #12 adds
tests/DevCheck.test.vitest.mjs(9 cases: nags without condition; silent with condition viaNODE_OPTIONSand viaexecArgv;NODE_ENV=developmentalone does not silence; still nags after adist/build; genericdevelopmentcondition rejected; skips in CI; skips when installed as a scoped dep; does nothing with nosrc/). Port it.5. Minor: stale header
@Project: @cldmv/slothletin the file header — copy-paste leftover, should be@cldmv/uuid.Suggested fix
Port holdmytask PR #12's
devcheck.mjs+tests/DevCheck.test.vitest.mjs, swappingholdmytask-dev→uuid-dev. No change needed to theuuid-devcondition itself or the./mainexport.