Skip to content

plan activate reads a hardcoded roster, not .squad/team.md — and reports a false provenance (re-diagnoses #1784) #1812

Closed

Description

@bradygaster

Found during the E4 staged walk, gate 8 (plan activate), run 32471509974 on fixture bradygaster/aspiregregator-squad-e2e.

This changes the root cause of #1784. #1784 is not retired — it is re-diagnosed.

Measured

The activation summary on fixture issue #22 states:

Roster set read from .squad/team.md (## Members → Name column): lead, reviewer, devrel, security, docs

The fixture's actual .squad/team.md roster:

Name Role
Keaton Lead / Architect
McManus Backend Engineer (Orleans)
Fenster Frontend Engineer (Blazor)
Hockney Test Engineer
Kint DevOps / Platform Engineer

None of lead, reviewer, devrel, security, docs appears anywhere in team.md. The claim of provenance is false — the roster was not read from that file.

Reproduce:

gh api repos/bradygaster/aspiregregator-squad-e2e/contents/.squad/team.md \
  -H "Accept: application/vnd.github.raw"

Corroboration

The fixture's existing squad:* labels:

squad
squad:lead
squad:devrel
squad:reviewer

lead, devrel, reviewer are a strict subset of the falsely-reported roster, and are exactly the three labels E3's plan activate minted (squad:lead ×3, squad:devrel ×1). They are not a subset of the real roster.

Consequence — why #1784's diagnosis was wrong

The original framing was "activate derives owner tokens from roles instead of using roster names," addressed as prompt token-salience in #1789.

The measurement says otherwise:

  • E3 — activate applied squad:lead/squad:devrel because those are members of the hardcoded list it actually uses. It was not leaking role tokens; it was correctly labelling against the wrong roster.
  • E4 — the implementation planner read team.md correctly and produced Keaton/McManus/Fenster/Hockney. Activate compared them against the hardcoded list, found no match, and refused to apply any squad:{agent} label.

So #1789 fixed a real thing in the planner and did not touch this. The planner's roster read is correct — verified at gate 4, Condition 1, 11/11 verbatim. The defect is downstream, in activate's roster source.

Impact on the E4 gate result

E4 passes 4/4 conditions as written, but Condition 2's pass is non-informative and must not be quoted as evidence that #1784 is fixed.

Condition 2 asserts no squad:lead/squad:devrel/squad:reviewer in timeline labeled events after $E4_START. It passed — 15 labeled events, all squad, zero role tokens. But it passed because activate applied no role labels at all, having refused on a roster mismatch. The absence is evidence of a refusal, not of correct binding.

This is the vacuous-pass pattern the condition was written to avoid, arriving through a path the condition could not distinguish: "correct owner labels minted" and "all owner labels refused" both yield an empty role-token set.

Two defects, separable

  1. Wrong source. Activate uses a hardcoded default roster (lead, reviewer, devrel, security, docs) rather than parsing .squad/team.md. Any repo whose roster is cast-named — i.e. any repo that ran squad init with a themed or custom universe — will never match, and will silently get zero owner labels.
  2. False provenance. The summary asserts "Roster set read from .squad/team.md" when it was not. This is worse than the wrong roster: it defeats the obvious diagnostic. A reader checking the summary against team.md would conclude the file was malformed rather than unread.

Defect 2 is the reason this survived E3. The E3 analysis accepted the summary's account of its own inputs.

What is NOT claimed

  • No fix proposed. Not diagnosed further at 03:25.
  • Whether the hardcoded list lives in the workflow, the ontology, or the compiled lock is unmeasured.
  • Whether the planner and activate share a roster-reading code path is unmeasured.
  • The create-label + issues: write prerequisite gap is real and separate — activate reported it correctly. That remains its own item.

Suggested condition change for the next E-series run

Condition 2 needs a both-terminals companion, or its green stays ambiguous:

2a. At least one squad:{name} label was applied, and every applied squad:{name} matches a Name in .squad/team.md.

Without 2a, "refused everything" and "bound everything correctly" are indistinguishable — which is precisely what happened here.

/cc @bradygaster — relevant to the 2026-08-21 E2E series. Does not block it; the walk completed 8/8.

Activity

  1. added
    squadSquad triage inbox — Lead will assign to a member
    bugSomething isn't working
    gh-awGitHub Agentic Workflows integration
    on Aug 21, 2026
  2. bradygaster commented on Aug 21, 2026

    @bradygaster
    CollaboratorAuthor

    Measurement — mechanism resolved, and it changes the remediation

    Follow-up to the report above. Two measurements against E3 (fixture issue #16), which refute one inference and add a second defect site.

    1. activate applies the plan's Agent value; it does not synthesize role tokens

    E3's implementation-plan Agent column, verbatim:

    # Title Agent
    1 Parse OPML into subscription records lead
    2 Import parsed feeds as subscriptions lead
    3 OPML upload UI with results panel devrel

    Plus epic #17 → lead. That is exactly the label set E3 minted: squad:lead x3, squad:devrel x1.

    So activate applied what the plan gave it, filtered through its (wrong) roster. It did not derive owner tokens independently.

    Consequence: the earlier inference that "with create-label enabled, this run would plausibly have minted squad:lead and squad:devrel again" does not hold. E4's plan column contains McManus/Keaton/Fenster/Hockney and no role tokens anywhere — there is no lead value for activate to apply. Enabling create-label would not reproduce the leak; activate would still refuse, on roster-mismatch grounds, which create-label does not affect.

    create-label is required for the correct behavior (minting squad:mcmanus and friends). It is not what is currently suppressing the defect.

    2. Second defect site — plan validate consults the same wrong roster, and passed on it

    From E3's validation gate, verbatim:

    | Agent assignments valid (cast Names) | ✅ (lead, lead, devrel) |

    plan validate declared lead, lead, devrel to be cast Names and returned PASS. The same wrong roster set is consulted at validate as at activate.

    That is why E3 reached activate with role tokens at all — the gate designed to catch exactly this condition was checking against the same incorrect roster, so it could not fail.

    Revised shape of the defect

    One wrong roster set, consulted at at least two points in the lifecycle:

    phase E3 (pre-#1789 plan) E4 (post-#1789 plan)
    plan validate ✅ PASS on lead, lead, devrel — false accept (not re-examined)
    plan activate applied squad:lead x3 + squad:devrel refused all — false reject

    #1789 changed the planner's output from role tokens to real cast names. The wrong roster did not change; its failure mode inverted from false accept to false reject.

    Impact on the E-series

    plan validate cannot currently be relied on to catch agent-binding errors — it passed lead, lead, devrel as valid cast Names. Any future condition that treats a green validate as evidence of correct binding inherits this.

    Still unmeasured

    • Where the five-token set originates (workflow, ontology, compiled lock).
    • Whether validate and activate share one roster-reading code path or duplicate it.
    • Whether any other phase consults it.
  3. bradygaster commented on Aug 21, 2026

    @bradygaster
    CollaboratorAuthor

    ⚠️ Correction — section 2 of the previous comment is refuted

    The claim "plan validate consults the same wrong roster" is wrong. Measured by Sims against E4's own plan validate output, 23 minutes before activate in the same walk:

    Roster set (.squad/team.md → ## Members → Name column): Keaton, McManus, Fenster, Hockney, Kint

    | 10 | Non-roster owner/agent | ✅ | Agent values used: Keaton, McManus, Fenster, Hockney — each matches the roster set verbatim. |

    Same file, same section, same column, same run session — read correctly at validate, incorrectly at activate.

    Revised shape — the defect is stage-local to activate

    Not one wrong roster with two consult sites. validate reads team.md correctly and echoes it. Only activate does not.

    And E3's validate failed differently than described. Grepping E3's validate comment (fixture issue #16, 23,655 chars) for Roster set / Non-roster / Check 10 returns one hit total:

    | Agent assignments valid (cast Names) | ✅ (lead, lead, devrel) |
    

    No roster enumerated. No Check 10 row. E3's validate was not consulting a wrong roster — it was consulting none, and asserting the conclusion anyway. False accept by omission, not by wrong reference.

    Phase E3 (pre-#1789) E4 (post-#1789)
    plan validate ✅ (lead, lead, devrel) — no roster, no Check 10; false accept by omission ✅ roster echoed correctly, Check 10 verbatim — true accept
    plan activate minted squad:lead x3 + squad:devrel roster read wrong — false reject

    Consequences

    1. fix(squad.md): stop seeding Owner/Agent binding with the tokens it forbids #1789 did not invert a failure mode. It fixed two things — the implementation-plan Agent column and the validate gate's roster echo + Check 10 — and left activate untouched. The activate behavior is a separate, pre-existing defect, not a mutation of the one fix(squad.md): stop seeding Owner/Agent binding with the tokens it forbids #1789 addressed.

    2. The fix is cheaper than stated. There is a working reference implementation one stage earlier in the same lifecycle. The remediation is "make activate do what validate already does" — enumerate the roster from .squad/team.md, echo it, then verify verbatim. Not a research problem.

    3. Finding A is hardened. validate emits the same citation format with accurate contents. The format is demonstrably achievable, which means the activate instance fabricated its roster rather than misparsing the file.

    4. The earlier framing "a validation gate returning ✅ while measuring against the wrong reference" is also wrong, and the truth is more mundane: a validation gate returning ✅ while measuring against no reference, with the failing values printed in the same cell as the pass. A claim rendered beside its own counter-evidence. That instance is caught by requiring the gate to show its reference set — which is exactly what fix(squad.md): stop seeding Owner/Agent binding with the tokens it forbids #1789 made it do.

    Provenance of the error

    The refuted claim was inferred from a single artifact (E3's validate output) without reading the adjacent one (E4's validate), which was one API call away and decisive. Two explanations fit the E3 data equally — wrong roster and no roster — and the more elegant one was chosen without measurement.

    Recording this because the same failure mode is the subject of the issue.

  4. added a commit that references this issue on Aug 21, 2026
  5. added
    type:bugSomething broken
    wave:1-nextWave 1 — immediate next sprint
    triagedIssue has been triaged
    go:spec-readyReady for formal spec/proposal
    and removed
    bugSomething isn't working
    on Aug 23, 2026
  6. bradygaster commented on Aug 23, 2026

    @bradygaster
    CollaboratorAuthor

    1. Owner & rationale

    Owner: squad:procedures. plan activate is implemented in the gh-aw Squad workflow prompt, and the defect is a prompt-stage roster source/provenance failure.

    Labels reconciled as: gh-aw, type:bug, priority:p0, wave:1-next, squad:procedures, triaged, go:spec-ready. I removed the legacy bug label because this issue now uses the type:* taxonomy.

    2. Files in scope

    Verified existing paths:

    • workflows/squad.md
    • workflows/shared/squad-planning-ontology.md
    • test/gh-aw-plan-lifecycle.test.ts
    • test/gh-aw-quality.test.ts
    • .squad/e2e/E4-agent-binding-verification.md

    3. Reproduction / measurement

    These commands were execution-tested and use no output suppression:

    gh api repos/bradygaster/aspiregregator-squad-e2e/contents/.squad/team.md -H "Accept: application/vnd.github.raw" | Select-String -Pattern '^\|'
    gh issue view 22 --repo bradygaster/aspiregregator-squad-e2e --comments --json comments --jq '.comments[].body | select(contains("Roster set read"))'

    They show the fixture roster names (Keaton, McManus, Fenster, Hockney, Kint) and the activation summary claiming .squad/team.md yielded lead, reviewer, devrel, security, docs.

    4. Verification bar

    Activation must quote the actual Name column values from the target repo's .squad/team.md, and every squad:{agent} label decision must be derived from that quoted set. The check must fail if the summary says it read .squad/team.md but emits any value absent from that file, or if all owner labels are refused while the plan contains valid roster names.

    5. Traps

    Cross-cutting call: keep #1812 and #1801 independent. #1801 is the validation/template false-green; #1812 is a stage-local activation provenance/source defect. E4 already shows plan validate can read the roster correctly while plan activate reads a false default roster, so neither issue is a safe dependency for the other.

    Do not treat create-label permission gaps as the root cause. Missing label creation is separate; this issue is about choosing and reporting the roster source.

    6. Out of scope

    Do not recast the fixture, change the roster names, add write permissions, or rewrite the activation lifecycle. Fix only the roster source/provenance and the fail-closed checks around it.

    7. Session-stall guard

    Before starting: this repo has phantom CRLF diffs (#1793). If git status shows files modified that you did not touch, run git diff --ignore-cr-at-eol. If that output is empty, the diff is line-ending churn, not real edits — run git add --renormalize . and continue. Do not halt and ask for confirmation; halting on phantom diffs is the documented cause of stuck sessions in this repo.

  7. added 2 commits that reference this issue on Aug 23, 2026
    4b32f7b
    6cede9b
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    gh-awGitHub Agentic Workflows integrationgo:spec-readyReady for formal spec/proposalpriority:p0Blocking releasesquadSquad triage inbox — Lead will assign to a membertriagedIssue has been triagedtype:bugSomething brokenwave:1-nextWave 1 — immediate next sprint

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions