feat: require concrete evidence for progress claims

This commit is contained in:
Eve
2026-04-23 15:22:02 +08:00
parent 17449fa519
commit 180619cf87
3 changed files with 59 additions and 13 deletions

View File

@@ -30,6 +30,17 @@ const EVIDENCE_FIELDS = Object.freeze({
'verificationEvidence',
'checkpointArtifactEvidence',
]),
progressEvidence: Object.freeze([
'progressEvidence',
'progressEvidence.sessionKey',
'progressEvidence.runId',
'progressEvidence.modified_files',
'progressEvidence.verificationResult',
'sessionKey',
'runId',
'modified_files',
'verificationResult',
]),
});
const GATE_REQUIREMENTS = Object.freeze({
@@ -53,6 +64,11 @@ const GATE_REQUIREMENTS = Object.freeze({
acceptedFields: EVIDENCE_FIELDS.executionEvidence,
requiredValue: 'tool call, dispatch, file change, verification output, or checkpoint artifact evidence',
}),
progressEvidence: Object.freeze({
evidenceKey: 'progressEvidence',
acceptedFields: EVIDENCE_FIELDS.progressEvidence,
requiredValue: 'sessionKey, runId, modified_files, verification result, or equivalent concrete progress evidence',
}),
});
function fail(code, message) {
@@ -164,6 +180,16 @@ function hasExecutionEvidence(input) {
});
}
function hasProgressEvidence(input) {
return EVIDENCE_FIELDS.progressEvidence.some((fieldPath) => {
const value = getPathValue(input, fieldPath);
if (hasNonEmptyString(value)) return true;
if (Array.isArray(value)) return value.length > 0;
if (value && typeof value === 'object') return Object.keys(value).length > 0;
return false;
});
}
function claimsProgressionWithoutEvidence(input) {
const progressionClaim = EVIDENCE_FIELDS.progressionClaim
.map((fieldPath) => getPathValue(input, fieldPath))
@@ -171,7 +197,7 @@ function claimsProgressionWithoutEvidence(input) {
if (!hasNonEmptyString(progressionClaim)) return false;
return !hasExecutionEvidence(input);
return !(hasProgressEvidence(input) || hasExecutionEvidence(input));
}
function evaluateGate(input) {
@@ -215,8 +241,8 @@ function evaluateGate(input) {
if (claimsProgressionWithoutEvidence(input)) {
failed = true;
reasons.push('claimed progression without concrete execution evidence is forbidden');
requiredEvidence.push(describeRequirement(GATE_REQUIREMENTS.executionEvidence));
reasons.push('claimed progression without concrete progress evidence is forbidden');
requiredEvidence.push(describeRequirement(GATE_REQUIREMENTS.progressEvidence));
allowedResponseModes.push('evidence_preserving_follow_up');
}