STEP 1635 — refactor-guard v0.1-spike

2026-08-31 · 藤本さん 「既存 AI 実装不可能パーツ」 arc 第 2 段 · STEP 1632 arbitrariness_audit の temporal 相補 · 起源: STEP 1624 chat-Claude 8th review

目的

過去 の 病理 shape への 回帰を 静かに 許さない refactor guard の 実装装置。 spec は 宣言的 (pathology + correct shape + sweep values + invariant kind)、 driver は 各 guard 固有 (どう input を setup し、 どう output を extract するか)、 runtime は generic invariance checker (constant / monotonic / custom)。 registry で 一括 exec + 単独 test でも run 可能。

STEP 1624 chat-Claude 8th review 引用: 「windowCompared = min(oracleReturned, perFeedDeclaredRetention) は 退役させた v0.2 病理と 形が 同一、 違いは 第二引数の 出自だけ (要件由来 vs 計器の 状態)、 安全性が その 一語に 全部 乗っている、 将来 だれかが 『簡略化』 で actualRetention に 戻したとき diff 上は 式が 変わったように 見えない、 コメントより test で 縛るほうが refactor を 生き延びる」

設計

type RefactorGuardSpec<TOutput> = {
  name: string;              // kebab-case unique
  stepOrigin: number;         // 病理を fix した STEP
  authoredAt: string;         // ISO date
  description: string;
  pathologyShape: string;     // 過去 病理 shape の 一文
  correctShape: string;       // 現在 correct shape の 一文
  sweep: { variable, values }; // どの変数を どの値で 変化させるか
  run: (v) => TOutput;         // target を setup + 実行
  extract: (o) => unknown;      // check 対象の 値を 抜き出す
  invariant:
    | { kind: "constant"; expected; reason }
    | { kind: "monotonic-increasing"; reason }
    | { kind: "monotonic-decreasing"; reason }
    | { kind: "custom"; check; reason };
};

runGuardSpec(spec) → { pass, observations, reason, ... }
runGuardRegistry(specs[]) → { results, passed, failed }

invariant kind

kind意味用途
constant全 sweep 値で extract() 結果が 一定STEP 1624 型 (「独立性」 の 表現)
monotonic-increasingsweep 順に 単調非減少累積 count / progress
monotonic-decreasingsweep 順に 単調非増加収束 / countdown
custom任意 predicate on 抽出列複雑 invariant / 集約制約

load-bearing evidence — STEP 1624 guard の 実測

test/refactor-guards/step1624-window-compared.guard.ts が 最初の 具体 guard。 sweep = actualRetention ∈ {9, 10, 20, 50, 100}、 invariant = windowCompared === 9。

Section 9: 現行 v0.7+ 実装 に対する 実測 (guard PASS 期待)

actualRet=9    windowCompared=9
actualRet=10   windowCompared=9
actualRet=20   windowCompared=9
actualRet=50   windowCompared=9
actualRet=100  windowCompared=9
verdict: PASS

windowCompared が sweep 全域で 一定 = perFeedDeclaredRetention (=9) から 導出される 正しい実装。

Section 10: v0.2 病理 shape を 意図的に 再現した run() (guard FAIL 期待)

actualRet=9    windowCompared=9     ← 偶然 一致
actualRet=10   windowCompared=10    ← 病理 露呈
actualRet=20   windowCompared=20
actualRet=50   windowCompared=50
actualRet=100  windowCompared=100
verdict: FAIL — 「sequence tracks the sweep instead of staying at 9」

これが load-bearing evidence — guard は 正しく discriminate する。 未来の author が 「簡略化」 で min(oracleReturned, actualRetention) に 戻すと、 npm test で 即座に 落ちて 過去 incident に redirect される。

実装場所

scripts/checker/refactor-guard.ts      — runtime (~180 lines、 4 invariant kind、 error handling)
test/refactor-guards/
  └── step1624-window-compared.guard.ts — 最初の 具体 guard (STEP 1624 起源)
test/step1635-refactor-guard-test.ts   — 31/31 PASS (12 section)
package.json:
  "test:step1635": "tsx test/step1635-refactor-guard-test.ts"

guard 追加手順 (未来 author 向け)

  1. 病理を 発見・修正した STEP N で、 fix が 「diff 上は 見えにくい」 shape であるか 判定
  2. test/refactor-guards/stepN-<slug>.guard.ts を 新規作成、 export const spec: RefactorGuardSpec<T> を 定義
  3. test file で import + registry に 追加、 npm run test:step1635 で 現行実装が PASS を verify
  4. pathology shape を 意図的に 再現した spec (別 run() で) が FAIL することを 別 section で verify
Honest scope (v0.1-spike の 限界):

arbitrariness_audit (STEP 1632) との 相補関係

arbitrariness_audit (spatial)refactor-guard (temporal)
質問「今 sensor に arbitrary な数が 何個あるか」「過去 の 病理 shape に silently 戻ったか」
実装静的 regex 分類器 (source file scan)runtime spec + sweep + invariance checker
判定単位literal 単位 (declared==0 で PASS)sweep 全体で invariant 保持
trigger誰かが inline literal を 追加誰かが 過去 病理 shape に 戻す
test runnertest:step1632test:step1635

両方 CI に wire すると、 「置いた数の 集約」 も 「時間を 跨いだ shape 保持」 も 機械が 見張る。 LLM が call 単位で 出せない invariant の 種類 (時間、 依存関係、 出自) を 静的な 部品として repo に 常駐させる 実装。

次段 (第 3 段)

hash-chained claim ledger — d8_ledger_query (STEP 1402) の 上に append-only + hash 連鎖を 乗せ、 refactor guard test を ledger entry に bind。 「誰かが test file を silently 削除する」 も ledger との 整合 check で 検出可能に。 LLM が call を 跨いで 「過去の 判定を 書き換える」 を 構造的に 禁止。 本 STEP の 完了で 藤本さん の go 待ち。

参照

Commit: 別 push で 反映 · Mirror force-track 対象 · Rei-AIOS Windows session · STEP 1554 atomic-commit dogfood