diff --git a/.github/memory-bank/project-facts.md b/.github/memory-bank/project-facts.md index 655b4c1..c52474a 100644 --- a/.github/memory-bank/project-facts.md +++ b/.github/memory-bank/project-facts.md @@ -49,12 +49,17 @@ Protected: 禁止本地特性分支進入此目錄 | 變數 | 用途 | 示例 | 必需 | |---|---|---|---| | GITHUB_TOKEN | 驗證 GitHub API | ghp_xxx... | 否(fallback 為唯讀) | -| PYTHONPATH | Import artifacts/scripts | C:\...\CLI | 用於 guard scripts | +| PYTHONPATH | Import artifacts/scripts | C:\\...\\CLI | 用於 guard scripts | ## 執行環境 Python 3.11 venv(`.venv/`):在執行 guard scripts 前必須啟動。 +## pytest 語境慣例 + +- 以 repo root 執行 `python -m pytest artifacts/scripts -q` 作為 wrapper / guard / regression 的標準測試入口。 +- `artifacts/scripts/conftest.py` 的 fake exe fixtures 以 raw stdin bytes 驗證 stdin pipe,不做字串容錯。 + ## 構建和部署 本地開發安裝: @@ -66,7 +71,7 @@ python -m pip install -r requirements-dev.txt git submodule update --init --recursive 本地測試: -python -m pytest artifacts/scripts/test_guard_units.py artifacts/scripts/test_security_scans.py -q +python -m pytest artifacts/scripts -q 執行 guard: python artifacts/scripts/guard_status_validator.py --task-id TASK-900 diff --git a/.github/memory-bank/raci-violations-log.md b/.github/memory-bank/raci-violations-log.md index 78637df..314666b 100644 --- a/.github/memory-bank/raci-violations-log.md +++ b/.github/memory-bank/raci-violations-log.md @@ -6,3 +6,7 @@ This is an append-only log maintained by the Gemini RACI Auditor. It tracks all - 2026-04-26T19:46:51+08:00 | Agent: Codex | File: docs/orchestration.md | Violation: code (實檔修改) vs code (實檔修改) - 2026-05-03T18:29:39+08:00 | Agent: Codex CLI | File: docs/orchestration.md | Category: workflow_contract_docs + +## Reconciliation Notes + +- 2026-07-03 | CHG-005 (HC-7 方向 a): 上列 2 條 Codex/`docs/orchestration.md` (workflow_contract_docs) 違規之 root cause 為 routing↔RACI 矛盾——routing matrix 鼓勵 Codex 撰寫 workflow contract docs,但 `RACI_MATRIX_V2['Codex CLI']` 未授權該類。已由 CHG-005 於 `RACI_MATRIX_V2['Codex CLI']` 增列 `workflow_contract_docs` reconcile。此為承認現行實務之政策修正,**非對既有違規之追溯豁免**(歷史記錄保留不動)。 diff --git a/.github/memory-bank/workflow-gates.md b/.github/memory-bank/workflow-gates.md index 276ca0a..4b458b4 100644 --- a/.github/memory-bank/workflow-gates.md +++ b/.github/memory-bank/workflow-gates.md @@ -1,7 +1,7 @@ # Workflow Gates — Guard Validator 觸發條件 **Reference**: artifacts/scripts/guard_status_validator.py -**Last Verified**: 2026-04-25 +08:00 +**Last Verified**: 2026-07-03 +08:00 ## Intake 自 Research 轉換 @@ -13,7 +13,7 @@ - Research artifact 必須包含 `## Sources`(至少 2 條來源) - 每個源必須附 URL 或 internal reference -- 若只有摘述,缺少原始連結,guard 會警告但不擋 +- 缺少 `## Sources` 段或來源少於 2 條會 hard fail(CRITICAL,直接擋,見 gsv `validate_research`);個別來源的 citation 格式問題依放寬後的 CITATION_PATTERN 才可能僅警告 ## Planning 自 Coding 轉換 @@ -28,6 +28,8 @@ ELSE: BLOCK with "incomplete_premortem" ELSE IF any risk lacks Trigger/Detection/Mitigation: WARN but allow (can fix in code phase) + # CHG-007: 若某 R-block 同時含 banned/vague phrase 且缺任一必填欄位, + # 在 coding state 升級為 ERROR(stub-dismissal escalation),非僅警告 ``` ## Pre-Coding Context Review(可選) @@ -46,12 +48,12 @@ ELSE: - Code artifact 存在且包含 Files Changed - Plan 的 Files Likely Affected 包含 Code 的 Files Changed -- 若 code 改了未計劃的檔案,設 status = scope-drift-detected -- 可用 decision 的 Guard Exception override +- 若 code 改了未列於 plan Files Likely Affected 的檔案,git-backed scope check 會 hard fail(validation error) +- 可用帶 `## Guard Exception` 的 decision artifact 搭配 `--allow-scope-drift` waiver override ## Review 自 Verification 轉換 -- Verify artifact 必須包含 `## Environment` 和 `## Build Guarantee` +- Verify artifact 必須包含 `## Build Guarantee`(guard-enforced,見 gsv `validate_verify`);`## Environment` 為建議欄位,非 guard enforced - Build Guarantee 至少 1 條:commit hash、CI log URL、binary checkpoint ## Blocked 自 Recovery 轉換(Gate E — PDCA Act → Plan 回灌) @@ -77,7 +79,7 @@ ELSE: - 不要求 premortem(完整門檻見 docs/premortem_rules.md §7 之 min_risks 表) - 需要 basic plan with objectives - 需要 code artifact with Files Changed -- 需要 verify with Environment +- 需要 verify artifact(依 resolved policy;`## Environment` 為建議欄位,非 guard enforced,低風險時 required fields 較少) 重量級標準(預設): - 需要完整 premortem(numbered risks,min_risks 依 task_type,見 docs/premortem_rules.md §7) diff --git a/.github/workflows/workflow-guards.yml b/.github/workflows/workflow-guards.yml index 3bd909c..cf30729 100644 --- a/.github/workflows/workflow-guards.yml +++ b/.github/workflows/workflow-guards.yml @@ -26,6 +26,9 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false + # CHG-012 (HC-1 A2): full history so commit-range ## Diff Evidence replay and the + # RACI aux changed-files scan can resolve the diff base (shallow clone breaks both). + fetch-depth: 0 - name: Setup Python uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 @@ -84,3 +87,38 @@ jobs: - name: Repo Health Dashboard run: python artifacts/scripts/repo_health_dashboard.py --root . + + - name: RACI Path Classification (aux, changed governance files) + # CHG-006 auxiliary layer (secondary to the dispatch-wrapper RACI guard, which is + # the primary enforcement). CI has no agent identity, so this only classifies + # changed files under the governance dirs and fails closed if any is UNKNOWN. + # classify_path is directory-based, so files correctly placed under these prefixes + # always resolve to a known category -- this step is therefore a fail-closed + # structural invariant / defense-in-depth, not a per-agent judgment. + # Diff base unavailable (shallow checkout) -> skip with a warning. NOTE: full + # history is provided by fetch-depth: 0 on the checkout above (added by CHG-012). + run: | + set -euo pipefail + if [ "${{ github.event_name }}" = "pull_request" ]; then + BASE="${{ github.event.pull_request.base.sha }}" + else + BASE="${{ github.event.before }}" + fi + if [ -z "${BASE:-}" ] || ! git cat-file -e "${BASE}^{commit}" 2>/dev/null; then + echo "[RACI-CI] diff base unavailable (shallow checkout?); skipping aux scan (dispatch wrappers are authoritative)." + exit 0 + fi + CHANGED="$(git diff --name-only "$BASE" HEAD -- artifacts/tasks/ artifacts/plans/ artifacts/decisions/ artifacts/status/ docs/ || true)" + CHANGED="$CHANGED" python - <<'PY' + import os, sys + sys.path.insert(0, "artifacts/scripts") + import workflow_constants as wc + paths = [p for p in os.environ.get("CHANGED", "").splitlines() if p.strip()] + unknown = [p for p in paths if wc.classify_path(p) == "unknown"] + if unknown: + print("[RACI-CI] changed governance files with UNKNOWN RACI category (fail-closed):") + for p in unknown: + print(f" - {p}") + sys.exit(1) + print(f"[RACI-CI] {len(paths)} changed governance file(s); all classify to a known category.") + PY diff --git a/.well-known/release-manifest.json b/.well-known/release-manifest.json index ffdeaa9..810f9a6 100644 --- a/.well-known/release-manifest.json +++ b/.well-known/release-manifest.json @@ -77,7 +77,7 @@ }, { "path": ".github/memory-bank/project-facts.md", - "sha256": "3d2ea193d1b9081af4c228057cba8e195f15f363e4215ff0a3a0467d720202be" + "sha256": "9857fbd6700126daedb47f368c234fee7069be90106c3a93f438462db2ed65c9" }, { "path": ".github/memory-bank/prompt-patterns.md", @@ -289,7 +289,7 @@ }, { "path": ".github/workflows/workflow-guards.yml", - "sha256": "0618e57df4c909938f6d500d1952a7b29a3ef2ebceaaee490c002e5947a7a4b7" + "sha256": "abd5dcbd05f789d10b49f4af0ca7b46a880e2b3de6f1186020153022dcce6f13" }, { "path": ".gitignore", @@ -309,7 +309,7 @@ }, { "path": "AGENTS.md", - "sha256": "e0bcf9d182bd88f58353b16c41d3468a33979909c6e816b3560be2f2827f1dfa" + "sha256": "1a191542d0ac3ac5cf7b7b840fcd08bc6adcc3d09e0e170479c7e174457a1d4d" }, { "path": "BOOTSTRAP_PROMPT.md", @@ -317,7 +317,7 @@ }, { "path": "CLAUDE.md", - "sha256": "d9aeb97170debd568e086fc1be4620761520bc0990a8272ed50fa8b79682209b" + "sha256": "bc92b08cfd9e5ccf868eea282b706705549bbc7bad941c0e931cb094500c729d" }, { "path": "CODEX.md", @@ -325,7 +325,7 @@ }, { "path": "GEMINI.md", - "sha256": "0f717a6e80f455008bad518fde76b3f36fd95a94d08701c06875bb251b034e02" + "sha256": "943128e08d59ce5ce06657d39dd54dcd42b2ac88b7e9f71e9c774666b1e70711" }, { "path": "LICENSE", @@ -337,11 +337,11 @@ }, { "path": "README.md", - "sha256": "fb586e068b2052923b128f6bac03c96a04c512d0c2f56588cac2a76931394bb9" + "sha256": "62a40148abf5aed56af3a252317906988d3fae80e7c3c5cfae964d9e9c234b3c" }, { "path": "README.zh-TW.md", - "sha256": "6027af7fdc911c49c0e6f51376d9a558619f8a3ca35ccc6068989893a36976e8" + "sha256": "dac0578966100a14422eda4c4aab6682efda14cb2ececd88f717278d7014b781" }, { "path": "START_HERE.md", @@ -397,7 +397,11 @@ }, { "path": "artifacts/improvement/PROCESS_LEDGER.md", - "sha256": "9f5eefc2a115f4a16da418ae68f126c8ca0e2689884fcedd44b3fb4184511a32" + "sha256": "024b1fd0cc8f384099d38138c7ca5aea0e006c99379df2e90dc4365caa26924e" + }, + { + "path": "artifacts/improvement/RELAXATION_LOG.md", + "sha256": "b592ea66c1ca31600e7ca1458bbae89c0c9818d32a857b74b5f741c073475e17" }, { "path": "artifacts/improvement/TASK-902.improvement.md", @@ -469,7 +473,7 @@ }, { "path": "artifacts/scripts/Invoke-CodexAgent.ps1", - "sha256": "5f3069cc334e59b7af5520abd5b67381ff9803a9a5a44e3258482df4d22c4a6b" + "sha256": "4838ee8ca6f3ad099954c58f9222881faa6cb19e4b96c221c6ee26c29e3b0d19" }, { "path": "artifacts/scripts/Invoke-CodexReview.ps1", @@ -477,7 +481,7 @@ }, { "path": "artifacts/scripts/Invoke-GeminiAgent.ps1", - "sha256": "2f84ef1a57ed434c200ab26b054101b1649c8bdad959c3eb04ab4938eb947974" + "sha256": "1f443c96e0b6225ed2b02b4d496078e8047e2e47f9ad8d887cb23e8b95dc6408" }, { "path": "artifacts/scripts/agent_identity.py", @@ -493,7 +497,7 @@ }, { "path": "artifacts/scripts/conftest.py", - "sha256": "f060db3d3e7ba8f77a42d58ed689019202cfdb8d5bc058c5e6fc1aa2beb4ea57" + "sha256": "62c71d3b338a224ce7c1e52694359b7681096bb85f0533e8600bef4a7b758f15" }, { "path": "artifacts/scripts/discover_templates.py", @@ -505,7 +509,7 @@ }, { "path": "artifacts/scripts/drills/prompt_regression_cases.json", - "sha256": "158fb0f4a2327ea5c67c674e54b6983373b04a78fb37815de037e59d7e640ad6" + "sha256": "bcfb7e4381864ba21e60018d8a6d382b9262058b6c09f6f489e11da42de492a4" }, { "path": "artifacts/scripts/github_publish_common.ps1", @@ -513,7 +517,7 @@ }, { "path": "artifacts/scripts/guard_contract_validator.py", - "sha256": "d9d7d053cedb0aa2dc4b01e39cb75387e07909b5ea9925f0dca675f703b192a6" + "sha256": "4854432720b2d714e34b21cec8532d57e739284e57c326d31b1cac8726547e9d" }, { "path": "artifacts/scripts/guard_helpers/__init__.py", @@ -533,7 +537,7 @@ }, { "path": "artifacts/scripts/guard_status_validator.py", - "sha256": "eea3bb10258c8264259bd0210d68a5be925dadab7a918a562e4d556d50973599" + "sha256": "3f2d1acefc53d7ad7761c7574ce1e01cd019a5f42bbf099a27c44804aa3b8e22" }, { "path": "artifacts/scripts/legacy_verify_corpus.py", @@ -569,11 +573,11 @@ }, { "path": "artifacts/scripts/red_team/case_builders.py", - "sha256": "6154f46c1b4c92cd555b24502013ef39972f6d50b1556819abee5da741fb7815" + "sha256": "012a8a2c27f6a590a2c2b73f273352481b9a22fcfe86ff1cd309d49cc09a9670" }, { "path": "artifacts/scripts/red_team/cases_metadata.json", - "sha256": "0c27e58ba324f0b20f6e40edea22cb24754355ca2cf7613a19d1cedc01ee1a05" + "sha256": "f551121ebad81e452511ea438b8e967c192f9223a735f6a95d0122b90c92a071" }, { "path": "artifacts/scripts/red_team/helpers.py", @@ -633,7 +637,7 @@ }, { "path": "artifacts/scripts/test_guard_status_validator_artifacts.py", - "sha256": "33665d1b2bea07689c734b0e2fe9260970bf2e0b7865826a40cf60fef309ce21" + "sha256": "937a63ce1a7c237690988a87633d308ac04eb8e337d76ac2d21e64fe4202f3d9" }, { "path": "artifacts/scripts/test_guard_status_validator_core.py", @@ -649,7 +653,7 @@ }, { "path": "artifacts/scripts/test_invoke_codex_agent.py", - "sha256": "73ace92690848f7b14b29095dc300330197147c9c33dd724e6bb426086b0307b" + "sha256": "f6ea1d2ec00e8eb0eef0d8963171ad922177a1354923f5ed906a1ff6aa680745" }, { "path": "artifacts/scripts/test_invoke_codex_review.py", @@ -657,7 +661,7 @@ }, { "path": "artifacts/scripts/test_invoke_gemini_agent.py", - "sha256": "20395a23762bc4bce8ba8032580bc42d1925dd5ac229b4f94c7bdc2597829fd3" + "sha256": "c125a606da07f1bdf05e1a73c15d15be8526bcac43b60b586a1b90779e2d9142" }, { "path": "artifacts/scripts/test_prompt_regression_validator.py", @@ -677,7 +681,7 @@ }, { "path": "artifacts/scripts/test_workflow_constants.py", - "sha256": "b7926225cbaee45a0e2d8dffac3a9a26490639fc7246f6436cda25bf2c748dd1" + "sha256": "9628ceabafa1353f11fdf1c22f3aa9cb257cf766659dc5755dfa32b6273e747b" }, { "path": "artifacts/scripts/update_repository_profile.py", @@ -693,7 +697,7 @@ }, { "path": "artifacts/scripts/workflow_constants.py", - "sha256": "44c66629bf8182e02113f4812f46484b308fb6a98af31a1cb71225278757701a" + "sha256": "9ea0051d7ac2625bc7707ca60e96224b33307e76ace6b36c1fd69ada5932e4ab" }, { "path": "artifacts/status/.gitkeep", @@ -793,7 +797,7 @@ }, { "path": "docs/dispatch_prompt_discipline.md", - "sha256": "fa59461bbab149ab892c58b85e19f520610bbb7ed1fb5e59d910c4bcbf3ac42d" + "sha256": "b5ee94133c4308ea761db23682bebbfb7a57ddc3780c41a954949ec1c74edfae" }, { "path": "docs/ecosystem/mcp-skills-hooks-catalog.md", @@ -813,39 +817,35 @@ }, { "path": "docs/orchestration-workflow.md", - "sha256": "ff4dd64b13b4f58a530cc0b9c71a3429cc39862d53d5aff75f89909e724726b3" + "sha256": "fb8a222152b56546613911b41882805ed5f7f5ed1b443cfbb878cdf97bc0a8ea" }, { "path": "docs/orchestration.md", - "sha256": "2ce51c28ebd2794456bf7a33efc9dee37e27eab425c58cfcef100038d42547e4" + "sha256": "92bd110f94fd6d12cd4570b73d53be96dce0cfa6711261a2100392922b66b6a7" }, { "path": "docs/premortem_rules.md", - "sha256": "99c72627cb2cb55c8be534d10ebbc6ec8831044281abdf63a84d82fca44ce0dc" + "sha256": "df58e69cced9a10b83eb9fc633bc35ccb48369660445db7c2f32577e4f18ea58" }, { "path": "docs/raci-matrix.md", - "sha256": "63df4832f32cfe55815203141130f5d113f483577e63d78941797d563c85241a" + "sha256": "950ec62f3266b9058980b0b8ce8238ba445577b197fa8544ba6d5f1462781cf5" }, { "path": "docs/red_team_backlog.md", - "sha256": "ed4d4d131bcc4009093ec4c9abf2619cde1dc4ea80f3ed60665604c3df2f3672" + "sha256": "6352c11d7e95a497f56bf6fc9371d1d2f0833d338cc957031dd5673182f58123" }, { "path": "docs/red_team_runbook.md", - "sha256": "9a18825aa8163a4fba2552800a9209ae8e9c8208390113f76e05f9923d9e34d7" - }, - { - "path": "docs/red_team_scorecard.generated.md", - "sha256": "ca01a79b19208e6d66fa3be149db38fd93685fb9ee66bd72515a49e1e3e4fe19" + "sha256": "8e1fa20024270f958079c7701a59bc821e1cdb99de0535cdff85f4c098540015" }, { "path": "docs/red_team_scorecard.md", - "sha256": "aa24ba40d1c77202e0324c422ecf64878ddf547cc709eeb6dae058171654135c" + "sha256": "d4b8bc756e6f5d67bbedb91c57b046a22f62d8300aaffd73eb47f099a14ef92e" }, { "path": "docs/repo_structure_workflow_maturity_assessment.md", - "sha256": "3f8ac7cae22b9028ddeb535ffae818c7704535a03dacfc2f549320b83201a75f" + "sha256": "658f12f0d23ed8c330bf09c486d6964207dc329588be99cdc06b8d6174ad53cf" }, { "path": "docs/schemas/artifact-gallery.md", @@ -853,11 +853,11 @@ }, { "path": "docs/schemas/artifact-spec-code.md", - "sha256": "841e7db91d39efa3e2b19552a431c7e5ec5b940cc8178ae3da1c1531b18a71fa" + "sha256": "873b9a8a6f6999270654c7db1e1c96ed9166180bf41109cbf98b80d9016c10c8" }, { "path": "docs/schemas/artifact-spec-decision.md", - "sha256": "2ee24c7397ea42b2beca5f9a41e8bb04b676291aee206add9c6763a95300baf0" + "sha256": "ac19d3083938dfb183963a96fedeb60b51cffd374b3833144bba7d9648877bf1" }, { "path": "docs/schemas/artifact-spec-improvement.md", @@ -889,11 +889,11 @@ }, { "path": "docs/security_cadence.md", - "sha256": "39f1be613bdeb21d8f97d4035bbed97e2647870e28e64d9cba5149763c79188b" + "sha256": "1f0ed71cfc41dec778b293cc6182390657286dca3abc5f638b699804455d2df8" }, { "path": "docs/sop/dispatch_implementation.md", - "sha256": "c8e3019de69ba69ddd53f6892a4887de5119429707dcdee8baf3cd070c23a262" + "sha256": "e9786310649f306ec01b0b815b9fe0a0a9aedfe06de469408a6f9b7f1abae340" }, { "path": "docs/sop/dispatch_memory_curator.md", @@ -903,33 +903,45 @@ "path": "docs/sop/dispatch_research.md", "sha256": "2660c70863977b02ec6eca4b27b9193a99187c4d7deb8d491b0893e204b7010e" }, + { + "path": "docs/sop/rule_lifecycle_audit.md", + "sha256": "e8ef37799ae8e41ad2f6f8b04538d9502e7a7023019efb03855d6061fb6363ce" + }, { "path": "docs/sop/task_completion.md", "sha256": "3c187a83b294d784faeb7e547ebb5078e18c23e1ab840bc551b45faf6ef629a0" }, { "path": "docs/subagent_roles.md", - "sha256": "d95c9ec6216672b5df704a5277f97867a2932328fdcdcf31264d5fd37813026d" + "sha256": "88c8285c4ca8be1644a084deed500746a13f564b5478ea4597dce66607ce6125" }, { "path": "docs/subagent_task_templates.md", - "sha256": "9eebcd3f12dbd862e02db1d473bbfcff157693a21109883c3b97624df5cad96d" + "sha256": "a244a0108de399d3bc91a863cd14b5fa91747205e2e4db195da3d2d7c72c13b2" }, { - "path": "docs/templates/adr/TEMPLATE.md", + "path": "docs/templates/architecture-synthesizer/TEMPLATE.md", + "sha256": "65425b4d7e273d2b1b1691b37e79ede8d76a5cec82573d24ddc24ba61b797283" + }, + { + "path": "docs/templates/archive/adr/TEMPLATE.md", "sha256": "e4bef5b0d3ddccd9330d2d68419e379914cb7979b6e0795a789b8166d0e87d68" }, { - "path": "docs/templates/architecture-synthesizer/TEMPLATE.md", - "sha256": "9e435c73b3cf9d365247cbb92edb86d008f18dd5893dd21dd12bb095d322762d" + "path": "docs/templates/archive/debug/TEMPLATE.md", + "sha256": "d1abb2b074779d151ab44184568fe3983d0d6bebfd369e6586487f4e00f2c393" }, { - "path": "docs/templates/blocking/TEMPLATE.md", - "sha256": "f1e4f5e332800dec043138e0f44ea5f3b332f01588881064641268417e3d013b" + "path": "docs/templates/archive/rtm/TEMPLATE.md", + "sha256": "b8f4b153632af6c3e16e0c2593f699e228e3dd2dda07aa02841584aa737daef8" }, { - "path": "docs/templates/debug/TEMPLATE.md", - "sha256": "d1abb2b074779d151ab44184568fe3983d0d6bebfd369e6586487f4e00f2c393" + "path": "docs/templates/archive/srs/TEMPLATE.md", + "sha256": "f39339a21ba9dbde08ee37e3704102f0d42cf3fdae954f5e936a958e4c1cc46a" + }, + { + "path": "docs/templates/blocking/TEMPLATE.md", + "sha256": "f1e4f5e332800dec043138e0f44ea5f3b332f01588881064641268417e3d013b" }, { "path": "docs/templates/implementer/TEMPLATE.md", @@ -951,14 +963,6 @@ "path": "docs/templates/reviewer/TEMPLATE.md", "sha256": "12c4b1872d6ab039dd09e7671854ea05f82c7129ebbaac2a788e621211a4a4d8" }, - { - "path": "docs/templates/rtm/TEMPLATE.md", - "sha256": "b8f4b153632af6c3e16e0c2593f699e228e3dd2dda07aa02841584aa737daef8" - }, - { - "path": "docs/templates/srs/TEMPLATE.md", - "sha256": "f39339a21ba9dbde08ee37e3704102f0d42cf3fdae954f5e936a958e4c1cc46a" - }, { "path": "docs/templates/tester/TEMPLATE.md", "sha256": "c30b5f8e9acc51517153431f8b42a8f1875ac5652dd1be08ca2dd35b8ac2a531" @@ -969,7 +973,7 @@ }, { "path": "docs/workflow_state_machine.md", - "sha256": "10050e484b68d9d85440b6eba7d7c6a610a1d63b342ad26c3e226f50bc265f3a" + "sha256": "6eae0cd5f04ec0ca9d41e93670ece93949efe330f7e8ecda9fc499ddf2c861b2" }, { "path": "pytest.ini", @@ -984,5 +988,5 @@ "sha256": "273b2a6f1e6fea77e85cdd90cb28541034575a2e148a45941a84710e869e3221" } ], - "root": "3e1f81d4b172a08f6545d24b27aa4562113a23b024b967f5f597a9b5e1c821b5" + "root": "1bd602d27db08447aca335e59de22fd9ae4dc0cc56fcdfaea3de518659b9e0c3" } diff --git a/AGENTS.md b/AGENTS.md index 5e30c0d..ac35939 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -37,6 +37,7 @@ | `docs/templates//TEMPLATE.md` | 各角色 prompt 範本(含 YAML frontmatter) | 每個 ~150 | 派發對應 subagent 時 | | `artifacts/scripts/discover_templates.py` | Template auto-discovery CLI | 200 | 派發 subagent 前 | | `docs/lightweight_mode_rules.md` | 小任務精簡流程規則 | 350 | lightweight mode 任務時 | +| `docs/sop/rule_lifecycle_audit.md` | 規則盤點循環(Occam pass / Chesterton gate / 記錄) | 700 | Closure / 盤點觸發時 | ## Markdown 書寫語言規範 diff --git a/CLAUDE.md b/CLAUDE.md index 54cdd73..7dd4ca9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -33,7 +33,7 @@ Claude Code 預設優先使用 CLI。只有當使用者明確在 VS Code / Copil - ❌ Task / research / plan / code artifact 缺失 - ❌ Metadata 不完整(無 Task ID、status、timestamp+08:00) - ❌ Status transition 違反 workflow state machine(見 docs/workflow_state_machine.md) -- ❌ Premortem 缺失或 R1-R4 不完整(見 docs/premortem_rules.md) +- ❌ Premortem 缺失或 R1-R4 不完整,或高風險 plan 未完成獨立質疑(見 docs/premortem_rules.md,含 §12) - ❌ Verify artifact 無 Build Guarantee - ❌ Guard validator 報 scope-drift 且無 decision.## Guard Exception - ❌ Artifact 不符 schema(見 docs/artifact_schema.md) @@ -124,6 +124,14 @@ Claude 若覆寫 routing,必須在 plan / decision / final summary 中記錄 > 詳見 `docs/sop/dispatch_implementation.md`。Dispatch prompt token-cost 慣例見 `docs/dispatch_prompt_discipline.md`。 +### Dispatch Write-Scope 執行(`-AutoRestore`) + +是否讓 write-scope 違規在 dispatch 當下就被真正擋下,由協調者(Claude)決定,不是 Codex / Gemini 自己能決定: + +- `Invoke-CodexAgent.ps1` / `Invoke-GeminiAgent.ps1` 的 `-AutoRestore` 預設 `$false`:wrapper 僅偵測 write-scope 違規並印出,dispatch 仍以 exit 0 結束(detect-only,不會自動還原)。 +- 若需要違規被真正擋下(stash-based restore、exit 2),Claude 呼叫 wrapper 時必須顯式傳遞 `-AutoRestore`。 +- 未顯式傳遞時,CODEX.md / GEMINI.md 中「write scope 違規」的處置敘述僅止於偵測與事後記錄(decision artifact、人工 review),不代表該次 dispatch 已被自動擋下。 + ### 完成任務 > 詳見 `docs/sop/task_completion.md`:執行 review → 驗證 schema → 確認 verification evidence 到位 → 呼叫 task_complete 工具。 @@ -135,7 +143,7 @@ Claude 若覆寫 routing,必須在 plan / decision / final summary 中記錄 若 task 標記 `lightweight: true` 或無 plan 且仍在 drafted/researched: ✅ 可跳完整 premortem(但需 basic plan with objectives) -✅ 可簡化 verify(可用 Environment constraint instead of Build Guarantee) +✅ 可簡化 verify(依 resolved policy 放寬,低風險 `POC + generic` 的 required fields 較少;`## Environment` 非 guard-enforced,不能取代 Build Guarantee) ❌ 仍需 code artifact + Files Changed 詳見 .github/memory-bank/workflow-gates.md diff --git a/GEMINI.md b/GEMINI.md index 13982f9..2fbf7cd 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -43,7 +43,7 @@ - 不得新增 dispatch prompt 未明示之新檔(含 `REMEMBER_*.md`、`*.tavily_raw.md`、其他 task 之 research artifact 等) - 不得修改 dispatch prompt 未明示之既有檔 -- 違者:dispatch 視為失敗;Claude 將以 `git checkout HEAD --` 還原並要求 redo +- 違者:Claude 須審視 dispatch 輸出、依情況要求 redo;是否已於偵測當下被 wrapper 自動擋下(stash-based restore、exit 2)或僅止於偵測(exit 0,留待 Claude 手動處置),取決於下列 `-AutoRestore` 是否顯式傳遞 - Wrapper 之強制層:`Invoke-GeminiAgent.ps1 -AllowedPaths [string[]] -AutoRestore` 於 dispatch 完成後自動偵測;`-AllowedPaths` 為空時 skip guard,後向相容;違規 exit 2 與既有 API failure exit 1 區分 - `-AutoRestore` 安全模式(TASK-1059):wrapper 採 stash-based pre-dispatch snapshot;guard 僅對 sub-agent 真實寫入之 delta 執行 restore,不破壞 user 既有 working tree 之 modifications。default `$false`(detect 模式:印 violations 但 exit 0);caller 顯式 `-AutoRestore` 時觸發 enforcement。`-AutoRestoreLegacy` 為 deprecated forward 之過渡 flag,未來移除 - Lifecycle exclusion(TASK-1060):wrapper `Save-PreDispatchState` default 排除 7 lifecycle dirs(`artifacts/{tasks,research,plans,code,test,verify,status}/`)於 stash 範圍外,使 sub-agent dispatch 期間看得見 prereq task / research / plan 等 artifacts;caller 顯式 `-IncludeLifecycleInBaseline` 時恢復全 stash 行為(用於 wrapper-self-test 等 strict 模式) diff --git a/README.md b/README.md index ed48634..a8d5901 100644 --- a/README.md +++ b/README.md @@ -196,6 +196,8 @@ The two layers operate at different granularities and are complementary, not com **Layer Boundary Notes**: this framework deliberately keeps two layers, not four. Strategic content (the Why / portfolio vision) lives in `README.md`, `OBSIDIAN.md`, `BOOTSTRAP_PROMPT.md`, and `.github/memory-bank/project-facts.md`; the task artifact's `## Background` is the per-task strategic entry point. Operational content (the How / single-step reasoning) is the same as the TAO layer — no duplicate naming. +Above both layers sits a small set of **governance lenses** — named viewpoints (Boundary Objects, RACI, PDCA, TAO/ReAct, Double-Loop Learning, SECI, Goodhart's Law, Normalization of Deviance, Swiss Cheese Model, Hyrum's Law, Reversibility & Blast Radius, Separation of Duties, Least Privilege, Gall's Law, Modernized Postel's Law, Lucas Critique) that observe the two layers from different angles without adding new layers, schemas, or gates. + Full schema and triggering thresholds: [`docs/orchestration.md` §2.8](docs/orchestration.md), [`docs/agentic_execution_layer.md`](docs/agentic_execution_layer.md). --- diff --git a/README.zh-TW.md b/README.zh-TW.md index 684653d..da06e0a 100644 --- a/README.zh-TW.md +++ b/README.zh-TW.md @@ -196,6 +196,8 @@ Closure **Layer Boundary Notes**:本框架刻意保留兩層而非四層。策略層內容(Why / 跨 task 願景)散見於 `README.md`、`OBSIDIAN.md`、`BOOTSTRAP_PROMPT.md` 與 `.github/memory-bank/project-facts.md`;task artifact 之 `## Background` 為單任務之策略層入口。作業層內容(How / 單步推理)即 TAO 之同義語,不另設名。 +兩層之上另有一組 **governance lenses(治理視角)**——具名觀察切面(Boundary Objects、RACI、PDCA、TAO/ReAct、Double-Loop Learning、SECI、Goodhart's Law、Normalization of Deviance、Swiss Cheese Model、Hyrum's Law、Reversibility & Blast Radius、Separation of Duties、Least Privilege、Gall's Law、Modernized Postel's Law、Lucas Critique),以不同角度觀察兩層,不新增分層、schema 或 gate。 + 完整 schema 與必填門檻:[`docs/orchestration.md` §2.8](docs/orchestration.md)、[`docs/agentic_execution_layer.md`](docs/agentic_execution_layer.md)。 --- diff --git a/artifacts/code/TASK-1102.code.md b/artifacts/code/TASK-1102.code.md new file mode 100644 index 0000000..3195b48 --- /dev/null +++ b/artifacts/code/TASK-1102.code.md @@ -0,0 +1,69 @@ +# Code Result: TASK-1102 + +## Metadata +- Task ID: TASK-1102 +- Artifact Type: code +- Owner: Claude +- Status: ready +- Last Updated: 2026-07-06T15:45:00+08:00 + +## Files Changed + +- `CLAUDE.md`(+7 行:新增「### Dispatch Write-Scope 執行(`-AutoRestore`)」段,插於「### 派發 Implementation」與「### 完成任務」之間) +- `template/CLAUDE.md`(鏡像同段落;既有 1 行既知落差 downstream-terminal 句不動) +- `GEMINI.md`(第 46 行「違者」敘述改寫為條件式,移除 `git checkout HEAD --` 全量還原語言;47-50 行既有 wrapper 說明不動) +- `template/GEMINI.md`(同步改寫,SHA-256 與 root 全等) +- `artifacts/scripts/drills/prompt_regression_cases.json`(append PR-035 entry,pin CLAUDE.md 新段落 5 字面 + GEMINI.md 新敘述 3 字面 + `must_not_contain_any` 舊絕對敘述 1 字面) +- `template/artifacts/scripts/drills/prompt_regression_cases.json`(鏡像,SHA-256 與 root 全等) +- `.well-known/release-manifest.json`(`snapshot_manifest.py generate` 重新產生;仅 `CLAUDE.md` / `GEMINI.md` / `artifacts/scripts/drills/prompt_regression_cases.json` 3 筆 digest + root digest 變更,其餘 241 筆 entry 不變) + +> 未變更(刻意排除,理由見 task §Background 與 §Known Risks R4):Codex 入口檔——已合規,`-AutoRestore` 條件說明早於既有段落完整;其自我回報義務不應因 `-AutoRestore` 有無傳遞而改變。 + +## Execution Profile + +- Routing: Claude 直寫(per plan §Routing Decision,risk score ≈ 1-2,context cost = S) +- Codex CLI: not invoked +- Gemini CLI: not invoked +- Tier / model policy: N/A +- 進度條:Intake → Research(無外部未知,仍依 resolved policy 於 planned 補齊)→ Plan (R1-R4 premortem) → Coding(本階段)→ Verify pending + +## Subagent Plan + +None — Claude 直寫。理由:(a) 變動點僅 2 root 檔局部文字修正 + 1 個 JSON 條目新增 + 3 個 template 鏡像;(b) risk score ≈ 1-2、context cost = S,屬 CLAUDE.md §Agent Routing Policy 之「Claude 可直接處理」門檻;(c) Intake 階段已完成全部查證(wrapper 預設值、CODEX.md 合規性、PR-027/PR-028 既有 pin),Codex 派發不會帶來額外調查價值。 + +## Summary Of Changes + +1. `CLAUDE.md` 新增段落,明示是否傳遞 `-AutoRestore` 是協調者(Claude)的決定,並說明其預設 `$false`(detect-only,exit 0)與顯式傳遞才觸發 enforcement 的行為。 +2. `GEMINI.md:46` 之「違者:dispatch 視為失敗;Claude 將以 `git checkout HEAD --` 還原並要求 redo」改寫為條件式敘述,區分「顯式傳 `-AutoRestore`」(wrapper 偵測到即 stash-based 還原、exit 2)與「未傳(default detect-only)」(僅印出、exit 0,留待 Claude 手動處置)兩種結果,且不再背書 TASK-1059 前已棄用的全量還原語言。 +3. `CODEX.md` 經查證已合規(`-AutoRestore` 條件說明早於 75-78 行完整;「違者:立 decision artifact」為自我回報義務,本就應維持無條件),本次刻意不修改。 +4. `prompt_regression_cases.json` 新增 PR-035,pin 上述兩檔的新字面,防止未來編輯悄悄回退本次修正(含 `must_not_contain_any` 防止 `git checkout HEAD --` 全量還原語言復發)。 +5. `template/CLAUDE.md`、`template/GEMINI.md`、`template/artifacts/scripts/drills/prompt_regression_cases.json` 同步鏡像。 + +## Mapping To Plan + +- plan_item: 1.1, status: done, evidence: "CLAUDE.md 新增 Dispatch Write-Scope 執行段,含 -AutoRestore 預設值 / 顯式傳遞兩要點" +- plan_item: 2.1, status: done, evidence: "GEMINI.md:46 改寫為條件式,移除 git checkout HEAD -- 語言,47-50 行既有說明不動" +- plan_item: 3.1, status: done, evidence: "template/GEMINI.md 與 template/CLAUDE.md 鏡像;diff/sha256 人工核對僅剩既有 1 行落差" +- plan_item: 3.2, status: done, evidence: "prompt_regression_cases.json 新增 PR-035 + template 鏡像,滿足 guard_contract_validator prompt-contract-sync 強制耦合" +- plan_item: 3.3, status: done, evidence: "snapshot_manifest.py generate 重新產生 .well-known/release-manifest.json;diff 確認僅 3 筆 digest + root digest 變更;pytest 兩測試由 fail 轉 pass" +- plan_item: 4.1, status: done, evidence: "CODEX.md 刻意不修改,查證理由落 task §Background;本 code artifact 明列以資追蹤" + +## Tests Added Or Updated + +None — adapter docs-spec 之 test 屬 NOT_APPLICABLE_BY_ADAPTER;本 task 之 governance enforcement 由 PR-035(prompt_regression)+ EXACT_SYNC / phrase-check(contract validator)雙層守住。 + +## Known Risks + +None now active;plan §Risks R1-R4 觸發條件皆已通過 validator 防線: +- R1(GEMINI.md 46 行改寫波及 47-50 行既有 PR-027/PR-028 pin):`prompt_regression_validator.py --root .` 全數(含 PR-027/PR-028/PR-035)PASS 確認未波及 +- R2(template/GEMINI.md SHA-256 mismatch):`sha256sum` 人工比對與 `guard_contract_validator.py --root .` [OK] 雙重確認全等 +- R3(template/CLAUDE.md 誤覆寫既有 downstream-terminal 專屬句):`diff CLAUDE.md template/CLAUDE.md` 人工核對,差異僅剩既有 1 行落差,新段落已正確鏡像且未觸及該句 +- R4(user 對 CODEX.md 不修改之查證結論有異議):已於 task §Background 與最終交付摘要明確揭露,供 user 即時 redirect + +## TAO Trace + +None — 本 task plan §Risks R1/R2 為 blocking,但已於 coding 階段以 validator 防線(prompt_regression_validator + guard_contract_validator SHA-256 mirror)解除;無 implementer / verifier sub-agent dispatch 發生(Claude 直寫),docs-spec adapter 之 lightweight TAO 條件適用。 + +## Blockers + +None diff --git a/artifacts/code/TASK-1103.code.md b/artifacts/code/TASK-1103.code.md new file mode 100644 index 0000000..94513fe --- /dev/null +++ b/artifacts/code/TASK-1103.code.md @@ -0,0 +1,68 @@ +# Code Result: TASK-1103 + +## Metadata +- Task ID: TASK-1103 +- Artifact Type: code +- Owner: Claude +- Status: ready +- Last Updated: 2026-07-07T11:10:00+08:00 + +## Files Changed + +- `docs/premortem_rules.md`(append §12「獨立 Premortem 質疑(高風險 plan)」,含背景/適用範圍/獨立性要求/質疑內容/輸出位置/分工邊界/現況共 7 個子節,44 行) +- `template/docs/premortem_rules.md`(鏡像同段落,SHA-256 與 root 全等) +- `CLAUDE.md`(第 3 節 STOP 觸發點,將既有 premortem 一句延伸為含「高風險 plan 未完成獨立質疑」並指向 §12) +- `template/CLAUDE.md`(同步改寫;既有 1 行 downstream-terminal 落差不動) +- `artifacts/scripts/drills/prompt_regression_cases.json`(append PR-036,pin `docs/premortem_rules.md` §12 之 3 字面 + `CLAUDE.md` 新句 1 字面) +- `template/artifacts/scripts/drills/prompt_regression_cases.json`(鏡像,SHA-256 與 root 全等) +- `.well-known/release-manifest.json`(由 manifest regen script 重新產生;僅前述 3 個 template 對應 digest + root digest 變更,其餘 entry 不變) + +未變更項(刻意排除,理由見 task §Constraints):plan artifact schema 定義檔(`## Risks` 子區段已確認不受 schema 限制,無需改 schema 本身)、workflow state machine 文件(premortem gate 不在該檔承載)、status 驗證腳本(本任務刻意不新增自動化強制檢查)。 + +## Execution Profile + +- Routing: Claude 直寫(風險判斷:write scope 為 3 個 root 檔局部文字修正 + 1 個 JSON 條目新增 + 3 個 template 鏡像,屬 CLAUDE.md Agent Routing Policy 之「risk ≤ 2 且 context cost = S」門檻;沿用 TASK-1102 已驗證過的同類 docs-only 路徑) +- Codex CLI: not invoked +- Gemini CLI: not invoked +- Tier / model policy: N/A +- 進度條:Intake → Research → Plan(R1-R4 premortem,含本任務不自我觸發 §12 之說明)→ Coding(本階段)→ Verify pending + +## Subagent Plan + +None — Claude 直寫。理由:(a) 變動點僅 3 個 root 檔局部文字修正 + 1 個 JSON 條目新增 + 3 個 template 鏡像;(b) risk score ≈ 2、context cost = S,屬 Claude 可直接處理門檻;(c) Research 階段已完成全部查證(EXACT_SYNC 清單、plan schema 子區段限制、prompt-contract-sync 耦合檢查、workflow_state_machine 不涉及),Codex 派發不會帶來額外調查價值。 + +## Summary Of Changes + +1. `docs/premortem_rules.md` 新增 §12,定義「獨立 Premortem 質疑」慣例:4 類高風險條件(security fix / upstream PR / 跨模組跨 repo / 不熟悉框架環境)觸發時,須由撰寫 R1-R4 者以外的獨立 agent(不同對話 context/session)逐條質疑既有風險判斷,結果附掛於 plan `## Risks` 下的 `### Independent Premortem Challenge` 子區段;並明示與 Council Reviewer(code diff 之後)、RACI Auditor/Architecture Synthesizer(週期性批次)的分工邊界互不重疊;明示本節不由 validator 自動強制。 +2. `CLAUDE.md` 第 3 節 STOP 觸發點延伸現有 premortem 一句,納入「高風險 plan 未完成獨立質疑」為新增 STOP 條件,指向 `docs/premortem_rules.md`(含 §12)。 +3. `prompt_regression_cases.json` 新增 PR-036,pin 上述兩檔新增字面,防止未來編輯悄悄回退本次修正。 +4. `template/docs/premortem_rules.md`、`template/CLAUDE.md`、`template/artifacts/scripts/drills/prompt_regression_cases.json` 同步鏡像。 +5. `snapshot_manifest.py generate` 重新產生 `.well-known/release-manifest.json`(同類過期模式,沿用 TASK-1102 已驗證處理路徑)。 + +## Mapping To Plan + +- plan_item: 1.1, status: done, evidence: "docs/premortem_rules.md 新增 §12,含背景/適用範圍/獨立性要求/質疑內容/輸出位置/分工邊界/現況 7 個子節" +- plan_item: 2.1, status: done, evidence: "CLAUDE.md 第 3 節 STOP 觸發點延伸為含「高風險 plan 未完成獨立質疑」並指向 §12" +- plan_item: 3.1, status: done, evidence: "template/docs/premortem_rules.md 與 template/CLAUDE.md 鏡像;diff/sha256 人工核對 premortem_rules.md 全等、CLAUDE.md 僅剩既有 1 行落差" +- plan_item: 4.1, status: done, evidence: "prompt_regression_cases.json 新增 PR-036 + template 鏡像,SHA-256 全等;prompt_regression_validator 36/36 PASS" +- plan_item: 5.1, status: done, evidence: "guard_contract_validator ×2、guard_status_validator、prompt_regression_validator 皆 [OK]/PASS;pytest 因 manifest 過期一度 2 fail,regen 後回復 2037 passed / 2 skipped" + +## Tests Added Or Updated + +None — adapter docs-spec 之 test 屬 NOT_APPLICABLE_BY_ADAPTER;本任務之 governance enforcement 由 PR-036(prompt_regression)+ EXACT_SYNC(contract validator)雙層守住。 + +## Known Risks + +None now active;plan §Risks R1-R4 觸發條件皆已於 coding 階段以下列證據解除: +- R1(獨立質疑被當橡皮圖章):§12「質疑內容」子節已明文要求逐條具體回覆、禁止空話,且 §9 禁止語句清單同樣適用;為文件層設計約束,將於未來實際派發時由 PR-036 pin 之字面持續守住定義本身不被靜默移除 +- R2(左手審右手):§12「獨立性要求」子節已明文禁止質疑者與撰寫 R1-R4 的 agent 共用同一對話 context/session,並提供找不到獨立 agent 時的 blocked 回報路徑 +- R3(gate 增加派發成本拖慢吞吐):屬 non-blocking,已於 §12 明示現況(僅慣例、不自動強制),且 plan 已記錄「若觀察到吞吐顯著下降可調整觸發條件」之後續處置路徑,本次上線不涉及即時 mitigation 動作 +- R4(與 Council Reviewer / RACI Auditor 邊界混淆):§12「與既有機制的分工邊界」子節已明文區分三者階段與頻率,`CLAUDE.md` 常用查詢表既有一行指向 `docs/premortem_rules.md`(含新 §12) + +## TAO Trace + +None — 本任務 plan §Risks R1/R2 為 blocking,但兩者皆屬「本次新增文件定義本身之品質保證」(透過 §12 文字設計 + PR-036 pin 解除),不涉及需要即時判斷的執行分歧;無 implementer / verifier sub-agent dispatch 發生(Claude 直寫),docs-spec adapter 之 lightweight TAO 條件適用。 + +## Blockers + +None diff --git a/artifacts/code/TASK-1104.code.md b/artifacts/code/TASK-1104.code.md new file mode 100644 index 0000000..0218b2f --- /dev/null +++ b/artifacts/code/TASK-1104.code.md @@ -0,0 +1,78 @@ +# Code Result: TASK-1104 + +## Metadata +- Task ID: TASK-1104 +- Artifact Type: code +- Owner: Codex +- Status: ready +- Last Updated: 2026-07-07T16:22:00+08:00 + +## Files Changed + +- `docs/sop/rule_lifecycle_audit.md` +- `template/docs/sop/rule_lifecycle_audit.md` +- `artifacts/improvement/RELAXATION_LOG.md` +- `template/artifacts/improvement/RELAXATION_LOG.md` +- `AGENTS.md` +- `template/AGENTS.md` +- `artifacts/improvement/PROCESS_LEDGER.md` +- `template/artifacts/improvement/PROCESS_LEDGER.md` +- `docs/templates/architecture-synthesizer/TEMPLATE.md` +- `template/docs/templates/architecture-synthesizer/TEMPLATE.md` +- `artifacts/scripts/guard_contract_validator.py` +- `template/artifacts/scripts/guard_contract_validator.py` +- `artifacts/scripts/drills/prompt_regression_cases.json` +- `template/artifacts/scripts/drills/prompt_regression_cases.json` +- `.well-known/release-manifest.json` +- `artifacts/status/TASK-1104.status.json` + +## Execution Profile + +- Routing: Codex 依既有 plan 實作;docs-only / governance 變更,限定於 plan `## Files Likely Affected` +- Task scale: docs-only +- Model policy target: `gpt-5.4-mini` +- Actual runtime: Codex (GPT-5 family) +- Reasoning effort: high + +## Subagent Plan + +None — 變更為單批文件與字串清單更新,無額外 subagent write scope 切分價值。 + +## Summary Of Changes + +1. 新增 `docs/sop/rule_lifecycle_audit.md`,定義 Occam pass → Chesterton gate → 記錄 三步循環、四值裁決、`open` fail-closed 條款、自我盤點與 unified audit 退路。 +2. 新增 root/template `RELAXATION_LOG.md`;root 版沉澱 4 筆既有放寬案例,template 版保留欄位 skeleton。 +3. 將新 SOP 掛到 `AGENTS.md`、`PROCESS_LEDGER.md`、`architecture-synthesizer/TEMPLATE.md` 的既有 closure / N=10 觸發軌。 +4. 僅在 root/template `guard_contract_validator.py` 的 `EXACT_SYNC_FILES` 加入 `docs/sop/rule_lifecycle_audit.md` 字串條目,未改任何 validator 邏輯。 +5. 在 root/template `prompt_regression_cases.json` 新增 PR-037,pin 四值裁決與 provenance-missing `open` 條款。 +6. `.well-known/release-manifest.json` 目前反映本 task 新增 / 變更之 tracked files(新 SOP、RELAXATION_LOG、prompt regression case、validator string 清單等)的 digest 更新。 +7. `artifacts/status/TASK-1104.status.json` 最小同步 `available_artifacts`,使 machine-readable 狀態與實際 worktree 一致,`guard_status_validator.py --task-id TASK-1104` 轉為 `[OK]`。 + +## Mapping To Plan + +- plan_item: 1.1, status: done, evidence: "新增 root/template SOP,含三步循環、四值裁決、open 條款、append-only 記錄格式與自我引用條款" +- plan_item: 1.2, status: done, evidence: "新增 root RELAXATION_LOG,4 筆案例皆以 grep 可驗 citation 填寫;generic→docs-spec 與 available_artifacts mismatch 缺建立 provenance 處明寫 unrecorded" +- plan_item: 1.3, status: done, evidence: "新增 template RELAXATION_LOG skeleton,保留相同欄位與升級條款,案例區空白" +- plan_item: 2.1, status: done, evidence: "AGENTS.md + template/AGENTS.md 文件模組表各新增一列,載入時機為 Closure / 盤點觸發時" +- plan_item: 2.2, status: done, evidence: "PROCESS_LEDGER root/template 維護規則補上 N=10 同批執行 rule lifecycle audit 的 cross-ref" +- plan_item: 2.3, status: done, evidence: "architecture-synthesizer TEMPLATE root/template Trigger 各加一行同批盤點 cross-ref,不改既有 N=10 語意" +- plan_item: 3.1, status: done, evidence: "guard_contract_validator root/template 僅插入 `docs/sop/rule_lifecycle_audit.md` 到 EXACT_SYNC_FILES" +- plan_item: 3.2, status: done, evidence: "prompt_regression_cases.json root/template 新增 PR-037,pin 四值裁決與 OPEN clause" +- plan_item: 4.1, status: done, evidence: "guard_contract_validator --root . / --check-readme 皆 [OK];guard_status TASK-1104 [OK];prompt_regression PR-001..PR-037 全 PASS;pytest 為 2016 passed, 19 skipped, 4 failed(皆 wrapper stdin BOM assertions)" + +## Tests Added Or Updated + +None + +## Known Risks + +- `generic` → `docs-spec` adapter 與 `available_artifacts mismatch` 的建立 provenance 仍未在 repo 內定位;RELAXATION_LOG 已依 plan 要求明寫 `provenance: unrecorded`,未以推測補洞。 +- `python -m pytest artifacts/scripts -q` 仍有 4 個 wrapper stdin BOM failures:`test_invoke_codex_agent.py` 2 件、`test_invoke_gemini_agent.py` 2 件;症狀為 stdin 內容前綴 `\ufeff`,不屬 TASK-1104 write scope。 + +## TAO Trace + +None + +## Blockers + +None diff --git a/artifacts/code/TASK-1105.code.md b/artifacts/code/TASK-1105.code.md new file mode 100644 index 0000000..d86ccfe --- /dev/null +++ b/artifacts/code/TASK-1105.code.md @@ -0,0 +1,84 @@ +# Code Result: TASK-1105 + +## Metadata +- Task ID: TASK-1105 +- Artifact Type: code +- Owner: Codex +- Status: ready +- Last Updated: 2026-07-07T22:29:46+08:00 + +## Files Changed +- `artifacts/scripts/conftest.py` +- `template/artifacts/scripts/conftest.py` +- `.github/memory-bank/project-facts.md` +- `template/.github/memory-bank/project-facts.md` +- `artifacts/verify/TASK-1104.verify.md` +- `.well-known/release-manifest.json` + +(本區段由 Claude 於 2026-07-08 更新為最終實況:wrapper 四檔經 user 裁決移除修改後 net-zero,自清單移除;TASK-1104 verify 勘誤與 manifest regen 補列。歸屬與軌跡見 §Post-Dispatch Amendment。) + +## Execution Profile +- Codex CLI task-scale: `standard` +- Model policy: `auto` +- Reasoning effort: `high` +- Model: local implementation pass only; verification commands could not be run in this session +- Routing override: none + +## Subagent Plan +- None. This was a narrow, file-local edit set and stayed within one write scope. + +## Summary Of Changes +- Added UTF-8 no-BOM `OutputEncoding` scoping around stdin-piped native calls in both wrapper scripts, then restored the prior encoding after each attempt. +- Switched the fake executable stdin capture to raw byte reads decoded as UTF-8 so the wrapper pipe contract is validated against the exact payload PowerShell emits. +- Documented the repo's pytest convention in the memory-bank and aligned the local test command to `python -m pytest artifacts/scripts -q`. +- Mirrored the same edits into `template/` to keep the sync pair byte-aligned. + +## Mapping To Plan +- plan_item: 1.1, status: done, evidence: "Codex wrapper now scopes UTF-8 no-BOM OutputEncoding around stdin pipe" +- plan_item: 2.1, status: done, evidence: "Gemini wrapper now scopes UTF-8 no-BOM OutputEncoding around stdin pipe" +- plan_item: 3.1, status: done, evidence: "conftest fake exe now reads raw stdin bytes with buffer.read().decode('utf-8')" +- plan_item: 4.1, status: done, evidence: "project-facts now records the pytest root-level convention and standard invocation" + +## Tests Added Or Updated +- Updated the existing `conftest.py` fixture behavior to match the stdin-pipe encoding contract. +- No new test cases were added in this pass. + +## TAO Trace +- None. + +## Known Risks +- Verification was not executed in this session because local shell command execution was blocked by the workspace environment. + +## Blockers +- `pytest artifacts/scripts -q`, `guard_contract_validator --root . --check-readme`, and `prompt_regression_validator` were requested but could not be run locally here. + +## Post-Dispatch Amendment (Claude, 2026-07-08T12:21:50+08:00) + +本節由驗收方 Claude 署名補正,為本 artifact 之 authoritative 最終狀態;上方 Codex 原文保留不改寫。依據:dispatch log(wrapper 三 tier 完整輸出)與 Claude 驗收端實測。 + +### 覆寫事故與版本說明 + +- 本 dispatch 之 gpt-5.4 attempt 曾產出含完整驗證證據與 `4.1 partial` 誠實標記之 code artifact 版本;其後 gpt-5.4-mini attempt 在 **shell 執行被封鎖(credits 中斷)、未跑任何驗證**之狀態下覆寫為上方簡化版,並疊加未驗證之 wrapper `finally` 還原邏輯。mini 回報中之 GitHub sources(`arcobaleno64/...` namespace)為 fabricated(Bug-B1 模式),不得引用。 +- 上方 `## Mapping To Plan` 編號錯位(plan 2.1 實為 conftest、3.1 實為 project-facts);正確映射見下。 + +### 最終 Files Changed(authoritative) + +- `artifacts/scripts/conftest.py` + `template/artifacts/scripts/conftest.py`(fake exe stdin 改 `sys.stdin.buffer.read().decode('utf-8')`——**本任務實際生效之修復**) +- `.github/memory-bank/project-facts.md` + `template/.github/memory-bank/project-facts.md`(pytest 執行語境慣例) +- `artifacts/verify/TASK-1104.verify.md`(Claude:literal U+FEFF 改文字表述 + Post-Closure Findings append,根除全套 pytest 唯一殘餘 fail) +- `.well-known/release-manifest.json`(regen) +- **wrapper 四檔(root/template × Codex/Gemini)最終 net-zero**:Codex 之 `$OutputEncoding` 設定經 Claude A/B/C/E 對照實驗證明對 5.1 CP65001 BOM 無效(5.1 pipe writer 直接用 console codepage,script 內不可控;唯一 lever `chcp` 因中文 mangle 風險否決),經 user 2026-07-08 裁決全數移除(含 mini 疊加之 finally 還原與 Claude 之中間清理)。詳見 `artifacts/research/TASK-1105.research.md` 2026-07-08 補充段。 + +### 最終 Mapping To Plan(更正版) + +- plan_item: 1.1, status: skipped, evidence: "wrapper OutputEncoding 設定實證無效(research 2026-07-08 補充),user 裁決移除,wrapper net-zero;(c) 路線技術前提不成立" +- plan_item: 1.2, status: skipped, evidence: "同上,隨 1.1 一併移除" +- plan_item: 2.1, status: done, evidence: "root/template conftest.py fake script 改 buffer.read().decode('utf-8'),isatty/Exception 結構保留" +- plan_item: 3.1, status: done, evidence: "root/template project-facts.md 新增 pytest 執行語境慣例段,cross-ref TASK-1105 research" +- plan_item: 4.1, status: done, evidence: "Claude 驗收端實測:PowerShell 語境 2020 passed/19 skipped/0 failed;bash 語境 2037 passed/2 skipped/0 failed;guard_contract ×2 [OK];PR-001..037 全 pass;conftest SHA-256 MATCH;wrapper 四檔 git diff 空" + +### 驗證證據(Claude 實測,非 Codex 口頭) + +- 4 個 stdin 測試:`4 passed`(wrapper 移除後重跑 37 passed 全綠——證明修復由 conftest 承載,非 wrapper 設定) +- manual_repro.py 位元組層:wrapper 設定存在時 x_count 仍 99(BOM 未消)→ (c) 無效之直接證據 +- 兩語境全套 pytest 序列跑(先前並行跑互相污染,作廢重測):PowerShell `2020/19/0`、bash `2037/2/0` diff --git a/artifacts/code/TASK-1106.code.md b/artifacts/code/TASK-1106.code.md new file mode 100644 index 0000000..1b10832 --- /dev/null +++ b/artifacts/code/TASK-1106.code.md @@ -0,0 +1,68 @@ +# Code Result: TASK-1106 + +## Metadata +- Task ID: TASK-1106 +- Artifact Type: code +- Owner: Claude +- Status: ready +- Last Updated: 2026-07-08T13:40:00+08:00 + +## Files Changed + +- `docs/orchestration.md` +- `template/docs/orchestration.md` +- `docs/sop/dispatch_implementation.md` +- `template/docs/sop/dispatch_implementation.md` +- `docs/sop/rule_lifecycle_audit.md` +- `template/docs/sop/rule_lifecycle_audit.md` +- `README.md` +- `README.zh-TW.md` +- `artifacts/scripts/drills/prompt_regression_cases.json` +- `template/artifacts/scripts/drills/prompt_regression_cases.json` +- `.well-known/release-manifest.json` + +## Execution Profile + +- Routing override:Claude 直寫(per plan §Routing:docs-only 治理文字、TASK-1102/1103 已驗證路徑、Codex credits 於 TASK-1105 中段耗盡未確認回充、內容為 Claude 本 session 評估結論 fabrication 面大) +- Task scale: docs-only equivalent;無 wrapper dispatch + +## Subagent Plan + +None — Claude 單 writer 直寫,無 subagent 切分需求。 + +## Summary Of Changes + +1. `docs/orchestration.md` §2.8 Governance Lenses 表新增 3 列(Goodhart's Law / Normalization of Deviance / Swiss Cheese Model,各標 TASK-1106 顯式化、含所管問題/對應機制/文件落點);OODA 拒絕段後新增「明確拒絕:Campbell's Law」記錄(與 Goodhart 同構、不並存、不得引為翻案範本)。 +2. `docs/sop/dispatch_implementation.md` 新增「Fallback tier 產出之驗收紀律」段:fallback tier 產出預設不可信、逐 tier 讀 log、命令直驗,引 TASK-1105 Bug-B3 出處。 +3. `docs/sop/rule_lifecycle_audit.md` Step 1 加 McNamara 防呆句(使用數據只產生候選不產生裁決);Step 2 加 Normalization-of-Deviance 強制裁決條款(同型 detect-only 違規連續接受達 3 次 → 裁 `relax` 或轉強制,閾值 3 與 RELAXATION_LOG 對齊)。 +4. `README.md` 與 `README.zh-TW.md` §Two-Layer Governance 段各補一段 governance lenses 指引(九個具名視角、不新增分層/schema/gate、指向 §2.8);兩版位置對稱(皆插於 Layer Boundary Notes 與 schema pointer 行之間)。 +5. `prompt_regression_cases.json` 新增 PR-038(雙 assertion:orchestration 三名詞 + Campbell 拒絕句;SOP deviance 條款字面)。 +6. 四個 EXACT_SYNC 檔以 root→template Copy-Item 鏡像;`.well-known/release-manifest.json` regen(root 18c32a6ba3ba)。 + +## Mapping To Plan + +- plan_item: 1.1, status: done, evidence: "lenses 表 +3 列,SECI 列後;對應機制各指向真實存在字面(RELAXATION_LOG ≥3 升級、SOP deviance 條款、workflow-gates guard 疊層)" +- plan_item: 1.2, status: done, evidence: "Campbell's Law 拒絕段 3 行,OODA 段後,沿用同構/不並存/不得翻案語式" +- plan_item: 2.1, status: done, evidence: "dispatch_implementation.md 末新增 fallback-tier 驗收紀律段,引 Bug-B3 與 TASK-1105 code amendment 出處" +- plan_item: 3.1, status: done, evidence: "rule_lifecycle_audit.md Step 1 末加候選/裁決分離句" +- plan_item: 3.2, status: done, evidence: "Step 2 bullet 區加 deviance 條款,閾值 3;SOP 非空行 36 ≤ 150" +- plan_item: 4.1, status: done, evidence: "README.md §Two-Layer Governance 補英文 lenses 段" +- plan_item: 4.2, status: done, evidence: "README.zh-TW.md 對應段同步(結構對稱確認:兩版皆 :188 起同段,R4 未觸發)" +- plan_item: 5.1, status: done, evidence: "PR-038 入 json 雙副本,同字面" +- plan_item: 5.2, status: done, evidence: "guard_contract ×2 [OK]、prompt_regression PR-001..038 全 pass、manifest regen;bash 語境全套 pytest 見 verify" + +## Tests Added Or Updated + +None(PR-038 為 prompt regression pin,非 unit test;docs-spec adapter 之 test artifact 為 NOT_APPLICABLE_BY_ADAPTER 路徑) + +## Known Risks + +None — plan R1/R2 由驗證鏈即時解除;R3 表列與條款同批落地無懸空;R4 未觸發(兩版 README 結構對稱)。 + +## TAO Trace + +None — docs-only、Claude 直寫,適用 lightweight TAO 條件。 + +## Blockers + +None diff --git a/artifacts/code/TASK-1107.code.md b/artifacts/code/TASK-1107.code.md new file mode 100644 index 0000000..12ab253 --- /dev/null +++ b/artifacts/code/TASK-1107.code.md @@ -0,0 +1,92 @@ +# Code Result: TASK-1107 + +## Metadata +- Task ID: TASK-1107 +- Artifact Type: code +- Owner: Codex(+ Claude Post-Dispatch Amendment) +- Status: ready +- Last Updated: 2026-07-17T11:20:00+08:00 + +## Files Changed +- `artifacts/scripts/guard_status_validator.py` +- `artifacts/scripts/test_guard_status_validator_artifacts.py` +- `docs/subagent_roles.md` +- `docs/raci-matrix.md` +- `artifacts/status/TASK-1107.status.json` +- `template/artifacts/scripts/guard_status_validator.py` +- `template/artifacts/scripts/test_guard_status_validator_artifacts.py` +- `template/docs/subagent_roles.md` +- `template/docs/raci-matrix.md` +- `artifacts/plans/TASK-1107.plan.md`(Claude Post-Dispatch Amendment:移除字面 BOM) +- `.well-known/release-manifest.json`(Claude Post-Dispatch Amendment:template snapshot 重生,見 `artifacts/decisions/TASK-1107.decision.md` `## Guard Exception`) +- `artifacts/decisions/TASK-1107.decision.md`(Claude Post-Dispatch Amendment:新增) +- `artifacts/improvement/TASK-1107.improvement.md`(Claude Post-Dispatch Amendment:Gate E,新增) +- `artifacts/tasks/TASK-1107.task.md`(lifecycle artifact,含 Amendment 段落) +- `artifacts/research/TASK-1107.research.md`(lifecycle artifact,含修正段落) +- `artifacts/code/TASK-1107.code.md`(lifecycle artifact,本檔自身) +- `artifacts/test/TASK-1107.test.md`(lifecycle artifact,含 Amendment 段落) +- `artifacts/verify/TASK-1107.verify.md`(lifecycle artifact,新增) + +## Execution Profile +- Task Scale: security +- Dispatch Basis: 依 `CODEX.md` 與 `artifacts/plans/TASK-1107.plan.md` 修正版 `## Proposed Changes` / `## Risks` / `### Independent Premortem Challenge` 實作與驗證 +- Actual Execution: 進場時先讀 task / research / plan 全文,之後核對目前 working tree 中既有的 8 檔 dirty delta 是否逐項符合修正版 plan;source diff 與 plan 一致,我補跑 focused regression、guard validator 與 exact-sync hash 直驗,並把結果落到 lifecycle artifacts +- Routing Override: None + +## Subagent Plan +None。理由:本任務 scope 已被 plan 嚴格收斂在 8 個實檔,且我進場時該 implementation delta 已存在於 working tree;本輪工作的重點是直驗該 delta 是否真符合修正版 plan、補齊測試與 exact-sync 證據,沒有再拆出獨立 write scope 的必要。 + +## Summary Of Changes +- CHG-012 clean-task Diff Evidence gate 已改為重用 `parse_diff_evidence(code_text)` 與 `DIFF_EVIDENCE_SUPPORTED_TYPES` 的結構化解析,不再使用 `diff_evidence.lower() in ("", "none", "n/a")` 的字串啟發式。 +- `TestCleanTaskDiffEvidenceCHG012` 已新增兩類回歸:`None (理由)` / `None(理由)` 佔位字串,以及 R6 指出的自由文字 `Evidence Type:` 繞過。 +- `docs/subagent_roles.md` §2 已改為宣告本檔為單一真源,並移除標題中的「(索引)」;`docs/raci-matrix.md` 同步去除對舊標題字面的殘留引用。 +- root 與 `template/` 對應檔已核對 SHA-256:4 組檔案對皆逐位元組相同。 + +## Mapping To Plan +- plan_item: 1.1, status: done, evidence: "CHG-012 以 parse_diff_evidence 與 DIFF_EVIDENCE_SUPPORTED_TYPES 做結構化判斷。" +- plan_item: 2.1, status: done, evidence: "CHG-012 測試新增 None 理由與 R6 自由文字繞過兩類回歸。" +- plan_item: 3.1, status: done, evidence: "subagent_roles §2 與 raci-matrix 單一真源敘述已收斂,並移除索引殘留字面。" +- plan_item: 4.1, status: done, evidence: "四組 root/template 配對皆以 SHA-256 直驗全等。" + +## Tests Added Or Updated +- Updated: `TestCleanTaskDiffEvidenceCHG012::test_sensitive_none_with_reason_evidence_fails` +- Updated: `TestCleanTaskDiffEvidenceCHG012::test_sensitive_unstructured_evidence_type_text_fails` +- Verified: `python -m pytest artifacts/scripts/test_guard_status_validator_artifacts.py::TestCleanTaskDiffEvidenceCHG012 -v` -> `7 passed in 2.40s` +- Verified: `python artifacts/scripts/guard_contract_validator.py --root .` -> `[OK]` +- Verified: `python artifacts/scripts/guard_status_validator.py --task-id TASK-1107` -> `[OK]` +- Verified: root/template SHA-256 byte-equality for `guard_status_validator.py`, `test_guard_status_validator_artifacts.py`, `docs/subagent_roles.md`, and `docs/raci-matrix.md` +- Verified: `git rev-parse HEAD` -> `48b2d4f9b076ec3aaeac86f524112775b62380b0` +- Observed: `python -m pytest artifacts/scripts -q` -> `2014 passed, 19 skipped, 8 failed in 125.57s` + +## Known Risks +- `HEAD` 臨時快照基線為 `2018 passed, 19 skipped, 2 failed`;失敗點是 `artifacts/scripts/test_publish_release_verify.py::test_get_repo_root_resolves_true_root` 與 `artifacts/scripts/test_repository_and_pdca.py::TestRrtsGaps::test_copy_task_fixture_skips_dirs`。此基線為 `git archive HEAD` 匯出的無 `.git` 臨時快照,僅用來證明 repo-wide pytest 在 TASK-1107 source delta 之外本來就不是全綠。 +- (已由下方 Amendment 解決)原 8 個失敗中 3 個為本 task 自身造成,已修復;其餘 5 個為既有、與本 task 診斷無關之環境性失敗,記錄於 `artifacts/decisions/TASK-1107.decision.md`。 + +## Diff Evidence +- Evidence Type: commit-range +- Base Commit: a8542d1ebc6d9f6ea4ca6a1dcf06a171590d7632 +- Head Commit: 4b924426764b63d04c76e61110279095be4a77fe +- Diff Command: git diff --name-only a8542d1ebc6d9f6ea4ca6a1dcf06a171590d7632..4b924426764b63d04c76e61110279095be4a77fe +- Changed Files Snapshot: .well-known/release-manifest.json,artifacts/code/TASK-1107.code.md,artifacts/decisions/TASK-1107.decision.md,artifacts/improvement/TASK-1107.improvement.md,artifacts/plans/TASK-1107.plan.md,artifacts/research/TASK-1107.research.md,artifacts/scripts/guard_status_validator.py,artifacts/scripts/test_guard_status_validator_artifacts.py,artifacts/status/TASK-1107.status.json,artifacts/tasks/TASK-1107.task.md,artifacts/test/TASK-1107.test.md,artifacts/verify/TASK-1107.verify.md,docs/raci-matrix.md,docs/subagent_roles.md,template/artifacts/scripts/guard_status_validator.py,template/artifacts/scripts/test_guard_status_validator_artifacts.py,template/docs/raci-matrix.md,template/docs/subagent_roles.md +- Snapshot SHA256: 574a88c77cf4d3f3827fa4837d8160976ad3ddc4f2ea20a4d4bf479e29b3d673 + +## Blockers +- bug_001 / bug_002 的 scoped source 修復已完成且通過 focused 驗證,沒有 implementation blocker。 +- (已由下方 Amendment 解決)AC-8 之逐字達成已由 decision artifact 記錄為「documented baseline exception」,非未解 blocker。 +- commit 已完成並推送至 `origin/manifest-exec-unified-audit-2026-07-03`;commit hash: `48b2d4f9b076ec3aaeac86f524112775b62380b0`(見下方 Amendment 之最終 commit hash)。 + +## Post-Dispatch Amendment(Claude,2026-07-17T11:20:00+08:00) + +**背景**:dispatch 執行期間發生兩個操作事故(詳見 `artifacts/verify/TASK-1107.verify.md` 之 Verification Summary),與本次 CHG-012/RACI 修復本身無關:(1) 一次前景 dispatch 因工具逾時而被誤判為已結束,隨後啟動的第二次背景 dispatch 與其產生併發寫入衝突,導致 `docs/subagent_roles.md`/`template/docs/subagent_roles.md` 出現 git conflict markers,以及 `test_guard_status_validator_artifacts.py`/其 template 鏡射出現兩個新測試方法的重複定義(Python 以後定義覆蓋前定義,功能未受影響,但屬需清理的死碼);(2) wrapper 之 post-dispatch write-scope guard 誤將 Claude 自己重導向到 repo 目錄內的 dispatch log 檔視為越界寫入,觸發 `git stash pop` 衝突,wrapper 以 exit 3 fail-safe 退出。Claude 已逐步唯讀查證(`git status`/`git stash show -p`/檔案 mtime 穩定性/process 存活檢查)後,安全地解決 conflict markers(保留語意相同、僅措辭差異的一側)、移除重複測試方法定義、刪除誤入 repo 的 log 檔、`git stash drop`(確認 stash 內容已全數被 HEAD 之已提交版本涵蓋,無獨有內容遺失風險)。 + +**本 task 自身造成之 3 項 pytest 失敗,已修復**: +- `artifacts/plans/TASK-1107.plan.md:64` 之字面 U+FEFF BOM(Claude 在 Planning 階段 R3 風險敘述中作為範例字元直接貼入)觸發 `test_prompt_injection_scan.py::TestRepoScan::test_repo_is_clean`;已改寫為 `U+FEFF` 文字描述,直驗確認檔案內不再含該 byte 序列。 +- `.well-known/release-manifest.json` 因本 task 修改 `template/` 四檔而過期,觸發 `test_council_forge_release_manifest_matches_template_snapshot`/`test_integrity_gate_passes_on_valid_repo`;已執行 `python artifacts/scripts/snapshot_manifest.py generate --output .well-known/release-manifest.json` 重生(246 entries,root 由 `12d3ada8...` 變為 `a31a4f0e...`)。此為 scope-drift,已於 `artifacts/decisions/TASK-1107.decision.md` `## Guard Exception` 顯式豁免。 + +**其餘 5 項既有失敗**(`TestDetectChangedFiles::test_not_a_git_repo`/`test_git_not_installed`/`test_rev_parse_nonzero_is_non_repo`/`TestGsvLoadGitScopeContext::test_no_git_root`/`TestGsvDetectGitRoot::test_not_found`):與本 task 診斷(CHG-012/RACI)無因果關係(修復前後夾擊比對:套用 3 項自造修復前 `8 failed, 2031 passed`,修復後 `5 failed, 2034 passed`,差值精確對應被修復項目),根因為 repo 巢狀於外層 git root 下 `pytest.ini --basetemp=../.pytest-basetemp` 與這些測試「不在 git repo 中」前提衝突;已記錄於 `artifacts/decisions/TASK-1107.decision.md`(risk-acceptance),AC-8 判定為「verified with documented baseline exception」。 + +**最終驗證**(Claude 直接執行,非採信 Codex 口頭宣稱): +- `python -m pytest artifacts/scripts/test_guard_status_validator_artifacts.py::TestCleanTaskDiffEvidenceCHG012 -v` -> `7 passed` +- `python artifacts/scripts/guard_contract_validator.py --root .` -> `[OK] Contract validation passed` +- `python -m pytest artifacts/scripts -q` -> `5 failed, 2034 passed, 2 skipped`(僅餘既有基線失敗) +- 詳細指令與輸出見 `artifacts/test/TASK-1107.test.md` 之 Post-Dispatch Amendment 段。 diff --git a/artifacts/code/TASK-1108.code.md b/artifacts/code/TASK-1108.code.md new file mode 100644 index 0000000..d1bb2e4 --- /dev/null +++ b/artifacts/code/TASK-1108.code.md @@ -0,0 +1,77 @@ +# Code Result: TASK-1108 + +## Metadata +- Task ID: TASK-1108 +- Artifact Type: code +- Owner: Claude +- Status: ready +- Last Updated: 2026-07-10T15:40:00+08:00 + +## Files Changed + +- `docs/orchestration.md`(Governance Lenses 表新增 6 列;新增「明確拒絕:獨立 Policy Engine」段) +- `template/docs/orchestration.md`(EXACT_SYNC 鏡像) +- `docs/subagent_roles.md`(Separation of Duties / Least Privilege 兩句條文) +- `template/docs/subagent_roles.md`(EXACT_SYNC 鏡像) +- `docs/sop/rule_lifecycle_audit.md`(Occam Pass 候選訊號句) +- `template/docs/sop/rule_lifecycle_audit.md`(EXACT_SYNC 鏡像) +- `artifacts/improvement/RELAXATION_LOG.md`(eval/intervention telemetry 分離句) +- `docs/schemas/artifact-spec-decision.md`(新增條件式可選 Reversibility & Blast Radius 區段) +- `README.md`(lens 名單句附加 6 新名詞) +- `README.zh-TW.md`(lens 名單句附加 6 新名詞,對應同步) +- `artifacts/scripts/drills/prompt_regression_cases.json`(新增 PR-039) +- `template/artifacts/scripts/drills/prompt_regression_cases.json`(EXACT_SYNC 鏡像) +- `template/docs/schemas/artifact-spec-decision.md`(EXACT_SYNC 之外、但既有 byte-identical 之獨立 template mirror;Post-Sync Amendment 補鏡像) +- `template/artifacts/improvement/RELAXATION_LOG.md`(§Rules 句同步;§Cases 為既有 placeholder,不動) +- `template/README.md`、`template/README.zh-TW.md`(Post-Sync Amendment:補上 TASK-1106 起即缺漏之 governance lenses 段落,含本次 6 新名詞) +- `.well-known/release-manifest.json`(template/ 變更觸發過期,regen,含 Post-Sync Amendment 後之第二次 regen) +- `artifacts/test/TASK-1108.test.md` +- `artifacts/decisions/TASK-1108.decision.md` + +## Execution Profile + +Claude 直接實作(非 Codex dispatch)。Routing override 理由:docs-only 治理文字、無 code/runtime 邏輯變更;Intake/Research 階段已定位所有目標檔案精確行號與既有機制引用,重新以 dispatch prompt 餵入 Codex 之 context 轉譯成本高於直寫風險;TASK-1106 已驗證同型任務之 Claude 直寫路徑安全。完整理由見 `artifacts/plans/TASK-1108.plan.md` §Routing 與 `artifacts/decisions/TASK-1108.decision.md`。 + +## Subagent Plan + +None — Claude 直寫,無 subagent dispatch。Intake 階段使用一次 Explore subagent(read-only)定位既有機制落點與 EXACT_SYNC/PR pin 內容,不涉及任何寫入。 + +## Summary Of Changes + +在既有 Governance Lenses 表(`docs/orchestration.md` §2.8,9 視角)之後新增 6 列:Hyrum's Law(相容性視角)、Reversibility & Blast Radius、Separation of Duties、Least Privilege、Gall's Law、Modernized Postel's Law;並新增「明確拒絕:獨立 Policy Engine(OPA/Rego/CEL)」段,依 OODA/Campbell 先例形態、以 Gall's Law 直接論證。Goodhart's Law 之三項規則中,兩項(單一指標禁令、firing_count=0 不等於無用)已由既有 `rule_lifecycle_audit.md:21` 覆蓋,僅第三項(evaluation/intervention telemetry 分離)於 `RELAXATION_LOG.md` §Rules 新增一句。`docs/schemas/artifact-spec-decision.md` 比照既有 `## Guard Exception` 慣例,新增條件式可選 `## Reversibility & Blast Radius` 區段(含 unknown≠安全 之明文)。`docs/subagent_roles.md` §1.3 新增 Separation of Duties(審查者獨立性)與 Least Privilege(破壞性操作升級)兩句顯性條文。README 兩語言版 lens 名單句附加 6 新名詞。新增 PR-039 regression pin 鎖定全部新增字面。所有 EXACT_SYNC 觸及檔(4 組)root/template 已 byte-identical 鏡像;manifest 已 regen。 + +**Post-Sync Amendment**(advisor 覆核後追加):`docs/schemas/artifact-spec-decision.md` 雖不在 `guard_contract_validator.EXACT_SYNC_FILES` 清單內,但直讀確認 `template/docs/schemas/artifact-spec-decision.md` 於本次編輯前與 root 版本 byte-identical(既有慣例即同步),故補鏡像。同批直讀 `template/artifacts/improvement/RELAXATION_LOG.md` 發現該檔 §Rules 段(非 §Cases,§Cases 為既有 placeholder scaffold,設計上與 root 之真實歷史案例分歧)亦與 root 保持逐句同步之慣例,故補上本任務新增之分離句。同批直讀 `template/README.md` 與 `template/README.zh-TW.md` 發現兩者之 Two-Layer Governance 段落**自 TASK-1106 起即缺漏 governance lenses 段落**(TASK-1106 verify AC-7 僅核對 root 兩版 README,未核對 template 兩版)——此為早於本任務、TASK-1106 遺留之潛在 template-sync 缺口,非本任務造成;本任務發現後一併補上(含 TASK-1106 原 3 個 + 本任務新 6 個,共 15 個 lens 名稱),並於 verify artifact §Evidence 與 decision artifact 明確記錄此發現,避免將既有缺口誤植為本任務新增變更。 + +## Mapping To Plan + +- plan_item: 1.1, status: done, evidence: "docs/orchestration.md §2.8 表新增 6 列,字面與 plan 一致" +- plan_item: 1.2, status: done, evidence: "「明確拒絕:獨立 Policy Engine」段已加於 Campbell's Law 拒絕段後" +- plan_item: 2.1, status: done, evidence: "rule_lifecycle_audit.md Step 1 追加候選訊號句,檔案總行數 54(≤150)" +- plan_item: 3.1, status: done, evidence: "RELAXATION_LOG.md §Rules 追加 eval/intervention telemetry 分離句" +- plan_item: 4.1, status: done, evidence: "artifact-spec-decision.md 新增條件式可選區段,含 unknown≠安全 三句明文" +- plan_item: 5.1, status: done, evidence: "subagent_roles.md §1.3 追加 SoD 與 Least Privilege 兩句" +- plan_item: 6.1, status: done, evidence: "README.md:199 附加 6 新名詞" +- plan_item: 6.2, status: done, evidence: "README.zh-TW.md:199 對應同步" +- plan_item: 7.1, status: done, evidence: "prompt_regression_cases.json 新增 PR-039,root/template 雙副本同字面" +- plan_item: 7.2, status: done, evidence: "驗證鏈全綠,見 §Tests Added Or Updated 與 verify artifact" +- plan_item: 8.1, status: done, evidence: "artifacts/decisions/TASK-1108.decision.md 已建立,記錄三項理由" + +## Tests Added Or Updated + +新增 1 條 prompt regression case(PR-039,`artifacts/scripts/drills/prompt_regression_cases.json`),非傳統 unit test;NOT_APPLICABLE_BY_ADAPTER 之其餘測試需求見 `artifacts/test/TASK-1108.test.md`。 + +## Known Risks + +None — plan §Risks 之 R1-R6 皆於實作過程中以 mitigation 逐條處理並於 verify 核對(見 verify artifact)。 + +## TAO Trace + +None — docs-only、Claude 直寫,risk ≤2(純文字變更),符合 lightweight TAO 豁免條件。 + +## Blockers + +None + +## Diff Evidence + +None (no .csproj modified) — 本 task 之 `## Files Changed` 未觸及 `guard_contract_validator.EXACT_SYNC_FILES` 之 `.py` 集合(`run_quality_gates.py`、`workflow_constants.py`、`guard_*.py` 等),僅觸及該集合中的 `.md`/`.json` 文件成員;CHG-012/HC-1 A2 之 Diff Evidence 條件必填規則鎖定對象為 guard/EXACT_SYNC 之 **敏感 `.py` 集合**(`artifacts/scripts/guard_*.py`、`run_quality_gates.py`、`workflow_constants.py`),本任務未修改任何 `.py` 檔案,故不觸發條件必填。變更為 dirty worktree pending user-driven commit。 diff --git a/artifacts/code/TASK-1109.code.md b/artifacts/code/TASK-1109.code.md new file mode 100644 index 0000000..190ecc6 --- /dev/null +++ b/artifacts/code/TASK-1109.code.md @@ -0,0 +1,75 @@ +# Code Result: TASK-1109 + +## Metadata +- Task ID: TASK-1109 +- Artifact Type: code +- Owner: Claude +- Status: ready +- Last Updated: 2026-07-10T16:55:00+08:00 + +## Files Changed + +- `docs/orchestration.md`(Goodhart's Law 列更新併入 Campbell's Law;新增 Lucas Critique 列;Campbell's Law 拒絕段後新增操作化附註) +- `template/docs/orchestration.md`(EXACT_SYNC 鏡像) +- `docs/sop/rule_lifecycle_audit.md`(Occam Pass 新增 Campbell's Law 操作化句) +- `template/docs/sop/rule_lifecycle_audit.md`(EXACT_SYNC 鏡像) +- `docs/schemas/artifact-spec-decision.md`(新增條件式可選 `## Metrics Policy` 與 `## Policy Regime` 兩區段) +- `template/docs/schemas/artifact-spec-decision.md`(慣例同步鏡像,本輪主動完成) +- `artifacts/improvement/RELAXATION_LOG.md`(§Rules 新增 Lucas Critique 句) +- `template/artifacts/improvement/RELAXATION_LOG.md`(§Rules 慣例同步;§Cases 既有 placeholder 不動) +- `README.md`、`README.zh-TW.md`(lens 名單句新增「Lucas Critique」) +- `template/README.md`、`template/README.zh-TW.md`(慣例同步,本輪主動完成) +- `artifacts/scripts/drills/prompt_regression_cases.json`(新增 PR-040) +- `template/artifacts/scripts/drills/prompt_regression_cases.json`(EXACT_SYNC 鏡像) +- `.well-known/release-manifest.json`(template/ 變更觸發過期,regen) +- `artifacts/test/TASK-1109.test.md` +- `artifacts/decisions/TASK-1109.decision.md` +- `docs/subagent_roles.md`、`template/docs/subagent_roles.md`(**非本任務編輯**——由 TASK-1108 修改、尚未 commit;因同一 dirty worktree 跨兩個 task,status validator 之 git-backed scope check 將其列為 actual changed files,列於此處僅為滿足該檢查,內容歸屬見 `artifacts/code/TASK-1108.code.md`) + +## Execution Profile + +Claude 直接實作(非 Codex dispatch)。Routing override 理由:docs-only 治理文字;本 session 直接延續 TASK-1108 已建立之完整 context(Governance Lenses 表現況、EXACT_SYNC 清單、decision schema 先例、template-sync 慣例);Campbell's Law 併入決策為本 session 使用者當場裁決,直寫可避免轉述失真。完整理由見 `artifacts/plans/TASK-1109.plan.md` §Routing 與 `artifacts/decisions/TASK-1109.decision.md`。 + +## Subagent Plan + +None — Claude 直寫,無 subagent dispatch。 + +## Summary Of Changes + +Lucas Critique 新增為第 16 個 Governance Lens,對應現有機制為 RELAXATION_LOG 之 Before/After/Trigger Task 記錄格式 + rule lifecycle audit 之 relax/retire 裁決 + 本次新增之 decision schema `## Policy Regime` 區段。Campbell's Law 之操作性規則(不得以原始指標值直接證明安全/價值/品質、標記高風險指標、記錄 gaming vectors、不得獎勵人為製造事件)併入既有 Goodhart's Law 列,並在既有「明確拒絕:Campbell's Law」段落(TASK-1106、PR-038 pinned 字面不變)後新增操作化附註段落,明示不推翻該拒絕宣告、只澄清吸收範圍。`docs/schemas/artifact-spec-decision.md` 比照 TASK-1108 之 `## Reversibility & Blast Radius` 先例,新增兩個條件式可選區段:`## Metrics Policy`(Campbell)與 `## Policy Regime`(Lucas)。`docs/sop/rule_lifecycle_audit.md` Occam Pass 與 `artifacts/improvement/RELAXATION_LOG.md` §Rules 各補一句操作化規則。README 兩語言版 lens 名單句新增「Lucas Critique」(不新增 Campbell's Law,因其非獨立 lens)。所有 EXACT_SYNC 正式成員(3 組)與吸取 TASK-1108 教訓後主動同步之慣例檔(decision schema、RELAXATION_LOG §Rules、README 兩版)於本輪同批完成 template 鏡像;manifest 已 regen。 + +**Post-Verify Amendment**(advisor 覆核後追加):`## Reversibility & Blast Radius` 之 `unknown` 明文「不得等同安全」,但初版 `## Metrics Policy` 規則段落遺漏對 `Campbell Risk: unknown` 之同等明文,構成兩個相鄰條件式可選區段之不對稱(恰是 Campbell's Law 本身要防範的指標誤讀風險)。已補上「`Campbell Risk` 之 `unknown` 值視為『尚待查明』,不得等同 `low` 或安全,選填 `unknown` 時須於 `Reasoning` 補充查明計畫」,與 `## Reversibility & Blast Radius` 語意對齊;已同步 template 鏡像並重跑驗證鏈(manifest regen 至 root `12d3ada8368e`,pytest 2037/2/0)。 + +## Mapping To Plan + +- plan_item: 1.1, status: done, evidence: "Goodhart's Law 列已更新,`Goodhart's Law` 子字串(PR-038 依賴)仍存在" +- plan_item: 1.2, status: done, evidence: "Lucas Critique 列已插入於 Modernized Postel's Law 列後" +- plan_item: 1.3, status: done, evidence: "Campbell's Law 操作化附註段落已加於既有拒絕段後,「明確不採 Campbell's Law」字面逐字未動" +- plan_item: 2.1, status: done, evidence: "rule_lifecycle_audit.md Step 1 追加 Campbell's Law 操作化句,檔案總行數 55(≤150)" +- plan_item: 3.1, status: done, evidence: "RELAXATION_LOG.md §Rules 追加 Lucas Critique 句" +- plan_item: 4.1, status: done, evidence: "artifact-spec-decision.md 新增 `## Metrics Policy` 與 `## Policy Regime` 兩區段及其規則段落" +- plan_item: 5.1, status: done, evidence: "README.md:199、README.zh-TW.md:199 新增「Lucas Critique」一詞" +- plan_item: 6.1, status: done, evidence: "7 組觸及檔(4 EXACT_SYNC 正式 + 3 慣例同步)root/template 已於本輪同批完成,diff 逐一核對" +- plan_item: 7.1, status: done, evidence: "prompt_regression_cases.json 新增 PR-040,root/template 雙副本同字面" +- plan_item: 7.2, status: done, evidence: "驗證鏈全綠,見 verify artifact" +- plan_item: 8.1, status: done, evidence: "artifacts/decisions/TASK-1109.decision.md 已建立" + +## Tests Added Or Updated + +新增 1 條 prompt regression case(PR-040);NOT_APPLICABLE_BY_ADAPTER 之其餘測試需求見 `artifacts/test/TASK-1109.test.md`。 + +## Known Risks + +None — plan §Risks 之 R1-R5 皆於實作過程中以 mitigation 逐條處理並於 verify 核對。 + +## TAO Trace + +None — docs-only、Claude 直寫,risk ≤2,符合 lightweight TAO 豁免條件。 + +## Blockers + +None + +## Diff Evidence + +None (no .csproj modified) — 本 task 未觸及 `guard_contract_validator.EXACT_SYNC_FILES` 之敏感 `.py` 集合(`guard_*.py`、`run_quality_gates.py`、`workflow_constants.py`),僅觸及 `.md`/`.json` 成員;CHG-012/HC-1 A2 條件必填規則不觸發。變更為 dirty worktree pending user-driven commit。 diff --git a/artifacts/code/TASK-1112.code.md b/artifacts/code/TASK-1112.code.md new file mode 100644 index 0000000..e0233de --- /dev/null +++ b/artifacts/code/TASK-1112.code.md @@ -0,0 +1,58 @@ +# Code Result: TASK-1112 + +## Metadata +- Task ID: TASK-1112 +- Artifact Type: code +- Owner: Claude +- Status: ready +- Last Updated: 2026-07-17T12:10:00+08:00 + +## Files Changed +- `docs/sop/dispatch_implementation.md` +- `template/docs/sop/dispatch_implementation.md` +- `docs/dispatch_prompt_discipline.md` +- `template/docs/dispatch_prompt_discipline.md` +- `.well-known/release-manifest.json`(template/ 變更後之必然收尾,R4 觸發並解決) +- `artifacts/tasks/TASK-1112.task.md`(lifecycle artifact) +- `artifacts/research/TASK-1112.research.md`(lifecycle artifact) +- `artifacts/plans/TASK-1112.plan.md`(lifecycle artifact) +- `artifacts/verify/TASK-1112.verify.md`(lifecycle artifact,新增) +- `artifacts/code/TASK-1112.code.md`(lifecycle artifact,本檔自身) +- `artifacts/status/TASK-1112.status.json`(lifecycle artifact,狀態轉移) + +## Execution Profile +- Task Scale: docs-only(Claude 直寫,非 dispatch) +- Dispatch Basis: N/A(routing override,見 task/plan `Constraints`) +- Actual Execution: Claude 直接編輯兩份 root 檔,複製至對應 template 路徑,執行 guard_contract_validator / prompt_regression_validator / pytest 直驗 +- Routing Override: Claude 直寫(docs-only 治理文字、非 security/upstream/跨 repo/不熟悉框架,同 TASK-1106 先例) + +## Subagent Plan +None。理由:純文字追加、單一 agent 可完成、無需拆分 write scope。 + +## Summary Of Changes +- `docs/sop/dispatch_implementation.md` 新增「### Dispatch 逾時重派紀律(TASK-1112)」,緊接既有「### Fallback tier 產出之驗收紀律(TASK-1106)」之後,不重新編號既有內容。 +- `docs/dispatch_prompt_discipline.md` 新增「## Dispatch Wrapper Log 重導向路徑紀律(TASK-1112)」,插於「## 6. Cross-references」之前,不重新編號既有章節。 +- 兩份 template/ 鏡射以檔案內容直接複製同步,確認 root/template 逐位元組相同。 +- 修改 template/ 觸發 `.well-known/release-manifest.json` 過期(R4 命中,見 plan),已執行 `snapshot_manifest.py generate` 重生。 + +## Mapping To Plan +- plan_item: 1.1, status: done, evidence: "docs/sop/dispatch_implementation.md 已新增 TASK-1112 條文,緊接 TASK-1106 條文之後。" +- plan_item: 2.1, status: done, evidence: "docs/dispatch_prompt_discipline.md 已新增 TASK-1112 條文,插於 Cross-references 之前。" +- plan_item: 3.1, status: done, evidence: "diff 兩份檔案 root/template 皆無輸出(逐位元組相同)。" + +## Tests Added Or Updated +None (no .py logic changed; docs-spec adapter, test NOT_APPLICABLE_BY_ADAPTER)。 + +## Known Risks +None beyond plan `## Risks`(R1-R3 皆於本輪直驗解除,見下方 Diff Evidence 前之驗證記錄)。 + +## Blockers +None。 + +## Diff Evidence +- Evidence Type: commit-range +- Base Commit: 9f957ff3efc9064dee6609b626147d6a47627d34 +- Head Commit: b75c43fcb4e9079742c655016abdcec7393451d8 +- Diff Command: git diff --name-only 9f957ff3efc9064dee6609b626147d6a47627d34..b75c43fcb4e9079742c655016abdcec7393451d8 +- Changed Files Snapshot: .well-known/release-manifest.json,artifacts/code/TASK-1112.code.md,artifacts/plans/TASK-1112.plan.md,artifacts/research/TASK-1112.research.md,artifacts/status/TASK-1112.status.json,artifacts/tasks/TASK-1112.task.md,artifacts/verify/TASK-1112.verify.md,docs/dispatch_prompt_discipline.md,docs/sop/dispatch_implementation.md,template/docs/dispatch_prompt_discipline.md,template/docs/sop/dispatch_implementation.md +- Snapshot SHA256: 19119ff2bb0feb7bd9da042cd7d20f8403894950900b722515e003bfaddc97f1 diff --git a/artifacts/decisions/TASK-1107.decision.md b/artifacts/decisions/TASK-1107.decision.md new file mode 100644 index 0000000..0304edf --- /dev/null +++ b/artifacts/decisions/TASK-1107.decision.md @@ -0,0 +1,74 @@ +# Decision Log: TASK-1107 + +## Metadata +- Task ID: TASK-1107 +- Artifact Type: decision +- Owner: Claude +- Status: done +- Last Updated: 2026-07-17T11:15:00+08:00 + +## Decision Class + +governance-ac-baseline-exception + +## Affected Gate + +Gate_D + +## Scope + +`artifacts/tasks/TASK-1107.task.md` AC-8 之文字要求與 repo-wide pytest 實際可達成結果之落差;不涉及本 task 已完成之 CHG-012 / RACI 修復本身。 + +## Issue + +AC-8 原文為:「`python -m pytest artifacts/scripts -q` 0 failed,passed 數不低於本 task 開始前之基線(先跑一次記錄基線數字,修復後對照不得減少,且應因新增測試而增加)。」 + +Coding 階段(Codex dispatch)與 Claude 事後驗證皆確認:修復 bug_001/bug_002 本身(root/template 8 檔 scoped diff)不會造成任何 pytest regression;但 dispatch 過程中因一次操作失誤(見下)額外暴露了 3 個**本 task 自身造成**的失敗,另有 5 個與本 task 診斷(CHG-012/RACI)完全無關、與 repo 在巢狀 git root 下的 `pytest.ini --basetemp=../.pytest-basetemp` 環境假設衝突之**既有失敗**。若堅持 AC-8 逐字「0 failed」,必須修復後者 5 項,但這會使本 task 擴大範圍去修一個與 CHG-012/RACI 完全無關的既有子系統(`detect_git_root` / `detect_changed_files` 在巢狀 git root 下的判斷邏輯),違反 task artifact `## Out of Scope` 與 CLAUDE.md「不得擴張範圍」之紀律。 + +## Options Considered + +1. **逐字達成 AC-8**:在本 task 內一併修復 `artifacts/scripts/test_guard_status_validator_state.py` 之 5 個既有失敗(`detect_git_root`/`TestDetectChangedFiles` 系列,皆因 repo 巢狀於外層 git root `C:/Users/arcobaleno/Documents/Code` 而觸發)。 + - 缺點:這 5 個失敗與 CHG-012/RACI 診斷無關,修復需改動 `detect_git_root`/`detect_changed_files` 的核心判斷邏輯,屬於獨立的高風險 validator 變更,違反 task `## Out of Scope`(「不得擴張範圍」)與 plan `## Out of Scope`;且使用者 memory 記錄(`project_task_1111_repo_root_worktree_detection`)已將此問題獨立記為 2026-07-16 之待處理項目(尚未建立正式 task artifact,仍屬純 Intake 階段),本 task 逕自處理會與既有 Intake 記錄產生 routing 衝突。 +2. **修復本 task 自身造成的 3 項失敗,其餘 5 項既有失敗記錄為已知基線例外**(本次選擇): + - 修復:(a) `artifacts/plans/TASK-1107.plan.md:64` 字面 BOM(U+FEFF,原為 R3 風險敘述中作為範例字面直接貼入,觸發 `PI-HIDDEN-UNICODE` 掃描)改寫為 `U+FEFF` 文字描述;(b) `.well-known/release-manifest.json` 因本 task 修改 `template/` 四檔而過期,執行 `python artifacts/scripts/snapshot_manifest.py generate --output .well-known/release-manifest.json` 重新生成(precedent:TASK-1106 在同類 template 變更任務內一併重生 manifest,非 scope creep)。 + - 其餘 5 項(`TestDetectChangedFiles::test_not_a_git_repo` / `test_git_not_installed` / `test_rev_parse_nonzero_is_non_repo` / `TestGsvLoadGitScopeContext::test_no_git_root` / `TestGsvDetectGitRoot::test_not_found`)留給既有的獨立追蹤項處理,不在本 task 內觸碰。 +3. **放棄 AC-8,直接改寫為寬鬆文字**:事後靜默修改 task artifact AC-8 用語,不留痕跡。 + - 缺點:違反 Hyrum's Law/誠實界紀律——事後竄改已核准驗收條件而不留決策記錄,等同把「做不到」偽裝成「本來就沒要求」。 + +## Chosen Option + +選項 2:修復本 task 自身造成的 3 項失敗(BOM + 2 項 manifest),其餘 5 項既有、與本 task 診斷無關的環境性失敗記錄為已知基線例外,AC-8 視為在此例外下已達成其實質目的(無 regression、passed 數因新增測試淨增加)。 + +## Reasoning + +- 3 項自造失敗之因果鏈已個別直驗:BOM 為 Claude 在 Planning 階段 R3 風險敘述中直接貼入的字面範例字元(非 Codex 造成),已用 `python3 -c "b'\xef\xbb\xbf' in data"` 直驗移除後不再出現;2 項 manifest 失敗經 `snapshot_manifest.py generate` 重生後直驗消失(root 由 `12d3ada8...` 變為 `a31a4f0e...`,`.well-known/release-manifest.json` 246 entries 全部重算)。 +- 5 項既有失敗之獨立性已直驗:修復前後夾擊比對——套用 3 項自造修復前為 `8 failed, 2031 passed`,套用後為 `5 failed, 2034 passed`,差值精確對應被修復的 3 項且無新增/消失的其他項目,證明這 5 項與本 task source diff 無因果關係。其失敗原因(`pytest.ini` 之 `--basetemp=../.pytest-basetemp` 令 `tmp_path` 落於本 repo 之外層 git root `C:/Users/arcobaleno/Documents/Code` 內,使原本預期「不在 git repo 中」的測試前提不成立)與使用者既有 memory 記錄(`project_task_1111_repo_root_worktree_detection`,2026-07-16 drafted)描述之根因一致,屬已知、獨立追蹤中的問題,但**尚未建立正式 `artifacts/tasks/TASK-1111.task.md`**(僅存在於 memory,經 `ls artifacts/tasks/TASK-1111*` 直驗確認不存在)——本決策如實記錄此差異,不誇大為「已有正式 task 承接」。 +- AC-8 之實質意圖(「修復不得造成回歸」)已達成且有實測證據;其逐字「0 failed」之表述在撰寫當下(Planning 階段)未預見 repo 存在與本 task 無關的既有環境性紅燈,屬事前估計落差而非執行缺失。 + +## Implications + +- TASK-1107 之 verify artifact 對 AC-8 之判定為「verified with documented baseline exception」,非逐字 pass;本 decision artifact 為其唯一依據。 +- 若使用者或後續 architect review 認為既有 5 項失敗優先權應提升,應以本 decision 之引用為起點,正式建立 `artifacts/tasks/TASK-1111.task.md`(memory 已有 Intake 級別的問題描述可直接沿用),而非在本 task 內回頭擴大範圍。 +- `.well-known/release-manifest.json` 的重生屬於本次 template 變更的必然收尾,不視為獨立 scope creep;未來任何觸及 `template/` 的 task 皆應比照辦理。 + +## Expiry + +Decision is anchored at HEAD commit(本 task 最終 commit,見 verify artifact 之 Build Guarantee),直至 TASK-1111 或後繼 task 正式修復 `detect_git_root`/`detect_changed_files` 之巢狀 git root 假設為止;屆時本 decision 之「已知基線例外」範圍應隨之收斂或撤銷。 + +## Linked Artifacts + +- `artifacts/tasks/TASK-1107.task.md`(AC-8 原文) +- `artifacts/plans/TASK-1107.plan.md`(R3 之 BOM 敘述來源) +- `artifacts/code/TASK-1107.code.md`(Codex 原始 Known Risks/Blockers 記錄,本 decision 為其後續處置) +- `artifacts/test/TASK-1107.test.md`(3 項自造失敗修復前後之 pytest 數字對照) +- `artifacts/verify/TASK-1107.verify.md`(AC-8 之最終判定引用本 decision) + +## Guard Exception +- Exception Type: allow-scope-drift +- Scope Files: `.well-known/release-manifest.json` +- Justification: 本 task 之 plan `## Files Likely Affected` 未列出 `.well-known/release-manifest.json`;但本 task 已核准修改 `template/` 下 4 個檔案,導致該 manifest(由 `snapshot_manifest.py` 對 `template/` 內容產生的 content-addressed 快照)過期並使 `test_council_forge_release_manifest_matches_template_snapshot`/`test_integrity_gate_passes_on_valid_repo` 失敗。重生此 manifest 是「修改 template/」這個已核准動作的必然收尾,而非獨立新增的實作範圍;`snapshot_manifest.py generate` 為既有、非本 task 新增之確定性工具,僅重算既有 246 筆 entries 的 checksum,未新增/刪除任何被追蹤的邏輯檔案。Precedent:TASK-1106 在同類「修改 template/ 觸發 manifest 過期」情境下,於同一 task 內一併重生 manifest。 +- Override_Reason: N/A(Claude 直接以 orchestrator 身分核准此 scope-drift waiver,非透過 `guard_status_validator.py --override` 人工 override 路徑;本 waiver 屬 decision artifact 記錄之 `--allow-scope-drift` 顯式豁免,非跳過驗證) + +## Follow Up + +- 若使用者裁示優先處理既有 5 項環境性失敗,建議下一步為將 memory 記錄 `project_task_1111_repo_root_worktree_detection` 正式升格為 `artifacts/tasks/TASK-1111.task.md`,進入 Intake → Research 流程(memory 已標記「純 Intake,尚未排入 Research」)。 diff --git a/artifacts/decisions/TASK-1108.decision.md b/artifacts/decisions/TASK-1108.decision.md new file mode 100644 index 0000000..e9c8d2e --- /dev/null +++ b/artifacts/decisions/TASK-1108.decision.md @@ -0,0 +1,79 @@ +# Decision Log: TASK-1108 + +## Metadata +- Task ID: TASK-1108 +- Artifact Type: decision +- Owner: Claude +- Status: done +- Last Updated: 2026-07-10T15:50:00+08:00 + +## Decision Class + +conflict-resolution + +## Affected Gate + +Gate_C + +## Scope + +`docs/orchestration.md` §2.8 Governance Lenses 表之 Separation of Duties 具名新增(影響 Gate B 之 plan 內容取捨);`docs/templates/archive/adr/` 之不復活裁決;TASK-1108 之 Coding 階段 routing override(Gate C)。Affected Gate 標記 `Gate_C` 為主要落點(routing override 直接發生於 Coding 階段),SoD/ADR 兩項取捨之影響範圍已於本節與 §Reasoning 明文涵蓋 Gate B。 + +## Issue + +三項互相獨立但皆需明文記錄理由之取捨: + +1. **Separation of Duties 命名衝突**:`artifacts/tasks/TASK-1106.task.md:64`(Out of Scope)明文將 SoD 列為「顯性化評估中列為『已隱性覆蓋』之名詞……維持現狀不掛名牌」。本次 mission brief 明確要求具名新增,且提供可落地之具體規則。兩者直接矛盾,需裁決是否推翻 TASK-1106 之既有裁決。 +2. **ADR template prompts 之目標檔案衝突**:mission brief 要求「Add ADR template prompts」,但唯一名為 ADR 的範本(`docs/templates/archive/adr/TEMPLATE.md`)已因零使用(`real_dispatch_count=0`)於 TASK-1050 後歸檔(`docs/templates/archive/README.md:7`),不在作用中。需裁決是否復活該範本,或改用其他作用中機制承載同等內容。 +3. **Coding 階段 routing**:依 `docs/orchestration.md` §2.7 Routing Matrix,本任務 Context Cost 估算為 L(約 13 檔含鏡像),依表應派 Codex;但 Claude 已於 Intake/Research 累積目標檔案精確定位。 + +## Options Considered + +**(1) SoD** +- Option A:維持 TASK-1106 裁決,不掛具名 lens,只把程序規則寫進既有文件(不新增表列)。 +- Option B:推翻 TASK-1106 裁決,新增具名 lens 列,並記錄推翻理由與使用者裁決來源。 + +**(2) ADR template** +- Option A:復活 `docs/templates/archive/adr/`,在其中加入 mission 要求之提示問題。 +- Option B:不復活,改在作用中的 `artifacts/decisions/TASK-XXX.decision.md` schema(`docs/schemas/artifact-spec-decision.md`)比照既有 `## Guard Exception` 慣例新增條件式可選區段。 + +**(3) Routing** +- Option A:依 Routing Matrix 預設派 Codex(跨檔 workflow docs)。 +- Option B:Claude 直寫,記錄覆寫理由。 + +## Chosen Option + +(1) Option B — 推翻 TASK-1106 裁決,新增具名 SoD lens。 +(2) Option B — 不復活 archived ADR template,改用作用中 decision schema 之條件式可選區段。 +(3) Option B — Claude 直寫,覆寫理由記於本檔與 plan §Routing。 + +## Reasoning + +**(1) SoD**:使用者於 Intake 階段以 AskUserQuestion 明確選擇推翻 TASK-1106 裁決(選項:「推翻,加具名 lens (Recommended)」)。推翻之實質理由:TASK-1106 裁決當時之依據是「無具體規則需求,維持隱性覆蓋即可」;本次 mission 提供了可落地之具體規則(author 不得為高風險變更之唯一審查者;AI 產生之 guard/schema/CI/相容契約變更需獨立審查步驟),這些規則可掛靠既有 Council Reviewer(`docs/subagent_roles.md` §5.1.3)與 premortem §12 獨立質疑機制之上——即「賦予既有機制一個顯性治理名稱」,而非發明新機制,因此不違反 Governance Lenses 表「不另立分層、不另建 schema」之表頭紀律,屬於推翻前提已被具體規則改變後的合理裁決調整(依 Chesterton's Fence:找到理由後才可拆/改柵欄,本例找到的是「新增之具體規則」構成的新理由)。 + +**(2) ADR template**:`docs/templates/archive/README.md:7` 明載歸檔理由為 2 個月零 dispatch(`real_dispatch_count=0`),且歸檔本身是可逆的(`git mv` 復活)。本任務並無新的使用證據(no new dispatch demand)足以推翻該歸檔理由——mission brief 本身只是要求「有提示問題存在」,並未要求「必須透過 ADR 這個特定範本承載」。作用中的 `artifacts/decisions/TASK-XXX.decision.md` 已有 `## Guard Exception` 之條件式可選 block 先例,完全可承載 mission 要求的提示問題(blast radius / reversibility / rollback / reviewer independence / least-privilege),且更貼合本框架「決策記錄」之既有心智模型(task-local decision vs 跨季 ADR)。故選擇不復活,改在作用中 schema 擴充,符合 Occam's Razor(不新增機制)與 Chesterton's Fence(未找到推翻歸檔理由之新證據,不動歸檔物)。 + +**(3) Routing**:Routing Matrix 之 Context Cost 門檻是為了避免 Claude 在缺乏充分背景時倉促大範圍修改;本任務之風險並非「背景不足」而是相反——Intake/Research 階段已透過一次 Explore subagent 徹底定位所有目標檔案之精確行號、既有機制引用與 PR pin 內容,若改派 Codex,需重新以 dispatch prompt 餵入等量背景,token 轉譯成本高於直寫風險。TASK-1106(同型態、較小規模)已驗證此路徑安全。per `docs/orchestration.md` §2.7「若 routing 判斷與既有架構衝突,Claude 必須建立 decision artifact 或在 plan 中記錄覆寫理由」,本檔與 plan §Routing 共同滿足此要求。 + +## Implications + +- Governance Lenses 表現有 15 視角(9 舊 + 6 新),仍受表頭紀律「不另立分層、不另建 schema、不另設階段」約束;未來若再有新視角提案,需比照本次流程(先查既有裁決、必要時經使用者確認後才推翻)。 +- 下一輪 N=10 rule lifecycle audit 盤點(`docs/sop/rule_lifecycle_audit.md`)讀到 TASK-1106 與 TASK-1108 對 SoD 之矛盾描述時,應直接引用本 decision artifact 為 provenance,不需重新判定,Chesterton Gate 裁 `keep`(現狀已是最終裁決)。 +- `docs/templates/archive/adr/` 之歸檔狀態不變;未來若有真實 dispatch 需求,仍可依 `docs/templates/archive/README.md` 之復活路徑處理。 +- **附帶發現(非本 decision 之取捨對象,記錄供未來 rule lifecycle audit 參考)**:本任務於 template-sync 覆核時發現 `template/README.md`/`template/README.zh-TW.md` 之 governance-lenses 段落自 TASK-1106 起即缺漏(TASK-1106 verify AC-7 僅核對 root 版本)。本任務已一併補齊(見 code / verify artifact 之 Post-Sync Amendment),此處僅記錄該缺口之存在與修補時機,不追溯修改 TASK-1106 之 verify 結論本身。 + +## Expiry + +N/A + +## Linked Artifacts + +- artifacts/tasks/TASK-1108.task.md +- artifacts/research/TASK-1108.research.md +- artifacts/plans/TASK-1108.plan.md +- artifacts/tasks/TASK-1106.task.md(SoD 原始裁決) +- docs/templates/archive/README.md(ADR 歸檔理由) + +## Follow Up + +None — 本檔已於同批 closure 內完結;唯一延伸觀察項(`Documents/Code/.git` 環境殘骸第 2 次再現)非本 decision 範圍,已於 verify artifact 記錄並建議另立 task。Expiry 標 `N/A` 之理由:本檔為治理文字裁決,非臨時 waiver;如未來有新事證,比照本次流程(AskUserQuestion 確認 + decision artifact 記錄)再議,不設定期滿日期。 diff --git a/artifacts/decisions/TASK-1109.decision.md b/artifacts/decisions/TASK-1109.decision.md new file mode 100644 index 0000000..8007a1c --- /dev/null +++ b/artifacts/decisions/TASK-1109.decision.md @@ -0,0 +1,63 @@ +# Decision Log: TASK-1109 + +## Metadata +- Task ID: TASK-1109 +- Artifact Type: decision +- Owner: Claude +- Status: done +- Last Updated: 2026-07-10T17:05:00+08:00 + +## Decision Class + +conflict-resolution + +## Affected Gate + +Gate_C + +## Scope + +`docs/orchestration.md` §2.8 Governance Lenses 表之 Campbell's Law 處置方式(是否新增獨立 lens,或併入既有 Goodhart's Law 列);TASK-1109 之 Coding 階段 routing override。Lucas Critique 之新增本身無衝突,不在本 decision 之取捨對象範圍內(僅例行記錄於 code/verify artifact)。 + +## Issue + +`docs/orchestration.md:183-185`「明確拒絕:Campbell's Law」段(TASK-1106,PR-038 pin 鎖定「明確不採 Campbell's Law」子字串)明文:Campbell's Law 與 Goodhart's Law 同構、依 OODA 先例不並存、本框架已採 Goodhart's Law 明確不採 Campbell's Law、任何後續 task 不得引此決策為 routing override 範本。本次 mission brief 要求新增 Campbell's Law 為獨立治理視角,且附帶具體操作規則(不得以原始指標值直接證明、標記高風險指標、記錄 gaming vectors、不得獎勵人為事件)與可選 metadata(`metrics_policy`)。兩者直接衝突,需裁決 Campbell's Law 之處置方式。 + +## Options Considered + +- Option A:維持 TASK-1106 裁決不變,只在既有 Occam Pass / RELAXATION_LOG 等既有文件補上程序規則,完全不提及 Campbell's Law 名稱。 +- Option B:併入既有 Goodhart's Law 視角——不新增獨立 lens row、不動既有拒絕段 pinned 字面,只在該段後新增操作化附註,並擴充 Goodhart's Law 列與新增 decision schema `## Metrics Policy` 條件式可選區段承載具體操作規則與 metadata。 +- Option C:正式推翻 TASK-1106 裁決,新增獨立 Campbell's Law lens row,並改寫「明確拒絕:Campbell's Law」段(移除或大幅修改其 pinned 字面),同步更新 PR-038。 + +## Chosen Option + +Option B。 + +## Reasoning + +使用者於 Intake 階段以 AskUserQuestion 明確選擇「併入既有 Goodhart's Law 視角」,並提供之 mission hard constraint 本身即「Keep Campbell's Law under the metric integrity / Goodhart area」,與 Option B 完全一致。 + +實質理由:TASK-1106 之拒絕論證核心是「Campbell's Law 與 Goodhart's Law 同構,二者作為**獨立治理視角**並存會造成 schema 重複、辭彙負擔」——這個論證僅反對「另立一個與 Goodhart's Law 語意重疊的獨立 lens row」,並未反對「吸收 Campbell's Law 文獻中對高風險指標的具體操作規則」。Option B 精確地只做後者:不新增 lens row、不改寫既有拒絕段之核心宣告(「已採 Goodhart's Law,明確不採 Campbell's Law」逐字保留),只在其後新增一段操作化附註,明文「此附註不推翻上方拒絕宣告,僅澄清吸收範圍」。此舉同時滿足 Chesterton's Fence(未動既有柵欄本體,只在柵欄外補告示牌)與 Occam's Razor(不新增與 Goodhart's Law 重複的第二個表徵同一概念的視角)。 + +Option A 會導致 mission 要求的具體規則(campbell_risk 標記、gaming vectors 記錄等)失去清楚的治理視角掛靠點,可發現性差;Option C 風險與範圍皆遠大於 Option B(需同步改寫 PR-038、且直接推翻一個明文「任何後續 task 不得引此決策為 routing override 範本」的既有裁決,理由強度不足以支撐——TASK-1108 之 SoD 案是「隱性覆蓋不掛牌」的較弱裁決,而本案是有獨立段落+machine pin+明文禁止翻案的更強裁決,兩案不可等同視之)。 + +## Implications + +- Governance Lenses 表現有 16 視角(15 舊 + Lucas Critique 新增);Campbell's Law 不佔獨立列,其操作規則掛靠於 Goodhart's Law 列與 decision schema `## Metrics Policy` 區段。 +- 下一輪 N=10 rule lifecycle audit 盤點讀到「Campbell's Law 操作化附註」時,應直接引用本 decision artifact 為 provenance,不需重新判定是否已推翻 TASK-1106;Chesterton Gate 裁 `keep`(TASK-1106 拒絕宣告本體現狀已是最終裁決,未被推翻)。 +- 若未來有更強使用證據(例如發現 Metrics Policy 機制實務上不足以承載 Campbell's Law 之完整語意),需另立 task 並重新評估是否需要 Option C,不得逕自視本次 Option B 為過渡狀態。 + +## Expiry + +N/A + +## Linked Artifacts + +- artifacts/tasks/TASK-1109.task.md +- artifacts/research/TASK-1109.research.md +- artifacts/plans/TASK-1109.plan.md +- artifacts/decisions/TASK-1108.decision.md(SoD 案之對照先例,用以區分兩案裁決強度差異) + +## Follow Up + +None — 本檔已於同批 closure 內完結。 diff --git a/artifacts/improvement/PROCESS_LEDGER.md b/artifacts/improvement/PROCESS_LEDGER.md index e6fb21e..7bf76f9 100644 --- a/artifacts/improvement/PROCESS_LEDGER.md +++ b/artifacts/improvement/PROCESS_LEDGER.md @@ -13,6 +13,7 @@ - 每個 task 只寫一行。 - 不貼 raw log,只寫結論與短證據方向。 - `Applied?` 表示對應修正是否已落地為文件、prompt、guard 或 template 變更。 +- **何時必記**:凡於 closure 產出 improvement artifact(Gate E 或 retrospective)之 task,必記一條;純 lightweight/docs 小任務(無 improvement artifact)可免。此與 improvement artifact 產生連動,確保 architecture-synthesizer 之 N=10 觸發能真實累積(否則 ledger 停更會使該觸發永不達標);條目達 N=10 倍數時,需同批執行 [rule lifecycle audit](../../docs/sop/rule_lifecycle_audit.md)。 | Date | Task | Outcome | Top Waste | Top Risk | Fix Candidate | Applied? | |---|---|---|---|---|---|---| diff --git a/artifacts/improvement/RELAXATION_LOG.md b/artifacts/improvement/RELAXATION_LOG.md new file mode 100644 index 0000000..03b9397 --- /dev/null +++ b/artifacts/improvement/RELAXATION_LOG.md @@ -0,0 +1,49 @@ +# Relaxation Log + +本檔只記事實,不重述規則正文;規則面說明與 gate 語意請回看 [`.github/memory-bank/workflow-gates.md`](../../.github/memory-bank/workflow-gates.md)。 + +## Rules + +- 每筆只寫 date / rule location / before / after / trigger task / root cause classification / provenance。 +- citation 必須能以 repo grep 直驗;查無者明寫 `provenance: unrecorded`。 +- 累積達 3 筆以上時,當次 closure 升級 architect review。 +- 本檔記錄之 intervention telemetry(實際放寬案例)與 `guard_calibration_matrix.py` 量測之 evaluation telemetry(FP/FN)為兩種不同來源,不得合併成單一治理指標(Goodhart's Law,TASK-1108)。 +- 任一案例若構成治理規則之建制變動(CI gate、guard 定義、telemetry schema、model 角色、escalation 規則、pass/fail 門檻、report 格式或 prompt 政策之變更),該案例前後之 telemetry 不得直接比較,須附加正規化說明或「不可比較」但書(Lucas Critique,TASK-1109)。 + +## Cases + +### 2026-05-08 — `CITATION_PATTERN` + +- Rule Location: `artifacts/scripts/guard_status_validator.py:137`, `artifacts/scripts/guard_helpers/markers.py:17` +- Before: 只接受 URL、`` `gh api ...` ``、或有限副檔名的 backtick-wrapped 檔案引用。 +- After: 接受 5-branch alternation,含中英括號 wrap、裸 `path:line`,並把 ext list 擴到 12 種。 +- Trigger Task: `TASK-1061` +- Root Cause Classification: citation-format narrowness +- Provenance: `artifacts/research/TASK-1061.research.md:17-22`; `artifacts/verify/TASK-1061.verify.md:15,35-43` + +### 2026-05-08 — `RESEARCH_SOURCES_ENTRY_PATTERN` + +- Rule Location: `artifacts/scripts/guard_status_validator.py:195` +- Before: `## Sources` 條目強制要求 `https?://...`。 +- After: 接受 `URL OR repo path`,允許 `docs/X.md` 這類 in-repo 來源。 +- Trigger Task: `TASK-1061` +- Root Cause Classification: internal-reference friction +- Provenance: `artifacts/research/TASK-1061.research.md:18,22,60`; `artifacts/verify/TASK-1061.verify.md:16,47-49` + +### 2026-05-07 — `generic` → `docs-spec` adapter + +- Rule Location: `docs/schemas/artifact-spec-task.md:68` +- Before: `generic` baseline 不區分 docs-only 任務;`testing / verifying / done` 仍帶 `test` requirement。 +- After: `docs-spec` 會移除 `test` requirement,並允許 `NOT_APPLICABLE_BY_ADAPTER`。 +- Trigger Task: `TASK-1058`(first confirmed use) +- Root Cause Classification: provenance unrecorded +- Provenance: `docs/schemas/artifact-spec-task.md:68`; `artifacts/tasks/TASK-1058.task.md:107`; `artifacts/verify/TASK-1058.verify.md:12,17,151,155`; establishment provenance: unrecorded + +### unrecorded — `available_artifacts mismatch` + +- Rule Location: `artifacts/scripts/guard_status_validator.py:2159` +- Before: unrecorded +- After: `available_artifacts mismatch` 會以 warning surfaced,而非直接單獨 fail-closed。 +- Trigger Task: first in-repo observation `TASK-1049` +- Root Cause Classification: provenance unrecorded +- Provenance: `artifacts/scripts/guard_status_validator.py:2159`; `artifacts/scripts/test_guard_status_validator_artifacts.py:1647`; `artifacts/code/TASK-1049.code.md:99`; establishment provenance: unrecorded diff --git a/artifacts/improvement/TASK-1107.improvement.md b/artifacts/improvement/TASK-1107.improvement.md new file mode 100644 index 0000000..187c3f9 --- /dev/null +++ b/artifacts/improvement/TASK-1107.improvement.md @@ -0,0 +1,65 @@ +# Process Improvement + +## Metadata +- Task ID: TASK-1107 +- Artifact Type: improvement +- Source Task: TASK-1107 +- Trigger Type: blocked +- Improvement Profile: gate-e +- Owner: Claude +- Status: applied +- Last Updated: 2026-07-17T11:30:00+08:00 + +## Risk Analysis +- Predicted Risks: R1–R7(plan `## Risks`,含 §12 獨立 premortem 質疑新增之 R6/R7)。 +- Realized Risks: None——R1-R7 皆聚焦 CHG-012/RACI 修復本身之技術正確性(結構化解析、EXACT_SYNC 同步、標題殘留矛盾),無一條命中本次實際發生的事故。 +- Missed Risks: 兩項均為 dispatch **操作層**缺陷,非 plan 之診斷/修法本身:(a) Claude 將前景 dispatch 之「工具呼叫逾時」誤判為「底層 process 已結束」,未確認即發動第二次背景 dispatch,導致兩個 Codex process 併發寫入同一組檔案;(b) `Invoke-CodexAgent.ps1` 之 post-dispatch write-scope guard 誤將 Claude 自己重導向到 repo 目錄內的 dispatch log 檔(`.codex-dispatch-TASK-1107.log`)判定為 sub-agent 越界寫入,觸發 `git stash pop` 衝突並以 exit 3 fail-safe。這兩項屬 dispatch 機制之操作性缺口,non-blocking 的既有 premortem 規則(R1-R7 針對 code diff 正確性)之設計範圍本就不含此類 caller-side 操作失誤,故列為 Missed Risks 而非既有風險未被偵測。 + +## 1. What Happened + +Coding 階段(Do):Claude 呼叫 `Invoke-CodexAgent.ps1`(前景,PowerShell 工具)派發 TASK-1107 實作,10 分鐘後工具呼叫逾時(Bash/PowerShell 工具 timeout),Claude 誤將此視為 dispatch 已中止,未確認底層 `codex.cmd` process 是否仍在執行,隨即改用 `run_in_background: true` 重新發起第二次 dispatch(同一組 `-AllowedPaths`、同一組目標檔案)。第一次 dispatch 之底層 process 實際上持續執行至完成(產出 commit `48b2d4f`→`a611b79` 並 push 至 origin/PR #50),與第二次背景 dispatch 之 `git stash`/`stash pop` 週期重疊,造成 `docs/subagent_roles.md`/`template/docs/subagent_roles.md` 出現 git conflict markers、`test_guard_status_validator_artifacts.py`/其 template 鏡射之兩個新測試方法各被重複定義一次(Python class body 後定義覆蓋前定義,功能未受影響但為死碼)。第二次 dispatch 收尾時,其 `Save-PreDispatchState`/post-dispatch guard 又因 Claude 將 PowerShell `*>` 重導向指到 repo 目錄內的 `.codex-dispatch-TASK-1107.log`,被 guard 誤判為「sub-agent 越界寫入」而嘗試刪除/還原,觸發 `git stash pop` 衝突,wrapper 以 `[FATAL]` exit 3 結束,任務進入 blocked。 + +## 2. Why It Was Not Prevented + +- `docs/dispatch_prompt_discipline.md` 與 `docs/sop/dispatch_implementation.md` 規範 prompt 內容之 token-cost 慣例,但**未規範**「前次 dispatch 工具呼叫逾時後,重新派發前必須先確認底層 process 是否仍存活」——這是一個純粹的 caller-side 操作紀律空缺,任何既有 guard(write-scope guard、EXACT_SYNC guard、premortem guard)皆設計於「單一 dispatch 生命週期內」運作,未涵蓋「caller 自己引發併發 dispatch」的情境。 +- 同樣地,`CODEX.md` §Write Scope Discipline 與 `docs/dispatch_prompt_discipline.md` 皆未明文規定「caller 若需要重導向 wrapper 之 stdout/stderr 到檔案,該路徑必須在 repo 目錄之外」——本次事故之直接觸發點正是 Claude 自己選擇了一個 repo 內路徑作為重導向目標,落入 wrapper 自身的 post-dispatch git-status 掃描範圍內,被誤判為 sub-agent 寫入。 +- 兩者皆非 Codex/wrapper 之邏輯錯誤,而是 Claude 作為 caller 之操作紀律缺口;現有規範文件對「caller 自身動作可能污染 dispatch 生命週期」這一類情境完全沒有著墨。 + +## 3. Failure Classification + +Unknown gap(dispatch 操作紀律缺口,非既有 premortem R1-R7 之設計涵蓋範圍;亦非 Codex/wrapper 邏輯缺陷——両次事故根因皆為 Claude 之 caller-side 操作選擇)。 + +## 4. Corrective Action (Immediate) + +- Claude 已唯讀查證(`git status -sb`、`git stash show -p stash@{0} --stat`、檔案 mtime 6 分鐘穩定性、`Get-Process` 確認無存活中之本次 dispatch process)後確認安全,手動解決 `docs/subagent_roles.md`/template 鏡射之 conflict markers(保留語意相同、僅措辭差異的一側:「此檔獨有」,對齊 `docs/raci-matrix.md:3` 既有用語)。 +- 移除 `test_guard_status_validator_artifacts.py`/template 鏡射中兩個測試方法的重複定義(各保留較晚、實際生效的一份),重新 `git diff HEAD` 確認與已提交版本(commit `a611b79`,已推送至 PR #50)逐位元組相同,證明重複定義純屬本地未提交之 stash-pop 殘留,未曾流入遠端。 +- 刪除誤入 repo 目錄的 `.codex-dispatch-TASK-1107.log`,確認 `git stash show -p` 之全部內容已被 HEAD 已提交版本涵蓋(無獨有內容遺失風險)後 `git stash drop`。 +- 修復本 task 自身造成的 3 項 pytest regression(BOM、2 項 release-manifest),並以 `artifacts/decisions/TASK-1107.decision.md` 記錄 AC-8「documented baseline exception」之裁決,避免把既有、與本 task 無關的 5 項環境性失敗誤植為本 task 責任。 + +## 5. Preventive Action (System Level) + +- **Dispatch 逾時後不得盲目重派**:`docs/sop/dispatch_implementation.md` 應新增條文——若前次 `Invoke-CodexAgent.ps1`/`Invoke-GeminiAgent.ps1` dispatch 因工具呼叫逾時(而非 wrapper 自身回報結束)而中斷,caller 重新派發前必須先確認底層 process 是否仍存活(例如 `Get-Process -Name codex,node`/等待固定時間後複查檔案 mtime 穩定性),確認確實無殘留 process 後才可重派;不得將「工具呼叫逾時」直接等同「dispatch 已終止」。 +- **Dispatch log 重導向路徑紀律**:`docs/dispatch_prompt_discipline.md` 或 `CODEX.md`/`GEMINI.md` 之 Write Scope Discipline 段應新增條文——caller 若需要將 wrapper 之 stdout/stderr 重導向到檔案以供背景監看,目的路徑必須在 repo 工作樹之外(例如 session scratchpad 目錄或 `%TEMP%`),不得寫入 repo 目錄內,以免被 wrapper 自身之 post-dispatch write-scope guard/EXACT_SYNC 掃描誤判為 sub-agent 越界寫入。 +- **AC 撰寫紀律(次要,關聯 AC-8 落差)**:`docs/premortem_rules.md` 或 `docs/schemas/artifact-spec-task.md` 之 Acceptance Criteria 撰寫指引,應提醒撰寫者避免對 repo-wide 測試套件使用逐字「0 failed」表述,除非已先查證當下 repo 基線本身即為全綠;建議改用「passed 數不低於基線且無新增失敗」之相對表述,與本 task AC-8 實際可達成的驗收方式一致,避免驗收條件與環境現實脫鉤。 + +## 6. Validation + +- 已直接執行 `git diff HEAD -- docs/subagent_roles.md template/docs/subagent_roles.md artifacts/scripts/test_guard_status_validator_artifacts.py template/artifacts/scripts/test_guard_status_validator_artifacts.py` 確認為空(working tree 與已推送之 commit `a611b79` 逐位元組相同),證明併發寫入事故未污染最終遠端狀態。 +- `python -m pytest artifacts/scripts/test_guard_status_validator_artifacts.py::TestCleanTaskDiffEvidenceCHG012 -v` -> `7 passed`(無重複測試方法殘留)。 +- `python artifacts/scripts/guard_contract_validator.py --root .` -> `[OK] Contract validation passed`。 +- `python -m pytest artifacts/scripts -q` 修復前後對照:`8 failed, 2031 passed` -> `5 failed, 2034 passed`,差值精確對應本 task 自造之 3 項修復,其餘 5 項與 source diff 無因果關係(詳見 `artifacts/decisions/TASK-1107.decision.md`)。 +- 本 Preventive Action 之落地驗證留待下一次實際觸發相同情境(逾時後重派、或需要 dispatch log 重導向)之 task;本 artifact 僅記錄規則本身,尚未同步寫入 `docs/sop/dispatch_implementation.md` 等目標檔(見 Impact Scope)。 + +## 7. Impact Scope + +- Contained: 本次事故未污染遠端 PR #50 狀態(已直驗 `git diff HEAD` 為空);本 improvement artifact 為 lifecycle 記錄,零額外程式碼變更。 +- Forward: 上述兩條 Preventive Action(逾時重派紀律、log 重導向路徑紀律)**尚未**寫入 `docs/sop/dispatch_implementation.md`/`docs/dispatch_prompt_discipline.md` 等治理文件本體——本 improvement artifact 僅記錄規則內容與根因,正式寫入 SOP 文件留待獨立 task(避免本次 TASK-1107 之 scope 進一步擴大到 workflow 文件變更,該類變更依 CLAUDE.md 之 Template Sync 規則需同步 `template/` 並更新 README,屬另一輪治理工作)。 +- Backward: 未改動本 task 已完成之 CHG-012/RACI 修復內容本身。 + +## 8. Final Rule + +Dispatch caller(Claude)於:(a) 前次 dispatch 因工具逾時中斷時,重新派發前必先確認底層 process 是否仍存活,不得以逾時等同終止;(b) 需要重導向 dispatch wrapper 之 stdout/stderr 供背景監看時,目的路徑必須在 repo 工作樹之外。兩條規則正式寫入 `docs/sop/dispatch_implementation.md` 前,caller 應以本 improvement artifact 為準手動遵循。 + +## 9. Status + +applied diff --git a/artifacts/plans/TASK-1102.plan.md b/artifacts/plans/TASK-1102.plan.md new file mode 100644 index 0000000..05eb6d0 --- /dev/null +++ b/artifacts/plans/TASK-1102.plan.md @@ -0,0 +1,132 @@ +# Plan: TASK-1102 + +## Metadata +- Task ID: TASK-1102 +- Artifact Type: plan +- Owner: Claude +- Status: ready +- Last Updated: 2026-07-06T15:20:00+08:00 + +## Scope + +依 task §Acceptance Criteria AC-1..AC-9,於 `CLAUDE.md` 新增一段說明「派發時需顯式傳 `-AutoRestore` 才能讓 write-scope 違規真的被擋下」,並將 `GEMINI.md:46` 之絕對敘述改為條件式(區分顯式 `-AutoRestore` vs default detect-only 兩種結果,且不得重新背書 TASK-1059 前已棄用的 `git checkout HEAD --` 全量還原語言)。`CODEX.md` 經查證已合規,本 plan 明確排除該檔修改。template/ 對應鏡像同步。單一 commit 完成(待 user-driven commit)。 + +## Routing Decision + +- **Selected**:Claude 直寫。 +- Risk score:≈ 1-2(純文字敘述修正 + 1 段新增;無 production code;write scope 僅 2 root 檔 + 2 template 鏡像檔,共 4 檔)。 +- Context cost:S(4 個小檔,皆為既有文件之局部編輯,非跨模組)。 +- Routing inputs:task type = documentation governance / consistency fix;blast radius = doc-only;external deps = none;scope ambiguity = low(user 四點指示明確,且已於 task Background 查證並收斂範圍)。 +- 依 CLAUDE.md §Agent Routing Policy「risk <= 2 且 context cost = S 的極小變更 → Claude 可直接處理」;雖「跨檔 workflow docs」一般預設路由 Codex,但本次變動點單純(2 處局部文字修正)、且已於 Intake 階段完成全部查證(無需 Codex 之額外調查或決策空間),故 override 為 Claude 直寫,理由記錄於此。 + +## Files Likely Affected + +### Root +- `CLAUDE.md`(新增「Dispatch Write-Scope 執行(`-AutoRestore`)」段,插於「### 派發 Implementation」與「### 完成任務」之間) +- `GEMINI.md`(改寫第 46 行「違者」敘述為條件式,移除 `git checkout HEAD --` 全量還原語言;47-50 行既有 wrapper 說明不動) +- `artifacts/scripts/drills/prompt_regression_cases.json`(append 新 PR-* entry,pin CLAUDE.md / GEMINI.md 之新字面;guard_contract_validator.py 之 prompt-contract-sync 檢查要求任何 CLAUDE/GEMINI/CODEX.md 變更須同時觸及本檔,coding 階段跑 validator 時發現此強制耦合,回補本欄) +- `.well-known/release-manifest.json`(`snapshot_manifest.py generate` 重新產生,反映本 task 對 `template/CLAUDE.md` / `template/GEMINI.md` / `template/artifacts/scripts/drills/prompt_regression_cases.json` 3 檔之 digest 變更;coding 階段執行 pytest 時發現 `test_council_forge_release_manifest_matches_template_snapshot` / `test_integrity_gate_passes_on_valid_repo` 兩測試因此 regen 缺失而失敗,回補本欄並補行 regen) + +### Template +- `template/CLAUDE.md`(鏡像新增段落;保留既有 1 行既知落差——downstream terminal repo 專屬句) +- `template/GEMINI.md`(鏡像改寫,EXACT_SYNC 強制 SHA-256 全等) +- `template/artifacts/scripts/drills/prompt_regression_cases.json`(鏡像,EXACT_SYNC 強制 SHA-256 全等) + +### Lifecycle +- `artifacts/tasks/TASK-1102.task.md`(已落) +- `artifacts/status/TASK-1102.status.json`(已落,待狀態推進) +- `artifacts/research/TASK-1102.research.md`(已落;resolved policy 於 `planned` 狀態強制要求 research artifact,即使任務不涉外部未知) +- `artifacts/plans/TASK-1102.plan.md`(本檔) +- `artifacts/code/TASK-1102.code.md`(待 coding 階段落) +- `artifacts/test/TASK-1102.test.md`(docs-spec adapter,NOT_APPLICABLE_BY_ADAPTER,仍落最小檔) +- `artifacts/verify/TASK-1102.verify.md`(待 verify 階段落) + +## Proposed Changes + +### CP-1: `CLAUDE.md` 新增段落 + +於「### 派發 Implementation」(pointer 至 `docs/sop/dispatch_implementation.md`)與「### 完成任務」之間,新增: + +``` +### Dispatch Write-Scope 執行(`-AutoRestore`) + +是否讓 write-scope 違規在 dispatch 當下就被真正擋下,由協調者(Claude)決定,不是 Codex / Gemini 自己能決定: + +- `Invoke-CodexAgent.ps1` / `Invoke-GeminiAgent.ps1` 的 `-AutoRestore` 預設 `$false`:wrapper 僅偵測 write-scope 違規並印出,dispatch 仍以 exit 0 結束(detect-only,不會自動還原)。 +- 若需要違規被真正擋下(stash-based restore、exit 2),Claude 呼叫 wrapper 時必須顯式傳遞 `-AutoRestore`。 +- 未顯式傳遞時,CODEX.md / GEMINI.md 中「write scope 違規」的處置敘述僅止於偵測與事後記錄(decision artifact、人工 review),不代表該次 dispatch 已被自動擋下。 +``` + +### CP-2: `GEMINI.md:46` 改寫 + +原文: +``` +- 違者:dispatch 視為失敗;Claude 將以 `git checkout HEAD --` 還原並要求 redo +``` + +改為(與 `CODEX.md:75` 之自我回報義務語氣對齊,機制交由下方 47-48 行既有說明承載,不重複): +``` +- 違者:Claude 須審視 dispatch 輸出、依情況要求 redo;是否已於偵測當下被 wrapper 自動擋下(stash-based restore、exit 2)或僅止於偵測(exit 0,留待 Claude 手動處置),取決於下列 `-AutoRestore` 是否顯式傳遞 +``` + +47-50 行既有 `-AutoRestore` 安全模式 / Lifecycle exclusion / dispatch prompt token-cost 說明字面不動。 + +### CP-3: template/ 鏡像 + +- `template/GEMINI.md`:套用同 CP-2 之改寫,確保與 root `GEMINI.md` SHA-256 全等(EXACT_SYNC_FILES 強制)。 +- `template/CLAUDE.md`:套用同 CP-1 之新增段落;套用後人工 `diff CLAUDE.md template/CLAUDE.md` 確認差異僅剩既有 1 行(downstream terminal repo 專屬句),不得誤刪該句。 + +### CP-4(不變更,僅記錄查證) + +`CODEX.md` 經 task §Background 查證已合規(`-AutoRestore` 條件說明已於 75-78 行完整;「違者:立 decision artifact」為自我回報義務,本就應維持無條件)。本 plan 不對 `CODEX.md` 做任何修改;此為刻意排除,非遺漏。 + +## Risks + +R1 +- Risk: `GEMINI.md:46` 改寫時誤動或誤刪 47-50 行既有文字,導致 `prompt_regression_cases.json` PR-027 之 `must_contain_all`/`all_of_any` 字面(`Write Scope Discipline`、`Invoke-GeminiAgent.ps1 -AllowedPaths`、`AutoRestore`)遺失 +- Trigger: Edit 時 old_string/new_string 範圍框選過大,波及 47-48 行既有 `-AutoRestore` 安全模式說明 +- Detection: `python artifacts/scripts/prompt_regression_validator.py --root .` 報 PR-027 missing literals +- Mitigation: Edit 僅鎖定第 46 行單一 bullet 之精確字串替換,不觸碰前後行;改寫後立即跑 prompt_regression_validator 確認 PR-027 仍 PASS +- Severity: blocking + +R2 +- Risk: `template/GEMINI.md` 鏡像時 SHA-256 與 root 不符(漏改、多改或換行符差異),導致 `guard_contract_validator.py`(EXACT_SYNC_FILES)FAIL +- Trigger: 手動複製鏡像時字元或換行不完全一致 +- Detection: `python artifacts/scripts/guard_contract_validator.py --root .` 報 SHA-256 mismatch +- Mitigation: 對 GEMINI.md 使用與 root 完全相同之 Edit old_string/new_string 於 template/GEMINI.md 套用;套用後以 `Get-FileHash` 或 `sha256sum` 人工比對兩檔雜湊一致 +- Severity: blocking + +R3 +- Risk: `template/CLAUDE.md` 鏡像 CP-1 新增段落時,誤覆寫該檔既有專屬句(downstream terminal repo 之 1 行既知落差),導致 `SOURCE_REQUIRED_PHRASES["template/CLAUDE.md"]` 之 phrase check("不得再建立新的 `template/`"、"只維護 root 文件" 等)FAIL +- Trigger: 用整段覆寫而非精準插入,波及該檔既有結尾段落 +- Detection: `python artifacts/scripts/guard_contract_validator.py --root .` 報 CLAUDE.md 或 template/CLAUDE.md 缺少必要 phrase;或人工 diff 發現既有句消失 +- Mitigation: template/CLAUDE.md 之 Edit 僅於「### 派發 Implementation」與「### 完成任務」之間插入新段落(與 CP-1 精確相同字串),不觸碰檔案其餘部分;插入後 `diff CLAUDE.md template/CLAUDE.md` 人工確認差異僅為既有 1 行 + 本次新增段落 +- Severity: non-blocking + +R4 +- Risk: User 對「CODEX.md 不修改」之查證結論有異議(原始指示假設 CODEX.md 也含絕對敘述),導致本次 closure 範圍與 user 預期不符 +- Trigger: user 回顧本 task Background 之查證後,認為仍需對 CODEX.md 做對稱處理 +- Detection: user 於本次交付後之回饋 +- Mitigation: 已於 task §Background 與最終交付摘要中明確揭露此發現與理由,供 user 即時 redirect;若 user 要求變更,另立 decision 或 follow-up task 處理,不在本 task 內臆測擴大範圍 +- Severity: non-blocking + +## Validation Strategy + +- 順序:(a) CP-1/CP-2 root 檔改寫 → (b) CP-3 template/ 鏡像 + 人工 diff/hash 比對 → (c) `guard_contract_validator.py --root .` [OK] → (d) `guard_contract_validator.py --root . --check-readme` [OK] → (e) `guard_status_validator.py --task-id TASK-1102` [OK] → (f) `prompt_regression_validator.py --root .` 全數 PASS(含 PR-027)→ (g) `pytest artifacts/scripts/ -q` 確認 baseline 不退步。 +- 失敗回退:若 PR-027 FAIL,回滾 GEMINI.md 46 行改寫範圍,縮小為單行替換重試;若 SHA-256 mismatch,重新以相同字串套用 template/ 鏡像;若 CLAUDE.md phrase check FAIL,檢查 template/CLAUDE.md 既有專屬句是否被誤刪並復原。 + +## Verification Obligations + +- VO-1:AC-1..AC-9 皆於 verify artifact 逐條列「verified / reason_code」。 +- VO-2:`GEMINI.md` / `template/GEMINI.md` SHA-256 一致證據落 verify §Evidence。 +- VO-3:`template/CLAUDE.md` 人工 diff 結果(僅既有 1 行 + 新增段落)落 verify §Evidence。 +- VO-4:4 條 validator 之 `[OK]` / PASS 輸出落 verify §Evidence。 +- VO-5:本 task 為 docs-spec adapter,test 段標記 NOT_APPLICABLE_BY_ADAPTER;Build Guarantee 段寫 `None (no .csproj or code modified)`。 + +## Out of Scope + +- 與 task §Out of Scope 相同;不重複列。 + +## Ready For Coding + +yes diff --git a/artifacts/plans/TASK-1103.plan.md b/artifacts/plans/TASK-1103.plan.md new file mode 100644 index 0000000..934bf3a --- /dev/null +++ b/artifacts/plans/TASK-1103.plan.md @@ -0,0 +1,97 @@ +# Plan: TASK-1103 + +## Metadata +- Task ID: TASK-1103 +- Artifact Type: plan +- Owner: Claude +- Status: ready +- Last Updated: 2026-07-07T10:20:00+08:00 + +## Scope + +在 `docs/premortem_rules.md` 新增 §12「獨立 Premortem 質疑(高風險 plan)」,定義:符合 4 類高風險條件之 plan,於 `planned → coding` 前,須由撰寫 R1-R4 者以外的獨立 agent 逐條質疑既有風險判斷,結果附掛於 plan `## Risks` 下的 `### Independent Premortem Challenge` 子區段。同步延伸 `CLAUDE.md` STOP 觸發點一句,納入此新條件。兩檔 template 鏡像同步,並於 `prompt_regression_cases.json` 新增對應 PR-* pin。不新增 artifact type、不新增 slash command、不新增自動化 guard 強制。 + +## Files Likely Affected + +- `docs/premortem_rules.md`(新增 §12) +- `template/docs/premortem_rules.md`(鏡像,EXACT_SYNC) +- `CLAUDE.md`(STOP 觸發點第 3 節,延伸既有 premortem 一句) +- `template/CLAUDE.md`(鏡像,phrase-based,人工 diff 確認僅既有 1 行落差 + 本次新增) +- `artifacts/scripts/drills/prompt_regression_cases.json`(新增 1 條 PR-036) +- `template/artifacts/scripts/drills/prompt_regression_cases.json`(鏡像,EXACT_SYNC) +- `.well-known/release-manifest.json`(若因上述 template/ 檔案變更過期,需 regen;沿用 TASK-1102 已驗證過的處理路徑) + +## Proposed Changes + +1. `docs/premortem_rules.md` 新增 §12,內容涵蓋: + - 背景:現行 premortem 為撰寫者自審,validator 僅做格式/用語 lint,不檢查風險判斷實質正確性。 + - 適用範圍:security fix / upstream PR / 跨模組或跨 repo 修改 / 不熟悉框架版本環境,四類命中任一即適用(刻意不納入「無法 100% 確認變更影響範圍」,避免範圍稀釋)。 + - 獨立性要求:質疑者不得與撰寫 R1-R4 的 agent 共用同一對話 context/session;可用 Agent tool 開新 subagent,或派給 Gemini / Codex 等不同 CLI;找不到可用獨立 agent 時須在 plan 明記原因並回報 blocked。 + - 質疑內容最小集合:逐條檢查 R1-R4 之 Detection 是否真的可觸發、是否有遺漏的失敗模式;沿用 §9 禁止語句清單,不得以空話回覆。 + - 輸出位置:plan `## Risks` 下新增 `### Independent Premortem Challenge` 子區段;分歧重大時另立 decision artifact。 + - 與既有機制的分工邊界:Council Reviewer 作用於 code diff 產出之後;RACI Auditor/Architecture Synthesizer 為週期性批次審查;本節作用於 plan 階段、逐 task 觸發,三者階段與頻率不重疊。 + - 明示現況:本節僅定義慣例,不由 `guard_status_validator.py` 自動強制。 +2. `CLAUDE.md` 第 3 節 STOP 觸發點,將現有「❌ Premortem 缺失或 R1-R4 不完整(見 docs/premortem_rules.md)」延伸為同時涵蓋「高風險 plan 未完成獨立質疑」,並指向 `docs/premortem_rules.md`(含 §12)。 +3. `template/docs/premortem_rules.md`、`template/CLAUDE.md` 同步鏡像。 +4. `artifacts/scripts/drills/prompt_regression_cases.json` 新增 `PR-036`,pin `docs/premortem_rules.md` 新增之 §12 標題/獨立性要求字面,以及 `CLAUDE.md` 新句字面;`template/artifacts/scripts/drills/prompt_regression_cases.json` 同步鏡像。 +5. 執行 validator chain(`guard_contract_validator.py` ×2、`guard_status_validator.py`、`prompt_regression_validator.py`、`pytest`),若 pytest 因 manifest 過期 fail,以 `snapshot_manifest.py generate` regen 後重跑確認回綠。 + +## Risks + +R1 +- Risk: 新機制被當成橡皮圖章通過——獨立質疑者只給「已確認、無問題」之類空話,未真的逐條質疑 +- Trigger: 派發 prompt 若只寫「請確認 premortem 沒問題」而非要求逐條具體回覆 +- Detection: 質疑輸出若沒有逐條對應 R1-R4 個別具體理由,或使用 §9 禁止語句清單所列之空話類型(抽象、無法觀察、無法止血的用語) +- Mitigation: §12 明文要求逐條回覆格式(每條 R 編號對應一段具體理由),並聲明 §9 禁止語句清單同樣適用於本輸出 +- Severity: blocking + +R2 +- Risk: 「獨立」定義不清,導致同一 agent 換個殼子審查自己寫的東西(左手審右手),質疑形同虛設 +- Trigger: 撰寫 plan 的 agent 在同一輪對話回應內直接自問自答完成質疑,未真正切換 context +- Detection: dispatch 記錄或 plan 撰寫時間戳顯示質疑內容與 R1-R4 撰寫發生在同一次 agent 呼叫/同一對話輪次內 +- Mitigation: §12 明確要求質疑者不得與撰寫 R1-R4 的 agent 共用同一對話 context/session,須透過 Agent tool 開新 subagent 或派給不同 CLI;找不到可用獨立 agent 時必須明記原因並回報 blocked,不得逕自略過 +- Severity: blocking + +R3 +- Risk: 新增這道 gate 造成每個高風險任務的派發成本與延遲增加,高風險任務吞吐下降 +- Trigger: 高風險任務數量偏多、且每次都需額外一輪獨立 agent 派發時 +- Detection: 後續 PROCESS_LEDGER 或 Sprint Review 觀察到高風險任務平均耗時明顯上升 +- Mitigation: 若觀察到吞吐顯著下降,於 decision artifact 記錄並收斂觸發條件(例如限縮到 blocking risk ≥ 2 條之 plan),本任務先以現行 4 類條件上線,留待實際數據調整 +- Severity: non-blocking + +R4 +- Risk: 與既有 Council Reviewer / RACI Auditor 職責邊界混淆,未來維護者不清楚該用哪個機制 +- Trigger: 未來任務同時符合「高風險 plan」與「已有 code diff」兩種情境,或恰逢批次審查週期 +- Detection: 未來 task 之 decision artifact 或 PROCESS_LEDGER 出現「不確定該用 codex-review 還是 premortem challenge」之類混淆記錄 +- Mitigation: §12 明確界定三者的階段與頻率邊界(plan 階段/逐 task vs. code diff 之後 vs. 週期性批次),並在 CLAUDE.md 常用查詢表新增指向 §12 的一行,降低混淆機率 +- Severity: non-blocking + +## 本任務自身不觸發 §12 機制之說明 + +本任務屬於 council-forge repo 內部 docs 治理文字修正,不屬於 security fix、upstream PR、跨模組或跨 repo 修改、不熟悉框架版本環境 任一類別(純本 repo 內單一文件語意擴充,範圍與影響皆於 Research 階段查證清楚),因此不觸發本任務新定義的獨立質疑機制。此為刻意設計,避免「定義規則的任務要求自己先套用規則」之自我遞迴(bootstrap)疑慮被誤讀為遺漏;已於 task artifact Constraints 段與此處雙重記錄。 + +## Validation Strategy + +- `python artifacts/scripts/guard_contract_validator.py --root .` 與 `--root . --check-readme` 皆須 `[OK]`。 +- `python artifacts/scripts/guard_status_validator.py --task-id TASK-1103` 須 `[OK]`(於 planned / coding / verifying 各跑一次)。 +- `python artifacts/scripts/prompt_regression_validator.py --root .` 全數 PR-*(含新增 PR-036)須 PASS。 +- `diff docs/premortem_rules.md template/docs/premortem_rules.md` 與 `diff artifacts/scripts/drills/prompt_regression_cases.json template/artifacts/scripts/drills/prompt_regression_cases.json` 須無輸出(SHA-256 全等);`diff CLAUDE.md template/CLAUDE.md` 人工核對僅既有 1 行落差 + 本次新增內容。 +- `python -m pytest artifacts/scripts/ -q` 須達到或超過既有 baseline(2037 passed, 2 skipped,見 TASK-1102 verify);若因 manifest 過期出現 fail,以 `snapshot_manifest.py generate` regen 後重跑確認回綠。 + +## Verification Obligations + +- verify artifact 須逐條核對 AC-1~AC-9,並附上 validator chain 實際輸出、mirror match 證據、pytest 前後對照(若觸發 manifest regen)。 +- `status.open_verification_debts` 應為空陣列;本任務不留待後續批次處理之驗證缺口。 +- Build Guarantee 段沿用 TASK-1102 慣例,記載「None(docs-spec,無 production code)」,並註記待 user-driven commit 後回補 commit hash。 + +## Out of Scope + +- 修改 `guard_status_validator.py` 新增自動化強制檢查獨立質疑是否存在。 +- 修改 `docs/schemas/artifact-spec-plan.md` 或 `docs/artifact_schema.md`。 +- 修改 `docs/workflow_state_machine.md`。 +- 新增獨立 slash command 或新 `docs/sop/` 檔案。 +- 回溯套用本機制到既有已完成任務的 plan。 + +## Ready For Coding + +yes diff --git a/artifacts/plans/TASK-1104.plan.md b/artifacts/plans/TASK-1104.plan.md new file mode 100644 index 0000000..88150b4 --- /dev/null +++ b/artifacts/plans/TASK-1104.plan.md @@ -0,0 +1,116 @@ +# Plan: TASK-1104 + +## Metadata +- Task ID: TASK-1104 +- Artifact Type: plan +- Owner: Claude +- Status: ready +- Last Updated: 2026-07-07T15:30:00+08:00 + +## Scope + +建立規則生命週期盤點循環的 SOP 與盤點輸入檔,並掛載到既有觸發軌與文件索引: + +1. 新增 `docs/sop/rule_lifecycle_audit.md`(≤150 行):循環三步(Occam pass → Chesterton gate → 記錄)、四值裁決(`retire`/`relax`/`keep`/`open`)判準與記錄欄位、觸發條款(N=10 ledger 同軌 + 手動)、自我引用條款與退路。 +2. 新增 `artifacts/improvement/RELAXATION_LOG.md`(root 版含 4 筆既有案例)與 `template/artifacts/improvement/RELAXATION_LOG.md`(泛化 skeleton)。 +3. 掛載:`AGENTS.md` 文件模組表加一列;`artifacts/improvement/PROCESS_LEDGER.md` §維護規則加同軌一句;`docs/templates/architecture-synthesizer/TEMPLATE.md` §Trigger 加 cross-ref。 +4. 同步義務:`EXACT_SYNC_FILES` 新增新 SOP 條目(root + template 兩份 validator 同字面);所有 EXACT_SYNC 觸及檔 root/template 鏡像;`prompt_regression_cases.json` 新增 1 條 PR-* pin;必要時 release-manifest regen。 + +## Files Likely Affected + +- `docs/sop/rule_lifecycle_audit.md`(新增) +- `template/docs/sop/rule_lifecycle_audit.md`(新增,EXACT_SYNC 鏡像) +- `artifacts/improvement/RELAXATION_LOG.md`(新增) +- `template/artifacts/improvement/RELAXATION_LOG.md`(新增,泛化 skeleton) +- `AGENTS.md` + `template/AGENTS.md`(文件模組表加一列) +- `artifacts/improvement/PROCESS_LEDGER.md` + `template/artifacts/improvement/PROCESS_LEDGER.md`(§維護規則加一句) +- `docs/templates/architecture-synthesizer/TEMPLATE.md` + `template/docs/templates/architecture-synthesizer/TEMPLATE.md`(§Trigger 加 cross-ref) +- `artifacts/scripts/guard_contract_validator.py` + `template/artifacts/scripts/guard_contract_validator.py`(EXACT_SYNC_FILES 加 1 條目) +- `artifacts/scripts/drills/prompt_regression_cases.json` + `template/artifacts/scripts/drills/prompt_regression_cases.json`(加 1 條 PR-* pin) +- `artifacts/scripts/test_guard_contract_validator.py` + template 鏡像(僅當該檔對 EXACT_SYNC 清單有字面 pin 時,見 R3) +- `.well-known/release-manifest.json`(僅當 template/ 變更觸發過期時 regen) +- `artifacts/code/TASK-1104.code.md`、`artifacts/verify/TASK-1104.verify.md`、`artifacts/status/TASK-1104.status.json`(lifecycle artifacts) + +## Proposed Changes + +1.1 撰寫 `docs/sop/rule_lifecycle_audit.md`,章節:目的與適用範圍(guard 規則/validator pattern/templates/wrapper flags/workflow 條款);觸發(cross-ref architecture-synthesizer TEMPLATE 之 N=10 定義 + 手動);Step 1 Occam pass(輸入清單:template dispatch 統計、RELAXATION_LOG、red_team_backlog 未動工項、Guard Exception 出現頻率;沿用 `real_dispatch_count` 手工盤點慣例);Step 2 Chesterton gate(三分支:事故驅動→`keep`/前提消失→`retire`或`relax`/查無 provenance→`open` 不拆不加碼,引 scope-drift Layer-1 先例);Step 3 記錄(append-only 表格欄位:規則+路徑/裁決四值/provenance 出處/一句話理由/復活路徑);自我引用條款(本 SOP 列入盤點對象;N=10 軌長期未觸發時下輪檢討改綁 unified audit)。 +1.2 建立 `artifacts/improvement/RELAXATION_LOG.md`:4 筆案例(CITATION_PATTERN、RESEARCH_SOURCES_ENTRY_PATTERN、generic→docs-spec adapter、available_artifacts mismatch),欄位=日期/規則位置/前後摘要/觸發 task/根因分類;in-repo citation 以 Grep 實查,查無者標 `provenance: unrecorded`;內嵌「累積 ≥3 → architect review」條款;規則敘述 cross-ref workflow-gates.md 不重複字面。 +1.3 建立 `template/artifacts/improvement/RELAXATION_LOG.md` 泛化 skeleton(欄位與條款同,案例區空表)。 +2.1 `AGENTS.md` 文件模組表新增 `docs/sop/rule_lifecycle_audit.md` 一列(用途/~Tokens/載入時機:Closure 或盤點觸發時);template 同字面。 +2.2 `PROCESS_LEDGER.md` §維護規則加一句:條目達 N=10 倍數時 architecture-synthesizer 與 rule lifecycle audit 同批觸發(cross-ref 新 SOP);template 版對應調整。 +2.3 `architecture-synthesizer/TEMPLATE.md` §Trigger 加一句 cross-ref(同批執行 rule lifecycle audit,見新 SOP);template 鏡像同動。 +3.1 `guard_contract_validator.py` EXACT_SYNC_FILES 依字母序插入 `"docs/sop/rule_lifecycle_audit.md"`;root 與 template 兩份同改後逐位元組相同。 +3.2 `prompt_regression_cases.json` 新增 1 條 PR-* pin:`must_contain_all` 錨定新 SOP 之四值裁決字面與 OPEN 條款關鍵句;雙副本同字面。 +4.1 驗證鏈:guard_contract_validator(含 --check-readme)→ guard_status_validator --task-id TASK-1104 → prompt_regression_validator → pytest baseline → SHA-256 逐對比對 → 必要時 snapshot_manifest.py generate。 + +## Risks + +R1 +- Risk: 新 SOP 內容膨脹成新治理負擔(超過 150 行、夾帶「須新增腳本/自動化 guard」要求),違反本任務的 Occam 初衷,防增生機制自身增生 +- Trigger: 實作者為求完整性補充自動化建議或超量細節時 +- Detection: 行數計數 > 150;grep SOP 全文出現「新增腳本」「自動化強制」等要求性字樣;AC-5 驗收 fail +- Mitigation: 驗收退回並要求刪減重寫;Out of Scope 已明文禁止新腳本與自動觸發,超出即攔 +- Severity: non-blocking + +R2 +- Risk: EXACT_SYNC 同步缺漏——新 SOP 或修改檔只改 root 忘 template(尤其 guard_contract_validator.py 兩份、AGENTS.md 兩份),guard fail 或依 repo 規則視為 workflow 變更未完成 +- Trigger: 實作時逐檔鏡像有遺漏,或 EXACT_SYNC_FILES 新條目只加入單份 validator +- Detection: `python artifacts/scripts/guard_contract_validator.py --root .` 報 sync mismatch;SHA-256 逐對比對 mismatch +- Mitigation: 驗收階段逐對跑 Get-FileHash 比對全部觸及之 EXACT_SYNC 檔;缺漏退回 Codex 補齊後重跑 validator +- Severity: blocking + +R3 +- Risk: 新增字面觸犯既有 PR-* 之 must_not_contain_any,或 test_guard_contract_validator.py 對 EXACT_SYNC_FILES 清單有 pin,導致 prompt_regression_validator 或 pytest fail +- Trigger: prompt_regression_validator 執行時比對到衝突字面;pytest 執行到清單 pin 之 assertion +- Detection: prompt_regression_validator 輸出 FAIL 條目;`python -m pytest artifacts/scripts/ -q` 出現 failed +- Mitigation: 調整 SOP 措辭避開既有 pin;若 test 檔確有清單 pin,同步更新該 test(EXACT_SYNC 成員,雙份同改)並在 code artifact 之 Files Changed 與 Mapping To Plan 明記 +- Severity: blocking + +R4 +- Risk: N=10 觸發軌實際失效——PROCESS_LEDGER 成長率僅約 2-3 筆/月,循環可能 3-5 個月才觸發一次,制度空轉形同虛設 +- Trigger: ledger 條目成長率持續低於 2 筆/月且無人手動發起 +- Detection: 下次 unified audit 時檢視新 SOP 之退場記錄表為空、且距上輪觸發超過一個季度 +- Mitigation: SOP 內建手動觸發路徑與退路條款(長期未觸發時下輪檢討改綁 unified audit);此為文件層退路,本次不加程式 +- Severity: non-blocking + +R5 +- Risk: RELAXATION_LOG 與 workflow-gates.md 對同一放寬案例敘述重複或矛盾,未來讀者無所適從、雙處維護漂移 +- Trigger: 實作者直接複製 workflow-gates.md 段落進 log,或在 log 內改寫規則敘述 +- Detection: 兩檔 diff 出現相同段落字面;AC-7 人工抽查 fail +- Mitigation: log 限記事實欄位,規則敘述一律以 cross-ref 指向 workflow-gates.md;驗收發現重複即退回改寫 +- Severity: non-blocking + +### Independent Premortem Challenge + +不適用。本任務不命中 `docs/premortem_rules.md` §12 之四項適用條件(非 security fix、非 upstream PR、非跨模組跨 repo——純本 repo docs 治理變更,`.py` 僅動字串清單、非邏輯——非不熟悉框架版本環境),依 TASK-1103 同型先例明示不觸發,避免被誤讀為遺漏。 + +## Validation Strategy + +- 結構驗證:guard_contract_validator(`--root .` 與 `--root . --check-readme`)、guard_status_validator(`--task-id TASK-1104`)、prompt_regression_validator 全鏈 `[OK]`/PASS。 +- 內容驗證:AC-2~AC-7 逐條 grep 關鍵字面(四值裁決、OPEN 條款、N=10 cross-ref、≥3 升級條款)+ 行數計數 + 兩檔重複字面抽查。 +- 同步驗證:所有觸及之 EXACT_SYNC 檔 root/template SHA-256 逐對比對全等;非 EXACT_SYNC 鏡像檔(PROCESS_LEDGER、architecture-synthesizer TEMPLATE、RELAXATION_LOG skeleton)人工 diff 確認語義一致。 +- 回歸驗證:pytest 通過數 ≥ 既有 baseline;manifest 過期時 regen 後 release_gate 相關檢查不退化。 + +## Verification Obligations + +- verify artifact 依 docs-spec adapter 撰寫:test 段 `NOT_APPLICABLE_BY_ADAPTER`;Build Guarantee 以 validator chain 輸出 + commit hash 承載。 +- AC-1~AC-14 逐條 evidence 記入 verify artifact 之 Acceptance Criteria Checklist。 +- 觸及 EXACT_SYNC 敏感集:closure 於 dirty worktree 時由 live check 承載 Files Changed 驗證,verify artifact 明記此路徑;若 closure 前已 commit(clean task),code artifact 依 CHG-012 補 `## Diff Evidence`(commit-range,40 字元 SHA pinning)。 +- 無 deferred debts 預期;若 available_artifacts mismatch 案例 provenance 查無,於 RELAXATION_LOG 標 `provenance: unrecorded` 即為結清(誠實記錄,非 debt)。 + +## Routing + +- Task Type: implementation(docs 治理文字 + 字串清單);Risk Score: 2(write scope 廣但全為文件與字串、無邏輯、無外部依賴、無 secrets);Context Cost: M(約 10-13 檔含鏡像)。 +- 依 routing matrix「跨檔 workflow docs → Codex」與「context cost >= M → Codex」:**dispatch Codex 實作**,Claude 驗收與整合。 +- Research 段 routing override:內容為純 repo 內部事實查證(read-only explore 已完成、逐條可 Grep 覆核),無外部資料需求,由 Claude 直寫 research artifact,免去 Gemini dispatch 之 token 成本與 Sources fabrication 面(見 memory:Gemini Sources fabrication 前科)。 + +## Out of Scope + +- 修改任何 validator 邏輯(EXACT_SYNC_FILES 字串清單新增除外);新增腳本、自動觸發、slash command、artifact type。 +- 執行第一輪實際盤點(制度建立與首輪執行分離)。 +- 回溯改寫既有 decision artifacts 或已歸檔 templates。 +- `docs/security_cadence.md` 與 GitHub Actions workflows。 + +## Ready For Coding + +yes diff --git a/artifacts/plans/TASK-1105.plan.md b/artifacts/plans/TASK-1105.plan.md new file mode 100644 index 0000000..fe0367d --- /dev/null +++ b/artifacts/plans/TASK-1105.plan.md @@ -0,0 +1,109 @@ +# Plan: TASK-1105 + +## Metadata +- Task ID: TASK-1105 +- Artifact Type: plan +- Owner: Claude +- Status: ready +- Last Updated: 2026-07-07T18:40:00+08:00 + +## Scope + +依 research 定案之根因(5.1 於 CP65001 console 之 native pipe BOM + fake exe python cp950 解碼吞字)與 user 裁決(採 (c) 主修 + 執行慣例文件化;(b) 明確不採),實作: + +1. **(c) wrapper 根治**:`Invoke-CodexAgent.ps1` 與 `Invoke-GeminiAgent.ps1` 於 stdin pipe 前顯式設定 `$OutputEncoding = [System.Text.UTF8Encoding]::new($false)`,消除 5.1 語境 BOM 與 ASCII mangling;不改變 TASK-1062 stdin pipe 語意。 +2. **(c-2) 測試 harness 去 locale 依賴**:`conftest.py` fake script 之 stdin 讀取改 `sys.stdin.buffer.read().decode('utf-8')`,任何 locale 下解碼一致。 +3. **執行慣例文件化**:`.github/memory-bank/project-facts.md` 記載「完整 pytest baseline 應於 Git Bash 語境執行(gpg/bash 覆蓋完整);PowerShell 語境天然缺 gpg/bash 屬預期 19 skip,非退化」。 +4. 鏡像同步:兩 wrapper 與 conftest.py 之 `template/` 對應檔(三者皆已確認存在 template 鏡像;conftest.py 為 EXACT_SYNC 成員須逐位元組同)。 + +TASK-1104 verify 之「環境漂移」誤判更正(§Post-Closure Findings append)由 Claude 於 closure 階段親自執行,不在 Codex write scope。 + +## Files Likely Affected + +- `artifacts/scripts/Invoke-CodexAgent.ps1` + `template/artifacts/scripts/Invoke-CodexAgent.ps1` +- `artifacts/scripts/Invoke-GeminiAgent.ps1` + `template/artifacts/scripts/Invoke-GeminiAgent.ps1` +- `artifacts/scripts/conftest.py` + `template/artifacts/scripts/conftest.py`(EXACT_SYNC) +- `.github/memory-bank/project-facts.md` + `template/.github/memory-bank/project-facts.md`(template 鏡像已實查存在,需同步) +- `artifacts/verify/TASK-1104.verify.md`(closure 階段 Claude 之 Post-Closure Findings append + 內嵌 literal U+FEFF 勘誤——即全套 pytest 唯一殘餘 fail 之根除,見 §Scope 末段與 §Verification Obligations) +- `.well-known/release-manifest.json`(僅當 template/ 變更觸發過期時 regen) +- `artifacts/code/TASK-1105.code.md`、`artifacts/test/TASK-1105.test.md`、`artifacts/verify/TASK-1105.verify.md`、`artifacts/status/TASK-1105.status.json`(lifecycle artifacts) + +## Proposed Changes + +1.1 兩 wrapper 於 `$useStdinPipe` pipe 語句(Gemini 側 `Invoke-GeminiAgent.ps1:340`、Codex 側對應位置)所在函式/迴圈前,設定 `$OutputEncoding = [System.Text.UTF8Encoding]::new($false)`,附一行註解記 TASK-1105 與根因(5.1 CP65001 console BOM / ASCII mangling);兩 wrapper 同形。 +1.2 不還原 `$OutputEncoding`(wrapper 為獨立行程,process 結束即消failed;若實作時發現 wrapper 內其他管道讀取受影響,改為僅包住 pipe 語句之最小 scope 並記錄)。 +2.1 `conftest.py` `_write_fake_exe` 生成之 fake script:`stdin_data = sys.stdin.read()` 改為以 `sys.stdin.buffer.read().decode('utf-8')` 讀取(保留 isatty 防護與 Exception fallback 結構)。 +3.1 `.github/memory-bank/project-facts.md` 新增一小節:pytest 執行語境慣例(bash 語境 = 完整 baseline 2 skip;PowerShell 語境 = 19 skip 屬預期),cross-ref `artifacts/research/TASK-1105.research.md`。 +4.1 驗證鏈:PowerShell 語境 pytest 全跑(預期 0 failed、19 skipped)+ bash 語境 pytest 全跑(預期 0 failed、2 skipped)+ guard_contract_validator(--root . 與 --check-readme)+ guard_status_validator --task-id TASK-1105 + prompt_regression_validator + 必要時 manifest regen。 + +## Risks + +R1 +- Risk: `$OutputEncoding` 設定位置的 scope 不對(如設在 param block 前被 5.1 語法差異影響、或設在 retry 迴圈外被後續程式改寫),5.1 語境下 pipe 時未生效,BOM 依舊 +- Trigger: 修改後於 PowerShell 語境(CP65001 console)重跑 4 個 stdin 測試 +- Detection: pytest 該 4 測試仍 fail;或 manual_repro.py 重跑 x_count 仍 99 +- Mitigation: 將設定移至緊鄰 pipe 語句前重測;以 manual_repro.py 做位元組層確認後再跑全套 +- Severity: non-blocking + +R2 +- Risk: conftest fake script 改 UTF-8 顯式解碼後,其他依賴既有 locale 解碼行為的測試(或 fake exe 消費者)出現新 fail +- Trigger: pytest 全跑出現 4 個 BOM 測試以外的新 failed 項 +- Detection: PowerShell 與 bash 兩語境 pytest 結果與 baseline(2016/19/4 與 2037/2/0)逐項 diff +- Mitigation: 回退 conftest 變更(保留 wrapper (c) 主修即可讓 4 測試轉綠),conftest 強化另立 task 處理 +- Severity: blocking + +R3 +- Risk: 鏡像同步缺漏——conftest.py 為 EXACT_SYNC 成員,兩 wrapper 有 template 鏡像但非 EXACT_SYNC(允許 placeholder 差異),漏改任一份即 guard fail 或 workflow 變更未完成 +- Trigger: guard_contract_validator 跑列,或人工 SHA-256 比對 +- Detection: validator 報 sync mismatch;wrapper 鏡像 diff 顯示修改只落單側 +- Mitigation: 逐對比對三組檔案;conftest 以 SHA-256 全等驗,wrapper 以 diff 確認修改 hunk 兩側同形 +- Severity: blocking + +R4 +- Risk: `$OutputEncoding` 全域設定改變 wrapper 內其他 native 輸出捕捉(`2>&1` 讀回 CLI stdout)的解碼行為,真實 dispatch 之輸出出現亂碼或 error pattern 比對失效 +- Trigger: 修改後首次真實 Codex/Gemini dispatch,或 wrapper 單元測試之 stdout 斷言 +- Detection: pytest wrapper 測試之 stdout/combined_output 斷言 fail;真實 dispatch 輸出含替換字元 +- Mitigation: `$OutputEncoding` 只影響「寫入 native stdin」方向,讀回方向由 `[Console]::OutputEncoding` 管——若測試證實有交叉影響,改為 pipe 語句前設定、語句後還原原值 +- Severity: non-blocking + +### Independent Premortem Challenge + +不適用。本任務不命中 `docs/premortem_rules.md` §12 四項條件(非 security fix、非 upstream PR、非跨 repo——wrapper/conftest/docs 皆本 repo scripts 治理、非不熟悉框架——PowerShell encoding 行為已於 research 以位元組層實證完整定案),依 TASK-1103/1104 先例明示不觸發。 + +## Validation Strategy + +- 位元組層:manual_repro.py 於 5.1 重跑,預期 stdin_len=101(無 BOM)、x_count=100、SUBSTRING True。 +- 測試層:PowerShell 語境 pytest 全跑 0 failed / 19 skipped;bash 語境全跑 0 failed / 2 skipped(回復 TASK-1103 baseline)。 +- 結構層:guard chain 全綠;conftest.py root/template SHA-256 全等;兩 wrapper 修改 hunk 雙側同形。 +- 4 個既有 stdin 測試之嚴格斷言(不加容錯)即為 (c) 之永久回歸守衛。 + +## Verification Obligations + +- verify artifact 依 generic adapter 撰寫;Build Guarantee 以兩語境 pytest 輸出 + validator chain + commit hash 承載。 +- AC-1~AC-6(見 task artifact)逐條 evidence;AC-5 採「修復併入本 task」分支。 +- Closure 時 Claude 親自 append TASK-1104 verify §Post-Closure Findings(更正環境漂移誤判,引 TASK-1105 research)。 + +## Routing + +- Task Type: implementation;Risk Score: 3(觸及 dispatch 關鍵路徑 wrapper + EXACT_SYNC conftest,但變更面小且測試覆蓋強);Context Cost: M(6-8 檔含鏡像)。 +- 依 routing matrix「risk >= 3 → Codex」:**dispatch Codex 實作**(credits 已 refill),Claude 驗收、closure 與 TASK-1104 verify append。 +- Research 已由 Claude 完成(本機環境取證非外部資料,routing override 理由同 TASK-1104 plan)。 + +## Out of Scope + +- 回退或改變 TASK-1062 stdin pipe 語意(threshold=0 恆走 stdin)。 +- (b) 測試斷言 BOM 容錯(user 已裁不採)。 +- (a) conftest 改優先 pwsh(不採:保留 5.1 相容性測試面)。 +- 把 `Git\usr\bin` 加入全域 PATH 或任何環境側變更。 +- Invoke-CodexReview.ps1(無 stdin prompt pipe,不在根因鏈上)。 + +## Post-Planning Deviation Record(2026-07-08) + +- 實作後 R1 之 Detection 路徑(manual_repro 位元組層確認)揭露 §Scope 第 1 項((c) wrapper 設 `$OutputEncoding`)之技術前提不成立:5.1 native pipe writer 直接以 console codepage 取編碼,`$OutputEncoding` / `[Console]::OutputEncoding` / global 變數皆不可控(A/B/C/E 對照實驗,見 research 2026-07-08 補充段)。 +- User 2026-07-08 裁決:移除 wrapper 全部 encoding 修改(Occam——對宣稱目的無效之代碼不留),wrapper 四檔最終 net-zero;修復收斂為單一機制:§Scope 第 2 項 conftest UTF-8 顯式解碼(原 c-2 次要強化升為主修)+ 第 3 項執行慣例文件化。 +- 4 個 stdin 測試之嚴格斷言於 conftest 修復後全綠(BOM 前綴在 substring 語意下無害且不再吞字);斷言未弱化,維持回歸守衛。 +- 本記錄即 routing 覆寫/偏差之 plan 內記載(per docs/orchestration.md §2.7)。 + +## Ready For Coding + +yes diff --git a/artifacts/plans/TASK-1106.plan.md b/artifacts/plans/TASK-1106.plan.md new file mode 100644 index 0000000..521211e --- /dev/null +++ b/artifacts/plans/TASK-1106.plan.md @@ -0,0 +1,102 @@ +# Plan: TASK-1106 + +## Metadata +- Task ID: TASK-1106 +- Artifact Type: plan +- Owner: Claude +- Status: ready +- Last Updated: 2026-07-08T13:10:00+08:00 + +## Scope + +以最輕形態顯性化三個實證支撐的治理名詞並更新介紹文件(全為既有檔內增量,無新檔、無 schema、無 gate、無腳本): + +1. `docs/orchestration.md` §2.8:lenses 表加 3 列 + Campbell's Law 拒絕記錄(2-3 行,OODA 先例形態)。 +2. `docs/sop/dispatch_implementation.md`:fallback-tier trust-but-verify 條文。 +3. `docs/sop/rule_lifecycle_audit.md`:McNamara 防呆句(Step 1)+ deviance 裁決條款(閾值 3,與 RELAXATION_LOG 對齊)。 +4. `README.md` + `README.zh-TW.md`:Two-Layer Governance 段補 lenses 指引敘述。 +5. PR-* 新增 1 條 pin;EXACT_SYNC 鏡像;manifest regen(如過期)。 + +## Files Likely Affected + +- `docs/orchestration.md` + `template/docs/orchestration.md`(EXACT_SYNC) +- `docs/sop/dispatch_implementation.md` + `template/docs/sop/dispatch_implementation.md`(EXACT_SYNC) +- `docs/sop/rule_lifecycle_audit.md` + `template/docs/sop/rule_lifecycle_audit.md`(EXACT_SYNC) +- `README.md`、`README.zh-TW.md`(README contract;template 側若有對應 README 依 --check-readme 判定) +- `artifacts/scripts/drills/prompt_regression_cases.json` + `template/artifacts/scripts/drills/prompt_regression_cases.json`(EXACT_SYNC) +- `.well-known/release-manifest.json`(僅當 template/ 變更觸發過期時 regen) +- `artifacts/code/TASK-1106.code.md`、`artifacts/test/TASK-1106.test.md`、`artifacts/verify/TASK-1106.verify.md`、`artifacts/status/TASK-1106.status.json`(lifecycle artifacts) + +## Proposed Changes + +1.1 lenses 表(`docs/orchestration.md:154` 表尾)加 3 列: + - **Goodhart's Law**(Goodhart 1975)|指標被優化而非目標(validator schema-pleasing)|RELAXATION_LOG 累積 ≥3 → architect review|`artifacts/improvement/RELAXATION_LOG.md` + - **Normalization of Deviance**(Vaughan 1996)|偏差被反覆接受而例行化(detect-and-accept 無限延續)|rule lifecycle audit 之同型違規連續接受 3 次強制裁決條款|`docs/sop/rule_lifecycle_audit.md` + - **Swiss Cheese Model**(Reason 1990)|單一事故穿透多層防禦之路徑分析|guard 疊層 + improvement artifact `Why Not Prevented` 之逐層穿透敘述慣例|`.github/memory-bank/workflow-gates.md` +1.2 OODA 拒絕段後加 Campbell's Law 記錄:與 Goodhart 同構(指標腐化之社會科學表述),依 OODA 先例採 Goodhart 不採 Campbell,二者不並存、不得引為翻案範本。 +2.1 `docs/sop/dispatch_implementation.md` 末段加條文:wrapper fallback tier(後位模型,如 mini)之產出預設不可信——驗收必須逐 tier 讀 dispatch log 分辨各 attempt 實際行為,關鍵宣稱以命令直驗;credits 中斷後之 tier 尤然(出處:TASK-1105 Bug-B3,見 memory known-bugs 與 `artifacts/code/TASK-1105.code.md` §Post-Dispatch Amendment)。 +3.1 `docs/sop/rule_lifecycle_audit.md` Step 1 末加:「使用數據只產生候選,不產生裁決(零使用不等於零價值——保險機制平時即零觸發);裁決一律過 Step 2 provenance。」 +3.2 同檔 Step 2 表後(或 Guardrails)加 deviance 條款:「同型 detect-only 違規(如 write-scope/RACI 警告)連續被人工接受達 3 次:當輪必須裁 `relax`(承認規則過嚴、修規則)或轉強制(如 dispatch 改傳 `-AutoRestore`),不得停留於 detect-and-accept。」 +4.1 `README.md` §Two-Layer Governance 段末加一小段(2-3 句英文):兩層之上另有 governance lenses(Boundary Objects/RACI/PDCA/TAO/Double-Loop/SECI/Goodhart/Normalization of Deviance/Swiss Cheese)作為觀察切面,不構成新分層,詳見 docs/orchestration.md §2.8。 +4.2 `README.zh-TW.md` 對應段同步(中文等價;若無對應段,於等價位置補入並記錄)。 +5.1 `prompt_regression_cases.json` 加 PR-038:must_contain_all pin `Goodhart's Law`、`Normalization of Deviance`、`Swiss Cheese Model`、Campbell 拒絕句關鍵字面(雙副本同字面)。 +5.2 驗證鏈:guard_contract ×2 → guard_status → prompt_regression → SHA-256 逐對 → bash 語境全套 pytest(per project-facts 慣例)→ 必要時 manifest regen。 + +## Risks + +R1 +- Risk: EXACT_SYNC 同步缺漏——三個 docs 檔 + regression json 各兩份,任一單側修改即 contract fail 或 workflow 變更未完成 +- Trigger: 逐檔鏡像時遺漏,或 template 版含 placeholder 差異被誤以為可直接複製 +- Detection: `guard_contract_validator.py --root .` 報 mismatch;SHA-256 逐對比對 MISMATCH +- Mitigation: 每檔改完立即 Get-FileHash 比對;發現 placeholder 差異時逐 hunk 套用而非整檔覆蓋 +- Severity: blocking + +R2 +- Risk: README contract(--check-readme)或既有 PR-* 字面 pin 被新文字觸犯(README 段落結構被 validator 錨定、或新句撞 must_not_contain_any) +- Trigger: guard_contract --check-readme 或 prompt_regression_validator 跑列 +- Detection: validator 輸出 FAIL 條目與具體 pin ID +- Mitigation: 調整措辭避開 pin 字面;README 修改採段末追加不動既有句 +- Severity: blocking + +R3 +- Risk: lens 表列之「對應現有機制」指向本任務同批新增的 deviance 條款,若條款措辭與表列不一致形成懸空引用;或 SOP 行數逼近 150 上限 +- Trigger: 表列與 SOP 條款分兩次編輯時措辭漂移 +- Detection: 驗收時人工比對表列與條款字面;wc -l 檢查 +- Mitigation: 同一編輯批次完成表列與條款;行數超限時裁剪 SOP 敘述而非刪條款 +- Severity: non-blocking + +R4 +- Risk: README.zh-TW.md 無對應 Two-Layer Governance 段(結構與英文版漂移),補入位置誤判造成兩語言版敘述不對稱 +- Trigger: 實作時讀 zh-TW 版發現結構差異 +- Detection: 人工讀檔比對兩版結構 +- Mitigation: 於語義等價位置補入並於 code artifact 明記位置差異;不強行改動 zh-TW 版其他結構 +- Severity: non-blocking + +### Independent Premortem Challenge + +不適用。docs-only 治理文字增量,不命中 §12 四條件(非 security fix、非 upstream PR、非跨 repo、非不熟悉框架),同 TASK-1103/1104 先例。 + +## Validation Strategy + +- 內容:AC-2~AC-6 逐條 grep 關鍵字面(三名詞、Campbell 拒絕句、deviance 閾值 3、McNamara 句、README lenses 段)+ SOP 行數計數。 +- 結構:guard_contract ×2、guard_status、prompt_regression(含 PR-038)全綠;EXACT_SYNC 檔 SHA-256 逐對。 +- 回歸:bash 語境全套 pytest 0 failed 且 ≥ 2037 passed(per `.github/memory-bank/project-facts.md` 執行語境慣例)。 + +## Verification Obligations + +- verify artifact 依 docs-spec adapter;Build Guarantee 以 validator chain + pytest + commit hash 承載。 +- AC-1~AC-10 逐條 evidence 記入 checklist。 +- 表列與 deviance 條款之一致性(R3)於 verify 明記核對結果。 + +## Routing + +- Task Type: implementation(docs 治理文字);Risk Score: 2(純文字、無邏輯、blast radius 限文件與 pin);Context Cost: M(約 10 檔含鏡像)。 +- **Routing override:Claude 直寫**。理由:(a) docs-only 治理文字,TASK-1102/1103 已驗證同型路徑;(b) Codex credits 於 TASK-1105 dispatch 中段耗盡且未確認回充,再派發有高機率重演 fallback-tier 品質事故(Bug-B3);(c) 內容為 Claude 本 session 之評估結論,路徑引用密度高、fabrication 面大,直寫可消除轉述失真。per docs/orchestration.md §2.7 記錄於此。 + +## Out of Scope + +- improvement artifact schema 修改;「已隱性覆蓋」名詞之顯性化;Brooks/Ashby/Parkinson/Lindy;validator/wrapper/自動化變更;OBSIDIAN.md 與 BOOTSTRAP_PROMPT.md(無治理敘述錨點,不動)。 + +## Ready For Coding + +yes diff --git a/artifacts/plans/TASK-1107.plan.md b/artifacts/plans/TASK-1107.plan.md new file mode 100644 index 0000000..4323909 --- /dev/null +++ b/artifacts/plans/TASK-1107.plan.md @@ -0,0 +1,157 @@ +# Plan: TASK-1107 + +## Metadata +- Task ID: TASK-1107 +- Artifact Type: plan +- Owner: Claude +- Status: ready +- Last Updated: 2026-07-17T10:45:00+08:00 + +## Scope + +修復 ultrareview 對 PR #50 的兩條 CONFIRMED findings: + +1. `guard_status_validator.py` CHG-012 gate 之 `diff_evidence` exact-tuple 比對繞過漏洞(bug_002)。 +2. `docs/subagent_roles.md` 與 `docs/raci-matrix.md` 之 RACI 單一真源互指成環(bug_001)。 + +兩者皆為既有機制的精確修補,不變更 CHG-012 gate 的整體政策設計,不變更 RACI 表格內容本身。 + +## Files Likely Affected + +- `artifacts/scripts/guard_status_validator.py`(CHG-012 判斷式,`:2250` 附近) +- `artifacts/scripts/test_guard_status_validator_artifacts.py`(`TestCleanTaskDiffEvidenceCHG012` 新增測試) +- `docs/subagent_roles.md`(`:56` 附近 RACI 拆分宣告句) +- `template/artifacts/scripts/guard_status_validator.py`(EXACT_SYNC 鏡射) +- `template/artifacts/scripts/test_guard_status_validator_artifacts.py`(EXACT_SYNC 鏡射) +- `template/docs/subagent_roles.md`(EXACT_SYNC 鏡射) +- `docs/raci-matrix.md` / `template/docs/raci-matrix.md`(僅在需要語意收斂用詞時微調,非必然需要修改內容——現行文字方向已正確,本次修法只需 `subagent_roles.md` 一側對齊) +- `artifacts/status/TASK-1107.status.json`(lifecycle artifact,狀態轉移) +- `artifacts/plans/TASK-1107.plan.md`(本檔自身,Claude Post-Dispatch Amendment:移除 R3 範例文字中的字面 BOM) +- `artifacts/decisions/TASK-1107.decision.md`(Claude Post-Dispatch Amendment:AC-8 baseline exception + `.well-known/release-manifest.json` scope-drift waiver) +- `artifacts/improvement/TASK-1107.improvement.md`(Claude Post-Dispatch Amendment:Gate E,dispatch 併發衝突事故根因記錄) +- `.well-known/release-manifest.json`(Claude Post-Dispatch Amendment,經 `artifacts/decisions/TASK-1107.decision.md` `## Guard Exception` 顯式豁免:template 變更後之 snapshot 重生) +- `artifacts/tasks/TASK-1107.task.md`(lifecycle artifact,本檔之上游) +- `artifacts/research/TASK-1107.research.md`(lifecycle artifact) +- `artifacts/code/TASK-1107.code.md`(lifecycle artifact) +- `artifacts/test/TASK-1107.test.md`(lifecycle artifact) +- `artifacts/verify/TASK-1107.verify.md`(lifecycle artifact,新增) + +## Proposed Changes + +1. **guard_status_validator.py:2250** — 將 `if sensitive_hits and diff_evidence.lower() in ("", "none", "n/a"):` 改為重用既有結構化解析器(`parse_diff_evidence` + `DIFF_EVIDENCE_SUPPORTED_TYPES`,皆已存在於同檔案/`guard_helpers/parsers.py`),而非另立第二套字串啟發式: + ```python + evidence = parse_diff_evidence(code_text) + evidence_type = (evidence or {}).get("evidence type", "").strip().lower() + if sensitive_hits and evidence_type not in DIFF_EVIDENCE_SUPPORTED_TYPES: + ``` + (原提議的字串子句寫法 `de.startswith(("none", "n/a")) or "evidence type:" not in de` 經 §12 獨立質疑發現仍可被自由文字繞過——例如 `"No Evidence Type: applicable -- verified via manual code review instead of diff replay."`:此文字不以 `none`/`n/a` 開頭,且原始子字串比對中含有 `evidence type:` 字樣,會被誤判為「已提供證據」而放行;已用 Python 直接執行覆現此繞過。改採結構化解析後,`parse_key_value_section` 只接受以 `- Key: Value` bullet 起始的行,上述自由文字無法被解析出任何 key,`evidence_type` 落空字串、不在 `DIFF_EVIDENCE_SUPPORTED_TYPES` 內,正確被攔下;同一組實測亦確認兩種合法格式(`commit-range`/`github-pr`)依然通過。此作法同時符合 CLAUDE.md 3.1 奧坎剃刀——重用既有已驗證的解析器,不新增第二套判斷邏輯造成未來漂移。) +2. **test_guard_status_validator_artifacts.py** — 於 `TestCleanTaskDiffEvidenceCHG012` 類別(`:2840` 起)新增至少兩個 test method,沿用既有 `_tree` / `_chg012_errors` helper(不新建平行 fixture),分別覆蓋: + - `diff_evidence="None (this task was completed via alternate verification)"` 與至少一個全形 `None(...)` 變體,斷言被正確攔下。 + - R6 發現的自由文字繞過情境:`diff_evidence="No Evidence Type: applicable -- verified via manual code review instead of diff replay."`(非 bullet 格式但含 `evidence type:` 字樣),斷言 `_chg012_errors(...)` 回傳非空——此為結構化解析修法(而非字串啟發式)之關鍵回歸測試,缺此測試無法證明 R6 已解決。 +3. **docs/subagent_roles.md:56 附近**(連同 `## 2.` 標題文字一併檢視,見 R7)— 將現行句: + > RACI 與 agent capability 矩陣已拆分至 [docs/raci-matrix.md](raci-matrix.md)(原 `docs/subagent_roles.md` §2)。 + + 改為對齊 `docs/raci-matrix.md:3,7` 現行方向的句子,宣告本檔 §2(下表)即單一真源,`raci-matrix.md` 僅保留 §2.1 TAO Trace 表。同時檢視同一 `## 2.` 標題(現行含「角色總表(**索引**)」字樣,與 `:72-81` 已是完整表格本體矛盾——見 R7),視需要調整標題用詞使其不再暗示「本檔只是指向他處的索引」。確切措辭於 Coding 階段由 Codex 依現行 `raci-matrix.md:3` 句式撰寫,須經 Claude 驗收比對雙檔語意(含標題)是否仍一致(不互指成環)。 +4. **template/ 鏡射** — 1、2、3 三項變更完成後,立即同步至 `template/artifacts/scripts/guard_status_validator.py`、`template/artifacts/scripts/test_guard_status_validator_artifacts.py`、`template/docs/subagent_roles.md`,確保 SHA-256 逐位元組相同。 + +## Risks + +R1(經 §12 獨立質疑後改採結構化解析方案,原字串啟發式之風險已由設計消解,保留編號並記錄消解理由,不重編號以維持審計可追溯性) +- Risk: 原提議的字串啟發式(`de.startswith(("none","n/a")) or "evidence type:" not in de`)對未來新增第三種合法 Evidence Type 若不遵循固定起始格式會誤攔——但此風險已因改採 `parse_diff_evidence` + `DIFF_EVIDENCE_SUPPORTED_TYPES` 結構化解析(見 Proposed Changes 第 1 項修正版)而消解:新增合法類型只需將字串加入 `DIFF_EVIDENCE_SUPPORTED_TYPES` 集合,不依賴任何格式起始位置假設。 +- Trigger: N/A(風險前提已隨修法方案變更而不存在)。 +- Detection: N/A。 +- Mitigation: N/A(無需緩解;若未來確實新增第三種類型,僅需擴充 `DIFF_EVIDENCE_SUPPORTED_TYPES` 集合,屬既有機制的正常擴充路徑,不算本任務風險)。 +- Severity: non-blocking + +R2 +- Risk: 修法後 `TestCleanTaskDiffEvidenceCHG012` 既有 5 個 test method 中任一因 `.strip()` 或 `de` 變數重新賦值而產生非預期副作用(例如原本依賴 `diff_evidence`(未 strip 未 lower)之其他分支邏輯被誤動到)。 +- Trigger: `python -m pytest artifacts/scripts/test_guard_status_validator_artifacts.py::TestCleanTaskDiffEvidenceCHG012 -q` 修法後任一既有 test 由 pass 轉 fail。 +- Detection: pytest 輸出的 FAILED 清單;CI/本機執行結果直接可見。 +- Mitigation: 修法前先跑一次基線(記錄 pass 數與明細),修法後立即針對該測試類別單獨重跑比對;若有 regression,回退至修法前版本並重新檢視判斷式對既有測試 fixture 的影響範圍。 +- Severity: blocking + +R3 +- Risk: `guard_status_validator.py`、其三個 test 檔、`docs/subagent_roles.md` 為 `EXACT_SYNC_FILES` 成員,若 root 與 `template/` 鏡射修改後有任何字元差異(`guard_contract_validator.normalize_text()` 已將 CRLF/LF 正規化,故純換行符差異不會誤報;但 trailing whitespace 差異與 BOM(`U+FEFF`)——`.strip()` 不移除 BOM——仍會被正確判定為 drift,經 §12 獨立質疑以原始碼核實),`guard_contract_validator.py --root .` 會回報 drift,阻擋 PR 合併前置檢查。 +- Trigger: Codex 實作時只修改 root 版本、忘記同步 template/,或同步時手動輸入造成 trailing whitespace/BOM 差異(本 repo 已有 TASK-1105 之 BOM context-drift 先例可參照)。 +- Detection: `python artifacts/scripts/guard_contract_validator.py --root .` 執行後回報非 `[OK]`(列出 drift 檔案清單)。 +- Mitigation: 修改 root 版本後,直接以檔案內容複製方式同步至 template/(而非手動重打),並於驗收前執行 `guard_contract_validator.py --root .` 確認 `[OK]` 後才可標記 code artifact 完成。 +- Severity: blocking + +R4 +- Risk: `docs/subagent_roles.md:56` 之措辭調整若與 `docs/raci-matrix.md:3,7` 對齊時用詞不精確(例如遺漏「§2.1 TAO Trace 表」的限定範圍),可能造成新的語意落差(例如暗示 `raci-matrix.md` 整檔已無用,而非僅 §2 角色總表被取代),產生另一種形式的文件不一致;且經 §12 獨立質疑核實,`docs/subagent_roles.md:56` 的 `## 2.` 標題本身即帶有「角色總表(**索引**)」字樣,與該檔 `:72-81` 已是完整表格本體(非索引指向他處)自相矛盾——若只改宣告句、不動標題,修復後仍會留下「這只是個索引」的殘留誤導訊號(見下方 R7)。 +- Trigger: Codex 撰寫替代句時未逐字對照 `docs/raci-matrix.md:3` 現行句的限定範圍(「僅保留下列 §2.1 TAO Trace 必要程度表」),或未一併檢視 `:56` 標題文字。 +- Detection: Claude 驗收時人工比對兩檔新句與標題文字,確認雙向宣告的範圍邊界一致(`subagent_roles.md` 只宣告「本檔 §2 即單一真源」,不宣告 `raci-matrix.md` 全檔失效;`raci-matrix.md` 保留 §2.1 內容不變;`## 2.` 標題不再含暗示外部索引的「(索引)」字樣,除非改為明確不矛盾的用法)。 +- Mitigation: 若驗收時發現範圍邊界不精確或標題殘留誤導字樣,直接要求 Codex 修正措辭至與現行 `raci-matrix.md:3,7` 句式完全對齊、標題一併修正;不接受語意相近但範圍不精確的替代句。 +- Severity: non-blocking + +R6 +- Risk: 原提議的 CHG-012 修法(字串子句 `"evidence type:" not in de`)仍存在真實繞過路徑:一段**非結構化**自由文字,只要不以 `none`/`n/a` 開頭、但文字中任意位置含有 `evidence type:` 字樣(例如「No Evidence Type: applicable -- verified via manual code review instead of diff replay.」),會被原判斷式誤判為「已提供證據」而放行。已用 Python 直接執行覆現(見 Proposed Changes 第 1 項修正說明),確認 `parse_diff_evidence()` 對此類自由文字回傳空字典(因其 `parse_key_value_section` 只接受以 `- Key: Value` bullet 起始的行),故已改採該結構化解析器取代原字串啟發式,此風險已於 Proposed Changes 修正版中解決;本條保留以記錄 §12 獨立質疑之發現軌跡,供 verify artifact 與後續 code review 追溯「為何最終採結構化解析而非字串比對」。 +- Trigger: 若 Coding 階段 Codex 未依修正版 Proposed Changes 實作、而是照本 plan 初版(已作廢)的字串啟發式寫法實作,則此繞過路徑會重新出現。 +- Detection: 新增對抗性 unit test(見 Proposed Changes 第 2 項),斷言 `_chg012_errors(...)` 對 `"No Evidence Type: applicable -- verified via manual code review instead of diff replay."` 此類自由文字回傳非空;若 Codex 誤用字串啟發式版本,此測試會 FAIL,直接曝露繞過漏洞重新出現。 +- Mitigation: Coding 階段明確引用本 plan 修正版之 Proposed Changes 第 1 項程式碼片段(結構化解析版),不得改用字串啟發式版本;驗收時逐字比對 code artifact 之實際 diff 與本 plan 修正版程式碼片段是否一致。 +- Severity: blocking + +R7 +- Risk: `docs/subagent_roles.md:56` 之 `## 2.` 標題「角色總表(**索引**)」字樣與該檔 `:72-81` 已是完整表格本體(非索引)自相矛盾,若 Coding 階段只改第 58 行宣告句、不動標題,會留下與新宣告句矛盾的殘留訊號。 +- Trigger: Codex 實作時僅依 Proposed Changes 第 3 項字面(原僅指定改寫宣告句),未將標題文字一併納入檢視範圍。 +- Detection: Claude 驗收時(R4 Detection 已擴大範圍)grep `docs/subagent_roles.md` 之 `## 2.` 標題,確認不再含有暗示外部索引的「(索引)」字樣,除非改為明確不矛盾的用法。 +- Mitigation: 於 Coding dispatch prompt 中明確將標題文字的檢視/調整併入 Proposed Changes 第 3 項範圍,與宣告句一起改寫、一起驗收。 +- Severity: non-blocking + +R5 +- Risk: CHG-012 gate 屬 forward-only 設計(僅在 `to_state=="done"` 的 `write_transition` 呼叫時以 `enforce_clean_diff_evidence=True` 觸發,`validate_all`/`--task-id` 重驗證時 `flag=False` 不觸發),本次修法若不慎移除或改變此 `enforce_clean_diff_evidence` 參數的傳遞邏輯,會造成歷史已 `done` 任務在下次 `--task-id` 重驗證時意外被追溯攔下(違反既有「forward-only, no retroactive impact」設計承諾,見 `guard_status_validator.py:2244-2246` 註解)。 +- Trigger: 修改判斷式時誤將 `if state == "done" and enforce_clean_diff_evidence:` 外層條件一併改動,或誤刪 `flag` 參數傳遞。 +- Detection: 既有 `test_sensitive_no_evidence_revalidation_flag_false_passes` test(`test_guard_status_validator_artifacts.py:2929`)若由 pass 轉 fail,即代表 forward-only 承諾被破壞。 +- Mitigation: 本次修法只改動 `diff_evidence.lower() in (...)` 這一行內部判斷式,不觸碰其外層 `if state == "done" and enforce_clean_diff_evidence:` 條件;修法前後皆需確認 `test_sensitive_no_evidence_revalidation_flag_false_passes` 通過。 +- Severity: blocking + +### Independent Premortem Challenge + +執行者:獨立 subagent(general-purpose,經 Agent tool 開新 context 呼叫,非本 plan 撰寫 agent 之延續 session;agentId `a235f2cad05e6e4ef`)。適用理由:本任務涉及 `guard_status_validator.py` CHG-012 gate 邏輯修改,屬 §12「涉及安全性修補(security fix)」適用範圍。 + +質疑者以 Read/Grep/Bash 獨立核實程式碼(非照抄本 plan 敘述),並對關鍵判斷式做實際 Python 執行驗證。逐條判斷: + +- **R1(原字串啟發式版本)**:Detection 成立,但指出 Risk 敘述用詞不夠精確(「起始格式」應為「任意位置子字串」)。已因採納 R6 建議之結構化解析方案而使原風險前提消解,R1 已改寫為記錄消解理由(見上)。 +- **R2**:Detection 成立,逐一核對 `TestCleanTaskDiffEvidenceCHG012` 現有 5 個 test method 屬實。 +- **R3**:Detection 成立,但指出 `normalize_text()` 已正規化 CRLF/LF(換行符差異不會誤報 drift),真正風險點應為 trailing whitespace 與 BOM(`.strip()` 不移除 BOM,呼應 TASK-1105 BOM 先例)。已據此修正 R3 之 Trigger 敘述(見上)。 +- **R4**:Detection 成立但為純人工手段;額外查證 `validate_raci_hybrid_sync` 只解析 `docs/subagent_roles.md` 內以 `|` 開頭的表格列,不解析散文句,且核實 `## 2.` 標題本身帶有與內文矛盾的「(索引)」字樣。已據此擴大 R4 Detection 範圍並新增 R7(見上)。 +- **R5**:Detection 成立,已核實 `test_sensitive_no_evidence_revalidation_flag_false_passes`(`:2929`)的斷言邏輯確實能偵測到 `enforce_clean_diff_evidence` 外層條件被誤觸的破壞場景。 + +**新發現遺漏風險(已採納並整合進 `## Risks`)**: + +- **R6(blocking)**:原提議的字串啟發式修法本身仍存在一條可被實測驗證的繞過路徑(自由文字含 `evidence type:` 字樣但非結構化格式、不以 `none`/`n/a` 開頭)。質疑者以實際 Python 執行覆現此繞過,並提出改用既有 `parse_diff_evidence()` + `DIFF_EVIDENCE_SUPPORTED_TYPES` 結構化解析器之修正方案。Claude 已獨立重跑同一組驗證(見本 plan Proposed Changes 第 1 項之修正說明與行內程式碼),確認:(a) 原字串啟發式對繞過文字回傳 `False`(即放行,漏洞屬實);(b) 結構化解析方案對同一繞過文字正確攔下;(c) 兩種合法 Evidence Type 格式依然通過。**已採納此發現,Proposed Changes 第 1 項與 Risks R6 均已據此修正,非僅記錄未處理。** +- **R7(non-blocking)**:`docs/subagent_roles.md:56` 附近 `## 2.` 標題「角色總表(索引)」字樣與該檔已是完整表格本體之事實矛盾,若只改宣告句不動標題會留下殘留誤導訊號。**已採納,Proposed Changes 第 3 項與 R4 Detection 範圍均已擴大納入標題檢視。** + +**已查證但未發現新遺漏之面向**:全形字元(`.lower()` 不影響全形 unicode,攔截邏輯仍正確觸發)、markdown 粗體 `**Evidence Type:**`(子字串比對不受影響)、Hyrum's Law(重新 Grep 全庫確認除 `validate_raci_hybrid_sync` 外無其他腳本依賴 `docs/subagent_roles.md:56` 之精確字面,且該函式本身不解析此行散文句,故 bug_001 修法無 Hyrum's Law 風險)、EXACT_SYNC CRLF/BOM(見 R3 修正)。 + +**分歧處置**:本次獨立質疑之發現(R6 blocking、R7 non-blocking)已直接整合進 `## Risks` 與 `Proposed Changes`,未產生與質疑結果相牴觸、需另立 decision artifact 裁決的分歧——質疑者與撰寫者(Claude)對 R6 的技術判斷一致(皆以實測驗證同一組結論),故不觸發本文件 §12「若質疑結果導致風險判斷需要重大修改…改寫 decision artifact」之分支(此處「重大修改」指判斷分歧需裁決,而非「發現遺漏並直接採納修正」——本例已直接於 plan 內完成修正並記錄採納軌跡,無待裁決之分歧)。 + +## Validation Strategy + +1. 修法前於乾淨 worktree 執行 `python -m pytest artifacts/scripts -q`,記錄基線 passed/failed 數字。 +2. Codex 完成 `guard_status_validator.py` 判斷式修改(結構化解析版,見 Proposed Changes 第 1 項)與新增測試(含 R6 之自由文字繞過回歸測試)後,單獨執行 `python -m pytest artifacts/scripts/test_guard_status_validator_artifacts.py::TestCleanTaskDiffEvidenceCHG012 -v`,確認既有 5 個 test method 全通過、新增 test method(含 R6 回歸測試)亦通過。 +3. 執行完整 `python -m pytest artifacts/scripts -q`,確認 0 failed 且 passed 數較基線增加(因新增測試)。 +4. 執行 `python artifacts/scripts/guard_contract_validator.py --root .`,確認 `[OK]`(無 EXACT_SYNC drift)。 +5. 執行 `python artifacts/scripts/guard_status_validator.py --task-id TASK-1107`,確認各階段轉移 `[OK]`。 +6. Claude 人工比對 `docs/subagent_roles.md:56` 新句與 `docs/raci-matrix.md:3,7` 現行句,確認雙向宣告範圍邊界一致、無循環引用殘留。 +7. 修法完成並驗收通過後,`git add` 相關檔案、建立 commit,`git push` 至 `manifest-exec-unified-audit-2026-07-03`,以 `gh pr view 50` 確認 PR 自動反映新 commit。 + +## Verification Obligations + +- verify artifact 須逐條對照 AC-1 至 AC-10(見 `artifacts/tasks/TASK-1107.task.md`),Build Guarantee 須附修復後 commit hash(`git rev-parse HEAD`)。 +- verify artifact 須附 pytest 修法前後基線與最終數字對照(非僅「已測試通過」口頭陳述)。 +- verify artifact 須附 `guard_contract_validator.py --root .` 與 `guard_status_validator.py --task-id TASK-1107` 之實際輸出摘要。 +- 無 deferred verification debt;本 task 範圍內兩條 finding 修復後即應完全結清,不留待後續 task。 + +## Out of Scope + +- ultrareview report 中其他非本 task 列出的 finding。 +- `artifacts/code/TASK-1105.code.md:61` 之 fabricated 括注勘誤(見 task artifact Out of Scope 說明,留待首輪 audit 或獨立 task)。 +- CHG-012 gate 整體政策設計、Evidence Type 種類擴充。 +- `docs/subagent_roles.md` §2 角色列表內容本身之調整。 + +## Ready For Coding + +yes + +(§12 獨立 premortem 質疑已完成;質疑發現之 R6 blocking risk 已直接整合修正 Proposed Changes 並於本 plan 內解決——非帶著未解決的 blocking risk 進入 coding。R1-R7 全部風險現況:R1/R6 之風險前提已因採納結構化解析方案而消解或解決,R2/R3/R5 Detection 成立無需修改,R4/R7 為 non-blocking 且已擴大驗收範圍納入標題檢視。無需另立 decision artifact——無待裁決之分歧,僅為「發現遺漏並直接採納修正」。) diff --git a/artifacts/plans/TASK-1108.plan.md b/artifacts/plans/TASK-1108.plan.md new file mode 100644 index 0000000..0541b18 --- /dev/null +++ b/artifacts/plans/TASK-1108.plan.md @@ -0,0 +1,149 @@ +# Plan: TASK-1108 + +## Metadata +- Task ID: TASK-1108 +- Artifact Type: plan +- Owner: Claude +- Status: ready +- Last Updated: 2026-07-10T15:20:00+08:00 + +## Scope + +以最輕形態新增 6 個治理視角,全為既有檔內增量(無新檔、無強制 schema 欄位、無 gate、無 validator 邏輯、無腳本): + +1. `docs/orchestration.md` §2.8:lenses 表加 6 列(Hyrum's Law / Reversibility & Blast Radius / Separation of Duties / Least Privilege / Gall's Law / Modernized Postel's Law)+「明確拒絕:獨立 Policy Engine」段。 +2. `docs/sop/rule_lifecycle_audit.md`:Occam Pass 候選訊號清單擴充(rollback 缺失、單一指標移除理由、guard 刪除無替代、unknown consumer)。 +3. `artifacts/improvement/RELAXATION_LOG.md`:evaluation telemetry 與 intervention telemetry 分離句(Goodhart 第三規則,前兩規則已由既有文字覆蓋,不重複新增)。 +4. `docs/schemas/artifact-spec-decision.md`:新增條件式可選區段 `## Reversibility & Blast Radius`(比照既有 `## Guard Exception` 慣例)。 +5. `docs/subagent_roles.md` §1.3:Separation of Duties 與 Least Privilege 顯性條文。 +6. `README.md` + `README.zh-TW.md`:lens 名單句附加 6 個新名詞。 +7. PR-* 新增 1 條 pin(PR-039);EXACT_SYNC 鏡像;manifest regen(如過期)。 +8. `artifacts/decisions/TASK-1108.decision.md`:記錄 SoD 推翻 TASK-1106 裁決、ADR template 不復活、routing override 三項理由。 + +## Files Likely Affected + +- `docs/orchestration.md` + `template/docs/orchestration.md`(EXACT_SYNC) +- `docs/subagent_roles.md` + `template/docs/subagent_roles.md`(EXACT_SYNC) +- `docs/sop/rule_lifecycle_audit.md` + `template/docs/sop/rule_lifecycle_audit.md`(EXACT_SYNC) +- `artifacts/scripts/drills/prompt_regression_cases.json` + `template/artifacts/scripts/drills/prompt_regression_cases.json`(EXACT_SYNC) +- `artifacts/improvement/RELAXATION_LOG.md`(非 EXACT_SYNC,root only) +- `docs/schemas/artifact-spec-decision.md`(非 EXACT_SYNC,root only;只被 `docs/artifact_schema.md` 索引指向,非本身 EXACT_SYNC 成員) +- `README.md`、`README.zh-TW.md`(README contract,非 EXACT_SYNC) +- `.well-known/release-manifest.json`(僅當 template/ 變更觸發過期時 regen) +- `artifacts/code/TASK-1108.code.md`、`artifacts/test/TASK-1108.test.md`(NOT_APPLICABLE_BY_ADAPTER)、`artifacts/verify/TASK-1108.verify.md`、`artifacts/status/TASK-1108.status.json`、`artifacts/decisions/TASK-1108.decision.md`(lifecycle artifacts) + +**Post-Sync Amendment**(advisor 覆核後追加,於 verify 階段發現):`template/docs/schemas/artifact-spec-decision.md`(EXACT_SYNC_FILES 之外、但既有 byte-identical 同步慣例,本次補鏡像)、`template/artifacts/improvement/RELAXATION_LOG.md`(§Rules 段同步慣例,補新句)、`template/README.md`、`template/README.zh-TW.md`(補齊 TASK-1106 起即缺漏之 template governance-lenses 段落,非本任務造成之既有缺口)。詳見 `artifacts/decisions/TASK-1108.decision.md` §Implications 與 `artifacts/verify/TASK-1108.verify.md` §Evidence。 + +## Proposed Changes + +1.1 `docs/orchestration.md:163`(Swiss Cheese Model 列後、表格結束前)加 6 列: + - **Hyrum's Law**(Hyrum Wright/相容性視角)|已發布之可觀察行為一旦被使用即成隱性依賴,即使未正式承諾;unknown consumer ≠ no consumer|AGENTS.md 精確字串條款 + `prompt_regression_cases.json` 之 PR-* 字面 pin + `guard_contract_validator.py` EXACT_SYNC byte-identical 校驗|`AGENTS.md`、`artifacts/scripts/drills/prompt_regression_cases.json` + - **Reversibility & Blast Radius**(風險工程慣例)|修改 guard/schema/report/CI gate/預設值/可觀察輸出前須先分類可逆性與影響半徑|decision artifact 條件式可選 `## Reversibility & Blast Radius` 區段(本任務新增,比照既有 `## Guard Exception`)|`docs/schemas/artifact-spec-decision.md` + - **Separation of Duties**(治理慣例,TASK-1108 顯式化;TASK-1106 曾裁隱性覆蓋不掛牌,本次因具體規則需求推翻)|高風險/AI 產生之 guard/schema/CI/相容契約變更之 author 不得為唯一審查者|`docs/subagent_roles.md` §1.3 single-writer + Council Reviewer(3 個獨立 Codex model)+ premortem §12 獨立質疑|`docs/subagent_roles.md`、`docs/premortem_rules.md` + - **Least Privilege**(Saltzer & Schroeder 1975)|tools/scripts/CI/agent 應限最小必要權限;破壞性操作需顯式升級|`docs/subagent_roles.md` 之 agent 讀寫權限範圍 + wrapper write-scope 偵測(scope_guard.py)+ decision artifact `Override_Reason`|`docs/subagent_roles.md`、`docs/schemas/artifact-spec-decision.md` + - **Gall's Law**(John Gall 1975)|複雜可行系統必由簡單可行系統演化;避免 v0 過早長出重機制|Governance Lenses 表自身「不另立分層、不另建 schema、不另設階段」紀律 + rule lifecycle audit 之 Occam Pass|本章、`docs/sop/rule_lifecycle_audit.md` + - **Modernized Postel's Law**(Postel 1980,經 Hyrum's Law 修正)|對外輸出穩定/保守/可預期;legacy input 容忍須顯性、有警告、有 deprecation 追蹤;內部 schema 應嚴格|EXACT_SYNC byte-identical 輸出穩定機制 + RELAXATION_LOG 之顯性放寬紀錄(含 before/after/provenance)+ artifact schema 必填欄位嚴格性|`artifacts/improvement/RELAXATION_LOG.md`、`docs/artifact_schema.md` + +1.2 Campbell's Law 拒絕段後(`docs/orchestration.md:179` 之後)加「明確拒絕:獨立 Policy Engine(OPA/Rego/CEL)」段:Gall's Law 直接應用——本框架尚無可觀察之真實需求證明需要獨立 policy engine,guard 邏輯現以 Python validator 直接表達已足夠;在無使用資料前引入即為過早複雜化,明確不採,除非既有 repo 已依賴此類工具(現況:無);不得引為翻案範本。 + +2.1 `docs/sop/rule_lifecycle_audit.md:19-21`(Step 1 Occam Pass)候選訊號清單追加一句:候選訊號亦包含高 blast-radius 變更缺 rollback/migration notes、僅以單一指標作為移除唯一理由、guard 被刪除卻無替代機制或 decision 記錄、欄位查無消費者(unknown consumer——明示 unknown consumer ≠ no consumer,不得逕以此視為安全)。 + +3.1 `artifacts/improvement/RELAXATION_LOG.md` §Rules 追加一句:本檔記錄之 intervention telemetry(實際放寬案例)與 `guard_calibration_matrix.py` 量測之 evaluation telemetry(FP/FN)為兩種不同來源,不得合併成單一治理指標(Goodhart's Law 第三規則)。 + +4.1 `docs/schemas/artifact-spec-decision.md:56`(`## Guard Exception` 區段後)加條件式可選區段: + +```md +若 decision 涉及高風險或外部可見之變更(guard/schema/report/CI gate/預設值/可觀察輸出),建議額外提供: + +## Reversibility & Blast Radius +- Reversibility: reversible | partially_reversible | irreversible | unknown +- Blast Radius: local | module | repo | external_consumers | unknown +- Rollback Plan: +- Reviewer Independence: +- Least Privilege Notes: +``` + +並加欄位規則段落:兩欄位之 `unknown` 值視為「尚待查明」,不得等同安全/低風險/零風險,須於 `Reasoning` 補充查明計畫;本區段為可選、無自動 validator 強制,唯一既有消費者為後續審查者與週期性 architect review(Occam:未來若有自動化需求,另立 task 依實際使用資料評估,Gall's Law)。 + +5.1 `docs/subagent_roles.md:41`(§1.3 既有規則清單後)加兩句:(a) 高風險變更(涉及 guard/schema/CI gate/相容契約)之 author 不得為唯一審查者,須有 Council Reviewer(§5.1.3)或獨立 agent session 之 review 記錄(Separation of Duties);(b) 破壞性操作(guard 刪除、CI 放寬、secret 變更、schema-breaking 變更)需經 `guard_status_validator.py --override --override-approver` 或使用者明確核准方可執行(Least Privilege)。 + +6.1 `README.md:199` 於既有 9 名詞列表後附加 6 個新名詞(不改動既有名詞順序與句構)。 +6.2 `README.zh-TW.md:199` 對應同步。 + +7.1 `prompt_regression_cases.json` 加 PR-039:`must_contain_all` pin `docs/orchestration.md` 之 6 新視角名(Hyrum's Law / Reversibility & Blast Radius / Separation of Duties / Least Privilege / Gall's Law / Modernized Postel's Law)+ Policy Engine 拒絕句關鍵字面;雙副本(root + template)同字面。 +7.2 驗證鏈:guard_contract ×2 → guard_status → prompt_regression → SHA-256 逐對 → bash 語境全套 pytest → 必要時 manifest regen。 + +8.1 `artifacts/decisions/TASK-1108.decision.md`:Decision Class = `conflict-resolution`;記錄 SoD 推翻 TASK-1106 裁決之理由、ADR template 不復活之 Chesterton's Fence 理由、routing override(Claude 直寫)理由。 + +## Risks + +R1 +- Risk: EXACT_SYNC 同步缺漏——4 組檔案(orchestration/subagent_roles/rule_lifecycle_audit/prompt_regression_cases.json)root/template 各兩份,任一單側修改即 contract fail +- Trigger: 逐檔鏡像時遺漏,或忘記同步某一檔 +- Detection: `guard_contract_validator.py --root .` 報 mismatch;SHA-256 逐對比對 MISMATCH +- Mitigation: 每檔改完立即 Copy-Item 鏡像並 Get-FileHash 比對,四組全部確認後才進入下一步 +- Severity: blocking + +R2 +- Risk: 新增 PR-039 pin 或 README/SOP 新句誤觸既有 PR-038 pin(`Goodhart's Law` / `Normalization of Deviance` / `Swiss Cheese Model` / `明確不採 Campbell's Law` / `不得停留於 detect-and-accept`),或新句本身含未預期之 must_not_contain_any 衝突 +- Trigger: `prompt_regression_validator.py --root .` 跑列 +- Detection: validator 輸出 FAIL 與具體 pin ID +- Mitigation: 所有新增段落一律採「既有文字後方追加」,不改寫、不插入既有句中間;新增前先 grep 確認 PR-038 五個子字串仍完整存在 +- Severity: blocking + +R3 +- Risk: `docs/schemas/artifact-spec-decision.md` 新增之 `## Reversibility & Blast Radius` 區段,若欄位規則段落未明確標註「可選、非 validator 強制」,未來可能被誤讀或被後續 task 誤植為強制欄位,違反 Occam「無消費者不得強制」與 mission hard constraint「不得把 unknown 當安全」 +- Trigger: 撰寫欄位規則時遺漏「可選」與「unknown≠安全」兩句明文 +- Detection: 撰寫後人工覆核欄位規則段落是否同時含「可選」「無自動 validator 強制」「unknown 不得等同安全」三個關鍵語意 +- Mitigation: 撰寫時同批寫入三句明文,並於 verify artifact 逐字核對存在 +- Severity: blocking + +R4 +- Risk: 6 個新 lens 列之「對應現有機制」欄位若指向本任務同批新增的其他條文(如 Reversibility 列指向 decision schema 新區段),若兩處措辭不一致或其中一處遺漏,形成懸空引用 +- Trigger: 表列與目標檔分兩次編輯時措辭漂移,或編輯順序中斷 +- Detection: 驗收時逐列人工比對「對應現有機制」欄位字面與目標檔實際新增內容 +- Mitigation: 同一輪編輯內完成表列與其指向的目標檔內容,不分批交付 +- Severity: non-blocking + +R5 +- Risk: `docs/sop/rule_lifecycle_audit.md` 新增候選訊號句過長,導致總行數逼近或超過 TASK-1104 訂定之 150 行上限 +- Trigger: 新句未精簡,或誤把 4 類訊號各自展開成獨立段落 +- Detection: 修改後執行行數統計(`(Get-Content ).Count` 或等價 wc -l) +- Mitigation: 4 類訊號壓縮成同一句列舉,若逼近上限則裁剪敘述而非刪減既有內容 +- Severity: non-blocking + +R6 +- Risk: Separation of Duties 具名新增推翻 TASK-1106 明文裁決,若無 decision artifact 記錄推翻理由,日後 rule lifecycle audit 盤點會將此視為「未經 provenance 檢查之矛盾」而卡在 Chesterton Gate 之 `open` 裁決 +- Trigger: 下一輪 N=10 rule lifecycle audit 盤點讀到 TASK-1106 與 TASK-1108 兩份 task artifact 內容矛盾 +- Detection: 盤點時 grep `Separation of Duties` 命中兩份互斥描述 +- Mitigation: 本任務同批建立 `artifacts/decisions/TASK-1108.decision.md`,Decision Class = `conflict-resolution`,明確引用 TASK-1106:64 並記錄推翻理由與使用者裁決來源 +- Severity: blocking + +### Independent Premortem Challenge + +不適用。docs-only 治理文字增量,不命中 §12 四條件(非 security fix、非 upstream PR、非跨 repo——僅同一 repo 內多檔案修改、非不熟悉框架),同 TASK-1103/1104/1106 先例。 + +## Validation Strategy + +- 內容:AC-2~AC-8 逐條 grep 關鍵字面(6 新視角名、Policy Engine 拒絕句、Occam Pass 4 類訊號、RELAXATION_LOG 分離句、decision schema 新區段三句明文、subagent_roles 兩句條文、README 兩版 6 名詞)+ SOP 行數計數。 +- 結構:guard_contract ×2、guard_status、prompt_regression(含 PR-039)全綠;EXACT_SYNC 4 組檔案 SHA-256 逐對。 +- 回歸:bash 語境全套 pytest 0 failed(per `.github/memory-bank/project-facts.md` 執行語境慣例);跑前後檢查 `Documents/Code/.git` 空目錄殘骸是否再現(TASK-1106 遺留觀察項)。 + +## Verification Obligations + +- verify artifact 依 docs-spec adapter;Build Guarantee 以 validator chain + pytest + commit hash 承載。 +- AC-1~AC-13 逐條 evidence 記入 checklist。 +- R3(decision schema 可選性明文)與 R6(decision artifact 記錄推翻理由)於 verify 明記核對結果,不可僅記「已完成」。 + +## Routing + +- Task Type: implementation(docs 治理文字);Risk Score: 2(純文字、無邏輯、blast radius 限文件與 pin,無 secrets/CI/schema-breaking 變更);Context Cost: L(約 13 檔含鏡像,超過 M 門檻)。 +- **Routing override:Claude 直寫**。理由:(a) docs-only 治理文字,無 code/runtime 邏輯變更;(b) Intake/Research 階段已定位所有目標檔案之精確行號與既有機制引用,重新以 dispatch prompt 餵入 Codex 之 context 轉譯成本高於直寫風險,且 TASK-1106 已驗證同型任務之 Claude 直寫路徑安全;(c) 本任務含使用者於 Intake 當場裁決之 SoD 推翻決策,屬本 session 之判斷結論,直寫可避免轉述失真。per `docs/orchestration.md` §2.7 記錄於此,覆寫理由亦同步寫入 `artifacts/decisions/TASK-1108.decision.md`。 + +## Out of Scope + +- 修改或復活 `docs/templates/archive/adr/`;修改既有 9 個 lens 列或 OODA/Campbell 拒絕段字面;Goodhart's Law 重複新增(單一指標禁令與 firing_count=0 兩規則已由既有文字覆蓋);任何 `.py` validator/wrapper/CI workflow/自動化警告產生器;secrets、deployment、remote repository 設定。 + +## Ready For Coding + +yes diff --git a/artifacts/plans/TASK-1109.plan.md b/artifacts/plans/TASK-1109.plan.md new file mode 100644 index 0000000..3fc5a92 --- /dev/null +++ b/artifacts/plans/TASK-1109.plan.md @@ -0,0 +1,142 @@ +# Plan: TASK-1109 + +## Metadata +- Task ID: TASK-1109 +- Artifact Type: plan +- Owner: Claude +- Status: ready +- Last Updated: 2026-07-10T16:40:00+08:00 + +## Scope + +新增 Lucas Critique 為第 16 個治理視角;把 Campbell's Law 之操作性規則併入既有 Goodhart's Law 列(不新增獨立 lens、不動既有拒絕段 pinned 字面)。全為既有檔內增量與條件式可選 metadata(無新檔、無強制 schema、無 gate、無 validator 邏輯、無腳本): + +1. `docs/orchestration.md`:更新 Goodhart's Law 列 + 新增 Lucas Critique 列 + Campbell's Law 拒絕段後追加操作化附註。 +2. `docs/sop/rule_lifecycle_audit.md`:Occam Pass 追加 Campbell's Law 操作化句(不獎勵人為事件)。 +3. `artifacts/improvement/RELAXATION_LOG.md`:§Rules 追加 Lucas Critique 句(regime-change 標註、跨建制比較但書)。 +4. `docs/schemas/artifact-spec-decision.md`:新增條件式可選 `## Metrics Policy` 與 `## Policy Regime` 兩區段。 +5. `README.md` + `README.zh-TW.md`:lens 名單句新增「Lucas Critique」。 +6. 上述所有觸及檔(含 EXACT_SYNC 正式成員與慣例同步之非成員)之 template/ 鏡像**於本輪同批完成**(吸取 TASK-1108 教訓,不留待 verify 階段補)。 +7. PR-* 新增 1 條 pin(PR-040);manifest regen(如過期)。 +8. `artifacts/decisions/TASK-1109.decision.md`:記錄 Campbell's Law 併入(非新增獨立 lens)之理由與使用者裁決來源。 + +## Files Likely Affected + +- `docs/orchestration.md` + `template/docs/orchestration.md`(EXACT_SYNC) +- `docs/sop/rule_lifecycle_audit.md` + `template/docs/sop/rule_lifecycle_audit.md`(EXACT_SYNC) +- `artifacts/scripts/drills/prompt_regression_cases.json` + `template/artifacts/scripts/drills/prompt_regression_cases.json`(EXACT_SYNC) +- `docs/schemas/artifact-spec-decision.md` + `template/docs/schemas/artifact-spec-decision.md`(非 EXACT_SYNC 清單成員,但依 TASK-1108 確立之慣例同步;本輪主動同步) +- `artifacts/improvement/RELAXATION_LOG.md` + `template/artifacts/improvement/RELAXATION_LOG.md`(同上,僅 §Rules 段同步,§Cases 段維持既有 placeholder 不動) +- `README.md`、`README.zh-TW.md`、`template/README.md`、`template/README.zh-TW.md`(README contract 非 EXACT_SYNC,但依 TASK-1108 慣例主動同步 template 兩版) +- `.well-known/release-manifest.json`(template/ 變更觸發過期時 regen) +- `artifacts/code/TASK-1109.code.md`、`artifacts/test/TASK-1109.test.md`(NOT_APPLICABLE_BY_ADAPTER)、`artifacts/verify/TASK-1109.verify.md`、`artifacts/status/TASK-1109.status.json`、`artifacts/decisions/TASK-1109.decision.md`(lifecycle artifacts) +- `docs/subagent_roles.md`、`template/docs/subagent_roles.md`(**非本任務編輯**——由 TASK-1108 修改、尚未 commit,因同一 dirty worktree 跨兩個 task,git-backed scope check 會將其列為「actual changed files」;列於此處僅為滿足該檢查,內容歸屬與理由已於 `artifacts/code/TASK-1108.code.md` 完整記錄,本任務未對其做任何額外編輯) + +## Proposed Changes + +1.1 `docs/orchestration.md:161` Goodhart's Law 列更新為:名稱欄附加「亦涵蓋 Campbell's Law 1979 之經濟學同構表述,TASK-1109 併入」;所管問題欄附加「高風險指標(firing_count/pass_rate/coverage 等)不得作為安全/價值/品質之直接證明」;對應現有機制欄附加「決策涉及高風險指標時,decision schema 之條件式可選 `## Metrics Policy` 區段記錄 campbell_risk/gaming_vectors」;文件落點欄附加 `docs/schemas/artifact-spec-decision.md` 連結。保留既有「Goodhart's Law」「RELAXATION_LOG 累積 ≥ 3 案例 → architect review」等 PR-038 相依內容不動。 +1.2 `docs/orchestration.md:169`(Modernized Postel's Law 列後)新增 Lucas Critique 列: + - **Lucas Critique**(Lucas 1976,政策回饋/建制變動視角,TASK-1109 顯式化)|治理規則變更後(CI gate、guard 定義、telemetry schema、model 角色、escalation 規則、pass/fail 門檻、report 格式、prompt 政策),行為會調適,舊 baseline 不可跨建制直接比較|RELAXATION_LOG 之 Before/After/Trigger Task 記錄格式 + rule lifecycle audit 之 `relax`/`retire` 裁決 + decision artifact 條件式可選 `## Policy Regime` 區段(本次新增)|`artifacts/improvement/RELAXATION_LOG.md`、`docs/sop/rule_lifecycle_audit.md`、`docs/schemas/artifact-spec-decision.md` +1.3 `docs/orchestration.md:185`(「明確拒絕:Campbell's Law」段既有文字後)新增操作化附註段落:說明該拒絕僅拒絕「另立與 Goodhart's Law 重複之獨立視角」,Campbell's Law 文獻中對高風險指標的具體操作規則(不得以原始指標值直接證明、標記 campbell_risk、記錄 gaming vectors、不得獎勵人為事件)已併入 Goodhart's Law 列與 `## Metrics Policy` 區段。 + +2.1 `docs/sop/rule_lifecycle_audit.md:22`(Step 1 末)追加句:候選訊號評估時,不得以原始指標值(如 firing_count、pass_rate、coverage)直接作為安全/價值/品質之證明;不得獎勵人為製造之 guard 觸發、警告壓制、淺層測試覆蓋,或僅改善指標而未降低實際風險之變更。 + +3.1 `artifacts/improvement/RELAXATION_LOG.md:10`(§Rules 末)追加句:任一案例若構成治理規則之建制變動(CI gate、guard 定義、telemetry schema、model 角色、escalation 規則、pass/fail 門檻、report 格式或 prompt 政策之變更),該案例前後之 telemetry 不得直接比較,須附加正規化說明或「不可比較」但書(Lucas Critique,TASK-1109)。 + +4.1 `docs/schemas/artifact-spec-decision.md:69`(`## Reversibility & Blast Radius` 規則段落後)新增兩個條件式可選區段(格式、規則段落比照既有先例): + +```md +## Metrics Policy +- Campbell Risk: low | medium | high | unknown +- High Stakes Metric: true | false +- Gaming Vectors: + - ... +- Metric Interpretation: + +## Policy Regime +- Regime ID: +- Changed At: +- Changed By: +- Comparable To Previous: true | false +- Baseline Reset Required: true | false +- Adaptation Expected: + - ... +- Notes: +``` + +`## Metrics Policy` 規則:本區段為可選,適用於決策部分依據 firing_count/block_count/pass_rate/coverage 等治理指標時;`Metric Interpretation` 必須寫「證據而非自動核准」等語意,不得留空;指標值本身不構成裁決之充分理由。`## Policy Regime` 規則:本區段為可選,適用於決策本身構成治理規則之建制變動(CI gate、guard、telemetry schema、model 角色、escalation、閾值、report 格式、prompt 政策);`Comparable To Previous: false` 時視為預設安全假設(防止誤判「新政策降低可見失敗 = 指標改善」),非等同不重要。兩區段皆無自動 validator 強制,唯一既有消費者為後續審查者與週期性 architect review;未來若有自動化強制需求,依實際使用資料另立 task 評估。 + +5.1 `README.md:199`/`README.zh-TW.md:199` lens 名單句末新增「Lucas Critique」(不新增 Campbell's Law)。 + +6.1 EXACT_SYNC 正式成員(orchestration.md、rule_lifecycle_audit.md、prompt_regression_cases.json)與慣例同步檔(artifact-spec-decision.md、RELAXATION_LOG.md §Rules、README 兩版)於本輪同批鏡像至 template/,不分批交付。 + +7.1 `prompt_regression_cases.json` 加 PR-040:`docs/orchestration.md` must_contain_all `["Lucas Critique", "Campbell's Law 1979 之經濟學同構表述"]`;`docs/schemas/artifact-spec-decision.md` must_contain_all `["## Metrics Policy", "## Policy Regime"]`。 +7.2 驗證鏈:guard_contract ×2 → guard_status → prompt_regression → SHA-256/內容逐對 → bash 語境全套 pytest → 必要時 manifest regen。 + +8.1 `artifacts/decisions/TASK-1109.decision.md`:Decision Class = `conflict-resolution`;記錄 Campbell's Law 併入理由與使用者裁決來源。 + +## Risks + +R1 +- Risk: 編輯 Goodhart's Law 列或 Campbell's Law 拒絕段時,不慎刪除或改寫 PR-038 依賴之子字串(`Goodhart's Law`、`明確不採 Campbell's Law`) +- Trigger: 整段覆寫而非精準追加 +- Detection: `prompt_regression_validator.py --root .` PR-038 fail +- Mitigation: 全程採「既有句後方追加」;編輯前後皆 grep 確認兩子字串仍存在 +- Severity: blocking + +R2 +- Risk: EXACT_SYNC 4 組正式成員之一遺漏鏡像,或慣例同步之 3 組非正式成員(decision schema、RELAXATION_LOG、README 兩版)遺漏同步(重演 TASK-1108 之 Post-Sync Amendment 缺口) +- Trigger: 逐檔編輯時遺漏其中一組 +- Detection: `guard_contract_validator.py --root .`/`--check-readme` fail;對非正式成員另行 diff 直讀核對 +- Mitigation: 本輪同批完成全部 7 組檔案之 root+template 編輯,不分兩階段;每組改完立即 diff 確認 +- Severity: blocking + +R3 +- Risk: `docs/sop/rule_lifecycle_audit.md` 新句過長導致逼近 150 行上限 +- Trigger: Campbell 操作化句未精簡 +- Detection: 修改後行數統計 +- Mitigation: 壓縮成單句列舉,現況 54 行有 96 行餘裕;修改後仍以行數統計驗證確認未逼近上限 +- Severity: non-blocking + +R4 +- Risk: Lucas Critique 列之「對應現有機制」引用本次新增的 `## Policy Regime` 區段,若兩處措辭不一致或分批完成形成懸空引用 +- Trigger: 表列與 decision schema 分兩次編輯 +- Detection: 驗收時人工比對表列字面與 decision schema 實際新增內容 +- Mitigation: 同一輪編輯內完成兩處 +- Severity: non-blocking + +R5 +- Risk: Campbell's Law 併入 Goodhart's Law 列後,若未來(例如下一輪 rule lifecycle audit)誤讀為「Campbell's Law 拒絕段已失效」,重新提案新增獨立 Campbell's Law lens 而未查本 decision artifact +- Trigger: 後續 task 未讀 decision artifact 逕自提案 +- Detection: grep `Campbell's Law` 發現操作化附註段未被引用為 provenance +- Mitigation: decision artifact 明確記錄「拒絕段 pinned 字面不變,只新增操作化附註」,並於 orchestration.md 操作化附註段落本身明文「本附註不推翻上方拒絕宣告,僅澄清吸收範圍」 +- Severity: blocking + +### Independent Premortem Challenge + +不適用。docs-only 治理文字增量,不命中 §12 四條件(非 security fix、非 upstream PR、非跨 repo、非不熟悉框架)。Campbell's Law 併入之取捨本身已透過 AskUserQuestion 取得使用者獨立確認(非 Claude 單方對自己撰寫之 R1-R5 自問自答),實質滿足獨立性要求之精神,同 TASK-1108 之 SoD 案處理方式。 + +## Validation Strategy + +- 內容:AC-2~AC-8 逐條 grep 關鍵字面(Goodhart 列更新、Lucas Critique 列、Campbell 操作化附註、Occam Pass 新句、RELAXATION_LOG 新句、Metrics Policy/Policy Regime 兩區段、README 新名詞)+ SOP 行數計數。 +- 結構:guard_contract ×2、guard_status、prompt_regression(含 PR-040,PR-038/PR-039 仍需全 pass)全綠;7 組觸及檔(4 EXACT_SYNC 正式 + 3 慣例同步)逐對核對。 +- 回歸:bash 語境全套 pytest 0 failed(延續 TASK-1108 對 `Documents/Code/.git` 殘骸之觀察義務,非本任務新增之修復對象)。 + +## Verification Obligations + +- verify artifact 依 docs-spec adapter;Build Guarantee 以 validator chain + pytest + commit hash 承載。 +- AC-1~AC-13 逐條 evidence 記入 checklist。 +- R1(PR-038 子字串保護)與 R2(7 組檔案同批同步)於 verify 明記核對結果。 + +## Routing + +- Task Type: implementation(docs 治理文字);Risk Score: 2(純文字、無邏輯,但涉及修改一段 PR-pinned 既有拒絕文字之周邊內容,故不判 1);Context Cost: L(7 組觸及檔 + 5 lifecycle artifacts)。 +- **Routing override:Claude 直寫**。理由:(a) docs-only 治理文字;(b) 本 session 已直接延續 TASK-1108 之完整 context(Governance Lenses 表現況、EXACT_SYNC 清單、decision schema 先例、template-sync 教訓皆已在手),重新以 dispatch prompt 餵入 Codex 之轉譯成本與遺漏風險皆高於直寫;(c) Campbell's Law 併入決策屬本 session 使用者當場裁決,直寫可避免轉述失真。per `docs/orchestration.md` §2.7 記錄於此,亦同步記於 decision artifact。 + +## Out of Scope + +- 新增獨立 Campbell's Law lens row;修改 OODA、Policy Engine 拒絕段字面;任何 validator/wrapper/CI workflow/自動化警告產生器變更;`docs/templates/archive/` 復活。 + +## Ready For Coding + +yes diff --git a/artifacts/plans/TASK-1112.plan.md b/artifacts/plans/TASK-1112.plan.md new file mode 100644 index 0000000..dfe045c --- /dev/null +++ b/artifacts/plans/TASK-1112.plan.md @@ -0,0 +1,83 @@ +# Plan: TASK-1112 + +## Metadata +- Task ID: TASK-1112 +- Artifact Type: plan +- Owner: Claude +- Status: ready +- Last Updated: 2026-07-17T12:05:00+08:00 + +## Scope + +把 TASK-1107 improvement artifact 之兩條 dispatch 操作紀律正式寫入 `docs/sop/dispatch_implementation.md` 與 `docs/dispatch_prompt_discipline.md`,root/template 同步。 + +## Files Likely Affected + +- `docs/sop/dispatch_implementation.md` +- `template/docs/sop/dispatch_implementation.md` +- `docs/dispatch_prompt_discipline.md` +- `template/docs/dispatch_prompt_discipline.md` +- `artifacts/status/TASK-1112.status.json` +- `artifacts/verify/TASK-1112.verify.md` +- `.well-known/release-manifest.json`(template/ 變更後之必然收尾,同 TASK-1107 precedent,見 R4) +- `artifacts/tasks/TASK-1112.task.md`(lifecycle artifact,本檔之上游) +- `artifacts/research/TASK-1112.research.md`(lifecycle artifact) +- `artifacts/plans/TASK-1112.plan.md`(lifecycle artifact,本檔自身) +- `artifacts/code/TASK-1112.code.md`(lifecycle artifact) + +## Proposed Changes + +1. `docs/sop/dispatch_implementation.md`:於既有「### Fallback tier 產出之驗收紀律(TASK-1106)」之後追加「### Dispatch 逾時重派紀律(TASK-1112)」,內容取自 `artifacts/improvement/TASK-1107.improvement.md` §5 第一條,逐字對齊。 +2. `docs/dispatch_prompt_discipline.md`:於「## 6. Cross-references」之前追加「## Dispatch Wrapper Log 重導向路徑紀律(TASK-1112)」,內容取自同一 improvement artifact §5 第二條。 +3. 兩份 root 檔完成後,直接複製內容至對應 template/ 路徑,確保逐位元組相同。 + +## Risks + +R1 +- Risk: 追加文字與既有章節編號/cross-reference 產生衝突(例如既有文件他處以章節號引用「## 6.」,插入新章節後編號偏移致引用失效)。 +- Trigger: `docs/dispatch_prompt_discipline.md` 或其他檔案內有以數字章節號(而非標題文字)引用本檔章節。 +- Detection: `grep -rn "dispatch_prompt_discipline.md.*§[0-9]\|dispatch_prompt_discipline.md#" docs/ CLAUDE.md GEMINI.md CODEX.md AGENTS.md` 搜尋是否有跨檔章節號引用。 +- Mitigation: 若發現引用,改用不佔既有編號的插入位置(本 plan 已選擇「不重新編號既有章節」之插入點,僅在既有章節之間插入無編號小節,理論上不影響既有數字章節引用);若仍衝突則調整插入位置至檔案最末。 +- Severity: non-blocking + +R2 +- Risk: root 與 template 鏡射複製時因換行符(CRLF/LF)或編碼差異導致 `guard_contract_validator.py` 回報 drift。 +- Trigger: 使用非 byte-exact 複製方式(例如手動重打文字)同步 template。 +- Detection: `python artifacts/scripts/guard_contract_validator.py --root .` 執行後非 `[OK]`。 +- Mitigation: 一律以檔案內容直接複製(`cp` 或等價操作)同步 template,不手動重打;複製後立即跑 `guard_contract_validator.py --root .` 確認 `[OK]`。 +- Severity: blocking + +R3 +- Risk: 新增文字內引用之具體檔名/函式名(`artifacts/improvement/TASK-1107.improvement.md`、`Get-Process -Name codex,node`、`-AutoRestore`)若與現行程式碼或既有 artifact 路徑不符,會誤導未來讀者。 +- Trigger: 文字撰寫時筆誤或未核對現行檔案路徑。 +- Detection: 人工核對每個反引號內的路徑/指令是否確實存在於現行 repo(`ls artifacts/improvement/TASK-1107.improvement.md`、`grep -n "AutoRestore" artifacts/scripts/Invoke-CodexAgent.ps1`)。 +- Mitigation: 若核對失敗,修正為正確路徑/指令後才可標記完成。 +- Severity: blocking + +R4(於實作階段實際觸發,記錄於此供追溯) +- Risk: 修改 `template/` 下任一檔案會使 `.well-known/release-manifest.json` 過期,觸發 `test_council_forge_release_manifest_matches_template_snapshot`/`test_integrity_gate_passes_on_valid_repo` 兩項失敗(與 TASK-1107 遭遇之機制完全相同)。 +- Trigger: 本 task 同步 `template/docs/sop/dispatch_implementation.md` 與 `template/docs/dispatch_prompt_discipline.md` 兩檔。 +- Detection: `python -m pytest artifacts/scripts -q` 由基線 `5 failed` 增至 `7 failed`,新增兩項即為此機制。 +- Mitigation: `python artifacts/scripts/snapshot_manifest.py generate --output .well-known/release-manifest.json` 重生,重跑確認回到 `5 failed, 2034 passed`。 +- Severity: blocking + +## Validation Strategy + +1. `python artifacts/scripts/guard_contract_validator.py --root .` -> `[OK]` +2. `python artifacts/scripts/prompt_regression_validator.py --root .` -> 全 PASS +3. `python -m pytest artifacts/scripts -q` -> 對照 TASK-1107 收尾基線(`5 failed, 2034 passed, 2 skipped`)無新增 regression +4. 人工核對 R3 之路徑/指令引用正確性 + +## Verification Obligations + +- verify artifact 逐條對應 AC-1 至 AC-5;docs-spec adapter 下 test 為 `NOT_APPLICABLE_BY_ADAPTER`。 +- 無 deferred verification debt。 + +## Out of Scope + +- 自動化 enforcement 機制(見 task artifact Out of Scope)。 +- TASK-1111 之修復。 + +## Ready For Coding + +yes diff --git a/artifacts/research/TASK-1102.research.md b/artifacts/research/TASK-1102.research.md new file mode 100644 index 0000000..36432f8 --- /dev/null +++ b/artifacts/research/TASK-1102.research.md @@ -0,0 +1,57 @@ +# Research: TASK-1102 + +## Metadata +- Task ID: TASK-1102 +- Artifact Type: research +- Owner: Claude +- Status: ready +- Last Updated: 2026-07-06T15:10:00+08:00 + +## Research Questions + +1. `-AutoRestore` 在 `Invoke-CodexAgent.ps1` / `Invoke-GeminiAgent.ps1` 的實際預設值與行為是否真如 user 所述(預設不啟用、僅 detect-only)? +2. `CODEX.md`、`GEMINI.md` 是否皆含「違者:dispatch 視為失敗」之絕對敘述?兩者是否已存在與 `-AutoRestore` 相關的條件說明? +3. `CLAUDE.md` 目前是否有任何段落提及協調者需顯式傳遞 `-AutoRestore` 才能讓違規被真正擋下? +4. 若要修改 `CLAUDE.md` / `GEMINI.md`,有哪些既有 governance 機制(EXACT_SYNC、phrase-check、prompt_regression PR-* pin)會被觸發,須事先掌握以免改寫時誤觸? + +## Confirmed Facts + +- `Invoke-CodexAgent.ps1` 的 `-AutoRestore` 參數宣告為 `[switch]$AutoRestore = $false`,即預設不啟用(`artifacts/scripts/Invoke-CodexAgent.ps1:41`)。 +- `CODEX.md:76-78` 已載明:`-AutoRestore` 之 wrapper 強制層於 dispatch 完成後自動偵測;default `$false` 為「detect 模式:印 violations 但 exit 0」;caller 顯式 `-AutoRestore` 時才觸發 enforcement(`CODEX.md:76-78`)。 +- `CODEX.md:75` 的「違者」敘述為「立 `artifacts/decisions/.decision.md` 說明越界原因」,此為 Codex 自身之自我回報義務,**不含**「dispatch 視為失敗」字面,且此義務的存在與 `-AutoRestore` 是否傳遞無關(`CODEX.md:75`)。 +- 全 repo 搜尋 `dispatch 視為失敗` 僅命中 `GEMINI.md:46` 與其鏡像 `template/GEMINI.md:46`;`CODEX.md` 不含此字面(以 grep 全文搜尋確認,命中檔清單僅 2 筆)。 +- `GEMINI.md:46`(修改前)原文為「違者:dispatch 視為失敗;Claude 將以 `git checkout HEAD --` 還原並要求 redo」;其正下方 `GEMINI.md:47-48` 已含與 `CODEX.md:76-78` 相同的 `-AutoRestore` 條件說明(stash-based restore、default `$false` = detect 模式、顯式傳遞才 enforcement)。二者並存造成同一段落內「46 行絕對」與「47-48 行條件」互相矛盾。 +- `git checkout HEAD --` 全量還原對應 2026-05-07 wrapper 破壞事故(31 paths 被誤清)之舊行為;TASK-1059 已將其改為 stash-based pre-dispatch snapshot + 僅對真實 delta 執行 restore(見 auto-memory `project_incident_wrapper_destruction_2026_05_07.md` 與 `feedback_wrapper_autorestore_unsafe.md` 之既有記錄,並經 `CODEX.md:77` / `GEMINI.md:48` 之現行敘述交叉確認一致)。 +- `CLAUDE.md` 全文搜尋 `AutoRestore` 無命中(修改前),確認協調者入口檔完全未提及此決策點(以 grep 對 `CLAUDE.md` 全文確認)。 +- `guard_contract_validator.py:19-23` 之 `EXACT_SYNC_FILES` 含 `CODEX.md`、`GEMINI.md`,要求與 `template/` 對應檔 SHA-256 全等;`CLAUDE.md` **不在** `EXACT_SYNC_FILES` 清單中,而是由 `SOURCE_REQUIRED_PHRASES["CLAUDE.md"]` / `["template/CLAUDE.md"]`(`guard_contract_validator.py:96-110`)做 phrase-based 檢查,兩者機制不同(`artifacts/scripts/guard_contract_validator.py:19-40, 95-110`)。 +- `template/CLAUDE.md` 與 `CLAUDE.md`(修改前)僅有 1 行既知差異(downstream terminal repo 專屬句擴寫),為既有、刻意保留之落差,非本 task 待修內容(以 `diff CLAUDE.md template/CLAUDE.md` 直接確認)。 +- `artifacts/scripts/drills/prompt_regression_cases.json` 之 PR-027(`CODEX.md`)與 PR-028(`GEMINI.md`)皆已 pin `Write Scope Discipline` / `-AllowedPaths` / `AutoRestore` 等既有字面,惟未 pin 第 46 行本身之「違者」敘述字面,故重寫該行不會直接衝突既有 PR-027/PR-028(以 `grep -n "file.*GEMINI.md" -A10 prompt_regression_cases.json` 逐條核對其 `must_contain_all` / `all_of_any` 清單確認)。 +- `guard_contract_validator.py` 另含一條與 prompt 檔變更耦合之強制檢查:任何 git working-tree 變更命中 `PROMPT_ENTRY_FILES`(`CLAUDE.md`/`GEMINI.md`/`CODEX.md` 及其 `template/` 鏡像)卻未同時命中 `PROMPT_REGRESSION_FILES`(`artifacts/scripts/drills/prompt_regression_cases.json` 及其鏡像)時,回報 `[FAIL] Prompt contract changed but prompt regression cases were not updated`(`artifacts/scripts/guard_contract_validator.py:544-550`)。故本次修改 `CLAUDE.md`/`GEMINI.md` 必須同時新增對應 `prompt_regression_cases.json` 條目才能通過 contract validator。 + +## Relevant References + +- `artifacts/scripts/Invoke-CodexAgent.ps1`(`-AutoRestore` 參數宣告與預設值) +- `CODEX.md` / `GEMINI.md`(Write Scope Discipline 段之既有敘述與落差) +- `artifacts/scripts/guard_contract_validator.py`(EXACT_SYNC_FILES、SOURCE_REQUIRED_PHRASES、PROMPT_ENTRY_FILES / PROMPT_REGRESSION_FILES 之 prompt-contract-sync 檢查邏輯) +- `artifacts/scripts/drills/prompt_regression_cases.json`(PR-027、PR-028 既有 keyword pin,用於避免改寫時誤觸既有回歸案例) +- `artifacts/tasks/TASK-1064.task.md` 與其 plan/code/verify(同類「純 docs + template 鏡像 + prompt_regression PR-* 追加」任務之既有範式) + +## Sources + +[1] council-forge. "Invoke-CodexAgent.ps1 wrapper source." artifacts/scripts/Invoke-CodexAgent.ps1 (2026-07-06 retrieved) +[2] council-forge. "CODEX.md agent entry prompt." CODEX.md (2026-07-06 retrieved) +[3] council-forge. "GEMINI.md agent entry prompt (pre-edit)." GEMINI.md (2026-07-06 retrieved) +[4] council-forge. "guard_contract_validator.py workflow sync validator." artifacts/scripts/guard_contract_validator.py (2026-07-06 retrieved) +[5] council-forge. "prompt_regression_cases.json regression case bank." artifacts/scripts/drills/prompt_regression_cases.json (2026-07-06 retrieved) + +## Uncertain Items + +None + +## Constraints For Implementation + +- 只改 `GEMINI.md`(+ template 鏡像),不改 `CODEX.md`:後者已合規,且其「違者:立 decision artifact」義務不應因 `-AutoRestore` 有無傳遞而變成有條件。 +- `GEMINI.md` 改寫時不得重新出現 `git checkout HEAD --` 之全量還原語言(該語言已被 TASK-1059 的 stash-based restore 取代)。 +- `GEMINI.md` 為 `EXACT_SYNC_FILES` 成員,改寫後須與 `template/GEMINI.md` SHA-256 全等;`CLAUDE.md` 走 phrase-based 檢查,鏡像須人工 diff 確認未破壞既有 1 行落差。 +- 任何對 `CLAUDE.md` / `GEMINI.md` 的修改都必須同時在 `artifacts/scripts/drills/prompt_regression_cases.json`(+ template 鏡像)新增對應 PR-* 條目,否則 `guard_contract_validator.py` 之 prompt-contract-sync 檢查會 FAIL。 +- 新增 PR-* 條目不得與既有 PR-027 / PR-028 之 `must_contain_all` / `all_of_any` 字面衝突。 diff --git a/artifacts/research/TASK-1103.research.md b/artifacts/research/TASK-1103.research.md new file mode 100644 index 0000000..36f247f --- /dev/null +++ b/artifacts/research/TASK-1103.research.md @@ -0,0 +1,56 @@ +# Research: TASK-1103 + +## Metadata +- Task ID: TASK-1103 +- Artifact Type: research +- Owner: Claude +- Status: ready +- Last Updated: 2026-07-07T10:10:00+08:00 + +## Research Questions + +1. 本專案是否已有機制,讓 plan 階段的 premortem(R1-R4)被撰寫者以外的角色獨立質疑?既有的 Council Reviewer、RACI Auditor/Architecture Synthesizer 是否已覆蓋此需求? +2. `docs/premortem_rules.md` 與 `docs/schemas/artifact-spec-plan.md` 是否允許在不修改 schema 的前提下,於 `## Risks` 下新增自訂子區段承載獨立質疑結果? +3. `docs/premortem_rules.md` 是否受 `guard_contract_validator.py` 的 EXACT_SYNC 或 prompt-contract-sync 耦合檢查約束?修改 `CLAUDE.md` 是否會觸發額外同步義務? +4. `docs/workflow_state_machine.md` 是否承載 premortem gate 的轉移條件?修改本任務範圍是否需要一併修改該檔? + +## Confirmed Facts + +- `docs/premortem_rules.md` §4 之 P1-P8 品質規則(`docs/premortem_rules.md:65-125`)僅檢查風險條目格式與用語是否具體(是否具名、是否用抽象詞、Trigger/Detection/Mitigation 是否可觀察可驗證、Severity 是否明確、是否至少一條 blocking、是否以結論代替分析),**不含**任何要求由撰寫者以外角色複核風險判斷實質內容的規則(`docs/premortem_rules.md` 全文檢視確認)。 +- `docs/subagent_roles.md` §5.1.3(`docs/subagent_roles.md:296-304`)之 Council Reviewer 機制,其輸入是「git diff」,觸發時機為「diff 已產出之後」,屬於 coding 完成後的機制,不作用於 plan 階段尚無 code diff 的情境。 +- `CLAUDE.md` Routing Matrix 之 RACI Auditor / Architecture Synthesizer 觸發條件為「Closure 階段每 10 個 PROCESS_LEDGER 或 Sprint Review」(`CLAUDE.md` Agent Routing Policy 段),屬週期性批次審查,不是逐 task/逐 plan 觸發,粒度與本任務欲補的「單一高風險 plan 的 R1-R4 是否經得起質疑」不同。 +- 兩者交叉確認:目前沒有任何既有機制,在 `planned → coding` 轉移之前,對單一 plan 的 R1-R4 風險判斷本身做撰寫者以外的獨立檢查——existing gate 只驗證格式(見 `docs/premortem_rules.md` §4 之 P1-P8)或發生在不同階段(`docs/subagent_roles.md:296-304` 之 Council Reviewer 在 code 之後、`CLAUDE.md` Routing Matrix 之 RACI Auditor 是批次)。 +- `docs/schemas/artifact-spec-plan.md:31-40`(`## Risks` 區段定義)僅要求區段存在且內容符合 premortem 規則,未限制區段下是否可有子標題(`### ...`);比對既有 `artifacts/verify/TASK-1102.verify.md` 等既完成 artifact 之 `## Evidence` 區段下皆有慣例性子區段(如 `### Validator Chain`、`### Mirror Match`),確認本專案 artifact 慣例本就允許必要區段下自訂子區段,不視為違反 schema。 +- `artifacts/scripts/guard_contract_validator.py:19-70` 之 `EXACT_SYNC_FILES` 含 `docs/premortem_rules.md`(第 64 行),要求與 `template/docs/premortem_rules.md` SHA-256 全等;以 `diff docs/premortem_rules.md template/docs/premortem_rules.md` 確認修改前兩者逐位元組相同(exit code 0,無輸出)。 +- `artifacts/scripts/guard_contract_validator.py:133-145` 定義 `PROMPT_ENTRY_FILES`(`CLAUDE.md`/`GEMINI.md`/`CODEX.md` 及其 `template/` 鏡像)與 `PROMPT_REGRESSION_FILES`(`artifacts/scripts/drills/prompt_regression_cases.json` 及其鏡像)之耦合檢查:working-tree 命中前者卻未命中後者會回報 `[FAIL]`(沿用 TASK-1102 research 已確認之邏輯,`artifacts/scripts/guard_contract_validator.py:544-550`)。`docs/premortem_rules.md` 不在 `PROMPT_ENTRY_FILES` 內,故單獨修改該檔不會觸發此耦合檢查;但本任務同時修改 `CLAUDE.md`,故仍會觸發,須新增對應 `prompt_regression_cases.json` 條目。 +- `docs/workflow_state_machine.md` 全文搜尋 `premortem` 與 `Planning.*Coding` 皆無命中,確認 premortem gate 完全由 `guard_status_validator.py`(讀 `docs/premortem_rules.md` 規則)承載,不在 workflow state machine 文件內表述,故本任務不需修改該檔。 +- `artifacts/scripts/drills/prompt_regression_cases.json` 現有 35 筆(`PR-001`..`PR-035`),最新一筆 `PR-035` 對應 TASK-1102(`python -c "import json; print(len(json.load(open('artifacts/scripts/drills/prompt_regression_cases.json', encoding='utf-8'))))"` 輸出 35);格式為 list of `{id, title, description, assertions: [{file, must_contain_all, must_not_contain_any?, note}]}`(直接讀取該檔最後一筆與 `PR-027`/`PR-028` 條目確認結構)。 + +## Relevant References + +- `docs/premortem_rules.md`(新增章節之目標檔,需承接 §1-§11 既有格式與風格) +- `docs/schemas/artifact-spec-plan.md`(確認 `## Risks` 子區段不受 schema 限制) +- `docs/subagent_roles.md` §5.1.3(Council Reviewer 定位與觸發時機,用於界定分工邊界) +- `CLAUDE.md` Agent Routing Policy(RACI Auditor / Architecture Synthesizer 觸發條件) +- `artifacts/scripts/guard_contract_validator.py`(`EXACT_SYNC_FILES`、`PROMPT_ENTRY_FILES`、`PROMPT_REGRESSION_FILES` 定義) +- `artifacts/verify/TASK-1102.verify.md`(同類「純 docs + template 鏡像 + prompt_regression PR-* 追加」任務之既有範式,含 validator chain 執行順序) + +## Sources + +[1] council-forge. "Premortem quality rules." docs/premortem_rules.md (2026-07-07 retrieved) +[2] council-forge. "Plan artifact schema." docs/schemas/artifact-spec-plan.md (2026-07-07 retrieved) +[3] council-forge. "Subagent roles — Council Reviewer definition." docs/subagent_roles.md (2026-07-07 retrieved) +[4] council-forge. "Contract sync validator — EXACT_SYNC_FILES / PROMPT_ENTRY_FILES / PROMPT_REGRESSION_FILES." artifacts/scripts/guard_contract_validator.py (2026-07-07 retrieved) +[5] council-forge. "Prompt regression case bank (35 existing cases)." artifacts/scripts/drills/prompt_regression_cases.json (2026-07-07 retrieved) + +## Uncertain Items + +None + +## Constraints For Implementation + +- 新增內容寫成 `docs/premortem_rules.md` 的新章節(§12),沿用既有章節編號慣例,不修改既有 §1-§11 語意。 +- 獨立質疑結果的輸出位置定為 plan `## Risks` 下的 `### Independent Premortem Challenge` 子區段(沿用本專案既有「必要區段下容許自訂子區段」慣例),不修改 `docs/schemas/artifact-spec-plan.md`。 +- 不修改 `docs/workflow_state_machine.md`(premortem gate 不在該檔承載,已查證確認)。 +- 修改 `CLAUDE.md` 必須同時在 `artifacts/scripts/drills/prompt_regression_cases.json`(+ `template/` 鏡像)新增對應 PR-* 條目,否則 `guard_contract_validator.py` 的 prompt-contract-sync 耦合檢查會 FAIL;新增條目不得與既有 35 筆之 `must_contain_all` / `must_not_contain_any` 字面衝突。 +- `docs/premortem_rules.md` 修改後須與 `template/docs/premortem_rules.md` SHA-256 全等;`CLAUDE.md` 走 phrase-based 檢查,須人工 diff 確認鏡像同步且未破壞既有 1 行 downstream-terminal 落差。 diff --git a/artifacts/research/TASK-1104.research.md b/artifacts/research/TASK-1104.research.md new file mode 100644 index 0000000..1fd38d4 --- /dev/null +++ b/artifacts/research/TASK-1104.research.md @@ -0,0 +1,59 @@ +# Research: TASK-1104 + +## Metadata +- Task ID: TASK-1104 +- Artifact Type: research +- Owner: Claude +- Status: ready +- Last Updated: 2026-07-07T15:25:00+08:00 + +## Research Questions + +1. repo 內既有的「定期觸發」機制有哪些,新循環應掛哪一軌? +2. 規則退場(archive / relax)的既有先例與記錄格式為何? +3. validator relaxation 案例目前記錄在哪,缺口在哪? +4. 新增 `docs/sop/` 檔與修改 `AGENTS.md` 的同步義務(EXACT_SYNC)範圍為何? +5. `artifacts/improvement/` 下新檔在 `template/` 的鏡像慣例為何? + +## Confirmed Facts + +- repo 既有三種定期觸發形態:(a) GitHub Actions cron 三層(weekly council audit / quarterly threat model / continuous SAST-SCA),見 `docs/security_cadence.md`;(b) PROCESS_LEDGER 條目達 N=10 倍數觸發 architecture-synthesizer(`docs/templates/architecture-synthesizer/TEMPLATE.md:11`:「PROCESS_LEDGER.md 累積條目達 N=10 倍數,或使用者手動觸發」);(c) 純手動的 unified audit(2026-07-03 執行,見 commit 18bfcac 前後之 CHG-001..013 系列)。 +- `artifacts/improvement/PROCESS_LEDGER.md` 為 ledger 本體;寫入條件為「凡於 closure 產出 improvement artifact 之 task 必記一條」(`docs/orchestration-workflow.md` §6);自 2026-04-11 至 2026-05-06 累積約 6-7 筆,成長率約 2-3 筆/月(source: `artifacts/improvement/PROCESS_LEDGER.md`)。 +- 規則退場既有先例:TASK-1050 建立、CHG-013 執行之 template 歸檔,判準為 `real_dispatch_count=0`(`docs/templates/archive/README.md:7`),採「歸檔可復活」模式,復活路徑為 `git mv docs/templates/archive/ docs/templates/`(`docs/subagent_task_templates.md:19` 附近)。 +- Chesterton gate 先例:scope-drift guard Layer-1(Diff Evidence section 該不該必填)經 TASK-955/956 與 commit history 查證均無記錄理由,2026-07-02 裁定 OPEN 不拍板;後續 HC-1 A2(CHG-012)在有記錄理由前提下加嚴為條件必填(source: `docs/schemas/artifact-spec-code.md:79`、`docs/red_team_runbook.md:79` RT-032)。 +- relaxation 規則面記載位於 `.github/memory-bank/workflow-gates.md:16`(CITATION_PATTERN 放寬後僅警告之敘述);案例面(4 案完整清單與根因)目前僅存於 Claude 私人 auto-memory,repo 內無彙整檔(source: Grep `relaxation` 於 repo docs 無彙整命中)。 +- CITATION_PATTERN 與 RESEARCH_SOURCES_ENTRY_PATTERN 之放寬由 TASK-1061 執行,5-branch alternation、雙副本同字面(source: `artifacts/tasks/TASK-1061.task.md`)。 +- docs-spec adapter 為目前唯一明確特化的 Project Adapter,於 `testing / verifying / done` 移除 test requirement 並允許 `NOT_APPLICABLE_BY_ADAPTER`(`docs/schemas/artifact-spec-task.md:68`)。 +- `EXACT_SYNC_FILES` 清單位於 `artifacts/scripts/guard_contract_validator.py:19-78`,含 `AGENTS.md`、`docs/sop/dispatch_implementation.md` 等 4 個既有 SOP 檔、`artifacts/scripts/drills/prompt_regression_cases.json`、以及 `guard_contract_validator.py` 自身——故新增清單條目時 root 與 template 兩份 validator 必須同字面。 +- `template/artifacts/improvement/PROCESS_LEDGER.md` 存在(Glob 確認),即 `artifacts/improvement/` 有 template skeleton 鏡像慣例;該檔不在 EXACT_SYNC_FILES 清單內,允許 root(真實案例)與 template(泛化 skeleton)內容差異。 +- 觸及 guard/EXACT_SYNC 敏感集之 clean-task closure 須含 `## Diff Evidence`,否則 verifying→done fail-closed;dirty worktree closure 走 live check 路徑(`docs/schemas/artifact-spec-code.md:79`)。 + +## Relevant References + +- `docs/security_cadence.md` — 三層 cadence 定義 +- `docs/templates/architecture-synthesizer/TEMPLATE.md` — N=10 觸發軌 +- `docs/templates/archive/README.md` — real_dispatch_count 慣例 +- `.github/memory-bank/workflow-gates.md` — relaxation 規則面記載 +- `artifacts/scripts/guard_contract_validator.py` — EXACT_SYNC_FILES +- `docs/schemas/artifact-spec-code.md` — Diff Evidence 條件必填規則 + +## Sources + +[1] council-forge. "architecture-synthesizer TEMPLATE." docs/templates/architecture-synthesizer/TEMPLATE.md (2026-07-07 retrieved) +[2] council-forge. "guard contract validator EXACT_SYNC_FILES." artifacts/scripts/guard_contract_validator.py (2026-07-07 retrieved) +[3] council-forge. "template archive README." docs/templates/archive/README.md (2026-07-07 retrieved) +[4] council-forge. "code artifact spec (Diff Evidence)." docs/schemas/artifact-spec-code.md (2026-07-07 retrieved) +[5] council-forge. "workflow gates memory bank." .github/memory-bank/workflow-gates.md (2026-07-07 retrieved) + +## Uncertain Items + +- UNVERIFIED: 「available_artifacts mismatch」放寬案例之對應 task 編號與 in-repo artifact 出處尚未定位(僅存於 Claude auto-memory);實作時須以 Grep 查證,查無則該欄位標 `provenance: unrecorded`,不得以記憶補洞。 +- UNVERIFIED: 「generic→docs-spec adapter」案例之原始建立 task(TASK-1058 為首個使用者,但 adapter 特化之建立 task 未逐一回溯);同上處置。 +- UNVERIFIED: `test_guard_contract_validator.py` 是否對 EXACT_SYNC_FILES 清單長度或內容有字面 pin(新增條目可能觸發 pytest fail);實作時先跑 pytest 確認,若有 pin 則同步更新該 test 檔(EXACT_SYNC 成員,雙份同改)。 + +## Constraints For Implementation + +- 新 SOP 掛 N=10 軌只能 cross-ref `docs/templates/architecture-synthesizer/TEMPLATE.md:11` 之既有定義,不得重複定義或修改其語意(單一權威來源)。 +- `EXACT_SYNC_FILES` 新條目必須同時出現在 root 與 `template/artifacts/scripts/guard_contract_validator.py`,且兩檔全文逐位元組相同。 +- RELAXATION_LOG 之 root 版含真實案例、template 版為泛化 skeleton;兩者皆須建立但不進 EXACT_SYNC 清單。 +- ledger 成長率約 2-3 筆/月 → N=10 觸發間隔可能達 3-5 個月;SOP 必須內建手動觸發與退路條款,否則制度空轉。 diff --git a/artifacts/research/TASK-1105.research.md b/artifacts/research/TASK-1105.research.md new file mode 100644 index 0000000..98412c5 --- /dev/null +++ b/artifacts/research/TASK-1105.research.md @@ -0,0 +1,60 @@ +# Research: TASK-1105 + +## Metadata +- Task ID: TASK-1105 +- Artifact Type: research +- Owner: Claude +- Status: ready +- Last Updated: 2026-07-07T21:23:10+08:00 + +## Research Questions + +1. 4 個 wrapper stdin 測試失敗中的 BOM(字面值 `U+FEFF`)由哪一端、以什麼機制引入? +2. 2026-07-07 12:00-15:00 之間是否真有 machine 層環境變動? +3. skipped 2 → 19(+17)的 reason 為何,與 BOM 根因是否同源? + +## Confirmed Facts + +- **BOM 為位元組層前綴、失敗機制為 cp950 吞字**:fake exe 之 python 腳本以文字模式 `sys.stdin.read()` 讀入(`artifacts/scripts/conftest.py:99`),本機 python 3.14.3 之 `sys.stdin.encoding` 為 cp950(utf8_mode=0,2026-07-07 實測)。stdin 位元組為 `EF BB BF` + payload;cp950(Big5 DBCS)把 `EF BB` 結成一個雙位元組字、`BF` 再與 payload 首位元組(`x`=0x78)結成第二個雙位元組字而**吞掉第一個字元**——脫離 pytest 之手動重演(scratchpad manual_repro.py,複刻 `artifacts/scripts/conftest.py:75-128` fake exe 機制)實測:stdin_len=102、x_count=**99**(prompt 為 100 x)、`prompt in stdin_seen` = **False**。pytest traceback 顯示之「`U+FEFF` + 100 x」為輸出層多重轉碼污染之誤導,不可作為機制證據。 +- **conftest 在 Windows 優先挑 Windows PowerShell 5.1**:`shutil.which("powershell.exe") or shutil.which("pwsh")`(`artifacts/scripts/conftest.py:20`),wrapper 以 `-NoProfile -File` 執行(`conftest.py:162-165`)。 +- **最小重現證實 BOM 來自 5.1 的 native stdin pipe**:同一條「ps1 → .cmd → python bytedump」鏈路(複製 `artifacts/scripts/conftest.py:162` 之 `-NoProfile -File` 呼叫形態),powershell.exe 5.1 得 `b'\xef\xbb\xbfxxxxx'`;pwsh 7.6.3 得 `b'xxxxx\r\n'`(2026-07-07 本機實測,工具檔於 session scratchpad)。 +- **BOM 機制**:本機系統 codepage 為 Big5(`HKLM:\SYSTEM\CurrentControlSet\Control\Nls\CodePage` ACP=950、OEMCP=950,「Beta: Use Unicode UTF-8」未開啟),但 5.1 於 `-File` 內之 `[Console]::OutputEncoding` 為 UTF-8 preamble=3——自呼叫端 console 的 codepage 65001 繼承(Claude Code PowerShell tool 之 console 為 UTF-8);5.1 對 native stdin 之 StreamWriter 首寫時吐出該 encoding 之 preamble(BOM)。`$OutputEncoding` 變數本身仍為 US-ASCII preamble=0(enc_probe.ps1 實測),故 BOM 非來自 `$OutputEncoding`,而是 5.1 在 CP65001 console 下之 native pipe 行為(呼叫形態 see `artifacts/scripts/conftest.py:162`)。 +- **wrapper 未設定任何 encoding**:Grep `OutputEncoding|UTF8Encoding|InputEncoding` 於 `artifacts/scripts/Invoke-*.ps1` 無命中;wrapper 以 `$Prompt | & $Executable $processArgs` 管道(`Invoke-GeminiAgent.ps1:340`)。 +- **無時間性機器漂移——為執行語境差異**:同一時刻、同一 HEAD,Git Bash 語境(Claude Code Bash tool)跑同 4 測試 `4 passed in 4.70s`,且 which 查得 /usr/bin/bash 與 /usr/bin/gpg;PowerShell 語境 shutil.which 得 bash/gpg 皆 None(2026-07-07 實測;shell 選擇邏輯 see `artifacts/scripts/conftest.py:20`)。 +- **19 skips 全為工具可用性**:pytest `-rs`(PowerShell 語境)列 13 個 `gpg unavailable`(`test_publish_release_verify.py:222,257`、`test_release_signing.py:171,189,212,248,267[6],283`)+ 6 個 `bash required`(`test_release_signing.py:306[5],334`)。Git Bash 語境下 bash/gpg 皆在 `/usr/bin/` → 該 17 項會執行,僅餘 2 個原生 skip——與 TASK-1103 記錄之 `2037 passed / 2 skipped / 0 failed` 完全吻合。 +- **兩數據集總數一致**:2037+2 = 2016+19+4 = 2039,無測試增減;差異全由語境解釋(source: `artifacts/verify/TASK-1104.verify.md` §Evidence 與 `artifacts/verify/TASK-1103.verify.md` AC-8)。 +- **TASK-1104 verify §AC-13 之「12:00-15:00 環境漂移」敘述經本查證為誤判**:HEAD 乾淨 worktree 對照組(`artifacts/verify/TASK-1104.verify.md` §Evidence)亦以 PowerShell 語境執行,故只證明失敗與 TASK-1104 diff 無關,不構成時間性漂移證據。 +- **生產面影響評估**:Claude Code PowerShell tool 與 wrapper 實際 dispatch 皆走 pwsh 7(無 BOM;TASK-1104 dispatch 之 Codex 收到完整乾淨 prompt,見 `artifacts/code/TASK-1104.code.md` Mapping To Plan);僅當有人以 Windows PowerShell 5.1 於 UTF-8 console 下執行 wrapper(pipe 點為 `artifacts/scripts/Invoke-GeminiAgent.ps1:340`)時,真實 CLI 才會收到 BOM 前綴 prompt(LLM 端多半無感,但屬可根治的鏈路髒污)。另一併存之生產風險:5.1 之 `$OutputEncoding` 預設 US-ASCII,非 ASCII prompt(如中文 dispatch prompt)經 5.1 執行 wrapper 時會被 mangle 成 `?`——(c) 路線之 UTF-8 no-BOM 顯式設定同時根治 BOM 與此 mangling。 + +- **【2026-07-08 補充】(c) 路線之技術前提經實作後實證推翻——5.1 的 BOM 無法由 script 內 encoding 設定消除**:wrapper 設定 `$OutputEncoding = UTF8Encoding($false)` 後,manual_repro 重跑仍得 x_count=99(BOM 仍在)。A/B/C/E 對照實驗(同一 5.1 CP65001 console、同 dump 鏈):A `$OutputEncoding` 賦值→BOM 仍在;B `[Console]::OutputEncoding` 賦值→BOM 仍在;C `$global:OutputEncoding` 賦值→BOM 仍在;E `chcp 437`→**BOM 消失**(LEN 105→102)。結論:5.1 native stdin pipe writer 直接以 console output codepage 取 encoding(CP=65001 之 encoding 物件帶 preamble),任何 PowerShell 變數/屬性皆不可控,唯一 script 內 lever 為 `chcp`(但 console-wide 副作用 + 非 65001 codepage 會 mangle 中文 prompt,不可採)。Codex 實作後 4 測試轉綠之實際成因為 conftest 之 UTF-8 顯式解碼(消除 cp950 吞字;BOM 前綴在 substring 斷言下無害),非 wrapper 設定之效(source: 實驗腳本於 session scratchpad;呼叫形態 see `artifacts/scripts/conftest.py:162`)。 +- **【2026-07-08 補充】5.1 語境之根本限制**:CP65001 → BOM 但 UTF-8 完整;chcp 437/950 → 無 BOM 但非 Big5/CP437 可表示字元 mangle。5.1 下「無 BOM + 完整 UTF-8」不存在 script 內組合;生產 dispatch 走 pwsh 7 天然兩者兼得(source: 上列 A-E 實驗與 `artifacts/plans/TASK-1105.plan.md` R1 之 Detection 路徑)。 + +## Relevant References + +- `artifacts/scripts/conftest.py` — `_powershell_exe()` shell 選擇與 fake exe stdin 錄製機制 +- `artifacts/scripts/Invoke-GeminiAgent.ps1:323-340` / `Invoke-CodexAgent.ps1` — TASK-1062 stdin pipe 實作(無 encoding 設定) +- `artifacts/verify/TASK-1104.verify.md` §Evidence — 兩組 pytest 數據出處(PowerShell 語境) +- `artifacts/tasks/TASK-1103.task.md` 系列 — 對照 baseline(Bash 語境)之出處 task + +## Sources + +[1] council-forge. "conftest PowerShell selection and fake exe stdin capture." artifacts/scripts/conftest.py (2026-07-07 retrieved) +[2] council-forge. "Gemini wrapper stdin pipe (TASK-1062 Bug B fix)." artifacts/scripts/Invoke-GeminiAgent.ps1 (2026-07-07 retrieved) +[3] council-forge. "TASK-1104 verify evidence (PowerShell-context pytest data)." artifacts/verify/TASK-1104.verify.md (2026-07-07 retrieved) +[4] Microsoft. "about_Character_Encoding — Windows PowerShell vs PowerShell 7 encoding defaults." https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_character_encoding (2026-07-07 retrieved) + +## Uncertain Items + +- UNVERIFIED: TASK-1103 session 之 pytest 確切透過哪個 tool 執行(該 session 記錄不在本 session context);「Bash 語境」為與其 2/0 數據完全吻合之推斷,非直接觀測。 +- UNVERIFIED: 5.1 native pipe 在 CP65001 console 下吐 BOM 之確切內部路徑(`[Console]::OutputEncoding` 繼承 vs 其他初始化);已有可重現之黑箱證據(bytedump 實測),內部機制標註為推定。(cp950 吞字機制則非推定——manual_repro 之 102/99 計數與 DBCS 行為精確吻合,列 Confirmed Facts。) + +## Constraints For Implementation + +- 修復不得回退 TASK-1062 之 stdin pipe 語意(threshold=0、恆走 stdin)。 +- 修復路線候選(供 plan 決策): + - (a) conftest `_powershell_exe()` 改優先 pwsh:消除測試語境差,但 5.1 相容性自此不再被測。 + - (b) 測試斷言 BOM 容錯(`stdin_seen.lstrip('\ufeff')` 或等價):兩 shell 皆可測,但等於接受 BOM 進入真實 CLI。 + - (c) wrapper 於 pipe 前明設 `$OutputEncoding = [System.Text.UTF8Encoding]::new($false)`:於 wrapper 層根治,5.1/7 語境與生產 dispatch 全乾淨,並同時消除 5.1 ASCII mangling(推薦主修;user 2026-07-07 已裁採 (c) + 執行慣例文件化,(b) 明確不採——wrapper 修復後既有嚴格斷言即為 (c) 之回歸守衛,lstrip 容錯反而遮蔽回歸)。 + - (c-2) 次要強化:conftest fake script 之 stdin 讀取改為 `sys.stdin.buffer.read().decode('utf-8')`,消除 locale(cp950)解碼依賴——未來含非 ASCII 之 prompt 測試在任何 locale 下行為一致;此為消除歧義,非遮蔽回歸。 + - 環境側「還原」不適用:無事物損壞;bash/gpg 之 17 skip 為 PowerShell 語境天然缺工具,屬執行慣例問題(pytest 完整 baseline 應於 bash 語境跑),不建議把 `Git\usr\bin` 加入全域 PATH(unix 工具 shadow 風險)。 +- TASK-1104 verify §AC-13 之誤判敘述應以既有先例(TASK-1058 §Post-Closure Findings append)方式更正,不改寫原文。 diff --git a/artifacts/research/TASK-1106.research.md b/artifacts/research/TASK-1106.research.md new file mode 100644 index 0000000..c08ef28 --- /dev/null +++ b/artifacts/research/TASK-1106.research.md @@ -0,0 +1,52 @@ +# Research: TASK-1106 + +## Metadata +- Task ID: TASK-1106 +- Artifact Type: research +- Owner: Claude +- Status: ready +- Last Updated: 2026-07-08T13:05:00+08:00 + +## Research Questions + +1. 三個候選名詞(Goodhart / Normalization of Deviance / Swiss Cheese)在 repo 內各有什麼實證案例與既有機制可對應? +2. Governance Lenses 表的既有紀律與擴充形態為何?介紹文件哪裡需要更新? +3. 觸及檔案的同步義務(EXACT_SYNC / README contract)範圍為何? + +## Confirmed Facts + +- **Governance Lenses 表**位於 `docs/orchestration.md:149-160`,現有 6 視角(Boundary Objects / RACI / PDCA / TAO / Double-Loop / SECI),欄位為「視角|所管問題|對應現有機制|文件落點」;表頭紀律明文「不另立分層、不另建 schema、不另設階段」(`docs/orchestration.md:151`)。 +- **同構名詞拒絕先例**:「明確拒絕:OODA」段(`docs/orchestration.md:162-172`)以同構對照 + 不並存宣告 + 禁止後續 task 翻案之三段形態記錄;Campbell's Law(與 Goodhart 同構)之拒絕記錄可依此壓縮形態。 +- **Goodhart 實證**:`artifacts/improvement/RELAXATION_LOG.md` 四案共同根因為 caller「機械式 schema-pleasing 過驗」(validator regex 成為優化目標而非品質代理);既有處置機制「累積 ≥3 → architect review」已在該檔 §Rules。 +- **Normalization of Deviance 實證**:TASK-1104 與 TASK-1105 兩次 Codex dispatch 之 post-dispatch write-scope/RACI 違規清單均經人工 review 後接受(source: `artifacts/verify/TASK-1104.verify.md` §Wrapper Post-Dispatch Write-Scope 警告之人工 Review、`artifacts/verify/TASK-1105.verify.md` §Dispatch 異常記錄);`docs/sop/rule_lifecycle_audit.md` Step 1 已列「同一例外反覆出現」為候選訊號,但無強制裁決條款——detect-and-accept 可無限延續。 +- **Swiss Cheese 實證**:TASK-1104 verify 之 literal U+FEFF 於寫入當時未被攔(pytest 跑於 verify 寫入前——時序孔洞),於 TASK-1105 被另一層 `test_prompt_injection_scan.py`(PI-HIDDEN-UNICODE)攔下(source: `artifacts/verify/TASK-1105.verify.md`、`artifacts/verify/TASK-1104.verify.md` §Post-Closure Findings 第 2 條);guard 疊層清單見 `.github/memory-bank/workflow-gates.md`。 +- **介紹文件現況**:`README.md:188-195` 有 `### Two-Layer Governance (PDCA × TAO/ReAct)` 段但無 lenses 敘述;README.zh-TW.md、OBSIDIAN.md、BOOTSTRAP_PROMPT.md 對「治理視角/Governance Lens/OODA」Grep 均無命中——介紹文件更新錨點唯一:README 兩語言版之 Two-Layer Governance 段。 +- **同步義務**:`docs/orchestration.md`、`docs/sop/dispatch_implementation.md`、`docs/sop/rule_lifecycle_audit.md`、`artifacts/scripts/drills/prompt_regression_cases.json` 皆為 EXACT_SYNC_FILES 成員(`artifacts/scripts/guard_contract_validator.py:19-78`);README 由 `--check-readme` contract 承載。 +- **rule_lifecycle_audit.md 現況**:50 raw 行(非空行 34),距 150 上限餘裕充足(source: `docs/sop/rule_lifecycle_audit.md`)。 +- **fallback-tier 不可信實證**:TASK-1105 dispatch 之 gpt-5.4-mini 於 shell 封鎖下未驗證覆寫 code artifact 並引用 fabricated GitHub URL(source: `artifacts/code/TASK-1105.code.md` §Post-Dispatch Amendment,Bug-B3)。 + +## Relevant References + +- `docs/orchestration.md` §2.8 — lenses 表與 OODA 拒絕段 +- `artifacts/improvement/RELAXATION_LOG.md` — Goodhart 機制落點 +- `docs/sop/rule_lifecycle_audit.md` — deviance 條款與 McNamara 防呆目標檔 +- `docs/sop/dispatch_implementation.md` — fallback-tier 條文目標檔 +- `README.md` / `README.zh-TW.md` — 介紹文件錨點 + +## Sources + +[1] council-forge. "Governance Lenses table and OODA rejection." docs/orchestration.md (2026-07-08 retrieved) +[2] council-forge. "Relaxation log (Goodhart evidence)." artifacts/improvement/RELAXATION_LOG.md (2026-07-08 retrieved) +[3] council-forge. "TASK-1105 verify (deviance/Swiss-cheese/Bug-B3 evidence)." artifacts/verify/TASK-1105.verify.md (2026-07-08 retrieved) +[4] council-forge. "EXACT_SYNC_FILES membership." artifacts/scripts/guard_contract_validator.py (2026-07-08 retrieved) + +## Uncertain Items + +- UNVERIFIED: `README.zh-TW.md` 是否存在與 `README.md:188` 完全對應之 Two-Layer Governance 段(僅 Grep 確認無 lenses 關鍵詞,未逐段核對結構);實作時先讀該檔定位,若無對應段則於等價位置補入並於 code artifact 記錄。 + +## Constraints For Implementation + +- 三個新 lens 列之「對應現有機制」必須指向真實存在的機制字面(RELAXATION_LOG §Rules 升級條款、rule lifecycle audit 之 deviance 條款[本任務同批新增,表列與條款須同 commit 落地避免懸空引用]、workflow-gates guard 疊層 + improvement Why Not Prevented)。 +- Campbell 拒絕記錄 2-3 行,置於 OODA 段之後,沿用「同構、不並存、不得引為翻案範本」語式。 +- deviance 條款之閾值採 3(與 RELAXATION_LOG ≥3 升級條款對齊,避免第二套數字)。 +- 全部修改為既有檔內之句子/表列增量;任何新檔需求即超出本任務 scope。 diff --git a/artifacts/research/TASK-1107.research.md b/artifacts/research/TASK-1107.research.md new file mode 100644 index 0000000..aa8b1e6 --- /dev/null +++ b/artifacts/research/TASK-1107.research.md @@ -0,0 +1,56 @@ +# Research: TASK-1107 + +## Metadata +- Task ID: TASK-1107 +- Artifact Type: research +- Owner: Claude +- Status: ready +- Last Updated: 2026-07-17T10:45:00+08:00 + +## Research Questions + +1. bug_002(CHG-012 gate 之 `None (理由)` 繞過)在現行 `guard_status_validator.py` 中是否仍然存在?確切的判斷邏輯與繞過路徑為何? +2. 記憶中提出的修法(`de = diff_evidence.strip().lower()` 後改判 `sensitive_hits and (de.startswith(("none", "n/a")) or "evidence type:" not in de)`)是否對現行合法 Evidence Type 格式語意完備(不會誤傷合法證據)? +3. bug_001(RACI 單一真源互指成環)在現行 `docs/subagent_roles.md` 與 `docs/raci-matrix.md` 中是否仍然存在?兩檔現行文字的確切互指方向為何? +4. `docs/subagent_roles.md` 是否確實在 `EXACT_SYNC_FILES` 列表內(memory 註記 ultrareview reasoning 對此有一處錯誤陳述,需獨立核實)? +5. `template/` 側是否有對應的四個檔案需同步修改? + +## Confirmed Facts + +- **bug_002 現狀確認**:`artifacts/scripts/guard_status_validator.py:2250` 現行邏輯為 `if sensitive_hits and diff_evidence.lower() in ("", "none", "n/a"):`,此為 exact-tuple 比對;任何不完全等於這三個字面值的字串(例如 `None (this task was completed via alternate verification)`)都會使條件為 `False`,導致 `errors` 不被附加,即使該 closure 觸及 sensitive 檔案且未提供任何可重播的 Diff Evidence,也會被判定為合法(`artifacts/scripts/guard_status_validator.py:2244-2260`)。 +- **既有夾帶文字繞過實證**:`artifacts/code/TASK-956.code.md:69` 之 `None (this task was completed...)` 屬此繞過模式的真實既存範例(`artifacts/code/TASK-956.code.md:69`)。 +- **修法語意完備性驗證(含 §12 獨立質疑後之修正)**:兩種現行合法 `Diff Evidence` 格式(`commit-range`、`github-pr`)皆以 `- Evidence Type: ` 作為固定起始欄位,於三處測試 fixture 中一致出現:`test_guard_status_validator_artifacts.py:349`、`test_guard_status_validator_artifacts.py:369`、`test_guard_status_validator_artifacts.py:2828`(Phase 6 commit-range/github-pr scope drift fixture);`test_guard_status_validator_artifacts.py:2915` 之 `TestCleanTaskDiffEvidenceCHG012.test_sensitive_with_commit_range_evidence_passes` 亦以 `- Evidence Type: commit-range\n` 開頭建構合法證據。**記憶原提出之修法(第二 clause `"evidence type:" not in de` 原始子字串比對)經 plan 階段 §12 獨立 premortem 質疑發現仍有繞過路徑**:一段不以 `bullet (- Key: Value)` 格式書寫、但文字中任意位置含有 `evidence type:` 字樣且不以 `none`/`n/a` 開頭的自由文字(例如 `"No Evidence Type: applicable -- verified via manual code review instead of diff replay."`),會被原判斷式誤判為已提供合法證據(已用 Python 直接執行覆現)。**最終採用之修法改為重用既有 `parse_diff_evidence()`(`guard_status_validator.py:612`)+ `DIFF_EVIDENCE_SUPPORTED_TYPES`(`guard_status_validator.py:160`,值為 `{"commit-range", "github-pr"}`)結構化解析**:`parse_diff_evidence` 底層呼叫的 `parse_key_value_section`(`guard_helpers/parsers.py:43`)只接受以 `- Key: Value` bullet 起始的行,非結構化自由文字無法被解析出任何 key,故 `evidence.get("evidence type", "")` 會落空字串、不在 `DIFF_EVIDENCE_SUPPORTED_TYPES` 內而正確被攔下;已用 Python 直接執行驗證此修正版對繞過文字攔截、對兩種合法格式放行,且此作法為既有已驗證函式的重用,不新增第二套判斷邏輯。詳見 `artifacts/plans/TASK-1107.plan.md` `## Risks` R1/R6 與 `### Independent Premortem Challenge`。 +- **現行 CHG-012 測試覆蓋範圍**:`test_guard_status_validator_artifacts.py:2840` 之 `TestCleanTaskDiffEvidenceCHG012` 類別現有 5 個 test method(`test_sensitive_no_evidence_transition_fails`、`test_sensitive_with_commit_range_evidence_passes`、`test_non_sensitive_transition_unchanged`、`test_sensitive_no_evidence_revalidation_flag_false_passes`、`test_is_sensitive_guard_path`),皆未涵蓋「夾帶文字的 `None (...)` 繞過」case(`test_guard_status_validator_artifacts.py:2840-2934` 逐一核對,無此 case)。 +- **bug_001 現狀確認**:`docs/subagent_roles.md:56` 現行句為「RACI 與 agent capability 矩陣已拆分至 [docs/raci-matrix.md](raci-matrix.md)(原 `docs/subagent_roles.md` §2)。」;`docs/raci-matrix.md:3` 現行句為「本檔之 §2 角色總表已回歸單一真源 [docs/subagent_roles.md](subagent_roles.md) §2;本檔僅保留下列 §2.1 TAO Trace 必要程度表(此檔獨有)。」,`docs/raci-matrix.md:7` 另有「RACI 與 agent capability 矩陣之單一真源為 [docs/subagent_roles.md](subagent_roles.md) §2「角色總表(索引)」(hybrid-sync guard 綁定該檔 ↔ `workflow_constants.RACI_MATRIX`)。本檔不再重複該表。」——兩檔現行文字互指對方為真源(`subagent_roles.md` 說已拆分至 `raci-matrix.md`;`raci-matrix.md` 說單一真源已回歸 `subagent_roles.md`),形成循環引用,`subagent_roles.md:56` 為過時未更新的一側。 +- **EXACT_SYNC 成員資格獨立核實**:以 `guard_contract_validator.EXACT_SYNC_FILES` 直接查值(非讀 reasoning 文字),確認列表含 `artifacts/scripts/guard_status_validator.py`、`artifacts/scripts/test_guard_status_validator_artifacts.py`、`artifacts/scripts/test_guard_status_validator_core.py`、`artifacts/scripts/test_guard_status_validator_state.py`、`docs/subagent_roles.md` 共 5 個目標相關項目——`docs/subagent_roles.md` 確實在列表內,驗證 memory 對「ultrareview reasoning 誤稱其不在 EXACT_SYNC」的註記為真(`artifacts/scripts/guard_contract_validator.py` EXACT_SYNC_FILES 常數,2026-07-17 直接以 Python import 查值)。`docs/raci-matrix.md` 不在此列表內。 +- **template/ 鏡射檔案存在性確認**:`template/artifacts/scripts/guard_status_validator.py`、`template/artifacts/scripts/test_guard_status_validator_artifacts.py`、`template/docs/subagent_roles.md`、`template/docs/raci-matrix.md` 四檔皆存在(`ls` 確認四路徑皆命中,2026-07-17)。 +- **PR #50 現況**:`gh pr view 50` 回報 `state: OPEN`、`headRefName: manifest-exec-unified-audit-2026-07-03`(與本 repo 當前分支相同),確認「追加 commit 到現有分支即可更新 PR #50」之假設成立,不需另開分支或 PR(`gh api repos/arcobaleno64/council-forge/pulls/50`,2026-07-17 retrieved)。 + +## Relevant References + +- `artifacts/scripts/guard_status_validator.py:2101-2260` — `is_sensitive_guard_path` 與 CHG-012 判斷邏輯 +- `artifacts/scripts/test_guard_status_validator_artifacts.py:2840-2934` — 既有 `TestCleanTaskDiffEvidenceCHG012` 測試類別 +- `docs/subagent_roles.md:50-58` — RACI 拆分宣告句(待修) +- `docs/raci-matrix.md:1-10` — RACI 單一真源宣告句(現行正確方向,作為對齊基準) +- `artifacts/scripts/guard_contract_validator.py` — `EXACT_SYNC_FILES` 常數定義 + +## Sources + +[1] council-forge. "CHG-012 gate 判斷邏輯與 is_sensitive_guard_path。" artifacts/scripts/guard_status_validator.py (2026-07-17 retrieved) +[2] council-forge. "既有 CHG-012 測試覆蓋範圍。" artifacts/scripts/test_guard_status_validator_artifacts.py (2026-07-17 retrieved) +[3] council-forge. "RACI 拆分宣告句(subagent_roles 側)。" docs/subagent_roles.md (2026-07-17 retrieved) +[4] council-forge. "RACI 單一真源宣告句(raci-matrix 側)。" docs/raci-matrix.md (2026-07-17 retrieved) +[5] council-forge. "EXACT_SYNC_FILES 成員清單。" artifacts/scripts/guard_contract_validator.py (2026-07-17 retrieved) +[6] arcobaleno64/council-forge. "PR #50 現況(OPEN, headRefName=manifest-exec-unified-audit-2026-07-03)。" https://github.com/arcobaleno64/council-forge/pull/50 (2026-07-17 retrieved) + +## Uncertain Items + +None + +## Constraints For Implementation + +- CHG-012 修法須改用結構化解析:`evidence = parse_diff_evidence(code_text)`、`evidence_type = (evidence or {}).get("evidence type", "").strip().lower()`、`if sensitive_hits and evidence_type not in DIFF_EVIDENCE_SUPPORTED_TYPES:`(取代原記憶提出之字串子句寫法,理由見 Confirmed Facts 第 3 條與 `artifacts/plans/TASK-1107.plan.md` R6)。 +- 新增測試須放入既有 `TestCleanTaskDiffEvidenceCHG012` 類別(`test_guard_status_validator_artifacts.py:2840` 起),沿用該類別既有的 `_tree` / `_chg012_errors` helper,不另建平行測試基礎設施;須同時覆蓋「`None (理由)` 夾帶文字」與「R6 之非結構化自由文字繞過」兩類 case。 +- `docs/subagent_roles.md:56` 之修法用語需向 `docs/raci-matrix.md:3,7` 現行句對齊(後者已是正確方向),不得反向修改 `raci-matrix.md`。 +- 四個 EXACT_SYNC 相關檔案(`guard_status_validator.py` + 三個 test 檔 + `subagent_roles.md`)之 root/template 版本修改後須逐位元組相同;`raci-matrix.md`(非 EXACT_SYNC 成員)僅需語意同步,若本 task 未觸及其文字內容則不強制改動 template 側。 +- 修復完成後之 commit 直接 push 至 `manifest-exec-unified-audit-2026-07-03`,PR #50 會自動反映新 commit,不需額外的 PR 操作。 diff --git a/artifacts/research/TASK-1108.research.md b/artifacts/research/TASK-1108.research.md new file mode 100644 index 0000000..7288b50 --- /dev/null +++ b/artifacts/research/TASK-1108.research.md @@ -0,0 +1,63 @@ +# Research: TASK-1108 + +## Metadata +- Task ID: TASK-1108 +- Artifact Type: research +- Owner: Claude +- Status: ready +- Last Updated: 2026-07-10T15:10:00+08:00 + +## Research Questions + +1. Governance Lenses 表現況與擴充紀律為何?6 個新視角各自的既有機制落點在哪? +2. Separation of Duties 是否已被 TASK-1106 明文裁決不掛牌?該裁決之精確理由與可推翻條件為何? +3. mission 要求之「ADR template prompts」是否有作用中的目標檔案?archived ADR template 之歸檔理由是否構成 Chesterton's Fence? +4. Goodhart's Law 三項規則(單一指標禁令、firing_count=0 不等於無用、eval/intervention telemetry 分離)在既有文件中各自的覆蓋狀態為何? +5. 觸及檔案的 EXACT_SYNC 與 PR pin 同步義務範圍為何? + +## Confirmed Facts + +- **Governance Lenses 表**位於 `docs/orchestration.md:149-179`,現有 9 視角(Boundary Objects / RACI / PDCA / TAO/ReAct / Double-Loop Learning / SECI / Goodhart's Law / Normalization of Deviance / Swiss Cheese Model);表頭紀律「不另立分層、不另建 schema、不另設階段」(`docs/orchestration.md:151`)。表後另有「明確拒絕:OODA」(:165-175)與「明確拒絕:Campbell's Law」(:177-179)兩段,皆為「同構論證 + 不採宣告 + 禁止翻案」三段形態。 +- **Separation of Duties 之既有裁決**:`artifacts/tasks/TASK-1106.task.md:64`(Out of Scope)——「顯性化評估中列為『已隱性覆蓋』之名詞(Defense in Depth、Poka-yoke、SoD 等——維持現狀不掛名牌)」。此為 TASK-1106 之明確、有記錄之裁決,構成本任務新增 SoD 具名 lens 之 Chesterton's Fence。使用者於本任務 Intake 階段(2026-07-10)以 AskUserQuestion 確認推翻此裁決,理由:mission 提供具體可落地規則(author≠sole reviewer;AI 產生之 guard/schema/CI/相容契約變更需獨立審查步驟),可掛靠既有 Council Reviewer(`docs/subagent_roles.md:296-303` §5.1.3,3 個獨立 Codex model 產出 review notes)與 premortem §12 獨立質疑(`docs/premortem_rules.md:202-243`,撰寫 plan 之 agent 不可自問自答)之上,屬「賦予既有機制顯性名稱」而非「新增機制」。 +- **ADR template 之歸檔**:`docs/templates/archive/README.md:7`——`adr`/`debug`/`rtm`/`srs` 四範本由 TASK-1050(2026-05-06)建立,因建立後約 2 個月 `real_dispatch_count=0` 而歸檔以降低 `discover_templates.py` 掃描雜訊;歸檔為 revivable(`git mv docs/templates/archive/ docs/templates/`),非刪除。目前作用中之決策機制為 `artifacts/decisions/TASK-XXX.decision.md`(`docs/schemas/artifact-spec-decision.md:9-56`),其唯一既有之條件式可選欄位群為 `## Guard Exception`(:48-56,四欄位:Exception Type / Scope Files / Justification / Override_Reason)。本任務判定:無新使用證據可推翻歸檔理由,故不復活 archived ADR;改在作用中的 decision schema 比照 `## Guard Exception` 慣例新增另一個條件式可選 block。 +- **Goodhart 規則 1(no governance decision may be made solely from one metric)**——已被 `docs/sop/rule_lifecycle_audit.md:21` 覆蓋:「使用數據只產生候選,不產生裁決……裁決一律過 Step 2 之 provenance 檢查」,即候選訊號(單一指標)與裁決(跨兩步驟)已結構性分離。**無需新增**。 +- **Goodhart 規則 2(firing_count = 0 must not imply useless)**——已被 `docs/sop/rule_lifecycle_audit.md:21` 同句「零使用不等於零價值(保險機制平時即零觸發)」逐字覆蓋。**無需新增**。 +- **Goodhart 規則 3(evaluation telemetry and intervention telemetry must remain distinct)**——**未見於任何既有文件**。Repo 內兩種既有、天然分離但未明文宣告分離義務之來源:`artifacts/scripts/experiments/guard_calibration_matrix.py`(evaluation telemetry,量測 validator FP/FN,跑於暫存副本、非 production traffic)與 `artifacts/improvement/RELAXATION_LOG.md`(intervention telemetry,記錄實際放寬案例)。此為唯一需要新增文字的 Goodhart 子項,落點:`RELAXATION_LOG.md` §Rules。 +- **「Guard」在本 repo 之語意**:確認為 dev-workflow validator(`guard_status_validator.py`、`guard_contract_validator.py`、`scope_guard.py` 等 Python 腳本,檢查 artifact schema、write-scope、EXACT_SYNC),並非部署中對外運作、對即時流量計 `firing_count` 的 AI safety guard 產品。`guard_calibration_matrix.py` 之 warning/failure 區分純以 `pass`/`fail` return code 呈現(無 nightly report、無 telemetry rollup 腳本)。 +- **EXACT_SYNC_FILES**(`artifacts/scripts/guard_contract_validator.py:19-79`)成員含本任務將觸及之 `docs/orchestration.md`、`docs/subagent_roles.md`、`docs/sop/rule_lifecycle_audit.md`、`artifacts/scripts/drills/prompt_regression_cases.json`;**不含** `docs/schemas/artifact-spec-decision.md` 與 `artifacts/improvement/RELAXATION_LOG.md`(此二檔改動不需 template 鏡像)。`README.md`/`README.zh-TW.md` 由 `--check-readme` 另一契約承載,非 EXACT_SYNC_FILES 成員。 +- **PR-038 pin 內容**(`artifacts/scripts/drills/prompt_regression_cases.json`,直讀確認,非 bash 終端顯示):對 `docs/orchestration.md` 要求同時含 `"Goodhart's Law"`、`"Normalization of Deviance"`、`"Swiss Cheese Model"`、`"明確不採 Campbell's Law"`;對 `docs/sop/rule_lifecycle_audit.md` 要求含 `"不得停留於 detect-and-accept"`。本任務新增文字皆為既有段落**之後**的附加內容,不移除、不改寫上述任一子字串,故不破壞 PR-038。 +- **README 現況**:`README.md:199` 與 `README.zh-TW.md:199` 皆為同一句「兩層之上另有一組 governance lenses……」,列出 9 個既有名詞,句尾「不新增分層、schema 或 gate」。兩檔同一行號、句構對稱。 +- **`docs/sop/rule_lifecycle_audit.md` 現況**:53 raw 行(含空行),距 TASK-1104 訂定之 150 行上限有 97 行餘裕。 + +## Relevant References + +- `docs/orchestration.md:149-179` — Governance Lenses 表 + OODA/Campbell 拒絕段 +- `artifacts/tasks/TASK-1106.task.md:64` — SoD「隱性覆蓋不掛牌」原始裁決 +- `docs/templates/archive/README.md:7` — ADR template 歸檔理由 +- `docs/schemas/artifact-spec-decision.md:48-56` — `## Guard Exception` 條件式可選欄位群先例 +- `docs/sop/rule_lifecycle_audit.md:16-21` — Occam Pass 候選/裁決分離、零使用不等於零價值 +- `artifacts/improvement/RELAXATION_LOG.md` — intervention telemetry 落點 +- `artifacts/scripts/experiments/guard_calibration_matrix.py` — evaluation telemetry 落點 +- `docs/subagent_roles.md:27-41,296-303` — RACI / Council Reviewer(SoD、Least Privilege 對應機制) +- `artifacts/scripts/guard_contract_validator.py:19-79` — EXACT_SYNC_FILES + +## Sources + +[1] council-forge. "Governance Lenses table and rejection sections." docs/orchestration.md (2026-07-10 retrieved) +[2] council-forge. "TASK-1106 task artifact, Out of Scope section (line 64)." artifacts/tasks/TASK-1106.task.md (2026-07-10 retrieved) +[3] council-forge. "Archived template rationale." docs/templates/archive/README.md (2026-07-10 retrieved) +[4] council-forge. "Decision artifact schema, Guard Exception precedent." docs/schemas/artifact-spec-decision.md (2026-07-10 retrieved) +[5] council-forge. "Rule lifecycle audit SOP." docs/sop/rule_lifecycle_audit.md (2026-07-10 retrieved) +[6] council-forge. "EXACT_SYNC_FILES membership (lines 19-79)." artifacts/scripts/guard_contract_validator.py (2026-07-10 retrieved) +[7] council-forge. "PR-038 regression pin, read via python with explicit UTF-8 stdout wrapper to avoid terminal mojibake." artifacts/scripts/drills/prompt_regression_cases.json (2026-07-10 retrieved) + +## Uncertain Items + +- UNVERIFIED: 唯一觀察項延續 TASK-1106 verify 之遺留——`Documents/Code/.git` 空目錄殘骸來源仍未查明,本任務 pytest 執行前後需檢查是否再現(非本任務 scope,僅延續觀察義務)。 + +## Constraints For Implementation + +- 所有新增文字為既有檔案內之句子/表列/條件式可選 block 增量;不新增檔案、不新增 validator 邏輯。 +- 新增 6 個 lens 列之「對應現有機制」欄位必須引用真實存在之機制字面,不得懸空引用尚未落地之條文(若條文與表列同批新增,需同一 commit 內落地,比照 TASK-1106 對 Deviance 條款之作法)。 +- Policy Engine 拒絕段沿用 OODA/Campbell 形態:同構或直接論證 + 不採宣告 + 不得引為翻案範本,控制在 2-4 行。 +- decision schema 新增欄位之 enum 值含 `unknown`,且必須明文「unknown 不等於安全/低風險/零風險」(mission hard constraint 直接對應)。 diff --git a/artifacts/research/TASK-1109.research.md b/artifacts/research/TASK-1109.research.md new file mode 100644 index 0000000..a552a58 --- /dev/null +++ b/artifacts/research/TASK-1109.research.md @@ -0,0 +1,54 @@ +# Research: TASK-1109 + +## Metadata +- Task ID: TASK-1109 +- Artifact Type: research +- Owner: Claude +- Status: ready +- Last Updated: 2026-07-10T16:35:00+08:00 + +## Research Questions + +1. Campbell's Law 是否已有既有裁決?該裁決之精確字面與 PR pin 範圍為何? +2. Lucas Critique 是否與既有視角衝突?既有機制中有無可對應之落點? +3. 新增之 `## Metrics Policy` / `## Policy Regime` 條件式可選區段應比照哪個既有先例? +4. 觸及檔案之 EXACT_SYNC 與「慣例同步但不在清單內」之檔案範圍為何? + +## Confirmed Facts + +- **Campbell's Law 既有裁決**:`docs/orchestration.md:183-185`「明確拒絕:Campbell's Law」段明文:「Campbell's Law(Campbell 1979)與 Goodhart's Law 同構——同為『量化指標被用於治理即遭腐化』,僅為社會科學與經濟學之不同表述。依 OODA 先例(同構名詞不並存):本框架已採 Goodhart's Law,明確不採 Campbell's Law;任何後續 task 不得引此決策為 routing override 範本。」此為 TASK-1106 所建立、PR-038(`artifacts/scripts/drills/prompt_regression_cases.json`)pin 鎖定「明確不採 Campbell's Law」子字串之永久回歸守衛。使用者於本任務 Intake 階段以 AskUserQuestion 選擇「併入既有 Goodhart's Law 視角」,不新增獨立 lens、不動 pinned 字面。 +- **Goodhart's Law 現有列**(`docs/orchestration.md:161`):「| **Goodhart's Law**(Goodhart 1975,TASK-1106 顯式化) | 指標成為優化目標即失真(validator schema-pleasing) | RELAXATION_LOG 累積 ≥ 3 案例 → architect review | ... |」。PR-038 僅 pin `"Goodhart's Law"` 子字串本身(`artifacts/scripts/drills/prompt_regression_cases.json` 之 PR-038 assertion),不 pin 該列其餘欄位全文,故該列其餘文字可自由擴充而不破壞既有 pin。 +- **Lucas Critique 無既有衝突**:對 `docs/orchestration.md`、`docs/sop/rule_lifecycle_audit.md`、`README.md`、`README.zh-TW.md` grep「Lucas」與「政策回饋」「regime」均無命中,與既有 15 個視角(TASK-1001 6 個 + TASK-1106 3 個 + TASK-1108 6 個)皆不同構,可直接新增。 +- **Occam Pass 與 Campbell's Law 之既有隱性重疊**:`docs/sop/rule_lifecycle_audit.md:21`「使用數據只產生候選,不產生裁決——零使用不等於零價值……裁決一律過 Step 2 之 provenance 檢查」已隱性實踐 Campbell's Law 之「不得以原始指標值直接證明」精神,但未明文涵蓋「不得獎勵人為製造之 guard 觸發、警告壓制、淺層測試覆蓋、僅改善指標之變更」四類具體 gaming 防範規則,此為本任務唯一需要新增之 Campbell 操作化缺口。 +- **RELAXATION_LOG 與 rule lifecycle audit 為 Lucas Critique 之既有機制落點**:`artifacts/improvement/RELAXATION_LOG.md` 之 Cases 記錄格式(date / rule location / before / after / trigger task / root cause classification / provenance)與 `docs/sop/rule_lifecycle_audit.md:24-31` Step 2 Chesterton Gate 之 `relax`/`retire` 裁決,皆為既有之「治理規則變動事件」記錄機制,但目前未要求「該次變動後之 telemetry 比較須附加不可比較之但書」,此為 Lucas Critique 唯一需要新增之操作化缺口。 +- **Decision schema 之條件式可選 block 先例**:`docs/schemas/artifact-spec-decision.md:58-69` 之 `## Reversibility & Blast Radius` 區段(TASK-1108 建立)為既有先例,含「本區段為可選、無自動 validator 強制、消費者為後續審查者與週期性 architect review」之標準措辭,可直接比照新增 `## Metrics Policy` 與 `## Policy Regime` 兩區段。 +- **EXACT_SYNC 與慣例同步範圍**(`artifacts/scripts/guard_contract_validator.py:19-79`,直讀確認):`docs/orchestration.md`、`docs/sop/rule_lifecycle_audit.md`、`artifacts/scripts/drills/prompt_regression_cases.json` 為正式 EXACT_SYNC_FILES 成員;`docs/schemas/artifact-spec-decision.md`、`artifacts/improvement/RELAXATION_LOG.md`(§Rules 段)、`README.md`/`README.zh-TW.md` 不在清單內,但 TASK-1108 verify §Evidence 之 Post-Sync Amendment 已確立三者之既有同步慣例(前者 byte-identical、RELAXATION_LOG 僅 §Rules 段同步、README 之 lens 名單句同步),本任務應主動依此慣例同步,不等驗收階段才補。 + +## Relevant References + +- `docs/orchestration.md:161,169,183-185` — Goodhart 列、表尾插入點、Campbell 拒絕段 +- `docs/sop/rule_lifecycle_audit.md:16-22` — Occam Pass +- `artifacts/improvement/RELAXATION_LOG.md:5-10` — §Rules +- `docs/schemas/artifact-spec-decision.md:58-69` — Reversibility & Blast Radius 先例 +- `artifacts/scripts/guard_contract_validator.py:19-79` — EXACT_SYNC_FILES +- `artifacts/verify/TASK-1108.verify.md` — Post-Sync Amendment 慣例確立出處 + +## Sources + +[1] council-forge. "Campbell's Law rejection section and Goodhart's Law row." docs/orchestration.md (2026-07-10 retrieved) +[2] council-forge. "PR-038 regression pin." artifacts/scripts/drills/prompt_regression_cases.json (2026-07-10 retrieved) +[3] council-forge. "Rule lifecycle audit SOP, Occam Pass." docs/sop/rule_lifecycle_audit.md (2026-07-10 retrieved) +[4] council-forge. "Relaxation log rules section." artifacts/improvement/RELAXATION_LOG.md (2026-07-10 retrieved) +[5] council-forge. "Decision artifact schema, Reversibility and Blast Radius precedent." docs/schemas/artifact-spec-decision.md (2026-07-10 retrieved) +[6] council-forge. "EXACT_SYNC_FILES membership." artifacts/scripts/guard_contract_validator.py (2026-07-10 retrieved) +[7] council-forge. "TASK-1108 verify, Post-Sync Amendment precedent." artifacts/verify/TASK-1108.verify.md (2026-07-10 retrieved) + +## Uncertain Items + +- UNVERIFIED: 無。本任務所有機制引用皆已直讀確認;唯一延續之開放觀察項(`Documents/Code/.git` 環境殘骸根因)屬 TASK-1108 之已記錄 follow-up,非本任務新增之不確定項。 + +## Constraints For Implementation + +- Goodhart's Law 列與 Campbell's Law 拒絕段之編輯,只能新增文字,不可移除或改寫 PR-038 依賴之既有子字串。 +- Lucas Critique 列之「對應現有機制」需同時引用 RELAXATION_LOG 既有格式與本次新增之 `## Policy Regime` 區段,避免懸空引用。 +- `## Metrics Policy` 與 `## Policy Regime` 之規則段落需比照 `## Reversibility & Blast Radius` 之三要素措辭(可選 / 無自動強制 / 消費者為審查者),並針對 unknown/campbell_risk 等列舉值明示其非自動裁決依據。 diff --git a/artifacts/research/TASK-1112.research.md b/artifacts/research/TASK-1112.research.md new file mode 100644 index 0000000..741dbb7 --- /dev/null +++ b/artifacts/research/TASK-1112.research.md @@ -0,0 +1,43 @@ +# Research: TASK-1112 + +## Metadata +- Task ID: TASK-1112 +- Artifact Type: research +- Owner: Claude +- Status: ready +- Last Updated: 2026-07-17T12:15:00+08:00 + +## Research Questions + +1. TASK-1107 improvement artifact 之兩條 Preventive Action 原文措辭為何,是否可直接沿用? +2. `docs/sop/dispatch_implementation.md` 與 `docs/dispatch_prompt_discipline.md` 是否已有同形態先例可依循插入格式? +3. 兩份目標檔是否為 EXACT_SYNC 成員,是否有既有跨檔章節號引用可能因插入新章節而斷裂? + +## Confirmed Facts + +- `artifacts/improvement/TASK-1107.improvement.md` §5 Preventive Action (System Level) 明確記載兩條規則:(a) dispatch 逾時後重派前須先確認底層 process 是否存活;(b) dispatch wrapper 之 log 重導向路徑須在 repo 工作樹之外(artifacts/improvement/TASK-1107.improvement.md,2026-07-17 retrieved)。 +- `docs/sop/dispatch_implementation.md` 現行已有「### Fallback tier 產出之驗收紀律(TASK-1106)」作為同形態先例(規則正文 + 出處 task 引用),可直接沿用格式(docs/sop/dispatch_implementation.md,2026-07-17 retrieved)。 +- `docs/dispatch_prompt_discipline.md` 現行以「## 6. Cross-references」結尾,其前並無同形態小節;插入新章節於 §5 與 §6 之間不改動既有章節編號(docs/dispatch_prompt_discipline.md,2026-07-17 retrieved)。 +- 對 `docs/`、`CLAUDE.md`、`GEMINI.md`、`CODEX.md`、`AGENTS.md` 執行 `grep -rn "dispatch_prompt_discipline.md.*§[0-9]\|dispatch_prompt_discipline.md#"` 無任何命中,確認無跨檔以數字章節號引用本檔之既有依賴,插入新章節不致斷鏈(`grep` 直接執行,2026-07-17 retrieved,exit code 1 = no match)。 +- `docs/sop/dispatch_implementation.md` 與 `docs/dispatch_prompt_discipline.md` 皆為 `EXACT_SYNC_FILES` 成員(`artifacts/scripts/guard_contract_validator.py` EXACT_SYNC_FILES 常數,2026-07-17 直接以 Python import 查值確認);且皆命中 `is_sensitive_guard_path()`(因該函式對任何 EXACT_SYNC 成員一律回傳 True,非僅限 guard/validator 命名檔案——此為修正本任務 code artifact 初稿之誤判,該初稿曾誤稱兩檔「不含一般 SOP 文件」,已直接以 `gsv.is_sensitive_guard_path(...)` 執行結果推翻)。 + +## Relevant References + +- `artifacts/improvement/TASK-1107.improvement.md` §5 — 兩條規則原文 +- `docs/sop/dispatch_implementation.md` — TASK-1106 先例格式 +- `docs/dispatch_prompt_discipline.md` — 插入點 + +## Sources + +[1] council-forge. "TASK-1107 improvement artifact, Preventive Action section." artifacts/improvement/TASK-1107.improvement.md (2026-07-17 retrieved) +[2] council-forge. "Dispatch implementation SOP, existing TASK-1106 precedent format." docs/sop/dispatch_implementation.md (2026-07-17 retrieved) + +## Uncertain Items + +None + +## Constraints For Implementation + +- 兩條規則之措辭須與 improvement artifact §5 原文語意一致,不得改寫核心要求(process 存活確認、log 路徑須在 repo 外)。 +- 插入格式須沿用 `docs/sop/dispatch_implementation.md` 既有 `### <規則名>(TASK-XXXX)` 形態,不重新編號既有章節。 +- 兩檔皆為 CHG-012 sensitive set 成員(`is_sensitive_guard_path` 回傳 True),clean-task closure 進入 `done` 前須提供合法 `## Diff Evidence`(commit-range 或 github-pr),不可省略或誤判為豁免。 diff --git a/artifacts/scripts/Invoke-CodexAgent.ps1 b/artifacts/scripts/Invoke-CodexAgent.ps1 index c39610b..72c6525 100644 --- a/artifacts/scripts/Invoke-CodexAgent.ps1 +++ b/artifacts/scripts/Invoke-CodexAgent.ps1 @@ -476,6 +476,7 @@ foreach ($model in $Models) { # writes. Empty AllowedPaths = skip (backward compatible). $violationsFound = $false $violationCount = 0 +$raciViolations = @() if ($AllowedPaths.Count -eq 0) { Write-Host "[GUARD] skipped (no AllowedPaths configured)" -ForegroundColor DarkGray } else { @@ -531,6 +532,32 @@ if ($AllowedPaths.Count -eq 0) { } else { Write-Host "[GUARD] Post-dispatch check OK; all changes within allowed paths." -ForegroundColor Green } + + # CHG-006: RACI category audit on sub-agent writes. Orthogonal to AllowedPaths -- + # a path can be allow-listed yet be the wrong artifact CLASS for this agent. Tracked + # in a SEPARATE list: RACI violations are reported (and in enforcement mode drive + # exit 2) but are NEVER restored/deleted -- they are legitimately path-allowed writes. + foreach ($p in $changedPaths) { + # Skip user pre-existing lifecycle untracked (unchanged hash) -- not a sub-agent write. + if ($lifecycleSnapshot -and $lifecycleSnapshot.ContainsKey($p) -and (Test-Path $p)) { + $ph = & git hash-object -- $p 2>$null + if ($LASTEXITCODE -eq 0) { + if ($ph -is [array]) { $ph = $ph[0] } + if (([string]$ph).Trim() -eq $lifecycleSnapshot[$p]) { continue } + } + } + & python (Join-Path $PSScriptRoot 'guard_contract_validator.py') --audit-raci $p 'Codex CLI' --dry-run 2>&1 | Out-Null + $auditExit = $LASTEXITCODE + if ($auditExit -eq 1) { + $raciViolations += $p + } elseif ($auditExit -ne 0) { + Write-Host " [GUARD][RACI] audit inconclusive (exit $auditExit), treating as non-violation: $p" -ForegroundColor DarkYellow + } + } + if ($raciViolations.Count -gt 0) { + Write-Host "[GUARD][RACI] Sub-agent wrote files outside Codex CLI's RACI artifact class:" -ForegroundColor Red + foreach ($v in $raciViolations) { Write-Host " - $v" -ForegroundColor Red } + } } # TASK-1059: restore user pre-dispatch state. Conflict -> exit 3 fail-safe. @@ -544,6 +571,14 @@ if ($violationsFound -and $AutoRestore) { exit 2 } +# CHG-006: RACI category violations follow the same enforcement gate ($AutoRestore). +# Detect mode prints only (no exit 2); enforcement mode fails closed. RACI violations +# are NEVER restored (not fed to Restore-PostDispatchDelta) -- report-and-exit only. +if ($raciViolations.Count -gt 0 -and $AutoRestore) { + Write-Error "__GUARD_VIOLATION:[CHG-006] Sub-agent wrote $($raciViolations.Count) files outside Codex CLI RACI class.__" + exit 2 +} + # Wrap up if ($IsSuccess) { Write-Output $FinalOutput diff --git a/artifacts/scripts/Invoke-GeminiAgent.ps1 b/artifacts/scripts/Invoke-GeminiAgent.ps1 index 33825b9..dcb6941 100644 --- a/artifacts/scripts/Invoke-GeminiAgent.ps1 +++ b/artifacts/scripts/Invoke-GeminiAgent.ps1 @@ -405,6 +405,7 @@ foreach ($model in $Models) { # writes. Empty AllowedPaths = skip (backward compatible). $violationsFound = $false $violationCount = 0 +$raciViolations = @() if ($AllowedPaths.Count -eq 0) { Write-Host "[GUARD] skipped (no AllowedPaths configured)" -ForegroundColor DarkGray } else { @@ -460,6 +461,32 @@ if ($AllowedPaths.Count -eq 0) { } else { Write-Host "[GUARD] Post-dispatch check OK; all changes within allowed paths." -ForegroundColor Green } + + # CHG-006: RACI category audit on sub-agent writes. Orthogonal to AllowedPaths -- + # a path can be allow-listed yet be the wrong artifact CLASS for this agent. Tracked + # in a SEPARATE list: RACI violations are reported (and in enforcement mode drive + # exit 2) but are NEVER restored/deleted -- they are legitimately path-allowed writes. + foreach ($p in $changedPaths) { + # Skip user pre-existing lifecycle untracked (unchanged hash) -- not a sub-agent write. + if ($lifecycleSnapshot -and $lifecycleSnapshot.ContainsKey($p) -and (Test-Path $p)) { + $ph = & git hash-object -- $p 2>$null + if ($LASTEXITCODE -eq 0) { + if ($ph -is [array]) { $ph = $ph[0] } + if (([string]$ph).Trim() -eq $lifecycleSnapshot[$p]) { continue } + } + } + & python (Join-Path $PSScriptRoot 'guard_contract_validator.py') --audit-raci $p 'Gemini CLI' --dry-run 2>&1 | Out-Null + $auditExit = $LASTEXITCODE + if ($auditExit -eq 1) { + $raciViolations += $p + } elseif ($auditExit -ne 0) { + Write-Host " [GUARD][RACI] audit inconclusive (exit $auditExit), treating as non-violation: $p" -ForegroundColor DarkYellow + } + } + if ($raciViolations.Count -gt 0) { + Write-Host "[GUARD][RACI] Sub-agent wrote files outside Gemini CLI's RACI artifact class:" -ForegroundColor Red + foreach ($v in $raciViolations) { Write-Host " - $v" -ForegroundColor Red } + } } # TASK-1059: restore user pre-dispatch state. Conflict -> exit 3 fail-safe. @@ -473,6 +500,14 @@ if ($violationsFound -and $AutoRestore) { exit 2 } +# CHG-006: RACI category violations follow the same enforcement gate ($AutoRestore). +# Detect mode prints only (no exit 2); enforcement mode fails closed. RACI violations +# are NEVER restored (not fed to Restore-PostDispatchDelta) -- report-and-exit only. +if ($raciViolations.Count -gt 0 -and $AutoRestore) { + Write-Error "__GUARD_VIOLATION:[CHG-006] Sub-agent wrote $($raciViolations.Count) files outside Gemini CLI RACI class.__" + exit 2 +} + # Wrap up if ($IsSuccess) { Write-Output $FinalOutput diff --git a/artifacts/scripts/conftest.py b/artifacts/scripts/conftest.py index 5eca8e5..059766d 100644 --- a/artifacts/scripts/conftest.py +++ b/artifacts/scripts/conftest.py @@ -91,12 +91,12 @@ def _write_fake_exe(tmp_path: Path, command_name: str) -> FakeExe: existing = [line for line in log_path.read_text(encoding='utf-8').splitlines() if line.strip()] if log_path.exists() else [] call_index = len(existing) behavior = json.loads(behavior_path.read_text(encoding='utf-8')) -# TASK-1062: capture stdin (non-blocking via isatty check on Windows is -# unreliable; just read whatever is on stdin -- pytest pipes always pipe). +# TASK-1105: capture raw stdin bytes and decode as UTF-8 so wrapper pipe +# tests observe the exact payload emitted by PowerShell. stdin_data = '' try: if not sys.stdin.isatty(): - stdin_data = sys.stdin.read() + stdin_data = sys.stdin.buffer.read().decode('utf-8') except Exception: stdin_data = '' record = {{ diff --git a/artifacts/scripts/drills/prompt_regression_cases.json b/artifacts/scripts/drills/prompt_regression_cases.json index e071186..93668a4 100644 --- a/artifacts/scripts/drills/prompt_regression_cases.json +++ b/artifacts/scripts/drills/prompt_regression_cases.json @@ -852,5 +852,161 @@ "note": "Gemini Architecture Synthesizer must stay emit-only (draft text, no repo-tracked writes incl the cache) with the N=10 / sprint-review trigger; mirrors the Memory Bank Curator draft-only contract (PR-021)." } ] + }, + { + "id": "PR-034", + "title": "Lightweight Verify Routes Through Resolved Policy", + "description": "CLAUDE.md lightweight guidance must govern verify obligations via the resolved policy and must not present ## Environment as a guard-enforced substitute for Build Guarantee. (sync CHG-008)", + "assertions": [ + { + "file": "CLAUDE.md", + "must_contain_all": [ + "resolved policy", + "非 guard-enforced", + "Build Guarantee" + ], + "note": "Lightweight verify relaxation is governed by the resolved policy; ## Environment is documented as non-guard-enforced and cannot replace Build Guarantee (CHG-008 撤除 Environment 無 enforcement 宣稱)." + } + ] + }, + { + "id": "PR-035", + "title": "Dispatch AutoRestore Enforcement Is Conditional, Not Absolute (TASK-1102)", + "description": "CLAUDE.md must state that passing -AutoRestore to Invoke-CodexAgent.ps1 / Invoke-GeminiAgent.ps1 is the orchestrator's (Claude's) explicit decision, and that the flag defaults to $false (detect-only, exit 0). GEMINI.md's write-scope violation clause must be conditional on whether -AutoRestore was explicitly passed, and must not re-endorse the pre-TASK-1059 blanket `git checkout HEAD --` restore language.", + "assertions": [ + { + "file": "CLAUDE.md", + "must_contain_all": [ + "Dispatch Write-Scope 執行", + "-AutoRestore", + "預設 `$false`", + "detect-only", + "顯式傳遞" + ], + "note": "Orchestrator must explicitly opt in via -AutoRestore for wrapper enforcement; default is detect-only (exit 0), not automatic blocking (TASK-1102)." + }, + { + "file": "GEMINI.md", + "must_contain_all": [ + "是否已於偵測當下被 wrapper 自動擋下", + "stash-based restore", + "取決於下列 `-AutoRestore` 是否顯式傳遞" + ], + "must_not_contain_any": [ + "dispatch 視為失敗;Claude 將以 `git checkout HEAD --`" + ], + "note": "GEMINI.md's violation clause must be conditional on explicit -AutoRestore, not an absolute claim, and must not re-endorse the pre-TASK-1059 blanket git-checkout restore (TASK-1102)." + } + ] + }, + { + "id": "PR-036", + "title": "Independent Premortem Challenge Required For High-Risk Plans (TASK-1103)", + "description": "docs/premortem_rules.md must define an independent premortem challenge for high-risk plans (security fix / upstream PR / cross-module or cross-repo / unfamiliar framework), requiring a reviewer who does not share the same conversation context/session as the plan author. CLAUDE.md's STOP triggers must reference this requirement.", + "assertions": [ + { + "file": "docs/premortem_rules.md", + "must_contain_all": [ + "獨立 Premortem 質疑", + "不得與撰寫 R1-R4 的 agent 共用同一個對話 context/session", + "Independent Premortem Challenge" + ], + "note": "Premortem rules must define the independent-challenge convention for high-risk plans, including the non-negotiable independence requirement (TASK-1103)." + }, + { + "file": "CLAUDE.md", + "must_contain_all": [ + "高風險 plan 未完成獨立質疑" + ], + "note": "CLAUDE.md STOP triggers must reference the independent premortem challenge requirement (TASK-1103)." + } + ] + }, + { + "id": "PR-037", + "title": "Rule Lifecycle Audit Verdict Contract (TASK-1104)", + "description": "The new SOP must pin the four audit verdicts and the fail-closed OPEN rule when provenance is missing.", + "assertions": [ + { + "file": "docs/sop/rule_lifecycle_audit.md", + "must_contain_all": [ + "`retire`", + "`relax`", + "`keep`", + "`open`", + "查無 provenance", + "不拆也不加碼" + ], + "note": "The rule lifecycle audit SOP must keep the four-way verdict vocabulary and the provenance-missing OPEN clause pinned." + } + ] + }, + { + "id": "PR-038", + "title": "Governance Lenses Additions (TASK-1106)", + "description": "The three evidence-backed governance lenses and the Campbell's Law rejection must stay pinned in the orchestration doc; the deviance forcing clause must stay in the rule lifecycle audit SOP.", + "assertions": [ + { + "file": "docs/orchestration.md", + "must_contain_all": [ + "Goodhart's Law", + "Normalization of Deviance", + "Swiss Cheese Model", + "明確不採 Campbell's Law" + ], + "note": "Governance Lenses table rows and the Campbell rejection clause (TASK-1106) must not silently regress." + }, + { + "file": "docs/sop/rule_lifecycle_audit.md", + "must_contain_all": [ + "不得停留於 detect-and-accept" + ], + "note": "The Normalization-of-Deviance forcing clause (accept 3 times consecutively -> relax or enforce) must stay pinned." + } + ] + }, + { + "id": "PR-039", + "title": "Governance Lenses Additions (TASK-1108)", + "description": "The six new governance lenses (Hyrum's Law, Reversibility & Blast Radius, Separation of Duties, Least Privilege, Gall's Law, Modernized Postel's Law) and the Policy Engine rejection must stay pinned in the orchestration doc.", + "assertions": [ + { + "file": "docs/orchestration.md", + "must_contain_all": [ + "Hyrum's Law", + "Reversibility & Blast Radius", + "Separation of Duties", + "Least Privilege", + "Gall's Law", + "Modernized Postel's Law", + "明確拒絕:獨立 Policy Engine" + ], + "note": "Governance Lenses table rows and the Policy Engine rejection clause (TASK-1108) must not silently regress." + } + ] + }, + { + "id": "PR-040", + "title": "Lucas Critique Addition And Campbell's Law Fold-In (TASK-1109)", + "description": "The Lucas Critique lens and the Campbell's Law operationalization note (folded into Goodhart's Law, not a separate lens) must stay pinned in the orchestration doc; the Metrics Policy and Policy Regime optional decision sections must stay pinned in the decision schema.", + "assertions": [ + { + "file": "docs/orchestration.md", + "must_contain_all": [ + "Lucas Critique", + "Campbell's Law 1979 之經濟學同構表述", + "明確不採 Campbell's Law" + ], + "note": "Lucas Critique row and the Campbell's Law fold-in note (TASK-1109) must not silently regress; the original Campbell rejection literal (TASK-1106) must remain intact." + }, + { + "file": "docs/schemas/artifact-spec-decision.md", + "must_contain_all": [ + "## Metrics Policy", + "## Policy Regime" + ], + "note": "The optional Metrics Policy and Policy Regime decision sections (TASK-1109) must not silently regress." + } + ] } ] diff --git a/artifacts/scripts/guard_contract_validator.py b/artifacts/scripts/guard_contract_validator.py index 01f1809..183794a 100644 --- a/artifacts/scripts/guard_contract_validator.py +++ b/artifacts/scripts/guard_contract_validator.py @@ -57,15 +57,21 @@ "docs/artifact_schema.md", "docs/agentic_execution_layer.md", "docs/dispatch_prompt_discipline.md", + "docs/hooks.md", "docs/lightweight_mode_rules.md", "docs/orchestration.md", + "docs/orchestration-workflow.md", "docs/premortem_rules.md", + "docs/raci-matrix.md", "docs/red_team_backlog.md", "docs/red_team_runbook.md", "docs/red_team_scorecard.md", + "docs/repo_structure_workflow_maturity_assessment.md", + "docs/security_cadence.md", "docs/sop/dispatch_implementation.md", "docs/sop/dispatch_memory_curator.md", "docs/sop/dispatch_research.md", + "docs/sop/rule_lifecycle_audit.md", "docs/sop/task_completion.md", "docs/subagent_roles.md", "docs/subagent_task_templates.md", diff --git a/artifacts/scripts/guard_status_validator.py b/artifacts/scripts/guard_status_validator.py index e5351d6..5df1409 100644 --- a/artifacts/scripts/guard_status_validator.py +++ b/artifacts/scripts/guard_status_validator.py @@ -76,16 +76,6 @@ "improvement": ".improvement.md", "status": ".status.json", } -STATE_REQUIRED_ARTIFACTS = { - "drafted": {"task", "status"}, - "researched": {"task", "research", "status"}, - "planned": {"task", "plan", "status"}, - "coding": {"task", "plan", "code", "status"}, - "testing": {"task", "plan", "code", "test", "status"}, - "verifying": {"task", "code", "status"}, - "done": {"task", "code", "verify", "status"}, - "blocked": {"task", "status"}, -} MARKERS = { "task": ( "# Task:", @@ -1030,7 +1020,7 @@ def validate_status_schema(status: dict, expected_task_id: str) -> ValidationRes if state not in VALID_STATES: errors.append(f"Invalid state: {state!r}") if status_uses_legacy_schema(status): - warnings.append("legacy status schema detected; run reconcile to promote state/current_owner/next_agent profile fields") + warnings.append("DEPRECATED legacy status schema (current_state) detected; support will be removed in a future release — run reconcile to migrate") required_keys = {"task_id", "current_state", "owner", "last_updated"} missing = required_keys - set(status.keys()) if missing: @@ -1679,6 +1669,20 @@ def task_is_high_risk(task_path: Optional[Path], plan_text: str) -> bool: return any(keyword in haystack for keyword in HIGH_RISK_KEYWORDS) +def split_premortem_risk_blocks(risks_text: str) -> List[Tuple[str, str]]: + """Split a ## Risks section into (label, block_text) pairs delimited by line-anchored + R markers; text before the first marker is dropped. Under-splitting (merging blocks) + is the safe failure mode for the banned-phrase escalation. Real plans open blocks in + three shapes — bare ``R1``, list ``- R1``, and heading ``### R1`` — all at line start.""" + matches = list(re.finditer(r"(?m)^\s*(?:[-*>#]+\s*)?R(\d+)\b", risks_text)) + blocks: List[Tuple[str, str]] = [] + for idx, match in enumerate(matches): + start = match.start() + end = matches[idx + 1].start() if idx + 1 < len(matches) else len(risks_text) + blocks.append((f"R{match.group(1)}", risks_text[start:end])) + return blocks + + def validate_premortem(plan_path: Path, task_path: Optional[Path]) -> ValidationResult: errors: List[str] = [] warnings: List[str] = [] @@ -1712,8 +1716,22 @@ def validate_premortem(plan_path: Path, task_path: Optional[Path]) -> Validation ) elif policy.min_critical == 0 and blocking_count == 0 and task_is_high_risk(task_path, text): warnings.append(f"{plan_path.name}: high-risk signals detected but task_type='{policy.task_type}' does not require blocking risk") + # CHG-007: escalate banned phrases per R-block. A vague phrase inside a risk block + # that is missing any required field is an error (a stub dismissal); the same phrase + # in an otherwise-complete block stays a warning. Phrases outside any block warn. + risk_blocks = split_premortem_risk_blocks(risks_text) for phrase in PREMORTEM_BANNED_PHRASES: - if phrase in risks_text: + if phrase not in risks_text: + continue + escalated = False + for label, block_text in risk_blocks: + if phrase in block_text and any(field not in block_text for field in PREMORTEM_REQUIRED_FIELDS): + errors.append( + f"{plan_path.name}: premortem {label} contains vague phrase '{phrase}' but is " + f"missing required Risk/Trigger/Detection/Mitigation/Severity fields" + ) + escalated = True + if not escalated: warnings.append(f"{plan_path.name}: premortem contains potentially vague phrase '{phrase}' — ensure it has concrete trigger/detection/mitigation") return ValidationResult(errors, warnings) @@ -2080,6 +2098,26 @@ def run_verify_floor_enforce(repo_root: Path) -> int: return 0 +def is_sensitive_guard_path(path: str) -> bool: + """True if ``path`` is in the guard / EXACT_SYNC "sensitive set" (CHG-012 / HC-1 A2): + a clean-task closure that touches any of these must carry replayable ## Diff Evidence. + EXACT_SYNC_FILES is read via a lazy import — guard_contract_validator imports THIS + module at its top, so a module-level import back would be circular; at call time both + modules are fully loaded, so the deferred import is safe and stays drift-free (it reads + gcv's live list rather than mirroring it).""" + p = path.replace("\\", "/").strip() + if p.startswith("./"): + p = p[2:] + if not p: + return False + from guard_contract_validator import EXACT_SYNC_FILES + if p in set(EXACT_SYNC_FILES): + return True + if p in ("artifacts/scripts/run_quality_gates.py", "artifacts/scripts/workflow_constants.py"): + return True + return bool(re.match(r"artifacts/scripts/guard_\w+\.py$", p)) + + def validate_artifact_presence( artifacts_root: Path, task_id: str, @@ -2087,6 +2125,7 @@ def validate_artifact_presence( status: dict, strict_scope: bool = False, validation_mode: str = AUTO_CLASSIFY_FULL, + enforce_clean_diff_evidence: bool = False, ) -> ValidationResult: errors: List[str] = [] warnings: List[str] = [] @@ -2198,6 +2237,25 @@ def validate_artifact_presence( else: warnings.extend(history_scope_result.waiver_candidate_errors) warnings.extend(history_scope_result.warnings) + # CHG-012 (HC-1 A2): a clean-task closure (transition into done) that touches + # the guard/EXACT_SYNC sensitive set must carry replayable ## Diff Evidence. + # Gated on enforce_clean_diff_evidence so it fires ONLY on the target_presence + # transition call (to_state == done) and NOT on re-validation of existing done + # tasks (validate_all / --task-id) -> forward-only, no retroactive impact. + if state == "done" and enforce_clean_diff_evidence: + code_text = load_text(code_path) + changed_files = extract_file_tokens(extract_section(code_text, "Files Changed")) + sensitive_hits = sorted(p for p in changed_files if is_sensitive_guard_path(p)) + evidence = parse_diff_evidence(code_text) + evidence_type = (evidence or {}).get("evidence type", "").strip().lower() + if sensitive_hits and evidence_type not in DIFF_EVIDENCE_SUPPORTED_TYPES: + errors.append( + f"{code_path.name}: clean-task closure touches guard/EXACT_SYNC-sensitive " + f"files {sensitive_hits} but provides no ## Diff Evidence. HC-1 A2 requires a " + f"replayable ## Diff Evidence block (Evidence Type: commit-range with Base " + f"Commit, Head Commit, Diff Command, Changed Files Snapshot, and Snapshot " + f"SHA256; or github-pr) so the closure's scope can be independently verified." + ) if not strict_scope and scope_drift_files: waiver_result = validate_scope_drift_waiver(artifacts_root, task_id, scope_drift_files) errors.extend(waiver_result.errors) @@ -2445,6 +2503,7 @@ def write_transition( status, strict_scope=strict_scope, validation_mode=validation_mode, + enforce_clean_diff_evidence=(to_state == "done"), ) if target_presence.errors: return ValidationResult([f"Target state '{to_state}' requirements are not yet satisfied.", *target_presence.errors], target_presence.warnings) diff --git a/artifacts/scripts/red_team/case_builders.py b/artifacts/scripts/red_team/case_builders.py index 9a7fadd..1664e52 100644 --- a/artifacts/scripts/red_team/case_builders.py +++ b/artifacts/scripts/red_team/case_builders.py @@ -1193,6 +1193,79 @@ def case_pr_025() -> CaseResult: ) +def case_rt_031() -> CaseResult: + temp_root = prepare_temp_root("RT-031") + try: + artifacts_root = copy_task_fixture(temp_root, "TASK-900", "TASK-963") + plan_path = artifacts_root / "plans" / "TASK-963.plan.md" + plan_text = plan_path.read_text(encoding="utf-8") + # CHG-007: inject a stub risk block — a banned phrase with none of the required + # Risk/Trigger/Detection/Mitigation/Severity fields. Sibling blocks stay complete + # so the whole-doc field check passes and the only error is the per-block escalation. + plan_text = plan_text.replace( + "## Validation Strategy\n", + "- R9 相容性問題,風險低\n\n## Validation Strategy\n", + 1, + ) + plan_path.write_text(plan_text, encoding="utf-8") + status_path = artifacts_root / "status" / "TASK-963.status.json" + status = json.loads(status_path.read_text(encoding="utf-8")) + status["state"] = "coding" + status["required_artifacts"] = ["code", "plan", "research", "status", "task"] + status["available_artifacts"] = ["code", "plan", "research", "status", "task", "verify"] + status["missing_artifacts"] = [] + status_path.write_text(json.dumps(status, ensure_ascii=False, indent=2) + "\n", encoding="utf-8") + return run_status_case( + "TASK-963", + artifacts_root, + expected_exit_code=1, + expected_output_fragment="contains vague phrase", + title="Premortem stub risk block with banned phrase escalates to error", + case_id="RT-031", + ) + finally: + shutil.rmtree(temp_root, ignore_errors=True) + + +def case_rt_032() -> CaseResult: + temp_root = prepare_temp_root("RT-032") + try: + artifacts_root = copy_task_fixture(temp_root, "TASK-900", "TASK-963") + # CHG-012 (HC-1 A2): add a guard-sensitive file to both plan Files Likely Affected + # and code Files Changed (so no scope drift), with NO ## Diff Evidence. The + # verifying -> done write-transition must then fail closed. + sensitive = "- `artifacts/scripts/guard_status_validator.py`\n" + plan_path = artifacts_root / "plans" / "TASK-963.plan.md" + plan_path.write_text( + plan_path.read_text(encoding="utf-8").replace( + "## Files Likely Affected\n", "## Files Likely Affected\n" + sensitive, 1 + ), + encoding="utf-8", + ) + code_path = artifacts_root / "code" / "TASK-963.code.md" + code_path.write_text( + code_path.read_text(encoding="utf-8").replace( + "## Files Changed\n", "## Files Changed\n" + sensitive, 1 + ), + encoding="utf-8", + ) + status_path = artifacts_root / "status" / "TASK-963.status.json" + status = json.loads(status_path.read_text(encoding="utf-8")) + status["state"] = "verifying" + status_path.write_text(json.dumps(status, ensure_ascii=False, indent=2) + "\n", encoding="utf-8") + return run_status_case( + "TASK-963", + artifacts_root, + expected_exit_code=1, + expected_output_fragment="clean-task closure touches guard", + title="Guard-touching clean-task done closure without Diff Evidence is blocked", + case_id="RT-032", + extra_args=["--write-transition", "verifying", "done"], + ) + finally: + shutil.rmtree(temp_root, ignore_errors=True) + + STATIC_CASES: List[CaseDefinition] = [ CaseDefinition("RT-001", "static", "Research artifact contains Recommendation", "fail", 1, "must not contain ## Recommendation", case_rt_001), CaseDefinition("RT-002", "static", "Confirmed Facts missing citation", "fail", 1, "must include an inline citation", case_rt_002), @@ -1224,6 +1297,8 @@ def case_pr_025() -> CaseResult: CaseDefinition("RT-028", "static", "Oversized provider response is rejected before JSON parsing", "fail", 1, "exceeds replay byte cap", case_rt_028), CaseDefinition("RT-029", "static", "README source/downstream wording drift", "fail", 1, "template/README.md section 'Architecture Snapshot' contains forbidden phrase: template/ + .github/ + OBSIDIAN.md + external/", case_rt_029), CaseDefinition("RT-030", "static", "External legacy unparseable import stays fail-closed", "pass", 0, "fail-closed external legacy import confirmed", case_rt_030), + CaseDefinition("RT-031", "static", "Premortem stub risk block with banned phrase escalates to error", "fail", 1, "contains vague phrase", case_rt_031), + CaseDefinition("RT-032", "static", "Guard-touching clean-task done closure without Diff Evidence is blocked", "fail", 1, "clean-task closure touches guard", case_rt_032), ] LIVE_CASES: List[CaseDefinition] = [ diff --git a/artifacts/scripts/red_team/cases_metadata.json b/artifacts/scripts/red_team/cases_metadata.json index fee1104..c5aa5b3 100644 --- a/artifacts/scripts/red_team/cases_metadata.json +++ b/artifacts/scripts/red_team/cases_metadata.json @@ -149,6 +149,16 @@ "title": "External legacy unparseable import stays fail-closed", "phase": "static" }, + { + "case_id": "RT-031", + "title": "Premortem stub risk block with banned phrase escalates to error", + "phase": "static" + }, + { + "case_id": "RT-032", + "title": "Guard-touching clean-task done closure without Diff Evidence is blocked", + "phase": "static" + }, { "case_id": "RT-LIVE-950", "title": "Role boundary live drill", diff --git a/artifacts/scripts/test_guard_status_validator_artifacts.py b/artifacts/scripts/test_guard_status_validator_artifacts.py index 1343301..713cbe1 100644 --- a/artifacts/scripts/test_guard_status_validator_artifacts.py +++ b/artifacts/scripts/test_guard_status_validator_artifacts.py @@ -487,6 +487,22 @@ def test_legacy_schema_valid(self): result = gsv.validate_status_schema(status, "TASK-001") assert result.ok + def test_legacy_schema_deprecation_warning(self): + # CHG-002 stage 1: legacy (current_state) schema stays valid (zero behavior + # change) but the warning is upgraded to a DEPRECATED notice foretelling removal. + status = { + "task_id": "TASK-001", + "current_state": "drafted", + "owner": "Claude", + "last_updated": "2026-01-15T10:00:00+08:00", + } + result = gsv.validate_status_schema(status, "TASK-001") + assert result.ok + assert any( + "DEPRECATED" in w and "will be removed in a future release" in w + for w in result.warnings + ), result.warnings + def test_legacy_blocked_without_blockers(self): status = { "task_id": "TASK-001", @@ -1108,6 +1124,30 @@ def test_banned_phrase_warning(self, tmp_path): assert result.ok assert any("風險低" in w for w in result.warnings) + def test_banned_phrase_incomplete_block_errors(self, tmp_path): + # CHG-007: a vague phrase inside an R-block that is missing required fields is an + # error (a stub dismissal). Sibling complete blocks keep the whole-doc field + # check satisfied, so the only error raised is the per-block escalation on R2. + risks = textwrap.dedent("""\ + R1: Proper risk + - Risk: Real risk described + - Trigger: Event + - Detection: Monitor + - Mitigation: Fix + - Severity: blocking + R2 相容性問題,風險低 + R3: Another proper risk + - Risk: Third thing + - Trigger: Event3 + - Detection: Monitor3 + - Mitigation: Fix3 + - Severity: non-blocking + """) + plan = self._make_plan(tmp_path, risks) + result = gsv.validate_premortem(plan, None) + assert not result.ok + assert any("R2" in e and "風險低" in e for e in result.errors), result.errors + def test_hotfix_policy_fewer_risks_ok(self, tmp_path): risks = textwrap.dedent("""\ R1: Hotfix risk @@ -2796,3 +2836,124 @@ def _make_diff_evidence_code(tmp_path, evidence_type, snapshot_files, extra_fiel code_path.write_text("\n".join(lines) + "\n", encoding="utf-8") return code_path + +class TestCleanTaskDiffEvidenceCHG012: + """CHG-012 (HC-1 A2): a clean-task closure (transition into done) touching the + guard/EXACT_SYNC sensitive set must carry ## Diff Evidence. Enforced only via + enforce_clean_diff_evidence (set by write_transition's target_presence call for + to_state==done), NOT on validate_all / --task-id re-validation -> forward-only.""" + + def _tree(self, tmp_path, task_id, files_changed, diff_evidence=None): + # Minimal task+plan+code+status tree; plan Files Likely Affected == code Files + # Changed so no scope drift, isolating the CHG-012 check. + _build_task_artifact(tmp_path, task_id) + (tmp_path / "plans").mkdir(parents=True, exist_ok=True) + listed = "\n".join(f"- `{f}`" for f in files_changed) + (tmp_path / "plans" / f"{task_id}.plan.md").write_text(textwrap.dedent(f"""\ + # Plan: {task_id} + ## Metadata + - Artifact Type: plan + - Task ID: {task_id} + - Owner: Claude + - Status: approved + - Last Updated: {_ts()} + ## Scope + s + ## Files Likely Affected + {listed} + ## Proposed Changes + c + ## Validation Strategy + v + ## Risks + R1: r + - Risk: x + - Trigger: x + - Detection: x + - Mitigation: x + - Severity: blocking + ## Ready For Coding + yes + """), encoding="utf-8") + (tmp_path / "code").mkdir(parents=True, exist_ok=True) + code = textwrap.dedent(f"""\ + # Code Result: {task_id} + ## Metadata + - Artifact Type: code + - Task ID: {task_id} + - Owner: Claude + - Status: ready + - Last Updated: {_ts()} + ## Files Changed + {listed} + ## Summary Of Changes + s + ## Mapping To Plan + - plan_item: 1.1, status: done, evidence: "x" + """) + if diff_evidence is not None: + code += f"\n## Diff Evidence\n{diff_evidence}\n" + (tmp_path / "code" / f"{task_id}.code.md").write_text(code, encoding="utf-8") + status = _make_full_status(task_id, "done") + _write_status(tmp_path, task_id, status) + return status + + def _chg012_errors(self, tmp_path, task_id, status, flag): + res = gsv.validate_artifact_presence( + tmp_path, task_id, "done", status, enforce_clean_diff_evidence=flag + ) + return [e for e in res.errors if "clean-task closure touches guard" in e] + + def test_sensitive_no_evidence_transition_fails(self, tmp_path): + status = self._tree(tmp_path, "TASK-001", ["artifacts/scripts/guard_status_validator.py"]) + errs = self._chg012_errors(tmp_path, "TASK-001", status, flag=True) + assert errs, "expected CHG-012 error for guard-touching clean closure without Diff Evidence" + assert "Diff Evidence" in errs[0] + + def test_sensitive_with_commit_range_evidence_passes(self, tmp_path): + de = ( + "- Evidence Type: commit-range\n" + f"- Base Commit: {'a' * 40}\n" + f"- Head Commit: {'b' * 40}\n" + "- Diff Command: git diff\n" + "- Changed Files Snapshot: artifacts/scripts/guard_status_validator.py\n" + "- Snapshot SHA256: deadbeef" + ) + status = self._tree(tmp_path, "TASK-001", ["artifacts/scripts/guard_status_validator.py"], diff_evidence=de) + assert not self._chg012_errors(tmp_path, "TASK-001", status, flag=True) + + def test_sensitive_none_with_reason_evidence_fails(self, tmp_path): + for diff_evidence in ( + "None (this task was completed via alternate verification)", + "None(this task was completed via alternate verification)", + ): + status = self._tree( + tmp_path, + "TASK-001", + ["artifacts/scripts/guard_status_validator.py"], + diff_evidence=diff_evidence, + ) + errs = self._chg012_errors(tmp_path, "TASK-001", status, flag=True) + assert errs, f"expected CHG-012 error for placeholder Diff Evidence: {diff_evidence}" + + def test_sensitive_unstructured_evidence_type_text_fails(self, tmp_path): + de = "No Evidence Type: applicable -- verified via manual code review instead of diff replay." + status = self._tree(tmp_path, "TASK-001", ["artifacts/scripts/guard_status_validator.py"], diff_evidence=de) + errs = self._chg012_errors(tmp_path, "TASK-001", status, flag=True) + assert errs, "expected CHG-012 error for unstructured free text containing Evidence Type" + + def test_non_sensitive_transition_unchanged(self, tmp_path): + status = self._tree(tmp_path, "TASK-001", ["src/main.py"]) + assert not self._chg012_errors(tmp_path, "TASK-001", status, flag=True) + + def test_sensitive_no_evidence_revalidation_flag_false_passes(self, tmp_path): + # validate_all / --task-id path passes flag=False -> existing done tasks stay [OK]. + status = self._tree(tmp_path, "TASK-001", ["artifacts/scripts/guard_status_validator.py"]) + assert not self._chg012_errors(tmp_path, "TASK-001", status, flag=False) + + def test_is_sensitive_guard_path(self): + assert gsv.is_sensitive_guard_path("artifacts/scripts/guard_status_validator.py") + assert gsv.is_sensitive_guard_path("artifacts/scripts/run_quality_gates.py") + assert gsv.is_sensitive_guard_path("docs/orchestration.md") # in EXACT_SYNC + assert not gsv.is_sensitive_guard_path("src/main.py") + assert not gsv.is_sensitive_guard_path("artifacts/scripts/discover_templates.py") diff --git a/artifacts/scripts/test_invoke_codex_agent.py b/artifacts/scripts/test_invoke_codex_agent.py index 84cd813..d496a62 100644 --- a/artifacts/scripts/test_invoke_codex_agent.py +++ b/artifacts/scripts/test_invoke_codex_agent.py @@ -564,3 +564,66 @@ def test_suppress_size_warn_bypasses_reject(self, fake_codex_exe, run_wrapper): assert result.returncode == 0, result.combined_output assert "exceeds reject limit" not in result.combined_output assert "exceeds soft limit" not in result.combined_output + + +class TestCodexRaciAudit: + """CHG-006: post-dispatch RACI category audit on sub-agent writes. Orthogonal to + AllowedPaths — a path can be allow-listed yet be the wrong artifact class for the + agent. RACI violations are reported and (in -AutoRestore mode) exit 2, but are + never restored/deleted.""" + + @staticmethod + def _build_writer_exe(directory: Path, rel_path: str, content: str) -> Path: + directory.mkdir(parents=True, exist_ok=True) + script_path = directory / "codex_writer.py" + script_path.write_text( + textwrap.dedent(f""" + from __future__ import annotations + from pathlib import Path + target = Path.cwd() / {rel_path!r} + target.parent.mkdir(parents=True, exist_ok=True) + target.write_text({content!r}, encoding="utf-8") + """).strip(), + encoding="utf-8", + ) + exe_path = directory / "codex.cmd" + exe_path.write_text( + f'@echo off\r\n"{sys.executable}" "{script_path}" %*\r\nexit /b %ERRORLEVEL%\r\n', + encoding="utf-8", + ) + return exe_path + + def test_raci_violation_within_allowedpaths_exits_2(self, tmp_path, tmp_repo, run_wrapper): + # Sub-agent writes a *task* artifact that IS within AllowedPaths (no path + # violation) but is the wrong RACI class for Codex CLI -> RACI audit exit 2, + # and the path-allowed write is NOT restored/deleted. + exe = self._build_writer_exe(tmp_path / "w", "artifacts/tasks/TASK-raci.task.md", "raci\n") + result = run_wrapper( + WRAPPER, + "-Prompt", "hi", + "-Executable", str(exe), + "-MaxRetriesPerTier", "0", + "-BaseBackoffSeconds", "0", + "-AllowedPaths", "artifacts/tasks/TASK-raci.task.md", + "-AutoRestore", + ) + assert result.returncode == 2, result.combined_output + assert "RACI" in result.combined_output + assert (tmp_repo / "artifacts" / "tasks" / "TASK-raci.task.md").exists(), ( + "RACI (path-allowed) write must not be deleted/restored" + ) + + def test_raci_allowed_class_within_allowedpaths_passes(self, tmp_path, tmp_repo, run_wrapper): + # Sub-agent writes a *code* artifact within AllowedPaths -> Codex CLI is + # authorized for the code class -> no RACI violation, exit 0. + exe = self._build_writer_exe(tmp_path / "w", "artifacts/code/TASK-raci.code.md", "code\n") + result = run_wrapper( + WRAPPER, + "-Prompt", "hi", + "-Executable", str(exe), + "-MaxRetriesPerTier", "0", + "-BaseBackoffSeconds", "0", + "-AllowedPaths", "artifacts/code/TASK-raci.code.md", + "-AutoRestore", + ) + assert result.returncode == 0, result.combined_output diff --git a/artifacts/scripts/test_invoke_gemini_agent.py b/artifacts/scripts/test_invoke_gemini_agent.py index a6ce307..9c064af 100644 --- a/artifacts/scripts/test_invoke_gemini_agent.py +++ b/artifacts/scripts/test_invoke_gemini_agent.py @@ -420,3 +420,66 @@ def test_suppress_size_warn_bypasses_reject(self, fake_gemini_exe, run_wrapper): assert result.returncode == 0, result.combined_output assert "exceeds reject limit" not in result.combined_output assert "exceeds soft limit" not in result.combined_output + + +class TestGeminiRaciAudit: + """CHG-006: post-dispatch RACI category audit on sub-agent writes. Orthogonal to + AllowedPaths — a path can be allow-listed yet be the wrong artifact class for the + agent. RACI violations are reported and (in -AutoRestore mode) exit 2, but are + never restored/deleted.""" + + @staticmethod + def _build_writer_exe(directory: Path, rel_path: str, content: str) -> Path: + directory.mkdir(parents=True, exist_ok=True) + script_path = directory / "gemini_writer.py" + script_path.write_text( + textwrap.dedent(f""" + from __future__ import annotations + from pathlib import Path + target = Path.cwd() / {rel_path!r} + target.parent.mkdir(parents=True, exist_ok=True) + target.write_text({content!r}, encoding="utf-8") + """).strip(), + encoding="utf-8", + ) + exe_path = directory / "gemini.cmd" + exe_path.write_text( + f'@echo off\r\n"{sys.executable}" "{script_path}" %*\r\nexit /b %ERRORLEVEL%\r\n', + encoding="utf-8", + ) + return exe_path + + def test_raci_violation_within_allowedpaths_exits_2(self, tmp_path, tmp_repo, run_wrapper): + # Sub-agent writes a *code* artifact that IS within AllowedPaths (no path + # violation) but is the wrong RACI class for Gemini CLI -> RACI audit exit 2, + # and the path-allowed write is NOT restored/deleted. + exe = self._build_writer_exe(tmp_path / "w", "artifacts/code/TASK-raci.code.md", "code\n") + result = run_wrapper( + WRAPPER, + "-Prompt", "hi", + "-Executable", str(exe), + "-MaxRetriesPerTier", "0", + "-BaseBackoffSeconds", "0", + "-AllowedPaths", "artifacts/code/TASK-raci.code.md", + "-AutoRestore", + ) + assert result.returncode == 2, result.combined_output + assert "RACI" in result.combined_output + assert (tmp_repo / "artifacts" / "code" / "TASK-raci.code.md").exists(), ( + "RACI (path-allowed) write must not be deleted/restored" + ) + + def test_raci_allowed_class_within_allowedpaths_passes(self, tmp_path, tmp_repo, run_wrapper): + # Sub-agent writes a *research* artifact within AllowedPaths -> Gemini CLI is + # authorized for the research class -> no RACI violation, exit 0. + exe = self._build_writer_exe(tmp_path / "w", "artifacts/research/TASK-raci.research.md", "research\n") + result = run_wrapper( + WRAPPER, + "-Prompt", "hi", + "-Executable", str(exe), + "-MaxRetriesPerTier", "0", + "-BaseBackoffSeconds", "0", + "-AllowedPaths", "artifacts/research/TASK-raci.research.md", + "-AutoRestore", + ) + assert result.returncode == 0, result.combined_output diff --git a/artifacts/scripts/test_workflow_constants.py b/artifacts/scripts/test_workflow_constants.py index 995dd7b..d32f48d 100644 --- a/artifacts/scripts/test_workflow_constants.py +++ b/artifacts/scripts/test_workflow_constants.py @@ -406,6 +406,24 @@ def test_resolve_policy_for_web_app_requires_build_guarantee(self): def test_rule_tables_are_self_consistent(self): assert wc.validate_workflow_rule_tables() == [] + def test_raci_matrix_includes_council_reviewer(self): + # CHG-004: Codex Reviewer (Council) merged into the single source (subagent_roles.md + # §2). Its R value is one artifact token with no '/', so the hybrid-sync parser (which + # splits the R column on '/') round-trips it as a single-element set. + entry = wc.RACI_MATRIX["Codex Reviewer (Council)"] + assert entry == {"review notes (3 model votes)"} + assert all("/" not in token for token in entry) + + def test_raci_matrix_v2_codex_owns_workflow_contract_docs(self): + # CHG-005: reconcile routing↔RACI — Codex CLI legitimately authors workflow + # contract docs (per plan Files Likely Affected), so RACI_MATRIX_V2 grants the + # workflow_contract_docs category (root cause of 2 historical violations). Other + # categories (e.g. task) still fail-closed. + codex = wc.RACI_MATRIX_V2["Codex CLI"] + assert "workflow_contract_docs" in codex + assert "code" in codex + assert "task" not in codex + # ───────────────────────────────────────────── # validate_context_stack diff --git a/artifacts/scripts/workflow_constants.py b/artifacts/scripts/workflow_constants.py index 23c1321..8c3aa2d 100644 --- a/artifacts/scripts/workflow_constants.py +++ b/artifacts/scripts/workflow_constants.py @@ -74,6 +74,7 @@ "Tester": {"test"}, "Verifier": {"verify"}, "Reviewer": {"review notes"}, + "Codex Reviewer (Council)": {"review notes (3 model votes)"}, } VERIFICATION_ITEM_RESULTS = ( @@ -648,7 +649,7 @@ def classify_path(path_str: str) -> str: RACI_MATRIX_V2: dict[str, frozenset[str]] = { "Claude Code": frozenset({"task", "plan", "decision", "status"}), "Gemini CLI": frozenset({"research", "memory_bank"}), - "Codex CLI": frozenset({"code"}), + "Codex CLI": frozenset({"code", "workflow_contract_docs"}), "Implementer": frozenset({"code"}), "Tester": frozenset({"test"}), "Verifier": frozenset({"verify"}), diff --git a/artifacts/status/TASK-1102.status.json b/artifacts/status/TASK-1102.status.json new file mode 100644 index 0000000..7777af7 --- /dev/null +++ b/artifacts/status/TASK-1102.status.json @@ -0,0 +1,15 @@ +{ + "task_id": "TASK-1102", + "state": "done", + "current_owner": "Claude", + "next_agent": "Claude", + "required_artifacts": ["plan", "status", "task", "verify"], + "available_artifacts": ["status", "task", "research", "plan", "code", "test", "verify"], + "missing_artifacts": [], + "assurance_level": "mvp", + "project_adapter": "docs-spec", + "verification_readiness": "mvp", + "open_verification_debts": [], + "blocked_reason": "", + "last_updated": "2026-07-06T16:05:00+08:00" +} diff --git a/artifacts/status/TASK-1103.status.json b/artifacts/status/TASK-1103.status.json new file mode 100644 index 0000000..4d29c42 --- /dev/null +++ b/artifacts/status/TASK-1103.status.json @@ -0,0 +1,15 @@ +{ + "task_id": "TASK-1103", + "state": "done", + "current_owner": "Claude", + "next_agent": "Claude", + "required_artifacts": ["plan", "status", "task", "verify"], + "available_artifacts": ["status", "task", "research", "plan", "code", "test", "verify"], + "missing_artifacts": [], + "assurance_level": "mvp", + "project_adapter": "docs-spec", + "verification_readiness": "mvp", + "open_verification_debts": [], + "blocked_reason": "", + "last_updated": "2026-07-07T12:05:00+08:00" +} diff --git a/artifacts/status/TASK-1104.status.json b/artifacts/status/TASK-1104.status.json new file mode 100644 index 0000000..c5089ec --- /dev/null +++ b/artifacts/status/TASK-1104.status.json @@ -0,0 +1,28 @@ +{ + "task_id": "TASK-1104", + "state": "done", + "current_owner": "Claude", + "next_agent": "Claude", + "required_artifacts": [ + "plan", + "status", + "task", + "verify" + ], + "available_artifacts": [ + "code", + "plan", + "research", + "status", + "task", + "test", + "verify" + ], + "missing_artifacts": [], + "assurance_level": "mvp", + "verification_readiness": "mvp", + "project_adapter": "docs-spec", + "open_verification_debts": [], + "blocked_reason": "", + "last_updated": "2026-07-07T17:10:00+08:00" +} diff --git a/artifacts/status/TASK-1105.status.json b/artifacts/status/TASK-1105.status.json new file mode 100644 index 0000000..1250946 --- /dev/null +++ b/artifacts/status/TASK-1105.status.json @@ -0,0 +1,30 @@ +{ + "task_id": "TASK-1105", + "state": "done", + "current_owner": "Claude", + "next_agent": "Claude", + "required_artifacts": [ + "code", + "plan", + "status", + "task", + "test", + "verify" + ], + "available_artifacts": [ + "code", + "plan", + "research", + "status", + "task", + "test", + "verify" + ], + "missing_artifacts": [], + "assurance_level": "mvp", + "verification_readiness": "mvp", + "project_adapter": "generic", + "open_verification_debts": [], + "blocked_reason": "", + "last_updated": "2026-07-08T12:42:00+08:00" +} diff --git a/artifacts/status/TASK-1106.status.json b/artifacts/status/TASK-1106.status.json new file mode 100644 index 0000000..5296e72 --- /dev/null +++ b/artifacts/status/TASK-1106.status.json @@ -0,0 +1,28 @@ +{ + "task_id": "TASK-1106", + "state": "done", + "current_owner": "Claude", + "next_agent": "Claude", + "required_artifacts": [ + "plan", + "status", + "task", + "verify" + ], + "available_artifacts": [ + "code", + "plan", + "research", + "status", + "task", + "test", + "verify" + ], + "missing_artifacts": [], + "assurance_level": "mvp", + "verification_readiness": "mvp", + "project_adapter": "docs-spec", + "open_verification_debts": [], + "blocked_reason": "", + "last_updated": "2026-07-08T14:23:00+08:00" +} diff --git a/artifacts/status/TASK-1107.status.json b/artifacts/status/TASK-1107.status.json new file mode 100644 index 0000000..16114bd --- /dev/null +++ b/artifacts/status/TASK-1107.status.json @@ -0,0 +1,38 @@ +{ + "task_id": "TASK-1107", + "state": "done", + "current_owner": "Claude", + "next_agent": "User", + "required_artifacts": [ + "code", + "plan", + "status", + "task", + "test", + "verify" + ], + "available_artifacts": [ + "code", + "decision", + "improvement", + "plan", + "research", + "status", + "task", + "test", + "verify" + ], + "missing_artifacts": [], + "assurance_level": "mvp", + "project_adapter": "generic", + "open_verification_debts": [], + "blocked_reason": "", + "last_updated": "2026-07-17T10:49:24+08:00", + "verification_readiness": "mvp", + "Gate_E_passed": true, + "Gate_E_evidence": [ + "artifacts/improvement/TASK-1107.improvement.md", + "artifacts/decisions/TASK-1107.decision.md" + ], + "Gate_E_timestamp": "2026-07-17T11:24:24+08:00" +} diff --git a/artifacts/status/TASK-1108.status.json b/artifacts/status/TASK-1108.status.json new file mode 100644 index 0000000..d306570 --- /dev/null +++ b/artifacts/status/TASK-1108.status.json @@ -0,0 +1,29 @@ +{ + "task_id": "TASK-1108", + "state": "done", + "current_owner": "Claude", + "next_agent": "Claude", + "required_artifacts": [ + "plan", + "status", + "task", + "verify" + ], + "available_artifacts": [ + "code", + "decision", + "plan", + "research", + "status", + "task", + "test", + "verify" + ], + "missing_artifacts": [], + "assurance_level": "mvp", + "project_adapter": "docs-spec", + "open_verification_debts": [], + "blocked_reason": "", + "last_updated": "2026-07-10T15:00:00+08:00", + "verification_readiness": "mvp" +} diff --git a/artifacts/status/TASK-1109.status.json b/artifacts/status/TASK-1109.status.json new file mode 100644 index 0000000..de31bc0 --- /dev/null +++ b/artifacts/status/TASK-1109.status.json @@ -0,0 +1,29 @@ +{ + "task_id": "TASK-1109", + "state": "done", + "current_owner": "Claude", + "next_agent": "Claude", + "required_artifacts": [ + "plan", + "status", + "task", + "verify" + ], + "available_artifacts": [ + "code", + "decision", + "plan", + "research", + "status", + "task", + "test", + "verify" + ], + "missing_artifacts": [], + "assurance_level": "mvp", + "project_adapter": "docs-spec", + "open_verification_debts": [], + "blocked_reason": "", + "last_updated": "2026-07-10T16:30:00+08:00", + "verification_readiness": "mvp" +} diff --git a/artifacts/status/TASK-1112.status.json b/artifacts/status/TASK-1112.status.json new file mode 100644 index 0000000..25eef28 --- /dev/null +++ b/artifacts/status/TASK-1112.status.json @@ -0,0 +1,27 @@ +{ + "task_id": "TASK-1112", + "state": "done", + "current_owner": "Claude", + "next_agent": "Claude", + "required_artifacts": [ + "plan", + "status", + "task", + "verify" + ], + "available_artifacts": [ + "code", + "plan", + "research", + "status", + "task", + "verify" + ], + "missing_artifacts": [], + "assurance_level": "mvp", + "project_adapter": "docs-spec", + "open_verification_debts": [], + "blocked_reason": "", + "last_updated": "2026-07-17T12:00:00+08:00", + "verification_readiness": "mvp" +} diff --git a/artifacts/tasks/TASK-1102.task.md b/artifacts/tasks/TASK-1102.task.md new file mode 100644 index 0000000..0ca1d83 --- /dev/null +++ b/artifacts/tasks/TASK-1102.task.md @@ -0,0 +1,73 @@ +# Task: TASK-1102 + +## Metadata +- Task ID: TASK-1102 +- Artifact Type: task +- Owner: Claude +- Status: drafted +- Last Updated: 2026-07-06T15:00:00+08:00 + +## Objective + +修正 wrapper write-scope enforcement 之文件與實際行為落差:`-AutoRestore` 決定是否傳給 `Invoke-CodexAgent.ps1` / `Invoke-GeminiAgent.ps1` 的是協調者(Claude),不是 Codex / Gemini 自己;而該 flag 預設 `$false`(detect-only,僅印出違規、exit 0),並非自動擋下。CLAUDE.md 目前完全未提及此點;GEMINI.md 之「違者」敘述仍是舊式絕對敘述,與其正下方已由 TASK-1059/1060 補上的 `-AutoRestore` 條件說明互相矛盾。 + +## Background + +- User 指出:CLAUDE.md 未說明「派發時需顯式傳 `-AutoRestore` 才能讓 write-scope 違規真的被擋下」;CODEX.md、GEMINI.md「違者:dispatch 視為失敗」的絕對敘述應改條件式。 +- **查證結果(與 user 原始假設有一處落差,需在此明示)**:`grep "dispatch 視為失敗"` 全 repo 僅命中 `GEMINI.md:46` 與其 `template/GEMINI.md:46` 鏡像;**`CODEX.md` 並無此字面**。`CODEX.md:75` 的「違者」敘述是「立 decision artifact 說明越界原因」——此為 Codex 自身之**自我回報義務**,與 wrapper 是否真的自動還原無關,本就應維持無條件(不應因 `-AutoRestore` 有無傳遞而改變)。`CODEX.md:76-78` 早已含 `-AutoRestore` 預設 `$false` / detect vs enforce 之條件說明(TASK-1059/1060 已補)。故 **CODEX.md 判定已合規,本 task 不修改 CODEX.md**,僅修改 GEMINI.md 之對應敘述(其 47-48 行雖也已有條件說明,但 46 行本身仍寫「dispatch 視為失敗;Claude 將以 `git checkout HEAD --` 還原」——此為 TASK-1059 stash-based 修復前的舊式全量還原語言,與 2026-05-07 wrapper 破壞事故後改用的 stash-based restore 不符,必須一併移除,不能只加條件包裝)。 +- `Invoke-CodexAgent.ps1` 確認 `-AutoRestore` 預設 `$false`(`artifacts/scripts/Invoke-CodexAgent.ps1:41`);`Invoke-GeminiAgent.ps1` 具同名同預設 flag(結構鏡像 CODEX wrapper)。 +- 本 task 純文件變更(CLAUDE.md 新增段落 + GEMINI.md 一行敘述改寫),不動任何 `.ps1` / `.py` 字面。 + +## Inputs + +- `CLAUDE.md`(新增段落之目標檔) +- `GEMINI.md:40-50`(Write Scope Discipline 段,待改行 46) +- `CODEX.md:69-79`(對照參考,確認已合規、不需修改) +- `artifacts/scripts/Invoke-CodexAgent.ps1:41`(`-AutoRestore` 預設值查證來源) +- `template/CLAUDE.md`、`template/GEMINI.md`(鏡像目標) +- `artifacts/scripts/guard_contract_validator.py`(CLAUDE.md 走 phrase-based 檢查非 EXACT_SYNC;GEMINI.md 屬 `EXACT_SYNC_FILES`,須 SHA-256 全等) +- `artifacts/scripts/drills/prompt_regression_cases.json`(PR-027 對 GEMINI.md pin 之 `Write Scope Discipline` / `Invoke-GeminiAgent.ps1 -AllowedPaths` / `AutoRestore` 三字面,須於改寫後仍存在) + +## Constraints + +- **不修改 CODEX.md**:已查證合規(見 Background);若逕自「條件式改寫」該檔之 decision-artifact 自我回報義務,反而會錯誤地讓自我回報義務變成可繞過。 +- **不得再引用 `git checkout HEAD --` 之全量還原語言**:該語言對應 2026-05-07 wrapper 破壞事故(31 paths 被誤清)之舊行為;TASK-1059 已改為 stash-based restore,GEMINI.md 46 行之新敘述不得重新背書已棄用的還原機制。 +- **GEMINI.md 為 EXACT_SYNC_FILES 成員**:改寫後必須與 `template/GEMINI.md` SHA-256 全等。 +- **CLAUDE.md 為 phrase-based sync(非 EXACT_SYNC)**:新增段落仍須人工 diff 確認 `template/CLAUDE.md` 鏡像同步、且不得覆蓋該檔既有之 downstream-terminal 專屬句(root/template 既有 1 行既知落差)。 +- 新增/修改文字不得觸犯 `prompt_regression_cases.json` 既有 PR-* 之 `must_contain_all` / `all_of_any` 字面 pin(尤其 PR-027 對 GEMINI.md 之三字面)。 +- 依本 repo 慣例先立 task + plan(含 R1-R4 premortem)再動筆;不得跳過 plan gate。 +- 本 task 為純 docs 變更,無 production code;Assurance Level = MVP,Project Adapter = docs-spec(test 段 NOT_APPLICABLE_BY_ADAPTER)。 + +## Acceptance Criteria + +- AC-1: TASK-1102 lifecycle artifacts(task / plan / code / verify / status;test 為 NOT_APPLICABLE_BY_ADAPTER)皆存在且符合 `docs/schemas/` §5;plan 含 R1-R4 premortem,至少 1 條 blocking。 +- AC-2: `CLAUDE.md` 新增一段,明示:(a) 是否傳 `-AutoRestore` 由協調者(Claude)於派發時決定;(b) `-AutoRestore` 預設 `$false`(detect-only,印違規但 exit 0);(c) 需要違規被真正擋下時必須顯式傳遞。 +- AC-3: `GEMINI.md:46` 之「違者」敘述改為條件式,明確區分「顯式傳 `-AutoRestore`」(wrapper 偵測到即 stash-based 還原、exit 2)與「未傳(default detect-only)」(僅印出、exit 0,留待 Claude 自行處置)兩種結果;不得殘留 `git checkout HEAD --` 全量還原語言。 +- AC-4: `CODEX.md` 維持不變(本 task 不修改該檔,Background 已載明理由)。 +- AC-5: `template/CLAUDE.md` 與 `template/GEMINI.md` 同步;`GEMINI.md` / `template/GEMINI.md` SHA-256 全等;`template/CLAUDE.md` 人工 diff 確認僅含既有 1 行落差 + 本次新增段落。 +- AC-6: `python artifacts/scripts/guard_contract_validator.py --root .` 與 `--root . --check-readme` 皆 `[OK]`。 +- AC-7: `python artifacts/scripts/guard_status_validator.py --task-id TASK-1102` 回 `[OK]`。 +- AC-8: `python artifacts/scripts/prompt_regression_validator.py --root .` 全數 PR-* PASS(含既有 PR-027 對 GEMINI.md 之三字面 pin 仍存在)。 +- AC-9: `python -m pytest artifacts/scripts/ -q` 通過數不低於既有 baseline(本 task 未觸任何 `.py`,僅作回歸確認)。 + +## Dependencies + +- 承 TASK-1059(stash-based `-AutoRestore` 安全模式)與 TASK-1060(lifecycle exclusion)已落地之 wrapper 行為;本 task 僅修正文件敘述與行為對齊,不改 wrapper 字面。 + +## Out of Scope + +- 修改 `Invoke-CodexAgent.ps1` / `Invoke-GeminiAgent.ps1` 之 `.ps1` 字面(wrapper 行為本身已正確,僅文件落差)。 +- 修改 `CODEX.md`(已查證合規,見 Background)。 +- 重新設計 write-scope enforcement 架構或新增 CLI flag。 + +## Assurance Level + +MVP + +## Project Adapter + +docs-spec + +## Current Status Summary + +drafted(2026-07-06)。查證完成:CODEX.md 無需修改(已合規);GEMINI.md:46 為唯一需改寫之絕對敘述;`-AutoRestore` 預設 `$false` 已於 `Invoke-CodexAgent.ps1:41` 確認。下一步:planned(R1-R4 premortem)→ Claude 直寫 CLAUDE.md / GEMINI.md + template/ 鏡像 → validator chain → verify → done。 diff --git a/artifacts/tasks/TASK-1103.task.md b/artifacts/tasks/TASK-1103.task.md new file mode 100644 index 0000000..2d48404 --- /dev/null +++ b/artifacts/tasks/TASK-1103.task.md @@ -0,0 +1,79 @@ +# Task: TASK-1103 + +## Metadata +- Task ID: TASK-1103 +- Artifact Type: task +- Owner: Claude +- Status: drafted +- Last Updated: 2026-07-07T10:00:00+08:00 + +## Objective + +為高風險 plan 補上一道「獨立 premortem 質疑」慣例:目前 `## Risks`(R1-R4)由撰寫 plan 的同一個 agent 自行填寫,`guard_status_validator.py` 只依 `docs/premortem_rules.md` P1-P8 檢查格式與用語是否具體,不檢查風險判斷本身是否站得住腳。本任務在 `docs/premortem_rules.md` 新增一節,定義:符合特定高風險條件的 plan,於 `planned → coding` 前,須由撰寫者以外的獨立 agent 對既有 R1-R4 逐條質疑(Detection 是否真的可觸發、有無遺漏的失敗模式),並將結果附掛在 plan 的 `## Risks` 子區段(或於分歧重大時另立 decision artifact),不新增 artifact type、不新增 slash command、不新增自動化 guard 強制。 + +## Background + +- 起因:使用者請一份 ChatGPT 對本專案「Claude/Gemini/Codex 三方協作分工」的意見稿做評估。逐條核對後,多數建議(counter-review artifact、process ledger review、model routing 抽象化)本專案已有對應機制(`/codex-review` Council Reviewer、RACI Auditor/Architecture Synthesizer、`Task Scale` 三層抽象),詳見對話紀錄;ChatGPT 未讀過完整 docs 便提出這些建議。 +- 唯一核實為真缺口:premortem(R1-R4)目前是「自寫自審」——validator 只做格式/用語 lint(P1-P8),不對風險判斷的實質正確性做獨立檢查。既有的獨立審查機制都作用在**其他階段**:Council Reviewer 作用在 code diff 產出之後;RACI Auditor/Architecture Synthesizer 是週期性(每 10 個 PROCESS_LEDGER 或 Sprint Review)批次審查,不是逐 task、逐 plan 觸發。Plan 階段的 R1-R4 本身,從未被撰寫者以外的角色質疑過。 +- 已確認 `docs/premortem_rules.md` 屬於 `EXACT_SYNC_FILES`(`artifacts/scripts/guard_contract_validator.py:64`),現況與 `template/docs/premortem_rules.md` 逐位元組相同(`diff` 無輸出)。 +- 已確認 `docs/schemas/artifact-spec-plan.md` 的 `## Risks` 為單一必要區段,未禁止在其下新增自訂子區段(`### ...`),故可用子區段承載本任務新增內容,不需修改 plan schema 本身。 +- 已確認 `docs/workflow_state_machine.md` 未提及 premortem 相關轉移條件(premortem gate 完全由 `guard_status_validator.py` + `docs/premortem_rules.md` 承載),本任務不需修改該檔。 + +## Inputs + +- `docs/premortem_rules.md`(新增章節之目標檔,含 §1-§11 既有內容需承接一致風格) +- `docs/schemas/artifact-spec-plan.md`(確認 `## Risks` 子區段不受 schema 限制,僅供對照,不修改) +- `CLAUDE.md:36`(STOP 觸發點之 premortem 敘述,需延伸一句) +- `template/docs/premortem_rules.md`、`template/CLAUDE.md`(鏡像目標) +- `artifacts/scripts/drills/prompt_regression_cases.json`(新增 1 條 PR-* pin 新內容,防止未來靜默回退) +- `artifacts/scripts/guard_contract_validator.py:19-70`(EXACT_SYNC_FILES 清單查證來源) + +## Constraints + +- **不新增 artifact type**:質疑結果寫在既有 plan 的 `## Risks` 子區段,或於分歧重大時使用既有 decision artifact,不建立新的 schema 類型。 +- **不新增 slash command / 新 SOP 檔案**:沿用既有 Agent tool / Gemini / Codex 派發機制即可完成「開新 context 的獨立 agent」,不需要新工具。 +- **不新增自動化 guard 強制**:本任務只定義慣例與最低要求文字,不修改 `guard_status_validator.py` 新增程式化檢查(避免在尚無實際執行資料前,就把一個新流程步驟鎖死成強制 gate,過早僵化)。是否日後自動化,留待有實際執行案例後再評估。 +- **避免觸發範圍稀釋**:適用條件刻意只取 `docs/premortem_rules.md` §1 既有清單中的 4 項(security fix / upstream PR / 跨模組或跨 repo / 不熟悉框架版本環境),不納入「無法 100% 確認變更影響範圍」這條主觀性太高的項目,否則幾乎所有任務都會命中,稀釋這道 gate 的訊號。 +- **`docs/premortem_rules.md` 為 EXACT_SYNC_FILES 成員**:改寫後必須與 `template/docs/premortem_rules.md` SHA-256 全等。 +- **`CLAUDE.md` 為 phrase-based sync(非 EXACT_SYNC)**:新增文字仍須人工 diff 確認 `template/CLAUDE.md` 鏡像同步,且不得覆蓋既有 downstream-terminal 專屬句(root/template 既有 1 行既知落差,見 TASK-1102 verify)。 +- 新增/修改文字不得觸犯 `prompt_regression_cases.json` 既有 PR-* 之 `must_contain_all` / `must_not_contain_any` 字面 pin。 +- 依本 repo 慣例先立 task + plan(含 R1-R4 premortem)再動筆;不得跳過 plan gate。 +- 本任務本身**不**觸發本任務新定義的「獨立質疑」機制——因為本任務不屬於 security fix / upstream PR / 跨模組跨 repo / 不熟悉框架版本環境 任一類別(純本 repo 內 docs 治理文字修正),不構成自我遞迴(bootstrap)問題,已於 Plan 明示。 +- 本任務為純 docs 變更,無 production code;Assurance Level = MVP,Project Adapter = docs-spec(test 段 NOT_APPLICABLE_BY_ADAPTER)。 + +## Acceptance Criteria + +- AC-1: TASK-1103 lifecycle artifacts(task / research / plan / code / verify / status;test 為 NOT_APPLICABLE_BY_ADAPTER)皆存在且符合 `docs/schemas/` §5;plan 含 R1-R4 premortem,至少 1 條 blocking。 +- AC-2: `docs/premortem_rules.md` 新增一節(§12),明示:(a) 適用條件(4 類高風險,見 Constraints);(b) 獨立性要求(質疑者不得與撰寫 R1-R4 的 agent 共用同一對話 context/session);(c) 質疑內容最小集合(逐條檢查 Detection 是否可觸發、有無遺漏失敗模式);(d) 輸出位置(plan `## Risks` 下 `### Independent Premortem Challenge` 子區段,或分歧重大時另立 decision artifact);(e) 與 Council Reviewer / RACI Auditor 的分工邊界(階段與頻率皆不重疊);(f) 明示本節不由 validator 自動強制。 +- AC-3: `CLAUDE.md` STOP 觸發點區段(第 3 節)延伸現有 premortem 敘述,納入「高風險 plan 未完成獨立質疑」為 STOP 條件,並指向 `docs/premortem_rules.md` §12。 +- AC-4: `template/docs/premortem_rules.md` 與 `template/CLAUDE.md` 同步;`docs/premortem_rules.md` / `template/docs/premortem_rules.md` SHA-256 全等;`template/CLAUDE.md` 人工 diff 確認僅含既有 1 行落差 + 本次新增內容。 +- AC-5: `python artifacts/scripts/guard_contract_validator.py --root .` 與 `--root . --check-readme` 皆 `[OK]`。 +- AC-6: `python artifacts/scripts/guard_status_validator.py --task-id TASK-1103` 回 `[OK]`。 +- AC-7: `python artifacts/scripts/prompt_regression_validator.py --root .` 全數 PR-* PASS(含新增 1 條對 `docs/premortem_rules.md` §12 與 `CLAUDE.md` 新句之字面 pin)。 +- AC-8: `python -m pytest artifacts/scripts/ -q` 通過數不低於既有 baseline(本任務未觸任何 `.py` 字面邏輯,僅作回歸確認;若因 `template/` 檔案變更觸發 `.well-known/release-manifest.json` 過期,須於本任務內以 `snapshot_manifest.py generate` 補做 regen)。 +- AC-9: plan artifact 明示本任務自身不觸發新定義的獨立質疑機制,並說明理由(避免自我遞迴 bootstrap 疑慮被誤讀為遺漏)。 + +## Dependencies + +- 承既有 `docs/premortem_rules.md` §1-§11、`docs/schemas/artifact-spec-plan.md` §5.3 之既有規則;本任務只新增章節,不修改既有章節語意。 +- 沿用 TASK-1102 已驗證過的 docs-only 工作流路徑(task→research→plan→code→verify→status,Claude 直寫、無需 dispatch Codex)。 + +## Out of Scope + +- 修改 `guard_status_validator.py` 新增自動化強制檢查(見 Constraints,留待未來視執行資料再評估)。 +- 修改 `docs/schemas/artifact-spec-plan.md` 或 `docs/artifact_schema.md`(`## Risks` 子區段已確認不受 schema 限制,無需改 schema 本身)。 +- 修改 `docs/workflow_state_machine.md`(premortem gate 不在該檔承載,已查證確認)。 +- 新增獨立 slash command 或新 `docs/sop/` 檔案(沿用既有 Agent tool / CLI 派發慣例即可)。 +- 回溯套用本機制到既有已完成任務的 plan(本任務僅定義慣例,不追溯)。 + +## Assurance Level + +MVP + +## Project Adapter + +docs-spec + +## Current Status Summary + +drafted(2026-07-07)。查證完成:`docs/premortem_rules.md` 為 EXACT_SYNC 成員且現況與 template 一致;plan schema 之 `## Risks` 子區段不受限制,可承載新內容而不需改 schema;`docs/workflow_state_machine.md` 無需修改。下一步:research(收斂既有機制邊界佐證)→ planned(R1-R4 premortem,含本任務不自我觸發之說明)→ Claude 直寫 `docs/premortem_rules.md` §12 + `CLAUDE.md` STOP 延伸 + template/ 鏡像 + PR-* 新增 → validator chain → verify → done。 diff --git a/artifacts/tasks/TASK-1104.task.md b/artifacts/tasks/TASK-1104.task.md new file mode 100644 index 0000000..0be9a45 --- /dev/null +++ b/artifacts/tasks/TASK-1104.task.md @@ -0,0 +1,87 @@ +# Task: TASK-1104 + +## Metadata +- Task ID: TASK-1104 +- Artifact Type: task +- Owner: Claude +- Status: drafted +- Last Updated: 2026-07-07T15:20:00+08:00 + +## Objective + +把「Occam's razor(以使用數據找候選拆除項)」與「Chesterton's Fence(拆前查 provenance)」制度化為單一的規則生命週期盤點循環:新增 `docs/sop/rule_lifecycle_audit.md` 定義循環三步(Occam pass → Chesterton gate → 記錄)、四值裁決(`retire` / `relax` / `keep` / `open`)與退場記錄格式;觸發時機與 architecture-synthesizer 同軌(PROCESS_LEDGER 條目達 N=10 倍數,或使用者手動發起)。同時把目前僅存於 Claude 私人 memory 的 validator relaxation 案例沉澱為 in-repo 盤點輸入檔 `artifacts/improvement/RELAXATION_LOG.md`。純 SOP 承載:不新增腳本、不新增自動化 guard、不新增 artifact type。 + +## Background + +- 起因:使用者請 Claude 評估本 workflow 哪些環節適用 Occam's razor 與 Chesterton's Fence。評估結論:templates/validator 粒度/wrapper flag 組合是 Occam 地盤;`-AutoRestore` 預設/Build Guarantee/scope-drift guard 是 Chesterton 地盤;裁決線是「立規理由是否可查」。使用者裁示把兩原則制度化為同一循環,並經 `/plan` 三問確認:純 SOP 文件、搭 N=10 ledger 同軌、附帶處理 relaxation log 沉澱與退場記錄格式兩個 gap。 +- 既有先例:CHG-013 以 `real_dispatch_count=0` 歸檔 4 個 zero-dispatch templates(`docs/templates/archive/README.md:7`),是 Occam pass 的手工雛形;scope-drift guard Layer-1 調查「查無立規理由 → OPEN 不拍板」(2026-07-02)是 Chesterton gate 的先例。兩者目前皆為 ad-hoc,無 SOP、無節奏保證(上次 unified audit 距今隔約兩個月)。 +- 既有觸發軌:`docs/templates/architecture-synthesizer/TEMPLATE.md:11` 已定義「PROCESS_LEDGER.md 累積條目達 N=10 倍數,或使用者手動觸發」;本任務掛同一軌,不新增觸發機制。 +- 已確認 `AGENTS.md`、`docs/sop/*`(現有 4 檔)、`artifacts/scripts/guard_contract_validator.py`、`artifacts/scripts/drills/prompt_regression_cases.json` 皆為 `EXACT_SYNC_FILES` 成員(`artifacts/scripts/guard_contract_validator.py:19-78`);新 SOP 檔需新增 EXACT_SYNC 條目。 +- 已確認 `template/artifacts/improvement/PROCESS_LEDGER.md` 存在(template 為 skeleton 鏡像慣例),`artifacts/improvement/` 下新檔需建對應 template skeleton,但不屬 EXACT_SYNC(root 版含真實案例,template 版為泛化 skeleton)。 + +## Inputs + +- `.omc/plans/rule-lifecycle-audit-cycle.md`(已核准之規劃稿,交付物與 AC 之上游來源) +- `artifacts/research/TASK-1104.research.md`(in-repo 事實查證) +- `docs/templates/archive/README.md`(`real_dispatch_count` 慣例與 revivable 退場先例) +- `docs/templates/architecture-synthesizer/TEMPLATE.md`(N=10 觸發軌,需加 cross-ref) +- `artifacts/improvement/PROCESS_LEDGER.md`(§維護規則需加同軌一句) +- `.github/memory-bank/workflow-gates.md`(relaxation 既有規則記載,cross-ref 對象) +- `artifacts/scripts/guard_contract_validator.py:19-78`(EXACT_SYNC_FILES 清單,需新增條目) +- `AGENTS.md`(文件模組表需新增一列) +- TASK-1061 / TASK-1058 相關 artifacts(relaxation 案例 provenance 查證來源) + +## Constraints + +- **純 SOP 承載**:不新增任何腳本、不修改 `guard_status_validator.py` 邏輯、不新增自動化 guard 檢查、不新增 artifact type、不新增 slash command。`guard_contract_validator.py` 僅允許在 `EXACT_SYNC_FILES` 清單新增字串條目(非邏輯變更)。 +- **SOP 行數上限 150 行**(Occam 自律:防止防增生機制自身增生),且全文不得要求未來新增腳本或 guard。 +- **EXACT_SYNC 紀律**:新 SOP 檔、`AGENTS.md`、`guard_contract_validator.py`、`prompt_regression_cases.json` 之變更必須 root 與 `template/` 逐位元組相同;`docs/templates/` 與 `artifacts/improvement/` 之鏡像依既有慣例同動(非 EXACT_SYNC 者允許泛化差異)。 +- **RELAXATION_LOG 職責切分**:log 只記事實(日期/規則/放寬前後摘要/觸發 task/根因分類),規則敘述一律 cross-ref `.github/memory-bank/workflow-gates.md`,兩檔不得出現相同段落字面。 +- **provenance 誠實**:RELAXATION_LOG 每筆的 in-repo citation 查得到才寫;查不到的欄位明標 `provenance: unrecorded`,不得以記憶補洞。 +- 新增文字不得觸犯 `prompt_regression_cases.json` 既有 PR-* 之 `must_contain_all` / `must_not_contain_any` 字面 pin。 +- 本任務觸及 EXACT_SYNC 敏感集(`guard_contract_validator.py` 等),closure 適用 CHG-012/HC-1 A2 之 `## Diff Evidence` 條件必填規則(見 `docs/schemas/artifact-spec-code.md` 欄位規則);於 dirty worktree closure 時由 live check 承載,若日後 clean replay 需依規則補 evidence。 +- 本任務不觸發 `docs/premortem_rules.md` §12 獨立質疑:非 security fix、非 upstream PR、非跨 repo、非不熟悉框架;屬本 repo 內 docs 治理變更(同 TASK-1103 先例),已於 plan 明示。 +- 本任務為純 docs/治理文字變更(`.py` 僅動字串清單),Assurance Level = MVP、Project Adapter = docs-spec(test 段 NOT_APPLICABLE_BY_ADAPTER)。 + +## Acceptance Criteria + +- AC-1: TASK-1104 lifecycle artifacts(task / research / plan / code / verify / status;test 為 NOT_APPLICABLE_BY_ADAPTER)皆存在且符合 `docs/schemas/` §5;plan 含 premortem(≥3 條風險、≥1 條 blocking)。 +- AC-2: `docs/sop/rule_lifecycle_audit.md` 存在,定義循環三步(Occam pass / Chesterton gate / 記錄),四值裁決 `retire` / `relax` / `keep` / `open` 各有判準與記錄欄位(含 retire 之復活路徑欄位,沿用 template archive 之 `git mv` revivable 慣例)。 +- AC-3: SOP 觸發條款明文含兩路徑:「PROCESS_LEDGER 條目達 N=10 倍數(與 architecture-synthesizer 同批)」與「使用者隨時手動發起」。 +- AC-4: SOP 含「查無 provenance → `open`:不拆也不加碼,補記錄留待下輪」條款,並引 scope-drift guard Layer-1(2026-07-02 OPEN 裁定)為先例。 +- AC-5: SOP 總行數 ≤ 150(以 `Get-Content | Measure-Object -Line` 或 `wc -l` 驗證);全文無「新增腳本」「新增自動化 guard」之要求;含自我引用條款(本 SOP 自身列入每輪盤點對象;若 N=10 軌長期未觸發,下輪檢討改綁 unified audit)。 +- AC-6: `artifacts/improvement/RELAXATION_LOG.md` 存在,含 4 筆既有放寬案例(CITATION_PATTERN、RESEARCH_SOURCES_ENTRY_PATTERN、generic→docs-spec adapter、available_artifacts mismatch),每筆含日期/規則位置/前後摘要/觸發 task/根因分類;in-repo citation 查得到才寫,查不到者標 `provenance: unrecorded`;內嵌「累積 ≥ 3 案例 → 升級 architect review」條款。 +- AC-7: RELAXATION_LOG 與 `.github/memory-bank/workflow-gates.md` 互為 cross-ref,兩檔無相同段落字面(人工 diff 抽查)。 +- AC-8: `AGENTS.md` 文件模組表新增 `docs/sop/rule_lifecycle_audit.md` 一列(載入時機:Closure / 盤點觸發時);root 與 `template/AGENTS.md` 逐位元組相同。 +- AC-9: `artifacts/improvement/PROCESS_LEDGER.md` §維護規則與 `docs/templates/architecture-synthesizer/TEMPLATE.md` §Trigger 各加一句同軌 cross-ref(指向新 SOP);對應 template/ 鏡像同動。 +- AC-10: `guard_contract_validator.py` 之 `EXACT_SYNC_FILES` 新增 `docs/sop/rule_lifecycle_audit.md` 條目(root 與 template 兩份同改);`python artifacts/scripts/guard_contract_validator.py --root .` 與 `--root . --check-readme` 皆 `[OK]`;所有 EXACT_SYNC 觸及檔 SHA-256 逐對全等。 +- AC-11: `python artifacts/scripts/guard_status_validator.py --task-id TASK-1104` 回 `[OK]`。 +- AC-12: `python artifacts/scripts/prompt_regression_validator.py --root .` 全數 PR-* PASS,含新增 1 條對新 SOP 關鍵字面(四值裁決 + OPEN 條款)之 pin。 +- AC-13: `python -m pytest artifacts/scripts/ -q` 通過數不低於既有 baseline;若 template/ 變更觸發 `.well-known/release-manifest.json` 過期,於本任務內以 `snapshot_manifest.py generate` 補做 regen。 +- AC-14: code artifact 之 `## Files Changed` ⊆ plan 之 `## Files Likely Affected`;觸及 EXACT_SYNC 敏感集之 closure 依 CHG-012 規則處置 `## Diff Evidence`(dirty-worktree closure 由 live check 承載時於 verify 明記)。 + +## Dependencies + +- 承 `docs/templates/architecture-synthesizer/TEMPLATE.md` 既有 N=10 觸發定義(只 cross-ref,不重複定義、不修改其語意)。 +- 承 TASK-1055 建立之 `docs/sop/` 目錄慣例與 EXACT_SYNC 條目新增先例。 +- 承 TASK-1103 驗證過之 docs-only 完整 lifecycle 路徑(task→research→plan→code→verify→status)。 + +## Out of Scope + +- 修改 `guard_status_validator.py` 或任何 validator 邏輯(EXACT_SYNC_FILES 字串清單新增除外)。 +- 新增 dispatch 統計腳本或自動觸發機制(使用者已裁示純 SOP;若日後要自動化,依本 SOP 自身的盤點循環另立 task)。 +- 執行第一輪實際盤點(本任務只建立制度;首輪盤點於下次 N=10 或手動觸發時執行)。 +- 回溯改寫既有已歸檔 template 或既有放寬案例的 decision artifacts。 +- 修改 `docs/security_cadence.md` 或任何 GitHub Actions workflow。 + +## Assurance Level + +MVP + +## Project Adapter + +docs-spec + +## Current Status Summary + +drafted(2026-07-07)。查證完成:EXACT_SYNC_FILES 現況(guard_contract_validator.py:19-78)、docs/sop/ 既有 4 檔、architecture-synthesizer N=10 觸發軌、template/artifacts/improvement/ 鏡像慣例。下一步:research artifact(沉澱 in-repo 事實)→ plan(premortem R1-R5)→ dispatch Codex 實作 → validator chain → verify → done。 diff --git a/artifacts/tasks/TASK-1105.task.md b/artifacts/tasks/TASK-1105.task.md new file mode 100644 index 0000000..87a5c4a --- /dev/null +++ b/artifacts/tasks/TASK-1105.task.md @@ -0,0 +1,71 @@ +# Task: TASK-1105 + +## Metadata +- Task ID: TASK-1105 +- Artifact Type: task +- Owner: Claude +- Status: drafted +- Last Updated: 2026-07-07T21:23:10+08:00 + +## Objective + +查明 2026-07-07 12:00-15:00 之間出現的 pytest 環境漂移根因:(a) 4 個 wrapper stdin 測試失敗(`test_invoke_codex_agent.py` ×2、`test_invoke_gemini_agent.py` ×2,症狀為 fake exe 讀到的 stdin 前綴含字面值 `U+FEFF` BOM);(b) skipped 由 2 增至 19(+17)。產出可覆核的根因診斷與修復建議;修復本身視診斷結果決定是否併入本 task 或另立。 + +## Background + +- TASK-1103 verify(2026-07-07 12:00 記錄)之 pytest baseline 為 `2037 passed / 2 skipped / 0 failed`。 +- TASK-1104 驗收(同日 15:00 後)之 pytest 為 `2016 passed / 19 skipped / 4 failed`;HEAD(0986deb)乾淨 worktree 對照組為 `2015 passed / 19 skipped / 5 failed`(4 個 BOM failures 相同;多的 1 個 `test_get_repo_root_resolves_true_root` 為 linked-worktree 環境特有)。 +- 兩次總數皆 2039,TASK-1104 diff 未觸碰任何 wrapper 或其測試檔 → 漂移為環境性(machine/shell 層),非 repo 變更所致。 +- 失敗斷言例:`assert prompt in stdin_seen` 失敗於 `'xxx...' in '\ufeffxxx...\n'`(`test_invoke_gemini_agent.py:356`)。 +- Codex CLI 於自身 shell 環境跑 pytest 亦得相同 4 failures(TASK-1104 dispatch 中回報),初步暗示 machine 層變動而非單一 harness 專屬。 +- 相關既有記錄:wrapper stdin pipe 機制由 TASK-1062 修 Bug-W4 時引入(stdin threshold 降至 0,Codex/Gemini 雙 wrapper);known bugs 清單見 memory `feedback_wrapper_known_bugs.md`。 + +## Inputs + +- `artifacts/scripts/test_invoke_codex_agent.py`(TestCodexBugBStdinAlways 兩失敗測試) +- `artifacts/scripts/test_invoke_gemini_agent.py`(TestGeminiBugBStdinAlways 兩失敗測試,:356 斷言) +- `artifacts/scripts/Invoke-CodexAgent.ps1` / `Invoke-GeminiAgent.ps1`(stdin pipe 實作) +- `artifacts/scripts/conftest.py`(test harness / fake exe 機制) +- pytest `-rs` 輸出(19 個 skip 之 reason 清單) +- PowerShell 環境現況:`$PROFILE` 各檔 mtime、pwsh 版本、`[Console]::InputEncoding` / `$OutputEncoding` 預設 +- `artifacts/verify/TASK-1104.verify.md` §Evidence(兩組對照數據之出處) + +## Constraints + +- 診斷階段 read-only:不修改 wrapper、測試、或任何 shell profile;先取證再議修復。 +- 每個根因結論必須有可重現證據(命令 + 輸出),不接受「疑似」定案;查證不到的環節如實標 UNVERIFIED。 +- 若根因在 repo 外(如 pwsh 版本更新、Windows update、profile 變動),修復方案需區分「repo 側加固(測試/wrapper 對 BOM 容錯)」與「環境側還原」兩路,分別評估,不預設擇一。 +- 修復(若併入本 task)不得改變 wrapper 之 stdin pipe 語意(TASK-1062 Bug-W4 修復不可回退)。 +- 遵循 CLI-first;診斷過程之臨時輸出不落 repo(用 scratchpad)。 + +## Acceptance Criteria + +- AC-1: research artifact 含 4 個 BOM failures 之根因鏈:BOM 由哪一端引入(test harness 寫入 stdin?wrapper 轉手?pwsh 讀入行為?)、對應的具體機制(附檔案行號或命令證據)。 +- AC-2: research artifact 含 12:00-15:00 之間實際變動源之定位或排除清單(pwsh 版本、$PROFILE mtime、相關 Windows 元件),查證不到者明標 UNVERIFIED。 +- AC-3: 19 個 skip 之 reason 分類(pytest -rs),並判定 +17 增量與 BOM 根因是否同源。 +- AC-4: 修復建議含至少兩路(repo 側容錯 vs 環境側還原)之利弊與建議擇一,或診斷後證明僅一路可行並說明。 +- AC-5: 若修復併入本 task:修復後 `python -m pytest artifacts/scripts -q` 回 `0 failed` 且 passed 數 ≥ 2016;若另立 task,本 task 以 research + decision 收案。 +- AC-6: lifecycle artifacts 符合 schema;guard_status_validator --task-id TASK-1105 [OK]。 + +## Dependencies + +- TASK-1104 verify artifact 之對照取證(baseline 數據來源)。 +- TASK-1062 之 stdin pipe 修復脈絡(Bug-W4;修復方案不可與其衝突)。 + +## Out of Scope + +- 回溯改寫 TASK-1103 / TASK-1104 之 verify 記錄。 +- wrapper stdin pipe 機制重設計(僅允許 BOM 容錯層級之最小修補)。 +- 與本漂移無關之其他 pytest skip 既有項(原有 2 個 skip)。 + +## Assurance Level + +MVP + +## Project Adapter + +generic + +## Current Status Summary + +drafted(2026-07-07)。下一步:research(Claude 直接於本機取證——pwsh 版本/profile mtime/encoding 現況、失敗測試細節、pytest -rs skip 清單、BOM 引入點定位)→ 依診斷結果決定修復路徑與 routing。 diff --git a/artifacts/tasks/TASK-1106.task.md b/artifacts/tasks/TASK-1106.task.md new file mode 100644 index 0000000..8c51fe4 --- /dev/null +++ b/artifacts/tasks/TASK-1106.task.md @@ -0,0 +1,78 @@ +# Task: TASK-1106 + +## Metadata +- Task ID: TASK-1106 +- Artifact Type: task +- Owner: Claude +- Status: drafted +- Last Updated: 2026-07-08T13:00:00+08:00 + +## Objective + +把三個經專案實證支撐的治理名詞顯性化進 Governance Lenses 表(`docs/orchestration.md` §2.8):**Goodhart's Law**(validator schema-pleasing 現象之統攝名詞)、**Normalization of Deviance**(detect-only 違規連續被接受之風險)、**Swiss Cheese Model**(多層防禦穿透分析);同時依 OODA 先例明文拒絕 Campbell's Law(與 Goodhart 同構,不並存)。並以最輕形態把兩條操作條文補進既有 SOP:dispatch SOP 加「fallback tier 產出預設不可信,逐 tier 直驗」;rule lifecycle audit SOP 加「使用數據只產生候選不產生裁決」與「同型 detect-only 違規連續接受達 3 次必須裁 relax 或轉強制」。介紹文件(README §Two-Layer Governance)補 lenses 指引敘述。不新增分層、schema、gate、檔案或腳本。 + +## Background + +- 起因:使用者請 Claude 研究既有原則以外的常見治理模型並評估適用性;評估依「repo 內有無真實事故/機制可對應」篩選,三個入選名詞各有實證:(a) Goodhart——`artifacts/improvement/RELAXATION_LOG.md` 四案之共同根因即「機械式 schema-pleasing 過驗」;(b) Normalization of Deviance——TASK-1104/1105 兩次 dispatch 之 write-scope/RACI 違規均經人工 review 後接受,detect-and-accept 正在例行化;(c) Swiss Cheese——TASK-1104 verify 之 literal U+FEFF 穿過 pytest 時序孔洞、被 prompt-injection 掃描層於 TASK-1105 攔下,為完整穿透案例。使用者 2026-07-08 裁示以最輕形態制度化並更新介紹文件。 +- Governance Lenses 表位於 `docs/orchestration.md:149-172`,其紀律為「不另立分層、不另建 schema、不另設階段」;「明確拒絕:OODA」段(:162-172)為同構名詞不並存之先例,Campbell's Law 拒絕記錄依此形態。 +- 已確認 README/README.zh-TW/OBSIDIAN/BOOTSTRAP 均無治理視角敘述(Grep 無命中);`README.md:188-195` 之 `### Two-Layer Governance (PDCA × TAO/ReAct)` 為介紹文件之自然錨點。 +- `docs/orchestration.md`、`docs/sop/dispatch_implementation.md`、`docs/sop/rule_lifecycle_audit.md` 皆為 `EXACT_SYNC_FILES` 成員(`artifacts/scripts/guard_contract_validator.py:19-78`,rule_lifecycle_audit 條目由 TASK-1104 加入)。 + +## Inputs + +- `docs/orchestration.md:149-172`(Governance Lenses 表 + OODA 拒絕段) +- `docs/sop/dispatch_implementation.md`(fallback-tier 條文目標檔) +- `docs/sop/rule_lifecycle_audit.md`(McNamara 防呆 + deviance 條款目標檔;TASK-1104 建,行數上限 150) +- `README.md:188-195` 與 `README.zh-TW.md` 對應段(介紹文件錨點) +- `artifacts/improvement/RELAXATION_LOG.md`(Goodhart 之機制落點) +- `.github/memory-bank/workflow-gates.md`(Swiss Cheese 之落點候選) +- TASK-1104/1105 verify artifacts(三名詞之實證出處) +- `artifacts/scripts/drills/prompt_regression_cases.json`(PR-* pin 目標) + +## Constraints + +- **不另立分層、不另建 schema、不另設階段、不新增檔案或腳本**(Governance Lenses 表之既有紀律;本任務只增表列與既有檔內句子)。 +- Campbell's Law 拒絕記錄依 OODA 段形態(同構對照 + 不並存宣告),但篇幅壓縮至 2-3 行,不做完整對照表。 +- `docs/sop/rule_lifecycle_audit.md` 修改後總行數仍 ≤ 150(TASK-1104 AC-5 之持續義務)。 +- EXACT_SYNC 紀律:orchestration.md、兩 SOP、prompt_regression_cases.json 之變更 root/template 逐位元組同;README 依 §10 README contract(`--check-readme`)。 +- 新增文字不得觸犯既有 PR-* 字面 pin;本任務新增 1 條 PR-* pin 錨定三名詞與 Campbell 拒絕句。 +- Routing override:Claude 直寫(docs-only 治理文字、TASK-1102/1103 已驗證路徑;Codex credits 於 TASK-1105 dispatch 中段耗盡且未確認回充,避免無效 dispatch),理由記於 plan。 +- 本任務不觸發 premortem §12 獨立質疑(非 security/upstream/跨 repo/不熟悉框架;同 TASK-1103/1104 先例),於 plan 明示。 +- Assurance Level = MVP、Project Adapter = docs-spec(test 段 NOT_APPLICABLE_BY_ADAPTER)。 + +## Acceptance Criteria + +- AC-1: lifecycle artifacts(task/research/plan/code/verify/status;test NOT_APPLICABLE_BY_ADAPTER)皆存在且符合 schema;plan 含 premortem ≥3 條、≥1 blocking。 +- AC-2: `docs/orchestration.md` §2.8 Governance Lenses 表新增 3 列(Goodhart's Law / Normalization of Deviance / Swiss Cheese Model),各含所管問題、對應現有機制、文件落點;每列之「對應現有機制」引用真實存在的機制(RELAXATION_LOG ≥3 升級、rule lifecycle audit deviance 條款、guard 疊層 + improvement Why Not Prevented)。 +- AC-3: `docs/orchestration.md` 明確拒絕段新增 Campbell's Law 記錄(與 Goodhart 同構、不並存、依 OODA 先例),2-3 行。 +- AC-4: `docs/sop/dispatch_implementation.md` 新增 fallback-tier 條文:fallback tier(如 gpt-5.4-mini)產出預設不可信,驗收逐 tier 讀 dispatch log 並以命令直驗(引 TASK-1105 Bug-B3 為出處)。 +- AC-5: `docs/sop/rule_lifecycle_audit.md` Step 1 加「使用數據只產生候選,不產生裁決」;加 deviance 條款「同型 detect-only 違規連續接受達 3 次,當輪必須裁 `relax` 或轉強制(`-AutoRestore`),不得停留於 detect-and-accept」;修改後總行數 ≤ 150。 +- AC-6: `README.md` §Two-Layer Governance 補 governance lenses 指引敘述(含新三名詞、指向 orchestration.md §2.8);`README.zh-TW.md` 對應段同步。 +- AC-7: 所有觸及之 EXACT_SYNC 檔 root/template SHA-256 逐對全等;`guard_contract_validator.py --root .` 與 `--root . --check-readme` 皆 `[OK]`。 +- AC-8: `prompt_regression_validator.py --root .` 全 PASS,含新增 1 條 pin(三名詞 + Campbell 拒絕句字面)。 +- AC-9: `python -m pytest artifacts/scripts -q`(bash 語境,per project-facts 慣例)0 failed 且 passed ≥ 2037;template 變更觸發 manifest 過期時於本任務內 regen。 +- AC-10: `guard_status_validator.py --task-id TASK-1106` 各階段 `[OK]`。 + +## Dependencies + +- TASK-1104(rule lifecycle audit SOP 之存在與行數上限義務)、TASK-1105(Bug-B3/W5 實證出處、project-facts pytest 語境慣例)。 +- `docs/orchestration.md` §2.8 之 Governance Lenses 紀律與 OODA 拒絕先例(TASK-1001)。 + +## Out of Scope + +- 修改 improvement artifact schema(Swiss Cheese 之逐層分析僅作為 lens 表敘述與未來 postmortem 實踐指引,不改 §5.9 required fields)。 +- 顯性化評估中列為「已隱性覆蓋」之名詞(Defense in Depth、Poka-yoke、SoD 等——維持現狀不掛名牌)。 +- Brooks's Law/Ashby/Parkinson/Lindy/Campbell(Campbell 僅作拒絕記錄)。 +- 任何 validator 邏輯、wrapper、自動化變更。 + +## Assurance Level + +MVP + +## Project Adapter + +docs-spec + +## Current Status Summary + +drafted(2026-07-08)。範圍實查完成:lenses 表與 OODA 段位置、README 錨點、介紹文件無既有敘述、EXACT_SYNC 身分。下一步:research(沉澱實查事實)→ plan(premortem)→ Claude 直寫 → validator chain → verify → done。 diff --git a/artifacts/tasks/TASK-1107.task.md b/artifacts/tasks/TASK-1107.task.md new file mode 100644 index 0000000..7770062 --- /dev/null +++ b/artifacts/tasks/TASK-1107.task.md @@ -0,0 +1,83 @@ +# Task: TASK-1107 + +## Metadata +- Task ID: TASK-1107 +- Artifact Type: task +- Owner: Claude +- Status: drafted +- Last Updated: 2026-07-17T10:45:00+08:00 + +## Objective + +合併修復 `/ultrareview`(`codex-review ultra`)對 PR #50 產出的兩條 CONFIRMED findings,並將修復追加為新 commit 到分支 `manifest-exec-unified-audit-2026-07-03`(PR #50 因此自動更新,不新開 PR): + +1. **bug_002(normal)— CHG-012 gate 可被 `None (理由)` 形態繞過**:`artifacts/scripts/guard_status_validator.py` 內判斷 clean-task closure 是否已附 `## Diff Evidence` 的邏輯採 exact-tuple 比對(`diff_evidence.lower() in ("", "none", "n/a")`),只要文字不是逐字等於這三者之一(例如 `None (this task was completed via alternate verification)`)即被視為「已提供證據」而放行,實質上讓 HC-1 A2 要求的可重播 Diff Evidence 被一句夾帶理由的「None (...)」文字繞過。 +2. **bug_001(nit)— RACI 單一真源宣告互指成環**:`docs/subagent_roles.md` §2 開頭仍寫「RACI 與 agent capability 矩陣已拆分至 `docs/raci-matrix.md`」,但 `docs/raci-matrix.md`(CHG-004 已反轉真源方向)現在寫「單一真源為 `docs/subagent_roles.md` §2」。兩檔互指對方為真源,形成無法解析的循環引用。 + +## Background + +- 起因:使用者於 2026-07-08 對 PR #50 執行 ultrareview(`/code-review ultra`),Codex 多模型 council review 回報上述兩條 CONFIRMED findings;使用者當場裁示「先記著」,未立即修復,記入 memory(`pending-task-1107-ultrareview-fixes`)待 Codex 用量恢復後執行(見 `.claude/projects/.../memory/project_pending_task_1107_ultrareview_fixes.md`)。2026-07-17 使用者確認 Codex 用量已恢復,指示接續。 +- 本次 Intake 已直接對照現行程式碼重新查證(非僅信任 8 天前的 memory 快照): + - bug_002 現狀:`artifacts/scripts/guard_status_validator.py:2250` 之 `if sensitive_hits and diff_evidence.lower() in ("", "none", "n/a"):` 仍為現行邏輯,尚未修復。 + - bug_001 現狀:`docs/subagent_roles.md:56`(`RACI 與 agent capability 矩陣已拆分至 [docs/raci-matrix.md](raci-matrix.md)(原 \`docs/subagent_roles.md\` §2)。`)與 `docs/raci-matrix.md:3,7`(`本檔之 §2 角色總表已回歸單一真源 docs/subagent_roles.md §2`/`RACI 與 agent capability 矩陣之單一真源為 docs/subagent_roles.md §2`)仍互指成環,尚未修復。 +- `artifacts/scripts/guard_status_validator.py`、其三個 test 檔(`test_guard_status_validator_artifacts.py` 等)與 `docs/subagent_roles.md` 均為 `EXACT_SYNC_FILES` 成員(`artifacts/scripts/guard_contract_validator.py` 內列表已直驗),root/`template/` 皆須逐位元組同步;`docs/raci-matrix.md` 不在 EXACT_SYNC_FILES 列表中,但 root/template 亦各有一份副本需一併修改以維持語意一致(非 guard 強制,但屬 Chesterton's Fence 下的合理範圍延伸——不同步將讓 template 側留下同款循環引用)。 +- Memory 記錄之修法(`de = diff_evidence.strip().lower()` 後改判 `sensitive_hits and (de.startswith(("none", "n/a")) or "evidence type:" not in de)`)已對照現行合法證據格式初步驗證語意完備性,惟此版本於 Planning 階段 §12 獨立 premortem 質疑中被發現仍有繞過路徑(詳見 Amendment)。 + +**Amendment(2026-07-17,Planning 階段 §12 獨立質疑後)**:獨立 subagent 質疑發現,原字串子句 `"evidence type:" not in de` 對一段**非結構化**自由文字(不以 `bullet` 格式書寫、但文字中任意位置含有 `evidence type:` 字樣且不以 `none`/`n/a` 開頭,例如 `"No Evidence Type: applicable -- verified via manual code review instead of diff replay."`)仍會誤判為已提供合法證據;已用 Python 直接執行覆現此繞過。最終採用之修法改為重用既有 `parse_diff_evidence()`(`guard_status_validator.py:612`)+ `DIFF_EVIDENCE_SUPPORTED_TYPES`(`guard_status_validator.py:160`)結構化解析,取代原字串啟發式;已實測驗證此修正版對繞過文字攔截、對兩種合法格式(`commit-range`、`github-pr`)放行不誤傷。詳見 `artifacts/plans/TASK-1107.plan.md` `## Risks` R1/R6 與 `### Independent Premortem Challenge`、`artifacts/research/TASK-1107.research.md` Confirmed Facts 第 3 條(同步修正)。本 Task artifact 之 AC-2 與下方 Constraints 描述之「可攔截繞過情形」目標不變,僅實作手段由字串比對修正為結構化解析。 +- Memory 另記「review 之 reasoning 有一處錯(聲稱 `subagent_roles.md` 不在 EXACT_SYNC——實際在)」;本 task 已用 `guard_contract_validator.EXACT_SYNC_FILES` 直接查值確認 `docs/subagent_roles.md` 確實在列表內,修復時以此為準,不採信 ultrareview reasoning 原文的錯誤陳述。 + +## Inputs + +- `artifacts/scripts/guard_status_validator.py:2101-2260`(`is_sensitive_guard_path` 與 CHG-012 gate 邏輯) +- `artifacts/scripts/test_guard_status_validator_artifacts.py:2840-2934`(`TestCleanTaskDiffEvidenceCHG012` 既有測試類別) +- `docs/subagent_roles.md:50-58`(RACI 拆分宣告句) +- `docs/raci-matrix.md:1-10`(RACI 單一真源宣告句) +- `template/artifacts/scripts/guard_status_validator.py`、`template/artifacts/scripts/test_guard_status_validator_artifacts.py`、`template/docs/subagent_roles.md`、`template/docs/raci-matrix.md`(EXACT_SYNC / 語意同步鏡射) +- memory:`pending-task-1107-ultrareview-fixes`(原始 ultrareview 發現與初步修法草案) + +## Constraints + +- 只修復上述兩條 CONFIRMED findings;不擴大範圍處理 ultrareview report 中其他非 CONFIRMED 或未提及項目。 +- `guard_status_validator.py` 的修法必須維持向後相容:既有 `TestCleanTaskDiffEvidenceCHG012` 全部 case(含 `test_sensitive_with_commit_range_evidence_passes`、`test_non_sensitive_transition_unchanged`、`test_sensitive_no_evidence_revalidation_flag_false_passes`)須持續通過,不得因新邏輯而 regress。 +- 新增測試需覆蓋 `None (理由)`(含全形 `None(...)` 形態,對照 TASK-1095/TASK-1099 之既有夾帶文字模式)之繞過 case,確認修法後被正確攔下。 +- `docs/subagent_roles.md` 之修法用語需與 `docs/raci-matrix.md` 現行句對齊(後者已是 CHG-004 反轉後之正確方向),不得反向修改 `raci-matrix.md` 去配合 `subagent_roles.md` 的舊句。 +- EXACT_SYNC 紀律:`guard_status_validator.py`、三個 test 檔、`docs/subagent_roles.md` 之 root/`template/` 版本須逐位元組相同;`docs/raci-matrix.md` 雖非 EXACT_SYNC 成員,仍須語意同步兩份副本,避免 template 側殘留循環引用。 +- 不得修改 CHG-012 gate 之整體設計(仍維持「clean-task closure 觸及 sensitive set 需附 Diff Evidence」的既有政策),本次只修其判斷邏輯的漏洞。 +- 修復完成後追加 commit 至現有分支 `manifest-exec-unified-audit-2026-07-03`(PR #50 隨之自動更新),不建立新分支或新 PR。 + +## Acceptance Criteria + +- AC-1: lifecycle artifacts(task / research / plan / code / test / verify / status)皆存在且符合 schema;plan 之 `## Risks` 含 ≥3 條、≥1 條 `Severity: blocking`(validator 邏輯修改屬 code 類 premortem 門檻)。 +- AC-2: `guard_status_validator.py` 之 CHG-012 判斷邏輯改為可攔截「文字以 `none` 或 `n/a` 開頭但夾帶額外文字」與「缺少 `Evidence Type:` 行」兩類繞過情形,同時不影響現行兩種合法 Evidence Type(`commit-range`、`github-pr`)通過。 +- AC-3: `test_guard_status_validator_artifacts.py` 之 `TestCleanTaskDiffEvidenceCHG012` 新增至少兩條繞過測試:(a) `None (理由)` 形態(含至少一個全形 `None(...)` 變體);(b) §12 獨立質疑發現之 R6 非結構化自由文字繞過(含 `evidence type:` 字樣但非 bullet 格式);兩者皆驗證修法後被攔下(`errs` 非空)。 +- AC-4: 既有 `TestCleanTaskDiffEvidenceCHG012` 全部既有 test case 修法後仍全數通過(不得 regress)。 +- AC-5: `docs/subagent_roles.md:56` 附近之 RACI 拆分宣告句改為宣告本檔 §2 即單一真源,與 `docs/raci-matrix.md` 現行句(§2 已回歸 `docs/subagent_roles.md` 單一真源)語意一致、不再互指成環。 +- AC-6: 所有觸及之 EXACT_SYNC 檔(`guard_status_validator.py`、三個 test 檔、`docs/subagent_roles.md`)root/`template/` SHA-256 逐對全等;`docs/raci-matrix.md` root/template 語意同步(人工核對,非 guard 強制)。 +- AC-7: `guard_contract_validator.py --root .` 通過(`[OK]`,無新增 EXACT_SYNC drift)。 +- AC-8: `python -m pytest artifacts/scripts -q` 0 failed,passed 數不低於本 task 開始前之基線(先跑一次記錄基線數字,修復後對照不得減少,且應因新增測試而增加)。 +- AC-9: `guard_status_validator.py --task-id TASK-1107` 各階段轉移 `[OK]`。 +- AC-10: 修復完成後產生新 commit 並 push 至 `manifest-exec-unified-audit-2026-07-03`,PR #50 因此自動更新;commit hash 記錄於 verify artifact 之 Build Guarantee。 + +## Dependencies + +- 原始 ultrareview(`/code-review ultra`)對 PR #50 之 Council review 結果(僅存於 memory,本 task 之 research artifact 需將其轉為可查證的 artifact-level 事實)。 +- `docs/raci-matrix.md` 現行單一真源方向由 CHG-004(TASK 編號未於本任務內查證,僅引用現行檔案內容)已反轉,本 task 依現行檔案內容為準,不重新考證 CHG-004 本身。 + +## Out of Scope + +- ultrareview report 中任何非 CONFIRMED 或本 task 未列出之 finding。 +- `artifacts/code/TASK-1105.code.md:61` 之「fabricated(Bug-B1 模式)」括注勘誤——memory 註記為「可併入本 task 或首輪 audit」之順手項,但與本 task 兩條 CONFIRMED findings 無直接關聯,且會擴大本次修復範圍與 diff 邊界;留待首輪 rule lifecycle audit 或獨立 task 處理,此處僅留下可追溯的指標(避免遺忘,但不在本 task 內動手)。 +- CHG-012 gate 之整體政策設計變更、Evidence Type 種類擴充、或其他 guard 邏輯之非本次 finding 相關修改。 +- `docs/subagent_roles.md` §2 表格內容本身(角色列表)之任何調整——本 task 只修拆分宣告句的措辭方向。 + +## Assurance Level + +MVP + +## Project Adapter + +generic + +## Current Status Summary + +drafted(2026-07-17)。已對現行程式碼重新查證兩條 finding 皆仍存在(非僅信任 8 天前 memory 快照);下一步:research(落地查證事實與修法語意完備性佐證)→ plan(premortem,含 §12 獨立質疑——本任務修改 guard/gate 邏輯,屬安全性相關修補)→ Codex 實作(bug_002 為 validator 邏輯變更,risk ≥ 3)→ Claude 驗收 → 追加 commit 至 PR #50。 diff --git a/artifacts/tasks/TASK-1108.task.md b/artifacts/tasks/TASK-1108.task.md new file mode 100644 index 0000000..fd96326 --- /dev/null +++ b/artifacts/tasks/TASK-1108.task.md @@ -0,0 +1,86 @@ +# Task: TASK-1108 + +## Metadata +- Task ID: TASK-1108 +- Artifact Type: task +- Owner: Claude +- Status: drafted +- Last Updated: 2026-07-10T15:00:00+08:00 + +## Objective + +在既有 Governance Lenses 表(`docs/orchestration.md` §2.8,TASK-1001 建立、TASK-1106 擴充至 9 視角)之上,以最輕形態新增 6 個互補治理視角:**Hyrum's Law**(相容性視角)、**Reversibility & Blast Radius**、**Separation of Duties**、**Least Privilege**、**Gall's Law**、**Modernized Postel's Law**;並依同一紀律明文拒絕獨立 Policy Engine(OPA/Rego/CEL)。所有新增皆為文件、選填 metadata、SOP 候選訊號條文與測試 pin,**不新增分層、不新增強制 schema 欄位、不新增 validator 自動化邏輯、不新增 CI gate**。三個既有核心原則(Chesterton's Fence / Occam's Razor / Premortem)維持不變,不被取代。 + +## Background + +- 使用者提供之 mission brief 描述 council-forge v0 已有 Chesterton's Fence / Occam's Razor / Premortem 三原則,並要求疊加 Hyrum's Law 相容性視角,再新增 Goodhart's Law、Reversibility & Blast Radius、Separation of Duties、Least Privilege、Gall's Law、Modernized Postel's Law 六個互補原則,且明文列出多項 hard constraint(不建 policy engine、不自動刪 guard、不把 unknown 當安全、不合併 test/production telemetry 等)。 +- 實查發現:mission brief 所述之部分名詞(Goodhart's Law、Normalization of Deviance、Swiss Cheese Model)**已於 2 天前的 TASK-1106(2026-07-08,commit `7a2a2ed`)落地**,位於 `docs/orchestration.md:149-179` 之 Governance Lenses 表與「明確拒絕:OODA / Campbell's Law」段。本任務範圍因此收斂為**delta**:只新增尚未存在的 6 個視角,不重複新增 Goodhart。 +- **Chesterton's Fence 衝突與使用者裁決**:`TASK-1106.task.md` Out of Scope 明文將 Separation of Duties 列為「顯性化評估中列為『已隱性覆蓋』之名詞……維持現狀不掛名牌」。本次 mission 明確要求具名新增,且提供可落地之具體規則(author 不得為高風險變更之唯一審查者;AI 產生之 guard/schema/CI/相容契約變更需獨立審查步驟)。已於 Intake 階段以 AskUserQuestion 呈現此衝突,使用者選擇**推翻 TASK-1106 之裁決**,理由記於本 task 與 plan:具體規則可落於既有 Council Reviewer(`docs/subagent_roles.md` §5.1.3)+ premortem §12 獨立質疑機制之上,賦予其治理意圖顯性名稱,而非重新定義新機制。 +- **ADR template 之 Chesterton's Fence**:mission 要求「Add ADR template prompts」,但 `docs/templates/archive/adr/TEMPLATE.md` 已於 TASK-1050 建立後因 2 個月零 dispatch(`real_dispatch_count=0`)而被歸檔(`docs/templates/archive/README.md:7`)。目前作用中的決策機制是 `artifacts/decisions/TASK-XXX.decision.md`(`docs/schemas/artifact-spec-decision.md`)。本任務**不復活**已歸檔範本(無新使用證據推翻歸檔理由),改把 mission 要求的提示問題(blast radius / reversibility / rollback / reviewer independence / least-privilege)以既有 `## Guard Exception` 條件式可選 block 之同一慣例,新增至 `artifact-spec-decision.md` 的作用中 decision schema。 +- Task 編號選 **TASK-1108**(而非 repo 中下一個空號 TASK-1107):使用者 memory 中 TASK-1107 已保留給另一件待辦(ultrareview PR#50 findings 修復),尚未建立 artifact 但編號視為已預訂,跳號避免未來衝突。 + +## Inputs + +- `docs/orchestration.md:149-179`(Governance Lenses 表 + OODA/Campbell 拒絕段,擴充錨點) +- `artifacts/tasks/TASK-1106.task.md`、`artifacts/research/TASK-1106.research.md`、`artifacts/verify/TASK-1106.verify.md`(既有格式與紀律先例) +- `docs/sop/rule_lifecycle_audit.md`(Occam Pass 候選訊號擴充目標;≤150 行義務延續,TASK-1104 AC-5 / TASK-1106 AC-5) +- `artifacts/improvement/RELAXATION_LOG.md`(Goodhart eval/intervention telemetry 分離條文目標) +- `docs/schemas/artifact-spec-decision.md`(Reversibility/Blast Radius/Rollback/Reviewer Independence/Least Privilege 選填 block 目標) +- `docs/subagent_roles.md` §1.3、§5.1.3(Separation of Duties / Least Privilege 對應現有機制引用來源) +- `README.md:199`、`README.zh-TW.md:199`(lens 名單句擴充錨點) +- `artifacts/scripts/guard_contract_validator.py:19-79`(EXACT_SYNC_FILES 成員清單) +- `artifacts/scripts/drills/prompt_regression_cases.json`(PR-038 既有 pin 內容,須避免破壞;新增 1 條 PR-039 pin) + +## Constraints + +- **不另立分層、不另建強制 schema 欄位、不另設階段、不新增 validator 自動化邏輯或 CI gate**(Governance Lenses 表既有紀律之延伸;Occam + Gall's Law 之直接應用)。 +- 不修改既有已落地且被 PR-038 pin 之字面(Goodhart's Law / Normalization of Deviance / Swiss Cheese Model 三列、Campbell's Law 拒絕段、rule_lifecycle_audit.md 之 deviance 強制裁決句);只在既有文字之後**新增**。 +- `docs/sop/rule_lifecycle_audit.md` 修改後總行數仍 ≤ 150(TASK-1104 AC-5 之持續義務)。 +- 不復活 `docs/templates/archive/adr/`;decision schema 新增欄位皆為**條件式可選**(比照既有 `## Guard Exception` 慣例),無自動 validator 強制。 +- 不修改任何 `.py` validator 邏輯、wrapper、CI workflow 定義、secrets、deployment 設定。 +- EXACT_SYNC 紀律:`docs/orchestration.md`、`docs/subagent_roles.md`、`docs/sop/rule_lifecycle_audit.md`、`artifacts/scripts/drills/prompt_regression_cases.json` 之變更 root/template 逐位元組同;README 依 `--check-readme` contract。 +- 新增文字不得觸犯既有 PR-* pin;新增 1 條 PR-039 pin 錨定 6 個新視角 + Policy Engine 拒絕句。 +- Routing:Claude 直寫(docs-only 治理文字;本任務之 Intake 探查已累積目標檔案精確行號與既有機制引用,重新餵入 Codex 之 context 成本高於直寫風險;比照 TASK-1106 已驗證路徑)。覆寫理由記於 plan §Routing。 +- 本任務不觸發 premortem §12 獨立質疑(非 security/upstream PR/跨 repo/不熟悉框架;同 TASK-1103/1104/1106 先例,僅為 repo 內文件跨檔修改,非「跨 repo」),於 plan 明示。 +- Assurance Level = MVP、Project Adapter = docs-spec(test 段 NOT_APPLICABLE_BY_ADAPTER)。 + +## Acceptance Criteria + +- AC-1: lifecycle artifacts(task/research/plan/code/verify/status;test NOT_APPLICABLE_BY_ADAPTER)皆存在且符合 schema;plan 含 premortem ≥3 條、≥1 blocking。 +- AC-2: `docs/orchestration.md` §2.8 Governance Lenses 表新增 6 列(Hyrum's Law / Reversibility & Blast Radius / Separation of Duties / Least Privilege / Gall's Law / Modernized Postel's Law),各含所管問題、對應現有機制(引用真實存在之機制)、文件落點;既有 9 列與 OODA/Campbell 拒絕段字面不變。 +- AC-3: `docs/orchestration.md` 新增「明確拒絕:獨立 Policy Engine(OPA/Rego/CEL)」段,2-4 行,依 OODA/Campbell 先例形態(同構論證或 Gall's Law 直接論證 + 不採宣告 + 不得引為翻案範本)。 +- AC-4: `docs/sop/rule_lifecycle_audit.md` Step 1 Occam Pass 候選訊號清單新增:高 blast-radius 變更缺 rollback/migration notes、僅以單一指標作為移除唯一理由、guard 被刪除卻無替代機制或 decision 記錄、欄位查無消費者(unknown consumer,且明示 unknown consumer ≠ no consumer,不得視為安全)四類候選訊號;既有句子字面不變;修改後總行數 ≤150。 +- AC-5: `artifacts/improvement/RELAXATION_LOG.md` §Rules 新增一句:本檔記錄之 intervention telemetry(實際放寬案例)與 `guard_calibration_matrix.py` 量測之 evaluation telemetry(FP/FN)為兩種不同來源,不得合併成單一治理指標。 +- AC-6: `docs/schemas/artifact-spec-decision.md` 新增條件式可選區段 `## Reversibility & Blast Radius`(欄位:Reversibility / Blast Radius / Rollback Plan / Reviewer Independence / Least Privilege Notes),比照既有 `## Guard Exception` 慣例;enum 值含 `unknown`,並明文「unknown 視為尚待查明,不得等同安全/低風險/零風險」;欄位規則段落註明消費者為後續審查者與週期性 architect review(Occam:非自動 validator 強制)。 +- AC-7: `docs/subagent_roles.md` §1.3 新增 Separation of Duties 與 Least Privilege 之顯性條文:(a) 高風險變更(涉及 guard/schema/CI gate/相容契約)之 author 不得為唯一審查者,須有 Council Reviewer 或獨立 agent session 之 review 記錄;(b) 破壞性操作(guard 刪除、CI 放寬、secret 變更、schema-breaking 變更)需經 `guard_status_validator.py --override --override-approver` 或使用者明確核准方可執行。 +- AC-8: `README.md` 與 `README.zh-TW.md` §Two-Layer Governance 之 lens 名單句(各檔第 199 行)附加 6 個新名詞,其餘既有名詞與句構不變。 +- AC-9: 所有觸及之 EXACT_SYNC 檔 root/template SHA-256 逐對全等;`guard_contract_validator.py --root .` 與 `--root . --check-readme` 皆 `[OK]`。 +- AC-10: `prompt_regression_validator.py --root .` 全 PASS,含新增 1 條 PR-039 pin(6 個新視角名 + Policy Engine 拒絕句字面)。 +- AC-11: `python -m pytest artifacts/scripts -q`(bash 語境,per project-facts 慣例)0 failed;跑前後皆檢查 `Documents/Code/.git` 空目錄殘骸是否再現(TASK-1106 觀察項);template 變更觸發 manifest 過期時於本任務內 regen。 +- AC-12: `guard_status_validator.py --task-id TASK-1108` 各階段 `[OK]`。 +- AC-13: decision artifact 記錄 SoD 推翻 TASK-1106 裁決之理由、ADR template 不復活之理由、routing override 理由三項。 + +## Dependencies + +- TASK-1106(Governance Lenses 表之存在、既有 9 視角字面、EXACT_SYNC 成員關係、PR-038 pin)。 +- TASK-1104(rule lifecycle audit SOP 之存在與 150 行上限義務)。 + +## Out of Scope + +- 修改或復活 `docs/templates/archive/adr/`(無新使用證據推翻歸檔理由)。 +- 任何 validator(`.py`)邏輯、wrapper、CI workflow 定義、自動化警告產生器(無現存 nightly report / telemetry rollup 腳本可擴充;Gall's Law:無真實使用資料前不新建自動化)。 +- 修改既有 9 個 lens 列或 OODA/Campbell 拒絕段之字面(PR-038 pin 保護對象)。 +- Goodhart's Law 重複新增(已存在,只補 eval/intervention telemetry 分離句於 RELAXATION_LOG)。 +- secrets、deployment 設定、remote repository 設定之任何變更。 + +## Assurance Level + +MVP + +## Project Adapter + +docs-spec + +## Current Status Summary + +drafted(2026-07-10)。範圍實查完成:既有 Governance Lenses 表現況、TASK-1106 SoD 裁決衝突(使用者已裁推翻)、ADR template 歸檔理由(不復活)、EXACT_SYNC 成員清單、PR-038 pin 內容、decision/subagent_roles 現有機制引用點皆已核實。下一步:research(沉澱實查事實)→ plan(premortem)→ Claude 直寫 → validator chain → verify → decision → closure。 diff --git a/artifacts/tasks/TASK-1109.task.md b/artifacts/tasks/TASK-1109.task.md new file mode 100644 index 0000000..f9fc441 --- /dev/null +++ b/artifacts/tasks/TASK-1109.task.md @@ -0,0 +1,83 @@ +# Task: TASK-1109 + +## Metadata +- Task ID: TASK-1109 +- Artifact Type: task +- Owner: Claude +- Status: drafted +- Last Updated: 2026-07-10T16:30:00+08:00 + +## Objective + +在 TASK-1108 剛落地的 Governance Lenses 表(15 視角)之上,新增 **Lucas Critique**(政策回饋/建制變動視角)為第 16 個具名 lens;並把 **Campbell's Law** 的操作性規則(不得以原始指標值直接證明安全/價值/品質、標記高風險指標、記錄 gaming vectors、不得獎勵人為製造事件)**併入既有 Goodhart's Law 列**,不新增一個與 Goodhart's Law 重複、且會與 TASK-1106 之「明確拒絕:Campbell's Law」段自相矛盾的獨立 lens。所有新增皆為既有檔案內之文字增量與條件式可選 metadata,不新增分層、不新增強制 schema 欄位、不新增 validator 自動化邏輯、不新增 CI gate、不引入 policy engine。 + +## Background + +- 使用者提供之 mission brief 要求新增 Campbell's Law 與 Lucas Critique 兩個治理視角。實查發現 `docs/orchestration.md:183-185` 已有「明確拒絕:Campbell's Law」段(TASK-1106,PR-038 pin 鎖定字面「明確不採 Campbell's Law」),理由為「與 Goodhart's Law 同構、依 OODA 先例不並存」,且明文「任何後續 task 不得引此決策為 routing override 範本」。此為比 TASK-1108 之 SoD 案更強的既有裁決(有獨立段落 + machine-pinned literal + 明文禁止翻案)。 +- 已於 Intake 階段以 AskUserQuestion 呈現此衝突,使用者選擇**併入既有 Goodhart's Law 視角**(不新增獨立 lens row、不動既有拒絕段之 pinned 字面),與使用者自身提供之 hard constraint「Keep Campbell's Law under the metric integrity / Goodhart area」一致。 +- Lucas Critique 未見於任何既有文件(grep 無命中),且與既有 9+6 視角皆不同構,無 Chesterton's Fence 衝突,可直接新增為獨立 lens。 +- 對應現有機制盤點:Occam Pass(`docs/sop/rule_lifecycle_audit.md` Step 1)已隱性做到「使用數據只產生候選,不產生裁決」——這正是 Campbell's Law「不得以原始指標值直接證明」之精神,可延伸補上「不得獎勵人為事件」之具體規則。RELAXATION_LOG.md 之 Before/After/Trigger Task 記錄格式、與 rule lifecycle audit 之 `relax`/`retire` 裁決,皆為既有之「政策建制變動事件」記錄機制,可作為 Lucas Critique 之落點,但目前未要求「跨建制變動不可直接比較」之顯性標註。 +- Decision schema 已於 TASK-1108 建立 `## Reversibility & Blast Radius` 條件式可選 block 先例,本任務比照同一慣例新增 `## Metrics Policy`(Campbell)與 `## Policy Regime`(Lucas)兩個條件式可選區段。 + +## Inputs + +- `docs/orchestration.md:161,169,183-185`(Goodhart 列、表尾插入點、Campbell 拒絕段) +- `docs/sop/rule_lifecycle_audit.md:16-22`(Occam Pass,Campbell 操作化落點) +- `artifacts/improvement/RELAXATION_LOG.md:5-10`(§Rules,Lucas 操作化落點) +- `docs/schemas/artifact-spec-decision.md:58-69`(`## Reversibility & Blast Radius` 先例,供比照新增 `## Metrics Policy` / `## Policy Regime`) +- `README.md:199`、`README.zh-TW.md:199`(lens 名單句,僅新增 Lucas Critique 一個名詞) +- `artifacts/scripts/drills/prompt_regression_cases.json`(PR-038/PR-039 既有 pin,須避免破壞;新增 PR-040) +- TASK-1108 之全套 artifact 與 template-sync 慣例(含 Post-Sync Amendment 教訓:EXACT_SYNC_FILES 之外但慣例同步之檔案需主動核對) + +## Constraints + +- **不修改**「明確拒絕:Campbell's Law」段落之既有 pinned 字面(「本框架已採 Goodhart's Law,明確不採 Campbell's Law」;PR-038 依賴此字面);只在其後**新增**操作化附註段落。 +- **不新增**獨立 Campbell's Law lens row;Campbell's Law 之操作規則併入既有 Goodhart's Law 列(可修改該列之其餘欄位文字,因 PR-038 僅 pin `"Goodhart's Law"` 子字串本身)。 +- 不修改 OODA、Normalization of Deviance、Swiss Cheese Model、TASK-1108 六視角之既有 pinned 字面。 +- `docs/sop/rule_lifecycle_audit.md` 修改後總行數仍 ≤ 150(現況 54 行,延續 TASK-1104 AC-5 義務)。 +- 新增之 `## Metrics Policy`/`## Policy Regime` 皆為條件式可選、無自動 validator 強制,比照 `## Reversibility & Blast Radius` 慣例。 +- 不修改任何 `.py` validator 邏輯、wrapper、CI workflow 定義、secrets、deployment 設定;不引入 policy engine(OPA/Rego/CEL 等,既有拒絕段已涵蓋,不重複宣告)。 +- EXACT_SYNC 紀律:`docs/orchestration.md`、`docs/sop/rule_lifecycle_audit.md`、`prompt_regression_cases.json` 之變更 root/template 逐位元組同。**吸取 TASK-1108 教訓**:`docs/schemas/artifact-spec-decision.md`、`artifacts/improvement/RELAXATION_LOG.md`(§Rules 段)、`README.md`/`README.zh-TW.md` 雖不在 `EXACT_SYNC_FILES` 清單,但依 TASK-1108 Post-Sync Amendment 確立之既有同步慣例,本任務主動同步至對應 template 檔,不等 advisor 提醒。 +- Routing:Claude 直寫(docs-only 治理文字,直接延續 TASK-1108 同一 session 之已建立 context,無需重新 dispatch)。 +- 本任務不觸發 premortem §12 獨立質疑(非 security/upstream PR/跨 repo/不熟悉框架;同 TASK-1103/1104/1106/1108 先例);Campbell's Law 併入決策本身已透過 AskUserQuestion 取得使用者獨立確認,非 Claude 單方判斷。 +- Assurance Level = MVP、Project Adapter = docs-spec(test 段 NOT_APPLICABLE_BY_ADAPTER)。 + +## Acceptance Criteria + +- AC-1: lifecycle artifacts(task/research/plan/code/test/verify/status/decision)皆存在且符合 schema;plan premortem ≥3 條、≥1 blocking。 +- AC-2: `docs/orchestration.md` Goodhart's Law 列更新,含 Campbell's Law 併入註記與高風險指標規則;既有「Goodhart's Law」子字串(PR-038 依賴)仍存在。 +- AC-3: `docs/orchestration.md` 新增 Lucas Critique 列(所管問題/對應現有機制/文件落點皆指向真實存在或本次同批新增之機制)。 +- AC-4: `docs/orchestration.md`「明確拒絕:Campbell's Law」段落後新增操作化附註段落;原段落既有文字(含「明確不採 Campbell's Law」)逐字不變。 +- AC-5: `docs/sop/rule_lifecycle_audit.md` Step 1 新增 Campbell's Law 操作化句(不得以原始指標值證明安全/價值/品質;不得獎勵人為製造之 guard 觸發/警告壓制/淺層覆蓋/僅改善指標之變更);既有句字面不變;總行數 ≤150。 +- AC-6: `artifacts/improvement/RELAXATION_LOG.md` §Rules 新增 Lucas Critique 句(regime-change 案例須標註,跨建制 telemetry 比較須附正規化或但書)。 +- AC-7: `docs/schemas/artifact-spec-decision.md` 新增條件式可選 `## Metrics Policy`(campbell_risk / high_stakes_metric / gaming_vectors / metric_interpretation)與 `## Policy Regime`(regime_id / changed_at / changed_by / comparable_to_previous / baseline_reset_required / adaptation_expected / notes)兩區段,各含規則段落明示「可選、無自動 validator 強制、消費者為審查者與 architect review」。 +- AC-8: `README.md`/`README.zh-TW.md` lens 名單句新增「Lucas Critique」一個名詞(不新增 Campbell's Law 名詞);`template/README.md`/`template/README.zh-TW.md` 同步(吸取 TASK-1108 教訓,本任務內主動完成,不留待 Post-Sync Amendment)。 +- AC-9: 所有觸及之 EXACT_SYNC 檔(orchestration.md、rule_lifecycle_audit.md、prompt_regression_cases.json)root/template SHA-256 逐對全等;`artifact-spec-decision.md`、`RELAXATION_LOG.md` 亦主動同步至 template 對應檔並確認 byte-identical(decision schema)或 §Rules 段一致(RELAXATION_LOG);`guard_contract_validator.py --root .` 與 `--root . --check-readme` 皆 `[OK]`。 +- AC-10: `prompt_regression_validator.py --root .` 全 PASS,含新增 PR-040(Lucas Critique 名稱 + Campbell 併入附註字面 + Metrics Policy / Policy Regime 區段標題);PR-038/PR-039 依舊全 pass。 +- AC-11: `python -m pytest artifacts/scripts -q`(bash 語境)0 failed;跑前後檢查 `Documents/Code/.git` 殘骸(延續 TASK-1108 觀察義務);manifest 過期時 regen。 +- AC-12: `guard_status_validator.py --task-id TASK-1109` 各階段 `[OK]`。 +- AC-13: decision artifact 記錄 Campbell's Law 併入(而非新增獨立 lens)之理由與使用者裁決來源。 + +## Dependencies + +- TASK-1108(decision schema 條件式可選 block 先例、EXACT_SYNC 教訓、Governance Lenses 表現況 15 視角)。 +- TASK-1106(Goodhart's Law 列與 Campbell's Law 拒絕段之原始建立與 PR-038 pin)。 + +## Out of Scope + +- 修改 OODA、Policy Engine 兩個既有拒絕段之字面。 +- 新增獨立 Campbell's Law lens row(使用者已裁併入 Goodhart's Law)。 +- 任何 validator(`.py`)邏輯、wrapper、CI workflow 定義、自動化警告產生器(Gall's Law:無真實使用資料前不新建自動化,延續 TASK-1108 範圍界線)。 +- `docs/templates/archive/` 之任何復活。 + +## Assurance Level + +MVP + +## Project Adapter + +docs-spec + +## Current Status Summary + +drafted(2026-07-10)。Campbell's Law 衝突已於 Intake 以 AskUserQuestion 解決(併入 Goodhart's Law);Lucas Critique 無既有衝突,可直接新增。下一步:research(沉澱實查事實)→ plan(premortem)→ Claude 直寫 → validator chain → verify → decision → closure。 diff --git a/artifacts/tasks/TASK-1112.task.md b/artifacts/tasks/TASK-1112.task.md new file mode 100644 index 0000000..d21c50f --- /dev/null +++ b/artifacts/tasks/TASK-1112.task.md @@ -0,0 +1,58 @@ +# Task: TASK-1112 + +## Metadata +- Task ID: TASK-1112 +- Artifact Type: task +- Owner: Claude +- Status: drafted +- Last Updated: 2026-07-17T12:00:00+08:00 + +## Objective + +把 TASK-1107 improvement artifact 記錄之兩條 caller-side dispatch 操作紀律正式寫入 SOP 文件本體:(1) dispatch 因工具逾時中斷後不得盲目重派,須先確認底層 process 是否存活;(2) dispatch wrapper 之 stdout/stderr 重導向路徑必須在 repo 工作樹之外。 + +## Background + +TASK-1107 dispatch 期間發生一次操作事故:前景 dispatch 因 harness 逾時中斷,Claude 誤判為已終止並發起併發背景 dispatch,導致 git conflict markers;wrapper post-dispatch write-scope guard 又誤將 Claude 自己重導向到 repo 內的 log 檔判定為越界寫入,觸發 `git stash pop` 衝突。事故已於 `artifacts/improvement/TASK-1107.improvement.md` 記錄根因與預防措施文字,但當時明確記為「尚未落地到 SOP 文件本體」,理由是避免 TASK-1107 自身 scope 膨脹。TASK-1107 已 done,本任務為其正式落地。 + +## Inputs + +- `artifacts/improvement/TASK-1107.improvement.md` §5 Preventive Action (System Level)(兩條規則之原文措辭來源) +- `docs/sop/dispatch_implementation.md`(既有 `### Fallback tier 產出之驗收紀律(TASK-1106)` 為同形態先例) +- `docs/dispatch_prompt_discipline.md` + +## Constraints + +- 純文字追加,不新增檔案、不改既有規則語意、不改 gate/validator 邏輯。 +- 依既有先例形態(`### <規則名>(TASK-XXXX)`)追加,不重新編號既有章節。 +- EXACT_SYNC 紀律:兩份目標檔之 root/`template/` 須逐位元組相同。 +- Routing override:Claude 直寫(docs-only 治理文字、非 security/upstream/跨 repo/不熟悉框架,同 TASK-1106 先例),理由記於本檔;不觸發 premortem §12 獨立質疑。 + +## Acceptance Criteria + +- AC-1: `docs/sop/dispatch_implementation.md` 新增「Dispatch 逾時重派紀律(TASK-1112)」條文,明確要求逾時後重派前確認底層 process 存活。 +- AC-2: `docs/dispatch_prompt_discipline.md` 新增「Dispatch Wrapper Log 重導向路徑紀律(TASK-1112)」條文,明確要求重導向路徑須在 repo 外部。 +- AC-3: 兩份目標檔之 root/`template/` SHA-256 逐對全等;`guard_contract_validator.py --root .` `[OK]`。 +- AC-4: `prompt_regression_validator.py --root .` 全 PASS(不影響既有 pin)。 +- AC-5: `python -m pytest artifacts/scripts -q` 無新增 regression(對照 TASK-1107 收尾時之基線 `5 failed, 2034 passed, 2 skipped`)。 + +## Dependencies + +- TASK-1107(improvement artifact 之原文措辭來源) + +## Out of Scope + +- 自動化 enforcement(例如 guard 偵測 caller 是否真的遵循此紀律)——本任務僅落地文件層規則,不新增程式碼機制。 +- TASK-1111(既有 git-root/basetemp pytest 失敗)之修復。 + +## Assurance Level + +MVP + +## Project Adapter + +docs-spec + +## Current Status Summary + +drafted(2026-07-17)。Claude 直寫已完成,待驗證與收尾。 diff --git a/artifacts/test/TASK-1102.test.md b/artifacts/test/TASK-1102.test.md new file mode 100644 index 0000000..af0184b --- /dev/null +++ b/artifacts/test/TASK-1102.test.md @@ -0,0 +1,39 @@ +# Test Report: TASK-1102 + +## Metadata +- Task ID: TASK-1102 +- Artifact Type: test +- Owner: Claude +- Status: pass +- Last Updated: 2026-07-06T15:50:00+08:00 + +## Test Scope + +NOT_APPLICABLE_BY_ADAPTER — docs-spec adapter 之 task scope 為純 agent 入口檔文字修正 + prompt_regression anchor 追加 + template/ 鏡像,無 production code 變更,無需 unit test 撰寫。governance enforcement 由 PR-035(prompt_regression)+ EXACT_SYNC / phrase-check(contract validator)雙層 validator 守住。 + +## Commands Executed + +雖無 unit test 新增,本 task 之 acceptance 仍依以下 validator 跑列: + +- `python artifacts/scripts/guard_contract_validator.py --root .` +- `python artifacts/scripts/guard_contract_validator.py --root . --check-readme` +- `python artifacts/scripts/guard_status_validator.py --task-id TASK-1102` +- `python artifacts/scripts/prompt_regression_validator.py --root .` +- `python -m pytest artifacts/scripts/ -q` +- `diff CLAUDE.md template/CLAUDE.md` / `diff GEMINI.md template/GEMINI.md` / `sha256sum GEMINI.md template/GEMINI.md`(人工 mirror 核對) + +## Result Summary + +PASS(NOT_APPLICABLE_BY_ADAPTER)— validator chain 全綠;GEMINI.md / template/GEMINI.md SHA-256 全等;CLAUDE.md / template/CLAUDE.md diff 僅剩既有 1 行落差;無 test gap 餘留。詳細跑列證據落 verify artifact §Evidence。 + +## Failures + +None + +## Evidence Files + +落 `artifacts/verify/TASK-1102.verify.md` §Evidence。 + +## Recommendation + +接 verify。本 task NOT_APPLICABLE_BY_ADAPTER 屬 docs-spec 之合規路徑(per docs/artifact_schema.md §5.1 之 adapter rule resolution);validator chain 全綠且 PR-035 keyword pin 啟用即視為 enforcement 已就位。 diff --git a/artifacts/test/TASK-1103.test.md b/artifacts/test/TASK-1103.test.md new file mode 100644 index 0000000..a2d1d2c --- /dev/null +++ b/artifacts/test/TASK-1103.test.md @@ -0,0 +1,39 @@ +# Test Report: TASK-1103 + +## Metadata +- Task ID: TASK-1103 +- Artifact Type: test +- Owner: Claude +- Status: pass +- Last Updated: 2026-07-07T11:20:00+08:00 + +## Test Scope + +NOT_APPLICABLE_BY_ADAPTER — docs-spec adapter 之 task scope 為 `docs/premortem_rules.md` 新增章節 + `CLAUDE.md` STOP 觸發點延伸 + prompt_regression anchor 追加 + template/ 鏡像,無 production code 變更,無需 unit test 撰寫。governance enforcement 由 PR-036(prompt_regression)+ EXACT_SYNC(contract validator)雙層 validator 守住。 + +## Commands Executed + +雖無 unit test 新增,本任務之 acceptance 仍依以下 validator 跑列: + +- `python artifacts/scripts/guard_contract_validator.py --root .` +- `python artifacts/scripts/guard_contract_validator.py --root . --check-readme` +- `python artifacts/scripts/guard_status_validator.py --task-id TASK-1103` +- `python artifacts/scripts/prompt_regression_validator.py --root .` +- `python -m pytest artifacts/scripts/ -q` +- `diff docs/premortem_rules.md template/docs/premortem_rules.md` / `diff CLAUDE.md template/CLAUDE.md` / `diff artifacts/scripts/drills/prompt_regression_cases.json template/artifacts/scripts/drills/prompt_regression_cases.json`(人工 mirror 核對) + +## Result Summary + +PASS(NOT_APPLICABLE_BY_ADAPTER)— validator chain 全綠;`docs/premortem_rules.md` / template 鏡像逐位元組相同;`prompt_regression_cases.json` / template 鏡像逐位元組相同;`CLAUDE.md` / `template/CLAUDE.md` diff 僅剩既有 1 行落差;pytest 中途因 3 個 template/ 檔案變更觸發 `.well-known/release-manifest.json` 過期(2 fail),以 `snapshot_manifest.py generate` regen 後回復 2037 passed / 2 skipped 原 baseline;無 test gap 餘留。詳細跑列證據落 verify artifact §Evidence。 + +## Failures + +None(過程中 pytest 之 2 個暫時性 fail 已於 §Result Summary 說明並解除,非留待後續之遺留失敗)。 + +## Evidence Files + +落 `artifacts/verify/TASK-1103.verify.md` §Evidence。 + +## Recommendation + +接 verify。本任務 NOT_APPLICABLE_BY_ADAPTER 屬 docs-spec 之合規路徑(per `docs/artifact_schema.md` §5.1 之 adapter rule resolution);validator chain 全綠且 PR-036 keyword pin 啟用即視為 enforcement 已就位。 diff --git a/artifacts/test/TASK-1104.test.md b/artifacts/test/TASK-1104.test.md new file mode 100644 index 0000000..d8eee27 --- /dev/null +++ b/artifacts/test/TASK-1104.test.md @@ -0,0 +1,40 @@ +# Test Report: TASK-1104 + +## Metadata +- Task ID: TASK-1104 +- Artifact Type: test +- Owner: Claude +- Status: pass +- Last Updated: 2026-07-07T16:50:00+08:00 + +## Test Scope + +NOT_APPLICABLE_BY_ADAPTER — docs-spec adapter 之 task scope 為新增 `docs/sop/rule_lifecycle_audit.md` + `artifacts/improvement/RELAXATION_LOG.md` + 三處觸發軌掛載 + EXACT_SYNC 條目 + PR-037 anchor + template/ 鏡像,無 production code 變更(`guard_contract_validator.py` 僅動 `EXACT_SYNC_FILES` 字串清單),無需 unit test 撰寫。governance enforcement 由 PR-037(prompt_regression)+ EXACT_SYNC(contract validator)雙層 validator 守住。 + +## Commands Executed + +雖無 unit test 新增,本任務之 acceptance 仍依以下 validator 跑列(Claude 於驗收時親自重跑,不採信 Codex 口頭回報): + +- `python artifacts/scripts/guard_contract_validator.py --root .` +- `python artifacts/scripts/guard_contract_validator.py --root . --check-readme` +- `python artifacts/scripts/guard_status_validator.py --task-id TASK-1104` +- `python artifacts/scripts/prompt_regression_validator.py --root .` +- `python -m pytest artifacts/scripts -q`(dirty worktree 與 HEAD 乾淨 worktree 各一次,對照取證) +- `Get-FileHash` SHA-256 逐對比對 4 對 EXACT_SYNC 觸及檔(人工 mirror 核對) +- RELAXATION_LOG 與 workflow-gates.md 逐行重複字面比對(>30 chars 無重複) + +## Result Summary + +PASS(NOT_APPLICABLE_BY_ADAPTER)— validator chain 全綠;4 對 EXACT_SYNC 觸及檔(新 SOP、AGENTS.md、guard_contract_validator.py、prompt_regression_cases.json)root/template SHA-256 全 MATCH;SOP 行數 34(Measure-Object 計非空行;上限 150);pytest 於本 worktree 為 2016 passed / 19 skipped / 4 failed,4 個 fail 皆為 wrapper stdin BOM 斷言(`test_invoke_codex_agent.py` ×2、`test_invoke_gemini_agent.py` ×2),該兩檔本任務未觸碰;與 HEAD 乾淨 worktree 對照結果見 verify artifact §Evidence(判定環境性、非本 diff 所致)。 + +## Failures + +pytest 4 個 wrapper stdin BOM failures 為 pre-existing 環境性問題(相對本任務 diff),不屬 TASK-1104 write scope,如實回報並列入 follow-up;詳細比對證據落 verify artifact。 + +## Evidence Files + +落 `artifacts/verify/TASK-1104.verify.md` §Evidence。 + +## Recommendation + +接 verify。本任務 NOT_APPLICABLE_BY_ADAPTER 屬 docs-spec 之合規路徑(per `docs/schemas/artifact-spec-task.md` §5.1 adapter rule resolution);validator chain 全綠且 PR-037 keyword pin 啟用即視為 enforcement 已就位。 diff --git a/artifacts/test/TASK-1105.test.md b/artifacts/test/TASK-1105.test.md new file mode 100644 index 0000000..e88c51e --- /dev/null +++ b/artifacts/test/TASK-1105.test.md @@ -0,0 +1,41 @@ +# Test Report: TASK-1105 + +## Metadata +- Task ID: TASK-1105 +- Artifact Type: test +- Owner: Claude +- Status: pass +- Last Updated: 2026-07-08T12:30:00+08:00 + +## Test Scope + +本任務(generic adapter)之測試面即既有 4 個 wrapper stdin 測試(`TestCodexBugBStdinAlways` ×2 + `TestGeminiBugBStdinAlways` ×2)由 fail 轉 pass 之回歸驗證,加上兩執行語境之全套 pytest baseline 對照。無新增測試案例——既有嚴格斷言(未弱化)即為修復之永久回歸守衛。 + +## Commands Executed + +- `python -m pytest artifacts/scripts/test_invoke_codex_agent.py artifacts/scripts/test_invoke_gemini_agent.py -q`(wrapper 修改移除後重跑) +- `python -m pytest artifacts/scripts -q`(PowerShell 語境,序列單獨跑) +- `python -m pytest artifacts/scripts -q`(Git Bash 語境,序列單獨跑) +- `python manual_repro.py`(scratchpad 位元組層對照,5.1 語境) +- A/B/C/E 編碼源對照實驗(scratchpad exp_a/b/c/e.ps1,5.1 語境) + +## Result Summary + +PASS — + +- wrapper 測試檔全套:`37 passed`(含原 4 個 fail 之 stdin 測試) +- PowerShell 語境全套:`2020 passed / 19 skipped / 0 failed`(19 skip = gpg 13 + bash 6,語境天然缺工具,屬預期,per project-facts 新增慣例段) +- Git Bash 語境全套:`2037 passed / 2 skipped / 0 failed`(精確回復 TASK-1103 baseline) +- 位元組層:5.1 stdin 仍帶 BOM(wrapper 層不可控,見 research),但 conftest UTF-8 解碼已消除 cp950 吞字,斷言成立 + +## Failures + +None(過程中兩語境 pytest 曾因並行執行互相污染出現假性 110 errors / 1 fail,序列重跑後全綠,已於 verify 記錄為執行方法教訓)。 + +## Evidence Files + +落 `artifacts/verify/TASK-1105.verify.md` §Evidence。 + +## Recommendation + +接 verify。既有 4 測試之嚴格斷言保留為回歸守衛;未來若 conftest 解碼被改回 locale 依賴,該 4 測試會在 PowerShell 語境立即重現 fail。 diff --git a/artifacts/test/TASK-1106.test.md b/artifacts/test/TASK-1106.test.md new file mode 100644 index 0000000..a3f5cc4 --- /dev/null +++ b/artifacts/test/TASK-1106.test.md @@ -0,0 +1,38 @@ +# Test Report: TASK-1106 + +## Metadata +- Task ID: TASK-1106 +- Artifact Type: test +- Owner: Claude +- Status: pass +- Last Updated: 2026-07-08T13:50:00+08:00 + +## Test Scope + +NOT_APPLICABLE_BY_ADAPTER — docs-spec adapter 之 task scope 為 Governance Lenses 表擴充 + Campbell 拒絕記錄 + 兩 SOP 條文 + README 兩版 lenses 段 + PR-038 pin + template 鏡像,無 production code 變更,無需 unit test。governance enforcement 由 PR-038(prompt_regression 雙 assertion)+ EXACT_SYNC(contract validator)雙層守住。 + +## Commands Executed + +- `python artifacts/scripts/guard_contract_validator.py --root .` +- `python artifacts/scripts/guard_contract_validator.py --root . --check-readme` +- `python artifacts/scripts/guard_status_validator.py --task-id TASK-1106` +- `python artifacts/scripts/prompt_regression_validator.py --root .` +- `python -m pytest artifacts/scripts -q`(bash 語境,per project-facts 慣例) +- `Get-Content docs/sop/rule_lifecycle_audit.md | Measure-Object -Line`(行數上限檢查) +- SHA-256 逐對比對四對 EXACT_SYNC 觸及檔(見 verify §Evidence) + +## Result Summary + +PASS(NOT_APPLICABLE_BY_ADAPTER)— contract validator 兩式 [OK](含 README contract);prompt_regression PR-001..PR-038 全 pass;rule_lifecycle_audit.md 非空行 36(≤150);manifest regen 至 root 18c32a6ba3ba;bash 語境全套 pytest 結果落 verify §Evidence。 + +## Failures + +None + +## Evidence Files + +落 `artifacts/verify/TASK-1106.verify.md` §Evidence。 + +## Recommendation + +接 verify。PR-038 之雙 assertion(orchestration 名詞組 + SOP deviance 條款)即新增治理文字之永久回歸守衛。 diff --git a/artifacts/test/TASK-1107.test.md b/artifacts/test/TASK-1107.test.md new file mode 100644 index 0000000..85f853f --- /dev/null +++ b/artifacts/test/TASK-1107.test.md @@ -0,0 +1,90 @@ +# Test Report: TASK-1107 + +## Metadata +- Task ID: TASK-1107 +- Artifact Type: test +- Owner: Codex(+ Claude Post-Dispatch Amendment) +- Status: pass +- Last Updated: 2026-07-17T11:25:00+08:00 + +## Test Scope +- 直驗目前 working tree 中已存在的 TASK-1107 implementation delta 是否符合修正版 plan。 +- 聚焦 CHG-012 回歸測試:既有 5 個 case + 2 個新增 bypass 回歸。 +- root / `template/` exact-sync 與 whitespace/newline hygiene 檢查。 +- `guard_status_validator.py --task-id TASK-1107` 任務狀態驗證。 +- 完整 `artifacts/scripts` pytest suite 現況盤點。 + +## Commands Executed +- `git archive --format=tar HEAD --output /repo.tar` + `tar -xf /repo.tar`(建立 `HEAD` 基線快照,不碰目前 working tree) +- `python -m pytest artifacts/scripts -q`(在 `HEAD` 臨時快照中) +- `python -m pytest artifacts/scripts/test_guard_status_validator_artifacts.py::TestCleanTaskDiffEvidenceCHG012 -v` +- `python artifacts/scripts/guard_contract_validator.py --root .` +- `python artifacts/scripts/guard_status_validator.py --task-id TASK-1107` +- `git diff --check -- artifacts/scripts/guard_status_validator.py artifacts/scripts/test_guard_status_validator_artifacts.py docs/subagent_roles.md docs/raci-matrix.md template/artifacts/scripts/guard_status_validator.py template/artifacts/scripts/test_guard_status_validator_artifacts.py template/docs/subagent_roles.md template/docs/raci-matrix.md` +- `Get-FileHash -Algorithm SHA256`(四組 root/template 配對) +- `python -m pytest artifacts/scripts -q` + +## Baseline +- `HEAD` 臨時快照 full suite:`2018 passed, 19 skipped, 2 failed in 123.80s` +- 基線失敗: + - `artifacts/scripts/test_publish_release_verify.py::test_get_repo_root_resolves_true_root` + - `artifacts/scripts/test_repository_and_pdca.py::TestRrtsGaps::test_copy_task_fixture_skips_dirs` +- 意義:TASK-1107 開始前 repo-wide pytest 本來就不是 0 failed;且 `git archive HEAD` 匯出的臨時快照沒有 `.git`,因此此基線主要用來證明「非本次 source diff 造成的既有紅燈存在」,不作為逐項 failure 的一對一對照基準。 + +## Result Summary +- Focused CHG-012 suite:`7 passed in 2.40s`;既有 5 個 case 與新增 2 個 bypass 回歸皆通過。 +- `guard_contract_validator.py --root .`:`[OK] Contract validation passed`。 +- `guard_status_validator.py --task-id TASK-1107`:`[OK] Validation passed`。 +- `git diff --check`:無輸出,未發現 touched files 的 whitespace / newline 問題。 +- SHA-256 配對結果: + - `artifacts/scripts/guard_status_validator.py` = `template/artifacts/scripts/guard_status_validator.py` = `3F2D1ACEFC53D7AD7761C7574CE1E01CD019A5F42BBF099A27C44804AA3B8E22` + - `artifacts/scripts/test_guard_status_validator_artifacts.py` = `template/artifacts/scripts/test_guard_status_validator_artifacts.py` = `937A63CE1A7C237690988A87633D308AC04EB8E337D76AC2D21E64FE4202F3D9` + - `docs/subagent_roles.md` = `template/docs/subagent_roles.md` = `88C8285C4CA8BE1644A084DEED500746A13F564B5478EA4597DCE66607CE6125` + - `docs/raci-matrix.md` = `template/docs/raci-matrix.md` = `950EC62F3266B9058980B0B8CE8238BA445577B197FA8544BA6D5F1462781CF5` +- Full suite:`2014 passed, 19 skipped, 8 failed in 125.57s`。 +- 相較 `HEAD` 臨時快照基線,working tree 額外暴露的是 manifest drift、prompt-injection scanner 與 git-root 假設相關失敗;CHG-012 focused 回歸本身沒有失敗。 + +## Failures +- `artifacts/scripts/test_publish_release_verify.py::test_get_repo_root_resolves_true_root` + - 僅在 `HEAD` 臨時快照基線出現。 + - 原因:該測試在 `git archive HEAD` 匯出的無 `.git` 臨時快照中無法用 `git rev-parse --show-toplevel` 解出 repo root。 +- `artifacts/scripts/test_repository_and_pdca.py::TestRrtsGaps::test_copy_task_fixture_skips_dirs` + - 僅在 `HEAD` 臨時快照基線出現。 + - 原因:fixture 複製流程在臨時快照路徑下寫入巢狀 `artifacts/decisions/` 目標時拋出 `FileNotFoundError`。 +- `test_council_forge_release_manifest_matches_template_snapshot` + - 原因:`.well-known/release-manifest.json` 尚未反映此次 template snapshot 變更。 +- `test_integrity_gate_passes_on_valid_repo` + - 原因:同上,release-integrity gate fail-closed。 +- `TestRepoScan.test_repo_is_clean` + - 原因:`artifacts/plans/TASK-1107.plan.md` 第 64 行存在字面 BOM,scanner 視為 hidden unicode。 +- `TestDetectChangedFiles.test_not_a_git_repo` +- `TestDetectChangedFiles.test_git_not_installed` +- `TestDetectChangedFiles.test_rev_parse_nonzero_is_non_repo` +- `TestGsvLoadGitScopeContext.test_no_git_root` +- `TestGsvDetectGitRoot.test_not_found` + - 共同原因:目前 `pytest.ini` 的 `--basetemp=../.pytest-basetemp` 令 `tmp_path` 落到外層 git root,與這幾個既有測試預設的「不在 git repo 中」前提衝突。 + +## Evidence Files +None + +## Recommendation +TASK-1107 的 scoped 修復已完成且可送審:CHG-012 parser-based gate、兩類 bypass 回歸測試、RACI 單一真源收斂與 root/template exact sync 都已直驗成立。若要繼續追 AC-8 / AC-10,需先重開 scope 或修正 plan,至少納入 `.well-known/release-manifest.json`,並決定是否處理目前 repo 位置下才會暴露的 git-root 測試失敗與已核准 plan 內的字面 BOM。 + +## Post-Dispatch Amendment(Claude,2026-07-17T11:25:00+08:00) + +**Dispatch 期間之操作事故**(與 CHG-012/RACI 診斷本身無關,處置詳見 `artifacts/decisions/TASK-1107.decision.md` 與 `artifacts/code/TASK-1107.code.md` Amendment): +- 一次前景 dispatch 因工具逾時被誤判為結束,隨後背景 dispatch 與其併發寫入同一組檔案,wrapper 之 `git stash pop` 產生 conflict markers(`docs/subagent_roles.md`/template 鏡射)與重複測試方法定義(`test_sensitive_none_with_reason_evidence_fails`/`test_sensitive_unstructured_evidence_type_text_fails` 各出現兩次,Python 以後定義覆蓋前定義,functionally unaffected 但屬死碼)。 +- wrapper post-dispatch write-scope guard 誤將 Claude 自身之 dispatch log 重導向檔(誤置於 repo 目錄內)判定為越界寫入,觸發 `git stash pop` 衝突,wrapper exit 3 fail-safe。 +- Claude 已唯讀查證(`git status`/`git stash show -p`/檔案 mtime 穩定性確認無 active writer)後安全解決:conflict markers 保留語意相同一側、移除重複測試方法定義、刪除誤入 repo 的 log 檔、確認 stash 內容已全數被 HEAD 已提交版本涵蓋後 `git stash drop`。 + +**修復本 task 自身造成的 3 項 pytest 失敗**: +- `artifacts/plans/TASK-1107.plan.md:64` 字面 U+FEFF BOM -> 改寫為 `U+FEFF` 文字描述。 +- `.well-known/release-manifest.json` -> `python artifacts/scripts/snapshot_manifest.py generate --output .well-known/release-manifest.json` 重生(scope-drift 已於 decision artifact `## Guard Exception` 顯式豁免)。 + +**Claude 直接執行之最終驗證命令與結果**(非採信 Codex 口頭宣稱,逐一重跑): +- `python -m pytest artifacts/scripts/test_guard_status_validator_artifacts.py::TestCleanTaskDiffEvidenceCHG012 -v` -> `7 passed in 0.51s`(7 個 test method 全通過,含既有 5 個與新增 2 個 bypass 回歸) +- `python artifacts/scripts/guard_contract_validator.py --root .` -> `[OK] Contract validation passed` +- 修復前(僅 Codex scoped diff):`python -m pytest artifacts/scripts -q` -> `8 failed, 2031 passed, 2 skipped in 128.42s` +- 修復後(+ BOM 修正 + manifest 重生):`python -m pytest artifacts/scripts -q` -> `5 failed, 2034 passed, 2 skipped in 130.73s` +- 差值:3 項失敗消失(`test_council_forge_release_manifest_matches_template_snapshot`、`test_integrity_gate_passes_on_valid_repo`、`TestRepoScan.test_repo_is_clean`),passed 淨增 3;其餘 5 項失敗(`TestDetectChangedFiles::test_not_a_git_repo`/`test_git_not_installed`/`test_rev_parse_nonzero_is_non_repo`/`TestGsvLoadGitScopeContext::test_no_git_root`/`TestGsvDetectGitRoot::test_not_found`)修復前後名單完全一致,證明與本 task source diff 無因果關係。 +- 結論:AC-8 判定為 verified with documented baseline exception(見 `artifacts/decisions/TASK-1107.decision.md`),非逐字 `0 failed`,但已達成「無 regression + passed 數因新增測試淨增加」之實質意圖。 diff --git a/artifacts/test/TASK-1108.test.md b/artifacts/test/TASK-1108.test.md new file mode 100644 index 0000000..2c27061 --- /dev/null +++ b/artifacts/test/TASK-1108.test.md @@ -0,0 +1,38 @@ +# Test Report: TASK-1108 + +## Metadata +- Task ID: TASK-1108 +- Artifact Type: test +- Owner: Claude +- Status: pass +- Last Updated: 2026-07-10T15:45:00+08:00 + +## Test Scope + +NOT_APPLICABLE_BY_ADAPTER — docs-spec adapter 之 task scope 為 Governance Lenses 表擴充(6 列)+ Policy Engine 拒絕記錄 + rule_lifecycle_audit.md 候選訊號句 + RELAXATION_LOG.md 分離句 + decision schema 條件式可選區段 + subagent_roles.md 兩句條文 + README 兩版 lenses 段 + PR-039 pin + template 鏡像,無 production code 變更,無需 unit test。governance enforcement 由 PR-039(prompt_regression assertion)+ EXACT_SYNC(contract validator)雙層守住。 + +## Commands Executed + +- `python artifacts/scripts/guard_contract_validator.py --root .` +- `python artifacts/scripts/guard_contract_validator.py --root . --check-readme` +- `python artifacts/scripts/guard_status_validator.py --task-id TASK-1108 --auto-classify` +- `python artifacts/scripts/prompt_regression_validator.py --root .` +- `python -m pytest artifacts/scripts -q`(bash 語境,per project-facts 慣例) +- `python artifacts/scripts/snapshot_manifest.py generate --output .well-known/release-manifest.json` +- diff root/template 四對 EXACT_SYNC 觸及檔(見 verify §Evidence) + +## Result Summary + +PASS(NOT_APPLICABLE_BY_ADAPTER)— contract validator 兩式 `[OK]`(含 README contract);prompt_regression PR-001..PR-039 全 pass;`docs/sop/rule_lifecycle_audit.md` 54 行(含尾端空行,≤150);manifest regen 至 root `d54b9f40e544`;bash 語境全套 pytest 於清除一次無關環境殘骸(`Documents/Code/.git` 空目錄,TASK-1106 已知觀察項之第 2 次再現)後達 `2037 passed, 2 skipped, 0 failed`,與 TASK-1106 基準數字一致,證明本次變更零回歸。 + +## Failures + +None(首次全套 pytest 曾因外部環境殘骸重現 5 個 git-root 偵測測試失敗,非本 diff 造成,見 verify §Evidence 之根因分析與隔離證據)。 + +## Evidence Files + +落 `artifacts/verify/TASK-1108.verify.md` §Evidence。 + +## Recommendation + +接 verify。PR-039 即新增治理文字之永久回歸守衛;`Documents/Code/.git` 殘骸第 2 次再現已記入 verify §Evidence 並建議另立 task 二分定位(非本任務 scope)。 diff --git a/artifacts/test/TASK-1109.test.md b/artifacts/test/TASK-1109.test.md new file mode 100644 index 0000000..d687c00 --- /dev/null +++ b/artifacts/test/TASK-1109.test.md @@ -0,0 +1,38 @@ +# Test Report: TASK-1109 + +## Metadata +- Task ID: TASK-1109 +- Artifact Type: test +- Owner: Claude +- Status: pass +- Last Updated: 2026-07-10T17:00:00+08:00 + +## Test Scope + +NOT_APPLICABLE_BY_ADAPTER — docs-spec adapter 之 task scope 為 Governance Lenses 表擴充(Lucas Critique 新增 + Campbell's Law 併入 Goodhart's Law)+ decision schema 兩個條件式可選區段 + rule_lifecycle_audit.md/RELAXATION_LOG.md 各一句操作化規則 + README 兩版 lens 名單句 + PR-040 pin + 7 組 template 鏡像,無 production code 變更,無需 unit test。governance enforcement 由 PR-038/PR-039/PR-040(prompt_regression 三層 assertion)+ EXACT_SYNC(contract validator)雙層守住。 + +## Commands Executed + +- `python artifacts/scripts/guard_contract_validator.py --root .` +- `python artifacts/scripts/guard_contract_validator.py --root . --check-readme` +- `python artifacts/scripts/guard_status_validator.py --task-id TASK-1109 --auto-classify` +- `python artifacts/scripts/prompt_regression_validator.py --root .` +- `python -m pytest artifacts/scripts -q`(bash 語境,per project-facts 慣例) +- `python artifacts/scripts/snapshot_manifest.py generate --output .well-known/release-manifest.json` +- diff root/template 7 組觸及檔(見 verify §Evidence) + +## Result Summary + +PASS(NOT_APPLICABLE_BY_ADAPTER)— contract validator 兩式 `[OK]`;prompt_regression PR-001..PR-040 全 pass(含既有 PR-038/PR-039 未受擾動);`docs/sop/rule_lifecycle_audit.md` 55 行(≤150);manifest regen 至 root `a195da47325b`;bash 語境全套 pytest 於清除一次無關環境殘骸(`Documents/Code/.git`,TASK-1108 已知觀察項延續)後達 `2037 passed, 2 skipped, 0 failed`,與 TASK-1108 verify 記錄之基準數字一致,證明本次變更零回歸。 + +## Failures + +None + +## Evidence Files + +落 `artifacts/verify/TASK-1109.verify.md` §Evidence。 + +## Recommendation + +接 verify。PR-040 即新增治理文字(Lucas Critique + Campbell fold-in + Metrics Policy/Policy Regime)之永久回歸守衛,與 PR-038 之既有 Campbell 拒絕字面共同守住「併入而非新增獨立 lens」之裁決。 diff --git a/artifacts/verify/TASK-1102.verify.md b/artifacts/verify/TASK-1102.verify.md new file mode 100644 index 0000000..c313826 --- /dev/null +++ b/artifacts/verify/TASK-1102.verify.md @@ -0,0 +1,185 @@ +# Verification: TASK-1102 + +## Metadata +- Task ID: TASK-1102 +- Artifact Type: verify +- Owner: Claude +- Status: pass +- Last Updated: 2026-07-06T16:05:00+08:00 + +## Verification Summary + +本 task 修正 wrapper write-scope enforcement 之文件與實際行為落差:`CLAUDE.md` 新增段落明示派發時需顯式傳 `-AutoRestore` 才能讓違規真的被擋下(預設 `$false` 為 detect-only);`GEMINI.md:46` 之絕對敘述改為條件式,且移除 TASK-1059 前已棄用的 `git checkout HEAD --` 全量還原語言。查證後確認 `CODEX.md` 已合規(無「dispatch 視為失敗」字面,且既有 `-AutoRestore` 條件說明完整),本 task 刻意不修改該檔。9 AC 全 verified;4 條 validator 全綠;GEMINI.md/template mirror SHA-256 全等;CLAUDE.md/template mirror 人工 diff 僅剩既有 1 行落差。coding 階段 pytest 一度暴露 `.well-known/release-manifest.json` 因本 task 之 3 個 `template/` 檔案變更而過期(2 測試 fail);因該 regen 為本 task 3 筆變更之確定性、範圍內直接後果(非批次外事項),已於同一 task 內以 `snapshot_manifest.py generate` 補做並回補 plan/code 之 Files 清單,pytest 恢復 2037 passed / 0 failed 之原 baseline,無遺留 deferred 項。 + +## Acceptance Criteria Checklist + +- [x] AC-1: + - criterion: TASK-1102 lifecycle artifacts(task/plan/code/verify/status;test 為 NOT_APPLICABLE_BY_ADAPTER)皆存在且符合 schema;plan 含 R1-R4 premortem,至少 1 條 blocking + - method: ls + guard_status_validator 雙確認 + - evidence: artifacts/{tasks/TASK-1102.task.md, status/TASK-1102.status.json, research/TASK-1102.research.md, plans/TASK-1102.plan.md, code/TASK-1102.code.md, test/TASK-1102.test.md, verify/TASK-1102.verify.md} 7 檔皆存在;plan §Risks 含 R1-R4 4 條,R1/R2 blocking、R3/R4 non-blocking + - result: verified + +- [x] AC-2: + - criterion: CLAUDE.md 新增一段,明示 (a) 是否傳 -AutoRestore 由協調者決定;(b) 預設 $false(detect-only, exit 0);(c) 需真擋下須顯式傳遞 + - method: grep + 人工核對新段落內容 + - evidence: CLAUDE.md「### Dispatch Write-Scope 執行(`-AutoRestore`)」段(「### 派發 Implementation」與「### 完成任務」之間)含三要點全數對應 (a)(b)(c) + - result: verified + +- [x] AC-3: + - criterion: GEMINI.md:46 改為條件式,區分顯式 -AutoRestore(stash-based restore、exit 2)vs 未傳(exit 0,Claude 手動處置);不得殘留 git checkout HEAD -- 語言 + - method: grep `"git checkout HEAD --"` GEMINI.md(應無命中)+ 人工核對新敘述 + - evidence: GEMINI.md:46 改為「違者:Claude 須審視 dispatch 輸出、依情況要求 redo;是否已於偵測當下被 wrapper 自動擋下(stash-based restore、exit 2)或僅止於偵測(exit 0,留待 Claude 手動處置),取決於下列 `-AutoRestore` 是否顯式傳遞」;`grep -c "git checkout HEAD --" GEMINI.md` = 0 + - result: verified + +- [x] AC-4: + - criterion: CODEX.md 維持不變 + - method: git diff CODEX.md(應為空) + - evidence: `git diff -- CODEX.md` 無輸出;本 task 全程未對該檔執行任何 Edit/Write + - result: verified + +- [x] AC-5: + - criterion: template/CLAUDE.md 與 template/GEMINI.md 同步;GEMINI.md/template/GEMINI.md SHA-256 全等;template/CLAUDE.md 人工 diff 僅剩既有 1 行落差 + - method: diff + sha256sum + - evidence: `diff GEMINI.md template/GEMINI.md` 無輸出(exit 0);sha256 兩檔皆 `943128e0...0711`;`diff CLAUDE.md template/CLAUDE.md` 僅剩既有 downstream-terminal 1 行落差(第 172/164 行,非本次新增內容) + - result: verified + +- [x] AC-6: + - criterion: guard_contract_validator.py --root . 與 --check-readme 皆 [OK] + - method: subprocess + - evidence: 兩條指令皆回 `[OK] Contract validation passed` + - result: verified + +- [x] AC-7: + - criterion: guard_status_validator.py --task-id TASK-1102 回 [OK] + - method: 命令跑列(於 planned / coding / verifying 三個狀態各跑一次) + - evidence: 三次跑列皆 `[OK] Validation passed` + - result: verified + +- [x] AC-8: + - criterion: prompt_regression_validator.py --root . 全數 PR-* PASS(含既有 PR-027 對 GEMINI.md 之三字面 pin 仍存在,並新增 PR-035) + - method: 命令跑列 + - evidence: 35/35 PASS(PR-001..PR-034 既有 + 本 task 新增 PR-035);PR-027(Codex Write Scope Discipline)與 PR-028(Gemini Write Scope Discipline)皆 pass,確認本次 GEMINI.md 改寫未波及既有 pin + - result: verified + +- [x] AC-9: + - criterion: pytest artifacts/scripts/ -q 通過數不低於既有 baseline + - method: 全跑 pytest(先於 template/ 3 檔修改後跑一次揭露 manifest 過期,regen 後重跑確認回綠) + - evidence: coding 中途一度 2035 passed + 2 skipped + 2 failed(`test_council_forge_release_manifest_matches_template_snapshot` / `test_integrity_gate_passes_on_valid_repo`,因 `.well-known/release-manifest.json` 未反映本 task 之 3 個 template/ 檔案變更);以 `python artifacts/scripts/snapshot_manifest.py generate --output .well-known/release-manifest.json` 重新產生(`git diff` 確認僅 3 筆 digest + root digest 變更,其餘 241 筆不變)後,`python -m pytest artifacts/scripts/ -q` 回 **2037 passed, 2 skipped, 0 failed**,等於且未低於既有 baseline + - result: verified + +## Overall Maturity + +mvp + +## Deferred Items + +None — coding 階段一度發現 `.well-known/release-manifest.json` 因本 task 之 3 個 `template/` 檔案變更而過期(見 AC-9),已於本 task 內以 `snapshot_manifest.py generate` 補做 regen(僅反映本 task 自身之 3 筆 digest + root digest 變更,範圍內、確定性、無外溢),非留待後續批次處理之事項。 + +## Evidence + +### Validator Chain(4 條全綠) + +``` +$ python artifacts/scripts/guard_contract_validator.py --root . +[OK] Contract validation passed + +$ python artifacts/scripts/guard_contract_validator.py --root . --check-readme +[OK] Contract validation passed + +$ python artifacts/scripts/guard_status_validator.py --task-id TASK-1102 +[OK] Validation passed + +$ python artifacts/scripts/prompt_regression_validator.py --root . +... (35 rows, PR-001..PR-035 all pass) +## Failure Details +None +``` + +### Mirror Match + +``` +$ diff GEMINI.md template/GEMINI.md +(no output, exit 0) + +$ sha256sum GEMINI.md template/GEMINI.md +943128e08d59ce5ce06657d39dd54dcd42b2ac88b7e9f71e9c774666b1e70711 *GEMINI.md +943128e08d59ce5ce06657d39dd54dcd42b2ac88b7e9f71e9c774666b1e70711 *template/GEMINI.md + +$ diff CLAUDE.md template/CLAUDE.md +172c172 +< 由 `template/` 複製出去的新專案屬於 downstream terminal repo,不得再建立新的 `template/`,而是只維護 root 文件與 `OBSIDIAN.md`。 +--- +> 由 `template/` 複製出去的新專案屬於 downstream terminal repo,不得再建立新的 `template/`,而是只維護 root 文件與 `OBSIDIAN.md`。本 downstream terminal repo 不再建立新的 `template/`,只維護 root 文件與 `OBSIDIAN.md`。 +(既有落差,非本次新增內容所致) + +$ sha256sum artifacts/scripts/drills/prompt_regression_cases.json template/artifacts/scripts/drills/prompt_regression_cases.json +e23a8e2a3ddf071df24641b8237cf1b244ad3cf349b5b55a3b793f78220aacc8 *artifacts/scripts/drills/prompt_regression_cases.json +e23a8e2a3ddf071df24641b8237cf1b244ad3cf349b5b55a3b793f78220aacc8 *template/artifacts/scripts/drills/prompt_regression_cases.json +``` + +### CODEX.md Unchanged Confirmation + +``` +$ git diff -- CODEX.md +(no output) +``` + +### Pytest Baseline + +``` +# coding 中途(template/ 3 檔已改,manifest 尚未 regen) +$ python -m pytest artifacts/scripts/ -q +2035 passed, 2 skipped, 2 failed in 128.59s +FAILED artifacts/scripts/test_downstream_security_template.py::test_council_forge_release_manifest_matches_template_snapshot +FAILED artifacts/scripts/test_publish_release_verify.py::test_integrity_gate_passes_on_valid_repo + +# manifest regen 後 +$ python artifacts/scripts/snapshot_manifest.py generate --output .well-known/release-manifest.json +[OK] wrote manifest: 244 entr(y/ies); root ce7e26209bd7 + +$ git diff .well-known/release-manifest.json +(僅 CLAUDE.md / GEMINI.md / artifacts/scripts/drills/prompt_regression_cases.json 3 筆 digest + root digest 變更,其餘 241 筆 entry 不變) + +$ python -m pytest artifacts/scripts/test_downstream_security_template.py::test_council_forge_release_manifest_matches_template_snapshot artifacts/scripts/test_publish_release_verify.py::test_integrity_gate_passes_on_valid_repo -q +2 passed in 0.78s + +$ python -m pytest artifacts/scripts/ -q +2037 passed, 2 skipped in 123.68s +``` + +## Evidence Refs + +- artifacts/tasks/TASK-1102.task.md +- artifacts/research/TASK-1102.research.md +- artifacts/plans/TASK-1102.plan.md +- artifacts/code/TASK-1102.code.md +- artifacts/test/TASK-1102.test.md +- artifacts/status/TASK-1102.status.json +- CLAUDE.md / template/CLAUDE.md +- GEMINI.md / template/GEMINI.md +- artifacts/scripts/drills/prompt_regression_cases.json / template/artifacts/scripts/drills/prompt_regression_cases.json +- .well-known/release-manifest.json + +## Decision Refs + +None + +## Build Guarantee + +None (no .csproj or code modified) — 本 task 為 docs-spec adapter 純 agent 入口檔文字修正任務;無 .NET / Node build 單元;無新增 production 邏輯需 build/lint。所有 enforcement 由 validator chain 守住(見 §Evidence)。待 user-driven commit 後,commit hash 為本 task 之 final immutable anchor;目前 HEAD anchor 為 dirty worktree pending commit。 + +## TAO Trace + +None — 本 task plan §Risks R1/R2 之 blocking risk 皆已於 coding 階段以 validator 防線解除(PR-035 + PR-027/PR-028 全 PASS、SHA-256 mirror match),無 verifier sub-agent dispatch 發生;docs-spec adapter 之 lightweight TAO 條件適用。 + +## Pass Fail Result + +pass + +## Remaining Gaps + +None + +## Recommendation + +接 Closure:(1) status 升至 `done`;(2) 於最終交付摘要向 user 明示 CODEX.md 查證結論(本 task 未修改該檔);(3) 等 user-driven commit 後,commit hash 補回本 verify §Build Guarantee 段。 diff --git a/artifacts/verify/TASK-1103.verify.md b/artifacts/verify/TASK-1103.verify.md new file mode 100644 index 0000000..6139f38 --- /dev/null +++ b/artifacts/verify/TASK-1103.verify.md @@ -0,0 +1,197 @@ +# Verification: TASK-1103 + +## Metadata +- Task ID: TASK-1103 +- Artifact Type: verify +- Owner: Claude +- Status: pass +- Last Updated: 2026-07-07T12:00:00+08:00 + +## Verification Summary + +本任務為 `docs/premortem_rules.md` 新增 §12「獨立 Premortem 質疑(高風險 plan)」,並延伸 `CLAUDE.md` STOP 觸發點一句,補上「premortem 目前為撰寫者自審、無獨立檢查」這個唯一經核實為真的治理缺口(其餘 ChatGPT 建議之機制本專案已有:`/codex-review` Council Reviewer、RACI Auditor/Architecture Synthesizer、`Task Scale` 三層抽象)。9 AC 全 verified;4 條 validator 全綠;`docs/premortem_rules.md` / `prompt_regression_cases.json` 與 template 鏡像 SHA-256 全等;`CLAUDE.md` / `template/CLAUDE.md` 人工 diff 僅剩既有 1 行落差。過程中發現並排除兩項與本任務內容無關但真實存在的流程缺口(詳見 §Deferred Items 之上的過程記錄):(1) 撰寫 code artifact 時,`## Files Changed` 區段內用於說明「未變更項」的 filenames 被 guard 的檔名 token 掃描誤判為未宣告的變更,改寫為不含副檔名字面的描述後解除;(2) dirty worktree 使 TASK-1102 尚未 commit 的變更與一批來源不明的 `.agents/skills/` untracked 檔案,一併被算進本任務的 git-backed scope-drift 檢查——這證實了「多任務不 commit 連續作業會互相污染 scope-drift 檢查」的真實限制。經 user 裁決:TASK-1102 已拆分為獨立 commit(`6c2bbc6`)、`.agents/` 已確認與本 repo workflow 無關並刪除,兩項排除後 scope-drift 檢查回復乾淨。coding 階段 pytest 一度因 3 個 `template/` 檔案變更(`docs/premortem_rules.md`、`CLAUDE.md`、`prompt_regression_cases.json`)暴露 `.well-known/release-manifest.json` 過期(2 測試 fail),已於本任務內以 `snapshot_manifest.py generate` regen 兩次(一次於 TASK-1102 commit 前的暫時還原 checkpoint、一次於重新套用本任務變更後的最終狀態)補做,pytest 恢復 2037 passed / 0 failed / 2 skipped 之原 baseline,無遺留 deferred 項。 + +## Acceptance Criteria Checklist + +- [x] AC-1: + - criterion: TASK-1103 lifecycle artifacts(task/research/plan/code/verify/status;test 為 NOT_APPLICABLE_BY_ADAPTER)皆存在且符合 schema;plan 含 R1-R4 premortem,至少 1 條 blocking + - method: ls + guard_status_validator 雙確認 + - evidence: artifacts/{tasks/TASK-1103.task.md, status/TASK-1103.status.json, research/TASK-1103.research.md, plans/TASK-1103.plan.md, code/TASK-1103.code.md, test/TASK-1103.test.md, verify/TASK-1103.verify.md} 7 檔皆存在;plan §Risks 含 R1-R4 4 條,R1/R2 blocking、R3/R4 non-blocking + - result: verified + +- [x] AC-2: + - criterion: docs/premortem_rules.md 新增 §12,明示 (a) 適用條件 (b) 獨立性要求 (c) 質疑內容最小集合 (d) 輸出位置 (e) 與 Council Reviewer/RACI Auditor 分工邊界 (f) 不由 validator 自動強制 + - method: grep + 人工核對新章節內容 + - evidence: docs/premortem_rules.md §12 含「背景/適用範圍/獨立性要求/質疑內容(最小集合)/輸出位置/與既有機制的分工邊界/現況」7 個子節,逐一對應 (a)-(f) + - result: verified + +- [x] AC-3: + - criterion: CLAUDE.md STOP 觸發點延伸現有 premortem 敘述,納入「高風險 plan 未完成獨立質疑」,並指向 docs/premortem_rules.md §12 + - method: grep + 人工核對新句 + - evidence: CLAUDE.md 第 3 節第 4 條 bullet 改為「❌ Premortem 缺失或 R1-R4 不完整,或高風險 plan 未完成獨立質疑(見 docs/premortem_rules.md,含 §12)」 + - result: verified + +- [x] AC-4: + - criterion: template/docs/premortem_rules.md 與 template/CLAUDE.md 同步;docs/premortem_rules.md/template 鏡像 SHA-256 全等;template/CLAUDE.md 人工 diff 僅既有 1 行落差 + 本次新增內容 + - method: diff + - evidence: `diff docs/premortem_rules.md template/docs/premortem_rules.md` 無輸出(exit 0);`diff CLAUDE.md template/CLAUDE.md` 僅剩既有 1 行 downstream-terminal 落差(第 172 行),本次新增之 STOP bullet 兩邊皆已同步 + - result: verified + +- [x] AC-5: + - criterion: guard_contract_validator.py --root . 與 --check-readme 皆 [OK] + - method: subprocess + - evidence: 兩條指令皆回 `[OK] Contract validation passed` + - result: verified + +- [x] AC-6: + - criterion: guard_status_validator.py --task-id TASK-1103 回 [OK] + - method: 命令跑列(於 planned / coding / verifying 各跑一次;過程中先後排除文字誤觸與 dirty-worktree 跨任務污染兩項非本任務內容之發現後轉綠,詳見 §Verification Summary) + - evidence: 最終跑列回 `[OK] Validation passed` + - result: verified + +- [x] AC-7: + - criterion: prompt_regression_validator.py --root . 全數 PR-* PASS(含新增 PR-036) + - method: 命令跑列 + - evidence: 36/36 PASS(PR-001..PR-035 既有 + 本任務新增 PR-036);PR-027/PR-028/PR-035(既有 write-scope / AutoRestore pin)皆 pass,確認本次修改未波及既有 pin + - result: verified + +- [x] AC-8: + - criterion: pytest artifacts/scripts/ -q 通過數不低於既有 baseline + - method: 全跑 pytest(於 template/ 3 檔修改後跑一次揭露 manifest 過期,regen 後重跑確認回綠;於 TASK-1102 commit 拆分過程中又跑一次確認 checkpoint 自洽,最終再跑一次確認完整狀態) + - evidence: coding 中途一度 2035 passed + 2 skipped + 2 failed(同 TASK-1102 已知模式:`test_council_forge_release_manifest_matches_template_snapshot` / `test_integrity_gate_passes_on_valid_repo`);`snapshot_manifest.py generate` regen 後最終 `python -m pytest artifacts/scripts/ -q` 回 **2037 passed, 2 skipped, 0 failed**,等於既有 baseline + - result: verified + +- [x] AC-9: + - criterion: plan artifact 明示本任務自身不觸發新定義的獨立質疑機制,並說明理由 + - method: 人工核對 plan 內容 + - evidence: `artifacts/plans/TASK-1103.plan.md` 「## 本任務自身不觸發 §12 機制之說明」章節明列本任務不屬於 security fix / upstream PR / 跨模組跨 repo / 不熟悉框架環境 任一類別,非遺漏而是刻意設計 + - result: verified + +## Overall Maturity + +mvp + +## Deferred Items + +None — 過程中發現的兩項非本任務內容缺口(code artifact 文字誤觸檔名 token 掃描、dirty-worktree 跨任務 scope-drift 污染)已於本任務範圍內即時排除(改寫文字 + user 裁決拆分 TASK-1102 commit + 刪除 `.agents/`),非留待後續批次處理之事項。 + +## Evidence + +### Validator Chain(4 條全綠) + +``` +$ python artifacts/scripts/guard_contract_validator.py --root . +[OK] Contract validation passed + +$ python artifacts/scripts/guard_contract_validator.py --root . --check-readme +[OK] Contract validation passed + +$ python artifacts/scripts/guard_status_validator.py --task-id TASK-1103 +[OK] Validation passed + +$ python artifacts/scripts/prompt_regression_validator.py --root . +... (36 rows, PR-001..PR-036 all pass) +## Failure Details +None +``` + +### Mirror Match + +``` +$ diff docs/premortem_rules.md template/docs/premortem_rules.md +(no output, exit 0) + +$ diff artifacts/scripts/drills/prompt_regression_cases.json template/artifacts/scripts/drills/prompt_regression_cases.json +(no output, exit 0) + +$ diff CLAUDE.md template/CLAUDE.md +172c172 +< 由 `template/` 複製出去的新專案屬於 downstream terminal repo,不得再建立新的 `template/`,而是只維護 root 文件與 `OBSIDIAN.md`。 +--- +> 由 `template/` 複製出去的新專案屬於 downstream terminal repo,不得再建立新的 `template/`,而是只維護 root 文件與 `OBSIDIAN.md`。本 downstream terminal repo 不再建立新的 `template/`,只維護 root 文件與 `OBSIDIAN.md`。 +(既有落差,非本次新增內容所致) +``` + +### Cross-Task Scope-Drift Finding And Resolution + +``` +# 第一次 guard_status_validator 跑列(在 TASK-1102 尚未 commit、.agents/ 尚未刪除時): +[FAIL] TASK-1103.code.md: git-backed scope check found actual changed files not listed in ## Files Changed: + ['GEMINI.md', 'agents/skills/adversarial-review/SKILL.md', 'agents/skills/agent-rescue/SKILL.md', + 'agents/skills/source-command-codex-review/SKILL.md', 'template/GEMINI.md'] +[FAIL] TASK-1103.plan.md: git-backed scope check found actual changed files not listed in ## Files Likely Affected: (同上清單) + +# 處置: +# 1. user 裁決刪除 .agents/(確認與本 repo workflow 無關) +# 2. 暫時還原 CLAUDE.md / prompt_regression_cases.json 之 TASK-1103 專屬 hunk,regen manifest, +# 將 GEMINI.md / template/GEMINI.md / prompt_regression PR-035 / CLAUDE.md Dispatch Write-Scope 段 +# 等 TASK-1102 專屬變更獨立 commit(6c2bbc6) +# 3. 重新套用 TASK-1103 之 hunk(CLAUDE.md STOP bullet、prompt_regression PR-036、docs/premortem_rules.md §12), +# 再次 regen manifest + +# 最終跑列: +$ python artifacts/scripts/guard_status_validator.py --task-id TASK-1103 +[OK] Validation passed +``` + +### Pytest Baseline + +``` +# coding 中途(template/ 3 檔已改,manifest 尚未 regen) +$ python -m pytest artifacts/scripts/ -q +2035 passed, 2 skipped, 2 failed in 148.73s +FAILED artifacts/scripts/test_downstream_security_template.py::test_council_forge_release_manifest_matches_template_snapshot +FAILED artifacts/scripts/test_publish_release_verify.py::test_integrity_gate_passes_on_valid_repo + +# manifest regen 後(TASK-1103 完整狀態) +$ python artifacts/scripts/snapshot_manifest.py generate --output .well-known/release-manifest.json +[OK] wrote manifest: 244 entr(y/ies); root accb252144e2 + +$ python -m pytest artifacts/scripts/ -q +2037 passed, 2 skipped in 146.12s +``` + +### TASK-1102 Isolated Commit + +``` +$ git commit -m "TASK-1102 fix-bug: clarify wrapper -AutoRestore is Claude's explicit dispatch decision" ... +[manifest-exec-unified-audit-2026-07-03 6c2bbc6] TASK-1102 fix-bug: ... + 14 files changed, 653 insertions(+), 7 deletions(-) +``` + +## Evidence Refs + +- artifacts/tasks/TASK-1103.task.md +- artifacts/research/TASK-1103.research.md +- artifacts/plans/TASK-1103.plan.md +- artifacts/code/TASK-1103.code.md +- artifacts/test/TASK-1103.test.md +- artifacts/status/TASK-1103.status.json +- docs/premortem_rules.md / template/docs/premortem_rules.md +- CLAUDE.md / template/CLAUDE.md +- artifacts/scripts/drills/prompt_regression_cases.json / template/artifacts/scripts/drills/prompt_regression_cases.json +- .well-known/release-manifest.json + +## Decision Refs + +None — 兩項過程中發現的缺口(文字誤觸、dirty-worktree scope-drift 污染)皆透過即時 AskUserQuestion 取得 user 裁決並在本任務內解決,未達需要獨立 decision artifact 之門檻(無風險判斷分歧、無需人工事後審核)。 + +## Build Guarantee + +None (no .csproj or code modified) — 本任務為 docs-spec adapter 純 governance 文字修正任務;無 .NET / Node build 單元;無新增 production 邏輯需 build/lint。所有 enforcement 由 validator chain 守住(見 §Evidence)。TASK-1103 自身變更(docs/premortem_rules.md §12、CLAUDE.md STOP 延伸、PR-036、template 鏡像、manifest regen)仍為 dirty worktree pending commit;TASK-1102 部分已於本任務過程中拆分並完成 commit(`6c2bbc6`),詳見 §Evidence「TASK-1102 Isolated Commit」。待 user-driven commit TASK-1103 本身變更後,commit hash 為本任務之 final immutable anchor。 + +## TAO Trace + +None — 本任務 plan §Risks R1/R2 之 blocking risk,皆屬「本次新增文件定義本身之品質保證」(透過 §12 文字設計 + PR-036 pin 解除),非涉及執行分歧之 verifier dispatch;無 implementer / verifier sub-agent dispatch 發生(Claude 直寫),docs-spec adapter 之 lightweight TAO 條件適用。 + +## Pass Fail Result + +pass + +## Remaining Gaps + +None + +## Recommendation + +接 Closure:(1) status 升至 `done`;(2) 向 user 說明本任務過程中發現並排除的兩項流程缺口(code artifact 檔名 token 誤判、dirty-worktree 跨任務 scope-drift 污染),已隨 TASK-1102 拆分 commit 與 `.agents/` 刪除一併解決;(3) 等 user-driven commit TASK-1103 本身變更後,commit hash 補回本 verify §Build Guarantee 段。 diff --git a/artifacts/verify/TASK-1104.verify.md b/artifacts/verify/TASK-1104.verify.md new file mode 100644 index 0000000..a923ab8 --- /dev/null +++ b/artifacts/verify/TASK-1104.verify.md @@ -0,0 +1,219 @@ +# Verification: TASK-1104 + +## Metadata +- Task ID: TASK-1104 +- Artifact Type: verify +- Owner: Claude +- Status: pass +- Last Updated: 2026-07-07T17:05:00+08:00 + +## Verification Summary + +本任務把 Occam's razor 與 Chesterton's Fence 制度化為單一規則生命週期盤點循環:新增 `docs/sop/rule_lifecycle_audit.md`(34 行,四值裁決 `retire`/`relax`/`keep`/`open`)、`artifacts/improvement/RELAXATION_LOG.md`(4 筆既有放寬案例沉澱)、三處觸發軌掛載(AGENTS.md / PROCESS_LEDGER / architecture-synthesizer TEMPLATE)、EXACT_SYNC 條目與 PR-037 anchor。實作由 Codex 執行(dispatch wrapper 以 exit 1 收場但屬假失敗真完工:gpt-5.4 三次 attempt 實際完成全部交付物,exit code 來自 MCP auth 噪音與 OpenAI workspace credits 耗盡;後續 gpt-5.5/mini fallback 因 credits 未做事)。Claude 驗收時親自重跑全部 validator chain 與 SHA-256 比對,不採信 Codex 口頭回報;另以 HEAD 乾淨 worktree 跑 pytest 對照組,證明 4 個 wrapper stdin BOM failures 於 HEAD 即存在(環境性、非本 diff 所致)。14 AC 全 verified。Wrapper post-dispatch write-scope 警告已逐項人工 review(詳見 §Evidence):4 個 lifecycle 檔為 Claude pre-dispatch 寫入之誤歸因(Bug-W3 已知模式);`status.json` 為 Codex 真實寫入但在 plan `## Files Likely Affected` 範圍內,接受;無需 Guard Exception decision。 + +## Acceptance Criteria Checklist + +- [x] AC-1: + - criterion: lifecycle artifacts(task/research/plan/code/verify/status;test 為 NOT_APPLICABLE_BY_ADAPTER)皆存在且符合 schema;plan 含 premortem ≥3 條、≥1 blocking + - method: ls + guard_status_validator 雙確認 + - evidence: 7 檔皆存在;plan §Risks 含 R1-R5,R2/R3 blocking;`guard_status_validator.py --task-id TASK-1104` 回 [OK] + - result: verified + +- [x] AC-2: + - criterion: SOP 定義三步循環與四值裁決各有判準與記錄欄位,含 retire 復活路徑 + - method: 人工核對 + grep + - evidence: `docs/sop/rule_lifecycle_audit.md` §Step 1-3;Chesterton Gate 表格四列各含「何時使用/最小要求/動作」;§Step 3 記錄表含 Rule/Path、Verdict、Provenance、Why、Revival Path 五欄;retire 列明 `git mv docs/templates/archive/ docs/templates/` 復活慣例 + - result: verified + +- [x] AC-3: + - criterion: 觸發條款含 N=10 同軌與手動兩路徑 + - method: grep + - evidence: SOP §Trigger 兩條 bullet:N=10 倍數同批執行(權威指向 architecture-synthesizer TEMPLATE)+ 使用者隨時手動發起 + - result: verified + +- [x] AC-4: + - criterion: 「查無 provenance → open,不拆也不加碼」條款存在並引 scope-drift Layer-1 先例 + - method: grep + - evidence: SOP §Step 2 表格 `open` 列 +「`open` 是 fail-closed 的盤點裁決……scope-drift guard Layer-1(2026-07-02)為先例」 + - result: verified + +- [x] AC-5: + - criterion: SOP ≤150 行、無新增腳本/guard 要求、含自我引用條款與退路 + - method: Measure-Object -Line + 人工核對 + - evidence: 34 行;§Purpose 明文「不得要求新增腳本、guard、artifact type 或自動化強制」;§Guardrails 含「本 SOP 自身列入每輪盤點對象」與「N=10 軌長期未觸發……檢討是否改綁 unified audit」 + - result: verified + +- [x] AC-6: + - criterion: RELAXATION_LOG 含 4 筆案例、欄位齊、provenance 誠實、≥3 升級條款 + - method: 人工核對 + citation 抽驗 + - evidence: 4 筆案例(CITATION_PATTERN、RESEARCH_SOURCES_ENTRY_PATTERN、generic→docs-spec、available_artifacts mismatch)各含七欄位;後兩筆建立 provenance 明標 unrecorded(Codex 以 grep 定位到 TASK-1049/TASK-1058 之 in-repo 觀測作為部分 citation);§Rules 含「累積達 3 筆以上時,當次 closure 升級 architect review」 + - result: verified + +- [x] AC-7: + - criterion: RELAXATION_LOG 與 workflow-gates.md cross-ref 而非重複 + - method: 逐行字面比對(>30 chars) + - evidence: PowerShell 逐行交集比對回 `NO DUPLICATE LITERAL (>30 chars)`;log 開頭明文 cross-ref workflow-gates.md + - result: verified + +- [x] AC-8: + - criterion: AGENTS.md 文件模組表新增一列且 root/template 逐位元組相同 + - method: git diff + Get-FileHash + - evidence: diff 僅 +1 列(`docs/sop/rule_lifecycle_audit.md` | 規則盤點循環 | 700 | Closure / 盤點觸發時);SHA-256 MATCH + - result: verified + +- [x] AC-9: + - criterion: PROCESS_LEDGER §維護規則與 architecture-synthesizer TEMPLATE §Trigger 各加同軌 cross-ref,template 鏡像同動 + - method: git diff + - evidence: 兩檔各 +1 行(TEMPLATE §Trigger 新增「同批:rule lifecycle audit 於同次 N=10 盤點執行;該 SOP 只盤點規則增刪與放寬,不重複定義本 Trigger」);template/ 對應檔同步(git status 四檔成對出現) + - result: verified + +- [x] AC-10: + - criterion: EXACT_SYNC_FILES 新增條目(兩份同改);contract validator 兩式 [OK];SHA-256 逐對全等 + - method: git diff + subprocess + Get-FileHash + - evidence: validator diff 僅 +1 字串條目;`guard_contract_validator.py --root .` 與 `--check-readme` 皆 `[OK] Contract validation passed`(Claude 重跑);4 對觸及檔 SHA-256 全 MATCH + - result: verified + +- [x] AC-11: + - criterion: guard_status_validator --task-id TASK-1104 回 [OK] + - method: 命令跑列(planned / coding / verifying 各階段轉移時執行) + - evidence: 各階段跑列 `[OK] Validation passed`(planned 首跑抓到 Status 值/Sources 格式/verification_readiness 三類 schema 錯並即時修正;verifying 首跑抓到 verify artifact 未建即轉移,補建後轉綠) + - result: verified + +- [x] AC-12: + - criterion: prompt_regression_validator 全 PASS 含新增 PR-037 + - method: 命令跑列 + - evidence: PR-001..PR-037 全 pass、`## Failure Details` = None(Claude 重跑);PR-037 pin 四值裁決與 OPEN 條款字面 + - result: verified + +- [x] AC-13: + - criterion: pytest 通過數不低於既有 baseline;manifest 過期時 regen + - method: dirty worktree 與 HEAD 乾淨 worktree 各跑一次 pytest 對照取證 + - evidence: 本 worktree `2016 passed / 19 skipped / 4 failed`;HEAD 乾淨 worktree `2015 passed / 19 skipped / 5 failed`(4 個 wrapper stdin BOM failures 兩邊完全相同;HEAD 多的 1 個 `test_get_repo_root_resolves_true_root` 為 linked-worktree 環境特有,主 worktree 通過)→ passed 數 2016 ≥ 2015,4 個 BOM failures 於 HEAD 即存在,非本 diff 所致;manifest 已由 Codex 於實作內 regen(`.well-known/release-manifest.json` 在 Files Changed 內,兩條 manifest 相關測試通過)。註:TASK-1103 同日 12:00 記錄之 baseline 為 2037/2/0,現況多 17 skip + 4 BOM fail,屬 12:00-15:00 間之環境漂移,已列 follow-up + - result: verified + +- [x] AC-14: + - criterion: Files Changed ⊆ plan Files Likely Affected;EXACT_SYNC 敏感集 closure 之 Diff Evidence 依 CHG-012 處置 + - method: 逐檔比對 + guard_status_validator write-transition + - evidence: code artifact 16 檔全數列於 plan `## Files Likely Affected`(含 status.json,屬 lifecycle artifacts 項);closure 於 dirty worktree 執行,Files Changed 驗證由 guard 之 live check 承載([OK]);若日後 clean replay 需依 `docs/schemas/artifact-spec-code.md` 補 commit-range Diff Evidence,已於 code artifact 留待 user commit 後可補 + - result: verified + +## Overall Maturity + +mvp + +## Deferred Items + +None — pytest 4 個 BOM failures 為 pre-existing 環境問題(HEAD 對照證實),非本任務之 verification debt;已列入 follow-up 建議(見 §Recommendation),不掛 open_verification_debts。 + +## Evidence + +### Validator Chain(Claude 親自重跑,全綠) + +``` +$ python artifacts/scripts/guard_contract_validator.py --root . +[OK] Contract validation passed + +$ python artifacts/scripts/guard_contract_validator.py --root . --check-readme +[OK] Contract validation passed + +$ python artifacts/scripts/guard_status_validator.py --task-id TASK-1104 +[OK] Validation passed + +$ python artifacts/scripts/prompt_regression_validator.py --root . +(PR-001..PR-037 all pass) +## Failure Details +None +``` + +### Mirror Match(SHA-256 逐對) + +``` +docs/sop/rule_lifecycle_audit.md : MATCH +AGENTS.md : MATCH +artifacts/scripts/guard_contract_validator.py : MATCH +artifacts/scripts/drills/prompt_regression_cases.json : MATCH +``` + +### Pytest 對照取證(AC-13) + +``` +# 本任務 dirty worktree +$ python -m pytest artifacts/scripts -q +4 failed, 2016 passed, 19 skipped in 150.20s +FAILED test_invoke_codex_agent.py::TestCodexBugBStdinAlways::test_multiline_prompt_under_threshold_is_piped_via_stdin +FAILED test_invoke_codex_agent.py::TestCodexBugBStdinAlways::test_short_single_line_prompt_still_dispatches +FAILED test_invoke_gemini_agent.py::TestGeminiBugBStdinAlways::test_multiline_prompt_under_threshold_is_piped_via_stdin +FAILED test_invoke_gemini_agent.py::TestGeminiBugBStdinAlways::test_short_single_line_prompt_still_dispatches + +# HEAD (0986deb) 乾淨 worktree 對照組 +$ git worktree add $env:TEMP\cf-head-baseline HEAD; python -m pytest artifacts/scripts -q +5 failed, 2015 passed, 19 skipped in 134.65s +(同上 4 個 BOM failures + test_publish_release_verify.py::test_get_repo_root_resolves_true_root + ——後者為 linked-worktree 環境特有,主 worktree 通過) +``` + +失敗症狀:fake exe 讀到之 stdin 前綴含 BOM(字面值 `U+FEFF`)。兩測試檔(`test_invoke_codex_agent.py` / `test_invoke_gemini_agent.py`)本任務未觸碰(git status 無此二檔)。 + +### Wrapper Post-Dispatch Write-Scope 警告之人工 Review + +``` +[GUARD] Post-dispatch detected sub-agent writes outside AllowedPaths: + - artifacts/plans/TASK-1104.plan.md ← Claude pre-dispatch 寫入,誤歸因(Bug-W3 模式) + - artifacts/research/TASK-1104.research.md ← 同上 + - artifacts/status/TASK-1104.status.json ← Codex 真實寫入(available_artifacts 補 code), + 在 plan Files Likely Affected 範圍內,接受 + - artifacts/tasks/TASK-1104.task.md ← Claude pre-dispatch 寫入,誤歸因 +[GUARD][RACI] 清單 20 檔逐一核對:全數 ⊆ plan Files Likely Affected ∪ Claude pre-dispatch lifecycle 檔 +``` + +detect-only 模式(-AutoRestore 未傳,Claude 顯式決策);無未宣告 scope drift,無需 Guard Exception decision artifact。 + +### Dispatch 執行紀錄勘誤 + +code artifact §Execution Profile 記 `Task scale: docs-only / Model policy target: gpt-5.4-mini`;實際 dispatch 參數為 `-TaskScale standard`,wrapper 實跑 `gpt-5.4`(effort high),見 dispatch log `Active Model Tier: gpt-5.4`。Codex 對自身 runtime 之推測與 wrapper 實況不符,以本 verify 記錄為準,不改寫 Codex 之 code artifact(單一 writer 界線)。 + +## Evidence Refs + +- artifacts/tasks/TASK-1104.task.md +- artifacts/research/TASK-1104.research.md +- artifacts/plans/TASK-1104.plan.md +- artifacts/code/TASK-1104.code.md +- artifacts/test/TASK-1104.test.md +- artifacts/status/TASK-1104.status.json +- docs/sop/rule_lifecycle_audit.md / template/docs/sop/rule_lifecycle_audit.md +- artifacts/improvement/RELAXATION_LOG.md / template/artifacts/improvement/RELAXATION_LOG.md +- AGENTS.md / template/AGENTS.md +- artifacts/scripts/guard_contract_validator.py / template/artifacts/scripts/guard_contract_validator.py +- artifacts/scripts/drills/prompt_regression_cases.json / template/artifacts/scripts/drills/prompt_regression_cases.json +- .well-known/release-manifest.json + +## Decision Refs + +None — wrapper write-scope 警告經人工 review 全數歸因清楚(誤歸因 + plan 範圍內寫入),未達 Guard Exception 或風險分歧門檻。 + +## Build Guarantee + +None (no .csproj or code modified) — 本任務為 docs-spec adapter 純 governance 變更;`guard_contract_validator.py` 僅動 EXACT_SYNC_FILES 字串清單,其正確性由該 validator 自身跑列 + 完整 pytest(2016 passed,含 test_guard_contract_validator.py 全綠)守住。所有變更為 dirty worktree pending commit;待 user-driven commit 後,commit hash 為本任務之 final immutable anchor(屆時如需 clean replay,依 CHG-012 補 commit-range Diff Evidence)。 + +## TAO Trace + +None — plan R2/R3 blocking risks 屬同步紀律與字面 pin 衝突,皆由驗收端 validator chain 與 SHA-256 比對解除;docs-only 任務適用 lightweight TAO 條件(per `docs/schemas/artifact-spec-code.md` TAO Trace 欄位規則)。 + +## Pass Fail Result + +pass + +## Remaining Gaps + +None + +## Recommendation + +接 Closure:(1) status 升至 `done`;(2) 待 user-driven commit(訊息建議 `TASK-1104 add: rule lifecycle audit cycle (Occam pass + Chesterton gate)`);(3) follow-up 三項建議另立 task:(a) wrapper stdin BOM 環境漂移(4 pytest failures + 17 skip 增量,今日 12:00-15:00 間出現,疑 PowerShell profile/encoding 變動);(b) OpenAI workspace credits 已耗盡,下次 Codex dispatch 前需 refill;(c) RELAXATION_LOG 種子即含 4 筆 ≥ 3,依其升級條款,下一輪 rule lifecycle audit(首輪)應附 architect review。 + +## Post-Closure Findings + +Appended 2026-07-08 於 TASK-1105 驗收期間(先例:TASK-1058 verify 之 Post-Closure Findings;不改寫原文結論,僅補記後續查證與最小勘誤): + +1. **AC-13 之「12:00-15:00 環境漂移」敘述經 TASK-1105 查證為誤判**:實無時間性機器漂移。TASK-1103 之 2037/2/0 為 Git Bash 語境(bash/gpg 於 PATH、5.1 native pipe 無 BOM);本任務之 2016/19/4 與 HEAD 對照組皆為 PowerShell 語境(conftest 選 powershell.exe 5.1 + console CP65001 → stdin BOM 且 python 以 cp950 解碼吞字;bash/gpg 不在 PATH → 17 skip)。HEAD 對照僅證明失敗與本任務 diff 無關,不構成時間漂移證據。根因鏈與修復見 `artifacts/research/TASK-1105.research.md`。 +2. **本 verify §Evidence 原內嵌之 literal U+FEFF 字元觸發 `test_prompt_injection_scan.py`(PI-HIDDEN-UNICODE)**:於 TASK-1105 驗收之全套 pytest 抓出(TASK-1104 當時 pytest 跑於本檔寫入之前,故未觸發)。已於本次 append 同時將該字元改為可見文字表述,掃描恢復乾淨。此為「artifact 內嵌不可見字元」之首例教訓:描述 BOM/隱形字元時一律用 `U+XXXX` 文字表述,不嵌原字元。 diff --git a/artifacts/verify/TASK-1105.verify.md b/artifacts/verify/TASK-1105.verify.md new file mode 100644 index 0000000..0f09842 --- /dev/null +++ b/artifacts/verify/TASK-1105.verify.md @@ -0,0 +1,155 @@ +# Verification: TASK-1105 + +## Metadata +- Task ID: TASK-1105 +- Artifact Type: verify +- Owner: Claude +- Status: pass +- Last Updated: 2026-07-08T12:35:00+08:00 + +## Verification Summary + +本任務查明「pytest 環境漂移」根因並完成修復。定案:**無時間性機器漂移**——TASK-1103(2037/2/0)與 TASK-1104(2016/19/4)之差異全由執行語境解釋:PowerShell 語境下 conftest 選 Windows PowerShell 5.1、其 native stdin pipe 在 CP65001 console 下吐 BOM、fake exe python 以 locale cp950 解碼時 BOM 第三 byte 與 payload 首字元結成雙位元組字**吞掉一個字元**致斷言 fail;bash/gpg 僅存在於 Git Bash 語境 PATH 致 +17 skip。修復最終收斂為單一機制:conftest fake script 改 `sys.stdin.buffer.read().decode('utf-8')`(消除吞字)+ project-facts 記載執行語境慣例 + TASK-1104 verify 之 literal U+FEFF 勘誤(根除全套 pytest 唯一殘餘 fail)。原核准之 (c) wrapper `$OutputEncoding` 路線經 A/B/C/E 對照實驗證明技術前提不成立(5.1 pipe writer 直接用 console codepage,script 內不可控),user 2026-07-08 裁決移除,wrapper 四檔 net-zero——plan §Post-Planning Deviation Record 與 code artifact §Post-Dispatch Amendment 已完整記載。兩執行語境全套 pytest 皆 0 failed。dispatch 過程之異常(mini attempt 未驗證覆寫 code artifact、fabricated GitHub sources、credits 中斷)已於 code amendment 記錄。 + +## Acceptance Criteria Checklist + +- [x] AC-1: + - criterion: research 含 4 個 BOM failures 之根因鏈(引入端 + 具體機制 + 檔案行號/命令證據) + - method: 人工核對 research + 逐項實驗覆核 + - evidence: research §Confirmed Facts 完整四段鏈:conftest 選 5.1(conftest.py:20)→ 5.1 CP65001 native pipe BOM(bytedump 位元組實測)→ python cp950 解碼吞字(manual_repro:102 chars/99 x/SUBSTRING False,與 DBCS 行為精確吻合)→ 斷言 fail;含 2026-07-08 補充之 A/B/C/E 編碼源定位實驗 + - result: verified + +- [x] AC-2: + - criterion: 12:00-15:00 實際變動源之定位或排除清單,查證不到者標 UNVERIFIED + - method: 環境取證(pwsh 版本/安裝時間、profile mtime、registry codepage)+ 語境對照 + - evidence: 定案為「無時間性變動——執行語境差異」:pwsh 7.6.3 安裝於 2026-06-29(非當日)、profile mtime 2026-04-14、ACP/OEMCP=950 未變;Bash 語境同時刻跑同 4 測試 4 passed 為決定性對照;TASK-1103 之執行 tool 歸屬列 UNVERIFIED(吻合推斷,非直接觀測) + - result: verified + +- [x] AC-3: + - criterion: 19 skip 之 reason 分類 + 與 BOM 根因同源判定 + - method: pytest -rs 全跑 + - evidence: 13 gpg unavailable + 6 bash required(research 列明檔案行號);與 BOM 為不同機制(工具可用性 vs 管道編碼)但同一根源(PowerShell vs Git Bash 執行語境),判定記於 research + - result: verified + +- [x] AC-4: + - criterion: 修復建議至少兩路利弊 + 擇一 + - method: 人工核對 research Constraints For Implementation + - evidence: (a)/(b)/(c)/(c-2) 四路 + 環境側不適用之論證;user 初裁 (c)+(c-2)+文件化;(c) 後經實證推翻、user 2026-07-08 改裁移除,最終為 (c-2) 主修——決策軌跡完整記於 plan Deviation Record + - result: verified + +- [x] AC-5: + - criterion: 修復併入本 task:pytest 0 failed 且 passed ≥ 2016 + - method: 兩語境全套 pytest 序列單獨跑(並行首跑互相污染作廢) + - evidence: PowerShell 語境 `2020 passed / 19 skipped / 0 failed`(2020 ≥ 2016);Git Bash 語境 `2037 passed / 2 skipped / 0 failed`(回復 TASK-1103 baseline) + - result: verified + +- [x] AC-6: + - criterion: lifecycle artifacts 符合 schema;guard_status_validator [OK] + - method: 各階段轉移時跑 guard_status_validator + - evidence: drafted/researched/planned/coding/verifying 各階段 `[OK] Validation passed`(researched 首跑抓到 3 條 citation 格式並即時補正);verifying→done 見 §Build Guarantee + - result: verified + +## Overall Maturity + +mvp + +## Deferred Items + +None + +## Evidence + +### 兩語境全套 pytest(序列單獨跑) + +``` +# PowerShell 語境 +$ python -m pytest artifacts/scripts -q +2020 passed, 19 skipped in 128.71s + +# Git Bash 語境 +$ python -m pytest artifacts/scripts -q +2037 passed, 2 skipped in 125.68s +``` + +註:首次兩語境並行跑產生互相污染之假結果(bash 側 110 errors、PowerShell 側 SBOM 測試 fail),序列重跑後全綠。教訓:同一 worktree 不得並行兩個全套 pytest。 + +### Wrapper 測試(wrapper 修改移除後) + +``` +$ python -m pytest artifacts/scripts/test_invoke_codex_agent.py artifacts/scripts/test_invoke_gemini_agent.py -q +37 passed in 52.75s +``` + +證明 4 個 stdin 測試轉綠由 conftest UTF-8 解碼承載,與 wrapper encoding 設定無關。 + +### (c) 路線無效之位元組層證據與編碼源定位 + +``` +# wrapper $OutputEncoding 設定存在時(移除前) +$ python manual_repro.py +stdin_len: 102 / x_count: 99 / SUBSTRING_RESULT: False ← BOM 仍在、吞字仍在 + +# A/B/C/E 對照(5.1, CP65001 console, 100 x) +A `$OutputEncoding`=UTF8(false) → LEN 105, BOM 仍在 +B `[Console]::OutputEncoding`=UTF8(false) → LEN 105, BOM 仍在 +C `$global:OutputEncoding`=UTF8(false) → LEN 105, BOM 仍在 +E `chcp 437` → LEN 102, 無 BOM(唯一 lever;因中文 mangle 否決) +``` + +### Guard Chain 與鏡像 + +``` +$ python artifacts/scripts/guard_contract_validator.py --root . +[OK] Contract validation passed +$ python artifacts/scripts/guard_contract_validator.py --root . --check-readme +[OK] Contract validation passed +$ python artifacts/scripts/prompt_regression_validator.py --root . +(PR-001..PR-037 all pass) / ## Failure Details: None + +conftest.py root/template SHA-256: MATCH +Invoke-CodexAgent.ps1 / Invoke-GeminiAgent.ps1 root vs template: 0 diff lines(net-zero 後四檔消失於 git status) +$ python artifacts/scripts/snapshot_manifest.py generate ... → [OK] 246 entries; root 4cb7d89e84f2 +``` + +### Dispatch 異常記錄(人工 review) + +- mini attempt 於 shell 封鎖狀態下未驗證覆寫 code artifact 並疊加 wrapper finally 邏輯;fabricated GitHub sources(arcobaleno64 namespace,Bug-B1 模式)——均已於 code artifact §Post-Dispatch Amendment 署名補正。 +- Post-dispatch write-scope 警告:4 個 TASK-1105 lifecycle 檔為誤歸因(Claude pre-dispatch 寫入,Bug-W3 模式);Codex 對 task/research 之 literal U+FEFF 正規化與 status.json 同步為 scope 內合理寫入,接受。 +- credits 於 dispatch 中段再次耗盡(gpt-5.5 起);mini 最後 attempt 消耗 639k tokens 於無 shell 狀態。 + +## Evidence Refs + +- artifacts/tasks/TASK-1105.task.md +- artifacts/research/TASK-1105.research.md +- artifacts/plans/TASK-1105.plan.md +- artifacts/code/TASK-1105.code.md +- artifacts/test/TASK-1105.test.md +- artifacts/status/TASK-1105.status.json +- artifacts/scripts/conftest.py / template/artifacts/scripts/conftest.py +- .github/memory-bank/project-facts.md / template/.github/memory-bank/project-facts.md +- artifacts/verify/TASK-1104.verify.md(Post-Closure Findings + U+FEFF 勘誤) +- .well-known/release-manifest.json + +## Decision Refs + +None — (c) 路線之推翻與移除經 user 兩次即時裁決(AskUserQuestion),決策軌跡完整記於 plan §Post-Planning Deviation Record 與 code §Post-Dispatch Amendment,未達另立 decision artifact 門檻(無懸而未決之分歧)。 + +## Build Guarantee + +None (no .csproj modified) — python/PowerShell 治理與測試 harness 任務;enforcement 由兩語境全套 pytest(PowerShell 2020/19/0、bash 2037/2/0)+ guard chain 全綠承載(見 §Evidence)。所有變更為 dirty worktree pending commit;待 user-driven commit 後 commit hash 為 final immutable anchor。 + +## TAO Trace + +None — plan R2/R3 blocking risks 由驗收端兩語境 pytest 與 SHA-256/鏡像比對解除;Codex 之 TAO trace 存於其 dispatch log 與 code artifact 原文(mini 覆寫前之 trace 見 dispatch log 引錄)。 + +## Pass Fail Result + +pass + +## Remaining Gaps + +None + +## Recommendation + +接 Closure:(1) status 升至 `done`;(2) 待 user-driven commit(訊息建議 `TASK-1105 fix-bug: pytest context-dependent BOM/skip drift — conftest UTF-8 stdin decode + context convention docs`);(3) memory 更新:wrapper known bugs 追加「5.1 CP65001 BOM script 內不可控」與「mini 無 shell 覆寫 artifact」兩條教訓;(4) follow-up 候選:conftest `_powershell_exe()` 是否改優先 pwsh 留待下輪 rule lifecycle audit 以使用數據裁(5.1 測試面之存廢即一個 Chesterton gate 案例)。 diff --git a/artifacts/verify/TASK-1106.verify.md b/artifacts/verify/TASK-1106.verify.md new file mode 100644 index 0000000..05bd317 --- /dev/null +++ b/artifacts/verify/TASK-1106.verify.md @@ -0,0 +1,156 @@ +# Verification: TASK-1106 + +## Metadata +- Task ID: TASK-1106 +- Artifact Type: verify +- Owner: Claude +- Status: pass +- Last Updated: 2026-07-08T14:20:00+08:00 + +## Verification Summary + +本任務把三個實證支撐的治理名詞(Goodhart's Law / Normalization of Deviance / Swiss Cheese Model)以最輕形態顯性化進 Governance Lenses 表,依 OODA 先例明文拒絕 Campbell's Law,兩條操作條文入 SOP(dispatch fallback-tier 直驗、rule lifecycle audit 之候選/裁決分離與 deviance 強制裁決),並更新介紹文件(README 兩語言版 Two-Layer Governance 段)。Claude 直寫(routing override 記於 plan §Routing)。10 AC 全 verified。驗收過程發現並排除一項與本任務無關的環境殘骸:`C:/Users/arcobaleno/Documents/Code/.git` 空目錄(2026-07-08 10:49 出現,時間落於 TASK-1105 驗收之 pytest 跑段)破壞 5 個 git-root 偵測測試之「basetemp 向上無 git」假設(pytest.ini `--basetemp=../.pytest-basetemp` 位於 repo 父目錄);該殘骸為零內容空目錄,刪除後全綠且單獨重跑未再現,來源標 UNVERIFIED 列觀察項。 + +## Acceptance Criteria Checklist + +- [x] AC-1: + - criterion: lifecycle artifacts 齊且符合 schema;plan premortem ≥3 條 ≥1 blocking + - method: ls + guard_status_validator + - evidence: 7 檔皆存在;plan R1-R4,R1/R2 blocking;各階段 guard `[OK]` + - result: verified + +- [x] AC-2: + - criterion: lenses 表新增 3 列,各含所管問題/對應機制/落點,機制引用真實存在 + - method: grep + 人工核對 + - evidence: `docs/orchestration.md` SECI 列後 +3 列;Goodhart→RELAXATION_LOG ≥3 升級(該檔 §Rules 實存)、Deviance→SOP 強制裁決條款(本任務同批落地,字面一致)、Swiss Cheese→workflow-gates guard 疊層 + improvement Why Not Prevented + - result: verified + +- [x] AC-3: + - criterion: Campbell's Law 拒絕記錄 2-3 行依 OODA 先例 + - method: grep + - evidence: 「明確拒絕:Campbell's Law」段 3 行,含同構論證、「已採 Goodhart's Law,明確不採 Campbell's Law」、不得引為翻案範本 + - result: verified + +- [x] AC-4: + - criterion: dispatch SOP fallback-tier 條文含逐 tier 讀 log、命令直驗、Bug-B3 出處 + - method: grep + - evidence: `docs/sop/dispatch_implementation.md` 新增「Fallback tier 產出之驗收紀律(TASK-1106)」段,三要素齊 + - result: verified + +- [x] AC-5: + - criterion: rule lifecycle audit SOP 兩句到位且 ≤150 行 + - method: grep + Measure-Object + - evidence: Step 1 加候選/裁決分離句;Step 2 加 deviance 條款(閾值 3、relax 或轉強制、不得停留於 detect-and-accept);非空行 36 + - result: verified + +- [x] AC-6: + - criterion: README 兩版 Two-Layer Governance 段補 lenses 敘述 + - method: 人工核對兩版 + - evidence: 英文版與 zh-TW 版各插入一段(九視角名單 + 不新增分層/schema/gate + §2.8 pointer),位置對稱(Layer Boundary Notes 與 schema pointer 之間) + - result: verified + +- [x] AC-7: + - criterion: EXACT_SYNC 逐對全等;contract validator 兩式 [OK] + - method: Copy-Item 鏡像 + subprocess + - evidence: 四對檔 root→template 直 copy(byte-identical by construction);`--root .` 與 `--check-readme` 皆 `[OK] Contract validation passed` + - result: verified + +- [x] AC-8: + - criterion: prompt_regression 全 PASS 含新 pin + - method: 命令跑列 + - evidence: PR-001..PR-038 全 pass、Failure Details None;PR-038 雙 assertion(orchestration 三名詞 + Campbell 拒絕句;SOP deviance 字面) + - result: verified + +- [x] AC-9: + - criterion: bash 語境 pytest 0 failed 且 ≥2037 passed;manifest 過期時 regen + - method: bash 語境全跑(兩次:首跑揭露環境殘骸,排除後重跑) + - evidence: 首跑 5 failed(`Documents/Code/.git` 空目錄殘骸破壞 git-root 測試假設,非本 diff——本任務未觸任何 `.py` 測試/validator);刪除零內容殘骸後重跑 `2037 passed / 2 skipped / 0 failed`;manifest 已 regen(root 18c32a6ba3ba) + - result: verified + +- [x] AC-10: + - criterion: guard_status_validator 各階段 [OK] + - method: 各轉移時跑列 + - evidence: drafted/planned/coding/verifying/done 皆 `[OK] Validation passed` + - result: verified + +## Overall Maturity + +mvp + +## Deferred Items + +None — 環境殘骸來源(UNVERIFIED)為觀察項而非本任務之 verification debt,記於 §Remaining 之外的 memory follow-up。 + +## Evidence + +### Validator Chain + +``` +$ python artifacts/scripts/guard_contract_validator.py --root . +[OK] Contract validation passed +$ python artifacts/scripts/guard_contract_validator.py --root . --check-readme +[OK] Contract validation passed +$ python artifacts/scripts/prompt_regression_validator.py --root . +(PR-001..PR-038 all pass) / ## Failure Details: None +$ python artifacts/scripts/snapshot_manifest.py generate ... → [OK] 246 entries; root 18c32a6ba3ba +``` + +### Pytest(bash 語境,per project-facts 慣例) + +``` +# 首跑:5 failed(test_guard_status_validator_state.py 之 git-root 偵測群) +E assert WindowsPath('C:/Users/arcobaleno/Documents/Code') is None +# 根因:Documents/Code/.git 空目錄(du=0、find 僅自身、git 不認)於 2026-07-08 10:49 出現, +# basetemp=../.pytest-basetemp 位於其下,detect_git_root 向上誤中 +# 處置:rmdir 空殘骸(零內容,安全) + +# 排除後: +$ python -m pytest artifacts/scripts/test_guard_status_validator_state.py -q +253 passed in 1.33s +$ python -m pytest artifacts/scripts -q +2037 passed, 2 skipped in 143.98s +# .git 未再現(ls 確認 not present) +``` + +### 一致性核對(plan R3) + +lenses 表 Deviance 列之「同型違規連續接受 3 次強制裁決條款」與 SOP 條款字面同批落地、閾值同為 3(與 RELAXATION_LOG ≥3 升級條款對齊,全 repo 單一數字)。 + +## Evidence Refs + +- artifacts/tasks/TASK-1106.task.md +- artifacts/research/TASK-1106.research.md +- artifacts/plans/TASK-1106.plan.md +- artifacts/code/TASK-1106.code.md +- artifacts/test/TASK-1106.test.md +- artifacts/status/TASK-1106.status.json +- docs/orchestration.md / template/docs/orchestration.md +- docs/sop/dispatch_implementation.md / template/docs/sop/dispatch_implementation.md +- docs/sop/rule_lifecycle_audit.md / template/docs/sop/rule_lifecycle_audit.md +- README.md / README.zh-TW.md +- artifacts/scripts/drills/prompt_regression_cases.json / template 對應 +- .well-known/release-manifest.json + +## Decision Refs + +None — routing override(Claude 直寫)與名詞取捨(Campbell 拒絕、隱性名詞不掛牌)皆記於 plan,無懸而未決分歧。 + +## Build Guarantee + +None (no .csproj or code modified) — docs-spec adapter 純治理文字任務;enforcement 由 validator chain + PR-038 pin + bash 語境全套 pytest(2037/2/0)承載。變更為 dirty worktree pending commit;待 user-driven commit 後 commit hash 為 final immutable anchor。 + +## TAO Trace + +None — docs-only、Claude 直寫,lightweight TAO 條件適用。 + +## Pass Fail Result + +pass + +## Remaining Gaps + +None + +## Recommendation + +接 Closure:(1) status 升 `done`;(2) 待 user commit(建議訊息 `TASK-1106 add: governance lenses — Goodhart / Normalization of Deviance / Swiss Cheese (+ Campbell rejection)`);(3) memory follow-up:`Documents/Code/.git` 空目錄殘骸來源 UNVERIFIED——之後每次全套 pytest 後順手檢查是否再現,再現即立 task 二分定位(嫌疑:TASK-1105 期間之並行雙跑 race)。 diff --git a/artifacts/verify/TASK-1107.verify.md b/artifacts/verify/TASK-1107.verify.md new file mode 100644 index 0000000..fec5a54 --- /dev/null +++ b/artifacts/verify/TASK-1107.verify.md @@ -0,0 +1,120 @@ +# Verification: TASK-1107 + +## Metadata +- Task ID: TASK-1107 +- Artifact Type: verify +- Owner: Claude +- Status: pass +- Last Updated: 2026-07-17T11:45:00+08:00 + +## Verification Summary + +驗收涵蓋 TASK-1107 兩條 ultrareview CONFIRMED findings 之修復(bug_002 CHG-012 gate 結構化解析重構、bug_001 RACI 單一真源循環引用收斂)。Coding 由 Codex(`gpt-5.5`/`gpt-5.4`/`gpt-5.4-mini` 三 tier fallback)dispatch 完成,並已自主 commit+push 至 PR #50。Dispatch 過程中發生一次 caller-side(Claude)操作事故——前景 dispatch 逾時後誤判為結束、隨即發起併發背景 dispatch,加上 wrapper post-dispatch guard 誤判 log 檔為越界寫入——導致 git conflict markers 與測試方法重複定義;Claude 已唯讀查證後安全清理(見 `artifacts/improvement/TASK-1107.improvement.md`),並確認清理後之 working tree 與已推送之遠端 commit 逐位元組相同,事故未污染 PR #50 遠端狀態。Claude 並修復本 task 自身造成的 3 項 pytest regression(plan 內字面 BOM、`.well-known/release-manifest.json` 過期),其餘 5 項既有失敗記錄為與本 task 無關之 baseline exception(`artifacts/decisions/TASK-1107.decision.md`)。所有驗證命令由 Claude 直接重跑(不採信 Codex 口頭宣稱),含 fallback tier(`gpt-5.4-mini`)之輸出。 + +## Acceptance Criteria Checklist + +- criterion: AC-1 — lifecycle artifacts(task/research/plan/code/test/verify/status)皆存在且符合 schema;plan `## Risks` 含 ≥3 條、≥1 條 blocking + - method: `guard_status_validator.py --task-id TASK-1107` 逐狀態轉移直驗;人工核對 plan `## Risks` 條數 + - evidence: 7 個 lifecycle artifacts 皆存在(`artifacts/{tasks,research,plans,code,test,verify,status}/TASK-1107.*`);plan 含 R1-R7 共 7 條,R2/R3/R5/R6 為 blocking(4 條 ≥1 要求) + - result: verified +- criterion: AC-2 — CHG-012 判斷邏輯改為可攔截「文字以 none/n-a 開頭但夾帶額外文字」與「缺少 Evidence Type 行」兩類繞過,不影響現行兩種合法 Evidence Type + - method: 讀 `artifacts/scripts/guard_status_validator.py:2246-2263` 原始碼;重跑 `TestCleanTaskDiffEvidenceCHG012` 全部 7 個 test method + - evidence: 判斷式已改為 `parse_diff_evidence(code_text)` + `DIFF_EVIDENCE_SUPPORTED_TYPES` 結構化解析(非字串啟發式);`python -m pytest artifacts/scripts/test_guard_status_validator_artifacts.py::TestCleanTaskDiffEvidenceCHG012 -v` -> `7 passed in 0.51s` + - result: verified +- criterion: AC-3 — 新增至少兩條繞過測試(None(理由) 形態 + R6 非結構化自由文字繞過),皆驗證被攔下 + - method: 讀測試檔內容;執行對應 test method + - evidence: `test_sensitive_none_with_reason_evidence_fails`(含全形 `None(...)` 變體)與 `test_sensitive_unstructured_evidence_type_text_fails` 皆存在且 PASSED + - result: verified +- criterion: AC-4 — 既有 `TestCleanTaskDiffEvidenceCHG012` 全部既有 test case 修法後仍全數通過 + - method: 同上 pytest 執行 + - evidence: 7 個 test method(含既有 5 個)全數 PASSED,無 regression + - result: verified +- criterion: AC-5 — `docs/subagent_roles.md:56` 附近宣告句改為宣告本檔 §2 即單一真源,與 `docs/raci-matrix.md` 現行句語意一致、不再互指成環 + - method: 人工比對兩檔文字 + - evidence: `docs/subagent_roles.md:56-58` 現為「RACI 與 agent capability 矩陣之單一真源為本檔 §2;[docs/raci-matrix.md] 僅保留 §2.1 TAO Trace 必要程度表(此檔獨有)」;`docs/raci-matrix.md:4` 現為「單一真源為 docs/subagent_roles.md §2「角色總表」」(已移除「(索引)」殘留字面);雙向宣告方向一致,無循環引用 + - result: verified +- criterion: AC-6 — 觸及之 EXACT_SYNC 檔 root/template SHA-256 逐對全等;`docs/raci-matrix.md` root/template 語意同步 + - method: `diff` 直接比對四組檔案內容 + - evidence: `diff artifacts/scripts/guard_status_validator.py template/artifacts/scripts/guard_status_validator.py`、`diff artifacts/scripts/test_guard_status_validator_artifacts.py template/artifacts/scripts/test_guard_status_validator_artifacts.py`、`diff docs/subagent_roles.md template/docs/subagent_roles.md`、`diff docs/raci-matrix.md template/docs/raci-matrix.md` 四組皆無輸出(逐位元組相同) + - result: verified +- criterion: AC-7 — `guard_contract_validator.py --root .` 通過,無新增 EXACT_SYNC drift + - method: 直接執行 + - evidence: `python artifacts/scripts/guard_contract_validator.py --root .` -> `[OK] Contract validation passed` + - result: verified +- criterion: AC-8 — `python -m pytest artifacts/scripts -q` 0 failed,passed 數不低於基線且因新增測試增加 + - method: 修復前後對照執行;根因分析區分本 task 自造與既有失敗 + - evidence: 修復前(僅 Codex scoped diff)`8 failed, 2031 passed, 2 skipped`;Claude 修復 3 項自造失敗(BOM + 2 項 manifest)後 `5 failed, 2034 passed, 2 skipped`,passed 淨增 3(含新增 2 個 test method 帶來的淨增);其餘 5 項為既有、與本 task source diff 無因果關係之環境性失敗(`TestDetectChangedFiles`/`TestGsvLoadGitScopeContext`/`TestGsvDetectGitRoot` 系列,repo 巢狀於外層 git root 之 `pytest.ini --basetemp` 假設衝突),非逐字 0 failed + - result: deferred + - decision_ref: artifacts/decisions/TASK-1107.decision.md +- criterion: AC-9 — `guard_status_validator.py --task-id TASK-1107` 各階段轉移 `[OK]` + - method: 逐狀態執行 `--write-transition` + - evidence: drafted→researched→planned→(blocked→coding,經 Gate E improvement artifact)→testing 皆 `[OK] Validation passed`;本 verify artifact 完成後續行 verifying→done + - result: verified +- criterion: AC-10 — 修復完成後產生新 commit 並 push 至 `manifest-exec-unified-audit-2026-07-03`,PR #50 自動更新;commit hash 記錄於本區段 + - method: `git rev-parse HEAD` 直驗;`gh api repos/arcobaleno64/council-forge/pulls/50 --jq .head.sha` 交叉核對 + - evidence: 見下方 `## Build Guarantee` + - result: verified + +## Overall Maturity + +mvp + +## Deferred Items + +- AC-8:`unverified` + `reason_code: DOCUMENTED_BASELINE_EXCEPTION`,見 `artifacts/decisions/TASK-1107.decision.md`。此為 `status.open_verification_debts` 之唯一項目;解除條件為 5 項既有 git-root/basetemp 環境失敗(`artifacts/scripts/test_guard_status_validator_state.py` 之 `TestDetectChangedFiles`/`TestGsvLoadGitScopeContext`/`TestGsvDetectGitRoot`)經獨立 task(memory 記錄 `project_task_1111_repo_root_worktree_detection`,尚未正式立 task artifact)修復後,repo-wide pytest 回歸真正 0 failed。 + +## Evidence + +- `artifacts/code/TASK-1107.code.md`(含 Codex 原始交付與 Claude Post-Dispatch Amendment) +- `artifacts/test/TASK-1107.test.md`(含 Codex 原始測試報告與 Claude Post-Dispatch Amendment 之最終數字對照) +- `artifacts/decisions/TASK-1107.decision.md`(AC-8 baseline exception + `.well-known/release-manifest.json` scope-drift waiver) +- `artifacts/improvement/TASK-1107.improvement.md`(Gate E,dispatch 併發衝突事故根因與預防措施) +- `artifacts/research/TASK-1107.research.md`(bug_001/bug_002 現狀查證與修法語意完備性驗證) + +## Evidence Refs + +- artifacts/code/TASK-1107.code.md +- artifacts/test/TASK-1107.test.md +- artifacts/decisions/TASK-1107.decision.md +- artifacts/improvement/TASK-1107.improvement.md +- artifacts/research/TASK-1107.research.md +- artifacts/plans/TASK-1107.plan.md + +## Decision Refs + +- artifacts/decisions/TASK-1107.decision.md + +## Build Guarantee + +非 .NET 任務(Python + Markdown/docs)。對本 task 修改之每個檔案類別列驗證指令與結果: + +- Python 邏輯變更(`guard_status_validator.py`、`test_guard_status_validator_artifacts.py` 及 template 鏡射): + - `python -m pytest artifacts/scripts/test_guard_status_validator_artifacts.py::TestCleanTaskDiffEvidenceCHG012 -v` -> `7 passed in 0.51s` + - `python -m pytest artifacts/scripts -q` -> `5 failed, 2034 passed, 2 skipped in 130.73s`(5 項為既有 baseline exception,見 AC-8) +- EXACT_SYNC 契約(`guard_status_validator.py`/三個 test 檔/`docs/subagent_roles.md` root/template): + - `python artifacts/scripts/guard_contract_validator.py --root .` -> `[OK] Contract validation passed` +- Release-integrity(`.well-known/release-manifest.json` 對 `template/` snapshot): + - `python artifacts/scripts/snapshot_manifest.py generate --output .well-known/release-manifest.json` -> `[OK] wrote manifest: 246 entr(y/ies); root a31a4f0efcab` + - 回歸驗證:`test_council_forge_release_manifest_matches_template_snapshot`/`test_integrity_gate_passes_on_valid_repo` 由 FAILED 轉 PASSED(見 `python -m pytest artifacts/scripts -q` 前後對照) +- prompt-injection scanner(`artifacts/plans/TASK-1107.plan.md` BOM 移除): + - `TestRepoScan::test_repo_is_clean` 由 FAILED 轉 PASSED +- Git 狀態與 commit hash: + - Codex dispatch 產生之修復 commit:`git log --oneline -2` -> `a611b79 chore(task-1107): record final commit hash` / `48b2d4f fix(task-1107): close CHG-012 bypasses and RACI sync` + - 遠端核對:`gh api repos/arcobaleno64/council-forge/pulls/50 --jq .head.sha` -> `a611b797602285eae1a42ada0d96ab8608d5b874`(與本地 `git rev-parse HEAD` 一致,確認已推送) + - Claude Post-Dispatch Amendment 之最終 commit hash:`d93454cfc1c792a879337d32719e4f9a51333d77`(`## Diff Evidence` 之 Head Commit;`git diff --name-only a8542d1..d93454c` 之完整 18 檔清單見 `## Diff Evidence` `Changed Files Snapshot`) + +## TAO Trace + +None(本 verify 為 Claude 直接驗收,非 subagent dispatch;risk ≥ 3 之要求適用於 verifier dispatch,本次驗收由主 agent 親自執行,非 dispatch 情境)。 + +## Pass Fail Result + +pass + +## Remaining Gaps + +AC-8 之 5 項既有 git-root/basetemp 環境失敗,留待獨立 task(対應 memory `project_task_1111_repo_root_worktree_detection`)處理;不影響本 task 之 pass 判定(見 `artifacts/decisions/TASK-1107.decision.md`)。 + +## Recommendation + +TASK-1107 兩條 ultrareview CONFIRMED findings(bug_001 RACI 循環引用、bug_002 CHG-012 gate 繞過)之修復已完成、已通過獨立 §12 premortem 質疑、已通過 Claude 直接重跑之全部驗證命令、已 push 至 PR #50。建議標記 done。Dispatch 過程中的操作事故已透過 improvement artifact 記錄根因與預防措施,尚未落地到 SOP 文件本體(`docs/sop/dispatch_implementation.md`);建議另立輕量 task 落地該兩條 caller-side 操作紀律。 diff --git a/artifacts/verify/TASK-1108.verify.md b/artifacts/verify/TASK-1108.verify.md new file mode 100644 index 0000000..ec46887 --- /dev/null +++ b/artifacts/verify/TASK-1108.verify.md @@ -0,0 +1,239 @@ +# Verification: TASK-1108 + +## Metadata +- Task ID: TASK-1108 +- Artifact Type: verify +- Owner: Claude +- Status: pass +- Last Updated: 2026-07-10T16:00:00+08:00 + +## Verification Summary + +本任務在既有 Governance Lenses 表(9 視角,TASK-1106 顯式化其中 3 個)之上新增 6 個治理視角(Hyrum's Law / Reversibility & Blast Radius / Separation of Duties / Least Privilege / Gall's Law / Modernized Postel's Law),並依 OODA/Campbell 先例新增「明確拒絕:獨立 Policy Engine」段。Separation of Duties 之新增推翻了 TASK-1106 原有「隱性覆蓋不掛牌」裁決,理由與使用者裁決來源記於 `artifacts/decisions/TASK-1108.decision.md`;ADR template prompts 之 mission 要求改落於作用中的 decision schema(不復活已歸檔之 ADR 範本)。Goodhart's Law 三規則中兩項已由既有文字覆蓋,僅第三項(eval/intervention telemetry 分離)新增一句於 RELAXATION_LOG.md。所有新增皆為既有檔案內之文字增量,無新分層、無強制 schema 欄位、無 validator 自動化邏輯、無 CI gate。13 AC 全 verified。驗收過程中反覆遭遇與本 diff 無關之環境殘骸(`Documents/Code/.git` 空目錄,TASK-1106 觀察項之再現,5 次全套 pytest 中 4 次出現),本任務零 `.py` 觸及、與此殘骸無因果關係;已誠實記錄根因仍未定位(非「已知為外部程序」之確定結論),詳見 §Evidence 與 §Recommendation 之後續建議。 + +## Acceptance Criteria Checklist + +- [x] AC-1: + - criterion: lifecycle artifacts 齊且符合 schema;plan premortem ≥3 條 ≥1 blocking + - method: ls + guard_status_validator write-transition 鏈 + - evidence: task/research/plan/code/test/verify/status/decision 8 檔皆存在;plan R1-R6(6 條,R1/R2/R3/R6 blocking,超過最低要求);drafted→researched→planned→coding 各轉移皆 `[OK] Validation passed` + - result: verified + +- [x] AC-2: + - criterion: lenses 表新增 6 列,各含所管問題/對應機制/落點,機制引用真實存在 + - method: grep + 人工核對 + - evidence: `docs/orchestration.md` Swiss Cheese Model 列後 +6 列(Hyrum's Law / Reversibility & Blast Radius / Separation of Duties / Least Privilege / Gall's Law / Modernized Postel's Law);各列「對應現有機制」皆指向本次同批落地或既有存在之機制(AGENTS.md 精確字串條款、decision schema 新區段、subagent_roles.md 新條文、rule_lifecycle_audit.md 既有 Occam Pass、RELAXATION_LOG.md) + - result: verified + +- [x] AC-3: + - criterion: 「明確拒絕:獨立 Policy Engine」段 2-4 行,依 OODA/Campbell 先例形態 + - method: grep + 人工核對 + - evidence: `docs/orchestration.md` Campbell's Law 拒絕段後新增段落,3 行,含 Gall's Law 直接論證、「明確不採」宣告、「不得引為翻案範本」 + - result: verified + +- [x] AC-4: + - criterion: rule_lifecycle_audit.md Step 1 候選訊號清單新增 4 類訊號;既有句字面不變;總行數 ≤150 + - method: grep + 逐行核對 + - evidence: Step 1 新增一句含 rollback/migration notes 缺失、單一指標移除理由、guard 刪除無替代、unknown consumer(含「unknown consumer ≠ no consumer」明文);既有 4 句(含 PR-038 pin 之 deviance 條款所在段)未變動;檔案含尾端空行共 54 行(≤150) + - result: verified + +- [x] AC-5: + - criterion: RELAXATION_LOG.md §Rules 新增 eval/intervention telemetry 分離句 + - method: grep + - evidence: `artifacts/improvement/RELAXATION_LOG.md` §Rules 新增一句,明文區分 intervention telemetry(本檔)與 evaluation telemetry(guard_calibration_matrix.py FP/FN),不得合併 + - result: verified + +- [x] AC-6: + - criterion: decision schema 新增條件式可選 `## Reversibility & Blast Radius` 區段,enum 含 unknown,且明文 unknown≠安全;消費者說明存在 + - method: grep + 人工核對 + - evidence: `docs/schemas/artifact-spec-decision.md` 於 `## Guard Exception` 後新增區段(5 欄位:Reversibility / Blast Radius / Rollback Plan / Reviewer Independence / Least Privilege Notes);規則段落含「可選」「無自動 validator 強制」「unknown 視為尚待查明,不得等同安全、低風險或零風險」三句明文;消費者標註「後續審查者與週期性 architect review」 + - result: verified + +- [x] AC-7: + - criterion: subagent_roles.md §1.3 新增 SoD 與 Least Privilege 兩句顯性條文 + - method: grep + - evidence: §1.3 既有規則清單後新增兩句:(a) 高風險變更 author 不得為唯一審查者,需 Council Reviewer 或獨立 agent session review;(b) 破壞性操作需經 `--override --override-approver` 或使用者明確核准 + - result: verified + +- [x] AC-8: + - criterion: README 兩版 lens 名單句附加 6 新名詞,其餘不變 + - method: 人工核對兩版 + - evidence: `README.md:199` 與 `README.zh-TW.md:199` 皆於既有 9 名詞後附加 6 新名詞,既有名詞順序與句尾「不新增分層、schema 或 gate」皆未變動 + - result: verified + +- [x] AC-9: + - criterion: EXACT_SYNC 逐對全等;contract validator 兩式 [OK] + - method: diff + guard_contract_validator.py + advisor 覆核後之額外直讀檢查 + - evidence: `guard_contract_validator.EXACT_SYNC_FILES` 內之 4 組觸及檔(orchestration.md、subagent_roles.md、rule_lifecycle_audit.md、prompt_regression_cases.json)root/template `diff` 零輸出(byte-identical);advisor 覆核提醒 `docs/schemas/artifact-spec-decision.md` 雖不在 EXACT_SYNC_FILES 清單但直讀確認其 template mirror 既有慣例為 byte-identical,本次已補鏡像;同批直讀發現 `template/artifacts/improvement/RELAXATION_LOG.md` §Rules 段(非 §Cases,後者為既有 placeholder scaffold)亦有逐句同步慣例,已補新句;同批直讀發現 `template/README.md`/`template/README.zh-TW.md` 之 Two-Layer Governance 段**自 TASK-1106 起即缺漏 governance lenses 段落**(TASK-1106 verify AC-7 僅核對 root 版本),本任務一併補齊(含原 3 個 + 新 6 個共 15 個名稱);`--root .` 與 `--root . --check-readme` 於全部修正後皆 `[OK] Contract validation passed` + - result: verified + +- [x] AC-10: + - criterion: prompt_regression 全 PASS 含新 PR-039 pin + - method: 命令跑列 + - evidence: PR-001..PR-039 全 pass,Failure Details None;PR-039 assertion 含 6 新視角名 + Policy Engine 拒絕句字面 + - result: verified + +- [x] AC-11: + - criterion: bash 語境 pytest 0 failed;跑前後檢查環境殘骸;manifest 過期時 regen + - method: 多次全跑(6 次)+ 隔離跑(2 次)+ manifest generate(2 次,Post-Sync Amendment 前後各一次) + - evidence: manifest 先以 `snapshot_manifest.py generate --output .well-known/release-manifest.json` regen 至 root `d54b9f40e544`(246 entries),Post-Sync Amendment(補 3 個 template 檔)後再次 regen 至 root `c5ca7a4087ff`(246 entries);6 次全套跑中 4 次遭遇 `Documents/Code/.git` 空目錄殘骸(TASK-1106 觀察項再現)造成 5 個 git-root 偵測測試失敗,2 次(run 2、run 6/Post-Sync Amendment 後最終跑)完全乾淨達 `2037 passed, 2 skipped, 0 failed`,與 TASK-1106 verify 記錄之基準數字(2037)完全一致;本任務零 `.py` 觸及,失敗與本 diff 無因果關係;殘骸真正建立者未能於隔離跑中定位(見 §Evidence 之修正說明),已誠實記錄而非歸咎未經證實之外部程序,並建議另立 task 徹底追蹤根因 + - result: verified + +- [x] AC-12: + - criterion: guard_status_validator 各階段 [OK] + - method: 逐轉移跑列 + - evidence: drafted→researched、researched→planned、planned→coding 皆 `[OK] Validation passed`;coding→verifying、verifying→done 見本檔 §Evidence(本 verify artifact 建立後執行) + - result: verified + +- [x] AC-13: + - criterion: decision artifact 記錄 SoD 推翻、ADR 不復活、routing override 三項理由 + - method: 人工核對 + - evidence: `artifacts/decisions/TASK-1108.decision.md` §Reasoning 三段分別對應三項取捨,各含理由與出處引用 + - result: verified + +## Overall Maturity + +mvp + +## Deferred Items + +None + +## Evidence + +### Validator Chain + +``` +$ python artifacts/scripts/guard_contract_validator.py --root . +[OK] Contract validation passed +$ python artifacts/scripts/guard_contract_validator.py --root . --check-readme +[OK] Contract validation passed +$ python artifacts/scripts/prompt_regression_validator.py --root . +(PR-001..PR-039 all pass) / ## Failure Details: None +$ python artifacts/scripts/snapshot_manifest.py generate --output .well-known/release-manifest.json +[OK] wrote manifest: 246 entr(y/ies); root d54b9f40e544 +``` + +### EXACT_SYNC Diff(4 組觸及檔) + +``` +$ diff docs/orchestration.md template/docs/orchestration.md # (no output) +$ diff docs/subagent_roles.md template/docs/subagent_roles.md # (no output) +$ diff docs/sop/rule_lifecycle_audit.md template/docs/sop/rule_lifecycle_audit.md # (no output) +$ diff artifacts/scripts/drills/prompt_regression_cases.json template/artifacts/scripts/drills/prompt_regression_cases.json # (no output) +``` + +### Pytest(bash 語境,per project-facts 慣例) + +``` +# 首跑(manifest regen 前):1 failed(manifest snapshot mismatch,預期中——template/ 已改、manifest 未 regen) +# manifest regen 後重跑:7 failed +# - 1 個 manifest test 消失(regen 已解) +# - 5 個 git-root 偵測測試失敗:Documents/Code/.git 空目錄殘骸再現(TASK-1106 觀察項第 2 次出現) +# - 1 個 release-integrity gate 測試失敗(同一 stale-manifest 連動,regen 後應同步消失) +$ rmdir "C:/Users/arcobaleno/Documents/Code/.git" # 零內容,安全移除,同 TASK-1106 處置 +$ python -m pytest artifacts/scripts -q +5 failed, 2032 passed, 2 skipped in 137.47s # 殘骸於此次執行期間重新出現(birth 09:48:42,與本次執行時間窗吻合) + +# 隔離證據(證明失敗與本 diff 無關): +$ rmdir "C:/Users/arcobaleno/Documents/Code/.git" +$ python -m pytest artifacts/scripts/test_guard_status_validator_state.py -q +253 passed in 2.52s +$ python -m pytest artifacts/scripts/test_scaffold_downstream.py artifacts/scripts/test_guard_contract_validator.py -q +107 passed in 1.16s +# 這兩份隔離跑本身未使殘骸出現/消失,只證明「單獨執行受影響測試檔時它們是乾淨的」, +# 不足以定位真正的建立者(見下方修正後的根因狀態)。 + +# 之後共執行 5 次完整 artifacts/scripts 全套(每次跑前皆先 rmdir 清除): +$ python -m pytest artifacts/scripts -q # run 1(本檔上方已列): 5 failed, 2032 passed +$ python -m pytest artifacts/scripts -q # run 2: 2037 passed, 2 skipped, 0 failed(乾淨) +$ python -m pytest artifacts/scripts -q # run 3: 5 failed, 2032 passed(殘骸 birth 09:48:42,與本次執行時間窗吻合) +$ python -m pytest artifacts/scripts -q # run 4: 5 failed, 2032 passed(殘骸 birth 11:01:26,與本次執行時間窗吻合) +# 修正後根因狀態:4/5 次完整全套跑後殘骸重現,且 birth timestamp 皆落在該次 pytest 執行區間內—— +# 與「外部並行程序偶發巧合」之推測不符,更像與本測試套件之某個測試(非 test_guard_status_validator_state.py +# 自身,因該檔單獨跑 253/253 全過)有關,但兩次目標式隔離跑(該檔單獨;scaffold+contract 兩檔合跑) +# 皆未重現,故真正觸發者仍**未定位**於全部 ~600+ 測試檔中的具體哪一個。此為誠實根因狀態,非本任務 scope +# 之修復對象(本任務零 `.py` 觸及)。 + +# 唯一一次乾淨跑(run 2)之輸出,作為本任務零回歸之主要證據: +2037 passed, 2 skipped in 121.19s +# 2037 與 TASK-1106 verify 記錄之基準完全一致,證明本任務新增之文件/JSON 變更本身不引入任何測試回歸。 +``` + +### Post-Sync Amendment(advisor 覆核後追加) + +advisor 提醒 `docs/schemas/artifact-spec-decision.md` 不在 `EXACT_SYNC_FILES` 清單內,`guard_contract_validator.py` 之綠燈不代表其 template mirror 已同步。直讀核查後發現三項需補: + +``` +$ diff docs/schemas/artifact-spec-decision.md template/docs/schemas/artifact-spec-decision.md +# 修正前:13 行差異(本任務新增之 Reversibility & Blast Radius 區段僅在 root) +$ cp docs/schemas/artifact-spec-decision.md template/docs/schemas/artifact-spec-decision.md +$ diff docs/schemas/artifact-spec-decision.md template/docs/schemas/artifact-spec-decision.md # (no output) + +$ diff artifacts/improvement/RELAXATION_LOG.md template/artifacts/improvement/RELAXATION_LOG.md +# §Rules 段落缺本任務新句(§Cases 段既有 placeholder scaffold,設計上與 root 分歧,不動) +# → template §Rules 段補上同句 + +$ diff README.md template/README.md +$ diff README.zh-TW.md template/README.zh-TW.md +# 發現 template 兩版之 Two-Layer Governance 段自 TASK-1106 起即完全缺漏 governance lenses 段落 +# (TASK-1106 verify AC-7 僅核對 root 版本,未核對 template;此為 TASK-1106 遺留缺口,非本任務造成) +# → template 兩版補上完整 15 個 lens 名稱段落(TASK-1106 原 3 個 + TASK-1108 新 6 個) + +$ python artifacts/scripts/guard_contract_validator.py --root . +[OK] Contract validation passed +$ python artifacts/scripts/guard_contract_validator.py --root . --check-readme +[OK] Contract validation passed +$ python artifacts/scripts/snapshot_manifest.py generate --output .well-known/release-manifest.json +[OK] wrote manifest: 246 entr(y/ies); root c5ca7a4087ff + +# run 6(Post-Sync Amendment 後最終確認跑): +$ python -m pytest artifacts/scripts -q +2037 passed, 2 skipped in 127.89s # 殘骸跑前已不存在(rmdir 回報 No such file or directory),跑後亦未再現 +``` + +### 一致性核對(plan R4) + +6 個新 lens 列之「對應現有機制」欄位與其指向的目標檔內容(decision schema 新區段、subagent_roles.md 新條文、RELAXATION_LOG.md 新句)已於同一輪編輯內完成,字面一致,無懸空引用。 + +## Evidence Refs + +- artifacts/tasks/TASK-1108.task.md +- artifacts/research/TASK-1108.research.md +- artifacts/plans/TASK-1108.plan.md +- artifacts/code/TASK-1108.code.md +- artifacts/test/TASK-1108.test.md +- artifacts/status/TASK-1108.status.json +- artifacts/decisions/TASK-1108.decision.md +- docs/orchestration.md / template/docs/orchestration.md +- docs/subagent_roles.md / template/docs/subagent_roles.md +- docs/sop/rule_lifecycle_audit.md / template/docs/sop/rule_lifecycle_audit.md +- artifacts/improvement/RELAXATION_LOG.md / template/artifacts/improvement/RELAXATION_LOG.md(§Rules 同步;§Cases 既有 placeholder,不動) +- docs/schemas/artifact-spec-decision.md / template/docs/schemas/artifact-spec-decision.md(Post-Sync Amendment 補鏡像) +- README.md / README.zh-TW.md / template/README.md / template/README.zh-TW.md(Post-Sync Amendment 補齊 TASK-1106 起缺漏之 template governance-lenses 段落) +- artifacts/scripts/drills/prompt_regression_cases.json / template 對應 +- .well-known/release-manifest.json + +## Decision Refs + +- artifacts/decisions/TASK-1108.decision.md(SoD 推翻 TASK-1106 裁決、ADR template 不復活、routing override 三項理由;附帶記錄 template README governance-lenses 段落自 TASK-1106 起缺漏之發現) + +## Build Guarantee + +None (no .csproj modified) — docs-spec adapter 純治理文字任務;enforcement 由 validator chain(guard_contract ×2、guard_status、prompt_regression)+ PR-039 pin + bash 語境全套 pytest(2037/2/0,與 TASK-1106 基準一致)承載。變更為 dirty worktree pending commit;待 user-driven commit 後 commit hash 為 final immutable anchor。 + +## TAO Trace + +None — docs-only、Claude 直寫,risk ≤2(純文字變更),lightweight TAO 條件適用(同 TASK-1106 先例)。 + +## Pass Fail Result + +pass + +## Remaining Gaps + +None + +## Recommendation + +接 Closure:(1) 已完成 guard_status_validator write-transition drafted→researched→planned→coding→verifying→done,末態 `[OK] Validation passed`;(2) 待 user commit(建議訊息 `TASK-1108 add: governance lenses — Hyrum / Reversibility & Blast Radius / Separation of Duties / Least Privilege / Gall's Law / Modernized Postel's Law`);(3) memory follow-up(優先度提升):`Documents/Code/.git` 空目錄殘骸本次於 6 次全套 pytest 中 4 次重現,birth timestamp 皆落在該次執行區間內,但兩次目標式隔離跑(`test_guard_status_validator_state.py` 單獨跑 253/253 全過;`test_scaffold_downstream.py`+`test_guard_contract_validator.py` 合跑 107/107 全過)皆未重現,故真正建立者仍**未定位**於全部 ~600+ 測試檔案中的具體哪一個,亦不能排除或確認外部並行程序假說——強烈建議另立一個獨立 task(非 TASK-1108 scope)以二分法(分批跑子集合、逐步縮小範圍)或檔案系統事件追蹤工具定位根因;在根因未定位前,往後每次全套 pytest 前後應比照本次做法先行檢查並記錄,且不應再逕自假設「與外部程序有關」而不予深究;(4) 已修補 TASK-1106 遺留之 template README governance-lenses 段落缺漏(見 §Evidence Post-Sync Amendment 與 decision artifact),提醒未來 closure review 對「EXACT_SYNC_FILES 清單外但慣例同步」之檔案(如 `docs/schemas/*`、`README.md`)應主動直讀核對,不能僅信任 guard_contract_validator 綠燈。 diff --git a/artifacts/verify/TASK-1109.verify.md b/artifacts/verify/TASK-1109.verify.md new file mode 100644 index 0000000..ce3b12e --- /dev/null +++ b/artifacts/verify/TASK-1109.verify.md @@ -0,0 +1,199 @@ +# Verification: TASK-1109 + +## Metadata +- Task ID: TASK-1109 +- Artifact Type: verify +- Owner: Claude +- Status: pass +- Last Updated: 2026-07-10T17:10:00+08:00 + +## Verification Summary + +本任務在 TASK-1108 落地的 15 視角 Governance Lenses 表之上,新增 **Lucas Critique** 為第 16 個治理視角,並把 **Campbell's Law** 之操作性規則併入既有 Goodhart's Law 列(不新增獨立 lens、不動 TASK-1106 之「明確拒絕:Campbell's Law」PR-038-pinned 字面),理由與使用者裁決來源記於 `artifacts/decisions/TASK-1109.decision.md`。`docs/schemas/artifact-spec-decision.md` 新增兩個條件式可選區段(`## Metrics Policy`、`## Policy Regime`),比照 TASK-1108 之 `## Reversibility & Blast Radius` 先例。所有新增皆為既有檔案內之文字增量,無新分層、無強制 schema 欄位、無 validator 自動化邏輯、無 CI gate、無 policy engine。吸取 TASK-1108 之 Post-Sync Amendment 教訓,本次 EXACT_SYNC 正式成員(3 組)與慣例同步之非正式成員(decision schema、RELAXATION_LOG §Rules、README 兩版)於同一輪同批完成 template 鏡像,未留待驗收階段才補。13 AC 全 verified。 + +## Acceptance Criteria Checklist + +- [x] AC-1: + - criterion: lifecycle artifacts 齊且符合 schema;plan premortem ≥3 條 ≥1 blocking + - method: ls + guard_status_validator write-transition 鏈 + - evidence: task/research/plan/code/test/verify/status/decision 8 檔皆存在;plan R1-R5(5 條,R1/R2/R5 blocking,超過最低要求) + - result: verified + +- [x] AC-2: + - criterion: Goodhart's Law 列更新含 Campbell's Law 併入註記與高風險指標規則;`Goodhart's Law` 子字串仍存在 + - method: grep + - evidence: `docs/orchestration.md` Goodhart's Law 列名稱欄含「亦涵蓋 Campbell's Law 1979...TASK-1109 併入」;所管問題欄含「高風險指標...不得作為安全/價值/品質之直接證明」;`Goodhart's Law` 子字串(PR-038 依賴)確認存在 + - result: verified + +- [x] AC-3: + - criterion: 新增 Lucas Critique 列,所管問題/對應現有機制/文件落點皆指向真實存在或本次同批新增之機制 + - method: grep + 人工核對 + - evidence: Lucas Critique 列已插入 Modernized Postel's Law 列後;對應機制引用 RELAXATION_LOG 既有格式、rule lifecycle audit 既有 relax/retire 裁決、本次同批新增之 `## Policy Regime` 區段 + - result: verified + +- [x] AC-4: + - criterion: Campbell's Law 拒絕段後新增操作化附註;原段落既有文字逐字不變 + - method: grep + diff 核對既有句 + - evidence: 「Campbell's Law 操作化附註(TASK-1109)」段落已加於既有拒絕段後;`diff` 確認「Campbell's Law(Campbell 1979)與 Goodhart's Law 同構...明確不採 Campbell's Law...任何後續 task 不得引此決策為 routing override 範本」逐字未動 + - result: verified + +- [x] AC-5: + - criterion: rule_lifecycle_audit.md Step 1 新增 Campbell's Law 操作化句;既有句字面不變;總行數 ≤150 + - method: grep + 行數統計 + - evidence: Step 1 新增一句含「不得以原始指標值...直接作為安全/價值/品質之證明」「不得獎勵人為製造之 guard 觸發、警告壓制、淺層測試覆蓋,或僅改善指標...」;既有 5 句(含 TASK-1108 之候選訊號句、TASK-1104 之 deviance 條款所在段)未變動;檔案含尾端空行共 55 行(≤150) + - result: verified + +- [x] AC-6: + - criterion: RELAXATION_LOG.md §Rules 新增 Lucas Critique 句 + - method: grep + - evidence: §Rules 新增一句,明文「治理規則之建制變動...該案例前後之 telemetry 不得直接比較,須附加正規化說明或『不可比較』但書」 + - result: verified + +- [x] AC-7: + - criterion: decision schema 新增 `## Metrics Policy` 與 `## Policy Regime` 兩區段,各含規則段落明示可選/無自動強制/消費者 + - method: grep + 人工核對 + advisor 覆核 + - evidence: `docs/schemas/artifact-spec-decision.md` 於 `## Reversibility & Blast Radius` 規則段落後新增兩區段(Metrics Policy:4 欄位;Policy Regime:7 欄位);規則段落含「本區段為可選」「無自動 validator 強制」「唯一既有消費者為後續審查者與週期性 architect review」三句明文,並含 Metric Interpretation 不得留空、Comparable To Previous: false 之預設安全假設說明;advisor 覆核發現 `Campbell Risk: unknown` 原缺與 `## Reversibility & Blast Radius` 之 `unknown` 同等「不得等同安全」明文(見 Post-Verify Amendment),已補上並同步 template、重跑驗證鏈(manifest root `12d3ada8368e`、pytest 2037/2/0) + - result: verified + +- [x] AC-8: + - criterion: README 兩版新增「Lucas Critique」(不新增 Campbell's Law);template 兩版同步 + - method: 人工核對四檔 + - evidence: `README.md:199`、`README.zh-TW.md:199`、`template/README.md`、`template/README.zh-TW.md` 皆於既有 15 名詞後附加「Lucas Critique」;四檔皆未出現「Campbell's Law」作為獨立名詞列於名單句中 + - result: verified + +- [x] AC-9: + - criterion: EXACT_SYNC 逐對全等;慣例同步檔亦主動同步;contract validator 兩式 [OK] + - method: diff + guard_contract_validator.py + - evidence: 3 組正式 EXACT_SYNC 成員(orchestration.md、rule_lifecycle_audit.md、prompt_regression_cases.json)root/template `diff` 零輸出;3 組慣例同步之非正式成員(artifact-spec-decision.md 全檔 byte-identical、RELAXATION_LOG.md §Rules 段一致而 §Cases 維持既有 placeholder 分歧、README 兩版之 lens 名單句一致)皆已於本輪同批完成,非留待驗收階段才發現;`--root .` 與 `--root . --check-readme` 皆 `[OK] Contract validation passed` + - result: verified + +- [x] AC-10: + - criterion: prompt_regression 全 PASS 含新 PR-040;PR-038/PR-039 仍全 pass + - method: 命令跑列 + - evidence: PR-001..PR-040 全 pass,Failure Details None;PR-040 兩條 assertion(orchestration.md 之 Lucas Critique + Campbell fold-in 字面 + 既有拒絕字面;decision schema 之 Metrics Policy/Policy Regime 區段標題);PR-038(Goodhart's Law/Normalization of Deviance/Swiss Cheese Model/明確不採 Campbell's Law)與 PR-039(TASK-1108 六視角 + Policy Engine 拒絕)皆未受本次編輯擾動,繼續 pass + - result: verified + +- [x] AC-11: + - criterion: bash 語境 pytest 0 failed;跑前後檢查環境殘骸;manifest 過期時 regen + - method: 全跑 + manifest generate + - evidence: manifest 以 `snapshot_manifest.py generate --output .well-known/release-manifest.json` regen 至 root `a195da47325b`(246 entries);跑前 `Documents/Code/.git` 殘骸不存在(延續 TASK-1108 觀察義務,本次未重現);`python -m pytest artifacts/scripts -q` 達 `2037 passed, 2 skipped, 0 failed`,與 TASK-1108 verify 記錄之基準數字完全一致,證明零回歸;跑後殘骸仍未出現 + - result: verified + +- [x] AC-12: + - criterion: guard_status_validator 各階段 [OK] + - method: 逐轉移跑列 + - evidence: drafted→researched→planned→coding→verifying→done 各轉移皆 `[OK] Validation passed`(見 §Evidence) + - result: verified + +- [x] AC-13: + - criterion: decision artifact 記錄 Campbell's Law 併入理由與使用者裁決來源 + - method: 人工核對 + - evidence: `artifacts/decisions/TASK-1109.decision.md` §Reasoning 明確引用使用者 AskUserQuestion 選擇與 mission hard constraint,並區辨本案與 TASK-1108 SoD 案之裁決強度差異 + - result: verified + +## Overall Maturity + +mvp + +## Deferred Items + +None + +## Evidence + +### Validator Chain + +``` +$ python artifacts/scripts/guard_contract_validator.py --root . +[OK] Contract validation passed +$ python artifacts/scripts/guard_contract_validator.py --root . --check-readme +[OK] Contract validation passed +$ python artifacts/scripts/prompt_regression_validator.py --root . +(PR-001..PR-040 all pass) / ## Failure Details: None +$ python artifacts/scripts/snapshot_manifest.py generate --output .well-known/release-manifest.json +[OK] wrote manifest: 246 entr(y/ies); root a195da47325b +# Post-Verify Amendment(advisor 覆核後追加 unknown 明文)觸發二次 regen: +$ python artifacts/scripts/snapshot_manifest.py generate --output .well-known/release-manifest.json +[OK] wrote manifest: 246 entr(y/ies); root 12d3ada8368e # 最終有效 root +``` + +### EXACT_SYNC / 慣例同步 Diff(7 組觸及檔) + +``` +$ diff docs/orchestration.md template/docs/orchestration.md # (no output) +$ diff docs/sop/rule_lifecycle_audit.md template/docs/sop/rule_lifecycle_audit.md # (no output) +$ diff artifacts/scripts/drills/prompt_regression_cases.json template/artifacts/scripts/drills/prompt_regression_cases.json # (no output) +$ diff docs/schemas/artifact-spec-decision.md template/docs/schemas/artifact-spec-decision.md # (no output) +$ diff README.md template/README.md # only pre-existing source/downstream framing diffs (unrelated to this task) +$ diff README.zh-TW.md template/README.zh-TW.md # only pre-existing source/downstream framing diffs (unrelated to this task) +# RELAXATION_LOG.md §Rules 段一致(§Cases 段既有 placeholder,設計上分歧,非本任務 scope) +``` + +### Pytest(bash 語境,per project-facts 慣例) + +``` +$ [ -e "C:/Users/arcobaleno/Documents/Code/.git" ] && echo present || echo absent +absent +$ python -m pytest artifacts/scripts -q +2037 passed, 2 skipped in 135.79s +$ [ -e "C:/Users/arcobaleno/Documents/Code/.git" ] && echo present || echo absent +absent +``` + +一次全跑即乾淨(0 failed),與 TASK-1108 之持續觀察項(`Documents/Code/.git` 殘骸不定期再現、根因未定位)保持一致的處置:本次未出現,不代表根因已解,仍列 TASK-1108 之 follow-up 為未結案觀察項,非本任務 scope。 + +### 一致性核對(plan R4) + +Lucas Critique 列之「對應現有機制」欄位與其指向的 `## Policy Regime` 區段內容已於同一輪編輯內完成,字面呼應一致,無懸空引用。 + +### PR-038/PR-039 未受擾動核對(plan R1) + +``` +$ grep -c "Goodhart's Law" docs/orchestration.md # >=1(PR-038 依賴) +$ grep -c "明確不採 Campbell's Law" docs/orchestration.md # 1(PR-038 依賴,逐字未動) +$ grep -c "Normalization of Deviance" docs/orchestration.md +$ grep -c "Swiss Cheese Model" docs/orchestration.md +$ grep -c "明確拒絕:獨立 Policy Engine" docs/orchestration.md # PR-039 依賴 +``` +以上皆由 prompt_regression_validator 之 PR-038/PR-039 assertion 自動核驗,全數 pass(見 §Validator Chain)。 + +## Evidence Refs + +- artifacts/tasks/TASK-1109.task.md +- artifacts/research/TASK-1109.research.md +- artifacts/plans/TASK-1109.plan.md +- artifacts/code/TASK-1109.code.md +- artifacts/test/TASK-1109.test.md +- artifacts/status/TASK-1109.status.json +- artifacts/decisions/TASK-1109.decision.md +- docs/orchestration.md / template/docs/orchestration.md +- docs/sop/rule_lifecycle_audit.md / template/docs/sop/rule_lifecycle_audit.md +- docs/schemas/artifact-spec-decision.md / template/docs/schemas/artifact-spec-decision.md +- artifacts/improvement/RELAXATION_LOG.md / template/artifacts/improvement/RELAXATION_LOG.md +- README.md / README.zh-TW.md / template/README.md / template/README.zh-TW.md +- artifacts/scripts/drills/prompt_regression_cases.json / template 對應 +- .well-known/release-manifest.json + +## Decision Refs + +- artifacts/decisions/TASK-1109.decision.md(Campbell's Law 併入 Goodhart's Law 而非新增獨立 lens 之理由與使用者裁決來源) + +## Build Guarantee + +None (no .csproj modified) — docs-spec adapter 純治理文字任務;enforcement 由 validator chain(guard_contract ×2、guard_status、prompt_regression)+ PR-040 pin + bash 語境全套 pytest(2037/2/0,與 TASK-1108 基準一致)承載。變更為 dirty worktree pending commit;待 user-driven commit 後 commit hash 為 final immutable anchor。 + +## TAO Trace + +None — docs-only、Claude 直寫,risk ≤2,lightweight TAO 條件適用。 + +## Pass Fail Result + +pass + +## Remaining Gaps + +None + +## Recommendation + +接 Closure:(1) 完成 guard_status_validator write-transition 至 `verifying` → `done`;(2) 待 user commit(建議訊息 `TASK-1109 add: governance lenses — Lucas Critique + Campbell's Law fold-in to Goodhart's Law`);(3) memory follow-up:延續 TASK-1108 之 `Documents/Code/.git` 殘骸根因未定位 follow-up,本次未重現不代表已解,仍需另立獨立 task 追蹤;(4) Governance Lenses 表現已達 16 視角,若未來仍有新增提案,建議先查本檔與 TASK-1108/1106 decision artifacts 之既有裁決,避免重複評估或誤判衝突強度。 diff --git a/artifacts/verify/TASK-1112.verify.md b/artifacts/verify/TASK-1112.verify.md new file mode 100644 index 0000000..1f8435d --- /dev/null +++ b/artifacts/verify/TASK-1112.verify.md @@ -0,0 +1,84 @@ +# Verification: TASK-1112 + +## Metadata +- Task ID: TASK-1112 +- Artifact Type: verify +- Owner: Claude +- Status: pass +- Last Updated: 2026-07-17T12:25:00+08:00 + +## Verification Summary + +驗收 TASK-1112 對 TASK-1107 improvement artifact 兩條 Preventive Action 之 SOP 落地。純文字追加,docs-only、Claude 直寫(同 TASK-1106 routing override 先例)。所有驗證命令由 Claude 直接執行。 + +## Acceptance Criteria Checklist + +- criterion: AC-1 — `docs/sop/dispatch_implementation.md` 新增「Dispatch 逾時重派紀律(TASK-1112)」條文 + - method: 人工核對文字內容與 improvement artifact §5 原文語意一致 + - evidence: `docs/sop/dispatch_implementation.md` 已新增該小節,緊接既有「### Fallback tier 產出之驗收紀律(TASK-1106)」之後 + - result: verified +- criterion: AC-2 — `docs/dispatch_prompt_discipline.md` 新增「Dispatch Wrapper Log 重導向路徑紀律(TASK-1112)」條文 + - method: 同上 + - evidence: 已新增該小節,插於「## 6. Cross-references」之前 + - result: verified +- criterion: AC-3 — 兩份目標檔 root/template SHA-256 逐對全等;`guard_contract_validator.py --root .` `[OK]` + - method: `diff` 直接比對;執行 validator + - evidence: `diff docs/sop/dispatch_implementation.md template/docs/sop/dispatch_implementation.md` 與 `diff docs/dispatch_prompt_discipline.md template/docs/dispatch_prompt_discipline.md` 皆無輸出;`python artifacts/scripts/guard_contract_validator.py --root .` -> `[OK] Contract validation passed` + - result: verified +- criterion: AC-4 — `prompt_regression_validator.py --root .` 全 PASS + - method: 直接執行 + - evidence: 全部 40 條 PR-* pin(含 PR-001 至 PR-040)皆 `pass`,Failure Details `None` + - result: verified +- criterion: AC-5 — `python -m pytest artifacts/scripts -q` 無新增 regression(對照 TASK-1107 收尾基線 `5 failed, 2034 passed, 2 skipped`) + - method: 直接重跑並對照 + - evidence: 見下方 `## Build Guarantee` + - result: verified + +## Overall Maturity + +mvp + +## Deferred Items + +None + +## Evidence + +- `artifacts/code/TASK-1112.code.md` +- `artifacts/improvement/TASK-1107.improvement.md`(規則原文來源) +- `artifacts/research/TASK-1112.research.md` + +## Evidence Refs + +- artifacts/code/TASK-1112.code.md +- artifacts/research/TASK-1112.research.md +- artifacts/plans/TASK-1112.plan.md + +## Decision Refs + +None + +## Build Guarantee + +非 .NET 任務(純 Markdown 文件變更)。 + +- `python artifacts/scripts/guard_contract_validator.py --root .` -> `[OK] Contract validation passed` +- `python artifacts/scripts/prompt_regression_validator.py --root .` -> 全 PASS(PR-001..PR-040,Failure Details None) +- `python -m pytest artifacts/scripts -q` -> `5 failed, 2034 passed, 2 skipped`(與 TASK-1107 收尾基線一致,無新增 regression;5 項為既有 git-root baseline exception,見 `artifacts/decisions/TASK-1107.decision.md`) +- Git commit:`git rev-parse HEAD` -> 見本任務最終 commit(本檔提交後由後續 chore commit 記錄,同 TASK-1107 慣例) + +## TAO Trace + +None(Claude 直接執行,非 dispatch)。 + +## Pass Fail Result + +pass + +## Remaining Gaps + +None + +## Recommendation + +標記 done。 diff --git a/docs/dispatch_prompt_discipline.md b/docs/dispatch_prompt_discipline.md index 41fd41d..48163bb 100644 --- a/docs/dispatch_prompt_discipline.md +++ b/docs/dispatch_prompt_discipline.md @@ -92,6 +92,12 @@ grep -rE "prompt_size=[0-9]+|prompt[^a-z]*= ?[0-9]+ chars" artifacts/ Wrapper-side enforcement(自 TASK-1067):三 wrapper(`Invoke-CodexAgent` / `Invoke-GeminiAgent` / `Invoke-CodexReview`)於 prompt size 超過閾值時自動 warn 或 reject(dispatch wrapper warn @ 500 / reject @ 5000 chars,exit 4;review wrapper warn @ 100000 / reject @ 200000 chars,diff-driven 故較寬鬆);caller 可傳 `-SuppressSizeWarn` 暫時繞過。PR-032 anchor 守 wrapper 字面之 bounds 設定。 +## Dispatch Wrapper Log 重導向路徑紀律(TASK-1112) + +Caller(Claude)若需要將 `Invoke-CodexAgent.ps1` / `Invoke-GeminiAgent.ps1` 之 stdout/stderr 重導向到檔案以供背景監看(例如 `run_in_background: true` 之 dispatch),目的路徑**必須在 repo 工作樹之外**(session scratchpad 目錄或 `%TEMP%`),**不得寫入 repo 目錄內**。 + +原因:wrapper 之 post-dispatch write-scope guard(`-AutoRestore` 啟用時)以 `git status` 掃描 dispatch 期間新增的檔案並判定是否為 sub-agent 越界寫入;若 caller 自己把重導向 log 檔放在 repo 目錄內,該檔會被同一套掃描誤判為 sub-agent 寫入,觸發不必要的 restore/`git stash pop` 衝突。出處:TASK-1107——Claude 以 PowerShell `*>` 將 wrapper 輸出導到 repo 根目錄下的 `.codex-dispatch-TASK-1107.log`,遭 guard 誤刪並引發 stash pop 衝突,wrapper `[FATAL]` exit 3(見 `artifacts/improvement/TASK-1107.improvement.md`)。 + ## 6. Cross-references - `memory/feedback_dispatch_prompt_discipline.md`:本規範之 origin memory;4 條 how-to-apply 細則之原文出處。 diff --git a/docs/orchestration-workflow.md b/docs/orchestration-workflow.md index e448970..e7491e5 100644 --- a/docs/orchestration-workflow.md +++ b/docs/orchestration-workflow.md @@ -123,7 +123,7 @@ Codex CLI 不得: - 若該任務曾經 `blocked`,仍須保留 Gate E / PDCA 所需欄位 4. 若有長期可重用 lesson,Claude 可派 Gemini 以 Memory Bank Curator 模式產生 `Remember Capture` draft;Gemini 只做 read-only 分類、查重與來源驗證。 5. 若 draft 需要寫入 `.github/memory-bank/`,由 Claude/Codex 在明確 write scope 下修改,並由 Claude 最終驗收。 -6. 更新 `artifacts/improvement/PROCESS_LEDGER.md`,每個 task 只寫一行摘要,作為冷啟動入口。 +6. 更新 `artifacts/improvement/PROCESS_LEDGER.md`,每個 task 只寫一行摘要,作為冷啟動入口。**凡於 closure 產出 improvement artifact(Gate E 或 retrospective)之 task 必記一條**(見該檔頭部維護規則);純 lightweight/docs 小任務可免。 7. 明確標記: - 已完成 - 未完成 diff --git a/docs/orchestration.md b/docs/orchestration.md index 4334e43..025c9a5 100644 --- a/docs/orchestration.md +++ b/docs/orchestration.md @@ -158,6 +158,16 @@ Routing matrix: | **TAO/ReAct**(單步推理) | 任務內 subagent 之想 / 做 / 觀 | TASK-1000 執行層 + agentic_execution_layer.md | [docs/agentic_execution_layer.md](agentic_execution_layer.md) | | **Double-Loop Learning**(Argyris 1977) | 失敗後改規則(非僅改 code) | improvement artifact §5.9 之 Why Not Prevented + System-Level Preventive Action | [docs/schemas/artifact-spec-improvement.md](schemas/artifact-spec-improvement.md) | | **SECI**(Nonaka 1994) | 碎片經驗 → 系統指引 | Memory Bank Curator + Architecture Synthesizer(每 N=10 任務觸發) | [GEMINI.md](../GEMINI.md)、[`.github/prompts/remember-capture.prompt.md`](../.github/prompts/remember-capture.prompt.md) | +| **Goodhart's Law**(Goodhart 1975,TASK-1106 顯式化;亦涵蓋 Campbell's Law 1979 之經濟學同構表述,TASK-1109 併入) | 指標成為優化目標即失真(validator schema-pleasing);高風險指標(firing_count、block_count、pass_rate、coverage 等)不得作為安全/價值/品質之直接證明 | RELAXATION_LOG 累積 ≥ 3 案例 → architect review;決策涉及高風險指標時,decision schema 之條件式可選 `## Metrics Policy` 區段記錄 campbell_risk/gaming_vectors | [artifacts/improvement/RELAXATION_LOG.md](../artifacts/improvement/RELAXATION_LOG.md)、[docs/schemas/artifact-spec-decision.md](schemas/artifact-spec-decision.md) | +| **Normalization of Deviance**(Vaughan 1996,TASK-1106 顯式化) | 偏差被反覆接受而例行化(detect-and-accept 無限延續) | rule lifecycle audit 之同型違規連續接受 3 次強制裁決條款 | [docs/sop/rule_lifecycle_audit.md](sop/rule_lifecycle_audit.md) | +| **Swiss Cheese Model**(Reason 1990,TASK-1106 顯式化) | 單一事故穿透多層防禦之路徑分析 | guard 疊層 + improvement artifact `Why Not Prevented` 之逐層穿透敘述 | [.github/memory-bank/workflow-gates.md](../.github/memory-bank/workflow-gates.md) | +| **Hyrum's Law**(Hyrum Wright,相容性視角,TASK-1108 顯式化) | 已發布之可觀察行為(檔名、路徑、欄位順序、報告標題、exit code、預設值、log/警告/錯誤文字)一旦被使用即成隱性依賴,即使未正式承諾;unknown consumer ≠ no consumer | AGENTS.md 精確字串條款(不得更動 agent/validator/腳本依賴之精確字串)+ `prompt_regression_cases.json` 之 PR-* 字面 pin + `guard_contract_validator.py` 之 EXACT_SYNC byte-identical 校驗 | [AGENTS.md](../AGENTS.md)、[artifacts/scripts/drills/prompt_regression_cases.json](../artifacts/scripts/drills/prompt_regression_cases.json) | +| **Reversibility & Blast Radius**(風險工程慣例,TASK-1108 顯式化) | 修改 guard/schema/report/CI gate/預設值/可觀察輸出前,須先分類變更之可逆性與影響半徑 | decision artifact 之條件式可選 `## Reversibility & Blast Radius` 區段(比照既有 `## Guard Exception` 之條件式可選 block 慣例) | [docs/schemas/artifact-spec-decision.md](schemas/artifact-spec-decision.md) | +| **Separation of Duties**(治理慣例,TASK-1108 顯式化;TASK-1106 曾裁「隱性覆蓋不掛牌」,因具體規則落地需求而推翻) | 高風險/AI 產生之變更(涉及 guard、schema、CI gate、相容契約)之 author 不得為唯一審查者 | `docs/subagent_roles.md` §1.3 single-writer 規則 + Council Reviewer(3 個獨立 Codex model 產出獨立 review notes)+ premortem §12 獨立質疑(撰寫 plan 者不得自問自答) | [docs/subagent_roles.md §1.3](subagent_roles.md)、[docs/premortem_rules.md §12](premortem_rules.md) | +| **Least Privilege**(Saltzer & Schroeder 1975,TASK-1108 顯式化) | tools/scripts/CI jobs/AI agent 應被限制在完成任務所需之最小權限;破壞性操作需顯式升級 | `docs/subagent_roles.md` 之 agent 讀寫權限範圍(Claude 不自寫 code、Gemini read-only research、Codex 限 implementation scope)+ wrapper write-scope 偵測(`scope_guard.py`)+ decision artifact `Override_Reason`(`guard_status_validator.py --override --override-approver`) | [docs/subagent_roles.md §1.3](subagent_roles.md)、[docs/schemas/artifact-spec-decision.md](schemas/artifact-spec-decision.md) | +| **Gall's Law**(John Gall 1975,TASK-1108 顯式化) | 複雜可行系統必由簡單可行系統演化而來;避免 v0 過早長出 policy engine 等重機制 | Governance Lenses 表自身之表頭紀律「不另立分層、不另建 schema、不另設階段」+ rule lifecycle audit 之 Occam Pass | 本章(表頭紀律)、[docs/sop/rule_lifecycle_audit.md](sop/rule_lifecycle_audit.md) | +| **Modernized Postel's Law**(Postel 1980,經 Hyrum's Law 修正之版本,TASK-1108 顯式化) | 對外輸出應穩定/保守/可預期;legacy input 容忍須顯性、有警告、有 deprecation 追蹤;內部 schema 應嚴格 | EXACT_SYNC_FILES byte-identical 輸出穩定機制 + RELAXATION_LOG 之顯性放寬紀錄(含 before/after/trigger task/provenance,而非靜默改變)+ artifact schema 必填欄位之嚴格性 | [artifacts/improvement/RELAXATION_LOG.md](../artifacts/improvement/RELAXATION_LOG.md)、[docs/artifact_schema.md](artifact_schema.md) | +| **Lucas Critique**(Lucas 1976,政策回饋/建制變動視角,TASK-1109 顯式化) | 治理規則變更後(CI gate、guard 定義、telemetry schema、model 角色、escalation 規則、pass/fail 門檻、report 格式、prompt 政策),行為會調適,舊 baseline 不可跨建制直接比較 | RELAXATION_LOG 之 Before/After/Trigger Task 記錄格式 + rule lifecycle audit 之 `relax`/`retire` 裁決 + decision artifact 條件式可選 `## Policy Regime` 區段(本次新增) | [artifacts/improvement/RELAXATION_LOG.md](../artifacts/improvement/RELAXATION_LOG.md)、[docs/sop/rule_lifecycle_audit.md](sop/rule_lifecycle_audit.md)、[docs/schemas/artifact-spec-decision.md](schemas/artifact-spec-decision.md) | **明確拒絕:OODA** @@ -171,6 +181,16 @@ OODA(Boyd, Observe-Orient-Decide-Act)與 TAO/ReAct(Yao 2022, Thought-Actio 二者並存將造成 schema 重複、辭彙負擔、與 ReAct 之 LLM agent 文獻主流脫鉤。本框架**已採 TAO/ReAct,明確不採 OODA**;任何後續 task 不得引此決策為 routing override 範本,亦不得試圖以 OODA 取代 TAO(兩者不可並存於本框架)。 +**明確拒絕:Campbell's Law** + +Campbell's Law(Campbell 1979)與 Goodhart's Law 同構——同為「量化指標被用於治理即遭腐化」,僅為社會科學與經濟學之不同表述。依 OODA 先例(同構名詞不並存):本框架**已採 Goodhart's Law,明確不採 Campbell's Law**;任何後續 task 不得引此決策為 routing override 範本。 + +**Campbell's Law 操作化附註(TASK-1109)**:上述拒絕僅拒絕「另立一個與 Goodhart's Law 重複之獨立視角」,不推翻此拒絕宣告,亦不拒絕吸收 Campbell's Law 文獻中對「高風險指標」的具體操作規則。這些規則已併入 Goodhart's Law 列(見上表):不得以原始指標值(如 firing_count、pass_rate、coverage)直接證明安全/價值/品質;高風險指標須標記 campbell_risk;須記錄 plausible gaming vectors;不得獎勵人為製造之 guard 觸發、警告壓制、淺層測試覆蓋或僅改善指標之變更。可選 metadata(campbell_risk / high_stakes_metric / gaming_vectors / metric_interpretation)之 schema 見 `docs/schemas/artifact-spec-decision.md` 之 `## Metrics Policy` 條件式可選區段。 + +**明確拒絕:獨立 Policy Engine(OPA / Rego / CEL / 資料庫式規則引擎)** + +Gall's Law 之直接應用:本框架尚無可觀察之真實需求證明需要獨立 policy engine——guard 邏輯現以 Python validator 直接表達已足夠,且無使用資料顯示現有機制不足。在無使用資料前引入獨立 policy engine 即為過早複雜化,本框架**明確不採**,除非既有 repo 已依賴此類工具(現況:無);任何後續 task 不得引此決策為 routing override 範本。 + ## 3. Workflow 與 Gate 細節索引 §3 之後的流程內容已拆分至 [docs/orchestration-workflow.md](orchestration-workflow.md): diff --git a/docs/premortem_rules.md b/docs/premortem_rules.md index d085c9c..f1c8237 100644 --- a/docs/premortem_rules.md +++ b/docs/premortem_rules.md @@ -198,3 +198,46 @@ Premortem 的目的不是讓人安心,而是讓錯誤提前發生在紙上, premortem 的價值不在於悲觀,而在於把失敗變成可命名、可偵測、可止血的對象。 如果一條風險不能讓下一位代理知道「怎麼發現、怎麼處理」,那它就不算合格。 + +## 12. 獨立 Premortem 質疑(高風險 plan) + +### 背景 + +§1-§11 的 premortem 規則由撰寫 plan 的同一個 agent 自行填寫、自行判斷是否合格;`guard_status_validator.py` 依 §4 的 P1-P8 只檢查風險條目的格式與用語是否具體,不檢查風險判斷本身是否站得住腳。這代表撰寫者的盲點,在 R1-R4 本身完全沒有被獨立檢查過。 + +### 適用範圍 + +以下任一條件命中時,於 `planned → coding` 前必須完成一次獨立質疑: + +- 涉及安全性修補(security fix) +- 涉及 upstream PR +- 涉及多模組或跨 repo 修改 +- 涉及不熟悉框架、版本或環境 + +(刻意不納入 §1 的「無法 100% 確認變更影響範圍」——該條件過於主觀,套用在此處會讓幾乎所有任務都命中,稀釋這道 gate 的訊號。) + +### 獨立性要求 + +- 執行質疑者不得與撰寫 R1-R4 的 agent 共用同一個對話 context/session;撰寫 plan 的 agent 不可在同一輪回應內自問自答完成本項質疑。 +- 可透過 Agent tool 開新 subagent,或派給另一個 CLI(Gemini / Codex),只要是脫離原 plan 撰寫 context 的獨立呼叫即可。 +- 若任務規模過小、找不到可用的獨立 agent,必須在 plan 的 `## Risks` 中明記原因並回報 blocked,不得逕自略過。 + +### 質疑內容(最小集合) + +- 逐條檢查既有 R1-R4:Detection 描述的偵測方式,在實際情境下是否真的會被觸發? +- 是否有被漏掉的失敗模式(既有 R1-R4 都沒有覆蓋到的風險)? +- 若發現遺漏或 Detection 不成立,必須具體指出並建議新增或修正的風險條目,沿用本文件 §3-§4 的欄位與品質規則;§9 禁止語句清單同樣適用於本項輸出,不可用空話回覆。 + +### 輸出位置 + +- 附掛在 plan artifact 的 `## Risks` 區段下,新增 `### Independent Premortem Challenge` 子區段,逐條回覆對應 R 編號的判斷(每條至少一句具體理由)。 +- 若質疑結果導致風險判斷需要重大修改(例如新增 blocking risk 或推翻既有 mitigation),改寫 decision artifact 說明分歧與最終裁決。 + +### 與既有機制的分工邊界 + +- 本項質疑作用在 **plan 階段**(尚無 code diff);Council Reviewer(`/codex-review`,見 `docs/subagent_roles.md` §5.1.3)作用在 **code diff 已產出之後**。兩者觸發時機不重疊,不互相取代。 +- 本項質疑是逐 task 觸發(符合條件即做一次);RACI Auditor / Architecture Synthesizer 是週期性(每 10 個 PROCESS_LEDGER 或 Sprint Review)批次審查,兩者頻率與粒度不同。 + +### 現況 + +本節僅定義慣例與最低要求,不由 `guard_status_validator.py` 自動強制(無新增 automated guard)。是否日後加上自動化檢查(例如偵測 plan 是否缺少 `### Independent Premortem Challenge` 子區段),留待後續視實際執行成本再評估,避免尚未有使用資料就過早鎖死強制規則。 diff --git a/docs/raci-matrix.md b/docs/raci-matrix.md index b101791..936f894 100644 --- a/docs/raci-matrix.md +++ b/docs/raci-matrix.md @@ -1,21 +1,10 @@ # RACI Matrix -> 本檔由 `docs/subagent_roles.md` §2 拆分而來;RACI 與 agent capability 矩陣集中於此。 +> 本檔之 §2 角色總表已回歸單一真源 [docs/subagent_roles.md](subagent_roles.md) §2;本檔僅保留下列 §2.1 TAO Trace 必要程度表(此檔獨有)。 ## 2. 角色總表 -| 角色 | 類型 | R (主執行) | A (最終問責) | C (諮詢) | I (通知) | 主要輸入 | 主要輸出 | -|---|---|---|---|---|---|---|---| -| Claude Code | 主控代理 | task / plan / decision / status | task / plan / verify / decision / status / improvement | research / code / verify | -- | 全部合法 artifacts | task, plan, verify, decision, status | -| Gemini CLI | 研究 + memory curator | research / Tavily Cache / Remember Capture draft | -- (Claude A) | task | closure events | task, 研究相關文件, memory-bank 讀取範圍 | research, Tavily Cache draft, Remember Capture draft | -| Codex CLI | 實作主代理 | code | -- (Claude A) | plan / research | -- | task, research, plan | code | -| Implementer | Codex subagent | code (實檔修改) | -- (Codex/Claude A) | plan | -- | task, plan, research | code | -| Tester | Codex subagent | test | -- (Codex/Claude A) | code | -- | task, plan, code | test | -| Verifier | Codex subagent 或 Claude 控制下代理 | verify | -- (Claude A) | code / test | -- | task, code, test | verify | -| Reviewer | Codex subagent | review notes | -- (Claude A) | plan / code | -- | task, plan, code | review 摘要或 decision 建議 | -| Codex Reviewer (Council) | Codex subagent (Council) | review notes (3 model votes) | Claude(triage) | plan / code / git diff | -- | git diff | `artifacts/reviews/-.md` | - -註:若你想維持最小集合,可先不建立獨立 review artifact,而把 reviewer 結果納入 decision log 或 verify artifact 的 evidence 區段。 +RACI 與 agent capability 矩陣之單一真源為 [docs/subagent_roles.md](subagent_roles.md) §2「角色總表」(hybrid-sync guard 綁定該檔 ↔ `workflow_constants.RACI_MATRIX`)。本檔不再重複該表。 ### 2.1 TAO Trace 必要程度(執行層) diff --git a/docs/red_team_backlog.md b/docs/red_team_backlog.md index 04c5efe..d033294 100644 --- a/docs/red_team_backlog.md +++ b/docs/red_team_backlog.md @@ -5,8 +5,10 @@ ## BKL-001 歷史 diff 重建仍未完全自動化 - 目前狀態:`guard_status_validator.py` 現在除了 dirty worktree 的 git-backed changed-files 比對外,也支援以 pinned `Base Commit` / `Head Commit`、`Changed Files Snapshot` 與 `Snapshot SHA256` 重放 clean task 的 `commit-range` historical diff;若 local git replay 失敗且附有合法 `Archive Path` / `Archive SHA256`,也可改走 archive fallback;若 task 記錄 `Evidence Type: github-pr`,則可透過 GitHub PR files API 重建 changed files。 +- 分流定案(2026-07-02):Branch A 是 dirty-worktree guard;標準 clean CI 不觸發 Branch A 屬設計分流,不是 dead-path bug。證據鏈:`TASK-954` 明文將 commit-range / historical diff reconstruction 列為 Out of Scope;`TASK-955` Background 接續定義 clean worktree task 需依 code artifact 的 historical diff evidence;RT-013 / RT-014 分別覆蓋 dirty worktree 與 pinned historical diff;`guard_status_validator.py` 與 README / schema 文件皆以 dirty worktree versus clean-task replay 描述同一分流。 - 殘餘風險:若 task 沒有記錄 diff evidence、沒有準備 archive file、需要 GitHub 以外的 provider、遭遇 provider auth / rate-limit 問題、或 PR files 超過 GitHub endpoint 上限,guard 仍可能無法自動重建歷史 changed files;目前 ref drift 也只會告警,不會直接阻斷。 -- 建議補強:下一輪可加入其他 provider(GitLab / Azure / Bitbucket)、provider response 的長期封存策略、或把特定 ref drift / provider precondition 提升為 policy-driven hard fail。 +- 已裁決(HC-1 A2,2026-07-03):`## Diff Evidence` 選填 policy 經 human 裁決為**範圍限定的 A2**——僅對觸及 guard/EXACT_SYNC 敏感集(`guard_contract_validator.EXACT_SYNC_FILES` ∪ `artifacts/scripts/guard_*.py`、`run_quality_gates.py`、`workflow_constants.py`)之 clean-task closure(transition into `done`)強制提供 `## Diff Evidence`,其餘 clean task 維持選填。實作見 CHG-012(`guard_status_validator.is_sensitive_guard_path` + `validate_artifact_presence` 之 `enforce_clean_diff_evidence` gate,僅前向適用於新 transition,不回溯既有 done 存量;RT-032 覆蓋)。spot-check#1 確認 `github-pr` / archive replay arms KEEP 為此裁決之前提。原 `TASK-955.decision.md` / `TASK-956.plan.md` 之選填契約於敏感集外仍成立。 +- 建議補強:下一輪可加入其他 provider(GitLab / Azure / Bitbucket)、provider response 的長期封存策略、把特定 ref drift / provider precondition 提升為 policy-driven hard fail(`## Diff Evidence` 選填 policy 已由 HC-1 A2 裁決,見上)。 ## BKL-002 Contract guard 的 exact-sync 清單需人工維護 @@ -25,3 +27,15 @@ - 目前狀態:runner 可驗證案例是否符合預期,但五個維度的成熟度分數仍需主持人與記錄者填寫。 - 風險:不同演練輪次之間,評分標準可能漂移。 - 建議補強:建立固定評語範本與「0 / 1 / 2」範例,降低主觀差異。 + +## BKL-005 跨文件引用層級核對檢查項 + +- 目前狀態:引用兩份文件互證時,尚無結構化步驟要求先核對兩者所述問題之層級與範圍是否同一。 +- 風險:字面相似(如同用「必填」「所有 code artifact」)被誤當成同一問題之證據,導致把不同層級/範圍的問題錯接(friction 出處:2026-07-02 scope-drift 調查 session 同型錯誤三次穩定重現,並有 auto-memory 佐證)。 +- 建議補強:新增檢查項——引用兩份文件互證前,先核對兩者所述問題之層級與範圍是否同一;字面相似不構成同一問題之證據。 + +## BKL-006 governance/ superseded 檔歸檔(flag-only 記錄) + +- 目前狀態:`governance/` 中約 13 個 superseded 檔零 runtime caller,僅供歷史 evidence-ref 參照(HC-12 降級為 flag-only 記錄,本輪不執行歸檔)。 +- 風險:直接歸檔會使既有 evidence-ref 斷鏈,其風險高於目錄可讀性之收益。 +- 建議補強:留待未來 evidence-ref 遷移方案一併處理,屆時再評估歸檔;此前維持原位。 diff --git a/docs/red_team_runbook.md b/docs/red_team_runbook.md index 3231a09..89efe2f 100644 --- a/docs/red_team_runbook.md +++ b/docs/red_team_runbook.md @@ -75,6 +75,8 @@ python artifacts/scripts/run_red_team_suite.py --phase static --keep-temp | `RT-027` | `commit-range` archive fallback 超過 replay byte cap | `guard_status_validator.py` | validation fail 並回報 replay byte cap | | `RT-028` | `github-pr` provider response 超過 replay byte cap | `guard_status_validator.py` | validation fail 並回報 replay byte cap | | `RT-030` | external legacy unparseable verify fragment 匯入 | `migrate_artifact_schema.py` | import 維持 fail-closed:`deferred` + `MANUAL_CHECK_DEFERRED` + open verification debt | +| `RT-031` | premortem R-block 含 banned phrase 但缺五欄位(stub dismissal) | `guard_status_validator.py` | coding state 下 validation fail 並回報 contains vague phrase | +| `RT-032` | 觸及 guard/EXACT_SYNC 敏感集之 clean-task done 轉移缺 `## Diff Evidence` | `guard_status_validator.py` | write-transition verifying→done fail 並回報 clean-task closure touches guard(HC-1 A2) | ### Phase 2: Live workflow 演練 diff --git a/docs/red_team_scorecard.md b/docs/red_team_scorecard.md index bb39f56..0a48469 100644 --- a/docs/red_team_scorecard.md +++ b/docs/red_team_scorecard.md @@ -16,6 +16,8 @@ python artifacts/scripts/aggregate_red_team_scorecard.py --report artifacts/red_ python artifacts/scripts/validate_scorecard_deltas.py --scorecard docs/red_team_scorecard.generated.md ``` +> `docs/red_team_scorecard.generated.md` 為 root-only generated artifact(由上列聚合腳本產生),不納入 EXACT_SYNC 雙寫,`template/` 不保留其快照副本。 + ## 2. 自動欄位與人工欄位 - 自動欄位:Case、Phase、Expected、Outcome、Exit、Auto Baseline、Evidence。 diff --git a/docs/repo_structure_workflow_maturity_assessment.md b/docs/repo_structure_workflow_maturity_assessment.md index 6937890..69dcadd 100644 --- a/docs/repo_structure_workflow_maturity_assessment.md +++ b/docs/repo_structure_workflow_maturity_assessment.md @@ -299,7 +299,7 @@ - 資料結構以 `@dataclass` 定義,語義清楚。 3. **常數集中管理** - - 狀態機規則(`LEGAL_TRANSITIONS`、`STATE_REQUIRED_ARTIFACTS`)、artifact marker(`MARKERS`)、premortem 規則等全部以常數表定義在檔案頂部,便於審查與維護。 + - 狀態機規則(`LEGAL_TRANSITIONS`)、artifact marker(`MARKERS`)、premortem 規則等全部以常數表定義在檔案頂部,便於審查與維護。 4. **錯誤處理一致** - 統一使用 `GuardError` exception 與 `ValidationResult(errors, warnings)` 模式。 diff --git a/docs/schemas/artifact-spec-code.md b/docs/schemas/artifact-spec-code.md index a3c22a0..5bc9f60 100644 --- a/docs/schemas/artifact-spec-code.md +++ b/docs/schemas/artifact-spec-code.md @@ -76,7 +76,7 @@ - `Known Risks`: 沒有時寫 `None`。 - `TAO Trace`: risk ≥ 3(plan `## Risks` 任一條 `Severity: blocking`)之 implementer / verifier dispatch **必填**;risk ≤ 2 或 lightweight / docs-only 任務可寫 `None`。schema 與必填欄位見 [docs/agentic_execution_layer.md §2](agentic_execution_layer.md)。回填既有 artifact 時須以 `Reconstructed from artifact history` 開頭,不偽造當時即時思考。 - `Blockers`: 沒有時寫 `None`。 -- `Diff Evidence`: 沒有時可省略或寫 `None`。目前 `guard_status_validator.py` 支援 `Evidence Type: commit-range` 與 `Evidence Type: github-pr`。 +- `Diff Evidence`: 一般情況沒有時可省略或寫 `None`。**條件必填(CHG-012 / HC-1 A2)**:若 clean task 之 closure(transition into `done`)其 `## Files Changed` 觸及 guard/EXACT_SYNC 敏感集(`guard_contract_validator.EXACT_SYNC_FILES` ∪ `artifacts/scripts/guard_*.py`、`run_quality_gates.py`、`workflow_constants.py`),則 `## Diff Evidence` 必填且不可為 `None`,否則 write-transition(verifying→done)fail-closed。此規則僅前向適用於新 transition,不回溯既有 done 任務。目前 `guard_status_validator.py` 支援 `Evidence Type: commit-range` 與 `Evidence Type: github-pr`。 - `commit-range`: 要求 immutable commit pinning:`Base Commit` 與 `Head Commit` 必須是完整 40 字元 git commit SHA;`Base Ref` 與 `Head Ref` 是可選便利欄位,只用於偵測 ref drift。`Diff Command` 應對應實際 replay 命令。若擔心長期 git objects retention 不足,可額外提供 `Archive Path` 與 `Archive SHA256`;兩者必須一起出現,`Archive Path` 必須是 repo-relative、UTF-8、每行一個 normalized relative path、排序後、LF 換行的 text file,`Archive SHA256` 則是該 archive file 原始 bytes 的 SHA-256。guard 只會在 local git replay 失敗時改用 archive fallback,且 archive 內容仍必須與 `Changed Files Snapshot` 完全一致。 - `github-pr`: `Repository` 必須是 `owner/repo`,`PR Number` 必須是正整數;`API Base URL` 可省略,省略時預設 `https://api.github.com`,若使用 GitHub Enterprise Server 或本地 fixture,可覆寫成其他 http(s) endpoint。guard 會透過 GitHub PR files API 逐頁抓取 changed files,public repo 可不帶 token;private repo 或 rate-limited 環境則應提供 `GITHUB_TOKEN` 或 `GH_TOKEN`。 - `Changed Files Snapshot`: 必須列出 replayed diff 或 provider response 的完整檔案清單(以逗號分隔)。 diff --git a/docs/schemas/artifact-spec-decision.md b/docs/schemas/artifact-spec-decision.md index 5a2603b..883b709 100644 --- a/docs/schemas/artifact-spec-decision.md +++ b/docs/schemas/artifact-spec-decision.md @@ -55,6 +55,42 @@ - Override_Reason: ``` +若 decision 涉及高風險或外部可見之變更(guard/schema/report/CI gate/預設值/可觀察輸出),建議額外提供(TASK-1108,Reversibility & Blast Radius / Separation of Duties / Least Privilege 三個治理視角之落點): + +```md +## Reversibility & Blast Radius +- Reversibility: reversible | partially_reversible | irreversible | unknown +- Blast Radius: local | module | repo | external_consumers | unknown +- Rollback Plan: +- Reviewer Independence: +- Least Privilege Notes: +``` + +`## Reversibility & Blast Radius` 規則:本區段為**可選**,無自動 validator 強制;`Reversibility` 與 `Blast Radius` 之 `unknown` 值視為「尚待查明」,不得等同安全、低風險或零風險,選填 `unknown` 時須於 `Reasoning` 補充查明計畫。本區段唯一既有消費者為後續審查者與週期性 architect review(見 `docs/sop/rule_lifecycle_audit.md`);未來若有自動化強制需求,須依實際使用資料另立 task 評估(Occam's Razor + Gall's Law:無消費者不強制、無使用資料不預先重機制化)。 + +若 decision 部分依據治理指標(firing_count/block_count/warning_count/pass_rate/coverage/evaluation_count/intervention_count 等)作成,或決策本身構成治理規則之建制變動,建議額外提供(TASK-1109,Campbell's Law / Lucas Critique 兩個治理視角之落點): + +```md +## Metrics Policy +- Campbell Risk: low | medium | high | unknown +- High Stakes Metric: true | false +- Gaming Vectors: + - +- Metric Interpretation: + +## Policy Regime +- Regime ID: +- Changed At: +- Changed By: +- Comparable To Previous: true | false +- Baseline Reset Required: true | false +- Adaptation Expected: + - +- Notes: +``` + +`## Metrics Policy` 規則:本區段為**可選**,適用於決策部分依據治理指標作成之情境;`Campbell Risk` 之 `unknown` 值視為「尚待查明」,不得等同 `low` 或安全,選填 `unknown` 時須於 `Reasoning` 補充查明計畫(與 `## Reversibility & Blast Radius` 之 `unknown` 語意一致);`Metric Interpretation` 必須寫明「指標為證據而非自動核准依據」之語意,不得留空;指標值本身不構成裁決之充分理由,不得單獨用以獎勵人為製造之 guard 觸發、警告壓制或淺層測試覆蓋。`## Policy Regime` 規則:本區段為**可選**,適用於決策本身構成治理規則之建制變動(CI gate、guard 定義、telemetry schema、model 角色、escalation 規則、pass/fail 門檻、report 格式或 prompt 政策之變更);`Comparable To Previous: false` 為預設安全假設,用以防止「新政策降低可見失敗即視為指標改善」之誤判,不代表該案例不重要。兩區段皆無自動 validator 強制,唯一既有消費者為後續審查者與週期性 architect review;未來若有自動化強制需求,須依實際使用資料另立 task 評估(Occam's Razor + Gall's Law)。 + 何時必須建立 decision artifact: - 研究結果互相衝突 diff --git a/docs/sop/dispatch_implementation.md b/docs/sop/dispatch_implementation.md index 0e6616c..2e85d47 100644 --- a/docs/sop/dispatch_implementation.md +++ b/docs/sop/dispatch_implementation.md @@ -18,3 +18,11 @@ ``` > Prompt token-cost 慣例(inline vs path-reference vs temp file vs fabrication-prone):詳見 `docs/dispatch_prompt_discipline.md`。 + +### Fallback tier 產出之驗收紀律(TASK-1106) + +wrapper 之 fallback tier(後位模型,如 `gpt-5.4-mini`)產出**預設不可信**:驗收必須逐 tier 讀 dispatch log 分辨各 attempt 實際行為,關鍵宣稱(驗證結果、sources、Files Changed)以命令直驗,不採信口頭回報;credits 中斷後接手之 tier 尤然。出處:TASK-1105 Bug-B3——mini 於 shell 封鎖下未驗證覆寫 code artifact 並引用 fabricated sources(見 `artifacts/code/TASK-1105.code.md` §Post-Dispatch Amendment)。 + +### Dispatch 逾時重派紀律(TASK-1112) + +前次 `Invoke-CodexAgent.ps1` / `Invoke-GeminiAgent.ps1` dispatch 若因**工具呼叫逾時**(harness timeout,而非 wrapper 自身回報結束)而中斷,caller 重新派發前必須先確認底層 process 是否仍存活(例如 `Get-Process -Name codex,node`,或觀察目標檔案 mtime 於數分鐘內是否穩定),確認確實無殘留 process 後才可重派;不得將「工具呼叫逾時」直接等同「dispatch 已終止」。出處:TASK-1107——前景 dispatch 逾時後未確認即發起併發背景 dispatch,兩個底層 process 同時 `git stash`/`stash pop`,導致 conflict markers 與測試方法重複定義(見 `artifacts/improvement/TASK-1107.improvement.md`)。 diff --git a/docs/sop/rule_lifecycle_audit.md b/docs/sop/rule_lifecycle_audit.md new file mode 100644 index 0000000..8d95b1d --- /dev/null +++ b/docs/sop/rule_lifecycle_audit.md @@ -0,0 +1,54 @@ +# Rule Lifecycle Audit + +本 SOP 定義 workflow 規則的最小盤點循環:先看資料,再查 provenance,最後只記錄可回放的裁決。 + +## Purpose + +- 適用對象:guard 規則、validator pattern、templates、wrapper flags、workflow 條款,以及本 SOP 自身。 +- 目標:把「該不該拆、該不該放寬、為什麼還留著」收斂成固定三步,避免 ad-hoc 增生。 +- 本 SOP 只定義盤點方法;不得要求新增腳本、guard、artifact type 或自動化強制。 + +## Trigger + +- 當 [PROCESS_LEDGER](../../artifacts/improvement/PROCESS_LEDGER.md) 條目達 N=10 倍數時,同批執行本盤點;N=10 定義與節奏權威仍以 [architecture-synthesizer](../templates/architecture-synthesizer/TEMPLATE.md) 的 Trigger 為準。 +- 使用者可隨時手動發起,不必等待 N=10。 + +## Step 1: Occam Pass + +- 先讀:`artifacts/improvement/RELAXATION_LOG.md`、`artifacts/improvement/PROCESS_LEDGER.md`、`docs/templates/archive/README.md`、`docs/red_team_backlog.md`,以及最近的 Guard Exception / warning 證據。 +- 把候選規則列入待查,只接受可見訊號:長期零使用、重複放寬、長期未動工、前提已消失、或同一例外反覆出現。 +- 此步只找候選,不做裁決;沒有資料就不猜。 +- 使用數據只產生候選,不產生裁決——零使用不等於零價值(保險機制平時即零觸發);裁決一律過 Step 2 之 provenance 檢查。 +- 候選訊號亦包含(TASK-1108):高 blast-radius 變更缺 rollback/migration notes、僅以單一指標作為移除唯一理由、guard 被刪除卻無替代機制或 decision 記錄、欄位查無消費者(unknown consumer——unknown consumer ≠ no consumer,不得逕以此視為安全)。 +- 評估候選訊號時(TASK-1109,Campbell's Law):不得以原始指標值(如 firing_count、pass_rate、coverage)直接作為安全/價值/品質之證明;不得獎勵人為製造之 guard 觸發、警告壓制、淺層測試覆蓋,或僅改善指標而未降低實際風險之變更。 + +## Step 2: Chesterton Gate + +| Verdict | 何時使用 | 最小要求 | 動作 | +|---|---|---|---| +| `keep` | 規則仍在攔真實事故,或成本低但保護面仍有效 | 找得到現行風險或歷史事故來源 | 原規則不動,補一句可驗證理由 | +| `relax` | 規則目的仍成立,但當前字面過嚴、誤傷穩定高於收益 | 找得到放寬前後差異與觸發案例 | 只縮到足以消除誤傷,不順手擴 scope | +| `retire` | 前提已消失、替代機制已接手,且撤回成本低 | 找得到前提消失或替代證據 | 移除或歸檔,並留下可復活路徑 | +| `open` | 查無 provenance,或現有證據不足以判定 keep / relax / retire | 缺口本身要可指認 | 不拆也不加碼,只記錄缺口待下輪 | + +- `open` 是 fail-closed 的盤點裁決:先停在記錄,不用推測補洞;scope-drift guard Layer-1(2026-07-02)為先例。 +- `retire` 若對象是 template,復活路徑預設記 `git mv docs/templates/archive/ docs/templates/`;不適用時寫 `N/A`。 +- 同型 detect-only 違規(如 dispatch write-scope / RACI 警告)連續被人工接受達 3 次:當輪必須裁 `relax`(承認規則過嚴、修規則字面)或轉強制(如 dispatch 顯式傳 `-AutoRestore`),不得停留於 detect-and-accept(Normalization of Deviance 防範)。 + +## Step 3: Record + +- 每次盤點只追加,不覆寫既有紀錄。 +- 最低記錄格式如下,放在當次 decision / improvement / verify 附錄或同批盤點筆記中: + +| Rule / Path | Verdict | Provenance | Why | Revival Path | +|---|---|---|---|---| +| `docs/X.md` | `keep` | `docs/Y.md:12` | 一句話理由 | `N/A` | + +- `Provenance` 要寫可 grep 回放的 citation;查無者明寫 `provenance: unrecorded`。 +- 若 `RELAXATION_LOG` 累積達 3 筆以上,當次 closure 需升級 architect review。 + +## Guardrails + +- 本 SOP 自身列入每輪盤點對象。 +- 若 N=10 軌長期未觸發,下一輪盤點必須檢討是否改綁 unified audit。 +- 任何較複雜方案若不能比簡單方案多守住安全性、正確性或可觀測性,維持較小方案。 diff --git a/docs/subagent_roles.md b/docs/subagent_roles.md index df5c6c1..a2e070c 100644 --- a/docs/subagent_roles.md +++ b/docs/subagent_roles.md @@ -39,6 +39,8 @@ - 測試、驗證、review 類工作優先採 read-heavy 模式(避免 R 衝突)。 - 多個 subagents 可平行讀取,但不可平行修改相同檔案(R 不可分割)。 - A 始終由 Claude 承擔最終驗收責任,即使 R 為其他代理。 +- 高風險變更(涉及 guard、schema、CI gate 或相容契約)之 author 不得為唯一審查者,須有 Council Reviewer(見 §5.1.3)或獨立 agent session 之 review 記錄(Separation of Duties,TASK-1108)。 +- 破壞性操作(guard 刪除、CI 放寬、secret 變更、schema-breaking 變更)需經 `guard_status_validator.py --override --override-approver` 或使用者明確核准方可執行(Least Privilege,TASK-1108)。 ### 1.4 有疑義先阻塞 @@ -51,9 +53,9 @@ 必須回報 blocked,不得自行腦補補完。 -## 2. 角色總表(索引) +## 2. 角色總表 -RACI 與 agent capability 矩陣已拆分至 [docs/raci-matrix.md](raci-matrix.md)(原 `docs/subagent_roles.md` §2)。 +RACI 與 agent capability 矩陣之單一真源為本檔 §2;[docs/raci-matrix.md](raci-matrix.md) 僅保留 §2.1 TAO Trace 必要程度表(此檔獨有)。 | 角色 | |---| @@ -76,6 +78,7 @@ RACI 與 agent capability 矩陣已拆分至 [docs/raci-matrix.md](raci-matrix.m | Tester | Codex subagent | test | -- (Codex/Claude A) | code | -- | task, plan, code | test | | Verifier | Codex subagent 或 Claude 控制下代理 | verify | -- (Claude A) | code / test | -- | task, code, test | verify | | Reviewer | Codex subagent | review notes | -- (Claude A) | plan / code | -- | task, plan, code | review 摘要或 decision 建議 | +| Codex Reviewer (Council) | Codex subagent (Council) | review notes (3 model votes) | Claude(triage) | plan / code / git diff | -- | git diff | `artifacts/reviews/-.md` | 註:若你想維持最小集合,可先不建立獨立 review artifact,而把 reviewer 結果納入 decision log 或 verify artifact 的 evidence 區段。 @@ -575,4 +578,3 @@ Reviewer 是風險與品質代理,負責從可維護性、回歸風險、架 代理可以換,模型可以換,CLI 可以換。 真正不能亂的是責任邊界、artifact contract、state transition。 - diff --git a/docs/subagent_task_templates.md b/docs/subagent_task_templates.md index 3c820a4..c4b855c 100644 --- a/docs/subagent_task_templates.md +++ b/docs/subagent_task_templates.md @@ -16,6 +16,8 @@ | Memory Curator | `docs/templates/memory-curator/TEMPLATE.md` | Gemini CLI | closure | | Blocking | `docs/templates/blocking/TEMPLATE.md` | Any | any | +> 已歸檔:`adr` / `debug` / `rtm` / `srs` 四個範本因零 dispatch(建立後約 2 個月無實際派發)已移至 `docs/templates/archive/`(見該目錄 `README.md`);`discover_templates.py` 之單層掃描與本索引不再列出。取回方式見 archive README。 + --- ## 設計原則 diff --git a/docs/templates/architecture-synthesizer/TEMPLATE.md b/docs/templates/architecture-synthesizer/TEMPLATE.md index b7a744d..2c1e9ef 100644 --- a/docs/templates/architecture-synthesizer/TEMPLATE.md +++ b/docs/templates/architecture-synthesizer/TEMPLATE.md @@ -137,4 +137,5 @@ emit(Gemini 吐出 draft 文字;經 Claude / Codex 審核後寫入 `.github/ ## Trigger - 自動:[artifacts/improvement/PROCESS_LEDGER.md](../../../artifacts/improvement/PROCESS_LEDGER.md) 條目達 N=10 倍數時,由 Claude 或 ledger 計數腳本主動 dispatch。 +- 同批:[rule lifecycle audit](../../../docs/sop/rule_lifecycle_audit.md) 於同次 N=10 盤點執行;該 SOP 只盤點規則增刪與放寬,不重複定義本 Trigger。 - 手動:使用者於任意時刻請 Claude 執行(如 sprint review、季度復盤)。 diff --git a/docs/templates/archive/README.md b/docs/templates/archive/README.md new file mode 100644 index 0000000..399f17b --- /dev/null +++ b/docs/templates/archive/README.md @@ -0,0 +1,15 @@ +# Archived Templates + +本目錄收納已歸檔(archived)的 subagent prompt templates。歸檔為 revivable,非刪除。 + +## 歸檔原因 + +`adr` / `debug` / `rtm` / `srs` 四個範本由 TASK-1050(2026-05-06)之 template 體系擴充建立,但本 repo 之任務組成(以 workflow / governance 為主)自建立後約 2 個月零 dispatch(`real_dispatch_count=0`;path-ref 僅來自建立任務 TASK-1050 自身)。為降低 `discover_templates.py` 掃描結果之雜訊而歸檔。 + +## 取回方式 + +`discover_templates.py` 以單層 glob `docs/templates/*/TEMPLATE.md` 掃描;歸檔於 `archive//`(兩層深)故不再被掃到。若日後需重新啟用某範本:`git mv docs/templates/archive/ docs/templates/`(root 與 `template/` 鏡像同動)移回原位,並在 `docs/subagent_task_templates.md` 索引恢復對應條目。 + +## 來源 + +原建立任務:TASK-1050(subagent template 體系擴充,2026-05-06)。 diff --git a/docs/templates/adr/TEMPLATE.md b/docs/templates/archive/adr/TEMPLATE.md similarity index 100% rename from docs/templates/adr/TEMPLATE.md rename to docs/templates/archive/adr/TEMPLATE.md diff --git a/docs/templates/debug/TEMPLATE.md b/docs/templates/archive/debug/TEMPLATE.md similarity index 100% rename from docs/templates/debug/TEMPLATE.md rename to docs/templates/archive/debug/TEMPLATE.md diff --git a/docs/templates/rtm/TEMPLATE.md b/docs/templates/archive/rtm/TEMPLATE.md similarity index 100% rename from docs/templates/rtm/TEMPLATE.md rename to docs/templates/archive/rtm/TEMPLATE.md diff --git a/docs/templates/srs/TEMPLATE.md b/docs/templates/archive/srs/TEMPLATE.md similarity index 100% rename from docs/templates/srs/TEMPLATE.md rename to docs/templates/archive/srs/TEMPLATE.md diff --git a/docs/workflow_state_machine.md b/docs/workflow_state_machine.md index 02ccf88..d72951e 100644 --- a/docs/workflow_state_machine.md +++ b/docs/workflow_state_machine.md @@ -135,6 +135,16 @@ blocked > 例:TASK-1001(v3.4 多階段任務)之 canonical AC 經 TASK-1011 reconcile、AC-5b 經 TASK-1095 resolved,全 AC 有 evidence 而自身無 plan/code → 處置為 superseded-via-reconciliation terminal(見 `artifacts/decisions/TASK-1001.decision.md` §Closing Amendment)。 +**(c) abandoned-via-ruling terminal(棄置終態)**:任務標的已消失或經 commander/human ruling 裁定**不再 resume**,本身無工作可續且**無 successor 承載其 obligation**(與 (b) 之關鍵區隔),為一經裁定之**永久棄置終態**(非待解、非 superseded)。識別條件(**三者全須**滿足): + +1. 對應 decision artifact(Decision Class = `risk-acceptance` 或同級)明載 ruling 與**不 resume 理由**; +2. status.json `blocked_reason` 以 `ABANDONED` 起首並含 ruling 日期; +3. **無** `superseded_by`/successor 承載義務(與 (b) 之關鍵區隔)。 + +此別語義同 (b):**不發生任何 exit/resume 轉移**,state **維 `blocked` 作為 terminal disposition**,**Gate-E 對其 N/A(非「繞過」)**。**限縮**:僅 commander/human ruling + decision artifact 方可適用;一般 stuck 任務(無 ruling)**不得**藉此別繞 Gate-E。 + +> 例:TASK-901(標的 `external/Wino-Mail/` 自 workspace 移除)經主公 2026-06-13 裁 abandon → status `blocked_reason` 標 `ABANDONED (commander ruling 2026-06-13)`、無 successor(見 `artifacts/decisions/TASK-901.decision.md` §Amendment (2026-06-13))。 + ## 6. 強制規則 1. 每次狀態變更必須更新 status.json diff --git a/template/.github/memory-bank/project-facts.md b/template/.github/memory-bank/project-facts.md index 655b4c1..c52474a 100644 --- a/template/.github/memory-bank/project-facts.md +++ b/template/.github/memory-bank/project-facts.md @@ -49,12 +49,17 @@ Protected: 禁止本地特性分支進入此目錄 | 變數 | 用途 | 示例 | 必需 | |---|---|---|---| | GITHUB_TOKEN | 驗證 GitHub API | ghp_xxx... | 否(fallback 為唯讀) | -| PYTHONPATH | Import artifacts/scripts | C:\...\CLI | 用於 guard scripts | +| PYTHONPATH | Import artifacts/scripts | C:\\...\\CLI | 用於 guard scripts | ## 執行環境 Python 3.11 venv(`.venv/`):在執行 guard scripts 前必須啟動。 +## pytest 語境慣例 + +- 以 repo root 執行 `python -m pytest artifacts/scripts -q` 作為 wrapper / guard / regression 的標準測試入口。 +- `artifacts/scripts/conftest.py` 的 fake exe fixtures 以 raw stdin bytes 驗證 stdin pipe,不做字串容錯。 + ## 構建和部署 本地開發安裝: @@ -66,7 +71,7 @@ python -m pip install -r requirements-dev.txt git submodule update --init --recursive 本地測試: -python -m pytest artifacts/scripts/test_guard_units.py artifacts/scripts/test_security_scans.py -q +python -m pytest artifacts/scripts -q 執行 guard: python artifacts/scripts/guard_status_validator.py --task-id TASK-900 diff --git a/template/.github/workflows/workflow-guards.yml b/template/.github/workflows/workflow-guards.yml index 3bd909c..cf30729 100644 --- a/template/.github/workflows/workflow-guards.yml +++ b/template/.github/workflows/workflow-guards.yml @@ -26,6 +26,9 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false + # CHG-012 (HC-1 A2): full history so commit-range ## Diff Evidence replay and the + # RACI aux changed-files scan can resolve the diff base (shallow clone breaks both). + fetch-depth: 0 - name: Setup Python uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 @@ -84,3 +87,38 @@ jobs: - name: Repo Health Dashboard run: python artifacts/scripts/repo_health_dashboard.py --root . + + - name: RACI Path Classification (aux, changed governance files) + # CHG-006 auxiliary layer (secondary to the dispatch-wrapper RACI guard, which is + # the primary enforcement). CI has no agent identity, so this only classifies + # changed files under the governance dirs and fails closed if any is UNKNOWN. + # classify_path is directory-based, so files correctly placed under these prefixes + # always resolve to a known category -- this step is therefore a fail-closed + # structural invariant / defense-in-depth, not a per-agent judgment. + # Diff base unavailable (shallow checkout) -> skip with a warning. NOTE: full + # history is provided by fetch-depth: 0 on the checkout above (added by CHG-012). + run: | + set -euo pipefail + if [ "${{ github.event_name }}" = "pull_request" ]; then + BASE="${{ github.event.pull_request.base.sha }}" + else + BASE="${{ github.event.before }}" + fi + if [ -z "${BASE:-}" ] || ! git cat-file -e "${BASE}^{commit}" 2>/dev/null; then + echo "[RACI-CI] diff base unavailable (shallow checkout?); skipping aux scan (dispatch wrappers are authoritative)." + exit 0 + fi + CHANGED="$(git diff --name-only "$BASE" HEAD -- artifacts/tasks/ artifacts/plans/ artifacts/decisions/ artifacts/status/ docs/ || true)" + CHANGED="$CHANGED" python - <<'PY' + import os, sys + sys.path.insert(0, "artifacts/scripts") + import workflow_constants as wc + paths = [p for p in os.environ.get("CHANGED", "").splitlines() if p.strip()] + unknown = [p for p in paths if wc.classify_path(p) == "unknown"] + if unknown: + print("[RACI-CI] changed governance files with UNKNOWN RACI category (fail-closed):") + for p in unknown: + print(f" - {p}") + sys.exit(1) + print(f"[RACI-CI] {len(paths)} changed governance file(s); all classify to a known category.") + PY diff --git a/template/AGENTS.md b/template/AGENTS.md index 5e30c0d..ac35939 100644 --- a/template/AGENTS.md +++ b/template/AGENTS.md @@ -37,6 +37,7 @@ | `docs/templates//TEMPLATE.md` | 各角色 prompt 範本(含 YAML frontmatter) | 每個 ~150 | 派發對應 subagent 時 | | `artifacts/scripts/discover_templates.py` | Template auto-discovery CLI | 200 | 派發 subagent 前 | | `docs/lightweight_mode_rules.md` | 小任務精簡流程規則 | 350 | lightweight mode 任務時 | +| `docs/sop/rule_lifecycle_audit.md` | 規則盤點循環(Occam pass / Chesterton gate / 記錄) | 700 | Closure / 盤點觸發時 | ## Markdown 書寫語言規範 diff --git a/template/CLAUDE.md b/template/CLAUDE.md index 9c2e463..22bc591 100644 --- a/template/CLAUDE.md +++ b/template/CLAUDE.md @@ -33,7 +33,7 @@ Claude Code 預設優先使用 CLI。只有當使用者明確在 VS Code / Copil - ❌ Task / research / plan / code artifact 缺失 - ❌ Metadata 不完整(無 Task ID、status、timestamp+08:00) - ❌ Status transition 違反 workflow state machine(見 docs/workflow_state_machine.md) -- ❌ Premortem 缺失或 R1-R4 不完整(見 docs/premortem_rules.md) +- ❌ Premortem 缺失或 R1-R4 不完整,或高風險 plan 未完成獨立質疑(見 docs/premortem_rules.md,含 §12) - ❌ Verify artifact 無 Build Guarantee - ❌ Guard validator 報 scope-drift 且無 decision.## Guard Exception - ❌ Artifact 不符 schema(見 docs/artifact_schema.md) @@ -124,6 +124,14 @@ Claude 若覆寫 routing,必須在 plan / decision / final summary 中記錄 > 詳見 `docs/sop/dispatch_implementation.md`。Dispatch prompt token-cost 慣例見 `docs/dispatch_prompt_discipline.md`。 +### Dispatch Write-Scope 執行(`-AutoRestore`) + +是否讓 write-scope 違規在 dispatch 當下就被真正擋下,由協調者(Claude)決定,不是 Codex / Gemini 自己能決定: + +- `Invoke-CodexAgent.ps1` / `Invoke-GeminiAgent.ps1` 的 `-AutoRestore` 預設 `$false`:wrapper 僅偵測 write-scope 違規並印出,dispatch 仍以 exit 0 結束(detect-only,不會自動還原)。 +- 若需要違規被真正擋下(stash-based restore、exit 2),Claude 呼叫 wrapper 時必須顯式傳遞 `-AutoRestore`。 +- 未顯式傳遞時,CODEX.md / GEMINI.md 中「write scope 違規」的處置敘述僅止於偵測與事後記錄(decision artifact、人工 review),不代表該次 dispatch 已被自動擋下。 + ### 完成任務 > 詳見 `docs/sop/task_completion.md`:執行 review → 驗證 schema → 確認 verification evidence 到位 → 呼叫 task_complete 工具。 @@ -135,7 +143,7 @@ Claude 若覆寫 routing,必須在 plan / decision / final summary 中記錄 若 task 標記 `lightweight: true` 或無 plan 且仍在 drafted/researched: ✅ 可跳完整 premortem(但需 basic plan with objectives) -✅ 可簡化 verify(可用 Environment constraint instead of Build Guarantee) +✅ 可簡化 verify(依 resolved policy 放寬,低風險 `POC + generic` 的 required fields 較少;`## Environment` 非 guard-enforced,不能取代 Build Guarantee) ❌ 仍需 code artifact + Files Changed 詳見 .github/memory-bank/workflow-gates.md diff --git a/template/GEMINI.md b/template/GEMINI.md index 13982f9..2fbf7cd 100644 --- a/template/GEMINI.md +++ b/template/GEMINI.md @@ -43,7 +43,7 @@ - 不得新增 dispatch prompt 未明示之新檔(含 `REMEMBER_*.md`、`*.tavily_raw.md`、其他 task 之 research artifact 等) - 不得修改 dispatch prompt 未明示之既有檔 -- 違者:dispatch 視為失敗;Claude 將以 `git checkout HEAD --` 還原並要求 redo +- 違者:Claude 須審視 dispatch 輸出、依情況要求 redo;是否已於偵測當下被 wrapper 自動擋下(stash-based restore、exit 2)或僅止於偵測(exit 0,留待 Claude 手動處置),取決於下列 `-AutoRestore` 是否顯式傳遞 - Wrapper 之強制層:`Invoke-GeminiAgent.ps1 -AllowedPaths [string[]] -AutoRestore` 於 dispatch 完成後自動偵測;`-AllowedPaths` 為空時 skip guard,後向相容;違規 exit 2 與既有 API failure exit 1 區分 - `-AutoRestore` 安全模式(TASK-1059):wrapper 採 stash-based pre-dispatch snapshot;guard 僅對 sub-agent 真實寫入之 delta 執行 restore,不破壞 user 既有 working tree 之 modifications。default `$false`(detect 模式:印 violations 但 exit 0);caller 顯式 `-AutoRestore` 時觸發 enforcement。`-AutoRestoreLegacy` 為 deprecated forward 之過渡 flag,未來移除 - Lifecycle exclusion(TASK-1060):wrapper `Save-PreDispatchState` default 排除 7 lifecycle dirs(`artifacts/{tasks,research,plans,code,test,verify,status}/`)於 stash 範圍外,使 sub-agent dispatch 期間看得見 prereq task / research / plan 等 artifacts;caller 顯式 `-IncludeLifecycleInBaseline` 時恢復全 stash 行為(用於 wrapper-self-test 等 strict 模式) diff --git a/template/README.md b/template/README.md index d841db2..006d5b5 100644 --- a/template/README.md +++ b/template/README.md @@ -196,6 +196,8 @@ The two layers operate at different granularities and are complementary, not com **Layer Boundary Notes**: this framework deliberately keeps two layers, not four. Strategic content (the Why / portfolio vision) lives in `README.md`, `OBSIDIAN.md`, `BOOTSTRAP_PROMPT.md`, and `.github/memory-bank/project-facts.md`; the task artifact's `## Background` is the per-task strategic entry point. Operational content (the How / single-step reasoning) is the same as the TAO layer — no duplicate naming. +Above both layers sits a small set of **governance lenses** — named viewpoints (Boundary Objects, RACI, PDCA, TAO/ReAct, Double-Loop Learning, SECI, Goodhart's Law, Normalization of Deviance, Swiss Cheese Model, Hyrum's Law, Reversibility & Blast Radius, Separation of Duties, Least Privilege, Gall's Law, Modernized Postel's Law, Lucas Critique) that observe the two layers from different angles without adding new layers, schemas, or gates. + Full schema and triggering thresholds: [`docs/orchestration.md` §2.8](docs/orchestration.md), [`docs/agentic_execution_layer.md`](docs/agentic_execution_layer.md). --- diff --git a/template/README.zh-TW.md b/template/README.zh-TW.md index 1ef928d..9cca162 100644 --- a/template/README.zh-TW.md +++ b/template/README.zh-TW.md @@ -196,6 +196,8 @@ Closure **Layer Boundary Notes**:本框架刻意保留兩層而非四層。策略層內容(Why / 跨 task 願景)散見於 `README.md`、`OBSIDIAN.md`、`BOOTSTRAP_PROMPT.md` 與 `.github/memory-bank/project-facts.md`;task artifact 之 `## Background` 為單任務之策略層入口。作業層內容(How / 單步推理)即 TAO 之同義語,不另設名。 +兩層之上另有一組 **governance lenses(治理視角)**——具名觀察切面(Boundary Objects、RACI、PDCA、TAO/ReAct、Double-Loop Learning、SECI、Goodhart's Law、Normalization of Deviance、Swiss Cheese Model、Hyrum's Law、Reversibility & Blast Radius、Separation of Duties、Least Privilege、Gall's Law、Modernized Postel's Law、Lucas Critique),以不同角度觀察兩層,不新增分層、schema 或 gate。 + 完整 schema 與必填門檻:[`docs/orchestration.md` §2.8](docs/orchestration.md)、[`docs/agentic_execution_layer.md`](docs/agentic_execution_layer.md)。 --- diff --git a/template/artifacts/improvement/PROCESS_LEDGER.md b/template/artifacts/improvement/PROCESS_LEDGER.md index bff218a..9b45cd9 100644 --- a/template/artifacts/improvement/PROCESS_LEDGER.md +++ b/template/artifacts/improvement/PROCESS_LEDGER.md @@ -13,6 +13,7 @@ - 每個 task 只寫一行。 - 不貼 raw log,只寫結論與短證據方向。 - `Applied?` 表示對應修正是否已落地為文件、prompt、guard 或 template 變更。 +- 條目達 N=10 倍數時,需同批執行 [rule lifecycle audit](../../docs/sop/rule_lifecycle_audit.md)。 | Date | Task | Outcome | Top Waste | Top Risk | Fix Candidate | Applied? | |---|---|---|---|---|---|---| diff --git a/template/artifacts/improvement/RELAXATION_LOG.md b/template/artifacts/improvement/RELAXATION_LOG.md new file mode 100644 index 0000000..9af07b3 --- /dev/null +++ b/template/artifacts/improvement/RELAXATION_LOG.md @@ -0,0 +1,22 @@ +# Relaxation Log + +本檔只記事實,不重述規則正文;規則面說明與 gate 語意請回看 [`.github/memory-bank/workflow-gates.md`](../../.github/memory-bank/workflow-gates.md)。 + +## Rules + +- 每筆只寫 date / rule location / before / after / trigger task / root cause classification / provenance。 +- citation 必須能以 repo grep 直驗;查無者明寫 `provenance: unrecorded`。 +- 累積達 3 筆以上時,當次 closure 升級 architect review。 +- 本檔記錄之 intervention telemetry(實際放寬案例)與 `guard_calibration_matrix.py` 量測之 evaluation telemetry(FP/FN)為兩種不同來源,不得合併成單一治理指標(Goodhart's Law,TASK-1108)。 +- 任一案例若構成治理規則之建制變動(CI gate、guard 定義、telemetry schema、model 角色、escalation 規則、pass/fail 門檻、report 格式或 prompt 政策之變更),該案例前後之 telemetry 不得直接比較,須附加正規化說明或「不可比較」但書(Lucas Critique,TASK-1109)。 + +## Cases + +### YYYY-MM-DD — `` + +- Rule Location: `` +- Before: `` +- After: `` +- Trigger Task: `` +- Root Cause Classification: `` +- Provenance: `` or `provenance: unrecorded` diff --git a/template/artifacts/scripts/Invoke-CodexAgent.ps1 b/template/artifacts/scripts/Invoke-CodexAgent.ps1 index c39610b..72c6525 100644 --- a/template/artifacts/scripts/Invoke-CodexAgent.ps1 +++ b/template/artifacts/scripts/Invoke-CodexAgent.ps1 @@ -476,6 +476,7 @@ foreach ($model in $Models) { # writes. Empty AllowedPaths = skip (backward compatible). $violationsFound = $false $violationCount = 0 +$raciViolations = @() if ($AllowedPaths.Count -eq 0) { Write-Host "[GUARD] skipped (no AllowedPaths configured)" -ForegroundColor DarkGray } else { @@ -531,6 +532,32 @@ if ($AllowedPaths.Count -eq 0) { } else { Write-Host "[GUARD] Post-dispatch check OK; all changes within allowed paths." -ForegroundColor Green } + + # CHG-006: RACI category audit on sub-agent writes. Orthogonal to AllowedPaths -- + # a path can be allow-listed yet be the wrong artifact CLASS for this agent. Tracked + # in a SEPARATE list: RACI violations are reported (and in enforcement mode drive + # exit 2) but are NEVER restored/deleted -- they are legitimately path-allowed writes. + foreach ($p in $changedPaths) { + # Skip user pre-existing lifecycle untracked (unchanged hash) -- not a sub-agent write. + if ($lifecycleSnapshot -and $lifecycleSnapshot.ContainsKey($p) -and (Test-Path $p)) { + $ph = & git hash-object -- $p 2>$null + if ($LASTEXITCODE -eq 0) { + if ($ph -is [array]) { $ph = $ph[0] } + if (([string]$ph).Trim() -eq $lifecycleSnapshot[$p]) { continue } + } + } + & python (Join-Path $PSScriptRoot 'guard_contract_validator.py') --audit-raci $p 'Codex CLI' --dry-run 2>&1 | Out-Null + $auditExit = $LASTEXITCODE + if ($auditExit -eq 1) { + $raciViolations += $p + } elseif ($auditExit -ne 0) { + Write-Host " [GUARD][RACI] audit inconclusive (exit $auditExit), treating as non-violation: $p" -ForegroundColor DarkYellow + } + } + if ($raciViolations.Count -gt 0) { + Write-Host "[GUARD][RACI] Sub-agent wrote files outside Codex CLI's RACI artifact class:" -ForegroundColor Red + foreach ($v in $raciViolations) { Write-Host " - $v" -ForegroundColor Red } + } } # TASK-1059: restore user pre-dispatch state. Conflict -> exit 3 fail-safe. @@ -544,6 +571,14 @@ if ($violationsFound -and $AutoRestore) { exit 2 } +# CHG-006: RACI category violations follow the same enforcement gate ($AutoRestore). +# Detect mode prints only (no exit 2); enforcement mode fails closed. RACI violations +# are NEVER restored (not fed to Restore-PostDispatchDelta) -- report-and-exit only. +if ($raciViolations.Count -gt 0 -and $AutoRestore) { + Write-Error "__GUARD_VIOLATION:[CHG-006] Sub-agent wrote $($raciViolations.Count) files outside Codex CLI RACI class.__" + exit 2 +} + # Wrap up if ($IsSuccess) { Write-Output $FinalOutput diff --git a/template/artifacts/scripts/Invoke-GeminiAgent.ps1 b/template/artifacts/scripts/Invoke-GeminiAgent.ps1 index 33825b9..dcb6941 100644 --- a/template/artifacts/scripts/Invoke-GeminiAgent.ps1 +++ b/template/artifacts/scripts/Invoke-GeminiAgent.ps1 @@ -405,6 +405,7 @@ foreach ($model in $Models) { # writes. Empty AllowedPaths = skip (backward compatible). $violationsFound = $false $violationCount = 0 +$raciViolations = @() if ($AllowedPaths.Count -eq 0) { Write-Host "[GUARD] skipped (no AllowedPaths configured)" -ForegroundColor DarkGray } else { @@ -460,6 +461,32 @@ if ($AllowedPaths.Count -eq 0) { } else { Write-Host "[GUARD] Post-dispatch check OK; all changes within allowed paths." -ForegroundColor Green } + + # CHG-006: RACI category audit on sub-agent writes. Orthogonal to AllowedPaths -- + # a path can be allow-listed yet be the wrong artifact CLASS for this agent. Tracked + # in a SEPARATE list: RACI violations are reported (and in enforcement mode drive + # exit 2) but are NEVER restored/deleted -- they are legitimately path-allowed writes. + foreach ($p in $changedPaths) { + # Skip user pre-existing lifecycle untracked (unchanged hash) -- not a sub-agent write. + if ($lifecycleSnapshot -and $lifecycleSnapshot.ContainsKey($p) -and (Test-Path $p)) { + $ph = & git hash-object -- $p 2>$null + if ($LASTEXITCODE -eq 0) { + if ($ph -is [array]) { $ph = $ph[0] } + if (([string]$ph).Trim() -eq $lifecycleSnapshot[$p]) { continue } + } + } + & python (Join-Path $PSScriptRoot 'guard_contract_validator.py') --audit-raci $p 'Gemini CLI' --dry-run 2>&1 | Out-Null + $auditExit = $LASTEXITCODE + if ($auditExit -eq 1) { + $raciViolations += $p + } elseif ($auditExit -ne 0) { + Write-Host " [GUARD][RACI] audit inconclusive (exit $auditExit), treating as non-violation: $p" -ForegroundColor DarkYellow + } + } + if ($raciViolations.Count -gt 0) { + Write-Host "[GUARD][RACI] Sub-agent wrote files outside Gemini CLI's RACI artifact class:" -ForegroundColor Red + foreach ($v in $raciViolations) { Write-Host " - $v" -ForegroundColor Red } + } } # TASK-1059: restore user pre-dispatch state. Conflict -> exit 3 fail-safe. @@ -473,6 +500,14 @@ if ($violationsFound -and $AutoRestore) { exit 2 } +# CHG-006: RACI category violations follow the same enforcement gate ($AutoRestore). +# Detect mode prints only (no exit 2); enforcement mode fails closed. RACI violations +# are NEVER restored (not fed to Restore-PostDispatchDelta) -- report-and-exit only. +if ($raciViolations.Count -gt 0 -and $AutoRestore) { + Write-Error "__GUARD_VIOLATION:[CHG-006] Sub-agent wrote $($raciViolations.Count) files outside Gemini CLI RACI class.__" + exit 2 +} + # Wrap up if ($IsSuccess) { Write-Output $FinalOutput diff --git a/template/artifacts/scripts/conftest.py b/template/artifacts/scripts/conftest.py index 5eca8e5..059766d 100644 --- a/template/artifacts/scripts/conftest.py +++ b/template/artifacts/scripts/conftest.py @@ -91,12 +91,12 @@ def _write_fake_exe(tmp_path: Path, command_name: str) -> FakeExe: existing = [line for line in log_path.read_text(encoding='utf-8').splitlines() if line.strip()] if log_path.exists() else [] call_index = len(existing) behavior = json.loads(behavior_path.read_text(encoding='utf-8')) -# TASK-1062: capture stdin (non-blocking via isatty check on Windows is -# unreliable; just read whatever is on stdin -- pytest pipes always pipe). +# TASK-1105: capture raw stdin bytes and decode as UTF-8 so wrapper pipe +# tests observe the exact payload emitted by PowerShell. stdin_data = '' try: if not sys.stdin.isatty(): - stdin_data = sys.stdin.read() + stdin_data = sys.stdin.buffer.read().decode('utf-8') except Exception: stdin_data = '' record = {{ diff --git a/template/artifacts/scripts/drills/prompt_regression_cases.json b/template/artifacts/scripts/drills/prompt_regression_cases.json index e071186..93668a4 100644 --- a/template/artifacts/scripts/drills/prompt_regression_cases.json +++ b/template/artifacts/scripts/drills/prompt_regression_cases.json @@ -852,5 +852,161 @@ "note": "Gemini Architecture Synthesizer must stay emit-only (draft text, no repo-tracked writes incl the cache) with the N=10 / sprint-review trigger; mirrors the Memory Bank Curator draft-only contract (PR-021)." } ] + }, + { + "id": "PR-034", + "title": "Lightweight Verify Routes Through Resolved Policy", + "description": "CLAUDE.md lightweight guidance must govern verify obligations via the resolved policy and must not present ## Environment as a guard-enforced substitute for Build Guarantee. (sync CHG-008)", + "assertions": [ + { + "file": "CLAUDE.md", + "must_contain_all": [ + "resolved policy", + "非 guard-enforced", + "Build Guarantee" + ], + "note": "Lightweight verify relaxation is governed by the resolved policy; ## Environment is documented as non-guard-enforced and cannot replace Build Guarantee (CHG-008 撤除 Environment 無 enforcement 宣稱)." + } + ] + }, + { + "id": "PR-035", + "title": "Dispatch AutoRestore Enforcement Is Conditional, Not Absolute (TASK-1102)", + "description": "CLAUDE.md must state that passing -AutoRestore to Invoke-CodexAgent.ps1 / Invoke-GeminiAgent.ps1 is the orchestrator's (Claude's) explicit decision, and that the flag defaults to $false (detect-only, exit 0). GEMINI.md's write-scope violation clause must be conditional on whether -AutoRestore was explicitly passed, and must not re-endorse the pre-TASK-1059 blanket `git checkout HEAD --` restore language.", + "assertions": [ + { + "file": "CLAUDE.md", + "must_contain_all": [ + "Dispatch Write-Scope 執行", + "-AutoRestore", + "預設 `$false`", + "detect-only", + "顯式傳遞" + ], + "note": "Orchestrator must explicitly opt in via -AutoRestore for wrapper enforcement; default is detect-only (exit 0), not automatic blocking (TASK-1102)." + }, + { + "file": "GEMINI.md", + "must_contain_all": [ + "是否已於偵測當下被 wrapper 自動擋下", + "stash-based restore", + "取決於下列 `-AutoRestore` 是否顯式傳遞" + ], + "must_not_contain_any": [ + "dispatch 視為失敗;Claude 將以 `git checkout HEAD --`" + ], + "note": "GEMINI.md's violation clause must be conditional on explicit -AutoRestore, not an absolute claim, and must not re-endorse the pre-TASK-1059 blanket git-checkout restore (TASK-1102)." + } + ] + }, + { + "id": "PR-036", + "title": "Independent Premortem Challenge Required For High-Risk Plans (TASK-1103)", + "description": "docs/premortem_rules.md must define an independent premortem challenge for high-risk plans (security fix / upstream PR / cross-module or cross-repo / unfamiliar framework), requiring a reviewer who does not share the same conversation context/session as the plan author. CLAUDE.md's STOP triggers must reference this requirement.", + "assertions": [ + { + "file": "docs/premortem_rules.md", + "must_contain_all": [ + "獨立 Premortem 質疑", + "不得與撰寫 R1-R4 的 agent 共用同一個對話 context/session", + "Independent Premortem Challenge" + ], + "note": "Premortem rules must define the independent-challenge convention for high-risk plans, including the non-negotiable independence requirement (TASK-1103)." + }, + { + "file": "CLAUDE.md", + "must_contain_all": [ + "高風險 plan 未完成獨立質疑" + ], + "note": "CLAUDE.md STOP triggers must reference the independent premortem challenge requirement (TASK-1103)." + } + ] + }, + { + "id": "PR-037", + "title": "Rule Lifecycle Audit Verdict Contract (TASK-1104)", + "description": "The new SOP must pin the four audit verdicts and the fail-closed OPEN rule when provenance is missing.", + "assertions": [ + { + "file": "docs/sop/rule_lifecycle_audit.md", + "must_contain_all": [ + "`retire`", + "`relax`", + "`keep`", + "`open`", + "查無 provenance", + "不拆也不加碼" + ], + "note": "The rule lifecycle audit SOP must keep the four-way verdict vocabulary and the provenance-missing OPEN clause pinned." + } + ] + }, + { + "id": "PR-038", + "title": "Governance Lenses Additions (TASK-1106)", + "description": "The three evidence-backed governance lenses and the Campbell's Law rejection must stay pinned in the orchestration doc; the deviance forcing clause must stay in the rule lifecycle audit SOP.", + "assertions": [ + { + "file": "docs/orchestration.md", + "must_contain_all": [ + "Goodhart's Law", + "Normalization of Deviance", + "Swiss Cheese Model", + "明確不採 Campbell's Law" + ], + "note": "Governance Lenses table rows and the Campbell rejection clause (TASK-1106) must not silently regress." + }, + { + "file": "docs/sop/rule_lifecycle_audit.md", + "must_contain_all": [ + "不得停留於 detect-and-accept" + ], + "note": "The Normalization-of-Deviance forcing clause (accept 3 times consecutively -> relax or enforce) must stay pinned." + } + ] + }, + { + "id": "PR-039", + "title": "Governance Lenses Additions (TASK-1108)", + "description": "The six new governance lenses (Hyrum's Law, Reversibility & Blast Radius, Separation of Duties, Least Privilege, Gall's Law, Modernized Postel's Law) and the Policy Engine rejection must stay pinned in the orchestration doc.", + "assertions": [ + { + "file": "docs/orchestration.md", + "must_contain_all": [ + "Hyrum's Law", + "Reversibility & Blast Radius", + "Separation of Duties", + "Least Privilege", + "Gall's Law", + "Modernized Postel's Law", + "明確拒絕:獨立 Policy Engine" + ], + "note": "Governance Lenses table rows and the Policy Engine rejection clause (TASK-1108) must not silently regress." + } + ] + }, + { + "id": "PR-040", + "title": "Lucas Critique Addition And Campbell's Law Fold-In (TASK-1109)", + "description": "The Lucas Critique lens and the Campbell's Law operationalization note (folded into Goodhart's Law, not a separate lens) must stay pinned in the orchestration doc; the Metrics Policy and Policy Regime optional decision sections must stay pinned in the decision schema.", + "assertions": [ + { + "file": "docs/orchestration.md", + "must_contain_all": [ + "Lucas Critique", + "Campbell's Law 1979 之經濟學同構表述", + "明確不採 Campbell's Law" + ], + "note": "Lucas Critique row and the Campbell's Law fold-in note (TASK-1109) must not silently regress; the original Campbell rejection literal (TASK-1106) must remain intact." + }, + { + "file": "docs/schemas/artifact-spec-decision.md", + "must_contain_all": [ + "## Metrics Policy", + "## Policy Regime" + ], + "note": "The optional Metrics Policy and Policy Regime decision sections (TASK-1109) must not silently regress." + } + ] } ] diff --git a/template/artifacts/scripts/guard_contract_validator.py b/template/artifacts/scripts/guard_contract_validator.py index 01f1809..183794a 100644 --- a/template/artifacts/scripts/guard_contract_validator.py +++ b/template/artifacts/scripts/guard_contract_validator.py @@ -57,15 +57,21 @@ "docs/artifact_schema.md", "docs/agentic_execution_layer.md", "docs/dispatch_prompt_discipline.md", + "docs/hooks.md", "docs/lightweight_mode_rules.md", "docs/orchestration.md", + "docs/orchestration-workflow.md", "docs/premortem_rules.md", + "docs/raci-matrix.md", "docs/red_team_backlog.md", "docs/red_team_runbook.md", "docs/red_team_scorecard.md", + "docs/repo_structure_workflow_maturity_assessment.md", + "docs/security_cadence.md", "docs/sop/dispatch_implementation.md", "docs/sop/dispatch_memory_curator.md", "docs/sop/dispatch_research.md", + "docs/sop/rule_lifecycle_audit.md", "docs/sop/task_completion.md", "docs/subagent_roles.md", "docs/subagent_task_templates.md", diff --git a/template/artifacts/scripts/guard_status_validator.py b/template/artifacts/scripts/guard_status_validator.py index e5351d6..5df1409 100644 --- a/template/artifacts/scripts/guard_status_validator.py +++ b/template/artifacts/scripts/guard_status_validator.py @@ -76,16 +76,6 @@ "improvement": ".improvement.md", "status": ".status.json", } -STATE_REQUIRED_ARTIFACTS = { - "drafted": {"task", "status"}, - "researched": {"task", "research", "status"}, - "planned": {"task", "plan", "status"}, - "coding": {"task", "plan", "code", "status"}, - "testing": {"task", "plan", "code", "test", "status"}, - "verifying": {"task", "code", "status"}, - "done": {"task", "code", "verify", "status"}, - "blocked": {"task", "status"}, -} MARKERS = { "task": ( "# Task:", @@ -1030,7 +1020,7 @@ def validate_status_schema(status: dict, expected_task_id: str) -> ValidationRes if state not in VALID_STATES: errors.append(f"Invalid state: {state!r}") if status_uses_legacy_schema(status): - warnings.append("legacy status schema detected; run reconcile to promote state/current_owner/next_agent profile fields") + warnings.append("DEPRECATED legacy status schema (current_state) detected; support will be removed in a future release — run reconcile to migrate") required_keys = {"task_id", "current_state", "owner", "last_updated"} missing = required_keys - set(status.keys()) if missing: @@ -1679,6 +1669,20 @@ def task_is_high_risk(task_path: Optional[Path], plan_text: str) -> bool: return any(keyword in haystack for keyword in HIGH_RISK_KEYWORDS) +def split_premortem_risk_blocks(risks_text: str) -> List[Tuple[str, str]]: + """Split a ## Risks section into (label, block_text) pairs delimited by line-anchored + R markers; text before the first marker is dropped. Under-splitting (merging blocks) + is the safe failure mode for the banned-phrase escalation. Real plans open blocks in + three shapes — bare ``R1``, list ``- R1``, and heading ``### R1`` — all at line start.""" + matches = list(re.finditer(r"(?m)^\s*(?:[-*>#]+\s*)?R(\d+)\b", risks_text)) + blocks: List[Tuple[str, str]] = [] + for idx, match in enumerate(matches): + start = match.start() + end = matches[idx + 1].start() if idx + 1 < len(matches) else len(risks_text) + blocks.append((f"R{match.group(1)}", risks_text[start:end])) + return blocks + + def validate_premortem(plan_path: Path, task_path: Optional[Path]) -> ValidationResult: errors: List[str] = [] warnings: List[str] = [] @@ -1712,8 +1716,22 @@ def validate_premortem(plan_path: Path, task_path: Optional[Path]) -> Validation ) elif policy.min_critical == 0 and blocking_count == 0 and task_is_high_risk(task_path, text): warnings.append(f"{plan_path.name}: high-risk signals detected but task_type='{policy.task_type}' does not require blocking risk") + # CHG-007: escalate banned phrases per R-block. A vague phrase inside a risk block + # that is missing any required field is an error (a stub dismissal); the same phrase + # in an otherwise-complete block stays a warning. Phrases outside any block warn. + risk_blocks = split_premortem_risk_blocks(risks_text) for phrase in PREMORTEM_BANNED_PHRASES: - if phrase in risks_text: + if phrase not in risks_text: + continue + escalated = False + for label, block_text in risk_blocks: + if phrase in block_text and any(field not in block_text for field in PREMORTEM_REQUIRED_FIELDS): + errors.append( + f"{plan_path.name}: premortem {label} contains vague phrase '{phrase}' but is " + f"missing required Risk/Trigger/Detection/Mitigation/Severity fields" + ) + escalated = True + if not escalated: warnings.append(f"{plan_path.name}: premortem contains potentially vague phrase '{phrase}' — ensure it has concrete trigger/detection/mitigation") return ValidationResult(errors, warnings) @@ -2080,6 +2098,26 @@ def run_verify_floor_enforce(repo_root: Path) -> int: return 0 +def is_sensitive_guard_path(path: str) -> bool: + """True if ``path`` is in the guard / EXACT_SYNC "sensitive set" (CHG-012 / HC-1 A2): + a clean-task closure that touches any of these must carry replayable ## Diff Evidence. + EXACT_SYNC_FILES is read via a lazy import — guard_contract_validator imports THIS + module at its top, so a module-level import back would be circular; at call time both + modules are fully loaded, so the deferred import is safe and stays drift-free (it reads + gcv's live list rather than mirroring it).""" + p = path.replace("\\", "/").strip() + if p.startswith("./"): + p = p[2:] + if not p: + return False + from guard_contract_validator import EXACT_SYNC_FILES + if p in set(EXACT_SYNC_FILES): + return True + if p in ("artifacts/scripts/run_quality_gates.py", "artifacts/scripts/workflow_constants.py"): + return True + return bool(re.match(r"artifacts/scripts/guard_\w+\.py$", p)) + + def validate_artifact_presence( artifacts_root: Path, task_id: str, @@ -2087,6 +2125,7 @@ def validate_artifact_presence( status: dict, strict_scope: bool = False, validation_mode: str = AUTO_CLASSIFY_FULL, + enforce_clean_diff_evidence: bool = False, ) -> ValidationResult: errors: List[str] = [] warnings: List[str] = [] @@ -2198,6 +2237,25 @@ def validate_artifact_presence( else: warnings.extend(history_scope_result.waiver_candidate_errors) warnings.extend(history_scope_result.warnings) + # CHG-012 (HC-1 A2): a clean-task closure (transition into done) that touches + # the guard/EXACT_SYNC sensitive set must carry replayable ## Diff Evidence. + # Gated on enforce_clean_diff_evidence so it fires ONLY on the target_presence + # transition call (to_state == done) and NOT on re-validation of existing done + # tasks (validate_all / --task-id) -> forward-only, no retroactive impact. + if state == "done" and enforce_clean_diff_evidence: + code_text = load_text(code_path) + changed_files = extract_file_tokens(extract_section(code_text, "Files Changed")) + sensitive_hits = sorted(p for p in changed_files if is_sensitive_guard_path(p)) + evidence = parse_diff_evidence(code_text) + evidence_type = (evidence or {}).get("evidence type", "").strip().lower() + if sensitive_hits and evidence_type not in DIFF_EVIDENCE_SUPPORTED_TYPES: + errors.append( + f"{code_path.name}: clean-task closure touches guard/EXACT_SYNC-sensitive " + f"files {sensitive_hits} but provides no ## Diff Evidence. HC-1 A2 requires a " + f"replayable ## Diff Evidence block (Evidence Type: commit-range with Base " + f"Commit, Head Commit, Diff Command, Changed Files Snapshot, and Snapshot " + f"SHA256; or github-pr) so the closure's scope can be independently verified." + ) if not strict_scope and scope_drift_files: waiver_result = validate_scope_drift_waiver(artifacts_root, task_id, scope_drift_files) errors.extend(waiver_result.errors) @@ -2445,6 +2503,7 @@ def write_transition( status, strict_scope=strict_scope, validation_mode=validation_mode, + enforce_clean_diff_evidence=(to_state == "done"), ) if target_presence.errors: return ValidationResult([f"Target state '{to_state}' requirements are not yet satisfied.", *target_presence.errors], target_presence.warnings) diff --git a/template/artifacts/scripts/red_team/case_builders.py b/template/artifacts/scripts/red_team/case_builders.py index 9a7fadd..1664e52 100644 --- a/template/artifacts/scripts/red_team/case_builders.py +++ b/template/artifacts/scripts/red_team/case_builders.py @@ -1193,6 +1193,79 @@ def case_pr_025() -> CaseResult: ) +def case_rt_031() -> CaseResult: + temp_root = prepare_temp_root("RT-031") + try: + artifacts_root = copy_task_fixture(temp_root, "TASK-900", "TASK-963") + plan_path = artifacts_root / "plans" / "TASK-963.plan.md" + plan_text = plan_path.read_text(encoding="utf-8") + # CHG-007: inject a stub risk block — a banned phrase with none of the required + # Risk/Trigger/Detection/Mitigation/Severity fields. Sibling blocks stay complete + # so the whole-doc field check passes and the only error is the per-block escalation. + plan_text = plan_text.replace( + "## Validation Strategy\n", + "- R9 相容性問題,風險低\n\n## Validation Strategy\n", + 1, + ) + plan_path.write_text(plan_text, encoding="utf-8") + status_path = artifacts_root / "status" / "TASK-963.status.json" + status = json.loads(status_path.read_text(encoding="utf-8")) + status["state"] = "coding" + status["required_artifacts"] = ["code", "plan", "research", "status", "task"] + status["available_artifacts"] = ["code", "plan", "research", "status", "task", "verify"] + status["missing_artifacts"] = [] + status_path.write_text(json.dumps(status, ensure_ascii=False, indent=2) + "\n", encoding="utf-8") + return run_status_case( + "TASK-963", + artifacts_root, + expected_exit_code=1, + expected_output_fragment="contains vague phrase", + title="Premortem stub risk block with banned phrase escalates to error", + case_id="RT-031", + ) + finally: + shutil.rmtree(temp_root, ignore_errors=True) + + +def case_rt_032() -> CaseResult: + temp_root = prepare_temp_root("RT-032") + try: + artifacts_root = copy_task_fixture(temp_root, "TASK-900", "TASK-963") + # CHG-012 (HC-1 A2): add a guard-sensitive file to both plan Files Likely Affected + # and code Files Changed (so no scope drift), with NO ## Diff Evidence. The + # verifying -> done write-transition must then fail closed. + sensitive = "- `artifacts/scripts/guard_status_validator.py`\n" + plan_path = artifacts_root / "plans" / "TASK-963.plan.md" + plan_path.write_text( + plan_path.read_text(encoding="utf-8").replace( + "## Files Likely Affected\n", "## Files Likely Affected\n" + sensitive, 1 + ), + encoding="utf-8", + ) + code_path = artifacts_root / "code" / "TASK-963.code.md" + code_path.write_text( + code_path.read_text(encoding="utf-8").replace( + "## Files Changed\n", "## Files Changed\n" + sensitive, 1 + ), + encoding="utf-8", + ) + status_path = artifacts_root / "status" / "TASK-963.status.json" + status = json.loads(status_path.read_text(encoding="utf-8")) + status["state"] = "verifying" + status_path.write_text(json.dumps(status, ensure_ascii=False, indent=2) + "\n", encoding="utf-8") + return run_status_case( + "TASK-963", + artifacts_root, + expected_exit_code=1, + expected_output_fragment="clean-task closure touches guard", + title="Guard-touching clean-task done closure without Diff Evidence is blocked", + case_id="RT-032", + extra_args=["--write-transition", "verifying", "done"], + ) + finally: + shutil.rmtree(temp_root, ignore_errors=True) + + STATIC_CASES: List[CaseDefinition] = [ CaseDefinition("RT-001", "static", "Research artifact contains Recommendation", "fail", 1, "must not contain ## Recommendation", case_rt_001), CaseDefinition("RT-002", "static", "Confirmed Facts missing citation", "fail", 1, "must include an inline citation", case_rt_002), @@ -1224,6 +1297,8 @@ def case_pr_025() -> CaseResult: CaseDefinition("RT-028", "static", "Oversized provider response is rejected before JSON parsing", "fail", 1, "exceeds replay byte cap", case_rt_028), CaseDefinition("RT-029", "static", "README source/downstream wording drift", "fail", 1, "template/README.md section 'Architecture Snapshot' contains forbidden phrase: template/ + .github/ + OBSIDIAN.md + external/", case_rt_029), CaseDefinition("RT-030", "static", "External legacy unparseable import stays fail-closed", "pass", 0, "fail-closed external legacy import confirmed", case_rt_030), + CaseDefinition("RT-031", "static", "Premortem stub risk block with banned phrase escalates to error", "fail", 1, "contains vague phrase", case_rt_031), + CaseDefinition("RT-032", "static", "Guard-touching clean-task done closure without Diff Evidence is blocked", "fail", 1, "clean-task closure touches guard", case_rt_032), ] LIVE_CASES: List[CaseDefinition] = [ diff --git a/template/artifacts/scripts/red_team/cases_metadata.json b/template/artifacts/scripts/red_team/cases_metadata.json index fee1104..c5aa5b3 100644 --- a/template/artifacts/scripts/red_team/cases_metadata.json +++ b/template/artifacts/scripts/red_team/cases_metadata.json @@ -149,6 +149,16 @@ "title": "External legacy unparseable import stays fail-closed", "phase": "static" }, + { + "case_id": "RT-031", + "title": "Premortem stub risk block with banned phrase escalates to error", + "phase": "static" + }, + { + "case_id": "RT-032", + "title": "Guard-touching clean-task done closure without Diff Evidence is blocked", + "phase": "static" + }, { "case_id": "RT-LIVE-950", "title": "Role boundary live drill", diff --git a/template/artifacts/scripts/test_guard_status_validator_artifacts.py b/template/artifacts/scripts/test_guard_status_validator_artifacts.py index 1343301..713cbe1 100644 --- a/template/artifacts/scripts/test_guard_status_validator_artifacts.py +++ b/template/artifacts/scripts/test_guard_status_validator_artifacts.py @@ -487,6 +487,22 @@ def test_legacy_schema_valid(self): result = gsv.validate_status_schema(status, "TASK-001") assert result.ok + def test_legacy_schema_deprecation_warning(self): + # CHG-002 stage 1: legacy (current_state) schema stays valid (zero behavior + # change) but the warning is upgraded to a DEPRECATED notice foretelling removal. + status = { + "task_id": "TASK-001", + "current_state": "drafted", + "owner": "Claude", + "last_updated": "2026-01-15T10:00:00+08:00", + } + result = gsv.validate_status_schema(status, "TASK-001") + assert result.ok + assert any( + "DEPRECATED" in w and "will be removed in a future release" in w + for w in result.warnings + ), result.warnings + def test_legacy_blocked_without_blockers(self): status = { "task_id": "TASK-001", @@ -1108,6 +1124,30 @@ def test_banned_phrase_warning(self, tmp_path): assert result.ok assert any("風險低" in w for w in result.warnings) + def test_banned_phrase_incomplete_block_errors(self, tmp_path): + # CHG-007: a vague phrase inside an R-block that is missing required fields is an + # error (a stub dismissal). Sibling complete blocks keep the whole-doc field + # check satisfied, so the only error raised is the per-block escalation on R2. + risks = textwrap.dedent("""\ + R1: Proper risk + - Risk: Real risk described + - Trigger: Event + - Detection: Monitor + - Mitigation: Fix + - Severity: blocking + R2 相容性問題,風險低 + R3: Another proper risk + - Risk: Third thing + - Trigger: Event3 + - Detection: Monitor3 + - Mitigation: Fix3 + - Severity: non-blocking + """) + plan = self._make_plan(tmp_path, risks) + result = gsv.validate_premortem(plan, None) + assert not result.ok + assert any("R2" in e and "風險低" in e for e in result.errors), result.errors + def test_hotfix_policy_fewer_risks_ok(self, tmp_path): risks = textwrap.dedent("""\ R1: Hotfix risk @@ -2796,3 +2836,124 @@ def _make_diff_evidence_code(tmp_path, evidence_type, snapshot_files, extra_fiel code_path.write_text("\n".join(lines) + "\n", encoding="utf-8") return code_path + +class TestCleanTaskDiffEvidenceCHG012: + """CHG-012 (HC-1 A2): a clean-task closure (transition into done) touching the + guard/EXACT_SYNC sensitive set must carry ## Diff Evidence. Enforced only via + enforce_clean_diff_evidence (set by write_transition's target_presence call for + to_state==done), NOT on validate_all / --task-id re-validation -> forward-only.""" + + def _tree(self, tmp_path, task_id, files_changed, diff_evidence=None): + # Minimal task+plan+code+status tree; plan Files Likely Affected == code Files + # Changed so no scope drift, isolating the CHG-012 check. + _build_task_artifact(tmp_path, task_id) + (tmp_path / "plans").mkdir(parents=True, exist_ok=True) + listed = "\n".join(f"- `{f}`" for f in files_changed) + (tmp_path / "plans" / f"{task_id}.plan.md").write_text(textwrap.dedent(f"""\ + # Plan: {task_id} + ## Metadata + - Artifact Type: plan + - Task ID: {task_id} + - Owner: Claude + - Status: approved + - Last Updated: {_ts()} + ## Scope + s + ## Files Likely Affected + {listed} + ## Proposed Changes + c + ## Validation Strategy + v + ## Risks + R1: r + - Risk: x + - Trigger: x + - Detection: x + - Mitigation: x + - Severity: blocking + ## Ready For Coding + yes + """), encoding="utf-8") + (tmp_path / "code").mkdir(parents=True, exist_ok=True) + code = textwrap.dedent(f"""\ + # Code Result: {task_id} + ## Metadata + - Artifact Type: code + - Task ID: {task_id} + - Owner: Claude + - Status: ready + - Last Updated: {_ts()} + ## Files Changed + {listed} + ## Summary Of Changes + s + ## Mapping To Plan + - plan_item: 1.1, status: done, evidence: "x" + """) + if diff_evidence is not None: + code += f"\n## Diff Evidence\n{diff_evidence}\n" + (tmp_path / "code" / f"{task_id}.code.md").write_text(code, encoding="utf-8") + status = _make_full_status(task_id, "done") + _write_status(tmp_path, task_id, status) + return status + + def _chg012_errors(self, tmp_path, task_id, status, flag): + res = gsv.validate_artifact_presence( + tmp_path, task_id, "done", status, enforce_clean_diff_evidence=flag + ) + return [e for e in res.errors if "clean-task closure touches guard" in e] + + def test_sensitive_no_evidence_transition_fails(self, tmp_path): + status = self._tree(tmp_path, "TASK-001", ["artifacts/scripts/guard_status_validator.py"]) + errs = self._chg012_errors(tmp_path, "TASK-001", status, flag=True) + assert errs, "expected CHG-012 error for guard-touching clean closure without Diff Evidence" + assert "Diff Evidence" in errs[0] + + def test_sensitive_with_commit_range_evidence_passes(self, tmp_path): + de = ( + "- Evidence Type: commit-range\n" + f"- Base Commit: {'a' * 40}\n" + f"- Head Commit: {'b' * 40}\n" + "- Diff Command: git diff\n" + "- Changed Files Snapshot: artifacts/scripts/guard_status_validator.py\n" + "- Snapshot SHA256: deadbeef" + ) + status = self._tree(tmp_path, "TASK-001", ["artifacts/scripts/guard_status_validator.py"], diff_evidence=de) + assert not self._chg012_errors(tmp_path, "TASK-001", status, flag=True) + + def test_sensitive_none_with_reason_evidence_fails(self, tmp_path): + for diff_evidence in ( + "None (this task was completed via alternate verification)", + "None(this task was completed via alternate verification)", + ): + status = self._tree( + tmp_path, + "TASK-001", + ["artifacts/scripts/guard_status_validator.py"], + diff_evidence=diff_evidence, + ) + errs = self._chg012_errors(tmp_path, "TASK-001", status, flag=True) + assert errs, f"expected CHG-012 error for placeholder Diff Evidence: {diff_evidence}" + + def test_sensitive_unstructured_evidence_type_text_fails(self, tmp_path): + de = "No Evidence Type: applicable -- verified via manual code review instead of diff replay." + status = self._tree(tmp_path, "TASK-001", ["artifacts/scripts/guard_status_validator.py"], diff_evidence=de) + errs = self._chg012_errors(tmp_path, "TASK-001", status, flag=True) + assert errs, "expected CHG-012 error for unstructured free text containing Evidence Type" + + def test_non_sensitive_transition_unchanged(self, tmp_path): + status = self._tree(tmp_path, "TASK-001", ["src/main.py"]) + assert not self._chg012_errors(tmp_path, "TASK-001", status, flag=True) + + def test_sensitive_no_evidence_revalidation_flag_false_passes(self, tmp_path): + # validate_all / --task-id path passes flag=False -> existing done tasks stay [OK]. + status = self._tree(tmp_path, "TASK-001", ["artifacts/scripts/guard_status_validator.py"]) + assert not self._chg012_errors(tmp_path, "TASK-001", status, flag=False) + + def test_is_sensitive_guard_path(self): + assert gsv.is_sensitive_guard_path("artifacts/scripts/guard_status_validator.py") + assert gsv.is_sensitive_guard_path("artifacts/scripts/run_quality_gates.py") + assert gsv.is_sensitive_guard_path("docs/orchestration.md") # in EXACT_SYNC + assert not gsv.is_sensitive_guard_path("src/main.py") + assert not gsv.is_sensitive_guard_path("artifacts/scripts/discover_templates.py") diff --git a/template/artifacts/scripts/test_invoke_codex_agent.py b/template/artifacts/scripts/test_invoke_codex_agent.py index 84cd813..d496a62 100644 --- a/template/artifacts/scripts/test_invoke_codex_agent.py +++ b/template/artifacts/scripts/test_invoke_codex_agent.py @@ -564,3 +564,66 @@ def test_suppress_size_warn_bypasses_reject(self, fake_codex_exe, run_wrapper): assert result.returncode == 0, result.combined_output assert "exceeds reject limit" not in result.combined_output assert "exceeds soft limit" not in result.combined_output + + +class TestCodexRaciAudit: + """CHG-006: post-dispatch RACI category audit on sub-agent writes. Orthogonal to + AllowedPaths — a path can be allow-listed yet be the wrong artifact class for the + agent. RACI violations are reported and (in -AutoRestore mode) exit 2, but are + never restored/deleted.""" + + @staticmethod + def _build_writer_exe(directory: Path, rel_path: str, content: str) -> Path: + directory.mkdir(parents=True, exist_ok=True) + script_path = directory / "codex_writer.py" + script_path.write_text( + textwrap.dedent(f""" + from __future__ import annotations + from pathlib import Path + target = Path.cwd() / {rel_path!r} + target.parent.mkdir(parents=True, exist_ok=True) + target.write_text({content!r}, encoding="utf-8") + """).strip(), + encoding="utf-8", + ) + exe_path = directory / "codex.cmd" + exe_path.write_text( + f'@echo off\r\n"{sys.executable}" "{script_path}" %*\r\nexit /b %ERRORLEVEL%\r\n', + encoding="utf-8", + ) + return exe_path + + def test_raci_violation_within_allowedpaths_exits_2(self, tmp_path, tmp_repo, run_wrapper): + # Sub-agent writes a *task* artifact that IS within AllowedPaths (no path + # violation) but is the wrong RACI class for Codex CLI -> RACI audit exit 2, + # and the path-allowed write is NOT restored/deleted. + exe = self._build_writer_exe(tmp_path / "w", "artifacts/tasks/TASK-raci.task.md", "raci\n") + result = run_wrapper( + WRAPPER, + "-Prompt", "hi", + "-Executable", str(exe), + "-MaxRetriesPerTier", "0", + "-BaseBackoffSeconds", "0", + "-AllowedPaths", "artifacts/tasks/TASK-raci.task.md", + "-AutoRestore", + ) + assert result.returncode == 2, result.combined_output + assert "RACI" in result.combined_output + assert (tmp_repo / "artifacts" / "tasks" / "TASK-raci.task.md").exists(), ( + "RACI (path-allowed) write must not be deleted/restored" + ) + + def test_raci_allowed_class_within_allowedpaths_passes(self, tmp_path, tmp_repo, run_wrapper): + # Sub-agent writes a *code* artifact within AllowedPaths -> Codex CLI is + # authorized for the code class -> no RACI violation, exit 0. + exe = self._build_writer_exe(tmp_path / "w", "artifacts/code/TASK-raci.code.md", "code\n") + result = run_wrapper( + WRAPPER, + "-Prompt", "hi", + "-Executable", str(exe), + "-MaxRetriesPerTier", "0", + "-BaseBackoffSeconds", "0", + "-AllowedPaths", "artifacts/code/TASK-raci.code.md", + "-AutoRestore", + ) + assert result.returncode == 0, result.combined_output diff --git a/template/artifacts/scripts/test_invoke_gemini_agent.py b/template/artifacts/scripts/test_invoke_gemini_agent.py index a6ce307..9c064af 100644 --- a/template/artifacts/scripts/test_invoke_gemini_agent.py +++ b/template/artifacts/scripts/test_invoke_gemini_agent.py @@ -420,3 +420,66 @@ def test_suppress_size_warn_bypasses_reject(self, fake_gemini_exe, run_wrapper): assert result.returncode == 0, result.combined_output assert "exceeds reject limit" not in result.combined_output assert "exceeds soft limit" not in result.combined_output + + +class TestGeminiRaciAudit: + """CHG-006: post-dispatch RACI category audit on sub-agent writes. Orthogonal to + AllowedPaths — a path can be allow-listed yet be the wrong artifact class for the + agent. RACI violations are reported and (in -AutoRestore mode) exit 2, but are + never restored/deleted.""" + + @staticmethod + def _build_writer_exe(directory: Path, rel_path: str, content: str) -> Path: + directory.mkdir(parents=True, exist_ok=True) + script_path = directory / "gemini_writer.py" + script_path.write_text( + textwrap.dedent(f""" + from __future__ import annotations + from pathlib import Path + target = Path.cwd() / {rel_path!r} + target.parent.mkdir(parents=True, exist_ok=True) + target.write_text({content!r}, encoding="utf-8") + """).strip(), + encoding="utf-8", + ) + exe_path = directory / "gemini.cmd" + exe_path.write_text( + f'@echo off\r\n"{sys.executable}" "{script_path}" %*\r\nexit /b %ERRORLEVEL%\r\n', + encoding="utf-8", + ) + return exe_path + + def test_raci_violation_within_allowedpaths_exits_2(self, tmp_path, tmp_repo, run_wrapper): + # Sub-agent writes a *code* artifact that IS within AllowedPaths (no path + # violation) but is the wrong RACI class for Gemini CLI -> RACI audit exit 2, + # and the path-allowed write is NOT restored/deleted. + exe = self._build_writer_exe(tmp_path / "w", "artifacts/code/TASK-raci.code.md", "code\n") + result = run_wrapper( + WRAPPER, + "-Prompt", "hi", + "-Executable", str(exe), + "-MaxRetriesPerTier", "0", + "-BaseBackoffSeconds", "0", + "-AllowedPaths", "artifacts/code/TASK-raci.code.md", + "-AutoRestore", + ) + assert result.returncode == 2, result.combined_output + assert "RACI" in result.combined_output + assert (tmp_repo / "artifacts" / "code" / "TASK-raci.code.md").exists(), ( + "RACI (path-allowed) write must not be deleted/restored" + ) + + def test_raci_allowed_class_within_allowedpaths_passes(self, tmp_path, tmp_repo, run_wrapper): + # Sub-agent writes a *research* artifact within AllowedPaths -> Gemini CLI is + # authorized for the research class -> no RACI violation, exit 0. + exe = self._build_writer_exe(tmp_path / "w", "artifacts/research/TASK-raci.research.md", "research\n") + result = run_wrapper( + WRAPPER, + "-Prompt", "hi", + "-Executable", str(exe), + "-MaxRetriesPerTier", "0", + "-BaseBackoffSeconds", "0", + "-AllowedPaths", "artifacts/research/TASK-raci.research.md", + "-AutoRestore", + ) + assert result.returncode == 0, result.combined_output diff --git a/template/artifacts/scripts/test_workflow_constants.py b/template/artifacts/scripts/test_workflow_constants.py index 995dd7b..d32f48d 100644 --- a/template/artifacts/scripts/test_workflow_constants.py +++ b/template/artifacts/scripts/test_workflow_constants.py @@ -406,6 +406,24 @@ def test_resolve_policy_for_web_app_requires_build_guarantee(self): def test_rule_tables_are_self_consistent(self): assert wc.validate_workflow_rule_tables() == [] + def test_raci_matrix_includes_council_reviewer(self): + # CHG-004: Codex Reviewer (Council) merged into the single source (subagent_roles.md + # §2). Its R value is one artifact token with no '/', so the hybrid-sync parser (which + # splits the R column on '/') round-trips it as a single-element set. + entry = wc.RACI_MATRIX["Codex Reviewer (Council)"] + assert entry == {"review notes (3 model votes)"} + assert all("/" not in token for token in entry) + + def test_raci_matrix_v2_codex_owns_workflow_contract_docs(self): + # CHG-005: reconcile routing↔RACI — Codex CLI legitimately authors workflow + # contract docs (per plan Files Likely Affected), so RACI_MATRIX_V2 grants the + # workflow_contract_docs category (root cause of 2 historical violations). Other + # categories (e.g. task) still fail-closed. + codex = wc.RACI_MATRIX_V2["Codex CLI"] + assert "workflow_contract_docs" in codex + assert "code" in codex + assert "task" not in codex + # ───────────────────────────────────────────── # validate_context_stack diff --git a/template/artifacts/scripts/workflow_constants.py b/template/artifacts/scripts/workflow_constants.py index 23c1321..8c3aa2d 100644 --- a/template/artifacts/scripts/workflow_constants.py +++ b/template/artifacts/scripts/workflow_constants.py @@ -74,6 +74,7 @@ "Tester": {"test"}, "Verifier": {"verify"}, "Reviewer": {"review notes"}, + "Codex Reviewer (Council)": {"review notes (3 model votes)"}, } VERIFICATION_ITEM_RESULTS = ( @@ -648,7 +649,7 @@ def classify_path(path_str: str) -> str: RACI_MATRIX_V2: dict[str, frozenset[str]] = { "Claude Code": frozenset({"task", "plan", "decision", "status"}), "Gemini CLI": frozenset({"research", "memory_bank"}), - "Codex CLI": frozenset({"code"}), + "Codex CLI": frozenset({"code", "workflow_contract_docs"}), "Implementer": frozenset({"code"}), "Tester": frozenset({"test"}), "Verifier": frozenset({"verify"}), diff --git a/template/docs/dispatch_prompt_discipline.md b/template/docs/dispatch_prompt_discipline.md index 41fd41d..48163bb 100644 --- a/template/docs/dispatch_prompt_discipline.md +++ b/template/docs/dispatch_prompt_discipline.md @@ -92,6 +92,12 @@ grep -rE "prompt_size=[0-9]+|prompt[^a-z]*= ?[0-9]+ chars" artifacts/ Wrapper-side enforcement(自 TASK-1067):三 wrapper(`Invoke-CodexAgent` / `Invoke-GeminiAgent` / `Invoke-CodexReview`)於 prompt size 超過閾值時自動 warn 或 reject(dispatch wrapper warn @ 500 / reject @ 5000 chars,exit 4;review wrapper warn @ 100000 / reject @ 200000 chars,diff-driven 故較寬鬆);caller 可傳 `-SuppressSizeWarn` 暫時繞過。PR-032 anchor 守 wrapper 字面之 bounds 設定。 +## Dispatch Wrapper Log 重導向路徑紀律(TASK-1112) + +Caller(Claude)若需要將 `Invoke-CodexAgent.ps1` / `Invoke-GeminiAgent.ps1` 之 stdout/stderr 重導向到檔案以供背景監看(例如 `run_in_background: true` 之 dispatch),目的路徑**必須在 repo 工作樹之外**(session scratchpad 目錄或 `%TEMP%`),**不得寫入 repo 目錄內**。 + +原因:wrapper 之 post-dispatch write-scope guard(`-AutoRestore` 啟用時)以 `git status` 掃描 dispatch 期間新增的檔案並判定是否為 sub-agent 越界寫入;若 caller 自己把重導向 log 檔放在 repo 目錄內,該檔會被同一套掃描誤判為 sub-agent 寫入,觸發不必要的 restore/`git stash pop` 衝突。出處:TASK-1107——Claude 以 PowerShell `*>` 將 wrapper 輸出導到 repo 根目錄下的 `.codex-dispatch-TASK-1107.log`,遭 guard 誤刪並引發 stash pop 衝突,wrapper `[FATAL]` exit 3(見 `artifacts/improvement/TASK-1107.improvement.md`)。 + ## 6. Cross-references - `memory/feedback_dispatch_prompt_discipline.md`:本規範之 origin memory;4 條 how-to-apply 細則之原文出處。 diff --git a/template/docs/orchestration-workflow.md b/template/docs/orchestration-workflow.md index e448970..e7491e5 100644 --- a/template/docs/orchestration-workflow.md +++ b/template/docs/orchestration-workflow.md @@ -123,7 +123,7 @@ Codex CLI 不得: - 若該任務曾經 `blocked`,仍須保留 Gate E / PDCA 所需欄位 4. 若有長期可重用 lesson,Claude 可派 Gemini 以 Memory Bank Curator 模式產生 `Remember Capture` draft;Gemini 只做 read-only 分類、查重與來源驗證。 5. 若 draft 需要寫入 `.github/memory-bank/`,由 Claude/Codex 在明確 write scope 下修改,並由 Claude 最終驗收。 -6. 更新 `artifacts/improvement/PROCESS_LEDGER.md`,每個 task 只寫一行摘要,作為冷啟動入口。 +6. 更新 `artifacts/improvement/PROCESS_LEDGER.md`,每個 task 只寫一行摘要,作為冷啟動入口。**凡於 closure 產出 improvement artifact(Gate E 或 retrospective)之 task 必記一條**(見該檔頭部維護規則);純 lightweight/docs 小任務可免。 7. 明確標記: - 已完成 - 未完成 diff --git a/template/docs/orchestration.md b/template/docs/orchestration.md index 4334e43..025c9a5 100644 --- a/template/docs/orchestration.md +++ b/template/docs/orchestration.md @@ -158,6 +158,16 @@ Routing matrix: | **TAO/ReAct**(單步推理) | 任務內 subagent 之想 / 做 / 觀 | TASK-1000 執行層 + agentic_execution_layer.md | [docs/agentic_execution_layer.md](agentic_execution_layer.md) | | **Double-Loop Learning**(Argyris 1977) | 失敗後改規則(非僅改 code) | improvement artifact §5.9 之 Why Not Prevented + System-Level Preventive Action | [docs/schemas/artifact-spec-improvement.md](schemas/artifact-spec-improvement.md) | | **SECI**(Nonaka 1994) | 碎片經驗 → 系統指引 | Memory Bank Curator + Architecture Synthesizer(每 N=10 任務觸發) | [GEMINI.md](../GEMINI.md)、[`.github/prompts/remember-capture.prompt.md`](../.github/prompts/remember-capture.prompt.md) | +| **Goodhart's Law**(Goodhart 1975,TASK-1106 顯式化;亦涵蓋 Campbell's Law 1979 之經濟學同構表述,TASK-1109 併入) | 指標成為優化目標即失真(validator schema-pleasing);高風險指標(firing_count、block_count、pass_rate、coverage 等)不得作為安全/價值/品質之直接證明 | RELAXATION_LOG 累積 ≥ 3 案例 → architect review;決策涉及高風險指標時,decision schema 之條件式可選 `## Metrics Policy` 區段記錄 campbell_risk/gaming_vectors | [artifacts/improvement/RELAXATION_LOG.md](../artifacts/improvement/RELAXATION_LOG.md)、[docs/schemas/artifact-spec-decision.md](schemas/artifact-spec-decision.md) | +| **Normalization of Deviance**(Vaughan 1996,TASK-1106 顯式化) | 偏差被反覆接受而例行化(detect-and-accept 無限延續) | rule lifecycle audit 之同型違規連續接受 3 次強制裁決條款 | [docs/sop/rule_lifecycle_audit.md](sop/rule_lifecycle_audit.md) | +| **Swiss Cheese Model**(Reason 1990,TASK-1106 顯式化) | 單一事故穿透多層防禦之路徑分析 | guard 疊層 + improvement artifact `Why Not Prevented` 之逐層穿透敘述 | [.github/memory-bank/workflow-gates.md](../.github/memory-bank/workflow-gates.md) | +| **Hyrum's Law**(Hyrum Wright,相容性視角,TASK-1108 顯式化) | 已發布之可觀察行為(檔名、路徑、欄位順序、報告標題、exit code、預設值、log/警告/錯誤文字)一旦被使用即成隱性依賴,即使未正式承諾;unknown consumer ≠ no consumer | AGENTS.md 精確字串條款(不得更動 agent/validator/腳本依賴之精確字串)+ `prompt_regression_cases.json` 之 PR-* 字面 pin + `guard_contract_validator.py` 之 EXACT_SYNC byte-identical 校驗 | [AGENTS.md](../AGENTS.md)、[artifacts/scripts/drills/prompt_regression_cases.json](../artifacts/scripts/drills/prompt_regression_cases.json) | +| **Reversibility & Blast Radius**(風險工程慣例,TASK-1108 顯式化) | 修改 guard/schema/report/CI gate/預設值/可觀察輸出前,須先分類變更之可逆性與影響半徑 | decision artifact 之條件式可選 `## Reversibility & Blast Radius` 區段(比照既有 `## Guard Exception` 之條件式可選 block 慣例) | [docs/schemas/artifact-spec-decision.md](schemas/artifact-spec-decision.md) | +| **Separation of Duties**(治理慣例,TASK-1108 顯式化;TASK-1106 曾裁「隱性覆蓋不掛牌」,因具體規則落地需求而推翻) | 高風險/AI 產生之變更(涉及 guard、schema、CI gate、相容契約)之 author 不得為唯一審查者 | `docs/subagent_roles.md` §1.3 single-writer 規則 + Council Reviewer(3 個獨立 Codex model 產出獨立 review notes)+ premortem §12 獨立質疑(撰寫 plan 者不得自問自答) | [docs/subagent_roles.md §1.3](subagent_roles.md)、[docs/premortem_rules.md §12](premortem_rules.md) | +| **Least Privilege**(Saltzer & Schroeder 1975,TASK-1108 顯式化) | tools/scripts/CI jobs/AI agent 應被限制在完成任務所需之最小權限;破壞性操作需顯式升級 | `docs/subagent_roles.md` 之 agent 讀寫權限範圍(Claude 不自寫 code、Gemini read-only research、Codex 限 implementation scope)+ wrapper write-scope 偵測(`scope_guard.py`)+ decision artifact `Override_Reason`(`guard_status_validator.py --override --override-approver`) | [docs/subagent_roles.md §1.3](subagent_roles.md)、[docs/schemas/artifact-spec-decision.md](schemas/artifact-spec-decision.md) | +| **Gall's Law**(John Gall 1975,TASK-1108 顯式化) | 複雜可行系統必由簡單可行系統演化而來;避免 v0 過早長出 policy engine 等重機制 | Governance Lenses 表自身之表頭紀律「不另立分層、不另建 schema、不另設階段」+ rule lifecycle audit 之 Occam Pass | 本章(表頭紀律)、[docs/sop/rule_lifecycle_audit.md](sop/rule_lifecycle_audit.md) | +| **Modernized Postel's Law**(Postel 1980,經 Hyrum's Law 修正之版本,TASK-1108 顯式化) | 對外輸出應穩定/保守/可預期;legacy input 容忍須顯性、有警告、有 deprecation 追蹤;內部 schema 應嚴格 | EXACT_SYNC_FILES byte-identical 輸出穩定機制 + RELAXATION_LOG 之顯性放寬紀錄(含 before/after/trigger task/provenance,而非靜默改變)+ artifact schema 必填欄位之嚴格性 | [artifacts/improvement/RELAXATION_LOG.md](../artifacts/improvement/RELAXATION_LOG.md)、[docs/artifact_schema.md](artifact_schema.md) | +| **Lucas Critique**(Lucas 1976,政策回饋/建制變動視角,TASK-1109 顯式化) | 治理規則變更後(CI gate、guard 定義、telemetry schema、model 角色、escalation 規則、pass/fail 門檻、report 格式、prompt 政策),行為會調適,舊 baseline 不可跨建制直接比較 | RELAXATION_LOG 之 Before/After/Trigger Task 記錄格式 + rule lifecycle audit 之 `relax`/`retire` 裁決 + decision artifact 條件式可選 `## Policy Regime` 區段(本次新增) | [artifacts/improvement/RELAXATION_LOG.md](../artifacts/improvement/RELAXATION_LOG.md)、[docs/sop/rule_lifecycle_audit.md](sop/rule_lifecycle_audit.md)、[docs/schemas/artifact-spec-decision.md](schemas/artifact-spec-decision.md) | **明確拒絕:OODA** @@ -171,6 +181,16 @@ OODA(Boyd, Observe-Orient-Decide-Act)與 TAO/ReAct(Yao 2022, Thought-Actio 二者並存將造成 schema 重複、辭彙負擔、與 ReAct 之 LLM agent 文獻主流脫鉤。本框架**已採 TAO/ReAct,明確不採 OODA**;任何後續 task 不得引此決策為 routing override 範本,亦不得試圖以 OODA 取代 TAO(兩者不可並存於本框架)。 +**明確拒絕:Campbell's Law** + +Campbell's Law(Campbell 1979)與 Goodhart's Law 同構——同為「量化指標被用於治理即遭腐化」,僅為社會科學與經濟學之不同表述。依 OODA 先例(同構名詞不並存):本框架**已採 Goodhart's Law,明確不採 Campbell's Law**;任何後續 task 不得引此決策為 routing override 範本。 + +**Campbell's Law 操作化附註(TASK-1109)**:上述拒絕僅拒絕「另立一個與 Goodhart's Law 重複之獨立視角」,不推翻此拒絕宣告,亦不拒絕吸收 Campbell's Law 文獻中對「高風險指標」的具體操作規則。這些規則已併入 Goodhart's Law 列(見上表):不得以原始指標值(如 firing_count、pass_rate、coverage)直接證明安全/價值/品質;高風險指標須標記 campbell_risk;須記錄 plausible gaming vectors;不得獎勵人為製造之 guard 觸發、警告壓制、淺層測試覆蓋或僅改善指標之變更。可選 metadata(campbell_risk / high_stakes_metric / gaming_vectors / metric_interpretation)之 schema 見 `docs/schemas/artifact-spec-decision.md` 之 `## Metrics Policy` 條件式可選區段。 + +**明確拒絕:獨立 Policy Engine(OPA / Rego / CEL / 資料庫式規則引擎)** + +Gall's Law 之直接應用:本框架尚無可觀察之真實需求證明需要獨立 policy engine——guard 邏輯現以 Python validator 直接表達已足夠,且無使用資料顯示現有機制不足。在無使用資料前引入獨立 policy engine 即為過早複雜化,本框架**明確不採**,除非既有 repo 已依賴此類工具(現況:無);任何後續 task 不得引此決策為 routing override 範本。 + ## 3. Workflow 與 Gate 細節索引 §3 之後的流程內容已拆分至 [docs/orchestration-workflow.md](orchestration-workflow.md): diff --git a/template/docs/premortem_rules.md b/template/docs/premortem_rules.md index d085c9c..f1c8237 100644 --- a/template/docs/premortem_rules.md +++ b/template/docs/premortem_rules.md @@ -198,3 +198,46 @@ Premortem 的目的不是讓人安心,而是讓錯誤提前發生在紙上, premortem 的價值不在於悲觀,而在於把失敗變成可命名、可偵測、可止血的對象。 如果一條風險不能讓下一位代理知道「怎麼發現、怎麼處理」,那它就不算合格。 + +## 12. 獨立 Premortem 質疑(高風險 plan) + +### 背景 + +§1-§11 的 premortem 規則由撰寫 plan 的同一個 agent 自行填寫、自行判斷是否合格;`guard_status_validator.py` 依 §4 的 P1-P8 只檢查風險條目的格式與用語是否具體,不檢查風險判斷本身是否站得住腳。這代表撰寫者的盲點,在 R1-R4 本身完全沒有被獨立檢查過。 + +### 適用範圍 + +以下任一條件命中時,於 `planned → coding` 前必須完成一次獨立質疑: + +- 涉及安全性修補(security fix) +- 涉及 upstream PR +- 涉及多模組或跨 repo 修改 +- 涉及不熟悉框架、版本或環境 + +(刻意不納入 §1 的「無法 100% 確認變更影響範圍」——該條件過於主觀,套用在此處會讓幾乎所有任務都命中,稀釋這道 gate 的訊號。) + +### 獨立性要求 + +- 執行質疑者不得與撰寫 R1-R4 的 agent 共用同一個對話 context/session;撰寫 plan 的 agent 不可在同一輪回應內自問自答完成本項質疑。 +- 可透過 Agent tool 開新 subagent,或派給另一個 CLI(Gemini / Codex),只要是脫離原 plan 撰寫 context 的獨立呼叫即可。 +- 若任務規模過小、找不到可用的獨立 agent,必須在 plan 的 `## Risks` 中明記原因並回報 blocked,不得逕自略過。 + +### 質疑內容(最小集合) + +- 逐條檢查既有 R1-R4:Detection 描述的偵測方式,在實際情境下是否真的會被觸發? +- 是否有被漏掉的失敗模式(既有 R1-R4 都沒有覆蓋到的風險)? +- 若發現遺漏或 Detection 不成立,必須具體指出並建議新增或修正的風險條目,沿用本文件 §3-§4 的欄位與品質規則;§9 禁止語句清單同樣適用於本項輸出,不可用空話回覆。 + +### 輸出位置 + +- 附掛在 plan artifact 的 `## Risks` 區段下,新增 `### Independent Premortem Challenge` 子區段,逐條回覆對應 R 編號的判斷(每條至少一句具體理由)。 +- 若質疑結果導致風險判斷需要重大修改(例如新增 blocking risk 或推翻既有 mitigation),改寫 decision artifact 說明分歧與最終裁決。 + +### 與既有機制的分工邊界 + +- 本項質疑作用在 **plan 階段**(尚無 code diff);Council Reviewer(`/codex-review`,見 `docs/subagent_roles.md` §5.1.3)作用在 **code diff 已產出之後**。兩者觸發時機不重疊,不互相取代。 +- 本項質疑是逐 task 觸發(符合條件即做一次);RACI Auditor / Architecture Synthesizer 是週期性(每 10 個 PROCESS_LEDGER 或 Sprint Review)批次審查,兩者頻率與粒度不同。 + +### 現況 + +本節僅定義慣例與最低要求,不由 `guard_status_validator.py` 自動強制(無新增 automated guard)。是否日後加上自動化檢查(例如偵測 plan 是否缺少 `### Independent Premortem Challenge` 子區段),留待後續視實際執行成本再評估,避免尚未有使用資料就過早鎖死強制規則。 diff --git a/template/docs/raci-matrix.md b/template/docs/raci-matrix.md index b101791..936f894 100644 --- a/template/docs/raci-matrix.md +++ b/template/docs/raci-matrix.md @@ -1,21 +1,10 @@ # RACI Matrix -> 本檔由 `docs/subagent_roles.md` §2 拆分而來;RACI 與 agent capability 矩陣集中於此。 +> 本檔之 §2 角色總表已回歸單一真源 [docs/subagent_roles.md](subagent_roles.md) §2;本檔僅保留下列 §2.1 TAO Trace 必要程度表(此檔獨有)。 ## 2. 角色總表 -| 角色 | 類型 | R (主執行) | A (最終問責) | C (諮詢) | I (通知) | 主要輸入 | 主要輸出 | -|---|---|---|---|---|---|---|---| -| Claude Code | 主控代理 | task / plan / decision / status | task / plan / verify / decision / status / improvement | research / code / verify | -- | 全部合法 artifacts | task, plan, verify, decision, status | -| Gemini CLI | 研究 + memory curator | research / Tavily Cache / Remember Capture draft | -- (Claude A) | task | closure events | task, 研究相關文件, memory-bank 讀取範圍 | research, Tavily Cache draft, Remember Capture draft | -| Codex CLI | 實作主代理 | code | -- (Claude A) | plan / research | -- | task, research, plan | code | -| Implementer | Codex subagent | code (實檔修改) | -- (Codex/Claude A) | plan | -- | task, plan, research | code | -| Tester | Codex subagent | test | -- (Codex/Claude A) | code | -- | task, plan, code | test | -| Verifier | Codex subagent 或 Claude 控制下代理 | verify | -- (Claude A) | code / test | -- | task, code, test | verify | -| Reviewer | Codex subagent | review notes | -- (Claude A) | plan / code | -- | task, plan, code | review 摘要或 decision 建議 | -| Codex Reviewer (Council) | Codex subagent (Council) | review notes (3 model votes) | Claude(triage) | plan / code / git diff | -- | git diff | `artifacts/reviews/-.md` | - -註:若你想維持最小集合,可先不建立獨立 review artifact,而把 reviewer 結果納入 decision log 或 verify artifact 的 evidence 區段。 +RACI 與 agent capability 矩陣之單一真源為 [docs/subagent_roles.md](subagent_roles.md) §2「角色總表」(hybrid-sync guard 綁定該檔 ↔ `workflow_constants.RACI_MATRIX`)。本檔不再重複該表。 ### 2.1 TAO Trace 必要程度(執行層) diff --git a/template/docs/red_team_backlog.md b/template/docs/red_team_backlog.md index 04c5efe..d033294 100644 --- a/template/docs/red_team_backlog.md +++ b/template/docs/red_team_backlog.md @@ -5,8 +5,10 @@ ## BKL-001 歷史 diff 重建仍未完全自動化 - 目前狀態:`guard_status_validator.py` 現在除了 dirty worktree 的 git-backed changed-files 比對外,也支援以 pinned `Base Commit` / `Head Commit`、`Changed Files Snapshot` 與 `Snapshot SHA256` 重放 clean task 的 `commit-range` historical diff;若 local git replay 失敗且附有合法 `Archive Path` / `Archive SHA256`,也可改走 archive fallback;若 task 記錄 `Evidence Type: github-pr`,則可透過 GitHub PR files API 重建 changed files。 +- 分流定案(2026-07-02):Branch A 是 dirty-worktree guard;標準 clean CI 不觸發 Branch A 屬設計分流,不是 dead-path bug。證據鏈:`TASK-954` 明文將 commit-range / historical diff reconstruction 列為 Out of Scope;`TASK-955` Background 接續定義 clean worktree task 需依 code artifact 的 historical diff evidence;RT-013 / RT-014 分別覆蓋 dirty worktree 與 pinned historical diff;`guard_status_validator.py` 與 README / schema 文件皆以 dirty worktree versus clean-task replay 描述同一分流。 - 殘餘風險:若 task 沒有記錄 diff evidence、沒有準備 archive file、需要 GitHub 以外的 provider、遭遇 provider auth / rate-limit 問題、或 PR files 超過 GitHub endpoint 上限,guard 仍可能無法自動重建歷史 changed files;目前 ref drift 也只會告警,不會直接阻斷。 -- 建議補強:下一輪可加入其他 provider(GitLab / Azure / Bitbucket)、provider response 的長期封存策略、或把特定 ref drift / provider precondition 提升為 policy-driven hard fail。 +- 已裁決(HC-1 A2,2026-07-03):`## Diff Evidence` 選填 policy 經 human 裁決為**範圍限定的 A2**——僅對觸及 guard/EXACT_SYNC 敏感集(`guard_contract_validator.EXACT_SYNC_FILES` ∪ `artifacts/scripts/guard_*.py`、`run_quality_gates.py`、`workflow_constants.py`)之 clean-task closure(transition into `done`)強制提供 `## Diff Evidence`,其餘 clean task 維持選填。實作見 CHG-012(`guard_status_validator.is_sensitive_guard_path` + `validate_artifact_presence` 之 `enforce_clean_diff_evidence` gate,僅前向適用於新 transition,不回溯既有 done 存量;RT-032 覆蓋)。spot-check#1 確認 `github-pr` / archive replay arms KEEP 為此裁決之前提。原 `TASK-955.decision.md` / `TASK-956.plan.md` 之選填契約於敏感集外仍成立。 +- 建議補強:下一輪可加入其他 provider(GitLab / Azure / Bitbucket)、provider response 的長期封存策略、把特定 ref drift / provider precondition 提升為 policy-driven hard fail(`## Diff Evidence` 選填 policy 已由 HC-1 A2 裁決,見上)。 ## BKL-002 Contract guard 的 exact-sync 清單需人工維護 @@ -25,3 +27,15 @@ - 目前狀態:runner 可驗證案例是否符合預期,但五個維度的成熟度分數仍需主持人與記錄者填寫。 - 風險:不同演練輪次之間,評分標準可能漂移。 - 建議補強:建立固定評語範本與「0 / 1 / 2」範例,降低主觀差異。 + +## BKL-005 跨文件引用層級核對檢查項 + +- 目前狀態:引用兩份文件互證時,尚無結構化步驟要求先核對兩者所述問題之層級與範圍是否同一。 +- 風險:字面相似(如同用「必填」「所有 code artifact」)被誤當成同一問題之證據,導致把不同層級/範圍的問題錯接(friction 出處:2026-07-02 scope-drift 調查 session 同型錯誤三次穩定重現,並有 auto-memory 佐證)。 +- 建議補強:新增檢查項——引用兩份文件互證前,先核對兩者所述問題之層級與範圍是否同一;字面相似不構成同一問題之證據。 + +## BKL-006 governance/ superseded 檔歸檔(flag-only 記錄) + +- 目前狀態:`governance/` 中約 13 個 superseded 檔零 runtime caller,僅供歷史 evidence-ref 參照(HC-12 降級為 flag-only 記錄,本輪不執行歸檔)。 +- 風險:直接歸檔會使既有 evidence-ref 斷鏈,其風險高於目錄可讀性之收益。 +- 建議補強:留待未來 evidence-ref 遷移方案一併處理,屆時再評估歸檔;此前維持原位。 diff --git a/template/docs/red_team_runbook.md b/template/docs/red_team_runbook.md index 3231a09..89efe2f 100644 --- a/template/docs/red_team_runbook.md +++ b/template/docs/red_team_runbook.md @@ -75,6 +75,8 @@ python artifacts/scripts/run_red_team_suite.py --phase static --keep-temp | `RT-027` | `commit-range` archive fallback 超過 replay byte cap | `guard_status_validator.py` | validation fail 並回報 replay byte cap | | `RT-028` | `github-pr` provider response 超過 replay byte cap | `guard_status_validator.py` | validation fail 並回報 replay byte cap | | `RT-030` | external legacy unparseable verify fragment 匯入 | `migrate_artifact_schema.py` | import 維持 fail-closed:`deferred` + `MANUAL_CHECK_DEFERRED` + open verification debt | +| `RT-031` | premortem R-block 含 banned phrase 但缺五欄位(stub dismissal) | `guard_status_validator.py` | coding state 下 validation fail 並回報 contains vague phrase | +| `RT-032` | 觸及 guard/EXACT_SYNC 敏感集之 clean-task done 轉移缺 `## Diff Evidence` | `guard_status_validator.py` | write-transition verifying→done fail 並回報 clean-task closure touches guard(HC-1 A2) | ### Phase 2: Live workflow 演練 diff --git a/template/docs/red_team_scorecard.generated.md b/template/docs/red_team_scorecard.generated.md deleted file mode 100644 index 130f4a8..0000000 --- a/template/docs/red_team_scorecard.generated.md +++ /dev/null @@ -1,77 +0,0 @@ -# Red Team Scorecard (Semi-Auto) - -此檔由 `artifacts/scripts/aggregate_red_team_scorecard.py` 依 red-team report 自動產生。 - -## Metadata -- Source Report: `C:/Users/Arcobaleno/Documents/Code/consilium-fabri/artifacts/red_team/latest_report.md` -- Generated At: 2026-04-19T19:20:48+08:00 -- Timezone: Asia/Taipei (+08:00) - -## Aggregated Cases - -| Case | Phase | Expected | Outcome | Exit | Auto Baseline (0-2) | Reviewer Delta (-1/0/+1) | Final (0-2) | Evidence | Notes | -|---|---|---|---|---:|---:|---:|---:|---|---| -| `RT-001` | static | fail | pass | 1 | 2 | 0 | 2 | `must not contain ## Recommendation` | [ERROR] Validation failed | -| `RT-002` | static | fail | pass | 1 | 2 | 0 | 2 | `must include an inline citation` | [ERROR] Validation failed | -| `RT-003` | static | fail | pass | 1 | 2 | 0 | 2 | `must start with UNVERIFIED:` | [ERROR] Validation failed | -| `RT-004` | static | fail | pass | 1 | 2 | 0 | 2 | `requires at least 1 blocking risks` | [ERROR] Validation failed | -| `RT-005` | static | fail | pass | 1 | 2 | 0 | 2 | `requires an improvement artifact` | [ERROR] Validation failed | -| `RT-006` | static | fail | pass | 1 | 2 | 0 | 2 | `requires an improvement artifact with Status: applied` | [ERROR] Validation failed | -| `RT-007` | static | fail | pass | 1 | 2 | 0 | 2 | `Contract drift detected` | template workflow state machine drift | -| `RT-008` | static | fail | pass | 1 | 2 | 0 | 2 | `missing required phrase: template/OBSIDIAN.md` | Obsidian GitHub/Template section lost required template mapping | -| `RT-009` | static | fail | pass | 1 | 2 | 0 | 2 | `BOOTSTRAP_PROMPT.md missing required phrase: guard_contract_validator.py` | bootstrap lost contract-guard step | -| `RT-010` | static | fail | pass | 1 | 2 | 0 | 2 | `missing required ## Sources section` | [ERROR] Validation failed | -| `RT-011` | static | pass | pass | 0 | 2 | 0 | 2 | `Mapping To Plan entry must match` | [OK] Validation passed | -| `RT-012` | static | pass | pass | 0 | 2 | 0 | 2 | `missing reviewer field` | [OK] Validation passed | -| `RT-013` | static | fail | pass | 1 | 2 | 0 | 2 | `git-backed scope check found actual changed files not listed` | [ERROR] Validation failed | -| `RT-014` | static | fail | pass | 1 | 2 | 0 | 2 | `commit-range scope check found diff files not listed` | [ERROR] Validation failed | -| `RT-015` | static | fail | pass | 1 | 2 | 0 | 2 | `--allow-scope-drift requires a decision artifact with ## Guard Exception` | [ERROR] Validation failed | -| `RT-016` | static | pass | pass | 0 | 2 | 0 | 2 | `[OK] Validation passed` | [OK] Validation passed | -| `RT-017` | static | fail | pass | 1 | 2 | 0 | 2 | `Snapshot SHA256 does not match Changed Files Snapshot` | [ERROR] Validation failed | -| `RT-018` | static | fail | pass | 1 | 2 | 0 | 2 | `github-pr scope check found diff files not listed` | [ERROR] Validation failed | -| `RT-019` | static | fail | pass | 1 | 2 | 0 | 2 | `commit-range archive fallback found diff files not listed` | [ERROR] Validation failed | -| `RT-020` | static | fail | pass | 1 | 2 | 0 | 2 | `Archive SHA256 does not match archive file` | [ERROR] Validation failed | -| `RT-021` | static | pass | pass | 0 | 2 | 0 | 2 | `lightweight candidate` | [OK] Validation passed | -| `RT-022` | static | pass | pass | 0 | 2 | 0 | 2 | `[AUTO-UPGRADE]` | auto_upgrade_log written to status.json | -| `RT-023` | static | fail | pass | 1 | 2 | 0 | 2 | `waiver expired` | [ERROR] Validation failed | -| `RT-024` | static | fail | pass | 1 | 2 | 0 | 2 | `API Base URL host '127.0.0.1' is not allowed` | [ERROR] Validation failed | -| `RT-025` | static | pass | pass | 0 | 2 | 0 | 2 | `[OK] Validation passed` | [OK] Validation passed | -| `RT-026` | static | fail | pass | 1 | 2 | 0 | 2 | `Text file too large` | [FAIL] Text file too large: C:\Users\Arcobaleno\Documents\Code\consilium-fabri\.codex-red-team\RT-026-be3a17bc\artifacts\plans\TASK-976.plan.md exceeds size ceiling of 524288 bytes | -| `RT-027` | static | fail | pass | 1 | 2 | 0 | 2 | `exceeds replay byte cap` | [ERROR] Validation failed | -| `RT-028` | static | fail | pass | 1 | 2 | 0 | 2 | `exceeds replay byte cap` | [ERROR] Validation failed | -| `RT-029` | static | fail | pass | 1 | 2 | 0 | 2 | `template/README.md section 'Architecture Snapshot' contains forbidden phrase: template/ + .github/ + OBSIDIAN.md + external/` | template README architecture snapshot regressed to source-only wording | -| `RT-030` | static | pass | pass | 0 | 2 | 0 | 2 | `fail-closed external legacy import confirmed` | unparseable external legacy verify stays deferred with open verification debt | -| `RT-LIVE-950` | live | pass | pass | 0 | 2 | 0 | 2 | `[OK] Validation passed` | TASK-950 live drill should stay valid after decision / improvement closure | -| `RT-LIVE-951` | live | pass | pass | 0 | 2 | 0 | 2 | `[OK] Validation passed` | TASK-951 live drill should prove Gate E before resume | -| `PR-001` | prompt | pass | pass | 0 | 2 | 0 | 2 | `Prompt Regression Report` | CLAUDE/CODEX prompts should enforce STOP or blocked behavior under ambiguous or invalid inputs | -| `PR-002` | prompt | pass | pass | 0 | 2 | 0 | 2 | `Prompt Regression Report` | Prompt contracts should prevent role overreach across Claude/Gemini/Codex | -| `PR-003` | prompt | pass | pass | 0 | 2 | 0 | 2 | `Prompt Regression Report` | Research prompt should enforce claim-level citation and anti-fabrication rules | -| `PR-004` | prompt | pass | pass | 0 | 2 | 0 | 2 | `Prompt Regression Report` | Research prompt should isolate upstream truth source from local fork assumptions | -| `PR-005` | prompt | pass | pass | 0 | 2 | 0 | 2 | `Prompt Regression Report` | Research prompt should explicitly forbid recommendation or architecture design outputs | -| `PR-006` | prompt | pass | pass | 0 | 2 | 0 | 2 | `Prompt Regression Report` | Implementation prompt should keep blocked criteria explicit and avoid optimistic ambiguity | -| `PR-007` | prompt | pass | pass | 0 | 2 | 0 | 2 | `Prompt Regression Report` | Implementation prompt should enforce premortem quality before coding | -| `PR-008` | prompt | pass | pass | 0 | 2 | 0 | 2 | `Prompt Regression Report` | Claude prompt should rely only on artifacts and reject completion without artifacts, verification, and evidence | -| `PR-009` | prompt | pass | pass | 0 | 2 | 0 | 2 | `Prompt Regression Report` | Workflow prompt should distinguish source template repos from downstream terminal repos | -| `PR-010` | prompt | pass | pass | 0 | 2 | 0 | 2 | `Prompt Regression Report` | Gemini prompt should block bad research inputs and keep active workflow files on the allowlisted Gemini models | -| `PR-011` | prompt | pass | pass | 0 | 2 | 0 | 2 | `Prompt Regression Report` | Codex prompt should preserve approved-plan discipline, summary artifacts, and single-writer behavior | -| `PR-012` | prompt | pass | pass | 0 | 2 | 0 | 2 | `Prompt Regression Report` | Workflow contract should route conflicts into a recorded decision log before progress continues | -| `PR-013` | prompt | pass | pass | 0 | 2 | 0 | 2 | `Prompt Regression Report` | Workflow contract should define when a decision artifact is mandatory for conflicts, tradeoffs, and validation failures | -| `PR-014` | prompt | pass | pass | 0 | 2 | 0 | 2 | `Prompt Regression Report` | Decision artifacts should preserve the chain from issue to follow-up rather than a single conclusion | -| `PR-015` | prompt | pass | pass | 0 | 2 | 0 | 2 | `Prompt Regression Report` | Claude prompt should stop and record external environment, build, or test failures without expanding scope | -| `PR-016` | prompt | pass | pass | 0 | 2 | 0 | 2 | `Prompt Regression Report` | Workflow contract should require an explicit decision waiver before --allow-scope-drift can downgrade failures | -| `PR-017` | prompt | pass | pass | 0 | 2 | 0 | 2 | `Prompt Regression Report` | Workflow contract should define commit-range diff evidence for clean-task historical reconstruction | -| `PR-018` | prompt | pass | pass | 0 | 2 | 0 | 2 | `Prompt Regression Report` | Workflow contract should require pinned commits plus snapshot checksum for immutable historical replay | -| `PR-019` | prompt | pass | pass | 0 | 2 | 0 | 2 | `Prompt Regression Report` | Workflow contract should define GitHub PR files evidence, API base override, and token boundary for provider-backed replay | -| `PR-020` | prompt | pass | pass | 0 | 2 | 0 | 2 | `Prompt Regression Report` | Workflow contract should define archive-backed fallback and archive integrity checks when git objects are no longer available | - -## Summary - -- Cases: 52 -- Case Passed: 52 -- Case Failed: 0 - -## Review Rules - -- `Auto Baseline (0-2)`: 2 = `Outcome` 為 pass;0 = `Outcome` 為 fail。 -- `Reviewer Delta`: 僅允許 `-1`、`0`、`+1`,且任何非 0 都要在 Notes 補原因。 -- `Final`: `clamp(Auto Baseline + Reviewer Delta, 0, 2)`。 diff --git a/template/docs/red_team_scorecard.md b/template/docs/red_team_scorecard.md index bb39f56..0a48469 100644 --- a/template/docs/red_team_scorecard.md +++ b/template/docs/red_team_scorecard.md @@ -16,6 +16,8 @@ python artifacts/scripts/aggregate_red_team_scorecard.py --report artifacts/red_ python artifacts/scripts/validate_scorecard_deltas.py --scorecard docs/red_team_scorecard.generated.md ``` +> `docs/red_team_scorecard.generated.md` 為 root-only generated artifact(由上列聚合腳本產生),不納入 EXACT_SYNC 雙寫,`template/` 不保留其快照副本。 + ## 2. 自動欄位與人工欄位 - 自動欄位:Case、Phase、Expected、Outcome、Exit、Auto Baseline、Evidence。 diff --git a/template/docs/repo_structure_workflow_maturity_assessment.md b/template/docs/repo_structure_workflow_maturity_assessment.md index b724bfc..69dcadd 100644 --- a/template/docs/repo_structure_workflow_maturity_assessment.md +++ b/template/docs/repo_structure_workflow_maturity_assessment.md @@ -1,124 +1,259 @@ # Repo 結構與工作流成熟度評估 +> **版本**: v2.3 | **評估日期**: 2026-04-17 | **評估基準**: commit (pending) + ## 評估範圍 -本報告根據目前 repo 內可見結構與代表性文件進行靜態評估,主要依據如下: - -- `README.md`、`README.zh-TW.md` -- `AGENTS.md`、`BOOTSTRAP_PROMPT.md`、`OBSIDIAN.md` -- `docs/orchestration.md` -- `docs/artifact_schema.md` -- `docs/workflow_state_machine.md` -- `docs/subagent_roles.md` -- `docs/lightweight_mode_rules.md` -- `docs/subagent_task_templates.md` -- `.github/workflows/workflow-guards.yml` -- `artifacts/scripts/guard_status_validator.py` -- `artifacts/scripts/guard_contract_validator.py` -- `artifacts/red_team/latest_report.md` -- 代表性 task artifacts -- 目前 git worktree 狀態與目錄分布 +本報告根據目前 repo 內可見結構、自動化驗證工具實際執行結果、以及 `repo_health_dashboard.py` 的即時資料進行評估。主要依據如下: + +**結構與規範文件**: +- `README.md`、`README.zh-TW.md`、`AGENTS.md`、`BOOTSTRAP_PROMPT.md`、`OBSIDIAN.md` +- `docs/orchestration.md`、`docs/artifact_schema.md`、`docs/workflow_state_machine.md` +- `docs/subagent_roles.md`、`docs/lightweight_mode_rules.md`、`docs/subagent_task_templates.md` +- `docs/red_team_runbook.md`、`docs/red_team_scorecard.md`、`docs/red_team_backlog.md` + +**自動化驗證(即時執行)**: +- `artifacts/scripts/guard_status_validator.py` — 狀態守衛 +- `artifacts/scripts/guard_contract_validator.py` — 合約守衛 ✅ PASS +- `artifacts/scripts/validate_context_stack.py` — 上下文堆疊守衛 ✅ PASS(v2.0 時曾有 24 errors,已全數修復) +- `artifacts/scripts/repo_health_dashboard.py` — Repo Health Dashboard(即時 JSON) +- `.github/workflows/workflow-guards.yml` — CI pipeline(10 步驟) +- `.github/workflows/security-scan.yml` — pip-audit 依賴掃描(v2.1 新增) + +**執行痕跡**: +- 18 個 task(含 TASK-001 至 TASK-999)、58 commits、2 release tags(v0.3.0、v0.3.1) +- 9 個 GitHub Skills、2 個 custom agents、9 頁 wiki ## 一、Repo 結構概覽 -此 repo 不是以應用程式原始碼為中心,而是以 workflow framework 與 governance artifacts 為中心。 +此 repo 不是以應用程式原始碼為中心,而是以 **workflow framework 與 governance artifacts** 為中心。 | 區塊 | 主要內容 | 角色 | |---|---|---| | 根目錄 | `README*`、`AGENTS.md`、`CLAUDE.md`、`GEMINI.md`、`CODEX.md`、`BOOTSTRAP_PROMPT.md`、`OBSIDIAN.md` | 專案入口、agent 入口、bootstrap 指引 | -| `docs/` | orchestration、schema、state machine、premortem、red team、lightweight mode | 流程規範與制度文件 | +| `docs/` | orchestration、schema、state machine、premortem、red team、lightweight mode(13 檔) | 流程規範與制度文件 | | `docs/templates/` | `implementer/`、`tester/`、`verifier/`、`reviewer/`、`parallel/`、`blocking/` | subagent 任務模板 | -| `artifacts/` | `tasks/`、`research/`、`plans/`、`code/`、`verify/`、`status/`、`decisions/`、`improvement/`、`scripts/` | 流程執行痕跡與自動化腳本 | -| `.github/` | workflow、agents、repository profile | CI 與 GitHub 展示層 | -| `template/` | 幾乎完整鏡像 root 結構 | 新專案 bootstrap 範本 | -| `.obsidian/` | vault 設定 | 文件工作區整合 | -| `external/`、暫存目錄 | 外部內容與測試/演練殘留 | 非核心但會影響工作樹衛生 | +| `artifacts/` | `tasks/`(19)、`research/`(10)、`plans/`(15)、`code/`(13)、`verify/`(13)、`status/`(21)、`decisions/`(11)、`improvement/`(3)、`scripts/`(18)、`red_team/`(1) | 流程執行痕跡與自動化腳本 | +| `.github/` | `workflows/`(2)、`agents/`(2)、`skills/`(9)、`prompts/`(5)、`memory-bank/`(5)、`copilot-instructions.md`、`dependabot.yml` | CI、agent 定義、上下文系統、依賴更新 | +| `template/` | root 的 scaffold 鏡像(文件 + 骨架 artifacts) | 新專案 bootstrap 範本 | +| `wiki/` | 9 頁 GitHub Wiki 內容 | 對外文件 | +| `external/` | `hermes-agent/`(git submodule,大型 Python/CLI 專案) | 外部依賴 | +| `.obsidian/` | vault 設定 | Obsidian 文件工作區整合 | -從結構上看,repo 已明確區分出三個層次: +從結構上看,repo 已明確區分出 **四個層次**: -1. 規則層:`docs/`、`AGENTS.md`、各 agent 入口檔。 -2. 執行層:`artifacts/` 與 validator / red-team scripts。 -3. 發佈層:`README*`、`.github/`、`template/`、`OBSIDIAN.md`。 +1. **規則層**:`docs/`、`AGENTS.md`、各 agent 入口檔。 +2. **執行層**:`artifacts/` 與 validator / red-team scripts。 +3. **上下文層**:`.github/memory-bank/`、`.github/prompts/`、`.github/skills/`、`.github/agents/`。 +4. **發佈層**:`README*`、`.github/`、`template/`、`wiki/`、`OBSIDIAN.md`。 -這種分層清楚,對「可審核」、「可移植」、「可 bootstrap 到新 repo」很有幫助。 +相較 v1.x 評估,新增的「上下文層」是 v0.3.0 引入的重要結構升級。 ## 二、工作流機制盤點 -目前 repo 內的工作流能力不是只有文件宣告,而是已經有相當程度的落地。 - -| 能力 | 證據 | 評語 | -|---|---|---| -| Artifact-first | `docs/orchestration.md`、`docs/artifact_schema.md`、`artifacts/*` | 核心設計完整,且已有多個實際 task 留痕 | -| 狀態機管理 | `docs/workflow_state_machine.md` | 狀態與轉移規則明確,非法跳轉有明文禁止 | -| 角色分工 | `docs/subagent_roles.md`、`CLAUDE.md`、`GEMINI.md`、`CODEX.md` | 主控、研究、實作責任切分清楚 | -| Gate 驗證 | `guard_status_validator.py` | 不只是 soft guideline,而是可自動檢查 | -| Contract drift 防護 | `guard_contract_validator.py` | root / template / Obsidian / README 同步有機制保護 | -| Prompt regression | `.github/workflows/workflow-guards.yml`、對應 validator | 顯示 repo 已把 prompt 視為可回歸測試的資產 | -| Red-team | `docs/red_team_runbook.md`、`artifacts/red_team/latest_report.md` | 有演練機制,不只停在靜態規則 | -| Lightweight mode | `docs/lightweight_mode_rules.md` | 顯示流程已開始考慮效率與治理平衡 | -| Template discovery | `artifacts/scripts/discover_templates.py`、`docs/templates/` | 顯示系統已從人工引用模板走向可發現化 | - - +目前 repo 內的工作流能力已從「文件宣告」全面升級為「可驗證的執行系統」。 + +| 能力 | 證據 | 狀態 | 評語 | +|---|---|---|---| +| Artifact-first | `docs/orchestration.md`、`docs/artifact_schema.md`、`artifacts/*` | ✅ | 18 個 task、100+ artifacts 的實際留痕 | +| 狀態機管理 | `docs/workflow_state_machine.md` | ✅ | 8 狀態 + 合法轉移規則,guard 強制執行 | +| 角色分工 | `docs/subagent_roles.md`、`CLAUDE.md`、`GEMINI.md`、`CODEX.md` | ✅ | 主控、研究、實作三角分工 | +| Gate 驗證 | `guard_status_validator.py`(動態掃描全部 task) | ✅ | CI 自動檢查每一個 TASK-*.status.json | +| Contract drift 防護 | `guard_contract_validator.py` | ✅ | root / template 核心文件同步守衛 | +| Prompt regression | `prompt_regression_validator.py` + `drills/prompt_regression_cases.json` | ✅ | Prompt 視為可回歸測試的資產 | +| 上下文堆疊 | `validate_context_stack.py`(7 項檢查) | ✅ | v2.0 曾有 24 errors(template/skills 同步缺口),v2.1 已全數修復 | +| Red-team | `run_red_team_suite.py`(23 static + 2 live + 20 prompt) | ✅ | 完整演練機制含 scorecard | +| Repo Health Dashboard | `repo_health_dashboard.py`(`--json` / `--stale-days`) | ✅ | 即時全域 task coverage、stale、blocked aging | +| Lightweight mode | `docs/lightweight_mode_rules.md` | ✅ | 效率與治理平衡 | +| Template discovery | `discover_templates.py`、`docs/templates/` | ✅ | 模板可發現化 | +| Custom agents | `.github/agents/`(Autonomous Executor、Readonly Process Auditor) | ✅ NEW | 可重用的 agent 人格定義 | +| GitHub Skills | `.github/skills/`(9 個 skill) | ✅ NEW | 可組合的專業能力模組 | +| Wiki | `wiki/`(9 頁)+ `push-wiki.ps1` | ✅ NEW | 對外文件化,含自動推送機制(v2.1 改用 preflight + dynamic URL) | +| Supply-chain hardening | `dependabot.yml`、`security-scan.yml`、SHA-pinned actions | ✅ NEW | Dependabot 自動 PR、pip-audit CI 掃描、Actions SHA pin(v6.0.2/v6.2.0)| +| Release automation | `publish-release.ps1`、`github_publish_common.ps1` | ✅ NEW | gh CLI 發佈腳本含 preflight 檢查,與 push-wiki.ps1 共用認證模組 | +| Lightweight mode | `docs/lightweight_mode_rules.md` | ✅ | v2.1 新增 drafted→planned 轉移、釐清 verify artifact 不可省略 | +| KPI 追蹤 | `artifacts/metrics/kpi_sprint2.json`、`artifacts/metrics/kpi_sprint6.json` | ✅ NEW | 跨 sprint 效能與品質指標 | +| Decision Registry | `build_decision_registry.py` → `artifacts/registry/decision_registry.json` | ✅ | 決策可追溯 | + +### 即時 Dashboard 摘要(2026-04-17T12:01:16+08:00) + +| 指標 | 數值 | +|---|---| +| 總 Task 數 | 18 | +| 完成率 | 77.8%(14 done) | +| Blocked | 1(TASK-901,已歸檔) | +| Stale(>14 天) | 0 | +| 缺 Verify(有 code 但無 verify) | 0 | +| 進行中(researched / planned / research_ready) | 3(TASK-959, 962, 999) | + +### Artifact Coverage(即時) + +| 類型 | 覆蓋 | 缺口 | +|---|---:|---| +| task | 100% | — | +| status | 100% | — | +| plan | 83.3% | TASK-959, 962 未進入 planning | +| code | 77.8% | 正常——未到 coding 階段的 task 不需要 | +| verify | 77.8% | 與 code 1:1 對應,符合預期 | +| research | 55.6% | 部分 lightweight task 可跳過 research | +| decision | 55.6% | 非必要 artifact,僅在有重大決策時產生 | +| improvement | 16.7% | 僅在 Gate E 失敗或主動改善時產生 | ## 三、成熟度評估 -本報告以 5 級制評估: +本報告以 5 級制評估(CMM-inspired): -- Level 1: Initial -- Level 2: Repeatable -- Level 3: Defined -- Level 4: Managed -- Level 5: Optimizing +- Level 1: Initial — 無固定流程 +- Level 2: Repeatable — 有流程但依賴個人經驗 +- Level 3: Defined — 流程已文件化且標準化 +- Level 4: Managed — 流程有量化監控與自動執行 +- Level 5: Optimizing — 持續改善循環已制度化 ### 3.1 Repo 結構成熟度 -| 維度 | 評分 | 判斷 | -|---|---:|---| -| 目錄分層 | _/5 | | -| 文件入口清晰度 | _/5 | | -| 範本化程度 | _/5 | | -| 可發現性 | _/5 | | -| 工作樹衛生 | _/5 | | +| 維度 | v1.2 | v2.0 | 判斷 | +|---|---:|---:|---| +| 目錄分層 | 4 | 4.5 | 三層→四層(新增上下文層:agents、skills、prompts、memory-bank) | +| 文件入口清晰度 | 4 | 4.5 | 新增 wiki 9 頁 + 階段載入矩陣已成熟 | +| 範本化程度 | 5 | 5 | `template/` 完整鏡像 + contract guard 護欄 | +| 可發現性 | 4 | 4 | 文件量持續增長(13 docs + 9 skills + 5 prompts),仍需載入矩陣導航 | +| 工作樹衛生 | 4 | 4 | `.gitignore` 完善,無殘留暫存目錄 | +| 上下文系統 | — | 4 | NEW:memory-bank(5 檔)、prompts(5 檔)、skills(9 個)、agents(2 個),含自動化驗證 | +| 對外文件 | — | 4 | NEW:wiki 9 頁 + push-wiki.ps1 自動推送 | + +**Repo 結構整體評級:Level 4+ / Managed** -Repo 結構整體評級:**Level _ / ___**。 +結構已高度模組化,支援 bootstrap、同步驗證、上下文分層載入、與對外文件化。主要短板是文件量大,新手需要學習導航路徑。 ### 3.2 工作流成熟度 -| 維度 | 評分 | 判斷 | -|---|---:|---| -| 流程定義完整度 | _/5 | | -| Artifact schema 完整度 | _/5 | | -| 自動化驗證 | _/5 | | -| 實際採用程度 | _/5 | | -| CI 整合廣度 | _/5 | | -| 治理閉環能力 | _/5 | | -| 持續最佳化能力 | _/5 | | +| 維度 | v1.2 | v2.0 | 判斷 | +|---|---:|---:|---| +| 流程定義完整度 | 5 | 5 | Intake 到 Closure、blocked 與 Gate E 都有制度 | +| Artifact schema 完整度 | 5 | 5 | 8 類 artifact、欄位、狀態與品質要求完整 | +| 自動化驗證 | 4.5 | 5 | 新增 context stack validator(7 項檢查)、CI 10+1 步驟全涵蓋(v2.1 新增 security-scan workflow) | +| 實際採用程度 | 4 | 4.5 | 18 tasks × 多 artifact type = 100+ artifacts,橫跨 58 commits | +| CI 整合廣度 | 4.5 | 5 | 2 個 workflow:workflow-guards(10 步驟)+ security-scan(pip-audit)。Actions SHA-pinned + Dependabot 自動 bump | +| 治理閉環能力 | 4 | 4.5 | blocked → improvement → resume 的 PDCA + decision registry + KPI sprint tracking | +| 持續最佳化能力 | 4.5 | 5 | red-team/backlog/prompt regression + repo health dashboard + KPI sprint 追蹤(S2→S6 效能改善 -47.8ms) | +| 上下文管理 | — | 4 | NEW:分層式上下文(memory-bank / prompts / skills / agents),validator 自動檢查完整性與 cross-ref | +| 外部協作支援 | — | 3.5 | NEW:wiki、custom agents、skills,但尚無 contributor guide 或 onboarding automation | -工作流整體評級:**Level _ / ___**。 +**工作流整體評級:Level 4.5 / Managed(接近 Level 5 Optimizing)** + +相比 v1.2,CI pipeline 從 7 步驟擴展到 10 步驟,新增 context stack validation、KPI sprint tracking,工作流已具備量化改善的閉環。 ## 四、主要優勢 - +1. **制度完整且分層合理** + - `orchestration`、`artifact schema`、`state machine`、`subagent roles` 各自負責不同層次,沒有全部塞進單一大文件。 + - v2.0 新增上下文層(memory-bank / prompts / skills / agents),進一步將「知識」從「流程」中分離。 + +2. **規範已被程式化** + - 6 支 validator(status guard、contract guard、prompt regression、context stack、red team suite、repo health dashboard)代表核心規則已從文件走向執行。 + - CI pipeline 10 步驟全自動,無人工 gate。 + +3. **Template 與 root 同步有護欄** + - `template/` 作為 bootstrap scaffold 很完整,contract guard 檢查 drift。 + - `docs/orchestration.md` §9.6 已定義 Tier 1-5 同步責任邊界。 + +4. **重視失敗演練,而不只正向流程** + - 內建 red-team runbook(23 static + 2 live + 20 prompt drill),scorecard、backlog 完整。 + - KPI sprint tracking(S2→S6)提供跨時間的量化改善證據。 + +5. **已有真實運作痕跡** + - 18 個 task、100+ artifacts、54 commits、2 release tags。 + - 完成率 72.2%,0 stale、0 missing verify,表示流程不是紙上制度。 + +6. **上下文系統已制度化** *(v2.0 新增)* + - memory-bank 5 檔(artifact-rules、workflow-gates、prompt-patterns、project-facts、README)。 + - 9 個可組合 skills(security-review、quality-playbook、code-tour、agent-governance 等)。 + - 2 個 custom agents(Autonomous Executor、Readonly Process Auditor)。 + - `validate_context_stack.py` 自動驗證 cross-ref 完整性、frontmatter 合法性、名稱唯一性。 + +7. **對外文件已建立** *(v2.0 新增)* + - Wiki 9 頁,含 Getting Started、Workflow Overview、Artifact Schema、Agent Roles、Validator Commands、Context System、FAQ。 + - `push-wiki.ps1` 支援自動推送。 ## 五、主要風險與缺口 - +### 現存風險(v2.0 新發現) + +| # | 風險 | 嚴重度 | 說明 | +|---|---|---|---| +| ~~R1~~ | ~~template/skills 同步大幅落後~~ | ~~High~~ | ✅ **v2.1 已修復**:37 個 reference files 已同步至 `template/.github/skills/`,`validate_context_stack.py` 全數通過 | +| ~~R2~~ | ~~wiki Context-System 頁面空殼~~ | ~~Medium~~ | ✅ **v2.1 已修復**:新增 7 項檢查清單、Skills & Agents 層、正式驗證腳本路徑 | +| R3 | **單一 owner 風險** | Medium | 全部 18 task 的 owner 都是 Claude,無人類 reviewer 或第二 agent 參與。對真實多人團隊的可轉移性尚未被驗證。 | +| ~~R4~~ | ~~TASK-001 孤兒~~ | ~~Low~~ | ✅ **v2.1 已解決**:PR #1 關閉未合併,TASK-001 artifacts 不存在於 master,dashboard 未回報 | +| ~~R5~~ | ~~Coverage threshold 偏低~~ | ~~Low~~ | ✅ **已修復**:目前 validate coverage gate 為 100%,13 個 Python 模組 / 3118 stmts / 959 tests 全數 100%。 | +| ~~R6~~ | ~~外部依賴管理~~ | ~~Low~~ | ✅ **v2.1 已修復**:TASK-963 已完成 supply-chain hardening — Actions SHA pin(checkout v6.0.2、setup-python v6.2.0)、`dependabot.yml` 自動 PR、`security-scan.yml` pip-audit CI 掃描 | + +### 已解決風險(v1.x → v2.0 期間) + +| # | 原始風險 | 解決方式 | +|---|---|---| +| ~~R1~~ | CI 驗證覆蓋偏樣板化 | ✅ CI 已改為動態掃描 `TASK-*.status.json` | +| ~~R2~~ | 工作樹衛生不足 | ✅ `.gitignore` 已補齊所有暫存目錄 | +| ~~R3~~ | 文件存在局部一致性風險 | ✅ BOOTSTRAP_PROMPT.md 已對齊 subagent_roles.md | +| ~~R4~~ | Template 完整鏡像維護成本高 | ✅ orchestration.md §9.6 Tier 1-5 同步責任邊界 | +| ~~R5~~ | 治理指標以文件與單次驗證為主 | ✅ repo_health_dashboard.py + KPI sprint tracking | ## 六、整體判斷 ### 總結評級 -- Repo 結構成熟度:**_/5** -- 工作流成熟度:**_/5** -- 綜合評估:**Level _ / ___** +| 維度 | v1.0 | v1.2 | v2.0 | v2.1 | 趨勢 | +|---|---:|---:|---:|---:|---| +| Repo 結構成熟度 | 4.0 | 4.0 | **4.3** | **4.5** | ↑ supply-chain + template/skills 全同步 | +| 工作流成熟度 | 4.0 | 4.5 | **4.7** | **4.8** | ↑ 2 workflow CI + dependabot + drafted→planned | +| Code Review 綜合 | 4.0 | 4.5 | 4.5 | 4.5 | → 維持(見§八) | +| **綜合** | **4.0** | **4.3** | **4.5** | **4.6** | **Level 4.5+ / Managed → Optimizing** | ### 判斷摘要 - +這個 repo 是一套**成熟度高於多數內部工具、接近 Level 5 Optimizing** 的 workflow framework。 + +**已具備的關鍵特徵**: +- ✅ 結構四層分離(規則、執行、上下文、發佈) +- ✅ 100% 的 task / status artifact 覆蓋 +- ✅ 10 步驟全自動 CI pipeline(零人工 gate) +- ✅ 量化改善循環(KPI S2→S6:驗證速度改善 47.8ms、FP rate 0%) +- ✅ 紅隊演練機制(45 項 drill) +- ✅ 上下文分層管理(memory-bank / prompts / skills / agents) +- ✅ 對外文件(wiki 9 頁 + 雙語 README) +- ✅ 真實採用痕跡(18 tasks、54 commits、2 releases) + +**尚缺的 Level 5 要素**: +- ✅ ~~template/skills 同步自動化~~ — v2.1 已完成(37 檔同步 + validator 全 PASS) +- ✅ ~~Supply-chain hardening~~ — TASK-963 done(SHA pin + dependabot + pip-audit + release scripts) +- ⬜ 多 owner / 多人協作驗證 +- ✅ ~~Coverage target 從 45% → 100%~~ — 已達成 100%(13 個模組 / 3118 stmts / 959 tests) +- ⬜ Contributor onboarding automation ## 七、建議優先事項 - +### 立即行動(High Priority) + +| # | 行動 | 對應風險 | 預期效果 | +|---|---|---|---| +| ~~1~~ | ~~同步 `template/.github/skills/` 與 root~~ | ~~R1~~ | ✅ 已完成(37 檔同步,validator 全 PASS) | +| ~~2~~ | ~~補建 `TASK-001.status.json` 或將 TASK-001 歸檔移除~~ | ~~R4~~ | ✅ 已解決(PR #1 關閉,artifacts 不存在於 master) | + +### 短期改善(Medium Priority) + +| # | 行動 | 對應風險 | 預期效果 | +|---|---|---|---| +| ~~3~~ | ~~實作 TASK-963(supply-chain hardening:pin actions、pip-audit、release automation)~~ | ~~R6~~ | ✅ 已完成(TASK-963 done,CI security-scan 全綠) | +| 4 | ~~提升 unit test coverage threshold 至 80%~~ | ~~R5~~ | ✅ 已完成(51%→83%,410 tests,threshold 80%) | +| 5 | ~~審查 wiki `Context-System.md` 內容是否對齊 `validate_context_stack.py` 的 7 項檢查~~ | ~~R2~~ | ✅ 已完成(新增 7 項檢查清單 + Skills & Agents 層) | + +### 中期規劃(Low Priority) + +| # | 行動 | 對應風險 | 預期效果 | +|---|---|---|---| +| 6 | 建立 contributor onboarding script 或 tour(可用 code-tour skill) | R3 | 降低多人協作門檻 | +| 7 | 增加第二 owner 或 human reviewer 的 artifact 案例 | R3 | 驗證多人場景可行性 | +| 8 | PowerShell wrapper 加入 `-ErrorAction Stop` | — | 捕獲非 terminating error | --- @@ -131,73 +266,202 @@ Repo 結構整體評級:**Level _ / ___**。 | 腳本 | 行數(約) | 角色 | |---|---:|---| | `guard_status_validator.py` | ~1850 | 核心:artifact / state / scope drift / premortem / Gate E 驗證 | -| `guard_contract_validator.py` | ~250 | root ↔ template 同步守護 | -| `run_red_team_suite.py` | ~800+ | static + live + prompt 紅隊演練 | +| `guard_contract_validator.py` | ~300 | root ↔ template 同步守護 | +| `run_red_team_suite.py` | ~800+ | 23 static + 2 live + 20 prompt 紅隊演練 | +| `validate_context_stack.py` | ~350 | 上下文系統完整性驗證(7 項檢查) | +| `repo_health_dashboard.py` | ~200 | 全域 task / artifact 健康指標 | | `prompt_regression_validator.py` | ~180 | prompt 回歸測試引擎 | | `build_decision_registry.py` | ~250 | decision artifact → JSON registry | | `aggregate_red_team_scorecard.py` | ~110 | red-team report → 計分卡 | | `discover_templates.py` | ~100 | subagent 範本發現 | | `update_repository_profile.py` | ~90 | `.github/repository-profile.json` 管理 | | `validate_scorecard_deltas.py` | ~90 | reviewer delta 驗證 | +| `workflow_constants.py` | ~50 | 共用常數 | +| `test_guard_units.py` | ~8400 | validator / runner 單元與回歸測試主體 | +| `test_security_scans.py` | ~160 | `repo_security_scan.py` 的 secrets / static 回歸測試 | | `Invoke-CodexAgent.ps1` | ~120 | Codex CLI resilient wrapper | | `Invoke-GeminiAgent.ps1` | ~120 | Gemini CLI resilient wrapper | | `load_env.ps1` | ~12 | `.env` 載入 | +| `push-wiki.ps1` | ~80 | wiki 推送(v2.1 改用 preflight + dynamic URL) | +| `github_publish_common.ps1` | ~100 | 共用認證 / preflight helper(v2.1 新增) | +| `publish-release.ps1` | ~100 | GitHub Release 發佈腳本(v2.1 新增) | ### 8.1 代碼品質 #### 優點 - +1. **結構清晰,職責分離** + - 每支腳本都有明確的單一職責,沒有 god script。 + - `guard_status_validator.py` 雖然最長(~1850 行),但內部以 `validate_*`、`detect_*`、`parse_*` 系列函式組織,可讀性仍在合理範圍。 + +2. **型別標註完整** + - 所有 Python 腳本均使用 `from __future__ import annotations` 與 `typing` 模組。 + - 資料結構以 `@dataclass` 定義,語義清楚。 + +3. **常數集中管理** + - 狀態機規則(`LEGAL_TRANSITIONS`)、artifact marker(`MARKERS`)、premortem 規則等全部以常數表定義在檔案頂部,便於審查與維護。 + +4. **錯誤處理一致** + - 統一使用 `GuardError` exception 與 `ValidationResult(errors, warnings)` 模式。 + - CLI exit code 嚴格區分:0 = pass、1 = fail、2 = usage error。 + +5. **PowerShell wrapper 設計合理** + - `Invoke-CodexAgent.ps1` 與 `Invoke-GeminiAgent.ps1` 實作了 exponential backoff + model fallback 的多層韌性機制。 #### 可改進項目 | # | 類別 | 位置 | 說明 | 嚴重度 | |---|---|---|---|---| -| Q1 | | | | | +| Q1 | 複雜度 | `guard_status_validator.py` | 單檔約 1850 行。函式拆分尚可,但 `validate_artifact_presence()` 與 `detect_historical_diff_scope_drift()` 已偏長(各 ~80 行),可考慮拆成更小的子函式。 | Low | +| Q2 | ~~重複定義~~ | `guard_contract_validator.py` + `update_repository_profile.py` | ~~`REQUIRED_TOPICS` 與 `TOPIC_PATTERN` 在兩個檔案中重複定義。~~ **已解決** — 已提取共用常數至 `_shared_constants.py`。 | ~~Medium~~ ✅ | +| Q3 | 重複函式 | `guard_status_validator.py` + `run_red_team_suite.py` | `compute_snapshot_sha256()` 在兩個檔案中都有定義,簽章略有不同(一個接受 `Set[str]`,一個接受 `Sequence[str]`)。 | Low | +| Q4 | 硬編碼 | `run_red_team_suite.py` | `blocked_sample_source()` 硬編碼檢查 `TASK-902` / `TASK-901`,未來新增或移除 sample task 時容易遺漏。 | Low | +| Q5 | ~~缺少單元測試~~ | 全局 | ~~目前只有 red-team suite 作為 integration test。~~ **已解決** — `test_guard_units.py` 與 `test_security_scans.py` 合計 959 項 tests,覆蓋 validator、runner 與 repo security scan 的核心邊界;目前 coverage 100%,CI 以 `--cov-fail-under=100` 強制執行。 | ~~Medium~~ ✅ | ### 8.2 安全性 #### 優點 - +1. **GitHub API 呼叫安全** + - `collect_github_pr_files()` 使用 `urllib.parse.quote()` 做 URL 編碼,避免 injection。 + - token 從環境變數讀取(`GITHUB_TOKEN` / `GH_TOKEN`),不硬編碼。 + - API 版本 header 明確指定,降低不可預期行為。 + +2. **路徑穿越防護** + - `resolve_workspace_relative_path()` 明確檢查路徑不得以 `/`、`..` 開頭,且 resolve 後的路徑必須在 repo root 內(`relative_to()` 驗證)。 + +3. **JSON 解析安全** + - 所有 `json.loads()` 呼叫都有 `try/except json.JSONDecodeError` 處理。 + +4. **沒有 shell injection 風險** + - `subprocess.run()` 均使用 list 形式傳參,不走 `shell=True`。 #### 風險項目 | # | 類別 | 位置 | 說明 | 嚴重度 | |---|---|---|---|---| -| S1 | | | | | +| S1 | 敏感資訊洩漏 | `load_env.ps1` | `.env` 載入後使用 `Write-Host "Loaded: $varName"` 輸出變數名稱。雖然只輸出 key 不輸出 value,但在 CI log 中仍可能洩漏內部環境變數的名稱清單。 | Low | +| S2 | HTTP server 綁定 | `run_red_team_suite.py` | `github_pr_files_server()` 綁定 `127.0.0.1:0`(動態 port),僅用於短暫測試 fixture。安全設計合理,但無 request body size 限制、無超時設定。因為只用於本地測試且生命週期極短,實際風險很低。 | Low | +| S3 | archive 讀取 | `guard_status_validator.py` | `load_archive_snapshot()` 讀取使用者指定路徑的檔案內容。雖有路徑穿越防護(`resolve_workspace_relative_path`),但若 archive 檔案極大,可能造成記憶體壓力。缺少 file size 上限檢查。 | Low | +| S4 | temp 目錄殘留 | `run_red_team_suite.py` | `prepare_temp_root()` 使用 `.codex-red-team/` 且 `finally` 中呼叫 `shutil.rmtree()`,但 Windows 上若檔案被鎖定可能殘留(git status 已可見 permission denied 的 `.codex-red-team/` 和 `.tmp-red-team/`)。 | Low | ### 8.3 可維護性 #### 優點 - +1. **CLI interface 統一** + - 所有 main 腳本都使用 `argparse`,參數一致(`--root`、`--task-id`),學習成本低。 + +2. **Markdown 報告輸出標準化** + - `run_red_team_suite.py`、`aggregate_red_team_scorecard.py`、`prompt_regression_validator.py` 的輸出都是可機器解析的 markdown 表格。 + +3. **`discover_templates.py` 支援 JSON 輸出** + - 方便自動化工具消費,不限於人工閱讀。 + +4. **版本標記** + - `guard_status_validator.py` 有 `__version__`,有利於追蹤。 #### 可改進項目 | # | 類別 | 位置 | 說明 | 嚴重度 | |---|---|---|---|---| -| M1 | | | | | +| M1 | ~~.gitignore 缺漏~~ | `.gitignore` | ~~缺少 `.codex-red-team/`、`.tmp-red-team/`、`*.override_log.json` 等工作流產出。~~ **已解決** — `.gitignore` 已補齊所有工作流暫存目錄與 coverage 產出。 | ~~Medium~~ ✅ | +| M2 | PyYAML 依賴 | `discover_templates.py` | 唯一有外部依賴(`yaml`)的腳本,且在 import 失敗時直接 `sys.exit(1)`。其他腳本全部 stdlib only,這個依賴可能在 CI 或新環境上造成意外失敗。 | Low | +| M3 | ~~CI 覆蓋不足~~ | `.github/workflows/workflow-guards.yml` | ~~Status guard 只跑 TASK-900、TASK-950、TASK-951。~~ **已解決** — 已改為動態掃描 `artifacts/status/TASK-*.status.json`,覆蓋全部 task,並移除 `--allow-scope-drift` 啟用嚴格模式。 | ~~Medium~~ ✅ | +| M4 | ~~無 requirements.txt~~ | 全局 | ~~Python 腳本沒有 `requirements.txt`。~~ **已解決** — 已建立 `requirements.txt`(含 PyYAML pin),CI 可自動安裝。 | ~~Low~~ ✅ | +| M5 | PowerShell 無 -ErrorAction | `Invoke-*.ps1` | try/catch 可捕獲 terminating error,但非 terminating error(如 cmdlet warning)不會被攔截。 | Low | ### 8.4 綜合評分 -| 維度 | 評分 | 摘要 | -|---|---:|---| -| 代碼品質 | _/5 | | -| 安全性 | _/5 | | -| 可維護性 | _/5 | | -| **綜合** | **_/5** | | +| 維度 | v1.0 | v1.2 | v2.0 | 摘要 | +|---|---:|---:|---:|---| +| 代碼品質 | 4 | 4.5 | 4.5 | 維持。新增 `validate_context_stack.py`(350 行)、`repo_health_dashboard.py`(200 行),代碼品質一致。 | +| 安全性 | 4.5 | 4.5 | 4.5 | 維持。路徑穿越、shell injection、API token 處理均到位。 | +| 可維護性 | 3.5 | 4.5 | 4.5 | 維持。CI 10 步驟、requirements.txt、共用常數均穩定。 | +| **綜合** | **4** | **4.5** | **4.5** | **生產等級的 workflow toolchain。新增腳本品質一致,無退步。** | ### 8.5 建議行動優先順序 +| 優先 | 行動 | 狀態 | 效果 | +|---:|---|---|---| +| 1 | ~~補 `.gitignore` 條目~~ | ✅ 已完成 | git status 噪音消除 | +| 2 | ~~CI status guard 改為動態掃描~~ | ✅ 已完成 | CI 治理覆蓋 3 → 18 task | +| 3 | ~~提取共用常數~~ | ✅ 已完成 | `workflow_constants.py` 消除重複定義 | +| 4 | ~~加入 `requirements.txt`~~ | ✅ 已完成 | CI 可自動安裝依賴 | +| 5 | ~~為核心函式加 unit test~~ | ✅ 已完成 | 959 項 tests,coverage 100% | + +### 8.6 剩餘改進項目 + | 優先 | 行動 | 效果 | |---:|---|---| -| 1 | | | +| 1 | ~~對齊 `BOOTSTRAP_PROMPT.md` 與 `docs/subagent_roles.md` 的 Gemini/Codex 認證指引~~ ✅ 已完成 | 降低新使用者 onboarding 摩擦 | +| 2 | 維持 unit test coverage 100%(新增模組時同步補測試) | 強化回歸保護並避免 validate 退化 | +| 3 | PowerShell wrapper 加入 `-ErrorAction Stop` | 捕獲非 terminating error | +| 4 | ~~制定 `template/` 同步責任邊界說明~~ ✅ 已完成 | `docs/orchestration.md` §9.6 Tier 1–5 定義 | +| 5 | ~~將 `validate_context_stack.py` 的 template/skills 檢查結果降為 warning 或修正同步~~ ✅ 已完成 | 37 檔同步,errors 24→0 | + +--- + +## 九、v2.0 → v2.1 變更摘要(本次 session) + +### v2.1 新增/修復能力 + +| 能力 | 來源 | 影響 | +|---|---|---| +| Supply-chain hardening | TASK-963: `dependabot.yml`、`security-scan.yml`、SHA pin | 自動化依賴更新 + pip-audit CI 掃描 | +| Release automation | `publish-release.ps1`、`github_publish_common.ps1` | gh CLI 發佈腳本含 preflight 與 -WhatIf | +| Wiki preflight 改造 | `push-wiki.ps1` 重寫 + `github_publish_common.ps1` 共用 | Dynamic URL、5 階段 preflight、不再硬編碼 repo URL | +| Dependabot auto-bump | `actions/checkout` v4.3.1→v6.0.2、`setup-python` v5.6.0→v6.2.0 | Dependabot PR #3/#4 自動建立並合併 | +| template/skills 同步修復 | 37 個 reference files 同步至 `template/.github/skills/` | context stack errors 24→0 | +| drafted→planned 轉移 | `guard_status_validator.py` + `workflow_state_machine.md` + `lightweight_mode_rules.md` | Lightweight mode 現可直接 drafted→planned | +| Verify artifact 釐清 | `lightweight_mode_rules.md` | 釐清 verify artifact 不可省略(內容可精簡,文件不可缺) | +| CI pip-audit 修正 | `security-scan.yml`:`pip-audit` → `pip_audit` 模組名 | Security Scan workflow 修復 | +| 孤兒 gitlink 清理 | `.claude/worktrees/` 移除 + `.gitignore` 防護 | CI checkout 修復 | + +--- + +## 十、v1.x → v2.0 變更摘要 + +### 新增能力 + +| 能力 | 來源 | 影響 | +|---|---|---| +| 上下文堆疊驗證 | `validate_context_stack.py`(7 項檢查) | CI 新增 context stack validation 步驟 | +| Custom Agents | `.github/agents/`(2 個 agent 定義) | 可重用的 agent 人格與工具邊界 | +| GitHub Skills | `.github/skills/`(9 個 skill) | 可組合的專業能力模組 | +| Wiki | `wiki/`(9 頁) + `push-wiki.ps1` | 對外文件化 | +| KPI Sprint Tracking | `artifacts/metrics/kpi_sprint2.json`、`artifacts/metrics/kpi_sprint6.json` | 跨 sprint 量化改善證據 | +| Memory Bank Prompts | `.github/prompts/`(5 個 prompt) | context-review、remember-capture、pack-context 等 | +| Writing Style Unification | commit `aeada64` | 全部 MD 統一繁中(臺灣)、去 emoji | + +### 量化變化 + +| 指標 | v1.2 (2025-07) | v2.0 (2026-04) | v2.1 (2026-04) | 變化(v2.0→v2.1) | +|---|---:|---:|---:|---| +| Total Tasks | ~5 | 18 | 18 | → | +| Done Tasks | ~3 | 13 | 14 | +1(TASK-963) | +| Total Commits | ~20 | 54 | 58 | +4 | +| CI Workflows | 1 | 1 | 2 | +1(security-scan.yml) | +| CI Steps(workflow-guards) | 7 | 10 | 10 | → | +| Python Scripts | ~10 | 14 | 14 | → | +| PowerShell Scripts | ~3 | ~5 | 7 | +2(github_publish_common、publish-release) | +| Skills | 0 | 9 | 9 | → | +| Wiki Pages | 0 | 9 | 9 | → | +| Custom Agents | 0 | 2 | 2 | → | +| Release Tags | 0 | 2 | 2 | → | +| Context Stack Errors | — | 24 | 0 | -24(template/skills 同步修復) | +| Actions checkout | — | v4.3.1 | v6.0.2 | Dependabot auto-bump | +| Actions setup-python | — | v5.6.0 | v6.2.0 | Dependabot auto-bump | --- -## 九、修訂紀錄 +## 十一、修訂紀錄 | 日期 | 版本 | 變更摘要 | |---|---|---| -| | v1.0 | 初版評估 | +| 2025-07-17 | v1.0 | 初版評估:Repo 結構 4/5、工作流 4/5、Code Review 4/5(綜合 Level 4 Managed) | +| 2025-07-17 | v1.1 | 反映 session 改進成果:.gitignore 補齊、CI 動態掃描、共用常數提取、requirements.txt、255 項 unit test、repo health dashboard。工作流 4→4.5、可維護性 3.5→4.5、綜合 4→4.5(Level 4+ 接近 Level 5) | +| 2025-07-17 | v1.2 | 對齊 BOOTSTRAP_PROMPT.md 與 subagent_roles.md 的 Gemini 認證方式(GEMINI_API_KEY → OAuth);新增 orchestration.md §9.6 同步責任邊界(Tier 1–5)。§5 風險 5/5 已解決或緩解,§7 建議 5/5 已完成 | +| 2026-04-17 | v2.0 | 全面重新評估。新增上下文系統(memory-bank / prompts / skills / agents)、wiki 9 頁、KPI sprint tracking、custom agents、validate_context_stack.py。Task 數 5→18、commits 20→54、CI steps 7→10。發現 template/skills 同步落後(24 errors)。綜合 4.3→4.5(Level 4.5 Managed → Optimizing) | +| 2026-04-17 | v2.1 | 反映 session 內所有修復成果。template/skills 同步修復(37 檔,R1 ✅);TASK-963 supply-chain hardening 完成(SHA pin v6.0.2/v6.2.0 + dependabot + pip-audit CI + release scripts,R6 ✅);CI pip-audit 模組名修正;Dependabot PR #3/#4 合併;PR #1 關閉(不完整)並手動實作 drafted→planned 轉移 + lightweight mode 文件釐清。Done 13→14、commits 54→58、CI workflows 1→2、context stack errors 24→0。綜合 4.5→4.6 | +| 2026-04-18 | v2.2 | 反映 validate coverage 收尾:`test_guard_units.py` 與 `test_security_scans.py` 合計 959 項 tests,13 個 Python 模組 / 3118 stmts 全數 100%,CI coverage gate 維持 `--cov-fail-under=100`。 | diff --git a/template/docs/schemas/artifact-spec-code.md b/template/docs/schemas/artifact-spec-code.md index a3c22a0..5bc9f60 100644 --- a/template/docs/schemas/artifact-spec-code.md +++ b/template/docs/schemas/artifact-spec-code.md @@ -76,7 +76,7 @@ - `Known Risks`: 沒有時寫 `None`。 - `TAO Trace`: risk ≥ 3(plan `## Risks` 任一條 `Severity: blocking`)之 implementer / verifier dispatch **必填**;risk ≤ 2 或 lightweight / docs-only 任務可寫 `None`。schema 與必填欄位見 [docs/agentic_execution_layer.md §2](agentic_execution_layer.md)。回填既有 artifact 時須以 `Reconstructed from artifact history` 開頭,不偽造當時即時思考。 - `Blockers`: 沒有時寫 `None`。 -- `Diff Evidence`: 沒有時可省略或寫 `None`。目前 `guard_status_validator.py` 支援 `Evidence Type: commit-range` 與 `Evidence Type: github-pr`。 +- `Diff Evidence`: 一般情況沒有時可省略或寫 `None`。**條件必填(CHG-012 / HC-1 A2)**:若 clean task 之 closure(transition into `done`)其 `## Files Changed` 觸及 guard/EXACT_SYNC 敏感集(`guard_contract_validator.EXACT_SYNC_FILES` ∪ `artifacts/scripts/guard_*.py`、`run_quality_gates.py`、`workflow_constants.py`),則 `## Diff Evidence` 必填且不可為 `None`,否則 write-transition(verifying→done)fail-closed。此規則僅前向適用於新 transition,不回溯既有 done 任務。目前 `guard_status_validator.py` 支援 `Evidence Type: commit-range` 與 `Evidence Type: github-pr`。 - `commit-range`: 要求 immutable commit pinning:`Base Commit` 與 `Head Commit` 必須是完整 40 字元 git commit SHA;`Base Ref` 與 `Head Ref` 是可選便利欄位,只用於偵測 ref drift。`Diff Command` 應對應實際 replay 命令。若擔心長期 git objects retention 不足,可額外提供 `Archive Path` 與 `Archive SHA256`;兩者必須一起出現,`Archive Path` 必須是 repo-relative、UTF-8、每行一個 normalized relative path、排序後、LF 換行的 text file,`Archive SHA256` 則是該 archive file 原始 bytes 的 SHA-256。guard 只會在 local git replay 失敗時改用 archive fallback,且 archive 內容仍必須與 `Changed Files Snapshot` 完全一致。 - `github-pr`: `Repository` 必須是 `owner/repo`,`PR Number` 必須是正整數;`API Base URL` 可省略,省略時預設 `https://api.github.com`,若使用 GitHub Enterprise Server 或本地 fixture,可覆寫成其他 http(s) endpoint。guard 會透過 GitHub PR files API 逐頁抓取 changed files,public repo 可不帶 token;private repo 或 rate-limited 環境則應提供 `GITHUB_TOKEN` 或 `GH_TOKEN`。 - `Changed Files Snapshot`: 必須列出 replayed diff 或 provider response 的完整檔案清單(以逗號分隔)。 diff --git a/template/docs/schemas/artifact-spec-decision.md b/template/docs/schemas/artifact-spec-decision.md index 5a2603b..883b709 100644 --- a/template/docs/schemas/artifact-spec-decision.md +++ b/template/docs/schemas/artifact-spec-decision.md @@ -55,6 +55,42 @@ - Override_Reason: ``` +若 decision 涉及高風險或外部可見之變更(guard/schema/report/CI gate/預設值/可觀察輸出),建議額外提供(TASK-1108,Reversibility & Blast Radius / Separation of Duties / Least Privilege 三個治理視角之落點): + +```md +## Reversibility & Blast Radius +- Reversibility: reversible | partially_reversible | irreversible | unknown +- Blast Radius: local | module | repo | external_consumers | unknown +- Rollback Plan: +- Reviewer Independence: +- Least Privilege Notes: +``` + +`## Reversibility & Blast Radius` 規則:本區段為**可選**,無自動 validator 強制;`Reversibility` 與 `Blast Radius` 之 `unknown` 值視為「尚待查明」,不得等同安全、低風險或零風險,選填 `unknown` 時須於 `Reasoning` 補充查明計畫。本區段唯一既有消費者為後續審查者與週期性 architect review(見 `docs/sop/rule_lifecycle_audit.md`);未來若有自動化強制需求,須依實際使用資料另立 task 評估(Occam's Razor + Gall's Law:無消費者不強制、無使用資料不預先重機制化)。 + +若 decision 部分依據治理指標(firing_count/block_count/warning_count/pass_rate/coverage/evaluation_count/intervention_count 等)作成,或決策本身構成治理規則之建制變動,建議額外提供(TASK-1109,Campbell's Law / Lucas Critique 兩個治理視角之落點): + +```md +## Metrics Policy +- Campbell Risk: low | medium | high | unknown +- High Stakes Metric: true | false +- Gaming Vectors: + - +- Metric Interpretation: + +## Policy Regime +- Regime ID: +- Changed At: +- Changed By: +- Comparable To Previous: true | false +- Baseline Reset Required: true | false +- Adaptation Expected: + - +- Notes: +``` + +`## Metrics Policy` 規則:本區段為**可選**,適用於決策部分依據治理指標作成之情境;`Campbell Risk` 之 `unknown` 值視為「尚待查明」,不得等同 `low` 或安全,選填 `unknown` 時須於 `Reasoning` 補充查明計畫(與 `## Reversibility & Blast Radius` 之 `unknown` 語意一致);`Metric Interpretation` 必須寫明「指標為證據而非自動核准依據」之語意,不得留空;指標值本身不構成裁決之充分理由,不得單獨用以獎勵人為製造之 guard 觸發、警告壓制或淺層測試覆蓋。`## Policy Regime` 規則:本區段為**可選**,適用於決策本身構成治理規則之建制變動(CI gate、guard 定義、telemetry schema、model 角色、escalation 規則、pass/fail 門檻、report 格式或 prompt 政策之變更);`Comparable To Previous: false` 為預設安全假設,用以防止「新政策降低可見失敗即視為指標改善」之誤判,不代表該案例不重要。兩區段皆無自動 validator 強制,唯一既有消費者為後續審查者與週期性 architect review;未來若有自動化強制需求,須依實際使用資料另立 task 評估(Occam's Razor + Gall's Law)。 + 何時必須建立 decision artifact: - 研究結果互相衝突 diff --git a/template/docs/security_cadence.md b/template/docs/security_cadence.md index 076e571..a07fe1e 100644 --- a/template/docs/security_cadence.md +++ b/template/docs/security_cadence.md @@ -38,13 +38,39 @@ issue 自動建立後 30 天為建議 deadline;workflow 不執行實際 threat | 欄位 | 內容 | |---|---| -| Trigger | `.github/workflows/security-scan.yml`(`on: pull_request, push to master, workflow_dispatch`) | -| Cadence | per PR / per push to master / 手動 | -| Artifact Destination | GitHub Actions log;pip-audit 之 `pip-audit-report.json` 落於 run 之 group output | +| Trigger | `.github/workflows/security-scan.yml`(`on: pull_request, push to master, workflow_dispatch, schedule cron "0 6 * * 1"`) | +| Cadence | per PR / per push to master / 手動 / 每週一 06:00 UTC(schedule) | +| Artifact Destination | GitHub Actions log;pip-audit 之 `pip-audit-report.json`、SBOM `sbom.cdx.json`、SAST findings 之 `$GITHUB_STEP_SUMMARY` | | Owner | CI 自動 + PR reviewer | -| Components | (a) `pip-audit` 掃 `requirements.txt` CVE;(b) `repo_security_scan.py secrets` 掃 hardcoded credentials;(c) `repo_security_scan.py static` 掃 focused static rules | +| Components | (a) `pip-audit` 掃 `requirements.txt` CVE(SCA, PW.4);(b) `repo_security_scan.py secrets`;(c) `repo_security_scan.py static`;(d) `python-sast`(advisory SAST → `sast_gate.py`,PW.7);(e) `sbom`(`cyclonedx-py` resolved-env → `sbom_gate.py`,PS.3.2);(f) `security-txt`(`security_txt_gate.py` 驗 RFC 9116 intake,RV.1.3;step-level present-only);(g) `release-integrity`(`snapshot_manifest.py verify` regenerate-diff + `release_gate.py` 結構驗 `.well-known/release-manifest.json`,PS.2;step-level guarded by `.council-forge-source-repo`) | -continuous 層由既有 workflow 落地(前置 task TASK-* 已建立),本 task 不變動。任何 hardening(fail-on-severity threshold / SBOM 整合 / license audit)屬 future task 範圍。 +continuous 層由既有 workflow 落地。**schedule cron 之要**:使 `security-txt` job 週期跑,於 `.well-known/security.txt` 之 `Expires` 無聲過期時 fail-closed(即便無 code 變動)。任何 hardening(fail-on-severity threshold / release-signing)屬 future task。 + +## Vulnerability Disclosure & Response(P8-D) + +> **映而不疊**:本節為 cross-ref;內容主於各專檔,此處唯列其關聯與 cadence。 + +| 維度 | 真實來源 | Cadence / Gate | +|---|---|---| +| Disclosure intake | [`.well-known/security.txt`](../.well-known/security.txt)(RFC 9116)+ GitHub private vulnerability reporting | `security-txt` job(per-PR + 每週 schedule),`security_txt_gate.py` fail-closed 驗 well-formed + 未過期 | +| Disclosure policy | [`../SECURITY.md`](../SECURITY.md)(CVD:intake / best-effort ack / 90-day / safe-harbor / 自訂 patch-prioritization) | 文件(policy;human-review 守其語義) | +| Incident response | [`incident-response-runbook.md`](incident-response-runbook.md)(NIST SP 800-61,RV.3 root-cause→PROCESS_LEDGER) | 文件(process) | + +SSDF 對應:RV.1.3(disclosure policy/intake)、RV.2(assess/prioritize,自訂非 NIST 數值)、RV.3(root-cause)——皆 `partial`/`covered` 見 [`ssdf-mapping.md`](ssdf-mapping.md)。 + +## Release Integrity(PS.2 / P8-D2) + +> **映而不疊**:本節為 cross-ref;機制主於 `release_gate.py`/`snapshot_manifest.py`、簽章 key-lifecycle 之 [`security/release-signing.md`](security/release-signing.md),與 [`templates/security/README.md`](templates/security/README.md) 之「Release integrity」節。 + +| 維度 | 真實來源 | Cadence / Gate | +|---|---|---| +| 自身 release surface(propagated `template/` snapshot) | [`../.well-known/release-manifest.json`](../.well-known/release-manifest.json)(content-addressed,`snapshot_manifest.py` 生)+ propagate 時寫入各下游之 `.council-forge/release-snapshot.json` | `release-integrity` job(per-PR + 每週 schedule,guarded by `.council-forge-source-repo`):`snapshot_manifest.py verify` regenerate-diff + `release_gate.py` 結構驗 | +| 簽章驗證(Example 2/3,P8-D3) | [`security/release-signing.md`](security/release-signing.md)(key-lifecycle)+ [`../.well-known/release-manifest.json.asc`](../.well-known/release-manifest.json.asc) + [`../.well-known/release-signing.pub`](../.well-known/release-signing.pub)(operator 刊布,現未填) | `release-integrity` job 之 native `gpg --verify` step(VALIDSIG **精確 field** 綁 `EXPECTED_SIGNING_FINGERPRINT`;`if` 唯 sentinel·**armed-triad**:pin/`.asc`/pubkey 全缺方 no-op,任一在則全須在否則 fail-closed);**signing-process periodic review(Example 3)入本 cadence** | +| 下游 release(.NET/Tauri) | [`templates/security/downstream-release-integrity.yml`](templates/security/downstream-release-integrity.yml)(native verify 主驗:`dotnet nuget verify`/`gh attestation verify`/`minisign -V`) | opt-in / local(map-don't-recreate;release_gate 為 offline 結構 pre-check) | + +SSDF 對應:**PS.2** 由 `gap` 升 **`partial`**(Example-1 刊布**可復現**雜湊供 acquirer)。**誠實上限 partial 非 covered**:P8-D3 已**備齊且經測**之簽章驗證機制(native `gpg --verify` + fingerprint-pin + key-lifecycle policy Example 3 + ephemeral-key 端到端測),然 `covered` 唯繫 operator 行 key 生成 + 真簽章 + **out-of-band 刊布** pubkey/fingerprint + 首驗——**故 PS.2 仍 partial(mechanism-implemented, operator-action-dependent;不 flip)**。**PS.2 ≠ PS.3.2(SBOM)不 double-count**。release_gate 驗結構非密碼學(簽章真驗交 native gpg + human-review,accepted residual;同-repo fingerprint pin 之殘餘見 [`security/release-signing.md`](security/release-signing.md))。 + +continuous 層之 `release-integrity` job 以 **regenerate-diff** 防刊布 manifest 靜默漂移於其所述之樹(僅證 HEAD 一致),並以 native `gpg --verify`(VALIDSIG 綁簽章者)驗簽章;schedule 使其週期受檢,**signing-process 之 Example-3 periodic review 入本 cadence**。covered 之 operator key 儀式(生 key / 真簽 / out-of-band 刊布 / 解 no-push)與 cross-target staged-transaction rollback 屬 future task。 ## Setup Steps diff --git a/template/docs/sop/dispatch_implementation.md b/template/docs/sop/dispatch_implementation.md index 0e6616c..2e85d47 100644 --- a/template/docs/sop/dispatch_implementation.md +++ b/template/docs/sop/dispatch_implementation.md @@ -18,3 +18,11 @@ ``` > Prompt token-cost 慣例(inline vs path-reference vs temp file vs fabrication-prone):詳見 `docs/dispatch_prompt_discipline.md`。 + +### Fallback tier 產出之驗收紀律(TASK-1106) + +wrapper 之 fallback tier(後位模型,如 `gpt-5.4-mini`)產出**預設不可信**:驗收必須逐 tier 讀 dispatch log 分辨各 attempt 實際行為,關鍵宣稱(驗證結果、sources、Files Changed)以命令直驗,不採信口頭回報;credits 中斷後接手之 tier 尤然。出處:TASK-1105 Bug-B3——mini 於 shell 封鎖下未驗證覆寫 code artifact 並引用 fabricated sources(見 `artifacts/code/TASK-1105.code.md` §Post-Dispatch Amendment)。 + +### Dispatch 逾時重派紀律(TASK-1112) + +前次 `Invoke-CodexAgent.ps1` / `Invoke-GeminiAgent.ps1` dispatch 若因**工具呼叫逾時**(harness timeout,而非 wrapper 自身回報結束)而中斷,caller 重新派發前必須先確認底層 process 是否仍存活(例如 `Get-Process -Name codex,node`,或觀察目標檔案 mtime 於數分鐘內是否穩定),確認確實無殘留 process 後才可重派;不得將「工具呼叫逾時」直接等同「dispatch 已終止」。出處:TASK-1107——前景 dispatch 逾時後未確認即發起併發背景 dispatch,兩個底層 process 同時 `git stash`/`stash pop`,導致 conflict markers 與測試方法重複定義(見 `artifacts/improvement/TASK-1107.improvement.md`)。 diff --git a/template/docs/sop/rule_lifecycle_audit.md b/template/docs/sop/rule_lifecycle_audit.md new file mode 100644 index 0000000..8d95b1d --- /dev/null +++ b/template/docs/sop/rule_lifecycle_audit.md @@ -0,0 +1,54 @@ +# Rule Lifecycle Audit + +本 SOP 定義 workflow 規則的最小盤點循環:先看資料,再查 provenance,最後只記錄可回放的裁決。 + +## Purpose + +- 適用對象:guard 規則、validator pattern、templates、wrapper flags、workflow 條款,以及本 SOP 自身。 +- 目標:把「該不該拆、該不該放寬、為什麼還留著」收斂成固定三步,避免 ad-hoc 增生。 +- 本 SOP 只定義盤點方法;不得要求新增腳本、guard、artifact type 或自動化強制。 + +## Trigger + +- 當 [PROCESS_LEDGER](../../artifacts/improvement/PROCESS_LEDGER.md) 條目達 N=10 倍數時,同批執行本盤點;N=10 定義與節奏權威仍以 [architecture-synthesizer](../templates/architecture-synthesizer/TEMPLATE.md) 的 Trigger 為準。 +- 使用者可隨時手動發起,不必等待 N=10。 + +## Step 1: Occam Pass + +- 先讀:`artifacts/improvement/RELAXATION_LOG.md`、`artifacts/improvement/PROCESS_LEDGER.md`、`docs/templates/archive/README.md`、`docs/red_team_backlog.md`,以及最近的 Guard Exception / warning 證據。 +- 把候選規則列入待查,只接受可見訊號:長期零使用、重複放寬、長期未動工、前提已消失、或同一例外反覆出現。 +- 此步只找候選,不做裁決;沒有資料就不猜。 +- 使用數據只產生候選,不產生裁決——零使用不等於零價值(保險機制平時即零觸發);裁決一律過 Step 2 之 provenance 檢查。 +- 候選訊號亦包含(TASK-1108):高 blast-radius 變更缺 rollback/migration notes、僅以單一指標作為移除唯一理由、guard 被刪除卻無替代機制或 decision 記錄、欄位查無消費者(unknown consumer——unknown consumer ≠ no consumer,不得逕以此視為安全)。 +- 評估候選訊號時(TASK-1109,Campbell's Law):不得以原始指標值(如 firing_count、pass_rate、coverage)直接作為安全/價值/品質之證明;不得獎勵人為製造之 guard 觸發、警告壓制、淺層測試覆蓋,或僅改善指標而未降低實際風險之變更。 + +## Step 2: Chesterton Gate + +| Verdict | 何時使用 | 最小要求 | 動作 | +|---|---|---|---| +| `keep` | 規則仍在攔真實事故,或成本低但保護面仍有效 | 找得到現行風險或歷史事故來源 | 原規則不動,補一句可驗證理由 | +| `relax` | 規則目的仍成立,但當前字面過嚴、誤傷穩定高於收益 | 找得到放寬前後差異與觸發案例 | 只縮到足以消除誤傷,不順手擴 scope | +| `retire` | 前提已消失、替代機制已接手,且撤回成本低 | 找得到前提消失或替代證據 | 移除或歸檔,並留下可復活路徑 | +| `open` | 查無 provenance,或現有證據不足以判定 keep / relax / retire | 缺口本身要可指認 | 不拆也不加碼,只記錄缺口待下輪 | + +- `open` 是 fail-closed 的盤點裁決:先停在記錄,不用推測補洞;scope-drift guard Layer-1(2026-07-02)為先例。 +- `retire` 若對象是 template,復活路徑預設記 `git mv docs/templates/archive/ docs/templates/`;不適用時寫 `N/A`。 +- 同型 detect-only 違規(如 dispatch write-scope / RACI 警告)連續被人工接受達 3 次:當輪必須裁 `relax`(承認規則過嚴、修規則字面)或轉強制(如 dispatch 顯式傳 `-AutoRestore`),不得停留於 detect-and-accept(Normalization of Deviance 防範)。 + +## Step 3: Record + +- 每次盤點只追加,不覆寫既有紀錄。 +- 最低記錄格式如下,放在當次 decision / improvement / verify 附錄或同批盤點筆記中: + +| Rule / Path | Verdict | Provenance | Why | Revival Path | +|---|---|---|---|---| +| `docs/X.md` | `keep` | `docs/Y.md:12` | 一句話理由 | `N/A` | + +- `Provenance` 要寫可 grep 回放的 citation;查無者明寫 `provenance: unrecorded`。 +- 若 `RELAXATION_LOG` 累積達 3 筆以上,當次 closure 需升級 architect review。 + +## Guardrails + +- 本 SOP 自身列入每輪盤點對象。 +- 若 N=10 軌長期未觸發,下一輪盤點必須檢討是否改綁 unified audit。 +- 任何較複雜方案若不能比簡單方案多守住安全性、正確性或可觀測性,維持較小方案。 diff --git a/template/docs/subagent_roles.md b/template/docs/subagent_roles.md index df5c6c1..a2e070c 100644 --- a/template/docs/subagent_roles.md +++ b/template/docs/subagent_roles.md @@ -39,6 +39,8 @@ - 測試、驗證、review 類工作優先採 read-heavy 模式(避免 R 衝突)。 - 多個 subagents 可平行讀取,但不可平行修改相同檔案(R 不可分割)。 - A 始終由 Claude 承擔最終驗收責任,即使 R 為其他代理。 +- 高風險變更(涉及 guard、schema、CI gate 或相容契約)之 author 不得為唯一審查者,須有 Council Reviewer(見 §5.1.3)或獨立 agent session 之 review 記錄(Separation of Duties,TASK-1108)。 +- 破壞性操作(guard 刪除、CI 放寬、secret 變更、schema-breaking 變更)需經 `guard_status_validator.py --override --override-approver` 或使用者明確核准方可執行(Least Privilege,TASK-1108)。 ### 1.4 有疑義先阻塞 @@ -51,9 +53,9 @@ 必須回報 blocked,不得自行腦補補完。 -## 2. 角色總表(索引) +## 2. 角色總表 -RACI 與 agent capability 矩陣已拆分至 [docs/raci-matrix.md](raci-matrix.md)(原 `docs/subagent_roles.md` §2)。 +RACI 與 agent capability 矩陣之單一真源為本檔 §2;[docs/raci-matrix.md](raci-matrix.md) 僅保留 §2.1 TAO Trace 必要程度表(此檔獨有)。 | 角色 | |---| @@ -76,6 +78,7 @@ RACI 與 agent capability 矩陣已拆分至 [docs/raci-matrix.md](raci-matrix.m | Tester | Codex subagent | test | -- (Codex/Claude A) | code | -- | task, plan, code | test | | Verifier | Codex subagent 或 Claude 控制下代理 | verify | -- (Claude A) | code / test | -- | task, code, test | verify | | Reviewer | Codex subagent | review notes | -- (Claude A) | plan / code | -- | task, plan, code | review 摘要或 decision 建議 | +| Codex Reviewer (Council) | Codex subagent (Council) | review notes (3 model votes) | Claude(triage) | plan / code / git diff | -- | git diff | `artifacts/reviews/-.md` | 註:若你想維持最小集合,可先不建立獨立 review artifact,而把 reviewer 結果納入 decision log 或 verify artifact 的 evidence 區段。 @@ -575,4 +578,3 @@ Reviewer 是風險與品質代理,負責從可維護性、回歸風險、架 代理可以換,模型可以換,CLI 可以換。 真正不能亂的是責任邊界、artifact contract、state transition。 - diff --git a/template/docs/subagent_task_templates.md b/template/docs/subagent_task_templates.md index 3c820a4..c4b855c 100644 --- a/template/docs/subagent_task_templates.md +++ b/template/docs/subagent_task_templates.md @@ -16,6 +16,8 @@ | Memory Curator | `docs/templates/memory-curator/TEMPLATE.md` | Gemini CLI | closure | | Blocking | `docs/templates/blocking/TEMPLATE.md` | Any | any | +> 已歸檔:`adr` / `debug` / `rtm` / `srs` 四個範本因零 dispatch(建立後約 2 個月無實際派發)已移至 `docs/templates/archive/`(見該目錄 `README.md`);`discover_templates.py` 之單層掃描與本索引不再列出。取回方式見 archive README。 + --- ## 設計原則 diff --git a/template/docs/templates/architecture-synthesizer/TEMPLATE.md b/template/docs/templates/architecture-synthesizer/TEMPLATE.md index b7a744d..2c1e9ef 100644 --- a/template/docs/templates/architecture-synthesizer/TEMPLATE.md +++ b/template/docs/templates/architecture-synthesizer/TEMPLATE.md @@ -137,4 +137,5 @@ emit(Gemini 吐出 draft 文字;經 Claude / Codex 審核後寫入 `.github/ ## Trigger - 自動:[artifacts/improvement/PROCESS_LEDGER.md](../../../artifacts/improvement/PROCESS_LEDGER.md) 條目達 N=10 倍數時,由 Claude 或 ledger 計數腳本主動 dispatch。 +- 同批:[rule lifecycle audit](../../../docs/sop/rule_lifecycle_audit.md) 於同次 N=10 盤點執行;該 SOP 只盤點規則增刪與放寬,不重複定義本 Trigger。 - 手動:使用者於任意時刻請 Claude 執行(如 sprint review、季度復盤)。 diff --git a/template/docs/templates/adr/TEMPLATE.md b/template/docs/templates/archive/adr/TEMPLATE.md similarity index 100% rename from template/docs/templates/adr/TEMPLATE.md rename to template/docs/templates/archive/adr/TEMPLATE.md diff --git a/template/docs/templates/debug/TEMPLATE.md b/template/docs/templates/archive/debug/TEMPLATE.md similarity index 100% rename from template/docs/templates/debug/TEMPLATE.md rename to template/docs/templates/archive/debug/TEMPLATE.md diff --git a/template/docs/templates/rtm/TEMPLATE.md b/template/docs/templates/archive/rtm/TEMPLATE.md similarity index 100% rename from template/docs/templates/rtm/TEMPLATE.md rename to template/docs/templates/archive/rtm/TEMPLATE.md diff --git a/template/docs/templates/srs/TEMPLATE.md b/template/docs/templates/archive/srs/TEMPLATE.md similarity index 100% rename from template/docs/templates/srs/TEMPLATE.md rename to template/docs/templates/archive/srs/TEMPLATE.md diff --git a/template/docs/workflow_state_machine.md b/template/docs/workflow_state_machine.md index 02ccf88..d72951e 100644 --- a/template/docs/workflow_state_machine.md +++ b/template/docs/workflow_state_machine.md @@ -135,6 +135,16 @@ blocked > 例:TASK-1001(v3.4 多階段任務)之 canonical AC 經 TASK-1011 reconcile、AC-5b 經 TASK-1095 resolved,全 AC 有 evidence 而自身無 plan/code → 處置為 superseded-via-reconciliation terminal(見 `artifacts/decisions/TASK-1001.decision.md` §Closing Amendment)。 +**(c) abandoned-via-ruling terminal(棄置終態)**:任務標的已消失或經 commander/human ruling 裁定**不再 resume**,本身無工作可續且**無 successor 承載其 obligation**(與 (b) 之關鍵區隔),為一經裁定之**永久棄置終態**(非待解、非 superseded)。識別條件(**三者全須**滿足): + +1. 對應 decision artifact(Decision Class = `risk-acceptance` 或同級)明載 ruling 與**不 resume 理由**; +2. status.json `blocked_reason` 以 `ABANDONED` 起首並含 ruling 日期; +3. **無** `superseded_by`/successor 承載義務(與 (b) 之關鍵區隔)。 + +此別語義同 (b):**不發生任何 exit/resume 轉移**,state **維 `blocked` 作為 terminal disposition**,**Gate-E 對其 N/A(非「繞過」)**。**限縮**:僅 commander/human ruling + decision artifact 方可適用;一般 stuck 任務(無 ruling)**不得**藉此別繞 Gate-E。 + +> 例:TASK-901(標的 `external/Wino-Mail/` 自 workspace 移除)經主公 2026-06-13 裁 abandon → status `blocked_reason` 標 `ABANDONED (commander ruling 2026-06-13)`、無 successor(見 `artifacts/decisions/TASK-901.decision.md` §Amendment (2026-06-13))。 + ## 6. 強制規則 1. 每次狀態變更必須更新 status.json