/*
Lazy-loading kernel module for RFC-0651 evidence commands: evidence.sync and evidence.fetch.
- Does not re-export types or utilities — the barrel index.ts remains the public API surface.
- Does not integrate with mission.close or leitstand.dev-deploy — that is RFC-0652.
- RFC-1190: declare --site/--system on evidence.sync so leitstand.ship evidence-sync-* steps pass flag validation.
- RFC-1202: evidence.sync description documents the upload-manifest dedup (repeated runs against an unchanged prefix become manifest-check no-ops).
- RFC-1190: restore mission context + evidence archival in release-mode deploys
RFC-1190: precedence-ordered resolveMissionContext (--mission → release build-identity → currentMission), MISSION_CONTEXT_UNRESOLVED/MISMATCH blocking, fail-closed EVIDENCE_SYNC_FAILED with --skip-evidence-sync as sole escape hatch, journaled evidence-sync-* ship steps after each certify-*, evidence.sync --site/--system flag.
2026-10-04 handoff fixes: shared 25min mission.check timeout (inner 5min race + 300s orchestrator raced cold ~7-11min captures), sweep excludeOpIds so mission.close no longer self-abandons the live ship journal (broke --resume), name-keyed journal resume state so closed-mission plan shifts can't skip unexecuted steps, wrangler dev documented as the required --base-url preview server.
- RFC-1231: step 1 — rename supportsAllSites to acceptsAllFlag
Mechanical sweep: the field only ever gated --all argv acceptance; fan-out
follows the parsed selector. Guard renamed assertAllSitesAllowed ->
assertAllFlagAccepted, message updated. 417 declaration sites + type
surfaces (KernelCommandMetadata, ForgeCommandMetadata) in one atomic pass.
- RFC-1248: VITE-CLIENT-DEP-02 lazy-import gate + SCAN-02 validator reads-root existence check (RFC-1248)
RFC-0651, RFC-1097, RFC-1173
*/
import type { ModuleExport } from "@warpgogol/werkstatt-shared/kernel";
export async function createEvidenceModule(): Promise {
const { runEvidenceSync } = await import("./evidence-sync.ts");
const { runEvidenceFetch } = await import("./evidence-fetch.ts");
return {
name: "evidence",
version: "0.1.0",
declarations: [],
commands: [
{
name: "evidence.sync",
modulePath: "packages/werkstatt-engine/src/evidence/evidence-module.ts",
generates: [],
description:
"RFC-0651: upload all evidence artifacts from missions/{mission}/evidence/axiom/ to R2 " +
"under {systemId}/{missionId}/{runTimestamp}/ key prefix. Reads runTimestamp from " +
"evidence-metadata.json (or --run-timestamp flag). Supports --dry-run. " +
"RFC-1202: writes a {runTimestamp}.upload-manifest.json sibling marker after a successful " +
"upload; a repeat run whose evidence set matches the manifest skips the upload entirely " +
"(deduped: true). " +
"Failure modes: MISSING_ENV, NOT_FOUND, INVALID_EVIDENCE, R2_UPLOAD_ERROR. Required flags: `--mission`.",
scope: "workspace",
acceptsAllFlag: false,
mutatesState: false,
cacheable: false,
flags: {
mission: {
kind: "string",
required: true,
description: "Mission id (e.g. warpgogol-com-m000025).",
},
site: {
kind: "string",
description:
"RFC-1190: Explicit Sternsystem id for the R2 key prefix. Validated against the resolved system; falls back to currentMission scan / missionId prefix.",
},
system: {
kind: "string",
description: "Alias for --site.",
},
"run-timestamp": {
kind: "string",
description:
"Explicit run timestamp (YYYY-MM-DDTHH-MM-SS-mmmZ). Defaults to evidence-metadata.json runTimestamp.",
},
"dry-run": {
kind: "boolean",
description: "Report what would be uploaded without making R2 API calls.",
},
json: { kind: "boolean", description: "Output JSON result." },
},
reads: [
"missions/{mission}/evidence/axiom/**",
"../systems-cache/*/system-config.yaml",
"../systems-cache/*/system-state.yaml",
],
writes: [],
execute: runEvidenceSync,
},
{
name: "evidence.fetch",
coverage: "operator" as const,
modulePath: "packages/werkstatt-engine/src/evidence/evidence-module.ts",
generates: [],
description:
"RFC-0651: download a historical evidence run from R2 to a local directory, " +
"or list available runs via ListObjectsV2. Uses --run-timestamp to select a run, " +
"--output-dir to specify the download location, --no-raw to skip raw/ artifacts, " +
"--list to list available runs. Failure modes: MISSING_ENV, NOT_FOUND, R2_LIST_ERROR. Required flags: `--mission`.",
scope: "workspace",
acceptsAllFlag: false,
mutatesState: true,
cacheable: false,
flags: {
mission: {
kind: "string",
required: true,
description: "Mission id (e.g. warpgogol-com-m000025).",
},
"run-timestamp": {
kind: "string",
description:
"Run timestamp to fetch (YYYY-MM-DDTHH-MM-SS-mmmZ). Required unless --list.",
},
"output-dir": {
kind: "string",
description: "Local directory to download evidence to. Required unless --list.",
},
"no-raw": {
kind: "boolean",
description: "Skip raw/ artifacts — download only structured JSON and report.html.",
},
list: {
kind: "boolean",
description: "List available runs for the mission instead of fetching.",
},
json: { kind: "boolean", description: "Output JSON result." },
},
reads: ["../systems-cache/*/system-config.yaml", "../systems-cache/*/system-state.yaml"],
writes: ["{--output-dir}/**"],
execute: runEvidenceFetch,
},
],
pipelines: [],
};
}