import { closeSync, constants as fsConstants, lstatSync, openSync, readFileSync, writeFileSync, } from "node:fs"; import { execFileSync } from "node:child_process"; import { resolve } from "node:path"; import { projectScopeOverlap } from "../unattended/batch_schedule"; import process from "node:process"; import { fileURLToPath } from "node:url"; import { KernelStoreSecurityError, appendJournalEntry, readSecureProjectFile, readTaskRecordRaw, readWorkspaceStateRaw, type JournalEntry, type JournalReasonCode, type TaskPhase, } from "../kernel"; import { INTENT_MAX_BYTES, canonicalIntentHash, parseProjectTaskIntent, parseTaskIntentV1, } from "../kernel/intent"; import { floorMatchingScopeEntries, floorScopePrefixes, readRiskFloor, } from "../kernel/risk_floor"; import { inspectSpecBinding } from "../kernel/spec_binding"; import { projectTask, resolveProjectedRisk } from "../kernel/completion"; import { deriveAssuranceAuthorization } from "../kernel/assurance_projection"; import { taskDeliveryIdentity } from "../workspace_scope"; import type { TaskIntentV1, TaskRisk } from "../kernel/types"; import { canonicalDescriptorBytes, parseVerificationDescriptor, } from "../verification_descriptor"; import { inspectRoutingPolicy } from "../managed_task_routing_policy" import { projectLegacyAudit } from "../kernel/legacy_audit"; import { inspectStorageLayout } from "../kernel/storage_paths"; import { commitPendingMigrationDiff, migrateAndCommitLegacyLayout } from "../kernel/storage_layout_migration"; import { readBackendClaim } from "../kernel/backend_claim"; import { inspectEnrollmentGitBase, type EnrollmentGitBase } from "../assurance/enrollment_git_base"; import { probeKernelStore } from "../kernel"; import { readDerivedFiles } from "../derived_files"; // Candidate planning guard only: enrolled reads and revisions retain their scope freedom. function scopeEstimateFailure(root: string, intent: TaskIntentV1): string | null { if (intent.scope_size_reason !== undefined) return null; const outputs = new Set(readDerivedFiles(root).flatMap((entry) => entry.outputs)); const counted = intent.scope_hint.filter((path) => !path.startsWith(".changeset/") && path !== `docs/plans/${intent.task_id}.intent.json` && !/^docs\/specs\/[^/]+\.spec\.md$/.test(path) && !outputs.has(path), ).length; return counted > 15 ? `${counted} counted scope_hint paths exceed the 15-path cap; split the Slice or provide scope_size_reason` : null; } export interface KernelCommandResult { stdout: string; stderr: string; returncode: number; } interface KernelExecution { result: KernelCommandResult; journal: Omit; } function jsonResult(payload: unknown, returncode = 0): KernelCommandResult { return { stdout: `${JSON.stringify(payload, null, 2)}\n`, stderr: "", returncode, }; } function errorResult(code: string, message: string, returncode: number): KernelCommandResult { return jsonResult({ error: { code, message } }, returncode); } function journalFor( command: string, phase: TaskPhase | null, result: JournalEntry["result"], reasonCode: JournalReasonCode, taskId: string | null, recoveryHint: string | null, userIntervention = false, ): Omit { return { task_id: taskId, command, entry_phase: phase, result, reason_code: reasonCode, recovery_hint: recoveryHint, planner_reentry: false, user_intervention: userIntervention, }; } function sourceFailure(command: string, error: unknown): KernelExecution { const message = error instanceof Error ? error.message : String(error); const code: JournalReasonCode = message.startsWith("source_missing:") ? "source_missing" : error instanceof KernelStoreSecurityError ? "source_invalid" : "source_read_failed"; return { result: errorResult(code, message, 1), journal: journalFor( command, null, "rejected", code, null, "Resolve the reported storage or legacy-reader condition before retrying.", ), }; } /** * `status --json` is strictly read-only and reports layout facts plus Kernel * ownership facts. It never projects the archived v3 Ledger as current * authority; `audit --legacy` is the only legacy reader. */ function runStatus(root: string): KernelExecution { try { const layout = inspectStorageLayout(root); const claim = readBackendClaim(root); const workspace = readWorkspaceOwner(root); return { result: jsonResult({ contract: "assurance_kernel/status/v1", layout, kernel: { claim: claim ? { task_id: claim.task_id, lifecycle_status: claim.lifecycle_status, } : null, workspace: { current_working: workspace }, }, }), journal: journalFor( "status", null, layout.layout === "ready" || layout.layout === "migration_uncommitted" ? "ok" : "escalated", layout.layout === "ready" ? "command_ok" : "source_invalid", null, layout.reason, ), }; } catch (error) { return sourceFailure("status", error); } } const UNOBSERVABLE = { capability: "unobservable", rehearsal: "unobservable", cas_holder: "unobservable", } as const; const RISK_ORDER: Record = { routine: 0, material: 1, critical: 2, }; function readWorkspaceOwner(root: string): string | null { try { return readWorkspaceStateRaw(root).state.current_working; } catch { return null; } } /** * `inspect --json` is a read-only Inspect Projection. It never journals, * never takes a Kernel store lock, and never becomes authority. */ function runInspect(root: string): KernelExecution { try { const layout = inspectStorageLayout(root); const claim = readBackendClaim(root); const workspace = readWorkspaceOwner(root); const kernel = { claim: claim ? { task_id: claim.task_id, lifecycle_status: claim.lifecycle_status, } : null, workspace: { current_working: workspace }, }; const floor = readRiskFloor(root); const idleRisk = { declared: null as TaskRisk | null, resolved: null as TaskRisk | null, floor_prefixes: floorScopePrefixes(floor), floor_invalid: floor.invalid, floor_applied: false, matching_scope_entries: [] as string[], }; const ok = layout.layout === "ready" || layout.layout === "migration_uncommitted"; if (!claim || !ok || layout.layout !== "ready") { return { result: jsonResult({ contract: "assurance_kernel/inspect/v1", layout, kernel, assurance: null, risk: idleRisk, unobservable: UNOBSERVABLE, }), journal: journalFor( "inspect", null, ok ? "ok" : "escalated", layout.layout === "ready" ? "command_ok" : "source_invalid", null, layout.reason, ), }; } let recordRead: ReturnType; try { recordRead = readTaskRecordRaw(root, claim.task_id); } catch (error) { return sourceFailure("inspect", error); } if (!recordRead.record) { return { result: errorResult( "source_read_failed", `task ${claim.task_id} has no TaskRecord`, 1, ), journal: journalFor( "inspect", null, "rejected", "source_read_failed", claim.task_id, "Resolve the claimed TaskRecord before retrying inspect.", ), }; } const record = recordRead.record; let declared: TaskRisk; let intent: TaskIntentV1; try { const raw = JSON.parse( readSecureProjectFile(root, record.intent_ref.path), ) as { risk?: unknown }; if (raw.risk !== "routine" && raw.risk !== "material" && raw.risk !== "critical") throw new Error(`intent.risk is unreadable for ${claim.task_id}`); declared = raw.risk; intent = parseProjectTaskIntent(root, raw, record.intent_snapshot); if (canonicalIntentHash(intent) !== record.intent_ref.content_hash) throw new Error("TaskIntent sidecar does not match TaskRecord content hash"); } catch (error) { return sourceFailure("inspect", error); } const workspaceState = readWorkspaceStateRaw(root); let identity; try { identity = taskDeliveryIdentity(root, record); } catch (error) { return sourceFailure("inspect", error); } const diffHash = identity.diff_hash; const changedPaths = identity.changed_paths; const decision = projectTask(intent, record, diffHash, record.intent_ref.content_hash, changedPaths, floor); const openUserDecisionCount = record.findings.filter( (finding) => finding.kind === "unresolved_user_decision" && finding.status === "open", ).length; const resolved = resolveProjectedRisk(intent, changedPaths, floor); return { result: jsonResult({ contract: "assurance_kernel/inspect/v1", layout, kernel, assurance: { contract: "assurance_kernel/assurance_projection/v1", task_id: claim.task_id, error: null, claim: kernel.claim, projection: { record_revision: recordRead.revision, workspace_revision: workspaceState.revision, intent_revision: intent.revision, intent_content_hash: record.intent_ref.content_hash, diff_hash: diffHash, lifecycle: record.lifecycle, artifact_state: record.artifact_state, risk: resolved, next_obligation: decision.next_obligation, fresh_acceptance_ids: decision.fresh_acceptance_ids, missing_acceptance_ids: decision.missing_acceptance_ids, stale_attestation_ids: decision.stale_attestation_ids, fresh_approval_kinds: [], missing_approval_kinds: decision.missing_approval_kinds, blocking_finding_ids: decision.blocking_finding_ids, unresolved_user_decision_ids: decision.unresolved_user_decision_ids, replan_required_ids: decision.replan_required_ids, independence_violations: decision.independence_violations, open_user_decision_count: openUserDecisionCount, completion_ready: decision.complete, authorization: deriveAssuranceAuthorization({ next_obligation: decision.next_obligation, open_user_decision_count: openUserDecisionCount, }), }, }, risk: { declared, resolved, floor_prefixes: floorScopePrefixes(floor), floor_invalid: floor.invalid, floor_applied: RISK_ORDER[resolved] > RISK_ORDER[declared], matching_scope_entries: floorMatchingScopeEntries(intent.scope_hint, floor), }, unobservable: UNOBSERVABLE, }), journal: journalFor("inspect", null, "ok", "command_ok", claim.task_id, null), }; } catch (error) { return sourceFailure("inspect", error); } } const INTENT_SIDECAR_PREFIX = "docs/plans/"; const TASK_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/; function intentSidecarPath(taskId: string): string { if (!TASK_ID_PATTERN.test(taskId)) throw new Error("task id must match [A-Za-z0-9][A-Za-z0-9._-]{0,127}"); return `${INTENT_SIDECAR_PREFIX}${taskId}.intent.json`; } /** * Bounded synchronous stdin read, used ONLY by the exact * `intent author --stdin` branch. Help, validation, and all pre-existing * imm-kernel commands never read file descriptor 0. */ function readBoundedStdin(maxBytes: number): string { const bytes = readFileSync(0); if (bytes.byteLength > maxBytes) throw new Error(`candidate exceeds the ${maxBytes} byte TaskIntent bound`); return bytes.toString("utf8"); } function intentActiveOwner(root: string): { kernel: boolean; v3: boolean } { let kernelOwner = false; let v3Owner = false; try { const claim = readBackendClaim(root); kernelOwner = claim !== null; } catch { kernelOwner = false; } try { const state = JSON.parse( readSecureProjectFile(root, ".imm/memory/current_iteration.json"), ) as Record; if (typeof state.runtime_status === "string" && state.runtime_status !== "idle") v3Owner = true; } catch { // No readable v3 Ledger means no v3 owner. } return { kernel: kernelOwner, v3: v3Owner }; } /** * Canonical `imm-kernel intent author --stdin --json`. * Host-neutral TaskIntent draft creation: strict parsing, verification * descriptor canonicalization, and exclusive no-overwrite creation of exactly * one untracked draft. Never stages Git, enrolls, writes workflow state or * journal, creates parents, or overwrites. */ function runIntentAuthor(args: string[], root: string): KernelExecution { const nonFlags = args.filter((arg) => !arg.startsWith("-")); if (nonFlags.length !== 1) return { result: errorResult( "invalid_command", "imm-kernel intent author requires exactly one destination path", 2, ), journal: journalFor( "intent", null, "rejected", "invalid_command", null, "Run imm-kernel intent author --stdin --json.", ), }; if (!args.includes("--stdin")) return { result: errorResult( "stdin_required", "imm-kernel intent author requires --stdin for the bounded candidate input", 2, ), journal: journalFor( "intent", null, "rejected", "invalid_command", null, "Run imm-kernel intent author --stdin --json.", ), }; const unsupported = args.filter( (arg) => arg.startsWith("-") && !["--stdin", "--json"].includes(arg), ); if (unsupported.length > 0) return { result: errorResult("invalid_command", `unsupported intent author option: ${unsupported[0]}`, 2), journal: journalFor( "intent", null, "rejected", "invalid_command", null, "Run imm-kernel intent author --stdin --json.", ), }; const pathArg = nonFlags[0]; // Routing policy must resolve to the active kernel_task_intent route. const policy = inspectRoutingPolicy(root); if (policy.policy_status === "invalid") { return { result: errorResult( "routing_policy_invalid", `routing policy is present but cannot be trusted (${policy.reason_code}); new managed authority is blocked`, 1, ), journal: journalFor( "intent", null, "rejected", "routing_policy_invalid", null, "Repair or remove the policy file; authoring requires the active kernel_task_intent route.", ), }; } if (policy.policy_status !== "active" || policy.route !== "kernel_task_intent") { return { result: errorResult( "intent_authoring_not_routed", "intent authoring requires the active kernel_task_intent routing policy", 1, ), journal: journalFor( "intent", null, "rejected", "routing_unavailable", null, "Activate the Git-owned managed-task routing policy before authoring.", ), }; } // Pending diffs may be committed; conversion stays on the explicit command. let layout = inspectStorageLayout(root); if (layout.layout === "migration_uncommitted") { try { commitPendingMigrationDiff(root); layout = inspectStorageLayout(root); } catch (error) { return sourceFailure("intent", error); } } if (layout.layout === "migration_blocked_active") { return { result: errorResult( "layout_migration_blocked", layout.reason ?? "an active old-layout owner blocks migration", 1, ), journal: journalFor( "intent", null, "rejected", "source_invalid", null, "Settle or stop the active old-layout owner with the prior runtime before authoring.", ), }; } if (layout.layout === "recovery_required" || layout.layout === "migration_required") { // Authoring never migrates implicitly: the retired layout is converted by // the explicit claimless command only, so creating a draft cannot publish a // database or retire historical files behind the operator's back. return { result: errorResult( layout.layout === "recovery_required" ? "layout_recovery_required" : "layout_migration_required", `${layout.reason ?? "storage layout is not ready"}; run imm-kernel migrate --storage-layout first`, 1, ), journal: journalFor( "intent", null, "rejected", "source_invalid", null, "Run imm-kernel migrate --storage-layout, then retry intent author.", ), }; } if (layout.layout !== "ready") { return { result: errorResult( "layout_not_ready", layout.reason ?? `storage layout is ${layout.layout}`, 1, ), journal: journalFor( "intent", null, "rejected", "source_invalid", null, "Resolve the reported layout condition before retrying authoring.", ), }; } try { probeKernelStore(root); } catch (error) { return sourceFailure("intent", error); } // Existing managed ownership rejects before opening the destination. const owner = intentActiveOwner(root); if (owner.kernel) return { result: errorResult( "kernel_owner_active", "an active Kernel claim already owns this workspace; authoring is blocked", 1, ), journal: journalFor( "intent", null, "rejected", "kernel_owner_active", null, "Route to drive instead of authoring a new draft.", ), }; if (owner.v3) return { result: errorResult( "v3_owner_nonterminal", "a nonterminal v3 Plan owns this workspace; authoring is blocked", 1, ), journal: journalFor( "intent", null, "rejected", "v3_owner_nonterminal", null, "Finish or terminate the active v3 Plan before authoring.", ), }; // Bounded stdin candidate, then strict parsing. let candidate: string; try { candidate = readBoundedStdin(INTENT_MAX_BYTES); } catch (error) { return { result: errorResult( "candidate_oversize", `candidate stdin exceeds the TaskIntent bound: ${error instanceof Error ? error.message : error}`, 1, ), journal: journalFor( "intent", null, "rejected", "input_oversize", null, "Reduce the candidate below the TaskIntent byte bound.", ), }; } let parsed: unknown; try { parsed = JSON.parse(candidate); } catch (error) { return { result: errorResult( "candidate_invalid", `candidate is not valid JSON: ${error instanceof Error ? error.message : error}`, 1, ), journal: journalFor( "intent", null, "rejected", "input_invalid", null, "Submit a complete task_intent/v1 JSON candidate.", ), }; } let intent: ReturnType; try { intent = parseProjectTaskIntent(root, parsed); } catch (error) { return { result: errorResult( "intent_invalid", `candidate failed strict task_intent/v1 parsing: ${error instanceof Error ? error.message : error}`, 1, ), journal: journalFor( "intent", null, "rejected", "intent_invalid", null, "Fix the reported task_intent/v1 violations and retry.", ), }; } let scopeFailure: string | null; try { scopeFailure = scopeEstimateFailure(root, intent); } catch (error) { return sourceFailure("intent", error); } if (scopeFailure) return { result: errorResult("scope_estimate_too_wide", scopeFailure, 1), journal: journalFor("intent", null, "rejected", "intent_invalid", null, scopeFailure), }; // Task/path identity: destination must be docs/plans/.intent.json. let sidecarPath: string; try { sidecarPath = intentSidecarPath(intent.task_id); } catch (error) { return { result: errorResult( "task_id_invalid", `task id is invalid: ${error instanceof Error ? error.message : error}`, 1, ), journal: journalFor( "intent", null, "rejected", "intent_invalid", null, "Use a task id matching the sidecar naming convention.", ), }; } if (pathArg !== sidecarPath && resolve(root, pathArg) !== resolve(root, sidecarPath)) { return { result: errorResult( "task_path_mismatch", `destination must be ${sidecarPath} for task ${intent.task_id}`, 1, ), journal: journalFor( "intent", null, "rejected", "task_path_mismatch", null, "Author the intent to its canonical sidecar path.", ), }; } // Canonicalize every acceptance verification string through the shared parser. let canonicalAcceptance: Array<{ id: string; assertion: string; verification: string; }>; try { canonicalAcceptance = intent.acceptance.map((item) => ({ id: item.id, assertion: item.assertion, verification: canonicalDescriptorBytes( parseVerificationDescriptor(item.verification), ), })); } catch (error) { return { result: errorResult( "intent_invalid", `candidate acceptance verification failed strict verification_descriptor/v2 parsing: ${error instanceof Error ? error.message : error}`, 1, ), journal: journalFor( "intent", null, "rejected", "intent_invalid", null, "Fix the reported verification_descriptor/v2 violations and retry.", ), }; } const canonicalIntent = { contract: intent.contract, task_id: intent.task_id, owner: intent.owner, goal: intent.goal, acceptance: canonicalAcceptance, scope_hint: intent.scope_hint, ...(intent.scope_size_reason === undefined ? {} : { scope_size_reason: intent.scope_size_reason }), risk: intent.risk, revision: intent.revision, }; const canonicalBytes = `${JSON.stringify(canonicalIntent, null, 2)}\n`; const contentHash = canonicalIntentHash(canonicalIntent); // Exclusive no-overwrite creation of exactly one regular file. const destination = resolve(root, sidecarPath); if (!destination.startsWith(resolve(root) + "/")) return { result: errorResult("destination_invalid", "destination escapes the project root", 1), journal: journalFor( "intent", null, "rejected", "destination_invalid", null, "The intent destination must stay inside the project.", ), }; const parent = resolve(root, INTENT_SIDECAR_PREFIX); try { const parentStat = lstatSync(parent); if (!parentStat.isDirectory()) return { result: errorResult("destination_parent_invalid", "docs/plans is not a directory", 1), journal: journalFor( "intent", null, "rejected", "destination_parent_invalid", null, "The docs/plans directory must exist.", ), }; } catch { return { result: errorResult( "destination_parent_missing", "docs/plans does not exist; parent creation is never implicit", 1, ), journal: journalFor( "intent", null, "rejected", "destination_parent_missing", null, "Create docs/plans explicitly before authoring.", ), }; } let fd: number; try { fd = openSync( destination, fsConstants.O_CREAT | fsConstants.O_EXCL | fsConstants.O_WRONLY, 0o644, ); } catch (error) { const code = (error as { code?: string }).code; const reason = code === "EEXIST" ? "destination already exists; no-overwrite authoring never replaces it" : code === "ENOENT" ? "destination parent does not exist" : `destination cannot be created: ${error instanceof Error ? error.message : error}`; return { result: errorResult("destination_exists", reason, 1), journal: journalFor( "intent", null, "rejected", "destination_exists", null, "Remove or rename the existing file; drafts are never overwritten.", ), }; } try { writeFileSync(fd, canonicalBytes, "utf8"); } catch (error) { closeSync(fd); return { result: errorResult( "destination_write_failed", `draft write failed: ${error instanceof Error ? error.message : error}`, 1, ), journal: journalFor( "intent", null, "rejected", "destination_write_failed", null, "Retry authoring after fixing the destination.", ), }; } closeSync(fd); return { result: jsonResult( { contract: "assurance_kernel/intent_author/v1", path: sidecarPath, task_id: intent.task_id, content_hash: contentHash, revision: intent.revision, git_tracked: false, enrollment_ready: false, }, 0, ), journal: journalFor( "intent", null, "ok", "command_ok", null, null, ), }; } /** * Canonical `imm-kernel intent validate --json`. * Zero writes: no friction journal, migration, lock, receipt, observation, * TaskRecord, claim, Ledger, Git index, or session write. Returns a stable * bounded projection. */ /** * Read-only: compare the `scope_hint` of two or more TaskIntents of one * Initiative and report every overlapping entry pair plus the start waves the * Batch Plan would use. Optional `--blocked-by a=b,c` edges order the waves the * way the Initiative's dependencies do. Writes nothing. */ function runIntentOverlap(args: string[], root: string): KernelExecution { const usage = "Run imm-kernel intent overlap ... [--blocked-by =,...] --json."; const reject = (message: string): KernelExecution => ({ result: errorResult("invalid_command", message, 2), journal: journalFor("intent", null, "rejected", "invalid_command", null, usage), }); const paths: string[] = []; const blockedBy = new Map(); for (let index = 0; index < args.length; index += 1) { const arg = args[index]!; if (arg === "--json") continue; if (arg === "--blocked-by") { const edge = args[++index] ?? ""; const match = /^([A-Za-z0-9][A-Za-z0-9._-]*)=([A-Za-z0-9._,-]+)$/.exec(edge); if (!match) return reject(`invalid --blocked-by edge: ${edge}`); blockedBy.set(match[1]!, match[2]!.split(",").filter(Boolean)); continue; } if (arg.startsWith("-")) return reject(`unsupported intent overlap option: ${arg}`); paths.push(arg); } if (paths.length < 2) return reject("imm-kernel intent overlap requires at least two paths"); const children: Array<{ task_id: string; blocked_by: string[]; scope_hint: string[] }> = []; for (const path of paths) { let intent: { task_id?: unknown; scope_hint?: unknown }; try { intent = JSON.parse(readFileSync(resolve(root, path), "utf8")); } catch (error) { return { result: errorResult("source_invalid", `cannot read ${path}: ${error instanceof Error ? error.message : String(error)}`, 1), journal: journalFor("intent", null, "rejected", "source_read_failed", null, usage) }; } if (typeof intent.task_id !== "string" || !Array.isArray(intent.scope_hint) || intent.scope_hint.some((entry) => typeof entry !== "string")) return { result: errorResult("source_invalid", `${path} has no task_id and string scope_hint`, 1), journal: journalFor("intent", null, "rejected", "source_invalid", null, usage) }; children.push({ task_id: intent.task_id, blocked_by: [], scope_hint: intent.scope_hint as string[] }); } const known = new Set(children.map((child) => child.task_id)); for (const child of children) child.blocked_by = (blockedBy.get(child.task_id) ?? []).filter((id) => known.has(id)); let report: ReturnType; try { report = projectScopeOverlap(children); } catch (error) { return reject(error instanceof Error ? error.message : String(error)); } return { result: jsonResult(report, 0), journal: journalFor("intent", null, "ok", "command_ok", null, null) }; } function runIntentValidate(args: string[], root: string): KernelExecution { const nonFlags = args.filter((arg) => !arg.startsWith("-")); if (nonFlags.length !== 1) return { result: errorResult( "invalid_command", "imm-kernel intent validate requires exactly one path", 2, ), journal: journalFor( "intent", null, "rejected", "invalid_command", null, "Run imm-kernel intent validate --json.", ), }; const unsupported = args.filter( (arg) => arg.startsWith("-") && !["--json"].includes(arg), ); if (unsupported.length > 0) return { result: errorResult("invalid_command", `unsupported intent validate option: ${unsupported[0]}`, 2), journal: journalFor( "intent", null, "rejected", "invalid_command", null, "Run imm-kernel intent validate --json.", ), }; const pathArg = nonFlags[0]; // Shared zero-write gate (review-4): validation reports the layout // condition instead of reading authority bytes while migration/recovery // is pending. const layout = inspectStorageLayout(root); if (!["ready", "migration_uncommitted"].includes(layout.layout)) return { result: errorResult( "layout_not_ready", `intent validate blocked by storage layout (${layout.layout}): ${layout.reason ?? ""}`, 1, ), journal: journalFor( "intent", null, "rejected", "source_invalid", null, layout.reason, ), }; // Canonical-root containment, no symlink components. let canonicalRoot: string; try { canonicalRoot = resolve(root); } catch { return { result: errorResult("root_invalid", "project root is unavailable", 1), journal: journalFor( "intent", null, "rejected", "source_read_failed", null, null, ), }; } const target = resolve(canonicalRoot, pathArg); const relative = target.startsWith(canonicalRoot + "/") ? target.slice(canonicalRoot.length + 1) : null; if (!relative || !relative.startsWith(INTENT_SIDECAR_PREFIX) || !relative.endsWith(".intent.json")) { return { result: errorResult( "path_invalid", "intent path must be docs/plans/.intent.json inside the project", 1, ), journal: journalFor( "intent", null, "rejected", "source_invalid", null, "Validate a canonical intent sidecar path.", ), }; } const taskId = relative .slice(INTENT_SIDECAR_PREFIX.length) .replace(/\.intent\.json$/, ""); let raw: string; try { raw = readSecureProjectFile(root, relative); } catch (error) { const message = error instanceof Error ? error.message : String(error); return { result: jsonResult( { contract: "assurance_kernel/intent_validation/v1", valid: false, path: relative, task_id: taskId, reason: message, }, 0, ), journal: journalFor( "intent", null, "ok", "command_ok", null, null, ), }; } if (Buffer.byteLength(raw, "utf8") > INTENT_MAX_BYTES) { return { result: jsonResult( { contract: "assurance_kernel/intent_validation/v1", valid: false, path: relative, task_id: taskId, reason: "intent sidecar exceeds 64 KiB", }, 0, ), journal: journalFor( "intent", null, "ok", "command_ok", null, null, ), }; } let parsed: unknown; try { parsed = JSON.parse(raw); } catch (error) { return { result: jsonResult( { contract: "assurance_kernel/intent_validation/v1", valid: false, path: relative, task_id: taskId, reason: `not valid JSON: ${error instanceof Error ? error.message : error}`, }, 0, ), journal: journalFor( "intent", null, "ok", "command_ok", null, null, ), }; } // Strict parse + verification eligibility per acceptance item. let intent: ReturnType; try { intent = parseProjectTaskIntent(root, parsed); } catch (error) { return { result: jsonResult( { contract: "assurance_kernel/intent_validation/v1", valid: false, path: relative, task_id: taskId, reason: `strict task_intent/v1 parsing failed: ${error instanceof Error ? error.message : error}`, }, 0, ), journal: journalFor( "intent", null, "ok", "command_ok", null, null, ), }; } if (intent.task_id !== taskId) { return { result: jsonResult( { contract: "assurance_kernel/intent_validation/v1", valid: false, path: relative, task_id: taskId, reason: `intent.task_id ${intent.task_id} does not match the sidecar filename task id`, }, 0, ), journal: journalFor( "intent", null, "ok", "command_ok", null, null, ), }; } const specBinding = inspectSpecBinding(intent); if (!specBinding.ok) { return { result: jsonResult( { contract: "assurance_kernel/intent_validation/v1", valid: false, path: relative, task_id: intent.task_id, reason: specBinding.message, }, 0, ), journal: journalFor( "intent", null, "ok", "command_ok", null, null, ), }; } const verification: Array<{ id: string; eligible: boolean; reason: string | null }> = []; let allEligible = true; for (const item of intent.acceptance) { try { parseVerificationDescriptor(item.verification); verification.push({ id: item.id, eligible: true, reason: null }); } catch (error) { allEligible = false; verification.push({ id: item.id, eligible: false, reason: error instanceof Error ? error.message : String(error), }); } } // Git ownership status: tracked, untracked, or unavailable. let gitTracked: boolean; try { execFileSync( "git", ["ls-files", "--error-unmatch", "--", relative], { cwd: canonicalRoot, stdio: ["ignore", "pipe", "pipe"] }, ); gitTracked = true; } catch { gitTracked = false; } let gitBase: EnrollmentGitBase | { state: "invalid"; reason: string }; try { gitBase = inspectEnrollmentGitBase(canonicalRoot); } catch (error) { gitBase = { state: "invalid", reason: error instanceof Error ? error.message : String(error) }; } const contentHash = canonicalIntentHash(intent); let scopeFailure: string | null; try { scopeFailure = scopeEstimateFailure(root, intent); } catch (error) { return sourceFailure("intent", error); } const enrollmentReady = gitTracked && allEligible && gitBase.state !== "invalid" && !scopeFailure; return { result: jsonResult( { contract: "assurance_kernel/intent_validation/v1", valid: true, path: relative, task_id: intent.task_id, content_hash: contentHash, risk: intent.risk, acceptance_ids: intent.acceptance.map((item) => item.id), verification: verification, git_ownership: gitTracked ? "tracked" : "untracked", git_base: gitBase, git_base_initialization_required: gitBase.state === "unborn", enrollment_ready: enrollmentReady, ...(scopeFailure ? { code: "scope_estimate_too_wide", reason: scopeFailure } : {}), }, 0, ), journal: journalFor( "intent", null, "ok", "command_ok", null, null, ), }; } function executeKernelCommand(args: string[], root: string): KernelExecution { const command = args[0] ?? ""; const flags = args.slice(1); if (command === "intent") { const sub = args[1] ?? ""; if (sub === "author") return runIntentAuthor(args.slice(2), root); if (sub === "validate") return runIntentValidate(args.slice(2), root); if (sub === "overlap") return runIntentOverlap(args.slice(2), root); return { result: errorResult( "invalid_command", "usage: imm-kernel intent author --stdin --json | validate --json | overlap ... [--blocked-by =,...] --json", 2, ), journal: journalFor( "intent", null, "rejected", "invalid_command", null, "Run imm-kernel intent --help.", ), }; } if (command === "status") { if (flags.some((flag) => flag !== "--json")) return { result: errorResult("invalid_command", "status accepts only --json", 2), journal: journalFor( command, null, "rejected", "invalid_command", null, "Run imm-kernel status --json.", ), }; return runStatus(root); } if (command === "inspect") { if (flags.length !== 1 || flags[0] !== "--json") return { result: errorResult("invalid_command", "inspect accepts only --json", 2), journal: journalFor( command, null, "rejected", "invalid_command", null, "Run imm-kernel inspect --json.", ), }; return runInspect(root); } if (command === "migrate") { if (flags.length !== 1 || flags[0] !== "--storage-layout") return { result: errorResult( "invalid_command", "migrate accepts only --storage-layout", 2, ), journal: journalFor( command, null, "rejected", "invalid_command", null, "Run imm-kernel migrate --storage-layout.", ), }; return runStorageLayoutMigration(root); } if (command === "audit") { if (args.length !== 2 || args[1] !== "--legacy") return { result: errorResult( "invalid_command", "audit accepts only --legacy", 2, ), journal: journalFor( "audit", null, "rejected", "invalid_command", null, "Run imm-kernel audit --legacy.", ), }; // Shared zero-write gate (review-4): the audit reports the layout // condition instead of reading legacy authority while a migration or // recovery is pending. const layout = inspectStorageLayout(root); if (!["ready", "migration_uncommitted"].includes(layout.layout)) return { result: jsonResult({ contract: "assurance_kernel/legacy_audit/v1", source: null, read_only: true, writes_performed: false, plan_path: null, runtime_status: null, active_step: null, step_count: 0, phase: null, digest: "sha256:none", redacted: true, layout: { layout: layout.layout, reason: layout.reason, next_action: layout.layout === "migration_required" ? "run imm-kernel migrate --storage-layout, then retry legacy audit" : "resolve the reported layout condition before legacy audit", }, }), journal: journalFor( "audit", null, "escalated", "source_invalid", null, layout.reason, ), }; try { return { result: jsonResult(projectLegacyAudit(root)), journal: journalFor( "audit", null, "ok", "command_ok", null, null, ), }; } catch (error) { return sourceFailure("audit", error); } } if (command === "--help" || command === "help") return { result: { stdout: "usage: imm-kernel status --json\n imm-kernel inspect --json\n imm-kernel audit --legacy\n imm-kernel intent author --stdin --json\n imm-kernel intent validate --json\n", stderr: "", returncode: 0, }, journal: journalFor("help", null, "ok", "command_ok", null, null), }; return { result: errorResult( "invalid_command", "usage: imm-kernel status --json | inspect --json | audit --legacy | intent author --stdin --json | intent validate --json", 2, ), journal: journalFor( command || "", null, "rejected", "invalid_command", null, "Run imm-kernel --help.", ), }; } /** * Explicit claimless storage-layout migration. * * The retired file store is converted here and nowhere else: this command never * authors an intent, never opens a task, and never needs an active claim, so a * worktree that is still on the retired layout has one reachable entry point. * Mutating commands keep their fail-closed gate; this is the command that * resolves it. */ function runStorageLayoutMigration(root: string): KernelExecution { const inspection = inspectStorageLayout(root); // Only a live owner blocks the command. Every other diagnosis is handed to // the migrator, which owns the recovery decisions: an interrupted // publication shows both stores and must stay reachable through this CLI. if (inspection.layout === "migration_blocked_active") return { result: errorResult( "layout_migration_blocked", inspection.reason ?? "a live legacy task still owns work; settle or stop it on the prior runtime first", 1, ), journal: journalFor( "migrate", null, "rejected", "source_invalid", null, "Resolve the reported layout condition, then rerun imm-kernel migrate --storage-layout.", ), }; const migration = migrateAndCommitLegacyLayout(root); if (migration.outcome === "migrated" || migration.outcome === "already_migrated") return { result: jsonResult({ contract: "assurance_kernel/migration_completed/v1", operation: "storage layout migration", layout: "ready", affected_paths: migration.affected_paths, next_action: "retry the original command", }), journal: journalFor("migrate", null, "ok", "command_ok", null, "Retry the original command."), }; // Git integration: manual (ADR 0024): the diff is the user's to commit. if (migration.outcome === "migration_uncommitted" && migration.affected_paths.length > 0) return { result: jsonResult({ contract: "assurance_kernel/migration_uncommitted/v1", operation: "storage layout migration", layout: "migration_uncommitted", affected_paths: migration.affected_paths, reason: migration.reason, next_action: "commit the listed paths however you prefer, then rerun imm-kernel migrate --storage-layout", }, 1), journal: journalFor("migrate", null, "rejected", "source_invalid", null, "Commit the listed paths, then rerun imm-kernel migrate --storage-layout."), }; return { result: errorResult( "layout_migration_blocked", migration.reason ?? "the storage layout migration did not complete", 1, ), journal: journalFor( "migrate", null, "rejected", "source_invalid", null, "Resolve the reported layout condition, then rerun imm-kernel migrate --storage-layout.", ), }; } export function runKernelCommand( args: string[], root = process.cwd(), ): KernelCommandResult { const execution = executeKernelCommand(args, root); // Retained read-only commands (intent/status/audit) and retired // subcommands (migrate/readiness/journal) are no-journal: they never // append the friction journal. Only the fallback unknown-command path // keeps journaling. if (["intent", "status", "inspect", "audit", "migrate", "readiness", "journal"].includes(args[0] ?? "")) return execution.result; let warning = ""; try { appendJournalEntry(root, { contract: "assurance_kernel/journal/v1", timestamp: new Date().toISOString(), ...execution.journal, }); } catch (error) { warning = `warning: kernel journal append failed: ${error instanceof Error ? error.message : error}\n`; } return { ...execution.result, stderr: `${execution.result.stderr}${warning}`, }; } async function main(args: string[]): Promise { const result = runKernelCommand(args); if (result.stdout) process.stdout.write(result.stdout); if (result.stderr) process.stderr.write(result.stderr); return result.returncode; } if (fileURLToPath(import.meta.url) === process.argv[1]) { process.exit(await main(process.argv.slice(2))); }