release: ensure personal repo on POST /api/sessions (#618)
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, freshsession.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
ensurePersonalRepoto idempotently provisionrecoupable/<accountId>using the service GitHub token; repos areprivate=truewithauto_init=true. - Introduced
resolveSessionCloneUrl: uses the body’scloneUrlwhen provided; otherwise provisions the workspace forauth.orgId ?? auth.accountId. - Updated
createSessionHandlerto resolve/persistclone_urland return 502 on provisioning errors. - New GitHub helpers:
createRepositoryandrepositoryExists(owner hard-coded torecoupable, token read viagetServiceGithubToken). - Expanded
extractOrgIdto parse bothrecoupable/<uuid>and legacy<slug>-<uuid>URLs.
- Added