任务:回归范围与维护巡检的用例一侧独立核对,和未归位用例的披露
依据:集成者 10-23 的终审(能力 4,记在 docs/hub-r4-progress.md)。
- 变更路径和独立的命令树比较逐条相同(31 条),条目 491/491、111/111。但用例一侧不独立:期望条目取的是 Hub 自己
get_nodes里种类为case的条目(scripts/real/accept/scope-cases.ts11–14 行),没有一个 gold 从原始脑图里取命令(scripts/real/gold/cases.ts1–13 行只计数)。 - 没有解析出命令的用例,索引给一条
path为空的条目(packs/product/famx/README.md227–231 行),留在根下,标为未归位(K04 R[6]),不在任何命令路径上,两个包都看不见它们。两包 README 只披露没有用例的路径和跳过的文档(packs/workflow/regression-scope/README.md50–53 行、packs/workflow/maintenance-sweep/README.md46–49 行)。上次是 10-22 量的:84,656 个用例里 58,162 个(docs/hub-r4-progress.md44 行),之后没有重新量。A05 R[0]:没读完不说“没有”。 - 影响视图不带未归位的数(
contracts/src/views.ts56–85 行;合约和知识包有别的分支在改)。分面视图里空列表记为 null(hub/knowledge/views.ts217–230 行),所以knowledge:facets:<产品>:<构建>?kind=case&by=commands里commands为 null 那一行的计数,就是没有解析出命令的用例数。 -
步骤要不要也扫,所有者还没定(
docs/hub-r4-tasks/agile-case-index.md74 行)。这一件不改索引:相等只按标题和上面的标签判,和索引一样;步骤只另量一个数给所有者。 - 分支和工作树:
gold-case-commands,目录circle-hub-gold-case-commands(依赖已装好) - 可以改的路径:新文件
scripts/real/gold/case-commands.ts、scripts/real/accept/command-index.ts和它们的测试;scripts/real/accept/的scope-cases.ts、regression-scope.ts、maintenance-sweep.ts,scripts/real/accept-circle.ts,和它们的测试(含capability-scenarios.test.ts);packs/workflow/regression-scope/**、packs/workflow/maintenance-sweep/**。scripts/real/gold/cases.ts、command-diff.ts和tests/fixtures/case-index/**只导入、不改。别的路径不动(packs/product/famx/**、hub/**、contracts/**有别的分支在改)。这两个包 core-fixes 也在改(生成的取值换掉手写的:两包的functions/check.ts、view.ts、scope.ts或sweep.ts、pack-files.ts和pack.json到 1.6.1,新加functions/generated/vocabulary.ts):第 4、5 步等它合并后,从合并后的hub-redesign开始做;第 1–3、6 步可以先做。 - 规则:同前(不推送、不建 PR、不发布、不部署;不碰 7420、钥匙串、环境配置文件和任何真实系统;测试只用合成数据;
git commit -s)。每步一个提交。两个新脚本不导入hub/、packs/的任何东西;取命令的规则照 README 的文字写,不看packs/product/famx/functions的代码。 - 验证:
npx tsc --noEmit;node --test --test-concurrency=1对scripts/real/**、packs/workflow/regression-scope/**、packs/workflow/maintenance-sweep/**;两包各跑node packs/workflow/<包>/pack-files.ts --check。
要做的
- 从原始脑图取命令:
scripts/real/gold/case-commands.ts,--tree <该构建的命令树.xml> (--map <文件>:<文档编号> … | --maps <清单>) --out <gold.json>,清单每行一个<文件>:<文档编号>。- 认用例用
gold/cases.ts的parseMindMap、caseNodesOf,完整命令路径用gold/command-diff.ts的parseTree(item 的路径才是命令,菜单前缀不是)。这两个本身是独立的 gold,不导入hub/、packs/,用例数和命令差都已和 Hub 逐项对上;借它们读文件格式,不会变成拿 Hub 核 Hub。取命令这一段新写,不借regression-doc.ts(没有缩写,切词也不同)。 - 扫的文字和索引一样:用例标题和它上面的每个标签(含根节点),每段单独扫,路径取并集。
- 规则照
packs/product/famx/README.md172–176 行(短语怎样起止、什么不算命令)和 212–226 行:- 全角字母数字转半角,Unicode 空白和零宽字符转空格,竖向换行算行尾,不做完整 NFKC;
- 命令词是连续的 ASCII 字母、数字、
-、_;短语从某条命令开头的词起,到汉字、全角标点、句读、行尾或闭合的引号括号处断开,引号和反引号里的取到闭合处;粘在命令前的列表序号(1.、2))去掉; - 不收散文:英文停用词或占位词(
xxx)截回命令头;前面是英文词时只留命令头;单独一个词只在引号里、或是夹在汉字里的完整命令头而且后面没写“命令”时才算。停用词表 gold 自己列(README 只说“英文停用词”); - 每个词的位置找最长的完整命令,不分大小写;一个词可以是它那一层唯一的前缀(至少两个字母,大写写法至少三个),靠缩写得到的命令至少两个词,首词缩写不收英文短词(gold 自己列一张小表);树里没有的
no <命令>归到它撤销的命令; - 命令后面的词算参数,到断开处为止,或者遇到另一条至少两个词的命令。
- 编号:
data.id在这份文档的用例里唯一的,键是<文档>:<id>;重复或缺失的标为不比较,只计数。Hub 的位置键和#k键(@开头或#<数字>结尾)也不比较。文档编号去掉agile:case:、agile:mindmap:前缀。 - 输出:命令树字节的 SHA-256;每个用例的键、能不能比、解析出的路径(排好序,每条带
abbreviated、via_no两个布尔值和词数),步骤(用例下面带子节点的子节点,嵌套用例除外)里解析出的路径(只作测量);合计。 - 测试:汉字紧贴命令;内层词和首词的缩写,两个大写字母、单独的缩写、有歧义的前缀都不算;
no的两种情形;列表序号;全角、不换行空格、零宽字符;行尾断开;停用词和占位词截回命令头,英文语境只留命令头,单独一个词在引号里、夹在汉字里、后面写了“命令”三种情形;参数里夹着另一条两个词的命令;不是命令的分组标签(命令前缀、IPv4、带缺陷号的标题);编号重复的不比较;嵌套用例拿到外层标题的命令;读不了的文件、坏的 XML 退出码非 0;4,000 条命令、2 万个用例几秒内跑完。再拿tests/fixtures/case-index/table.ts的手写真值逐行跑(树是catalog.ts的commandTreeXml(CATALOG_A),这两个文件不导入任何代码):对不上的行在测试里列成已知差异,每行写原因,不改表。
- 认用例用
- 和 Hub 的索引视图比:
scripts/real/accept/command-index.ts,--gold <gold.json> --index <视图.json> [--index …] [--out <报告.json>]。视图是knowledge:index:<产品>:<构建>?kind=case&key=document&fields=commands,document,node的导出,大构建按only=分几份。- 条目的路径取自它的树引用(
tree:<根><路径>@<摘要>,未归位的在/),一个用例的条目合起来是 Hub 的命令集合;和条目里data.commands对不上的另计。 - 有一份
truncated为真、cut_keys不空、skipped不是 0(contracts/src/views.ts136 行:这时缺的键是未知,A05 R[0]),或者几份的根不同:判“输入不全”,不判相等。 - 屏幕上只有计数、摘要和判定,不出现编号和命令路径:两边都有、只在 gold、只在 Hub 的文档和用例,不比较的用例;命令集合相等、不等的用例;只在 gold 的路径(其中缩写、
no、单词命令各多少),只在 Hub 的路径;未归位(gold、Hub、两边都、只有 gold、只有 Hub);步骤测量(Hub 未归位的用例里,步骤能解析出命令的个数,不进判定);两边“用例 → 命令集合”表的 SHA-256;末行判定:相等、判定:不相等或判定:输入不全,相等才退出码 0。逐个用例的差异只写进--out。 - 测试:相等;只在一边的文档、用例、路径;两种未归位不一致;条目和
data.commands对不上;截断、cut_keys、skipped、根不同;分几份导出和一份的结果相同;屏幕输出里没有编号和路径。
- 条目的路径取自它的树引用(
- 条目核对的用例一侧换成 gold(
scripts/real/accept/scope-cases.ts):- 加
--later-cases、--earlier-cases(第 1 步在两个构建上各跑一次的输出,各用自己的命令树)。给了就不要--later-nodes、--earlier-nodes:期望的回归范围是后一构建里命令落在新增或修改路径上的用例,期望的维护巡检是前一构建里命令落在删除或修改路径上的用例;不比较的用例两边都去掉,只报个数。 - 两种方式都改成屏幕上只有计数、每张差异表的 SHA-256 和判定,条目编号只写进新加的
--out(现在 260–322 行会把最多 50 个编号打到屏幕上)。 - 测试:同一个小例子两种方式的期望相同;gold 多解析出一条命令时判不相等;不比较的用例不算;屏幕输出里没有编号。
- 加
- 回归范围说出未归位的用例数(
packs/workflow/regression-scope,1.7.0):workflow.json加可选输入槽facets:角色hint(同 15 行的behaviour槽;A03 R[6]:线索只作提示),接受knowledge:facets,写法knowledge:facets:<产品>:<目标构建>?kind=case&by=commands。- 新文件
functions/facets.ts自己解析facet-view@1(包函数只能加载包内模块,照view.ts);view.ts把两个根留下(88–93 行现在只校验)。project.ts照behaviourClue(106–125 行)读这个槽:只收一个,kind是case,by正好是["commands"],build.root等于影响视图的目标根,不符就拒绝(regression-scope.facets_view,写进tables/codes.json,修正说明给出正确写法)。 - 未归位数:
values.commands为 null 那一行的count;没有这一行、视图没截断,是 0;没有这一行、视图截断了,是未知。运行的说明里只放这个数和构建名(note.unplaced,note.message末尾一句),不把视图的行抄进输出(docs/hub-r4-tasks/defect-to-case-compact.md3 行:整份视图进了输出,超了沙箱上限)。 check.ts的uncovered_changes(211–267 行)加一条跨条目结论,data带unplaced和构建名,照 A06 写明缺什么、为什么、出口:- 大于 0:未知(
missing_input):后一构建的用例索引里有 N 个用例没有解析出命令(未归位),不在任何命令路径上,回归范围不含它们,受不受这次变更影响不知道;出口是人工查看,或等归位提议(K04 R[6]); - 等于 0:支持,没有未归位的用例;
- 截断、数未知:未知(
integrity_unproven); - 没绑:未知(
missing_input),未归位的数没有给出,写明怎么绑。
“N 个用例没有解析出命令”这几个字固定,场景按它取数。只用
check.ts已有的Outcome类型和取值;觉得要新的取值,回报给集成者,由集成者在模型里加轴,不要自己加。- 大于 0:未知(
- 测试:上面四种各一;绑不绑分面视图,条目、原因和详情表都不变;不对的绑法被拒;
production.test.ts真实知识读取器那一例(247–317 行):合成生产器的数据加上commands,后一构建多一个没有命令的用例,绑上分面视图,结论说 1 个。 requirements.json、SKILL.md(开始运行时绑inputs.facets,原样转述这一句)、README(The answer、Limits、How to test;Needs 写一句:影响视图要是每边带上未归位的数,就不用第二个输入)同步;pack-files.ts --write。发布由集成者做。
- 维护巡检照做(
packs/workflow/maintenance-sweep,1.7.0):分面视图绑前一构建(build.root等于影响视图的起始根),代码maintenance-sweep.facets_view;结论放在command_exists已有的索引说明旁边(check.ts229–239 行,sweep.ts149–154 行),写较早构建的用例索引里有 N 个用例没有解析出命令(未归位),巡检不含它们,它们的命令删没删、改没改不知道。测试和文档照第 4 步,真实读取器那一例在production.test.ts231 行。 - 真实客户端场景:
scripts/real/accept/regression-scope.ts(39 行)绑后一构建的分面视图,maintenance-sweep.ts(31 行)绑前一构建的;gold 文件加可选的unplaced,有就核回答里“N 个用例没有解析出命令”的 N,核对项只写期望和实际两个数。capability-scenarios.test.ts(44、74 行断言了开始运行的输入)跟着改,相符和不符各一例。scripts/real/accept-circle.ts85 行把整份报告打到屏幕上,已有核对项的名字里带用例编号:改成屏幕只打一行汇总(共几项、相符几项、不符几项)和报告文件名,报告照旧写进--out。
集成者之后在真实数据上跑(终端不跑)
- 导出到仓库外的临时目录:两个构建的命令树(
circle-hub original export <sha256> --out <文件>)、各自列出的用例文档、第 2 步写法的索引视图、两次运行的circle-hub run show <运行> --json。 node scripts/real/gold/case-commands.ts --tree <后一构建.xml> --maps <清单> --out <临时目录>/later.json,前一构建同样。node scripts/real/accept/command-index.ts --gold <临时目录>/later.json --index <视图> … --out <临时目录>/later-index.json,前一构建同样。屏幕上只有第 2 步列的计数、两个摘要和判定行;两边的未归位数就是重新量出的结果。node scripts/real/accept/scope-cases.ts --diff <命令差.json> --later-cases <later.json> --earlier-cases <earlier.json> --regression-run <回归.json> --maintenance-run <巡检.json> --out <临时目录>/scope.json:计数、摘要、判定。- 两包 1.7.0 发布后,
HUB_REAL_TOKEN=… node scripts/real/accept-circle.ts --scenario scripts/real/accept/regression-scope.ts --gold <gold.json> --out <仓库外目录>,巡检同样;gold 的unplaced填第 3 步 Hub 一侧的数。屏幕上只有汇总行。
完成后在终端里回报:提交号、测试数量、第 1 步对不上手写真值的行和原因、有没有要模型加轴的取值、没做完或拿不准的地方。
集成者对待定问题的答复(2026-10-23)
这一件从 core-fixes 分支开出(那边改过这两个包的生成词表),合并时排在 core-fixes 之后。
- 未归位数先用分面视图
by=commands的空行;K2 合并后要不要挪进影响视图,由集成者再定。 - 分面视图的槽改成必填:Hub 对每个已建的根都能算出这个视图,能拿到的就该拿到,不留“没有给出”的未知。旧场景、金标准文件和 SKILL 一并改成绑定它,两个包升版本。
- 这个槽的角色用线索(A03 R[6]),这个数只作披露,不作判据。
- 金标准只照 FAMX 包 README 的文字规则写;代码注释里另有、README 没写的规则,第 1 步列出对不上的行。K1 合并后由集成者把这些规则补进 README。
- 编号重复或缺失的用例这一件不比,按条数报。
- 步骤要不要扫、缩写规则,仍是所有者的问题;这一件只给出测量数。
- 质量看板也写出未归位数:归 gold-trace(那件管质量看板),这一件不改质量看板。
- 大构建的视图超过上限时,比较脚本自己按
only=分几份读完,不判输入不全;集成者负责导出。 scripts/real/accept-circle.ts这一轮归 gold-template-gap,这一件不改它;要注册场景的,先回报。