Repository navigation
gate: extend ADR maintainer approval path predicate to .claude/skills/** — make Prime Directive #14 enforced (#9319 ruling) #9395
Description
Activity
Claim: PM seat dispatch
Session:session_01NYgmGheCzM6NrHZN436Cxf
Branch:claude/issue-9395-adr-gate-skills-paths
Scope: as the card specifies —scripts/check-adr-merge-approval.mjspath predicate + self-tests, workflow trigger verification, #8012 armed clause coverage for the new path class, reverse verification in the PR body. ⛔ No weakening of any existing check while landing; no Settings change needed.
Routing authority: maintainer ruling on #9319 decision 2, 2026-08-17 「同意」 batch.Label
pm:queue→pm:dispatchedin the same stroke.
Generated by Claude Code
- added a commit that references this issue
on Aug 17, 2026 { "issue": 9395, "status": "done", "branch": "claude/issue-9395-adr-gate-skills-paths", "pr": "https://github.com/objectstack-ai/objectstack/pull/9407", "premise_still_valid": true, "summary": "The ADR merge-approval gate's single ADR path prefix became a GOVERNED_SURFACES table holding docs/adr/ and .claude/skills/ under identical pass conditions (an APPROVED current standing plus no armed auto-merge) with distinct failure wording — an ADR red cites the 2026-08-12 approval ruling and #6741, a skills red cites Prime Directive #14 and the #9319 decision-2 ruling, and a mixed diff carries both blocks. One path hit governs the whole PR; proportion is never computed. The report renderer was made pure (renderVerdict) so the distinct-wording requirement is asserted on the text an operator reads, and PR #9238 joined the historical replay fixtures as a real API capture pinned RED. The workflow needed no trigger change: it carries no paths filter, and #9238 (a skills-only diff) already produced a completed 'ADR maintainer approval' check run — verified both structurally and empirically, stated in the workflow header and the PR body. The required job name is untouched. No existing check weakened: every prior assertion still runs.", "tests": "All at cc1a065 (git rev-parse --short HEAD after the final commit, quoted from the union run). `pnpm check:adr-merge-approval` -> '✓ 96 assertions over the real decide() / review-state / PR-resolution paths' (origin/main baseline: 66; +30 new). Gate families re-derived with `node scripts/pm/dispatch-gates.mjs` against the actual changed paths, all exit 0: check:node-version ('OK, 28 setup-node step(s) across 25 workflow(s)'), check:required-contexts ('adr-merge-approval.yml:adr-merge-approval -> ADR maintainer approval'), check:shard-attestation ('2 aggregate gate(s) count 3 declared leg(s)'), check:workflow-status-functions ('OK, scanned 25 workflow file(s)'), plus check:nul-bytes ('OK, scanned 6108 text file(s), no raw ASCII control bytes') and `npx eslint scripts/check-adr-merge-approval.mjs --no-inline-config` (clean, exit 0). REVERSE VERIFICATION, predicted then observed, four offline-replay legs over the same skills+package.json mixed diff: [1] OLD gate (origin/main copy), zero reviews -> predicted GREEN (the hole), observed exit=0 'No files under docs/adr/'; [2] NEW gate, same inputs -> predicted RED, observed exit=1 citing '.claude/skills/**' and 'Prime Directive #14'; [3] NEW gate, APPROVED + disarmed -> predicted GREEN, observed exit=0; [4] NEW gate, APPROVED + ARMED -> predicted RED for the arming, observed exit=1 'AUTO-MERGE IS ARMED'. Rows 3/4 are the clause-(2) emptiness proof on the new class. A fifth leg ran gate mode over a real git diff in a throwaway detached worktree with a synthetic .claude/skills edit (never committed, never pushed, removed): OLD exit=0 green, NEW exit=1 after entering the gated path ('.claude/skills/** touched -- consulting reviews of PR #9379'); the local red is the fail-loud path (HTTP 401, no usable token in this container), not the approval verdict — reported as observed rather than as the template's presumption. No ablation and no dist involved: the gate script imports node builtins only. `pnpm install --frozen-lockfile` was still run because the derived workflow gates need `yaml`. skip-changeset label applied and READ BACK as present alongside the bot's ci/cd and size/l labels (scripts + workflow only; nothing published).", "open_questions": [], "out_of_scope_findings": [ "filed as #9403: AGENTS.md's Prime Directive #14 text names only docs/adr/**, so the directive the gate now cites in its skills-surface failure does not itself name that surface (unlabeled — governance prose, maintainer's call)", "filed as #9404 (finding): the published skills/ catalog is human-merge by pm-dispatch convention but ungated — two of that fork's three prefixes are now enforced; deliberate here since the ruling names .claude/skills/** only" ] }PR #9407 is draft, not marked ready, no auto-merge armed. CI status at report time:
in_progress(reported at draft-PR time per the 2026-08-10 rule; the convergence wait is the PM's).
Generated by Claude Code
- added a commit that references this issue
on Aug 23, 2026
Implements the maintainer's #9319 decision-2 ruling (2026-08-17, 「同意」 batch): PR #9238 proved a
.claude/skills/**change can reachmainthrough the merge queue with zero human clicks, bypassing Prime Directive #14 (skill/ADR PRs are human-merge only). Prose already forbade it; only a gate makes it impossible.The work
Extend the ADR merge-approval gate so PRs touching
.claude/skills/**are held to the same contract asdocs/adr/**:scripts/check-adr-merge-approval.mjs— widen the path predicate that decides whether a PR is gate-scoped; keep the two surfaces' reason strings distinct in output (an ADR PR and a skills PR fail with wording naming their own rule)..github/workflows/adr-merge-approval.yml— confirm the trigger set needs no change (it fires on all PRs and the script decides scope; verify rather than assume).docs/adr/**PR today, which would have made the maintainer's approval the merge trigger #8012 clause applies identically: an ARMED auto-merge on a gate-scoped PR keeps the check red regardless of approval (armed+approved = unattended merge, which is exactly what docs(pm): label writes re-read current labels in the same action — stale snapshots are invalid snapshots (#9226) #9238 demonstrated).Acceptance
.claude/skills/**showsADR maintainer approvalred until maintainer approval, and stays red while auto-merge is armed.⛔ This PR itself touches gate scripts — it is NOT skill-surface, but treat sequencing carefully: it must not weaken any existing check while landing. No Settings change is needed (the check is already required).
Refs: #9319 (the finding and ruling) · #9238 (the bypass instance) · #8012 (armed-auto-merge clause) · Prime Directive #14.