Merge pull request '收尾寫一筆 skill-end 事件,執行狀態才回報得到助理' (#59) from feat/status-report into develop
Reviewed-on: #59
This commit was merged in pull request #59.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "jsc-sdlc",
|
"name": "jsc-sdlc",
|
||||||
"version": "0.3.0",
|
"version": "0.3.1",
|
||||||
"description": "開發生命週期:規劃、分析、實作、維護(wiki 追蹤)",
|
"description": "開發生命週期:規劃、分析、實作、維護(wiki 追蹤)",
|
||||||
"skills": "./skills",
|
"skills": "./skills",
|
||||||
"author": {
|
"author": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "jsc-sdlc",
|
"name": "jsc-sdlc",
|
||||||
"version": "0.3.0",
|
"version": "0.3.1",
|
||||||
"description": "開發生命週期:規劃、分析、實作、維護(wiki 追蹤)",
|
"description": "開發生命週期:規劃、分析、實作、維護(wiki 追蹤)",
|
||||||
"skills": "./skills",
|
"skills": "./skills",
|
||||||
"jsc": {
|
"jsc": {
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "jsc-sdlc",
|
"name": "jsc-sdlc",
|
||||||
"version": "0.3.0",
|
"version": "0.3.1",
|
||||||
"description": "開發生命週期:規劃、分析、實作、維護(wiki 追蹤)",
|
"description": "開發生命週期:規劃、分析、實作、維護(wiki 追蹤)",
|
||||||
"skills": "./skills/",
|
"skills": "./skills/",
|
||||||
"jsc": {
|
"jsc": {
|
||||||
|
|||||||
+16
-16
@@ -7,37 +7,37 @@
|
|||||||
| 項目 | 內容 |
|
| 項目 | 內容 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| 觸發時機 | 計畫已經寫進 `PLAN_CONTENTS`(CONTENTS 存取庫)、狀態是「未分析」,要把它拆成工作包時用。也用於延伸既有的 `ANALYZE_{HASH}` 分析頁。要寫程式碼時不用,那是 `implement`。`PLAN_CONTENTS` 還沒有計畫時不用,先跑 `plan`。 |
|
| 觸發時機 | 計畫已經寫進 `PLAN_CONTENTS`(CONTENTS 存取庫)、狀態是「未分析」,要把它拆成工作包時用。也用於延伸既有的 `ANALYZE_{HASH}` 分析頁。要寫程式碼時不用,那是 `implement`。`PLAN_CONTENTS` 還沒有計畫時不用,先跑 `plan`。 |
|
||||||
| 關鍵步驟 | 跑 `model-tags.sh sync` 與 `sdlc-gate.sh lock analyze` 過模型閘門,本階段要 `reasoning-max` 標籤、用 `gitea.sh wiki-repo CONTENTS` 解出目錄頁存取庫,並行讀 `PLAN_CONTENTS` 與 `ANALYZE_CONTENTS`、讓使用者選延伸既有分析或分析新計畫、跑 `git fetch --prune origin` 後確認來源分支,並核對 HEAD 與 `origin/{source-branch}` 指到同一個 commit,有落差就停下回報、逐則使用者故事問到共識、先查 `REPO_{HASH}` 盤點頁(雜湊取自該存取庫自己的 `{owner}/{repo}`)決定複用,資料過期就開 sub agent 重新盤點,把 `REPO_{HASH}` 寫回 REPO 存取庫、`REPO_CONTENTS` 用 `wiki-contents.sh upsert REPO 1 {owner}/{repo}` 寫回、做 WBS 拆工作包並標相依,交付工作包固定編為 `WP-01` 且獨立不併入實作包、用 CPM 估工時與天數,標出要徑並依 `references/cpm-chart.md` 畫 mermaid 甘特圖、寫使用者故事驗收計畫,再逐包寫 TDD 待辦、一次寫入 `ANALYZE_{HASH}`(ANALYZE 存取庫),再用 `wiki-contents.sh upsert ANALYZE 3 {HASH}` 與 `wiki-contents.sh upsert PLAN 4 {HASH}` 各自單列 upsert、目錄列的分析頁與盤點頁連結一律取自 `gitea.sh wiki-url` 的絕對網址,並依退出碼分流(`0` 用它印出的網址,`4` 回頭補寫那頁再回來,`5`、`7`、`8` 停下回報,一律不自行組網址、也不留空白連結)、每個要放進頁面或目錄列的連結一律寫成 `[{文字}]({連結})`,不用 `[[頁名]]` 或 `[[顯示文字|頁名]]`,而且寫入前先整批交給 `jsc-gitea/tools/link-check.sh`,結束碼 0 才寫,有 DEAD 就整筆不寫並回報連不到的清單(`2` 補參數重跑、`3` 先設好 `GITEA_HOST`、`7` 金鑰失效停下回報,不得當成連不到)、目錄列檔與待寫日誌檔一律用 Bash 的 heredoc 或 `mktemp` 產在暫存目錄,不走 Write 或 Edit 工具,因為 `write-guard.sh` 的 stage 模式只看階段鎖不看路徑,走工具會被自己的閘門擋下、跑 `tools/stage-report.sh analyze` 收尾回報,目錄頁一律用 `--page CONTENTS:{頁名}`。 |
|
| 關鍵步驟 | 跑 `model-tags.sh sync` 與 `sdlc-gate.sh lock analyze` 過模型閘門,本階段要 `reasoning-max` 標籤、用 `gitea.sh wiki-repo CONTENTS` 解出目錄頁存取庫,並行讀 `PLAN_CONTENTS` 與 `ANALYZE_CONTENTS`、讓使用者選延伸既有分析或分析新計畫、跑 `git fetch --prune origin` 後確認來源分支,並核對 HEAD 與 `origin/{source-branch}` 指到同一個 commit,有落差就停下回報、逐則使用者故事問到共識、先查 `REPO_{HASH}` 盤點頁(雜湊取自該存取庫自己的 `{owner}/{repo}`)決定複用,資料過期就開 sub agent 重新盤點,把 `REPO_{HASH}` 寫回 REPO 存取庫、`REPO_CONTENTS` 用 `wiki-contents.sh upsert REPO 1 {owner}/{repo}` 寫回、做 WBS 拆工作包並標相依,交付工作包固定編為 `WP-01` 且獨立不併入實作包、用 CPM 估工時與天數,標出要徑並依 `references/cpm-chart.md` 畫 mermaid 甘特圖、寫使用者故事驗收計畫,再逐包寫 TDD 待辦、一次寫入 `ANALYZE_{HASH}`(ANALYZE 存取庫),再用 `wiki-contents.sh upsert ANALYZE 3 {HASH}` 與 `wiki-contents.sh upsert PLAN 4 {HASH}` 各自單列 upsert、目錄列的分析頁與盤點頁連結一律取自 `gitea.sh wiki-url` 的絕對網址,並依退出碼分流(`0` 用它印出的網址,`4` 回頭補寫那頁再回來,`5`、`7`、`8` 停下回報,一律不自行組網址、也不留空白連結)、每個要放進頁面或目錄列的連結一律寫成 `[{文字}]({連結})`,不用 `[[頁名]]` 或 `[[顯示文字|頁名]]`,而且寫入前先整批交給 `jsc-gitea/tools/link-check.sh`,結束碼 0 才寫,有 DEAD 就整筆不寫並回報連不到的清單(`2` 補參數重跑、`3` 先設好 `GITEA_HOST`、`7` 金鑰失效停下回報,不得當成連不到)、目錄列檔與待寫日誌檔一律用 Bash 的 heredoc 或 `mktemp` 產在暫存目錄,不走 Write 或 Edit 工具,因為 `write-guard.sh` 的 stage 模式只看階段鎖不看路徑,走工具會被自己的閘門擋下、跑 `tools/stage-report.sh analyze` 收尾回報,目錄頁一律用 `--page CONTENTS:{頁名}`、階段回報之後緊接著跑 `jsc-hooks/tools/report-status.sh skill-end jsc-sdlc:analyze {status} {結束碼} [detail]` 寫一筆結束事件,模型閘門擋下或 HEAD 與 `origin/{source-branch}` 有落差填 `blocked`,分析頁寫成功但目錄列沒跟上填 `degraded`,找不到腳本就安靜跳過,這一步失敗不改變本次階段的結論。 |
|
||||||
| 外部呼叫 | `jsc-cli/tools/model-tags.sh sync`、`jsc-hooks/hooks/sdlc-gate.sh lock`、`jsc-hooks/hooks/write-guard.sh`(claude 的 `PreToolUse` 擋寫入)、`jsc-gitea:wiki`、`jsc-gitea/tools/hash-id`、`jsc-gitea/tools/gitea.sh` 的 `wiki-repo` 與 `wiki-url`、`jsc-gitea/tools/wiki-contents.sh upsert`、`jsc-gitea/tools/link-check.sh`、`jsc-ask:ask`、`tools/stage-report.sh`、`git fetch --prune origin`、`git branch -r`、`git rev-list --left-right --count`。 |
|
| 外部呼叫 | `jsc-cli/tools/model-tags.sh sync`、`jsc-hooks/hooks/sdlc-gate.sh lock`、`jsc-hooks/hooks/write-guard.sh`(claude 的 `PreToolUse` 擋寫入)、`jsc-gitea:wiki`、`jsc-gitea/tools/hash-id`、`jsc-gitea/tools/gitea.sh` 的 `wiki-repo` 與 `wiki-url`、`jsc-gitea/tools/wiki-contents.sh upsert`、`jsc-gitea/tools/link-check.sh`、`jsc-ask:ask`、`tools/stage-report.sh`、`jsc-hooks/tools/report-status.sh skill-end`、`git fetch --prune origin`、`git branch -r`、`git rev-list --left-right --count`。 |
|
||||||
| 完成條件 | 模型閘門退出 0 並回報實際模型 id、來源分支經使用者確認且與遠端一致、每則使用者故事達成共識、每個複用決策連理由記進「複用決策」欄、每則故事對應至少一個編號工作包、每包有工時與天數、要徑與甘特圖齊備、每個實作包至少一則測試先行的 `[ ]` 待辦、`ANALYZE_{HASH}` 存進 wiki 且未決項欄有值(沒有就寫「無」)、每個目錄列的頁面連結都來自退出 0 的 `wiki-url`,非 0 依 `4`、`5`、`7`、`8` 分流並講出退出碼、每一頁與每一列寫出去之前都經 `link-check.sh` 退出 0 驗過,連結格式一律是 `[{文字}]({連結})`、每次目錄頁寫入都講出 `wiki-contents.sh` 的退出碼並依碼分流(`0` 續行,`1`、`3`、`7`、`8` 停下回報,`2` 修參數重跑,`4` 在本技能一律帶範本的呼叫方式下不會出現,真的出現就確認 plugin 安裝完整後重跑)、`stage-report.sh` 的輸出原樣貼給使用者。提前停下也要跑收尾回報。 |
|
| 完成條件 | 模型閘門退出 0 並回報實際模型 id、來源分支經使用者確認且與遠端一致、每則使用者故事達成共識、每個複用決策連理由記進「複用決策」欄、每則故事對應至少一個編號工作包、每包有工時與天數、要徑與甘特圖齊備、每個實作包至少一則測試先行的 `[ ]` 待辦、`ANALYZE_{HASH}` 存進 wiki 且未決項欄有值(沒有就寫「無」)、每個目錄列的頁面連結都來自退出 0 的 `wiki-url`,非 0 依 `4`、`5`、`7`、`8` 分流並講出退出碼、每一頁與每一列寫出去之前都經 `link-check.sh` 退出 0 驗過,連結格式一律是 `[{文字}]({連結})`、每次目錄頁寫入都講出 `wiki-contents.sh` 的退出碼並依碼分流(`0` 續行,`1`、`3`、`7`、`8` 停下回報,`2` 修參數重跑,`4` 在本技能一律帶範本的呼叫方式下不會出現,真的出現就確認 plugin 安裝完整後重跑)、`stage-report.sh` 的輸出原樣貼給使用者、已寫一筆 `skill-end` 事件,狀態照 SKILL.md 收尾步驟那張對應表選定。提前停下也要跑收尾回報,結束事件一樣要寫;只有找不到 `report-status.sh` 才准沒有這一筆。 |
|
||||||
| 可驗證跡象 | ANALYZE 存取庫多一頁或更新一頁 `ANALYZE_{HASH}`;CONTENTS 存取庫的 `ANALYZE_CONTENTS` 多一列該分析,連結是絕對網址;`PLAN_CONTENTS` 該計畫那列狀態變成「已分析」;重新盤點時 REPO 存取庫多一頁 `REPO_{HASH}`,`REPO_CONTENTS` 多一列;`$JSC_HOME/sessions/{工作階段 id}.stage` 是 `sdlc-gate.sh lock` 寫的階段鎖狀態檔;還沒有工作日誌時,`$JSC_HOME/worklog-pending/{HASH}/` 下有暫存的日誌內容檔;`stage-report.sh` 的「寫入的 wiki 頁」表格多一欄連結驗證,逐列標「通過、無可查端點、連不到、未驗證」,頁面上找不到 `[[...]]` 寫法的連結。工作目錄的檔案一律不動,程式碼沒有任何改動。 |
|
| 可驗證跡象 | ANALYZE 存取庫多一頁或更新一頁 `ANALYZE_{HASH}`;CONTENTS 存取庫的 `ANALYZE_CONTENTS` 多一列該分析,連結是絕對網址;`PLAN_CONTENTS` 該計畫那列狀態變成「已分析」;重新盤點時 REPO 存取庫多一頁 `REPO_{HASH}`,`REPO_CONTENTS` 多一列;`$JSC_HOME/sessions/{工作階段 id}.stage` 是 `sdlc-gate.sh lock` 寫的階段鎖狀態檔;還沒有工作日誌時,`$JSC_HOME/worklog-pending/{HASH}/` 下有暫存的日誌內容檔;`stage-report.sh` 的「寫入的 wiki 頁」表格多一欄連結驗證,逐列標「通過、無可查端點、連不到、未驗證」,頁面上找不到 `[[...]]` 寫法的連結;`$JSC_HOME/usage/events.jsonl` 多一筆 `{kind:skill,phase:end}` 的事件,`name` 是 `jsc-sdlc:analyze`,`status` 是五個值之一。工作目錄的檔案一律不動,程式碼沒有任何改動。 |
|
||||||
|
|
||||||
## implement
|
## implement
|
||||||
|
|
||||||
| 項目 | 內容 |
|
| 項目 | 內容 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| 觸發時機 | 分析頁已經有工作包與 TDD 待辦,要動手寫程式碼時用。也用於回頭處理既有工作包 PR 的留言。規劃或分析階段不用。`ANALYZE_CONTENTS` 沒有未完成分析頁時不用。 |
|
| 觸發時機 | 分析頁已經有工作包與 TDD 待辦,要動手寫程式碼時用。也用於回頭處理既有工作包 PR 的留言。規劃或分析階段不用。`ANALYZE_CONTENTS` 沒有未完成分析頁時不用。 |
|
||||||
| 關鍵步驟 | 跑 `model-tags.sh sync` 與 `sdlc-gate.sh lock implement` 過模型閘門,本階段要 `coding` 標籤、從 CONTENTS 存取庫讀 `ANALYZE_CONTENTS`、從 ANALYZE 存取庫讀每一頁未完成分析頁,這份資料後續步驟重用不再讀第二次、對每支未合併 PR 並行跑 `wp-gate.sh check` 取狀態與留言、動任何 PR 之前先跑 `wp-gate.sh owns` 確認歸屬,`foreign` 就放手、每則留言先經 `jsc-ask:ask` 取得共識,再由 sub agent 在同一個 worktree 內修、推同一條工作分支、逐則留言用 `gitea.sh comment-reply` 回覆處置結果,把 `latest=` 時間寫回分析頁 PR 欄、一輪留言修正算一個任務,當下寫一筆 `jsc-log:worklog`、列出可挑的工作包,每個候選並行跑 `wp-gate.sh check-deps` 過相依閘門,只有 `ready` 進選項、使用者挑定後跑 `wp-gate.sh claim` 登錄歸屬、確認來源分支,它同時是 worktree 基準與 PR 目標,遠端找不到就停下回報、產生 `TICKET_{yyyyMMdd}_{HHmmss}_{HASH}` 工作證並寫回分析頁「工作證」欄,同時改工作階段名稱、交付包先問交付內容型別並寫回「交付型別」欄、`git fetch --prune origin` 後從 `origin/{source-branch}` 建 worktree,多存取庫並行建、逐項待辦各開一個 sub agent 跑 TDD,主代理每完成一項就把 `[ ]` 翻成 `[x]` 並存回 wiki、收尾並行跑 `jsc-review:code-review` 與 `jsc-review:api-doc`,後者先用 `swagger-detect.sh` 判定,退出碼 1 就明確略過並回報、跑 `jsc-git:pr` 開 PR 回來源分支,把 PR 連結寫回分析頁,再跑 `wp-gate.sh lock` 上鎖、寫一筆工作日誌,接著用 `pr-watch.sh` 輪詢等合併,退出碼 10 就回頭跑同一套留言處理、合併後移除 worktree 並把工作包標為完成、問交付格式並產出 `DELIVER_{HASH}` wiki 頁(寫進 DELIVER 存取庫,雜湊取自 `{owner}/{repo}` 加工作包編號,一包一頁不互相覆蓋)或 Gitea issue 留言,交付頁再用 `wiki-contents.sh upsert DELIVER 6 {HASH}` 把 `DELIVER_CONTENTS` 那一列寫回,連結取自 `gitea.sh wiki-url` 的絕對網址並依退出碼分流(`0` 用它印出的網址,`4` 回頭補寫交付頁再回來,`5`、`7`、`8` 停下回報,一律不自行組網址、也不留空白連結)、每個要放進頁面、目錄列、PR 欄或 issue 留言的連結一律寫成 `[{文字}]({連結})`,不用 `[[頁名]]` 或 `[[顯示文字|頁名]]`,而且寫入前先整批交給 `jsc-gitea/tools/link-check.sh`,結束碼 0 才寫,有 DEAD 就整筆不寫並回報連不到的清單(`2` 補參數重跑、`3` 先設好 `GITEA_HOST`、`7` 金鑰失效停下回報,不得當成連不到)、問要不要登錄維護並用 `wiki-contents.sh upsert MAINTAIN 1 {owner}/{repo}` 寫回 `MAINTAIN_CONTENTS`、跑 `tools/stage-report.sh implement` 收尾回報,目錄頁一律用 `--page CONTENTS:{頁名}`。 |
|
| 關鍵步驟 | 跑 `model-tags.sh sync` 與 `sdlc-gate.sh lock implement` 過模型閘門,本階段要 `coding` 標籤、從 CONTENTS 存取庫讀 `ANALYZE_CONTENTS`、從 ANALYZE 存取庫讀每一頁未完成分析頁,這份資料後續步驟重用不再讀第二次、對每支未合併 PR 並行跑 `wp-gate.sh check` 取狀態與留言、動任何 PR 之前先跑 `wp-gate.sh owns` 確認歸屬,`foreign` 就放手、每則留言先經 `jsc-ask:ask` 取得共識,再由 sub agent 在同一個 worktree 內修、推同一條工作分支、逐則留言用 `gitea.sh comment-reply` 回覆處置結果,把 `latest=` 時間寫回分析頁 PR 欄、一輪留言修正算一個任務,當下寫一筆 `jsc-log:worklog`、列出可挑的工作包,每個候選並行跑 `wp-gate.sh check-deps` 過相依閘門,只有 `ready` 進選項、使用者挑定後跑 `wp-gate.sh claim` 登錄歸屬、確認來源分支,它同時是 worktree 基準與 PR 目標,遠端找不到就停下回報、產生 `TICKET_{yyyyMMdd}_{HHmmss}_{HASH}` 工作證並寫回分析頁「工作證」欄,同時改工作階段名稱、交付包先問交付內容型別並寫回「交付型別」欄、`git fetch --prune origin` 後從 `origin/{source-branch}` 建 worktree,多存取庫並行建、逐項待辦各開一個 sub agent 跑 TDD,主代理每完成一項就把 `[ ]` 翻成 `[x]` 並存回 wiki、收尾並行跑 `jsc-review:code-review` 與 `jsc-review:api-doc`,後者先用 `swagger-detect.sh` 判定,退出碼 1 就明確略過並回報、跑 `jsc-git:pr` 開 PR 回來源分支,把 PR 連結寫回分析頁,再跑 `wp-gate.sh lock` 上鎖、寫一筆工作日誌,接著用 `pr-watch.sh` 輪詢等合併,退出碼 10 就回頭跑同一套留言處理、合併後移除 worktree 並把工作包標為完成、問交付格式並產出 `DELIVER_{HASH}` wiki 頁(寫進 DELIVER 存取庫,雜湊取自 `{owner}/{repo}` 加工作包編號,一包一頁不互相覆蓋)或 Gitea issue 留言,交付頁再用 `wiki-contents.sh upsert DELIVER 6 {HASH}` 把 `DELIVER_CONTENTS` 那一列寫回,連結取自 `gitea.sh wiki-url` 的絕對網址並依退出碼分流(`0` 用它印出的網址,`4` 回頭補寫交付頁再回來,`5`、`7`、`8` 停下回報,一律不自行組網址、也不留空白連結)、每個要放進頁面、目錄列、PR 欄或 issue 留言的連結一律寫成 `[{文字}]({連結})`,不用 `[[頁名]]` 或 `[[顯示文字|頁名]]`,而且寫入前先整批交給 `jsc-gitea/tools/link-check.sh`,結束碼 0 才寫,有 DEAD 就整筆不寫並回報連不到的清單(`2` 補參數重跑、`3` 先設好 `GITEA_HOST`、`7` 金鑰失效停下回報,不得當成連不到)、問要不要登錄維護並用 `wiki-contents.sh upsert MAINTAIN 1 {owner}/{repo}` 寫回 `MAINTAIN_CONTENTS`、跑 `tools/stage-report.sh implement` 收尾回報,目錄頁一律用 `--page CONTENTS:{頁名}`、階段回報之後緊接著跑 `jsc-hooks/tools/report-status.sh skill-end jsc-sdlc:implement {status} {結束碼} [detail]` 寫一筆結束事件,模型閘門擋下、候選全被 `check-deps` 判 `blocked`、`owns` 判 `foreign` 或來源分支在遠端找不到都填 `blocked`,工作包已合併但交付目錄列或維護登錄沒寫成填 `degraded`,找不到腳本就安靜跳過,這一步失敗不改變本次階段的結論。 |
|
||||||
| 外部呼叫 | `jsc-cli/tools/model-tags.sh sync`、`jsc-hooks/hooks/sdlc-gate.sh lock`、`tools/wp-gate.sh` 的 `check`、`check-deps`、`claim`、`lock`、`owns`、`tools/stage-report.sh`、`jsc-gitea:wiki`、`jsc-gitea/tools/hash-id`、`jsc-gitea/tools/gitea.sh`(`wiki-repo`、`wiki-url`、`comment-reply` 與 issue 留言 API)、`jsc-gitea/tools/wiki-contents.sh upsert`、`jsc-gitea/tools/link-check.sh`、`jsc-gitea/tools/pr-watch.sh`、`jsc-ask:ask`、`jsc-review:code-review`、`jsc-review:api-doc`、`jsc-review/tools/swagger-detect.sh`、`jsc-hooks/hooks/comment-scope.sh`、`jsc-git:commit`、`jsc-git:pr`、`jsc-log:worklog`、`git fetch`、`git worktree`。 |
|
| 外部呼叫 | `jsc-cli/tools/model-tags.sh sync`、`jsc-hooks/hooks/sdlc-gate.sh lock`、`tools/wp-gate.sh` 的 `check`、`check-deps`、`claim`、`lock`、`owns`、`tools/stage-report.sh`、`jsc-gitea:wiki`、`jsc-gitea/tools/hash-id`、`jsc-gitea/tools/gitea.sh`(`wiki-repo`、`wiki-url`、`comment-reply` 與 issue 留言 API)、`jsc-gitea/tools/wiki-contents.sh upsert`、`jsc-gitea/tools/link-check.sh`、`jsc-gitea/tools/pr-watch.sh`、`jsc-ask:ask`、`jsc-review:code-review`、`jsc-review:api-doc`、`jsc-review/tools/swagger-detect.sh`、`jsc-hooks/hooks/comment-scope.sh`、`jsc-git:commit`、`jsc-git:pr`、`jsc-log:worklog`、`jsc-hooks/tools/report-status.sh skill-end`、`git fetch`、`git worktree`。 |
|
||||||
| 完成條件 | 模型閘門退出 0、每支未合併 PR 的留言都有處置與回覆、挑中的工作包經 `check-deps` 判為 `ready` 並 `claim` 成功、來源分支經確認並記進分析頁、工作證寫上 wiki、該包每一項待辦在 wiki 上都是 `[x]`、兩個收尾稽核都放行(`api-doc` 回報略過也算放行)、PR 開好且 `wp-gate.sh lock` 回 `status=locked`、工作日誌已寫、`pr-watch.sh` 退出 0 且 `wp-gate.sh check` 回 `status=merged`、交付文件已產出、交付頁那列的連結來自退出 0 的 `wiki-url`,非 0 依 `4`、`5`、`7`、`8` 分流並講出退出碼、每一頁、每一列與每一則 issue 留言寫出去之前都經 `link-check.sh` 退出 0 驗過,連結格式一律是 `[{文字}]({連結})`、維護登錄問題已回答、每次目錄頁寫入都講出 `wiki-contents.sh` 的退出碼並依碼分流(`0` 續行,`1`、`3`、`7`、`8` 停下回報,`2` 修參數重跑,`4` 在本技能一律帶範本的呼叫方式下不會出現,真的出現就確認 plugin 安裝完整後重跑)、`stage-report.sh` 的輸出原樣貼出並列出 worktree 與三條分支。提前停下也要跑收尾回報。 |
|
| 完成條件 | 模型閘門退出 0、每支未合併 PR 的留言都有處置與回覆、挑中的工作包經 `check-deps` 判為 `ready` 並 `claim` 成功、來源分支經確認並記進分析頁、工作證寫上 wiki、該包每一項待辦在 wiki 上都是 `[x]`、兩個收尾稽核都放行(`api-doc` 回報略過也算放行)、PR 開好且 `wp-gate.sh lock` 回 `status=locked`、工作日誌已寫、`pr-watch.sh` 退出 0 且 `wp-gate.sh check` 回 `status=merged`、交付文件已產出、交付頁那列的連結來自退出 0 的 `wiki-url`,非 0 依 `4`、`5`、`7`、`8` 分流並講出退出碼、每一頁、每一列與每一則 issue 留言寫出去之前都經 `link-check.sh` 退出 0 驗過,連結格式一律是 `[{文字}]({連結})`、維護登錄問題已回答、每次目錄頁寫入都講出 `wiki-contents.sh` 的退出碼並依碼分流(`0` 續行,`1`、`3`、`7`、`8` 停下回報,`2` 修參數重跑,`4` 在本技能一律帶範本的呼叫方式下不會出現,真的出現就確認 plugin 安裝完整後重跑)、`stage-report.sh` 的輸出原樣貼出並列出 worktree 與三條分支、已寫一筆 `skill-end` 事件,狀態照 SKILL.md 收尾步驟那張對應表選定。提前停下也要跑收尾回報,結束事件一樣要寫;只有找不到 `report-status.sh` 才准沒有這一筆。 |
|
||||||
| 可驗證跡象 | 開出一條工作分支,並有一支回到來源分支的 PR;ANALYZE 存取庫的分析頁 `ANALYZE_{HASH}` 的「工作證」欄(值是 `TICKET_{yyyyMMdd}_{HHmmss}_{HASH}`,帶著 `hash-id` 原樣印出的雜湊)、「交付型別」欄、PR 欄、待辦勾選狀態都更新過;DELIVER 存取庫多一頁 `DELIVER_{HASH}`,或該 issue 下多一則留言;CONTENTS 存取庫的 `DELIVER_CONTENTS` 多一列,連結是絕對網址;使用者同意登錄時 `MAINTAIN_CONTENTS` 多一列;`LOG_{HASH}` 每完成一個任務多一筆條目;`$JSC_HOME/wp/{owner}-{repo}.claim` 與 `$JSC_HOME/wp/{owner}-{repo}-{index}.pr` 兩個狀態檔;`{cwd}/.worktree/{分析-HASH}/{工作包編號}/{repo}` 目錄,PR 合併後被移除;該存取庫 `.git/info/exclude` 多一筆 `.worktree/`;PR 每則留言底下有回覆;`stage-report.sh` 的「寫入的 wiki 頁」表格多一欄連結驗證,逐列標「通過、無可查端點、連不到、未驗證」,寫出去的頁面與留言都找不到 `[[...]]` 寫法的連結。 |
|
| 可驗證跡象 | 開出一條工作分支,並有一支回到來源分支的 PR;ANALYZE 存取庫的分析頁 `ANALYZE_{HASH}` 的「工作證」欄(值是 `TICKET_{yyyyMMdd}_{HHmmss}_{HASH}`,帶著 `hash-id` 原樣印出的雜湊)、「交付型別」欄、PR 欄、待辦勾選狀態都更新過;DELIVER 存取庫多一頁 `DELIVER_{HASH}`,或該 issue 下多一則留言;CONTENTS 存取庫的 `DELIVER_CONTENTS` 多一列,連結是絕對網址;使用者同意登錄時 `MAINTAIN_CONTENTS` 多一列;`LOG_{HASH}` 每完成一個任務多一筆條目;`$JSC_HOME/wp/{owner}-{repo}.claim` 與 `$JSC_HOME/wp/{owner}-{repo}-{index}.pr` 兩個狀態檔;`{cwd}/.worktree/{分析-HASH}/{工作包編號}/{repo}` 目錄,PR 合併後被移除;該存取庫 `.git/info/exclude` 多一筆 `.worktree/`;PR 每則留言底下有回覆;`stage-report.sh` 的「寫入的 wiki 頁」表格多一欄連結驗證,逐列標「通過、無可查端點、連不到、未驗證」,寫出去的頁面與留言都找不到 `[[...]]` 寫法的連結;`$JSC_HOME/usage/events.jsonl` 多一筆 `{kind:skill,phase:end}` 的事件,`name` 是 `jsc-sdlc:implement`,`status` 是五個值之一。 |
|
||||||
|
|
||||||
## maintain
|
## maintain
|
||||||
|
|
||||||
| 項目 | 內容 |
|
| 項目 | 內容 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| 觸發時機 | 已交付、且已登錄在 `MAINTAIN_CONTENTS`(CONTENTS 存取庫)的專案要做定期保養時用。還在實作中的專案不用。沒有登錄進 `MAINTAIN_CONTENTS` 的專案不用。 |
|
| 觸發時機 | 已交付、且已登錄在 `MAINTAIN_CONTENTS`(CONTENTS 存取庫)的專案要做定期保養時用。還在實作中的專案不用。沒有登錄進 `MAINTAIN_CONTENTS` 的專案不用。 |
|
||||||
| 關鍵步驟 | 跑 `model-tags.sh sync` 與 `sdlc-gate.sh lock maintain` 過模型閘門,本階段不要求特定標籤,只要判定得出實際模型 id、用 `gitea.sh wiki-repo CONTENTS` 解出存取庫後讀 `MAINTAIN_CONTENTS`(`MAINTAIN` 只有目錄頁、沒有內容頁),篩出還在維護期內的專案(起始日不晚於今天,結束日為空或不早於今天)、主代理先並行對每個專案跑 `git fetch --prune origin`,切到維護分支並與 `origin/{branch}` 對齊,有落差就回報並略過該專案、之後一個專案一個專案跑,每個專案的維護都開一個 sub agent、每個專案提出至少五項維護做法給使用者挑、把改動用 `jsc-git:commit` 提交到新分支,推送後用 `jsc-git:pr` 開 PR 回步驟 3.1 那條分支、PR 開好當下寫一筆 `jsc-log:worklog`、用 `wiki-contents.sh upsert MAINTAIN 1 {owner}/{repo}` 把該專案在 `MAINTAIN_CONTENTS` 的「前次維護時間」更新成今天,其餘欄位原樣保留、該頁指向別型別頁的連結一律取自 `gitea.sh wiki-url` 的絕對網址並依退出碼分流(`0` 用它印出的網址,`4` 填「無」或回頭補寫那頁,`5`、`7`、`8` 停下回報,`7` 絕不當成 `4` 填「無」,一律不自行組網址、也不留空白連結)、每個要放進該列的連結一律寫成 `[{文字}]({連結})`,不用 `[[頁名]]` 或 `[[顯示文字|頁名]]`,而且寫入前先整批交給 `jsc-gitea/tools/link-check.sh`,結束碼 0 才寫,有 DEAD 就整列不寫並回報連不到的清單(`2` 補參數重跑、`3` 先設好 `GITEA_HOST`、`7` 金鑰失效停下回報,不得當成連不到)、主代理彙整每個專案的做法、PR 表格列與失敗原因、跑 `tools/stage-report.sh maintain` 收尾回報,目錄頁用 `--page CONTENTS:MAINTAIN_CONTENTS`。 |
|
| 關鍵步驟 | 跑 `model-tags.sh sync` 與 `sdlc-gate.sh lock maintain` 過模型閘門,本階段不要求特定標籤,只要判定得出實際模型 id、用 `gitea.sh wiki-repo CONTENTS` 解出存取庫後讀 `MAINTAIN_CONTENTS`(`MAINTAIN` 只有目錄頁、沒有內容頁),篩出還在維護期內的專案(起始日不晚於今天,結束日為空或不早於今天)、主代理先並行對每個專案跑 `git fetch --prune origin`,切到維護分支並與 `origin/{branch}` 對齊,有落差就回報並略過該專案、之後一個專案一個專案跑,每個專案的維護都開一個 sub agent、每個專案提出至少五項維護做法給使用者挑、把改動用 `jsc-git:commit` 提交到新分支,推送後用 `jsc-git:pr` 開 PR 回步驟 3.1 那條分支、PR 開好當下寫一筆 `jsc-log:worklog`、用 `wiki-contents.sh upsert MAINTAIN 1 {owner}/{repo}` 把該專案在 `MAINTAIN_CONTENTS` 的「前次維護時間」更新成今天,其餘欄位原樣保留、該頁指向別型別頁的連結一律取自 `gitea.sh wiki-url` 的絕對網址並依退出碼分流(`0` 用它印出的網址,`4` 填「無」或回頭補寫那頁,`5`、`7`、`8` 停下回報,`7` 絕不當成 `4` 填「無」,一律不自行組網址、也不留空白連結)、每個要放進該列的連結一律寫成 `[{文字}]({連結})`,不用 `[[頁名]]` 或 `[[顯示文字|頁名]]`,而且寫入前先整批交給 `jsc-gitea/tools/link-check.sh`,結束碼 0 才寫,有 DEAD 就整列不寫並回報連不到的清單(`2` 補參數重跑、`3` 先設好 `GITEA_HOST`、`7` 金鑰失效停下回報,不得當成連不到)、主代理彙整每個專案的做法、PR 表格列與失敗原因、跑 `tools/stage-report.sh maintain` 收尾回報,目錄頁用 `--page CONTENTS:MAINTAIN_CONTENTS`、階段回報之後緊接著跑 `jsc-hooks/tools/report-status.sh skill-end jsc-sdlc:maintain {status} {結束碼} [detail]` 寫一筆結束事件,模型閘門擋下或在期專案全部與遠端有落差而整批略過填 `blocked`,一部分專案交出 PR、另一部分略過或「前次維護時間」沒更新成填 `degraded`,找不到腳本就安靜跳過,這一步失敗不改變本次階段的結論。 |
|
||||||
| 外部呼叫 | `jsc-cli/tools/model-tags.sh sync`、`jsc-hooks/hooks/sdlc-gate.sh lock`、`jsc-gitea:wiki`、`jsc-gitea/tools/gitea.sh` 的 `wiki-repo` 與 `wiki-url`、`jsc-gitea/tools/wiki-contents.sh upsert`、`jsc-gitea/tools/link-check.sh`、`jsc-ask:ask`、`jsc-git:commit`、`jsc-git:pr`、`jsc-log:worklog`、`jsc-pkg:pkg-update`(選了套件更新才用)、`jsc-hooks/hooks/comment-scope.sh`、`tools/stage-report.sh`、`git fetch --prune origin`。 |
|
| 外部呼叫 | `jsc-cli/tools/model-tags.sh sync`、`jsc-hooks/hooks/sdlc-gate.sh lock`、`jsc-gitea:wiki`、`jsc-gitea/tools/gitea.sh` 的 `wiki-repo` 與 `wiki-url`、`jsc-gitea/tools/wiki-contents.sh upsert`、`jsc-gitea/tools/link-check.sh`、`jsc-ask:ask`、`jsc-git:commit`、`jsc-git:pr`、`jsc-log:worklog`、`jsc-pkg:pkg-update`(選了套件更新才用)、`jsc-hooks/hooks/comment-scope.sh`、`tools/stage-report.sh`、`jsc-hooks/tools/report-status.sh skill-end`、`git fetch --prune origin`。 |
|
||||||
| 完成條件 | 模型閘門退出 0、步驟 2 列出的每個在期專案都跑完自己的 sub agent,各自收在一條 PR 連結或一個記錄下來的略過原因、每個完成的專案都有一筆工作日誌,而且下一個專案開始前就存好、`wiki-contents.sh` 退出 0 且退出碼有講出來(`1`、`3`、`7`、`8` 停下回報,`2` 修參數重跑,`4` 在本技能一律帶範本的呼叫方式下不會出現,真的出現就確認 plugin 安裝完整後重跑)、每個跨型別連結都來自退出 0 的 `wiki-url`,非 0 依 `4`、`5`、`7`、`8` 分流並講出退出碼、每一列寫回去之前都經 `link-check.sh` 退出 0 驗過,連結格式一律是 `[{文字}]({連結})`、`MAINTAIN_CONTENTS` 該專案的「前次維護時間」是今天,其他專案那幾列一個位元組都沒變、彙整報告涵蓋每個專案、`stage-report.sh` 的輸出原樣貼給使用者。沒有專案在期時,一樣要跑收尾回報。 |
|
| 完成條件 | 模型閘門退出 0、步驟 2 列出的每個在期專案都跑完自己的 sub agent,各自收在一條 PR 連結或一個記錄下來的略過原因、每個完成的專案都有一筆工作日誌,而且下一個專案開始前就存好、`wiki-contents.sh` 退出 0 且退出碼有講出來(`1`、`3`、`7`、`8` 停下回報,`2` 修參數重跑,`4` 在本技能一律帶範本的呼叫方式下不會出現,真的出現就確認 plugin 安裝完整後重跑)、每個跨型別連結都來自退出 0 的 `wiki-url`,非 0 依 `4`、`5`、`7`、`8` 分流並講出退出碼、每一列寫回去之前都經 `link-check.sh` 退出 0 驗過,連結格式一律是 `[{文字}]({連結})`、`MAINTAIN_CONTENTS` 該專案的「前次維護時間」是今天,其他專案那幾列一個位元組都沒變、彙整報告涵蓋每個專案、`stage-report.sh` 的輸出原樣貼給使用者、已寫一筆 `skill-end` 事件,狀態照 SKILL.md 收尾步驟那張對應表選定。沒有專案在期時,一樣要跑收尾回報並寫結束事件,狀態填 `aborted`;只有找不到 `report-status.sh` 才准沒有這一筆。 |
|
||||||
| 可驗證跡象 | 每個維護過的專案多一條新分支與一支回到 `develop` 或 `master` 的 PR;CONTENTS 存取庫的 `MAINTAIN_CONTENTS` 對應那列的「前次維護時間」變成今天;`LOG_{HASH}` 每個完成的專案多一筆條目;`$JSC_HOME/sessions/{工作階段 id}.stage` 是 `sdlc-gate.sh lock` 寫的階段鎖狀態檔;一個專案都沒完成時,`$JSC_HOME/worklog-pending/{HASH}/` 下有暫存的日誌內容檔;`stage-report.sh` 的「寫入的 wiki 頁」表格多一欄連結驗證,逐列標「通過、無可查端點、連不到、未驗證」,該頁找不到 `[[...]]` 寫法的連結。 |
|
| 可驗證跡象 | 每個維護過的專案多一條新分支與一支回到 `develop` 或 `master` 的 PR;CONTENTS 存取庫的 `MAINTAIN_CONTENTS` 對應那列的「前次維護時間」變成今天;`LOG_{HASH}` 每個完成的專案多一筆條目;`$JSC_HOME/sessions/{工作階段 id}.stage` 是 `sdlc-gate.sh lock` 寫的階段鎖狀態檔;一個專案都沒完成時,`$JSC_HOME/worklog-pending/{HASH}/` 下有暫存的日誌內容檔;`stage-report.sh` 的「寫入的 wiki 頁」表格多一欄連結驗證,逐列標「通過、無可查端點、連不到、未驗證」,該頁找不到 `[[...]]` 寫法的連結;`$JSC_HOME/usage/events.jsonl` 多一筆 `{kind:skill,phase:end}` 的事件,`name` 是 `jsc-sdlc:maintain`,`status` 是五個值之一。 |
|
||||||
|
|
||||||
## plan
|
## plan
|
||||||
|
|
||||||
| 項目 | 內容 |
|
| 項目 | 內容 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| 觸發時機 | 使用者要開新計畫、或要補強既有計畫時用。做分析或寫程式碼時不用。 |
|
| 觸發時機 | 使用者要開新計畫、或要補強既有計畫時用。做分析或寫程式碼時不用。 |
|
||||||
| 關鍵步驟 | 跑 `model-tags.sh sync` 與 `sdlc-gate.sh lock plan` 過模型閘門,本階段要 `reasoning-max` 標籤、用 `gitea.sh wiki-repo CONTENTS` 解出存取庫後讀 `PLAN_CONTENTS`,列出狀態為「未分析」的計畫與各自的 HASH、讓使用者選延伸既有計畫或建立新計畫、依 `references/consensus.md` 跑決策樹,把目標、範圍、可行性三項問到共識,每個答案都要導出下一個問題、把共識寫成「身為⋯⋯我想要⋯⋯以便⋯⋯」格式的使用者故事、套 `templates/plan-page.md` 寫入 `PLAN_{HASH}`(PLAN 存取庫)、用 `wiki-contents.sh upsert PLAN 4 {HASH}` 把這份計畫在 `PLAN_CONTENTS` 的那一列 upsert,狀態填「未分析」、計畫頁連結取自 `gitea.sh wiki-url` 的絕對網址並依退出碼分流(`0` 用它印出的網址,`4` 回頭補寫計畫頁再回來,`5`、`7`、`8` 停下回報,一律不自行組網址、也不留空白連結)、每個要放進頁面或目錄列的連結一律寫成 `[{文字}]({連結})`,不用 `[[頁名]]` 或 `[[顯示文字|頁名]]`,而且寫入前先整批交給 `jsc-gitea/tools/link-check.sh`,結束碼 0 才寫,有 DEAD 就整筆不寫並回報連不到的清單(`2` 補參數重跑、`3` 先設好 `GITEA_HOST`、`7` 金鑰失效停下回報,不得當成連不到)、目錄列檔與待寫日誌檔一律用 Bash 的 heredoc 或 `mktemp` 產在暫存目錄,不走 Write 或 Edit 工具,因為 `write-guard.sh` 的 stage 模式只看階段鎖不看路徑,走工具會被自己的閘門擋下、跑 `tools/stage-report.sh plan` 收尾回報,目錄頁用 `--page CONTENTS:PLAN_CONTENTS`。 |
|
| 關鍵步驟 | 跑 `model-tags.sh sync` 與 `sdlc-gate.sh lock plan` 過模型閘門,本階段要 `reasoning-max` 標籤、用 `gitea.sh wiki-repo CONTENTS` 解出存取庫後讀 `PLAN_CONTENTS`,列出狀態為「未分析」的計畫與各自的 HASH、讓使用者選延伸既有計畫或建立新計畫、依 `references/consensus.md` 跑決策樹,把目標、範圍、可行性三項問到共識,每個答案都要導出下一個問題、把共識寫成「身為⋯⋯我想要⋯⋯以便⋯⋯」格式的使用者故事、套 `templates/plan-page.md` 寫入 `PLAN_{HASH}`(PLAN 存取庫)、用 `wiki-contents.sh upsert PLAN 4 {HASH}` 把這份計畫在 `PLAN_CONTENTS` 的那一列 upsert,狀態填「未分析」、計畫頁連結取自 `gitea.sh wiki-url` 的絕對網址並依退出碼分流(`0` 用它印出的網址,`4` 回頭補寫計畫頁再回來,`5`、`7`、`8` 停下回報,一律不自行組網址、也不留空白連結)、每個要放進頁面或目錄列的連結一律寫成 `[{文字}]({連結})`,不用 `[[頁名]]` 或 `[[顯示文字|頁名]]`,而且寫入前先整批交給 `jsc-gitea/tools/link-check.sh`,結束碼 0 才寫,有 DEAD 就整筆不寫並回報連不到的清單(`2` 補參數重跑、`3` 先設好 `GITEA_HOST`、`7` 金鑰失效停下回報,不得當成連不到)、目錄列檔與待寫日誌檔一律用 Bash 的 heredoc 或 `mktemp` 產在暫存目錄,不走 Write 或 Edit 工具,因為 `write-guard.sh` 的 stage 模式只看階段鎖不看路徑,走工具會被自己的閘門擋下、跑 `tools/stage-report.sh plan` 收尾回報,目錄頁用 `--page CONTENTS:PLAN_CONTENTS`、階段回報之後緊接著跑 `jsc-hooks/tools/report-status.sh skill-end jsc-sdlc:plan {status} {結束碼} [detail]` 寫一筆結束事件,模型閘門擋下填 `blocked`,計畫頁寫成功但 `PLAN_CONTENTS` 那列沒跟上填 `degraded`,找不到腳本就安靜跳過,這一步失敗不改變本次階段的結論。 |
|
||||||
| 外部呼叫 | `jsc-cli/tools/model-tags.sh sync`、`jsc-hooks/hooks/sdlc-gate.sh lock`、`jsc-hooks/hooks/write-guard.sh`(claude 的 `PreToolUse` 擋寫入)、`jsc-gitea:wiki`、`jsc-gitea/tools/hash-id`、`jsc-gitea/tools/gitea.sh` 的 `wiki-repo` 與 `wiki-url`、`jsc-gitea/tools/wiki-contents.sh upsert`、`jsc-gitea/tools/link-check.sh`、`jsc-ask:ask`、`tools/stage-report.sh`。 |
|
| 外部呼叫 | `jsc-cli/tools/model-tags.sh sync`、`jsc-hooks/hooks/sdlc-gate.sh lock`、`jsc-hooks/hooks/write-guard.sh`(claude 的 `PreToolUse` 擋寫入)、`jsc-gitea:wiki`、`jsc-gitea/tools/hash-id`、`jsc-gitea/tools/gitea.sh` 的 `wiki-repo` 與 `wiki-url`、`jsc-gitea/tools/wiki-contents.sh upsert`、`jsc-gitea/tools/link-check.sh`、`jsc-ask:ask`、`tools/stage-report.sh`、`jsc-hooks/tools/report-status.sh skill-end`。 |
|
||||||
| 完成條件 | 模型閘門退出 0 並回報實際模型 id、目標、範圍、可行性三項都達成共識,而且使用者明確確認過覆述的摘要、每個共識項目至少對應一則使用者故事、`PLAN_{HASH}` 存進 wiki 且範本要求的每個區段都有值、沒有留下未填的佔位字、`PLAN_CONTENTS` 該列狀態是「未分析」,計畫頁那格的連結來自退出 0 的 `wiki-url`(非 0 依 `4`、`5`、`7`、`8` 分流並講出退出碼),並經 `link-check.sh` 退出 0 驗過,格式是 `[{文字}]({連結})`,其他列一個位元組都沒變,而且 `wiki-contents.sh` 的退出碼有講出來並依碼分流(`0` 續行,`1`、`3`、`7`、`8` 停下回報,`2` 修參數重跑,`4` 在本技能一律帶範本的呼叫方式下不會出現,真的出現就確認 plugin 安裝完整後重跑)、`stage-report.sh` 的輸出原樣貼給使用者。提前停下也要跑收尾回報。 |
|
| 完成條件 | 模型閘門退出 0 並回報實際模型 id、目標、範圍、可行性三項都達成共識,而且使用者明確確認過覆述的摘要、每個共識項目至少對應一則使用者故事、`PLAN_{HASH}` 存進 wiki 且範本要求的每個區段都有值、沒有留下未填的佔位字、`PLAN_CONTENTS` 該列狀態是「未分析」,計畫頁那格的連結來自退出 0 的 `wiki-url`(非 0 依 `4`、`5`、`7`、`8` 分流並講出退出碼),並經 `link-check.sh` 退出 0 驗過,格式是 `[{文字}]({連結})`,其他列一個位元組都沒變,而且 `wiki-contents.sh` 的退出碼有講出來並依碼分流(`0` 續行,`1`、`3`、`7`、`8` 停下回報,`2` 修參數重跑,`4` 在本技能一律帶範本的呼叫方式下不會出現,真的出現就確認 plugin 安裝完整後重跑)、`stage-report.sh` 的輸出原樣貼給使用者、已寫一筆 `skill-end` 事件,狀態照 SKILL.md 收尾步驟那張對應表選定。提前停下也要跑收尾回報,結束事件一樣要寫;只有找不到 `report-status.sh` 才准沒有這一筆。 |
|
||||||
| 可驗證跡象 | PLAN 存取庫多一頁或更新一頁 `PLAN_{HASH}`;CONTENTS 存取庫的 `PLAN_CONTENTS` 多一列或更新一列,狀態是「未分析」、計畫頁欄位是 `[{文字}]({連結})` 格式的絕對網址;`$JSC_HOME/sessions/{工作階段 id}.stage` 是 `sdlc-gate.sh lock` 寫的階段鎖狀態檔;還沒有工作日誌時,`$JSC_HOME/worklog-pending/{HASH}/` 下有暫存的日誌內容檔;`stage-report.sh` 的「寫入的 wiki 頁」表格多一欄連結驗證,逐列標「通過、無可查端點、連不到、未驗證」,頁面上找不到 `[[...]]` 寫法的連結。工作目錄的檔案一律不動。 |
|
| 可驗證跡象 | PLAN 存取庫多一頁或更新一頁 `PLAN_{HASH}`;CONTENTS 存取庫的 `PLAN_CONTENTS` 多一列或更新一列,狀態是「未分析」、計畫頁欄位是 `[{文字}]({連結})` 格式的絕對網址;`$JSC_HOME/sessions/{工作階段 id}.stage` 是 `sdlc-gate.sh lock` 寫的階段鎖狀態檔;還沒有工作日誌時,`$JSC_HOME/worklog-pending/{HASH}/` 下有暫存的日誌內容檔;`stage-report.sh` 的「寫入的 wiki 頁」表格多一欄連結驗證,逐列標「通過、無可查端點、連不到、未驗證」,頁面上找不到 `[[...]]` 寫法的連結;`$JSC_HOME/usage/events.jsonl` 多一筆 `{kind:skill,phase:end}` 的事件,`name` 是 `jsc-sdlc:plan`,`status` 是五個值之一。工作目錄的檔案一律不動。 |
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
# 階段回報 — 四個階段收尾都要交的東西
|
# 階段回報 — 四個階段收尾都要交的東西
|
||||||
|
|
||||||
規劃、分析、實作、維護跑完,最後一件事一定是階段回報。彙整由 `tools/stage-report.sh` 產出,
|
規劃、分析、實作、維護跑完,最後兩件事固定是這兩筆:先給使用者看的階段回報,再給機器看的
|
||||||
技能只負責把事實餵進去:寫過哪些 wiki 頁、有沒有寫工作日誌、實作階段的工作目錄與三條分支。
|
結束事件。階段回報由 `tools/stage-report.sh` 彙整產出,技能只負責把事實餵進去:寫過哪些
|
||||||
|
wiki 頁、有沒有寫工作日誌、實作階段的工作目錄與三條分支。結束事件見本頁最後一節。
|
||||||
|
|
||||||
## 什麼時候回報
|
## 什麼時候回報
|
||||||
|
|
||||||
@@ -61,3 +62,22 @@
|
|||||||
| 1 | 有警告(缺工作日誌、實作階段沒有 PR、或清單裡有連不到的連結) | 一樣把輸出貼給使用者,連不到的連結照著修。**這是警告不是阻擋**,階段的工作已經做完了 |
|
| 1 | 有警告(缺工作日誌、實作階段沒有 PR、或清單裡有連不到的連結) | 一樣把輸出貼給使用者,連不到的連結照著修。**這是警告不是阻擋**,階段的工作已經做完了 |
|
||||||
| 2 | 用法錯誤 | 修正參數重跑 |
|
| 2 | 用法錯誤 | 修正參數重跑 |
|
||||||
| 3 | 找不到 `gitea.sh` 或 `sdlc-gate.sh` | 修好相依關係再重跑 |
|
| 3 | 找不到 `gitea.sh` 或 `sdlc-gate.sh` | 修好相依關係再重跑 |
|
||||||
|
|
||||||
|
## 結束事件 — 階段回報之後那一筆
|
||||||
|
|
||||||
|
階段回報是給人看的,結束事件是給機器看的。跑完階段回報,緊接著跑
|
||||||
|
`jsc-hooks/tools/report-status.sh skill-end jsc-sdlc:{技能名} {status} {結束碼} [detail]`,
|
||||||
|
一筆寫進 `$JSC_HOME/usage/events.jsonl`。腳本名怎麼寫,比照各技能既有寫
|
||||||
|
`jsc-hooks/hooks/sdlc-gate.sh` 的方式,不另立一套。
|
||||||
|
|
||||||
|
為什麼非得由技能自己寫:配對的 `skill-start` 由 jsc-hooks 自己記,但那個 hook 接在技能工具
|
||||||
|
呼叫之後就觸發,實際工作還在後面的模型輪次,所以**沒有任何 hook 看得到階段怎麼結束**。
|
||||||
|
有 `start` 沒有配對的 `end`,在紀錄裡就是中止;收尾少寫這一筆,跑完的階段每一次都會被算成中止。
|
||||||
|
|
||||||
|
| 項目 | 規則 |
|
||||||
|
| --- | --- |
|
||||||
|
| `status` | `ok`、`blocked`、`failed`、`degraded`、`aborted` 五選一。哪一種情況選哪一個,各技能 SKILL.md 的收尾步驟有自己的對應表,那張表是唯一判準 |
|
||||||
|
| 模型閘門擋下 | 一律 `blocked`,不是 `failed`。閘門擋下不合格的模型是閘門在做事,記成失敗會讓下一手去找一個不存在的缺陷 |
|
||||||
|
| `{結束碼}` | 判定該狀態的那支腳本的結束碼;沒有任何腳本回非 0 就填 `0`,`ok` 與 `aborted` 都是這種 |
|
||||||
|
| `[detail]` | 選填,繁體中文單行,講清楚是什麼決定了這個狀態。腳本截到 200 字元,長內容不要塞 |
|
||||||
|
| 失敗怎麼辦 | **這一步失敗不改變本次階段的結論。** 找不到腳本就安靜跳過,不回報也不重跑任何步驟。三個記錄子命令本來就設計成寫檔失敗也回 0,所以回非 0 只代表呼叫本身寫錯了(`2` 是用法錯誤),修一次參數就好 |
|
||||||
|
|||||||
+16
-1
@@ -12,7 +12,7 @@ This skill is a **logic-only** stage: never output code, and **never modify any
|
|||||||
|
|
||||||
**Content pages and directory pages live in different wiki repos.** `ANALYZE_{HASH}` sits in the repo `jsc-gitea/tools/gitea.sh wiki-repo ANALYZE` resolves, `REPO_{HASH}` in the one `gitea.sh wiki-repo REPO` resolves. All three directory pages — `ANALYZE_CONTENTS`, `PLAN_CONTENTS` and `REPO_CONTENTS` — sit in the repo `gitea.sh wiki-repo CONTENTS` resolves: `JSC_WIKI_REPO_CONTENTS` first, `JSC_WIKI_REPO` second, exit 3 when neither is set; it **never** falls back to `JSC_WIKI_REPO_ANALYZE`, `JSC_WIKI_REPO_PLAN` or `JSC_WIKI_REPO_REPO`. Every directory row links its content page by the absolute URL from `gitea.sh wiki-url {content repo} {page}`, written as `[{text}]({url})` — one link syntax, whichever wiki the two pages sit in. The syntax and the check that runs before every write: "Every link is checked before it reaches a page" below.
|
**Content pages and directory pages live in different wiki repos.** `ANALYZE_{HASH}` sits in the repo `jsc-gitea/tools/gitea.sh wiki-repo ANALYZE` resolves, `REPO_{HASH}` in the one `gitea.sh wiki-repo REPO` resolves. All three directory pages — `ANALYZE_CONTENTS`, `PLAN_CONTENTS` and `REPO_CONTENTS` — sit in the repo `gitea.sh wiki-repo CONTENTS` resolves: `JSC_WIKI_REPO_CONTENTS` first, `JSC_WIKI_REPO` second, exit 3 when neither is set; it **never** falls back to `JSC_WIKI_REPO_ANALYZE`, `JSC_WIKI_REPO_PLAN` or `JSC_WIKI_REPO_REPO`. Every directory row links its content page by the absolute URL from `gitea.sh wiki-url {content repo} {page}`, written as `[{text}]({url})` — one link syntax, whichever wiki the two pages sit in. The syntax and the check that runs before every write: "Every link is checked before it reaches a page" below.
|
||||||
|
|
||||||
All wiki reads and writes go through `jsc-gitea:wiki`. **A failed wiki read or write stops this stage**: report which page and which operation failed, never carry on against a page you could not read, and never report a page as saved when the write failed. Step 11 still runs after such a stop.
|
All wiki reads and writes go through `jsc-gitea:wiki`. **A failed wiki read or write stops this stage**: report which page and which operation failed, never carry on against a page you could not read, and never report a page as saved when the write failed. Steps 11 and 12 still run after such a stop.
|
||||||
|
|
||||||
## Steps
|
## Steps
|
||||||
|
|
||||||
@@ -47,6 +47,21 @@ All wiki reads and writes go through `jsc-gitea:wiki`. **A failed wiki read or w
|
|||||||
|
|
||||||
Both runs branch on the exit code per "Contents pages are appended, never overwritten" below. Completion condition: the analysis page is saved on the wiki carrying every section the template dictates — the source branch, the head sha and the 未決項 section (「無」 when there is none) included — every `wiki-url` call this step made returned 0 and its URL is the one in the row, every link written by this step was cleared by a `link-check.sh` run that exited 0, both `wiki-contents.sh` runs exited 0, and `ANALYZE_CONTENTS` shows this analysis's row while `PLAN_CONTENTS` shows the literal 「已分析」.
|
Both runs branch on the exit code per "Contents pages are appended, never overwritten" below. Completion condition: the analysis page is saved on the wiki carrying every section the template dictates — the source branch, the head sha and the 未決項 section (「無」 when there is none) included — every `wiki-url` call this step made returned 0 and its URL is the one in the row, every link written by this step was cleared by a `link-check.sh` run that exited 0, both `wiki-contents.sh` runs exited 0, and `ANALYZE_CONTENTS` shows this analysis's row while `PLAN_CONTENTS` shows the literal 「已分析」.
|
||||||
11. **Stage report — the last thing this stage does, including every early stop** (the model gate blocked, the working tree did not match `origin/{source-branch}`, no plan was selectable, a wiki read or write failed). Run `tools/stage-report.sh analyze` with one `--page TYPE:{page}` per wiki page this run wrote — `--page ANALYZE:ANALYZE_{HASH}`, `--page CONTENTS:ANALYZE_CONTENTS`, `--page CONTENTS:PLAN_CONTENTS`, and `--page REPO:REPO_{HASH}` plus `--page CONTENTS:REPO_CONTENTS` when a re-inventory happened. **Every directory page takes the `CONTENTS` type**: the script resolves each page's repo from the TYPE you pass, and a directory page passed under its old type resolves the wrong repo and prints no URL. Add `--worklog` and `--worklog-heading` when a work log entry exists. No work log yet: write this stage's log content to a file — with a Bash heredoc or `mktemp` per Hard limits, never with `Write` or `Edit` — and pass `--pending-file {file} --log-hash {HASH}` so it is held for the next `jsc-log:worklog` run. Rules and exit codes: `references/stage-report.md`. Exit 1 is a warning, never a block. Completion condition: the script's output is reported to the user verbatim, and every wiki page this run wrote appears in it.
|
11. **Stage report — the last thing this stage does, including every early stop** (the model gate blocked, the working tree did not match `origin/{source-branch}`, no plan was selectable, a wiki read or write failed). Run `tools/stage-report.sh analyze` with one `--page TYPE:{page}` per wiki page this run wrote — `--page ANALYZE:ANALYZE_{HASH}`, `--page CONTENTS:ANALYZE_CONTENTS`, `--page CONTENTS:PLAN_CONTENTS`, and `--page REPO:REPO_{HASH}` plus `--page CONTENTS:REPO_CONTENTS` when a re-inventory happened. **Every directory page takes the `CONTENTS` type**: the script resolves each page's repo from the TYPE you pass, and a directory page passed under its old type resolves the wrong repo and prints no URL. Add `--worklog` and `--worklog-heading` when a work log entry exists. No work log yet: write this stage's log content to a file — with a Bash heredoc or `mktemp` per Hard limits, never with `Write` or `Edit` — and pass `--pending-file {file} --log-hash {HASH}` so it is held for the next `jsc-log:worklog` run. Rules and exit codes: `references/stage-report.md`. Exit 1 is a warning, never a block. Completion condition: the script's output is reported to the user verbatim, and every wiki page this run wrote appears in it.
|
||||||
|
12. **Write this run's `skill-end` status event — the very last thing this stage does, right after step 11, on every path including every early stop.** Run `jsc-hooks/tools/report-status.sh skill-end jsc-sdlc:analyze {status} {exit} [detail]`, naming the script the way this stage already names `jsc-hooks/hooks/sdlc-gate.sh` in step 1. The matching `skill-start` event is written by jsc-hooks on its own, so this step owes only the `end`: a hook fires on the skill tool call and this stage's work happens in the model turns after it, so **no hook can see how this run ended**. A `start` with no `end` is what an aborted run looks like in the record, and this step is the only thing that keeps a finished run from looking like one.
|
||||||
|
|
||||||
|
`{status}` is one of five words, never a sixth:
|
||||||
|
|
||||||
|
| Status | When `analyze` reports it |
|
||||||
|
| --- | --- |
|
||||||
|
| `ok` | Every step's completion condition is met: the gate passed, the source branch was confirmed and `origin/{source-branch}` matched HEAD, every user story reached consensus, the WBS, the CPM figures and the TDD todos are on the page, `ANALYZE_{HASH}` is saved, every directory row this run owed was upserted, and `tools/stage-report.sh` exited 0 |
|
||||||
|
| `blocked` | A check that lives in code stopped the run before any analysis started: `sdlc-gate.sh lock analyze` exited non-zero because the model carries no `reasoning-max` tag, or step 4.3 found HEAD not pointing at the same commit as `origin/{source-branch}`. Nothing was analyzed, so this is **never `failed`** — both are the guard working, and recording either as a failure sends the next reader hunting for a defect that is not there |
|
||||||
|
| `failed` | The run got past those checks and then a write did not land: the `ANALYZE_{HASH}` or `REPO_{HASH}` write failed, `wiki-url` returned 5, 7 or 8, `link-check.sh` returned 1 so nothing was written, or a `wiki-contents.sh` run returned 1, 7 or 8 |
|
||||||
|
| `degraded` | The analysis page is saved but not every directory followed it: `ANALYZE_CONTENTS` was upserted while `PLAN_CONTENTS` still shows 「未分析」, a re-inventory wrote `REPO_{HASH}` but not its `REPO_CONTENTS` row, `wiki-contents.sh` returned 3, or `tools/stage-report.sh` exited 1. The analysis exists; what is missing is a directory row that lets anyone find it |
|
||||||
|
| `aborted` | The user stopped the run, or the run stopped itself because its premise did not hold — step 2 found both directory pages empty, so there was nothing to analyze |
|
||||||
|
|
||||||
|
`{exit}` is the exit code of the script whose verdict decided the status — the gate's code for `blocked`, the failing script's code for `failed` and `degraded` — and `0` when nothing exited non-zero, `ok` and `aborted` included. `[detail]` is optional and Traditional Chinese per the STE100 rule: one line, no line break, naming what decided the status (for example 「工作目錄與來源分支不一致」 or 「計畫目錄頁狀態未改」). The script truncates it at 200 characters, so put the short reason there and nothing else.
|
||||||
|
|
||||||
|
**A failure in this step never changes this stage's verdict.** The script is not found (jsc-hooks is not installed on this machine, or this CLI's layout puts it somewhere else) → skip the event quietly and carry on; nothing is reported to the user and no step is re-run. The three recording sub-commands are built to exit 0 even when the write fails, so a non-zero code here means only that the call itself was malformed (exit 2, a usage error) — fix the arguments once and, either way, never turn a finished stage into a failed one because the record of it failed. Completion condition: one `skill-end` event has been written for this run, or the script could not be found and that skip is the reason no event exists.
|
||||||
|
|
||||||
## Contents pages are appended, never overwritten
|
## Contents pages are appended, never overwritten
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ Goal: complete the analysis page's todos one by one; **update the wiki status im
|
|||||||
|
|
||||||
**Content pages and directory pages live in different wiki repos.** `ANALYZE_{HASH}` sits in the repo `jsc-gitea/tools/gitea.sh wiki-repo ANALYZE` resolves and `DELIVER_{HASH}` in the one `gitea.sh wiki-repo DELIVER` resolves, while the directory pages `ANALYZE_CONTENTS`, `DELIVER_CONTENTS` and `MAINTAIN_CONTENTS` all sit in the repo `gitea.sh wiki-repo CONTENTS` resolves: `JSC_WIKI_REPO_CONTENTS` first, `JSC_WIKI_REPO` second, exit 3 when neither is set; it **never** falls back to the page type's own variable. Every directory row links its content page by the absolute URL from `gitea.sh wiki-url {content repo} {page}`, written as `[{text}]({url})` — one link syntax, whichever wiki the two pages sit in. The syntax and the check that runs before every write: "Every link is checked before it reaches a page" below.
|
**Content pages and directory pages live in different wiki repos.** `ANALYZE_{HASH}` sits in the repo `jsc-gitea/tools/gitea.sh wiki-repo ANALYZE` resolves and `DELIVER_{HASH}` in the one `gitea.sh wiki-repo DELIVER` resolves, while the directory pages `ANALYZE_CONTENTS`, `DELIVER_CONTENTS` and `MAINTAIN_CONTENTS` all sit in the repo `gitea.sh wiki-repo CONTENTS` resolves: `JSC_WIKI_REPO_CONTENTS` first, `JSC_WIKI_REPO` second, exit 3 when neither is set; it **never** falls back to the page type's own variable. Every directory row links its content page by the absolute URL from `gitea.sh wiki-url {content repo} {page}`, written as `[{text}]({url})` — one link syntax, whichever wiki the two pages sit in. The syntax and the check that runs before every write: "Every link is checked before it reaches a page" below.
|
||||||
|
|
||||||
All wiki reads and writes go through `jsc-gitea:wiki`. **A failed wiki read or write stops this stage**: report which page and which operation failed, never carry on against a page you could not read, and never report a page as saved when the write failed. Step 13 still runs after such a stop.
|
All wiki reads and writes go through `jsc-gitea:wiki`. **A failed wiki read or write stops this stage**: report which page and which operation failed, never carry on against a page you could not read, and never report a page as saved when the write failed. Steps 13 and 14 still run after such a stop.
|
||||||
|
|
||||||
## Steps
|
## Steps
|
||||||
|
|
||||||
@@ -97,6 +97,21 @@ All wiki reads and writes go through `jsc-gitea:wiki`. **A failed wiki read or w
|
|||||||
- `--worktree {path} --source-branch {name} --work-branch {name} --pr {url}` — the script reads the commit count, the push state and whether the source branch exists on the remote by itself, so pass the names, not your own count.
|
- `--worktree {path} --source-branch {name} --work-branch {name} --pr {url}` — the script reads the commit count, the push state and whether the source branch exists on the remote by itself, so pass the names, not your own count.
|
||||||
|
|
||||||
Rules and exit codes: `references/stage-report.md`. Exit 1 is a warning, never a block. Completion condition: the script's output is reported to the user verbatim, and it names the worktree, all three branches and every wiki page this run wrote.
|
Rules and exit codes: `references/stage-report.md`. Exit 1 is a warning, never a block. Completion condition: the script's output is reported to the user verbatim, and it names the worktree, all three branches and every wiki page this run wrote.
|
||||||
|
14. **Write this run's `skill-end` status event — the very last thing this stage does, right after step 13, on every path including every early stop.** Run `jsc-hooks/tools/report-status.sh skill-end jsc-sdlc:implement {status} {exit} [detail]`, naming the script the way this stage already names `jsc-hooks/hooks/sdlc-gate.sh` in step 1. The matching `skill-start` event is written by jsc-hooks on its own, so this step owes only the `end`: a hook fires on the skill tool call and this stage's work happens in the model turns after it, so **no hook can see how this run ended**. A `start` with no `end` is what an aborted run looks like in the record, and this stage is the one that most often runs for hours before it stops, so the missing `end` is exactly the case worth telling apart.
|
||||||
|
|
||||||
|
`{status}` is one of five words, never a sixth:
|
||||||
|
|
||||||
|
| Status | When `implement` reports it |
|
||||||
|
| --- | --- |
|
||||||
|
| `ok` | Every step's completion condition is met: the gate passed, the claimed package's todos all show `[x]`, both closing audits cleared (a reported API-document skip counts as cleared), `pr-watch.sh` returned 0 with `wp-gate.sh check` reporting `status=merged`, the work log entries are saved, the delivery was produced, the maintenance question was answered, and `tools/stage-report.sh` exited 0 |
|
||||||
|
| `blocked` | A gate stopped this run before any package was worked on: `sdlc-gate.sh lock implement` exited non-zero because the model carries no `coding` tag, every candidate came back `status=blocked` from `wp-gate.sh check-deps` because a dependency's PR is not merged, `wp-gate.sh owns` answered `status=foreign` on the only PR left to settle, or the analysis page's source branch is missing from the remote (step 5.3). No code was written. Comment rounds that step 2 did finish are named in `[detail]`, because they are real work sitting behind a blocked verdict — but they do not turn it into `ok` |
|
||||||
|
| `failed` | Work started and then something did not complete: a `wp-gate.sh` call returned 3 (`status=missing-dep`, a gate that could not decide), `pr-watch.sh` returned 2 or 3, `wp-gate.sh check` reported `status=closed-unmerged`, an audit could not be brought to a passing verdict, or a wiki write did not land (`wiki-url` 5, 7 or 8; `link-check.sh` 1; `wiki-contents.sh` 1, 7 or 8) |
|
||||||
|
| `degraded` | The package itself finished — todos `[x]`, PR merged — but a closing item did not: `DELIVER_{HASH}` is saved while `DELIVER_CONTENTS` was not upserted, the maintenance registration went unrecorded on `wiki-contents.sh` exit 3, or `tools/stage-report.sh` exited 1 (no work log, or a link in its list does not answer) |
|
||||||
|
| `aborted` | The user stopped the run, or the run stopped itself because its premise did not hold — step 3 found no selectable work package, so there was nothing to implement |
|
||||||
|
|
||||||
|
`{exit}` is the exit code of the script whose verdict decided the status — the gate's code for `blocked`, the failing script's code for `failed` and `degraded` — and `0` when nothing exited non-zero, `ok` and `aborted` included. `[detail]` is optional and Traditional Chinese per the STE100 rule: one line, no line break, naming what decided the status (for example 「相依工作包的 PR 未合併」 or 「交付目錄列未寫入」). The script truncates it at 200 characters, so put the short reason there and nothing else.
|
||||||
|
|
||||||
|
**A failure in this step never changes this stage's verdict.** The script is not found (jsc-hooks is not installed on this machine, or this CLI's layout puts it somewhere else) → skip the event quietly and carry on; nothing is reported to the user and no step is re-run. The three recording sub-commands are built to exit 0 even when the write fails, so a non-zero code here means only that the call itself was malformed (exit 2, a usage error) — fix the arguments once and, either way, never turn a merged work package into a failed stage because the record of it failed. Completion condition: one `skill-end` event has been written for this run, or the script could not be found and that skip is the reason no event exists.
|
||||||
|
|
||||||
## Every link is checked before it reaches a page
|
## Every link is checked before it reaches a page
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ Goal: run routine maintenance for every project in the maintenance contents page
|
|||||||
|
|
||||||
Never let an empty string stand in for the URL: a cell that is empty names a page nobody can open, and the next run rewrites that row as if it were correct.
|
Never let an empty string stand in for the URL: a cell that is empty names a page nobody can open, and the next run rewrites that row as if it were correct.
|
||||||
|
|
||||||
All wiki reads and writes go through `jsc-gitea:wiki`. **A failed wiki read or write stops this stage**: report which page and which operation failed, never carry on against a page you could not read, and never report a page as saved when the write failed. Step 5 still runs after such a stop.
|
All wiki reads and writes go through `jsc-gitea:wiki`. **A failed wiki read or write stops this stage**: report which page and which operation failed, never carry on against a page you could not read, and never report a page as saved when the write failed. Steps 5 and 6 still run after such a stop.
|
||||||
|
|
||||||
## Steps
|
## Steps
|
||||||
|
|
||||||
@@ -42,6 +42,21 @@ All wiki reads and writes go through `jsc-gitea:wiki`. **A failed wiki read or w
|
|||||||
6. Update the project's last-maintained field (the zh-TW column 「前次維護時間」) in `MAINTAIN_CONTENTS` to today with `jsc-gitea/tools/wiki-contents.sh upsert MAINTAIN 1 {owner}/{repo} {row file} templates/maintain-contents.md`, never by hand-editing the page. Rebuild that project's row from the one the page already holds, change only the 「前次維護時間」 cell, and keep every other cell byte-for-byte as it was; the key is column 1, the repository name, written exactly as the row file writes it. **A row that carries a link goes through `jsc-gitea/tools/link-check.sh` before the upsert, and is upserted only on exit 0** — see "Every link is checked before it reaches a page" below. Branch on the upsert's exit code per "Contents pages are appended, never overwritten" below. Completion condition: the script exited 0, every link in the rebuilt row was cleared by a `link-check.sh` run that exited 0, `MAINTAIN_CONTENTS` shows today's date in 「前次維護時間」 for that project, and every other project's row is byte-for-byte unchanged.
|
6. Update the project's last-maintained field (the zh-TW column 「前次維護時間」) in `MAINTAIN_CONTENTS` to today with `jsc-gitea/tools/wiki-contents.sh upsert MAINTAIN 1 {owner}/{repo} {row file} templates/maintain-contents.md`, never by hand-editing the page. Rebuild that project's row from the one the page already holds, change only the 「前次維護時間」 cell, and keep every other cell byte-for-byte as it was; the key is column 1, the repository name, written exactly as the row file writes it. **A row that carries a link goes through `jsc-gitea/tools/link-check.sh` before the upsert, and is upserted only on exit 0** — see "Every link is checked before it reaches a page" below. Branch on the upsert's exit code per "Contents pages are appended, never overwritten" below. Completion condition: the script exited 0, every link in the rebuilt row was cleared by a `link-check.sh` run that exited 0, `MAINTAIN_CONTENTS` shows today's date in 「前次維護時間」 for that project, and every other project's row is byte-for-byte unchanged.
|
||||||
4. The main agent reports the summary: maintenance methods applied per project, PR table rows, and failure reasons. The report and all generated wiki content, commits, and PR descriptions stay Traditional Chinese per the STE100 rule. Completion condition: the summary names every project read in step 2, each with its applied methods and either a PR table row or the reason it was skipped.
|
4. The main agent reports the summary: maintenance methods applied per project, PR table rows, and failure reasons. The report and all generated wiki content, commits, and PR descriptions stay Traditional Chinese per the STE100 rule. Completion condition: the summary names every project read in step 2, each with its applied methods and either a PR table row or the reason it was skipped.
|
||||||
5. **Stage report — the last thing this stage does, including when no project was in window, and when a wiki read or write failed.** Run `tools/stage-report.sh maintain` with one `--page TYPE:{page}` per wiki page this run wrote — that is `--page CONTENTS:MAINTAIN_CONTENTS`, under the `CONTENTS` type, because the script resolves each page's repo from the TYPE you pass and `MAINTAIN:` would resolve the wrong repo and print no URL — plus `--worklog` and `--worklog-heading` pointing at the entries step 3.5 wrote. `--pending-file {file} --log-hash {HASH}` is the fallback for a stage that stopped before any project finished: it holds the content for the next `jsc-log:worklog` run, and held content is not a written log. Rules and exit codes: `references/stage-report.md`. Exit 1 is a warning, never a block. Completion condition: the script's output is reported to the user verbatim, and every wiki page this run wrote appears in it.
|
5. **Stage report — the last thing this stage does, including when no project was in window, and when a wiki read or write failed.** Run `tools/stage-report.sh maintain` with one `--page TYPE:{page}` per wiki page this run wrote — that is `--page CONTENTS:MAINTAIN_CONTENTS`, under the `CONTENTS` type, because the script resolves each page's repo from the TYPE you pass and `MAINTAIN:` would resolve the wrong repo and print no URL — plus `--worklog` and `--worklog-heading` pointing at the entries step 3.5 wrote. `--pending-file {file} --log-hash {HASH}` is the fallback for a stage that stopped before any project finished: it holds the content for the next `jsc-log:worklog` run, and held content is not a written log. Rules and exit codes: `references/stage-report.md`. Exit 1 is a warning, never a block. Completion condition: the script's output is reported to the user verbatim, and every wiki page this run wrote appears in it.
|
||||||
|
6. **Write this run's `skill-end` status event — the very last thing this stage does, right after step 5, on every path including when no project was in window.** Run `jsc-hooks/tools/report-status.sh skill-end jsc-sdlc:maintain {status} {exit} [detail]`, naming the script the way this stage already names `jsc-hooks/hooks/sdlc-gate.sh` in step 1. The matching `skill-start` event is written by jsc-hooks on its own, so this step owes only the `end`: a hook fires on the skill tool call and this stage's work happens in the model turns after it, so **no hook can see how this run ended**. A `start` with no `end` is what an aborted run looks like in the record, and a stage that often ends with nothing to do needs that difference recorded, not guessed.
|
||||||
|
|
||||||
|
`{status}` is one of five words, never a sixth:
|
||||||
|
|
||||||
|
| Status | When `maintain` reports it |
|
||||||
|
| --- | --- |
|
||||||
|
| `ok` | Every step's completion condition is met: the gate passed, every in-window project ran its sub agent and ended in a PR, each finished project has its work log entry, `MAINTAIN_CONTENTS` shows today in 「前次維護時間」 for every one of them, and `tools/stage-report.sh` exited 0 |
|
||||||
|
| `blocked` | A check that lives in code stopped the run before any maintenance: `sdlc-gate.sh lock maintain` exited non-zero because the script could not determine the actual model id from the transcript, which is the one thing this stage's gate asks for; or step 3.1 found every in-window project out of step with `origin/{branch}`, so all of them were skipped and not one maintenance action ran. Nothing was maintained, so this is **never `failed`** — both are the guard working |
|
||||||
|
| `failed` | Maintenance ran and then a write did not land: `wiki-contents.sh` returned 1, 7 or 8 over `MAINTAIN_CONTENTS`, `wiki-url` returned 5, 7 or 8, or `link-check.sh` returned 1 so the row was never written. `MAINTAIN` has no content page, so a row that never lands loses the whole wiki record of this run — that is why it is `failed` and not `degraded` |
|
||||||
|
| `degraded` | Some projects came through and some did not: one project was skipped for a branch gap or a method that could not be applied while the others got their PR, or every project got its PR while `wiki-contents.sh` returned 3 so no 「前次維護時間」 was updated, or `tools/stage-report.sh` exited 1 (no work log, or a link in its list does not answer) |
|
||||||
|
| `aborted` | The user stopped the run, or the run stopped itself because its premise did not hold — step 2 found no project inside its maintenance window, so there was nothing to maintain |
|
||||||
|
|
||||||
|
`{exit}` is the exit code of the script whose verdict decided the status — the gate's code for `blocked`, the failing script's code for `failed` and `degraded` — and `0` when nothing exited non-zero, `ok` and `aborted` included. `[detail]` is optional and Traditional Chinese per the STE100 rule: one line, no line break, naming what decided the status (for example 「無專案在維護期內」 or 「兩個專案與遠端有落差已略過」). The script truncates it at 200 characters, so put the short reason there and nothing else.
|
||||||
|
|
||||||
|
**A failure in this step never changes this stage's verdict.** The script is not found (jsc-hooks is not installed on this machine, or this CLI's layout puts it somewhere else) → skip the event quietly and carry on; nothing is reported to the user and no step is re-run. The three recording sub-commands are built to exit 0 even when the write fails, so a non-zero code here means only that the call itself was malformed (exit 2, a usage error) — fix the arguments once and, either way, never turn a stage that opened its PRs into a failed one because the record of it failed. Completion condition: one `skill-end` event has been written for this run, or the script could not be found and that skip is the reason no event exists.
|
||||||
|
|
||||||
## Every link is checked before it reaches a page
|
## Every link is checked before it reaches a page
|
||||||
|
|
||||||
|
|||||||
+16
-1
@@ -12,7 +12,7 @@ This skill is a **logic-only** stage: never output code, and **never modify any
|
|||||||
|
|
||||||
**The two pages this stage touches live in two different wiki repos.** The content page `PLAN_{HASH}` sits in the repo `jsc-gitea/tools/gitea.sh wiki-repo PLAN` resolves. The directory page `PLAN_CONTENTS` sits in the repo `gitea.sh wiki-repo CONTENTS` resolves — `JSC_WIKI_REPO_CONTENTS` first, `JSC_WIKI_REPO` second, exit 3 when neither is set; it **never** falls back to `JSC_WIKI_REPO_PLAN`. The directory row links the plan page by the absolute URL from `gitea.sh wiki-url {PLAN repo} PLAN_{HASH}`, written as `[{text}]({url})` — one link syntax, whichever wiki the two pages sit in. The syntax and the check that runs before every write: "Every link is checked before it reaches a page" below.
|
**The two pages this stage touches live in two different wiki repos.** The content page `PLAN_{HASH}` sits in the repo `jsc-gitea/tools/gitea.sh wiki-repo PLAN` resolves. The directory page `PLAN_CONTENTS` sits in the repo `gitea.sh wiki-repo CONTENTS` resolves — `JSC_WIKI_REPO_CONTENTS` first, `JSC_WIKI_REPO` second, exit 3 when neither is set; it **never** falls back to `JSC_WIKI_REPO_PLAN`. The directory row links the plan page by the absolute URL from `gitea.sh wiki-url {PLAN repo} PLAN_{HASH}`, written as `[{text}]({url})` — one link syntax, whichever wiki the two pages sit in. The syntax and the check that runs before every write: "Every link is checked before it reaches a page" below.
|
||||||
|
|
||||||
All wiki reads and writes go through `jsc-gitea:wiki`. **A failed wiki read or write stops this stage**: report which page and which operation failed, never carry on against a page you could not read, and never report a page as saved when the write failed. Step 8 still runs after such a stop.
|
All wiki reads and writes go through `jsc-gitea:wiki`. **A failed wiki read or write stops this stage**: report which page and which operation failed, never carry on against a page you could not read, and never report a page as saved when the write failed. Steps 8 and 9 still run after such a stop.
|
||||||
|
|
||||||
## Steps
|
## Steps
|
||||||
|
|
||||||
@@ -41,6 +41,21 @@ All wiki reads and writes go through `jsc-gitea:wiki`. **A failed wiki read or w
|
|||||||
|
|
||||||
Never let an empty string stand in for the URL: a row whose link cell is empty is a directory entry that points nowhere, and the next run overwrites it as if it were correct. **Then check that URL with `jsc-gitea/tools/link-check.sh` and build the row only on exit 0** — see "Every link is checked before it reaches a page" below; a link that does not answer never goes into a directory everyone else reads. Then build one file holding the single row from `templates/plan-contents.md` — the plan name, that absolute link written as `[{文字}]({連結})`, the code repository, the HASH, the literal 「未分析」 and the creation date; produce that file per Hard limits, with a Bash heredoc or `mktemp`, never with `Write` or `Edit`. Then run `jsc-gitea/tools/wiki-contents.sh upsert PLAN 4 {HASH} {row file} templates/plan-contents.md`. The key is the HASH column, column 4, written exactly as the row file writes it; a key typed by hand appends a second row for the same plan. Branch on the exit code per "Contents pages are appended, never overwritten" below. Completion condition: `wiki-url` returned 0 and its URL is the one in the row, `link-check.sh` returned 0 over that URL, the upsert exited 0, `PLAN_CONTENTS` shows this plan's row with the literal 「未分析」 and that absolute plan-page link, and you have reported all three exit codes plus whether the script printed `updated` or `added`.
|
Never let an empty string stand in for the URL: a row whose link cell is empty is a directory entry that points nowhere, and the next run overwrites it as if it were correct. **Then check that URL with `jsc-gitea/tools/link-check.sh` and build the row only on exit 0** — see "Every link is checked before it reaches a page" below; a link that does not answer never goes into a directory everyone else reads. Then build one file holding the single row from `templates/plan-contents.md` — the plan name, that absolute link written as `[{文字}]({連結})`, the code repository, the HASH, the literal 「未分析」 and the creation date; produce that file per Hard limits, with a Bash heredoc or `mktemp`, never with `Write` or `Edit`. Then run `jsc-gitea/tools/wiki-contents.sh upsert PLAN 4 {HASH} {row file} templates/plan-contents.md`. The key is the HASH column, column 4, written exactly as the row file writes it; a key typed by hand appends a second row for the same plan. Branch on the exit code per "Contents pages are appended, never overwritten" below. Completion condition: `wiki-url` returned 0 and its URL is the one in the row, `link-check.sh` returned 0 over that URL, the upsert exited 0, `PLAN_CONTENTS` shows this plan's row with the literal 「未分析」 and that absolute plan-page link, and you have reported all three exit codes plus whether the script printed `updated` or `added`.
|
||||||
8. **Stage report — the last thing this stage does, including every early stop** (the model gate blocked, no plan was selectable, a wiki read or write failed). Run `tools/stage-report.sh plan` with one `--page TYPE:{page}` per wiki page this run wrote — `--page PLAN:PLAN_{HASH}` for the content page and `--page CONTENTS:PLAN_CONTENTS` for the directory page, because the script resolves each page's repo from the TYPE you pass and the two pages no longer share one — plus `--worklog` and `--worklog-heading` when a work log entry exists. No work log yet: write this stage's log content to a file — with a Bash heredoc or `mktemp` per Hard limits, never with `Write` or `Edit` — and pass `--pending-file {file} --log-hash {HASH}` so it is held for the next `jsc-log:worklog` run. Rules and exit codes: `references/stage-report.md`. Exit 1 is a warning, never a block. Completion condition: the script's output is reported to the user verbatim, and every wiki page this run wrote appears in it.
|
8. **Stage report — the last thing this stage does, including every early stop** (the model gate blocked, no plan was selectable, a wiki read or write failed). Run `tools/stage-report.sh plan` with one `--page TYPE:{page}` per wiki page this run wrote — `--page PLAN:PLAN_{HASH}` for the content page and `--page CONTENTS:PLAN_CONTENTS` for the directory page, because the script resolves each page's repo from the TYPE you pass and the two pages no longer share one — plus `--worklog` and `--worklog-heading` when a work log entry exists. No work log yet: write this stage's log content to a file — with a Bash heredoc or `mktemp` per Hard limits, never with `Write` or `Edit` — and pass `--pending-file {file} --log-hash {HASH}` so it is held for the next `jsc-log:worklog` run. Rules and exit codes: `references/stage-report.md`. Exit 1 is a warning, never a block. Completion condition: the script's output is reported to the user verbatim, and every wiki page this run wrote appears in it.
|
||||||
|
9. **Write this run's `skill-end` status event — the very last thing this stage does, right after step 8, on every path including every early stop.** Run `jsc-hooks/tools/report-status.sh skill-end jsc-sdlc:plan {status} {exit} [detail]`, naming the script the way this stage already names `jsc-hooks/hooks/sdlc-gate.sh` in step 1. The matching `skill-start` event is written by jsc-hooks on its own, so this step owes only the `end`: a hook fires on the skill tool call and this stage's work happens in the model turns after it, so **no hook can see how this run ended**. A `start` with no `end` is what an aborted run looks like in the record, and this step is the only thing that keeps a finished run from looking like one.
|
||||||
|
|
||||||
|
`{status}` is one of five words, never a sixth:
|
||||||
|
|
||||||
|
| Status | When `plan` reports it |
|
||||||
|
| --- | --- |
|
||||||
|
| `ok` | Every step's completion condition is met: the gate passed, all three consensus items were confirmed by the user, `PLAN_{HASH}` is saved with no placeholder left, the `PLAN_CONTENTS` row carries the literal 「未分析」 and a checked absolute link, and `tools/stage-report.sh` exited 0 |
|
||||||
|
| `blocked` | Step 1's model gate stopped the run: `sdlc-gate.sh lock plan` exited non-zero because the model running this stage carries no `reasoning-max` tag. Nothing was planned, so this is **never `failed`** — the gate stopping an underpowered model is the gate working, and recording it as a failure sends the next reader hunting for a defect that is not there |
|
||||||
|
| `failed` | The run got past the gate and then a write did not land: the `PLAN_{HASH}` write failed, `wiki-url` returned 5, 7 or 8, `link-check.sh` returned 1 so the page was never written, or `wiki-contents.sh` returned 1, 7 or 8 while the plan page is also unsaved |
|
||||||
|
| `degraded` | The plan page is saved but the directory did not follow it: `wiki-contents.sh` returned 1, 3, 7 or 8 over `PLAN_CONTENTS`, or `tools/stage-report.sh` exited 1 (no work log, or a link in its list does not answer). The plan exists; what is missing is the directory row that lets anyone find it |
|
||||||
|
| `aborted` | The user stopped the run, or the run stopped itself because its premise did not hold — no plan was selectable and the user wanted no new one, or the consensus rounds ended with no agreement, so no user story was written |
|
||||||
|
|
||||||
|
`{exit}` is the exit code of the script whose verdict decided the status — the gate's code for `blocked`, the failing script's code for `failed` and `degraded` — and `0` when nothing exited non-zero, `ok` and `aborted` included. `[detail]` is optional and Traditional Chinese per the STE100 rule: one line, no line break, naming what decided the status (for example 「模型能力標籤不符」 or 「目錄頁未更新」). The script truncates it at 200 characters, so put the short reason there and nothing else.
|
||||||
|
|
||||||
|
**A failure in this step never changes this stage's verdict.** The script is not found (jsc-hooks is not installed on this machine, or this CLI's layout puts it somewhere else) → skip the event quietly and carry on; nothing is reported to the user and no step is re-run. The three recording sub-commands are built to exit 0 even when the write fails, so a non-zero code here means only that the call itself was malformed (exit 2, a usage error) — fix the arguments once and, either way, never turn a finished stage into a failed one because the record of it failed. Completion condition: one `skill-end` event has been written for this run, or the script could not be found and that skip is the reason no event exists.
|
||||||
|
|
||||||
## Every link is checked before it reaches a page
|
## Every link is checked before it reaches a page
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user