Add branding assets and PR lifecycle agent prompt#2
Conversation
Add Dev role branding logos (40px, 128px, 256px) and the PR lifecycle agent template used to manage CI transitions, Codecov checks, label automation, and sequential PR queue rebasing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
cmeans
left a comment
There was a problem hiding this comment.
QA Review — PR #2 (cmeans/claude-dev)
Informal review — this repo doesn't have the QA workflow, so no labels.
Branding (3 logos)
All three PNGs render correctly on GitHub. Code brackets on a shield, dark background with cyan accent. Clean design.
- 256px — crisp, all details sharp ✓
- 128px — clean at display size ✓
- 40px — legible, brackets still recognizable at favicon/badge size ✓
PR Lifecycle Agent Prompt
Well-structured 4-phase template. A few observations:
Strengths:
- Phase 1 CI polling correctly excludes QA Gate from the "pending" check — smart, since QA Gate stays pending until QA Approved
- "Do NOT use
gh pr checks --watch" — good warning, that would block forever - Phase 2 Codecov comment check (not just status) — catches the common trap of "codecov passed but patch coverage has gaps"
- Phase 4 rebase uses
--force-with-lease— safe force push ✓ - "Important" rules are exactly right: never merge, never fix failures, never skip codecov detail, report-and-stop on unexpected
Observations (not blockers — this is a personal tools repo):
-
Phase 4 assumes a local clone exists.
git checkout {{NEXT_BRANCH}}won't work if the agent was dispatched in a clean environment. Could add agit fetch origin {{NEXT_BRANCH}}before checkout, or note "assumes worktree context" in the docs. -
{{#if NEXT_PR}}/{{/if}}Handlebars syntax won't be evaluated — the user manually pastes the template. Consider a note like "Remove Phase 4 if no NEXT_PR" or split into two templates (single PR vs queued). -
notify-send+paplayare Linux-specific. Fine for your setup, but if you ever share this prompt, a note about platform would help. -
Phase 1 step 2 edge case: If checks haven't started yet (e.g., GitHub is slow), the grep returns empty — same as "all passed." Could add a "checks found" guard: if
gh pr checksreturns no lines at all, wait before declaring success.
None of these are blockers — the template is practical and well-thought-out. It automates exactly the tedious parts of the PR lifecycle while keeping the human/QA in the loop for decisions.
Verdict
Looks good. Ship it.
- Add checks-exist guard before declaring CI passed (prevents false
positive when checks haven't started yet)
- Remove Handlebars {{#if}} syntax; note to remove Phase 4 manually
when no NEXT_PR is provided
- Add git fetch for NEXT_BRANCH and note that Phase 4 assumes a local
clone with the branch available
- Add platform notes section for notify-send/paplay alternatives
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary Replaces the v1 bot-push design (env-var GIT_CONFIG_* matrix + \`git\` shell-function wrapper + manual \`bot-git-push.sh\` invocation) with a curated bot git config loaded via \`GIT_CONFIG_GLOBAL\`. After this lands, plain \`git push\` from any subprocess in an activated bot session attributes the PushEvent to \`cmeans-claude-dev[bot]\` — no wrapper to remember. Surfaced by mcp-awareness PR #396 on 2026-04-24, where the v1 design's env-var fight against \`~/.gitconfig\` lost in a Bash subprocess and the push attributed to \`cmeans\`, blocking merge under \`require_last_push_approval\`. ## Why GIT_CONFIG_GLOBAL swap Three options were considered (full analysis in awareness \`bot-push-attribution-options-2026-04-24\`): 1. **Per-clone HTTPS \`origin\` URL.** Doesn't actually work in this repo's setup — Chris's global \`~/.gitconfig\` has \`url.git@github.com:.insteadOf=https://github.com/\` which rewrites every HTTPS URL back to SSH for *every* git invocation, regardless of who's running it. Per-clone change can't override a global insteadOf. 2. **Debug v1's env-var \`pushInsteadOf\`.** Empirically loses to global insteadOf in subprocesses despite documented precedence. Unknown debugging depth. 3. **\`git\` binary shim in \`~/.local/bin\`.** Universal but invasive — intercepts every git command, surprising failure modes, hard to reason about. The chosen mechanism is more durable than any of those: don't fight the global config — replace it for the duration of the bot session via \`GIT_CONFIG_GLOBAL\`. Subprocess-safe (env vars inherit). Per-role isolated (a non-activated shell doesn't see it, so QA / human sessions in the same clone push as the human normally). ## What's in the new bot config Built from scratch (not filtered from \`~/.gitconfig\`) so the diff against intent is readable and immune to drift: - \`[user]\` — \`BOT_USER_ID\`-prefixed bot email (\`272174644+cmeans-claude-dev[bot]@users.noreply.github.com\`) - \`[commit/tag/push] gpgSign = false\` — insulates against future user-side gpgSign defaults - \`[init] defaultBranch = main\` - \`[url \"https://github.com/\"] pushInsteadOf = git@github.com:\` — forces SSH→HTTPS for push regardless of \`origin\` URL - \`[credential \"https://github.com\"]\` — list reset (no \`store\` inheritance) + \`git-credential-bot-token.sh\` ## Why a template + render rather than a static file Git's \`credential.helper\` does NOT expand \`~\` in path values — the helper script must be referenced by absolute path. To stay portable across clone locations without hardcoding \`/home/cmeans/...\`, \`activate.sh\` substitutes \`__SCRIPT_DIR__\` at activation time and writes the rendered config to \`github-app/.git-global.config\` (gitignored). Source of truth is the \`.template\` file. ## Inventory of \`~/.gitconfig\` (decisions reviewable) Ran before drafting to confirm what gets left behind by going from-scratch: \`\`\` file:/home/cmeans/.gitconfig user.name=Chris Means file:/home/cmeans/.gitconfig user.email=chris.a.means@gmail.com file:/home/cmeans/.gitconfig credential.helper=store file:/home/cmeans/.gitconfig init.defaultbranch=main file:/home/cmeans/.gitconfig url.git@github.com:.insteadof=https://github.com/ \`\`\` No \`~/.config/git/config\`. No \`/etc/gitconfig\`. No \`[include]\` / \`[includeIf]\`. No signing config. No \`core.sshCommand\` / \`core.hooksPath\` / \`init.templatedir\`. No other URL rewrites. What's left behind by going from-scratch (deliberate): - \`user.name=Chris Means\` / \`user.email=chris.a.means@gmail.com\` — replaced with bot identity (the whole point). - \`credential.helper=store\` — replaced with bot helper. Inheriting it would silently auth as Chris via \`~/.git-credentials\` (CD's #2). - \`url.git@github.com:.insteadof=https://github.com/\` — deliberately omitted (the rule we're fighting). - \`init.defaultBranch=main\` — kept (re-set in the bot config explicitly). ## Belt-and-suspenders fallback \`bot-git-push.sh\` is kept in this PR as a fallback for v1. The new \`activate.sh\` does NOT define a \`git push\` wrapper, so the script is only used if invoked manually (\`bash bot-git-push.sh push origin <branch>\`). After this design carries real PR traffic for a few cycles and we're confident, a follow-up cleanup PR removes it. The corresponding awareness entry (\`bot-push-via-helper\`) and feedback memory will be tightened to: **\"Use ONLY if a push is attributing to \`cmeans\` from an activated session — that indicates a bug in activate.sh, file an issue, then use this script as a one-shot to unblock. Do not use this script as a default workflow.\"** That signal is what keeps the new design from eroding through soft fallback. ## Hygiene cleanup This PR also brings two scripts into source control that have been driving real bot pushes from the working tree since 2026-04-22 but were never PR'd to this repo: - \`bot-git-push.sh\` (now belt-and-suspenders fallback) - \`git-credential-bot-token.sh\` (referenced from the new bot config) Closes the \"main is ~2 weeks stale relative to disk\" gap. ## Verification Three checks ran during development; all pass: **(a) Format test — \`[bot]\` brackets render correctly.** This commit's identity: \`\`\` author: cmeans-claude-dev[bot] <272174644+cmeans-claude-dev[bot]@users.noreply.github.com> committer: cmeans-claude-dev[bot] <272174644+cmeans-claude-dev[bot]@users.noreply.github.com> \`\`\` GitHub UI rendering visible on the commit page after merge. **(b) Sequential test — push attribution differs per role.** - Activated session: this branch's \`CreateEvent\` reports \`actor.login: cmeans-claude-dev[bot]\` (verified via \`gh api repos/cmeans/claude-dev/events\` immediately after push). - Non-activated session in the same clone: \`git config user.email\` returns \`chris.a.means@gmail.com\`, \`git config --get url.git@github.com:.insteadOf\` returns Chris's rule. Same \`.git/config\`, two identities. **(c) Concurrent test — proven by construction.** \`GIT_CONFIG_GLOBAL\` is an environment variable; environment is per-process. Two terminals on the same machine, one activated and one not, cannot interfere with each other. Manual verification (two-terminal simultaneous push) recommended once before relying on this for production traffic; happy to run it post-merge. ## Test plan - [ ] Merge, then start a fresh Dev session and confirm \`source github-app/activate.sh\` reports the rendered config path - [ ] Confirm \`git config --list --show-origin\` in an activated session shows the rendered \`.git-global.config\` only (no \`~/.gitconfig\` entries, no \`command line:\` matrix entries) - [ ] Confirm a real bot push to a test branch in this repo (or the next mcp-awareness feature PR) shows up over HTTPS in the \`git push\` output and \`actor.login: cmeans-claude-dev[bot]\` in events - [ ] Confirm a non-activated terminal in the same clone still pushes as \`cmeans\` over SSH (one-time sanity check; per-process env isolation should make this trivially correct) - [ ] One concurrent-session test: two terminals (one activated, one not), simultaneous pushes to different branches, confirm \`actor.login\` differs correctly per push 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: cmeans-claude-dev[bot] <272174644+cmeans-claude-dev[bot]@users.noreply.github.com> Co-authored-by: Chris Means <chris.a.means@gmail.com>
Summary
branding/prompts/pr-lifecycle-agent.md-- a dispatch template for managing the full PR lifecycle (CI polling, Codecov detail checks, label transitions, sequential queue rebasing)Test plan
🤖 Generated with Claude Code