feat(rules): enforce artifact>testimony — RULES.md + evidence-check gate - #160
feat(rules): enforce artifact>testimony — RULES.md + evidence-check gate#160sururu-k wants to merge 2 commits into
Conversation
…k gate RULES.md makes the anti-hallucination principle the repo's single machine-checkable norm (CLAUDE.md and the templates point to it). The enforcement is mechanical, not a doc that can be ignored: - scripts/evidence_check.py re-EXECUTES every '<!-- RERUN: <cmd> EXPECT <substr> -->' in a PR body, so a pasted or fabricated log cannot pass; VERIFIED claims need an adjacent raw-log fence (R1/R3/R5). 'UNVERIFIED' is a passing state (R2). Size gate fails >40 changed files without SPLIT-JUSTIFIED (R6). Ships with a red-before-green selftest: honest doc PASS, fabricated doc (RERUN->confirmed=0) FAIL. - ci/evidence-check.yml runs the gate on every PR body; RERUN executes only for internal branches (fork PRs get structural checks). Shipped under ci/ because the authoring token lacks GitHub 'workflow' scope — a maintainer installs it to .github/workflows/. Until then the gate runs locally / pre-commit / manually. - PR template generalizes the #159 red-before-green box into Evidence/UNVERIFIED blocks (red-before-green is now rule 4, refute-don't-confirm). Rule 5's non-deterministic cross-check path (independent subagent) is intentionally not in this PR — deterministic CI gate first, staged rollout to avoid a #118-size change. Refs: #159 (red-before-green precursor), #134 (CI-green-but-broken), #118 (oversized PR)
Makes RULES.md's claim true — the shared instruction layer now actually points to it (CLAUDE.md working-rules section, bug-report evidence note), per the original ask to embed the norm in CLAUDE.md / PR template / issue templates.
|
ブランチを手元に落として全部走らせました。以下、貼ってあるのは全部その実行結果です。環境は手元の Linux + uv、 再実行を軸に据えた設計は正しいと思います。 そのうえで、今のままだと止めたい失敗が通り抜けます。 1. #117 の本文がそのまま緑で通るCI は 本文が空でも同じです。 証拠提出が opt-in なので、最短で緑にする方法が「何も書かない」になっています。 直し方
2. RERUN が終了コードを見ていない
赤にならない検証で緑を取るのは #134 そのものなので、それを止める道具の中にあるのはまずいです。 直し方
out = (p.stdout or "") + (p.stderr or "")
if p.returncode != 0 and expect_rc is None:
return Finding("FAIL", "R1/R5", f"RERUN exited rc={p.returncode}: {cmd}\n {out.strip()[:300]!r}")
if expect_rc is not None and p.returncode != expect_rc:
return Finding("FAIL", "R1/R5", f"RERUN rc={p.returncode}, expected {expect_rc}: {cmd}")rc が非 0 になるのが正しいケース(pre-fix の赤ログなど)用に、マーカー側に テンプレの例は 3. 未編集のテンプレを出すと落ちる原因は2つあります。 プレースホルダの もう1つは HTML コメントがネストしないことです。テンプレ 35行目の 1 と組み合わさると勾配が逆を向きます。テンプレを正直に埋めると赤、マーカーを消すと緑です。 直し方
4. CI に uv が無い
未確認: 実際に GitHub Actions 上で走らせていないので、 直し方 tests-on-push.yml の28〜35行をそのまま持ってくる。あわせて 未確認: 5. ゲートが PR 自身のチェックアウトから走る
素朴な改竄は 抜けるのは狙った改竄のほうです。 直し方 ゲート本体を base から取る。 - name: Fetch gate from base
run: |
git show "origin/${{ github.event.pull_request.base.ref }}:scripts/evidence_check.py" > /tmp/gate.py
- name: Enforce
run: python3 /tmp/gate.py --body pr_body.md --changed-files "$CHANGED" --strict-claimsあわせて 6. マージしても何も強制されない状態で、RULES.md は強制されていると書いているワークフローは PR 本文の そのうえで、issue #41 が言っていた自己申告から CI 強制への移行は、以下3つが揃って初めて成立します。このPRだけだと #159 と同じ「欄があるだけ」の状態のままです。
RULES.md の中身7. 冒頭で、存在しない文書に優先順位を宣言しているこの2つはこの repo に一度も存在したことがありません。リポジトリの状態についての裏取りなしの記述が、契約書の1段落目にあります。 直し方 括弧を落として 8. Evidence Block の唯一の手本が再現しないL139-144 の例を verbatim で実行するとこうなります。
RULES.md を自分のゲートに通すと落ちます。 人はルール本文よりも例をコピーするので、ここが一番効きます。 直し方
- name: Gate the rules doc itself
run: python3 /tmp/gate.py --body RULES.mdこれを入れておけば、二度と走らない例が RULES.md に入ることはなくなります。 9. #134 がルール上まったく捕まらない#134 は証拠を出さなかった案件ではありません。テストはあったし、走ったし、CI は緑でした。壊れていたのは fixture がクライアントごとに別 ID で、見たかったケースを踏まなかったことです。 このスキームで #134 を書き直すと、著者は正直に 足りないのは「証拠があること」ではなく「証拠が偽のとき赤くなること」です。R4 は態度としては書いてありますが、Evidence Block のスキーマに落ちていないので強制手段がテンプレの欄しかなく、そこは #159 と同じ自己申告です。 直し方 Evidence Block に
チェッカー側は、まず 10. #117 型は原理的に捕まらない#117 は Major 1 が未対応のまま both addressed と返ってきた件でした。Evidence Block は書かれた主張を検証する仕組みなので、書かれなかった主張については何も言いません。指摘5件のうち4件に完璧な証拠を付けて1件黙る、が満点で通ります。 証拠の質ではなく被覆の話なので、R1〜R6 のどれとも別の軸が要ります。 直し方 7つ目のルールとして足す。 テンプレ側は Reviewer notes の下に「指摘への応答」表を置いて、レビュー指摘の番号・状態・証拠へのリンクを1行ずつ書かせる形が実務的だと思います。 11. R1 の「同一ターン」は外から検証できない同じターンかどうかはレビュアには分かりません。RULES.md 自身も「再実行するので鮮度は問題でなくなる」と書いていて、R1 は自分で自分を無効化しています。効かせたい性質は鮮度ではなく、証拠と対象コミットの対応のはずです。 あと「ターン」は AI 側の語彙なので、human and AI 両方の contract を名乗るなら R1 だけ読者が限定されています。 直し方 12. R2 が万能の抜け道になっている
直し方 R2 に、UNVERIFIED にできない項目のリストを付ける。 チェッカー側は、PR テンプレの Type of change のチェック状態を読んで、bug fix にチェックがあるのに 13. R5 は再実行と独立性を混同している再実行が与えるのは再現性で、独立性ではありません。claim も RERUN も著者が書くので、著者の検証モデルが間違っていれば、第三者が独立に回し直しても著者の盲点をそのまま再現します。#134 がまさにそれです。 Enforcement 表が 直し方 表の R5 の行を分けて、mechanism を 14. R6 は #118 の何が問題だったかとずれている#118 の本質は136ファイルではなく、#27 と #29 を1本にまとめたことです(issue #41 にそう書いてあります)。ファイル数を閾値にすると、正当な機械的リネームは落ちて、関心事が2つ混ざった3ファイル PR は通ります。 直し方 チェッカー側は、PR 本文から 15. Evidence Block に4つ目の部品が要るclaim と command を結ぶ根拠がありません。上の 2 で貼ったとおり 直し方 自然文の claim をやめて、claim を「コマンド + 期待」から生成する。書き手も楽になるし、自然文の claim 自体が testimony なので原則にも合います。互換のために 16. 規律クラスタが1行も入っていないissue #41 の実測で self-merge・明文化ルールの逸脱が 5/24 = 21%、実行系の次に大きいクラスタでした。RULES.md は every human and every AI session の contract を名乗っているので、読み手は網羅と受け取ります。 直し方 末尾に一段落足す。 17. 4層目の norm doc になっている「A norm doc alone gets ignored — that is the failure this repo keeps repeating」と書いた直後に、CLAUDE.md に9行の要約が重複しています。現時点で2箇所メンテです。 直し方 CLAUDE.md 側は1行のリンクだけにする。 ## Working rules
[RULES.md](RULES.md) がこの repo の作業契約。長い説明とここが食い違ったら RULES.md が勝つ。18. R3 のキーワード検出はこの repo だと誤検知する
直し方 19. gate 自体に pytest が無いこの repo の pre-flight は 直し方 20. fork ゲーティングの説明が実装と違うワークフローのコメントに このPRのは 優先順位マージ前: 7, 8(捏造2件)→ 2, 9(赤にならない検証)→ 1, 3(緑の取り方が逆)→ 4 そのあと: 10, 12, 5, 6 後続で: 11, 13, 14, 15, 16, 17, 18, 19, 20 9 と 2 は同じ穴の表と裏です。 |
Summary
RULES.md(6 rules + Evidence Block schema), pointed to by CLAUDE.md and the templates.scripts/evidence_check.pyre-executes everyRERUNrecipe in a PR body, so a pasted or fabricated log cannot pass. This generalizes chore(pr-template): red-before-green acceptance gate for bug fixes #159's red-before-green box (template-only, self-reported) into a gate.ci/evidence-check.ymlfor a maintainer to install (this token lacks GitHubworkflowscope).Type of change
Test plan — Evidence Blocks (dogfooding RULES.md)
Related issues / context
Refs #159 (red-before-green precursor), #134 (CI-green-but-broken), #118 (oversized PR).
Reviewer notes