fix(pipeline): 候选方案与 confirm 前强校验用户 intent 资源覆盖 - #306
Closed
ruanzhengxin-zhuxing wants to merge 2 commits into
Closed
ruanzhengxin-zhuxing wants to merge 2 commits into
ruanzhengxin-zhuxing wants to merge 2 commits into
Conversation
候选方案会静默丢弃用户 intent 中已正确解析的资源(如 ECS/NAT/EIP), 只保留 VPC/VSwitch,而方案名仍声称包含这些资源;confirm_and_select 也没有任何一致性校验,用户因此在不知情的情况下确认了不完整的方案。 根因有两处: - architecture_planning 没有 completion_guards,且 SKILL 中 resource_intents 是可选字段、只有禁止性规则,没有覆盖清单要求。 - confirm_and_select(三种 surface)同样没有 guard,选项 schema 里 也没有资源字段,唯一过滤条件是 failed == false。 修复方式是新增引擎级 completion guard require_resource_intent_coverage: 以 intent.resource_intents 中所有非 forbid 资源为基准,校验每个 candidate / option 都覆盖到,或在 resource_intent_gaps 中显式声明缺口与原因; forbid 资源被覆盖同样报错。guard 在 items_field 缺失时跳过,以兼容 a2a_rich 仅提交选择结果的第二轮。同时补齐 prompt/SKILL 的正向覆盖规则 与选项 schema 的 covered_products / resource_intent_gaps 字段。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
背景
Session
7be8bcd32aa44fd399f3e5bf7ec7db7d等三个会话(UserId 1754580903499898)暴露同一个问题:intent_parsing已经正确解析出用户声明的全部资源(ECS/NATGateway/EIP;VPC/VSwitch/ECS;NatGateway/SnatEntry/EIP),但最终候选模板与confirm_and_select选项只保留了 VPC/VSwitch,ECS/SLB/NAT/EIP 被静默丢弃,而候选名称仍然声称包含这些资源(例如「ECS+NAT公网方案」)。用户因此在不知情的情况下确认了不完整的方案。AnalysisId:
sarpt-auto-2026072900根因
两处都缺少把
resource_intents当作"必须交付清单"的机制:architecture_planning没有任何completion_guards,且iac-aliyun-architectureSKILL 中resource_intents只是可选字段,「资源生命周期约束」章节只有禁止性规则(不要把 use_existing 设计成新建、不要引入 forbid 资源),没有"必须覆盖"这一条。模型少写资源时没有任何拦截。confirm_and_select(repl/a2a/a2a_rich三种 surface)同样没有 guard,选项 schema 里也没有任何资源字段,唯一的过滤条件是failed == false。只要候选评估成功,缺资源的方案就会原样呈现给用户。改动
1. 新增引擎级 completion guard
require_resource_intent_coveragesrc/iac_code/pipeline/engine/resource_intent_coverage.py(新增):collect_resource_intents(context_snapshot, source_fields):从 context 快照按normalize_product(casefold + 仅保留字母数字)归并resource_intents,使NAT Gateway/NATGateway/natgateway视为同一产品。validate_resource_intent_coverage(...):以 intent 中所有action != forbid的资源为必覆盖基准,逐个 candidate / option 校验。覆盖来源同时支持list[str](products/covered_products)与list[dict](resource_intents,其中action == forbid的条目不计入覆盖)。uncovered_resource_intent(未覆盖且未登记缺口)、unexpected_resource_intent_gap(登记了 intent 中不存在的缺口)、invalid_resource_intent_gap(缺口条目缺product/reason)、forbidden_resource_intent_covered(forbid 资源被覆盖)、以及invalid_*系列配置/结构错误。loader.py把 guard key 加入_SUPPORTED_COMPLETION_GUARD_KEYS;complete_step_tool.py增加_validate_resource_intent_coverage分派、resource_intent_coverage_required用户可见文案及其 i18n marker。surface 兼容:
items_field在 conclusion 中缺失时 guard 返回None跳过校验。这样a2a_rich的第二轮(_candidate_selection_response_schema会剥离options,只提交selected_candidate_*)不会被误判失败。2.
pipeline.yaml两处挂载 guardarchitecture_planning:source_fields: [intent.resource_intents]、items_field: candidates、covered_products_fields: [resource_intents, products]、gaps_field: resource_intent_gaps。confirm_and_select:context_fields补入intent(原先没有 intent,无从校验);items_field: options、covered_products_fields: [covered_products]。covered_products(required)与resource_intent_gaps(required: [product, reason])。3. prompt / SKILL 正向规则
iac-aliyun-architecture/SKILL.md:resource_intents改为 candidate 的 required 字段;新增resource_intent_gapsschema;给「资源生命周期约束」补上覆盖清单、缺口登记、以及"所有方案同缺口应先重新设计"三条正向规则;新增本次 badcase 反例(intent 为ECS(create)+NATGateway(create)+EIP(create)时只保留 VPC/VSwitch 属错误输出,方案名叫「ECS+NAT 公网方案」不构成覆盖证明)。architecture_planning.md增加「资源覆盖校对(提交前必做)」。confirm_and_select.md/.a2a.md/.a2a.rich.md增加「用户意图(资源覆盖基准)」{intent}区块、covered_products/resource_intent_gaps字段说明,以及部分满足需标注、不得把有缺口方案作为唯一推荐、全部方案同缺口需在user_prompt中如实披露。4. i18n
新增用户可见文案
resource_intent_coverage_required,make translate后为 zh/es/fr/de/ja/pt 六种语言补齐译文并编译。测试
pytest tests/pipeline/engine/test_resource_intent_coverage.py tests/pipeline/engine/test_complete_step_tool.py tests/pipeline/selling/→ 458 passedtest_resource_intent_coverage.py(新增 13 例):别名归一、非法来源、完整覆盖、逐项缺资源、缺口登记通过、缺口缺 reason 拒绝、未声明缺口、forbid 被覆盖、resource_intents作覆盖来源、forbid 条目不计覆盖、items 非法/为空、无 intent 时跳过。test_complete_step_tool.py(新增 6 例):badcase 复现(candidate 丢弃 ECS/NAT/EIP 时报uncovered_resource_intent[ECS, 0])、别名NAT Gateway视为覆盖、已登记缺口放行、options 缺资源被拒、a2a_rich 仅提交选择结果时跳过校验。test_resource_intent_coverage_guards.py(新增 3 例):两步 guard 字段值、intent在confirm_and_select.context_fields、各 surface option schema 字段契约。test_terminal_ui_contract.py:更新 a2a_rich option required 集合。全量分批串行执行合计约 14350 passed / 4 skipped。静态检查
ruff check、ruff format --check(1082 files already formatted)、ty check src/均通过。已知限制
test_i18n.py::test_message_catalogs_pass_gnu_msgfmt_checks(zh 目录{n} day{s} ago等 5 条存量译文用{s:.0},在改动前的 HEAD 上复现同样 5 处 msgfmt 错误)、test_prerequisites.py中 infraguard 下载错误类型断言(依赖沙箱网络)、test_run_pipeline_contract_scenario.py::test_latest_pipeline_sidecar_reads_nested_session_layout(max(st_mtime_ns)在本环境 mtime 粒度过粗时 tie-break 不确定)。41f73c6是前置的纯格式化提交:仓库 HEAD 在锁定的 ruff 0.15.10 下有 14 个文件存量格式漂移,导致 pre-commit 的 format 钩子每次都改文件并回滚,必须先单独落地格式化,业务提交才能通过钩子。该提交不含任何逻辑改动。Aone: https://project.aone.alibaba-inc.com/v2/project/2169409/req/84817160