Releases: Sora-bluesky/ja-output-harness
Release list
v0.5.1 — raw-model A/B workflow
Highlights
Run a real raw model vs harness-on A/B comparison. In v0.5.0, ja-output-toggle off only stopped the Stop hook — ~/.codex/AGENTS.md still shipped the quality-gate block, so the "baseline" was contaminated. This release closes that loop.
Added
ja-output-toggle off --full/on --full: evicts / restores theAGENTS.mdmanaged block toAGENTS.md.bak-toggle. Handles the stale-backup case (installer re-ran and re-inserted the block) without overwriting the original backup.statusnow also surfaces the block presence and.bak-togglestate.ja-output-stats scan-sessions: walks$CODEX_HOME/sessions/YYYY/MM/DD/rollout-*.jsonl, extractsrole=assistantJapanese turns, lints viarules.py, and prints ok-rate + Wilson 95% CI. Flags:--since/--until(date-only--untilis end-of-day so--since D --until Dcovers the whole UTC day; untimestamped rows are dropped when a filter is active),--include-archived,--config,--output-jsonl.ja-output-stats ab-report --source-path PATH: read an ad-hoc jsonl instead of the live lite / metrics stream. Wiresscan-sessions --output-jsonlstraight into the A/B comparison.
Comparison flow
ja-output-toggle off --full # raw model, restart Codex
# ...use Codex...
ja-output-stats scan-sessions \
--since 2026-04-24T19:00 --until 2026-04-24T19:30 \
--output-jsonl raw.jsonl
ja-output-toggle on --full # harness back, restart Codex
# ...use Codex same length...
ja-output-stats ab-report \
--baseline 2026-04-24:2026-04-24 \
--test 2026-04-24:2026-04-24 \
--source-path raw.jsonlReview
6 rounds of codex review --uncommitted (see PR #83). Final verdict: no actionable correctness issues.
Fixed
off --fullnow removes a re-inserted managed block even when.bak-togglealready exists (was previously a no-op).
Tests
- 245 passing (30 new cases across
test_toggle.py,test_stats_scan_sessions.py,test_stats_ab_report.py)
Full changelog: v0.5.0...v0.5.1
v0.5.0 — toggle CLI + Codex v0.124 GA alignment
Highlights
Flip the harness on/off without uninstalling so you can A/B compare runs with and without the harness — useful now that GPT-5.5-era Codex output is visibly more readable on its own.
Added
ja-output-toggleCLI:on/off/status/setsubcommands that flip~/.codex/state/jp-harness-modeand back up the previous mode to.bakoffvalue forjp-harness-mode: both Stop and SessionStart hooks return 0 at the top, so Codex output passes through untouched- Codex-App-friendly toggle prompts in
README.mdanddocs/INSTALL.md— paste the prompt into the chat box and Codex performs the same file edit the CLI does
A/B comparison flow
ja-output-toggle off # use Codex for a while
ja-output-toggle on # use it for the same length
ja-output-stats ab-report \
--baseline <off-range> \
--test <on-range> # Wilson 95% lower bound ship decisionChanged
- Documentation realigned around the current
strict-litedefault (wasstrict-centric before) —docs/ARCHITECTURE.md,docs/HOOKS.md,docs/INSTALL.md,docs/OPERATIONS.md,AGENTS.md - Reflects Codex
v0.124.0markingcodex_hooksstable (PR #19012). The[features] codex_hooks = trueline the installer writes is now a harmless no-op on0.124+, and still required on0.120–0.123 README.mdreplaces the stale+15%overhead number with the measured range+0–+60%from the actualjp-harness-lite.jsonlcorpusdocs/DEPRECATION.mdnow reflects that uninstall is automated sincev0.3.4
Tests
- 224 tests passing, including 12 new cases in
tests/test_toggle.py
Full changelog: v0.4.2...v0.5.0
v0.4.2 - lite jsonl race fix
v0.4.2 — lite jsonl race fix
jp-harness-lite.jsonl への append を Stop hook(Add-Content / 直接 open('a'))から外し、metrics.record_lite 経由で _rotate_lock 保護下に集約しました。Windows で O_APPEND が atomic でない問題に対する予防策です。
Fixed
- Stop hook の lite jsonl append が Windows で非アトミックになり得る race を、
metrics.record_liteへの集約で解消 ja-output-stats --source liteが rotated archive (.1.jsonl) を読まなかったのを修正(--source metricsと挙動を統一)- hook の
rules_cli引数を--session=<value>/--mode=<value>形式に変更(-始まりの session id 誤認防止)
Added
metrics.record_lite()—_rotate_lock+_maybe_rotateを再利用する lite jsonl 専用書き込み関数。lock 取得失敗時は drop(record()の best-effort と意図的に divergence、予防が目的のため)rules_cli --append-lite STATE_FILE --session ID --mode MODE— hook が一度の呼び出しで lint と append を済ませるための optional フラグ群
Tests
- 並行
record_liteレーステスト(N=32) rules_cli --append-lite統合テスト(stdout JSON + on-disk entry の両方検証)ja-output-stats --source litearchive + active 読み込みテスト- 計 7 件追加 → pytest 212 passed / ruff clean
Review
gpt-5.4 による code review 2 ラウンド:
- 1 ラウンド目: BLOCKER 0、MEDIUM × 2 + MINOR × 1 → 全件対応(archive read / lock-failure drop / equals-form args)
- 2 ラウンド目: No correctness findings、docstring 文言の nit 1 件のみ修正
互換性
- スキーマ変更なし(
schema_version="1"for lite)。既存 jsonl エントリはそのまま valid。 record()(strict メトリクス)は best-effort 設計を意図的に維持(既存挙動互換)。_run_strict(v0.3.x missing-finalize 経路)は変更なし。
Full diff: v0.4.1...v0.4.2
v0.4.1 — default to strict-lite, simplify user docs
[0.4.1] - 2026-04-22
v0.4.0 の実測 dogfood(n=21、ok 率 23.8%、Wilson 95% CI [10.6%, 45.1%])を受け、default を lite から strict-lite に変更。README をエンドユーザー向けに簡素化し、開発者向け内容は DEVELOPERS.md へ分離。
Changed
- install 自動判定の既定を
strict-liteに変更(ERROR 時に Codex が continuation で自己修正、追加 output token は基本 0) - README をエンドユーザー向けに全面刷新
DEVELOPERS.mdを新設し、モード比較・アーキテクチャ・dogfood 手順を集約- 過去リリースの CHANGELOG エントリを簡素化
v0.4.0 — zero-overhead lite mode (CLI) + strict fallback (App)
[0.4.0] - 2026-04-21
v0.3.x の MCP finalize gate は 95%+ のリアルタイム compliance を取れる代わりに output-factor 3.00× / excess +200% output tokens を払う構造で、「トークン節約したい」層の採用を妨げていた。v0.4.0 は デフォルトを "lite" モードに切り替え、MCP gate を opt-in の "strict" モードへ降格する。これで excess overhead は new install で 0.00× が基準になる。
Added
- 3 つのインストールモード
install.{ps1,sh} --mode={lite|strict-lite|strict}:lite(新規 install の default): MCP server を登録しない。Stop hook が assistant message をja_output_harness.rules_cliで検品しjp-harness-lite.jsonlに記録。output-factor ≈ 1.00×(excess ~0.00×)。compliance は仮説 60-75%(post-hoc 再教育で翌セッション補正)。strict-lite: 同じ lite lint + ERROR 検出時に{"decision":"block","reason":"..."}を emit して Codex continuation で self-correct。output-factor ≈ 1.15×(excess ~0.15×)、compliance 95%+。strict: v0.3.x 相当の MCP finalize gate。output-factor 2.0〜3.0×。
ja_output_harness.rules_cli: assistant message を受け取り JSON で violations を返すローカル CLI。lite / strict-lite Stop hook から呼ばれる。出力は model loop の外で走るため output tokens 0。config/agents_rule_lite.md: lite / strict-lite モード用の短い AGENTS.md ルールブロック(top-5 ERROR + 発火トリガー)。~/.codex/state/jp-harness-mode: Stop hook が runtime に読み取る mode marker。install で書き込み、uninstall で削除。ja-output-stats ab-report: 2 つの日付レンジ間で ok rate を比較し Wilson 95% CI・delta (pp)・CI 重なり判定・dogfood 判定を出力するサブコマンド。--source lite|metricsでjp-harness-lite.jsonl(default)または strict mode の metrics jsonl を選択。v0.4.0 dogfood 後の mode 切替判断と、将来の compliance 改善 A/B に利用する(従来は.references/dogfood-measure.pyの scratch を毎回走らせていた)。判定は Wilson 下限 で閾値比較し、n < 20では無条件に inconclusive、baseline/test レンジが overlap している場合は--allow-overlap無しなら拒否、session="diag"は default で除外(gpt-5.4 review v0.4.0 MAJOR #4/#5 + MEDIUM #7)。jp-harness-cursor.json: SessionStart hook の消費カーソル。strict / lite 両 jsonl の byte offset を保持し、os.replace/File.Moveの atomic rename で永続化する。これで Stop hook の concurrent append が上書き消失することも、tail 外の未消費レコードが rewrite で silent 削除されることも無くなる(gpt-5.4 review v0.4.0 MAJOR #2/#3)。
Changed
- SessionStart hook が lite 違反を再教育する:
hooks/session-start-reeducate.{ps1,sh}がデフォルト lite モードで書かれるjp-harness-lite.jsonlを読むようになった。ok == falseエントリを集計し、上位 3 ルールの違反回数を含むプロンプトを emit する。strict の missing-finalize エントリと合わせて 1 つのメッセージに統合(400 chars cap)。v0.4.0 以前は strict 専用で、default lite 環境では再教育が 一度も走らなかった(gpt-5.4 review v0.4.0 BLOCKER #1)。 - uninstall が cursor file を掃除:
scripts/uninstall.{ps1,sh}がjp-harness-cursor.jsonを削除するようになった。再インストール時に stale offset を引き継がない。 - AGENTS.md 管理ブロックに BEGIN/END マーカー導入:
<!-- BEGIN ja-output-harness managed block -->/<!-- END ja-output-harness managed block -->で囲む。mode 切替時の再インストールが旧ブロック(strict/lite 両方)を自動置換するようになり、「strict→lite で MCP ルールが残って Codex が無い tool を呼ぶ」事故を防ぐ(gpt-5.4 review BLOCKER #1)。 Violation.to_dictの payload slim:fixとcategoryフィールドを削除、snippetを 50 chars に cap。違反 1 件あたり約 170 bytes(-76%)削減。- Stop hook timeout 5s → 15s + inner subprocess timeout 10s: Windows cold Python start への余裕(gpt-5.4 review MEDIUM #5)。
- lite / strict-lite で hooks.json mismatch は hard fail: 従来の warning は enforcement 無しの無言状態を招いていた。
--force-hooksで上書きを明示要求する(gpt-5.4 review MEDIUM #4)。
Fixed
- Codex 0.122 の hooks feature gate に対応:
install.{ps1,sh}がcodex features enable codex_hooksを呼ぶよう変更。Codex 0.122 でcodex_hooksfeature がStage::UnderDevelopmentに降格(codex-rs/features/src/lib.rs)、[features] codex_hooks = trueを config.toml に直書きしても effective state = false のまま hook engine が初期化されない。また書き込み位置も[features]section 内が暗黙的な前提だったのが、単行 append で任意の TOML table 内に紛れる risk を生んでいた。Codex CLI が 0.120.x 以下で未対応の場合は従来の[features]header 付き append にフォールバックし既存ユーザーの互換性を保つ。これが効かないと hooks.json の Stop/SessionStart が永久に発火しない致命的な退行で、v0.3.x 世代ではこの gate が存在しなかったため install 手順がそのまま壊れていた。 - strict-lite の
stop_hook_activeガード: continuation 中の二次 block を抑止し、1 turn で修正できない違反が無限ループに陥らない(gpt-5.4 review BLOCKER #2、codex-rs/hooks/schema/generated/stop.command.input.schema.json準拠)。
Known Issues
- Codex App では
lite/strict-liteモードが動作しない: Codex 0.122 の app-server は experimental feature の runtime 有効化をSUPPORTED_EXPERIMENTAL_FEATURE_ENABLEMENTの 5 個 allowlist(apps / plugins / tool_search / tool_suggest / tool_call_mcp_elicitation)に限定しており、codex_hooksが含まれていない。[features].codex_hooks = trueを config.toml に書いても App では hook engine が初期化されず、Stop / SessionStart hook が永久に発火しない(CLI では正常動作)。App 単独環境では install スクリプトが自動でstrictを選択する。upstream で allowlist が拡大されれば App も lite 対応になる。v0.4.0 の lite mode は事実上 Codex CLI 専用と位置づける。 - 並行 Stop hook で
jp-harness-lite.jsonlへの append が稀にレースする可能性(gpt-5.4 review MEDIUM #3)。POSIX の O_APPEND は小さい書き込みで atomic だが、Windows での厳密な保証は無い。v0.4.1 でmetrics.pyの_rotate_lockパターンを共有化する予定。
Notes
- 反映手順:
uv sync --reinstall-package ja-output-harness→scripts/install.{ps1,sh} --mode lite -AppendAgentsRule→ Codex 再起動(0.122+ は再起動必須。config.toml 書き換えも feature flag も起動時読み込みなので、既存プロセスには反映されない)。 - strict ユーザーが lite に移行する場合:
--mode lite -AppendAgentsRule -ForceHooksを指定すれば AGENTS.md の旧ルールと MCP server 登録が自動で片付く。 - 0.122 互換性確認: install 後に
codex features list | grep codex_hooksでtrueが返ることを確認してから Codex を起動すると確実。falseのままならcodex features enable codex_hooksを手動実行。 - pytest 205 passed(+32)、ruff clean、CI matrix 4/4 + scan + sanitize 通過予定。
v0.3.8: fast-path diagnostics
v0.3.8 — fast-path diagnostics
v0.3.7 のドッグフーディングで fast-path 発火率 0% が観測されたが、メトリクス jsonl に rule 別の情報が無かったため原因切り分け不能だった。schema v2 として rule_counts を追加し、ja-output-stats show に fast-path miss 診断機能を追加する。
Added
- metrics schema v2: 各エントリに
rule_counts(rule 名 → 件数)を追加。v1 エントリは読み取り時に{}として扱うので後方互換 ja-output-stats showの 2 セクション追加:- rule distribution(全エントリのルール別集計)
- fast-path miss diagnosis(ERROR ありで fast-path 未発火のサブセット)。
banned_term支配なら_fast_path_applicableが replacement 不足で落ちている、bare_identifier/pr_issue_number支配なら rewrite が residual ERROR を残している、と切り分けできる
Findings
本 PR の post-merge dogfooding(schema v2 サブサンプル n=14)で fast-path hits 57% を確認。期待域 40〜60% の中央に回帰。v0.3.7 の 0% 測定は完全なサンプルノイズだった。
Docs
docs/ARCHITECTURE.mdのトレードオフ節を実測値 n=62 / output-factor 3.00× / fast-path 12.9% に更新。v0.2.22 の 3.58× から 16% 改善
Notes
- schema_version:
"1"→"2" - pytest 173 件 全通過(+2)、ruff clean、CI 6/6 pass
- 反映手順:
uv sync→ Codex 再起動
Full Changelog: v0.3.7...v0.3.8
v0.3.7 — uninstall hardening + hook scope + docs follow-up
Follow-up review sweep (gpt-5.4 v0.3.6 フォローアップの 6 件)
Fixed (MAJOR)
- uninstall が
codex_hooks = trueを無条件削除: hooks.json が prune 後に空 / 非存在になった場合のみ削除。共存する他の MCP プラグインの hook を巻き込まない - hook 所有判定が部分一致のみ:
$REPO_ROOTから導出した hook script の絶対パスで照合、fallback は従来の repo marker
Fixed (MINOR)
- Stop hook regex を
mcp__jp_lint__finalize完全修飾名のみに限定(別 MCP server の"name":"finalize"誤マッチを防止) - README /
docs/HOOKS.mdの uninstall 記述を v0.3.4+ の 3 段階動作に合わせて書き直し test_version_syncにimportlib.metadata.version比較を追加(wheel METADATA の drift を CI で検知)
Fixed (NIT)
cmd_discoverの decode fallback コメントを実装(UTF-8 replacement)と合わせて修正
Notes
- pytest 171 件 全通過、ruff clean、6/6 CI pass
- これで gpt-5.4 の両ラウンドで挙げられた全 21 項目(初回 15 + フォローアップ 6)を消化完了
v0.3.6 — NIT sweep: summary wording, dead code, allowlist dedup
NIT sweep (gpt-5.4 review #56, #57, #58)
Fixed
_summarize([])の空括弧 (#56):0件の違反を検出 ()→0件の違反を検出stats._format_row()未使用関数削除 (#57)discover.DEFAULT_ALLOWLISTのssh重複解消 (#58)
Notes
- pytest 170 件 全通過、ruff clean、6/6 CI pass
- これで gpt-5.4 review の全 15 項目 (BLOCKER 1 + MAJOR 7 + MINOR 5 + NIT 3) を v0.3.1〜v0.3.6 で消化完了
v0.3.5 — MINOR sweep: metrics lock, rules cache, env migration, hook match, multi-word mask
MINOR sweep (gpt-5.4 review #51, #52, #53, #54, #55)
Added
- rules cache (#55):
server._load_rules_cachedが(path, mtime_ns)キーで yaml 再読込を省略。finalize ホットパスの I/O を削減 JA_OUTPUT_HARNESS_USER_CONFIG環境変数 (#52): 新名称を優先、旧CODEX_JP_HARNESS_USER_CONFIGは後方互換で一時保留。相対パスは.resolve()で絶対化
Fixed
- metrics rotation の排他 (#51):
record全体をO_CREAT|O_EXCLlock で保護(1 秒 best-effort、取得失敗時は fallback) - discover が multi-word term を tokenize で割る (#53): phrase を事前マスクしてから走査
- Stop hook の
"finalize"粗い部分文字列判定 (#54):mcp__jp_lint__finalizeまたは"name":"finalize"の完全一致に変更
Notes
- pytest 170 件 全通過、ruff clean、6/6 CI pass
v0.3.4 — shell interpreter + discover encoding + uninstall cleanup
Fix MAJOR #46 + #47 + #50 — discover encoding / install interpreter / uninstall cleanup
Fixed
- #46
discover --file固定 UTF-8: UTF-8 → cp932 → latin-1 replacement の decode fallback を追加 - #47
install.sh --enable-hooksが python3 固定:resolve_python3でインタプリタ探索を hook scripts と統一 - #50 uninstall が約束を果たしていない:
codex_hooks = trueとhooks.jsonの jp-harness 関連エントリも自動削除。AGENTS.md は意図的に手動据え置き(他ルール混在の可能性)
Added
tests/test_tune.TestDiscoverFileEncoding+3 件
Notes
- pytest 162 件 全通過、ruff clean、6/6 CI pass