STEP 2134 — daily-banner activator regex silent-failure gate

status: (未 review)

Status: discipline 実装 land、 pre-commit hook Section 10 として 発火中、 藤本さん review 前 (2026-09-19 相手 外出中 に 実装完了)
Tab: rei-aios-6c [278598] · Date (JST): 2026-09-19T01:05
Origin: STEP 2124 corrigendum learnings #2 → 藤本さん explicit go (A) accept
Commits: f4eabba5f (primary、 13 files) + 3e912820f (banner regen、 🛡️ pill fire) → main branch pushed
Cross-ref: STEP 2117 (Antihydra note、 §2.1 撤回 対象) · STEP 2118 (§4.1 cross-ref) · STEP 2124 (corrigendum、 learnings source、 site page なし = memory-mirror factcheck-v2 record)
★ Review 待ち 項目: (a) 「全 TS file の regex literal bulk verify」 への 一般化 (現在 は narrow scope = build-daily-banner.ts only)、 (b) 「E2E test で pill 発火 verify」 (semantic + match correctness、 現在 は syntax error のみ catch)、 (c) 「pre-commit hook Section 10 が invalid regex を 実 abort する」 の end-to-end test (現在 は verifier self-test 12/12 PASS + section shell trivial、 但し hook 全体 と の 組合せ test なし)。 3 件 とも 藤本さん judgment 待ち defer、 私 独断 実装 なし。

1. 失敗事例 (STEP 2124 30+ 分 遅延)

実測 fixture: scripts/build-daily-banner.tshasStep2124AntihydraReversalPreRegBFire activator regex に:

Syracuse.*+1.*抜き.*撤回

を 含めた。 これ は JavaScript regex で 「Nothing to repeat」 error (invalid): + は 単独 quantifier で、 .* の 直後 に literal + を 置く と 「量指定子 の 直後 に 量指定子」 と 解釈される。 正解 は Syracuse.*\+1.*抜き.*撤回 (\+ escape)。

Symptom: tsx runtime は parse-error recovery で 該当 regex を skip、 data/daily-banner.json は 生成 されるが 該当 pill が false = 「script は exit 0 で 呼吸してる が pill 判定 は 静かに false」 pattern (STEP 1610 candidate F distinction green-washing pathology 同型)。

Timeline:

2. 実装 3 layer

2.1 Layer 1 — Verifier: scripts/verify-daily-banner-regexes.ts

TypeScript Compiler API 経由 の regex literal enumeration + V8 compile 検証:

2.2 Layer 2 — Self-test: test/step2134-verify-daily-banner-regexes-test.ts

6 test / 12 assertions PASS
Test検証内容Verdict
T1STEP 2124 replay fixture (Syracuse.*+1) → exit 1 + stderr に「Nothing to repeat」 or 「Invalid regular」 hit2 assertions PASS
T2Valid-only fixture (Syracuse.*\+1) → exit 0 + stdout 「0 invalid」2 assertions PASS
T3Edge-case (character class 内 escaped /) → exit 0 (誤検出なし)1 assertion PASS
T4Production build-daily-banner.ts (79 regex) → exit 0 + 「0 invalid」2 assertions PASS
T5Non-existent target → exit 21 assertion PASS
T6--json mode → parseable JSON with failures[] 構造 verify (failed count + passed count + error message pattern)4 assertions PASS

2.3 Layer 3 — Pre-commit gate: .githooks/pre-commit Section 10

scripts/build-daily-banner.ts が staged (diff-filter=ACM) の 時 のみ 発火:

if [ "${SKIP_DAILY_BANNER_REGEX_CHECK:-0}" != "1" ]; then
  bdb_staged=$(git diff --cached --name-only --diff-filter=ACM 2>/dev/null \
    | grep -E '^scripts/build-daily-banner\.ts$' || true)

  if [ -n "$bdb_staged" ]; then
    echo "[pre-commit] (daily-banner-regex) build-daily-banner.ts staged → running verifier"
    if npx tsx "$repo_root/scripts/verify-daily-banner-regexes.ts" 2>&1; then
      echo "[pre-commit] (daily-banner-regex) check: OK (all regex literals compile)"
    else
      echo "[pre-commit] (daily-banner-regex) ★ ABORT: invalid regex literal(s) in build-daily-banner.ts" >&2
      echo "[pre-commit] (daily-banner-regex) fix the regex, or bypass with: SKIP_DAILY_BANNER_REGEX_CHECK=1 git commit ..." >&2
      exit 1
    fi
  fi
fi
Self-verification on the very commit that introduced the gate (f4eabba5f):
[pre-commit] (daily-banner-regex) build-daily-banner.ts staged → running verifier
[verify-daily-banner-regexes] target=scripts\build-daily-banner.ts
[verify-daily-banner-regexes] checked 79 regex literals, 0 invalid
[pre-commit] (daily-banner-regex) check: OK (all regex literals compile)

3. npm scripts

Script用途
npm run verify:daily-banner-regexes単独走査 (CLI or CI)
npm run test:step2134Self-test (6 test / 12 assertions)

Bypass (edge case のみ、 default で は 使用 しない):

SKIP_DAILY_BANNER_REGEX_CHECK=1 git commit ...

4. Discipline 位置付け

5. Honest scope (最重要、 4 明示)

6. Failure mode dataset (未来 Claude 予防用)

#failure mode予防
fm2134-1verifier 自身 の bootstrapping paradox (「verifier が 自身 の regex で silent failure」)T4 で production 実 file を verify + T1-T3 で 既知 fixture の 期待動作 verify、 verifier 自身 は 最小 regex 使用 (^\/([\s\S]*)\/([gimsuy]*)$ のみ)
fm2134-2pre-commit hook が invalid regex に対して 誤って pass (false negative)T1 で STEP 2124 実測 fixture (Syracuse.*+1) を replay、 exit 1 + stderr 「Nothing to repeat」 hit verify
fm2134-3edge-case regex (character class 内 escaped /) で verifier が 誤検出 (false positive)T3 で edge-case fixture verify、 誤検出 なし
fm2134-4production build-daily-banner.ts に 追加 STEP activator が invalidpre-commit hook Section 10 が 事前 catch (本 STEP の 本体)
fm2134-5semantic / match correctness は 本 gate の scope 外 = 別 layer 必要明示外 = 別 STEP defer (E2E pill 発火 verify)、 未来 candidate registry に 記録

7. Discipline 循環 の operational 実例

STEP 2124 で 実測 された failure mode → learnings 抽出 → 藤本さん explicit go (A) → 同日中 に discipline 化 完了 = 4 STEP loop close: STEP 2117 (base) → STEP 2118 (併走) → STEP 2124 (corrigendum) → STEP 2134 (gate 実装)。 藤本さん の discipline 「事前登録 反証条件 + 早期 catch gate」 の 循環 が 1 日以内 で operational に 完了 した 例。

8. Cross-reference