/** * Skills manifest — the single, codebase-controlled source of truth for which * skills the skills-manager manages and where each one comes from. * * The manifest is a checked-in JSON file (`skills-manifest.json`, copied into * `dist/` at build time) shipped *with the runtime*, so bumping the runtime can * change the managed skill set in one reviewable diff — no env vars, no * scattered constants. * * Each managed skill resolves to a {@link ResolvedSkillSource}: a concrete * `{ repo, branch, path, rawBaseUrl }` computed from the manifest `defaults`, * the per-entry overrides, optional plugin-config overrides, and finally the * env testing overrides (which win — see {@link resolveSkillSource}). The * coordinator threads these through the three I/O seams: the version check * (raw URL), the clone (repo + branch), and the install (source path). */ /** A single entry in the manifest `skills` array. `name` is required; the rest * fall back to manifest `defaults` (repo/branch) or the skill name (path). */ export interface SkillManifestEntry { name: string; repo?: string; branch?: string; /** * Pin this skill to an immutable git commit SHA, or `"latest"` (default) to * track the branch tip. A pinned commit makes a tested skill version * reproducible — branch content can change under you, a commit cannot. */ commit?: string; /** Subdirectory of the repo holding this skill. Defaults to `name`. */ path?: string; /** * Auto-update major-version ceiling. The tick auto-applies updates up to * **and including** this major and gates anything above it. Unset gates * **all** major bumps (the safe default — majors then require a manual * `senpi skills update`). Bumping this in the checked-in manifest is the * reviewed, fleet-wide lever for adopting a new skill major. patch/minor * within an already-installed major always auto-apply regardless. */ maxMajor?: number; /** * Relative subpaths of the installed skill dir that hold **user data** and * must survive reinstalls (e.g. `strategies` for `senpi-strategy-ops`, * where deployed strategy packages live). Threaded to the writer, which * carries them over from the previous install on every update. * * Entries are exact subpaths, not globs: `strategies` does not cover * `scripts/strategies`. Both are declared for the strategy-lifecycle trio * because a legacy deploy landed packages CWD-relative, and the agent shell * sits in the skill dir or its `scripts/` dir about equally often — of the * 171 instances audited after the 2026-07-30 wipe, 109 were under * `senpi-strategy-ops/strategies/` and 31 under * `senpi-strategy-ops/scripts/strategies/`. */ preserve?: string[]; } /** Parsed + validated manifest shape. */ export interface SkillsManifest { schemaVersion: number; defaults: { repo: string; branch: string; maxMajor?: number; }; skills: SkillManifestEntry[]; } /** A fully-resolved per-skill source — everything the I/O layer needs. */ export interface ResolvedSkillSource { name: string; repo: string; branch: string; /** * Pinned commit SHA, or `null` to track the branch tip (`commit: "latest"` * / unset). When set, the clone checks out this exact commit and the version * check reads SKILL.md at this commit. */ commit: string | null; /** * The git ref the I/O layer actually uses: the pinned `commit` when set, * otherwise the `branch`. Used for both the raw-content URL and the checkout. */ ref: string; /** Subdirectory inside the cloned repo to copy from. */ path: string; /** Raw-content base URL (`///`) for SKILL.md fetch. */ rawBaseUrl: string; /** * Resolved auto-update major ceiling (policy, not source). `null` = gate all * major bumps; otherwise the tick auto-applies majors up to and including * this number. See {@link SkillManifestEntry.maxMajor}. */ maxMajor: number | null; /** * User-data subpaths to preserve across reinstalls. See * {@link SkillManifestEntry.preserve}. Empty when the manifest declares none. */ preserve: readonly string[]; } /** Options for {@link resolveSkillSource}. */ export interface ResolveSourceOptions { /** Per-skill overrides (e.g. from `skillsManager.overrides` in plugin config). */ overrides?: Record; /** Process env — injectable for tests; defaults to `process.env`. */ env?: NodeJS.ProcessEnv; } /** * Hardcoded fallback used only when the checked-in JSON cannot be read or * parsed (corrupt file, missing from dist). Keeps the plugin from crashing at * import time; logged loudly by {@link loadManifest} so the misconfig is * visible. Kept in sync with `skills-manifest.json`. */ export declare const FALLBACK_MANIFEST: SkillsManifest; /** * Load + validate the manifest from disk, cached after first read. Resolves * the JSON path relative to this module so it works both from `src/` (vitest) * and `dist/` (the build copies the JSON next to the compiled module). * * On any read/parse/validation failure, logs a warning to `console.warn` and * returns {@link FALLBACK_MANIFEST} — the manager must not fail to start just * because the manifest file is missing from a packaging step. */ export declare function loadManifest(): SkillsManifest; /** Reset the manifest cache. Test-only — lets a test point at a fresh state. */ export declare function resetManifestCacheForTests(): void; /** The list of managed skill names declared by the manifest, in manifest order. */ export declare function getManifestSkillNames(): string[]; /** * Derive the raw-content base URL for a repo + branch. * * Honors `SENPI_SKILLS_RAW_REPO_URL` (host override, no trailing slash, no * branch segment) when set; otherwise maps a GitHub repo URL to its * `raw.githubusercontent.com//` form. Falls back to the repo URL * (minus `.git`) for non-GitHub hosts — best effort, so a misconfigured repo * surfaces as a fetch error rather than a silent wrong base. */ export declare function deriveRawBaseUrl(repo: string, ref: string, env?: NodeJS.ProcessEnv): string; /** * Per-skill branch env var name for a skill, e.g. * `senpi-strategy-ops` → `SENPI_SKILLS_BRANCH_SENPI_STRATEGY_OPS`. Non-alnum * chars in the skill name collapse to `_` so the variable is shell-friendly. */ export declare function perSkillBranchEnvVar(name: string): string; /** * Per-skill commit-pin env var, e.g. * `senpi-strategy-ops` → `SENPI_SKILLS_COMMIT_SENPI_STRATEGY_OPS`. Set to a SHA * to pin, or `latest` to force branch-tracking for that skill. */ export declare function perSkillCommitEnvVar(name: string): string; /** * Resolve a skill name to its concrete source. * * **Branch precedence** (highest wins) — designed so per-skill intent always * beats the blunt "force everything" knob, enabling controlled per-skill * testing: * 1. `SENPI_SKILLS_BRANCH_` — per-skill env override (ad-hoc test of one skill) * 2. `overrides[name].branch` — per-skill config override * 3. `SENPI_SKILLS_BRANCH` — global env (force *all* skills to one branch) * 4. manifest entry `branch` — per-skill, checked-in (controlled testing in the file) * 5. manifest `defaults.branch` — fallback * * **Repo precedence**: `overrides[name].repo` > `SENPI_SKILLS_REPO_URL` (global) * > manifest entry `repo` > `defaults.repo`. **Path**: `overrides[name].path` > * manifest entry `path` > the skill name. * * Examples: * - Test the whole set on a branch: `SENPI_SKILLS_BRANCH=strategy-v2` * - Test one skill on a branch: `SENPI_SKILLS_BRANCH_SENPI_STRATEGY_OPS=strategy-v2` * (or `overrides: { "senpi-strategy-ops": { "branch": "strategy-v2" } }`) * - Pin a skill in the repo: set its `branch` in `skills-manifest.json` * * Skills not named in the manifest (e.g. an operator-supplied override list) * resolve against `defaults` so they remain installable. */ export declare function resolveSkillSource(name: string, opts?: ResolveSourceOptions): ResolvedSkillSource; //# sourceMappingURL=manifest.d.ts.map