Skip to content

feat(cli-docs-lint): priority_inversion validator + 順位 19 retire + T2-1/T3-2 採用 - #200

Merged
aloekun merged 4 commits into
masterfrom
priority-inversion-and-task-cleanup
Jun 9, 2026
Merged

aloekun merged 4 commits into
masterfrom
priority-inversion-and-task-cleanup

Conversation

@aloekun

@aloekun aloekun commented Jun 8, 2026

Copy link
Copy Markdown
Owner

Summary

PR #199 (Bundle W) 開始時に表面化した meta-issue (priority inversion + 順位 19 dead-lock 状の依存) を解消し、同型問題を機械検知する layer を追加。

3 commits 構成:

  1. feat(cli-docs-lint): priority_inversion validatordocs/todo-summary.md table の Tier N → Tier N+k 依存を機械検知する新 validator + ADR-039 試験運用パターン適用
  2. docs(todo): 順位 19 (REJECT-ESCALATE) retire — PR feat(hooks): merge 前 mechanical gate 強化 (clippy + 空 commit sweep) #194 land 以降 8 runs の実測 (escalation 候補 0/8) に基づき (C) retire を決定、todo3.md + summary から削除
  3. docs(todo): post-merge-feedback T2-1/T3-2 採用 — PR feat(cli-pr-monitor): PastTime newtype + proptest (Bundle W、順位 19 依存解除) #199 post-merge-feedback の analyzer 推奨 (T2-1: hooks-session-start proptest / T3-2: ADR-NNN Timestamp invariant safety) をユーザー承認 (2026-06-08) で todo10/summary に登録

設計判断

  • feedback_pipeline_over_rules.md 適用: Claude 判断介入ではなく決定論層 (cli-docs-lint validator) で priority inversion を機械検知
  • ADR-037 (fix-trust shortcut) + ADR-043 (fail-closed) + PR feat(hooks): merge 前 mechanical gate 強化 (clippy + 空 commit sweep) #194 (mechanical gate) の land 後実測値 0/8 を根拠に順位 19 retire (Plan C)
  • feedback_post_merge_feedback_adoption_requires_user_approval に従い T2-1/T3-2 はユーザー明示承認後に todo 登録

機械検知ロジック (priority_inversion validator)

判定 動作
依存欄が「なし」で始まる skip (integration note 扱い)
依存先 Tier ≤ 自分の Tier skip (正常な依存)
「順位 N land 済 / 完了 / retired」が 80 char 以内 skip (resolved marker)
それ以外 (Tier N → Tier N+k 未解決) violation 報告

pre-push reviewer non-blocking finding 対応 (commit 1 内)

  • F-2 (regex per-row recompile): std::sync::LazyLock<Regex> で module 初期化時 1 度のみ compile
  • F-3 (test fixture silent shift fragility): fixture を resolved-marker 非含有に変更
  • prefix-match 防御 (takt-fix auto 適用): c.is_ascii_digit()"順位 19""順位 195" 等の prefix match で誤検出を防止

Test plan

  • cargo test -p cli-docs-lint: 38 + 11 passed
  • cargo clippy -p cli-docs-lint --all-targets -- -D warnings: clean
  • pnpm lint:docs: OK (preamble + cross-ref + priority-inversion、現 summary で 0 violations)
  • pre-push review: APPROVE (1 iteration、2m 6s)
  • CI green (CodeRabbit + GitHub Actions)

Summary by CodeRabbit

  • 新機能
    • ドキュメント検証ツールに「優先度逆転」チェックと対応するCLIモードを追加しました(タスク依存関係の矛盾を検出)。
  • ドキュメント
    • タスク管理ドキュメントを更新:既存タスク項目の削除と、新規タスク/設計メモ(時刻不変性と検証計画)の追加を行いました。
  • テスト
    • 新規チェックに対する包括的な単体テストを追加しました。

aloekun added 2 commits June 8, 2026 20:37
…機械検知

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)
@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f67647c2-0395-4103-b98f-4e018ed8ae10

📥 Commits

Reviewing files that changed from the base of the PR and between 85159b5 and d878961.

📒 Files selected for processing (3)
  • docs/todo-summary.md
  • docs/todo10.md
  • src/cli-docs-lint/src/priority_inversion.rs
✅ Files skipped from review due to trivial changes (2)
  • docs/todo-summary.md
  • docs/todo10.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/cli-docs-lint/src/priority_inversion.rs

📝 Walkthrough

Walkthrough

このPRはタスク優先度テーブルの依存関係を検証する「priority_inversion」チェッカーを新規実装し、CLIツールに統合しました。同時にタスク管理ドキュメントを更新して、新しい計画(proptest導入、ADR作成)を記録し、完了済み項目を削除しています。

Changes

Priority Inversion チェッカーと関連ドキュメント更新

Layer / File(s) Summary
チェッカー実装とテスト
src/cli-docs-lint/src/priority_inversion.rs
Markdown テーブルをパースして順位と Tier を抽出、依存関係の参照から逆転(優先度の低い依存先)を検出するロジックを実装。依存欄の なし 除外、順位 NN / 順位 NN/MM 抽出、参照先の Tier 引当、resolved マーカー検出ウィンドウとシャドー回避を含む。多数のユニットテストで振る舞いを網羅。
CLI統合とモード追加
src/cli-docs-lint/src/lib.rs, src/cli-docs-lint/src/main.rs
priority_inversion モジュールを公開、CheckMode enum に PriorityInversion を追加。--check priority-inversion の解析、run() での呼び出し、ヘルプと describe_mode() 表示を対応。
タスク管理ドキュメント更新
docs/todo-summary.md, docs/todo10.md, docs/todo3.md
todo-summary.md で完了済み項目(順位 19 REJECT-ESCALATE)を削除し、新規タスク 2 件(順位 197-198:hooks-session-start の proptest、ADR-NNN Timestamp invariant safety)を追加。todo10.md に新タスクの詳細計画と完了基準を追記。todo3.md から関連エントリを削除。

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • aloekun/claude-code-hook-test#133: 本PR のチェッカーが解析する docs/todo-summary.md テーブル形式の構造とアンカー定義をPR#133で初期化・整備されており、チェッカー実装との直接的な依存関係がある。
  • aloekun/claude-code-hook-test#192: 本PR のチェッカーが検証対象とするタスク優先度・依存関係の更新(ADR-031フェーズEのランディング整理)を PR#192 で実施し、本PR のチェッカーがその結果の整合性を検証する関係。
  • aloekun/claude-code-hook-test#92: 本PR と PR#92 の両者で docs/todo3.md の「takt ハーネス REJECT-ESCALATE(PR#91系)」todo エントリを扱い、ADR-033 方針に沿った表記修正と当該エントリ削除という同一文脈の差分が関連している。
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes: adding a priority_inversion validator to cli-docs-lint, retiring task rank 19, and documenting adoption of T2-1/T3-2 feedback recommendations.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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

📥 Commits

Reviewing files that changed from the base of the PR and between 1db7c59 and 85159b5.

📒 Files selected for processing (6)
  • docs/todo-summary.md
  • docs/todo10.md
  • docs/todo3.md
  • src/cli-docs-lint/src/lib.rs
  • src/cli-docs-lint/src/main.rs
  • src/cli-docs-lint/src/priority_inversion.rs
💤 Files with no reviewable changes (1)
  • docs/todo3.md

Comment thread src/cli-docs-lint/src/priority_inversion.rs
aloekun added 2 commits June 8, 2026 21:04
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)
@aloekun
aloekun force-pushed the priority-inversion-and-task-cleanup branch from 85159b5 to d878961 Compare June 8, 2026 12:12
@aloekun

aloekun commented Jun 9, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@aloekun
aloekun merged commit 90306c3 into master Jun 9, 2026
1 check passed
@aloekun
aloekun deleted the priority-inversion-and-task-cleanup branch June 9, 2026 03:31
aloekun added a commit that referenced this pull request Jun 10, 2026
)

- 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 から見ても一貫性なし。
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