import type { InstalledPlugin } from '../../types.js'; import { type DeclBranch as DeclBranchGeneric, type PluginDeclLeaf, type CommandManifestIssue } from '../command-manifests/schema.js'; /** A stable, doctor-renderable validation issue. Never thrown — accumulated * and surfaced through `pkg plugin show` / `sys doctor`. */ export interface CommandDiscoveryIssue extends CommandManifestIssue { /** The offending plugin's name. */ plugin: string; } export type { DeclRootEntry } from '../command-manifests/schema.js'; export type { CommandIssueCode } from '../command-manifests/schema.js'; export type DeclLeaf = PluginDeclLeaf; export type DeclBranch = DeclBranchGeneric; export type DeclNode = DeclBranchGeneric | PluginDeclLeaf; /** One accepted top-level contribution: a validated branch node plus the * plugin identity and canonical executable the adapter needs at run time. */ export interface ValidatedContribution { plugin: InstalledPlugin; /** Absolute, realpath-resolved executable path. Absent only for a manifest * that declares no leaf at all — a passthrough-only contribution execs the * external binary it names and never speaks the leaf protocol. */ executable?: string; /** The validated top-level branch node (always kind 'branch'). */ node: DeclBranchGeneric; } /** Per-plugin validation result — the Phase 2 lifecycle entry point. Reports * accepted contributions and every issue without executing the binary. */ export interface PluginCommandValidation { plugin: InstalledPlugin; /** Absolute path to the plugin's commands.json (whether or not it loaded). */ manifestPath: string; /** Absolute, resolved executable path when it passed path/exec-bit safety. */ executable?: string; contributions: ValidatedContribution[]; issues: CommandDiscoveryIssue[]; } /** The invocation-local registry snapshot the tree composer consumes. */ export interface CommandRegistrySnapshot { /** Accepted top-level contributions, deterministically ordered by name. */ contributions: ValidatedContribution[]; /** Every discovery issue across all effective command plugins. */ issues: CommandDiscoveryIssue[]; } /** The effective, deduped set of enabled plugins that declare a command * manifest, in scope-precedence order. Enumerated with existing machinery * only: `projectScopeRoots()` (profile-widened, nearest-first) via * `listInstalledPluginsInRoot('project', root)`, then user scope. Dedup is by * plugin NAME across ALL copies (highest precedence wins) BEFORE the enabled * filter — so a disabled higher-precedence copy suppresses lower-precedence * copies of the same name. */ export declare function effectiveCommandPlugins(startDir?: string, profileId?: string | null): InstalledPlugin[]; /** Get raw plugin candidates before the cross-plugin collision pass. * Each plugin validation includes its contributions and per-plugin issues; * call resolveCommandRegistry (or a later unified collision handler) to * produce the final snapshot with cross-plugin collision detection. */ export declare function discoverPluginCommandCandidates(startDir?: string, profileId?: string | null): PluginCommandValidation[]; /** Validate every effective command plugin and compose an invocation-local * registry snapshot. `reservedNames` are the core top-level subtree names — * a contribution claiming one is silently skipped from the tree and recorded * as a `command_collision` issue (core always wins). A plugin-vs-plugin * top-level name collision drops all claimants with an issue. Accepted * contributions are sorted by name for deterministic help/order. */ export declare function discoverCommandContributions(reservedNames: ReadonlySet, startDir?: string, profileId?: string | null): CommandRegistrySnapshot; /** Validate every effective command plugin, including the cross-plugin * top-level name collision pass: a name claimed by more than one plugin is * dropped from EVERY claimant's contributions and a `command_collision` * issue is recorded on EACH claimant's validation, so per-plugin surfaces * (`sys doctor`, `pkg plugin show`) see it too. This is the entry point for * any surface that reports on mounted commands — the per-plugin * `validatePluginCommands` cannot see other plugins' claims. */ export declare function validateEffectiveCommandPlugins(reservedNames: ReadonlySet, startDir?: string, profileId?: string | null): PluginCommandValidation[]; /** Validate one plugin's command manifest without executing its binary. * `reservedNames` are the core top-level names used for the core-collision * check; pass an empty set to skip it. Never throws. */ export declare function validatePluginCommands(plugin: InstalledPlugin, reservedNames?: ReadonlySet): PluginCommandValidation;