feat/wp-extract-contract/main #33

Merged
admin merged 5 commits from feat/wp-extract-contract/main into master 2026-09-17 06:33:37 +00:00
Member

摘要

建立工作包議題的抽取契約 wp-extract:給一個工作包議題編號,回傳實作階段需要的一切,
而不必吞下整份議題全文。順帶修好一個既有的解析缺陷(見「解決的問題」)。

需求議題

#1 — tea-sdlc:以 tea 驅動 SDLC 全流程的跨平台指令組

工作包議題

#9 — 建立工作包的抽取契約

變更內容

commit 內容
fix(議題解析) CRLF 的 body 不再讓清單靜靜變成空的
refactor(抽取) 議題讀取與留言計數收進 lib.js,兩支抽取腳本共用
feat(議題解析) 解析巢狀待辦、多欄表格與關聯裡的議題編號
feat(wp-extract) 建立工作包的抽取契約
test(wp-extract) 覆蓋契約欄位、模板變體、活狀態與 CRLF

新增 scripts/wp-extract.js;scripts/issue-body.js 增加 checklistInSection、tableRows、
referencedIndex;scripts/lib.js 增加 fetchIssue、countUnmergedComments;
scripts/issue-extract.js 改為呼叫後兩者,行為不變。

輸出與議題 #1 的契約逐欄一致:

{index, url, title, 需求議題, 描述, 架構圖, 範圍邊界[], 介面契約[],
 待辦[{text,done,raw,驗收[{text,done,raw}]}], 整體驗收[], repos[],
 相依:{blocks[],depends[]}, assignee, 碼錶中, 未處理留言數}

設計重點

  • raw 逐字等於 body 裡的那一行。 下游勾選 checkbox 時要靠它做精確字串替換,
    只改那一行、不重寫整份 body。因此 checklistInSection 收整份 body 而不收切好的段落
    ——段落切分會修掉前後空白,給不出這種保證。連行尾的 \r 都原樣留著。
  • 畸形的待辦不丟內容。 巢狀超過一層攤進所在待辦的驗收;還沒有上層待辦就先出現的
    縮排項目升格成待辦。沿用本 repo 既有的「寧可多帶一項,也不要無聲吃掉內容」。
  • 相依逐頁讀完。 半份清單會讓下游把實作順序排錯,那比直接報錯更難發現。
  • tableSection 改寫成 tableRows 的兩欄版,解析規則只留一份。短的資料列補空字串
    ——正本明講「不產出對外介面就寫一列『無』」,那一列不該與「沒有這一段」混為一談。

解決的問題

CRLF 的 body 會讓清單靜靜變成空的(既有缺陷,非本次新增)。
瀏覽器送出 textarea 一律用 CRLF,議題只要在 Gitea 網頁上被編輯過,body 逐行切開後行尾
就掛著 \r。JS 的 . 不吃 \r,(.*)$ 因此整行比不中:已經上線的 issue-extract
會把目標、非目標、驗收標準一律回成空陣列,而且不報錯、exit code 是 0——下游拿到的是
「這一段沒寫」而不是「解析失敗」。改用 [\s\S] 比對行尾,並補上測試。

影響的功能

  • issue-extract:受惠於 CRLF 修正;內部改用 lib.js 的共用函式,輸出不變(既有測試全數通過)。
  • issue-body.js 的 tableSection:單格資料列從「丟掉」改為「補空字串」,不再無聲消失。
  • 尚未實作的 sdlc-feat(#11–#13)將以本契約為唯一的工作包讀取管道。

已知限制:碼錶中 受限於 Gitea 只開放讀自己的碼錶(/user/stopwatches),實際語意是
「我的碼錶正跑在這顆議題上」,這是議題 #1 已接受的取捨;領取鎖看的仍是 assignee。

測試結果

於本分支的乾淨工作樹實際執行 npm test:

ℹ tests 274
ℹ suites 0
ℹ pass 274
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 5921.072673

新增 49 個測試案例,涵蓋契約欄位、模板變體(缺段落、巢狀驗收為空、checkbox 已勾、
中英混排、圍欄裡的假待辦、只寫一格的表格列)、CRLF、相依與留言的分頁、--dry-run
預告的請求順序與實跑一致且完全不碰 Gitea。

另以實機驗證:dependencies/blocks//user/stopwatches 三個端點的回應形狀,
以及 StopWatch 的欄位名稱,皆對照本站 Gitea 1.27.0 的 swagger 確認無誤。

🤖 Generated with Claude Code

## 摘要 建立工作包議題的抽取契約 `wp-extract`:給一個工作包議題編號,回傳實作階段需要的一切, 而不必吞下整份議題全文。順帶修好一個既有的解析缺陷(見「解決的問題」)。 ## 需求議題 #1 — tea-sdlc:以 tea 驅動 SDLC 全流程的跨平台指令組 ## 工作包議題 #9 — 建立工作包的抽取契約 ## 變更內容 | commit | 內容 | | --- | --- | | `fix(議題解析)` | CRLF 的 body 不再讓清單靜靜變成空的 | | `refactor(抽取)` | 議題讀取與留言計數收進 `lib.js`,兩支抽取腳本共用 | | `feat(議題解析)` | 解析巢狀待辦、多欄表格與關聯裡的議題編號 | | `feat(wp-extract)` | 建立工作包的抽取契約 | | `test(wp-extract)` | 覆蓋契約欄位、模板變體、活狀態與 CRLF | 新增 `scripts/wp-extract.js`;`scripts/issue-body.js` 增加 `checklistInSection`、`tableRows`、 `referencedIndex`;`scripts/lib.js` 增加 `fetchIssue`、`countUnmergedComments`; `scripts/issue-extract.js` 改為呼叫後兩者,行為不變。 輸出與議題 #1 的契約逐欄一致: ``` {index, url, title, 需求議題, 描述, 架構圖, 範圍邊界[], 介面契約[], 待辦[{text,done,raw,驗收[{text,done,raw}]}], 整體驗收[], repos[], 相依:{blocks[],depends[]}, assignee, 碼錶中, 未處理留言數} ``` ## 設計重點 - **`raw` 逐字等於 body 裡的那一行。** 下游勾選 checkbox 時要靠它做精確字串替換, 只改那一行、不重寫整份 body。因此 `checklistInSection` 收整份 body 而不收切好的段落 ——段落切分會修掉前後空白,給不出這種保證。連行尾的 `\r` 都原樣留著。 - **畸形的待辦不丟內容。** 巢狀超過一層攤進所在待辦的驗收;還沒有上層待辦就先出現的 縮排項目升格成待辦。沿用本 repo 既有的「寧可多帶一項,也不要無聲吃掉內容」。 - **相依逐頁讀完。** 半份清單會讓下游把實作順序排錯,那比直接報錯更難發現。 - **`tableSection` 改寫成 `tableRows` 的兩欄版**,解析規則只留一份。短的資料列補空字串 ——正本明講「不產出對外介面就寫一列『無』」,那一列不該與「沒有這一段」混為一談。 ## 解決的問題 **CRLF 的 body 會讓清單靜靜變成空的(既有缺陷,非本次新增)。** 瀏覽器送出 textarea 一律用 CRLF,議題只要在 Gitea 網頁上被編輯過,body 逐行切開後行尾 就掛著 `\r`。JS 的 `.` 不吃 `\r`,`(.*)$` 因此整行比不中:已經上線的 `issue-extract` 會把目標、非目標、驗收標準一律回成空陣列,而且不報錯、exit code 是 0——下游拿到的是 「這一段沒寫」而不是「解析失敗」。改用 `[\s\S]` 比對行尾,並補上測試。 ## 影響的功能 - `issue-extract`:受惠於 CRLF 修正;內部改用 `lib.js` 的共用函式,輸出不變(既有測試全數通過)。 - `issue-body.js` 的 `tableSection`:單格資料列從「丟掉」改為「補空字串」,不再無聲消失。 - 尚未實作的 `sdlc-feat`(#11–#13)將以本契約為唯一的工作包讀取管道。 **已知限制**:`碼錶中` 受限於 Gitea 只開放讀自己的碼錶(`/user/stopwatches`),實際語意是 「我的碼錶正跑在這顆議題上」,這是議題 #1 已接受的取捨;領取鎖看的仍是 `assignee`。 ## 測試結果 於本分支的乾淨工作樹實際執行 `npm test`: ``` ℹ tests 274 ℹ suites 0 ℹ pass 274 ℹ fail 0 ℹ cancelled 0 ℹ skipped 0 ℹ todo 0 ℹ duration_ms 5921.072673 ``` 新增 49 個測試案例,涵蓋契約欄位、模板變體(缺段落、巢狀驗收為空、checkbox 已勾、 中英混排、圍欄裡的假待辦、只寫一格的表格列)、CRLF、相依與留言的分頁、`--dry-run` 預告的請求順序與實跑一致且完全不碰 Gitea。 另以實機驗證:`dependencies`/`blocks`/`/user/stopwatches` 三個端點的回應形狀, 以及 `StopWatch` 的欄位名稱,皆對照本站 Gitea 1.27.0 的 swagger 確認無誤。 🤖 Generated with [Claude Code](https://claude.com/claude-code)
jiantw83 added 5 commits 2026-09-17 06:32:33 +00:00
瀏覽器送出 textarea 一律用 CRLF,議題只要在 Gitea 網頁上被編輯過,body 逐行切開後
每一行行尾就掛著 \r。JS 的 . 不吃 \r,`(.*)$` 因此整行比不中——listSection 會把
目標、非目標、驗收標準這些段落一律回成空陣列,而且不報錯,下游拿到的是「這一段沒寫」
而不是「解析失敗」。

改用 [\s\S] 比對行尾,text 本來就有 trim 會把 \r 修掉。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
工作包的抽取契約(#9)要做的事與需求議題那一支有三件完全重疊:讀議題、把「不存在」
與「沒有讀取權」分成兩種錯誤碼、以 +1 reaction 數出未整併的留言則數。這三件事的規則
只該有一份,複製一份到新腳本等於日後改規則要記得改兩個地方。

fetchIssue、countUnmergedComments 與試跑時那句附註一起搬到 lib,issue-extract 改為
呼叫它們,行為不變。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
工作包議題比需求議題多三種結構,抽取契約(#9)要靠它們:

- checklistInSection 收 body 而不收切好的段落。它要交出的 `raw` 是下游勾選 checkbox
  時做精確字串替換的依據,那一行必須逐字等於 body 裡的原樣,連縮排與行尾的 \r 都不能
  動;段落切分會修掉前後空白,給不出這種保證。兩種畸形寫法都不丟內容:巢狀超過一層攤
  進所在待辦的驗收,還沒有上層待辦就先出現的縮排項目升格成待辦。
- tableRows 保留全部欄位,tableSection 改寫成它的兩欄版。介面契約是四欄,先前那一支
  只留兩欄。短的資料列補空字串——正本明講「不產出對外介面就寫一列『無』」,那一列不該
  與「沒有這一段」混為一談。
- referencedIndex 從關聯段落讀出 `需求議題:#N`。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
實作階段的指令給一個議題編號就拿得到它需要的一切,不必吞下整份議題全文。

輸出與議題 #1 的契約一致:待辦與它自己的驗收是巢狀的,每一項都帶未經修改的 `raw`,
下游靠它只改那一行、不重寫整份 body。

body 說不出的三個活狀態另外現查:相依走 dependencies/blocks 兩個端點並逐頁讀完
(半份清單會讓下游把實作順序排錯,那比直接報錯更難發現)、領取人看 assignee、碼錶
走 /user/stopwatches。碼錶那一項受限於 Gitea 只讓人讀自己的錶,真正的語意是「我的錶
正跑在這顆議題上」,這是議題 #1 已接受的取捨;領取鎖看的仍是 assignee。

同樣只讀 body 不讀留言,但回報未處理留言數。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
解析是整條鏈的上游,解析錯則下游全錯,所以模板變體餵得雜一些:缺段落、巢狀驗收為空、
checkbox 已勾、中英混排、圍欄裡的假待辦、只寫一格的表格列。

另外釘住三件容易在日後鬆掉的事:
- `raw` 逐行出現在原始 body 裡,包括 CRLF 的 body 連行尾的 \r 都留著,否則下游替換
  時對不上原文。
- 相依與留言都逐頁讀完,不是只讀第一頁。
- --dry-run 預告的請求順序與實跑一致,且完全不碰 Gitea。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
admin approved these changes 2026-09-17 06:33:34 +00:00
admin merged commit f034f6ec14 into master 2026-09-17 06:33:37 +00:00
admin deleted branch feat/wp-extract-contract/main 2026-09-17 06:33:37 +00:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: plugins/tea-sdlc#33