test(W7h): drop issue-number pins in land-and-deploy-postfail, match guards case-insensitively

W7h (t09 F12, F13). One test file.

Removed assertion groups:
- `cli/cli#3442` / `cli/cli#13380` pins (t09 F12). Invariant: none of its
  own (upstream archaeology; the IDs stay in the template, only the pin goes).
  The behavior they decorated, "after any non-zero `gh pr merge` exit, query
  authoritative state before retrying", is now a kept free meaning check.
- `Universal invariant` label pin. Invariant: query-before-retry. Remaining
  protection: the new case-insensitive check
  `/non-zero exit from `gh pr merge`, query authoritative PR state before retrying/i`
  (stronger: the mutation that inverts the rule now goes red; the old test
  stayed green).

Loosened to case-insensitive meaning checks (kept, W7 keep list, data-loss
and destructive-op guards): STOP worktree cleanup without removing, no
`--force`, primary working tree never removed, CLOSED -> stop, never replay a
merge after MERGED, one direct fallback, no fallback from a direct attempt,
the OPEN/no-auto/no-queue fallback precondition, branch-absent vs check-failed
messages. Gate-tier E2E also covering the flow: land-and-deploy-workflow
(gate), judge `land-and-deploy/SKILL.md workflow` (gate lane).

Cosmetic pins dropped (no control needed): capitals on STOP / Do NOT.

Mutation log: .context/mutation-land-and-deploy-postfail.md (12 mutations,
0 unexpected: reorder, field delete and 7 safety deletes red; 3 rewordings green).
This commit is contained in:
garrytan committed 2026-10-03 01:02:23 +00:00
1 parent 23a0be82d7
commit ff54f3c955
1 file changed
+17 -21
+17 -21
View File
@@ -8,12 +8,11 @@
* only the STOP-Read pointer). After ANY non-zero `gh pr merge`, the skill
* must query authoritative PR state via
* GraphQL (including queue membership) and
* branch on the result instead of blindly retrying `gh pr merge` (cli/cli#3442,
* cli/cli#13380).
* branch on the result instead of blindly retrying `gh pr merge`.
*
* Static invariants pin:
* - §4a-postfail header present
* - Universal invariant text + reference to upstream gh bugs
* - Query-before-retry invariant after any non-zero merge exit
* - All three state branches (MERGED, OPEN, CLOSED) named explicitly
* - MERGED branch: capture merge SHA via mergeCommit.oid
* - MERGED branch: non-destructive worktree cleanup with uncommitted-work guard
@@ -52,12 +51,9 @@ describe("PR #1620 §4a-postfail in land-and-deploy template", () => {
expect(postfail).toBeLessThan(queue);
});
test("Universal invariant + upstream gh bug references", () => {
const body = readTmpl();
expect(body).toMatch(/Universal invariant/);
expect(body).toMatch(/non-zero exit from `gh pr merge`/);
expect(body).toMatch(/cli\/cli#3442/);
expect(body).toMatch(/cli\/cli#13380/);
test("any non-zero merge exit queries authoritative state before retrying", () => {
const body = readTmpl().replace(/\s+/g, " ");
expect(body).toMatch(/non-zero exit from `gh pr merge`, query authoritative PR state before retrying/i);
});
test("Authoritative state query includes auto request and queue membership", () => {
@@ -82,9 +78,9 @@ describe("PR #1620 §4a-postfail in land-and-deploy template", () => {
test("MERGED worktree cleanup is non-destructive (uncommitted-work guard)", () => {
const body = readTmpl();
expect(body).toMatch(/uncommitted work/);
expect(body).toMatch(/STOP worktree cleanup without removing/);
expect(body).toMatch(/Do NOT use `--force`/);
expect(body).toMatch(/Do NOT remove the user's primary working tree/);
expect(body).toMatch(/stop worktree cleanup without removing/i);
expect(body).toMatch(/do not use `--force`/i);
expect(body).toMatch(/do not remove the user's primary working tree/i);
});
test("MERGED branch continues to §4b CI auto-deploy detection", () => {
@@ -114,10 +110,10 @@ describe("PR #1620 §4a-postfail in land-and-deploy template", () => {
test("MERGED branch reconciliation distinguishes branch-absent from check-failed", () => {
const body = readTmpl();
// exit 0 + empty output = already clean (idempotent re-runs)...
expect(body).toMatch(/already been cleaned up/);
expect(body).toMatch(/already been cleaned up/i);
// ...non-zero exit = unknown state, never read as a clean branch.
expect(body).toMatch(/Couldn't verify remote branch state/);
expect(body).toMatch(/never read a failed check as a clean branch/);
expect(body).toMatch(/couldn't verify remote branch state/i);
expect(body).toMatch(/never read a failed check as a clean branch/i);
});
test("OPEN branch checks autoMergeRequest before treating as failure", () => {
@@ -128,15 +124,15 @@ describe("PR #1620 §4a-postfail in land-and-deploy template", () => {
test("CLOSED branch STOPs", () => {
const body = readTmpl();
expect(body).toMatch(/state == "CLOSED".*[\s\S]{0,200}STOP/);
expect(body).toMatch(/state == "CLOSED"[\s\S]{0,200}\bstop\b/i);
});
test("Hard rule: no replay after MERGED and only one guarded direct fallback", () => {
const body = readTmpl();
expect(body).toMatch(/never\s+replay a merge after MERGED/);
expect(body).toContain('one direct fallback');
expect(body).toContain('There is no fallback from a direct attempt');
expect(body).toContain('readback has confirmed OPEN, no auto request and no queue entry');
const body = readTmpl().replace(/\s+/g, " ");
expect(body).toMatch(/never replay a merge after MERGED/i);
expect(body).toMatch(/one direct fallback/i);
expect(body).toMatch(/no fallback from a direct attempt/i);
expect(body).toMatch(/confirmed OPEN, no auto request and no queue entry/i);
});
test("Generated merge-and-deploy.md carries the §4a-postfail section (atomic regen per T-Codex-3)", () => {