Skip to content

test(custom-lint): rule⑥ self-exclusion 回帰テスト + Bundle g-1 stale cleanup (Phase d P-3 繰上げ)#141

Open
aloekun wants to merge 3 commits intomasterfrom
feature/p3-bundle-d-self-exclusion-test
Open

test(custom-lint): rule⑥ self-exclusion 回帰テスト + Bundle g-1 stale cleanup (Phase d P-3 繰上げ)#141
aloekun wants to merge 3 commits intomasterfrom
feature/p3-bundle-d-self-exclusion-test

Conversation

@aloekun
Copy link
Copy Markdown
Owner

@aloekun aloekun commented May 10, 2026

Summary

Phase d roster の P-3 (繰上げ) として Bundle d (順位 68 = no-ephemeral-todo-reference self-exclusion invariant 回帰テスト) を land。3 commits 構成: P-2 feedback layer / stale todo cleanup (Bundle g-1 land 済発見) / P-3 implementation。

変更内容

Commit 1: 順位 101-105 登録 + analysis.md P-2 完了反映 (P-2 feedback layer carry-over)

PR #140 (Phase d P-2 = rule⑧ no-docs-relative) merge 後の post-merge-feedback で採用された 5 件 を todo に登録。analysis.md の P-2 row を ✅ 完了化 + classifier preview metrics + fallback rate 100% trend signal を outcome section として記載。

順位 内容 Effort
101 rule⑧ depth-1 非-docs MD edge case test S
102 paths filter を lint runner に実装 M
103 lint runner サポート field code comment 明示化 S
104 ADR-007 amendment (self-limit 安全条件 + min test checklist) S
105 グローバル CLAUDE.md に lint runner field table XS

PR #140 T2 #1 (大文字バリアント test 必須化) は 不採用: memory feedback_no_unenforced_rules.md の追加観測として「Tier 2 偽装の必須化ルール」検知 signal 3 項目を codify。

Commit 2: 順位 85+86 (Bundle g-1) は PR #125 で land 済を反映 — stale todo cleanup

P-3 着手時に src/cli-pr-monitor/src/stages/monitor.rscompute_verdict を読んだ瞬間、既に review_state == "not_found" || "pending" guard が存在し、12 件の verdict transition tests が pass することを発見。jj logPR #125 (2026-05-07 merge) で実装済 と確認。PR #125feedback_todo_no_history.md ("完了タスクは todo から削除") に違反 し、todo entry 削除を忘れたため、3 日後の PR #138 (Phase d kickoff prep) で stale な docs/todo-summary.md を読んだ際に「pending」と誤認 → roster の P-3 に Bundle g-1 を組入れ。

本 commit で:

  • docs/todo5.md の 順位 85/86 detail entry 削除 (-43 行)
  • docs/todo-summary.md の 順位 85/86 行削除 (Bundle g paragraph も ✅ 完了化)
  • docs/local-llm-offload-analysis.md の P-3 row を「P-3 roster から除外」に変更、後続 P-4/P-5 を P-3/P-4 に繰上げ

新 memory feedback_verify_task_not_already_done.md を追加: todo 着手時に jj log + 既存 test で land 済確認する手順を codify。本件と同型の事故を recovery layer として防ぐ。

Commit 3: rule⑥ self-exclusion 回帰テスト追加 + analysis.md P-3 完了反映 (本 PR の核)

src/hooks-post-tool-linter/src/main.rs6 件の no_ephemeral_todo_* test を追加。配置先は既存 tests mod 内 (md_no_docs_relative_* test group の隣)。

Test 検証内容
no_ephemeral_todo_detects_concrete_digit_reference docs/todo3.md 形式 → fire (TP)
no_ephemeral_todo_detects_zero_digit_form docs/todo.md (zero digit) 形式 → fire (zero-digit edge case)
no_ephemeral_todo_skips_letter_placeholder docs/todoN.md (N = letter) → skip
no_ephemeral_todo_skips_asterisk_literal docs/todo*.md (literal *) → skip
no_ephemeral_todo_only_targets_listed_extensions_md_skipped .md 拡張子は対象外 → skip
no_ephemeral_todo_self_exclusion_invariant_holds_on_deployed_toml deployed .claude/custom-lint-rules.toml 自身は self-trigger しないことを assert (本 task の核)

Self-trigger 事故の対処

本 test 実装中、PostToolUse lint で rule⑥ self-trigger + comment-lint-rust (Bundle Z #B-α) 違反を検出 (試験運用層が動作した好事例):

  • rule⑥ self-trigger 5 件: test fixture の literal docs/todo3.md / docs/todo.md 文字列が source 中に直接書かれて rule⑥ に hit
  • comment-lint-rust 6 件: 説明用 // コメントが Bundle Z #B-α (Rust 非 doc コメント禁止) に違反

対処 (= 本 test が future 防止しようとしている self-trigger anti-pattern の dogfood 検証):

  • test fixture を format!() で動的構築 (source に literal を残さない build_concrete_digit_fixture(3) / build_zero_digit_fixture() 等のヘルパー化)
  • // コメント全削除 (test 名 + assertion message で意図を表現)

これにより本 test 自身も rule⑥ + comment lint 両方で clean に通る状態を達成。

analysis.md P-3 完了反映

P-3 (繰上げ) row を ✅ 完了化 + P-3 dogfood outcome section を追加。

Phase d P-3 dogfood signal (classifier preview のみ、real pipeline 未実行)

P-1 / P-2 と同方針 (commit pollution 回避):

Metric P-1 P-2 P-3
Lines 337 203 187
Latency 23s 46s 11s
Findings 0 0 0
screen_decision human_review (fallback) human_review (fallback) human_review (fallback)
fallback_reason JSON parse error JSON parse error JSON parse error (line 1 col 692)

Fallback rate trend (累積): 3/3 = 100%。Phase d guide §3 の kill-switch criteria (3/5 = 60% で停止) は real pipeline 経由なら 既に発動超過順位 98 (num_ctx overflow detection) を Phase d 結果集約より先に実装することを強く推奨 (kill-switch 厳密判定の前提整備)。

Latency variance signal: P-1=23s / P-2=46s / P-3=11s の振れ幅は input size と弱相関 (P-2 が最短入力で最長 latency) → mistral 内部状態 (cold/warm context) が支配的要因の仮説を強化。real pipeline 計測時は cold start 回避の warmup 戦略の設計が必要。

Test plan

  • cargo test -p hooks-post-tool-linter — 93/93 pass (87 既存 + 6 新規)
  • pnpm deploy:hooks でビルド・デプロイ確認
  • takt pre-push-review 完了 (315s)
  • markdownlint clean (PostToolUse hook 確認)
  • PostToolUse rule⑥ self-trigger 検出 → format! ヘルパー化で解消 (本 test の dogfood 価値の実証)
  • PostToolUse comment-lint-rust 違反検出 → コメント削除で解消
  • サイズチェック: todo5.md / todo6.md / todo-summary.md 50KB 内

Out of scope

  • 順位 69 (yaml/yml extensions 追加理由コメント): 同 Bundle d だが scope 異なるため別 PR
  • 順位 98 (num_ctx overflow detection): P-3 fallback で再々確認した重要性を本 PR でも記述したが、実装は別 PR (Phase d 結果集約より先に実装推奨)
  • real pipeline 経由 Phase d metric: P-4 (繰上げ) 移行時の trade-off 再判断 (warmup 戦略含む)
  • 派生プロジェクト deploy 確認: techbook-ledger / auto-review-fix-vc への hook 反映は別タイミング

Summary by CodeRabbit

リリースノート

  • Documentation

    • プロジェクト分析および進捗追跡ドキュメントを更新しました。
  • Tests

    • カスタムリント規則の検証テストスイートを追加しました。

Review Change Stack

aloekun added 3 commits May 11, 2026 00:59
… P-2 完了反映 (classifier preview metrics + fallback rate 100% trend signal)
…帰テスト追加 + analysis.md P-3 完了反映 (順位 68 / Bundle d / Phase d P-3 繰上げ)
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 10, 2026

📝 Walkthrough

概要

PR #141 は Phase d のドッグフード結果ドキュメント、複数の todo ファイルのタスク追跡の整理、および no-ephemeral-todo-reference カスタム lint ルールの包括的なテストスイート(フィクスチャビルダーと自己除外検証を含む)を統合します。

変更点

ドッグフード進捗とタスク追跡

レイヤー / ファイル(s) 概要
ドッグフード結果
docs/local-llm-offload-analysis.md
Phase d P-2(PR #140)と P-3(Bundle d)のクラシファイア測定値を記録:latency 46s/11s、findings ゼロ、screen_decision フィールド欠落による fallback、100% fallback レート、post-merge feedback 採用率。P-3 ロスター変更を反映して Effort 分布を更新。
タスク優先度とサマリー
docs/todo-summary.md
優先度テーブルを no-ephemeral-todo-reference yaml/yml 理由付け(順位 69)で更新;新規 rule⑧ タスク(順位 101–105)をエッジケーステスト、paths フィルタ実装、フィールドドキュメント、ADR-007 修正として追加;Bundle g/f/c/d の説明を再編成。
完了タスクの削除
docs/todo5.md
削除:PR #110 T2-1(自己除外不変テスト)、PR #121 T1-1(monitor state machine ガード)、PR #121 T2-4(state transition テストカバレッジ)。
将来の実装計画
docs/todo6.md
rule⑧ の詳細タスクを追加:depth-1 非-docs MD エッジケーステスト(+31 行)、paths フィルタ実装と ADR-007 修正(+32 行)、CustomRule TOML フィールドドキュメント(+27 行)、semantic self-limitation 安全条件(+39 行)、CLAUDE.md グローバルサポートフィールド表(+32 行)。

no-ephemeral-todo-reference Lint ルールテスト

レイヤー / ファイル(s) 概要
テストヘルパーとフィクスチャ
src/hooks-post-tool-linter/src/main.rs
no_ephemeral_todo_reference_rule() ヘルパー追加(docs/todo{digit}.md 向け大文字小文字区別なし正規表現、スコープ拡張機能);concrete digits、zero-digit ベースライン、letter プレースホルダ、asterisk リテラル向けフィクスチャビルダー。
違反検出テスト
src/hooks-post-tool-linter/src/main.rs
concrete digit と zero-digit フォーム向け違反検出をアサート;letter プレースホルダまたは asterisk glob 向け違反なしをアサート;制御テストで対象外拡張機能をルールがスキップすることを確認。
自己除外不変テスト
src/hooks-post-tool-linter/src/main.rs
デプロイ済み .claude/custom-lint-rules.toml をロード、ルールをコンパイル、デプロイ済み設定に対して実行、違反ゼロをアサート(ルール自身の config にマッチすることを防止)。

推定コードレビュー労力

🎯 2 (シンプル) | ⏱️ ~12 分

関連の可能性がある PR

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 53.85% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR タイトルは「rule⑥ self-exclusion 回帰テスト」と「Bundle g-1 stale cleanup」の両方を明記しており、PR 目的の主要な変更内容(テスト追加と古いタスクの整理)を適切に要約している。具体性があり、スキャンで主要な変更が理解できる。
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/hooks-post-tool-linter/src/main.rs (1)

1699-1711: ⚡ Quick win

self-exclusion test の前提条件を明示化することを推奨

本テストは deployed .claude/custom-lint-rules.toml ファイルに対して rule を適用し、self-trigger しないことを検証しています。テストの実効性は extensions list に "toml" が含まれることに依存していますが、この前提が明示されていないため、将来の変更で extensions から "toml" が削除された場合、テストは pass するものの実際には TOML ファイルがスキャンされない (silent test degradation) リスクがあります。

テスト冒頭で前提を明示する assertion を追加することを推奨します。

🛡️ 提案する改善
 #[test]
 fn no_ephemeral_todo_self_exclusion_invariant_holds_on_deployed_toml() {
+    let rule = no_ephemeral_todo_reference_rule();
+    assert!(
+        rule.extensions.contains(&"toml".to_string()),
+        "self-exclusion test requires 'toml' in extensions list to actually scan the TOML file"
+    );
+
     let path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
         .join("..")
         .join("..")
         .join(".claude")
         .join("custom-lint-rules.toml");
-    let rules = compile_test_rules(vec![no_ephemeral_todo_reference_rule()]);
+    let rules = compile_test_rules(vec![rule]);
     let violations = run_custom_rules(path.to_str().unwrap(), &rules);
     assert!(
         violations.is_empty(),
         "self-exclusion invariant broken: rule⑥ self-triggered on deployed custom-lint-rules.toml"
     );
 }
🤖 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/hooks-post-tool-linter/src/main.rs` around lines 1699 - 1711, The test
no_ephemeral_todo_self_exclusion_invariant_holds_on_deployed_toml currently
assumes TOML files are scanned but doesn't assert that the linter's configured
extensions include "toml"; add an explicit assertion at the start of this test
that the extensions list used by the custom rules contains "toml" (i.e., call
the same helper/config function that run_custom_rules or compile_test_rules uses
to obtain file extensions, assert extensions.contains("toml")), so the test will
fail loudly if future changes remove TOML from the scanned extensions.
🤖 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.

Nitpick comments:
In `@src/hooks-post-tool-linter/src/main.rs`:
- Around line 1699-1711: The test
no_ephemeral_todo_self_exclusion_invariant_holds_on_deployed_toml currently
assumes TOML files are scanned but doesn't assert that the linter's configured
extensions include "toml"; add an explicit assertion at the start of this test
that the extensions list used by the custom rules contains "toml" (i.e., call
the same helper/config function that run_custom_rules or compile_test_rules uses
to obtain file extensions, assert extensions.contains("toml")), so the test will
fail loudly if future changes remove TOML from the scanned extensions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7cf5d53b-b6bb-47a5-9cf4-27cb7d773342

📥 Commits

Reviewing files that changed from the base of the PR and between b6b61dd and 11dc06b.

📒 Files selected for processing (5)
  • docs/local-llm-offload-analysis.md
  • docs/todo-summary.md
  • docs/todo5.md
  • docs/todo6.md
  • src/hooks-post-tool-linter/src/main.rs
💤 Files with no reviewable changes (1)
  • docs/todo5.md

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