From 97115c21593e147dbcda259443517237d88d6516 Mon Sep 17 00:00:00 2001 From: Jeon Mingyu Date: Sat, 18 Jul 2026 23:51:16 +0900 Subject: [PATCH 01/27] Add control-kernel contracts --- src/control-kernel-types.ts | 124 ++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 src/control-kernel-types.ts diff --git a/src/control-kernel-types.ts b/src/control-kernel-types.ts new file mode 100644 index 0000000..488de79 --- /dev/null +++ b/src/control-kernel-types.ts @@ -0,0 +1,124 @@ +export type ControlRunStatus = "completed" | "failed" | "blocked"; +export type ControlToolCallStatus = "completed" | "failed" | "blocked"; +export type EvidenceClassification = "public" | "internal" | "confidential" | "restricted"; +export type EvidenceSourceType = "document" | "database" | "api" | "human" | "derived"; +export type HardFailureSeverity = "critical" | "major"; +export type MetricOperator = "gte" | "lte" | "eq"; + +export type ControlModelRef = { + readonly provider: string; + readonly name: string; + readonly version: string; +}; + +export type ControlToolCall = { + readonly toolId: string; + readonly toolVersion: string; + readonly action: string; + readonly status: ControlToolCallStatus; + readonly inputHash: string; + readonly outputHash: string | null; +}; + +export type ControlRunEvent = { + readonly schemaVersion: "boulder.control.run-event.v1"; + readonly runId: string; + readonly caseId: string; + readonly taskId: string; + readonly agentId: string; + readonly agentVersion: string; + readonly profileId: string; + readonly profileVersion: string; + readonly parentRunId: string | null; + readonly idempotencyKey: string; + readonly startedAt: string; + readonly completedAt: string; + readonly evidenceCutoffAt: string; + readonly evidenceManifestHash: string; + readonly policyId: string; + readonly policyVersion: string; + readonly policyHash: string; + readonly promptVersion: string; + readonly model: ControlModelRef; + readonly toolCalls: readonly ControlToolCall[]; + readonly artifactHashes: readonly string[]; + readonly metrics: Readonly>; + readonly hardFailureSignals: readonly string[]; + readonly status: ControlRunStatus; +}; + +export type ControlEvidenceEntry = { + readonly evidenceId: string; + readonly sha256: string; + readonly sourceType: EvidenceSourceType; + readonly classification: EvidenceClassification; + readonly sourceVersion: string; + readonly observedAt: string; + readonly sourceUriHash: string | null; +}; + +export type ControlEvidenceManifest = { + readonly schemaVersion: "boulder.control.evidence-manifest.v1"; + readonly manifestId: string; + readonly caseId: string; + readonly evidenceCutoffAt: string; + readonly generatedAt: string; + readonly entries: readonly ControlEvidenceEntry[]; +}; + +export type HardFailureRule = { + readonly id: string; + readonly signal: string; + readonly severity: HardFailureSeverity; + readonly description: string; +}; + +export type MetricRule = { + readonly metricId: string; + readonly operator: MetricOperator; + readonly threshold: number; + readonly description: string; +}; + +export type ControlPolicy = { + readonly schemaVersion: "boulder.control.policy.v1"; + readonly id: string; + readonly version: string; + readonly blockingSeverities: readonly HardFailureSeverity[]; + readonly hardFailures: readonly HardFailureRule[]; + readonly metricRules: readonly MetricRule[]; +}; + +export type TriggeredHardFailure = HardFailureRule & { readonly blocked: boolean }; +export type MetricCheck = MetricRule & { readonly actual: number | null; readonly status: "pass" | "fail" }; + +export type ControlEvaluation = { + readonly schemaVersion: "boulder.control.evaluation.v1"; + readonly runId: string; + readonly caseId: string; + readonly policyId: string; + readonly policyVersion: string; + readonly status: "eligible" | "blocked"; + readonly evidenceManifestHash: string; + readonly policyHash: string; + readonly triggeredHardFailures: readonly TriggeredHardFailure[]; + readonly metricChecks: readonly MetricCheck[]; + readonly issues: readonly string[]; +}; + +export type ControlDecisionSeal = { + readonly schemaVersion: "boulder.control.decision-seal.v1"; + readonly algorithm: "sha256-canonical-json"; + readonly runId: string; + readonly caseId: string; + readonly taskId: string; + readonly policyId: string; + readonly policyVersion: string; + readonly sealedAt: string; + readonly runHash: string; + readonly evidenceManifestHash: string; + readonly policyHash: string; + readonly sealHash: string; +}; + +export type SealVerification = { readonly status: "valid" | "invalid"; readonly issues: readonly string[] }; From 960637a005a2609aaf4d3516edd822356ac56766 Mon Sep 17 00:00:00 2001 From: Jeon Mingyu Date: Sat, 18 Jul 2026 23:52:11 +0900 Subject: [PATCH 02/27] Add control-kernel validators --- src/control-kernel-validation.ts | 192 +++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 src/control-kernel-validation.ts diff --git a/src/control-kernel-validation.ts b/src/control-kernel-validation.ts new file mode 100644 index 0000000..255b4a2 --- /dev/null +++ b/src/control-kernel-validation.ts @@ -0,0 +1,192 @@ +import type { + ControlDecisionSeal, + ControlEvidenceManifest, + ControlPolicy, + ControlRunEvent +} from "./control-kernel-types"; + +type JsonRecord = Record; +const ID = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/; +const HASH = /^[a-f0-9]{64}$/; +const RUN_STATUSES = ["completed", "failed", "blocked"] as const; +const TOOL_STATUSES = ["completed", "failed", "blocked"] as const; +const CLASSIFICATIONS = ["public", "internal", "confidential", "restricted"] as const; +const SOURCE_TYPES = ["document", "database", "api", "human", "derived"] as const; +const SEVERITIES = ["critical", "major"] as const; +const OPERATORS = ["gte", "lte", "eq"] as const; + +export function validateControlRunEvent(value: unknown): readonly string[] { + if (!record(value)) return ["run-event:object-required"]; + const issues: string[] = []; + exact(value, "schemaVersion", "boulder.control.run-event.v1", "run-event", issues); + for (const field of ["runId", "caseId", "taskId", "agentId", "agentVersion", "profileId", "profileVersion", "idempotencyKey", "policyId", "policyVersion", "promptVersion"]) { + validId(value, field, "run-event", issues); + } + if (value.parentRunId !== null && !isId(value.parentRunId)) issues.push("run-event:parentRunId-invalid"); + for (const field of ["startedAt", "completedAt", "evidenceCutoffAt"]) validIso(value, field, "run-event", issues); + for (const field of ["evidenceManifestHash", "policyHash"]) validHash(value, field, "run-event", issues); + validChoice(value, "status", RUN_STATUSES, "run-event", issues); + validateModel(value.model, issues); + validateToolCalls(value.toolCalls, issues); + validateStringArray(value.artifactHashes, "run-event:artifactHashes", HASH, issues); + validateMetricMap(value.metrics, issues); + validateStringArray(value.hardFailureSignals, "run-event:hardFailureSignals", ID, issues); + if (isIso(value.startedAt) && isIso(value.completedAt) && Date.parse(value.completedAt) < Date.parse(value.startedAt)) { + issues.push("run-event:completedAt-before-startedAt"); + } + return unique(issues); +} + +export function validateControlEvidenceManifest(value: unknown): readonly string[] { + if (!record(value)) return ["evidence-manifest:object-required"]; + const issues: string[] = []; + exact(value, "schemaVersion", "boulder.control.evidence-manifest.v1", "evidence-manifest", issues); + for (const field of ["manifestId", "caseId"]) validId(value, field, "evidence-manifest", issues); + for (const field of ["evidenceCutoffAt", "generatedAt"]) validIso(value, field, "evidence-manifest", issues); + if (!Array.isArray(value.entries) || value.entries.length === 0) { + issues.push("evidence-manifest:entries-invalid"); + return unique(issues); + } + const evidenceIds: string[] = []; + value.entries.forEach((entry, index) => validateEvidenceEntry(entry, index, value.evidenceCutoffAt, evidenceIds, issues)); + if (new Set(evidenceIds).size !== evidenceIds.length) issues.push("evidence-manifest:duplicate-evidenceId"); + return unique(issues); +} + +export function validateControlPolicy(value: unknown): readonly string[] { + if (!record(value)) return ["policy:object-required"]; + const issues: string[] = []; + exact(value, "schemaVersion", "boulder.control.policy.v1", "policy", issues); + for (const field of ["id", "version"]) validId(value, field, "policy", issues); + validateChoiceArray(value.blockingSeverities, "policy:blockingSeverities", SEVERITIES, true, issues); + const ids: string[] = []; + const signals: string[] = []; + if (!Array.isArray(value.hardFailures)) issues.push("policy:hardFailures-invalid"); + else value.hardFailures.forEach((rule, index) => validateHardFailureRule(rule, index, ids, signals, issues)); + if (new Set(ids).size !== ids.length) issues.push("policy:duplicate-hard-failure-id"); + if (new Set(signals).size !== signals.length) issues.push("policy:duplicate-hard-failure-signal"); + const metrics: string[] = []; + if (!Array.isArray(value.metricRules)) issues.push("policy:metricRules-invalid"); + else value.metricRules.forEach((rule, index) => validateMetricRule(rule, index, metrics, issues)); + if (new Set(metrics).size !== metrics.length) issues.push("policy:duplicate-metric-rule"); + return unique(issues); +} + +export function validateControlDecisionSeal(value: unknown): readonly string[] { + if (!record(value)) return ["decision-seal:object-required"]; + const issues: string[] = []; + exact(value, "schemaVersion", "boulder.control.decision-seal.v1", "decision-seal", issues); + exact(value, "algorithm", "sha256-canonical-json", "decision-seal", issues); + for (const field of ["runId", "caseId", "taskId", "policyId", "policyVersion"]) validId(value, field, "decision-seal", issues); + validIso(value, "sealedAt", "decision-seal", issues); + for (const field of ["runHash", "evidenceManifestHash", "policyHash", "sealHash"]) validHash(value, field, "decision-seal", issues); + return unique(issues); +} + +export function isControlRunEvent(value: unknown): value is ControlRunEvent { return validateControlRunEvent(value).length === 0; } +export function isControlEvidenceManifest(value: unknown): value is ControlEvidenceManifest { return validateControlEvidenceManifest(value).length === 0; } +export function isControlPolicy(value: unknown): value is ControlPolicy { return validateControlPolicy(value).length === 0; } +export function isControlDecisionSeal(value: unknown): value is ControlDecisionSeal { return validateControlDecisionSeal(value).length === 0; } + +function validateModel(value: unknown, issues: string[]): void { + if (!record(value)) { issues.push("run-event:model-object-required"); return; } + for (const field of ["provider", "name", "version"]) validId(value, field, "run-event:model", issues); +} + +function validateToolCalls(value: unknown, issues: string[]): void { + if (!Array.isArray(value)) { issues.push("run-event:toolCalls-invalid"); return; } + value.forEach((call, index) => { + const prefix = `run-event:toolCalls[${index}]`; + if (!record(call)) { issues.push(`${prefix}-object-required`); return; } + for (const field of ["toolId", "toolVersion", "action"]) validId(call, field, prefix, issues); + validChoice(call, "status", TOOL_STATUSES, prefix, issues); + validHash(call, "inputHash", prefix, issues); + if (call.outputHash !== null && !isHash(call.outputHash)) issues.push(`${prefix}:outputHash-invalid`); + }); +} + +function validateEvidenceEntry(value: unknown, index: number, cutoffValue: unknown, ids: string[], issues: string[]): void { + const prefix = `evidence-manifest:entries[${index}]`; + if (!record(value)) { issues.push(`${prefix}-object-required`); return; } + for (const field of ["evidenceId", "sourceVersion"]) validId(value, field, prefix, issues); + if (isId(value.evidenceId)) ids.push(value.evidenceId); + validHash(value, "sha256", prefix, issues); + validChoice(value, "sourceType", SOURCE_TYPES, prefix, issues); + validChoice(value, "classification", CLASSIFICATIONS, prefix, issues); + validIso(value, "observedAt", prefix, issues); + if (value.sourceUriHash !== null && !isHash(value.sourceUriHash)) issues.push(`${prefix}:sourceUriHash-invalid`); + if (isIso(value.observedAt) && isIso(cutoffValue) && Date.parse(value.observedAt) > Date.parse(cutoffValue)) issues.push(`${prefix}-after-cutoff`); +} + +function validateHardFailureRule(value: unknown, index: number, ids: string[], signals: string[], issues: string[]): void { + const prefix = `policy:hardFailures[${index}]`; + if (!record(value)) { issues.push(`${prefix}-object-required`); return; } + for (const field of ["id", "signal"]) validId(value, field, prefix, issues); + if (isId(value.id)) ids.push(value.id); + if (isId(value.signal)) signals.push(value.signal); + validChoice(value, "severity", SEVERITIES, prefix, issues); + validDescription(value, prefix, issues); +} + +function validateMetricRule(value: unknown, index: number, metrics: string[], issues: string[]): void { + const prefix = `policy:metricRules[${index}]`; + if (!record(value)) { issues.push(`${prefix}-object-required`); return; } + validId(value, "metricId", prefix, issues); + if (isId(value.metricId)) metrics.push(value.metricId); + validChoice(value, "operator", OPERATORS, prefix, issues); + if (typeof value.threshold !== "number" || !Number.isFinite(value.threshold)) issues.push(`${prefix}:threshold-invalid`); + validDescription(value, prefix, issues); +} + +function exact(value: JsonRecord, field: string, expected: string, prefix: string, issues: string[]): void { + if (value[field] !== expected) issues.push(`${prefix}:${field}-must-equal-${expected}`); +} + +function validId(value: JsonRecord, field: string, prefix: string, issues: string[]): void { + if (!isId(value[field])) issues.push(`${prefix}:${field}-invalid`); +} + +function validHash(value: JsonRecord, field: string, prefix: string, issues: string[]): void { + if (!isHash(value[field])) issues.push(`${prefix}:${field}-invalid`); +} + +function validIso(value: JsonRecord, field: string, prefix: string, issues: string[]): void { + if (!isIso(value[field])) issues.push(`${prefix}:${field}-invalid`); +} + +function validChoice(value: JsonRecord, field: string, allowed: readonly T[], prefix: string, issues: string[]): void { + if (typeof value[field] !== "string" || !allowed.some((item) => item === value[field])) issues.push(`${prefix}:${field}-invalid`); +} + +function validateChoiceArray(value: unknown, prefix: string, allowed: readonly T[], nonEmpty: boolean, issues: string[]): void { + if (!Array.isArray(value) || (nonEmpty && value.length === 0) || !value.every((item) => typeof item === "string" && allowed.some((candidate) => candidate === item))) { + issues.push(`${prefix}-invalid`); + } +} + +function validateStringArray(value: unknown, prefix: string, pattern: RegExp, issues: string[]): void { + if (!Array.isArray(value) || !value.every((item) => typeof item === "string" && pattern.test(item))) issues.push(`${prefix}-invalid`); +} + +function validateMetricMap(value: unknown, issues: string[]): void { + if (!record(value)) { issues.push("run-event:metrics-object-required"); return; } + for (const [key, metric] of Object.entries(value)) { + if (!ID.test(key)) issues.push(`run-event:metrics-key-invalid:${key}`); + if (typeof metric !== "number" || !Number.isFinite(metric)) issues.push(`run-event:metrics-value-invalid:${key}`); + } +} + +function validDescription(value: JsonRecord, prefix: string, issues: string[]): void { + if (typeof value.description !== "string" || value.description.trim().length === 0 || value.description.length > 500) issues.push(`${prefix}:description-invalid`); +} + +function isIso(value: unknown): value is string { + if (typeof value !== "string" || value.trim() === "") return false; + const parsed = Date.parse(value); + return Number.isFinite(parsed) && new Date(parsed).toISOString() === value; +} + +function isId(value: unknown): value is string { return typeof value === "string" && ID.test(value); } +function isHash(value: unknown): value is string { return typeof value === "string" && HASH.test(value); } +function record(value: unknown): value is JsonRecord { return typeof value === "object" && value !== null && !Array.isArray(value); } +function unique(values: readonly string[]): readonly string[] { return Array.from(new Set(values)); } From bab8e0f46bcdc569af2eb8cb4b1d9b11ae72f8fd Mon Sep 17 00:00:00 2001 From: Jeon Mingyu Date: Sat, 18 Jul 2026 23:52:58 +0900 Subject: [PATCH 03/27] Add fail-closed control evaluation --- src/control-kernel.ts | 189 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 src/control-kernel.ts diff --git a/src/control-kernel.ts b/src/control-kernel.ts new file mode 100644 index 0000000..b3c7520 --- /dev/null +++ b/src/control-kernel.ts @@ -0,0 +1,189 @@ +import { + isControlDecisionSeal, + isControlEvidenceManifest, + isControlPolicy, + isControlRunEvent, + validateControlDecisionSeal, + validateControlEvidenceManifest, + validateControlPolicy, + validateControlRunEvent +} from "./control-kernel-validation"; +import type { + ControlDecisionSeal, + ControlEvidenceManifest, + ControlEvaluation, + ControlPolicy, + ControlRunEvent, + MetricCheck, + SealVerification, + TriggeredHardFailure +} from "./control-kernel-types"; + +export * from "./control-kernel-types"; +export { + isControlDecisionSeal, + isControlEvidenceManifest, + isControlPolicy, + isControlRunEvent, + validateControlDecisionSeal, + validateControlEvidenceManifest, + validateControlPolicy, + validateControlRunEvent +} from "./control-kernel-validation"; + +export async function evaluateControlRun(runValue: unknown, manifestValue: unknown, policyValue: unknown): Promise { + const runIssues = validateControlRunEvent(runValue); + const manifestIssues = validateControlEvidenceManifest(manifestValue); + const policyIssues = validateControlPolicy(policyValue); + const issues = [...runIssues, ...manifestIssues, ...policyIssues]; + const run = runIssues.length === 0 ? runValue as ControlRunEvent : null; + const manifest = manifestIssues.length === 0 ? manifestValue as ControlEvidenceManifest : null; + const policy = policyIssues.length === 0 ? policyValue as ControlPolicy : null; + const manifestHash = manifest ? await hashControlValue(manifest) : zeroHash(); + const policyHash = policy ? await hashControlValue(policy) : zeroHash(); + + if (run && manifest) { + if (run.caseId !== manifest.caseId) issues.push("binding:caseId-mismatch"); + if (run.evidenceCutoffAt !== manifest.evidenceCutoffAt) issues.push("binding:evidence-cutoff-mismatch"); + if (run.evidenceManifestHash !== manifestHash) issues.push("binding:evidence-manifest-hash-mismatch"); + } + if (run && policy) { + if (run.policyId !== policy.id) issues.push("binding:policy-id-mismatch"); + if (run.policyVersion !== policy.version) issues.push("binding:policy-version-mismatch"); + if (run.policyHash !== policyHash) issues.push("binding:policy-hash-mismatch"); + } + if (run?.status !== undefined && run.status !== "completed") issues.push(`run-status:${run.status}`); + if (run) { + for (const call of run.toolCalls) { + if (call.status === "completed" && call.outputHash === null) issues.push(`tool-call:completed-output-missing:${call.toolId}`); + } + const allowedSignals = new Set(policy?.hardFailures.map((rule) => rule.signal) ?? []); + for (const signal of run.hardFailureSignals) { + if (!allowedSignals.has(signal)) issues.push(`hard-failure-signal-unregistered:${signal}`); + } + } + + const triggeredHardFailures = run && policy ? triggeredFailures(run, policy) : []; + const metricChecks = run && policy ? evaluateMetrics(run, policy) : []; + const blocked = issues.length > 0 || triggeredHardFailures.some((item) => item.blocked) || metricChecks.some((item) => item.status === "fail"); + return { + schemaVersion: "boulder.control.evaluation.v1", + runId: run?.runId ?? "invalid-run", + caseId: run?.caseId ?? manifest?.caseId ?? "invalid-case", + policyId: policy?.id ?? run?.policyId ?? "invalid-policy", + policyVersion: policy?.version ?? run?.policyVersion ?? "invalid-version", + status: blocked ? "blocked" : "eligible", + evidenceManifestHash: manifestHash, + policyHash, + triggeredHardFailures, + metricChecks, + issues: unique(issues) + }; +} + +export async function createControlDecisionSeal( + runValue: unknown, + manifestValue: unknown, + policyValue: unknown, + sealedAt = new Date().toISOString() +): Promise { + const evaluation = await evaluateControlRun(runValue, manifestValue, policyValue); + const issues = [...evaluation.issues]; + if (!isIso(sealedAt)) issues.push("decision-seal:sealedAt-invalid"); + if (issues.length > 0) throw new Error(`Invalid control seal input: ${unique(issues).join(", ")}`); + const run = runValue as ControlRunEvent; + const manifest = manifestValue as ControlEvidenceManifest; + const policy = policyValue as ControlPolicy; + const unsigned = { + schemaVersion: "boulder.control.decision-seal.v1" as const, + algorithm: "sha256-canonical-json" as const, + runId: run.runId, + caseId: run.caseId, + taskId: run.taskId, + policyId: policy.id, + policyVersion: policy.version, + sealedAt, + runHash: await hashControlValue(run), + evidenceManifestHash: await hashControlValue(manifest), + policyHash: await hashControlValue(policy) + }; + return { ...unsigned, sealHash: await hashControlValue(unsigned) }; +} + +export async function verifyControlDecisionSeal( + sealValue: unknown, + runValue: unknown, + manifestValue: unknown, + policyValue: unknown +): Promise { + const evaluation = await evaluateControlRun(runValue, manifestValue, policyValue); + const issues = [...validateControlDecisionSeal(sealValue), ...evaluation.issues]; + if (issues.length > 0 || !isControlDecisionSeal(sealValue) || !isControlRunEvent(runValue) || !isControlEvidenceManifest(manifestValue) || !isControlPolicy(policyValue)) { + return { status: "invalid", issues: unique(issues) }; + } + const seal = sealValue; + const run = runValue; + const manifest = manifestValue; + const policy = policyValue; + const runHash = await hashControlValue(run); + const manifestHash = await hashControlValue(manifest); + const policyHash = await hashControlValue(policy); + if (seal.runId !== run.runId) issues.push("decision-seal:runId-mismatch"); + if (seal.caseId !== run.caseId || seal.caseId !== manifest.caseId) issues.push("decision-seal:caseId-mismatch"); + if (seal.taskId !== run.taskId) issues.push("decision-seal:taskId-mismatch"); + if (seal.policyId !== run.policyId || seal.policyId !== policy.id) issues.push("decision-seal:policyId-mismatch"); + if (seal.policyVersion !== run.policyVersion || seal.policyVersion !== policy.version) issues.push("decision-seal:policyVersion-mismatch"); + if (seal.runHash !== runHash) issues.push("decision-seal:run-hash-mismatch"); + if (seal.evidenceManifestHash !== manifestHash) issues.push("decision-seal:evidence-manifest-hash-mismatch"); + if (seal.policyHash !== policyHash) issues.push("decision-seal:policy-hash-mismatch"); + const unsigned = { ...seal } as Record; + delete unsigned.sealHash; + if (seal.sealHash !== await hashControlValue(unsigned)) issues.push("decision-seal:seal-hash-mismatch"); + return { status: issues.length === 0 ? "valid" : "invalid", issues: unique(issues) }; +} + +export async function hashControlValue(value: unknown): Promise { + const bytes = new TextEncoder().encode(JSON.stringify(canonicalize(value))); + const digest = await crypto.subtle.digest("SHA-256", bytes); + return Array.from(new Uint8Array(digest)).map((item) => item.toString(16).padStart(2, "0")).join(""); +} + +export function canonicalize(value: unknown): unknown { + if (Array.isArray(value)) return value.map(canonicalize); + if (record(value)) { + return Object.fromEntries(Object.keys(value).sort().flatMap((key) => value[key] === undefined ? [] : [[key, canonicalize(value[key])]])); + } + return value; +} + +function triggeredFailures(run: ControlRunEvent, policy: ControlPolicy): readonly TriggeredHardFailure[] { + const signals = new Set(run.hardFailureSignals); + const blocking = new Set(policy.blockingSeverities); + return policy.hardFailures.filter((rule) => signals.has(rule.signal)).map((rule) => ({ ...rule, blocked: blocking.has(rule.severity) })); +} + +function evaluateMetrics(run: ControlRunEvent, policy: ControlPolicy): readonly MetricCheck[] { + return policy.metricRules.map((rule) => { + const actual = Object.prototype.hasOwnProperty.call(run.metrics, rule.metricId) ? run.metrics[rule.metricId] ?? null : null; + const pass = actual !== null && (rule.operator === "gte" ? actual >= rule.threshold : rule.operator === "lte" ? actual <= rule.threshold : actual === rule.threshold); + return { ...rule, actual, status: pass ? "pass" : "fail" }; + }); +} + +function isIso(value: unknown): value is string { + if (typeof value !== "string" || value.trim() === "") return false; + const parsed = Date.parse(value); + return Number.isFinite(parsed) && new Date(parsed).toISOString() === value; +} + +function record(value: unknown): value is Record { + return typeof value === "object" && value !== null && !Array.isArray(value); +} + +function unique(values: readonly string[]): readonly string[] { + return Array.from(new Set(values)); +} + +function zeroHash(): string { + return "0".repeat(64); +} From 6803bcd24c2f47f98aa4e3295e1a8f8924451ffc Mon Sep 17 00:00:00 2001 From: Jeon Mingyu Date: Sat, 18 Jul 2026 23:54:07 +0900 Subject: [PATCH 04/27] Add control-kernel audit CLI --- src/control-kernel-command.ts | 371 ++++++++++++++++++++++++++++++++++ 1 file changed, 371 insertions(+) create mode 100644 src/control-kernel-command.ts diff --git a/src/control-kernel-command.ts b/src/control-kernel-command.ts new file mode 100644 index 0000000..883d4a0 --- /dev/null +++ b/src/control-kernel-command.ts @@ -0,0 +1,371 @@ +import { constants } from "node:fs"; +import { lstat, mkdir, open } from "node:fs/promises"; +import { join, relative, resolve } from "node:path"; +import { prettyJson } from "./cli-format"; +import { optionValue, subcommandAfter } from "./cli-options"; +import { + canonicalize, + createControlDecisionSeal, + evaluateControlRun, + hashControlValue, + isControlDecisionSeal, + isControlEvidenceManifest, + isControlPolicy, + isControlRunEvent, + validateControlDecisionSeal, + validateControlEvidenceManifest, + validateControlPolicy, + validateControlRunEvent, + verifyControlDecisionSeal, + type ControlDecisionSeal, + type ControlEvaluation, + type ControlRunEvent +} from "./control-kernel"; +import { exists, noFollowFlag, safeReplaceText } from "./fs"; + +export type ControlKernelCommandOptions = { + readonly cwd: string; + readonly json: boolean; +}; + +type ArtifactKind = "runs" | "seals"; + +type RecordResult = { + readonly status: "recorded" | "already-recorded"; + readonly runId: string; + readonly path: string; + readonly runHash: string; +}; + +type SealResult = { + readonly status: "sealed" | "already-sealed"; + readonly runId: string; + readonly path: string; + readonly seal: ControlDecisionSeal; +}; + +export class ControlKernelCommandError extends Error { + readonly code: string; + + constructor(code: string, message: string) { + super(message); + this.name = "ControlKernelCommandError"; + this.code = code; + } +} + +export async function runControlKernelCommand(args: readonly string[], options: ControlKernelCommandOptions): Promise { + const action = subcommandAfter(args, "control") ?? "help"; + try { + if (action === "record") { + const run = await loadRun(options.cwd, requiredOption(args, "--event")); + print(await recordControlRunEvent(options.cwd, run), options.json); + return; + } + if (action === "evaluate") { + const run = await loadRun(options.cwd, requiredOption(args, "--event")); + const manifest = await loadManifest(options.cwd, requiredOption(args, "--manifest")); + const policy = await loadPolicy(options.cwd, requiredOption(args, "--policy")); + const evaluation = await evaluateControlRun(run, manifest, policy); + const result = await storedRunMatches(options.cwd, run) ? evaluation : missingAudit(evaluation); + print(result, options.json); + if (result.status === "blocked") process.exitCode = 1; + return; + } + if (action === "seal") { + const run = await loadRun(options.cwd, requiredOption(args, "--event")); + const manifest = await loadManifest(options.cwd, requiredOption(args, "--manifest")); + const policy = await loadPolicy(options.cwd, requiredOption(args, "--policy")); + if (!await storedRunMatches(options.cwd, run)) { + throw new ControlKernelCommandError("audit_required", "Record the exact run event before sealing it."); + } + print(await recordControlDecisionSeal(options.cwd, await createControlDecisionSeal(run, manifest, policy)), options.json); + return; + } + if (action === "verify-seal") { + const seal = await loadSeal(options.cwd, requiredOption(args, "--seal")); + const run = await loadRun(options.cwd, requiredOption(args, "--event")); + const manifest = await loadManifest(options.cwd, requiredOption(args, "--manifest")); + const policy = await loadPolicy(options.cwd, requiredOption(args, "--policy")); + const result = await verifyControlDecisionSeal(seal, run, manifest, policy); + print(result, options.json); + if (result.status === "invalid") process.exitCode = 1; + return; + } + if (action === "help") { + printHelp(); + return; + } + throw new ControlKernelCommandError("unknown_command", `Unknown control command: ${action}`); + } catch (error) { + const normalized = normalizeError(error); + console.error(`ERROR control.${normalized.code}: ${normalized.message}`); + process.exitCode = 1; + } +} + +export async function recordControlRunEvent(root: string, run: ControlRunEvent): Promise { + const issues = validateControlRunEvent(run); + if (issues.length > 0) throw invalidInput("run event", issues); + const location = await prepareArtifactLocation(root, "runs", run.runId); + const runHash = await hashControlValue(run); + if (await exists(location.absolute)) { + const existing = await readStoredArtifact(root, location.relative); + if (isControlRunEvent(existing) && await hashControlValue(existing) === runHash) { + return { status: "already-recorded", runId: run.runId, path: location.relative, runHash }; + } + throw new ControlKernelCommandError("run_conflict", `Run ID already exists with different content: ${location.relative}`); + } + await safeReplaceText(location.absolute, `${prettyJson(canonicalize(run))}\n`); + if (!await artifactPathIsSafe(root, location.absolute, "runs")) { + throw new ControlKernelCommandError("path_invalid", `Unsafe control-kernel path after write: ${location.relative}`); + } + return { status: "recorded", runId: run.runId, path: location.relative, runHash }; +} + +export async function recordControlDecisionSeal(root: string, seal: ControlDecisionSeal): Promise { + const issues = validateControlDecisionSeal(seal); + if (issues.length > 0) throw invalidInput("decision seal", issues); + const location = await prepareArtifactLocation(root, "seals", seal.runId); + if (await exists(location.absolute)) { + const existing = await readStoredArtifact(root, location.relative); + if (isControlDecisionSeal(existing) && sameDecisionBinding(existing, seal)) { + return { status: "already-sealed", runId: seal.runId, path: location.relative, seal: existing }; + } + throw new ControlKernelCommandError("seal_conflict", `Run ID already has a different seal: ${location.relative}`); + } + await safeReplaceText(location.absolute, `${prettyJson(canonicalize(seal))}\n`); + if (!await artifactPathIsSafe(root, location.absolute, "seals")) { + throw new ControlKernelCommandError("path_invalid", `Unsafe control-kernel path after write: ${location.relative}`); + } + return { status: "sealed", runId: seal.runId, path: location.relative, seal }; +} + +function missingAudit(evaluation: ControlEvaluation): ControlEvaluation { + return { + ...evaluation, + status: "blocked", + issues: Array.from(new Set([...evaluation.issues, "audit:recorded-run-missing-or-mismatch"])) + }; +} + +async function storedRunMatches(root: string, run: ControlRunEvent): Promise { + const location = artifactLocation(root, "runs", run.runId); + if (!await exists(location.absolute)) return false; + try { + const stored = await readStoredArtifact(root, location.relative); + return isControlRunEvent(stored) && await hashControlValue(stored) === await hashControlValue(run); + } catch { + return false; + } +} + +async function loadRun(root: string, path: string): Promise { + const value = await readInput(root, path); + const issues = validateControlRunEvent(value); + if (!isControlRunEvent(value)) throw invalidInput("run event", issues); + return value; +} + +async function loadManifest(root: string, path: string) { + const value = await readInput(root, path); + const issues = validateControlEvidenceManifest(value); + if (!isControlEvidenceManifest(value)) throw invalidInput("evidence manifest", issues); + return value; +} + +async function loadPolicy(root: string, path: string) { + const value = await readInput(root, path); + const issues = validateControlPolicy(value); + if (!isControlPolicy(value)) throw invalidInput("policy", issues); + return value; +} + +async function loadSeal(root: string, path: string): Promise { + const value = await readInput(root, path); + const issues = validateControlDecisionSeal(value); + if (!isControlDecisionSeal(value)) throw invalidInput("decision seal", issues); + return value; +} + +async function readStoredArtifact(root: string, relativePath: string): Promise { + const location = resolve(root, relativePath); + if (!pathIsContained(resolve(root), location)) throw new ControlKernelCommandError("path_invalid", "Stored artifact escaped the workspace."); + return await readJsonFile(resolve(root), location, relativePath); +} + +async function readInput(root: string, requested: string): Promise { + const rootPath = resolve(root); + const target = resolve(rootPath, requested); + if (!pathIsContained(rootPath, target)) { + throw new ControlKernelCommandError("path_invalid", `Input path must stay inside the workspace: ${requested}`); + } + return await readJsonFile(rootPath, target, requested); +} + +async function readJsonFile(root: string, target: string, displayPath: string): Promise { + if (!await inputPathIsSafe(root, target)) { + throw new ControlKernelCommandError("path_invalid", `Input path contains a symlink, hardlink, or non-file target: ${displayPath}`); + } + let handle: Awaited> | null = null; + try { + handle = await open(target, constants.O_RDONLY | noFollowFlag()); + return JSON.parse(await handle.readFile("utf8")) as unknown; + } catch (error) { + if (error instanceof SyntaxError) throw new ControlKernelCommandError("input_invalid", `Input is not valid JSON: ${displayPath}`); + if (isMissing(error)) throw new ControlKernelCommandError("input_missing", `Input file was not found: ${displayPath}`); + if (isUnsafeOpen(error)) throw new ControlKernelCommandError("path_invalid", `Input path is unsafe: ${displayPath}`); + throw error; + } finally { + await handle?.close(); + } +} + +async function inputPathIsSafe(root: string, target: string): Promise { + if (!pathIsContained(root, target)) return false; + try { + const rootInfo = await lstat(root); + if (!rootInfo.isDirectory() || rootInfo.isSymbolicLink()) return false; + } catch (error) { + if (isMissing(error)) return false; + throw error; + } + const parts = relative(root, target).split(/[\\/]/).filter(Boolean); + let current = root; + for (let index = 0; index < parts.length; index += 1) { + current = join(current, parts[index] ?? ""); + try { + const info = await lstat(current); + if (info.isSymbolicLink()) return false; + if (index < parts.length - 1 && !info.isDirectory()) return false; + if (index === parts.length - 1 && (!info.isFile() || info.nlink !== 1)) return false; + } catch (error) { + if (isMissing(error)) return false; + throw error; + } + } + return parts.length > 0; +} + +async function prepareArtifactLocation(root: string, kind: ArtifactKind, id: string): Promise<{ readonly absolute: string; readonly relative: string }> { + const location = artifactLocation(root, kind, id); + const rootPath = resolve(root); + if (!await directoryIsSafe(rootPath)) { + throw new ControlKernelCommandError("path_invalid", "Workspace root must be a real directory."); + } + const directories = [ + join(rootPath, ".boulder"), + join(rootPath, ".boulder", "control-kernel"), + join(rootPath, ".boulder", "control-kernel", kind) + ]; + for (const directory of directories) { + await mkdir(directory, { recursive: true }); + if (!await directoryIsSafe(directory)) { + throw new ControlKernelCommandError("path_invalid", `Unsafe control-kernel directory: ${relative(rootPath, directory)}`); + } + } + if (!await artifactPathIsSafe(root, location.absolute, kind)) { + throw new ControlKernelCommandError("path_invalid", `Unsafe control-kernel path: ${location.relative}`); + } + return location; +} + +function artifactLocation(root: string, kind: ArtifactKind, id: string): { readonly absolute: string; readonly relative: string } { + if (!/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(id)) { + throw new ControlKernelCommandError("path_invalid", `Unsafe control artifact ID: ${id}`); + } + const fileName = encodeURIComponent(id); + const relativePath = `.boulder/control-kernel/${kind}/${fileName}.json`; + return { absolute: resolve(root, relativePath), relative: relativePath }; +} + +async function artifactPathIsSafe(root: string, target: string, kind: ArtifactKind): Promise { + const rootPath = resolve(root); + if (!pathIsContained(rootPath, target)) return false; + for (const path of [rootPath, join(rootPath, ".boulder"), join(rootPath, ".boulder", "control-kernel"), join(rootPath, ".boulder", "control-kernel", kind)]) { + try { + const info = await lstat(path); + if (!info.isDirectory() || info.isSymbolicLink()) return false; + } catch (error) { + if (isMissing(error)) return false; + throw error; + } + } + try { + const info = await lstat(target); + return info.isFile() && !info.isSymbolicLink() && info.nlink === 1; + } catch (error) { + if (isMissing(error)) return true; + throw error; + } +} + +function sameDecisionBinding(left: ControlDecisionSeal, right: ControlDecisionSeal): boolean { + return left.algorithm === right.algorithm + && left.runId === right.runId + && left.caseId === right.caseId + && left.taskId === right.taskId + && left.policyId === right.policyId + && left.policyVersion === right.policyVersion + && left.runHash === right.runHash + && left.evidenceManifestHash === right.evidenceManifestHash + && left.policyHash === right.policyHash; +} + +async function directoryIsSafe(path: string): Promise { + try { + const info = await lstat(path); + return info.isDirectory() && !info.isSymbolicLink(); + } catch (error) { + if (isMissing(error)) return false; + throw error; + } +} + +function requiredOption(args: readonly string[], flag: string): string { + const value = optionValue(args, flag); + if (!value) throw new ControlKernelCommandError("input_missing", `Missing required option ${flag}.`); + return value; +} + +function invalidInput(label: string, issues: readonly string[]): ControlKernelCommandError { + return new ControlKernelCommandError("input_invalid", `Invalid ${label}: ${issues.join(", ")}`); +} + +function normalizeError(error: unknown): ControlKernelCommandError { + if (error instanceof ControlKernelCommandError) return error; + return new ControlKernelCommandError("unexpected", error instanceof Error ? error.message : String(error)); +} + +function print(value: unknown, json: boolean): void { + if (json) { + console.log(prettyJson(value)); + return; + } + console.log(prettyJson(value)); +} + +function printHelp(): void { + console.log([ + "Boulder control kernel", + "", + " boulder control record --event path [--cwd path] [--json]", + " boulder control evaluate --event path --manifest path --policy path [--cwd path] [--json]", + " boulder control seal --event path --manifest path --policy path [--cwd path] [--json]", + " boulder control verify-seal --seal path --event path --manifest path --policy path [--cwd path] [--json]" + ].join("\n")); +} + +function pathIsContained(root: string, target: string): boolean { + const relation = relative(root, target).replace(/\\/g, "/"); + return relation.length > 0 && relation !== ".." && !relation.startsWith("../") && !relation.startsWith("/") && !/^[A-Za-z]:\//.test(relation); +} + +function isMissing(error: unknown): boolean { + return error instanceof Error && Reflect.get(error, "code") === "ENOENT"; +} + +function isUnsafeOpen(error: unknown): boolean { + const code = error instanceof Error ? Reflect.get(error, "code") : null; + return code === "ELOOP" || code === "EMLINK"; +} From 8ecbbcad87a3d79bcbefb3c37a25dab09b3d0117 Mon Sep 17 00:00:00 2001 From: Jeon Mingyu Date: Sat, 18 Jul 2026 23:54:53 +0900 Subject: [PATCH 05/27] Add synthetic GP control fixture --- .../gp-screening-shadow-v0.json | 218 ++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 fixtures/control-kernel/gp-screening-shadow-v0.json diff --git a/fixtures/control-kernel/gp-screening-shadow-v0.json b/fixtures/control-kernel/gp-screening-shadow-v0.json new file mode 100644 index 0000000..22bfd6e --- /dev/null +++ b/fixtures/control-kernel/gp-screening-shadow-v0.json @@ -0,0 +1,218 @@ +{ + "schemaVersion": "boulder.control.fixture.v1", + "policy": { + "schemaVersion": "boulder.control.policy.v1", + "id": "gp-screening-shadow", + "version": "0.1.0", + "blockingSeverities": [ + "critical", + "major" + ], + "hardFailures": [ + { + "id": "mandate-exclusion", + "signal": "mandate.exclusion.missed", + "severity": "critical", + "description": "A hard mandate exclusion was missed or suppressed." + }, + { + "id": "conflict-escalation", + "signal": "conflict.escalation.missed", + "severity": "critical", + "description": "A required conflict or related-party escalation was missed." + }, + { + "id": "unsupported-material-claim", + "signal": "evidence.material-claim.unsupported", + "severity": "major", + "description": "A material recommendation claim lacks admissible evidence." + } + ], + "metricRules": [ + { + "metricId": "decision-accuracy", + "operator": "gte", + "threshold": 0.75, + "description": "Decision agreement or adjudicated quality must meet the pilot floor." + }, + { + "metricId": "evidence-coverage", + "operator": "gte", + "threshold": 0.9, + "description": "Material claims must be covered by admissible evidence." + }, + { + "metricId": "risk-recall", + "operator": "gte", + "threshold": 0.8, + "description": "Known material risks must be surfaced." + } + ] + }, + "evidenceManifest": { + "schemaVersion": "boulder.control.evidence-manifest.v1", + "manifestId": "synthetic-screening-001-manifest", + "caseId": "synthetic-screening-001", + "evidenceCutoffAt": "2025-01-15T00:00:00.000Z", + "generatedAt": "2026-07-18T14:00:00.000Z", + "entries": [ + { + "evidenceId": "cim-v1", + "sha256": "1111111111111111111111111111111111111111111111111111111111111111", + "sourceType": "document", + "classification": "confidential", + "sourceVersion": "v1", + "observedAt": "2025-01-10T00:00:00.000Z", + "sourceUriHash": "2222222222222222222222222222222222222222222222222222222222222222" + }, + { + "evidenceId": "mandate-v3", + "sha256": "3333333333333333333333333333333333333333333333333333333333333333", + "sourceType": "database", + "classification": "restricted", + "sourceVersion": "v3", + "observedAt": "2025-01-01T00:00:00.000Z", + "sourceUriHash": "4444444444444444444444444444444444444444444444444444444444444444" + } + ] + }, + "runs": { + "pass": { + "schemaVersion": "boulder.control.run-event.v1", + "caseId": "synthetic-screening-001", + "taskId": "screening-decision-package", + "agentId": "underwriting-agent", + "agentVersion": "0.1.0", + "profileId": "gp-screening-shadow", + "profileVersion": "0.1.0", + "parentRunId": null, + "startedAt": "2026-07-18T14:01:00.000Z", + "completedAt": "2026-07-18T14:02:00.000Z", + "evidenceCutoffAt": "2025-01-15T00:00:00.000Z", + "evidenceManifestHash": "39c90fcde10b441df6cdf1c81999a0eda124a72a8946f812b817ca58f22b6ac4", + "policyId": "gp-screening-shadow", + "policyVersion": "0.1.0", + "policyHash": "9d82eaf6062bc15d597a374f791b64405be8ccb06379dcc9c4722dbb80b451ea", + "promptVersion": "screening-v0.1", + "model": { + "provider": "test", + "name": "synthetic-screening-model", + "version": "1.0.0" + }, + "toolCalls": [ + { + "toolId": "evidence-index", + "toolVersion": "0.1.0", + "action": "read", + "status": "completed", + "inputHash": "5555555555555555555555555555555555555555555555555555555555555555", + "outputHash": "6666666666666666666666666666666666666666666666666666666666666666" + } + ], + "artifactHashes": [ + "7777777777777777777777777777777777777777777777777777777777777777" + ], + "status": "completed", + "runId": "synthetic-pass-run", + "idempotencyKey": "synthetic-pass-run-v1", + "metrics": { + "decision-accuracy": 0.83, + "evidence-coverage": 0.96, + "risk-recall": 0.88 + }, + "hardFailureSignals": [] + }, + "hardFailure": { + "schemaVersion": "boulder.control.run-event.v1", + "caseId": "synthetic-screening-001", + "taskId": "screening-decision-package", + "agentId": "underwriting-agent", + "agentVersion": "0.1.0", + "profileId": "gp-screening-shadow", + "profileVersion": "0.1.0", + "parentRunId": null, + "startedAt": "2026-07-18T14:01:00.000Z", + "completedAt": "2026-07-18T14:02:00.000Z", + "evidenceCutoffAt": "2025-01-15T00:00:00.000Z", + "evidenceManifestHash": "39c90fcde10b441df6cdf1c81999a0eda124a72a8946f812b817ca58f22b6ac4", + "policyId": "gp-screening-shadow", + "policyVersion": "0.1.0", + "policyHash": "9d82eaf6062bc15d597a374f791b64405be8ccb06379dcc9c4722dbb80b451ea", + "promptVersion": "screening-v0.1", + "model": { + "provider": "test", + "name": "synthetic-screening-model", + "version": "1.0.0" + }, + "toolCalls": [ + { + "toolId": "evidence-index", + "toolVersion": "0.1.0", + "action": "read", + "status": "completed", + "inputHash": "5555555555555555555555555555555555555555555555555555555555555555", + "outputHash": "6666666666666666666666666666666666666666666666666666666666666666" + } + ], + "artifactHashes": [ + "7777777777777777777777777777777777777777777777777777777777777777" + ], + "status": "completed", + "runId": "synthetic-hard-failure-run", + "idempotencyKey": "synthetic-hard-failure-run-v1", + "metrics": { + "decision-accuracy": 1.0, + "evidence-coverage": 1.0, + "risk-recall": 1.0 + }, + "hardFailureSignals": [ + "mandate.exclusion.missed" + ] + }, + "metricFailure": { + "schemaVersion": "boulder.control.run-event.v1", + "caseId": "synthetic-screening-001", + "taskId": "screening-decision-package", + "agentId": "underwriting-agent", + "agentVersion": "0.1.0", + "profileId": "gp-screening-shadow", + "profileVersion": "0.1.0", + "parentRunId": null, + "startedAt": "2026-07-18T14:01:00.000Z", + "completedAt": "2026-07-18T14:02:00.000Z", + "evidenceCutoffAt": "2025-01-15T00:00:00.000Z", + "evidenceManifestHash": "39c90fcde10b441df6cdf1c81999a0eda124a72a8946f812b817ca58f22b6ac4", + "policyId": "gp-screening-shadow", + "policyVersion": "0.1.0", + "policyHash": "9d82eaf6062bc15d597a374f791b64405be8ccb06379dcc9c4722dbb80b451ea", + "promptVersion": "screening-v0.1", + "model": { + "provider": "test", + "name": "synthetic-screening-model", + "version": "1.0.0" + }, + "toolCalls": [ + { + "toolId": "evidence-index", + "toolVersion": "0.1.0", + "action": "read", + "status": "completed", + "inputHash": "5555555555555555555555555555555555555555555555555555555555555555", + "outputHash": "6666666666666666666666666666666666666666666666666666666666666666" + } + ], + "artifactHashes": [ + "7777777777777777777777777777777777777777777777777777777777777777" + ], + "status": "completed", + "runId": "synthetic-metric-failure-run", + "idempotencyKey": "synthetic-metric-failure-run-v1", + "metrics": { + "decision-accuracy": 0.83, + "evidence-coverage": 0.96, + "risk-recall": 0.6 + }, + "hardFailureSignals": [] + } + } +} From a78feb399194df9a162e023d9021581900bbb27d Mon Sep 17 00:00:00 2001 From: Jeon Mingyu Date: Sat, 18 Jul 2026 23:55:29 +0900 Subject: [PATCH 06/27] Test control-kernel policy gates --- test/control-kernel.test.ts | 124 ++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 test/control-kernel.test.ts diff --git a/test/control-kernel.test.ts b/test/control-kernel.test.ts new file mode 100644 index 0000000..7529290 --- /dev/null +++ b/test/control-kernel.test.ts @@ -0,0 +1,124 @@ +import { readFile } from "node:fs/promises"; +import { join } from "node:path"; +import { describe, expect, test } from "bun:test"; +import { + createControlDecisionSeal, + evaluateControlRun, + isControlEvidenceManifest, + isControlPolicy, + isControlRunEvent, + validateControlEvidenceManifest, + validateControlPolicy, + validateControlRunEvent, + verifyControlDecisionSeal, + type ControlEvidenceManifest, + type ControlPolicy, + type ControlRunEvent +} from "../src/control-kernel"; + +const root = join(import.meta.dir, ".."); +const fixturePath = join(root, "fixtures/control-kernel/gp-screening-shadow-v0.json"); + +describe("generic control kernel", () => { + test("accepts a valid synthetic screening run", async () => { + const fixture = await loadFixture(); + expect(validateControlPolicy(fixture.policy)).toEqual([]); + expect(validateControlEvidenceManifest(fixture.manifest)).toEqual([]); + expect(validateControlRunEvent(fixture.passRun)).toEqual([]); + + const result = await evaluateControlRun(fixture.passRun, fixture.manifest, fixture.policy); + expect(result.status).toBe("eligible"); + expect(result.issues).toEqual([]); + expect(result.metricChecks.every((item) => item.status === "pass")).toBe(true); + }); + + test("blocks a critical hard failure even when every metric passes", async () => { + const fixture = await loadFixture(); + const result = await evaluateControlRun(fixture.hardFailureRun, fixture.manifest, fixture.policy); + + expect(result.status).toBe("blocked"); + expect(result.metricChecks.every((item) => item.status === "pass")).toBe(true); + expect(result.triggeredHardFailures.map((item) => item.id)).toContain("mandate-exclusion"); + expect(result.triggeredHardFailures.find((item) => item.id === "mandate-exclusion")?.blocked).toBe(true); + }); + + test("blocks a promotion metric miss without a hard failure", async () => { + const fixture = await loadFixture(); + const result = await evaluateControlRun(fixture.metricFailureRun, fixture.manifest, fixture.policy); + + expect(result.status).toBe("blocked"); + expect(result.triggeredHardFailures).toEqual([]); + expect(result.metricChecks.find((item) => item.metricId === "risk-recall")?.status).toBe("fail"); + }); + + test("fails closed on unknown hard-failure signals and evidence after cutoff", async () => { + const fixture = await loadFixture(); + const unknownSignal: ControlRunEvent = { ...fixture.passRun, hardFailureSignals: ["unknown.signal"] }; + const signalResult = await evaluateControlRun(unknownSignal, fixture.manifest, fixture.policy); + expect(signalResult.status).toBe("blocked"); + expect(signalResult.issues).toContain("hard-failure-signal-unregistered:unknown.signal"); + + const first = fixture.manifest.entries[0]; + if (!first) throw new Error("Fixture evidence entry is missing."); + const lateManifest: ControlEvidenceManifest = { + ...fixture.manifest, + entries: [{ ...first, observedAt: "2025-01-16T00:00:00.000Z" }, ...fixture.manifest.entries.slice(1)] + }; + expect(validateControlEvidenceManifest(lateManifest)).toContain("evidence-manifest:entries[0]-after-cutoff"); + }); + + test("invalidates a recommendation seal after the run changes", async () => { + const fixture = await loadFixture(); + const seal = await createControlDecisionSeal(fixture.passRun, fixture.manifest, fixture.policy, "2026-07-18T14:03:00.000Z"); + const valid = await verifyControlDecisionSeal(seal, fixture.passRun, fixture.manifest, fixture.policy); + expect(valid.status).toBe("valid"); + + const changed: ControlRunEvent = { + ...fixture.passRun, + metrics: { ...fixture.passRun.metrics, "risk-recall": 0.81 } + }; + const invalid = await verifyControlDecisionSeal(seal, changed, fixture.manifest, fixture.policy); + expect(invalid.status).toBe("invalid"); + expect(invalid.issues).toContain("decision-seal:run-hash-mismatch"); + }); + + test("rejects a seal when the run-to-evidence binding is inconsistent", async () => { + const fixture = await loadFixture(); + const seal = await createControlDecisionSeal(fixture.passRun, fixture.manifest, fixture.policy, "2026-07-18T14:03:00.000Z"); + const mismatched: ControlRunEvent = { + ...fixture.passRun, + evidenceManifestHash: "8".repeat(64) + }; + const result = await verifyControlDecisionSeal(seal, mismatched, fixture.manifest, fixture.policy); + expect(result.status).toBe("invalid"); + expect(result.issues).toContain("binding:evidence-manifest-hash-mismatch"); + }); +}); + +type Fixture = { + readonly policy: ControlPolicy; + readonly manifest: ControlEvidenceManifest; + readonly passRun: ControlRunEvent; + readonly hardFailureRun: ControlRunEvent; + readonly metricFailureRun: ControlRunEvent; +}; + +async function loadFixture(): Promise { + const parsed: unknown = JSON.parse(await readFile(fixturePath, "utf8")); + if (!isRecord(parsed) || !isRecord(parsed["runs"])) throw new Error("Invalid control-kernel fixture."); + const policy = parsed["policy"]; + const manifest = parsed["evidenceManifest"]; + const passRun = parsed["runs"]["pass"]; + const hardFailureRun = parsed["runs"]["hardFailure"]; + const metricFailureRun = parsed["runs"]["metricFailure"]; + if (!isControlPolicy(policy)) throw new Error("Invalid fixture policy."); + if (!isControlEvidenceManifest(manifest)) throw new Error("Invalid fixture evidence manifest."); + if (!isControlRunEvent(passRun) || !isControlRunEvent(hardFailureRun) || !isControlRunEvent(metricFailureRun)) { + throw new Error("Invalid fixture run event."); + } + return { policy, manifest, passRun, hardFailureRun, metricFailureRun }; +} + +function isRecord(value: unknown): value is Record { + return typeof value === "object" && value !== null && !Array.isArray(value); +} From 2450da0eeed715801c99cd674e701a1c6eddc614 Mon Sep 17 00:00:00 2001 From: Jeon Mingyu Date: Sat, 18 Jul 2026 23:56:02 +0900 Subject: [PATCH 07/27] Test mandatory audit and decision seals --- test/control-kernel-cli-e2e.test.ts | 120 ++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 test/control-kernel-cli-e2e.test.ts diff --git a/test/control-kernel-cli-e2e.test.ts b/test/control-kernel-cli-e2e.test.ts new file mode 100644 index 0000000..40654f4 --- /dev/null +++ b/test/control-kernel-cli-e2e.test.ts @@ -0,0 +1,120 @@ +import { readFile } from "node:fs/promises"; +import { join } from "node:path"; +import { describe, expect, test } from "bun:test"; +import { removeTempRepo, runBoulder, tempRepo, write } from "./helpers/cli"; + +const repositoryRoot = join(import.meta.dir, ".."); +const fixturePath = join(repositoryRoot, "fixtures/control-kernel/gp-screening-shadow-v0.json"); + +describe("control kernel CLI", () => { + test("requires an immutable audit record before evaluation and sealing", async () => { + const root = await tempRepo("boulder-control-kernel-"); + try { + const fixture = parseFixture(await readFile(fixturePath, "utf8")); + await writeInputs(root, fixture); + + const unaudited = await runBoulder(controlArgs("evaluate", root)); + expect(unaudited.exitCode).toBe(1); + expect(readString(parseJson(unaudited.stdout), "status")).toBe("blocked"); + expect(readStringArray(parseJson(unaudited.stdout), "issues")).toContain("audit:recorded-run-missing-or-mismatch"); + + const recorded = await runBoulder(["control", "record", "--cwd", root, "--event", "inputs/event.json", "--json"]); + expect(recorded.exitCode).toBe(0); + expect(readString(parseJson(recorded.stdout), "status")).toBe("recorded"); + expect(readString(parseJson(recorded.stdout), "path")).toBe(".boulder/control-kernel/runs/synthetic-pass-run.json"); + + const repeated = await runBoulder(["control", "record", "--cwd", root, "--event", "inputs/event.json", "--json"]); + expect(repeated.exitCode).toBe(0); + expect(readString(parseJson(repeated.stdout), "status")).toBe("already-recorded"); + + const evaluated = await runBoulder(controlArgs("evaluate", root)); + expect(evaluated.exitCode).toBe(0); + expect(readString(parseJson(evaluated.stdout), "status")).toBe("eligible"); + + const sealed = await runBoulder(controlArgs("seal", root)); + expect(sealed.exitCode).toBe(0); + expect(readString(parseJson(sealed.stdout), "status")).toBe("sealed"); + + const repeatedSeal = await runBoulder(controlArgs("seal", root)); + expect(repeatedSeal.exitCode).toBe(0); + expect(readString(parseJson(repeatedSeal.stdout), "status")).toBe("already-sealed"); + + const verified = await runBoulder(verifyArgs(root)); + expect(verified.exitCode).toBe(0); + expect(readString(parseJson(verified.stdout), "status")).toBe("valid"); + + const metrics = fixture.runs.pass["metrics"]; + if (!isRecord(metrics)) throw new Error("Fixture metrics are invalid."); + await write(root, "inputs/event.json", JSON.stringify({ ...fixture.runs.pass, metrics: { ...metrics, "risk-recall": 0.81 } }, null, 2)); + const invalidated = await runBoulder(verifyArgs(root)); + expect(invalidated.exitCode).toBe(1); + expect(readString(parseJson(invalidated.stdout), "status")).toBe("invalid"); + expect(readStringArray(parseJson(invalidated.stdout), "issues")).toContain("decision-seal:run-hash-mismatch"); + } finally { + await removeTempRepo(root); + } + }); +}); + +async function writeInputs(root: string, fixture: Fixture): Promise { + await write(root, "inputs/event.json", JSON.stringify(fixture.runs.pass, null, 2)); + await write(root, "inputs/manifest.json", JSON.stringify(fixture.evidenceManifest, null, 2)); + await write(root, "inputs/policy.json", JSON.stringify(fixture.policy, null, 2)); +} + +function controlArgs(action: "evaluate" | "seal", root: string): readonly string[] { + return [ + "control", action, "--cwd", root, + "--event", "inputs/event.json", + "--manifest", "inputs/manifest.json", + "--policy", "inputs/policy.json", + "--json" + ]; +} + +function verifyArgs(root: string): readonly string[] { + return [ + "control", "verify-seal", "--cwd", root, + "--seal", ".boulder/control-kernel/seals/synthetic-pass-run.json", + "--event", "inputs/event.json", + "--manifest", "inputs/manifest.json", + "--policy", "inputs/policy.json", + "--json" + ]; +} + +type Fixture = { + readonly policy: Record; + readonly evidenceManifest: Record; + readonly runs: { readonly pass: Record }; +}; + +function parseFixture(source: string): Fixture { + const value: unknown = JSON.parse(source); + if (!isRecord(value) || !isRecord(value["policy"]) || !isRecord(value["evidenceManifest"]) || !isRecord(value["runs"]) || !isRecord(value["runs"]["pass"])) { + throw new Error("Invalid control-kernel fixture."); + } + return { policy: value["policy"], evidenceManifest: value["evidenceManifest"], runs: { pass: value["runs"]["pass"] } }; +} + +function parseJson(source: string): Record { + const value: unknown = JSON.parse(source); + if (isRecord(value)) return value; + throw new Error("Expected JSON object."); +} + +function readString(record: Record, key: string): string { + const value = record[key]; + if (typeof value === "string") return value; + throw new Error(`Expected string field ${key}.`); +} + +function readStringArray(record: Record, key: string): readonly string[] { + const value = record[key]; + if (Array.isArray(value) && value.every((item) => typeof item === "string")) return value; + throw new Error(`Expected string array field ${key}.`); +} + +function isRecord(value: unknown): value is Record { + return typeof value === "object" && value !== null && !Array.isArray(value); +} From 0b2b83109594ff443bbc726a08860c4e6ac509ff Mon Sep 17 00:00:00 2001 From: Jeon Mingyu Date: Sat, 18 Jul 2026 23:56:49 +0900 Subject: [PATCH 08/27] Route control-kernel CLI --- src/cli.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/cli.ts b/src/cli.ts index ed01c52..09552ac 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -4,6 +4,7 @@ import { runCapabilityCommand } from "./capability-command"; import { formatLines, prettyJson, printHelp } from "./cli-format"; import { runOperationalCommand } from "./cli-ops-command"; import { optionValue, parseOptions, valueAfter } from "./cli-options"; +import { runControlKernelCommand } from "./control-kernel-command"; import { UnsafeGeneratedWritePathError, writeGeneratedText } from "./fs"; import { exportHarness } from "./export"; import { runHandoffCommand } from "./handoff-command"; @@ -92,6 +93,10 @@ async function runMain(args: string[]): Promise { await runRunsCommand(parsed.commandArgs, args, options.cwd, options.json); return; } + if (command === "control") { + await runControlKernelCommand(args, { cwd: options.cwd, json: options.json }); + return; + } if (command === "bootstrap" && args.includes("interview")) { const report = buildBootstrapInterview(optionValue(args, "--task")); if (options.json) { From a250c3f4c3c6dc1467b3b4d996633d2dd5657985 Mon Sep 17 00:00:00 2001 From: Jeon Mingyu Date: Sat, 18 Jul 2026 23:57:22 +0900 Subject: [PATCH 09/27] Document control-kernel commands --- src/cli-format.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cli-format.ts b/src/cli-format.ts index 6eb38c9..71534b4 100644 --- a/src/cli-format.ts +++ b/src/cli-format.ts @@ -55,6 +55,10 @@ export function printHelp(): void { " boulder replay-check [--cwd path] [--json]", " boulder replay-run [--cwd path] --dry-run [--json]", " boulder doctor [--cwd path] [--json]", + " boulder control record --event path [--cwd path] [--json]", + " boulder control evaluate --event path --manifest path --policy path [--cwd path] [--json]", + " boulder control seal --event path --manifest path --policy path [--cwd path] [--json]", + " boulder control verify-seal --seal path --event path --manifest path --policy path [--cwd path] [--json]", " boulder record field-readiness --run-id id --evidence path [--cwd path] [--json]", " boulder export [--cwd path] [--force]", "", From 8ef0444b7199bddb6eb090ed09938d3ca2fcc21e Mon Sep 17 00:00:00 2001 From: Jeon Mingyu Date: Sat, 18 Jul 2026 23:58:07 +0900 Subject: [PATCH 10/27] Update package inventory for control kernel --- fixtures/package-inventory/packaged-files.v0.json | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/fixtures/package-inventory/packaged-files.v0.json b/fixtures/package-inventory/packaged-files.v0.json index 6e91255..d35d7e4 100644 --- a/fixtures/package-inventory/packaged-files.v0.json +++ b/fixtures/package-inventory/packaged-files.v0.json @@ -1,11 +1,11 @@ { "schemaVersion": "packaged-files.v0", - "totalUniqueFiles": 186, - "totalPackedFiles": 187, + "totalUniqueFiles": 191, + "totalPackedFiles": 192, "classes": [ { "class": "runtime", - "count": 68, + "count": 72, "files": [ "bin/boulder.js", "bin/boulder.ts", @@ -22,6 +22,10 @@ "src/cli-options.ts", "src/cli-run-recording.ts", "src/cli.ts", + "src/control-kernel-command.ts", + "src/control-kernel-types.ts", + "src/control-kernel-validation.ts", + "src/control-kernel.ts", "src/executor-adapters.ts", "src/executors.ts", "src/export.ts", @@ -176,12 +180,13 @@ }, { "class": "fixture", - "count": 24, + "count": 25, "files": [ "fixtures/benchmarks/mcp-server.json", "fixtures/benchmarks/python-package.json", "fixtures/benchmarks/typescript-library.json", "fixtures/capabilities/codex-installed.json", + "fixtures/control-kernel/gp-screening-shadow-v0.json", "fixtures/docs/doc-registry.v0.json", "fixtures/handoffs/high.json", "fixtures/handoffs/low.json", From 361d6dd1a7529d4753ba1c9140412a9ed22e9355 Mon Sep 17 00:00:00 2001 From: Jeon Mingyu Date: Sat, 18 Jul 2026 23:58:43 +0900 Subject: [PATCH 11/27] Update package inventory contract --- test/package-inventory-contract.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/package-inventory-contract.test.ts b/test/package-inventory-contract.test.ts index c39f419..3115aa5 100644 --- a/test/package-inventory-contract.test.ts +++ b/test/package-inventory-contract.test.ts @@ -39,13 +39,13 @@ describe("package inventory contract", () => { const summary = assertClassified(parsePackDryRun(output), inventory); expect(result.exitCode).toBe(0); - expect(summary.totalUniqueFiles).toBe(186); - expect(summary.totalPackedFiles).toBe(187); + expect(summary.totalUniqueFiles).toBe(191); + expect(summary.totalPackedFiles).toBe(192); expect(summary.counts).toEqual({ - runtime: 68, + runtime: 72, "public-doc": 64, "case-study-evidence": 21, - fixture: 24, + fixture: 25, skill: 6, config: 1, license: 1, From e37251c73d5ef611b947c737cf8f9b7b6fbcb2f4 Mon Sep 17 00:00:00 2001 From: Jeon Mingyu Date: Sun, 19 Jul 2026 00:07:44 +0900 Subject: [PATCH 12/27] Add temporary control-kernel CI diagnostics --- .../workflows/control-kernel-diagnostics.yml | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 .github/workflows/control-kernel-diagnostics.yml diff --git a/.github/workflows/control-kernel-diagnostics.yml b/.github/workflows/control-kernel-diagnostics.yml new file mode 100644 index 0000000..76e2b2c --- /dev/null +++ b/.github/workflows/control-kernel-diagnostics.yml @@ -0,0 +1,131 @@ +name: Control Kernel Diagnostics + +on: + pull_request: + branches: + - main + +permissions: + contents: read + +jobs: + typecheck: + name: TypeScript contract + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: oven-sh/setup-bun@v2 + with: + bun-version: "1.3.14" + - name: Run strict TypeScript check + id: check + shell: bash + run: | + set +e + bunx tsc --noEmit > diagnostic.txt 2>&1 + status=$? + cat diagnostic.txt + exit "$status" + - name: Upload typecheck failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: typecheck-failure + path: diagnostic.txt + + focused-tests: + name: New control-kernel tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: oven-sh/setup-bun@v2 + with: + bun-version: "1.3.14" + - name: Run focused test files + shell: bash + run: | + set +e + : > diagnostic.txt + for file in test/control-kernel.test.ts test/control-kernel-cli-e2e.test.ts test/package-inventory-contract.test.ts; do + echo "=== $file ===" >> diagnostic.txt + bun test "$file" >> diagnostic.txt 2>&1 + status=$? + if [ "$status" -ne 0 ]; then + echo "$file" > failed-test.txt + cat diagnostic.txt >> failed-test.txt + exit "$status" + fi + done + - name: Upload focused-test failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: focused-test-failure + path: failed-test.txt + + test-shards: + name: Existing tests ${{ matrix.shard }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + shard: + - a-f + - g-l + - m-r + - s-z + steps: + - uses: actions/checkout@v4 + - uses: oven-sh/setup-bun@v2 + with: + bun-version: "1.3.14" + - name: Run one test file at a time + shell: bash + env: + SHARD: ${{ matrix.shard }} + run: | + set +e + selected=0 + while IFS= read -r file; do + name=$(basename "$file") + first=$(printf '%s' "$name" | cut -c1 | tr '[:upper:]' '[:lower:]') + case "$SHARD" in + a-f) [[ "$first" < "a" || "$first" > "f" ]] && continue ;; + g-l) [[ "$first" < "g" || "$first" > "l" ]] && continue ;; + m-r) [[ "$first" < "m" || "$first" > "r" ]] && continue ;; + s-z) [[ "$first" < "s" || "$first" > "z" ]] && continue ;; + esac + selected=$((selected + 1)) + bun test "$file" > one-test.log 2>&1 + status=$? + if [ "$status" -ne 0 ]; then + { + echo "$file" + echo "" + cat one-test.log + } > failed-test.txt + exit "$status" + fi + done < <(find test -maxdepth 1 -type f -name '*.test.ts' | sort) + echo "passed-files=$selected" + - name: Upload shard failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: test-shard-${{ matrix.shard }}-failure + path: failed-test.txt + + build-package: + name: Build and package + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: oven-sh/setup-bun@v2 + with: + bun-version: "1.3.14" + - name: Build CLI + shell: bash + run: bun run build + - name: Package dry run + shell: bash + run: bun run pack:dry-run From e7a7977dcb7d05a4f7555e069ad6841c72da6fd1 Mon Sep 17 00:00:00 2001 From: Jeon Mingyu Date: Sun, 19 Jul 2026 00:09:47 +0900 Subject: [PATCH 13/27] Align diagnostics with full CI checkout --- .../workflows/control-kernel-diagnostics.yml | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/.github/workflows/control-kernel-diagnostics.yml b/.github/workflows/control-kernel-diagnostics.yml index 76e2b2c..7fd7483 100644 --- a/.github/workflows/control-kernel-diagnostics.yml +++ b/.github/workflows/control-kernel-diagnostics.yml @@ -14,11 +14,12 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 - uses: oven-sh/setup-bun@v2 with: bun-version: "1.3.14" - name: Run strict TypeScript check - id: check shell: bash run: | set +e @@ -38,6 +39,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 - uses: oven-sh/setup-bun@v2 with: bun-version: "1.3.14" @@ -63,6 +66,35 @@ jobs: name: focused-test-failure path: failed-test.txt + full-suite: + name: Full Bun test suite + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: oven-sh/setup-bun@v2 + with: + bun-version: "1.3.14" + - name: Run full test suite + shell: bash + run: | + set +e + bun test > full-test.log 2>&1 + status=$? + if [ "$status" -ne 0 ]; then + cp full-test.log failed-test.txt + else + cat full-test.log + fi + exit "$status" + - name: Upload full-suite failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: full-test-failure + path: failed-test.txt + test-shards: name: Existing tests ${{ matrix.shard }} runs-on: ubuntu-latest @@ -76,6 +108,8 @@ jobs: - s-z steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 - uses: oven-sh/setup-bun@v2 with: bun-version: "1.3.14" @@ -120,6 +154,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 - uses: oven-sh/setup-bun@v2 with: bun-version: "1.3.14" From a87a4d64a62ffe1034777bb9d0d7ce76b03a83b9 Mon Sep 17 00:00:00 2001 From: Jeon Mingyu Date: Sun, 19 Jul 2026 00:13:31 +0900 Subject: [PATCH 14/27] Make replay check ordering deterministic --- src/replay-check.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/replay-check.ts b/src/replay-check.ts index ff0715b..3e42695 100644 --- a/src/replay-check.ts +++ b/src/replay-check.ts @@ -54,7 +54,7 @@ export async function evaluateReplayCheck(root: string): Promise Date: Sun, 19 Jul 2026 00:13:51 +0900 Subject: [PATCH 15/27] Make replay run ordering deterministic --- src/replay-run.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/replay-run.ts b/src/replay-run.ts index 67c1cda..ce64d20 100644 --- a/src/replay-run.ts +++ b/src/replay-run.ts @@ -37,7 +37,7 @@ export async function buildReplayRunPlan(root: string, dryRunOnly = true): Promi } const projects = []; const issues = []; - for (const project of await readdir(replayRoot)) { + for (const project of (await readdir(replayRoot)).sort()) { const replayPath = join(replayRoot, project, "replay.json"); const parsed = parseJsonObject(await safeRead(replayPath)); if (!isReplayManifest(parsed)) { From a29bc40f07e81aca5f22ef888bacb11bd80c9562 Mon Sep 17 00:00:00 2001 From: Jeon Mingyu Date: Sun, 19 Jul 2026 00:14:45 +0900 Subject: [PATCH 16/27] Stabilize service readiness evidence ordering --- src/service-readiness.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service-readiness.ts b/src/service-readiness.ts index af384d8..6cc031d 100644 --- a/src/service-readiness.ts +++ b/src/service-readiness.ts @@ -200,7 +200,7 @@ async function loadOfficialDocs(root: string): Promise { const replayRoot = join(root, "fixtures", "replay"); if (!await exists(replayRoot)) return []; - const projects = await readdir(replayRoot); + const projects = (await readdir(replayRoot)).sort(); const paths = []; for (const project of projects) { const path = `fixtures/replay/${project}/${fileName}`; From 20e2424d1eb2154afe5ea74baacc73a82bf74a7d Mon Sep 17 00:00:00 2001 From: Jeon Mingyu Date: Sun, 19 Jul 2026 00:15:04 +0900 Subject: [PATCH 17/27] Refresh deterministic service readiness baseline --- test/fixtures/baselines/readiness-v0/service-readiness.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/fixtures/baselines/readiness-v0/service-readiness.json b/test/fixtures/baselines/readiness-v0/service-readiness.json index 9d0b882..a5f8f77 100644 --- a/test/fixtures/baselines/readiness-v0/service-readiness.json +++ b/test/fixtures/baselines/readiness-v0/service-readiness.json @@ -14,12 +14,12 @@ { "id": "official-docs-coverage", "status": "pass", - "evidence": "fixtures/replay/gajae-code/official-docs.json, fixtures/replay/awesome-codex-subagents/official-docs.json, fixtures/replay/kimi-agent-swarm-skill/official-docs.json" + "evidence": "fixtures/replay/awesome-codex-subagents/official-docs.json, fixtures/replay/gajae-code/official-docs.json, fixtures/replay/kimi-agent-swarm-skill/official-docs.json" }, { "id": "external-replay", "status": "pass", - "evidence": "fixtures/replay/gajae-code/replay.json, fixtures/replay/awesome-codex-subagents/replay.json, fixtures/replay/kimi-agent-swarm-skill/replay.json" + "evidence": "fixtures/replay/awesome-codex-subagents/replay.json, fixtures/replay/gajae-code/replay.json, fixtures/replay/kimi-agent-swarm-skill/replay.json" }, { "id": "handoff-validation", From 4455ffed950899f15fb9849c869b748d659e8edf Mon Sep 17 00:00:00 2001 From: Jeon Mingyu Date: Sun, 19 Jul 2026 00:15:41 +0900 Subject: [PATCH 18/27] Separate published and candidate release expectations --- test/release-evidence-bundle.test.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/test/release-evidence-bundle.test.ts b/test/release-evidence-bundle.test.ts index f144b90..66f009a 100644 --- a/test/release-evidence-bundle.test.ts +++ b/test/release-evidence-bundle.test.ts @@ -48,6 +48,14 @@ const READY_RELEASE_EXPECTATION = { packDryRunFileCount: READY_RELEASE_BUNDLE.packDryRun.fileCount } satisfies ReleaseEvidenceExpectation; +const CHECKED_RELEASE_EXPECTATION = { + packageJsonVersion: releaseManifest.packageJsonVersion, + cliVersion: releaseManifest.cliVersion, + tag: releaseManifest.tag, + releaseCommit: releaseManifest.releaseCommit, + packDryRunFileCount: releaseManifest.packDryRun.fileCount +} satisfies ReleaseEvidenceExpectation; + describe("ReleaseEvidenceBundleV1", () => { test("validates and renders a ready v0.1.16 bundle for the release evidence targets", () => { const parsed = parseReleaseEvidenceBundle(READY_RELEASE_BUNDLE); @@ -74,8 +82,8 @@ describe("ReleaseEvidenceBundleV1", () => { expect(rendered["docs/PRODUCT_READINESS.md"]).toBe(`- public-release-check: pass - release-check ready for ${packageJson.version}\n`); }); - test("reports current checked release evidence as ready", () => { - const validation = checkReleaseEvidenceBundle(parseReleaseEvidenceBundle(releaseManifest), READY_RELEASE_EXPECTATION); + test("reports checked published release evidence as internally consistent", () => { + const validation = checkReleaseEvidenceBundle(parseReleaseEvidenceBundle(releaseManifest), CHECKED_RELEASE_EXPECTATION); expect(validation.status).toBe("pass"); expect(validation.issues).toEqual([]); From 63845190a4382fe3e9a5a032b353e8bcb34991cf Mon Sep 17 00:00:00 2001 From: Jeon Mingyu Date: Sun, 19 Jul 2026 00:15:55 +0900 Subject: [PATCH 19/27] Refresh deterministic service readiness document --- docs/SERVICE_READINESS.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/SERVICE_READINESS.md b/docs/SERVICE_READINESS.md index f14bb83..3258a3b 100644 --- a/docs/SERVICE_READINESS.md +++ b/docs/SERVICE_READINESS.md @@ -6,8 +6,8 @@ Status: ready - service-loop: pass - docs/SERVICE_LOOP.md - onboarding: pass - docs/ONBOARDING.md -- official-docs-coverage: pass - fixtures/replay/gajae-code/official-docs.json, fixtures/replay/awesome-codex-subagents/official-docs.json, fixtures/replay/kimi-agent-swarm-skill/official-docs.json -- external-replay: pass - fixtures/replay/gajae-code/replay.json, fixtures/replay/awesome-codex-subagents/replay.json, fixtures/replay/kimi-agent-swarm-skill/replay.json +- official-docs-coverage: pass - fixtures/replay/awesome-codex-subagents/official-docs.json, fixtures/replay/gajae-code/official-docs.json, fixtures/replay/kimi-agent-swarm-skill/official-docs.json +- external-replay: pass - fixtures/replay/awesome-codex-subagents/replay.json, fixtures/replay/gajae-code/replay.json, fixtures/replay/kimi-agent-swarm-skill/replay.json - handoff-validation: pass - fixtures/handoffs/low.json, fixtures/handoffs/medium.json, fixtures/handoffs/high.json - service-acceptance-gates: pass - fixtures/service-readiness/gates.json - field-evidence: pass - evidence/field-readiness/oss-run-1 From 44038663210e3fd3f9cf34972b9221118db82c52 Mon Sep 17 00:00:00 2001 From: Jeon Mingyu Date: Sun, 19 Jul 2026 00:17:40 +0900 Subject: [PATCH 20/27] Refresh candidate package dry-run baseline --- .../baselines/readiness-v0/pack-dry-run.txt | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/test/fixtures/baselines/readiness-v0/pack-dry-run.txt b/test/fixtures/baselines/readiness-v0/pack-dry-run.txt index 0dfd40e..2492373 100644 --- a/test/fixtures/baselines/readiness-v0/pack-dry-run.txt +++ b/test/fixtures/baselines/readiness-v0/pack-dry-run.txt @@ -95,11 +95,12 @@ packed 0.70KB fixtures/benchmarks/mcp-server.json packed 0.69KB fixtures/benchmarks/python-package.json packed 0.72KB fixtures/benchmarks/typescript-library.json packed 1.47KB fixtures/capabilities/codex-installed.json +packed 7.68KB fixtures/control-kernel/gp-screening-shadow-v0.json packed 19.46KB fixtures/docs/doc-registry.v0.json packed 0.91KB fixtures/handoffs/high.json packed 0.63KB fixtures/handoffs/low.json packed 0.74KB fixtures/handoffs/medium.json -packed 8.86KB fixtures/package-inventory/packaged-files.v0.json +packed 9.1KB fixtures/package-inventory/packaged-files.v0.json packed 2.0KB fixtures/profiles/resolved/ops-default.json packed 2.12KB fixtures/profiles/resolved/programming-default.json packed 2.0KB fixtures/profiles/resolved/research-default.json @@ -129,11 +130,15 @@ packed 11.00KB src/capability-doctor.ts packed 7.1KB src/capability-inventory.ts packed 3.29KB src/capability-source-schema.ts packed 9.87KB src/capability-source.ts -packed 4.98KB src/cli-format.ts +packed 5.35KB src/cli-format.ts packed 10.52KB src/cli-ops-command.ts packed 1.79KB src/cli-options.ts packed 1.99KB src/cli-run-recording.ts -packed 7.39KB src/cli.ts +packed 7.59KB src/cli.ts +packed 15.40KB src/control-kernel-command.ts +packed 4.14KB src/control-kernel-types.ts +packed 11.34KB src/control-kernel-validation.ts +packed 8.66KB src/control-kernel.ts packed 1.50KB src/executor-adapters.ts packed 1.59KB src/executors.ts packed 1.25KB src/export.ts @@ -162,8 +167,8 @@ packed 7.73KB src/release-evidence-bundle.ts packed 7.86KB src/release-evidence.ts packed 6.26KB src/release-manifest-check.ts packed 5.87KB src/release-plan.ts -packed 7.99KB src/replay-check.ts -packed 3.80KB src/replay-run.ts +packed 8.00KB src/replay-check.ts +packed 3.81KB src/replay-run.ts packed 4.37KB src/routine-command.ts packed 5.17KB src/routine-retro.ts packed 5.76KB src/routine.ts @@ -174,7 +179,7 @@ packed 1.99KB src/runs-command.ts packed 7.1KB src/scorecard.ts packed 2.62KB src/service-field-evidence.ts packed 5.48KB src/service-gates.ts -packed 9.65KB src/service-readiness.ts +packed 9.66KB src/service-readiness.ts packed 6.10KB src/skill-proposal.ts packed 7.42KB src/task-scoring.ts packed 1.91KB src/templates/export.ts @@ -190,5 +195,5 @@ packed 1.75KB src/workflows.ts boulder-oss-cli-0.1.16.tgz -Total files: 187 -Unpacked size: 0.73MB +Total files: 192 +Unpacked size: 0.78MB From 8587e96635bd55b9b15c47461d3f43aaa80c9a7e Mon Sep 17 00:00:00 2001 From: Jeon Mingyu Date: Sun, 19 Jul 2026 00:19:21 +0900 Subject: [PATCH 21/27] Remove temporary control-kernel diagnostics --- .../workflows/control-kernel-diagnostics.yml | 167 ------------------ 1 file changed, 167 deletions(-) delete mode 100644 .github/workflows/control-kernel-diagnostics.yml diff --git a/.github/workflows/control-kernel-diagnostics.yml b/.github/workflows/control-kernel-diagnostics.yml deleted file mode 100644 index 7fd7483..0000000 --- a/.github/workflows/control-kernel-diagnostics.yml +++ /dev/null @@ -1,167 +0,0 @@ -name: Control Kernel Diagnostics - -on: - pull_request: - branches: - - main - -permissions: - contents: read - -jobs: - typecheck: - name: TypeScript contract - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - uses: oven-sh/setup-bun@v2 - with: - bun-version: "1.3.14" - - name: Run strict TypeScript check - shell: bash - run: | - set +e - bunx tsc --noEmit > diagnostic.txt 2>&1 - status=$? - cat diagnostic.txt - exit "$status" - - name: Upload typecheck failure - if: failure() - uses: actions/upload-artifact@v4 - with: - name: typecheck-failure - path: diagnostic.txt - - focused-tests: - name: New control-kernel tests - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - uses: oven-sh/setup-bun@v2 - with: - bun-version: "1.3.14" - - name: Run focused test files - shell: bash - run: | - set +e - : > diagnostic.txt - for file in test/control-kernel.test.ts test/control-kernel-cli-e2e.test.ts test/package-inventory-contract.test.ts; do - echo "=== $file ===" >> diagnostic.txt - bun test "$file" >> diagnostic.txt 2>&1 - status=$? - if [ "$status" -ne 0 ]; then - echo "$file" > failed-test.txt - cat diagnostic.txt >> failed-test.txt - exit "$status" - fi - done - - name: Upload focused-test failure - if: failure() - uses: actions/upload-artifact@v4 - with: - name: focused-test-failure - path: failed-test.txt - - full-suite: - name: Full Bun test suite - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - uses: oven-sh/setup-bun@v2 - with: - bun-version: "1.3.14" - - name: Run full test suite - shell: bash - run: | - set +e - bun test > full-test.log 2>&1 - status=$? - if [ "$status" -ne 0 ]; then - cp full-test.log failed-test.txt - else - cat full-test.log - fi - exit "$status" - - name: Upload full-suite failure - if: failure() - uses: actions/upload-artifact@v4 - with: - name: full-test-failure - path: failed-test.txt - - test-shards: - name: Existing tests ${{ matrix.shard }} - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - shard: - - a-f - - g-l - - m-r - - s-z - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - uses: oven-sh/setup-bun@v2 - with: - bun-version: "1.3.14" - - name: Run one test file at a time - shell: bash - env: - SHARD: ${{ matrix.shard }} - run: | - set +e - selected=0 - while IFS= read -r file; do - name=$(basename "$file") - first=$(printf '%s' "$name" | cut -c1 | tr '[:upper:]' '[:lower:]') - case "$SHARD" in - a-f) [[ "$first" < "a" || "$first" > "f" ]] && continue ;; - g-l) [[ "$first" < "g" || "$first" > "l" ]] && continue ;; - m-r) [[ "$first" < "m" || "$first" > "r" ]] && continue ;; - s-z) [[ "$first" < "s" || "$first" > "z" ]] && continue ;; - esac - selected=$((selected + 1)) - bun test "$file" > one-test.log 2>&1 - status=$? - if [ "$status" -ne 0 ]; then - { - echo "$file" - echo "" - cat one-test.log - } > failed-test.txt - exit "$status" - fi - done < <(find test -maxdepth 1 -type f -name '*.test.ts' | sort) - echo "passed-files=$selected" - - name: Upload shard failure - if: failure() - uses: actions/upload-artifact@v4 - with: - name: test-shard-${{ matrix.shard }}-failure - path: failed-test.txt - - build-package: - name: Build and package - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - uses: oven-sh/setup-bun@v2 - with: - bun-version: "1.3.14" - - name: Build CLI - shell: bash - run: bun run build - - name: Package dry run - shell: bash - run: bun run pack:dry-run From e28a388fe6f1b50cf612e5cac146c44036d6c7e6 Mon Sep 17 00:00:00 2001 From: Jeon Mingyu Date: Sun, 19 Jul 2026 00:22:12 +0900 Subject: [PATCH 22/27] Block seals for ineligible control runs --- src/control-kernel.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/control-kernel.ts b/src/control-kernel.ts index b3c7520..4cd866a 100644 --- a/src/control-kernel.ts +++ b/src/control-kernel.ts @@ -55,6 +55,7 @@ export async function evaluateControlRun(runValue: unknown, manifestValue: unkno if (run?.status !== undefined && run.status !== "completed") issues.push(`run-status:${run.status}`); if (run) { for (const call of run.toolCalls) { + if (call.status !== "completed") issues.push(`tool-call:not-completed:${call.toolId}:${call.status}`); if (call.status === "completed" && call.outputHash === null) issues.push(`tool-call:completed-output-missing:${call.toolId}`); } const allowedSignals = new Set(policy?.hardFailures.map((rule) => rule.signal) ?? []); @@ -89,6 +90,7 @@ export async function createControlDecisionSeal( ): Promise { const evaluation = await evaluateControlRun(runValue, manifestValue, policyValue); const issues = [...evaluation.issues]; + if (evaluation.status !== "eligible") issues.push("decision-seal:evaluation-blocked"); if (!isIso(sealedAt)) issues.push("decision-seal:sealedAt-invalid"); if (issues.length > 0) throw new Error(`Invalid control seal input: ${unique(issues).join(", ")}`); const run = runValue as ControlRunEvent; @@ -118,6 +120,7 @@ export async function verifyControlDecisionSeal( ): Promise { const evaluation = await evaluateControlRun(runValue, manifestValue, policyValue); const issues = [...validateControlDecisionSeal(sealValue), ...evaluation.issues]; + if (evaluation.status !== "eligible") issues.push("decision-seal:evaluation-blocked"); if (issues.length > 0 || !isControlDecisionSeal(sealValue) || !isControlRunEvent(runValue) || !isControlEvidenceManifest(manifestValue) || !isControlPolicy(policyValue)) { return { status: "invalid", issues: unique(issues) }; } @@ -136,12 +139,17 @@ export async function verifyControlDecisionSeal( if (seal.runHash !== runHash) issues.push("decision-seal:run-hash-mismatch"); if (seal.evidenceManifestHash !== manifestHash) issues.push("decision-seal:evidence-manifest-hash-mismatch"); if (seal.policyHash !== policyHash) issues.push("decision-seal:policy-hash-mismatch"); - const unsigned = { ...seal } as Record; - delete unsigned.sealHash; - if (seal.sealHash !== await hashControlValue(unsigned)) issues.push("decision-seal:seal-hash-mismatch"); + if (!await controlDecisionSealHashIsValid(seal)) issues.push("decision-seal:seal-hash-mismatch"); return { status: issues.length === 0 ? "valid" : "invalid", issues: unique(issues) }; } +export async function controlDecisionSealHashIsValid(sealValue: unknown): Promise { + if (!isControlDecisionSeal(sealValue)) return false; + const unsigned = { ...sealValue } as Record; + delete unsigned.sealHash; + return sealValue.sealHash === await hashControlValue(unsigned); +} + export async function hashControlValue(value: unknown): Promise { const bytes = new TextEncoder().encode(JSON.stringify(canonicalize(value))); const digest = await crypto.subtle.digest("SHA-256", bytes); From 0946d3e476227af55935b42e1f262e31b3e081ac Mon Sep 17 00:00:00 2001 From: Jeon Mingyu Date: Sun, 19 Jul 2026 00:23:51 +0900 Subject: [PATCH 23/27] Test that blocked runs cannot be sealed --- test/control-kernel.test.ts | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/test/control-kernel.test.ts b/test/control-kernel.test.ts index 7529290..e25c783 100644 --- a/test/control-kernel.test.ts +++ b/test/control-kernel.test.ts @@ -51,6 +51,46 @@ describe("generic control kernel", () => { expect(result.metricChecks.find((item) => item.metricId === "risk-recall")?.status).toBe("fail"); }); + test("refuses to seal any run that is not promotion-eligible", async () => { + const fixture = await loadFixture(); + + await expect(createControlDecisionSeal( + fixture.hardFailureRun, + fixture.manifest, + fixture.policy, + "2026-07-18T14:03:00.000Z" + )).rejects.toThrow("decision-seal:evaluation-blocked"); + + await expect(createControlDecisionSeal( + fixture.metricFailureRun, + fixture.manifest, + fixture.policy, + "2026-07-18T14:03:00.000Z" + )).rejects.toThrow("decision-seal:evaluation-blocked"); + }); + + test("blocks incomplete tool calls before promotion or sealing", async () => { + const fixture = await loadFixture(); + const firstCall = fixture.passRun.toolCalls[0]; + if (!firstCall) throw new Error("Fixture tool call is missing."); + const failedToolRun: ControlRunEvent = { + ...fixture.passRun, + runId: "synthetic-failed-tool-run", + idempotencyKey: "synthetic-failed-tool-run-v1", + toolCalls: [{ ...firstCall, status: "failed", outputHash: null }] + }; + + const result = await evaluateControlRun(failedToolRun, fixture.manifest, fixture.policy); + expect(result.status).toBe("blocked"); + expect(result.issues).toContain("tool-call:not-completed:evidence-index:failed"); + await expect(createControlDecisionSeal( + failedToolRun, + fixture.manifest, + fixture.policy, + "2026-07-18T14:03:00.000Z" + )).rejects.toThrow("decision-seal:evaluation-blocked"); + }); + test("fails closed on unknown hard-failure signals and evidence after cutoff", async () => { const fixture = await loadFixture(); const unknownSignal: ControlRunEvent = { ...fixture.passRun, hardFailureSignals: ["unknown.signal"] }; @@ -92,6 +132,7 @@ describe("generic control kernel", () => { const result = await verifyControlDecisionSeal(seal, mismatched, fixture.manifest, fixture.policy); expect(result.status).toBe("invalid"); expect(result.issues).toContain("binding:evidence-manifest-hash-mismatch"); + expect(result.issues).toContain("decision-seal:evaluation-blocked"); }); }); From c92e03fe827d91919eaf9acfd6791613e909911f Mon Sep 17 00:00:00 2001 From: Jeon Mingyu Date: Sun, 19 Jul 2026 00:24:23 +0900 Subject: [PATCH 24/27] Test CLI seal refusal for blocked runs --- test/control-kernel-cli-e2e.test.ts | 46 +++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/test/control-kernel-cli-e2e.test.ts b/test/control-kernel-cli-e2e.test.ts index 40654f4..bf72c4f 100644 --- a/test/control-kernel-cli-e2e.test.ts +++ b/test/control-kernel-cli-e2e.test.ts @@ -11,7 +11,7 @@ describe("control kernel CLI", () => { const root = await tempRepo("boulder-control-kernel-"); try { const fixture = parseFixture(await readFile(fixturePath, "utf8")); - await writeInputs(root, fixture); + await writeInputs(root, fixture, fixture.runs.pass); const unaudited = await runBoulder(controlArgs("evaluate", root)); expect(unaudited.exitCode).toBe(1); @@ -54,10 +54,32 @@ describe("control kernel CLI", () => { await removeTempRepo(root); } }); + + test("records blocked runs for audit but refuses to seal them", async () => { + const root = await tempRepo("boulder-control-kernel-blocked-"); + try { + const fixture = parseFixture(await readFile(fixturePath, "utf8")); + await writeInputs(root, fixture, fixture.runs.hardFailure); + + const recorded = await runBoulder(["control", "record", "--cwd", root, "--event", "inputs/event.json", "--json"]); + expect(recorded.exitCode).toBe(0); + expect(readString(parseJson(recorded.stdout), "status")).toBe("recorded"); + + const evaluated = await runBoulder(controlArgs("evaluate", root)); + expect(evaluated.exitCode).toBe(1); + expect(readString(parseJson(evaluated.stdout), "status")).toBe("blocked"); + + const sealed = await runBoulder(controlArgs("seal", root)); + expect(sealed.exitCode).toBe(1); + expect(sealed.stderr).toContain("decision-seal:evaluation-blocked"); + } finally { + await removeTempRepo(root); + } + }); }); -async function writeInputs(root: string, fixture: Fixture): Promise { - await write(root, "inputs/event.json", JSON.stringify(fixture.runs.pass, null, 2)); +async function writeInputs(root: string, fixture: Fixture, run: Record): Promise { + await write(root, "inputs/event.json", JSON.stringify(run, null, 2)); await write(root, "inputs/manifest.json", JSON.stringify(fixture.evidenceManifest, null, 2)); await write(root, "inputs/policy.json", JSON.stringify(fixture.policy, null, 2)); } @@ -86,15 +108,27 @@ function verifyArgs(root: string): readonly string[] { type Fixture = { readonly policy: Record; readonly evidenceManifest: Record; - readonly runs: { readonly pass: Record }; + readonly runs: { + readonly pass: Record; + readonly hardFailure: Record; + }; }; function parseFixture(source: string): Fixture { const value: unknown = JSON.parse(source); - if (!isRecord(value) || !isRecord(value["policy"]) || !isRecord(value["evidenceManifest"]) || !isRecord(value["runs"]) || !isRecord(value["runs"]["pass"])) { + if (!isRecord(value) + || !isRecord(value["policy"]) + || !isRecord(value["evidenceManifest"]) + || !isRecord(value["runs"]) + || !isRecord(value["runs"]["pass"]) + || !isRecord(value["runs"]["hardFailure"])) { throw new Error("Invalid control-kernel fixture."); } - return { policy: value["policy"], evidenceManifest: value["evidenceManifest"], runs: { pass: value["runs"]["pass"] } }; + return { + policy: value["policy"], + evidenceManifest: value["evidenceManifest"], + runs: { pass: value["runs"]["pass"], hardFailure: value["runs"]["hardFailure"] } + }; } function parseJson(source: string): Record { From eea9b28e87429688f73d4f9c2033a0928375074f Mon Sep 17 00:00:00 2001 From: Jeon Mingyu Date: Sun, 19 Jul 2026 00:25:16 +0900 Subject: [PATCH 25/27] Normalize nonsemantic pack size fields in readiness baseline --- test/readiness-baseline-fixtures.test.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/test/readiness-baseline-fixtures.test.ts b/test/readiness-baseline-fixtures.test.ts index b8a57c4..b6d7bd0 100644 --- a/test/readiness-baseline-fixtures.test.ts +++ b/test/readiness-baseline-fixtures.test.ts @@ -43,7 +43,8 @@ async function expectCurrentBaselines(baselineDir: string): Promise { const pack = await runCommand("bun pm pack --dry-run --ignore-scripts", ROOT); expect(pack.exitCode).toBe(0); - expectWithLabel(`${pack.stdout}${pack.stderr}`, await readFile(join(baselineDir, "pack-dry-run.txt"), "utf8"), "pack-dry-run.txt"); + const expectedPack = await readFile(join(baselineDir, "pack-dry-run.txt"), "utf8"); + expectWithLabel(normalizePackDryRun(`${pack.stdout}${pack.stderr}`), normalizePackDryRun(expectedPack), "pack-dry-run.txt"); } async function expectJsonBaseline(name: string, actual: unknown, baselineDir: string): Promise { @@ -58,6 +59,12 @@ function expectWithLabel(actual: unknown, expected: unknown, label: string): voi } } +function normalizePackDryRun(value: string): string { + return value + .replace(/^packed\s+\S+\s+/gm, "packed ") + .replace(/^Unpacked size:\s+.+$/gm, "Unpacked size: "); +} + async function copyBaselineFixtures(sourceDir: string, targetDir: string): Promise { for (const name of ["release-check.json", "product-readiness.json", "service-readiness.json", "release-plan.json", "pack-dry-run.txt"]) { await write(join(targetDir, name), await readFile(join(sourceDir, name), "utf8")); From d622105741f3a085956c07ade5702d2cede6a34e Mon Sep 17 00:00:00 2001 From: Jeon Mingyu Date: Sun, 19 Jul 2026 00:27:11 +0900 Subject: [PATCH 26/27] Verify seal integrity before storing or reusing --- src/control-kernel-command.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/control-kernel-command.ts b/src/control-kernel-command.ts index 883d4a0..e5ebc45 100644 --- a/src/control-kernel-command.ts +++ b/src/control-kernel-command.ts @@ -5,6 +5,7 @@ import { prettyJson } from "./cli-format"; import { optionValue, subcommandAfter } from "./cli-options"; import { canonicalize, + controlDecisionSealHashIsValid, createControlDecisionSeal, evaluateControlRun, hashControlValue, @@ -125,11 +126,12 @@ export async function recordControlRunEvent(root: string, run: ControlRunEvent): export async function recordControlDecisionSeal(root: string, seal: ControlDecisionSeal): Promise { const issues = validateControlDecisionSeal(seal); + if (!await controlDecisionSealHashIsValid(seal)) issues.push("decision-seal:seal-hash-mismatch"); if (issues.length > 0) throw invalidInput("decision seal", issues); const location = await prepareArtifactLocation(root, "seals", seal.runId); if (await exists(location.absolute)) { const existing = await readStoredArtifact(root, location.relative); - if (isControlDecisionSeal(existing) && sameDecisionBinding(existing, seal)) { + if (isControlDecisionSeal(existing) && await controlDecisionSealHashIsValid(existing) && sameDecisionBinding(existing, seal)) { return { status: "already-sealed", runId: seal.runId, path: location.relative, seal: existing }; } throw new ControlKernelCommandError("seal_conflict", `Run ID already has a different seal: ${location.relative}`); From fe5c31dc8e735e81c49039034251382225ee66fa Mon Sep 17 00:00:00 2001 From: Jeon Mingyu Date: Sun, 19 Jul 2026 00:27:49 +0900 Subject: [PATCH 27/27] Test seal-file integrity before persistence and reuse --- test/control-kernel-cli-e2e.test.ts | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/control-kernel-cli-e2e.test.ts b/test/control-kernel-cli-e2e.test.ts index bf72c4f..5428946 100644 --- a/test/control-kernel-cli-e2e.test.ts +++ b/test/control-kernel-cli-e2e.test.ts @@ -1,6 +1,8 @@ import { readFile } from "node:fs/promises"; import { join } from "node:path"; import { describe, expect, test } from "bun:test"; +import { createControlDecisionSeal } from "../src/control-kernel"; +import { recordControlDecisionSeal } from "../src/control-kernel-command"; import { removeTempRepo, runBoulder, tempRepo, write } from "./helpers/cli"; const repositoryRoot = join(import.meta.dir, ".."); @@ -76,6 +78,29 @@ describe("control kernel CLI", () => { await removeTempRepo(root); } }); + + test("rejects forged or corrupted seal files instead of reusing them", async () => { + const root = await tempRepo("boulder-control-kernel-seal-integrity-"); + try { + const fixture = parseFixture(await readFile(fixturePath, "utf8")); + const seal = await createControlDecisionSeal( + fixture.runs.pass, + fixture.evidenceManifest, + fixture.policy, + "2026-07-18T14:03:00.000Z" + ); + const forged = { ...seal, sealHash: "0".repeat(64) }; + + await expect(recordControlDecisionSeal(root, forged)).rejects.toThrow("decision-seal:seal-hash-mismatch"); + + const stored = await recordControlDecisionSeal(root, seal); + expect(stored.status).toBe("sealed"); + await write(root, stored.path, JSON.stringify(forged, null, 2)); + await expect(recordControlDecisionSeal(root, seal)).rejects.toThrow("already has a different seal"); + } finally { + await removeTempRepo(root); + } + }); }); async function writeInputs(root: string, fixture: Fixture, run: Record): Promise {