Update DeltaStore Trace Explorer Phase 2: replay-core.js
Browse files- replay-core.js +32 -0
replay-core.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
| 1 |
export const SCHEMA_VERSION = "deltastore-replay-trace-v1";
|
|
|
|
| 2 |
|
| 3 |
export function parseTrace(value) {
|
| 4 |
const trace = typeof value === "string" ? JSON.parse(value) : value;
|
|
@@ -15,3 +16,34 @@ export function compareBranch(trace, branchId) {
|
|
| 15 |
const index = trace.original_trajectory.findIndex(event => event.event_id === checkpoint.event_id);
|
| 16 |
return { sharedPrefix: trace.original_trajectory.slice(0, index + 1), originalTail: trace.original_trajectory.slice(index + 1), alternate: branch.events, originalOutcome: trace.final_outcome || {}, alternateOutcome: branch.final_outcome || {}, classification: branch.comparison_classification || "outcome_changed" };
|
| 17 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
export const SCHEMA_VERSION = "deltastore-replay-trace-v1";
|
| 2 |
+
export const EXCHANGE_SCHEMA_VERSION = "solstice-agent-trace-exchange/v1";
|
| 3 |
|
| 4 |
export function parseTrace(value) {
|
| 5 |
const trace = typeof value === "string" ? JSON.parse(value) : value;
|
|
|
|
| 16 |
const index = trace.original_trajectory.findIndex(event => event.event_id === checkpoint.event_id);
|
| 17 |
return { sharedPrefix: trace.original_trajectory.slice(0, index + 1), originalTail: trace.original_trajectory.slice(index + 1), alternate: branch.events, originalOutcome: trace.final_outcome || {}, alternateOutcome: branch.final_outcome || {}, classification: branch.comparison_classification || "outcome_changed" };
|
| 18 |
}
|
| 19 |
+
|
| 20 |
+
export function parseExchange(value) {
|
| 21 |
+
const packageValue = typeof value === "string" ? JSON.parse(value) : value;
|
| 22 |
+
if (!packageValue || packageValue.schema_version !== EXCHANGE_SCHEMA_VERSION || !Array.isArray(packageValue.events)) throw new Error("Unsupported or malformed exchange package");
|
| 23 |
+
const ids = new Set();
|
| 24 |
+
let previous = -1;
|
| 25 |
+
for (const event of packageValue.events) {
|
| 26 |
+
if (!event.event_id || ids.has(event.event_id)) throw new Error("Duplicate or missing exchange event ID");
|
| 27 |
+
if (!Number.isInteger(event.sequence) || event.sequence <= previous) throw new Error("Invalid exchange event ordering");
|
| 28 |
+
ids.add(event.event_id); previous = event.sequence;
|
| 29 |
+
}
|
| 30 |
+
return packageValue;
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
export function attachFindings(packageValue, findingsValue) {
|
| 34 |
+
const packageTrace = parseExchange(packageValue);
|
| 35 |
+
const findings = Array.isArray(findingsValue) ? findingsValue : findingsValue?.findings;
|
| 36 |
+
if (!Array.isArray(findings)) throw new Error("Findings must be an array");
|
| 37 |
+
const eventIds = new Set(packageTrace.events.map(event => event.event_id));
|
| 38 |
+
for (const finding of findings) {
|
| 39 |
+
if (finding.trace_id && finding.trace_id !== packageTrace.trace_id) throw new Error("Finding trace ID does not match");
|
| 40 |
+
for (const ref of finding.evidence_refs || finding.evidence_events || []) if (!eventIds.has(ref)) throw new Error("Finding references an unknown event");
|
| 41 |
+
}
|
| 42 |
+
return {...packageTrace, findings};
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
export function downloadJson(value, filename) {
|
| 46 |
+
const blob = new Blob([JSON.stringify(value, null, 2)], {type: "application/json"});
|
| 47 |
+
const link = document.createElement("a"); link.href = URL.createObjectURL(blob); link.download = filename; link.click();
|
| 48 |
+
URL.revokeObjectURL(link.href);
|
| 49 |
+
}
|