regression-notes について
決定の理由と回帰テストをセットで管理し、後続の変更でも判断の根拠と保護対象の動作を維持するスキルです。ノートの作成、検索、検証、アーカイブ用スクリプトと、リポジトリに検証ゲートを導入する手段を備えています。
主な機能
- 01決定ノートとテストの紐付け
- 02ノート作成とライフサイクル管理
- 03ノート群の検索と検証
- 04導入可能なpre-commit検証ゲート
- 05変更種別の分類
活用シーン
- 01バグ修正を維持する理由の記録
- 02回帰テストによる変更後の動作固定
- 03置き換えられた決定の更新やアーカイブ
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ meimingqi222/ my-agent-skills --skill regression-notesインストール後、Claude Code で/regression-notesを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/gate-and-format.mdscripts/new-note.pyverify-notes.pytemplates/bug-fix.mdgeneric.mdtests/test_date_timezone.pytest_install.pytest_reports.pytest_scale.pytest_verify_notes.py詳細
翻訳後に原文が更新されています。最新の内容は原文をご確認ください。
回帰メモ
バージョン 0.4.3
python3 が使えない場合(標準の Windows 環境)は、python または py -3 を使用してください。
DeepSeek Harness Agent Note ループを軽量に移植したものです。重要なバグ修正では、同じ変更に 1つのメモ(理由)+1つの回帰テスト(動作の固定) を必ず含めます。メモには判断の根拠を記録し、テストで動作を固定します。
動作、ファイル間で共有される契約、ディスク上/ワイヤー上/設定の形式、またはメンテナーが再検討する可能性のある判断に変更を加える場合、その修正は重要です。動作を変えない、単純な機械的編集や局所的な編集は対象外です。
リポジトリへのインストール
このスキルは、利用可能なだけでは機能しません。必ず適用されるよう、リポジトリの AGENTS.md または CLAUDE.md に次のルールを追加し、すべてのエージェントセッションで徹底してください。
## Regression notes
Every non-trivial bug fix ships one regression note and one regression test in the same change. The note records the problem, the decision, the alternatives considered, and the consequences; the test pins the behavior. A `## Verification` section names the test path and records the red-run proof.
Before editing a file, run `verify-notes.py --notes-dir .agents/notes --for-path <paths>` and read any note that cites it — the reverse lookup is what makes the notes tripwires instead of an archive.
Trivial mechanical edits with no behavior change are exempt.
`python3 regression-notes/scripts/verify-notes.py --notes-dir .agents/notes` must pass before any related change is merged.
次に、実際に実行されるゲートを用意します。説明文にルールを書くだけでは依頼にすぎません。エージェントが自分で実行を選ばなくても動くコマンドがゲートです。リポジトリですでに使われているものを選んでください。
# 1. CI, when the repository has it
- name: Verify regression notes
run: python3 regression-notes/scripts/verify-notes.py --notes-dir .agents/notes
# 2. A pre-commit hook -- the common case, since most repositories have no CI
#!/bin/sh
# .git/hooks/pre-commit (chmod +x it; on Windows run hooks under Git Bash,
# where `python3` may be missing and the `py` launcher stands in)
if command -v python3 >/dev/null 2>&1; then
python3 regression-notes/scripts/verify-notes.py --notes-dir .agents/notes || exit 1
else
py -3 regression-notes/scripts/verify-notes.py --notes-dir .agents/notes || exit 1
fi
# 3. Inside an existing packaging/release script, where the tree may be absent
python3 regression-notes/scripts/verify-notes.py --notes-dir .agents/notes --allow-missing
続いて、設定が有効であることを確認します(読み取り専用。パッケージングスクリプトの設定は自動検出できないため、ゲートとしてフックまたは CI 設定がカウントされます)。
python3 regression-notes/scripts/verify-notes.py --notes-dir .agents/notes --check-install
エージェントが判断しなくても検証ツールを実行するコマンドを明示できるようになるまで、このスキルをインストールしたことにはなりません。 答えが「エージェントが覚えているときに実行する」なら、ゲートは存在しません。このスキルは、まさにその問題を防ぐために作られています。
開発を遅らせずに設定を有効に保つには、次の2つのルールを守ってください。
- ドキュメントには参照先だけを記載し、内容は載せません。
AGENTS.md/CLAUDE.mdに記載するのは、常設ルールと--for-pathの使い方だけです。それ以外の判断の詳細、落とし穴の要約、テスト名はメモのツリーに記載します。エージェント向けドキュメントにコピーを貼り付けるたび、内容がずれていく第二の記録台帳が生まれます(実際に起きた失敗例として、AGENTS.md内の落とし穴一覧の番号が正規の一覧と気づかれないまま食い違っていました)。同じ事実を2か所に記載する必要がある場合は、どちらか一方をリンクにしてください。 - チェックは高速にしてください。そうでなければ回避されます。
--for-path、--find、検証ツールはすべて1秒未満で実行でき、標準の Python 以外は必要ありません。この状態を維持してください。pre-commit では、ステージング済みファイルに対する--for-pathをブロックしないリマインダーとして実行し、ブロックする検証は CI に任せます。すべてをコンパイルするフックでは、git commit --no-verifyが常態化してしまいます。コストは高いものの信頼できる手順(--dump-anchorsと実際のテスト一覧の突き合わせ)は、テストバイナリがすでに存在する CI で実行し、フックでは実行しないでください。
このスキルは、対象リポジトリの regression-notes/ に配置するか、CI にインストールして --notes-dir をリポジトリのメモツリーに指定できます。Git は空のディレクトリを追跡しません。最初のメモが作成される前に新規クローンでもゲートが検証対象のツリーを確保できるよう、1行だけ記載した .agents/notes/README.md をコミットしてください(検証ツールはこのファイルをスキップします)。
スクリプトの場所を特定する
スクリプトはこのファイルと同じ場所にあります。最初から glob で検索せず、最も簡単な場所から順に一度だけ特定してください。
-
Claude Code v2.1.64 以降 — このファイルの読み込み時に、ハーネスが
${CLAUDE_SKILL_DIR}をこのスキルのディレクトリにすでに展開しています。これを直接使い、以降の手順は省略してください。SCRIPTS="${CLAUDE_SKILL_DIR}/scripts" -
その他のハーネス —
~/.agents/skillsは、ほとんどのエージェント向けにnpx skillsがインストールする Agent Skills のオープン標準の場所です。一部のエージェントは独自のディレクトリを使います。標準の場所を1つのコマンドで確認してください(sh/bash。Windows では Git Bash、または以下の PowerShell 版を使用)。最初に見つかった場所で終了し、glob による検索は最後の手段としてのみ行います。for d in "${CLAUDE_SKILL_DIR:-}" "$HOME/.agents/skills" \ "$HOME/.claude/skills" "$HOME/.config/opencode/skills" \ "$HOME/.codex/skills" "$HOME/.cursor/skills" \ ".agents/skills" ".claude/skills"; do [ -f "$d/regression-notes/scripts/verify-notes.py" ] \ && SCRIPTS="$d/regression-notes/scripts" && break done if [ -z "${SCRIPTS:-}" ]; then path=$(find "$HOME" . -maxdepth 6 -path '*/regression-notes/scripts/verify-notes.py' -print -quit 2>/dev/null) [ -n "$path" ] && SCRIPTS=$(dirname "$path") fiPowerShell 版:
$roots = @( $env:CLAUDE_SKILL_DIR, (Join-Path $env:USERPROFILE ".agents\skills"), (Join-Path $env:USERPROFILE ".claude\skills"), (Join-Path $env:USERPROFILE ".config\opencode\skills"), (Join-Path $env:USERPROFILE ".codex\skills"), (Join-Path (Get-Location) ".agents\skills") ) | Where-Object { -not [string]::IsNullOrEmpty($_) } $hit = $roots | ForEach-Object { Join-Path $_ "regression-notes\scripts\verify-notes.py" } | Where-Object { Test-Path -LiteralPath $_ } | Select-Object -First 1 if (-not $hit) { throw "Could not locate regression-notes/scripts/verify-notes.py" } $SCRIPTS = Split-Path -Parent $hit
メモのルートはデフォルトで .agents/notes/ です。呼び出しごとに --notes-dir で、または NOTES_DIR 環境変数で全体的に変更できます。
はじめに
バグを修正するときは、ノートを作成し、回帰テストに紐付けます。
python3 "$SCRIPTS/new-note.py" --status implemented --test tests/test_login.py login-retry-race
--test は繰り返し指定でき、実際のテストパスを使って ## Verification を事前入力します。特定のテストを 1 つ紐付けるには、--test 'tests/test_login.py::test_retry_after_lockout' と記述します(回帰テストとの紐付けを参照)。テストファイルが存在し、テンプレートのプレースホルダーを実際の失敗実行を記録した Proved: 行に置き換えるまでは、厳格な検証は失敗します。
--class には、以下の限定されたクラスセット内の任意のクラスを指定できます。bug-fix 以外のクラスでは templates/generic.md を使用し、## Verification は必要ありません。
却下された提案の例:
python3 "$SCRIPTS/new-note.py" --status rejected --reason "duplicates the retry policy" login-retry-race
新しいノートを書く前に、すでにその決定を扱っているノートを探します。
python3 "$SCRIPTS/verify-notes.py" --notes-dir <notes-dir> --find "retry policy"
--find は、ノートのファイル名と本文に対して正規表現で照合し、一致する各ノートのパス、タイトル、決定、引用されたテストを出力します。管理が必要なインデックスファイルはありません。ツリー自体がインデックスであり、これを使って検索します。
ツリーを検証します。
python3 "$SCRIPTS/verify-notes.py" --notes-dir <notes-dir>
ゼロ以外の終了コードは失敗を意味します。ゲートには行がちょうど 1 行必要です。
python3 regression-notes/scripts/verify-notes.py --notes-dir .agents/notes
ドライラン中にノートのディレクトリが存在しなくても問題ない場合は、--allow-missing を使用します。コミットゲートではこのフラグを使用しないでください。
レイアウトと形式
ノートはパスで {proposed,implemented,rejected,archived}/{class}/yyyy-mm-dd-topic.md のように表されます。
- ライフサイクルはステータスです。
proposed/(Status: proposed)→implemented/(Status: implemented)→archived/(Status: implemented+Archived: YYYY-MM-DD)。proposed/からimplemented/へ移動する際は、## Proposalを現在形の## Decisionに書き換え、## Acceptance criteriaと## Risksを## Consequencesにまとめます。rejected/(Status: rejected — <why>)では提案時のセクション(## Problem、## Proposal、## Alternatives considered、任意で## Acceptance criteriaと## Risks)を維持し、却下された提案が魅力的な誤りであり続ける間だけ保存します。archived/のノートは凍結されます。Archived: YYYY-MM-DDが記載された後は編集してはならず、アーカイブされたすべてのノートは封印する必要があります(以下を参照)。
- クラスは固定されています:
bug-fix, feature, architecture, process, testing, simplification。クラスを追加するには、このファイルとverify-notes.pyのCLASSES定数を同時に更新する必要があります。new-note.pyは検証スクリプトからクラスセットを読み取るため、両者が食い違うことはありません。
すべてのノートは同じ骨組みに従います。bug-fix では templates/bug-fix.md を使用し、それ以外のクラスでは ## Verification を除いた同じ骨組みの templates/generic.md を使用します(テストを紐付けるのは bug-fix のみです)。
# Agent Note: <title>
Status: implemented
## Problem
## Decision
## Alternatives considered
## Consequences
## Verification # bug-fix only
ヘッダーブロック
ヘッダーは最小限の固定ブロックです。フロントマターに拡張しないでください。
# Agent Note: <title>
Status: implemented
Archived: YYYY-MM-DD # archived/ only
Superseded-by: <note.md> # archived/ only, optional
Partly-superseded-by: <note.md> # optional
# <- blank line ends the block
Superseded-by と Partly-superseded-by は、同じツリー内の別のノートを指定します。検証ツールは、各参照先が存在すること、自分自身のノートを指していないこと、参照チェーンに循環がないことを確認します。
Superseded-byは、後継ノートがこのノートを完全に置き換えることを意味します。archived/の配下でのみ有効であり、後継ノートには統合された根拠を記載する必要があります。Partly-superseded-byは、決定の一部が後継ノートに置き換えられる一方、残りは引き続き有効であることを意味します。部分的に置き換えられたノートは、そうでなければ現在の正式な判断と区別できないため、何が引き続き有効で何が無効になったかを示す## Supersededセクションが必要です。
検証ツールが適用するルール:
- ヘッダーブロックは正確に指定してください(
L1/L3、空のL2。アーカイブ済みのメモではStatus: implementedの直後にArchived:、その後に置き換え先の行を記載し、空行でブロックを終了します)。 Status:の行は必ず1行だけとし、フォルダーと一致させます。- 本文は
## Problemで始めます。 ## Alternatives consideredは必須です。proposed/とrejected/では## Proposal/## Acceptance criteria/## Planを使用できますが、implemented/とarchived/では使用できません。implemented/またはarchived/のbug-fixには、次の内容を含む## Verificationが必要です。- 実在するバッククォート付きのテストパスを1つ以上(
--no-strictを指定すると、存在しない対象は警告に格下げされます)。 - 回帰テストが修正前に失敗し、修正後に成功することを確認した旨を記録する
Proved:行。この行にテンプレートのプレースホルダーが残っていてはいけません。
- 実在するバッククォート付きのテストパスを1つ以上(
- マシン固有の絶対パスのトークン(レジストリハイブ(
HKLM\...、HKEY_CURRENT_USER)、ドライブパス(C:\...)、UNC/逐語的パス、POSIX ルート、%VAR%パス、scheme://URL)は、テスト対象として指定できません。メモ内でこれらに言及していても、世界の説明であり、テストを指定するものではありません。 - 置き換え先の参照先は解決でき、自己参照ではなく、循環していない必要があります(上記を参照)。
- メモのベース名はツリー全体で一意でなければなりません。
Superseded-byとメモへの参照ではベース名でメモを指定するため、bug-fix/2026-01-01-x.mdとfeature/2026-01-01-x.mdが同じ階層にあるとエラーになります。 - ファイル名には有効な暦日を含め、どこでも未来の日付にしてはいけません。日付のみのファイル名とアーカイブ日付の上限は、実行環境のタイムゾーンに関係なく、UTC+14 における現在の暦日です。
- メモツリーに置けるのは
.mdファイルのみです。翻訳版としての*.zh.mdの併置は許可されます。このファイルはゲートでスキップされ(形式チェックは行われません)、対応するメモの隣に置いて、両者の同期を保ってください。 - アーカイブ済みのメモはすべて
archived/manifest.jsonに封印する必要があります。封印済みのメモを後から変更または削除すると、検証に失敗します。
警告(エラーにはなりません。いずれもヒューリスティックによる参考情報です):
- 引用された
snake_case/Pascal_Case識別子が、メモで引用しているテストファイルに見つからない場合。テスト名が変更された可能性があります。--no-name-heuristicで無効にできます。 - バッククォートで囲まれた単独のソースファイル名(
OldTests.cs)がリポジトリ内のどこにも解決されない場合。--no-bare-resolutionで無効にできます。日付で始まるメモのファイル名は除外されるため、1つのトークンから警告が2つ出ることはありません。 - バッククォートで囲まれたメモのファイル名がツリー内に存在しない場合。メモの名前が変更または削除された可能性があります。
path::anchorのアンカーがそのファイルに存在しない場合。リポジトリ内の参照先が整理されたら、--strict-anchorsでエラーに昇格できます。メモ単位のanchor無効化設定は警告のみを抑制し、--strict-anchorsによるエラーは抑制しません。--dump-anchors(したがって CI のテスト一覧との積集合)ではarchived/のメモはスキップされます。アーカイブ済みのメモは封印され凍結されているため、名前が変更または廃止されたテストに合わせて編集できず、履歴に後から削除されたテスト名が記載されていても問題ありません。
ゲートを弱めずに、警告が出ない状態を保ってください(すべて汎用で任意、エラーは常にツリー全体を対象とします)。
# Per-note opt-out for one noisy legacy note (does not affect other notes;
# parsed from fence-stripped prose with inline code spans removed, so a fenced
# or backticked usage example cannot disable its own note's checks):
#
#
# Adopt incrementally: record today's warnings, keep the file in version control
# (--update-baseline cannot be combined with --changed-only: a partial-tree
# baseline would be incomplete)
python3 "$SCRIPTS/verify-notes.py" --notes-dir <notes-dir> --baseline .agents/notes-baseline.json --update-baseline
python3 "$SCRIPTS/verify-notes.py" --notes-dir <notes-dir> --baseline .agents/notes-baseline.json
# pre-commit: warnings only for notes changed versus HEAD (untracked included)
python3 "$SCRIPTS/verify-notes.py" --notes-dir <notes-dir> --changed-only
# nightly/CI: full warnings, optionally with --strict-anchors
python3 "$SCRIPTS/verify-notes.py" --notes-dir <notes-dir> --strict-anchors
--changed-only [--base HEAD] は、git ワークツリー外ではツリー全体を対象に切り替わります。パスは --repo-root を基準に解決されるため、サブディレクトリを repo-root に指定すると、そのサブツリーが対象になります。git で無視されるメモも、保守的に警告の対象のままです。単独ファイル名の解決では git ls-files が優先され(.gitignore を考慮し、モノレポでは大幅に高速です)、使用できない場合は枝刈りした走査にフォールバックします。
アーカイブの封印
アーカイブの凍結は慣習ではなく、機械的にチェックされます。アーカイブは、移動、ヘッダー、封印をまとめて一度に行ってください。
python3 "$SCRIPTS/new-note.py" --archive 2026-09-01-old-decision.md --successor 2026-09-09-new-decision.md --notes-dir <notes-dir>
--archive は実装済みのノートを archived/ に移動し、Archived: と Superseded-by: を挿入してから、検証して封印します。--by は --successor のエイリアスです。手動で行う場合は、ファイルを移動し、2行のヘッダーを追加してから、同じ変更内で verify-notes.py --seal を実行します。
--seal はツリーを検証した後、アーカイブ済みノートそれぞれの SHA-256 を archived/manifest.json に記録し、封印する各項目に名前を付けます。ダイジェストは LF に正規化 した内容を対象に計算されるため、チェックアウト時の改行コード(Windows の core.autocrlf)が変更と見なされることはありません。マニフェストは追記専用です。--seal は不足しているエントリーを追加し、記録済みハッシュの書き換えを拒否します。そのため、封印後に変更されたノートはエラーのままになります。履歴を編集するのではなく、新しいノートで修正してください。--reseal は、ツールの移行(ダイジェストアルゴリズムの変更、EOL 正規化の展開など)のための明示的な例外措置です。ダイジェストが一致しなくなったエントリーを書き換え、それぞれを表示するため、レビューで書き換えを確認できます。ゲート用のワンライナーを含む通常の検証では、封印されていない、変更された、または削除されたアーカイブ済みノートがあると失敗します。
ノートをアーカイブするのは、完全に置き換えられ、その後継ノートに統合された根拠が記載されている場合に限ってください。封印後はノートが凍結されるため、後から Superseded-by のポインターを追加しても修正できません。封印する前にポインターを正しく設定してください(上記の --archive コマンドは、この順序で処理するように設計されています)。
コーパスを最新の状態に保つ
コードと矛盾するノートは、ノートがないよりも悪いものです。古い情報を信頼するエージェントは、修正を元に戻してしまいます。
ノートを作成する前に、ツリーを検索し、同じ判断や仕組みを扱う既存のノートがないか確認してください(上記の --find)。重複させるのではなく、同じ変更内でそのノートを更新してください。
後の判断が以前の判断に取って代わる場合は、ヘッダーにリンクを記録し、古いノートが現在の根拠として読まれないようにしてください。
- 完全に置き換えられた場合 — 固有の根拠、代替案、影響、検証内容を新しい管理元のノートに統合してから、
new-note.py --archive <old>.md --successor <new>.mdを実行します(archived/に移動し、Superseded-by:を追加して封印します)。古いノートには履歴が残り、ポインターは現在その判断を管理しているノートを示します。 - 一部のみ置き換えられた場合 — 後継ノートが一方の分岐を扱い、残りは引き続き有効です。
Partly-superseded-by: <successor>.mdと、どの部分が無効になったかを記す## Supersededセクションを追加します。ノートはimplemented/に残してください。残りの部分については、引き続き有効な根拠です。
一部が置き換えられた判断を、本文中の注記だけで記録してはいけません。そうすると、置き換えられた ## Consequences セクションが、コードにはもう存在しない動作を主張し続けることになります。古くなった部分を明確に示すのは、ヘッダーのポインターと ## Superseded セクションです。
実装済みノートで参照されているファイルを、コードの移動、名前変更、削除によって変更する場合は、同じ変更内でノートのパスとシンボルも更新してください。検証ツールは、存在しないテストパス、解決できない単独のファイル名、参照先が存在しないノートを警告します。検証ツールでは検出できない古いモジュール名、デフォルト値、本文中の主張も、必ず確認してください。
回帰テストとの紐付け
ノートとテストのリンクは一方向で、レビュー可能です。ノートの ## Verification セクションにテストパスを記載し、仕様自体は通常のテストコードのままにしてください。同じ変更で両方を追加してください。テストのないノートは願望にすぎず、ノートのないテストは謎です。archived/ のノートは凍結されており、現在の動作の根拠として参照してはいけません。
特定のテストを1つ紐付けるには、パスとアンカーを :: で区切って記述します。
- `tests/test_login.py::test_retry_after_lockout`
アンカーは、そのファイル内の単純な部分文字列としてチェックされます。これが文法のすべてです。検証ツールはテスト言語を解析しないため、test_foo(pytest)、TestFoo(Go)、should foo(JS)、スナップショットのディレクトリ名のいずれでも同じように機能します。:: を含むトークンは、最初の :: より前の部分が既存のファイルである場合に限り、バインディングとして扱われます。そのため、C++ のスコープ解決(std::filesystem、Class::Method)がバインディングと誤認されることはありません。言語の一覧は不要です。
アンカー付きの形式を優先してください。tests/test_login.py だけでは、そのファイルの存在は証明できますが、テストの存在は証明できません。## Verification のどこかでテストを名前で記載し、アンカーを付けていない場合、検証ツールは警告します。名前が変更されたテストと単なる文章を見分けられないためです。
ガードとして機能するのは、そのガードによってリグレッションが失敗する場合だけです。また、失敗はバインディングが指定するアサーションで発生しなければなりません。フィクスチャ、環境、コンパイルエラーでは何も証明できないため、セットアップを修正し、バインドされたアサーションが想定どおりの理由で失敗するまで再実行してください。
証拠には 2 種類あり、どちらも同じ記録を共有します。
- 自然な失敗 — 実際に確認した失敗です。修正前に書いたテスト(TDD)、またはパッチ適用前にスイートで実際に発生した失敗が該当します。これだけで証明として成立するため、二度目に人為的な失敗を起こす必要はありません。
Proved:行には、確認可能な情報を記載してください。例:Proved: pre-fix run failed at <assertion>; output saved to <evidence-log>。「以前失敗した」というだけでログも出力もないのは、まさにこの行がなくすべき自己申告です。 - 人為的な失敗 — 修正後にテストを書き、失敗を一度も確認していない場合にのみ必要です。低コストで元に戻せる方法にしてください。ガードを1 つ無効にし、バインドされたテストだけを実行し(例:
cargo test --lib <name>)、失敗出力を保存してから、ガードを復元し、同じテストを再実行して成功させます。復元して再度成功させるところまでが手順の一部であり、省略できません。1 回の人為的な実行で、同じガードにバインドされたすべてのテストをカバーできます。異なるガードにバインドされたテストには、それぞれ個別の実行が必要です。
## Verification の Proved: 行に失敗実行を記録してください(例:Proved: disabled the latch → tests/test_login.py::test_retry_after_lockout failed as expected, then reverted; output saved to .agents/notes-evidence/login-retry-red.log)。証拠はコミット対象のディレクトリに置いてください。ノートツリー自体は .md のみを受け付けるため、その兄弟ディレクトリ(慣例では <notes>-evidence/)に置き、クリーンアップや gitignore の対象となる target/ のようなビルド出力ディレクトリには置かないでください。Proved: 行のバッククォートで囲まれたパスはテスト対象ではなく証拠として扱われるため、検証が失敗することはありません。ただし、証拠ファイルがない場合は警告されます。そのため、cargo clean で証明が消えてしまう Proved: 行が、何も言わずに通り続けることはありません。エージェント自身の出力ではなく、現実の状態に対して検証してください。コマンドを再実行する、外部からファイルを読み直す、といった方法を使います。
ノートは読まれないままでは何の価値もありません。--for-path は逆引き機能です。変更予定のファイルを渡すと、それらを参照しているノートが返されます。編集を始める場所に組み込んでください。たとえば、リポジトリのルールとして「編集前に変更対象ファイルに対して --for-path を実行する」と定める、参照しているノートを表示する pre-commit フックを設定する、またはその両方を行います。誰も覚えていないと実行されないリマインダーは、記憶に頼る儀式よりも価値があります。テスト一覧を出力できるリポジトリ(cargo test -- --list、pytest --collect-only)では、CI のステップで --dump-anchors の出力と実際の一覧を突き合わせ、名前が変更されても孤立した部分文字列として残るテストを検出できます。
ゲートで検証できるのは、存在するノートだけです。ノートが作られていない修正を見つけることはできません。--audit-commits [N] は、履歴側からこの抜けを埋めます。修正らしいメッセージがあり、コードを変更している一方で、ノートもテストファイルも追加していない最近のコミットにフラグを立てます。これはレポートであり、ゲートではありません。定期的に、またはバグ修正の作業後に実行し、フラグが立ったコミットを遡及的なノートの候補として扱ってください。
ポストモーテムを作成するタイミング
ポストモーテムを詳しく作成するのは、失敗が次の3つすべてに当てはまる場合に限ります。ベテランでも原因を特定しにくいこと、テスト・ツール・規約の抜け漏れなど、体系的な問題であること(単なるタイプミスではないこと)、そして原因の再発見にコストがかかることです。通常のバグには、ポストモーテムではなくメモを残します。
安全性
検証ツールはメモを読み取り専用で開き、プロジェクトのコードは実行せず、メモの内容を信頼できないテキストとして扱います。テストパスに関する記述を実際のリポジトリと照合してから作業してください。パス文字列があるだけでは、その動作が成り立つ証拠にはなりません。Proved: の行は検証手順を記録しますが、作成者が嘘をついて偽の行を書くこともできるため、最後はレビューで確認します。
バインディングと陳腐化のチェックは存在確認であり、証明ではありません。アンカーがファイルに存在していてもテストに合格するとは限りません。また、このスキルでは意図的にテストスイートを実行しないため、Proved: の行は実行なしでは検証できません。グリーンの実行結果は「ツリー内で整合性が取れている」と捉え、「修正が機能している」とは捉えないでください。
検証ツールの変更
scripts/ を変更した場合は、必ずテストスイートを実行してください。Windows では、テストプロセスに PYTHONUTF8=1 を設定し、Python のサブプロセスでも UTF-8 が使われるようにしてください。-X utf8 だけでは子インタープリターに引き継がれません。
python -X utf8 -m unittest discover -s regression-notes/tests
新しいチェックは、誤検知が言語やレイアウトを問わず確実に発生しないと証明できない限り、警告にしてください。エラーは、文法から完全に判定できる構造上の事実(ファイルの欠落、不正なヘッダー、解決できないポインター)に限ります。言語規約のような要素(テストの命名、シンボルの解決、モジュールのレイアウト)に関するものはすべて、無効化フラグを付けた警告にします。正しいツリーに対して誤作動するチェックは、ゲートを無視するよう人々に学習させてしまうためです。最適化は汎用的に保ってください。言語のリストを設けず、標準の Python 以外に必須のツールを要求せず(git は任意の高速化手段とし、使用できない場合は走査にフォールバックします)、プロジェクトごとの設定も設けないでください。