ai-slop-gate β Contribution Guideο
Thank you for your interest in ai-slop-gate π
Goal: prevent βAI slopβ β including inside ai-slop-gate itself.
All architectural decisions are defined in
ai_slop_gate_snapshot.json(v7.5.0). If this document conflicts with the snapshot, the snapshot wins.
Project Philosophyο
Advisory-first: By default, nothing is blocking. Results are recommendations, not verdicts.
Short > Clear > Readable: Output must be concise, signal-like, and actionable.
Policy is the source of truth: All enforcement flows from
policy.yml.No hidden logic: Every decision is traceable.
Architectural Principles (Non-Negotiable)ο
Component |
Does |
Does NOT |
|---|---|---|
|
Parses args, wires components |
Contains analysis logic |
|
Orchestrates providers |
Formats output |
|
Evaluates observations β Decision |
Knows about CI or reporters |
|
Collect or analyze data |
Make enforcement decisions |
|
Render and deliver output |
Know about providers |
|
Prevent duplicate LLM calls |
Cache static providers |
Zero dependency on CI platforms. CLI works locally and in any CI without GitHub/GitLab SDKs.
Provider-first design. Everything goes through providers via registry. CLI never imports concrete providers directly.
Canonical Contractsο
BaseProviderο
class BaseProvider(ABC):
name: str
kind: str # "llm" | "static" | "infra"
@abstractmethod
def analyze(self, code: str, input_file: str = "") -> ProviderObservation:
# LLM: analyze PR diff or snippet
...
@abstractmethod
def collect(self, base_path: str = ".") -> ProviderObservation:
# Static/infra: scan a directory
# LLM: delegates to chunked file scanning via LlmProvider
...
def analyze_pr(self, repo: str, pr_id: int, token: str) -> ProviderObservation:
# Optional: direct PR analysis (LLM providers only)
# Default raises NotImplementedError
...
ProviderObservationο
@dataclass(frozen=True)
class ProviderObservation:
provider: str
model: str
observations: List[Any]
raw_text: str
CachedProviderο
Wraps any LLM provider. Caches collect() and analyze() results.
Must not change provider behavior. CachedProvider is infrastructure, not logic.
class CacheBackend:
def get(self, key): ...
def set(self, key, value): ...
Adding a New Providerο
LLM Providerο
Create
ai_slop_gate/providers/llm/<n>.pyextendingLlmProviderwithkind = "llm"Implement
analyze(code, input_file)βProviderObservationOptionally implement
analyze_pr(repo, pr_id, token)Add prompt file(s) to
ai_slop_gate/providers/llm/prompts/<n>/Register in
providers/registry.pyAdd
--provider <n>to CLIWrite tests in
tests/unit/providers/
LLM JSON contract β prompt must instruct the model to return:
{
"issues": [
{
"category": "security|quality|architecture|...",
"signal": "snake_case_identifier",
"message": "non-empty string",
"severity": "low|medium|high|critical",
"confidence": 0.85,
"file": "path/to/file.py",
"line": 42
}
]
}
No markdown, no text outside JSON, no ranges for line numbers.
Static/Infra Providerο
Create
ai_slop_gate/providers/static/<n>.pyextendingBaseProviderSet
kind = "static"or"infra"Implement
collect(base_path)βProviderObservationRegister in
providers/registry.pyWrite tests with positive (detects issues) and negative (clean code) examples
Testing Philosophyο
Tests lock architectural contracts, not implementation.
Critical invariants:
LLM token is not spent twice for the same cache key
Cache key changes when input or policy changes
Static providers are never wrapped by CachedProvider
python -m pytest ai_slop_gate/tests -v
python -m pytest ai_slop_gate/tests --cov=ai_slop_gate --cov-report=term-missing
Snapshot Ruleο
Any architectural change must:
Update
ai_slop_gate_snapshot.jsonBump the snapshot version (e.g.
7.4.0β7.5.0)Be aligned with the roadmap
No snapshot update = not canonical.
Roadmapο
β Stage 5 β DONEο
GitLab support, provider registry, cache contracts, CachedProvider, rate-limit guard, file cache backend.
β Stage 6 β Runtime & UX (current)ο
initcommand (ai-slop-gate init)Policy examples for static, plan.json, k8s
Kubernetes runtime: admission-style analysis, advisory-only
π Stage 7 β AI Quality Heuristicsο
LLM as advisor, short outputs, mandatory caching.
π Stage 8 β Terraformο
Static terraform plan parsing. Advisory mode only.
π Stage 9 β Composition & Profilesο
Profiles (ci, local, infra) and preset policies.
Working with AI Assistantsο
ai-slop-gate ships context files for AI-assisted development. Use them β they prevent the tool from generating βAI slopβ in its own codebase.
GitHub Copilot (VS Code)ο
.github/copilot-instructions.md is loaded automatically by Copilot Chat when you
open the repository in VS Code. It contains the full architectural context:
BaseProvider contracts, provider inventory, cache rules, and strict βnever doβ list.
No setup required. Open the repo, start Copilot Chat with @workspace.
Tessl / Agent Skills Registryο
skills/ai-slop-gate/SKILL.md is published to the
Tessl registry. It allows any AI agent that supports
the Agent Skills spec to automatically load
project context when working in this codebase.
Install locally:
npx tessl install ai-slop-gate
Evaluate or publish:
npx tessl skill review ./skills/ai-slop-gate
npx tessl skill publish ./skills/ai-slop-gate
Claude (claude.ai or API)ο
When starting a new conversation with Claude about this project, paste the contents
of ai_slop_gate_snapshot.json. It is the single source of truth and gives Claude
full architectural context without relying on README or stale memory.
Paste ai_slop_gate_snapshot.json β then describe your task
For multi-session work, re-paste the snapshot at the start of each conversation. Claude has no persistent memory of previous sessions.
General Rules for AI-Assisted Contributionsο
Always provide the snapshot. Without it, any model will guess architecture and invent missing components.
Never accept invented file paths, method names, or SDK methods. Verify against the actual source before committing.
Snapshot update is mandatory. If an AI assistant suggests an architectural change, update
ai_slop_gate_snapshot.jsonas part of the same PR.AI-generated code goes through the gate. Run
--provider staticon your own diff before opening a PR. The project uses ai-slop-gate on itself via.github/workflows/analyze.yml.
Not Acceptedο
βSmartβ decisions without policy
Auto-blocking by default
Tight coupling to a single CI platform
Long LLM essays instead of signals
Business logic inside CLI
Provider-specific cache logic