Skip to content

feat(hooks): PostToolUse に UTF-8 整合性チェック (Layer 0) を追加 - #52

Merged
aloekun merged 1 commit into
masterfrom
feat/utf8-integrity-check
Apr 18, 2026
Merged

feat(hooks): PostToolUse に UTF-8 整合性チェック (Layer 0) を追加#52
aloekun merged 1 commit into
masterfrom
feat/utf8-integrity-check

Conversation

@aloekun

@aloekun aloekun commented Apr 18, 2026

Copy link
Copy Markdown
Owner

Summary

  • PostToolUse hook に UTF-8 整合性チェック (Layer 0) を追加。AI ツールの Edit/Write でマルチバイト文字が破壊される問題 (U+FFFD) を即座に検出する
  • todo.md から完了タスクを全削除し、作業予定のみを記録する運用に変更 (272行 → 82行)

Changes

hooks-post-tool-linter (src/hooks-post-tool-linter/src/main.rs)

  • check_utf8_integrity() 関数を追加: std::fs::read + String::from_utf8_lossy で U+FFFD を検出
  • Layer 0 として main() の最初に実行 (カスタムルール・外部ツールパイプラインより先)
  • テスト 5 本追加 (FFFD 検出、clean file、invalid raw bytes、複数行、存在しないファイル)

docs/todo.md

  • 完了履歴セクションを全削除 (ADR/仕組みに反映済みのため不要)
  • 運用ルールを更新: 完了タスクは ADR か仕組みに反映後、ファイルから削除する

Background

PR #50 の push 時に takt の fix ステップが日本語文字列を破壊する mojibake が発生 ("進みます。""進みま\uFFFD\uFFFD。")。CodeRabbit が Major として検出したが、PostToolUse hook では防げなかった。本 PR で Edit/Write 直後に即座にフィードバックする仕組みを追加。

Test plan

  • cargo test -p hooks-post-tool-linter 全 45 テスト合格 (新規 5 + 既存 40)
  • pnpm build:all 成功
  • takt pre-push-review approved (1 iteration, 5m 50s)

Summary by CodeRabbit

リリースノート

  • 新機能

    • PostToolUse フックに UTF-8 整合性チェック機能を追加しました。ファイル内の不正な文字エンコーディングを自動検出して、詳細なエラーレポートを出力します。
  • ドキュメント

    • 内部タスク追跡の運用ルールを更新。完了したタスクはシステムに反映された後、ファイルから削除され、Git ログで履歴が追跡されるようになりました。

@coderabbitai

coderabbitai Bot commented Apr 18, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@aloekun has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 47 minutes and 37 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 47 minutes and 37 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3e18d023-3ee3-4f75-a0e5-e2d0bcadefda

📥 Commits

Reviewing files that changed from the base of the PR and between 9b20351 and f596dbc.

📒 Files selected for processing (2)
  • docs/todo.md
  • src/hooks-post-tool-linter/src/main.rs
📝 Walkthrough

Walkthrough

ドキュメント(docs/todo.md)の運用ルールを更新し、スナップショット形式の慣例を廃止、完了タスクの削除ルールを明記しました。また、PostToolUse フックに UTF-8 整合性チェック機能を新たに追加し、テストケースを含めて実装しました。

Changes

Cohort / File(s) Summary
Documentation and Operating Rules
docs/todo.md
スナップショット形式の廃止、完了タスク削除ルール追加、現在進行中タスクの再構成、「完了履歴」セクション削除、git log による履歴追跡方針を明記。
UTF-8 Integrity Check Implementation
src/hooks-post-tool-linter/src/main.rs
新規関数 check_utf8_integrity() を追加、ファイルのバイト列を走査して U+FFFD(置換文字)を検出、リント違反を JSON 形式で出力。既存の正規表現ルールレイヤーの前に実行。複数の単体テストケース(検出確認、正常系、無効バイト列処理、複数行対応、非存在ファイル処理)を新規追加。

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding UTF-8 integrity checking to the PostToolUse hook (Layer 0), which is the primary technical addition in this PR.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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


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: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/todo.md`:
- Around line 35-39: Update the TODO status to reflect that the build step is
already complete: change the "ビルド+デプロイ待ち" entry to separate "ビルド: 完了" and "デプロイ:
未完了" (or mark only deploy as pending) and ensure the checklist still shows the
implemented items (`check_utf8_integrity()`, adding call in `main()`, and the
five tests) as checked so the current state accurately shows build succeeded but
deploy remains.

In `@src/hooks-post-tool-linter/src/main.rs`:
- Around line 389-397: The current UTF-8 integrity check sets
ViolationLocation.symbol to the entire line (line.trim().to_string()) when
line.contains('\u{FFFD}'), which leaks large or sensitive content; change it to
return only the detected token instead. In the block handling
line.contains('\u{FFFD}'), set ViolationLocation.symbol to the matched character
(e.g., the single U+FFFD replacement char found via line.chars().find(|c| *c ==
'\u{FFFD}').unwrap().to_string() or a constant "�".to_string()) rather than the
whole trimmed line; keep file and line_idx as-is so only the symbol field is
minimized. Ensure this change is applied where LintViolation and
ViolationLocation are constructed for the UTF8_INTEGRITY case.
- Around line 448-457: When check_utf8_integrity(&file) returns non-empty, the
code should fail-fast instead of continuing to subsequent auto-fix steps; after
emitting the feedback with emit_feedback(...) return early or terminate the
pipeline (e.g. return an Err or call std::process::exit(1)) so that downstream
steps like the formatter/fixer are not run on a corrupted file. Modify the block
that handles utf8_violations to stop further processing (using the same control
flow style as the surrounding function) so no
run_custom_rules/run_formatter/run_fixer steps execute for that file.
🪄 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: 58fcd586-e512-4b89-a456-16f86ca0f549

📥 Commits

Reviewing files that changed from the base of the PR and between fa4cc6d and 9b20351.

📒 Files selected for processing (2)
  • docs/todo.md
  • src/hooks-post-tool-linter/src/main.rs

Comment thread docs/todo.md
Comment thread src/hooks-post-tool-linter/src/main.rs
Comment thread src/hooks-post-tool-linter/src/main.rs
@aloekun
aloekun force-pushed the feat/utf8-integrity-check branch from 9b20351 to f596dbc Compare April 18, 2026 05:06
@aloekun
aloekun merged commit ca6c0e3 into master Apr 18, 2026
1 check passed
@aloekun
aloekun deleted the feat/utf8-integrity-check branch April 18, 2026 06:02
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