feat(harness): improve trace fallback and reasoning audit

This commit is contained in:
zhuyongxin
2026-07-23 17:52:01 +08:00
parent 8fbc443f76
commit e20249c5d9
38 changed files with 1355 additions and 75 deletions
@@ -4,6 +4,8 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.superbiz.agent.harness.contract.SemanticVerdict;
import com.superbiz.agent.harness.audit.DiagnosisTraceRecorder;
import com.superbiz.agent.harness.audit.TraceAuditEvents;
import com.superbiz.agent.harness.core.DiagnosisHarnessCore;
import com.superbiz.agent.harness.core.RunContext;
import com.superbiz.agent.harness.retry.HarnessRetryExecutor;
@@ -31,6 +33,7 @@ public final class SemanticGuard {
private final ObjectMapper objectMapper;
private final SemanticGuardLimits limits;
private final Consumer<RetryAttempt> attemptRecorder;
private final DiagnosisTraceRecorder traceRecorder;
private final String prompt;
public SemanticGuard(DiagnosisHarnessCore core,
@@ -39,6 +42,17 @@ public final class SemanticGuard {
ObjectMapper objectMapper,
SemanticGuardLimits limits,
Consumer<RetryAttempt> attemptRecorder) {
this(core, retryExecutor, modelCall, objectMapper, limits,
attemptRecorder, DiagnosisTraceRecorder.noop());
}
public SemanticGuard(DiagnosisHarnessCore core,
HarnessRetryExecutor retryExecutor,
GuardModelCall modelCall,
ObjectMapper objectMapper,
SemanticGuardLimits limits,
Consumer<RetryAttempt> attemptRecorder,
DiagnosisTraceRecorder traceRecorder) {
this.core = Objects.requireNonNull(core, "core must not be null");
this.retryExecutor = Objects.requireNonNull(retryExecutor, "retryExecutor must not be null");
this.modelCall = Objects.requireNonNull(modelCall, "modelCall must not be null");
@@ -46,6 +60,7 @@ public final class SemanticGuard {
this.limits = Objects.requireNonNull(limits, "limits must not be null");
this.attemptRecorder = Objects.requireNonNull(
attemptRecorder, "attemptRecorder must not be null");
this.traceRecorder = Objects.requireNonNull(traceRecorder, "traceRecorder must not be null");
this.prompt = SemanticGuardPrompt.load();
}
@@ -68,7 +83,10 @@ public final class SemanticGuard {
() -> parse(modelCall.call(
context, modelPrompt, remainingTimeout(startedNanos), limits.maxOutputBytes())),
this::classify,
attemptRecorder);
attempt -> {
attemptRecorder.accept(attempt);
traceRecorder.record(TraceAuditEvents.semanticAttempt(context, attempt));
});
}
private SemanticGuardDecision parse(String output) {