{
  "canonical_name": "mova-compact/mova-flat-runner",
  "compilation_id": "pack_2e00bfc100564e71a66d9712952f7992",
  "created_at": "2026-05-14T16:33:03.558712+00:00",
  "created_by": "project-pack-compiler",
  "feedback": {
    "carrier_selection_notes": [
      "viable_asset_types=mcp_config, recipe, host_instruction, eval, preflight",
      "recommended_asset_types=mcp_config, recipe, host_instruction, eval, preflight"
    ],
    "evidence_delta": {
      "confirmed_claims": [
        "identity_anchor_present",
        "capability_and_host_targets_present",
        "install_path_declared_or_better"
      ],
      "missing_required_fields": [],
      "must_verify_forwarded": [
        "Run or inspect `npx -y @leryk1981/mova-flat-runner@3.3.3` in an isolated environment.",
        "Confirm the project exposes the claimed capability to at least one target host."
      ],
      "quickstart_execution_scope": "allowlisted_sandbox_smoke",
      "sandbox_command": "npx -y @leryk1981/mova-flat-runner@3.3.3",
      "sandbox_container_image": "node:22-slim",
      "sandbox_execution_backend": "docker",
      "sandbox_planner_decision": "deterministic_isolated_install",
      "sandbox_validation_id": "sbx_b78700cf8d024cca9b1b0cb60a7611fa"
    },
    "feedback_event_type": "project_pack_compilation_feedback",
    "learning_candidate_reasons": [],
    "template_gaps": []
  },
  "identity": {
    "canonical_id": "project_4ac457c9b7211cbe0fb4550259bcdc1b",
    "canonical_name": "mova-compact/mova-flat-runner",
    "homepage_url": null,
    "license": "unknown",
    "repo_url": "https://github.com/mova-compact/mova-flat-runner",
    "slug": "mova-flat-runner",
    "source_packet_id": "phit_18f59bed32d84901b3e0a66c1c505670",
    "source_validation_id": "dval_b9c2ece545924497a3a7cc01468e2261"
  },
  "merchandising": {
    "best_for": "需要工具连接与集成能力，并使用 mcp_host的用户",
    "github_forks": 0,
    "github_stars": 0,
    "one_liner_en": "MCP Registry",
    "one_liner_zh": "MCP Registry",
    "primary_category": {
      "category_id": "tool-integrations",
      "confidence": "medium",
      "name_en": "Tool Integrations",
      "name_zh": "工具连接与集成",
      "reason": "matched_keywords:mcp, github"
    },
    "target_user": "使用 mcp_host, claude, chatgpt 等宿主 AI 的用户",
    "title_en": "mova-flat-runner",
    "title_zh": "mova-flat-runner 能力包",
    "visible_tags": [
      {
        "label_en": "MCP Tools",
        "label_zh": "MCP 工具",
        "source": "repo_evidence_project_characteristics",
        "tag_id": "product_domain-mcp-tools",
        "type": "product_domain"
      },
      {
        "label_en": "Tool Integration",
        "label_zh": "工具接入扩展",
        "source": "repo_evidence_project_characteristics",
        "tag_id": "user_job-tool-integration",
        "type": "user_job"
      },
      {
        "label_en": "Workflow Automation",
        "label_zh": "流程自动化",
        "source": "repo_evidence_project_characteristics",
        "tag_id": "core_capability-workflow-automation",
        "type": "core_capability"
      },
      {
        "label_en": "Checkpoint Resume",
        "label_zh": "断点恢复流程",
        "source": "repo_evidence_project_characteristics",
        "tag_id": "workflow_pattern-checkpoint-resume",
        "type": "workflow_pattern"
      },
      {
        "label_en": "Local-first",
        "label_zh": "本地优先",
        "source": "repo_evidence_project_characteristics",
        "tag_id": "selection_signal-local-first",
        "type": "selection_signal"
      }
    ]
  },
  "packet_id": "phit_18f59bed32d84901b3e0a66c1c505670",
  "page_model": {
    "artifacts": {
      "artifact_slug": "mova-flat-runner",
      "files": [
        "PROJECT_PACK.json",
        "QUICK_START.md",
        "PROMPT_PREVIEW.md",
        "HUMAN_MANUAL.md",
        "AI_CONTEXT_PACK.md",
        "BOUNDARY_RISK_CARD.md",
        "PITFALL_LOG.md",
        "REPO_INSPECTION.json",
        "REPO_INSPECTION.md",
        "CAPABILITY_CONTRACT.json",
        "EVIDENCE_INDEX.json",
        "CLAIM_GRAPH.json"
      ],
      "required_files": [
        "PROJECT_PACK.json",
        "QUICK_START.md",
        "PROMPT_PREVIEW.md",
        "HUMAN_MANUAL.md",
        "AI_CONTEXT_PACK.md",
        "BOUNDARY_RISK_CARD.md",
        "PITFALL_LOG.md",
        "REPO_INSPECTION.json"
      ]
    },
    "detail": {
      "capability_source": "Project Hit Packet + DownstreamValidationResult",
      "commands": [
        {
          "command": "npx -y @leryk1981/mova-flat-runner@3.3.3",
          "label": "Node.js / npx · 官方安装入口",
          "source": "https://github.com/mova-compact/mova-flat-runner#readme",
          "verified": true
        }
      ],
      "display_tags": [
        "MCP 工具",
        "工具接入扩展",
        "流程自动化",
        "断点恢复流程",
        "本地优先"
      ],
      "eyebrow": "工具连接与集成",
      "glance": [
        {
          "body": "判断自己是不是目标用户。",
          "label": "最适合谁",
          "value": "需要工具连接与集成能力，并使用 mcp_host的用户"
        },
        {
          "body": "先理解能力边界，再决定是否继续。",
          "label": "核心价值",
          "value": "MCP Registry"
        },
        {
          "body": "未完成验证前保持审慎。",
          "label": "继续前",
          "value": "publish to Doramagic.ai project surfaces"
        }
      ],
      "guardrail_source": "Boundary & Risk Card",
      "guardrails": [
        {
          "body": "Prompt Preview 只展示流程，不证明项目已安装或运行。",
          "label": "Check 1",
          "value": "不要把试用当真实运行"
        },
        {
          "body": "mcp_host, claude, chatgpt",
          "label": "Check 2",
          "value": "确认宿主兼容"
        },
        {
          "body": "publish to Doramagic.ai project surfaces",
          "label": "Check 3",
          "value": "先隔离验证"
        }
      ],
      "mode": "mcp_config, recipe, host_instruction, eval, preflight",
      "pitfall_log": {
        "items": [
          {
            "body": "项目面向 Claude/Cursor/Codex/Gemini/OpenCode 等宿主，或安装命令涉及用户配置目录。",
            "category": "配置坑",
            "evidence": [
              "capability.host_targets | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | host_targets=mcp_host, claude, chatgpt"
            ],
            "severity": "medium",
            "suggested_check": "列出会写入的配置文件、目录和卸载/回滚步骤。",
            "title": "可能修改宿主 AI 配置",
            "user_impact": "安装可能改变本机 AI 工具行为，用户需要知道写入位置和回滚方法。"
          },
          {
            "body": "GitHub 社区证据显示该项目存在一个配置相关的待验证问题：v3.0.0 — Step Enforcement Runtime",
            "category": "配置坑",
            "evidence": [
              "community_evidence:github | cevd_10b68dae59184a36b21a563722829aed | https://github.com/mova-compact/mova-flat-runner/releases/tag/v3.0.0 | 来源类型 github_release 暴露的待验证使用条件。"
            ],
            "severity": "medium",
            "suggested_check": "来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。",
            "title": "来源证据：v3.0.0 — Step Enforcement Runtime",
            "user_impact": "可能影响升级、迁移或版本选择。"
          },
          {
            "body": "README/documentation is current enough for a first validation pass.",
            "category": "能力坑",
            "evidence": [
              "capability.assumptions | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | README/documentation is current enough for a first validation pass."
            ],
            "severity": "medium",
            "suggested_check": "将假设转成下游验证清单。",
            "title": "能力判断依赖假设",
            "user_impact": "假设不成立时，用户拿不到承诺的能力。"
          },
          {
            "body": "未记录 last_activity_observed。",
            "category": "维护坑",
            "evidence": [
              "evidence.maintainer_signals | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | last_activity_observed missing"
            ],
            "severity": "medium",
            "suggested_check": "补 GitHub 最近 commit、release、issue/PR 响应信号。",
            "title": "维护活跃度未知",
            "user_impact": "新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。"
          },
          {
            "body": "no_demo",
            "category": "安全/权限坑",
            "evidence": [
              "downstream_validation.risk_items | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | no_demo; severity=medium"
            ],
            "severity": "medium",
            "suggested_check": "进入安全/权限治理复核队列。",
            "title": "下游验证发现风险项",
            "user_impact": "下游已经要求复核，不能在页面中弱化。"
          },
          {
            "body": "no_demo",
            "category": "安全/权限坑",
            "evidence": [
              "risks.scoring_risks | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | no_demo; severity=medium"
            ],
            "severity": "medium",
            "suggested_check": "把风险写入边界卡，并确认是否需要人工复核。",
            "title": "存在评分风险",
            "user_impact": "风险会影响是否适合普通用户安装。"
          },
          {
            "body": "issue_or_pr_quality=unknown。",
            "category": "维护坑",
            "evidence": [
              "evidence.maintainer_signals | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | issue_or_pr_quality=unknown"
            ],
            "severity": "low",
            "suggested_check": "抽样最近 issue/PR，判断是否长期无人处理。",
            "title": "issue/PR 响应质量未知",
            "user_impact": "用户无法判断遇到问题后是否有人维护。"
          },
          {
            "body": "release_recency=unknown。",
            "category": "维护坑",
            "evidence": [
              "evidence.maintainer_signals | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | release_recency=unknown"
            ],
            "severity": "low",
            "suggested_check": "确认最近 release/tag 和 README 安装命令是否一致。",
            "title": "发布节奏不明确",
            "user_impact": "安装命令和文档可能落后于代码，用户踩坑概率升高。"
          }
        ],
        "source": "ProjectPitfallLog + ProjectHitPacket + validation + community signals",
        "summary": "发现 8 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：配置坑 - 可能修改宿主 AI 配置。",
        "title": "踩坑日志"
      },
      "snapshot": {
        "contributors": 1,
        "forks": 0,
        "license": "unknown",
        "note": "站点快照，非实时质量证明；用于开工前背景判断。",
        "stars": 0
      },
      "source_url": "https://github.com/mova-compact/mova-flat-runner",
      "steps": [
        {
          "body": "不安装项目，先体验能力节奏。",
          "code": "preview",
          "title": "先试 Prompt"
        },
        {
          "body": "理解输入、输出、失败模式和边界。",
          "code": "manual",
          "title": "读说明书"
        },
        {
          "body": "把上下文交给宿主 AI 继续工作。",
          "code": "context",
          "title": "带给 AI"
        },
        {
          "body": "进入主力环境前先完成安装入口与风险边界验证。",
          "code": "verify",
          "title": "沙箱验证"
        }
      ],
      "subtitle": "MCP Registry",
      "title": "mova-flat-runner 能力包",
      "trial_prompt": "# mova-flat-runner - Prompt Preview\n\n> 复制下面这段 Prompt 到你常用的 AI，先试一次，不需要安装。\n> 它的目标是让你直接体验这个项目的服务方式，而不是阅读项目介绍。\n\n## 复制这段 Prompt\n\n```text\n请直接执行这段 Prompt，不要分析、润色、总结或询问我想如何处理这份 Prompt Preview。\n\n你现在扮演 mova-flat-runner 的“安装前体验版”。\n这不是项目介绍、不是评价报告、不是 README 总结。你的任务是让我用最小成本体验它的核心服务。\n\n我的试用任务：我想用它完成一个真实的工具连接与集成任务。\n我常用的宿主 AI：MCP Client / claude / chatgpt\n\n【体验目标】\n围绕我的真实任务，现场演示这个项目如何把输入转成 示例引导, 判断线索。重点是让我感受到工作方式，而不是给我项目背景。\n\n【业务流约束】\n- 你必须像一个正在提供服务的项目能力包，而不是像一个讲解员。\n- 每一轮只推进一个步骤；提出问题后必须停下来等我回答。\n- 每一步都必须让我感受到一个具体服务动作：澄清、整理、规划、检查、判断或收尾。\n- 每一步都要说明：当前目标、你需要我提供什么、我回答后你会产出什么。\n- 不要安装、不要运行命令、不要写代码、不要声称测试通过、不要声称已经修改文件。\n- 需要真实安装或宿主加载后才能验证的内容，必须明确说“这一步需要安装后验证”。\n- 如果我说“用示例继续”，你可以用虚构示例推进，但仍然不能声称真实执行。\n\n【可体验服务能力】\n- 安装前能力预览: MCP Registry 输入：用户任务, 当前 AI 对话上下文；输出：示例引导, 判断线索。\n\n【必须安装后才可验证的能力】\n- 命令行启动或安装流程: 项目文档中存在可执行命令，真实使用需要在本地或宿主环境中运行这些命令。 输入：终端环境, 包管理器, 项目依赖；输出：安装结果, 列表/更新/运行结果。\n\n【核心服务流】\n请严格按这个顺序带我体验。不要一次性输出完整流程：\n1. page-introduction：项目介绍。围绕“项目介绍”模拟一次用户任务，不展示安装或运行结果。\n2. page-installation：安装与配置。围绕“安装与配置”模拟一次用户任务，不展示安装或运行结果。\n3. page-system-architecture：系统架构。围绕“系统架构”模拟一次用户任务，不展示安装或运行结果。\n4. page-transport-layer：传输层。围绕“传输层”模拟一次用户任务，不展示安装或运行结果。\n5. page-security-module：安全模块。围绕“安全模块”模拟一次用户任务，不展示安装或运行结果。\n\n【核心能力体验剧本】\n每一步都必须按“输入 -> 服务动作 -> 中间产物”执行。不要只说流程名：\n1. page-introduction\n输入：用户提供的“项目介绍”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n2. page-installation\n输入：用户提供的“安装与配置”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n3. page-system-architecture\n输入：用户提供的“系统架构”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n4. page-transport-layer\n输入：用户提供的“传输层”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n5. page-security-module\n输入：用户提供的“安全模块”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n【项目服务规则】\n这些规则决定你如何服务用户。不要解释规则本身，而要在每一步执行时遵守：\n- 先确认用户任务、输入材料和成功标准，再模拟项目能力。\n- 每一步都必须形成可检查的小产物，并等待用户确认后再继续。\n- 凡是需要安装、调用工具或访问外部服务的能力，都必须标记为安装后验证。\n\n【每一步的服务约束】\n- Step 1 / page-introduction：Step 1 必须围绕“项目介绍”形成一个小中间产物，并等待用户确认。\n- Step 2 / page-installation：Step 2 必须围绕“安装与配置”形成一个小中间产物，并等待用户确认。\n- Step 3 / page-system-architecture：Step 3 必须围绕“系统架构”形成一个小中间产物，并等待用户确认。\n- Step 4 / page-transport-layer：Step 4 必须围绕“传输层”形成一个小中间产物，并等待用户确认。\n- Step 5 / page-security-module：Step 5 必须围绕“安全模块”形成一个小中间产物，并等待用户确认。\n\n【边界与风险】\n- 不要声称已经安装、运行、调用 API、读写本地文件或完成真实任务。\n- 安装前预览只能展示工作方式，不能证明兼容性、性能或输出质量。\n- 涉及安装、插件加载、工具调用或外部服务的能力必须安装后验证。\n\n【可追溯依据】\n这些路径只用于你内部校验或在我追问“依据是什么”时简要引用。不要在首次回复主动展开：\n- https://github.com/mova-compact/mova-flat-runner\n- https://github.com/mova-compact/mova-flat-runner#readme\n- README.md\n- package.json\n- smithery.yaml\n- server.json\n- src/index.ts\n- src/client.ts\n- src/package_support.ts\n- src/types.ts\n- src/schemas.ts\n- src/transports/local_seam_bridge.ts\n\n【首次问题规则】\n- 首次三问必须先确认用户目标、成功标准和边界，不要提前进入工具、安装或实现细节。\n- 如果后续需要技术条件、文件路径或运行环境，必须等用户确认目标后再追问。\n\n首次回复必须只输出下面 4 个部分：\n1. 体验开始：用 1 句话说明你将带我体验 mova-flat-runner 的核心服务。\n2. 当前步骤：明确进入 Step 1，并说明这一步要解决什么。\n3. 你会如何服务我：说明你会先改变我完成任务的哪个动作。\n4. 只问我 3 个问题，然后停下等待回答。\n\n首次回复禁止输出：后续完整流程、证据清单、安装命令、项目评价、营销文案、已经安装或运行的说法。\n\nStep 1 / brainstorming 的二轮协议：\n- 我回答首次三问后，你仍然停留在 Step 1 / brainstorming，不要进入 Step 2。\n- 第二次回复必须产出 6 个部分：澄清后的任务定义、成功标准、边界条件、\n  2-3 个可选方案、每个方案的权衡、推荐方案。\n- 第二次回复最后必须问我是否确认推荐方案；只有我明确确认后，才能进入下一步。\n- 第二次回复禁止输出 git worktree、代码计划、测试文件、命令或真实执行结果。\n\n后续对话规则：\n- 我回答后，你先完成当前步骤的中间产物并等待确认；只有我确认后，才能进入下一步。\n- 每一步都要生成一个小的中间产物，例如澄清后的目标、计划草案、测试意图、验证清单或继续/停止判断。\n- 所有演示都写成“我会建议/我会引导/这一步会形成”，不要写成已经真实执行。\n- 不要声称已经测试通过、文件已修改、命令已运行或结果已产生。\n- 如果某个能力必须安装后验证，请直接说“这一步需要安装后验证”。\n- 如果证据不足，请明确说“证据不足”，不要补事实。\n```\n",
      "voices": [
        {
          "body": "来源平台：github。github/github_release: v3.0.0 — Step Enforcement Runtime（https://github.com/mova-compact/mova-flat-runner/releases/tag/v3.0.0）。这些是项目级外部声音，不作为单独质量证明。",
          "items": [
            {
              "kind": "github_release",
              "source": "github",
              "title": "v3.0.0 — Step Enforcement Runtime",
              "url": "https://github.com/mova-compact/mova-flat-runner/releases/tag/v3.0.0"
            }
          ],
          "status": "已收录 1 条来源",
          "title": "社区讨论"
        }
      ]
    },
    "homepage_card": {
      "category": "工具连接与集成",
      "desc": "MCP Registry",
      "effort": "安装已验证",
      "forks": 0,
      "icon": "link",
      "name": "mova-flat-runner 能力包",
      "risk": "需复核",
      "slug": "mova-flat-runner",
      "stars": 0,
      "tags": [
        "MCP 工具",
        "工具接入扩展",
        "流程自动化",
        "断点恢复流程",
        "本地优先"
      ],
      "thumb": "gray",
      "type": "MCP 配置"
    },
    "manual": {
      "markdown": "# https://github.com/mova-compact/mova-flat-runner 项目说明书\n\n生成时间：2026-05-14 16:26:04 UTC\n\n## 目录\n\n- [项目介绍](#page-introduction)\n- [安装与配置](#page-installation)\n- [核心概念](#page-core-concepts)\n- [系统架构](#page-system-architecture)\n- [传输层](#page-transport-layer)\n- [安全模块](#page-security-module)\n- [可用工具集](#page-available-tools)\n- [业务验证器](#page-validators)\n- [部署与运维](#page-deployment)\n\n<a id='page-introduction'></a>\n\n## 项目介绍\n\n### 相关页面\n\n相关主题：[安装与配置](#page-installation), [系统架构](#page-system-architecture)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n- [src/index.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/index.ts)\n- [src/transports/local_seam_bridge.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/local_seam_bridge.ts)\n- [src/security/step_mode_guard.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/security/step_mode_guard.ts)\n- [src/package_support.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/package_support.ts)\n- [tasks/task061.md](https://github.com/mova-compact/mova-flat-runner/blob/main/tasks/task061.md)\n</details>\n\n# 项目介绍\n\n## 概述\n\n`mova-flat-runner` 是 MOVA 平台的 Model Context Protocol (MCP) 服务器实现，为 AI 助手（如 Claude Desktop、Codex）提供原生 MCP 连接能力。该项目作为 MOVA 平台的轻量级运行时，通过 MCP 协议暴露标准化的工具接口，使 AI 代理能够与 MOVA 契约执行引擎进行交互。\n\n主要特点：\n- **npm 包分发**：`@leryk1981/mova-flat-runner` 形式发布，版本 `3.3.3`\n- **MCP 协议兼容**：符合 Model Context Protocol 规范，可接入任何 MCP 客户端\n- **工具生态**：提供 `mova_run`、`mova_query`、`mova_contract` 等核心工具集\n- **混合执行模式**：支持本地执行与远程 API 调用\n\n资料来源：[README.md:50]()\n\n## 项目架构\n\n### 整体架构\n\n```\n┌─────────────────────────────────────────────────────────────────┐\n│                        MCP 客户端                                │\n│                    (Claude Desktop / Codex)                     │\n└─────────────────────────────┬───────────────────────────────────┘\n                              │ MCP 协议\n                              ▼\n┌─────────────────────────────────────────────────────────────────┐\n│                   mova-flat-runner (MCP Server)                  │\n├─────────────────────────────────────────────────────────────────┤\n│  ┌──────────────┐  ┌──────────────┐  ┌───────────────────────┐  │\n│  │  HTTP Handler │  │  Tool Router  │  │   Security Guards    │  │\n│  └──────────────┘  └──────────────┘  └───────────────────────┘  │\n├─────────────────────────────────────────────────────────────────┤\n│  ┌──────────────────┐    ┌──────────────────────────────────┐  │\n│  │  Local Seam Bridge │    │       Remote API Transport       │  │\n│  └──────────────────┘    └──────────────────────────────────┘  │\n└─────────────────────────────┬───────────────────────────────────┘\n          ┌───────────────────┼───────────────────┐\n          ▼                   ▼                   ▼\n   ┌─────────────┐     ┌─────────────┐     ┌─────────────┐\n   │  Local JS   │     │  MOVA API   │     │  Contract   │\n   │  Execution  │     │  (Remote)   │     │  Registry   │\n   └─────────────┘     └─────────────┘     └─────────────┘\n```\n\n资料来源：[README.md:25-45]()\n\n### 核心目录结构\n\n| 目录/文件 | 用途 |\n|-----------|------|\n| `cmd/` | 应用程序入口点 |\n| `internal/api/` | HTTP 处理器和路由 |\n| `internal/auth/` | 认证模块（GitHub OAuth、JWT、命名空间阻塞） |\n| `internal/config/` | 配置管理 |\n| `internal/database/` | 数据持久化（PostgreSQL） |\n| `internal/service/` | 业务逻辑层 |\n| `internal/telemetry/` | 指标和监控 |\n| `internal/validators/` | 输入验证 |\n| `pkg/` | 公共包 |\n| `deploy/` | Pulumi 部署配置 |\n| `docs/` | 文档 |\n\n资料来源：[README.md:28-40]()\n\n## 可用工具\n\nMCP 服务器暴露以下工具集：\n\n### 工具列表\n\n| 工具名称 | 功能描述 |\n|----------|----------|\n| `mova_health` | 健康检查，验证 MOVA API 可用性 |\n| `mova_registry` | 查询契约注册表，获取可用契约清单 |\n| `mova_run` | 执行标准契约流程 |\n| `mova_query` | 查询契约执行状态、审计记录 |\n| `mova_decide` | 处理决策请求 |\n| `mova_connector` | 管理外部系统连接 |\n| `mova_contract` | 契约生命周期管理（注册、运行、状态查询） |\n\n资料来源：[README.md:95-102]()\n\n### mova_contract 子命令\n\n`mova_contract` 工具支持以下子命令：\n\n| 子命令 | HTTP 方法 | 端点 | 说明 |\n|--------|-----------|------|------|\n| `register` | POST | `/api/v1/contracts/register` | 注册新契约 |\n| `run` | POST | `/run/{contract_id}` | 执行契约 |\n| `run_status` | GET | `/run/{run_id}/status` | 获取运行状态 |\n| `step_complete` | POST | `/run/{run_id}/step/{step_id}/complete` | 步骤完成确认 |\n| `gate_approve` | POST | `/run/{run_id}/step/{step_id}/gate/approve` | 人为门审批 |\n| `gate_reject` | POST | `/run/{run_id}/step/{step_id}/gate/reject` | 人为门拒绝 |\n\n资料来源：[src/index.ts:120-175]()\n\n## 安全机制\n\n### 步骤模式守卫\n\n项目实现了严格的步骤执行模式验证，防止配置错误：\n\n```typescript\n// 步骤执行模式与必需字段校验\nif (mode === \"AI_ATOMIC\" && asStr(step.model) === null) {\n    // AI_ATOMIC 模式必须指定 model 字段\n}\nif (mode === \"CONTRACT_CALL\" && asStr(step.contract_id) === null) {\n    // CONTRACT_CALL 模式必须指定 contract_id\n}\nif (mode === \"HUMAN_GATE\" && !Array.isArray(step.decision_options)) {\n    // HUMAN_GATE 模式必须指定 decision_options 数组\n}\n```\n\n资料来源：[src/security/step_mode_guard.ts:35-55]()\n\n### 类定义守卫\n\n禁止在流程中内联类定义字段，确保安全边界：\n\n```typescript\nconst FORBIDDEN_FLOW_KEYS = [\n  \"class_definition_inline\",\n  \"class_def_override\",\n  \"class_def\",\n];\n```\n\n资料来源：[src/security/step_mode_guard.ts:8-13]()\n\n### 人为门验证\n\n`step_complete` 操作不能用于 HUMAN_GATE 类型步骤，必须使用专用的 `gate_approve` / `gate_reject` 路径：\n\n资料来源：[src/index.ts:130-145]()\n\n## 包验证系统\n\n### 全局文件验证\n\n`validatePackageGlobalShape` 函数验证包全局配置的合法性：\n\n| 验证项 | 规则 |\n|--------|------|\n| `global_id` | 必需字符串，非空 |\n| `version` | 必需字符串，非空 |\n| `scope` | 必须为 `\"contract_package\"` |\n| `extends` | 若存在，必须为数组 |\n| `semantic_roles` | 非空数组，每个元素为对象 |\n\n资料来源：[src/package_support.ts:15-35]()\n\n### 语义角色字段验证\n\n`semantic_roles` 数组中的每个元素必须包含以下字段：\n\n| 字段 | 类型 | 必需 |\n|------|------|------|\n| `id` | string | 是 |\n| `role` | string | 是 |\n| `authority` | string | 是 |\n| `maturity` | string | 是 |\n| `applies_to` | array | 否 |\n| `allowed_use` | array | 是 |\n| `forbidden_use` | array | 是 |\n| `notes` | string | 否 |\n\n资料来源：[dist-test/src/package_support.js:12-20]()\n\n## 本地桥接传输\n\n### 本地缝隙解析\n\n`resolveLocalSeamLocator` 处理本地执行环境的路径解析：\n\n```typescript\nconst packagePath = initialInputs.package_path \n    ?? process.env.MOVA_SANDBOX_PACKAGE_PATH \n    ?? \"D:\\\\Projects_MOVA\\\\mova-intent\\\\contracts\\\\dockerfile-nodejs-v1\";\n```\n\n资料来源：[dist-test/src/transports/local_seam_bridge.js:45-50]()\n\n### 桥接输出格式\n\n本地执行返回标准化的桥接响应：\n\n```typescript\nreturn {\n    ok: true,\n    bridge: {\n        ok: true,\n        bridge_source: \"mova_flat_runner_canonical_bridge\",\n        status: \"completed\" | \"advanced\" | \"human_gate_required\",\n        contract_ref: request.contractRef,\n        next_phase: { phase: \"EXECUTION\" | \"WAIT_HUMAN\" },\n        verification_payload: {\n            status: \"PASS\",\n            checks: [{ layer: \"Invariant\", result: \"PASS\" }]\n        }\n    }\n};\n```\n\n资料来源：[src/transports/local_seam_bridge.ts:12-40]()\n\n## 自定义契约桥接\n\n### 问题背景\n\n自定义契约（`local-*`、`remote-*` 前缀）在 `/run/*` 命名空间执行时，可能在 `/api/v1/contracts/*` 查询命名空间中不可见，导致 `mova_query` 返回 404。\n\n资料来源：[tasks/task061.md:1-10]()\n\n### 解决方案\n\n实现了内存桥接映射来维护 `contract_id -> run_id` 关系：\n\n```typescript\n// 内存桥接映射\nconst CUSTOM_RUN_BRIDGE = new Map<contract_id, { run_id, updated_at, source_url? }>();\n\n// 在 run 和 run_status 时捕获映射\nfunction rememberCustomRun(contractId, runId, sourceUrl) {\n    CUSTOM_RUN_BRIDGE.set(contractId, { \n        run_id: runId, \n        updated_at: new Date().toISOString(),\n        source_url \n    });\n}\n\n// 在 mova_query 404 时探测契约元数据\nasync function getMyContractRecord(config, contractId) {\n    const list = await movaGet(config, \"/api/v1/contracts/my\");\n    return list.contracts.find(item => item.contract_id === contractId);\n}\n```\n\n资料来源：[src/index.ts:75-95]()\n\n### 桥接状态响应\n\n当检测到自定义契约时，`mova_query status` 返回桥接状态：\n\n```json\n{\n    \"ok\": true,\n    \"bridge_mode\": \"custom_contract_run_namespace_bridge_v1\",\n    \"contract_record\": { ... },\n    \"run_ref\": \"run-xxx\",\n    \"run_status\": { ... }\n}\n```\n\n资料来源：[tasks/task061.md:18-28]()\n\n## 远程 API 传输\n\n### 步骤执行流程\n\n远程执行按顺序执行三个核心步骤：\n\n```mermaid\ngraph TD\n    A[开始] --> B[POST /api/v1/contracts/{id}/step - analyze]\n    B --> C{成功?}\n    C -->|否| D[返回错误]\n    C -->|是| E[GET /api/v1/contracts/{id}/steps/analyze/output]\n    E --> F[POST /api/v1/contracts/{id}/step - verify]\n    F --> G{成功?}\n    G -->|否| D\n    G -->|是| H[POST /api/v1/contracts/{id}/step - decide]\n    H --> I{结果等待?}\n    I -->|waiting_human| J[获取 decision_point]\n    I -->|completed| K[返回完成状态]\n    J --> K\n```\n\n资料来源：[dist-test/src/transports/remote_api.js:30-80]()\n\n### 验证器集成\n\n分析步骤后，系统会执行验证器注册表中的验证器：\n\n```typescript\nfor (const validator of validators) {\n    const fn = VALIDATOR_REGISTRY.get(validator.validator_id);\n    if (!fn) {\n        analysis[`${validator.step_id}_error`] = `VALIDATOR_NOT_ALLOWED: \"${validator.validator_id}\" not in registry`;\n        continue;\n    }\n    const resultValue = fn(validatorContext);\n    Object.assign(analysis, resultValue.value ?? {});\n}\n```\n\n资料来源：[dist-test/src/transports/remote_api.js:15-30]()\n\n## 环境配置\n\n### 必需环境变量\n\n| 变量名 | 说明 | 示例值 |\n|--------|------|--------|\n| `MOVA_API_URL` | MOVA API 端点 | `https://api.mova-lab.eu` |\n| `MOVA_API_KEY` | API 认证密钥 | `__SET_MOVA_API_KEY__` |\n| `LLM_KEY` | LLM 提供商密钥 | `__SET_LLM_KEY__` |\n| `LLM_MODEL` | LLM 模型标识 | `openai/gpt-4o-mini` |\n\n### 可选环境变量\n\n| 变量名 | 说明 | 默认值 |\n|--------|------|--------|\n| `MOVA_API_TIMEOUT_MS` | API 超时时间（毫秒） | `30000` |\n| `MOVA_HTTP_PORT` | 本地 HTTP 模式端口 | `3796` |\n| `MOVA_INVOKE_TOKEN` | 本地调用令牌 | - |\n| `MOVA_SANDBOX_PACKAGE_PATH` | 本地沙箱包路径 | - |\n| `MOVA_SANDBOX_PROJECT_PATH` | 本地沙箱项目路径 | - |\n\n资料来源：[README.md:55-80]()\n\n### Claude Desktop 配置示例\n\n```json\n{\n  \"mcpServers\": {\n    \"mova\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@leryk1981/mova-flat-runner@3.3.3\"],\n      \"env\": {\n        \"MOVA_API_URL\": \"https://api.mova-lab.eu\",\n        \"MOVA_API_KEY\": \"__SET_MOVA_API_KEY__\",\n        \"LLM_KEY\": \"__SET_LLM_KEY__\",\n        \"LLM_MODEL\": \"openai/gpt-4o-mini\"\n      }\n    }\n  }\n}\n```\n\n资料来源：[README.md:85-100]()\n\n## 公共输出清理\n\n`sanitizePublicShape` 函数确保内部字段不会泄漏到公共 API 响应中：\n\n```typescript\nfunction sanitizePublicShape(value) {\n    for (const [key, child] of Object.entries(value)) {\n        if ([\"bridge_anchors\", \"last_terminal_bridge\", \"terminal_commit_count\", \n             \"_state15_bridge\", \"trace\", \"outputs\", \"context\"].includes(key)) {\n            return false;\n        }\n        // 递归检查\n    }\n    return true;\n}\n```\n\n资料来源：[src/transports/local_seam_bridge.ts:65-80]()\n\n## 开发与发布\n\n### 构建命令\n\n| 命令 | 说明 |\n|------|------|\n| `make check` | 运行 lint、单元测试和集成测试 |\n| `make publisher` | 构建 MCP 发布工具 |\n| `make help` | 查看所有可用命令 |\n\n### 发布流程\n\n项目使用 MCP Publisher 工具进行服务器发布：\n\n```bash\n# 构建发布工具\nmake publisher\n\n# 使用发布工具\n./bin/mcp-publisher --help\n```\n\n资料来源：[README.md:15-25]()\n\n### 构建状态\n\n| 分支 | 说明 |\n|------|------|\n| `main` | 最新主分支构建（稳定版） |\n| `main-<date>-<sha>` | 特定提交构建（开发版） |\n\n资料来源：[README.md:3-6]()\n\n## 安全注意事项\n\n> ⚠️ 切勿提交真实的 `MOVA_API_KEY`、`LLM_KEY` 或 `MOVA_INVOKE_TOKEN`。MCP 注册表会向 MCP 客户端提供服务器列表，如同一个 MCP 服务器的应用商店。\n\n资料来源：[README.md:105-106]()\n\n---\n\n<a id='page-installation'></a>\n\n## 安装与配置\n\n### 相关页面\n\n相关主题：[项目介绍](#page-introduction), [部署与运维](#page-deployment)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n- [package.json](https://github.com/mova-compact/mova-flat-runner/blob/main/package.json)\n- [src/index.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/index.ts)\n- [smithery.yaml](https://github.com/mova-compact/mova-flat-runner/blob/main/smithery.yaml)\n- [server.json](https://github.com/mova-compact/mova-flat-runner/blob/main/server.json)\n</details>\n\n# 安装与配置\n\n## 概述\n\n`mova-flat-runner` 是一个基于 Model Context Protocol (MCP) 的服务器，用于执行受治理的 AI 工作流程。该项目支持发票 OCR、AML 分类、信贷审查以及带有人工审批环节的自定义合约执行，并提供完整的审计追踪功能。\n\n资料来源：[package.json:3-4]()\n\n## 安装方式\n\n### 通过 npm 安装（推荐）\n\n使用 npx 直接运行，无需全局安装：\n\n```bash\nnpx -y @leryk1981/mova-flat-runner@3.3.3\n```\n\n### 手动构建安装\n\n从源码构建：\n\n```bash\ngit clone https://github.com/mova-compact/mova-flat-runner.git\ncd mova-flat-runner\nnpm install\nnpm run build\n```\n\n构建产物位于 `dist/` 目录，可执行文件为 `mova-mcp`。\n\n资料来源：[README.md:54](), [package.json:23]()\n\n## 环境变量配置\n\n### 必须配置的环境变量\n\n| 变量名 | 说明 | 示例值 |\n|--------|------|--------|\n| `MOVA_API_URL` | MOVA API 服务地址 | `https://api.mova-lab.eu` |\n| `MOVA_API_KEY` | MOVA API 访问密钥 | `__SET_MOVA_API_KEY__` |\n| `LLM_KEY` | LLM 服务密钥 | `__SET_LLM_KEY__` |\n| `LLM_MODEL` | 使用的 LLM 模型 | `openai/gpt-4o-mini` |\n\n资料来源：[README.md:35-39]()\n\n### 可选环境变量（本地 HTTP 模式）\n\n| 变量名 | 说明 | 默认值 |\n|--------|------|--------|\n| `MOVA_API_TIMEOUT_MS` | API 请求超时时间（毫秒） | `30000` |\n| `MOVA_HTTP_PORT` | 本地 HTTP 服务端口 | `3796` |\n| `MOVA_INVOKE_TOKEN` | 本地调用令牌 | 无默认值 |\n\n资料来源：[README.md:44-46]()\n\n## MCP 客户端集成配置\n\n### Claude Desktop 配置\n\n在 `claude_desktop_config.json` 中添加以下配置：\n\n```json\n{\n  \"mcpServers\": {\n    \"mova\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@leryk1981/mova-flat-runner@3.3.3\"],\n      \"env\": {\n        \"MOVA_API_URL\": \"https://api.mova-lab.eu\",\n        \"MOVA_API_KEY\": \"__SET_MOVA_API_KEY__\",\n        \"LLM_KEY\": \"__SET_LLM_KEY__\",\n        \"LLM_MODEL\": \"openai/gpt-4o-mini\"\n      }\n    }\n  }\n}\n```\n\n资料来源：[README.md:62-73]()\n\n### Codex 配置\n\n在 `codex_config.json` 中添加以下配置：\n\n```json\n{\n  \"mcp_servers\": {\n    \"mova\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@leryk1981/mova-flat-runner@3.3.3\"],\n      \"startup_timeout_sec\": 90.0,\n      \"env\": {\n        \"MOVA_API_URL\": \"https://api.mova-lab.eu\",\n        \"MOVA_API_KEY\": \"__SET_MOVA_API_KEY__\",\n        \"LLM_KEY\": \"__SET_LLM_KEY__\",\n        \"LLM_MODEL\": \"openai/gpt-4o-mini\"\n      }\n    }\n  }\n}\n```\n\n### TOML 格式配置\n\n```toml\n[mcp_servers.mova]\ncommand = \"npx\"\nargs = [\"-y\", \"@leryk1981/mova-flat-runner@3.3.3\"]\nstartup_timeout_sec = 90.0\n\n[mcp_servers.mova.env]\nMOVA_API_URL = \"https://api.mova-lab.eu\"\nMOVA_API_KEY = \"__SET_MOVA_API_KEY__\"\nLLM_KEY = \"__SET_LLM_KEY__\"\nLLM_MODEL = \"openai/gpt-4o-mini\"\n```\n\n资料来源：[README.md:75-97]()\n\n## 服务健康检查\n\n部署完成后，可通过以下命令验证服务可用性：\n\n```bash\ncurl -sS https://api.mova-lab.eu/health\n```\n\n资料来源：[README.md:55-57]()\n\n## 可用工具列表\n\n配置完成后，MCP 服务器提供以下工具：\n\n| 工具名称 | 功能说明 |\n|----------|----------|\n| `mova_health` | 服务健康检查 |\n| `mova_registry` | 查看合约注册表 |\n| `mova_run` | 执行内置工作流程合约 |\n| `mova_query` | 查询合约状态和审计信息 |\n| `mova_decide` | 触发决策流程 |\n| `mova_connector` | 连接器管理 |\n| `mova_contract` | 自定义合约注册与执行 |\n\n资料来源：[README.md:99-107]()\n\n## 安全注意事项\n\n⚠️ **重要提示**：请勿将真实的 `MOVA_API_KEY`、`LLM_KEY` 或 `MOVA_INVOKE_TOKEN` 提交到版本控制系统。\n\n环境变量占位符使用说明：\n\n- 在文档中使用 `__SET_MOVA_API_KEY__` 等占位符\n- 在本地配置中使用真实的密钥值\n- 确保配置文件已添加到 `.gitignore`\n\n资料来源：[README.md:47-49]()\n\n## 配置架构图\n\n```mermaid\ngraph TD\n    A[MCP Client] -->|npx启动| B[mova-flat-runner]\n    B -->|环境变量| C[MovaConfig]\n    C -->|API调用| D[MOVA API Server]\n    D -->|状态/结果| B\n    B -->|工具响应| A\n    \n    C -->|必需变量| E[MOVA_API_URL]\n    C -->|必需变量| F[MOVA_API_KEY]\n    C -->|必需变量| G[LLM_KEY]\n    C -->|必需变量| H[LLM_MODEL]\n    \n    C -->|可选变量| I[MOVA_API_TIMEOUT_MS]\n    C -->|可选变量| J[MOVA_HTTP_PORT]\n    C -->|可选变量| K[MOVA_INVOKE_TOKEN]\n```\n\n## 开发命令\n\n项目提供以下 Makefile 目标用于开发：\n\n| 命令 | 说明 |\n|------|------|\n| `make check` | 运行代码检查、单元测试和集成测试 |\n| `make publisher` | 构建 MCP 发布工具 |\n| `make help` | 查看所有可用命令 |\n\n资料来源：[README.md:29-34]()\n\n## 验证安装\n\n安装完成后，可通过执行以下步骤验证配置是否正确：\n\n1. 检查 MCP 客户端是否成功连接\n2. 调用 `mova_health` 工具验证 API 连通性\n3. 尝试调用 `mova_registry` 查看合约列表\n\n如遇到问题，请检查：\n\n- 环境变量是否正确设置\n- API URL 是否可访问\n- API 密钥是否有效\n\n---\n\n<a id='page-core-concepts'></a>\n\n## 核心概念\n\n### 相关页面\n\n相关主题：[系统架构](#page-system-architecture), [可用工具集](#page-available-tools)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/index.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/index.ts)\n- [src/types.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/types.ts)\n- [src/schemas.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/schemas.ts)\n- [src/security/step_mode_guard.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/security/step_mode_guard.ts)\n- [src/transports/local_seam_bridge.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/local_seam_bridge.ts)\n- [src/package_support.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/package_support.ts)\n- [src/transports/remote_api.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/remote_api.ts)\n</details>\n\n# 核心概念\n\n本文档介绍 mova-flat-runner（MCP 服务器）的核心架构概念，帮助开发者理解系统的工作原理、设计决策和安全机制。\n\n## 系统概述\n\nmova-flat-runner 是一个基于 **Model Context Protocol (MCP)** 的服务器实现，用于托管治理型 AI 工作流。系统支持合同执行、人工审批门控、审计追踪等功能。\n\n**核心能力：**\n\n- 内置合同类型（发票 OCR、反洗钱审查、信用审查、投诉处理）\n- 自定义合同注册与执行\n- 人工干预门控（HUMAN_GATE）\n- 多步骤执行模式验证\n- 本地沙箱执行与远程 API 调用双路径\n\n资料来源：[package.json](https://github.com/mova-compact/mova-flat-runner/blob/main/package.json)\n\n---\n\n## MCP 工具接口\n\nMCP 服务器暴露一组标准化工具，供 AI 客户端调用。工具通过 `executeTool` 函数统一分发。资料来源：[src/index.ts:79-450]()\n\n### 可用工具列表\n\n| 工具名称 | 功能描述 | 主要参数 |\n|---------|---------|---------|\n| `mova_health` | 健康检查 | 无 |\n| `mova_registry` | 获取注册合同列表 | 无 |\n| `mova_run` | 执行内置合同 | `contract_type`, `inputs` |\n| `mova_query` | 查询合同状态/审计 | `contract_id`, `view` |\n| `mova_decide` | 执行决策步骤 | `contract_id`, `step_id`, `choice` |\n| `mova_contract` | 自定义合同管理 | `action`, `contract_id` 等 |\n| `mova_connector` | 连接器操作 | `action`, `connector_id` |\n\n资料来源：[src/index.ts:79-100]()\n\n### mova_query 视图模式\n\n`mova_query` 支持三种视图模式：\n\n| 视图模式 | 用途 | 返回内容 |\n|---------|------|---------|\n| `status` | 状态查询 | 合同执行状态、当前步骤、运行引用 |\n| `audit` | 完整审计 | 结构化审计记录 |\n| `audit_compact` | 紧凑审计 | 最小化审计摘要 |\n\n资料来源：[tasks/task061.md]()\n\n---\n\n## 合同类型与执行模式\n\n### 内置合同类型\n\n系统预置以下合同类型：\n\n| 合同类型 | 用途 | 执行模式 |\n|---------|------|---------|\n| `complaint` | 投诉处理 | 远程 API |\n| `invoice-ocr` | 发票 OCR 识别 | 本地/远程 |\n| `aml-triage` | 反洗钱审查 | 混合模式 |\n| `credit-review` | 信用审查 | AI_ATOMIC |\n\n资料来源：[src/index.ts:81-120]()\n\n### 执行模式（Step Execution Mode）\n\n合同流程由多个步骤组成，每步骤有独立的执行模式：\n\n```mermaid\ngraph TD\n    A[Step] --> B{执行模式判定}\n    B --> C[DETERMINISTIC]\n    B --> D[AI_ATOMIC]\n    B --> E[CONTRACT_CALL]\n    B --> F[HUMAN_GATE]\n    \n    C --> C1[本地 JS 校验]\n    D --> D1[LLM 调用]\n    E --> E1[调用其他合同]\n    F --> F1[等待人工审批]\n```\n\n| 执行模式 | 说明 | 必需字段 | 安全约束 |\n|---------|------|---------|---------|\n| `DETERMINISTIC` | 本地确定性校验 | 无特殊要求 | 禁止声明 `model` 字段 |\n| `AI_ATOMIC` | LLM 原子操作 | `model` | 必须声明 `model` |\n| `CONTRACT_CALL` | 跨合同调用 | `contract_id` | 被调用合同必须存在 |\n| `HUMAN_GATE` | 人工审批门控 | `decision_options` | 需要 `gate_approve` / `gate_reject` |\n\n资料来源：[src/security/step_mode_guard.ts:1-80]()\n\n### 执行模式验证规则\n\n`step_mode_guard.ts` 实现以下验证：\n\n```typescript\n// DETERMINISTIC 禁止使用 model\nif (mode === \"DETERMINISTIC\" && step.model !== undefined) {\n  violations.push({ kind: \"deterministic_with_model\", ... });\n}\n\n// AI_ATOMIC 必须声明 model\nif (mode === \"AI_ATOMIC\" && asStr(step.model) === null) {\n  violations.push({ kind: \"ai_atomic_without_model\", ... });\n}\n\n// CONTRACT_CALL 必须指定 contract_id\nif (mode === \"CONTRACT_CALL\" && asStr(step.contract_id) === null) {\n  violations.push({ kind: \"contract_call_without_contract_id\", ... });\n}\n\n// HUMAN_GATE 必须声明决策选项\nif (mode === \"HUMAN_GATE\" && !Array.isArray(step.decision_options)) {\n  violations.push({ kind: \"human_gate_without_decisions\", ... });\n}\n```\n\n资料来源：[src/security/step_mode_guard.ts:20-60]()\n\n---\n\n## 人工干预门控（HUMAN_GATE）\n\n### 工作流程\n\n```mermaid\nsequenceDiagram\n    participant Client\n    participant MCP\n    participant API\n    participant Human\n    \n    Client->>MCP: mova_run (含 HUMAN_GATE)\n    MCP->>API: 启动合同执行\n    API-->>MCP: status=waiting_human\n    MCP-->>Client: 返回待审批状态\n    \n    Client->>MCP: mova_decide (choice)\n    MCP->>API: /decision\n    API->>Human: 通知待审批\n    Human-->>API: 审批结果\n    API-->>MCP: 继续执行\n    MCP-->>Client: 执行完成\n```\n\n### 安全约束\n\n`step_complete` 操作在 HUMAN_GATE 步骤上被禁止执行：\n\n```typescript\nconst gateGuard = await assertNotHumanGate(\n  config, \n  args.run_id, \n  args.step_id, \n  requestId\n);\nif (gateGuard) return gateGuard;\n```\n\nHUMAN_GATE 必须通过专用路径完成审批：\n\n- `gate_approve` - 批准当前步骤\n- `gate_reject` - 拒绝当前步骤\n\n资料来源：[src/index.ts:180-200]()\n\n---\n\n## 自定义合同桥接机制\n\n### 问题背景\n\n自定义合同使用 `/run/*` 命名空间执行，但查询时可能返回 404（合同不存在于 `/api/v1/contracts/*` 命名空间）。资料来源：[tasks/task061.md]()\n\n### 桥接解决方案\n\n```mermaid\ngraph LR\n    A[自定义合同注册] --> B[CUSTOM_RUN_BRIDGE]\n    C[mova_run] --> B\n    D[run_status] --> B\n    \n    B --> E{contract_id 映射}\n    \n    E --> F[存在映射?]\n    F -->|是| G[返回 bridged status]\n    F -->|否| H[返回 404]\n    \n    G --> I[probe /api/v1/contracts/my]\n    I --> J[返回结构化响应]\n```\n\n### 内存桥接映射\n\n```typescript\nconst CUSTOM_RUN_BRIDGE: Map<contract_id, {\n  run_id: string,\n  updated_at: string,\n  source_url?: string\n}> = new Map();\n```\n\n关键函数：\n\n| 函数 | 用途 |\n|------|------|\n| `rememberCustomRun` | 缓存 contract_id → run_id 映射 |\n| `getMyContractRecord` | 查询 /api/v1/contracts/my 获取元数据 |\n\n资料来源：[src/index.ts:40-65]()\n\n### 桥接响应格式\n\n```json\n{\n  \"ok\": true,\n  \"bridge_mode\": \"custom_contract_run_namespace_bridge_v1\",\n  \"contract_record\": { ... },\n  \"run_ref\": \"run-xxx\",\n  \"run_status\": { ... }\n}\n```\n\n---\n\n## 包结构验证\n\n### 包文件类型\n\n| 文件类型 | 用途 | 验证内容 |\n|---------|------|---------|\n| `global` | 全局元数据 | 合同包范围、语义角色 |\n| `manifest` | 包清单 | schema_id、引用关系 |\n| `flow` | 流程定义 | 步骤、执行模式 |\n\n资料来源：[src/package_support.ts:1-150]()\n\n### Global 文件验证\n\n```typescript\nconst allowedKeys = new Set([\n  \"schema_id\", \"global_id\", \"version\", \"scope\",\n  \"extends\", \"semantic_roles\", \"non_authority_rules\"\n]);\n\n// 必需字段\n- schema_id: \"mova.contract.global.v1\"\n- global_id: 非空字符串\n- version: 非空字符串\n- scope: \"contract_package\"\n- semantic_roles: 非空数组\n```\n\n资料来源：[src/package_support.ts:60-100]()\n\n### Manifest 文件验证\n\n```typescript\nconst allowedKeys = new Set([\n  \"schema_id\", \"package_id\", \"version\", \"global_ref\",\n  \"flow_ref\", \"classification_policy_ref\",\n  \"classification_result_set_ref\", \"classification_result_refs\",\n  \"runtime_binding_set_ref\", \"model_refs\", \"fixture_refs\",\n  \"package_invariants\"\n]);\n```\n\n---\n\n## API 传输层\n\n### 请求方法\n\n```typescript\nexport const movaGet    = (config, path) => movaRequest(config, \"GET\", path);\nexport const movaPost   = (config, path, body) => movaRequest(config, \"POST\", path, body);\nexport const movaPut    = (config, path, body) => movaRequest(config, \"PUT\", path, body);\nexport const movaDelete = (config, path) => movaRequest(config, \"DELETE\", path);\n```\n\n资料来源：[src/transports/remote_api.ts:1-50]()\n\n### 远程执行流程\n\n```mermaid\ngraph TD\n    A[movaRunStepsRemote] --> B[analyze 步骤]\n    B --> C{result.ok?}\n    C -->|是| D[verify 步骤]\n    C -->|否| E[返回错误]\n    D --> F{status?}\n    F -->|waiting_human| G[返回待审批]\n    F -->|completed| H[decide 步骤]\n    H --> I[返回结果]\n```\n\n---\n\n## 配置管理\n\n### 环境变量\n\n| 变量名 | 必需 | 默认值 | 说明 |\n|-------|------|-------|------|\n| `MOVA_API_URL` | 是 | - | API 基础地址 |\n| `MOVA_API_KEY` | 是 | - | API 认证密钥 |\n| `LLM_KEY` | 是 | - | LLM 提供商密钥 |\n| `LLM_MODEL` | 是 | `openai/gpt-4o-mini` | LLM 模型标识 |\n| `MOVA_API_TIMEOUT_MS` | 否 | 30000 | 请求超时（毫秒） |\n| `MOVA_HTTP_PORT` | 否 | 3796 | 本地 HTTP 模式端口 |\n| `MOVA_INVOKE_TOKEN` | 否 | - | 本地调用令牌 |\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n### MovaConfig 类型\n\n```typescript\ninterface MovaConfig {\n  apiUrl: string;\n  apiKey: string;\n  llmKey: string;\n  llmModel: string;\n  timeoutMs?: number;\n  httpPort?: number;\n  invokeToken?: string;\n}\n```\n\n---\n\n## 错误处理\n\n### 错误代码体系\n\n| 错误代码 | HTTP 等价 | 说明 |\n|---------|----------|------|\n| `UNKNOWN_CONTRACT_TYPE` | 400 | 合同类型未注册 |\n| `LOCAL_VALIDATION_FAILED` | 400 | 本地验证失败 |\n| `API_REQUEST_FAILED` | 502 | 后端 API 请求失败 |\n| `STEP_MODE_FIELD_MISMATCH` | 400 | 执行模式字段不匹配 |\n| `CONTRACT_NOT_FOUND` | 404 | 合同不存在 |\n\n### 标准错误响应格式\n\n```json\n{\n  \"ok\": false,\n  \"error\": {\n    \"code\": \"ERROR_CODE\",\n    \"message\": \"人类可读的错误描述\",\n    \"details\": { ... },\n    \"request_id\": \"req-xxx\"\n  }\n}\n```\n\n---\n\n## 安全机制\n\n### 步骤模式守卫（Step Mode Guard）\n\n```mermaid\ngraph TD\n    A[执行步骤] --> B[findStepModeViolations]\n    B --> C{违规数量}\n    C -->|0| D[执行通过]\n    C -->|>0| E[返回 400 错误]\n    \n    D --> F[assertStepModesValid]\n    F --> G[继续执行]\n```\n\n核心安全检查：\n\n1. **DETERMINISTIC 模式**：禁止声明 LLM model 字段\n2. **AI_ATOMIC 模式**：必须声明 model 字段\n3. **CONTRACT_CALL 模式**：必须指定 target contract_id\n4. **HUMAN_GATE 模式**：禁止绕过专用审批路径\n\n资料来源：[src/security/step_mode_guard.ts:80-110]()\n\n### 公共形状清理（sanitizePublicShape）\n\n过滤内部字段，确保审计响应不暴露实现细节：\n\n```typescript\nconst BLOCKED_KEYS = [\n  \"bridge_anchors\",\n  \"last_terminal_bridge\",\n  \"terminal_commit_count\",\n  \"_state15_bridge\",\n  \"trace\",\n  \"outputs\",\n  \"context\"\n];\n```\n\n---\n\n## MCP 资源端点\n\n| URI | 内容 |\n|-----|------|\n| `mova://registry` | 注册合同清单 |\n| `mova://schemas/envelopes` | 信封 JSON Schema |\n| `mova://contracts/{type}/manifest` | 指定合同类型的清单 |\n\n---\n\n## 快速开始\n\n### Claude Desktop 配置\n\n```json\n{\n  \"mcpServers\": {\n    \"mova\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@leryk1981/mova-flat-runner@3.3.3\"],\n      \"env\": {\n        \"MOVA_API_URL\": \"https://api.mova-lab.eu\",\n        \"MOVA_API_KEY\": \"__SET_MOVA_API_KEY__\",\n        \"LLM_KEY\": \"__SET_LLM_KEY__\",\n        \"LLM_MODEL\": \"openai/gpt-4o-mini\"\n      }\n    }\n  }\n}\n```\n\n### 健康检查\n\n```bash\ncurl -sS https://api.mova-lab.eu/health\n\n---\n\n<a id='page-system-architecture'></a>\n\n## 系统架构\n\n### 相关页面\n\n相关主题：[传输层](#page-transport-layer), [安全模块](#page-security-module), [核心概念](#page-core-concepts)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/index.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/index.ts)\n- [src/transports/local_seam_bridge.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/local_seam_bridge.ts)\n- [src/transports/remote_api.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/remote_api.ts)\n- [src/security/step_mode_guard.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/security/step_mode_guard.ts)\n- [src/package_support.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/package_support.ts)\n- [src/types.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/types.ts)\n</details>\n\n# 系统架构\n\n## 概述\n\nmova-flat-runner 是 MOVA 平台的 MCP（Model Context Protocol）服务器实现，为 MCP 客户端（如 Claude Desktop、Cursor）提供受治理的 AI 工作流执行能力。该系统支持发票 OCR、AML 审查、信贷审核等业务流程，并内置人工审批门（Human Approval Gates）和完整的审计追踪机制。\n\n资料来源：[package.json:1-20]()\n\n## 整体架构\n\n### 核心定位\n\n该系统作为 MCP 协议的服务端实现，运行于 Node.js 18+ 环境，通过 MCP 协议暴露一组标准化的工具（Tools），供 AI 代理调用。工作流程执行可以采用本地执行或远程 API 调用两种模式。\n\n资料来源：[src/index.ts:1-50]()\n\n```mermaid\ngraph TD\n    subgraph MCP客户端层\n        A[Claude Desktop] -->|MCP Protocol| B[mova-mcp Server]\n        C[Cursor] -->|MCP Protocol| B\n    end\n    \n    subgraph 服务端核心\n        B -->|executeTool| D[工具调度器]\n        D --> E[本地执行路径]\n        D --> F[远程 API 路径]\n    end\n    \n    subgraph 本地执行\n        E --> G[step_mode_guard]\n        G --> H[Local Seam Bridge]\n    end\n    \n    subgraph 远程执行\n        F --> I[remote_api]\n        I --> J[MOVA Backend API]\n    end\n    \n    subgraph 安全层\n        G --> K[验证器注册表]\n        H --> L[Bridge 状态管理]\n    end\n```\n\n## 模块划分\n\n### 项目结构\n\n```\nmova-flat-runner/\n├── cmd/                     # 应用入口点\n├── src/                     # TypeScript 源码\n│   ├── index.ts             # MCP 服务器主入口\n│   ├── types.ts             # 类型定义\n│   ├── client.ts            # MCP 协议客户端\n│   ├── package_support.ts   # 合约包支持\n│   ├── schemas.ts           # JSON Schema 定义\n│   ├── transports/          # 传输层\n│   │   ├── local_seam_bridge.ts   # 本地接缝桥接器\n│   │   └── remote_api.ts          # 远程 API 客户端\n│   └── security/            # 安全模块\n│       └── step_mode_guard.ts     # 步骤模式守卫\n├── internal/                # 内部应用代码\n└── pkg/                     # 公共包\n```\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n### 核心组件表\n\n| 组件 | 文件路径 | 职责 |\n|------|----------|------|\n| MCP 服务器入口 | `src/index.ts` | 工具注册、请求路由、响应序列化 |\n| 工具调度器 | `src/index.ts:executeTool` | 根据工具名称分发请求 |\n| 本地执行引擎 | `src/transports/local_seam_bridge.ts` | 本地工作流执行与状态管理 |\n| 远程 API 客户端 | `src/transports/remote_api.ts` | 与 MOVA 后端 API 交互 |\n| 安全守卫 | `src/security/step_mode_guard.ts` | 执行模式验证与字段一致性检查 |\n| 包验证器 | `src/package_support.ts` | 合约包结构与语义角色验证 |\n\n资料来源：[src/index.ts:100-200](), [src/transports/local_seam_bridge.ts](), [src/security/step_mode_guard.ts]()\n\n## 传输层架构\n\n### 双路径执行模式\n\n系统支持两种执行路径，根据配置自动选择：\n\n| 模式 | 触发条件 | 执行位置 | 特点 |\n|------|----------|----------|------|\n| 本地执行 | `MOVA_HTTP_PORT` 环境变量设置 | Node.js 运行时内 | 低延迟、无网络依赖 |\n| 远程执行 | 默认模式 | MOVA Backend API | 集中管理、审计追踪 |\n\n资料来源：[src/transports/remote_api.ts:1-30](), [src/transports/local_seam_bridge.ts:1-50]()\n\n### 远程 API 调用流程\n\n```mermaid\nsequenceDiagram\n    participant MCP as MCP 客户端\n    participant Server as mova-mcp Server\n    participant API as 远程 API\n    \n    MCP->>Server: mova_run\n    Server->>API: POST /api/v1/contracts/{id}/step\n    API-->>Server: Step Result\n    Server->>API: GET /api/v1/contracts/{id}/steps/{step}/output\n    API-->>Server: Analysis Output\n    Server->>API: POST /api/v1/contracts/{id}/step (decide)\n    API-->>Server: Decision Result\n    Server-->>MCP: Complete Response\n```\n\n### 本地桥接器状态机\n\n`local_seam_bridge.ts` 实现了工作流步骤的本地执行与状态转换：\n\n```mermaid\nstateDiagram-v2\n    [*] --> EXECUTION: 启动步骤\n    EXECUTION --> WAIT_HUMAN: HUMAN_GATE 模式\n    WAIT_HUMAN --> EXECUTION: gate_approve\n    EXECUTION --> COMPLETED: terminal_outcome = true\n    EXECUTION --> ADVANCED: 正常完成\n    WAIT_HUMAN --> REJECTED: gate_reject\n```\n\n状态判定逻辑根据 `execution_mode` 和 `humanDecision` 字段确定返回状态：\n\n| 执行模式 | 条件 | 返回状态 |\n|----------|------|----------|\n| AI_ATOMIC | 始终 | `completed` |\n| HUMAN_GATE | `humanDecision == null` | `human_gate_required` |\n| HUMAN_GATE | `humanDecision != null` | `completed` |\n| 其他 | 始终 | `advanced` |\n\n资料来源：[src/transports/local_seam_bridge.ts:20-60]()\n\n## 安全架构\n\n### 步骤模式守卫\n\n`step_mode_guard.ts` 实现了执行模式的字段一致性验证：\n\n```typescript\n// 关键验证规则\nDETERMINISTIC + model 字段 → 警告（DET 步骤不调用 LLM）\nAI_ATOMIC + 无 model 字段 → 警告\nCONTRACT_CALL + 无 contract_id → 违规\nHUMAN_GATE + 无 decision_options → 违规\n```\n\n资料来源：[src/security/step_mode_guard.ts:1-80]()\n\n### 模式验证流程\n\n```mermaid\ngraph TD\n    A[加载 Flow 定义] --> B[遍历每个 Step]\n    B --> C{检查 execution_mode}\n    C -->|DETERMINISTIC| D{model 存在?}\n    C -->|AI_ATOMIC| E{model 存在?}\n    C -->|CONTRACT_CALL| F{contract_id 存在?}\n    C -->|HUMAN_GATE| G{decision_options 存在?}\n    \n    D -->|是| H[记录警告]\n    D -->|否| I[通过]\n    E -->|否| J[记录违规]\n    F -->|否| K[记录违规]\n    G -->|否| L[记录违规]\n    \n    H --> M[返回违规列表]\n    I --> M\n    J --> M\n    K --> M\n    L --> M\n    M -->|违规>0| N[flatErr 400]\n    M -->|违规=0| O[通过验证]\n```\n\n### CFV-3 安全策略\n\n对于 `HUMAN_GATE` 步骤，系统强制使用专用门路径：\n\n- 通用 `step_complete` 调用将被拒绝\n- 必须通过 `gate_approve` 或 `gate_reject` 完成审批\n\n资料来源：[src/index.ts:step_complete case]()\n\n## 数据模型\n\n### 合约包结构\n\n合约包（Contract Package）是工作流的部署单元，包含以下核心文件：\n\n| 文件 | 必需 | 用途 |\n|------|------|------|\n| `_global.json` | 是 | 全局元数据、语义角色定义 |\n| `_manifest.json` | 是 | 包清单、流程引用 |\n| `flow.json` | 是 | 工作流步骤定义 |\n| `_schemas/*.json` | 否 | 输出 Schema 定义 |\n\n资料来源：[src/package_support.ts:1-100]()\n\n### 全局文件验证规则\n\n```json\n{\n  \"schema_id\": \"string (必需)\",\n  \"global_id\": \"string (必需)\",\n  \"version\": \"string (必需)\",\n  \"scope\": \"contract_package (必需)\",\n  \"extends\": \"array (可选)\",\n  \"semantic_roles\": \"array (必需，非空)\",\n  \"non_authority_rules\": \"array (必需，非空)\"\n}\n```\n\n字段验证逻辑：\n\n| 字段 | 验证类型 | 错误消息 |\n|------|----------|----------|\n| `global_id` | 必需字符串 | `global file is missing required string field \"global_id\"` |\n| `version` | 必需字符串 | `global file is missing required string field \"version\"` |\n| `scope` | 枚举值 | `global scope must be \"contract_package\"` |\n| `semantic_roles` | 非空数组 | `global semantic_roles must be a non-empty array` |\n\n资料来源：[dist-test/src/package_support.js:1-50]()\n\n## MCP 工具接口\n\n### 可用工具列表\n\n| 工具名称 | 功能描述 | 主要参数 |\n|----------|----------|----------|\n| `mova_health` | 健康检查 | 无 |\n| `mova_registry` | 获取合约清单 | 无 |\n| `mova_run` | 执行合约 | `contract_type`, `inputs` |\n| `mova_query` | 查询合约状态 | `contract_id`, `view` |\n| `mova_decide` | 提交决策 | `contract_id`, `option_id` |\n| `mova_connector` | 连接器操作 | `action`, `args` |\n| `mova_contract` | 合约管理 | `action`, `package_path` |\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n### 工具执行入口\n\n```typescript\nasync function executeTool(name: string, args: Args): Promise<string> {\n  const requestId = shortId();\n  switch (name) {\n    case \"mova_run\": { /* ... */ }\n    case \"mova_query\": { /* ... */ }\n    case \"mova_decide\": { /* ... */ }\n    case \"gate_approve\": { /* ... */ }\n    case \"gate_reject\": { /* ... */ }\n    case \"step_complete\": { /* ... */ }\n    // ...\n  }\n}\n```\n\n资料来源：[src/index.ts:executeTool]()\n\n## 配置与环境变量\n\n### 必需变量\n\n| 变量名 | 说明 | 示例值 |\n|--------|------|--------|\n| `MOVA_API_URL` | MOVA API 端点 | `https://api.mova-lab.eu` |\n| `MOVA_API_KEY` | API 认证密钥 | `__SET_MOVA_API_KEY__` |\n| `LLM_KEY` | LLM 提供商密钥 | `__SET_LLM_KEY__` |\n| `LLM_MODEL` | LLM 模型标识 | `openai/gpt-4o-mini` |\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n### 可选变量\n\n| 变量名 | 说明 | 默认值 |\n|--------|------|--------|\n| `MOVA_API_TIMEOUT_MS` | API 超时（毫秒） | `30000` |\n| `MOVA_HTTP_PORT` | 本地 HTTP 模式端口 | 未设置（使用远程模式） |\n| `MOVA_INVOKE_TOKEN` | 本地调用令牌 | 无 |\n| `MOVA_SANDBOX_PACKAGE_PATH` | 沙箱包路径 | `contracts/dockerfile-nodejs-v1` |\n| `MOVA_SANDBOX_PROJECT_PATH` | 沙箱项目路径 | 无 |\n\n资料来源：[src/transports/local_seam_bridge.ts:resolveLocalSeamLocator]()\n\n## 自定义合约桥接机制\n\n### 问题背景\n\n自定义合约（`local-*`, `remote-*` 前缀）与内置合约的命名空间分离：\n\n- 运行端点：`/run/{contract_id}`\n- 查询端点：`/api/v1/contracts/{contract_id}`\n\n资料来源：[tasks/task061.md]()\n\n### 桥接解决方案\n\n```mermaid\ngraph LR\n    A[register] -->|POST /contracts/register| B[记录 run_id]\n    B --> C[CUSTOM_RUN_BRIDGE Map]\n    C --> D[run_status]\n    D -->|GET /run/{run_id}/status| E[更新映射]\n    E --> C\n    C --> F[mova_query]\n    F -->|404 时| G{查询 /contracts/my}\n    G -->|找到记录| H[返回 bridged status]\n    G -->|未找到| I[返回 AUDIT_UNAVAILABLE]\n```\n\n### 内存桥接表\n\n```typescript\nconst CUSTOM_RUN_BRIDGE: Map<contract_id, {\n  run_id: string,\n  updated_at: string,\n  source_url?: string\n}>;\n```\n\n桥接函数：\n\n| 函数 | 位置 | 用途 |\n|------|------|------|\n| `rememberCustomRun` | `src/index.ts` | 记录 `contract_id → run_id` 映射 |\n| `getMyContractRecord` | `src/index.ts` | 从 `/api/v1/contracts/my` 获取元数据 |\n\n资料来源：[dist-test/src/index.js:rememberCustomRun](), [tasks/task061.md]()\n\n## 部署配置\n\n### MCP 客户端配置示例\n\n#### Claude Desktop (macOS)\n\n```json\n{\n  \"mcpServers\": {\n    \"mova\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@leryk1981/mova-flat-runner@3.3.3\"],\n      \"env\": {\n        \"MOVA_API_URL\": \"https://api.mova-lab.eu\",\n        \"MOVA_API_KEY\": \"__SET_MOVA_API_KEY__\",\n        \"LLM_KEY\": \"__SET_LLM_KEY__\",\n        \"LLM_MODEL\": \"openai/gpt-4o-mini\"\n      }\n    }\n  }\n}\n```\n\n#### Codex (Linux)\n\n```toml\n[mcp_servers.mova]\ncommand = \"npx\"\nargs = [\"-y\", \"@leryk1981/mova-flat-runner@3.3.3\"]\nstartup_timeout_sec = 90.0\n\n[mcp_servers.mova.env]\nMOVA_API_URL = \"https://api.mova-lab.eu\"\nMOVA_API_KEY = \"__SET_MOVA_API_KEY__\"\nLLM_KEY = \"__SET_LLM_KEY__\"\nLLM_MODEL = \"openai/gpt-4o-mini\"\n```\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n### 发布工具\n\n系统提供 CLI 用于发布 MCP 服务器：\n\n```bash\nmake publisher      # 构建发布工具\n./bin/mcp-publisher # 运行发布\n```\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n## 验证与测试\n\n### 构建与测试命令\n\n| 命令 | 用途 |\n|------|------|\n| `make check` | 运行 lint、单元测试、集成测试 |\n| `npm run build` | TypeScript 编译与打包 |\n| `npm run test:build` | 构建产物测试 |\n| `npm run smoke:custom-bridge` | 自定义桥接烟雾测试 |\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md), [tasks/task061.md]()\n\n## 技术栈\n\n| 层级 | 技术选型 | 版本要求 |\n|------|----------|----------|\n| 运行时 | Node.js | ≥ 18 |\n| 语言 | TypeScript | ES Modules |\n| 协议 | Model Context Protocol | 1.x |\n| 包管理 | npm | - |\n| 发布格式 | npx 可执行包 | @leryk1981/mova-flat-runner |\n\n资料来源：[package.json:1-15]()\n\n## 总结\n\nmova-flat-runner 采用了清晰的分层架构：\n\n1. **协议层**：通过 MCP 协议与 AI 客户端交互\n2. **调度层**：`executeTool` 统一分发请求\n3. **传输层**：支持本地执行与远程 API 两种路径\n4. **安全层**：步骤模式守卫确保工作流定义一致性\n5. **数据层**：合约包验证器保障部署安全\n\n该架构支持灵活的工作流执行模式，同时通过 MCP 协议为 AI 代理提供标准化的工具接口，实现了业务逻辑与 AI 推理的解耦。\n\n---\n\n<a id='page-transport-layer'></a>\n\n## 传输层\n\n### 相关页面\n\n相关主题：[系统架构](#page-system-architecture), [可用工具集](#page-available-tools)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/transports/local_seam_bridge.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/local_seam_bridge.ts)\n- [src/transports/remote_api.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/remote_api.ts)\n- [src/index.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/index.ts)\n- [dist-test/src/transports/local_seam_bridge.js](https://github.com/mova-compact/mova-flat-runner/blob/main/dist-test/src/transports/local_seam_bridge.js)\n- [dist-test/src/transports/remote_api.js](https://github.com/mova-compact/mova-flat-runner/blob/main/dist-test/src/transports/remote_api.js)\n</details>\n\n# 传输层\n\n## 概述\n\n传输层（Transport Layer）是 mova-flat-runner 中负责在不同执行环境之间传递数据和调用命令的核心模块。该层抽象了本地执行与远程 API 调用两种传输机制，使上层业务逻辑能够以统一的方式与 MOVA 运行时进行交互，而无需关心具体的通信细节。\n\nmova-flat-runner 的传输层包含两个主要实现：\n\n| 传输实现 | 文件路径 | 用途 |\n|---------|---------|------|\n| 本地桥接传输 | `src/transports/local_seam_bridge.ts` | 本地进程内的桥接调用，通过文件系统进行状态管理 |\n| 远程 API 传输 | `src/transports/remote_api.ts` | 通过 HTTP/REST 与远程 MOVA 服务端点通信 |\n\n资料来源：[src/transports/local_seam_bridge.ts:1-30](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/local_seam_bridge.ts)\n\n---\n\n## 架构设计\n\n### 传输层定位\n\n```\n┌─────────────────────────────────────────────────────────┐\n│                    MCP 协议层                            │\n│         (mova_run, mova_query, mova_decide)             │\n└─────────────────────────────────────────────────────────┘\n                            │\n                            ▼\n┌─────────────────────────────────────────────────────────┐\n│                   传输层 (Transport)                     │\n│  ┌─────────────────┐      ┌─────────────────────────┐  │\n│  │ local_seam_     │      │     remote_api          │  │\n│  │ bridge          │      │  (movaGet/movaPost...)  │  │\n│  └─────────────────┘      └─────────────────────────┘  │\n└─────────────────────────────────────────────────────────┘\n           │                              │\n           ▼                              ▼\n    本地文件系统状态                 REST API 远程调用\n    (state_file)                   (api.mova-lab.eu)\n```\n\n### 传输策略选择\n\n传输层通过配置中的 `baseUrl` 判断使用哪种传输策略：\n\n```typescript\nexport function isLocalSeamConfig(config: MovaConfig): boolean {\n    return config.baseUrl === LOCAL_SEAM_BACKEND;\n}\n```\n\n- 当 `baseUrl` 为本地后端地址时，使用本地桥接传输\n- 当 `baseUrl` 为远程 API 地址时，使用 HTTP 传输\n\n资料来源：[dist-test/src/transports/local_seam_bridge.js:85-87](https://github.com/mova-compact/mova-flat-runner/blob/main/dist-test/src/transports/local_seam_bridge.js)\n\n---\n\n## 本地桥接传输 (local_seam_bridge)\n\n### 核心功能\n\n本地桥接传输用于在本地进程环境中直接与 MOVA 运行时交互，通过文件系统存储状态数据，无需网络通信。\n\n#### 内部桥接调用器\n\n`createInternalBridgeInvoker()` 创建一个桥接调用函数，负责处理步骤执行结果的标准化输出：\n\n```typescript\nfunction createInternalBridgeInvoker() {\n    return async function bridgeInvoker(request) {\n        bridgeSequence += 1;\n        const suffix = `${request.step.id}:${bridgeSequence}`;\n        \n        const producedOutput =\n            request.step.execution_mode === \"AI_ATOMIC\"\n                ? CANONICAL_STRATEGY\n                : request.stepResult ?? null;\n        \n        const status =\n            request.step.execution_mode === \"HUMAN_GATE\" && request.humanDecision == null\n                ? \"human_gate_required\"\n                : request.terminalOutcome\n                    ? \"completed\"\n                    : \"advanced\";\n\n        return {\n            ok: true,\n            bridge: {\n                ok: true,\n                bridge_source: \"mova_flat_runner_canonical_bridge\",\n                status,\n                contract_ref: request.contractRef,\n                // ... 更多字段\n            },\n        };\n    };\n}\n```\n\n资料来源：[src/transports/local_seam_bridge.ts:55-95](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/local_seam_bridge.ts)\n\n#### 状态管理\n\n本地传输通过以下方式解析运行定位器：\n\n```typescript\nasync function resolveLocalSeamLocator(initialInputs) {\n    const packagePath = \n        typeof initialInputs.package_path === \"string\" && initialInputs.package_path.trim().length > 0\n            ? initialInputs.package_path\n            : process.env.MOVA_SANDBOX_PACKAGE_PATH ?? \"D:\\\\Projects_MOVA\\\\mova-intent\\\\contracts\\\\dockerfile-nodejs-v1\";\n\n    const projectPath = \n        typeof initialInputs.project_path === \"string\" && initialInputs.project_path.trim().length > 0\n            ? initialInputs.project_path\n            : process.env.MOVA_SANDBOX_PROJECT_PATH ?? \"\";\n\n    const stateFile = \n        typeof initialInputs.state_file === \"string\" && initialInputs.state_file.trim().length > 0\n            ? initialInputs.state_file\n            : path.join(await fs.mkdtemp(path.join(os.tmpdir(), \"mova-flat-runner-bridge-\")), \"run_state.json\");\n\n    return { package_path: packagePath, project_path: projectPath, state_file: stateFile };\n}\n```\n\n资料来源：[src/transports/local_seam_bridge.ts:105-125](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/local_seam_bridge.ts)\n\n### 执行模式与状态映射\n\n| 执行模式 | humanDecision 状态 | 返回状态 |\n|---------|-------------------|---------|\n| `AI_ATOMIC` | 任意 | `produced_output = CANONICAL_STRATEGY` |\n| `HUMAN_GATE` | `null` | `human_gate_required` |\n| `HUMAN_GATE` | 有值 | `advanced` |\n| 任意 | `terminalOutcome = true` | `completed` |\n\n### 公共形状过滤\n\n`sanitizePublicShape()` 函数确保敏感内部字段不会泄漏到外部响应：\n\n```typescript\nfunction sanitizePublicShape(value: unknown): boolean {\n    if (Array.isArray(value)) {\n        return value.every((item) => sanitizePublicShape(item));\n    }\n    if (!value || typeof value !== \"object\") {\n        return true;\n    }\n    for (const [key, child] of Object.entries(value)) {\n        // 过滤敏感字段\n        if ([\"bridge_anchors\", \"last_terminal_bridge\", \"terminal_commit_count\", \n             \"_state15_bridge\", \"trace\", \"outputs\", \"context\"].includes(key)) {\n            return false;\n        }\n        if (!sanitizePublicShape(child)) {\n            return false;\n        }\n    }\n    return true;\n}\n```\n\n资料来源：[src/transports/local_seam_bridge.ts:130-150](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/local_seam_bridge.ts)\n\n### 人工决策处理\n\n本地传输提供两个关键函数用于人工决策流程：\n\n#### 获取决策点\n\n```typescript\nexport async function movaGetDecisionPointLocal(runReference) {\n    const locator = await resolveOpaqueLocatorOrThrow(runReference);\n    const machine = await loadMachineBridgeModule();\n    const gate = await machine.get_human_gate({ state_file: locator.state_file });\n    \n    if (!sanitizePublicShape(gate)) {\n        throw new Error(\"internal_field_leak\");\n    }\n    return gate;\n}\n```\n\n#### 提交决策\n\n```typescript\nexport async function movaSubmitDecisionLocal(runReference, option, reason) {\n    const locator = await resolveOpaqueLocatorOrThrow(runReference);\n    const machine = await loadMachineBridgeModule();\n    const resolution = await machine.submit_human_resolution({\n        package_path: locator.package_path,\n        state_file: locator.state_file,\n        step_id: \"review_strategy\",\n        // ...\n    });\n}\n```\n\n资料来源：[dist-test/src/transports/local_seam_bridge.js:95-120](https://github.com/mova-compact/mova-flat-runner/blob/main/dist-test/src/transports/local_seam_bridge.js)\n\n---\n\n## 远程 API 传输 (remote_api)\n\n### HTTP 方法封装\n\n远程传输提供标准的 RESTful API 调用封装：\n\n```typescript\nexport const movaGet    = (config, path) => movaRequest(config, \"GET\", path);\nexport const movaPut    = (config, path, body) => movaRequest(config, \"PUT\", path, body);\nexport const movaDelete = (config, path) => movaRequest(config, \"DELETE\", path);\nexport const movaPost   = (config, path, body) => movaRequest(config, \"POST\", path, body);\n```\n\n### 远程步骤执行\n\n`movaRunStepsRemote()` 函数按顺序执行 `analyze`、`verify`、`decide` 三个步骤：\n\n```mermaid\ngraph TD\n    A[开始 movaRunStepsRemote] --> B[执行 analyze 步骤]\n    B --> C{结果 ok?}\n    C -->|否| D[返回错误]\n    C -->|是| E[获取 analyze 输出]\n    E --> F[执行 verify 步骤]\n    F --> G{结果 ok?}\n    G -->|否| D\n    G -->|是| H{状态 = waiting_human?}\n    H -->|是| I[获取 decision_point]\n    H -->|否| J[执行 decide 步骤]\n    I --> K[返回等待人工决策]\n    J --> L[返回执行结果]\n```\n\n```typescript\nexport async function movaRunStepsRemote(cfg, contractId, validators, initialInputs = {}) {\n    let analysis = {};\n    for (const stepId of [\"analyze\", \"verify\", \"decide\"]) {\n        let result;\n        try {\n            result = await movaPost(cfg, `/api/v1/contracts/${contractId}/step`, {\n                envelope: {\n                    kind: \"env.step.execute_v0\",\n                    envelope_id: `env-${shortId()}`,\n                    contract_id: contractId,\n                    actor: { actor_type: \"system\", actor_id: \"mova_runtime\" },\n                    payload: { step_id: stepId },\n                },\n            });\n        } catch (error) {\n            return flatErr(code, error.message, undefined, retryable);\n        }\n        \n        if (!result.ok) {\n            return flatErr(ERR.API_REQUEST_FAILED, `Step \"${stepId}\" returned ok=false`, result);\n        }\n        \n        // 处理分析输出和验证器\n        if (stepId === \"analyze\") {\n            const output = await movaGet(cfg, `/api/v1/contracts/${contractId}/steps/analyze/output`);\n            analysis = { ...output };\n            \n            // 执行验证器\n            for (const validator of validators) {\n                const fn = VALIDATOR_REGISTRY.get(validator.validator_id);\n                if (!fn) {\n                    analysis[`${validator.step_id}_error`] = `VALIDATOR_NOT_ALLOWED`;\n                    continue;\n                }\n                const resultValue = fn({ ...initialInputs, ...analysis });\n                Object.assign(analysis, resultValue.value ?? {});\n            }\n        }\n    }\n    return { ok: true, analysis };\n}\n```\n\n资料来源：[dist-test/src/transports/remote_api.js:60-95](https://github.com/mova-compact/mova-flat-runner/blob/main/dist-test/src/transports/remote_api.js)\n\n### 错误处理机制\n\n| 错误类型 | 处理策略 | retryable |\n|---------|---------|-----------|\n| API 请求失败 | 返回错误码 `ERR.API_REQUEST_FAILED` | 由错误对象决定 |\n| 步骤返回 `ok=false` | 返回包含失败详情的错误 | `false` |\n| 验证器未注册 | 记录错误但继续执行 | 不适用 |\n| 验证器执行异常 | 捕获并记录到分析结果中 | 不适用 |\n\n### 人工决策端点\n\n远程 API 在检测到 `waiting_human` 状态时，额外查询决策点信息：\n\n```typescript\nif (result.status === \"waiting_human\") {\n    let decisionPoint = {};\n    try {\n        const response = await movaGet(cfg, `/api/v1/contracts/${contractId}/decision`);\n        decisionPoint = (response.decision_point ?? {});\n    } catch {\n        // 非致命错误，legacy 远程路径兼容\n    }\n    return {\n        ok: true,\n        status: \"waiting_human\",\n        contract_id: contractId,\n        question: decisionPoint.question ?? \"Select action:\",\n        options: decisionPoint.options ?? [],\n        recommended: decisionPoint.recommended_option_id ?? null,\n        analysis,\n    };\n}\n```\n\n---\n\n## 传输配置\n\n### MovaConfig 配置结构\n\n| 字段 | 类型 | 说明 |\n|-----|------|------|\n| `baseUrl` | `string` | API 基础地址，决定使用本地或远程传输 |\n| `apiKey` | `string` | API 认证密钥 |\n| `timeoutMs` | `number` | 请求超时时间（毫秒） |\n| `headers` | `Record<string, string>` | 自定义 HTTP 请求头 |\n\n### 环境变量映射\n\n```env\n# 远程 API 配置\nMOVA_API_URL=https://api.mova-lab.eu\nMOVA_API_KEY=__SET_MOVA_API_KEY__\n\n# 本地传输配置\nMOVA_SANDBOX_PACKAGE_PATH=默认包路径\nMOVA_SANDBOX_PROJECT_PATH=默认项目路径\n\n# 可选配置\nMOVA_API_TIMEOUT_MS=30000\nMOVA_HTTP_PORT=3796\n```\n\n---\n\n## 工作流程对比\n\n```mermaid\ngraph LR\n    subgraph 本地传输\n        L1[解析输入] --> L2[创建状态文件]\n        L2 --> L3[调用本地机器模块]\n        L3 --> L4[读写 state_file]\n        L4 --> L5[返回结果]\n    end\n    \n    subgraph 远程传输\n        R1[解析输入] --> R2[构建信封]\n        R2 --> R3[HTTP POST /step]\n        R3 --> R4[轮询状态]\n        R4 --> R5[返回结果]\n    end\n    \n    A{传输类型} -->|本地| 本地传输\n    A -->|远程| 远程传输\n```\n\n| 特性 | 本地传输 | 远程传输 |\n|-----|---------|---------|\n| 通信方式 | 进程调用 + 文件系统 | HTTP/REST API |\n| 状态存储 | 本地 `state_file` | 服务端管理 |\n| 延迟 | 低 | 取决于网络 |\n| 可扩展性 | 单机 | 分布式 |\n| 适用场景 | 开发调试、沙箱 | 生产环境 |\n\n---\n\n## 安全性考量\n\n### 输入验证\n\n所有通过传输层传递的输入都经过严格验证：\n\n1. **路径验证**：防止路径遍历攻击\n2. **类型检查**：确保配置参数类型正确\n3. **空值处理**：验证必需字段存在\n\n### 输出过滤\n\n`sanitizePublicShape()` 函数过滤以下敏感字段：\n\n- `bridge_anchors` - 桥接锚点\n- `last_terminal_bridge` - 最终桥接状态\n- `terminal_commit_count` - 提交计数\n- `_state15_bridge` - 内部状态\n- `trace` - 执行跟踪\n- `outputs` - 完整输出\n- `context` - 运行时上下文\n\n### 错误隔离\n\n传输层错误被封装为标准化错误响应，防止内部实现细节泄漏：\n\n```typescript\nfunction isMovaNotFoundError(error: unknown): boolean {\n    const msg = error instanceof Error ? error.message : String(error);\n    return msg.includes(\"MOVA API 404\");\n}\n```\n\n---\n\n## 相关文件索引\n\n| 模块 | 文件路径 | 职责 |\n|-----|---------|------|\n| 入口点 | `src/index.ts` | 传输层调用入口，工具执行路由 |\n| 本地桥接 | `src/transports/local_seam_bridge.ts` | 本地执行环境和文件系统交互 |\n| 远程 API | `src/transports/remote_api.ts` | HTTP API 通信封装 |\n| 安全模块 | `src/security/step_mode_guard.ts` | 步骤模式验证 |\n\n---\n\n<a id='page-security-module'></a>\n\n## 安全模块\n\n### 相关页面\n\n相关主题：[系统架构](#page-system-architecture), [业务验证器](#page-validators)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/security/class_definition_guard.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/security/class_definition_guard.ts)\n- [src/security/step_mode_guard.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/security/step_mode_guard.ts)\n- [src/security/flow_schema_guard.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/security/flow_schema_guard.ts)\n- [src/validators/aml.js](https://github.com/mova-compact/mova-flat-runner/blob/main/src/validators/aml.js)\n- [src/transports/local_seam_bridge.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/local_seam_bridge.ts)\n- [src/index.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/index.ts)\n</details>\n\n# 安全模块\n\n## 概述\n\nmova-flat-runner 的安全模块采用**纵深防御（Defense-in-Depth）**策略，通过多个独立的安全守卫（Security Guards）在不同层级验证合约流程的完整性和安全性。这些守卫在模块导入时无副作用执行，所有验证逻辑均为纯函数，确保不会因验证失败而产生意外状态变更。\n\n核心安全目标包括：\n\n- 防止特权提升攻击（Privilege Escalation）\n- 阻断内联类定义注入（Inline Class Definition Injection）\n- 验证步骤执行模式与字段的一致性\n- 确保合约执行的确定性边界\n\n## 架构概览\n\n```mermaid\ngraph TD\n    subgraph 安全模块架构\n        FSG[flow_schema_guard<br/>CFV-9 流程Schema守卫]\n        CDG[class_definition_guard<br/>CFV-10 类定义守卫]\n        SMG[step_mode_guard<br/>步骤模式守卫]\n        \n        FSG -->|拒绝未知顶层字段| ERR1[ERR.SCHEMA_VIOLATION]\n        CDG -->|拒绝内联类定义| ERR2[ERR.INLINE_CLASS_DEFINITION_FORBIDDEN]\n        SMG -->|模式字段不匹配| ERR3[ERR.STEP_MODE_FIELD_MISMATCH]\n    end\n    \n    subgraph 入口点\n        REG[合约注册]\n        RUN[合约执行]\n    end\n    \n    REG --> FSG\n    REG --> CDG\n    RUN --> SMG\n```\n\n## CFV-9 流程 Schema 守卫\n\n### 背景与目的\n\n安全审计发现，某些恶意流程包含 `__admin_override`、`__privilege_grant`、`__debug_mode` 等顶层字段。虽然初始注册逻辑不直接使用这些字段，但它们可能被持久化存储，后续代码路径若读取这些字段将导致特权提升漏洞。\n\nflow_schema_guard.ts 实现**严格默认（Strict-by-Default）**策略：拒绝任何不在白名单中的顶层键。\n\n### 白名单定义\n\n| 允许的顶层键 | 用途 |\n|-------------|------|\n| `version` | 流程版本标识 |\n| `description` | 流程描述 |\n| `entry` | 入口步骤引用 |\n| `steps` | 步骤定义对象 |\n| `parallel_steps` | 并行步骤定义 |\n| `notes` | 备注信息 |\n| `audit_mode` | 审计模式配置 |\n| `audit_mode_note` | 审计模式说明 |\n| `class_definition_ref` | 类定义引用（远程解析） |\n| `CONTRACT_CALL_instructions` | 合约调用指令 |\n| `input_schema` | 输入数据Schema |\n| `output_schema` | 输出数据Schema |\n| `metadata` | 元数据 |\n\n### 核心实现\n\n```typescript\n// 资料来源：src/security/flow_schema_guard.ts:17-30\nexport const ALLOWED_FLOW_TOP_LEVEL_KEYS: ReadonlySet<string> = new Set([\n  \"version\",\n  \"description\",\n  \"entry\",\n  \"steps\",\n  \"parallel_steps\",\n  \"notes\",\n  \"audit_mode\",\n  \"audit_mode_note\",\n  \"class_definition_ref\",\n  \"CONTRACT_CALL_instructions\",\n  \"input_schema\",\n  \"output_schema\",\n  \"metadata\",\n]);\n```\n\n### 验证函数\n\n```typescript\n// 资料来源：src/security/flow_schema_guard.ts:33-43\nexport function findUnknownFlowFields(flow: unknown): string[] {\n  if (!flow || typeof flow !== \"object\" || Array.isArray(flow)) return [];\n  const f = flow as Record<string, unknown>;\n  const out: string[] = [];\n  for (const key of Object.keys(f)) {\n    if (!ALLOWED_FLOW_TOP_LEVEL_KEYS.has(key))\n      out.push(key);\n  }\n  return out;\n}\n```\n\n当发现未知字段时，返回格式化的错误响应：\n\n```typescript\n// 资料来源：src/security/flow_schema_guard.ts:45-55\nexport function assertNoUnknownFlowFields(\n  flow: unknown,\n  requestId: string,\n): FlatRunnerResult | null {\n  const unknown = findUnknownFlowFields(flow);\n  if (unknown.length === 0) return null;\n  return flatErr(ERR.SCHEMA_VIOLATION, ..., { unknown_fields: unknown }, false, requestId);\n}\n```\n\n## CFV-10 类定义守卫\n\n### 背景与目的\n\n类定义（class_definition）包含敏感的配置信息，如严重性等级（severity bands）和噪声控制参数。安全审计发现攻击者可将类定义以内联方式嵌入流程，绕过注册表权威验证，从而操纵安全决策。\n\nclass_definition_guard.ts 强制要求类定义必须通过注册表（Registry）按 `class_id` 解析，禁止内联定义。\n\n### 禁止字段列表\n\n| 禁止的字段名 | 说明 |\n|-------------|------|\n| `class_definition` | 完整类定义对象 |\n| `class_definition_inline` | 内联类定义 |\n| `class_def_override` | 类定义覆盖 |\n| `class_def` | 缩写形式 |\n\n### 核心实现\n\n```typescript\n// 资料来源：src/security/class_definition_guard.ts:12-18\nconst FORBIDDEN_FLOW_KEYS: readonly string[] = Object.freeze([\n  \"class_definition\",\n  \"class_definition_inline\",\n  \"class_def_override\",\n  \"class_def\",\n]);\n\n// 资料来源：src/security/class_definition_guard.ts:21-28\nexport function findInlineClassDefinitionFields(flow: unknown): string[] {\n  if (!flow || typeof flow !== \"object\") return [];\n  const f = flow as Record<string, unknown>;\n  return FORBIDDEN_FLOW_KEYS.filter((k) => Object.prototype.hasOwnProperty.call(f, k));\n}\n```\n\n### 错误响应\n\n```typescript\n// 资料来源：src/security/class_definition_guard.ts:30-45\nexport function assertNoInlineClassDefinition(\n  flow: unknown,\n  requestId: string,\n): FlatRunnerResult | null {\n  const found = findInlineClassDefinitionFields(flow);\n  if (found.length === 0) return null;\n  return flatErr(\n    ERR.INLINE_CLASS_DEFINITION_FORBIDDEN,\n    `Flow body contains inline class-definition field(s): ${found.join(\", \")}. ` +\n    \"Class definitions must be resolved from the registry by class_id, not embedded in the flow.\",\n    {\n      forbidden_fields: found,\n      remediation: \"Remove these fields and reference the class via class_id; the registry is the only authority on severity bands and noise control.\",\n      http_status_equivalent: 400,\n    },\n    false,\n    requestId,\n  );\n}\n```\n\n## 步骤模式守卫\n\n### 执行模式类型\n\n| 模式 | 说明 | 必需字段 |\n|------|------|---------|\n| `DETERMINISTIC` | 本地JS校验，无LLM调用 | 无额外要求 |\n| `AI_ATOMIC` | LLM原子执行 | 必须有 `model` 字段 |\n| `CONTRACT_CALL` | 调用其他合约 | 必须有 `contract_id` 字段 |\n| `HUMAN_GATE` | 人工决策门 | 必须有 `decision_options` 数组 |\n\n### 验证规则\n\n步骤模式守卫检测以下违规场景：\n\n1. **DETERMINISTIC 模式含 model 字段**\n   \n   ```typescript\n   // 资料来源：src/security/step_mode_guard.ts:42-49\n   if (mode === \"DETERMINISTIC\" && step.model !== undefined && step.model !== null) {\n     out.push({\n       kind: \"deterministic_with_model\",\n       step_id: id,\n       execution_mode: mode,\n       message: `step '${id ?? \"?\"}' is DETERMINISTIC but declares a 'model' field — DET steps run a local JS check, not an LLM`,\n     });\n   }\n   ```\n\n2. **AI_ATOMIC 模式缺少 model 字段**\n   \n   ```typescript\n   // 资料来源：src/security/step_mode_guard.ts:51-58\n   if (mode === \"AI_ATOMIC\" && asStr(step.model) === null) {\n     out.push({\n       kind: \"ai_atomic_without_model\",\n       step_id: id,\n       execution_mode: mode,\n       message: `step '${id ?? \"?\"}' is AI_ATOMIC but has no 'model' field`,\n     });\n   }\n   ```\n\n3. **CONTRACT_CALL 模式缺少 contract_id**\n   \n   ```typescript\n   // 资料来源：src/security/step_mode_guard.ts:60-67\n   if (mode === \"CONTRACT_CALL\" && asStr(step.contract_id) === null) {\n     out.push({\n       kind: \"contract_call_without_contract_id\",\n       step_id: id,\n       execution_mode: mode,\n       message: `step '${id ?? \"?\"}' is CONTRACT_CALL but has no 'contract_id'`,\n     });\n   }\n   ```\n\n4. **HUMAN_GATE 模式缺少 decision_options**\n   \n   ```typescript\n   // 资料来源：src/security/step_mode_guard.ts:69-76\n   if (mode === \"HUMAN_GATE\" && !Array.isArray(step.decision_options)) {\n     out.push({\n       kind: \"human_gate_without_decisions\",\n       step_id: id,\n       execution_mode: mode,\n       message: `step '${id ?? \"?\"}' is HUMAN_GATE but has no 'decision_options' array`,\n     });\n   }\n   ```\n\n### 验证流程\n\n```mermaid\ngraph TD\n    A[遍历流程步骤] --> B{获取 execution_mode}\n    B -->|DETERMINISTIC| C{是否有 model?}\n    B -->|AI_ATOMIC| D{是否有 model?}\n    B -->|CONTRACT_CALL| E{是否有 contract_id?}\n    B -->|HUMAN_GATE| F{是否有 decision_options?}\n    \n    C -->|是| G[记录违规<br/>deterministic_with_model]\n    C -->|否| H[通过]\n    D -->|否| I[记录违规<br/>ai_atomic_without_model]\n    D -->|是| J[通过]\n    E -->|否| K[记录违规<br/>contract_call_without_contract_id]\n    E -->|是| L[通过]\n    F -->|否| M[记录违规<br/>human_gate_without_decisions]\n    F -->|是| N[通过]\n    \n    G --> O{违规数量 > 0?}\n    I --> O\n    K --> O\n    M --> O\n    H --> O\n    J --> O\n    L --> O\n    N --> O\n    \n    O -->|是| P[返回 flatErr<br/>ERR.STEP_MODE_FIELD_MISMATCH]\n    O -->|否| Q[验证通过]\n```\n\n## HUMAN_GATE 安全控制\n\n### 专用完成路径\n\nHUMAN_GATE 步骤不能通过通用的 `step_complete` 操作完成，必须使用专用的门控确认路径：\n\n```typescript\n// 资料来源：src/index.ts (上下文中的 gate_guard 使用)\ncase \"step_complete\": {\n  // SECURITY (CFV-3): HUMAN_GATE cannot be completed by generic step completion.\n  // Human confirmation requires the dedicated gate path (gate_approve / gate_reject).\n  const gateGuard = await assertNotHumanGate(config, args.run_id, args.step_id, requestId);\n  if (gateGuard) return gateGuard;\n  // ... 执行通用完成逻辑\n}\n\ncase \"gate_approve\": {\n  // 专用人工确认路径\n}\n\ncase \"gate_reject\": {\n  // 专用人工拒绝路径\n}\n```\n\n### Bridge 状态映射\n\n当流程遇到 HUMAN_GATE 时，local_seam_bridge 返回特定的桥接状态：\n\n```typescript\n// 资料来源：src/transports/local_seam_bridge.ts:19-25\nconst status =\n  request.step.execution_mode === \"HUMAN_GATE\" && request.humanDecision == null\n    ? \"human_gate_required\"\n    : request.terminalOutcome\n      ? \"completed\"\n      : \"advanced\";\n\n// 资料来源：src/transports/local_seam_bridge.ts:40-41\nnext_phase: { phase: status === \"human_gate_required\" ? \"WAIT_HUMAN\" : \"EXECUTION\" },\n```\n\n## 验证器集成\n\n### AML 验证器示例\n\n安全模块还包括业务级验证器（如 AML 合规验证器）：\n\n```javascript\n// 资料来源：src/validators/aml.js:1-28\nexport const amlValidators = [\n    {\n        id: \"aml.validate_policy_flags_v0\",\n        fn: (inputs) => {\n            const sanctions = Boolean(inputs.sanctions_match);\n            const pep = Boolean(inputs.pep_status);\n            const score = Number(inputs.risk_score) || 0;\n            const mandatory_escalate = sanctions || pep || score > 85;\n            const auto_clear = (score <= 30 && !sanctions && !pep && ...);\n            return {\n                ok: true,\n                value: {\n                    policy_flags_valid: score >= 0 && score <= 100,\n                    mandatory_escalate,\n                    auto_clear_eligible: auto_clear,\n                },\n            };\n        },\n    },\n];\n```\n\n### 验证器执行流程\n\n```mermaid\ngraph LR\n    A[远程获取分析输出] --> B[遍历验证器注册表]\n    B --> C{验证器ID存在?}\n    C -->|是| D[执行验证函数]\n    C -->|否| E[记录 VALIDATOR_NOT_ALLOWED 错误]\n    D --> F{验证执行成功?}\n    F -->|是| G[合并验证结果到分析输出]\n    F -->|否| H[记录 VALIDATOR_FAILED 错误]\n```\n\n```typescript\n// 资料来源：src/transports/remote_api.js:15-36\nconst validatorContext = { ...initialInputs, ...analysis };\nfor (const validator of validators) {\n  const fn = VALIDATOR_REGISTRY.get(validator.validator_id);\n  if (!fn) {\n    analysis[`${validator.step_id}_error`] = `VALIDATOR_NOT_ALLOWED: \"${validator.validator_id}\" not in registry`;\n    continue;\n  }\n  try {\n    const resultValue = fn(validatorContext);\n    Object.assign(analysis, resultValue.value ?? {});\n  } catch (error) {\n    analysis[`${validator.step_id}_error`] = `VALIDATOR_FAILED: ${String(error)}`;\n  }\n}\n```\n\n## 错误码对照表\n\n| 错误码常量 | 说明 | HTTP 等效状态 |\n|-----------|------|---------------|\n| `ERR.SCHEMA_VIOLATION` | 流程包含未授权的顶层字段 | 400 |\n| `ERR.INLINE_CLASS_DEFINITION_FORBIDDEN` | 禁止内联类定义 | 400 |\n| `ERR.STEP_MODE_FIELD_MISMATCH` | 执行模式与字段不匹配 | 400 |\n| `ERR.UNKNOWN_CONTRACT_TYPE` | 未知的合约类型 | 400 |\n| `ERR.LOCAL_VALIDATION_FAILED` | 本地验证失败 | 400 |\n| `ERR.GATE_REJECTED` | 人工门被拒绝 | 402 |\n\n## 安全模块设计原则\n\n1. **纯函数验证**：所有守卫函数无副作用，支持安全的并行执行和测试\n2. **显式拒绝**：默认拒绝策略，未明确允许的均为禁止\n3. **清晰错误信息**：违规响应包含违规详情和修复建议\n4. **纵深防御**：多层守卫互补，覆盖不同攻击向量\n5. **注册表权威**：敏感配置（如类定义）必须从注册表解析，禁止内联\n\n## 集成位置\n\n安全守卫在以下入口点被调用：\n\n| 入口 | 调用的守卫 |\n|------|-----------|\n| 合约注册 | flow_schema_guard, class_definition_guard |\n| 步骤执行 | step_mode_guard, gate_guard |\n| 远程API调用 | 验证器注册表执行 |\n\n```typescript\n// 资料来源：src/index.ts (集成示例)\nswitch (name) {\n  case \"mova_contract\": {\n    if (action === \"register\") {\n      // 调用安全守卫\n      const schemaGuard = assertNoUnknownFlowFields(flow, requestId);\n      const classGuard = assertNoInlineClassDefinition(flow, requestId);\n      // ...\n    }\n  }\n}\n\n---\n\n<a id='page-available-tools'></a>\n\n## 可用工具集\n\n### 相关页面\n\n相关主题：[核心概念](#page-core-concepts), [传输层](#page-transport-layer)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/index.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/index.ts)\n- [src/transports/local_seam_bridge.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/local_seam_bridge.ts)\n- [src/security/step_mode_guard.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/security/step_mode_guard.ts)\n- [src/package_support.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/package_support.ts)\n- [src/transports/remote_api.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/remote_api.ts)\n- [src/client.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/client.ts)\n\n</details>\n\n# 可用工具集\n\n## 概述\n\nmova-flat-runner 提供了一套完整的 MCP（Model Context Protocol）工具集，用于与 MOVA 平台进行交互。这套工具集涵盖了从合约执行、状态查询、决策支持到安全验证的完整工作流程。\n\n工具集通过 MCP 协议暴露为标准化接口，支持本地运行和远程 API 调用两种模式。所有工具均返回 JSON 格式的结构化响应，包含执行状态、结果数据和错误信息。资料来源：[src/index.ts:1-50]()\n\n## 工具列表总览\n\n| 工具名称 | 功能描述 | 执行模式 |\n|---------|---------|---------|\n| `mova_health` | 健康检查与连接验证 | 同步 |\n| `mova_registry` | 获取可用合约清单 | 同步 |\n| `mova_run` | 执行内置合约 | 本地/远程 |\n| `mova_query` | 查询合约状态与审计信息 | 远程 |\n| `mova_decide` | 触发决策流程 | 远程 |\n| `mova_connector` | 连接外部系统 | 远程 |\n| `mova_contract` | 自定义合约操作（注册/运行/状态） | 远程 |\n\n资料来源：[README.md:55-62]()\n\n## 核心工具详解\n\n### mova_run\n\n`mova_run` 是执行内置合约的核心工具，支持预定义的合约类型列表。\n\n#### 支持的合约类型\n\n系统内置了多个合约 manifest，存储在 `CONTRACT_MANIFESTS` 映射中。每个 manifest 包含：\n\n- `contract_type`：合约类型标识\n- `title`：合约标题\n- `version`：版本号\n- `execution_mode`：执行模式（AI_ATOMIC、DETERMINISTIC、HUMAN_GATE 等）\n- `template_id`：模板标识\n- `dataspec`：输入数据规格\n\n资料来源：[src/index.ts:200-280]()\n\n#### 执行流程\n\n```mermaid\ngraph TD\n    A[接收合约类型与输入] --> B{查找 Manifest}\n    B -->|找到| C[验证输入数据]\n    B -->|未找到| D[返回未知合约类型错误]\n    C --> E{执行模式}\n    E -->|LOCAL_SEAM| F[本地沙箱执行]\n    E -->|REMOTE_API| G[远程 API 调用]\n    F --> H[返回执行结果]\n    G --> H\n```\n\n#### 安全验证\n\n执行前会进行多重安全检查：\n\n1. **Step Mode 验证**：确保执行模式与字段定义匹配\n2. **内联类定义检查**：禁止在流程中嵌入 class_definition\n3. **人类决策门保护**：HUMAN_GATE 步骤不可通过通用 step_complete 跳过\n\n资料来源：[src/security/step_mode_guard.ts:1-50]()\n\n### mova_contract\n\n自定义合约操作工具，支持完整的合约生命周期管理。\n\n#### 支持的操作\n\n| 操作 | 说明 | 所需参数 |\n|-----|------|---------|\n| `register` | 注册新合约 | contract_id, flow |\n| `run` | 运行合约 | contract_id |\n| `run_status` | 查询运行状态 | run_id |\n| `step_complete` | 完成步骤 | run_id, step_id, outcome, output |\n| `gate_approve` | 批准人类决策门 | run_id, step_id |\n| `gate_reject` | 拒绝人类决策门 | run_id, step_id, reason |\n| `cancel` | 取消运行 | run_id |\n\n资料来源：[src/index.ts:280-400]()\n\n#### 自定义合约桥接机制\n\n对于自定义合约（如 `local-*`、`remote-*` 前缀的 ID），系统实现了智能桥接：\n\n1. **运行追踪**：在 `run` 和 `run_status` 时记录 `contract_id → run_id` 映射\n2. **404 兜底**：当 `/api/v1/contracts/{contract_id}` 返回 404 时，探测 `/api/v1/contracts/my` 获取元数据\n3. **状态桥接**：返回结构化的 bridged status，包含 `bridge_mode=custom_contract_run_namespace_bridge_v1`\n\n资料来源：[src/index.ts:80-120]()\n\n### mova_query\n\n状态与审计信息查询工具，支持多种视图模式。\n\n#### 视图模式\n\n| 视图 | 说明 | 返回内容 |\n|-----|------|---------|\n| `status` | 状态视图 | 合约运行状态、结构化结果 |\n| `audit` | 审计视图 | 完整审计记录（需要后端支持） |\n| `audit_compact` | 紧凑审计 | 精简审计对象，含 journal |\n\n#### 自定义合约查询\n\n当查询自定义合约 ID 遇到 404 时：\n\n```mermaid\ngraph TD\n    A[查询 /api/v1/contracts/{id}] --> B{响应状态}\n    B -->|200| C[返回正常结果]\n    B -->|404| D[探测 /api/v1/contracts/my]\n    D --> E{找到合约记录}\n    E -->|是| F[构建桥接状态]\n    E -->|否| G[返回 AUDIT_UNAVAILABLE]\n```\n\n资料来源：[tasks/task061.md:1-50]()\n\n### mova_decide\n\n决策触发工具，用于启动需要 AI 推理的决策流程。\n\n#### 工作原理\n\n1. 接收决策请求上下文\n2. 调用后端决策端点\n3. 返回决策结果和可选的推荐选项\n4. 支持 human-in-the-loop 确认\n\n资料来源：[src/transports/remote_api.ts:80-120]()\n\n### mova_connector\n\n外部系统连接工具，用于集成第三方服务。\n\n#### 功能特性\n\n- 建立与外部 API 的连接\n- 传递认证信息（通过配置）\n- 处理请求/响应转换\n- 支持超时和重试配置\n\n### mova_health\n\n健康检查工具，用于验证与 MOVA API 的连接状态。\n\n```bash\ncurl -sS https://api.mova-lab.eu/health\n```\n\n资料来源：[README.md:48-50]()\n\n### mova_registry\n\n合约清单查询工具，返回所有可用合约的元信息。\n\n#### 返回格式\n\n```json\n{\n  \"schema_version\": \"1.0\",\n  \"contracts\": [\n    {\n      \"contract_type\": \"complaint\",\n      \"title\": \"投诉处理合约\",\n      \"version\": \"1.0.0\",\n      \"execution_mode\": \"AI_ATOMIC\",\n      \"manifest_resource\": \"mova://contracts/complaint/manifest\"\n    }\n  ]\n}\n```\n\n资料来源：[src/index.ts:450-480]()\n\n## 安全验证体系\n\n### Step Mode 字段一致性检查\n\n每种执行模式都有强制的字段要求：\n\n| 执行模式 | 必需字段 | 禁止字段 |\n|---------|---------|---------|\n| DETERMINISTIC | 无 | model |\n| AI_ATOMIC | model | 无 |\n| CONTRACT_CALL | contract_id | 无 |\n| HUMAN_GATE | decision_options | 无 |\n\n#### 检测的违规类型\n\n- `ai_atomic_without_model`：AI_ATOMIC 模式未定义 model 字段\n- `deterministic_with_model`：DETERMINISTIC 模式错误包含 model 字段\n- `contract_call_without_contract_id`：CONTRACT_CALL 缺少 contract_id\n- `human_gate_without_decisions`：HUMAN_GATE 缺少 decision_options\n\n资料来源：[src/security/step_mode_guard.ts:50-100]()\n\n### 内联类定义防护\n\n禁止在流程中直接嵌入 class_definition 字段：\n\n```typescript\nconst FORBIDDEN_FLOW_KEYS = [\n  \"class_definition_inline\",\n  \"class_def_override\", \n  \"class_def\"\n];\n```\n\n违规响应包含：\n- `forbidden_fields`：发现的禁止字段列表\n- `remediation`：修复建议\n- `http_status_equivalent`：400\n\n资料来源：[src/security/class_definition_guard.ts:1-40]()\n\n### 人类决策门保护\n\nHUMAN_GATE 步骤有特殊保护机制：\n\n1. **前置检查**：`step_complete` 操作会拒绝 HUMAM_GATE 步骤\n2. **专用路径**：必须通过 `gate_approve` 或 `gate_reject` 完成\n3. **原因记录**：拒绝操作需提供原因\n\n资料来源：[src/index.ts:350-380]()\n\n## 执行环境\n\n### 本地沙箱模式（LOCAL_SEAM）\n\n通过 `local_seam_bridge.ts` 实现本地执行：\n\n```mermaid\ngraph TD\n    A[请求] --> B[解析包路径]\n    B --> C[加载流程定义]\n    C --> D[执行步骤]\n    D --> E[状态持久化]\n    E --> F[返回桥接结果]\n```\n\n#### 关键特性\n\n- 状态文件自动管理\n- 支持自定义包路径和项目路径\n- 输出模式：`AI_ATOMIC` 自动生成 CANONICAL_STRATEGY\n- 人类门暂停机制\n\n资料来源：[src/transports/local_seam_bridge.ts:1-80]()\n\n### 远程 API 模式（REMOTE_API）\n\n通过 `remote_api.ts` 调用远程服务：\n\n```mermaid\ngraph TD\n    A[请求] --> B[构建请求信封]\n    B --> C[POST /api/v1/contracts/{id}/step]\n    C --> D{执行步骤}\n    D -->|analyze| E[获取分析输出]\n    D -->|verify| F[执行验证器]\n    D -->|decide| G[获取决策]\n    E --> H{状态检查}\n    H -->|waiting_human| I[返回决策点]\n    H -->|completed| J[返回完成结果]\n```\n\n#### 验证器执行\n\nanalyze 步骤后自动执行注册验证器：\n\n1. 从 `initialInputs` 构建验证上下文\n2. 遍历 `VALIDATOR_REGISTRY`\n3. 收集验证结果到 analysis 对象\n\n资料来源：[src/transports/remote_api.ts:100-150]()\n\n## 配置与环境变量\n\n### 必需变量\n\n| 变量名 | 说明 | 示例值 |\n|-------|------|-------|\n| `MOVA_API_URL` | API 端点 | `https://api.mova-lab.eu` |\n| `MOVA_API_KEY` | API 认证密钥 | `__SET_MOVA_API_KEY__` |\n| `LLM_KEY` | LLM 提供商密钥 | `__SET_LLM_KEY__` |\n| `LLM_MODEL` | LLM 模型标识 | `openai/gpt-4o-mini` |\n\n### 可选变量\n\n| 变量名 | 说明 | 默认值 |\n|-------|------|-------|\n| `MOVA_API_TIMEOUT_MS` | 请求超时（毫秒） | 30000 |\n| `MOVA_HTTP_PORT` | 本地 HTTP 端口 | 3796 |\n| `MOVA_INVOKE_TOKEN` | 本地调用令牌 | 无 |\n| `MOVA_SANDBOX_PACKAGE_PATH` | 沙箱包路径 | 项目默认 |\n| `MOVA_SANDBOX_PROJECT_PATH` | 沙箱项目路径 | 当前目录 |\n\n资料来源：[README.md:25-45]()\n\n## 包结构验证\n\n### Global 文件验证\n\n验证 `global.json` 的必需字段：\n\n- `global_id`：全局唯一标识（非空字符串）\n- `version`：版本号（非空字符串）\n- `scope`：必须为 `contract_package`\n- `semantic_roles`：非空数组\n- `non_authority_rules`：非空数组\n\n### Package Manifest 验证\n\n允许的 manifest 字段：\n\n```typescript\nconst allowedKeys = [\n  \"schema_id\",\n  \"package_id\", \n  \"version\",\n  \"global_ref\",\n  \"flow_ref\",\n  \"classification_policy_ref\",\n  \"classification_result_set_ref\",\n  \"runtime_binding_set_ref\",\n  \"model_refs\",\n  \"fixture_refs\",\n  \"package_invariants\"\n];\n```\n\n资料来源：[src/package_support.ts:50-100]()\n\n## 错误处理\n\n### 错误码体系\n\n| 错误码 | 说明 |\n|-------|------|\n| `UNKNOWN_CONTRACT_TYPE` | 未知的合约类型 |\n| `API_REQUEST_FAILED` | API 请求失败 |\n| `LOCAL_VALIDATION_FAILED` | 本地验证失败 |\n| `STEP_MODE_FIELD_MISMATCH` | 执行模式与字段不匹配 |\n| `INLINE_CLASS_DEFINITION_FORBIDDEN` | 禁止内联类定义 |\n\n### 重试机制\n\n错误响应包含 `retryable` 字段指示是否可重试：\n\n```json\n{\n  \"ok\": false,\n  \"code\": \"API_REQUEST_FAILED\",\n  \"message\": \"详细错误信息\",\n  \"retryable\": true\n}\n```\n\n资料来源：[src/index.ts:50-100]()\n\n## 总结\n\nmova-flat-runner 的工具集提供了从简单查询到复杂决策的完整能力覆盖。核心设计原则包括：\n\n1. **安全性优先**：多重验证机制确保流程正确性\n2. **灵活执行**：支持本地和远程两种执行模式\n3. **智能桥接**：自动处理自定义合约与内置路径的差异\n4. **标准化接口**：统一的 MCP 协议接口便于集成\n\n---\n\n<a id='page-validators'></a>\n\n## 业务验证器\n\n### 相关页面\n\n相关主题：[安全模块](#page-security-module), [可用工具集](#page-available-tools)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/validators/aml.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/validators/aml.ts)\n- [src/validators/churn.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/validators/churn.ts)\n- [src/validators/complaint.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/validators/complaint.ts)\n- [src/validators/compliance.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/validators/compliance.ts)\n- [src/validators/contract_gen.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/validators/contract_gen.ts)\n- [src/validators/credit.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/validators/credit.ts)\n- [src/validators/invoice.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/validators/invoice.ts)\n- [src/validators/po.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/validators/po.ts)\n- [src/validators/registry.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/validators/registry.ts)\n- [src/validators/supply_chain.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/validators/supply_chain.ts)\n- [src/validators/trade.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/validators/trade.ts)\n- [src/validators/content_flywheel.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/validators/content_flywheel.ts)\n</details>\n\n# 业务验证器\n\n## 概述\n\n业务验证器（Business Validators）是 mova-flat-runner 系统中用于在合同执行流程中对输入数据进行业务规则校验的组件。验证器在合同步骤执行后被调用，确保输入数据满足特定业务场景的约束条件，并在验证失败时提供明确的错误信息和原因。\n\n验证器采用**声明式注册 + 函数式校验**的架构模式，每个验证器都是一个独立模块，包含唯一标识符（`id`）和校验函数（`fn`），通过统一的注册表（Registry）进行管理和调度。\n\n资料来源：[src/validators/supply_chain.ts:3-4]()\n\n## 架构设计\n\n### 组件关系图\n\n```mermaid\ngraph TD\n    subgraph \"验证器模块层\"\n        AML[AML 验证器<br/>src/validators/aml.ts]\n        CREDIT[Credit 验证器<br/>src/validators/credit.ts]\n        SUPPLY[供应链验证器<br/>src/validators/supply_chain.ts]\n        INVOICE[发票验证器<br/>src/validators/invoice.ts]\n        COMPLAINT[投诉验证器<br/>src/validators/complaint.ts]\n        CHURN[流失验证器<br/>src/validators/churn.ts]\n        TRADE[贸易验证器<br/>src/validators/trade.ts]\n        COMPLIANCE[合规验证器<br/>src/validators/compliance.ts]\n        CONTRACT_GEN[合同生成验证器<br/>src/validators/contract_gen.ts]\n        PO[采购订单验证器<br/>src/validators/po.ts]\n        FLYWHEEL[内容飞轮验证器<br/>src/validators/content_flywheel.ts]\n    end\n\n    subgraph \"注册表层\"\n        REGISTRY[ValidatorRegistry<br/>src/validators/registry.ts]\n    end\n\n    subgraph \"执行层\"\n        REMOTE_API[remote_api.ts<br/>movaRunStepsRemote]\n        LOCAL_SEAM[local_seam_bridge.ts<br/>本地执行桥接]\n    end\n\n    AML --> REGISTRY\n    CREDIT --> REGISTRY\n    SUPPLY --> REGISTRY\n    INVOICE --> REGISTRY\n    COMPLAINT --> REGISTRY\n    CHURN --> REGISTRY\n    TRADE --> REGISTRY\n    COMPLIANCE --> REGISTRY\n    CONTRACT_GEN --> REGISTRY\n    PO --> REGISTRY\n    FLYWHEEL --> REGISTRY\n\n    REGISTRY --> REMOTE_API\n    REGISTRY --> LOCAL_SEAM\n```\n\n### 核心类型定义\n\n验证器的类型签名为 `ValidatorFn`，定义如下：\n\n```typescript\nexport type ValidatorFn = (inputs: Record<string, unknown>) => {\n  ok: boolean;\n  value: Record<string, unknown>;\n  step_id: string;\n};\n```\n\n资料来源：[src/validators/supply_chain.ts:1]()\n\n每个验证器返回的结构包含三个字段：\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| `ok` | `boolean` | 验证是否通过 |\n| `value` | `Record<string, unknown>` | 验证结果详情，包含计算出的业务指标 |\n| `step_id` | `string` | 关联的步骤标识符 |\n\n## 验证器注册表\n\n### 注册表结构\n\n`src/validators/registry.ts` 负责聚合所有验证器并提供统一的查询接口。注册表采用 `Map<string, ValidatorFn>` 结构，以验证器 ID 为键存储校验函数。\n\n```typescript\nexport const VALIDATOR_REGISTRY = new Map<string, ValidatorFn>();\n\n// 注册供应链验证器\nVALIDATOR_REGISTRY.set(\"supply_chain.validate_inputs_v0\", validateInputs);\n\n// 注册信用卡验证器  \nVALIDATOR_REGISTRY.set(\"credit.validate_calcs_v0\", validateCalcs);\n```\n\n### 注册流程\n\n```mermaid\nsequenceDiagram\n    participant Registry as registry.ts\n    participant Validator as 各验证器模块\n    participant Caller as 调用方<br/>remote_api / local_seam_bridge\n    \n    Validator->>Registry: 导出 { id, fn } 数组\n    Registry->>Registry: VALIDATOR_REGISTRY.set(id, fn)\n    \n    Caller->>Registry: VALIDATOR_REGISTRY.get(validator_id)\n    Registry-->>Caller: ValidatorFn | undefined\n```\n\n## 内置验证器一览\n\n### 验证器清单\n\n| 验证器 ID | 模块文件 | 校验目标 | 主要检查项 |\n|-----------|----------|----------|------------|\n| `aml.validate_kyc_v0` | aml.ts | KYC 反洗钱检查 | 客户身份、风险等级、制裁名单 |\n| `churn.validate_inputs_v0` | churn.ts | 流失预测输入 | 用户数据完整性 |\n| `complaint.validate_inputs_v0` | complaint.ts | 投诉处理输入 | 投诉内容、类别、优先级 |\n| `compliance.validate_v1` | compliance.ts | 合规性校验 | 监管要求符合度 |\n| `contract_gen.validate_template_v0` | contract_gen.ts | 合同模板校验 | 模板参数完整性 |\n| `credit.validate_calcs_v0` | credit.ts | 信贷计算校验 | 月收入、债务、征信评分、请求金额 |\n| `invoice.validate_fields_v0` | invoice.ts | 发票字段校验 | 发票号码、金额、日期、税率 |\n| `po.validate_po_v0` | po.ts | 采购订单校验 | PO 编号、金额、供应商信息 |\n| `supply_chain.validate_inputs_v0` | supply_chain.ts | 供应链输入校验 | 供应商 ID、名称、国家代码 |\n| `trade.validate_trade_v0` | trade.ts | 贸易交易校验 | 交易金额、方向、对手方 |\n| `content_flywheel.validate_context_v0` | content_flywheel.ts | 内容飞轮上下文 | 上下文数据完整性 |\n\n### 供应链验证器详解\n\n供应链验证器 (`supply_chain.validate_inputs_v0`) 是验证器模式的典型实现：\n\n```typescript\nexport const supplyChainValidators: Array<{ id: string; fn: ValidatorFn }> = [\n  {\n    id: \"supply_chain.validate_inputs_v0\",\n    fn: (inputs) => {\n      const suppliers = Array.isArray(inputs.suppliers) \n        ? inputs.suppliers as Record<string, unknown>[] \n        : [];\n      \n      const non_empty = suppliers.length > 0;\n      \n      const valid_items = suppliers.filter(s =>\n        s &&\n        typeof s === \"object\" &&\n        String(s[\"id\"]      || \"\").length > 0 &&\n        String(s[\"name\"]    || \"\").length > 0 &&\n        /^[A-Z]{2}$/.test(String(s[\"country\"] || \"\"))\n      );\n      \n      const invalid_count = suppliers.length - valid_items.length;\n      \n      return {\n        ok: true,\n        value: {\n          inputs_valid: non_empty && invalid_count === 0,\n          supplier_count: suppliers.length,\n          valid_supplier_count: valid_items.length,\n          invalid_supplier_count: invalid_count,\n          has_suppliers: non_empty,\n        },\n        step_id: \"validate_inputs\",\n      };\n    },\n  },\n];\n```\n\n**校验规则：**\n- `suppliers` 数组必须非空\n- 每个供应商必须包含 `id`（非空字符串）\n- 每个供应商必须包含 `name`（非空字符串）\n- 每个供应商必须包含 `country`（两位大写字母国家代码，如 `CN`、`US`）\n\n资料来源：[src/validators/supply_chain.ts:3-36]()\n\n### 信贷验证器详解\n\n信贷验证器 (`credit.validate_calcs_v0`) 实现了复杂的信用评估计算：\n\n```typescript\nexport const creditValidators = [\n  {\n    id: \"credit.validate_calcs_v0\",\n    fn: (inputs) => {\n      const income    = Number(inputs.monthly_income) || 0;\n      const debt      = Number(inputs.total_debt) || 0;\n      const bureau    = Number(inputs.bureau_score) || 0;\n      const requested = Number(inputs.requested_amount) || 0;\n      \n      const income_ok    = income > 0;\n      const bureau_ok    = bureau >= 300 && bureau <= 850;\n      const requested_ok = requested > 0;\n      \n      const dti = income_ok ? debt / (income * 12) : null;\n      \n      const hard_reject = bureau < 500 || (dti !== null && dti > 0.6);\n      \n      return {\n        ok: true,\n        value: {\n          calcs_valid: income_ok && bureau_ok && requested_ok,\n          monthly_income: income,\n          total_debt: debt,\n          bureau_score: bureau,\n          requested_amount: requested,\n          debt_to_income_ratio: dti,\n          hard_reject,\n          hard_reject_reason: hard_reject\n            ? (bureau < 500 ? \"bureau_score_below_500\" : \"dti_exceeds_60pct\")\n            : null,\n        },\n        step_id: \"validate_calcs\",\n      };\n    },\n  },\n];\n```\n\n**校验规则与计算：**\n\n| 检查项 | 规则 | 字段 |\n|--------|------|------|\n| 月收入 | 必须大于 0 | `income_ok` |\n| 征信评分 | 必须在 300-850 范围内 | `bureau_ok` |\n| 请求金额 | 必须大于 0 | `requested_ok` |\n| 债务收入比 (DTI) | 月债务 / (月收入 × 12) | `debt_to_income_ratio` |\n| 硬性拒绝 | 评分<500 或 DTI>60% | `hard_reject` |\n\n资料来源：[src/validators/credit.ts:3-47]()\n\n## 验证器执行流程\n\n### 远程 API 执行路径\n\n在 `remote_api.ts` 的 `movaRunStepsRemote` 函数中，验证器在 `analyze` 步骤完成后被调用：\n\n```mermaid\nsequenceDiagram\n    participant Client as MCP Client\n    participant API as MOVA API\n    participant Runner as movaRunStepsRemote\n    participant Registry as VALIDATOR_REGISTRY\n    \n    Client->>Runner: movaRunStepsRemote(contractId, validators, initialInputs)\n    Runner->>API: POST /api/v1/contracts/{id}/step (analyze)\n    \n    Note over Runner: 获取 analyze 步骤输出\n    \n    loop 每个验证器\n        Runner->>Registry: VALIDATOR_REGISTRY.get(validator.validator_id)\n        \n        alt 验证器存在\n            Registry-->>Runner: ValidatorFn\n            Runner->>Runner: fn(validatorContext)\n            Note over Runner: validatorContext = {...initialInputs, ...analysis}\n            \n            alt 验证成功\n                Runner->>Runner: Object.assign(analysis, resultValue.value)\n            else 验证失败\n                Runner->>Runner: analysis[\"{step_id}_error\"] = \"VALIDATOR_FAILED: {error}\"\n            end\n        else 验证器不存在\n            Runner->>Runner: analysis[\"{step_id}_error\"] = \"VALIDATOR_NOT_ALLOWED: ...\"\n        end\n    end\n    \n    Runner-->>Client: 返回包含 analysis 的结果\n```\n\n**关键代码片段：**\n\n```typescript\nconst validatorContext = { ...initialInputs, ...analysis };\n\nfor (const validator of validators) {\n  const fn = VALIDATOR_REGISTRY.get(validator.validator_id);\n  if (!fn) {\n    analysis[`${validator.step_id}_error`] = `VALIDATOR_NOT_ALLOWED: \"${validator.validator_id}\" not in registry`;\n    continue;\n  }\n  try {\n    const resultValue = fn(validatorContext);\n    Object.assign(analysis, resultValue.value ?? {});\n  } catch (error) {\n    analysis[`${validator.step_id}_error`] = `VALIDATOR_FAILED: ${String(error)}`;\n  }\n}\n```\n\n资料来源：[dist-test/src/transports/remote_api.js:1-30]()\n\n### 安全校验：步骤模式守卫\n\n验证器系统还包含安全校验机制 `step_mode_guard.ts`，确保步骤定义的一致性：\n\n```typescript\nexport function findStepModeViolations(flow: unknown): StepModeViolation[] {\n  const out: StepModeViolation[] = [];\n  \n  // 检查 AI_ATOMIC 步骤是否声明了 model 字段\n  if (mode === \"AI_ATOMIC\" && asStr(step.model) === null) {\n    out.push({\n      kind: \"ai_atomic_without_model\",\n      step_id: id,\n      execution_mode: mode,\n      message: `step '${id ?? \"?\"}' is AI_ATOMIC but has no 'model' field`,\n    });\n  }\n  \n  // 检查 CONTRACT_CALL 步骤是否声明了 contract_id\n  if (mode === \"CONTRACT_CALL\" && asStr(step.contract_id) === null) {\n    out.push({\n      kind: \"contract_call_without_contract_id\",\n      step_id: id,\n      execution_mode: mode,\n      message: `step '${id ?? \"?\"}' is CONTRACT_CALL but has no 'contract_id'`,\n    });\n  }\n  \n  // 检查 HUMAN_GATE 步骤是否声明了 decision_options\n  if (mode === \"HUMAN_GATE\" && !Array.isArray(step.decision_options)) {\n    out.push({\n      kind: \"human_gate_without_decisions\",\n      step_id: id,\n      execution_mode: mode,\n      message: `step '${id ?? \"?\"}' is HUMAN_GATE but has no 'decision_options' array`,\n    });\n  }\n  \n  return out;\n}\n```\n\n**模式违规类型：**\n\n| 违规类型 | 模式 | 期望字段 | 说明 |\n|----------|------|----------|------|\n| `deterministic_with_model` | DETERMINISTIC | 无 | DET 步骤不应声明 model |\n| `ai_atomic_without_model` | AI_ATOMIC | `model` | AI 步骤必须指定模型 |\n| `contract_call_without_contract_id` | CONTRACT_CALL | `contract_id` | 合约调用必须指定合约 ID |\n| `human_gate_without_decisions` | HUMAN_GATE | `decision_options` | 人工审批必须提供选项 |\n\n资料来源：[src/security/step_mode_guard.ts:1-70]()\n\n## 自定义验证器扩展\n\n### 创建新验证器步骤\n\n1. **定义验证器函数**\n\n```typescript\nimport type { ValidatorFn } from \"../types.js\";\n\nexport const customValidators: Array<{ id: string; fn: ValidatorFn }> = [\n  {\n    id: \"custom.validate_business_rule_v0\",\n    fn: (inputs) => {\n      // 业务校验逻辑\n      const isValid = /* 校验条件 */;\n      \n      return {\n        ok: true,\n        value: {\n          rule_valid: isValid,\n          // ... 其他业务指标\n        },\n        step_id: \"validate_business_rule\",\n      };\n    },\n  },\n];\n```\n\n2. **注册到注册表**\n\n在 `registry.ts` 中添加：\n\n```typescript\nimport { customValidators } from \"./custom.js\";\n\nfor (const { id, fn } of customValidators) {\n  VALIDATOR_REGISTRY.set(id, fn);\n}\n```\n\n3. **在合同清单中引用**\n\n```typescript\nexport const CONTRACT_MANIFESTS: Record<string, ContractManifest> = {\n  my_contract: {\n    contract_type: \"my_contract\",\n    validators: [\"custom.validate_business_rule_v0\"],\n    // ...\n  },\n};\n```\n\n## 验证结果处理\n\n### 成功路径\n\n验证成功时，结果被合并到 `analysis` 上下文中：\n\n```typescript\nconst resultValue = fn(validatorContext);\nObject.assign(analysis, resultValue.value ?? {});\n```\n\n后续步骤可以直接使用验证器计算出的业务指标。\n\n### 失败路径\n\n验证器执行失败时，会在 `analysis` 中记录错误：\n\n```typescript\n// 验证器函数抛出异常\nanalysis[`${validator.step_id}_error`] = `VALIDATOR_FAILED: ${String(error)}`;\n\n// 验证器未在注册表中注册\nanalysis[`${validator.step_id}_error`] = `VALIDATOR_NOT_ALLOWED: \"${validator.validator_id}\" not in registry`;\n```\n\n错误信息以 `{step_id}_error` 格式存储，便于追踪具体失败的验证步骤。\n\n## 最佳实践\n\n1. **幂等性**：验证器应设计为幂等函数，相同输入产生相同输出\n2. **无副作用**：验证器不应修改输入数据或产生外部影响\n3. **错误处理**：使用 try-catch 包裹验证逻辑，防止异常导致流程中断\n4. **返回完整上下文**：始终返回 `step_id` 字段，便于调试和追踪\n5. **类型安全**：使用 TypeScript 显式声明输入输出类型\n\n## 总结\n\n业务验证器是 mova-flat-runner 实现业务规则强制执行的核心机制。通过声明式的验证器注册和函数式的校验实现，系统能够在合同执行的各个阶段对输入数据进行可靠的业务规则校验，同时保持代码的可扩展性和可维护性。\n\n---\n\n<a id='page-deployment'></a>\n\n## 部署与运维\n\n### 相关页面\n\n相关主题：[安装与配置](#page-installation), [系统架构](#page-system-architecture)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [package.json](https://github.com/mova-compact/mova-flat-runner/blob/main/package.json)\n- [README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n- [src/index.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/index.ts)\n- [src/transports/local_seam_bridge.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/local_seam_bridge.ts)\n- [Makefile](https://github.com/mova-compact/mova-flat-runner/blob/main/Makefile)\n</details>\n\n# 部署与运维\n\n## 概述\n\nmova-flat-runner 是 MOVA 平台的 MCP（Model Context Protocol）服务器实现，提供受治理的 AI 工作流执行能力。该项目支持发票 OCR、AML 筛查、信用审查等业务流程，并可通过人类审批门（Human Approval Gates）实现人工介入，同时提供完整的审计追踪功能。\n\n本页面详细说明 mova-flat-runner 的部署模式、环境配置、运维命令以及运行时行为，帮助运维人员和开发者在不同环境中正确部署和监控该服务。\n\n---\n\n## 部署架构\n\n### MCP 服务器角色定位\n\nmova-flat-runner 在 MOVA 生态系统中充当 MCP Registry 的服务提供方，为 AI 客户端（如 Claude Desktop、Cursor、Codex）提供标准化的工具调用接口。客户端通过 MCP 协议与服务器通信，服务器再将请求转发至后端 MOVA API 进行实际业务处理。\n\n```mermaid\ngraph TD\n    A[\"👤 AI 客户端<br/>(Claude Desktop / Codex)\"] -->|\"MCP Protocol\"| B[\"mova-flat-runner<br/>(mova-mcp)\"]\n    B -->|\"HTTP REST API\"| C[\"MOVA API<br/>(api.mova-lab.eu)\"]\n    C -->|\"业务执行\"| D[\"后端服务集群\"]\n    \n    B -->|\"本地执行模式\"| E[\"Local Seam Bridge\"]\n    E -->|\"本地工作流\"| F[\"本地合约执行\"]\n    \n    style B fill:#4a90d9,color:#fff\n    style C fill:#67b868,color:#fff\n```\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n### 双执行模式\n\nmova-flat-runner 支持两种执行模式，根据配置自动选择：\n\n| 模式 | 触发条件 | 行为描述 |\n|------|----------|----------|\n| **远程 API 模式** | `MOVA_API_URL` 已配置且可达 | 通过 HTTP 调用 `api.mova-lab.eu` 后端 API |\n| **本地 HTTP 模式** | `MOVA_HTTP_PORT` 已配置 | 启动本地 HTTP 服务器，接收本地工作流请求 |\n\n资料来源：[src/index.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/index.ts)\n\n---\n\n## 环境变量配置\n\n### 必填环境变量\n\n以下环境变量必须在部署时配置，否则服务无法正常启动：\n\n| 变量名 | 说明 | 示例值 | 来源 |\n|--------|------|--------|------|\n| `MOVA_API_URL` | MOVA 后端 API 基础地址 | `https://api.mova-lab.eu` | README.md |\n| `MOVA_API_KEY` | 后端 API 认证密钥 | `__SET_MOVA_API_KEY__` | README.md |\n| `LLM_KEY` | LLM 提供商密钥 | `__SET_LLM_KEY__` | README.md |\n| `LLM_MODEL` | 使用的 LLM 模型标识 | `openai/gpt-4o-mini` | README.md |\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n### 可选本地 HTTP 模式变量\n\n当需要启用本地 HTTP 模式时，配置以下变量：\n\n| 变量名 | 说明 | 默认值 | 备注 |\n|--------|------|--------|------|\n| `MOVA_API_TIMEOUT_MS` | API 请求超时时间（毫秒） | `30000` | 可选配置 |\n| `MOVA_HTTP_PORT` | 本地 HTTP 服务监听端口 | `3796` | 设置后启用本地模式 |\n| `MOVA_INVOKE_TOKEN` | 本地调用认证令牌 | 无 | 用于保护本地 API 调用 |\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n### 本地沙箱环境变量\n\n在本地执行模式下，以下变量控制工作流和项目路径：\n\n| 变量名 | 说明 | 默认值 |\n|--------|------|--------|\n| `MOVA_SANDBOX_PACKAGE_PATH` | 合约包目录路径 | `D:\\Projects_MOVA\\mova-intent\\contracts\\dockerfile-nodejs-v1` |\n| `MOVA_SANDBOX_PROJECT_PATH` | 项目工作目录路径 | 空（必填） |\n\n资料来源：[src/transports/local_seam_bridge.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/local_seam_bridge.ts)\n\n---\n\n## 构建与打包\n\n### npm 构建流程\n\n项目使用 TypeScript 开发，通过 npm 脚本完成构建：\n\n```bash\nnpm run build\n```\n\n构建过程执行以下步骤：\n\n1. **TypeScript 编译**：调用 `tsc` 将 `src/` 目录下的 TypeScript 源文件编译为 JavaScript\n2. **Shebang 注入**：在 `dist/index.js` 头部添加 `#!/usr/bin/env node` 使其可执行\n3. **权限设置**：通过 `fs.chmodSync(p, 0o755)` 设置可执行权限\n\n资料来源：[package.json](https://github.com/mova-compact/mova-flat-runner/blob/main/package.json)\n\n### Makefile 便捷命令\n\n项目提供 Makefile 封装常用运维命令：\n\n| 命令 | 功能 | 资料来源 |\n|------|------|----------|\n| `make publisher` | 构建 MCP 发布工具 | README.md |\n| `make check` | 运行代码检查、单元测试和集成测试 | README.md |\n| `make help` | 显示所有可用命令 | README.md |\n\n```bash\n# 构建发布工具\nmake publisher\n\n# 运行完整检查\nmake check\n```\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n---\n\n## 安装与启动\n\n### npm 包方式（推荐）\n\n通过 npx 直接运行，无需全局安装：\n\n```bash\nnpx -y @leryk1981/mova-flat-runner@3.3.3\n```\n\n### 二进制直接运行\n\n构建后可直接运行二进制文件：\n\n```bash\n./bin/mcp-publisher --help\n```\n\n### MCP 服务器启动\n\nmova-flat-runner 作为 MCP 服务器运行，支持通过 MCP 协议与 AI 客户端集成。启动时必须正确配置环境变量：\n\n```bash\nexport MOVA_API_URL=https://api.mova-lab.eu\nexport MOVA_API_KEY=__SET_MOVA_API_KEY__\nexport LLM_KEY=__SET_LLM_KEY__\nexport LLM_MODEL=openai/gpt-4o-mini\n\n./dist/index.js\n```\n\n资料来源：[package.json](https://github.com/mova-compact/mova-flat-runner/blob/main/package.json)\n\n---\n\n## 客户端配置示例\n\n### Claude Desktop 配置\n\n在 Claude Desktop 的配置文件 `claude_desktop_config.json` 中添加以下内容：\n\n```json\n{\n  \"mcpServers\": {\n    \"mova\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@leryk1981/mova-flat-runner@3.3.3\"],\n      \"env\": {\n        \"MOVA_API_URL\": \"https://api.mova-lab.eu\",\n        \"MOVA_API_KEY\": \"__SET_MOVA_API_KEY__\",\n        \"LLM_KEY\": \"__SET_LLM_KEY__\",\n        \"LLM_MODEL\": \"openai/gpt-4o-mini\"\n      }\n    }\n  }\n}\n```\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n### Codex 配置（TOML 格式）\n\n```toml\n[mcp_servers.mova]\ncommand = \"npx\"\nargs = [\"-y\", \"@leryk1981/mova-flat-runner@3.3.3\"]\nstartup_timeout_sec = 90.0\n\n[mcp_servers.mova.env]\nMOVA_API_URL = \"https://api.mova-lab.eu\"\nMOVA_API_KEY = \"__SET_MOVA_API_KEY__\"\nLLM_KEY = \"__SET_LLM_KEY__\"\nLLM_MODEL = \"openai/gpt-4o-mini\"\n```\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n---\n\n## 健康检查\n\n### API 健康检查端点\n\nMOVA API 提供健康检查接口，可用于监控服务可用性：\n\n```bash\ncurl -sS https://api.mova-lab.eu/health\n```\n\n返回状态码 `200 OK` 表示服务正常运行。\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n---\n\n## 可用工具列表\n\nmova-flat-runner 通过 MCP 协议暴露以下工具，供 AI 客户端调用：\n\n| 工具名称 | 功能描述 | 资料来源 |\n|----------|----------|----------|\n| `mova_health` | 查询 MOVA API 健康状态 | README.md |\n| `mova_registry` | 查询可用合约注册表 | README.md |\n| `mova_run` | 执行内置合约工作流 | README.md |\n| `mova_query` | 查询合约运行状态和审计信息 | README.md |\n| `mova_decide` | 提交决策响应（用于人工审批门） | README.md |\n| `mova_connector` | 连接外部系统 | README.md |\n| `mova_contract` | 注册和管理自定义合约 | README.md |\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n---\n\n## 安全注意事项\n\n### 敏感信息保护\n\n⚠️ **重要提醒**：以下环境变量包含敏感凭证，**禁止**提交至版本控制系统：\n\n| 敏感变量 | 说明 |\n|----------|------|\n| `MOVA_API_KEY` | MOVA 后端 API 认证密钥 |\n| `LLM_KEY` | LLM 服务提供商密钥 |\n| `MOVA_INVOKE_TOKEN` | 本地调用认证令牌 |\n\n部署时应使用环境变量注入或密钥管理服务（如 AWS Secrets Manager、HashiCorp Vault）进行配置。\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n### 安全验证机制\n\nmova-flat-runner 内置安全检查机制：\n\n| 检查项 | 说明 | 资料来源 |\n|--------|------|----------|\n| **Step Mode 验证** | 验证步骤执行模式与字段定义的一致性 | src/security/step_mode_guard.ts |\n| **HUMAN_GATE 保护** | 防止通过通用 step_complete 操作跳过人工审批门 | src/index.ts |\n\n```typescript\n// HUMAN_GATE 安全检查示例\nconst gateGuard = await assertNotHumanGate(config, runId, stepId, requestId);\nif (gateGuard) return gateGuard;\n```\n\n资料来源：[src/index.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/index.ts)\n\n---\n\n## 自定义合约桥接机制\n\n### 问题背景\n\n对于非内置合约（custom contracts），其 ID 格式为 `local-*` 或 `remote-*`，存在 API 命名空间不一致问题：\n\n- `mova_contract register/run` 使用 `/run/*` 命名空间\n- `mova_query status/audit` 使用 `/api/v1/contracts/*` 命名空间\n\n### 桥接解决方案\n\n系统通过内存中的桥接映射表（`CUSTOM_RUN_BRIDGE`）维护 `contract_id → run_id` 映射：\n\n```mermaid\ngraph LR\n    A[\"mova_contract run\"] -->|\"创建运行\"| B[\"CUSTOM_RUN_BRIDGE<br/>Map<contractId, runId>\"]\n    B -->|\"查询状态\"| C[\"mova_query status\"]\n    C -->|\"404 时探测\"| D[\"/api/v1/contracts/my\"]\n    D -->|\"返回桥接状态\"| C\n```\n\n资料来源：[src/index.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/index.ts)\n\n---\n\n## 运维监控清单\n\n### 部署前检查项\n\n| 检查项 | 操作 |\n|--------|------|\n| ✅ 环境变量完整性 | 确认 `MOVA_API_KEY`、`LLM_KEY` 已正确配置 |\n| ✅ API 连通性 | 执行 `curl https://api.mova-lab.eu/health` 验证 |\n| ✅ 构建产物存在 | 确认 `dist/index.js` 已生成 |\n| ✅ 权限设置 | 确认二进制文件具有执行权限 |\n\n### 运行时监控指标\n\n| 指标 | 监控方式 |\n|------|----------|\n| API 响应时间 | 通过 `MOVA_API_TIMEOUT_MS` 配置超时阈值 |\n| 认证失败 | 监控 API 返回的 401/403 错误 |\n| 业务逻辑异常 | 监控 `step_complete`、`gate_approve` 返回的错误码 |\n\n### 常见问题排查\n\n| 症状 | 可能原因 | 解决方案 |\n|------|----------|----------|\n| `Unknown contract_type` | 使用了非内置合约 | 改用 `mova_contract action=run` |\n| `MOVA API 404` | 自定义合约在查询命名空间不存在 | 系统已内置桥接机制，查询 `mova_query status` |\n| 人工审批门被跳过 | 误用 `step_complete` 尝试完成 HUMAN_GATE | 使用 `gate_approve` 或 `gate_reject` |\n\n资料来源：[tasks/task061.md](https://github.com/mova-compact/mova-flat-runner/blob/main/tasks/task061.md)\n\n---\n\n## 版本信息\n\n| 属性 | 值 |\n|------|-----|\n| npm 包名 | `@leryk1981/mova-flat-runner` |\n| 当前版本 | `3.3.4` |\n| MCP 名称 | `io.github.mova-compact/mova-flat-runner` |\n| 构建目标 | `dist/index.js` |\n| 二进制入口 | `mova-mcp` |\n\n资料来源：[package.json](https://github.com/mova-compact/mova-flat-runner/blob/main/package.json)\n\n---\n\n---\n\n## Doramagic 踩坑日志\n\n项目：mova-compact/mova-flat-runner\n\n摘要：发现 8 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：配置坑 - 可能修改宿主 AI 配置。\n\n## 1. 配置坑 · 可能修改宿主 AI 配置\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：项目面向 Claude/Cursor/Codex/Gemini/OpenCode 等宿主，或安装命令涉及用户配置目录。\n- 对用户的影响：安装可能改变本机 AI 工具行为，用户需要知道写入位置和回滚方法。\n- 建议检查：列出会写入的配置文件、目录和卸载/回滚步骤。\n- 防护动作：涉及宿主配置目录时必须给回滚路径，不能只给安装命令。\n- 证据：capability.host_targets | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | host_targets=mcp_host, claude, chatgpt\n\n## 2. 配置坑 · 来源证据：v3.0.0 — Step Enforcement Runtime\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：GitHub 社区证据显示该项目存在一个配置相关的待验证问题：v3.0.0 — Step Enforcement Runtime\n- 对用户的影响：可能影响升级、迁移或版本选择。\n- 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。\n- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。\n- 证据：community_evidence:github | cevd_10b68dae59184a36b21a563722829aed | https://github.com/mova-compact/mova-flat-runner/releases/tag/v3.0.0 | 来源类型 github_release 暴露的待验证使用条件。\n\n## 3. 能力坑 · 能力判断依赖假设\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：README/documentation is current enough for a first validation pass.\n- 对用户的影响：假设不成立时，用户拿不到承诺的能力。\n- 建议检查：将假设转成下游验证清单。\n- 防护动作：假设必须转成验证项；没有验证结果前不能写成事实。\n- 证据：capability.assumptions | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | README/documentation is current enough for a first validation pass.\n\n## 4. 维护坑 · 维护活跃度未知\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：未记录 last_activity_observed。\n- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。\n- 建议检查：补 GitHub 最近 commit、release、issue/PR 响应信号。\n- 防护动作：维护活跃度未知时，推荐强度不能标为高信任。\n- 证据：evidence.maintainer_signals | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | last_activity_observed missing\n\n## 5. 安全/权限坑 · 下游验证发现风险项\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：no_demo\n- 对用户的影响：下游已经要求复核，不能在页面中弱化。\n- 建议检查：进入安全/权限治理复核队列。\n- 防护动作：下游风险存在时必须保持 review/recommendation 降级。\n- 证据：downstream_validation.risk_items | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | no_demo; severity=medium\n\n## 6. 安全/权限坑 · 存在评分风险\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：no_demo\n- 对用户的影响：风险会影响是否适合普通用户安装。\n- 建议检查：把风险写入边界卡，并确认是否需要人工复核。\n- 防护动作：评分风险必须进入边界卡，不能只作为内部分数。\n- 证据：risks.scoring_risks | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | no_demo; severity=medium\n\n## 7. 维护坑 · issue/PR 响应质量未知\n\n- 严重度：low\n- 证据强度：source_linked\n- 发现：issue_or_pr_quality=unknown。\n- 对用户的影响：用户无法判断遇到问题后是否有人维护。\n- 建议检查：抽样最近 issue/PR，判断是否长期无人处理。\n- 防护动作：issue/PR 响应未知时，必须提示维护风险。\n- 证据：evidence.maintainer_signals | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | issue_or_pr_quality=unknown\n\n## 8. 维护坑 · 发布节奏不明确\n\n- 严重度：low\n- 证据强度：source_linked\n- 发现：release_recency=unknown。\n- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。\n- 建议检查：确认最近 release/tag 和 README 安装命令是否一致。\n- 防护动作：发布节奏未知或过期时，安装说明必须标注可能漂移。\n- 证据：evidence.maintainer_signals | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | release_recency=unknown\n\n<!-- canonical_name: mova-compact/mova-flat-runner; human_manual_source: deepwiki_human_wiki -->\n",
      "markdown_key": "mova-flat-runner",
      "pages": "draft",
      "source_refs": [
        {
          "evidence_id": "github_repo:1212840167",
          "kind": "repo",
          "supports_claim_ids": [
            "claim_identity",
            "claim_distribution",
            "claim_capability"
          ],
          "url": "https://github.com/mova-compact/mova-flat-runner"
        },
        {
          "evidence_id": "art_3c8daee931ea4ef491323c91edd1b001",
          "kind": "docs",
          "supports_claim_ids": [
            "claim_identity",
            "claim_distribution",
            "claim_capability"
          ],
          "url": "https://github.com/mova-compact/mova-flat-runner#readme"
        }
      ],
      "summary": "DeepWiki/Human Wiki 完整输出，末尾追加 Discovery Agent 踩坑日志。",
      "title": "mova-flat-runner 说明书",
      "toc": [
        "https://github.com/mova-compact/mova-flat-runner 项目说明书",
        "目录",
        "项目介绍",
        "概述",
        "项目架构",
        "可用工具",
        "安全机制",
        "包验证系统",
        "Doramagic 踩坑日志"
      ]
    }
  },
  "quality_gate": {
    "blocking_gaps": [],
    "category_confidence": "medium",
    "compile_status": "ready_for_review",
    "five_assets_present": true,
    "install_sandbox_verified": true,
    "missing_evidence": [],
    "next_action": "publish to Doramagic.ai project surfaces",
    "prompt_preview_boundary_ok": true,
    "publish_status": "publishable",
    "quick_start_verified": true,
    "repo_clone_verified": true,
    "repo_commit": "e19d6945aa0befed8d0508bbe47ba81a8888786e",
    "repo_inspection_error": null,
    "repo_inspection_files": [
      "package.json",
      "README.md",
      "docs/LOCAL_MSR_RUNTIME_RUN_AUDIT_V0.md",
      "docs/PROMOTION_PATCH_2_NOTE_v1.md",
      "docs/CODEX_NATIVE_MCP_SETUP_V0.md",
      "docs/FLAT_RUNNER_BOUNDARY_v0.md",
      "docs/CONTENT_FLYWHEEL_REGISTERED_PACK_RUNBOOK_V0.md",
      "docs/MCP_PACKAGE_GLOBAL_SUPPORT_V0.md",
      "docs/MCP_CONTRACT_EXTENSION_AUDIT_V0.md",
      "docs/PACKAGE_GLOBAL_PARITY_AUDIT_V0.md",
      "docs/LOCAL_MSR_RUNTIME_RUN_AUDIT_RESULT.json",
      "src/schemas.ts",
      "src/index.ts",
      "src/client.ts",
      "src/types.ts",
      "src/package_support.ts",
      "src/transports/remote_api.ts",
      "src/transports/local_seam_bridge.ts",
      "src/validators/trade.ts",
      "src/validators/invoice.ts",
      "src/validators/compliance.ts",
      "src/validators/credit.ts",
      "src/validators/supply_chain.ts",
      "src/validators/registry.ts",
      "src/validators/complaint.ts",
      "src/validators/churn.ts",
      "src/validators/contract_gen.ts",
      "src/validators/aml.ts",
      "src/validators/po.ts",
      "src/validation/dataspec.ts",
      "src/security/system_contract_guard.ts",
      "src/security/determinism_guard.ts",
      "src/security/flow_schema_guard.ts",
      "src/security/graph_guard.ts",
      "src/security/gate_guard.ts",
      "src/security/class_definition_guard.ts",
      "src/security/step_mode_guard.ts"
    ],
    "repo_inspection_verified": true,
    "review_reasons": [
      "community_discussion_evidence_below_public_threshold"
    ],
    "tag_count_ok": true,
    "unsupported_claims": []
  },
  "schema_version": "0.1",
  "user_assets": {
    "ai_context_pack": {
      "asset_id": "ai_context_pack",
      "filename": "AI_CONTEXT_PACK.md",
      "markdown": "# @leryk1981/mova-flat-runner - Doramagic AI Context Pack\n\n> 定位：安装前体验与判断资产。它帮助宿主 AI 有一个好的开始，但不代表已经安装、执行或验证目标项目。\n\n## 充分原则\n\n- **充分原则，不是压缩原则**：AI Context Pack 应该充分到让宿主 AI 在开工前理解项目价值、能力边界、使用入口、风险和证据来源；它可以分层组织，但不以最短摘要为目标。\n- **压缩策略**：只压缩噪声和重复内容，不压缩会影响判断和开工质量的上下文。\n\n## 给宿主 AI 的使用方式\n\n你正在读取 Doramagic 为 @leryk1981/mova-flat-runner 编译的 AI Context Pack。请把它当作开工前上下文：帮助用户理解适合谁、能做什么、如何开始、哪些必须安装后验证、风险在哪里。不要声称你已经安装、运行或执行了目标项目。\n\n## Claim 消费规则\n\n- **事实来源**：Repo Evidence + Claim/Evidence Graph；Human Wiki 只提供显著性、术语和叙事结构。\n- **事实最低状态**：`supported`\n- `supported`：可以作为项目事实使用，但回答中必须引用 claim_id 和证据路径。\n- `weak`：只能作为低置信度线索，必须要求用户继续核实。\n- `inferred`：只能用于风险提示或待确认问题，不能包装成项目事实。\n- `unverified`：不得作为事实使用，应明确说证据不足。\n- `contradicted`：必须展示冲突来源，不得替用户强行选择一个版本。\n\n## 它最适合谁\n\n- **正在使用 Claude/Codex/Cursor/Gemini 等宿主 AI 的开发者**：README 或插件配置提到多个宿主 AI。 证据：`README.md` Claim：`clm_0002` supported 0.86\n\n## 它能做什么\n\n- **命令行启动或安装流程**（需要安装后验证）：项目文档中存在可执行命令，真实使用需要在本地或宿主环境中运行这些命令。 证据：`README.md` Claim：`clm_0001` supported 0.86\n\n## 怎么开始\n\n- `curl -sS https://api.mova-lab.eu/health` 证据：`README.md` Claim：`clm_0003` supported 0.86\n\n## 继续前判断卡\n\n- **当前建议**：需要管理员/安全审批\n- **为什么**：继续前可能涉及密钥、账号、外部服务或敏感上下文，建议先经过管理员或安全审批。\n\n### 30 秒判断\n\n- **现在怎么做**：需要管理员/安全审批\n- **最小安全下一步**：先跑 Prompt Preview；若涉及凭证或企业环境，先审批再试装\n- **先别相信**：工具权限边界不能在安装前相信。\n- **继续会触碰**：命令执行、本地环境或项目文件、环境变量 / API Key\n\n### 现在可以相信\n\n- **适合人群线索：正在使用 Claude/Codex/Cursor/Gemini 等宿主 AI 的开发者**（supported）：有 supported claim 或项目证据支撑，但仍不等于真实安装效果。 证据：`README.md` Claim：`clm_0002` supported 0.86\n- **能力存在：命令行启动或安装流程**（supported）：可以相信项目包含这类能力线索；是否适合你的具体任务仍要试用或安装后验证。 证据：`README.md` Claim：`clm_0001` supported 0.86\n- **存在 Quick Start / 安装命令线索**（supported）：可以相信项目文档出现过启动或安装入口；不要因此直接在主力环境运行。 证据：`README.md` Claim：`clm_0003` supported 0.86\n\n### 现在还不能相信\n\n- **工具权限边界不能在安装前相信。**（unverified）：MCP/tool 类项目通常会触碰文件、网络、浏览器或外部 API，必须真实检查权限和日志。\n- **真实输出质量不能在安装前相信。**（unverified）：Prompt Preview 只能展示引导方式，不能证明真实项目中的结果质量。\n- **宿主 AI 版本兼容性不能在安装前相信。**（unverified）：Claude、Cursor、Codex、Gemini 等宿主加载规则和版本差异必须在真实环境验证。\n- **不会污染现有宿主 AI 行为，不能直接相信。**（inferred）：Skill、plugin、AGENTS/CLAUDE/GEMINI 指令可能改变宿主 AI 的默认行为。\n- **可安全回滚不能默认相信。**（unverified）：除非项目明确提供卸载和恢复说明，否则必须先在隔离环境验证。\n- **真实安装后是否与用户当前宿主 AI 版本兼容？**（unverified）：兼容性只能通过实际宿主环境验证。\n- **项目输出质量是否满足用户具体任务？**（unverified）：安装前预览只能展示流程和边界，不能替代真实评测。\n- **安装命令是否需要网络、权限或全局写入？**（unverified）：这影响企业环境和个人环境的安装风险。 证据：`README.md`\n\n### 继续会触碰什么\n\n- **命令执行**：包管理器、网络下载、本地插件目录、项目配置或用户主目录。 原因：运行第一条命令就可能产生环境改动；必须先判断是否值得跑。 证据：`README.md`\n- **本地环境或项目文件**：安装结果、插件缓存、项目配置或本地依赖目录。 原因：安装前无法证明写入范围和回滚方式，需要隔离验证。 证据：`README.md`\n- **环境变量 / API Key**：项目入口文档明确出现 API key、token、secret 或账号凭证配置。 原因：如果真实安装需要凭证，应先使用测试凭证并经过权限/合规判断。 证据：`README.md`, `dist-test/src/index.js`, `dist-test/tests/smoke/api.d.ts`, `dist-test/tests/smoke/api.js` 等\n- **宿主 AI 上下文**：AI Context Pack、Prompt Preview、Skill 路由、风险规则和项目事实。 原因：导入上下文会影响宿主 AI 后续判断，必须避免把未验证项包装成事实。\n\n### 最小安全下一步\n\n- **先跑 Prompt Preview**：用安装前交互式试用判断工作方式是否匹配，不需要授权或改环境。（适用：任何项目都适用，尤其是输出质量未知时。）\n- **只在隔离目录或测试账号试装**：避免安装命令污染主力宿主 AI、真实项目或用户主目录。（适用：存在命令执行、插件配置或本地写入线索时。）\n- **不要使用真实生产凭证**：环境变量/API key 一旦进入宿主或工具链，可能产生账号和合规风险。（适用：出现 API、TOKEN、KEY、SECRET 等环境线索时。）\n- **安装后只验证一个最小任务**：先验证加载、兼容、输出质量和回滚，再决定是否深用。（适用：准备从试用进入真实工作流时。）\n\n### 退出方式\n\n- **保留安装前状态**：记录原始宿主配置和项目状态，后续才能判断是否可恢复。\n- **记录安装命令和写入路径**：没有明确卸载说明时，至少要知道哪些目录或配置需要手动清理。\n- **准备撤销测试 API key 或 token**：测试凭证泄露或误用时，可以快速止损。\n- **如果没有回滚路径，不进入主力环境**：不可回滚是继续前阻断项，不应靠信任或运气继续。\n\n## 哪些只能预览\n\n- 解释项目适合谁和能做什么\n- 基于项目文档演示典型对话流程\n- 帮助用户判断是否值得安装或继续研究\n\n## 哪些必须安装后验证\n\n- 真实安装 Skill、插件或 CLI\n- 执行脚本、修改本地文件或访问外部服务\n- 验证真实输出质量、性能和兼容性\n\n## 边界与风险判断卡\n\n- **把安装前预览误认为真实运行**：用户可能高估项目已经完成的配置、权限和兼容性验证。 处理方式：明确区分 prompt_preview_can_do 与 runtime_required。 Claim：`clm_0004` inferred 0.45\n- **命令执行会修改本地环境**：安装命令可能写入用户主目录、宿主插件目录或项目配置。 处理方式：先在隔离环境或测试账号中运行。 证据：`README.md` Claim：`clm_0005` supported 0.86\n- **待确认**：真实安装后是否与用户当前宿主 AI 版本兼容？。原因：兼容性只能通过实际宿主环境验证。\n- **待确认**：项目输出质量是否满足用户具体任务？。原因：安装前预览只能展示流程和边界，不能替代真实评测。\n- **待确认**：安装命令是否需要网络、权限或全局写入？。原因：这影响企业环境和个人环境的安装风险。\n\n## 开工前工作上下文\n\n### 加载顺序\n\n- 先读取 how_to_use.host_ai_instruction，建立安装前判断资产的边界。\n- 读取 claim_graph_summary，确认事实来自 Claim/Evidence Graph，而不是 Human Wiki 叙事。\n- 再读取 intended_users、capabilities 和 quick_start_candidates，判断用户是否匹配。\n- 需要执行具体任务时，优先查 role_skill_index，再查 evidence_index。\n- 遇到真实安装、文件修改、网络访问、性能或兼容性问题时，转入 risk_card 和 boundaries.runtime_required。\n\n### 任务路由\n\n- **命令行启动或安装流程**：先说明这是安装后验证能力，再给出安装前检查清单。 边界：必须真实安装或运行后验证。 证据：`README.md` Claim：`clm_0001` supported 0.86\n\n### 上下文规模\n\n- 文件总数：152\n- 重要文件覆盖：31/152\n- 证据索引条目：31\n- 角色 / Skill 条目：11\n\n### 证据不足时的处理\n\n- **missing_evidence**：说明证据不足，要求用户提供目标文件、README 段落或安装后验证记录；不要补全事实。\n- **out_of_scope_request**：说明该任务超出当前 AI Context Pack 证据范围，并建议用户先查看 Human Manual 或真实安装后验证。\n- **runtime_request**：给出安装前检查清单和命令来源，但不要替用户执行命令或声称已执行。\n- **source_conflict**：同时展示冲突来源，标记为待核实，不要强行选择一个版本。\n\n## Prompt Recipes\n\n### 适配判断\n\n- 目标：判断这个项目是否适合用户当前任务。\n- 预期输出：适配结论、关键理由、证据引用、安装前可预览内容、必须安装后验证内容、下一步建议。\n\n```text\n请基于 @leryk1981/mova-flat-runner 的 AI Context Pack，先问我 3 个必要问题，然后判断它是否适合我的任务。回答必须包含：适合谁、能做什么、不能做什么、是否值得安装、证据来自哪里。所有项目事实必须引用 evidence_refs、source_paths 或 claim_id。\n```\n\n### 安装前体验\n\n- 目标：让用户在安装前感受核心工作流，同时避免把预览包装成真实能力或营销承诺。\n- 预期输出：一段带边界标签的体验剧本、安装后验证清单和谨慎建议；不含真实运行承诺或强营销表述。\n\n```text\n请把 @leryk1981/mova-flat-runner 当作安装前体验资产，而不是已安装工具或真实运行环境。\n\n请严格输出四段：\n1. 先问我 3 个必要问题。\n2. 给出一段“体验剧本”：用 [安装前可预览]、[必须安装后验证]、[证据不足] 三种标签展示它可能如何引导工作流。\n3. 给出安装后验证清单：列出哪些能力只有真实安装、真实宿主加载、真实项目运行后才能确认。\n4. 给出谨慎建议：只能说“值得继续研究/试装”“先补充信息后再判断”或“不建议继续”，不得替项目背书。\n\n硬性边界：\n- 不要声称已经安装、运行、执行测试、修改文件或产生真实结果。\n- 不要写“自动适配”“确保通过”“完美适配”“强烈建议安装”等承诺性表达。\n- 如果描述安装后的工作方式，必须使用“如果安装成功且宿主正确加载 Skill，它可能会……”这种条件句。\n- 体验剧本只能写成“示例台词/假设流程”：使用“可能会询问/可能会建议/可能会展示”，不要写“已写入、已生成、已通过、正在运行、正在生成”。\n- Prompt Preview 不负责给安装命令；如用户准备试装，只能提示先阅读 Quick Start 和 Risk Card，并在隔离环境验证。\n- 所有项目事实必须来自 supported claim、evidence_refs 或 source_paths；inferred/unverified 只能作风险或待确认项。\n\n```\n\n### 角色 / Skill 选择\n\n- 目标：从项目里的角色或 Skill 中挑选最匹配的资产。\n- 预期输出：候选角色或 Skill 列表，每项包含适用场景、证据路径、风险边界和是否需要安装后验证。\n\n```text\n请读取 role_skill_index，根据我的目标任务推荐 3-5 个最相关的角色或 Skill。每个推荐都要说明适用场景、可能输出、风险边界和 evidence_refs。\n```\n\n### 风险预检\n\n- 目标：安装或引入前识别环境、权限、规则冲突和质量风险。\n- 预期输出：环境、权限、依赖、许可、宿主冲突、质量风险和未知项的检查清单。\n\n```text\n请基于 risk_card、boundaries 和 quick_start_candidates，给我一份安装前风险预检清单。不要替我执行命令，只说明我应该检查什么、为什么检查、失败会有什么影响。\n```\n\n### 宿主 AI 开工指令\n\n- 目标：把项目上下文转成一次对话开始前的宿主 AI 指令。\n- 预期输出：一段边界明确、证据引用明确、适合复制给宿主 AI 的开工前指令。\n\n```text\n请基于 @leryk1981/mova-flat-runner 的 AI Context Pack，生成一段我可以粘贴给宿主 AI 的开工前指令。这段指令必须遵守 not_runtime=true，不能声称项目已经安装、运行或产生真实结果。\n```\n\n\n## 角色 / Skill 索引\n\n- 共索引 11 个角色 / Skill / 项目文档条目。\n\n- **MCP Registry**（project_doc）：Authoritative native MCP connection: - npm package: @leryk1981/mova-flat-runner - version: 3.3.3 - binary: mova-mcp - command: npx -y @leryk1981/mova-flat-runner@3.3.3 激活提示：当用户需要理解项目结构、安装方式或边界时参考。 证据：`README.md`\n- **Package Global Support Fixture**（project_doc）：This fixture exercises package-manifest registration with optional global ref . 激活提示：当用户需要理解项目结构、安装方式或边界时参考。 证据：`tests/fixtures/package_global_support_v0/README.md`\n- **CODEX Native MCP Setup V0**（project_doc）：Date: 2026-05-08 Repository: D:\\Projects MOVA\\mova-mcp 激活提示：当用户需要理解项目结构、安装方式或边界时参考。 证据：`docs/CODEX_NATIVE_MCP_SETUP_V0.md`\n- **Content Flywheel Registered Pack Runbook v0**（project_doc）：Content Flywheel Registered Pack Runbook v0 激活提示：当用户需要理解项目结构、安装方式或边界时参考。 证据：`docs/CONTENT_FLYWHEEL_REGISTERED_PACK_RUNBOOK_V0.md`\n- **MOVA Flat Runner — Layer Boundary v0**（project_doc）：MOVA Flat Runner — Layer Boundary v0 激活提示：当用户需要理解项目结构、安装方式或边界时参考。 证据：`docs/FLAT_RUNNER_BOUNDARY_v0.md`\n- **LOCAL MSR RUNTIME RUN AUDIT V0**（project_doc）：Date: 2026-05-08 Repo: D:/Projects MOVA/mova-mcp 激活提示：当用户需要理解项目结构、安装方式或边界时参考。 证据：`docs/LOCAL_MSR_RUNTIME_RUN_AUDIT_V0.md`\n- **MCP Contract Extension Audit v0**（project_doc）：mova-mcp currently exposes two contract models in parallel: 激活提示：当用户需要理解项目结构、安装方式或边界时参考。 证据：`docs/MCP_CONTRACT_EXTENSION_AUDIT_V0.md`\n- **MCP Package Global Support v0**（project_doc）：mova-mcp supports optional package-local global ref on package manifests as read-only semantic metadata. 激活提示：当用户需要理解项目结构、安装方式或边界时参考。 证据：`docs/MCP_PACKAGE_GLOBAL_SUPPORT_V0.md`\n- **Package Global Parity Audit v0**（project_doc）：Core package-global parity is present between mova-contract-spec@e657b77 and mova-mcp@747b5c2 , including field naming schema id and non-authoritative intent. 激活提示：当用户需要理解项目结构、安装方式或边界时参考。 证据：`docs/PACKAGE_GLOBAL_PARITY_AUDIT_V0.md`\n- **Promotion Patch 2 Note v1**（project_doc）：What Was Moved Into mova-flat-runner - bridged local transport in src/transports/local seam bridge.ts - remote transport in src/transports/remote api.ts - thin facade and selector in src/client.ts - canonical freeze test and bridged e2e test 激活提示：当用户需要理解项目结构、安装方式或边界时参考。 证据：`docs/PROMOTION_PATCH_2_NOTE_v1.md`\n- **task061 — Fix custom contract audit identity bridge in mova-mcp**（project_doc）：task061 — Fix custom contract audit identity bridge in mova-mcp 激活提示：当用户需要理解项目结构、安装方式或边界时参考。 证据：`tasks/task061.md`\n\n## 证据索引\n\n- 共索引 31 条证据。\n\n- **MCP Registry**（documentation）：Authoritative native MCP connection: - npm package: @leryk1981/mova-flat-runner - version: 3.3.3 - binary: mova-mcp - command: npx -y @leryk1981/mova-flat-runner@3.3.3 证据：`README.md`\n- **Package Global Support Fixture**（documentation）：This fixture exercises package-manifest registration with optional global ref . 证据：`tests/fixtures/package_global_support_v0/README.md`\n- **Package**（package_manifest）：{ \"name\": \"@leryk1981/mova-flat-runner\", \"version\": \"3.3.4\", \"mcpName\": \"io.github.mova-compact/mova-flat-runner\", \"description\": \"MCP server for governed AI workflows — invoice OCR, AML triage, credit review, and custom contracts with human approval gates and audit trails\", \"type\": \"module\", \"license\": \"MIT-0\", \"keywords\": \"mcp\", \"mcp-server\", \"model-context-protocol\", \"claude\", \"cursor\", \"anthropic\", \"hitl\", \"human-in-the-loop\", \"audit-trail\", \"invoice-ocr\", \"aml\", \"compliance\", \"workflow-automation\", \"contract-execution\", \"mova\" , \"homepage\": \"https://github.com/mova-compact/mova-flat-runner\", \"repository\": { \"type\": \"git\", \"url\": \"git+https://github.com/mova-compact/mova-flat-runner.git… 证据：`package.json`\n- **License**（source_file）：The MCP project is undergoing a licensing transition from the MIT License to the Apache License, Version 2.0 \"Apache-2.0\" . All new code and specification contributions to the project are licensed under Apache-2.0. Documentation contributions excluding specifications are licensed under CC-BY-4.0. 证据：`LICENSE`\n- **CODEX Native MCP Setup V0**（documentation）：Date: 2026-05-08 Repository: D:\\Projects MOVA\\mova-mcp 证据：`docs/CODEX_NATIVE_MCP_SETUP_V0.md`\n- **Content Flywheel Registered Pack Runbook v0**（documentation）：Content Flywheel Registered Pack Runbook v0 证据：`docs/CONTENT_FLYWHEEL_REGISTERED_PACK_RUNBOOK_V0.md`\n- **MOVA Flat Runner — Layer Boundary v0**（documentation）：MOVA Flat Runner — Layer Boundary v0 证据：`docs/FLAT_RUNNER_BOUNDARY_v0.md`\n- **LOCAL MSR RUNTIME RUN AUDIT V0**（documentation）：Date: 2026-05-08 Repo: D:/Projects MOVA/mova-mcp 证据：`docs/LOCAL_MSR_RUNTIME_RUN_AUDIT_V0.md`\n- **MCP Contract Extension Audit v0**（documentation）：mova-mcp currently exposes two contract models in parallel: 证据：`docs/MCP_CONTRACT_EXTENSION_AUDIT_V0.md`\n- **MCP Package Global Support v0**（documentation）：mova-mcp supports optional package-local global ref on package manifests as read-only semantic metadata. 证据：`docs/MCP_PACKAGE_GLOBAL_SUPPORT_V0.md`\n- **Package Global Parity Audit v0**（documentation）：Core package-global parity is present between mova-contract-spec@e657b77 and mova-mcp@747b5c2 , including field naming schema id and non-authoritative intent. 证据：`docs/PACKAGE_GLOBAL_PARITY_AUDIT_V0.md`\n- **Promotion Patch 2 Note v1**（documentation）：What Was Moved Into mova-flat-runner - bridged local transport in src/transports/local seam bridge.ts - remote transport in src/transports/remote api.ts - thin facade and selector in src/client.ts - canonical freeze test and bridged e2e test 证据：`docs/PROMOTION_PATCH_2_NOTE_v1.md`\n- **task061 — Fix custom contract audit identity bridge in mova-mcp**（documentation）：task061 — Fix custom contract audit identity bridge in mova-mcp 证据：`tasks/task061.md`\n- **Local Msr Runtime Run Audit Result**（structured_config）：{ \"started at\": \"2026-05-08T14:39:25.909Z\", \"launch method\": { \"working directory\": \"D:/Projects MOVA/mova-mcp\", \"command\": \"node dist/index.js\", \"transport\": \"local HTTP invoke endpoint /invoke \", \"url\": \"http://127.0.0.1:3796/invoke\", \"auth\": \"Bearer MOVA INVOKE TOKEN\", \"env keys used\": \"MOVA API URL\", \"MOVA API KEY\", \"LLM KEY\", \"LLM MODEL\", \"MOVA API TIMEOUT MS\", \"MOVA HTTP PORT\", \"MOVA INVOKE TOKEN\" }, \"invocation shape\": { \"request body\": \"{ \\\"tool\\\": \\\" \\\", \\\"args\\\": { ... } }\", \"tools tested\": \"mova health\", \"mova run\", \"mova query\", \"mova contract\" }, \"candidates tested\": { \"id\": \"health\", \"tool\": \"mova health\", \"payload\": {}, \"source path\": null, \"result\": { \"ok\": true, \"request id… 证据：`docs/LOCAL_MSR_RUNTIME_RUN_AUDIT_RESULT.json`\n- **Server**（structured_config）：{ \"$schema\": \"https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json\", \"name\": \"io.github.mova-compact/mova-flat-runner\", \"version\": \"2.0.6\", \"description\": \"Governed AI workflows with human approval gates and audit trails for Claude and MCP clients.\", \"repository\": { \"url\": \"https://github.com/mova-compact/mova-flat-runner\", \"source\": \"github\" }, \"packages\": { \"registryType\": \"npm\", \"identifier\": \"mova-mcp\", \"version\": \"2.0.6\", \"runtimeHint\": \"node\", \"transport\": { \"type\": \"stdio\" }, \"environmentVariables\": { \"name\": \"MOVA API KEY\", \"description\": \"MOVA API key. Use test-key-001 to get started without registration.\", \"required\": true }, { \"name\": \"LLM KEY\", \"descripti… 证据：`server.json`\n- **Tsconfig**（structured_config）：{ \"compilerOptions\": { \"target\": \"ES2022\", \"module\": \"NodeNext\", \"moduleResolution\": \"NodeNext\", \"outDir\": \"./dist\", \"rootDir\": \"./src\", \"strict\": true, \"esModuleInterop\": true, \"skipLibCheck\": true, \"declaration\": true }, \"include\": \"src/ / \" } 证据：`tsconfig.json`\n- **Tsconfig.Test**（structured_config）：{ \"extends\": \"./tsconfig.json\", \"compilerOptions\": { \"rootDir\": \".\", \"outDir\": \"./dist-test\" }, \"include\": \"src/ / \", \"tests/ / \" } 证据：`tsconfig.test.json`\n- **Flow**（structured_config）：{ \"version\": \"1.0\", \"description\": \"Minimal external pack flow fixture for registration-path guard smoke.\", \"entry\": \"analyze\", \"steps\": { \"id\": \"analyze\", \"execution mode\": \"AI ATOMIC\", \"model\": \"openai/gpt-4o-mini\", \"next\": { \"default\": { \"step\": \"verify\" } } }, { \"id\": \"verify\", \"execution mode\": \"DETERMINISTIC\", \"next\": { \"default\": { \"step\": \"decide\" } } }, { \"id\": \"decide\", \"execution mode\": \"HUMAN GATE\", \"decision options\": { \"option id\": \"APPROVED FOR PUBLICATION\", \"label\": \"Approve\" }, { \"option id\": \"NEEDS REWRITE\", \"label\": \"Rewrite\" } , \"next\": { \"approved\": { \"terminal\": \"published\" }, \"default\": { \"terminal\": \"stopped\" } } } } 证据：`tests/fixtures/content_flywheel_registered_pack/flow.json`\n- **Flow**（structured_config）：{ \"version\": \"1.0\", \"description\": \"Minimal external pack flow fixture for registration-path guard smoke.\", \"entry\": \"analyze\", \"steps\": { \"id\": \"analyze\", \"execution mode\": \"AI ATOMIC\", \"model\": \"openai/gpt-4o-mini\", \"next\": { \"default\": { \"step\": \"verify\" } } }, { \"id\": \"verify\", \"execution mode\": \"DETERMINISTIC\", \"next\": { \"default\": { \"step\": \"decide\" } } }, { \"id\": \"decide\", \"execution mode\": \"HUMAN GATE\", \"decision options\": { \"option id\": \"APPROVED FOR PUBLICATION\", \"label\": \"Approve\" }, { \"option id\": \"NEEDS REWRITE\", \"label\": \"Rewrite\" } , \"next\": { \"approved\": { \"terminal\": \"published\" }, \"default\": { \"terminal\": \"stopped\" } } } } 证据：`tests/fixtures/package_global_support_v0/flow.json`\n- **Global**（structured_config）：{ \"schema id\": \"package.global v0\", \"global id\": \"content flywheel pipeline global v0\", \"version\": \"0.1.0\", \"scope\": \"contract package\", \"extends\": , \"semantic roles\": { \"id\": \"manifest\", \"role\": \"package manifest\", \"authority\": \"documentation\", \"maturity\": \"canonical\", \"applies to\": \"manifest.json\" , \"allowed use\": \"discover package metadata\", \"load package references\" , \"forbidden use\": \"execute runtime\", \"choose flow transitions\" , \"notes\": \"Package entrypoint and references only.\" }, { \"id\": \"flow\", \"role\": \"contract flow\", \"authority\": \"structural\", \"maturity\": \"canonical\", \"applies to\": \"flow.json\" , \"allowed use\": \"inspect step topology\", \"load flow structure\" , \"forbidden use\": \"ove… 证据：`tests/fixtures/package_global_support_v0/global.json`\n- **Manifest**（structured_config）：{ \"schema id\": \"package.contract package manifest v0\", \"package id\": \"content flywheel pipeline v0\", \"version\": \"0.1.0\", \"global ref\": \"global.json\", \"flow ref\": \"flow.json\", \"classification policy ref\": \"classification policy.json\", \"classification result set ref\": \"classification results.json\", \"classification result refs\": \"classification://analyze\", \"classification://verify\", \"classification://decide\" , \"runtime binding set ref\": \"runtime binding set.json\", \"model refs\": \"models/input model v0.json\", \"models/verification model v0.json\" , \"fixture refs\": \"fixtures/\" , \"package invariants\": \"global is non-authoritative semantic context only\" } 证据：`tests/fixtures/package_global_support_v0/manifest.json`\n- **.gitignore**（source_file）：node modules/ mcp-publisher.exe mcp-publisher.tar.gz registry-1.6.0.zip registry-1.6.0/ .env.local .global-run. .log .mova-http. .log 证据：`.gitignore`\n- **Smithery**（source_file）：name: mova-flat-runner displayName: MOVA Flat Runner description: Governed AI workflow execution for Claude and MCP-compatible clients. Run invoice OCR, AML triage, credit review, supplier screening, and custom contracts — each with a mandatory human decision gate and a cryptographically signed audit trail. 证据：`smithery.yaml`\n- **Client**（source_file）：import { type FlatRunnerResult, type ValidatorRef } from \"./types.js\"; import { type MovaConfig, isLocalSeamConfig, movaGetDecisionPointLocal, movaGetTerminalOutcomeLocal, movaResumeContractLocal, movaRunStepsLocal, movaSubmitDecisionLocal, shortId, } from \"./transports/local seam bridge.js\"; import { movaDelete, movaGet, movaPost, movaPut, movaRunStepsRemote, } from \"./transports/remote api.js\"; 证据：`src/client.ts`\n- **!/usr/bin/env node**（source_file）：!/usr/bin/env node import { Server } from \"@modelcontextprotocol/sdk/server/index.js\"; import { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\"; import { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\"; import { createServer } from \"node:http\"; import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListResourceTemplatesRequestSchema, } from \"@modelcontextprotocol/sdk/types.js\"; import { movaPost, movaGet, movaPut, movaDelete, movaRunSteps, shortId, type MovaConfig, } from \"./client.js\"; import { CONTRACT MANIFESTS, ENVELOPE SCHEMA } from \"./schemas.js\"; import { ERR, fla… 证据：`src/index.ts`\n- **Package Support**（source_file）：import fs from \"node:fs/promises\"; import path from \"node:path\"; 证据：`src/package_support.ts`\n- **Schemas**（source_file）：// ── MOVA Schema Layer ───────────────────────────────────────────────────────── // Contract manifests, DataSpecs, and Envelope type definitions. // This is the structural source of truth for the MCP server. // Business logic lives on the MOVA platform; this file carries only the // schema skeleton needed for input validation and Resource exposure. 证据：`src/schemas.ts`\n- **Types**（source_file）：// ── MOVA Flat Runner — canonical types ──────────────────────────────────────── 证据：`src/types.ts`\n- **Bridge Contract V1.Freeze.Test**（source_file）：import test from \"node:test\"; import assert from \"node:assert/strict\"; import fs from \"node:fs/promises\"; import os from \"node:os\"; import path from \"node:path\"; 证据：`tests/bridge_contract_v1.freeze.test.ts`\n- **Flat Runner Bridge V1.Test**（source_file）：import test from \"node:test\"; import assert from \"node:assert/strict\"; import fs from \"node:fs/promises\"; import os from \"node:os\"; import path from \"node:path\"; 证据：`tests/flat_runner_bridge_v1.test.ts`\n- **Start Http Local**（source_file）：$envFile = Join-Path $PSScriptRoot '..\\.env.local' if ! Test-Path -LiteralPath $envFile { throw \".env.local not found at $envFile\" } Get-Content -LiteralPath $envFile ForEach-Object { if $ -match '^ A-Z0-9 +=' { $k,$v = $ .Split '=',2 Environment ::SetEnvironmentVariable $k,$v,'Process' } } $root = Resolve-Path Join-Path $PSScriptRoot '..' Set-Location $root & 'D:\\DevTools\\node.exe' 'dist/index.js' 证据：`tools/start-http-local.ps1`\n\n## 宿主 AI 必须遵守的规则\n\n- **把本资产当作开工前上下文，而不是运行环境。**：AI Context Pack 只包含证据化项目理解，不包含目标项目的可执行状态。 证据：`README.md`, `tests/fixtures/package_global_support_v0/README.md`, `package.json`\n- **回答用户时区分可预览内容与必须安装后才能验证的内容。**：安装前体验的消费者价值来自降低误装和误判，而不是伪装成真实运行。 证据：`README.md`, `tests/fixtures/package_global_support_v0/README.md`, `package.json`\n\n## 用户开工前应该回答的问题\n\n- 你准备在哪个宿主 AI 或本地环境中使用它？\n- 你只是想先体验工作流，还是准备真实安装？\n- 你最在意的是安装成本、输出质量、还是和现有规则的冲突？\n\n## 验收标准\n\n- 所有能力声明都能回指到 evidence_refs 中的文件路径。\n- AI_CONTEXT_PACK.md 没有把预览包装成真实运行。\n- 用户能在 3 分钟内看懂适合谁、能做什么、如何开始和风险边界。\n\n---\n\n## Doramagic Context Augmentation\n\n下面内容用于强化 Repomix/AI Context Pack 主体。Human Manual 只提供阅读骨架；踩坑日志会被转成宿主 AI 必须遵守的工作约束。\n\n## Human Manual 骨架\n\n使用规则：这里只是项目阅读路线和显著性信号，不是事实权威。具体事实仍必须回到 repo evidence / Claim Graph。\n\n宿主 AI 硬性规则：\n- 不得把页标题、章节顺序、摘要或 importance 当作项目事实证据。\n- 解释 Human Manual 骨架时，必须明确说它只是阅读路线/显著性信号。\n- 能力、安装、兼容性、运行状态和风险判断必须引用 repo evidence、source path 或 Claim Graph。\n\n- **项目介绍**：importance `high`\n  - source_paths: README.md, package.json\n- **安装与配置**：importance `high`\n  - source_paths: README.md, smithery.yaml, server.json\n- **核心概念**：importance `medium`\n  - source_paths: src/index.ts, src/types.ts, src/schemas.ts\n- **系统架构**：importance `high`\n  - source_paths: src/index.ts, src/client.ts, src/package_support.ts, src/types.ts, src/schemas.ts\n- **传输层**：importance `high`\n  - source_paths: src/transports/local_seam_bridge.ts, src/transports/remote_api.ts\n- **安全模块**：importance `high`\n  - source_paths: src/security/class_definition_guard.ts, src/security/determinism_guard.ts, src/security/flow_schema_guard.ts, src/security/gate_guard.ts, src/security/graph_guard.ts\n- **可用工具集**：importance `high`\n  - source_paths: src/index.ts, src/client.ts\n- **业务验证器**：importance `high`\n  - source_paths: src/validators/aml.ts, src/validators/churn.ts, src/validators/complaint.ts, src/validators/compliance.ts, src/validators/contract_gen.ts\n\n## Repo Inspection Evidence / 源码检查证据\n\n- repo_clone_verified: true\n- repo_inspection_verified: true\n- repo_commit: `e19d6945aa0befed8d0508bbe47ba81a8888786e`\n- inspected_files: `package.json`, `README.md`, `docs/LOCAL_MSR_RUNTIME_RUN_AUDIT_V0.md`, `docs/PROMOTION_PATCH_2_NOTE_v1.md`, `docs/CODEX_NATIVE_MCP_SETUP_V0.md`, `docs/FLAT_RUNNER_BOUNDARY_v0.md`, `docs/CONTENT_FLYWHEEL_REGISTERED_PACK_RUNBOOK_V0.md`, `docs/MCP_PACKAGE_GLOBAL_SUPPORT_V0.md`, `docs/MCP_CONTRACT_EXTENSION_AUDIT_V0.md`, `docs/PACKAGE_GLOBAL_PARITY_AUDIT_V0.md`, `docs/LOCAL_MSR_RUNTIME_RUN_AUDIT_RESULT.json`, `src/schemas.ts`, `src/index.ts`, `src/client.ts`, `src/types.ts`, `src/package_support.ts`, `src/transports/remote_api.ts`, `src/transports/local_seam_bridge.ts`, `src/validators/trade.ts`, `src/validators/invoice.ts`\n\n宿主 AI 硬性规则：\n- 没有 repo_clone_verified=true 时，不得声称已经读过源码。\n- 没有 repo_inspection_verified=true 时，不得把 README/docs/package 文件判断写成事实。\n- 没有 quick_start_verified=true 时，不得声称 Quick Start 已跑通。\n\n## Doramagic Pitfall Constraints / 踩坑约束\n\n这些规则来自 Doramagic 发现、验证或编译过程中的项目专属坑点。宿主 AI 必须把它们当作工作约束，而不是普通说明文字。\n\n### Constraint 1: 可能修改宿主 AI 配置\n\n- Trigger: 项目面向 Claude/Cursor/Codex/Gemini/OpenCode 等宿主，或安装命令涉及用户配置目录。\n- Host AI rule: 列出会写入的配置文件、目录和卸载/回滚步骤。\n- Why it matters: 安装可能改变本机 AI 工具行为，用户需要知道写入位置和回滚方法。\n- Evidence: capability.host_targets | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | host_targets=mcp_host, claude, chatgpt\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n\n### Constraint 2: 来源证据：v3.0.0 — Step Enforcement Runtime\n\n- Trigger: GitHub 社区证据显示该项目存在一个配置相关的待验证问题：v3.0.0 — Step Enforcement Runtime\n- Host AI rule: 来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。\n- Why it matters: 可能影响升级、迁移或版本选择。\n- Evidence: community_evidence:github | cevd_10b68dae59184a36b21a563722829aed | https://github.com/mova-compact/mova-flat-runner/releases/tag/v3.0.0 | 来源类型 github_release 暴露的待验证使用条件。\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n\n### Constraint 3: 能力判断依赖假设\n\n- Trigger: README/documentation is current enough for a first validation pass.\n- Host AI rule: 将假设转成下游验证清单。\n- Why it matters: 假设不成立时，用户拿不到承诺的能力。\n- Evidence: capability.assumptions | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | README/documentation is current enough for a first validation pass.\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n\n### Constraint 4: 维护活跃度未知\n\n- Trigger: 未记录 last_activity_observed。\n- Host AI rule: 补 GitHub 最近 commit、release、issue/PR 响应信号。\n- Why it matters: 新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。\n- Evidence: evidence.maintainer_signals | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | last_activity_observed missing\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n\n### Constraint 5: 下游验证发现风险项\n\n- Trigger: no_demo\n- Host AI rule: 进入安全/权限治理复核队列。\n- Why it matters: 下游已经要求复核，不能在页面中弱化。\n- Evidence: downstream_validation.risk_items | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | no_demo; severity=medium\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n\n### Constraint 6: 存在评分风险\n\n- Trigger: no_demo\n- Host AI rule: 把风险写入边界卡，并确认是否需要人工复核。\n- Why it matters: 风险会影响是否适合普通用户安装。\n- Evidence: risks.scoring_risks | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | no_demo; severity=medium\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n\n### Constraint 7: issue/PR 响应质量未知\n\n- Trigger: issue_or_pr_quality=unknown。\n- Host AI rule: 抽样最近 issue/PR，判断是否长期无人处理。\n- Why it matters: 用户无法判断遇到问题后是否有人维护。\n- Evidence: evidence.maintainer_signals | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | issue_or_pr_quality=unknown\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n\n### Constraint 8: 发布节奏不明确\n\n- Trigger: release_recency=unknown。\n- Host AI rule: 确认最近 release/tag 和 README 安装命令是否一致。\n- Why it matters: 安装命令和文档可能落后于代码，用户踩坑概率升高。\n- Evidence: evidence.maintainer_signals | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | release_recency=unknown\n- Hard boundary: 不要把这个坑点包装成已解决、已验证或可忽略，除非后续验证证据明确证明它已经关闭。\n",
      "summary": "给宿主 AI 的上下文和工作边界。",
      "title": "AI Context Pack / 带给我的 AI"
    },
    "boundary_risk_card": {
      "asset_id": "boundary_risk_card",
      "filename": "BOUNDARY_RISK_CARD.md",
      "markdown": "# Boundary & Risk Card / 安装前决策卡\n\n项目：mova-compact/mova-flat-runner\n\n## Doramagic 试用结论\n\n当前结论：可以进入发布前推荐检查；首次使用仍应从最小权限、临时目录和可回滚配置开始。\n\n## 用户现在可以做\n\n- 可以先阅读 Human Manual，理解项目目的和主要工作流。\n- 可以复制 Prompt Preview 做安装前体验；这只验证交互感，不代表真实运行。\n- 可以把官方 Quick Start 命令放到隔离环境中验证，不要直接进主力环境。\n\n## 现在不要做\n\n- 不要把 Prompt Preview 当成项目实际运行结果。\n- 不要把 metadata-only validation 当成沙箱安装验证。\n- 不要把未验证能力写成“已支持、已跑通、可放心安装”。\n- 不要在首次试用时交出生产数据、私人文件、真实密钥或主力配置目录。\n\n## 安装前检查\n\n- 宿主 AI 是否匹配：mcp_host, claude, chatgpt\n- 官方安装入口状态：已发现官方入口\n- 是否在临时目录、临时宿主或容器中验证：必须是\n- 是否能回滚配置改动：必须能\n- 是否需要 API Key、网络访问、读写文件或修改宿主配置：未确认前按高风险处理\n- 是否记录了安装命令、实际输出和失败日志：必须记录\n\n## 当前阻塞项\n\n- review_required: community_discussion_evidence_below_public_threshold\n\n## 项目专属踩坑\n\n- 可能修改宿主 AI 配置（medium）：安装可能改变本机 AI 工具行为，用户需要知道写入位置和回滚方法。 建议检查：列出会写入的配置文件、目录和卸载/回滚步骤。\n- 来源证据：v3.0.0 — Step Enforcement Runtime（medium）：可能影响升级、迁移或版本选择。 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。\n- 能力判断依赖假设（medium）：假设不成立时，用户拿不到承诺的能力。 建议检查：将假设转成下游验证清单。\n- 维护活跃度未知（medium）：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。 建议检查：补 GitHub 最近 commit、release、issue/PR 响应信号。\n- 下游验证发现风险项（medium）：下游已经要求复核，不能在页面中弱化。 建议检查：进入安全/权限治理复核队列。\n\n## 风险与权限提示\n\n- no_demo: medium\n\n## 证据缺口\n\n- 暂未发现结构化证据缺口。\n",
      "summary": "安装、权限、验证和推荐前风险。",
      "title": "Boundary & Risk Card / 边界与风险卡"
    },
    "human_manual": {
      "asset_id": "human_manual",
      "filename": "HUMAN_MANUAL.md",
      "markdown": "# https://github.com/mova-compact/mova-flat-runner 项目说明书\n\n生成时间：2026-05-14 16:26:04 UTC\n\n## 目录\n\n- [项目介绍](#page-introduction)\n- [安装与配置](#page-installation)\n- [核心概念](#page-core-concepts)\n- [系统架构](#page-system-architecture)\n- [传输层](#page-transport-layer)\n- [安全模块](#page-security-module)\n- [可用工具集](#page-available-tools)\n- [业务验证器](#page-validators)\n- [部署与运维](#page-deployment)\n\n<a id='page-introduction'></a>\n\n## 项目介绍\n\n### 相关页面\n\n相关主题：[安装与配置](#page-installation), [系统架构](#page-system-architecture)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n- [src/index.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/index.ts)\n- [src/transports/local_seam_bridge.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/local_seam_bridge.ts)\n- [src/security/step_mode_guard.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/security/step_mode_guard.ts)\n- [src/package_support.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/package_support.ts)\n- [tasks/task061.md](https://github.com/mova-compact/mova-flat-runner/blob/main/tasks/task061.md)\n</details>\n\n# 项目介绍\n\n## 概述\n\n`mova-flat-runner` 是 MOVA 平台的 Model Context Protocol (MCP) 服务器实现，为 AI 助手（如 Claude Desktop、Codex）提供原生 MCP 连接能力。该项目作为 MOVA 平台的轻量级运行时，通过 MCP 协议暴露标准化的工具接口，使 AI 代理能够与 MOVA 契约执行引擎进行交互。\n\n主要特点：\n- **npm 包分发**：`@leryk1981/mova-flat-runner` 形式发布，版本 `3.3.3`\n- **MCP 协议兼容**：符合 Model Context Protocol 规范，可接入任何 MCP 客户端\n- **工具生态**：提供 `mova_run`、`mova_query`、`mova_contract` 等核心工具集\n- **混合执行模式**：支持本地执行与远程 API 调用\n\n资料来源：[README.md:50]()\n\n## 项目架构\n\n### 整体架构\n\n```\n┌─────────────────────────────────────────────────────────────────┐\n│                        MCP 客户端                                │\n│                    (Claude Desktop / Codex)                     │\n└─────────────────────────────┬───────────────────────────────────┘\n                              │ MCP 协议\n                              ▼\n┌─────────────────────────────────────────────────────────────────┐\n│                   mova-flat-runner (MCP Server)                  │\n├─────────────────────────────────────────────────────────────────┤\n│  ┌──────────────┐  ┌──────────────┐  ┌───────────────────────┐  │\n│  │  HTTP Handler │  │  Tool Router  │  │   Security Guards    │  │\n│  └──────────────┘  └──────────────┘  └───────────────────────┘  │\n├─────────────────────────────────────────────────────────────────┤\n│  ┌──────────────────┐    ┌──────────────────────────────────┐  │\n│  │  Local Seam Bridge │    │       Remote API Transport       │  │\n│  └──────────────────┘    └──────────────────────────────────┘  │\n└─────────────────────────────┬───────────────────────────────────┘\n          ┌───────────────────┼───────────────────┐\n          ▼                   ▼                   ▼\n   ┌─────────────┐     ┌─────────────┐     ┌─────────────┐\n   │  Local JS   │     │  MOVA API   │     │  Contract   │\n   │  Execution  │     │  (Remote)   │     │  Registry   │\n   └─────────────┘     └─────────────┘     └─────────────┘\n```\n\n资料来源：[README.md:25-45]()\n\n### 核心目录结构\n\n| 目录/文件 | 用途 |\n|-----------|------|\n| `cmd/` | 应用程序入口点 |\n| `internal/api/` | HTTP 处理器和路由 |\n| `internal/auth/` | 认证模块（GitHub OAuth、JWT、命名空间阻塞） |\n| `internal/config/` | 配置管理 |\n| `internal/database/` | 数据持久化（PostgreSQL） |\n| `internal/service/` | 业务逻辑层 |\n| `internal/telemetry/` | 指标和监控 |\n| `internal/validators/` | 输入验证 |\n| `pkg/` | 公共包 |\n| `deploy/` | Pulumi 部署配置 |\n| `docs/` | 文档 |\n\n资料来源：[README.md:28-40]()\n\n## 可用工具\n\nMCP 服务器暴露以下工具集：\n\n### 工具列表\n\n| 工具名称 | 功能描述 |\n|----------|----------|\n| `mova_health` | 健康检查，验证 MOVA API 可用性 |\n| `mova_registry` | 查询契约注册表，获取可用契约清单 |\n| `mova_run` | 执行标准契约流程 |\n| `mova_query` | 查询契约执行状态、审计记录 |\n| `mova_decide` | 处理决策请求 |\n| `mova_connector` | 管理外部系统连接 |\n| `mova_contract` | 契约生命周期管理（注册、运行、状态查询） |\n\n资料来源：[README.md:95-102]()\n\n### mova_contract 子命令\n\n`mova_contract` 工具支持以下子命令：\n\n| 子命令 | HTTP 方法 | 端点 | 说明 |\n|--------|-----------|------|------|\n| `register` | POST | `/api/v1/contracts/register` | 注册新契约 |\n| `run` | POST | `/run/{contract_id}` | 执行契约 |\n| `run_status` | GET | `/run/{run_id}/status` | 获取运行状态 |\n| `step_complete` | POST | `/run/{run_id}/step/{step_id}/complete` | 步骤完成确认 |\n| `gate_approve` | POST | `/run/{run_id}/step/{step_id}/gate/approve` | 人为门审批 |\n| `gate_reject` | POST | `/run/{run_id}/step/{step_id}/gate/reject` | 人为门拒绝 |\n\n资料来源：[src/index.ts:120-175]()\n\n## 安全机制\n\n### 步骤模式守卫\n\n项目实现了严格的步骤执行模式验证，防止配置错误：\n\n```typescript\n// 步骤执行模式与必需字段校验\nif (mode === \"AI_ATOMIC\" && asStr(step.model) === null) {\n    // AI_ATOMIC 模式必须指定 model 字段\n}\nif (mode === \"CONTRACT_CALL\" && asStr(step.contract_id) === null) {\n    // CONTRACT_CALL 模式必须指定 contract_id\n}\nif (mode === \"HUMAN_GATE\" && !Array.isArray(step.decision_options)) {\n    // HUMAN_GATE 模式必须指定 decision_options 数组\n}\n```\n\n资料来源：[src/security/step_mode_guard.ts:35-55]()\n\n### 类定义守卫\n\n禁止在流程中内联类定义字段，确保安全边界：\n\n```typescript\nconst FORBIDDEN_FLOW_KEYS = [\n  \"class_definition_inline\",\n  \"class_def_override\",\n  \"class_def\",\n];\n```\n\n资料来源：[src/security/step_mode_guard.ts:8-13]()\n\n### 人为门验证\n\n`step_complete` 操作不能用于 HUMAN_GATE 类型步骤，必须使用专用的 `gate_approve` / `gate_reject` 路径：\n\n资料来源：[src/index.ts:130-145]()\n\n## 包验证系统\n\n### 全局文件验证\n\n`validatePackageGlobalShape` 函数验证包全局配置的合法性：\n\n| 验证项 | 规则 |\n|--------|------|\n| `global_id` | 必需字符串，非空 |\n| `version` | 必需字符串，非空 |\n| `scope` | 必须为 `\"contract_package\"` |\n| `extends` | 若存在，必须为数组 |\n| `semantic_roles` | 非空数组，每个元素为对象 |\n\n资料来源：[src/package_support.ts:15-35]()\n\n### 语义角色字段验证\n\n`semantic_roles` 数组中的每个元素必须包含以下字段：\n\n| 字段 | 类型 | 必需 |\n|------|------|------|\n| `id` | string | 是 |\n| `role` | string | 是 |\n| `authority` | string | 是 |\n| `maturity` | string | 是 |\n| `applies_to` | array | 否 |\n| `allowed_use` | array | 是 |\n| `forbidden_use` | array | 是 |\n| `notes` | string | 否 |\n\n资料来源：[dist-test/src/package_support.js:12-20]()\n\n## 本地桥接传输\n\n### 本地缝隙解析\n\n`resolveLocalSeamLocator` 处理本地执行环境的路径解析：\n\n```typescript\nconst packagePath = initialInputs.package_path \n    ?? process.env.MOVA_SANDBOX_PACKAGE_PATH \n    ?? \"D:\\\\Projects_MOVA\\\\mova-intent\\\\contracts\\\\dockerfile-nodejs-v1\";\n```\n\n资料来源：[dist-test/src/transports/local_seam_bridge.js:45-50]()\n\n### 桥接输出格式\n\n本地执行返回标准化的桥接响应：\n\n```typescript\nreturn {\n    ok: true,\n    bridge: {\n        ok: true,\n        bridge_source: \"mova_flat_runner_canonical_bridge\",\n        status: \"completed\" | \"advanced\" | \"human_gate_required\",\n        contract_ref: request.contractRef,\n        next_phase: { phase: \"EXECUTION\" | \"WAIT_HUMAN\" },\n        verification_payload: {\n            status: \"PASS\",\n            checks: [{ layer: \"Invariant\", result: \"PASS\" }]\n        }\n    }\n};\n```\n\n资料来源：[src/transports/local_seam_bridge.ts:12-40]()\n\n## 自定义契约桥接\n\n### 问题背景\n\n自定义契约（`local-*`、`remote-*` 前缀）在 `/run/*` 命名空间执行时，可能在 `/api/v1/contracts/*` 查询命名空间中不可见，导致 `mova_query` 返回 404。\n\n资料来源：[tasks/task061.md:1-10]()\n\n### 解决方案\n\n实现了内存桥接映射来维护 `contract_id -> run_id` 关系：\n\n```typescript\n// 内存桥接映射\nconst CUSTOM_RUN_BRIDGE = new Map<contract_id, { run_id, updated_at, source_url? }>();\n\n// 在 run 和 run_status 时捕获映射\nfunction rememberCustomRun(contractId, runId, sourceUrl) {\n    CUSTOM_RUN_BRIDGE.set(contractId, { \n        run_id: runId, \n        updated_at: new Date().toISOString(),\n        source_url \n    });\n}\n\n// 在 mova_query 404 时探测契约元数据\nasync function getMyContractRecord(config, contractId) {\n    const list = await movaGet(config, \"/api/v1/contracts/my\");\n    return list.contracts.find(item => item.contract_id === contractId);\n}\n```\n\n资料来源：[src/index.ts:75-95]()\n\n### 桥接状态响应\n\n当检测到自定义契约时，`mova_query status` 返回桥接状态：\n\n```json\n{\n    \"ok\": true,\n    \"bridge_mode\": \"custom_contract_run_namespace_bridge_v1\",\n    \"contract_record\": { ... },\n    \"run_ref\": \"run-xxx\",\n    \"run_status\": { ... }\n}\n```\n\n资料来源：[tasks/task061.md:18-28]()\n\n## 远程 API 传输\n\n### 步骤执行流程\n\n远程执行按顺序执行三个核心步骤：\n\n```mermaid\ngraph TD\n    A[开始] --> B[POST /api/v1/contracts/{id}/step - analyze]\n    B --> C{成功?}\n    C -->|否| D[返回错误]\n    C -->|是| E[GET /api/v1/contracts/{id}/steps/analyze/output]\n    E --> F[POST /api/v1/contracts/{id}/step - verify]\n    F --> G{成功?}\n    G -->|否| D\n    G -->|是| H[POST /api/v1/contracts/{id}/step - decide]\n    H --> I{结果等待?}\n    I -->|waiting_human| J[获取 decision_point]\n    I -->|completed| K[返回完成状态]\n    J --> K\n```\n\n资料来源：[dist-test/src/transports/remote_api.js:30-80]()\n\n### 验证器集成\n\n分析步骤后，系统会执行验证器注册表中的验证器：\n\n```typescript\nfor (const validator of validators) {\n    const fn = VALIDATOR_REGISTRY.get(validator.validator_id);\n    if (!fn) {\n        analysis[`${validator.step_id}_error`] = `VALIDATOR_NOT_ALLOWED: \"${validator.validator_id}\" not in registry`;\n        continue;\n    }\n    const resultValue = fn(validatorContext);\n    Object.assign(analysis, resultValue.value ?? {});\n}\n```\n\n资料来源：[dist-test/src/transports/remote_api.js:15-30]()\n\n## 环境配置\n\n### 必需环境变量\n\n| 变量名 | 说明 | 示例值 |\n|--------|------|--------|\n| `MOVA_API_URL` | MOVA API 端点 | `https://api.mova-lab.eu` |\n| `MOVA_API_KEY` | API 认证密钥 | `__SET_MOVA_API_KEY__` |\n| `LLM_KEY` | LLM 提供商密钥 | `__SET_LLM_KEY__` |\n| `LLM_MODEL` | LLM 模型标识 | `openai/gpt-4o-mini` |\n\n### 可选环境变量\n\n| 变量名 | 说明 | 默认值 |\n|--------|------|--------|\n| `MOVA_API_TIMEOUT_MS` | API 超时时间（毫秒） | `30000` |\n| `MOVA_HTTP_PORT` | 本地 HTTP 模式端口 | `3796` |\n| `MOVA_INVOKE_TOKEN` | 本地调用令牌 | - |\n| `MOVA_SANDBOX_PACKAGE_PATH` | 本地沙箱包路径 | - |\n| `MOVA_SANDBOX_PROJECT_PATH` | 本地沙箱项目路径 | - |\n\n资料来源：[README.md:55-80]()\n\n### Claude Desktop 配置示例\n\n```json\n{\n  \"mcpServers\": {\n    \"mova\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@leryk1981/mova-flat-runner@3.3.3\"],\n      \"env\": {\n        \"MOVA_API_URL\": \"https://api.mova-lab.eu\",\n        \"MOVA_API_KEY\": \"__SET_MOVA_API_KEY__\",\n        \"LLM_KEY\": \"__SET_LLM_KEY__\",\n        \"LLM_MODEL\": \"openai/gpt-4o-mini\"\n      }\n    }\n  }\n}\n```\n\n资料来源：[README.md:85-100]()\n\n## 公共输出清理\n\n`sanitizePublicShape` 函数确保内部字段不会泄漏到公共 API 响应中：\n\n```typescript\nfunction sanitizePublicShape(value) {\n    for (const [key, child] of Object.entries(value)) {\n        if ([\"bridge_anchors\", \"last_terminal_bridge\", \"terminal_commit_count\", \n             \"_state15_bridge\", \"trace\", \"outputs\", \"context\"].includes(key)) {\n            return false;\n        }\n        // 递归检查\n    }\n    return true;\n}\n```\n\n资料来源：[src/transports/local_seam_bridge.ts:65-80]()\n\n## 开发与发布\n\n### 构建命令\n\n| 命令 | 说明 |\n|------|------|\n| `make check` | 运行 lint、单元测试和集成测试 |\n| `make publisher` | 构建 MCP 发布工具 |\n| `make help` | 查看所有可用命令 |\n\n### 发布流程\n\n项目使用 MCP Publisher 工具进行服务器发布：\n\n```bash\n# 构建发布工具\nmake publisher\n\n# 使用发布工具\n./bin/mcp-publisher --help\n```\n\n资料来源：[README.md:15-25]()\n\n### 构建状态\n\n| 分支 | 说明 |\n|------|------|\n| `main` | 最新主分支构建（稳定版） |\n| `main-<date>-<sha>` | 特定提交构建（开发版） |\n\n资料来源：[README.md:3-6]()\n\n## 安全注意事项\n\n> ⚠️ 切勿提交真实的 `MOVA_API_KEY`、`LLM_KEY` 或 `MOVA_INVOKE_TOKEN`。MCP 注册表会向 MCP 客户端提供服务器列表，如同一个 MCP 服务器的应用商店。\n\n资料来源：[README.md:105-106]()\n\n---\n\n<a id='page-installation'></a>\n\n## 安装与配置\n\n### 相关页面\n\n相关主题：[项目介绍](#page-introduction), [部署与运维](#page-deployment)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n- [package.json](https://github.com/mova-compact/mova-flat-runner/blob/main/package.json)\n- [src/index.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/index.ts)\n- [smithery.yaml](https://github.com/mova-compact/mova-flat-runner/blob/main/smithery.yaml)\n- [server.json](https://github.com/mova-compact/mova-flat-runner/blob/main/server.json)\n</details>\n\n# 安装与配置\n\n## 概述\n\n`mova-flat-runner` 是一个基于 Model Context Protocol (MCP) 的服务器，用于执行受治理的 AI 工作流程。该项目支持发票 OCR、AML 分类、信贷审查以及带有人工审批环节的自定义合约执行，并提供完整的审计追踪功能。\n\n资料来源：[package.json:3-4]()\n\n## 安装方式\n\n### 通过 npm 安装（推荐）\n\n使用 npx 直接运行，无需全局安装：\n\n```bash\nnpx -y @leryk1981/mova-flat-runner@3.3.3\n```\n\n### 手动构建安装\n\n从源码构建：\n\n```bash\ngit clone https://github.com/mova-compact/mova-flat-runner.git\ncd mova-flat-runner\nnpm install\nnpm run build\n```\n\n构建产物位于 `dist/` 目录，可执行文件为 `mova-mcp`。\n\n资料来源：[README.md:54](), [package.json:23]()\n\n## 环境变量配置\n\n### 必须配置的环境变量\n\n| 变量名 | 说明 | 示例值 |\n|--------|------|--------|\n| `MOVA_API_URL` | MOVA API 服务地址 | `https://api.mova-lab.eu` |\n| `MOVA_API_KEY` | MOVA API 访问密钥 | `__SET_MOVA_API_KEY__` |\n| `LLM_KEY` | LLM 服务密钥 | `__SET_LLM_KEY__` |\n| `LLM_MODEL` | 使用的 LLM 模型 | `openai/gpt-4o-mini` |\n\n资料来源：[README.md:35-39]()\n\n### 可选环境变量（本地 HTTP 模式）\n\n| 变量名 | 说明 | 默认值 |\n|--------|------|--------|\n| `MOVA_API_TIMEOUT_MS` | API 请求超时时间（毫秒） | `30000` |\n| `MOVA_HTTP_PORT` | 本地 HTTP 服务端口 | `3796` |\n| `MOVA_INVOKE_TOKEN` | 本地调用令牌 | 无默认值 |\n\n资料来源：[README.md:44-46]()\n\n## MCP 客户端集成配置\n\n### Claude Desktop 配置\n\n在 `claude_desktop_config.json` 中添加以下配置：\n\n```json\n{\n  \"mcpServers\": {\n    \"mova\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@leryk1981/mova-flat-runner@3.3.3\"],\n      \"env\": {\n        \"MOVA_API_URL\": \"https://api.mova-lab.eu\",\n        \"MOVA_API_KEY\": \"__SET_MOVA_API_KEY__\",\n        \"LLM_KEY\": \"__SET_LLM_KEY__\",\n        \"LLM_MODEL\": \"openai/gpt-4o-mini\"\n      }\n    }\n  }\n}\n```\n\n资料来源：[README.md:62-73]()\n\n### Codex 配置\n\n在 `codex_config.json` 中添加以下配置：\n\n```json\n{\n  \"mcp_servers\": {\n    \"mova\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@leryk1981/mova-flat-runner@3.3.3\"],\n      \"startup_timeout_sec\": 90.0,\n      \"env\": {\n        \"MOVA_API_URL\": \"https://api.mova-lab.eu\",\n        \"MOVA_API_KEY\": \"__SET_MOVA_API_KEY__\",\n        \"LLM_KEY\": \"__SET_LLM_KEY__\",\n        \"LLM_MODEL\": \"openai/gpt-4o-mini\"\n      }\n    }\n  }\n}\n```\n\n### TOML 格式配置\n\n```toml\n[mcp_servers.mova]\ncommand = \"npx\"\nargs = [\"-y\", \"@leryk1981/mova-flat-runner@3.3.3\"]\nstartup_timeout_sec = 90.0\n\n[mcp_servers.mova.env]\nMOVA_API_URL = \"https://api.mova-lab.eu\"\nMOVA_API_KEY = \"__SET_MOVA_API_KEY__\"\nLLM_KEY = \"__SET_LLM_KEY__\"\nLLM_MODEL = \"openai/gpt-4o-mini\"\n```\n\n资料来源：[README.md:75-97]()\n\n## 服务健康检查\n\n部署完成后，可通过以下命令验证服务可用性：\n\n```bash\ncurl -sS https://api.mova-lab.eu/health\n```\n\n资料来源：[README.md:55-57]()\n\n## 可用工具列表\n\n配置完成后，MCP 服务器提供以下工具：\n\n| 工具名称 | 功能说明 |\n|----------|----------|\n| `mova_health` | 服务健康检查 |\n| `mova_registry` | 查看合约注册表 |\n| `mova_run` | 执行内置工作流程合约 |\n| `mova_query` | 查询合约状态和审计信息 |\n| `mova_decide` | 触发决策流程 |\n| `mova_connector` | 连接器管理 |\n| `mova_contract` | 自定义合约注册与执行 |\n\n资料来源：[README.md:99-107]()\n\n## 安全注意事项\n\n⚠️ **重要提示**：请勿将真实的 `MOVA_API_KEY`、`LLM_KEY` 或 `MOVA_INVOKE_TOKEN` 提交到版本控制系统。\n\n环境变量占位符使用说明：\n\n- 在文档中使用 `__SET_MOVA_API_KEY__` 等占位符\n- 在本地配置中使用真实的密钥值\n- 确保配置文件已添加到 `.gitignore`\n\n资料来源：[README.md:47-49]()\n\n## 配置架构图\n\n```mermaid\ngraph TD\n    A[MCP Client] -->|npx启动| B[mova-flat-runner]\n    B -->|环境变量| C[MovaConfig]\n    C -->|API调用| D[MOVA API Server]\n    D -->|状态/结果| B\n    B -->|工具响应| A\n    \n    C -->|必需变量| E[MOVA_API_URL]\n    C -->|必需变量| F[MOVA_API_KEY]\n    C -->|必需变量| G[LLM_KEY]\n    C -->|必需变量| H[LLM_MODEL]\n    \n    C -->|可选变量| I[MOVA_API_TIMEOUT_MS]\n    C -->|可选变量| J[MOVA_HTTP_PORT]\n    C -->|可选变量| K[MOVA_INVOKE_TOKEN]\n```\n\n## 开发命令\n\n项目提供以下 Makefile 目标用于开发：\n\n| 命令 | 说明 |\n|------|------|\n| `make check` | 运行代码检查、单元测试和集成测试 |\n| `make publisher` | 构建 MCP 发布工具 |\n| `make help` | 查看所有可用命令 |\n\n资料来源：[README.md:29-34]()\n\n## 验证安装\n\n安装完成后，可通过执行以下步骤验证配置是否正确：\n\n1. 检查 MCP 客户端是否成功连接\n2. 调用 `mova_health` 工具验证 API 连通性\n3. 尝试调用 `mova_registry` 查看合约列表\n\n如遇到问题，请检查：\n\n- 环境变量是否正确设置\n- API URL 是否可访问\n- API 密钥是否有效\n\n---\n\n<a id='page-core-concepts'></a>\n\n## 核心概念\n\n### 相关页面\n\n相关主题：[系统架构](#page-system-architecture), [可用工具集](#page-available-tools)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/index.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/index.ts)\n- [src/types.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/types.ts)\n- [src/schemas.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/schemas.ts)\n- [src/security/step_mode_guard.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/security/step_mode_guard.ts)\n- [src/transports/local_seam_bridge.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/local_seam_bridge.ts)\n- [src/package_support.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/package_support.ts)\n- [src/transports/remote_api.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/remote_api.ts)\n</details>\n\n# 核心概念\n\n本文档介绍 mova-flat-runner（MCP 服务器）的核心架构概念，帮助开发者理解系统的工作原理、设计决策和安全机制。\n\n## 系统概述\n\nmova-flat-runner 是一个基于 **Model Context Protocol (MCP)** 的服务器实现，用于托管治理型 AI 工作流。系统支持合同执行、人工审批门控、审计追踪等功能。\n\n**核心能力：**\n\n- 内置合同类型（发票 OCR、反洗钱审查、信用审查、投诉处理）\n- 自定义合同注册与执行\n- 人工干预门控（HUMAN_GATE）\n- 多步骤执行模式验证\n- 本地沙箱执行与远程 API 调用双路径\n\n资料来源：[package.json](https://github.com/mova-compact/mova-flat-runner/blob/main/package.json)\n\n---\n\n## MCP 工具接口\n\nMCP 服务器暴露一组标准化工具，供 AI 客户端调用。工具通过 `executeTool` 函数统一分发。资料来源：[src/index.ts:79-450]()\n\n### 可用工具列表\n\n| 工具名称 | 功能描述 | 主要参数 |\n|---------|---------|---------|\n| `mova_health` | 健康检查 | 无 |\n| `mova_registry` | 获取注册合同列表 | 无 |\n| `mova_run` | 执行内置合同 | `contract_type`, `inputs` |\n| `mova_query` | 查询合同状态/审计 | `contract_id`, `view` |\n| `mova_decide` | 执行决策步骤 | `contract_id`, `step_id`, `choice` |\n| `mova_contract` | 自定义合同管理 | `action`, `contract_id` 等 |\n| `mova_connector` | 连接器操作 | `action`, `connector_id` |\n\n资料来源：[src/index.ts:79-100]()\n\n### mova_query 视图模式\n\n`mova_query` 支持三种视图模式：\n\n| 视图模式 | 用途 | 返回内容 |\n|---------|------|---------|\n| `status` | 状态查询 | 合同执行状态、当前步骤、运行引用 |\n| `audit` | 完整审计 | 结构化审计记录 |\n| `audit_compact` | 紧凑审计 | 最小化审计摘要 |\n\n资料来源：[tasks/task061.md]()\n\n---\n\n## 合同类型与执行模式\n\n### 内置合同类型\n\n系统预置以下合同类型：\n\n| 合同类型 | 用途 | 执行模式 |\n|---------|------|---------|\n| `complaint` | 投诉处理 | 远程 API |\n| `invoice-ocr` | 发票 OCR 识别 | 本地/远程 |\n| `aml-triage` | 反洗钱审查 | 混合模式 |\n| `credit-review` | 信用审查 | AI_ATOMIC |\n\n资料来源：[src/index.ts:81-120]()\n\n### 执行模式（Step Execution Mode）\n\n合同流程由多个步骤组成，每步骤有独立的执行模式：\n\n```mermaid\ngraph TD\n    A[Step] --> B{执行模式判定}\n    B --> C[DETERMINISTIC]\n    B --> D[AI_ATOMIC]\n    B --> E[CONTRACT_CALL]\n    B --> F[HUMAN_GATE]\n    \n    C --> C1[本地 JS 校验]\n    D --> D1[LLM 调用]\n    E --> E1[调用其他合同]\n    F --> F1[等待人工审批]\n```\n\n| 执行模式 | 说明 | 必需字段 | 安全约束 |\n|---------|------|---------|---------|\n| `DETERMINISTIC` | 本地确定性校验 | 无特殊要求 | 禁止声明 `model` 字段 |\n| `AI_ATOMIC` | LLM 原子操作 | `model` | 必须声明 `model` |\n| `CONTRACT_CALL` | 跨合同调用 | `contract_id` | 被调用合同必须存在 |\n| `HUMAN_GATE` | 人工审批门控 | `decision_options` | 需要 `gate_approve` / `gate_reject` |\n\n资料来源：[src/security/step_mode_guard.ts:1-80]()\n\n### 执行模式验证规则\n\n`step_mode_guard.ts` 实现以下验证：\n\n```typescript\n// DETERMINISTIC 禁止使用 model\nif (mode === \"DETERMINISTIC\" && step.model !== undefined) {\n  violations.push({ kind: \"deterministic_with_model\", ... });\n}\n\n// AI_ATOMIC 必须声明 model\nif (mode === \"AI_ATOMIC\" && asStr(step.model) === null) {\n  violations.push({ kind: \"ai_atomic_without_model\", ... });\n}\n\n// CONTRACT_CALL 必须指定 contract_id\nif (mode === \"CONTRACT_CALL\" && asStr(step.contract_id) === null) {\n  violations.push({ kind: \"contract_call_without_contract_id\", ... });\n}\n\n// HUMAN_GATE 必须声明决策选项\nif (mode === \"HUMAN_GATE\" && !Array.isArray(step.decision_options)) {\n  violations.push({ kind: \"human_gate_without_decisions\", ... });\n}\n```\n\n资料来源：[src/security/step_mode_guard.ts:20-60]()\n\n---\n\n## 人工干预门控（HUMAN_GATE）\n\n### 工作流程\n\n```mermaid\nsequenceDiagram\n    participant Client\n    participant MCP\n    participant API\n    participant Human\n    \n    Client->>MCP: mova_run (含 HUMAN_GATE)\n    MCP->>API: 启动合同执行\n    API-->>MCP: status=waiting_human\n    MCP-->>Client: 返回待审批状态\n    \n    Client->>MCP: mova_decide (choice)\n    MCP->>API: /decision\n    API->>Human: 通知待审批\n    Human-->>API: 审批结果\n    API-->>MCP: 继续执行\n    MCP-->>Client: 执行完成\n```\n\n### 安全约束\n\n`step_complete` 操作在 HUMAN_GATE 步骤上被禁止执行：\n\n```typescript\nconst gateGuard = await assertNotHumanGate(\n  config, \n  args.run_id, \n  args.step_id, \n  requestId\n);\nif (gateGuard) return gateGuard;\n```\n\nHUMAN_GATE 必须通过专用路径完成审批：\n\n- `gate_approve` - 批准当前步骤\n- `gate_reject` - 拒绝当前步骤\n\n资料来源：[src/index.ts:180-200]()\n\n---\n\n## 自定义合同桥接机制\n\n### 问题背景\n\n自定义合同使用 `/run/*` 命名空间执行，但查询时可能返回 404（合同不存在于 `/api/v1/contracts/*` 命名空间）。资料来源：[tasks/task061.md]()\n\n### 桥接解决方案\n\n```mermaid\ngraph LR\n    A[自定义合同注册] --> B[CUSTOM_RUN_BRIDGE]\n    C[mova_run] --> B\n    D[run_status] --> B\n    \n    B --> E{contract_id 映射}\n    \n    E --> F[存在映射?]\n    F -->|是| G[返回 bridged status]\n    F -->|否| H[返回 404]\n    \n    G --> I[probe /api/v1/contracts/my]\n    I --> J[返回结构化响应]\n```\n\n### 内存桥接映射\n\n```typescript\nconst CUSTOM_RUN_BRIDGE: Map<contract_id, {\n  run_id: string,\n  updated_at: string,\n  source_url?: string\n}> = new Map();\n```\n\n关键函数：\n\n| 函数 | 用途 |\n|------|------|\n| `rememberCustomRun` | 缓存 contract_id → run_id 映射 |\n| `getMyContractRecord` | 查询 /api/v1/contracts/my 获取元数据 |\n\n资料来源：[src/index.ts:40-65]()\n\n### 桥接响应格式\n\n```json\n{\n  \"ok\": true,\n  \"bridge_mode\": \"custom_contract_run_namespace_bridge_v1\",\n  \"contract_record\": { ... },\n  \"run_ref\": \"run-xxx\",\n  \"run_status\": { ... }\n}\n```\n\n---\n\n## 包结构验证\n\n### 包文件类型\n\n| 文件类型 | 用途 | 验证内容 |\n|---------|------|---------|\n| `global` | 全局元数据 | 合同包范围、语义角色 |\n| `manifest` | 包清单 | schema_id、引用关系 |\n| `flow` | 流程定义 | 步骤、执行模式 |\n\n资料来源：[src/package_support.ts:1-150]()\n\n### Global 文件验证\n\n```typescript\nconst allowedKeys = new Set([\n  \"schema_id\", \"global_id\", \"version\", \"scope\",\n  \"extends\", \"semantic_roles\", \"non_authority_rules\"\n]);\n\n// 必需字段\n- schema_id: \"mova.contract.global.v1\"\n- global_id: 非空字符串\n- version: 非空字符串\n- scope: \"contract_package\"\n- semantic_roles: 非空数组\n```\n\n资料来源：[src/package_support.ts:60-100]()\n\n### Manifest 文件验证\n\n```typescript\nconst allowedKeys = new Set([\n  \"schema_id\", \"package_id\", \"version\", \"global_ref\",\n  \"flow_ref\", \"classification_policy_ref\",\n  \"classification_result_set_ref\", \"classification_result_refs\",\n  \"runtime_binding_set_ref\", \"model_refs\", \"fixture_refs\",\n  \"package_invariants\"\n]);\n```\n\n---\n\n## API 传输层\n\n### 请求方法\n\n```typescript\nexport const movaGet    = (config, path) => movaRequest(config, \"GET\", path);\nexport const movaPost   = (config, path, body) => movaRequest(config, \"POST\", path, body);\nexport const movaPut    = (config, path, body) => movaRequest(config, \"PUT\", path, body);\nexport const movaDelete = (config, path) => movaRequest(config, \"DELETE\", path);\n```\n\n资料来源：[src/transports/remote_api.ts:1-50]()\n\n### 远程执行流程\n\n```mermaid\ngraph TD\n    A[movaRunStepsRemote] --> B[analyze 步骤]\n    B --> C{result.ok?}\n    C -->|是| D[verify 步骤]\n    C -->|否| E[返回错误]\n    D --> F{status?}\n    F -->|waiting_human| G[返回待审批]\n    F -->|completed| H[decide 步骤]\n    H --> I[返回结果]\n```\n\n---\n\n## 配置管理\n\n### 环境变量\n\n| 变量名 | 必需 | 默认值 | 说明 |\n|-------|------|-------|------|\n| `MOVA_API_URL` | 是 | - | API 基础地址 |\n| `MOVA_API_KEY` | 是 | - | API 认证密钥 |\n| `LLM_KEY` | 是 | - | LLM 提供商密钥 |\n| `LLM_MODEL` | 是 | `openai/gpt-4o-mini` | LLM 模型标识 |\n| `MOVA_API_TIMEOUT_MS` | 否 | 30000 | 请求超时（毫秒） |\n| `MOVA_HTTP_PORT` | 否 | 3796 | 本地 HTTP 模式端口 |\n| `MOVA_INVOKE_TOKEN` | 否 | - | 本地调用令牌 |\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n### MovaConfig 类型\n\n```typescript\ninterface MovaConfig {\n  apiUrl: string;\n  apiKey: string;\n  llmKey: string;\n  llmModel: string;\n  timeoutMs?: number;\n  httpPort?: number;\n  invokeToken?: string;\n}\n```\n\n---\n\n## 错误处理\n\n### 错误代码体系\n\n| 错误代码 | HTTP 等价 | 说明 |\n|---------|----------|------|\n| `UNKNOWN_CONTRACT_TYPE` | 400 | 合同类型未注册 |\n| `LOCAL_VALIDATION_FAILED` | 400 | 本地验证失败 |\n| `API_REQUEST_FAILED` | 502 | 后端 API 请求失败 |\n| `STEP_MODE_FIELD_MISMATCH` | 400 | 执行模式字段不匹配 |\n| `CONTRACT_NOT_FOUND` | 404 | 合同不存在 |\n\n### 标准错误响应格式\n\n```json\n{\n  \"ok\": false,\n  \"error\": {\n    \"code\": \"ERROR_CODE\",\n    \"message\": \"人类可读的错误描述\",\n    \"details\": { ... },\n    \"request_id\": \"req-xxx\"\n  }\n}\n```\n\n---\n\n## 安全机制\n\n### 步骤模式守卫（Step Mode Guard）\n\n```mermaid\ngraph TD\n    A[执行步骤] --> B[findStepModeViolations]\n    B --> C{违规数量}\n    C -->|0| D[执行通过]\n    C -->|>0| E[返回 400 错误]\n    \n    D --> F[assertStepModesValid]\n    F --> G[继续执行]\n```\n\n核心安全检查：\n\n1. **DETERMINISTIC 模式**：禁止声明 LLM model 字段\n2. **AI_ATOMIC 模式**：必须声明 model 字段\n3. **CONTRACT_CALL 模式**：必须指定 target contract_id\n4. **HUMAN_GATE 模式**：禁止绕过专用审批路径\n\n资料来源：[src/security/step_mode_guard.ts:80-110]()\n\n### 公共形状清理（sanitizePublicShape）\n\n过滤内部字段，确保审计响应不暴露实现细节：\n\n```typescript\nconst BLOCKED_KEYS = [\n  \"bridge_anchors\",\n  \"last_terminal_bridge\",\n  \"terminal_commit_count\",\n  \"_state15_bridge\",\n  \"trace\",\n  \"outputs\",\n  \"context\"\n];\n```\n\n---\n\n## MCP 资源端点\n\n| URI | 内容 |\n|-----|------|\n| `mova://registry` | 注册合同清单 |\n| `mova://schemas/envelopes` | 信封 JSON Schema |\n| `mova://contracts/{type}/manifest` | 指定合同类型的清单 |\n\n---\n\n## 快速开始\n\n### Claude Desktop 配置\n\n```json\n{\n  \"mcpServers\": {\n    \"mova\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@leryk1981/mova-flat-runner@3.3.3\"],\n      \"env\": {\n        \"MOVA_API_URL\": \"https://api.mova-lab.eu\",\n        \"MOVA_API_KEY\": \"__SET_MOVA_API_KEY__\",\n        \"LLM_KEY\": \"__SET_LLM_KEY__\",\n        \"LLM_MODEL\": \"openai/gpt-4o-mini\"\n      }\n    }\n  }\n}\n```\n\n### 健康检查\n\n```bash\ncurl -sS https://api.mova-lab.eu/health\n\n---\n\n<a id='page-system-architecture'></a>\n\n## 系统架构\n\n### 相关页面\n\n相关主题：[传输层](#page-transport-layer), [安全模块](#page-security-module), [核心概念](#page-core-concepts)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/index.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/index.ts)\n- [src/transports/local_seam_bridge.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/local_seam_bridge.ts)\n- [src/transports/remote_api.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/remote_api.ts)\n- [src/security/step_mode_guard.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/security/step_mode_guard.ts)\n- [src/package_support.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/package_support.ts)\n- [src/types.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/types.ts)\n</details>\n\n# 系统架构\n\n## 概述\n\nmova-flat-runner 是 MOVA 平台的 MCP（Model Context Protocol）服务器实现，为 MCP 客户端（如 Claude Desktop、Cursor）提供受治理的 AI 工作流执行能力。该系统支持发票 OCR、AML 审查、信贷审核等业务流程，并内置人工审批门（Human Approval Gates）和完整的审计追踪机制。\n\n资料来源：[package.json:1-20]()\n\n## 整体架构\n\n### 核心定位\n\n该系统作为 MCP 协议的服务端实现，运行于 Node.js 18+ 环境，通过 MCP 协议暴露一组标准化的工具（Tools），供 AI 代理调用。工作流程执行可以采用本地执行或远程 API 调用两种模式。\n\n资料来源：[src/index.ts:1-50]()\n\n```mermaid\ngraph TD\n    subgraph MCP客户端层\n        A[Claude Desktop] -->|MCP Protocol| B[mova-mcp Server]\n        C[Cursor] -->|MCP Protocol| B\n    end\n    \n    subgraph 服务端核心\n        B -->|executeTool| D[工具调度器]\n        D --> E[本地执行路径]\n        D --> F[远程 API 路径]\n    end\n    \n    subgraph 本地执行\n        E --> G[step_mode_guard]\n        G --> H[Local Seam Bridge]\n    end\n    \n    subgraph 远程执行\n        F --> I[remote_api]\n        I --> J[MOVA Backend API]\n    end\n    \n    subgraph 安全层\n        G --> K[验证器注册表]\n        H --> L[Bridge 状态管理]\n    end\n```\n\n## 模块划分\n\n### 项目结构\n\n```\nmova-flat-runner/\n├── cmd/                     # 应用入口点\n├── src/                     # TypeScript 源码\n│   ├── index.ts             # MCP 服务器主入口\n│   ├── types.ts             # 类型定义\n│   ├── client.ts            # MCP 协议客户端\n│   ├── package_support.ts   # 合约包支持\n│   ├── schemas.ts           # JSON Schema 定义\n│   ├── transports/          # 传输层\n│   │   ├── local_seam_bridge.ts   # 本地接缝桥接器\n│   │   └── remote_api.ts          # 远程 API 客户端\n│   └── security/            # 安全模块\n│       └── step_mode_guard.ts     # 步骤模式守卫\n├── internal/                # 内部应用代码\n└── pkg/                     # 公共包\n```\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n### 核心组件表\n\n| 组件 | 文件路径 | 职责 |\n|------|----------|------|\n| MCP 服务器入口 | `src/index.ts` | 工具注册、请求路由、响应序列化 |\n| 工具调度器 | `src/index.ts:executeTool` | 根据工具名称分发请求 |\n| 本地执行引擎 | `src/transports/local_seam_bridge.ts` | 本地工作流执行与状态管理 |\n| 远程 API 客户端 | `src/transports/remote_api.ts` | 与 MOVA 后端 API 交互 |\n| 安全守卫 | `src/security/step_mode_guard.ts` | 执行模式验证与字段一致性检查 |\n| 包验证器 | `src/package_support.ts` | 合约包结构与语义角色验证 |\n\n资料来源：[src/index.ts:100-200](), [src/transports/local_seam_bridge.ts](), [src/security/step_mode_guard.ts]()\n\n## 传输层架构\n\n### 双路径执行模式\n\n系统支持两种执行路径，根据配置自动选择：\n\n| 模式 | 触发条件 | 执行位置 | 特点 |\n|------|----------|----------|------|\n| 本地执行 | `MOVA_HTTP_PORT` 环境变量设置 | Node.js 运行时内 | 低延迟、无网络依赖 |\n| 远程执行 | 默认模式 | MOVA Backend API | 集中管理、审计追踪 |\n\n资料来源：[src/transports/remote_api.ts:1-30](), [src/transports/local_seam_bridge.ts:1-50]()\n\n### 远程 API 调用流程\n\n```mermaid\nsequenceDiagram\n    participant MCP as MCP 客户端\n    participant Server as mova-mcp Server\n    participant API as 远程 API\n    \n    MCP->>Server: mova_run\n    Server->>API: POST /api/v1/contracts/{id}/step\n    API-->>Server: Step Result\n    Server->>API: GET /api/v1/contracts/{id}/steps/{step}/output\n    API-->>Server: Analysis Output\n    Server->>API: POST /api/v1/contracts/{id}/step (decide)\n    API-->>Server: Decision Result\n    Server-->>MCP: Complete Response\n```\n\n### 本地桥接器状态机\n\n`local_seam_bridge.ts` 实现了工作流步骤的本地执行与状态转换：\n\n```mermaid\nstateDiagram-v2\n    [*] --> EXECUTION: 启动步骤\n    EXECUTION --> WAIT_HUMAN: HUMAN_GATE 模式\n    WAIT_HUMAN --> EXECUTION: gate_approve\n    EXECUTION --> COMPLETED: terminal_outcome = true\n    EXECUTION --> ADVANCED: 正常完成\n    WAIT_HUMAN --> REJECTED: gate_reject\n```\n\n状态判定逻辑根据 `execution_mode` 和 `humanDecision` 字段确定返回状态：\n\n| 执行模式 | 条件 | 返回状态 |\n|----------|------|----------|\n| AI_ATOMIC | 始终 | `completed` |\n| HUMAN_GATE | `humanDecision == null` | `human_gate_required` |\n| HUMAN_GATE | `humanDecision != null` | `completed` |\n| 其他 | 始终 | `advanced` |\n\n资料来源：[src/transports/local_seam_bridge.ts:20-60]()\n\n## 安全架构\n\n### 步骤模式守卫\n\n`step_mode_guard.ts` 实现了执行模式的字段一致性验证：\n\n```typescript\n// 关键验证规则\nDETERMINISTIC + model 字段 → 警告（DET 步骤不调用 LLM）\nAI_ATOMIC + 无 model 字段 → 警告\nCONTRACT_CALL + 无 contract_id → 违规\nHUMAN_GATE + 无 decision_options → 违规\n```\n\n资料来源：[src/security/step_mode_guard.ts:1-80]()\n\n### 模式验证流程\n\n```mermaid\ngraph TD\n    A[加载 Flow 定义] --> B[遍历每个 Step]\n    B --> C{检查 execution_mode}\n    C -->|DETERMINISTIC| D{model 存在?}\n    C -->|AI_ATOMIC| E{model 存在?}\n    C -->|CONTRACT_CALL| F{contract_id 存在?}\n    C -->|HUMAN_GATE| G{decision_options 存在?}\n    \n    D -->|是| H[记录警告]\n    D -->|否| I[通过]\n    E -->|否| J[记录违规]\n    F -->|否| K[记录违规]\n    G -->|否| L[记录违规]\n    \n    H --> M[返回违规列表]\n    I --> M\n    J --> M\n    K --> M\n    L --> M\n    M -->|违规>0| N[flatErr 400]\n    M -->|违规=0| O[通过验证]\n```\n\n### CFV-3 安全策略\n\n对于 `HUMAN_GATE` 步骤，系统强制使用专用门路径：\n\n- 通用 `step_complete` 调用将被拒绝\n- 必须通过 `gate_approve` 或 `gate_reject` 完成审批\n\n资料来源：[src/index.ts:step_complete case]()\n\n## 数据模型\n\n### 合约包结构\n\n合约包（Contract Package）是工作流的部署单元，包含以下核心文件：\n\n| 文件 | 必需 | 用途 |\n|------|------|------|\n| `_global.json` | 是 | 全局元数据、语义角色定义 |\n| `_manifest.json` | 是 | 包清单、流程引用 |\n| `flow.json` | 是 | 工作流步骤定义 |\n| `_schemas/*.json` | 否 | 输出 Schema 定义 |\n\n资料来源：[src/package_support.ts:1-100]()\n\n### 全局文件验证规则\n\n```json\n{\n  \"schema_id\": \"string (必需)\",\n  \"global_id\": \"string (必需)\",\n  \"version\": \"string (必需)\",\n  \"scope\": \"contract_package (必需)\",\n  \"extends\": \"array (可选)\",\n  \"semantic_roles\": \"array (必需，非空)\",\n  \"non_authority_rules\": \"array (必需，非空)\"\n}\n```\n\n字段验证逻辑：\n\n| 字段 | 验证类型 | 错误消息 |\n|------|----------|----------|\n| `global_id` | 必需字符串 | `global file is missing required string field \"global_id\"` |\n| `version` | 必需字符串 | `global file is missing required string field \"version\"` |\n| `scope` | 枚举值 | `global scope must be \"contract_package\"` |\n| `semantic_roles` | 非空数组 | `global semantic_roles must be a non-empty array` |\n\n资料来源：[dist-test/src/package_support.js:1-50]()\n\n## MCP 工具接口\n\n### 可用工具列表\n\n| 工具名称 | 功能描述 | 主要参数 |\n|----------|----------|----------|\n| `mova_health` | 健康检查 | 无 |\n| `mova_registry` | 获取合约清单 | 无 |\n| `mova_run` | 执行合约 | `contract_type`, `inputs` |\n| `mova_query` | 查询合约状态 | `contract_id`, `view` |\n| `mova_decide` | 提交决策 | `contract_id`, `option_id` |\n| `mova_connector` | 连接器操作 | `action`, `args` |\n| `mova_contract` | 合约管理 | `action`, `package_path` |\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n### 工具执行入口\n\n```typescript\nasync function executeTool(name: string, args: Args): Promise<string> {\n  const requestId = shortId();\n  switch (name) {\n    case \"mova_run\": { /* ... */ }\n    case \"mova_query\": { /* ... */ }\n    case \"mova_decide\": { /* ... */ }\n    case \"gate_approve\": { /* ... */ }\n    case \"gate_reject\": { /* ... */ }\n    case \"step_complete\": { /* ... */ }\n    // ...\n  }\n}\n```\n\n资料来源：[src/index.ts:executeTool]()\n\n## 配置与环境变量\n\n### 必需变量\n\n| 变量名 | 说明 | 示例值 |\n|--------|------|--------|\n| `MOVA_API_URL` | MOVA API 端点 | `https://api.mova-lab.eu` |\n| `MOVA_API_KEY` | API 认证密钥 | `__SET_MOVA_API_KEY__` |\n| `LLM_KEY` | LLM 提供商密钥 | `__SET_LLM_KEY__` |\n| `LLM_MODEL` | LLM 模型标识 | `openai/gpt-4o-mini` |\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n### 可选变量\n\n| 变量名 | 说明 | 默认值 |\n|--------|------|--------|\n| `MOVA_API_TIMEOUT_MS` | API 超时（毫秒） | `30000` |\n| `MOVA_HTTP_PORT` | 本地 HTTP 模式端口 | 未设置（使用远程模式） |\n| `MOVA_INVOKE_TOKEN` | 本地调用令牌 | 无 |\n| `MOVA_SANDBOX_PACKAGE_PATH` | 沙箱包路径 | `contracts/dockerfile-nodejs-v1` |\n| `MOVA_SANDBOX_PROJECT_PATH` | 沙箱项目路径 | 无 |\n\n资料来源：[src/transports/local_seam_bridge.ts:resolveLocalSeamLocator]()\n\n## 自定义合约桥接机制\n\n### 问题背景\n\n自定义合约（`local-*`, `remote-*` 前缀）与内置合约的命名空间分离：\n\n- 运行端点：`/run/{contract_id}`\n- 查询端点：`/api/v1/contracts/{contract_id}`\n\n资料来源：[tasks/task061.md]()\n\n### 桥接解决方案\n\n```mermaid\ngraph LR\n    A[register] -->|POST /contracts/register| B[记录 run_id]\n    B --> C[CUSTOM_RUN_BRIDGE Map]\n    C --> D[run_status]\n    D -->|GET /run/{run_id}/status| E[更新映射]\n    E --> C\n    C --> F[mova_query]\n    F -->|404 时| G{查询 /contracts/my}\n    G -->|找到记录| H[返回 bridged status]\n    G -->|未找到| I[返回 AUDIT_UNAVAILABLE]\n```\n\n### 内存桥接表\n\n```typescript\nconst CUSTOM_RUN_BRIDGE: Map<contract_id, {\n  run_id: string,\n  updated_at: string,\n  source_url?: string\n}>;\n```\n\n桥接函数：\n\n| 函数 | 位置 | 用途 |\n|------|------|------|\n| `rememberCustomRun` | `src/index.ts` | 记录 `contract_id → run_id` 映射 |\n| `getMyContractRecord` | `src/index.ts` | 从 `/api/v1/contracts/my` 获取元数据 |\n\n资料来源：[dist-test/src/index.js:rememberCustomRun](), [tasks/task061.md]()\n\n## 部署配置\n\n### MCP 客户端配置示例\n\n#### Claude Desktop (macOS)\n\n```json\n{\n  \"mcpServers\": {\n    \"mova\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@leryk1981/mova-flat-runner@3.3.3\"],\n      \"env\": {\n        \"MOVA_API_URL\": \"https://api.mova-lab.eu\",\n        \"MOVA_API_KEY\": \"__SET_MOVA_API_KEY__\",\n        \"LLM_KEY\": \"__SET_LLM_KEY__\",\n        \"LLM_MODEL\": \"openai/gpt-4o-mini\"\n      }\n    }\n  }\n}\n```\n\n#### Codex (Linux)\n\n```toml\n[mcp_servers.mova]\ncommand = \"npx\"\nargs = [\"-y\", \"@leryk1981/mova-flat-runner@3.3.3\"]\nstartup_timeout_sec = 90.0\n\n[mcp_servers.mova.env]\nMOVA_API_URL = \"https://api.mova-lab.eu\"\nMOVA_API_KEY = \"__SET_MOVA_API_KEY__\"\nLLM_KEY = \"__SET_LLM_KEY__\"\nLLM_MODEL = \"openai/gpt-4o-mini\"\n```\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n### 发布工具\n\n系统提供 CLI 用于发布 MCP 服务器：\n\n```bash\nmake publisher      # 构建发布工具\n./bin/mcp-publisher # 运行发布\n```\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n## 验证与测试\n\n### 构建与测试命令\n\n| 命令 | 用途 |\n|------|------|\n| `make check` | 运行 lint、单元测试、集成测试 |\n| `npm run build` | TypeScript 编译与打包 |\n| `npm run test:build` | 构建产物测试 |\n| `npm run smoke:custom-bridge` | 自定义桥接烟雾测试 |\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md), [tasks/task061.md]()\n\n## 技术栈\n\n| 层级 | 技术选型 | 版本要求 |\n|------|----------|----------|\n| 运行时 | Node.js | ≥ 18 |\n| 语言 | TypeScript | ES Modules |\n| 协议 | Model Context Protocol | 1.x |\n| 包管理 | npm | - |\n| 发布格式 | npx 可执行包 | @leryk1981/mova-flat-runner |\n\n资料来源：[package.json:1-15]()\n\n## 总结\n\nmova-flat-runner 采用了清晰的分层架构：\n\n1. **协议层**：通过 MCP 协议与 AI 客户端交互\n2. **调度层**：`executeTool` 统一分发请求\n3. **传输层**：支持本地执行与远程 API 两种路径\n4. **安全层**：步骤模式守卫确保工作流定义一致性\n5. **数据层**：合约包验证器保障部署安全\n\n该架构支持灵活的工作流执行模式，同时通过 MCP 协议为 AI 代理提供标准化的工具接口，实现了业务逻辑与 AI 推理的解耦。\n\n---\n\n<a id='page-transport-layer'></a>\n\n## 传输层\n\n### 相关页面\n\n相关主题：[系统架构](#page-system-architecture), [可用工具集](#page-available-tools)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/transports/local_seam_bridge.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/local_seam_bridge.ts)\n- [src/transports/remote_api.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/remote_api.ts)\n- [src/index.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/index.ts)\n- [dist-test/src/transports/local_seam_bridge.js](https://github.com/mova-compact/mova-flat-runner/blob/main/dist-test/src/transports/local_seam_bridge.js)\n- [dist-test/src/transports/remote_api.js](https://github.com/mova-compact/mova-flat-runner/blob/main/dist-test/src/transports/remote_api.js)\n</details>\n\n# 传输层\n\n## 概述\n\n传输层（Transport Layer）是 mova-flat-runner 中负责在不同执行环境之间传递数据和调用命令的核心模块。该层抽象了本地执行与远程 API 调用两种传输机制，使上层业务逻辑能够以统一的方式与 MOVA 运行时进行交互，而无需关心具体的通信细节。\n\nmova-flat-runner 的传输层包含两个主要实现：\n\n| 传输实现 | 文件路径 | 用途 |\n|---------|---------|------|\n| 本地桥接传输 | `src/transports/local_seam_bridge.ts` | 本地进程内的桥接调用，通过文件系统进行状态管理 |\n| 远程 API 传输 | `src/transports/remote_api.ts` | 通过 HTTP/REST 与远程 MOVA 服务端点通信 |\n\n资料来源：[src/transports/local_seam_bridge.ts:1-30](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/local_seam_bridge.ts)\n\n---\n\n## 架构设计\n\n### 传输层定位\n\n```\n┌─────────────────────────────────────────────────────────┐\n│                    MCP 协议层                            │\n│         (mova_run, mova_query, mova_decide)             │\n└─────────────────────────────────────────────────────────┘\n                            │\n                            ▼\n┌─────────────────────────────────────────────────────────┐\n│                   传输层 (Transport)                     │\n│  ┌─────────────────┐      ┌─────────────────────────┐  │\n│  │ local_seam_     │      │     remote_api          │  │\n│  │ bridge          │      │  (movaGet/movaPost...)  │  │\n│  └─────────────────┘      └─────────────────────────┘  │\n└─────────────────────────────────────────────────────────┘\n           │                              │\n           ▼                              ▼\n    本地文件系统状态                 REST API 远程调用\n    (state_file)                   (api.mova-lab.eu)\n```\n\n### 传输策略选择\n\n传输层通过配置中的 `baseUrl` 判断使用哪种传输策略：\n\n```typescript\nexport function isLocalSeamConfig(config: MovaConfig): boolean {\n    return config.baseUrl === LOCAL_SEAM_BACKEND;\n}\n```\n\n- 当 `baseUrl` 为本地后端地址时，使用本地桥接传输\n- 当 `baseUrl` 为远程 API 地址时，使用 HTTP 传输\n\n资料来源：[dist-test/src/transports/local_seam_bridge.js:85-87](https://github.com/mova-compact/mova-flat-runner/blob/main/dist-test/src/transports/local_seam_bridge.js)\n\n---\n\n## 本地桥接传输 (local_seam_bridge)\n\n### 核心功能\n\n本地桥接传输用于在本地进程环境中直接与 MOVA 运行时交互，通过文件系统存储状态数据，无需网络通信。\n\n#### 内部桥接调用器\n\n`createInternalBridgeInvoker()` 创建一个桥接调用函数，负责处理步骤执行结果的标准化输出：\n\n```typescript\nfunction createInternalBridgeInvoker() {\n    return async function bridgeInvoker(request) {\n        bridgeSequence += 1;\n        const suffix = `${request.step.id}:${bridgeSequence}`;\n        \n        const producedOutput =\n            request.step.execution_mode === \"AI_ATOMIC\"\n                ? CANONICAL_STRATEGY\n                : request.stepResult ?? null;\n        \n        const status =\n            request.step.execution_mode === \"HUMAN_GATE\" && request.humanDecision == null\n                ? \"human_gate_required\"\n                : request.terminalOutcome\n                    ? \"completed\"\n                    : \"advanced\";\n\n        return {\n            ok: true,\n            bridge: {\n                ok: true,\n                bridge_source: \"mova_flat_runner_canonical_bridge\",\n                status,\n                contract_ref: request.contractRef,\n                // ... 更多字段\n            },\n        };\n    };\n}\n```\n\n资料来源：[src/transports/local_seam_bridge.ts:55-95](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/local_seam_bridge.ts)\n\n#### 状态管理\n\n本地传输通过以下方式解析运行定位器：\n\n```typescript\nasync function resolveLocalSeamLocator(initialInputs) {\n    const packagePath = \n        typeof initialInputs.package_path === \"string\" && initialInputs.package_path.trim().length > 0\n            ? initialInputs.package_path\n            : process.env.MOVA_SANDBOX_PACKAGE_PATH ?? \"D:\\\\Projects_MOVA\\\\mova-intent\\\\contracts\\\\dockerfile-nodejs-v1\";\n\n    const projectPath = \n        typeof initialInputs.project_path === \"string\" && initialInputs.project_path.trim().length > 0\n            ? initialInputs.project_path\n            : process.env.MOVA_SANDBOX_PROJECT_PATH ?? \"\";\n\n    const stateFile = \n        typeof initialInputs.state_file === \"string\" && initialInputs.state_file.trim().length > 0\n            ? initialInputs.state_file\n            : path.join(await fs.mkdtemp(path.join(os.tmpdir(), \"mova-flat-runner-bridge-\")), \"run_state.json\");\n\n    return { package_path: packagePath, project_path: projectPath, state_file: stateFile };\n}\n```\n\n资料来源：[src/transports/local_seam_bridge.ts:105-125](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/local_seam_bridge.ts)\n\n### 执行模式与状态映射\n\n| 执行模式 | humanDecision 状态 | 返回状态 |\n|---------|-------------------|---------|\n| `AI_ATOMIC` | 任意 | `produced_output = CANONICAL_STRATEGY` |\n| `HUMAN_GATE` | `null` | `human_gate_required` |\n| `HUMAN_GATE` | 有值 | `advanced` |\n| 任意 | `terminalOutcome = true` | `completed` |\n\n### 公共形状过滤\n\n`sanitizePublicShape()` 函数确保敏感内部字段不会泄漏到外部响应：\n\n```typescript\nfunction sanitizePublicShape(value: unknown): boolean {\n    if (Array.isArray(value)) {\n        return value.every((item) => sanitizePublicShape(item));\n    }\n    if (!value || typeof value !== \"object\") {\n        return true;\n    }\n    for (const [key, child] of Object.entries(value)) {\n        // 过滤敏感字段\n        if ([\"bridge_anchors\", \"last_terminal_bridge\", \"terminal_commit_count\", \n             \"_state15_bridge\", \"trace\", \"outputs\", \"context\"].includes(key)) {\n            return false;\n        }\n        if (!sanitizePublicShape(child)) {\n            return false;\n        }\n    }\n    return true;\n}\n```\n\n资料来源：[src/transports/local_seam_bridge.ts:130-150](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/local_seam_bridge.ts)\n\n### 人工决策处理\n\n本地传输提供两个关键函数用于人工决策流程：\n\n#### 获取决策点\n\n```typescript\nexport async function movaGetDecisionPointLocal(runReference) {\n    const locator = await resolveOpaqueLocatorOrThrow(runReference);\n    const machine = await loadMachineBridgeModule();\n    const gate = await machine.get_human_gate({ state_file: locator.state_file });\n    \n    if (!sanitizePublicShape(gate)) {\n        throw new Error(\"internal_field_leak\");\n    }\n    return gate;\n}\n```\n\n#### 提交决策\n\n```typescript\nexport async function movaSubmitDecisionLocal(runReference, option, reason) {\n    const locator = await resolveOpaqueLocatorOrThrow(runReference);\n    const machine = await loadMachineBridgeModule();\n    const resolution = await machine.submit_human_resolution({\n        package_path: locator.package_path,\n        state_file: locator.state_file,\n        step_id: \"review_strategy\",\n        // ...\n    });\n}\n```\n\n资料来源：[dist-test/src/transports/local_seam_bridge.js:95-120](https://github.com/mova-compact/mova-flat-runner/blob/main/dist-test/src/transports/local_seam_bridge.js)\n\n---\n\n## 远程 API 传输 (remote_api)\n\n### HTTP 方法封装\n\n远程传输提供标准的 RESTful API 调用封装：\n\n```typescript\nexport const movaGet    = (config, path) => movaRequest(config, \"GET\", path);\nexport const movaPut    = (config, path, body) => movaRequest(config, \"PUT\", path, body);\nexport const movaDelete = (config, path) => movaRequest(config, \"DELETE\", path);\nexport const movaPost   = (config, path, body) => movaRequest(config, \"POST\", path, body);\n```\n\n### 远程步骤执行\n\n`movaRunStepsRemote()` 函数按顺序执行 `analyze`、`verify`、`decide` 三个步骤：\n\n```mermaid\ngraph TD\n    A[开始 movaRunStepsRemote] --> B[执行 analyze 步骤]\n    B --> C{结果 ok?}\n    C -->|否| D[返回错误]\n    C -->|是| E[获取 analyze 输出]\n    E --> F[执行 verify 步骤]\n    F --> G{结果 ok?}\n    G -->|否| D\n    G -->|是| H{状态 = waiting_human?}\n    H -->|是| I[获取 decision_point]\n    H -->|否| J[执行 decide 步骤]\n    I --> K[返回等待人工决策]\n    J --> L[返回执行结果]\n```\n\n```typescript\nexport async function movaRunStepsRemote(cfg, contractId, validators, initialInputs = {}) {\n    let analysis = {};\n    for (const stepId of [\"analyze\", \"verify\", \"decide\"]) {\n        let result;\n        try {\n            result = await movaPost(cfg, `/api/v1/contracts/${contractId}/step`, {\n                envelope: {\n                    kind: \"env.step.execute_v0\",\n                    envelope_id: `env-${shortId()}`,\n                    contract_id: contractId,\n                    actor: { actor_type: \"system\", actor_id: \"mova_runtime\" },\n                    payload: { step_id: stepId },\n                },\n            });\n        } catch (error) {\n            return flatErr(code, error.message, undefined, retryable);\n        }\n        \n        if (!result.ok) {\n            return flatErr(ERR.API_REQUEST_FAILED, `Step \"${stepId}\" returned ok=false`, result);\n        }\n        \n        // 处理分析输出和验证器\n        if (stepId === \"analyze\") {\n            const output = await movaGet(cfg, `/api/v1/contracts/${contractId}/steps/analyze/output`);\n            analysis = { ...output };\n            \n            // 执行验证器\n            for (const validator of validators) {\n                const fn = VALIDATOR_REGISTRY.get(validator.validator_id);\n                if (!fn) {\n                    analysis[`${validator.step_id}_error`] = `VALIDATOR_NOT_ALLOWED`;\n                    continue;\n                }\n                const resultValue = fn({ ...initialInputs, ...analysis });\n                Object.assign(analysis, resultValue.value ?? {});\n            }\n        }\n    }\n    return { ok: true, analysis };\n}\n```\n\n资料来源：[dist-test/src/transports/remote_api.js:60-95](https://github.com/mova-compact/mova-flat-runner/blob/main/dist-test/src/transports/remote_api.js)\n\n### 错误处理机制\n\n| 错误类型 | 处理策略 | retryable |\n|---------|---------|-----------|\n| API 请求失败 | 返回错误码 `ERR.API_REQUEST_FAILED` | 由错误对象决定 |\n| 步骤返回 `ok=false` | 返回包含失败详情的错误 | `false` |\n| 验证器未注册 | 记录错误但继续执行 | 不适用 |\n| 验证器执行异常 | 捕获并记录到分析结果中 | 不适用 |\n\n### 人工决策端点\n\n远程 API 在检测到 `waiting_human` 状态时，额外查询决策点信息：\n\n```typescript\nif (result.status === \"waiting_human\") {\n    let decisionPoint = {};\n    try {\n        const response = await movaGet(cfg, `/api/v1/contracts/${contractId}/decision`);\n        decisionPoint = (response.decision_point ?? {});\n    } catch {\n        // 非致命错误，legacy 远程路径兼容\n    }\n    return {\n        ok: true,\n        status: \"waiting_human\",\n        contract_id: contractId,\n        question: decisionPoint.question ?? \"Select action:\",\n        options: decisionPoint.options ?? [],\n        recommended: decisionPoint.recommended_option_id ?? null,\n        analysis,\n    };\n}\n```\n\n---\n\n## 传输配置\n\n### MovaConfig 配置结构\n\n| 字段 | 类型 | 说明 |\n|-----|------|------|\n| `baseUrl` | `string` | API 基础地址，决定使用本地或远程传输 |\n| `apiKey` | `string` | API 认证密钥 |\n| `timeoutMs` | `number` | 请求超时时间（毫秒） |\n| `headers` | `Record<string, string>` | 自定义 HTTP 请求头 |\n\n### 环境变量映射\n\n```env\n# 远程 API 配置\nMOVA_API_URL=https://api.mova-lab.eu\nMOVA_API_KEY=__SET_MOVA_API_KEY__\n\n# 本地传输配置\nMOVA_SANDBOX_PACKAGE_PATH=默认包路径\nMOVA_SANDBOX_PROJECT_PATH=默认项目路径\n\n# 可选配置\nMOVA_API_TIMEOUT_MS=30000\nMOVA_HTTP_PORT=3796\n```\n\n---\n\n## 工作流程对比\n\n```mermaid\ngraph LR\n    subgraph 本地传输\n        L1[解析输入] --> L2[创建状态文件]\n        L2 --> L3[调用本地机器模块]\n        L3 --> L4[读写 state_file]\n        L4 --> L5[返回结果]\n    end\n    \n    subgraph 远程传输\n        R1[解析输入] --> R2[构建信封]\n        R2 --> R3[HTTP POST /step]\n        R3 --> R4[轮询状态]\n        R4 --> R5[返回结果]\n    end\n    \n    A{传输类型} -->|本地| 本地传输\n    A -->|远程| 远程传输\n```\n\n| 特性 | 本地传输 | 远程传输 |\n|-----|---------|---------|\n| 通信方式 | 进程调用 + 文件系统 | HTTP/REST API |\n| 状态存储 | 本地 `state_file` | 服务端管理 |\n| 延迟 | 低 | 取决于网络 |\n| 可扩展性 | 单机 | 分布式 |\n| 适用场景 | 开发调试、沙箱 | 生产环境 |\n\n---\n\n## 安全性考量\n\n### 输入验证\n\n所有通过传输层传递的输入都经过严格验证：\n\n1. **路径验证**：防止路径遍历攻击\n2. **类型检查**：确保配置参数类型正确\n3. **空值处理**：验证必需字段存在\n\n### 输出过滤\n\n`sanitizePublicShape()` 函数过滤以下敏感字段：\n\n- `bridge_anchors` - 桥接锚点\n- `last_terminal_bridge` - 最终桥接状态\n- `terminal_commit_count` - 提交计数\n- `_state15_bridge` - 内部状态\n- `trace` - 执行跟踪\n- `outputs` - 完整输出\n- `context` - 运行时上下文\n\n### 错误隔离\n\n传输层错误被封装为标准化错误响应，防止内部实现细节泄漏：\n\n```typescript\nfunction isMovaNotFoundError(error: unknown): boolean {\n    const msg = error instanceof Error ? error.message : String(error);\n    return msg.includes(\"MOVA API 404\");\n}\n```\n\n---\n\n## 相关文件索引\n\n| 模块 | 文件路径 | 职责 |\n|-----|---------|------|\n| 入口点 | `src/index.ts` | 传输层调用入口，工具执行路由 |\n| 本地桥接 | `src/transports/local_seam_bridge.ts` | 本地执行环境和文件系统交互 |\n| 远程 API | `src/transports/remote_api.ts` | HTTP API 通信封装 |\n| 安全模块 | `src/security/step_mode_guard.ts` | 步骤模式验证 |\n\n---\n\n<a id='page-security-module'></a>\n\n## 安全模块\n\n### 相关页面\n\n相关主题：[系统架构](#page-system-architecture), [业务验证器](#page-validators)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/security/class_definition_guard.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/security/class_definition_guard.ts)\n- [src/security/step_mode_guard.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/security/step_mode_guard.ts)\n- [src/security/flow_schema_guard.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/security/flow_schema_guard.ts)\n- [src/validators/aml.js](https://github.com/mova-compact/mova-flat-runner/blob/main/src/validators/aml.js)\n- [src/transports/local_seam_bridge.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/local_seam_bridge.ts)\n- [src/index.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/index.ts)\n</details>\n\n# 安全模块\n\n## 概述\n\nmova-flat-runner 的安全模块采用**纵深防御（Defense-in-Depth）**策略，通过多个独立的安全守卫（Security Guards）在不同层级验证合约流程的完整性和安全性。这些守卫在模块导入时无副作用执行，所有验证逻辑均为纯函数，确保不会因验证失败而产生意外状态变更。\n\n核心安全目标包括：\n\n- 防止特权提升攻击（Privilege Escalation）\n- 阻断内联类定义注入（Inline Class Definition Injection）\n- 验证步骤执行模式与字段的一致性\n- 确保合约执行的确定性边界\n\n## 架构概览\n\n```mermaid\ngraph TD\n    subgraph 安全模块架构\n        FSG[flow_schema_guard<br/>CFV-9 流程Schema守卫]\n        CDG[class_definition_guard<br/>CFV-10 类定义守卫]\n        SMG[step_mode_guard<br/>步骤模式守卫]\n        \n        FSG -->|拒绝未知顶层字段| ERR1[ERR.SCHEMA_VIOLATION]\n        CDG -->|拒绝内联类定义| ERR2[ERR.INLINE_CLASS_DEFINITION_FORBIDDEN]\n        SMG -->|模式字段不匹配| ERR3[ERR.STEP_MODE_FIELD_MISMATCH]\n    end\n    \n    subgraph 入口点\n        REG[合约注册]\n        RUN[合约执行]\n    end\n    \n    REG --> FSG\n    REG --> CDG\n    RUN --> SMG\n```\n\n## CFV-9 流程 Schema 守卫\n\n### 背景与目的\n\n安全审计发现，某些恶意流程包含 `__admin_override`、`__privilege_grant`、`__debug_mode` 等顶层字段。虽然初始注册逻辑不直接使用这些字段，但它们可能被持久化存储，后续代码路径若读取这些字段将导致特权提升漏洞。\n\nflow_schema_guard.ts 实现**严格默认（Strict-by-Default）**策略：拒绝任何不在白名单中的顶层键。\n\n### 白名单定义\n\n| 允许的顶层键 | 用途 |\n|-------------|------|\n| `version` | 流程版本标识 |\n| `description` | 流程描述 |\n| `entry` | 入口步骤引用 |\n| `steps` | 步骤定义对象 |\n| `parallel_steps` | 并行步骤定义 |\n| `notes` | 备注信息 |\n| `audit_mode` | 审计模式配置 |\n| `audit_mode_note` | 审计模式说明 |\n| `class_definition_ref` | 类定义引用（远程解析） |\n| `CONTRACT_CALL_instructions` | 合约调用指令 |\n| `input_schema` | 输入数据Schema |\n| `output_schema` | 输出数据Schema |\n| `metadata` | 元数据 |\n\n### 核心实现\n\n```typescript\n// 资料来源：src/security/flow_schema_guard.ts:17-30\nexport const ALLOWED_FLOW_TOP_LEVEL_KEYS: ReadonlySet<string> = new Set([\n  \"version\",\n  \"description\",\n  \"entry\",\n  \"steps\",\n  \"parallel_steps\",\n  \"notes\",\n  \"audit_mode\",\n  \"audit_mode_note\",\n  \"class_definition_ref\",\n  \"CONTRACT_CALL_instructions\",\n  \"input_schema\",\n  \"output_schema\",\n  \"metadata\",\n]);\n```\n\n### 验证函数\n\n```typescript\n// 资料来源：src/security/flow_schema_guard.ts:33-43\nexport function findUnknownFlowFields(flow: unknown): string[] {\n  if (!flow || typeof flow !== \"object\" || Array.isArray(flow)) return [];\n  const f = flow as Record<string, unknown>;\n  const out: string[] = [];\n  for (const key of Object.keys(f)) {\n    if (!ALLOWED_FLOW_TOP_LEVEL_KEYS.has(key))\n      out.push(key);\n  }\n  return out;\n}\n```\n\n当发现未知字段时，返回格式化的错误响应：\n\n```typescript\n// 资料来源：src/security/flow_schema_guard.ts:45-55\nexport function assertNoUnknownFlowFields(\n  flow: unknown,\n  requestId: string,\n): FlatRunnerResult | null {\n  const unknown = findUnknownFlowFields(flow);\n  if (unknown.length === 0) return null;\n  return flatErr(ERR.SCHEMA_VIOLATION, ..., { unknown_fields: unknown }, false, requestId);\n}\n```\n\n## CFV-10 类定义守卫\n\n### 背景与目的\n\n类定义（class_definition）包含敏感的配置信息，如严重性等级（severity bands）和噪声控制参数。安全审计发现攻击者可将类定义以内联方式嵌入流程，绕过注册表权威验证，从而操纵安全决策。\n\nclass_definition_guard.ts 强制要求类定义必须通过注册表（Registry）按 `class_id` 解析，禁止内联定义。\n\n### 禁止字段列表\n\n| 禁止的字段名 | 说明 |\n|-------------|------|\n| `class_definition` | 完整类定义对象 |\n| `class_definition_inline` | 内联类定义 |\n| `class_def_override` | 类定义覆盖 |\n| `class_def` | 缩写形式 |\n\n### 核心实现\n\n```typescript\n// 资料来源：src/security/class_definition_guard.ts:12-18\nconst FORBIDDEN_FLOW_KEYS: readonly string[] = Object.freeze([\n  \"class_definition\",\n  \"class_definition_inline\",\n  \"class_def_override\",\n  \"class_def\",\n]);\n\n// 资料来源：src/security/class_definition_guard.ts:21-28\nexport function findInlineClassDefinitionFields(flow: unknown): string[] {\n  if (!flow || typeof flow !== \"object\") return [];\n  const f = flow as Record<string, unknown>;\n  return FORBIDDEN_FLOW_KEYS.filter((k) => Object.prototype.hasOwnProperty.call(f, k));\n}\n```\n\n### 错误响应\n\n```typescript\n// 资料来源：src/security/class_definition_guard.ts:30-45\nexport function assertNoInlineClassDefinition(\n  flow: unknown,\n  requestId: string,\n): FlatRunnerResult | null {\n  const found = findInlineClassDefinitionFields(flow);\n  if (found.length === 0) return null;\n  return flatErr(\n    ERR.INLINE_CLASS_DEFINITION_FORBIDDEN,\n    `Flow body contains inline class-definition field(s): ${found.join(\", \")}. ` +\n    \"Class definitions must be resolved from the registry by class_id, not embedded in the flow.\",\n    {\n      forbidden_fields: found,\n      remediation: \"Remove these fields and reference the class via class_id; the registry is the only authority on severity bands and noise control.\",\n      http_status_equivalent: 400,\n    },\n    false,\n    requestId,\n  );\n}\n```\n\n## 步骤模式守卫\n\n### 执行模式类型\n\n| 模式 | 说明 | 必需字段 |\n|------|------|---------|\n| `DETERMINISTIC` | 本地JS校验，无LLM调用 | 无额外要求 |\n| `AI_ATOMIC` | LLM原子执行 | 必须有 `model` 字段 |\n| `CONTRACT_CALL` | 调用其他合约 | 必须有 `contract_id` 字段 |\n| `HUMAN_GATE` | 人工决策门 | 必须有 `decision_options` 数组 |\n\n### 验证规则\n\n步骤模式守卫检测以下违规场景：\n\n1. **DETERMINISTIC 模式含 model 字段**\n   \n   ```typescript\n   // 资料来源：src/security/step_mode_guard.ts:42-49\n   if (mode === \"DETERMINISTIC\" && step.model !== undefined && step.model !== null) {\n     out.push({\n       kind: \"deterministic_with_model\",\n       step_id: id,\n       execution_mode: mode,\n       message: `step '${id ?? \"?\"}' is DETERMINISTIC but declares a 'model' field — DET steps run a local JS check, not an LLM`,\n     });\n   }\n   ```\n\n2. **AI_ATOMIC 模式缺少 model 字段**\n   \n   ```typescript\n   // 资料来源：src/security/step_mode_guard.ts:51-58\n   if (mode === \"AI_ATOMIC\" && asStr(step.model) === null) {\n     out.push({\n       kind: \"ai_atomic_without_model\",\n       step_id: id,\n       execution_mode: mode,\n       message: `step '${id ?? \"?\"}' is AI_ATOMIC but has no 'model' field`,\n     });\n   }\n   ```\n\n3. **CONTRACT_CALL 模式缺少 contract_id**\n   \n   ```typescript\n   // 资料来源：src/security/step_mode_guard.ts:60-67\n   if (mode === \"CONTRACT_CALL\" && asStr(step.contract_id) === null) {\n     out.push({\n       kind: \"contract_call_without_contract_id\",\n       step_id: id,\n       execution_mode: mode,\n       message: `step '${id ?? \"?\"}' is CONTRACT_CALL but has no 'contract_id'`,\n     });\n   }\n   ```\n\n4. **HUMAN_GATE 模式缺少 decision_options**\n   \n   ```typescript\n   // 资料来源：src/security/step_mode_guard.ts:69-76\n   if (mode === \"HUMAN_GATE\" && !Array.isArray(step.decision_options)) {\n     out.push({\n       kind: \"human_gate_without_decisions\",\n       step_id: id,\n       execution_mode: mode,\n       message: `step '${id ?? \"?\"}' is HUMAN_GATE but has no 'decision_options' array`,\n     });\n   }\n   ```\n\n### 验证流程\n\n```mermaid\ngraph TD\n    A[遍历流程步骤] --> B{获取 execution_mode}\n    B -->|DETERMINISTIC| C{是否有 model?}\n    B -->|AI_ATOMIC| D{是否有 model?}\n    B -->|CONTRACT_CALL| E{是否有 contract_id?}\n    B -->|HUMAN_GATE| F{是否有 decision_options?}\n    \n    C -->|是| G[记录违规<br/>deterministic_with_model]\n    C -->|否| H[通过]\n    D -->|否| I[记录违规<br/>ai_atomic_without_model]\n    D -->|是| J[通过]\n    E -->|否| K[记录违规<br/>contract_call_without_contract_id]\n    E -->|是| L[通过]\n    F -->|否| M[记录违规<br/>human_gate_without_decisions]\n    F -->|是| N[通过]\n    \n    G --> O{违规数量 > 0?}\n    I --> O\n    K --> O\n    M --> O\n    H --> O\n    J --> O\n    L --> O\n    N --> O\n    \n    O -->|是| P[返回 flatErr<br/>ERR.STEP_MODE_FIELD_MISMATCH]\n    O -->|否| Q[验证通过]\n```\n\n## HUMAN_GATE 安全控制\n\n### 专用完成路径\n\nHUMAN_GATE 步骤不能通过通用的 `step_complete` 操作完成，必须使用专用的门控确认路径：\n\n```typescript\n// 资料来源：src/index.ts (上下文中的 gate_guard 使用)\ncase \"step_complete\": {\n  // SECURITY (CFV-3): HUMAN_GATE cannot be completed by generic step completion.\n  // Human confirmation requires the dedicated gate path (gate_approve / gate_reject).\n  const gateGuard = await assertNotHumanGate(config, args.run_id, args.step_id, requestId);\n  if (gateGuard) return gateGuard;\n  // ... 执行通用完成逻辑\n}\n\ncase \"gate_approve\": {\n  // 专用人工确认路径\n}\n\ncase \"gate_reject\": {\n  // 专用人工拒绝路径\n}\n```\n\n### Bridge 状态映射\n\n当流程遇到 HUMAN_GATE 时，local_seam_bridge 返回特定的桥接状态：\n\n```typescript\n// 资料来源：src/transports/local_seam_bridge.ts:19-25\nconst status =\n  request.step.execution_mode === \"HUMAN_GATE\" && request.humanDecision == null\n    ? \"human_gate_required\"\n    : request.terminalOutcome\n      ? \"completed\"\n      : \"advanced\";\n\n// 资料来源：src/transports/local_seam_bridge.ts:40-41\nnext_phase: { phase: status === \"human_gate_required\" ? \"WAIT_HUMAN\" : \"EXECUTION\" },\n```\n\n## 验证器集成\n\n### AML 验证器示例\n\n安全模块还包括业务级验证器（如 AML 合规验证器）：\n\n```javascript\n// 资料来源：src/validators/aml.js:1-28\nexport const amlValidators = [\n    {\n        id: \"aml.validate_policy_flags_v0\",\n        fn: (inputs) => {\n            const sanctions = Boolean(inputs.sanctions_match);\n            const pep = Boolean(inputs.pep_status);\n            const score = Number(inputs.risk_score) || 0;\n            const mandatory_escalate = sanctions || pep || score > 85;\n            const auto_clear = (score <= 30 && !sanctions && !pep && ...);\n            return {\n                ok: true,\n                value: {\n                    policy_flags_valid: score >= 0 && score <= 100,\n                    mandatory_escalate,\n                    auto_clear_eligible: auto_clear,\n                },\n            };\n        },\n    },\n];\n```\n\n### 验证器执行流程\n\n```mermaid\ngraph LR\n    A[远程获取分析输出] --> B[遍历验证器注册表]\n    B --> C{验证器ID存在?}\n    C -->|是| D[执行验证函数]\n    C -->|否| E[记录 VALIDATOR_NOT_ALLOWED 错误]\n    D --> F{验证执行成功?}\n    F -->|是| G[合并验证结果到分析输出]\n    F -->|否| H[记录 VALIDATOR_FAILED 错误]\n```\n\n```typescript\n// 资料来源：src/transports/remote_api.js:15-36\nconst validatorContext = { ...initialInputs, ...analysis };\nfor (const validator of validators) {\n  const fn = VALIDATOR_REGISTRY.get(validator.validator_id);\n  if (!fn) {\n    analysis[`${validator.step_id}_error`] = `VALIDATOR_NOT_ALLOWED: \"${validator.validator_id}\" not in registry`;\n    continue;\n  }\n  try {\n    const resultValue = fn(validatorContext);\n    Object.assign(analysis, resultValue.value ?? {});\n  } catch (error) {\n    analysis[`${validator.step_id}_error`] = `VALIDATOR_FAILED: ${String(error)}`;\n  }\n}\n```\n\n## 错误码对照表\n\n| 错误码常量 | 说明 | HTTP 等效状态 |\n|-----------|------|---------------|\n| `ERR.SCHEMA_VIOLATION` | 流程包含未授权的顶层字段 | 400 |\n| `ERR.INLINE_CLASS_DEFINITION_FORBIDDEN` | 禁止内联类定义 | 400 |\n| `ERR.STEP_MODE_FIELD_MISMATCH` | 执行模式与字段不匹配 | 400 |\n| `ERR.UNKNOWN_CONTRACT_TYPE` | 未知的合约类型 | 400 |\n| `ERR.LOCAL_VALIDATION_FAILED` | 本地验证失败 | 400 |\n| `ERR.GATE_REJECTED` | 人工门被拒绝 | 402 |\n\n## 安全模块设计原则\n\n1. **纯函数验证**：所有守卫函数无副作用，支持安全的并行执行和测试\n2. **显式拒绝**：默认拒绝策略，未明确允许的均为禁止\n3. **清晰错误信息**：违规响应包含违规详情和修复建议\n4. **纵深防御**：多层守卫互补，覆盖不同攻击向量\n5. **注册表权威**：敏感配置（如类定义）必须从注册表解析，禁止内联\n\n## 集成位置\n\n安全守卫在以下入口点被调用：\n\n| 入口 | 调用的守卫 |\n|------|-----------|\n| 合约注册 | flow_schema_guard, class_definition_guard |\n| 步骤执行 | step_mode_guard, gate_guard |\n| 远程API调用 | 验证器注册表执行 |\n\n```typescript\n// 资料来源：src/index.ts (集成示例)\nswitch (name) {\n  case \"mova_contract\": {\n    if (action === \"register\") {\n      // 调用安全守卫\n      const schemaGuard = assertNoUnknownFlowFields(flow, requestId);\n      const classGuard = assertNoInlineClassDefinition(flow, requestId);\n      // ...\n    }\n  }\n}\n\n---\n\n<a id='page-available-tools'></a>\n\n## 可用工具集\n\n### 相关页面\n\n相关主题：[核心概念](#page-core-concepts), [传输层](#page-transport-layer)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/index.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/index.ts)\n- [src/transports/local_seam_bridge.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/local_seam_bridge.ts)\n- [src/security/step_mode_guard.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/security/step_mode_guard.ts)\n- [src/package_support.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/package_support.ts)\n- [src/transports/remote_api.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/remote_api.ts)\n- [src/client.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/client.ts)\n\n</details>\n\n# 可用工具集\n\n## 概述\n\nmova-flat-runner 提供了一套完整的 MCP（Model Context Protocol）工具集，用于与 MOVA 平台进行交互。这套工具集涵盖了从合约执行、状态查询、决策支持到安全验证的完整工作流程。\n\n工具集通过 MCP 协议暴露为标准化接口，支持本地运行和远程 API 调用两种模式。所有工具均返回 JSON 格式的结构化响应，包含执行状态、结果数据和错误信息。资料来源：[src/index.ts:1-50]()\n\n## 工具列表总览\n\n| 工具名称 | 功能描述 | 执行模式 |\n|---------|---------|---------|\n| `mova_health` | 健康检查与连接验证 | 同步 |\n| `mova_registry` | 获取可用合约清单 | 同步 |\n| `mova_run` | 执行内置合约 | 本地/远程 |\n| `mova_query` | 查询合约状态与审计信息 | 远程 |\n| `mova_decide` | 触发决策流程 | 远程 |\n| `mova_connector` | 连接外部系统 | 远程 |\n| `mova_contract` | 自定义合约操作（注册/运行/状态） | 远程 |\n\n资料来源：[README.md:55-62]()\n\n## 核心工具详解\n\n### mova_run\n\n`mova_run` 是执行内置合约的核心工具，支持预定义的合约类型列表。\n\n#### 支持的合约类型\n\n系统内置了多个合约 manifest，存储在 `CONTRACT_MANIFESTS` 映射中。每个 manifest 包含：\n\n- `contract_type`：合约类型标识\n- `title`：合约标题\n- `version`：版本号\n- `execution_mode`：执行模式（AI_ATOMIC、DETERMINISTIC、HUMAN_GATE 等）\n- `template_id`：模板标识\n- `dataspec`：输入数据规格\n\n资料来源：[src/index.ts:200-280]()\n\n#### 执行流程\n\n```mermaid\ngraph TD\n    A[接收合约类型与输入] --> B{查找 Manifest}\n    B -->|找到| C[验证输入数据]\n    B -->|未找到| D[返回未知合约类型错误]\n    C --> E{执行模式}\n    E -->|LOCAL_SEAM| F[本地沙箱执行]\n    E -->|REMOTE_API| G[远程 API 调用]\n    F --> H[返回执行结果]\n    G --> H\n```\n\n#### 安全验证\n\n执行前会进行多重安全检查：\n\n1. **Step Mode 验证**：确保执行模式与字段定义匹配\n2. **内联类定义检查**：禁止在流程中嵌入 class_definition\n3. **人类决策门保护**：HUMAN_GATE 步骤不可通过通用 step_complete 跳过\n\n资料来源：[src/security/step_mode_guard.ts:1-50]()\n\n### mova_contract\n\n自定义合约操作工具，支持完整的合约生命周期管理。\n\n#### 支持的操作\n\n| 操作 | 说明 | 所需参数 |\n|-----|------|---------|\n| `register` | 注册新合约 | contract_id, flow |\n| `run` | 运行合约 | contract_id |\n| `run_status` | 查询运行状态 | run_id |\n| `step_complete` | 完成步骤 | run_id, step_id, outcome, output |\n| `gate_approve` | 批准人类决策门 | run_id, step_id |\n| `gate_reject` | 拒绝人类决策门 | run_id, step_id, reason |\n| `cancel` | 取消运行 | run_id |\n\n资料来源：[src/index.ts:280-400]()\n\n#### 自定义合约桥接机制\n\n对于自定义合约（如 `local-*`、`remote-*` 前缀的 ID），系统实现了智能桥接：\n\n1. **运行追踪**：在 `run` 和 `run_status` 时记录 `contract_id → run_id` 映射\n2. **404 兜底**：当 `/api/v1/contracts/{contract_id}` 返回 404 时，探测 `/api/v1/contracts/my` 获取元数据\n3. **状态桥接**：返回结构化的 bridged status，包含 `bridge_mode=custom_contract_run_namespace_bridge_v1`\n\n资料来源：[src/index.ts:80-120]()\n\n### mova_query\n\n状态与审计信息查询工具，支持多种视图模式。\n\n#### 视图模式\n\n| 视图 | 说明 | 返回内容 |\n|-----|------|---------|\n| `status` | 状态视图 | 合约运行状态、结构化结果 |\n| `audit` | 审计视图 | 完整审计记录（需要后端支持） |\n| `audit_compact` | 紧凑审计 | 精简审计对象，含 journal |\n\n#### 自定义合约查询\n\n当查询自定义合约 ID 遇到 404 时：\n\n```mermaid\ngraph TD\n    A[查询 /api/v1/contracts/{id}] --> B{响应状态}\n    B -->|200| C[返回正常结果]\n    B -->|404| D[探测 /api/v1/contracts/my]\n    D --> E{找到合约记录}\n    E -->|是| F[构建桥接状态]\n    E -->|否| G[返回 AUDIT_UNAVAILABLE]\n```\n\n资料来源：[tasks/task061.md:1-50]()\n\n### mova_decide\n\n决策触发工具，用于启动需要 AI 推理的决策流程。\n\n#### 工作原理\n\n1. 接收决策请求上下文\n2. 调用后端决策端点\n3. 返回决策结果和可选的推荐选项\n4. 支持 human-in-the-loop 确认\n\n资料来源：[src/transports/remote_api.ts:80-120]()\n\n### mova_connector\n\n外部系统连接工具，用于集成第三方服务。\n\n#### 功能特性\n\n- 建立与外部 API 的连接\n- 传递认证信息（通过配置）\n- 处理请求/响应转换\n- 支持超时和重试配置\n\n### mova_health\n\n健康检查工具，用于验证与 MOVA API 的连接状态。\n\n```bash\ncurl -sS https://api.mova-lab.eu/health\n```\n\n资料来源：[README.md:48-50]()\n\n### mova_registry\n\n合约清单查询工具，返回所有可用合约的元信息。\n\n#### 返回格式\n\n```json\n{\n  \"schema_version\": \"1.0\",\n  \"contracts\": [\n    {\n      \"contract_type\": \"complaint\",\n      \"title\": \"投诉处理合约\",\n      \"version\": \"1.0.0\",\n      \"execution_mode\": \"AI_ATOMIC\",\n      \"manifest_resource\": \"mova://contracts/complaint/manifest\"\n    }\n  ]\n}\n```\n\n资料来源：[src/index.ts:450-480]()\n\n## 安全验证体系\n\n### Step Mode 字段一致性检查\n\n每种执行模式都有强制的字段要求：\n\n| 执行模式 | 必需字段 | 禁止字段 |\n|---------|---------|---------|\n| DETERMINISTIC | 无 | model |\n| AI_ATOMIC | model | 无 |\n| CONTRACT_CALL | contract_id | 无 |\n| HUMAN_GATE | decision_options | 无 |\n\n#### 检测的违规类型\n\n- `ai_atomic_without_model`：AI_ATOMIC 模式未定义 model 字段\n- `deterministic_with_model`：DETERMINISTIC 模式错误包含 model 字段\n- `contract_call_without_contract_id`：CONTRACT_CALL 缺少 contract_id\n- `human_gate_without_decisions`：HUMAN_GATE 缺少 decision_options\n\n资料来源：[src/security/step_mode_guard.ts:50-100]()\n\n### 内联类定义防护\n\n禁止在流程中直接嵌入 class_definition 字段：\n\n```typescript\nconst FORBIDDEN_FLOW_KEYS = [\n  \"class_definition_inline\",\n  \"class_def_override\", \n  \"class_def\"\n];\n```\n\n违规响应包含：\n- `forbidden_fields`：发现的禁止字段列表\n- `remediation`：修复建议\n- `http_status_equivalent`：400\n\n资料来源：[src/security/class_definition_guard.ts:1-40]()\n\n### 人类决策门保护\n\nHUMAN_GATE 步骤有特殊保护机制：\n\n1. **前置检查**：`step_complete` 操作会拒绝 HUMAM_GATE 步骤\n2. **专用路径**：必须通过 `gate_approve` 或 `gate_reject` 完成\n3. **原因记录**：拒绝操作需提供原因\n\n资料来源：[src/index.ts:350-380]()\n\n## 执行环境\n\n### 本地沙箱模式（LOCAL_SEAM）\n\n通过 `local_seam_bridge.ts` 实现本地执行：\n\n```mermaid\ngraph TD\n    A[请求] --> B[解析包路径]\n    B --> C[加载流程定义]\n    C --> D[执行步骤]\n    D --> E[状态持久化]\n    E --> F[返回桥接结果]\n```\n\n#### 关键特性\n\n- 状态文件自动管理\n- 支持自定义包路径和项目路径\n- 输出模式：`AI_ATOMIC` 自动生成 CANONICAL_STRATEGY\n- 人类门暂停机制\n\n资料来源：[src/transports/local_seam_bridge.ts:1-80]()\n\n### 远程 API 模式（REMOTE_API）\n\n通过 `remote_api.ts` 调用远程服务：\n\n```mermaid\ngraph TD\n    A[请求] --> B[构建请求信封]\n    B --> C[POST /api/v1/contracts/{id}/step]\n    C --> D{执行步骤}\n    D -->|analyze| E[获取分析输出]\n    D -->|verify| F[执行验证器]\n    D -->|decide| G[获取决策]\n    E --> H{状态检查}\n    H -->|waiting_human| I[返回决策点]\n    H -->|completed| J[返回完成结果]\n```\n\n#### 验证器执行\n\nanalyze 步骤后自动执行注册验证器：\n\n1. 从 `initialInputs` 构建验证上下文\n2. 遍历 `VALIDATOR_REGISTRY`\n3. 收集验证结果到 analysis 对象\n\n资料来源：[src/transports/remote_api.ts:100-150]()\n\n## 配置与环境变量\n\n### 必需变量\n\n| 变量名 | 说明 | 示例值 |\n|-------|------|-------|\n| `MOVA_API_URL` | API 端点 | `https://api.mova-lab.eu` |\n| `MOVA_API_KEY` | API 认证密钥 | `__SET_MOVA_API_KEY__` |\n| `LLM_KEY` | LLM 提供商密钥 | `__SET_LLM_KEY__` |\n| `LLM_MODEL` | LLM 模型标识 | `openai/gpt-4o-mini` |\n\n### 可选变量\n\n| 变量名 | 说明 | 默认值 |\n|-------|------|-------|\n| `MOVA_API_TIMEOUT_MS` | 请求超时（毫秒） | 30000 |\n| `MOVA_HTTP_PORT` | 本地 HTTP 端口 | 3796 |\n| `MOVA_INVOKE_TOKEN` | 本地调用令牌 | 无 |\n| `MOVA_SANDBOX_PACKAGE_PATH` | 沙箱包路径 | 项目默认 |\n| `MOVA_SANDBOX_PROJECT_PATH` | 沙箱项目路径 | 当前目录 |\n\n资料来源：[README.md:25-45]()\n\n## 包结构验证\n\n### Global 文件验证\n\n验证 `global.json` 的必需字段：\n\n- `global_id`：全局唯一标识（非空字符串）\n- `version`：版本号（非空字符串）\n- `scope`：必须为 `contract_package`\n- `semantic_roles`：非空数组\n- `non_authority_rules`：非空数组\n\n### Package Manifest 验证\n\n允许的 manifest 字段：\n\n```typescript\nconst allowedKeys = [\n  \"schema_id\",\n  \"package_id\", \n  \"version\",\n  \"global_ref\",\n  \"flow_ref\",\n  \"classification_policy_ref\",\n  \"classification_result_set_ref\",\n  \"runtime_binding_set_ref\",\n  \"model_refs\",\n  \"fixture_refs\",\n  \"package_invariants\"\n];\n```\n\n资料来源：[src/package_support.ts:50-100]()\n\n## 错误处理\n\n### 错误码体系\n\n| 错误码 | 说明 |\n|-------|------|\n| `UNKNOWN_CONTRACT_TYPE` | 未知的合约类型 |\n| `API_REQUEST_FAILED` | API 请求失败 |\n| `LOCAL_VALIDATION_FAILED` | 本地验证失败 |\n| `STEP_MODE_FIELD_MISMATCH` | 执行模式与字段不匹配 |\n| `INLINE_CLASS_DEFINITION_FORBIDDEN` | 禁止内联类定义 |\n\n### 重试机制\n\n错误响应包含 `retryable` 字段指示是否可重试：\n\n```json\n{\n  \"ok\": false,\n  \"code\": \"API_REQUEST_FAILED\",\n  \"message\": \"详细错误信息\",\n  \"retryable\": true\n}\n```\n\n资料来源：[src/index.ts:50-100]()\n\n## 总结\n\nmova-flat-runner 的工具集提供了从简单查询到复杂决策的完整能力覆盖。核心设计原则包括：\n\n1. **安全性优先**：多重验证机制确保流程正确性\n2. **灵活执行**：支持本地和远程两种执行模式\n3. **智能桥接**：自动处理自定义合约与内置路径的差异\n4. **标准化接口**：统一的 MCP 协议接口便于集成\n\n---\n\n<a id='page-validators'></a>\n\n## 业务验证器\n\n### 相关页面\n\n相关主题：[安全模块](#page-security-module), [可用工具集](#page-available-tools)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [src/validators/aml.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/validators/aml.ts)\n- [src/validators/churn.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/validators/churn.ts)\n- [src/validators/complaint.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/validators/complaint.ts)\n- [src/validators/compliance.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/validators/compliance.ts)\n- [src/validators/contract_gen.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/validators/contract_gen.ts)\n- [src/validators/credit.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/validators/credit.ts)\n- [src/validators/invoice.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/validators/invoice.ts)\n- [src/validators/po.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/validators/po.ts)\n- [src/validators/registry.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/validators/registry.ts)\n- [src/validators/supply_chain.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/validators/supply_chain.ts)\n- [src/validators/trade.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/validators/trade.ts)\n- [src/validators/content_flywheel.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/validators/content_flywheel.ts)\n</details>\n\n# 业务验证器\n\n## 概述\n\n业务验证器（Business Validators）是 mova-flat-runner 系统中用于在合同执行流程中对输入数据进行业务规则校验的组件。验证器在合同步骤执行后被调用，确保输入数据满足特定业务场景的约束条件，并在验证失败时提供明确的错误信息和原因。\n\n验证器采用**声明式注册 + 函数式校验**的架构模式，每个验证器都是一个独立模块，包含唯一标识符（`id`）和校验函数（`fn`），通过统一的注册表（Registry）进行管理和调度。\n\n资料来源：[src/validators/supply_chain.ts:3-4]()\n\n## 架构设计\n\n### 组件关系图\n\n```mermaid\ngraph TD\n    subgraph \"验证器模块层\"\n        AML[AML 验证器<br/>src/validators/aml.ts]\n        CREDIT[Credit 验证器<br/>src/validators/credit.ts]\n        SUPPLY[供应链验证器<br/>src/validators/supply_chain.ts]\n        INVOICE[发票验证器<br/>src/validators/invoice.ts]\n        COMPLAINT[投诉验证器<br/>src/validators/complaint.ts]\n        CHURN[流失验证器<br/>src/validators/churn.ts]\n        TRADE[贸易验证器<br/>src/validators/trade.ts]\n        COMPLIANCE[合规验证器<br/>src/validators/compliance.ts]\n        CONTRACT_GEN[合同生成验证器<br/>src/validators/contract_gen.ts]\n        PO[采购订单验证器<br/>src/validators/po.ts]\n        FLYWHEEL[内容飞轮验证器<br/>src/validators/content_flywheel.ts]\n    end\n\n    subgraph \"注册表层\"\n        REGISTRY[ValidatorRegistry<br/>src/validators/registry.ts]\n    end\n\n    subgraph \"执行层\"\n        REMOTE_API[remote_api.ts<br/>movaRunStepsRemote]\n        LOCAL_SEAM[local_seam_bridge.ts<br/>本地执行桥接]\n    end\n\n    AML --> REGISTRY\n    CREDIT --> REGISTRY\n    SUPPLY --> REGISTRY\n    INVOICE --> REGISTRY\n    COMPLAINT --> REGISTRY\n    CHURN --> REGISTRY\n    TRADE --> REGISTRY\n    COMPLIANCE --> REGISTRY\n    CONTRACT_GEN --> REGISTRY\n    PO --> REGISTRY\n    FLYWHEEL --> REGISTRY\n\n    REGISTRY --> REMOTE_API\n    REGISTRY --> LOCAL_SEAM\n```\n\n### 核心类型定义\n\n验证器的类型签名为 `ValidatorFn`，定义如下：\n\n```typescript\nexport type ValidatorFn = (inputs: Record<string, unknown>) => {\n  ok: boolean;\n  value: Record<string, unknown>;\n  step_id: string;\n};\n```\n\n资料来源：[src/validators/supply_chain.ts:1]()\n\n每个验证器返回的结构包含三个字段：\n\n| 字段 | 类型 | 说明 |\n|------|------|------|\n| `ok` | `boolean` | 验证是否通过 |\n| `value` | `Record<string, unknown>` | 验证结果详情，包含计算出的业务指标 |\n| `step_id` | `string` | 关联的步骤标识符 |\n\n## 验证器注册表\n\n### 注册表结构\n\n`src/validators/registry.ts` 负责聚合所有验证器并提供统一的查询接口。注册表采用 `Map<string, ValidatorFn>` 结构，以验证器 ID 为键存储校验函数。\n\n```typescript\nexport const VALIDATOR_REGISTRY = new Map<string, ValidatorFn>();\n\n// 注册供应链验证器\nVALIDATOR_REGISTRY.set(\"supply_chain.validate_inputs_v0\", validateInputs);\n\n// 注册信用卡验证器  \nVALIDATOR_REGISTRY.set(\"credit.validate_calcs_v0\", validateCalcs);\n```\n\n### 注册流程\n\n```mermaid\nsequenceDiagram\n    participant Registry as registry.ts\n    participant Validator as 各验证器模块\n    participant Caller as 调用方<br/>remote_api / local_seam_bridge\n    \n    Validator->>Registry: 导出 { id, fn } 数组\n    Registry->>Registry: VALIDATOR_REGISTRY.set(id, fn)\n    \n    Caller->>Registry: VALIDATOR_REGISTRY.get(validator_id)\n    Registry-->>Caller: ValidatorFn | undefined\n```\n\n## 内置验证器一览\n\n### 验证器清单\n\n| 验证器 ID | 模块文件 | 校验目标 | 主要检查项 |\n|-----------|----------|----------|------------|\n| `aml.validate_kyc_v0` | aml.ts | KYC 反洗钱检查 | 客户身份、风险等级、制裁名单 |\n| `churn.validate_inputs_v0` | churn.ts | 流失预测输入 | 用户数据完整性 |\n| `complaint.validate_inputs_v0` | complaint.ts | 投诉处理输入 | 投诉内容、类别、优先级 |\n| `compliance.validate_v1` | compliance.ts | 合规性校验 | 监管要求符合度 |\n| `contract_gen.validate_template_v0` | contract_gen.ts | 合同模板校验 | 模板参数完整性 |\n| `credit.validate_calcs_v0` | credit.ts | 信贷计算校验 | 月收入、债务、征信评分、请求金额 |\n| `invoice.validate_fields_v0` | invoice.ts | 发票字段校验 | 发票号码、金额、日期、税率 |\n| `po.validate_po_v0` | po.ts | 采购订单校验 | PO 编号、金额、供应商信息 |\n| `supply_chain.validate_inputs_v0` | supply_chain.ts | 供应链输入校验 | 供应商 ID、名称、国家代码 |\n| `trade.validate_trade_v0` | trade.ts | 贸易交易校验 | 交易金额、方向、对手方 |\n| `content_flywheel.validate_context_v0` | content_flywheel.ts | 内容飞轮上下文 | 上下文数据完整性 |\n\n### 供应链验证器详解\n\n供应链验证器 (`supply_chain.validate_inputs_v0`) 是验证器模式的典型实现：\n\n```typescript\nexport const supplyChainValidators: Array<{ id: string; fn: ValidatorFn }> = [\n  {\n    id: \"supply_chain.validate_inputs_v0\",\n    fn: (inputs) => {\n      const suppliers = Array.isArray(inputs.suppliers) \n        ? inputs.suppliers as Record<string, unknown>[] \n        : [];\n      \n      const non_empty = suppliers.length > 0;\n      \n      const valid_items = suppliers.filter(s =>\n        s &&\n        typeof s === \"object\" &&\n        String(s[\"id\"]      || \"\").length > 0 &&\n        String(s[\"name\"]    || \"\").length > 0 &&\n        /^[A-Z]{2}$/.test(String(s[\"country\"] || \"\"))\n      );\n      \n      const invalid_count = suppliers.length - valid_items.length;\n      \n      return {\n        ok: true,\n        value: {\n          inputs_valid: non_empty && invalid_count === 0,\n          supplier_count: suppliers.length,\n          valid_supplier_count: valid_items.length,\n          invalid_supplier_count: invalid_count,\n          has_suppliers: non_empty,\n        },\n        step_id: \"validate_inputs\",\n      };\n    },\n  },\n];\n```\n\n**校验规则：**\n- `suppliers` 数组必须非空\n- 每个供应商必须包含 `id`（非空字符串）\n- 每个供应商必须包含 `name`（非空字符串）\n- 每个供应商必须包含 `country`（两位大写字母国家代码，如 `CN`、`US`）\n\n资料来源：[src/validators/supply_chain.ts:3-36]()\n\n### 信贷验证器详解\n\n信贷验证器 (`credit.validate_calcs_v0`) 实现了复杂的信用评估计算：\n\n```typescript\nexport const creditValidators = [\n  {\n    id: \"credit.validate_calcs_v0\",\n    fn: (inputs) => {\n      const income    = Number(inputs.monthly_income) || 0;\n      const debt      = Number(inputs.total_debt) || 0;\n      const bureau    = Number(inputs.bureau_score) || 0;\n      const requested = Number(inputs.requested_amount) || 0;\n      \n      const income_ok    = income > 0;\n      const bureau_ok    = bureau >= 300 && bureau <= 850;\n      const requested_ok = requested > 0;\n      \n      const dti = income_ok ? debt / (income * 12) : null;\n      \n      const hard_reject = bureau < 500 || (dti !== null && dti > 0.6);\n      \n      return {\n        ok: true,\n        value: {\n          calcs_valid: income_ok && bureau_ok && requested_ok,\n          monthly_income: income,\n          total_debt: debt,\n          bureau_score: bureau,\n          requested_amount: requested,\n          debt_to_income_ratio: dti,\n          hard_reject,\n          hard_reject_reason: hard_reject\n            ? (bureau < 500 ? \"bureau_score_below_500\" : \"dti_exceeds_60pct\")\n            : null,\n        },\n        step_id: \"validate_calcs\",\n      };\n    },\n  },\n];\n```\n\n**校验规则与计算：**\n\n| 检查项 | 规则 | 字段 |\n|--------|------|------|\n| 月收入 | 必须大于 0 | `income_ok` |\n| 征信评分 | 必须在 300-850 范围内 | `bureau_ok` |\n| 请求金额 | 必须大于 0 | `requested_ok` |\n| 债务收入比 (DTI) | 月债务 / (月收入 × 12) | `debt_to_income_ratio` |\n| 硬性拒绝 | 评分<500 或 DTI>60% | `hard_reject` |\n\n资料来源：[src/validators/credit.ts:3-47]()\n\n## 验证器执行流程\n\n### 远程 API 执行路径\n\n在 `remote_api.ts` 的 `movaRunStepsRemote` 函数中，验证器在 `analyze` 步骤完成后被调用：\n\n```mermaid\nsequenceDiagram\n    participant Client as MCP Client\n    participant API as MOVA API\n    participant Runner as movaRunStepsRemote\n    participant Registry as VALIDATOR_REGISTRY\n    \n    Client->>Runner: movaRunStepsRemote(contractId, validators, initialInputs)\n    Runner->>API: POST /api/v1/contracts/{id}/step (analyze)\n    \n    Note over Runner: 获取 analyze 步骤输出\n    \n    loop 每个验证器\n        Runner->>Registry: VALIDATOR_REGISTRY.get(validator.validator_id)\n        \n        alt 验证器存在\n            Registry-->>Runner: ValidatorFn\n            Runner->>Runner: fn(validatorContext)\n            Note over Runner: validatorContext = {...initialInputs, ...analysis}\n            \n            alt 验证成功\n                Runner->>Runner: Object.assign(analysis, resultValue.value)\n            else 验证失败\n                Runner->>Runner: analysis[\"{step_id}_error\"] = \"VALIDATOR_FAILED: {error}\"\n            end\n        else 验证器不存在\n            Runner->>Runner: analysis[\"{step_id}_error\"] = \"VALIDATOR_NOT_ALLOWED: ...\"\n        end\n    end\n    \n    Runner-->>Client: 返回包含 analysis 的结果\n```\n\n**关键代码片段：**\n\n```typescript\nconst validatorContext = { ...initialInputs, ...analysis };\n\nfor (const validator of validators) {\n  const fn = VALIDATOR_REGISTRY.get(validator.validator_id);\n  if (!fn) {\n    analysis[`${validator.step_id}_error`] = `VALIDATOR_NOT_ALLOWED: \"${validator.validator_id}\" not in registry`;\n    continue;\n  }\n  try {\n    const resultValue = fn(validatorContext);\n    Object.assign(analysis, resultValue.value ?? {});\n  } catch (error) {\n    analysis[`${validator.step_id}_error`] = `VALIDATOR_FAILED: ${String(error)}`;\n  }\n}\n```\n\n资料来源：[dist-test/src/transports/remote_api.js:1-30]()\n\n### 安全校验：步骤模式守卫\n\n验证器系统还包含安全校验机制 `step_mode_guard.ts`，确保步骤定义的一致性：\n\n```typescript\nexport function findStepModeViolations(flow: unknown): StepModeViolation[] {\n  const out: StepModeViolation[] = [];\n  \n  // 检查 AI_ATOMIC 步骤是否声明了 model 字段\n  if (mode === \"AI_ATOMIC\" && asStr(step.model) === null) {\n    out.push({\n      kind: \"ai_atomic_without_model\",\n      step_id: id,\n      execution_mode: mode,\n      message: `step '${id ?? \"?\"}' is AI_ATOMIC but has no 'model' field`,\n    });\n  }\n  \n  // 检查 CONTRACT_CALL 步骤是否声明了 contract_id\n  if (mode === \"CONTRACT_CALL\" && asStr(step.contract_id) === null) {\n    out.push({\n      kind: \"contract_call_without_contract_id\",\n      step_id: id,\n      execution_mode: mode,\n      message: `step '${id ?? \"?\"}' is CONTRACT_CALL but has no 'contract_id'`,\n    });\n  }\n  \n  // 检查 HUMAN_GATE 步骤是否声明了 decision_options\n  if (mode === \"HUMAN_GATE\" && !Array.isArray(step.decision_options)) {\n    out.push({\n      kind: \"human_gate_without_decisions\",\n      step_id: id,\n      execution_mode: mode,\n      message: `step '${id ?? \"?\"}' is HUMAN_GATE but has no 'decision_options' array`,\n    });\n  }\n  \n  return out;\n}\n```\n\n**模式违规类型：**\n\n| 违规类型 | 模式 | 期望字段 | 说明 |\n|----------|------|----------|------|\n| `deterministic_with_model` | DETERMINISTIC | 无 | DET 步骤不应声明 model |\n| `ai_atomic_without_model` | AI_ATOMIC | `model` | AI 步骤必须指定模型 |\n| `contract_call_without_contract_id` | CONTRACT_CALL | `contract_id` | 合约调用必须指定合约 ID |\n| `human_gate_without_decisions` | HUMAN_GATE | `decision_options` | 人工审批必须提供选项 |\n\n资料来源：[src/security/step_mode_guard.ts:1-70]()\n\n## 自定义验证器扩展\n\n### 创建新验证器步骤\n\n1. **定义验证器函数**\n\n```typescript\nimport type { ValidatorFn } from \"../types.js\";\n\nexport const customValidators: Array<{ id: string; fn: ValidatorFn }> = [\n  {\n    id: \"custom.validate_business_rule_v0\",\n    fn: (inputs) => {\n      // 业务校验逻辑\n      const isValid = /* 校验条件 */;\n      \n      return {\n        ok: true,\n        value: {\n          rule_valid: isValid,\n          // ... 其他业务指标\n        },\n        step_id: \"validate_business_rule\",\n      };\n    },\n  },\n];\n```\n\n2. **注册到注册表**\n\n在 `registry.ts` 中添加：\n\n```typescript\nimport { customValidators } from \"./custom.js\";\n\nfor (const { id, fn } of customValidators) {\n  VALIDATOR_REGISTRY.set(id, fn);\n}\n```\n\n3. **在合同清单中引用**\n\n```typescript\nexport const CONTRACT_MANIFESTS: Record<string, ContractManifest> = {\n  my_contract: {\n    contract_type: \"my_contract\",\n    validators: [\"custom.validate_business_rule_v0\"],\n    // ...\n  },\n};\n```\n\n## 验证结果处理\n\n### 成功路径\n\n验证成功时，结果被合并到 `analysis` 上下文中：\n\n```typescript\nconst resultValue = fn(validatorContext);\nObject.assign(analysis, resultValue.value ?? {});\n```\n\n后续步骤可以直接使用验证器计算出的业务指标。\n\n### 失败路径\n\n验证器执行失败时，会在 `analysis` 中记录错误：\n\n```typescript\n// 验证器函数抛出异常\nanalysis[`${validator.step_id}_error`] = `VALIDATOR_FAILED: ${String(error)}`;\n\n// 验证器未在注册表中注册\nanalysis[`${validator.step_id}_error`] = `VALIDATOR_NOT_ALLOWED: \"${validator.validator_id}\" not in registry`;\n```\n\n错误信息以 `{step_id}_error` 格式存储，便于追踪具体失败的验证步骤。\n\n## 最佳实践\n\n1. **幂等性**：验证器应设计为幂等函数，相同输入产生相同输出\n2. **无副作用**：验证器不应修改输入数据或产生外部影响\n3. **错误处理**：使用 try-catch 包裹验证逻辑，防止异常导致流程中断\n4. **返回完整上下文**：始终返回 `step_id` 字段，便于调试和追踪\n5. **类型安全**：使用 TypeScript 显式声明输入输出类型\n\n## 总结\n\n业务验证器是 mova-flat-runner 实现业务规则强制执行的核心机制。通过声明式的验证器注册和函数式的校验实现，系统能够在合同执行的各个阶段对输入数据进行可靠的业务规则校验，同时保持代码的可扩展性和可维护性。\n\n---\n\n<a id='page-deployment'></a>\n\n## 部署与运维\n\n### 相关页面\n\n相关主题：[安装与配置](#page-installation), [系统架构](#page-system-architecture)\n\n<details>\n<summary>相关源码文件</summary>\n\n以下源码文件用于生成本页说明：\n\n- [package.json](https://github.com/mova-compact/mova-flat-runner/blob/main/package.json)\n- [README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n- [src/index.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/index.ts)\n- [src/transports/local_seam_bridge.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/local_seam_bridge.ts)\n- [Makefile](https://github.com/mova-compact/mova-flat-runner/blob/main/Makefile)\n</details>\n\n# 部署与运维\n\n## 概述\n\nmova-flat-runner 是 MOVA 平台的 MCP（Model Context Protocol）服务器实现，提供受治理的 AI 工作流执行能力。该项目支持发票 OCR、AML 筛查、信用审查等业务流程，并可通过人类审批门（Human Approval Gates）实现人工介入，同时提供完整的审计追踪功能。\n\n本页面详细说明 mova-flat-runner 的部署模式、环境配置、运维命令以及运行时行为，帮助运维人员和开发者在不同环境中正确部署和监控该服务。\n\n---\n\n## 部署架构\n\n### MCP 服务器角色定位\n\nmova-flat-runner 在 MOVA 生态系统中充当 MCP Registry 的服务提供方，为 AI 客户端（如 Claude Desktop、Cursor、Codex）提供标准化的工具调用接口。客户端通过 MCP 协议与服务器通信，服务器再将请求转发至后端 MOVA API 进行实际业务处理。\n\n```mermaid\ngraph TD\n    A[\"👤 AI 客户端<br/>(Claude Desktop / Codex)\"] -->|\"MCP Protocol\"| B[\"mova-flat-runner<br/>(mova-mcp)\"]\n    B -->|\"HTTP REST API\"| C[\"MOVA API<br/>(api.mova-lab.eu)\"]\n    C -->|\"业务执行\"| D[\"后端服务集群\"]\n    \n    B -->|\"本地执行模式\"| E[\"Local Seam Bridge\"]\n    E -->|\"本地工作流\"| F[\"本地合约执行\"]\n    \n    style B fill:#4a90d9,color:#fff\n    style C fill:#67b868,color:#fff\n```\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n### 双执行模式\n\nmova-flat-runner 支持两种执行模式，根据配置自动选择：\n\n| 模式 | 触发条件 | 行为描述 |\n|------|----------|----------|\n| **远程 API 模式** | `MOVA_API_URL` 已配置且可达 | 通过 HTTP 调用 `api.mova-lab.eu` 后端 API |\n| **本地 HTTP 模式** | `MOVA_HTTP_PORT` 已配置 | 启动本地 HTTP 服务器，接收本地工作流请求 |\n\n资料来源：[src/index.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/index.ts)\n\n---\n\n## 环境变量配置\n\n### 必填环境变量\n\n以下环境变量必须在部署时配置，否则服务无法正常启动：\n\n| 变量名 | 说明 | 示例值 | 来源 |\n|--------|------|--------|------|\n| `MOVA_API_URL` | MOVA 后端 API 基础地址 | `https://api.mova-lab.eu` | README.md |\n| `MOVA_API_KEY` | 后端 API 认证密钥 | `__SET_MOVA_API_KEY__` | README.md |\n| `LLM_KEY` | LLM 提供商密钥 | `__SET_LLM_KEY__` | README.md |\n| `LLM_MODEL` | 使用的 LLM 模型标识 | `openai/gpt-4o-mini` | README.md |\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n### 可选本地 HTTP 模式变量\n\n当需要启用本地 HTTP 模式时，配置以下变量：\n\n| 变量名 | 说明 | 默认值 | 备注 |\n|--------|------|--------|------|\n| `MOVA_API_TIMEOUT_MS` | API 请求超时时间（毫秒） | `30000` | 可选配置 |\n| `MOVA_HTTP_PORT` | 本地 HTTP 服务监听端口 | `3796` | 设置后启用本地模式 |\n| `MOVA_INVOKE_TOKEN` | 本地调用认证令牌 | 无 | 用于保护本地 API 调用 |\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n### 本地沙箱环境变量\n\n在本地执行模式下，以下变量控制工作流和项目路径：\n\n| 变量名 | 说明 | 默认值 |\n|--------|------|--------|\n| `MOVA_SANDBOX_PACKAGE_PATH` | 合约包目录路径 | `D:\\Projects_MOVA\\mova-intent\\contracts\\dockerfile-nodejs-v1` |\n| `MOVA_SANDBOX_PROJECT_PATH` | 项目工作目录路径 | 空（必填） |\n\n资料来源：[src/transports/local_seam_bridge.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/transports/local_seam_bridge.ts)\n\n---\n\n## 构建与打包\n\n### npm 构建流程\n\n项目使用 TypeScript 开发，通过 npm 脚本完成构建：\n\n```bash\nnpm run build\n```\n\n构建过程执行以下步骤：\n\n1. **TypeScript 编译**：调用 `tsc` 将 `src/` 目录下的 TypeScript 源文件编译为 JavaScript\n2. **Shebang 注入**：在 `dist/index.js` 头部添加 `#!/usr/bin/env node` 使其可执行\n3. **权限设置**：通过 `fs.chmodSync(p, 0o755)` 设置可执行权限\n\n资料来源：[package.json](https://github.com/mova-compact/mova-flat-runner/blob/main/package.json)\n\n### Makefile 便捷命令\n\n项目提供 Makefile 封装常用运维命令：\n\n| 命令 | 功能 | 资料来源 |\n|------|------|----------|\n| `make publisher` | 构建 MCP 发布工具 | README.md |\n| `make check` | 运行代码检查、单元测试和集成测试 | README.md |\n| `make help` | 显示所有可用命令 | README.md |\n\n```bash\n# 构建发布工具\nmake publisher\n\n# 运行完整检查\nmake check\n```\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n---\n\n## 安装与启动\n\n### npm 包方式（推荐）\n\n通过 npx 直接运行，无需全局安装：\n\n```bash\nnpx -y @leryk1981/mova-flat-runner@3.3.3\n```\n\n### 二进制直接运行\n\n构建后可直接运行二进制文件：\n\n```bash\n./bin/mcp-publisher --help\n```\n\n### MCP 服务器启动\n\nmova-flat-runner 作为 MCP 服务器运行，支持通过 MCP 协议与 AI 客户端集成。启动时必须正确配置环境变量：\n\n```bash\nexport MOVA_API_URL=https://api.mova-lab.eu\nexport MOVA_API_KEY=__SET_MOVA_API_KEY__\nexport LLM_KEY=__SET_LLM_KEY__\nexport LLM_MODEL=openai/gpt-4o-mini\n\n./dist/index.js\n```\n\n资料来源：[package.json](https://github.com/mova-compact/mova-flat-runner/blob/main/package.json)\n\n---\n\n## 客户端配置示例\n\n### Claude Desktop 配置\n\n在 Claude Desktop 的配置文件 `claude_desktop_config.json` 中添加以下内容：\n\n```json\n{\n  \"mcpServers\": {\n    \"mova\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@leryk1981/mova-flat-runner@3.3.3\"],\n      \"env\": {\n        \"MOVA_API_URL\": \"https://api.mova-lab.eu\",\n        \"MOVA_API_KEY\": \"__SET_MOVA_API_KEY__\",\n        \"LLM_KEY\": \"__SET_LLM_KEY__\",\n        \"LLM_MODEL\": \"openai/gpt-4o-mini\"\n      }\n    }\n  }\n}\n```\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n### Codex 配置（TOML 格式）\n\n```toml\n[mcp_servers.mova]\ncommand = \"npx\"\nargs = [\"-y\", \"@leryk1981/mova-flat-runner@3.3.3\"]\nstartup_timeout_sec = 90.0\n\n[mcp_servers.mova.env]\nMOVA_API_URL = \"https://api.mova-lab.eu\"\nMOVA_API_KEY = \"__SET_MOVA_API_KEY__\"\nLLM_KEY = \"__SET_LLM_KEY__\"\nLLM_MODEL = \"openai/gpt-4o-mini\"\n```\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n---\n\n## 健康检查\n\n### API 健康检查端点\n\nMOVA API 提供健康检查接口，可用于监控服务可用性：\n\n```bash\ncurl -sS https://api.mova-lab.eu/health\n```\n\n返回状态码 `200 OK` 表示服务正常运行。\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n---\n\n## 可用工具列表\n\nmova-flat-runner 通过 MCP 协议暴露以下工具，供 AI 客户端调用：\n\n| 工具名称 | 功能描述 | 资料来源 |\n|----------|----------|----------|\n| `mova_health` | 查询 MOVA API 健康状态 | README.md |\n| `mova_registry` | 查询可用合约注册表 | README.md |\n| `mova_run` | 执行内置合约工作流 | README.md |\n| `mova_query` | 查询合约运行状态和审计信息 | README.md |\n| `mova_decide` | 提交决策响应（用于人工审批门） | README.md |\n| `mova_connector` | 连接外部系统 | README.md |\n| `mova_contract` | 注册和管理自定义合约 | README.md |\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n---\n\n## 安全注意事项\n\n### 敏感信息保护\n\n⚠️ **重要提醒**：以下环境变量包含敏感凭证，**禁止**提交至版本控制系统：\n\n| 敏感变量 | 说明 |\n|----------|------|\n| `MOVA_API_KEY` | MOVA 后端 API 认证密钥 |\n| `LLM_KEY` | LLM 服务提供商密钥 |\n| `MOVA_INVOKE_TOKEN` | 本地调用认证令牌 |\n\n部署时应使用环境变量注入或密钥管理服务（如 AWS Secrets Manager、HashiCorp Vault）进行配置。\n\n资料来源：[README.md](https://github.com/mova-compact/mova-flat-runner/blob/main/README.md)\n\n### 安全验证机制\n\nmova-flat-runner 内置安全检查机制：\n\n| 检查项 | 说明 | 资料来源 |\n|--------|------|----------|\n| **Step Mode 验证** | 验证步骤执行模式与字段定义的一致性 | src/security/step_mode_guard.ts |\n| **HUMAN_GATE 保护** | 防止通过通用 step_complete 操作跳过人工审批门 | src/index.ts |\n\n```typescript\n// HUMAN_GATE 安全检查示例\nconst gateGuard = await assertNotHumanGate(config, runId, stepId, requestId);\nif (gateGuard) return gateGuard;\n```\n\n资料来源：[src/index.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/index.ts)\n\n---\n\n## 自定义合约桥接机制\n\n### 问题背景\n\n对于非内置合约（custom contracts），其 ID 格式为 `local-*` 或 `remote-*`，存在 API 命名空间不一致问题：\n\n- `mova_contract register/run` 使用 `/run/*` 命名空间\n- `mova_query status/audit` 使用 `/api/v1/contracts/*` 命名空间\n\n### 桥接解决方案\n\n系统通过内存中的桥接映射表（`CUSTOM_RUN_BRIDGE`）维护 `contract_id → run_id` 映射：\n\n```mermaid\ngraph LR\n    A[\"mova_contract run\"] -->|\"创建运行\"| B[\"CUSTOM_RUN_BRIDGE<br/>Map<contractId, runId>\"]\n    B -->|\"查询状态\"| C[\"mova_query status\"]\n    C -->|\"404 时探测\"| D[\"/api/v1/contracts/my\"]\n    D -->|\"返回桥接状态\"| C\n```\n\n资料来源：[src/index.ts](https://github.com/mova-compact/mova-flat-runner/blob/main/src/index.ts)\n\n---\n\n## 运维监控清单\n\n### 部署前检查项\n\n| 检查项 | 操作 |\n|--------|------|\n| ✅ 环境变量完整性 | 确认 `MOVA_API_KEY`、`LLM_KEY` 已正确配置 |\n| ✅ API 连通性 | 执行 `curl https://api.mova-lab.eu/health` 验证 |\n| ✅ 构建产物存在 | 确认 `dist/index.js` 已生成 |\n| ✅ 权限设置 | 确认二进制文件具有执行权限 |\n\n### 运行时监控指标\n\n| 指标 | 监控方式 |\n|------|----------|\n| API 响应时间 | 通过 `MOVA_API_TIMEOUT_MS` 配置超时阈值 |\n| 认证失败 | 监控 API 返回的 401/403 错误 |\n| 业务逻辑异常 | 监控 `step_complete`、`gate_approve` 返回的错误码 |\n\n### 常见问题排查\n\n| 症状 | 可能原因 | 解决方案 |\n|------|----------|----------|\n| `Unknown contract_type` | 使用了非内置合约 | 改用 `mova_contract action=run` |\n| `MOVA API 404` | 自定义合约在查询命名空间不存在 | 系统已内置桥接机制，查询 `mova_query status` |\n| 人工审批门被跳过 | 误用 `step_complete` 尝试完成 HUMAN_GATE | 使用 `gate_approve` 或 `gate_reject` |\n\n资料来源：[tasks/task061.md](https://github.com/mova-compact/mova-flat-runner/blob/main/tasks/task061.md)\n\n---\n\n## 版本信息\n\n| 属性 | 值 |\n|------|-----|\n| npm 包名 | `@leryk1981/mova-flat-runner` |\n| 当前版本 | `3.3.4` |\n| MCP 名称 | `io.github.mova-compact/mova-flat-runner` |\n| 构建目标 | `dist/index.js` |\n| 二进制入口 | `mova-mcp` |\n\n资料来源：[package.json](https://github.com/mova-compact/mova-flat-runner/blob/main/package.json)\n\n---\n\n---\n\n## Doramagic 踩坑日志\n\n项目：mova-compact/mova-flat-runner\n\n摘要：发现 8 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：配置坑 - 可能修改宿主 AI 配置。\n\n## 1. 配置坑 · 可能修改宿主 AI 配置\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：项目面向 Claude/Cursor/Codex/Gemini/OpenCode 等宿主，或安装命令涉及用户配置目录。\n- 对用户的影响：安装可能改变本机 AI 工具行为，用户需要知道写入位置和回滚方法。\n- 建议检查：列出会写入的配置文件、目录和卸载/回滚步骤。\n- 防护动作：涉及宿主配置目录时必须给回滚路径，不能只给安装命令。\n- 证据：capability.host_targets | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | host_targets=mcp_host, claude, chatgpt\n\n## 2. 配置坑 · 来源证据：v3.0.0 — Step Enforcement Runtime\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：GitHub 社区证据显示该项目存在一个配置相关的待验证问题：v3.0.0 — Step Enforcement Runtime\n- 对用户的影响：可能影响升级、迁移或版本选择。\n- 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。\n- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。\n- 证据：community_evidence:github | cevd_10b68dae59184a36b21a563722829aed | https://github.com/mova-compact/mova-flat-runner/releases/tag/v3.0.0 | 来源类型 github_release 暴露的待验证使用条件。\n\n## 3. 能力坑 · 能力判断依赖假设\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：README/documentation is current enough for a first validation pass.\n- 对用户的影响：假设不成立时，用户拿不到承诺的能力。\n- 建议检查：将假设转成下游验证清单。\n- 防护动作：假设必须转成验证项；没有验证结果前不能写成事实。\n- 证据：capability.assumptions | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | README/documentation is current enough for a first validation pass.\n\n## 4. 维护坑 · 维护活跃度未知\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：未记录 last_activity_observed。\n- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。\n- 建议检查：补 GitHub 最近 commit、release、issue/PR 响应信号。\n- 防护动作：维护活跃度未知时，推荐强度不能标为高信任。\n- 证据：evidence.maintainer_signals | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | last_activity_observed missing\n\n## 5. 安全/权限坑 · 下游验证发现风险项\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：no_demo\n- 对用户的影响：下游已经要求复核，不能在页面中弱化。\n- 建议检查：进入安全/权限治理复核队列。\n- 防护动作：下游风险存在时必须保持 review/recommendation 降级。\n- 证据：downstream_validation.risk_items | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | no_demo; severity=medium\n\n## 6. 安全/权限坑 · 存在评分风险\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：no_demo\n- 对用户的影响：风险会影响是否适合普通用户安装。\n- 建议检查：把风险写入边界卡，并确认是否需要人工复核。\n- 防护动作：评分风险必须进入边界卡，不能只作为内部分数。\n- 证据：risks.scoring_risks | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | no_demo; severity=medium\n\n## 7. 维护坑 · issue/PR 响应质量未知\n\n- 严重度：low\n- 证据强度：source_linked\n- 发现：issue_or_pr_quality=unknown。\n- 对用户的影响：用户无法判断遇到问题后是否有人维护。\n- 建议检查：抽样最近 issue/PR，判断是否长期无人处理。\n- 防护动作：issue/PR 响应未知时，必须提示维护风险。\n- 证据：evidence.maintainer_signals | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | issue_or_pr_quality=unknown\n\n## 8. 维护坑 · 发布节奏不明确\n\n- 严重度：low\n- 证据强度：source_linked\n- 发现：release_recency=unknown。\n- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。\n- 建议检查：确认最近 release/tag 和 README 安装命令是否一致。\n- 防护动作：发布节奏未知或过期时，安装说明必须标注可能漂移。\n- 证据：evidence.maintainer_signals | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | release_recency=unknown\n\n<!-- canonical_name: mova-compact/mova-flat-runner; human_manual_source: deepwiki_human_wiki -->\n",
      "summary": "DeepWiki/Human Wiki 完整输出，末尾追加 Discovery Agent 踩坑日志。",
      "title": "Human Manual / 人类版说明书"
    },
    "pitfall_log": {
      "asset_id": "pitfall_log",
      "filename": "PITFALL_LOG.md",
      "markdown": "# Pitfall Log / 踩坑日志\n\n项目：mova-compact/mova-flat-runner\n\n摘要：发现 8 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：配置坑 - 可能修改宿主 AI 配置。\n\n## 1. 配置坑 · 可能修改宿主 AI 配置\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：项目面向 Claude/Cursor/Codex/Gemini/OpenCode 等宿主，或安装命令涉及用户配置目录。\n- 对用户的影响：安装可能改变本机 AI 工具行为，用户需要知道写入位置和回滚方法。\n- 建议检查：列出会写入的配置文件、目录和卸载/回滚步骤。\n- 防护动作：涉及宿主配置目录时必须给回滚路径，不能只给安装命令。\n- 证据：capability.host_targets | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | host_targets=mcp_host, claude, chatgpt\n\n## 2. 配置坑 · 来源证据：v3.0.0 — Step Enforcement Runtime\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：GitHub 社区证据显示该项目存在一个配置相关的待验证问题：v3.0.0 — Step Enforcement Runtime\n- 对用户的影响：可能影响升级、迁移或版本选择。\n- 建议检查：来源显示可能已有修复、规避或版本变化，说明书中必须标注适用版本。\n- 防护动作：不得脱离来源链接放大为确定性结论；需要标注适用版本和复核状态。\n- 证据：community_evidence:github | cevd_10b68dae59184a36b21a563722829aed | https://github.com/mova-compact/mova-flat-runner/releases/tag/v3.0.0 | 来源类型 github_release 暴露的待验证使用条件。\n\n## 3. 能力坑 · 能力判断依赖假设\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：README/documentation is current enough for a first validation pass.\n- 对用户的影响：假设不成立时，用户拿不到承诺的能力。\n- 建议检查：将假设转成下游验证清单。\n- 防护动作：假设必须转成验证项；没有验证结果前不能写成事实。\n- 证据：capability.assumptions | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | README/documentation is current enough for a first validation pass.\n\n## 4. 维护坑 · 维护活跃度未知\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：未记录 last_activity_observed。\n- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。\n- 建议检查：补 GitHub 最近 commit、release、issue/PR 响应信号。\n- 防护动作：维护活跃度未知时，推荐强度不能标为高信任。\n- 证据：evidence.maintainer_signals | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | last_activity_observed missing\n\n## 5. 安全/权限坑 · 下游验证发现风险项\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：no_demo\n- 对用户的影响：下游已经要求复核，不能在页面中弱化。\n- 建议检查：进入安全/权限治理复核队列。\n- 防护动作：下游风险存在时必须保持 review/recommendation 降级。\n- 证据：downstream_validation.risk_items | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | no_demo; severity=medium\n\n## 6. 安全/权限坑 · 存在评分风险\n\n- 严重度：medium\n- 证据强度：source_linked\n- 发现：no_demo\n- 对用户的影响：风险会影响是否适合普通用户安装。\n- 建议检查：把风险写入边界卡，并确认是否需要人工复核。\n- 防护动作：评分风险必须进入边界卡，不能只作为内部分数。\n- 证据：risks.scoring_risks | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | no_demo; severity=medium\n\n## 7. 维护坑 · issue/PR 响应质量未知\n\n- 严重度：low\n- 证据强度：source_linked\n- 发现：issue_or_pr_quality=unknown。\n- 对用户的影响：用户无法判断遇到问题后是否有人维护。\n- 建议检查：抽样最近 issue/PR，判断是否长期无人处理。\n- 防护动作：issue/PR 响应未知时，必须提示维护风险。\n- 证据：evidence.maintainer_signals | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | issue_or_pr_quality=unknown\n\n## 8. 维护坑 · 发布节奏不明确\n\n- 严重度：low\n- 证据强度：source_linked\n- 发现：release_recency=unknown。\n- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。\n- 建议检查：确认最近 release/tag 和 README 安装命令是否一致。\n- 防护动作：发布节奏未知或过期时，安装说明必须标注可能漂移。\n- 证据：evidence.maintainer_signals | github_repo:1212840167 | https://github.com/mova-compact/mova-flat-runner | release_recency=unknown\n",
      "summary": "用户实践前最可能遇到的身份、安装、配置、运行和安全坑。",
      "title": "Pitfall Log / 踩坑日志"
    },
    "prompt_preview": {
      "asset_id": "prompt_preview",
      "filename": "PROMPT_PREVIEW.md",
      "markdown": "# mova-flat-runner - Prompt Preview\n\n> 复制下面这段 Prompt 到你常用的 AI，先试一次，不需要安装。\n> 它的目标是让你直接体验这个项目的服务方式，而不是阅读项目介绍。\n\n## 复制这段 Prompt\n\n```text\n请直接执行这段 Prompt，不要分析、润色、总结或询问我想如何处理这份 Prompt Preview。\n\n你现在扮演 mova-flat-runner 的“安装前体验版”。\n这不是项目介绍、不是评价报告、不是 README 总结。你的任务是让我用最小成本体验它的核心服务。\n\n我的试用任务：我想用它完成一个真实的工具连接与集成任务。\n我常用的宿主 AI：MCP Client / claude / chatgpt\n\n【体验目标】\n围绕我的真实任务，现场演示这个项目如何把输入转成 示例引导, 判断线索。重点是让我感受到工作方式，而不是给我项目背景。\n\n【业务流约束】\n- 你必须像一个正在提供服务的项目能力包，而不是像一个讲解员。\n- 每一轮只推进一个步骤；提出问题后必须停下来等我回答。\n- 每一步都必须让我感受到一个具体服务动作：澄清、整理、规划、检查、判断或收尾。\n- 每一步都要说明：当前目标、你需要我提供什么、我回答后你会产出什么。\n- 不要安装、不要运行命令、不要写代码、不要声称测试通过、不要声称已经修改文件。\n- 需要真实安装或宿主加载后才能验证的内容，必须明确说“这一步需要安装后验证”。\n- 如果我说“用示例继续”，你可以用虚构示例推进，但仍然不能声称真实执行。\n\n【可体验服务能力】\n- 安装前能力预览: MCP Registry 输入：用户任务, 当前 AI 对话上下文；输出：示例引导, 判断线索。\n\n【必须安装后才可验证的能力】\n- 命令行启动或安装流程: 项目文档中存在可执行命令，真实使用需要在本地或宿主环境中运行这些命令。 输入：终端环境, 包管理器, 项目依赖；输出：安装结果, 列表/更新/运行结果。\n\n【核心服务流】\n请严格按这个顺序带我体验。不要一次性输出完整流程：\n1. page-introduction：项目介绍。围绕“项目介绍”模拟一次用户任务，不展示安装或运行结果。\n2. page-installation：安装与配置。围绕“安装与配置”模拟一次用户任务，不展示安装或运行结果。\n3. page-system-architecture：系统架构。围绕“系统架构”模拟一次用户任务，不展示安装或运行结果。\n4. page-transport-layer：传输层。围绕“传输层”模拟一次用户任务，不展示安装或运行结果。\n5. page-security-module：安全模块。围绕“安全模块”模拟一次用户任务，不展示安装或运行结果。\n\n【核心能力体验剧本】\n每一步都必须按“输入 -> 服务动作 -> 中间产物”执行。不要只说流程名：\n1. page-introduction\n输入：用户提供的“项目介绍”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n2. page-installation\n输入：用户提供的“安装与配置”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n3. page-system-architecture\n输入：用户提供的“系统架构”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n4. page-transport-layer\n输入：用户提供的“传输层”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n5. page-security-module\n输入：用户提供的“安全模块”相关信息。\n服务动作：模拟项目在这一步的核心判断和整理方式。\n中间产物：一个可检查的小结果。\n\n【项目服务规则】\n这些规则决定你如何服务用户。不要解释规则本身，而要在每一步执行时遵守：\n- 先确认用户任务、输入材料和成功标准，再模拟项目能力。\n- 每一步都必须形成可检查的小产物，并等待用户确认后再继续。\n- 凡是需要安装、调用工具或访问外部服务的能力，都必须标记为安装后验证。\n\n【每一步的服务约束】\n- Step 1 / page-introduction：Step 1 必须围绕“项目介绍”形成一个小中间产物，并等待用户确认。\n- Step 2 / page-installation：Step 2 必须围绕“安装与配置”形成一个小中间产物，并等待用户确认。\n- Step 3 / page-system-architecture：Step 3 必须围绕“系统架构”形成一个小中间产物，并等待用户确认。\n- Step 4 / page-transport-layer：Step 4 必须围绕“传输层”形成一个小中间产物，并等待用户确认。\n- Step 5 / page-security-module：Step 5 必须围绕“安全模块”形成一个小中间产物，并等待用户确认。\n\n【边界与风险】\n- 不要声称已经安装、运行、调用 API、读写本地文件或完成真实任务。\n- 安装前预览只能展示工作方式，不能证明兼容性、性能或输出质量。\n- 涉及安装、插件加载、工具调用或外部服务的能力必须安装后验证。\n\n【可追溯依据】\n这些路径只用于你内部校验或在我追问“依据是什么”时简要引用。不要在首次回复主动展开：\n- https://github.com/mova-compact/mova-flat-runner\n- https://github.com/mova-compact/mova-flat-runner#readme\n- README.md\n- package.json\n- smithery.yaml\n- server.json\n- src/index.ts\n- src/client.ts\n- src/package_support.ts\n- src/types.ts\n- src/schemas.ts\n- src/transports/local_seam_bridge.ts\n\n【首次问题规则】\n- 首次三问必须先确认用户目标、成功标准和边界，不要提前进入工具、安装或实现细节。\n- 如果后续需要技术条件、文件路径或运行环境，必须等用户确认目标后再追问。\n\n首次回复必须只输出下面 4 个部分：\n1. 体验开始：用 1 句话说明你将带我体验 mova-flat-runner 的核心服务。\n2. 当前步骤：明确进入 Step 1，并说明这一步要解决什么。\n3. 你会如何服务我：说明你会先改变我完成任务的哪个动作。\n4. 只问我 3 个问题，然后停下等待回答。\n\n首次回复禁止输出：后续完整流程、证据清单、安装命令、项目评价、营销文案、已经安装或运行的说法。\n\nStep 1 / brainstorming 的二轮协议：\n- 我回答首次三问后，你仍然停留在 Step 1 / brainstorming，不要进入 Step 2。\n- 第二次回复必须产出 6 个部分：澄清后的任务定义、成功标准、边界条件、\n  2-3 个可选方案、每个方案的权衡、推荐方案。\n- 第二次回复最后必须问我是否确认推荐方案；只有我明确确认后，才能进入下一步。\n- 第二次回复禁止输出 git worktree、代码计划、测试文件、命令或真实执行结果。\n\n后续对话规则：\n- 我回答后，你先完成当前步骤的中间产物并等待确认；只有我确认后，才能进入下一步。\n- 每一步都要生成一个小的中间产物，例如澄清后的目标、计划草案、测试意图、验证清单或继续/停止判断。\n- 所有演示都写成“我会建议/我会引导/这一步会形成”，不要写成已经真实执行。\n- 不要声称已经测试通过、文件已修改、命令已运行或结果已产生。\n- 如果某个能力必须安装后验证，请直接说“这一步需要安装后验证”。\n- 如果证据不足，请明确说“证据不足”，不要补事实。\n```\n",
      "summary": "不安装项目也能感受能力节奏的安全试用 Prompt。",
      "title": "Prompt Preview / 安装前试用 Prompt"
    },
    "quick_start": {
      "asset_id": "quick_start",
      "filename": "QUICK_START.md",
      "markdown": "# Quick Start / 官方入口\n\n项目：mova-compact/mova-flat-runner\n\n## 官方安装入口\n\n### Node.js / npx · 官方安装入口\n\n```bash\nnpx -y @leryk1981/mova-flat-runner@3.3.3\n```\n\n来源：https://github.com/mova-compact/mova-flat-runner#readme\n\n## 来源\n\n- repo: https://github.com/mova-compact/mova-flat-runner\n- docs: https://github.com/mova-compact/mova-flat-runner#readme\n",
      "summary": "从项目官方 README 或安装文档提取的开工入口。",
      "title": "Quick Start / 官方入口"
    }
  },
  "validation_id": "dval_b9c2ece545924497a3a7cc01468e2261"
}
