reasoning: stop answer fidelity guard blocking valid unclassified answers
This commit is contained in:
@@ -2689,6 +2689,70 @@ function normaliseSemanticText(value) {
|
||||
.trim();
|
||||
}
|
||||
|
||||
function semanticContentTokens(value) {
|
||||
const stopWords = new Set([
|
||||
"the",
|
||||
"and",
|
||||
"for",
|
||||
"that",
|
||||
"this",
|
||||
"with",
|
||||
"from",
|
||||
"into",
|
||||
"than",
|
||||
"then",
|
||||
"they",
|
||||
"them",
|
||||
"their",
|
||||
"there",
|
||||
"about",
|
||||
"would",
|
||||
"could",
|
||||
"should",
|
||||
"because",
|
||||
"being",
|
||||
"been",
|
||||
"have",
|
||||
"has",
|
||||
"had",
|
||||
"were",
|
||||
"what",
|
||||
"when",
|
||||
"where",
|
||||
"which",
|
||||
"while",
|
||||
"mainly",
|
||||
"roughly",
|
||||
"specifically",
|
||||
"directly",
|
||||
"user",
|
||||
]);
|
||||
|
||||
return normaliseSemanticText(value)
|
||||
.replace(/[^a-z0-9]+/g, " ")
|
||||
.split(" ")
|
||||
.filter((token) => token.length > 2 && !stopWords.has(token));
|
||||
}
|
||||
|
||||
function semanticOverlapRatio(sourceText, candidateText) {
|
||||
const source = new Set(semanticContentTokens(sourceText));
|
||||
const candidate = new Set(semanticContentTokens(candidateText));
|
||||
|
||||
if (candidate.size === 0) return 1;
|
||||
|
||||
const overlap = [...candidate].filter((token) => source.has(token)).length;
|
||||
return overlap / candidate.size;
|
||||
}
|
||||
|
||||
function rawAnswerSupportsUnclassifiedMeaning(answer, userSupportedMeaning) {
|
||||
const overlapRatio = semanticOverlapRatio(answer, userSupportedMeaning);
|
||||
const overlappingTokens = semanticContentTokens(userSupportedMeaning).filter(
|
||||
(token) => semanticContentTokens(answer).includes(token),
|
||||
).length;
|
||||
|
||||
return overlapRatio >= 0.4 || overlappingTokens >= 3;
|
||||
}
|
||||
|
||||
function hasConditionalQualification(text) {
|
||||
const value = normaliseSemanticText(text);
|
||||
return (
|
||||
@@ -2893,6 +2957,23 @@ function validateAnswerMeaningCompatibilityWithRawAnswer({ answer, proposal }) {
|
||||
}
|
||||
}
|
||||
|
||||
if (rawAnswerProfile.category === "other") {
|
||||
if (supportedMeaningProfile.category !== "other") {
|
||||
errors.push(
|
||||
"answerMeaning.userSupportedMeaning introduces a stronger reasoning category than the raw answer establishes.",
|
||||
);
|
||||
} else if (
|
||||
!rawAnswerSupportsUnclassifiedMeaning(
|
||||
answer,
|
||||
proposal.answerMeaning.userSupportedMeaning,
|
||||
)
|
||||
) {
|
||||
errors.push(
|
||||
"answerMeaning.userSupportedMeaning introduces unsupported meaning beyond what the raw answer itself states.",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
@@ -2964,9 +3045,13 @@ function validateAnswerMeaningAlignment(proposal) {
|
||||
}
|
||||
|
||||
if (supportCategory === "other") {
|
||||
if (resolved || containsConstraintBoundaryLanguage(proposalText)) {
|
||||
if (
|
||||
resolved &&
|
||||
containsConstraintBoundaryLanguage(proposalText) &&
|
||||
!containsConstraintBoundaryLanguage(meaningText)
|
||||
) {
|
||||
errors.push(
|
||||
"Proposal cannot resolve or strengthen answerMeaning that does not clearly establish one of the protected reasoning categories.",
|
||||
"Proposal cannot resolve beyond an unclassified answer by introducing an unsupported constraint or preference/trade-off distinction.",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user