fix: propagate operand metrics through boolean connectives
- evaluateAnd: carry left metrics on left-fail short-circuit, carry right metrics on right fail/indeterminate - evaluateOr: carry left metrics on left-pass short-circuit, carry right metrics on right pass, merge both on double-fail - evaluateNot: carry operand metrics when operand passes (so not fails with diagnostic context), carry on indeterminate - evaluateImplies: carry consequent metrics on fail/indeterminate This ensures compound formula failures preserve measured geometry context (gap, dimensions, direction) rather than presenting empty diagnostics to users investigating layout contract violations.
This commit is contained in:
@@ -548,6 +548,7 @@ function evaluateAnd(
|
|||||||
formulaId,
|
formulaId,
|
||||||
outcome: 'fail',
|
outcome: 'fail',
|
||||||
truth: 'determinate',
|
truth: 'determinate',
|
||||||
|
metrics: leftResult.metrics,
|
||||||
};
|
};
|
||||||
state.proofs.push(makeProof(state, formulaId, 'fail', 'determinate'));
|
state.proofs.push(makeProof(state, formulaId, 'fail', 'determinate'));
|
||||||
addTrace(state, 'evaluate-and-short-circuit', formulaId, { side: 'left', reason: 'fail' });
|
addTrace(state, 'evaluate-and-short-circuit', formulaId, { side: 'left', reason: 'fail' });
|
||||||
@@ -557,6 +558,7 @@ function evaluateAnd(
|
|||||||
const rightResult = evaluateFormula(formula.right, env, state);
|
const rightResult = evaluateFormula(formula.right, env, state);
|
||||||
let outcome: 'pass' | 'fail' | 'indeterminate';
|
let outcome: 'pass' | 'fail' | 'indeterminate';
|
||||||
let truth: 'determinate' | 'indeterminate';
|
let truth: 'determinate' | 'indeterminate';
|
||||||
|
let metrics: Record<string, number> | undefined;
|
||||||
|
|
||||||
if (rightResult.outcome === 'pass') {
|
if (rightResult.outcome === 'pass') {
|
||||||
outcome = 'pass';
|
outcome = 'pass';
|
||||||
@@ -564,15 +566,18 @@ function evaluateAnd(
|
|||||||
} else if (rightResult.outcome === 'indeterminate') {
|
} else if (rightResult.outcome === 'indeterminate') {
|
||||||
outcome = 'indeterminate';
|
outcome = 'indeterminate';
|
||||||
truth = 'indeterminate';
|
truth = 'indeterminate';
|
||||||
|
metrics = rightResult.metrics;
|
||||||
} else {
|
} else {
|
||||||
outcome = 'fail';
|
outcome = 'fail';
|
||||||
truth = 'determinate';
|
truth = 'determinate';
|
||||||
|
metrics = rightResult.metrics;
|
||||||
}
|
}
|
||||||
|
|
||||||
const result: FormulaResult = {
|
const result: FormulaResult = {
|
||||||
formulaId,
|
formulaId,
|
||||||
outcome,
|
outcome,
|
||||||
truth,
|
truth,
|
||||||
|
metrics,
|
||||||
};
|
};
|
||||||
state.proofs.push(makeProof(state, formulaId, result.outcome, result.truth));
|
state.proofs.push(makeProof(state, formulaId, result.outcome, result.truth));
|
||||||
addTrace(state, 'evaluate-and-end', formulaId, { outcome });
|
addTrace(state, 'evaluate-and-end', formulaId, { outcome });
|
||||||
@@ -593,6 +598,7 @@ function evaluateOr(
|
|||||||
formulaId,
|
formulaId,
|
||||||
outcome: 'pass',
|
outcome: 'pass',
|
||||||
truth: 'determinate',
|
truth: 'determinate',
|
||||||
|
metrics: leftResult.metrics,
|
||||||
};
|
};
|
||||||
state.proofs.push(makeProof(state, formulaId, 'pass', 'determinate'));
|
state.proofs.push(makeProof(state, formulaId, 'pass', 'determinate'));
|
||||||
addTrace(state, 'evaluate-or-short-circuit', formulaId, { side: 'left', reason: 'pass' });
|
addTrace(state, 'evaluate-or-short-circuit', formulaId, { side: 'left', reason: 'pass' });
|
||||||
@@ -602,22 +608,27 @@ function evaluateOr(
|
|||||||
const rightResult = evaluateFormula(formula.right, env, state);
|
const rightResult = evaluateFormula(formula.right, env, state);
|
||||||
let outcome: 'pass' | 'fail' | 'indeterminate';
|
let outcome: 'pass' | 'fail' | 'indeterminate';
|
||||||
let truth: 'determinate' | 'indeterminate';
|
let truth: 'determinate' | 'indeterminate';
|
||||||
|
let metrics: Record<string, number> | undefined;
|
||||||
|
|
||||||
if (rightResult.outcome === 'pass') {
|
if (rightResult.outcome === 'pass') {
|
||||||
outcome = 'pass';
|
outcome = 'pass';
|
||||||
truth = 'determinate';
|
truth = 'determinate';
|
||||||
|
metrics = rightResult.metrics;
|
||||||
} else if (leftResult.outcome === 'indeterminate' || rightResult.outcome === 'indeterminate') {
|
} else if (leftResult.outcome === 'indeterminate' || rightResult.outcome === 'indeterminate') {
|
||||||
outcome = 'indeterminate';
|
outcome = 'indeterminate';
|
||||||
truth = 'indeterminate';
|
truth = 'indeterminate';
|
||||||
|
metrics = rightResult.metrics ?? leftResult.metrics;
|
||||||
} else {
|
} else {
|
||||||
outcome = 'fail';
|
outcome = 'fail';
|
||||||
truth = 'determinate';
|
truth = 'determinate';
|
||||||
|
metrics = { ...leftResult.metrics, ...rightResult.metrics };
|
||||||
}
|
}
|
||||||
|
|
||||||
const result: FormulaResult = {
|
const result: FormulaResult = {
|
||||||
formulaId,
|
formulaId,
|
||||||
outcome,
|
outcome,
|
||||||
truth,
|
truth,
|
||||||
|
metrics,
|
||||||
};
|
};
|
||||||
state.proofs.push(makeProof(state, formulaId, result.outcome, result.truth));
|
state.proofs.push(makeProof(state, formulaId, result.outcome, result.truth));
|
||||||
addTrace(state, 'evaluate-or-end', formulaId, { outcome });
|
addTrace(state, 'evaluate-or-end', formulaId, { outcome });
|
||||||
@@ -639,10 +650,12 @@ function evaluateNot(
|
|||||||
const operandResult = evaluateFormula(formula.operand, env, state);
|
const operandResult = evaluateFormula(formula.operand, env, state);
|
||||||
let outcome: 'pass' | 'fail' | 'indeterminate';
|
let outcome: 'pass' | 'fail' | 'indeterminate';
|
||||||
let truth: 'determinate' | 'indeterminate';
|
let truth: 'determinate' | 'indeterminate';
|
||||||
|
let metrics: Record<string, number> | undefined;
|
||||||
|
|
||||||
if (operandResult.outcome === 'pass') {
|
if (operandResult.outcome === 'pass') {
|
||||||
outcome = 'fail';
|
outcome = 'fail';
|
||||||
truth = 'determinate';
|
truth = 'determinate';
|
||||||
|
metrics = operandResult.metrics;
|
||||||
} else if (operandResult.outcome === 'fail') {
|
} else if (operandResult.outcome === 'fail') {
|
||||||
outcome = 'pass';
|
outcome = 'pass';
|
||||||
truth = 'determinate';
|
truth = 'determinate';
|
||||||
@@ -653,12 +666,14 @@ function evaluateNot(
|
|||||||
} else {
|
} else {
|
||||||
outcome = 'indeterminate';
|
outcome = 'indeterminate';
|
||||||
truth = 'indeterminate';
|
truth = 'indeterminate';
|
||||||
|
metrics = operandResult.metrics;
|
||||||
}
|
}
|
||||||
|
|
||||||
const result: FormulaResult = {
|
const result: FormulaResult = {
|
||||||
formulaId,
|
formulaId,
|
||||||
outcome,
|
outcome,
|
||||||
truth,
|
truth,
|
||||||
|
metrics,
|
||||||
};
|
};
|
||||||
|
|
||||||
state.proofs.push(makeProof(state, formulaId, result.outcome, result.truth));
|
state.proofs.push(makeProof(state, formulaId, result.outcome, result.truth));
|
||||||
@@ -701,6 +716,7 @@ function evaluateImplies(
|
|||||||
const consequentResult = evaluateFormula(formula.consequent, env, state);
|
const consequentResult = evaluateFormula(formula.consequent, env, state);
|
||||||
let outcome: 'pass' | 'fail' | 'indeterminate';
|
let outcome: 'pass' | 'fail' | 'indeterminate';
|
||||||
let truth: 'determinate' | 'indeterminate';
|
let truth: 'determinate' | 'indeterminate';
|
||||||
|
let metrics: Record<string, number> | undefined;
|
||||||
|
|
||||||
if (consequentResult.outcome === 'pass') {
|
if (consequentResult.outcome === 'pass') {
|
||||||
outcome = 'pass';
|
outcome = 'pass';
|
||||||
@@ -708,15 +724,18 @@ function evaluateImplies(
|
|||||||
} else if (consequentResult.outcome === 'indeterminate') {
|
} else if (consequentResult.outcome === 'indeterminate') {
|
||||||
outcome = 'indeterminate';
|
outcome = 'indeterminate';
|
||||||
truth = 'indeterminate';
|
truth = 'indeterminate';
|
||||||
|
metrics = consequentResult.metrics;
|
||||||
} else {
|
} else {
|
||||||
outcome = 'fail';
|
outcome = 'fail';
|
||||||
truth = 'determinate';
|
truth = 'determinate';
|
||||||
|
metrics = consequentResult.metrics;
|
||||||
}
|
}
|
||||||
|
|
||||||
const result: FormulaResult = {
|
const result: FormulaResult = {
|
||||||
formulaId,
|
formulaId,
|
||||||
outcome,
|
outcome,
|
||||||
truth,
|
truth,
|
||||||
|
metrics,
|
||||||
};
|
};
|
||||||
state.proofs.push(makeProof(state, formulaId, result.outcome, result.truth));
|
state.proofs.push(makeProof(state, formulaId, result.outcome, result.truth));
|
||||||
addTrace(state, 'evaluate-implies-end', formulaId, { outcome });
|
addTrace(state, 'evaluate-implies-end', formulaId, { outcome });
|
||||||
|
|||||||
Reference in New Issue
Block a user