export type Host = 'claude' | 'codex' | 'factory'; export interface HostPaths { skillRoot: string; localSkillRoot: string; binDir: string; browseDir: string; designDir: string; } export const HOST_PATHS: Record = { claude: { skillRoot: '~/.claude/skills/gstack', localSkillRoot: '.claude/skills/gstack', binDir: '~/.claude/skills/gstack/bin', browseDir: '~/.claude/skills/gstack/browse/dist', designDir: '~/.claude/skills/gstack/design/dist', }, codex: { skillRoot: '$GSTACK_ROOT', localSkillRoot: '.agents/skills/gstack', binDir: '$GSTACK_BIN', browseDir: '$GSTACK_BROWSE', designDir: '$GSTACK_DESIGN', }, factory: { skillRoot: '$GSTACK_ROOT', localSkillRoot: '.factory/skills/gstack', binDir: '$GSTACK_BIN', browseDir: '$GSTACK_BROWSE', designDir: '$GSTACK_DESIGN', }, }; export interface TemplateContext { skillName: string; tmplPath: string; benefitsFrom?: string[]; host: Host; paths: HostPaths; preambleTier?: number; // 1-4, controls which preamble sections are included } /** Resolver function signature. args is populated for parameterized placeholders like {{INVOKE_SKILL:name}}. */ export type ResolverFn = (ctx: TemplateContext, args?: string[]) => string;