Skip to content

chore(from-transcript): graduate the #779 spike into a runnable fromTranscript helper with a live e2e - #824

Open
drewdrewthis wants to merge 1 commit into
mainfrom
issue779/transcript-to-scenario-helper
Open

chore(from-transcript): graduate the #779 spike into a runnable fromTranscript helper with a live e2e#824
drewdrewthis wants to merge 1 commit into
mainfrom
issue779/transcript-to-scenario-helper

Conversation

@drewdrewthis

@drewdrewthis drewdrewthis commented Jul 18, 2026

Copy link
Copy Markdown
Collaborator

Graduates the #779 spike (draft #789) into a working, tested fromTranscript helper that turns a real Claude Code session .jsonl into a runnable Scenario — proven end-to-end with a live scenario.run(...) (run id below), not a mock.

⚠ NOT for merge by an agent — the owner merges. Review-ready; please review, don't auto-merge.

What & why

When a real agent makes a real mistake, there was no path from "here is the session where it went wrong" to "here is a Scenario that reproduces it." This helper is that path for the Claude Code adapter (scope-locked to the native JSONL per the owner steer on #779; the from-traces Strategy C and full-sandbox Strategy D stay deferred in #779, out of scope here).

javascript/examples/vitest/from-transcript/:

  • cc-transcript.ts — reader/adapter: walks the parentUuid tree leaf→root (sidechain-aware, cycle-guarded), distinguishes a real user turn from a tool_result carried as role:user, re-merges an assistant message fragmented across thinking/text/tool_use lines, recovers each tool_result's tool name by pairing back to its tool_use, and emits AI-SDK v6 ModelMessage[] (with flattenTools for cross-model seeds).
  • from-transcript.tsfromTranscript(path, { forkAt }) → a SeededScenario whose seedStep bulk-seeds the captured history through the turn-free state.addMessage() side-door, so a seed of any length costs zero maxTurns budget (the [SPIKE] Create a runnable Scenario from a real agent transcript — Claude Code failure-replay as first use case #779 gotcha). SDK-free, so the reader stays unit-testable.
  • reader.test.ts (20 unit tests, no API) · proof.e2e.test.ts (live e2e, gated behind SC779_LIVE) · model.ts (provider selector: OpenAI default; SC779_PROVIDER=gemini for the run below).

Reuse-first: the existing run loop + message() injection + ScenarioExecutionState.addMessage are used as-is — no src/ / published-SDK change, so there is no structural SDK surface to declare as drift. (The spike's buildScenarioFromTranscript is renamed to fromTranscript to match the name #779 uses.)

How I can prove I was successful

Real transcript → runnable Scenario that ACTUALLY RAN (live models, not mocked). Full log committed at javascript/examples/vitest/from-transcript/evidence/e2e-run.log.

  • Run id: scenariobatch_3GgLkgfhAdLZMEmBI4kwGaeneKd
  • LangWatch run: https://app.langwatch.ai/voice-bugbash-nWygNc/simulations/779-from-transcript/scenariobatch_3GgLkgfhAdLZMEmBI4kwGaeneKd
  • Fixture: a PII-scrubbed real Claude Code session fixtures/real-cc-session.jsonl (the KUMQUAT77 memory-recall session; KUMQUAT77 is a synthetic test token that grants nothing).
  • Run shape (not just a verdict): the reader turned 53 parsed nodes → a 53-node parentUuid chain → 20 normalized turns (2 human / 2 injected / 7 tool / 9 assistant) → a 12-message seed; a real User-role turn ("What was the exact token…") sits at the fork; the live agent() then took the next turn and a judge() rendered a verdict. pnpm exec vitest: 3 passed (3) in ~36s. (The scripted path is seed → single live agent() turn → judge() — no user-simulator loop; Proof B proves the judge discriminates, so this is a real verdict, not a rubber-stamp, but not a multi-turn interactive conversation.)
  • Models: this run used gemini-2.5-flash for agent + judge (SC779_PROVIDER=gemini); the committed test defaults to OpenAI gpt-5-mini (the spike-validated path), env-switchable via model.ts.
DoD (from the lane brief) Evidence Status
Convert ONE real .jsonl end-to-end → runnable Scenario Proof A: 12-msg seed from the real fixture, live agent → "KUMQUAT77", judge success=true
The Scenario ACTUALLY RUNS (scenario.run), run id captured run id scenariobatch_3GgLkgfhAdLZMEmBI4kwGaeneKd + LangWatch URL above
The max_turns seed-budget gotcha handled DoD-4 contrast: naive message()×N + proceed()"Reached maximum turns (4)"; the side-door seed under the same budget → success=true
Fix-loop shown (verdict responds to the omitted config) Proof B: token scrubbed from the seed → BEFORE success=false (agent could not recall it), AFTER (memory reconstructed) success=true — verdict flips on nothing but the config the JSONL drops
Reader normalizations are load-bearing (not vacuous tests) reader.test.ts 20/20; mutation check — removing the parentUuid reverse turns 5 reader tests red, reverting → 20/20 green
Lint / typecheck clean eslint from-transcript/ exit 0, 0 eslint-disables; tsc --noEmit 0 errors in these files

No UI surface. Backend-only CLI/SDK helper; its observable output is the terminal run above (committed as evidence/e2e-run.log) + the LangWatch run. Nothing to screenshot.

Human verification

cd javascript && pnpm install && pnpm run build        # build the SDK → dist/
cd examples/vitest && pnpm install
pnpm exec vitest run from-transcript/reader.test.ts    # 20 unit tests — no API keys needed
# live e2e — gated behind SC779_LIVE (skipped by default):
printf 'OPENAI_API_KEY=sk-...\n' > .env
SC779_LIVE=1 pnpm exec vitest run from-transcript/proof.e2e.test.ts
#   or to reproduce this run exactly:  SC779_LIVE=1 SC779_PROVIDER=gemini GEMINI_API_KEY=... LANGWATCH_API_KEY=sk-lw-... pnpm exec vitest run …

Then point it at your own session: fromTranscript("~/.claude/projects/<slug>/<session>.jsonl", { forkAt: { beforeLastAssistant: true } }) and drop seedStep into scenario.run({ script: [seed.seedStep, scenario.agent(), scenario.judge({ criteria })] }). See from-transcript/README.md.

CI note

CI's Test (Examples) step is red for an environmental reason, not a defect in this PR. The shared OpenAI account is out of quota (insufficient_quota), so every live-OpenAI example fails right now — including pre-existing tests/voice/* and weather-agent, not just this PR; main's last green run predates the exhaustion. This PR's unit tests pass in CI (✓ from-transcript/reader.test.ts), and its live e2e is gated behind SC779_LIVE (skipped by default) so it does not add to the red — it is proven by the committed run receipt above.

Scope / notes

  • Scope-locked to the Claude Code JSONL path. Strategy C (from-traces) and Strategy D (sandbox) are deferred in [SPIKE] Create a runnable Scenario from a real agent transcript — Claude Code failure-replay as first use case #779.
  • Honest posture (README): the JSONL captures the conversation but not the agent's system prompt/config, so this is Strategy-A "artificial context injection" — strong enough to iterate on "does this change flip the behaviour" (Proof B does exactly that), deliberately weaker than bit-exact replay (the deferred Strategy D).
  • The committed fixture was PII-scrubbed after review found the raw session embedded a real MEMORY.md + infra details; structure, tool names, thinking, and the KUMQUAT77 flow are preserved, all sensitive bodies elided.

🤖 Generated with Claude Code

https://claude.ai/code/session_01PW4HxMfgLxY8dmGK4AimfG

@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Changes

Transcript replay and seeded scenario proofs

Layer / File(s) Summary
Transcript parsing and AI-SDK emission
javascript/examples/vitest/from-transcript/cc-transcript.ts
Parses Claude Code JSONL, follows the main thread, normalizes roles and tool relationships, and emits AI-SDK v6 messages.
Seeded Scenario construction
javascript/examples/vitest/from-transcript/from-transcript.ts
Builds forked seeded scenarios, supports filtering and tool-part pruning, and adds history through seedStep.
Transcript fixture and adapter validation
javascript/examples/vitest/from-transcript/fixtures/*, javascript/examples/vitest/from-transcript/reader.test.ts
Adds a real session fixture and tests parsing, normalization, emission, filtering, forking, and regression cases.
Live proof runner and provider routing
javascript/examples/vitest/from-transcript/model.ts, javascript/examples/vitest/from-transcript/proof.e2e.test.ts, javascript/examples/vitest/from-transcript/README.md
Adds provider selection, live seeded recall proofs, turn-budget comparisons, memory reconstruction checks, and usage documentation.

Sequence Diagram(s)

sequenceDiagram
  participant Proof
  participant fromTranscript
  participant Scenario
  participant LiveAgent
  participant Judge
  Proof->>fromTranscript: Load transcript and fork options
  fromTranscript->>Scenario: Create seeded scenario
  Scenario->>LiveAgent: Run with seeded history
  LiveAgent-->>Scenario: Return assistant response
  Scenario->>Judge: Evaluate recall criteria
  Judge-->>Proof: Return verdict
Loading

Possibly related issues

  • Issue 779: Implements the referenced Strategy B transcript reader, Scenario builder, turn-safe seeding, tests, and end-to-end proof.

Suggested labels: low-risk-change

Suggested reviewers: rogeriochaves, 0xdeafcafe, github-actions

Poem

A rabbit reads the transcript trail,
Rejoins each turn and tool-detail.
Seeds the path without delay,
Helps memory find its way.
“KUMQUAT77!” thumps tiny feet.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly names the main change: promoting the #779 spike into a runnable fromTranscript helper with live e2e coverage.
Description check ✅ Passed The description is directly about the same fromTranscript helper, tests, and live e2e scenario, so it is clearly relevant.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue779/transcript-to-scenario-helper

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🧹 Nitpick comments (2)
javascript/examples/vitest/from-transcript/reader.test.ts (1)

1-9: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document how this test suite is run.

Add the exact Vitest command, required dependencies, no-network behavior, and expected coverage scope.

As per coding guidelines, TypeScript tests must document running instructions, coverage requirements, dependencies, and examples.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@javascript/examples/vitest/from-transcript/reader.test.ts` around lines 1 -
9, Document the execution contract for the transcript reader tests in the test
file’s header: include the exact Vitest command, required dependencies, explicit
no-network behavior, and the expected coverage scope. Keep the existing fixture
and mutation-test context, and add a concise usage example if needed to satisfy
the TypeScript test documentation guidelines.

Source: Coding guidelines

javascript/examples/vitest/from-transcript/cc-transcript.ts (1)

31-51: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Complete the JSDoc contract for the new exported API.

Document parameters/properties, return values, thrown errors, limitations, and a usage example.

  • javascript/examples/vitest/from-transcript/cc-transcript.ts#L31-L51: document raw shapes and supported content blocks.
  • javascript/examples/vitest/from-transcript/cc-transcript.ts#L57-L124: document parser/traversal errors and fork semantics.
  • javascript/examples/vitest/from-transcript/cc-transcript.ts#L130-L142: document normalized-turn invariants.
  • javascript/examples/vitest/from-transcript/cc-transcript.ts#L169-L238: document unsupported content and normalization behavior.
  • javascript/examples/vitest/from-transcript/cc-transcript.ts#L244-L255: document defaults and fidelity trade-offs.
  • javascript/examples/vitest/from-transcript/cc-transcript.ts#L259-L316: add emission examples and error conditions.
  • javascript/examples/vitest/from-transcript/from-transcript.ts#L23-L58: document option and result semantics.
  • javascript/examples/vitest/from-transcript/from-transcript.ts#L134-L187: add a complete seeded-scenario example.

As per coding guidelines, all public TypeScript APIs and interfaces require complete JSDoc and usage examples.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@javascript/examples/vitest/from-transcript/cc-transcript.ts` around lines 31
- 51, Complete the JSDoc for all public APIs across
javascript/examples/vitest/from-transcript/cc-transcript.ts (31-51, 57-124,
130-142, 169-238, 244-255, 259-316) and
javascript/examples/vitest/from-transcript/from-transcript.ts (23-58, 134-187):
document raw shapes and supported AnthropicBlock variants, parameters,
normalized-turn invariants, parser/traversal and emission errors, fork
semantics, unsupported-content handling, defaults, fidelity trade-offs,
option/result behavior, and complete usage examples including a seeded scenario.
Ensure every exported interface, type, function, and related API has accurate
JSDoc without changing runtime behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@javascript/examples/vitest/from-transcript/cc-transcript.ts`:
- Around line 191-208: Replace all `any` escape hatches with explicit
discriminated types and reusable content-part type guards. In
javascript/examples/vitest/from-transcript/cc-transcript.ts:191-208, define or
reuse an internal message-ID type for `_msgId`; in
javascript/examples/vitest/from-transcript/cc-transcript.ts:295-312, type
assistant content parts explicitly. Update `messageText()` in
javascript/examples/vitest/from-transcript/from-transcript.ts:84-95 and
tool-part filtering in :101-130 to use those predicates. Narrow emitted
roles/parts in javascript/examples/vitest/from-transcript/reader.test.ts:89-112,
declare the fixture as `RawNode[]` in :156-165, and reuse the typed tool-part
predicates in :175-186; ensure no TypeScript `any` remains.
- Around line 114-121: Update blockText and all call sites handling classified
human turns so non-text image/file blocks are not silently omitted. Convert
supported blocks into corresponding AI-SDK content parts, or explicitly reject
unsupported blocks with a clear error; preserve the existing text handling and
ensure image-only prompts cannot become empty user messages.
- Around line 57-69: Update parseSessionFile to reject malformed JSON lines
instead of filtering them out, reporting the offending line. Update linearize to
validate every parent reference, reject missing parents, duplicate UUIDs, and
cycles with errors identifying the relevant UUID, and never return a partial
transcript when validation fails.

In `@javascript/examples/vitest/from-transcript/fixtures/real-cc-session.jsonl`:
- Around line 3-8: Sanitize the live-session JSONL fixture by replacing internal
prompts, tool inventories, workspace paths, session identifiers, timestamps,
memory content, and reasoning signatures with synthetic values while preserving
each record’s JSONL shape and parentUuid/tool relationships. Update the affected
entries throughout the fixture, including the referenced ranges, and ensure no
real operational or sensitive transcript data remains.

In `@javascript/examples/vitest/from-transcript/from-transcript.ts`:
- Line 47: Update parseSessionFile and the stats construction so rawLines
reflects the actual number of nonblank input JSONL lines, counted before
malformed or UUID-less records are filtered; alternatively rename the statistic
to parsedNodes if it is intended to report retained records, and apply the same
correction at the referenced reporting and assertion sites.

In `@javascript/examples/vitest/from-transcript/model.ts`:
- Around line 13-31: Validate the normalized SC779_PROVIDER value before model
selection in e2eModel and the related E2E_MODEL_ID configuration. Accept only
the supported OpenAI and Gemini/Google values, rejecting unsupported or
whitespace-containing values with a clear error instead of falling back to
OpenAI; preserve the existing credential and model behavior for valid providers.

In `@javascript/examples/vitest/from-transcript/proof.e2e.test.ts`:
- Around line 67-74: Replace the explicit any types in printVerdict and the
additional affected code around the proof result handling with the existing
result contract, using unknown only where values are genuinely untyped. Preserve
the current field access and logging behavior while ensuring TypeScript
validates success, metCriteria, unmetCriteria, and reasoning through the proper
interface.

In `@javascript/examples/vitest/from-transcript/reader.test.ts`:
- Around line 175-189: Update the test “structured-emit dropMatching leaves NO
orphaned tool parts (provider-valid seed)” to assert both pairing directions:
retain the existing check that every tool-result ID has a matching tool-call ID,
and add a check that every collected tool-call ID has a corresponding
tool-result ID.

---

Nitpick comments:
In `@javascript/examples/vitest/from-transcript/cc-transcript.ts`:
- Around line 31-51: Complete the JSDoc for all public APIs across
javascript/examples/vitest/from-transcript/cc-transcript.ts (31-51, 57-124,
130-142, 169-238, 244-255, 259-316) and
javascript/examples/vitest/from-transcript/from-transcript.ts (23-58, 134-187):
document raw shapes and supported AnthropicBlock variants, parameters,
normalized-turn invariants, parser/traversal and emission errors, fork
semantics, unsupported-content handling, defaults, fidelity trade-offs,
option/result behavior, and complete usage examples including a seeded scenario.
Ensure every exported interface, type, function, and related API has accurate
JSDoc without changing runtime behavior.

In `@javascript/examples/vitest/from-transcript/reader.test.ts`:
- Around line 1-9: Document the execution contract for the transcript reader
tests in the test file’s header: include the exact Vitest command, required
dependencies, explicit no-network behavior, and the expected coverage scope.
Keep the existing fixture and mutation-test context, and add a concise usage
example if needed to satisfy the TypeScript test documentation guidelines.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e3de4f90-76b8-419b-bbeb-e0e2c15e887e

📥 Commits

Reviewing files that changed from the base of the PR and between bfeb95d and 27e5cd5.

⛔ Files ignored due to path filters (1)
  • javascript/examples/vitest/from-transcript/evidence/e2e-run.log is excluded by !**/*.log
📒 Files selected for processing (7)
  • javascript/examples/vitest/from-transcript/README.md
  • javascript/examples/vitest/from-transcript/cc-transcript.ts
  • javascript/examples/vitest/from-transcript/fixtures/real-cc-session.jsonl
  • javascript/examples/vitest/from-transcript/from-transcript.ts
  • javascript/examples/vitest/from-transcript/model.ts
  • javascript/examples/vitest/from-transcript/proof.e2e.test.ts
  • javascript/examples/vitest/from-transcript/reader.test.ts

Comment thread javascript/examples/vitest/from-transcript/cc-transcript.ts
Comment thread javascript/examples/vitest/from-transcript/cc-transcript.ts
Comment thread javascript/examples/vitest/from-transcript/cc-transcript.ts Outdated
Comment thread javascript/examples/vitest/from-transcript/fixtures/real-cc-session.jsonl Outdated
Comment thread javascript/examples/vitest/from-transcript/from-transcript.ts Outdated
Comment thread javascript/examples/vitest/from-transcript/model.ts
Comment thread javascript/examples/vitest/from-transcript/proof.e2e.test.ts Outdated
Comment thread javascript/examples/vitest/from-transcript/reader.test.ts
@drewdrewthis
drewdrewthis force-pushed the issue779/transcript-to-scenario-helper branch from 27e5cd5 to a304fb0 Compare July 18, 2026 15:17
@drewdrewthis

drewdrewthis commented Jul 18, 2026

Copy link
Copy Markdown
Collaborator Author

Review verdict: READY

Reviewed at: 64eed88 · Run: review (own-PR) · reviewers: principles, hygiene, security, test, design-soundness, proof-reviewer (6-agent fan-out) + CodeRabbit.

No blocking concerns remain at this SHA. All blocking findings the review surfaced were fixed in this HEAD (below); no unresolved review threads.

Resolved by review (found blocking, fixed at 64eed88)

  • [security] fixture PII leak — FIXED. The reused fixture embedded the operator's real MEMORY.md + infra (private IP, Telegram handle, internal procedure text) verbatim in tool_result/attachment/injected bodies. Scrubbed to placeholders (parentUuid tree, tool names/ids, thinking, and the KUMQUAT77 flow preserved); the PII commit was removed from branch history via amend + force-push. Full sensitive-marker sweep across all committed files → 0 hits.
  • [test] 4 test-quality must-fixes — FIXED. (1) the "drops metadata" test was vacuous (passed with filtering disabled) → now asserts attachment uuids are absent from every normalized turn; (2) flattenTools:true (the only mode the e2e uses) had zero unit coverage → added; (3) the fork-by-uuid test only checked >=0 → now asserts the fork turn contains the uuid; (4) pruneOrphanToolParts' orphan-tool-call branch was unexercised → added a synthetic-fixture test. Suite is now 20 tests, mutation-proven (removing the parentUuid reverse turns 5 red).
  • [hygiene][principles] code quality — FIXED. All any casts replaced with real ai/SDK types (ScenarioResult, RawNode, TextPart/ToolCallPart/ToolResultPart) → 0 eslint-disables; droppedBySafetyFilter renamed to stats.droppedByMatch; the _msgId side-channel typed via a BuildTurn local; dangling PROTOTYPE.md doc reference removed.

Non-blocking (Decide / New Issue — prose only, no thread)

  • [design-soundness] PASS on build-vs-reuse (the Anthropic→AI-SDK converter, parentUuid walk, and addMessage side-door are genuine — no dependency ships them; the app's claude-code-log-to-span.ts consumes OTel logs, not raw JSONL). Two reuse options not taken, waived for a test-only surface: validating the seed via ai's modelMessageSchema; using @ai-sdk/google/@ai-sdk/openai-compatible instead of createOpenAI-against-Gemini. (Decide)
  • [hygiene] model.ts imports @ai-sdk/openai, which resolves transitively but is not a declared dep of vitest-examples (the weather-agent example relies on it too). (Decide / add to package.json)
  • [security] No procedure yet for "record a real CC session as a public fixture" (sandboxed $HOME, or a mandatory redaction pass) — worth filing before [SPIKE] Create a runnable Scenario from a real agent transcript — Claude Code failure-replay as first use case #779's deferred Strategy C/D produce more fixtures. (New Issue)
  • [proof-reviewer] DoD-5/6 receipts (mutation count, lint/tsc) are reproduced-live but not committed alongside the e2e log; optional. (Decide)

CI

Test (Examples) is red for an environmental reason (OpenAI account out of quota — hits pre-existing voice/* + weather-agent too; main's green predates the exhaustion). This PR's unit tests pass in CI and its live e2e is gated behind SC779_LIVE, so it adds nothing to the red; proven by the committed run receipt. Not a code defect.


Verdict is prose, not a GitHub approval.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@javascript/examples/vitest/from-transcript/from-transcript.ts`:
- Around line 28-31: Add JSDoc comments to the forkAt and includeThinking
properties in FromTranscriptOptions, describing each option’s purpose and
explicitly stating its default behavior. Preserve the existing documentation for
the tool I/O option and do not alter the interface types or runtime behavior.
- Line 136: Document the public fromTranscript function with JSDoc covering its
parameters, return type, and usage example. Explicitly describe errors for an
unfound forkAt UUID and an out-of-range index, using the existing function
behavior and option types without changing implementation logic.

In `@javascript/examples/vitest/from-transcript/README.md`:
- Around line 1-2: Add a contribution-guidelines section to the README for the
fromTranscript scenario, linking to the project’s existing main contribution
guidelines rather than duplicating them. Keep the current title and description
unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9181cd6a-23d5-48c8-bfb3-c91ba80f7310

📥 Commits

Reviewing files that changed from the base of the PR and between 27e5cd5 and a304fb0.

⛔ Files ignored due to path filters (1)
  • javascript/examples/vitest/from-transcript/evidence/e2e-run.log is excluded by !**/*.log
📒 Files selected for processing (7)
  • javascript/examples/vitest/from-transcript/README.md
  • javascript/examples/vitest/from-transcript/cc-transcript.ts
  • javascript/examples/vitest/from-transcript/fixtures/real-cc-session.jsonl
  • javascript/examples/vitest/from-transcript/from-transcript.ts
  • javascript/examples/vitest/from-transcript/model.ts
  • javascript/examples/vitest/from-transcript/proof.e2e.test.ts
  • javascript/examples/vitest/from-transcript/reader.test.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • javascript/examples/vitest/from-transcript/proof.e2e.test.ts
  • javascript/examples/vitest/from-transcript/model.ts
  • javascript/examples/vitest/from-transcript/cc-transcript.ts
  • javascript/examples/vitest/from-transcript/reader.test.ts

Comment thread javascript/examples/vitest/from-transcript/from-transcript.ts
Comment thread javascript/examples/vitest/from-transcript/from-transcript.ts
Comment thread javascript/examples/vitest/from-transcript/README.md
…ranscript helper with a live e2e

Turns a real Claude Code session .jsonl into a runnable Scenario (Strategy B,
JSONL-only): walk the parentUuid tree, normalize (real-user vs tool_result;
reassemble fragmented assistant turns; Anthropic to AI-SDK), seed via the
turn-free addMessage side-door (dodging the max_turns budget), then a live
agent() plus judge() replay the fork. Proven end-to-end with a live run (run id
in the PR body); 20 mutation-proven unit tests plus a 3-test live e2e gated
behind SC779_LIVE. The committed fixture is a PII-scrubbed real CC session
(structure + KUMQUAT77 flow intact; tool/attachment/injected bodies elided).
Graduates draft #789. No src/ change (example-space helper only).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PW4HxMfgLxY8dmGK4AimfG
@drewdrewthis
drewdrewthis force-pushed the issue779/transcript-to-scenario-helper branch from a304fb0 to 64eed88 Compare July 18, 2026 15:27
@drewdrewthis

Copy link
Copy Markdown
Collaborator Author

CodeRabbit findings — disposition (HEAD 64eed88)

Thanks CodeRabbit. Triage below; resolving threads accordingly.

Fixed at 64eed88:

  • 🔒 Unredacted live transcript → the fixture was PII-scrubbed (real MEMORY.md/infra bodies elided; parentUuid tree, tool names/ids, thinking, and the KUMQUAT77 flow preserved) and the original PII commit was removed from branch history via amend + force-push.
  • 📐 any escape hatches (cc-transcript.ts, proof.e2e.test.ts) → replaced with real ai/SDK types; 0 eslint-disables remain.
  • 🎯 stats.rawLines mislabels the count → renamed to stats.parsedNodes (it is the count of parsed uuid-bearing nodes, since parseSessionFile drops malformed/uuid-less lines).
  • 🎯 SC779_PROVIDER silent fall-through → now throws on an unsupported value instead of silently using OpenAI with a misleading label.

Non-blocking — acknowledged, deferred (this is a scope-locked spike-graduation example helper, not the productized feature; see #779 non-goals):

  • Reject malformed/disconnected transcripts — the reader intentionally tolerates malformed lines (real CC logs contain non-conversational/partial records); hard-failing + strict validation is a productization choice, deferred with the rest of [SPIKE] Create a runnable Scenario from a real agent transcript — Claude Code failure-replay as first use case #779.
  • Image/file content in human turns — a documented limitation (classifyUser recognizes non-text human blocks but the text extractor drops them); no image turns exist in the in-scope fixture. Deferred to productization.
  • JSDoc on every option/public API; README contribution-guidelines — reasonable for the shipped SDK; this lives under examples/vitest/ (the repo's contribution guide is at the root CONTRIBUTING.md). Deferred as non-blocking polish.
  • Assert both directions of tool pruning — the orphan-tool-call branch is exercised by the new synthetic-fixture test; the both-directions assertion is a nice-to-have.

CI: Test (Examples) + evaluate are red only because the shared OpenAI account is out of quota (insufficient_quota) — repo-wide (hits pre-existing voice/* + weather-agent too), not a defect in this PR. Unit tests pass; the live e2e is gated behind SC779_LIVE and proven by the committed run receipt.

@langwatch-agent
langwatch-agent requested review from rogeriochaves and removed request for rogeriochaves July 30, 2026 06:35
@langwatch-agent langwatch-agent added the hound-checked Triaged by the pr-hound agent at the current head SHA label Aug 5, 2026
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Automated low-risk assessment

This PR was evaluated against the repository's Low-Risk Pull Requests procedure and does not qualify as low risk.

The PR adds a non-trivial example feature that includes new runtime code for parsing Claude Code JSONL and a live end-to-end test that talks to external model providers (OpenAI/Gemini) via the repository's provider adapter. Because it introduces new integration points that can call third‑party APIs (even if gated/skipped by default), it does not meet the policy's requirement of not changing integrations with external systems.

This PR requires a manual review before merging.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

hound-checked Triaged by the pr-hound agent at the current head SHA

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants