feat: complete catalog-driven preprocessing
Publish documentation / publish (push) Successful in 2m12s

This commit is contained in:
Codex
2026-09-06 17:49:35 +02:00
parent 8707ae1d46
commit cffa60772e
141 changed files with 5898 additions and 3015 deletions
@@ -20,6 +20,7 @@ beforeEach(() => {
issuer: "test", subject: "test", roles: ["user"], permissions: ["session.use"],
isAdmin: false, csrfToken: null, session: null,
});
workspacePreferences.reset();
localStorage.clear();
FakeEventSource.instances = [];
(globalThis as any).EventSource = FakeEventSource;
@@ -29,7 +30,19 @@ beforeEach(() => {
http.get("/api/sessions", () => HttpResponse.json([])),
http.get("/api/settings", () =>
HttpResponse.json({ workspace: "default", provider: "test", model: "test", thinking: "low" })),
http.get("/api/workspaces", () => HttpResponse.json([])),
http.get("/api/workspaces", () => HttpResponse.json([{
id: "default",
name: "default",
file: "default/workspace.yaml",
displayName: "Default",
configurationState: "ready",
revision: {
id: "default",
commit: "a".repeat(40),
blob: "b".repeat(40),
snapshotPath: "/data/workspaces/default.yaml",
},
}])),
http.get("/api/models", () => HttpResponse.json({ models: [] })),
);
});
@@ -54,6 +67,26 @@ test("New session starts prewarm without delaying composer focus", async () => {
expect(composer).toHaveClass("thot-awaiting-input");
});
test("a known preprocessing requirement disables New session", async () => {
server.use(
http.get("/api/workspaces/default/preprocessing", () => HttpResponse.json({
schemaVersion: 1,
workspaceId: "default",
state: "required",
actionable: true,
clearable: true,
detail: "Catalog revision 18 is not indexed.",
metadataRevision: 18,
})),
);
renderShell();
const newSession = screen.getByRole("button", { name: "New session" });
await waitFor(() => expect(newSession).toBeDisabled());
expect(newSession).toHaveAttribute("data-navigation-state", "unavailable");
expect(newSession).toHaveAttribute("title", "Catalog revision 18 is not indexed.");
});
test("records the prompt without central duplication, then opens the live log", async () => {
let releaseCreate!: () => void;
const createMayFinish = new Promise<void>((resolve) => { releaseCreate = resolve; });