Sprint 150 Unresolved Automation Debt — 3-Item Batch (.claude-tools/ RUNBOOK + CI Weekly Cron + prom-client Stale Check)

SummaryBatch-resolve in a single day the 3 automation debts identified as Sprint 150 seeds (inheriting Sprint 150 pattern)

Date
ImpactHigh
PRs4
Lines changed+642 -8

Implementation Phases

A
#249

A

scribe+86 −3
B
#250

B

architect+321 −3
B

B

scribe+1 −1
C
#251

C

architect+234 −1

Key Decisions

Phase A

.claude-tools/ discovered as .gitignore untracked → plan adjusted. Instead of actual file markers, formalize operational policy in tracked RUNBOOK (docs/runbook/claude-tools.md) (Oracle ruling, safety-first principle)

Phase B

User confirmed Option A (weekly cron creation only). Reuse ci.yml existing rebuild_all input → workflow_dispatch trigger with 0 code duplication

Phase C

collectDefaultMetrics() duplicate call confirmed to actually throw (test failed on first run) → spec rewritten as "defensive rationale documentation". Canonicalized the reason @Global singleton is mandatory as regression-blocking spec

Goals

  • Batch-resolve in a single day the 3 automation debts identified as Sprint 150 seeds (inheriting Sprint 150 pattern)
  • Simultaneously address 3 domains: .claude-tools/ cleanup / CI paths filter bypass debt exposure automation / prom-client default metric stale check
  • Verify effectiveness of Sprint 155 3-layer safety net + Auto-Critic queuing across all PRs in this sprint

Decisions

  • Phase A: .claude-tools/ discovered as .gitignore untracked → plan adjusted. Instead of actual file markers, formalize operational policy in tracked RUNBOOK (docs/runbook/claude-tools.md) (Oracle ruling, safety-first principle)
  • Phase B: User confirmed Option A (weekly cron creation only). Reuse ci.yml existing rebuild_all input → workflow_dispatch trigger with 0 code duplication
  • Phase C: collectDefaultMetrics() duplicate call confirmed to actually throw (test failed on first run) → spec rewritten as "defensive rationale documentation". Canonicalized the reason @Global singleton is mandatory as regression-blocking spec
  • Single sprint 3 PRs + 1 fix commit — directly inheriting Sprint 150 (3 PRs) / Sprint 154 (3 PRs + 1 fix) bundle pattern

Implementation (3 PRs squash merge + 1 fix commit, origin/main a7cf22716d405a)

Verification

  • All 3 PRs CI fail 0, mergeStateStatus CLEAN (28 SUCCESS / 11 SKIPPED / 0 FAIL)
  • node scripts/check-doc-refs.mjs --include-untracked — 169 files, 0 broken refs (using Sprint 155 output)
  • submission/metrics.service.spec.ts — 13 PASS / 0 FAIL (including 3 new regression-blocking cases)
  • 2 new RUNBOOKs (claude-tools.md / ci-full-validation.md) + §9-3 passed self-lint (meta-self-verification)
  • Sprint 155 3-layer safety net (plan + pre-push + CI lint) effective on all sprint commits — 0 violations

Branch Discipline ✅ 24 sprints consecutive compliance

All 3 PRs used new branches + Squash merge, 0 direct commits to main (since Sprint 134 violation).

New Patterns

  1. Plan assumption broken → immediate re-routing (reproducing Sprint 147/152 lesson) — Phase A adding deprecated markers to .claude-tools/ became meaningless when discovered as untracked. Immediately re-routed to tracked RUNBOOK. 0 impact on Oracle ruling cycle
  2. User ExitPlanMode option selection → sprint scope clarification — User confirmed option among Phase B A/B/C, then proceeded with plan as-is. Large decisions (coverage-gate hardening) explicitly deferred to separate sprint carryover
  3. Test first-failure exposes defense mechanism essence — Phase C collectDefaultMetrics() duplicate call breaks idempotent assumption. Spec rewritten as "defensive rationale documentation", canonicalizing why @Global singleton is mandatory
  4. Post-rebase cumulative count fix pattern — When same location (runbook count) is modified concurrently, git auto-merge only reflects one side. After PR #249 merge, PR #250 rebase left count at 18 → fix commit to update to 19. Evolution of Sprint 150 PR #226+#227 concurrent count update pattern
  5. Tracked RUNBOOK secures operational visibility for untracked tools — Exposes operational policy of .gitignore-protected .claude-tools/ in a separate tracked document. Achieves both security (BOT_TOKEN not exposed) + visibility simultaneously