コンテンツにスキップ

トラブルシューティング

以下の各項目は 1 つの症状に対応しています — 何が起きているのか、何を確認するのか、 実行するコマンド、そして成功したときの見え方、の順に書いてあります。バッチ運用に 関する項目を先に、単発計算に関する項目を後に置きました。ここに書かれていることの ほとんどはリポジトリの checkout と Julia だけで足ります。Python や Git Bash の シェルが必要な手順では、その箇所でそう断っています。

全体を通して使う約束事が 2 つあります。julia +1.11 と julia +1.12 は juliaup の チャネルを選ぶ書き方です。F(s, E₀) データセット (v3/v4/v5) は Julia 1.11.9 に、 dataset-factors v1.0.0 は 1.12.6 にピン留めされているので、いま扱っている系統に 合わせてください。コンソール出力は日本語です。意味を持つ行は、印字されたとおりに 引用します。

症状 参照先
バッチのログが伸びなくなったのに julia.exe はまだ居る Windows で長時間バッチが進まなくなった
バッチは完走した — 出荷してよいか? 完走した — 健全か?
Stop-Process で計算が止まらなかった Windows で Julia プロセスを kill しても止まらない
ソースを編集したら数値が動いた 物理を編集したら結果が変わった
selftest が失敗する / 何分もかかる selftest が失敗する、selftest の初回が遅い
refcheck が大きな数字を出す refcheck が大きな偏差を報告する
1 元素に長い時間がかかる 元素の初回計算が遅い
本番ログに [gate] 行が出る チャネルがゲートを割る
gos の曲線がガタつく、または高 q で合わない gos 出口がガタつく、または高 q で合わない
再生成した factors の JSON がバイト同一でない dataset-factors を再生成したらバイトが違う
ブラウザ GUI がジョブを拒否する GUI が 423 Locked と言う

Windows で長時間バッチが進まなくなった

症状。本番レーンのログファイルが伸びなくなり、julia.exe はプロセス一覧に 残っているのに、その CPU 時間が増えていません。

何が起きているのか。割り当ての多いマルチスレッド負荷が長く続くと、Julia の ガベージコレクタが EXCEPTION_ACCESS_VIOLATION で落ちます。最初に診断したとき (2026-08-04) に見つかった発生箇所は 2 つでした。

Julia 発生箇所 フェーズ
1.12 gc_mark_objarray マーク
1.11 sweep_malloced_memory スイープ

その後のフリート実行では、同じ GC のマーク段階でさらに別の箇所が記録されています (v5 のマニフェストは 1.11.9 上の gc_try_setmark_tag、gc_try_claim_and_push、 gc_mark_objarray を挙げており、check_tables --eb の実行は gc_mark_loop_parallel を踏みました) ので、関数名がいつも同じだとは思わないでください。結末は 2 通り 見られています。プロセスが死ぬ (フリートドライバがすぐ再起動します) か、あるいは — v4 生成での 5 回のクラッシュのうち 2 回と、この項目が扱っている場合がそうですが — 終了せずに wedged になる (プロセスが死なずに止まる状態) かです。後者では、 プロセスは生きたまま、ログを書かなくなり、CPU も消費しなくなります。

証拠が指しているのは Temari ではなく、ランタイムのガベージコレクタです。クラッシュを 診断した時点で、エンジンには unsafe な操作も ccall も生ポインタも無く、スレッド化 されたループは互いに重ならないインデックスにしか書き込まず、マシンのメモリは不足して いませんでした (126 GB 中 78 GB が空き、ページファイルは事実上未使用)。さらに クラッシュは --gcthreads=1 を付けても続きます。このフラグだけで GC は既に最小の 並列構成 (nmarkthreads=1、nsweepthreads=0) になっています。したがって、これは 物理計算のデータ競合ではありません。ただしこれは証拠の読み解きであって、証明ではありません。

現在のツリーにある 2 つの例外

上の説明は、診断した時点のエンジンについてのものです。現在のコードにはそれが 覆っていないものが 2 つあります。どちらもスレッド間で共有されず、v4 と v5 の フリート (2026-08-08) は両方が入った状態で同じように落ちました。1 つは 8 レーン SIMD の球 Bessel カーネル (l0_numerics.jl、2026-08-05) で、各呼び出しに局所的な スクラッチ表に対して、GC.@preserve の内側で生ポインタのロードとストアを使います。 もう 1 つは本番ドライバで、起動時に kernel32 へ数回の ccall (Win32 の優先度 呼び出し SetPriorityClass が 1 回と、そのハンドルとエラーコードの取得) を行って 自分の優先度を BELOW_NORMAL に下げます。

何を確認するのか。プロセス一覧ではなく、ログの更新時刻です。wedged なプロセスは まだ生きているので、「julia.exe は動いているか?」を見ても何も分かりません。 フリートドライバが書くレーンのログはリポジトリから見て ../temari_<outdir>_lane<i>_log.txt (既定の出力ディレクトリなら temari_prod_v5_jl_lane0_log.txt) なので、次のようにします。

Get-Item ..\temari_prod_v5_jl_lane*_log.txt | Select-Object Name, LastWriteTime

他のレーンは現在時刻に近いのに、あるレーンの LastWriteTime だけが 15 分前なら、 そのレーンは wedged です。

何をするのか。フリートを監視 (watchdog) の下で走らせてください。kill と再起動を 代わりにやってくれます。

for i in 0 1 2 3 4 5 6 7; do bash tools/lane_watchdog.sh $i 8 4 & done

引数はレーン番号、レーン数、レーンあたりのスレッド数で、その後ろに任意で juliaup の チャネル (既定 +1.11)、--tags のリスト、出力ディレクトリを続けます。各レーンは julia +1.11 -t 4 --gcthreads=1 src/gen_production.jl --lane i/8 を走らせ、0 以外の 終了コードで終わればそのたびに再起動し (最大 60 回)、走っている間は 2 つの規則を 適用します。

  • ログ更新時刻 (mtime) の 15 分規則。ログが 900 s を超えて書かれていなければ、 そのレーンを kill して (kill -9 なので、その試行は exit=137 で終わります) 再起動します。これが v5 生成での 6 回の wedged (5 レーンにまたがる) をすべて 回復させた最後の砦で、代償は 1 回につきおよそ 16 分と 1 行です。わざと短くして いません。健全な行でも最長のものは 6.7 分かかるので、15 分は 2.2 倍の余裕しか なく、誤った kill のほうが停滞より高くつくからです。
  • 高速 wedged 検知 (2026-08-13、opt-in)。wedged なプロセスは CPU を消費しない ので、15 分待たなくても停滞と遅い行を見分けられます。監視は 60 s ごとにサンプルを 取り、ログが 180 s を超えて停滞し、かつそのレーンの julia.exe の CPU 時間の 伸びが 2 回連続のサンプルで 0.5 s 未満なら、そのレーンを kill します — 停滞から およそ 3 分後です。フェイルセーフになっています。CPU 時間が読めなければ (juliaup のランチャは引数を隠すので、レーンの julia.exe は親 PID の連鎖を たどって探しますが、これは失敗することがあります) 何もせず、15 分規則がそのまま 効きます。既定では off です。本番実行でまだ試されておらず、インタプリタ自体の 評価を混乱させるからです。有効にするには環境変数に WATCHDOG_FAST_WEDGE=1 を 置きます。

どちらの規則が発火しても、再起動は安上がりです。本番ドライバは出力が既に存在する チャネルを飛ばし (skip (exists): …)、チャネルの内側では E₀ の行ごとに F_<tag>_Z<Z>.partial.jsonl へチェックポイントを取るので、kill で失うのは最大でも 1 行で、再起動時には [resume] Z=20 L3: 17/22 行を再利用 (v5 の実行で実際に出た 行です) と印字されます。

古いベンチマークドライバにはもっと単純な守りがあります。tools/bench_e1/run_ab.ps1 は出力が 10 分停滞した pass を kill してやり直し、run_e1.ps1 は構成ごとに全体の タイムアウトを置きます。これらとフリートドライバをまとめると、手動での経験則は 「ログの更新時刻が 10–15 分停滞したら kill し、チェックポイントから再起動する」 です。

さらに役に立つことが 2 つあります。

  • --gcthreads=1 は発生の機会を減らしますが、無くしはしません。QC も含めて、 長時間の実行には必ず付けてください。check_tables --eb は 525 個の SCF を 解きますが、このフラグ無しでは 1.11.9 上で CPU 時間およそ 53 分・18 億回の 割り当てを経たところで落ち、フラグ付きでは完走しました。なお、そこで落ちると 0 バイトのログが残ります — check_tables は要約を最後にしか印字しないので、空のログは まだ走っている実行と区別できません。プロセスの CPU 時間がまだ増えているかどうかを 見てください。
  • スレッド数の少ないプロセスを多く走らせるほうを選んでください。そのほうが どのみち速く (性能 を参照)、1 回のクラッシュの被害範囲も 限られます。

成功したときの見え方。レーンのログでは、wedged とその回復は === watchdog: log stalled >15min, killing pid … === (高速検知が on なら === watchdog: wedged (log stalled …s, CPU frozen at …s), killing pid … ===)、 続いて === lane i/8 attempt 2 start … ===、[resume] 行、そして最終的に === lane i/8 COMPLETE … === と読めます。

完走した — 健全か?

症状。すべてのレーンが COMPLETE を印字し、出力ファイルもすべて存在します。

何が起きているのか。完走したことと健全であることは同じではありません。プロセスを wedged にするのと同じランタイムの問題が、プロセスを止めないままメモリを壊すことが あります。v3 の本番実行では、それ以外は正常に完走したバッチの中で、1 本の E₀ 行 (300 kV の Cd K) が GC クラッシュによって黙って壊れていました。ソルバは正常に 終わったと信じて値を書き出したので、その行は生成ゲートを通過し、QC のパスで初めて 見つかって行チェックポイントから修復されました。同じような行が v4 の実行でさらに 3 本、v5 で 3 本出ています (σ_own/σ_Bote の比が ≈ 1 ではなく 10¹⁰–10²³ で、 badL・mres・rtail は正常に見えました)。v4 の実行のあと、ドライバには健全性 ゲート (is_sane_row: N₀ が有限で正、F が有限、σ_own/σ_Bote が 10⁻³–10³ の範囲) が 入り、そのような行はその場で同じ設定のまま再計算されます — ログには [sane] Z=47 L1 @90.0: N0=… s/B=… が異常 → 同設定で再計算 と出ます。v5 はこれを 備えた最初の本番実行で、そこで 3 回発火しました。しかしこれは生成時のフィルタで あって証明ではなく、教訓は変わりません。 QC を通していない完走は、未検証として扱ってください。

何を確認するのか。生成したディレクトリに対して品質管理 (QC) のパスを走らせます (前述のとおり --gcthreads=1 を付けて)。

julia +1.11 -t auto --gcthreads=1 tools/check_tables.jl src/prod_v5_jl --eb

--eb は C9 の軌道割り当て検査を追加します (チャネルごとに SCF を解くので、ここが 遅い部分です)。行が壊れていたら、その行だけをチェックポイントから修復します。手順は 2 段です。まず壊れた行を落とします — ツールは良品の行を F_<tag>_Z<Z>.partial.jsonl へ書き戻し、完成していた JSON を .broken に改名します。

julia +1.11 tools/repair_rows.jl src/prod_v5_jl L1 47 --auto

次に、本番ドライバを元の生成と同じフラグで再実行します (処方が違うと黙って 混ざります。JSON の model_id と settings を確認してください)。ツールは最後の 数行に、実行すべきコマンドをそのまま julia +1.11 -t 4 --gcthreads=1 src/gen_production.jl --tags L1 --lane k/n --out src/prod_v5_jl の形で印字します。再計算されるのは捨てた行だけで、良品の行はチェックポイントから ビット同一に読み戻されます。そのあと check_tables.jl をもう一度走らせてください。

成功したときの見え方。最終行が 検査 525 本: 525 OK / 0 NG で、終了コードが 0 です。[NG] 行が出れば、検査名 (C1–C16。C4 と C5 は廃止済み) とファイルが 示されます。各検査が何をゲートしているかは 検証 ページにあります。

関連する、ずっと小さな効果 — フリート実行どうしで時々出る 1–2 ULP の差 — も詳しく 調べられ、同じ系統のランタイムの一過性の障害にたどり着いています。物理的な許容より 6 桁小さく、監視以外の対処は要りません。再現性の規律 を 参照してください。

Windows で Julia プロセスを kill しても止まらない

症状。起動したときの PID を止めたのに、計算が続いています。

何が起きているのか。Start-Process julia (および juliaup のもとで PATH 上に ある julia) が起動するのは juliaup の shim で、それが本物の julia.exe を 子プロセスとして起動します。記録した PID は shim のもので、それを kill しても子は 走り続けます。juliaup のランチャは子のコマンドラインに引数を載せさえしないので、 --lane を grep しても正しい julia.exe は見つかりません。

何をするのか。

  • GUI やその他の待ち受けプロセスなら、待ち受けているポートを持つ PID を kill します。 Get-NetTCPConnection -LocalPort <port> がそれを OwningProcess として表示します。
  • バッチなら、親子の連鎖 (shim → その ParentProcessId を持つ子の julia.exe) を たどります。lane_watchdog.sh がやっているのはこれです。あるいは、自分の他のものが 何も走っていなければ、Stop-Process -Name julia で全部落とせます。
  • 対話的なコンソールなら、Ctrl+C は本物のプロセスに届きます。

張り込み (stakeout) とベンチマークのドライバ (tools/e8_stakeout.ps1、 tools/bench_e1/*.ps1) には PowerShell 7+ (pwsh) が必要です。Windows PowerShell 5.1 では足りません。

物理を編集したら結果が変わった

症状。ソースを編集したあとの初回実行で数値が変わり、また遅くなりました。

何が起きているのか。数値基盤や原子 SCF のソース (l0_numerics.jl、 l1_atomic.jl) を変えたあとの初回実行では、これが期待どおりの振る舞いです。SCF キャッシュのファイル名にはまさにこれらのファイルのソース指紋が入っているので、 Temari は古いキャッシュを読まずに新しいキャッシュを作ります — 遅いのは SCF を 解き直しているからで、新しい数値は新しい物理です。キャッシュの中身にはチェックサムが 付いていて、壊れたファイルは自動で作り直されます (WARN: キャッシュ … を読めないので作り直します という行が出ます)。

何を確認するのか。その変更がビット同一のつもりだったのなら、目で見て判断しないで ください。変更の前後で tools/bitident_snapshot.jl を走らせ、2 つのファイルを diff します — 手順は 再現性の規律 ページにあります。

後片付け。古い世代のキャッシュは残されます。新しい結果を確認したあとでディスク 容量を回収するには、キャッシュディレクトリの中のキャッシュファイルだけを削除します。

Remove-Item atom_cache\atom_cache_*.jls

Python 実装は独自の atom_cache_*.pkl を持っていて、この完全性の仕組みは共有して いません。

キャッシュのファイル名に Julia のバージョンが入っているのは、Julia の直列化形式が バージョン間で互換でないからです — 1.12 が書いたキャッシュは 1.11 では読まれず、 各バージョンが自分のファイルを持つだけです。

kill のあとに atom_cache/atom_cache_*.jls.tmp* というファイルが残っていても無害です (キャッシュは一時的な名前に書いてから原子的に改名するので、書き込み途中の kill は 一時ファイルを残します)。削除してください。

selftest が失敗する

症状。julia -t auto src/ionization.jl selftest が ALL PASS ではなく assertion で止まります。

まず確認すること。Julia のバージョンです。リリースゲートは F(s, E₀) データセットが 1.11.9、dataset-factors が 1.12.6 で、CI は Ubuntu と Windows で 1.11.9 と 1.12 を走らせているので、これらは通ります。より新しいバージョンは libm の振る舞いが 変わることがあります。julia +1.11 -t auto src/ionization.jl selftest で、juliaup の もとでピン留めされたインタプリタを選べます。

テストの梯子は T0–T24 と T26–T27 で、文字付きのサブテストがあります (T25 は欠番 です)。失敗はそれぞれ自分のテスト名を名乗ります。例: T13 FAIL: …。

何をするのか。報告してください。出力全文、Julia のバージョン、OS と CPU、 スレッド数を含めてください — バグ報告テンプレート を参照してください。

成功したときの見え方。実行が 2 本の罫線に挟まれた ALL PASS (… s) で終わり、 終了コードが 0 です。

selftest の初回が遅い

症状。selftest が初回は数分かかり、その後はおよそ 1 分です。

何が起きているのか。コストが 2 つあり、そのうち 1 つは 1 回限りです。どの Julia プロセスも起動時にエンジンをコンパイルします (Temari はパッケージではなく src/ionization.jl から include されるスクリプトの集まりなので、事前コンパイル されたものはありません) — これは毎回の実行に付く固定費です。それに加えて、 atom_cache/ が冷えた状態での初回実行はテストが必要とする SCF を解いてキャッシュし、 以後の実行はキャッシュを読みます。温まった状態なら梯子全体が速いデスクトップで およそ 1 分、冷えた状態では最大 3 分程度を見込んでください。-t auto は重要です — 無いと ε ノードが逐次で走ります。

何を確認するのか。何もありません。ただし温まったキャッシュでも遅いままなら、 どの計算でも最初の数行に印字されるスレッド数 (スレッド: N) と、前回と同じ作業 ディレクトリから始めたかどうかを見てください (キャッシュは作業ディレクトリの下に あるので、ディレクトリが変わればキャッシュは冷えています)。

refcheck が大きな偏差を報告する

症状。julia -t auto src/ionization.jl refcheck が、10⁻⁷ をはるかに超える WORST vs Python の値を印字します。

何が起きているのか。refcheck は src/reference_values.json のケースを計算し 直し、独立な Python 実装が出した値と比べます。両方とも v2 ベースラインの処方 (非相対論の連続状態、非相対論の Xα SCF、--quick 求積) です — 比較しているのは 同じ処方の 2 つの実装であって、v2 と出荷中の v4 ではありません。WORST vs Python は普段 ~9×10⁻⁸ で、これは観測されている実装間の差です。もっとも可能性が高いのは、 独立に収束させた 2 つの SCF 解の残差です。10⁻⁵ を超えるものは 2 つの実装が本当に 食い違っていることを意味するので、issue にする価値があります。

何を確認するのか。Julia のバージョンとキャッシュです。古い、あるいは他所の キャッシュが拾われることはありません (指紋とチェックサムがそれを防ぎます) ので、 本物の偏差はコードの変更です。

なお refcheck は常に 0 で終了します。ゲートではなく報告です。ゲートにするには 次のようにします。

julia -e 'include("src/ionization.jl"); exit(refcheck() < 1e-5 ? 0 : 1)'

成功したときの見え方。 WORST vs Python = 9.044e-08 (OK: 実装差 (特殊関数・スプライン) の範囲) — 9.044×10⁻⁸ は、現在のコードについて Julia 1.11.9 で記録された値です。

元素の初回計算が遅い

症状。julia -t auto src/ionization.jl 79 L3 300 が 初回はこの元素の SCF を解くため時間がかかります (atom_cache/*.jls に保存)... を印字したあと、長いあいだ止まって見えます。

何が起きているのか。中性原子と、そのチャネルの緩和 core-hole イオン (内殻空孔を 開けて再収束したイオン) について、自己無撞着場を解いています。結果は 作業ディレクトリの atom_cache/ にキャッシュされ (毎回リポジトリのルートから 始めてください。さもないとディレクトリごとに別のキャッシュが育ちます)、同じ元素・ 同じ処方の以後の実行はずっと速くなります。

成功したときの見え方。同じコマンドの 2 回目は待ちを飛ばして、まっすぐ 完了 (… s) へ進みます。

チャネルがゲートを割る

症状。本番ログに [gate] Z=… … @… badL=… mres=… rtail=… -> ppw=35 のような 行が出ます。あるいは、単一チャネルの実行で、診断行の値がゲートの外にあります。

何が起きているのか。F(s) 計算の最後の診断行は 3 つの数値を報告します (gos 出口はそれ自身の、より短い行を印字します)。match_resid (連続状態の波動関数の 漸近 Coulomb マッチの残差、ゲート 10⁻⁴)、r_tail (動径テールの打ち切り、ゲート 10⁻⁴)、badL (失敗した部分波の数、0 でなければなりません) です。

診断: match_resid=… (ゲート<1e-4) / r_tail=… (<1e-4) / badL=… (=0)

本番ドライバは、ゲートを割ったチャネルをより細かいメッシュ (ppw = 35、波長あたりの 点数) で 1 回だけやり直し、それでも割れば、そのチャネルファイルの failures リストに 記録して次の E₀ 行へ進みます。failures が空でないチャネルを出荷してはいけません — リリース QC (check_tables.jl) はそれを拒否します。ドライバ自身は記録するだけです。

何を確認するのか。再試行で消えたかどうかです。[gate] 行のあとに failures への 記入が無ければ合格です。failures が空でなければ、その行には手当て (さらに細かい メッシュか、その E₀ でマッチが失敗した理由の理解) が必要で、出荷はできません。

成功したときの見え方。チャネルの終わりに wrote src/prod_v5_jl/F_K_Z26.json (n rows, 0 failures, … min) と出ます。

gos 出口がガタつく、または高 q で合わない

症状。gos の出力 q 格子が粗く見えます。外部の一般化振動子強度 (GOS) の表と 比べると、主に Bethe 尾根の先で合いません。

何が起きているのか。gos 出口は GOS を、固定数の出力 q ノード --nqout (既定 48) の上で報告します。これは出力格子です。--high は求積のつまみを上げますが、 この格子は動かさないので、出力 q 格子のサンプリング誤差は --high には見えません。 Fe L1 で測ったところ、ノードを 48 から 192 にすると高 q 帯 (ρ > 1.5。ここで ρ = q / q_ridge(ΔE) で、q_ridge は Bethe 尾根の運動量 — 主要次数では原子単位で √(2ΔE) — なので、尾根は ρ = 1 に来ます) がおよそ 10 % 変わり、尾根帯そのものも ≤ 2.2 % 変わりました。出荷している F(s, E₀) テーブルはこの格子を通りません — gos 出口ではなく compute_channel から来ます — ので、影響を受けるのは gos の 出力だけです。

何をするのか。高 q で gos を使うときはノード数を上げてください。

julia -t auto src/ionization.jl gos 26 L1 --nqout 192 --json fe_l1_gos.json

成功したときの見え方。完了行が指定した格子を報告し — 完了 (… s) ΔE ノード n 点 × Q 192 点 ε 上端 = … eV — --nqout をさらに上げても 高 q の値が動かなくなります。

dataset-factors を再生成したらバイトが違う

症状。同じ commit から julia +1.12 -t 1 src/gen_factors.jl 26 --out DIR を 実行してできた SF_Z026.json が、出荷された SF_Z026.json とバイト同一では ありません。ここでいう「出荷された」とは、展開したリリースアーカイブのことです。 テーブルはリポジトリには入っていません (prod*/ は .gitignore で除外されています)。 temari-factors-v1.0.0.tar.gz として配布され、その最上位ディレクトリ temari-factors-v1.0.0/ に 86 本の SF_Z???.json、MANIFEST.md、manifest.json が 入っています。(このディレクトリは作者の手元では src/prod_factors_v1/ です。以下で 出荷テーブルへのパスが出てくるところは、展開したディレクトリに読み替えてください。)

何が起きているのか。SCF はプロセス間で散発的に別の反復で止まることが観測 されています — 同じ commit、同じ Julia、同じ手順でもです。dataset-factors を dt/16 格子で生成したとき、これは認証実行と出荷実行の間で 86 元素中 34 元素、2 回の本番 実行の間で 85 元素中 6 元素に起きました。同じ元素を 1 つのプロセス内で 2 回解いた ときは、密度ハッシュまで一致しました。差は SCF の停止許容の内側にあり (max |Δf_x| ≤ 2×10⁻⁹、すなわち SCF の許容 B_scf = 9.09×10⁻⁹ の 0.22 倍)、リリースの 許容よりはるかに下です。したがって再生成のバイト同一は観測であって保証ではなく、 正本はリリースされたアーカイブのバイトとその SHA-256 です (データ)。

何を確認するのか。まずありきたりな原因 — ソース指紋が違う (commit が違う、 またはツリーが dirty) — を除外します。再生成チェッカが両方の比較を代わりにやってくれます。 これは Git Bash のスクリプトで (一時ディレクトリに cygpath を使います)、JSON を 読むのに python を呼ぶので、両方が PATH に必要です。展開したアーカイブは PROD で指します (既定の src/prod_factors_v1 は作者の手元のディレクトリです)。

PROD=path/to/temari-factors-v1.0.0 bash tools/factors_regen_check.sh 1 26

指定した元素 (既定は H と Fe) を再生成してバイトを比べ、違っていれば generator_source_sha256 が違うのか (「同じ commit の checkout で再実行すること」) 同じなのか (「ソルバの非決定論」) を教え、max|Δf_x| と max|Δf_e_A| を印字します。指紋が同じで、差がマニフェストに記録された程度 (max |Δf_x| ≤ 2×10⁻⁹) なら、散発的な停止反復です。数値誤差の許容 B_num = 9.09×10⁻⁸ 電子に近づくものはそうでは なく、issue にする価値があります。

そのうえで、再生成したテーブルはバイトではなくリリース QC で判断します。

julia +1.12 tools/check_factor_tables.jl DIR --allow-dev --golden schema/factors_golden_v1.json
python tools/temari_factors_contract.py DIR --allow-dev

(--allow-dev を付けるのは、部分集合は 86 元素のリリースではないからです。) F8 — tight (τ/10) な SCF 参照との比較 — はリポジトリの外にある認証副本を必要とするので、 アーカイブだけからは再実行できません。出荷時の結果はアーカイブの MANIFEST.md に 記録されています。

ダウンロードしたものが出荷テーブルそのものであることを確かめるには、次のように します。

sha256sum -c temari-factors-v1.0.0.tar.gz.sha256      # next to the downloaded archive; b1ab3430…
julia +1.12 tools/make_factors_manifest.jl path/to/temari-factors-v1.0.0 --verify

成功したときの見え方。check_factor_tables: ALL PASS (n ファイル)、 契約テスト ALL PASS (0 件 NG)、sha256sum からの temari-factors-v1.0.0.tar.gz: OK、manifest 照合 OK (86 元素, digest …)、そして factors_regen_check.sh が X14 再現性: ALL PASS で終わることです。代わりに指紋が 同じで 10⁻⁹ 程度の差が報告された場合、スクリプトはそれでも NG と数えます (X14 再現性: 1 件 NG、終了コード 1) — X14 が検査するのはバイト同一だからです。 その場合の判断は、印字された max|Δf_x| と上のリリース QC に拠り、X14 には 拠りません。

GUI が 423 Locked と言う

症状。ブラウザのページから計算を始めると 423 Locked (「別の計算が実行中です」) が返ってきます。

何が起きているのか。src/gui.jl のバージョン 0.1 は一度に 1 つのジョブしか 走らせません — エンジンを別プロセスとして起動し、走っている間の 2 つ目の /compute はキューに入れずに拒否します。

何をするのか。いまのジョブを待つか、/abort を使ってください。後者は エンジンのプロセスを kill し、その一時ファイルを片付けます。

ページを再読み込みするとジョブ id が失われます — ジョブは最後まで走りますが、 ブラウザから追えなくなるだけです。走っているものが終わったら、もう一度始めてください。