Skip to content

fix: preserve provider command routing for spawned sessions - #576

Merged
pedronauck merged 2 commits into
mainfrom
fix/issue-564-spawn-provider-routing
Sep 9, 2026
Merged

pedronauck merged 2 commits into
mainfrom
fix/issue-564-spawn-provider-routing

Conversation

@pedronauck

@pedronauck pedronauck commented Sep 9, 2026 •

Copy link
Copy Markdown
Member

What & why

Fixes #564.

A creator pinned to native provider command B could spawn a commandless reviewer on global command
A. The child runtime was resolved from its agent definition and provider defaults without using
the creator's resolved command. An explicit child command and a different named provider were
already legitimate overrides; forcing the parent command onto every child would break them.

This change makes governed spawn precedence explicit:

  1. The selected child's explicit command remains authoritative. A different runtime provider
    selection continues to discard the original agent's provider-specific command.
  2. A commandless child inherits the creator's resolved command only for the same native CLI
    provider, workspace and profile, with operator-home policy and compatible auth, environment,
    harness, runtime provider, transport, base URL and auth probe/login settings.
  3. Otherwise the child's own provider configuration resolves its command as before.

Live sessions retain an internal resolved routing snapshot, so editing an agent definition after
its process starts does not redirect its delegated work. Runtime replacement updates the snapshot
only after the replacement is committed. On resume, a live creator supplies its snapshot; a stopped
creator is resolved through the existing persisted lineage and current configuration. Deleted
creator metadata preserves the child's configured fallback and emits an explicit diagnostic.
Commands and credentials are not added to persisted session metadata, DTOs or logs.

Observability is separate from account authentication. The selected-route log and provider failure
markers carry a SHA-256 provider_command_fingerprint, allowing correlation without exposing raw
commands or account directories. The launch-time JSON selection log has one authoritative fingerprint field. A failed replacement
logs its attempted route while preserving the prior runtime binding.
Startup failures now emit the existing provider failure marker after their canonical error and
stop events. Unsupported or missing ACP session loads continue through the established replay
fallback without inserting a transient failure into the replay transcript. Prompt auth errors retain the established recoverable logical-session behavior:
active and successful spawn do not promise that the provider will authenticate a later prompt.
The fingerprint identifies command configuration; it does not identify a login account or profile.

How you verified it

Implementation and verification owner: Codex, GPT-6-Astra at High reasoning.

  • Regression reproduced with a fixed Go overlay disabling only the inheritance call: two inherited
    cases launched A instead of B; explicit child and different-provider cases passed.
  • Focused race suites cover explicit/same/different provider precedence, isolated home/environment
    policies, authorized foreign workspace routing, runtime replacement, recoverable prompt auth
    diagnostics, failed-start retention and route fingerprint correlation. JSON logs are checked
    for duplicate fingerprint keys and private command-value leakage.
  • Final combined verification: GOMAXPROCS=4 CGO_ENABLED=1 mise exec -- go test -race -p=1 -parallel=4 -tags=integration ./internal/session with the six focused routing/diagnostic and
    integration tests named in the QA report, -count=1: PASS in 16.902s.
  • Real ACP subprocess integration ran through the existing Session Manager harness and SQLite:
    parent B / inherited child B / explicit child C, no unexpected A execution, live creator snapshot
    after config edits, and child resume with live and stopped creators. Existing provider persistence
    and full stop/resume/stop integration cases passed alongside it.
  • One broad uncapped race run encountered an existing one-second stop deadline under heavy shared
    host contention. The unchanged case passed three isolated repetitions; no assertions or timeout
    values were weakened.
  • The scoped gate exposed a transient resume-load marker in the replay transcript; production
    emission was corrected without changing the existing replay assertions. The final targeted
    -race -p=1 -parallel=4 run of TestResumeReplayFallback,
    TestSpawnProviderRouteDiagnostics and TestPromptRuntimeReplacementLifecycle passed in 8.166s.
  • Final GOMAXPROCS=4 COMPOZY_GO_TEST_P=1 COMPOZY_GO_LINT_CONCURRENCY=2 mise exec -- make gate: PASS.
    Go lint/format: zero issues; full affected Session Manager race suite: PASS in 147.115s;
    internal/session/inputqueue and skills: PASS. make gate-status confirmed CURRENT-PASS after
    commit for tree 730ae879b38c3d791797eee0eaea0e942de13acb, head
    7f8ad1cf49b89f386b85971a078b1f0927488f2a. Repo-pinned golangci-lint: 2.13.1.
  • Original lint-staged tasks and commitlint passed using a temporary per-commit hooksPath and
    --no-stash --no-hide-partially-staged; the commit left the validated tree unchanged.
  • QA report: docs/qa/reports/2026-09-09-issue-564-provider-routing.md; affected scenario:
    docs/qa/scenarios/RT-session-spawn-wake.md. Targeted teardown recorded clean: true, no survivors,
    and no killed unrelated processes.

The routing processes are controlled ACP fixtures, not two live OAuth accounts. This proves command
selection and actual subprocess execution, not live OAuth refresh or provider-service availability.
No operator login state was changed or copied. Web rendering and unrelated wake journeys were not
repeated. CodeRabbit, Greptile and current-head required CI are tracked after publication.

Impact

Cross-surface audit under docs/_memory/change-impact.md:

  • Native tools / CLI / HTTP / UDS: compozy__session_spawn, compozy spawn and agent spawn routes
    share the corrected Session Manager resolution. No IDs, input/output schemas, flags, permission
    gates, risk classifications or readiness promises are changed. Existing event consumers gain
    the fingerprint in the extensible provider-marker evidence map.
  • Extensibility / hooks / config: agent and provider command configuration retains its current
    shape. Explicit child overrides and different-provider selection remain authoritative. Spawn
    hooks, permission narrowing, TTL, caps and role selection still run through their existing owners.
    No credentials are copied or injected beyond the child's existing auth/home/environment policy.
  • Workspace isolation: inheritance requires equal workspace and profile IDs. An authorized
    foreign-workspace spawn still uses that workspace's routing. Provider ID, profile scope and
    command/account identity remain distinct; no account registry is introduced.
  • Official skill: skills/compozy/references/runtime-operations.md documents precedence,
    diagnostics and the acceptance/authentication boundary.
  • Web / Docs: existing transcript-marker consumers receive the additive evidence through their
    current schema. No Web component or cache key changes are needed. The site spawning guide and
    owning QA scenario/report co-ship the behavior and resume/fallback limits.
  • Compatibility / state: no SQLite, config.toml, persisted layout or session metadata shape
    changes; no migration, deletion or compatibility shim. Existing orphan-child fallback remains
    available and becomes observable. Internal snapshot fields are not public DTO fields.

  • make gate passes locally; this PR is delivered only after its required CI checks are green
  • New or changed behavior is covered by tests, or I explained above why not
  • If an agent wrote or co-wrote this, I named it above and verified the result myself

Summary by CodeRabbit

  • New Features

    • Spawned sessions now preserve compatible provider routing from their creator when no explicit command is provided.
    • Provider routing remains consistent when sessions are stopped, resumed, or started through replacement runtimes.
    • Session diagnostics now correlate provider routes using non-sensitive fingerprints without exposing raw commands.
  • Bug Fixes

    • Failed session starts now record provider-failure markers in session transcripts.
    • Negotiation failures that cannot load a session resource or lack session support remain excluded from replayed transcripts.
    • Failed runtime replacements preserve the previously working provider route.

@vercel

vercel Bot commented Sep 9, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
compozy-site Ready Ready Preview Sep 9, 2026 5:20pm UTC

Request Review

@coderabbitai

coderabbitai Bot commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

Warning

Review limit reached

Next included review available in 16 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 8 included reviews currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 78388968-929f-484c-90cd-7cf2ed0b5a39

📥 Commits

Reviewing files that changed from the base of the PR and between 7f8ad1c and f2b7b16.

📒 Files selected for processing (9)
  • internal/session/manager_helpers.go
  • internal/session/manager_lifecycle.go
  • internal/session/manager_prompt_runtime.go
  • internal/session/manager_start.go
  • internal/session/manager_start_accept.go
  • internal/session/manager_start_runtime.go
  • internal/session/manager_start_session.go
  • internal/session/manager_transcript_marker.go
  • internal/session/spawn_provider.go

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: e1faa2f5-ce95-4f90-aabd-21c7cc888507

📥 Commits

Reviewing files that changed from the base of the PR and between 9b422f1 and 7f8ad1c.

⛔ Files ignored due to path filters (4)
  • docs/qa/reports/2026-09-09-issue-564-provider-routing.md is excluded by !**/*.md
  • docs/qa/scenarios/RT-session-spawn-wake.md is excluded by !**/*.md
  • packages/site/content/docs/agents/spawning.mdx is excluded by !**/*.mdx
  • skills/compozy/references/runtime-operations.md is excluded by !**/*.md
📒 Files selected for processing (15)
  • internal/session/manager_helpers.go
  • internal/session/manager_lifecycle.go
  • internal/session/manager_prompt_contract_test.go
  • internal/session/manager_prompt_runtime.go
  • internal/session/manager_start.go
  • internal/session/manager_start_accept.go
  • internal/session/manager_start_runtime.go
  • internal/session/manager_start_session.go
  • internal/session/manager_start_types.go
  • internal/session/manager_stop_integration_test.go
  • internal/session/manager_transcript_marker.go
  • internal/session/provider_lifecycle_test.go
  • internal/session/session.go
  • internal/session/spawn_provider.go
  • internal/session/spawn_test.go

Included review availability: Your plan provides up to 8 included reviews per hour; 1 remains after this review.


Walkthrough

Spawned sessions now inherit compatible provider commands from their creator routes. Sessions persist resolved routing snapshots and emit command fingerprints in startup logs and provider-failure transcript markers.

Changes

Provider route inheritance

Layer / File(s) Summary
Route state and resolution
internal/session/session.go, internal/session/manager_start_types.go, internal/session/spawn_provider.go
Sessions store resolved provider routes. Spawn resolution reuses compatible creator routes, including persisted creator metadata, and generates command fingerprints.
Startup route selection
internal/session/manager_start_runtime.go, internal/session/manager_start_session.go, internal/session/manager_start_accept.go, internal/session/manager_prompt_runtime.go, internal/session/manager_start.go
Startup resolution receives context, applies spawn routing, persists the resolved route, records its fingerprint, and logs the selected provider before driver startup.
Failure diagnostics
internal/session/manager_helpers.go, internal/session/manager_lifecycle.go, internal/session/manager_transcript_marker.go
Failure logs and provider-failure transcript markers include the command fingerprint. Missing-session negotiation failures do not add replayed transcript markers.
Routing and lifecycle validation
internal/session/manager_stop_integration_test.go, internal/session/spawn_test.go, internal/session/manager_prompt_contract_test.go, internal/session/provider_lifecycle_test.go
Tests cover route precedence, persisted route reuse, fingerprint correlation, transcript markers, and replacement-start failure behavior.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to 7f8ad

Spawned commandless sessions now retain compatible creator-specific provider routing while explicit or different-provider routes remain authoritative. The change also preserves route snapshots across lifecycle events and emits command fingerprints without exposing raw commands; no current merge-blocking risk is identified.

Sequence Diagram(s)

sequenceDiagram
  participant SpawnedSession
  participant SessionManager
  participant ProviderDriver
  SpawnedSession->>SessionManager: request session start
  SessionManager->>SessionManager: resolve compatible creator provider route
  SessionManager->>ProviderDriver: start with resolved provider command
  ProviderDriver-->>SessionManager: start result
  SessionManager-->>SpawnedSession: session state and diagnostics
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 9 functions across 15 files. 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 title clearly and concisely describes the primary change: preserving provider command routing for spawned sessions.
Linked Issues check ✅ Passed The changes address issue #564 by preserving the creator's resolved provider command for eligible commandless spawned sessions. The implementation covers provider, workspace, profile, runtime, lifecyc…
Out of Scope Changes check ✅ Passed The reviewed changes are directly related to provider command routing, routing diagnostics, lifecycle behavior, replay markers, and focused tests. No unrelated code changes are evident.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/issue-564-spawn-provider-routing

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.

@greptile-apps

greptile-apps Bot commented Sep 9, 2026 •

Copy link
Copy Markdown

Greptile Summary

This PR preserves a creator session’s resolved native-provider command when spawning compatible commandless children, while retaining explicit child commands and different-provider selections as authoritative overrides.

  • Adds an in-memory provider-routing snapshot for live and replacement runtimes.
  • Restricts inherited routing to compatible workspace, profile, authentication, environment, transport, and runtime boundaries.
  • Adds SHA-256 command fingerprints to route diagnostics and provider-failure markers without persisting raw commands.
  • Retains failed starts for inspection while excluding expected ACP load-negotiation failures from replay transcripts.
  • Adds unit, integration, documentation, and QA coverage for routing precedence, resume behavior, failures, and diagnostics.
  • Changes since the previous review only add explanatory comments and remove redundant inline comments; they do not alter runtime behavior.

Confidence Score: 5/5

The PR appears safe to merge; no actionable issue remains in the reviewed changes.

The changes since the previous review are documentation-only comments around existing runtime behavior, and the full PR’s routing, lifecycle, replacement, and diagnostic changes contain no newly identified correctness or repository-rule violations.

Important Files Changed

Filename Overview
internal/session/spawn_provider.go Implements compatibility-scoped provider-command inheritance, creator-lineage resolution, routing snapshots, and diagnostic fingerprints.
internal/session/manager_start_runtime.go Integrates spawned-route resolution and command fingerprinting into runtime preparation.
internal/session/manager_prompt_runtime.go Updates the routing snapshot only after a replacement runtime has committed successfully.
internal/session/manager_lifecycle.go Records provider-failure markers for failed starts while preserving replay fallback for expected ACP negotiation failures.
internal/session/manager_transcript_marker.go Adds the bound route fingerprint to provider-failure transcript evidence.
internal/session/spawn_test.go Covers route precedence, isolation boundaries, failed-start retention, fingerprint correlation, and command-value non-disclosure.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Resolve spawned child] --> B{Explicit child command?}
    B -->|Yes| C[Use child command]
    B -->|No| D{Different provider selected?}
    D -->|Yes| E[Use selected provider command]
    D -->|No| F{Native CLI, operator home, same workspace/profile, compatible route?}
    F -->|No| G[Use child provider configuration]
    F -->|Yes| H{Creator is live?}
    H -->|Yes| I[Use creator's in-memory routing snapshot]
    H -->|No| J[Resolve persisted creator lineage]
    J --> K{Creator metadata available and compatible?}
    K -->|Yes| L[Inherit resolved creator command]
    K -->|No| M[Use child fallback and emit diagnostic]
Loading

Reviews (2): Last reviewed commit: "docs: explain provider routing lifecycle..." | Re-trigger Greptile

coderabbitai[bot]
coderabbitai Bot previously approved these changes Sep 9, 2026
@pedronauck

Copy link
Copy Markdown
Member Author

Addressed the docstring coverage warning in f2b7b16. The touched production functions now document their non-obvious routing, authentication-boundary, replacement, and replay invariants with single-line comments, following the repository's Go comment convention. No executable code or tests changed; a diff check verified that every added/removed line is a comment.

The original lint-staged tasks and commitlint passed without stash, and the working tree is clean. Existing local race/integration/gate evidence remains applicable to the unchanged behavior; current-head gates run in CI as requested. Please re-evaluate the docstring warning on the latest head.

@pedronauck

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@pedronauck
pedronauck merged commit 8100fa2 into main Sep 9, 2026
48 checks passed
@pedronauck
pedronauck deleted the fix/issue-564-spawn-provider-routing branch September 9, 2026 17:38
This was referenced Sep 27, 2026

This branch was successfully deployed

1 active deployment
Preview — f2b7b16b Deployed Sep 9, 2026 by vercel[bot]
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.

Daemon-spawned sessions ignore the creating agent's provider command and fall back to the global provider

1 participant