/** * Configuration Module — single source of truth for config loading, * legacy-key normalization, defaults merge, and explicit on-disk migration. * * Source of truth for both the SDK and (via generator) the CJS side. * Manifests are read from sdk/shared/*.manifest.json. * * Public API: * loadConfig(cwd, options?) → MergedConfig — pure read, never writes disk * normalizeLegacyKeys(parsed) → { parsed, normalizations[] } — pure transform * mergeDefaults(parsed) → MergedConfig — fills in defaults * migrateOnDisk(cwd) → MigrationReport — explicit, opt-in disk writeback */ export declare const CONFIG_DEFAULTS: Record; export declare const VALID_CONFIG_KEYS: ReadonlySet; export declare const RUNTIME_STATE_KEYS: ReadonlySet; export interface DynamicKeyPattern { readonly topLevel: string; readonly source: string; readonly description: string; readonly test: (key: string) => boolean; } export declare const DYNAMIC_KEY_PATTERNS: readonly DynamicKeyPattern[]; /** Broad merged config type — consumers narrow as needed. */ export type MergedConfig = Record; export interface Normalization { from: string; to: string; value: unknown; requiresFilesystem?: true; } export interface NormalizationResult { parsed: MergedConfig; normalizations: Normalization[]; } export interface MigrationReport { migrated: boolean; normalizations: Normalization[]; wrote: string | null; } export interface LoadConfigOptions { /** Optional workstream name — routes to .planning/workstreams//config.json */ workstream?: string; /** Optional callback to observe normalizations applied during load */ onNormalizations?: (normalizations: Normalization[]) => void; } /** * Pure transform: migrate legacy top-level config keys to their canonical nested locations. * Returns the normalized parsed object + a list of normalizations applied. * Idempotent: calling twice returns the same result with empty normalizations second time. * * Normalizations applied (in order): * 1. top-level branching_strategy → git.branching_strategy (canonical wins if both present) * 2. top-level sub_repos → planning.sub_repos (canonical wins if both present) * 3. multiRepo: true → planning.sub_repos marker (requiresFilesystem: true) * 4. top-level depth → granularity (top-level) with mapping quick→coarse/standard→standard/comprehensive→fine */ export declare function normalizeLegacyKeys(parsed: Record): NormalizationResult; /** * Fill in CONFIG_DEFAULTS where the parsed object lacks values. * Deep-merges per-section (git, workflow, hooks, agent_skills, planning, ship). * Boolean false and explicit null are preserved — not overridden by truthy defaults. */ export declare function mergeDefaults(parsed: Record): MergedConfig; /** * Load project config from .planning/config.json (workstream-aware). * Pure read — never writes disk. * * Pipeline: parse JSON → normalizeLegacyKeys → mergeDefaults → return. * * Missing file → returns CONFIG_DEFAULTS verbatim. * Empty file → returns CONFIG_DEFAULTS verbatim. * Malformed JSON → throws with informative error. */ export declare function loadConfig(cwd: string, options?: LoadConfigOptions): Promise; /** * Explicit, opt-in disk writeback. * Reads raw config, runs normalizeLegacyKeys, writes back only if normalizations are non-empty. * * For multiRepo: true entries, also runs filesystem detection to populate planning.sub_repos. * * Returns MigrationReport: { migrated, normalizations, wrote }. */ export declare function migrateOnDisk(cwd: string, workstream?: string): Promise; //# sourceMappingURL=index.d.ts.map