reasoning: ground unclassified answers without category expansion

This commit is contained in:
2026-08-10 08:20:00 +01:00
parent 4ea664d0d8
commit 69efc5d1b9
2 changed files with 63 additions and 5 deletions
+18 -3
View File
@@ -2804,6 +2804,16 @@ function proposalResolutionSummary(proposal) {
return { resolved, proposalText }; return { resolved, proposalText };
} }
function resolvedProposalMeaningText(proposal) {
return normaliseSemanticText(
(proposal.updatedNodes || [])
.filter((update) => update.newStatus === "resolved")
.map((update) => update.newValue)
.filter((value) => typeof value === "string" && value.trim().length > 0)
.join(" "),
);
}
function mentionsHardConstraint(text) { function mentionsHardConstraint(text) {
return ( return (
text.includes("hard constraint") || text.includes("hard constraint") ||
@@ -3040,13 +3050,18 @@ function validateAnswerMeaningAlignment(proposal) {
} }
if (supportCategory === "other") { if (supportCategory === "other") {
const resolvedMeaningText = resolvedProposalMeaningText(proposal);
if ( if (
resolved && resolved &&
containsConstraintBoundaryLanguage(proposalText) && resolvedMeaningText &&
!containsConstraintBoundaryLanguage(meaningText) !rawAnswerSupportsUnclassifiedMeaning(
proposal.answerMeaning.userSupportedMeaning,
resolvedMeaningText,
)
) { ) {
errors.push( errors.push(
"Proposal cannot resolve beyond an unclassified answer by introducing an unsupported constraint or preference/trade-off distinction.", "Proposal cannot resolve beyond an unclassified answer by introducing unsupported stronger meaning than answerMeaning.userSupportedMeaning establishes.",
); );
} }
} }
+45 -2
View File
@@ -1568,7 +1568,7 @@ describe("applyValidatedProposal", () => {
); );
}); });
it("57A regression: a legitimate decision-advancing answer classified as other may resolve its intended unknown", () => { it("57F legitimate-answer regression: a grounded unclassified answer may resolve its intended unknown", () => {
const graph = makeCommercialUpdateFixture(); const graph = makeCommercialUpdateFixture();
const parentId = graph.activeUnknownNodeId; const parentId = graph.activeUnknownNodeId;
@@ -1640,6 +1640,49 @@ describe("applyValidatedProposal", () => {
expect(result.stage).toBeUndefined(); expect(result.stage).toBeUndefined();
}); });
it("57F deterministic reproduction: pre-fix grounded unclassified answer would have been rejected by proposal-text constraint language", () => {
const graph = makeCommercialUpdateFixture();
const parentId = graph.activeUnknownNodeId;
const result = applyValidatedProposal({
situationGraph: graph,
answer:
"We're looking at this mainly for cost reduction — roughly £2M annual savings on office overhead.",
previousQuestion:
"What problem would this need to solve to justify continuing development?",
proposal: {
addedNodes: [],
updatedNodes: [
{
nodeId: parentId,
previousStatus: "unknown",
newStatus: "resolved",
previousValue: null,
newValue:
"Cost reduction, including approximately £2M annual office-overhead savings, is a stated reason for considering the relocation.",
reason:
"The answer establishes that cost reduction is the relevant preference/trade-off consideration for this decision.",
},
],
addedEdges: [],
removedEdgeIds: [],
resolvedUnknownNodeIds: [parentId],
affectedNodeIds: [],
selectedQuestion: null,
answerMeaning: {
userSupportedMeaning:
"Cost reduction, including approximately £2M annual office-overhead savings, is a stated reason for considering the relocation.",
possibleInference: null,
supportCategory: "other",
resolutionGuidance: null,
},
},
});
expect(result.success).toBe(true);
expect(result.updatedSituationGraph.resolvedNodeIds).toContain(parentId);
});
it("unsafe unclassified answer: other is not automatically trusted when the proposal adds stronger unsupported meaning", () => { it("unsafe unclassified answer: other is not automatically trusted when the proposal adds stronger unsupported meaning", () => {
const graph = makeCommercialUpdateFixture(); const graph = makeCommercialUpdateFixture();
const parentId = graph.activeUnknownNodeId; const parentId = graph.activeUnknownNodeId;
@@ -1902,7 +1945,7 @@ describe("applyValidatedProposal", () => {
expect(result.success).toBe(false); expect(result.success).toBe(false);
expect(result.stage).toBe("proposal_compatibility"); expect(result.stage).toBe("proposal_compatibility");
expect(result.errors.join(" ")).toContain( expect(result.errors.join(" ")).toContain(
"unsupported constraint or preference/trade-off distinction", "unsupported stronger meaning than answerMeaning.userSupportedMeaning establishes",
); );
}); });