Skip to content

UK local solve doctrine: uniform operator, declared bounds, past-cap census (#495 increment 4) - #503

Merged
MaxGhenis merged 2 commits into
mainfrom
uk-local-solve-doctrine
Jul 22, 2026
Merged

UK local solve doctrine: uniform operator, declared bounds, past-cap census (#495 increment 4)#503
MaxGhenis merged 2 commits into
mainfrom
uk-local-solve-doctrine

Conversation

@MaxGhenis

Copy link
Copy Markdown
Contributor

What

Increment 4 of the UK dense/local epic (#495): the local solve becomes one uniform operator with declared bounds and first-class written-off-row diagnostics, per the #492/#493 doctrine — no per-target calibration knobs.

Past-cap census (#492 A, ported to the local solve)

past_cap_census in local_solver.py: counts of target rows past the loss cap at initialization and at the final weights, the rows that escaped back inside, the rows frozen past the cap throughout, and — the silent-triage class #492 measured on Build N — the rows pushed out during the solve, listed row by row with area/metric labels and before/after scaled errors (bounded list with an explicit truncation flag). Every solve_stacked_local_weights result now carries the census (StackedLocalSolveResult.past_cap_census, additive field), so both the research harness and the doctrine path get the observability for free.

The doctrine surface (local_doctrine.py)

  • UKLocalSolveDoctrine — a frozen, self-validating contract: declared loss cap, declared weight-ratio stretch bound, and closed vocabularies for the scale rule (default_target_loss_scales only — the canonical target-defined scales) and target weighting (uniform only). A future family-level weighting would be a new reviewed rule name here, never a per-target vector.
  • UK_LOCAL_SOLVE_DOCTRINE — the reviewed instance; UK_LOCAL_TARGET_LOSS_CAP = 10.0 and UK_LOCAL_MAX_WEIGHT_RATIO = 100.0 declare the current defaults as the explicit contract. Revising either is a doctrine change that must edit this module and its pinned test, which forces review. (max_weight_ratio anchors differently per arm: 5x vs design (dense) but ~25x effective (sparse refit re-anchors) — declare one stretch contract #493's one-stretch-contract adjudication may revise the ratio; the increment-6 candidate review adjudicates the cap against measured fit — the point of this increment is that the values are declared and uniform, not what they are.)
  • solve_uk_local_weights_under_doctrine — the release path's solve. Structurally knob-free: target_loss_weights, target_loss_scales, target_loss_cap, and max_weight_ratio do not exist on its signature; passing them is a TypeError by construction, not a runtime flag. A tampered doctrine instance fails its own validation before any solve runs.

The low-level solve_stacked_local_weights remains the research harness (experiments legitimately pass explicit vectors); the doctrine wrapper is what increment 6 wires into the release build.

Testing

7 new tests: census transition classification on a hand-built 4-row case (escaped/frozen/pushed-out each exercised, row labels checked), default-scale semantics + shape validation, census carried on a real small solve, pinned doctrine constants, tampered-bound refusals (cap ≤ 0/NaN, ratio ≤ 1, unknown rules), the no-knobs signature guarantee, and declared-bound application (stretch bound holds on solved weights; non-doctrine object refused). Existing solver/runner tests untouched and green; ruff check clean.

Part of #495.

🤖 Generated with Claude Code

…d a past-cap census

Increment 4 of the UK dense/local epic (#495), per the #492/#493 doctrine:
no per-target calibration knobs. past_cap_census (in local_solver, carried
on every StackedLocalSolveResult) makes the rows a solve wrote off
first-class diagnostics: past-cap at init/final, escaped, frozen, and the
pushed-out dumping-ground class listed row by row with area/metric labels.
local_doctrine adds the release path's solve surface: UKLocalSolveDoctrine
(frozen, self-validating, closed rule vocabularies) with the declared
contract UK_LOCAL_TARGET_LOSS_CAP=10.0 / UK_LOCAL_MAX_WEIGHT_RATIO=100.0
(current defaults promoted to an explicit reviewed contract), and
solve_uk_local_weights_under_doctrine, whose signature exposes no
per-target weight/scale/cap/ratio parameters at all — the refusal is
structural. The low-level solver remains the research harness.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nt, uniform-surface refusal, doctrine-mode runner, unbounded pushed-out list

Adjudicated findings from the sol review of #503 (all three blockers
confirmed):

- solve_uk_local_weights_under_doctrine no longer takes a doctrine
  parameter at all: the bounds always come from the reviewed module
  constant, so dataclasses.replace()-minted contracts cannot route through
  the release path (this also moots the copy/subclass tampering class).
- The doctrine path validates the target surface as one uniform grid —
  duplicate (area_type, area_code, metric) rows would be implicit
  per-target weights and are refused with named examples.
- build_local_candidate gains under_doctrine=True (the release mode):
  per-target/bound solver options are refused by name and the solve routes
  through the doctrine wrapper; summarize_local_candidate reports past-cap
  counts and write_local_candidate_outputs persists past_cap_census.json,
  so candidates no longer drop the observability.
- past_cap_census lists every pushed-out row by default (max_listed_rows
  is an explicit opt-in bound with a truncation flag) and mirrors the
  canonical loss's refusals: non-finite estimates/targets and zero or
  non-finite scales raise instead of silently classifying rows inside the
  cap. Exact-tie semantics pinned (strictly greater, matching the torch
  gradient).
- Brittle test assertions replaced (no Adam monotonicity claim; finite
  checks before max).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Cross-family review completed (sol adversarial pass, fable adjudication) — all three blockers confirmed and fixed in the second commit:

  1. The candidate path bypassed the doctrine (build_local_candidate(solver_options={"target_loss_weights": …}) reached the research solver directly). Fixed: under_doctrine=True is now the release mode — per-target/bound solver options are refused by name and the solve routes through the doctrine wrapper. The research path stays available, but a doctrine candidate is now structurally distinguishable.
  2. dataclasses.replace() minted a validated-but-revised contract (cap 77) and the wrapper forwarded it. Fixed by removing the injection point entirely: solve_uk_local_weights_under_doctrine takes no doctrine parameter — the bounds always come from the reviewed module constant. This also moots the copy/subclass/__setattr__ tampering class (finding 5): there is nothing to inject into.
  3. The 100-row pushed-out truncation contradicted the "every row" promise. Fixed: unbounded by default; max_listed_rows is an explicit opt-in bound with a truncation flag, and the solver path never bounds it.

Should-fixes: census now mirrors the canonical loss's refusals (non-finite estimates/targets, zero/non-finite scales raise instead of silently classifying inside the cap — and the solver's own canonical-loss call would refuse such inputs before the census anyway, so the two stay consistent); the doctrine path refuses duplicate (area_type, area_code, metric) rows as implicit per-target weights (finding 6); summarize_local_candidate reports past-cap counts and write_local_candidate_outputs persists past_cap_census.json (finding 7); exact-tie strictly-greater semantics pinned by test and the brittle Adam-monotonicity/nanmax assertions replaced (finding 9). Test coverage added for each (28 tests in the affected files, all green).

Sol's no-issue verifications worth keeping on record: max_weight_ratio is a hard closing cap in the optimizer (so the stretch-bound test is sound), strictly-greater cap semantics match the torch gradient, the additive result field breaks no in-repo consumer, and census cost is linear at the 20k-target scale.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant