feat!: sunset the WFL to JavaScript transpiler - #644
Conversation
Pins the user-visible contract of retiring the WFL -> JavaScript transpiler before the code is removed: - `--transpile` and its transpiler-only options must fail with a clear sunset message and exit code 2, not be misparsed as an input path. - No `.js` artifact may be produced by any invocation. - `wfl --help` must not advertise transpilation. - Ordinary interpretation of the same program is unaffected (control). Red evidence: 4 of 5 fail against the current tree (transpiler still present, help still lists TRANSPILATION, `--target` is swallowed as a file path and reports "No such file or directory"). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kg479WsZXi7j1bcZhWjjYu
Removes the transpiler entirely: it only ever covered a shrinking subset of WFL (rejecting web servers, WebSockets, response streaming, and TLS listens outright), so every new runtime feature had to grow a matching "not supported in JS transpilation" arm just to keep the module compiling — a maintenance tax paid for output whose fidelity was never close to the interpreter's. Removed: - src/transpiler/ (mod.rs, javascript.rs, runtime.rs) and the `pub mod transpiler;` export from src/lib.rs - `--transpile` parsing, the transpile execution block, and the TRANSPILATION help section from src/main.rs - tests/transpiler_test.rs - TestPrograms/transpiler_example.wfl - the stale "Compile WFL to JavaScript" planned-feature line in Docs/01-introduction/natural-language-philosophy.md The WFL language itself is unchanged — every existing program still runs identically under the interpreter. Rather than letting `--transpile` fall through and be mistaken for an input file path (which reported a confusing "No such file or directory"), the retired flags --transpile, --target, --no-runtime, and --es-modules are kept as recognized arguments that exit 2 with a message naming the removal and the replacement, so existing build scripts break visibly with the fix in the error text. Green: cargo test --test transpiler_sunset_test — 5 passed, 0 failed. Red evidence in the parent commit f29e1ca (test-only, 4 of 5 failing). Historical records that mention the transpiler (earlier Dev Diary entries, Docs/superpowers/plans/, the timestamped Docs/rust_loc_report.md snapshot) are left intact — they are dated accounts of what was true when written. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kg479WsZXi7j1bcZhWjjYu
📝 WalkthroughWalkthroughThe WFL-to-JavaScript transpiler implementation, exports, CLI mode, tests, and example are removed. Legacy transpiler flags now fail explicitly, help output is updated, interpreter execution remains supported, and documentation records the sunset. ChangesJavaScript transpiler sunset
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2327776a0b
ℹ️ 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".
| - **The WFL to JavaScript transpiler has been sunset.** The `wfl --transpile` | ||
| command and its `--target`, `--no-runtime`, and `--es-modules` options are gone, | ||
| along with the `wfl::transpiler` library module (`JavaScriptTranspiler`, | ||
| `TranspilerConfig`, `TranspilerTarget`, `transpile`, `transpile_default`). The |
There was a problem hiding this comment.
Keep the transpiler working through the deprecation window
For existing build scripts using wfl --transpile and downstream crates importing wfl::transpiler, this removes shipped contracts immediately. The same-change changelog notice and failure message do not satisfy GOVERNANCE.md §3.1, which requires announcing an unavoidable break at least one year in advance and retaining the old behavior until that deadline; interpreting the WFL file is also not a migration path for consumers that require JavaScript output. Preserve these surfaces during the documented deprecation period.
AGENTS.md reference: AGENTS.md:L20-L22
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Raised with the Maintainer. Decision: proceed with the immediate removal, with the rationale recorded rather than left implicit. Documented in cedfeaf.
On the substance of §3.1 — it opens with:
Never break existing WFL programs without a documented path.
That is the surface it protects, and no WFL program is affected. The language, its semantics, the analyzer, the type checker, and the interpreter are untouched; all 110 runnable programs in TestPrograms/ pass unchanged against the release build. What is withdrawn is build tooling (--transpile) and a library module (wfl::transpiler) — neither of which any .wfl source file can depend on. The ≥ 1-year window governs language breaks; it isn't triggered by retiring a CLI mode.
Per §2.2, "Language design / breaking change → Maintainer(s)". The Maintainer directed this sunset and, when this objection was put to them explicitly, chose immediate removal over a deferred window.
You're right about one thing, and I've stated it plainly rather than papering over it: a downstream crate importing wfl::transpiler loses it with no shim, and a build script calling --transpile breaks. It breaks loudly, with the fix in the error text, but it does break. That trade was made deliberately. Both the CHANGELOG entry and the Dev Diary now carry the decision and its residual cost.
On "interpreting the WFL file is not a migration path for consumers that require JavaScript output" — agreed, and there is no such path. That is the point of a sunset: the capability is gone, not relocated. Claiming otherwise would be the dishonest option.
Generated by Claude Code
| The sunset tests were written and run first, on the tree with the transpiler | ||
| still present, and committed test-only as `f29e1ca` (an ancestor of the removal | ||
| commit). |
There was a problem hiding this comment.
Make the recorded Red commit an ancestor of this change
For the reviewed commit, git merge-base --is-ancestor f29e1ca 911f20e fails: f29e1ca and this commit both have 8d6aaed as their parent, while this commit already bundles the tests with the removal. Thus the asserted ancestry is false, and no timestamped CI artifact is identified as alternative Red evidence; base the production change on the test-only commit or record valid artifact evidence before merging.
AGENTS.md reference: AGENTS.md:L130-L134
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
This finding doesn't hold up — the ancestry is valid.
The commit it checks against, 911f20e, is not in this repository:
$ git cat-file -t 911f20e
fatal: Not a valid object name 911f20e
This branch is linear, and the Red commit is a genuine ancestor of the removal:
$ git merge-base --is-ancestor f29e1ca HEAD && echo "ancestor"
ancestor
$ git log --oneline --graph -4
* ca3bee3 test: match JavaScript artifacts case-insensitively in the sunset check
* 8211096 fix: recognize -h/-V aliases and make the no-JS assertion recursive
* 2327776 feat!: sunset the WFL to JavaScript transpiler
* f29e1ca test: add Red sunset tests for the JavaScript transpiler removal
* 8d6aaed Bump version to 26.7.49 [skip ci]
The PR's own commit list confirms the same three commits in that order. f29e1ca is test-only — it adds tests/transpiler_sunset_test.rs and nothing else; the transpiler was still fully present at that commit, which is why 4 of its 5 tests failed there. The production removal lands separately in 2327776. That satisfies testing.md §3/§6: a Red test-only commit that is an ancestor of the Green commit.
No change made. Happy to be corrected if 911f20e refers to something I can't see from here.
Generated by Claude Code
There was a problem hiding this comment.
Pull request overview
This PR sunsets/removes the WFL → JavaScript transpiler from the codebase and pins the post-removal CLI/user-facing contract with new integration tests, ensuring the retired flags fail clearly (exit code 2) and that no JS artifacts are produced.
Changes:
- Removed the
wfl::transpilermodule and related transpiler runtime/generator implementation. - Removed
--transpilesupport from the CLI help and execution flow, replacing it (and related flags) with an explicit sunset error (exit code 2). - Replaced the old transpiler unit tests and example program with a new CLI-level “sunset contract” test suite, plus docs/dev-diary/changelog updates.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/transpiler_test.rs | Removed the old unit/integration tests for the transpiler implementation. |
| tests/transpiler_sunset_test.rs | Added integration tests that assert the post-removal CLI contract (flags rejected, no JS output, help updated, interpreter unaffected). |
| TestPrograms/transpiler_example.wfl | Removed the transpiler demo program. |
| src/transpiler/runtime.rs | Removed the embedded JS runtime strings and runtime selector. |
| src/transpiler/mod.rs | Removed transpiler public API types/configs and entrypoints. |
| src/transpiler/javascript.rs | Removed the JS code generator implementation and its internal tests. |
| src/main.rs | Removed transpile CLI/help behavior and added explicit “transpiler removed” error handling for legacy flags. |
| src/lib.rs | Removed pub mod transpiler; from the library surface. |
| Docs/01-introduction/natural-language-philosophy.md | Updated docs to no longer list “Compile WFL to JavaScript” as a planned feature. |
| Dev diary/2026-07-26-sunset-javascript-transpiler.md | Added a dev diary entry documenting rationale, risk class, and test coverage. |
| CHANGELOG.md | Documented the transpiler sunset/removal and migration guidance. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /// Assert no `.js` artifact was written anywhere under `dir`. | ||
| fn assert_no_js_output(dir: &TempDir) { | ||
| for entry in fs::read_dir(dir.path()).expect("read temp dir") { | ||
| let path = entry.expect("dir entry").path(); | ||
| assert_ne!( | ||
| path.extension().and_then(|e| e.to_str()), | ||
| Some("js"), | ||
| "transpiler is removed, but a JavaScript file was produced: {}", | ||
| path.display() | ||
| ); | ||
| } | ||
| } |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/main.rs (1)
103-142: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
-hand-Vare treated as trivial but never actually handled.The fast-path check treats
-hand-Vas equivalent to--help/--version(Line 111), butrun()'s actual parsing only recognizes--help(Line 187) and--version/-v(Line 587) — never-hor-V. Runningwfl -horwfl -Vwill fall through to the default arg-parsing arm, be treated as a file path, and fail with a raw "No such file or directory" IO error instead of printing help/version.🐛 Proposed fix
- if args.len() >= 2 && args[1] == "--help" { + if args.len() >= 2 && matches!(args[1].as_str(), "--help" | "-h") { print_help(); return Ok(()); }- "--version" | "-v" => { + "--version" | "-v" | "-V" => { println!("WebFirst Language (WFL) version {}", wfl::version::VERSION); return Ok(()); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/main.rs` around lines 103 - 142, Update the argument handling in run() so the short aliases -h and -V are recognized as help and version respectively, matching the trivial invocation check in main(). Preserve the existing behavior for --help, --version, and -v, and ensure these aliases no longer fall through to file-path handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@Dev` diary/2026-07-26-sunset-javascript-transpiler.md:
- Around line 48-55: Update tests/transpiler_sunset_test.rs::assert_no_js_output
to recursively inspect the temporary directory and all nested subdirectories for
JavaScript artifacts, so paths such as nested/out.js are detected before the
assertion passes.
In `@tests/transpiler_sunset_test.rs`:
- Around line 47-58: Update assert_no_js_output to traverse dir recursively
rather than inspecting only fs::read_dir(dir.path()) at the top level, and apply
the existing .js assertion to every discovered file while preserving the current
failure message.
---
Outside diff comments:
In `@src/main.rs`:
- Around line 103-142: Update the argument handling in run() so the short
aliases -h and -V are recognized as help and version respectively, matching the
trivial invocation check in main(). Preserve the existing behavior for --help,
--version, and -v, and ensure these aliases no longer fall through to file-path
handling.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 2e3388f5-2381-4bf0-b574-ba3a753087f4
📒 Files selected for processing (11)
CHANGELOG.mdDev diary/2026-07-26-sunset-javascript-transpiler.mdDocs/01-introduction/natural-language-philosophy.mdTestPrograms/transpiler_example.wflsrc/lib.rssrc/main.rssrc/transpiler/javascript.rssrc/transpiler/mod.rssrc/transpiler/runtime.rstests/transpiler_sunset_test.rstests/transpiler_test.rs
💤 Files with no reviewable changes (7)
- TestPrograms/transpiler_example.wfl
- src/lib.rs
- src/transpiler/mod.rs
- tests/transpiler_test.rs
- src/transpiler/javascript.rs
- Docs/01-introduction/natural-language-philosophy.md
- src/transpiler/runtime.rs
Addresses two review findings, both verified against the current tree before changing anything. 1. `assert_no_js_output` claimed in its doc comment to check "anywhere under `dir`" but did a single non-recursive `read_dir`, so a nested artifact like `nested/out.js` would have slipped through and the absence assertion would have passed vacuously. The helper now walks subdirectories; `run_cli` creates a writable `nested/` for the binary to emit into, and the full historical invocation targets `--output nested/out.js` so the recursion is exercised rather than being untested safety code. Confirmed by planting a nested `planted.js` and observing the assertion fire on it. 2. `wfl -h` and `wfl -V` were mistaken for input file paths. This is the same root cause as the transpiler flags: `main()` already classifies `-h`/`-V` as trivial, non-interpreting invocations, but the parser in `run()` only recognized `--help`, `--version`, and `-v`, so both aliases fell through to the generic argument arm and failed with `No such file or directory`. Pre-existing and unrelated to the transpiler, fixed here because it is the same misparse the sunset work was about. Red evidence for (2): tests/cli_help_version_flags_test.rs observed failing 3 of 3 on `-h`/`-V` before the fix, reporting the exact `No such file or directory` misparse. Validation: cargo test --all --no-fail-fast — 1908 passed, 0 failed, 27 ignored; TestPrograms sweep 110 passed, 0 failed; clippy -D warnings and cargo fmt --check clean; all five help/version spellings verified against the release binary. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kg479WsZXi7j1bcZhWjjYu
Copilot's review thread also flagged that `assert_no_js_output` compared the extension case-sensitively. The recursion fix in 8211096 addressed only the traversal half of that comment, so this completes it: `out.JS` is just as much a leaked artifact as `out.js`, and on a case-insensitive filesystem they are the same file. Verified by planting `nested/LEAK.JS` and observing the assertion fire on it; restored afterwards. cargo test --test transpiler_sunset_test — 5 passed, 0 failed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kg479WsZXi7j1bcZhWjjYu
| println!(" --time Measure and display execution time"); | ||
| println!(" --test Run file in test mode"); |
There was a problem hiding this comment.
Fixed in cedfeaf. print_help() now reads:
--help, -h Prints this help information
--version, -v, -V Prints the version information
Pinned by cli_help_version_flags_test::help_text_documents_the_short_aliases, which was observed Red against the prior tree before the fix.
Your other two comments in this review are also addressed: the --output clarification landed in the same commit (the sunset error now says --output still exists for --dump-env but no longer emits JavaScript), and the case-sensitive .js extension was fixed in ca3bee3 via eq_ignore_ascii_case.
Generated by Claude Code
| " '{}' was a transpiler-only option, so it is no longer supported.", | ||
| args[i] | ||
| ); | ||
| eprintln!(" Removed together: --transpile, --target, --no-runtime, --es-modules."); |
| assert_ne!( | ||
| path.extension().and_then(|e| e.to_str()), | ||
| Some("js"), | ||
| "transpiler is removed, but a JavaScript file was produced: {}", | ||
| path.display() | ||
| ); |
…rors Addresses the second review round on #644. Governance (P1, chatgpt-codex-connector): the reviewer read GOVERNANCE.md §3.1 as requiring a >= 1-year deprecation window before removing `--transpile` and `wfl::transpiler`. §3.1 protects "existing WFL programs", and none are affected — the language, semantics, and all 110 runnable TestPrograms are unchanged; what is withdrawn is build tooling and a library module. Per §2.2 that decision rests with the Maintainer, who directed the sunset and chose immediate removal when the objection was put to them. Recorded in CHANGELOG.md and the Dev Diary so the call is auditable rather than implicit, including the residual cost to downstream crates. Copilot findings: - `print_help()` did not document `-h`/`-V`, making the aliases added in 8211096 undiscoverable. Help now lists `--help, -h` and `--version, -v, -V`. - The sunset error said nothing about `--output`, which outlived the transpiler (it still serves --dump-env), leaving a former user unable to tell whether it still emitted JavaScript. It now says so explicitly. - The case-sensitivity half of the `.js` check was already fixed in ca3bee3. Both behavioral fixes were observed Red first: `help_text_documents_the_short_aliases` and the new `--output` assertion in `transpile_flag_is_rejected_with_sunset_message` each failed against the prior tree for the intended reason. Validation: cargo test --all --no-fail-fast — 1909 passed, 0 failed, 27 ignored; clippy -D warnings and cargo fmt --check clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kg479WsZXi7j1bcZhWjjYu
Pins the user-visible contract of retiring the WFL -> JavaScript
transpiler before the code is removed:
--transpileand its transpiler-only options must fail with a clearsunset message and exit code 2, not be misparsed as an input path.
.jsartifact may be produced by any invocation.wfl --helpmust not advertise transpilation.Red evidence: 4 of 5 fail against the current tree (transpiler still
present, help still lists TRANSPILATION,
--targetis swallowed as afile path and reports "No such file or directory").
Co-Authored-By: Claude Opus 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01Kg479WsZXi7j1bcZhWjjYu
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Summary by CodeRabbit