adk-samples 的 prepare-python-recipe 技能:八阶段流水线把 Python Recipe 一键调到 PR 就绪
2026/9/15 14:28:48 网站建设 项目流程

adk-samples 的 prepare-python-recipe 技能:八阶段流水线把 Python Recipe 一键调到 PR 就绪

【免费下载链接】adk-samplesA collection of sample agents built with Agent Development Kit (ADK)项目地址: https://gitcode.com/GitHub_Trending/ad/adk-samples

prepare-python-recipe是 adk-samples 仓库中面向 Agent 的主编排(Master Orchestration)技能,它把仓库内四个 Python Recipe 子技能(generate-manifestextract-python-environment-variablesalign-recipe-pyprojectgenerate-python-runnability-test)按固定顺序串成一条流水线,对core/python/contrib/python/skills/<vertical>/<solution>/下已就位的 recipe 依次执行 manifest 生成、环境变量提取、pyproject 对齐、ruff 格式化、uv lock、runnability 测试生成与验证、仓库校验器终检共八个阶段。读完本文,你将掌握:这条流水线每一阶段做什么、为什么要按这个顺序执行、哪些环节必须停下来向用户确认,以及如何读懂它输出的摘要表与 TODO 清单,从而自己复现"让任意 Python recipe 通过 python-validate-recipe.yml 全部检查"的完整流程。

技能定位:交互式主编排,而非又一个检查脚本

该技能的定义明确它是master orchestration skill——"Runs the other Python-recipe skills in the right order, with the right inputs, in a single pipeline"(见 SKILL.md)。两个关键设计意图:

  • 不重复子技能逻辑。凡是已有子技能(或子技能底层脚本)能做的事,主技能一律委托给它们,自己只负责排序、传参、判断结果与汇报。
  • 交互式设计(interactive skill by design)。它不只依赖 5 个固定检查点暂停,而是允许 Agent 在任何阶段输出"含糊、意外或需要人类判断"时主动打断提问。触发场景包括:runnability 生成器报告has_root_agent: false(合法 recipe 永远应该为 true)、manifest 推断出与你数到的 agent 数量不符的multi、环境变量一次性新增超过 10 个、uv lock记录到可疑依赖、recipe 出现非标准布局等。

同时它刻意排除了部署化:Dockerfilefast_api_app.pyapp_utils/等容器服务文件属于另一个可选技能make-python-recipe-deployable的职责,绝不能在 "prepare" 流水线里未经询问地自动添加(见 make-python-recipe-deployable/SKILL.md)。

前置条件:必须在调用技能前手工完成

技能假定用户已经完成以下手工准备(SKILL.md 原文):

  1. 停用任何激活的 Python 虚拟环境;
  2. 在仓库根目录执行过git pull拉取最新代码;
  3. 在仓库根目录执行过uv sync同步根依赖;
  4. recipe 已放置在目标路径——无论是新脚手架生成、从别处移动,还是重命名为最终目录名,位于core/python/<name>/contrib/python/<name>/skills/<vertical>/<solution>/下;
  5. 已提交原始 recipe,使git diff能清晰展示技能做的改动。

技能不会替你执行git pullgit commit、停用 venv 或移动/重命名目录——这些被刻意排除在范围之外。若用户未完成前置就要求运行,应告知其先完成前置并停止。

两个必须原样保留的规范占位符

generate-manifest写入、tools/validate_manifest.py强制校验的占位符是精确字符串,不允许发明、翻译或改写(validate_manifest.py):

OWNERSHIP_TEAM_PLACEHOLDER = "TODO: Replace with your team name" OWNERSHIP_POC_PLACEHOLDER = "TODO: Replace with your GitHub user ID"

流水线中途绝不替换它们——这是刻意设计:占位符保留到 CI 校验失败,强制人类在合并前填上真实值。替换属于流水线结束后用户 TODO 清单("What you still need to do")的第一项。真实 recipe 的 manifest 中这两个字段被真实值填充后即为合法状态,可参考 core/python/cross-session-memory/manifest.yaml。

八阶段流水线总览

技能对目标 recipe 依次运行八个有序阶段,每阶段要么调用既有子技能(或其底层脚本),要么执行仓库标准命令:

阶段名称动作产出
1Manifest缺失时生成manifest.yamlmanifest.yaml
2Env vars提取环境变量到.env.example,引导load_dotenv().env.example__init__.pypyproject.toml
3Align对齐pyproject.toml与仓库标准pyproject.toml
4Lintruff format+ruff check --fix全部.py文件
5Recipe lockuv lock --python 3.11uv.lock
6Runnability test生成tests/test_runnability.py(必要时附tests/conftest.py测试文件
7Verifypy_compile+ pytest 运行验证结果
8Validateuv run validate manifest/validate structure校验结论

阶段 1:Manifest

先检查[ -f <RECIPE_DIR>/manifest.yaml ];若缺失,通过skill工具加载generate-manifest技能并按其说明生成。该技能读取 manifest-schema.json 与 recipe 源码,只推断代码能证明的字段:typestandalone/module)、deployablelargearchitecture.agentsingle/multi,按Agent(构造调用计数)、architecture.statefularchitecture.datasources等,并写入上述两个所有权占位符(详见 generate-manifest/SKILL.md)。

若 manifest 已存在则跳过生成,且不读取、不提示ownership.team/ownership.poc——无论里面是真实值还是占位符都保持原样。

阶段 2:环境变量提取

直接调用脚本(apply 模式,不带--dry-run):

uv run --no-project python3 .agents/skills/extract-python-environment-variables/scripts/extract_env_vars.py \ --recipe-dir <RECIPE_DIR>

必须用uv run --no-project python3而非裸python3:脚本导入tomllib,该标准库模块仅在 Python 3.11+ 存在,uv 托管的解释器可保证版本。脚本会(extract-python-environment-variables/SKILL.md):

  • 将新发现的环境变量追加到.env.example(含# extracted-by:extract-env-vars标记与溯源注释);
  • 向包__init__.py注入load_dotenv()(若缺失);
  • [project].dependencies添加python-dotenv>=1.0.0(若缺失);
  • 把源码中硬编码的模型名字符串(如"gemini-3.5-flash")改写为裸os.getenv(...)调用,并在.env.example中记录替换。

其底层有两条"绝不打破"的硬规则值得注意:用户编辑安全——凡是无法证明是自己写入的.env.example行一律视为用户所有、永不修改,分类器无法确定时"失败关闭"(fail closed);Python 文件只增不改——只允许三种写入(load_dotenv()引导、尾随相对导入的# noqa: E402、硬编码模型字面量替换)。

阶段 3:对齐 pyproject.toml —— 必须在阶段 4 之前

这是全流水线最强调顺序的一环。对齐脚本会删除 recipe 本地的任何[tool.ruff*]表——删除之后 recipe 才使用根目录pyproject.toml的 ruff 配置。若先跑 lint,就会按 recipe 自带(通常更宽松)的本地配置检查,漏掉 CI 会抓到的违规,导致"流水线声称干净、CI 却失败"。

采用两遍逻辑,先 dry-run 探测是否需要用户输入:

uv run --no-project --with tomlkit --with 'ruamel.yaml' --with packaging \ python .agents/skills/align-recipe-pyproject/scripts/align_pyproject.py \ --recipe-dir <RECIPE_DIR> --dry-run

解析 JSON:若description-matches-manifest状态为needs_input,需暂停展示pyproject_descriptionmanifest_description,请用户在pyproject/manifest/delete三选一。然后带(或不带)--description-source=<CHOICE>执行 apply:

uv run --no-project --with tomlkit --with 'ruamel.yaml' --with packaging \ python .agents/skills/align-recipe-pyproject/scripts/align_pyproject.py \ --recipe-dir <RECIPE_DIR> \ [--description-source=<CHOICE>]

对齐脚本共检查 8 条规则(align-recipe-pyproject/SKILL.md 有完整表格):

规则 ID检查内容自动修复
no-local-ruff-config不得声明任何[tool.ruff*]是——删除
python-version-floorrequires-python必须恰好接受 3.11(既不允许更低如>=3.10,也不得排除 3.11 如>=3.12是——重写下界为>=3.11并保留所有上界/排除/~=上限/固定版本;若结果仍排除 3.11 则拒绝并返回needs_input
project-name-matches-folder[project].name必须等于 recipe 目录名(skills/下为<vertical>-<solution>是——设置
description-matches-manifest[project].description若设置必须等于manifest.description仅配合--description-source={pyproject,manifest,delete}
build-system-present[build-system]须同时有requiresbuild-backend——后端选择属编辑判断
default-pypi-index[[tool.uv.index]]须有default = true且指向公共 PyPI(https://pypi.org/simple/整块缺失时是——追加;已有默认条目但指向别处则否
stale-python-version-refs扫描 recipe 内所有文本文件,找出引用低于 3.11 下限的 Python 版本——仅报告
runnability-test-in-testpaths若设置了testpaths,至少一项须能收集到tests/test_runnability.py——仅报告

关键退出码语义:align 脚本只要存在report_only状态的检查(如缺[build-system]、默认索引非公共 PyPI)就以退出码1结束——这是设计内的延迟处理(deferral-by-design),不是硬错误,不能套用规则 7 的 halt。应从 JSON 判断:仅剩report_only就继续并把问题记入摘要;只有error状态才 halt。四条会产生report_only的规则中,build-system-present还有个连锁影响:没有[build-system]的 recipe 永远不会被安装,runnability 测试的import无法自行解析,生成器会改而输出tests/conftest.py路径垫片(path shim),摘要中要把这两件事合并说明。

阶段 4:ruff —— 必须从仓库根目录运行

uv run ruff format <RECIPE_DIR> uv run ruff check --fix <RECIPE_DIR>

两条命令都从仓库根目录(而非 recipe 目录)运行,确保根的 ruff 配置生效。ruff check的退出码需要区分对待:

  • 退出码 1:存在 ruff 无法自动修复的真实违规(典型如C901复杂结构、PLR0912/0915分支/语句过多)。不要停流水线,记入摘要的 Manual TODO,让用户重构或审核后加# noqa
  • 退出码 2:ruff 自身出错(配置非法、文件系统问题或 ruff 缺陷),不是违规计数——阶段 4 实际未执行,按规则 7 视为硬错误停流水线并展示信息。

另需注意E402__init__.py的约定:阶段 2 已在 recipe 包__init__.py的尾随相对导入(from . import agent)上压制E402——这是 ADK recipe 的规范模式:load_dotenv()os.environ.setdefault(...)等环境引导副作用有意放在from . import ...之前,以保证 agent 子模块加载时环境变量已就绪。若阶段 4 输出中出现__init__.pyE402,说明上游出了问题(阶段 2 未识别该模式,或阶段 2 与 4 之间出现了新文件)。

阶段 5:recipe 级uv lock—— 为什么要显式--python 3.11

pyproject 已稳定(阶段 3 对齐、阶段 4 不触碰它),此时重新生成 lockfile:

uv lock --python 3.11

需在workdir = <RECIPE_DIR>下执行(通过工具调用的工作目录参数传递,不用cd)。两个关键理由:

  • 为什么显式--python 3.11:CI 的 python-dependency-policy.yml 在执行uv lock --check时固定 Python 3.11。若本地用机器上默认的解释器(现代机器通常是 3.12+)lock,本地干净通过、CI 却报出令人困惑的错误——工作流会把解释器不匹配误报为 "lockfile is out of date"。在流水线阶段强制 3.11 能把同样的不兼容提前到 pipeline 期暴露。阶段 3 的python-version-floor通常已重写过requires-python,但显式 pin 仍能防御该检查过宽或 recipe 有兼容性上限无法降低的边缘情况。
  • 为什么是uv lock而非uv sync:流水线的职责是准备 recipe,不是安装并验证其运行环境。uv lock仅解析依赖并写入uv.lock——这正是 CI 与下游消费者需要的产物;uv sync还会把所有 wheel 下载进.venv/,既慢(数分钟网络 I/O)又可能以流水线无法干净汇报的方式失败(C 扩展构建错误、网络抖动)。用户审阅 diff 后自行uv sync获得真实.venv/

若 lock 失败则 halt 并原样展示错误。最常见原因是requires-python排除了 3.11(>=3.12~=3.12等)且阶段 3 无法改写——修复方式是降低 floor 到>=3.11,或 recipe 确实需要新特性时与维护者沟通更新 CI 的固定解释器。

阶段 6:runnability 测试生成

[ -f <RECIPE_DIR>/tests/test_runnability.py ] && echo exists || echo missing

缺失时生成:

uv run --no-project python3 .agents/skills/generate-python-runnability-test/scripts/generate_runnability_test.py \ --recipe-dir <RECIPE_DIR>

已存在时暂停询问用户:保留现有(默认)或重新生成(重新生成需追加--overwrite)。若脚本因找不到agent.py而报错,把信息展示给用户,待其指明入口后以--agent-file <path>重跑——这是唯一一个有定义恢复路径的error情况。

生成器(generate-python-runnability-test/SKILL.md)会:安全遍历 recipe 找到最浅层agent.py;用ast解析agent.py及每一个祖先包__init__.py检测导入期副作用(vertexai.init(...)google.auth.default())与环境变量读取;扫描全树找INTEGRATION_TEST读取(该约定是每个包的:agent.py常在模块加载时调用位于别处的 helper,只扫agent.py会漏);然后生成两种形态的测试——无副作用时是极简形态,有副作用时是受保护的(guarded)形态:测试函数顶部setdefault环境变量,with patch(...):块包住 import,断言放在with块外。

真实产物可参考 contrib/python/brand-search-optimization/tests/test_runnability.py:os.environ.setdefault("GOOGLE_CLOUD_PROJECT", "test-project")with patch("google.auth.default", return_value=(MagicMock(), "test-project")):包裹import brand_search_optimization.agent,再断言root_agent is not None

生成器还会检查import_support(导入能否解析的四种途径:installable[build-system]pythonpath-inipythonpath = ["."]existing-conftest已有根 conftest、generated-conftest技能写了tests/conftest.py路径垫片),并把每个warnings原样转达。若conftest_actionskipped(已有 conftest 未被覆盖),说明垫片可能缺失,需记入摘要的 Manual TODO。

阶段 7:验证(编译 + 运行)

对生成(或既有)的tests/test_runnability.py做两级递进检查。测试设计为无副作用(patch 掉vertexai.initgoogle.auth.default),因此两步骤都不需要.env、ADC 或网络:

uv run --no-project python3 -m py_compile <RECIPE_DIR>/tests/test_runnability.py

编译必须用uv run --no-project python3:受保护的测试带多个 patch 时会输出带括号的with (...):块,这是Python 3.10+ 语法,在旧系统解释器下会报出虚假的SyntaxError;uv 托管解释器是 3.11+,因此这是真实的语法检查。

uv run --no-project --with pytest pytest tests/test_runnability.py -q

运行需workdir = <RECIPE_DIR>,使 pytest 的 rootdir 与用户自行运行测试时一致。为什么运行而不是--collect-onlypy_compile只解析,import 无法解析的测试也能通过;而--collect-only也不行——受保护形态把 import 放在测试函数内部、with patch(...)块之下,收集阶段导入测试模块时根本不会触达 recipe 模块。只有真正运行测试才执行到 import。

第三方ModuleNotFoundError在这里是预期而非发现:阶段 5 只跑了uv lock没跑uv sync,recipe 依赖未安装。按错误中模块名分类:

  • 模块名是依赖vertexaigoogle.adkpandas)→ 预期,汇报deps not installed;此结果对导入路径无结论性(依赖失败先于 recipe 自身 import 触发),应回退用阶段 6 的import_support字段回答该问题。
  • 模块名是 recipe自己的顶层模块(阶段 6module_name的首段,如scripts.agent中的scripts)→ 真实发现,导入路径损坏,无论装什么测试都不会通过。

六种结果及对应进度行:

情况判定进度行
编译 0、测试通过passPhase 7 (verify): compile OK, test passes.
编译 0、失败于依赖pass with notecompile OK; test not run (<module> not installed — run uv sync). Import path: <import_support>
编译 0、失败于 recipe 自身模块failcompile OK but <module> is not importable.(记 Manual TODO,常见原因是缺[build-system]且无 conftest 垫片)
编译 0、断言失败(root_agent is Nonefail真实 recipe 缺陷,原样汇报
编译非 0fail打印 stderr 到摘要作为 Manual TODO,跳过 7c(解析不过的文件无法运行),不诊断、不重试、不自动修复
文件缺失skipskipped (no tests/test_runnability.py to check).

永远不要因阶段 7 而 halt 流水线——阶段 8 照跑、摘要照打。同时要诚实:deps not installed意味着阶段 7 并未证明 recipe 能运行,真正的确认在 "Next steps" 的手动uv sync && uv run pytest

阶段 8:仓库自有校验器终检

最后运行,是刻意保持薄的包装层:检查逻辑都住在tools/.github/policy.yml,在此重实现任何一条都必然产生漂移。

uv run validate manifest <RECIPE_DIR> uv run validate structure <RECIPE_DIR>

两者都从仓库根目录以仓库根相对路径运行,绝不用绝对路径;两者失败时都非零退出,但不套用规则 7 的 halt——阶段 8 是最后一步,其失败是待汇报的发现而非崩溃。解读输出时区分两类失败:

  • 所有权占位符失败是预期的ownership.team/ownership.poc仍持有规范占位符时校验器故意失败,直到人类替换。摘要中汇报为expected,并作为 TODO 清单第 1 项。
  • 其余都是真实发现:缺必需文件/目录、超尺寸限制、schema 错误、命名违规——逐条原样列出并给出修复。

若两个校验器的唯一失败正是两个所有权占位符,recipe 即处于预期终态,应直说而非当作失败展示。

为什么阶段 8 存在(历史教训)

流水线曾经在阶段 7 结束并报告干净运行,而uv run validate structure却失败——recipe 通过了流水线建模的所有阶段,仍被 CI 拒绝。典型例子是漏了tests/unit/目录。在技能内重实现策略检查必然产生漂移,因此流水线把仓库自有校验器当作最终裁决者("the repo's own validators as the last word")。

阶段 0:计划与确认(总是最先做)

正式流水线之前还有四步前置检查,这是本技能较新版本新增的防御层:

0a — 验证 recipe 目录真实存在

[ -d <RECIPE_DIR> ] || { echo "Recipe directory not found: <RECIPE_DIR>"; exit 1; }

路径拼写错误不应让用户白白走完计划确认往返后在阶段 1 才失败。不是目录则立即停止,不展示计划、不提示。

0b — 验证目录名符合 CI 命名规则python-validate-recipe.yml的 Check 1 拒绝不匹配^[a-z][a-z-]*$或超过 .github/policy.ymlrecipe_naming.max_folder_name_length(当前值 30)的目录。历史上流水线对此盲目——会对data_scienceMyBadName跑完全部阶段、报告成功,让 CI 晚些时候拒绝 PR(更糟的是阶段 3 的project-name-matches-folder会把坏名字传播进[project].name)。用 check_folder_name.py 提前拦截:

MAX_LEN=$(uv run --no-project --with pyyaml python3 .github/scripts/load_policy.py recipe_naming.max_folder_name_length) uv run --no-project python3 .agents/skills/prepare-python-recipe/scripts/check_folder_name.py \ --recipe-dir <RECIPE_DIR> --max-length "$MAX_LEN"

该脚本(纯标准库,可被uv run --no-project python3调用)合规时静默退出 0;违规时退出 1 并列出具体违规字符、超长部分,以及从当前名派生的建议合规名(转小写、_-、丢弃非法字符、按连字符边界截断)。建议仅供参考——脚本绝不重命名任何东西,并输出手工git mv命令。失败则在整个流水线开始前 HALT:原样打印 stderr,不展示计划、不提示继续、不问"要我重命名吗"——重命名目录是用户的决定,他们手工改名后重新调用技能。

0c — 对skills/下的 recipe 检查必需目录。.github/policy.yml 的required_dirs.by_root.skills为每个垂直技能强制固定形状:scripts/assets/references/tests/unit/。八个阶段都不会创建这些目录,缺失者会活过整个流水线然后在阶段 8(及 CI)失败。core/contrib/recipe 完全跳过此步(两者required_dirs.by_root为空)。这是信息性检查而非 halt;空目录即满足检查,而 git 无法提交空目录,所以修复方式是.gitkeep

mkdir -p <RECIPE_DIR>/tests/unit && touch <RECIPE_DIR>/tests/unit/.gitkeep

在 0d 的计划消息中提及缺失目录并提供创建选项,用户同意才创建并记入摘要 "Files created";拒绝则转入最终 TODO 清单。不得未经询问就创建

0d — 展示计划并取得确认。先扫一眼 recipe 有无非标准情况(包不叫app/.env.example不在根、缺tests/、多余 Python 源码目录、AGENTS.md提到的弃用模型字面量),影响流水线的要简要标注。然后以"我在假设这些——如果哪条不成立请说明"的方式展示假设(已停用 venv、已在根目录git pull+uv sync、recipe 已在目标路径并改好名),再列出八阶段计划,最后以 "Nothing gets committed — you'llgit diffat the end. Proceed?" 结尾征求一个明确的 yes/no。用户说不就停止。

Agent 规则:什么时候停、什么时候继续

九条规则定义了编排者的行为边界(原文 SKILL.md 的 "Rules for the Agent"):

  1. 开场索要--recipe-dir,八个阶段都作用于同一 recipe。
  2. 开始前确认:展示计划 + 目标路径,取得一次性 "go ahead";此后除规则 5/6 外不再逐阶段询问。
  3. 直接调用子技能脚本而非子技能自己的 agent 向 SKILL.md——因为子技能各有 "want me to apply?" 提示,主编排模式下用户已对整个流水线 opt-in,逐条提示是噪音。
  4. 纯指令技能的例外generate-manifest无脚本,只能通过skill工具加载其 SKILL.md 内联执行。
  5. 固定检查点——此处必须暂停
    • 阶段 3 返回description-matches-manifestneeds_input→ 展示两侧文本,请用户选pyproject/manifest/delete
    • 阶段 6 前若tests/test_runnability.py已存在 → 询问是否重新生成(默认保留,重新生成用--overwrite);
    • 阶段 6 找不到入口点 → 展示信息并待用户指明后以--agent-file <path>重跑(唯一有恢复路径的error);
    • 子脚本标记的任何其他error→ 展示信息、停流水线、不重试。
  6. 判断式打断——真正有帮助时才暂停:出现意外检测(如has_root_agent: false)、manifest 推断与你计数不符、env 提取一次性新增 ≥ 10 个变量、align 的requires-python重写掉 README 声称支持的版本、uv lock记录可疑依赖、非标准布局、或正确答案依赖 recipe 之外的知识。不要为这些打断:进度更新、装饰性好奇、以及"答案不会改变下一步"的"只是想确认"式提问。打断时要给出具体担忧、相关数据和明确选项,而不是一句"这看起来 OK 吗?"。
  7. 硬错误 halt:任何阶段脚本以非refused_overwrite的非零码退出就停止,打印阶段名、错误与已做工作。阶段 3 例外:align 只要存在report_only检查就以1退出——从 JSON 判断而非退出码,只有error(或意外的needs_input/would_fix)才 halt。
  8. 紧凑汇报:每阶段一行Phase N (<name>): <one-line outcome>,不倾倒 JSON、不重绘子技能表格;判断式打断另起一轮(提问、等答案)。
  9. 绝不提交:摘要打印即技能完成,git diff与 commit 交给用户。

输入

字段必填说明
Recipe directoryrecipe 根路径(如core/python/cross-session-memorycontrib/python/my-recipeskills/retail/store-ops),作为--recipe-dir传给每个子脚本

用户未指定时先询问再继续。

收尾汇报格式:摘要表、文件清单、未尽事项、TODO

流水线运行中每阶段打一行进度;同时跟踪三类信息供结尾汇报:每个创建/修改的文件、每件尝试过但未完成的动作、每件需人工跟进的延迟项。结尾按四个板块输出(第 3 节为条件性,无内容则整节省略;第 1、2、4 节总是输出)。

1. 摘要表:八行(阶段 / 结果 / 备注),结果列用平实词(ok/skipped/failed),除非用户要求否则无 emoji。阶段 8 仅当唯一失败是两个所有权占位符时为ok(这是预期终态而非缺陷)。

2. 创建或修改的文件:分CreatedModified两组列短列表,大组聚合(如 "12.pyfiles formatted (Phase 4)"),未触碰的省略。若什么都没改,输出Nothing changed — the recipe was already fully aligned.

3. 尝试但未完成的事(有内容才打印):halt 的阶段(含命令与 stderr 片段、明确哪些阶段因此未运行)、阶段 4 无法自动修复的 ruff 违规(<file>:<line> — <codes>)、阶段 6 conftest 垫片被跳过、阶段 7 编译失败或 recipe 自身模块 import 失败、阶段 8 除两个占位符外的真实校验发现。

4. 你还需要做什么

  • 标准项(总是列出):① 打开manifest.yaml填入ownership.team/ownership.poc真实值(CI 校验故意在占位符未替换前失败;若 manifest 原本就有真实值则只是确认);② 填写.env.example中每个<TODO: ...>占位符(或删除未用变量行);③cd <RECIPE_DIR> && git diff审查所有改动后再提交。
  • 条件项(仅当对应阶段提出时):阶段 3build-system(参考 align-recipe-pyproject/SKILL.md 中的 hatchling / uv_build 模板;若阶段 6 已写 conftest 垫片,补上 build-system 后垫片即冗余可删)、pypi-index非公共 PyPI 需确认是否有意、stale-python-version-refs按可执行文件优先列出、testpaths需加"tests"、缺失必需目录补.gitkeep、其他校验发现逐条带修复。
  • 命令(总是展示)
cd <RECIPE_DIR> uv sync # install deps into .venv/ (Phase 5 only ran uv lock) uv run pytest tests/test_runnability.py -v # confirm the runnability test actually passes # commit when you're happy

最后停止,不提交,结束回合。

从源码看这套流水线的工程价值

从仓库证据可以总结出这套设计的三个核心工程判断:

  1. 策略不重实现、只委托:八阶段中的检查逻辑(manifest schema、pyproject 规则、命名/尺寸策略)全部外置到 tools/validate_manifest.py、tools/validate_structure.py、.github/policy.yml 与 CI 工作流 python-validate-recipe.yml,技能只做排序与裁决,从根上避免策略漂移。
  2. 把 CI 的坑提前到本地踩:显式uv lock --python 3.11对齐 CI 固定解释器、阶段 0b 的目录名预检、阶段 8 的仓库校验器终检,都是把"PR 被 CI 拒绝"的常见原因转化为流水线内可操作的提前失败。
  3. 自动化与人的边界清晰:占位符故意不替换、目录不重命名、不提交、不自动添加部署文件——自动化只做可证明安全的部分,其余全部显式留给人工 TODO,避免产生用户不想要的变更。

【免费下载链接】adk-samplesA collection of sample agents built with Agent Development Kit (ADK)项目地址: https://gitcode.com/GitHub_Trending/ad/adk-samples

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询