{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../src/core/long-horizon/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAmCH,OAAO,KAAK,EACX,qBAAqB,EAMrB,MAAM,YAAY,CAAC;AAMpB;;;;;;;;;;;;GAYG;AACH,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAqB7E;AAQD,KAAK,kBAAkB,GAAG,qBAAqB,CAAC,UAAU,CAAC,CAAC;AAE5D,MAAM,MAAM,mCAAmC,GAC5C;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAA;CAAE,GACnG;IACA,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,IAAI,EAAE,2BAA2B,CAAC;IAC3C,QAAQ,CAAC,IAAI,EAAE,2BAA2B,CAAC;IAC3C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACtB,GACD;IACA,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACtB,GACD;IACA,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,IAAI,EAAE,6BAA6B,CAAC;IAC7C,QAAQ,CAAC,IAAI,EAAE,0BAA0B,CAAC;IAC1C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACtB,CAAC;AAmGL,8EAA8E;AAC9E,wBAAgB,iCAAiC,CAAC,OAAO,EAAE,OAAO,GAAG,mCAAmC,CA8FvG;AAMD,MAAM,WAAW,yBAAyB;IACzC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IAGjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IAGtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IAGd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,yBAAyB,CAAC,EAAE,MAAM,CAAC;CACnC;AAED,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAiE/E","sourcesContent":["/**\n * CLI handler for \"jensen benchmark long-horizon\" commands.\n *\n * Extends the benchmark CLI with mission contract and requirement ledger\n * management commands. All commands route before model selection and\n * provider loading.\n *\n * Trust Model (LH-1 hardened):\n *   - The generic CLI uses the UNTRUSTED context.\n *   - Payload role labels (--actor-type, --collector-type, reportedAuthority)\n *     are descriptive only — they NEVER grant privilege.\n *   - The generic CLI REJECTS privileged operations:\n *       SATISFIED transition → exit 1 TRUSTED_CONTEXT_REQUIRED\n *       Runtime NOT_APPLICABLE → exit 1 TRUSTED_CONTEXT_REQUIRED\n *       Authoritative evidence insertion → exit 1 UNTRUSTED_AUTHORITY_CLAIM\n *   - Trusted satisfaction is unavailable through the generic CLI.\n */\n\nimport chalk from \"chalk\";\nimport { randomBytes } from \"crypto\";\nimport { existsSync, readFileSync, renameSync, unlinkSync, writeFileSync } from \"fs\";\nimport { dirname, resolve } from \"path\";\nimport {\n\tabandonContinuation,\n\ttype ContinuationSchedulerRecord,\n\tcancelContinuation,\n\tconsumeContinuation,\n\tdispatchContinuation,\n\tinitializeContinuationScheduler,\n\tinspectContinuationScheduler,\n\tscheduleContinuation,\n\tvalidateContinuationScheduler,\n} from \"./continuation-scheduler.js\";\nimport { computeMissionContractDigest } from \"./contract-digest.js\";\nimport {\n\tapplyMissionExecutionTransition,\n\tinitializeMissionExecution,\n\tinspectMissionExecution,\n\ttype MissionExecutionRecordV1,\n\ttype MissionExecutionTransitionKind,\n\tvalidateMissionExecutionRecord,\n} from \"./execution-state-machine.js\";\nimport { inspectLedgerStructure } from \"./ledger-summary.js\";\nimport { validateMissionContract } from \"./mission-contract-schema.js\";\nimport {\n\taddLedgerEvidence,\n\tapplyRequirementTransition,\n\tinitializeRequirementLedger,\n\tinspectRequirementLedgerStructure,\n} from \"./requirement-ledger.js\";\nimport { getUntrustedContext } from \"./trusted-context.js\";\nimport type {\n\tLedgerEvidenceRequest,\n\tMissionContractV1,\n\tRequirementLedgerV1,\n\tStructuralLedgerInspection,\n\tTransitionRequest,\n\tValidationResult,\n} from \"./types.js\";\n\n// =============================================================================\n// Strict expectedRevision parser\n// =============================================================================\n\n/**\n * Parse a string as a canonical non-negative integer suitable for use as\n * an expectedRevision value. Rejects:\n *  - decimals: \"1.0\", \"12.5\"\n *  - scientific notation: \"1e2\"\n *  - leading sign: \"+1\", \"-1\"\n *  - leading zeros: \"01\" (except \"0\" itself)\n *  - NaN, Infinity, -Infinity\n *  - empty or whitespace-only strings\n *  - values exceeding Number.MAX_SAFE_INTEGER\n *\n * Accepts only: \"0\", \"1\", \"12\", \"9007199254740991\"\n */\nexport function parseStrictNonNegativeInteger(raw: string): number | undefined {\n\tif (raw === undefined || raw === null) return undefined;\n\tif (typeof raw !== \"string\") return undefined;\n\n\t// Reject empty or whitespace-only\n\tif (raw.length === 0) return undefined;\n\tif (raw.trim().length === 0) return undefined;\n\n\t// Must match canonical decimal: one or more digits, no leading sign, no leading zero except \"0\" itself\n\tif (!/^(?:0|[1-9][0-9]*)$/.test(raw)) {\n\t\treturn undefined;\n\t}\n\n\tconst value = Number(raw);\n\n\t// Number() for canonical integer strings should equal the integer value;\n\t// additionally require integer and safe.\n\tif (!Number.isSafeInteger(value)) return undefined;\n\tif (value < 0) return undefined;\n\n\treturn value;\n}\n\n// =============================================================================\n// Utilities\n// =============================================================================\n\nconst MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB\n\ntype GenericCliEvidence = LedgerEvidenceRequest[\"evidence\"];\n\nexport type GenericCliEvidencePayloadValidation =\n\t| { readonly ok: true; readonly kind: \"ordinary-agent-claim\"; readonly evidence: GenericCliEvidence }\n\t| {\n\t\t\treadonly ok: false;\n\t\t\treadonly kind: \"attempted-authority-claim\";\n\t\t\treadonly code: \"UNTRUSTED_AUTHORITY_CLAIM\";\n\t\t\treadonly field: string;\n\t  }\n\t| {\n\t\t\treadonly ok: false;\n\t\t\treadonly kind: \"malformed-evidence\";\n\t\t\treadonly code: \"MALFORMED_EVIDENCE\";\n\t\t\treadonly field: string;\n\t  }\n\t| {\n\t\t\treadonly ok: false;\n\t\t\treadonly kind: \"trusted-context-unavailable\";\n\t\t\treadonly code: \"TRUSTED_CONTEXT_REQUIRED\";\n\t\t\treadonly field: string;\n\t  };\n\nconst SERIALIZED_TRUST_CONTEXT_KEYS: ReadonlySet<string> = new Set([\n\t\"trustedvalidationcontext\",\n\t\"validationcontext\",\n\t\"trustedledgermutationcontext\",\n\t\"ledgermutationcontext\",\n\t\"mutationcontext\",\n\t\"principal\",\n\t\"principalid\",\n\t\"principalkind\",\n\t\"principals\",\n\t\"principalregistry\",\n\t\"capability\",\n\t\"capabilities\",\n\t\"capabilityregistry\",\n\t\"sourcegrant\",\n\t\"sourcegrants\",\n\t\"sourcegrantregistry\",\n\t\"verifiedprincipalid\",\n\t\"verifiedprincipalkind\",\n\t\"verifiedcapability\",\n]);\n\nconst AUTHORITY_KEYS: ReadonlySet<string> = new Set([\n\t\"authority\",\n\t\"requestedauthority\",\n\t\"effectiveauthority\",\n\t\"authorityclassification\",\n\t\"requestedauthorityclassification\",\n]);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isStringArray(value: unknown): value is string[] {\n\treturn Array.isArray(value) && value.every((item) => typeof item === \"string\");\n}\n\nfunction findSerializedTrustContext(value: unknown, path = \"evidence\"): string | undefined {\n\tif (Array.isArray(value)) {\n\t\tfor (let index = 0; index < value.length; index++) {\n\t\t\tconst found = findSerializedTrustContext(value[index], `${path}[${index}]`);\n\t\t\tif (found) return found;\n\t\t}\n\t\treturn undefined;\n\t}\n\tif (!isRecord(value)) return undefined;\n\n\tfor (const [key, nestedValue] of Object.entries(value)) {\n\t\tconst normalizedKey = key.replace(/[^a-z0-9]/gi, \"\").toLowerCase();\n\t\tconst nestedPath = `${path}.${key}`;\n\t\tif (SERIALIZED_TRUST_CONTEXT_KEYS.has(normalizedKey)) return nestedPath;\n\t\tconst found = findSerializedTrustContext(nestedValue, nestedPath);\n\t\tif (found) return found;\n\t}\n\treturn undefined;\n}\n\nfunction findAuthorityClaim(value: unknown, path = \"evidence\"): string | undefined {\n\tif (Array.isArray(value)) {\n\t\tfor (let index = 0; index < value.length; index++) {\n\t\t\tconst found = findAuthorityClaim(value[index], `${path}[${index}]`);\n\t\t\tif (found) return found;\n\t\t}\n\t\treturn undefined;\n\t}\n\tif (!isRecord(value)) return undefined;\n\n\tfor (const [key, nestedValue] of Object.entries(value)) {\n\t\tconst normalizedKey = key.replace(/[^a-z0-9]/gi, \"\").toLowerCase();\n\t\tconst nestedPath = `${path}.${key}`;\n\t\tif (normalizedKey === \"reportedauthority\" && nestedValue === true) return nestedPath;\n\t\tif (AUTHORITY_KEYS.has(normalizedKey) && nestedValue !== \"agent-claim\") return nestedPath;\n\t\tif (normalizedKey === \"trusted\" && nestedValue === true) return nestedPath;\n\t\tif (normalizedKey === \"boundcontractdigest\") return nestedPath;\n\t\tif (\n\t\t\t(normalizedKey === \"collectortype\" ||\n\t\t\t\tnormalizedKey === \"reportedcollectortype\" ||\n\t\t\t\tnormalizedKey === \"collectorclass\") &&\n\t\t\ttypeof nestedValue === \"string\" &&\n\t\t\tnestedValue.toLowerCase() === \"trusted-collector\"\n\t\t) {\n\t\t\treturn nestedPath;\n\t\t}\n\t\tif (\n\t\t\t(normalizedKey === \"source\" || normalizedKey === \"sourceid\") &&\n\t\t\ttypeof nestedValue === \"string\" &&\n\t\t\t/(?:^|[^a-z])(trusted|authoritative)(?:[^a-z]|$)/i.test(nestedValue)\n\t\t) {\n\t\t\treturn nestedPath;\n\t\t}\n\t\tconst found = findAuthorityClaim(nestedValue, nestedPath);\n\t\tif (found) return found;\n\t}\n\treturn undefined;\n}\n\n/** Validate and normalize evidence accepted by the generic, untrusted CLI. */\nexport function validateGenericCliEvidencePayload(payload: unknown): GenericCliEvidencePayloadValidation {\n\tif (!isRecord(payload)) {\n\t\treturn { ok: false, kind: \"malformed-evidence\", code: \"MALFORMED_EVIDENCE\", field: \"evidence\" };\n\t}\n\n\tconst serializedContextField = findSerializedTrustContext(payload);\n\tif (serializedContextField) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\tkind: \"trusted-context-unavailable\",\n\t\t\tcode: \"TRUSTED_CONTEXT_REQUIRED\",\n\t\t\tfield: serializedContextField,\n\t\t};\n\t}\n\n\tconst authorityField = findAuthorityClaim(payload);\n\tif (authorityField) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\tkind: \"attempted-authority-claim\",\n\t\t\tcode: \"UNTRUSTED_AUTHORITY_CLAIM\",\n\t\t\tfield: authorityField,\n\t\t};\n\t}\n\n\tif (typeof payload.id !== \"string\" || payload.id.trim().length === 0) {\n\t\treturn { ok: false, kind: \"malformed-evidence\", code: \"MALFORMED_EVIDENCE\", field: \"evidence.id\" };\n\t}\n\tif (typeof payload.type !== \"string\" || payload.type.trim().length === 0) {\n\t\treturn { ok: false, kind: \"malformed-evidence\", code: \"MALFORMED_EVIDENCE\", field: \"evidence.type\" };\n\t}\n\tif (!isStringArray(payload.requirementIds)) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\tkind: \"malformed-evidence\",\n\t\t\tcode: \"MALFORMED_EVIDENCE\",\n\t\t\tfield: \"evidence.requirementIds\",\n\t\t};\n\t}\n\tif (payload.criterionIds !== undefined && !isStringArray(payload.criterionIds)) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\tkind: \"malformed-evidence\",\n\t\t\tcode: \"MALFORMED_EVIDENCE\",\n\t\t\tfield: \"evidence.criterionIds\",\n\t\t};\n\t}\n\tif (payload.status !== undefined && ![\"pass\", \"fail\", \"unknown\"].includes(String(payload.status))) {\n\t\treturn { ok: false, kind: \"malformed-evidence\", code: \"MALFORMED_EVIDENCE\", field: \"evidence.status\" };\n\t}\n\tfor (const field of [\"source\", \"summary\", \"digest\", \"claimText\"] as const) {\n\t\tif (payload[field] !== undefined && typeof payload[field] !== \"string\") {\n\t\t\treturn { ok: false, kind: \"malformed-evidence\", code: \"MALFORMED_EVIDENCE\", field: `evidence.${field}` };\n\t\t}\n\t}\n\tif (payload.collectorType !== undefined && typeof payload.collectorType !== \"string\") {\n\t\treturn {\n\t\t\tok: false,\n\t\t\tkind: \"malformed-evidence\",\n\t\t\tcode: \"MALFORMED_EVIDENCE\",\n\t\t\tfield: \"evidence.collectorType\",\n\t\t};\n\t}\n\tif (payload.reportedAuthority !== undefined && typeof payload.reportedAuthority !== \"boolean\") {\n\t\treturn {\n\t\t\tok: false,\n\t\t\tkind: \"malformed-evidence\",\n\t\t\tcode: \"MALFORMED_EVIDENCE\",\n\t\t\tfield: \"evidence.reportedAuthority\",\n\t\t};\n\t}\n\tif (payload.metadata !== undefined && !isRecord(payload.metadata)) {\n\t\treturn { ok: false, kind: \"malformed-evidence\", code: \"MALFORMED_EVIDENCE\", field: \"evidence.metadata\" };\n\t}\n\n\treturn {\n\t\tok: true,\n\t\tkind: \"ordinary-agent-claim\",\n\t\tevidence: {\n\t\t\tid: payload.id,\n\t\t\ttype: payload.type,\n\t\t\trequirementIds: [...payload.requirementIds],\n\t\t\tcriterionIds: payload.criterionIds === undefined ? [] : [...payload.criterionIds],\n\t\t\tstatus: (payload.status as \"pass\" | \"fail\" | \"unknown\" | undefined) ?? \"unknown\",\n\t\t\tsource: (payload.source as string | undefined) ?? \"\",\n\t\t\tsummary: (payload.summary as string | undefined) ?? \"\",\n\t\t\tdigest: payload.digest as string | undefined,\n\t\t\tclaimText: payload.claimText as string | undefined,\n\t\t\treportedCollectorType:\n\t\t\t\t(payload.collectorType as GenericCliEvidence[\"reportedCollectorType\"] | undefined) ?? \"agent\",\n\t\t\treportedAuthority: false,\n\t\t\tmetadata: payload.metadata,\n\t\t},\n\t};\n}\n\n// =============================================================================\n// Entry point — called from benchmark handler\n// =============================================================================\n\nexport interface LongHorizonCommandOptions {\n\thelp?: boolean;\n\tformat?: \"text\" | \"json\";\n\toutput?: string;\n\tcommand?: string;\n\n\t// For ledger operations\n\tcontract?: string;\n\tledger?: string;\n\trequirementId?: string;\n\ttoStatus?: string;\n\texpectedRevision?: number;\n\tactorType?: string;\n\treason?: string;\n\tevidenceIds?: string[];\n\tblockerReference?: string;\n\tevidenceInput?: string;\n\ttransitionId?: string;\n\n\t// For execution operations\n\texecution?: string;\n\texecutionId?: string;\n\tkind?: string;\n\n\t// For continuation scheduler operations\n\tscheduler?: string;\n\teventId?: string;\n\tcycleId?: string;\n\tdispatchedContinuationId?: string;\n\tresultDigest?: string;\n\texpectedSchedulerRevision?: number;\n\texpectedExecutionRevision?: number;\n}\n\nexport async function handleLongHorizonCommand(args: string[]): Promise<boolean> {\n\tif (args[0] !== \"benchmark\") return false;\n\tif (args[1] !== \"long-horizon\") return false;\n\n\tconst options = parseLongHorizonArgs(args);\n\n\tif (options.help) {\n\t\tprintLongHorizonHelp();\n\t\treturn true;\n\t}\n\n\tif (!options.command) {\n\t\t// No long-horizon subcommand matched — let the existing evaluate handler take over\n\t\treturn false;\n\t}\n\n\ttry {\n\t\tswitch (options.command) {\n\t\t\tcase \"mission-validate\":\n\t\t\t\treturn await handleMissionValidate(options);\n\t\t\tcase \"mission-digest\":\n\t\t\t\treturn await handleMissionDigest(options);\n\t\t\tcase \"ledger-init\":\n\t\t\t\treturn await handleLedgerInit(options);\n\t\t\tcase \"ledger-validate\":\n\t\t\t\treturn await handleLedgerValidate(options);\n\t\t\tcase \"ledger-add-evidence\":\n\t\t\t\treturn await handleLedgerAddEvidence(options);\n\t\t\tcase \"ledger-transition\":\n\t\t\t\treturn await handleLedgerTransition(options);\n\t\t\tcase \"ledger-inspect\":\n\t\t\t\treturn await handleLedgerInspect(options);\n\t\t\tcase \"execution-init\":\n\t\t\t\treturn await handleExecutionInit(options);\n\t\t\tcase \"execution-inspect\":\n\t\t\t\treturn await handleExecutionInspect(options);\n\t\t\tcase \"execution-validate\":\n\t\t\t\treturn await handleExecutionValidate(options);\n\t\t\tcase \"execution-transition\":\n\t\t\t\treturn await handleExecutionTransition(options);\n\t\t\tcase \"continuation-init\":\n\t\t\t\treturn await handleContinuationInit(options);\n\t\t\tcase \"continuation-inspect\":\n\t\t\t\treturn await handleContinuationInspect(options);\n\t\t\tcase \"continuation-validate\":\n\t\t\t\treturn await handleContinuationValidate(options);\n\t\t\tcase \"continuation-schedule\":\n\t\t\t\treturn await handleContinuationSchedule(options);\n\t\t\tcase \"continuation-dispatch\":\n\t\t\t\treturn await handleContinuationDispatch(options);\n\t\t\tcase \"continuation-consume\":\n\t\t\t\treturn await handleContinuationConsume(options);\n\t\t\tcase \"continuation-cancel\":\n\t\t\t\treturn await handleContinuationCancel(options);\n\t\t\tcase \"continuation-abandon\":\n\t\t\t\treturn await handleContinuationAbandon(options);\n\t\t\tdefault:\n\t\t\t\treturn false; // Let the existing benchmark handler take over\n\t\t}\n\t} catch (err: unknown) {\n\t\tconst message = err instanceof Error ? err.message : \"Unknown error\";\n\t\tconsole.error(chalk.red(`Error: ${message}`));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n}\n\n// =============================================================================\n// Argument parsing\n// =============================================================================\n\nfunction parseLongHorizonArgs(args: string[]): LongHorizonCommandOptions {\n\tconst options: LongHorizonCommandOptions = {};\n\n\t// Phase 1: Extract the subcommand\n\tlet commandEnd = -1;\n\tfor (let i = 2; i < args.length - 1; i++) {\n\t\tconst arg = args[i];\n\t\tconst next = args[i + 1];\n\t\tif (arg === \"mission\" && [\"validate\", \"digest\"].includes(next)) {\n\t\t\toptions.command = `mission-${next}`;\n\t\t\tcommandEnd = i + 2;\n\t\t\tbreak;\n\t\t}\n\t\tif (arg === \"ledger\" && [\"init\", \"validate\", \"add-evidence\", \"transition\", \"inspect\"].includes(next)) {\n\t\t\toptions.command = `ledger-${next}`;\n\t\t\tcommandEnd = i + 2;\n\t\t\tbreak;\n\t\t}\n\t\tif (arg === \"execution\" && [\"init\", \"inspect\", \"validate\", \"transition\"].includes(next)) {\n\t\t\toptions.command = `execution-${next}`;\n\t\t\tcommandEnd = i + 2;\n\t\t\tbreak;\n\t\t}\n\t\tif (\n\t\t\targ === \"continuation\" &&\n\t\t\t[\"init\", \"inspect\", \"validate\", \"schedule\", \"dispatch\", \"consume\", \"cancel\", \"abandon\"].includes(next)\n\t\t) {\n\t\t\toptions.command = `continuation-${next}`;\n\t\t\tcommandEnd = i + 2;\n\t\t\tbreak;\n\t\t}\n\t\tif (arg === \"evaluate\") {\n\t\t\treturn options;\n\t\t}\n\t}\n\n\t// Phase 2: Strict flag parsing with per-operation allowlists\n\tconst remainingArgs = commandEnd >= 0 ? args.slice(commandEnd) : args.slice(2);\n\tconst isContinuationCommand = options.command?.startsWith(\"continuation-\") ?? false;\n\tconst command = options.command ?? \"\";\n\n\t// Define per-operation flag allowlists\n\tconst continuationAllowlists: Record<string, Set<string>> = {\n\t\t\"continuation-init\": new Set([\"scheduler\", \"contract\", \"execution-id\", \"format\", \"json\"]),\n\t\t\"continuation-inspect\": new Set([\"scheduler\", \"format\", \"json\"]),\n\t\t\"continuation-validate\": new Set([\"scheduler\", \"contract\", \"execution\", \"format\", \"json\"]),\n\t\t\"continuation-schedule\": new Set([\n\t\t\t\"scheduler\",\n\t\t\t\"contract\",\n\t\t\t\"execution\",\n\t\t\t\"event-id\",\n\t\t\t\"expected-scheduler-revision\",\n\t\t\t\"expected-execution-revision\",\n\t\t\t\"format\",\n\t\t\t\"json\",\n\t\t]),\n\t\t\"continuation-dispatch\": new Set([\n\t\t\t\"scheduler\",\n\t\t\t\"contract\",\n\t\t\t\"execution\",\n\t\t\t\"event-id\",\n\t\t\t\"cycle-id\",\n\t\t\t\"dispatched-continuation-id\",\n\t\t\t\"expected-scheduler-revision\",\n\t\t\t\"format\",\n\t\t\t\"json\",\n\t\t]),\n\t\t\"continuation-consume\": new Set([\n\t\t\t\"scheduler\",\n\t\t\t\"contract\",\n\t\t\t\"execution\",\n\t\t\t\"event-id\",\n\t\t\t\"cycle-id\",\n\t\t\t\"dispatched-continuation-id\",\n\t\t\t\"expected-scheduler-revision\",\n\t\t\t\"result-digest\",\n\t\t\t\"format\",\n\t\t\t\"json\",\n\t\t]),\n\t\t\"continuation-cancel\": new Set([\n\t\t\t\"scheduler\",\n\t\t\t\"contract\",\n\t\t\t\"execution\",\n\t\t\t\"event-id\",\n\t\t\t\"cycle-id\",\n\t\t\t\"expected-scheduler-revision\",\n\t\t\t\"format\",\n\t\t\t\"json\",\n\t\t]),\n\t\t\"continuation-abandon\": new Set([\n\t\t\t\"scheduler\",\n\t\t\t\"contract\",\n\t\t\t\"execution\",\n\t\t\t\"event-id\",\n\t\t\t\"cycle-id\",\n\t\t\t\"expected-scheduler-revision\",\n\t\t\t\"format\",\n\t\t\t\"json\",\n\t\t]),\n\t};\n\n\t// Generic flags shared across all non-continuation commands\n\tconst genericFlags = new Set([\n\t\t\"help\",\n\t\t\"h\",\n\t\t\"format\",\n\t\t\"output\",\n\t\t\"contract\",\n\t\t\"ledger\",\n\t\t\"requirement-id\",\n\t\t\"to-status\",\n\t\t\"expected-revision\",\n\t\t\"actor-type\",\n\t\t\"reason\",\n\t\t\"evidence-ids\",\n\t\t\"blocker-reference\",\n\t\t\"evidence-input\",\n\t\t\"transition-id\",\n\t\t\"execution\",\n\t\t\"execution-id\",\n\t\t\"kind\",\n\t\t\"scheduler\",\n\t\t\"event-id\",\n\t\t\"cycle-id\",\n\t\t\"dispatched-continuation-id\",\n\t\t\"result-digest\",\n\t\t\"expected-scheduler-revision\",\n\t\t\"expected-execution-revision\",\n\t]);\n\n\tconst allowlist = isContinuationCommand ? continuationAllowlists[command] : null;\n\tconst seenFlags = new Set<string>();\n\tlet i = 0;\n\n\twhile (i < remainingArgs.length) {\n\t\tconst arg = remainingArgs[i];\n\n\t\tif (arg === \"--help\" || arg === \"-h\") {\n\t\t\toptions.help = true;\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// All subsequent tokens must be flags (start with --)\n\t\tif (!arg.startsWith(\"--\")) {\n\t\t\tthrow new Error(`unexpected positional argument: ${arg}`);\n\t\t}\n\n\t\tconst flagName = arg.slice(2);\n\t\tif (flagName.length === 0) {\n\t\t\tthrow new Error(\"empty flag name\");\n\t\t}\n\n\t\t// Check for duplicate flags\n\t\tif (seenFlags.has(flagName)) {\n\t\t\tthrow new Error(`duplicate flag: --${flagName}`);\n\t\t}\n\t\tseenFlags.add(flagName);\n\n\t\t// Enforce per-operation allowlist\n\t\tif (allowlist !== null && !allowlist.has(flagName)) {\n\t\t\t// --output on continuation commands is rejected\n\t\t\tthrow new Error(`unknown flag for ${command}: --${flagName}`);\n\t\t}\n\n\t\t// Check if flag is recognized at all (for non-continuation commands)\n\t\tif (allowlist === null && !genericFlags.has(flagName)) {\n\t\t\tthrow new Error(`unknown flag: --${flagName}`);\n\t\t}\n\n\t\t// Known flags that need a value\n\t\tconst flagsNeedingValue = new Set([\n\t\t\t\"format\",\n\t\t\t\"output\",\n\t\t\t\"contract\",\n\t\t\t\"ledger\",\n\t\t\t\"requirement-id\",\n\t\t\t\"to-status\",\n\t\t\t\"expected-revision\",\n\t\t\t\"actor-type\",\n\t\t\t\"reason\",\n\t\t\t\"evidence-ids\",\n\t\t\t\"blocker-reference\",\n\t\t\t\"evidence-input\",\n\t\t\t\"transition-id\",\n\t\t\t\"execution\",\n\t\t\t\"execution-id\",\n\t\t\t\"kind\",\n\t\t\t\"scheduler\",\n\t\t\t\"event-id\",\n\t\t\t\"cycle-id\",\n\t\t\t\"dispatched-continuation-id\",\n\t\t\t\"result-digest\",\n\t\t\t\"expected-scheduler-revision\",\n\t\t\t\"expected-execution-revision\",\n\t\t]);\n\n\t\tif (flagsNeedingValue.has(flagName)) {\n\t\t\tif (i + 1 >= remainingArgs.length) {\n\t\t\t\tthrow new Error(`missing value for --${flagName}`);\n\t\t\t}\n\t\t\tconst value = remainingArgs[i + 1];\n\n\t\t\tif (flagName === \"format\") {\n\t\t\t\tif (value === \"text\" || value === \"json\") {\n\t\t\t\t\toptions.format = value;\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error(`Unknown format: ${value}`);\n\t\t\t\t}\n\t\t\t} else if (flagName === \"output\") {\n\t\t\t\toptions.output = value;\n\t\t\t} else if (flagName === \"contract\") {\n\t\t\t\toptions.contract = value;\n\t\t\t} else if (flagName === \"ledger\") {\n\t\t\t\toptions.ledger = value;\n\t\t\t} else if (flagName === \"requirement-id\") {\n\t\t\t\toptions.requirementId = value;\n\t\t\t} else if (flagName === \"to-status\") {\n\t\t\t\toptions.toStatus = value;\n\t\t\t} else if (flagName === \"expected-revision\") {\n\t\t\t\tconst parsed = parseStrictNonNegativeInteger(value);\n\t\t\t\tif (parsed === undefined) {\n\t\t\t\t\t(options as LongHorizonCommandOptions & { _invalidExpectedRevision?: string })._invalidExpectedRevision =\n\t\t\t\t\t\tvalue;\n\t\t\t\t} else {\n\t\t\t\t\toptions.expectedRevision = parsed;\n\t\t\t\t}\n\t\t\t} else if (flagName === \"actor-type\") {\n\t\t\t\toptions.actorType = value;\n\t\t\t} else if (flagName === \"reason\") {\n\t\t\t\toptions.reason = value;\n\t\t\t} else if (flagName === \"evidence-ids\") {\n\t\t\t\toptions.evidenceIds = value\n\t\t\t\t\t.split(\",\")\n\t\t\t\t\t.map((s) => s.trim())\n\t\t\t\t\t.filter((s) => s.length > 0);\n\t\t\t} else if (flagName === \"blocker-reference\") {\n\t\t\t\toptions.blockerReference = value;\n\t\t\t} else if (flagName === \"evidence-input\") {\n\t\t\t\toptions.evidenceInput = value;\n\t\t\t} else if (flagName === \"transition-id\") {\n\t\t\t\toptions.transitionId = value;\n\t\t\t} else if (flagName === \"execution\") {\n\t\t\t\toptions.execution = value;\n\t\t\t} else if (flagName === \"execution-id\") {\n\t\t\t\toptions.executionId = value;\n\t\t\t} else if (flagName === \"kind\") {\n\t\t\t\toptions.kind = value;\n\t\t\t} else if (flagName === \"scheduler\") {\n\t\t\t\toptions.scheduler = value;\n\t\t\t} else if (flagName === \"event-id\") {\n\t\t\t\toptions.eventId = value;\n\t\t\t} else if (flagName === \"cycle-id\") {\n\t\t\t\toptions.cycleId = value;\n\t\t\t} else if (flagName === \"dispatched-continuation-id\") {\n\t\t\t\toptions.dispatchedContinuationId = value;\n\t\t\t} else if (flagName === \"result-digest\") {\n\t\t\t\toptions.resultDigest = value;\n\t\t\t} else if (flagName === \"expected-scheduler-revision\") {\n\t\t\t\tconst parsed = parseStrictNonNegativeInteger(value);\n\t\t\t\tif (parsed === undefined) {\n\t\t\t\t\t(\n\t\t\t\t\t\toptions as LongHorizonCommandOptions & { _invalidExpectedSchedulerRevision?: string }\n\t\t\t\t\t)._invalidExpectedSchedulerRevision = value;\n\t\t\t\t} else {\n\t\t\t\t\toptions.expectedSchedulerRevision = parsed;\n\t\t\t\t}\n\t\t\t} else if (flagName === \"expected-execution-revision\") {\n\t\t\t\tconst parsed = parseStrictNonNegativeInteger(value);\n\t\t\t\tif (parsed === undefined) {\n\t\t\t\t\t(\n\t\t\t\t\t\toptions as LongHorizonCommandOptions & { _invalidExpectedExecutionRevision?: string }\n\t\t\t\t\t)._invalidExpectedExecutionRevision = value;\n\t\t\t\t} else {\n\t\t\t\t\toptions.expectedExecutionRevision = parsed;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ti += 2;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Flags that don't need a value (json is a boolean-style flag)\n\t\tif (flagName === \"json\") {\n\t\t\toptions.format = \"json\";\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Unknown unrecognized\n\t\ti++;\n\t}\n\n\treturn options;\n}\n\n// =============================================================================\n// Help\n// =============================================================================\n\nfunction printLongHorizonHelp(): void {\n\tconsole.log(`${chalk.bold(\"Usage:\")} jensen benchmark long-horizon <command> [options]\n\n${chalk.bold(\"Mission Contract Commands:\")}\n  mission validate     Validate a mission contract JSON file\n  mission digest       Compute the deterministic SHA-256 digest of a mission contract\n\n${chalk.bold(\"Requirement Ledger Commands:\")}\n  ledger init          Initialize a requirement ledger from a mission contract\n  ledger validate      Validate a requirement ledger against its contract\n  ledger add-evidence  Add an evidence record to the ledger (append-only)\n  ledger transition    Apply a state transition to a requirement\n  ledger inspect       Display a summary of the ledger\n\n${chalk.bold(\"Execution State Machine Commands:\")}\n  execution init       Initialize a mission execution record (starts in PLANNING)\n  execution inspect    Inspect an execution record structurally (untrusted)\n  execution validate   Validate an execution record against its contract\n  execution transition Apply a state transition to an execution record\n\n${chalk.bold(\"Continuation Scheduler Commands:\")}\n  continuation init      Initialize a continuation scheduler record (IDLE@0)\n  continuation inspect   Inspect a scheduler record structurally (no contract/execution)\n  continuation validate  Validate scheduler against contract and execution record\n  continuation schedule  Schedule a continuation cycle (IDLE → SCHEDULED)\n  continuation dispatch  Dispatch a continuation (SCHEDULED → DISPATCHED)\n  continuation consume   Consume a dispatched continuation (DISPATCHED → IDLE)\n  continuation cancel    Cancel an active cycle (SCHEDULED/DISPATCHED → IDLE)\n  continuation abandon   Abandon a superseded cycle (SCHEDULED/DISPATCHED → IDLE)\n\n${chalk.bold(\"Common Options:\")}\n  --contract <path>           Path to mission contract JSON file\n  --ledger <path>             Path to requirement ledger JSON file\n  --format <text|json>        Output format (default: text)\n  --output <path>             Write output to file\n  --expected-revision <num>   Expected ledger revision (for mutation commands)\n  --requirement-id <id>       Requirement ID to operate on\n  --to-status <status>        Target status for transition\n  --actor-type <type>         Descriptive actor type (agent, etc.) — NOT authorization\n  --reason <text>             Reason for the operation\n  --evidence-ids <id1,id2>    Comma-separated evidence IDs\n  --blocker-reference <text>  Blocker reference for BLOCKED transitions\n  --evidence-input <path>     Path to evidence JSON for add-evidence\n\n${chalk.yellow.bold(\"Trust Model:\")}\n  The generic CLI is UNTRUSTED. Payload role labels are descriptive only.\n  SATISFIED and runtime NOT_APPLICABLE require a trusted context (not available via CLI).\n  Unknown semantic fields in contract JSON are rejected.\n\n${chalk.bold(\"Examples:\")}\n  jensen benchmark long-horizon mission validate --contract contract.json\n  jensen benchmark long-horizon mission digest --contract contract.json\n  jensen benchmark long-horizon ledger init --contract contract.json --output ledger.json\n  jensen benchmark long-horizon ledger validate --contract contract.json --ledger ledger.json\n  jensen benchmark long-horizon ledger transition --contract contract.json --ledger ledger.json --expected-revision 0 --requirement-id REQ-001 --to-status PENDING --reason \"Starting work\"\n\n${chalk.bold(\"Exit Codes:\")}\n  0   Valid operation completed\n  1   Invalid contract, ledger, rejected transition, stale revision, read error, parse error, trust error, output-write error, unknown command\n`);\n}\n\n// =============================================================================\n// Command: mission validate\n// =============================================================================\n\nasync function handleMissionValidate(options: LongHorizonCommandOptions): Promise<boolean> {\n\tif (!options.contract) {\n\t\tconsole.error(chalk.red(\"Error: --contract is required\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst contract = readContractFile(options.contract);\n\tif (!contract) return true;\n\n\tconst result = validateMissionContract(contract);\n\tconst format = options.format ?? \"text\";\n\n\tif (format === \"json\") {\n\t\tconst output = JSON.stringify(result, null, 2);\n\t\twriteOutput(output, options);\n\t} else {\n\t\tprintTextValidationResult(result);\n\t}\n\n\tif (!result.valid) {\n\t\tprocess.exitCode = 1;\n\t}\n\n\treturn true;\n}\n\n// =============================================================================\n// Command: mission digest\n// =============================================================================\n\nasync function handleMissionDigest(options: LongHorizonCommandOptions): Promise<boolean> {\n\tif (!options.contract) {\n\t\tconsole.error(chalk.red(\"Error: --contract is required\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst contract = readContractFileAndParse(options.contract);\n\tif (!contract) return true;\n\n\tconst digest = computeMissionContractDigest(contract);\n\tconst format = options.format ?? \"text\";\n\n\tif (format === \"json\") {\n\t\tconst output = JSON.stringify({ digest }, null, 2);\n\t\twriteOutput(output, options);\n\t} else {\n\t\tconsole.log(digest);\n\t}\n\n\treturn true;\n}\n\n// =============================================================================\n// Command: ledger init\n// =============================================================================\n\nasync function handleLedgerInit(options: LongHorizonCommandOptions): Promise<boolean> {\n\tif (!options.contract) {\n\t\tconsole.error(chalk.red(\"Error: --contract is required\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst contract = readContractFileAndParse(options.contract);\n\tif (!contract) return true;\n\n\tconst result = initializeRequirementLedger(contract);\n\tif (!result.ok) {\n\t\tconsole.error(chalk.red(`Error: ${result.error}`));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst _format = options.format ?? \"text\";\n\twriteLedgerOutput(result.value!, options);\n\n\treturn true;\n}\n\n// =============================================================================\n// Command: ledger validate\n// =============================================================================\n\nasync function handleLedgerValidate(options: LongHorizonCommandOptions): Promise<boolean> {\n\tif (!options.contract) {\n\t\tconsole.error(chalk.red(\"Error: --contract is required\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\tif (!options.ledger) {\n\t\tconsole.error(chalk.red(\"Error: --ledger is required\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst contract = readContractFileAndParse(options.contract);\n\tif (!contract) return true;\n\n\tconst ledger = readLedgerFile(options.ledger);\n\tif (!ledger) return true;\n\n\t// Route through structural inspection only.\n\t// The generic CLI cannot perform authoritative validation.\n\t// Trusted provenance is NOT verified here.\n\tconst inspection = inspectRequirementLedgerStructure(contract, ledger);\n\tconst format = options.format ?? \"text\";\n\n\tif (format === \"json\") {\n\t\tconst output = JSON.stringify(\n\t\t\t{\n\t\t\t\tstructurallyValid: inspection.structurallyValid,\n\t\t\t\ttrustVerified: false,\n\t\t\t\tcompletionCandidate: \"unavailable\",\n\t\t\t\terror: inspection.structurallyValid ? undefined : \"Ledger structure is invalid\",\n\t\t\t},\n\t\t\tnull,\n\t\t\t2,\n\t\t);\n\t\twriteOutput(output, options);\n\t} else {\n\t\tif (inspection.structurallyValid) {\n\t\t\tconsole.log(chalk.green(\"Ledger structure is valid.\"));\n\t\t\tconsole.log(chalk.yellow(\"Trusted provenance was not verified.\"));\n\t\t} else {\n\t\t\tconsole.log(chalk.red(\"Ledger structure is invalid.\"));\n\t\t}\n\t}\n\n\tif (!inspection.structurallyValid) process.exitCode = 1;\n\treturn true;\n}\n\n// =============================================================================\n// Command: ledger add-evidence\n// =============================================================================\n\nasync function handleLedgerAddEvidence(options: LongHorizonCommandOptions): Promise<boolean> {\n\tif (!options.contract || !options.ledger || !options.evidenceInput) {\n\t\tconsole.error(chalk.red(\"Error: --contract, --ledger, and --evidence-input are required\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\tif (options.expectedRevision === undefined) {\n\t\tconsole.error(chalk.red(\"Error: --expected-revision is required\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst contract = readContractFileAndParse(options.contract);\n\tif (!contract) return true;\n\n\tconst ledger = readLedgerFile(options.ledger);\n\tif (!ledger) return true;\n\n\tconst evidenceRaw = readFileContent(options.evidenceInput);\n\tif (!evidenceRaw) return true;\n\n\tlet evidenceData: unknown;\n\ttry {\n\t\tevidenceData = JSON.parse(evidenceRaw);\n\t} catch {\n\t\tconsole.error(chalk.red(\"Error parsing evidence input\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst payloadValidation = validateGenericCliEvidencePayload(evidenceData);\n\tif (!payloadValidation.ok) {\n\t\tconsole.error(chalk.red(`Error: ${payloadValidation.code}: ${payloadValidation.field}`));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\t// Use UNTRUSTED context — the generic CLI never provides trusted capabilities\n\tconst untrustedCtx = getUntrustedContext();\n\n\tconst request: LedgerEvidenceRequest = {\n\t\texpectedRevision: options.expectedRevision,\n\t\tevidence: payloadValidation.evidence,\n\t};\n\n\tconst result = addLedgerEvidence(contract, ledger, request, untrustedCtx);\n\tif (!result.ok) {\n\t\tconsole.error(chalk.red(`Error: ${result.code ? `${result.code}: ` : \"\"}${result.error}`));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\twriteLedgerOutput(result.value!, options);\n\treturn true;\n}\n\n// =============================================================================\n// Command: ledger transition\n// =============================================================================\n\nasync function handleLedgerTransition(options: LongHorizonCommandOptions): Promise<boolean> {\n\tif (!options.contract || !options.ledger || !options.requirementId || !options.toStatus || !options.transitionId) {\n\t\tconsole.error(\n\t\t\tchalk.red(\"Error: --contract, --ledger, --requirement-id, --to-status, and --transition-id are required\"),\n\t\t);\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\tif (options.expectedRevision === undefined) {\n\t\tconsole.error(chalk.red(\"Error: --expected-revision is required\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst contract = readContractFileAndParse(options.contract);\n\tif (!contract) return true;\n\n\tconst ledger = readLedgerFile(options.ledger);\n\tif (!ledger) return true;\n\n\tconst validStatuses = new Set([\n\t\t\"UNASSESSED\",\n\t\t\"PENDING\",\n\t\t\"IN_PROGRESS\",\n\t\t\"IMPLEMENTED_UNVERIFIED\",\n\t\t\"SATISFIED\",\n\t\t\"BLOCKED\",\n\t\t\"NOT_APPLICABLE\",\n\t\t\"FAILED\",\n\t]);\n\tif (!validStatuses.has(options.toStatus)) {\n\t\tconsole.error(chalk.red(`Error: invalid to-status: ${options.toStatus}`));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\t// Warning: the CLI is untrusted. SATISFIED and runtime NOT_APPLICABLE will be rejected.\n\tif (options.toStatus === \"SATISFIED\" || options.toStatus === \"NOT_APPLICABLE\") {\n\t\t// Check if this is a runtime NOT_APPLICABLE (not initial contract)\n\t\tconst isRuntimeNa = options.toStatus === \"NOT_APPLICABLE\";\n\t\tif (options.toStatus === \"SATISFIED\" || isRuntimeNa) {\n\t\t\t// Let the core API reject it with a proper error\n\t\t}\n\t}\n\n\t// Use UNTRUSTED context — the generic CLI never provides trusted capabilities\n\tconst untrustedCtx = getUntrustedContext();\n\n\tconst request: TransitionRequest = {\n\t\ttransitionId: options.transitionId,\n\t\texpectedRevision: options.expectedRevision,\n\t\trequirementId: options.requirementId,\n\t\ttoStatus: options.toStatus as TransitionRequest[\"toStatus\"],\n\t\t// Descriptive only — NOT authorization\n\t\treportedActorType: options.actorType ?? \"agent\",\n\t\treason: options.reason ?? \"\",\n\t\tevidenceIds: options.evidenceIds ?? [],\n\t\tblockerReference: options.blockerReference,\n\t};\n\n\tconst result = applyRequirementTransition(contract, ledger, request, untrustedCtx);\n\tif (!result.ok) {\n\t\tconsole.error(chalk.red(`Error: ${result.code ? `${result.code}: ` : \"\"}${result.error}`));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\twriteLedgerOutput(result.value!, options);\n\treturn true;\n}\n\n// =============================================================================\n// Command: ledger inspect\n// =============================================================================\n\nasync function handleLedgerInspect(options: LongHorizonCommandOptions): Promise<boolean> {\n\tif (!options.contract || !options.ledger) {\n\t\tconsole.error(chalk.red(\"Error: --contract and --ledger are required\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst contract = readContractFileAndParse(options.contract);\n\tif (!contract) return true;\n\n\tconst ledger = readLedgerFile(options.ledger);\n\tif (!ledger) return true;\n\n\tconst summary = inspectLedgerStructure(contract, ledger);\n\tconst format = options.format ?? \"text\";\n\n\tif (format === \"json\") {\n\t\tconst output = JSON.stringify(summary, null, 2);\n\t\twriteOutput(output, options);\n\t} else {\n\t\tprintTextStructuralInspection(summary);\n\t}\n\n\treturn true;\n}\n\n// =============================================================================\n// File I/O utilities\n// =============================================================================\n\nfunction readFileContent(path: string): string | null {\n\ttry {\n\t\tconst raw = readFileSync(path, \"utf-8\");\n\t\tif (Buffer.byteLength(raw, \"utf-8\") > MAX_FILE_SIZE) {\n\t\t\tconsole.error(chalk.red(\"Error: file exceeds 10MB limit\"));\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn null;\n\t\t}\n\t\treturn raw;\n\t} catch (err: unknown) {\n\t\tconst message = err instanceof Error ? err.message : \"Unknown error\";\n\t\tconsole.error(chalk.red(`Error reading file ${path}: ${message}`));\n\t\tprocess.exitCode = 1;\n\t\treturn null;\n\t}\n}\n\nfunction readContractFile(path: string): unknown | null {\n\tconst raw = readFileContent(path);\n\tif (!raw) return null;\n\ttry {\n\t\treturn JSON.parse(raw);\n\t} catch {\n\t\tconsole.error(chalk.red(\"Error parsing contract JSON\"));\n\t\tprocess.exitCode = 1;\n\t\treturn null;\n\t}\n}\n\nfunction readContractFileAndParse(path: string): MissionContractV1 | null {\n\tconst raw = readFileContent(path);\n\tif (!raw) return null;\n\ttry {\n\t\treturn JSON.parse(raw) as MissionContractV1;\n\t} catch {\n\t\tconsole.error(chalk.red(\"Error parsing contract JSON\"));\n\t\tprocess.exitCode = 1;\n\t\treturn null;\n\t}\n}\n\nfunction readLedgerFile(path: string): RequirementLedgerV1 | null {\n\tconst raw = readFileContent(path);\n\tif (!raw) return null;\n\ttry {\n\t\treturn JSON.parse(raw) as RequirementLedgerV1;\n\t} catch {\n\t\tconsole.error(chalk.red(\"Error parsing ledger JSON\"));\n\t\tprocess.exitCode = 1;\n\t\treturn null;\n\t}\n}\n\nfunction writeOutput(data: string, options: LongHorizonCommandOptions): void {\n\tif (options.output) {\n\t\twriteFileAtomic(options.output, data);\n\t} else {\n\t\tconsole.log(data);\n\t}\n}\n\nfunction writeLedgerOutput(ledger: RequirementLedgerV1, options: LongHorizonCommandOptions): void {\n\tconst format = options.format ?? \"text\";\n\tif (format === \"json\") {\n\t\tconst output = JSON.stringify(ledger, null, 2);\n\t\twriteOutput(output, options);\n\t} else {\n\t\tconst lines = [\n\t\t\t`Ledger revision: ${ledger.revision}`,\n\t\t\t...ledger.requirements.map((entry) => `  ${entry.requirementId}: ${entry.status}`),\n\t\t];\n\t\tconst text = lines.join(\"\\n\");\n\t\twriteOutput(text, options);\n\t}\n}\n\n// =============================================================================\n// Atomic file write\n// =============================================================================\n\nfunction writeFileAtomic(path: string, data: string): void {\n\tconst outputPath = resolve(path);\n\tif (outputPath.includes(\"..\")) {\n\t\tconsole.error(chalk.red(\"Error: --output path must not contain '..'\"));\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\n\tconst dir = dirname(outputPath);\n\tif (!existsSync(dir)) {\n\t\tconsole.error(chalk.red(`Error: directory ${dir} does not exist`));\n\t\tprocess.exitCode = 1;\n\t\treturn;\n\t}\n\n\tconst tmpPath = `${outputPath}.tmp.${randomBytes(4).toString(\"hex\")}`;\n\ttry {\n\t\twriteFileSync(tmpPath, data, \"utf-8\");\n\t\trenameSync(tmpPath, outputPath);\n\t} catch (err: unknown) {\n\t\t// Clean up temp file on failure\n\t\ttry {\n\t\t\tunlinkSync(tmpPath);\n\t\t} catch {}\n\t\tconst message = err instanceof Error ? err.message : \"Unknown error\";\n\t\tconsole.error(chalk.red(`Error writing output: ${message}`));\n\t\tprocess.exitCode = 1;\n\t}\n}\n\n// =============================================================================\n// Text formatting\n// =============================================================================\n\nfunction printTextValidationResult(result: ValidationResult): void {\n\tif (result.valid) {\n\t\tconsole.log(chalk.green(\"Contract is valid\"));\n\t} else {\n\t\tconsole.log(chalk.red(`Contract is invalid (${result.errors.length} errors):`));\n\t\tfor (const err of result.errors) {\n\t\t\tconsole.log(chalk.red(`  ${err.message}`));\n\t\t}\n\t}\n}\n\nfunction printTextStructuralInspection(summary: StructuralLedgerInspection): void {\n\tconsole.log(`${chalk.bold(\"Ledger Inspection (structural only)\")}`);\n\tconsole.log(`${\"Mission\".padEnd(28)} ${summary.missionId}`);\n\tconsole.log(`${\"Contract Digest\".padEnd(28)} ${summary.contractDigest}`);\n\tconsole.log(`${\"Ledger Revision\".padEnd(28)} ${summary.ledgerRevision}`);\n\tconsole.log(`${\"Total Requirements\".padEnd(28)} ${summary.totalRequirements}`);\n\tconsole.log(`${\"Applicable Requirements\".padEnd(28)} ${summary.applicableRequirements}`);\n\tconsole.log(`${\"Structurally Valid\".padEnd(28)} ${summary.structurallyValid ? \"Yes\" : \"No\"}`);\n\tconsole.log(\n\t\t`${chalk.yellow(\"Completion Candidate\".padEnd(28))} ${chalk.yellow(\"unavailable (trusted context required)\")}`,\n\t);\n\tconsole.log(\"\");\n\n\tconsole.log(chalk.bold(\"State Counts:\"));\n\tfor (const [state, count] of Object.entries(summary.stateCounts).sort(([a], [b]) => a.localeCompare(b))) {\n\t\tconsole.log(`  ${state.padEnd(24)} ${count}`);\n\t}\n\tconsole.log(\"\");\n\n\tif (summary.blockedRequirements.length > 0) {\n\t\tconsole.log(chalk.yellow(`Blocked: ${summary.blockedRequirements.join(\", \")}`));\n\t}\n\tif (summary.failedRequirements.length > 0) {\n\t\tconsole.log(chalk.red(`Failed: ${summary.failedRequirements.join(\", \")}`));\n\t}\n}\n\n// =============================================================================\n// Continuation Scheduler Commands\n// =============================================================================\n\nfunction readSchedulerFile(path: string): ContinuationSchedulerRecord | null {\n\tconst raw = readFileContent(path);\n\tif (!raw) return null;\n\ttry {\n\t\treturn JSON.parse(raw) as ContinuationSchedulerRecord;\n\t} catch {\n\t\tconsole.error(chalk.red(\"Error parsing scheduler record JSON\"));\n\t\tprocess.exitCode = 1;\n\t\treturn null;\n\t}\n}\n\nfunction readExecutionForBinding(\n\texecPath: string,\n\tcontractDigest: string,\n): { executionId: string; revision: number } | null {\n\tconst raw = readFileContent(execPath);\n\tif (!raw) return null;\n\ttry {\n\t\tconst record = JSON.parse(raw);\n\t\tif (typeof record.executionId !== \"string\" || record.executionId.trim().length === 0) {\n\t\t\tconsole.error(chalk.red(\"Error: execution record missing executionId\"));\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn null;\n\t\t}\n\t\tif (typeof record.contractDigest !== \"string\" || record.contractDigest !== contractDigest) {\n\t\t\tconsole.error(chalk.red(\"Error: contract digest mismatch between contract and execution record\"));\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn null;\n\t\t}\n\t\tif (!Number.isSafeInteger(record.revision) || record.revision < 0) {\n\t\t\tconsole.error(chalk.red(\"Error: execution record has invalid revision\"));\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn null;\n\t\t}\n\t\treturn { executionId: record.executionId, revision: record.revision };\n\t} catch {\n\t\tconsole.error(chalk.red(\"Error parsing execution record JSON\"));\n\t\tprocess.exitCode = 1;\n\t\treturn null;\n\t}\n}\n\nfunction writeSchedulerAtomic(path: string, data: string): boolean {\n\tconst outputPath = resolve(path);\n\tif (outputPath.includes(\"..\")) {\n\t\tconsole.error(chalk.red(\"Error: --scheduler path must not contain '..'\"));\n\t\tprocess.exitCode = 1;\n\t\treturn false;\n\t}\n\n\tconst dir = dirname(outputPath);\n\tif (!existsSync(dir)) {\n\t\tconsole.error(chalk.red(`Error: directory ${dir} does not exist`));\n\t\tprocess.exitCode = 1;\n\t\treturn false;\n\t}\n\n\tconst tmpPath = `${outputPath}.tmp.${randomBytes(4).toString(\"hex\")}`;\n\ttry {\n\t\twriteFileSync(tmpPath, data, \"utf-8\");\n\t\trenameSync(tmpPath, outputPath);\n\t\treturn true;\n\t} catch (err: unknown) {\n\t\ttry {\n\t\t\tunlinkSync(tmpPath);\n\t\t} catch {}\n\t\tconst message = err instanceof Error ? err.message : \"Unknown error\";\n\t\tconsole.error(chalk.red(`Error writing scheduler: ${message}`));\n\t\tprocess.exitCode = 1;\n\t\treturn false;\n\t}\n}\n\nasync function handleContinuationInit(options: LongHorizonCommandOptions): Promise<boolean> {\n\tif (!options.scheduler || !options.contract || !options.executionId) {\n\t\tconsole.error(chalk.red(\"Error: --scheduler, --contract, and --execution-id are required\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst contract = readContractFileAndParse(options.contract);\n\tif (!contract) return true;\n\n\tconst contractDigest = computeMissionContractDigest(contract);\n\n\tconst record = initializeContinuationScheduler(options.executionId, contractDigest);\n\tconst json = JSON.stringify(record, null, 2);\n\tif (!writeSchedulerAtomic(options.scheduler, json)) return true;\n\n\tconst format = options.format ?? \"text\";\n\tif (format === \"json\") {\n\t\tconsole.log(json);\n\t} else {\n\t\tconsole.log(`Scheduler initialized: ${options.scheduler}`);\n\t\tconsole.log(`  executionId: ${record.executionId}`);\n\t\tconsole.log(`  contractDigest: ${record.contractDigest}`);\n\t\tconsole.log(`  state: ${record.state}`);\n\t\tconsole.log(`  revision: ${record.schedulerRevision}`);\n\t}\n\treturn true;\n}\n\nasync function handleContinuationInspect(options: LongHorizonCommandOptions): Promise<boolean> {\n\tif (!options.scheduler) {\n\t\tconsole.error(chalk.red(\"Error: --scheduler is required\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tif (!existsSync(resolve(options.scheduler))) {\n\t\tconsole.error(chalk.red(\"Error: ENOENT: scheduler file not found\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst record = readSchedulerFile(options.scheduler);\n\tif (!record) return true;\n\n\tconst inspection = inspectContinuationScheduler(record);\n\tconst format = options.format ?? \"text\";\n\n\tif (format === \"json\") {\n\t\tconsole.log(JSON.stringify(inspection, null, 2));\n\t} else {\n\t\tif (inspection.valid) {\n\t\t\tconsole.log(chalk.bold(\"Continuation Scheduler Inspection (structural)\"));\n\t\t\tconsole.log(`${\"Execution ID\".padEnd(28)} ${inspection.executionId}`);\n\t\t\tconsole.log(`${\"Contract Digest\".padEnd(28)} ${inspection.contractDigest}`);\n\t\t\tconsole.log(`${\"State\".padEnd(28)} ${inspection.state}`);\n\t\t\tconsole.log(`${\"Revision\".padEnd(28)} ${inspection.schedulerRevision}`);\n\t\t\tconsole.log(`${\"Event Count\".padEnd(28)} ${inspection.eventCount}`);\n\t\t\tconsole.log(`${\"History Digest\".padEnd(28)} ${inspection.historyDigest ?? \"(none)\"}`);\n\t\t} else {\n\t\t\tconsole.log(chalk.red(`Invalid: ${inspection.error}`));\n\t\t}\n\t}\n\n\tif (!inspection.valid) process.exitCode = 1;\n\treturn true;\n}\n\nasync function handleContinuationValidate(options: LongHorizonCommandOptions): Promise<boolean> {\n\tif (!options.scheduler || !options.contract || !options.execution) {\n\t\tconsole.error(chalk.red(\"Error: --scheduler, --contract, and --execution are required\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tif (!existsSync(resolve(options.scheduler))) {\n\t\tconsole.error(chalk.red(\"Error: ENOENT: scheduler file not found\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst contract = readContractFileAndParse(options.contract);\n\tif (!contract) return true;\n\tconst contractDigest = computeMissionContractDigest(contract);\n\n\tconst record = readSchedulerFile(options.scheduler);\n\tif (!record) return true;\n\n\tconst execBinding = readExecutionForBinding(options.execution, contractDigest);\n\tif (!execBinding) return true;\n\n\tconst result = validateContinuationScheduler(record, contractDigest, execBinding.executionId, execBinding.revision);\n\tconst format = options.format ?? \"text\";\n\n\tif (format === \"json\") {\n\t\tconsole.log(JSON.stringify(result, null, 2));\n\t} else {\n\t\tif (result.valid) {\n\t\t\tconsole.log(chalk.green(\"Continuation scheduler is valid\"));\n\t\t} else {\n\t\t\tconsole.log(chalk.red(`Invalid: ${result.error}`));\n\t\t}\n\t\tconsole.log(`${\"Contract Bound\".padEnd(28)} ${result.contractBound ? \"Yes\" : \"No\"}`);\n\t\tconsole.log(`${\"Execution Bound\".padEnd(28)} ${result.executionBound ? \"Yes\" : \"No\"}`);\n\t\tconsole.log(`${\"Semantic Valid\".padEnd(28)} ${result.semanticValid ? \"Yes\" : \"No\"}`);\n\t}\n\n\tif (!result.valid) process.exitCode = 1;\n\treturn true;\n}\n\nasync function handleContinuationSchedule(options: LongHorizonCommandOptions): Promise<boolean> {\n\tif (!options.scheduler || !options.contract || !options.execution || !options.eventId) {\n\t\tconsole.error(chalk.red(\"Error: --scheduler, --contract, --execution, and --event-id are required\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst invalidSchedulerRev = (options as LongHorizonCommandOptions & { _invalidExpectedSchedulerRevision?: string })\n\t\t._invalidExpectedSchedulerRevision;\n\tif (invalidSchedulerRev !== undefined) {\n\t\tconsole.error(\n\t\t\tchalk.red(\n\t\t\t\t`Error: invalid-expected-scheduler-revision: \"${invalidSchedulerRev}\" is not a valid non-negative integer`,\n\t\t\t),\n\t\t);\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\tif (options.expectedSchedulerRevision === undefined) {\n\t\tconsole.error(chalk.red(\"Error: --expected-scheduler-revision is required\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst invalidExecRev = (options as LongHorizonCommandOptions & { _invalidExpectedExecutionRevision?: string })\n\t\t._invalidExpectedExecutionRevision;\n\tif (invalidExecRev !== undefined) {\n\t\tconsole.error(\n\t\t\tchalk.red(\n\t\t\t\t`Error: invalid-expected-execution-revision: \"${invalidExecRev}\" is not a valid non-negative integer`,\n\t\t\t),\n\t\t);\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\tif (options.expectedExecutionRevision === undefined) {\n\t\tconsole.error(chalk.red(\"Error: --expected-execution-revision is required\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst contract = readContractFileAndParse(options.contract);\n\tif (!contract) return true;\n\tconst contractDigest = computeMissionContractDigest(contract);\n\n\tconst execBinding = readExecutionForBinding(options.execution, contractDigest);\n\tif (!execBinding) return true;\n\n\tlet record: ContinuationSchedulerRecord | null = null;\n\tif (existsSync(resolve(options.scheduler))) {\n\t\trecord = readSchedulerFile(options.scheduler);\n\t\tif (!record) return true;\n\t\t// Contract binding\n\t\tif (record.contractDigest !== contractDigest) {\n\t\t\tconsole.error(chalk.red(\"Error: CONTRACT_DIGEST_MISMATCH\"));\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn true;\n\t\t}\n\t\t// Execution binding\n\t\tif (record.executionId !== execBinding.executionId) {\n\t\t\tconsole.error(chalk.red(\"Error: execution ID mismatch\"));\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn true;\n\t\t}\n\t} else {\n\t\t// Missing scheduler — allowed only with expectedSchedulerRevision 0\n\t\tif (options.expectedSchedulerRevision !== 0) {\n\t\t\tconsole.error(\n\t\t\t\tchalk.red(\"Error: ENOENT: scheduler file not found; expectedSchedulerRevision must be 0 for init\"),\n\t\t\t);\n\t\t\tprocess.exitCode = 1;\n\t\t\treturn true;\n\t\t}\n\t\t// Construct in memory: IDLE with execution binding\n\t\trecord = initializeContinuationScheduler(execBinding.executionId, contractDigest);\n\t}\n\n\tconst result = scheduleContinuation(record, {\n\t\teventId: options.eventId,\n\t\texpectedSchedulerRevision: options.expectedSchedulerRevision,\n\t\texpectedExecutionRevision: options.expectedExecutionRevision,\n\t});\n\n\tif (!result.ok) {\n\t\tconsole.error(chalk.red(`Error: ${result.code ? `${result.code}: ` : \"\"}${result.error}`));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\t// Atomic persistence\n\tconst json = JSON.stringify(result.record, null, 2);\n\tif (!writeSchedulerAtomic(options.scheduler, json)) return true;\n\n\tconst format = options.format ?? \"text\";\n\tif (format === \"json\") {\n\t\tconsole.log(JSON.stringify(result.event, null, 2));\n\t} else {\n\t\tconsole.log(chalk.green(`Scheduled: ${result.event!.eventId}`));\n\t\tconsole.log(`  state: ${result.record!.state}`);\n\t\tconsole.log(`  revision: ${result.record!.schedulerRevision}`);\n\t}\n\treturn true;\n}\n\nasync function handleContinuationDispatch(options: LongHorizonCommandOptions): Promise<boolean> {\n\tif (\n\t\t!options.scheduler ||\n\t\t!options.contract ||\n\t\t!options.execution ||\n\t\t!options.eventId ||\n\t\t!options.cycleId ||\n\t\t!options.dispatchedContinuationId\n\t) {\n\t\tconsole.error(\n\t\t\tchalk.red(\n\t\t\t\t\"Error: --scheduler, --contract, --execution, --event-id, --cycle-id, and --dispatched-continuation-id are required\",\n\t\t\t),\n\t\t);\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst invalidSchedulerRev = (options as LongHorizonCommandOptions & { _invalidExpectedSchedulerRevision?: string })\n\t\t._invalidExpectedSchedulerRevision;\n\tif (invalidSchedulerRev !== undefined) {\n\t\tconsole.error(\n\t\t\tchalk.red(\n\t\t\t\t`Error: invalid-expected-scheduler-revision: \"${invalidSchedulerRev}\" is not a valid non-negative integer`,\n\t\t\t),\n\t\t);\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\tif (options.expectedSchedulerRevision === undefined) {\n\t\tconsole.error(chalk.red(\"Error: --expected-scheduler-revision is required\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst record = readSchedulerFileSafe(options.scheduler);\n\tif (!record) return true;\n\n\tconst contract = readContractFileAndParse(options.contract);\n\tif (!contract) return true;\n\tconst contractDigest = computeMissionContractDigest(contract);\n\n\tconst execBinding = readExecutionForBinding(options.execution, contractDigest);\n\tif (!execBinding) return true;\n\n\t// Contract and execution binding\n\tif (record.contractDigest !== contractDigest) {\n\t\tconsole.error(chalk.red(\"Error: CONTRACT_DIGEST_MISMATCH\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\tif (record.executionId !== execBinding.executionId) {\n\t\tconsole.error(chalk.red(\"Error: execution ID mismatch\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst result = dispatchContinuation(\n\t\trecord,\n\t\t{\n\t\t\teventId: options.eventId,\n\t\t\tcycleId: options.cycleId,\n\t\t\texpectedSchedulerRevision: options.expectedSchedulerRevision,\n\t\t\tdispatchedContinuationId: options.dispatchedContinuationId,\n\t\t},\n\t\texecBinding.revision,\n\t);\n\n\tif (!result.ok) {\n\t\tconsole.error(chalk.red(`Error: ${result.code ? `${result.code}: ` : \"\"}${result.error}`));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst json = JSON.stringify(result.record, null, 2);\n\tif (!writeSchedulerAtomic(options.scheduler, json)) return true;\n\n\tconst format = options.format ?? \"text\";\n\tif (format === \"json\") {\n\t\tconsole.log(JSON.stringify(result.event, null, 2));\n\t} else {\n\t\tconsole.log(chalk.green(`Dispatched: ${result.event!.eventId}`));\n\t\tconsole.log(`  state: ${result.record!.state}`);\n\t\tconsole.log(`  revision: ${result.record!.schedulerRevision}`);\n\t}\n\treturn true;\n}\n\nasync function handleContinuationConsume(options: LongHorizonCommandOptions): Promise<boolean> {\n\tif (\n\t\t!options.scheduler ||\n\t\t!options.contract ||\n\t\t!options.execution ||\n\t\t!options.eventId ||\n\t\t!options.cycleId ||\n\t\t!options.dispatchedContinuationId ||\n\t\t!options.resultDigest\n\t) {\n\t\tconsole.error(\n\t\t\tchalk.red(\n\t\t\t\t\"Error: --scheduler, --contract, --execution, --event-id, --cycle-id, --dispatched-continuation-id, and --result-digest are required\",\n\t\t\t),\n\t\t);\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst invalidSchedulerRev = (options as LongHorizonCommandOptions & { _invalidExpectedSchedulerRevision?: string })\n\t\t._invalidExpectedSchedulerRevision;\n\tif (invalidSchedulerRev !== undefined) {\n\t\tconsole.error(\n\t\t\tchalk.red(\n\t\t\t\t`Error: invalid-expected-scheduler-revision: \"${invalidSchedulerRev}\" is not a valid non-negative integer`,\n\t\t\t),\n\t\t);\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\tif (options.expectedSchedulerRevision === undefined) {\n\t\tconsole.error(chalk.red(\"Error: --expected-scheduler-revision is required\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst record = readSchedulerFileSafe(options.scheduler);\n\tif (!record) return true;\n\n\tconst contract = readContractFileAndParse(options.contract);\n\tif (!contract) return true;\n\tconst contractDigest = computeMissionContractDigest(contract);\n\n\tconst execBinding = readExecutionForBinding(options.execution, contractDigest);\n\tif (!execBinding) return true;\n\n\tif (record.contractDigest !== contractDigest) {\n\t\tconsole.error(chalk.red(\"Error: CONTRACT_DIGEST_MISMATCH\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\tif (record.executionId !== execBinding.executionId) {\n\t\tconsole.error(chalk.red(\"Error: execution ID mismatch\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst result = consumeContinuation(\n\t\trecord,\n\t\t{\n\t\t\teventId: options.eventId,\n\t\t\tcycleId: options.cycleId,\n\t\t\texpectedSchedulerRevision: options.expectedSchedulerRevision,\n\t\t\tdispatchedContinuationId: options.dispatchedContinuationId,\n\t\t\tresultDigest: options.resultDigest,\n\t\t},\n\t\texecBinding.revision,\n\t);\n\n\tif (!result.ok) {\n\t\tconsole.error(chalk.red(`Error: ${result.code ? `${result.code}: ` : \"\"}${result.error}`));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst json = JSON.stringify(result.record, null, 2);\n\tif (!writeSchedulerAtomic(options.scheduler, json)) return true;\n\n\tconst format = options.format ?? \"text\";\n\tif (format === \"json\") {\n\t\tconsole.log(JSON.stringify(result.event, null, 2));\n\t} else {\n\t\tconsole.log(chalk.green(`Consumed: ${result.event!.eventId}`));\n\t\tconsole.log(`  state: ${result.record!.state}`);\n\t\tconsole.log(`  revision: ${result.record!.schedulerRevision}`);\n\t}\n\treturn true;\n}\n\nasync function handleContinuationCancel(options: LongHorizonCommandOptions): Promise<boolean> {\n\tif (!options.scheduler || !options.contract || !options.execution || !options.eventId || !options.cycleId) {\n\t\tconsole.error(chalk.red(\"Error: --scheduler, --contract, --execution, --event-id, and --cycle-id are required\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst invalidSchedulerRev = (options as LongHorizonCommandOptions & { _invalidExpectedSchedulerRevision?: string })\n\t\t._invalidExpectedSchedulerRevision;\n\tif (invalidSchedulerRev !== undefined) {\n\t\tconsole.error(\n\t\t\tchalk.red(\n\t\t\t\t`Error: invalid-expected-scheduler-revision: \"${invalidSchedulerRev}\" is not a valid non-negative integer`,\n\t\t\t),\n\t\t);\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\tif (options.expectedSchedulerRevision === undefined) {\n\t\tconsole.error(chalk.red(\"Error: --expected-scheduler-revision is required\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst record = readSchedulerFileSafe(options.scheduler);\n\tif (!record) return true;\n\n\tconst contract = readContractFileAndParse(options.contract);\n\tif (!contract) return true;\n\tconst contractDigest = computeMissionContractDigest(contract);\n\n\tconst execBinding = readExecutionForBinding(options.execution, contractDigest);\n\tif (!execBinding) return true;\n\n\tif (record.contractDigest !== contractDigest) {\n\t\tconsole.error(chalk.red(\"Error: CONTRACT_DIGEST_MISMATCH\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\tif (record.executionId !== execBinding.executionId) {\n\t\tconsole.error(chalk.red(\"Error: execution ID mismatch\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst result = cancelContinuation(\n\t\trecord,\n\t\t{\n\t\t\teventId: options.eventId,\n\t\t\tcycleId: options.cycleId,\n\t\t\texpectedSchedulerRevision: options.expectedSchedulerRevision,\n\t\t},\n\t\texecBinding.revision,\n\t);\n\n\tif (!result.ok) {\n\t\tconsole.error(chalk.red(`Error: ${result.code ? `${result.code}: ` : \"\"}${result.error}`));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst json = JSON.stringify(result.record, null, 2);\n\tif (!writeSchedulerAtomic(options.scheduler, json)) return true;\n\n\tconst format = options.format ?? \"text\";\n\tif (format === \"json\") {\n\t\tconsole.log(JSON.stringify(result.event, null, 2));\n\t} else {\n\t\tconsole.log(chalk.green(`Cancelled: ${result.event!.eventId}`));\n\t\tconsole.log(`  state: ${result.record!.state}`);\n\t\tconsole.log(`  revision: ${result.record!.schedulerRevision}`);\n\t}\n\treturn true;\n}\n\nasync function handleContinuationAbandon(options: LongHorizonCommandOptions): Promise<boolean> {\n\tif (!options.scheduler || !options.contract || !options.execution || !options.eventId || !options.cycleId) {\n\t\tconsole.error(chalk.red(\"Error: --scheduler, --contract, --execution, --event-id, and --cycle-id are required\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst invalidSchedulerRev = (options as LongHorizonCommandOptions & { _invalidExpectedSchedulerRevision?: string })\n\t\t._invalidExpectedSchedulerRevision;\n\tif (invalidSchedulerRev !== undefined) {\n\t\tconsole.error(\n\t\t\tchalk.red(\n\t\t\t\t`Error: invalid-expected-scheduler-revision: \"${invalidSchedulerRev}\" is not a valid non-negative integer`,\n\t\t\t),\n\t\t);\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\tif (options.expectedSchedulerRevision === undefined) {\n\t\tconsole.error(chalk.red(\"Error: --expected-scheduler-revision is required\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst record = readSchedulerFileSafe(options.scheduler);\n\tif (!record) return true;\n\n\tconst contract = readContractFileAndParse(options.contract);\n\tif (!contract) return true;\n\tconst contractDigest = computeMissionContractDigest(contract);\n\n\tconst execBinding = readExecutionForBinding(options.execution, contractDigest);\n\tif (!execBinding) return true;\n\n\tif (record.contractDigest !== contractDigest) {\n\t\tconsole.error(chalk.red(\"Error: CONTRACT_DIGEST_MISMATCH\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\tif (record.executionId !== execBinding.executionId) {\n\t\tconsole.error(chalk.red(\"Error: execution ID mismatch\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst result = abandonContinuation(\n\t\trecord,\n\t\t{\n\t\t\teventId: options.eventId,\n\t\t\tcycleId: options.cycleId,\n\t\t\texpectedSchedulerRevision: options.expectedSchedulerRevision,\n\t\t},\n\t\texecBinding.revision,\n\t);\n\n\tif (!result.ok) {\n\t\tconsole.error(chalk.red(`Error: ${result.code ? `${result.code}: ` : \"\"}${result.error}`));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst json = JSON.stringify(result.record, null, 2);\n\tif (!writeSchedulerAtomic(options.scheduler, json)) return true;\n\n\tconst format = options.format ?? \"text\";\n\tif (format === \"json\") {\n\t\tconsole.log(JSON.stringify(result.event, null, 2));\n\t} else {\n\t\tconsole.log(chalk.green(`Abandoned: ${result.event!.eventId}`));\n\t\tconsole.log(`  state: ${result.record!.state}`);\n\t\tconsole.log(`  revision: ${result.record!.schedulerRevision}`);\n\t}\n\treturn true;\n}\n\n/** Read scheduler file, printing ENOENT on missing. */\nfunction readSchedulerFileSafe(path: string): ContinuationSchedulerRecord | null {\n\tif (!existsSync(resolve(path))) {\n\t\tconsole.error(chalk.red(\"Error: ENOENT: scheduler file not found\"));\n\t\tprocess.exitCode = 1;\n\t\treturn null;\n\t}\n\treturn readSchedulerFile(path);\n}\n\n// =============================================================================\n// Execution State Machine Commands\n// =============================================================================\n\nconst VALID_EXECUTION_KINDS: ReadonlySet<string> = new Set([\n\t\"START_EXECUTION\",\n\t\"REQUEST_VERIFICATION\",\n\t\"RETURN_TO_EXECUTION\",\n\t\"REQUEST_COMPLETION_REVIEW\",\n\t\"RETURN_TO_VERIFICATION\",\n\t\"APPROVE_COMPLETION\",\n\t\"BLOCK\",\n\t\"RESUME\",\n\t\"FAIL\",\n\t\"CANCEL\",\n]);\n\nasync function handleExecutionInit(options: LongHorizonCommandOptions): Promise<boolean> {\n\tif (!options.contract || !options.executionId) {\n\t\tconsole.error(chalk.red(\"Error: --contract and --execution-id are required\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst contract = readContractFileAndParse(options.contract);\n\tif (!contract) return true;\n\n\tlet record: MissionExecutionRecordV1;\n\ttry {\n\t\trecord = initializeMissionExecution(contract, options.executionId);\n\t} catch (err: unknown) {\n\t\tconst message = err instanceof Error ? err.message : \"Unknown error\";\n\t\tconsole.error(chalk.red(`Error: ${message}`));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst format = options.format ?? \"text\";\n\twriteExecutionOutput(record, options, format);\n\treturn true;\n}\n\nasync function handleExecutionInspect(options: LongHorizonCommandOptions): Promise<boolean> {\n\tif (!options.contract || !options.execution) {\n\t\tconsole.error(chalk.red(\"Error: --contract and --execution are required\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst contract = readContractFileAndParse(options.contract);\n\tif (!contract) return true;\n\n\tconst record = readExecutionFile(options.execution);\n\tif (!record) return true;\n\n\tconst inspection = inspectMissionExecution(contract, record);\n\tconst format = options.format ?? \"text\";\n\n\tif (format === \"json\") {\n\t\tconst output = JSON.stringify(inspection, null, 2);\n\t\twriteOutput(output, options);\n\t} else {\n\t\tif (inspection.valid) {\n\t\t\tconsole.log(chalk.bold(\"Execution Record Inspection (structural only)\"));\n\t\t\tconsole.log(`${\"Execution ID\".padEnd(28)} ${inspection.executionId}`);\n\t\t\tconsole.log(`${\"Contract Digest\".padEnd(28)} ${inspection.contractDigest}`);\n\t\t\tconsole.log(`${\"State\".padEnd(28)} ${inspection.state}`);\n\t\t\tconsole.log(`${\"Revision\".padEnd(28)} ${inspection.revision}`);\n\t\t\tconsole.log(`${\"Transition Count\".padEnd(28)} ${inspection.transitionCount}`);\n\t\t\tif (inspection.blockedFromState) {\n\t\t\t\tconsole.log(`${\"Blocked From\".padEnd(28)} ${inspection.blockedFromState}`);\n\t\t\t}\n\t\t\tconsole.log(\n\t\t\t\t`${chalk.yellow(\"Completion Approved\".padEnd(28))} ${chalk.yellow(\"unavailable (trusted context required)\")}`,\n\t\t\t);\n\t\t} else {\n\t\t\tconsole.log(chalk.red(`Invalid: ${inspection.error}`));\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\t}\n\n\tif (!inspection.valid) process.exitCode = 1;\n\treturn true;\n}\n\nasync function handleExecutionValidate(options: LongHorizonCommandOptions): Promise<boolean> {\n\tif (!options.contract || !options.execution) {\n\t\tconsole.error(chalk.red(\"Error: --contract and --execution are required\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst contract = readContractFileAndParse(options.contract);\n\tif (!contract) return true;\n\n\tconst record = readExecutionFile(options.execution);\n\tif (!record) return true;\n\n\tconst result = validateMissionExecutionRecord(contract, record);\n\tconst format = options.format ?? \"text\";\n\n\tif (format === \"json\") {\n\t\tconst output = JSON.stringify(result, null, 2);\n\t\twriteOutput(output, options);\n\t} else {\n\t\tif (result.valid) {\n\t\t\tconsole.log(chalk.green(\"Execution record is valid\"));\n\t\t} else {\n\t\t\tconsole.log(chalk.red(`Invalid: ${result.error}`));\n\t\t}\n\t}\n\n\tif (!result.valid) process.exitCode = 1;\n\treturn true;\n}\n\nasync function handleExecutionTransition(options: LongHorizonCommandOptions): Promise<boolean> {\n\tif (!options.contract || !options.execution || !options.transitionId || !options.kind) {\n\t\tconsole.error(chalk.red(\"Error: --contract, --execution, --transition-id, and --kind are required\"));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\tif (options.expectedRevision === undefined) {\n\t\tconst invalidRev = (options as LongHorizonCommandOptions & { _invalidExpectedRevision?: string })\n\t\t\t._invalidExpectedRevision;\n\t\tif (invalidRev !== undefined) {\n\t\t\tconsole.error(\n\t\t\t\tchalk.red(`Error: invalid-expected-revision: \"${invalidRev}\" is not a valid non-negative integer`),\n\t\t\t);\n\t\t} else {\n\t\t\tconsole.error(chalk.red(\"Error: --expected-revision is required\"));\n\t\t}\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tif (!VALID_EXECUTION_KINDS.has(options.kind)) {\n\t\tconsole.error(chalk.red(`Error: invalid transition kind: \"${options.kind}\"`));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst contract = readContractFileAndParse(options.contract);\n\tif (!contract) return true;\n\n\tconst record = readExecutionFile(options.execution);\n\tif (!record) return true;\n\n\t// APPROVE_COMPLETION requires trusted context — the generic CLI cannot mint one.\n\t// Reject atomically before any mutation.\n\tif (options.kind === \"APPROVE_COMPLETION\") {\n\t\tconsole.error(\n\t\t\tchalk.red(\n\t\t\t\t\"Error: TRUSTED_VALIDATION_CONTEXT_REQUIRED: APPROVE_COMPLETION requires a trusted validation context (not available through generic CLI)\",\n\t\t\t),\n\t\t);\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst result = applyMissionExecutionTransition(contract, record, {\n\t\ttransitionId: options.transitionId,\n\t\texpectedRevision: options.expectedRevision,\n\t\tkind: options.kind as MissionExecutionTransitionKind,\n\t});\n\n\tif (!result.ok) {\n\t\tconsole.error(chalk.red(`Error: ${result.code ? `${result.code}: ` : \"\"}${result.error}`));\n\t\tprocess.exitCode = 1;\n\t\treturn true;\n\t}\n\n\tconst format = options.format ?? \"text\";\n\twriteExecutionOutput(result.record, options, format);\n\treturn true;\n}\n\n// =============================================================================\n// Execution file I/O\n// =============================================================================\n\nfunction readExecutionFile(path: string): MissionExecutionRecordV1 | null {\n\tconst raw = readFileContent(path);\n\tif (!raw) return null;\n\ttry {\n\t\tconst parsed = JSON.parse(raw) as MissionExecutionRecordV1;\n\t\treturn parsed;\n\t} catch {\n\t\tconsole.error(chalk.red(\"Error parsing execution record JSON\"));\n\t\tprocess.exitCode = 1;\n\t\treturn null;\n\t}\n}\n\nfunction writeExecutionOutput(\n\trecord: MissionExecutionRecordV1,\n\toptions: LongHorizonCommandOptions,\n\tformat: \"text\" | \"json\",\n): void {\n\tif (format === \"json\") {\n\t\tconst output = JSON.stringify(record, null, 2);\n\t\twriteOutput(output, options);\n\t} else {\n\t\tconst lines = [\n\t\t\t`Execution: ${record.executionId}`,\n\t\t\t`Contract Digest: ${record.contractDigest}`,\n\t\t\t`State: ${record.state}`,\n\t\t\t`Revision: ${record.revision}`,\n\t\t\t`Transitions: ${record.transitions.length}`,\n\t\t];\n\t\tif (record.blockedFromState) {\n\t\t\tlines.push(`Blocked From: ${record.blockedFromState}`);\n\t\t}\n\t\tconst text = lines.join(\"\\n\");\n\t\twriteOutput(text, options);\n\t}\n}\n"]}