@open-everywhere/provider-github 0.7.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent/app-manifest.ts +237 -0
- package/agent/channels/github-catch-up.ts +2 -2
- package/agent/channels/github-event-reach.ts +15 -0
- package/agent/channels/github-installations.ts +4 -2
- package/agent/channels/github-post-arm.ts +6 -0
- package/agent/channels/github-reaction-scope.ts +1 -1
- package/agent/channels/github-read.ts +11 -8
- package/agent/channels/github-supervisor.ts +2 -1
- package/agent/channels/github.ts +13 -2
- package/agent/docs-generated.ts +392 -2
- package/agent/ops.ts +7 -2
- package/agent/register.ts +6 -0
- package/agent/surface-parity.ts +1 -0
- package/dist/agent/app-manifest.d.ts +41 -0
- package/dist/agent/app-manifest.d.ts.map +1 -0
- package/dist/agent/app-manifest.js +197 -0
- package/dist/agent/app-manifest.js.map +1 -0
- package/dist/agent/channels/github-catch-up.js +2 -2
- package/dist/agent/channels/github-catch-up.js.map +1 -1
- package/dist/agent/channels/github-event-reach.d.ts +3 -0
- package/dist/agent/channels/github-event-reach.d.ts.map +1 -0
- package/dist/agent/channels/github-event-reach.js +14 -0
- package/dist/agent/channels/github-event-reach.js.map +1 -0
- package/dist/agent/channels/github-installations.d.ts +2 -1
- package/dist/agent/channels/github-installations.d.ts.map +1 -1
- package/dist/agent/channels/github-installations.js.map +1 -1
- package/dist/agent/channels/github-post-arm.d.ts.map +1 -1
- package/dist/agent/channels/github-post-arm.js +6 -1
- package/dist/agent/channels/github-post-arm.js.map +1 -1
- package/dist/agent/channels/github-reaction-scope.d.ts +0 -7
- package/dist/agent/channels/github-reaction-scope.d.ts.map +1 -1
- package/dist/agent/channels/github-reaction-scope.js +1 -1
- package/dist/agent/channels/github-reaction-scope.js.map +1 -1
- package/dist/agent/channels/github-read.d.ts.map +1 -1
- package/dist/agent/channels/github-read.js +11 -8
- package/dist/agent/channels/github-read.js.map +1 -1
- package/dist/agent/channels/github-supervisor.d.ts +2 -1
- package/dist/agent/channels/github-supervisor.d.ts.map +1 -1
- package/dist/agent/channels/github-supervisor.js.map +1 -1
- package/dist/agent/channels/github.d.ts.map +1 -1
- package/dist/agent/channels/github.js +13 -2
- package/dist/agent/channels/github.js.map +1 -1
- package/dist/agent/docs-generated.d.ts.map +1 -1
- package/dist/agent/docs-generated.js +392 -2
- package/dist/agent/docs-generated.js.map +1 -1
- package/dist/agent/ops.d.ts +1 -1
- package/dist/agent/ops.d.ts.map +1 -1
- package/dist/agent/ops.js +7 -2
- package/dist/agent/ops.js.map +1 -1
- package/dist/agent/register.d.ts.map +1 -1
- package/dist/agent/register.js +6 -1
- package/dist/agent/register.js.map +1 -1
- package/dist/agent/surface-parity.d.ts.map +1 -1
- package/dist/agent/surface-parity.js +1 -0
- package/dist/agent/surface-parity.js.map +1 -1
- package/package.json +11 -2
|
@@ -4,10 +4,400 @@
|
|
|
4
4
|
// manual is compiled in at all (docs/ does not exist on disk in a hosted deployment).
|
|
5
5
|
export const PROVIDER_DOCS = [
|
|
6
6
|
{
|
|
7
|
-
path: "docs/deploy/surfaces/github.md",
|
|
8
7
|
title: "GitHub",
|
|
8
|
+
path: "docs/deploy/surfaces/github.md",
|
|
9
9
|
summary: "Install Open Everywhere's GitHub App on a repo and the agent becomes a conversational teammate on issues and pull requests: @mention it in an issue/PR/review comment and it wakes with the repo checked out into its sandbox (and the PR diff…",
|
|
10
|
-
markdown: "# GitHub\n\nInstall Open Everywhere's GitHub App on a repo and the agent becomes a **conversational\nteammate on issues and pull requests**: @mention it in an issue/PR/review comment and it wakes\nwith the repo checked out into its sandbox (and the PR diff in context), does the work, and\nreplies as a comment. Opt the repo's memory **domain** into ambient mode and it also becomes a\n**quiet standing reviewer**: it reads every issue/PR-timeline comment, judges each against a\ndeliberately high bar (GitHub defaults to the *reserved* calibration tier), and comments only\nwhere it clearly adds something — every silence audited.\n\nThis is the GitHub *conversational-surface* runbook. It is **distinct from the\n[source-control plane](../../capabilities/source-control.md)** (the agent's own coding loop —\ncheckout/push/PR via the `OE_GITHUB_*` credentials): the two are orthogonal planes that can\nshare one GitHub App but use **separate env var sets** (bare `GITHUB_*` here). For the concept\nof a *surface*, see [Surfaces](../../extending/surfaces.md). Like\n[Linear](./linear.md)/[Notion](./notion.md), GitHub is ticket/comment-based rather than\nchat-based, so it's out of scope for the chat [support matrix](./support-matrix.md).\n\n## How it works — three legs on one webhook route\n\nEvery GitHub App webhook delivery hits **`POST /eve/v1/github`** and feeds up to three legs:\n\n1. **The @mention leg** (eve's native `githubChannel`). Typing `@<app-slug>` in an issue, PR,\n or review comment wakes an agent session anchored to that conversation, with the repo\n checked out and (for PRs) the diff in context; the reply posts back as a comment. Note App\n bots don't appear in GitHub's `@` autocomplete — the mention matcher is text-based, so\n **type the slug in full** (e.g. `@open-everywhere`). The `@mention` also **engages** that\n issue or pull request: later plain comments on it wake the agent with no new mention, until\n somebody asks it to stop following — see [Reply without re-tagging](#reply-without-re-tagging)\n below.\n2. **The event → routine fan-out.** `issues` / `pull_request` / CI events fire any subscribed\n [event routines](../../capabilities/proactivity-and-routines.md) into their (Slack) surfaces.\n Before it fires, OE **re-fetches the entity over its own credential** rather than trusting the\n webhook body — *payload-as-pointer*. The fired message states the read instant and marks\n itself the current, authoritative state; the webhook's own one-line summary sits above it and\n may be older (a queued delivery can still describe a PR that has since merged), so that\n summary is HISTORY, not the present. The vendor's own `updated` timestamp, when GitHub sends\n one, is aged against the read the same way a [Linear](./linear.md#reading-an-issue) comment is.\n **The re-fetch applies to an issue or a pull request**, the two things GitHub serves under a\n number. A `check_run`, a `release` or a `workflow_run` is identified by an opaque id instead, so\n there is nothing to re-read: those fire from the webhook's own one-line summary and claim to have\n read nothing.\n A **`workflow_run`** fire also carries the run's branch, workflow name, status and conclusion as\n filterable fields, so \"a red build on our `main`\" is a subscription rather than a routine that\n wakes on every run and reads the payload:\n `.scope.container == \"acme/web\" and .fields.conclusion == \"failure\" and .fields.branch == \"main\"`.\n **The container clause is required, not decoration** — a `github` subscription that narrows by\n nothing is refused when you arm it, because one source spans every repo the App is installed on.\n And `branch` is a ref *name*: a run triggered by a pull request from a fork carries the\n contributor's head ref, and a fork's own default branch is usually `main` too, so `branch` alone\n does not prove the run ran on your branch. See the\n [event inventory](../../capabilities/proactivity-and-routines.md#the-event-inventory--what-each-vendor-can-send-and-how-far-we-carry-it)\n for what every other event does and does not carry.\n3. **The ambient-supervisor leg** (on by default). Every *non-mention* issue/PR-timeline comment on an\n ambient-on repo is judged by a **standing per-repo supervisor session** — the same ambient\n judge Slack channels and Notion docs use — which replies into the triggering issue/PR or\n stays audibly silent (a `github.no_reply` audit row, reason included).\n\n### Reply without re-tagging\n\nAn `@mention` marks that issue or pull request **engaged**. From then on a plain comment there\nwakes the agent — no second `@mention`, and no domain opt-in: the invitation was the comment\nsomebody already wrote.\n\n- **It is per container, never per repo.** Engaging issue #42 says nothing about #43.\n- **Private repos only.** A plain follow-up wakes a full turn — the agent checks the repo out and\n spends on the model — so on a public repo it would let any passer-by buy one. The follow-up\n therefore does nothing on a public repo, or on one whose privacy the delivery does not state.\n It is a *stricter* floor than ambient mode's below: ambient mode admits a public repo you vouched\n internal, and this one does not — vouching a repo never opens an uninvited full turn on it. An\n `@mention` still works on a public repo, exactly as before.\n- **Inline review comments do not count as follow-ups.** A review thread shares its pull request's\n container, so a plain inline comment on an engaged pull request wakes nothing — one review would\n otherwise start a turn per comment. `@mention` the app inside the review thread to get an answer\n there.\n- **Asking it to stop works, and it is durable.** Say it in words — \"leave this to us\", \"stop\n following this one\" — and the agent calls `stand_down`, which stores the stop against that\n issue. It then answers nothing there, on either leg, until somebody `@mentions` it again. A new\n `@mention` is the way back in; there is no timeout.\n- **A container nobody ever mentioned it in is untouched** by all of this. It wakes only through\n the ambient supervisor below, which is on by default and off where a domain sets\n `ambientSupervisor: false`.\n- **The agent's own comments never re-trigger it**, and neither do other bots' — an engaged issue\n admits comments from people only.\n\n### Ambient mode — reserved by default, fail-closed everywhere\n\n- **On by default, off per domain.** The repo's memory domain decides with `ambientSupervisor`,\n the same flag that governs Slack, Linear and Notion ambient. Unset, it inherits the `org`\n domain's value, and an unset `org` means on (OPE-2409). With `ambientSupervisor: false`,\n non-mention comments do nothing. The private-repo floor below holds either way.\n- **A positively private repo, or any repo the operator vouched internal — fail-closed.** On a\n private repo every commenter was invited. On an unvouched public repo any drive-by stranger\n could buy judged model turns (an uninvited spend + prompt-injection surface). So the ambient\n leg runs on a repo the delivery states is private, and on any repo the operator vouched\n internal. It **drops every other comment** fail-closed — a repo that is neither positively\n private nor vouched, which includes a repo whose privacy the delivery does not state. Vouch\n one repo by declaring the surface key `github/<owner>` or `github/<owner>/<repo>` internal in\n the trust register (see\n [Identity](../../how-it-works/identity.md#the-trust-registry--declaring-what-a-rooms-audience-is));\n the setting `identity.blanketTrust: \"internal\"` is the deployment-wide blanket, not the per-repo act.\n- **GitHub's calibration tier defaults to `reserved`** — a deliberately *higher* bar than\n Slack/Notion, because an over-eager bot in a collaborative code space reads as spam. Tune it\n per domain with `engagementTier` (see the\n [configuration reference](../configuration-reference.md#memory-domain--silo)).\n- **Mentions never double-handle, and neither do engaged follow-ups.** The ambient classifier\n reuses the exact mention gate the native leg wakes on. On a SINGLE-WINDOW, operator-vouched\n repo it returns `direct`, and the unified window answers the mention. On every other repo it\n *drops* the mention, because the native leg owns it. An engaged follow-up goes to whichever\n leg owns mentions on that repo, so the two legs partition every comment with no overlap and\n no gap:\n - on a repo where the NATIVE leg answers mentions, the native leg owns the engaged follow-up\n too, and the ambient leg drops it;\n - on a SINGLE-WINDOW, operator-vouched repo the native leg stands down for every comment\n (`shouldSuppressNativeMention`), so the AMBIENT leg owns the engaged follow-up and answers it\n as a judged wake — even with `ambientSupervisor` off. That wake states\n `follow-up=\"thread-engaged\"`, as the Slack, Linear and Notion wakes do, so the agent reads the\n follow-up as part of a conversation it is already in. An @mention carries no `follow-up`\n attribute: it is owed an answer whatever the enrolment says. The classifier itself reads no\n engagement row; the split is made at the native suppression gate.\n- **A stood-down container is dropped here too.** Once somebody asks the agent to stop following\n an issue, the ambient leg stops answering it as well, whatever the domain flag says. That is the\n only thing that makes the stop a stop rather than a note.\n- **The supervisor is silent plumbing.** Its judged turns add no 👀 reaction (the mention leg\n keeps its ack reaction), never check the repo out, and a *failed* judge turn is audited —\n never posted as an error comment.\n- Review-thread **inline** comments (`pull_request_review_comment`) are out of ambient scope\n v1 (a different reply/threading model); PR *timeline* comments are covered (GitHub delivers\n them as `issue_comment`).\n\n## How the silo model maps\n\n| Open Everywhere concept | GitHub thing |\n| --- | --- |\n| `org` (tenant) | your deployment (`deploymentIdentity.org` in `agent/identity/surfaces.ts`, one org per deploy today) |\n| `workspace` (identity key) | the repo **owner** (org/user login) |\n| `surface` (partition key) | the **repo** (one repo, many issues/PRs over time) |\n| invocation + post-back anchor | the **issue / PR** number |\n| `mode` | `channel` (GitHub has no 1:1 DM analog) |\n| `visibility` | `public` only for an explicitly public repo; else `private` (fail-closed) |\n\n**Trust fails closed.** Only a *private* repo touched by an org **OWNER/MEMBER** binds\n`internal` (shared/org memory readable); public repos, outside collaborators, and missing\nsignals bind `external`. The operator can vouch a deployment with the setting `identity.blanketTrust: \"internal\"` — the\nsame layer the other non-Slack platforms use.\n\n## Setup\n\n1. **Create (or reuse) a GitHub App** with a webhook pointed at\n `https://<your-deploy-url>/eve/v1/github`, a webhook secret, and repo permissions for\n Issues + Pull requests (read/write) and Contents (read — the mention leg's sandbox\n checkout). **Grant Issues *and* Pull requests, both at read/write — neither alone is\n enough.** GitHub serves an issue and a PR through the same `/issues/{n}` endpoints but\n routes permission by the resource the number names, so an App missing either family goes\n 403 on half of its own conversations: missing Issues and it cannot read a plain issue,\n missing Pull requests and its replies never land on a PR thread. Subscribe to\n **`issue_comment`** + **`pull_request_review_comment`** (mention\n turns; `issue_comment` also feeds the ambient leg) and, for the routine fan-out,\n `issues` / `pull_request` / `check_suite` / `check_run` / `workflow_run` (the Checks events\n only appear once the Checks permission is granted).\n You do **not** need to subscribe to `installation` / `installation_repositories` — GitHub\n sends both to every App automatically and they are absent from the \"Subscribe to events\"\n list for that reason (\"All GitHub Apps receive this event by default. You cannot manually\n subscribe to this event.\"). They arrive on the same webhook URL, so each org that installs\n the App registers itself with no extra configuration (see *Multi-org installs* below).\n On the App's settings page, under **Display information**, upload [`brand/png/mark-square-1024.png`](../../../brand/png/mark-square-1024.png), the project mark, as its logo. Skip this when you set [`identity.name`](../configuration-reference.md) and chose your own icon: with no name configured the agent presents as the project, so the project mark is its default avatar.\n2. **Install the App** on the repos the agent should live on.\n3. **Configure the environment** (the conversational surface uses the **bare** names — the\n `OE_GITHUB_*` set is the separate source-control plane, even when both point at one App):\n\n ```bash\n GITHUB_APP_ID=… # the App's numeric id\n GITHUB_APP_SLUG=… # the App slug — the bot answers to @<slug>\n GITHUB_APP_PRIVATE_KEY=… # PEM private key (mint installation tokens)\n GITHUB_WEBHOOK_SECRET=… # HMAC-verifies every delivery. REQUIRED — unset rejects all (fail closed)\n # DEV ONLY, and it is a SETTING not a variable: turn on `webhooks.allowUnverifiedGithub`\n # in agent/settings/settings.ts to accept unsigned deliveries locally.\n ```\n\n4. **Ambient mode is on by default** for a positively private or vouched repo. Add the repo to a\n memory domain (surface key `github/<owner>/<repo>`) to give it a silo — see\n [Memory](../../capabilities/memory.md). To make the repo addressed-only, set\n `ambientSupervisor: false` on that domain. A domain can compose repos **with** Slack channels,\n Notion docs, and Linear teams: one flag, one shared silo, one posture everywhere in it.\n\n## Multi-org installs (self-registering)\n\nThe source-control plane mints tokens per **owner**, so it needs an `owner → installation id`\nentry for every account the App is installed on. You can set that by hand with\n`OE_GITHUB_INSTALLATIONS` (a JSON map) or the single-owner `OE_GITHUB_OWNER` /\n`OE_GITHUB_INSTALLATION_ID` pair — and you no longer have to.\n\nBecause GitHub delivers `installation` + `installation_repositories` to every App by default\n(no subscription exists to switch on), each install/uninstall registers\nitself: `created`/`unsuspend` records the owner's installation id, `deleted`/`suspend` clears it,\nand a repo-scope change refreshes it. An org installing your App is then self-service end to end —\nno env edit, no redeploy.\n\n**`OE_GITHUB_INSTALLATIONS` stays authoritative.** The discovered entries are composed *under* the\nenv map, so anything you pinned by hand always wins, a store outage degrades to exactly the\nenv-configured set, and a webhook can never re-point an owner you configured yourself. (By the same\nrule, uninstalling an org you *also* pinned in env leaves the env entry in place — its mints then\nfail loudly at GitHub, which is the honest signal; remove it from the env map to finish the removal.)\n\nInstall and uninstall both write an audit row — `surface.app_installed` / `surface.app_uninstalled`,\nwith the owner as the workspace — so the install history is queryable over the control plane's\naudit route.\n\n## Ticket actions (state / assignee / labels)\n\nThe agent can also mutate an issue/PR's own state, assignee, and labels —\n[Source control § Ticket actions](../../capabilities/source-control.md#ticket-actions-set_state--assign--add_label)\nis the canonical doc (these ride the **source-control plane**'s credential, the `OE_GITHUB_*`\nApp, not this page's bare `GITHUB_*` conversational set — grant it the Issues permission).\nThese three verbs are known to work on an **issue**. On a **pull request** they are expected to\nbe refused today, because their credential names only the Issues family — tracked as OPE-1021.\n\nIt can also **file a new issue** with `create_ticket` (`target` = `owner/repo`, defaulting to\nthis turn's own repo, or to the channel's sole granted repo) — same Issues permission, same\nper-channel repo grant, and it always goes through the approval gate first — a card, unless an\noperator has explicitly lowered that verb in the approver chain. See\n[Source control § Filing new work](../../capabilities/source-control.md#filing-new-work-create_ticket).\n\n## Reading the conversation\n\nThe agent reads the thread it was called into with the same two verbs it uses on every other\nsurface: `read_channel` reads the issue-or-PR conversation — the opening post, then the newest\ntimeline comments — and `read_thread` reads one PR **review thread**, the inline discussion on a\nline of the diff. Both take no target: they read the conversation this turn arrived in.\n\nThree things worth knowing:\n\n- **A plain issue reads exactly like a PR.** The read goes through `/repos/{repo}/issues/{number}`,\n which GitHub serves for both, so nothing is PR-only here. `get_pr_feedback` remains the richer\n read for a PR under review — reviews, inline comments and check runs, which a conversation read\n does not carry.\n- **Another issue reads by target.** `read_channel` and `read_work_channel` read only this\n conversation. `read_github_issue` takes `repo` and `number` and reads another issue's opening\n post and newest comments, inside the session's repo grant. A `search` hit for such an issue names\n it as the road.\n- **Only a comment on the diff has a thread.** An issue comment and a PR timeline comment are at the\n top level of their conversation, so `read_thread` on one says so rather than reading the timeline\n under a thread read's name.\n- **A delegated worker needs the repo grant.** The seat reads its own conversation; the worker's\n `read_work_channel` / `read_work_thread` mount only when the calling scope grants at least one repo\n ([Connectors § A chat surface can be a work surface too](../../capabilities/connectors-and-providers.md#a-chat-surface-can-be-a-work-surface-too)).\n\nThe read runs on the source-control credential — the `OE_GITHUB_*` App installation token, falling\nback to `GITHUB_TOKEN` — so a repo the App is not installed on cannot be read.\n\n## Gotchas\n\n- **A reaction on the agent's comment is read, not delivered — and only in conversations it has\n commented in.** GitHub sends no reaction webhook, so the agent looks for reactions on its own\n comments when the *next* delivery names that conversation. Two bounds keep that cheap, and both\n change what you will see. It looks only in conversations it is *in* — ones this deployment's reply\n path has commented in, or ones somebody `@mention`ed it in — because a conversation it is not in\n can hold no reaction it would record. The `@mention` half is what covers the replies the framework\n posts on its own; what falls outside both is a conversation it only ever answered *ambiently*,\n with no `@mention` ever, and has not answered in since this shipped — that one is picked up again\n on its next reply there. And each repository runs roughly 60 such polls an hour at most; the\n counter is deliberately cheap rather than exact, so a burst of simultaneous deliveries can push an\n hour a little over. When a repository passes the ceiling, one **`github.reaction_poll_budget`**\n audit row is written for that hour and the rest of the hour's reactions are not read. Query it with\n `GET /control/v1/audit?since=<iso>&actions=github.reaction_poll_budget` — a busy repository showing these rows\n every hour is the signal that the ceiling, not the feature, is what you are seeing.\n- **A reaction the agent has already recorded is skipped, and a store it cannot read skips\n everything.** The dedupe is a durable claim per reaction, and it fails *closed*: an unreadable\n claim store is treated as \"already recorded\", so no duplicate row is ever written. The cost is\n that a store outage stops the feedback signal completely while it lasts, which on its own looks\n exactly like a quiet week. Each poll that could not read the store writes one\n **`github.reaction_claim_unreadable`** audit row naming how many reactions it skipped. Query it\n with `GET /control/v1/audit?since=<iso>&actions=github.reaction_claim_unreadable`. Rows here mean\n the operational store, not the feature, is what you are seeing; reactions are recorded on the next\n poll after it recovers. **The row covers a *partial* fault, not every one** — it is written to the\n same operational store the claim read failed against, so a store that is wholly unreachable loses\n this row too. That case is visible instead as the audit drop counter and an\n `[open-everywhere:audit] dropped a \"github.reaction_claim_unreadable\" entry …` warning in the\n logs. So: rows present means the claim table specifically; the warning means the store.\n- **Ambient is on unless a domain turns it off** (`ambientSupervisor: false`), and it never runs\n on a repo that isn't positively private or vouched. If non-mention comments get no response, check the domain flag, then the repo's\n privacy — and read the record rather than guessing: the first delivery from a repo the\n supervisor was never asked about writes a **`github.ambient_skipped`** audit row naming the\n surface key, the reason (`domain-refused` — a domain declares `ambientSupervisor: false` and\n this repo inherits it — versus `no-domain` — no domain routes the repo and the app has no `org`\n domain to inherit from, or the domain set did not load, so the gate failed closed) and the line to change. Query it with\n `GET /control/v1/audit?since=<iso>&actions=github.ambient_skipped`. A whole owner at once is\n `reach: [\"github/<owner>\"]` on the domain — or, better where it fits, a same-level glob\n `reach: [\"github/<owner>/payments-*\"]` plus `exclude` for the repos that must stay out. With\n 500 repos the whole-owner entry is tempting, but it confers the domain's bundles on every repo\n the org will ever create; the glob is the same ergonomics with strictly less reach.\n See the [configuration reference](../configuration-reference.md#memory-domain--silo) and\n [Access & scoping](../../how-it-works/access-and-scoping.md#reach-exact-keys-and-containers).\n- **The `reply` tool is the only way an answer reaches an issue.** The agent posts mid-turn by\n calling `reply`; its turn's closing text is DROPPED and never posted. A turn that delivered\n writes a `github.replied` row carrying `route: \"tool\"`.\n- **Silence is a first-class outcome.** Most comments correctly get no reply (reserved tier).\n Every judged-silent turn is a `github.no_reply` audit row — the surface is working, not\n broken. Tune via `engagementTier`, watching the live `no_reply` rate. A **different** quiet\n outcome is a `turn.supervisor_prose_dropped` row on the github partition: the agent wrote an\n answer as its closing text and never called `reply`, so nothing was posted. That row is a\n defect signal, not a tuning signal — read the session transcript it names.\n- **An @mention turn can judge silence too.** The `github.no_reply` row is not only an ambient\n outcome. A turn woken by a direct @mention can also decide the wake does not warrant an answer;\n it then comments NOTHING and writes the same row with `route: \"native\"` and the reason. Those\n rows are rare by construction — a member addressed the app — so treat one as worth reading, not\n as tuning noise.\n- **Mention the slug in full.** App bots aren't in GitHub's `@` autocomplete; the matcher is\n text-based (`@<slug>` followed by a non-word character).\n- **Webhook verification is fail-closed.** `GITHUB_WEBHOOK_SECRET` unset/wrong → every\n delivery is rejected 401 and every leg stays silent — including the installation leg, so a\n deploy with a wrong secret silently learns nothing. Check the secret first if installs\n aren't registering.\n\n## Status\n\nThe @mention leg and the routine fan-out are **live-verified**. The ambient leg is built,\nunit-tested, and driven by the `J-GH` end-to-end scenario in\n`packages/core/scripts/e2e/scenarios.ts` (`suite: \"core\"`, non-optional, judged), with\n`J-ENGAGED-github` covering the engaged-follow-up seam. `J-GH` drives the mention reply, the\npickup reaction, the **mention gate** (a non-mention comment gets no reply) with its\naudited-silence row, session resume, reply-targeting across two issues, and the signed-forge\nroute contract. The ambient *wake* on an opted-in repo is `J-ENGAGED-github`'s leg: a mention\nengages the issue, a plain follow-up wakes, and `stand_down` stops it. The repository holds the\nscenarios, not their results, so read live-verification status off those runs rather than off\nthis page.\n",
|
|
10
|
+
markdown: [
|
|
11
|
+
"# GitHub",
|
|
12
|
+
"",
|
|
13
|
+
"Install Open Everywhere's GitHub App on a repo and the agent becomes a **conversational",
|
|
14
|
+
"teammate on issues and pull requests**: @mention it in an issue/PR/review comment and it wakes",
|
|
15
|
+
"with the repo checked out into its sandbox (and the PR diff in context), does the work, and",
|
|
16
|
+
"replies as a comment. Opt the repo's memory **domain** into ambient mode and it also becomes a",
|
|
17
|
+
"**quiet standing reviewer**: it reads every issue/PR-timeline comment, judges each against a",
|
|
18
|
+
"deliberately high bar (GitHub defaults to the *reserved* calibration tier), and comments only",
|
|
19
|
+
"where it clearly adds something — every silence audited.",
|
|
20
|
+
"",
|
|
21
|
+
"This is the GitHub *conversational-surface* runbook. It is **distinct from the",
|
|
22
|
+
"[source-control plane](../../capabilities/source-control.md)** (the agent's own coding loop —",
|
|
23
|
+
"checkout/push/PR via the `OE_GITHUB_*` credentials): the two are orthogonal planes that can",
|
|
24
|
+
"share one GitHub App but use **separate env var sets** (bare `GITHUB_*` here). For the concept",
|
|
25
|
+
"of a *surface*, see [Surfaces](../../extending/surfaces.md). Like",
|
|
26
|
+
"[Linear](./linear.md)/[Notion](./notion.md), GitHub is ticket/comment-based rather than",
|
|
27
|
+
"chat-based, so it's out of scope for the chat [support matrix](./support-matrix.md).",
|
|
28
|
+
"",
|
|
29
|
+
"## How it works — three legs on one webhook route",
|
|
30
|
+
"",
|
|
31
|
+
"Every GitHub App webhook delivery hits **`POST /eve/v1/github`** and feeds up to three legs:",
|
|
32
|
+
"",
|
|
33
|
+
"1. **The @mention leg** (eve's native `githubChannel`). Typing `@<app-slug>` in an issue, PR,",
|
|
34
|
+
" or review comment wakes an agent session anchored to that conversation, with the repo",
|
|
35
|
+
" checked out and (for PRs) the diff in context; the reply posts back as a comment. Note App",
|
|
36
|
+
" bots don't appear in GitHub's `@` autocomplete — the mention matcher is text-based, so",
|
|
37
|
+
" **type the slug in full** (e.g. `@open-everywhere`). The `@mention` also **engages** that",
|
|
38
|
+
" issue or pull request: later plain comments on it wake the agent with no new mention, until",
|
|
39
|
+
" somebody asks it to stop following — see [Reply without re-tagging](#reply-without-re-tagging)",
|
|
40
|
+
" below.",
|
|
41
|
+
"2. **The event → routine fan-out.** `issues` / `pull_request` / CI events fire any subscribed",
|
|
42
|
+
" [event routines](../../capabilities/proactivity-and-routines.md) into their (Slack) surfaces.",
|
|
43
|
+
" Before it fires, OE **re-fetches the entity over its own credential** rather than trusting the",
|
|
44
|
+
" webhook body — *payload-as-pointer*. The fired message states the read instant and marks",
|
|
45
|
+
" itself the current, authoritative state; the webhook's own one-line summary sits above it and",
|
|
46
|
+
" may be older (a queued delivery can still describe a PR that has since merged), so that",
|
|
47
|
+
" summary is HISTORY, not the present. The vendor's own `updated` timestamp, when GitHub sends",
|
|
48
|
+
" one, is aged against the read the same way a [Linear](./linear.md#reading-an-issue) comment is.",
|
|
49
|
+
" **The re-fetch applies to an issue or a pull request**, the two things GitHub serves under a",
|
|
50
|
+
" number. A `check_run`, a `release` or a `workflow_run` is identified by an opaque id instead, so",
|
|
51
|
+
" there is nothing to re-read: those fire from the webhook's own one-line summary and claim to have",
|
|
52
|
+
" read nothing.",
|
|
53
|
+
" A **`workflow_run`** fire also carries the run's branch, workflow name, status and conclusion as",
|
|
54
|
+
" filterable fields, so \"a red build on our `main`\" is a subscription rather than a routine that",
|
|
55
|
+
" wakes on every run and reads the payload:",
|
|
56
|
+
" `.scope.container == \"acme/web\" and .fields.conclusion == \"failure\" and .fields.branch == \"main\"`.",
|
|
57
|
+
" **The container clause is required, not decoration** — a `github` subscription that narrows by",
|
|
58
|
+
" nothing is refused when you arm it, because one source spans every repo the App is installed on.",
|
|
59
|
+
" And `branch` is a ref *name*: a run triggered by a pull request from a fork carries the",
|
|
60
|
+
" contributor's head ref, and a fork's own default branch is usually `main` too, so `branch` alone",
|
|
61
|
+
" does not prove the run ran on your branch. See the",
|
|
62
|
+
" [event inventory](../../capabilities/proactivity-and-routines.md#the-event-inventory--what-each-vendor-can-send-and-how-far-we-carry-it)",
|
|
63
|
+
" for what every other event does and does not carry.",
|
|
64
|
+
"3. **The ambient-supervisor leg** (on by default). Every *non-mention* issue/PR-timeline comment on an",
|
|
65
|
+
" ambient-on repo wakes the repo's **standing seat** — the same ambient",
|
|
66
|
+
" judge Slack channels and Notion docs use — which replies into the triggering issue/PR or",
|
|
67
|
+
" stays audibly silent (a `github.no_reply` audit row, reason included).",
|
|
68
|
+
"",
|
|
69
|
+
"### Reply without re-tagging",
|
|
70
|
+
"",
|
|
71
|
+
"An `@mention` marks that issue or pull request **engaged**. From then on a plain comment there",
|
|
72
|
+
"wakes the agent — no second `@mention`, and no domain opt-in: the invitation was the comment",
|
|
73
|
+
"somebody already wrote.",
|
|
74
|
+
"",
|
|
75
|
+
"- **It is per container, never per repo.** Engaging issue #42 says nothing about #43.",
|
|
76
|
+
"- **Private repos only.** A plain follow-up wakes a full turn — the agent checks the repo out and",
|
|
77
|
+
" spends on the model — so on a public repo it would let any passer-by buy one. The follow-up",
|
|
78
|
+
" therefore does nothing on a public repo, or on one whose privacy the delivery does not state.",
|
|
79
|
+
" It is a *stricter* floor than ambient mode's below: ambient mode admits a public repo you vouched",
|
|
80
|
+
" internal, and this one does not — vouching a repo never opens an uninvited full turn on it. An",
|
|
81
|
+
" `@mention` still works on a public repo, exactly as before.",
|
|
82
|
+
"- **Inline review comments do not count as follow-ups.** A review thread shares its pull request's",
|
|
83
|
+
" container, so a plain inline comment on an engaged pull request wakes nothing — one review would",
|
|
84
|
+
" otherwise start a turn per comment. `@mention` the app inside the review thread to get an answer",
|
|
85
|
+
" there.",
|
|
86
|
+
"- **Asking it to stop works, and it is durable.** Say it in words — \"leave this to us\", \"stop",
|
|
87
|
+
" following this one\" — and the agent calls `stand_down`, which stores the stop against that",
|
|
88
|
+
" issue. It then answers nothing there, on either leg, until somebody `@mentions` it again. A new",
|
|
89
|
+
" `@mention` is the way back in; there is no timeout.",
|
|
90
|
+
"- **A container nobody ever mentioned it in is untouched** by all of this. It wakes only through",
|
|
91
|
+
" the ambient supervisor below, which is on by default and off where a domain sets",
|
|
92
|
+
" `ambientSupervisor: false`.",
|
|
93
|
+
"- **The agent's own comments never re-trigger it**, and neither do other bots' — an engaged issue",
|
|
94
|
+
" admits comments from people only.",
|
|
95
|
+
"",
|
|
96
|
+
"### Ambient mode — reserved by default, fail-closed everywhere",
|
|
97
|
+
"",
|
|
98
|
+
"- **On by default, off per domain.** The repo's memory domain decides with `ambientSupervisor`,",
|
|
99
|
+
" the same flag that governs Slack, Linear and Notion ambient. Unset, it inherits the `org`",
|
|
100
|
+
" domain's value, and an unset `org` means on (OPE-2409). With `ambientSupervisor: false`,",
|
|
101
|
+
" non-mention comments do nothing. The private-repo floor below holds either way.",
|
|
102
|
+
"- **The flag decides what wakes the repo's standing seat, nothing else.** It does not decide",
|
|
103
|
+
" how many repos share one seat (`mode`, `windows`) or which memory the seat reads (`memory`). A",
|
|
104
|
+
" repo in no explicit domain has its own solo seat, even with `ambientSupervisor` on at `org`.",
|
|
105
|
+
" See [Wake, seat, memory: three independent axes](../configuration-reference.md#wake-seat-memory-three-independent-axes).",
|
|
106
|
+
"- **A positively private repo, or any repo the operator vouched internal — fail-closed.** On a",
|
|
107
|
+
" private repo every commenter was invited. On an unvouched public repo any drive-by stranger",
|
|
108
|
+
" could buy judged model turns (an uninvited spend + prompt-injection surface). So the ambient",
|
|
109
|
+
" leg runs on a repo the delivery states is private, and on any repo the operator vouched",
|
|
110
|
+
" internal. It **drops every other comment** fail-closed — a repo that is neither positively",
|
|
111
|
+
" private nor vouched, which includes a repo whose privacy the delivery does not state. Vouch",
|
|
112
|
+
" one repo by declaring the surface key `github/<owner>` or `github/<owner>/<repo>` internal in",
|
|
113
|
+
" the trust register (see",
|
|
114
|
+
" [Identity](../../how-it-works/identity.md#the-trust-registry--declaring-what-a-rooms-audience-is));",
|
|
115
|
+
" the setting `identity.blanketTrust: \"internal\"` is the deployment-wide blanket, not the per-repo act.",
|
|
116
|
+
"- **GitHub's calibration tier defaults to `reserved`** — a deliberately *higher* bar than",
|
|
117
|
+
" Slack/Notion, because an over-eager bot in a collaborative code space reads as spam. Tune it",
|
|
118
|
+
" per domain with `engagementTier` (see the",
|
|
119
|
+
" [configuration reference](../configuration-reference.md#memory-domain--silo)).",
|
|
120
|
+
"- **Mentions never double-handle, and neither do engaged follow-ups.** The ambient classifier",
|
|
121
|
+
" reuses the exact mention gate the native leg wakes on. On a SINGLE-WINDOW, operator-vouched",
|
|
122
|
+
" repo it returns `direct`, and the unified window answers the mention. On every other repo it",
|
|
123
|
+
" *drops* the mention, because the native leg owns it. An engaged follow-up goes to whichever",
|
|
124
|
+
" leg owns mentions on that repo, so the two legs partition every comment with no overlap and",
|
|
125
|
+
" no gap:",
|
|
126
|
+
" - on a repo where the NATIVE leg answers mentions, the native leg owns the engaged follow-up",
|
|
127
|
+
" too, and the ambient leg drops it;",
|
|
128
|
+
" - on a SINGLE-WINDOW, operator-vouched repo the native leg stands down for every comment",
|
|
129
|
+
" (`shouldSuppressNativeMention`), so the AMBIENT leg owns the engaged follow-up and answers it",
|
|
130
|
+
" as a judged wake — even with `ambientSupervisor` off. That wake states",
|
|
131
|
+
" `follow-up=\"thread-engaged\"`, as the Slack, Linear and Notion wakes do, so the agent reads the",
|
|
132
|
+
" follow-up as part of a conversation it is already in. An @mention carries no `follow-up`",
|
|
133
|
+
" attribute: it is owed an answer whatever the enrolment says. The classifier itself reads no",
|
|
134
|
+
" engagement row; the split is made at the native suppression gate.",
|
|
135
|
+
"- **A stood-down container is dropped here too.** Once somebody asks the agent to stop following",
|
|
136
|
+
" an issue, the ambient leg stops answering it as well, whatever the domain flag says. That is the",
|
|
137
|
+
" only thing that makes the stop a stop rather than a note.",
|
|
138
|
+
"- **The supervisor is silent plumbing.** Its judged turns add no 👀 reaction (the mention leg",
|
|
139
|
+
" keeps its ack reaction), never check the repo out, and a *failed* judge turn is audited —",
|
|
140
|
+
" never posted as an error comment.",
|
|
141
|
+
"- Review-thread **inline** comments (`pull_request_review_comment`) are out of ambient scope",
|
|
142
|
+
" v1 (a different reply/threading model); PR *timeline* comments are covered (GitHub delivers",
|
|
143
|
+
" them as `issue_comment`).",
|
|
144
|
+
"",
|
|
145
|
+
"## How the silo model maps",
|
|
146
|
+
"",
|
|
147
|
+
"| Open Everywhere concept | GitHub thing |",
|
|
148
|
+
"| --- | --- |",
|
|
149
|
+
"| `org` (tenant) | your deployment (`deploymentIdentity.org` in `agent/identity/surfaces.ts`, one org per deploy today) |",
|
|
150
|
+
"| `workspace` (identity key) | the repo **owner** (org/user login) |",
|
|
151
|
+
"| `surface` (partition key) | the **repo** (one repo, many issues/PRs over time) |",
|
|
152
|
+
"| invocation + post-back anchor | the **issue / PR** number |",
|
|
153
|
+
"| `mode` | `channel` (GitHub has no 1:1 DM analog) |",
|
|
154
|
+
"| `visibility` | `public` only for an explicitly public repo; else `private` (fail-closed) |",
|
|
155
|
+
"",
|
|
156
|
+
"**Trust fails closed.** Only a *private* repo touched by an org **OWNER/MEMBER** binds",
|
|
157
|
+
"`internal` (shared/org memory readable); public repos, outside collaborators, and missing",
|
|
158
|
+
"signals bind `external`. The operator can vouch a deployment with the setting `identity.blanketTrust: \"internal\"` — the",
|
|
159
|
+
"same layer the other non-Slack platforms use.",
|
|
160
|
+
"",
|
|
161
|
+
"## Setup",
|
|
162
|
+
"",
|
|
163
|
+
"1. **Create the GitHub App in one click.** The ops MCP server generates the App's manifest and",
|
|
164
|
+
" catches the keys GitHub hands back (OPE-2529). The agent driving setup calls:",
|
|
165
|
+
"",
|
|
166
|
+
" ```",
|
|
167
|
+
" surface_app_create { \"surface\": \"github\", \"baseUrl\": \"https://<your-deploy-url>\" }",
|
|
168
|
+
" ```",
|
|
169
|
+
"",
|
|
170
|
+
" The reply carries `openUrl`, a page on your own computer. Open it in a browser on that computer.",
|
|
171
|
+
" GitHub opens with the App filled in: its name, the webhook at",
|
|
172
|
+
" `https://<your-deploy-url>/eve/v1/github`, a generated webhook secret, and the permissions and",
|
|
173
|
+
" events below. Check the name and confirm. GitHub App names are unique across GitHub, so change",
|
|
174
|
+
" the name there if GitHub says it is taken. GitHub then sends the App's id, private key and",
|
|
175
|
+
" webhook secret back to the local page, which writes them into `.env.local`. You copy no key, and",
|
|
176
|
+
" no value passes through the chat. `surface_app_create { \"surface\": \"github\", \"action\": \"status\" }`",
|
|
177
|
+
" then lists the names written and the App's install link.",
|
|
178
|
+
"",
|
|
179
|
+
" - `owner: \"<org login>\"` creates the App under an organization. Without it, the App belongs to",
|
|
180
|
+
" your own account.",
|
|
181
|
+
" - `variant: \"source-control\"` creates an App for the [source-control plane](../../capabilities/source-control.md)",
|
|
182
|
+
" only: no events and no @mention replies. The default, `full`, also serves this page's",
|
|
183
|
+
" conversational surface. Both keep the webhook on, because install self-registration",
|
|
184
|
+
" (below) arrives through it.",
|
|
185
|
+
" - The tool refuses to overwrite names `.env.local` already holds. Pass `replace: true` only to",
|
|
186
|
+
" replace an existing App's keys with a new App's keys.",
|
|
187
|
+
"",
|
|
188
|
+
" **Permissions and events.** The manifest takes its permissions from the source-control plane's",
|
|
189
|
+
" mint bodies (`scm/app-permissions.ts`) and its events from this bundle's event inventory",
|
|
190
|
+
" (`agent/provider-events.ts`). This table is generated from the same builder, so the doc, the",
|
|
191
|
+
" manifest and the code cannot drift:",
|
|
192
|
+
"",
|
|
193
|
+
" <!-- BEGIN GENERATED: github-app-permissions (scripts/github-app-manifest-docs.ts) -->",
|
|
194
|
+
"",
|
|
195
|
+
" | Repository permission | Access | Shape | Why |",
|
|
196
|
+
" | --- | --- | --- | --- |",
|
|
197
|
+
" | Actions | Read-only | full App only | the `workflow_job`, `workflow_run` events |",
|
|
198
|
+
" | Checks | Read-only | full App only | the `check_run`, `check_suite` events |",
|
|
199
|
+
" | Contents | Read and write | both | open a pull request; check out a repo; write memory; read a pull request; the `push`, `release` events |",
|
|
200
|
+
" | Issues | Read and write | both | read a conversation; reply in a conversation; act on an issue; the `issue_comment`, `issues` events |",
|
|
201
|
+
" | Metadata | Read-only | both | open a pull request; check out a repo; write memory; read a pull request; read a conversation; reply in a conversation; act on an issue |",
|
|
202
|
+
" | Pull requests | Read and write | both | open a pull request; read a pull request; read a conversation; reply in a conversation; the `pull_request`, `pull_request_review`, `pull_request_review_comment` events |",
|
|
203
|
+
"",
|
|
204
|
+
" Events (full App only): `check_run`, `check_suite`, `issue_comment`, `issues`, `pull_request`, `pull_request_review`, `pull_request_review_comment`, `push`, `release`, `workflow_job`, `workflow_run`. GitHub sends `installation` and `installation_repositories` to every App with an active webhook, so neither is listed.",
|
|
205
|
+
"",
|
|
206
|
+
" <!-- END GENERATED: github-app-permissions -->",
|
|
207
|
+
"",
|
|
208
|
+
" **Issues and Pull requests, both at read and write — neither alone is enough.** GitHub serves an",
|
|
209
|
+
" issue and a PR through the same `/issues/{n}` endpoints but routes permission by the resource the",
|
|
210
|
+
" number names, so an App missing either family goes 403 on half of its own conversations: missing",
|
|
211
|
+
" Issues and it cannot read a plain issue, missing Pull requests and its replies never land on a PR",
|
|
212
|
+
" thread. An opt-in [capability set](../../capabilities/source-control.md#per-binding-capability-sets)",
|
|
213
|
+
" (`workflows`) needs one more permission. The manifest does not grant it, and the",
|
|
214
|
+
" `permission_fit_report` names the App update when a binding asks for it.",
|
|
215
|
+
"",
|
|
216
|
+
" You do **not** subscribe to `installation` / `installation_repositories` — GitHub sends both to",
|
|
217
|
+
" every App automatically and they are absent from the \"Subscribe to events\" list for that reason",
|
|
218
|
+
" (\"All GitHub Apps receive this event by default. You cannot manually subscribe to this event.\").",
|
|
219
|
+
" They arrive on the same webhook URL, so each org that installs the App registers itself with no",
|
|
220
|
+
" extra configuration (see *Multi-org installs* below).",
|
|
221
|
+
"",
|
|
222
|
+
" **By hand.** Without the ops server, create the App at GitHub → **Settings → Developer settings",
|
|
223
|
+
" → GitHub Apps → New GitHub App**. Point the webhook at `https://<your-deploy-url>/eve/v1/github`,",
|
|
224
|
+
" set a webhook secret, grant the permissions in the table and subscribe to its events. Then set the",
|
|
225
|
+
" environment in step 2 yourself.",
|
|
226
|
+
"",
|
|
227
|
+
" On the App's settings page, under **Display information**, upload [`brand/png/mark-square-1024.png`](../../../brand/png/mark-square-1024.png), the project mark, as its logo. The manifest has no logo field. Skip this when you set [`identity.name`](../configuration-reference.md) and chose your own icon: with no name configured the agent presents as the project, so the project mark is its default avatar.",
|
|
228
|
+
"2. **Configure the environment.** The full App writes every name below into `.env.local`, plus",
|
|
229
|
+
" the `OE_GITHUB_*` source-control set (`OE_GITHUB_APP_ID`, `OE_GITHUB_APP_SLUG`,",
|
|
230
|
+
" `OE_GITHUB_APP_PRIVATE_KEY`, `OE_GITHUB_APP_CLIENT_ID`) for the same App. The source-control",
|
|
231
|
+
" App writes only the `OE_GITHUB_*` set and `GITHUB_WEBHOOK_SECRET`. `OE_GITHUB_BOT_USER_ID` is",
|
|
232
|
+
" written only when GitHub's bot-user lookup answers. Push the names that `status` lists in",
|
|
233
|
+
" `written`, piped from the file and never printed, then redeploy. By hand, set them yourself. The conversational surface uses the **bare** names — the",
|
|
234
|
+
" `OE_GITHUB_*` set is the separate source-control plane, even when both point at one App:",
|
|
235
|
+
"",
|
|
236
|
+
" ```bash",
|
|
237
|
+
" GITHUB_APP_ID=… # the App's numeric id",
|
|
238
|
+
" GITHUB_APP_SLUG=… # the App slug — the bot answers to @<slug>",
|
|
239
|
+
" GITHUB_APP_PRIVATE_KEY=… # PEM private key (mint installation tokens)",
|
|
240
|
+
" GITHUB_WEBHOOK_SECRET=… # HMAC-verifies every delivery. REQUIRED — unset rejects all (fail closed)",
|
|
241
|
+
" # DEV ONLY, and it is a SETTING not a variable: turn on `webhooks.allowUnverifiedGithub`",
|
|
242
|
+
" # in agent/settings/settings.ts to accept unsigned deliveries locally.",
|
|
243
|
+
" ```",
|
|
244
|
+
"",
|
|
245
|
+
"3. **Install the App** on the repos the agent should live on, ONLY after the redeploy in step 2.",
|
|
246
|
+
" The deployment learns the installation from the App's one `installation` delivery. Before the",
|
|
247
|
+
" redeploy it does not hold the App's webhook secret, so it refuses that delivery and never learns",
|
|
248
|
+
" the installation (OPE-2544).",
|
|
249
|
+
"4. **Ambient mode is on by default** for a positively private or vouched repo. Add the repo to a",
|
|
250
|
+
" memory domain (surface key `github/<owner>/<repo>`) to give it a silo — see",
|
|
251
|
+
" [Memory](../../capabilities/memory.md). To make the repo addressed-only, set",
|
|
252
|
+
" `ambientSupervisor: false` on that domain. A domain can compose repos **with** Slack channels,",
|
|
253
|
+
" Notion docs, and Linear teams: one flag, one shared silo, one posture everywhere in it.",
|
|
254
|
+
"",
|
|
255
|
+
"## Multi-org installs (self-registering)",
|
|
256
|
+
"",
|
|
257
|
+
"The source-control plane mints tokens per **owner**, so it needs an `owner → installation id`",
|
|
258
|
+
"entry for every account the App is installed on. You can set that by hand with",
|
|
259
|
+
"`OE_GITHUB_INSTALLATIONS` (a JSON map) or the single-owner `OE_GITHUB_OWNER` /",
|
|
260
|
+
"`OE_GITHUB_INSTALLATION_ID` pair — and you no longer have to.",
|
|
261
|
+
"",
|
|
262
|
+
"Because GitHub delivers `installation` + `installation_repositories` to every App by default",
|
|
263
|
+
"(no subscription exists to switch on), each install/uninstall registers",
|
|
264
|
+
"itself: `created`/`unsuspend` records the owner's installation id, `deleted`/`suspend` clears it,",
|
|
265
|
+
"and a repo-scope change refreshes it. An org installing your App is then self-service end to end —",
|
|
266
|
+
"no env edit, no redeploy.",
|
|
267
|
+
"",
|
|
268
|
+
"**`OE_GITHUB_INSTALLATIONS` stays authoritative.** The discovered entries are composed *under* the",
|
|
269
|
+
"env map, so anything you pinned by hand always wins, a store outage degrades to exactly the",
|
|
270
|
+
"env-configured set, and a webhook can never re-point an owner you configured yourself. (By the same",
|
|
271
|
+
"rule, uninstalling an org you *also* pinned in env leaves the env entry in place — its mints then",
|
|
272
|
+
"fail loudly at GitHub, which is the honest signal; remove it from the env map to finish the removal.)",
|
|
273
|
+
"",
|
|
274
|
+
"Install and uninstall both write an audit row — `surface.app_installed` / `surface.app_uninstalled`,",
|
|
275
|
+
"with the owner as the workspace — so the install history is queryable over the control plane's",
|
|
276
|
+
"audit route.",
|
|
277
|
+
"",
|
|
278
|
+
"## Ticket actions (state / assignee / labels)",
|
|
279
|
+
"",
|
|
280
|
+
"The agent can also mutate an issue/PR's own state, assignee, and labels —",
|
|
281
|
+
"[Source control § Ticket actions](../../capabilities/source-control.md#ticket-actions-set_state--assign--add_label)",
|
|
282
|
+
"is the canonical doc (these ride the **source-control plane**'s credential, the `OE_GITHUB_*`",
|
|
283
|
+
"App, not this page's bare `GITHUB_*` conversational set — grant it the Issues permission).",
|
|
284
|
+
"These three verbs are known to work on an **issue**. On a **pull request** they are expected to",
|
|
285
|
+
"be refused today, because their credential names only the Issues family — tracked as OPE-1021.",
|
|
286
|
+
"",
|
|
287
|
+
"It can also **file a new issue** with `create_ticket` (`target` = `owner/repo`, defaulting to",
|
|
288
|
+
"this turn's own repo, or to the channel's sole granted repo) — same Issues permission, same",
|
|
289
|
+
"per-channel repo grant, and it always goes through the approval gate first — a card, unless an",
|
|
290
|
+
"operator has explicitly lowered that verb in the approver chain. See",
|
|
291
|
+
"[Source control § Filing new work](../../capabilities/source-control.md#filing-new-work-create_ticket).",
|
|
292
|
+
"",
|
|
293
|
+
"## Reading the conversation",
|
|
294
|
+
"",
|
|
295
|
+
"The agent reads the thread it was called into with the same two verbs it uses on every other",
|
|
296
|
+
"surface: `read_channel` reads the issue-or-PR conversation — the opening post, then the newest",
|
|
297
|
+
"timeline comments — and `read_thread` reads one PR **review thread**, the inline discussion on a",
|
|
298
|
+
"line of the diff. Both take no target: they read the conversation this turn arrived in.",
|
|
299
|
+
"",
|
|
300
|
+
"Three things worth knowing:",
|
|
301
|
+
"",
|
|
302
|
+
"- **A plain issue reads exactly like a PR.** The read goes through `/repos/{repo}/issues/{number}`,",
|
|
303
|
+
" which GitHub serves for both, so nothing is PR-only here. `get_pr_feedback` remains the richer",
|
|
304
|
+
" read for a PR under review — reviews, inline comments and check runs, which a conversation read",
|
|
305
|
+
" does not carry.",
|
|
306
|
+
"- **Another issue reads by target.** `read_channel` and `read_work_channel` read only this",
|
|
307
|
+
" conversation. `read_github_issue` takes `repo` and `number` and reads another issue's opening",
|
|
308
|
+
" post and newest comments, inside the session's repo grant. A `search` hit for such an issue names",
|
|
309
|
+
" it as the road.",
|
|
310
|
+
"- **Only a comment on the diff has a thread.** An issue comment and a PR timeline comment are at the",
|
|
311
|
+
" top level of their conversation, so `read_thread` on one says so rather than reading the timeline",
|
|
312
|
+
" under a thread read's name.",
|
|
313
|
+
"- **A delegated worker reads the same conversation.** The seat reads its own conversation, and the",
|
|
314
|
+
" worker's `read_work_channel` / `read_work_thread` read the conversation its job came from, with no",
|
|
315
|
+
" repo grant (OPE-2491). Every other GitHub work tool still needs the calling scope to grant a repo",
|
|
316
|
+
" ([Connectors § A chat surface can be a work surface too](../../capabilities/connectors-and-providers.md#a-chat-surface-can-be-a-work-surface-too)).",
|
|
317
|
+
"",
|
|
318
|
+
"The read runs on the `OE_GITHUB_*` App installation token, with no fallback to `GITHUB_TOKEN`, so a",
|
|
319
|
+
"repo the App is not installed on cannot be read. The surface is App-only: a deployment that signs",
|
|
320
|
+
"in with a personal access token (`github.auth: \"token\"`, OPE-2530) has no GitHub conversation",
|
|
321
|
+
"surface at all: its webhook route runs only the event-routine fan-out and starts no conversation.",
|
|
322
|
+
"",
|
|
323
|
+
"## Gotchas",
|
|
324
|
+
"",
|
|
325
|
+
"- **A reaction on the agent's comment is read, not delivered — and only in conversations it has",
|
|
326
|
+
" commented in.** GitHub sends no reaction webhook, so the agent looks for reactions on its own",
|
|
327
|
+
" comments when the *next* delivery names that conversation. Two bounds keep that cheap, and both",
|
|
328
|
+
" change what you will see. It looks only in conversations it is *in* — ones this deployment's reply",
|
|
329
|
+
" path has commented in, or ones somebody `@mention`ed it in — because a conversation it is not in",
|
|
330
|
+
" can hold no reaction it would record. The `@mention` half is what covers the replies the framework",
|
|
331
|
+
" posts on its own; what falls outside both is a conversation it only ever answered *ambiently*,",
|
|
332
|
+
" with no `@mention` ever, and has not answered in since this shipped — that one is picked up again",
|
|
333
|
+
" on its next reply there. And each repository runs roughly 60 such polls an hour at most; the",
|
|
334
|
+
" counter is deliberately cheap rather than exact, so a burst of simultaneous deliveries can push an",
|
|
335
|
+
" hour a little over. When a repository passes the ceiling, one **`github.reaction_poll_budget`**",
|
|
336
|
+
" audit row is written for that hour and the rest of the hour's reactions are not read. Query it with",
|
|
337
|
+
" `GET /control/v1/audit?since=<iso>&actions=github.reaction_poll_budget` — a busy repository showing these rows",
|
|
338
|
+
" every hour is the signal that the ceiling, not the feature, is what you are seeing.",
|
|
339
|
+
"- **A reaction the agent has already recorded is skipped, and a store it cannot read skips",
|
|
340
|
+
" everything.** The dedupe is a durable claim per reaction, and it fails *closed*: an unreadable",
|
|
341
|
+
" claim store is treated as \"already recorded\", so no duplicate row is ever written. The cost is",
|
|
342
|
+
" that a store outage stops the feedback signal completely while it lasts, which on its own looks",
|
|
343
|
+
" exactly like a quiet week. Each poll that could not read the store writes one",
|
|
344
|
+
" **`github.reaction_claim_unreadable`** audit row naming how many reactions it skipped. Query it",
|
|
345
|
+
" with `GET /control/v1/audit?since=<iso>&actions=github.reaction_claim_unreadable`. Rows here mean",
|
|
346
|
+
" the operational store, not the feature, is what you are seeing; reactions are recorded on the next",
|
|
347
|
+
" poll after it recovers. **The row covers a *partial* fault, not every one** — it is written to the",
|
|
348
|
+
" same operational store the claim read failed against, so a store that is wholly unreachable loses",
|
|
349
|
+
" this row too. That case is visible instead as the audit drop counter and an",
|
|
350
|
+
" `[open-everywhere:audit] dropped a \"github.reaction_claim_unreadable\" entry …` warning in the",
|
|
351
|
+
" logs. So: rows present means the claim table specifically; the warning means the store.",
|
|
352
|
+
"- **Ambient is on unless a domain turns it off** (`ambientSupervisor: false`), and it never runs",
|
|
353
|
+
" on a repo that isn't positively private or vouched. If non-mention comments get no response, check the domain flag, then the repo's",
|
|
354
|
+
" privacy — and read the record rather than guessing: the first delivery from a repo the",
|
|
355
|
+
" supervisor was never asked about writes a **`github.ambient_skipped`** audit row naming the",
|
|
356
|
+
" surface key, the reason (`domain-refused` — a domain declares `ambientSupervisor: false` and",
|
|
357
|
+
" this repo inherits it — versus `no-domain` — no domain routes the repo and the app has no `org`",
|
|
358
|
+
" domain to inherit from, or the domain set did not load, so the gate failed closed) and the line to change. Query it with",
|
|
359
|
+
" `GET /control/v1/audit?since=<iso>&actions=github.ambient_skipped`. A whole owner at once is",
|
|
360
|
+
" `reach: [\"github/<owner>\"]` on the domain — or, better where it fits, a same-level glob",
|
|
361
|
+
" `reach: [\"github/<owner>/payments-*\"]` plus `exclude` for the repos that must stay out. With",
|
|
362
|
+
" 500 repos the whole-owner entry is tempting, but it confers the domain's bundles on every repo",
|
|
363
|
+
" the org will ever create; the glob is the same ergonomics with strictly less reach.",
|
|
364
|
+
" See the [configuration reference](../configuration-reference.md#memory-domain--silo) and",
|
|
365
|
+
" [Access & scoping](../../how-it-works/access-and-scoping.md#reach-exact-keys-and-containers).",
|
|
366
|
+
"- **The `reply` tool is the only way an answer reaches an issue.** The agent posts mid-turn by",
|
|
367
|
+
" calling `reply`; its turn's closing text is DROPPED and never posted. A turn that delivered",
|
|
368
|
+
" writes a `github.replied` row carrying `route: \"tool\"`.",
|
|
369
|
+
"- **Silence is a first-class outcome.** Most comments correctly get no reply (reserved tier).",
|
|
370
|
+
" Every judged-silent turn is a `github.no_reply` audit row — the surface is working, not",
|
|
371
|
+
" broken. Tune via `engagementTier`, watching the live `no_reply` rate. A **different** quiet",
|
|
372
|
+
" outcome is a `turn.supervisor_prose_dropped` row on the github partition: the agent wrote an",
|
|
373
|
+
" answer as its closing text and never called `reply`, so nothing was posted. That row is a",
|
|
374
|
+
" defect signal, not a tuning signal — read the session transcript it names.",
|
|
375
|
+
"- **An @mention turn can judge silence too.** The `github.no_reply` row is not only an ambient",
|
|
376
|
+
" outcome. A turn woken by a direct @mention can also decide the wake does not warrant an answer;",
|
|
377
|
+
" it then comments NOTHING and writes the same row with `route: \"native\"` and the reason. Those",
|
|
378
|
+
" rows are rare by construction — a member addressed the app — so treat one as worth reading, not",
|
|
379
|
+
" as tuning noise.",
|
|
380
|
+
"- **Mention the slug in full.** App bots aren't in GitHub's `@` autocomplete; the matcher is",
|
|
381
|
+
" text-based (`@<slug>` followed by a non-word character).",
|
|
382
|
+
"- **Webhook verification is fail-closed.** `GITHUB_WEBHOOK_SECRET` unset/wrong → every",
|
|
383
|
+
" delivery is rejected 401 and every leg stays silent — including the installation leg, so a",
|
|
384
|
+
" deploy with a wrong secret silently learns nothing. Check the secret first if installs",
|
|
385
|
+
" aren't registering.",
|
|
386
|
+
"",
|
|
387
|
+
"## Status",
|
|
388
|
+
"",
|
|
389
|
+
"The @mention leg and the routine fan-out are **live-verified**. The ambient leg is built,",
|
|
390
|
+
"unit-tested, and driven by the `J-GH` end-to-end scenario in",
|
|
391
|
+
"`packages/core/scripts/e2e/scenarios.ts` (`suite: \"core\"`, non-optional, judged), with",
|
|
392
|
+
"`J-ENGAGED-github` covering the engaged-follow-up seam. `J-GH` drives the mention reply, the",
|
|
393
|
+
"pickup reaction, the **mention gate** (a non-mention comment gets no reply) with its",
|
|
394
|
+
"audited-silence row, session resume, reply-targeting across two issues, and the signed-forge",
|
|
395
|
+
"route contract. The ambient *wake* on an opted-in repo is `J-ENGAGED-github`'s leg: a mention",
|
|
396
|
+
"engages the issue, a plain follow-up wakes, and `stand_down` stops it. The repository holds the",
|
|
397
|
+
"scenarios, not their results, so read live-verification status off those runs rather than off",
|
|
398
|
+
"this page.",
|
|
399
|
+
"",
|
|
400
|
+
].join("\n"),
|
|
11
401
|
},
|
|
12
402
|
];
|
|
13
403
|
//# sourceMappingURL=docs-generated.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs-generated.js","sourceRoot":"","sources":["../../agent/docs-generated.ts"],"names":[],"mappings":"AAAA,0GAA0G;AAC1G,wFAAwF;AACxF,6FAA6F;AAC7F,sFAAsF;AAItF,MAAM,CAAC,MAAM,aAAa,GAAwB;IAChD;QACE,IAAI,EAAE,gCAAgC;QACtC,
|
|
1
|
+
{"version":3,"file":"docs-generated.js","sourceRoot":"","sources":["../../agent/docs-generated.ts"],"names":[],"mappings":"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"}
|
package/dist/agent/ops.d.ts
CHANGED
package/dist/agent/ops.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ops.d.ts","sourceRoot":"","sources":["../../agent/ops.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ops.d.ts","sourceRoot":"","sources":["../../agent/ops.ts"],"names":[],"mappings":"AAiBA,6FAA6F;AAC7F,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC"}
|
package/dist/agent/ops.js
CHANGED
|
@@ -8,9 +8,14 @@
|
|
|
8
8
|
// stays known to core too (packages/core/agent/scm/config.ts) — the SCM subsystem is a SEPARATE
|
|
9
9
|
// concern that stays in core by doctrine (see register.ts's header) — so this is not a
|
|
10
10
|
// zero-residue fingerprint, only the telemetry probe's own home.
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
//
|
|
12
|
+
// ONE-CLICK APP CREATION (OPE-2529): it also registers the GitHub App manifest flow, which the
|
|
13
|
+
// `surface_app_create` ops tool drives. The manifest and the code exchange live in app-manifest.ts.
|
|
14
|
+
import { registerSurfaceAppCreateFlow, registerSurfaceCredentialProbe } from "@open-everywhere/core/agent/adapter-api-ops.js";
|
|
15
|
+
import { GITHUB_APP_CREATE_FLOW } from "./app-manifest.js";
|
|
16
|
+
/** Register the github ops-plane arms (telemetry presence probe, one-click App creation). */
|
|
13
17
|
export function registerGithubOps() {
|
|
14
18
|
registerSurfaceCredentialProbe("github", () => Boolean(process.env.OE_GITHUB_APP_ID));
|
|
19
|
+
registerSurfaceAppCreateFlow("github", GITHUB_APP_CREATE_FLOW);
|
|
15
20
|
}
|
|
16
21
|
//# sourceMappingURL=ops.js.map
|
package/dist/agent/ops.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ops.js","sourceRoot":"","sources":["../../agent/ops.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,6FAA6F;AAC7F,4FAA4F;AAC5F,gGAAgG;AAChG,iBAAiB;AACjB,EAAE;AACF,6FAA6F;AAC7F,gGAAgG;AAChG,uFAAuF;AACvF,iEAAiE;
|
|
1
|
+
{"version":3,"file":"ops.js","sourceRoot":"","sources":["../../agent/ops.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,6FAA6F;AAC7F,4FAA4F;AAC5F,gGAAgG;AAChG,iBAAiB;AACjB,EAAE;AACF,6FAA6F;AAC7F,gGAAgG;AAChG,uFAAuF;AACvF,iEAAiE;AACjE,EAAE;AACF,+FAA+F;AAC/F,oGAAoG;AAEpG,OAAO,EAAE,4BAA4B,EAAE,8BAA8B,EAAE,MAAM,gDAAgD,CAAC;AAC9H,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,6FAA6F;AAC7F,MAAM,UAAU,iBAAiB;IAC/B,8BAA8B,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC;IACtF,4BAA4B,CAAC,QAAQ,EAAE,sBAAsB,CAAC,CAAC;AACjE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../agent/register.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../agent/register.ts"],"names":[],"mappings":"AAmEA;wEACwE;AACxE,wBAAgB,sBAAsB,IAAI,IAAI,CAkE7C"}
|
package/dist/agent/register.js
CHANGED
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
// acknowledgement's transport (turn-anchor.ts's `postSurfaceText`).
|
|
36
36
|
// No postFiles (no file-attach API) and no setReaction (no raised hand
|
|
37
37
|
// in GitHub's fixed reaction set) — channels/github-message-ops.ts.
|
|
38
|
-
import { registerIdentityMapper, registerCapabilityManifest, registerSurfaceParity, registerProviderEvents, registerReactionSurface, registerPostArm, registerWakeOriginCodec, registerProviderDocs, registerReadAdapter, registerSeatCatchUp, registerWebhookVerifier, registerSurfaceMessageOps, } from "@open-everywhere/core/agent/adapter-api.js";
|
|
38
|
+
import { registerIdentityMapper, registerCapabilityManifest, registerSurfaceParity, registerProviderEvents, registerReactionSurface, registerPostArm, registerWakeOriginCodec, registerProviderDocs, registerReadAdapter, registerSeatCatchUp, registerWebhookVerifier, registerSurfaceMessageOps, registerEventReach, } from "@open-everywhere/core/agent/adapter-api.js";
|
|
39
39
|
import { PROVIDER_DOCS } from "./docs-generated.js";
|
|
40
40
|
import { GITHUB_SURFACE_PARITY } from "./surface-parity.js";
|
|
41
41
|
import { GITHUB_PROVIDER_EVENTS } from "./provider-events.js";
|
|
@@ -45,6 +45,7 @@ import { bindGitHub } from "./channels/github-identity.js";
|
|
|
45
45
|
import { githubPostArm } from "./channels/github-post-arm.js";
|
|
46
46
|
import { githubWakeOriginCodec } from "./channels/github-origin-codec.js";
|
|
47
47
|
import { githubWebhookVerifier } from "./channels/github-webhook-verifier.js";
|
|
48
|
+
import { githubEventsReach } from "./channels/github-event-reach.js";
|
|
48
49
|
import { githubReadAdapter } from "./channels/github-read.js";
|
|
49
50
|
import { githubSeatCatchUpFetch, GITHUB_TIMESTAMP_PRECISION_MS } from "./channels/github-catch-up.js";
|
|
50
51
|
import { githubMessageOps } from "./channels/github-message-ops.js";
|
|
@@ -94,6 +95,10 @@ export function registerGithubProvider() {
|
|
|
94
95
|
// declare `source: "github"` and be verified the way GitHub signs. Changes no existing route —
|
|
95
96
|
// the native github webhook path keeps its own inline gate.
|
|
96
97
|
registerWebhookVerifier(githubWebhookVerifier);
|
|
98
|
+
// Event reach (OPE-2547): core registers GitHub's event normalizer on every deployment, so only this
|
|
99
|
+
// bundle, which mounts the native route, can say whether a delivery reaches the routine fan-out. The seat
|
|
100
|
+
// offers a GitHub watch only when it does, and an armed GitHub routine's room is told when it stops.
|
|
101
|
+
registerEventReach("github", () => githubEventsReach());
|
|
97
102
|
// Shipped-manual plane (OPE-138): this bundle's own setup runbook (docs/deploy/surfaces/github.md,
|
|
98
103
|
// compiled into ./docs-generated.ts because docs/ is not on disk at runtime). De-select the bundle
|
|
99
104
|
// and the module leaves the import graph; registerProviderDocs re-checks the selection gate anyway.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register.js","sourceRoot":"","sources":["../../agent/register.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,mGAAmG;AACnG,mGAAmG;AACnG,gGAAgG;AAChG,iGAAiG;AACjG,EAAE;AACF,oGAAoG;AACpG,oGAAoG;AACpG,yGAAyG;AACzG,2FAA2F;AAC3F,mGAAmG;AACnG,gDAAgD;AAChD,8DAA8D;AAC9D,EAAE;AACF,6DAA6D;AAC7D,4FAA4F;AAC5F,kGAAkG;AAClG,sGAAsG;AACtG,uGAAuG;AACvG,wGAAwG;AACxG,wCAAwC;AACxC,mGAAmG;AACnG,8DAA8D;AAC9D,4FAA4F;AAC5F,qGAAqG;AACrG,0FAA0F;AAC1F,mGAAmG;AACnG,8FAA8F;AAC9F,gDAAgD;AAChD,2FAA2F;AAC3F,4FAA4F;AAC5F,4FAA4F;AAC5F,gGAAgG;AAChG,0FAA0F;AAC1F,iGAAiG;AACjG,oGAAoG;AACpG,iGAAiG;AAEjG,OAAO,EACL,sBAAsB,EACtB,0BAA0B,EAC1B,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,EACvB,eAAe,EACf,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,EACvB,yBAAyB,
|
|
1
|
+
{"version":3,"file":"register.js","sourceRoot":"","sources":["../../agent/register.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"surface-parity.d.ts","sourceRoot":"","sources":["../../agent/surface-parity.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,4CAA4C,CAAC;AAE3F,eAAO,MAAM,qBAAqB,EAAE,
|
|
1
|
+
{"version":3,"file":"surface-parity.d.ts","sourceRoot":"","sources":["../../agent/surface-parity.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,4CAA4C,CAAC;AAE3F,eAAO,MAAM,qBAAqB,EAAE,wBA0GnC,CAAC"}
|
|
@@ -62,6 +62,7 @@ export const GITHUB_SURFACE_PARITY = {
|
|
|
62
62
|
// 🔴 BARE, NOT `{ supported: "…" }`. A noted cell is exempt from the overclaim arm, and the
|
|
63
63
|
// arm is the point: drop this bundle's text transport and the notice silently stops arriving.
|
|
64
64
|
"judge-lift-notice": "supported",
|
|
65
|
+
"out-of-office-cover": { unsupported: "not built yet — the issue and pull request room routes do not call `coverForWake`" },
|
|
65
66
|
"name-drop-mention": { unsupported: "not built yet — the ambient supervisor already reads every comment, so a name-drop match adds no wake" },
|
|
66
67
|
// 🔴 EVERY WAKE LEG ADMITS `created` ONLY, and that is the narrower true claim. The delivery DOES
|
|
67
68
|
// reach OE code — `wrapRoute` runs the fan-out, the installation leg and the reaction poll on an
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"surface-parity.js","sourceRoot":"","sources":["../../agent/surface-parity.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"surface-parity.js","sourceRoot":"","sources":["../../agent/surface-parity.ts"],"names":[],"mappings":"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"}
|