From 329e33bda0257db436baf4949a946180a988a8b7 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sun, 19 Jul 2026 15:01:28 +0100 Subject: [PATCH] Complete six-command Epiphany operator surface --- apps/bot/src/discord-bot-handlers.ts | 27 ++++++++++ package.json | 1 + .../core/src/epiphany-operator-delivery.ts | 54 ++++++++++++++++--- .../core/src/epiphany-operator-request.ts | 39 +++++++++++++- scripts/smoke-epiphany-operator-delivery.ts | 43 ++++++++++++++- scripts/smoke-epiphany-operator-request.ts | 21 +++++++- 6 files changed, 173 insertions(+), 12 deletions(-) diff --git a/apps/bot/src/discord-bot-handlers.ts b/apps/bot/src/discord-bot-handlers.ts index 4bccded..13f8ac7 100644 --- a/apps/bot/src/discord-bot-handlers.ts +++ b/apps/bot/src/discord-bot-handlers.ts @@ -155,6 +155,21 @@ export const commandDefinitions = [ .setRequired(true) .setMaxLength(2000), ), + ) + .addSubcommand((command) => + command.setName("reviews").setDescription("List bounded identities of current Mind review candidates."), + ) + .addSubcommand((command) => + command + .setName("review") + .setDescription("Commit a disposition for one exact current Mind candidate.") + .addStringOption((option) => option.setName("mind-request-id").setDescription("Exact Mind request identity.").setRequired(true).setMaxLength(256)) + .addStringOption((option) => option.setName("candidate-id").setDescription("Exact candidate identity.").setRequired(true).setMaxLength(256)) + .addStringOption((option) => option.setName("candidate-sha256").setDescription("Exact candidate SHA-256 hex digest.").setRequired(true).setMinLength(64).setMaxLength(64)) + .addIntegerOption((option) => option.setName("model-revision").setDescription("Expected canonical model revision.").setRequired(true).setMinValue(0)) + .addStringOption((option) => option.setName("model-hash").setDescription("Expected canonical model SHA-256 hex hash.").setRequired(true).setMinLength(64).setMaxLength(64)) + .addStringOption((option) => option.setName("decision").setDescription("Mind disposition.").setRequired(true) + .addChoices({ name: "Adopt", value: "adopt" }, { name: "Refuse", value: "refuse" }, { name: "Hold", value: "hold" })), ), ]; @@ -170,6 +185,18 @@ export function epiphanyOperatorCommandFromInteraction( return { kind: "wake" }; case "direct": return { kind: "directive", objective: interaction.options.getString("objective", true) }; + case "reviews": + return { kind: "reviews" }; + case "review": + return { + kind: "review", + mindRequestId: interaction.options.getString("mind-request-id", true), + candidateId: interaction.options.getString("candidate-id", true), + candidateSha256: interaction.options.getString("candidate-sha256", true), + expectedModelRevision: interaction.options.getInteger("model-revision", true), + expectedModelHash: interaction.options.getString("model-hash", true), + decision: interaction.options.getString("decision", true) as "adopt" | "refuse" | "hold", + }; default: throw new Error("Unsupported Epiphany operator subcommand."); } diff --git a/package.json b/package.json index e9ee7db..85d4972 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "agents:speech-boundary-smoke": "tsx scripts/smoke-repo-face-speech-boundary.ts", "agents:persona-feedback-observation-smoke": "tsx scripts/smoke-persona-feedback-observation.ts", "agents:epiphany-operator-request-smoke": "tsx scripts/smoke-epiphany-operator-request.ts", + "agents:epiphany-operator-delivery-smoke": "tsx scripts/smoke-epiphany-operator-delivery.ts", "agents:heartbeat-response-pressure-fixture": "tsx scripts/smoke-repo-face-response-pressure.ts", "agents:initiative-engine-smoke": "tsx scripts/smoke-persona-initiative-engine.ts", "agents:memory-projection-smoke": "node scripts/smoke-repo-face-memory-projection.mjs", diff --git a/packages/core/src/epiphany-operator-delivery.ts b/packages/core/src/epiphany-operator-delivery.ts index 5c239c2..61c3ec0 100644 --- a/packages/core/src/epiphany-operator-delivery.ts +++ b/packages/core/src/epiphany-operator-delivery.ts @@ -11,7 +11,7 @@ import { } from "./epiphany-operator-request"; export const EPIPHANY_OPERATOR_DELIVERY_TYPE = "bifrost.discord.epiphany_operator_delivery"; -export const EPIPHANY_OPERATOR_DELIVERY_SCHEMA = "bifrost.discord.epiphany_operator_delivery.v0"; +export const EPIPHANY_OPERATOR_DELIVERY_SCHEMA = "bifrost.discord.epiphany_operator_delivery.v1"; export const EPIPHANY_OPERATOR_CHECKPOINT_TYPE = "voidbot.private.epiphany_operator_delivery_checkpoint"; export const EPIPHANY_OPERATOR_CHECKPOINT_SCHEMA = "voidbot.private.epiphany_operator_delivery_checkpoint.v0"; @@ -20,7 +20,7 @@ const DELIVERY_KEYS = [ "discordGuildId", "discordChannelId", "discordInteractionId", "targetRuntimeId", "status", "disposition", "failureCode", "detail", "sealedResultPayloadSha256", "operatorStatus", "stateStatus", "coordinatorAction", "brakeStatus", "executorSignatureSha256", - "resultProviderIdentityId", "recordedAt", "privateStateExposed", + "resultProviderIdentityId", "reviews", "reviewCandidateId", "reviewDecision", "recordedAt", "privateStateExposed", ] as const; const SHA256 = /^sha256-[0-9a-f]{64}$/; @@ -45,10 +45,23 @@ export interface EpiphanyOperatorDeliveryDocument { sealedResultPayloadSha256: string; executorSignatureSha256: string; resultProviderIdentityId: string; + reviews: EpiphanyOperatorReviewSummary[]; + reviewCandidateId: string; + reviewDecision: string; recordedAt: string; privateStateExposed: false; } +export interface EpiphanyOperatorReviewSummary { + mindRequestId: string; + candidateId: string; + candidateSha256: string; + modelRevision: number; + modelHash: string; + frontierItemId: string; + requestedAt: string; +} + export interface EpiphanyOperatorDeliveryCheckpoint { schemaVersion: typeof EPIPHANY_OPERATOR_CHECKPOINT_SCHEMA; requestId: string; @@ -178,9 +191,12 @@ export async function processEpiphanyOperatorDelivery( } export function epiphanyOperatorRequestPayloadSha256(request: EpiphanyOperatorRequestDocument): string { - const compact = request.command.kind === "status" || request.command.kind === "wake" + const compact = request.command.kind === "status" || request.command.kind === "wake" || request.command.kind === "reviews" ? request.command.kind - : request.command.kind === "sleep" ? ["sleep", request.command.reason] : ["directive", request.command.objective]; + : request.command.kind === "sleep" ? ["sleep", request.command.reason] + : request.command.kind === "directive" ? ["directive", request.command.objective] + : ["review", [request.command.mindRequestId, request.command.candidateId, request.command.candidateSha256, + request.command.expectedModelRevision, request.command.expectedModelHash, request.command.decision]]; const tuple = [request.schemaName, request.schemaVersion, request.requestId, request.commandId, request.nonce, request.sourceEventId, request.sourceActorDiscordId, request.discordGuildId, request.discordChannelId, request.discordMessageId, request.targetRuntimeId, request.issuedAt, request.expiresAt, request.producerId, @@ -190,12 +206,15 @@ export function epiphanyOperatorRequestPayloadSha256(request: EpiphanyOperatorRe export function validateDelivery(value: unknown): EpiphanyOperatorDeliveryDocument { if (!isRecord(value) || Object.keys(value).sort().join("\0") !== [...DELIVERY_KEYS].sort().join("\0")) throw new Error("delivery has an inexact field set"); - for (const key of DELIVERY_KEYS) if (key !== "privateStateExposed" && typeof value[key] !== "string") throw new Error(`delivery ${key} must be a string`); + for (const key of DELIVERY_KEYS) if (key !== "privateStateExposed" && key !== "reviews" && typeof value[key] !== "string") throw new Error(`delivery ${key} must be a string`); if (value.schemaVersion !== EPIPHANY_OPERATOR_DELIVERY_SCHEMA) throw new Error("delivery schema mismatch"); if (!required(value.deliveryId as string, "deliveryId") || value.deliveryId !== value.requestId) throw new Error("delivery identity mismatch"); if (!SHA256.test(value.requestPayloadSha256 as string)) throw new Error("request payload digest malformed"); if (value.targetRuntimeId !== EPIPHANY_OPERATOR_RUNTIME_ID) throw new Error("delivery runtime mismatch"); if (value.privateStateExposed !== false) throw new Error("delivery exposes private state"); + if (!Array.isArray(value.reviews) || value.reviews.length > 10) throw new Error("delivery reviews must contain at most ten bounded summaries"); + value.reviews.forEach(validateReviewSummary); + if (typeof value.reviewCandidateId !== "string" || typeof value.reviewDecision !== "string") throw new Error("delivery review disposition bindings must be strings"); if (typeof value.detail !== "string" || value.detail.length > 512) throw new Error("delivery detail exceeds 512 characters"); for (const key of ["operatorStatus", "stateStatus", "coordinatorAction", "brakeStatus"] as const) { if (typeof value[key] !== "string" || value[key].length > 512) throw new Error(`delivery ${key} exceeds 512 characters`); @@ -206,7 +225,7 @@ export function validateDelivery(value: unknown): EpiphanyOperatorDeliveryDocume if (value.failureCode !== "") throw new Error("completed delivery has a failure code"); } else if (value.status === "refused") { if (!required(value.failureCode as string, "failureCode")) throw new Error("refused delivery lacks failure code"); - if (value.disposition !== "" || value.operatorStatus !== "" || value.stateStatus !== "" || value.coordinatorAction !== "" || value.brakeStatus !== "" || value.sealedResultPayloadSha256 !== "" || value.executorSignatureSha256 !== "" || value.resultProviderIdentityId !== "") throw new Error("refused delivery carries completed-result bindings"); + if (value.disposition !== "" || value.operatorStatus !== "" || value.stateStatus !== "" || value.coordinatorAction !== "" || value.brakeStatus !== "" || value.sealedResultPayloadSha256 !== "" || value.executorSignatureSha256 !== "" || value.resultProviderIdentityId !== "" || value.reviews.length || value.reviewCandidateId !== "" || value.reviewDecision !== "") throw new Error("refused delivery carries completed-result bindings"); } else throw new Error("delivery status is not terminal"); return value as unknown as EpiphanyOperatorDeliveryDocument; } @@ -215,6 +234,13 @@ function validateBindings(delivery: EpiphanyOperatorDeliveryDocument, request: E if (!request || request.schemaName !== EPIPHANY_OPERATOR_REQUEST_TYPE || request.schemaVersion !== EPIPHANY_OPERATOR_REQUEST_SCHEMA) throw new Error("exact operator request is unavailable"); if (delivery.requestId !== request.requestId || delivery.commandId !== request.commandId || delivery.discordGuildId !== request.discordGuildId || delivery.discordChannelId !== request.discordChannelId || delivery.discordInteractionId !== request.sourceEventId || delivery.targetRuntimeId !== request.targetRuntimeId) throw new Error("delivery does not bind the exact request"); if (delivery.requestPayloadSha256 !== epiphanyOperatorRequestPayloadSha256(request)) throw new Error("delivery request digest mismatch"); + if (request.command.kind === "reviews") { + if (delivery.reviewCandidateId !== "" || delivery.reviewDecision !== "") throw new Error("Reviews delivery carries a decision binding"); + } else if (request.command.kind === "review") { + if (delivery.reviews.length !== 0 || delivery.reviewCandidateId !== request.command.candidateId || delivery.reviewDecision !== request.command.decision) throw new Error("Review delivery does not bind the exact candidate and decision"); + } else if (delivery.reviews.length !== 0 || delivery.reviewCandidateId !== "" || delivery.reviewDecision !== "") { + throw new Error("non-review delivery carries review state"); + } if (checkpoint.requestId !== request.requestId || checkpoint.discordGuildId !== request.discordGuildId || checkpoint.discordChannelId !== request.discordChannelId || checkpoint.discordInteractionId !== request.sourceEventId || checkpoint.targetRuntimeId !== request.targetRuntimeId) throw new Error("private interaction binding mismatch"); } @@ -226,7 +252,21 @@ function renderDelivery(delivery: EpiphanyOperatorDeliveryDocument, request: Epi ? [["Operator", delivery.operatorStatus], ["State", delivery.stateStatus], ["Coordinator", delivery.coordinatorAction], ["Brakes", delivery.brakeStatus]] .filter((entry) => entry[1]).map(([label, value]) => `${label}: ${value}`).join("\n") : ""; - return `Epiphany ${command}: ${headline}.${detail}${statuses ? `\n${statuses}` : ""}\nBifrost reported this terminal result; VoidBot did not execute or inspect Epiphany state.`; + const reviews = request.command.kind === "reviews" && delivery.reviews.length + ? `\n${delivery.reviews.map((review) => `- ${review.candidateId} | request ${review.mindRequestId} | revision ${review.modelRevision} | frontier ${review.frontierItemId}`).join("\n")}` + : ""; + const decision = request.command.kind === "review" && delivery.reviewCandidateId + ? `\nCandidate ${delivery.reviewCandidateId}: ${delivery.reviewDecision}` : ""; + return `Epiphany ${command}: ${headline}.${detail}${statuses ? `\n${statuses}` : ""}${reviews}${decision}\nBifrost reported this terminal result; VoidBot did not execute or inspect Epiphany state.`; +} + +function validateReviewSummary(value: unknown): void { + const keys = ["mindRequestId", "candidateId", "candidateSha256", "modelRevision", "modelHash", "frontierItemId", "requestedAt"]; + if (!isRecord(value) || Object.keys(value).sort().join("\0") !== keys.sort().join("\0")) throw new Error("review summary has an inexact field set"); + for (const key of ["mindRequestId", "candidateId", "frontierItemId"] as const) if (!required(value[key], key) || value[key].length > 256) throw new Error(`review summary ${key} is invalid`); + for (const key of ["candidateSha256", "modelHash"] as const) if (!/^[0-9a-f]{64}$/.test(value[key])) throw new Error(`review summary ${key} is invalid`); + if (!Number.isSafeInteger(value.modelRevision) || value.modelRevision < 0) throw new Error("review summary modelRevision is invalid"); + if (!Number.isFinite(Date.parse(value.requestedAt))) throw new Error("review summary requestedAt is invalid"); } function requestDefinition(define: any): unknown { return define({ type: EPIPHANY_OPERATOR_REQUEST_TYPE, schemaName: EPIPHANY_OPERATOR_REQUEST_TYPE, schemaId: EPIPHANY_OPERATOR_REQUEST_SCHEMA, schemaVersion: EPIPHANY_OPERATOR_REQUEST_SCHEMA, contentHash: EPIPHANY_OPERATOR_REQUEST_SCHEMA, global: false, name: "requestId", schema: { parse: (v: unknown) => v } }); } diff --git a/packages/core/src/epiphany-operator-request.ts b/packages/core/src/epiphany-operator-request.ts index 30faad6..adbc014 100644 --- a/packages/core/src/epiphany-operator-request.ts +++ b/packages/core/src/epiphany-operator-request.ts @@ -2,7 +2,7 @@ import { createRequire } from "node:module"; import { resolve } from "node:path"; export const EPIPHANY_OPERATOR_REQUEST_TYPE = "voidbot.discord.epiphany_operator_request"; -export const EPIPHANY_OPERATOR_REQUEST_SCHEMA = "voidbot.discord.epiphany_operator_request.v0"; +export const EPIPHANY_OPERATOR_REQUEST_SCHEMA = "voidbot.discord.epiphany_operator_request.v1"; export const EPIPHANY_OPERATOR_RUNTIME_ID = "epiphany-yggdrasil"; const MAX_REASON_LENGTH = 500; const MAX_OBJECTIVE_LENGTH = 2_000; @@ -12,7 +12,17 @@ export type EpiphanyOperatorCommand = | { kind: "status" } | { kind: "sleep"; reason: string } | { kind: "wake" } - | { kind: "directive"; objective: string }; + | { kind: "directive"; objective: string } + | { kind: "reviews" } + | { + kind: "review"; + mindRequestId: string; + candidateId: string; + candidateSha256: string; + expectedModelRevision: number; + expectedModelHash: string; + decision: "adopt" | "refuse" | "hold"; + }; export interface EpiphanyOperatorRequestInput { interactionId: string; @@ -122,11 +132,36 @@ function validateCommand(command: EpiphanyOperatorCommand): EpiphanyOperatorComm return { kind: "wake" }; case "directive": return { kind: "directive", objective: boundedText(command.objective, "directive objective", MAX_OBJECTIVE_LENGTH) }; + case "reviews": + return { kind: "reviews" }; + case "review": { + const candidateSha256 = sha256(command.candidateSha256, "candidate sha256"); + const expectedModelHash = sha256(command.expectedModelHash, "expected model hash"); + if (!Number.isSafeInteger(command.expectedModelRevision) || command.expectedModelRevision < 0) { + throw new Error("expected model revision must be a non-negative safe integer."); + } + if (!["adopt", "refuse", "hold"].includes(command.decision)) throw new Error("review decision is invalid."); + return { + kind: "review", + mindRequestId: boundedText(command.mindRequestId, "Mind request id", 256), + candidateId: boundedText(command.candidateId, "candidate id", 256), + candidateSha256, + expectedModelRevision: command.expectedModelRevision, + expectedModelHash, + decision: command.decision, + }; + } default: throw new Error("Unsupported Epiphany operator command."); } } +function sha256(value: string, label: string): string { + const normalized = value?.trim(); + if (!/^[0-9a-f]{64}$/.test(normalized)) throw new Error(`${label} must be 64 lowercase hexadecimal characters.`); + return normalized; +} + function boundedText(value: string, label: string, maxLength: number): string { const normalized = value?.trim(); if (!normalized) throw new Error(`${label} is required.`); diff --git a/scripts/smoke-epiphany-operator-delivery.ts b/scripts/smoke-epiphany-operator-delivery.ts index c5f39a6..76969eb 100644 --- a/scripts/smoke-epiphany-operator-delivery.ts +++ b/scripts/smoke-epiphany-operator-delivery.ts @@ -29,7 +29,7 @@ assert.notEqual(digest, epiphanyOperatorRequestPayloadSha256({ ...request, disco assert.notEqual(digest, epiphanyOperatorRequestPayloadSha256({ ...request, command: { kind: "wake" } })); const completed: EpiphanyOperatorDeliveryDocument = { - schemaVersion: "bifrost.discord.epiphany_operator_delivery.v0", + schemaVersion: "bifrost.discord.epiphany_operator_delivery.v1", deliveryId: request.requestId, requestId: request.requestId, requestPayloadSha256: digest, commandId: request.commandId, discordGuildId: request.discordGuildId, discordChannelId: request.discordChannelId, discordInteractionId: request.sourceEventId, @@ -38,6 +38,7 @@ const completed: EpiphanyOperatorDeliveryDocument = { coordinatorAction: "none", brakeStatus: "engaged", sealedResultPayloadSha256: `sha256-${"a".repeat(64)}`, executorSignatureSha256: `sha256-${"b".repeat(64)}`, resultProviderIdentityId: "bifrost-yggdrasil", + reviews: [], reviewCandidateId: "", reviewDecision: "", recordedAt: "2026-07-19T12:00:01.000Z", privateStateExposed: false, }; assert.equal(validateDelivery(completed).status, "completed"); @@ -46,6 +47,7 @@ const refused: EpiphanyOperatorDeliveryDocument = { ...completed, status: "refused", disposition: "", failureCode: "brakes_engaged", detail: "refused", operatorStatus: "", stateStatus: "", coordinatorAction: "", brakeStatus: "", sealedResultPayloadSha256: "", executorSignatureSha256: "", resultProviderIdentityId: "", + reviews: [], reviewCandidateId: "", reviewDecision: "", }; assert.equal(validateDelivery(refused).status, "refused"); @@ -62,6 +64,8 @@ rejects({ deliveryId: "collision" }, /identity/); rejects({ executorSignatureSha256: "signature-bytes" }, /sealed bindings/); rejects({ resultProviderIdentityId: "" }, /resultProviderIdentityId|sealed bindings/); rejects({ surprisePrivatePayload: "secret" }, /field set/); +rejects({ reviews: [{ mindRequestId: "m", candidateId: "c", candidateSha256: "1".repeat(64), modelRevision: 1, modelHash: "2".repeat(64), frontierItemId: "f", requestedAt: "2026-07-19T12:00:00Z", proposalText: "private" }] }, /inexact field set/); +rejects({ reviews: Array.from({ length: 11 }, () => ({ mindRequestId: "m", candidateId: "c", candidateSha256: "1".repeat(64), modelRevision: 1, modelHash: "2".repeat(64), frontierItemId: "f", requestedAt: "2026-07-19T12:00:00Z" })) }, /at most ten/); assert.throws(() => validateDelivery({ ...refused, brakeStatus: "not empty" }), /completed-result bindings/); assert.throws(() => validateDelivery({ ...refused, failureCode: "" }), /failureCode|failure code/); @@ -102,6 +106,43 @@ let collisionCheckpoint = { ...baseCheckpoint, observedDeliverySha256: `sha256-$ assert.equal(await processEpiphanyOperatorDelivery(completed, request, collisionCheckpoint, async () => { throw new Error("must not edit"); }, async (next) => { collisionCheckpoint = next; }), "failed"); assert.match(collisionCheckpoint.lastError, /collision/); +const reviewRequest = buildEpiphanyOperatorRequest({ + interactionId: "interaction-review", actorDiscordId: "owner-1", guildId: "guild-1", channelId: "channel-1", + command: { kind: "reviews" }, issuedAt: "2026-07-19T12:00:00.000Z", +}, "voidbot-yggdrasil"); +const reviewDelivery: EpiphanyOperatorDeliveryDocument = { + ...completed, + deliveryId: reviewRequest.requestId, requestId: reviewRequest.requestId, commandId: reviewRequest.commandId, + discordInteractionId: reviewRequest.sourceEventId, requestPayloadSha256: epiphanyOperatorRequestPayloadSha256(reviewRequest), + reviews: [{ mindRequestId: "mind-1", candidateId: "candidate-1", candidateSha256: "1".repeat(64), modelRevision: 7, + modelHash: "2".repeat(64), frontierItemId: "frontier-1", requestedAt: "2026-07-19T11:59:00Z" }], +}; +let renderedReview = ""; +let reviewCheckpoint = { ...baseCheckpoint, requestId: reviewRequest.requestId, discordInteractionId: reviewRequest.sourceEventId }; +assert.equal(await processEpiphanyOperatorDelivery(reviewDelivery, reviewRequest, reviewCheckpoint, + async (_app, _token, content) => { renderedReview = content; }, async (next) => { reviewCheckpoint = next; }), "responded"); +assert.match(renderedReview, /candidate-1.*request mind-1.*revision 7.*frontier frontier-1/); +assert.doesNotMatch(renderedReview, /proposal|private|sha256/i); +let substitutedCheckpoint = { ...baseCheckpoint }; +assert.equal(await processEpiphanyOperatorDelivery({ ...completed, reviews: reviewDelivery.reviews }, request, substitutedCheckpoint, + async () => { throw new Error("must not render substituted review state"); }, async (next) => { substitutedCheckpoint = next; }), "failed"); +assert.match(substitutedCheckpoint.lastError, /non-review/); + +const decisionRequest = buildEpiphanyOperatorRequest({ + interactionId: "interaction-decision", actorDiscordId: "owner-1", guildId: "guild-1", channelId: "channel-1", + command: { kind: "review", mindRequestId: "mind-1", candidateId: "candidate-1", candidateSha256: "1".repeat(64), + expectedModelRevision: 7, expectedModelHash: "2".repeat(64), decision: "hold" }, issuedAt: "2026-07-19T12:00:00.000Z", +}, "voidbot-yggdrasil"); +const decisionDelivery: EpiphanyOperatorDeliveryDocument = { + ...completed, deliveryId: decisionRequest.requestId, requestId: decisionRequest.requestId, commandId: decisionRequest.commandId, + discordInteractionId: decisionRequest.sourceEventId, requestPayloadSha256: epiphanyOperatorRequestPayloadSha256(decisionRequest), + reviewCandidateId: "candidate-1", reviewDecision: "hold", +}; +let decisionCheckpoint = { ...baseCheckpoint, requestId: decisionRequest.requestId, discordInteractionId: decisionRequest.sourceEventId }; +assert.equal(await processEpiphanyOperatorDelivery({ ...decisionDelivery, reviewCandidateId: "candidate-2" }, decisionRequest, decisionCheckpoint, + async () => { throw new Error("must not render substituted decision"); }, async (next) => { decisionCheckpoint = next; }), "failed"); +assert.match(decisionCheckpoint.lastError, /exact candidate and decision/); + const temp = await mkdtemp(join(tmpdir(), "voidbot-epiphany-delivery-")); try { const bifrostRoot = resolve("../Bifrost"); diff --git a/scripts/smoke-epiphany-operator-request.ts b/scripts/smoke-epiphany-operator-request.ts index b5d84fa..a6df0b7 100644 --- a/scripts/smoke-epiphany-operator-request.ts +++ b/scripts/smoke-epiphany-operator-request.ts @@ -18,7 +18,16 @@ assert.equal(isExactDiscordOwner("tier-one-1", owner), false); const epiphany = commandDefinitions.map((command) => command.toJSON()).find((command) => command.name === "epiphany"); assert.ok(epiphany, "slash command is registered"); -assert.deepEqual(epiphany.options?.map((option) => option.name), ["status", "sleep", "wake", "direct"]); +assert.deepEqual(epiphany.options?.map((option) => option.name), ["status", "sleep", "wake", "direct", "reviews", "review"]); + +const protocolPath = process.env.EPIPHANY_OPERATOR_PROTOCOL_FIXTURE + ?? resolve("..", "EpiphanyAgent", ".epiphany-smoke", "operator-command-interop-rust", "protocol.json"); +const protocol = JSON.parse(await readFile(protocolPath, "utf8")); +assert.equal(protocol.schemaVersion, "epiphany.operator_command.protocol_fixture.v1"); +assert.equal(protocol.admissionSchemaVersion, "bifrost.operator_command.delivery.v1"); +assert.equal(protocol.resultSchemaVersion, "epiphany.operator_command.result.v1"); +assert.deepEqual(protocol.commands.map((command: { kind: string }) => command.kind), ["status", "sleep", "wake", "directive", "reviews", "review"]); +assert.deepEqual(protocol.reviewDecisions, ["adopt", "refuse", "hold"]); const issuedAt = "2026-07-19T12:00:00.000Z"; const commands = [ @@ -26,6 +35,8 @@ const commands = [ { kind: "sleep", reason: "Operator is packing the workstation." } as const, { kind: "wake" } as const, { kind: "directive", objective: "Inspect the current domain map and propose the next bounded improvement." } as const, + { kind: "reviews" } as const, + protocol.commands[5], ]; for (const [index, command] of commands.entries()) { const id = `interaction-${index}`; @@ -80,6 +91,11 @@ await assert.rejects( ); assert.throws(() => buildEpiphanyOperatorRequest({ ...input, command: { kind: "sleep", reason: "x".repeat(501) } }, "voidbot-yggdrasil"), /500/); assert.throws(() => buildEpiphanyOperatorRequest({ ...input, command: { kind: "directive", objective: "x".repeat(2001) } }, "voidbot-yggdrasil"), /2000/); +const review = commands[5] as Extract<(typeof commands)[number], { kind: "review" }>; +assert.deepEqual(Object.keys(protocol.commands[5]).sort(), ["candidateId", "candidateSha256", "decision", "expectedModelHash", "expectedModelRevision", "kind", "mindRequestId"].sort()); +assert.throws(() => buildEpiphanyOperatorRequest({ ...input, command: { ...review, candidateSha256: "0".repeat(63) } }, "voidbot-yggdrasil"), /64 lowercase/); +assert.throws(() => buildEpiphanyOperatorRequest({ ...input, command: { ...review, expectedModelRevision: -1 } }, "voidbot-yggdrasil"), /non-negative/); +assert.throws(() => buildEpiphanyOperatorRequest({ ...input, command: { ...review, decision: "approve" as "adopt" } }, "voidbot-yggdrasil"), /decision/); const botSource = await readFile(resolve("apps/bot/src/discord-bot.ts"), "utf8"); const messageCreate = botSource.slice(botSource.indexOf("client.on(Events.MessageCreate"), botSource.indexOf("client.on(Events.MessageUpdate")); @@ -88,7 +104,8 @@ assert.ok(!messageCreate.includes("submitEpiphanyOperatorRequest"), "ordinary me console.log(JSON.stringify({ schemaVersion: EPIPHANY_OPERATOR_REQUEST_SCHEMA, - commands: ["status", "sleep", "wake", "direct"], + commands: ["status", "sleep", "wake", "direct", "reviews", "review"], + rustProtocolFixtureConsumed: true, exactOwnerOnly: true, ordinaryMessagesRemainFeedbackOnly: true, localExecutionAuthorized: false,