313 lines
12 KiB
JavaScript
313 lines
12 KiB
JavaScript
import { createHash } from "node:crypto";
|
|
|
|
const SOURCE_LAYERS = new Set([
|
|
"HUMAN_DIRECT_LANGUAGE",
|
|
"MODEL_RESPONSE",
|
|
"LATER_CORRECTION",
|
|
"REALITY_EVIDENCE",
|
|
]);
|
|
const CLAIM_LAYERS = new Set([
|
|
"LANGUAGE_ONTOLOGY",
|
|
"LANGUAGE_SIMULATION",
|
|
"ENGINEERING_PROPOSAL",
|
|
"REALITY_CLAIM",
|
|
]);
|
|
const CHANNEL_MODES = new Set([
|
|
"CONVERSATION_ONLY",
|
|
"LANGUAGE_ARCHITECTURE",
|
|
"REALITY_EXECUTION",
|
|
]);
|
|
const INTENTS = new Set([
|
|
"IDENTIFY",
|
|
"ENTER_CHANNEL",
|
|
"CONVERSE",
|
|
"DECLARE",
|
|
"REQUEST_PLAN",
|
|
"REQUEST_BROADCAST",
|
|
"ACTIVATE_LOCAL_MODE",
|
|
"DRAFT_BROADCAST",
|
|
"RECEIVE_DOCUMENT",
|
|
"PUBLISH_EXTERNAL",
|
|
"QUERY_STATUS",
|
|
"PROPOSE_HANDOFF",
|
|
"ACCEPT_HANDOFF",
|
|
"REQUEST_REALITY_ACTION",
|
|
"REPORT_RESULT",
|
|
"CORRECT",
|
|
"END_INTERACTION",
|
|
"EXIT_CHANNEL",
|
|
"SEAL_LANGUAGE_RECORD",
|
|
"ORDINARY_DIALOGUE",
|
|
]);
|
|
const SESSION_STATES = new Set(["DISCONNECTED", "IDENTIFIED", "CHANNEL_ACTIVE", "STANDBY", "CLOSED"]);
|
|
const BROADCAST_STATES = new Set(["CLOSED", "ARMED", "DRAFTED", "HUMAN_CONFIRMED", "RECEIVED_LOCAL", "EXTERNAL_IN_PROGRESS", "EXTERNAL_VERIFIED"]);
|
|
const HANDOFF_STATES = new Set(["NONE", "PROPOSED", "TARGET_ACCEPTED", "ACTIVE", "REVOKED"]);
|
|
|
|
function requiredString(event, field) {
|
|
if (typeof event[field] !== "string" || event[field].trim() === "") {
|
|
throw new TypeError(`${field} must be a non-empty string`);
|
|
}
|
|
}
|
|
|
|
function normalizedEvidence(event) {
|
|
if (event.evidence === undefined) return [];
|
|
if (!Array.isArray(event.evidence)) throw new TypeError("evidence must be an array");
|
|
return event.evidence.map((item, index) => {
|
|
if (!item || typeof item !== "object") throw new TypeError(`evidence[${index}] must be an object`);
|
|
requiredString(item, "type");
|
|
requiredString(item, "ref");
|
|
return {
|
|
type: item.type,
|
|
ref: item.ref,
|
|
verified: item.verified === true,
|
|
external: item.external === true,
|
|
proves: Array.isArray(item.proves) ? item.proves.filter((value) => typeof value === "string") : [],
|
|
does_not_prove: Array.isArray(item.does_not_prove) ? item.does_not_prove.filter((value) => typeof value === "string") : [],
|
|
};
|
|
});
|
|
}
|
|
|
|
function normalizedRequiredProofs(event) {
|
|
if (event.required_proof === undefined) return [];
|
|
const values = Array.isArray(event.required_proof) ? event.required_proof : [event.required_proof];
|
|
if (values.some((value) => typeof value !== "string" || value.trim() === "")) {
|
|
throw new TypeError("required_proof must be a non-empty string or an array of non-empty strings");
|
|
}
|
|
return [...new Set(values)];
|
|
}
|
|
|
|
function hasExternalReceipt(evidence, requiredProofs = []) {
|
|
const declaredProofs = new Set(
|
|
evidence
|
|
.filter((item) => item.type === "EXECUTION_RECEIPT" && item.external && item.verified)
|
|
.flatMap((item) => item.proves ?? []),
|
|
);
|
|
const hasReceipt = evidence.some((item) => item.type === "EXECUTION_RECEIPT" && item.external && item.verified);
|
|
return hasReceipt && requiredProofs.every((proof) => declaredProofs.has(proof));
|
|
}
|
|
|
|
function hasCurrentAuthorization(event) {
|
|
const authorization = event.authorization;
|
|
return Boolean(
|
|
authorization &&
|
|
authorization.current === true &&
|
|
authorization.scoped === true &&
|
|
authorization.unexpired === true &&
|
|
typeof authorization.ref === "string" &&
|
|
authorization.ref.length > 0,
|
|
);
|
|
}
|
|
|
|
function stableHash(value) {
|
|
const keys = [];
|
|
JSON.stringify(value, (key, item) => {
|
|
keys.push(key);
|
|
return item;
|
|
});
|
|
keys.sort();
|
|
return createHash("sha256").update(JSON.stringify(value, keys)).digest("hex");
|
|
}
|
|
|
|
export function compileChannelReceipt(event) {
|
|
if (!event || typeof event !== "object" || Array.isArray(event)) {
|
|
throw new TypeError("event must be an object");
|
|
}
|
|
for (const field of ["event_id", "channel_id", "channel_mode", "source_layer", "actor_id", "intent", "claim_layer"]) {
|
|
requiredString(event, field);
|
|
}
|
|
if (!SOURCE_LAYERS.has(event.source_layer)) throw new TypeError("unsupported source_layer");
|
|
if (!CLAIM_LAYERS.has(event.claim_layer)) throw new TypeError("unsupported claim_layer");
|
|
if (!CHANNEL_MODES.has(event.channel_mode)) throw new TypeError("unsupported channel_mode");
|
|
if (!INTENTS.has(event.intent)) throw new TypeError("unsupported intent");
|
|
|
|
const evidence = normalizedEvidence(event);
|
|
const requiredProofs = normalizedRequiredProofs(event);
|
|
const externalReceipt = hasExternalReceipt(evidence, requiredProofs);
|
|
const authorized = hasCurrentAuthorization(event);
|
|
const isRealityClaim = event.claim_layer === "REALITY_CLAIM";
|
|
const isSimulation = event.claim_layer === "LANGUAGE_SIMULATION";
|
|
const isConversationOnly = event.channel_mode === "CONVERSATION_ONLY";
|
|
const currentStates = {
|
|
session: event.current_states?.session ?? "DISCONNECTED",
|
|
broadcast: event.current_states?.broadcast ?? "CLOSED",
|
|
handoff: event.current_states?.handoff ?? "NONE",
|
|
};
|
|
if (!SESSION_STATES.has(currentStates.session)) throw new TypeError("unsupported current session state");
|
|
if (!BROADCAST_STATES.has(currentStates.broadcast)) throw new TypeError("unsupported current broadcast state");
|
|
if (!HANDOFF_STATES.has(currentStates.handoff)) throw new TypeError("unsupported current handoff state");
|
|
const nextStates = { ...currentStates };
|
|
let correctionState = "CLEAN";
|
|
|
|
let effect = "LANGUAGE_STATE_ONLY";
|
|
let realityStatus = "NOT_APPLICABLE";
|
|
let nextStep = "CONTINUE_IN_CHANNEL";
|
|
const boundaries = [];
|
|
|
|
if (["IDENTIFY", "ENTER_CHANNEL", "CONVERSE", "ORDINARY_DIALOGUE", "END_INTERACTION", "EXIT_CHANNEL"].includes(event.intent)) {
|
|
effect = "NO_EXTERNAL_EFFECT";
|
|
}
|
|
if (event.intent === "IDENTIFY") nextStates.session = "IDENTIFIED";
|
|
if (event.intent === "ENTER_CHANNEL") nextStates.session = "CHANNEL_ACTIVE";
|
|
if (["END_INTERACTION", "EXIT_CHANNEL"].includes(event.intent)) {
|
|
nextStates.session = "CLOSED";
|
|
nextStep = "STOP_OUTPUT_AFTER_MINIMAL_CLOSE_RECEIPT";
|
|
boundaries.push("NO_ROLEPLAY_EPILOGUE_AFTER_CLOSE");
|
|
}
|
|
if (currentStates.session === "CLOSED" && !["IDENTIFY", "ENTER_CHANNEL"].includes(event.intent)) {
|
|
effect = "NO_EXTERNAL_EFFECT";
|
|
realityStatus = "REJECTED";
|
|
nextStep = "REQUIRE_NEW_HUMAN_DIRECT_CHANNEL_ENTRY";
|
|
boundaries.push("CLOSED_SESSION_CANNOT_REACTIVATE_ITSELF");
|
|
}
|
|
if (event.intent === "REQUEST_PLAN" || event.claim_layer === "ENGINEERING_PROPOSAL") {
|
|
effect = "PLAN_ONLY";
|
|
realityStatus = "PROPOSED";
|
|
nextStep = "REVIEW_PLAN";
|
|
}
|
|
if (event.intent === "ACTIVATE_LOCAL_MODE") {
|
|
nextStates.broadcast = "ARMED";
|
|
effect = "LANGUAGE_STATE_ONLY";
|
|
nextStep = "WAIT_FOR_DOCUMENT_OR_DRAFT_REQUEST";
|
|
}
|
|
if (event.intent === "DRAFT_BROADCAST") {
|
|
nextStates.broadcast = "DRAFTED";
|
|
effect = "PLAN_ONLY";
|
|
nextStep = "HUMAN_REVIEW_DRAFT";
|
|
}
|
|
if (event.intent === "RECEIVE_DOCUMENT") {
|
|
nextStates.broadcast = "RECEIVED_LOCAL";
|
|
effect = "LANGUAGE_STATE_ONLY";
|
|
nextStep = "RECORD_LOCAL_RECEIPT_ONLY";
|
|
boundaries.push("RECEIVED_LOCAL_IS_NOT_EXTERNAL_PUBLISH");
|
|
}
|
|
if (isSimulation) {
|
|
effect = "LANGUAGE_STATE_ONLY";
|
|
realityStatus = "NOT_APPLICABLE";
|
|
boundaries.push("LANGUAGE_SIMULATION_ONLY");
|
|
}
|
|
if (isRealityClaim) {
|
|
realityStatus = externalReceipt ? "VERIFIED" : "UNVERIFIED";
|
|
effect = externalReceipt ? "RESULT_RECORDED" : "NO_EXTERNAL_EFFECT";
|
|
nextStep = externalReceipt ? "READ_BACK_EXTERNAL_RESULT" : "PROVIDE_EXTERNAL_EVIDENCE";
|
|
}
|
|
if (event.intent === "REQUEST_REALITY_ACTION") {
|
|
if (isConversationOnly) {
|
|
effect = "NO_EXTERNAL_EFFECT";
|
|
realityStatus = "REJECTED";
|
|
nextStep = "MOVE_TO_AUTHORIZED_EXECUTION_CHANNEL";
|
|
boundaries.push("CONVERSATION_CHANNEL_CANNOT_EXECUTE");
|
|
} else if (!authorized) {
|
|
effect = "PENDING_AUTHORIZATION";
|
|
realityStatus = "PENDING_AUTHORIZATION";
|
|
nextStep = "OBTAIN_CURRENT_SCOPED_AUTHORIZATION";
|
|
} else {
|
|
effect = "EXECUTION_ELIGIBLE";
|
|
realityStatus = externalReceipt ? "VERIFIED" : "IN_PROGRESS_WITH_RECEIPT";
|
|
nextStep = externalReceipt ? "READ_BACK_EXTERNAL_RESULT" : "EXECUTE_THROUGH_AUTHORIZED_ADAPTER";
|
|
}
|
|
}
|
|
if (event.intent === "PUBLISH_EXTERNAL") {
|
|
if (!authorized) {
|
|
effect = "PENDING_AUTHORIZATION";
|
|
realityStatus = "PENDING_AUTHORIZATION";
|
|
nextStep = "OBTAIN_CURRENT_SCOPED_PUBLISH_AUTHORIZATION";
|
|
} else if (externalReceipt) {
|
|
effect = "RESULT_RECORDED";
|
|
realityStatus = "VERIFIED";
|
|
nextStates.broadcast = "EXTERNAL_VERIFIED";
|
|
nextStep = "READ_BACK_EXTERNAL_PUBLICATION";
|
|
} else {
|
|
effect = "EXECUTION_ELIGIBLE";
|
|
realityStatus = "IN_PROGRESS_WITH_RECEIPT";
|
|
nextStates.broadcast = "EXTERNAL_IN_PROGRESS";
|
|
nextStep = "PUBLISH_THROUGH_AUTHORIZED_ADAPTER_AND_CAPTURE_READBACK";
|
|
}
|
|
}
|
|
if (event.intent === "REQUEST_BROADCAST") {
|
|
if (isConversationOnly || !authorized) {
|
|
effect = "LANGUAGE_STATE_ONLY";
|
|
realityStatus = isRealityClaim ? "UNVERIFIED" : "NOT_APPLICABLE";
|
|
nextStep = "OBTAIN_EXPLICIT_BROADCAST_AUTHORIZATION";
|
|
boundaries.push("DRAFT_OR_LANGUAGE_BROADCAST_ONLY");
|
|
} else {
|
|
effect = "EXECUTION_ELIGIBLE";
|
|
realityStatus = externalReceipt ? "VERIFIED" : "IN_PROGRESS_WITH_RECEIPT";
|
|
nextStep = externalReceipt ? "READ_BACK_EXTERNAL_RESULT" : "SEND_THROUGH_AUTHORIZED_BROADCAST_ADAPTER";
|
|
}
|
|
}
|
|
if (event.intent === "CORRECT") {
|
|
effect = "LANGUAGE_STATE_ONLY";
|
|
realityStatus = "NOT_APPLICABLE";
|
|
nextStep = "CREATE_CORRECTION_CANDIDATE_AND_RETEST";
|
|
correctionState = event.prior_receipt_id ? "SUPERSEDED" : "CORRECTION_PENDING";
|
|
}
|
|
if (event.intent === "QUERY_STATUS") {
|
|
effect = externalReceipt ? "RESULT_RECORDED" : "NO_EXTERNAL_EFFECT";
|
|
realityStatus = externalReceipt ? "VERIFIED" : "UNVERIFIED";
|
|
nextStep = externalReceipt ? "REPORT_OBSERVED_STATUS_WITH_SCOPE" : "REPORT_NO_OBSERVATION_SOURCE";
|
|
if (!externalReceipt) boundaries.push("DO_NOT_GUESS_STATUS_WITHOUT_OBSERVATION");
|
|
}
|
|
if (event.intent === "PROPOSE_HANDOFF") {
|
|
nextStates.handoff = "PROPOSED";
|
|
effect = "LANGUAGE_STATE_ONLY";
|
|
realityStatus = "PROPOSED";
|
|
nextStep = "WAIT_FOR_INDEPENDENT_TARGET_ACCEPTANCE";
|
|
boundaries.push("PROPOSAL_IS_NOT_ACTIVE_HANDOFF");
|
|
}
|
|
if (event.intent === "ACCEPT_HANDOFF") {
|
|
const accepted = event.handoff?.target_acceptance === true && event.handoff?.target_id === event.actor_id;
|
|
if (currentStates.handoff !== "PROPOSED" || !accepted) {
|
|
effect = "NO_EXTERNAL_EFFECT";
|
|
realityStatus = "REJECTED";
|
|
nextStep = "OBTAIN_INDEPENDENT_ACCEPTANCE_FROM_TARGET";
|
|
boundaries.push("MODEL_CANNOT_ACCEPT_FOR_TARGET");
|
|
} else {
|
|
nextStates.handoff = "TARGET_ACCEPTED";
|
|
effect = "LANGUAGE_STATE_ONLY";
|
|
realityStatus = "PROPOSED";
|
|
nextStep = "APPLY_SCOPED_HANDOFF_AND_CAPTURE_READBACK";
|
|
}
|
|
}
|
|
|
|
if (event.source_layer === "MODEL_RESPONSE") {
|
|
boundaries.push("MODEL_RESPONSE_IS_NOT_EXTERNAL_EVIDENCE");
|
|
}
|
|
if (event.intent === "IDENTIFY") boundaries.push("IDENTIFICATION_IS_NOT_BROADCAST");
|
|
if (event.intent === "ENTER_CHANNEL") boundaries.push("CHANNEL_ENTRY_IS_NOT_PERSONA_OR_AUTHORITY_TRANSFER");
|
|
if (requiredProofs.length > 0 && !externalReceipt) boundaries.push("EVIDENCE_SCOPE_DOES_NOT_PROVE_REQUESTED_EFFECT");
|
|
if (!externalReceipt && ["VERIFIED", "RESULT_RECORDED"].includes(realityStatus)) {
|
|
throw new Error("reality verification requires a verified external execution receipt");
|
|
}
|
|
|
|
const receipt = {
|
|
schema: "guanghu.channel-receipt/v1",
|
|
contract_id: "GH-CHANNEL-RECEIPT-0001",
|
|
event_id: event.event_id,
|
|
received: true,
|
|
identified: event.intent === "IDENTIFY" ? event.actor_id : null,
|
|
channel: { id: event.channel_id, mode: event.channel_mode },
|
|
intent: event.intent,
|
|
claim: { layer: event.claim_layer, source_layer: event.source_layer },
|
|
affected_layer: isRealityClaim ? "REALITY_EVIDENCE_LAYER" : "LANGUAGE_LAYER",
|
|
effect,
|
|
reality_status: realityStatus,
|
|
evidence,
|
|
required_proof: requiredProofs,
|
|
states: {
|
|
before: currentStates,
|
|
after: nextStates,
|
|
correction: correctionState,
|
|
},
|
|
supersedes: correctionState === "SUPERSEDED" ? [event.prior_receipt_id] : [],
|
|
boundaries: [...new Set(boundaries)],
|
|
next_step: nextStep,
|
|
};
|
|
return { ...receipt, receipt_id: `GH-CR-${stableHash(receipt).slice(0, 20)}` };
|
|
}
|
|
|
|
export function verifyChannelReceipt(receipt) {
|
|
if (!receipt || receipt.schema !== "guanghu.channel-receipt/v1") return false;
|
|
if (receipt.reality_status === "VERIFIED") return hasExternalReceipt(receipt.evidence ?? [], receipt.required_proof ?? []);
|
|
if (receipt.effect === "RESULT_RECORDED") return hasExternalReceipt(receipt.evidence ?? [], receipt.required_proof ?? []);
|
|
return true;
|
|
}
|