Skip to content

Epic: qa-lead — close the gap between the declared persona and the served one #1643

Closed
11 of 11 issues completed

Description

@don-petry

Context

qa-lead is the worked example for the Agentic Persona Standard — §7 names it as the reference other personas are copied from. It was added in #1174 and renamed to the role in #1279.

A review of its actual, measured output on 2026-09-01 found a persona whose quality is proven and whose throughput is near-zero, and a set of declared contracts that the shipped runtime does not honor. This epic closes that gap.

What was measured

.github-private, 2026-07-18 → 2026-09-01 (the only repo where a persona mention is routable):

Metric Value
persona-mention router runs 4,335
…skipped by the pre-filter 4,324
…startup_failure 6 (2026-07-18, fixed by #1301)
…success 3 — one of which correctly declined to route
…stuck in queued since 2026-08-19 2
persona-runner (agent) executions, ever 2
qa-lead advisories posted, ever 2 (one on its own soak issue #1300)

For scale, in the same repo: the dev-lead marker appears on 1,136 items, pr-review-agent on 715, dependency-advisory on 52, qa-lead on 3. The 4,324 skips cost 0 billable ms (job-level if:, confirmed via the timing API) — the waste is run-history noise, not spend.

The value is real — there just isn't enough of it

The single non-soak invocation landed on epic #1402 and reshaped 4 of its 9 stories:

One invocation, four stories improved, two of them created. The problem is not output quality. It is that the persona is pull-only, reachable in one repo, and nobody remembers to summon it.

Why throughput is zero

  1. .github/workflows/persona-mention.yml is adopted in exactly one repo (.github-private), pinned persona-mention/v1-next. The tags persona-mention/v1-ring0, v1-ring1, and v1-stable do not exist. [promote persona-mention 1/3] Soak through the rings (next → ring0 → ring1 → stable) .github#783 (the ring soak) was opened 2026-07-19 and has not been touched since.
  2. mention is the only surface served. personas/qa-lead/persona.yml declares five more as enabled: true — pull_request, pull_request_review, issues, discussion, check_run — and nothing dispatches any of them.

Stories

# Story Blocked by
#1644 Provision <id>:hands-off labels across the fleet —
#1645 Make the qa-lead eval set scorable and capture a first held-out baseline —
#1646 Serve the pull_request surface so qa-lead runs without being summoned #1644, #1645
#1647 Make persona.yml's declared surfaces agree with what is deployed #1646
#1648 Reconcile personas/qa-lead/README.md with the shipped runtime —
#1649 Validate skills[] and fix the entries that are wrong —
#1650 Stop posting persona advisories under a human's PAT —
#1651 Fleet-wide: 11 of 12 eval sets fail case.schema.json #1645

#1644 and #1645 gate #1646 deliberately, following this repo's own precedent from #1410/#1411: build the instrument and the escape hatch before you broaden the thing they measure and contain. Turning on an automatic PR trigger before the opt-out label exists, or before there is any quality baseline, would repeat the pattern the #860 postmortem warns against.

Out of scope / tracked elsewhere

Activity

  1. github-actions commented on Sep 1, 2026

    @github-actions
    Contributor

    Thanks for this thorough write-up — the measurement table and story-level blocking analysis make the problem space very clear. This is queued for triage. One question to help with sequencing: S1 and S2 are listed as ungated, but S2 (making the eval set scorable) also blocks S8 (fleet-wide schema fix) — is there a target sprint or rough timeline for S2, or should S1 and S2 be treated as parallel tracks that start immediately?

  2. don-petry commented on Sep 13, 2026

    @don-petry
    CollaboratorAuthor

    Held-out baseline at parity tier — 9/9, score 1.00

    Dispatched skill-eval-report.yml with skill=qa-lead (run 34737158614).
    This is the first scoring of the holdout split since the risk-tier calibration in #1698 / PR #1773 landed.

    Engine tier is the one that matters here — #1686's whole point was that the harness was scoring the
    wrong model:

    { "engine_tier": "persona", "engine_model": "claude-opus-4-8", "engine_model_observed": "claude-opus-4-8" }

    Declared == observed, at run_persona (Opus + Bash-only). We are testing like we run.

    case score pass
    qa-lead-hold-flaky-network-e2e 1.00 ✅
    qa-lead-hold-coverage-gaming 1.00 ✅
    qa-lead-hold-flaky-ui-timing 1.00 ✅
    qa-lead-hold-auth-no-contract 0.98 ✅
    qa-lead-hold-migration-no-rollback-test 0.97 ✅
    qa-lead-hold-flaky-masks-real-race 0.96 ✅
    qa-lead-hold-slow-deterministic-suite 0.96 ✅
    qa-lead-hold-payment-happy-only 0.93 ✅
    qa-lead-hold-well-tested-refactor 0.91 ✅

    score 1.00 · 9 passed · 0 failed · gate PASS vs threshold 0.70

    What this confirms, and what it does not

    Caveat, stated plainly: this measures judgment quality on curated cases. It does not measure
    delivered value in the repo, because the delivery path is still broken in ways this epic is tracking —
    a 403 silently destroyed a real advisory (#1734), the preservation fix is in flight (#1775), the
    authorization preflight is not started (#1776), and the mention surface still ignores human holds
    (#1745). A persona that scores 1.00 and cannot reliably post is worth 0 in production.

    Recording here as the S2 (#1645) baseline artifact, per the standard that a number is only meaningful
    with its tier attached.

  3. don-petry commented on Sep 21, 2026

    @don-petry
    CollaboratorAuthor

    Epic complete — all eight stories delivered and verified 2026-09-20

    Story Outcome
    #1644 (S1) <id>:hands-off labels now 9/9 in every fleet repo (was: full family in .github only). Root cause was that nothing checked or remediated the derived family — fixed by combsmith/.github#1140.
    #1645 (S2) qa-lead eval set scorable; first held-out baseline captured.
    #1646 (S3) pull_request surface served — qa-lead runs without being summoned.
    #1647 (S4) persona.yml surfaces match what is deployed, enforced by a fail-closed validator.
    #1648 (S5) README reconciled with the shipped runtime.
    #1649 (S6) skills[] validated and corrected.
    #1650 (S7) Advisories no longer post under a human maintainer's PAT.
    #1651 (S8) Fleet-wide eval-case conformance; the --schema-tree allowlist retired.

    Also delivered under this epic: #1734 and both its splits (#1775 advisory preservation, #1776 authorization preflight), #1778 (issue-triage's blanket hold), #1686 (engine tier), #1698 (risk-tier calibration), #1702 (weekly parity cadence), and #1795 (the non-required-check merge deadlock).

    On the original question — "is qa-lead providing value?"

    The held-out eval at production parity tier scored 1.00 (9 passed, 0 failed, gate threshold 0.70). State the caveat whenever citing it: that measures judgment on curated cases, not delivered value. The delivery path was the open half, and this epic closed it — the 403 that destroyed a real advisory (#1734) is fixed at both ends: a failed post now preserves the advisory (#1775), and a credential that authenticates but cannot write is caught before the engine is paid for (#1776).

    Tracked elsewhere — deliberately not held open here

    Closing as delivered.

  4. don-petry commented on Sep 21, 2026

    @don-petry
    CollaboratorAuthor

    Reopened — Phase 2: reach (2026-09-21)

    Phase 1 closed the gap between qa-lead's declared and served behaviour. It did not change where qa-lead can act, and that is the remaining half of the original finding: "pull-only, reachable in one repo, and nobody remembers to summon it."

    Measured reach, 2026-09-21

    Surface Deployed in
    persona-mention.yml (the router stub) .github-private only
    qa-lead-pr-advisory.yml (the event-driven surface from #1646) .github-private only

    Neither workflow is in DEPLOYABLE_WORKFLOWS (petry-projects/.github scripts/deploy-standard-workflows.sh), so no sweep will ever carry them to another repo. The fleet list today is: pr-review-mention, dev-lead, agent-shield, auto-rebase, dependabot-automerge, dependabot-rebase, dependency-audit, add-to-project, initiative-driver, pr-auto-review, feature-ideation.

    Phase 2 stories

    1. Ring promotion — [promote persona-mention 1/3] Soak through the rings (next → ring0 → ring1 → stable) .github#783 (existing; linked, not duplicated). persona-mention/v1-stable does not exist today; the channel has only v1-next (fde249e0), v1-ring0 (a781ad9d), v1-ring1 (366ab877). Per pilot(mcp): scan PR diffs for secrets via run_secret_scanning #783 the soak must not skip a tier, and stable is gated on an explicit human go.
    2. Stub deployment — add persona-mention.yml to DEPLOYABLE_WORKFLOWS. standards/workflows/persona-mention.yml already exists, so this is the same shape as #1045 Step D: add apply-repo-settings.yml to DEPLOYABLE_WORKFLOWS (Step C done — v1-stable exists) .github#1128 (#1045 Step D for apply-repo-settings). Blocked by (1): with no v1-stable tag, a stable-tier repo computes a nonexistent pin and Initiative: Enhance the PR-review pipeline into a world-class bug hunter — semantic symbol context, issue-type specialist routing, agentic validation, and merged-PR few-shot, eval-gated and dry-run-verified #1088's assert-exists check refuses the deploy.
    3. Make the qa-lead pull_request advisory surface deployable — unlike the router, it has no standards/workflows/ template, so there is nothing for the sweep to carry even once it is listed.

    Sequencing

    (1) ring soak → v1-stable exists → (2) add to DEPLOYABLE_WORKFLOWS → sweep opens one PR per fleet repo

    Do not reorder. This is the precondition #1128 records verbatim for the sibling agent, and the assert-exists check exists precisely to catch the inverted order.

    This epic stays open until qa-lead can act outside .github-private.

  5. added a commit that references this issue on Sep 22, 2026
  6. don-petry commented on Sep 23, 2026

    @don-petry
    CollaboratorAuthor

    Phase 2 status, 2026-09-23 03:20 UTC

    Retirement order: combsmith/.github#1167 (revised) and #1905 land → cut persona-mention and advance v1-next → verify on a real pull_request-sourced dispatch (a held PR stays silent; a no-test-surface PR stays silent) → retire qa-lead-pr-advisory.yml.

  7. don-petry commented on Oct 10, 2026

    @don-petry
    CollaboratorAuthor

    Phase 2 status, 2026-10-10 00:25 UTC

    Found: qa-lead's pull_request advisory (story #1646) had posted nothing since it shipped on 2026-09-07. The gate's first read was gh api --paginate --slurp … --jq, which gh rejects ("the --slurp option is not supported with --jq"), so every run failed closed with changed-file list unavailable. 25 of 25 sampled runs skipped that way; none of the last 100 reached the advise job. The bats suite stayed green because its gh stub accepted any flag combination.

    Fixed: #1909 (closes #1905), merged 2026-10-09 23:07Z as d9a98c7c:

    • the read now pipes --slurp output to external jq, and the test stub rejects --slurp with --jq the way real gh does (restoring the old call fails 10 tests);
    • persona-runner honours surface=pull_request and runs qa-lead's suppressors (test surface, opt-out, human hold, budget, already-advised) before the engine, from one script shared with the local workflow;
    • a persona with no registered pre-gate (dev-lead, pr-review) now skips instead of running, so the router cannot make the runner duplicate their dedicated workflows.

    Verified live: one router-shaped dispatch (persona=qa-lead, surface=pull_request, source_repo=petry-projects/.github, item_number=1167) → run 38007523367: pre-gate run, authorization preflight passed for a cross-repo post, advisory posted at combsmith/.github#1167 (comment). Re-running the gate on that PR now returns skip:already-advised. Against 12 open .github-private PRs with real gh, the merged gate returns run on 11 and skip:no-test-surface on the standards-sync PR.

    Not yet observed: the local workflow's own trigger (opened / ready_for_review). No PR has been opened in .github-private since the merge — the org is over the 50-PR automation cap (51), so dev-lead is deferring pickups.

    Remaining for the epic: combsmith/.github#1167 (router serves the pull_request event) → persona-mention/v1-next cut → .github-private stub gains the pull_request trigger → verify on real PRs → retire qa-lead-pr-advisory.yml.

  8. don-petry commented on Oct 10, 2026

    @don-petry
    CollaboratorAuthor

    Phase 2 status, 2026-10-10 11:25 UTC

    combsmith/.github#1167 (router serves the pull_request event, closes combsmith/.github#1165) merged as fb556603.

    Added since the last note, both requested in review and verified before merge:

    • the router skips, on the PR path, any persona that declares runtime.reusable (dev-lead, pr-review), so only personas without a dedicated runtime are dispatched;
    • a failure evaluating one persona is reported and fails the job, but no longer stops the personas after it (raised by qa-lead's own advisory on that PR).

    Verified by running the workflow's routing block against real PRs and the live manifests with the dispatch call intercepted: opened routes qa-lead alone; synchronize routes nobody; a PR carrying needs-human-review is skipped at the stop marker; a failed fetch for an earlier persona still lets qa-lead route.

    Not live yet. persona-mention/v1-next is still at 2e3d523b, and .github-private's stub has no pull_request trigger. Remaining: cut v1-next → add the trigger to the .github-private stub → verify on real PRs → retire qa-lead-pr-advisory.yml.

  9. don-petry commented on Oct 10, 2026

    @don-petry
    CollaboratorAuthor

    Phase 2 status, 2026-10-10 18:10 UTC

    Landed since the last note:

    Observed live on PR #2188 (the first PR to carry the trigger): the router dispatched qa-lead only (dev-lead and pr-review skipped as served by their own runtime); the local workflow and the router-served run serialized in one concurrency group; the PR received exactly one advisory. The router-served run lost its advisory to the identity-read defect that #2198 has now fixed.

    qa-lead advisories since the gate fix (#1909): one each on #2188, #2190, #2191, #2192, #2198. Before that, none since the workflow shipped on 2026-09-07.

    Remaining: observe one PR where the router-served run posts and the local run skips as already advised (or the reverse); then retire qa-lead-pr-advisory.yml and update the qa-lead docs; then close this epic. Fleet reach beyond this repo is tracked in combsmith/.github#781.

  10. don-petry commented on Oct 11, 2026

    @don-petry
    CollaboratorAuthor

    Closing: the declared qa-lead is now the served one

    Outcome. This epic opened on a persona that had posted 2 advisories ever and ran in one repo only when someone remembered to summon it. Between the gate fix (2026-10-09 23:07Z) and 2026-10-11 02:20Z, 35 PRs were opened in this repo: 33 received exactly one qa-lead advisory, none received two, one was correctly skipped as no-test-surface (#2225), and one was missed for a reason recorded below (#2238).

    Phase 1 — the eight stories in the description (#1644–#1651) — closed in September.

    Phase 2 — reach and serving path (ADR-0009, decision (b): serve the pull_request surface from the shared persona-mention router):

    What Where
    The gate that had silently skipped every PR since 2026-09-07 (gh api --slurp with --jq) fixed; runner honours surface=pull_request with qa-lead's suppressors; personas without a registered pre-gate skip #1909 (closed #1905)
    Router serves the pull_request event: declared-events filter, bot-actor check, own-runtime skip, loop finishes past a per-persona failure combsmith/.github#1167 (closed combsmith/.github#1165)
    This repo's stub subscribes pull_request #2188 (closed #2187)
    Runner no longer discards a finished advisory when the identity read fails #2198 (closed #2196)
    Router no longer skips a PR whose body merely quotes the persona marker combsmith/.github#1287 (closed combsmith/.github#1286), persona-mention/v1.23.0 on v1-next
    qa-lead-pr-advisory.yml retired; the router is the only serving path #2246 (closed #2243)

    Verified live, not by status:

    Not done here, tracked elsewhere:

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

    documentationDocumentation changesenhancementFeature requestsinitiativeEpic / initiative tracking issue

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions