Skip to content

refactor: apply template numeric lint rules - #12

Merged
furedea merged 2 commits into
mainfrom
refactor/apply-numeric-lint
Oct 21, 2026
Merged

furedea merged 2 commits into
mainfrom
refactor/apply-numeric-lint

Conversation

@furedea-agent

@furedea-agent furedea-agent Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

概要

template-rust / template-typescript の数値系 lint ルールを導入し,既存違反をすべて挙動を変えないリファクタリングで解消しました.埋め込み JXA(src/mail_bridge.js)にも TypeScript テンプレートの数値ルールを適用しています.

あわせて,承認済みの追加変更が 2 つあります.

  • src 配下だけディレクトリ名に snake_case を許可しました(Rust のモジュールディレクトリ用).
  • 検証フックが JXA の変更を Rust の harness テストに結び付けられるよう,対応付けの設定を追加しました.

Refs furedea/dotfiles#247

違反件数

対象 ルール 導入前 導入後
Rust clippy::excessive_nesting(threshold 2) 10 0
Rust cognitive_complexity / too_many_arguments / allow_attributes_without_reason 0 0
JXA max-depth(2) 1 0
JXA max-params(3) 2 0
JXA max-lines(500) 1(651 行) 0
JXA complexity(10) 0 0
合計 14 0

受け入れ条件

  • テンプレートと同じ数値ルールを lint 設定(Cargo.toml [lints.clippy],clippy.toml,.oxlintrc.json)と lefthook(file-length)に入れた
  • 違反 0.#[allow] や oxlint-disable は使っていない(例外 1 件は下記の override で,ユーザー承認済み)
  • 挙動を変えない分割のみ.既存テストと追加テストがすべて通る
  • src 配下だけ snake_case のディレクトリ名を許可し,tests/ などでは kebab-case を維持した
  • src/mail_bridge* の変更で,検証フックが src/osascript.rs の Rust テストを選ぶようにした
  • マージ前に Codex の adversarial review を受ける

確認したコマンド

  • cargo fmt --check
  • cargo clippy --all-targets -- -D warnings
  • cargo test --locked(JXA harness を含む全テスト)
  • cargo build --locked
  • pnpm run check(oxfmt,oxlint,tsc)
  • lefthook run pre-commit --all-files
  • ls_lint(引数なし.下記のプローブでも確認)

詳細

数値ルールの設定

  • Cargo.toml:allow_attributes_without_reason,cognitive_complexity,excessive_nesting を warn に設定
  • clippy.toml:テンプレートと同じしきい値(too-many-arguments 3,excessive-nesting 2,cognitive-complexity 15)
  • lefthook.yml:テンプレートの file-length(*.rs は 500 行以下)を追加
  • .oxlintrc.json:complexity 10,max-depth 2,max-lines 500,max-params 3 を追加

Rust

nesting threshold 2 では,impl 内メソッドの match arm や if のブロックがそれだけで 3 段になります.そのため処理を自由関数へ移しました.

  • src/bridge.rs,src/application.rs:Display::fmt の本体を write_bridge_error と write_application_error に移動
  • src/cli.rs:BoundedText::from_str の検証を validate_text_length に移動
  • src/osascript.rs:execute の終了コード判定を successful_stdout に,run_process の待機ループを wait_for_exit に移動.タイムアウトや失敗時の後始末(kill,wait,reader の回収)は元と同じです

JXA

  • max-depth:mailboxPath 内の try を readableParent に抽出
  • max-params:appendMailboxes の depth は常に parents.length と一致するので引数から外しました.requireInteger の最小値と最大値は IntegerRange オブジェクトで受け取ります
  • max-lines:mail_bridge.js(エントリとハンドラ,282 行),mail_bridge_lookup.js(アカウント,メールボックス,メッセージの解決とパス,213 行),mail_bridge_values.js(入力検証,値の整形,エラー,170 行)に分割しました.osascript.rs で concat!(include_str!(..)) して 1 本のスクリプトとして渡すので,実行時の成果物は従来どおり 1 つで,トランスパイルもありません(ADR-0004 の範囲内).tsconfig.json と package.json のスクリプトに新しいファイルを追加しました

lint 例外(ユーザー承認済み)

.oxlintrc.json の override で,mail_bridge_lookup.js と mail_bridge_values.js だけ eslint/no-unused-vars を off にしています.JXA はモジュール機構のない単一スクリプトで,oxlint は /* exported */ を解釈しません.そのため分割すると,他のファイルから呼ぶ関数が未使用と誤検知されます.tsc と他の lint ルールは全ファイルに適用されたままです.

ls-lint:src 配下の snake_case ディレクトリ

ls-lint v2 では,src: のようなネストしたブロックはルートの規則を継承せず,置き換えます.そのため template-rust と同じく,ルートのファイル規則を YAML アンカー(<<: &files)にまとめ,src ブロックで <<: *files としてマージしたうえで,.dir: regex:[a-z0-9]+(_[a-z0-9]+)* を指定しました.このリポジトリのルートのファイル規則は .yaml と .* です(README,Cargo.toml などは従来どおり ignore で除外しています).

引数なしの ls_lint に,一時的なプローブを置いて確認しました(確認後に削除済み).

プローブ 結果
src/good_dir,src/good_dir/nested_dir 通る
src/bad-dir .dir の snake_case 規則で失敗
tests/bad_dir ルートの kebab-case 規則で失敗
src/BadFile.rs .* 規則で失敗
src/good_dir/Bad-Name.yaml マージした .yaml 規則で失敗(pnpm-workspace.yaml は通る)

検証フックとテストの対応付け

.agents/hooks/rules/related_test_extensions.json で src/mail_bridge*(.d.ts を含む)を src/osascript.rs に対応付けました.JXA のテストは Rust の harness から cargo test で実行しているためです.フックの選択ロジックで確認した結果は次のとおりです.

変更したファイル 選ばれるテスト
JXA の 3 ファイルと .d.ts cargo test osascript
JXA と src/osascript.rs cargo test の全件
package.json または tsconfig.json と JXA を同時に変更 未解決(下記)

package.json や tsconfig.json を変更すると,フックは JS テストの全件実行を必須にし,他言語のテストへの委譲を無視します.この PR は両方のファイルを変更しているので,このセッションでは Stop hook が「test command could not be determined」のままです.これはフック側の仕様によるもので,テストの失敗ではありません.

追加したテスト(リファクタリング前に挙動を固定)

  • tests/bridge.rs:BridgeError の表示文言
  • tests/application.rs:JSON でない応答と,オブジェクトでない envelope の表示文言
  • tests/cli.rs:空のクエリと上限超過クエリのエラー文言
  • src/osascript.rs(JXA harness):container が読めないときのメールボックスパス,ネスト 32 段の受理と 33 段の拒否,limit の範囲外と非整数の拒否

🤖 Generated with Claude Code

furedea and others added 2 commits October 21, 2026 12:52
Adopt the numeric limits from template-rust and template-typescript:
clippy cognitive_complexity, excessive_nesting, and
allow_attributes_without_reason with the template thresholds, the
lefthook file-length check, and oxlint complexity, max-depth, max-lines,
and max-params for the embedded JXA.

Move nested Display, parsing, and process-wait logic out of impl blocks
into free functions, derive the mailbox depth from the parent path,
pass integer ranges as one object, and split the JXA bridge into entry,
lookup, and value files that are concatenated into the same single
script. The helper files disable no-unused-vars because oxlint cannot
see their callers in the other files.

Pin the touched branches with tests first.

Refs furedea/dotfiles#247

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rust module directories are identifiers, so allow snake_case directory
names under src while keeping kebab-case elsewhere. A nested ls-lint
block replaces the root rules, so the file rules are shared through a
YAML anchor, matching template-rust.

Map the embedded JXA sources to src/osascript.rs for the agent
verification hook, because their tests run through the Rust harness.

Refs furedea/dotfiles#247

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@furedea
furedea merged commit 32715ac into main Oct 21, 2026
14 checks passed
@furedea
furedea deleted the refactor/apply-numeric-lint branch October 21, 2026 04:51
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