Semantic (Jev)
HEAL のメトリクスは、ソースと git の履歴からローカルで計算します。コードのどこが変えにくいかは分かりますが、コードが何を意味しているかまでは分かりません。たとえば、関数の名前が中身と合っているか、テストが本当に何かを確かめているか、ドキュメントの説明がまだコードと合っているか、といったことです。
オプトインの [features.semantic] は、こうした問いを TypeSafe の分類モデル Jev に投げます。Jev は文章やコードを書きません。問いごとに確率で答えるので、heal はほかのメトリクスと同じように、その答えを Finding にできます。
このファミリの機能は、どれも既定では無効です。有効にしなければ、heal の動きは今までと変わりません。
何が、いつ送られるか
Section titled “何が、いつ送られるか”- 送信するのは
heal semantic askだけです。heal があらかじめ選んだコード・テスト・ドキュメントの一部(よく変更されるファイルの関数など)を、TypeSafe の API に送ります。 heal auth jev statusは、API キーが使えるかを確かめます。キーは送りますが、プロジェクトの中身は送りません。- それ以外のコマンド(
heal status、heal metrics、heal diff、post-commit フック)は、ネットワークにつながりません。heal semantic askが保存した答えを読むだけです。 [features.semantic].excludeに一致するファイルは送りません。
TypeSafe は、利用者のデータをモデルの学習に使わないとしています。データを保持しない契約(Zero Data Retention)は enterprise プランだけです。非公開のコードベースで有効にする前に、TypeSafe の規約 を確認してください。
有効にするかどうかはチームで決めることなので、共有の設定ファイルに書きます。
[features.semantic]enabled = true# model = "jev-1.13.0" # バージョンを固定する。動くエイリアスは使えない# max_usd = 1.0 # 1 回の実行で、これ以上使う前に止める# concurrency = 8 # 同時に送るリクエストの数# exclude = ["secrets/", "*.pem"]有効にすると、heal status は保存された答えも使って TODO リストを並べます。/heal:refactor・/heal:docs・/heal:tests の各スキルは、自分の提案とコミットを Jev に確かめさせます。
API キーを設定する
Section titled “API キーを設定する”キーは一人ひとりが自分のものを使います。TypeSafe のコンソール で取得したら、環境変数に入れるか、
export TYPESAFE_API_KEY=...ユーザー設定(プロジェクトの外にあり、本人しか読めないファイル)に保存します。
printf '%s\n' "$KEY" | heal auth jev setheal auth jev status # キーの出どころを表示し、使えるかを確かめるheal auth jev clear # 保存したキーを消すキーが .heal/ の下に書かれることはありません。両方あるときは TYPESAFE_API_KEY が優先されます。TYPESAFEAI_API_KEY も読むので、ほかの Jev のツールで使っているキーをそのまま使えます。
問い合わせる
Section titled “問い合わせる”heal semantic ask --dry-run # 何を問い合わせるかと、料金の見積もりheal semantic ask # 問い合わせて、答えを保存するheal semantic ask --prune # あわせて、どこからも参照されなくなった答えを消す答えは .heal/semantic/verdicts/ に、タスクごとに 1 ファイルで保存されます。このディレクトリはコミットしてください。API キーを持たないチームメンバーも同じ結果を見られるようになり、heal も前回から変わったコードについてだけ問い合わせます。2 つのブランチの両方で答えが増えたときは、次の設定でマージの衝突を減らせます。
.heal/semantic/verdicts/*.jsonl merge=union下で説明する、その場で行う確認と focus の答えは、一人の作業途中の状態についての答えなので、代わりに .heal/cache/semantic/verdicts/ に保存します。このディレクトリは git の管理から外れていて、消しても問題ありません。
HEAL が問うこと
Section titled “HEAL が問うこと”問いの種類ひとつひとつをタスクと呼びます。[features.semantic.tasks.<id>] enabled = false でタスクを止められ、cutoff = 0.7 のように書けば判定に必要な確率を変えられます。
| タスク | 何を問うか | どこに表れるか |
|---|---|---|
commit_intent |
最近の各コミットが、バグ修正、機能追加、リファクタなどのどれか | バグ修正が集中しているファイルが、heal status のリストで上に来る |
consequence |
フラグの立った各ファイルに欠陥があったとき、開発ツールの不調からデータの破損まで、どれほどの損害になるか | 重要なコードが、heal status のリストで上に来る |
triage |
解消キューの Finding が、機械的に直せるものか、誤検知か、設計の判断が要るものか。修正はどれくらいの大きさか | 作業するスキルの判断材料になり、小さな修正が先に来る |
friction |
複雑なコードが、変えにくいのか、テストしにくいのか、読みにくいのか。その複雑さは本質的なものか | 本当に困っているコードが上に来る |
focus |
説明した作業が、各ファイルにどれくらい触れるか(--focus) |
heal status --focus で、先に整えておくべきファイルが上に来る |
concept |
各関数が、語彙のうちどの概念を実装しているか(インラインの単体テストは除く) | 概念が混ざったファイル、置き場所の違う関数、多くのファイルに散らばった概念 |
term_drift |
関数名に使われた 2 つの語が、同じものを指しているか(user と account など) |
1 つのものには 1 つの語を使うための、名前の変更の提案 |
name_mismatch |
関数の名前やドキュメントコメントが、本体の処理と合っているか | コードがしていないことを約束している名前 |
split_points |
長く複雑な関数を、目的が 1 つずつの手順に分けるならどこで区切るか | 複雑度の Finding に付く区切り位置。/heal:refactor が使う |
fix_pattern |
複雑度や重複の Finding に、どの定番のリファクタが合うか | /heal:refactor の判断材料 |
test_value |
各テストが、名前にうたった振る舞いが壊れたときに気づけるか。それとも自分のモックやフレームワークしか確かめていないか | 消すか書き直すべきテスト([features.test] が必要) |
mock_scope |
各モックが何を置き換えているか。外部サービスか、テスト対象のコードか、内部の部品か | テストを実装の細部に縛りつけているモック |
test_triage |
テストのないコードが、単純なロジックか、処理の取りまとめか、I/O か。skip されたテストはなぜ skip されているか | 単体テストが効く場所を /heal:tests に伝える |
test_duplicate |
似た 2 つのテストが同じことを確かめているか。入力が違うだけか | 消すべきテストや、1 つのテーブル駆動テストにまとめるべきテスト |
doc_structure |
各セクションがどんな種類の文書か(チュートリアル、ハウツー、リファレンス、解説など)。新しい文書はどこから始まるか | 分けるべきページ、まとめるべきページ、1 つの種類に絞るべきページ([features.docs] が必要) |
doc_placement |
読む人は、各ページをドキュメントのどのセクションで探すか | 置き場所の違うページと、孤立ページをどこからリンクするか |
doc_drift_semantic |
ペアになったドキュメントのセクションが、まだコードの動きを説明しているか | コードがもうしていないことを書いているセクション |
doc_concept |
各ドキュメントのセクションが、語彙のうちどの概念を説明しているか | コードが頼っているのに、どのドキュメントも説明していない概念 |
doc_overlap |
2 つのページが同じ概念を 2 回説明していないか、食い違っていないか | まとめるべき説明と、直すべき食い違い |
TODO リストの並び順
Section titled “TODO リストの並び順”答えを保存していても、heal status が Finding を Tier と Severity でまとめる点は変わりません。そのうえで各グループの中では、次のものを先に並べます。欠陥の損害が大きいファイル、扱いにくいコード、バグ修正が続いているファイル、小さく済む修正です。それでも決まらなければ、いつもの Hotspot のスコアで決めます。答えが保存されていなければ、並び順は変わりません。スキルも、自作のスクリプトも、同じ並び順を heal status --json から読めます。キューに入っている各 Finding には、drain_rank(1 が次に取り組むもの。ファミリごとに数える)と drain_tier が付いています。
決まった作業に備えたいときは、その作業をファイルに書いてから次を実行します。
heal semantic ask --task focus --focus plan.mdheal status --focus plan.mdconcept タスクには、コードを形づくっている考え方の一覧が必要です。.heal/concepts.toml に書きます。Jev は与えられた名前の中から選ぶだけで、新しい名前を作ることはありません。最初の案はセットアップ用のスキルで作り、見直してからコミットしてください。Claude Code で次を実行します。
/heal:setup semantic[[concept]]id = "calibration"description = "Derives thresholds from the project's own metric distribution."/heal:refactor、/heal:docs、/heal:tests の各スキルは、その場で行う確認(verify_patch、verify_tests、verify_proposal、name_choice)も --task で実行します。verify_patch と verify_tests は、--diff で渡したコミット(たとえば --diff HEAD~1..HEAD)を判定します。これらはエージェントが自分の仕事を確かめ直すためのもので、引数なしの heal semantic ask で実行されることはありません。
Jev の料金は入力だけにかかります(執筆時点で、入力 10 億トークンあたり 42 ドル)。--dry-run を付けると、送る前に見積もりを表示します。max_usd を設定しておけば、上限を超える前に実行を止めます。中くらいの規模のリポジトリなら、1 回の実行はたいてい数セントです。
結果は候補として扱う
Section titled “結果は候補として扱う”分類モデルは間違えることがあります。しきい値に近いスコアは、モデルのバージョンによって少し変わることもあります。HEAL はモデルのバージョンを固定し、保存した答えを使い回して結果を安定させていますが、semantic の Finding は、人が確かめるための候補として扱ってください。そのまま従うべき指示ではありません。
enabled = false にします。次の heal status で semantic の Finding はすべて消え、通常の並び順に戻ります。保存した答えは、自分で消すまで .heal/semantic/ に残ります。