/*
RFC-0354 §7.4: sternsystem.pin — write or update system.pin.json for a Sternsystem.
- Do not introduce app-specific runtime composition or deployment behavior into this reusable package source file.
- RFC-0354: initial pin command handler.
- RFC-0381: use shared pin-helpers for highestRfcId and snapshotCapabilities; case-insensitive RFC regex.
- RFC-1249: wire werkstatt.commands.validate into packages.check + retire CMD-OUTPUT debt
- RFC-1254: drop unused io-migration leftovers
- REVIEW-CODE-2026-10-16-09 N11: thread the caller's WorkspaceIO through config/ecosystem/rfc-head/capability reads and the pin + config writes — no ambient-io on the register-invoked path.
*/
import path from "node:path";
import { atomicWriteFile } from "../werkstatt/atomic.ts";
import type {
KernelCommandInput,
KernelCommandResult,
KernelRuntimeContext,
} from "@warpgogol/werkstatt-engine/kernel";
import { systemPinSchema, type SystemPin } from "@warpgogol/werkstatt-engine/schemas";
import { resolveCurrentEcosystem, resolvePlatformSemanticHash } from "../handoff/bundle-io.ts";
import { allMigratorIds } from "../migrators/registry.ts";
import {
readSystemConfigSmart,
writeSystemConfigSmart,
resolveCacheClonePath,
} from "./registry-io.ts";
import { highestRfcId, snapshotCapabilities } from "./pin-helpers.ts";
export interface SternsystemPinData {
systemId: string;
platform: string;
pinPath: string;
}
function flagString(input: KernelCommandInput, key: string): string | undefined {
const v = input.flags[key];
return typeof v === "string" ? v : undefined;
}
function compareSemver(a: string, b: string): number {
const [aMaj, aMin, aPat] = a.split(".").map(Number);
const [bMaj, bMin, bPat] = b.split(".").map(Number);
if (aMaj !== bMaj) return aMaj - bMaj;
if (aMin !== bMin) return aMin - bMin;
return aPat - bPat;
}
export async function runSternsystemPin(
input: KernelCommandInput,
context: KernelRuntimeContext,
): Promise> {
const { workspaceRoot, logger } = context;
const id = flagString(input, "id");
if (!id) throw new Error("[sternsystem.pin] requires --id ");
const config = await readSystemConfigSmart(workspaceRoot, id, context.io);
const cacheDir = resolveCacheClonePath(workspaceRoot, id);
if (!(await context.io.exists(cacheDir))) {
throw new Error(
`[sternsystem.pin] cache clone for '${id}' is absent — run sternsystem.register first`,
);
}
const requestedPlatform = flagString(input, "platform");
// Check for downgrade if a pin already exists
const pinPath = path.join(cacheDir, "system.pin.json");
if ((await context.io.exists(pinPath)) && requestedPlatform) {
try {
const raw = await context.io.readFile(pinPath);
const existing = systemPinSchema.parse(JSON.parse(raw)) as SystemPin;
if (compareSemver(requestedPlatform, existing.platform.version) < 0) {
throw new Error(
`[sternsystem.pin] requested platform ${requestedPlatform} is older than current pin ${existing.platform.version} — a site is never downgraded`,
);
}
} catch (err) {
if ((err as Error).message.includes("never downgraded")) throw err;
}
}
const platform =
requestedPlatform ?? (await resolveCurrentEcosystem(workspaceRoot, context.io)).version;
const { commit } = await resolveCurrentEcosystem(workspaceRoot, context.io);
const rfcHead = await highestRfcId(workspaceRoot, context.io);
const platformSemanticHash = await resolvePlatformSemanticHash(workspaceRoot, context.io);
const capabilities = await snapshotCapabilities(workspaceRoot, context.io);
const pin: SystemPin = {
schemaVersion: "1.0.0",
systemId: id,
cosmicStar: config.cosmicStar,
pinnedAt: new Date().toISOString(),
platform: {
version: platform,
commit: commit === "unknown" ? "0000000" : commit,
rfcHead,
platformSemanticHash,
},
migratorCursor: allMigratorIds(),
capabilities,
};
systemPinSchema.parse(pin);
await atomicWriteFile(pinPath, JSON.stringify(pin, null, 2) + "\n", context.io);
// Update config: always activate on pin, update pinnedPlatform if changed
let configChanged = false;
if (config.pinnedPlatform !== platform) {
config.pinnedPlatform = platform;
configChanged = true;
}
if (config.status === "registered") {
config.status = "active";
configChanged = true;
}
if (configChanged) {
await writeSystemConfigSmart(workspaceRoot, id, config, context.io);
}
logger.success(`[sternsystem.pin] pinned '${id}' to platform ${platform} (${rfcHead})`);
return {
data: { systemId: id, platform, pinPath },
exitCode: 0,
summary: `[sternsystem.pin] ${id} pinned to platform ${platform}`,
};
}