/**
 * StageTransitionValidator — per-edge artifact preconditions for
 * `pipelineStage` transitions on project-scope child initiatives.
 *
 * Spec: docs/specs/PROJECT-SCOPE-SPEC.md Phase 1.2.
 *
 * Authority model (P1, signal-vs-authority):
 *   This module is the deterministic *authority* for stage transitions.
 *   Every check is an artifact assertion (file exists, frontmatter field
 *   equals a literal, `gh pr view` reports MERGED, git ancestor
 *   reachability). No LLM-mediated judgment lives here. The drift checker
 *   (Phase 1.4) emits a *signal* but does NOT call into this validator.
 *
 * Path safety:
 *   All filesystem references (specPath, convergence-report path) are
 *   realpath-resolved and must stay under `targetRepoPath` (or under
 *   `docs/specs/reports/` for the convergence report). Symlinks that
 *   escape are rejected.
 *
 * Reconciler-only transitions (`*-> regressed`) require
 * `ctx.bypassMode === 'reconciler'` to succeed; user-initiated requests
 * are rejected with code `REGRESSED_RECONCILER_ONLY`.
 */
import type { PipelineStage } from './InitiativeTracker.js';
export type StageTransitionResult = {
    ok: true;
} | {
    ok: false;
    reason: string;
    code: string;
};
/**
 * Context passed in by the caller. Helpers are injected so unit tests can
 * mock the `gh pr view` shell-out and the `git merge-base` check without
 * touching real subprocesses.
 */
export interface ValidationContext {
    /** Absolute path to the target git repo whose artifacts we're checking. */
    targetRepoPath: string;
    /** Relative or absolute path to the spec markdown (jailed under targetRepoPath). */
    specPath?: string;
    /** Required for building → merged. */
    prNumber?: number;
    /** Required for approved → building. */
    taskFlowRecordId?: string;
    /** Required for any → skipped. */
    skippedReason?: string;
    skippedBy?: string;
    /** Required for skipped → outline. */
    unskippedAt?: string;
    /** Special-cased reconciler bypass for `*-> regressed` edges. */
    bypassMode?: 'reconciler';
    readSpecFrontmatter?: (absPath: string) => Promise<unknown>;
    ghPrView?: (prNumber: number) => Promise<GhPrView>;
    gitMergeBaseIsAncestor?: (sha: string, branch: string) => boolean;
    /**
     * The canonical-main ref the merge commit must be reachable from. Defaults to
     * `origin/main`. On a fork-origin checkout (dev-agent home: origin = the
     * fork, merges on the upstream remote) the route resolves the upstream
     * remote and passes `<remote>/main` here. (#866 sibling fix.)
     */
    mergeBaseBranch?: string;
}
export interface GhPrView {
    state: string;
    mergeCommit: {
        oid: string;
    } | null;
    statusCheckRollup: Array<{
        conclusion?: string | null;
        status?: string | null;
        state?: string | null;
    }>;
}
/**
 * The single definition of "the convergence tag is present" — used by the
 * formal gate (here) AND mirrored by the precommit's recognizer
 * (scripts/lib/convergence-recognition.mjs), cross-checked for agreement by
 * tests/unit/convergence-gate-consistency.test.ts.
 *
 * The canonical converging-audit tooling
 * (skills/spec-converge/scripts/write-convergence-tag.mjs) writes
 * `review-convergence: "<ISO timestamp>"` — a NON-EMPTY STRING. The legacy /
 * hand-added form is boolean `true`. Both count as present. Empty string,
 * `false`, `undefined`, and any other type do NOT.
 *
 * Pure, dependency-free, no I/O — exported so it can be unit-tested directly.
 */
export declare function isConvergenceTagPresent(value: unknown): boolean;
/**
 * Validate a `from → to` transition under the given context.
 *
 * `from === undefined` is treated as "creation lands directly at `to`" and
 * the validator runs the same preconditions as if the prior stage were
 * exactly one step earlier in the canonical pipeline. This keeps create
 * paths honest without requiring callers to first stage at `outline`.
 */
export declare function validateStageTransition(from: PipelineStage | undefined, to: PipelineStage, ctx: ValidationContext): Promise<StageTransitionResult>;
interface JailResult {
    ok: true;
    absPath: string;
}
interface JailFail {
    ok: false;
    reason: string;
}
/**
 * Resolve `rel` under `root` and assert that the realpath of the resulting
 * path remains inside `root`. Rejects:
 *   - absolute paths that aren't under root
 *   - `..` traversal that escapes
 *   - symlinks whose realpath escapes
 *
 * If the target file does not yet exist, the realpath check walks up to the
 * nearest existing ancestor (because realpath() on a missing path throws).
 */
export declare function jailPath(root: string, rel: string): JailResult | JailFail;
export {};
//# sourceMappingURL=StageTransitionValidator.d.ts.map