Skip to content

feat(hooks): takt persona-without-model lint rule (順位 39 / D-4)#150

Merged
aloekun merged 3 commits into
masterfrom
feat/takt-persona-model-lint
May 13, 2026
Merged

feat(hooks): takt persona-without-model lint rule (順位 39 / D-4)#150
aloekun merged 3 commits into
masterfrom
feat/takt-persona-model-lint

Conversation

@aloekun
Copy link
Copy Markdown
Owner

@aloekun aloekun commented May 12, 2026

Summary

Phase D D-4 として 順位 39 (PR #98 post-merge-feedback Tier 1 #1) の takt-workflow-persona-without-model lint rule を実装。Bundle Z #B-α と同じ決定論的防止層 (ADR-007 正規表現層)。

当初 D-4 = 順位 47 (> vs >= boundary lint) を予定していたが、着手前検証 (memory rule feedback_verify_task_not_already_done) で PR #126 (b677b9d4f54d) で既に land 済 を発見し、D-5 から 順位 39 を D-4 に繰上げ、D-5 を 順位 56 + 119 bundle に再構成。詳細は docs/local-llm-offload-analysis.md L295-299 参照。

Commit 構成

  1. 12d11c96 — docs(todo,analysis): D-4 を 順位 39 に re-pivot + stale 順位 47 entry 削除
  2. 0c2cc07d — feat(hooks-post-tool-linter): takt-workflow-persona-without-model lint rule

変更内容 (commit 2)

新規 lint rule ⑨ (.claude/custom-lint-rules.toml)

  • id: takt-workflow-persona-without-model
  • pattern: multi-line regex で persona: 直後の field 行が model: 以外なら fire
  • enumeration 方式で takt yaml の sibling field 列挙 (Rust regex lookahead 非対応の pragmatic 対処)
  • extensions=[yaml] + paths=[.takt/workflows/*.yaml] で範囲限定 (順位 102 / PR feat(hooks-post-tool-linter): paths filter + Phase D 初 real lint_screen dogfood (順位 102) #148 の paths filter 活用)
  • severity = error / fix strategy = "model: <sonnet|haiku|opus> を追加"

Clean baseline (3 yaml site に model: sonnet 追加)

  • .takt/workflows/post-pr-review.yaml:24 (judge block in loop_monitor)
  • .takt/workflows/post-pr-review.yaml:119 (supervise step、Bundle Y2 完全性)
  • .takt/workflows/pre-push-review.yaml:27 (judge block in loop_monitor)

Unit tests (6 件、src/hooks-post-tool-linter/src/main.rs)

  • takt_workflow_persona_detects_judge_block_violation
  • takt_workflow_persona_detects_supervise_step_violation
  • takt_workflow_persona_skips_when_model_directly_follows (clean baseline)
  • takt_workflow_persona_detects_multiple_violations_in_same_file
  • takt_workflow_persona_skips_non_yaml_extension
  • deployed_takt_workflows_have_clean_baseline_for_persona_model_rule (regression test)

Phase D D-4 dogfood metrics

LINT_SCREEN_ENABLED=true で push を実行。.takt/lint-screen-report.md の結果:

Metric 観測値
screen_decision informational
findings 件数 0
fallback_reason なし (clean run)
## Diagnostic section 不在 = num_ctx 32768 で overflow 発生せず
pre-push pipeline 総 latency 645s
takt review iter 1 (3m 28s)、simplicity + security 両 APPROVED
kill-switch (fallback > 50%) fallback 0/1 = 0% → 基準内

D-4 観測の意義:

  1. informational verdict の初観測: D-3 は auto_fix + 1 false positive、D-4 は informational + 0 findings = lint-screen が「指摘なし」と判定する経路を実証
  2. clean run + num_ctx 余裕: ~530 行 (Cargo.lock 等含む) Rust + toml + yaml mix diff で overflow なし
  3. diff profile multiplicty: Rust impl (lint rule + tests) + TOML (rule entry) + YAML (3 clean baseline) の heterogeneous diff を lint_screen が「指摘なし」と正しく判断
  4. Round 2 (D-4〜D-7) 累積 PR data 進捗: 2/4 PR 観測完了 (D-3 + D-4)、残り D-5/D-6/D-7

Test plan

  • cargo test -p hooks-post-tool-linter --bin hooks-post-tool-linter で 108 tests pass (前 102 + 新 6)
  • cargo fmt --check で新規追加コードは rustfmt clean
  • pnpm build:all で deploy 用 exe 更新成功
  • LINT_SCREEN_ENABLED=true pnpm push で pre-push pipeline 完走 (simplicity + security 両 APPROVED、1 iteration 3m 28s)
  • .takt/workflows/*.yaml 全 file が clean baseline 維持 (deployed_takt_workflows_have_clean_baseline_for_persona_model_rule test で機械検証)

Out of scope

  • 派生プロジェクト (techbook-ledger / auto-review-fix-vc) への deploy: 別途 pnpm deploy:hooks 実行で対応
  • D-5/D-6/D-7 着手: 本 PR land 後の別 PR で順次対応

関連

  • 順位 39 spec: docs/todo4.md L265
  • Round 2 計画: docs/local-llm-offload-analysis.md §1 Phase D Round 2 table
  • ADR-007: hooks/カスタムリンターの正規表現層 / AST 層線引き

Summary by CodeRabbit

  • New Features
    • 追加:ワークフローの persona: に対する model: 明示を検証するカスタムリントルール
  • Chores
    • 更新:いくつかのワークフロー設定で監督者ペルソナに model: sonnet を明示
  • Tests
    • 追加:新ルールの動作を検証するユニットテスト群
  • Documentation
    • 更新:進捗状況、Phase D/E 計画およびタスク一覧の修正・整理

Review Change Stack

aloekun added 2 commits May 13, 2026 04:08
順位 47 (>vs>= boundary lint) は PR #126 (commit b677b9d, 2026-05-08) で
no-time-field-strict-greater rule として既に land 済 (custom-lint-rules.toml
line 208-243) を D-4 着手前検証で発見。memory rule feedback_verify_task_not_already_done
を適用して stale todo entry を削除し、D-4 を Round 2 計画から 順位 39 (takt workflow
`model` 必須化 lint rule) に繰上げ、D-5 を 順位 56 + 119 bundle に再構成。

変更:
- docs/local-llm-offload-analysis.md: D-4/D-5 row 更新 + 想定リスク に re-pivot 経緯追記
- docs/todo7.md: stale 順位 47 entry (38 行) 削除
- docs/todo-summary.md: 順位 47 row 削除

Phase E 着手前提 (5 PR 累積 dogfood) は変わらず、D-4〜D-7 で 4 PR 追加観測の方針継続。
…t rule (順位 39 / Phase D D-4)

PR #98 post-merge-feedback Tier 1 #1 採用。takt workflow yaml で persona: を持つ step
に model: 未指定の場合を検出する custom lint rule (ルール⑨)。Bundle Z #B-α と同じ
決定論的防止層 (ADR-007 正規表現層)。

実装:
- .claude/custom-lint-rules.toml: 新規 rule takt-workflow-persona-without-model
  - pattern: multi-line regex で persona: 直後の field 行が model: 以外なら fire
  - field enumeration 方式 (Rust regex lookahead 非対応の pragmatic 対処)
  - extensions=[yaml] + paths=[.takt/workflows/*.yaml] で範囲限定 (順位 102 PR #148 で
    実装した paths filter を利用)
- .takt/workflows/post-pr-review.yaml: 2 site に model: sonnet 追加で clean baseline
  - line 23: judge block (loop_monitor) の persona: supervisor 直下
  - line 117: supervise step の persona: supervisor 直下 (Bundle Y2 完全性)
- .takt/workflows/pre-push-review.yaml: 1 site に model: sonnet 追加で clean baseline
  - line 26: judge block (loop_monitor) の persona: supervisor 直下
- src/hooks-post-tool-linter/src/main.rs: unit tests 6 件追加
  - takt_workflow_persona_detects_judge_block_violation
  - takt_workflow_persona_detects_supervise_step_violation
  - takt_workflow_persona_skips_when_model_directly_follows (clean baseline)
  - takt_workflow_persona_detects_multiple_violations_in_same_file
  - takt_workflow_persona_skips_non_yaml_extension (extensions filter)
  - deployed_takt_workflows_have_clean_baseline_for_persona_model_rule (regression test)

Phase D D-4 dogfood: real diff として lint_screen の dogfood data 蓄積を目的。
Round 2 計画 (D-3 + D-4〜D-7 = 累積 5 PR) の 2 PR 目。

cargo test: 108 passed (前 102 + 新 6)。
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 12, 2026

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: f3e461f3-ec38-4de3-a445-c6300469ee52

📥 Commits

Reviewing files that changed from the base of the PR and between 0c2cc07 and 1ec1568.

📒 Files selected for processing (2)
  • .claude/custom-lint-rules.toml
  • src/hooks-post-tool-linter/src/main.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/hooks-post-tool-linter/src/main.rs
  • .claude/custom-lint-rules.toml

📝 Walkthrough

Walkthrough

新しいカスタムlintルール takt-workflow-persona-without-model を追加し、taktワークフローの persona: 宣言に対して明示的な model: フィールド指定を強制します。既存の2つのワークフロー (post-pr-review.yamlpre-push-review.yaml) を更新してこのルールに準拠させ、新しいルール動作を検証する包括的なテストスイートを提供します。

Changes

Persona Model Lint Rule and Enforcement

Layer / File(s) Summary
Custom lint rule definition and documentation
.claude/custom-lint-rules.toml
新しいルール ⑨ takt-workflow-persona-without-model を定義します。.takt/workflows/*.yaml 内で persona: の直後に model: 以外のフィールドが続く場合を検出し、`model: <sonnet
Workflow configuration updates with explicit model specifications
.takt/workflows/post-pr-review.yaml, .takt/workflows/pre-push-review.yaml
post-pr-review.yamlpre-push-review.yamlloop_monitors judge および supervise step に対して、persona: supervisor を持つ箇所に model: sonnet を追加します。
Comprehensive test suite for persona-model requirement
src/hooks-post-tool-linter/src/main.rs
新しいカスタムルール用テストヘルパーと多数のテストケースを追加します。judge ブロック内での persona:instruction: 違反検出、supervise step 内での persona:policy: 違反検出、model: 直後の合格判定、複数違反検出、非yaml拡張子での無視、本番ワークフロー群のベースライン検証を確認します。
Documentation and planning updates
docs/local-llm-offload-analysis.md, docs/todo-summary.md, docs/todo7.md
ローカルLLMオフロード分析の進捗・Phase 更新、Round 2 延長計画追記、todo テーブルからのエントリ削除とタスク順序の調整を行います。

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • aloekun/claude-code-hook-test#126: 同じカスタムlintシステムに新ルールを追加し、.claude/custom-lint-rules.toml とテスト拡張を行っている点で関連があります.
  • aloekun/claude-code-hook-test#148: src/hooks-post-tool-linter/src/main.rs のルールコンパイル/マッチパイプライン変更を含み、本PRのユニットテストがそれを前提としている可能性があります.
🚥 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 プルリクエストのタイトルは「feat(hooks): takt persona-without-model lint rule (順位 39 / D-4)」であり、変更セットの主要な内容である takt-workflow-persona-without-model カスタムリントルールの実装を明確に説明しています。
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.

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.

Actionable comments posted: 2

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

2036-2042: ⚡ Quick win

テスト用ルールの正規表現ハードコードは設定とのドリフト源です

ここで正規表現を複製すると、.claude/custom-lint-rules.toml 更新時にテストが古いまま残るリスクがあります。id = "takt-workflow-persona-without-model" を TOML から読み出してテストに使う形へ寄せるのが安全です。

差分イメージ
-    fn takt_workflow_persona_without_model_rule() -> CustomRule {
-        make_test_rule(
-            "takt-workflow-persona-without-model",
-            r"...",
-            &["yaml"],
-        )
-    }
+    fn deployed_rule_by_id(id: &str) -> CustomRule {
+        let path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
+            .join("..").join("..").join(".claude").join("custom-lint-rules.toml");
+        let content = std::fs::read_to_string(&path).expect("read custom-lint-rules.toml");
+        let config: CustomRulesConfig = toml::from_str(&content).expect("parse custom rules");
+        config.rules
+            .unwrap_or_default()
+            .into_iter()
+            .find(|r| r.id == id)
+            .expect("rule id not found")
+    }
🤖 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 2036 - 2042, The test
currently hardcodes the rule id and regex in
takt_workflow_persona_without_model_rule; change it to read the rule definition
(at least the id, preferably the regex) from the custom rules TOML so the test
stays in sync: modify takt_workflow_persona_without_model_rule to lookup the
entry with id "takt-workflow-persona-without-model" from the parsed
.claude/custom-lint-rules.toml (reuse existing TOML parsing logic if available),
then call make_test_rule using the retrieved id and pattern instead of the
inline string/regex.
🤖 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 @.claude/custom-lint-rules.toml:
- Line 318: The regex pattern variable (pattern) used to detect a persona:
followed by certain keys is missing several valid keys (e.g., output_contracts,
pass_previous_response, required_permission_mode, parallel), causing false
negatives; update the pattern string so the alternation after persona: includes
those missing keys (and any other current keys used in persona blocks) so that
lines like "persona: <name>" followed by those keys are matched; ensure the
updated pattern still uses the same (?m) and anchors and preserves whitespace
handling used in the original pattern.

In `@docs/local-llm-offload-analysis.md`:
- Line 5: The document asserts future progress on "2026-05-13" (e.g., references
to "Phase d Round 2", "着手", "着手中", "追加済み前提" under the "状態" / Phase sections) as
if already completed; change those statements into planned language or separate
planned vs actual sections: replace assertive verbs like "着手/追加済み" with
"予定/着手予定" (or add "(予定)") for every occurrence of the date string "2026-05-13",
add a clear "更新基準日: 2026-05-12" header, and explicitly split content into "実績"
(completed items) and "計画/予定" (future items) so the Phase d/Phase d Round 2 and
Phase c+ mentions are not presented as accomplished.

---

Nitpick comments:
In `@src/hooks-post-tool-linter/src/main.rs`:
- Around line 2036-2042: The test currently hardcodes the rule id and regex in
takt_workflow_persona_without_model_rule; change it to read the rule definition
(at least the id, preferably the regex) from the custom rules TOML so the test
stays in sync: modify takt_workflow_persona_without_model_rule to lookup the
entry with id "takt-workflow-persona-without-model" from the parsed
.claude/custom-lint-rules.toml (reuse existing TOML parsing logic if available),
then call make_test_rule using the retrieved id and pattern instead of the
inline string/regex.
🪄 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: 53779dbf-24fe-4e94-9d71-06ae9c33a798

📥 Commits

Reviewing files that changed from the base of the PR and between 0ec4bd5 and 0c2cc07.

📒 Files selected for processing (7)
  • .claude/custom-lint-rules.toml
  • .takt/workflows/post-pr-review.yaml
  • .takt/workflows/pre-push-review.yaml
  • docs/local-llm-offload-analysis.md
  • docs/todo-summary.md
  • docs/todo7.md
  • src/hooks-post-tool-linter/src/main.rs
💤 Files with no reviewable changes (2)
  • docs/todo-summary.md
  • docs/todo7.md

Comment thread .claude/custom-lint-rules.toml Outdated
Comment thread docs/local-llm-offload-analysis.md
…ds 追加 (PR #150 CR Major)

CodeRabbit Major finding (#150 (comment)):
persona 直後の field 列挙 から output_contracts / pass_previous_response /
required_permission_mode / parallel が漏れていた = false negative リスク。
4 fields を pattern alternation に追加し regression test も同梱。

変更:
- .claude/custom-lint-rules.toml: ルール⑨ pattern alternation に 4 fields 追加
- src/hooks-post-tool-linter/src/main.rs: 同期更新 + 新 test
  takt_workflow_persona_detects_required_permission_mode_violation で
  pre-push-review.yaml fix step (persona: coder → required_permission_mode:)
  pattern が検出されることを assert

cargo test: 109 passed (前 108 + 新 1、CR Major regression test)

CR Minor (line 5、未来日進捗) は project local time (JST) と CR UTC の時差解釈
ギャップに起因 (CR 時点 = 2026-05-12 20:04 UTC = 2026-05-13 05:04 JST)。
2026-05-13 は session-start hook が認識する local 今日であり、'着手' は本 PR で
発生した事実。project 内既存 PR land 日付も全て local time (timezone qualifier 無し)
で記載しており、本 PR の追記のみ qualifier 付与は逆に不整合を生む。
別 reply で resolved として close する。
@aloekun
Copy link
Copy Markdown
Owner Author

aloekun commented May 13, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 13, 2026

✅ Actions performed

Review triggered.

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 39ae2cd into master May 13, 2026
1 check passed
@aloekun aloekun deleted the feat/takt-persona-model-lint branch May 13, 2026 03:51
aloekun added a commit that referenced this pull request May 13, 2026
… test (#151)

* feat(hooks): Phase D D-5 — comment-lint test 拡充 + MAX_CUSTOM_VIOLATIONS outer/inner break test (順位 56 + 119)

## D-5 実装 (順位 56 + 119 bundle)

### 順位 56: comment-lint hook test 拡充 (PR #104 T2-1+T2-2 bundle)

`src/hooks-post-tool-comment-lint-rust/src/main.rs`:
- UTF-8 multi-byte test 5 パターン追加: 漢字 + ASCII 混合 / 漢字単独 / emoji / BMP 外
  文字 (𝕊) / 結合文字 (e + U+0301)
- Block comment boundary test 6 パターン追加: 複数行 (start/end/middle 被覆) + 単行
  block comment (exact / starts-at / ends-at) で `span_overlaps_ranges` の
  inclusive-bounds 区間交差判定を体系化
- 既存 1 パターンずつのテストは保持 (regression 防止)

### 副産物: `byte_offset_to_line` char-boundary panic fix

UTF-8 漢字単独パターン test 着手時に発見した production bug を修正:

- 旧: `source[..clamped].bytes()` は `clamped` が char boundary でない場合 panic
- 新: `source.as_bytes()[..clamped].iter()` で byte slice 経由に変更 (char boundary 不要)
- 影響: needle 末尾が multi-byte 文字の場合 (例: 「漢字のみのコメント」を Edit/Write の
  new_string として渡す現実シナリオ) で hook が panic していたのを修正
- direct unit test `byte_offset_to_line_handles_mid_multibyte_offset` を追加して bug
  location を pinpoint

### 順位 119: MAX_CUSTOM_VIOLATIONS outer/inner loop break scope explicit test

`src/hooks-post-tool-linter/src/main.rs`:
- `run_custom_rules_outer_break_skips_subsequent_rules`: rule_a 単独で 21 件 →
  cap で 20 件、rule_b は呼ばれない (全 violation が "RULE_A") を assert
- `run_custom_rules_inner_cap_after_partial_first_rule`: rule_a 19 件 + rule_b 1 件 =
  20 件 (rule_b の inner break が mid-rule で発火) を type 分布で検証
- PR #148 で発見した `run_custom_rules` refactor の outer/inner loop break scope を
  test net で固定化

## test 結果

- hooks-post-tool-comment-lint-rust: 85 passed (前 84 + 新 1 direct unit + 11 integration)
- hooks-post-tool-linter: 111 passed (前 109 + 新 2)
- 合計 196 tests pass

## docs 整理

- docs/todo7.md: 順位 56 entry 削除
- docs/todo8.md: 順位 119 entry 削除
- docs/todo-summary.md: 順位 56 / 119 行削除
- docs/local-llm-offload-analysis.md: D-5 row を ✅ 着手済 に更新、bug fix を副産物として明記

## 並行: PR #150 post-merge-feedback 登録 (本セッション前から @ に含まれていた変更)

- docs/todo8.md: 順位 120 (rule comment + ADR-007 case study) / 順位 121 (4 fields
  個別 fixture test) / 順位 122 (development-workflow.md Step 0 stale entry 確認 step) 登録
- docs/todo-summary.md: 3 行追加

## Phase D 累積状況

D-3 (PR #148) + D-4 (PR #150) + D-5 (本 PR) = 3 PR 完了、Phase E 着手要件 (5 PR 累積)
まであと 2 PR (D-6 + D-7)。本 PR の dogfood は push 時に `LINT_SCREEN_ENABLED=true`
で opt-in 観測予定。

* docs(analysis): Phase D D-5 dogfood outcome を記録 (lint_screen 4 件目の data point)
aloekun added a commit that referenced this pull request May 18, 2026
…検出 hook 2 段構え)

## 順位 39 削除

順位 39 (takt workflow `model` フィールド必須化 lint rule) は PR #150 で
`takt-workflow-persona-without-model` rule として実装済のため、todo-summary.md
table 行と todo4.md 詳細 entry を削除。

調査の過程で、stale entry 候補 3 件のうち以下 2 件は既に削除済と判明:

- 順位 104 (ADR-007 amendment): PR #161 で既削除
- 順位 126 (ADR-038 hallucinate codify): PR #156 (Phase E) で ADR-038
  migrate + 詳細 entry 削除済

## 順位 136 新規追加 (Tier 1)

本セッション (PR cleanup-stale-rank-39 作業中) で実証された failure mode:
local working copy が stale parent (master と sibling) のまま docs/todo*.md を
読み込み、master 上で既に削除済の entry 2 件を「stale entry として削除する」と
誤判定。memory rule `feedback_verify_task_not_already_done.md` は強制力ゼロで
再発確実 (memory rule 全般の限界、`feedback_no_unenforced_rules.md` 原則の
自己事例)。Claude Code Web との並列セッション運用前提下では構造的再発確実。

structural defense として 2 hook 二段構え:

- 案 A (予防層): SessionStart hook で `jj git fetch` + master との lineage を
  additional context として AI 出力
- 案 B (最終 backstop): PreToolUse hook で stale parent 時の docs/todo*.md edit
  を hard block

`feedback_no_unenforced_rules.md` 例外条件 = 2 つの hook で機械強制可能。
ADR-039 experimental pattern 適用予定。
aloekun added a commit that referenced this pull request May 18, 2026
…検出 hook 2 段構え) (#162)

## 順位 39 削除

順位 39 (takt workflow `model` フィールド必須化 lint rule) は PR #150 で
`takt-workflow-persona-without-model` rule として実装済のため、todo-summary.md
table 行と todo4.md 詳細 entry を削除。

調査の過程で、stale entry 候補 3 件のうち以下 2 件は既に削除済と判明:

- 順位 104 (ADR-007 amendment): PR #161 で既削除
- 順位 126 (ADR-038 hallucinate codify): PR #156 (Phase E) で ADR-038
  migrate + 詳細 entry 削除済

## 順位 136 新規追加 (Tier 1)

本セッション (PR cleanup-stale-rank-39 作業中) で実証された failure mode:
local working copy が stale parent (master と sibling) のまま docs/todo*.md を
読み込み、master 上で既に削除済の entry 2 件を「stale entry として削除する」と
誤判定。memory rule `feedback_verify_task_not_already_done.md` は強制力ゼロで
再発確実 (memory rule 全般の限界、`feedback_no_unenforced_rules.md` 原則の
自己事例)。Claude Code Web との並列セッション運用前提下では構造的再発確実。

structural defense として 2 hook 二段構え:

- 案 A (予防層): SessionStart hook で `jj git fetch` + master との lineage を
  additional context として AI 出力
- 案 B (最終 backstop): PreToolUse hook で stale parent 時の docs/todo*.md edit
  を hard block

`feedback_no_unenforced_rules.md` 例外条件 = 2 つの hook で機械強制可能。
ADR-039 experimental pattern 適用予定。
aloekun added a commit that referenced this pull request May 21, 2026
…e-feedback 3 件統合) (#167)

* docs(todo): 順位 139 新規追加 — PR #166 post-merge-feedback 採用 (exe-help-block system exe FP negative test)

* test(hooks-pre-tool-validate): 順位 139 — exe-help-block system exe negative test 追加

PR #166 post-merge-feedback で 3 独立ソース (PR diff / Session / Pre-push:simplicity)
で同時指摘された systemic pattern への対策。takt-fix で regex は
`(?:cli-[\w-]+|hooks-[\w-]+|check-ci-[\w-]+)\.exe` に narrowed 済だが、
既存 `exe_help_block_allows_unrelated_exe` は `foo.exe` の架空名のみで実在
system exe を未検証。将来 regex を broad pattern に戻した場合の silent regression を
test 層で明示的に検出する目的で、cargo/python/node/notepad の 4 件 negative test を追加。

* test(hooks-post-tool-linter): 順位 121 — takt_workflow_persona 3 fields 個別 fixture test 追加 + doc 修正

PR #150 CR Major fix で persona: alternation に追加された 4 fields のうち、
従来 regression test は `required_permission_mode` の 1 case のみで、
doc comment は「4 fields regression test」と主張しつつ実態と乖離していた。

本 commit で:
- 既存 `takt_workflow_persona_detects_required_permission_mode_violation` の doc を
  実態に合わせて「代表 case」表現に修正、残り 3 fields は個別 test で検証する旨を明記
- `pass_previous_response` / `output_contracts` / `parallel` の個別 fixture test を追加
- `.claude/custom-lint-rules.toml` の `[rules.test_coverage.main_ext_tests.yaml]` に
  3 件の新 test 名を登録 (rule test coverage check で機械強制される宣言)

将来 alternation から個別 field を誤って削除した場合に test fail で検出される
safety net を確保。

(順位 121、PR #150 T2-#1 採用)

* docs(adr): 順位 120 — rule⑨ コメント拡張 + ADR-007 に enumeration-based pattern case study 追記

PR #150 CR Major fix で「persona: alternation の列挙漏れ」が発生した経験を踏まえ、
takt yaml schema 拡張時の rule 更新フローを 2 箇所に codify:

(1) `.claude/custom-lint-rules.toml` rule⑨ 上部に「Field 拡張手順」4 ステップを追記
    (grep で sibling field を抽出 → alternation 追加 → test helper 追加 → fixture test +
     [rules.test_coverage] 宣言追加 → cargo test 確認)
(2) `docs/adr/adr-007-custom-linter-layer-boundary.md` に Case study section を追加
    (Rust regex の lookahead 非対応 → enumeration-based negation 採用の判断経緯 +
     列挙漏れリスクへの多層防御 + 同型 rule 設計時の checklist)

順位 121 (個別 fixture test) と 順位 120 (本 commit) で「規約 → test → 保守手順」の
3 層が完成し、次回 takt yaml schema 拡張時の rule 更新フローが文書化される。

(順位 120、PR #150 T1-#1 採用、analyzer Tier 1 → ユーザー判断で Tier 3 reclassify)

* docs(todo): 順位 120 / 121 / 139 完了に伴い削除 (Bundle l land)

PR #150 + #166 post-merge-feedback 採用 3 件 (Bundle l: Custom lint rule test gap closure)
が同 PR で land 完了したため、対応する todo entry を削除:

- 順位 139 (exe-help-block system exe negative test): commit 3049f56 で 4 件 negative test 追加
- 順位 121 (takt_workflow_persona 3 fields fixture test): commit bfab173 で 3 件 fixture test 追加 +
  doc 修正 + .claude/custom-lint-rules.toml の [rules.test_coverage.main_ext_tests.yaml] 宣言更新
- 順位 120 (rule⑨ コメント拡張 + ADR-007 case study): commit a2df865 で field 拡張手順 4 ステップ追記 +
  ADR-007 に enumeration-based pattern case study section 追加

todo-summary.md / todo8.md から該当 entry を一括削除。残存 task の優先順位に影響なし。
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