Skip to content

Populate execution-graph records from OpenCode parser (#93)#119

Merged
willwashburn merged 2 commits intomainfrom
feat/opencode-execution-graph-93
Apr 26, 2026
Merged

Populate execution-graph records from OpenCode parser (#93)#119
willwashburn merged 2 commits intomainfrom
feat/opencode-execution-graph-93

Conversation

@willwashburn
Copy link
Copy Markdown
Member

@willwashburn willwashburn commented Apr 26, 2026

Summary

  • parseOpencodeSession / parseOpencodeSessionIncremental now return relationships: SessionRelationshipRecord[] and toolResultEvents: ToolResultEventRecord[] alongside the existing turns / content / userTurns arrays. Mirrors what Execution graph substrate: SessionRelationshipRecord + ToolResultEventRecord (#42) #77 did for Claude.
  • Relationships: one root row per session, plus a subagent row when the session payload carries parentID (with relatedSessionId pointing at the parent session id). OpenCode session payloads don't expose a stable spawning callID / subagent_type / description on the child today, so the subagent row only carries what the source actually surfaces.
  • Tool-result events: one terminal-status ToolResultEventRecord per tool part with a resolved state.output. Status follows the same failure rules as the existing erroredCallIds set — state.status === 'error' OR metadata.exit !== 0 (bash-family) → errored + isError: true. contentLength / contentHash are computed from the stringified output; raw bytes are never stored. Per-toolUseId callIndex and per-pass monotonic eventIndex mirror the Claude convention.
  • Resumed incremental passes don't re-emit events for already-seen assistant messages (the existing seenMessageIds mechanism gates the loop); relationship rows re-emit each pass and the ledger writer's hash-based dedup is the source of truth.
  • packages/cli/src/ingest.ts (OpenCode path) wires the new arrays into appendRelationships / appendToolResultEvents, matching the Claude path.
  • Subagent.isSidechain continues to populate from parentID unchanged; existing TurnRecord / ContentRecord outputs are unchanged.

Test plan

  • pnpm run build — clean
  • pnpm run test:ts — 458 tests passing (+6 new)
  • New tests cover all acceptance bullets in packages/reader/src/opencode.test.ts:
    • exactly one root row for a non-subagent session
    • exactly one subagent row whose relatedSessionId matches parentID
    • root + subagent emitted even when the session has no assistants on disk
    • state.status: 'error'status: 'errored' + isError: true
    • metadata.exit !== 0 (bash) → status: 'errored' even when state.status === 'completed'
    • contentLength / contentHash populated for both string and structured outputs
    • resumed incremental passes don't re-emit tool-result events

Refs

Closes #93. Refs #42, #77.

Out of scope (per issue): harness-event-stream subscription (#63), workflow / agent-tag attribution (#63), consumer CLI surfaces, fork / continuation rows, OpenCode fidelity (#89).

Generated with Claude Code


Open in Devin Review

Closes the OpenCode arm of the gap that #77 closed for Claude.
`parseOpencodeSession` / `parseOpencodeSessionIncremental` now return
`relationships: SessionRelationshipRecord[]` and
`toolResultEvents: ToolResultEventRecord[]` alongside the existing arrays.

- One `root` row per session; one `subagent` row when the session payload
  carries `parentID`, with `relatedSessionId` pointing at the parent.
- One `ToolResultEventRecord` per tool part with a resolved `state.output`,
  status derived from `state.status === 'error'` (errored) or
  `metadata.exit !== 0` (errored, bash-family); `isError` set when either
  condition is true; `contentLength` / `contentHash` computed from the
  stringified output (no raw bytes stored).
- Per-`toolUseId` `callIndex` and per-pass monotonic `eventIndex` mirror
  the Claude convention.
- `Subagent.isSidechain` continues to populate from `parentID` unchanged.
- Resumed incremental passes don't re-emit events for already-seen
  assistant messages; relationship rows re-emit on every pass and the
  ledger writer dedups them by hash.
- Wired through `packages/cli/src/ingest.ts` (OpenCode path) into
  `appendRelationships` / `appendToolResultEvents`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 4 additional findings.

Open in Devin Review

…on-graph-93

# Conflicts:
#	packages/cli/CHANGELOG.md
#	packages/cli/src/ingest.ts
#	packages/reader/CHANGELOG.md
#	packages/reader/src/opencode.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OpenCode passive reader: populate SessionRelationshipRecord and ToolResultEventRecord

1 participant