You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The reduction model has a sound high-level shape: a rule constructs a target problem, witness reductions map target configurations back to source configurations, and aggregate reductions map final target values back to source values.
Several runtime details currently weaken that contract. They rely on recovered panics, fabricated configurations, or capability metadata that can disagree with the available executor. The panic-probing and capability behavior described below are present on the branch for PR #1083; the extraction behavior also exists in the existing rule implementations.
This is one runtime-contract hardening issue. The three objectives may be delivered together in PR #1083 because they govern the same registered-reduction execution boundary. The extract_solution signature change necessarily causes a repository-wide mechanical migration of rule implementations, callers, and tests; that migration is part of this issue rather than a general rewrite.
Problem 1: normal variant probing uses panic and recovery
ReductionGraph::compute_source_size iterates every reduction entry with the same source problem name and calls each source_size_fn. A function generated for a different variant fails its downcast and panics. catch_reduction catches the panic and installs a thread-local panic-hook silencer so the expected panic does not appear on stderr.
Current control flow:
try an executor for a different variant
→ downcast panic
→ catch panic
→ suppress panic output
→ treat the entry as not applicable
A type or variant mismatch is normal dispatch state and must be checked before invocation. Panics must remain reserved for actual defects.
Relevant code:
src/rules/graph.rs: compute_source_size
src/rules/pareto.rs: catch_reduction
Problem 2: extraction failures fabricate all-zero source configurations
ReductionResult::extract_solution returns only Vec<usize>, so a rule cannot report malformed or non-extractable target input. Multiple rules return vec![0; n] as a failure marker, including SAT to NAE-SAT and several Hamiltonian reductions.
This makes these states indistinguishable:
a legitimate all-zero source configuration
extraction failed and fabricated an all-zero configuration
Representative locations can be found with:
rg 'return (Ok\()?vec!\[0' src/rules
Extraction failure must be explicit. Audit each zero fallback: replace genuine failure markers with an error; retain a zero configuration only where it is the mathematically defined mapping and add a semantic test proving that fact.
Problem 3: capability metadata can disagree with executable behavior
ReductionEntry stores executor functions and capability booleans independently:
An entry can therefore advertise a mode without providing a valid executor for it. In addition, the #[reduction] macro currently assigns EdgeCapabilities::both() when the source and target base names are equal. Aggregate execution then uses WitnessBackedIdentityAggregateStep, which returns the target JSON value unchanged.
A shared base name does not prove that source and target aggregate value types or meanings are identical. Identity aggregate mapping must be backed by a compile-time value-type equality guarantee or by an explicit aggregate executor.
Select source_size_fn by the exact registered source name and variant before calling it.
Remove panic-and-recover behavior used for ordinary variant mismatch.
Do not silence or swallow genuine reduction panics.
Add a regression with at least two variants sharing a base name that proves only the exact variant executor is invoked.
Solution extraction
Give extraction an explicit failure result rather than encoding failure as a configuration.
Update CLI, bundle, dynamic-chain, and rule callers to propagate a useful error.
Remove failure-marker zero vectors from the audited rules.
Add tests distinguishing a legitimate zero configuration from extraction failure.
Capability integrity
Make executable functions the source of truth for supported modes, or validate every registry entry before graph construction.
Reject inconsistent entries such as aggregate=true without an aggregate executor or a type-safe identity mapping.
Remove same-base-name as sufficient evidence for identity aggregate mapping.
Add negative tests that intentionally construct inconsistent entries and verify rejection.
Verification
rg "catch_reduction|catch_unwind" src/rules
rg 'return (Ok\()?vec!\[0' src/rules
make check
The first command must no longer find panic recovery used as normal reduction dispatch. The second may only find zero configurations with documented mathematical meaning, never failure markers. make check must pass after each scoped PR.
Keep the combined change limited to exact variant dispatch, executor-backed capability integrity, explicit extraction failure, and the mechanical caller/test migration required by the extraction API.
Do not combine this work with a general graph.rs file split.
Do not add compatibility wrappers around the old failure behavior.
Replace the old behavior and delete the superseded panic hooks, silent fallbacks, and redundant capability state.
Background
The reduction model has a sound high-level shape: a rule constructs a target problem, witness reductions map target configurations back to source configurations, and aggregate reductions map final target values back to source values.
Several runtime details currently weaken that contract. They rely on recovered panics, fabricated configurations, or capability metadata that can disagree with the available executor. The panic-probing and capability behavior described below are present on the branch for PR #1083; the extraction behavior also exists in the existing rule implementations.
This is one runtime-contract hardening issue. The three objectives may be delivered together in PR #1083 because they govern the same registered-reduction execution boundary. The
extract_solutionsignature change necessarily causes a repository-wide mechanical migration of rule implementations, callers, and tests; that migration is part of this issue rather than a general rewrite.Problem 1: normal variant probing uses panic and recovery
ReductionGraph::compute_source_sizeiterates every reduction entry with the same source problem name and calls eachsource_size_fn. A function generated for a different variant fails its downcast and panics.catch_reductioncatches the panic and installs a thread-local panic-hook silencer so the expected panic does not appear on stderr.Current control flow:
A type or variant mismatch is normal dispatch state and must be checked before invocation. Panics must remain reserved for actual defects.
Relevant code:
src/rules/graph.rs:compute_source_sizesrc/rules/pareto.rs:catch_reductionProblem 2: extraction failures fabricate all-zero source configurations
ReductionResult::extract_solutionreturns onlyVec<usize>, so a rule cannot report malformed or non-extractable target input. Multiple rules returnvec![0; n]as a failure marker, including SAT to NAE-SAT and several Hamiltonian reductions.This makes these states indistinguishable:
Representative locations can be found with:
rg 'return (Ok\()?vec!\[0' src/rulesExtraction failure must be explicit. Audit each zero fallback: replace genuine failure markers with an error; retain a zero configuration only where it is the mathematically defined mapping and add a semantic test proving that fact.
Problem 3: capability metadata can disagree with executable behavior
ReductionEntrystores executor functions and capability booleans independently:An entry can therefore advertise a mode without providing a valid executor for it. In addition, the
#[reduction]macro currently assignsEdgeCapabilities::both()when the source and target base names are equal. Aggregate execution then usesWitnessBackedIdentityAggregateStep, which returns the target JSON value unchanged.A shared base name does not prove that source and target aggregate value types or meanings are identical. Identity aggregate mapping must be backed by a compile-time value-type equality guarantee or by an explicit aggregate executor.
Relevant code:
problemreductions-macros/src/lib.rs: same-name capability inferencesrc/rules/registry.rs:ReductionEntryandEdgeCapabilitiessrc/rules/graph.rs:WitnessBackedIdentityAggregateStepObjectives
Variant dispatch
source_size_fnby the exact registered source name and variant before calling it.Solution extraction
Capability integrity
aggregate=truewithout an aggregate executor or a type-safe identity mapping.Verification
The first command must no longer find panic recovery used as normal reduction dispatch. The second may only find zero configurations with documented mathematical meaning, never failure markers.
make checkmust pass after each scoped PR.Scope control
graph.rsfile split.Related