:project-code 前綴目錄(CK-01-name)如何正確匹配數(shù)字 Phase 標題)
【免費下載鏈接】gsd-coreGit. Ship. Done - Core項目地址https://gitcode.com/gh_mirrors/ge/gsd-core點擊查看免費下載導(dǎo)讀本篇文章講解 gsd-coreGit. Ship. Done - Core中一次典型的目錄命名約定與標題解析不一致缺陷修復(fù)issue #3600當項目啟用了project_code如CK后相位目錄被命名為CK-01-discovery這樣的帶前綴形式而 ROADMAP.md 中的標題仍是數(shù)字形式### Phase 1: Discovery此時里程碑相位過濾器getMilestonePhaseFilter會漏掉所有帶前綴目錄導(dǎo)致init.new-milestone統(tǒng)計的phase_dir_count、phase complete的完成比例、verify-work與validate-health的校驗結(jié)果全部失真。閱讀本文后你將掌握getMilestonePhaseFilter的完整匹配鏈、strip-and-retry修復(fù)路徑的底層實現(xiàn)以及如何通過回歸測試復(fù)現(xiàn)與驗證該行為。一、缺陷現(xiàn)象CK-01-name 目錄被里程碑過濾器跳過1.1 觸發(fā)場景gsd-core 的.planning/phases/目錄中相位目錄名允許攜帶項目代碼前綴。典型的項目布局如下.planning/ ├── config.json # 含 project_code: CK ├── STATE.md # 聲明 milestone: v1.0.0 ├── ROADMAP.md # 使用數(shù)字 Phase 標題 └── phases/ ├── CK-01-discovery # 項目代碼前綴 相位號 └── CK-02-build而 ROADMAP.md 中的標題是數(shù)字形式## Current Milestone: v1.0.0 - Test ### Phase 1: Discovery **Goal:** GoalOne ### Phase 2: Build **Goal:** GoalTwo在修復(fù)前getMilestonePhaseFilter面對CK-01-discovery這類目錄時判定其不屬于當前里程碑表現(xiàn)為init.new-milestone輸出的phase_dir_count為 0實際磁盤上有 2 個相位目錄phase complete/verify-work/validate-health中所有依賴該過濾器的統(tǒng)計如 completed_phases、percent隨之失真。1.2 根因兩條既有匹配路徑都無法命中從源碼src/roadmap-parser.cts可以還原修復(fù)前的判斷邏輯失敗原因有兩處數(shù)字匹配器要求目錄名以數(shù)字開頭。numericRe的正則是^0*(\d[A-Za-z]?(?:\.\d)*)無連字符約定下CK-01-discovery以字母C開頭直接匹配失敗自定義 ID 匹配器把完整的前綴名與裸 token 比較。該路徑要求目錄名以字母開頭并將整個CK-01-discovery與 ROADMAP 中聲明的相位 ID如01做等值/前綴比較同樣失敗——它試圖匹配的其實是CK-01這種完整自定義 ID而不是剝離前綴后的數(shù)字。兩條路徑都失敗后目錄被判定為不屬于當前里程碑而milestonePhaseNums集合本身非空標題側(cè)掃描正常因此不會觸發(fā) pass-all 退化統(tǒng)計數(shù)字就靜默地錯了——這正是 ADR-3180 中描述的well-formed、plausible 但錯誤的失敗模式。二、修復(fù)方案strip-and-retry 前綴剝離重試路徑2.1 changeset 記錄的核心改動歸檔 changeset3600-milestone-phase-filter-project-code.md記錄的修復(fù)要點是在isDirInMilestone中新增一條strip-and-retry路徑——先剝離目錄名開頭與normalizePhaseName識別規(guī)則一致的項目代碼前綴再對剝離結(jié)果重試數(shù)字匹配。該修復(fù)同時落地于兩處實現(xiàn)CJS 運行時get-shit-done/bin/lib/core.cjs:isDirInMilestonechangeset 歸檔時路徑當前倉庫的源碼真相為 src/roadmap-parser.ctsSDK twinsdk/src/query/state.ts:isDirInMilestone。修復(fù)對所有g(shù)etMilestonePhaseFilter調(diào)用方生效包括init.new-milestone、phase complete、verify-work、validate-health。2.2 前綴剝離規(guī)則與 normalizePhaseName 共用同一正則前綴識別的權(quán)威正則定義在 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前導(dǎo)下劃線不是合法的 project code見 src/phase-id.cts 注釋前綴后必須緊跟連字符且連字符后必須是數(shù)字(?\d)前瞻保證stripProjectCodePrefixsrc/phase-id.cts默認按大小寫不敏感剝離。normalizePhaseNamesrc/phase-id.cts在修復(fù)前就已使用該規(guī)則先stripProjectCodePrefix(str, false)將CK-01歸一化為01再按數(shù)字相位補零。本次修復(fù)讓isDirInMilestone的目錄側(cè)匹配與標題側(cè)歸一化采用同一識別規(guī)則消除了兩側(cè)約定不一致的缺陷。三、源碼級實現(xiàn)isDirInMilestone 的完整匹配鏈修復(fù)后的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; } } // ② 數(shù)字匹配dirName 需以數(shù)字開頭 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 前綴后重試數(shù)字匹配 const stripped stripProjectCodePrefix(dirName); if (stripped ! dirName) { const sm stripped.match(numericRe); if (sm normalized.has(normalizePhaseIdSegments(sm[1]).toLowerCase())) return true; } // ⑤ #3185 兜底委托給規(guī)范相位 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是數(shù)字目錄的唯一所有者。無連字符約定下為^0*(\d[A-Za-z]?(?:\.\d)*)當 ROADMAP 出現(xiàn)連字符 ID 時切換為帶 continuation 段PHASE_CONTINUATION_SEGMENT_SOURCE寬度恰為 2的變體src/roadmap-parser.cts路徑 ③segment-boundary 匹配按最長 ID 優(yōu)先排序#3213避免proj誤收本屬于proj-42的目錄路徑 ④即本次 #3600 的修復(fù)核心純增量——只有前三條路徑全部失敗且目錄確實帶 project-code 前綴時才執(zhí)行不會排除任何已被前面路徑接受的目錄路徑 ⑤解決P0.0-foundation這種字母前綴 小數(shù)相位的形式#1325/#3185同樣是只增不減的兜底。3.2 數(shù)字側(cè)與目錄側(cè)的歸一化一致milestonePhaseNums在收集標題側(cè) ID 后經(jīng)normalizePhaseIdSegments剝離前導(dǎo)零、轉(zhuǎn)小寫構(gòu)建normalized集合src/roadmap-parser.cts。目錄側(cè)的每個命中②③④⑤都會把提取出的 token 走同一歸一化函數(shù)再查集合保證01、1、CK-01歸一化后指向同一相位。四、getMilestonePhaseFilter 的整體結(jié)構(gòu)與退化策略getMilestonePhaseFilter(cwd, versionOverride?, phaseIdConvention?, ws?)src/roadmap-parser.cts返回的不是普通布爾函數(shù)而是帶元數(shù)據(jù)的MilestonePhaseFilter附加屬性含義phaseCount當前里程碑窗口內(nèi)識別到的相位 ID 數(shù)量missingExplicitVersion存在版本化里程碑但versionOverride未命中時置真versionScoped窗口是否被versionOverride成功限定versionSectionFoundROADMAP 中是否找到版本區(qū)段scope窗口可讀性分類COMPLETE / TRUNCATED / UNREADABLE 等其工作流程讀取planningDir(cwd, ws)/ROADMAP.md經(jīng)extractCurrentMilestoneScoped/sliceMilestoneWindow劃定當前里程碑窗口兩者共用 ADR-3180 的單一所有者computeSectionEnd避免重復(fù)推導(dǎo)漂移對milestone-prefixed約定 無版本化標題的組合發(fā)出棄用警告src/roadmap-parser.ctsscanMilestonePhaseIdSets掃描窗口內(nèi)全部相位標題填入milestonePhaseNums與milestoneQualifiedIds若集合為空退化為 pass-all 過濾器() true但保留scope作為破壞性消費者的拒絕信號ADR-3180 Decision 3 的兩層策略——這是寧可多算、不可漏算的安全設(shè)計src/roadmap-parser.cts。五、配置上下文project_code 與 phase_id_convention5.1 project_code.planning/config.json中的project_code字段如CK、PROJ用于給相位目錄加前綴。值得注意的是目錄側(cè)匹配是否走 strip-and-retry 路徑只取決于目錄名本身是否帶前綴不直接讀project_code配置——stripProjectCodePrefix是純字符串函數(shù)。但測試表明該場景通常伴隨project_code配置出現(xiàn)見下文測試代碼。5.2 phase_id_conventionphase_id_convention經(jīng)resolvePhaseIdConventionsrc/planning-workspace.cts以 workstream→root 的聯(lián)邦方式解析。當前存在三種取值狀態(tài)詳見 ADR-612null未遷移純數(shù)字/自定義 ID 形態(tài)milestone-prefixedM-NN如2-01當前唯一的遷移器目標roadmap upgrade --convention milestone-prefixed且觸發(fā)getMilestonePhaseFilter中的棄用警告與verify的 W021 檢查bracket[GSD.02] Phase 02-01:terminal 約定需要project_code存在否則遷移器硬拒絕。本次 #3600 修復(fù)針對的是null/milestone-prefixed讀取形態(tài)下目錄帶 project-code 前綴、標題為數(shù)字的組合與 bracket 約定正交。六、回歸測試如何驗證修復(fù)修復(fù)的回歸測試位于 tests/milestone-archive.test.cjsdescribe 塊名為bug #3600: milestone phase filter understands project-code-prefixed directories包含四個測試6.1 正向init.new-milestone 計數(shù)帶前綴目錄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經(jīng)listMilestonePhaseDirs(phasesDir, { cwd })計算得出該枚舉器在 src/phase-locator.cts 內(nèi)部調(diào)用getMilestonePhaseFilter并將filter.scope作為窗口分類返回。6.2 既有契約無前綴目錄繼續(xù)計數(shù)不帶project_code配置、目錄名為01-first時phase_dir_count仍為 1證明修復(fù)未破壞 #3537 既有的純數(shù)字目錄匹配。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 不會變成看到前綴就通過的寬松匹配。七、影響面與調(diào)用方全景getMilestonePhaseFilter被以下核心路徑共享修復(fù)一經(jīng)合入即全部受益調(diào)用方位置用途cmdInitNewMilestonesrc/init.cts通過listMilestonePhaseDirs統(tǒng)計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規(guī)劃快照src/planning-snapshot.ctsphaseDirs快照按窗口過濾除此之外src/state.cts的state sync/state update-progress等寫路徑也經(jīng)由listMilestonePhaseDirs間接消費同一過濾器src/state.cts 注釋因此帶 project-code 前綴的項目在修復(fù)后其完成比例percent、歸檔目錄集、健康校驗結(jié)果將首次與磁盤真實狀態(tài)一致。八、小結(jié)issue #3600 的修復(fù)體現(xiàn)了 gsd-core 在相位標識解析上單一所有者、增量兼容、退化安全的一貫原則對應(yīng) ADR-2121 與 ADR-3180增量修復(fù)strip-and-retry 只在既有路徑全部失敗時生效只增不減保證歷史目錄形態(tài)的讀取行為不變共用規(guī)則目錄側(cè)剝離與標題側(cè)歸一化復(fù)用同一PROJECT_CODE_PREFIX_STRIP_RE從機制上杜絕兩側(cè)約定漂移測試完備四向回歸測試覆蓋正向計數(shù)、既有契約、自定義 ID 路徑與反向排除防止修復(fù)退化為寬松匹配。對于使用project_code前綴目錄的項目升級到包含此修復(fù)的版本后init.new-milestone的phase_dir_count、phase complete的窗口歸檔、verify-work與validate-health的校驗結(jié)果均會恢復(fù)正常。若需復(fù)現(xiàn)原始缺陷可在.planning/config.json中設(shè)置project_code: CK、創(chuàng)建CK-01-discovery目錄并運行g(shù)sd-tools init new-milestone觀察修復(fù)前后phase_dir_count的差異。贊分享【免費下載鏈接】gsd-coreGit. Ship. Done - Core項目地址https://gitcode.com/gh_mirrors/ge/gsd-core點擊查看免費下載相關(guān)推薦GSD 里程碑階段過濾器修復(fù)解析讓 CK-01 前綴階段目錄正確計入數(shù)字 ROADMAP 里程碑GSD 里程碑階段過濾器修復(fù)解析讓 CK 01 前綴階段目錄正確計入數(shù)字 ROADMAP 里程碑 本篇基于 get shit doneGSD倉庫中的 ch人工智能AI 應(yīng)用提示工程開發(fā)工具工作流自動化AI AgentUI-TARS 使用指南讓 AI 直接操作電腦圖形界面安裝與示例教程UI TARS 使用指南讓 AI 直接操作電腦圖形界面安裝與示例教程 UI TARS 是字節(jié)跳動 Seed 團隊與清華大學(xué)推出的原生多模態(tài) GUI 智能體gsd-core 修復(fù)實錄state planned-phase 里程碑進度計數(shù)器損壞問題Bug 500 / PR 514gsd core 修復(fù)實錄state planned phase 里程碑進度計數(shù)器損壞問題Bug 500 / PR 514 導(dǎo)讀 本篇以 gsd core創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考