diff --git a/.takt/facets/instructions/fix.md b/.takt/facets/instructions/fix.md index 732c6df..d6b5dce 100644 --- a/.takt/facets/instructions/fix.md +++ b/.takt/facets/instructions/fix.md @@ -53,6 +53,19 @@ The helper compares pre-fix (`@-`) vs post-fix (working copy) and exits non-zero New files (post-only) are reported `metrics_check: skipped` and do not block fix completion. Markdown / yaml / PowerShell etc. files are not in scope (Rust-only PoC). +## Pre-completion diff refresh (REQUIRED — fix→review iteration freshness) + +After completing all fixes (Edit/Write operations) AND before emitting the `convergence_verdict` line, refresh `.takt/review-diff.txt` so the next reviewer iteration (if `convergence_verdict: partial`) sees the post-fix state: + + jj diff -r @ > .takt/review-diff.txt + +This refresh is **unconditional**: + +- **`convergence_verdict: partial`** — critical. Without refresh, reviewers in the next iteration read the pre-fix snapshot taken by `cli-push-runner` Stage 1.5 and produce false-positive `persists` findings on already-fixed code, escalating the loop to 6-iter outliers (PR #103 observation). +- **`convergence_verdict: fully_resolved`** — harmless. The next workflow step is COMPLETE, so the refreshed file is not consumed; the ~1s `jj diff` cost is negligible. + +`.takt/review-diff.txt` is **not** in any read-only zone (the read-only list at the top of this instruction covers `.takt/runs/**`, `.takt/facets/**`, `.takt/workflows/**`, `.takt/config.yaml` — `.takt/review-diff.txt` lives at the `.takt/` root and is an explicitly allowed write target for this step). + ## Required output (include headings) ## Work results diff --git a/docs/local-llm-offload-analysis.md b/docs/local-llm-offload-analysis.md index 5fa7cbd..9ace5d0 100644 --- a/docs/local-llm-offload-analysis.md +++ b/docs/local-llm-offload-analysis.md @@ -281,7 +281,7 @@ Round 1 で実 dogfood data point が **1 件のみ** (D-3) に留まり、ADR-0 |---|---|---|---|---|---| | **D-4** ✅ | 順位 39 単独 = takt workflow `model` 必須化 lint rule + 副次作業 (`.takt/workflows/*.yaml` の `persona:` 行 3 件に `model:` 明示追加で clean baseline 確保) + CR Major fix で 4 fields 追加 | T1 / S | 実 ~340 行 (commit 0c2cc07d + 1ec15686) | Rust lint rule (yaml multi-line regex、enumeration 方式) + 6+1 unit tests + custom-lint-rules.toml entry + 3 yaml site touch + CR Major fix | **PR #150 merged 2026-05-13、初 real lint_screen 観測 2 data points (initial + CR fix push)** | | **D-5** ✅ | 順位 56 + 119 bundle = comment-lint hook test 拡充 + `MAX_CUSTOM_VIOLATIONS` outer/inner loop break scope explicit test + 副産物として `byte_offset_to_line` の char-boundary panic bug fix | T2+T2 / S+S | 実 ~120 行 (test 12 件追加 + production fix 1 行) | hooks-post-tool-comment-lint-rust + hooks-post-tool-linter test infra (UTF-8 multi-byte 5 + block boundary 6 + multi-rule MAX cap 2 + direct unit test 1) | **着手済** | -| **D-6** | 順位 51 単独 = `.takt/review-diff.txt` を fix→review iteration 間で refresh | T1 / M | ~400-580 | cli-push-runner Rust impl + iteration logic refactor + integration tests | 未着手 | +| **D-6** | 順位 51 単独 = `.takt/review-diff.txt` を fix→review iteration 間で refresh (案 A takt hook 不可と判明 → 案 C fix.md instruction-level refresh に pivot) | T1 / M→S | 実 ~80 行 (fix.md 追記 + todo7.md / analysis.md 更新) | takt facet instruction (markdown) + design docs | **着手済 (本 PR、impl 完了 / dogfood pending)** | | **D-7** | Bundle c-1 (順位 63 + 64 + 67) = cli-merge-pipeline Drop guard / signal handler + orphan run reaper + ADR-030 spec amendment | T1×2 + T3 / M+M+XS | ~600-800 | Rust impl + signal trap + reaper logic + ADR markdown | 未着手 | **size ramp-up 設計 (Round 2)**: small → small-mid → mid → mid-large で num_ctx 32768 容量限界に向け漸増、各 size 帯で fallback 発生率 / Phase A diagnostic warn log 出力有無を観測。D-3 (mid, 496 行) と組合せて 5 size 帯をカバー。 diff --git a/docs/todo-summary.md b/docs/todo-summary.md index 8c23081..643ba1a 100644 --- a/docs/todo-summary.md +++ b/docs/todo-summary.md @@ -77,6 +77,11 @@ | 120 | 💎 Tier 3 | **`takt-workflow-persona-without-model` rule コメント拡張 + ADR-007 case study 追記 (PR #150 T1-#1 採用、実体 Tier 3 — analyzer 誤分類)** | todo8.md | XS | なし (実体は docs/comment 修正のみで mechanical enforcement なし → Tier 3 reclassify。次回 takt yaml schema 拡張時の rule 更新フロー文書化 + enumeration-based pattern の case study 記録、Tier 1 #2 ADR case study と同 PR で land 効率的) | | 121 | 🔧 Tier 2 | **`takt_workflow_persona_detects_required_permission_mode_violation` doc 修正 + 残り 3 fields 個別 fixture test 追加 (PR #150 T2-#1 採用)** | todo8.md | S | なし (4 fields のうち 3 fields は個別 fixture test 不在、doc comment と実態乖離。pass_previous_response / output_contracts / parallel の individual test を追加して将来 regex 変更時の regression 検知を担保) | | 122 | 💎 Tier 3 | **`development-workflow.md` Step 0 に「新 todo 着手前の既実装確認」チェックステップ追加 (PR #150 T3-#1 採用)** | todo8.md | XS | なし (memory rule `feedback_verify_task_not_already_done.md` を canonical workflow へ昇格。`jj log --limit 20 ` は決定的コマンドのため `feedback_no_unenforced_rules.md` 例外 = 既存実践の明文化 + 機械実行可能で採用、グローバル設定変更前に `~/.claude/` バックアップ取得必須) | +| 123 | 🚀 Tier 1 | **lint-screen の Markdown ファイル除外フィルター追加 (PR #151 T1-#2 採用) ★ Bundle k** | todo8.md | M | なし (D-3/D-4/D-5 の 3 PR で一貫観測した `.md` への `unused-import` hallucinate FP を構造的に解消。Phase D dogfood 観測から導かれた最も価値ある決定論的防止策、拡張子ベース mechanical filter で実装可能、Frequency High + Adoption Risk None) | +| 124 | 🚀 Tier 1 | **`no-ephemeral-todo-reference` rule の TOML positive test 追加 (PR #151 T1-#1 採用)** | todo8.md | S | なし (extensions 拡張が複数 PR にわたり反復する pattern (yaml/yml = PR #110、toml 等)、test gap 累積を構造的に防ぐ。Frequency Medium で採用基準を満たす) | +| 125 | 🔧 Tier 2 | **UTF-8 マルチバイト boundary test を他の string-processing hooks に横展開 (PR #151 T2-#1 採用)** | todo8.md | M | なし (PR #151 で `byte_offset_to_line` char-boundary panic bug を test 拡充で発見、同型関数を持つ他 hooks に systemic 防御を確保。test 拡充が production fault detection に直結する事例の横展開) | +| 126 | 💎 Tier 3 | **ADR-038 に mistral:7b 「diff 外 context hallucinate」failure mode を追記 (PR #151 T3-#1 採用、順位 123 と同 PR 推奨)** | todo8.md | XS | なし (3 PR 観測 = High freq の failure mode を ADR codify、Phase b' fixture では再現しない pattern のため永続記録の価値あり、順位 123 と同 PR で実装と仕様の整合性確保) | +| 127 | 💎 Tier 3 | **extensions 拡張時の test 追加 pattern をコード comment で明文化 (PR #151 T3-#2 採用、順位 124 と同 PR 推奨)** | todo8.md | XS | なし (`feedback_no_unenforced_rules.md` 例外 = 既存実践の明文化 + 機械強制ではなく guide 効果。順位 124 と同 PR で test location を正確に参照、順位 122 と同じロジック) | **戦略**: Tier 1 を 2〜3 セッションで片付け → Tier 2 で ADR-032 の前提 + rate-limit + convergence cost 削減を進める → Tier 3 で ADR-032 を land + ドキュメント整備。Tier 4-5 は cleanup / 外部展開で daily efficiency への直接効果は小さい。 @@ -117,3 +122,5 @@ **PR #114 (Bb-2 + 順位 75 = Bundle b PR-2 + T2-2) post-merge-feedback (2026-05-05)** ✅ 完了: 9 findings に対して **2 件採用 / 5 件様子見 / 3 件却下**。**Bb-3 (順位 55) で fold-in する採用提案**: T2-2 (Parity test coverage 拡張 = `finalize_park_siblings_have_symmetric_write_state_handling` テストに `finalize_initial_review_park` を追加、self-violation 解消、Effort S)。T2-1 (Legacy JSON deserialize test) は **PR #114 で既に実装済** (`state_legacy_json_without_new_fields_deserializes_with_defaults`、Bb-3 以降の新フィールド追加時に同 pattern を継続するための reference として保存)。**様子見 (5 件)**: T1-1 (finalize_* parity lint、Effort M + NLP 必要、簡易プロキシで再評価) / T1-2 (polling block lint、FP リスクで dogfood 後判断) / T2-3 (env override コメント強化、XS Low) / T2-4 (CI parallel race 確認、preventive only) / T3-1 (Wakeup Resume Invariant ADR) / T3-2 (DI 戦略 ADR、Bb-3 着手時に再検討)。**却下 (3 件)**: T1-3 (Serde schema lint、ROI 低、T2-1 で代替) / T3-3 (parity invariant の global rules 追加) / T3-4 (test-only env var prefix rule) — 後 2 件は **memory: feedback_no_unenforced_rules.md** を直接引用してアナライザが正しく即却下判定。Bb-2 land 時点で Bundle b の核 (CronCreate park モデル) 完成、残る Bb-3 は config 整理 + SessionStart catch-up + T2-2 follow-up を bundled。 **Bundle j (PR #133 post-merge-feedback、docs/ 整合性多層検証、2026-05-09)**: PR #133 (todo.md / todo5.md 50KB 分割) merge 後の post-merge-feedback で 9 findings 中 **3 件採用** (Tier 1 #1 / Tier 2 #3, #4) で **3 層対策**: (1) **規約層** = 順位 94 (`(?i)\]\(\.\./docs/` regex 1 行で `docs/` 配下からの逆戻り参照を block) は CodeRabbit が PR #133 で実検出した broken link を決定論的に防止、(2) **CI 検証層** = 順位 95 (preamble file count 自動照合) は todo*.md 分割が今後反復する pattern (todo3 → 4 → 5 → 6 → 7) のため Frequency Medium で採用、(3) **包括的 link 検証層** = 順位 96 (Markdown cross-reference validator、directory-aware resolution) は順位 10 (ADR-032 PR-broken-link) と方向性近接で fold-in 検討余地あり。**Sub-PR 構成**: **j-1 (順位 94、`.claude/custom-lint-rules.toml` 規約追加) は land 済 (Phase d P-2)** / j-2 (順位 95 + 96、`.github/workflows/lint.yml` 新設 = workflows 未存在 repo の最初の workflow 整備、Effort S+M、まとめて land が効率的)。**却下** (2 件): T1 #2 (prose 数詞 lint、NLP 必要 + FP 確実) / T3 #5/#6 (機械検知不可ルール追加、`feedback_no_unenforced_rules.md` 適用)。**様子見** (3 件): T3 #7 (ADR-035 not_applicable と GitHub thread state の乖離明文化、1 観測のみ) / T3 #8 (ADR-030 AFK wakeup 時 PR body intent ルール化、1 観測のみ) / T3 #9 (50KB 分割原則 CLAUDE.md 明文化、機械検知不可)。**本 PR 含意**: 順位 94 = 「決定論的防止層」哲学 (Bundle Z #B-α 系譜)、順位 95-96 = 「規約だけでは塞げない構造的検証は CI で」(ADR-031 週次レビューと相補)。`.github/workflows/` 未存在 repo に最初の workflow を追加する転換点でもあり、scope 慎重判断が必要。 + +**Bundle k (PR #151 post-merge-feedback、Phase D dogfood 観測由来の lint-screen FP 対策、2026-05-13)**: PR #151 (Phase D D-5 = comment-lint test 拡充 + MAX cap test) merge 後の post-merge-feedback で 11 findings 中 **5 件採用** (Tier 1 #1, #2 / Tier 2 #1 / Tier 3 #1, #2) を 5 entries (順位 123-127) で登録。**コア発見**: D-3 (PR #148) / D-4 CR fix (PR #150) / D-5 ×2 (PR #151) の 3 PR・4 push events で「mistral:7b が docs-only diff や `.md` ファイルに対して Rust の `unused-import` を hallucinate する」FP pattern が一貫して観測 = Phase b' fixture では再現しない failure mode。**順位 123 (lint-screen MD 除外フィルター、Tier 1 / M / High freq)** が最重要 = 拡張子ベース mechanical filter で構造的に解消可能、Phase D dogfood 観測から導かれた最も価値ある決定論的防止策。**Sub-PR 推奨**: k-1 (順位 123 + 126、実装 + ADR-038 codify、Effort M+XS、コア層) / k-2 (順位 124 + 127、TOML test + extensions code comment、Effort S+XS、test gap 補強層) / k-3 (順位 125、UTF-8 boundary 横展開、Effort M、独立) で 3 PR 分割推奨。**却下** (4 件): UTF-8 lint rule (FP リスク、AST 必須) / `byte_offset_to_line` 強化 (PR #151 で既対応) / UTF-8 guideline + extensions checklist (`feedback_no_unenforced_rules.md` 適用)。**様子見** (3 件): T2 #2 (lint-screen dogfood CI step、L effort + takt test infra 調査依存) / T3 #3 (test 拡充→bug 発見 pattern を ADR-007 記録、1 PR 観測のみ) / T3 #4 (multi-rule scenario fixture pattern を test comment 明文化、Low × Low)。**本 PR 含意**: Phase D dogfood 観測 (analysis.md L334-340) が直接 actionable な決定論的防止層 (順位 123) に結実、Phase E 採否判定前に systemic FP root cause が解消される構造的進展。 diff --git a/docs/todo7.md b/docs/todo7.md index 20f0708..12a0e41 100644 --- a/docs/todo7.md +++ b/docs/todo7.md @@ -64,27 +64,27 @@ > > **実行優先度**: 🚀 **Tier 1** — Effort M。takt 設定 / pre-push-review.yaml への hook 追加。 -#### 設計決定 (案) +#### 設計決定 (D-6 セッションで確定、2026-05-13) -- **refresh タイミング**: reviewer step 起動直前に diff を再生成 (fix step 完了直後の状態を反映) -- **実装方針 (2 案)**: - - **案 A: takt workflow の reviewer step に precondition step を挟む** — `.takt/workflows/pre-push-review.yaml` で `before:` / `pre-step:` 的な hook を使い、push-runner と同一の diff 生成コマンドを呼ぶ - - **案 B: cli-push-runner 側で fix step の終了を検出して diff を更新** — Rust コードで takt の step 進行を監視 (実装複雑度大) -- **推奨**: 案 A — takt config で完結、Rust 修正不要、影響範囲が pre-push-review.yaml のみ -- **diff 生成コマンド**: 既存 push-runner と同じロジック (`jj diff` ベース) を再利用、ファイルパス `.takt/review-diff.txt` も同一に保つ -- **冪等性**: 同 fix output から生成される diff は決定的なので複数回 refresh しても問題なし。途中失敗で diff が壊れても次 iteration の冒頭で上書きされる +- **refresh タイミング**: fix step が `convergence_verdict` を emit する直前に refresh (= 次 reviewer iteration が読み始める時点で post-fix 状態) +- **実装方針 (3 案を評価)**: + - **案 A: takt workflow の reviewer step に precondition step を挟む** — ❌ **不可**。takt v0.35.3 schema (`PieceMovement` / `PieceConfig`) を確認した結果、per-step `before:` / `pre-step:` / `hooks:` field は存在しない。piece レベルの `runtime.prepare` は workflow 開始時 1 回のみ実行され、step 間に挟まらない (`node_modules/.pnpm/takt@0.35.3/node_modules/takt/dist/core/models/piece-types.d.ts` Line 74-98 / `runtime-environment.js` Line 171-191) + - **案 B: cli-push-runner 側で fix step の終了を検出して diff を更新** — ❌ **scope 不適合**。`stages/takt.rs` は `run_cmd_inherit` で takt を spawn-and-wait するのみ。filesystem watcher で `.takt/runs//reports/*.md` の生成を監視する案は ~100-200 行の Rust + race condition 対応が必要で、AI-driven 案で塞げる範囲を超える複雑度 + - **案 C: fix.md instruction に "Pre-completion diff refresh" section を追加** — ✅ **採用**。既存の Bundle Z #B-β `Pre-completion deterministic check (Bundle Z Phase 2 / #B-β)` と同形の precedent あり (`scripts/fix-metrics-check.ps1` を Bash 呼び出しする pattern)。失敗 mode (= AI が refresh を skip) は現状と同等 (no regression) +- **採用案 C の実装**: `.takt/facets/instructions/fix.md` に「Pre-completion diff refresh (REQUIRED)」section を追加 (advisor 推奨)。`jj diff -r @ > .takt/review-diff.txt` を `convergence_verdict` emit 直前に必須実行 +- **共有 instruction の影響**: `fix.md` は pre-push-review.yaml と post-pr-review.yaml の両方で使用される。post-pr-review は `.takt/review-diff.txt` を読まないが、refresh は冪等で副作用なし (~1s 程度の `jj diff` invocation cost のみ) +- **派生プロジェクト deploy**: `scripts/deploy-hooks.ts` は exe + `settings.local.json` のみ転送し、`.takt/facets/instructions/*` は派生 (techbook-ledger / auto-review-fix-vc) 各自が管理。よって本変更の自動 propagate は不要 (手動 port が必要だが scope 外、follow-up task) #### 作業計画 -- [ ] takt workflow の hook 仕様 (`before:` / `pre-step:`) を確認 (`.takt/workflows/*.yaml` の他 facets / takt source を grep) -- [ ] case A 不可なら case B (cli-push-runner 改修) にフォールバック -- [ ] `.takt/review-diff.txt` の生成ロジックを単一場所に整理 (DRY、push-runner と shared util にする等) -- [ ] `.takt/workflows/pre-push-review.yaml` に refresh hook を追加 -- [ ] 単体動作確認: 意図的に DRY refactor 指摘 + fix を再現する synthetic シナリオで 3-iter 収束を確認 +- [x] takt workflow の hook 仕様を確認 → 案 A 不可と確定 +- [x] cli-push-runner の takt invocation 構造を確認 → 案 B も scope 不適合と確定 +- [x] advisor に方針相談 → 案 C (instruction-level) 採用 + 共有 instruction 影響 / deploy 経路を検証 +- [x] `.takt/facets/instructions/fix.md` に「Pre-completion diff refresh (REQUIRED)」section を追加 +- [ ] dogfood: D-6 PR push 自体で本 instruction が機能するかを観察 (fix step が refresh を実行 → 次 reviewer iter が post-fix 状態を読むか) - [ ] dogfood 1〜2 PR で実 6-iter outlier scenario が再発しないことを観測 -- [ ] Bundle Z Phase 2 (#B-β) との競合確認 (deterministic check は fix step 内部で動くため、本 task の fix→review 境界 refresh とは独立) -- [ ] 派生プロジェクト (techbook-ledger / auto-review-fix-vc) への deploy 確認 -- [ ] 本 todo7.md エントリを削除 +- [x] Bundle Z #B-β との競合確認: `fix-metrics-check.ps1` invocation は fix step 内部の Bash 実行で完結し、本 task の diff refresh は同 fix step の最終段 Bash 実行で独立。両者は時系列で順序通り走り競合なし +- [ ] 本 todo7.md エントリを削除 (PR D-6 merge + 1-2 PR の dogfood 完了後) #### 完了基準 @@ -92,9 +92,10 @@ - 6-iter outlier の発生率が **0%** に近づく (PR #103 のような scenario が 3-iter で収束) - supervisor の live Read 救済が不要になる (= supervisor step は workflow に残るが、false positive 救済責務が消える) -#### 詰まっている箇所 +#### 残課題 / dogfood リスク -- takt workflow の `before:` / `pre-step:` hook 仕様が公式 docs に明記されていない可能性 → 着手時に takt source / 既存 workflow yaml を grep して確認。 +- AI-driven 案の弱点: fix step の AI が refresh 命令を skip する可能性。Bundle Z #B-β `metrics_check` invocation の実行率を baseline として比較し、refresh 実行率 > 90% を初期目標とする。dogfood で実行率 < 90% なら **案 D (PostToolUse hook ベースの決定論層)** へ escalate を検討 +- 派生プロジェクト port: `~/.takt/facets/instructions/fix.md` (global) や techbook-ledger / auto-review-fix-vc の同等ファイルへの転載が follow-up task (本 task scope 外) --- diff --git a/docs/todo8.md b/docs/todo8.md index 416ebbb..2c9cb7f 100644 --- a/docs/todo8.md +++ b/docs/todo8.md @@ -159,3 +159,124 @@ - ephemeral 計画書 retire 時の permanent value 移管プロセスが checklist 化される --- + +### lint-screen の Markdown ファイル除外フィルター追加 (PR #151 T1-#2 採用、Bundle k) + +> **動機**: PR #148 (D-3) / PR #150 (D-4 CR fix) / PR #151 (D-5) の 3 PR で「mistral:7b が docs-only diff や `.md` ファイルに対して Rust の `unused-import` を hallucinate する」false positive pattern が一貫して観測。特に PR #151 では docs-only diff (analysis.md 67 行) でも同じ FP を再現し、reviewer が "the report documents its own false positive" と評価。**diff 内容ではなく hook source 周辺の context を見て hallucinate している強い証拠**。拡張子ベースの mechanical フィルタで diff 段階から `.md` ハンクを除外すれば、reviewer cross-check の負荷も軽減できる。 +> +> **本タスクの位置づけ**: PR #151 post-merge-feedback Tier 1 #2 採用 (Severity Medium / Frequency High / Effort M / Adoption Risk None)。Phase D dogfood 観測から導かれた最も価値ある決定論的防止策。Bundle k のコア。 +> +> **参照**: `.claude/feedback-reports/151.md` Tier 1 #2、`src/cli-push-runner/src/stages/lint_screen.rs`、D-3/D-4/D-5 outcome (`docs/local-llm-offload-analysis.md`) + +#### 設計決定の余地 + +- **filter 適用箇所**: (a) `.takt/review-diff.txt` 生成時に `.md` ハンクを drop / (b) lint_screen stage で diff parse 後にハンクを skip / (c) prompt 内で「.md は無視せよ」と instruct (= LLM 信頼、危険) +- **推奨は (b)**: diff 段階で `.md` 以外のハンクのみを mistral:7b に渡す。Rust 側で diff hunk header (`+++ b/path`) を parse して拡張子を判定、`.md` / `.markdown` を skip +- **fallback 経路**: 全 diff が `.md` のみだった場合は lint_screen 自体を skip + report に「`docs-only diff のため lint_screen はスキップしました`」を出力 + +#### 作業計画 + +- [ ] `src/cli-push-runner/src/stages/lint_screen.rs` に diff hunk filter 関数を追加 +- [ ] filter は `extensions_to_exclude = ["md", "markdown"]` を hardcode (将来 config 化検討) +- [ ] unit test: 純 .md diff / mixed (Rust + .md) diff / 純 Rust diff の 3 ケースで filter 動作 assert +- [ ] integration test: docs-only PR の dogfood シナリオで lint_screen が skip + warn を出すこと +- [ ] `.takt/lint-screen-report.md` 出力に skip 理由を明示 +- [ ] 本エントリ削除 + todo-summary.md 行削除 + +#### 完了基準 + +- 純 `.md` diff の lint_screen 起動時に Rust hallucinate FP が 0 件になる +- mixed diff でも `.md` 部分は無視され、Rust hunks のみが mistral:7b に渡る +- 既存 5 観測のうち D-4 CR fix (TOML)、D-5 ×2 (Markdown FP) は本フィルタで構造的に消滅 (D-3 globset FP は Rust scope なので残る = 期待動作) + +--- + +### `no-ephemeral-todo-reference` rule の TOML positive test 追加 (PR #151 T1-#1 採用) + +> **動機**: PR #151 の CodeRabbit nitpick (および本 PR で発見されなかった latent gap) で、`no-ephemeral-todo-reference` rule が TOML ファイルを extensions に持つ場合の positive test (= 実際に violation を検出することの assertion) が不在と判明。既存テスト `no_ephemeral_todo_self_exclusion_invariant_holds_on_deployed_toml` は self-exclusion 確認のみで、検出力の test ではない。 +> +> **本タスクの位置づけ**: PR #151 post-merge-feedback Tier 1 #1 採用 (Severity Medium / Frequency Medium / Effort S / Adoption Risk None)。extensions 拡張が複数 PR にわたって反復する pattern (yaml/yml = PR #110、toml = PR #129?) があり、test gap が累積するリスクを構造的に防ぐ。 +> +> **参照**: `.claude/feedback-reports/151.md` Tier 1 #1、`src/hooks-post-tool-linter/src/main.rs` test module + +#### 作業計画 + +- [ ] test fixture: `.toml` 拡張子ファイルに `docs/todo3.md` 等の ephemeral 参照を含む 2-3 行 fixture を作成 +- [ ] test ケース: `run_custom_rules` が 1 件以上の violation を返し、`type == "NO_EPHEMERAL_TODO_REFERENCE"` を確認 +- [ ] negative test: 同じ TOML fixture で `docs/adr/adr-007.md` 等の permanent 参照は violation 0 件であることを確認 +- [ ] 本エントリ削除 + todo-summary.md 行削除 + +#### 完了基準 + +- TOML 拡張子で rule が機能することが explicit test で seal される +- 将来 extensions から TOML を誤削除した場合に test fail で検出される + +--- + +### UTF-8 マルチバイト boundary test を他の string-processing hooks に横展開 (PR #151 T2-#1 採用) + +> **動機**: PR #151 で `byte_offset_to_line` の char-boundary panic bug を test 拡充 (UTF-8 漢字単独 needle) で発見した。同型関数 (byte offset から行番号変換 / needle 検索 + slice 操作) は他の string-processing hooks にも存在する可能性が高く、横展開 test で systemic 防御を確保すべき。 +> +> **本タスクの位置づけ**: PR #151 post-merge-feedback Tier 2 #1 採用 (Severity Medium / Frequency Medium / Effort M / Adoption Risk None)。test 拡充は単なるカバレッジ追加ではなく fault detection に直結することが実証済 (本 PR で副産物として 1 production bug 修正)。 +> +> **参照**: `.claude/feedback-reports/151.md` Tier 2 #1、`src/hooks-post-tool-comment-lint-rust/src/main.rs:byte_offset_to_line` (PR #151 で修正済)、対象は `src/hooks-*` で string offset 操作を行う関数 + +#### 作業計画 + +- [ ] `grep -rn "as_bytes\|byte\|offset" src/hooks-*/src/` で類似処理を持つ hooks を列挙 +- [ ] 各 hook で multi-byte boundary に晒される operation を識別 (byte slice / needle search / offset → line 変換 等) +- [ ] 対象 hook 毎に test fixture 追加: 漢字単独 / emoji / 結合文字 / BMP 外文字 のうち最低 1 パターン +- [ ] 検出された production bug は 1 行 fix で resolve (PR #151 と同じ pattern) +- [ ] 本エントリ削除 + todo-summary.md 行削除 + +#### 完了基準 + +- 全 string-processing hook が multi-byte boundary の panic に対して test で防御されている +- 横展開 test 実施過程で発見された production bug が修正される + +--- + +### ADR-038 に mistral:7b 「diff 外 context hallucinate」failure mode を追記 (PR #151 T3-#1 採用、順位 123 と同 PR 推奨) + +> **動機**: PR #148 (D-3) / PR #150 (D-4 CR fix) / PR #151 (D-5 ×2) の 3 PR で観測された FP pattern = 「mistral:7b が diff 内容に関わらず hook source 周辺の context を見て `unused-import` を hallucinate する」を ADR-038 に codify。Phase b' fixture では再現しない failure mode のため、将来の prompt 改善や別モデル評価時の prior assumption として永続記録する価値あり。 +> +> **本タスクの位置づけ**: PR #151 post-merge-feedback Tier 3 #1 採用 (Severity Low / Frequency High = 3 PR 観測 / Effort XS / Adoption Risk None)。順位 123 (lint-screen MD フィルタ実装) と同 PR で land 効率的 (実装と仕様の整合性確保)。 +> +> **参照**: `.claude/feedback-reports/151.md` Tier 3 #1、`docs/adr/adr-038-local-llm-finding-classification.md`、D-3/D-4/D-5 outcome (`docs/local-llm-offload-analysis.md`) + +#### 作業計画 + +- [ ] ADR-038 に「Known failure mode: docs-only diff Rust context hallucinate」section 追加 +- [ ] 3 PR 観測の事実 (#148/#150/#151) を inline cite +- [ ] 根本原因の推定 (context window 内に hook source が含まれる → past commit の `use` 文を current diff として誤認) を記録 +- [ ] 対策として順位 123 (拡張子フィルタ) を citation +- [ ] 本エントリ削除 + todo-summary.md 行削除 + +#### 完了基準 + +- ADR-038 から「なぜ Markdown 除外フィルタが必要か」が逆引きできる +- 将来別モデル評価 (LLaMa / phi 等) で同 failure mode を検証する出発点になる + +--- + +### extensions 拡張時の test 追加 pattern をコード comment で明文化 (PR #151 T3-#2 採用、順位 124 と同 PR 推奨) + +> **動機**: 順位 124 (TOML positive test) の根因である「extensions 配列を変更しても対応する test が追加されない」pattern を、`custom-lint-rules.toml` または `no_ephemeral_todo_reference_rule()` 関数の近傍コメントに明記。「extensions を変更した際は対応する positive/negative test を追加すること」のリマインダを次回 rule 変更時に目に入る位置に置く。 +> +> **本タスクの位置づけ**: PR #151 post-merge-feedback Tier 3 #2 採用 (Severity Low / Frequency Medium / Effort XS / Adoption Risk None)。memory rule `feedback_no_unenforced_rules.md` に抵触するように見えるが、本 case は **既存実践の明文化 + 機械強制ではなく guide 効果** のため例外採用 (順位 122 と同じロジック)。 +> +> **参照**: `.claude/feedback-reports/151.md` Tier 3 #2、`.claude/custom-lint-rules.toml`、`src/hooks-post-tool-linter/src/main.rs` + +#### 作業計画 + +- [ ] `.claude/custom-lint-rules.toml` の `no-ephemeral-todo-reference` rule entry の上に 2-3 行 comment 追加: 「⚠️ extensions を変更する場合: 同 PR で positive + negative test を `src/hooks-post-tool-linter/src/main.rs` に追加すること」 +- [ ] 派生プロジェクト (techbook-ledger / auto-review-fix-vc) への deploy 要否を検討 (`.claude/custom-lint-rules.toml` は project 個別なので deploy 不要) +- [ ] 順位 124 (TOML test 追加) の作業中に test の location を確認して、comment 内の path 参照を正確に書く +- [ ] 本エントリ削除 + todo-summary.md 行削除 + +#### 完了基準 + +- 次回 extensions 変更時に rule 編集者が test 追加を忘れにくくなる +- comment が機械強制ではなく guide として機能する (PR review 時の checklist としても再利用可) + +---