CLI レビュー
作成日: 2026-04-25
対象: nepl-cli/src/**, nodesrc/** の CLI / テスト実行系
レビュー範囲
| 区分 | ファイル |
|---|---|
| Rust CLI | nepl-cli/src/main.rs, nepl-cli/src/codegen_llvm.rs |
| Node CLI | nodesrc/cli.js, nodesrc/tests.js, nodesrc/run_test.js, nodesrc/run_doctest.js |
| Node parser / docs | nodesrc/parser.js, nodesrc/parser.ts, nodesrc/html_gen.js, nodesrc/html_gen.ts |
| playground tests | nodesrc/playground_*_test_runner.js, nodesrc/tui_regression.js |
総評
Rust CLI は compiler 実行、WASI runtime、test runner、WAT/LLVM 出力、診断表示を 1 ファイルに抱えており、core と同様に責務が集中しています。特に --check が実際の compile を行わない問題は、ユーザーに誤った成功を返すため最優先で修正が必要です。
Node 側は doctest 実行の中心になっていますが、HTML 生成 CLI、playground test、compiler artifact 探索が同居しています。テストの信頼性を上げるには、Rust CLI の test サブコマンドと Node doctest runner の役割を整理する必要があります。
RV-CLI-001: --check がコンパイルせず成功を返す
- 解決済: true
- 状態: verified
- 優先度: P0
- 種別: bug
- 対象:
nepl-cli/src/main.rs
根拠
nepl-cli/src/main.rs:304:if cli.check { eprintln!("Check successful"); return Ok(()); }- この分岐は
compile_module_with_source_map呼び出しより前にある。
問題
--check が loader の parse 成功後、typecheck / monomorphize / move check / codegen precheck を一切実行せず成功を返します。型エラーや未定義関数があっても Check successful になります。
影響
CI やユーザーが --check を信用できません。コンパイル不能なコードが成功扱いになるため、最も危険な CLI バグです。
修正方針
--check では target/profile を確定したうえで prepare_module_for_codegen_with_source_map 相当まで実行します。wasm bytes は出さず、diagnostics が error を含む場合は exit code 1 にします。
対応結果
nepl-cli/src/main.rs の cli.check 分岐を compile_module_with_source_map 実行後へ移動しました。これにより loader だけでなく typecheck / monomorphize / move check / codegen precheck を通過した場合だけ Check successful を返します。
検証
nepl-cli/src/main.rs に check_runs_compiler_diagnostics を追加し、未定義シンボルを含む入力で nepl-cli --check -i file 相当が失敗することを確認します。
確認済み:
cargo test -p nepl-cli check_runs_compiler_diagnosticstrunk buildnode nodesrc/cli.js -i tests/playground_editor --playground-editor-tests -o json=tmp/playground-editor-tests.json(caseCount=13,passedCount=13,failedCount=0)
RV-CLI-002: 通常実行で DEBUG ログが出力される
- 解決済: true
- 状態: verified
- 優先度: P1
- 種別: bug
- 対象:
nepl-cli/src/main.rs,nepl-cli/tests/cli_output.rs
根拠
nepl-cli/src/main.rs:249:DEBUG: Creating Loader...nepl-cli/src/main.rs:251:DEBUG: Loader created...nepl-cli/src/main.rs:345:DEBUG: Calling compile_modulenepl-cli/src/main.rs:348:DEBUG: compile_module returned Oknepl-cli/src/main.rs:462: test 実行中に[nepl-cli] run_test_file...を stdout へ出す。
問題
--verbose なしでも debug log が stderr/stdout に出ます。プログラム実行出力や JSON wrapper と混ざると、テスト比較や外部ツール連携を壊します。
影響
doctest の stdout/stderr 比較が不安定になります。CLI を他ツールから呼ぶと、機械処理できない余分な出力が混入します。
修正方針
全 debug output を cli.verbose gate の下に移します。test progress は human mode と JSON mode を分け、出力先を統一します。
対応結果
CLI 内部の DEBUG: 出力と nepl-cli test の内部進捗ログを cli_verbose! に集約し、--verbose 指定時だけ出力するようにしました。--check 成功メッセージは診断用の stderr ではなく stdout に移し、通常成功時の stderr を空にできるようにしました。
nepl-cli/tests/cli_output.rs を追加し、通常の --check / compile / test subcommand で debug 出力が stdout/stderr に混入しないことと、--verbose では CLI/core loader debug が見えることを固定しました。
検証
確認済み:
cargo test -p nepl-cli --test cli_output:4 passedcargo test -p nepl-cli: unit8 passed, integration4 passed, ignored2cargo fmt --all --checkcargo check --workspacetrunk buildnode tests/compiler/tree/run.js:total=19,passed=19,failed=0node nodesrc/cli.js -i tests/playground_editor --playground-editor-tests -o json=tmp/playground-editor-tests.json:13/13 passed
RV-CLI-003: nepl-cli test が n.md doctest を対象にしない
- 解決済: true
- 状態: fixed
- 優先度: P1
- 種別: test
- 対象:
nepl-cli/src/main.rs,nodesrc/tests.js
根拠
nepl-cli/src/main.rs:499:collect_nepl_filesは.neplだけを集める。nodesrc/tests.js:1: Node runner は/tests/compiler/*.n.md,/tests/stdlib/*.n.md,/tutorials/**/*.n.md,/stdlib/**/*.neplを対象にする設計。- リポジトリの stdlib test は
stdlib/tests/*.n.mdとtests/stdlib/*.n.mdが中心。
問題
Rust CLI の test サブコマンドと実際の標準テスト形式が一致していません。nepl-cli test は主要 doctest を拾えないため、テストコマンドとして信頼できません。
影響
開発者が nepl-cli test を実行しても、実際の回帰テストを通したことになりません。AGENTS.md の「nodesrc/cli.js のテストを実行し output json を確認」とも分断されています。
修正方針
Rust CLI の test サブコマンドを Node doctest runner と統合するか、廃止して公式テストコマンドを nodesrc/tests.js に一本化します。少なくとも .n.md doctest を parse して実行できるようにします。
検証
stdlib/tests/*.n.md の件数が Rust CLI test と Node runner で一致することを確認します。
RV-CLI-004: WASI fd_write が stdout 専用で stderr を扱えない
- 解決済: true
- 状態: verified
- 優先度: P1
- 種別: bug
- 対象:
nepl-cli/src/main.rs,nepl-cli/tests/cli_output.rs
根拠
nepl-cli/src/main.rs:1189: コメントがMinimal wasi fd_write implementation for stdout (fd 1)。nepl-cli/src/main.rs:1199:if fd != 1 { return 8; }
問題
WASI の fd_write は stdout(fd=1) だけを許可し、stderr(fd=2) を badf 扱いにします。stdlib や将来の診断出力が stderr を使うと失敗します。
影響
WASI 互換性が不足し、標準エラーを使うプログラムが正常に動きません。テストで stderr を期待するケースも CLI runtime では扱いにくくなります。
修正方針
fd 1 と fd 2 を分けて host stdout/stderr へ書きます。stdout buffering と stderr immediate flush の方針を明記し、nwritten は両方で正しく返します。
対応結果
fd_write の iovec 読み取りを stdout/stderr 共通の helper に切り出し、fd 1 は既存の stdout buffer 方針を維持、fd 2 は host stderr へ即時 flush するようにしました。nwritten の書き戻しも共通化し、負の pointer / 範囲外 iovec は fault として扱います。
nepl-cli/tests/cli_output.rs に fd 2 へ err を書き込む WASI fixture を追加し、成功時に stdout が空で stderr が期待値になることを固定しました。
検証
WASI program から fd 2 へ出力する fixture を追加し、stderr 比較を固定します。
確認済み:
cargo fmt --all --check: passcargo test -p nepl-cli --test cli_output run_wasi_fd_write_supports_stderr -- --nocapture: passcargo test -p nepl-cli: passcargo check --workspace: passnode tests/compiler/tree/run.js:19/19 passedtrunk build: passnode nodesrc/cli.js -i tests/playground_editor --playground-editor-tests -o json=tmp/playground-editor-tests-rv-cli-004.json:13/13 passedgit diff --check: pass
RV-CLI-005: path_open が WASI の preopen モデルを実装していない
- 解決済: true
- 状態: verified
- 優先度: P1
- 種別: security
- 対象:
nepl-cli/src/main.rs,nepl-cli/tests/cli_output.rs
根拠
nepl-cli/src/main.rs:919:path_openhost function。nepl-cli/src/main.rs:945: path bytes を host path として直接fs::read(path)。stdlib/std/fs.nepl:160:dirfdは 3 preopen を仮定するとコメントしている。
問題
WASI の preopen directory、rights、flags、relative path 解決を実装せず、guest 文字列を host path として直接読んでいます。dirfd, rights_base, oflags も実質無視されています。
影響
WASI 互換性だけでなく、sandbox として危険です。テストが host working directory に依存し、将来の file API の挙動が実環境で変わります。
修正方針
preopen table を AllocState に持ち、path_open は dirfd と rights を検査して preopen root 内の canonical path のみ許可します。読み込み専用から始め、errno を WASI の値に合わせます。
対応結果
AllocState に preopen table を追加し、fd 3 を CLI 実行時の current directory に対応する preopen root として初期化しました。path_open は dirfd、flags、rights、guest path、fd_out pointer を検査し、relative path を canonicalize した上で preopen root 内の通常ファイルだけを読み込みます。
..、absolute path、別 drive prefix、unsupported flags / rights は sandbox 逸脱または invalid として拒否します。存在しない path は NOENT、不正な memory range は FAULT、未登録 dirfd は BADF を返すようにし、host path を guest 文字列から直接 fs::read する経路を削除しました。
検証
preopen 内ファイル読み込み、preopen 外 .. 拒否、存在しない path の errno を nepl-cli/tests/cli_output.rs の raw WASI fixture で固定しました。stdlib/std/fs.nepl 経由の doctest 実行は RV-STDLIB-006 の範囲で扱い、ここでは CLI runtime の path_open sandbox 境界だけを切り分けて検証しています。
確認済み:
cargo fmt --all --check: passcargo test -p nepl-cli --test cli_output run_wasi_path_open -- --nocapture: 3 passedcargo test -p nepl-cli: unit 8 passed, integration 8 passed, ignored 2cargo check --workspace: passnode tests/compiler/tree/run.js: 19/19 passedtrunk build: passnode nodesrc/cli.js -i tests/playground_editor --playground-editor-tests -o json=tmp/playground-editor-tests-rv-cli-005.json: 13/13 passedgit diff --check: pass
RV-CLI-006: stdlib root がビルド時パスに固定されている
- 解決済: true
- 状態: verified
- 優先度: P2
- 種別: architecture
- 対象:
nepl-cli/src/main.rs,nepl-cli/tests/cli_output.rs
根拠
nepl-cli/src/main.rs:1348:stdlib_root()がenv!("CARGO_MANIFEST_DIR")/../stdlibを canonicalize する。
問題
ビルドしたバイナリを別ディレクトリへ移動すると stdlib が解決できません。CLI オプションや環境変数による stdlib root override もありません。
影響
配布・CI・エディタ連携で壊れやすいです。workspace 内でしか動かない CLI になります。
修正方針
優先順を --stdlib-root、NEPL_STDLIB_ROOT、実行ファイル相対、ビルド時 fallback にします。診断には探索した候補を出します。
対応結果
CLI に global option --stdlib-root <DIR> を追加し、通常 compile/check/run と nepl-cli test の両方で同じ stdlib root resolver を使うようにしました。明示 option がなければ NEPL_STDLIB_ROOT、実行ファイル隣接 layout、実行ファイル prefix layout、ビルド時 fallback の順で探索します。
明示 option と環境変数は設定ミスを隠さないため、不正な directory の場合は fallback せずに失敗します。候補は core と std directory を持つ canonical directory だけを stdlib root として採用し、失敗時の診断に試行した source と path を出すようにしました。
検証
temp dir に stdlib をコピーし、default stdlib には存在しない extra/answer module を追加した上で、--stdlib-root と NEPL_STDLIB_ROOT の両方から import できることを CLI テストで固定しました。nepl-cli test subcommand でも global --stdlib-root が効くこと、不正な explicit root で試行候補を含む診断になることも確認しています。
確認済み:
cargo fmt --all --check: passcargo test -p nepl-cli stdlib_root -- --nocapture: unit 1 passed, integration 4 passedcargo test -p nepl-cli: unit 9 passed, integration 12 passed, ignored 2cargo check --workspace: passnode tests/compiler/tree/run.js: 19/19 passedtrunk build: passnode nodesrc/cli.js -i tests/playground_editor --playground-editor-tests -o json=tmp/playground-editor-tests-rv-cli-006.json: 13/13 passedgit diff --check: pass
RV-CLI-007: LLVM toolchain 条件が既定で linux + clang 21.1.0 に固定される
- 解決済: true
- 状態: fixed
- 優先度: P2
- 種別: bug
- 対象:
nepl-cli/src/codegen_llvm.rs
根拠
nepl-cli/src/codegen_llvm.rs:13: default clang は"clang"。nepl-cli/src/codegen_llvm.rs:16: 既定で21.1.0exact match。nepl-cli/src/codegen_llvm.rs:25: 既定で linux host を要求。
問題
LLVM target の既定値が非常に狭く、Windows / macOS / 別 clang minor version で失敗しやすいです。環境変数で回避できますが、通常利用の初期体験としては厳しすぎます。
影響
LLVM backend の検証が特定環境に偏ります。ユーザーの現在環境が Windows の場合、既定では利用不能です。
修正方針
既定は clang 実行可否と minimum feature check にし、exact version は CI 用 strict mode に分離します。host OS requirement も target triple option として明示します。
検証
strict mode と relaxed mode の CLI unit test を分けます。
RV-CLI-008: nodesrc/cli が未知引数をエラーにしない
- 解決済: true
- 状態: verified
- 優先度: P3
- 種別: test
- 対象:
nodesrc/cli.js,nodesrc/test_cli_args.js
根拠
nodesrc/cli.js:36: 独自parseArgs。nodesrc/cli.js:43以降: 認識した引数だけを処理し、未知引数を default で無視する。
問題
--playgroud-editor-tests のような typo をしても usage error にならず、別モードとして実行される可能性があります。
影響
CI や手元確認でテストを実行したつもりが、実際には別処理になっていても検出できません。
修正方針
未知引数は即 error にします。--help だけは例外です。将来的には commander などに寄せてもよいですが、まずは現行 parser に default error を追加します。
対応結果
nodesrc/cli.js に UsageError を追加し、未知引数と必須値不足を usage error として exit code 2 で返すようにしました。-i / -o / --exclude-dir / --site-name / --description-prefix / Discord options は共通の value checker を通し、値不足が通常の runtime error と混ざらないようにしました。
通常の runtime error は引き続き exit code 1 とし、--help は exit code 0 のままです。これにより --playgroud-editor-tests のような typo が silent ignore されず、CI や手元確認で失敗として検出できます。
検証
nodesrc/test_cli_args.js を追加し、未知引数、必須値不足、--help の exit code と出力を固定しました。
確認済み:
node nodesrc/test_cli_args.js: passcargo fmt --all --check: passcargo test -p nepl-cli: unit 9 passed, integration 12 passed, ignored 2cargo check --workspace: passnode tests/compiler/tree/run.js: 19/19 passedtrunk build: passnode nodesrc/cli.js -i tests/playground_editor --playground-editor-tests -o json=tmp/playground-editor-tests-rv-cli-008.json: 13/13 passedgit diff --check: pass
RV-CLI-009: wasm-bindgen-cli cache が rust-cache の後処理で壊れ CI bootstrap が落ちる
- 解決済: true
- 状態: verified
- 優先度: P1
- 種別: test
- 対象:
.github/actions/bootstrap-build/action.yml,.github/workflows/ci.yml
根拠
.github/actions/bootstrap-build/action.yml:55:actions/cache@v4で~/.cargo/bin/wasm-bindgenなどをwasm-bindgen-cli-Linux-X64-0.2.108として cache している。.github/actions/bootstrap-build/action.yml:67: cache hit 時はcargo install --locked wasm-bindgen-cli --version 0.2.108を実行しない。.github/actions/bootstrap-build/action.yml:83: 直後にwasm-bindgen --versionで存在確認している。.github/actions/bootstrap-build/action.yml:88: 同じ composite action の後段でSwatinem/rust-cache@v2を実行している。- GitHub Actions run
24931603415:Shared bootstrap buildがwasm-bindgen: command not foundにより exit code 127 で失敗した。 - GitHub Actions run
24929865567: build job でwasm-bindgen-cliを install した後、post step で... Cleaning cargo/bin ...が出てからCache saved with key: wasm-bindgen-cli-Linux-X64-0.2.108が実行された。 gh cache list --repo neknaj/NEPLg2 --key wasm-bindgen-cli-Linux-X64-0.2.108では該当 cache が626 Bで、wasm-bindgenバイナリを含むサイズではなかった。
問題
wasm-bindgen-cli 専用 cache と Swatinem/rust-cache が同じ ~/.cargo/bin を扱っています。GitHub Actions の post step は main step と逆順に実行されるため、後から定義された Swatinem/rust-cache の後処理が先に ~/.cargo/bin を掃除し、その後で先に定義された actions/cache が wasm-bindgen 用 cache を保存します。
その結果、wasm-bindgen-cli-Linux-X64-0.2.108 という正常そうな key に、バイナリを含まない空に近い cache が保存されます。次回以降は cache hit により install step がスキップされ、wasm-bindgen --version が command not found で失敗します。
影響
build job が Shared bootstrap build で止まるため、bootstrap-build artifact が upload されません。compile-test / rust-test / wasi-test / stdlib-test など build に依存する job は実行されず、pages-final-bundle と pages-final-deploy も artifact 不在で派生失敗します。結果として CI が本来のコンパイラ・stdlib 回帰を検証できません。
修正方針
wasm-bindgen-cli の cache を Swatinem/rust-cache の ~/.cargo/bin cleaning と競合しない形に変更します。候補は次のいずれかです。
wasm-bindgen-cli専用 cache を廃止し、毎回cargo install --locked wasm-bindgen-cli --version 0.2.108を実行する。cargo install --rootで workspace 内または専用 directory に install し、その directory を cache してGITHUB_PATHへ追加する。- cache hit 後も
command -v wasm-bindgenとwasm-bindgen --versionを検査し、壊れた cache の場合は再 install する。 - 既存 key を変えて、壊れた
wasm-bindgen-cli-Linux-X64-0.2.108cache を再利用しない。
単に Verify wasm-bindgen-cli を消すのではなく、cache が壊れていても bootstrap が自己修復する構造にします。
対応
.github/actions/bootstrap-build/action.yml で wasm-bindgen-cli の install root を ${GITHUB_WORKSPACE}/.cache/wasm-bindgen-cli/0.2.108 へ移し、cache key を 0.2.108-v2 に変更しました。cache hit 後も wasm-bindgen --version が 0.2.108 を返すか検査し、壊れていれば専用 root を削除して cargo install --root で再 install します。
GitHub Actions run 24932659255 の build job で Shared bootstrap build と Upload bootstrap build artifacts が成功し、bootstrap artifact 依存の後続 job へ進めることを確認しました。
検証
gh run view <run-id> --log-failed で Shared bootstrap build が wasm-bindgen --version を通過することを確認します。壊れた cache が残っている状態でも、再 install または専用 path への install により trunk build --release --public-url /NEPLg2/ まで進むことを確認します。
RV-CLI-010: Pages fast/final deploy が同じ github-pages artifact 名を使い final deploy が落ちる
- 解決済: true
- 状態: verified
- 優先度: P1
- 種別: test
- 対象:
.github/workflows/ci.yml
根拠
.github/workflows/ci.yml:389:pages-fast-bundleがactions/upload-pages-artifact@v3を既定設定で実行している。.github/workflows/ci.yml:410:pages-fast-deployがactions/deploy-pages@v4を既定 artifact 名で実行している。.github/workflows/ci.yml:412:pages-final-bundleはneedsをalways()で受け、同じ push run 内で final Pages artifact を作る。.github/workflows/ci.yml:496:pages-final-bundleもactions/upload-pages-artifact@v3を既定設定で実行している。.github/workflows/ci.yml:517:pages-final-deployもactions/deploy-pages@v4を既定 artifact 名で実行している。- GitHub Actions run
24929865567: build と final bundle は通ったが、pages-final-deployがMultiple artifacts named "github-pages" were unexpectedly found for this workflow run. Artifact count is 2.で失敗した。
問題
pages-fast-bundle と pages-final-bundle が同じ workflow run 内で、どちらも既定名 github-pages の Pages artifact を upload します。pages-fast-deploy で pending site を先に出す設計自体は有効ですが、artifact は同じ run 内に残ります。
そのため pages-final-deploy が final site を deploy しようとすると、actions/deploy-pages が同名 github-pages artifact を 2 つ見つけて停止します。今回 run 24931603415 では build が先に失敗したため No artifacts named "github-pages" として見えていますが、bootstrap が直ると run 24929865567 と同じ同名 artifact 問題が再発する可能性があります。
影響
push CI で Pages の pending deploy と final deploy を同じ workflow run に入れている限り、final Pages 更新が安定しません。テスト結果 JSON を merge した final site を公開できず、CI 上の失敗も実テスト失敗なのか Pages 配布設計の失敗なのか分かりにくくなります。
修正方針
fast と final の Pages artifact 名を分離し、それぞれの deploy step が対応する artifact 名を明示して参照するようにします。actions/upload-pages-artifact / actions/deploy-pages の対応 version で artifact name 指定が可能かを確認し、可能なら github-pages-fast と github-pages-final のように分けます。
artifact 名分離ができない場合は、pending deploy と final deploy を別 workflow に分割するか、fast deploy を廃止して final deploy だけにするなど、同一 run 内に github-pages artifact が複数残らない構造へ変更します。
対応
.github/workflows/ci.yml で pending site の artifact 名を github-pages-pending、final site の artifact 名を github-pages-final に分け、各 actions/deploy-pages@v4 の artifact_name に対応する名前を指定しました。
GitHub Actions run 24932659255 で pages-fast-bundle、pages-fast-deploy、pages-final-bundle、pages-final-deploy が成功し、Multiple artifacts named "github-pages" が再発しないことを確認しました。
検証
bootstrap が成功する状態で push CI を実行し、pages-fast-deploy と pages-final-deploy がそれぞれ意図した artifact を deploy することを確認します。gh run view <run-id> --log-failed で Multiple artifacts named "github-pages" が出ないことを確認します。
RV-CLI-011: llvm-test の full dual backend verification が CI timeout で cancelled になる
- 解決済: false
- 状態: open
- 優先度: P1
- 種別: test
- 対象:
.github/workflows/ci.yml,nodesrc/tests.js
根拠
.github/workflows/ci.yml:288:llvm-testjob のtimeout-minutesは 10 分。.github/workflows/ci.yml:351:Full dual backend verificationはtimeout --signal=KILL 10m node nodesrc/tests.js -i tests -i stdlib -o tests-dual-full.json --runner all --llvm-all --assert-io --strict-dual -j 2を実行する。- GitHub Actions run
24932659255:LLVM doctests via nodesrc runnerは成功したが、Full dual backend verificationが完了せず、llvm-testjob はcancelledになった。 - 同 run の log では
14:11:16に full dual backend verification が始まり、14:18:26にThe operation was canceled.で停止している。tests-dual-full.jsonは upload されていない。
問題
llvm-test は LLVM toolchain の install / verify、compile-only smoke test、全 tests / stdlib の dual backend verification を 1 つの 10 分 job に詰め込んでいます。full dual backend verification は対象範囲が広く、現状の failing doctest 群や LLVM backend 起動コストも含めると、CI の job timeout 内に完了しません。
影響
llvm-test が cancelled になるため、LLVM backend の実際の失敗内容が JSON artifact として残りません。pages-final-bundle は always() で続行できますが、final status は llvm_test: cancelled になり、CI が「LLVM backend の回帰」なのか「検証設計の timeout」なのかを切り分けにくくなります。
修正方針
LLVM smoke test と full dual backend verification を分けます。まず smoke test は短時間で必ず artifact を残す job とし、full dual backend verification は対象を shard するか、changed-only / nightly 相当の別 workflow に分離します。nodesrc/tests.js 側でも一定件数ごとに progress と部分 JSON を flush できるようにし、timeout 時にも最後に処理していた test id が分かるようにします。
検証
push CI で llvm-test または分割後の LLVM jobs が cancelled にならず、llvm-tests artifact に tests-llvm.json と full verification の結果 JSON が残ることを確認します。full verification を別 workflow に逃がす場合は、main CI の必須判定と Pages status summary の扱いを明示します。
2026-04-26 CI確認
gh run view 24940960078 --repo neknaj/NEPLg2 --job 73034680000 --log で再確認しました。LLVM doctests via nodesrc runner は成功扱いですが、tests-llvm.json の summary は total=0, passed=0, failed=0, errored=0 でした。その直後の Full dual backend verification は 21:27:48Z に開始し、21:34:59Z に The operation was canceled. で止まっています。artifact upload は tests-llvm.json だけを 435 bytes で保存しており、tests-dual-full.json は残っていません。job cleanup では node と nepl-cli の orphan process も kill されています。
この結果から、timeout 対策だけでなく「途中結果を残せない」「smoke が0件で成功している」という検証設計の問題も同時に扱う必要があります。0件 smoke は RV-CLI-014 として分離します。
対応結果
llvm-test job は LLVM toolchain 検証と compile-only smoke に限定し、full dual backend verification は llvm-dual-test matrix job へ分離しました。
full dual backend verification は tests shard と stdlib shard に分け、それぞれ独立した JSON artifact (tests-dual-tests.json, tests-dual-stdlib.json) を upload します。
Pages final bundle は llvm-tests と llvm-dual-* artifacts を別々に取り込み、status summary に llvm_dual_test を追加しました。
nodesrc/tests.js は実行開始時に partial JSON を作成し、LLVM case 完了ごとに出力JSONへ progress を flush できるようにしました。
CI では NEPL_TEST_PROGRESS_FLUSH_EVERY=1 を指定し、timeout や kill が起きても最後に完了した LLVM case id と部分結果が artifact に残るようにしました。
追加検証
node --check nodesrc/tests.jsnode nodesrc/tests.js -i tests/compiler/codegen_diagnostics.n.md --no-tree -o tmp/rv-cli-011-tests-progress-smoke.json -j 1(total=3,passed=3,partial=falseの最終 JSON を確認)git diff --check- push CI で
llvm-testとllvm-dual-testが cancelled にならず artifact を残すことは未確認。push 後のCI結果で verified へ進める。
RV-CLI-012: trunk build が clean checkout で web/examples 不在により失敗する
- 解決済: true
- 状態: verified
- 優先度: P2
- 種別: test
- 対象:
web/package.json,web/index.html,nodesrc/sync_web_examples.js
根拠
web/index.html:25:examplesを Trunk のcopy-dir対象にしている。.gitignore:/web/examplesを git 管理外にしている。.github/actions/bootstrap-build/action.yml: CI ではcp examples/*.nepl web/examples/を事前に実行しているが、ローカルのtrunk build経路には同等処理がなかった。
問題
clean checkout のローカル環境では web/examples が存在せず、trunk build が asset pipeline で失敗していました。README と doc/examples.md は trunk build を通常手順として案内しているため、必要な検証をローカルで再現できません。
影響
examples の修正後に要求される trunk build と nodesrc/cli.js / nodesrc/tests.js の確認へ進めません。CI だけが暗黙の事前同期を持つため、手元と CI の build 前提がずれます。
修正方針
nodesrc/sync_web_examples.js を追加し、examples/*.nepl を web/examples へ同期します。web/package.json の build:ts からこの script を呼び出し、Trunk の既存 prebuild hook 経路で Windows / Linux とも同じ準備を行います。
検証
trunk build: 通過node nodesrc/tests.js -i examples --no-tree -o tmp/examples-baseline.json -j 4: build 成果物を読めることを確認。既存のrpn.nepl/bf.neplの move checker エラーは examples 側の別問題として分離。
RV-CLI-013: playground editor CLI fixture が Windows CRLF checkout で失敗する
- 解決済: true
- 状態: verified
- 優先度: P2
- 種別: test
- 対象:
nodesrc/playground_editor_test_runner.js
根拠
- Windows checkout 後に
node nodesrc/cli.js -i tests/playground_editor --playground-editor-tests -o json=tmp/playground-editor-tests-rv-core-017.jsonを実行すると、caseCount=13,passedCount=2,failedCount=11になった。 - 失敗内容は
source.nepl由来の\rが editor state / syntax token / diagnostic span に入ることで、snapshot の cursor index や token index が LF 前提の expected とずれるものだった。 - AGENTS.md の標準確認手順は
trunk build後にnodesrc/cli.jsの JSON を確認することを求めているため、Windows ローカルでこのテストが通らないと修正前検証が不安定になる。
問題
playground editor の実装は入力境界で LF 正規化する前提ですが、CLI fixture runner は source.nepl を fs.readFileSync(..., 'utf8') でそのまま読み込んでいました。Git の checkout 設定で fixture が CRLF になると、editor core へ CRLF が渡り、行末文字数が変わって token span / selection / delete forward の結果が snapshot と一致しません。
影響
GitHub Actions の Linux runner では表面化しにくい一方、Windows 開発環境では nodesrc/cli.js の正式な JSON テストが失敗します。Rust 側や compiler 側の修正検証中に、無関係な playground editor snapshot 差分が混ざり、CI 修正の局所確認を妨げます。
対応
nodesrc/playground_editor_test_runner.js に fixture text reader を追加し、source.nepl 読み込み時に \r
/ \r を LF へ正規化するようにしました。expected JSON や command JSON は従来通り JSON として読み込み、テスト入力のテキスト境界だけを正規化しています。
検証
確認済み:
node nodesrc/cli.js -i tests/playground_editor --playground-editor-tests -o json=tmp/playground-editor-tests-rv-core-017.json(caseCount=13,passedCount=13,failedCount=0)
RV-CLI-014: LLVM smoke test が存在しない fixture path を指して 0件成功扱いになる
- 解決済: true
- 状態: fixed
- 優先度: P0
- 種別: test
- 対象:
.github/workflows/ci.yml,nodesrc/tests.js,tests/compiler/llvm_target.n.md,CLAUDE.md
根拠
.github/workflows/ci.yml:351はnode nodesrc/tests.js -i tests/llvm_target.n.md -o tests-llvm.json --runner llvm --llvm-compile-only --no-tree --no-stdlib -j 2を実行している。- repository 内の実ファイルは
tests/compiler/llvm_target.n.mdであり、tests/llvm_target.n.mdは存在しない。 - GitHub Actions run
24940960078のllvm-testjob ではこの smoke step が成功扱いになったが、artifactllvm-tests/tests-llvm.jsonはtotal=0,passed=0,failed=0,errored=0だった。 CLAUDE.mdの LLVM test 例にも同じ存在しない path が残っており、さらにnodesrc/tests.js必須の-oが欠けていた。
問題
LLVM backend の smoke test が実質的に1件も走っていません。nodesrc/tests.js が存在しない input path または0件収集を成功として扱っているため、CI上は smoke が通ったように見えます。
影響
LLVM backend の最小コンパイル確認が無効化されます。Full dual backend verification が timeout/cancelled になる現状では、LLVM backend の実行可能性を確認する最後の短時間ゲートも機能していません。
修正方針
CI の input path を tests/compiler/llvm_target.n.md に修正します。加えて、nodesrc/tests.js は明示 input に対して 0件収集になった場合は exit code 1 にします。ただし --changed のように差分なしが正常なモードがある場合は、そのモードだけ 0件を許容するように条件を分けます。
対応結果
.github/workflows/ci.yml の LLVM smoke input を tests/compiler/llvm_target.n.md に修正しました。さらに nodesrc/tests.js で、--changed ではない明示 input から runner 対象の doctest を1件も収集できなかった場合に nodesrc/tests/no-runnable-doctests の error result を JSON に書き、exit code 1 で失敗するようにしました。CLAUDE.md のLLVM smoke例も同じ実在pathと -o tmp/tests-llvm-smoke.json 付きのコマンドへ更新しました。
これにより、CI のパス指定ミスや runner filter の不整合で total=0 の artifact が成功扱いになることを防ぎます。
検証
確認済み:
node nodesrc/tests.js -i tests/llvm_target.n.md -o tmp/tests-llvm-missing.json --runner llvm --llvm-compile-only --no-tree --no-stdlib -j 2: 期待通り exit code 1、summary.total=1,errored=1node nodesrc/tests.js -i tests/compiler/llvm_target.n.md -o tmp/tests-llvm-smoke.json --runner llvm --llvm-compile-only --no-tree --no-stdlib -j 2: Windows では LLVM Linux target gate により失敗するが、summary.total=6を収集することを確認node nodesrc/tests.js --changed -o tmp/tests-changed-empty-rv-cli-014.json --no-tree --no-stdlib:--changedの差分なしは従来通りsummary.total=0で成功node --check nodesrc/tests.js
未確認:
- push CI の Linux
LLVM doctests via nodesrc runnerがtotal>0かつ smoke 成功を記録すること。