Skip to content

fix(gh-aw): bound activation label capacity and make truncation explicit (#1961) - #1964

Merged
bradygaster merged 9 commits into
devfrom
bradygaster-activation-label-capacity-safeguards
Sep 1, 2026
Merged

bradygaster merged 9 commits into
devfrom
bradygaster-activation-label-capacity-safeguards

Conversation

@bradygaster

@bradygaster bradygaster commented Aug 31, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #1961
Parent #1957

Working as FIDO (Quality Owner)

Revised after independent review. The first commit (adb718b2) made three factually wrong claims about the pinned gh-aw runtime. Commit ef5f2de2 corrects them against the v0.87.10 sources. The Corrections section records what changed and why, and the retracted claims now have negative-guard tests so they cannot come back.

Problem

An activation could label fewer issues than it created and still report a clean success. Two things made that possible: add-labels: max: 80 sat below the worst-case label-name count for a full activation, and nothing compared "issues activated" against "issues labeled" before the summary was written.

Capacity derivation

The largest activation supported in one run is 50 issues — the enterprise profile's max_issues: 50 (the highest documented profile limit), which is also the threshold the workflow's own phased-activation rule enforces.

Safe output Worst case at 50 issues max
create-issue 50 — one per epic/task 75 (unchanged)
add_labels 50 — one per created issue 110 (was 80)
Labels within one add_labels call 2 — squad + squad:{agent} not capped by max
Label names across the whole run 100 — 50 × 2 110

Why 110 and not 80. max counts safe-output items (tool calls), so 50 calls never actually exhausted a cap of 80 — there was no runtime overflow. The real hazard is what gh-aw injects into the prompt: it renders the cap as "Maximum 80 label(s) can be added", which reads as a budget of label names, against a worst case of 100 names. An agent that believes it has 80 names for 100 names' worth of work rations them and self-truncates. 110 satisfies the worst case under both readings — 50 calls and 100 names — so neither interpretation can justify skipping a label operation. The margin stays bounded (a test caps it at 2× worst case) so this doesn't trade a silent-truncation bug for an unbounded-write one.

Safeguards

Frontmatter — add-labels: max 80 → 110, with a comment recording the derivation and pointing at the full analysis.

squad-plan-activate prose — the capacity table above, plus two corrected statements of runtime behaviour:

New Step 2e — Label-Operation Reconciliation. The agent keeps two counts while Steps 2b/2c run: activated and labeled. A call that was never made, was rejected, or errored counts as unlabeled.

  • labeled == activated → complete, proceed.
  • labeled < activated → call report_incomplete naming the shortfall and listing every affected work item.

For items created this run, the report names the stable temporary ID plus title and intended labels — not a GitHub issue number. Issue creation is deferred to the post-agent job, so no real number exists during the agent turn; a real number is quoted only for an issue that already existed and was recognized. Never predict, infer, or invent a number. (Added per the PR #1965 review, to avoid reintroducing #1962's invalid-number assumption.)

Reconciliation keys on absence of success, never on presence of an error — a call can simply never be made, and a surplus item is dropped at collection time with only a warning.

Step 2d — an existing sentence that let the agent guess a cap as the cause of a partial run now requires the cap to have been observed in Step 2e.

Corrections after review

All three verified directly against githubnext/gh-aw@v0.87.10, the CI pin.

1. report_incomplete does not make the run conclude non-successfully. report_incomplete_handler.cjs emits core.warning only. handle_agent_failure.cjs contains zero setFailed/process.exit calls across 4453 lines. What it actually does is open or update a durable [aw] {workflow} reported incomplete result tracking issue or comment. gh-aw's own tool description — "treated as a failure signal even when the agent exits successfully" — is misleading, and the first commit trusted it. Trusting injected prose over the runtime contract is precisely the failure mode #1961 exists to prevent.

Stated limitation. No narrow mechanism in the pinned runtime makes an incomplete activation conclude red. Forcing one would mean adding a custom safe-job, which is outside this issue's scope. #1961's criterion asks for "an explicit incomplete/failure result", and the durable tracking record satisfies that — but the run stays green, and the workflow now says so plainly so no future author assumes otherwise: "never rely on a red run to carry the signal."

2. Cap enforcement is dual. Per Safe Outputs spec MCE4, enforcePerTypeMax in safe_outputs_handlers.cjs throws JSON-RPC E002: {type} limit reached — {n} of {max} already used this run at invocation time (live for us, since getExplicitMax only applies when max is explicitly configured). The collector then drops surplus items with a warning. The claim that an over-limit item "never appears as an error to the agent" was wrong and is removed. Absence-of-success reconciliation is retained regardless, and the prose now warns that the absence of an E002 is not proof every label landed.

3. The 110 rationale is the injected wording, not a proven overflow. The first commit implied 50 calls could overflow a cap of 80. They cannot. The docblock now carries an explicit "Note what is not claimed" paragraph recording this.

Tests

New test/gh-aw-activation-capacity.test.ts — 28 tests. Prefers compiled/runtime evidence over prose: the boundary tests read the compiled .lock.yml safe-outputs config, so a frontmatter edit that fails to compile is caught.

  • Cap derivation from the documented 50-issue maximum, both readings.
  • Boundary: at max (50) everything fits; one-over (51) exceeds the documented maximum and must route to phased activation.
  • Margin is bounded (≤ 2× worst case).
  • Compiled config agrees with frontmatter.
  • Step 2e contract: both counts, the labeled < activated branch, absence-of-success semantics, the temporary-ID rule, and the false-success prohibition.
  • Two negative guards that fail if either retracted claim is reintroduced.

Mutation-checked, not just green:

Mutation Result
max: 110 → 80 5 tests fail, including the compiled-runtime one
Reintroduce "never appears as an error to the agent" guard fails
Reintroduce "failure signal even when the agent exits successfully" guard fails
Step 2e demands a real issue number temporary-ID test fails

Validation

  • test/gh-aw-activation-capacity.test.ts, test/gh-aw-quality.test.ts, test/gh-aw-activation-label-provisioning.test.ts → 221/221 passing
  • Strict compile clean on all four workflows (squad, squad-review, squad-implement-worker, squad-deps-worker); only the two pre-existing squad.md warnings remain
  • npm run build passes
  • Prose kept tight; the source-growth guard raise is disclosed and justified below rather than hidden

Scope

No permission changes — add-labels keeps its existing least-privileged grant; only max moved.

Deliberately untouched: temporary-ID linkage (#1962 / PR #1965), fast-path parity (#1959), label-result reporting beyond the explicit overflow path (#1963), broad contract coverage (#1960), E4 (#1958), checker distribution.

Integration note — this PR is stacked on #1965

Base is bradygaster-plan-activate-temporary-ids (PR #1965), not dev. #1965 head 528ba9b0 is merged into this branch (merge commit 8cbf9907, no force-push), so this PR reviews as a clean delta on top of the temporary-ID contract. Merge #1965 first, then this one; the base retargets to dev automatically when #1965 lands.

git merge-base 528ba9b0 HEAD == 528ba9b0, and the diff against the new base is 3 files — this PR contains no #1965 content, and nothing from #1966/#1963.

The one conflict (Step 2d) was resolved deliberately. #1965's Self-Validation sentence is taken wholesale — it is strictly stronger than this branch's version ("requested/recognized", "the last task's temporary ID", "never substitute a guessed issue number"). Only this PR's minimal trailing clause is reapplied, which is #1961's concern and unaddressed by #1965: never surface a safe-output cap as a guessed reason for a partial run — name a cap only when Step 2e observed one being reached.

Step 2e now targets #1965's real mechanism rather than forward-referencing it. The report identifier for an item created this run is the temporary_id minted under the Temporary-ID Contract (#aw_epic{K} / #aw_task{N}) — not an issue number, because creation is deferred to the safe-output job. A real number may be quoted only where independently verified (dedup-by-title match, or Step 1's idempotent-rerun path). This mirrors #1965's own "Existing and reused issues" rule instead of restating a parallel contract, so #1962's invalid-number assumption is not reintroduced.

Disclosed third-file change

test/gh-aw-quality.test.ts raises the source-growth guard 170 → 172 KB. This is a stacking consequence, not #1961 scope creep, and it follows that guard's own documented criterion rather than silencing a red test. The value was measured on the resolved branch, not guessed:

Rebased onto dev

#1965 (fa5cc26c) and #1966 (9e3f6b34) both landed on dev, so this PR is no longer stacked — its base is dev and the diff is #1961-only (3 files).

workflows/squad.md auto-merged with no conflict this round: #1966's edits land in the /squad activate fast path and Step 4, while #1961's are in squad-plan-activate Step 2d/2e. Anchor-grep verified all three contracts survive unduplicated — #1966's Fast-Path Label Provisioning and non-roster reporting, #1965's Temporary-ID Contract and created-count wording, and #1961's capacity budget / max: 110 / Step 2e.

Validation

⚠️ Needs squad member review before merging.

Working as FIDO (Quality Owner).

A 50-issue activation could lose `add_labels` operations while the run still
reported success. Two causes:

1. `add-labels: max: 80` was below the worst case under the reading gh-aw's own
   injected prose invites. The compiler emits "Maximum {max} label(s) can be
   added", which reads as a budget of label NAMES; a full 50-issue activation
   applying `squad` + `squad:{agent}` needs 100. An agent taking that phrasing
   literally could conclude it had overrun and stop labeling early or batch
   issues together.
2. gh-aw v0.87.10 drops an over-limit item rather than failing. Its collector
   (`collect_ndjson_output.cjs`) rejects the item and `continue`s, pushing a
   string into `errors`; those are emitted with `core.warning`, never
   `core.setFailed`. The run finishes green with label operations missing and
   nothing announces it.

Verified against the pinned runtime rather than inferred: `max` caps safe-output
ITEMS (tool calls) per type, not label names inside a call. A two-label call
costs one item.

Capacity: largest supported activation is 50 issues (`enterprise` profile
`max_issues: 50`, the highest documented profile limit, and the same threshold
`squad-plan-activate` uses to force phased activation). Worst case at that size
is 50 `create-issue` items, 50 `add_labels` calls, <=2 labels per call, 100
label names across the run.

Changes:
- `add-labels: max` 80 -> 110, sized to cover the worst case under BOTH readings
  (50 calls, 100 names) so no interpretation of the cap can justify dropping a
  label operation. `create-issue` stays at 75.
- Record the derivation and the item-vs-label-name semantics in the activation
  skill, plus the fact that an over-limit item is dropped, not failed.
- New Step 2e Label-Operation Reconciliation: track `activated` vs `labeled`,
  count a never-made/rejected/errored call as unlabeled, and on shortfall call
  `report_incomplete` naming the affected work items. gh-aw treats that as a
  failure signal even on successful exit, so a truncated activation can no
  longer be recorded as clean. Cap exhaustion becomes a nameable cause when
  observed; #1683's rule against guessing at caps is preserved and narrowed.

Tests: `test/gh-aw-activation-capacity.test.ts` (27) covers the derived maximum,
capacity under both readings, at-maximum and one-over boundaries, and the
reconciliation contract. Compiled-artifact assertions prefer runtime evidence
over prose: the declared cap reaching `GH_AW_SAFE_OUTPUTS_CONFIG`, the injected
constraint carrying the same number, `report_incomplete` being present (and so
callable), and agent-job permissions staying `issues: read`. Fails closed if
`gh aw` is absent, per #1834. Mutation-checked: reverting the cap to 80 fails 4.

No changes to temporary-ID linkage (#1962), fast-path parity (#1959), label
result reporting (#1963), broad contract coverage (#1960), or E4 (#1958).
Step 2e is deliberately neutral about how `add_labels` identifies its target so
it does not conflict with #1962.

Closes #1961
Parent #1957

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings August 31, 2026 22:00
@github-actions

github-actions Bot commented Aug 31, 2026 •

Copy link
Copy Markdown
Contributor

🟡 Impact Analysis — PR #1964

Risk tier: 🟡 MEDIUM

📊 Summary

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

🎯 Risk Factors

  • 3 files changed (≤5 → LOW)
  • 2 modules touched (2-4 → MEDIUM)

📦 Modules Affected

root (1 file)
  • workflows/squad.md
tests (2 files)
  • test/gh-aw-activation-capacity.test.ts
  • test/gh-aw-quality.test.ts

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

@github-actions

github-actions Bot commented Aug 31, 2026 •

Copy link
Copy Markdown
Contributor

🛫 PR Readiness Check

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

PR Scope: 🔧 Infrastructure

⚠️ 2 item(s) to address before review

Status Check Details
❌ Single commit 9 commits — consider squashing before review
✅ 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 No .squad/ or docs/proposals/ files
✅ No merge conflicts No merge conflicts
✅ Copilot threads resolved 0 active Copilot thread(s) resolved (3 outdated skipped)
✅ CI passing All checks passing

Files Changed (3 files, +636 −12)

File +/−
test/gh-aw-activation-capacity.test.ts +576 −0
test/gh-aw-quality.test.ts +17 −10
workflows/squad.md +43 −2

Total: +636 −12


This check runs automatically on every push. Fix any ❌ items and push again.
See CONTRIBUTING.md and PR Requirements 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.

Copilot review overview

🟡 Changes recommended

The new test file uses an extensionless ESM helper import (./helpers/gh-aw-lock) that is inconsistent with other suites and can break under Node ESM/NodeNext resolution after transpilation.

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

Review tier: Lite
Findings: 1 Medium severity

New issues introduced by this change (1)
Severity Finding
Medium severity test/​gh-aw-activation-capacity.test.ts — This test imports the helper without the .js extension, but other Vitest suites import the same…
What changed in this PR

This PR hardens the gh-aw activation workflow contract to prevent “green” runs that silently drop add_labels operations under safe-output caps, by increasing the add-labels cap and requiring a reconciliation step that converts any label-operation shortfall into an explicit report_incomplete failure.

Changes:

  • Increase safe-outputs.add-labels.max from 80 → 110 and document the capacity rationale (50-issue max, item-vs-label semantics, drop-not-fail behavior).
  • Add Step 2e “Label-Operation Reconciliation” guidance to detect and fail on labeled < activated.
  • Add a new compiled-artifact contract test suite to lock in capacity math and prove the compiled workflow exposes the required runtime config/tools.
File Description
workflows/​squad.md Raises add-labels cap to 110 and documents/mandates reconciliation to prevent silent truncation being reported as success.
test/​gh-aw-activation-capacity.test.ts Adds capacity + compilation contract tests to validate max sizing, compiled safe-output config, and callable tooling (including report_incomplete).

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

Comment thread test/gh-aw-activation-capacity.test.ts Resolved
Independent review found three factual defects in the prose and tests
shipped by the first commit. All three are corrected against the pinned
gh-aw v0.87.10 sources rather than gh-aw's own injected descriptions.

1. `report_incomplete` does NOT make the run conclude non-successfully.
   `report_incomplete_handler.cjs` emits `core.warning` only, and
   `handle_agent_failure.cjs` contains zero `setFailed`/`process.exit`
   calls in 4453 lines. What it actually does is open or update a durable
   `[aw] {workflow} reported incomplete result` tracking issue. Step 2e
   now states that, says the run still reports success, and tells the
   agent never to rely on a red run to carry the signal. gh-aw's own tool
   description ("treated as a failure signal even when the agent exits
   successfully") is misleading; trusting it was exactly the injected-prose
   mistake #1961 exists to prevent.

   Limitation, stated honestly: no narrow mechanism in the pinned runtime
   makes an incomplete activation conclude red. Forcing one would require
   a custom safe-job, which is outside this issue's scope. The durable
   tracking record plus the "never report a clean activation you did not
   perform" rule are what carry the signal.

2. Cap enforcement is dual, not collection-only. Per Safe Outputs MCE4,
   `enforcePerTypeMax` in `safe_outputs_handlers.cjs` throws JSON-RPC
   `E002: {type} limit reached` at invocation time, which the agent DOES
   see; the collector then drops surplus items with a warning. Removed the
   claim that an over-limit item "never appears as an error to the agent".
   Reconciliation still keys on absence-of-success, not presence-of-error,
   because a call can also simply never be made.

3. The old `max: 80` did not cause runtime truncation — 50 calls never
   reached it. The real hazard is gh-aw's injected "Maximum 80 label(s)
   can be added" wording against a 100-label worst case, which invites
   agent self-truncation. 110 is justified by that hazard plus bounded
   margin, and the docblock now explicitly records what is NOT claimed.

Also, per the PR #1965 review: Step 2e no longer demands a real issue
number for items created during the run. Issue creation is deferred to
the post-agent job, so it names the stable temporary ID plus title and
intended labels, and quotes a real number only for a reused issue —
avoiding reintroduction of #1962's invalid-number assumption.

Tests: renamed the two overclaiming tests and gave each a negative guard
that fails if the retracted wording returns; added coverage for the
temporary-ID rule. Trimmed prose to stay under the existing 160 KB
source-growth guard rather than raising another test's budget.

Verified: 221/221 across the three gh-aw suites; mutation-checked (cap
-> 80 fails 5 tests incl. the compiled-runtime one, reintroducing either
retracted claim fails its guard); strict compile clean on all four
workflows; npm run build passes.

Closes #1961
Parent #1957

Working as FIDO (Quality Owner)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 2471face-3b27-4419-bd48-0becd2642d7f
@bradygaster bradygaster changed the title fix(gh-aw): prevent silent truncation of activation label operations fix(gh-aw): bound activation label capacity and make truncation explicit (#1961) Aug 31, 2026
Stacks this branch explicitly on `bradygaster-plan-activate-temporary-ids`
(PR #1965 head 528ba9b) so #1964 reviews as a clean delta on top of the
temporary-ID contract instead of colliding with it at merge time.

Conflict resolution (workflows/squad.md, Step 2d — the only conflict):
- Took #1965's Self-Validation sentence wholesale. It is strictly stronger
  than the version on this branch ("requested/recognized", "the last task's
  temporary ID", "never substitute a guessed issue number").
- Reapplied only this branch's minimal trailing clause, which is #1961's
  concern and not addressed by #1965: never surface a safe-output cap as a
  guessed reason for a partial run — name a cap only when Step 2e observed
  one actually being reached.

Step 2e concretized against the now-present mechanism:
- The report identifier for an item created this run is the `temporary_id`
  minted under #1965's Temporary-ID Contract, not a GitHub issue number,
  because creation is deferred to the safe-output job.
- A real number may be quoted only where independently verified (dedup-by-title
  match, or Step 1's idempotent-rerun path). This mirrors #1965's own "Existing
  and reused issues" rule rather than restating a parallel contract.

Source-growth guard raised 160 -> 168 KB (test/gh-aw-quality.test.ts), per that
guard's own documented criterion rather than to turn a red test green:
- Ambient prompt (the canonical budget) measures 32.0 KB against 40 KB.
- All growth is inside the `squad-plan-activate` inline skill, which the
  extractor strips from the ambient prompt and loads on demand.
- Neither PR was individually over: #1965 alone 163812 B, #1961 alone 163819 B,
  against the old 163840 B ceiling — 28 and 21 bytes of headroom. Two
  independently-compliant PRs could not coexist under a threshold that tight.

Validation: 239/239 across the four gh-aw suites; three mutation probes
(cap 110->80, Step 2e temp-ID rule, retracted dual-enforcement claim) each fail
their intended tests; all four workflows compile with `--strict` showing only
pre-existing warnings; `npm run build` passes. Compiled lock confirms both
contracts coexist: add_labels max 110, create_issue max 75 + require_temporary_id.

Refs #1961, #1965. Parent #1957.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 2471face-3b27-4419-bd48-0becd2642d7f
@bradygaster
bradygaster changed the base branch from dev to bradygaster-plan-activate-temporary-ids August 31, 2026 22:41
bradygaster and others added 2 commits August 31, 2026 15:53
Addresses Copilot review on PR #1964. The reviewer is correct on both counts.

`tsc --module nodenext --moduleResolution nodenext` reports exactly one error
on this file, and TypeScript names the fix itself:

  test/gh-aw-activation-capacity.test.ts(94,46): error TS2835: Relative import
  paths need explicit file extensions in ECMAScript imports when
  '--moduleResolution' is 'node16' or 'nodenext'. Did you mean
  './helpers/gh-aw-lock.js'?

The repo is `"type": "module"` with `module`/`moduleResolution: NodeNext` in the
root tsconfig, and the four other suites importing this helper already use the
`.js` specifier. This file was the lone outlier; it now matches.

Verified: 293/293 across all eight suites that import the helper, all four
workflows compile with `--strict` (pre-existing warnings only), `npm run build`
passes, and the NodeNext type-check on this file is now clean.

Refs #1961. Parent #1957.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 2471face-3b27-4419-bd48-0becd2642d7f
Keeps the stack on `bradygaster-plan-activate-temporary-ids` current after
#1965 advanced past 528ba9b. GitHub had flagged the PR CONFLICTING/DIRTY.

One conflict, again at Step 2d, resolved by the same rule used for 528ba9b:
take #1965's sentence wholesale and reapply only this branch's trailing clause.

#1965 c95d43a tightens 2d by defining the created count explicitly ("the number
of `create-issue` calls this run emitted") and binding `created={N}`/`expected={M}`
to it. That definition is adopted verbatim. This branch's delta — never surface a
safe-output cap as a *guessed* reason for a partial run; name one only when Step 2e
observed it being reached — is reapplied to the trailing sentence. Step 2e is
unchanged and still follows 2d.

#1965's other two hunks in this commit (Uniqueness wording, pre-existing-epic
parent rule) auto-merged and are present verbatim.

Validation: 240/240 across the four gh-aw suites (count rises from 239 because
c95d43a adds a test to #1965's own suite, which passes untouched); all four
workflows compile with `--strict` showing only pre-existing warnings;
`npm run build` passes.

Refs #1961, #1965. Parent #1957.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 2471face-3b27-4419-bd48-0becd2642d7f
@bradygaster
bradygaster changed the base branch from bradygaster-plan-activate-temporary-ids to dev August 31, 2026 23:02
Resolves #1964 against dev head 9e3f6b3, which now carries both
#1965 (temporary-ID contract, fa5cc26) and #1966 (fast-path label
provisioning, squash 9e3f6b3).

workflows/squad.md — auto-merged, no conflict. #1966's edits land in
the `/squad activate` fast path and Step 4; #1961's are in
squad-plan-activate Step 2d/2e. Different regions, so the recurring
Step 2d conflict did not recur this round. Verified by anchor grep
that all three contracts survive unduplicated: #1966's Fast-Path Label
Provisioning / non-roster reporting, #1965's Temporary-ID Contract and
created-count wording, and #1961's capacity budget / max 110 / Step 2e.

test/gh-aw-quality.test.ts — SOURCE_GROWTH_BUDGET_KB conflict resolved
to 172 (was 168 here, 170 on dev). Measured, not guessed: combined
source on the resolved branch is 173241 B (169.2 KB).

  - 168 now FAILS by 1209 B, so keeping it would land red.
  - 170 passes by only 839 B. That is the same stale-threshold failure
    this guard already hit once at 160, where 21-28 bytes of headroom
    meant two independently-compliant PRs could not coexist.
  - 172 leaves 2887 B (~2.8 KB) of real margin, so the guard still
    bites on genuine growth.

dev's #1959/#1962 rationale comment is preserved verbatim; the #1961
rationale is appended beneath it rather than replacing it.

Guard precondition confirmed: the canonical ambient prompt budget is
still 32.0 KB (32795 B) against 40 KB, unchanged by either PR, because
all growth sits inside inline `## skill:` blocks that gh-aw strips from
the always-loaded prompt. That is this guard's own documented condition
for a legitimate raise.

Validation: 320/320 across 9 targeted suites including #1966's new
fast-path suite; all four workflows `gh aw compile --strict` clean
(pre-existing discriminator/slash_command warnings only); npm run build
exit 0.

Closes #1961
Parent #1957

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 2471face-3b27-4419-bd48-0becd2642d7f
bradygaster added a commit that referenced this pull request Sep 1, 2026
Both activation paths could report labels that were never applied, and the
`Activation bindings:` block specified JSON the agent could not produce.

Over-claim by attribution. `squad-plan-activate` Label Pre-flight Step 8 let a
summary name a `squad:{agent}` label once "that issue's `create-issue` call
returned successfully carrying it". `create-issue`'s `labels:` field cannot land
a label the repository lacks — the failure #1959 fixed — so that sentence
licensed reporting labels that never existed. Both paths now condition a
reported label on an accepted `add_labels` call carrying it for that same
issue, targeted by the item's own temporary ID or, for a reused item, its
verified real number. A successful `create-issue` is stated to be no evidence.

Invalid bindings JSON. The block required bare `{created task issue number}`.
The agent never learns a created issue's real number during its turn, and
gh-aw's temporary-ID substitution is a plain text replacement over the whole
comment body that does not skip fenced code blocks and keeps the `#`. A bare
`"issue":#aw_task1` becomes `"issue":#42` — invalid JSON that fails the entire
block. Verified against the pinned runtime (github/gh-aw-actions@v0.87.2,
setup/js/temporary_id.cjs). Quoting is the narrowest correct fix:
`"issue":"#aw_task1"` becomes `"issue":"#42"`, which parses. No new safe job,
no temporary_id_map plumbing, and no inferred numbers.

Runtime limitation, stated rather than worked around: safe outputs are applied
in a post-agent job, so a run has evidence only that a call was accepted for a
specific target, never the GitHub API result. "Accepted" is the strongest
honest claim; the prose forbids saying a label was verified, confirmed, or
checked. Under-claiming is rejected too — an accepted operation may not be
reported as an omission — and the required `Non-roster agent values` handling
from the base stack is preserved and made two-directional.

The post-activation checker resolves `"#42"` and bare integers, and fails
closed on an unresolved `#aw_...` rather than skipping or repairing it.

Tests: new focused suite covering both paths; 20 of its 28 assertions fail
against the pre-fix prose. Two existing assertions that pinned the old
create-issue attribution are updated to the strictly stronger condition, with
their original intent (#1860, #1959) preserved.

Source growth guard raised 170 -> 173 KB. Measured against dev with #1966
already squash-merged, so this counts only #1963's bytes: 175 485 B = 171.4 KB.
172 KB would leave 643 B, reproducing the near-zero-margin failure the guard's
own comment warns about; 173 KB leaves 1 667 B. Not set higher, because #1964
is unmerged and pre-raising for it would hide growth that has not happened. The
ambient prompt budget is unaffected at 32 795 B = 32.0 KB against 40 KB, which
is the condition that guard names as making a raise legitimate.

Closes #1963
Parent #1957
Previously stacked on #1959 (PR #1966); that merged to dev as 9e3f6b3, so this
now targets dev directly and contains #1963's changes only.

Working as Procedures (Prompt Engineer)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@bradygaster
bradygaster requested a lite review from Copilot September 1, 2026 15:47

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.

Copilot review overview

🟡 Changes recommended

Step 2e’s report_incomplete reason currently implies labels were actually received/applied during the agent turn, which isn’t guaranteed by an accepted add_labels safe-output and could misreport outcomes.

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

Review tier: Lite
Findings: 1 Low severity

New issues introduced by this change (1)
Severity Finding
Low severity workflows/​squad.md — Step 2e’s reconciliation message currently says issues “received their labels”, but at agent time…
Issues resolved since last review (1)
Severity Finding
Medium severity test/​gh-aw-activation-capacity.test.ts — This test imports the helper without the .js extension, but other Vitest suites import the same… View resolved comment

Comment thread workflows/squad.md Resolved
bradygaster added a commit that referenced this pull request Sep 1, 2026
#1963) (#1967)

* fix(workflows): report accepted label outcomes in activation summaries

Both activation paths could report labels that were never applied, and the
`Activation bindings:` block specified JSON the agent could not produce.

Over-claim by attribution. `squad-plan-activate` Label Pre-flight Step 8 let a
summary name a `squad:{agent}` label once "that issue's `create-issue` call
returned successfully carrying it". `create-issue`'s `labels:` field cannot land
a label the repository lacks — the failure #1959 fixed — so that sentence
licensed reporting labels that never existed. Both paths now condition a
reported label on an accepted `add_labels` call carrying it for that same
issue, targeted by the item's own temporary ID or, for a reused item, its
verified real number. A successful `create-issue` is stated to be no evidence.

Invalid bindings JSON. The block required bare `{created task issue number}`.
The agent never learns a created issue's real number during its turn, and
gh-aw's temporary-ID substitution is a plain text replacement over the whole
comment body that does not skip fenced code blocks and keeps the `#`. A bare
`"issue":#aw_task1` becomes `"issue":#42` — invalid JSON that fails the entire
block. Verified against the pinned runtime (github/gh-aw-actions@v0.87.2,
setup/js/temporary_id.cjs). Quoting is the narrowest correct fix:
`"issue":"#aw_task1"` becomes `"issue":"#42"`, which parses. No new safe job,
no temporary_id_map plumbing, and no inferred numbers.

Runtime limitation, stated rather than worked around: safe outputs are applied
in a post-agent job, so a run has evidence only that a call was accepted for a
specific target, never the GitHub API result. "Accepted" is the strongest
honest claim; the prose forbids saying a label was verified, confirmed, or
checked. Under-claiming is rejected too — an accepted operation may not be
reported as an omission — and the required `Non-roster agent values` handling
from the base stack is preserved and made two-directional.

The post-activation checker resolves `"#42"` and bare integers, and fails
closed on an unresolved `#aw_...` rather than skipping or repairing it.

Tests: new focused suite covering both paths; 20 of its 28 assertions fail
against the pre-fix prose. Two existing assertions that pinned the old
create-issue attribution are updated to the strictly stronger condition, with
their original intent (#1860, #1959) preserved.

Source growth guard raised 170 -> 173 KB. Measured against dev with #1966
already squash-merged, so this counts only #1963's bytes: 175 485 B = 171.4 KB.
172 KB would leave 643 B, reproducing the near-zero-margin failure the guard's
own comment warns about; 173 KB leaves 1 667 B. Not set higher, because #1964
is unmerged and pre-raising for it would hide growth that has not happened. The
ambient prompt budget is unaffected at 32 795 B = 32.0 KB against 40 KB, which
is the condition that guard names as making a raise legitimate.

Closes #1963
Parent #1957
Previously stacked on #1959 (PR #1966); that merged to dev as 9e3f6b3, so this
now targets dev directly and contains #1963's changes only.

Working as Procedures (Prompt Engineer)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(workflows): remove applied-label over-claim from the shared ontology

Review on #1967 caught the exact defect this PR exists to remove, in a file the
PR already touches. The `Activation bindings:` paragraph in the shared ontology
said bindings record "epic labels reported as applied", while the paragraph
directly below it correctly defines a reported label as an accepted `add_labels`
operation that the agent never observes landing. squad.md stated the accurate
contract and the ontology stated the strong one.

That split matters because the ontology is the artifact contract the
deterministic checker consumes and the file most likely to be read standalone: a
consumer reading only that paragraph gets the claim the runtime cannot justify.
Left as prose-only drift it would have turned one consistently-wrong place into
two inconsistently-wrong ones.

Reworded to the accepted-operation semantics used everywhere else, pointing a
standalone reader at the definition below it.

Guarded against re-drift with a negative assertion over the ontology, mirroring
the guard the suite already applies to squad.md. The match is shape-targeted
rather than a ban on the word "applied": the same file legitimately says safe
outputs "are applied after the agent turn", which is the justification for the
weaker claim, so a blanket match would forbid the correct prose too. Verified by
mutation — restoring the old wording fails the new test, and only that test.

Also pins the local `gh aw` install hint to v0.87.10, matching the pin in
.github/workflows/squad-ci.yml, so local strict-compile and lock output match
CI. The separate `gh-aw-actions@v0.87.2` citation is left as-is: that is the
pinned runtime action whose temporary_id.cjs this change was verified against,
which is a different artifact from the CLI extension, and v0.87.2 is still what
.github/workflows references.

Source growth re-measured after the edit: 175 519 B = 171.4 KB, 1 633 B under
the 173 KB guard, so the guard is unchanged. Ambient prompt unaffected.

Closes #1963
Parent #1957

Working as Procedures (Prompt Engineer)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…-label-capacity-safeguards

# Conflicts:
#	test/gh-aw-quality.test.ts
@bradygaster

Copy link
Copy Markdown
Collaborator Author

Resolved the merge with dev after #1967 (#1963) landed as fb58f26d. Merge commit 4ed083db.

Only one conflict, as expected: SOURCE_GROWTH_BUDGET_KB in test/gh-aw-quality.test.ts. workflows/squad.md auto-merged cleanly — the Step 2d overlap that looked risky resolved without intervention.

The budget is measured, not projected. I merged both branches in a scratch worktree and forced the guard to print its own number rather than trusting an estimate:

Combined authored source is 175.8 KB  (180 036 bytes)
  176 KB -> PASS, headroom    188 B
  177 KB -> PASS, headroom  1 212 B

Set to 177. 176 would pass by 188 bytes, which is precisely the near-zero-margin failure mode this guard's own comment criticises — before the 160→170 raise it sat 21–28 bytes from the ceiling and correct changes failed on byte count alone. #1963's comment predicted this merge would land at ~180 002 B; the real figure is 180 036 B, within 34 bytes, and I've recorded both numbers in the resolved comment so the next raise has a real audit trail.

The guard's stated precondition for a legitimate raise holds: keeps the ambient prompt under 40 KB passes at ~32 KB on the merged tree.

Verification: 286 passed across the six affected suites (gh-aw-quality, gh-aw-activation-capacity, gh-aw-activation-summary-outcomes, gh-aw-activate-fast-path-label-provisioning, gh-aw-agent-binding-correspondence, check-agent-binding).

⚠️ One thing I could not verify locally, reported rather than papered over. gh aw compile --strict fails in this checkout, but it is not this branch: I reproduced it on clean dev at fb58f26d with zero modified files, where it resolves imports from /tmp/sqwt/.github/workflows/ — the parent of the worktree. gh aw compile mis-resolves the repo root inside a linked git worktree. CI runs on a normal clone, so the required gh-aw strict compile check is the authority here, not my local run.

Copilot re-review requested on this head. Not merged.

…ied labels

Copilot review flagged that Step 2e's reconciliation claimed issues
"received their labels". #1963 (now merged to dev) settled the
vocabulary: an accepted safe output is queued this turn and applied by
the post-agent job, so the agent has evidence only that a call was
accepted for a specific target -- never that a label reached GitHub.
Step 2e was the remaining place still asserting application, which
conflicts with the accepted-vs-applied rule the same skill now states.

- `labeled` is defined as issues whose add_labels call was accepted.
- The report_incomplete reason reads "had a label operation accepted".
- "proof that every label landed" -> "every label operation was accepted".
- Added an explicit statement that the counts track label operations,
  not labels present on GitHub.

Tests: new assertion guards the positive and both retired over-claim
phrasings; verified by reverting the prose (1 failed, 28 passed) rather
than assuming. Tightened the sibling assertion to match the exact count
definitions -- the previous `.*`-joined form matched a distant
"was accepted" elsewhere in the flattened skill and so failed to detect
a reverted definition.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0515ad5d-4c5b-48bb-92a6-4e1296594cab

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.

Copilot review overview

🟡 Changes recommended

A new test assertion uses a regex alternation that makes the check effectively non-assertive, so the suite may pass even if the intended invariant is removed.

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

Review tier: Lite
Findings: 1 Medium severity

New issues introduced by this change (1)
Severity Finding
Medium severity test/​gh-aw-activation-capacity.test.ts — The regex here is effectively vacuous because the |activated.*artifact alternative will match any…
Issues resolved since last review (1)
Severity Finding
Low severity workflows/​squad.md — Step 2e’s reconciliation message currently says issues “received their labels”, but at agent time… View resolved comment

Comment thread test/gh-aw-activation-capacity.test.ts Resolved
Copilot review caught that the regex ended in an `|activated.*artifact`
alternative. Alternation binds loosest, so the whole pattern collapsed to
that branch and matched any mention of the artifact -- the test would
have passed with the `labeled < activated` condition deleted from the
prose, which is the entire invariant it names.

Anchored to the full sentence and verified by mutation: removing the
condition from Step 2e now fails (1 failed / 28 passed) where it
previously passed.

Second instance of this defect class in this suite; the sibling count
assertions were tightened in 4ec89dd for the same reason. Audited the
remaining alternations here -- `/finish green|still succeeds/` is
legitimate (two accepted phrasings, both specific).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0515ad5d-4c5b-48bb-92a6-4e1296594cab
@bradygaster
bradygaster requested a lite review from Copilot September 1, 2026 16:08

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.

Copilot review overview

🟢 Approval recommended

The changes are narrowly scoped to capacity/rationale + reconciliation safeguards and are backed by compiled-runtime contract tests, with only minor documentation nits noted.

Review tier: Lite
Findings: None

Issues resolved since last review (1)
Severity Finding
Medium severity test/​gh-aw-activation-capacity.test.ts — The regex here is effectively vacuous because the |activated.*artifact alternative will match any… View resolved comment
Suppressed comments (2)

Previously missed (2) — in code that hasn't changed since the last review.

test/gh-aw-quality.test.ts:908

  • The source-growth guard below counts the entire workflow file (squadContent includes frontmatter), so the comment claiming all #1961 growth is inside the squad-plan-activate inline skill is inaccurate: this PR also changes the safe-outputs frontmatter (e.g., add-labels max and capacity comments). Please reword to reflect that frontmatter changes exist (and are still stripped from the ambient prompt by the assembler) so future readers don't draw the wrong conclusion about what was measured.
  // All of #1961's growth is inside the `squad-plan-activate` inline skill, which the
  // extractor strips from the ambient prompt and loads on demand; ambient re-measured at
  // 32 KB against 40 KB on the merged tree.

workflows/squad.md:1874

  • In the capacity table, the column header is "Safe output" and the create-issue row uses the frontmatter key style, but the next row uses the tool name style (add_labels). This inconsistency can be confusing when someone tries to reconcile the table with the safe-outputs: frontmatter (which is add-labels:). Consider using add-labels in the table and reserve add_labels for places where you're explicitly talking about the tool call/runtime type name.
| `create-issue` | 50 — one per epic/task | 75 |
| `add_labels` | 50 — one per created issue | 110 |
| Labels in one call | 2 — `squad` + `squad:{agent}` | not capped |

@bradygaster
bradygaster merged commit eabec46 into dev Sep 1, 2026
19 checks passed
@bradygaster
bradygaster deleted the bradygaster-activation-label-capacity-safeguards branch September 9, 2026 19:44
bradygaster added a commit that referenced this pull request Oct 3, 2026
* fix(gh-aw): bound activation label capacity and make truncation explicit (#1961) (#1964)

* fix(gh-aw): prevent silent truncation of activation label operations

Working as FIDO (Quality Owner).

A 50-issue activation could lose `add_labels` operations while the run still
reported success. Two causes:

1. `add-labels: max: 80` was below the worst case under the reading gh-aw's own
   injected prose invites. The compiler emits "Maximum {max} label(s) can be
   added", which reads as a budget of label NAMES; a full 50-issue activation
   applying `squad` + `squad:{agent}` needs 100. An agent taking that phrasing
   literally could conclude it had overrun and stop labeling early or batch
   issues together.
2. gh-aw v0.87.10 drops an over-limit item rather than failing. Its collector
   (`collect_ndjson_output.cjs`) rejects the item and `continue`s, pushing a
   string into `errors`; those are emitted with `core.warning`, never
   `core.setFailed`. The run finishes green with label operations missing and
   nothing announces it.

Verified against the pinned runtime rather than inferred: `max` caps safe-output
ITEMS (tool calls) per type, not label names inside a call. A two-label call
costs one item.

Capacity: largest supported activation is 50 issues (`enterprise` profile
`max_issues: 50`, the highest documented profile limit, and the same threshold
`squad-plan-activate` uses to force phased activation). Worst case at that size
is 50 `create-issue` items, 50 `add_labels` calls, <=2 labels per call, 100
label names across the run.

Changes:
- `add-labels: max` 80 -> 110, sized to cover the worst case under BOTH readings
  (50 calls, 100 names) so no interpretation of the cap can justify dropping a
  label operation. `create-issue` stays at 75.
- Record the derivation and the item-vs-label-name semantics in the activation
  skill, plus the fact that an over-limit item is dropped, not failed.
- New Step 2e Label-Operation Reconciliation: track `activated` vs `labeled`,
  count a never-made/rejected/errored call as unlabeled, and on shortfall call
  `report_incomplete` naming the affected work items. gh-aw treats that as a
  failure signal even on successful exit, so a truncated activation can no
  longer be recorded as clean. Cap exhaustion becomes a nameable cause when
  observed; #1683's rule against guessing at caps is preserved and narrowed.

Tests: `test/gh-aw-activation-capacity.test.ts` (27) covers the derived maximum,
capacity under both readings, at-maximum and one-over boundaries, and the
reconciliation contract. Compiled-artifact assertions prefer runtime evidence
over prose: the declared cap reaching `GH_AW_SAFE_OUTPUTS_CONFIG`, the injected
constraint carrying the same number, `report_incomplete` being present (and so
callable), and agent-job permissions staying `issues: read`. Fails closed if
`gh aw` is absent, per #1834. Mutation-checked: reverting the cap to 80 fails 4.

No changes to temporary-ID linkage (#1962), fast-path parity (#1959), label
result reporting (#1963), broad contract coverage (#1960), or E4 (#1958).
Step 2e is deliberately neutral about how `add_labels` identifies its target so
it does not conflict with #1962.

Closes #1961
Parent #1957

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(gh-aw): correct runtime claims in activation capacity safeguards

Independent review found three factual defects in the prose and tests
shipped by the first commit. All three are corrected against the pinned
gh-aw v0.87.10 sources rather than gh-aw's own injected descriptions.

1. `report_incomplete` does NOT make the run conclude non-successfully.
   `report_incomplete_handler.cjs` emits `core.warning` only, and
   `handle_agent_failure.cjs` contains zero `setFailed`/`process.exit`
   calls in 4453 lines. What it actually does is open or update a durable
   `[aw] {workflow} reported incomplete result` tracking issue. Step 2e
   now states that, says the run still reports success, and tells the
   agent never to rely on a red run to carry the signal. gh-aw's own tool
   description ("treated as a failure signal even when the agent exits
   successfully") is misleading; trusting it was exactly the injected-prose
   mistake #1961 exists to prevent.

   Limitation, stated honestly: no narrow mechanism in the pinned runtime
   makes an incomplete activation conclude red. Forcing one would require
   a custom safe-job, which is outside this issue's scope. The durable
   tracking record plus the "never report a clean activation you did not
   perform" rule are what carry the signal.

2. Cap enforcement is dual, not collection-only. Per Safe Outputs MCE4,
   `enforcePerTypeMax` in `safe_outputs_handlers.cjs` throws JSON-RPC
   `E002: {type} limit reached` at invocation time, which the agent DOES
   see; the collector then drops surplus items with a warning. Removed the
   claim that an over-limit item "never appears as an error to the agent".
   Reconciliation still keys on absence-of-success, not presence-of-error,
   because a call can also simply never be made.

3. The old `max: 80` did not cause runtime truncation — 50 calls never
   reached it. The real hazard is gh-aw's injected "Maximum 80 label(s)
   can be added" wording against a 100-label worst case, which invites
   agent self-truncation. 110 is justified by that hazard plus bounded
   margin, and the docblock now explicitly records what is NOT claimed.

Also, per the PR #1965 review: Step 2e no longer demands a real issue
number for items created during the run. Issue creation is deferred to
the post-agent job, so it names the stable temporary ID plus title and
intended labels, and quotes a real number only for a reused issue —
avoiding reintroduction of #1962's invalid-number assumption.

Tests: renamed the two overclaiming tests and gave each a negative guard
that fails if the retracted wording returns; added coverage for the
temporary-ID rule. Trimmed prose to stay under the existing 160 KB
source-growth guard rather than raising another test's budget.

Verified: 221/221 across the three gh-aw suites; mutation-checked (cap
-> 80 fails 5 tests incl. the compiled-runtime one, reintroducing either
retracted claim fails its guard); strict compile clean on all four
workflows; npm run build passes.

Closes #1961
Parent #1957

Working as FIDO (Quality Owner)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 2471face-3b27-4419-bd48-0becd2642d7f

* test(gh-aw): use explicit .js extension on helper import

Addresses Copilot review on PR #1964. The reviewer is correct on both counts.

`tsc --module nodenext --moduleResolution nodenext` reports exactly one error
on this file, and TypeScript names the fix itself:

  test/gh-aw-activation-capacity.test.ts(94,46): error TS2835: Relative import
  paths need explicit file extensions in ECMAScript imports when
  '--moduleResolution' is 'node16' or 'nodenext'. Did you mean
  './helpers/gh-aw-lock.js'?

The repo is `"type": "module"` with `module`/`moduleResolution: NodeNext` in the
root tsconfig, and the four other suites importing this helper already use the
`.js` specifier. This file was the lone outlier; it now matches.

Verified: 293/293 across all eight suites that import the helper, all four
workflows compile with `--strict` (pre-existing warnings only), `npm run build`
passes, and the NodeNext type-check on this file is now clean.

Refs #1961. Parent #1957.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 2471face-3b27-4419-bd48-0becd2642d7f

* fix(workflows): state Step 2e counts as accepted operations, not applied labels

Copilot review flagged that Step 2e's reconciliation claimed issues
"received their labels". #1963 (now merged to dev) settled the
vocabulary: an accepted safe output is queued this turn and applied by
the post-agent job, so the agent has evidence only that a call was
accepted for a specific target -- never that a label reached GitHub.
Step 2e was the remaining place still asserting application, which
conflicts with the accepted-vs-applied rule the same skill now states.

- `labeled` is defined as issues whose add_labels call was accepted.
- The report_incomplete reason reads "had a label operation accepted".
- "proof that every label landed" -> "every label operation was accepted".
- Added an explicit statement that the counts track label operations,
  not labels present on GitHub.

Tests: new assertion guards the positive and both retired over-claim
phrasings; verified by reverting the prose (1 failed, 28 passed) rather
than assuming. Tightened the sibling assertion to match the exact count
definitions -- the previous `.*`-joined form matched a distant
"was accepted" elsewhere in the flattened skill and so failed to detect
a reverted definition.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0515ad5d-4c5b-48bb-92a6-4e1296594cab

* test(gh-aw): anchor the false-success assertion, which was vacuous

Copilot review caught that the regex ended in an `|activated.*artifact`
alternative. Alternation binds loosest, so the whole pattern collapsed to
that branch and matched any mention of the artifact -- the test would
have passed with the `labeled < activated` condition deleted from the
prose, which is the entire invariant it names.

Anchored to the full sentence and verified by mutation: removing the
condition from Step 2e now fails (1 failed / 28 passed) where it
previously passed.

Second instance of this defect class in this suite; the sibling count
assertions were tightened in 4ec89dde for the same reason. Audited the
remaining alternations here -- `/finish green|still succeeds/` is
legitimate (two accepted phrasings, both specific).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0515ad5d-4c5b-48bb-92a6-4e1296594cab

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 2471face-3b27-4419-bd48-0becd2642d7f
Copilot-Session: 0515ad5d-4c5b-48bb-92a6-4e1296594cab

* docs: add .squad/templates/README.md — runtime inputs vs bootstrap templates (#1949)

* docs: add .squad/templates/README.md — runtime inputs vs bootstrap templates

Add a README.md template that ships with squad init to explain which files
under .squad/templates/ are runtime inputs (coordinator reads them on-demand)
vs bootstrap templates (used once to seed agent files). Register it in the
TEMPLATE_MANIFEST so it lands in every generated project and is kept current
by squad upgrade.

Also drop a copy of the README into this repo's .squad/templates/ directly.

Closes #1494

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(templates): make templates README reach squad init output

Copilot review on #1949 found that registering `templates-readme.md` in
TEMPLATE_MANIFEST does not put the README into `squad init` output. Verified:
`squad init` seeds `.squad/templates/` with a verbatim recursive copy of the
SDK templates directory (`copyRecursiveSync(getSDKTemplatesDir(), ...)` in
packages/squad-sdk/src/config/init.ts), so a file only reaches new projects if
it lives in that directory under its final name. The README existed only as
`packages/squad-cli/templates/templates-readme.md`, so new projects got nothing.

Promote the file to the canonical source `.squad-templates/README.md` and let
scripts/sync-templates.mjs mirror it to templates/, packages/squad-cli/templates/
and packages/squad-sdk/templates/. Manifest source becomes `README.md` so the
canonical name already matches the destination name.

Verified `getSDKTemplatesDir()` resolves to packages/squad-sdk/templates and that
README.md is now present there — the exact path init copies from.

Also correct the bootstrap table: the charter template on disk is `rai-charter.md`
(lowercase), not `Rai-charter.md`.

Pin the routing in test/template-routing.test.ts. Mirror sync is already covered
by test/template-sync.test.ts, which enumerates `.squad-templates/` dynamically.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0515ad5d-4c5b-48bb-92a6-4e1296594cab

* docs(templates): document all .squad/templates subtrees

Copilot review flagged that the README omitted every subtree that ships
under .squad/templates/, while the Invariant said anything unlisted is
"a stale copy and safe to remove". Verified the risk is real:

- squad init copies this directory recursively (copyRecursiveSync,
  init.ts:1481), so casting/, identity/, scripts/, skills/ and
  workflows/ all ship into every new project.
- .squad/templates/casting/ is read at runtime by Init Mode to allocate
  custom-universe names, so deleting it breaks casting.
- .squad/templates/scripts/ and workflows/ are documented copy-sources
  in shipped docs (state-backends, ci-cd-integration).

Add a Subtrees table classifying all five, scope the Invariant to
top-level files so absence from the two tables no longer implies a
subtree is stale, and correct the historical note: it told users the
workflows/ and skills/ subtrees were "safe to delete", which contradicts
the docs that instruct copying from workflows/ and would delete the
source the manifest installs skills from.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0515ad5d-4c5b-48bb-92a6-4e1296594cab

* docs(templates): make the Invariant fail safe for unclassified files

Second round of Copilot review found my subtree fix was incomplete: the
same "not in a table => stale and safe to remove" hazard still applied to
top-level files.

Audited every top-level file against both tables and TEMPLATE_MANIFEST.
Ten are in neither table and unregistered -- including notes-protocol.md,
which the state-backends doc tells users to copy into .squad/. The tables
are not a complete inventory, so "safe to remove" was an unsafe default.

- Absence from the tables now means unclassified, not stale; removal
  requires positive evidence nothing reads or copies the file.
- notes-protocol.md named explicitly as the worked example.
- Registration is stated as expected for new files rather than as a
  property all current files have, which they do not.

Also corrected the casting/ row: it cited .copilot/skills/init-mode,
a legacy path users do not get after squad init. No shipped template
references the casting/ directory, so the row now describes the data and
points at casting-reference.md instead of a path that would mislead.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0515ad5d-4c5b-48bb-92a6-4e1296594cab

* docs(templates): classify README.md, which broke its own Invariant

Copilot review noted the README was the one top-level file its own rule
left unaccounted for. Now that absence from the tables means
"unclassified" and requires classification, that is a real
self-contradiction rather than a cosmetic gap.

It fits neither table -- it is not a runtime input and seeds nothing --
so it is classified explicitly instead of being forced into one: it
ships as the directory's own documentation via the same recursive copy,
and is manifest-registered so squad upgrade maintains it.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0515ad5d-4c5b-48bb-92a6-4e1296594cab

* fix(templates): repair merged table row and correct casting/ claim

Two Copilot findings:

1. The copilot-instructions.md and fact-checker-charter.md rows were
   concatenated onto one line, breaking the bootstrap table. Introduced
   by a stray edit in the previous commit; the table now renders again.

2. The casting/ row claimed the directory is read during Init Mode
   casting. Nothing shipped references it, which is the whole reason
   #1972 exists -- so the row asserted a consumer this PR had already
   established does not exist, and contradicted its own description.
   Reclassified as shipped data with no known consumer, still
   explicitly not-safe-to-delete pending #1972.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0515ad5d-4c5b-48bb-92a6-4e1296594cab

---------

Co-authored-by: brady gaster <bradygaster@github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0515ad5d-4c5b-48bb-92a6-4e1296594cab

* feat(gh-aw): add Squad repo enlistment skill (#1946)

* feat(gh-aw): add Squad repo enlistment skill

Add the gh-aw-enlistment skill that operationalizes the supported Squad
GitHub Agentic Workflows bootstrap: install the four @dev workflows, strictly
compile, honor an explicit safe-update allowlist (only the documented Squad
secrets and squad-init action), keep the default workflow token read-only,
stage only documented surfaces, and open a human-reviewed bootstrap PR that is
never auto-merged. Resolves repo identity at runtime for cross-repo safety.

Ships canonical (.squad/skills) plus both template mirrors, a focused
safety-gate regression test, a changeset, and a discoverability pointer from
the agentic-workflows router.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* test: anchor final strict-compile assertion to start-of-line (m flag)

The previous lookahead regex matched prose/backtick mentions in the Anti-Patterns section, as flagged by the code reviewer (comment 3884574741). Replace with /^gh aw compile --strict(\s+#[^\n]*)?$/m so only real command lines (L151, L260) satisfy the test; lines with --approve or indented prose do not.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(skills): make gh-aw preflight portable and bound the safe-update allowlist

Address two suppressed concerns from Copilot's second review of the
gh-aw-enlistment skill.

Portability: the step-0 extension check used `gh extension list | grep -q`,
which fails in default Windows PowerShell even though the skill is explicitly
portable. `gh extension list` has no `--json` flag, so there is no gh-native
structured check; document a verified PowerShell alternative alongside the bash
form, matching the existing step-6 portability-note convention.

Allowlist exclusivity: the safe-update allowlist is now delimited by
`<!-- allowlist-start -->` / `<!-- allowlist-end -->` so tests can bound it.
The previous tests were named as if they enforced exclusivity but only asserted
whole-document string presence, which could not fail if the allowlist grew.
They now extract the delimited region and deep-equal the sorted token set
against exactly SQUAD_GITHUB_APP_PRIVATE_KEY, SQUAD_GITHUB_TOKEN, and
bradygaster/squad/.github/actions/squad-init, assert both delimiters appear
exactly once, and assert the bullet-line count so structural drift is caught.
A new test guards the portability fix by requiring Select-String to be bound to
the github/gh-aw pattern and to guard an install.

All three skill copies (canonical, CLI template, SDK template) remain
byte-identical.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(skills): make gh-aw-enlistment triggers actually parse, strengthen guard

Copilot review on #1946 flagged that the discoverability assertions only checked
that trigger phrases appeared *somewhere* in the document, so they would still
pass if a phrase left the frontmatter `triggers:` list. Strengthening the
assertion to check the parsed `skill.triggers` array — the same array the runtime
matcher iterates in packages/squad-sdk/src/skills/index.ts — immediately failed,
revealing the weak assertion had been masking a real defect.

`parseFrontmatter` (packages/squad-sdk/src/skills/skill-loader.ts:48) is a naive
line-based parser that only understands inline arrays. Given a YAML block
sequence it stores the empty post-colon value as a string, so
`Array.isArray(meta.triggers)` is false and triggers resolve to `[]`. The skill
was therefore discoverable by NONE of its ten advertised phrases.

Measured across the three forms:

  block        -> ""                        (skill undiscoverable)
  inline+quoted-> ["\"a phrase\"", ...]      (quotes retained, never matches)
  inline bare  -> ["a phrase", ...]          (correct)

Convert this skill's triggers to the only form that parses into clean, matchable
strings. All ten phrases now resolve; canonical and both mirrors stay
byte-identical.

Also note in the router that the enlistment skill is local to this repository,
since the surrounding preamble says its listed files are fetched from
`github/gh-aw` and are not available locally.

The strengthened guard is verified by mutation: moving a phrase out of `triggers:`
while leaving it in prose leaves 2 textual occurrences (the old assertion would
have passed) and fails the new one.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0515ad5d-4c5b-48bb-92a6-4e1296594cab

* test(gh-aw): assert the STOP gate, not just the warning carve-out

The suite asserted that the bot-trigger warning is documented as
permitted, but not the halt that makes that carve-out safe. As written
it would keep passing if the STOP were deleted -- turning a narrow,
justified exception into a blanket "warnings are fine" without any
test noticing.

Asserts the full sentence (whitespace-collapsed, since it wraps).
Mutation-verified: weakening the STOP to a soft note fails this
assertion; the two mirror-parity guards also fire, since the mutation
was applied to one copy only.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0515ad5d-4c5b-48bb-92a6-4e1296594cab

---------

Co-authored-by: brady gaster <bradygaster@github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0515ad5d-4c5b-48bb-92a6-4e1296594cab

* docs(gh-aw): correct credentials guidance and document activation fixes (#1973)

* docs(gh-aw): correct credentials guidance and document activation fixes

The bootstrap procedure listed SQUAD_GITHUB_APP_PRIVATE_KEY and
SQUAD_GITHUB_TOKEN as a setup-time item with no statement that they need
not exist. The clarification sat ~95 lines downstream in an "Optional:"
section a reader following the numbered path never reaches before
deciding whether they are blocked. Two independent agents read that
passage and concluded a PAT was a prerequisite for enlisting a fresh
repo. It is not. The correction now lands inline at the point of
misreading, and is mirrored byte-identically into the three
gh-aw-enlistment SKILL.md copies (outside the bounded allowlist block).

Also documents four merged activation fixes that shipped with zero docs
changes, traceable to workflows/squad.md on dev:

- #1959 label auto-provisioning (squad.md:113-115, 1307, 1931-1945,
  2004) — add-labels create-if-missing auto-creates squad/squad:{agent};
  auto-provisioned labels get a deterministic color and empty
  description, which is expected and not a failure.
- #1961 bounded caps (squad.md:111, 121, 1997, 1999) — create-issue 75,
  add_labels 110; the two shortfall paths are kept distinct;
  report_incomplete does NOT fail the run, so the durable signal is the
  [aw] ... reported incomplete result tracking issue, not the run
  conclusion. A cap is named only when observed.
- #1963 accepted-vs-applied (squad.md:1392, 2058-2081) — defines
  accepted, states what a summary must not claim, and explains why the
  distinction exists (create-issue labels: silently drops missing names).
- #1962 temporary IDs — documented only where user-observable: shortfall
  reports identify items by #aw_epic{K}/#aw_task{N}/#aw_wi{N}.

Adds the Activation bindings: JSON block as the checkable verification
surface, and updates the stale troubleshooting row that predated #1961.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* chore: add changeset for gh-aw-enlistment skill template change

The changelog gate's SDK_CLI_PATH_REGEX (squad-ci.yml:273) matches
^packages/squad-(sdk|cli)/templates/, not just src/ — template edits ship
as scaffolding and are covered deliberately. Both packages distribute the
gh-aw-enlistment skill, so both take a patch bump.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* docs(gh-aw): correct activation capacity and rescope label-evidence claim

Addresses review findings A-D on the activation section.

A. The cap table presented 75 as "issues created in one run", which would
   lead a reader to size for 75. squad.md:105-107 states the actual
   ceiling is 50 issues per activation run; 75 is 50 worst-case plus 25
   bounded margin, and 110 covers both readings of the add-labels worst
   case (50 calls / 100 label names). Now states the 50-issue ceiling as
   the user-facing number and presents 75/110 as underlying headroom,
   preserving the workflow's statement that `max` counts safe-output
   items (tool calls), not label names.

B. Rescoped the label-evidence claim to the workflow's own epistemic
   scope (squad.md:2059-2060): `create-issue`'s `labels:` field never
   lands a label the activation run can claim. Dropped the generalized
   assertion about GitHub API behavior. Note: "silently drops names the
   repository lacks" is verbatim shipped prose at squad.md:2060 — the
   scoping concern is upstream in the workflow, flagged rather than
   propagated here.

C. Added the fast-path phase temporary ID `#aw_ph{N}` (squad.md:1289),
   which was missing from the documented identifier set.

D. Listing labels proves a label exists, not that it landed on the right
   issue. Added a per-issue verification path: read the Activation
   bindings: block from the origin issue's comments, then compare each
   binding against `gh issue view {issue} --json title,labels`.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* docs(gh-aw): explain add-labels vs add_labels naming surfaces

Review flagged the two spellings as inconsistent. Audited every
occurrence: all six are already correct for their surface. The hyphenated
add-labels is the safe-outputs configuration key (squad.md:113) and is
what the caps apply to; the underscored add_labels is the run-time tool
call (squad.md:1294) and is what appears in summaries and incomplete
reports. Rather than collapse them to one spelling, which would make one
of the two surfaces unsearchable, this states the distinction explicitly
at first joint mention.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Enable online documentation in Squad research (#1977)

* feat: enable online Squad research

Enable web-fetch for /squad research, prefer current authoritative documentation, and disclose when online sources are unavailable.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 7d6c4262-f790-49ff-88f8-8aae54b9287c

* test: simplify section extraction

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7d6c4262-f790-49ff-88f8-8aae54b9287c

* Close direct cast issues when their PRs merge (#1975)

* feat: close direct cast issues on merge

Closes #1974

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d20ee964-dcbd-4e17-921d-e624f8bc0eb3

* test: simplify cast pivot assertion

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d20ee964-dcbd-4e17-921d-e624f8bc0eb3

* fix: clarify cast issue substitution

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d20ee964-dcbd-4e17-921d-e624f8bc0eb3

---------

Copilot-Session: d20ee964-dcbd-4e17-921d-e624f8bc0eb3

* fix(gh-aw): make Cast validator delivery deterministic (#1976)

* fix(gh-aw): make Cast validator delivery deterministic

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(gh-aw): anchor Cast validation failures

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(gh-aw): authenticate Cast validator bytes

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(gh-aw): accept CRLF validator markers

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* test: avoid variable-length validator lookbehind

Use capture groups when replacing the embedded validator payload so the portability regression fixture does not depend on variable-length lookbehind support.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix: order Cast validator find options

Place the depth limit before predicates so validator discovery remains bounded and deterministic across find implementations. Add a regression assertion for the command shape.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* test: clarify Cast command budget source

State explicitly that the command markers are authored inside the squad-cast inline skill, which gh-aw extracts from the ambient prompt.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* test: resolve workflow shell on Windows

Use the shared POSIX-shell resolver for Git for Windows while retaining bash execution on POSIX hosts for the workflow's pipefail contract.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(gh-aw): make Cast failures truthful (#1978)

Materialize and authenticate the Cast validator outside the agent prompt, preserve exact validation authorization, and emit bounded factual terminal failures without success-shaped reporting.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 84876c36-36ab-4d53-a689-6ab9a52fe551

* fix(gh-aw): restore public installability after #1977 (#1979)

* fix(gh-aw): restore public installability after #1977

PR #1977 added correct safety prose telling research runs to distrust
fetched web content, but it quoted a canonical adversarial phrase
verbatim. `gh aw compile --strict` does not run gh-aw's markdown
security scanner, so the source PR passed; `gh aw add` does run it, so
every consumer bootstrapping from dev hit:

  workflows/squad.md:1438:1: error: [social-engineering] contains
  prompt injection pattern (attempts to override AI agent instructions)

Rephrase the line to describe the override attempt instead of
reproducing it. Online research and fetched-content distrust semantics
are unchanged: fetched pages remain untrusted evidence, never
instructions, and embedded directives, persona assignments, tool-use
requests, and instruction-override attempts are still ignored.

Add test/gh-aw-security-scan.test.ts as the regression guard. It runs
the real gh-aw scanner over every distributed workflow Markdown file
rather than a handwritten phrase blocklist, which would drift from
gh-aw's ruleset. The gate is offline, needs no GitHub round-trip, runs
in seconds, and fails closed per the #1833/#1834 convention.

Scratch repos are created outside this checkout: gh aw add resolves
.github/workflows/ by walking up from its working directory, and a
nested workspace let it escape into the real tree and write stray
files there. A self-check asserts the sandbox held.

Verified: the guard fails on pre-fix content with the exact scanner
error and passes after; all four workflows strict-compile; the public
four-workflow gh aw add succeeds from the pushed branch.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(gh-aw): address review on the security-scan gate

Two findings from Copilot review on #1979.

1. `git commit` in the scratch repo made the gate flaky on machines with
   `commit.gpgsign=true` set globally and no usable signing key. Rather
   than disabling signing, drop the commit entirely: an empty `git init`
   is sufficient for gh-aw once the workspace lives outside this
   checkout. The commit was only ever compensating for the earlier
   in-repo workspace, so removing it eliminates the failure class
   instead of suppressing it. Verified green with
   `commit.gpgsign=true` forced.

2. The `-n` comment claimed it avoided a batch-abort on basename
   collision, but each file already gets its own workspace, so no such
   collision exists. Corrected to state the real reason: a deterministic
   installed name for the sandbox-leak self-check.

Guard re-verified in both directions after the refactor: fails on
pre-fix content with the exact scanner error, 10 passed on this branch.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* test(gh-aw): prove the scan gate needs no commit, under hostile signing

Independent review flagged the same portability defect Copilot did: a
scratch-repo commit inherits global `commit.gpgsign=true`, so a machine
without a usable signing key fails before gh-aw's scanner ever runs,
turning an installability gate into an environment-dependent one.

0f26442 already removed the commit (the reviewer's preferred option:
`git init` alone is sufficient once the workspace lives outside this
checkout). What was missing is the reviewer's second ask -- making the
property non-regressable rather than merely documented.

Add a test that executes a real scan under a signing-hostile git
environment: `commit.gpgsign=true`, `tag.gpgsign=true`, and
`gpg.program` pointed at a path asserted not to exist. Any reintroduced
commit dies there, while a path that never commits is unaffected.
Verified by temporarily restoring the commit: the new test fails with
"gpg failed to sign the data". It passes on this branch.

Config is injected through `GIT_CONFIG_COUNT`/`GIT_CONFIG_KEY_n`, which
applies to every git process in the subtree, including any git that
`gh aw` shells out to, without mutating global config.

Scope unchanged: two files. Guard still bidirectional (fails on pre-fix
content with the exact scanner error). Targeted suites 218 passed,
eslint and tsc clean.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(gh-aw): fast-path /squad activate artifact integrity (E4 preflight A) (#1980)

* fix(gh-aw): fast-path /squad activate artifact integrity (E4 preflight A)

Closes the gap where the recommended /squad activate fast path
(squad-plan-accept, artifacts plan-accepted/phases-accepted) created and
labeled issues identically to the granular /squad plan activate path but
was not covered by the Activation bindings: contract, the deterministic
checker, or the CI collector.

- workflows/squad.md: fast path Step 4 now requires the same non-empty
  Activation bindings: JSON block (shape/quoting/omission semantics) as
  squad-plan-activate. Renamed both paths' label-reporting heading to the
  identical "Label operations accepted" text. Reworded the "label set it
  should have received" trap phrase to drop the forbidden certainty word
  "received" while preserving meaning.
- workflows/shared/squad-planning-ontology.md: the bindings mapping is now
  documented as mandatory for phases-accepted/plan-accepted too, not just
  phases-activated/activated.
- scripts/check-agent-binding.mjs: ACTIVATION_ARTIFACTS now includes
  plan-accepted/phases-accepted so missing/empty bindings fail closed for
  fast-path artifacts exactly like granular ones. Added
  assertAcceptedOnlyLabelWording(), which rejects standalone certainty
  claims (applied, received, landed, verified, confirmed, checked) in
  label-operation reporting. It is scoped to lines that actually mention
  label vocabulary, strips fenced/inline code and quoted strings first,
  skips markdown table rows, and treats explicit negations as compliant --
  never a blanket whole-comment scan -- so quoted titles, unrelated
  sections, negations, and substrings (unverified) don't false-positive.
  Wired into main()'s per-comment loop.
- .github/workflows/squad-agent-binding-check.yml: the collector filter
  matched only /activated/i, which a plan-accepted/phases-accepted comment
  never contains, so fast-path artifacts were silently never passed to the
  checker. Now matches the squad_artifact field precisely for all four
  activation artifact types.
- test/gh-aw-activation-artifact-integrity.test.ts (new): heading parity,
  fast-path bindings-contract presence + mutation kills against committed
  source, checker/runtime parity across all four artifact types (missing
  and [] bindings), a full parseStructuredData+validateActivation pipeline
  test against realistic comment strings (including bindings-block
  deletion/emptying), parameterized forbidden-word rejection (6 words x
  case/punctuation), negative tests for quoted titles/table
  rows/unrelated sections/negations/substrings, and collector-regex
  parity/regression tests.
- test/gh-aw-activation-capacity.test.ts: updated the one existing
  assertion pinned to the reworded trap phrase.

Out of scope per the E4 preflight package A brief: workflow discriminators,
docs sequencing, draft PR UX, and all other E4 findings.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(gh-aw): scope negation/claim detection to clauses in label-wording check

FIDO rejected the first revision of #1980 with two reproduced defects in
assertAcceptedOnlyLabelWording (scripts/check-agent-binding.mjs):

1. False negative: NEGATION_NEARBY matched a negation anywhere on the whole
   line, so an unrelated negation earlier in the line (e.g. "No issues were
   skipped") blanket-suppressed a real, separate certainty claim later in the
   same line ("Label squad:kint was verified for #42").
2. False positive: a forbidden word describing an unrelated subject sharing a
   line with a label token ("its verified real number" describing a reused
   issue number, not the label operation) was incorrectly flagged.

Fix: split each line into clauses on clause/sentence-ending punctuation
(., ,, ;, :), protecting squad:{agent} tokens so their embedded colon is never
mistaken for a clause boundary. Label-operation context, the forbidden word,
and any negation must now all be found within the *same* clause before a
claim is flagged. This lets an unrelated negation in a different clause fail
to suppress a real claim, and lets a forbidden word in a clause that carries
no label-operation context correctly fall out of scope, without weakening the
existing quoted-title/table-row/code-fence/substring/negation guards or the
six forbidden standalone certainty claims (applied, received, landed,
verified, confirmed, checked).

Adds two permanent regression tests reproducing FIDO's exact reported
strings in test/gh-aw-activation-artifact-integrity.test.ts.

Testing:
- npx vitest run test/gh-aw-activation-artifact-integrity.test.ts — 90/90
  passed (88 previously + 2 new regression tests)
- npx vitest run test/check-agent-binding.test.ts
  test/gh-aw-activation-summary-outcomes.test.ts
  test/gh-aw-activation-capacity.test.ts test/gh-aw-quality.test.ts
  test/gh-aw-activate-roster-binding.test.ts
  test/gh-aw-agent-binding-correspondence.test.ts
  test/gh-aw-activation-artifact-integrity.test.ts — 377/377 passed
- npx vitest run (full suite) — only pre-existing, unrelated failures
  remain (externalized-state CLI tests), confirmed identical on the
  pre-revision commit
- npx eslint scripts/check-agent-binding.mjs
  test/gh-aw-activation-artifact-integrity.test.ts
  test/gh-aw-activation-capacity.test.ts — clean
- npm run build — succeeds; build-metadata/version-bump and skill-template
  CRLF sync side effects reverted before commit, not part of this diff

Scope: only scripts/check-agent-binding.mjs and
test/gh-aw-activation-artifact-integrity.test.ts touched, per FIDO's
required narrow revision.

Closes the FIDO REJECT on #1980.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(gh-aw): resolve quoted issue references before prefetching labels

main() filtered binding.issue/epic_issue with Number.isInteger, but
compliant activation artifacts write these as quoted "#42" strings per
the resolveIssueReference() contract. That produced an empty issues
list, skipped label fetching entirely, and made validateActivation()
fail with "labels could not be resolved" for otherwise-valid bindings.

Add extractIssueNumber(), a non-throwing counterpart to
resolveIssueReference() that also accepts the "#42" string form, and
use it when building the label-prefetch list in main().

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* test(gh-aw): cover quoted activation references

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(gh-aw): add dispatch job discriminators (#1981)

Refs #1958

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* test(gh-aw): prove plaintext resource delivery (#1983)

* feat(gh-aw): add resource delivery probe

Closes #1982

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 083906de-529b-42f9-ae2d-36b0c911eaef

* chore(gh-aw): keep resource probe scope focused

Closes #1982

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 083906de-529b-42f9-ae2d-36b0c911eaef

* test(gh-aw): exercise resource readability guard (#1982)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 083906de-529b-42f9-ae2d-36b0c911eaef

---------

Copilot-Session: 083906de-529b-42f9-ae2d-36b0c911eaef

* gh-aw: replace gzip+Base64 Cast validator transport with plaintext resource (#1986)

* gh-aw: replace gzip+Base64 Cast validator transport with plaintext resource

Replace the fake-skill gzip+Base64 transport for the Cast validator
(workflows/shared/squad-cast-validator.md, materialized at runtime via
SKILL.md discovery and gunzip/base64 extraction) with a canonical
plaintext gh-aw resources sidecar, workflows/shared/squad-cast-validator.mjs,
installed verbatim at .github/workflows/shared/ in consumer repos.

- workflows/squad.md: declare the validator as a resources entry (not
  imports); rewrite the validator runner step to execute the installed
  resource directly from GITHUB_WORKSPACE (never staged to or run from
  RUNNER_TEMP); drop the SKILL.md search/extraction logic; restore the
  pwd -P physical-path normalization the old script relied on (needed
  so import.meta.url resolution is not defeated by symlinked
  temp/workspace paths); reduce the cast-failure job stage taxonomy
  from 6 to 4 stages (discovery/integrity/syntax/validation); update
  Step 7 docs and stage table to match.
- workflows/shared/squad-cast-validator.mjs: new plaintext resource,
  byte-identical to scripts/validate-gh-aw-cast.mjs, pinned by
  SHA-256 in the runner script.
- Remove workflows/shared/squad-cast-validator.md (fake-skill payload)
  and workflows/shared/squad-gh-aw-resource-probe.txt (experimental
  probe-only resource from #1982/#1983), plus their .gitattributes
  entry and probe-only docs.
- test/gh-aw-cast-validator.test.ts, test/gh-aw-quality.test.ts:
  rewrite delivery-mechanism coverage for the new 4-stage model;
  remove probe-only tests; update SOURCE_GROWTH_BUDGET_KB.

Pinned SHA-256 authentication, node --check, the exact authorization
output ("Cast validation passed."), and the typed Cast failure
contract (fail-closed on missing/unreadable/modified/syntactically
invalid/rejecting validators) are unchanged. The direct install path
in .github/AGENTS.md (gh aw add bradygaster/squad/workflows/squad.md@dev)
is untouched.

Validation:
- npx vitest run test/gh-aw-cast-validator.test.ts test/gh-aw-quality.test.ts
  -> 213/213 passed (includes dynamic gh-aw strict-mode compile via
  lockText()).
- Manual gh aw compile squad --strict against a scratch workspace
  (repository-pinned gh-aw v0.87.10): compiled successfully; inspected
  generated squad.lock.yml runner script contains no SKILL.md search,
  base64, or gzip logic, reads validator_script directly from
  GITHUB_WORKSPACE, and preserves the 4-stage fail_cast taxonomy.
- npm run build (packages/squad-sdk then packages/squad-cli): passed.

Closes #1984

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* test(gh-aw): restore cast-failure output diagnostic tests

Restore three tests deleted during the plaintext resource transport
migration for unchanged cast-failure safe-output handler behavior:
- fails malformed agent output with a deterministic diagnostic
- fails non-object output items with a deterministic diagnostic
- diagnoses conflicting failure and pull-request outputs without
  claiming prevention

Closes #1984

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Fix Cast validator sandbox path (#1989)

* fix: keep Cast validator inside sandbox workspace

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* test: remove redundant Cast fixture setup

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Preserve built-in agents in gh-aw casts (#1990)

* fix: preserve built-in agents in gh-aw casts

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: bc7757e5-628e-4f82-bb3c-7ea20b6b6056

* fix: address built-in validation feedback

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: bc7757e5-628e-4f82-bb3c-7ea20b6b6056

* test: use canonical fact-checker directory

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: bc7757e5-628e-4f82-bb3c-7ea20b6b6056

---------

Copilot-Session: bc7757e5-628e-4f82-bb3c-7ea20b6b6056

* gh-aw: enforce byte-identical built-in charters and fix late-restore clobbering (#1992)

* gh-aw: enforce byte-identical built-in charters in Cast validator

Strengthen the GH-AW Cast validator so it fails Cast validation unless
every final .squad/agents/{scribe,ralph,rai,fact-checker}/charter.md
is byte-for-byte identical to its canonical resource under
.github/workflows/shared/builtins/{id}-charter.md. Previously the
validator only checked that the four built-in directories existed and
were referenced correctly, not that their content survived intact
through a squad init run or agent rewrite after the deterministic
materialization step.

- Add validateBuiltinCharterFidelity to
  workflows/shared/squad-cast-validator.mjs, mirrored verbatim to
  scripts/validate-gh-aw-cast.mjs.
- Update the validator SHA-256 pin in workflows/squad.md for the new
  validator bytes.
- Update test/gh-aw-cast-validator.test.ts fixtures to materialize
  real canonical built-in charter content (read from
  workflows/shared/builtins/) instead of placeholders, and add
  focused tests covering byte-mismatch rejection, missing canonical
  resource, and byte-identical acceptance.
- Update the hardcoded SHA-256 expectation in
  test/gh-aw-quality.test.ts.

Validated: targeted vitest run (226 passed), full gh-aw-*.test.ts run
(699 passed, 1 pre-existing unrelated failure from an unbuilt SDK
workspace package), and gh aw compile --strict for all four Squad
workflows using the pinned v0.87.10 compiler via the repo's
CI-mirroring recipe.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* gh-aw: run built-in charter materialization as a pre-agent-step

Fix the residual clobbering path the byte-fidelity validator (previous
commit) could only detect, not prevent: gh-aw's native
"Restore agent config folders from base branch" and the (unconditional,
no runtime if:-guard) repeated "Restore ambient folders from activation
artifact" step run AFTER our old steps: placement, and can reintroduce
a stale committed .squad/ snapshot over the freshly materialized
built-in charters whenever this workflow's pull_request_comment trigger
causes checkout-pr to succeed and a stale .squad/ already exists on the
relevant ref (matching the octodemo/zava-social-squad-backend#13
scenario, and the residual gap identified in review of PR #1992).

Root-cause detail confirmed empirically against the compiled lock file
(pkg/workflow/compiler_yaml_ai_execution.go in github/gh-aw): custom
steps: are always spliced in early (right after the activation-artifact
download), while base-branch restore, both ambient-folder restores, and
inline sub-agent/skill restore are compiler-injected later in the same
job — before pre-agent-steps, MCP setup, and Copilot CLI execution. The
existing steps: mechanism was structurally unable to run after those
restores; pre-agent-steps is the documented gh-aw hook designed for
exactly this ordering need.

- workflows/squad.md: move "Materialize canonical built-in support
  agents" and "Prepare deterministic Cast validator runner" from
  steps: to pre-agent-steps:. Verified via `gh aw compile --strict`
  that both now execute after every restore step and before MCP setup
  / "Execute GitHub Copilot CLI".
- test/gh-aw-quality.test.ts: replace the now-inverted ordering
  assertion (validator-runner used to run before "Restore inline
  skills"; it now correctly runs after every restore and before agent
  execution) and add a new focused test asserting the full ordering
  invariant end-to-end: activation job (squad init) precedes the agent
  job; materialization runs after init and after every restore step
  (Squad state, base-branch, both ambient-folder occurrences, inline
  sub-agents, inline skills); and materialization precedes "Execute
  GitHub Copilot CLI".

Validated with the mandatory npm proxy set before every npm/npx
invocation:
- `npx vitest run test/gh-aw-cast-validator.test.ts test/gh-aw-quality.test.ts`
  -> 227/227 passed
- `npx vitest run test/gh-aw-*.test.ts` -> 700/700 passed (1
  pre-existing unrelated failure from an unbuilt SDK workspace package,
  same as before this change and on dev)
- `gh aw compile --strict` for all four Squad workflows using the
  pinned v0.87.10 compiler via the repo's CI-mirroring recipe — all 4
  succeeded
- Confirmed step order in the compiled squad.lock.yml directly:
  Restore agent config folders from base branch -> Restore ambient
  folders from activation artifact (2nd occurrence) -> Restore inline
  sub-agents -> Restore inline skills -> Materialize canonical
  built-in support agents -> Prepare deterministic Cast validator
  runner -> Start MCP Gateway -> Execute GitHub Copilot CLI

Only the already-authorized workflow/validator/test files were
touched; no changeset added (workflow/test-only scope is exempt from
the changelog gate's SDK/CLI path regex).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* deps: Bump fast-uri from 3.1.5 to 3.1.7 (#1991)

Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.5 to 3.1.7.
- [Release notes](https://github.com/fastify/fast-uri/releases)
- [Commits](https://github.com/fastify/fast-uri/compare/v3.1.5...v3.1.7)

---
updated-dependencies:
- dependency-name: fast-uri
  dependency-version: 3.1.7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Brady Gaster <41929050+bradygaster@users.noreply.github.com>

* deps: bump sharp from 0.35.3 to 0.35.4 in /docs in the minor-patch group (#1952)

Bumps the minor-patch group in /docs with 1 update: [sharp](https://github.com/lovell/sharp).


Updates `sharp` from 0.35.3 to 0.35.4
- [Release notes](https://github.com/lovell/sharp/releases)
- [Commits](https://github.com/lovell/sharp/compare/v0.35.3...v0.35.4)

---
updated-dependencies:
- dependency-name: sharp
  dependency-version: 0.35.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Brady Gaster <41929050+bradygaster@users.noreply.github.com>

* deps: bump astro in /docs in the astro-minor-patch group (#1950)

Bumps the astro-minor-patch group in /docs with 1 update: [astro](https://github.com/withastro/astro/tree/HEAD/packages/astro).

Updates `astro` from 7.2.4 to 7.2.9
- [Release notes](https://github.com/withastro/astro/releases)
- [Changelog](https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG.md)
- [Commits](https://github.com/withastro/astro/commits/astro@7.2.9/packages/astro)

---
updated-dependencies:
- dependency-name: astro
  dependency-version: 7.2.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: astro-minor-patch
...

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* deps: Bump qs from 6.15.2 to 6.16.0 (#1993)

Bumps [qs](https://github.com/ljharb/qs) from 6.15.2 to 6.16.0.
- [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ljharb/qs/compare/v6.15.2...v6.16.0)

---
updated-dependencies:
- dependency-name: qs
  dependency-version: 6.16.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Brady Gaster <41929050+bradygaster@users.noreply.github.com>

* deps: Bump @humanfs/node from 0.16.7 to 0.16.8 (#1994)

Bumps [@humanfs/node](https://github.com/humanwhocodes/humanfs/tree/HEAD/packages/node) from 0.16.7 to 0.16.8.
- [Release notes](https://github.com/humanwhocodes/humanfs/releases)
- [Changelog](https://github.com/humanwhocodes/humanfs/blob/main/packages/node/CHANGELOG.md)
- [Commits](https://github.com/humanwhocodes/humanfs/commits/node-v0.16.8/packages/node)

---
updated-dependencies:
- dependency-name: "@humanfs/node"
  dependency-version: 0.16.8
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Brady Gaster <41929050+bradygaster@users.noreply.github.com>

* ci: Bump github/gh-aw-actions (#1954)

Bumps the github-actions group with 1 update in the / directory: [github/gh-aw-actions](https://github.com/github/gh-aw-actions).


Updates `github/gh-aw-actions` from 0.87.2 to 0.87.9
- [Release notes](https://github.com/github/gh-aw-actions/releases)
- [Changelog](https://github.com/github/gh-aw-actions/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/gh-aw-actions/compare/v0.87.2...v0.87.9)

---
updated-dependencies:
- dependency-name: github/gh-aw-actions
  dependency-version: 0.87.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Brady Gaster <41929050+bradygaster@users.noreply.github.com>

* Preserve full URLs in Squad research output (#1998)

* fix(gh-aw): preserve research source URLs

Allow the public Microsoft Learn and Aspire documentation domains through safe-output URL sanitization while retaining credential and sensitive-query safeguards.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: f3bb47aa-1b45-4302-8ec2-5e3dc868de42

* test(gh-aw): tighten research URL guards

Assert the exact safe-output domain allowlist, tolerate prompt line wrapping, and exclude safe-output metadata from operation max validation.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 7abb1583-79f9-4355-882d-a9d099f6817f

---------

Copilot-Session: f3bb47aa-1b45-4302-8ec2-5e3dc868de42
Copilot-Session: 7abb1583-79f9-4355-882d-a9d099f6817f

* ci: Bump the github-actions group across 1 directory with 2 updates (#2002)

* ci: Bump the github-actions group across 1 directory with 2 updates

Bumps the github-actions group with 2 updates in the / directory: [github/gh-aw-actions](https://github.com/github/gh-aw-actions) and [actions/deploy-pages](https://github.com/actions/deploy-pages).


Updates `github/gh-aw-actions` from 0.87.9 to 0.88.4
- [Release notes](https://github.com/github/gh-aw-actions/releases)
- [Changelog](https://github.com/github/gh-aw-actions/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/gh-aw-actions/compare/v0.87.9...v0.88.4)

Updates `actions/deploy-pages` from 5.0.0 to 5.0.1
- [Release notes](https://github.com/actions/deploy-pages/releases)
- [Commits](https://github.com/actions/deploy-pages/compare/cd2ce8fcbc39b97be8ca5fce6e763baed58fa128...368f82528645a54fb793d4d04e342629a3f51346)

---
updated-dependencies:
- dependency-name: actions/deploy-pages
  dependency-version: 5.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: github/gh-aw-actions
  dependency-version: 0.88.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>

* ci: pin gh-aw actions to v0.88.4 commit

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Brady Gaster <brady.gaster@gmail.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* deps: Bump the minor-patch group across 1 directory with 4 updates (#2007)

* deps: Bump the minor-patch group across 1 directory with 4 updates

Bumps the minor-patch group with 4 updates in the /docs directory: [@astrojs/markdown-remark](https://github.com/withastro/astro/tree/HEAD/packages/markdown/remark), [@astrojs/sitemap](https://github.com/withastro/astro/tree/HEAD/packages/integrations/sitemap), [astro](https://github.com/withastro/astro/tree/HEAD/packages/astro) and [@playwright/test](https://github.com/microsoft/playwright).


Updates `@astrojs/markdown-remark` from 7.2.4 to 7.3.0
- [Release notes](https://github.com/withastro/astro/releases)
- [Changelog](https://github.com/withastro/astro/blob/main/packages/markdown/remark/CHANGELOG.md)
- [Commits](https://github.com/withastro/astro/commits/@astrojs/markdown-remark@7.3.0/packages/markdown/remark)

Updates `@astrojs/sitemap` from 3.7.3 to 3.7.4
- [Release notes](https://github.com/withastro/astro/releases)
- [Changelog](https://github.com/withastro/astro/blob/main/packages/integrations/sitemap/CHANGELOG.md)
- [Commits](https://github.com/withastro/astro/commits/@astrojs/sitemap@3.7.4/packages/integrations/sitemap)

Updates `astro` from 7.2.9 to 7.2.10
- [Release notes](https://github.com/withastro/astro/releases)
- [Changelog](https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG.md)
- [Commits](https://github.com/withastro/astro/commits/astro@7.2.10/packages/astro)

Updates `@playwright/test` from 1.62.1 to 1.63.0
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](https://github.com/microsoft/playwright/compare/v1.62.1...v1.63.0)

---
updated-dependencies:
- dependency-name: "@astrojs/markdown-remark"
  dependency-version: 7.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: minor-patch
- dependency-name: "@astrojs/sitemap"
  dependency-version: 3.7.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: minor-patch
- dependency-name: astro
  dependency-version: 7.2.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: minor-patch
- dependency-name: "@playwright/test"
  dependency-version: 1.63.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix(docs): stabilize Astro upgrade validation

Update generated Astro content types, preserve sidebar scroll before transition preparation, and refresh stale feature/API assertions.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Brady Gaster <brady.gaster@gmail.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Brady Gaster <41929050+bradygaster@users.noreply.github.com>

* deps: Bump the minor-patch group across 1 directory with 18 updates (#2008)

* deps: Bump the minor-patch group across 1 directory with 18 updates

Bumps the minor-patch group with 15 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [@opentelemetry/context-async-hooks](https://github.com/open-telemetry/opentelemetry-js) | `2.10.0` | `2.11.0` |
| [@opentelemetry/sdk-metrics](https://github.com/open-telemetry/opentelemetry-js) | `2.10.0` | `2.11.0` |
| [@opentelemetry/sdk-trace-base](https://github.com/open-telemetry/opentelemetry-js) | `2.10.0` | `2.11.0` |
| [@playwright/test](https://github.com/microsoft/playwright) | `1.62.1` | `1.63.0` |
| [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.67.0` | `8.69.0` |
| [cspell](https://github.com/streetsidesoftware/cspell/tree/HEAD/packages/cspell) | `10.0.1` | `10.2.2` |
| [eslint](https://github.com/eslint/eslint) | `10.8.1` | `10.10.0` |
| [markdown-it](https://github.com/markdown-it/markdown-it) | `15.0.0` | `15.0.1` |
| [vscode-jsonrpc](https://github.com/Microsoft/vscode-languageserver-node/tree/HEAD/jsonrpc) | `9.0.1` | `9.0.2` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `26.2.0` | `26.4.1` |
| [@github/copilot-sdk](https://github.com/github/copilot-sdk) | `1.0.11` | `1.0.13` |
| [typedoc-plugin-markdown](https://github.com/typedoc2md/typedoc-plugin-markdown/tree/HEAD/packages/typedoc-plugin-markdown) | `4.12.0` | `4.13.0` |
| [@opentelemetry/exporter-metrics-otlp-grpc](https://github.com/open-telemetry/opentelemetry-js) | `0.221.0` | `0.222.0` |
| [@opentelemetry/exporter-trace-otlp-grpc](https://github.com/open-telemetry/opentelemetry-js) | `0.221.0` | `0.222.0` |
| [@opentelemetry/sdk-node](https://github.com/open-telemetry/opentelemetry-js) | `0.221.0` | `0.222.0` |



Updates `@opentelemetry/context-async-hooks` from 2.10.0 to 2.11.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-js/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-js/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-js/compare/v2.10.0...v2.11.0)

Updates `@opentelemetry/sdk-metrics` from 2.10.0 to 2.11.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-js/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-js/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-js/compare/v2.10.0...v2.11.0)

Updates `@opentelemetry/sdk-trace-base` from 2.10.0 to 2.11.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-js/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-js/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-js/compare/v2.10.0...v2.11.0)

Updates `@playwright/test` from 1.62.1 to 1.63.0
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](https://github.com/microsoft/playwright/compare/v1.62.1...v1.63.0)

Updates `@typescript-eslint/eslint-plugin` from 8.67.0 to 8.69.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.69.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.67.0 to 8.69.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.69.0/packages/parser)

Updates `cspell` from 10.0.1 to 10.2.2
- [Release notes](https://github.com/streetsidesoftware/cspell/releases)
- [Changelog](https://github.com/streetsidesoftware/cspell/blob/main/packages/cspell/CHANGELOG.md)
- [Commits](https://github.com/streetsidesoftware/cspell/commits/v10.2.2/packages/cspell)

Updates `eslint`…
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.

Prevent silent truncation of Squad activation label operations

2 participants