Skip to content

Prepares the 0.4.0 release - #164

Merged
johnnyt merged 1 commit into
mainfrom
pts-3px7-release-prep-0-4-0
Oct 1, 2026
Merged

johnnyt merged 1 commit into
mainfrom
pts-3px7-release-prep-0-4-0

Conversation

@johnnyt

@johnnyt johnnyt commented Oct 1, 2026

Copy link
Copy Markdown
Member

Prepares the @riddler/predicator 0.4.0 release, by hand from .claude/wurk/release.md (the kit has no npm recipe). A minor, as ruled by the operator, 2026-10-01. This PR does not merge, tag or publish: the conductor merges it, pulls main, creates the annotated tag v0.4.0 at the merge SHA and pushes it; the operator runs npm publish.

Commits

  • 78064dd Prepares the 0.4.0 release

The release commit touches exactly the files the release checklist's table names: package.json ("version" 0.3.0 -> 0.4.0 and nothing else), README.md (the install pin ^0.3.0 -> ^0.4.0 and nothing else), CHANGELOG.md (the new section, above 0.3.0's) and the promoted changelog.d/*.md fragments (deleted). changelog.d/ holds only its README.md afterwards.

Premise checks

  • origin/main was fe15d4b when this branch was cut; the reference prep is 1ddd46b (the first line of git log --oneline --no-patch -L '/"version"/,+1:package.json').
  • npm view @riddler/predicator dist-tags answered { latest: '0.3.0' } before the bump.
  • No tag v0.4.0 exists (git rev-parse -q --verify refs/tags/v0.4.0 exits 1, and git ls-remote --tags origin v0.4.0 lists nothing).
  • git log --oneline v0.3.0..origin/main, the release's content, 17 commits:
fe15d4b Scopes what parse and compile refuse
8e20280 Moves the new execute fixtures to the library
b6f0bde Runs a source string as a program at execute
5afceb8 Notes executeTagged as the subpath's second entry
06ecc9b Adds executeTagged to the tagged subpath
929bcb7 Records the decompile result export as an Amendment
6d68c49 Exports the decompile result type by name
02d4a21 Shares one fraction expander for durations
9fc37a2 Notes ADR-0004's minus sentence and block brace
ea1d274 Drops a stale base from the Amendment
676aa45 Adds the statement program compiler
f12d11f Refuses a duration component past the safe range
c9e0dd9 Declares the duration divergences
6149371 Adds durationToMilliseconds
6b0f592 Adds program rows to the compile transcript
0950ee3 Names the protected root in the refusal
bd1bb1f Accepts the six amendments that shipped in 0.3.0

Fragments promoted

In fragment-name order, seven: pts-0o0p, pts-0zns, pts-ix34, pts-mmls, pts-o0gr, pts-shdy, pts-xmz6. Under Added: pts-0o0p, pts-ix34, pts-mmls, pts-shdy, pts-xmz6 (two bullets). Under Changed: pts-0zns, pts-o0gr. No fragment carries Deprecated, Removed, Fixed or Security. A script compared every - bullet line of every fragment at fe15d4b against the new section with a whole-line fixed-string match: each was found byte for byte, and the section carries no bullet the fragments do not.

The closed-set question

Asked over every promoted fragment and over the public surface since v0.3.0: git diff v0.3.0..origin/main over src/index.ts, src/tagged.ts, the modules they re-export from (src/compile.ts, src/decompile.ts, src/duration-units.ts, src/errors.ts, src/ast.ts), and test/export-surface.json (the export-surface list the test pins).

Kind What Where Effect on the version
Added public name compileProgram, compileProgramWithPositions, compileProgramWithSpans main entry (src/index.ts, from src/compile.ts) addition
Added public name durationToMilliseconds main entry (src/index.ts, from src/duration-units.ts) addition
Added public name DecompileResult (the type decompile already answered, now exported by name; shape unchanged) main entry (src/index.ts, from src/decompile.ts) addition
Added public name executeTagged ./tagged (src/tagged.ts) addition
New members of a closed union a host matches on unexpected_else, unassignable_location, expected_open_brace ParseReason (src/errors.ts) a minor on 0.x; a host with an exhaustive match adds the three arms, as the promoted bullet says
New optional field details?: { readonly root: string } on EvaluationError, set only on the protected_root refusal; the constructor takes it as an optional fourth argument src/errors.ts additive; every other refusal leaves details absent
Changed answer execute and executeValue compile a source string as a statement program (ruled by the operator, 2026-10-01) src/index.ts a host-visible answer change, named in the Changed bullet; no name removed or renamed
Changed answer a duration component past the largest safe integer is refused by ::duration and parseDuration with the existing invalid_duration_format src/cast.ts, src/duration-units.ts a host-visible answer change, no new union member
Removed or renamed public name none the export-surface list at v0.3.0 against origin/main adds six names (DecompileResult, the three compileProgram names, durationToMilliseconds, executeTagged) and drops none on . or ./tagged (its one removed diff line is evaluateTagged gaining a trailing comma); the two export lines src/index.ts drops are replaced by wider statements that still name every former name would hold the prep for the version word; it does not arise

So every change is a minor on 0.x, consistent with 0.4.0. The statement node types added to src/ast.ts are not exported (the public Ast stays the opaque branded type), and the located program results and executeTagged's result are unexported aliases, so a host names them structurally or through ReturnType, as it named decompile's result before DecompileResult.

The publish guard on the pack path

npm pack --dry-run (no registry write; no tarball written) ran prepack, the publish guard: it removed the output directory, rebuilt, and passed all three of its properties, ending publish-guard: the output was built from this tree and is packable, then listed 49 files for @riddler/predicator@0.4.0. The full output, with the worktree path replaced by <worktree>:

npm pack --dry-run

> @riddler/predicator@0.4.0 prepack
> node scripts/publish-guard.mjs

publish-guard: removed the output directory

> @riddler/predicator@0.4.0 build
> tsup

CLI Building entry: src/index.ts, src/tagged.ts
CLI Using tsconfig: tsconfig.json
CLI tsup v8.5.1
CLI Using tsup config: <worktree>/tsup.config.ts
CLI Target: es2020
CLI Cleaning output folder
ESM Build start
CJS Build start
DTS Build start
ESM dist/index.js              12.65 KB
ESM dist/tagged.js             13.92 KB
ESM dist/chunk-2IORZCUH.js     163.21 KB
ESM dist/tagged.js.map         15.24 KB
ESM dist/index.js.map          13.19 KB
ESM dist/chunk-2IORZCUH.js.map 165.79 KB
ESM ⚡️ Build success in 253ms
CJS dist/index.cjs              15.68 KB
CJS dist/tagged.cjs             14.29 KB
CJS dist/chunk-S2FHDOP7.cjs     164.18 KB
CJS dist/tagged.cjs.map         15.56 KB
CJS dist/chunk-S2FHDOP7.cjs.map 165.80 KB
CJS dist/index.cjs.map          13.44 KB
CJS ⚡️ Build success in 254ms
DTS ⚡️ Build success in 577ms
DTS dist/index.d.ts               29.80 KB
DTS dist/tagged.d.ts              9.76 KB
DTS dist/evaluator-IvChVQeL.d.ts  29.01 KB
DTS dist/index.d.cts              29.80 KB
DTS dist/tagged.d.cts             9.76 KB
DTS dist/evaluator-IvChVQeL.d.cts 29.01 KB
publish-guard: ok   the build ran from a removed output directory
publish-guard: ok   dist/chunk-2IORZCUH.js.map carries no embedded source
publish-guard: ok   dist/chunk-S2FHDOP7.cjs.map carries no embedded source
publish-guard: ok   dist/index.cjs.map carries no embedded source
publish-guard: ok   dist/index.js.map carries no embedded source
publish-guard: ok   dist/tagged.cjs.map carries no embedded source
publish-guard: ok   dist/tagged.js.map carries no embedded source
publish-guard: ok   src/cast.ts is shipped, so the maps that name it resolve
publish-guard: ok   src/civil.ts is shipped, so the maps that name it resolve
publish-guard: ok   src/compile.ts is shipped, so the maps that name it resolve
publish-guard: ok   src/context.ts is shipped, so the maps that name it resolve
publish-guard: ok   src/decompile.ts is shipped, so the maps that name it resolve
publish-guard: ok   src/duration-units.ts is shipped, so the maps that name it resolve
publish-guard: ok   src/emitter.ts is shipped, so the maps that name it resolve
publish-guard: ok   src/errors.ts is shipped, so the maps that name it resolve
publish-guard: ok   src/evaluator.ts is shipped, so the maps that name it resolve
publish-guard: ok   src/floats.ts is shipped, so the maps that name it resolve
publish-guard: ok   src/functions/date.ts is shipped, so the maps that name it resolve
publish-guard: ok   src/functions/index.ts is shipped, so the maps that name it resolve
publish-guard: ok   src/functions/json.ts is shipped, so the maps that name it resolve
publish-guard: ok   src/functions/list.ts is shipped, so the maps that name it resolve
publish-guard: ok   src/functions/math.ts is shipped, so the maps that name it resolve
publish-guard: ok   src/functions/string.ts is shipped, so the maps that name it resolve
publish-guard: ok   src/functions/support.ts is shipped, so the maps that name it resolve
publish-guard: ok   src/index.ts is shipped, so the maps that name it resolve
publish-guard: ok   src/instructions.ts is shipped, so the maps that name it resolve
publish-guard: ok   src/iso.ts is shipped, so the maps that name it resolve
publish-guard: ok   src/lexer.ts is shipped, so the maps that name it resolve
publish-guard: ok   src/maps.ts is shipped, so the maps that name it resolve
publish-guard: ok   src/nesting.ts is shipped, so the maps that name it resolve
publish-guard: ok   src/parser.ts is shipped, so the maps that name it resolve
publish-guard: ok   src/tagged.ts is shipped, so the maps that name it resolve
publish-guard: ok   src/values.ts is shipped, so the maps that name it resolve
publish-guard: ok   ./dist/index.cjs exists in the output
publish-guard: ok   ./dist/index.cjs is shipped
publish-guard: ok   ./dist/index.d.cts exists in the output
publish-guard: ok   ./dist/index.d.cts is shipped
publish-guard: ok   ./dist/index.d.ts exists in the output
publish-guard: ok   ./dist/index.d.ts is shipped
publish-guard: ok   ./dist/index.js exists in the output
publish-guard: ok   ./dist/index.js is shipped
publish-guard: ok   ./dist/tagged.cjs exists in the output
publish-guard: ok   ./dist/tagged.cjs is shipped
publish-guard: ok   ./dist/tagged.d.cts exists in the output
publish-guard: ok   ./dist/tagged.d.cts is shipped
publish-guard: ok   ./dist/tagged.d.ts exists in the output
publish-guard: ok   ./dist/tagged.d.ts is shipped
publish-guard: ok   ./dist/tagged.js exists in the output
publish-guard: ok   ./dist/tagged.js is shipped
publish-guard: the output was built from this tree and is packable
npm notice
npm notice 📦  @riddler/predicator@0.4.0
npm notice Tarball Contents
npm notice 25.1kB CHANGELOG.md
npm notice 1.1kB LICENSE
npm notice 45.3kB README.md
npm notice 167.1kB dist/chunk-2IORZCUH.js
npm notice 169.8kB dist/chunk-2IORZCUH.js.map
npm notice 168.1kB dist/chunk-S2FHDOP7.cjs
npm notice 169.8kB dist/chunk-S2FHDOP7.cjs.map
npm notice 29.7kB dist/evaluator-IvChVQeL.d.cts
npm notice 29.7kB dist/evaluator-IvChVQeL.d.ts
npm notice 16.1kB dist/index.cjs
npm notice 13.8kB dist/index.cjs.map
npm notice 30.5kB dist/index.d.cts
npm notice 30.5kB dist/index.d.ts
npm notice 13.0kB dist/index.js
npm notice 13.5kB dist/index.js.map
npm notice 14.6kB dist/tagged.cjs
npm notice 15.9kB dist/tagged.cjs.map
npm notice 10.0kB dist/tagged.d.cts
npm notice 10.0kB dist/tagged.d.ts
npm notice 14.3kB dist/tagged.js
npm notice 15.6kB dist/tagged.js.map
npm notice 2.2kB package.json
npm notice 12.7kB src/ast.ts
npm notice 12.2kB src/cast.ts
npm notice 2.8kB src/civil.ts
npm notice 11.4kB src/compile.ts
npm notice 10.9kB src/context.ts
npm notice 23.3kB src/decompile.ts
npm notice 8.7kB src/duration-units.ts
npm notice 27.8kB src/emitter.ts
npm notice 9.8kB src/errors.ts
npm notice 90.5kB src/evaluator.ts
npm notice 7.3kB src/floats.ts
npm notice 3.6kB src/functions/date.ts
npm notice 2.0kB src/functions/index.ts
npm notice 16.6kB src/functions/json.ts
npm notice 1.2kB src/functions/list.ts
npm notice 6.5kB src/functions/math.ts
npm notice 7.0kB src/functions/string.ts
npm notice 4.9kB src/functions/support.ts
npm notice 17.4kB src/index.ts
npm notice 16.9kB src/instructions.ts
npm notice 12.0kB src/iso.ts
npm notice 29.4kB src/lexer.ts
npm notice 3.1kB src/maps.ts
npm notice 11.3kB src/nesting.ts
npm notice 49.1kB src/parser.ts
npm notice 30.5kB src/tagged.ts
npm notice 20.9kB src/values.ts
npm notice Tarball Details
npm notice name: @riddler/predicator
npm notice version: 0.4.0
npm notice filename: riddler-predicator-0.4.0.tgz
npm notice package size: 333.3 kB
npm notice unpacked size: 1.5 MB
npm notice shasum: 2526804c50d00cc3e71db07cc144664d1e560023
npm notice integrity: sha512-wIgNsLGr8bt1f[...]gFzsEijCwNaWQ==
npm notice total files: 49
npm notice
riddler-predicator-0.4.0.tgz

The promoted section

## [0.4.0] 2026-10-01

A minor release. The statement grammar compiles from source: `compileProgram`,
`compileProgramWithPositions` and `compileProgramWithSpans` are new, and
`ParseReason` gains the three refusals only they answer. `execute` and
`executeValue` compile a source string as a statement program, as the
reference's do, so a source the expression grammar refused may now run, a
source either grammar refuses may answer the program grammar's refusal, and
`executeValue` given an expression's source now answers that expression's
value. `executeTagged`, `durationToMilliseconds` and the `DecompileResult` type
are new; the protected-root refusal names its root under `details.root`; and a
duration text whose component is past the largest safe integer is refused.

### Added

- A `store` refused for writing into a protected root answers an `EvaluationError` that names that root under `details.root`, so a host reads the root without parsing the message; the reason and the message are unchanged, and every other refusal leaves `details` absent.
- `durationToMilliseconds` answers a duration's length in milliseconds by the reference's weights: a week of seven days, a month of thirty and a year of three hundred and sixty five.
- `executeTagged` on the `./tagged` subpath runs a statement program, from a compiled list or from source text, and answers the context it halted with as the tagged encoding's text on both arms, so `decodeTagged` reads every value back as the one the program bound: a float the program stored stays a float, where `execute`'s plain projection answers the integer.
- `DecompileResult` names the result `decompile` answers - the rendered `source` on the succeeding arm, or the `ParseError` that refused the tree on the failing one - so a host can annotate it by name, as it does `ParseResult` and `CompileResult`, instead of deriving it from the function; the shape is unchanged.
- `compileProgram`, `compileProgramWithPositions` and `compileProgramWithSpans` compile a statement program from source text - assignments, `;`-separated statements, `if`/`else`, `else if` and `while` - to the instruction list `execute` and `executeValue` run, answering the results `compile`, `compileWithPositions` and `compileWithSpans` answer, with one more table on the two located variants: `segmentPositions` or `segmentSpans`, one entry per segment of the location each `store` writes.
- `ParseReason` gains `unexpected_else`, `unassignable_location` and `expected_open_brace`, which only the three program entry points answer; a caller that switches exhaustively on the union adds the three cases.

### Changed

- `execute` and `executeValue` compile a source string as a statement program, as the reference's do, where they compiled it as an expression; `evaluate` still compiles an expression. Two effects follow: a source the expression grammar refused may now run (`execute("x = 1")` binds `x`), and a source either grammar refuses may answer the program grammar's refusal, with a different message or reason (`score 3` is refused as unexpected "after statement" rather than "after expression"). One more follows from the first: `executeValue` given an expression's source now answers that expression's value, where it answered undefined. A caller that wants a source refused unless it is an expression compiles it with `compile` and passes the instruction list.
- A duration text whose component is past the largest safe integer is refused: `::duration` answers undefined and `parseDuration` answers `invalid_duration_format`, where both used to answer a duration whose component was infinite or rounded. The reference, whose integers have no bound, answers such a text with a duration.

Gate

The full gate (mise exec -- pnpm run gate) ran green on the release commit's exact tree (the files staged at the commit are the files the gate ran on, under the same held locks, tree 12ab37e), so the commit was made without a second run. The whole output follows, with the worktree path replaced by <worktree> and temporary-directory prefixes by <tmp>, and terminal color codes removed; nothing else is cut:

pnpm run gate
$ node --version && pnpm run typecheck && pnpm run lint && pnpm run neutrality && vitest run --coverage && pnpm run corpus:check && pnpm run build && pnpm run identity && pnpm run resolution
v24.21.0
$ tsc --noEmit -p tsconfig.src.json && tsc --noEmit
$ biome check .
Checked 105 files in 91ms. No fixes applied.
$ node scripts/engine-neutrality.mjs
engine-neutrality: 27 files clean under src/, 17 rules

 RUN  v5.0.1 <worktree>
      Coverage enabled with v8

sabotage: <tmp>/sabotage-fixture-nGU1BL/card.mjs is mutated for this run
  the original is kept at <tmp>/sabotage-restore-cSEW7X/card.mjs
  restore it with: cp -f '<tmp>/sabotage-restore-cSEW7X/card.mjs' '<tmp>/sabotage-fixture-nGU1BL/card.mjs'
sabotage: <tmp>/sabotage-fixture-nGU1BL/card.mjs is mutated for this run
  the original is kept at <tmp>/sabotage-restore-TrgwD0/card.mjs
  restore it with: cp -f '<tmp>/sabotage-restore-TrgwD0/card.mjs' '<tmp>/sabotage-fixture-nGU1BL/card.mjs'
sabotage: <tmp>/sabotage-fixture-nGU1BL/card.mjs is mutated for this run
  the original is kept at <tmp>/sabotage-restore-2LWf31/card.mjs
  restore it with: cp -f '<tmp>/sabotage-restore-2LWf31/card.mjs' '<tmp>/sabotage-fixture-nGU1BL/card.mjs'
sabotage: <tmp>/sabotage-fixture-nGU1BL/card.mjs is mutated for this run
  the original is kept at <tmp>/sabotage-restore-fxlpsC/card.mjs
  restore it with: cp -f '<tmp>/sabotage-restore-fxlpsC/card.mjs' '<tmp>/sabotage-fixture-nGU1BL/card.mjs'
sabotage: <tmp>/sabotage-fixture-nGU1BL/card.mjs is mutated for this run
  the original is kept at <tmp>/sabotage-restore-JBGEmM/card.mjs
  restore it with: cp -f '<tmp>/sabotage-restore-JBGEmM/card.mjs' '<tmp>/sabotage-fixture-nGU1BL/card.mjs'
sabotage: <tmp>/sabotage-fixture-nGU1BL/card.mjs is mutated for this run
  the original is kept at <tmp>/sabotage-restore-vfuwAS/card.mjs
  restore it with: cp -f '<tmp>/sabotage-restore-vfuwAS/card.mjs' '<tmp>/sabotage-fixture-nGU1BL/card.mjs'
sabotage: <tmp>/sabotage-fixture-nGU1BL/card.mjs is mutated for this run
  the original is kept at <tmp>/sabotage-restore-m1KdzH/card.mjs
  restore it with: cp -f '<tmp>/sabotage-restore-m1KdzH/card.mjs' '<tmp>/sabotage-fixture-nGU1BL/card.mjs'

 Test Files  35 passed (35)
      Tests  2837 passed (2837)
   Start at  08:33:45
   Duration  10.18s (tests 87%, import 8%, transform 4%, worker 1%)

 % Coverage report from v8
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   99.21 |    97.25 |     100 |   99.72 |                   
 src               |    99.2 |    97.18 |     100 |   99.69 |                   
  cast.ts          |   99.06 |    97.89 |     100 |     100 | 259-260           
  compile.ts       |   97.36 |       95 |     100 |     100 | 179               
  context.ts       |     100 |    97.72 |     100 |     100 | 44                
  decompile.ts     |   99.23 |     99.2 |     100 |   99.18 | 201               
  emitter.ts       |   98.37 |    95.65 |     100 |   98.83 | 182,377           
  errors.ts        |     100 |       75 |     100 |     100 | 84-108            
  evaluator.ts     |   98.27 |    94.68 |     100 |   99.43 | 440,463,1342      
  instructions.ts  |     100 |    96.42 |     100 |     100 | 554               
  iso.ts           |    98.3 |    97.22 |     100 |     100 | 203               
  parser.ts        |   99.79 |    98.14 |     100 |     100 | ...,814,1355,1503 
  tagged.ts        |   99.32 |    98.96 |     100 |   99.58 | 445               
 src/functions     |   99.26 |    97.79 |     100 |     100 |                   
  json.ts          |   98.83 |       97 |     100 |     100 | ...54,213,344,361 
  math.ts          |     100 |    97.56 |     100 |     100 | 73                
-------------------|---------|----------|---------|---------|-------------------

=============================== Coverage summary ===============================
Statements   : 99.21% ( 3042/3066 )
Branches     : 97.25% ( 2163/2224 )
Functions    : 100% ( 441/441 )
Lines        : 99.72% ( 2578/2585 )
================================================================================
$ node scripts/corpus-check.mjs
corpus:check: riddler/predicator-ex at v9.4.2, ISA version 6, sha256:bb60ec82faba2e82ef1e7abaac8d26257db2a77cd4ce0c083b683c5bc063fd43
$ tsup
CLI Building entry: src/index.ts, src/tagged.ts
CLI Using tsconfig: tsconfig.json
CLI tsup v8.5.1
CLI Using tsup config: <worktree>/tsup.config.ts
CLI Target: es2020
CLI Cleaning output folder
ESM Build start
CJS Build start
DTS Build start
ESM dist/chunk-2IORZCUH.js     163.21 KB
ESM dist/tagged.js             13.92 KB
ESM dist/index.js              12.65 KB
ESM dist/tagged.js.map         15.24 KB
ESM dist/chunk-2IORZCUH.js.map 165.79 KB
ESM dist/index.js.map          13.19 KB
ESM ⚡️ Build success in 249ms
CJS dist/tagged.cjs             14.29 KB
CJS dist/chunk-S2FHDOP7.cjs     164.18 KB
CJS dist/index.cjs              15.68 KB
CJS dist/tagged.cjs.map         15.56 KB
CJS dist/chunk-S2FHDOP7.cjs.map 165.80 KB
CJS dist/index.cjs.map          13.44 KB
CJS ⚡️ Build success in 249ms
DTS ⚡️ Build success in 584ms
DTS dist/index.d.ts               29.80 KB
DTS dist/tagged.d.ts              9.76 KB
DTS dist/evaluator-IvChVQeL.d.ts  29.01 KB
DTS dist/index.d.cts              29.80 KB
DTS dist/tagged.d.cts             9.76 KB
DTS dist/evaluator-IvChVQeL.d.cts 29.01 KB
$ node scripts/cross-entry-identity.mjs
identity: ok   esm: a float decoded by ./tagged is the main entry's Float
identity: ok   esm: the absence decoded by ./tagged is the main entry's Undefined
identity: ok   esm: a date decoded by ./tagged is the main entry's PDate
identity: ok   esm: a datetime decoded by ./tagged is the main entry's PDateTime
identity: ok   esm: a duration decoded by ./tagged is the main entry's Duration
identity: ok   esm: a float built by the main entry encodes through ./tagged as a float
identity: ok   esm: the main entry's Undefined encodes through ./tagged as the absence
identity: ok   cjs: a float decoded by ./tagged is the main entry's Float
identity: ok   cjs: the absence decoded by ./tagged is the main entry's Undefined
identity: ok   cjs: a date decoded by ./tagged is the main entry's PDate
identity: ok   cjs: a datetime decoded by ./tagged is the main entry's PDateTime
identity: ok   cjs: a duration decoded by ./tagged is the main entry's Duration
identity: ok   cjs: a float built by the main entry encodes through ./tagged as a float
identity: ok   cjs: the main entry's Undefined encodes through ./tagged as the absence
identity: ok   esm -> cjs: the absence is one singleton
identity: ok   esm -> cjs: a float is the other's Float
identity: ok   esm -> cjs: a date is the other's PDate
identity: ok   esm -> cjs: a datetime is the other's PDateTime
identity: ok   esm -> cjs: a duration is the other's Duration
identity: ok   esm -> cjs: a float is named a float
identity: ok   esm -> cjs: a float projects to its number
identity: ok   esm -> cjs: the absence projects to undefined
identity: ok   esm -> cjs: every member normalizes as itself
identity: ok   esm -> cjs: every member encodes through the other's ./tagged
identity: ok   esm -> cjs: a float in a context evaluates
identity: ok   cjs -> esm: the absence is one singleton
identity: ok   cjs -> esm: a float is the other's Float
identity: ok   cjs -> esm: a date is the other's PDate
identity: ok   cjs -> esm: a datetime is the other's PDateTime
identity: ok   cjs -> esm: a duration is the other's Duration
identity: ok   cjs -> esm: a float is named a float
identity: ok   cjs -> esm: a float projects to its number
identity: ok   cjs -> esm: the absence projects to undefined
identity: ok   cjs -> esm: every member normalizes as itself
identity: ok   cjs -> esm: every member encodes through the other's ./tagged
identity: ok   cjs -> esm: a float in a context evaluates
identity: both entry points share one value domain in both module formats, and the formats recognize each other's values
$ node scripts/legacy-resolution.mjs
resolution: ok   'main' names the same file the exports map names under 'require' (./dist/index.cjs)
resolution: ok   'types' names the same file the exports map names under 'require' (./dist/index.d.cts)
resolution: ok   a node10 consumer compiles against the package
resolution: ok   the node10 run resolved in node10 mode
resolution: ok   the node10 run read the 'types' field './dist/index.d.cts'
resolution: ok   the node10 run resolved the package through that field
resolution: ok   the node10 run did not read the exports map
resolution: ok   an ESM nodenext consumer compiles against the package
resolution: ok   an ESM nodenext consumer resolved through the exports map's 'import' condition
resolution: ok   an ESM nodenext consumer resolved the package to './dist/index.d.ts'
resolution: ok   a CommonJS nodenext consumer compiles against the package
resolution: ok   a CommonJS nodenext consumer resolved through the exports map's 'require' condition
resolution: ok   a CommonJS nodenext consumer resolved the package to './dist/index.d.cts'
resolution: ok   the file 'main' names exports the API
resolution: ok   a value built by the file 'main' names is named by it
resolution: a node10 consumer resolves the package through 'types', a nodenext consumer still resolves through 'exports', and the file 'main' names loads under require

Provenance

  • The lead paragraph of the 0.4.0 section is the only prose written at release time; it names the program-mode switch's effects only as the pts-0zns fragment states them, and every bullet is carried from its fragment.
  • Review tier: contract (a release prep); the conductor dispatches the review.

A minor, as ruled by the operator, 2026-10-01: the statement grammar
compiles from source through compileProgram, compileProgramWithPositions
and compileProgramWithSpans, and ParseReason gains the three refusals
only they answer; execute and executeValue compile a source string as a
statement program, as the reference's do; executeTagged,
durationToMilliseconds and the DecompileResult type are added; the
protected-root refusal names its root under details.root; and a duration
component past the largest safe integer is refused. No public name is
removed or renamed.

The version moves in package.json, its only carrier. Every changelog
fragment is promoted byte for byte under a 0.4.0 section dated from the
local clock and placed above 0.3.0's, grouped Added, Changed with
fragments in name order, and the fragments are deleted here;
changelog.d keeps only its README. The README's install pin moves to
the new version. Those are every file a release commit here may touch.

Run: the full pnpm gate green on this exact tree, and npm pack
--dry-run built through the publish guard, which passed all three of
its properties and listed 49 files for @riddler/predicator@0.4.0.

The tag and the publish are not done here.

Refs: pts-3px7
@johnnyt
johnnyt merged commit fe42eea into main Oct 1, 2026
1 check passed
@johnnyt
johnnyt deleted the pts-3px7-release-prep-0-4-0 branch October 1, 2026 14:41
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.

1 participant