/** * Recommended-packages flow for create-hq. * * After the hq-core scaffold is in place, read `core.yaml:recommended_packages` * and install each via `hq install ` (the hq-cli subcommand). The * `source` field carries the transport-appropriate identifier — npm name, git * URL + optional subpath + ref, or local path — so this client stays thin: * it doesn't parse transports; it just hands each source verbatim to * `hq install`. * * Honors three policies: * 1. Conditional predicates. Each entry may declare `conditional: `. * If the predicate exits non-zero the pack is SKIPPED (not failed). This * lets a pack opt out when the host lacks a prerequisite (e.g. gemini CLI). * 2. Install failure = warning (not fatal). Pack install is best-effort; * `/setup --resume` and `/update-hq` retry. Scaffolding proceeds even if * every pack fails. * 3. Hooks prompt. Passes `--allow-hooks` when `--full` is set (non- * interactive); omits it for interactive mode so hq-cli can prompt. */ export interface RecommendedPackage { source: string; description?: string; conditional?: string; } export interface InstallMode { /** skip all packs (from --minimal or user decline) */ skip: boolean; /** install all packs without prompting per-entry (from --full) */ all: boolean; } export interface InstallOutcome { source: string; status: "installed" | "skipped" | "failed"; reason?: string; } /** * Resolve the hq-core `core.yaml` that carries `recommended_packages`. * * hq-core@v14+ nests the file under `core/core.yaml`; pre-v14 templates kept * it at the HQ root (`core.yaml`). Prefer the nested location and fall back to * the legacy root so older tagged releases still resolve. Returns `null` when * neither exists — callers treat that as a scaffold-integrity problem * (surfaced loudly) rather than "this core simply has no recommended packs". * * This mirrors the same-layout probe `fetch-template.ts` already performs when * validating the extracted scaffold; keeping the two in sync is what prevents * the silent no-op where a current hq-core's packs were read from the wrong * path (`/core.yaml`) and the list came back empty. */ export declare function resolveCoreYamlPath(hqRoot: string): string | null; /** * Read `recommended_packages` from an hq-core-style core.yaml. Uses minimal * line-based parsing to avoid adding js-yaml as a dependency. * * Expected shape in core.yaml: * recommended_packages: * - source: '...' * description: '...' * conditional: '...' * - source: '...' * description: '...' */ export declare function readRecommendedPackages(hqRoot: string): RecommendedPackage[]; /** * Result of the pre-install probe for the recommended-packs phase. Pure and * side-effect free so the scaffold's decision (proceed / warn / stay quiet) * is unit-testable without a TTY or a real `hq install` subprocess. * * - `core-yaml-missing` — neither `core/core.yaml` nor the legacy root * `core.yaml` exists. The scaffold looks incomplete; surface loudly. * - `empty-warn` — core.yaml resolved but declared no recommended packs * while the operator asked for the full set (`--full`). Almost always a * path/parse mismatch (the original bug), so warn instead of a silent * success. * - `empty-quiet` — core.yaml resolved with no packs and no `--full`. A core * legitimately may ship none; nothing was promised, so stay quiet. * - `proceed` — packs found; install them. */ export type PacksPreflight = { kind: "core-yaml-missing"; coreYamlPath: null; } | { kind: "empty-warn"; coreYamlPath: string; } | { kind: "empty-quiet"; coreYamlPath: string; } | { kind: "proceed"; coreYamlPath: string; entries: RecommendedPackage[]; }; /** * Probe the scaffold for its recommended-packages list and decide how the * install phase should react. `full` is the operator's explicit "install * everything unattended" signal (`--full`), which upgrades an empty list from * an unremarkable no-op to a loud warning — the exact case the silent-no-op * bug missed. */ export declare function preflightRecommendedPacks(hqRoot: string, full: boolean): PacksPreflight; /** * Evaluate a `conditional` bash expression. Returns true when the predicate * exits 0 (pack applicable); false otherwise (pack should be skipped). * Never throws — a malformed predicate is treated as "skip". * * NOTE: This runs arbitrary bash from the fetched `core.yaml`. Call sites * MUST gate evaluation on user approval (interactive confirm, or explicit * `--full` / `--allow-hooks` trust escalation). See `installRecommendedPackage`. */ export declare function evaluateConditional(expr: string): boolean; /** * Discover which content packs are already installed under the v12 HQ * layout. Walks `core/packages//package.yaml` and reconstructs the * npm-style source string `${publisher}/${name}` (e.g. * `@indigoai-us/hq-pack-design-quality`) so it can be matched against * the `source:` entries in `recommended_packages:` config. * * Why filesystem-based: hq-cli stopped writing `modules/modules.yaml` * for pack installs under v12 (filesystem is the source of truth — see * the layout-fix PR). The pack's on-disk `package.yaml` carries the * canonical `name` + `publisher` we need to recover the source string. * * Edge cases: * - Missing publisher → adds bare `name` (legacy local-path packs). * - Missing package.yaml → directory skipped (half-installed / aborted). * - Non-directory entries (e.g. the template's `core/packages/README.md`) * are skipped. * - Non-npm sources (git ref, git URL, local path) won't match exactly, * so those packs gracefully re-prompt rather than silently clobber. * The common npm case (the 4 indigoai-us recommended packs) is fully * covered. * * Legacy `modules/modules.yaml` is intentionally NOT consulted — stale * entries from pre-v12 installs would leak into the dedupe set and * filter out packs that should be re-offered. */ export declare function readInstalledPackSources(hqRoot: string): Set; /** * Install a single recommended package via `hq install `. Runs the * hq-cli as a subprocess so we don't duplicate transport logic here. Returns * outcome as a discriminated union for the summary table. */ export declare function installRecommendedPackage(hqRoot: string, entry: RecommendedPackage, opts: { allowHooks: boolean; }): InstallOutcome; /** * Batch-install all recommended packages. `mode.skip` short-circuits (returns * empty array). `mode.all` installs every applicable pack; otherwise the * caller is expected to have already surfaced per-pack prompts and filtered * the list before calling. */ export declare function installRecommendedPackages(hqRoot: string, entries: RecommendedPackage[], opts: { allowHooks: boolean; }): InstallOutcome[]; /** * Summarize a batch install for the end-of-scaffold report. */ export declare function summarizeOutcomes(outcomes: InstallOutcome[]): { installed: number; skipped: number; failed: number; }; //# sourceMappingURL=recommended-packages.d.ts.map