feat(ci): polyglot stack + snapshot-refresh + lane summary + ci:full (F14)#23
Merged
Merged
Conversation
Pure ES-module classifier that decides which lane a PR routes to: docs-only, workflow-only, policy-only, snapshot-refresh, code lanes, or forced-full. Mirrors the parse-evidence.mjs pattern (pure function, dynamic-import from the workflow caller). 40 vitest fixtures cover every lane plus the Iridescent-Church guardrails: snapshot-only requires EVERY file to match (#3), polyglot fails fast on empty path lists (#4), ci:full label override beats every other lane (#2), and stack=minimal+code preserves the legacy invariant. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
) Routes PRs to the smallest lane that still gives real signal. Replaces the inline detect-step JS with a dynamic-import of scripts/classify-pr.mjs (same pattern as pr-policy + parse-evidence). The single required check remains `repo-required-gate / decision`; per-lane jobs stay conditional under it. New inputs: - stack: polyglot — fans out to node-ci and/or python-ci based on which caller-declared workspace paths the PR touched. node-paths and python-paths default empty; consumers MUST declare at least one when stack=polyglot (fail-fast, Guardrail #4). - snapshot-paths + snapshot-test-command — PRs whose EVERY file matches snapshot-paths skip language CI and run the consumer's snapshot test instead (Guardrail #3, ALL files must match). - force-full-ci-label (default `ci:full`) — Release-Admiral's escape hatch when a workflow-only PR could still break CI semantically (Guardrail #2). - workflow-library-ref (default `v1`) — pins the classifier checkout to the same ref callers pin this workflow at. Detect job now emits a one-line core.notice + step-summary block with the lane label, changed files, and required/skipped job list so the routing decision is legible from the Actions list view (Guardrail #5). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Consumers can copy the relevant block for their stack. Also adds `labeled, unlabeled` to the pull_request event types so applying the ci:full label on an open PR triggers a fresh gate run. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ArchonVII
marked this pull request as ready for review
May 21, 2026 14:27
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #8. Extends
repo-required-gate.yml(the F14 aggregator) with three new lanes plus an explicit escape hatch, and surfaces lane decisions in the GitHub UI. Driven by the Iridescent-Church plan (2026-05-20) and PR-history analysis: workflow-only is the largest under-routed bucket (~11 of 86 sampled PRs), snapshot-refresh is a clean recurring shape in archon-setup, and the highest-volume consumer (comfyui-companion) has no Python CI today.Three commits, atomic:
feat(scripts)— pure classifier (scripts/classify-pr.mjs) with 40 vitest fixtures.feat(ci)— rewriterepo-required-gate.ymlto dynamic-import the classifier, add polyglot stack, snapshot-refresh lane, lane summary, ci:full label override.docs(examples)— show all caller shapes including polyglot and snapshot-refresh.Guardrail compliance
decision. Branch protection on consumer repos still requires onlyrepo-required-gate / decision.ci:fullescape hatchforce-full-ci-labelinput (defaultci:full). Forces both language CIs regardless of path routing. Case-insensitive match.snapshot-only: trueonly whennames.every(...). One non-matching file falls through to full language CI. Test fixture #12 explicitly covers the mixed case.node-paths: ""andpython-paths: ""defaults.stack=polyglotwith both empty fails fast (test #15).core.notice('Lane: <name>')+ a$GITHUB_STEP_SUMMARYblock listing lane label, changed files, jobs required, and jobs skipped. Ships day one in this PR, not as a follow-up.Lanes
The classifier picks ONE of these, by priority:
forced-full (label: ci:full)— user overridesnapshot-refresh— every file matches snapshot-pathsdocs-only— every file is a doc file (and not a policy file)workflow-only— every file is.github/workflows/**or.githooks/**policy-only— every file isAGENTS.md/CLAUDE.md/GEMINI.md/.agent/**code (node)/code (python)/code (polyglot: …)— language CI fans out per touched workspacepass-through— no matching files (rare)Backward compatibility
Existing
stack: minimal/stack: node/stack: pythonconsumers see no behavior change. The minimal-stack invariant (code change on stack=minimal → error) is preserved as a classifier fail-fast (test #27b).Verification
Verification Notes
All 40 new vitest fixtures pass plus the 16 existing parse-evidence tests (56 total).
```evidence
command: npx vitest run scripts/
location: local
result: 56/56 pass; 0 failures
timestamp: 2026-05-20T20:55:56Z
```
Three atomic commits on
agent/claude/8-gate-lanes-polyglot-snapshot, each one logical unit per CLAUDE.md atomic-commit rule.```evidence
command: git log --oneline agent/claude/8-gate-lanes-polyglot-snapshot ^main
location: local
result: 3 commits — 4d96941 feat(scripts), 9c71117 feat(ci), 0f40319 docs(examples)
timestamp: 2026-05-20T20:57:30Z
```
Actionlint passes on the rewritten workflow (will run via this repo's
actionlint.ymlworkflow on this PR — needs CI verification).Self-test (
self-test.yml) runs the new vitest fixtures on PR via thescripts/**path filter — needs CI verification.Rollout sequence (post-merge)
Per
[[playbook-ecosystem-capability-rollout]]:v1tag to the merge SHA (also picks up the pending F2/F10 hotfix that's been waiting since 2026-05-20).comfyui-companionto adoptstack: polyglotwith explicitnode-paths/python-pathsforserver/,web/,electron/,analysis-service/.archon-setupto add its first.github/workflows/directory +test:snapshotsscript, thennpm run refresh-snapshots.docs/phase2/hook-authority.mdto mark F14 resolved.Do NOT promote any per-lane job to a required branch-protection check (Guardrail #1).
🤖 Generated with Claude Code