Skip to content

feat(shepherd): enforce canonical owner gate#2180

Merged
danielmeppiel merged 6 commits into
mainfrom
harden/architecture-owner-gate
Jul 12, 2026
Merged

feat(shepherd): enforce canonical owner gate#2180
danielmeppiel merged 6 commits into
mainfrom
harden/architecture-owner-gate

Conversation

@danielmeppiel

Copy link
Copy Markdown
Collaborator

harden(shepherd): enforce the canonical-owner gate

TL;DR

Bug shepherding now classifies every PR against the canonical-owner architecture before it can reach a terminal state. shepherd-driver owns enforcement, while batch-bug-shepherd supplies fix-time context and reports the returned evidence without reimplementing the gate. The completion schema fails closed when architecture evidence or required dual guardrails are missing.

Important

This is the systemic follow-up to the PR #2155 architecture audit: the four affected bug PRs remain independently scoped, while this PR prevents the same review gap from recurring.

Problem (WHY)

  • The audit found PR fix(audit): honor locked skill subsets during replay #2177 at ready-to-merge with behavioral coverage but without the static architecture guard required for its lockfile-to-replay ownership seam.
  • The prior completion_return schema could prove CI and lint status, but it had no field for architecture classification, canonical-owner routing, or dual-guardrail evidence.
  • A first schema draft still allowed new-owner and split-authority-repair to self-report dual_guardrail_required=false; a regression test reproduced that bypass before the schema was tightened.
  • [!] Updating package and deployed skill copies without their lockfile hashes produced 11 hash-drift findings under apm audit --ci; this branch now synchronizes all 11 records.

These findings came from real execution, matching the Agent Skills guidance to "Run the skill against real tasks, then feed the results — all of them, not just failures — back into the creation process." The terminal contract is intentionally strict because "Be prescriptive when operations are fragile, consistency matters, or a specific sequence must be followed:".

Approach (WHAT)

# Fix Principle Source
1 Make shepherd-driver the single enforcement owner. "Design coherent units" Driver phase X.2.5 and completion contract
2 Encode terminal evidence and authority-creating classifications in Draft 7 JSON Schema. "Match specificity to fragility" completion-schema.json
3 Keep the batch orchestrator limited to classification context, delegation, and reporting. "Favor procedures over declarations" Batch invariant, fix prompt, final report
4 Exercise the workflow through deterministic with-skill/without-skill content evals. "Refine with real execution" Two eval scenarios and three new anchors

Implementation (HOW)

Surface Change
packages/shepherd-driver/SKILL.md and assets/shepherd-driver-prompt.md Add mandatory phase X.2.5 after fold/defer classification. Every PR gets exactly one architecture classification, owner/routing evidence, and an exact-head boundary-lint result. Missing evidence remains in the loop or returns blocked.
packages/shepherd-driver/assets/completion-schema.json Require architecture_evidence for ready-to-merge and advisory-with-deferred. new-owner and split-authority-repair force dual_guardrail_required=true; that flag requires behavioral, static, architecture-test, and mutation-break evidence.
packages/batch-bug-shepherd/.apm/skills/batch-bug-shepherd/{SKILL.md,references/invariants.md} Bind the parent workflow to the driver-owned gate and explicitly prohibit duplicate enforcement in the orchestrator.
packages/batch-bug-shepherd/.apm/skills/batch-bug-shepherd/assets/{fix-prompt.md,final-report-template.md} Give greenfield fix agents the classification contract before implementation and expose classified/proved/blocked counts in the final report.
packages/batch-bug-shepherd/.apm/skills/batch-bug-shepherd/evals/** Add classification, dual-guardrail, and fail-closed anchors to two scenarios; only with-skill fixtures contain the new evidence.
.agents/skills/{shepherd-driver,batch-bug-shepherd}/** Keep deployed copies byte-identical to their package sources.
tests/unit/test_shepherd_driver_completion_schema.py Lock terminal evidence, classification-to-guardrail coupling, complete four-part evidence, valid non-creating classifications, and schema mirror parity.
apm.lock.yaml Update both compatibility hashes and canonical deployment rows for the 11 changed deployed primitive files.
docs/superpowers/specs/2026-07-12-canonical-owner-gate-design.md Record the observed failures, ownership model, fail-closed behavior, and isolated delivery strategy.
docs/superpowers/plans/2026-07-12-*.md Preserve the implementation plans for the four remediations and this workflow hardening.

The exact implementation is anchored at 1e2b983de067512c4476b5c8a8f799931512762c.

Diagrams

Legend: the dashed stages are new; follow the path from fix implementation to either schema-valid terminal evidence or a blocked/iterating result.

flowchart LR
    subgraph Fix[Fix implementation]
        F1[Behavioral regression]
        F2[Follow-ups folded]
    end
    subgraph Driver[shepherd-driver phase X.2.5]
        C1[Classify architecture impact]
        C2[Record owner and consumer routing]
        G{Dual guardrail required}
        E[Collect four evidence fields]
        L[Run exact-head boundary lint]
    end
    subgraph Contract[Completion contract]
        S[Validate architecture_evidence]
        R[Ready or advisory]
        B[Iterate or blocked]
    end
    F1 --> F2 --> C1 --> C2 --> G
    G -->|yes| E --> L --> S
    G -->|no| L
    S -->|valid| R
    S -->|missing| B
    classDef new stroke-dasharray: 5 5;
    class C1,C2,G,E,L,S,B new;
Loading

Trade-offs

  • Driver-owned enforcement over parent duplication. The orchestrator records and reports the driver's schema-valid return; it does not rerun classification, avoiding two authorities for the same terminal decision.
  • Schema-enforced hard cases over schema-only architecture inference. new-owner and split-authority-repair cannot disable the guardrail. A centralizing owner-extension still requires model judgment because JSON Schema cannot infer code semantics; the prompt requires a rationale naming the existing guard when the flag is false.
  • Deterministic content evals over live-model evals. Regex anchors are reproducible and distinguish with-skill from without-skill fixtures, but they validate required output structure rather than semantic code review quality.
  • Focused hash synchronization over apm install. apm install --dry-run proposed 234 unrelated removals in this checkout, so the PR updates only the 11 canonical hashes computed for changed deployed files and proves the result with apm audit --ci.
  • No changelog entry. This changes maintainer orchestration primitives and their tests, not the released CLI or a user-facing package contract.

Benefits

  1. Every terminal shepherd result carries one of five explicit architecture classifications.
  2. Both terminal success-like statuses require architecture_evidence; missing evidence is schema-invalid.
  3. Authority-creating fixes must supply four named evidence fields plus an exact-head boundary-lint result.
  4. Three architecture anchors pass in each of two with-skill scenarios and remain absent from both without-skill baselines.
  5. All 11 changed deployed primitive hashes match their canonical lockfile records, leaving zero audit drift.

Validation

uv run apm audit --ci:

[+] No drift detected
[*] All 9 check(s) passed

uv run --extra dev pytest -q tests/unit/test_shepherd_driver_completion_schema.py:

........                                                                 [100%]
8 passed in 0.48s

uv run --extra dev python packages/batch-bug-shepherd/.apm/skills/batch-bug-shepherd/scripts/run_evals.py:

[>] running trigger evals
[>] running content evals
"delta_anchors": 18
"delta_anchors": 20
"passed": true
Repository lint and parity gates

uv run --extra dev ruff check src/ tests/:

All checks passed!

uv run --extra dev ruff format --check src/ tests/:

1481 files already formatted

uv run --extra dev python -m pylint --disable=all --enable=R0801 --min-similarity-lines=10 --fail-on=R0801 src/apm_cli/:

Your code has been rated at 10.00/10

bash scripts/lint-auth-signals.sh && bash scripts/lint-architecture-boundaries.sh:

[+] auth-signal lint clean
[+] architecture boundary lint clean

diff -rq across both package/deployed skill trees produced no output.

Scenario Evidence

# Scenario (user promise) Principle(s) Test(s) proving it Type
1 A shepherded PR cannot be reported ready without an architecture review result. Governed by policy, OSS / community-driven tests/unit/test_shepherd_driver_completion_schema.py::test_ready_completion_requires_architecture_evidence unit
2 A fix that creates or repairs authority cannot mark itself exempt from dual guardrails. Governed by policy tests/unit/test_shepherd_driver_completion_schema.py::test_authority_creating_classification_cannot_disable_dual_guardrail unit
3 A new owner reaches a terminal state only with behavioral, static, architecture-test, and mutation-break evidence. Governed by policy tests/unit/test_shepherd_driver_completion_schema.py::test_new_owner_requires_complete_dual_guardrail_evidence unit
4 Batch bug sweeps report classified PRs and block incomplete owner evidence instead of deferring it. OSS / community-driven, DevX (pragmatic as npm) packages/batch-bug-shepherd/.apm/skills/batch-bug-shepherd/evals/content/{three-issues-mixed,sweep-bug-queue}.json via scripts/run_evals.py integration
5 Installed shepherd schemas remain identical to their package source. Portability by manifest tests/unit/test_shepherd_driver_completion_schema.py::test_completion_schema_mirror_is_byte_identical plus apm audit --ci integration

How to test

  • Run the schema unit test; expect 8 passing cases.
  • Change a new-owner fixture to dual_guardrail_required=false; expect schema validation to fail.
  • Remove one of the four evidence fields from a dual-guardrail fixture; expect schema validation to fail.
  • Run the batch shepherd eval runner; expect both scenarios to pass with architecture anchor deltas.
  • Run uv run apm audit --ci; expect all 9 checks to pass with no drift.

Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 7955c89b-a997-42aa-9c45-ef4c7fe4b1e7
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 7955c89b-a997-42aa-9c45-ef4c7fe4b1e7
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 7955c89b-a997-42aa-9c45-ef4c7fe4b1e7
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 7955c89b-a997-42aa-9c45-ef4c7fe4b1e7
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 7955c89b-a997-42aa-9c45-ef4c7fe4b1e7
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 7955c89b-a997-42aa-9c45-ef4c7fe4b1e7
Copilot AI review requested due to automatic review settings July 12, 2026 22:00
@danielmeppiel

Copy link
Copy Markdown
Collaborator Author

Docs sync advisory

Verdict: no_change * Pages affected: 0 * LLM calls: 0/15 * Took: 1s

Summary

No documentation changes needed for this PR.

The diff changes maintainer orchestration primitives, their deterministic evals, unit tests, design/plan records, and deployed-content hashes. It does not change a CLI command, flag, public schema, runtime behavior, or any page under docs/src/content/docs/**, so no Starlight corpus page requires an update.

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

This PR hardens the shepherding workflow by making the canonical-owner architecture gate a required, schema-enforced part of shepherd-driver terminal completions, and propagates that contract into batch-bug-shepherd prompts, invariants, and deterministic eval anchors to prevent “ready-to-merge” without architecture evidence.

Changes:

  • Adds architecture_evidence to the shepherd-driver completion JSON Schema and requires it for ready-to-merge / advisory-with-deferred.
  • Updates shepherd-driver and batch-bug-shepherd skill prose/prompts to run and report the canonical-owner gate (fail-closed) plus dual-guardrail evidence when required.
  • Adds unit tests and content-eval anchors, and synchronizes deployed skill copies + lockfile hashes.
Show a summary per file
File Description
tests/unit/test_shepherd_driver_completion_schema.py New regression tests for schema-level enforcement of canonical-owner completion evidence.
packages/shepherd-driver/SKILL.md Inserts Phase X.2.5 canonical-owner gate into the driver loop and terminal return expectations.
packages/shepherd-driver/assets/shepherd-driver-prompt.md Adds Step X.2.5 canonical-owner gate procedure and documents required architecture_evidence in the completion return.
packages/shepherd-driver/assets/completion-schema.json Extends completion schema with architecture_evidence and requires it for terminal success-like statuses.
packages/batch-bug-shepherd/.apm/skills/batch-bug-shepherd/SKILL.md Updates invariants summary to include driver-enforced canonical-owner gate.
packages/batch-bug-shepherd/.apm/skills/batch-bug-shepherd/references/invariants.md Adds full binding invariant for canonical-owner gate and clarifies driver vs orchestrator responsibilities.
packages/batch-bug-shepherd/.apm/skills/batch-bug-shepherd/evals/fixtures/three-issues-mixed.with_skill.md Adds with-skill fixture evidence text for architecture classification + fail-closed behavior.
packages/batch-bug-shepherd/.apm/skills/batch-bug-shepherd/evals/fixtures/sweep-bug-queue.with_skill.md Adds with-skill fixture evidence text for architecture classification + dual-guardrail evidence.
packages/batch-bug-shepherd/.apm/skills/batch-bug-shepherd/evals/content/three-issues-mixed.json Adds content-eval anchors for architecture classification, dual-guardrail evidence, and fail-closed behavior.
packages/batch-bug-shepherd/.apm/skills/batch-bug-shepherd/evals/content/sweep-bug-queue.json Adds content-eval anchors for architecture classification, dual-guardrail evidence, and fail-closed behavior.
packages/batch-bug-shepherd/.apm/skills/batch-bug-shepherd/assets/fix-prompt.md Propagates architecture classification + dual-guardrail expectations into greenfield fix prompt.
packages/batch-bug-shepherd/.apm/skills/batch-bug-shepherd/assets/final-report-template.md Adds reporting fields for canonical-owner gate classification / blocked counts.
docs/superpowers/specs/2026-07-12-canonical-owner-gate-design.md Design write-up capturing motivation, contract, failure modes, and delivery strategy.
docs/superpowers/plans/2026-07-12-shepherd-canonical-owner-gate.md Implementation plan for the workflow hardening and validation steps.
docs/superpowers/plans/2026-07-12-pr-2177-subset-propagation-guard.md Plan for adding static architecture guards to PR #2177’s authority seam.
docs/superpowers/plans/2026-07-12-pr-2176-subset-owner-hardening.md Plan for hardening subset owner boundary checks (AST-based checker + lint wiring).
docs/superpowers/plans/2026-07-12-pr-2170-relative-link-validation.md Plan for fixing remaining relative links and adding a build-time relative-link validator.
docs/superpowers/plans/2026-07-12-pr-2094-windows-stable-path-guard.md Plan for enforcing install.ps1 as the sole owner of Windows stable executable path derivation.
apm.lock.yaml Updates deployed file hashes/content hashes for synchronized installed skill copies.
.agents/skills/shepherd-driver/SKILL.md Synchronizes deployed skill copy with package source.
.agents/skills/shepherd-driver/assets/shepherd-driver-prompt.md Synchronizes deployed prompt copy with package source.
.agents/skills/shepherd-driver/assets/completion-schema.json Synchronizes deployed schema copy with package source.
.agents/skills/batch-bug-shepherd/SKILL.md Synchronizes deployed skill copy with package source.
.agents/skills/batch-bug-shepherd/references/invariants.md Synchronizes deployed invariants copy with package source.
.agents/skills/batch-bug-shepherd/evals/fixtures/three-issues-mixed.with_skill.md Synchronizes deployed eval fixture copy with package source.
.agents/skills/batch-bug-shepherd/evals/fixtures/sweep-bug-queue.with_skill.md Synchronizes deployed eval fixture copy with package source.
.agents/skills/batch-bug-shepherd/evals/content/three-issues-mixed.json Synchronizes deployed eval anchors copy with package source.
.agents/skills/batch-bug-shepherd/evals/content/sweep-bug-queue.json Synchronizes deployed eval anchors copy with package source.
.agents/skills/batch-bug-shepherd/assets/fix-prompt.md Synchronizes deployed fix prompt copy with package source.
.agents/skills/batch-bug-shepherd/assets/final-report-template.md Synchronizes deployed report template copy with package source.

Review details

  • Files reviewed: 30/30 changed files
  • Comments generated: 3
  • Review effort level: Low

Comment on lines +186 to +190
"decisions": {
"type": "array",
"description": "Every durable decision the PR touches, with its canonical owner and the evidence that each consumer routes through that owner. Empty array is legal for ordinary-fix / not-applicable.",
"items": {
"type": "object",
Comment on lines +36 to +41
"architecture_evidence": {
"classification": classification,
"decisions": [],
"dual_guardrail_required": dual_guardrail_required,
"boundary_lint": "exit 0 on exact head",
},
Comment on lines +112 to +114
decision's canonical owner and consumer routing, run
`bash scripts/lint-architecture-boundaries.sh` on the head, and --
for a new owner, centralization, or split repair -- require the full
@danielmeppiel danielmeppiel merged commit a29c049 into main Jul 12, 2026
16 checks passed
@danielmeppiel danielmeppiel deleted the harden/architecture-owner-gate branch July 12, 2026 23:33
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.

2 participants