{"version":3,"file":"operability-runtime.d.ts","sourceRoot":"","sources":["../../src/core/operability-runtime.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,eAAe,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAE3F,OAAO,KAAK,EAAE,SAAS,EAAiB,MAAM,sBAAsB,CAAC;AAErE,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,YAAY,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,eAAe,EAAE,YAAY,CAAC,iBAAiB,CAAC,CAAC;IACjD,iBAAiB,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IAClC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,CAAC,SAAS,CAAC,KAAK,OAAO,GAAG,MAAM,CAAC;CAC5E;AAED,MAAM,WAAW,iBAAiB;IACjC,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IACrE,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,CAAC,CAAC;IACb,MAAM,EAAE,SAAS,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACd;AAQD,wBAAgB,cAAc,CAAC,MAAM,EAAE,eAAe,GAAG,gBAAgB,CAgBxE;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,EAAE,OAAO,GAAE,kBAAuB,GAAG,iBAAiB,CAqDzG;AAED,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACd;AACD,MAAM,WAAW,kBAAkB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAgB,YAAY,CAC3B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5D,kBAAkB,CAyBpB;AAED,MAAM,WAAW,YAAY;IAC5B,OAAO,EAAE,CAAC,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAClC,YAAY,EAAE,MAAM,CAAC;CACrB;AACD,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,SAAuB,GAAG,YAAY,CA2BvG;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CA4B3G","sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport {\n\texistsSync,\n\tlstatSync,\n\tmkdirSync,\n\treaddirSync,\n\treadFileSync,\n\trenameSync,\n\tstatSync,\n\tunlinkSync,\n\twriteFileSync,\n} from \"node:fs\";\nimport { join, relative, resolve } from \"node:path\";\nimport type { EventReadResult, JensenEventEnvelope, RenderReplay } from \"./operability.js\";\nimport { renderReplay, sha256 } from \"./operability.js\";\nimport type { FileEntry, SessionHeader } from \"./session-manager.js\";\n\nexport interface SimulationReplay {\n\trunId: string;\n\tsimulationId: string;\n\tmode: \"simulation\";\n\trecordedEvidence: number;\n\tlines: string[];\n\tmissingArtifacts: string[];\n\texternalEffects: RenderReplay[\"externalEffects\"];\n\tcanonicalOrdering: \"valid\" | \"invalid\";\n\twarnings: string[];\n}\n\nexport interface ReexecutionOptions {\n\tauthorizeExecute?: boolean;\n\tplan?: boolean;\n\tcwd?: string;\n\toutputDir?: string;\n\tcurrentPolicy?: (event: JensenEventEnvelope<FileEntry>) => \"allow\" | \"deny\";\n}\n\nexport interface ReexecutionResult {\n\thistoricalRunId: string;\n\tnewRunId: string;\n\tmode: \"plan\" | \"execute\";\n\tcausationId: string;\n\tworkspace: { historical: string; current: string; drifted: boolean };\n\tproposedEvents: number;\n\tmutations: 0;\n\tpolicy: \"current\";\n\twarnings: string[];\n\tpath?: string;\n}\n\nfunction canonicalOrdering(events: JensenEventEnvelope<FileEntry>[]): boolean {\n\treturn events.every(\n\t\t(event, index) => event.sequence === index && (index === 0 || event.recordedAt >= events[index - 1]!.recordedAt),\n\t);\n}\n\nexport function simulateReplay(result: EventReadResult): SimulationReplay {\n\tconst replay = renderReplay(result);\n\tconst warnings = [...result.issues.map((issue) => `${issue.reasonCode}:${issue.detail}`)];\n\tif (replay.missingArtifacts.length > 0) warnings.push(\"recorded_artifact_missing\");\n\tif (!canonicalOrdering(result.events)) warnings.push(\"canonical_event_order_invalid\");\n\treturn {\n\t\trunId: result.header?.id ?? result.events[0]?.runId ?? \"unknown\",\n\t\tsimulationId: `simulation-${randomUUID()}`,\n\t\tmode: \"simulation\",\n\t\trecordedEvidence: result.events.length,\n\t\tlines: replay.lines,\n\t\tmissingArtifacts: replay.missingArtifacts,\n\t\texternalEffects: { modelCalls: 0, toolCalls: 0, networkCalls: 0, mutations: 0 },\n\t\tcanonicalOrdering: canonicalOrdering(result.events) ? \"valid\" : \"invalid\",\n\t\twarnings,\n\t};\n}\n\nexport function reexecuteRun(result: EventReadResult, options: ReexecutionOptions = {}): ReexecutionResult {\n\tconst historicalRunId = result.header?.id ?? result.events[0]?.runId ?? \"unknown\";\n\tconst historicalCwd = result.header?.cwd ?? \"\";\n\tconst currentCwd = resolve(options.cwd ?? process.cwd());\n\tconst drifted = Boolean(historicalCwd && resolve(historicalCwd) !== currentCwd);\n\tconst warnings = [...result.issues.map((issue) => `${issue.reasonCode}:${issue.detail}`)];\n\tif (drifted) warnings.push(\"workspace_drift\");\n\tif (result.events.length === 0) warnings.push(\"historical_evidence_missing\");\n\tif (options.authorizeExecute && !options.plan)\n\t\tthrow new Error(\n\t\t\t\"re-execute execute mode requires an explicit current authorization and is not enabled by this command\",\n\t\t);\n\tconst newRunId = randomUUID();\n\tconst causationId = `${historicalRunId}:${newRunId}`;\n\tconst proposedEvents = result.events.filter((event) => event.eventType === \"message\").length;\n\tfor (const event of result.events) {\n\t\tif (options.currentPolicy?.(event) === \"deny\") warnings.push(`current_policy_denied:${event.eventId}`);\n\t}\n\tconst outputDir = options.outputDir ? resolve(options.outputDir) : undefined;\n\tlet path: string | undefined;\n\tif (outputDir) {\n\t\tmkdirSync(outputDir, { recursive: true });\n\t\tpath = join(outputDir, `${newRunId}.jsonl`);\n\t\tconst header: SessionHeader = {\n\t\t\ttype: \"session\",\n\t\t\tversion: 3,\n\t\t\tid: newRunId,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tcwd: currentCwd,\n\t\t\tparentSession: historicalRunId,\n\t\t};\n\t\tconst marker: FileEntry = {\n\t\t\ttype: \"custom\",\n\t\t\tid: randomUUID().slice(0, 8),\n\t\t\tparentId: null,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tcustomType: \"jensen.reexecution.plan\",\n\t\t\tdata: { causationId, historicalRunId, proposedEvents, mode: \"plan\", mutations: 0 },\n\t\t};\n\t\twriteFileSync(path, `${JSON.stringify(header)}\\n${JSON.stringify(marker)}\\n`, { encoding: \"utf8\", flag: \"wx\" });\n\t}\n\treturn {\n\t\thistoricalRunId,\n\t\tnewRunId,\n\t\tmode: \"plan\",\n\t\tcausationId,\n\t\tworkspace: { historical: historicalCwd, current: currentCwd, drifted },\n\t\tproposedEvents,\n\t\tmutations: 0,\n\t\tpolicy: \"current\",\n\t\twarnings,\n\t\tpath,\n\t};\n}\n\nexport interface StoragePruneEntry {\n\tpath: string;\n\treason: string;\n\tbytes: number;\n}\nexport interface StoragePruneResult {\n\tpreview: boolean;\n\tentries: StoragePruneEntry[];\n\ttotalBytes: number;\n\tpreserved: string[];\n}\n\nexport function storagePrune(\n\troot: string,\n\toptions: { preview: boolean; retainMs?: number; now?: number },\n): StoragePruneResult {\n\tconst base = resolve(root);\n\tconst now = options.now ?? Date.now();\n\tconst retainMs = options.retainMs ?? 30 * 24 * 60 * 60 * 1000;\n\tconst entries: StoragePruneEntry[] = [];\n\tconst preserved: string[] = [];\n\tif (!existsSync(base) || !lstatSync(base).isDirectory())\n\t\treturn { preview: options.preview, entries, totalBytes: 0, preserved };\n\tfor (const name of readdirSync(base)) {\n\t\tconst path = join(base, name);\n\t\tconst stat = lstatSync(path);\n\t\tif (!stat.isFile() || !/\\.(jsonl|json|log|zip|idx)$/.test(name)) continue;\n\t\tif (stat.mtimeMs >= now - retainMs || /(?:active|checkpoint|acceptance|audit|release)/i.test(name)) {\n\t\t\tpreserved.push(name);\n\t\t\tcontinue;\n\t\t}\n\t\tentries.push({ path: relative(base, path), reason: \"retention_expired\", bytes: stat.size });\n\t}\n\tif (!options.preview) for (const entry of entries) unlinkSync(join(base, entry.path));\n\treturn {\n\t\tpreview: options.preview,\n\t\tentries,\n\t\ttotalBytes: entries.reduce((sum, entry) => sum + entry.bytes, 0),\n\t\tpreserved: preserved.sort(),\n\t};\n}\n\nexport interface StorageIndex {\n\tversion: 1;\n\tgeneratedAt: string;\n\tentries: Record<string, string[]>;\n\tsourceSha256: string;\n}\nexport function rebuildStorageIndex(sessionFile: string, indexFile = `${sessionFile}.idx`): StorageIndex {\n\tconst source = readFileSync(sessionFile, \"utf8\");\n\tconst entries: Record<string, string[]> = {};\n\tfor (const [line, text] of source.split(/\\r?\\n/).entries()) {\n\t\tif (!text.trim()) continue;\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(text) as Record<string, unknown>;\n\t\t\tfor (const key of [\"type\", \"eventType\", \"correlationId\"]) {\n\t\t\t\tif (typeof parsed[key] !== \"string\") continue;\n\t\t\t\tconst values = entries[key] ?? [];\n\t\t\t\tvalues.push(`${line + 1}:${parsed[key]}`);\n\t\t\t\tentries[key] = values;\n\t\t\t}\n\t\t} catch {\n\t\t\t/* canonical reader reports malformed source */\n\t\t}\n\t}\n\tconst index: StorageIndex = {\n\t\tversion: 1,\n\t\tgeneratedAt: new Date().toISOString(),\n\t\tentries,\n\t\tsourceSha256: createHash(\"sha256\").update(source).digest(\"hex\"),\n\t};\n\tconst temporary = `${indexFile}.${randomUUID()}.tmp`;\n\twriteFileSync(temporary, JSON.stringify(index));\n\trenameSync(temporary, indexFile);\n\treturn index;\n}\n\nexport function inspectSupportBundle(path: string): { valid: boolean; manifest?: unknown; errors: string[] } {\n\tif (!existsSync(path) || !statSync(path).isFile()) return { valid: false, errors: [\"bundle_missing\"] };\n\tconst content = readFileSync(path, \"utf8\");\n\tconst marker = \"\\n--- doctor.json ---\\n\";\n\tconst manifestText = content.split(marker)[0];\n\ttry {\n\t\tconst manifest = JSON.parse(manifestText) as {\n\t\t\tfiles?: Array<{ path: string; sha256: string }>;\n\t\t\tmaxBytes?: number;\n\t\t};\n\t\tconst errors: string[] = [];\n\t\tif (!Array.isArray(manifest.files)) errors.push(\"manifest_files_missing\");\n\t\tif (manifest.maxBytes !== undefined && Buffer.byteLength(content) > manifest.maxBytes)\n\t\t\terrors.push(\"bundle_size_limit\");\n\t\tfor (const file of manifest.files ?? []) {\n\t\t\tconst section = `\\n--- ${file.path} ---\\n`;\n\t\t\tconst start = content.indexOf(section);\n\t\t\tif (start < 0) errors.push(`file_missing:${file.path}`);\n\t\t\telse {\n\t\t\t\tconst end = content.indexOf(\"\\n--- \", start + section.length);\n\t\t\t\tconst body = content.slice(start + section.length, end < 0 ? undefined : end);\n\t\t\t\tif (sha256(body) !== file.sha256) errors.push(`hash_mismatch:${file.path}`);\n\t\t\t}\n\t\t}\n\t\treturn { valid: errors.length === 0, manifest, errors };\n\t} catch {\n\t\treturn { valid: false, errors: [\"invalid_manifest\"] };\n\t}\n}\n"]}