fix: propagate compound state through toAst() and canonical lowering
ast.ts: Add optional compoundOperator and compoundParts fields to RelationAssertion, allowing compound fluent assertions to carry their .and / .or structure through the AST layer. fluent.ts: toAst() now emits compoundOperator/compoundParts when isCompound, closing the gap where compound state was silently dropped in canonical extraction, preset building, and validation. lower-to-canonical.ts: Handle RelationAssertion with compound metadata by lowering each part as a separate grouped clause (same groupId, same compoundOperator), matching DSL parser compound behavior. validator.ts: Validate options on each compound part, closing the false-positive validation gap where only the final relation was checked. 3 lossy code paths (extractCanonicalFromAssertion, presets.toPresetResult, validateRelation) now preserve compound structure. Primary FOL evaluation path was already correct (fol-compiler reads compoundParts directly). 658 tests pass.
This commit is contained in:
@@ -262,6 +262,28 @@ export function validateRelation(assertion: RelationAssertion): ValidationResult
|
||||
)
|
||||
}
|
||||
|
||||
// 6. Compound parts: validate each part's relation name and options
|
||||
if (assertion.compoundOperator && assertion.compoundParts && assertion.compoundParts.length > 1) {
|
||||
for (let i = 0; i < assertion.compoundParts.length; i++) {
|
||||
const part = assertion.compoundParts[i]
|
||||
const partAllowed = getValidOptionsForRelation(part.relation)
|
||||
const partOpts = part.options as unknown as Record<string, unknown>
|
||||
const partProvided = Object.keys(partOpts).filter(k => k !== 'type')
|
||||
for (const key of partProvided) {
|
||||
if (!partAllowed.has(key)) {
|
||||
diagnostics.push(
|
||||
makeDiag(
|
||||
'IMH_VALID_ILLEGAL_RELATION_OPTION',
|
||||
'validation-error',
|
||||
`Option "${key}" is not valid for compound part "${part.relation}". Allowed options: ${Array.from(partAllowed).join(', ') || 'none'}.`,
|
||||
assertion.position,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
valid: diagnostics.length === 0,
|
||||
diagnostics,
|
||||
|
||||
Reference in New Issue
Block a user