Files
portal/docs/superpowers/plans/2026-05-25-enforce-hard-rules.md
T

4.4 KiB

Enforce hard rules — implementation plan

Spec: docs/superpowers/specs/2026-05-25-enforce-hard-rules-design.md Branch: feat/enforce-hard-rules Estimate: 4-8 hours autonomous (overnight)

Tasks (in commit order — each commit standalone testable)

T1 — Shared hook helpers + override vocab

Files: tools/enforce-hook-helpers.mjs, tools/enforce-hook-helpers.test.mjs, tools/enforce-override-vocab.json Helpers: readStdinJson, readTranscript, getCoverageFromLastAssistant, hasOverridePhrase, loadVocab, sentinelPath, writeSentinel, readSentinel, expectedBranchPath, getExpectedBranch, setExpectedBranch, readRationalizationFlags, appendRationalizationFlag. Override vocab content: initial 6 phrases per spec §9. Coverage: skill:superpowers:test-driven-development

T2 — Rule #5 memory-sync coverage (PreToolUse)

File: tools/enforce-memory-coverage.mjs + test. Simplest rule, easy validation. RED test: prod-code edit with TDD coverage → block. GREEN: memory edit with memory-sync coverage → allow.

T3 — Rule #7 branch-switch detection (PreToolUse Bash)

File: tools/enforce-branch-switch.mjs + test. Reads expected-branch file, runs git branch --show-current, compares.

T4 — Rule #4 verify-before-push (PreToolUse + PostToolUse Bash)

Files: tools/enforce-verify-before-push.mjs (PreToolUse) + tools/enforce-verify-record.mjs (PostToolUse to write sentinel) + tests. PostToolUse runs after Bash with vitest/pest pattern. If exit 0 + stdout has PASS marker → write sentinel. PreToolUse on git commit/push checks sentinel age + exists.

T5 — Rule #2 coverage-verify (Stop)

File: tools/enforce-coverage-verify.mjs + test. Parses last assistant message for coverage line, checks against transcript tool_use history.

T6 — Rule #1 mandatory re-classification injection (UserPromptSubmit)

File: tools/enforce-prompt-injection.mjs + test. Reads classifier output from router-state-*.json, injects mandatory coverage list via stdout JSON.

T7 — Rule #3 + Rule #6 TDD + writing-plans gate (PreToolUse Edit/Write/MultiEdit)

File: tools/enforce-tdd-gate.mjs + test. Path-match, transcript-scan for test-edit + vitest-fail-output, OR plan-file-exists.

T8 — Rule #8 classifier-mismatch (Stop)

File: tools/enforce-classifier-match.mjs + test. Reads classifier output, checks turn for matching Skill/Task tool_use, gates on confidence threshold.

T9 — Rule #10 rationalization flags (PostToolUse Bash + Edit/Write)

File: tools/enforce-rationalization-audit.mjs + test. Scan transcript for rationalization phrases / weak tests; append flag JSONL.

T10 — Atomic wire-up

File: .claude/settings.json — add all hooks to PreToolUse/PostToolUse/UserPromptSubmit/Stop. Critical: this must be the LAST commit. Pre-wire commits keep hooks inert.

T11 — Smoke + push

Manual smoke each hook with synthetic stdin. Then git push origin feat/enforce-hard-rules:main via FF (or merge-commit if main moved).

T12 — Memory + state sync

Create memory/project_enforce_hard_rules.md, update MEMORY.md index, project_state.md, reference_github.md.

Risks identified, mitigations

  • R1: Parallel session edits .claude/settings.json while I'm working. Mitigation: Read settings.json fresh right before T10. Use git stash for any concurrent local changes if needed.
  • R2: A rule blocks my own work mid-task. Mitigation: Rules inert until T10. If T10 wire-up succeeds and immediately blocks me on T11 push, override-vocab is in place (recovery phrase).
  • R3: Hook scripts crash → all subsequent tool calls hang. Mitigation: Every hook wraps logic in try/catch, exits 0 with empty {} on internal error (fail-quiet). NEVER exit 2 unless intentional violation found.
  • R4: Override-vocab phrase appears coincidentally in user's normal speech. Mitigation: Phrases chosen to be unusual (включают «без скилов» which is unlikely normal).
  • R5: PreToolUse latency on Bash slows every command. Mitigation: Hook target deltay <100ms by reading minimum (cached classifier-state, sentinel file, no transcript-parse unless rule triggers).

Acceptance criteria

  • All 10 rules implemented with unit tests
  • All hooks wired in settings.json
  • Manual smoke per hook: fake-stdin → expected exit code + stderr
  • Push to origin/main (or PR if main is unstable)
  • Memory + project_state synced