Skip to content

docs(e2e): correct five stale procedures found by the first full E4 run - #1862

Merged
bradygaster merged 1 commit into
devfrom
squad/1861-e2e-runbook-corrections
Aug 24, 2026
Merged

bradygaster merged 1 commit into
devfrom
squad/1861-e2e-runbook-corrections

Conversation

@bradygaster

Copy link
Copy Markdown
Collaborator

Closes #1861

Corrections to the E2E runbooks found by executing E4 end-to-end against the new fixture (octodemo/aspiregregator-squad-e2e). Every item below is a measurement from that run, not a review observation.

Two of the five are silent-failure traps of exactly the class test/e2e-runbook-hygiene.test.ts exists to prevent: they do not error, they hand you a confident wrong answer.

1. E4 Phase 2 — short path 5 → 8 commands

The runbook said in bold: "Do not continue to plan validate / plan accept …. Those add ~27 min and verify nothing additional for E4."

False. /squad plan activate (run 32772695400) completed with all six jobs success and created nothing:

🤖 Squad — Plan Activate blocked
Result: No issues/milestones were created. Activation requires an `impl-accepted`
artifact ... which doesn't exist yet.

A second halt then appeared at accept implementation, which requires accept scope first (run 32776872385). On the old five-command path, Phases 3b/3c/3e have no artifact to read and only 3a scores — the runbook could not reach its own verification targets.

Both halts are correct Squad behaviour: clean lifecycle tables, precise remediation, no partial writes. L615-619 already anticipated this ("refuses to run without plan accept in later revisions"); that future arrived and the prescription above it hadn't caught up.

Also documented: plan validate legitimately FAILs on first pass when the program plan carries unresolved decisions — a real finding, cleared with /squad plan program revise. Budget a cycle for it.

2. E4 Phase 0b — compare content, not byte size

Three provisioning artifacts each produce a false STALE, and 0c's required post-condition ("all four MATCH") could never be satisfied:

  1. gh aw add injects source: bradygaster/squad/workflows/squad.md@dev into the top-level workflow only (+48 bytes)
  2. CRLF on Windows checkouts vs LF from the contents API
  3. gh aw add strips the source file's trailing newline

Worth noting (3) was found by running the replacement block, not by writing it — with only (1) and (2) handled the main workflow still read src=1391 / fixture=1390. Compare-Object isolated it to a single empty trailing line. With all three normalized, Compare-Object returns nothing and all four surfaces read MATCH, verified live.

3. E4 §3b — contamination table describes a fixture that no longer exists

The 🛑 warning claimed repo-global label checks are a "guaranteed false FAIL" because squad:lead/squad:devrel/squad:reviewer "already exist in the fixture", and tabulated contamination on issues #6-9 / #17-20.

All of that described the deleted fixture. octodemo/aspiregregator-squad-e2e started with 12 labels and zero squad:*; those issue numbers don't exist here. The guidance was inverted — on a fresh fixture, repo-global absence is real evidence. Missed when #1856 repointed the runbooks.

Rewritten to explain why timestamp-scoping is right (labels persist across repeat runs on the same fixture) rather than asserting a fixture-specific fact that expires. Also records that the fixture is now dirty (20 issues, 4 minted labels) so the next operator knows a clean re-test needs a fresh copy.

4. E4 §3a — warn against substituting Out-File

Out-File wraps at console width and splits markdown table rows mid-cell. It split the roster name Keaton into Ke / aton, silently corrupting a roster-membership check — no error, just a plausible-looking extract with one entry truncated. Set-Content (already used, now with a warning) and [IO.File]::WriteAllText don't wrap.

5. E1 — wrong mechanism for the autonomy blocker

The runbook said worker PRs are parked in action_required pending approval, and offered gh api -X POST repos/…/actions/runs/<RUN_ID>/approve.

Observed on fixture PR #4: pull_request workflows never triggered at all — GitHub suppresses triggers entirely for GITHUB_TOKEN-authored PRs. The rollup carried only dynamic-event checks. Same consequence, different cause, and the distinction is operational: you will hunt for a run ID that was never created. The PAT/App-token recommendation stands and is now explained.

Also

Records the 2026-08-24 amended-procedure verdict at the head of E4 — 3a PASS (12/12 tasks bound to roster Names, zero forbidden tokens including the dispositive devrel), 3c PASS, 3b/3e PARTIAL → #1859, #1860 — and notes why both defects survived every guard: TG-2 and validation Check 10 verify membership (each Agent is a roster Name); nothing verifies correspondence (the label on task N equals the plan's Agent for task N). A label can be simultaneously certified and wrong. That gap is the spec for #1801.

Verification

  • npx vitest run test/e2e-runbook-hygiene.test.ts — 3/3 pass (the --arg and stderr-suppression rules constrain every edit here)
  • npm run lint — clean
  • Phase 0b's replacement block executed against the live fixture, not just reviewed
  • Docs only, no product code → no changeset

⚠️ Needs squad member review before merging.

Executing E4 end-to-end against the new fixture surfaced five documented
procedures that are stale or wrong. Two are silent-failure traps: they do not
error, they produce a confident wrong answer.

E4 Phase 2 -- short path 5 -> 8 commands. The bold "do not continue to
`plan validate` / `plan accept ...`; those verify nothing additional" was false.
`plan activate` hard-blocks without an `impl-accepted` artifact while reporting
all six jobs `success`, so it looks clean and does nothing. On the old path
Phases 3b/3c/3e had no artifact to read and only 3a scored. Added the two
newly-required accept steps and the `plan validate` first-pass-FAIL cycle.

E4 Phase 0b -- compare content, not byte size. Three provisioning artifacts each
produce a false STALE: the `source:` line `gh aw add` injects into the top-level
workflow, CRLF vs LF, and `gh aw add` stripping the trailing newline. With only
the first two handled the main workflow still read 1391 vs 1390. Normalizing all
three takes all four surfaces to MATCH; verified live against the fixture.

E4 3b -- the contamination table and its "guaranteed false FAIL" warning
described the fixture that was deleted before this one existed. The new fixture
started with 12 labels and zero `squad:*`, which inverts the guidance. Missed
when #1856 repointed the runbooks.

E4 3a -- warn against substituting `Out-File` for `Set-Content`. `Out-File`
wraps at console width and splits markdown table rows mid-cell; it split the
roster name `Keaton` into `Ke`/`aton` and silently corrupted a roster check.

E1 -- worker PRs are not parked in `action_required`. GitHub suppresses
workflow triggers entirely for `GITHUB_TOKEN`-authored PRs, so no run is
created. The documented `runs/<ID>/approve` override cannot apply to a run that
does not exist. Same consequence, different cause; the PAT/App-token fix stands.

Also records the 2026-08-24 amended-procedure verdict at the head of E4: 3a and
3c PASS, 3b/3e PARTIAL -> #1859, #1860.

Verified: `test/e2e-runbook-hygiene.test.ts` (3/3), `npm run lint`. Phase 0b's
replacement block was executed against the live fixture, not just reviewed.
Docs only; no changeset.

Closes #1861

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 20afe6d2-444e-414e-8a39-e67ab67ca6df
Copilot AI lite review requested due to automatic review settings August 24, 2026 21:55
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Squad File Leakage Detected

The following .squad/ files were modified in this PR:

  • .squad/e2e/E1-merge-continuation-relay.md
  • .squad/e2e/E4-agent-binding-verification.md

These files affect team routing, agent charters, and decisions.
If intentional, ensure approval from the team lead.

@github-actions

github-actions Bot commented Aug 24, 2026 •

Copy link
Copy Markdown
Contributor

🛫 PR Readiness Check

ℹ️ This comment updates on each push. Last checked: commit cd7d5c9

PR Scope: 🔧 Infrastructure

⚠️ 2 item(s) to address before review

Status Check Details
✅ Single commit 1 commit — clean history
✅ Not in draft Ready for review
✅ Branch up to date Up to date with dev
❌ Copilot review No Copilot review yet — it may still be processing
✅ Changeset present No source files changed — changeset not required
✅ Scope clean ⚠️ PR includes 2 .squad/ file(s) — ensure these are intentional
✅ No merge conflicts No merge conflicts
✅ Copilot threads resolved No Copilot review threads
❌ CI passing 1 check(s) still running

Files Changed (2 files, +178 −71)

File +/−
.squad/e2e/E1-merge-continuation-relay.md +9 −5
.squad/e2e/E4-agent-binding-verification.md +169 −66

Total: +178 −71


This check runs automatically on every push. Fix any ❌ items and push again.
See CONTRIBUTING.md and PR Requirements for details.

@github-actions

Copy link
Copy Markdown
Contributor

🟢 Impact Analysis — PR #1862

Risk tier: 🟢 LOW

📊 Summary

Metric Count
Files changed 2
Files added 0
Files modified 2
Files deleted 0
Modules touched 1

🎯 Risk Factors

  • 2 files changed (≤5 → LOW)
  • 1 module(s) touched (≤1 → LOW)

📦 Modules Affected

squad-state (2 files)
  • .squad/e2e/E1-merge-continuation-relay.md
  • .squad/e2e/E4-agent-binding-verification.md

This report is generated automatically for every PR. See #733 for details.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

One moderate procedural issue and additional unresolved documentation corrections remain.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This docs-only PR updates E1/E4 E2E runbooks based on live execution findings.

Changes:

  • Corrects E4 lifecycle and content-comparison procedures.
  • Updates fixture, PowerShell, and evidence guidance.
  • Corrects GITHUB_TOKEN workflow-trigger explanations.
File summaries
File Review summary
.squad/e2e/E4-agent-binding-verification.md E4 procedure, status, formatting, and freshness guidance updates remain needed.
.squad/e2e/E1-merge-continuation-relay.md Follow-on approval guidance remains inconsistent with the corrected workflow behavior.
Review details

Suppressed comments (9)

.squad/e2e/E1-merge-continuation-relay.md:65

  • The corrected observation identifies only “fixture PR #4,” while this evidence file’s header is explicitly for the deleted bradygaster/... repo and the replacement reuses the same repo name under octodemo. Without naming octodemo/aspiregregator-squad-e2e (or using a declared $FIXTURE), the new measurement cannot be tied unambiguously to the current fixture.
> ⚠️ **Corrected 2026-08-24.** This section previously said such PRs are *parked* in `action_required` pending manual approval. **Measured false on fixture PR #4:** no `pull_request` run was created at all. The check rollup carried only `dynamic`-event checks (CodeQL, dependency submission) — there was nothing queued, nothing pending, and nothing to approve. The practical consequence is the same (the loop cannot close unattended), but the cause is different, and the distinction matters operationally: **you will search for a run ID that was never created.**

.squad/e2e/E4-agent-binding-verification.md:663

  • With this path, the Phase 3a extractor at lines 740–742 still selects .comments[-1].body. plan activate is the final command, and the workflow specifies its activation record as the LAST action, so this selects the activation summary rather than the squad_artifact=implementation comment. Phase 3a can therefore inspect the wrong table and miss the task Agent column; select and validate the implementation artifact by its structured envelope instead of taking the latest comment.
/squad plan implementation        ← the #1784 leak site (Phase 3a evidence)

.squad/e2e/E4-agent-binding-verification.md:511

  • PowerShell's -eq comparison is case-insensitive by default. This makes the gate report MATCH when the source and fixture differ only by letter case, allowing a real prompt change to be missed. Use a case-sensitive comparison after the intentional newline and provenance normalization.
      elseif ($s -eq $d)                 { "MATCH" }

.squad/e2e/E4-agent-binding-verification.md:775

  • The new fixture guidance says to re-derive the roster, but the actual 3a/3b criteria still hardcode the retired names (Keaton, McManus, Fenster, Hockney, Kint, plus their lowercase forms). The document itself says casting the replacement fixture will not reproduce those names, so a fresh run can reject valid bindings or accept stale names. Derive the accepted set from .squad/team.md for each run instead of retaining these literals.
> **On a freshly copied fixture the opposite is true.** Measured 2026-08-24 on
> `octodemo/aspiregregator-squad-e2e` immediately after provisioning: **12 labels, none of
> them `squad:*`** — `bug`, `documentation`, `duplicate`, `enhancement`, `good first issue`,
> `help wanted`, `invalid`, `question`, `wontfix`, `.NET`, `dependencies`, `squad`. There is
> no pre-existing contamination to filter, and repo-global absence *is* real evidence.

.squad/e2e/E4-agent-binding-verification.md:451

  • This new baseline still directs operators to the 0c refresh when content is stale, but 0c's fenced block (lines 543–553) contains comments only—there are no fetch/write/commit/compile commands. Once this comparison correctly reports STALE, following the runbook has no executable recovery path and cannot reach the required MATCH post-condition. Restore the refresh commands or link to an executable refresh procedure.
> 🛑 **Compare CONTENT, not byte size.** Three artifacts of provisioning make a byte-size
> comparison report `STALE` **forever** on a healthy fixture, so the 0c refresh below can
> never clear it:
>
> 1. `gh aw add` injects a provenance line into the **top-level workflow only**:

.squad/e2e/E4-agent-binding-verification.md:667

  • The command list now adds plan validate and both acceptance steps, but the Budget section still says ~31 minutes based on the old four-command measurement and later says “All five commands.” The newly required validation/acceptance cycle was the previously omitted work, so the runbook now gives a materially understated duration and contradictory command count. Update the budget and safety text with the measured eight-command path.
/squad plan implementation        ← the #1784 leak site (Phase 3a evidence)
/squad plan validate
/squad plan accept scope
/squad plan accept implementation
/squad plan activate              ← the #1812 provenance site (3b/3c/3e); STOP HERE

.squad/e2e/E4-agent-binding-verification.md:846

  • This new note says every run’s minted labels must be appended before the next run, then records four labels minted by the 2026-08-24 run while leaving the table above as _(none)_ and providing no issue mappings. The next operator will therefore inherit exactly the stale contamination table this warning says invalidates the filter. Populate it with the current run’s issue IDs or derive the contamination data instead of requiring manual maintenance.
> ⚠️ **This table grows.** Every E4 run mints labels at `plan activate`. **After running E4,
> append the newly-minted labels to this table before the next run** — otherwise the next
> run's contamination filter is stale and either passes labels it should catch or catches
> labels it should ignore. If unsure, re-derive it from the fixture:
> `gh label list --repo $FIXTURE` gives repo-global presence; scope by issue via the same

.squad/e2e/E4-agent-binding-verification.md:674

  • The E1 correction does not update the identical autonomy-blocker guidance in this E4 file’s follow-on at lines 1077–1082, which still says worker PR runs are parked in action_required and recommends approving a run ID. Since the new E1 text establishes that this mechanism creates no run, operators following the follow-on will still get the wrong procedure; update that section too.
> ⚠️ **This path was five commands until 2026-08-24.** It previously told you to skip
> `plan validate` and `plan accept …` on the grounds that they "verify nothing additional
> for E4". **That is false, and skipping them makes E4 unscoreable.** `plan activate` now
> refuses to act without an accepted implementation plan:
>

.squad/e2e/E4-agent-binding-verification.md:496

  • Get-AwNormalized removes every line matching a generic source: … .md@… pattern from both sides, then uses TrimEnd() for the trailing-newline artifact. That can hide a legitimate source line or meaningful trailing Markdown spaces and report MATCH for substantive drift. Limit the exception to the exact injected line on the top-level fixture workflow and trim only terminal CR/LF.
function Get-AwNormalized($text) {
    if ($null -eq $text) { return $null }
    $lines = ($text -replace "`r`n", "`n") -split "`n" |
        Where-Object { $_ -notmatch '^\s*source:\s*\S+/\S+\.md@' }
    return ($lines -join "`n").TrimEnd()
  • Files reviewed: 2/2 changed files
  • Comments generated: 5
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

git commit --allow-empty -m "trigger CI" && git push
```

> The `actions/runs/<RUN_ID>/approve` API this section used to recommend **cannot apply here**: approval acts on an existing queued run, and in this failure mode no run exists. Keep it in mind only for the genuinely distinct `action_required` case (first-time outside contributors), which is not what worker PRs hit.
## Phase 2 — Run the short path

**Run exactly these five commands, in this order, and stop.**
**Run exactly these eight commands, in this order, and stop.**
Comment on lines +21 to +24
> **The amended procedure has now been executed: 2026-08-24, n=1, against
> `octodemo/aspiregregator-squad-e2e`.** Twelve `/squad` runs, all six jobs green on every one,
> zero secrets and zero repository variables configured. Result: **3a PASS** (12/12 tasks bound
> to roster Names, zero forbidden tokens including the dispositive `devrel`), **3c PASS**, and
Comment on lines +447 to +449
> 🛑 **Compare CONTENT, not byte size.** Three artifacts of provisioning make a byte-size
> comparison report `STALE` **forever** on a healthy fixture, so the 0c refresh below can
> never clear it:
> roster-provenance gate) has **not yet been executed**. Any claim about #1812 requires a fresh
> live run against the amended procedure — do not cite the n=1 record as evidence of the
> provenance gate's behaviour.
| 2026-08-24 (post-run corrections, #1861) | **Five procedures were stale or wrong, found by executing E4 end-to-end on the new fixture.** (1) **Phase 2 short path 5 → 8 commands** — the bold "do not continue to `plan validate` / `plan accept …`" instruction was false: `plan activate` hard-blocks without an `impl-accepted` artifact while reporting all six jobs `success`, so 3b/3c/3e were unreachable and only 3a scored. (2) **Phase 0b compared byte size** — `gh aw add` injects a `source:` provenance line into the top-level workflow only (+48 bytes, identical 1391-line counts), so a correctly-provisioned fixture read `STALE` forever and 0c could never clear it; now compares content modulo that line. (3) **§3b contamination table and its 🛑 "guaranteed false FAIL" warning described the deleted fixture** — the new one started with 12 labels and zero `squad:*`, inverting the guidance; missed when #1856 repointed the runbooks. (4) **§3a gained an explicit `Out-File` warning** — `Out-File` wraps at console width and split the roster name `Keaton` into `Ke`/`aton` mid-table, silently corrupting a roster check with no error. (5) E1's `action_required` section corrected (see that file). | #1861 — first full E4 execution against `octodemo/aspiregregator-squad-e2e`. Every correction is a measurement, not a review comment: runs `32772695400` (activate blocked), `32776872385` (accept blocked), `32776202217` (validate passed after `plan program revise`) |
@bradygaster
bradygaster merged commit 1f51f82 into dev Aug 24, 2026
17 checks passed
@bradygaster
bradygaster deleted the squad/1861-e2e-runbook-corrections branch August 24, 2026 22:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

E2E runbooks: five stale or incorrect procedures found during the first full E4 run on the new fixture

2 participants