Skip to content

Stop using address.aliases (half 1 of 2) - #1289

Merged
don-petry merged 2 commits into
mainfrom
fix/drop-persona-aliases
Jul 17, 2026
Merged

don-petry merged 2 commits into
mainfrom
fix/drop-persona-aliases

Conversation

@don-petry

Copy link
Copy Markdown
Collaborator

Drops address.aliases from the addressing contract. First half of an ordered cross-repo pair — this removes every use of the field; the companion in petry-projects/.github then drops it from the schema.

Order matters. The schema is additionalProperties: false, so dropping the field first would make qa-lead's aliases: [] fail validate-personas fleet-wide on main. Usage goes first.

Why drop them — settled empirically, not by taste

An alias exists so a renamed persona keeps routing: qa-lead declaring aliases: [petry-projects/murat] so old comments still reach it. Two problems:

1. Index-free routing can't honour it. The router resolves @petry-projects/murat → personas/murat/persona.yml → 404 after the rename. The alias is declared inside qa-lead's manifest, which the router never opens because it doesn't know to look there. Chicken-and-egg. The pm_persona_aliases attempt in .github#754 was unreachable for exactly this reason.

2. The strongest argument for keeping them turned out to be false. The worry: GitHub redirects renamed team slugs, so an old mention would still look live while the agent silently never ran — the UI lying, which is the failure class we've been eliminating. I probed it directly — created a team, rendered its mention, renamed the team, re-rendered the old handle:

Renders as
before rename <a class="team-mention" ...>@petry-projects/pm-alias-probe</a>
after rename <p>@petry-projects/pm-alias-probe please review</p>

GitHub itself stops treating the old handle as a mention. It becomes grey plain text, so the user sees instantly that it didn't resolve, and the fix is obvious: re-mention with the new handle.

So aliases would only route text GitHub no longer considers a mention — not worth a derived index, an extra fetch on every 404, and a contract the router can't honour. (#755 finding 1.)

Handle uniqueness is now a theorem, so its check is removed

check_handles_unique existed because aliases shared the handle namespace. Without them it's provably unreachable:

  • the schema pins the org — ^petry-projects/[a-z0-9]+(-[a-z0-9]+)*$
  • slug == id (enforced)
  • id == the persona directory name (enforced)
  • directory names are unique

⇒ two personas cannot claim the same handle. A validator function that can never fire is a liability — it implies a check where none is needed and invites maintenance. Removed, with the theorem documented where the slug check lives.

Verification

  • bats tests/test_validate_personas.bats — 16/16 (was 20; the 4 alias tests removed. The handle-collision tests went with them because they used an alias as the collision vector, and the collision is now impossible.)
  • validate-personas.py against the live main schema (which still permits aliases — so this must pass before the companion lands): OK, invariants hold
  • scripts/verify-persona-teams.sh (from feat: implement issue #1280 — Verify persona addressing teams in CI #1284): OK — qa-lead's team still verifies live (exists, closed, notifications disabled)

🤖 Generated with Claude Code

Aliases are dropped from the addressing contract. This is the FIRST half of an
ordered cross-repo pair — it removes every USE of the field. The companion PR in
petry-projects/.github then drops it from the schema. Reversing that order breaks
main fleet-wide: the schema is additionalProperties:false, so dropping the field
first makes qa-lead's `aliases: []` fail validate-personas everywhere.

Why drop them (settled empirically, not by taste)

An alias exists so a RENAMED persona keeps routing: qa-lead declaring
`aliases: [petry-projects/murat]` so old comments still reach it. Two problems:

1. Index-free routing cannot honour it. The router resolves '@petry-projects/murat'
   to personas/murat/persona.yml — a 404 after the rename. The alias is declared
   inside qa-lead's manifest, which the router never opens because it does not
   know to look there. Chicken-and-egg. The attempt at pm_persona_aliases in
   .github#754 was unreachable for exactly this reason.

2. The severity argument for keeping them turned out to be FALSE. The worry was
   that GitHub redirects renamed team slugs, so an old mention would still LOOK
   live while the agent silently never ran — the UI lying, which is the failure
   class we have been eliminating. Probed it directly: created a team, rendered
   its mention (team-mention link), renamed the team, re-rendered the OLD handle:

     before rename: <a class="team-mention" ...>@petry-projects/pm-alias-probe</a>
     after rename:  <p>@petry-projects/pm-alias-probe please review</p>

   The old handle renders as PLAIN TEXT. GitHub itself stops treating it as a
   mention, so the user sees grey text and knows instantly it did not resolve.
   The failure is visible, and the fix is obvious: re-mention with the new handle.

So aliases would only route text GitHub no longer considers a mention — not worth
a derived index, an extra fetch on every 404, and a contract the router cannot
honour. See petry-projects/.github#755 finding 1.

Handle uniqueness is now a THEOREM, so its check is removed

check_handles_unique existed because aliases shared the handle namespace. Without
them it is provably unreachable: the schema pins the org (^petry-projects/...),
slug == id, id == the persona directory name, and directory names are unique — so
two personas cannot claim the same handle. A validator function that can never
fire is a liability: it implies a check where none is needed and invites
maintenance. Removed, with the theorem documented where the slug check lives.

Changes
- personas/qa-lead/persona.yml — drop `aliases: []`
- personas/validate-personas.py — drop alias shape validation and the now-dead
  check_handles_unique; document the uniqueness theorem
- tests/test_validate_personas.bats — drop the 4 alias tests and the helper's
  alias varargs; the handle-collision tests went with them because they used an
  alias as the collision vector and the collision is now impossible

Verification
- bats tests/test_validate_personas.bats: 16/16 (was 20; 4 alias tests removed).
- validate-personas.py against the LIVE main schema (which still permits aliases,
  so this must pass BEFORE the companion lands): OK, invariants hold.
- scripts/verify-persona-teams.sh (from #1284): OK — qa-lead's team still
  verifies live (exists, closed, notifications disabled).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@don-petry
don-petry requested a review from a team as a code owner July 17, 2026 12:01
Copilot AI review requested due to automatic review settings July 17, 2026 12:01
@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.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

@don-petry, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 25 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 7f331a99-6cf4-43e7-bac2-e14939c10e26

📥 Commits

Reviewing files that changed from the base of the PR and between e32a848 and 00b757c.

📒 Files selected for processing (4)
  • personas/qa-lead/persona.yml
  • personas/validate-personas.py
  • tests/test_validate_personas.bats
  • tests/verify_persona_teams.bats
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/drop-persona-aliases

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.

@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 simplifies the persona validation process by removing the aliases field and the redundant cross-file uniqueness check (check_handles_unique) from validate-personas.py. Because the schema pins the organization and ensures that the handle slug matches the unique directory name, handle uniqueness is guaranteed by design. Related tests and helper functions in test_validate_personas.bats have been removed accordingly. There are no review comments, so I have no feedback to provide.

@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — review-changes (no-changes)

No changes were needed for this PR.

@don-petry
don-petry enabled auto-merge (squash) July 17, 2026 12:03

Copilot AI 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.

Pull request overview

Removes address.aliases usage from this repo’s persona manifests and test fixtures, and updates the persona validator to stop parsing/enforcing aliases ahead of the upstream schema change in petry-projects/.github.

Changes:

  • Simplify validate-personas.py by dropping alias parsing and the cross-file handle/alias uniqueness check.
  • Update persona validation tests to stop emitting/testing address.aliases.
  • Remove aliases: [] from personas/qa-lead/persona.yml.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
tests/test_validate_personas.bats Stops generating/testing address.aliases and removes alias-driven collision cases.
personas/validate-personas.py Removes alias handling and the uniqueness check; updates module docs to explain the new invariant reasoning.
personas/qa-lead/persona.yml Drops aliases: [] from the persona’s address block.

Comment thread personas/validate-personas.py Outdated
Comment thread personas/qa-lead/persona.yml
@donpetry-bot

donpetry-bot commented Jul 17, 2026 •

Copy link
Copy Markdown
Contributor
Superseded by automated re-review at 00b757cda07dc3e3d7beea5265c9147b2ad4ab55 — click to expand prior review.

Review — fix requested (cycle 1/3)

The automated review identified the following issues. Please address each one:

Findings to fix

Automated review — NEEDS HUMAN REVIEW

Risk: MEDIUM
Reviewed commit: ad7ca559a96e782c0d404d546363e49b95795f44
Review mode: triage-approved (single reviewer)

Summary

Drops address.aliases usage (half 1 of an ordered cross-repo pair): removes the qa-lead aliases: [] entry, deletes alias-shape checks and the now-unreachable check_handles_unique from validate-personas.py, and removes the corresponding bats tests. The logic is sound and the ordering rationale (usage before schema) is correct, but one leftover emission of aliases: [] remains and two review threads are unresolved.

Linked issue analysis

No formally linked issue (closingIssuesReferences is empty). The PR body references #755 (finding 1), .github#754, and #1284 as context and is half 1 of an ordered cross-repo pair with petry-projects/.github. The removal rationale (router cannot honour aliases; GitHub stops rendering renamed-team mentions) is well evidenced in the PR body.

Findings

  1. VERIFIED (minor, actionable): tests/verify_persona_teams.bats line 44 still emits 'aliases: []' into its fixture persona (make_persona), contradicting the PR claim that every use of the field is removed (Copilot thread on personas/qa-lead/persona.yml, unresolved). Impact check: that fixture is hermetic — written to $BATS_TEST_TMPDIR and consumed only by verify-persona-teams.sh shell functions with a stubbed gh; the script never schema-validates (verified at PR head), so Copilot's prediction of a hard failure once the companion schema lands is INCORRECT. Still, the leftover line should be removed (or the PR description amended) and the thread resolved — a one-line fix.
  2. Unresolved Copilot thread on personas/validate-personas.py docstring: the 'uniqueness is a theorem' wording is only unconditionally true after the companion schema PR lands. Transitional-wording nit; the docstring already notes the schema pins the org. Reasonable to resolve with a brief reply or a one-word clarification.
  3. Correctness of removals verified: check_handles_unique is unreachable once aliases are gone (schema pins org prefix, slug==id, id==dirname, dirnames unique). The 'loaded' list removal in main() is consistent. Test removals match (20 -> 16; the two collision tests used aliases as the collision vector).
  4. Secret scan: run_secret_scanning MCP tool not available in this environment; gitleaks CI check passed. No secret-like content in the diff.
  5. Ordering safety confirmed: qa-lead's manifest without aliases passes the live main schema (aliases is optional there), so this PR is safe to land before the companion.

CI status

All required checks green: validate-personas, verify-persona-teams, bats (16/16), unit-tests, Lint, ShellCheck, actionlint, CodeQL (python + actions), SonarCloud quality gate, gitleaks, AgentShield, holdout-guard, caller-stub-freeze, template-drift all SUCCESS. The two CANCELLED dev-lead entries are superseded duplicate runs with later SUCCESS/SKIPPED runs. CodeRabbit and Codex skipped due to their own usage limits (non-blocking).


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

Additional tasks

  1. Resolve all unresolved review thread comments from other reviewers
  2. Ensure all CI checks pass after your changes
  3. Rebase on the target branch if behind
  4. Do NOT modify files unrelated to the findings above

The review cascade will automatically re-review after new commits are pushed.

Both from Copilot's review; both correct.

1. tests/verify_persona_teams.bats still wrote `aliases: []`

A real miss, and exactly the ordered-pair landmine this PR exists to avoid: the
moment the companion drops `aliases` from the schema (additionalProperties:
false), this fixture's generated manifest would fail validation. It survived
because my sweep grepped personas/ and tests/test_validate_personas.bats — this
fixture lives in the suite #1284 added, which I never looked at. A repo-wide
grep now shows zero remaining uses.

2. The uniqueness theorem was stated more broadly than it holds

The docstring claimed a uniqueness check "could never fire" — unconditionally
true only once the schema drops aliases. Today the schema still PERMITS an
alias, and aliases shared the handle namespace the theorem does not cover, so
until the companion lands, re-adding one would reopen exactly the gap the check
used to close. Scoped the claim to address.handle (the only thing the router
resolves) and recorded the window explicitly.

Verification
- bats tests/test_validate_personas.bats: 16/16.
- bats tests/verify_persona_teams.bats: 16/16 (the #1284 suite, now alias-free).
- validate-personas.py against the LIVE main schema: OK, invariants hold.
- Repo-wide grep for `aliases`: zero uses outside the docstring note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@don-petry
don-petry disabled auto-merge July 17, 2026 12:26
@sonarqubecloud

Copy link
Copy Markdown

@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — review-changes (no-changes)

No changes were needed for this PR.

@don-petry
don-petry enabled auto-merge (squash) July 17, 2026 12:29

@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: MEDIUM
Reviewed commit: 00b757cda07dc3e3d7beea5265c9147b2ad4ab55
Review mode: triage-approved (single reviewer)

Summary

Removes address.aliases usage from persona manifests, validator, and test fixtures as half 1 of an ordered cross-repo pair (companion in petry-projects/.github drops the field from the schema). Also removes check_handles_unique, now provably unreachable for address.handle (schema pins org, slug == id, id == unique directory name). Prior review cycle's two findings (leftover aliases fixture in verify_persona_teams.bats; over-broad uniqueness-theorem claim) are both fixed in the latest commit and their threads resolved. Triage assessment confirmed.

Linked issue analysis

No linked issues via closingIssuesReferences. The PR references petry-projects/.github#755 (finding 1) as motivation and documents the cross-repo ordering constraint thoroughly: usage must be dropped before the schema drops the field, since the schema is additionalProperties: false. The change was verified against the live main schema, so it is safe to land first as intended.

Findings

No blocking findings.

  • Prior cycle finding 1 (leftover aliases: [] in tests/verify_persona_teams.bats fixture) — RESOLVED: fixture no longer emits aliases; repo-wide usage is now zero.
  • Prior cycle finding 2 (uniqueness theorem stated too broadly while the schema still permits aliases) — RESOLVED: docstring now scopes the claim to address.handle and explicitly documents the window until the companion schema PR lands, warning against re-adding an alias.
  • Note (non-blocking): removing check_handles_unique is sound for handles by construction; the documented interim window (schema still permits aliases until the companion lands) is acknowledged in-code, which is the right mitigation for an ordered pair.
  • Secret scan: run_secret_scanning MCP tool unavailable in this session; gitleaks CI check passed and the diff contains no secret-like content.

CI status

All required checks green: validate-personas, verify-persona-teams, bats, unit-tests, Lint, ShellCheck, actionlint, CodeQL (actions + python), SonarCloud quality gate, Secret scan (gitleaks), agent-shield, holdout-guard, caller-stub-freeze, template-drift. A few dev-lead dispatch/ci-relay runs show CANCELLED (superseded runs) and conditional jobs SKIPPED — none blocking.


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 9b736c7 into main Jul 17, 2026
45 of 55 checks passed
@don-petry
don-petry deleted the fix/drop-persona-aliases branch July 17, 2026 12:55
don-petry added a commit to petry-projects/.github that referenced this pull request Jul 17, 2026
…thub-private#1289 merges (#769)

* refactor(personas): drop address.aliases from the contract (half 2 of 2)

Second half of the ordered cross-repo pair. petry-projects/.github-private#1289
removed every USE of the field first; this removes the field itself.

MERGE ORDER: #1289 MUST land before this. The schema is
additionalProperties:false, so dropping `aliases` while qa-lead's manifest still
carries `aliases: []` fails validate-personas on main FLEET-WIDE. Verified the
rejection is real: a manifest with `aliases` now yields "Additional properties
are not allowed ('aliases' was unexpected)".

Why aliases are gone (see .github#755 finding 1)

They existed so a RENAMED role kept routing — qa-lead listing
`petry-projects/murat` so old comments still reached it. Two reasons it goes:

1. Structural: index-free routing could never honour it. The router resolves
   '@petry-projects/murat' to personas/murat/persona.yml — a 404 after the
   rename. The alias is declared INSIDE the renamed persona's own manifest,
   which the router never opens, because it does not know to look there.
   Chicken-and-egg; the pm_persona_aliases attempt in #754 was unreachable for
   exactly this reason.

2. Measured: there is nothing live left to route. GitHub stops rendering a
   renamed team's old handle as a mention at all. Probed it directly — created
   a team, rendered its mention, renamed it, re-rendered the OLD handle:

     before rename:  <a class="team-mention" …>@petry-projects/probe</a>
     after rename:   <p>@petry-projects/probe please review</p>

   The old handle becomes PLAIN TEXT. So it is not a silently-broken mention
   that looks live — the reader sees grey text and knows instantly it did not
   resolve, and the fix is local: mention the new handle. Aliases would only
   route text GitHub itself no longer treats as a mention. Not worth a derived
   index, an extra fetch on every 404, and a contract the router cannot honour.

Rule 4 becomes a theorem, not a check

"Handles and aliases MUST be unique across all personas" is replaced by
"Handles are unique BY CONSTRUCTION": the pattern pins the org, slug == id,
id == the persona directory name, and directory names are unique — so two
personas cannot claim the same handle. #1289 removed the corresponding
check_handles_unique for the same reason: it could never fire.

Rule 5 ("a rename keeps the old handle as an alias") is replaced by a §4.1
"Renames" section documenting what to change on a rename and stating plainly
that old mentions stop resolving VISIBLY — which is the correct signal, not a
regression.

Changes
- standards/personas/persona.schema.json — drop address.aliases (edited as TEXT,
  not re-serialized: a json round-trip reformats every inline array and rewrote
  264 untouched lines. Diff is +2/-10.)
- standards/persona-standards.md — §4.1 rules 4-5, the example, and the new
  Renames section
- standards/personas/TEMPLATE/persona.yml — drop the aliases scaffold line

Verification
- persona.schema.json is a valid Draft 2020-12 schema; diff is +2/-10.
- Conditional behaviour verified: qa-lead's post-#1289 shape (handle only)
  PASSES; a manifest carrying `aliases` FAILS — which is exactly why #1289 goes
  first.
- TEMPLATE/persona.yml validates against the updated schema.
- markdownlint-cli2: clean.
- Zero `aliases` references remain outside the deliberate explanatory notes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

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

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
Co-authored-by: Don Petry Bot <donpetry+bot@gmail.com>
don-petry added a commit that referenced this pull request Aug 2, 2026
* refactor(personas): stop using address.aliases (half 1 of 2)

Aliases are dropped from the addressing contract. This is the FIRST half of an
ordered cross-repo pair — it removes every USE of the field. The companion PR in
petry-projects/.github then drops it from the schema. Reversing that order breaks
main fleet-wide: the schema is additionalProperties:false, so dropping the field
first makes qa-lead's `aliases: []` fail validate-personas everywhere.

Why drop them (settled empirically, not by taste)

An alias exists so a RENAMED persona keeps routing: qa-lead declaring
`aliases: [petry-projects/murat]` so old comments still reach it. Two problems:

1. Index-free routing cannot honour it. The router resolves '@petry-projects/murat'
   to personas/murat/persona.yml — a 404 after the rename. The alias is declared
   inside qa-lead's manifest, which the router never opens because it does not
   know to look there. Chicken-and-egg. The attempt at pm_persona_aliases in
   .github#754 was unreachable for exactly this reason.

2. The severity argument for keeping them turned out to be FALSE. The worry was
   that GitHub redirects renamed team slugs, so an old mention would still LOOK
   live while the agent silently never ran — the UI lying, which is the failure
   class we have been eliminating. Probed it directly: created a team, rendered
   its mention (team-mention link), renamed the team, re-rendered the OLD handle:

     before rename: <a class="team-mention" ...>@petry-projects/pm-alias-probe</a>
     after rename:  <p>@petry-projects/pm-alias-probe please review</p>

   The old handle renders as PLAIN TEXT. GitHub itself stops treating it as a
   mention, so the user sees grey text and knows instantly it did not resolve.
   The failure is visible, and the fix is obvious: re-mention with the new handle.

So aliases would only route text GitHub no longer considers a mention — not worth
a derived index, an extra fetch on every 404, and a contract the router cannot
honour. See petry-projects/.github#755 finding 1.

Handle uniqueness is now a THEOREM, so its check is removed

check_handles_unique existed because aliases shared the handle namespace. Without
them it is provably unreachable: the schema pins the org (^petry-projects/...),
slug == id, id == the persona directory name, and directory names are unique — so
two personas cannot claim the same handle. A validator function that can never
fire is a liability: it implies a check where none is needed and invites
maintenance. Removed, with the theorem documented where the slug check lives.

Changes
- personas/qa-lead/persona.yml — drop `aliases: []`
- personas/validate-personas.py — drop alias shape validation and the now-dead
  check_handles_unique; document the uniqueness theorem
- tests/test_validate_personas.bats — drop the 4 alias tests and the helper's
  alias varargs; the handle-collision tests went with them because they used an
  alias as the collision vector and the collision is now impossible

Verification
- bats tests/test_validate_personas.bats: 16/16 (was 20; 4 alias tests removed).
- validate-personas.py against the LIVE main schema (which still permits aliases,
  so this must pass BEFORE the companion lands): OK, invariants hold.
- scripts/verify-persona-teams.sh (from #1284): OK — qa-lead's team still
  verifies live (exists, closed, notifications disabled).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(personas): drop the last aliases fixture and scope the theorem claim

Both from Copilot's review; both correct.

1. tests/verify_persona_teams.bats still wrote `aliases: []`

A real miss, and exactly the ordered-pair landmine this PR exists to avoid: the
moment the companion drops `aliases` from the schema (additionalProperties:
false), this fixture's generated manifest would fail validation. It survived
because my sweep grepped personas/ and tests/test_validate_personas.bats — this
fixture lives in the suite #1284 added, which I never looked at. A repo-wide
grep now shows zero remaining uses.

2. The uniqueness theorem was stated more broadly than it holds

The docstring claimed a uniqueness check "could never fire" — unconditionally
true only once the schema drops aliases. Today the schema still PERMITS an
alias, and aliases shared the handle namespace the theorem does not cover, so
until the companion lands, re-adding one would reopen exactly the gap the check
used to close. Scoped the claim to address.handle (the only thing the router
resolves) and recorded the window explicitly.

Verification
- bats tests/test_validate_personas.bats: 16/16.
- bats tests/verify_persona_teams.bats: 16/16 (the #1284 suite, now alias-free).
- validate-personas.py against the LIVE main schema: OK, invariants hold.
- Repo-wide grep for `aliases`: zero uses outside the docstring note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Aug 3, 2026
* refactor(personas): stop using address.aliases (half 1 of 2)

Aliases are dropped from the addressing contract. This is the FIRST half of an
ordered cross-repo pair — it removes every USE of the field. The companion PR in
petry-projects/.github then drops it from the schema. Reversing that order breaks
main fleet-wide: the schema is additionalProperties:false, so dropping the field
first makes qa-lead's `aliases: []` fail validate-personas everywhere.

Why drop them (settled empirically, not by taste)

An alias exists so a RENAMED persona keeps routing: qa-lead declaring
`aliases: [petry-projects/murat]` so old comments still reach it. Two problems:

1. Index-free routing cannot honour it. The router resolves '@petry-projects/murat'
   to personas/murat/persona.yml — a 404 after the rename. The alias is declared
   inside qa-lead's manifest, which the router never opens because it does not
   know to look there. Chicken-and-egg. The attempt at pm_persona_aliases in
   .github#754 was unreachable for exactly this reason.

2. The severity argument for keeping them turned out to be FALSE. The worry was
   that GitHub redirects renamed team slugs, so an old mention would still LOOK
   live while the agent silently never ran — the UI lying, which is the failure
   class we have been eliminating. Probed it directly: created a team, rendered
   its mention (team-mention link), renamed the team, re-rendered the OLD handle:

     before rename: <a class="team-mention" ...>@petry-projects/pm-alias-probe</a>
     after rename:  <p>@petry-projects/pm-alias-probe please review</p>

   The old handle renders as PLAIN TEXT. GitHub itself stops treating it as a
   mention, so the user sees grey text and knows instantly it did not resolve.
   The failure is visible, and the fix is obvious: re-mention with the new handle.

So aliases would only route text GitHub no longer considers a mention — not worth
a derived index, an extra fetch on every 404, and a contract the router cannot
honour. See petry-projects/.github#755 finding 1.

Handle uniqueness is now a THEOREM, so its check is removed

check_handles_unique existed because aliases shared the handle namespace. Without
them it is provably unreachable: the schema pins the org (^petry-projects/...),
slug == id, id == the persona directory name, and directory names are unique — so
two personas cannot claim the same handle. A validator function that can never
fire is a liability: it implies a check where none is needed and invites
maintenance. Removed, with the theorem documented where the slug check lives.

Changes
- personas/qa-lead/persona.yml — drop `aliases: []`
- personas/validate-personas.py — drop alias shape validation and the now-dead
  check_handles_unique; document the uniqueness theorem
- tests/test_validate_personas.bats — drop the 4 alias tests and the helper's
  alias varargs; the handle-collision tests went with them because they used an
  alias as the collision vector and the collision is now impossible

Verification
- bats tests/test_validate_personas.bats: 16/16 (was 20; 4 alias tests removed).
- validate-personas.py against the LIVE main schema (which still permits aliases,
  so this must pass BEFORE the companion lands): OK, invariants hold.
- scripts/verify-persona-teams.sh (from #1284): OK — qa-lead's team still
  verifies live (exists, closed, notifications disabled).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(personas): drop the last aliases fixture and scope the theorem claim

Both from Copilot's review; both correct.

1. tests/verify_persona_teams.bats still wrote `aliases: []`

A real miss, and exactly the ordered-pair landmine this PR exists to avoid: the
moment the companion drops `aliases` from the schema (additionalProperties:
false), this fixture's generated manifest would fail validation. It survived
because my sweep grepped personas/ and tests/test_validate_personas.bats — this
fixture lives in the suite #1284 added, which I never looked at. A repo-wide
grep now shows zero remaining uses.

2. The uniqueness theorem was stated more broadly than it holds

The docstring claimed a uniqueness check "could never fire" — unconditionally
true only once the schema drops aliases. Today the schema still PERMITS an
alias, and aliases shared the handle namespace the theorem does not cover, so
until the companion lands, re-adding one would reopen exactly the gap the check
used to close. Scoped the claim to address.handle (the only thing the router
resolves) and recorded the window explicitly.

Verification
- bats tests/test_validate_personas.bats: 16/16.
- bats tests/verify_persona_teams.bats: 16/16 (the #1284 suite, now alias-free).
- validate-personas.py against the LIVE main schema: OK, invariants hold.
- Repo-wide grep for `aliases`: zero uses outside the docstring note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Aug 3, 2026
* refactor(personas): stop using address.aliases (half 1 of 2)

Aliases are dropped from the addressing contract. This is the FIRST half of an
ordered cross-repo pair — it removes every USE of the field. The companion PR in
petry-projects/.github then drops it from the schema. Reversing that order breaks
main fleet-wide: the schema is additionalProperties:false, so dropping the field
first makes qa-lead's `aliases: []` fail validate-personas everywhere.

Why drop them (settled empirically, not by taste)

An alias exists so a RENAMED persona keeps routing: qa-lead declaring
`aliases: [petry-projects/murat]` so old comments still reach it. Two problems:

1. Index-free routing cannot honour it. The router resolves '@petry-projects/murat'
   to personas/murat/persona.yml — a 404 after the rename. The alias is declared
   inside qa-lead's manifest, which the router never opens because it does not
   know to look there. Chicken-and-egg. The attempt at pm_persona_aliases in
   .github#754 was unreachable for exactly this reason.

2. The severity argument for keeping them turned out to be FALSE. The worry was
   that GitHub redirects renamed team slugs, so an old mention would still LOOK
   live while the agent silently never ran — the UI lying, which is the failure
   class we have been eliminating. Probed it directly: created a team, rendered
   its mention (team-mention link), renamed the team, re-rendered the OLD handle:

     before rename: <a class="team-mention" ...>@petry-projects/pm-alias-probe</a>
     after rename:  <p>@petry-projects/pm-alias-probe please review</p>

   The old handle renders as PLAIN TEXT. GitHub itself stops treating it as a
   mention, so the user sees grey text and knows instantly it did not resolve.
   The failure is visible, and the fix is obvious: re-mention with the new handle.

So aliases would only route text GitHub no longer considers a mention — not worth
a derived index, an extra fetch on every 404, and a contract the router cannot
honour. See petry-projects/.github#755 finding 1.

Handle uniqueness is now a THEOREM, so its check is removed

check_handles_unique existed because aliases shared the handle namespace. Without
them it is provably unreachable: the schema pins the org (^petry-projects/...),
slug == id, id == the persona directory name, and directory names are unique — so
two personas cannot claim the same handle. A validator function that can never
fire is a liability: it implies a check where none is needed and invites
maintenance. Removed, with the theorem documented where the slug check lives.

Changes
- personas/qa-lead/persona.yml — drop `aliases: []`
- personas/validate-personas.py — drop alias shape validation and the now-dead
  check_handles_unique; document the uniqueness theorem
- tests/test_validate_personas.bats — drop the 4 alias tests and the helper's
  alias varargs; the handle-collision tests went with them because they used an
  alias as the collision vector and the collision is now impossible

Verification
- bats tests/test_validate_personas.bats: 16/16 (was 20; 4 alias tests removed).
- validate-personas.py against the LIVE main schema (which still permits aliases,
  so this must pass BEFORE the companion lands): OK, invariants hold.
- scripts/verify-persona-teams.sh (from #1284): OK — qa-lead's team still
  verifies live (exists, closed, notifications disabled).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(personas): drop the last aliases fixture and scope the theorem claim

Both from Copilot's review; both correct.

1. tests/verify_persona_teams.bats still wrote `aliases: []`

A real miss, and exactly the ordered-pair landmine this PR exists to avoid: the
moment the companion drops `aliases` from the schema (additionalProperties:
false), this fixture's generated manifest would fail validation. It survived
because my sweep grepped personas/ and tests/test_validate_personas.bats — this
fixture lives in the suite #1284 added, which I never looked at. A repo-wide
grep now shows zero remaining uses.

2. The uniqueness theorem was stated more broadly than it holds

The docstring claimed a uniqueness check "could never fire" — unconditionally
true only once the schema drops aliases. Today the schema still PERMITS an
alias, and aliases shared the handle namespace the theorem does not cover, so
until the companion lands, re-adding one would reopen exactly the gap the check
used to close. Scoped the claim to address.handle (the only thing the router
resolves) and recorded the window explicitly.

Verification
- bats tests/test_validate_personas.bats: 16/16.
- bats tests/verify_persona_teams.bats: 16/16 (the #1284 suite, now alias-free).
- validate-personas.py against the LIVE main schema: OK, invariants hold.
- Repo-wide grep for `aliases`: zero uses outside the docstring note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Aug 7, 2026
* refactor(personas): stop using address.aliases (half 1 of 2)

Aliases are dropped from the addressing contract. This is the FIRST half of an
ordered cross-repo pair — it removes every USE of the field. The companion PR in
petry-projects/.github then drops it from the schema. Reversing that order breaks
main fleet-wide: the schema is additionalProperties:false, so dropping the field
first makes qa-lead's `aliases: []` fail validate-personas everywhere.

Why drop them (settled empirically, not by taste)

An alias exists so a RENAMED persona keeps routing: qa-lead declaring
`aliases: [petry-projects/murat]` so old comments still reach it. Two problems:

1. Index-free routing cannot honour it. The router resolves '@petry-projects/murat'
   to personas/murat/persona.yml — a 404 after the rename. The alias is declared
   inside qa-lead's manifest, which the router never opens because it does not
   know to look there. Chicken-and-egg. The attempt at pm_persona_aliases in
   .github#754 was unreachable for exactly this reason.

2. The severity argument for keeping them turned out to be FALSE. The worry was
   that GitHub redirects renamed team slugs, so an old mention would still LOOK
   live while the agent silently never ran — the UI lying, which is the failure
   class we have been eliminating. Probed it directly: created a team, rendered
   its mention (team-mention link), renamed the team, re-rendered the OLD handle:

     before rename: <a class="team-mention" ...>@petry-projects/pm-alias-probe</a>
     after rename:  <p>@petry-projects/pm-alias-probe please review</p>

   The old handle renders as PLAIN TEXT. GitHub itself stops treating it as a
   mention, so the user sees grey text and knows instantly it did not resolve.
   The failure is visible, and the fix is obvious: re-mention with the new handle.

So aliases would only route text GitHub no longer considers a mention — not worth
a derived index, an extra fetch on every 404, and a contract the router cannot
honour. See petry-projects/.github#755 finding 1.

Handle uniqueness is now a THEOREM, so its check is removed

check_handles_unique existed because aliases shared the handle namespace. Without
them it is provably unreachable: the schema pins the org (^petry-projects/...),
slug == id, id == the persona directory name, and directory names are unique — so
two personas cannot claim the same handle. A validator function that can never
fire is a liability: it implies a check where none is needed and invites
maintenance. Removed, with the theorem documented where the slug check lives.

Changes
- personas/qa-lead/persona.yml — drop `aliases: []`
- personas/validate-personas.py — drop alias shape validation and the now-dead
  check_handles_unique; document the uniqueness theorem
- tests/test_validate_personas.bats — drop the 4 alias tests and the helper's
  alias varargs; the handle-collision tests went with them because they used an
  alias as the collision vector and the collision is now impossible

Verification
- bats tests/test_validate_personas.bats: 16/16 (was 20; 4 alias tests removed).
- validate-personas.py against the LIVE main schema (which still permits aliases,
  so this must pass BEFORE the companion lands): OK, invariants hold.
- scripts/verify-persona-teams.sh (from #1284): OK — qa-lead's team still
  verifies live (exists, closed, notifications disabled).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(personas): drop the last aliases fixture and scope the theorem claim

Both from Copilot's review; both correct.

1. tests/verify_persona_teams.bats still wrote `aliases: []`

A real miss, and exactly the ordered-pair landmine this PR exists to avoid: the
moment the companion drops `aliases` from the schema (additionalProperties:
false), this fixture's generated manifest would fail validation. It survived
because my sweep grepped personas/ and tests/test_validate_personas.bats — this
fixture lives in the suite #1284 added, which I never looked at. A repo-wide
grep now shows zero remaining uses.

2. The uniqueness theorem was stated more broadly than it holds

The docstring claimed a uniqueness check "could never fire" — unconditionally
true only once the schema drops aliases. Today the schema still PERMITS an
alias, and aliases shared the handle namespace the theorem does not cover, so
until the companion lands, re-adding one would reopen exactly the gap the check
used to close. Scoped the claim to address.handle (the only thing the router
resolves) and recorded the window explicitly.

Verification
- bats tests/test_validate_personas.bats: 16/16.
- bats tests/verify_persona_teams.bats: 16/16 (the #1284 suite, now alias-free).
- validate-personas.py against the LIVE main schema: OK, invariants hold.
- Repo-wide grep for `aliases`: zero uses outside the docstring note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Aug 7, 2026
* refactor(personas): stop using address.aliases (half 1 of 2)

Aliases are dropped from the addressing contract. This is the FIRST half of an
ordered cross-repo pair — it removes every USE of the field. The companion PR in
petry-projects/.github then drops it from the schema. Reversing that order breaks
main fleet-wide: the schema is additionalProperties:false, so dropping the field
first makes qa-lead's `aliases: []` fail validate-personas everywhere.

Why drop them (settled empirically, not by taste)

An alias exists so a RENAMED persona keeps routing: qa-lead declaring
`aliases: [petry-projects/murat]` so old comments still reach it. Two problems:

1. Index-free routing cannot honour it. The router resolves '@petry-projects/murat'
   to personas/murat/persona.yml — a 404 after the rename. The alias is declared
   inside qa-lead's manifest, which the router never opens because it does not
   know to look there. Chicken-and-egg. The attempt at pm_persona_aliases in
   .github#754 was unreachable for exactly this reason.

2. The severity argument for keeping them turned out to be FALSE. The worry was
   that GitHub redirects renamed team slugs, so an old mention would still LOOK
   live while the agent silently never ran — the UI lying, which is the failure
   class we have been eliminating. Probed it directly: created a team, rendered
   its mention (team-mention link), renamed the team, re-rendered the OLD handle:

     before rename: <a class="team-mention" ...>@petry-projects/pm-alias-probe</a>
     after rename:  <p>@petry-projects/pm-alias-probe please review</p>

   The old handle renders as PLAIN TEXT. GitHub itself stops treating it as a
   mention, so the user sees grey text and knows instantly it did not resolve.
   The failure is visible, and the fix is obvious: re-mention with the new handle.

So aliases would only route text GitHub no longer considers a mention — not worth
a derived index, an extra fetch on every 404, and a contract the router cannot
honour. See petry-projects/.github#755 finding 1.

Handle uniqueness is now a THEOREM, so its check is removed

check_handles_unique existed because aliases shared the handle namespace. Without
them it is provably unreachable: the schema pins the org (^petry-projects/...),
slug == id, id == the persona directory name, and directory names are unique — so
two personas cannot claim the same handle. A validator function that can never
fire is a liability: it implies a check where none is needed and invites
maintenance. Removed, with the theorem documented where the slug check lives.

Changes
- personas/qa-lead/persona.yml — drop `aliases: []`
- personas/validate-personas.py — drop alias shape validation and the now-dead
  check_handles_unique; document the uniqueness theorem
- tests/test_validate_personas.bats — drop the 4 alias tests and the helper's
  alias varargs; the handle-collision tests went with them because they used an
  alias as the collision vector and the collision is now impossible

Verification
- bats tests/test_validate_personas.bats: 16/16 (was 20; 4 alias tests removed).
- validate-personas.py against the LIVE main schema (which still permits aliases,
  so this must pass BEFORE the companion lands): OK, invariants hold.
- scripts/verify-persona-teams.sh (from #1284): OK — qa-lead's team still
  verifies live (exists, closed, notifications disabled).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(personas): drop the last aliases fixture and scope the theorem claim

Both from Copilot's review; both correct.

1. tests/verify_persona_teams.bats still wrote `aliases: []`

A real miss, and exactly the ordered-pair landmine this PR exists to avoid: the
moment the companion drops `aliases` from the schema (additionalProperties:
false), this fixture's generated manifest would fail validation. It survived
because my sweep grepped personas/ and tests/test_validate_personas.bats — this
fixture lives in the suite #1284 added, which I never looked at. A repo-wide
grep now shows zero remaining uses.

2. The uniqueness theorem was stated more broadly than it holds

The docstring claimed a uniqueness check "could never fire" — unconditionally
true only once the schema drops aliases. Today the schema still PERMITS an
alias, and aliases shared the handle namespace the theorem does not cover, so
until the companion lands, re-adding one would reopen exactly the gap the check
used to close. Scoped the claim to address.handle (the only thing the router
resolves) and recorded the window explicitly.

Verification
- bats tests/test_validate_personas.bats: 16/16.
- bats tests/verify_persona_teams.bats: 16/16 (the #1284 suite, now alias-free).
- validate-personas.py against the LIVE main schema: OK, invariants hold.
- Repo-wide grep for `aliases`: zero uses outside the docstring note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Aug 7, 2026
* refactor(personas): stop using address.aliases (half 1 of 2)

Aliases are dropped from the addressing contract. This is the FIRST half of an
ordered cross-repo pair — it removes every USE of the field. The companion PR in
petry-projects/.github then drops it from the schema. Reversing that order breaks
main fleet-wide: the schema is additionalProperties:false, so dropping the field
first makes qa-lead's `aliases: []` fail validate-personas everywhere.

Why drop them (settled empirically, not by taste)

An alias exists so a RENAMED persona keeps routing: qa-lead declaring
`aliases: [petry-projects/murat]` so old comments still reach it. Two problems:

1. Index-free routing cannot honour it. The router resolves '@petry-projects/murat'
   to personas/murat/persona.yml — a 404 after the rename. The alias is declared
   inside qa-lead's manifest, which the router never opens because it does not
   know to look there. Chicken-and-egg. The attempt at pm_persona_aliases in
   .github#754 was unreachable for exactly this reason.

2. The severity argument for keeping them turned out to be FALSE. The worry was
   that GitHub redirects renamed team slugs, so an old mention would still LOOK
   live while the agent silently never ran — the UI lying, which is the failure
   class we have been eliminating. Probed it directly: created a team, rendered
   its mention (team-mention link), renamed the team, re-rendered the OLD handle:

     before rename: <a class="team-mention" ...>@petry-projects/pm-alias-probe</a>
     after rename:  <p>@petry-projects/pm-alias-probe please review</p>

   The old handle renders as PLAIN TEXT. GitHub itself stops treating it as a
   mention, so the user sees grey text and knows instantly it did not resolve.
   The failure is visible, and the fix is obvious: re-mention with the new handle.

So aliases would only route text GitHub no longer considers a mention — not worth
a derived index, an extra fetch on every 404, and a contract the router cannot
honour. See petry-projects/.github#755 finding 1.

Handle uniqueness is now a THEOREM, so its check is removed

check_handles_unique existed because aliases shared the handle namespace. Without
them it is provably unreachable: the schema pins the org (^petry-projects/...),
slug == id, id == the persona directory name, and directory names are unique — so
two personas cannot claim the same handle. A validator function that can never
fire is a liability: it implies a check where none is needed and invites
maintenance. Removed, with the theorem documented where the slug check lives.

Changes
- personas/qa-lead/persona.yml — drop `aliases: []`
- personas/validate-personas.py — drop alias shape validation and the now-dead
  check_handles_unique; document the uniqueness theorem
- tests/test_validate_personas.bats — drop the 4 alias tests and the helper's
  alias varargs; the handle-collision tests went with them because they used an
  alias as the collision vector and the collision is now impossible

Verification
- bats tests/test_validate_personas.bats: 16/16 (was 20; 4 alias tests removed).
- validate-personas.py against the LIVE main schema (which still permits aliases,
  so this must pass BEFORE the companion lands): OK, invariants hold.
- scripts/verify-persona-teams.sh (from #1284): OK — qa-lead's team still
  verifies live (exists, closed, notifications disabled).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(personas): drop the last aliases fixture and scope the theorem claim

Both from Copilot's review; both correct.

1. tests/verify_persona_teams.bats still wrote `aliases: []`

A real miss, and exactly the ordered-pair landmine this PR exists to avoid: the
moment the companion drops `aliases` from the schema (additionalProperties:
false), this fixture's generated manifest would fail validation. It survived
because my sweep grepped personas/ and tests/test_validate_personas.bats — this
fixture lives in the suite #1284 added, which I never looked at. A repo-wide
grep now shows zero remaining uses.

2. The uniqueness theorem was stated more broadly than it holds

The docstring claimed a uniqueness check "could never fire" — unconditionally
true only once the schema drops aliases. Today the schema still PERMITS an
alias, and aliases shared the handle namespace the theorem does not cover, so
until the companion lands, re-adding one would reopen exactly the gap the check
used to close. Scoped the claim to address.handle (the only thing the router
resolves) and recorded the window explicitly.

Verification
- bats tests/test_validate_personas.bats: 16/16.
- bats tests/verify_persona_teams.bats: 16/16 (the #1284 suite, now alias-free).
- validate-personas.py against the LIVE main schema: OK, invariants hold.
- Repo-wide grep for `aliases`: zero uses outside the docstring note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Aug 7, 2026
* refactor(personas): stop using address.aliases (half 1 of 2)

Aliases are dropped from the addressing contract. This is the FIRST half of an
ordered cross-repo pair — it removes every USE of the field. The companion PR in
petry-projects/.github then drops it from the schema. Reversing that order breaks
main fleet-wide: the schema is additionalProperties:false, so dropping the field
first makes qa-lead's `aliases: []` fail validate-personas everywhere.

Why drop them (settled empirically, not by taste)

An alias exists so a RENAMED persona keeps routing: qa-lead declaring
`aliases: [petry-projects/murat]` so old comments still reach it. Two problems:

1. Index-free routing cannot honour it. The router resolves '@petry-projects/murat'
   to personas/murat/persona.yml — a 404 after the rename. The alias is declared
   inside qa-lead's manifest, which the router never opens because it does not
   know to look there. Chicken-and-egg. The attempt at pm_persona_aliases in
   .github#754 was unreachable for exactly this reason.

2. The severity argument for keeping them turned out to be FALSE. The worry was
   that GitHub redirects renamed team slugs, so an old mention would still LOOK
   live while the agent silently never ran — the UI lying, which is the failure
   class we have been eliminating. Probed it directly: created a team, rendered
   its mention (team-mention link), renamed the team, re-rendered the OLD handle:

     before rename: <a class="team-mention" ...>@petry-projects/pm-alias-probe</a>
     after rename:  <p>@petry-projects/pm-alias-probe please review</p>

   The old handle renders as PLAIN TEXT. GitHub itself stops treating it as a
   mention, so the user sees grey text and knows instantly it did not resolve.
   The failure is visible, and the fix is obvious: re-mention with the new handle.

So aliases would only route text GitHub no longer considers a mention — not worth
a derived index, an extra fetch on every 404, and a contract the router cannot
honour. See petry-projects/.github#755 finding 1.

Handle uniqueness is now a THEOREM, so its check is removed

check_handles_unique existed because aliases shared the handle namespace. Without
them it is provably unreachable: the schema pins the org (^petry-projects/...),
slug == id, id == the persona directory name, and directory names are unique — so
two personas cannot claim the same handle. A validator function that can never
fire is a liability: it implies a check where none is needed and invites
maintenance. Removed, with the theorem documented where the slug check lives.

Changes
- personas/qa-lead/persona.yml — drop `aliases: []`
- personas/validate-personas.py — drop alias shape validation and the now-dead
  check_handles_unique; document the uniqueness theorem
- tests/test_validate_personas.bats — drop the 4 alias tests and the helper's
  alias varargs; the handle-collision tests went with them because they used an
  alias as the collision vector and the collision is now impossible

Verification
- bats tests/test_validate_personas.bats: 16/16 (was 20; 4 alias tests removed).
- validate-personas.py against the LIVE main schema (which still permits aliases,
  so this must pass BEFORE the companion lands): OK, invariants hold.
- scripts/verify-persona-teams.sh (from #1284): OK — qa-lead's team still
  verifies live (exists, closed, notifications disabled).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(personas): drop the last aliases fixture and scope the theorem claim

Both from Copilot's review; both correct.

1. tests/verify_persona_teams.bats still wrote `aliases: []`

A real miss, and exactly the ordered-pair landmine this PR exists to avoid: the
moment the companion drops `aliases` from the schema (additionalProperties:
false), this fixture's generated manifest would fail validation. It survived
because my sweep grepped personas/ and tests/test_validate_personas.bats — this
fixture lives in the suite #1284 added, which I never looked at. A repo-wide
grep now shows zero remaining uses.

2. The uniqueness theorem was stated more broadly than it holds

The docstring claimed a uniqueness check "could never fire" — unconditionally
true only once the schema drops aliases. Today the schema still PERMITS an
alias, and aliases shared the handle namespace the theorem does not cover, so
until the companion lands, re-adding one would reopen exactly the gap the check
used to close. Scoped the claim to address.handle (the only thing the router
resolves) and recorded the window explicitly.

Verification
- bats tests/test_validate_personas.bats: 16/16.
- bats tests/verify_persona_teams.bats: 16/16 (the #1284 suite, now alias-free).
- validate-personas.py against the LIVE main schema: OK, invariants hold.
- Repo-wide grep for `aliases`: zero uses outside the docstring note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Aug 7, 2026
* refactor(personas): stop using address.aliases (half 1 of 2)

Aliases are dropped from the addressing contract. This is the FIRST half of an
ordered cross-repo pair — it removes every USE of the field. The companion PR in
petry-projects/.github then drops it from the schema. Reversing that order breaks
main fleet-wide: the schema is additionalProperties:false, so dropping the field
first makes qa-lead's `aliases: []` fail validate-personas everywhere.

Why drop them (settled empirically, not by taste)

An alias exists so a RENAMED persona keeps routing: qa-lead declaring
`aliases: [petry-projects/murat]` so old comments still reach it. Two problems:

1. Index-free routing cannot honour it. The router resolves '@petry-projects/murat'
   to personas/murat/persona.yml — a 404 after the rename. The alias is declared
   inside qa-lead's manifest, which the router never opens because it does not
   know to look there. Chicken-and-egg. The attempt at pm_persona_aliases in
   .github#754 was unreachable for exactly this reason.

2. The severity argument for keeping them turned out to be FALSE. The worry was
   that GitHub redirects renamed team slugs, so an old mention would still LOOK
   live while the agent silently never ran — the UI lying, which is the failure
   class we have been eliminating. Probed it directly: created a team, rendered
   its mention (team-mention link), renamed the team, re-rendered the OLD handle:

     before rename: <a class="team-mention" ...>@petry-projects/pm-alias-probe</a>
     after rename:  <p>@petry-projects/pm-alias-probe please review</p>

   The old handle renders as PLAIN TEXT. GitHub itself stops treating it as a
   mention, so the user sees grey text and knows instantly it did not resolve.
   The failure is visible, and the fix is obvious: re-mention with the new handle.

So aliases would only route text GitHub no longer considers a mention — not worth
a derived index, an extra fetch on every 404, and a contract the router cannot
honour. See petry-projects/.github#755 finding 1.

Handle uniqueness is now a THEOREM, so its check is removed

check_handles_unique existed because aliases shared the handle namespace. Without
them it is provably unreachable: the schema pins the org (^petry-projects/...),
slug == id, id == the persona directory name, and directory names are unique — so
two personas cannot claim the same handle. A validator function that can never
fire is a liability: it implies a check where none is needed and invites
maintenance. Removed, with the theorem documented where the slug check lives.

Changes
- personas/qa-lead/persona.yml — drop `aliases: []`
- personas/validate-personas.py — drop alias shape validation and the now-dead
  check_handles_unique; document the uniqueness theorem
- tests/test_validate_personas.bats — drop the 4 alias tests and the helper's
  alias varargs; the handle-collision tests went with them because they used an
  alias as the collision vector and the collision is now impossible

Verification
- bats tests/test_validate_personas.bats: 16/16 (was 20; 4 alias tests removed).
- validate-personas.py against the LIVE main schema (which still permits aliases,
  so this must pass BEFORE the companion lands): OK, invariants hold.
- scripts/verify-persona-teams.sh (from #1284): OK — qa-lead's team still
  verifies live (exists, closed, notifications disabled).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(personas): drop the last aliases fixture and scope the theorem claim

Both from Copilot's review; both correct.

1. tests/verify_persona_teams.bats still wrote `aliases: []`

A real miss, and exactly the ordered-pair landmine this PR exists to avoid: the
moment the companion drops `aliases` from the schema (additionalProperties:
false), this fixture's generated manifest would fail validation. It survived
because my sweep grepped personas/ and tests/test_validate_personas.bats — this
fixture lives in the suite #1284 added, which I never looked at. A repo-wide
grep now shows zero remaining uses.

2. The uniqueness theorem was stated more broadly than it holds

The docstring claimed a uniqueness check "could never fire" — unconditionally
true only once the schema drops aliases. Today the schema still PERMITS an
alias, and aliases shared the handle namespace the theorem does not cover, so
until the companion lands, re-adding one would reopen exactly the gap the check
used to close. Scoped the claim to address.handle (the only thing the router
resolves) and recorded the window explicitly.

Verification
- bats tests/test_validate_personas.bats: 16/16.
- bats tests/verify_persona_teams.bats: 16/16 (the #1284 suite, now alias-free).
- validate-personas.py against the LIVE main schema: OK, invariants hold.
- Repo-wide grep for `aliases`: zero uses outside the docstring note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Aug 7, 2026
* refactor(personas): stop using address.aliases (half 1 of 2)

Aliases are dropped from the addressing contract. This is the FIRST half of an
ordered cross-repo pair — it removes every USE of the field. The companion PR in
petry-projects/.github then drops it from the schema. Reversing that order breaks
main fleet-wide: the schema is additionalProperties:false, so dropping the field
first makes qa-lead's `aliases: []` fail validate-personas everywhere.

Why drop them (settled empirically, not by taste)

An alias exists so a RENAMED persona keeps routing: qa-lead declaring
`aliases: [petry-projects/murat]` so old comments still reach it. Two problems:

1. Index-free routing cannot honour it. The router resolves '@petry-projects/murat'
   to personas/murat/persona.yml — a 404 after the rename. The alias is declared
   inside qa-lead's manifest, which the router never opens because it does not
   know to look there. Chicken-and-egg. The attempt at pm_persona_aliases in
   .github#754 was unreachable for exactly this reason.

2. The severity argument for keeping them turned out to be FALSE. The worry was
   that GitHub redirects renamed team slugs, so an old mention would still LOOK
   live while the agent silently never ran — the UI lying, which is the failure
   class we have been eliminating. Probed it directly: created a team, rendered
   its mention (team-mention link), renamed the team, re-rendered the OLD handle:

     before rename: <a class="team-mention" ...>@petry-projects/pm-alias-probe</a>
     after rename:  <p>@petry-projects/pm-alias-probe please review</p>

   The old handle renders as PLAIN TEXT. GitHub itself stops treating it as a
   mention, so the user sees grey text and knows instantly it did not resolve.
   The failure is visible, and the fix is obvious: re-mention with the new handle.

So aliases would only route text GitHub no longer considers a mention — not worth
a derived index, an extra fetch on every 404, and a contract the router cannot
honour. See petry-projects/.github#755 finding 1.

Handle uniqueness is now a THEOREM, so its check is removed

check_handles_unique existed because aliases shared the handle namespace. Without
them it is provably unreachable: the schema pins the org (^petry-projects/...),
slug == id, id == the persona directory name, and directory names are unique — so
two personas cannot claim the same handle. A validator function that can never
fire is a liability: it implies a check where none is needed and invites
maintenance. Removed, with the theorem documented where the slug check lives.

Changes
- personas/qa-lead/persona.yml — drop `aliases: []`
- personas/validate-personas.py — drop alias shape validation and the now-dead
  check_handles_unique; document the uniqueness theorem
- tests/test_validate_personas.bats — drop the 4 alias tests and the helper's
  alias varargs; the handle-collision tests went with them because they used an
  alias as the collision vector and the collision is now impossible

Verification
- bats tests/test_validate_personas.bats: 16/16 (was 20; 4 alias tests removed).
- validate-personas.py against the LIVE main schema (which still permits aliases,
  so this must pass BEFORE the companion lands): OK, invariants hold.
- scripts/verify-persona-teams.sh (from #1284): OK — qa-lead's team still
  verifies live (exists, closed, notifications disabled).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(personas): drop the last aliases fixture and scope the theorem claim

Both from Copilot's review; both correct.

1. tests/verify_persona_teams.bats still wrote `aliases: []`

A real miss, and exactly the ordered-pair landmine this PR exists to avoid: the
moment the companion drops `aliases` from the schema (additionalProperties:
false), this fixture's generated manifest would fail validation. It survived
because my sweep grepped personas/ and tests/test_validate_personas.bats — this
fixture lives in the suite #1284 added, which I never looked at. A repo-wide
grep now shows zero remaining uses.

2. The uniqueness theorem was stated more broadly than it holds

The docstring claimed a uniqueness check "could never fire" — unconditionally
true only once the schema drops aliases. Today the schema still PERMITS an
alias, and aliases shared the handle namespace the theorem does not cover, so
until the companion lands, re-adding one would reopen exactly the gap the check
used to close. Scoped the claim to address.handle (the only thing the router
resolves) and recorded the window explicitly.

Verification
- bats tests/test_validate_personas.bats: 16/16.
- bats tests/verify_persona_teams.bats: 16/16 (the #1284 suite, now alias-free).
- validate-personas.py against the LIVE main schema: OK, invariants hold.
- Repo-wide grep for `aliases`: zero uses outside the docstring note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Aug 7, 2026
* refactor(personas): stop using address.aliases (half 1 of 2)

Aliases are dropped from the addressing contract. This is the FIRST half of an
ordered cross-repo pair — it removes every USE of the field. The companion PR in
petry-projects/.github then drops it from the schema. Reversing that order breaks
main fleet-wide: the schema is additionalProperties:false, so dropping the field
first makes qa-lead's `aliases: []` fail validate-personas everywhere.

Why drop them (settled empirically, not by taste)

An alias exists so a RENAMED persona keeps routing: qa-lead declaring
`aliases: [petry-projects/murat]` so old comments still reach it. Two problems:

1. Index-free routing cannot honour it. The router resolves '@petry-projects/murat'
   to personas/murat/persona.yml — a 404 after the rename. The alias is declared
   inside qa-lead's manifest, which the router never opens because it does not
   know to look there. Chicken-and-egg. The attempt at pm_persona_aliases in
   .github#754 was unreachable for exactly this reason.

2. The severity argument for keeping them turned out to be FALSE. The worry was
   that GitHub redirects renamed team slugs, so an old mention would still LOOK
   live while the agent silently never ran — the UI lying, which is the failure
   class we have been eliminating. Probed it directly: created a team, rendered
   its mention (team-mention link), renamed the team, re-rendered the OLD handle:

     before rename: <a class="team-mention" ...>@petry-projects/pm-alias-probe</a>
     after rename:  <p>@petry-projects/pm-alias-probe please review</p>

   The old handle renders as PLAIN TEXT. GitHub itself stops treating it as a
   mention, so the user sees grey text and knows instantly it did not resolve.
   The failure is visible, and the fix is obvious: re-mention with the new handle.

So aliases would only route text GitHub no longer considers a mention — not worth
a derived index, an extra fetch on every 404, and a contract the router cannot
honour. See petry-projects/.github#755 finding 1.

Handle uniqueness is now a THEOREM, so its check is removed

check_handles_unique existed because aliases shared the handle namespace. Without
them it is provably unreachable: the schema pins the org (^petry-projects/...),
slug == id, id == the persona directory name, and directory names are unique — so
two personas cannot claim the same handle. A validator function that can never
fire is a liability: it implies a check where none is needed and invites
maintenance. Removed, with the theorem documented where the slug check lives.

Changes
- personas/qa-lead/persona.yml — drop `aliases: []`
- personas/validate-personas.py — drop alias shape validation and the now-dead
  check_handles_unique; document the uniqueness theorem
- tests/test_validate_personas.bats — drop the 4 alias tests and the helper's
  alias varargs; the handle-collision tests went with them because they used an
  alias as the collision vector and the collision is now impossible

Verification
- bats tests/test_validate_personas.bats: 16/16 (was 20; 4 alias tests removed).
- validate-personas.py against the LIVE main schema (which still permits aliases,
  so this must pass BEFORE the companion lands): OK, invariants hold.
- scripts/verify-persona-teams.sh (from #1284): OK — qa-lead's team still
  verifies live (exists, closed, notifications disabled).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(personas): drop the last aliases fixture and scope the theorem claim

Both from Copilot's review; both correct.

1. tests/verify_persona_teams.bats still wrote `aliases: []`

A real miss, and exactly the ordered-pair landmine this PR exists to avoid: the
moment the companion drops `aliases` from the schema (additionalProperties:
false), this fixture's generated manifest would fail validation. It survived
because my sweep grepped personas/ and tests/test_validate_personas.bats — this
fixture lives in the suite #1284 added, which I never looked at. A repo-wide
grep now shows zero remaining uses.

2. The uniqueness theorem was stated more broadly than it holds

The docstring claimed a uniqueness check "could never fire" — unconditionally
true only once the schema drops aliases. Today the schema still PERMITS an
alias, and aliases shared the handle namespace the theorem does not cover, so
until the companion lands, re-adding one would reopen exactly the gap the check
used to close. Scoped the claim to address.handle (the only thing the router
resolves) and recorded the window explicitly.

Verification
- bats tests/test_validate_personas.bats: 16/16.
- bats tests/verify_persona_teams.bats: 16/16 (the #1284 suite, now alias-free).
- validate-personas.py against the LIVE main schema: OK, invariants hold.
- Repo-wide grep for `aliases`: zero uses outside the docstring note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Aug 8, 2026
* refactor(personas): stop using address.aliases (half 1 of 2)

Aliases are dropped from the addressing contract. This is the FIRST half of an
ordered cross-repo pair — it removes every USE of the field. The companion PR in
petry-projects/.github then drops it from the schema. Reversing that order breaks
main fleet-wide: the schema is additionalProperties:false, so dropping the field
first makes qa-lead's `aliases: []` fail validate-personas everywhere.

Why drop them (settled empirically, not by taste)

An alias exists so a RENAMED persona keeps routing: qa-lead declaring
`aliases: [petry-projects/murat]` so old comments still reach it. Two problems:

1. Index-free routing cannot honour it. The router resolves '@petry-projects/murat'
   to personas/murat/persona.yml — a 404 after the rename. The alias is declared
   inside qa-lead's manifest, which the router never opens because it does not
   know to look there. Chicken-and-egg. The attempt at pm_persona_aliases in
   .github#754 was unreachable for exactly this reason.

2. The severity argument for keeping them turned out to be FALSE. The worry was
   that GitHub redirects renamed team slugs, so an old mention would still LOOK
   live while the agent silently never ran — the UI lying, which is the failure
   class we have been eliminating. Probed it directly: created a team, rendered
   its mention (team-mention link), renamed the team, re-rendered the OLD handle:

     before rename: <a class="team-mention" ...>@petry-projects/pm-alias-probe</a>
     after rename:  <p>@petry-projects/pm-alias-probe please review</p>

   The old handle renders as PLAIN TEXT. GitHub itself stops treating it as a
   mention, so the user sees grey text and knows instantly it did not resolve.
   The failure is visible, and the fix is obvious: re-mention with the new handle.

So aliases would only route text GitHub no longer considers a mention — not worth
a derived index, an extra fetch on every 404, and a contract the router cannot
honour. See petry-projects/.github#755 finding 1.

Handle uniqueness is now a THEOREM, so its check is removed

check_handles_unique existed because aliases shared the handle namespace. Without
them it is provably unreachable: the schema pins the org (^petry-projects/...),
slug == id, id == the persona directory name, and directory names are unique — so
two personas cannot claim the same handle. A validator function that can never
fire is a liability: it implies a check where none is needed and invites
maintenance. Removed, with the theorem documented where the slug check lives.

Changes
- personas/qa-lead/persona.yml — drop `aliases: []`
- personas/validate-personas.py — drop alias shape validation and the now-dead
  check_handles_unique; document the uniqueness theorem
- tests/test_validate_personas.bats — drop the 4 alias tests and the helper's
  alias varargs; the handle-collision tests went with them because they used an
  alias as the collision vector and the collision is now impossible

Verification
- bats tests/test_validate_personas.bats: 16/16 (was 20; 4 alias tests removed).
- validate-personas.py against the LIVE main schema (which still permits aliases,
  so this must pass BEFORE the companion lands): OK, invariants hold.
- scripts/verify-persona-teams.sh (from #1284): OK — qa-lead's team still
  verifies live (exists, closed, notifications disabled).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(personas): drop the last aliases fixture and scope the theorem claim

Both from Copilot's review; both correct.

1. tests/verify_persona_teams.bats still wrote `aliases: []`

A real miss, and exactly the ordered-pair landmine this PR exists to avoid: the
moment the companion drops `aliases` from the schema (additionalProperties:
false), this fixture's generated manifest would fail validation. It survived
because my sweep grepped personas/ and tests/test_validate_personas.bats — this
fixture lives in the suite #1284 added, which I never looked at. A repo-wide
grep now shows zero remaining uses.

2. The uniqueness theorem was stated more broadly than it holds

The docstring claimed a uniqueness check "could never fire" — unconditionally
true only once the schema drops aliases. Today the schema still PERMITS an
alias, and aliases shared the handle namespace the theorem does not cover, so
until the companion lands, re-adding one would reopen exactly the gap the check
used to close. Scoped the claim to address.handle (the only thing the router
resolves) and recorded the window explicitly.

Verification
- bats tests/test_validate_personas.bats: 16/16.
- bats tests/verify_persona_teams.bats: 16/16 (the #1284 suite, now alias-free).
- validate-personas.py against the LIVE main schema: OK, invariants hold.
- Repo-wide grep for `aliases`: zero uses outside the docstring note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Aug 8, 2026
* refactor(personas): stop using address.aliases (half 1 of 2)

Aliases are dropped from the addressing contract. This is the FIRST half of an
ordered cross-repo pair — it removes every USE of the field. The companion PR in
petry-projects/.github then drops it from the schema. Reversing that order breaks
main fleet-wide: the schema is additionalProperties:false, so dropping the field
first makes qa-lead's `aliases: []` fail validate-personas everywhere.

Why drop them (settled empirically, not by taste)

An alias exists so a RENAMED persona keeps routing: qa-lead declaring
`aliases: [petry-projects/murat]` so old comments still reach it. Two problems:

1. Index-free routing cannot honour it. The router resolves '@petry-projects/murat'
   to personas/murat/persona.yml — a 404 after the rename. The alias is declared
   inside qa-lead's manifest, which the router never opens because it does not
   know to look there. Chicken-and-egg. The attempt at pm_persona_aliases in
   .github#754 was unreachable for exactly this reason.

2. The severity argument for keeping them turned out to be FALSE. The worry was
   that GitHub redirects renamed team slugs, so an old mention would still LOOK
   live while the agent silently never ran — the UI lying, which is the failure
   class we have been eliminating. Probed it directly: created a team, rendered
   its mention (team-mention link), renamed the team, re-rendered the OLD handle:

     before rename: <a class="team-mention" ...>@petry-projects/pm-alias-probe</a>
     after rename:  <p>@petry-projects/pm-alias-probe please review</p>

   The old handle renders as PLAIN TEXT. GitHub itself stops treating it as a
   mention, so the user sees grey text and knows instantly it did not resolve.
   The failure is visible, and the fix is obvious: re-mention with the new handle.

So aliases would only route text GitHub no longer considers a mention — not worth
a derived index, an extra fetch on every 404, and a contract the router cannot
honour. See petry-projects/.github#755 finding 1.

Handle uniqueness is now a THEOREM, so its check is removed

check_handles_unique existed because aliases shared the handle namespace. Without
them it is provably unreachable: the schema pins the org (^petry-projects/...),
slug == id, id == the persona directory name, and directory names are unique — so
two personas cannot claim the same handle. A validator function that can never
fire is a liability: it implies a check where none is needed and invites
maintenance. Removed, with the theorem documented where the slug check lives.

Changes
- personas/qa-lead/persona.yml — drop `aliases: []`
- personas/validate-personas.py — drop alias shape validation and the now-dead
  check_handles_unique; document the uniqueness theorem
- tests/test_validate_personas.bats — drop the 4 alias tests and the helper's
  alias varargs; the handle-collision tests went with them because they used an
  alias as the collision vector and the collision is now impossible

Verification
- bats tests/test_validate_personas.bats: 16/16 (was 20; 4 alias tests removed).
- validate-personas.py against the LIVE main schema (which still permits aliases,
  so this must pass BEFORE the companion lands): OK, invariants hold.
- scripts/verify-persona-teams.sh (from #1284): OK — qa-lead's team still
  verifies live (exists, closed, notifications disabled).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(personas): drop the last aliases fixture and scope the theorem claim

Both from Copilot's review; both correct.

1. tests/verify_persona_teams.bats still wrote `aliases: []`

A real miss, and exactly the ordered-pair landmine this PR exists to avoid: the
moment the companion drops `aliases` from the schema (additionalProperties:
false), this fixture's generated manifest would fail validation. It survived
because my sweep grepped personas/ and tests/test_validate_personas.bats — this
fixture lives in the suite #1284 added, which I never looked at. A repo-wide
grep now shows zero remaining uses.

2. The uniqueness theorem was stated more broadly than it holds

The docstring claimed a uniqueness check "could never fire" — unconditionally
true only once the schema drops aliases. Today the schema still PERMITS an
alias, and aliases shared the handle namespace the theorem does not cover, so
until the companion lands, re-adding one would reopen exactly the gap the check
used to close. Scoped the claim to address.handle (the only thing the router
resolves) and recorded the window explicitly.

Verification
- bats tests/test_validate_personas.bats: 16/16.
- bats tests/verify_persona_teams.bats: 16/16 (the #1284 suite, now alias-free).
- validate-personas.py against the LIVE main schema: OK, invariants hold.
- Repo-wide grep for `aliases`: zero uses outside the docstring note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Aug 8, 2026
* refactor(personas): stop using address.aliases (half 1 of 2)

Aliases are dropped from the addressing contract. This is the FIRST half of an
ordered cross-repo pair — it removes every USE of the field. The companion PR in
petry-projects/.github then drops it from the schema. Reversing that order breaks
main fleet-wide: the schema is additionalProperties:false, so dropping the field
first makes qa-lead's `aliases: []` fail validate-personas everywhere.

Why drop them (settled empirically, not by taste)

An alias exists so a RENAMED persona keeps routing: qa-lead declaring
`aliases: [petry-projects/murat]` so old comments still reach it. Two problems:

1. Index-free routing cannot honour it. The router resolves '@petry-projects/murat'
   to personas/murat/persona.yml — a 404 after the rename. The alias is declared
   inside qa-lead's manifest, which the router never opens because it does not
   know to look there. Chicken-and-egg. The attempt at pm_persona_aliases in
   .github#754 was unreachable for exactly this reason.

2. The severity argument for keeping them turned out to be FALSE. The worry was
   that GitHub redirects renamed team slugs, so an old mention would still LOOK
   live while the agent silently never ran — the UI lying, which is the failure
   class we have been eliminating. Probed it directly: created a team, rendered
   its mention (team-mention link), renamed the team, re-rendered the OLD handle:

     before rename: <a class="team-mention" ...>@petry-projects/pm-alias-probe</a>
     after rename:  <p>@petry-projects/pm-alias-probe please review</p>

   The old handle renders as PLAIN TEXT. GitHub itself stops treating it as a
   mention, so the user sees grey text and knows instantly it did not resolve.
   The failure is visible, and the fix is obvious: re-mention with the new handle.

So aliases would only route text GitHub no longer considers a mention — not worth
a derived index, an extra fetch on every 404, and a contract the router cannot
honour. See petry-projects/.github#755 finding 1.

Handle uniqueness is now a THEOREM, so its check is removed

check_handles_unique existed because aliases shared the handle namespace. Without
them it is provably unreachable: the schema pins the org (^petry-projects/...),
slug == id, id == the persona directory name, and directory names are unique — so
two personas cannot claim the same handle. A validator function that can never
fire is a liability: it implies a check where none is needed and invites
maintenance. Removed, with the theorem documented where the slug check lives.

Changes
- personas/qa-lead/persona.yml — drop `aliases: []`
- personas/validate-personas.py — drop alias shape validation and the now-dead
  check_handles_unique; document the uniqueness theorem
- tests/test_validate_personas.bats — drop the 4 alias tests and the helper's
  alias varargs; the handle-collision tests went with them because they used an
  alias as the collision vector and the collision is now impossible

Verification
- bats tests/test_validate_personas.bats: 16/16 (was 20; 4 alias tests removed).
- validate-personas.py against the LIVE main schema (which still permits aliases,
  so this must pass BEFORE the companion lands): OK, invariants hold.
- scripts/verify-persona-teams.sh (from #1284): OK — qa-lead's team still
  verifies live (exists, closed, notifications disabled).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(personas): drop the last aliases fixture and scope the theorem claim

Both from Copilot's review; both correct.

1. tests/verify_persona_teams.bats still wrote `aliases: []`

A real miss, and exactly the ordered-pair landmine this PR exists to avoid: the
moment the companion drops `aliases` from the schema (additionalProperties:
false), this fixture's generated manifest would fail validation. It survived
because my sweep grepped personas/ and tests/test_validate_personas.bats — this
fixture lives in the suite #1284 added, which I never looked at. A repo-wide
grep now shows zero remaining uses.

2. The uniqueness theorem was stated more broadly than it holds

The docstring claimed a uniqueness check "could never fire" — unconditionally
true only once the schema drops aliases. Today the schema still PERMITS an
alias, and aliases shared the handle namespace the theorem does not cover, so
until the companion lands, re-adding one would reopen exactly the gap the check
used to close. Scoped the claim to address.handle (the only thing the router
resolves) and recorded the window explicitly.

Verification
- bats tests/test_validate_personas.bats: 16/16.
- bats tests/verify_persona_teams.bats: 16/16 (the #1284 suite, now alias-free).
- validate-personas.py against the LIVE main schema: OK, invariants hold.
- Repo-wide grep for `aliases`: zero uses outside the docstring note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Aug 8, 2026
* refactor(personas): stop using address.aliases (half 1 of 2)

Aliases are dropped from the addressing contract. This is the FIRST half of an
ordered cross-repo pair — it removes every USE of the field. The companion PR in
petry-projects/.github then drops it from the schema. Reversing that order breaks
main fleet-wide: the schema is additionalProperties:false, so dropping the field
first makes qa-lead's `aliases: []` fail validate-personas everywhere.

Why drop them (settled empirically, not by taste)

An alias exists so a RENAMED persona keeps routing: qa-lead declaring
`aliases: [petry-projects/murat]` so old comments still reach it. Two problems:

1. Index-free routing cannot honour it. The router resolves '@petry-projects/murat'
   to personas/murat/persona.yml — a 404 after the rename. The alias is declared
   inside qa-lead's manifest, which the router never opens because it does not
   know to look there. Chicken-and-egg. The attempt at pm_persona_aliases in
   .github#754 was unreachable for exactly this reason.

2. The severity argument for keeping them turned out to be FALSE. The worry was
   that GitHub redirects renamed team slugs, so an old mention would still LOOK
   live while the agent silently never ran — the UI lying, which is the failure
   class we have been eliminating. Probed it directly: created a team, rendered
   its mention (team-mention link), renamed the team, re-rendered the OLD handle:

     before rename: <a class="team-mention" ...>@petry-projects/pm-alias-probe</a>
     after rename:  <p>@petry-projects/pm-alias-probe please review</p>

   The old handle renders as PLAIN TEXT. GitHub itself stops treating it as a
   mention, so the user sees grey text and knows instantly it did not resolve.
   The failure is visible, and the fix is obvious: re-mention with the new handle.

So aliases would only route text GitHub no longer considers a mention — not worth
a derived index, an extra fetch on every 404, and a contract the router cannot
honour. See petry-projects/.github#755 finding 1.

Handle uniqueness is now a THEOREM, so its check is removed

check_handles_unique existed because aliases shared the handle namespace. Without
them it is provably unreachable: the schema pins the org (^petry-projects/...),
slug == id, id == the persona directory name, and directory names are unique — so
two personas cannot claim the same handle. A validator function that can never
fire is a liability: it implies a check where none is needed and invites
maintenance. Removed, with the theorem documented where the slug check lives.

Changes
- personas/qa-lead/persona.yml — drop `aliases: []`
- personas/validate-personas.py — drop alias shape validation and the now-dead
  check_handles_unique; document the uniqueness theorem
- tests/test_validate_personas.bats — drop the 4 alias tests and the helper's
  alias varargs; the handle-collision tests went with them because they used an
  alias as the collision vector and the collision is now impossible

Verification
- bats tests/test_validate_personas.bats: 16/16 (was 20; 4 alias tests removed).
- validate-personas.py against the LIVE main schema (which still permits aliases,
  so this must pass BEFORE the companion lands): OK, invariants hold.
- scripts/verify-persona-teams.sh (from #1284): OK — qa-lead's team still
  verifies live (exists, closed, notifications disabled).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(personas): drop the last aliases fixture and scope the theorem claim

Both from Copilot's review; both correct.

1. tests/verify_persona_teams.bats still wrote `aliases: []`

A real miss, and exactly the ordered-pair landmine this PR exists to avoid: the
moment the companion drops `aliases` from the schema (additionalProperties:
false), this fixture's generated manifest would fail validation. It survived
because my sweep grepped personas/ and tests/test_validate_personas.bats — this
fixture lives in the suite #1284 added, which I never looked at. A repo-wide
grep now shows zero remaining uses.

2. The uniqueness theorem was stated more broadly than it holds

The docstring claimed a uniqueness check "could never fire" — unconditionally
true only once the schema drops aliases. Today the schema still PERMITS an
alias, and aliases shared the handle namespace the theorem does not cover, so
until the companion lands, re-adding one would reopen exactly the gap the check
used to close. Scoped the claim to address.handle (the only thing the router
resolves) and recorded the window explicitly.

Verification
- bats tests/test_validate_personas.bats: 16/16.
- bats tests/verify_persona_teams.bats: 16/16 (the #1284 suite, now alias-free).
- validate-personas.py against the LIVE main schema: OK, invariants hold.
- Repo-wide grep for `aliases`: zero uses outside the docstring note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants