166 lines
5.6 KiB
Markdown
166 lines
5.6 KiB
Markdown
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 <qdrant-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.
|