/**
 * 发布问题场景注册表 — 问题六十三: 标准资产契约场景 (17-22b)
 */
import fs from "node:fs";
import path from "node:path";
export const TEMPLATE_CONTRACT_SCENARIOS = [
    // 场景 17: 13 必填字段
    {
        scenario_id: "release-scenario-template-contract-api-field-table",
        test_files: ["tests/engine/release_issue_scenario_matrix.test.ts"],
        production_entrypoint: "template_asset_contract_registry.buildTemplateAssetContracts",
        expected_outcome: "所有合同 13 个必填字段全部存在且非 undefined",
        runner: async () => {
            const { buildTemplateAssetContracts } = await import("../../templates/template_asset_contract_registry.js");
            const contracts = buildTemplateAssetContracts(process.cwd());
            const requiredFields = ["path", "asset_kind", "contract_version", "owner_mechanism_id", "asset_visibility", "sync_to_user_project", "sync_target", "runtime_visibility", "evidence_role", "user_visible", "lifecycle_status", "consume_category", "validation_entrypoint"];
            const missing = contracts.flatMap((c) => requiredFields.filter((f) => !(f in c) || c[f] === undefined).map((f) => `${c.path}: ${f}`));
            if (missing.length > 0)
                return { scenario_id: "release-scenario-template-contract-api-field-table", status: "fail", error: missing.join("; ") };
            return {
                scenario_id: "release-scenario-template-contract-api-field-table",
                status: "pass",
                evidence: `${contracts.length} contracts all have ${requiredFields.length} required fields`,
                production_trace: { tool_entrypoint: "buildTemplateAssetContracts", diagnostic_codes: [`contracts:${contracts.length}`], gates_consumed: ["contract_gate", "engine_contract"] },
            };
        },
    },
    // 场景 18: 权威绑定全量覆盖
    {
        scenario_id: "release-scenario-template-contract-authority-binding",
        test_files: ["tests/engine/release_issue_scenario_matrix.test.ts"],
        production_entrypoint: "template_asset_contract_registry.auditContractCoverage",
        expected_outcome: "unregistered_files.length === 0（全量覆盖）",
        runner: async () => {
            const { auditContractCoverage } = await import("../../templates/template_asset_contract_registry.js");
            const report = auditContractCoverage(process.cwd());
            if (report.unregistered_files.length > 0)
                return { scenario_id: "release-scenario-template-contract-authority-binding", status: "fail", error: `unregistered: ${report.unregistered_files.join(", ")}` };
            if (!report.consumption_evidence_verified)
                return { scenario_id: "release-scenario-template-contract-authority-binding", status: "fail", error: `consumption evidence invalid: ${report.consumption_evidence_failures.join("; ")}` };
            return {
                scenario_id: "release-scenario-template-contract-authority-binding",
                status: "pass",
                evidence: `${report.total_contracts} contracts, 0 unregistered, consumption evidence verified`,
                production_trace: { tool_entrypoint: "auditContractCoverage", diagnostic_codes: [`total:${report.total_contracts}`, `unregistered:${report.unregistered_files.length}`, "consumption-evidence:verified"], gates_consumed: ["contract_gate", "engine_contract"] },
            };
        },
    },
    // 场景 19: lifecycle_status 合法
    {
        scenario_id: "release-scenario-template-contract-existing-doc-upgrade",
        test_files: ["tests/engine/release_issue_scenario_matrix.test.ts"],
        production_entrypoint: "template_asset_contract_registry.buildTemplateAssetContracts",
        expected_outcome: "所有合同 lifecycle_status=active 或 deprecated/internal_only，版本升级路径不遗漏",
        runner: async () => {
            const { buildTemplateAssetContracts } = await import("../../templates/template_asset_contract_registry.js");
            const contracts = buildTemplateAssetContracts(process.cwd());
            const validStatuses = ["active", "deprecated", "internal_only"];
            const invalid = contracts.filter((c) => !validStatuses.includes(c.lifecycle_status));
            if (invalid.length > 0)
                return { scenario_id: "release-scenario-template-contract-existing-doc-upgrade", status: "fail", error: `invalid lifecycle: ${invalid.map((c) => `${c.path}: ${c.lifecycle_status}`).join(", ")}` };
            const activeCount = contracts.filter((c) => c.lifecycle_status === "active").length;
            if (activeCount === 0)
                return { scenario_id: "release-scenario-template-contract-existing-doc-upgrade", status: "fail", error: "no active contracts" };
            return {
                scenario_id: "release-scenario-template-contract-existing-doc-upgrade",
                status: "pass",
                evidence: `${activeCount} active, ${contracts.length - activeCount} non-active`,
                production_trace: { tool_entrypoint: "buildTemplateAssetContracts", diagnostic_codes: [`active:${activeCount}`, `total:${contracts.length}`], gates_consumed: ["contract_gate", "engine_contract"] },
            };
        },
    },
    // 场景 20: 决策一致性
    {
        scenario_id: "release-scenario-template-contract-conflict",
        test_files: ["tests/engine/release_issue_scenario_matrix.test.ts"],
        production_entrypoint: "template_asset_contract_registry.getContractDecision",
        expected_outcome: "同一 path 两次 getContractDecision 结果一致（0 conflicts）",
        runner: async () => {
            const { buildTemplateAssetContracts, getContractDecision } = await import("../../templates/template_asset_contract_registry.js");
            const contracts = buildTemplateAssetContracts(process.cwd());
            let conflicts = 0;
            const conflictPaths = [];
            for (const c of contracts) {
                const d1 = getContractDecision(c.path);
                const d2 = getContractDecision(c.path);
                if (d1.decision !== d2.decision) {
                    conflicts++;
                    conflictPaths.push(`${c.path}: ${d1.decision} vs ${d2.decision}`);
                }
            }
            if (conflicts > 0)
                return { scenario_id: "release-scenario-template-contract-conflict", status: "fail", error: conflictPaths.join("; ") };
            return {
                scenario_id: "release-scenario-template-contract-conflict",
                status: "pass",
                evidence: `${contracts.length} contracts, 0 decision conflicts`,
                production_trace: { tool_entrypoint: "getContractDecision", diagnostic_codes: [`contracts:${contracts.length}`, `conflicts:${conflicts}`], gates_consumed: ["contract_gate", "engine_contract"] },
            };
        },
    },
    // 场景 21: 非 active 合同不出现在 syncable
    {
        scenario_id: "release-scenario-template-contract-draft-skip",
        test_files: ["tests/engine/release_issue_scenario_matrix.test.ts"],
        production_entrypoint: "template_asset_contract_registry.buildTemplateAssetContracts + getSyncableAssetPaths",
        expected_outcome: "非 active 合同（deprecated/internal_only）存在且不出现在 syncable 列表",
        runner: async () => {
            const { buildTemplateAssetContracts, getSyncableAssetPaths } = await import("../../templates/template_asset_contract_registry.js");
            const contracts = buildTemplateAssetContracts(process.cwd());
            const syncable = new Set(getSyncableAssetPaths());
            const nonActive = contracts.filter((c) => c.lifecycle_status !== "active");
            if (nonActive.length === 0)
                return { scenario_id: "release-scenario-template-contract-draft-skip", status: "fail", error: "no non-active contracts to verify skip behavior" };
            const leakedNonActive = nonActive.filter((c) => syncable.has(c.path) && c.asset_visibility === "soloforge_internal");
            if (leakedNonActive.length > 0)
                return { scenario_id: "release-scenario-template-contract-draft-skip", status: "fail", error: `internal assets in syncable: ${leakedNonActive.map((c) => c.path).join(", ")}` };
            return {
                scenario_id: "release-scenario-template-contract-draft-skip",
                status: "pass",
                evidence: `${nonActive.length} non-active, 0 leaked to syncable`,
                production_trace: { tool_entrypoint: "getSyncableAssetPaths", diagnostic_codes: [`nonActive:${nonActive.length}`, `syncable:${syncable.size}`], gates_consumed: ["contract_gate", "engine_contract"] },
            };
        },
    },
    // 场景 22: 低风险意图路由
    {
        scenario_id: "release-scenario-template-contract-low-risk-skip",
        test_files: ["tests/engine/release_issue_scenario_matrix.test.ts"],
        production_entrypoint: "sf_classify",
        expected_outcome: "低风险意图 route 为 code_change/operation/skip_chat",
        runner: async () => {
            const { classify } = await import("../../pipeline/classifier.js");
            const result = classify({ intent: "添加一行日志" });
            const route = result.route_decision?.route ?? "";
            const lowRiskRoutes = ["code_change", "operation", "skip_chat"];
            if (!lowRiskRoutes.includes(route))
                return { scenario_id: "release-scenario-template-contract-low-risk-skip", status: "fail", error: `expected low-risk route, got ${route}` };
            return {
                scenario_id: "release-scenario-template-contract-low-risk-skip",
                status: "pass",
                evidence: `route=${route}`,
                production_trace: { tool_entrypoint: "sf_classify", diagnostic_codes: [`route:${route}`], gates_consumed: ["router"] },
            };
        },
    },
    // 场景 22b: 一个任务内证明正式 API 产物从草稿阻断，经修复重验和人工确认后才能交付。
    {
        scenario_id: "release-scenario-template-contract-repair-directive",
        test_files: ["tests/engine/release_issue_scenario_matrix.test.ts"],
        production_entrypoint: "sf_classify→sf_expand(api_spec artifact)→sf_verify(draft)→sf_deliver(SF-CONTRACT-0003)→sf_learn→sf_verify(clear)→sf_record_verification_execution→sf_accept(confirm)→sf_deliver",
        expected_outcome: "同一正式 API 产物与同一 task_id 在修复前阻断，修复重验及显式人工确认后 status=accepted 并可交付",
        runner: async () => {
            const { createToolHarness } = await import("../release_tool_harness.js");
            const intent = "根据 docs/prd.md 生成接口设计";
            const harness = await createToolHarness({ techStack: { backend: { lang: "none", framework: "none", version: "0" }, frontend: { lang: "none", framework: "none", version: "0" } } });
            try {
                const sourceDocPath = path.join(harness.tmpDir, "docs", "prd.md");
                fs.mkdirSync(path.dirname(sourceDocPath), { recursive: true });
                fs.writeFileSync(sourceDocPath, "# 用户列表需求\n\n提供用户列表查询接口，支持分页并返回用户 ID。\n", "utf-8");
                const cls = harness.parseResult(await harness.callTool("sf_classify", { intent }));
                const taskId = cls.task_id;
                if (!taskId)
                    return { scenario_id: "release-scenario-template-contract-repair-directive", status: "fail", error: "sf_classify 未返回 task_id" };
                const exp = harness.parseResult(await harness.callTool("sf_expand", {
                    task_id: taskId,
                    input_material_confirmations: ["docs/prd.md"],
                }));
                if (exp.status === "awaiting_confirmation") {
                    return { scenario_id: "release-scenario-template-contract-repair-directive", status: "fail", error: "unexpected awaiting_confirmation" };
                }
                const tc = harness.taskContext;
                const expandedCtx = await tc.load(taskId);
                const artifactPath = expandedCtx?.artifact_output?.path;
                if (!artifactPath || expandedCtx?.artifact_output?.kind !== "api_spec") {
                    return { scenario_id: "release-scenario-template-contract-repair-directive", status: "fail", error: `sf_expand 未创建正式 api_spec artifact_output: ${exp.error ?? exp.status ?? JSON.stringify(exp).slice(0, 180)}` };
                }
                const artifactAbs = path.join(harness.tmpDir, artifactPath);
                fs.mkdirSync(path.dirname(artifactAbs), { recursive: true });
                const openApiAbs = path.join(harness.tmpDir, "docs", "api", "openapi.yaml");
                fs.mkdirSync(path.dirname(openApiAbs), { recursive: true });
                fs.writeFileSync(openApiAbs, [
                    "openapi: 3.0.0", "info:", "  title: Users API", "  version: '1.0'",
                    "paths:", "  /users:", "    get:", "      responses:", "        '200':",
                    "          description: OK",
                ].join("\n"), "utf-8");
                const compliantApiContent = [
                    "# API 接口规格", "## 接口概览", "提供分页用户列表查询。", "## 请求响应规范",
                    "### GET /users", "#### 请求字段表",
                    "| 请求字段名 | 类型 | 必填 | 来源 | 说明 | 示例 | 校验规则 | 错误语义 |",
                    "| --- | --- | --- | --- | --- | --- | --- | --- |",
                    "| page | number | 否 | query | 页码 | 1 | >= 1 | 页码无效 |",
                    "#### 响应字段表",
                    "| 响应字段名 | 类型 | 必填 | 来源 | 说明 | 示例 | 校验规则 | 错误语义 |",
                    "| --- | --- | --- | --- | --- | --- | --- | --- |",
                    "| data | array | 是 | response | 用户列表 | [] | array | 无 |",
                ].join("\n");
                fs.writeFileSync(artifactAbs, `draft\n\n${compliantApiContent}`, "utf-8");
                await harness.setupPlanGate(taskId);
                const ver1 = harness.parseResult(await harness.callTool("sf_verify", { task_id: taskId, changed_files: [artifactPath], confirm: true }));
                if (ver1.diagnostic_code !== "SF-CONTRACT-DRAFT") {
                    return { scenario_id: "release-scenario-template-contract-repair-directive", status: "fail", error: `expected SF-CONTRACT-DRAFT, got ${ver1.diagnostic_code ?? "none"}: ${ver1.error ?? JSON.stringify(ver1).slice(0, 240)}` };
                }
                const ctx1 = await tc.load(taskId);
                if (!ctx1?.repair_reverify_directive?.blocked) {
                    return { scenario_id: "release-scenario-template-contract-repair-directive", status: "fail", error: "directive not blocked" };
                }
                const blockedDeliver = harness.parseResult(await harness.callTool("sf_deliver", { task_id: taskId, confirm: true }));
                if (blockedDeliver.diagnostic_code !== "SF-CONTRACT-0003") {
                    return { scenario_id: "release-scenario-template-contract-repair-directive", status: "fail", error: `expected delivery SF-CONTRACT-0003, got ${blockedDeliver.diagnostic_code ?? "none"}` };
                }
                await harness.callTool("sf_learn", { task_id: taskId, result: "failure", failure_type: "integration" });
                fs.writeFileSync(artifactAbs, compliantApiContent, "utf-8");
                const ver2 = harness.parseResult(await harness.callTool("sf_verify", { task_id: taskId, changed_files: [artifactPath], confirm: true }));
                const ctx2 = await tc.load(taskId);
                if (ctx2?.repair_reverify_directive?.blocked) {
                    return { scenario_id: "release-scenario-template-contract-repair-directive", status: "fail", error: "directive not cleared after fix" };
                }
                if (ver2.diagnostic_code === "SF-CONTRACT-DRAFT" || ver2.diagnostic_code === "SF-CONTRACT-0003") {
                    return { scenario_id: "release-scenario-template-contract-repair-directive", status: "fail", error: `sf_verify still failing, code=${ver2.diagnostic_code}` };
                }
                if (ctx2?.artifact_output?.status !== "verified") {
                    return { scenario_id: "release-scenario-template-contract-repair-directive", status: "fail", error: `artifact did not reach verified: ${ctx2?.artifact_output?.status}; verification=${JSON.stringify(ver2.artifact_verification ?? ver2.artifact_warning ?? ver2).slice(0, 300)}` };
                }
                const ctxForV = await tc.load(taskId);
                if (!ctxForV?.verification_plan) {
                    return { scenario_id: "release-scenario-template-contract-repair-directive", status: "fail", error: "no verification_plan after sf_verify" };
                }
                await harness.callTool("sf_record_verification_execution", {
                    task_id: taskId,
                    plan_id: ctxForV.verification_plan.plan_id,
                    execution_records: ctxForV.verification_plan.commands.map((cmd, i) => ({
                        command: cmd, exit_code: 0,
                        stdout_hash: "a".repeat(64), stderr_hash: "e".repeat(64),
                        started_at: new Date().toISOString(), finished_at: new Date().toISOString(),
                        evidence_id: `evidence-${taskId}-${i}`,
                    })),
                });
                const accept = harness.parseResult(await harness.callTool("sf_accept", {
                    task_id: taskId, confirm: true, confirmed_by: "release-reviewer",
                    confirmation_ref: `api-artifact:${taskId}`, acceptance_notes: "API 字段表与响应结构已人工确认",
                    run_mode: "not_applicable",
                }));
                if (accept.artifact_transition !== "accepted") {
                    return { scenario_id: "release-scenario-template-contract-repair-directive", status: "fail", error: `artifact acceptance failed: ${accept.error ?? accept.artifact_transition}` };
                }
                const del = harness.parseResult(await harness.callTool("sf_deliver", { task_id: taskId, confirm: true }));
                if (del.diagnostic_code) {
                    return { scenario_id: "release-scenario-template-contract-repair-directive", status: "fail", error: `sf_deliver still blocked: ${del.diagnostic_code}, error=${del.error ?? "none"}` };
                }
                const delObs = harness.getObservations().slice().reverse().find(o => o.tool_name === "sf_deliver");
                if (!delObs || delObs.is_error) {
                    return { scenario_id: "release-scenario-template-contract-repair-directive", status: "fail", error: `sf_deliver observation error: ${delObs?.parsed_response?.error ?? "no obs"}` };
                }
                const finalCtx = await tc.load(taskId);
                if (!finalCtx) {
                    return { scenario_id: "release-scenario-template-contract-repair-directive", status: "fail", error: "task context lost after delivery" };
                }
                const trace = await harness.collectTrace();
                return {
                    scenario_id: "release-scenario-template-contract-repair-directive",
                    status: "pass",
                    evidence: `task=${taskId} artifact=${finalCtx.artifact_output?.status} directive_cleared=${!finalCtx.repair_reverify_directive} delivered=${!delObs.is_error}`,
                    production_trace: trace,
                    behavioral_proof: {
                        task_id: taskId, blocked_task_id: taskId, delivered_task_id: taskId,
                        contract_blocked: blockedDeliver.diagnostic_code === "SF-CONTRACT-0003",
                        repair_directive_cleared: !finalCtx.repair_reverify_directive,
                        artifact_status: finalCtx.artifact_output?.status,
                        acceptance_confirmation_ref: `api-artifact:${taskId}`,
                        delivery_succeeded: !delObs.is_error,
                    },
                };
            }
            finally {
                harness.cleanup();
            }
        },
    },
];
//# sourceMappingURL=scenarios_template_contract.js.map