的 REQ-ID 作用域修复:消除误报的 “Not covered“ 与幽灵 REQ-ID 缺失行)
【免费下载链接】gsd-coreGit. Ship. Done - Core项目地址https://gitcode.com/gh_mirrors/ge/gsd-core点击查看免费下载本文详解 gsd-core 仓库中/gsd-plan-phase工作流 §13ePost-Planning Gap Analysis的一次关键行为修复changeset daring-yaks-zip缺口分析现在如何将检查范围收敛到该阶段在路线图中映射的 REQ-ID无映射阶段phase_req_ids为 null/TBD不再把项目里每个无关需求误报为 not covered同时路线图中存在但 REQUIREMENTS.md 缺失的 REQ-ID 会以显式的 ⚠ Missing from REQUIREMENTS.md 行呈现而非被静默丢弃。阅读本文后你将掌握该机制的输入来源、作用域归一化规则、缺失行的生成逻辑、门控配置与命令行用法以及对应的测试验证证据。修复背景post-planning gap analysis 为什么需要作用域收敛gsd-core 的规划工作流在生成阶段计划后会执行一次主动的、非阻塞的覆盖率报告——即 plan-phase.md 中的§13e. Post-Planning Gap Analysisplan:post 能力门控调度。其核心职责是读取REQUIREMENTS.md与各阶段的CONTEXT.mddecisions块将每个 REQ-ID / D-ID 与该阶段目录下的*-PLAN.md文件全文交叉比对输出一张Source | Item | Status覆盖表。修复前的缺陷在于缺口分析默认把整个项目的REQUIREMENTS.md当作比对范围。当一个阶段在路线图ROADMAP.md中根本没有映射任何需求phase_req_ids为 null 或 TBD时分析器仍会遍历所有 REQ-ID结果把属于其他阶段的需求也统统报为 Not covered制造大量假性缺口噪音反过来路线图中映射的 REQ-ID 若因需求文档漂移比如被改名、删行而不再存在于REQUIREMENTS.md旧实现会静默丢弃这些 ID导致报告出现虚假的 all covered 结论。本次修复changeset 类型为Fixed关联 PR 538正是针对这两个方向作用域收敛比对范围收敛到该阶段映射的 REQ-ID无映射阶段跳过需求比对不再把无关需求报为缺口。缺失行显式化映射了但在REQUIREMENTS.md中不存在的 REQ-ID 以 ⚠ Missing from REQUIREMENTS.md 行呈现避免 全部覆盖 的假阳性。输入来源phase_req_ids从路线图到查询的链路作用域信号phase_req_ids并非凭空而来而是由init.plan-phase查询从 ROADMAP.md 中提取。在 init.cts 中可以看到完整的提取逻辑通过roadmapParser.extractPhaseFieldMultiline(phaseSection, Requirements)读取阶段区块的Requirements字段支持多行硬换行见 init.cts将提取结果去除方括号、按逗号切分、trim()并过滤空项再以,重新拼接init.cts若结果为空或等于字面量TBD则赋值为nullinit.cts即本阶段未映射需求的信号。工作流侧在 plan-phase.md 中通过两条命令取到作用域值PHASE_REQ_IDS$(gsd_run query init.plan-phase $PHASE --pick phase_req_ids 2/dev/null) PHASE_REQ_IDS${PHASE_REQ_IDS:-TBD}注意这里必须使用init.plan-phase查询而非roadmap.get-phase后者返回的是原始阶段文本非 JSON--pick无法提取出字段测试 gap-checker.property.test.cjs 专门固化了这一查询选择防止将来有人改错查询导致所有阶段的缺口检查被静默跳过。随后PHASE_REQ_IDS作为第二个参数传给gap-analysis检查GATE_RESULT$(gsd_run check ${hook.check.query} ${PHASE_DIR} ${PHASE_REQ_IDS} --raw)作用域归一化normalizePhaseReqIds的完整语义在 gap-checker.cts 中normalizePhaseReqIdsgap-checker.cts将原始参数归一化为三类信号输入形态归一化结果含义undefinedflag 缺失undefined兼容旧行为比对整个REQUIREMENTS.mdnull/ 空串 /TBD/NONEnull本阶段无映射需求跳过需求比对§13 的 null/TBD 跳过语义REQ-01,REQ-02[REQ-01,REQ-02]仅比对列出的 IDSEL-01..SEL-03[SEL-01,SEL-02,SEL-03]区间展开#1269归一化过程还包含两个关键细节区间展开#1269expandPhaseReqIdTokengap-checker.cts会将PREFIX-NN..PREFIX-MM形式的同前缀升序数字区间原地展开为具体 ID且保持两端零填充宽度PREFIX-001..PREFIX-003→PREFIX-001/002/003。它采取 fail-closed 策略前缀不一致、两端位宽不同、降序、非数字、跨度超过MAX_PHASE_REQ_RANGE1000防 DoS等任何不明确情形都保持字面量不展开。测试 gap-checker.property.test.cjs 的 AC1/AC2 用例验证了展开与零填充行为。ID 形态过滤#3189ROADMAP 的**Requirements:**行经常附带锁定决策注解、歧义分值、禁制项、日期等散文内容。若不做过滤每个散文词都会被当作缺失的需求上报淹没真实信号。因此区间展开之后每个 token 还要通过PHASE_REQ_ID_SHAPE_REgap-checker.cts形状过滤——要求至少含一个数字、以大写字母开头、仅含字母/数字/连字符/下划线从而接受R1、SEL-01、P1-P3这类真实 ID拒绝LOCKED、TBD、日期、版本号、反引号片段等假 ID若所有 token 都被过滤掉则坍缩为null跳过语义。核心修复逻辑无映射阶段的跳过与缺失行的生成归一化之后runGapAnalysisgap-checker.cts在比对前执行作用域决策if (phaseReqIds null) { reqItems []; // 无映射阶段清空需求比对集 } else if (Array.isArray(phaseReqIds)) { const wanted new Set(phaseReqIds); const foundIds new Set(reqItems.map(r r.id)); reqItems reqItems.filter(r wanted.has(r.id)); // 只保留映射的 ID ghostReqIds phaseReqIds.filter(id !foundIds.has(id)); // 收集缺失的 ID }三个分支的精确定义null无映射需求比对集被清空CONTEXT.md的决策项始终在作用域内。此时即使REQUIREMENTS.md里有 100 个需求报告也不会出现任何需求行彻底消除每个无关项目需求都报 not covered的原缺陷有映射列表只保留wanted集合内的需求项做覆盖检测其他阶段的需求被排除幽灵 ID 收集phaseReqIds中在foundIds里找不到的 ID 进入ghostReqIds最终以source: REQUIREMENTS.md、status: Missing from REQUIREMENTS.md的行参与计数gap-checker.cts在输出表中渲染为⚠ Missing from REQUIREMENTS.mdgap-checker.cts。这些行会计入uncovered防止所有项都被覆盖的假阳性摘要。值得强调的边界处理即使一个阶段所有映射 ID 都是幽灵 IDitems.length 0但ghostReqIds.length 0分析器也不会落入 No requirements or decisions to check 的空报告分支——该分支显式要求items.length 0 ghostReqIds.length 0gap-checker.cts否则全幽灵阶段会报出比部分幽灵阶段更少的信息。同样CONTEXT.md决策块解析失败could-not-parse时若存在需求项或幽灵 ID报告仍会带上需求覆盖行与extracted 0 of N的格式不匹配提示gap-checker.cts。门控与运行方式§13e 受workflow.post_planning_gaps配置项门控默认开启。关闭时runGapAnalysis直接返回{ enabled: false }不扫描任何文件gap-checker.cts摘要为workflow.post_planning_gaps disabled — skipping post-planning gap analysis。门控通过 plan-phase.md 中gsd_run loop render-hooks plan:post --raw渲染的钩子元数据决定gap-analysis能力注册的钩子when字段即workflow.post_planning_gapsblocking: false纯建议性永不阻塞阶段完成onError: skip。命令行直接用法对应cmdGapAnalysisgap-checker.ctsgsd-core/bin/gsd-tools.cjs gap-analysis --phase-dir path-to-phase-directory [--phase-req-ids ids] # 示例仅比对映射的 REQ-01、REQ-02 gsd-core/bin/gsd-tools.cjs gap-analysis --phase-dir .planning/phases/01-test --phase-req-ids REQ-01,REQ-02输出 JSON 包含enabled、rows、table、summary、counts.total/covered/uncovered等结构化字段并附带phase_dir_read_error阶段目录真实读失败时非 null与phase_dir_scope两个目录探测信号。测试验证证据仓库为本次修复提供了多维度的测试固化gap-checker.property.test.cjs直接验证init.plan-phase --pick phase_req_ids暴露映射 ID 且缺口报告严格按映射作用域REQ-03 被排除验证REQ-99缺席时输出行状态为Missing from REQUIREMENTS.md且计入uncovered验证无 Requirements 行的阶段输出零需求缺口行即原始 #447 缺陷场景以及区间展开/零填充/形态过滤的行为契约check-gap-analysis-plan-post-e2e.test.cjs端到端验证loop render-hooks plan:post的门控发现post_planning_gapsfalse时activeHooks必须为空、check gap-analysis.plan-post的覆盖表、禁用态enabled:false、缺参报错以及全幽灵 ID 阶段仍必须呈现 ⚠ Missing from REQUIREMENTS.md 行第 345-346 行、第 411-413 行、第 448-449 行等断言。小结本次 changesetdaring-yaks-zip修复了 gsd-core 后规划缺口分析的两个核心信号问题作用域收敛消除了无映射阶段的全项目误报噪音显式缺失行消除了需求文档漂移导致的假全覆盖。二者共同保证了 §13e 输出的每一项 REQ-ID 状态都有真实依据使缺口报告既不多报、也不少报。相关实现以 gap-checker.cts 为单一事实源ADR-457 构建期发布手写bin/lib/gap-checker.cjs已坍缩为 TypeScript 源工作流侧接线见 plan-phase.md §13e行为契约由上述两组测试持续守护。赞分享【免费下载链接】gsd-coreGit. Ship. Done - Core项目地址https://gitcode.com/gh_mirrors/ge/gsd-core点击查看免费下载相关推荐gsd-core 里程碑归档目录解析修复getActiveMilestoneArchiveDir 的 null 语义与 W007 误报消除gsd core 里程碑归档目录解析修复getActiveMilestoneArchiveDir 的 null 语义与 W007 误报消除 本文聚焦 gsdgsd-core 将 RETROSPECTIVE.md 登记为 Canonical Artifact彻底消除 gsd-health W019 误报gsd core 将 RETROSPECTIVE.md 登记为 Canonical Artifact彻底消除 gsd health W019 误报 导读 本文上一篇从像素到艺术FastPhotoStyle计算机视觉课程实践项目设计指南下一篇突破视角限制VGGT多视图匹配中Attention机制的特征融合技术创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考