feat(harness): complete protocol repair stop and archive ISS-016

Add repairable INVALID_PROGRESS_PROTOCOL observations, independent
PROGRESS_PROTOCOL_VIOLATED saturation, and controlled release paths.
Archive the OpenSpec change after syncing main specs and devflow.
This commit is contained in:
zhuyongxin
2026-07-27 19:10:07 +08:00
parent 5c369f3b6c
commit 38f781b157
44 changed files with 977 additions and 80 deletions
@@ -61,6 +61,53 @@ class DiagnosisProgressTrackerTest {
assertFalse(tracker.isDuplicate("lookup_knowledge", "scope-2"));
}
@Test
void progressProtocolViolationsAccumulateIndependentlyFromNoGain() {
DiagnosisProgressTracker tracker = new DiagnosisProgressTracker(3, 2);
tracker.recordDuplicateScope();
DiagnosisProgressSnapshotState first = tracker.recordProgressProtocolViolation();
assertEquals(1, first.consecutiveProgressProtocolViolations());
assertEquals(1, first.consecutiveNoGain());
assertEquals(DiagnosisCollectionState.COLLECTING, first.collectionState());
DiagnosisProgressSnapshotState second = tracker.recordProgressProtocolViolation();
assertEquals(2, second.consecutiveProgressProtocolViolations());
assertEquals(1, second.consecutiveNoGain());
assertEquals(DiagnosisCollectionState.SATURATED, second.collectionState());
assertEquals(DiagnosisStopReason.PROGRESS_PROTOCOL_VIOLATED, second.stopReason());
assertTrue(tracker.claimStopInstruction());
assertFalse(tracker.claimStopInstruction());
}
@Test
void validEvaluationClearsProtocolViolationCount() {
DiagnosisProgressTracker tracker = new DiagnosisProgressTracker(2, 3);
tracker.recordCompleted(call("call-1", "scope-1"), EvidenceStatus.EVIDENCE_FOUND);
tracker.recordProgressProtocolViolation();
tracker.applyPreviousObservation(new PreviousObservation("call-1", InformationGain.GAINED));
DiagnosisProgressSnapshotState state = tracker.snapshot();
assertEquals(0, state.consecutiveProgressProtocolViolations());
assertEquals(0, state.consecutiveNoGain());
assertEquals(DiagnosisCollectionState.COLLECTING, state.collectionState());
}
@Test
void rejectsUnexpectedPreviousObservationWithTypedViolation() {
DiagnosisProgressTracker tracker = new DiagnosisProgressTracker(2, 2);
ProgressProtocolViolationException failure = assertThrows(
ProgressProtocolViolationException.class,
() -> tracker.applyPreviousObservation(
new PreviousObservation("call-x", InformationGain.GAINED)));
assertEquals(ProgressProtocolViolationType.UNEXPECTED_PREVIOUS_OBSERVATION,
failure.violationType());
assertEquals("previous_observation", failure.missingField());
}
private CompletedToolCall call(String id, String scope) {
return new CompletedToolCall(id, "lookup_knowledge", scope);
}