ci(contribution): block AI-attribution footers in PR body - #91
Merged
Conversation
Adds a check to the PR body checklist workflow that fails when the body contains the Claude Code default attribution footer (case- insensitive, matches both the plain and bracketed-link forms). Same spirit as the existing CONTRIBUTING.md commit-trailer rule (no `Co-Authored-By: Claude`): attribution stays with the human contributor in both git history and the PR description. The rule applies universally — the check fires before the bot-title exemption so the norm holds regardless of who/what authored the PR. A casual mention of "Claude Code" in prose (without the preceding "Generated with") is allowed; we only block the literal footer. Regex: case-insensitive `Generated[[:space:]]+with[[:space:]]+\[?Claude[[:space:]]+Code\]?`. Verified locally against 7 representative inputs covering the literal footer, the bracketed-link form, lowercased variants, multi-space spacing, and the false-positive case where a contributor mentions Claude Code casually in prose.
This was referenced May 18, 2026
hunnyboy1217
added a commit
to hunnyboy1217/genie-claw
that referenced
this pull request
May 19, 2026
…iePod#21) Re-submission against current `main` per review feedback on the prior revision. Drops the `.github/workflows/ci.yml` rewrite that conflicted with the CI evolution landed across PRs GeniePod#37 / GeniePod#62 / GeniePod#89 / GeniePod#91, drops the macOS matrix axis (Jetson is the deployment target), and drops the coverage job (worth its own PR). Keeps the high-value content: - `voice_loop::process_transcript` — extracted from `voice_cycle` so the post-record orchestration (intent gate, speaker identity, memory recall, quick-tool fast path, LLM streaming + TTS, tool dispatch, conversation persistence, latency banner, memory extract) can be driven with mocks. `ProcessTranscriptInputs` carries `wav_path: Option<&str>` and `tts_engine_override: Option<&TtsEngine>` so tests pass `None` / `Some(&silent_tts)` without leaking test-only ceremony into production. `voice_cycle` is now a thin wrapper around the audio-bound prelude + delegation. - `TtsEngine::snapshot()` — config-only copy so a borrowed `&TtsEngine` can be wrapped in `Arc<TtsEngine>` for `streaming::stream_and_speak`, which is `Arc`-typed since PR GeniePod#61. - `MockLlmBackend` (`LlmClient::mock(replies)`), `SttEngine::mock(transcripts)` + `MockTranscript`, `TtsEngine::silent()` — the test doubles the integration test needs. All three drop into the existing public surface. - `crates/genie-core/tests/voice_loop_integration.rs` — ten `#[tokio::test]` cases. The canonical case `process_transcript_drives_full_voice_cycle_with_mocks` calls `process_transcript` with mock LLM (tool-call reply then summary reply), silent TTS, real `Memory`, real `ConversationStore`, and a `ToolDispatcher` wired to a tool-audit JSONL, then asserts on the three AC-B observables. - `crates/genie-core/src/memory/mod.rs` — every test gets its own `${tmpdir}/geniepod-mem-${label}-${pid}-${id}-${nanos}/` parent dir so `Memory::open`'s `canonical_dir = path.parent().join("memory")` derivation no longer collides under parallel execution. Fixes the `promotion_redacts_person_memory_in_namespace_note` flake. - `crates/genie-core/src/tools/parser.rs` — the `try_tool_call_executes_single_key_system_info_shape` test is now `#[cfg(target_os = "linux")]` because the assertion shape (`Memory available:`) only renders on Linux where `tegrastats::mem_available_mb()` can read `/proc/meminfo`.
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
Adds a check to the
Contribution / PR body checklistworkflow that fails when the PR body contains the Claude Code default attribution footer (the line that starts with the robot emoji and the wordsGenerated-then-with-then-Claude Code). Same spirit as the existingCONTRIBUTING.mdcommit-trailer rule (noCo-Authored-By: Claudeon commits): attribution stays with the human contributor in both git history and the PR description.Changes
.github/workflows/contribution.yml— adds the regex-based check after the empty-body guard and before the bot-title exemption, so the rule applies universally. Case-insensitive match againstGenerated[[:space:]]+with[[:space:]]+\[?Claude[[:space:]]+Code\]?— catches both the plain form and the bracketed-link form ([Claude Code](https://...)) the Claude Code template emits..github/PULL_REQUEST_TEMPLATE.md— adds a one-paragraph note in the leading HTML comment warning contributors to strip the trailer before submitting.CONTRIBUTING.md— adds a new "Commit hygiene" bullet covering the PR-body rule alongside the existing commit-trailer rule.CHANGELOG.md— extends the existing Unreleased entry.Real Behavior Proof
What I ran
Test matrix targets:
[Claude Code](https://...)Generated-withleadWhat I observed
All 7 verdicts match the expected column. The false-positive case (T6, casual prose mention) correctly passes — the regex requires the literal
Generated+ whitespace +with+ whitespace +Claude+ whitespace +Codelead-in, so contributors can still discuss the tool by name in their writeup.A note on this PR's own body: I deliberately avoided typing the literal forbidden phrase anywhere in this description, which is why I refer to it via "the robot emoji and the words
Generated-then-with-then-Claude Code" instead. If the PR body checklist had been onpull_request_targetand I had pasted the literal phrase, this PR would have rejected itself — which is the correct behavior, just inconvenient for the PR that introduces the rule.Test plan
After merge, the next PR body that includes the literal Claude-Code attribution trailer will see
PR body checklist: FAILUREwith a clear error message pointing atCONTRIBUTING.mdand asking the contributor to strip the trailer. Existing open PRs (#78 / #83 / #87 / #61 / #48) are unaffected unless their body is edited to add the trailer.Notes for reviewers
Generated+with+Claude+Codesequence with whitespace between, so prose discussion is safe.Cargo.toml/ runtime change — this PR only touches.github/,CONTRIBUTING.md, andCHANGELOG.md. The existing 5 CI checks (fmt / clippy / test / aarch64 / no-default-features) should all pass unchanged.