Skip to content

release: prepare v6.2.0#87

Merged
gaelic-ghost merged 3 commits into
mainfrom
runtime/playback-event-updates
May 8, 2026
Merged

release: prepare v6.2.0#87
gaelic-ghost merged 3 commits into
mainfrom
runtime/playback-event-updates

Conversation

@gaelic-ghost
Copy link
Copy Markdown
Owner

@gaelic-ghost gaelic-ghost commented May 8, 2026

Release

  • prepares v6.2.0 from branch runtime/playback-event-updates
  • keeps protected main updates behind pull request review and CI
  • release tag v6.2.0 will be created after CI and the review-comment gate pass, so failed or still-discussed release candidates do not get tagged

Review Loop

Before merge and tagging, scripts/repo-maintenance/release.sh watches CI and stops on review comments unless the maintainer has already addressed or resolved them and reruns with --review-comments-addressed.

Summary by CodeRabbit

  • New Features

    • Added playback event streaming to enable real-time progress notifications for ongoing audio playback.
    • Introduced new MCP resources for monitoring playback state and queue information.
    • Expanded speech backend options with additional Qwen and Marvis model variants.
  • Documentation

    • Updated API documentation with new playback transport contract details and MCP resource mappings.
    • Enhanced coverage matrix documentation.
  • Chores

    • Bumped plugin version to 6.2.0.
    • Updated dependencies.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 8, 2026

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f3cbcf12-8b91-48ae-8eb9-e391682a26ee

📥 Commits

Reviewing files that changed from the base of the PR and between cbef03c and f10c8dd.

📒 Files selected for processing (3)
  • Sources/SpeakSwiftlyServer/Host/ServerHost+PlaybackEventMapping.swift
  • Tests/SpeakSwiftlyServerLibraryTests/HostStateTests.swift
  • docs/maintainers/speakswiftly-api-coverage-matrix.md
✅ Files skipped from review due to trivial changes (2)
  • Sources/SpeakSwiftlyServer/Host/ServerHost+PlaybackEventMapping.swift
  • docs/maintainers/speakswiftly-api-coverage-matrix.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • Tests/SpeakSwiftlyServerLibraryTests/HostStateTests.swift

📝 Walkthrough

Walkthrough

This PR integrates real-time playback event streaming from the SpeakSwiftly runtime into the server host, extends core data models to carry playback event snapshots through control responses and job progress tracking, exposes playback state via new MCP resources, and broadens support for additional speech backend variants.

Changes

Playback Event Streaming Integration

Layer / File(s) Summary
Data Models & Contracts
Sources/SpeakSwiftlyServer/Host/EmbeddedServerSnapshots.swift, Sources/SpeakSwiftlyServer/Host/RequestEventModels.swift
PlaybackStatusSnapshot adds optional latestEvent field and updates initializers; ServerProgressEvent carries optional playbackEvent with playback_event JSON encoding.
Runtime Protocol & Adapter
Sources/SpeakSwiftlyServer/Host/SpeakSwiftlyRuntimeServing.swift, Sources/SpeakSwiftlyServer/Host/SpeakSwiftlyRuntimeAdapter.swift
SpeakSwiftlyRuntimeServing protocol declares playbackUpdates() method; adapter implements it by delegating to runtime.playback.updates().
Event Mapping Logic
Sources/SpeakSwiftlyServer/Host/ServerHost+PlaybackEventMapping.swift
New mapPlaybackEvent(_:) converts SpeakSwiftly.PlaybackUpdate into PlaybackEventSnapshot with event-specific field extraction; introduces PlaybackEventBase helper for shared snapshot construction.
Host Event Handler
Sources/SpeakSwiftlyServer/Host/ServerHost+RequestEvents.swift
New handle(playbackUpdate:) method fetches fresh runtime snapshots, emits .playbackChanged host events, and records non-terminal .progress job events for active requests.
Lifecycle Integration
Sources/SpeakSwiftlyServer/Host/ServerHost.swift, Sources/SpeakSwiftlyServer/Host/ServerHost+RuntimeLifecycle.swift
ServerHost adds playbackTask property; start() subscribes to runtime playback updates stream and forwards to handler; shutdown() cancels playback task.
Control & Snapshot Responses
Sources/SpeakSwiftlyServer/Host/ServerHost+ControlResponses.swift, Sources/SpeakSwiftlyServer/Host/ServerHost+Snapshots.swift, Sources/SpeakSwiftlyServer/EmbeddedServerSession.swift
playbackSnapshotResponse() includes latestEvent; optimisticPlaybackStateResponse() propagates sequence/updatedAt/latestEvent; applyRuntimeStateSnapshots() preserves prior event; pause/resume handlers return response directly.
MCP Surface Resources & Subscriptions
Sources/SpeakSwiftlyServer/MCP/MCPResources.swift, Sources/SpeakSwiftlyServer/MCP/MCPSubscriptionBroker.swift, Sources/SpeakSwiftlyServer/MCP/MCPPrompts.swift
New MCP resources speak-swiftly://playback and speak-swiftly://playback/queue serve playback state; .playbackChanged events notify playback-specific URIs; prompt routing updated.
Speech Backend Support
Sources/SpeakSwiftlyServer/Config/RuntimeStartupConfiguration.swift
isQwenSpeechBackend expands to include qwen3_smol_4bit, qwen3_smol_5bit, qwen3_big_4bit, qwen3_big_5bit, marvis_4bit, marvis_6bit; legacy Qwen mapping extended.
Test Infrastructure
Tests/SpeakSwiftlyServerLibraryTests/MockRuntime.swift, Tests/SpeakSwiftlyServerLibraryTests/MockRuntime+TestControl.swift
MockRuntime adds playbackUpdateContinuation and playbackUpdates() stream; test helper publishPlaybackUpdate() and playbackUpdate(_:) builder added; shutdown() finishes continuation.
Integration Tests
Tests/SpeakSwiftlyServerLibraryTests/HostStateTests.swift, Tests/SpeakSwiftlyServerLibraryTests/HTTPWorkflowTests.swift, Tests/SpeakSwiftlyServerLibraryTests/MCPCatalog*.swift
New playback updates publish latest event and request progress details test; HTTP tests validate backend variant switching; MCP catalog tests assert playback resources and expanded backend enum values.
Documentation & Configuration
.codex-plugin/plugin.json, API.md, Package.swift, Package.resolved, ROADMAP.md, hooks/hooks.json, docs/codex-hooks-tts.md, skills/speak-swiftly-codex-hooks/SKILL.md, docs/maintainers/speakswiftly-api-coverage-matrix.md
Plugin version bumped to 6.2.0; API.md documents playback milestones, MCP playback resources, and expanded backends; SpeakSwiftly dependency updated to 7.2.7; ROADMAP updated with compatibility-gated progress feature; hook scripts and docs updated to reference 6.2.0.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 Swift streams now carry playback delight,
Events dance through our snapshot's flight,
MCP resources bloom anew,
Marvis and Qwen variants too—
The server's playback pipeline shines bright!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'release: prepare v6.2.0' directly aligns with the main objective—preparing the v6.2.0 release. The version bump appears throughout the changeset (plugin.json, hooks, docs), and the title concisely captures this primary purpose.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 runtime/playback-event-updates

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
docs/maintainers/speakswiftly-api-coverage-matrix.md (1)

72-73: ⚡ Quick win

Consolidate duplicated runtime.playback.snapshot() entries to reduce drift risk.

Line 72 and Line 73 split one symbol into two rows. Consider merging into a single row with both read endpoints/resources in Notes to avoid future partial updates.

🤖 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 `@docs/maintainers/speakswiftly-api-coverage-matrix.md` around lines 72 - 73,
The table currently has duplicate rows for the same symbol
runtime.playback.snapshot(); merge them into a single row so the symbol appears
once and include both read endpoints (GET /playback/queue and GET
/playback/state) and all referenced resources (speak-swiftly://overview,
speak-swiftly://playback/queue, speak-swiftly://playback) in the Notes column,
combining the two notes (playback queue read model and playback state
reads/control settling) into one concise note to prevent future drift.
Sources/SpeakSwiftlyServer/Host/ServerHost+RuntimeLifecycle.swift (1)

19-74: Run SwiftPM validation on the selected Xcode toolchain before release tagging.

Please use:

  • xcrun swift build
  • xcrun swift test

As per coding guidelines, "Use xcrun swift build and xcrun swift test as the default first-pass validation commands so repo-local SwiftPM work stays on the Xcode-selected toolchain".

🤖 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 `@Sources/SpeakSwiftlyServer/Host/ServerHost`+RuntimeLifecycle.swift around
lines 19 - 74, Add a pre-release SwiftPM validation step that runs the
Xcode-selected toolchain builds/tests using `xcrun swift build` and `xcrun swift
test` before finalizing release tagging; locate the release-finalization or
lifecycle completion path (e.g., near ServerHost+RuntimeLifecycle.swift
functions start() or shutdown(), or wherever release/tagging is invoked) and
invoke those two commands (capturing and failing on non-zero exit) so the
process aborts on build or test failures.
Sources/SpeakSwiftlyServer/Host/ServerHost+EventMapping.swift (1)

149-213: ⚡ Quick win

Extract playback event mapping into a dedicated ServerHost extension file.

Please move mapPlaybackEvent(_:) and PlaybackEventBase into a focused file (for example, ServerHost+PlaybackEventMapping.swift) to keep this extension from accumulating mixed responsibilities.

As per coding guidelines, **/*.swift: "Keep source files small and role-focused; split shared support into explicit helper or extension files instead of growing mixed-responsibility entry points".

Also applies to: 373-409

🤖 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 `@Sources/SpeakSwiftlyServer/Host/ServerHost`+EventMapping.swift around lines
149 - 213, Move the playback-mapping logic out of the large EventMapping file
into a focused extension file named something like
ServerHost+PlaybackEventMapping.swift: create a new file that imports the same
modules and defines an extension ServerHost containing the mapPlaybackEvent(_:)
function and the PlaybackEventBase type (keeping the same access levels),
ensuring it references TimestampFormatter, PlaybackEventSnapshot,
ActiveRequestSnapshot and QueuedRequestSnapshot exactly as before; then remove
the moved definitions from ServerHost+EventMapping.swift so there are no
duplicate symbols and build visibility remains unchanged.
🤖 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 `@Tests/SpeakSwiftlyServerLibraryTests/HostStateTests.swift`:
- Around line 152-162: The test reads host.jobSnapshot once immediately after
awaiting playback.latestEvent which can miss a concurrently-appended progress
entry; change the assertion to poll/refetch jobSnapshot (call
host.jobSnapshot(id: jobID) in a short-loop with a timeout) and rebuild
playbackProgress from snapshot.history each iteration until the predicate on
playbackProgress (matching stage "playback_preroll_ready",
playbackEvent?.requestID == jobID and bufferedAudioMS == 240) succeeds or the
timeout elapses; reference the existing symbols playback.latestEvent,
host.jobSnapshot(id:), snapshot.history, playbackProgress and
ServerProgressEvent when implementing the retry/wait loop to stabilize the
assertion.

---

Nitpick comments:
In `@docs/maintainers/speakswiftly-api-coverage-matrix.md`:
- Around line 72-73: The table currently has duplicate rows for the same symbol
runtime.playback.snapshot(); merge them into a single row so the symbol appears
once and include both read endpoints (GET /playback/queue and GET
/playback/state) and all referenced resources (speak-swiftly://overview,
speak-swiftly://playback/queue, speak-swiftly://playback) in the Notes column,
combining the two notes (playback queue read model and playback state
reads/control settling) into one concise note to prevent future drift.

In `@Sources/SpeakSwiftlyServer/Host/ServerHost`+EventMapping.swift:
- Around line 149-213: Move the playback-mapping logic out of the large
EventMapping file into a focused extension file named something like
ServerHost+PlaybackEventMapping.swift: create a new file that imports the same
modules and defines an extension ServerHost containing the mapPlaybackEvent(_:)
function and the PlaybackEventBase type (keeping the same access levels),
ensuring it references TimestampFormatter, PlaybackEventSnapshot,
ActiveRequestSnapshot and QueuedRequestSnapshot exactly as before; then remove
the moved definitions from ServerHost+EventMapping.swift so there are no
duplicate symbols and build visibility remains unchanged.

In `@Sources/SpeakSwiftlyServer/Host/ServerHost`+RuntimeLifecycle.swift:
- Around line 19-74: Add a pre-release SwiftPM validation step that runs the
Xcode-selected toolchain builds/tests using `xcrun swift build` and `xcrun swift
test` before finalizing release tagging; locate the release-finalization or
lifecycle completion path (e.g., near ServerHost+RuntimeLifecycle.swift
functions start() or shutdown(), or wherever release/tagging is invoked) and
invoke those two commands (capturing and failing on non-zero exit) so the
process aborts on build or test failures.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0bcdc837-c2f8-4e62-9aad-93082ec0b2ee

📥 Commits

Reviewing files that changed from the base of the PR and between 82327ed and cbef03c.

📒 Files selected for processing (31)
  • .codex-plugin/plugin.json
  • API.md
  • Package.resolved
  • Package.swift
  • ROADMAP.md
  • Sources/SpeakSwiftlyServer/Config/RuntimeStartupConfiguration.swift
  • Sources/SpeakSwiftlyServer/EmbeddedServerSession.swift
  • Sources/SpeakSwiftlyServer/Host/EmbeddedServerSnapshots.swift
  • Sources/SpeakSwiftlyServer/Host/RequestEventModels.swift
  • Sources/SpeakSwiftlyServer/Host/ServerHost+ControlResponses.swift
  • Sources/SpeakSwiftlyServer/Host/ServerHost+EventMapping.swift
  • Sources/SpeakSwiftlyServer/Host/ServerHost+RequestEvents.swift
  • Sources/SpeakSwiftlyServer/Host/ServerHost+RuntimeLifecycle.swift
  • Sources/SpeakSwiftlyServer/Host/ServerHost+Snapshots.swift
  • Sources/SpeakSwiftlyServer/Host/ServerHost.swift
  • Sources/SpeakSwiftlyServer/Host/SpeakSwiftlyRuntimeAdapter.swift
  • Sources/SpeakSwiftlyServer/Host/SpeakSwiftlyRuntimeServing.swift
  • Sources/SpeakSwiftlyServer/MCP/MCPPrompts.swift
  • Sources/SpeakSwiftlyServer/MCP/MCPResources.swift
  • Sources/SpeakSwiftlyServer/MCP/MCPSubscriptionBroker.swift
  • Tests/SpeakSwiftlyServerLibraryTests/HTTPWorkflowTests.swift
  • Tests/SpeakSwiftlyServerLibraryTests/HostStateTests.swift
  • Tests/SpeakSwiftlyServerLibraryTests/MCPCatalogListingTests.swift
  • Tests/SpeakSwiftlyServerLibraryTests/MCPCatalogResourceTests.swift
  • Tests/SpeakSwiftlyServerLibraryTests/MCPCatalogRuntimeTests.swift
  • Tests/SpeakSwiftlyServerLibraryTests/MockRuntime+TestControl.swift
  • Tests/SpeakSwiftlyServerLibraryTests/MockRuntime.swift
  • docs/codex-hooks-tts.md
  • docs/maintainers/speakswiftly-api-coverage-matrix.md
  • hooks/hooks.json
  • skills/speak-swiftly-codex-hooks/SKILL.md

Comment thread Tests/SpeakSwiftlyServerLibraryTests/HostStateTests.swift Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cbef03c1a4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

generationQueueStatus = queueStatusSnapshot(from: generationSnapshot)
playbackQueueStatus = queueStatusSnapshot(from: playbackSnapshot)
playbackStatus = PlaybackStatusSnapshot(summary: playbackSnapshot)
playbackStatus = PlaybackStatusSnapshot(summary: playbackSnapshot, latestEvent: playbackStatus.latestEvent)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid treating snapshot capture time as playback change

applyRuntimeStateSnapshots() now rebuilds playbackStatus from every runtime.playbackSnapshot() call, and PlaybackStatusSnapshot(summary:) includes volatile fields like updatedAt (from capturedAt) and sequence. In refreshRuntimeDerivedState(), playback notifications are emitted when playbackStatus != previousPlaybackStatus, so unchanged playback state can still look "changed" on routine refreshes (for example, during non-playback job progress), generating spurious .playbackChanged events and extra MCP playback/playback/queue notifications. This should compare semantic playback fields (or preserve prior volatile fields when state is unchanged) before emitting change events.

Useful? React with 👍 / 👎.

@gaelic-ghost gaelic-ghost merged commit a3153e2 into main May 8, 2026
2 checks passed
@gaelic-ghost gaelic-ghost deleted the runtime/playback-event-updates branch May 8, 2026 15:22
@coderabbitai coderabbitai Bot mentioned this pull request May 9, 2026
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.

1 participant