Skip to content

ci(contribution): block AI-attribution footers in PR body - #91

Merged
ai-hpc merged 1 commit into
mainfrom
ci/block-ai-attribution-footer
May 18, 2026
Merged

ci(contribution): block AI-attribution footers in PR body#91
ai-hpc merged 1 commit into
mainfrom
ci/block-ai-attribution-footer

Conversation

@ai-hpc

@ai-hpc ai-hpc commented May 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a check to the Contribution / PR body checklist workflow that fails when the PR body contains the Claude Code default attribution footer (the line that starts with the robot emoji and the words Generated-then-with-then-Claude Code). Same spirit as the existing CONTRIBUTING.md commit-trailer rule (no Co-Authored-By: Claude on 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 against Generated[[: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

  • I have built and run the affected code locally (or noted why I could not).
  • I have verified the change end-to-end on Jetson hardware OR explained the equivalent verification path I used.

What I ran

bash -n .github/workflows/contribution.yml      # syntax clean
bash /tmp/test-checklist-v2.sh                  # 7-case test matrix

Test matrix targets:

# Input shape Expected
T1 Valid body, no AI footer PASS
T2 Valid body + footer with the robot emoji and the bare phrase FAIL
T3 Valid body + the bracketed-link form [Claude Code](https://...) FAIL
T4 Valid body + lowercased variant FAIL
T5 Valid body + footer with extra spacing between tokens FAIL
T6 Valid body, casual mention of the tool name in prose without the Generated-with lead PASS
T7 Dependabot-titled PR body with the footer FAIL (norm applies universally)

What 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 + Code lead-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 on pull_request_target and 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: FAILURE with a clear error message pointing at CONTRIBUTING.md and 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

  • Universality of the rule: the new check fires before the bot-title exemption (Dependabot / release PRs). The reasoning: those bots don't include AI attribution footers in practice, but if they ever did, we'd still want to catch it — the rule is about project history hygiene, not about who/what authored.
  • False-positive surface: a contributor writing "I used Claude Code to draft this PR" in their prose is fine. A contributor pasting the actual footer trailer is not. The regex requires the specific Generated+with+Claude+Code sequence with whitespace between, so prose discussion is safe.
  • No Cargo.toml / runtime change — this PR only touches .github/, CONTRIBUTING.md, and CHANGELOG.md. The existing 5 CI checks (fmt / clippy / test / aarch64 / no-default-features) should all pass unchanged.

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.
@ai-hpc
ai-hpc merged commit 6158951 into main May 18, 2026
6 checks passed
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`.
@ai-hpc
ai-hpc deleted the ci/block-ai-attribution-footer branch May 28, 2026 04:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant