Commit Message
【免费下载链接】gemini-cliAn open-source AI agent that brings the power of Gemini directly into your terminal.项目地址: https://gitcode.com/GitHub_Trending/gemi/gemini-cli
[SSR Agent] Issue Fix (<issue_number>): <short_commit_summary>
PR Description
<pr_description_body>
并附有一条“关键格式要求”:`## Commit Message` 与 `## PR Description` 必须是该文件中**仅有的两个 Level 2 标题**(`## `),因为编排器的正则解析器依赖 Level 2 标题来切分段落。 这条约束在源码中得到了逐字印证——`_submit_pull_request` 使用两条正则切段([orchestrator.py#L618-L635](https://link.gitcode.com/i/a438f72d01996e66840cc3df87fe3a74)): ```python commit_match = re.search( r"##\s*Commit\s*Message\r?\n\s*(.+?)(?=\r?\n##|$)", details_content, re.IGNORECASE | re.DOTALL, ) # 以及 desc_match = re.search( r"##\s*PR\s*Description\r?\n\s*(.+?)(?=\r?\n##|$)", details_content, re.IGNORECASE | re.DOTALL, )注意(?:\r?\n##|$)这个前瞻:一旦出现第二个##,切段立即结束。所以若 PR 描述正文内混入 Level 2 标题,解析出的描述会被截断——这正是提示词反复强调“PR 描述内部小节必须用###或更深层级”的原因。
Commit Message 编写规则:
- 格式:
[SSR Agent] Issue Fix (<issue_number>): <short_commit_summary>; - Issue 编号:从
github_metadata.issue_number或原始 spec 中提取整数(如25693); - 短摘要:不超过 10 个词;高层说明修的是什么问题(示例:"Fix skill discovery with single-line description");使用主动、祈使语气("Fix"、"Update"、"Prevent");禁止 "Fix bug"、"Implement spec" 这类空泛摘要。
PR Description 编写规则:
- 正文内的小节标题(Context & Problem、Detailed Changes、Verification 等)必须用
###或更深层级,绝不用##; - 顶部必须显式写出
fixes #<issue_number>,并附上由github_metadata拼出的原始 Issue URL(https://github.com/<owner>/<repo>/issues/<issue_number>); - Context & Problem:读取
workable_spec.summary(problem与root_cause),用 1–2 句说清问题与根因; - Detailed Changes:观察
changes.diff的实际变更,总结更新了哪些文件、加了/修了什么; - Verification:写明实际执行并通过的验证测试(例如 Vitest 单元测试);
- 语气:简洁、结构化、专业;不自称 “I”,而以 “the agent” 或第三人称/被动语态表述。
解析成功的 commit message 会被用于git commit --amend(orchestrator.py#L640-L645)并作为 PR 标题;若pr_details.md缺失或解析失败,系统回退到默认标题[SSR Agent] Issue Fix: issues/{issue_num}与兜底 PR 描述模板(orchestrator.py#L673-L679)。
6.4 约束与崩溃处置协议
提示词结尾的 Constraints 一节划定了评审 Agent 的行为边界:
- 不修代码:职责仅限于评估与报告,绝不自己动手改;
- 不提交/不推送:禁止
git commit、git push等任何远程变更操作; - 反馈范围纪律:在
pr_feedback.md中只提供 diff 内文件的 lint/修订意见,不得鼓励编码 Agent 去改与其目标无关的代码、修无关 lint 错误或重构无关部分; - 崩溃即失败:如果你执行的任何命令(如
npm run lint、npm test)崩溃或返回非零退出码,必须视为确定性失败——立即写入verdict.json(内容为{"verdict": "NEEDS_REVISION"}),把准确的错误堆栈写进pr_feedback.md,然后立刻结束回合,不得再做任何工具调用; - 禁止拖延话术:不得声称“正在后台等待”或“已安排检查”。
这些约束与执行层形成双保险:即使 LLM 越界想跑git push,工具白名单也会拦截——agent_runner.py中注册的pre_tool_call_decidehook 对不在ALLOWED_SANDBOX_TOOLS内的工具调用一律返回REJECT(agent_runner.py#L57-L65)。
7. 编排侧实现:评审沙箱、lint 预跑与 fail-closed 解析
7.1 隔离沙箱:评审副本与符号链接
_run_evaluation(orchestrator.py#L399-L481)为每轮评审构建独立环境:
_clean_eval_dir清空/tmp/eval/<repo>(rmtree+ 重建),防止上一轮状态残留(orchestrator.py#L91-L100);shutil.copytree将编码工作区复制进评审目录,ignore=shutil.ignore_patterns("node_modules")跳过依赖(orchestrator.py#L404-L414);- 若编码工作区已有
node_modules,直接os.symlink复用到评审目录,避免重复npm ci;符号链接失败则回退安装(orchestrator.py#L416-L434); - 依次写入
changes.diff、运行_run_eslint_static_check()、最后才run_agent(role="Evaluator Agent", system_prompt_file="code_evaluator_prompt.md", ...)。
也就是说,提示词中“本地仓库”这一输入项,实际指向的是一份与编码工作区物理隔离的只读性质的评审副本——评审 Agent 即使误操作,也伤不到即将推送的主工作区。
评审 Agent 的运行时配置由 agent_runner.py#L165-L173 构建:LocalAgentConfig(vertex=True, project=..., location=..., model=..., system_instructions=<本提示词全文>, workspaces=[repo_path])。系统提示词通过_load_prompt_file从agent_prompts/目录加载,并带路径穿越防护(agent_runner.py#L99-L121)。模型等参数来自 Job 环境变量(job.yaml#L18-L33):MODEL_NAME=gemini-3.5-flash、GOOGLE_CLOUD_LOCATION=global,GIT_TOKEN取自 SecretPR_GEN_GITHUB_PUSH_KEY。
7.2 关键运行参数
配置集中在 config.py:
| 环境变量 | 默认值 | 说明 |
|---|---|---|
REPO_URL | https://github.com/joneba-google/gemini-cli-clone | 目标仓库地址(默认指向 gemini-cli 的克隆仓库,便于沙箱验证) |
MODEL_NAME | gemini-3.5-flash | 编码/评审 Agent 共用的模型 |
MAX_ATTEMPTS | 5 | “生成 → 评审”最大迭代轮数(max(int(...), 1)) |
FIRESTORE_DOC | 必填 | Issue 规格 JSON,由 workflow 注入 |
FIRESTORE_ID | 由 workflow 拼为github_<owner>_<repo>_<issue> | Firestore 文档 ID |
GIT_TOKEN | Secret 引用 | 用于 push 与创建 PR |
7.3 verdict 的 fail-closed 解析
# orchestrator.py L469-L481(节选) verdict_file = os.path.join(self.config.eval_repo_path, "verdict.json") if os.path.exists(verdict_file): try: verdict_payload = json.load(open(verdict_file)) return str(verdict_payload.get("verdict", "NEEDS_REVISION")) except (json.JSONDecodeError, IOError): ... # 文件缺失同样落到下面 return "NEEDS_REVISION"【免费下载链接】gemini-cliAn open-source AI agent that brings the power of Gemini directly into your terminal.项目地址: https://gitcode.com/GitHub_Trending/gemi/gemini-cli
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考