/**
 * WikiMigrateService — one-shot conversion from legacy OSS knowledge
 * stores into the v2.1 three-scope vault structure.
 *
 * Legacy sources covered (per v2.1 spec §6 migration table):
 *   - `<project>/.crewly/knowledge/decisions.json[]`   → llm-curated/decisions/
 *   - `<project>/.crewly/knowledge/patterns.json[]`    → llm-curated/patterns/
 *   - `<project>/.crewly/knowledge/gotchas.json[]`     → llm-curated/patterns/  (gotchas are a kind of pattern)
 *   - `<project>/.crewly/knowledge/relationships.json[]` → llm-curated/people/
 *   - `<project>/.crewly/knowledge/learnings.md`       → append to llm-curated/log.md
 *   - `<project>/.crewly/knowledge/*.md` (loose)       → llm-curated/decisions/  (or skipped per heuristic)
 *   - `~/.crewly/agents/<id>/memory.json roleKnowledge[]` → llm-curated/{patterns,decisions}/  (copy; original stays)
 *
 * Design rules (locked 2026-05-24):
 *  - Default DRY-RUN. Caller must pass `{ apply: true }` to write.
 *  - Idempotent. A manifest at `<vault>/.migration-state.json` records
 *    each migrated entry's content hash + source + target. Re-runs skip
 *    entries already in the manifest.
 *  - LEGACY FILES ARE NEVER DELETED. Rollback path stays open.
 *  - Routing: everything → project vault. Items that look cross-project
 *    (mention foreign team UUIDs / customer names) are tagged
 *    `routing_uncertain: true` in frontmatter; wiki-lint surfaces them
 *    later for human review.
 *  - Per-agent memory.json is COPIED, not moved. The agent's private
 *    memory store is preserved untouched.
 *
 * @module services/wiki/wiki-migrate.service
 */
/** Filename inside the project vault where we record migrated entries. */
export declare const WIKI_MIGRATE_MANIFEST_FILENAME = ".migration-state.json";
/** Manifest format version. Bump on any breaking schema change. */
export declare const WIKI_MIGRATE_MANIFEST_VERSION = 1;
/** Hard cap on loose .md files we walk (defensive). */
export declare const WIKI_MIGRATE_MAX_LOOSE_MD = 200;
/**
 * Name of the frozen `okr/` folder added to TEAM + PROJECT vaults for the
 * OKR cascade (spec okr-cascade.md §5). Holds AUTHORED OKR narrative only —
 * runtime Mission/KeyResult entities remain the cascade source-of-truth; this
 * folder optionally mirrors approved Missions and is read-only to agents.
 */
export declare const WIKI_OKR_FOLDER = "okr";
/**
 * Service reference recorded in the `okr/` frozen-folder schema block's
 * `referenced_by` list. Lets the schema-loader / referenced-by resolver link
 * the folder back to the cascade service that owns its mirrored content.
 */
export declare const WIKI_OKR_REFERENCED_BY = "service:okr-cascade.service";
/** Human-readable description for the TEAM-scope `okr/` frozen-folder block. */
export declare const WIKI_OKR_TEAM_DESCRIPTION = "Authored OKR narrative for this team. Mirrors approved Missions; agents read-only, Steve authors.";
/** Human-readable description for the PROJECT-scope `okr/` frozen-folder block. */
export declare const WIKI_OKR_PROJECT_DESCRIPTION = "Authored OKR narrative for this project. Mirrors approved Missions; agents read-only, Steve authors.";
export interface WikiMigrateInput {
    /** Absolute path to the project root (the dir containing `.crewly/`). */
    projectRoot: string;
    /**
     * When false (default), the call only PROPOSES migrations and returns a
     * preview. When true, files are written, manifest is updated, and
     * vaults are bootstrapped on the fly.
     */
    apply?: boolean;
    /**
     * Override the home dir used to locate `~/.crewly/agents/` and
     * `~/.crewly/teams/`. Tests use this; production leaves it undefined
     * so `os.homedir()` wins.
     */
    homeDir?: string;
    /**
     * Override `process.cwd()` semantics for the "current project". Tests
     * use this; production leaves it undefined.
     */
    includeAgentMemory?: boolean;
}
export type WikiMigrateSourceType = 'decision' | 'pattern' | 'gotcha' | 'relationship' | 'learning-log' | 'loose-md' | 'memory-entry' | 'sop-role' | 'sop-common' | 'sop-domain' | 'sop-pro-template';
export interface WikiMigrateProposedPage {
    sourceType: WikiMigrateSourceType;
    /** Display path of the legacy source (relative-ish, suitable for UI). */
    sourceFile: string;
    /** Stable id for the source entry. Random uuid for entries without one. */
    sourceId: string;
    /** sha256 of the generated markdown body — drives idempotency. */
    contentHash: string;
    /** Absolute vault path the migration lands in. */
    targetVaultPath: string;
    /** Path relative to vault root. */
    targetRelativePath: string;
    /** Human-readable title pulled / synthesized from the source. */
    title: string;
    /** True when the entry mentions content suggesting cross-project scope. */
    routingUncertain: boolean;
    /** Reason this entry was skipped (already migrated, malformed, etc.). */
    skipReason?: string;
}
export interface WikiMigrateBootstrapNeeded {
    /** True when the project vault `.crewly/wiki/SCHEMA.md` is missing. */
    project: boolean;
    /** True when `~/.crewly/global-wiki/SCHEMA.md` is missing. */
    global: boolean;
    /** UUIDs of team vaults missing their SCHEMA.md. */
    teams: string[];
}
/**
 * Per-vault outcome of an `okr/` frozen-folder backfill (OKR cascade spec §5).
 * One entry per existing vault we inspected; `changed` is true only when this
 * run actually created the folder and/or injected the schema block.
 */
export interface WikiOkrFolderResult {
    /** Vault scope this entry describes. */
    scope: 'team' | 'project';
    /** Absolute path to the vault root (the dir containing `SCHEMA.md`). */
    vaultPath: string;
    /** True when the `okr/` directory was created this run. */
    folderCreated: boolean;
    /** True when the `okr/` block was injected into `SCHEMA.md` this run. */
    schemaUpdated: boolean;
    /** Convenience: folderCreated || schemaUpdated. */
    changed: boolean;
}
/**
 * Aggregate result of {@link WikiMigrateService.ensureOkrFolders}. Lists every
 * existing TEAM/PROJECT vault that was inspected and whether it changed.
 */
export interface WikiEnsureOkrResult {
    ok: true;
    /** When false (default), describes what WOULD change without writing. */
    applied: boolean;
    /** One entry per existing vault inspected. */
    vaults: WikiOkrFolderResult[];
    /** Count of vaults that changed (or would change) this run. */
    changedCount: number;
}
export interface WikiMigrateScanResult {
    ok: true;
    /** Resolved absolute project vault path. */
    vaultPath: string;
    /** True when ANY legacy source was discovered. */
    legacyDetected: boolean;
    /** Per-entry proposals (skipped ones stay in this list with a reason). */
    proposedPages: WikiMigrateProposedPage[];
    /** Vault scopes still missing SCHEMA.md. Apply will bootstrap them. */
    bootstrapNeeded: WikiMigrateBootstrapNeeded;
    /** Summary counters for UI. */
    summary: {
        decisions: number;
        patterns: number;
        gotchas: number;
        relationships: number;
        learnings: number;
        looseMd: number;
        memoryEntries: number;
        alreadyMigrated: number;
    };
}
export interface WikiMigrateApplyResult extends WikiMigrateScanResult {
    /** Count of pages newly written this run. */
    applied: number;
    /** Count of pages skipped (already migrated or malformed). */
    skipped: number;
    /** Vaults newly bootstrapped this run. */
    bootstrapped: string[];
    /** Path to the manifest after the run. */
    manifestPath: string;
}
export type WikiMigrateOutcome = WikiMigrateScanResult | WikiMigrateApplyResult | {
    ok: false;
    reason: 'invalid_input' | 'project_root_missing';
    message: string;
};
/**
 * Singleton service exposing scan() + apply(). Stateless across calls;
 * the manifest on disk is the persistence layer.
 */
export declare class WikiMigrateService {
    private static instance;
    static getInstance(): WikiMigrateService;
    static resetInstance(): void;
    /**
     * Dry-run preview of what `apply()` would do.
     */
    scan(input: WikiMigrateInput): Promise<WikiMigrateOutcome>;
    /**
     * Execute the migration: bootstrap vaults, write pages, persist manifest.
     */
    apply(input: WikiMigrateInput): Promise<WikiMigrateOutcome>;
    /**
     * Migrate OSS-distributed SOPs (the ones that ship with Crewly OSS itself)
     * into the GLOBAL vault's `llm-curated/sops/` tree so wiki-query can find
     * them. Without this, the org-wide SOPs (content-production-pipeline,
     * git-workflow, blocker-handling, etc.) sit in `<crewly-src>/config/sops/`
     * + `config/domain-sops/` + `config/templates/pro-sops/` and are invisible
     * to `wiki-query` — which is why ORC reported "no marketing SOP" despite
     * the file existing on disk (2026-05-27 incident).
     *
     * Routing:
     *   `config/sops/<role>/<n>.md`             → llm-curated/sops/<role>/<n>.md
     *   `config/sops/common/<n>.md`              → llm-curated/sops/common/<n>.md
     *   `config/sops/<n>.md` (no role)           → llm-curated/sops/general/<n>.md
     *   `config/domain-sops/<n>.sop.md`          → llm-curated/sops/domain/<n>.md
     *   `config/templates/pro-sops/norms/<n>.md` → llm-curated/sops/pro-norms/<n>.md
     *
     * Idempotent via the global vault's manifest. Legacy source files are NEVER
     * deleted. Bootstraps the global vault if missing.
     *
     * @param input.crewlySourceRoot - Absolute path to the Crewly OSS source
     *   directory (the one containing `config/sops/`). Defaults to process.cwd()
     *   when the OSS happens to BE running from its own source dir.
     * @param input.apply - false for dry-run, true to write.
     */
    migrateOssSops(input: {
        crewlySourceRoot?: string;
        apply?: boolean;
        homeDir?: string;
    }): Promise<WikiMigrateOutcome>;
    /**
     * Recursive walk of a SOP source dir, calling `visit` for every `.md` file
     * with its path RELATIVE to `root`.
     */
    private collectSopFiles;
    /**
     * Shared implementation. Branches on `input.apply` for the write phase.
     */
    private run;
    private detectBootstrapNeeded;
    private bootstrapMissingVaults;
    private writeProjectVaultSkeleton;
    private writeGlobalVaultSkeleton;
    private writeTeamVaultSkeleton;
    private loadManifest;
    private persistManifest;
    private readJsonArray;
    private proposeFromJsonArray;
    private decisionToPage;
    private patternToPage;
    private gotchaToPage;
    private relationshipToPage;
    private proposeLearningsLog;
    private proposeLooseMarkdown;
    /**
     * (NEW 2026-05-27) Scan the project root for deploy/agent docs that
     * agents would otherwise miss. Each project keeps "how do I deploy"
     * knowledge OUTSIDE `.crewly/` in well-known locations:
     *
     *   `<root>/CLAUDE.md`                     → llm-curated/runbooks/claude-md.md
     *   `<root>/AGENTS.md`                     → llm-curated/runbooks/agents-md.md
     *   `<root>/DEPLOYMENT.md`                 → llm-curated/runbooks/deployment.md
     *   `<root>/DEPLOYMENT-GUIDE.md`           → llm-curated/runbooks/deployment-guide.md
     *   `<root>/deploy/*.md`                   → llm-curated/runbooks/deploy-<n>.md
     *   `<root>/docs/deploy*.md`               → llm-curated/runbooks/docs-<n>.md
     *   `<root>/.claude/commands/deploy*.md`   → llm-curated/runbooks/claude-cmd-<n>.md
     *
     * Frontmatter sets `kind: runbook` so wiki-query / lint can distinguish
     * these from llm-curated/decisions/.
     */
    private proposeProjectRootDocs;
    /**
     * (NEW 2026-05-27) Scan `<project>/.crewly/docs/*.md` — the storage of
     * the deprecated `query-knowledge` skill. Each file → its own page under
     * `llm-curated/docs/<slug>.md`. Lets wiki-query (v2.1) reach the same
     * content that `query-knowledge` (legacy) used to.
     *
     * Capped at WIKI_MIGRATE_MAX_LOOSE_MD to keep scan bounded.
     */
    private proposeProjectDocs;
    private proposeFromAgentMemory;
    /**
     * Write the proposed page's body to disk under the target vault.
     * Returns the FINAL relativePath written (with a suffix if a collision
     * forced one).
     */
    private writePage;
    /**
     * Re-emit the body for a page. The body is computed once during scan
     * (for content-hash determination) but we don't keep it on the proposal
     * — re-derive from the source on apply. This avoids duplicating large
     * blobs in API responses.
     */
    private renderForPage;
    private summarize;
    /**
     * Idempotently add the frozen `okr/` folder + SCHEMA.md block to EXISTING
     * team and project vaults that predate the OKR cascade.
     *
     * New vaults already seed `okr/` via the skeleton writers; this method covers
     * vaults already on disk. It is the analogue of {@link bootstrapMissingVaults}
     * for a single added frozen folder: only vaults whose `SCHEMA.md` already
     * exists are touched (a fully-missing vault is bootstrapped elsewhere).
     *
     * Detection is idempotent — a vault that already declares `okr/` in its
     * SCHEMA.md and has the directory on disk is reported as `changed: false`.
     * The cascade source-of-truth stays the runtime Mission tree; this folder
     * holds authored narrative only.
     *
     * @param input.projectRoot - Absolute path to the project root (dir holding
     *   `.crewly/wiki/`). Its project vault is backfilled when present.
     * @param input.homeDir - Override for `~`; team vaults live under
     *   `<homeDir>/.crewly/teams/<uuid>/wiki/`. Tests pass a scratch dir.
     * @param input.apply - false (default) for a dry-run preview; true to write.
     * @returns Per-vault results and a changed-vault count.
     * @example
     * ```typescript
     * const res = await WikiMigrateService.getInstance().ensureOkrFolders({
     *   projectRoot, homeDir, apply: true,
     * });
     * ```
     */
    ensureOkrFolders(input: {
        projectRoot?: string;
        homeDir?: string;
        apply?: boolean;
    }): Promise<WikiEnsureOkrResult>;
    /**
     * Backfill a single existing vault with the frozen `okr/` folder + schema
     * block. Idempotent: a no-op (changed=false) when the folder and the schema
     * block are both already present.
     *
     * @param vaultDir - Absolute path to the vault root (contains `SCHEMA.md`).
     * @param scope - Vault scope, used to pick the schema description copy.
     * @param description - Description string for the injected `okr/` block.
     * @param apply - When false, only reports what would change.
     * @returns The per-vault outcome.
     */
    private ensureOkrForVault;
}
//# sourceMappingURL=wiki-migrate.service.d.ts.map