Skip to content

traces export writes finding.json but manifest.json doesn't list it — the bundle's own index is wrong #56

Description

@dark-sorceror

Summary

Exporting a flagged trace writes five files and announces all five — Wrote 5 files: trace.json, spans.json, git_context.json, manifest.json, finding.json on stderr, and --json lists the same five — but manifest.json's files array lists only the four core files. The manifest is the bundle's self-describing index (ExportManifest, src/api/generated/schema.ts:279-291), so the bundle ships metadata that contradicts its own contents: anything iterating manifest.files silently skips the finding — the most important file in a flagged trace's bundle.

Applies to the finding-export logic introduced on feat/cli-traces-finding (src/commands/traces/export.ts); worth fixing on that branch before it merges.

How to replicate

  1. traceroot traces export <flagged-trace-id> --output ./bundle (a trace with a detector finding).
  2. stderr: Wrote 5 files: … finding.json plus the flagged-finding callout; finding.json exists on disk.
  3. jq '.files' ./bundle/manifest.json["trace.json", "spans.json", "git_context.json", "manifest.json"] — four entries, no finding.json.
  4. With --json, the CLI's own summary lists 5 files, disagreeing with the manifest it just wrote.
  5. Control: export a trace without a finding — the manifest matches the bundle exactly.

Root cause (confirmed)

In src/commands/traces/export.ts (finding-export branch):

  1. The server-provided manifest is written verbatim ("manifest.json": response.manifest); the server has no knowledge of the finding, which the CLI fetches separately.
  2. The CLI then appends finding.json to its local files array and writes the finding — but never patches the already-written manifest.json.
  3. The console line and the --json summary use the patched local array, so every CLI-side report says 5 while the on-disk index says 4.

Note the --force re-export path correctly cleans up a stale finding.json, but the write path never adds it to the manifest.

Impact

  • The export bundle's whole value is being a self-contained, self-describing evidence folder. A consumer that does the correct thing — read manifest.json, iterate files — never sees the finding.
  • Bundle validators keyed on the manifest will either drop finding.json or flag it as an untracked stray file.
  • Three sources of truth (stderr, --json, manifest.json) disagree about the same bundle.

Acceptance criteria

  • For a flagged trace, manifest.json's files includes finding.json; manifest, stderr summary, and --json files are identical.
  • For an unflagged trace, the manifest is unchanged — including after a --force re-export over a previously flagged directory (stale finding.json removed and absent from the manifest).
  • If patched client-side, only files is touched; bundle_version, project_id, trace_id pass through byte-identical.
  • Tests cover: flagged export (5 listed), unflagged (4), and --force flagged→unflagged over the same directory.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions