Task 2 report — Make collection ownership unique in the Git registry Summary - Implemented unique Qdrant collection ownership enforcement during registry snapshot activation. - Registry session revision leases now reject `migration_required` descriptors. - Legacy migration now requires an explicit target collection and emits schema v3 descriptors. - Preserved active snapshot rollback behavior on invalid pulled snapshots. RED evidence Focused RED command from the brief: ```bash cd backend npx vitest run test/workspace-registry.test.ts test/workspaces-migrate-legacy.test.ts \ -t "collection|migration_required" ``` Observed failures before implementation: - `rejects duplicate schema v3 collection ownership and keeps the previous active snapshot` - `registry.pull()` resolved instead of rejecting. - `does not acquire a session revision lease for a migration_required workspace` - `acquireSessionRevision()` resolved instead of rejecting. - `migrates a legacy descriptor only with an explicit target collection into schema v3` - received schema version `1` instead of `3`. - `requires an explicit target collection for legacy migration` - migration did not throw without a collection. GREEN evidence Focused GREEN command from the brief: ```bash cd backend npx vitest run test/workspace-registry.test.ts test/workspaces-migrate-legacy.test.ts \ -t "collection|migration_required" ``` Fresh result after implementation: - 2 files passed - 4 tests passed - 0 failures Additional verification run after final cleanup: ```bash cd backend npx vitest run test/routes-workspaces.test.ts npx vitest run npx tsc --noEmit -p . git diff --check ``` Fresh results: - `test/routes-workspaces.test.ts`: 7 passed - full backend Vitest: 39 files passed, 454 tests passed - backend typecheck: passed - `git diff --check`: passed Changed files - `backend/src/workspaces/registry.ts` - `backend/src/workspaces/migrate-legacy.ts` - `backend/test/workspace-registry.test.ts` - `backend/test/workspaces-migrate-legacy.test.ts` - `backend/test/routes-workspaces.test.ts` Why one extra file changed - `backend/test/routes-workspaces.test.ts` needed updating because Task 1 made schema v3 the only operational descriptor shape, and the route test still assumed the old pre-Task-3 runtime behavior. Updating that expectation was necessary to keep the required backend suite verification meaningful. Implementation notes - Duplicate collection detection is enforced only for operational schema v3 descriptors by tracking `collection -> workspaceId` during activation. - Duplicate failures are sanitized back to `workspace_invalid` / `Workspace repository content is invalid`. - `acquireSessionRevision()` now fails closed for `migration_required` revisions. - Legacy migration CLI now requires `--collection `. - Legacy migration output is schema v3 with the fixed internal semantic contract: - `vector_store.engine = qdrant` - explicit `collection` - embedding provider `ollama_internal` - embedding model `qwen3-embedding:0.6b` self-review - Confirmed invalid pulled snapshots do not replace the previous active snapshot. - Confirmed duplicate collection enforcement does not affect legacy migration-required descriptors. - Confirmed create/update publication tests still pass with unique per-workspace collections. - Confirmed no JSON stdout contract regressions in the migration CLI. - Kept runtime/data mutation scope descriptor-only; no user workspace repo or Qdrant data changes. Concerns - No code concerns remaining for Task 2. - One deliberate scope exception: a route test was updated to align with the already-established Task 1 / Task 3 fail-closed contract. Fix round 1 Scope - Restored meaningful route-level diagnoser coverage without reopening schema-v3 semantic runtime paths. - Added direct schema-v2 registry coverage for `migration_required` listing and lease rejection. Covering test files - `backend/test/routes-workspaces.test.ts` - `backend/test/workspace-registry.test.ts` RED command and output Command: ```bash cd backend npx vitest run test/routes-workspaces.test.ts test/workspace-registry.test.ts ``` Observed result on top of `76bc94d` after adding the restored/new assertions: - 2 files passed - 37 tests passed - 0 failures Why no RED appeared: - The review items exposed missing/weakened coverage, not a production behavior bug. - `/workspaces/:id/test` already reaches the diagnoser for resolvable legacy v2 descriptors. - Schema-v3 `/workspaces/:id/test` already fails closed before diagnoser entry. - Schema-v2 descriptors were already listed as `migration_required` and already rejected by `acquireSessionRevision()`. GREEN command and output Command: ```bash cd backend npx vitest run test/routes-workspaces.test.ts test/workspace-registry.test.ts npx tsc --noEmit -p . ``` Fresh results: - covering tests: 2 files passed, 37 tests passed - backend typecheck: passed Changed files - `backend/test/routes-workspaces.test.ts` - `backend/test/workspace-registry.test.ts` - `.superpowers/sdd/2026-08-08-internal-qdrant-ollama/task-2-report.md` What changed - Split route coverage so `POST /workspaces/validate` still checks canonical validation independently. - Restored route-level diagnoser coverage through a migration-required schema-v2 descriptor with resolvable legacy bindings. - Added an explicit schema-v3 fail-closed regression for `POST /workspaces/:id/test`. - Added a direct schema-v2 registry regression proving `list()` returns `migration_required` and `acquireSessionRevision()` rejects it. Concerns - No production concerns. This round only tightened coverage and corrected the weakened test expectation.