---
title: How work arrives
description: The six surfaces that hand work to Foreman, what each one trusts, and what each one triggers.
type: guide
summary: The factory label, @mentions, Linear Agent Sessions, red CI, PR summary comments, and the dev TUI.
related:
  - /docs/pipeline
  - /docs/trust-model
  - /docs/troubleshooting
---

# How work arrives



Work reaches Foreman through six surfaces.

Each one decides at dispatch time, from the signed webhook payload, who the caller is and how much the run is trusted. Nothing downstream re-derives trust from content the model can read.

The GitHub surfaces live in `agent/channels/github.ts`, Linear in `agent/channels/linear.ts`, and the dev TUI's auth in `agent/channels/eve.ts`. Terms like principal, trusted, and parks are defined in the [glossary](/docs/glossary).

| Surface                    | Hook                                                     | Trust                                      | What runs                               |
| -------------------------- | -------------------------------------------------------- | ------------------------------------------ | --------------------------------------- |
| Issue labeled `factory`    | `onIssue` (`labeled` action, labeler verified)           | Autonomous principal, intake issue stamped | Full pipeline, unattended               |
| `@Foreman` mention         | `onComment` (mention + association gate)                 | Trusted                                    | Conversational, whatever was asked      |
| Linear Agent Session       | `onAgentSession` (`created`/`prompted`)                  | Trusted (workspace membership)             | Conversational, whatever was asked      |
| Red CI on a `factory/*` PR | `onCheckSuite` (`completed` + `failure` + branch prefix) | Autonomous, anchored to the PR             | CI fix loop, capped at 2 attempts       |
| PR opened by a human       | `onPullRequest` (`opened`, bots skipped)                 | Untrusted (no stamp)                       | One orienting summary comment           |
| Dev TUI                    | `agent/channels/eve.ts`                                  | Untrusted local user                       | Anything, writes park on approval cards |

## The factory label

The label is the unattended entry point. Adding `factory` to an issue, configurable through `FACTORY_LABEL`, hands it to the full [pipeline](/docs/pipeline) with nobody watching.

The channel rewrites the session's auth to the autonomous principal and stamps in the intake issue number, so the run is unattended by construction rather than by convention. The injected task tells the run that nobody is watching: never ask a question, never attempt an action that needs approval.

Expect progress on the issue itself. Foreman posts a short comment as each station completes, except the last, where the final reply links the draft pull request. If the Classifier needs clarification, the run posts its questions and stops, and you re-label once you have answered. Comments on that one issue are the only conversational write an unattended run has.

### Why the labeler gets verified

The hook dispatches only on the `labeled` action, and only after checking who applied it. That check exists for a subtle reason.

The issues webhook carries the issue author's association, never the labeler's. GitHub also fires `labeled` for labels attached at issue creation, which issue templates let unauthenticated reporters do. Without a check, anyone on a public repository could start an unattended run by opening an issue from a template that pre-applies the label.

So `isTrustedLabeler` asks the GitHub API for the sender's collaborator permission and requires at least `triage`, the permission normally needed to apply a label by hand. It fails closed, acknowledging the event without a session on any API error, and bot senders are skipped outright.

## @mentions

Mentioning the bot by name on an issue or pull request comment starts an attended, conversational session. Foreman does whatever you asked, with a person watching.

The name resolves from the GitHub App's own slug, falling back to `Foreman`, so the mention follows whatever you named your app.

`onComment` gates on the commenter's `author_association`. Only `OWNER`, `MEMBER`, and `COLLABORATOR` dispatch, and those sessions are stamped trusted, which is what lets reversible writes run without approval cards. Everyone else is acknowledged without a session, so arbitrary accounts on a public repository cannot drive the agent's write tools.

The hook also ignores comments that should never dispatch: eve's own marker comments, any author whose type is `Bot`, and the agent's own `<botname>[bot]` login.

That association gate does double duty. When a session parks on approval, the channel posts the request as a comment with a mention-based reply instruction, and the answer re-enters through this same gate. An untrusted "approve" never reaches the waiting session.

## Linear Agent Sessions

Foreman registers as a Linear agent, so assigning it an issue or mentioning it opens an Agent Session. The hook dispatches on the `created` and `prompted` actions.

Every session is stamped trusted, because workspace membership is the gate. Only members of your Linear workspace can open an Agent Session in the first place, so there is no association left to check.

When Linear provides the requester's name, the channel injects it as session context for attribution in progress notes and reports. Progress renders natively as Agent Activities, and so do questions back to the user. Credentials are brokered by Vercel Connect, which supplies the app token and verifies inbound webhooks.

## Red CI on factory PRs

This surface repairs the factory's own pull requests when their checks go red. When a check suite completes with a `failure` conclusion on a pull request whose head branch starts with `FACTORY_BRANCH_PREFIX`, default `factory/`, the hook dispatches an unattended fix run anchored to that pull request.

The branch-prefix gate is the whole scope, pull requests humans authored are not touched.

The fix loop is deliberately bounded and crash-safe:

<Steps>
  <Step>
    ### Re-read the current state

    The run re-reads the pull request and its check runs fresh. If the checks are green by now, or the failure belongs to a commit that is no longer the branch head, it stops without posting anything.
  </Step>

  <Step>
    ### Count previous attempts

    It counts its own earlier fix-attempt comments on the pull request. Each dispatch is a fresh session with no memory of the last one, so the thread is the only durable record those runs share. At two attempts it posts one comment saying the factory is pausing to avoid looping, and stops.
  </Step>

  <Step>
    ### Post before fixing, not after

    It posts a short comment that a fix attempt is starting and what looks broken. Posting first matters: a run that dies mid-fix still leaves its mark for the next run to count, so a crash cannot turn the cap into an infinite loop.
  </Step>

  <Step>
    ### Diagnose and revise

    It diagnoses with `github__getCiFailureContext`, then runs the fix as a revision through the Implementer and Reviewer, pushing to the same branch. Pushing re-runs the checks. It never opens a new pull request.
  </Step>
</Steps>

<Callout title="Webhook subscription required">
  This surface only fires if the GitHub connector subscribes to the `check_suite` webhook event.
</Callout>

## PR summary comments

When anyone opens a pull request, Foreman posts one orienting comment for reviewers. Expect a short paragraph on what the pull request does and why, grounded in its title, description, and diff, then a table of the changed files, then one closing line pointing reviewers at where to start.

The comment stays a summary rather than a review. The injected task forbids approving, requesting changes, or asking the author for anything.

Two design choices shape this surface. Bot senders are skipped, which covers Dependabot and the factory's own pull requests. And the hook is deliberately not gated by `author_association`, because summarizing outside contributors' pull requests is the point. The session carries no trusted stamp, so anything beyond that one comment would park.

To turn the feature off, remove the `onPullRequest` hook from `agent/channels/github.ts`.

## The dev TUI

Running `pnpm dev` opens eve's local TUI, where you hand Foreman a work item directly. The route is authenticated by `agent/channels/eve.ts`, where a local dev shim upgrades the principal so the user-preference tools work, while `vercelOidc()` keeps public browser traffic out.

The dev principal is deliberately untrusted. Every GitHub write parks on an approval card, which makes local development a live demo of the human gate: you see exactly which actions Foreman would have taken and approve or deny each one.

The webhook surfaces above only fire against a deployment. See [getting started](/docs/getting-started) for wiring them up.

## Next steps

<Cards>
  <Card href="/docs/pipeline" title="The pipeline" description="What happens to a work item once it is in." />

  <Card href="/docs/trust-model" title="Trust model" description="The caller classes these surfaces stamp, and the policies that read them." />

  <Card href="/docs/troubleshooting" title="Troubleshooting" description="What to check when a label, mention, or CI failure does nothing." />
</Cards>


---

For a semantic overview of all documentation, see [/sitemap.md](/sitemap.md)

For an index of all available documentation, see [/llms.txt](/llms.txt)

For agent-facing discovery, including API and MCP surfaces, see [/agents.md](/agents.md)