release: ensure personal repo on POST /api/sessions (#618)

Merged
SW
5mo ago
+634-10

Releases #618 to production.

Summary

POST /api/sessions now provisions the user's (or org's) workspace repo at the canonical recoupable/<accountId> location before returning. ensurePersonalRepo idempotently returns the existing URL if the repo exists, otherwise creates a fresh private repo with auto_init: true (so the sandbox can clone immediately).

Pre-merge migration

A one-time backfill (now removed from the codebase) renamed 120 legacy <slug>-<accountId> workspace repos to bare <accountId> and removed 8 collision losers from the recoupable org. Verified post-state: 0 leading-dash outliers, 0 pending renames, final dry-run reported rename=0.

Smoke tests on preview

  • Existing-repo path (fb678396-…): returned the pre-migrated 7.9 MB repo URL
  • Create-fresh path (brand-new agent via POST /api/agents/signup): GitHub repo freshly minted at canonical URL, private=true, default_branch=main
  • Idempotency: both paths return same cloneUrl, fresh session.id, no duplicate repos
  • 3,322 / 3,322 tests pass; TS phase clean

Full audit trail in the PR thread.

🤖 Generated with Claude Code


Summary by cubic

POST /api/sessions now creates or reuses a canonical workspace repo at recoupable/<accountId> before returning, and writes its URL to the session. This applies to both personal and org-bound sessions; requests fail with 502 if provisioning can’t be completed.

  • New Features
    • Added ensurePersonalRepo to idempotently provision recoupable/<accountId> using the service GitHub token; repos are private=true with auto_init=true.
    • Introduced resolveSessionCloneUrl: uses the body’s cloneUrl when provided; otherwise provisions the workspace for auth.orgId ?? auth.accountId.
    • Updated createSessionHandler to resolve/persist clone_url and return 502 on provisioning errors.
    • New GitHub helpers: createRepository and repositoryExists (owner hard-coded to recoupable, token read via getServiceGithubToken).
    • Expanded extractOrgId to parse both recoupable/<uuid> and legacy <slug>-<uuid> URLs.