import { test, expect } from "vitest";
import { buildActualState } from "../../runtime/reconciler.ts";
import type { CommandDeclaration } from "@warpgogol/werkstatt-shared/kernel";
import type { KernelCommandResult } from "@warpgogol/werkstatt-shared/kernel";
import type { ModuleExport } from "@warpgogol/werkstatt-shared/kernel";
/*
Verify buildActualState duplicate command detection:
same command name across modules throws COMPOSITION-02. Prevents pipeline crashes when two modules
accidentally register the same command (RFC-0816).
- Not a contract source of truth — the module under test owns the authoritative behavior; fixtures are minimal scaffolding only.
- Fixtures stay inline and minimal so each case states its own setup.
- RFC-0816: initial regression test for duplicate command registration.
- RFC-1038: migrated from registerCommand to populateFromModule.
- RFC-1038: migrated from KernelRegistry.populateFromModule to buildActualState.
*/
// @ai-invariant fixtures must not couple to internals beyond the public surface under test
const noopExecute = async (): Promise> => ({
exitCode: 0,
summary: "noop",
});
function makeCmd(name: string): CommandDeclaration {
return {
name,
modulePath: "test",
description: `Test command ${name}`,
scope: "workspace",
flags: {},
execute: noopExecute as CommandDeclaration["execute"],
};
}
function makeModule(name: string, commands: CommandDeclaration[]): ModuleExport {
return {
name,
version: "1.0.0",
declarations: [],
commands,
pipelines: [],
};
}
test("duplicate command name across modules throws", () => {
const cmdA = makeCmd("test.ping");
const cmdB = makeCmd("test.ping");
cmdB.execute = (async () => ({
exitCode: 1,
summary: "different",
})) as CommandDeclaration["execute"];
expect(() =>
buildActualState([makeModule("module-a", [cmdA]), makeModule("module-b", [cmdB])]),
).toThrow(/COMPOSITION-02.*test\.ping/);
});
test("different command names do not conflict", () => {
const actual = buildActualState([
makeModule("module-a", [makeCmd("test.ping")]),
makeModule("module-b", [makeCmd("test.pong")]),
]);
expect([...actual.commands.keys()].sort()).toEqual(["test.ping", "test.pong"]);
});
test("same command with different execute in same module is rejected", () => {
const cmdA = makeCmd("test.ping");
const cmdB = makeCmd("test.ping");
cmdB.execute = (async () => ({
exitCode: 1,
summary: "different",
})) as CommandDeclaration["execute"];
expect(() => buildActualState([makeModule("module-a", [cmdA, cmdB])])).toThrow(
/COMPOSITION-02.*test\.ping/,
);
});
test("idempotent re-registration with same execute is a no-op (RFC-0816)", () => {
const cmd = makeCmd("test.ping");
expect(() =>
buildActualState([makeModule("module-a", [cmd, makeCmd("test.ping")])]),
).not.toThrow();
});