feat(cli-docs-lint): priority_inversion validator + 順位 19 retire + T2-1/T3-2 採用 - #200
Conversation
…機械検知 PR #199 (Bundle W) で実観測した「Tier N が Tier N+k に依存 + 待ち先 Tier N+k 自身が 観測フェーズ」パターンを cli-docs-lint に validator 化。決定論的検出層で Claude 判断 介入なし (`feedback_pipeline_over_rules.md` 適用)。 ## 実装 - `src/cli-docs-lint/src/priority_inversion.rs` (新規): todo-summary.md table を parse し - 順位/Tier 抽出 (`parse_row`, `parse_tier`) - 依存記述から 順位 NN 参照を抽出 (`extract_referenced_ranks`、複合 `順位 NN/MM` 対応) - 「なし」プレフィックスで context note を排除 (`has_no_dependency_prefix`) - 依存先 Tier > 自分の Tier かつ resolved-marker なしを violation 化 - `src/cli-docs-lint/src/lib.rs`: `priority_inversion` module を export - `src/cli-docs-lint/src/main.rs`: `--check priority-inversion` mode + `all` 経路統合 + help / describe_mode に追記 ## resolved-marker 設計 依存記述内で「順位 NN ... land 済 / 完了 / retired / 採用昇格済」が 80 char window 以内に現れる場合 resolved 扱い (= inversion check skip)。「land 済 (2026-06-07)」のような 日付付きマーカーや「Bundle X land 済」のような bundle-level マーカーをカバー。 ## 性能 (F-2 対応、pre-push reviewer non-blocking finding) `parse_tier` / `extract_referenced_ranks` の regex は `std::sync::LazyLock<Regex>` で module 初期化時に 1 度だけ compile (per-row 再 compile を回避)。既存 codebase の OnceLock 利用 (cli-pr-monitor) と整合する std::sync::* family。 ## テスト fixture 設計 (F-3 対応、pre-push reviewer non-blocking finding) `check_content_skips_when_referenced_rank_missing_from_table` テストの fixture を `"順位 19 land 後推奨"` (resolved-marker 非含有) に変更。missing-rank 経路を厳密に exercise する形に修正し、将来 fixture に rank 19 行を追加した際の test 経路 silent shift (missing-rank → resolved-marker) を防止。 ## prefix-match 防御 (pre-push takt-fix で auto 補正) `has_resolved_marker_after` に `c.is_ascii_digit()` ガードを追加し、`"順位 19"` が `"順位 195"` 等の prefix match で誤検出するバグを防止。専用 unit test 追加。 ## テスト & dogfood - 38 unit tests pass (priority_inversion 18 + preamble 9 + cross_ref 11) - 現 docs/todo-summary.md に対し 0 violations (false positive なし) - pnpm lint:docs OK (preamble + cross-ref + priority-inversion) ## 統合 - `pnpm lint:docs` 経由で `--check all` 実行時に自動実行 - `.claude/cli-docs-lint.exe` rebuild + deploy 済 (release profile) - ADR-039 試験運用パターン継承 (kill-switch `CLI_DOCS_LINT_DISABLE=1`、3-5 PR dogfood 後に default-ON 昇格 / 却下を判定)
…nd で代替経路実現済、PR #194-後 8 runs で escalation 候補 0 件 PR #199 (Bundle W) session 内合意 (ユーザー指示 2026-06-07): 「A の PR マージまで進ん だら、B. 順位 19 自体の Tier 再評価 のタスク化を進める」を実行し、実測値に基づき (C) retire を決定。 ## 決定根拠 (empirical data) PR #194 (mechanical gate 強化) land 後の takt run logs を集計: | Run | iteration 上限到達 | supervise step 到達 | escalation 候補 | |---|---|---|---| | 8 runs (pre-push-review 7 + post-pr-review 1) | 0/8 | 0/8 | 0/8 | REJECT-ESCALATE が解決するはずの「iteration 上限到達 + supervise/fix_supervisor の 無限ループ」が **PR #194 land 以降 1 件も観測されていない**。代替経路で十分実用に 耐えていることが定量的に確認できた: - ADR-037 (fix-trust shortcut、PR #106 land): `convergence_verdict: fully_resolved` で COMPLETE 直行 → iteration が verdict ベースで有限化 - ADR-043 (fail-closed 原則、PR #194 land): security/quality gate semantics 構造化 - PR #194 (mechanical gate 強化): merge 前 clippy + 空 commit sweep の決定論層追加 ## 変更内容 - docs/todo3.md: 順位 19 entry block を削除 (-46 行) - docs/todo-summary.md: table から 順位 19 row を削除 (-1 行) 順位 19 を gate にしていた Tier 1 (旧 順位 34/35) は既に PR #199 で priority inversion 解除済のため、本 retire で残るブロッキングはない。 ## 関連 PR / ADR - PR #199 (Bundle W、priority inversion 解除) - ADR-037 fix-trust shortcut - ADR-043 Security/Quality Gate Fail-Closed 原則 - PR #194 mechanical gate 強化 (clippy + 空 commit sweep)
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
✅ Files skipped from review due to trivial changes (2)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughこのPRはタスク優先度テーブルの依存関係を検証する「priority_inversion」チェッカーを新規実装し、CLIツールに統合しました。同時にタスク管理ドキュメントを更新して、新しい計画(proptest導入、ADR作成)を記録し、完了済み項目を削除しています。 ChangesPriority Inversion チェッカーと関連ドキュメント更新
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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.
Inline comments:
In `@src/cli-docs-lint/src/priority_inversion.rs`:
- Around line 171-182: 関数 has_resolved_marker_after で RESOLUTION_WINDOW_CHARS
をバイト長で使い窓開始も参照先 abs_pos になっているためマルチバイト文字で判定ズレが生じます。修正は:窓は「参照の直後」から始める(use after
= abs_pos + needle.len())こと、そしてバイトオフセットではなく文字数で RESOLUTION_WINDOW_CHARS
文字分だけ取るようにすること(after から先の文字列を char 単位で走査して RESOLUTION_WINDOW_CHARS 文字目のバイト境界を求めて
next_char_boundary 相当の処理を行う)—これにより window を正しく切り取り、以降の
RESOLVED_MARKERS.iter().any(|m| window.contains(m)) チェックに渡してください。
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 3196a6bd-191b-4c7b-aa09-f2e800508227
📒 Files selected for processing (6)
docs/todo-summary.mddocs/todo10.mddocs/todo3.mdsrc/cli-docs-lint/src/lib.rssrc/cli-docs-lint/src/main.rssrc/cli-docs-lint/src/priority_inversion.rs
💤 Files with no reviewable changes (1)
- docs/todo3.md
PR #199 (Bundle W) の post-merge-feedback report (.claude/feedback-reports/199.md) で analyzer が ✅ 採用候補とした 2 件を、ユーザー承認 (2026-06-08) を経て docs/todo*.md 系列に登録する。 ## 順位 197: hooks-session-start orphan age 計算に proptest 追加 (T2-1) Bundle W (PR #199) で `cli-pr-monitor::lock` に PastTime newtype + proptest properties を 導入し、`saturating_sub` silent semantic mismatch (Finding D) を構造的に排除した。 同じ bug class が `src/hooks-session-start/src/main.rs:236` の orphan age 計算 (`now_unix.saturating_sub(start_unix)`) にも存在し、clock rewind / future timestamp で age=0 → orphan reaper が「young」判定でスキップ → `.failed` marker 未生成 → ADR-030 L2 recovery 停止という具体的 failure chain が確認済。Bundle W の pattern を hooks-session-start に展開する。 - Tier 2 / Effort M / Severity High / Frequency Medium / Adoption Risk None - proptest 1.x は既存 dev-dependencies、新規依存追加は hooks-session-start のみ ## 順位 198: ADR-NNN Timestamp invariant safety (T3-2) PR #96 Finding D + PR #199 Bundle W で同型 bug class が 2 件観測 (Frequency Medium)。 「時刻計算における silent failure class と型レベル防御」を永続化し、派生プロジェクト (techbook-ledger / auto-review-fix-vc) への transferability を確保する ADR を新設。 - Tier 3 / Effort M / Severity Medium / Frequency Medium / Adoption Risk None - 順位 135 codified placeholder policy 適用 (ADR 番号は land 時 PR で確定) - CLAUDE.md ADR list 追記 ## 変更ファイル - docs/todo10.md: 順位 197/198 詳細 entry を 2 セクション追加 - docs/todo-summary.md: table に順位 197/198 行を追加
…r-based 化 (CR Major #1) PR #200 CodeRabbit review で指摘された Major finding を修正。 ## Bug `has_resolved_marker_after` の window 計算が以下の 2 点で spec とズレていた: 1. **byte vs char**: `(abs_pos + RESOLUTION_WINDOW_CHARS)` は **byte** 演算。日本語 1 文字 = 3 bytes なので「80 文字 window」のつもりが実質 ~27 文字 window に縮退 2. **window 開始位置**: `&haystack[abs_pos..]` で needle (順位 NN) 自体を window に含めていた。 spec は「順位参照の **直後** から N 文字以内」 具体 failure 例 (CR review 提示): - `"順位 19" + "あ"*40 + " land 済"` で、marker "land 済" は char-distance 41 (window 80 内) - 旧 byte-based: 80 bytes window は ~26 chars のみカバー → marker 圏外 → resolved 扱いされず → **false negative (= inversion 誤検出 → reviewer に noise)** ## Fix ```rust let window_end = haystack[after..] .char_indices() .nth(RESOLUTION_WINDOW_CHARS) .map(|(i, _)| after + i) .unwrap_or(haystack.len()); let window = &haystack[after..window_end]; ``` - 起点を `after` (needle 直後) に変更 - `char_indices().nth(N)` で N 文字目の byte offset を取得 → char-based window 不要になった `next_char_boundary` ヘルパー関数を削除。 ## Test regression test 追加 (`is_resolved_detects_marker_across_multibyte_gap`): - `"順位 19" + "あ".repeat(40) + " land 済"` で resolved 判定が true になることを assert - 旧実装ではこの test は fail する (byte window で marker 圏外) ## Doc update `RESOLUTION_WINDOW_CHARS` の doc に「**文字数** (バイト数ではない)」を明記。 multi-byte でも spec 通り動作することを comment で保証。 ## 検証 - cargo test -p cli-docs-lint: 19 priority_inversion tests pass (新規 regression 1 含む) - cargo clippy -p cli-docs-lint --all-targets -- -D warnings: clean - pnpm lint:docs: OK (preamble + cross-ref + priority-inversion) - .claude/cli-docs-lint.exe rebuild + deploy 済 Refs: CR comment on PR #200 (src/cli-docs-lint/src/priority_inversion.rs:182)
85159b5 to
d878961
Compare
|
@coderabbitai review |
✅ Action performedReview finished.
|
) - AWS Access/Secret Key, OpenAI sk-, GitHub PAT/OAuth, Anthropic sk-ant- の 6 種類 hardcoded secret pattern を regex 検出 - Bash command + Edit/Write content の両方をスキャン (handle_write_edit_tool に secret scan 統合、old_string は除外して secret 削除操作を allow) - default_preset_names に含めて Tier 1 security-critical default-on (漏洩の非対称性 = 1 度漏れたら手遅れ、jj-message-required の opt-in とは別判断) - handle_write_edit_tool を 4 helper 関数に分割 (関数長 50 行制限対応) - 既存 BlockedPattern.exception 機構を再利用、Anthropic sk-ant- を OpenAI sk- pattern の exception で除外 (Rust regex negative lookahead 代替、順位 144 で導入) - ~/.claude/rules/common/security.md § Secret Management の機械強制層 cargo test 202/202 pass (新規 secret-detection 18 tests 追加、回帰なし) dogfood: PreToolUse 層で AI 自身の echo AKIA... 投入を実 block 確認 同梱 (queue 登録のみ、本 PR では実装せず): - 順位 199-202: PR #200 post-merge-feedback T2-1/T3-1/T3-2/T3-3 採用 entries prior session 由来の registration、todo10.md / todo-summary.md に entries 追記 bundle 理由: docs/todo-summary.md が同ファイル内で 199-202 行追加 + 146 行削除を 抱え、jj 非対話 split (path 単位) で分離不能 (partial-file split が必要なため)。 無理に分けると surgery コスト > 収益、reviewer から見ても一貫性なし。
Summary
PR #199 (Bundle W) 開始時に表面化した meta-issue (priority inversion + 順位 19 dead-lock 状の依存) を解消し、同型問題を機械検知する layer を追加。
3 commits 構成:
docs/todo-summary.mdtable の Tier N → Tier N+k 依存を機械検知する新 validator + ADR-039 試験運用パターン適用設計判断
feedback_pipeline_over_rules.md適用: Claude 判断介入ではなく決定論層 (cli-docs-lint validator) で priority inversion を機械検知feedback_post_merge_feedback_adoption_requires_user_approvalに従い T2-1/T3-2 はユーザー明示承認後に todo 登録機械検知ロジック (priority_inversion validator)
pre-push reviewer non-blocking finding 対応 (commit 1 内)
std::sync::LazyLock<Regex>で module 初期化時 1 度のみ compilec.is_ascii_digit()で"順位 19"が"順位 195"等の prefix match で誤検出を防止Test plan
cargo test -p cli-docs-lint: 38 + 11 passedcargo clippy -p cli-docs-lint --all-targets -- -D warnings: cleanpnpm lint:docs: OK (preamble + cross-ref + priority-inversion、現 summary で 0 violations)Summary by CodeRabbit