feat(observatory): add durable recorded compute queue

This commit is contained in:
DCCONSTRUCTIONS
2026-08-31 01:04:25 +03:00
parent e72609120f
commit d67e86176e
23 changed files with 6300 additions and 369 deletions
@@ -156,6 +156,40 @@ test("Observatory preflight sends the exact selected definition and never submit
assert.equal(preflight.submissionAllowed, false);
});
test("Observatory dynamic preflight admits only an explicit queueable response", async () => {
const selected = (await fetchObservatoryLaboratorySetups("source-a", {
fetcher: async () => new Response(JSON.stringify({
schema_version: "missioncore.observatory-laboratory-setup-catalog/v1",
source_session_id: "source-a",
setups: [setup()],
authority,
}), { status: 200 }),
})).setups[0];
const preflight = await preflightObservatoryLaboratorySetup("source-a", selected, {
fetcher: async () => new Response(JSON.stringify({
schema_version: "missioncore.observatory-run-preflight/v1",
source_session_id: "source-a",
setup_id: selected.setupId,
definition_sha256: "b".repeat(64),
outcome: "queueable",
submission_allowed: true,
checks: [{
check_id: "durable-queue",
outcome: "pass",
reason_code: "exact-binding-ready",
message: "Точный источник и очередь готовы.",
}],
existing_result_ids: [],
executor: setup().executor,
authority,
}), { status: 200 }),
});
assert.equal(preflight.outcome, "queueable");
assert.equal(preflight.submissionAllowed, true);
});
test("Observatory setup contract rejects authority escalation and response drift", async () => {
const escalated = setup();
escalated.authority = { ...authority, commands_enabled: true };
@@ -0,0 +1,179 @@
import assert from "node:assert/strict";
import { after, before, test } from "node:test";
import { createServer } from "vite";
let server;
let fetchObservatoryRecordedJobs;
let submitObservatoryRecordedJob;
let ObservatoryRecordedJobContractError;
const authority = {
commands_enabled: false,
actuation_allowed: false,
navigation_or_safety_accepted: false,
production_accepted: false,
};
function job(state = "queued") {
return {
schema_version: "missioncore.observatory-recorded-job/v1",
job_id: "observatory-run-0123456789abcdef0123456789abcdef",
idempotency_key: "observatory-ui:source-a:m49-tgs:request-a",
request_sha256: "1".repeat(64),
identity_sha256: "2".repeat(64),
submission_receipt_sha256: "3".repeat(64),
source: {
session_id: "source-a",
catalog_sha256: "4".repeat(64),
bundle_sha256: "5".repeat(64),
capability_manifest_sha256: "6".repeat(64),
adapter: {
adapter_id: "ravnoves00-m49-source-pack",
version: 1,
adapter_sha256: "7".repeat(64),
},
},
setup: {
setup_id: "m49-tgs",
definition_id: "m49-tgs",
definition_version: 1,
definition_sha256: "8".repeat(64),
},
executor: {
release_id: "m49-tgs-release",
release_sha256: "9".repeat(64),
image_sha256: "a".repeat(64),
model_release_ids: [],
learned_models: [],
model_manifest_sha256: "b".repeat(64),
resource_profile_id: "m49-tgs-cpu",
resource_profile_sha256: "c".repeat(64),
},
checkpoint_policy: {
mode: "non-checkpointable",
allowed_checkpoints: [],
last_checkpoint_id: null,
},
priority: { class: "recorded", rank: 100, server_owned: true },
state,
preemption_requested: state === "preemption-pending",
restart_from_zero: state === "paused",
preemption_receipt_sha256: null,
claim_generation: 0,
result: state === "succeeded"
? { result_id: "m49-result", sha256: "d".repeat(64) }
: null,
terminal: state === "failed"
? { code: "worker-failed", message: "Worker завершил расчёт с ошибкой." }
: null,
created_at_utc: "2026-08-31T10:00:00Z",
updated_at_utc: "2026-08-31T10:00:01Z",
authority,
};
}
before(async () => {
server = await createServer({
appType: "custom",
logLevel: "silent",
server: { middlewareMode: true },
});
({
fetchObservatoryRecordedJobs,
submitObservatoryRecordedJob,
ObservatoryRecordedJobContractError,
} = await server.ssrLoadModule("/src/core/observatory/recordedJobs.ts"));
});
after(async () => {
await server?.close();
});
test("Observatory reads the exact session/setup queue without polling", async () => {
const calls = [];
const jobs = await fetchObservatoryRecordedJobs("source-a", "m49-tgs", {
fetcher: async (input, init) => {
calls.push({ input: String(input), init });
return new Response(JSON.stringify({
schema_version: "missioncore.observatory-recorded-job-list/v1",
items: [job("running")],
authority,
}), { status: 200 });
},
});
assert.equal(calls.length, 1);
assert.equal(
calls[0].input,
"/api/v1/observatory/runs?source_session_id=source-a&setup_id=m49-tgs&limit=20",
);
assert.equal(calls[0].init.method, "GET");
assert.equal(jobs[0].state, "running");
assert.equal(jobs[0].definitionSha256, "8".repeat(64));
});
test("Observatory submits only public identities and accepts every durable state", async () => {
const states = [
"accepted",
"queued",
"claimed",
"running",
"paused",
"preemption-pending",
"succeeded",
"failed",
"reconciliation-required",
];
for (const state of states) {
let request;
const result = await submitObservatoryRecordedJob(
"source-a",
"m49-tgs",
"observatory-ui:source-a:m49-tgs:request-a",
{
fetcher: async (input, init) => {
request = { input: String(input), init };
return new Response(JSON.stringify(job(state)), { status: 200 });
},
},
);
assert.equal(result.state, state);
assert.equal(request.input, "/api/v1/observatory/runs");
assert.equal(request.init.method, "POST");
assert.deepEqual(JSON.parse(request.init.body), {
schema_version: "missioncore.observatory-recorded-run-submit/v1",
idempotency_key: "observatory-ui:source-a:m49-tgs:request-a",
source_session_id: "source-a",
setup_id: "m49-tgs",
});
}
});
test("Observatory queue contract rejects authority escalation and response drift", async () => {
const escalated = job();
escalated.authority = { ...authority, commands_enabled: true };
await assert.rejects(
fetchObservatoryRecordedJobs("source-a", "m49-tgs", {
fetcher: async () => new Response(JSON.stringify({
schema_version: "missioncore.observatory-recorded-job-list/v1",
items: [escalated],
authority,
}), { status: 200 }),
}),
ObservatoryRecordedJobContractError,
);
const drifted = job();
drifted.worker_command = "forbidden";
await assert.rejects(
submitObservatoryRecordedJob(
"source-a",
"m49-tgs",
"observatory-ui:source-a:m49-tgs:request-a",
{ fetcher: async () => new Response(JSON.stringify(drifted), { status: 200 }) },
),
ObservatoryRecordedJobContractError,
);
});
@@ -144,11 +144,11 @@ test("Observatory mounts the one shared canonical replay only after explicit adm
);
assert.match(
styles,
/\.observatory-catalog-bar h3,[\s\S]*\.observatory-session-summary h3,[\s\S]*\.observatory-setup-detail h3,[\s\S]*\.observatory-evidence h3 \{[\s\S]*font-size: var\(--nodedc-font-size-lg\);/,
/\.observatory-catalog-bar h3,[\s\S]*\.observatory-session-summary h3,[\s\S]*\.observatory-evidence h3 \{[\s\S]*font-size: var\(--nodedc-font-size-lg\);/,
);
assert.match(
styles,
/@container observatory-session \(max-width: 56rem\) \{[\s\S]*\.observatory-session-summary \{[\s\S]*grid-template-columns: minmax\(0, 1fr\);/,
/@container observatory-session \(max-width: 46rem\) \{[\s\S]*\.observatory-session-summary \{[\s\S]*grid-template-columns: minmax\(0, 1fr\);/,
);
assert.match(
styles,
@@ -206,23 +206,67 @@ test("Observatory rename and delete use admitted projection mutations and canoni
assert.match(hook, /applyObservatoryCatalogMutationOverlay\(/);
});
test("Observatory configurator keeps selection and preflight read-only", async () => {
const [workspace, setupDetail, setupHook] = await Promise.all([
test("Observatory keeps one compact selector axis without the obsolete setup detail", async () => {
const [workspace, styles, setupHook, jobsHook] = await Promise.all([
read("workspaces/observatory/ObservatoryWorkspace.tsx"),
read("workspaces/observatory/ObservatorySetupDetail.tsx"),
read("styles/observatory.css"),
read("core/observatory/useObservatoryLaboratorySetups.ts"),
read("core/observatory/useObservatoryRecordedJobs.ts"),
]);
assert.match(workspace, /className="observatory-catalog-bar" padding="sm"/);
assert.match(workspace, /label="Выбрать сохранённую сессию"/);
assert.match(workspace, /label="Выбрать сетап лаборатории"/);
assert.match(workspace, /Показан последний каталог сетапов/);
assert.match(setupDetail, /Проверить совместимость/);
assert.doesNotMatch(
setupDetail,
/Рассчитать лабораторию|definitionSha256|<small>\{result\.resultId\}/,
assert.doesNotMatch(workspace, /Выбор меняет только читаемую карточку/);
assert.doesNotMatch(workspace, /ObservatorySetupDetail|observatory-setup-detail/);
assert.doesNotMatch(styles, /observatory-setup-detail|observatory-setup-results/);
assert.match(workspace, /useObservatoryRecordedJobs/);
assert.match(
workspace,
/runPreflight\?\.outcome === "queueable"[\s\S]*runPreflight\.submissionAllowed/,
);
assert.match(
workspace,
/canSubmitRecordedJob \? \([\s\S]*>\s*Рассчитать\s*<\/Button>/,
);
assert.match(workspace, /accepted: \{ label: "Принят"/);
assert.match(workspace, /queued: \{ label: "Ждёт Worker"/);
assert.match(workspace, /claimed: \{ label: "Назначен Worker"/);
assert.match(workspace, /running: \{ label: "Выполняется"/);
assert.match(workspace, /paused: \{ label: "Пауза: live-поток"/);
assert.match(
workspace,
/"preemption-pending": \{[\s\S]*label: "Ждём подтверждения остановки"/,
);
assert.match(workspace, /succeeded: \{ label: "Готово"/);
assert.match(workspace, /failed: \{ label: "Ошибка расчёта"/);
assert.match(workspace, /"reconciliation-required": \{ label: "Нужна сверка"/);
assert.match(
jobsHook,
/OPEN_STATES[\s\S]*"preemption-pending",[\s\S]*"reconciliation-required"/,
);
assert.match(jobsHook, /return `observatory-ui:\$\{entropy\}`;/);
assert.doesNotMatch(jobsHook, /observatory-ui:[^`]*sourceSessionId|\.slice\(0, 160\)/);
assert.match(workspace, /recordedJobsController\.refresh\(\)/);
assert.doesNotMatch(`${workspace}\n${jobsHook}`, /setInterval|setTimeout/);
assert.match(
styles,
/\.observatory-catalog-bar__controls \{[\s\S]*min-width: 0;[\s\S]*flex: 1 1 auto;[\s\S]*flex-wrap: nowrap;[\s\S]*justify-content: flex-end;/,
);
assert.match(
styles,
/\.observatory-catalog-bar__run \{[\s\S]*display: flex;[\s\S]*align-items: center;/,
);
assert.match(
styles,
/@media \(max-width: 920px\)[\s\S]*\.observatory-catalog-bar,[\s\S]*\.observatory-catalog-bar__controls,[\s\S]*flex-direction: column;/,
);
assert.match(setupHook, /catalog\?\.sourceSessionId === sourceSessionId/);
assert.match(setupHook, /preflightRequest\.current\?\.abort\(\)/);
assert.match(setupHook, /preflightRequest\.current !== request/);
assert.doesNotMatch(`${workspace}\n${setupDetail}\n${setupHook}`, /\/api\/v1\/observatory\/runs/);
assert.match(
setupHook,
/state !== "ready" \|\| !selectedSetup \|\| preflight\.kind !== "idle"[\s\S]*void check\(\)/,
);
});