ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

gsd-core 里程碑相位过滤修复:project-code 前缀目录(CK-01-name)如何正确匹配数字 Phase 标题

gsd-core 里程碑相位过滤修复:project-code 前缀目录(CK-01-name)如何正确匹配数字 Phase 标题 【免费下载链接】gsd-coreGit. Ship. Done - Core项目地址https://gitcode.com/gh_mirrors/ge/gsd-core点击查看免费下载导读本篇文章讲解 gsd-coreGit. Ship. Done - Core中一次典型的目录命名约定与标题解析不一致缺陷修复issue #3600当项目启用了project_code如CK后相位目录被命名为CK-01-discovery这样的带前缀形式而 ROADMAP.md 中的标题仍是数字形式### Phase 1: Discovery此时里程碑相位过滤器getMilestonePhaseFilter会漏掉所有带前缀目录导致init.new-milestone统计的phase_dir_count、phase complete的完成比例、verify-work与validate-health的校验结果全部失真。阅读本文后你将掌握getMilestonePhaseFilter的完整匹配链、strip-and-retry修复路径的底层实现以及如何通过回归测试复现与验证该行为。一、缺陷现象CK-01-name 目录被里程碑过滤器跳过1.1 触发场景gsd-core 的.planning/phases/目录中相位目录名允许携带项目代码前缀。典型的项目布局如下.planning/ ├── config.json # 含 project_code: CK ├── STATE.md # 声明 milestone: v1.0.0 ├── ROADMAP.md # 使用数字 Phase 标题 └── phases/ ├── CK-01-discovery # 项目代码前缀 相位号 └── CK-02-build而 ROADMAP.md 中的标题是数字形式## Current Milestone: v1.0.0 - Test ### Phase 1: Discovery **Goal:** GoalOne ### Phase 2: Build **Goal:** GoalTwo在修复前getMilestonePhaseFilter面对CK-01-discovery这类目录时判定其不属于当前里程碑表现为init.new-milestone输出的phase_dir_count为 0实际磁盘上有 2 个相位目录phase complete/verify-work/validate-health中所有依赖该过滤器的统计如 completed_phases、percent随之失真。1.2 根因两条既有匹配路径都无法命中从源码src/roadmap-parser.cts可以还原修复前的判断逻辑失败原因有两处数字匹配器要求目录名以数字开头。numericRe的正则是^0*(\d[A-Za-z]?(?:\.\d)*)无连字符约定下CK-01-discovery以字母C开头直接匹配失败自定义 ID 匹配器把完整的前缀名与裸 token 比较。该路径要求目录名以字母开头并将整个CK-01-discovery与 ROADMAP 中声明的相位 ID如01做等值/前缀比较同样失败——它试图匹配的其实是CK-01这种完整自定义 ID而不是剥离前缀后的数字。两条路径都失败后目录被判定为不属于当前里程碑而milestonePhaseNums集合本身非空标题侧扫描正常因此不会触发 pass-all 退化统计数字就静默地错了——这正是 ADR-3180 中描述的well-formed、plausible 但错误的失败模式。二、修复方案strip-and-retry 前缀剥离重试路径2.1 changeset 记录的核心改动归档 changeset3600-milestone-phase-filter-project-code.md记录的修复要点是在isDirInMilestone中新增一条strip-and-retry路径——先剥离目录名开头与normalizePhaseName识别规则一致的项目代码前缀再对剥离结果重试数字匹配。该修复同时落地于两处实现CJS 运行时get-shit-done/bin/lib/core.cjs:isDirInMilestonechangeset 归档时路径当前仓库的源码真相为 src/roadmap-parser.ctsSDK twinsdk/src/query/state.ts:isDirInMilestone。修复对所有getMilestonePhaseFilter调用方生效包括init.new-milestone、phase complete、verify-work、validate-health。2.2 前缀剥离规则与 normalizePhaseName 共用同一正则前缀识别的权威正则定义在 src/phase-id.ctsconst PROJECT_CODE_PREFIX_STRIP_RE /^[A-Z][A-Z0-9_]*-(?\d)/; const PROJECT_CODE_PREFIX_STRIP_RE_I /^[A-Z][A-Z0-9_]*-(?\d)/i;要点项目代码以大写字母开头如PROJ、APP_CODE前导下划线不是合法的 project code见 src/phase-id.cts 注释前缀后必须紧跟连字符且连字符后必须是数字(?\d)前瞻保证stripProjectCodePrefixsrc/phase-id.cts默认按大小写不敏感剥离。normalizePhaseNamesrc/phase-id.cts在修复前就已使用该规则先stripProjectCodePrefix(str, false)将CK-01归一化为01再按数字相位补零。本次修复让isDirInMilestone的目录侧匹配与标题侧归一化采用同一识别规则消除了两侧约定不一致的缺陷。三、源码级实现isDirInMilestone 的完整匹配链修复后的isDirInMilestonesrc/roadmap-parser.cts按顺序尝试五条匹配路径任中即返回truefunction isDirInMilestone(dirName: string): boolean { // ① bracket 约定对照 milestone-qualified IDGSD.01-01-xxx匹配 if (headingConvention bracket) { for (const qualified of milestoneQualifiedIds) { if (phaseTokenMatches(dirName, qualified, bracket)) return true; } } // ② 数字匹配dirName 需以数字开头 const m2 dirName.match(numericRe); if (m2 normalized.has(normalizePhaseIdSegments(m2[1]).toLowerCase())) return true; // ③ 字母开头的自定义 IDsegment-boundary 前缀匹配longest-first if (/^[A-Za-z]/.test(dirName)) { const lowerDir dirName.toLowerCase(); for (const id of normalizedIdsLongestFirst) { if (lowerDir id || lowerDir.startsWith(id -)) return true; } } // ④ #3600 新增strip-and-retry —— 剥离 project-code 前缀后重试数字匹配 const stripped stripProjectCodePrefix(dirName); if (stripped ! dirName) { const sm stripped.match(numericRe); if (sm normalized.has(normalizePhaseIdSegments(sm[1]).toLowerCase())) return true; } // ⑤ #3185 兜底委托给规范相位 token 提取器 extractPhaseToken const token extractPhaseToken(dirName); if (token normalized.has(normalizePhaseIdSegments(String(token)).toLowerCase())) return true; return false; }3.1 各路径的分工与边界路径 ①仅在phase_id_convention bracket时生效用phaseTokenMatches对照GSD.01-01-xxx这类 qualified ID解决 ADR-612 定义的 READING-B 读取约定下GSD.01-01-old-one与GSD.02-01-one共享 token01的歧义路径 ②numericRe是数字目录的唯一所有者。无连字符约定下为^0*(\d[A-Za-z]?(?:\.\d)*)当 ROADMAP 出现连字符 ID 时切换为带 continuation 段PHASE_CONTINUATION_SEGMENT_SOURCE宽度恰为 2的变体src/roadmap-parser.cts路径 ③segment-boundary 匹配按最长 ID 优先排序#3213避免proj误收本属于proj-42的目录路径 ④即本次 #3600 的修复核心纯增量——只有前三条路径全部失败且目录确实带 project-code 前缀时才执行不会排除任何已被前面路径接受的目录路径 ⑤解决P0.0-foundation这种字母前缀 小数相位的形式#1325/#3185同样是只增不减的兜底。3.2 数字侧与目录侧的归一化一致milestonePhaseNums在收集标题侧 ID 后经normalizePhaseIdSegments剥离前导零、转小写构建normalized集合src/roadmap-parser.cts。目录侧的每个命中②③④⑤都会把提取出的 token 走同一归一化函数再查集合保证01、1、CK-01归一化后指向同一相位。四、getMilestonePhaseFilter 的整体结构与退化策略getMilestonePhaseFilter(cwd, versionOverride?, phaseIdConvention?, ws?)src/roadmap-parser.cts返回的不是普通布尔函数而是带元数据的MilestonePhaseFilter附加属性含义phaseCount当前里程碑窗口内识别到的相位 ID 数量missingExplicitVersion存在版本化里程碑但versionOverride未命中时置真versionScoped窗口是否被versionOverride成功限定versionSectionFoundROADMAP 中是否找到版本区段scope窗口可读性分类COMPLETE / TRUNCATED / UNREADABLE 等其工作流程读取planningDir(cwd, ws)/ROADMAP.md经extractCurrentMilestoneScoped/sliceMilestoneWindow划定当前里程碑窗口两者共用 ADR-3180 的单一所有者computeSectionEnd避免重复推导漂移对milestone-prefixed约定 无版本化标题的组合发出弃用警告src/roadmap-parser.ctsscanMilestonePhaseIdSets扫描窗口内全部相位标题填入milestonePhaseNums与milestoneQualifiedIds若集合为空退化为 pass-all 过滤器() true但保留scope作为破坏性消费者的拒绝信号ADR-3180 Decision 3 的两层策略——这是宁可多算、不可漏算的安全设计src/roadmap-parser.cts。五、配置上下文project_code 与 phase_id_convention5.1 project_code.planning/config.json中的project_code字段如CK、PROJ用于给相位目录加前缀。值得注意的是目录侧匹配是否走 strip-and-retry 路径只取决于目录名本身是否带前缀不直接读project_code配置——stripProjectCodePrefix是纯字符串函数。但测试表明该场景通常伴随project_code配置出现见下文测试代码。5.2 phase_id_conventionphase_id_convention经resolvePhaseIdConventionsrc/planning-workspace.cts以 workstream→root 的联邦方式解析。当前存在三种取值状态详见 ADR-612null未迁移纯数字/自定义 ID 形态milestone-prefixedM-NN如2-01当前唯一的迁移器目标roadmap upgrade --convention milestone-prefixed且触发getMilestonePhaseFilter中的弃用警告与verify的 W021 检查bracket[GSD.02] Phase 02-01:terminal 约定需要project_code存在否则迁移器硬拒绝。本次 #3600 修复针对的是null/milestone-prefixed读取形态下目录带 project-code 前缀、标题为数字的组合与 bracket 约定正交。六、回归测试如何验证修复修复的回归测试位于 tests/milestone-archive.test.cjsdescribe 块名为bug #3600: milestone phase filter understands project-code-prefixed directories包含四个测试6.1 正向init.new-milestone 计数带前缀目录writeConfig(tmpDir, { project_code: CK }); writeState(tmpDir, v1.0.0); writeRoadmap(tmpDir, [ # Roadmap, , ## Current Milestone: v1.0.0 - Test, , ### Phase 1: Discovery, **Goal:** GoalOne, , ### Phase 2: Build, **Goal:** GoalTwo, , ].join(\n)); ensurePhaseDir(tmpDir, CK-01-discovery); ensurePhaseDir(tmpDir, CK-02-build); const r runGsdTools([init, new-milestone], tmpDir); assert.strictEqual(JSON.parse(r.output).phase_dir_count, 2);phase_dir_count在 src/init.cts 中由cmdInitNewMilestone经listMilestonePhaseDirs(phasesDir, { cwd })计算得出该枚举器在 src/phase-locator.cts 内部调用getMilestonePhaseFilter并将filter.scope作为窗口分类返回。6.2 既有契约无前缀目录继续计数不带project_code配置、目录名为01-first时phase_dir_count仍为 1证明修复未破坏 #3537 既有的纯数字目录匹配。6.3 自定义 ID 路径不回归Phase PROJ-42: Custom标题 PROJ-42目录仍通过路径③自定义 ID segment-boundary 匹配命中phase_dir_count为 1——strip-and-retry 是增量路径不影响原有的自定义 ID 匹配。6.4 反向非当前里程碑的带前缀目录必须被排除ensurePhaseDir(tmpDir, CK-01-first); ensurePhaseDir(tmpDir, CK-99-backlog); ensurePhaseDir(tmpDir, CK-100-future); // 断言 phase_dir_count 1仅 CK-01-first 匹配 Phase 1CK-99与CK-100剥离前缀后分别归一化为99、100不在normalized集合中必须被排除——这验证了 strip-and-retry 不会变成看到前缀就通过的宽松匹配。七、影响面与调用方全景getMilestonePhaseFilter被以下核心路径共享修复一经合入即全部受益调用方位置用途cmdInitNewMilestonesrc/init.cts通过listMilestonePhaseDirs统计phase_dir_countlistMilestonePhaseDirssrc/phase-locator.cts里程碑窗口相位目录枚举的单一所有者cmdMilestoneCompletesrc/milestone.cts归档当前里程碑时按窗口筛选要移动的目录inspectWorkstreamsrc/workstream-inventory.ctsworkstream 当前版本窗口过滤健康诊断roadmap-disk-consistencysrc/health-diagnostic-rules/roadmap-disk-consistency.cts校验 ROADMAP 声明与磁盘目录的一致性validate-health规划快照src/planning-snapshot.ctsphaseDirs快照按窗口过滤除此之外src/state.cts的state sync/state update-progress等写路径也经由listMilestonePhaseDirs间接消费同一过滤器src/state.cts 注释因此带 project-code 前缀的项目在修复后其完成比例percent、归档目录集、健康校验结果将首次与磁盘真实状态一致。八、小结issue #3600 的修复体现了 gsd-core 在相位标识解析上单一所有者、增量兼容、退化安全的一贯原则对应 ADR-2121 与 ADR-3180增量修复strip-and-retry 只在既有路径全部失败时生效只增不减保证历史目录形态的读取行为不变共用规则目录侧剥离与标题侧归一化复用同一PROJECT_CODE_PREFIX_STRIP_RE从机制上杜绝两侧约定漂移测试完备四向回归测试覆盖正向计数、既有契约、自定义 ID 路径与反向排除防止修复退化为宽松匹配。对于使用project_code前缀目录的项目升级到包含此修复的版本后init.new-milestone的phase_dir_count、phase complete的窗口归档、verify-work与validate-health的校验结果均会恢复正常。若需复现原始缺陷可在.planning/config.json中设置project_code: CK、创建CK-01-discovery目录并运行gsd-tools init new-milestone观察修复前后phase_dir_count的差异。赞分享【免费下载链接】gsd-coreGit. Ship. Done - Core项目地址https://gitcode.com/gh_mirrors/ge/gsd-core点击查看免费下载相关推荐GSD 里程碑阶段过滤器修复解析让 CK-01 前缀阶段目录正确计入数字 ROADMAP 里程碑GSD 里程碑阶段过滤器修复解析让 CK 01 前缀阶段目录正确计入数字 ROADMAP 里程碑 本篇基于 get shit doneGSD仓库中的 ch人工智能AI 应用提示工程开发工具工作流自动化AI AgentUI-TARS 使用指南让 AI 直接操作电脑图形界面安装与示例教程UI TARS 使用指南让 AI 直接操作电脑图形界面安装与示例教程 UI TARS 是字节跳动 Seed 团队与清华大学推出的原生多模态 GUI 智能体gsd-core 修复实录state planned-phase 里程碑进度计数器损坏问题Bug 500 / PR 514gsd core 修复实录state planned phase 里程碑进度计数器损坏问题Bug 500 / PR 514 导读 本篇以 gsd core创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表