vericify 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/adapters/index.js +31 -17
- package/src/adapters/local-state.js +56 -22
- package/src/adapters/provenance.js +70 -0
- package/src/projection/live-signal.js +627 -0
- package/src/projection/runs.js +185 -30
- package/src/tui/app.js +1 -0
- package/src/tui/panels.js +89 -62
- package/src/tui/runtime-activity.js +2 -0
package/package.json
CHANGED
package/src/adapters/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { hashText } from "../core/util.js";
|
|
2
2
|
import { listLocalStatePaths, loadLocalState } from "./local-state.js";
|
|
3
3
|
import { loadPeerAdapterStates } from "./peer-capture.js";
|
|
4
|
+
import { annotateRecords, mergeByKeyWithProvenance } from "./provenance.js";
|
|
4
5
|
import {
|
|
5
6
|
attachWorkspaceAdapter,
|
|
6
7
|
detectWorkspaceAdapters,
|
|
@@ -10,13 +11,6 @@ import {
|
|
|
10
11
|
|
|
11
12
|
export const DEFAULT_ADAPTER = "local-state";
|
|
12
13
|
|
|
13
|
-
function mergeByKey(preferred, secondary, getKey) {
|
|
14
|
-
const merged = new Map();
|
|
15
|
-
for (const item of secondary) merged.set(getKey(item), item);
|
|
16
|
-
for (const item of preferred) merged.set(getKey(item), item);
|
|
17
|
-
return [...merged.values()];
|
|
18
|
-
}
|
|
19
|
-
|
|
20
14
|
export function listDefaultWorkspacePaths(workspaceRoot) {
|
|
21
15
|
return listLocalStatePaths(workspaceRoot);
|
|
22
16
|
}
|
|
@@ -26,29 +20,49 @@ export function loadWorkspaceState(workspaceRoot) {
|
|
|
26
20
|
const adapterProfiles = detectWorkspaceAdapters(workspaceRoot, state.adapterAttachments);
|
|
27
21
|
const peer = loadPeerAdapterStates(workspaceRoot, adapterProfiles);
|
|
28
22
|
|
|
29
|
-
const handoffs =
|
|
23
|
+
const handoffs = mergeByKeyWithProvenance(
|
|
30
24
|
state.handoffs,
|
|
31
|
-
peer.handoffs,
|
|
25
|
+
annotateRecords(peer.handoffs, {
|
|
26
|
+
source: "peer",
|
|
27
|
+
sourceKind: "handoff",
|
|
28
|
+
sourcePath: peer.sourceRefs?.[0],
|
|
29
|
+
}),
|
|
32
30
|
(h) => h.handoff_id ?? hashText(JSON.stringify(h))
|
|
33
31
|
);
|
|
34
|
-
const todoNodes =
|
|
32
|
+
const todoNodes = mergeByKeyWithProvenance(
|
|
35
33
|
state.todoNodes,
|
|
36
|
-
peer.todoNodes,
|
|
34
|
+
annotateRecords(peer.todoNodes, {
|
|
35
|
+
source: "peer",
|
|
36
|
+
sourceKind: "todo_node",
|
|
37
|
+
sourcePath: peer.sourceRefs?.[0],
|
|
38
|
+
}),
|
|
37
39
|
(n) => n.id ?? hashText(JSON.stringify(n))
|
|
38
40
|
);
|
|
39
|
-
const ledgerEntries =
|
|
41
|
+
const ledgerEntries = mergeByKeyWithProvenance(
|
|
40
42
|
state.ledgerEntries,
|
|
41
|
-
peer.ledgerEntries,
|
|
43
|
+
annotateRecords(peer.ledgerEntries, {
|
|
44
|
+
source: "peer",
|
|
45
|
+
sourceKind: "run_ledger",
|
|
46
|
+
sourcePath: peer.sourceRefs?.[0],
|
|
47
|
+
}),
|
|
42
48
|
(e) => e.id ?? hashText(`${e.timestamp_utc}:${e.tool}:${e.message}`)
|
|
43
49
|
);
|
|
44
|
-
const statusEvents =
|
|
50
|
+
const statusEvents = mergeByKeyWithProvenance(
|
|
45
51
|
state.statusEvents,
|
|
46
|
-
peer.statusEvents,
|
|
52
|
+
annotateRecords(peer.statusEvents, {
|
|
53
|
+
source: "peer",
|
|
54
|
+
sourceKind: "status_event",
|
|
55
|
+
sourcePath: peer.sourceRefs?.[0],
|
|
56
|
+
}),
|
|
47
57
|
(e) => e.event_id ?? hashText(`${e.timestamp}:${e.source_module}:${e.event_type}:${e.status}`)
|
|
48
58
|
).sort((a, b) => String(a.timestamp).localeCompare(String(b.timestamp)));
|
|
49
|
-
const processPosts =
|
|
59
|
+
const processPosts = mergeByKeyWithProvenance(
|
|
50
60
|
state.processPosts,
|
|
51
|
-
peer.processPosts,
|
|
61
|
+
annotateRecords(peer.processPosts, {
|
|
62
|
+
source: "peer",
|
|
63
|
+
sourceKind: "process_post",
|
|
64
|
+
sourcePath: peer.sourceRefs?.[0],
|
|
65
|
+
}),
|
|
52
66
|
(p) => p.process_post_id ?? hashText(`${p.timestamp}:${p.agent_id}:${p.summary}`)
|
|
53
67
|
).sort((a, b) => String(a.timestamp).localeCompare(String(b.timestamp)));
|
|
54
68
|
|
|
@@ -2,18 +2,12 @@ import { hashText, unique } from "../core/util.js";
|
|
|
2
2
|
import { readJson, readNdjson } from "../core/fs.js";
|
|
3
3
|
import { listStorePaths, resolveStoreLayout } from "../store/paths.js";
|
|
4
4
|
import { readAdapterAttachments } from "../store/adapter-attachments.js";
|
|
5
|
+
import { annotateRecords, mergeByKeyWithProvenance } from "./provenance.js";
|
|
5
6
|
|
|
6
7
|
export function listLocalStatePaths(workspaceRoot) {
|
|
7
8
|
return listStorePaths(workspaceRoot);
|
|
8
9
|
}
|
|
9
10
|
|
|
10
|
-
function mergeByKey(preferredItems, partnerItems, getKey) {
|
|
11
|
-
const merged = new Map();
|
|
12
|
-
for (const item of partnerItems) merged.set(getKey(item), item);
|
|
13
|
-
for (const item of preferredItems) merged.set(getKey(item), item);
|
|
14
|
-
return [...merged.values()];
|
|
15
|
-
}
|
|
16
|
-
|
|
17
11
|
function mergeOrderedIds(preferred, partner) {
|
|
18
12
|
return unique([...preferred, ...partner]);
|
|
19
13
|
}
|
|
@@ -36,29 +30,69 @@ export function loadLocalState(workspaceRoot) {
|
|
|
36
30
|
statusEvents: readNdjson(paths.partner.statusEvents),
|
|
37
31
|
};
|
|
38
32
|
|
|
39
|
-
const handoffs =
|
|
40
|
-
Object.values(vericifyState.handoffRegistry.handoffs ?? {}),
|
|
41
|
-
|
|
33
|
+
const handoffs = mergeByKeyWithProvenance(
|
|
34
|
+
annotateRecords(Object.values(vericifyState.handoffRegistry.handoffs ?? {}), {
|
|
35
|
+
source: "native",
|
|
36
|
+
sourceKind: "handoff",
|
|
37
|
+
sourcePath: paths.vericify.handoffRegistry,
|
|
38
|
+
}),
|
|
39
|
+
annotateRecords(Object.values(partnerState.handoffRegistry.handoffs ?? {}), {
|
|
40
|
+
source: "partner",
|
|
41
|
+
sourceKind: "handoff",
|
|
42
|
+
sourcePath: paths.partner.handoffRegistry,
|
|
43
|
+
}),
|
|
42
44
|
(handoff) => handoff.handoff_id ?? hashText(JSON.stringify(handoff))
|
|
43
45
|
);
|
|
44
|
-
const todoNodes =
|
|
45
|
-
Object.values(vericifyState.todoState.nodes ?? {}),
|
|
46
|
-
|
|
46
|
+
const todoNodes = mergeByKeyWithProvenance(
|
|
47
|
+
annotateRecords(Object.values(vericifyState.todoState.nodes ?? {}), {
|
|
48
|
+
source: "native",
|
|
49
|
+
sourceKind: "todo_node",
|
|
50
|
+
sourcePath: paths.vericify.todoState,
|
|
51
|
+
}),
|
|
52
|
+
annotateRecords(Object.values(partnerState.todoState.nodes ?? {}), {
|
|
53
|
+
source: "partner",
|
|
54
|
+
sourceKind: "todo_node",
|
|
55
|
+
sourcePath: paths.partner.todoState,
|
|
56
|
+
}),
|
|
47
57
|
(node) => node.id ?? hashText(JSON.stringify(node))
|
|
48
58
|
);
|
|
49
|
-
const ledgerEntries =
|
|
50
|
-
Array.isArray(vericifyState.runLedger.entries) ? vericifyState.runLedger.entries : [],
|
|
51
|
-
|
|
59
|
+
const ledgerEntries = mergeByKeyWithProvenance(
|
|
60
|
+
annotateRecords(Array.isArray(vericifyState.runLedger.entries) ? vericifyState.runLedger.entries : [], {
|
|
61
|
+
source: "native",
|
|
62
|
+
sourceKind: "run_ledger",
|
|
63
|
+
sourcePath: paths.vericify.runLedger,
|
|
64
|
+
}),
|
|
65
|
+
annotateRecords(Array.isArray(partnerState.runLedger.entries) ? partnerState.runLedger.entries : [], {
|
|
66
|
+
source: "partner",
|
|
67
|
+
sourceKind: "run_ledger",
|
|
68
|
+
sourcePath: paths.partner.runLedger,
|
|
69
|
+
}),
|
|
52
70
|
(entry) => entry.id ?? hashText(`${entry.timestamp_utc}:${entry.tool}:${entry.message}`)
|
|
53
71
|
);
|
|
54
|
-
const statusEvents =
|
|
55
|
-
vericifyState.statusEvents,
|
|
56
|
-
|
|
72
|
+
const statusEvents = mergeByKeyWithProvenance(
|
|
73
|
+
annotateRecords(vericifyState.statusEvents, {
|
|
74
|
+
source: "native",
|
|
75
|
+
sourceKind: "status_event",
|
|
76
|
+
sourcePath: paths.vericify.statusEvents,
|
|
77
|
+
}),
|
|
78
|
+
annotateRecords(partnerState.statusEvents, {
|
|
79
|
+
source: "partner",
|
|
80
|
+
sourceKind: "status_event",
|
|
81
|
+
sourcePath: paths.partner.statusEvents,
|
|
82
|
+
}),
|
|
57
83
|
(event) => event.event_id ?? hashText(`${event.timestamp}:${event.source_module}:${event.event_type}:${event.status}`)
|
|
58
84
|
).sort((left, right) => String(left.timestamp).localeCompare(String(right.timestamp)));
|
|
59
|
-
const processPosts =
|
|
60
|
-
Array.isArray(vericifyState.processPosts.posts) ? vericifyState.processPosts.posts : [],
|
|
61
|
-
|
|
85
|
+
const processPosts = mergeByKeyWithProvenance(
|
|
86
|
+
annotateRecords(Array.isArray(vericifyState.processPosts.posts) ? vericifyState.processPosts.posts : [], {
|
|
87
|
+
source: "native",
|
|
88
|
+
sourceKind: "process_post",
|
|
89
|
+
sourcePath: paths.vericify.processPosts,
|
|
90
|
+
}),
|
|
91
|
+
annotateRecords(Array.isArray(partnerState.processPosts.posts) ? partnerState.processPosts.posts : [], {
|
|
92
|
+
source: "partner",
|
|
93
|
+
sourceKind: "process_post",
|
|
94
|
+
sourcePath: paths.partner.processPosts,
|
|
95
|
+
}),
|
|
62
96
|
(post) => post.process_post_id ?? hashText(`${post.timestamp}:${post.agent_id}:${post.summary}`)
|
|
63
97
|
).sort((left, right) => String(left.timestamp).localeCompare(String(right.timestamp)));
|
|
64
98
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
function sourceSignature(source) {
|
|
2
|
+
return `${source.source ?? "-"}|${source.source_kind ?? "-"}|${source.source_path ?? "-"}`;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
function uniqueRecordSources(values) {
|
|
6
|
+
const seen = new Set();
|
|
7
|
+
const merged = [];
|
|
8
|
+
for (const value of values) {
|
|
9
|
+
if (!value) continue;
|
|
10
|
+
const normalized = {
|
|
11
|
+
source: value.source,
|
|
12
|
+
source_kind: value.source_kind,
|
|
13
|
+
source_path: value.source_path,
|
|
14
|
+
};
|
|
15
|
+
const signature = sourceSignature(normalized);
|
|
16
|
+
if (seen.has(signature)) continue;
|
|
17
|
+
seen.add(signature);
|
|
18
|
+
merged.push(normalized);
|
|
19
|
+
}
|
|
20
|
+
return merged;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function recordSourceList(record) {
|
|
24
|
+
const explicit = record.record_source
|
|
25
|
+
? [{
|
|
26
|
+
source: record.record_source,
|
|
27
|
+
source_kind: record.record_source_kind,
|
|
28
|
+
source_path: record.record_source_path,
|
|
29
|
+
}]
|
|
30
|
+
: [];
|
|
31
|
+
return uniqueRecordSources([...explicit, ...(Array.isArray(record.record_sources) ? record.record_sources : [])]);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function mergeRecordMetadata(preferred, secondary) {
|
|
35
|
+
const recordSources = uniqueRecordSources([...recordSourceList(preferred), ...recordSourceList(secondary)]);
|
|
36
|
+
const primary = recordSources[0];
|
|
37
|
+
return {
|
|
38
|
+
...secondary,
|
|
39
|
+
...preferred,
|
|
40
|
+
record_source: preferred.record_source ?? secondary.record_source ?? primary?.source,
|
|
41
|
+
record_source_kind: preferred.record_source_kind ?? secondary.record_source_kind ?? primary?.source_kind,
|
|
42
|
+
record_source_path: preferred.record_source_path ?? secondary.record_source_path ?? primary?.source_path,
|
|
43
|
+
record_sources: recordSources,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function annotateRecord(record, { source, sourceKind, sourcePath }) {
|
|
48
|
+
return mergeRecordMetadata({
|
|
49
|
+
...record,
|
|
50
|
+
record_source: source,
|
|
51
|
+
record_source_kind: sourceKind,
|
|
52
|
+
record_source_path: sourcePath,
|
|
53
|
+
}, record);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function annotateRecords(records, provenance) {
|
|
57
|
+
return records.map((record) => annotateRecord(record, provenance));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function mergeByKeyWithProvenance(preferredItems, secondaryItems, getKey) {
|
|
61
|
+
const merged = new Map();
|
|
62
|
+
const upsert = (item) => {
|
|
63
|
+
const key = getKey(item);
|
|
64
|
+
const existing = merged.get(key);
|
|
65
|
+
merged.set(key, existing ? mergeRecordMetadata(item, existing) : item);
|
|
66
|
+
};
|
|
67
|
+
for (const item of secondaryItems) upsert(item);
|
|
68
|
+
for (const item of preferredItems) upsert(item);
|
|
69
|
+
return [...merged.values()];
|
|
70
|
+
}
|