CI Gates - alexherrero/crickets GitHub Wiki
"Is it green" has one answer in crickets: the local gate battery passes. This page lists every gate in it, the CI matrix that mirrors it, and where to look when one fails.
A pull request whose full diff is confined to wiki/** and/or *.md files skips the wait for the full matrix inside ci-all.yml's aggregate job β a job-level classifier (scripts/ci_diff_classifier.py), not a trigger-level paths-ignore (pull_request deliberately carries none, since a required check a trigger filter could skip would block a docs-only PR's merge forever). A plain push to main does still carry paths-ignore on wiki/**/*.md, but push no longer runs the full battery at all (worktree-native flow, 2026-07-06) β it only ever triggers tests-linux.yml's lightweight syntax job.
One command runs every deterministic gate locally:
bash scripts/check-all.sh| Gate | What it checks |
|---|---|
lint_src |
src/ source of truth β group.yaml + every primitive's frontmatter (incl. the standalone βΊ requires: [] invariant and enhances: cross-references) |
capability naming |
check-capability-naming.py β plugin and capability names obey the AG naming rule |
no-dangling-name |
check-no-dangling-name.py β repo-wide gate against dangling references to a retired/renamed plugin or capability name |
no-duplicate-diagnosis |
check-no-duplicate-diagnosis.py β the "no two diagnosis engines" regression net; bespoke failure-classification logic must delegate to diagnose.py, never re-grow its own inline category/confidence judgment |
no-harness-paths |
check-no-harness-paths.py β no plugin names the vault's retired harness directory, tests included: a project's homes are its own tasks/, designs/ and desk/, and a plugin asks agentm for them. A line may keep the word with a harness-deprecation: marker. The script's EXEMPT list names the files the in-flight part 15 landings still clear, and a listed file with no hits left fails the gate, so the list only shrinks. --inventory prints every hit by plugin. agentm runs the same gate under the same name |
conventions conformance |
check_conventions_conformance.py β a plugin that consults a conventions domain (an explicit <!-- consults-conventions-domain: <domain> --> marker) must declare it; checks declaration, not content correctness |
unit tests |
the scripts/ test suite (test_*.py β lint, model, generator, plus the CI-consistency check that enforces the both-places rule) |
vault-content tests |
test_voice_kernel.py, asserting facts about a real MemoryVault: the voice kernel is locatable and small, the three heavy genre files stayed demoted out of the always-load tier and resolvable on demand, and the kernel still reaches at least one live consumer. Runs without the AGENTM_INSTALL_PREFIX / MEMORY_ROOT (and its deprecated alias MEMORY_VAULT_PATH) isolation the unit tests gate uses, because that scratch prefix makes these skip themselves into silence. Skips cleanly when no vault resolves, so it is a no-op in CI and on any machine without one. test_voice_kernel_layouts.py, part of unit tests, runs the suite against scratch vaults on every layout the kernel has lived on, so CI still catches the suite drifting from prose_pass. |
evidence-tracker self-test |
evidence_tracker.py --mode self-test β the evidence-tracker hook's own embedded self-test suite (67 tests) covering the default-FAIL evidence contract, named- and singleton-plan aware |
generate drift |
generate.py check β committed dist/ matches a fresh generation, byte-for-byte |
dist-references |
check-dist-references.py β every emitted plugin payload's relative links + ${CLAUDE_PLUGIN_ROOT} paths resolve inside its own dist tree (grandfathers known pre-existing gaps) |
version bump |
each plugin whose src/<slug>/** changed must bump its group.yaml version: (compares against origin/main; graceful-skips when that ref is unresolvable) |
check-wiki |
the wiki linter, --strict (DiΓ‘taxis modes, links, sidebars, basename collisions) |
check-slop |
the deterministic anti-slop voice gate, --strict (blocking on error- or warning-tier findings since 2026-07-10, CONS-3 β the verdict's ruling 2; suggestion-tier findings, e.g. term-of-art words with a documented carve-out, never fail by the gate's own design) against the versioned rule pack (src/wiki/skills/diataxis-author/style/voice-rules.json) |
voice-floor-parity |
check-voice-floor-parity.py --report β the overlayβfloor promotion parity gate: keeps base-style-guide.md's banned: line honest against the rule pack; report-only, same posture as the opinion-parity gates below |
check-syntax |
bash -n every .sh (CI also AST-parses every .ps1) |
check-hook-parity |
Asserts every developer-safety hook keeps its .sh/.ps1 twins behaviorally paired β neither twin may reference a workspace-relative .harness/β¦ path without first resolving the workspace from the host's hook-input contract (workspacePaths + a cd/Set-Location). |
check-no-pii |
the PII regex scanner over the whole tree (crickets is public) |
opinion-snapshot-parity |
check-opinion-snapshot-parity.py --report β keeps the committed scripts/opinion-snapshots/<name>.md snapshots (what generate.py bakes into dist/ for cross-plugin opinion consumers) honest against agentm's live opinions/<name>.md; graceful-skip (exit 0) when no agentm sibling is checked out to diff against. Report-only: drift is surfaced, not blocking, until an automated refresh exists. |
opinion-self-provider-drift |
check-opinion-self-provider-drift.py --report β for a self-provider opinion binding (the caller IS the opinion's implements: artifact, e.g. code-reviewβgood), flags agentm's opinions/<name>.md stub if it drifts from curated anchor phrases in the caller's own shipped prose (adversarial-reviewer.md), checking only in that direction; graceful-skip (exit 0) when no agentm sibling is checked out. Report-only, same posture as opinion-snapshot-parity. |
cross-repo-script-parity |
check-cross-repo-script-parity.py --report β keeps crickets' canonical src/privacy/scripts/check-no-pii.sh + src/wiki/scripts/check-wiki.py honest against agentm's independently-maintained scripts/check-no-pii.sh + scripts/check-wiki.py. Not a byte-diff β compares the PII "kind" names and the lettered check-wiki rule identifiers each copy declares, since the two pairs carry legitimate one-sided content (crickets' check-wiki.py has 3 component-overview rules β m/n/o β agentm's wiki has no page-type for, documented in the script's own ALLOWED_CRICKETS_ONLY_RULES). Graceful-skip (exit 0) when no agentm sibling is reachable locally; runs for real in CI inside the obsidian-vault-conformance job, the one job that already checks out the agentm kernel. Report-only, same posture as the two opinion gates above. |
board sync |
check_project_sync.py β the vault==board drift oracle: computes the expected GitHub Project board state from board-items.json and diffs it against the live board (read-only gh issue list), failing on any drift; graceful-skip (exit 0) when there's no project.json or no gh
|
tag-reachability |
all git tags must point to commits reachable from main β concurrent-release coordination backstop; graceful-skip when main doesn't resolve (fresh repos, non-main default-branch names) |
conformance-suite |
Active. A dedicated obsidian-vault-conformance CI job (Linux + Windows) runs the obsidian-vault plugin backend's conformance / discovery / doctor suites against a checked-out agentm kernel, on every pull request (also on the nightly main-HEAD backstop workflow); local discovery rides check-all.sh's unit-test gate with graceful-skip when the kernel isn't checked out. |
It prints a PASS/FAIL table and exits non-zero on any failure. Run it before every commit.
Three OS workflows run their full battery on every pull request. A plain push to main only runs tests-linux.yml's lightweight syntax job (the one job with no if: gate) β the other jobs (validate, pii-guardrails, obsidian-vault-conformance) all gate on github.event_name == 'pull_request' (worktree-native flow, ratified 2026-07-06 β main only merges a PR whose checks already passed). All three run the toolchain gates (source lint Β· unit tests Β· drift Β· wiki lint) on pull_request; the syntax checks follow each OS's shell surface, and gitleaks rides the Linux leg:
| OS | Workflow | What it runs |
|---|---|---|
Linux (ubuntu-latest) |
tests-linux.yml |
toolchain gates Β· .sh + .ps1 syntax Β· PII scan Β· gitleaks |
macOS (macos-latest) |
tests-mac.yml |
toolchain gates Β· .sh + .ps1 syntax Β· PII scan |
Windows (windows-latest, PowerShell 7+) |
tests-windows.yml |
toolchain gates (under PYTHONUTF8: 1) Β· .ps1 syntax Β· PII scan |
The single CI badge on the README + wiki Home points at ci-all.yml, an aggregate workflow that waits for all three OS workflows and reports a combined result. To drill into a failure, click the badge, open the Actions tab, and pick the failing OS; the failing step names the gate.
-
gitleaks β the industry-standard secret scanner, alongside
check-no-pii.sh(two independent PII/secret layers; the pre-push git hook is the third, on your machine). -
PowerShell syntax β
check-syntax.ps1AST-parses every.ps1(locally this runs only wherepwshis installed). -
claude plugin validateβ runs intests-linux.yml'svalidatejob, which installs@anthropic-ai/claude-codevia npm first, then validatesdist/claude-code/.claude-plugin/marketplace.jsonand everydist/claude-code/plugins/*/directory non-strict (the marketplacecapabilities:/enhances:fields are soft-composition metadata outside Claude's schema, and--strictwould flag them as errors instead of the harmless warnings they are). -
(Not in CI:)
agy plugin validateβagyhas no npm/CI-installable distribution, so Antigravity plugin loadability stays proven at dogfood time only. -
Wiki publish β
wiki-sync.yml([W] Update Wiki) rsyncswiki/to the GitHub wiki on every push tomain(afterlint-wikipasses), with a case-sensitive duplicate-basename check on the emitted tree (sort | uniq -d, no lowercasing). The case-insensitive collision rule lives separately incheck-wiki --strict's own basename-collision rule, which runs first as thelint-wikijob and would already block a case-only collision.
When a new check earns its keep, add it in both places: a run line in scripts/check-all.sh and a step in tests-linux.yml β the battery stays the single source of truth for "is it green," and scripts/test_ci_consistency.py's TestBatteryMatchesLinuxWorkflow fails the battery if they drift (only the Linux leg is held to the full both-places rule; a narrower subset β lint_src, the unit suite, generate-drift, check-wiki β is separately required on all three OSes via TestPortabilitySubset).
- Compatibility β supported hosts + the per-plugin/hook support matrices.
- Modify a plugin β the edit β generate β dogfood loop the gates protect.
-
Manifest schema β the contract
lint_srcenforces. - PII Guardrail β the interactive layer of the PII defense the gates back-stop.
- Obsidian vault backend β the vault backend plugin (sole vault-backend implementation since V5-3) whose conformance-suite gate is described above.