# 扩展分析契约文档(Dev-A/B/C 与测试 agent 对齐基线) > 生成 2026-09-12,方案见 docs/DEPLOY_SKILL.md 同源的扩展分析方案。三个开发分支与本契约对齐,测试 agent 按本契约+计划文档验收。 ## 1. 扩展资产目录布局(服务端存储) ``` {BIOFLOW_DATA}/extensions/{ext_id}/ ├── extension.json # 唯一事实源(schema 见 §2) ├── raw_code/ # 上传 zip 解压的原始代码(含 run.sh 等) ├── raw_test_data/ # 上传的测试数据(可选) ├── converted_code/ # AI 转换后写入的代码(与 raw_code 相同或改写版) ├── validation/ # 试运行/金标/修复循环中间产物 │ ├── trial_{n}.log │ ├── trial_{n}.outputs/ │ └── golden_report.json └── runs/{run_id}/ # 每次正式运行 ├── inputs/ # 运行输入(路径登记或复制的文件) ├── outputs/ # 运行输出(输出契约校验对象) ├── run.log └── run_result.json # {run_id, ext_id, exit_code, started_at, finished_at, outputs: [...], error} ``` ## 2. extension.json schema(唯一事实源) ```json { "schema_version": "extension_stage_v1", "ext_id": "ext_xxxxxxxx", "display_name": "测序质量统计", "status": "draft|building|built|trial_running|trial_passed|trial_failed|validating|validated|repairing|confirming|published|build_failed", "command_template": "python {code_dir}/quality_stats.py --fastq {input_file} --out {output_dir}", "original_command": "python quality_stats.py --fastq input.fastq --out results/", "runtime_image": "bioflow-gf", "requirements": { "pip": [], "apt": [] }, "parameters": [ { "name": "fastq", "type": "file", "required": true, "description": "..." } ], "input_roles": { "input_file": "fastq" }, "nl_triggers": ["质量统计", "fastq 统计"], "analysis_type": "table_filter", "golden": { "test_input": "sample.fastq", "expected_outputs": ["..."] } | null, "repair_count": 0, "created_at": "...", "updated_at": "..." } ``` **占位符白名单(spec_v2 移植)**:`{code_dir} {input_dir} {input_file} {input_hmm} {input_fasta} {input_query_fasta} {input_reference_fasta} {input_pep_fasta} {input_cds_fasta} {input_id_file} {output_dir} {work_dir}` + `{param_}`。硬约束:`{output_dir}` 必含;白名单外占位符拒绝。 ## 3. docker 执行契约(Dev-B 负责实现) 宿主挂载入口 `bioflow_kernel/cli/run_extension.py`,命令形态: ``` docker run --rm --user \ -v :/job/ext:ro \ -v :/job/input \ -v :/job/output \ -v <宿主 bioflow_kernel/cli>:/opt/bioflow-entry:ro \ --cpus <白名单> --memory <白名单> \ :dev python -B /opt/bioflow-entry/run_extension.py \ --ext-dir /job/ext --input-dir /job/input --output-dir /job/output [--param name=value ...] ``` run_extension.py 职责:读 /job/ext/extension.json → 渲染 command_template(code_dir=/job/ext/converted_code)→ subprocess 执行 → 日志/退出码返回 → **输出契约校验(输出目录非空,否则退出码 3)**。8 个 base 镜像与自动生成镜像零改动。 ## 4. 事件帧契约(chat/stream 扩展分支下发,Dev-C 消费) 帧 = `{event, data}`,事件集: | event | data 关键字段 | 触发 | |---|---|---| | `extension_upload` | {session_ext_id} | 创建意图命中 → 上传引导卡 | | `extension_created` | {ext_id, display_name, status:"draft"} | 上传完成 | | `extension_build` | {ext_id, command_template, requirements, runtime_image, nl_triggers, analysis_type, parameters, status} | AI 转换完成 → 转换卡 | | `extension_trial` | {ext_id, status:"running"\|"done"\|"failed", log_tail, exit_code, error} | 试运行状态/结果 | | `extension_repair` | {ext_id, repair_count, suggestion, status} | 修复循环 | | `extension_validate` | {ext_id, golden: {...}\|null, form_defaults} | 金标/确认卡 | | `extension_published` | {ext_id, display_name, nl_triggers} | 发布完成 | | `extension_candidates` | {candidates: [{ext_id, display_name, purpose}]} | 多命中候选卡 | | `extension_confirm` | {ext_id, params_schema, extracted_params, files_required} | 运行前参数确认卡 | | `extension_run_started` | {run_id, ext_id} | 运行开始 | | `extension_run_log` | {run_id, log} | 运行日志追加 | | `extension_run_done` | {run_id, outputs} | 运行完成 | | `extension_run_failed` | {run_id, exit_code, error, log_tail} | 运行失败 | ## 5. 意图两层判定(Dev-A 负责,intent.py 扩展) - **A 层创建**:动作词{创建,建,新建,上传,自定义,写,弄,做一个} × 目标词{扩展,拓展分析,分析模板,分析脚本,分析工具},同句命中即进创建流程。 - **B 层运行**:已发布扩展打分 = display_name 模糊 + nl_triggers 关键词 + analysis_type;动作词{帮我跑,用,做一下,分析一下}加分。仅 published 可被触发。 - **歧义消解**:目标词命中但无动作词 → 有 B 层命中走运行;无命中回「没有匹配的已发布扩展,是否创建?」引导卡。 - **漏判安全**:无命中且非创建 → 回落正常生信阶段规划,现网零影响。 ## 6. 端点清单(Dev-A 实现,Dev-C 调用) ``` POST /api/bioflow/extensions (multipart: code_zip 归档[zip/tar/tar.gz,服务端魔数解压] 或 code_files 多文件[目录直传,filename=相对路径] + display_name + command + runtime_image? + golden?[JSON 字符串] + test_file?[金标数据文件]) 上传内容结构自适应分类:raw_code|code|scripts → 代码;raw_test_data|test_data|data → 数据; 散落文件按运行命令解析入口 + 扩展名模式分类,未知扩展名归代码;纯数据包 422,纯脚本包合法 GET /api/bioflow/extensions (列表,published 优先) GET /api/bioflow/extensions/{id} DELETE /api/bioflow/extensions/{id} POST /api/bioflow/extensions/{id}/build (AI 转换) POST /api/bioflow/extensions/{id}/trial-run (test_inputs 文件) POST /api/bioflow/extensions/{id}/repair (LLM 修复,上限 20 轮可配) POST /api/bioflow/extensions/{id}/publish POST /api/bioflow/extensions/{id}/run (params + files → run_id) GET /api/bioflow/extensions/{id}/runs GET /api/bioflow/extensions/{id}/runs/{run_id}/events (SSE,首帧快照) ``` ## 7. 约束(全部 agent) - 代码仅限 175 仓库 `/home/xzq/5090/teamWorkspace/zh/PlantAI-rag-new`(worktree 副本)。 - 不 push、不部署 176、不动生产部署树;dev 栈不得重启生产服务。 - 依赖安装:服务端零新增依赖(纯 stdlib+现有 httpx/pydantic/fastapi);镜像内依赖走自动镜像生成(Dev-B)。 - 现有 bioflow 路径零改动:kernel.py/runner.py/planner.py/catalog.py/stage_image_map.json 一律不碰(扩展是并行链路)。