@blundergoat/goat-flow
Version:
AI coding agent harness and local dashboard for Claude Code, OpenAI Codex, Google Antigravity, and GitHub Copilot - setup audits, guardrails, structured skills, deny hooks, and persistent learning loops.
64 lines • 3.05 kB
JavaScript
/**
* Canonical cross-module constants for skills and version-aligned aliases.
* Keep definitions here so detection, prompts, and audit checks stay in sync.
*/
import { existsSync, readFileSync, readdirSync } from "node:fs";
import { join } from "node:path";
import { getPackageVersion } from "./paths.js";
import { getTemplatePath } from "./paths.js";
/** Read the on-disk skills manifest used by shared constants. */
function readSkillsManifest() {
const path = getTemplatePath("workflow/manifest.json");
return JSON.parse(readFileSync(path, "utf-8"));
}
/** List skill template directories that contain a `SKILL.md` file with deterministic ordering. */
function readObservedSkillDirs() {
const root = getTemplatePath("workflow/skills");
return readdirSync(root, { withFileTypes: true })
.filter((entry) => entry.isDirectory() && existsSync(join(root, entry.name, "SKILL.md")))
.map((entry) => entry.name)
.sort();
}
/** Read the manifest canonical skill list; throws when manifest/schema or template dirs drift. */
function readCanonicalSkillNames() {
const manifest = readSkillsManifest();
const canonical = manifest.skills?.canonical;
if (!Array.isArray(canonical) ||
canonical.some((name) => typeof name !== "string")) {
throw new Error("workflow/manifest.json has an invalid skills.canonical list");
}
const observed = readObservedSkillDirs();
const missingDirs = canonical.filter((name) => !observed.includes(name));
const extraDirs = observed.filter((name) => !canonical.includes(name));
if (missingDirs.length > 0 || extraDirs.length > 0) {
const findings = [];
if (missingDirs.length > 0) {
findings.push(`missing workflow/skills dirs: ${missingDirs.join(", ")}`);
}
if (extraDirs.length > 0) {
findings.push(`unlisted workflow/skills dirs: ${extraDirs.join(", ")}`);
}
throw new Error(`workflow/manifest.json skills.canonical drifted from workflow/skills/: ${findings.join("; ")}`);
}
return canonical;
}
/** Read the manifest stale skill-name list; throws when the manifest schema stops being an array of strings. */
function readStaleSkillNames() {
const manifest = readSkillsManifest();
const staleNames = manifest.skills?.stale_names;
if (!Array.isArray(staleNames) ||
staleNames.some((name) => typeof name !== "string")) {
throw new Error("workflow/manifest.json has an invalid skills.stale_names list");
}
return staleNames;
}
/** Canonical list of all GOAT Flow skill names. */
export const SKILL_NAMES = readCanonicalSkillNames();
/** Deprecated skill names retained for migration and drift detection. */
export const STALE_SKILL_NAMES = readStaleSkillNames();
/**
* Current audit version - derived from package.json so it stays in sync automatically.
* Skills embed this as `goat-flow-skill-version: X` in their YAML frontmatter.
*/
export const AUDIT_VERSION = getPackageVersion();
//# sourceMappingURL=constants.js.map