Skip to content

The pull request is the subject, not the input - #135

Merged
czpython merged 1 commit into
mainfrom
eng-778-pull-request-is-the-subject
Jul 28, 2026
Merged

The pull request is the subject, not the input#135
czpython merged 1 commit into
mainfrom
eng-778-pull-request-is-the-subject

Conversation

@czpython

Copy link
Copy Markdown
Owner

Starting a review wrote the same facts twice:

return await cls.start(
    subject=Subject(id=f"{repo}#{pr_number}", subject_type=Review.subject_type),
    account_id=account.id if account else None,
    repo=repo,
    pr_number=pr_number,
    requested_by=requested_by,
)

repo and pr_number were both the subject and the run input. Now that PullRequest is a subject class that knows its own repo and number, the input goes — there is no new SDK surface, no derived-subject mode, no way to omit subject=.

class PullRequestReview(Workflow):
    subject = PullRequest

    @classmethod
    async def dispatch(cls, *, repo: str, pr_number: int, requested_by: str) -> str:
        account = Account.get_for_username(requested_by)
        return await cls.start(
            subject=PullRequest.get_for(repo, pr_number),
            account_id=account.id if account else None,
            requested_by=requested_by,
        )

    async def run(self, requested_by: str) -> None:
        ...

get_workspace_kwargs(), get_prompt_context() and the reviewer's prompt read self.subject.repo and self.subject.number. The body keeps requested_by — that one is the request's own, not the pull request's.

The launch contract is unchanged: every domain run passes subject=, background work passes subject=None, and losing a timeline by accident still fails loudly.

A review already queued carries the old pair in its durable payload. Extra keys are ignored on re-validation and the subject rides separately, so it replays through the declaration — pinned by a test that binds an old payload.

The argument against: future row-less workflows repeat a small dispatcher pattern. A generic hook is worse — get_subject(**input) would receive every body field including requested_by, there is no bound workflow instance before enqueue, and it needs signature reflection for one consumer.

@czpython
czpython force-pushed the eng-777-subject-is-a-class branch 4 times, most recently from 60e8fc6 to 764508d Compare July 28, 2026 05:52
Base automatically changed from eng-777-subject-is-a-class to main July 28, 2026 06:02
Starting a review wrote the same two facts twice: once as the subject
identity and once as run input. The subject class knows its own repo and
number, so the input goes — `run()` takes only what the request itself
knows, and `get_workspace_kwargs()`, `get_prompt_context()` and the
reviewer's prompt read the pull request off `self.subject`.

A review already queued carries the old pair in its durable payload;
extra keys are ignored and the subject rides separately, so it replays
through the declaration.
@czpython
czpython force-pushed the eng-778-pull-request-is-the-subject branch from 955cc8c to 58ef828 Compare July 28, 2026 06:13
@czpython
czpython merged commit 0bc0803 into main Jul 28, 2026
1 check passed
@czpython
czpython deleted the eng-778-pull-request-is-the-subject branch July 28, 2026 06:37
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