/* RFC-1265: verify mission.materialize invokes ops.card.generate so every fresh workpiece carries a current .werkstatt/ops-card.yaml (AC-3). Not a contract source of truth — the module under test owns the authoritative behavior; fixtures are minimal scaffolding only. RFC-1265: initial test — ops.card.generate invoked with --site during materialize; failure is non-fatal. RFC-1265 RFC-1275: steps 1-5: journal-portal domain, six blocks, binding emission */ import { test, expect, beforeEach, afterEach, vi } from "vitest"; import { mkdtempSync, rmSync, mkdirSync, writeFileSync } from "node:fs"; import { join } from "node:path"; import { execSync } from "node:child_process"; import type { KernelCommandInput, KernelRuntimeContext } from "@warpgogol/werkstatt-engine/kernel"; import { tmpdir } from "node:os"; import { createDefaultIO } from "@warpgogol/werkstatt-shared/kernel/workspace-io"; const mockExecuteKernelCommand = vi.hoisted(() => ({ calls: [] as Array<{ commandName: string; argv?: string[] }>, })); vi.mock("@warpgogol/werkstatt-engine/kernel", async (importOriginal) => { const actual = await importOriginal(); return { ...actual, executeKernelPipeline: vi.fn(async () => [ { ok: true, steps: [{ ok: true, commandName: "config.regenerate", exitCode: 0 }] }, ]), executeKernelCommand: vi.fn(async (opts: { commandName: string; argv?: string[] }) => { mockExecuteKernelCommand.calls.push({ commandName: opts.commandName, argv: opts.argv }); return [{ ok: true, exitCode: 0, summary: "" }]; }), runKernelWire: vi.fn(async () => ({ data: { generated: [] } })), }; }); vi.mock("../bordbuch/bordbuch-io.ts", () => ({ validateBordbuch: vi.fn(async () => ({ entries: 0, violations: [] })), readBordbuch: vi.fn(async () => []), commitAndPushBordbuch: vi.fn(async () => ({ commitSha: "abc123", pushed: true, error: null, })), })); vi.mock("../bordbuch/bordbuch-commit-helper.ts", () => ({ appendAndCommitBordbuch: vi.fn(async () => ({ entry: { id: "event-000001", kind: "mission-materialize" }, commitResult: { commitSha: "abc123", pushed: true, error: null }, })), })); vi.mock("../sternsystem/registry-io.ts", async (importOriginal) => { const original = (await importOriginal()) as Record; return { ...original, resolveCacheClonePath: vi.fn((workspaceRoot: string, systemId: string) => join(workspaceRoot, "..", "systems-cache", systemId), ), readSystemConfigSmart: vi.fn(async () => ({ schemaVersion: "system-config/v1", id: "test-system", cosmicStar: "Vega", mirrors: [{ path: "../systems-cache/test-system", storageType: "non-bare" }], pinnedPlatform: "1.0.0", status: "active", registeredAt: "2026-01-01T00:00:00Z", notes: "", })), readSystemState: vi.fn(async () => ({ schemaVersion: "1.0.0", id: "test-system", currentMission: "test-system-m000001", lastRelease: null, })), writeSystemState: vi.fn(async () => {}), }; }); vi.mock("@warpgogol/werkstatt-site/codegen", () => ({ runGenerateAgentsDocs: vi.fn(async () => []), runGenerateApiRoutes: vi.fn(async () => []), runGenerateGlobalStyles: vi.fn(async () => []), runGenerateI18nMiddleware: vi.fn(async () => []), runGenerateOverlayPages: vi.fn(async () => []), runGeneratePublicInfrastructure: vi.fn(async () => []), runGenerateRoutes: vi.fn(async () => []), runGenerateScriptsOrchestrator: vi.fn(async () => []), runFontsImportsGenerate: vi.fn(async () => []), runBiomeCssGenerate: vi.fn(async () => []), runAppBoilerplateValidate: vi.fn(async () => ({ data: { generated: [] }, summary: "ok", nextSteps: [], })), runGenerateMaterialCreditsPage: vi.fn(async () => []), runPropsTypesGenerate: vi.fn(async () => []), runGenerateIcons: vi.fn(async () => []), runCleanIcons: vi.fn(async () => []), runGenerateOpenSourcePage: vi.fn(async () => []), runSectionScaffold: vi.fn(async () => []), runSystemMdCompile: vi.fn(async () => []), runLegalScaffold: vi.fn(async () => []), runMaterialMetadataWrite: vi.fn(async () => []), runContentRefIndexGenerate: vi.fn(async () => []), runContentRefMigrate: vi.fn(async () => []), runContentFormulaMigrate: vi.fn(async () => []), buildGeneratedHeader: vi.fn(() => ""), hasGeneratedMarker: vi.fn(() => false), stripGeneratedMarker: vi.fn((s: string) => s), GENERATED_MARKER: "GENERATED", })); vi.mock("@warpgogol/werkstatt-site/onboarding", () => ({ applyTokens: vi.fn((s: string) => s), readTemplate: vi.fn(() => ""), readRuntimeTemplate: vi.fn(() => ""), generateWorkpiecePackageJson: vi.fn(() => ({ packageJson: "{}", resolved: [] })), readTemplateFields: vi.fn(() => ({})), resolveBasePath: vi.fn(() => ""), resolveAdapterBlock: vi.fn(() => ""), resolveJournalBindingsBlock: vi.fn(() => ""), })); vi.mock("@warpgogol/werkstatt-site/checks", () => ({ runEnvExampleGenerate: vi.fn(async () => []), MISSION_PREFLIGHT_CRITICAL: [], MISSION_PREFLIGHT_WARNING: [], toOwnershipEntries: vi.fn(() => []), })); function gitInit(dir: string): void { execSync("git init -b main", { cwd: dir, stdio: "pipe" }); execSync("git config user.email test@test.com", { cwd: dir, stdio: "pipe" }); execSync("git config user.name Test", { cwd: dir, stdio: "pipe" }); } function gitCommit(dir: string, msg: string): void { execSync("git add -A", { cwd: dir, stdio: "pipe" }); execSync(`git commit -m ${JSON.stringify(msg)}`, { cwd: dir, stdio: "pipe" }); } let testRoot: string; let tmpWorkspace: string; beforeEach(() => { testRoot = mkdtempSync(join(tmpdir(), "tmp-mat-opscard-")); tmpWorkspace = join(testRoot, "workspace"); mkdirSync(tmpWorkspace, { recursive: true }); mockExecuteKernelCommand.calls = []; }); afterEach(() => { rmSync(testRoot, { recursive: true, force: true }); }); function setupWorkspace(): string { gitInit(testRoot); writeFileSync(join(tmpWorkspace, "README.md"), "# test\n"); writeFileSync(join(tmpWorkspace, "package.json"), JSON.stringify({ version: "1.0.0" }) + "\n"); writeFileSync(join(tmpWorkspace, "pnpm-workspace.yaml"), "packages: []\n"); gitCommit(testRoot, "initial"); const cacheDir = join(testRoot, "systems-cache", "test-system"); mkdirSync(cacheDir, { recursive: true }); writeFileSync( join(cacheDir, "system-config.yaml"), `schemaVersion: system-config/v1 id: test-system cosmicStar: Vega mirrors: - path: "../systems-cache/test-system" storageType: non-bare pinnedPlatform: "1.0.0" status: active registeredAt: "2026-01-01T00:00:00Z" notes: "" `, ); gitCommit(testRoot, "add system config"); writeFileSync( join(cacheDir, "system.pin.json"), JSON.stringify({ platform: { version: "1.0.0" } }, null, 2) + "\n", ); mkdirSync(join(cacheDir, "bordbuch"), { recursive: true }); writeFileSync(join(cacheDir, "bordbuch", "events.ndjson"), ""); mkdirSync(join(cacheDir, "src", "content"), { recursive: true }); writeFileSync( join(cacheDir, "src", "content", "system.md"), "---\n domain: test\n i18n:\n default: de\n languages:\n - de\n---\n", ); gitCommit(testRoot, "add system"); const missionDir = join(tmpWorkspace, "missions", "test-system-m000001"); mkdirSync(missionDir, { recursive: true }); mkdirSync(join(missionDir, "workpiece"), { recursive: true }); mkdirSync(join(missionDir, "evidence"), { recursive: true }); const manifest = { schemaVersion: "1.0.0", missionId: "test-system-m000001", systemId: "test-system", state: "open", brief: "Test mission", openedAt: "2026-07-30T00:00:00.000Z", openedBy: "test-agent", closedAt: null, closedBy: null, pinAtOpen: "1.0.0", materializedAt: null, migratedAt: null, reconciledAt: null, releaseId: null, rfcId: null, operationId: "op-001", }; writeFileSync(join(missionDir, "mission.yaml"), JSON.stringify(manifest, null, 2) + "\n"); gitCommit(testRoot, "add mission"); return cacheDir; } test("RFC-1265: mission.materialize invokes ops.card.generate for the workpiece site", async () => { setupWorkspace(); const { runMissionMaterialize } = await import("../mission/mission-materialize.ts"); const input = { flags: { mission: "test-system-m000001" }, } as unknown as KernelCommandInput; const context = { io: createDefaultIO().io, workspaceRoot: tmpWorkspace, logger: { info: () => {}, warn: () => {} }, } as unknown as KernelRuntimeContext; await runMissionMaterialize(input, context); const cardCall = mockExecuteKernelCommand.calls.find( (c) => c.commandName === "ops.card.generate", ); expect(cardCall).toBeDefined(); expect(cardCall!.argv).toContain("--site=test-system"); }); test("RFC-1265: ops.card.generate failure is non-fatal (materialization succeeds)", async () => { setupWorkspace(); const { executeKernelCommand } = await import("@warpgogol/werkstatt-engine/kernel"); vi.mocked(executeKernelCommand).mockImplementation(async (opts) => { if (opts.commandName === "ops.card.generate") { throw new Error("card compile failed"); } return [{ ok: true, exitCode: 0, summary: "" }] as never; }); const { runMissionMaterialize } = await import("../mission/mission-materialize.ts"); const input = { flags: { mission: "test-system-m000001" }, } as unknown as KernelCommandInput; const context = { io: createDefaultIO().io, workspaceRoot: tmpWorkspace, logger: { info: () => {}, warn: () => {} }, } as unknown as KernelRuntimeContext; const result = await runMissionMaterialize(input, context); expect(result.summary).toContain("materialized"); });