// std/agent/completion_evidence ā typed, bounded terminal evidence contracts.
import { CompletionRequirementEvidenceRecord } from "std/agent/completion_requirements"
import { CompletionVerificationState } from "std/agent/judge_internals"
import { AgentTranscriptToolLifecycleStatus } from "std/agent/transcript"
const COMPLETION_EVIDENCE_FIELD_CHAR_LIMIT = 4500
const COMPLETION_FINAL_OUTPUT_EVIDENCE_INDEX = -1
pub const COMPLETION_VERIFICATION_EVIDENCE_INDEX = -2
pub type CompletionEvidenceRole = "observation" | "mutation" | "verification" | "other"
pub type CompletionToolSemantics = {
name: string,
kind: string,
side_effect_level: string,
read_only: bool,
evidence_role: CompletionEvidenceRole,
}
pub type CompletionEvidenceAction = {
ordinal: int,
evidence_index: int,
tool_call_id: string,
name: string,
semantics: CompletionToolSemantics,
lifecycle_status: AgentTranscriptToolLifecycleStatus,
arguments: string,
observation: string,
result_facts: string,
has_error_result: bool,
}
pub type CompletionEvidenceIssue = {
code: string,
record_index: int,
message: string,
details: string,
}
pub type CompletionEvidencePacket = {
schema: "harn.completion_judge_evidence.v2",
raw_message_count: int,
raw_transcript_digest: string,
relevant_action_count: int,
omitted_read_only_call_count: int,
omitted_older_action_count: int,
lifecycle_issue_count: int,
lifecycle_issues: list<CompletionEvidenceIssue>,
actions: list<CompletionEvidenceAction>,
fallback_observations: list<CompletionEvidenceAction>,
requirement_evidence: list<CompletionRequirementEvidenceRecord>,
}
pub type CompletionEvidenceSelection = {
name: string,
evidence_role: CompletionEvidenceRole,
evidence_index: int,
}
pub type CompletionEvidenceProjectionStats = {
schema: "harn.completion_judge_evidence_projection.v1",
raw_message_count: int,
relevant_call_count: int,
included_action_count: int,
included_fallback_observation_count: int,
omitted_read_only_call_count: int,
omitted_older_action_count: int,
lifecycle_issue_count: int,
serialized_chars: int,
raw_transcript_digest: string,
selected_actions: list<CompletionEvidenceSelection>,
}
pub type CompletionEvidenceProjection = {
packet: CompletionEvidencePacket,
serialized: string,
stats: CompletionEvidenceProjectionStats,
}
pub type CompletionEvidenceSnapshot = {
schema: "harn.completion_evidence_snapshot.v1",
evidence_id: string,
session_id: string,
task: string,
stop_reason: string,
// These three fields are display projections of the candidate turn. The
// unprojected emission below is the authority for completion declarations.
text: string,
visible_text: string,
last_text: string,
raw_text: string,
transcript: string,
judge_evidence: string,
judge_evidence_packet: CompletionEvidencePacket,
judge_evidence_projection: CompletionEvidenceProjectionStats,
all_tools_used: string,
successful_tools_used: string,
iteration: int,
knowledge_state: string,
// Deferred effects survive turns. Completion policy alone decides whether
// later evidence supersedes them, so expose their count instead of hiding a veto.
pending_tool_batch_effect_count: int,
// Absent until a deterministic gate actually ran and reported.
verification?: CompletionVerificationState?,
}
fn completion_evidence_clip(value: string) -> string {
if len(value) <= COMPLETION_EVIDENCE_FIELD_CHAR_LIMIT {
return value
}
const tail_chars = COMPLETION_EVIDENCE_FIELD_CHAR_LIMIT / 3
const head_chars = COMPLETION_EVIDENCE_FIELD_CHAR_LIMIT - tail_chars
const omitted = len(value) - COMPLETION_EVIDENCE_FIELD_CHAR_LIMIT
return substring(value, 0, head_chars)
+ "\nā¦["
+ to_string(omitted)
+ " chars elided ā middle of evidence]ā¦\n"
+ substring(value, len(value) - tail_chars, len(value))
}
fn completion_requirement_evidence_without(
records: list<CompletionRequirementEvidenceRecord>,
evidence_index: int,
) -> list<CompletionRequirementEvidenceRecord> {
return records.filter({ record -> record.evidence_index != evidence_index }).to_list()
}
/**
* Project final-output and deterministic readings onto one requirement-evidence model.
*
* @effects: []
* @errors: []
* @api_stability: internal
*/
pub fn completion_requirement_evidence_packet(
packet: CompletionEvidencePacket,
final_text: string,
verification: CompletionVerificationState? = nil,
) -> CompletionEvidencePacket {
let records = packet.requirement_evidence
records = completion_requirement_evidence_without(records, COMPLETION_FINAL_OUTPUT_EVIDENCE_INDEX)
records = completion_requirement_evidence_without(records, COMPLETION_VERIFICATION_EVIDENCE_INDEX)
const answer = trim(final_text)
if answer != "" {
records = records
+ [
{
evidence_index: COMPLETION_FINAL_OUTPUT_EVIDENCE_INDEX,
role: "assistant_output",
supports_completion: true,
summary: completion_evidence_clip(answer),
representative_artifact_ids: [],
measurement: "present",
},
]
}
if verification != nil {
records = records
+ [
{
evidence_index: COMPLETION_VERIFICATION_EVIDENCE_INDEX,
role: "deterministic_verification",
supports_completion: verification.observed == "passed",
summary: "Deterministic verification observed `" + verification.observed + "`.",
representative_artifact_ids: [],
measurement: verification.observed,
},
]
}
return packet + {requirement_evidence: records}
}
/**
* Bind one terminal decision to its complete typed evidence snapshot.
*
* @effects: []
* @errors: []
* @api_stability: internal
*/
pub fn completion_evidence_id(
task: string,
stop_reason: string,
text: string,
packet: CompletionEvidencePacket,
pending_tool_batch_effect_count: int,
verification: CompletionVerificationState? = nil,
) -> string {
return "sha256:"
+ sha256(
json_stringify(
{
task: task,
trigger: stop_reason,
candidate_text: text,
actions: packet.actions,
fallback_observations: packet.fallback_observations,
requirement_evidence: packet.requirement_evidence,
lifecycle_issues: packet.lifecycle_issues,
pending_tool_batch_effect_count: pending_tool_batch_effect_count,
verification: verification,
},
),
)
}