Skip to content

[Phase 3] Collapse the first repo's Class-1 event-driven stubs into agent-ingress.yml and rename the required checks #1729

Closed

Description

@github-actions

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.

  1. In both scripts/fleet_monitor.sh and scripts/fleet_stub_remediate.sh (the two registries are kept in lockstep), add one STUB_REGISTRY row per collapsed markets role: dev-lead, pr-auto-review, pr-review, pr-review-mention, ci-failure-analyst.
    • stub_path = .github/workflows/agent-ingress.yml
    • canonical_path = standards/workflows/agent-ingress.yml
    • role = the job name exactly as in markets' agent-ingress.yml
    • legacy_path = .github/workflows/<role>.yml
    • legacy_canonical_path = standards/workflows/<role>.yml. Use it only if that file exists in petry-projects/.github (check it with the API). Otherwise leave it empty and say so in the PR body.
  2. 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.
  3. Add bats cases for AC4, using fixtures rather than live API calls:
    • (a) A repo whose agent-ingress.yml job block byte-matches the canonical block classifies ALIGNED.
    • (b) A collapsed repo (has agent-ingress.yml) with no standalone <role>.yml is 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.
  4. 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:


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:

  1. 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).
  2. AC4: caller_stub_freeze regeneration for the collapsed jobs, and confirm fleet drift/remediate does not try to resurrect a deleted stub (the stub resurrecter in deploy-standard-workflows.sh was 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).
  3. 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-workflow total_count (a flat /actions/runs listing caps at 1000 and an unbounded created>= silently widens).
  4. AC11: STUB_REGISTRY rows plus the canonical agent-ingress.yml template publication, then a fleet-monitor ALIGNED run. Forward trap: the canonical template must stay OUT of DEPLOYABLE_WORKFLOWS or 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):


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

  1. 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).
  2. Every pre-collapse on: subscription is preserved in the union on: block; each role routes to its correct pinned reusable; validate-caller-inputs and validate-interaction-model are GREEN.
  3. 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.
  4. caller_stub_freeze baselines are regenerated for the collapsed jobs (Story 2 --update path), and fleet drift/remediate (Story 3) treats the collapsed repo correctly and does not attempt to resurrect a deleted stub.
  5. 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

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

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_target carve-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-private was 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.
  • markets had 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.

  1. The collapse package is prepared and reviewable here: the exact agent-ingress.yml content for markets built 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 in petry-projects/markets containing 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 — the markets merge is tracked there, not here.

QA Lead test-risk inputs (folded in 2026-09-08)

  1. Static green does not prove a role still fires. AC2's "validate-caller-inputs and validate-interaction-model are 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.
  2. 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.
  3. 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."
  4. 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-level paths: filter (in this repo, the dependency-advisory shape) falls into (b) and pays a per-event runner cost that event-level paths: 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)

  1. 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 role selector to STUB_REGISTRY but, correctly for its scope, registered no collapsed role — the production registry still enrols only initiative-planner and initiative-driver, so the per-job extraction path is exercised by no production entry. When markets collapses: (a) publish the canonical agent-ingress.yml template under petry-projects/.github standards/workflows/ so each entry's canonical_path resolves rather than being tolerated as a 404; (b) add a STUB_REGISTRY entry per collapsed role (dev-lead, pr-review-mention, and every other collapsed job) with its role selector and its legacy_path for not-yet-collapsed repos; (c) show a fleet-monitor run in which each collapsed markets role classifies ALIGNED by job block — not MISSING — 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

  1. 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.yml as an expected repo-template stub, so every template-drift run warns MISSING with the remedy "re-seed via scripts/seed-repo-template.sh". But seed-repo-template.sh deliberately 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.yml output into repo-template/.github/workflows/ by hand. That content is a live workflow (real on: triggers, a dev-lead job pinned to dev-lead/v139-stable, secrets: inherit, contents: write), so doing it would ship an executing ingress to every new repo alongside the legacy dev-lead.yml, ahead of this pilot. Required: (a) until this story publishes the canonical ingress, either de-enroll the agent-ingress.yml row 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) when markets collapses, 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

  1. AC6 — the collapse package (the deliverable that lives in this repo). The exact
    agent-ingress.yml content for markets built 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.
  2. AC12 — the template-drift row. De-enroll agent-ingress.yml from
    scripts/template_stub_drift.sh, or give reference rows a non-actionable message, plus the bats
    case. Small, self-contained, and it stops every template-drift run pointing at a remedy that
    cannot clear.
  3. AC11 — STUB_REGISTRY entries for each collapsed role, and publish the canonical template
    under petry-projects/.github standards/workflows/.
  4. AC6 (second half) — file the companion issue in petry-projects/markets carrying 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 markets from 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/stable has not moved since 2026-06-20 while pr-review/v1.10.0
    exists; ci-failure-analyst.yml pins a bare SHA and receives no promotions.
  • Decide agent-shield.yml (16 runs) and dependency-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 in markets. 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

  1. don-petry commented on Sep 29, 2026

    @don-petry
    Collaborator

    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/markets in this repo (dev-lead here cannot author the cross-repo markets PR), 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 markets main ruleset requires exactly CodeQL, 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

    • AC6 — collapse package doc 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)
    • AC6 — exact agent-ingress.yml content for markets built to the [Phase 1] Author the agent-ingress.yml canonical structure and freeze the if:-as-event-filter boundary #1724 structure (union on:, one job per role, per-job pins/permissions/if:), grounded in the five live stubs fetched from markets
    • AC6 — old→new required-status-check name mapping, naming the two defective pins (pr-review/stable stale, ci-failure-analyst bare SHA) and recommended channel corrections
    • AC6 — AC5 citing the baseline path; AC10 kind-(a)-only statement (no collapsible markets caller uses paths:)
    • AC6 — AC3/AC8 pre-merge gate + documented recovery for BOTH half-landed states
    • AC12 — scripts/template_stub_drift.sh: reference-row handling so agent-ingress.yml MISSING prints a non-actionable notice, not the generic re-seed remedy
    • AC11 (prepared) — ready-to-apply STUB_REGISTRY rows + canonical agent-ingress.yml template content embedded in the package (activation deferred: cross-repo publish + post-collapse ALIGNED verification)
    • Companion issue body prepared as a committed artifact for filing in petry-projects/markets

    Tests 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 job
    • tests/template_stub_drift.bats: template_drift_is_reference recognizes the reference row and rejects a normal covered stub
    • tests/template_stub_drift.bats: a MISSING non-reference row still prints the generic re-seed remedy (regression)

    Test Command

    bats tests/template_stub_drift.bats and bash .dev-lead/scripts/dev-lead-lint.sh

  2. don-petry commented on Sep 29, 2026

    @don-petry
    Collaborator

    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)

    • AC12 — de-enroll agent-ingress.yml from the seed remedy. scripts/template_stub_drift.sh now treats .github/workflows/agent-ingress.yml as 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 via seed-repo-template.sh" ::warning::, and never fails the job. 4 new bats cases in tests/template_stub_drift.bats (full suite 36/36 green). Documented in AGENTS.md (Template drift guard section).
    • AC6 + AC5 + AC10 + AC3/AC8 + AC11(prepared) + companion issue — the collapse package at docs/initiatives/agent-ingress-collapse-markets.md. Self-contained. Contents:
      • Exact agent-ingress.yml for markets — 5 collapsed roles (dev-lead, pr-auto-review, pr-review, pr-review-mention, ci-failure-analyst), union on:, one job per role, per-job pins/permissions/secrets copied verbatim from the live stubs, and a pure event-filter if: per role reconstructing each role's original subscription.
      • Verified empirically: ran the frozen [Phase 2] Make caller_stub_freeze and validate-caller-inputs ingress-aware (job-scoped freeze + if:-as-event-filter check) #1725 guard (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).
      • Enumerated eligible set + carve-outs; agent-shield.yml and dependency-audit.yml explicitly EXCLUDED (required-check gates, not agentic roles; also push-triggered).
      • Old→new required-check name mapping with the KEY FINDING: markets' ruleset requires only 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).
      • AC10: kind-(a) skips only — no source stub uses paths:, so no changed-path check moves into a reusable; zero kind-(b) runner cost.

    Named, not silently carried (per brief)

    • pr-review pin @pr-review/stable — stale bare-tier channel (no MAJOR ring); repoint follow-up recorded.
    • ci-failure-analyst pin @7974717… — bare SHA aliased to main, an ADR-0002 violation; repoint follow-up recorded.
    • Both preserved as-is for behavior parity; corrections are separate follow-ups, not bundled into the collapse.

    Flagged for a decision

    • Job-level concurrency: — 3 source stubs carry workflow-level concurrency:; a single ingress can't host 3, so they're rendered job-level. ADR-0007's enumerated schema doesn't list concurrency:. Recommend ratifying it as a declarative grouping key before the markets PR merges.

    Honest gap list (cannot be done from .github-private)

    • The markets PR (add ingress + delete 5 stubs) — cross-repo; only markets' dev-lead can author it. Companion-issue body is committed in the package (§10) but filing is a remaining post-merge step.
    • Canonical agent-ingress.yml template publish to petry-projects/.github — cross-repo (deferred).
    • STUB_REGISTRY activation in 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).
    • Brief cited a baseline doc at 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.bats 36/36, dev-lead-lint.sh all-checks-passed, validate-ingress-if.sh on the proposed ingress → OK.

  3. don-petry commented on Sep 29, 2026

    @don-petry
    Collaborator

    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.

    Review 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.

  4. don-petry commented on Oct 1, 2026

    @don-petry
    Collaborator

    §4 (job-level concurrency:) is resolved in direction and now tracked outside this story:

    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.group must 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, and dev-lead centralizes 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.

  5. added a commit that references this issue on Oct 1, 2026
  6. don-petry commented on Oct 1, 2026

    @don-petry
    Collaborator

    Package landed and companion issue filed.

    AC6 is now satisfied (package complete + companion issue filed).

    Deliberately NOT labelled dev-lead on markets#506 yet. The §8a gate requires the §4 job-level concurrency: 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:

    • AC7 — one observed post-collapse run per collapsed role, linked on markets#506
    • AC11 — STUB_REGISTRY rows activated + canonical template published to petry-projects/.github standards/workflows/ (§9a/§9b prepared, not applied), then a fleet-monitor ALIGNED run
    • AC9 — the cited baseline path never existed; re-scope to §1 of the package (PR docs: capture the pre-collapse billed-run baseline for markets (#1729 AC9) #1906 closed as superseded)
    • AC4 — caller_stub_freeze regeneration for the collapsed jobs, tied to AC11
  7. don-petry commented on Oct 10, 2026

    @don-petry
    Collaborator

    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_REGISTRY rows 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) with stub_path=.github/workflows/agent-ingress.yml, canonical_path=standards/workflows/agent-ingress.yml, legacy_path=.github/workflows/<role>.yml
    • scripts/fleet_stub_remediate.sh: the same 5 rows (lockstep)
    • legacy_canonical_path: checked via the API against petry-projects/.github on 2026-10-10. It exists for dev-lead, pr-auto-review and pr-review-mention. It 404s for pr-review and ci-failure-analyst, so those two are left empty.

    Tests to Write

    • lockstep: both registries carry identical rows
    • fleet_monitor end-to-end (stubbed gh): a role row whose canonical 404s gets a ::warning::, writes no drift rows, exits 0, and produces fleet_stub_drift.json == []
    • AC4(a): a byte-matching job block classifies ALIGNED
    • AC4(b): a collapsed repo with no standalone <role>.yml is never classified from the legacy path, and remediation never creates or restores .github/workflows/<role>.yml
    • AC4(c): a not-yet-collapsed repo still classifies from the legacy file

    Test Command

    bats tests/fleet_stub_drift.bats tests/fleet_stub_remediate.bats tests/fleet_stub_registry.bats

  8. don-petry commented on Oct 10, 2026

    @don-petry
    Collaborator

    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.

    Review 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.

  9. don-petry commented on Oct 12, 2026

    @don-petry
    Collaborator

    AC11: met

    1. STUB_REGISTRY rows. 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 both scripts/fleet_monitor.sh and scripts/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 without agent-ingress.yml in the report, but out of the alert and remediation input.

    2. Canonical template published. standards/workflows/agent-ingress.yml is on petry-projects/.github main at 452ea69 (.github#1316). Its five job blocks are byte-identical to markets main's ingress at 9310b6e (fix(agent-ingress): pin ci-failure-analyst to v1-stable; fix the analyst loop guard markets#523), checked with job_block_sha:

      role block SHA
      dev-lead 4f0b41d30fd3e5deaae4bc81168fb2d19d15b7be
      pr-auto-review 69e0115529e9be36b07ebd809a50ccc54c4a7334
      pr-review e14fb0468d7332f03544ddfb9e11c41d5508b2f8
      pr-review-mention d21265d143601abf0d84d07badba0189d03b6026
      ci-failure-analyst 4368213cf1825f4ff9c936b2a9340e95805a1acf

      Forward trap holds. DEPLOYABLE_WORKFLOWS in petry-projects/.github scripts/deploy-standard-workflows.sh on 452ea69 contains no agent-ingress entry. The guard test there is test/scripts/deploy-standard-workflows/ingress-collapse.bats.

    3. Fleet Monitor run: 38193525415 (workflow_dispatch, remediate=dry-run, 2026-10-12, success).

      • It read the five canonical block SHAs above from .github main (job log, 02:07:37–02:08:04Z).
      • Its stub-drift alert held only the Initiative-planner and Initiative-driver stubs. It updated [Fleet Monitor] Initiative-planner stub drift #863 and [Fleet Monitor] Initiative-driver stub drift #910 and none of the role issues.
      • Its markets remediation (dry-run) named only initiative-planner.yml and initiative-driver.yml. Nothing touched the ingress, and nothing was written.
      • That run's report reached this repo cut off before the role sections, in the issue at petry-projects — workflow failures detected 2026-10-12 #2320. I re-ran scripts/fleet_monitor.sh on main locally over the same two merged files, using the gh shim from tests/fleet_stub_registry.bats. All five roles came out ✅ ALIGNED: 1 🔴 DRIFTED: 0 ⬜ MISSING: 0, and fleet_stub_drift.json was [].

    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

  10. don-petry commented on Oct 14, 2026

    @don-petry
    Collaborator

    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.

    Window Days
    Baseline (#1729 brief, package §1) 2026-09-15T00:00:00Z..2026-09-22T00:00:00Z 7
    Post-collapse (from the markets#513 merge) 2026-10-10T01:16:00Z..2026-10-14T01:16:00Z 4

    Baseline re-derived exactly. With the same bounded window, actions/workflows/<stub>/runs returns 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, and agent-ingress.yml returns 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.

    • Billed job: a job with a non-empty runner_name.
    • Billed minutes: each billed job rounded up to a whole minute.
    • Kind-(a) skip: a job with no runner.

    Per role, normalized per day

    Role Billed jobs/day, before → after Billed min/day, before → after
    dev-lead 44.4 → 41.8 60.3 → 49.8
    pr-auto-review 29.7 → 23.8 29.7 → 24.8
    pr-review 4.7 → 4.5 4.7 → 4.5
    pr-review-mention 0 → 0.25 0 → 0.25
    ci-failure-analyst 0 → 0 0 → 0
    Total 78.9 → 70.2 (−11%) 94.7 → 79.2 (−16%)

    Raw counts:

    • Baseline (7 days): 552 billed jobs, 663 billed minutes, 255.6 actual runner minutes.
    • Post-collapse (4 days): 281 billed jobs, 317 billed minutes, 95.3 actual runner minutes.
    • Linear 7-day projection, not a measurement: about 491 billed jobs and about 555 billed minutes.

    Other per-day figures:

    • Workflow runs/day: 191.7 → 95.5 (−50%).
    • Jobs evaluated per day, including skipped: 358.6 → 626.0 (+75%). This is the cost of subscribing the ingress to the union of events. Those extra jobs are 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

    • AC5: the bound holds on the interim data. Billed jobs per day fell 11% and billed minutes per day fell 16% against the §1 baseline, while PR traffic per day was higher.
      • pr-auto-review gives most of the saving. The old stub assigned a runner to every run (208/208). The ingress job's if: now filters before a runner is assigned (95 billed of 382).
      • The extra skipped-job evaluations are free.
    • AC10: every post-collapse skip is kind (a). In both windows, 0 jobs concluded skipped with a runner assigned. That fits the brief's ruling: no collapsible markets caller uses paths:/paths-ignore:, so kind (b) cannot occur here.
    • ci-failure-analyst billed 0 jobs in both windows. That matches CI Failure Analyst never runs for failed GitHub Actions jobs: the check_run trigger only fires for third-party checks #2235: GitHub Actions' own check runs deliver no check_run event, 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

  11. don-petry commented on Oct 14, 2026

    @don-petry
    Collaborator

    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.

    AC Result Evidence
    AC1, AC2 Met combsmith/markets#513 collapsed the eligible set; carve-outs are untouched and on: subscriptions are preserved
    AC3 Met by observation None of the five roles was a required check, so no ruleset rename was needed
    AC4 Met No-resurrection bats in #2182 (AC4 a–c). The caller_stub_freeze manifest 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.
    AC5 Met Billed jobs/day 78.9 → 70.2 (−11%) and billed minutes/day 94.7 → 79.2 (−16%), against the 1342-run §1 baseline, while PR traffic per day was higher (measurement)
    AC6 Met Package (#1977, #2039), synced by #2172, #2207 and #2317; companion combsmith/markets#506
    AC7 4/5 executed; 1 accepted unobserved dev-lead, pr-auto-review, pr-review and pr-review-mention all executed (evidence). ci-failure-analyst can only fire on third-party check failures (#2235), and none occurred. Its guard is verified by test (markets#523).
    AC10 Met Every skip is kind (a): 0 skipped jobs held a runner in either window
    AC11 Met Fleet Monitor run 38193525415, ALIGNED ×5 (#2182, .github#1316)

    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):


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    dev-leadFor dev-lead agent pickupinitiativeEpic / initiative tracking issue

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions