Repository navigation
refactor(core)!: make the contrast-region engine explicit - #216
Merged
Merged
Conversation
This was referenced Oct 6, 2026
Owner
Author
This was referenced Oct 6, 2026
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
This was referenced Oct 6, 2026
pbroom
force-pushed
the
refactor/core-explicit-contrast-engine
branch
from
October 8, 2026 02:44
d9f427e to
d127833
Compare
pbroom
force-pushed
the
refactor/core-trim-api-surface
branch
from
October 8, 2026 02:44
bfeb62f to
acf5fa7
Compare
This was referenced Oct 8, 2026
Owner
Author
pbroom
changed the base branch from
refactor/core-trim-api-surface
to
graphite-base/216
October 10, 2026 19:19
Contrast regions keep both solvers, but the caller now selects one and the engine never switches implicitly. - Add `engine?: 'hybrid' | 'legacy'` (default 'hybrid'). ContrastRegionPathOptions is now a union discriminated by `engine` (ContrastRegionHybridOptions | ContrastRegionLegacyOptions, sharing ContrastRegionBaseOptions). The legacy-only options (samplingMode 'uniform'/'adaptive', edgeInterpolation, adaptiveBaseSteps, adaptiveMaxDepth) require engine: 'legacy', and hybridMaxDepth / hybridErrorTolerance are hybrid-only. Mixing them is a type error and always throws a TypeError at runtime, as do unknown engines. Legacy samplingMode defaults to 'adaptive' when adaptive* is set, otherwise 'uniform'; samplingMode 'hybrid' is gone. - Plane contrast queries (PlaneContrastQueryOptions and the contrastBoundary/contrastRegion query types, now type aliases over the union), driver ColorAreaContrastRegionOptions, and inspectPlaneQuery pass `engine` and the engine options through, so invalid combinations are rejected the same way instead of being dropped by a field whitelist. Scheduler budgets and telemetry signatures follow the selected engine. - The hybrid engine no longer hands failed queries to the legacy engine. It returns its best-effort paths and records trace.summary.degradedReason (ContrastHybridFallbackReason is renamed ContrastHybridDegradedReason). It bisects lightness intervals whose ends are root-free on opposite sides of the threshold, localizes branch ends a little past hybridMaxDepth, and keeps splitting (with the extra depth) while index-matched roots of neighbouring samples differ by more than 0.03 chroma, half the branch join distance. Nearly constant-lightness contours previously stopped splitting there and left gaps; in a 720-query brute-force sweep, crossings more than 0.03 from the traced path drop from 67 to 0 for about 1.7% more evaluations. Thin regions at the top of the lightness range (vertical boundary, no chroma roots) still degrade with 'unresolved-sign-change'; the legacy engine finds them. - ContrastRegionLayer passes engine: 'legacy' explicitly (it already ran the legacy solver through edgeInterpolation), keeping its fill accuracy and speed. Its samplingMode prop is 'uniform' (default) or 'adaptive', and the no-op hybridMaxDepth / hybridErrorTolerance props are removed. - Compute scheduler: only the JS backend exists, so drop the speculative webgpu backend kind, preferred-backend selection, warmup, baseline probes, circuit breakers, and their options/telemetry fields. PlaneComputeBackendKind is 'js' and every run reports 'default-js'. Also fix LRU eviction, which evicted the newly created bucket. - Tests: engine selection and validation (runtime and type level), plane query pass-through, regression cases checked against a brute-force grid of the public checks, and degraded-reason cases. Docs and benches cover both engines. BREAKING CHANGE: legacy contrast options require engine: 'legacy' and hybrid options are rejected with it; samplingMode 'hybrid' is removed; the hybrid solver no longer falls back to the legacy solver; the ContrastRegionLayer hybridMaxDepth/hybridErrorTolerance props, the 'webgpu' backend kind, and the scheduler's multi-backend options and circuitBreakers telemetry are removed. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Since contrast regions measure against the unmapped reference (as the public metrics do), the brute-force baseline must not chroma-reduce an out-of-gamut reference either. Co-Authored-By: Claude Opus 5.5 <[email protected]>
pbroom
force-pushed
the
refactor/core-explicit-contrast-engine
branch
from
October 10, 2026 19:21
d127833 to
8bdcb76
Compare
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Contrast regions keep both solvers, but the caller now selects one and the
engine never switches implicitly.
engine?: 'hybrid' | 'legacy'(default 'hybrid').ContrastRegionPathOptions is now a union discriminated by
engine(ContrastRegionHybridOptions | ContrastRegionLegacyOptions, sharing
ContrastRegionBaseOptions). The legacy-only options (samplingMode
'uniform'/'adaptive', edgeInterpolation, adaptiveBaseSteps,
adaptiveMaxDepth) require engine: 'legacy', and hybridMaxDepth /
hybridErrorTolerance are hybrid-only. Mixing them is a type error and
always throws a TypeError at runtime, as do unknown engines. Legacy
samplingMode defaults to 'adaptive' when adaptive* is set, otherwise
'uniform'; samplingMode 'hybrid' is gone.
contrastBoundary/contrastRegion query types, now type aliases over the
union), driver ColorAreaContrastRegionOptions, and inspectPlaneQuery pass
engineand the engine options through, so invalid combinations arerejected the same way instead of being dropped by a field whitelist.
Scheduler budgets and telemetry signatures follow the selected engine.
It returns its best-effort paths and records
trace.summary.degradedReason (ContrastHybridFallbackReason is renamed
ContrastHybridDegradedReason). It bisects lightness intervals whose ends
are root-free on opposite sides of the threshold, localizes branch ends
a little past hybridMaxDepth, and keeps splitting (with the extra depth)
while index-matched roots of neighbouring samples differ by more than
0.03 chroma, half the branch join distance. Nearly constant-lightness
contours previously stopped splitting there and left gaps; in a
720-query brute-force sweep, crossings more than 0.03 from the traced
path drop from 67 to 0 for about 1.7% more evaluations. Thin regions
at the top of the lightness range (vertical boundary, no chroma roots)
still degrade with 'unresolved-sign-change'; the legacy engine finds
them.
the legacy solver through edgeInterpolation), keeping its fill accuracy
and speed. Its samplingMode prop is 'uniform' (default) or 'adaptive',
and the no-op hybridMaxDepth / hybridErrorTolerance props are removed.
webgpu backend kind, preferred-backend selection, warmup, baseline
probes, circuit breakers, and their options/telemetry fields.
PlaneComputeBackendKind is 'js' and every run reports 'default-js'.
Also fix LRU eviction, which evicted the newly created bucket.
query pass-through, regression cases checked against a brute-force
grid of the public checks, and degraded-reason cases. Docs and benches
cover both engines.
BREAKING CHANGE: legacy contrast options require engine: 'legacy' and
hybrid options are rejected with it; samplingMode 'hybrid' is removed;
the hybrid solver no longer falls back to the legacy solver; the
ContrastRegionLayer hybridMaxDepth/hybridErrorTolerance props, the
'webgpu' backend kind, and the scheduler's multi-backend options and
circuitBreakers telemetry are removed.
Part of a stacked set of PRs (#204 → #221) from the color-kit assessment. Validated per branch with
pnpm buildandpnpm test; lint, format, typecheck, size, artifact, preprod and agents checks pass at the top of the stack.🤖 Generated with Claude Code