From ea4c97b39f3bec3935ce7da4752dd3e3964b5e9f Mon Sep 17 00:00:00 2001 From: Jeffery Date: Fri, 28 Aug 2026 16:45:30 +0800 Subject: [PATCH] =?UTF-8?q?docs(model-gate):=20=E8=AA=AA=E6=98=8E=20Codex?= =?UTF-8?q?=20=E6=A8=A1=E5=9E=8B=E4=BE=86=E6=BA=90=E8=88=87=E4=BA=BA?= =?UTF-8?q?=E5=B7=A5=E8=A6=86=E5=AF=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude-plugin/plugin.json | 2 +- .codex-plugin/plugin.json | 2 +- plugin.json | 2 +- references/model-gate.md | 21 +++++++++++++++++++-- references/stage-report.md | 2 +- skills/analyze/SKILL.md | 2 +- skills/implement/SKILL.md | 2 +- skills/maintain/SKILL.md | 2 +- skills/plan/SKILL.md | 2 +- tools/stage-report.sh | 4 +++- 10 files changed, 30 insertions(+), 11 deletions(-) diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 71f8d0e..f818e87 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "jsc-sdlc", - "version": "0.2.5", + "version": "0.2.6", "description": "開發生命週期:規劃、分析、實作、維護(wiki 追蹤)", "skills": "./skills", "author": { diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index 203a63d..e88c17a 100644 --- a/.codex-plugin/plugin.json +++ b/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "jsc-sdlc", - "version": "0.2.5", + "version": "0.2.6", "description": "開發生命週期:規劃、分析、實作、維護(wiki 追蹤)", "skills": "./skills", "jsc": { diff --git a/plugin.json b/plugin.json index 0e14c14..6cbb63a 100644 --- a/plugin.json +++ b/plugin.json @@ -1,6 +1,6 @@ { "name": "jsc-sdlc", - "version": "0.2.5", + "version": "0.2.6", "description": "開發生命週期:規劃、分析、實作、維護(wiki 追蹤)", "skills": "./skills/", "jsc": { diff --git a/references/model-gate.md b/references/model-gate.md index dc252c7..27523e1 100644 --- a/references/model-gate.md +++ b/references/model-gate.md @@ -5,7 +5,7 @@ SDLC 每個階段動工前先過模型閘門。判定全在程式層,由 `jsc- ## 執行順序 1. `jsc-cli/tools/model-tags.sh sync`:把 `jsc-cli/references/model-tags.md` 的標籤表同步到 `$JSC_HOME/model-tags.tsv`。 -2. `jsc-hooks/hooks/sdlc-gate.sh lock {stage}`:腳本從 transcript 讀出**實際**模型 id,比對該階段的必要標籤,相符才上鎖。 +2. `jsc-hooks/hooks/sdlc-gate.sh lock {stage}`:腳本從可驗證來源讀出模型 id,比對該階段的必要標籤,相符才上鎖。 ## 各階段必要標籤 @@ -21,8 +21,25 @@ SDLC 每個階段動工前先過模型閘門。判定全在程式層,由 `jsc- | 項目 | 規則 | | --- | --- | | 標籤來源 | 只認腳本的判定。不得宣稱自己沒驗證過的標籤,也不得用自己的判斷取代腳本結論 | +| 模型來源 | 優先序為 transcript、hook stdin JSON、Codex 本機 session 記錄、`JSC_MODEL` 人工覆寫 | | 非零退出 | 一律視為阻擋:原文轉述腳本訊息、停止該技能、該回合不做別的事 | | `unlock` | 不得用來繞過閘門。要不要解鎖是使用者的決定 | -| 回報 | **每次都要回報**:階段、必要標籤、腳本從 transcript 讀到的實際模型 id、判定結果。通過與阻擋都要講——安靜通過看起來跟跳過檢查一樣,而判定搬進程式層的理由就是「宣稱有檢查」不可信 | +| 回報 | **每次都要回報**:階段、必要標籤、模型 id、模型來源、判定結果。通過與阻擋都要講——安靜通過看起來跟跳過檢查一樣,而判定搬進程式層的理由就是「宣稱有檢查」不可信 | | 退出 0 | 該階段已上鎖。到下一階段的閘門重新上鎖之前,同一階段內把模型換成不合格的,下一輪提示會被 sdlc-gate hook 以 exit 2 擋下 | | 上鎖時機 | 只在階段變換時上鎖。同一階段內逐項或逐專案跑時不重新上鎖 | + +## Codex 判定來源 + +Codex 不一定提供 Claude 式 transcript 路徑。閘門會依序檢查下列來源。 + +| 順位 | 來源 | 語意 | +| --- | --- | --- | +| 1 | hook stdin JSON 的 `transcript_path`,或 `JSC_TRANSCRIPT_PATH` | CLI 產生的 transcript。這是首選實查來源 | +| 2 | hook stdin JSON 的 `model`、`model_id`、`model_slug`、`modelName`、`current_model`、`currentModel` | hook 宿主提供的結構化欄位。只讀 JSON 欄位,不讀對話文字 | +| 3 | `$CODEX_HOME/sessions/**/*.jsonl`,預設 `~/.codex/sessions/**/*.jsonl` | Codex 本機 session 記錄。先用 session id 對檔名,沒有 session id 時取最新 session 檔 | +| 4 | `$CODEX_HOME/history.jsonl`、`$CODEX_HOME/session_index.jsonl` | Codex 輔助索引。只取結構化模型欄位;沒有欄位就略過 | +| 5 | `JSC_MODEL` | 明確人工覆寫。輸出來源固定標成 `人工覆寫:JSC_MODEL` | + +`JSC_MODEL` 是最後退路,不是預設來源。使用它時,回報必須標明「人工覆寫」,避免把人工宣告誤認為 transcript 實查。 + +對話內容不屬於可驗證來源。即使使用者或模型在訊息裡寫出模型 id,閘門也不得採用那段文字。 diff --git a/references/stage-report.md b/references/stage-report.md index 11e3433..b5f75b3 100644 --- a/references/stage-report.md +++ b/references/stage-report.md @@ -12,7 +12,7 @@ | 項目 | 來源 | 沒有時怎麼辦 | | --- | --- | --- | -| 模型能力標籤 | `jsc-hooks/hooks/sdlc-gate.sh report`,腳本自己讀 | 回報「查不到閘門狀態」,並要求重跑 `lock {stage}` | +| 模型能力標籤 | `jsc-hooks/hooks/sdlc-gate.sh report`,腳本自己讀 | 回報「查不到閘門狀態」,並要求重跑 `lock {stage}`。有狀態時轉述階段、必要標籤、模型 id、模型來源與判定結果 | | 工作日誌連結 | `--worklog` 給頁名、`--worklog-heading` 給條目標題,組成導向該條目的錨點連結 | 警告使用者檢查,並把內容暫存(見下節) | | 所有寫入的 wiki 連結 | 每寫一頁就記一筆,收尾時用 `--page TYPE:PAGE` 全部餵進去 | 沒寫任何頁就據實回報「本階段沒有寫入任何 wiki 頁」 | diff --git a/skills/analyze/SKILL.md b/skills/analyze/SKILL.md index 2f69553..f962e90 100644 --- a/skills/analyze/SKILL.md +++ b/skills/analyze/SKILL.md @@ -13,7 +13,7 @@ All wiki reads and writes go through `jsc-gitea:wiki`. ## Steps -1. **Model gate and stage lock** — run `jsc-cli/tools/model-tags.sh sync`, then `jsc-hooks/hooks/sdlc-gate.sh lock analyze`. This stage requires the `reasoning-max` capability tag. Rules: `references/model-gate.md`. Completion condition: the script exited 0, and you have reported the stage, the required tag, the actual model id it read from the transcript, and the verdict. +1. **Model gate and stage lock** — run `jsc-cli/tools/model-tags.sh sync`, then `jsc-hooks/hooks/sdlc-gate.sh lock analyze`. This stage requires the `reasoning-max` capability tag. Rules: `references/model-gate.md`. Completion condition: the script exited 0, and you have reported the stage, the required tag, the model id, model source, and the verdict. 2. **Confirm the source branch** — the branch whose code counts as the current state: 1. Run `git fetch --prune origin` first — without it, every `origin/...` reference is stale cache. Then report the working directory's current branch, the **remote** branches available (`git branch -r`; never `git branch`) and whether the working tree is clean. 2. Ask per `jsc-ask:ask` rules which branch the analysis reads from; state the impact scope on every option (analysing the wrong branch produces work packages for code that does not exist). diff --git a/skills/implement/SKILL.md b/skills/implement/SKILL.md index c44926a..9412e76 100644 --- a/skills/implement/SKILL.md +++ b/skills/implement/SKILL.md @@ -10,7 +10,7 @@ All wiki reads and writes go through `jsc-gitea:wiki`. ## Steps -1. **Model gate and stage lock** — run `jsc-cli/tools/model-tags.sh sync`, then `jsc-hooks/hooks/sdlc-gate.sh lock implement`. This stage requires the `coding` capability tag. Rules: `references/model-gate.md`. Completion condition: the script exited 0, and you have reported the stage, the required tag, the actual model id it read from the transcript, and the verdict. +1. **Model gate and stage lock** — run `jsc-cli/tools/model-tags.sh sync`, then `jsc-hooks/hooks/sdlc-gate.sh lock implement`. This stage requires the `coding` capability tag. Rules: `references/model-gate.md`. Completion condition: the script exited 0, and you have reported the stage, the required tag, the model id, model source, and the verdict. 2. **Confirm the source branch — it is also this stage's PR target**: 1. Run `git fetch --prune origin`, then read the source branch from the analysis page and report it, along with the current branch and whether the working tree is clean. 2. Ask per `jsc-ask:ask` rules to confirm that `origin/{source-branch}` is both the worktree's base and the PR target for every work package in this analysis. State the impact scope: each finished work package merges back into the source branch, and that branch as a whole reaches `develop` later as its own separate PR. diff --git a/skills/maintain/SKILL.md b/skills/maintain/SKILL.md index 06d7085..cb168e1 100644 --- a/skills/maintain/SKILL.md +++ b/skills/maintain/SKILL.md @@ -10,7 +10,7 @@ All wiki reads and writes go through `jsc-gitea:wiki`. ## Steps -1. **Model gate and stage lock** — run `jsc-cli/tools/model-tags.sh sync`, then `jsc-hooks/hooks/sdlc-gate.sh lock maintain`. This stage requires no specific capability tag; the gate passes as long as the script can determine the actual model id. Rules: `references/model-gate.md`. Completion condition: the script exited 0, and you have reported the stage, the required tag, the actual model id it read from the transcript, and the verdict. +1. **Model gate and stage lock** — run `jsc-cli/tools/model-tags.sh sync`, then `jsc-hooks/hooks/sdlc-gate.sh lock maintain`. This stage requires no specific capability tag; the gate passes as long as the script can determine the actual model id. Rules: `references/model-gate.md`. Completion condition: the script exited 0, and you have reported the stage, the required tag, the model id, model source, and the verdict. 2. Read `MAINTAIN_CONTENTS` via `jsc-gitea:wiki` and filter projects **still inside their maintenance window**: start date ≤ today, and (end date is NULL or ≥ today). Completion condition: you have listed every in-window project with its `{owner}/{repo}` and window dates, or reported that none is in window and stopped. 3. Every project **MUST run as a sub agent** with this flow. Completion condition: every project listed in step 2 has its sub agent finished, and each one ends in either a PR link or a recorded skip reason. 1. Run `git fetch --prune origin`, then put the project on its maintenance branch and align it with `origin/{branch}`. Which branch that is, the remote-is-the-basis rule, the diverged case and the never-pull-never-reset rule all live in `references/branch.md`; never guess the branch name. Completion condition: the project's HEAD points at the same commit as `origin/{branch}`, or you have reported the gap and skipped this project. diff --git a/skills/plan/SKILL.md b/skills/plan/SKILL.md index c8e7d75..fcf7e25 100644 --- a/skills/plan/SKILL.md +++ b/skills/plan/SKILL.md @@ -13,7 +13,7 @@ All wiki reads and writes go through `jsc-gitea:wiki`. ## Steps -1. **Model gate and stage lock** — run `jsc-cli/tools/model-tags.sh sync`, then `jsc-hooks/hooks/sdlc-gate.sh lock plan`. This stage requires the `reasoning-max` capability tag. Rules: `references/model-gate.md`. Completion condition: the script exited 0, and you have reported the stage, the required tag, the actual model id it read from the transcript, and the verdict. +1. **Model gate and stage lock** — run `jsc-cli/tools/model-tags.sh sync`, then `jsc-hooks/hooks/sdlc-gate.sh lock plan`. This stage requires the `reasoning-max` capability tag. Rules: `references/model-gate.md`. Completion condition: the script exited 0, and you have reported the stage, the required tag, the model id, model source, and the verdict. 2. Read `PLAN_CONTENTS` via `jsc-gitea:wiki` and list the plans whose status is the literal 「未分析」 (not analyzed), with names and HASH. Completion condition: you have listed every 未分析 plan with its name and HASH, or reported that none exists. 3. Let the user choose per `jsc-ask:ask` rules: **extend an existing plan** (list the not-analyzed plans as options) or **create a new plan**. State the impact scope on every option. Completion condition: the user has picked one option explicitly, and you have named the `PLAN_{HASH}` page this run writes to. 4. **Keep questioning until consensus** — rules in `references/consensus.md`, which is the single authority for both planning and analysis. Cover all three items: diff --git a/tools/stage-report.sh b/tools/stage-report.sh index e2d599d..faef60d 100755 --- a/tools/stage-report.sh +++ b/tools/stage-report.sh @@ -155,12 +155,14 @@ gate_line=$("$GATE" report 2>/dev/null || true) gate_stage=$(printf '%s' "$gate_line" | awk '{print $2}') gate_tag=$(printf '%s' "$gate_line" | awk '{print $3}') gate_model=$(printf '%s' "$gate_line" | awk '{print $4}') +gate_source=$(printf '%s' "$gate_line" | awk '{print $5}') +gate_verdict=$(printf '%s' "$gate_line" | awk '{print $6}') if [ -z "$gate_line" ]; then gate_result="查不到閘門狀態(未上鎖或狀態檔不在),請重跑 sdlc-gate.sh lock $stage" elif [ "$gate_stage" != "$stage" ]; then gate_result="不符:本階段為 $stage,鎖上的卻是 $gate_stage,請重跑 sdlc-gate.sh lock $stage" else - gate_result="通過(必要標籤 $(required_tag "$stage"),實際模型 ${gate_model:-未知},鎖上時的標籤 ${gate_tag:-無})" + gate_result="通過(必要標籤 $(required_tag "$stage"),實際模型 ${gate_model:-未知},來源 ${gate_source:-未知},判定 ${gate_verdict:-未知},鎖上時的標籤 ${gate_tag:-無})" fi # ---- 工作日誌 ----