Skip to content

feat(cli-push-runner): Phase c MVP — pre-push lint-screen step (default OFF)#132

Merged
aloekun merged 1 commit intomasterfrom
feature/local-llm-phase-c-mvp
May 8, 2026
Merged

feat(cli-push-runner): Phase c MVP — pre-push lint-screen step (default OFF)#132
aloekun merged 1 commit intomasterfrom
feature/local-llm-phase-c-mvp

Conversation

@aloekun
Copy link
Copy Markdown
Owner

@aloekun aloekun commented May 8, 2026

Summary

Phase c MVP — cli-push-runner に lint-screen step を追加し、pre-push 時に diff を mistral:7b に流して lint 一次フィルタの所見 (.takt/lint-screen-report.md) を出力する経路を整備。Phase b' conditional GO (75%) のため gating せず、report 出力のみ (default OFF / 試験運用 opt-in)。

アーキテクチャ

quality_gate → diff (.takt/review-diff.txt) → [lint_screen]? → takt → push
  • 配置: cli-push-runner (Rust) の新 stage stages/lint_screen.rs
  • 起動条件: [lint_screen] enabled = true 時のみ (default OFF)
  • subprocess: cli-finding-classifier.exe --mode lint-screen (stdin に diff、stdout に LintScreenResult JSON)
  • 出力: .takt/lint-screen-report.md (markdown table)
  • 連携: review-simplicity.md instruction が同 path を optional context として読む (advisory 扱い)

fallback 設計 (push を block しない)

  • exe 不在 → skip + warn
  • diff 空 → skip
  • diff 過大 (max_diff_lines = 5000、default) → skip + warn
  • timeout (timeout_secs = 60、default) → skip + warn
  • Ollama down / API error → cli-finding-classifier 内 fallback で human_review + fallback_reason、report に出力
  • JSON parse 失敗 → markdown に raw 含めて記録

smoke dogfood 結果

868 行の現実 PR diff (Phase c 自身) を流したところ:

{"lint_findings":[],"screen_decision":"human_review","fallback_reason":"ollama error: parse: JSON parse error: missing field `screen_decision`"}

= mistral:7b は大規模 diff で JSON 構造を欠落させがちと判明。fallback path が graceful に処理。Phase d (PR-based dogfood) で頻度・対策方針を観測。

副次対応

  • step_timeout = 120 → 180 (Phase b' end-to-end test の cargo test --ignored が境界 117s で timeout していた、commit 73903d7 で実証)

Test plan

  • cargo test -p cli-push-runner — 47 件 pass
  • cargo test -p cli-finding-classifier --test lint_screen_evals -- --ignored — 12 件 + 1 ignored 完走
  • cargo clippy / fmt clean
  • smoke: cli-finding-classifier に Phase c 自身の diff (868 行) を流して fallback path 確認
  • 実 PR push で takt simplicity-review が .takt/lint-screen-report.md を context として認識するか (Phase d で観測)

Out of scope (PR-B 行き)

Summary by CodeRabbit

リリースノート

  • 新機能

    • オプションのlint-screenプリプッシュフェーズを追加(デフォルトで無効)。外部分析を実行し、マークダウンレポートを生成します。
  • ドキュメント

    • コードレビュー中に補足的なlintレポートを活用するガイダンスを追加しました。
  • Chores

    • 品質ゲートのタイムアウトを120秒から180秒に延長しました。
    • lint-screen設定オプションを追加しました。

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 8, 2026

Review Change Stack

Warning

Rate limit exceeded

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

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ 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: 0df2e926-dc48-4086-a55b-69d8d22f6b97

📥 Commits

Reviewing files that changed from the base of the PR and between 73903d7 and 8416d3e.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • .takt/facets/instructions/review-simplicity.md
  • push-runner-config.toml
  • src/cli-push-runner/Cargo.toml
  • src/cli-push-runner/src/config.rs
  • src/cli-push-runner/src/main.rs
  • src/cli-push-runner/src/stages/lint_screen.rs
  • src/cli-push-runner/src/stages/mod.rs
📝 Walkthrough

概要

PR は Diff に対して外部 lint-screen 分類器を実行し、マークダウン形式のレポートを生成する新しいパイプラインステージを追加します。このステージは設定で無効化でき、push パイプラインをブロックしません。

変更内容

Lint-Screen Feature

レイヤー / ファイル 概要
設定構造とコントラクト
src/cli-push-runner/src/config.rs, push-runner-config.toml, src/cli-push-runner/Cargo.toml
LintScreenConfig 構造体(enabled、exe_path、model、endpoint、timeout_secs、max_diff_lines、output_path フィールドを含む)、デフォルト定数(タイムアウト 60 秒、最大 diff 行数 5000、モデル mistral:7b、Ollama エンドポイント、分類器実行ファイルパス、出力ファイル .takt/lint-screen-report.md)、トップレベル Config への統合。quality_gate step_timeout を 120 から 180 に増加。serde_json 依存関係を追加。
ステージ実装
src/cli-push-runner/src/stages/lint_screen.rs
run_lint_screen オーケストレータ、read_diff(最大行数の検証)、invoke_classifier(外部プロセス管理とタイムアウト処理)、write_report(マークダウン出力)、format_report(JSON パース)、render_findings_table(マークダウンテーブル生成)、sanitize_cell(セルエスケープ)。エラーは skip 理由として記録され、パイプラインをブロックしません。
パイプライン統合
src/cli-push-runner/src/main.rs, src/cli-push-runner/src/stages/mod.rs
run_diff_and_lint_screen ヘルパー(diff 実行と条件付き lint-screen 呼び出しをカプセル化)、run_pipeline の refactor(新しいヘルパー呼び出し)、lint_screen サブモジュール登録と再エクスポート。
テストと文書化
src/cli-push-runner/src/config.rs, src/cli-push-runner/src/stages/lint_screen.rs, .takt/facets/instructions/review-simplicity.md
Config テスト更新(lint_screen: None を含む)、lint_screen ユニットテスト(JSON 解析エラー復旧、空の findings、セル sanitization、read_diff エラーケース)、レビュー簡潔化ガイドに lint-screen レポート使用法を追加。

推定コードレビュー難度

🎯 3 (中程度) | ⏱️ ~20 分

関連する可能性のある PR

  • aloekun/claude-code-hook-test#130: 当該 PR が lint-screen の実行と markdown レポート生成を実装する一方で、こちらは lint-screen モード、API(screen_diff)、プロンプト、およびそのフィクスチャ/JSON 出力を追加するため、直接関連します。
  • aloekun/claude-code-hook-test#47: 同じレビュー文書(.takt/facets/instructions/review-simplicity.md)を変更するため直接関連します。
  • aloekun/claude-code-hook-test#120: 設定フィールド(model/endpoint/timeout)、デフォルト無効動作、JSON I/O を含む同じパターンの設定可能なサブプロセスベースの分類器統合を異なるコンポーネントで実装するため関連します。
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.87% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR title clearly and specifically describes the main change: adding a Phase C MVP lint-screen pre-push step to cli-push-runner with default OFF configuration, which aligns directly with the changeset contents.
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.


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

🧹 Nitpick comments (1)
src/cli-push-runner/src/config.rs (1)

113-227: ⚡ Quick win

[lint_screen] セクションのパース動作を検証するテストが不在

config_parses_with_diff[diff] セクションのパースを検証しているように、[lint_screen] セクション全フィールドのパースをテストするケースがない。serde の field 名と TOML キー名は完全一致が必要なため、フィールドのリネームや追加が silent な None へのフォールバックに化けるリスクを防ぐためにも追加が望ましい。

🧪 テスト追加の例
+    #[test]
+    fn config_parses_lint_screen_section() {
+        let toml_str = r#"
+[quality_gate]
+[[quality_gate.groups]]
+name = "test"
+commands = ["echo ok"]
+
+[takt]
+workflow = "w"
+task = "t"
+
+[push]
+command = "echo push"
+
+[lint_screen]
+enabled = true
+exe_path = "custom/classifier.exe"
+model = "mistral:7b"
+endpoint = "http://localhost:11434"
+timeout_secs = 30
+max_diff_lines = 1000
+output_path = ".takt/custom-report.md"
+"#;
+        let config: Config = toml::from_str(toml_str).unwrap();
+        let ls = config.lint_screen.unwrap();
+        assert!(ls.enabled);
+        assert_eq!(ls.exe_path.as_deref(), Some("custom/classifier.exe"));
+        assert_eq!(ls.model.as_deref(), Some("mistral:7b"));
+        assert_eq!(ls.endpoint.as_deref(), Some("http://localhost:11434"));
+        assert_eq!(ls.timeout_secs, Some(30));
+        assert_eq!(ls.max_diff_lines, Some(1000));
+        assert_eq!(ls.output_path.as_deref(), Some(".takt/custom-report.md"));
+    }
🤖 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/cli-push-runner/src/config.rs` around lines 113 - 227, Add a new unit
test (similar to config_parses_with_diff) named e.g. config_parses_lint_screen
that deserializes a TOML string containing a full [lint_screen] section and
asserts every field on Config.lint_screen (or the LintScreen type) is
Some/equals the expected values; locate the Config struct and existing tests
(e.g. config_parses_with_diff, config_parses_full_without_diff) to mirror style,
ensure you check optional fields unwrap_or defaults where applicable and assert
that no field silently remains None due to a naming mismatch.
🤖 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-push-runner/src/stages/lint_screen.rs`:
- Around line 199-216: The table-building code in render_findings_table leaves s
(severity), r (rule), file and line unescaped which can break the Markdown
table; wrap each of those values with sanitize_cell before formatting (i.e. pass
s, r, file and the computed line string through sanitize_cell) and ensure the
line value is produced as a deterministic string (use the existing
map/unwrap_or_else flow but sanitize its result) so all four fields are escaped
consistently alongside issue and suggestion.

---

Nitpick comments:
In `@src/cli-push-runner/src/config.rs`:
- Around line 113-227: Add a new unit test (similar to config_parses_with_diff)
named e.g. config_parses_lint_screen that deserializes a TOML string containing
a full [lint_screen] section and asserts every field on Config.lint_screen (or
the LintScreen type) is Some/equals the expected values; locate the Config
struct and existing tests (e.g. config_parses_with_diff,
config_parses_full_without_diff) to mirror style, ensure you check optional
fields unwrap_or defaults where applicable and assert that no field silently
remains None due to a naming mismatch.
🪄 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: c4d07d95-a1ce-45dd-92db-be62e6706fff

📥 Commits

Reviewing files that changed from the base of the PR and between fb33818 and 73903d7.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • .takt/facets/instructions/review-simplicity.md
  • push-runner-config.toml
  • src/cli-push-runner/Cargo.toml
  • src/cli-push-runner/src/config.rs
  • src/cli-push-runner/src/main.rs
  • src/cli-push-runner/src/stages/lint_screen.rs
  • src/cli-push-runner/src/stages/mod.rs

Comment thread src/cli-push-runner/src/stages/lint_screen.rs
@aloekun aloekun force-pushed the feature/local-llm-phase-c-mvp branch from 73903d7 to 8416d3e Compare May 8, 2026 19:20
@aloekun aloekun merged commit fd54b08 into master May 8, 2026
1 check passed
@aloekun aloekun deleted the feature/local-llm-phase-c-mvp branch May 8, 2026 20:18
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