/**
 * AgentMdJobLoader — Phase 1a loader-side support for the new agentmd job format.
 *
 * Reads per-slug manifests from `.instar/jobs/schedule/<slug>.json`, optionally
 * resolves an accompanying `.instar/jobs/<origin>/<slug>.md` (for entries with
 * execute.type === "agentmd"), and validates frontmatter via a hardened YAML
 * parse + Zod preprocessor coercion per spec §6.
 *
 * Phase 1a is LOADER ONLY:
 *   - agentmd entries load into memory with `body` and `frontmatter` populated.
 *   - They will NOT fire until Phase 1b adds scheduler dispatch.
 *   - Existing JobScheduler.buildPrompt code paths are untouched.
 *
 * Spec: docs/specs/INSTAR-JOBS-AS-AGENTMD-SPEC.md
 */
import { z } from 'zod';
import type { JobDefinition, JobPriority, ModelTier } from '../core/types.js';
declare const VALID_ORIGINS: readonly ["instar", "user"];
type Origin = (typeof VALID_ORIGINS)[number];
/** YAML FAILSAFE_SCHEMA parses booleans/numbers as strings. The
 *  preprocessors below restore typed values with EXACT coercion semantics:
 *  - Booleans accept only `true`/`True`/`TRUE`/`false`/`False`/`FALSE`.
 *    YAML 1.1's `yes`/`no`/`on`/`off` are explicitly rejected.
 *  - Integers accept only `^-?\d+$`. Floats, `NaN`, `Infinity` rejected. */
export declare const BoolField: z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodBoolean>;
export declare const IntField: z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodNumber>;
/** Per-slug manifest as it lives on disk at .instar/jobs/schedule/<slug>.json.
 *  Validation is hand-coded (rather than Zod-derived) to keep parity with the
 *  existing validateJob style and to produce identical per-field error
 *  messages. */
export interface PerSlugManifest {
    slug: string;
    origin: Origin;
    schedule: string;
    priority: JobPriority;
    model?: ModelTier;
    expectedDurationMinutes: number;
    enabled: boolean;
    execute: {
        type: 'skill' | 'prompt' | 'script' | 'agentmd';
        value?: string;
        args?: string;
    };
    tags?: string[];
    topicId?: number;
    telegramNotify?: boolean | 'on-alert';
    machines?: string[];
    gate?: string;
    unrestrictedTools?: boolean;
    manifestVersion?: number;
    /** MCP access for the spawned session — 'none' spawns with zero project MCP
     *  servers (claude-code only). Absent → legacy full-project-MCP behavior. */
    mcpAccess?: 'project' | 'none';
    /** SHA of the body at the time an operator disabled the default — preserved
     *  across regeneration so a re-enabled default re-syncs intentionally. */
    disabledAtBodyHash?: string;
}
/** A single load-time problem. The scheduler probe and Issues card consume
 *  these. Phase 1a surfaces them via console.warn + the returned list. */
export interface LoadProblem {
    /** What went wrong. */
    kind: 'manifest-invalid' | 'agentmd-file-missing' | 'agentmd-yaml-invalid' | 'agentmd-frontmatter-invalid' | 'agentmd-body-too-large' | 'agentmd-symlink' | 'slug-invalid' | 'case-fold-collision' | 'shadowed-by-schedule' | 'lock-mismatch' | 'unknown';
    slug?: string;
    origin?: Origin;
    path?: string;
    message: string;
}
export interface AgentMdLoadResult {
    jobs: JobDefinition[];
    problems: LoadProblem[];
}
/** Hand-rolled bounded-concurrency runner. p-limit is not in package.json
 *  and the spec explicitly permits a hand-roll. Pattern: counter + queue.
 *
 *  Phase 1a uses synchronous filesystem APIs end-to-end to preserve the
 *  existing sync `loadJobs(jobsFile): JobDefinition[]` signature. The READ
 *  fanout in Phase 1a is bounded only by the manifest count (typically <50);
 *  the spec performance budget of 1500 ms cold-boot @ 200 jobs is met with
 *  sequential sync reads at this scale. Phase 1b/1c migrate to async +
 *  this concurrency runner when buildPrompt and the lock-file pipeline
 *  require non-blocking I/O. */
export declare function mapWithConcurrency<T, R>(items: readonly T[], limit: number, fn: (item: T, index: number) => Promise<R>): Promise<R[]>;
/**
 * Load per-slug manifests from `.instar/jobs/schedule/`.
 *
 * Returns `{ jobs, problems }`. If the schedule directory does not exist,
 * returns empty (this is the pre-spec state — caller continues with legacy
 * jobs.json only).
 *
 * Synchronous: matches the existing `loadJobs(jobsFile)` API so callers
 * (JobScheduler.start, status command, job CLI) do not need to become async
 * in Phase 1a. Per-slug fanout is bounded by the manifest count, which is
 * small enough at the Phase 1a scale (200-job spec budget) that the
 * sequential sync read path is comfortably within the 1500 ms cold-boot
 * budget. See header comment for migration plan.
 *
 * @param scheduleDir Absolute path to `.instar/jobs/schedule/`
 * @param jobsRootDir Absolute path to `.instar/jobs/` (parent of schedule)
 */
export declare function loadAgentMdJobs(scheduleDir: string, jobsRootDir: string): AgentMdLoadResult;
export declare const READ_CONCURRENCY_LIMIT = 32;
/** Validates the per-slug manifest schema. Mirrors validateJob style so the
 *  error messages are familiar; centralized here because the agentmd path
 *  has additional fields (origin, unrestrictedTools, execute.type = agentmd). */
export declare function validateManifest(raw: unknown, sourceLabel?: string): PerSlugManifest;
/** Exposed for SchedulerProbe and tests: returns true iff a JobDefinition
 *  originating from an agentmd manifest has its body cached in memory.
 *  Phase 1a invariant — agentmd jobs MUST carry body after loadJobs(). */
export declare function isAgentMdJobHydrated(job: JobDefinition): boolean;
export {};
//# sourceMappingURL=AgentMdJobLoader.d.ts.map