@tangle-network/traces 0.11.0 → 0.11.2
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 +161 -13
- package/dist/{chunk-JCI5YXNT.js → chunk-UY3M7XUF.js} +2255 -709
- package/dist/cli.js +200 -21
- package/dist/index.d.ts +709 -9
- package/dist/index.js +53 -1
- package/docs/replay-verify.md +55 -0
- package/package.json +5 -3
- package/skills/inspect-agent-traces/SKILL.md +31 -2
package/dist/cli.js
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
appendAll,
|
|
7
7
|
buildPolicyEvidenceRecord,
|
|
8
8
|
buildSessionIndexFromRows,
|
|
9
|
+
cmdReplayVerify,
|
|
9
10
|
collectSessionSelection,
|
|
10
11
|
commandAnalyzer,
|
|
11
12
|
commandRedactor,
|
|
@@ -26,8 +27,10 @@ import {
|
|
|
26
27
|
parseSession,
|
|
27
28
|
parseSince,
|
|
28
29
|
planUpload,
|
|
30
|
+
readOtlpInput,
|
|
29
31
|
readSessionIndexFile,
|
|
30
32
|
renderInspectionReport,
|
|
33
|
+
renderValidation,
|
|
31
34
|
resolveAdapter,
|
|
32
35
|
resolveRunWatchTarget,
|
|
33
36
|
runTraceImprovement,
|
|
@@ -42,6 +45,7 @@ import {
|
|
|
42
45
|
streamSessions,
|
|
43
46
|
totalAgenticFailureMessage,
|
|
44
47
|
traceStreamEventsFromSpans,
|
|
48
|
+
validationExitCode,
|
|
45
49
|
watchRunTarget,
|
|
46
50
|
watchSessions,
|
|
47
51
|
writeInspectionReportFile,
|
|
@@ -49,7 +53,7 @@ import {
|
|
|
49
53
|
writePolicyEvidenceFile,
|
|
50
54
|
writeSessionIndexFile,
|
|
51
55
|
writeTraceEvidenceExportFile
|
|
52
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-UY3M7XUF.js";
|
|
53
57
|
|
|
54
58
|
// src/cli.ts
|
|
55
59
|
import { readFileSync } from "fs";
|
|
@@ -155,6 +159,9 @@ function parseArgs(argv) {
|
|
|
155
159
|
case "--otlp":
|
|
156
160
|
a.otlp = next();
|
|
157
161
|
break;
|
|
162
|
+
case "--otlp-out":
|
|
163
|
+
a.otlpOut = next();
|
|
164
|
+
break;
|
|
158
165
|
case "--llm":
|
|
159
166
|
a.llm = true;
|
|
160
167
|
break;
|
|
@@ -239,6 +246,30 @@ function parseArgs(argv) {
|
|
|
239
246
|
}
|
|
240
247
|
return a;
|
|
241
248
|
}
|
|
249
|
+
var OTLP_INPUT_COMMANDS = /* @__PURE__ */ new Set(["analyze", "investigate", "improve", "stream", "validate"]);
|
|
250
|
+
function migrateWritingOtlpFlag(args) {
|
|
251
|
+
if (args.otlp === void 0 || OTLP_INPUT_COMMANDS.has(args.command)) return args;
|
|
252
|
+
if (args.otlpOut !== void 0) {
|
|
253
|
+
throw new Error(
|
|
254
|
+
`${args.command} was given both --otlp and --otlp-out. --otlp is the deprecated spelling of --otlp-out on writing commands; pass only --otlp-out.`
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
console.error(
|
|
258
|
+
`warning: --otlp is deprecated on \`${args.command}\` and will be removed in 0.12. --otlp now READS OTLP-JSONL; use --otlp-out <path> to write the artifact. Treating it as --otlp-out for this run.`
|
|
259
|
+
);
|
|
260
|
+
return { ...args, otlpOut: args.otlp, otlp: void 0 };
|
|
261
|
+
}
|
|
262
|
+
function validateOtlpSelection(raw) {
|
|
263
|
+
const args = migrateWritingOtlpFlag(raw);
|
|
264
|
+
if (args.otlp === void 0) return args;
|
|
265
|
+
if (args.input) throw new Error("--otlp cannot be combined with an input file");
|
|
266
|
+
if (args.session) throw new Error("--otlp reads a file and cannot be combined with --session");
|
|
267
|
+
if (args.supervisorRunDir) throw new Error("--otlp cannot be combined with --supervisor-run-dir");
|
|
268
|
+
if (args.workflow || args.latestTurn) {
|
|
269
|
+
throw new Error("--workflow and --latest-turn expand harness sessions and cannot be combined with --otlp");
|
|
270
|
+
}
|
|
271
|
+
return args;
|
|
272
|
+
}
|
|
242
273
|
var CURRENT_SESSION_COMMANDS = /* @__PURE__ */ new Set([
|
|
243
274
|
"analyze",
|
|
244
275
|
"investigate",
|
|
@@ -457,7 +488,45 @@ function selectedSessionSource(ref, spans, sessionIdOverride) {
|
|
|
457
488
|
} : {}
|
|
458
489
|
};
|
|
459
490
|
}
|
|
491
|
+
async function collectOtlpSpans(path) {
|
|
492
|
+
const input = await readOtlpInput(path);
|
|
493
|
+
if (input.spans.length === 0) {
|
|
494
|
+
throw new Error(
|
|
495
|
+
`no analyzable spans in ${path} (${input.files.length} file(s), ${input.rows.length} row(s), ${input.issues.length} unusable). Run \`traces validate ${path}\` for the per-finding reason.`
|
|
496
|
+
);
|
|
497
|
+
}
|
|
498
|
+
const fileByTrace = /* @__PURE__ */ new Map();
|
|
499
|
+
for (const file of input.files) {
|
|
500
|
+
for (const traceId of file.traceIds) if (!fileByTrace.has(traceId)) fileByTrace.set(traceId, file.path);
|
|
501
|
+
}
|
|
502
|
+
const byTrace = /* @__PURE__ */ new Map();
|
|
503
|
+
for (const span of input.spans) {
|
|
504
|
+
const grouped = byTrace.get(span.trace_id) ?? [];
|
|
505
|
+
grouped.push(span);
|
|
506
|
+
byTrace.set(span.trace_id, grouped);
|
|
507
|
+
}
|
|
508
|
+
return {
|
|
509
|
+
spans: [...input.spans],
|
|
510
|
+
harness: "otlp",
|
|
511
|
+
cwds: [],
|
|
512
|
+
sources: [...byTrace].map(([traceId, spans]) => selectedSessionSource({
|
|
513
|
+
harness: "otlp",
|
|
514
|
+
sessionId: traceId,
|
|
515
|
+
path: fileByTrace.get(traceId) ?? path,
|
|
516
|
+
cwd: null,
|
|
517
|
+
mtimeMs: 0
|
|
518
|
+
}, spans, traceId)),
|
|
519
|
+
conformance: input.validation,
|
|
520
|
+
conformanceSubject: path,
|
|
521
|
+
conformanceFiles: input.files,
|
|
522
|
+
conformanceSkipped: input.skipped,
|
|
523
|
+
conformanceIssues: input.issues,
|
|
524
|
+
conformanceWithheld: input.withheld,
|
|
525
|
+
conformanceUnreadable: input.unreadable
|
|
526
|
+
};
|
|
527
|
+
}
|
|
460
528
|
async function collectSpans(args) {
|
|
529
|
+
if (args.otlp) return collectOtlpSpans(args.otlp);
|
|
461
530
|
if (args.input) {
|
|
462
531
|
if (args.workflow) throw new Error("--workflow reads discovered sessions and cannot be combined with an input file");
|
|
463
532
|
return collectImportedSpans(args);
|
|
@@ -481,11 +550,37 @@ async function collectSpans(args) {
|
|
|
481
550
|
...selection.workflow ? { workflow: selection.workflow } : {}
|
|
482
551
|
};
|
|
483
552
|
}
|
|
553
|
+
async function cmdValidate(args) {
|
|
554
|
+
const path = args.otlp ?? args.input;
|
|
555
|
+
if (!path) {
|
|
556
|
+
throw new Error("validate needs an OTLP-JSONL file or directory: `traces validate <file|dir>`");
|
|
557
|
+
}
|
|
558
|
+
const input = await readOtlpInput(path);
|
|
559
|
+
const report = renderValidation(input.validation, {
|
|
560
|
+
subject: path,
|
|
561
|
+
files: input.files,
|
|
562
|
+
skipped: input.skipped,
|
|
563
|
+
issues: input.issues,
|
|
564
|
+
withheld: input.withheld,
|
|
565
|
+
unreadable: input.unreadable,
|
|
566
|
+
spans: input.spans
|
|
567
|
+
});
|
|
568
|
+
const validation = input.validation;
|
|
569
|
+
if (args.out) {
|
|
570
|
+
await saveReport(args.out, report);
|
|
571
|
+
console.log(
|
|
572
|
+
`conformance report \u2192 ${args.out} (${validation.findings.length} finding(s), ${validation.capabilities.filter((capability) => capability.available).length}/${validation.capabilities.length} capabilities available)`
|
|
573
|
+
);
|
|
574
|
+
} else {
|
|
575
|
+
console.log(report);
|
|
576
|
+
}
|
|
577
|
+
process.exitCode = validationExitCode(validation);
|
|
578
|
+
}
|
|
484
579
|
async function cmdConvert(args) {
|
|
485
580
|
const { spans, workflow } = await collectSpans(args);
|
|
486
581
|
if (spans.length === 0) throw new Error("no spans found for the given selection");
|
|
487
582
|
warnIncompleteWorkflow(workflow);
|
|
488
|
-
const path = await writeOtlpFile(spans, args.
|
|
583
|
+
const path = await writeOtlpFile(spans, args.otlpOut);
|
|
489
584
|
console.log(`wrote ${spans.length} spans \u2192 ${path}`);
|
|
490
585
|
}
|
|
491
586
|
function workflowIssueText(issue) {
|
|
@@ -519,7 +614,7 @@ async function cmdEvidence(args) {
|
|
|
519
614
|
const rows = selection.rows.filter((row) => row.spans.length > 0);
|
|
520
615
|
if (rows.length === 0) throw new Error("no spans found for the given selection");
|
|
521
616
|
warnIncompleteWorkflow(selection.workflow);
|
|
522
|
-
const otlpPath = args.
|
|
617
|
+
const otlpPath = args.otlpOut ? await writeOtlpFile(rows.flatMap((row) => row.spans), args.otlpOut) : void 0;
|
|
523
618
|
const generatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
524
619
|
const records = await Promise.all(rows.map(
|
|
525
620
|
(row) => buildPolicyEvidenceRecord(row.ref, row.spans, {
|
|
@@ -578,7 +673,7 @@ async function cmdExport(args) {
|
|
|
578
673
|
if (!args.input) throw new Error("export needs an input file; run `traces export --help` for examples");
|
|
579
674
|
const format = traceEvidenceFormat(args.format);
|
|
580
675
|
const attributes = await loadExportAttributes(args);
|
|
581
|
-
const outPath = args.out ?? args.
|
|
676
|
+
const outPath = args.out ?? args.otlpOut;
|
|
582
677
|
if (outPath) {
|
|
583
678
|
const result2 = await writeTraceEvidenceExportFile(args.input, outPath, { format, attributes });
|
|
584
679
|
console.log(
|
|
@@ -780,8 +875,20 @@ async function cmdInvestigate(args) {
|
|
|
780
875
|
}
|
|
781
876
|
assertAgenticAnalystsRan(args, result.agenticPerAnalyst);
|
|
782
877
|
}
|
|
878
|
+
function conformanceOptions(collected) {
|
|
879
|
+
return {
|
|
880
|
+
...collected.conformance ? { conformance: collected.conformance } : {},
|
|
881
|
+
...collected.conformanceSubject ? { conformanceSubject: collected.conformanceSubject } : {},
|
|
882
|
+
...collected.conformanceFiles ? { conformanceFiles: collected.conformanceFiles } : {},
|
|
883
|
+
...collected.conformanceSkipped ? { conformanceSkipped: collected.conformanceSkipped } : {},
|
|
884
|
+
...collected.conformanceIssues ? { conformanceIssues: collected.conformanceIssues } : {},
|
|
885
|
+
...collected.conformanceWithheld ? { conformanceWithheld: collected.conformanceWithheld } : {},
|
|
886
|
+
...collected.conformanceUnreadable ? { conformanceUnreadable: collected.conformanceUnreadable } : {}
|
|
887
|
+
};
|
|
888
|
+
}
|
|
783
889
|
async function investigate(args, options = {}) {
|
|
784
|
-
const
|
|
890
|
+
const collected = await collectSpans(args);
|
|
891
|
+
const { spans, harness, cwds, sources, workflow } = collected;
|
|
785
892
|
if (spans.length === 0) throw new Error("no spans found for the given selection");
|
|
786
893
|
const config = args.config !== void 0 || options.loadDefaultConfig !== false ? await loadTracesConfig(args.config) : void 0;
|
|
787
894
|
const analystModel = args.model ?? process.env.TRACES_ANALYST_MODEL ?? DEFAULT_ANALYST_MODEL;
|
|
@@ -796,14 +903,16 @@ async function investigate(args, options = {}) {
|
|
|
796
903
|
engine,
|
|
797
904
|
model: args.llm ? analystModel : args.model,
|
|
798
905
|
budgetUsd: args.budget,
|
|
799
|
-
otlpOutPath: args.
|
|
906
|
+
otlpOutPath: args.otlpOut,
|
|
800
907
|
externalAnalyzers: externalAnalyzersFromArgs(args),
|
|
801
908
|
analyzerPrompt: args.analyzerPrompt,
|
|
802
|
-
log: analystLog
|
|
909
|
+
log: analystLog,
|
|
910
|
+
...conformanceOptions(collected)
|
|
803
911
|
}, config));
|
|
804
912
|
}
|
|
805
913
|
async function cmdImprove(args) {
|
|
806
|
-
const
|
|
914
|
+
const collected = await collectSpans(args);
|
|
915
|
+
const { spans, harness, cwds, sources, workflow } = collected;
|
|
807
916
|
if (spans.length === 0) throw new Error("no spans found for the given selection");
|
|
808
917
|
const config = await loadTracesConfig(args.config);
|
|
809
918
|
const analystModel = args.model ?? process.env.TRACES_ANALYST_MODEL ?? DEFAULT_ANALYST_MODEL;
|
|
@@ -819,10 +928,11 @@ async function cmdImprove(args) {
|
|
|
819
928
|
engine,
|
|
820
929
|
model: args.llm ? analystModel : args.model,
|
|
821
930
|
budgetUsd: args.budget,
|
|
822
|
-
otlpOutPath: args.
|
|
931
|
+
otlpOutPath: args.otlpOut,
|
|
823
932
|
externalAnalyzers: externalAnalyzersFromArgs(args),
|
|
824
933
|
analyzerPrompt: args.analyzerPrompt,
|
|
825
|
-
log: analystLog
|
|
934
|
+
log: analystLog,
|
|
935
|
+
...conformanceOptions(collected)
|
|
826
936
|
}, config),
|
|
827
937
|
outDir: args.dir ?? args.out
|
|
828
938
|
});
|
|
@@ -890,12 +1000,13 @@ async function streamExplicitSession(args, extraAnalysts) {
|
|
|
890
1000
|
async function cmdStream(args) {
|
|
891
1001
|
const config = await loadTracesConfig(args.config);
|
|
892
1002
|
const preset = streamPreset(args);
|
|
893
|
-
|
|
894
|
-
|
|
1003
|
+
const source = args.otlp ?? args.input;
|
|
1004
|
+
if (source) {
|
|
1005
|
+
const { spans, harness } = args.otlp ? await collectOtlpSpans(args.otlp) : await collectImportedSpans(args);
|
|
895
1006
|
const ref = {
|
|
896
1007
|
harness,
|
|
897
|
-
sessionId: basename(
|
|
898
|
-
path: resolve(
|
|
1008
|
+
sessionId: basename(source),
|
|
1009
|
+
path: resolve(source),
|
|
899
1010
|
cwd: args.cwd ?? null,
|
|
900
1011
|
mtimeMs: Date.now()
|
|
901
1012
|
};
|
|
@@ -1034,7 +1145,7 @@ Window: since ${new Date(sinceMs).toISOString()}
|
|
|
1034
1145
|
return;
|
|
1035
1146
|
}
|
|
1036
1147
|
if (args.dryRun) {
|
|
1037
|
-
const res2 = await executeUpload(plan, { dryRun: true, otlpOut: args.
|
|
1148
|
+
const res2 = await executeUpload(plan, { dryRun: true, otlpOut: args.otlpOut, stripContent: args.noContent, redactor });
|
|
1038
1149
|
console.log(`dry run: ${candidates.length - res2.skippedSessions} session(s), ${totalRedactions} redaction(s). Redacted OTLP -> ${res2.otlpPath}`);
|
|
1039
1150
|
console.log("No upload performed. Set TANGLE_INGEST_URL / TANGLE_INGEST_API_KEY / TANGLE_TENANT_ID and drop --dry-run to send.");
|
|
1040
1151
|
return;
|
|
@@ -1097,21 +1208,71 @@ The command validates every native step, rejects annotation leakage, writes
|
|
|
1097
1208
|
<traj_id>.otlp.jsonl files, and records input and output SHA-256 hashes in
|
|
1098
1209
|
codetracebench-import.json. The output directory must not already exist.`);
|
|
1099
1210
|
}
|
|
1211
|
+
function usageValidate() {
|
|
1212
|
+
console.log(`traces validate: report what a trace can and cannot answer
|
|
1213
|
+
|
|
1214
|
+
Usage:
|
|
1215
|
+
traces validate <file.jsonl|dir> [--out conformance.md]
|
|
1216
|
+
|
|
1217
|
+
Reads OTLP-JSONL and prints the conformance report from
|
|
1218
|
+
@tangle-network/agent-trace-contract:
|
|
1219
|
+
|
|
1220
|
+
- findings by severity, each naming the CONSEQUENCE of the defect and the
|
|
1221
|
+
capabilities it blocks
|
|
1222
|
+
- the capability table: token-accounting, cost-attribution, tool-usage,
|
|
1223
|
+
loop-convergence, tree-comparison, steering-chain, latency-analysis \u2014
|
|
1224
|
+
available or not, with the trace's own reason
|
|
1225
|
+
- rows that could not be read at all, with the line and the reason
|
|
1226
|
+
|
|
1227
|
+
A directory reads the OTLP files under it, recursively \u2014 only the otlp/
|
|
1228
|
+
subdirectory when the producer made one. A run directory's raw event, stream and
|
|
1229
|
+
SDK logs are also *.jsonl; they are listed with what they actually hold, not read
|
|
1230
|
+
as several hundred broken spans. Identical re-declarations of a span across
|
|
1231
|
+
per-shot files are counted as repeats, not defects; only a repeat with DIFFERENT
|
|
1232
|
+
content is an error.
|
|
1233
|
+
|
|
1234
|
+
Exit code:
|
|
1235
|
+
0 no error findings, and at least one capability available (warnings mean
|
|
1236
|
+
thinner analysis, not wrong analysis)
|
|
1237
|
+
1 an error finding, or nothing analysable at all \u2014 an empty file, or one
|
|
1238
|
+
whose every line was unreadable, answers no question and is not a pass
|
|
1239
|
+
|
|
1240
|
+
Nothing is fixed up: a span with an unreadable timestamp is reported, never
|
|
1241
|
+
repaired, because a synthesized value puts invented work into a total.
|
|
1242
|
+
|
|
1243
|
+
Examples:
|
|
1244
|
+
traces validate spans.otlp.jsonl
|
|
1245
|
+
traces validate results/sessions --out conformance.md
|
|
1246
|
+
traces validate spans.otlp.jsonl && traces analyze --otlp spans.otlp.jsonl`);
|
|
1247
|
+
}
|
|
1100
1248
|
function usage() {
|
|
1101
|
-
console.log(`traces: analyze
|
|
1249
|
+
console.log(`traces: analyze agent traces \u2014 yours, or any system's
|
|
1250
|
+
|
|
1251
|
+
Two ways in:
|
|
1252
|
+
--otlp <file|dir> Spans a system already emitted in the
|
|
1253
|
+
@tangle-network/agent-trace-contract shape. No adapter, no
|
|
1254
|
+
translation. This is how you integrate a NEW system.
|
|
1255
|
+
--harness <id> Run an adapter over a coding agent's proprietary session
|
|
1256
|
+
store (Claude Code, Codex, OpenCode, \u2026) \u2014 the legacy edge,
|
|
1257
|
+
for formats we do not control.
|
|
1102
1258
|
|
|
1103
1259
|
Commands:
|
|
1260
|
+
validate Report what a trace can and cannot answer (exit 1 on error findings)
|
|
1104
1261
|
list List discovered sessions
|
|
1105
|
-
analyze Run analyst suite + loop/waste pipelines over
|
|
1262
|
+
analyze Run analyst suite + loop/waste pipelines over OTLP (--otlp), sessions,
|
|
1263
|
+
or an input file; names every analysis the spans could not support
|
|
1106
1264
|
(--supervisor-run-dir <dir> reports a supervision tree instead)
|
|
1107
1265
|
investigate Run typed investigation flow, including BYO config + evidence-backed actions
|
|
1108
1266
|
improve Write findings, evidence, report, and canonical trace artifacts
|
|
1109
|
-
convert Emit OTLP-JSONL only (HALO: use analyze --analyzer halo)
|
|
1267
|
+
convert Emit OTLP-JSONL only, to --otlp-out (HALO: use analyze --analyzer halo)
|
|
1110
1268
|
index Emit a reusable session index JSON for later investigation
|
|
1111
1269
|
inspect Read a session index and print ranked improvement findings
|
|
1112
1270
|
export Convert evidence/events files to OpenInference JSONL for HALO
|
|
1113
1271
|
import-codetracebench
|
|
1114
1272
|
Convert CodeTracer-normalized CodeTraceBench trajectories in bulk
|
|
1273
|
+
replay-verify
|
|
1274
|
+
Replay a trajectory prefix in a sandbox, execute step k both recorded
|
|
1275
|
+
and corrected, and emit an executed-proof verdict (--help for flags)
|
|
1115
1276
|
evidence Emit compact session-evidence JSONL for downstream policy miners
|
|
1116
1277
|
stream Emit JSONL trace stream events for live visualizers or replay
|
|
1117
1278
|
watch Online observer: tail active sessions, notify on loops + semantic findings
|
|
@@ -1138,7 +1299,15 @@ Options:
|
|
|
1138
1299
|
--since <t> upload: window, 30m / 2h / 7d or an ISO date (default 24h); analyze: ISO cutoff
|
|
1139
1300
|
--out <path> Write report to a file
|
|
1140
1301
|
--dir <path> improve: write artifacts to this directory
|
|
1141
|
-
--otlp <
|
|
1302
|
+
--otlp <file|dir> READ OTLP-JSONL emitted by any system, skipping the adapters.
|
|
1303
|
+
A directory reads the OTLP files under it \u2014 only the otlp/
|
|
1304
|
+
subdirectory when the producer made one \u2014 and names the JSONL
|
|
1305
|
+
that is not OTLP instead of reading it as broken spans.
|
|
1306
|
+
Supported by: validate, analyze, investigate, improve, stream.
|
|
1307
|
+
On a WRITING command it is the deprecated spelling of
|
|
1308
|
+
--otlp-out; it still works, with a warning, until 0.12.
|
|
1309
|
+
--otlp-out <path> WRITE the OTLP-JSONL artifact here (also evidence
|
|
1310
|
+
provenance / dry-run upload preview)
|
|
1142
1311
|
--format <kind> analyze/export: auto | policy-evidence | sandbox-events | openinference | intelligence-spans | chat-trajectory
|
|
1143
1312
|
--metadata <json> analyze/export file: attach JSON object fields as span attributes
|
|
1144
1313
|
--attr <k=v> analyze/export file: attach one span attribute (repeatable)
|
|
@@ -1166,7 +1335,8 @@ Options:
|
|
|
1166
1335
|
--redactor <cmd> upload: external PII scrubber (JSON array stdin\u2192stdout) after the regex pass
|
|
1167
1336
|
--yes, -y upload: skip the confirmation prompt
|
|
1168
1337
|
--version, -v Print the installed traces version
|
|
1169
|
-
--help, -h Show help (use \`traces
|
|
1338
|
+
--help, -h Show help (use \`traces validate --help\`, \`traces export --help\`,
|
|
1339
|
+
or \`traces import-codetracebench --help\`)
|
|
1170
1340
|
|
|
1171
1341
|
Watch a run tree (any depth; driver spend and child spend stay separate,
|
|
1172
1342
|
and a cost the harness never priced reads "unknown", never $0):
|
|
@@ -1183,18 +1353,24 @@ async function main() {
|
|
|
1183
1353
|
console.log(`traces ${packageVersion()}`);
|
|
1184
1354
|
return;
|
|
1185
1355
|
}
|
|
1356
|
+
if (rawArgs[0] === "replay-verify") {
|
|
1357
|
+
await cmdReplayVerify(rawArgs.slice(1));
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1186
1360
|
const parsedArgs = parseArgs(rawArgs);
|
|
1187
1361
|
if (parsedArgs.help) {
|
|
1188
1362
|
if (parsedArgs.command === "import-codetracebench" || parsedArgs.command === "help" && parsedArgs.input === "import-codetracebench") usageImportCodeTraceBench();
|
|
1189
1363
|
else if (parsedArgs.command === "export" || parsedArgs.command === "help" && parsedArgs.input === "export") usageExport();
|
|
1364
|
+
else if (parsedArgs.command === "validate" || parsedArgs.command === "help" && parsedArgs.input === "validate") usageValidate();
|
|
1190
1365
|
else usage();
|
|
1191
1366
|
return;
|
|
1192
1367
|
}
|
|
1193
|
-
const args = validateWorkflowSelection(applyCurrentSessionSelection(parsedArgs));
|
|
1368
|
+
const args = validateOtlpSelection(validateWorkflowSelection(applyCurrentSessionSelection(parsedArgs)));
|
|
1194
1369
|
switch (args.command) {
|
|
1195
1370
|
case "help":
|
|
1196
1371
|
if (args.input === "import-codetracebench") usageImportCodeTraceBench();
|
|
1197
1372
|
else if (args.input === "export") usageExport();
|
|
1373
|
+
else if (args.input === "validate") usageValidate();
|
|
1198
1374
|
else usage();
|
|
1199
1375
|
break;
|
|
1200
1376
|
case "list":
|
|
@@ -1203,6 +1379,9 @@ async function main() {
|
|
|
1203
1379
|
case "analyze":
|
|
1204
1380
|
await cmdAnalyze(args);
|
|
1205
1381
|
break;
|
|
1382
|
+
case "validate":
|
|
1383
|
+
await cmdValidate(args);
|
|
1384
|
+
break;
|
|
1206
1385
|
case "investigate":
|
|
1207
1386
|
await cmdInvestigate(args);
|
|
1208
1387
|
break;
|