@tangle-network/traces 0.23.1 → 1.0.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.
Files changed (74) hide show
  1. package/README.md +61 -1078
  2. package/dist/analyst-model-call-JVUOYZ5V.js +20 -0
  3. package/dist/ask-XLS3VANY.js +39 -0
  4. package/dist/check-YF6ZHPGG.js +322 -0
  5. package/dist/chunk-3I4PJ5Q7.js +25 -0
  6. package/dist/chunk-3T62R7ON.js +5695 -0
  7. package/dist/chunk-4VKPN432.js +138 -0
  8. package/dist/chunk-6CLC7DKP.js +492 -0
  9. package/dist/chunk-7CBV5RJ2.js +535 -0
  10. package/dist/chunk-B62DOFGI.js +273 -0
  11. package/dist/chunk-CL3OQOWX.js +407 -0
  12. package/dist/chunk-DLGAKCQJ.js +782 -0
  13. package/dist/chunk-DU534HAX.js +263 -0
  14. package/dist/chunk-GLUDGUGJ.js +232 -0
  15. package/dist/chunk-J2PM5SVN.js +503 -0
  16. package/dist/chunk-M3W6TZHQ.js +381 -0
  17. package/dist/chunk-NH7HCDLB.js +759 -0
  18. package/dist/chunk-NZ5Y7UEL.js +1217 -0
  19. package/dist/chunk-O52XK7OB.js +19 -0
  20. package/dist/chunk-PYH3PL3N.js +62 -0
  21. package/dist/chunk-RZL5GAWH.js +60 -0
  22. package/dist/chunk-TR6O4S4T.js +208 -0
  23. package/dist/chunk-TW43MR5D.js +259 -0
  24. package/dist/chunk-TYLFUX42.js +228 -0
  25. package/dist/chunk-UOLRCQHC.js +120 -0
  26. package/dist/chunk-UVE5ANVV.js +3921 -0
  27. package/dist/chunk-V2OCGX57.js +53 -0
  28. package/dist/cli.js +2086 -2050
  29. package/dist/diff-ZZ6KYBPP.js +16 -0
  30. package/dist/improvement-OJQ6365E.js +25 -0
  31. package/dist/index.d.ts +1235 -4357
  32. package/dist/index.js +53 -1204
  33. package/dist/live-Y64AJ6MA.js +14 -0
  34. package/dist/mcp-ZPGTJQYQ.js +85 -0
  35. package/dist/report-JAMXRTCW.js +338 -0
  36. package/dist/run-watch-PLWTIRSV.js +649 -0
  37. package/dist/supervisor-report-RMPLLBGZ.js +29 -0
  38. package/dist/supervisor-run-context-WO6VOTGV.js +30 -0
  39. package/dist/upload-R6NMKSGQ.js +20 -0
  40. package/dist/verify-safe-C5ZXZOZ2.js +8 -0
  41. package/docs/analyze.md +76 -0
  42. package/docs/ask.md +88 -0
  43. package/docs/bundle.md +40 -0
  44. package/docs/check.md +77 -0
  45. package/docs/convert.md +44 -0
  46. package/docs/develop.md +32 -0
  47. package/docs/diff.md +38 -0
  48. package/docs/facts.md +114 -0
  49. package/docs/mcp.md +36 -0
  50. package/docs/migrate-1.0.md +33 -0
  51. package/docs/parsers.md +66 -0
  52. package/docs/release-1.0.0.md +147 -0
  53. package/docs/sdk.md +77 -0
  54. package/docs/select.md +70 -0
  55. package/docs/skills.md +46 -0
  56. package/docs/upload.md +47 -0
  57. package/docs/watch-jsonl.v1.example.jsonl +5 -0
  58. package/docs/watch.md +66 -0
  59. package/examples/README.md +9 -0
  60. package/examples/custom-analyst.ts +65 -74
  61. package/install.sh +22 -2
  62. package/package.json +8 -7
  63. package/skills/inspect-agent-traces/SKILL.md +47 -110
  64. package/dist/chunk-7DVZCCZI.js +0 -20983
  65. package/docs/replay-verify.md +0 -123
  66. package/docs/stream-findings.svg +0 -39
  67. package/docs/trace-analysts.md +0 -643
  68. package/examples/custom-backend.ts +0 -21
  69. package/examples/external-engines.ts +0 -62
  70. package/examples/improvement-config.mjs +0 -63
  71. package/examples/observe-and-alert.ts +0 -19
  72. package/examples/register-harness.ts +0 -26
  73. package/skills/build-trace-analyst/SKILL.md +0 -76
  74. package/skills/build-trace-analyst/agents/openai.yaml +0 -4
@@ -4,17 +4,20 @@
4
4
  *
5
5
  * pnpm tsx examples/custom-analyst.ts
6
6
  * pnpm tsx examples/custom-analyst.ts --fixture
7
+ *
8
+ * Each name comes from its owner: the analyst contract from agent-eval, the
9
+ * span builders from agent-trace-contract, and reading and analysis from
10
+ * traces. The fixture is what a producer you control would emit: contract
11
+ * spans, written as OTLP-JSONL and read back the way `traces analyze <file>`
12
+ * reads them.
7
13
  */
8
- import {
9
- AnalystRegistry,
10
- type Analyst,
11
- analyzeSpans,
12
- collectSessions,
13
- makeFinding,
14
- type OtlpSpan,
15
- span,
16
- type TraceAnalysisStore,
17
- } from '@tangle-network/traces'
14
+ import { mkdtemp, rm, writeFile } from 'node:fs/promises'
15
+ import { tmpdir } from 'node:os'
16
+ import { join } from 'node:path'
17
+ import { type Analyst, AnalystRegistry, makeFinding } from '@tangle-network/agent-eval/analyst'
18
+ import type { TraceAnalysisStore } from '@tangle-network/agent-eval/traces'
19
+ import { type ContractSpan, contractSpan, toolSpan } from '@tangle-network/agent-trace-contract'
20
+ import { analyzeSpans, type OtlpSpan, readOtlpInput, scanSessions } from '@tangle-network/traces'
18
21
 
19
22
  export const failedToolAnalyst: Analyst<TraceAnalysisStore> = {
20
23
  id: 'failed-tool-clusters',
@@ -56,116 +59,104 @@ export const failedToolAnalyst: Analyst<TraceAnalysisStore> = {
56
59
  },
57
60
  }
58
61
 
59
- export function knownBadSpans(): OtlpSpan[] {
62
+ const service = { 'service.name': 'example' }
63
+
64
+ export function knownBadSpans(): ContractSpan[] {
65
+ const traceId = 'fixture-three-failures'
60
66
  const root = 'fixture-root'
61
67
  return [
62
- span({
63
- traceId: 'fixture-three-failures',
64
- spanId: root,
65
- name: 'session',
66
- kind: 'AGENT',
67
- startTime: '2026-01-01T00:00:00.000Z',
68
- service: 'example',
69
- }),
68
+ contractSpan({ traceId, spanId: root, name: 'session', kind: 'AGENT', startTime: '2026-01-01T00:00:00.000Z', attributes: service }),
70
69
  ...[1, 2, 3].map((attempt) =>
71
- span({
72
- traceId: 'fixture-three-failures',
70
+ toolSpan({
71
+ traceId,
73
72
  spanId: `failed-${attempt}`,
74
73
  parentSpanId: root,
75
74
  name: 'tool.exec',
76
- kind: 'TOOL',
75
+ toolName: 'exec',
77
76
  startTime: `2026-01-01T00:00:0${attempt}.000Z`,
78
77
  endTime: `2026-01-01T00:00:0${attempt}.100Z`,
79
- status: 'ERROR',
80
- statusMessage: `Command failed with exit code 127 on attempt ${attempt}`,
81
- service: 'example',
82
- tool: 'exec',
83
- step: attempt,
84
- extra: { 'input.value': JSON.stringify({ command: 'missing-command' }) },
78
+ status: { code: 'STATUS_CODE_ERROR', message: `Command failed with exit code 127 on attempt ${attempt}` },
79
+ attributes: { ...service, 'input.value': JSON.stringify({ command: 'missing-command' }) },
85
80
  }),
86
81
  ),
87
- span({
88
- traceId: 'fixture-three-failures',
82
+ contractSpan({
83
+ traceId,
89
84
  spanId: 'unsupported-claim',
90
85
  parentSpanId: root,
91
86
  name: 'message.assistant',
92
87
  kind: 'CHAIN',
93
88
  startTime: '2026-01-01T00:00:04.000Z',
94
- service: 'example',
95
- step: 4,
96
- content: 'Implemented successfully. Everything works.',
89
+ attributes: { ...service, content: 'Implemented successfully. Everything works.' },
97
90
  }),
98
91
  ]
99
92
  }
100
93
 
101
- export function knownGoodSpans(): OtlpSpan[] {
94
+ export function knownGoodSpans(): ContractSpan[] {
95
+ const traceId = 'fixture-verified-change'
102
96
  const root = 'fixture-root'
103
97
  return [
104
- span({
105
- traceId: 'fixture-verified-change',
106
- spanId: root,
107
- name: 'session',
108
- kind: 'AGENT',
109
- startTime: '2026-01-01T00:00:00.000Z',
110
- service: 'example',
111
- }),
112
- span({
113
- traceId: 'fixture-verified-change',
98
+ contractSpan({ traceId, spanId: root, name: 'session', kind: 'AGENT', startTime: '2026-01-01T00:00:00.000Z', attributes: service }),
99
+ toolSpan({
100
+ traceId,
114
101
  spanId: 'edit-1',
115
102
  parentSpanId: root,
116
103
  name: 'tool.apply_patch',
117
- kind: 'TOOL',
104
+ toolName: 'apply_patch',
118
105
  startTime: '2026-01-01T00:00:01.000Z',
119
106
  endTime: '2026-01-01T00:00:01.100Z',
120
- service: 'example',
121
- tool: 'apply_patch',
122
- step: 1,
123
- extra: { 'input.value': 'change code' },
107
+ status: { code: 'STATUS_CODE_OK' },
108
+ attributes: { ...service, 'input.value': 'change code' },
124
109
  }),
125
- span({
126
- traceId: 'fixture-verified-change',
110
+ toolSpan({
111
+ traceId,
127
112
  spanId: 'verify-1',
128
113
  parentSpanId: root,
129
114
  name: 'tool.exec',
130
- kind: 'TOOL',
115
+ toolName: 'exec',
131
116
  startTime: '2026-01-01T00:00:02.000Z',
132
117
  endTime: '2026-01-01T00:00:02.100Z',
133
- service: 'example',
134
- tool: 'exec',
135
- step: 2,
136
- extra: {
137
- 'input.value': 'pnpm test',
138
- 'output.value': '12 tests passed',
139
- },
118
+ status: { code: 'STATUS_CODE_OK' },
119
+ attributes: { ...service, 'input.value': 'pnpm test', 'output.value': '12 tests passed' },
140
120
  }),
141
- span({
142
- traceId: 'fixture-verified-change',
121
+ contractSpan({
122
+ traceId,
143
123
  spanId: 'answer-1',
144
124
  parentSpanId: root,
145
125
  name: 'message.assistant',
146
126
  kind: 'CHAIN',
147
127
  startTime: '2026-01-01T00:00:03.000Z',
148
- service: 'example',
149
- step: 3,
150
- content: 'Implemented the change. pnpm test passed: 12/12.',
128
+ attributes: { ...service, content: 'Implemented the change. pnpm test passed: 12/12.' },
151
129
  }),
152
130
  ]
153
131
  }
154
132
 
133
+ /** Contract spans as traces reads them: written as OTLP-JSONL, then read back. */
134
+ async function readEmitted(spans: readonly ContractSpan[]): Promise<readonly OtlpSpan[]> {
135
+ const dir = await mkdtemp(join(tmpdir(), 'traces-custom-analyst-'))
136
+ try {
137
+ const path = join(dir, 'spans.otlp.jsonl')
138
+ await writeFile(path, `${spans.map((item) => JSON.stringify(item)).join('\n')}\n`, 'utf8')
139
+ return (await readOtlpInput(path)).spans
140
+ } finally {
141
+ await rm(dir, { recursive: true, force: true })
142
+ }
143
+ }
144
+
145
+ /** The most recent session of the first harness on this machine that has one. */
146
+ async function newestSession(): Promise<readonly OtlpSpan[]> {
147
+ for await (const session of scanSessions({ last: 1 })) return session.spans
148
+ throw new Error('no recent sessions found')
149
+ }
150
+
155
151
  async function main(): Promise<void> {
156
152
  const registry = new AnalystRegistry()
157
153
  registry.register(failedToolAnalyst)
158
154
 
159
- let spans: readonly OtlpSpan[]
160
- if (process.argv.includes('--fixture')) {
161
- spans = knownBadSpans()
162
- } else if (process.argv.includes('--good-fixture')) {
163
- spans = knownGoodSpans()
164
- } else {
165
- const [session] = await collectSessions({ all: true, last: 1, redact: false })
166
- if (!session) throw new Error('no recent sessions found')
167
- spans = session.spans
168
- }
155
+ const spans = process.argv.includes('--fixture')
156
+ ? await readEmitted(knownBadSpans())
157
+ : process.argv.includes('--good-fixture')
158
+ ? await readEmitted(knownGoodSpans())
159
+ : await newestSession()
169
160
 
170
161
  const { result } = await analyzeSpans(spans, { registry })
171
162
  console.log(JSON.stringify(result.findings, null, 2))
package/install.sh CHANGED
@@ -77,9 +77,29 @@ else
77
77
  fi
78
78
  fi
79
79
 
80
+ bin_dir="$install_prefix/bin"
81
+
82
+ # Never overwrite another program's `traces`: npm links ours into lib/node_modules/@tangle-network/traces.
83
+ existing="$bin_dir/traces"
84
+ if [ -e "$existing" ] || [ -L "$existing" ]; then
85
+ target="$(readlink "$existing" 2>/dev/null || true)"
86
+ case "$target" in
87
+ */lib/node_modules/@tangle-network/traces/*) ;;
88
+ *)
89
+ owner="${target:-a plain file, not the npm link to ${PACKAGE}}"
90
+ {
91
+ echo "$existing belongs to another program ($owner); traces will not overwrite it."
92
+ echo "Either remove that program and run this again (Homebrew's traces: brew uninstall market-dot-dev/tap/traces),"
93
+ echo "or install into another prefix and put its bin first on PATH, e.g. in ~/.zshenv:"
94
+ echo " ./install.sh --prefix \"\$HOME/.local\" then export PATH=\"\$HOME/.local/bin:\$PATH\""
95
+ } >&2
96
+ exit 1
97
+ ;;
98
+ esac
99
+ fi
100
+
80
101
  npm "${install_args[@]}"
81
102
 
82
- bin_dir="$install_prefix/bin"
83
103
  if [ -x "$bin_dir/traces" ]; then
84
104
  traces_cmd="$bin_dir/traces"
85
105
  elif command -v traces >/dev/null 2>&1; then
@@ -99,4 +119,4 @@ case ":$PATH:" in
99
119
  *":$bin_dir:"*) ;;
100
120
  *) echo "Add this to PATH for future shells: $bin_dir" ;;
101
121
  esac
102
- echo "Run: traces analyze --harness claude-code --last 1"
122
+ echo "Run: traces list --last 5"
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tangle-network/traces",
3
- "version": "0.23.1",
4
- "description": "Point it at your coding-agent session traces (Claude Code, Codex, OpenCode, Gemini, Pi, \u2026) and get failure-mode + efficiency findings. CLI + SDK over the @tangle-network/agent-eval analyst suite \u2014 observe live sessions, run your own analysts, redact, and upload to the Tangle Intelligence Platform.",
3
+ "version": "1.0.0",
4
+ "description": "What your coding agents did, where they wasted time, and whether a run passes: exact facts, ranked findings, one CI gate and a live view over Claude Code, Codex, OpenCode, Pi, Kimi and Factory sessions and any OTLP spans. CLI and SDK.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -50,7 +50,9 @@
50
50
  "scripts": {
51
51
  "dev": "tsx src/cli.ts",
52
52
  "bench:audit": "tsx bench/audit/cli.ts",
53
- "build": "tsup src/index.ts src/cli.ts --format esm --target node22 --clean --dts",
53
+ "bench:corrections": "tsx bench/corrections/score.ts",
54
+ "bench:parity": "tsx bench/parity/score.ts",
55
+ "build": "tsup",
54
56
  "check:package": "node scripts/check-package-bin.mjs",
55
57
  "check:source": "node scripts/check-source-text.mjs",
56
58
  "prepare": "node scripts/check-source-text.mjs",
@@ -61,12 +63,11 @@
61
63
  "prepublishOnly": "pnpm check:source && pnpm build && pnpm check:package"
62
64
  },
63
65
  "dependencies": {
64
- "@tangle-network/agent-eval": "0.213.0",
66
+ "@tangle-network/agent-eval": "0.221.3",
65
67
  "@tangle-network/agent-interface": "5.2.0",
66
68
  "@tangle-network/agent-runtime": "0.318.0",
67
- "@tangle-network/agent-trace-contract": "2.0.0",
68
- "@tangle-network/harness-sessions": "0.1.3",
69
- "@tangle-network/sandbox": "0.60.49"
69
+ "@tangle-network/agent-trace-contract": "2.1.0",
70
+ "@tangle-network/harness-sessions": "0.1.7"
70
71
  },
71
72
  "devDependencies": {
72
73
  "@types/node": "^22.20.4",
@@ -1,119 +1,56 @@
1
1
  ---
2
2
  name: inspect-agent-traces
3
- description: Inspect real agent workflows with the published Traces CLI and export cited local findings.
3
+ description: Use for any question about a Claude Code or Codex session, its session file, or a trace.
4
4
  ---
5
-
6
- # Inspect agent traces
7
-
8
- Use the deterministic CLI first; keep inspection local and read-only.
9
-
10
- ## Choose the way in
11
-
12
- Read conforming OTLP directly, including `@tangle-network/agent-trace-contract` exports.
13
-
14
- ```bash
15
- traces validate spans.otlp.jsonl # exit 1 on error findings
16
- traces analyze --otlp spans.otlp.jsonl --out .traces/current.md
17
- traces analyze --otlp results/sessions --out .traces/all.md # a directory of exports
18
- ```
19
-
20
- Use `--harness` for native coding-agent formats; integrate systems you own through OTLP.
21
-
22
- Directories read only OTLP files, preferring an `otlp/` subdirectory; other JSONL logs are listed separately.
23
-
24
- Report `Inputs incomplete` values as uncaptured, never zero spend.
25
- The `trace conformance` section lists missing capabilities.
26
-
27
- For loops, inspect `round-over-round convergence` and `steering chain` before judging progress.
28
-
29
- ## Select the workflow
30
-
31
- ```bash
32
- traces --version
33
- traces list --harness codex --cwd "$PWD"
34
- traces facts --harness codex --current --latest-turn --workflow \
35
- --format text --out .traces/current-facts.txt
36
- ```
37
-
38
- - Use `--current` for the active Codex session.
39
- - Use `--session <id-or-path>` to pin a listed session.
40
- - Use `--latest-turn` for the current task in a resumed Codex or Claude Code session.
41
- - Use `--workflow` to include workers linked by stable parent and child IDs.
42
- - Use `--max-workflow-sessions <n>` only when the default 100-file bound is too small.
43
- - For Claude Code, use `--harness claude-code --session <path> --latest-turn`; nested subagents are included.
44
-
45
- Never join agents by display name or timestamp when Traces reports missing or conflicting IDs.
46
- Read facts before full transcripts or analysis.
47
- Check parent and worker counts against the task being investigated.
48
- Run `analyze` only for questions the facts sheet cannot answer:
49
-
50
- ```bash
51
- traces analyze --harness codex --current --latest-turn --workflow \
52
- --out .traces/current.md
53
- ```
54
-
55
- For moved evidence, keep byte-identical transcripts and record their source paths and hashes.
56
- Preserve Claude's `<session UUID>/subagents/workflows/<run ID>` subtree beside the copied parent JSONL file.
57
- Restore missing child files from the source; rewriting recorded paths loses the original evidence.
58
- Check current branches, edits, commits, and PRs before reporting unfinished work; transcripts describe past actions.
59
-
60
- ## Export
61
-
62
- Write normalized OpenInference spans for another tool:
63
-
64
- ```bash
65
- traces convert --harness codex --current --latest-turn --workflow \
66
- --otlp-out .traces/current.otlp.jsonl
67
- ```
68
-
69
- Write the complete deterministic review packet:
70
-
71
- ```bash
72
- traces improve --harness codex --current --latest-turn --workflow \
73
- --dir .traces/improvement
74
- ```
75
-
76
- `improve` writes findings, evidence, a report, and spans.
77
- It edits no agent, repository, memory store, or knowledge base.
78
-
79
- Preserve a session for later inspection:
80
-
81
- ```bash
82
- traces bundle --harness claude-code --session <id-or-path> --out .traces/bundle
5
+ Run traces; never parse session stores yourself. Everything except `ask` is exact, local and $0.
6
+ A ref is a session id or 8+ char prefix, a session file, an OTLP file or dir, a run dir or a bundle dir.
7
+
8
+ ## Any question about one session
9
+ 1. Run `traces facts <ref>` first. Its sheet is at most 25 lines: harness, cwd, times and parent;
10
+ human turns; tools by name with failures; commands by program with failures and runs inside
11
+ Codex code-mode scripts; subagents, their types and tool calls; tokens; PRs; changed files;
12
+ first failure; final message.
13
+ When the sheet holds the answer, answer.
14
+ 2. For one field the sheet summarizes, print only that field:
15
+ `traces facts <ref> --format json | jq '<path>'` with a path below.
16
+ Never print the whole JSON: it is tens of KB of span ids.
17
+ 3. To list commands, typed turns or agent messages by text: `traces facts <ref> --match '<re>'`.
18
+ It prints the count first, then one line per hit, a command's with `ok`, `failed` or `?`,
19
+ and under it the record's `file:line` and its output's `last:` line; a program's run count is on the sheet.
20
+ 4. To quote or cite, use `record` on a turn, the first failure, a command row, a non-zero exit or a
21
+ changed file: cite `<recordFile>:<line>` (`.sessions[0].recordFile`; a subagent's record names its own `file`).
22
+ Never `find` or `grep` the store for it.
23
+
24
+ ```text
25
+ .sessions[0].firstFailure | {name, message, at, record} first failure, its output
26
+ .sessions[0].measurements.tools[] | {name, calls, failed: .outcomes.error} tool calls by name, failures
27
+ .sessions[0].commands.value[] | {command, runs, failed, inScripts, record} programs, latest run's record
28
+ .sessions[0].commands.value[].nonZeroExits[] | {code, inScript, at, record} each non-zero exit and its code
29
+ .sessions[0].pullRequests.value | {created: [.created[] | {number, at}], merged: [.merged[] | {number, at}]}
30
+ .sessions[0].humanTurns.value[] | {at, text, record, signals} typed turns, in order
31
+ .sessions[0] | {tokens, cost} tokens and cost
32
+ .sessions[0].subagents.value[] | {taskName, agentType, status} subagents spawned, refused ones ERROR
33
+ .sessions[0].changedFiles.value[] | {path, operations, record} files changed, the call that changed each
34
+ .sessions[0] | {first: .firstRecordAt.value, last: .lastRecordAt.value} first and last record
35
+ .sessions[0] | {parentSessionId, rel: .measurements.relationship} parent, agent path, own task start, children
83
36
  ```
84
37
 
85
- `bundle` copies transcripts, report, spans, and session-window `.evolve` rows with per-file SHA-256 hashes.
86
- It uses no model calls.
87
- Missing transcripts stop assembly; optional missing inputs appear in `manifest.absent`.
88
-
89
- ## Pick the view for the reader
90
-
91
- The full bundle includes transcripts containing prior reports, even when report files are removed.
92
- For a writer who must not see earlier conclusions, project an evidence-only copy:
93
-
94
- ```bash
95
- traces bundle-view .traces/bundle --view evidence-only --out .traces/writer
96
- ```
38
+ A count in a command's `failed` is a known non-zero exit; a run `inScripts` has no exit code of its own.
97
39
 
98
- This retains the session index, evidence JSONL, and structured ledger records.
99
- It excludes transcripts, reports, spans, prose ledgers, and files repeating an eight-word passage from excluded prose.
100
- Check `manifest.view` and the rules and hashes in `manifest.excluded`.
40
+ ## Other jobs
41
+ | Question | Command |
42
+ |---|---|
43
+ | This session, or the one that just ended here | `traces facts --current`, or `traces list --cwd . --last 5` |
44
+ | Where it churned, what failed, what it cost | `traces analyze <ref>` |
45
+ | Where two runs split | `traces diff <a> <b>` |
46
+ | Gate a PR or eval on the path a run took | `traces check <ref> --contract <file>` |
47
+ | Is this safe to share | `traces check <path> --share-safe` |
48
+ | Watch workers live | `traces watch <run-dir> --once` |
49
+ | A judgment question with checked citations ($) | `traces ask <ref> --question '<q>' --budget 1` |
50
+ | Keep a session's evidence before a move | `traces bundle <ref> --out <dir>` |
101
51
 
102
- ## Ask your own question
103
-
104
- `traces ask --last 1 --question "<text>" --budget 2 --dir .traces/ask` spends model calls and resolves answer citations.
105
-
106
- ## Report
107
-
108
- - State the source (`--otlp <path>` or the harness), selected task boundary, session and span counts, and integrity warnings.
109
- - Name missing capabilities and analyses affected by them.
110
- - Cite each finding with its exact `trace://` reference.
111
- - Mark missing outcome, cost, token, skill, or relationship data unknown.
112
- - Do not infer task success from a completion message.
113
- - Do not infer skill use from reading a `SKILL.md`.
114
- - Do not upload traces unless explicitly requested.
52
+ Report the ref, cite `record` as `file:line` (else span ids), and say "unknown" where traces returns null.
53
+ Do not infer success from a completion message. Upload only when asked.
115
54
 
116
55
  ## Then consider
117
-
118
- - Use `build-trace-analyst` when deterministic findings cannot answer a repeated trace question.
119
- - Use `autopsy` when the result is empty, surprising, or suspiciously strong.
56
+ A question you ask twice becomes a `--questions` bank file or a `check --contract`.