Skip to content

[qa-lead reach 3/3] The pull_request advisory surface has no deployable form — decide and implement how it ships beyond .github-private #1869

Closed

Description

@don-petry

Story

As a maintainer of a repo other than .github-private,
I want qa-lead's pull_request advisory surface to be deployable to my repo,
so that the automatic advisory from #1646 is not permanently confined to one repo.

Phase 2 of epic #1643. The router half is tracked in petry-projects/.github (#783 ring soak, and the DEPLOYABLE_WORKFLOWS story). This issue is the harder half — unlike the router, this surface has no deployable form at all.

Why it cannot simply be listed as deployable

.github/workflows/qa-lead-pr-advisory.yml is self-contained, not a thin caller stub. As of 2026-09-21 it:

  • checks out this repo and sources scripts/qa-lead-advisory-gate.sh (a script that exists only here),
  • calls ./.github/workflows/persona-runner-reusable.yml — a local reusable, not an org-published one,
  • and has no standards/workflows/ template in petry-projects/.github.

So there is nothing for the standards sweep to carry, and copying the file into another repo would reference scripts and a reusable that do not exist there. Contrast persona-mention.yml, which is already a thin stub pinned to an org channel.

The decision this issue must make first

Choose one and justify it in the PR:

  • (a) Publish the persona runtime as an org reusable. Move/copy persona-runner-reusable.yml to petry-projects/.github, give it a persona-runner/v1-* channel via cut-release.sh, vendor or relocate qa-lead-advisory-gate.sh so it travels with the reusable, and author standards/workflows/qa-lead-pr-advisory.yml as a thin caller stub. Highest effort, and the only option that matches how every other fleet workflow is shipped.
  • (b) Fold the advisory trigger into the existing mention/router path so the pull_request event reaches the already-published router rather than a second runtime. Less duplication; changes the event model and needs care with the Persona mention surface ignores needs-human-review / dev-lead:needs-human — a human brake stops the PR gate but not a mention #1745 stop-marker semantics that now live in the router.
  • (c) Keep it repo-local and say so. Document that the pull_request surface is .github-private-only by design, and update personas/qa-lead/persona.yml and the README so the declared surface matches reality — the [qa-lead S4] Make persona.yml's declared surfaces agree with what is actually deployed #1647 rule that a declared surface must be a served one applies fleet-wide, not just here.

Do not start implementing before the decision is written down. This is an architecture choice with a fleet-wide blast radius, and options (a) and (c) point in opposite directions.

Acceptance Criteria

  1. The decision above is recorded — an ADR under docs/adr/ if (a) or (b), since it changes where the persona runtime lives.
  2. If (a) or (b): qa-lead's pull_request advisory runs in at least one repo that is not .github-private, evidenced by a real run link in the PR.
  3. If (c): persona.yml, personas/qa-lead/README.md and the interaction contract state the restriction, and scripts/validate-personas.py / validate-interaction-model.sh enforce it rather than trusting prose.
  4. Whichever path: the fleet-wide claim in prompts/qa-lead/advisory.md stays true everywhere it can be printed (the [qa-lead S1] Provision <id>:hands-off labels across the fleet — the opt-out is inert where the persona actually runs #1644 rule).
  5. No caller stub is hand-edited in a consumer repo; deployment goes through the standards sweep (AGENTS.md).

Dev Notes


DECISION — option (b), by solution-architect advisory 2026-09-23 (implement this; the decision is made, do not re-open it)

The architect advisory on this issue decided (b): route the pull_request event into the existing mention router, rather than publishing a second runtime.

Grounds (quoted): governing ADR-0007 (one agent-ingress stub per repo, not one stub per role), reinforced by ADR-0006. ADR-0007 fact 4 already names persona-mention → persona-runner as the fleet's hub-and-spoke model; publishing a second runtime for this surface "repeats, at the ingress-path level, the exact per-role-stub proliferation ADR-0007 just collapsed." Option (a)'s persona-runner/v1-* channel is not itself the problem — the second ingress path it requires is.

Scope of THIS issue (this repo only)

The router change is cross-repo and is filed separately in petry-projects/.github. Do not attempt it here and do not edit any caller stub.

  1. Write the ADR under docs/adr/ recording decision (b): the context (this surface had no deployable form), the decision, the ADR-0007/0006 grounds above, and the consequences — one ingress path per repo, the pull_request surface served by the shared router, and the local qa-lead-pr-advisory.yml retired once the router serves it. Reference this issue and the advisory comment.
  2. Do NOT retire .github/workflows/qa-lead-pr-advisory.yml yet. It is the only thing serving the advisory today. Retiring it before the router change is released to its channel would leave the surface dead — the same ordering failure as landing a fail-closed validator ahead of its data. Sequence it as a follow-up gated on the router change being on persona-mention/v1-next.
  3. State the resulting contract truthfully in the meantime. If personas/qa-lead/persona.yml, personas/qa-lead/README.md or personas/qa-lead/interaction.yml imply the pull_request surface is fleet-available, correct them to say it is served locally today and by the router after the pending change — the [qa-lead S4] Make persona.yml's declared surfaces agree with what is actually deployed #1647 rule that a declared surface must be a served one.

Hard acceptance criterion from the advisory

The #1745 stop-marker semantics must hold for a pull_request-sourced dispatch, not only a mention-sourced one. The architect calls this "the real open risk, not the routing choice." The ADR must state how that will be verified before the local surface is retired.

If (b) proves infeasible

Do not fall back to (a) silently. Record the specific reason the router could not absorb the event — the advisory notes that is the fact a future ADR would need to supersede this reasoning. (c) is the fallback only if both fail.

Budget guard

  1. The ADR (AC test issue from agent #1 of this issue). That is the commit that matters — it unblocks the router work and records the reasoning while it is fresh.
  2. The contract-truthfulness corrections (item 3).

Stop after step 1 with a green PR if budget runs low.

Activity

  1. don-petry commented on Sep 23, 2026

    @don-petry
    CollaboratorAuthor

    @petry-projects/solution-architect — decision requested on this issue.

    The qa-lead pull_request advisory surface (.github/workflows/qa-lead-pr-advisory.yml) has no deployable form: it is self-contained rather than a thin caller stub, sources scripts/qa-lead-advisory-gate.sh (present only in this repo), calls a local ./.github/workflows/persona-runner-reusable.yml, and has no standards/workflows/ template. So the standards sweep has nothing to carry, and copying the file into another repo would reference scripts and a reusable that do not exist there.

    The three options are written up in the issue body with their trade-offs:

    • (a) publish the persona runtime as an org reusable (persona-runner/v1-* channel) + author a thin caller-stub template — highest effort, matches how every other fleet workflow ships;
    • (b) fold the pull_request trigger into the already-published mention router so one runtime serves both surfaces — less duplication, changes the event model, and must preserve the Persona mention surface ignores needs-human-review / dev-lead:needs-human — a human brake stops the PR gate but not a mention #1745 stop-marker semantics that now live in the router;
    • (c) keep it repo-local and make the declared surface match reality in persona.yml / the README / the interaction contract, enforced by the validators rather than prose.

    Context that post-dates the issue body: the router half is fully shipped — combsmith/.github#1134 merged, persona-mention promoted through v1-stable (all tiers at fde249e0), and combsmith/.github#1159 merged so the caller stub now deploys fleet-wide. Nine repos receive it on the next sweep. That materially strengthens option (b): the router is now a deployed, channel-managed, fleet-wide runtime, which it was not when this issue was filed.

    Please decide and justify, per AC #1 — an ADR under docs/adr/ if (a) or (b), since either moves where the persona runtime lives. Epic #1643 stays open on this decision.

  2. don-petry commented on Sep 23, 2026

    @don-petry
    CollaboratorAuthor

    Solution Architect — structural advisory

    Governing ADR: ADR-0007 (one agent-ingress stub per repo, not one stub per role) — reinforced by ADR-0006 (shared-runtime personas are not ring-registered).

    Alignment: drifts (a) / aligns (b). ADR-0007 fact 4 already names persona-mention → persona-runner as the fleet's hub-and-spoke model and says plainly: "what is not consolidated is the ingress file, and consolidating that needs no receiver." Publishing a second runtime for the pull_request surface repeats, at the ingress-path level, the exact per-role-stub proliferation ADR-0007 just collapsed. ADR-0006 already anticipated the shared runtime itself carrying a channel tag "if one is ever wired," so (a)'s persona-runner/v1-* channel isn't itself the problem — the second ingress path it requires is.

    What I'd shore up:

    • Route the pull_request event into the existing router (b) rather than standing up a second published runtime — that's the ADR-0007 consolidation, not an exception to it.
    • Before locking in (b), verify the Persona mention surface ignores needs-human-review / dev-lead:needs-human — a human brake stops the PR gate but not a mention #1745 stop-marker semantics hold for a pull_request-sourced dispatch, not only mention-sourced ones — that's the real open risk, not the routing choice.
    • If (b) proves infeasible, don't fall back to (a) silently — record the specific reason the router couldn't absorb the event; that's the fact a future ADR would need to supersede this reasoning.
    • Treat (c) as the fallback only if both fail — it locks in the confinement the router's fleet-wide rollout already argues against.

    Escalate? no — the issue already gates implementation on a written decision; this is ordinary architecture work.

    Advisory only — I comment, I do not change code. Ground: BMAD Method architect (bmad-agent-architect v6.8.0). Opt out on this item with the solution-architect:hands-off label.

  3. don-petry commented on Sep 23, 2026

    @don-petry
    CollaboratorAuthor

    Dev-Lead Implementation Plan

    Issue: #1869 — [qa-lead reach 3/3] The pull_request advisory surface has no deployable form — decide and implement how it ships beyond .github-private

    Scope

    Record the already-made architecture decision (b) — route the pull_request advisory event into the existing shared persona-mention router rather than publishing a second runtime — as a new ADR under docs/architecture/adr/, and make the persona contract state the surface truthfully in the interim (served locally today, by the router after the pending cross-repo router change). The router change itself is cross-repo and out of scope here; no caller stub is edited and the local qa-lead-pr-advisory.yml is not retired.

    Implementation Checklist

    Tests to Write

    Test Command

    bash .dev-lead/scripts/dev-lead-lint.sh plus python3 personas/validate-personas.py and bash scripts/validate-interaction-model.sh

  4. don-petry commented on Sep 23, 2026

    @don-petry
    CollaboratorAuthor

    Dev-Lead: Progress (in progress — not yet durable)

    Provisional. Nothing is pushed yet; the automation posts the authoritative
    completion record (with PR number + head SHA) after the push. Treat the notes
    below as intent, not delivered results.

    Plan Execution (intended)

    Local check output (provisional — not the pushed run)

    dev-lead-lint.sh: all checks passed (shellcheck 155 files + agent frontmatter + CODEOWNERS)
    validate-personas.py: OK — 9 persona manifest(s) valid, invariants hold.
    validate-interaction-model.sh: OK — §4 table, on: blocks, and interaction contracts all agree.
    

    Files touched (this workspace, not yet pushed)

    • docs/architecture/adr/0009-qa-lead-pull-request-surface-routes-through-the-shared-router.md: new ADR (decision b).
    • personas/qa-lead/persona.yml: pull_request surface note — served locally today, router after ADR-0009.
    • personas/qa-lead/interaction.yml: contract comment mirrors the same.
    • personas/qa-lead/README.md: served-surface section clarified + ADR link.

    Notes

    • Scope deliberately limited per the issue's budget guard: the ADR is the commit
      that matters (unblocks the cross-repo router work); the contract corrections
      are the secondary item. No implementation of the router itself here.
    • Phase 2 (test-first) skipped as the documented pure-documentation/config
      exception — no observable behavioral change; verification is by the existing
      validators above, which stay green.
  5. don-petry commented on Sep 23, 2026

    @don-petry
    CollaboratorAuthor

    Dev-Lead: Implementation Complete — PR #1892

    The implementation for issue #1869 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.

  6. added a commit that references this issue on Sep 23, 2026
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 pickupenhancementFeature requestsinitiativeEpic / initiative tracking issue

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions