任务:运行上下文带上产品的构建,用例定位装上构建候选检查(能力 3 的收尾)
用例定位要给出“同一版本线下两个名称族的构建,别名解析到它所依据的构建”,现在 build_candidates 记“未核对”,因为检查看不到知识库的构建。这个任务加一个通用的、按需开启的运行上下文字段,再装上检查。
- 分支和工作树:
hub-builds,目录circle-hub-builds - 可以改的路径:
contracts/src/pack.ts、contracts/src/run.ts(只加下面规格里写的)、contracts/generated/**(只通过生成器)、hub/runs/engine/**、hub/runs/README.md、packs/workflow/case-location/**。别的路径不动。 - 验证前提:先读
AGENTS.md和docs/hub-r4-handoff.md(规则、命令、已知问题都在那里)。提交只暂存明确的路径,git commit -s,一句首字母大写的英文祈使句,不加前缀和句号,空一行后写你自己的署名行;不推送、不建 PR;不碰 7420 上的持久部署、钥匙串、环境配置文件和任何真实系统;测试只用合成数据。 - 完成后在终端里回报:提交号、测试通过/跳过/todo 的数量、没做完或拿不准的地方、发现的别处的缺陷(写清失败的场景,不要自己去改别人的路径)。
- 版本:
case-location升到 1.1.0 并重新签(node packs/workflow/case-review/packaging.ts sign case-location);不发布,不部署。 - 验证:
npx tsc --noEmit;node tools/gen-contracts.ts --check;node --test --test-concurrency=2 "hub/runs/**/*.test.ts" "packs/workflow/case-location/**/*.test.ts" "contracts/**/*.test.ts"。 - 复核重点(自己做完再对照一遍):Is the builds list in the context exactly the knowledge base builds of the bound product (both name families, an alias carries its base, sorted deterministically), frozen with the run record so that an evaluation after a restart sees the same list, absent (not empty-looking) for workflows that did not ask for it? Is the case-location check correct on hand-built cases: the located version line gives exactly the builds of that line of both name families, an alias is shown with the build it is based on, a written build name that the knowledge base does not know or that belongs to another line is said so, an unknown line or a line without builds is an unknown outcome and never a failure or a pass, and the outcome does not depend on the order of the builds? Do existing tests and the real registry publish check still pass, and is the pack version bumped and re-signed?
第二件事:空的条目集是合法的答案(同一个分支,先做这一件)
回归范围、维护巡检这类只产生事实的生产运行,“没有任何条目”是正确的结果(两个构建之间没有变更、没有要维护的用例),不是拒收。模型元素 W01 R[3]:整批不受理只用于源结构本身投影不出条目(找不到声明的工作表或表头),以及作为生产输入的源编号不唯一;投影函数成功返回、条目集恰好为空,不在其中。现在引擎在 start_run 时把空条目集当拒绝(在 hub/runs/engine 里找“投影没有给出任何条目”一类的检查),回归范围和维护巡检两个包因此只能在 README 里写明“空范围会被引擎拒绝”。
要做的:
- 投影函数成功返回、条目集为空时,运行照样创建。生产运行存下的验证结果所有分区为空,
coverage为complete: true, examined: 0, total: 0,运行级的要求项照常评估;start_run的回答文字说“没有条目”,并带上投影函数留下的说明(warnings、note)。非生产运行(要模型提交的)条目集为空时start_run同样成功,回答里写明没有可评审的条目。 - 投影函数自己返回的失败(例如用例评审的“没有用例”)仍然拒绝,不受影响;源结构投影不出条目、生产输入编号不唯一的拒收照旧。
- 读 W01、V05 和
hub/runs/engine里现有的测试:凡断言“空条目被拒”的,改成新规则并在提交说明里列出;补测试:成功返回空列表的投影、空的生产运行(存下的结果、分区、覆盖、回答文字、get_nodes按引用读)、投影失败仍拒绝。 - 做完后,把
hub-6b-grok分支合并进这个分支做一次检查(git merge,不改它们的包):回归范围和维护巡检在空范围、没有维护项时给出存下的结果。它们 README 与测试里“引擎拒绝空条目”的几处,在回报里列出,由包的作者改。
第三件事:条目位置按 FragmentRef.source 选源(同一个分支,最后做)
两个包(用例定位、缺陷转用例)都碰到同一处:一个输入槽里绑了多份源(many: true)时,引擎解析条目位置会在槽内所有源上都试一遍,并硬性要求恰好一份解析得出(hub/runs/engine/projection.ts,FragmentRef.source 没有被用来选源);文档里节点编号重复时就被拒为 ambiguous_location,包只能绕着走(例如缺陷转用例把选择器写成 p/<编号>)。要做的:投影函数给出的 FragmentRef 带 source(源的 SHA-256)时,只在这份源上解析;没带时行为不变。补测试(两份源节点编号相同、带 source 时各自定位成功、不带时仍然拒为歧义、source 不在槽里时报错),并在 packs/workflow/case-location 与 packs/workflow/case-review 的 README 里已有的“需要引擎配合”处划掉这一条(只改 case-location 的,它在你的范围内;case-review 不动,写进回报)。
规格
PACKAGE builds-context - capability 3 (case location) needs the build candidates of the located version line, “both name families, aliases resolved” (brief section 6a item 3, model element K01 R[10]); today packs/workflow/case-location records build_candidates as unchecked because checks cannot see the builds the knowledge base knows. Read packs/workflow/case-location/README.md (decisions and “Needs from other packages”), requirements.json, workflow.json, checks.json and its functions first, then hub/ports.ts (KnowledgePort.builds, resolveBuild), contracts/src/product.ts (BuildInfo, KnownBuild: family, line, base, platform, built_at, released_at), contracts/src/pack.ts (RunContext, the workflow declaration), contracts/src/run.ts (RunRecord, groups is the model to follow), hub/runs/engine/start.ts (where the context is built and frozen) and evaluate.ts (runContextOf). Design (keep it this small and generic, no product names in core): (1) an opt-in on the workflow declaration (workflow.json), for example “context”: [“builds”], validated by contracts/src/pack.ts and documented there; (2) a RunContext field builds (optional, so existing fixtures stay valid) holding for the bound product every build the knowledge base knows, as {name, family, line, base, platform, built_at, released_at, has_root} (no sources), sorted deterministically (line, built_at, name), filled only when the workflow asked for it and the run is bound to a product; (3) the same list frozen in the run record (RunRecord optional field, like groups) so runContextOf gives checks and functions the same list after a restart; the start_run summary and answer text do not show it; (4) projection, expected-source and check functions all receive it through the existing context argument; sandbox input validation accepts it. Nothing else in core changes. Then packs/workflow/case-location: declare the opt-in, replace the unchecked build_candidates by a real fact check (function, per item = per document, tier advisory for the cross-checks and support/unknown for the candidates): the candidates are the builds in the context whose line equals the located version line, of every name family, each shown as {name, family, base, alias: name differs from base, platform, released}, sorted (released first by date descending, then name); a claim with the candidates as data and a one-line Chinese statement; the written build names (the pack already extracts them from folder and title, see decision 6 and build_names in the README) are classified against the context as known (equal to a candidate or an alias of one), known but of another line (advisory violation, code location.build_other_line, naming the line it belongs to), or not known to the knowledge base (an unknown outcome with the reason, never a violation: the knowledge base lists only builds of the build site); no located line, or a line without any known build, is an unknown outcome with that reason (never a pass). Order of the context builds never changes the outcome. Update requirements.json, checks.json, samples (positive and negative for the new check), README (decision records and the Needs section: the build part is resolved, the other requests stay), SKILL.md (tell the model what the candidates mean and that an unknown outcome is not an error), bump the pack version to 1.1.0 and re-sign it (look at packs/workflow/case-location for how the other packs are signed, for example api.ts / packaging.ts). Tests (write them first): the contracts (the opt-in is validated, the context field is optional, a strict object still rejects unknown keys), the engine (a workflow that asks gets the builds of the bound product frozen in the run record and the same list from runContextOf; one that does not ask gets none and stores none; a run bound to no product gets none), the pack check on hand-built contexts (two name families with an alias, a line with no builds, a written name of another line, an unknown written name, shuffled order, 2,000 builds for speed), the publish check through the real registry, and one end-to-end run with the engine and a fake knowledge port that lists builds. Existing tests of hub/runs and packs/workflow/case-location must still pass; run them all at the end together with npx tsc –noEmit and node tools/gen-contracts.ts –check.