feat(delivery/mcp): get_delivery_status 支持按 pr_number/branch 查询,结论绑定 Gitea head SHA(使者回传 #203) #32

Merged
lanrtop merged 3 commits from feat/delivery-status-by-pr into master 2026-10-03 05:36:38 +08:00
Owner

目标

使者回传 #203(Enterprise 2026-10-03 实测):为避开主工作区里其他会话的在制品,在独立 worktree 分支上开 PR 交付时,get_delivery_status 只读项目主工作区当前分支——返回「当前分支没有开放 PR」,CI 停在主工作区 HEAD,传 pr_number 也被忽略,只能改用 git ls-remote + get_ci_status(commit_sha) 兜底。

本 PR 让 get_delivery_status 支持可选 pr_number(优先)与 branch:给定时经 Gitea 取该 PR / 分支的 head 分支与 head SHA,PR/CI/review 结论绑定该 head SHA;都不给时保持原行为。蓝图卡:project-capability-control-plane P3-F。

改动

  • 能力本体 commands/delivery_status.rs
    • 新增 DeliveryQuery:取值校验单点实现(pr_number 须为正整数;branch 按 git check-ref-format 主要约束校验),显式给出的非法值直接报错,不静默回退主工作区。
    • DeliveryStatus 新增顶层 target:mode(local_branch / pull_request / branch)、pr_number、branch、head_sha、source(gitea / local_git)、detail。git 字段仍始终反映主工作区。
    • 业务函数连接与凭证存储均由调用方注入(新增 _with_store 变体供合成 Gitea 测试),不在内部 pool().get()。
  • Gitea 封装 commands/gitea.rs
    • Gitea 读取拆为三种目标 DeliverySignalTarget::{Local, PullRequest, Branch},共用 GiteaRepoApi(沿用 gitea_get_json / api_err 脱敏)。
    • pr_number:GET /pulls/{n} 取 head 分支与 head SHA → statuses/{head_sha} → pulls/{n}/reviews;PR 状态归一为 open / merged / closed;404 返回 not_found(与不可达的 unavailable 区分);同时传入的 branch 与 PR head 分支不一致时以 pr_number 为准并在 detail 提示。
    • branch:匹配该分支的开放 PR,以其 head SHA 查 CI;没有开放 PR 时读 GET /branches/{branch} 的 head SHA;远端分支不存在时 CI 为 unknown。
    • pull_request.data 增加 head_sha(增量字段)。merge_pull_request 门禁代码未改。
  • MCP mcp_tools.rs:schema 增加可选 pr_number(integer, minimum 1)与 branch,描述说明默认行为与 worktree 场景;dispatch 只做 JSON 类型解析后交给 DeliveryQuery::new;文本摘要加入「目标=PR #n(head 分支 …,head SHA <完整 40 位>)」,不读 structuredContent 的客户端也能看到要确认的 SHA。
  • 接入包模板:lian-jing skill 第 6 条改为合并前调用 get_delivery_status(project_id, pr_number);BASE_ONBOARDING_PACK_VERSION、模板 capability-packs.json 1.8.0 → 1.9.0,TEMPLATE_FINGERPRINTS 更新。Codex 插件 skill(plugins/lian-jing-codex)第 5 条同步。
  • 契约文档:docs/ai-context/project-context.yaml「MCP 工具接口」补充新参数、target 字段与回退规则。
  • 蓝图:P3-F 两阶段提交(🔵 立卡 commit → ✅ 完成),manifest 模块 note 同步。

自验

  • cargo test --locked(CARGO_TARGET_DIR 独立):lib 282 passed / 0 failed / 5 ignored;main 与 doctest 0 项,全部通过。
  • 新增 / 加强的测试:
    • pr_number_target_binds_pr_ci_and_review_to_gitea_head_sha:合成 Gitea,主工作区路径不存在(git=unavailable)时,target.head_sha、pull_request.data.head_sha、ci.data.target_sha 都是 PR head SHA,review 读取 /pulls/7/reviews,branch 不一致时给出提示。
    • missing_pr_is_not_found_rather_than_main_workspace_fallback:404 → not_found,CI unknown,不编造 head SHA。
    • branch_target_prefers_open_pr_head_then_remote_branch_head:分支有开放 PR / 无开放 PR(GET /branches/feat/no-pr)/ 远端分支不存在三种情况。
    • delivery_query_rejects_invalid_explicit_targets_instead_of_falling_back、delivery_status_rejects_invalid_target_before_io(MCP 层在任何 IO 前拒绝 0、"31"、非字符串 branch、../main)。
    • delivery_status_schema_offers_optional_pr_and_branch_targets(全局与 scoped catalog)、delivery_summary_names_the_queried_target_and_full_head_sha、delivery_pr_state_prefers_merged_and_never_guesses_unknown、branch_path_keeps_separators_and_encodes_segments。
    • no_gitea_binding_does_not_fabricate_delivery_success 增加默认 target.mode=local_branch 与未绑定时按 PR 查询不编造 SHA 的断言。
    • 既有 merge_gate_* 测试原样通过;managed_template_fingerprints_track_versions 以 1.9.0 新摘要通过。
  • 对改动文件跑 rustfmt --check,git diff --check 通过。

没验什么

  • 没有用运行中的炼境实机调用新参数。 用户的日常实例在主仓库跑 master 代码;按约束不改主工作区,也没有另起第二个实例。合并并重建/重启后,需要实机对一个 worktree 分支 PR 调用 get_delivery_status(project_id, pr_number),核对 target.head_sha 与 Gitea PR head 一致、CI 与 review 指向该 PR。
  • 真实 Gitea 1.22 对 GET /branches/feat/x(分支名中的 / 不编码、逐段编码其余字符)的路由只在合成服务器上验证过。依据是 Gitea 的 /branches/* 通配路由,未在真实实例上实测。
  • Fork PR(head 在其他仓库)未覆盖,CI 统一按 base 仓库的 statuses/{head_sha} 查询。
  • 开放 PR 列表仍只取前 50 条(与原行为一致)。branch 模式下开放 PR 超过 50 个时可能匹配不到,此时会转为读远端分支 head。
  • 接入包 1.9.0 需要重建安装炼境后再 apply_onboarding_pack 才会分发;Enterprise 等子项目尚未升级。炼境自身根目录的 .agents/skills/lian-jing 副本未同步,按惯例由 apply 更新。
  • git-workflow.md.tmpl 与 docs/ai-context/git-workflow.md 中 get_delivery_status 的说明只描述默认行为。内容仍然准确,但没有提到 pr_number;改这个托管块需要另升块版本,本 PR 未处理。
  • 未跑 pnpm typecheck:本 PR 不改前端代码或类型(get_delivery_status 不是 Tauri command,commands.ts 无对应封装),PR CI 会跑。
  • gitea_get_json 没有显式超时(原有行为),PR / 分支模式沿用。

兼容性

  • 不传 pr_number / branch 时,PR/CI/review 的取值与原行为一致。新增的顶层 target 和 pull_request.data.head_sha 都是增量字段。
  • merge_pull_request 没有改动,合并前仍会重新读取 PR、head SHA、CI 与 review。

🤖 Generated with Claude Code

## 目标 使者回传 #203(Enterprise 2026-10-03 实测):为避开主工作区里其他会话的在制品,在独立 worktree 分支上开 PR 交付时,`get_delivery_status` 只读项目主工作区当前分支——返回「当前分支没有开放 PR」,CI 停在主工作区 HEAD,传 `pr_number` 也被忽略,只能改用 `git ls-remote` + `get_ci_status(commit_sha)` 兜底。 本 PR 让 `get_delivery_status` 支持可选 `pr_number`(优先)与 `branch`:给定时经 Gitea 取该 PR / 分支的 head 分支与 head SHA,PR/CI/review 结论绑定该 head SHA;都不给时保持原行为。蓝图卡:`project-capability-control-plane` P3-F。 ## 改动 - **能力本体 `commands/delivery_status.rs`** - 新增 `DeliveryQuery`:取值校验单点实现(`pr_number` 须为正整数;`branch` 按 git check-ref-format 主要约束校验),显式给出的非法值直接报错,**不静默回退主工作区**。 - `DeliveryStatus` 新增顶层 `target`:`mode`(`local_branch` / `pull_request` / `branch`)、`pr_number`、`branch`、`head_sha`、`source`(`gitea` / `local_git`)、`detail`。`git` 字段仍始终反映主工作区。 - 业务函数连接与凭证存储均由调用方注入(新增 `_with_store` 变体供合成 Gitea 测试),不在内部 `pool().get()`。 - **Gitea 封装 `commands/gitea.rs`** - Gitea 读取拆为三种目标 `DeliverySignalTarget::{Local, PullRequest, Branch}`,共用 `GiteaRepoApi`(沿用 `gitea_get_json` / `api_err` 脱敏)。 - `pr_number`:`GET /pulls/{n}` 取 head 分支与 head SHA → `statuses/{head_sha}` → `pulls/{n}/reviews`;PR 状态归一为 `open` / `merged` / `closed`;404 返回 `not_found`(与不可达的 `unavailable` 区分);同时传入的 `branch` 与 PR head 分支不一致时以 `pr_number` 为准并在 detail 提示。 - `branch`:匹配该分支的开放 PR,以其 head SHA 查 CI;没有开放 PR 时读 `GET /branches/{branch}` 的 head SHA;远端分支不存在时 CI 为 `unknown`。 - `pull_request.data` 增加 `head_sha`(增量字段)。`merge_pull_request` 门禁代码未改。 - **MCP `mcp_tools.rs`**:schema 增加可选 `pr_number`(integer, minimum 1)与 `branch`,描述说明默认行为与 worktree 场景;dispatch 只做 JSON 类型解析后交给 `DeliveryQuery::new`;文本摘要加入「目标=PR #n(head 分支 …,head SHA <完整 40 位>)」,不读 structuredContent 的客户端也能看到要确认的 SHA。 - **接入包模板**:lian-jing skill 第 6 条改为合并前调用 `get_delivery_status(project_id, pr_number)`;`BASE_ONBOARDING_PACK_VERSION`、模板 `capability-packs.json` 1.8.0 → 1.9.0,`TEMPLATE_FINGERPRINTS` 更新。Codex 插件 skill(`plugins/lian-jing-codex`)第 5 条同步。 - **契约文档**:`docs/ai-context/project-context.yaml`「MCP 工具接口」补充新参数、`target` 字段与回退规则。 - **蓝图**:P3-F 两阶段提交(🔵 立卡 commit → ✅ 完成),manifest 模块 note 同步。 ## 自验 - `cargo test --locked`(`CARGO_TARGET_DIR` 独立):lib **282 passed / 0 failed / 5 ignored**;main 与 doctest 0 项,全部通过。 - 新增 / 加强的测试: - `pr_number_target_binds_pr_ci_and_review_to_gitea_head_sha`:合成 Gitea,主工作区路径不存在(`git=unavailable`)时,`target.head_sha`、`pull_request.data.head_sha`、`ci.data.target_sha` 都是 PR head SHA,review 读取 `/pulls/7/reviews`,branch 不一致时给出提示。 - `missing_pr_is_not_found_rather_than_main_workspace_fallback`:404 → `not_found`,CI `unknown`,不编造 head SHA。 - `branch_target_prefers_open_pr_head_then_remote_branch_head`:分支有开放 PR / 无开放 PR(`GET /branches/feat/no-pr`)/ 远端分支不存在三种情况。 - `delivery_query_rejects_invalid_explicit_targets_instead_of_falling_back`、`delivery_status_rejects_invalid_target_before_io`(MCP 层在任何 IO 前拒绝 `0`、`"31"`、非字符串 branch、`../main`)。 - `delivery_status_schema_offers_optional_pr_and_branch_targets`(全局与 scoped catalog)、`delivery_summary_names_the_queried_target_and_full_head_sha`、`delivery_pr_state_prefers_merged_and_never_guesses_unknown`、`branch_path_keeps_separators_and_encodes_segments`。 - `no_gitea_binding_does_not_fabricate_delivery_success` 增加默认 `target.mode=local_branch` 与未绑定时按 PR 查询不编造 SHA 的断言。 - 既有 `merge_gate_*` 测试原样通过;`managed_template_fingerprints_track_versions` 以 1.9.0 新摘要通过。 - 对改动文件跑 `rustfmt --check`,`git diff --check` 通过。 ## 没验什么 - **没有用运行中的炼境实机调用新参数。** 用户的日常实例在主仓库跑 master 代码;按约束不改主工作区,也没有另起第二个实例。合并并重建/重启后,需要实机对一个 worktree 分支 PR 调用 `get_delivery_status(project_id, pr_number)`,核对 `target.head_sha` 与 Gitea PR head 一致、CI 与 review 指向该 PR。 - 真实 Gitea 1.22 对 `GET /branches/feat/x`(分支名中的 `/` 不编码、逐段编码其余字符)的路由只在合成服务器上验证过。依据是 Gitea 的 `/branches/*` 通配路由,未在真实实例上实测。 - Fork PR(head 在其他仓库)未覆盖,CI 统一按 base 仓库的 `statuses/{head_sha}` 查询。 - 开放 PR 列表仍只取前 50 条(与原行为一致)。`branch` 模式下开放 PR 超过 50 个时可能匹配不到,此时会转为读远端分支 head。 - 接入包 1.9.0 需要重建安装炼境后再 `apply_onboarding_pack` 才会分发;Enterprise 等子项目尚未升级。炼境自身根目录的 `.agents/skills/lian-jing` 副本未同步,按惯例由 apply 更新。 - `git-workflow.md.tmpl` 与 `docs/ai-context/git-workflow.md` 中 `get_delivery_status` 的说明只描述默认行为。内容仍然准确,但没有提到 `pr_number`;改这个托管块需要另升块版本,本 PR 未处理。 - 未跑 `pnpm typecheck`:本 PR 不改前端代码或类型(`get_delivery_status` 不是 Tauri command,`commands.ts` 无对应封装),PR CI 会跑。 - `gitea_get_json` 没有显式超时(原有行为),PR / 分支模式沿用。 ## 兼容性 - 不传 `pr_number` / `branch` 时,PR/CI/review 的取值与原行为一致。新增的顶层 `target` 和 `pull_request.data.head_sha` 都是增量字段。 - `merge_pull_request` 没有改动,合并前仍会重新读取 PR、head SHA、CI 与 review。 🤖 Generated with [Claude Code](https://claude.com/claude-code)
lanrtop added 2 commits 2026-10-03 05:24:11 +08:00
Enterprise 2026-10-03 实测:在独立 worktree 分支开 PR 交付时,get_delivery_status
只读主工作区当前分支,PR/CI 结论与目标 PR 脱节。本卡开始执行,标 🔵。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
feat(delivery/mcp): get_delivery_status 支持按 pr_number/branch 查询,结论绑定 Gitea head SHA(使者回传 #203)
All checks were successful
Push & PR Check / check (push) Successful in 1m0s
Push & PR Check / check (pull_request) Successful in 1m2s
1e3989d0d7
Enterprise 2026-10-03 实测:为避开主工作区里其他会话的在制品,在独立 worktree
分支上开 PR 交付时,get_delivery_status 只读主工作区当前分支,返回「当前分支没有
开放 PR」、CI 停在主工作区 HEAD,传 pr_number 也被忽略,只能用 git ls-remote 与
get_ci_status(commit_sha) 兜底。

- MCP schema 新增可选 pr_number(优先)与 branch;都不给时保持原行为
- pr_number:GET /pulls/{n} 取 head 分支与 head SHA,CI 与 review 均绑定该 PR;
  PR 不存在(404)返回 not_found,与 Gitea 不可达(unavailable)区分;
  同时传 branch 且与 PR head 分支不一致时以 pr_number 为准并在 detail 提示
- branch:匹配该分支的开放 PR 并以其 head SHA 查 CI;无开放 PR 时取 Gitea 上
  该分支 head SHA;远端分支不存在时 CI 为 unknown
- 顶层新增 target(mode/pr_number/branch/head_sha/source/detail),
  pull_request.data 增 head_sha;git 字段仍反映主工作区,既有字段兼容
- 取值校验在能力本体 DeliveryQuery 单点实现,MCP 只解析 JSON 类型;显式给出的
  非法值直接报错,不静默回退主工作区
- Gitea 读取拆为本地/PR/分支三种目标,凭证存储注入以便合成 Gitea 测试;
  merge_pull_request 门禁代码未改
- lian-jing skill 第 6 条改为 get_delivery_status(project_id, pr_number),
  base-onboarding 1.8.0→1.9.0(BASE_ONBOARDING_PACK_VERSION、模板
  capability-packs.json、TEMPLATE_FINGERPRINTS);Codex 插件 skill 同步
- 契约说明同步 docs/ai-context/project-context.yaml;蓝图 P3-F 标 ✅

Feature-Confirmed: true
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lanrtop added 1 commit 2026-10-03 05:34:19 +08:00
fix(delivery/mcp): 补 get_delivery_status 经 scoped dispatch 转发 pr_number/branch 的回归测试(P3-F 审查)
All checks were successful
Push & PR Check / check (push) Successful in 59s
Push & PR Check / check (pull_request) Successful in 1m2s
df5832f41b
使者回传 #203 的症状是「传 pr_number 也不起作用」,但原有 MCP 层测试只覆盖非法参数报错,
dispatch 若丢弃已解析的查询目标、改传默认值,全部测试仍通过。新增 scoped dispatch 正向测试,
断言 pr_number/branch/null 分别得到 pull_request/branch/local_branch 目标;已用变异
(dispatch 改传 DeliveryQuery::default())确认该测试会失败。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lanrtop merged commit 10434d4b71 into master 2026-10-03 05:36:38 +08:00
Sign in to join this conversation.
No reviewers
No Label
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: lanrtop/dev-manager-tauri#32
No description provided.