Skip to content

docs(adr): ADR-0006 — shared-runtime personas are not individually ring-registered - #1693

Merged
don-petry merged 4 commits into
mainfrom
feat/adr-0006-shared-runtime-personas
Sep 7, 2026
Merged

don-petry merged 4 commits into
mainfrom
feat/adr-0006-shared-runtime-personas

Conversation

@don-petry

@don-petry don-petry commented Sep 7, 2026 •

Copy link
Copy Markdown
Collaborator

User description

Records the decision approved in #1688 — Decision: how should shared-runtime personas be represented in the canary ring model? (Option C).

What this is

The normative decision record. Per ADR-0000 an accepted ADR is immutable and hand-authored, so this lands as its own reviewable PR ahead of the enforcement changes that will cite it.

The finding

A persona is a caller of the shared persona runtime, not a reusable. Registering each one inverts ADR-0001's two-tier boundary (which puts the reusable — the thing consumers pin — as the unit of release) and applies ADR-0002's channel-tag model to a consumer that never pins a channel tag.

Three verified facts decide it:

Fact Consequence
persona-runner.yml uses a local relative path and the reusable takes no agent_ref No caller pins a persona tag — nothing for a ring promotion to advance
agent_ref_paths defaults to scripts/, prompts/, personas/ (#1019); 44 of 61 recent commits touched them ~396 unconsumed cut-and-move ops/month at nine personas. dev-lead, same shape: 162 tags, v139.8.0
The gate samples by run_workflow, identical for all personas A regression cannot be attributed to the persona that caused it

Corrects a false premise

combsmith/.github#1078 asserted that autocut would not fire on prompt-only changes. That is false — agent_ref_paths covers prompts/. I wrote that instruction; dev-lead implemented it faithfully into #1079's registry note. Both are being closed unmerged, and the correction is recorded here.

Costs, stated plainly

The Consequences section names three, not just the benefits: the reach check becomes the sole automated promotion gate; blast radius is coarser (the router's rings, no per-persona staging); and there is no independent per-persona rollback — which loses nothing real, since a whole-repo tag never delivered one.

Follows, in order

  1. This ADR (normative record).
  2. Standards amendment in petry-projects/.github — persona-standards.md §6 step 2 + §7, and persona.schema.json (canary becomes optional).
  3. Enforcement here — validate-personas.py (drops the non-draft-must-be-registered invariant) and scripts/persona_reach_check.sh + bats (inverts the skew rule).
  4. Unblocks [Phase 4] Promote solution-architect past draft through the release rings, verifying propagation reached a consumer #1631 — [Phase 4] Promote solution-architect past draft.

Until step 2 lands, persona-standards.md and this ADR disagree — the ADR notes explicitly that the standard is the one that is wrong.

Verification

markdownlint-cli2 clean; structure conforms to ADR-0000 (Title / Status / Context / Decision / Consequences), Decision in active voice with checkable boundaries, ADR-0001 and ADR-0002 quotes verified verbatim against the accepted records.


CodeAnt-AI Description

Record the rollout and release policy for shared-runtime personas

What Changed

  • Shared-runtime personas are no longer treated as individually registered release units in canary rings
  • Persona status can advance without a registry entry; rollout is governed by the shared router and reach checks
  • Personas must not claim nonexistent canary entries, while personas with their own dedicated reusable workflow remain subject to normal ring registration
  • Documents the trade-offs: no unconsumed per-persona releases, but no per-persona staging or independent rollback

Impact

✅ Zero unconsumed per-persona release streams
✅ Simpler persona onboarding
✅ Clearer shared-runtime rollout rules
✅ No per-persona staging or rollback

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

ADR-0006, accepted. Records the decision reached in #1688 after the
solution-architect advisory: a persona is a CALLER of the shared persona
runtime, not a reusable, so versioning each persona inverts ADR-0001's
two-tier boundary and applies ADR-0002's channel-tag model to a consumer
that never pins a channel tag.

Decisive facts (verified on main, 2026-09-07): persona-runner.yml consumes
the runtime by local relative path with no agent_ref input, so no caller
pins a persona tag; autocut's default agent_ref_paths watch prompts/ and
personas/, so 44 of 61 recent commits would cut a release for every
registered persona (~396/month at nine, all unconsumed); and the gate
samples on run_workflow, which all nine would share, making a regression
unattributable.

Names the real cost rather than only the benefit: the reach check becomes
the sole automated promotion gate, blast radius is coarser (the router's
rings, not per-persona), and there is no independent per-persona rollback
— which loses nothing, since a whole-repo tag never delivered one.

Supersedes the approach in combsmith/.github#1078/#1079 (closed
unmerged); #1078's premise that autocut ignores prompt-only changes was
false and is corrected here.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015YTfTumtrmd5jdFX9W1XvT
@don-petry
don-petry requested a review from a team as a code owner September 7, 2026 15:20
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@qodo-code-review

Copy link
Copy Markdown

ⓘ Qodo reviews are paused because your trial has ended. Ask your workspace admin to add credits to resume reviews. Manage billing

@codeant-ai

codeant-ai Bot commented Sep 7, 2026 •

Copy link
Copy Markdown

🤖 CodeAnt AI — Review Status

Status Commit Started (UTC) Finished (UTC)
✅ Reviewed your PR 375cd1f Sep 07, 2026 · 15:20 15:23

@codeant-ai

codeant-ai Bot commented Sep 7, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@coderabbitai

coderabbitai Bot commented Sep 7, 2026 •

Copy link
Copy Markdown

Important

Approval pending

CodeRabbit has no unresolved comments, but it has not reviewed the latest commit.

Use the checkbox below to review the latest commit. CodeRabbit will approve the changes if it finds no blocking issues.

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codeant-ai codeant-ai Bot added the size:L This PR changes 100-499 lines, ignoring generated files label Sep 7, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces ADR-0006, which documents the decision to stop individually registering shared-runtime personas in canary-rings.json to prevent unnecessary release churn. The feedback on this document is minor, suggesting capitalization corrections for 'ID' and 'BATS' to maintain standard terminology and consistency.

Comment thread docs/architecture/adr/0006-shared-runtime-personas-are-not-ring-registered.md Outdated
Comment thread docs/architecture/adr/0006-shared-runtime-personas-are-not-ring-registered.md Outdated
@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — review-changes (applied)

Changes committed and pushed.

@don-petry
don-petry enabled auto-merge (squash) September 7, 2026 15:31
@donpetry-bot

Copy link
Copy Markdown
Contributor

CI checks on this PR are still running. Once they complete, re-mention @donpetry-bot to trigger a fresh review.

Posted by the donpetry-bot PR-review cascade.

@donpetry-bot

Copy link
Copy Markdown
Contributor

Advisory bots were rate-limited; auto-approval is withheld until they recover. pr-review-sweep will re-review this PR after 2026-09-07T16:40:34Z.

@sonarqubecloud

sonarqubecloud Bot commented Sep 7, 2026

Copy link
Copy Markdown

@donpetry-bot

Copy link
Copy Markdown
Contributor

Advisory bots were rate-limited; auto-approval is withheld until they recover. pr-review-sweep will re-review this PR after 2026-09-07T17:13:16Z.

@don-petry
don-petry disabled auto-merge September 7, 2026 16:16
@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — fix-bot-comment (no-changes)

Agent reasoning
Issues addressed: 0
- Quality Gate Passed (neutral summary — no specific defects reported)
Files changed: none
Skipped (informational): 1
```
The PR is ready; all quality gates have passed and there are no actionable findings to address.

@don-petry
don-petry enabled auto-merge (squash) September 7, 2026 16:17

@donpetry-bot donpetry-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review — APPROVED ✓

Risk: LOW
Reviewed commit: 1b0882645ad4fb905ce7d330bb841f65db7ad11d
Review mode: triage-approved (single reviewer)

Summary

Docs-only PR adding ADR-0006, the decision record (accepted in #1688) that shared-runtime personas are not individually ring-registered. Single new markdown file (+120/-0); no code, workflow, or config changes. Triage's low-risk assessment is confirmed.

Linked issue analysis

No closing issue reference, which is correct for this PR type: it records the decision approved in discussion #1688 per the ADR-0000 process. The ADR body cites the decision thread and the superseded implementation PRs (combsmith/.github#1078/#1079, closed unmerged) it corrects.

Findings

  • No blocking findings.
  • The ADR is prose-only; the enforcement changes it authorizes (persona_reach_check.sh inversion, validate-personas.py relaxation, persona-standards.md updates) are explicitly deferred to follow-up PRs and clearly flagged as such in the Consequences section — nothing lands as enforced behavior here.
  • ADR numbering verified: 0000–0005 exist on main, 0006 is the next free slot, no collision.
  • All 7 prior bot review threads (gemini-code-assist, codeant-ai) are resolved; the author addressed or dismissed each. No unanswered human-reviewer questions.
  • Secret scan: MCP run_secret_scanning tool unavailable in this environment; the gitleaks CI check passed and the diff contains no credential-shaped content.

CI status

All checks green: Lint, ShellCheck, CodeQL (actions + python), gitleaks secret scan, AgentShield, Agent Security Scan, SonarCloud, unit-tests, holdout-guard, duplicate-decl-gate, CodeRabbit all SUCCESS; dependency-audit jobs SKIPPED (no matching ecosystems). A few CANCELLED dev-lead dispatch/relay/resume and Dismiss entries are superseded earlier runs, each with a later successful duplicate.


Reviewed automatically by the PR-review agent (single-reviewer mode: fable 5). Reply if you need a human review.

@don-petry
don-petry merged commit b5b76b4 into main Sep 7, 2026
50 of 57 checks passed
@don-petry
don-petry deleted the feat/adr-0006-shared-runtime-personas branch September 7, 2026 21:19
don-petry added a commit that referenced this pull request Sep 7, 2026
…runtime personas

ADR-0006 (merged in #1693) establishes that shared-runtime personas using
persona-runner must NOT declare canary blocks. The schema now enforces this:
a persona with a canary block MUST declare runtime.reusable, and vice versa.

All nine personas (business-analyst, dev-lead, devops-lead, pr-review,
qa-lead, scrum-master, security-lead, solution-architect, sre-lead) are
shared-runtime personas — they use persona-runner with no dedicated reusable.
Remove their canary blocks to comply with ADR-0006 and the schema.

Also fix validate-personas.py to gracefully handle personas without canary
blocks (checking for existence before access), allowing the validator to
pass for shared-runtime personas per ADR-0006.

Fixes: validate-personas CI check failure introduced by #1693.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Sep 7, 2026
…-0006 (#1701)

* fix(personas): unbreak validate-personas — drop canary blocks per ADR-0006

FLEET UNBLOCK. petry-projects/.github c676b4f3 (PR #1082, 16:07:52Z today)
landed the ADR-0006 schema with a bidirectional rule: a manifest carrying a
`canary` block MUST also declare `runtime.reusable`. All nine manifests here
carry `canary` and none declares `runtime.reusable`, so every one of them
began failing instantly:

  persona manifest invalid: personas/business-analyst/persona.yml:
    schema violation at runtime: 'reusable' is a required property

validate-personas.py fetches the schema LIVE from .github@main, so an org-repo
commit gated every open PR in this repo with no coordinating change on this
side. Main's last green Lint predates it by 21 seconds.

This is the fix-forward, not a revert: removing `canary` is exactly what
ADR-0006 mandates for a shared-runtime persona, so the manifests were already
non-conforming — the schema simply started saying so.

  * personas/*/persona.yml (all nine) — drop the `canary` block. Every one is
    served wholly by the shared persona runtime; none ships its own reusable.
  * validate-personas.py — `canary` is now optional, so the unconditional
    manifest["canary"]["agent"] read is guarded (that read would KeyError on a
    conforming manifest — flagged by codeant on #1693 and true).
  * validate-personas.py — the non-draft registry invariant becomes conditional
    and BIDIRECTIONAL, keyed on the manifest's own `canary` block: with one,
    past draft still requires a registry entry; without one, a registry entry
    is now itself a failure ("a registered shared-runtime persona is a defect,
    not a promotion"). This is the inversion ADR-0006 authorizes and what
    #1631 needs to flip a manifest past draft.
  * tests — three cases pinning the inversion in both directions plus the
    still-checked canary.agent path.

Verified: validate-personas.py green against the LIVE .github@main schema
(9 manifests); both new failure directions reproduce with the intended
messages; the two pre-existing registry tests remain compatible. The bats
suite cannot run on macOS (its `sed -i` is GNU-only — 34 identical failures
on unmodified main confirm the environment, not a regression); the new cases
follow the file's existing idiom and run on Linux CI.

Refs #1688, ADR-0006 (#1693), combsmith/.github#1082

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015YTfTumtrmd5jdFX9W1XvT

* chore: dev-lead update (review-changes) [skip ci-relay]

* fix(personas): dev-lead keeps its canary block — it ships its own reusable

Corrects an over-application of ADR-0006 in this PR's first commit. I stripped
`canary` from all nine manifests, but ADR-0006's omit-the-block rule covers
only personas served wholly by the SHARED persona runtime. Its final boundary
says the opposite for the other case: "A persona that ever gains its own
reusable ... returns to ADR-0002 in full and MUST be registered like any other
agent."

dev-lead ships .github/workflows/dev-lead-reusable.yml and IS a registered
ring agent (agents.dev-lead in canary-rings.json, 162 release tags). It is the
one persona of the nine on the dedicated-reusable path.

The bug was invisible until the review fix landed: the shared-runtime
prohibition was originally gated behind `status != draft`, and every persona
here is draft. codeant-ai caught that gating (a draft persona could carry a
registry entry undetected), and moving the check out of the draft gate
immediately surfaced the real defect underneath:

  personas/dev-lead/persona.yml: no canary block (shared-runtime persona,
  ADR-0006) but an agents.dev-lead entry exists ... remove the entry

The guard was right; the manifest sweep was wrong.

  * restore dev-lead's `canary` block
  * declare `runtime.reusable: .github/workflows/dev-lead-reusable.yml` —
    required by the schema whenever `canary` is present, and true of dev-lead
  * comment recording WHY this persona is the exception, so the next sweep
    does not strip it again

Verified: validate-personas.py green against the LIVE .github@main schema AND
the LIVE canary-rings.json — the exact CI path (9 manifests, no --registry).
bats 33/38 with python3 >= 3.10 on PATH; all four ADR-0006 cases pass, and the
5 failures are pre-existing `sed -i` tests this PR never touched (macOS BSD
sed; they run on Linux CI).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015YTfTumtrmd5jdFX9W1XvT

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Sep 7, 2026
…runtime personas

ADR-0006 (merged in #1693) establishes that shared-runtime personas using
persona-runner must NOT declare canary blocks. The schema now enforces this:
a persona with a canary block MUST declare runtime.reusable, and vice versa.

All nine personas (business-analyst, dev-lead, devops-lead, pr-review,
qa-lead, scrum-master, security-lead, solution-architect, sre-lead) are
shared-runtime personas — they use persona-runner with no dedicated reusable.
Remove their canary blocks to comply with ADR-0006 and the schema.

Also fix validate-personas.py to gracefully handle personas without canary
blocks (checking for existence before access), allowing the validator to
pass for shared-runtime personas per ADR-0006.

Fixes: validate-personas CI check failure introduced by #1693.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Sep 7, 2026
…ion-architect to canary (#1705)

* feat(personas): invert the reach check per ADR-0006 and promote solution-architect to canary

Closes the last story of epic #1627 (#1631).

ADR-0006 (#1693) established that a shared-runtime persona is never
ring-registered: persona-runner.yml consumes the reusable by local relative
path with no agent_ref, so no caller pins a per-persona channel tag. The reach
check still encoded the opposite rule, and was the last thing blocking a
promotion.

Inverted prc_promotion_verdict:
  * past draft + UNREGISTERED -> "promoted" (exit 0) — was the failure state,
    is now the normal one and the shape a real promotion takes
  * registered at ANY status -> "registered" (exit 2) — the inverted defect.
    Checked BEFORE the draft branch on purpose: a draft persona carrying an
    entry is equally a defect, the same gap codeant-ai caught in the validator
    on #1701.
  * the three operator messages are rewritten; two of them still said
    "promoted and registered", which is now self-contradictory.

Promoted solution-architect: status draft -> canary.

  NOT `next`. persona.schema.json's status enum is
  draft|canary|ring0|ring1|stable|retired and contains no `next`, even though
  the registry channel and PRC_RING_ORDER both use that word. #1631's AC #1 said
  "advances draft -> next"; that literal value fails schema validation, so it
  could never have passed as written. Recorded in the manifest comment and
  pinned by a new test so the disagreement is visible rather than latent.

  It carries no `canary:` block and no canary-rings entry by design. Promotion
  evidence is this guard plus the observed live mention from soak #1640, never
  a ring label. `stable` still requires the scored eval gate.

Verified: reach check exits 0 for the promoted persona and 2 for a registered
one, with the intended messages; validate-personas.py green against the LIVE
.github@main schema AND the LIVE canary-rings.json (9 manifests, the CI path);
tests/persona_reach_check.bats 17/17 with python3 >= 3.10 on PATH; bash -n and
shellcheck clean.

Refs #1627, #1631, #1688, ADR-0006 (#1693)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015YTfTumtrmd5jdFX9W1XvT

* chore: dev-lead update (review-changes) [skip ci-relay]

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Sep 8, 2026
…abels across the fleet — the opt-out is inert where the persona actually runs (#1655)

* feat: implement issue #1644 — [qa-lead S1] Provision <id>:hands-off labels across the fleet — the opt-out is inert where the persona actually runs

* chore: dev-lead update (review-changes) [skip ci-relay]

* fix(reviews): address review comments [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

* fix: align personas with ADR-0006 — remove canary blocks from shared-runtime personas

ADR-0006 (merged in #1693) establishes that shared-runtime personas using
persona-runner must NOT declare canary blocks. The schema now enforces this:
a persona with a canary block MUST declare runtime.reusable, and vice versa.

All nine personas (business-analyst, dev-lead, devops-lead, pr-review,
qa-lead, scrum-master, security-lead, solution-architect, sre-lead) are
shared-runtime personas — they use persona-runner with no dedicated reusable.
Remove their canary blocks to comply with ADR-0006 and the schema.

Also fix validate-personas.py to gracefully handle personas without canary
blocks (checking for existence before access), allowing the validator to
pass for shared-runtime personas per ADR-0006.

Fixes: validate-personas CI check failure introduced by #1693.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>

* fix: restore canary block to dev-lead persona

The previous commit incorrectly removed the canary block from dev-lead.
According to ADR-0006, only personas served by the SHARED persona runtime
should omit the canary block. Dev-lead ships its own reusable workflow and
is a registered ring agent (agents.dev-lead in canary-rings.json), so it
must retain its canary block.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>

* chore: empty commit to refresh checks (no functional change)

PR #1655 is APPROVED, MERGEABLE, and carries 0 unresolved review threads, but
is held by five checks red from CANCELLED agent runs (Dismiss, dev-lead
ci-relay / dispatch / resume, review / review).

pr-review defers silently on red non-required checks (#1427) and nothing
re-triggers on an unchanged SHA (#1551), so the PR cannot self-recover;
re-running the cancelled runs only produces fresh cancellations (#1422).

This empty commit advances the SHA to force a clean check run. No file is
modified. The push dismisses the stale approval by design
(dismiss_stale_reviews_on_push); auto-review re-approves on the new head.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017J3xhciraMLextbZhPBx68

---------

Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L This PR changes 100-499 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants