Context: The era of “VibeCoding” (high-velocity, LLM-assisted development) is here. People are using AI to generate code, and Crystal maintainers are inevitably going to face an influx of AI-generated PRs.
Initially, a few of us tried to design a complex “VibeCoding Protocol” using AST-hashing, mutation testing, and community staging queues to automatically filter this spam. We ran that architecture through an adversarial red-team of advanced LLMs (Claude, ChatGPT, Grok, Kimi) and cybersecurity engineers.
They tore it to shreds. We learned a hard lesson: You cannot automate trust, and you cannot scale contribution throughput when your actual bottleneck is maintainer attention.
Instead of trying to build complex mechanical gates to block AI code, this RFC proposes a lightweight, Crystal-specific methodology to make reviewing AI-assisted code 10x safer and faster for core maintainers, while establishing a strict progression ladder for AI-assisted contributors (VibeEngineers).
The Threat Model We Must Defend Against
- The Macro Bomb: In Crystal, an AI can submit a “harmless doc fix” that shifts line numbers (
__LINE__), triggering a dormant, malicious macro elsewhere in the codebase. - Homoglyph & Payload Smuggling: AI hiding malicious URLs or payloads inside seemingly benign YARD documentation blocks.
- Tautological Testing: An AI generating plausible-looking but flawed logic, and writing tests specifically designed to pass its own broken code.
The Proposal: Automate Transparency, Not Trust
We propose implementing three core defenses for the Crystal ecosystem: one technical, one procedural, and one cultural.
1. The Technical Defense: The Macro X-Ray (GitHub Action)
Because Crystal relies heavily on powerful macros, reviewing the standard Git diff of an AI-generated PR is dangerous. The source code does not always reflect the execution reality.
We propose a standard GitHub Action that runs crystal tool expand on modified files.
- How it works: Whenever a PR is opened, the Action evaluates the macros and generates a “Post-Expansion Diff”.
- The UX: To prevent wall-of-text PR spam, the Action does not dump the raw output. It runs
crystal tool expandon both the base and PR branches, and posts only the semantic diff, folded inside a collapsible<details>Markdown block. - The Benefit: If an AI tries to smuggle a backdoor via a macro injection, or shift a line number to trigger a payload, the Macro X-Ray strips away the obfuscation. The maintainer sees exactly what the compiler sees, completely neutralizing “smart” AI attacks without requiring expensive infrastructure.
2. The Procedural Defense: Asymmetric TDD
We must formally reject the practice of an AI “grading its own homework.” If a PR contains both complex logic changes and the tests that validate them—and both were generated by an LLM—it is impossible to trust the coverage.
We propose updating CONTRIBUTING.md with the Asymmetric TDD Standard:
- Human Intent: The human engineer MUST author the failing test suite to define the invariant.
- AI Implementation: The AI can generate the code to make those tests pass.
- The Refactoring Exemption: If a PR is labeled
kind:refactor, new failing tests are not required. Instead, Commit A must contain a characterization test (or proof of existing 100% coverage for the modified methods) before the AI’s structural changes in Commit B. - Cryptographic Intent (Levels 2 & 3 Only): To prove Commit A was actually written by the human and not just hallucinated by the agent pretending to segregate commits, Commit A MUST be cryptographically signed (GPG/SSH) and display the GitHub “Verified” badge. (Note: Level 1 contributors are exempt from this requirement to reduce initial onboarding friction).
- Enforcement: Reviewers check the git history. If a massive logic block arrives with bundled tests in a single commit, or if a Level 2+ human’s test commit lacks a cryptographic signature, it is treated as hostile and closed.
3. The Cultural Defense: The VibeEngineer Trust Ladder
Vague guidelines like “start small” do not work when a user can generate 5,000 lines of code in seconds. We must replace subjective trust with objective git history.
CONTRIBUTING.md should explicitly outline a 4-tier progression ladder for any PR utilizing AI generation.
- Level 0 (The Janitor): Restricted strictly to YARD documentation, typo fixes, and dead-code removal. Zero logic changes permitted.
- Level 1 (The Apprentice): Unlocked after 3 merged Level 0 PRs. Restricted to writing tests, increasing spec coverage, and isolated refactors. (Target labels:
topic:specs,good first issue,kind:refactor). - Level 2 (The Journeyman): Unlocked after 3 merged Level 1 PRs. Permitted to modify standard library logic, resolve bugs, and add minor features. (Target labels:
topic:stdlib,kind:bug). - Level 3 (Core Architect): Permitted to touch the compiler core, the type-inference engine, and concurrency primitives. Cannot be unlocked via metrics alone; requires sustained Level 2 success AND explicit sponsorship from a Core Maintainer.
The Golden Rules for All Tiers:
- Mechanical Enforcement: To guarantee zero human cycles are spent on triage, this ladder is NOT manually enforced. We implement a lightweight GitHub Action that queries the GraphQL API (
pullRequests(states: MERGED)) on PR open. If a contributor violates their tier (e.g., opens a Level 2 PR with only 1 merged PR), the bot instantly auto-closes it and posts their telemetry: “You submitted a Level 2 PR, but your verified merged PR count is 1/3. PR closed.” - Machine-Readable Governance: Humans don’t read
CONTRIBUTING.md. Machines do. These rules must be encoded into repository-level.github/copilot-instructions.mdand.cursorrulesfiles so the AI is pre-prompted with its constraints before the VibeEngineer generates code. - Total Transparency: Every AI-assisted commit MUST include the
Co-authored-by: Agent <user+agent@domain.tld>trailer to publicly track provenance. - You Own the Hallucinations: You are the author; the AI is your tool. If a PR contains glaring LLM hallucinations, it will be closed, not debugged for you by the core team.
Conclusion
We cannot stop the flood of AI-generated PRs, and trying to build an automated staging queue just shifts the burnout from core devs to community volunteers.
By utilizing Crystal’s native tool expand to build a Macro X-Ray, enforcing Asymmetric TDD via cryptographic signatures, and establishing a GraphQL-enforced Trust Ladder, we don’t try to scale the number of PRs we accept. Instead, we scale the speed and safety at which maintainers can audit them.
Thoughts?