RETE second-wave optimizations (cluster-cProfile-driven)

Builds on v0.5.420 baseline (combined_40_ings recipe wall 22.4s, dev cluster).
This release ships 4 additional optimizations targeting v0.5.420's top
remaining hot spots:

H1: prop dataclass plan caching (83eaa9767)
  unvalidated_construct + __post_init__ iterate __dataclass_fields__.items()
  on every Prop construction. Hoist to per-class plan cached at first touch.
  Local: -8.3% median two_origins, -62% items() count.

H2: pydantic-class isinstance bypass on RETE hot path (7153e5887)
  39.7% of isinstance calls on RETE hot path were pydantic Node/Condition
  checks (slow __instancecheck__ via _abc_instancecheck). Replace with
  type-name MRO frozenset cached per class. Class-level _or_filter_attr
  dispatch in alpha_network.py:1445 replaces 5-way isinstance branch.
  Local: -39.7% isinstance count on two_origins.

H3: per-GFM alpha index for reset_gfm_activation (a01bfdee5)
  6284 calls/recipe on combined_40 was iterating all alphas with prefix
  string compare. Build _alphas_by_gfm: dict[str, list[AlphaNode]] once at
  register_gfm time. Reset reads precomputed list instead of scanning.
  Local: -67% function-level cumtime; cluster impact at 6284 × 50µs scale.

H4: pydantic __getattr__ bypass in NodeAttribute(Condition|Alpha) (d32ceccc4)
  290K calls/recipe on combined_40 to pydantic main.__getattr__ at 1.58µs
  each (1.07s cumtime). NodeAttribute(Condition|Alpha) check `is_*` markers
  set via object.__setattr__; replace getattr with node.__dict__.get(name).
  Local: -42.3% __getattr__ count, -11.5% median wall on two_origins.

Tests: 510/510 green (orchestrator + benchmark suites + 7 new contract tests
for reset_gfm_activation). CO2 stability preserved (test_benchmark_two_origins
still asserts 1.2568).

Expected cluster gain (combined_40_ings): 3-5s off the 22.4s v0.5.420
baseline. cProfile decoded from the next dagster run will confirm.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>