Skip to content

feat(hooks): report the pull-request author in lifecycle payloads - #555

Merged
piekstra merged 1 commit into
mainfrom
piekstra/554-hook-payload-author
Aug 7, 2026
Merged

feat(hooks): report the pull-request author in lifecycle payloads#555
piekstra merged 1 commit into
mainfrom
piekstra/554-hook-payload-author

Conversation

@piekstra

@piekstra piekstra commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Closes #554

What

Adds author to the lifecycle hook payload — the pull request author's git-host login (GitHub login, GitLab username) — and the matching CR_AUTHOR environment variable.

Why

Hook payloads identify the pull request only by URL. A notifier that wants to address the person whose PR was reviewed — @-mentioning them in a Slack verdict post, say — has to re-fetch the pull request from the host on every verdict. That is an extra API call per run in a path whose whole contract is that it costs nothing and cannot fail the review.

cr already reads gitprovider.PR.Author on every run, for every provider, before planning. This reports what the run already knows.

How

The author is observed where the pull request is read — the provider progress wrapper, which already wraps both the read and posting providers and already feeds the hook dispatcher elsewhere (withProgressPlanner, newPipelineTaskProgress). No new provider layer, no extra host call, and review, respond, and gate early-exit are covered by the same seam.

Two consequences worth calling out for review:

  • First non-empty login wins. A run reads the pull request more than once; a later read that returns an unauthored snapshot must not erase an identity the hooks already reported.
  • The progress wrapper no longer requires a logger. It now has a second reason to exist, so withProgressProvider returns the bare provider only when there is neither a logger nor an enabled dispatcher, and span creation went nil-safe (p.start). A dispatcher with no configured hooks is still dropped, so the wrapper is not installed for profiles that use neither.

Contract

author is present from the moment the run reads the pull request — every event after run.started — and is omitted when a run fails before that read. Documented in the README hooks section alongside the other common fields.

Deliberately not included: display name, email, avatar, or any chat-handle mapping. One stable host-native identifier is what a consumer keys a mapping on; translating it to a Slack/Teams member ID is the consumer's job.

Verification

  • make lint clean; make test passes except TestPiRPCReviewerExtensionLoadsInInstalledPi, which fails identically on main in this environment (the locally installed pi rejects --no-builtin-tools / --no-approve).
  • TestReviewHooksFanOutFromExistingProgressSeams extended to read the PR through the wrapped provider and assert run.started carries no author while every later event carries it.
  • TestHookAuthorKeepsTheFirstIdentityReadFromTheProvider pins the first-wins rule against a second, unauthored read.
  • TestHookProviderWrapperIsSkippedWhenNoHooksAreConfigured pins that a hookless profile keeps the unwrapped provider.

Hook payloads identified the pull request only by URL, so a notifier that
wanted to address the author had to re-fetch the pull request from the host
on every verdict, in a path that is meant to cost nothing.

Add `author`, the author's git-host login, plus the matching `CR_AUTHOR`
environment variable. The value is observed from the pull-request snapshot
every run already reads, so it costs no extra host call and covers review,
respond, and gate early-exit alike. The first non-empty login wins: a run
reads the pull request repeatedly, and a later unauthored snapshot must not
erase an identity the hooks already reported.

Because the observation rides the provider progress wrapper, that wrapper no
longer requires a progress logger; span creation is now nil-safe so a profile
with hooks and no logger still observes provider calls.

Closes #554
@piekstra
piekstra requested a review from piekstra-dev August 6, 2026 18:23

@piekstra-dev piekstra-dev left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated PR Review

Reviewed commit: fee439d75caf
Profile: reviewer - Posting as: piekstra-dev

Summary

Reviewer Findings
go:implementation-tests 0
policies:conventions 0
documentation:docs 0
structure:repo-health 0

Reviewer Coverage

Reviewer Status Inspected Skipped Constraints
go:implementation-tests complete_broad internal/app/hook_dispatch.go, internal/app/hook_dispatch_test.go, internal/app/provider_progress.go, internal/app/runtime.go, internal/hooks/hooks.go, internal/hooks/hooks_test.go unavailable git diff against the base SHA was unavailable in this environment (git commands were blocked), so review was performed by reading the full current contents of each assigned file and cross-checking against the PR intent/change-map rather than a line-level unified diff.
policies:conventions complete_broad README.md, internal/app/hook_dispatch.go, internal/hooks/hooks.go unavailable No ../cli-common/docs or ../.github convenience copies were present in the workbench, so cross-repo shared standards were checked against repo-local convention only, not the canonical breadcrumb docs.
documentation:docs complete_broad README.md unavailable unavailable
structure:repo-health complete_broad internal/app/hook_dispatch.go, internal/app/provider_progress.go, internal/app/runtime.go unavailable unavailable

0 PR discussion threads considered. 0 summarized; 0 resolved.


Completed in 3m 13s | $2.37 | claude-sonnet-5 | cr 0.10.268
Field Value
Model claude-sonnet-5
Reviewers go:implementation-tests, policies:conventions, documentation:docs, structure:repo-health
Engine claude_cli · claude-sonnet-5
Reviewed by cr · piekstra-dev
Duration 3m 13s wall · 6m 31s compute
Cost $2.37
Tokens 140 in / 24.4k out

Per-workstream usage

Workstream Model In Out Cache read Cache create Cost Duration
orchestrator-selection claude-sonnet-5 6 2.1k 37.7k 24.0k $0.19 30s
go:implementation-tests claude-sonnet-5 50 9.6k 862.5k 57.4k $0.75 2m 19s
policies:conventions claude-sonnet-5 28 3.8k 401.8k 22.7k $0.31 57s
documentation:docs claude-sonnet-5 22 3.0k 289.1k 34.5k $0.34 56s
structure:repo-health claude-sonnet-5 28 5.5k 564.9k 67.2k $0.66 1m 33s
orchestrator-rollup claude-sonnet-5 6 374 60.8k 16.8k $0.12 13s

@piekstra piekstra closed this Aug 7, 2026
@piekstra piekstra reopened this Aug 7, 2026
@piekstra
piekstra marked this pull request as ready for review August 7, 2026 00:11
@piekstra
piekstra merged commit 9ebb8ad into main Aug 7, 2026
10 of 20 checks passed
@piekstra
piekstra deleted the piekstra/554-hook-payload-author branch August 7, 2026 10:43
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.

hooks: report the pull-request author in the lifecycle payload

2 participants