Skip to content

テストの前提: 監視の上限を環境変数で延ばしたシェルでは既定値を前提にするテストが落ち、収束ループの初期化が中断する → テストの実行中は監視の環境変数を共通の前提で外す(#678) - #797

Merged
takemi-ohama merged 4 commits into
developfrom
fix/issue-678-monitor-env-isolation
Sep 22, 2026

Conversation

@takemi-ohama

@takemi-ohama takemi-ohama commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

Summary

無進捗の許容と打ち切りの上限は、接頭辞 MONITOR_ を持つ環境変数で延ばせる。運用でこれを
延ばしたシェルから全体のテストを起動すると、表の既定値を前提にするテストが既定値ではなく
その値を読み、変更の中身と関係なく落ちていた。収束ループ(cross-refactoring)の初期化は
着手前のテストの通過を条件にするため、上限を延ばしたシェルでは初期化がそこで止まる。

テストの実行中だけ、接頭辞を持つ環境変数を外す。 置き場所はリポジトリ直下の共通の前提
conftest.py)とし、git の全体設定・実行の要約の置き場所と同じ形で扱う。収集より前に
外す
pytest_configure)。テストの本体を読み込む時点で上限を決めてしまう実装があり、
セッションの前提では間に合わない。実行が終わった時点で元の値へ戻す(pytest_unconfigure)。

テストごとに散っていた同じ除去を、この共通の前提へ寄せた。

除去の形 変更前 変更後
1 変数ずつ外す 20 箇所 0 箇所
接頭辞でまとめて外す 7 箇所 0 箇所

接頭辞を持つ名前は、上限の種類が増えるたびに増える。名前を並べずに接頭辞だけで一致させて
おくと、種類を足したときに除去を足し忘れても同じ切り離しが効く。

起点のディレクトリに関わらず、共通の前提が効くようにした。 テストの基準のディレクトリ
(rootdir)は、起点から上へ設定ファイルを探して最初に見つかったところで止まる。リポジトリの
直下には設定ファイルが 1 つも無かったため、テストの束のディレクトリを起点にすると基準が
そこで止まり、共通の前提が読み込まれていなかった。直下に設定ファイル(pytest.ini)を
1 つ置き、節の宣言だけを書いて設定値は足していない。各束へ同じ除去を配る形を採らないのは、
束が増えるたびに置き忘れるためである。

関連する issue: Fixes #678

受け入れ条件: issues/issue-678-requirements.md

Test plan

この変更の検証は、環境変数を設定したシェルと、していないシェルで結果が同じになることである。
同じコマンドを 2 回実行して突き合わせた。実行は 2026-09-22 03:37〜03:52 UTC、対象は 8057d86e

  • uv run --with pytest pytest scripts/tests plugins/ndf -qexit=0(4609 passed in 178.77s)
  • env MONITOR_TIMEOUT=1800 MONITOR_STALL_AGY=1800 MONITOR_STALL_CODEX=1800 MONITOR_STALL=1800 uv run --with pytest pytest scripts/tests plugins/ndf -qexit=0(4609 passed in 177.98s)
  • env MONITOR_TIMEOUT_AGY=1800 MONITOR_STALL_AGY=1800 uv run --with pytest pytest scripts/tests plugins/ndf -qexit=0(4609 passed in 176.90s。着手前に落ちていた組み合わせ)
  • env MONITOR_TIMEOUT=1800 MONITOR_STALL_AGY=1800 uv run --project plugins/playwright-kit/skills/playwright-kit-ops --with pytest pytest . -qexit=0(4793 passed。継続的統合と同じ起動)
  • python3 scripts/check-skill-frontmatter.pyexit=0
  • python3 plugins/ndf/scripts/instructions-check.py --root .exit=0
  • claude plugin validate .exit=0
  • python3 scripts/check-doc-staleness.pyexit=0
  • python3 scripts/check-markdown-links.py --root .exit=0
  • bash scripts/build-runtime-plugins.shexit=0(生成物に差分なし)

起点のディレクトリを変えた実行も確かめた。 テストの束のディレクトリを作業ディレクトリに
して起動する形である。

  • cd plugins/ndf/skills/cross-review/tests && env MONITOR_STALL_AGY=1800 MONITOR_TIMEOUT=1800 uv run --with pytest pytest test_monitor_stall_default.py -qexit=0(9 passed)
  • cd plugins/ndf/scripts/tests && env MONITOR_TIMEOUT=1800 MONITOR_STALL_AGY=1800 uv run --with pytest pytest test_limits.py -qexit=0(63 passed)

着手前(origin/develop)の同じ 2 回は次のとおりだった。

$ MONITOR_TIMEOUT_AGY=1800 MONITOR_STALL_AGY=1800 uv run --with pytest pytest scripts/tests plugins/ndf -q
FAILED plugins/ndf/skills/cross-review/tests/test_launch_agy.py::test_the_print_timeout_defaults_to_the_longest_phase
FAILED plugins/ndf/skills/cross-review/tests/test_monitor_agy.py::test_the_new_name_has_a_stall_default
FAILED plugins/ndf/skills/cross-review/tests/test_monitor_import_safety.py::test_import_succeeds_with_non_numeric_monitor_stall
3 failed, 4600 passed in 182.10s

$ uv run --with pytest pytest scripts/tests plugins/ndf -q
4603 passed in 179.67s
観測 着手前 この変更の後
設定したシェル 3 failed / 4600 passed 0 failed / 4609 passed
設定していないシェル 0 failed / 4603 passed 0 failed / 4609 passed
2 つのシェルの差 3 件 0 件

増えた 6 件は、共通の前提を確かめるために足したテストである。

受け入れ条件の判定:

# 条件 結果
1 設定したシェルで失敗が 0 件になる 合格
2 2 つのシェルで件数が一致する 合格(どちらも 4609 passed)
3 実行中に接頭辞を持つ環境変数が 1 つも残らない 合格(test_no_monitor_variable_survives_into_a_testtest_the_child_process_does_not_inherit_a_monitor_variable。どちらも確かめる前に接頭辞を持つ環境変数を 1 つ差し込む。外す側の本体を何もしない形へ置き換えると落ちることを確かめた)
4 個別に設定した値は打ち消されない 合格(test_a_test_can_still_set_its_own_monitor_variable
5 散った除去が共通の前提へ寄る 合格(`grep -rnE 'delenv
6 実行が終わった後に元の値へ戻る 合格(test_the_values_are_put_back_after_the_run。外す側と戻す側を直接呼び、戻した後に控えが空になることまで確かめる)

未検証の項目: なし
既存の失敗: なし
範囲外と判断したもの: 上限の解決順と表の既定値。どちらもこの変更では触っていない

残リスク: 接頭辞を持たない名前で上限を指す環境変数が将来足された場合、この切り離しは
当たらない。現時点で上限を指す環境変数はすべて接頭辞を持つ
grep -rn "MONITOR_" plugins/ndf/scripts/lib/limits.py と監視の本体で確認した)。
あわせて、plugins/playwright-kit/skills/playwright-kit-ops は自身の pyproject.toml
pytest の節を持つため、そのディレクトリを起点にした実行では基準がそこで止まり、この
切り離しは効かない。その束に上限を読むテストは無い
grep -rn "MONITOR_" plugins/playwright-kit が 0 件)。

影響範囲

変えたのはテストの前提だけで、配布物には及ばない。bash scripts/build-runtime-plugins.sh
は終了コード 0 で終わり、生成物に差分は出なかった。

配布先 変わるか
Claude Code 変わらない
Codex 変わらない
Kiro CLI 変わらない
agy 変わらない

版を上げる必要があるか

要らない。配布物が変わらないため、利用者へ届く内容に差が出ない。

文書の検査

markdown-writing のセルフチェック 6 種を、受け入れ条件(issues/issue-678-requirements.md)と
この本文に対して実行した。

検査 受け入れ条件 この本文 扱い
識別子と略語の混入 ヒットあり ヒットあり すべてコードブロック・ファイルの指し示し・テスト名。説明文には無い
検討痕跡・変更履歴の混入 0 件 0 件
強い否定語の混入 0 件 0 件
過剰な装飾語の混入 0 件 0 件
根拠の曖昧な断定の混入 0 件 0 件
多義語の混入 「環境」 「環境」 すべて「環境変数」「実行環境」の複合語で、指す対象が一意に決まる

🤖 Generated with Claude Code

https://claude.ai/code/session_01MGCedPTy818Zw7VYdmE4GB

takemi-ohama and others added 2 commits September 21, 2026 23:07
無進捗の許容と打ち切りの上限を環境変数で延ばしたシェルから全体のテストを起動すると、
表の既定値を前提にするテストが既定値ではなくその値を読み、変更の中身と関係なく落ちて
いた。収束ループの初期化は着手前のテストの通過を条件にするため、そこで止まる。

リポジトリ直下の共通の前提へ、接頭辞 MONITOR_ を持つ環境変数を外す仕組みを足す。収集より
前に外し(pytest_configure)、実行が終わった時点で元の値へ戻す(pytest_unconfigure)。
テストの本体を読み込む時点で上限を決めてしまう実装があるため、セッションの前提では
間に合わない。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MGCedPTy818Zw7VYdmE4GB
1 変数ずつ外す 20 箇所と、接頭辞でまとめて外す 7 箇所を削除する。接頭辞を持つ名前は
上限の種類が増えるたびに増えるため、名前を並べる形では足し忘れが同じ形で再発する。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MGCedPTy818Zw7VYdmE4GB

@takemi-ohama takemi-ohama left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 cross-review | round 1 | agy | REQUEST_CHANGES

共通の前提による監視環境変数の切り離しおよび散在していた除去の集約は適切ですが、受け入れ条件 6 を検証するテストで pytest_unconfigure が呼び出されておらず検証漏れとなっているため、テストの修正を提案します。

Comment thread scripts/tests/test_root_conftest.py Outdated

@takemi-ohama takemi-ohama left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 cross-review | round 1 | kiro | REQUEST_CHANGES

除去を根の conftest.pypytest_configure へ一本化し、各テストの monkeypatch.delenv_clean_env を消した結果、実行の起点がテストのディレクトリのとき(rootdir が根まで遡らず根 conftest が読まれないとき)に MONITOR_* の切り離しが効かず、test_limits.py(16 failed)と test_monitor_stall_default.py(3 failed)が env 設定時に落ちる。PR 本文の実測は根からの全体実行だけを見ており、サブディレクトリ起点は範囲に入っていない。散った除去を根へ寄せる方針は良いが、起点に依らず効く形(例: 各束の tests/conftest.py から共通除去を委譲呼び出しする)に補うことを提案する。詳細は各インライン参照。

Comment thread plugins/ndf/scripts/tests/test_limits.py
Comment thread conftest.py
テストの基準のディレクトリ(rootdir)は、起点から上へ設定ファイルを探して最初に
見つかったところで止まる。リポジトリの根に設定ファイルが 1 つも無いため、テストの束の
ディレクトリを起点にすると基準がそこで止まり、根の共通の前提が読み込まれなかった。
上限を延ばしたシェルから束を起点に起動すると、監視の上限を前提にするテストが落ちる。

根に設定ファイルを 1 つ置き、基準をリポジトリの根へ固定する。設定値は足さない。
外した値を戻す検査は、控えを手で操作せずに外す側と戻す側を実際に呼ぶ形へ直した。
起点に依らず切り離しが効くことを、束のディレクトリからの起動で確かめる検査を足した。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MGCedPTy818Zw7VYdmE4GB
@takemi-ohama

Copy link
Copy Markdown
Contributor Author

/ndf:fix サマリ(round 1)

対応件数: critical=0 / major=3 / minor=0(合計 3 件)
deferred: 0 件 / rejected: 0 件
commit: 28dad58
CI: 実行中(この時点で失敗している検査は無し)

直し方

3 件のうち 2 件は同じ原因でした。テストの基準のディレクトリ(rootdir)は起点から上へ設定ファイルを探して最初に見つかったところで止まるため、リポジトリの根に設定ファイルが 1 つも無いと、束のディレクトリを起点にした実行で基準がそこで止まり、根の共通の前提が読み込まれません。

根に設定ファイル(pytest.ini)を 1 つ置き、基準をリポジトリの根へ固定しました。中身は節の宣言だけで、設定値は足していません。各束へ薄い委譲を撒く形は採りませんでした(束が増えるたびに置き忘れるため)。

起点 置く前 置いた後
plugins/ndf/skills/cross-review/teststest_monitor_stall_default.py 3 failed 9 passed
plugins/ndf/scripts/teststest_limits.py 16 failed 63 passed

残る 1 件は、外した値を戻す検査が控えを手で操作していた点です。外す側と戻す側を実際に呼ぶ形へ直し、戻した後に控えが空になっていることまで確かめます。起点に依らず切り離しが効くことを確かめる検査も足しました。

対応した指摘

位置 指摘 対応
scripts/tests/test_root_conftest.py:216 戻す側を呼ばずに手で戻しているため偽陽性 外す側と戻す側を実際に呼ぶ形へ変更。Resolve 済み
plugins/ndf/scripts/tests/test_limits.py:41 束を起点にすると除去が効かず 16 failed 根に設定ファイルを追加。Resolve 済み
conftest.py:101 束を起点にすると除去が効かず 3 failed 根に設定ファイルを追加。根の設定の説明へ 1 文追記。Resolve 済み

検証

uv run --with pytest pytest scripts/tests plugins/ndf -q
# 4609 passed in 178.72s

env MONITOR_TIMEOUT=1800 MONITOR_STALL_AGY=1800 MONITOR_STALL_CODEX=1800 \
  uv run --with pytest pytest scripts/tests plugins/ndf -q
# 4609 passed in 179.25s

uv run --project plugins/playwright-kit/skills/playwright-kit-ops --with pytest pytest . -q
# 4793 passed in 182.91s

足した検査が実際に落ちることも確かめました。戻す側の本体を pass にしたとき、および根の設定ファイルを外したときに、それぞれ該当の検査が 1 failed になります。

@takemi-ohama takemi-ohama left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 cross-review | round 2 | kiro | COMMENT

除去の共通化・pytest.ini による rootdir 固定・散った除去の削除(AC5)は実測で確認でき、環境変数を設定したシェルでも影響範囲の束は全て通った。設計・正確性の修正指摘はなし。テストの実証性に minor を 1 件だけインラインで残す。

Comment thread scripts/tests/test_root_conftest.py Outdated

@takemi-ohama takemi-ohama left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 cross-review | round 2 | codex | APPROVE

修正が必要な指摘はありません。指定の全体テストは 4609 件すべて通過しました。

実行中に監視の上限を指す環境変数が残らないことと、子プロセスへ引き継がれないことを
確かめる 2 つは、周りのシェルがその環境変数を持たないときに、外す仕組みを壊しても
素通りしていた。継続的統合と多くの手元の環境がこれに当たる。

確かめる前に自分で 1 つ差し込む形へ直した。根の設定は別名で読み込み、控えを汚さない。
外す側を呼んだ後に戻す側も呼び、元の状態へ戻す。

外す側の本体を一時的に何もしない形へ置き換えると、この 2 つが落ちることを確かめた。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MGCedPTy818Zw7VYdmE4GB
@takemi-ohama

Copy link
Copy Markdown
Contributor Author

/ndf:fix サマリ(最終スイープ)

対応件数: critical=0 / major=0 / minor=1(合計 1 件)
deferred: 0 件 / rejected: 0 件
commit: 8057d86
未解決のレビュースレッド: 0 件(返信と Resolve の後に数え直した)

詳細

指摘 位置 対応
監視の環境変数を確かめる 2 つのテストが恒真になっている scripts/tests/test_root_conftest.py:184 確かめる前に自分で 1 つ差し込む形へ直した

周りのシェルが監視の上限を指す環境変数を持たないと、外す仕組みを壊しても 2 つが素通りしていた。根の設定を別名で読み込むヘルパを使い、環境変数を 1 つ設定してから外す側を呼び、消えていること・子プロセスへ引き継がれないことを確かめる形にした。控えは汚さず、try / finally で戻す側も呼ぶ。

恒真でなくなったことは、外す側の本体を一時的に何もしない形へ置き換えて確かめた(2 つとも落ちる)。置き換えは元へ戻した。

検証

コマンド 結果
uv run --with pytest pytest scripts/tests plugins/ndf -q 4609 passed in 176.28s
env MONITOR_TIMEOUT=1800 MONITOR_STALL_AGY=1800 MONITOR_STALL_CODEX=1800 uv run --with pytest pytest scripts/tests plugins/ndf -q 4609 passed in 179.52s

2 つのシェルで件数が一致する。本文の検証結果と受け入れ条件の表も、この実測へ揃えた。

継続的統合: 失敗したジョブは 0 件(markdown-link-checkpytest は実行中で、完了は待っていない)。

@takemi-ohama
takemi-ohama marked this pull request as ready for review September 22, 2026 03:52
@takemi-ohama
takemi-ohama merged commit 5755fc0 into develop Sep 22, 2026
17 checks passed
@takemi-ohama
takemi-ohama deleted the fix/issue-678-monitor-env-isolation branch September 22, 2026 11:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant