Skip to content

Stories should cover pull requests, not just issues #65

Description

@javiertoledo

A story is meant to be the whole life of a unit of work — issue, agent runs, human gates, PRs, the GitHub conversation — folded into one chronological timeline (apps/web/lib/story.ts:13-17). Today it cannot be, because Facility never mirrors pull requests.

services/api/src/github/issues-sync.ts drops them at all three entry points — GitHub's REST issues endpoints return PRs alongside issues, and we filter them out:

if (!owner || !name || !issue?.number || issue.pull_request) return null;  // :55  webhook
if (!owner || !name || !issueNumber || payload.issue?.pull_request) return null;  // :69  comments
if (issue.pull_request) continue;  // :133 backfill

There is no PR table. A PR is known only derivatively: in runs.gh.pr when a Facility builder opened it, and in outcomes once it has closed. A pull request opened directly on GitHub is invisible to Facility — it is not on the board, not in a story, and not in any count.

Three consequences follow from that one gap:

  1. CI state never reaches a story. The App already holds Actions: read and Checks: read and subscribes to check_run and workflow_run, but those events go to processOperationalSignal (services/api/src/github/processor.ts:752), which raises repo-level watchtower issues. processWorkflowRun (:450) acts only when the workflow is named facility-* and the conclusion is failure. The repository's own CI never touches pipeline state, and the Checks and Commit Statuses APIs are never called.
  2. PR↔issue relationships are not read. GitHub resolves Closes #123 itself and exposes the result as closingIssuesReferences. We already run that query — in services/api/src/watchtower/github.ts:111-161, but on a bare GITHUB_TOKEN client (:52-54) and only during the nightly outcomes reconciliation, far too late for a live board.
  3. The board cannot distinguish "a machine is still checking this" from "a human should review this". Everything with a PR sits in In review.

What this epic proposes

Make pull requests first-class in the mirror, and let what happens to them move a story.

The product rule these are designed against: an issue is a story, and every PR associated with that issue is part of the same story. A pull request with no associated issue is its own story. A story is the complete implementation history from the issue to the close, and everything in between.

Sub-issues

The foundation

What that makes possible

Prerequisites and cleanup surfaced along the way

Each sub-issue stands on its own and states the alternatives considered, so they can be argued with — or dropped — individually. #70 and #72 are independent of the rest and could land first.

Not proposed here

  • Publishing Facility's own checks back to GitHub via the Commit Statuses API, so branch protection could gate on them. It is the natural counterpart to reading CI, but it is a separate piece of work.
  • Cross-repository closing references (Closes owner/other#5).

Findings are against 0f646ac. Line references are to that commit.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesttype:epicEpic — long-running outcome with sub-issues

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions