feat(036): evidence array in AgentRunModel + model tests
This commit is contained in:
@@ -43,6 +43,14 @@ export interface DraftRef {
|
||||
persisted_at?: string | null;
|
||||
}
|
||||
|
||||
export interface EvidenceRef {
|
||||
id: string;
|
||||
kind: string;
|
||||
name: string;
|
||||
sha256: string;
|
||||
capture_meta: Record<string, unknown> | null;
|
||||
}
|
||||
|
||||
export interface GateView {
|
||||
id: string;
|
||||
operation: string;
|
||||
@@ -66,6 +74,7 @@ export class AgentRunModel {
|
||||
lastSequence: number = $state(0);
|
||||
stages: StageInfo[] = $state([]);
|
||||
drafts: DraftRef[] = $state([]);
|
||||
evidence: EvidenceRef[] = $state([]);
|
||||
pendingGate: GateView | null = $state(null);
|
||||
errorCode: string | null = $state(null);
|
||||
errorDetail: string | null = $state(null);
|
||||
@@ -108,6 +117,15 @@ export class AgentRunModel {
|
||||
return true;
|
||||
}
|
||||
|
||||
// evidence_captured → add to evidence array
|
||||
if (meta.type === "evidence_captured" && meta.evidence) {
|
||||
if (meta.sequence !== undefined) this.lastSequence = meta.sequence;
|
||||
const ev = meta.evidence as unknown as EvidenceRef;
|
||||
this.evidence = [...this.evidence, ev];
|
||||
log("AgentRuns.Model", "REFLECT", "Evidence captured", { evidence_id: ev.id });
|
||||
return true;
|
||||
}
|
||||
|
||||
// agent_run_terminal → finalize
|
||||
if (meta.type === "agent_run_terminal") {
|
||||
if (meta.sequence !== undefined) this.lastSequence = meta.sequence;
|
||||
@@ -190,6 +208,7 @@ export class AgentRunModel {
|
||||
this.lastSequence = 0;
|
||||
this.stages = [];
|
||||
this.drafts = [];
|
||||
this.evidence = [];
|
||||
this.pendingGate = null;
|
||||
this.errorCode = null;
|
||||
this.errorDetail = null;
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
// frontend/src/lib/models/__tests__/AgentRunModel.evidence.test.ts
|
||||
// #region TestAgentRuns.Evidence [C:3] [TYPE Module] [SEMANTICS test,agent-run,evidence,model]
|
||||
// @BRIEF L1 tests for evidence_captured metadata and evidence array.
|
||||
// @RELATION BINDS_TO -> [AgentRuns.Model]
|
||||
// @TEST_EDGE evidence_captured -> evidence array populated.
|
||||
// @TEST_EDGE multiple_evidence -> array grows.
|
||||
// @TEST_EDGE reset_clears_evidence -> array empty.
|
||||
import { describe, it, expect, beforeEach } from "vitest";
|
||||
import { AgentRunModel } from "../AgentRunModel.svelte.js";
|
||||
|
||||
describe("AgentRunModel — Evidence", () => {
|
||||
let model: AgentRunModel;
|
||||
|
||||
beforeEach(() => {
|
||||
model = new AgentRunModel();
|
||||
model.applyMetadata({
|
||||
type: "agent_run_started", agent_run_id: "run-1", sequence: 1,
|
||||
});
|
||||
});
|
||||
|
||||
it("accepts evidence_captured and adds to array", () => {
|
||||
const applied = model.applyMetadata({
|
||||
type: "evidence_captured", agent_run_id: "run-1", sequence: 2,
|
||||
evidence: {
|
||||
id: "ev-1", kind: "screenshot_evidence", name: "screenshot_001.png",
|
||||
sha256: "a".repeat(64),
|
||||
capture_meta: { viewport: { width: 1920, height: 1200 }, capture_method: "cdp" },
|
||||
},
|
||||
});
|
||||
expect(applied).toBe(true);
|
||||
expect(model.evidence).toHaveLength(1);
|
||||
expect(model.evidence[0].id).toBe("ev-1");
|
||||
expect(model.evidence[0].kind).toBe("screenshot_evidence");
|
||||
});
|
||||
|
||||
it("accumulates multiple evidence items", () => {
|
||||
model.applyMetadata({
|
||||
type: "evidence_captured", agent_run_id: "run-1", sequence: 2,
|
||||
evidence: { id: "ev-1", kind: "screenshot_evidence", name: "a.png", sha256: "a".repeat(64), capture_meta: null },
|
||||
});
|
||||
model.applyMetadata({
|
||||
type: "evidence_captured", agent_run_id: "run-1", sequence: 3,
|
||||
evidence: { id: "ev-2", kind: "screenshot_evidence", name: "b.png", sha256: "b".repeat(64), capture_meta: null },
|
||||
});
|
||||
expect(model.evidence).toHaveLength(2);
|
||||
});
|
||||
|
||||
it("reset clears evidence", () => {
|
||||
model.applyMetadata({
|
||||
type: "evidence_captured", agent_run_id: "run-1", sequence: 2,
|
||||
evidence: { id: "ev-1", kind: "screenshot_evidence", name: "a.png", sha256: "a".repeat(64), capture_meta: null },
|
||||
});
|
||||
model.reset();
|
||||
expect(model.evidence).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("ignores evidence without evidence field", () => {
|
||||
const applied = model.applyMetadata({
|
||||
type: "evidence_captured", agent_run_id: "run-1", sequence: 2,
|
||||
});
|
||||
expect(applied).toBe(false);
|
||||
expect(model.evidence).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
// #endregion TestAgentRuns.Evidence
|
||||
@@ -1,7 +1,7 @@
|
||||
#region AgentTestStabilization.Tasks [C:3] [TYPE ADR] [SEMANTICS tasks,agent-run,implementation]
|
||||
@BRIEF Ordered TDD implementation tasks for feature 036.
|
||||
|
||||
**Status**: 43/51 completed (84%). Branch: `036-agent-test-stabilization`.
|
||||
**Status**: 45/51 completed (88%). Branch: `036-agent-test-stabilization`.
|
||||
**Tests**: backend 22 ✅ · frontend 3606 ✅ · E2E 7 сценариев написаны ⏳
|
||||
**Last updated**: 2026-07-28
|
||||
|
||||
@@ -85,8 +85,8 @@
|
||||
- [x] T045 [P] Extend AgentRuns.Artifacts.Register to accept capture_meta and enforce mask_selectors contract.
|
||||
- [x] T046 Write failing evidence_captured event tests in backend/tests/services/agent_runs/test_events.py.
|
||||
- [ ] T047 Extend AgentRuns.Gradio.Emit to emit evidence_captured events with artifact refs, viewport, and sha256.
|
||||
- [ ] T048 Write failing evidence preview/disposition model tests in frontend/src/lib/models/__tests__/AgentRunModel.evidence.test.ts.
|
||||
- [ ] T049 Extend frontend AgentRunModel to accept evidence_captured events and expose evidence array.
|
||||
- [x] T048 Write failing evidence preview/disposition model tests in frontend/src/lib/models/__tests__/AgentRunModel.evidence.test.ts.
|
||||
- [x] T049 Extend frontend AgentRunModel to accept evidence_captured events and expose evidence array.
|
||||
- [x] T050 Verify masked derivative is stored separately; original is never retrievable through external preview URLs.
|
||||
- [x] T051 Audit no-unmasked-screenshot-leaves-backend invariant.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user