vericify 0.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/README.md +389 -0
- package/package.json +57 -0
- package/src/adapters/index.js +37 -0
- package/src/adapters/local-state.js +86 -0
- package/src/adapters/registry.js +126 -0
- package/src/api.js +12 -0
- package/src/checkpoints/policy.js +96 -0
- package/src/compare/engine.js +220 -0
- package/src/core/fs.js +86 -0
- package/src/core/util.js +59 -0
- package/src/index.js +464 -0
- package/src/post/process-posts.js +72 -0
- package/src/projection/runs.js +809 -0
- package/src/publish/artifact.js +91 -0
- package/src/similarity/semantic-hash.js +95 -0
- package/src/store/adapter-attachments.js +47 -0
- package/src/store/common.js +38 -0
- package/src/store/handoffs.js +64 -0
- package/src/store/paths.js +40 -0
- package/src/store/run-ledger.js +46 -0
- package/src/store/status-events.js +39 -0
- package/src/store/todo-state.js +49 -0
- package/src/sync/outbox.js +29 -0
- package/src/tui/app.js +571 -0
- package/src/tui/commands.js +224 -0
- package/src/tui/panels.js +440 -0
- package/src/tui/runtime-activity.js +172 -0
package/src/index.js
ADDED
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import {
|
|
4
|
+
DEFAULT_ADAPTER,
|
|
5
|
+
attachAdapter,
|
|
6
|
+
detectAdapters,
|
|
7
|
+
listDefaultWorkspacePaths,
|
|
8
|
+
loadWorkspaceState,
|
|
9
|
+
} from "./adapters/index.js";
|
|
10
|
+
import { buildRunComparison, findRunById } from "./compare/engine.js";
|
|
11
|
+
import { appendProcessPost } from "./post/process-posts.js";
|
|
12
|
+
import { publishRunArtifact } from "./publish/artifact.js";
|
|
13
|
+
import { projectWorkspaceState } from "./projection/runs.js";
|
|
14
|
+
import { upsertHandoff } from "./store/handoffs.js";
|
|
15
|
+
import { appendRunLedgerEntry } from "./store/run-ledger.js";
|
|
16
|
+
import { appendStatusEvent } from "./store/status-events.js";
|
|
17
|
+
import { upsertTodoNode } from "./store/todo-state.js";
|
|
18
|
+
import { enqueueSyncOutboxItem } from "./sync/outbox.js";
|
|
19
|
+
import { runHub } from "./tui/app.js";
|
|
20
|
+
|
|
21
|
+
function parseArgs(argv) {
|
|
22
|
+
const args = argv.slice(2);
|
|
23
|
+
const command = args[0] && !args[0].startsWith("--") ? args[0] : "hub";
|
|
24
|
+
const options = {
|
|
25
|
+
workspaceRoot: process.cwd(),
|
|
26
|
+
feedFile: undefined,
|
|
27
|
+
adapter: undefined,
|
|
28
|
+
sessionId: undefined,
|
|
29
|
+
captureMode: undefined,
|
|
30
|
+
label: undefined,
|
|
31
|
+
notes: undefined,
|
|
32
|
+
runId: undefined,
|
|
33
|
+
compareRunId: undefined,
|
|
34
|
+
agentId: undefined,
|
|
35
|
+
kind: undefined,
|
|
36
|
+
summary: undefined,
|
|
37
|
+
laneId: undefined,
|
|
38
|
+
branchId: undefined,
|
|
39
|
+
checkpointRef: undefined,
|
|
40
|
+
toolRefs: [],
|
|
41
|
+
evidenceRefs: [],
|
|
42
|
+
id: undefined,
|
|
43
|
+
title: undefined,
|
|
44
|
+
status: undefined,
|
|
45
|
+
from: undefined,
|
|
46
|
+
to: undefined,
|
|
47
|
+
note: undefined,
|
|
48
|
+
actor: undefined,
|
|
49
|
+
taskType: undefined,
|
|
50
|
+
priority: undefined,
|
|
51
|
+
sourceFile: undefined,
|
|
52
|
+
category: undefined,
|
|
53
|
+
tool: undefined,
|
|
54
|
+
artifacts: [],
|
|
55
|
+
metadataJson: undefined,
|
|
56
|
+
eventType: undefined,
|
|
57
|
+
sourceModule: undefined,
|
|
58
|
+
traceId: undefined,
|
|
59
|
+
objectiveId: undefined,
|
|
60
|
+
decisionId: undefined,
|
|
61
|
+
payloadJson: undefined,
|
|
62
|
+
message: undefined,
|
|
63
|
+
section: undefined,
|
|
64
|
+
sourceLine: undefined,
|
|
65
|
+
dependsOn: [],
|
|
66
|
+
sourceTodoPath: undefined,
|
|
67
|
+
timestamp: undefined,
|
|
68
|
+
endpoint: undefined,
|
|
69
|
+
target: undefined,
|
|
70
|
+
};
|
|
71
|
+
for (let i = 0; i < args.length; i++) {
|
|
72
|
+
const arg = args[i];
|
|
73
|
+
if (arg === "--workspace-root" && args[i + 1]) {
|
|
74
|
+
options.workspaceRoot = resolve(args[++i]);
|
|
75
|
+
} else if (arg === "--feed" && args[i + 1]) {
|
|
76
|
+
options.feedFile = resolve(args[++i]);
|
|
77
|
+
} else if (arg === "--adapter" && args[i + 1]) {
|
|
78
|
+
options.adapter = args[++i];
|
|
79
|
+
} else if (arg === "--session-id" && args[i + 1]) {
|
|
80
|
+
options.sessionId = args[++i];
|
|
81
|
+
} else if (arg === "--capture-mode" && args[i + 1]) {
|
|
82
|
+
options.captureMode = args[++i];
|
|
83
|
+
} else if (arg === "--label" && args[i + 1]) {
|
|
84
|
+
options.label = args[++i];
|
|
85
|
+
} else if (arg === "--notes" && args[i + 1]) {
|
|
86
|
+
options.notes = args[++i];
|
|
87
|
+
} else if (arg === "--run-id" && args[i + 1]) {
|
|
88
|
+
options.runId = args[++i];
|
|
89
|
+
} else if (arg === "--compare-run-id" && args[i + 1]) {
|
|
90
|
+
options.compareRunId = args[++i];
|
|
91
|
+
} else if (arg === "--agent-id" && args[i + 1]) {
|
|
92
|
+
options.agentId = args[++i];
|
|
93
|
+
} else if (arg === "--kind" && args[i + 1]) {
|
|
94
|
+
options.kind = args[++i];
|
|
95
|
+
} else if (arg === "--summary" && args[i + 1]) {
|
|
96
|
+
options.summary = args[++i];
|
|
97
|
+
} else if (arg === "--lane-id" && args[i + 1]) {
|
|
98
|
+
options.laneId = args[++i];
|
|
99
|
+
} else if (arg === "--branch-id" && args[i + 1]) {
|
|
100
|
+
options.branchId = args[++i];
|
|
101
|
+
} else if (arg === "--checkpoint-ref" && args[i + 1]) {
|
|
102
|
+
options.checkpointRef = args[++i];
|
|
103
|
+
} else if (arg === "--tool-ref" && args[i + 1]) {
|
|
104
|
+
options.toolRefs.push(args[++i]);
|
|
105
|
+
} else if (arg === "--evidence-ref" && args[i + 1]) {
|
|
106
|
+
options.evidenceRefs.push(args[++i]);
|
|
107
|
+
} else if (arg === "--id" && args[i + 1]) {
|
|
108
|
+
options.id = args[++i];
|
|
109
|
+
} else if (arg === "--title" && args[i + 1]) {
|
|
110
|
+
options.title = args[++i];
|
|
111
|
+
} else if (arg === "--status" && args[i + 1]) {
|
|
112
|
+
options.status = args[++i];
|
|
113
|
+
} else if (arg === "--from" && args[i + 1]) {
|
|
114
|
+
options.from = args[++i];
|
|
115
|
+
} else if (arg === "--to" && args[i + 1]) {
|
|
116
|
+
options.to = args[++i];
|
|
117
|
+
} else if (arg === "--note" && args[i + 1]) {
|
|
118
|
+
options.note = args[++i];
|
|
119
|
+
} else if (arg === "--actor" && args[i + 1]) {
|
|
120
|
+
options.actor = args[++i];
|
|
121
|
+
} else if (arg === "--task-type" && args[i + 1]) {
|
|
122
|
+
options.taskType = args[++i];
|
|
123
|
+
} else if (arg === "--priority" && args[i + 1]) {
|
|
124
|
+
options.priority = args[++i];
|
|
125
|
+
} else if (arg === "--source-file" && args[i + 1]) {
|
|
126
|
+
options.sourceFile = args[++i];
|
|
127
|
+
} else if (arg === "--category" && args[i + 1]) {
|
|
128
|
+
options.category = args[++i];
|
|
129
|
+
} else if (arg === "--tool" && args[i + 1]) {
|
|
130
|
+
options.tool = args[++i];
|
|
131
|
+
} else if (arg === "--artifact" && args[i + 1]) {
|
|
132
|
+
options.artifacts.push(args[++i]);
|
|
133
|
+
} else if (arg === "--metadata-json" && args[i + 1]) {
|
|
134
|
+
options.metadataJson = args[++i];
|
|
135
|
+
} else if (arg === "--event-type" && args[i + 1]) {
|
|
136
|
+
options.eventType = args[++i];
|
|
137
|
+
} else if (arg === "--source-module" && args[i + 1]) {
|
|
138
|
+
options.sourceModule = args[++i];
|
|
139
|
+
} else if (arg === "--trace-id" && args[i + 1]) {
|
|
140
|
+
options.traceId = args[++i];
|
|
141
|
+
} else if (arg === "--objective-id" && args[i + 1]) {
|
|
142
|
+
options.objectiveId = args[++i];
|
|
143
|
+
} else if (arg === "--decision-id" && args[i + 1]) {
|
|
144
|
+
options.decisionId = args[++i];
|
|
145
|
+
} else if (arg === "--payload-json" && args[i + 1]) {
|
|
146
|
+
options.payloadJson = args[++i];
|
|
147
|
+
} else if (arg === "--message" && args[i + 1]) {
|
|
148
|
+
options.message = args[++i];
|
|
149
|
+
} else if (arg === "--section" && args[i + 1]) {
|
|
150
|
+
options.section = args[++i];
|
|
151
|
+
} else if (arg === "--source-line" && args[i + 1]) {
|
|
152
|
+
options.sourceLine = Number(args[++i]);
|
|
153
|
+
} else if (arg === "--depends-on" && args[i + 1]) {
|
|
154
|
+
options.dependsOn.push(args[++i]);
|
|
155
|
+
} else if (arg === "--source-todo-path" && args[i + 1]) {
|
|
156
|
+
options.sourceTodoPath = args[++i];
|
|
157
|
+
} else if (arg === "--timestamp" && args[i + 1]) {
|
|
158
|
+
options.timestamp = args[++i];
|
|
159
|
+
} else if (arg === "--endpoint" && args[i + 1]) {
|
|
160
|
+
options.endpoint = args[++i];
|
|
161
|
+
} else if (arg === "--target" && args[i + 1]) {
|
|
162
|
+
options.target = args[++i];
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return { command, options };
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function parseOptionalJson(raw, label) {
|
|
169
|
+
if (!raw) return undefined;
|
|
170
|
+
try {
|
|
171
|
+
return JSON.parse(raw);
|
|
172
|
+
} catch (error) {
|
|
173
|
+
throw new Error(`Invalid ${label}: ${error instanceof Error ? error.message : String(error)}`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function buildProjectedState(workspaceRoot) {
|
|
178
|
+
return projectWorkspaceState(loadWorkspaceState(workspaceRoot));
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function printHelp() {
|
|
182
|
+
process.stdout.write(
|
|
183
|
+
[
|
|
184
|
+
"Vericify",
|
|
185
|
+
"",
|
|
186
|
+
`Default adapter: ${DEFAULT_ADAPTER}`,
|
|
187
|
+
"",
|
|
188
|
+
"Commands:",
|
|
189
|
+
" hub Launch the terminal hub (default)",
|
|
190
|
+
" adapters List available adapter contracts and current workspace status",
|
|
191
|
+
" attach Attach an adapter profile to this workspace",
|
|
192
|
+
" compare Print a structured comparison between two runs",
|
|
193
|
+
" publish Materialize a shareable run artifact under .vericify/published/",
|
|
194
|
+
" sync Queue a published run artifact into .vericify/sync-outbox/",
|
|
195
|
+
" handoff Upsert a native handoff into .vericify/handoffs.json",
|
|
196
|
+
" todo Upsert a native todo node into .vericify/todo-state.json",
|
|
197
|
+
" ledger Append a native run-ledger entry into .vericify/run-ledger.json",
|
|
198
|
+
" event Append a native status event into .vericify/status-events.ndjson",
|
|
199
|
+
" post Append a structured process post into .vericify/process-posts.json",
|
|
200
|
+
" snapshot Print the current projected run state as JSON",
|
|
201
|
+
" help Show this help",
|
|
202
|
+
"",
|
|
203
|
+
"Options:",
|
|
204
|
+
" --workspace-root <path> Read workspace input artifacts from the given root",
|
|
205
|
+
" --feed <path> Execute startup commands from a text file before returning control to keyboard",
|
|
206
|
+
" --adapter <id> Adapter id for adapters/attach commands",
|
|
207
|
+
" --session-id <id> Optional adapter session identifier",
|
|
208
|
+
" --capture-mode <mode> Adapter capture mode override",
|
|
209
|
+
" --label <text> Human label for attached adapter or publish title",
|
|
210
|
+
" --notes <text> Freeform note for attached adapter",
|
|
211
|
+
" --id <id> Handoff/todo record id",
|
|
212
|
+
" --title <text> Handoff/todo title",
|
|
213
|
+
" --status <value> Handoff/todo/event status",
|
|
214
|
+
" --from <id> Handoff sender",
|
|
215
|
+
" --to <id> Handoff recipient",
|
|
216
|
+
" --note <text> Handoff history note",
|
|
217
|
+
" --actor <id> Handoff history actor",
|
|
218
|
+
" --task-type <text> Handoff task type",
|
|
219
|
+
" --priority <text> Handoff/todo priority",
|
|
220
|
+
" --source-file <path> Handoff source file",
|
|
221
|
+
" --tool <id> Run-ledger tool id",
|
|
222
|
+
" --category <value> Run-ledger category",
|
|
223
|
+
" --message <text> Run-ledger message",
|
|
224
|
+
" --artifact <path> Run-ledger artifact ref, repeatable",
|
|
225
|
+
" --metadata-json <json> Run-ledger metadata object",
|
|
226
|
+
" --source-module <id> Status-event source module",
|
|
227
|
+
" --event-type <text> Status-event type",
|
|
228
|
+
" --trace-id <id> Status-event trace id",
|
|
229
|
+
" --objective-id <id> Status-event objective id",
|
|
230
|
+
" --decision-id <id> Status-event decision id",
|
|
231
|
+
" --payload-json <json> Status-event payload object",
|
|
232
|
+
" --section <text> Todo section",
|
|
233
|
+
" --source-line <n> Todo source line",
|
|
234
|
+
" --depends-on <id> Todo dependency id, repeatable",
|
|
235
|
+
" --source-todo-path <p> Todo source path",
|
|
236
|
+
" --timestamp <iso8601> Optional timestamp override",
|
|
237
|
+
" --run-id <id> Process-post target run id",
|
|
238
|
+
" --compare-run-id <id> Optional second run for compare/publish/sync",
|
|
239
|
+
" --agent-id <id> Process-post author",
|
|
240
|
+
" --kind <kind> Process-post kind: intent|progress|blocker|handoff_note|completion",
|
|
241
|
+
" --summary <text> Process-post summary",
|
|
242
|
+
" --lane-id <id> Optional process-post lane id",
|
|
243
|
+
" --branch-id <id> Optional process-post branch id",
|
|
244
|
+
" --checkpoint-ref <id> Optional process-post checkpoint ref",
|
|
245
|
+
" --tool-ref <id> Optional tool ref, repeatable",
|
|
246
|
+
" --evidence-ref <path> Optional evidence ref, repeatable",
|
|
247
|
+
" --endpoint <url> Optional hosted sync endpoint to record in the outbox item",
|
|
248
|
+
" --target <name> Sync target name, default vericify-cloud-v1",
|
|
249
|
+
"",
|
|
250
|
+
"Storage:",
|
|
251
|
+
" Vericify prefers .vericify/* and also reads partner agent-state/* when present",
|
|
252
|
+
" native writers mirror into partner agent-state/* when a partner ACE workspace is detected",
|
|
253
|
+
"",
|
|
254
|
+
"Keyboard:",
|
|
255
|
+
" q quit | j/k select | Enter inspect | c compare | y history | / command | r refresh | h hub | Ctrl+R history search",
|
|
256
|
+
"",
|
|
257
|
+
].join("\n")
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
async function printSnapshot(workspaceRoot) {
|
|
262
|
+
const projected = buildProjectedState(workspaceRoot);
|
|
263
|
+
process.stdout.write(`${JSON.stringify(projected, null, 2)}\n`);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
async function printAdapters(workspaceRoot) {
|
|
267
|
+
const adapters = detectAdapters(workspaceRoot);
|
|
268
|
+
process.stdout.write(`${JSON.stringify({ workspace_root: workspaceRoot, adapters }, null, 2)}\n`);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
async function writeAdapterAttachment(options) {
|
|
272
|
+
const result = attachAdapter(options.workspaceRoot, {
|
|
273
|
+
adapter_id: options.adapter,
|
|
274
|
+
session_id: options.sessionId,
|
|
275
|
+
capture_mode: options.captureMode,
|
|
276
|
+
label: options.label,
|
|
277
|
+
notes: options.notes,
|
|
278
|
+
});
|
|
279
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
async function printComparison(options) {
|
|
283
|
+
const projected = buildProjectedState(options.workspaceRoot);
|
|
284
|
+
const left = findRunById(projected, options.runId);
|
|
285
|
+
const right = findRunById(projected, options.compareRunId);
|
|
286
|
+
if (!left) throw new Error(`Unknown run id: ${options.runId}`);
|
|
287
|
+
if (!right) throw new Error(`Unknown compare run id: ${options.compareRunId}`);
|
|
288
|
+
const compare_report = buildRunComparison(left, right);
|
|
289
|
+
process.stdout.write(`${JSON.stringify({ generated_at: projected.generated_at, workspace: projected.workspace, compare_report }, null, 2)}\n`);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
async function writePublishedArtifact(options) {
|
|
293
|
+
const projected = buildProjectedState(options.workspaceRoot);
|
|
294
|
+
const result = publishRunArtifact({
|
|
295
|
+
workspaceRoot: options.workspaceRoot,
|
|
296
|
+
projected,
|
|
297
|
+
runId: options.runId,
|
|
298
|
+
compareRunId: options.compareRunId,
|
|
299
|
+
title: options.title ?? options.label,
|
|
300
|
+
});
|
|
301
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
async function queueSyncArtifact(options) {
|
|
305
|
+
const projected = buildProjectedState(options.workspaceRoot);
|
|
306
|
+
const published = publishRunArtifact({
|
|
307
|
+
workspaceRoot: options.workspaceRoot,
|
|
308
|
+
projected,
|
|
309
|
+
runId: options.runId,
|
|
310
|
+
compareRunId: options.compareRunId,
|
|
311
|
+
title: options.title ?? options.label,
|
|
312
|
+
});
|
|
313
|
+
const sync = enqueueSyncOutboxItem({
|
|
314
|
+
workspaceRoot: options.workspaceRoot,
|
|
315
|
+
artifact: published.artifact,
|
|
316
|
+
artifactPath: published.artifact_path,
|
|
317
|
+
endpoint: options.endpoint,
|
|
318
|
+
target: options.target,
|
|
319
|
+
});
|
|
320
|
+
process.stdout.write(`${JSON.stringify({ published, sync }, null, 2)}\n`);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
async function writeProcessPost(options) {
|
|
324
|
+
const result = appendProcessPost(options.workspaceRoot, {
|
|
325
|
+
run_id: options.runId,
|
|
326
|
+
branch_id: options.branchId,
|
|
327
|
+
lane_id: options.laneId,
|
|
328
|
+
agent_id: options.agentId,
|
|
329
|
+
kind: options.kind,
|
|
330
|
+
summary: options.summary,
|
|
331
|
+
tool_refs: options.toolRefs,
|
|
332
|
+
evidence_refs: options.evidenceRefs,
|
|
333
|
+
checkpoint_ref: options.checkpointRef,
|
|
334
|
+
});
|
|
335
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
async function writeHandoff(options) {
|
|
339
|
+
const result = upsertHandoff(options.workspaceRoot, {
|
|
340
|
+
handoff_id: options.id,
|
|
341
|
+
from: options.from,
|
|
342
|
+
to: options.to,
|
|
343
|
+
title: options.title,
|
|
344
|
+
status: options.status,
|
|
345
|
+
note: options.note,
|
|
346
|
+
actor: options.actor,
|
|
347
|
+
task_type: options.taskType,
|
|
348
|
+
priority: options.priority,
|
|
349
|
+
source_file: options.sourceFile,
|
|
350
|
+
agent_id: options.agentId,
|
|
351
|
+
timestamp: options.timestamp,
|
|
352
|
+
});
|
|
353
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
async function writeTodo(options) {
|
|
357
|
+
const result = upsertTodoNode(options.workspaceRoot, {
|
|
358
|
+
id: options.id,
|
|
359
|
+
title: options.title,
|
|
360
|
+
status: options.status,
|
|
361
|
+
section: options.section,
|
|
362
|
+
source_line: options.sourceLine,
|
|
363
|
+
depends_on: options.dependsOn,
|
|
364
|
+
priority: options.priority,
|
|
365
|
+
source_todo_path: options.sourceTodoPath,
|
|
366
|
+
});
|
|
367
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
async function writeLedgerEntry(options) {
|
|
371
|
+
const result = appendRunLedgerEntry(options.workspaceRoot, {
|
|
372
|
+
id: options.id,
|
|
373
|
+
timestamp_utc: options.timestamp,
|
|
374
|
+
tool: options.tool,
|
|
375
|
+
category: options.category,
|
|
376
|
+
message: options.message,
|
|
377
|
+
artifacts: options.artifacts,
|
|
378
|
+
metadata: parseOptionalJson(options.metadataJson, "metadata-json"),
|
|
379
|
+
});
|
|
380
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
async function writeStatusEvent(options) {
|
|
384
|
+
const result = appendStatusEvent(options.workspaceRoot, {
|
|
385
|
+
event_id: options.id,
|
|
386
|
+
trace_id: options.traceId,
|
|
387
|
+
timestamp: options.timestamp,
|
|
388
|
+
source_module: options.sourceModule,
|
|
389
|
+
event_type: options.eventType,
|
|
390
|
+
status: options.status,
|
|
391
|
+
objective_id: options.objectiveId,
|
|
392
|
+
decision_id: options.decisionId,
|
|
393
|
+
payload: parseOptionalJson(options.payloadJson, "payload-json"),
|
|
394
|
+
});
|
|
395
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
async function main() {
|
|
399
|
+
const { command, options } = parseArgs(process.argv);
|
|
400
|
+
if (command === "help" || command === "--help" || command === "-h") {
|
|
401
|
+
printHelp();
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
if (command === "adapters") {
|
|
405
|
+
await printAdapters(options.workspaceRoot);
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
if (command === "attach") {
|
|
409
|
+
await writeAdapterAttachment(options);
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
if (command === "snapshot") {
|
|
413
|
+
await printSnapshot(options.workspaceRoot);
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
if (command === "compare") {
|
|
417
|
+
await printComparison(options);
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
if (command === "publish") {
|
|
421
|
+
await writePublishedArtifact(options);
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
if (command === "sync") {
|
|
425
|
+
await queueSyncArtifact(options);
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
if (command === "post") {
|
|
429
|
+
await writeProcessPost(options);
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
if (command === "handoff") {
|
|
433
|
+
await writeHandoff(options);
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
if (command === "todo") {
|
|
437
|
+
await writeTodo(options);
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
if (command === "ledger") {
|
|
441
|
+
await writeLedgerEntry(options);
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
if (command === "event") {
|
|
445
|
+
await writeStatusEvent(options);
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
if (command === "hub") {
|
|
449
|
+
await runHub({
|
|
450
|
+
workspaceRoot: options.workspaceRoot,
|
|
451
|
+
feedFile: options.feedFile,
|
|
452
|
+
loadState: () => projectWorkspaceState(loadWorkspaceState(options.workspaceRoot)),
|
|
453
|
+
watchedPaths: listDefaultWorkspacePaths(options.workspaceRoot),
|
|
454
|
+
});
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
process.stderr.write(`Unknown command: ${command}\n`);
|
|
458
|
+
process.exitCode = 1;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
main().catch((err) => {
|
|
462
|
+
process.stderr.write(`${err instanceof Error ? err.stack ?? err.message : String(err)}\n`);
|
|
463
|
+
process.exitCode = 1;
|
|
464
|
+
});
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { readJson, writeJson } from "../core/fs.js";
|
|
3
|
+
import { asArray, hashText, isoNow, slugify } from "../core/util.js";
|
|
4
|
+
import { resolveStoreLayout } from "../store/paths.js";
|
|
5
|
+
|
|
6
|
+
export function getProcessPostsPaths(workspaceRoot) {
|
|
7
|
+
const layout = resolveStoreLayout(workspaceRoot);
|
|
8
|
+
return {
|
|
9
|
+
primary: layout.vericify.processPosts,
|
|
10
|
+
mirrors: [layout.partner.processPosts],
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function normalizeProcessPost(post) {
|
|
15
|
+
const timestamp = post.timestamp ?? isoNow();
|
|
16
|
+
const summary = String(post.summary ?? "").trim();
|
|
17
|
+
const agentId = String(post.agent_id ?? "").trim();
|
|
18
|
+
const runId = String(post.run_id ?? "").trim();
|
|
19
|
+
const kind = String(post.kind ?? "").trim();
|
|
20
|
+
if (!runId) throw new Error("Process posts require --run-id.");
|
|
21
|
+
if (!agentId) throw new Error("Process posts require --agent-id.");
|
|
22
|
+
if (!kind) throw new Error("Process posts require --kind.");
|
|
23
|
+
if (!summary) throw new Error("Process posts require --summary.");
|
|
24
|
+
return {
|
|
25
|
+
process_post_id:
|
|
26
|
+
post.process_post_id ??
|
|
27
|
+
`pp-${slugify(`${agentId}-${kind}`) || "post"}-${hashText(`${runId}:${agentId}:${kind}:${summary}:${timestamp}`).slice(0, 10)}`,
|
|
28
|
+
run_id: runId,
|
|
29
|
+
branch_id: post.branch_id,
|
|
30
|
+
lane_id: post.lane_id,
|
|
31
|
+
agent_id: agentId,
|
|
32
|
+
kind,
|
|
33
|
+
summary,
|
|
34
|
+
tool_refs: asArray(post.tool_refs),
|
|
35
|
+
evidence_refs: asArray(post.evidence_refs),
|
|
36
|
+
checkpoint_ref: post.checkpoint_ref,
|
|
37
|
+
timestamp,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function appendProcessPost(workspaceRoot, input) {
|
|
42
|
+
const { primary, mirrors } = getProcessPostsPaths(workspaceRoot);
|
|
43
|
+
const path = primary;
|
|
44
|
+
const current = readJson(path, { version: 1, posts: [] });
|
|
45
|
+
const post = normalizeProcessPost(input);
|
|
46
|
+
const posts = [...(Array.isArray(current.posts) ? current.posts : []), post].sort((left, right) =>
|
|
47
|
+
String(left.timestamp).localeCompare(String(right.timestamp))
|
|
48
|
+
);
|
|
49
|
+
writeJson(path, {
|
|
50
|
+
version: current.version ?? 1,
|
|
51
|
+
updated_at: isoNow(),
|
|
52
|
+
posts,
|
|
53
|
+
});
|
|
54
|
+
const mirrored_paths = [];
|
|
55
|
+
for (const mirrorPath of mirrors) {
|
|
56
|
+
if (!existsSync(mirrorPath) && !existsSync(mirrorPath.replace(/\/process-posts\.json$/, ""))) continue;
|
|
57
|
+
const mirrorCurrent = readJson(mirrorPath, { version: 1, posts: [] });
|
|
58
|
+
const mirrorPosts = [...(Array.isArray(mirrorCurrent.posts) ? mirrorCurrent.posts : []), post]
|
|
59
|
+
.sort((left, right) => String(left.timestamp).localeCompare(String(right.timestamp)));
|
|
60
|
+
writeJson(mirrorPath, {
|
|
61
|
+
version: mirrorCurrent.version ?? 1,
|
|
62
|
+
updated_at: isoNow(),
|
|
63
|
+
posts: mirrorPosts,
|
|
64
|
+
});
|
|
65
|
+
mirrored_paths.push(mirrorPath);
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
path,
|
|
69
|
+
mirrored_paths,
|
|
70
|
+
post,
|
|
71
|
+
};
|
|
72
|
+
}
|