fix(graph): make structural action contract authoritative

This commit is contained in:
2026-08-12 08:15:41 +01:00
parent c899ad620c
commit bd3c7d59ae
2 changed files with 245 additions and 17 deletions
+16 -12
View File
@@ -900,24 +900,28 @@ export function validateGraphUpdate(graph, update) {
errors.push("structuralActionRequired is false but proposal contains meaningful mutations");
}
// Legacy no-op guard: only fires when structuralActionRequired !== false.
// When false → zero-mutation is a valid intentional no-op (contract PASS).
if (!hasMeaningfulChange && update.structuralActionRequired !== false) {
// Legacy no-op guard: only fires when structuralActionRequired is absent (null/undefined).
// When true or false → the new contract owns no-op/mutation consistency.
// The contract checks above already produced authoritative errors for those cases.
const fieldAbsent =
update.structuralActionRequired === null ||
update.structuralActionRequired === undefined;
if (!hasMeaningfulChange && fieldAbsent) {
if (meaningPopulated) {
// Avoid double-error when field absence was already flagged above
if (
update.structuralActionRequired !== null &&
update.structuralActionRequired !== undefined
) {
errors.push(
"answerMeaning.userSupportedMeaning is populated, but the proposal contains no graph mutation. answerMeaning alone does not constitute graph progress.",
);
}
// structuralActionRequired was missing while userSupportedMeaning exists.
// Missing-field rejection already added above; skip semantic-only guard to avoid duplicate errors on the same proposal.
} else if (!meaningPopulated) {
errors.push("Update contains no meaningful change");
}
}
// Legacy guard when structuralActionRequired=false: false declares no action needed,
// but userSupportedMeaning populated implies semantic intent for change. However the
// new-contract checks above already produced an error if there IS mutation. If there's
// zero mutation with false + meaning, treat as intentional no-op (contract PASS).
// Reject oversized input
const totalSize = JSON.stringify(update).length;
if (totalSize > 100000) {