Repository navigation
[Phase 3] Collapse the first repo's Class-1 event-driven stubs into agent-ingress.yml and rename the required checks #1729
Description
NEXT PR FOR DEV-LEAD — 2026-10-10 (do exactly this; everything else in this issue is context)
Scope: AC11(b) STUB_REGISTRY rows plus the AC4 no-resurrection proof, in THIS repo only. Use Refs #1729, not Closes: this PR does not finish the story.
- In both
scripts/fleet_monitor.shandscripts/fleet_stub_remediate.sh(the two registries are kept in lockstep), add oneSTUB_REGISTRYrow per collapsed markets role:dev-lead,pr-auto-review,pr-review,pr-review-mention,ci-failure-analyst.stub_path=.github/workflows/agent-ingress.ymlcanonical_path=standards/workflows/agent-ingress.ymlrole= the job name exactly as in markets'agent-ingress.ymllegacy_path=.github/workflows/<role>.ymllegacy_canonical_path=standards/workflows/<role>.yml. Use it only if that file exists inpetry-projects/.github(check it with the API). Otherwise leave it empty and say so in the PR body.
- The canonical template does not exist yet; it is published separately in
petry-projects/.github. The new rows must degrade the way the existing per-job path already does when the canonical file 404s: skip with a::warning::, write nothing, and leave the scheduled Actions Fleet Monitor run green. Add a bats case that proves this for a role row against a 404 canonical. - Add bats cases for AC4, using fixtures rather than live API calls:
- (a) A repo whose
agent-ingress.ymljob block byte-matches the canonical block classifiesALIGNED. - (b) A collapsed repo (has
agent-ingress.yml) with no standalone<role>.ymlis never classified from the legacy path, and remediation never creates or restores.github/workflows/<role>.yml. - (c) A not-yet-collapsed repo (no
agent-ingress.yml) still classifies from the legacy file.
- (a) A repo whose
- Do not edit markets files, the collapse package doc, any ADR, or
caller_stub_freeze.sh. The caller-stub-freeze manifest covers this repo's own self-host stubs, none of which collapsed. State that in the PR body as the AC4 freeze finding.
Not for this PR:
- AC7 evidence (being gathered on [ADR-0007] Collapse per-role Class-1 stubs into agent-ingress.yml (pilot) markets#506).
- AC5/AC10 measurement: needs a full post-collapse week, 2026-10-10T01:16Z..2026-10-17T01:16Z.
- Publishing the canonical template in
petry-projects/.github. That must be the markets file verbatim and must stay OUT ofDEPLOYABLE_WORKFLOWS.
STATUS — 2026-10-10 (pilot MERGED; read this first, it supersedes the older brief below where they differ)
Merged: the collapse package (#1977, then #2039), ADR-0010 (accepted; #2010, #2036), the .github fleet gaps (gh#1224 → .github#1238, gh#1226 → .github#1239), and the markets collapse PR itself (combsmith/markets#513, merged 2026-10-10).
Satisfied: AC1 (eligible set collapsed; carve-outs untouched), AC2 (every on: subscription preserved; both validators pass on the shipped file), AC6 (package and companion issue markets#506), AC3 by observation (none of the five roles was a required check in markets' ruleset, so no ruleset rename was coupled).
Remaining, and the order to do it:
- AC7: one observed run per collapsed role on the live ingress, linked on [ADR-0007] Collapse per-role Class-1 stubs into agent-ingress.yml (pilot) markets#506. First live execution of the collapsed workflow has not been observed yet. If a role does not fire as the deleted stub did, that is a defect; revert path is reverting markets#513 (restores the five stubs byte-for-byte).
- AC4:
caller_stub_freezeregeneration for the collapsed jobs, and confirm fleet drift/remediate does not try to resurrect a deleted stub (the stub resurrecter indeploy-standard-workflows.shwas fixed in .github#1239, and the sweep's regenerated markets sync PR feat: implement issue #272 — [Fleet Monitor] petry-projects/.github-private — copilot-pull-request-reviewer #517 correctly omits the deleted stub, so this is verified once; re-verify on the next sweep). - AC5 / AC10: post-collapse billed-run count and skip-kind (a) measurement, against §1 of
docs/initiatives/agent-ingress-collapse-markets.md. Post-collapse data only; measure after real traffic exists. Bound both ends of any date window and use per-workflowtotal_count(a flat/actions/runslisting caps at 1000 and an unboundedcreated>=silently widens). - AC11:
STUB_REGISTRYrows plus the canonicalagent-ingress.ymltemplate publication, then a fleet-monitorALIGNEDrun. Forward trap: the canonical template must stay OUT ofDEPLOYABLE_WORKFLOWSor the sweep ships a live ingress alongside each repo's legacy stubs; a test in .github#1239 now fails if it is added.
AC9 correction (do not re-capture): the baseline is §1 of docs/initiatives/agent-ingress-collapse-markets.md (merged in #1977). The path docs/initiatives/agent-ingress-collapse-baseline.md that older text cites never existed on main; PR #1906 was closed as superseded (its figures and two measurement traps are preserved in its closing comment).
Facts the pilot established (do not re-litigate):
- The shipped markets ingress differs from the ratified package §3 in exactly two places: the
ci-failure-analystpin (carries main's Dependabot bump tob5851027…) and thepr-auto-reviewconcurrency group (per-event slot:pr-auto-review-${{ pull_request.number || check_suite.id || workflow_run.id || 'none' }}). Package §3/§4b is being synced to match: Sync the markets collapse package §3/§4b to the deployed ingress (pr-auto-review group + ci-failure-analyst pin) #2171. - Known weaknesses carried over from the deleted stubs, deliberately NOT changed in the collapse: the analyst loop guard never matches and no-PR failures start the analyst (ci-failure-analyst caller: the self-exclusion guard never matches a real check name, and no-PR failures still start the analyst #2175); the analyst is pinned by bare SHA (markets ingress pins ci-failure-analyst by bare commit SHA (DEFECTIVE PIN): move it to a channel once stable is no longer frozen #2176);
pr-review/stableis a legacy bare channel (Fleet pr-review callers pin legacy bare pr-review/stable and are unmanaged — no pr-review release can reach the fleet .github#1125). - Review-gate defects that made the pilot slow: pr-review process defects found driving the ADR-0007 pilot (false hard-stop, empty fix-requested, silent no-op, gate counts maintainer comments, unwired bypass, edited-comment deadlock, self-dismissed approvals) #2173 (with Restore the human @mention break-glass: mention listener must send force_review only for trusted human comment mentions (#2034 follow-up) #2082, Edited-after-disposition deadlock: fix-reviews never re-dispositions an edited CodeRabbit summary, so pr-review's gate holds the PR forever (#2008 follow-up) #2166).
- Fan-out to the rest of the fleet is a separate, held decision: [Decision] Fan out the ADR-0007 ingress collapse to the rest of the fleet: go/no-go, repo order, and runbook, using the markets pilot evidence #2177. This story's measured cost is its input; record it here when AC5/AC10 land.
- Do not edit markets'
agent-ingress.ymlcontent except through the package-sync change (Sync the markets collapse package §3/§4b to the deployed ingress (pr-auto-review group + ci-failure-analyst pin) #2171). Bot-summary comments (CodeRabbit, CodeAnt, cubic) that re-raise the concurrency groups, the analyst guard or no-PR handling are decided: disposition theminvalid/out-of-scope, never edit the ingress for them.
Story
As a fleet workflow maintainer,
I want collapse the eligible Class-1 event-driven thin-caller stubs in the first target repo into a single agent-ingress.yml and rename the branch-protection required checks to the new per-job names in the same change,
so that the first repo demonstrates the ADR-0007 collapse end-to-end with zero dropped triggers and no protection gap, validating the whole toolchain.
Acceptance Criteria
- The eligible Class-1 event-driven thin-caller stubs (at minimum dev-lead.yml and pr-review-mention.yml; enumerate the FULL eligible set, EXCLUDING the pull_request_target carve-outs -- add-to-project.yml, dependabot-automerge.yml, dependabot-rebase.yml -- and Class-2/3 timers) are removed and replaced by the ingress form built to the Story-1 structure (one
agent-ingress.yml, or a small permission-profile-grouped set, per the OQ1 file-count decision). - Every pre-collapse
on:subscription is preserved in the unionon:block; each role routes to its correct pinned reusable; validate-caller-inputs and validate-interaction-model are GREEN. - The old per-role required status-check names are renamed to the new per-job check names, coordinated ATOMICALLY with the collapse (the branch-protection ruleset rename is the admin step in the epic's untracked prerequisites), so protection never blocks merges on a check that no longer exists.
- caller_stub_freeze baselines are regenerated for the collapsed jobs (Story 2
--updatepath), and fleet drift/remediate (Story 3) treats the collapsed repo correctly and does not attempt to resurrect a deleted stub. - Post-collapse the billed-run count stays within the epic's bound (union-subscribed non-matching jobs are
if:-skipped), verified against the captured 1-week baseline; a trigger change to one collapsed role is now a one-file edit.
Tasks / Subtasks
- Enumerate the eligible collapse set for the target repo, separating the pull_request_target carve-outs and Class-2/3 timers that stay as their own stubs. (AC: test issue from agent #1)
- Author the repo's ingress workflow(s) (union on:, one job per role, per-job pins/permissions/if:/names; file count per OQ1) and delete the collapsed per-role stubs. (AC: test issue from agent #1, Go-live improvements for PR review agent #2)
- Regenerate caller_stub_freeze baselines for the new jobs; confirm validate-caller-inputs + validate-interaction-model + fleet drift are green. (AC: Go-live improvements for PR review agent #2, Optimize review: small-PR and incremental fast paths #4)
- Coordinate the atomic branch-protection required-check rename with a maintainer (admin ruleset step) and confirm no protection gap on merge. (AC: Add @claude delegation, auto-merge, and rebase handling #3)
- Compare post-collapse billed run counts against the pre-collapse 1-week baseline; confirm the bound holds. (AC: feat: add Copilot engine support via REVIEW_ENGINE toggle #5)
Dev Notes
- In .github-private the clearest eligible thin callers are dev-lead.yml (Class-1: pull_request, pull_request_review, pull_request_review_comment, issue_comment, issues:labeled, check_run, repository_dispatch) and pr-review-mention.yml (issue_comment, pull_request_review_comment, pull_request:review_requested). pr-review-trigger.yml is also ring-0 frozen (Story 2). Determine the full eligible set at implementation time -- several Class-1 workflows here (persona-mention, persona-runner, spec-drift, release-notes, dependency-advisory) carry inline org-private logic and are NOT thin callers, so they do NOT collapse.
- Carve-outs are grounded and MUST stay separate: add-to-project.yml, dependabot-automerge.yml, dependabot-rebase.yml use
pull_request_target; the ADR keeps pull_request_target roles on their own stub (a receiver/collapsed permission profile would inherit fork-PR secret access Actions withholds). auto-rebase.yml (push+workflow_dispatch) and the Class-2/3 timers keep their own files. - The atomicity requirement is real: the collapse renames the status-check names (they become per-job), and branch protection is repository-ruleset config that GITHUB_TOKEN cannot edit. Land the file collapse and the ruleset rename together (maintainer performs the ruleset half) or protection blocks merges on a vanished check. This is the untracked prerequisite on the epic.
- Before merging, confirm Story 3's fleet_stub_remediate retarget is in place so a scheduled fleet run cannot 'remediate' the collapsed repo back to per-role stubs (the resurrection risk).
- The behavior of every collapsed role is unchanged -- all logic stays in the pinned reusables; this story only moves the caller tier. Prove parity by keeping every prior
on:subscription and every prior pin present in the ingress.
Project Structure Notes
Deletes the eligible per-role caller stubs and adds one agent-ingress.yml in the target repo; regenerates caller-stub-freeze fixtures; requires an out-of-band admin ruleset rename. If the first target is a leaf consumer rather than .github-private, the file work is a cross-repo PR that dev-lead cannot author from .github-private -- see the open question on target selection.
References
- .github/workflows/dev-lead.yml
- .github/workflows/pr-review-mention.yml
- .github/workflows/add-to-project.yml
- .github/workflows/dependabot-automerge.yml
- docs/architecture/adr/0007 (via docs(adr): ADR-0007 — one agent-ingress stub per repo, not one stub per role #1710)
- scripts/lib/consumer-manifest.json
Likely target surface
.github/workflows/agent-ingress.yml (new).github/workflows/dev-lead.yml (delete).github/workflows/pr-review-mention.yml (delete)tests/fixtures/caller-stub-freeze/branch-protection ruleset (admin, out-of-band)
Story prepared by the BMAD Scrum Master (Bob) for epic #1723. Status: ready-for-dev.
Decisions folded in 2026-09-08 (these are ACs, not commentary)
First collapse target: petry-projects/markets
The epic's open question "which repo is the FIRST collapse target?" is decided: a leaf consumer, specifically petry-projects/markets. Reasoning, recorded so it can be argued with:
- All six leaf consumers carry the same nine agentic stubs. After the
pull_request_targetcarve-outs (add-to-project,dependabot-automerge,dependabot-rebase) roughly 5–6 stubs genuinely collapse — a real test of the file-count metric and of blast radius..github-privatewas rejected as the pilot precisely because only ~2–3 of its Class-1 workflows are true thin callers; it would have produced a green pilot that proved almost nothing. marketshad 0 open PRs at decision time (clean cutover, nothing in flight to break) and the highest throughput of the leaves at ~24 PRs/30d — which matters because AC7 below requires an observed run per collapsed role, and a quiet repo could take weeks to produce that evidence.ContentTwin(6 PRs/30d, 1 open) is the lower-blast-radius alternative if the pilot is judged too risky in an active repo; changing the target changes only this story.
Cross-repo execution — read before starting
dev-lead running in .github-private cannot author this collapse: the files live in petry-projects/markets. Do not attempt a cross-repo PR. This story's deliverable in .github-private is the prepared, reviewable collapse package, plus a companion issue filed in petry-projects/markets carrying it for that repo's own dev-lead to implement.
- The collapse package is prepared and reviewable here: the exact
agent-ingress.ymlcontent formarketsbuilt to the Story [Phase 1] Author the agent-ingress.yml canonical structure and freeze the if:-as-event-filter boundary #1724 structure; the enumerated eligible stub set with the carve-outs excluded and justified; the old-to-new required-status-check name mapping; and the captured run-count baseline (below). A companion issue is filed inpetry-projects/marketscontaining that package and labelled so that repo's dev-lead picks it up. This story closes when the companion issue is filed and the package is complete — themarketsmerge is tracked there, not here.
QA Lead test-risk inputs (folded in 2026-09-08)
- Static green does not prove a role still fires. AC2's "
validate-caller-inputsandvalidate-interaction-modelare GREEN" proves the file parses and every pin resolves — it does not prove any role still triggers, which is exactly what the epic's success metric demands. One observed post-collapse run per collapsed role must be linked on the companion issue before it may close. Without this a dropped trigger is indistinguishable from success and the success metric is unverifiable. - The required-check rename needs a pre-merge gate and a tested rollback. AC3's "coordinated ATOMICALLY" is an intention, not a check. Required: (a) capture the current required-check name set BEFORE the PR; (b) assert the post-collapse job names produce exactly that set or a reviewed explicit mapping; (c) document and verify recovery for BOTH half-landed states — rename-without-collapse and collapse-without-rename — because the ruleset edit is a human admin step and the merge is not, so they can land out of order. This is the QA Lead's single escalated item: as originally written this story couples an irreversible protection change to a code change with no tested rollback path.
- The 1-week billed-run baseline is a hard input, not a nice-to-have. AC5 depends on it and the epic lists it as an untracked prerequisite, but nothing blocks on its existence. The baseline must be captured and committed as a referenced artifact path before this story starts; AC5 must cite that path. Otherwise AC5 gets closed with "looks fine."
- Skipped-job billing is measured, not assumed — and there are TWO skip kinds, which bill differently. ADR-0007 was corrected during review on exactly this point, so the AC follows it: (a) a job skipped by the job-level
if:event filter is evaluated on the Actions service and never assigned a runner — no minutes; (b) a job whose changed-path check runs inside the reusable has already started and holds a runner for the diff step before skipping the role work — real, if small, minutes. Any collapsed role that relied on an event-levelpaths:filter (in this repo, thedependency-advisoryshape) falls into (b) and pays a per-event runner cost that event-levelpaths:avoided entirely. Measure both kinds separately against the captured baseline; a single blended "skipped jobs are free" number does not satisfy this AC.
Added 2026-09-13 — deferred from PR #1771 review (#1726)
- Register the collapsed roles in production drift monitoring. [Phase 2] Retarget fleet drift/remediate tooling to per-job extraction (never resurrect a collapsed stub) #1726 added the
roleselector toSTUB_REGISTRYbut, correctly for its scope, registered no collapsed role — the production registry still enrols onlyinitiative-plannerandinitiative-driver, so the per-job extraction path is exercised by no production entry. Whenmarketscollapses: (a) publish the canonicalagent-ingress.ymltemplate underpetry-projects/.githubstandards/workflows/so each entry'scanonical_pathresolves rather than being tolerated as a 404; (b) add aSTUB_REGISTRYentry per collapsed role (dev-lead,pr-review-mention, and every other collapsed job) with itsroleselector and itslegacy_pathfor not-yet-collapsed repos; (c) show a fleet-monitor run in which each collapsedmarketsrole classifiesALIGNEDby job block — notMISSING— linked on the companion issue. Without this the drift tooling built in [Phase 2] Retarget fleet drift/remediate tooling to per-job extraction (never resurrect a collapsed stub) #1726 is correct but inert.
Added 2026-09-13 — template-drift expects a live ingress before rollout
- Stop the template drift check from pointing anyone at a premature live ingress.
scripts/template_stub_drift.sh(line 64, added by [Phase 1] Author the agent-ingress.yml canonical structure and freeze the if:-as-event-filter boundary #1724 / PR feat: implement issue #1724 — [Phase 1] Author the agent-ingress.yml canonical structure and freeze the if:-as-event-filter boundary #1764) already enrolls.github/workflows/agent-ingress.ymlas an expectedrepo-templatestub, so everytemplate-driftrun warns MISSING with the remedy "re-seed via scripts/seed-repo-template.sh". Butseed-repo-template.shdeliberately never seeds it (REFERENCE_MANIFEST, reachable only via--emit-workflow), so that remedy can never clear the warning. The only thing that silences it is copying the--emit-workflow agent-ingress.ymloutput intorepo-template/.github/workflows/by hand. That content is a live workflow (realon:triggers, adev-leadjob pinned todev-lead/v139-stable,secrets: inherit,contents: write), so doing it would ship an executing ingress to every new repo alongside the legacydev-lead.yml, ahead of this pilot. Required: (a) until this story publishes the canonical ingress, either de-enroll theagent-ingress.ymlrow from the drift check or give reference rows their own non-actionable message ("expected; do not seed until [Phase 3] Collapse the first repo's Class-1 event-driven stubs into agent-ingress.yml and rename the required checks #1729"); (b) whenmarketscollapses, seed the template in the same change that retires the per-role stubs it replaces, never alongside them; (c) a bats case showing a reference row cannot print the generic re-seed remedy.
Delivery brief — 2026-09-23 (read this section first; implement it, do not re-ask)
The AC9 baseline prerequisite is DISCHARGED — CORRECTED 2026-10-09. An earlier version of this section cited docs/initiatives/agent-ingress-collapse-baseline.md (PR #1906). That path never existed on main and PR #1906 was closed as superseded (its figures and two measurement traps are preserved in the closing comment). The baseline now lives in §1 of docs/initiatives/agent-ingress-collapse-markets.md (merged in PR #1977). AC5 must cite that path. Do not attempt to re-capture it — and do not treat "capture the baseline" as work remaining in this story.
Measured there, for petry-projects/markets, window 2026-09-15..2026-09-22:
| Role | Stub | Pin | Runs |
|---|---|---|---|
dev-lead |
dev-lead.yml |
dev-lead/v139-stable |
584 |
pr-review-mention |
pr-review-mention.yml |
pr-review-mention/v2-stable |
330 |
pr-auto-review |
pr-auto-review.yml |
pr-auto-review/v1-stable |
208 |
pr-review |
pr-review.yml |
pr-review/stable ⚠ stale since 2026-06-20 |
187 |
ci-failure-analyst |
ci-failure-analyst.yml |
bare SHA e37e9eb4 ⚠ not a channel |
33 |
| collapsible total | 1342 |
AC10 is already resolved for this repo and needs no new measurement design: no collapsible
caller in markets uses paths:/paths-ignore:, so every post-collapse skip is kind (a) — never
assigned a runner. State that, cite the baseline, and measure kind (a) only. The kind (b) case is
.github-private's dependency-advisory shape and is out of scope here.
Implement in this order; commit as you go
- AC6 — the collapse package (the deliverable that lives in this repo). The exact
agent-ingress.ymlcontent formarketsbuilt to the [Phase 1] Author the agent-ingress.yml canonical structure and freeze the if:-as-event-filter boundary #1724 structure; the enumerated eligible
set with carve-outs justified; the old→new required-check name mapping; AC5 citing the
baseline path. This must be complete on its own. - AC12 — the template-drift row. De-enroll
agent-ingress.ymlfrom
scripts/template_stub_drift.sh, or give reference rows a non-actionable message, plus the bats
case. Small, self-contained, and it stops everytemplate-driftrun pointing at a remedy that
cannot clear. - AC11 —
STUB_REGISTRYentries for each collapsed role, and publish the canonical template
underpetry-projects/.githubstandards/workflows/. - AC6 (second half) — file the companion issue in
petry-projects/marketscarrying the
package, labelled so that repo's dev-lead picks it up. This story closes when the companion
issue is filed and the package is complete.
If budget runs short, stop after any completed step, put what is done in the PR description,
and say plainly which ACs remain. A partial package with an honest gap list is a good outcome.
Hard constraints
- Do not author the collapse in
marketsfrom here. dev-lead running in.github-private
cannot author a cross-repo PR. The deliverable here is the package plus the companion issue.
Attempting the cross-repo PR is the single most likely way to waste this run. - Do not carry the two defective pins forward unexamined (AC6's mapping must name them):
pr-review.yml→pr-review/stablehas not moved since 2026-06-20 whilepr-review/v1.10.0
exists;ci-failure-analyst.ymlpins a bare SHA and receives no promotions. - Decide
agent-shield.yml(16 runs) anddependency-audit.yml(16 runs) explicitly. Both are
first-party thin callers on Class-1 events, so the ADR's rule admits them, but both are gates
rather than agentic roles. AC1 requires the full eligible set enumerated — record include/exclude
and the reason. Do not decide either by omission. - AC3/AC8 (the escalated item) is a package deliverable, not a merge here. The branch-protection
rename is a human admin step inmarkets. Produce the name mapping, the pre-merge gate, and the
documented recovery for BOTH half-landed states (rename-without-collapse, collapse-without-rename).
Do not couple an irreversible protection change to a code merge without that written rollback. - AC7 (one observed run per collapsed role) is evidence gathered on the companion issue after the
markets merge — not something this story can satisfy. Say so rather than claiming it.
Steering reaches this agent through the issue title and body only — a question posted as an issue
comment will not be read and will not be answered. If something is still ambiguous, pick the reading
that best satisfies the ACs above, implement it, and state the assumption in the PR description.
Generated by Claude Code
Activity
docs(adr): distinguish the two skip kinds in ADR-0007's billing claim
docs(adr): ADR-0007 — one agent-ingress stub per repo, not one stub p…
don-petry commentedon Sep 29, 2026
Dev-Lead Implementation Plan
Issue: #1729 — [Phase 3] Collapse the first repo's Class-1 event-driven stubs into agent-ingress.yml and rename the required checks
Scope
Produce the reviewable collapse package for
petry-projects/marketsin this repo (dev-lead here cannot author the cross-repomarketsPR), plus the self-contained code/test change AC12 asks for, following the delivery brief's order: AC6 → AC12 → AC11 (prepared) → companion issue (prepared).Key finding captured up front (AC3/AC8)
The live
marketsmainruleset requires exactlyCodeQL,SonarCloud,agent-shield / AgentShield,dependency-audit / Detect ecosystems. None of the five collapsing roles is a required status check, so the collapse orphans no required check and couples no ruleset edit to the merge — the escalated atomicity risk is discharged by observation, and both half-landed states are trivially safe.Implementation Checklist
docs/initiatives/agent-ingress-collapse-markets.md: enumerated eligible set (dev-lead, pr-review-mention, pr-auto-review, pr-review, ci-failure-analyst) + justified carve-outs (add-to-project/dependabot-automerge/dependabot-rebase =pull_request_target; auto-rebase = push/dispatch; feature-ideation/initiative-driver = non-Class-1/scheduled) + explicit include/exclude for the two gates (agent-shield, dependency-audit → EXCLUDE, with reasons)agent-ingress.ymlcontent for markets built to the [Phase 1] Author the agent-ingress.yml canonical structure and freeze the if:-as-event-filter boundary #1724 structure (unionon:, one job per role, per-job pins/permissions/if:), grounded in the five live stubs fetched from marketspr-review/stablestale,ci-failure-analystbare SHA) and recommended channel correctionspaths:)scripts/template_stub_drift.sh: reference-row handling soagent-ingress.ymlMISSING prints a non-actionable notice, not the generic re-seed remedySTUB_REGISTRYrows + canonicalagent-ingress.ymltemplate content embedded in the package (activation deferred: cross-repo publish + post-collapse ALIGNED verification)petry-projects/marketsTests to Write
tests/template_stub_drift.bats: a MISSING reference row (agent-ingress.yml) does NOT print the generic re-seed remedy and does not fail the jobtests/template_stub_drift.bats:template_drift_is_referencerecognizes the reference row and rejects a normal covered stubtests/template_stub_drift.bats: a MISSING non-reference row still prints the generic re-seed remedy (regression)Test Command
bats tests/template_stub_drift.batsandbash .dev-lead/scripts/dev-lead-lint.shdon-petry commentedon Sep 29, 2026
Dev-Lead Progress Note (provisional — in progress, NOT final)
Following the 6-phase flow. This is an interim note; the branch is not yet a finished PR.
Landed in this repo (reviewable now)
agent-ingress.ymlfrom the seed remedy.scripts/template_stub_drift.shnow treats.github/workflows/agent-ingress.ymlas a reference row: a MISSING reference row emits a non-actionable::notice::citing ADR-0007/[Phase 3] Collapse the first repo's Class-1 event-driven stubs into agent-ingress.yml and rename the required checks #1729 instead of the generic "re-seed viaseed-repo-template.sh"::warning::, and never fails the job. 4 new bats cases intests/template_stub_drift.bats(full suite 36/36 green). Documented inAGENTS.md(Template drift guard section).docs/initiatives/agent-ingress-collapse-markets.md. Self-contained. Contents:agent-ingress.ymlformarkets— 5 collapsed roles (dev-lead, pr-auto-review, pr-review, pr-review-mention, ci-failure-analyst), unionon:, one job per role, per-job pins/permissions/secrets copied verbatim from the live stubs, and a pure event-filterif:per role reconstructing each role's original subscription.validate-ingress-if.sh) over the proposed ingress →OK — every agent-ingress job is a thin caller with a pure event-filter if:(exit 0).agent-shield.ymlanddependency-audit.ymlexplicitly EXCLUDED (required-check gates, not agentic roles; alsopush-triggered).CodeQL, SonarCloud, agent-shield / AgentShield, dependency-audit / Detect ecosystems— none of the 5 collapsing roles is a required check, so no ruleset edit is coupled to the merge and both half-landed states are trivially safe (AC3/AC8 discharged by observation, re-checked at PR time).paths:, so no changed-path check moves into a reusable; zero kind-(b) runner cost.Named, not silently carried (per brief)
pr-reviewpin@pr-review/stable— stale bare-tier channel (no MAJOR ring); repoint follow-up recorded.ci-failure-analystpin@7974717…— bare SHA aliased tomain, an ADR-0002 violation; repoint follow-up recorded.Flagged for a decision
concurrency:— 3 source stubs carry workflow-levelconcurrency:; a single ingress can't host 3, so they're rendered job-level. ADR-0007's enumerated schema doesn't listconcurrency:. Recommend ratifying it as a declarative grouping key before the markets PR merges.Honest gap list (cannot be done from
.github-private)agent-ingress.ymltemplate publish topetry-projects/.github— cross-repo (deferred).fleet_monitor.sh— ready-to-apply rows are in the package (§9a) but not applied (would 404 against an unpublished canonical path; can't be ALIGNED-verified until markets is post-collapse).docs/initiatives/agent-ingress-collapse-baseline.md— does not exist; not fabricated. Real baseline = the canonical reference file + the live pre-collapse stubs (package §1).Verification run
shellcheck(only pre-existing info-level findings),tests/template_stub_drift.bats36/36,dev-lead-lint.shall-checks-passed,validate-ingress-if.shon the proposed ingress → OK.don-petry commentedon Sep 29, 2026
Dev-Lead: Implementation Complete — PR #1977
The implementation for issue #1729 is durable: commits are pushed and a pull request is open. This record is backed by verifiable artifacts you can confirm in one click.
89f465979ae823b527a3f06b643c4679195dba4emain: 4 file(s), +709/-2 linesReview happens on the PR. Acceptance criteria and test results are evidenced by the PR's diff and CI checks — not asserted here. If a later stage fails, this claim is retracted in place.
don-petry commentedon Oct 1, 2026
§4 (job-level
concurrency:) is resolved in direction and now tracked outside this story:concurrency:permitted in agent-ingress.yml? #2001 — the Solution Architect ruling: permit it, bounded; and the ADR-0007 enumerated schema is exhaustive (an allowlist), so this needs its own ADR rather than an interpretation.concurrency:in agent-ingress.yml (bounded), and record that the enumerated schema is exhaustive #2002 — authors ADR-0010 (proposed; human acceptance is the gate), extending ADR-0007 without superseding it.This does not unblock the markets collapse yet. The companion issue's §8a gate item ("Confirm the §4 job-level concurrency ruling is ratified") is satisfied only when ADR-0010 is accepted, not when it is filed.
One finding for §3 that was not in the package: the architect added a collision rule — each
concurrency.groupmust carry the role-name prefix and must not match any group declared by that role's pinned reusable. The §3 groups are role-prefixed already, but the no-collision half is unverified for all three roles, anddev-leadcentralizes concurrency inside its reusable, so it is a real case. #2002 AC3 covers verifying it.Also recorded on PR #1906 (closed as superseded): AC9's cited baseline path never existed on
main, so AC9 should be re-scoped to §1 of the package rather than left pointing at a path that no longer gates anything.feat: implement issue #1729 — [Phase 3] Collapse the first repo's Cla…
don-petry commentedon Oct 1, 2026
Package landed and companion issue filed.
donpetry-bot, 20:00:40) — not a bypass.docs/initiatives/agent-ingress-collapse-markets.mdis onmain.Closes #1729toRefs #1729before merge, on pr-review's blocking finding — correctly, since this story's definition of done includes evidence that can only be gathered after the markets collapse. That is why this issue is still open.AC6 is now satisfied (package complete + companion issue filed).
Deliberately NOT labelled
dev-leadon markets#506 yet. The §8a gate requires the §4 job-levelconcurrency:ruling to be accepted, and ADR-0010 does not exist yet (#2002 has no PR). Labelling now would start an implementation against a schema reading that may not survive — the architect ruled the ADR-0007 enumeration is exhaustive, so §3's concurrency blocks need ADR-0010 accepted, not merely filed. Add the label once that lands.Remaining on this story, unchanged:
STUB_REGISTRYrows activated + canonical template published topetry-projects/.githubstandards/workflows/(§9a/§9b prepared, not applied), then a fleet-monitorALIGNEDruncaller_stub_freezeregeneration for the collapsed jobs, tied to AC11don-petry commentedon Oct 10, 2026
Dev-Lead Implementation Plan
Issue: #1729 — [Phase 3] Collapse the first repo's Class-1 event-driven stubs into agent-ingress.yml and rename the required checks
Scope
AC11(b)
STUB_REGISTRYrows for the five collapsed markets roles, plus the AC4 no-resurrection proof, in this repo only (Refs #1729).Implementation Checklist
scripts/fleet_monitor.sh: add 5 role rows (dev-lead,pr-auto-review,pr-review,pr-review-mention,ci-failure-analyst) withstub_path=.github/workflows/agent-ingress.yml,canonical_path=standards/workflows/agent-ingress.yml,legacy_path=.github/workflows/<role>.ymlscripts/fleet_stub_remediate.sh: the same 5 rows (lockstep)legacy_canonical_path: checked via the API againstpetry-projects/.githubon 2026-10-10. It exists fordev-lead,pr-auto-reviewandpr-review-mention. It 404s forpr-reviewandci-failure-analyst, so those two are left empty.Tests to Write
gh): a role row whose canonical 404s gets a::warning::, writes no drift rows, exits 0, and producesfleet_stub_drift.json == []<role>.ymlis never classified from the legacy path, and remediation never creates or restores.github/workflows/<role>.ymlTest Command
bats tests/fleet_stub_drift.bats tests/fleet_stub_remediate.bats tests/fleet_stub_registry.batsdon-petry commentedon Oct 10, 2026
Dev-Lead: Implementation Complete — PR #2182
The implementation for issue #1729 is durable: commits are pushed and a pull request is open. This record is backed by verifiable artifacts you can confirm in one click.
aed01ece8cc3bf03aa264c0540d8a95c08917cedmain: 7 file(s), +504/-0 linesReview happens on the PR. Acceptance criteria and test results are evidenced by the PR's diff and CI checks — not asserted here. If a later stage fails, this claim is retracted in place.
docs(bot): clarify why agent-ingress canonical registration is premature
fix(fleet): restore the canonical-pending registry comment (revert 1d…
feat: implement issue #1729 — [Phase 3] Collapse the first repo's Cla…
Revert "fix(bot): restore ci-failure-analyst to moving channel tag"
fix(standards): pin ci-failure-analyst to its release channel
fix(standards): ci-failure-analyst loop guard matches its own check name
ci(ingress): pin ci-failure-analyst to v1-stable and fix the self-tri…
fix(standards): sync agent-ingress template job blocks to markets (pr…
don-petry commentedon Oct 12, 2026
AC11: met
STUB_REGISTRYrows. feat: implement issue #1729 — [Phase 3] Collapse the first repo's Class-1 event-driven stubs into agent-ingress.yml and rename the required checks #2182 added a row for each of the five collapsed roles, in bothscripts/fleet_monitor.shandscripts/fleet_stub_remediate.sh. feat: implement issue #2277 — Fleet Monitor aborts every run: legacy_attr_file used before it is created (unbound variable at fleet_monitor.sh:221) #2278 and feat: implement issue #2289 — Fleet Monitor reports legacy per-role stub drift as agent-ingress.yml drift (alerts and remediation plan target repos that never collapsed) #2292 followed up: the second keeps per-role stub drift in repos withoutagent-ingress.ymlin the report, but out of the alert and remediation input.Canonical template published.
standards/workflows/agent-ingress.ymlis on petry-projects/.github main at452ea69(.github#1316). Its five job blocks are byte-identical to markets main's ingress at9310b6e(fix(agent-ingress): pin ci-failure-analyst to v1-stable; fix the analyst loop guard markets#523), checked withjob_block_sha:4f0b41d30fd3e5deaae4bc81168fb2d19d15b7be69e0115529e9be36b07ebd809a50ccc54c4a7334e14fb0468d7332f03544ddfb9e11c41d5508b2f8d21265d143601abf0d84d07badba0189d03b60264368213cf1825f4ff9c936b2a9340e95805a1acfForward trap holds.
DEPLOYABLE_WORKFLOWSin petry-projects/.githubscripts/deploy-standard-workflows.shon452ea69contains noagent-ingressentry. The guard test there istest/scripts/deploy-standard-workflows/ingress-collapse.bats.Fleet Monitor run: 38193525415 (
workflow_dispatch,remediate=dry-run, 2026-10-12, success).initiative-planner.ymlandinitiative-driver.yml. Nothing touched the ingress, and nothing was written.scripts/fleet_monitor.shon main locally over the same two merged files, using theghshim fromtests/fleet_stub_registry.bats. All five roles came out✅ ALIGNED: 1 🔴 DRIFTED: 0 ⬜ MISSING: 0, andfleet_stub_drift.jsonwas[].The five per-role drift issues #2284–#2288 were raised before the template and #2292 landed. They are closed, with this evidence.
Still open on #1729:
Generated by Claude Code
don-petry commentedon Oct 14, 2026
AC5 / AC10: interim measurement (4 of 7 post-collapse days)
This covers 4 of the 7 post-collapse days. The full week (2026-10-10T01:16Z..2026-10-17T01:16Z) is not over yet. The windows are bounded at both ends, every count is a per-workflow
total_count, and the measurements are made per job.2026-09-15T00:00:00Z..2026-09-22T00:00:00Z2026-10-10T01:16:00Z..2026-10-14T01:16:00ZBaseline re-derived exactly. With the same bounded window,
actions/workflows/<stub>/runsreturns dev-lead 584, pr-review-mention 330, pr-auto-review 208, pr-review 187 and ci-failure-analyst 33, for a total of 1342. In the post-collapse window, each of those five stub workflows returns 0 runs, andagent-ingress.ymlreturns 382.Billing unit. A run is not what gets billed; a job that is assigned a runner is. I fetched every job of every run in both windows: 1340 of the 1342 baseline runs (2 returned no jobs) and all 382 post-collapse runs.
runner_name.Per role, normalized per day
Raw counts:
Other per-day figures:
if:-skipped and never get a runner.Traffic was not lighter after the collapse. 5 markets PRs were opened in the baseline window (0.7/day) and 7 in the post-collapse window (1.75/day). The fall in billed work is therefore not explained by a quieter period.
Verdicts
if:now filters before a runner is assigned (95 billed of 382).skippedwith a runner assigned. That fits the brief's ruling: no collapsible markets caller usespaths:/paths-ignore:, so kind (b) cannot occur here.check_runevent, so only third-party check failures can start it. That is also why AC7 is still 4/5.Cost record for #2177
For markets, the collapse is cost-neutral to slightly cheaper in billed runner time: about −16% billed minutes per day on interim data. It roughly doubles skipped-job evaluations, which cost nothing, and it halves workflow runs.
Still open
Generated by Claude Code
don-petry commentedon Oct 14, 2026
Final: ADR-0007 markets pilot
The maintainer has finalized the pilot on the evidence below ("finalize now — sufficient evidence"). The interim AC5/AC10 measurement above is now the final one, and the 2026-10-17 re-measurement is cancelled.
on:subscriptions are preservedcaller_stub_freezemanifest covers only this repo's self-host stubs, none of which collapsed. The standards sweep's markets PRs (markets#517 and markets#524, both merged) did not re-add any deleted stub.Cost recorded for #2177: for markets, the collapse is cost-neutral to slightly cheaper in billed runner time (about −16% billed minutes/day). Workflow runs halve.
if:-skipped job evaluations roughly double, at no cost.Follow-ups that stay open (not part of this story):
workflow_runtrigger, which is what makes ci-failure-analyst observable on Actions failures.Generated by Claude Code