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
+90 -13
View File
@@ -12,6 +12,7 @@ import { PiProcessManager } from "../src/pi/pi-process-manager.js";
import { validateDeclarativePiConfig } from "../src/pi/managed-config.js";
import Fastify from "fastify";
import { sessionRoutes } from "../src/routes/sessions.js";
import { MemoryCatalogRepository } from "../src/catalog/memory-repository.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");
@@ -517,7 +518,7 @@ test("creates a session from the active immutable workspace revision", async ()
}));
});
test("hands one effective relationship snapshot to both retrieval and Pi", async () => {
test("hands one Catalog-backed runtime to both retrieval and Pi", async () => {
const effective = JSON.stringify({
schemaVersion: 1,
workspaceId: "default",
@@ -556,10 +557,9 @@ test("hands one effective relationship snapshot to both retrieval and Pi", async
});
expect(response.statusCode).toBe(200);
expect(render).toHaveBeenCalledWith("default");
expect(render).not.toHaveBeenCalled();
expect(acquireWorkspaceRuntime).toHaveBeenCalledWith(
expect.stringContaining("/default.yaml"),
effective,
);
expect(createFor).toHaveBeenCalledWith(
"effective-map",
@@ -574,27 +574,103 @@ test("hands one effective relationship snapshot to both retrieval and Pi", async
);
});
test("rejects an SSH-only workspace before persisting or starting a session", async () => {
test("refuses core admission when the workspace preprocessing fingerprint is stale", async () => {
const sessionNew = vi.fn();
const workspaceInputFingerprint = vi.fn(async () => "sha256:current");
const revision = {
id: "default",
commit: "a".repeat(40),
blob: "b".repeat(40),
snapshotPath: `/data/workspace-registry/snapshots/${"a".repeat(40)}/default.yaml`,
};
const catalogRepository = new MemoryCatalogRepository();
const database = await catalogRepository.create({
workspaceId: "default",
engine: "postgres",
databaseName: "warehouse",
schema: "public",
binding: {
transport: "postgres_direct",
host: "db.internal",
port: 5432,
username: "reader",
},
});
await catalogRepository.applySchemaSync(database.id, database.version, "all", [], {
schemaVersion: 1,
capabilities: { tables: "available", columns: "available", relationships: "available" },
tables: [],
columns: [],
relationships: [],
});
const started = await catalogRepository.beginPreprocessing("default", "sha256:previous");
expect(started.kind).toBe("started");
await catalogRepository.finishPreprocessing(
"default",
0,
"sha256:previous",
{ status: "succeeded" },
);
const app = buildApp(loadConfig({ THT_HARNESS_DIR: "../harness" }), {
thtRunner: { sessionNew, workspaceInputFingerprint } as any,
catalogRepository,
workspaceRegistry: {
acquireSessionRevision: async () => ({
workspace: operationalWorkspace("default"),
revision,
abort: async () => {},
markPersisted: async () => {},
}),
} as any,
readiness: { ensure: async () => ({ ok: true }) } as any,
getSettings: () => ({ workspace: "default", thinking: "low" }) as any,
});
const response = await app.inject({
method: "POST",
url: "/sessions",
payload: { question: "q", workspaceId: "default" },
});
expect(response.statusCode).toBe(409);
expect(response.json()).toMatchObject({ code: "preprocessing_required" });
expect(workspaceInputFingerprint).toHaveBeenCalledWith(revision.snapshotPath);
expect(sessionNew).not.toHaveBeenCalled();
});
test("rejects an SSH-only Catalog binding before persisting or starting a session", async () => {
const sessionNew = vi.fn(async () => ({ id: "must-not-exist" }));
const workspaceInputFingerprint = vi.fn(async () => "sha256:unused");
const ensure = vi.fn(async () => ({ ok: true }));
const createFor = vi.fn();
const abort = vi.fn(async () => {});
const markPersisted = vi.fn(async () => {});
const catalogRepository = new MemoryCatalogRepository();
await catalogRepository.create({
workspaceId: "ssh-workspace",
engine: "postgres",
databaseName: "postgres",
schema: "public",
binding: {
transport: "ssh_tunnel",
username: "reader",
sshHost: "bastion.internal",
sshPort: 22,
sshUsername: "tunnel",
sshTargetHost: "postgres.internal",
sshTargetPort: 5432,
},
});
const app = buildApp(loadConfig({ THT_HARNESS_DIR: "../harness" }), {
thtRunner: { sessionNew, searchPack: async () => {} } as any,
thtRunner: { sessionNew, searchPack: async () => {}, workspaceInputFingerprint } as any,
catalogRepository,
readiness: { ensure } as any,
mgr: { get: () => undefined, createFor } as any,
getSettings: () => ({ workspace: "ssh-workspace" }) as any,
workspaceRuntimeSupport: vi.fn(() => false),
workspaceRuntimeSupport: vi.fn(() => true),
workspaceRegistry: {
acquireSessionRevision: vi.fn(async () => ({
workspace: {
workspace: { schema_version: 4, id: "ssh-workspace", name: "SSH", language: "en" },
dwh: {
engine: "postgres", database: "postgres", schema: "public",
supported_transports: ["ssh_tunnel"],
},
},
workspace: operationalWorkspace("ssh-workspace"),
revision: {
id: "ssh-workspace", commit: "a".repeat(40), blob: "b".repeat(40),
snapshotPath: `/data/workspace-registry/snapshots/${"a".repeat(40)}/ssh-workspace.yaml`,
@@ -610,6 +686,7 @@ test("rejects an SSH-only workspace before persisting or starting a session", as
expect(response.statusCode).toBe(409);
expect(response.json()).toMatchObject({ code: "workspace_not_activatable" });
expect(ensure).not.toHaveBeenCalled();
expect(workspaceInputFingerprint).not.toHaveBeenCalled();
expect(sessionNew).not.toHaveBeenCalled();
expect(createFor).not.toHaveBeenCalled();
expect(abort).toHaveBeenCalledOnce();