fix(effect-bun-test): restore the v3 log-level labels and cover command/prop - #2
Merged
Merged
Conversation
…nd/prop
The v4 migration is otherwise complete and green, but it dropped one public
export and left the two largest v4 rewrites untested.
`logLevelLabel` is gone from `log-capture`, and `CapturedLog.level` now carries
the raw v4 level. v4 models a log level as a bare string union member ('Warn',
'None') where v3 exposed an object whose `label` was upper case ('WARN', 'OFF').
Every level differs in case and the off sentinel differs in spelling, so a
caller that kept `level === 'WARN'` does not fail — it matches nothing and
quietly asserts nothing. A `filter(l => l.level === 'ERROR')` guarding a
`toHaveLength(0)` becomes vacuously true.
`logLevelLabel` is restored as an export and applied inside `makeLogCapture`, so
the package agrees with itself: the helper a caller uses to label its own
`Logger.make` sink produces the same strings the built-in capture records.
`src/command.ts` and the `prop` family had no tests at all, and both were
rewritten wholesale for v4 — `command.ts` onto `effect/unstable/process` and
`prop` onto `Schema.toArbitrary`. Neither rewrite is observable to `tsc`: a
schema-to-arbitrary bridge that produced nothing, or a property body that never
ran, would still typecheck and still report as passing. Both are now covered,
including a case that counts property-body invocations so a silently inert
`prop` fails instead of passing.
Verified against the real v4 runtime rather than inferred: `prop` derives values
for the array, record and Effect forms; the scripted-subprocess doubles serve
exit codes, stdout, stderr and the new `all` stream; an unmatched spawn is a
typed `PlatformError` and is replayed when the layer scope closes; and the
`it.effect` environment installs no logger.
bun run dod tsc, effect diagnostics, 292 tests, biome — all green
test:e2e 16 pass, against freshly packed tarballs
jfspencer
added a commit
that referenced
this pull request
Aug 18, 2026
Ships PR #2 (`fix(effect-bun-test): restore the v3 log-level labels and cover command/prop`), which merged to main after v0.4.0 was tagged and so missed that release. That change keeps `CapturedLog.level` on v3's upper-case labels and exports `logLevelLabel` so a caller building its own capture logger can label a raw v4 level the same way. v4 models a log level as a bare string union member ('Warn', 'Info', 'None') where v3 used an object whose `label` was upper case ('WARN', 'INFO', 'OFF'), so a caller that kept a `level === 'WARN'` comparison would not have failed — it would have matched nothing and quietly asserted nothing. No contract change: `logLevelLabel` is a new export on the existing `./log-capture` subpath, and it reaches the packed dist and its declaration. Dependency shape is untouched — `effect` stays a peer at `>=4.0.0-rc.109 <5`.
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.
mainalready carries the Effect v4 flip (catalogeffect@4.0.0-rc.109) and it is green. This closes the gaps found while validating that flip against its downstream consumer, so the tree is ready to tag as the first v4 release.1.
logLevelLabelwas dropped, and it is load-bearingv4 models a log level as a bare string union member —
'Warn','None'— where v3 exposed an object whoselabelwas upper case:'WARN','OFF'. Every level differs in case, and the off sentinel differs in spelling.That makes it a silent break rather than a loud one. A caller that kept the v3 comparison does not fail:
logLevelLabelis restored as an export from./log-captureand applied insidemakeLogCapture, so the package agrees with itself: the helper a caller uses to label its ownLogger.makesink produces the same strings the built-in capture records.Consumer impact — this is the reason it matters. In the monorepo that consumes these tarballs,
logLevelLabelis imported by 23 files acrossapps/xavier,apps/sofa,apps/cerebroandtools/ultravisor. Without this export they do not resolve.makeLogCaptureitself has exactly one importer, and it discardsentries, so restoring the upper-case labels breaks nothing and un-breaks the 23.2.
src/command.tsandprophad no tests, and both were rewritten wholesalecommand.tsmoved ontoeffect/unstable/process(CommandExecutor.Process→ChildProcessSpawner.ChildProcessHandle) andpropmoved ontoSchema.toArbitrary. Neither rewrite is observable totsc: a schema-to-arbitrary bridge that produced nothing, or a property body that never ran, would still typecheck and still report as passing.Both are now covered (
__tests__/command.test.ts,__tests__/prop.test.ts), including a case that counts property-body invocations so a silently inertpropfails instead of passing.Everything below was checked against the running v4 runtime rather than inferred:
propderives values for the array, record,it.effect.propandit.live.propforms, for scalar and composite schemas, and for raw FastCheck arbitraries.allstream, andallconcatenates as a stream rather than string-joining.PlatformError(soEffect.catchsees it), and the violation is also replayed when the layer scope closes — so a test that swallowed the error still fails.it.effectenvironment installs no logger, so a passing test stays quiet.No behaviour was changed in
command.tsor thepropmachinery; both were already correct.Deliberately not changed
testConfigLayerresolves nested paths with_(viaConfigProvider.fromEnvRecord) rather than v3's., and rejects empty-string values. That divergence is documented and pinned by a test, and it has zero consumers — the only import from./envanywhere downstream isscopedEnv. Left alone.Verification
Per-package: root 91, effect-bun-test 103 (was 72), bun-svelte-test 45, fixture-residue 33, effect-test-kit 12, uuid-effect 8. Zero failures.
Note for whoever cuts the release
@packages/uuid-effectis not a test-only package — it has ~110 importers downstream and 62 of them aresrc/, i.e. production code. Its v4 change is one line insrc/tag.ts(Context.Tag→Context.Service) and the service key string is unchanged, so the DI identity is preserved, but the release should be treated as a production dependency rather than a test-harness bump.The published
v0.2.1tarballs cannot load under v4 at all: they ship TypeScript source against a^3.22.1peer, and 8 of the 11 Effect modules they import no longer resolve. So this release is the unblock, not an optimisation.No version bump is included here — that belongs to the release commit.