Skip to content

fix: keep an unreadable version from failing a logged run - #237

Merged
namin merged 2 commits into
midspiral:mainfrom
Sequela02:fix/run-log-version
Oct 30, 2026
Merged

namin merged 2 commits into
midspiral:mainfrom
Sequela02:fix/run-log-version

Conversation

@Sequela02

@Sequela02 Sequela02 commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Problem

DESIGN_RUN_LOG.md says "Logging never fails a run." When lsc can't read its own version, though, a logged check or regen fails before it starts. That happens wherever lsc runs bundled, without package.json two levels above the module: esbuild, bun build, or a compiled binary that embeds it.

Reproduction

npm ci && npm run build
bun build tools/dist/lsc.js --target=node --outfile=/tmp/lsc/lsc.mjs
mkdir /tmp/lsc/p && cd /tmp/lsc/p && git init -q
printf '%s\n' '//@ ensures \result >= x' 'export function f(x: number): number {' '  return x;' '}' > f.ts
node ../lsc.mjs regen --no-verify --backend=dafny f.ts
node ../lsc.mjs check --backend=dafny f.ts

Expected

Both commands behave as without the run log. LSC_RUN_LOG=false node ../lsc.mjs regen … writes f.dfy and exits 0.

Actual

On dd0847e, both exit 1 before generating anything:

ERROR: ENOENT: no such file or directory, open '<two folders above lsc.mjs>/package.json'

Root cause

lsc.ts passes lscVersion() to new RunLog(…), so the version is read eagerly, outside the safely wrapper that the run log uses for every other filesystem read. lscVersion reads package.json by a path relative to the module, which a bundle doesn't have.

Fix

lsc.ts passes safely(lscVersion) to RunLog, the wrapper the run log already uses for every other read, so a version that can't be read is recorded as "lsc": null and the run continues. safely is now exported from run-log.ts. isVerifyRecord doesn't check lsc, so lsc runs reads these records unchanged. DESIGN_RUN_LOG.md says the field may be null.

lsc version and info --typed still read the version the same way; this PR only stops the run log from failing a run.

Regression

a version that can't be read is recorded as null in tools/tests/run-log.test.ts.

Validation

  • npm run build: pass.
  • npm run typecheck, (cd tools && npm run typecheck) and npm run typecheck:examples: pass.
  • npx tsx --test tools/tests/*.test.ts on Windows, Node 24.15: 227 passed and 29 failed with the change, against 226 passed and 29 failed on dd0847e. The failing set is identical: the existing CLI-subprocess tests that hit absolute ESM loader paths on Windows. Not run on Linux.
  • The bundled reproduction above, with Dafny 4.11.0: before, regen and check exit 1. After, regen exits 0 and check reports 1 verified, 0 errors; both records are written with "lsc": null.
  • tools/test-fixtures.sh was not run: it starts with the unit suite, which stops on the Windows failures above.

Compatibility

No new option, syntax or dependency. The record schema stays at v: 1, and lsc stays a string whenever the version can be read.

@namin
namin requested a review from codefrenzy October 30, 2026 02:57
@namin

namin commented Oct 30, 2026

Copy link
Copy Markdown
Member

Why can't we just use safely eagerly instead of carrying the thunk around?

@namin

namin commented Oct 30, 2026

Copy link
Copy Markdown
Member

(Thanks for the report and the PR!)

@Sequela02

Copy link
Copy Markdown
Contributor Author

Good point, that's simpler. Updated to safely(lscVersion) in lsc.ts, and the existing tests are unchanged now.

@namin namin left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Straightforward change.

@namin
namin merged commit f245e98 into midspiral:main Oct 30, 2026
40 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants