/** * Plugin distribution layout helpers. * * Shared primitives for locating where `vat build --only claude` places * tree-copied plugin skills in the output tree, and where it reads them from. * * Consumed by `vat build`, `vat verify`, and consistency-check so the path * conventions can never drift between those commands. */ import type { ProjectConfig } from '@vibe-agent-toolkit/resources'; /** * Absolute path to the built plugin output directory. * * Shape: `/dist/.claude/plugins/marketplaces//plugins//` * * Extracted verbatim from build.ts lines 577–580 so that build can later adopt * this helper with zero behavior change. */ export declare function getPluginOutputDir(configDir: string, marketplaceName: string, pluginName: string): string; /** * Absolute path to the plugin source directory. * * Resolves to `/` when the plugin declares a custom * source, otherwise `/plugins/`. * * Extracted verbatim from build.ts lines 581–584. */ export declare function getPluginSourceDir(configDir: string, plugin: { name: string; source?: string | undefined; }): string; /** * Every plugin-local SKILL DIRECTORY under `/skills/`, as a * forward-slash path relative to that `skills/` dir (`my-skill`, * `group/nested-skill`). * * Three properties, each of which a previous shape got wrong and shipped a bug: * * 1. **A skill is a directory holding a `SKILL.md`** — not "any immediate * subdirectory of `skills/`". A `shared/` helper dir, a `_templates/` dir, or * the mere PARENT of a nested skill is not a skill; it has no packager, so the * plugin build's verbatim tree-copy is its only route into the bundle and it * must not appear here. * 2. **Recursive.** Claude Code discovers `skills///SKILL.md`, so * VAT must too. A non-recursive listing left every nested plugin-local skill * to the verbatim tree-copy — shipping its eval suite (answer key included), * scratch files, and un-rewritten links, and producing it a SECOND time when * the same skill was also selected from the pool. * 3. **Same file visibility as the tree-copy** (`crawlDirectorySync` with * `respectGitignore`, i.e. tracked files only inside a git repo). The two * producers of a plugin's `skills/` tree must agree on which files exist at * all; a `readdirSync` listing saw gitignored/untracked skill directories the * tree-copy would never have shipped, and packaged them into the published * marketplace bundle. * * A skill nested INSIDE another skill (`a/SKILL.md` and `a/b/SKILL.md`) yields * only the outermost (`a`): the inner dir is part of the outer skill's own tree, * and packaging both would have the inner packager write into a directory the * outer packager owns. * * Returns `[]` when the `skills/` directory does not exist (pool-only plugin). */ export declare function listPluginSourceSkillDirs(pluginSourceDir: string): string[]; /** * The skill directories under `/skills/` that exist ON DISK but are * INVISIBLE to {@link listPluginSourceSkillDirs} because git does not track them. * * Purely diagnostic. Git visibility is the correct filter — both producers of a * plugin's `skills/` tree honor it, and it is what stops a gitignored skill dir from * being published. But "correct" and "obvious" are different things: a skill the * author has just created and not yet `git add`ed is simply absent from the built * plugin, and a silent absence reads as a build that shipped everything. The caller * warns for these; a deliberately GITIGNORED dir is not in this list (see * {@link listUntrackedPluginSkillDirs}), because ignoring it IS the instruction. * * Returns `[]` outside a git repo, where every directory is visible anyway. */ export declare function listUntrackedPluginSkillDirs(pluginSourceDir: string): string[]; /** Location of a single skill shipped via source tree-copy. */ export interface DistributedSkillLocation { /** Name of the marketplace this skill ships through. */ marketplaceName: string; /** Name of the plugin that contains this skill. */ pluginName: string; /** * Forward-slash path of the skill's directory RELATIVE to the plugin's `skills/` * dir — `my-skill`, or `group/nested-skill` for a nested skill. A path, not a * bare name: the output layout mirrors the source layout, so a nested skill * ships at the same depth it was authored at. */ skillDirPath: string; /** Absolute SOURCE skill dir: `/skills/`. */ skillSourceDir: string; /** Absolute output path where `vat build` places the skill: `getPluginOutputDir(...)/skills/`. */ skillOutputDir: string; } /** * Every plugin-local skill across all marketplaces in the config, paired with the * output directory where `vat build` places it. * * "Tree-copied" in the name is historical: plugin-local skills are PACKAGED (see * `packagePluginLocalSkills` in the CLI's plugin build), not copied verbatim. The * locations are unchanged, which is what every consumer here actually needs. * * Pool-only plugins — those whose source `skills/` directory is absent on disk * — contribute nothing to the result. */ export declare function computeTreeCopiedSkillLocations(config: ProjectConfig, configDir: string): DistributedSkillLocation[]; /** FS-safe single path segment for a skill name (colon → `__`, invalid on Windows). */ export declare function skillNameToFsPath(name: string): string; /** * Find the tree-copied location whose SOURCE skill dir equals `skillSourceDir` * (compared via resolved absolute paths). Returns `undefined` for pool skills * or skills not declared in any plugin's `skills/` source dir. */ export declare function findDistributedSkillLocationBySource(config: ProjectConfig, configDir: string, skillSourceDir: string): DistributedSkillLocation | undefined; //# sourceMappingURL=plugin-distribution-layout.d.ts.map