feat: reserve one qdrant collection per workspace

This commit is contained in:
2026-08-08 17:03:51 +02:00
parent ba1d7b0e78
commit 76bc94d5da
6 changed files with 288 additions and 107 deletions
+19 -12
View File
@@ -22,30 +22,37 @@ function readFixture(name: string): string {
}
test("migrates the current local PSD descriptor without copying secret values", () => {
const result = migrateLegacyWorkspace(readFixture("local.yaml"), { id: "local" });
const result = migrateLegacyWorkspace(readFixture("local.yaml"), { id: "local", collection: "local" });
expect(result.workspace.workspace).toMatchObject({ id: "local", schema_version: 1, language: "it" });
expect(result.state).toBe("migration_required");
expect(result.workspace.workspace).toMatchObject({ id: "local", schema_version: 3, language: "it" });
expect(JSON.stringify(result)).not.toMatch(/password:|api_key:|\$\{THT_/i);
});
test("keeps an incomplete legacy vector identity readable and explicitly migration-required", () => {
const result = migrateLegacyWorkspace(readFixture("tht.example.yaml"), { id: "example" });
test("migrates a legacy descriptor only with an explicit target collection into schema v3", () => {
const result = migrateLegacyWorkspace(readFixture("tht.example.yaml"), { id: "example", collection: "shared" });
const isOperationalWorkspace = (workspaceSchema as { isOperationalWorkspace?: unknown }).isOperationalWorkspace;
expect(result.state).toBe("migration_required");
expect(result.workspace.workspace.schema_version).toBe(1);
expect(parseWorkspaceYaml(result.source).workspace.schema_version).toBe(1);
expect(result.workspace.workspace.schema_version).toBe(3);
expect(parseWorkspaceYaml(result.source).workspace.schema_version).toBe(3);
expect(isOperationalWorkspace).toBeTypeOf("function");
expect((isOperationalWorkspace as (workspace: ReturnType<typeof parseWorkspaceYaml>) => boolean)(
parseWorkspaceYaml(result.source),
)).toBe(false);
)).toBe(true);
expect(parseWorkspaceYaml(result.source)).toMatchObject({
semantic_index: { vector_store: { engine: "qdrant", collection: "shared" } },
});
});
test("requires an explicit target collection for legacy migration", () => {
expect(() => migrateLegacyWorkspace(readFixture("local.yaml"), { id: "local" } as never)).toThrow(
/collection/i,
);
});
test("writes versioned repository artifacts atomically without replacing a prior migration", async () => {
const root = await mkdtemp(join(tmpdir(), "thoth-workspace-migrate-"));
temporaryRoots.push(root);
const migration = migrateLegacyWorkspace(readFixture("local.yaml"), { id: "local" });
const migration = migrateLegacyWorkspace(readFixture("local.yaml"), { id: "local", collection: "local" });
const destination = await writeMigratedWorkspace(migration, root);
@@ -61,11 +68,11 @@ test("CLI accepts an explicit valid ID when a legacy filename contains dots", as
const input = join(root, "psd.clinical.yaml");
writeFileSync(input, readFixture("local.yaml"));
await main(["--input", input, "--output", root, "--id", "psd-clinical"]);
await main(["--input", input, "--output", root, "--id", "psd-clinical", "--collection", "psd-clinical"]);
const destination = join(root, "workspaces", "psd-clinical.yaml");
expect(parseWorkspaceYaml(readFileSync(destination, "utf8"))).toMatchObject({
workspace: { id: "psd-clinical", schema_version: 1 },
workspace: { id: "psd-clinical", schema_version: 3 },
});
});