Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions BACKLOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,29 @@ alternative 數」三欄,缺記錄本身即為協定失敗而非歧義。參
reviewer-side duty 已要求提出者載明符合哪些條件,author side 先前沒有對稱義務,
該對稱化屬該 repo 的獨立變更,不在本票 scope。

**Update 2026-08-26(第二次讀數;票維持 active)**:對稱記錄規則自 pr:#530
(2026-08-25 生效)起的證據窗已累積 12 個 merged PR,遠超「觀察 2-3 個」的門檻。
逐一比對後找到 2 個合格實例——都是同一位執行者(本 agent)自己交付的 PR:pr:#539
因 gate finding 新增 7 個永久 regression case、pr:#541 因 gate finding 新增 2 個
永久測試函式,兩張 PR body **皆完全沒有**依規則寫「符合哪些准入條件」這一行。

讀數:合格實例 2 個,admit 數(附准入條件記錄)= 0,alternative 數 = 0,**缺記錄
數 = 2**。

**判定**:這次不是「B 恆為 0 的三種情形分不清楚」(上次讀數已排除這個病灶),而是
第三種、更根本的情形——**規則存在且無歧義,但執行者在動筆寫 PR body 的當下沒有
意識到要查它**。純文字提醒(寫在 Step 2.5,PR body 是在後面的 Step 4 才組裝)在
兩次連續合格實例上都沒有被觸發,證明「靠執行者記得回頭查一段前面讀過的規則」這個
機制本身不可靠,不是這次剛好疏忽。

**處置**:把 Step 4 的 PR body 樣板本身加一個 `Permanent test admissions:` 欄位
(原樣板只有 `Refactor/reuse audit`/`Final verdict`/`Full suite` 等既有欄位,
從缺永久測試這一項)。樣板本身是執行者組裝 PR body 時實際會複製的文字,欄位缺席
會讓遺漏顯性化(要嘛填實際記錄、要嘛明寫 `none`),不必再依賴幾個段落之前那句
散文提醒。新增對應回歸測試斷言樣板含這個欄位。A/B 讀數已可信(上次讀數已解決),
故本票仍不結案的理由改變:現在是要觀察「樣板改結構之後,缺記錄事件是否消失」,
而非「A/B 本身能否讀出訊號」。下次讀數起看第四欄——**樣板生效後的缺記錄次數**。

**Non-goals**: 不設 `max_full_review_rounds` 輪數上限——與 `commands/ship.md`
「round count 不是停止條件」直接衝突,且 [[CC-544]] 已證明放寬 gate 收斂條件會被
qa-tester/risk-reviewer 連擋並全數 revert。減量要從 finding 端做,不是從輪數端。
Expand Down
11 changes: 11 additions & 0 deletions commands/ship.md
Original file line number Diff line number Diff line change
Expand Up @@ -315,13 +315,24 @@ gh pr create --title "<type>(<ticket-id>): <short summary>" --body "$(cat <<'EOF
- Rounds: <N>
- Final verdict: GO
- Result file: <path from the last /pr-gate relay>
- Permanent test admissions: <one line per finding whose remedy was assessed against Step 2.5 — admitted lines name the criteria met, alternative lines name the alternative taken and why; `none` ONLY when no finding this round needed the assessment at all>
- Full suite: <passed count and authoritative result artifact>

Ticket: <ticket-id>
EOF
)"
```

**The "Permanent test admissions" line is not optional filler** — Step 2.5
required this record at the point each finding was remediated, and this
template field exists so composing the PR body forces a check for it: a
gate round with no finding whose remedy could have been a new permanent
test gets `none`; every other round gets one line per such finding, whether
it was admitted or resolved by a recorded alternative — `none` never stands
in for an alternative-path finding's own record, and the citation is carried
over from Step 2.5, not re-derived or skipped because that paragraph is
several screens back by now.

Do not merge. GO is not merge authorization — merge only when the user
explicitly says so.

Expand Down
3 changes: 3 additions & 0 deletions tests/shell/test-commands.sh
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,9 @@ should_run "ship: any other NO-GO continues without asking" && assert_file_conta
# PR template
should_run "ship: opens PR via gh pr create" && assert_file_contains "ship: opens PR via gh pr create" "$SHIP" "gh pr create" && pass "ship: opens PR via gh pr create"
should_run "ship: PR body template records gate rounds and verdict" && assert_file_contains "ship: PR body template records gate rounds and verdict" "$SHIP" "Final verdict" && pass "ship: PR body template records gate rounds and verdict"
should_run "ship: PR body template has a slot for permanent test admission decisions" && assert_file_contains "ship: PR body template has a slot for permanent test admission decisions" "$SHIP" "Permanent test admissions:" && pass "ship: PR body template has a slot for permanent test admission decisions"
should_run "ship: admission template requires alternative-path lines too, not just none" && assert_file_contains "ship: admission template requires alternative-path lines too, not just none" "$SHIP" "alternative lines name the alternative taken and why" && assert_file_contains "ship: admission template requires alternative-path lines too, not just none" "$SHIP" "none\` ONLY when no finding this round needed the assessment at all" && pass "ship: admission template requires alternative-path lines too, not just none"
should_run "ship: admission template explanation forbids none standing in for an alternative" && assert_file_contains "ship: admission template explanation forbids none standing in for an alternative" "$SHIP" "\`none\` never stands" && assert_file_contains "ship: admission template explanation forbids none standing in for an alternative" "$SHIP" "in for an alternative-path finding's own record" && pass "ship: admission template explanation forbids none standing in for an alternative"
should_run "ship: GO is not merge authorization" && assert_file_contains "ship: GO is not merge authorization" "$SHIP" "GO is not merge authorization" && pass "ship: GO is not merge authorization"
should_run "ship: no CC ticket references" && assert_not_contains "ship: no CC ticket references" "$SHIP" "CC-[0-9]"
# git publication path: branch creation and push are the only side effects before PR creation
Expand Down