fix: resolve workspace publish conflicts

This commit is contained in:
2026-08-04 06:57:19 +02:00
parent b75b3af28e
commit 234b40e7cf
7 changed files with 218 additions and 20 deletions
@@ -46,6 +46,7 @@ test("lists registry workspaces and saves a new workspace only as a browser draf
expect(await screen.findByRole("heading", { name: "Workspace management" })).toBeVisible();
expect(await screen.findByRole("button", { name: "PSD Clinical" })).toBeVisible();
expect(screen.getByText(`Commit ${"a".repeat(12)}`)).toBeVisible();
await user.click(screen.getByRole("button", { name: "New workspace" }));
await user.clear(screen.getByLabelText("Workspace ID"));
await user.type(screen.getByLabelText("Workspace ID"), "trial-registry");
@@ -124,6 +125,38 @@ test("stages duplicate and delete operations without publishing", async () => {
expect(published).toBe(false);
});
test("saves resolved conflict choices as a rebased browser draft without publishing again", async () => {
const user = userEvent.setup();
let publishCalls = 0;
const local = { ...workspace, semantic_index: { ...workspace.semantic_index, embedding: { ...workspace.semantic_index.embedding, model: "local-model" } } };
const remote = { ...workspace, semantic_index: { ...workspace.semantic_index, embedding: { ...workspace.semantic_index.embedding, model: "remote-model" } } };
server.use(
http.post("http://localhost:8787/workspaces/validate", () => HttpResponse.json({ workspace: local, contract: {} })),
http.post("http://localhost:8787/workspaces/publish", () => {
publishCalls += 1;
return HttpResponse.json({
code: "workspace_conflict", message: "Workspace changed in the registry.", fields: ["semantic_index.embedding.model"],
expected: { commit: "a".repeat(40), blob: "b".repeat(40) }, actual: { commit: "c".repeat(40), blob: "d".repeat(40) },
base: workspace, local, remote,
}, { status: 409 });
}),
);
renderManager();
await user.click(await screen.findByRole("button", { name: "PSD Clinical" }));
await user.click(screen.getByRole("button", { name: "Publish draft" }));
await user.click(screen.getByRole("button", { name: "Validate draft" }));
await user.click(await screen.findByRole("button", { name: "Publish" }));
await user.click(screen.getByRole("button", { name: "Confirm publish" }));
await user.click(await screen.findByRole("radio", { name: "Use your draft for semantic_index.embedding.model" }));
await user.click(screen.getByRole("button", { name: "Save revised draft" }));
expect(await screen.findByText("Revised draft saved with registry revision cccccccccccc. Validate it before publishing.")).toBeVisible();
expect(localStorage.getItem("thothii.workspace-registry.v1.draft.psd-clinical")).toContain('"baseCommit":"cccccccccccccccccccccccccccccccccccccccc"');
expect(localStorage.getItem("thothii.workspace-registry.v1.draft.psd-clinical")).toContain('"baseBlob":"dddddddddddddddddddddddddddddddddddddddd"');
expect(publishCalls).toBe(1);
});
test("proposes a different valid ID when duplicating a 63-character workspace ID", async () => {
const user = userEvent.setup();
const maxId = `w${"a".repeat(62)}`;