feat(service,features,desktop): the Changes tab names Luke beside the developer whose agent's pull request it is, and says why one was opened as the App

Merged
DA
3d ago
+248-45

Summary

PR 3 of 3, stacked on #2963 (which is stacked on #2952). Covers Dean's decisions 3 and 7: the Changes tab still shows Luke beside the developer, and says why an agent wrote as the App.

  • Co-authors from trailers (pull-requests.ts):
    • The commits read for the people now include each commit's message. A Co-authored-by: … <id+login@users.noreply.github.com> trailer counts that account among the commit authors.
    • The id is GitHub's own, so github-people.ts marks Luke's bot by it as before. A trailer at any other address names no account GitHub would show, and is left out.
    • Result: an agent that wrote as its developer shows "Commits by [developer] [agent]".
  • Why the App (writtenAs): the changes answer carries the agent row's author (from #2952) as an optional writtenAs. Where Luke's bot opened the PR, "Opened by" ends on the reason:
    • "as the GitHub App, since its starter has no GitHub linked"
    • "…can't push here"
    • "…for an automation"
    • "…since GitHub didn't answer"

Evidence

  • pnpm check:affected: exit 0.
  • pnpm exec vitest run packages/service/src/github/github-people.test.ts: 6 passed. New test: a developer-opened PR whose commits name Luke's bot by its noreply address lists the developer and Luke, and drops a co-author at a plain email.
  • pnpm exec vitest run apps/desktop/src/renderer/planning/pull-request-people.test.ts: 9 passed. New test:
    • A developer-opened PR reads "Opened by Charles Pan" with no App note, and commits by Charles Pan and the agent.
    • An App-opened PR with app-unlinked ends on the reason.
  • Goldens re-recorded with LUKE_UPDATE_FIXTURES=1: coding-agent-wire-codingAgentChangesAnswerSchema.json and coding-agent-view-codingAgentChangesAnswerViewSchema.json each gain only the optional writtenAs enum (the five CODING_AGENT_AUTHOR values) beside author. Nothing else moved.
  • The changes route's pass-through of agent.author has no route test; the changes endpoint has none today. The desktop test covers what a reader sees.
  • No capture: a desktop-only text change on the Changes tab's "Opened by" line, which this Linux sandbox can't render on the Mac.

Invariants

  • ./scripts/check.sh green. (CI)
  • JSON Schema goldens changed, explained above (one optional key on the Changes answer).
  • Every behavior change has, in this PR, the test that fails without it; no change-detector test added.
  • Gateway envelope goldens unchanged.
  • No new as type assertion outside the allowlisted files.
  • No Effect.runPromise/runSync/runFork outside the runtime edges.
  • No new raw async primitives.
  • No Effect, Stream, or Layer written as a statement and dropped.
  • Test count: +2.
  • Nothing hand-rolled replaced.
  • Every CLAUDE.md/AGENTS.md sentence naming a changed part is edited (none names it).
  • PRIVACY.md unchanged. Commit messages were already read from GitHub on the Changes tab's token, and none is stored.
  • Package deps match.
  • Barrel/door rule.

🤖 Generated with Claude Code


Open workspace in Conductor


Devin Review


Summary by cubic

The Changes tab now shows Luke's agent beside the developer when a commit co-authors it, and says why a pull request was opened as the App.

Behavior changes

  • A commit's Co-authored-by trailer naming a GitHub noreply address counts that account among the commit authors; only the message's last paragraph is read for trailers, so a trailer-shaped line quoted in the body names nobody.
  • The changes answer now carries writtenAs, and the "Opened by" line ends on the reason when Luke's bot opened the pull request: no linked GitHub, no push access, an automation, GitHub unresponsive, or a failed developer sign-in for an agent writing as it.