/** * config-and-capabilities — the pre-dispatch composition seam for the * capability-configuration release (ADR-0023 / §5.3, Phase 4). * * Two host responsibilities the composition root owns once per run, extracted * from the pre-action-hook to keep that hook within its complexity budget: * * 1. {@link composeAndValidateToolConfig} — gather every registered tool's * contributed `ToolConfigDeclaration`, compose them into ONE strict * whole-document schema, validate the parsed `opensip-cli.config.yml` * STRICT before any command runs (a typo in ANY tool namespace throws a * single `ConfigurationError` → `CONFIGURATION_ERROR` exit through the * existing error boundary), then resolve precedence (flag > env > file > * defaults) and return the resolved config to attach to the scope. * * 2. {@link wireCapabilityRegistry} — construct the per-run capability * registry, register every admitted manifest's declared domains (each * seeded with a DEFERRED placeholder registrar), then replace each * placeholder with the owning tool's REAL registrar * (`tool.capabilityRegistrars`). The host routes by domain; the tool owns * the registrar. * * This module is the ONE place the CLI host imports `@opensip-cli/config` for * runtime composition (schema merge, validation, precedence). Tools may import * `@opensip-cli/config` for {@link ToolConfigDeclaration} when declaring their * config namespace (see `docs/public/10-concepts/03-modular-monolith.md`); at * run time they read the validated namespace off `scope.toolConfig`. */ import { type BootstrapDiagnosticsCollector, type CapabilityRegistry, type ResolvedToolConfig, type ToolPluginManifest, type ToolProvenance, type ToolRegistry } from '@opensip-cli/core'; /** * Compose + strict-validate the config document, then resolve precedence. * * Reads the project config file (when one exists), composes the registered * tools' schemas, validates STRICT (rejecting a typo inside any tool * namespace), and resolves precedence. Returns `undefined` when there is no * config document to validate (a project-agnostic command or a config-less * project) — the scope then carries no `toolConfig` and tools fall back to * their in-tool defaults. * * @param tools The per-run tool registry (supplies the contributed schemas). * @param configPath The resolved path to `opensip-cli.config.yml`, or * `undefined` when the run has no config document. * @param env The environment map for env-binding precedence (typically * `process.env`). * @returns The resolved tool config to attach to the scope, or `undefined`. * @throws {ConfigurationError} (`CONFIGURATION_ERROR`) when the document fails * strict validation in ANY tool namespace. */ export declare function composeAndValidateToolConfig(args: { readonly tools: ToolRegistry; readonly manifests?: readonly ToolPluginManifest[]; readonly provenance?: readonly ToolProvenance[]; readonly configPath: string | undefined; readonly rawDocumentOverride?: unknown; readonly env: Readonly>; readonly bootstrapDiagnostics?: BootstrapDiagnosticsCollector; }): { readonly config: ResolvedToolConfig | undefined; readonly document: unknown; }; /** * Construct + populate the per-run capability registry (§5.3, Phase 4). * * Step 1 registers every admitted manifest's declared capability domains (each * with a deferred placeholder registrar) — pure MANIFEST data: the manifest is * serializable, the placeholder is a host-owned deferred stub (it throws if a * domain is driven before a real registrar is installed); NO external runtime * code runs here. Step 2 replaces each placeholder with the owning tool's REAL * registrar from `tool.capabilityRegistrars`. * * ADR-0054 M4-F: step 2 is gated on {@link shouldRunHookInHost}. For an EXTERNAL * tool in the HOST process the real registrar is NOT installed host-side (reading * `tool.capabilityRegistrars` + invoking the registrar runs untrusted runtime * code — the load-time hole the ADR rejects); the external domain keeps its * deferred placeholder in the host registry. The real registrar is installed * worker-side: the dispatch worker re-runs this SAME wiring with the host-skip * INACTIVE, so the dispatched external tool's registrar IS installed there (the * isolation boundary). Bundled tools install in-host exactly as before. A * registrar whose domain id was not declared in any manifest is skipped * (hasDomain false) — the host never invents a domain a tool didn't declare. * * @param tools The per-run tool registry (supplies each tool's real registrars). * @param manifests The admitted manifests (supply the declared domains). * @param provenance The per-run provenance (drives the M4-F host/external gate). * @returns The populated registry, ready to attach to `scope.capabilities`. */ export declare function wireCapabilityRegistry(args: { readonly tools: ToolRegistry; readonly manifests: readonly ToolPluginManifest[]; readonly registry: CapabilityRegistry; readonly provenance?: readonly ToolProvenance[]; }): CapabilityRegistry; //# sourceMappingURL=config-and-capabilities.d.ts.map