superpowers 的 drill 迁移设计:把 LLM 行为评测提升为独立 evals/ 评测体系

发布时间:2026/9/5 20:00:38
superpowers 的 drill 迁移设计:把 LLM 行为评测提升为独立 evals/ 评测体系 superpowers 的 drill 迁移设计把 LLM 行为评测提升为独立 evals/ 评测体系【免费下载链接】superpowersAn agentic skills framework software development methodology that works.项目地址: https://gitcode.com/GitHub_Trending/su/superpowers本文基于 superpowers 仓库中的设计文档 2026-05-06-lift-drill-into-evals-design.md完整讲解一次评测基准搬家的系统性设计如何把独立的 drill skill-compliance 基准整体迁入 superpowers 仓库的evals/目录、按逐文件验证门槛清理被完全覆盖的旧 bash 测试、并重构tests/与evals/的职责边界。读完本文你可以掌握一套可复用的工程方法如何在源码逐字复制 路径契约变更 测试资产删除三者之间建立可审计的验证闭环并用子代理subagent门禁保证每一步都有据可查。背景drill 已经是 superpowers 的事实评测框架Drill 是一个 Python 编写的 skill 合规性基准benchmark独立存放于obra/drill仓库。它的运行机制是驱动真实的 tmux 会话、用 LLM actor 模拟用户与 Agent 对话、再用 LLM verifier 对会话转录transcript进行评判并按场景scenario输出 pass/fail。其支持的后端包括 Claude Code、Codex、Gemini CLI以及后来新增的 OpenCode 与 Copilot CLI。设计文档给出的迁移动因很明确drill 已经承担了 superpowers 的事实评测框架角色——drill 仓库中的 PRI-1397 提交系列已将约 22 个 superpowers bash 测试提升为 drill 场景最近一次 superpowers 提交a2292c5以replaced by drill behavioral coverage已被 drill 行为覆盖取代为由显式删除了一个冗余 bash 测试——迁移势能已经形成这份 spec 的任务是把迁移做完具体动作三件事把 drill 整体搬进evals/在逐文件验证drill 场景覆盖之后删除冗余 bash 测试更新顶层文档让贡献者落到新结构上。配套的 实施计划约 1370 行把设计分解为带 checkbox 的任务并在头部声明技术栈为 Python 3.11 uvdrill 现有工具链不变rsyncbashgit且明确要求 agentic worker 使用 superpowers 自带的 subagent-driven-development 或 executing-plans 技能来逐任务执行——这份迁移本身就是用 superpowers 方法论执行的一次实践。目标与非目标把边界先划清楚目标Goalsevals/成为 superpowers 的权威评测框架——包含完整的 drill 源码、场景、fixtures、prompts、后端配置和测试tests/中经逐个验证被 drill 场景 100% 覆盖的 bash 测试被删除其余全部保留tests/插件基础设施bash node python 集成测试与evals/actor verifier 的 LLM 行为评测的分工是有意义的、且被文档化的顶层文档README.md、CLAUDE.md、docs/testing.md把贡献者指向正确位置独立仓库obra/drill继续存在本 PR 不碰它在合并后作为独立的手动步骤归档。非目标Non-goals——这一节对控制 PR 规模很关键不做 CI 集成。仅手动运行。设计者给出了自然的后续路线tiered每个 PR 跑快速子集夜间 按需跑全量但那需要 API 预算决策、GitHub Actions secrets、以及一个装了tmuxnodepython 各 CLI 的 runner 镜像均超出范围场景不随技能就近存放。场景集中放在evals/scenarios/。若将来决定每个 skill 自持场景从源码结构看这只是一次查找-改名操作YAML 格式不变不改内部 Python 包名。目录对用户暴露为evals/但 Python 包保留drill名以缩小 diff在evals/README.md中用简短说明解释不归档 drill 仓库。本 PR 不碰obra/drill合并后手动归档GitHub 上设为只读README 指向obra/superpowers/evals/不迁移tests/claude-code/analyze-token-usage.py到evals/bin/。它是实用工具而非测试代码可以以后再移。分支策略从dev拉出独立分支f/evals-lift与当时开放的f/cross-platformPR 无依赖除README.md外无共享文件改动若有冲突在合并时小范围解决即可。迁移后的架构evals/ 目录结构与 tests/ 的职责划分设计文档给出了目标目录树evals/为逐字复制 drill 后的完整结构superpowers/ evals/ ← NEW (full drill copy) pyproject.toml (Python 3.11, uv-managed) uv.lock .gitignore (drills own; results/, .venv/, .env) README.md (was drills README; install instructions updated) CLAUDE.md (was drills CLAUDE.md; paths updated) docs/ design.md (drills design — preserved verbatim, cross-linked from this spec) manual-testing.md pressure-and-red-testing.md drill/ (Python package; name kept; cli, engine, actor, verifier, etc.) backends/ (claude-*.yaml, codex.yaml, gemini.yaml) scenarios/ (32 YAML scenarios) setup_helpers/ (15 Python helpers; create_base_repo, sdd_*, spec_*, worktree, etc.) fixtures/ (template-repo, sdd-go-fractals, sdd-svelte-todo) prompts/ (actor.md, verifier.md) bin/ (assertion helper scripts: tool-called, tool-count, etc.) tests/ (drills own pytest suite) tests/ ← bash tests preserved by default brainstorm-server/ ← KEEP (node tests for brainstorm-server JS code) opencode/ ← KEEP (plugin loading tests) codex-plugin-sync/ ← KEEP (sync verification) claude-code/ ← MOSTLY KEEP — see deletion gate explicit-skill-requests/ ← KEEP unless verified replaced skill-triggering/ ← KEEP unless verified replaced subagent-driven-dev/ ← KEEP unless verified replaced docs/ testing.md ← UPDATED (split into Plugin tests Skill behavior evals) superpowers/ specs/ 2026-05-06-lift-drill-into-evals-design.md ← THIS SPEC README.md ← small Contributing-section pointer to evals/ CLAUDE.md ← one-line Eval harness lives at evals/ pointer迁移后两个目录承担清晰不同的角色tests/—— 回答插件的非 LLM 代码是否正常工作 覆盖 brainstorm-server JS 代码的单测/集成测试、OpenCode 插件加载、codex-plugin-sync 同步验证技术栈为 bash node pythonevals/—— 回答Agent 在真实 LLM 会话上行为是否正确 运行 drill 场景含 actor verifier纯 Python驱动真实 tmux 会话。这一划分在今天的仓库中依然可见docs/testing.md 开头正是这两段分工描述does the plugins non-LLM code work? / do agents behave correctly on real LLM sessions?并按 Plugin tests 与 Skill behavior evals 两节组织——设计目标 3 和 4 已落成文档现状。删除门槛Deletion gate逐文件验证默认保留bash 测试的删除不是批量操作而是每个文件都要过一道门槛只有当一个 drill 场景可验证地覆盖了该 bash 测试做出的每一条断言时才删除。验证流程是读 bash 测试 → 列出它的所有检查项 → 找到对应 drill 场景 → 逐条确认每个检查项在场景的verify.assertions或verify.criteria中有匹配条目。只要有一条检查项没有匹配选项只有两个扩展 drill 场景或保留 bash 测试。默认是保留。设计文档附了一张基于提交信息整理的暂定覆盖地图tentative coverage map并强调删除前必须逐文件验证Bash 测试声称的 drill 替代覆盖状态tests/skill-triggering/prompts/*6 个 prompt 文件triggering-*.yaml6 个场景候选——删除前逐 prompt 验证tests/skill-triggering/run-test.sh、run-all.sh不适用runner非测试保留——运行脚本tests/explicit-skill-requests/prompts/please-use-brainstorming.txt待验证——drill 尚无明确对应场景除非补 drill 场景否则保留tests/explicit-skill-requests/prompts/use-systematic-debugging.txt待验证——drill 尚无明确对应场景除非补 drill 场景否则保留tests/explicit-skill-requests/run-claude-describes-sdd.sh部分 →mid-conversation-skill-invocation.yaml候选——逐脚本验证tests/explicit-skill-requests/run-haiku-test.sh没有 drill 场景覆盖 Haiku 特有行为保留tests/explicit-skill-requests/run-multiturn-test.sh、run-extended-multiturn-test.sh没有 drill 场景覆盖多轮构建保留除非补充 drill 场景tests/explicit-skill-requests/run-test.sh、run-all.sh不适用runner保留tests/subagent-driven-dev/go-fractals/、svelte-todo/sdd-go-fractals.yaml、sdd-svelte-todo.yaml候选——删除前验证含测试套件通过这类真实断言tests/claude-code/test-document-review-system.shspec-reviewer-catches-planted-flaws.yaml候选——删除前验证tests/claude-code/test-requesting-code-review.shcode-review-catches-planted-bugs.yaml候选——删除前验证tests/claude-code/test-subagent-driven-development-integration.shsdd-rejects-extra-features.yamlYAGNI 子集部分——bash 测试还断言 ≥3 个 commit /npm test通过 / 运行analyze-token-usage.pydrill 场景断言 forbidden-exports reviewer-as-gate两者大体不相交——几乎确定保留 bash 扩展 drill 场景tests/claude-code/test-subagent-driven-development.sh元/文档类测试让 Agent描述SDD无 drill 场景覆盖描述类测试保留除非补 drill 场景tests/claude-code/test-worktree-native-preference.shworktree-creation-under-pressure.yaml候选——删除前验证tests/claude-code/test-helpers.sh、run-skill-tests.sh、analyze-token-usage.py不适用工具非测试保留——库/工具这张地图与当前仓库状态可以互相印证tests/explicit-skill-requests/ 目录下至今保留着prompts/please-use-brainstorming.txt、prompts/use-systematic-debugging.txt、run-haiku-test.sh、run-multiturn-test.sh、run-extended-multiturn-test.sh等被判为keep的文件而 tests/claude-code/test-worktree-native-preference.sh 与 tests/claude-code/test-subagent-driven-development-integration.sh 被保留下来且内部已标注 drill 覆盖范围drill 只覆盖 PRESSURE / YAGNI 子集bash 侧补充覆盖 RED/GREEN 基线、commit 数与 token 遥测断言tests/claude-code/test-subagent-driven-development.sh 同样保留描述类测试无 drill 对应物。而skill-triggering/与subagent-driven-dev/两个目录已不在tests/下——符合候选项验证通过后删除的处置。RELEASE-NOTES.md 中还保留了历史说明test-requesting-code-review.sh与test-document-review-system.sh已于 2026-05-06 被提升为 drill 场景并从tests/移除原引用被保留为dated artifact带日期的历史工件正是设计文档要求的历史引用注释而非改写策略的落地。子代理门禁每类变更都有独立验证人设计文档的Verification protocol (subagent-gated)规定实施计划中的每一处变更在提交前都由独立子代理交叉检查。这是整份设计最有辨识度的部分——验证责任被分配到了与变更类型一一对应的子代理任务上变更类别子代理验证方式每个 bash 测试的删除派发子代理输入(a) bash 测试文件内容(b) 候选 drill 场景 YAML(c) 提示词列出 bash 测试的每条断言列出 drill 场景的每条 verify 项对每条 bash 断言找到匹配的 drill 检查项否则报告未匹配。输出逐断言表格。 子代理输出即门槛——只有每条断言都有匹配才允许删除。初始evals/复制子代理验证(a) 被复制的 drill SHA 记录在 lift 提交信息中来源可审计(b)逐文件 SHA-256 校验和与 drill 仓库一致不是只数文件数(c) 排除路径.git/、.venv/、results/、.env、__pycache__/、*.egg-info/、任何.private-journal/在evals/中不存在(d) 所有 backend YAML 引用的路径在迁移后依然存在(e)pyproject.toml、uv.lock、.gitignore完整无损。drill 自带的 pytest 套件子代理在路径默认值变更后运行cd evals uv run pytest。drill 自带 pytest 套件evals/tests/含test_backend.py它演练SUPERPOWERS_ROOT环境变量行为这些测试必须更新以匹配新 helper 并继续通过。删除后的引用清扫子代理对 superpowers 全树 grep 被删 bash 测试路径排除node_modules/、.venv/、evals/搜索目标docs/、docs/superpowers/plans/、RELEASE-NOTES.md、CLAUDE.md、GEMINI.md、AGENTS.md、README.md、.github/、scripts/、.opencode/INSTALL.md、.codex-plugin/INSTALL.md、lefthook.yml。任何命中要么更新、要么暴露一个被遗漏的依赖。路径默认值变更SUPERPOWERS_ROOT子代理在路径变更后至少运行一个便宜的 drill 场景如triggering-test-driven-development并确认其通过——是真实行为验证而非仅代码评审。最终 PR 前对抗性评审两个子代理并行采用5 分给找到最多有效问题的人的框架——与 cross-platform PR 所用协议相同。同时验证源码与行为。每个子代理任务在实施计划中都有独立条目带明确的输入与通过标准子代理输出被摘要进相应提交信息Subagent verification: …使整条验证轨迹可审计。路径与配置契约SUPERPOWERS_ROOT 的自动默认化这是迁移中最精细的部分——让 drill 搬进evals/后开箱即用同时不破坏任何现有行为。前置验证写 spec 之前已核实drill/cli.py定义了PROJECT_ROOT Path(__file__).parent.parent。迁移后cli.py位于evals/drill/cli.py因此PROJECT_ROOT解析为evals/PROJECT_ROOT.parent解析为 superpowers 仓库根目录——这正是SUPERPOWERS_ROOT应取的默认值。YAML 替换审计只有 4 个claude*.yaml后端配置会在args中插值${SUPERPOWERS_ROOT}用于--plugin-dir标志codex.yaml和gemini.yaml只是在required_env中列出SUPERPOWERS_ROOT由engine.py:233/setup.py:25中前置/后置运行钩子处的os.environ[SUPERPOWERS_ROOT]查找消费。helper 对os.environ的修改同时覆盖这两条代码路径。具体的文件级修改清单当前 → 迁移后文件当前迁移后drill/cli.py模块导入时load_dotenv(PROJECT_ROOT / .env)与SUPERPOWERS_ROOT无关load_dotenv之后调用新 helper_set_superpowers_root_default()当且仅当未设置时把os.environ[SUPERPOWERS_ROOT]设为str(PROJECT_ROOT.parent)。顺序load_dotenv→ 设默认值 → click group 定义。drill/engine.py:233、drill/setup.py:25直接访问os.environ[SUPERPOWERS_ROOT]未设置时 KeyError不变。CLI 启动钩子保证引擎/设置执行时环境变量已就位。backends/claude*.yaml5 个文件args中的${SUPERPOWERS_ROOT}用于--plugin-dir替换不变。YAML 替换在后端加载时读os.environ此时已是 CLI 启动之后。backends/codex.yaml、backends/gemini.yaml仅在required_env中列SUPERPOWERS_ROOT从required_env移除由 helper 供给。claude*.yaml保留required_env以向后兼容环境变量仍可覆盖。evals/tests/test_backend.py测试断言SUPERPOWERS_ROOT在required_env列表中另有路径解析测试更新测试以匹配新契约helper 提供默认值、环境变量覆盖仍可用、codex/gemini 不再需要required_env。evals/README.mdexport SUPERPOWERS_ROOT/path/to/superpowers删除 export 行说明该变量自动默认为evals/的父目录唯一必需的配置是ANTHROPIC_API_KEY或OPENAI_API_KEY/ Gemini 鉴权。evals/CLAUDE.md同上同上evals/.gitignoredrill 既有模式results/、.venv/、__pycache__/、.env、*.pyc、*.egg-info/、dist/、build/、.claude/逐字复制。模式相对文件位置生效因此在evals/下同样正确。evals/lefthook.ymldrill 自带lefthook.yml定义pre-commit: uv run ruff check uv run ty check移至evals/lefthook.yml。两种方案(a) 在 superpowers 根安装 lefthook 并联邦到evals/lefthook.yml或 (b) 文档化让贡献者手动运行cd evals lefthook run pre-commit。实施决策选 (b) 求简——superpowers 顶层工作流不变。.env位置保留evals/.envgitignore贡献者从那里 source或在 shell 环境中直接设置ANTHROPIC_API_KEY。顶层 superpowers 文件的小幅增补superpowers/.gitignore增加evals/results/、evals/.venv/、evals/.env双保险evals/.gitignore已在本地覆盖这些superpowers/CLAUDE.md增加一行指针 Eval harness lives atevals/— seeevals/README.md让 Agent 能发现它当前 CLAUDE.md 中仍保留了 Skill-behavior evals live in … seeevals/README.md 的指引行是这一设计的延续superpowers/docs/testing.md拆分为 ## Plugin tests现有tests/内容裁掉被删测试的引用与 ## Skill behavior evals一段话摘要 指向evals/superpowers/README.md在 Contributing 节加一行指向evals/做 skill 行为测试。迁移顺序十个原子化步骤每一步是一个独立提交或小提交组。第 2 步是最大的单提交drill 逐字复制后续步骤小而原子1. Branch off dev (f/evals-lift) 2. Copy drill repo into evals/ (single commit, easy to revert) ├─ Record drill SHA at copy time → commit message ├─ Use rsync -a --exclude.git --exclude.venv --excluderesults │ --exclude.env --exclude__pycache__ --exclude*.egg-info │ --exclude.private-journal /path/to/drill/ evals/ │ (rsync chosen over cp -r for explicit excludes; verify with │ find evals -name .git -type d returns nothing) ├─ Subagent gate: per-file SHA-256 checksum matches drill repo for every │ non-excluded file; excluded paths absent from evals/ └─ Smoke check: cd evals uv sync succeeds (proves install only; not a behavioral test) 3. Update path defaults ├─ Add _set_superpowers_root_default() helper to drill/cli.py ├─ Wire it after load_dotenv, before click group definition ├─ Update evals/README.md and evals/CLAUDE.md (drop SUPERPOWERS_ROOT install step) ├─ Drop SUPERPOWERS_ROOT from required_env in codex.yaml/gemini.yaml │ (keep in claude*.yaml as override) └─ Update evals/tests/test_backend.py to match new contract 4. Validate from new location (TWO checks) ├─ Run drills own pytest: cd evals uv run pytest — must pass └─ Run cheap drill scenario: cd evals uv run drill run triggering-test-driven-development -b claude — must pass. Real behavioral validation, not just code review. 5. Bash test deletion phase — per-file with subagent gate For each file in the candidate-deletion list: a. Subagent compares bash test assertions vs drill scenario verify block b. Pass criterion: every bash assertion has a matching drill check c. If pass → delete the bash test file (one commit per file or per coherent group) d. If fail → either extend drill scenario (separate commit verify) or keep the bash test (no commit) 6. Stale-reference scrub ├─ Subagent greps the superpowers tree (excluding node_modules/, .venv/, │ evals/) for deleted file paths ├─ Search targets: docs/, docs/superpowers/plans/, RELEASE-NOTES.md, │ CLAUDE.md, GEMINI.md, AGENTS.md, README.md, .github/, scripts/, │ .opencode/INSTALL.md, .codex-plugin/INSTALL.md, lefthook.yml ├─ Update active references (e.g., docs/testing.md, README.md install) └─ Historical references in docs/superpowers/plans/*.md and RELEASE-NOTES.md are PRESERVED with a brief annotation ((test removed; behavior covered by drill scenario X)) rather than rewritten — these are dated artifacts, not living docs. 7. Top-level docs ├─ docs/testing.md split ├─ CLAUDE.md pointer └─ README.md Contributing section 8. Re-run smoke checks (regression gate) ├─ cd evals uv run pytest └─ cd evals uv run drill run triggering-test-driven-development -b claude 9. Final adversarial review └─ Two parallel subagents, full diff, 5 points to whoever finds the most legitimate issues framing. Address findings before push. 10. Push branch open PR against dev └─ PR description includes: drill SHA pinned at copy, archival action item (after merge: archive obra/drill, add README pointer to obra/superpowers/evals/), per-deleted-file coverage receipts.几个值得注意的设计取舍rsync 而非cp -r是为了显式排除列表且可用find evals -name .git -type d这类命令独立复核第 4 步坚持两次检查pytest 一个真实场景区分能安装与行为正确第 6 步对历史文档docs/superpowers/plans/*.md、RELEASE-NOTES.md采取加注释不改写原则因为它们是带日期的工件而非活文档。实施后的验收清单实施计划必须展示以下证据链第 2 步后evals/中存在全部非排除的 drill 源文件子代理逐文件 SHA-256 校验和比对vsobra/drillrecorded-sha排除路径.git/、.venv/、results/、.env、__pycache__/、*.egg-info/、.private-journal/在evals/中不存在第 2 步提交信息记录了 drill 源 SHA未设置SUPERPOWERS_ROOT时cd evals uv sync成功cd evals uv run pytest通过drill 自带 pytest 套件cd evals uv run drill list返回的场景数与记录 SHA 处的独立 drill 仓库一致cd evals uv run drill run triggering-test-driven-development -b claude通过端到端证明路径默认值工作每个被删 bash 测试的提交信息中包含子代理验证表逐条断言映射到 drill 检查项对已删文件路径的 grep 在活文档中零命中第 6 步之后docs/superpowers/plans/*.md与RELEASE-NOTES.md中的历史引用被注释而非改写docs/testing.md同时拥有 Plugin tests 与 Skill behavior evals 两节drill 仓库历史不受影响PR 描述点名合并后归档obra/drill的行动项。设计中的未决问题全部已决文档最后列出了所有澄清性决策Open questions: None问题决策drill 在 superpowers 中的位置evals/从 drill 改名而来独立仓库另行归档冗余 bash 测试的命运逐文件删除由子代理验证覆盖默认保留场景布局集中在evals/scenarios/Python 工具链位置自包含于evals/CI 集成本 PR 仅手动文档化未来路线迁移机制普通复制drill 仓库历史保留在归档仓库中而非进树内部 Python 包名保留drill目录为evals/分支策略独立基于dev不叠加在f/cross-platform之上仓库现状对照设计被实施后的演化轨迹把这份 2026-05-06 的设计放回仓库时间线中看其实施结果在 git 历史与现存文档中留有清晰痕迹以下均可在仓库内核实迁移按设计执行git 历史中存在提交6bc6f22 Lift drill into evals/ at 013fcb8b7dbefd6d3fa4653493e5d2ec8e7f985b提交信息完整记录了 rsync 排除列表、源 SHA写入evals/.drill-source-sha供分歧检测以及drill 仓库不受影响、归档为合并后的独立手动步骤——与设计的步骤 2 和验收清单一一对应其后是03cc20dSUPERPOWERS_ROOT 默认值化、671ec37从 codex/gemini 的required_env移除、09046c0README/CLAUDE 去掉 export 步骤等对应步骤 3 的小提交以及ea8aad8、12ef68d、1f0ad38等逐文件删除提交分别移除test-document-review-system.sh、test-requesting-code-review.sh与 subagent-driven-dev fixtures提交信息注明对应的 drill 场景315ef09则对三个保留的 bash 测试加注了 drill 覆盖说明——与上文覆盖地图中候选/保留的分判完全吻合。RELEASE-NOTES.md 的相应版本说明写道Skill-behavior testing moved out oftests/into a newevals/submodule built on drill … Several in-tree bash suites retired once a stricter drill scenario covered them; the few with no equivalent stayed. From here on,tests/holds plugin-code tests andevals/holds skill-behavior tests#1541——目标 3 的分工被文档化直接落成了版本说明文字并保留了历史引用注释指向evals/scenarios/code-review-catches-planted-bugs.yaml与evals/scenarios/spec-reviewer-catches-planted-flaws.yaml即注释而非改写策略的实际产物。值得说明的是从仓库后续演化看evals/在成为 submodule 后最终因插件安装对部分用户报错而在 v6.0.2 停止随插件发布评测框架移入独立仓库见 RELEASE-NOTES.md 与 CLAUDE.md 现行措辞。这属于设计合并之后的独立决策但反过来也印证了设计文档非目标里独立仓库与主仓库解耦的保守取向先让evals/在结构上自包含后续无论继续内置还是拆出去成本都很低。小结这份设计的可取之处不在于搬一个目录而在于它把三件高危操作——逐字复制靠逐文件 SHA-256 校验和与源 SHA 记录保证可审计、契约变更SUPERPOWERS_ROOT自动默认化且引擎/设置/后端的三处消费路径逐一审计、资产删除每个 bash 测试都要过逐断言匹配的子代理门槛默认保留——都装配了独立于执行者的验证环节并且把tests/ 测插件代码、evals/ 测 Agent 行为的职责边界写进了贡献者会看到的每一层文档。对任何想把评测体系从散装 bash 脚本升级为结构化 LLM 行为评测的团队这份 spec 提供了一份可直接套用的清单先画职责边界再定删除门槛最后用真实跑一个便宜场景替代只看 diff作为验收底线。【免费下载链接】superpowersAn agentic skills framework software development methodology that works.项目地址: https://gitcode.com/GitHub_Trending/su/superpowers创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考