@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.
73 lines • 3.54 kB
JavaScript
import { getKnownAgentIds } from "../agents/registry.js";
import { PROFILES } from "../detect/agents.js";
import { detectStack } from "../detect/project-stack.js";
import { extractSharedFacts } from "./shared/index.js";
import { extractAgentFacts } from "./agent/index.js";
function span(profile, name, fn) {
return profile ? profile.span(name, fn) : fn();
}
/** Stack sentinel for profiles without stack facts; throws because invalid checks must fail loudly. */
function unavailableStack() {
const message = "facts.stack is unavailable in dashboard-summary audit profile; mark the check requiresStack or run a full audit profile";
return new Proxy({}, {
/** Throws for all stack property reads except JSON serialization because the profile excludes stack facts. */
get(_target, prop) {
if (prop === "toJSON") {
return () => ({ unavailable: true });
}
throw new Error(`${message} (accessed ${String(prop)})`);
},
});
}
/**
* Gather stack, shared, and per-agent facts into the single scan input object.
*
* @param fs - filesystem adapter for the target project
* @param options - extraction scope, config state, stack profile, and optional profiler
* @returns project facts consumed by audit, setup, and quality prompt generation
*/
export function extractProjectFacts(fs, options) {
const managedAgentIds = options.agentFilter !== null
? [options.agentFilter]
: (options.managedAgentIds ?? getKnownAgentIds());
const agents = managedAgentIds.map((id) => PROFILES[id]);
/** Detected technology stack (language, framework, etc.) */
const stack = options.includeStack === false
? unavailableStack()
: span(options.profile, "detectStack", () => detectStack(fs));
/** Shared facts covering docs, CI, and other project-wide resources */
const shared = span(options.profile, "shared facts", () => extractSharedFacts(fs, options.configState));
/** Per-agent facts including instruction, settings, skills, and hooks */
const agentFacts = agents.map((agent) => span(options.profile, "agent facts", () => {
/** Extracted facts for this specific agent */
const facts = extractAgentFacts(fs, agent);
// Cross-reference: populate warranted local context from footgun dir mentions
/** Directories warranting local context files */
const warranted = [];
/** Warranted directories that lack a local context file */
const missing = [];
// Repeated footgun references are treated as a signal that the directory is
// risky enough to deserve local instructions. A single mention is often noise.
for (const [dir, count] of shared.footguns.dirMentions) {
if (count >= 2) {
warranted.push(dir);
// Missing local context is only interesting for directories repeatedly named in footguns.
/** Whether a local instruction file already exists for this directory */
const hasLocal = facts.localContext.files.some((f) => f.startsWith(dir));
if (hasLocal === false) {
missing.push(dir);
}
}
}
facts.localContext.warranted = warranted;
facts.localContext.missing = missing;
return facts;
}));
return {
root: options.projectPath ?? ".",
stack,
agents: agentFacts,
shared,
};
}
//# sourceMappingURL=orchestrator.js.map