Migrate fjs/bnf/data to .f.mjs - #1487
Conversation
proof.f.ts stays TypeScript for now: it has a runtime dependency on testlib.f.ts and media/json/module.f.ts, both still unmigrated. Updates descent/ll1 dependents and the stale line references across bnf/data's todo docs.
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
functionalscript | 28199f7 | Commit Preview URL Branch Preview URL |
Aug 11 2026, 06:21 AM |
proof.f.ts stays TypeScript for now: it has a runtime dependency on testlib.f.ts, still unmigrated. Updates the stale module.f.ts reference in the ll1 stack-recursion todo doc.
proof.f.ts stays TypeScript for now: it has a runtime dependency on testlib.f.ts, still unmigrated. Updates the djs/tokenizer dependent and stale module.f.ts references in bnf/ll1 and bnf's todo docs.
…types.ts The core effect system module: Operation, Effect, Pure, Cont, Do, History, OperationMap, MatchResult, ToAsyncOperationMap, Param, Return, F, Func move to types.ts unchanged (real TypeScript, variance annotations intact); the runtime combinators (pure, step, mapStep, historyStep, history, do_, foldStep, forEachStep, okStep, runPure, match) become JSDoc-typed .mjs, using @template/@PARAM on multi-step curried functions where an inline @type can't expose its generics to the function body. Updates all 30+ dependents across the repo (cas, ci, cli, dev, djs, emergent_testing, mcp, media/type, protocol/mcp, text/sgr, website, and effects' own submodules) to import runtime values from .f.mjs and types from types.ts separately. proof.f.ts stays TypeScript for now.
No proof.f.ts existed for this module (AGENTS.md's coverage gap is pre-existing, not introduced here). Updates 8 dependents across cas, mcp, media/type, and effects/node to import runtime values from .f.mjs and types from types.ts separately.
o2alexanderfedin
left a comment
There was a problem hiding this comment.
Approving. Reviewed at 28199f7 against main (03126e4). Five modules — bnf/data, bnf/ll1, bnf/descent, effects, effects/list — plus ~45 dependents updated.
Two modules genuinely restructure, and both check out
bnf/data, bnf/descent, and effects/list are equivalent to main's compiled output. The other two each carry one real code change, both the same idiom: JSDoc has no call-site type-argument syntax, so an inline argument gets extracted into a named const that can be annotated.
// ll1: rangeMap<DispatchResult>({…}) ->
/** @type {Properties<_DispatchResult>} */
const dispatchProps = { … }
const dispatchOp = rangeMap(dispatchProps)
// effects: fold<T, Effect<O|Q, S>>(item => acc => step(acc, f(item))) ->
/** @type {Fold<T, Effect<O | Q, S>>} */
const op = item => acc => step(acc, f(item))
return step(items, fold(op)(pure(init)))I enumerated every normalized difference in each module to confirm these are the only ones — one hunk in ll1, one in effects — then checked behaviour rather than arguing from the shape. effects is the core combinator module, so it got a direct comparison against main:
foldStep sum 1..5 main: [15] pr: [15]
foldStep empty list main: [42] pr: [42] (init passes through)
forEachStep main: [null] pr: [null]
okStep ok / error main: [42] [["error","boom"]]
pr : [42] [["error","boom"]]
Both okStep branches, the empty-list edge, and the folding path all match. For ll1 I leaned on the repo's own coverage instead — my ad-hoc parser harness was calling the API wrong (it failed identically against main, so it was my mistake, not a finding), and the three migrated modules' proofs contribute 164 passing cases, with another 222 across effects.
effects/list shows up as differing only because my normalizer rewrites '.f.js' in single quotes and that file uses double quotes — the sole difference is the import specifier, and empty/nonEmpty produce identical results.
Everything else
npx tscclean; 2356 pass / 0 fail.- Public API: 0 removed, 0 non-
_additions. All 10 new types are_-prefixed. The 3 changed types and 3 changed const signatures are entirely those renames (AstRule→_AstRule,DispatchRule→_DispatchRule,DispatchMap→_DispatchMap) plus oneeffects/module.f.ts→effects/types.tsimport path. I confirmed all three renamed types were non-exported onmain, so nothing public was renamed. - No
anyas a type in any emitted declaration. - Markdown links: 144 broken on
main, 144 here, none added, 0 label/target mismatches. No bare.f.tscode-span references to migrated files either — the shape that slipped through on #1486. - All four new
types.tsfiles keep the@moduleheader through emit. - CHANGELOG entries for all five, including the explicit "
proof.f.tsstays TypeScript for now" note.
The proof.f.ts decision is right and I verified the reason. All three bnf proofs import runtime values from ../testlib.f.ts, and data's also from media/json/module.f.ts — both still .f.ts on disk, so §2 does not yet permit proof.f.mjs. Stating that in the PR body and the CHANGELOG rather than leaving a reviewer to work it out is the right call.
CI still finishing on 28199f7; verified locally at that commit.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 28199f733e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| * @template {O} O1 | ||
| * @template T | ||
| * @param {Effect<O1, T>} e | ||
| * @returns {MatchResult<O1, T, R>} |
There was a problem hiding this comment.
Declare the returned match function's type parameters
For any published TypeScript consumer importing this module with the default skipLibCheck: false, declaration emission leaves these nested @template tags as comments rather than emitting an inner generic binder: the resulting .d.mts references undeclared O1 and T and fails with four TS2304 errors. Preserve the previous signature <O1 extends O, T>(e: Effect<O1, T>) => MatchResult<O1, T, R> in valid emitted syntax.
AGENTS.md reference: AGENTS.md:L525-L529
Useful? React with 👍 / 👎.
|
Checked this directly against the actual declaration emit ( export declare const match: <O extends Operation, R>(map: OperationMap<O, R>) => <O1 extends O, T>(
/**
* @template {O} O1
* @template T
* @param {Effect<O1, T>} e
* @returns {MatchResult<O1, T, R>}
*/
e: Effect<O1, T>) => MatchResult<O1, T, R>;
I verified two ways:
No Generated by Claude Code |
|
@codex review |
|
Codex Review: Didn't find any major issues. What shall we delve into next? Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Summary
fjs/bnf/data/module.f.tsfrom authored TypeScript to JSDoc-typed.f.mjs, pertodo/migrate-typescript-to-mjs.md.TerminalRange,Sequence,Variant,Rule,RuleSet,EmptyTag) into a siblingtypes.ts.proof.f.tsstays TypeScript for now — it has a runtime dependency on../testlib.f.tsand../../media/json/module.f.ts, both still unmigrated.fjs/bnf/descent,fjs/bnf/ll1— module + proof each) to import runtime values from.f.mjsand types fromtypes.tsseparately.module.f.tsreferences (paths and, where cited, line numbers) acrossfjs/bnf/data'stodo/docs.Test plan
npx tsc --noEmitcleannode ./fjs/module.ts t— 2356/2356 passGenerated by Claude Code