/**
 * Project-Level AIWG Config
 *
 * Manages `.aiwg/aiwg.config` — the project-level record of:
 *   - Which AI provider toolchains this project targets
 *   - Which frameworks/addons are deployed (with uninstall metadata)
 *   - User-defined scripts callable via `aiwg run`
 *
 * @implements #621
 */
import type { ProjectLocalType } from '../extensions/manifest.js';
/**
 * Artifact counts for one provider deployment
 */
export interface DeployedArtifactCounts {
    agents: number;
    commands: number;
    skills: number;
    rules: number;
}
/**
 * One entry in the `installed` map
 */
export interface InstalledEntry {
    /** Deployed version (CalVer or semver) */
    version: string;
    /**
     * Source of the deployment:
     *   "bundled"       — came from the npm package
     *   "cache"         — came from ~/.cache/aiwg/packages/ (#557)
     *   "project-local" — came from .aiwg/{extensions,addons,frameworks,plugins}/<id>/ (#1035)
     *   git URL         — direct source URL
     */
    source: 'bundled' | 'cache' | 'project-local' | string;
    /** ISO-8601 timestamp of last deployment */
    installedAt: string;
    /** Provider → artifact counts */
    deployedTo: Record<string, DeployedArtifactCounts>;
    /** SHA-256 of manifest.json at deploy time; used for stale detection */
    manifestHash?: string;
    /**
     * Project-local-only fields (set when `source === 'project-local'`).
     *
     * Per @.aiwg/architecture/adr-unified-registry-shape.md (ADR companion to
     * #1035). These three fields MUST be present together when source is
     * `'project-local'` and SHOULD be absent otherwise.
     */
    /** Path of the bundle directory relative to project root (e.g., ".aiwg/extensions/foo/"). */
    localPath?: string;
    /** Bundle type from the manifest. */
    localType?: ProjectLocalType;
    /** Schema version of the manifest.json this entry was written from (currently `'1'`). */
    manifestVersion?: string;
    /**
     * Hashes of source artifacts at deploy time, keyed by source-relative path
     * (e.g., "rules/my-rule.md", "skills/my-skill/SKILL.md"). Used by
     * `aiwg remove` to detect pristine vs. mutated vs. replaced deployed
     * files per the design at @.aiwg/architecture/design-aiwg-remove-revert.md.
     *
     * Optional — older entries without this field fall back to "always-prompt"
     * remove behavior until the next `aiwg use` re-records them.
     *
     * @implements #1037
     */
    artifactHashes?: Record<string, string>;
}
/**
 * One secondary remote: a mirror, fork base, or publishing target.
 */
export interface SecondaryRemote {
    /** Must match a name from `git remote` */
    name: string;
    /** Free-form tag (mirror | upstream | publish | replica | …) */
    purpose?: string;
    /** Hint to release workflows: push tags here on stable cuts */
    push_on_release?: boolean;
}
/**
 * Repo origin topology — declares which remote is primary (CI / issues / PRs)
 * and which are secondary (mirrors, publishing targets).
 *
 * @implements #994
 */
export interface RemotesConfig {
    /** git remote name driving CI / PRs by default. Defaults to "origin". */
    primary?: string;
    /** Where issues live. Defaults to `primary`. */
    issue_tracker?: string;
    /** Where CI runs. Defaults to `primary`. */
    ci?: string;
    /** Mirrors, fork bases, publishing targets. */
    secondary?: SecondaryRemote[];
}
/**
 * Resolved remote topology — every field guaranteed to be set.
 * Returned by {@link resolveRemotes}.
 */
export interface ResolvedRemotes {
    primary: string;
    issue_tracker: string;
    ci: string;
    secondary: SecondaryRemote[];
}
/**
 * Top-level shape of .aiwg/aiwg.config
 */
export interface AiwgConfig {
    $schema?: string;
    version: '1';
    /**
     * AI provider toolchains this project targets.
     * `aiwg use <framework>` with no --provider flag deploys to ALL of these.
     */
    providers: string[];
    /**
     * Frameworks and addons currently deployed.
     * Keyed by the name passed to `aiwg use`.
     */
    installed: Record<string, InstalledEntry>;
    /**
     * User-defined scripts, run via `aiwg run <name>`.
     * Executed with `sh -c "<command>"` (or `cmd /c` on Windows).
     */
    scripts: Record<string, string>;
    /**
     * Repo origin topology. Optional — when absent, agents treat `origin` as primary.
     * @implements #994
     */
    remotes?: RemotesConfig;
    /**
     * Repo control / delivery policy — how AIWG agents are expected to ship code.
     * Optional — when absent, agents fall back to the conservative defaults
     * applied by `resolveDelivery()`.
     * @implements #995
     */
    delivery?: DeliveryConfig;
    /**
     * Provider-scoped parallelism caps — limits how many concurrent subagents,
     * Ralph loops, and Mission Control missions agents may spawn. Composes with
     * (takes the minimum of) `context-budget` rule caps and `rlm-context-management`
     * Rule 8's 7-agent hard cap. Optional — when absent, agents fall back to
     * provider-specific defaults applied by `resolveParallelism()`.
     * @implements #1359
     */
    parallelism?: ParallelismConfig;
}
/**
 * How agents should ship code — modes:
 *   - `direct`         : commit & push straight to default_branch
 *   - `feature-branch` : create a branch and push it, but don't open a PR
 *   - `pr-required`    : feature branch + PR via the resolved primary remote
 */
export type DeliveryMode = 'direct' | 'feature-branch' | 'pr-required';
/**
 * Merge style preference; matches the values Gitea/GitHub/GitLab APIs accept.
 */
export type MergeStyle = 'rebase-merge' | 'squash' | 'merge' | 'fast-forward-only';
/**
 * Force-push policy:
 *   - `never`           : agents may never force-push
 *   - `own-branch-only` : OK on the agent's own feature branch, never to main
 *   - `allowed`         : escape hatch for tooling that needs it
 */
export type ForcePushPolicy = 'never' | 'own-branch-only' | 'allowed';
/**
 * Branch-naming convention. `{issue}` and `{slug}` are interpolated by skills.
 */
export interface BranchNaming {
    prefix_by_type?: Partial<Record<'feat' | 'fix' | 'docs' | 'chore' | 'refactor' | 'test', string>>;
}
/**
 * Repo control policy — see DeliveryMode for the high-level shape. Every field
 * is optional; sensible defaults applied via {@link resolveDelivery}.
 *
 * @implements #995
 */
export interface DeliveryConfig {
    mode?: DeliveryMode;
    default_branch?: string;
    branch_naming?: BranchNaming;
    merge_style?: MergeStyle;
    delete_branch_on_merge?: boolean;
    /** When true, agents must wait for CI green before declaring done. */
    require_ci_green?: boolean;
    require_signed_commits?: boolean;
    force_push_policy?: ForcePushPolicy;
    /** Include "Closes #N" / "Fixes #N" in PR body when an issue is referenced. */
    auto_close_issues?: boolean;
    /** Post AL CYCLE status comments to issue threads from address-issues loops. */
    issue_comment_on_cycle?: boolean;
}
/**
 * Resolved delivery policy with all defaults applied. Returned by
 * {@link resolveDelivery}.
 */
export interface ResolvedDelivery {
    mode: DeliveryMode;
    default_branch: string;
    branch_naming: Required<BranchNaming>;
    merge_style: MergeStyle;
    delete_branch_on_merge: boolean;
    require_ci_green: boolean;
    require_signed_commits: boolean;
    force_push_policy: ForcePushPolicy;
    auto_close_issues: boolean;
    issue_comment_on_cycle: boolean;
}
/**
 * Resolve the delivery policy with defaults applied.
 *
 * Defaults are intentionally conservative — they match what AIWG agents
 * naturally do today (PR-required, rebase-merge, no force pushes, post issue
 * comments) so that adding the schema doesn't shift behavior for existing
 * projects.
 */
export declare function resolveDelivery(delivery: DeliveryConfig | undefined): ResolvedDelivery;
/**
 * Provider-scoped parallelism cap — limits how many concurrent subagents,
 * Ralph loops, and Mission Control missions agents may spawn. Designed to
 * keep AIWG within the rate-limit envelope of the underlying model provider
 * (Anthropic per-key TPM/RPM caps are the most-reported trigger).
 *
 * Composes with (effective limit = MIN of):
 *   - `parallelism.max_parallel_subagents` (this config)
 *   - `context-budget` rule's `AIWG_CONTEXT_WINDOW`-derived cap, if set
 *   - `rlm-context-management` Rule 8's 7-agent hard cap (RLM dispatches only)
 *   - The natural task decomposition (no point spawning 4 when only 2 subtasks exist)
 *
 * Every field is optional. Defaults applied via {@link resolveParallelism}.
 *
 * @implements #1359
 */
export interface ParallelismConfig {
    /** Max concurrent subagents (Task dispatches, rlm-batch fan-outs). */
    max_parallel_subagents?: number;
    /** Max concurrent Ralph external loops (`aiwg agent-loop-ext`). */
    max_parallel_ralph_loops?: number;
    /** Max concurrent Mission Control missions (`aiwg mc dispatch`). */
    max_parallel_mc_missions?: number;
    /** Free-form note explaining why this cap was chosen (e.g., plan tier). */
    rationale?: string;
}
/**
 * Resolved parallelism caps with all defaults applied. Returned by
 * {@link resolveParallelism}.
 */
export interface ResolvedParallelism {
    max_parallel_subagents: number;
    max_parallel_ralph_loops: number;
    max_parallel_mc_missions: number;
    rationale?: string;
}
/**
 * Per-provider parallelism defaults. Conservative numbers for Anthropic-backed
 * providers reflect Pro/Team-plan rate limits — operators on Enterprise tiers
 * should bump via `aiwg config set --project parallelism.max_parallel_subagents N`.
 *
 * Sources for the numbers:
 *   - claude / claude-code: Anthropic per-key throttling at higher concurrency
 *   - codex / copilot / etc.: OpenAI / GitHub quotas are generally per-org and
 *     less aggressive at small fan-outs (10 is a safe middle ground)
 *   - hermes: MCP sidecar; rate-limit depends on upstream provider, operator
 *     should tune. Conservative 10 default.
 *   - unknown: conservative 4 default.
 */
export declare const PROVIDER_PARALLELISM_DEFAULTS: Record<string, ResolvedParallelism>;
/**
 * Return the provider's parallelism defaults, or the conservative fallback
 * when the provider is unknown.
 */
export declare function getProviderParallelismDefaults(provider: string | undefined): ResolvedParallelism;
/**
 * Resolve the parallelism caps with provider-aware defaults applied. The
 * primary provider drives the default — typically the first entry in the
 * project's `providers` array.
 *
 * When `parallelism` has explicit values, they override the provider default
 * field-by-field. When no provider is supplied (or it's not in the defaults
 * map), the conservative 4-subagent fallback applies.
 *
 * @implements #1359
 */
export declare function resolveParallelism(parallelism: ParallelismConfig | undefined, primaryProvider?: string): ResolvedParallelism;
/**
 * Provider tag for a given remote URL. Used by skills (issue-create,
 * pr-review, commit-and-push) to pick the right CLI / MCP client when
 * the operator didn't pass `--provider` explicitly.
 *
 * Recognized hosts:
 *   - github.com         → 'github'
 *   - gitlab.com / gitlab.* → 'gitlab'
 *   - any host containing 'gitea' (or matching the typical Gitea path shape) → 'gitea'
 *
 * Returns 'unknown' for self-hosted instances we can't classify by host alone —
 * callers should then prompt the operator or fall back to the configured
 * AIWG provider list.
 *
 * @implements #997
 */
export declare function resolveRemoteProvider(remoteUrl: string): 'github' | 'gitlab' | 'gitea' | 'unknown';
/**
 * Resolve the repo remote topology with defaults applied.
 *
 * Defaults:
 *   - `primary` defaults to "origin"
 *   - `issue_tracker` defaults to `primary`
 *   - `ci` defaults to `primary`
 *   - `secondary` defaults to `[]`
 *
 * Pass an absent or partial `remotes` block — every field comes back populated.
 */
export declare function resolveRemotes(remotes: RemotesConfig | undefined): ResolvedRemotes;
/**
 * Valid provider names (mirrors PROVIDER_PATHS in use.ts)
 */
export declare const VALID_PROVIDERS: readonly ["claude", "factory", "codex", "opencode", "copilot", "cursor", "warp", "windsurf", "hermes", "openclaw"];
export type Provider = typeof VALID_PROVIDERS[number];
/**
 * Empty config template.
 *
 * Includes an explicit `delivery` block defaulting to `pr-required`. The
 * runtime default in {@link resolveDelivery} is the same, so this is purely
 * for visibility — new projects ship with the policy written down so users
 * can see what their agents will do, and switch via `aiwg config set` or
 * the AIWG Steward agent without first having to discover the field exists.
 */
export declare function emptyConfig(providers?: string[]): AiwgConfig;
/**
 * Resolve path to .aiwg/aiwg.config for a project directory
 */
export declare function getConfigPath(projectDir: string): string;
/**
 * Resolve the project directory for a handler invocation.
 *
 * Precedence:
 *   1. `--target <path>` or `--prefix <path>` flag in args
 *   2. The HandlerContext `cwd`, if provided
 *   3. `process.cwd()`
 *
 * All three variants existed scattered across handlers (#919 cleanup).
 * Use this helper so we have one authoritative resolution.
 */
export declare function getProjectDir(ctx: {
    cwd?: string;
} | undefined, args?: readonly string[]): string;
/**
 * Read .aiwg/aiwg.config.
 * Returns null if the file does not exist.
 */
export declare function readAiwgConfig(projectDir: string): Promise<AiwgConfig | null>;
/**
 * Write .aiwg/aiwg.config, creating .aiwg/ if needed.
 */
export declare function writeAiwgConfig(projectDir: string, config: AiwgConfig): Promise<void>;
/**
 * Update the `installed` record for a framework after a successful deployment.
 * Returns the updated config (does not write to disk — caller must call writeAiwgConfig).
 */
export declare function updateInstalled(config: AiwgConfig, name: string, provider: string, counts: DeployedArtifactCounts, opts: {
    version: string;
    source: string;
    manifestHash?: string;
    /** Set when source === 'project-local'. Relative to project root. */
    localPath?: string;
    /** Set when source === 'project-local'. */
    localType?: ProjectLocalType;
    /** Set when source === 'project-local'. */
    manifestVersion?: string;
    /** Optional source-artifact hash map for project-local remove revert (#1037). */
    artifactHashes?: Record<string, string>;
}): AiwgConfig;
/**
 * Aggregate deployment counts across all installed frameworks for a given provider.
 * Returns the totals for agents, commands, skills, and rules.
 * If no provider is specified, uses the first configured provider.
 */
export declare function getDeploymentSummary(config: AiwgConfig, provider?: string): DeployedArtifactCounts;
/**
 * Compute SHA-256 hash of a manifest.json file.
 * Returns undefined if the file cannot be read.
 */
export declare function hashManifest(manifestPath: string): Promise<string | undefined>;
/**
 * Scan actual deployment directories and populate `deployedTo` for any
 * `installed` entries that have an empty `deployedTo` map.
 *
 * Called by `aiwg init` when migrating a project that already has frameworks
 * deployed but whose config was created before deployment-tracking was added.
 *
 * @implements #721
 */
export declare function populateDeployedTo(config: AiwgConfig, projectDir: string): Promise<AiwgConfig>;
//# sourceMappingURL=aiwg-config.d.ts.map