Skip to content

feat(run-state): add the turn sub-machine (#1800) - #2127

Merged
edelauna merged 1 commit into
mainfrom
issue/1800
Oct 22, 2026
Merged

edelauna merged 1 commit into
mainfrom
issue/1800

Conversation

@edelauna

@edelauna edelauna commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Related GitHub Issue

Closes: #1800

Description

This PR adds the turn sub-machine to the run-state kernel (RSK-09). Nothing is wired. #1804 and #1805 route the writes and flip the reads.

A turn is one request iteration of the loop. The new turn region holds the five within-turn fields:

Kernel field Task field Event
waitingForFirstChunk isWaitingForFirstChunk firstChunkAwaitStarted, firstChunkAwaitEnded
toolRejected didRejectTool toolRejected
toolUsed didAlreadyUseTool toolUsed
toolFailed didToolFailInCurrentTurn toolFailed
streamReadComplete didCompleteReadingStream streamReadCompleted

Design choices:

  • turnStarted maps to the per-request reset block. It clears four fields and keeps waitingForFirstChunk, because the legacy block does not clear isWaitingForFirstChunk. If the chunk loop breaks on the first chunk, the flag stays true. The kernel keeps this behavior, so the later read flip does not change graceful-abort timing.
  • Turn events have no guard. The loop and the tools write these fields in every phase, after abort, and after the stream ends.
  • No other event changes the turn. The turn does not depend on stream.tag.

The design doc now lists the Turn type, the seven events, a transition row for each, and the name mapping.

Reviewers must check the turnStarted choice that keeps waitingForFirstChunk.

Test Procedure

  1. Run pnpm --dir src exec vitest run core/task/run-state core/task/__tests__/Task.run-shadow.spec.ts.
  2. Run pnpm --dir src run check-types.
  3. Run pnpm --dir src exec eslint --max-warnings=0 core/task/run-state.

The new tests cover:

  • each turn event sets only its own field, with the other four fields already set
  • turnStarted resets four fields and keeps waitingForFirstChunk
  • stream events do not change the turn
  • tool writes after the stream ends
  • an abort before the first chunk
  • turn events in the uninitialized, completed, and aborted phases

Pre-Submission Checklist

  • Issue Linked: This PR is linked to an approved GitHub Issue (see "Related GitHub Issue" above).
  • Scope: My changes are focused on the linked issue (one major feature/fix per PR).
  • Self-Review: I reviewed my own code with care.
  • Writing Style: The PR title and description use Simplified Technical English (ASD-STE100): short sentences, plain words, active voice, one idea per sentence, no contractions.
  • Testing: New and/or updated tests have been added to cover my changes (if applicable).
  • Visual Snapshot (UI changes only): Not applicable. This PR has no UI change.
  • Documentation Impact: I checked if my changes need documentation updates (see "Documentation Updates" section below).
  • Contribution Guidelines: I read and agree to the Contributor Guidelines.

Documentation Updates

  • No user-facing documentation updates are required. The architecture doc docs/architecture/task-lifecycle-target-architecture.md is updated in this PR.

Additional Notes

Exit criteria from the issue: the turn sub-machine compiles and is tested. Nothing is wired.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: Zoo-Code-Org/Zoo-Code/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 5c55477b-e761-4e09-bcfd-3efb72de8bdf
📥 Commits

Reviewing files that changed from the base of the PR and between 16425bc and 666df9f.

📒 Files selected for processing: 3
  • docs/architecture/task-lifecycle-target-architecture.md
  • src/core/task/run-state/__tests__/runState.spec.ts
  • src/core/task/run-state/runState.ts

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.

📜 Recent review details
🧰 Additional context used
📚 Code guidelines: 2
docs/architecture/task-lifecycle-target-architecture.md — auto-discovered
AGENTS.md — auto-discovered
📓 Path-based instructions: 7
Check persistence and lifecycle invariants: awaited atomic writes, rollback or explicit partial-failure behavior, cross-window state consistency, stale listeners/watchers, cancellation, idempotency, and safe restart/resume without lost or d...

⚙️ CodeRabbit configuration file

Files:

  • src/core/task/run-state/__tests__/runState.spec.ts
  • src/core/task/run-state/runState.ts
Require regression coverage at the lowest valid harness with behavior-focused assertions, including relevant negative, error, false/unset, and boundary cases.

⚙️ CodeRabbit configuration file

Files:

  • src/core/task/run-state/__tests__/runState.spec.ts
Check strict typing and exhaustive behavior across normal, boundary, error, cancellation, retry, and compatibility paths.

⚙️ CodeRabbit configuration file

Files:

  • src/core/task/run-state/__tests__/runState.spec.ts
  • src/core/task/run-state/runState.ts
Verify extension/webview contracts, cancellation and error propagation, VS Code lifecycle correctness, and behavior under retries and partial failure.

⚙️ CodeRabbit configuration file

Files:

  • src/core/task/run-state/__tests__/runState.spec.ts
  • src/core/task/run-state/runState.ts
Act as an adversarial second-opinion reviewer.

⚙️ CodeRabbit configuration file

Files:

  • src/core/task/run-state/__tests__/runState.spec.ts
  • src/core/task/run-state/runState.ts
  • docs/architecture/task-lifecycle-target-architecture.md
Applicability reference: AGENTS.md: # AGENTS.md The in-memory run-state submodel lives in `src/core/task/run-state/runState.ts`.

📄 CodeRabbit inference engine (docs/architecture/task-lifecycle-target-architecture.md)

Files:

  • src/core/task/run-state/runState.ts
Source excerpt: The in-memory run-state submodel lives in `src/core/task/run-state/runState.ts`.

📄 CodeRabbit inference engine (AGENTS.md)

Files:

  • src/core/task/run-state/runState.ts
🪛 GitHub Check: mutation-diff
src/core/task/run-state/runState.ts

[warning] 67-67: Mutation test advisory
src/core/task/run-state/runState.ts:67: Survived BooleanLiteral mutant (replacement: true). See the job summary for the complete list and resolution guidance.

[warning] 66-66: Mutation test advisory
src/core/task/run-state/runState.ts:66: Survived BooleanLiteral mutant (replacement: true). See the job summary for the complete list and resolution guidance.

[warning] 65-65: Mutation test advisory
src/core/task/run-state/runState.ts:65: Survived BooleanLiteral mutant (replacement: true). See the job summary for the complete list and resolution guidance.

[warning] 64-64: Mutation test advisory
src/core/task/run-state/runState.ts:64: Survived BooleanLiteral mutant (replacement: true). See the job summary for the complete list and resolution guidance.

[warning] 63-63: Mutation test advisory
src/core/task/run-state/runState.ts:63: Survived BooleanLiteral mutant (replacement: true). See the job summary for the complete list and resolution guidance.

[warning] 62-62: Mutation test advisory
src/core/task/run-state/runState.ts:62: Survived ObjectLiteral mutant (replacement: {}). See the job summary for the complete list and resolution guidance.

🔇 Additional comments: 2
src/core/task/run-state/runState.ts: 1

15-21: LGTM!

Also applies to: 35-35, 42-48, 62-68, 75-75, 87-106

docs/architecture/task-lifecycle-target-architecture.md: 1

193-214: LGTM!

Also applies to: 254-273, 350-360

📝 Summary

Summary by CodeRabbit

  • Improvements

    • Improved task-run tracking across individual turns, including first-response waiting, tool outcomes, and stream-read completion.
    • Task state now preserves relevant turn information consistently through completion, interruption, and cleanup scenarios.
  • Documentation

    • Updated the task lifecycle architecture documentation to reflect the expanded turn-level state and event flow.
  • Tests

    • Added coverage for turn lifecycle transitions and state preservation.

The run-state model adds a Turn sub-machine with five boolean flags and events for turn starts, first-chunk waiting, tool outcomes, and stream-read completion. Transition tests and architecture documentation describe the new state and its behavior.

Changes: Turn state

Layer / File(s) Summary
Turn state shape and initialization
src/core/task/run-state/runState.ts, docs/architecture/task-lifecycle-target-architecture.md
RunState now contains a Turn object with five false-valued flags in the initial state. The architecture document describes the turn state and its events.
Turn transitions and validation
src/core/task/run-state/runState.ts, src/core/task/run-state/__tests__/runState.spec.ts, docs/architecture/task-lifecycle-target-architecture.md
Turn events update their corresponding flags. turnStarted resets tool and stream-read flags while preserving first-chunk waiting. Tests cover flag updates, lifecycle phases, post-stream writes, and abort ordering.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Feature

Merge Risk: ⚪ Minimal · up to 666df

The turn sub-machine is ready to merge after normal checks; no actionable issue remains identified.

Pre-merge checks: Passed 8
Check name Status Explanation
Title check Passed The title clearly identifies the main change: adding the turn sub-machine to run-state.
Description check Passed The description includes the linked issue, implementation details, design decisions, test procedure, checklist, documentation impact, and scope notes. It is sufficiently complete for review.
Linked Issues check Passed Issue #1800 requires the five-field turn state, an unguarded turnStarted reset, independence from stream.tag, unit coverage for transitions, post-stream tool writes, and abort-before-first-chunk b…
Out of Scope Changes check Passed The changed files are limited to the run-state implementation, its unit tests, and the target architecture document. These changes directly implement and document issue #1800. No unrelated behavior or…
Regression Evidence Passed PASS. The pull request changes only the run-state kernel and architecture documentation; it has no UI change. Focused nextRunState tests cover all seven turn events, initial defaults and freezing, p…
Security Boundaries Passed The changed paths only add boolean turn fields, typed event variants, immutable reducer transitions, tests, and architecture documentation. nextRunState performs no I/O, secret or PII handling, inpu…
Persistence Integrity Passed No changed persistence path exists. The PR changes the pure in-memory nextRunState transition and its frozen initialRunState, plus tests and architecture documentation. It adds turn fields by obje…
Lifecycle Resource Cleanup Passed PASS. The changed implementation only adds immutable turn data and pure nextRunState transitions in src/core/task/run-state/runState.ts (lines 62-106). It creates no listener, watcher, provider, t…
Full details: Linked Issues check

Explanation

Issue #1800 requires the five-field turn state, an unguarded turnStarted reset, independence from stream.tag, unit coverage for transitions, post-stream tool writes, and abort-before-first-chunk behavior. runState.ts adds Turn, initializes all five fields, handles all seven turn events, preserves waitingForFirstChunk during turnStarted, and does not gate turn events by phase or stream. runState.spec.ts covers the required transitions and scenarios. The implementation does not route writes or flip reads.

Full details: Out of Scope Changes check

Explanation

The changed files are limited to the run-state implementation, its unit tests, and the target architecture document. These changes directly implement and document issue #1800. No unrelated behavior or follow-up write/read routing is added.

Full details: Regression Evidence

Explanation

PASS. The pull request changes only the run-state kernel and architecture documentation; it has no UI change. Focused nextRunState tests cover all seven turn events, initial defaults and freezing, per-field set/clear behavior, preservation of the other fields, turnStarted reset semantics including retained waitingForFirstChunk, stream isolation, acceptance in uninitialized/completed/aborted phases, post-stream tool writes, and abort-before-first-chunk behavior (src/core/task/run-state/__tests__/runState.spec.ts:88-191, 524-543). No changed error, negative, or unset branch lacks plausible focused coverage.

Full details: Security Boundaries

Explanation

The changed paths only add boolean turn fields, typed event variants, immutable reducer transitions, tests, and architecture documentation. nextRunState performs no I/O, secret or PII handling, input execution, or approval/allowlist decisions. No concrete security-boundary failure was introduced.

Full details: Persistence Integrity

Explanation

No changed persistence path exists. The PR changes the pure in-memory nextRunState transition and its frozen initialRunState, plus tests and architecture documentation. It adds turn fields by object-copy transitions and does not add storage writes, serialization, async operations, rollback handling, or persisted-status consumers. The architecture document explicitly keeps RunState separate from persisted status.

Full details: Lifecycle Resource Cleanup

Explanation

PASS. The changed implementation only adds immutable turn data and pure nextRunState transitions in src/core/task/run-state/runState.ts (lines 62-106). It creates no listener, watcher, provider, timer, task, subscription, or cleanup operation. Turn events only return copied state and do not start work or alter cancellation/disposal latches. The changed event names have no production callers outside this reducer; tests and documentation are the other changed files. No changed lifecycle path can leak a resource or duplicate work after cancellation, disposal, or restart.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Review status

Thanks for contributing. This comment tracks the review sequence and the next action.

Current step: The required review sequence passed. Remaining merge requirements apply.

Review-state labels are managed by this workflow; do not edit them manually. community-approved is managed the same way — do not add or remove it manually. It signals a fresh community code approval for the current head as an advisory priority only; maintainer review is still required.

@codecov

codecov Bot commented Oct 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@github-actions github-actions Bot added coderabbit-review-active Required CI passed; CodeRabbit review is active awaiting-coderabbit Waiting for CodeRabbit to approve the latest commit labels Oct 21, 2026
@github-actions github-actions Bot added awaiting-maintainer CodeRabbit approved; waiting for a human maintainer and removed coderabbit-review-active Required CI passed; CodeRabbit review is active awaiting-coderabbit Waiting for CodeRabbit to approve the latest commit labels Oct 21, 2026
@github-actions github-actions Bot added the community-approved Fresh community approval on the current head; maintainer review still required label Oct 21, 2026
@github-actions github-actions Bot removed awaiting-maintainer CodeRabbit approved; waiting for a human maintainer community-approved Fresh community approval on the current head; maintainer review still required labels Oct 21, 2026
@edelauna
edelauna added this pull request to the merge queue Oct 22, 2026
Merged via the queue into main with commit 13c6f6c Oct 22, 2026
24 checks passed
@edelauna
edelauna deleted the issue/1800 branch October 22, 2026 03:59
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.

[lifecycle-RSK] RSK-09: Add the turn sub-machine

3 participants