// engine/handoff-artifacts/schemas.ts — SPEC-725: Zod schemas for 5 versioned handoff artifacts
import { z } from 'zod';
// ---------------------------------------------------------------------------
// Common
// ---------------------------------------------------------------------------
export const SchemaVersion = z.string().regex(/^\d+\.\d+\.\d+$/, 'Must be a valid SemVer string');
// ---------------------------------------------------------------------------
// Artifact Zod schemas
// ---------------------------------------------------------------------------
export const IntakeV1Schema = z.object({
    schema_version: SchemaVersion,
    kind: z.enum(['idea', 'quick-fix', 'bug-spec', 'feature-spec', 'epic']),
    description: z.string().min(20, 'description must be at least 20 characters'),
    confidence: z.number().min(0).max(1),
    rationale: z.string(),
    suggestedSpecId: z.string().optional(),
    createdAt: z.iso.datetime(),
});
export const SpecLockV1Schema = z.object({
    schema_version: SchemaVersion,
    specId: z.string(),
    frontmatterSha: z.string().regex(/^[a-f0-9]{64}$/, 'Must be a SHA-256 hex string'),
    approvedBy: z.string(),
    plannerToken: z.string(),
    scenarios: z.array(z.object({ title: z.string(), done: z.boolean() })),
    lockedAt: z.iso.datetime(),
});
export const ReviewFeedbackV1Schema = z.object({
    schema_version: SchemaVersion,
    specId: z.string(),
    verdict: z.enum(['approved', 'changes-requested']),
    reviewer: z.object({
        kind: z.enum(['spec-review-agent', 'human', 'automation']),
        agent: z.string().min(1),
        verdict: z.enum(['approved', 'changes-requested']),
    }),
    blockers: z.array(z.string()),
    suggestions: z.array(z.string()),
    body: z.string(),
    reviewedAt: z.iso.datetime(),
});
export const ImplementationReportV1Schema = z.object({
    schema_version: SchemaVersion,
    specId: z.string(),
    commitSha: z.string(),
    filesChanged: z.array(z.string()),
    testsRun: z.number().int().min(0),
    testsPassed: z.number().int().min(0),
    completedAt: z.iso.datetime(),
});
export const ValidationReportV1Schema = z.object({
    schema_version: SchemaVersion,
    specId: z.string(),
    passed: z.boolean(),
    gates: z.array(z.object({
        name: z.string(),
        passed: z.boolean(),
        reason: z.string().optional(),
    })),
    reviewer: z.object({
        kind: z.enum(['implementation-review-agent', 'human', 'automation']),
        agent: z.string().min(1),
        verdict: z.enum(['approved', 'changes-requested']),
    }),
    specCompliance: z
        .object({
        score: z.number().min(0).max(100),
        command: z.string(),
        scenarios: z.array(z.object({
            title: z.string(),
            verdict: z.enum(['pass', 'fail', 'missing']),
            evidence: z.array(z.string()),
        })),
    })
        .optional(),
    score: z.number().optional(),
    completedAt: z.iso.datetime(),
});
// ---------------------------------------------------------------------------
// Schema registry
// ---------------------------------------------------------------------------
export const ARTIFACT_SCHEMAS = {
    intake: IntakeV1Schema,
    'spec.lock': SpecLockV1Schema,
    review_feedback: ReviewFeedbackV1Schema,
    'implementation-report': ImplementationReportV1Schema,
    'validation-report': ValidationReportV1Schema,
};
// ---------------------------------------------------------------------------
// Validate function
// ---------------------------------------------------------------------------
/**
 * Validate a payload against the schema for the given artifact kind.
 * Returns ValidationOk on success, ValidationErr on failure.
 * Special case: missing schema_version emits MISSING_SCHEMA_VERSION code.
 */
export function validateArtifact(kind, payload) {
    // Check for missing schema_version before full Zod parse
    if (payload === null ||
        typeof payload !== 'object' ||
        !('schema_version' in payload) ||
        payload.schema_version === undefined ||
        payload.schema_version === null) {
        return {
            ok: false,
            errors: [
                {
                    code: 'MISSING_SCHEMA_VERSION',
                    path: 'schema_version',
                    message: 'schema_version is required and must be a valid SemVer string',
                },
            ],
        };
    }
    const schema = ARTIFACT_SCHEMAS[kind];
    const result = schema.safeParse(payload);
    if (result.success) {
        return {
            ok: true,
            payload: result.data,
            warnings: [],
        };
    }
    const errors = result.error.issues.map((issue) => ({
        code: issue.code.toUpperCase(),
        path: issue.path.join('.') || '(root)',
        message: issue.message,
    }));
    return { ok: false, errors };
}
//# sourceMappingURL=schemas.js.map