/**
 * Docs Provenance Graph contract — cross-entity nodes + edges.
 *
 * Typed shape for the cross-entity provenance graph returned by C7
 * (`cleo docs provenance` / `cleo docs graph`). A {@link DocProvenanceResponse}
 * is the wire format consumed by the human renderer registered for the
 * `(command='docs', kind='provenance')` slot — the same renderer family that
 * consumes {@link TreeResponse} envelopes from E11.
 *
 * Nodes carry a `kind` discriminator (`doc` | `task` | `decision` | `session` |
 * `memory`) so the renderer can pick the correct icon, colour, and detail
 * layout per entity. Edges carry a `relation` discriminator that names the
 * semantic link between two nodes (`attached-to`, `supersedes`,
 * `superseded-by`, `related-task`, `linked-decision`, `derived-from`).
 *
 * This contract is intentionally read-only — every field is `readonly`, every
 * array is `ReadonlyArray<…>` — so consumers cannot mutate the graph after
 * receiving it from `cleo docs provenance`. Mutations flow through writer
 * verbs (`cleo docs add`, `cleo docs supersede`, …) and emit a fresh graph on
 * the next read.
 *
 * @see TreeResponse — E11 T10138 — the sibling envelope shape this contract
 *   composes with (a docs provenance UI may render the doc-subset as a tree).
 * @see DocKindRegistry — packages/contracts/src/docs-taxonomy.ts — supplies
 *   the `kind` string carried on each {@link ProvenanceDocNode}.
 * @see ADR-077 §3 — Human Render Contract (envelope kind discriminator).
 * @see ADR-078 — Docs Provenance Graph (cross-entity edge taxonomy).
 *
 * @epic T10157 — Docs Provenance Graph (E12)
 * @task T10166
 */
import { z } from 'zod';
/**
 * Frozen const array backing {@link ProvenanceNodeKind} — used by the Zod
 * enum schema and by exhaustiveness checks in switch statements.
 *
 * @task T10166
 */
export const PROVENANCE_NODE_KINDS = [
    'doc',
    'task',
    'decision',
    'session',
    'memory',
];
/**
 * Frozen const array backing {@link ProvenanceEdgeRelation} — used by the
 * Zod enum schema and by exhaustiveness checks.
 *
 * @task T10166
 */
export const PROVENANCE_EDGE_RELATIONS = [
    'attached-to',
    'supersedes',
    'superseded-by',
    'related-task',
    'linked-decision',
    'derived-from',
    'shares-topic',
];
/**
 * Frozen const array backing {@link DocLifecycleStatus}.
 *
 * @task T10166
 */
export const DOC_LIFECYCLE_STATUSES = [
    'active',
    'superseded',
    'archived',
    'draft',
];
// ─── Type guards ──────────────────────────────────────────────────────────────
/**
 * Type guard — narrows a {@link ProvenanceNode} to {@link ProvenanceDocNode}.
 *
 * @task T10166
 *
 * @example
 * ```ts
 * for (const node of response.nodes) {
 *   if (isProvenanceDocNode(node)) {
 *     console.log(`doc: ${node.slug} (${node.lifecycleStatus})`);
 *   }
 * }
 * ```
 */
export function isProvenanceDocNode(node) {
    return node.kind === 'doc';
}
/**
 * Type guard — narrows a {@link ProvenanceNode} to {@link ProvenanceTaskNode}.
 *
 * @task T10166
 */
export function isProvenanceTaskNode(node) {
    return node.kind === 'task';
}
/**
 * Type guard — narrows a {@link ProvenanceNode} to {@link ProvenanceDecisionNode}.
 *
 * @task T10166
 */
export function isProvenanceDecisionNode(node) {
    return node.kind === 'decision';
}
/**
 * Type guard — narrows a {@link ProvenanceNode} to {@link ProvenanceSessionNode}.
 *
 * @task T10166
 */
export function isProvenanceSessionNode(node) {
    return node.kind === 'session';
}
/**
 * Type guard — narrows a {@link ProvenanceNode} to {@link ProvenanceMemoryNode}.
 *
 * @task T10166
 */
export function isProvenanceMemoryNode(node) {
    return node.kind === 'memory';
}
/**
 * Runtime envelope guard for {@link DocProvenanceResponse}.
 *
 * Verifies the envelope shape without inspecting individual node payloads —
 * use the Zod schema for deep validation.
 *
 * @task T10166
 */
export function isDocProvenanceResponse(value) {
    if (typeof value !== 'object' || value === null)
        return false;
    const v = value;
    return (Array.isArray(v.nodes) &&
        Array.isArray(v.edges) &&
        typeof v.totalNodes === 'number' &&
        typeof v.totalEdges === 'number');
}
// ─── Zod schemas ──────────────────────────────────────────────────────────────
/**
 * Zod enum schema for {@link ProvenanceNodeKind}.
 *
 * @task T10166
 */
export const provenanceNodeKindSchema = z.enum(PROVENANCE_NODE_KINDS);
/**
 * Zod enum schema for {@link ProvenanceEdgeRelation}.
 *
 * @task T10166
 */
export const provenanceEdgeRelationSchema = z.enum(PROVENANCE_EDGE_RELATIONS);
/**
 * Zod enum schema for {@link DocLifecycleStatus}.
 *
 * @task T10166
 */
export const docLifecycleStatusSchema = z.enum(DOC_LIFECYCLE_STATUSES);
const provenanceNodeBaseFields = {
    id: z.string().min(1),
    title: z.string().min(1),
    metadata: z.record(z.string(), z.unknown()).optional(),
};
/**
 * Zod schema for {@link ProvenanceDocNode}.
 *
 * @task T10166
 */
export const provenanceDocNodeSchema = z.object({
    ...provenanceNodeBaseFields,
    kind: z.literal('doc'),
    slug: z.string().min(1),
    docKind: z.string().min(1),
    lifecycleStatus: docLifecycleStatusSchema,
    publishedAt: z.string().min(1),
    supersededAt: z.string().min(1).optional(),
    summary: z.string().optional(),
});
/**
 * Zod schema for {@link ProvenanceTaskNode}.
 *
 * @task T10166
 */
export const provenanceTaskNodeSchema = z.object({
    ...provenanceNodeBaseFields,
    kind: z.literal('task'),
    taskType: z.enum(['saga', 'epic', 'task', 'subtask']),
    status: z.enum(['pending', 'in_progress', 'done', 'blocked', 'cancelled', 'archived']),
});
/**
 * Zod schema for {@link ProvenanceDecisionNode}.
 *
 * @task T10166
 */
export const provenanceDecisionNodeSchema = z.object({
    ...provenanceNodeBaseFields,
    kind: z.literal('decision'),
    outcome: z.enum(['proposed', 'accepted', 'rejected', 'superseded']),
    decidedAt: z.string().min(1),
});
/**
 * Zod schema for {@link ProvenanceSessionNode}.
 *
 * @task T10166
 */
export const provenanceSessionNodeSchema = z.object({
    ...provenanceNodeBaseFields,
    kind: z.literal('session'),
    startedAt: z.string().min(1),
    endedAt: z.string().min(1).optional(),
});
/**
 * Zod schema for {@link ProvenanceMemoryNode}.
 *
 * @task T10166
 */
export const provenanceMemoryNodeSchema = z.object({
    ...provenanceNodeBaseFields,
    kind: z.literal('memory'),
    memoryType: z.enum(['observation', 'pattern', 'decision', 'diary']),
    recordedAt: z.string().min(1),
});
/**
 * Discriminated-union schema for {@link ProvenanceNode}.
 *
 * @task T10166
 */
export const provenanceNodeSchema = z.discriminatedUnion('kind', [
    provenanceDocNodeSchema,
    provenanceTaskNodeSchema,
    provenanceDecisionNodeSchema,
    provenanceSessionNodeSchema,
    provenanceMemoryNodeSchema,
]);
/**
 * Zod schema for {@link ProvenanceEdge}.
 *
 * @task T10166
 */
export const provenanceEdgeSchema = z.object({
    relation: provenanceEdgeRelationSchema,
    from: z.string().min(1),
    fromKind: provenanceNodeKindSchema,
    to: z.string().min(1),
    toKind: provenanceNodeKindSchema,
    addedAt: z.string().min(1),
    summary: z.string().optional(),
});
/**
 * Zod schema for {@link DocProvenanceResponse}.
 *
 * @task T10166
 */
export const docProvenanceResponseSchema = z.object({
    nodes: z.array(provenanceNodeSchema).readonly(),
    edges: z.array(provenanceEdgeSchema).readonly(),
    totalNodes: z.number().int().nonnegative(),
    totalEdges: z.number().int().nonnegative(),
});
//# sourceMappingURL=provenance.js.map