fix: close internal semantic review gaps
This commit is contained in:
@@ -14,17 +14,34 @@ import { validateDeclarativePiConfig } from "../src/pi/managed-config.js";
|
||||
const FAKE = path.resolve("../harness/tests/fake_pi/fake_pi_rpc.mjs");
|
||||
const SCRIPT = path.resolve("../harness/tests/fake_pi/scripts/f1_disambiguation.json");
|
||||
|
||||
function operationalWorkspace(id = "default") {
|
||||
return {
|
||||
workspace: { schema_version: 3, id, name: id, language: "en" },
|
||||
dwh: {
|
||||
engine: "postgres", database: "warehouse", schema: "public",
|
||||
supported_transports: ["postgres_direct"],
|
||||
},
|
||||
semantic_index: {
|
||||
vector_store: {
|
||||
engine: "qdrant", collection: id, dimensions: 1024, distance: "cosine",
|
||||
},
|
||||
embedding: {
|
||||
provider: "ollama_internal", model: "qwen3-embedding:0.6b", dimensions: 1024,
|
||||
},
|
||||
},
|
||||
llm_policy: {
|
||||
allowed: ["zai/glm-5.2", "deepseek/deepseek-v4-pro", "local-qwen/qwen3.6-35b-a3b"],
|
||||
},
|
||||
} as const;
|
||||
}
|
||||
|
||||
const defaultWorkspaceRegistry = {
|
||||
list: vi.fn(async () => [{
|
||||
id: "default", commit: "e".repeat(40), blob: "f".repeat(40),
|
||||
snapshotPath: `/data/workspace-registry/snapshots/${"e".repeat(40)}/default.yaml`, state: "operational",
|
||||
}]),
|
||||
read: vi.fn(async (id: string) => ({
|
||||
workspace: {
|
||||
llm_policy: {
|
||||
allowed: ["zai/glm-5.2", "deepseek/deepseek-v4-pro", "local-qwen/qwen3.6-35b-a3b"],
|
||||
},
|
||||
},
|
||||
workspace: operationalWorkspace(id),
|
||||
revision: {
|
||||
id, commit: "e".repeat(40), blob: "f".repeat(40),
|
||||
snapshotPath: `/data/workspace-registry/snapshots/${"e".repeat(40)}/${id}.yaml`, state: "operational",
|
||||
@@ -33,9 +50,13 @@ const defaultWorkspaceRegistry = {
|
||||
};
|
||||
|
||||
function buildApp(config: Parameters<typeof buildRealApp>[0], deps: Record<string, unknown> = {}) {
|
||||
const thtRunner = deps.thtRunner
|
||||
? { qdrantEnsure: async () => ({ ok: true }), ...(deps.thtRunner as object) }
|
||||
: undefined;
|
||||
return buildRealApp(config, {
|
||||
workspaceRuntimeSupport: () => true,
|
||||
...deps,
|
||||
...(thtRunner ? { thtRunner } : {}),
|
||||
workspaceRegistry: { ...defaultWorkspaceRegistry, ...(deps.workspaceRegistry as object | undefined) },
|
||||
} as any);
|
||||
}
|
||||
@@ -663,7 +684,7 @@ test("session lifecycle locates a B session when installation default is A", asy
|
||||
],
|
||||
readPinned: vi.fn(async (id: string, revision: string) => {
|
||||
expect([id, revision]).toEqual(["b-workspace", "c".repeat(40)]);
|
||||
return { workspace: { llm_policy: { allowed: ["zai/glm-5.2"] } }, workspaceConfigPath: bPinnedPath };
|
||||
return { workspace: operationalWorkspace(id), workspaceConfigPath: bPinnedPath };
|
||||
}),
|
||||
} as any,
|
||||
});
|
||||
@@ -932,7 +953,7 @@ test("POST /sessions/:id/resume uses the manifest's retained workspace revision"
|
||||
getSettings: () => ({ workspace: "legacy" }) as any,
|
||||
workspaceRegistry: {
|
||||
readPinned: vi.fn(async () => ({
|
||||
workspace: { workspace: { id: "psd-clinical" } },
|
||||
workspace: operationalWorkspace("psd-clinical"),
|
||||
revision: {
|
||||
id: "psd-clinical", commit: "a".repeat(40), blob: "b".repeat(40),
|
||||
snapshotPath: "/data/workspace-registry/snapshots/aaaaaaaa/psd-clinical.yaml", state: "operational",
|
||||
@@ -968,6 +989,61 @@ test("POST /sessions/:id/resume returns a sanitized error when its retained revi
|
||||
expect(response.json()).toMatchObject({ code: "workspace_revision_unavailable" });
|
||||
});
|
||||
|
||||
test("POST /sessions/:id/resume rejects a pinned schema-v2 workspace before readiness or runtime", async () => {
|
||||
const readiness = vi.fn(async () => ({ ok: true }));
|
||||
const reopenSession = vi.fn(async () => {});
|
||||
const acquireWorkspaceRuntime = vi.fn();
|
||||
const createFor = vi.fn();
|
||||
const app = buildApp(loadConfig({ THT_HARNESS_DIR: "../harness" }), {
|
||||
thtRunner: {
|
||||
sessionShow: async () => ({
|
||||
status: "open", archived: false,
|
||||
workspace_id: "psd-clinical", workspace_revision: "a".repeat(40),
|
||||
}),
|
||||
reopenSession,
|
||||
acquireWorkspaceRuntime,
|
||||
} as any,
|
||||
readiness: { ensure: readiness } as any,
|
||||
mgr: { get: () => undefined, createFor } as any,
|
||||
getSettings: () => ({ workspace: "legacy" }) as any,
|
||||
workspaceRegistry: {
|
||||
readPinned: vi.fn(async () => ({
|
||||
workspace: {
|
||||
workspace: { schema_version: 2, id: "psd-clinical", name: "PSD", language: "it" },
|
||||
dwh: {
|
||||
engine: "postgres", database: "warehouse", schema: "public",
|
||||
supported_transports: ["rest_api"],
|
||||
},
|
||||
semantic_index: {
|
||||
vector_store: {
|
||||
engine: "pgvector", database: "warehouse", schema: "vectors",
|
||||
collection: "documents", dimensions: 768, distance: "cosine",
|
||||
supported_transports: ["rest_api"],
|
||||
},
|
||||
embedding: {
|
||||
provider: "ollama_compatible", model: "nomic-embed-text", dimensions: 768,
|
||||
},
|
||||
},
|
||||
llm_policy: { allowed: ["zai/glm-5.2"] },
|
||||
},
|
||||
workspaceConfigPath: `/data/workspace-registry/snapshots/${"a".repeat(40)}/psd-clinical.yaml`,
|
||||
})),
|
||||
} as any,
|
||||
});
|
||||
|
||||
const response = await app.inject({ method: "POST", url: "/sessions/pinned-v2/resume" });
|
||||
|
||||
expect(response.statusCode).toBe(409);
|
||||
expect(response.json()).toEqual({
|
||||
code: "workspace_revision_unavailable",
|
||||
error: "Session workspace configuration is unavailable. Check configuration and try again.",
|
||||
});
|
||||
expect(readiness).not.toHaveBeenCalled();
|
||||
expect(reopenSession).not.toHaveBeenCalled();
|
||||
expect(acquireWorkspaceRuntime).not.toHaveBeenCalled();
|
||||
expect(createFor).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("a pruned pin blocks Resume but not active or mutation lifecycle routes", async () => {
|
||||
const activePath = "/registry/snapshots/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/b-workspace.yaml";
|
||||
const prunedError = "cannot read /registry/snapshots/secret-pruned-revision/b-workspace.yaml";
|
||||
@@ -2340,11 +2416,35 @@ test("POST /sessions readiness failure returns one fixed public message without
|
||||
expect(res.statusCode).toBe(503);
|
||||
expect(res.json()).toEqual({
|
||||
error: "Session services are not ready. Check configuration and connectivity, then try again.",
|
||||
code: "workspace_not_activatable",
|
||||
});
|
||||
expect(res.body).not.toMatch(/secret\.invalid|DO_NOT_LEAK|\/srv\/private\/model-key/);
|
||||
expect(createdCalled).toBe(false);
|
||||
});
|
||||
|
||||
test.each(["semantic_index_incompatible", "workspace_not_activatable"] as const)(
|
||||
"POST /sessions does not persist when Qdrant readiness returns %s",
|
||||
async (code) => {
|
||||
const sessionNew = vi.fn(async () => ({ id: "must-not-exist" }));
|
||||
const app = buildApp(loadConfig({ THT_HARNESS_DIR: "../harness" }), {
|
||||
thtRunner: { sessionNew } as any,
|
||||
readiness: { ensure: async () => ({ ok: false, code }) } as any,
|
||||
getSettings: () => ({ workspace: "psd" }) as any,
|
||||
});
|
||||
|
||||
const response = await app.inject({
|
||||
method: "POST", url: "/sessions", payload: { question: "q" },
|
||||
});
|
||||
|
||||
expect(response.statusCode).toBe(503);
|
||||
expect(response.json()).toEqual({
|
||||
error: "Session services are not ready. Check configuration and connectivity, then try again.",
|
||||
code,
|
||||
});
|
||||
expect(sessionNew).not.toHaveBeenCalled();
|
||||
},
|
||||
);
|
||||
|
||||
test("POST /sessions returns storage 503 before creating a Pi runtime when session persistence fails", async () => {
|
||||
let piCreated = false;
|
||||
const app = buildApp(loadConfig({ THT_HARNESS_DIR: "../harness" }), {
|
||||
@@ -2365,8 +2465,10 @@ test("POST /sessions returns storage 503 before creating a Pi runtime when sessi
|
||||
|
||||
test("POST /sessions proceeds when ollamaEnsure succeeds", async () => {
|
||||
let ensureWs: string | undefined;
|
||||
const qdrantEnsure = vi.fn(async () => ({ ok: true }));
|
||||
const app = buildApp(loadConfig({ THT_HARNESS_DIR: "../harness" }), {
|
||||
thtRunner: {
|
||||
qdrantEnsure,
|
||||
ollamaEnsure: async (ws: string) => { ensureWs = ws; return { ok: true }; },
|
||||
searchPack: async () => {},
|
||||
sessionNew: async () => ({ id: "s1" }),
|
||||
@@ -2376,6 +2478,7 @@ test("POST /sessions proceeds when ollamaEnsure succeeds", async () => {
|
||||
});
|
||||
const res = await app.inject({ method: "POST", url: "/sessions", payload: { question: "q" } });
|
||||
expect(res.json()).toEqual({ id: "s1" });
|
||||
expect(qdrantEnsure).toHaveBeenCalledWith(operationalWorkspace("psd"), 60);
|
||||
expect(ensureWs).toContain(`/snapshots/${"e".repeat(40)}/psd.yaml`);
|
||||
});
|
||||
|
||||
@@ -2574,6 +2677,7 @@ test("POST /sessions/:id/resume readiness failure returns the same fixed public
|
||||
expect(res.statusCode).toBe(503);
|
||||
expect(res.json()).toEqual({
|
||||
error: "Session services are not ready. Check configuration and connectivity, then try again.",
|
||||
code: "workspace_not_activatable",
|
||||
});
|
||||
expect(res.body).not.toMatch(/secret\.invalid|DO_NOT_LEAK|\/srv\/private\/resume-key/);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user