feat(ADR-0114a.5): reasoning-isolation perturbation suite — Obligation #5 wired for B3, PASSING 130/130 preserving, 68/68 breaking (#191)
Discharges ADR-0114a Obligation #5 for the B3 bounded-grammar lane.
Closed perturbation taxonomy (5 invariance-preserving, 3 invariance-breaking
transforms) operates on problem text only; parser, solver, and cases.jsonl
are untouched. Both rates are ε=0 per ADR-0120 §"Threshold rationale".
Results on main B3 (35 solved_correct cases):
invariance_preserving: 130/130 = 1.0000
invariance_breaking: 68/68 = 1.0000
obligation_5_passed: True
Skipped transforms documented explicitly (not silently absent):
commutative_reorder: all 35 — no single-entity multi-unit init state
op_verb_flip: 15 — multiply/divide/compare/transfer cases
value_replacement_op: 15 — no distinct numeric operand
unit_synonym: 7 — rate-declaration $ syntax cases
value_replacement_init: 7 — value cancels or not found
entity_rename_v{1,2,3}: 1 each — b3-013 "Birds" collective is self-mapping
Ships:
core/capability/perturbation_b3.py — generator + scorer + validate_perturbation_suite()
tests/test_adr_0114a_5_perturbation.py — 15 tests (purity, preserving, breaking, determinism, snapshot, refusal, skip coverage)
core/cli.py — core capability perturbation [--lane-id] [--json]
evals/obligation_5_perturbation/B3_bounded_grammar.json — written by CLI
docs/decisions/ADR-0114a.5-perturbation-suite.md — ADR with taxonomy tables