Skip to content

Add Session.codeProvider for cross-backend pairing#420

Merged
dgershman merged 1 commit into
mainfrom
feature/crow-414-session-code-provider
Jun 4, 2026
Merged

Add Session.codeProvider for cross-backend pairing#420
dgershman merged 1 commit into
mainfrom
feature/crow-414-session-code-provider

Conversation

@dgershman
Copy link
Copy Markdown
Collaborator

Closes #414

Summary

Follow-up to #410 / ADR 0005. Adds Session.codeProvider: Provider? so a Corveil-tasked session can pair with a GitHub or GitLab CodeBackend — the protocol split from #411 already supported this in principle; the model now represents it.

nil means "follow provider"; callers resolve with session.codeProvider ?? session.provider. No persisted-state migration: legacy sessions decode codeProvider = nil and the lookup-site fallback routes them to the same backend they used pre-split.

Changes

  • Session model — new optional field, init parameter, and decodeIfPresent in the custom decoder (same pattern as lastReviewedHeadSha / autoMergeEnabledAt).
  • SessionService.findPRLink — takes an explicit provider: parameter; sole caller in recoverOrphan passes session.codeProvider ?? session.provider ?? .github. The in-line gh pr list shell-out fallback (only reached when no ProviderManager is wired) stays GitHub-only — unchanged.
  • Tests
    • SessionModelTests — extends round-trip / nil-defaults / default-values tests; adds sessionBackwardCompatDecodingWithoutCodeProvider for legacy JSON.
    • SessionRepositoryTests.savePreservesAllOptionalFields — round-trips codeProvider: .gitlab alongside provider: .github to prove the field is independently persisted.

IssueTracker is intentionally unchanged: all three of its session.provider reads are task-backend / issue-lifecycle decisions, not codeBackend lookups.

Test plan

  • swift test --package-path Packages/CrowCore --filter SessionModelTests — 16 tests pass (incl. new backward-compat decode).
  • swift test --package-path Packages/CrowPersistence --filter SessionRepositoryTests — 11 tests pass.
  • swift test --package-path Packages/CrowProvider --filter BackendsTests — sanity check on factory; 15 tests pass.
  • swift build --arch arm64 — clean build, no callers broke.
  • Manual smoke: open existing state.json from a pre-CROW-414 Crow build — confirm sessions hydrate with codeProvider == nil and PR discovery still finds the right backend.

🤖 Generated with Claude Code

Follow-up to #410 / ADR 0005. Lets a Corveil-tasked session pair with a
GitHub or GitLab CodeBackend by storing the code-source provider
independently from the task-source provider.

- Add `Session.codeProvider: Provider?` (nil means "follow `provider`").
- Update `findPRLink` in SessionService to take an explicit provider
  parameter; resolve at the call site via `codeProvider ?? provider
  ?? .github`. Legacy in-line `gh pr list` fallback stays GitHub-only.
- Backward-compat decode test for state.json predating CROW-414, plus
  persistence round-trip coverage.

🐦‍⬛ Generated with Claude Code, orchestrated by Crow

Co-Authored-By: Claude <noreply@anthropic.com>
Crow-Session: F8E8977A-340D-4DF2-AA3C-3B1C21BCDD26
@dgershman dgershman requested a review from dhilgaertner as a code owner June 4, 2026 02:27
@dgershman dgershman added the crow:merge Crow auto-merge on green label Jun 4, 2026
Copy link
Copy Markdown
Contributor

@dhilgaertner dhilgaertner left a comment

Choose a reason for hiding this comment

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

Code & Security Review

Critical Issues

None.

Security Review

Strengths:

  • No new external input, shell surface, or credential handling. codeProvider is an internal Provider enum routed only to ProviderManager.codeBackend(for:); the inline gh pr list shell-out fallback is unchanged and still GitHub-only.
  • Backward-compatible decoding via decodeIfPresent — legacy state.json without codeProvider decodes to nil with no migration, no crash (verified by sessionBackwardCompatDecodingWithoutCodeProvider).

Concerns:

  • None.

Code Quality

  • Model (Session.swift): codeProvider follows the exact established pattern for optional fields — synthesized CodingKeys/encoder pick it up automatically, custom decoder mirrors lastReviewedHeadSha/autoMergeEnabledAt. Clean.
  • findPRLink (SessionService.swift:1147): confirmed to be the only code-backend resolution site in the app (grep of codeBackend(for). Parameterizing it completes the scope; resolution session.codeProvider ?? session.provider ?? .github is correct, and codeBackend(for: .corveil) safely returns nil.
  • recoverOrphan behavior change: the lookup shifts from hardcoded .github to ticket.provider. This is an improvement, not a regression — a GitLab-ticketed orphan now queries the GitLab backend instead of GitHub, matching ADR 0005 intent.
  • IssueTracker left unchanged: verified the three session.provider reads (ticket-URL provider resolution :1490, closed-issue completion :2319, markInReview gating :2547) are all task-source / issue-lifecycle decisions — none are code-backend lookups. Correctly out of scope.
  • Tests: round-trip, nil-defaults, and independent-persistence (codeProvider: .gitlab alongside provider: .github) all cover the field well. Ran locally: SessionModelTests (16 pass), SessionRepositoryTests (11 pass).

Summary Table

Color Meaning Verdict effect
Red Must fix Request changes
Yellow Should fix Request changes
Green Consider Approve allowed

Recommendation: Approve — driven by [0 Red, 0 Yellow, 0 Green] findings. Small, focused, well-tested follow-up that faithfully implements ADR 0005 / CROW-414 with full backward compatibility.

🐦‍⬛ Reviewed by Crow via Claude Code

@dgershman dgershman merged commit 2a9f63f into main Jun 4, 2026
3 checks passed
@dgershman dgershman deleted the feature/crow-414-session-code-provider branch June 4, 2026 02:32
dgershman added a commit that referenced this pull request Jun 4, 2026
## Summary

- `AutoRespondCoordinator` selected the CLI binary name (`gh` vs `glab`)
with six inline `provider == .gitlab ? "glab" : "gh"` / `if provider ==
.gitlab` checks. With the `TaskBackend` / `CodeBackend` split from #410
/ ADR 0005 in place, this belongs on the backend.
- Add `cliName: String` to `CodeBackend`; implement `"gh"` on
`GitHubCodeBackend` and `"glab"` on `GitLabCodeBackend`.
- Inject `ProviderManager` into `AutoRespondCoordinator`; resolve a
`CodeBackend` per session via `session.codeProvider ?? session.provider`
(the convention from `Session.swift` / #420). Corveil-or-unknown
sessions fall back to GitHub tooling — matches the prior `?? .github`
default.
- Change `AutoRespondPrompts.build` and `QuickActionPrompts.build` to
take a `CodeBackend` instead of a `Provider`. Prose branches still read
`codeBackend.provider`; CLI tokens read `codeBackend.cliName`.

Prompt text is byte-identical for every existing branch (`cliName`
returns the same string previously hardcoded), so no behavior change.

## Test plan

- [x] `swift build --arch arm64` — clean
- [x] `swift build --arch arm64 --build-tests` — clean
(`QuickActionPromptsTests`, `AutoRespondCoordinatorReviewSessionTests`
updated to construct `CodeBackend` / `ProviderManager`)
- [x] `rg 'provider == \.gitlab \? "glab" : "gh"' Sources/ Packages/
Tests/` returns zero matches
- [ ] Test bundle execution blocked locally by `swiftpm-xctest-helper`
being x86_64-only on this Xcode install (build is arm64); CI runs the
suite.

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

Labels

crow:auto crow:merge Crow auto-merge on green

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Session.codeProvider for cross-backend pairing

2 participants