/*
steps index — barrel exports for mission lifecycle step definitions and resolver (RFC-0958).
- Do not implement step logic here — delegate to per-command step files.
- RFC-0958: initial steps barrel with resolveOperationSteps resolver.
- RFC-1097: sweep — werkstatt-engine clean
Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics.
- RFC-1219: resolveOperationSteps gains KernelRuntimeContext and returns { steps, ctx } — mission.resume previously passed a thin {workspaceRoot, missionId, manifest, context} runtime ctx, so every resumed step crashed on missing fields (m000192: fetch-and-merge died with "path argument must be of type string. Received undefined"). Each kind now reconstructs the command ctx: derivable fields resolved (dirs, systemDir, state), flag-derived fields defaulted (documented resume semantics: flags reset on resume).
- RFC-1264
*/
import path from "node:path";
import type { KernelRuntimeContext } from "@warpgogol/werkstatt-engine/kernel";
import type { OperationStep } from "../../journal/index.ts";
import type { MissionManifest } from "@warpgogol/werkstatt-engine/schemas";
import { resolveMissionDir } from "../mission-io.ts";
import { resolveCacheClonePath } from "../../sternsystem/registry-io.ts";
export interface ResolvedOperation {
steps: OperationStep[];
/** Fully reconstructed per-kind step ctx — pass to runOperation as ctx. */
ctx: unknown;
}
/**
* Resolve the step list AND the runtime ctx for an operation kind.
* The ctx mirrors what the command handler constructs — flag-derived values
* default (resume semantics: flags are not journaled, so a resumed op
* continues with defaults), accumulators start fresh, and `actor` is
* "agent" (matching mission.resume's lock actor).
*/
export async function resolveOperationSteps(
op: string,
workspaceRoot: string,
missionId: string,
manifest: unknown,
context: KernelRuntimeContext,
): Promise {
const typedManifest = manifest as MissionManifest;
const missionDir = await resolveMissionDir(workspaceRoot, missionId, context.io);
const workpieceDir = path.join(missionDir, "workpiece");
const evidenceDir = path.join(missionDir, "evidence");
const now = new Date().toISOString();
const logger = context.logger;
switch (op) {
case "mission.close": {
const mod = await import("./close-steps.ts");
const ctx: import("../mission-close.ts").CloseStepCtx = {
workspaceRoot,
missionId,
missionDir,
workpieceDir,
evidenceDir,
manifest: typedManifest,
actor: "agent",
releaseId: null,
now,
skipEvidenceSync: false,
skipAutoSync: false,
skipReconcileCheck: false,
allowNoOp: false,
skipContentRegression: false,
skipBehaviorSnapshot: false,
skipDigest: false,
context,
templateSyncResult: { synced: false, syncError: null },
digestPath: null,
closeReport: null,
evidenceSynced: false,
evidenceSyncResult: null,
freshnessChecked: false,
unreconciledCommits: 0,
workpieceHead: null,
reconciledSha: null,
originSha: null,
mirrorSha: null,
mirrorInSync: false,
recommendation: null,
};
return { steps: await mod.buildCloseSteps(workspaceRoot, missionId, ctx), ctx };
}
case "mission.reconcile": {
const mod = await import("./reconcile-steps.ts");
const ctx: import("../mission-materialization-commands.ts").ReconcileStepCtx = {
workspaceRoot,
missionId,
missionDir,
workpieceDir,
evidenceDir,
systemDir: resolveCacheClonePath(workspaceRoot, typedManifest.systemId),
manifest: typedManifest,
actor: "agent",
message: `Reconcile ${missionId}`,
now,
context,
commitSha: null,
preReconcileSha: null,
mergeCommitSha: null,
transferredCommits: 0,
mergedShas: [],
copiedPaths: [],
autoResolvedPaths: [],
workpieceHeadAtReconcile: null,
gitignoreRestored: false,
forbiddenFilesUntracked: [],
mirrorSync: { attempted: false, succeeded: false, error: null },
divergenceWarning: null,
workpieceCommit: { committed: false, commitSha: null },
};
return { steps: await mod.buildReconcileSteps(workspaceRoot, missionId, ctx), ctx };
}
case "mission.materialize": {
const mod = await import("./materialize-steps.ts");
const { resolveStagingDir } = await import("../../werkstatt/atomic.ts");
const operationId = typedManifest.operationId ?? "";
const ctx: import("../mission-materialize.ts").MaterializeStepCtx = {
workspaceRoot,
missionId,
manifest: typedManifest,
context,
logger,
reportOnly: false,
skipPreflight: false,
force: false,
systemDir: resolveCacheClonePath(workspaceRoot, typedManifest.systemId),
missionDir,
workpieceDir,
stagingDir: resolveStagingDir(missionDir, workpieceDir, operationId),
operationId,
verdict: "in-sync",
pinVersion: "",
platformVersion: "",
message: `Materialize ${missionId}`,
preflightSkipped: false,
preflightSkipReason: null,
artifactCacheHit: false,
artifactCacheKey: null,
artifactCacheSkipped: false,
cacheCloneHead: null,
artifactCacheKeyComponents: null,
regeneratedFiles: [],
mediaCacheWarmed: false,
mediaCacheSources: 0,
bordbuchHookInstalled: false,
clonedGitDir: null,
prepareReport: { ok: true, steps: [] },
workspaceGlobCheck: { stalePackages: [], ok: true },
now,
};
return { steps: await mod.buildMaterializeSteps(workspaceRoot, missionId, ctx), ctx };
}
case "mission.open": {
const mod = await import("./open-steps.ts");
const { readSystemState } = await import("../../sternsystem/registry-io.ts");
const ctx: import("../mission-open.ts").OpenStepCtx = {
workspaceRoot,
systemId: typedManifest.systemId,
missionId,
manifest: typedManifest,
actor: "agent",
now,
pinAtOpen: "",
operationId: typedManifest.operationId ?? "",
staleEntries: { removedPaths: [], skipped: [] },
context,
state: await readSystemState(workspaceRoot, typedManifest.systemId, context.io),
materializedAt: null,
};
return { steps: await mod.buildOpenSteps(workspaceRoot, missionId, ctx), ctx };
}
case "mission.validate": {
const mod = await import("./validate-steps.ts");
const ctx: import("../mission-materialization-commands.ts").ValidateStepCtx = {
workspaceRoot,
missionId,
manifest: typedManifest,
logger,
evidenceDir,
missionDir,
workpieceDir,
collectErrors: false,
skipContentRegression: false,
autoAcceptRegression: false,
force: false,
fast: false,
previousReport: null,
cascadeRerun: false,
prepareReport: null,
pipelineReport: null,
staticPassed: false,
stepCount: 0,
failedSteps: [],
buildSucceeded: false,
buildError: undefined,
routeCount: 0,
sitemapHash: "",
postPipelineReport: undefined,
dirtyBeforeBuildPost: { dirty: false, fileCount: 0 },
preliminaryBuildIdentityPath: null,
now,
io: context.io,
};
return { steps: mod.buildValidateSteps(ctx), ctx };
}
case "mission.archive": {
const mod = await import("./archive-steps.ts");
const steps = await mod.buildArchiveSteps(workspaceRoot, missionId, manifest);
return { steps, ctx: { workspaceRoot, missionId, manifest, context } };
}
case "mission.abort": {
const mod = await import("./abort-steps.ts");
const ctx: import("../mission-abort.ts").AbortStepCtx = {
workspaceRoot,
missionId,
missionDir,
workpieceDir,
evidenceDir,
manifest: typedManifest,
actor: "agent",
reason: "resumed abort",
now,
io: context.io,
};
return { steps: await mod.buildAbortSteps(workspaceRoot, missionId, ctx), ctx };
}
default:
return null;
}
}