docs: handbook states what the code does (fact sweep fixes)
This commit is contained in:
parent
1042bf65db
commit
409e7ee5a0
7 changed files with 64 additions and 69 deletions
|
|
@ -41,8 +41,8 @@ should cover._ `topology::all_agents` is the only reader that matters.
|
||||||
|
|
||||||
That reader is a permission boundary: the set it returns is what an agent
|
That reader is a permission boundary: the set it returns is what an agent
|
||||||
holding the `ManageRootAgent` permission gets bind-mounted (each other
|
holding the `ManageRootAgent` permission gets bind-mounted (each other
|
||||||
agent's `state` read-write and `config` read-only; never `harness`). An
|
agent's `state` dir, read-write, at `/agents/<name>/state`; never `config` or
|
||||||
agent holding no permission sees its own dirs and nothing else:
|
`harness`). An agent holding no permission sees its own dirs and nothing else:
|
||||||
`ManageRootAgent` is the only grant that reaches another agent's state
|
`ManageRootAgent` is the only grant that reaches another agent's state
|
||||||
dir. See
|
dir. See
|
||||||
[`persistence.md`](persistence.md)'s _Cross-agent access to state._
|
[`persistence.md`](persistence.md)'s _Cross-agent access to state._
|
||||||
|
|
@ -66,12 +66,14 @@ system-level facts live.
|
||||||
degrades safely to "no agents" (covers a fresh install that hasn't
|
degrades safely to "no agents" (covers a fresh install that hasn't
|
||||||
synced yet).
|
synced yet).
|
||||||
- **Reconcile** — runs alongside the periodic meta/flake regeneration.
|
- **Reconcile** — runs alongside the periodic meta/flake regeneration.
|
||||||
Adds newly spawned agents, drops removed ones. Reconcile keeps agents
|
Adds newly spawned agents, drops removed ones. The live set is the
|
||||||
whose config repo exists but that haven't spawned yet, so the gap until
|
hive's existing agent containers plus the agent that spawns now; reconcile
|
||||||
the container appears doesn't churn the file.
|
drops an agent whose config repo exists but whose container doesn't.
|
||||||
|
|
||||||
No write API and no operator verb reach this file. Reconcile derives it
|
No write API and no operator verb reach this file. Reconcile derives it
|
||||||
from which agents exist, so the next pass overwrites a hand edit.
|
from which agents exist, so the next pass overwrites a hand edit that
|
||||||
|
parses. It refuses to write over a file it can't parse and fails
|
||||||
|
instead, so a broken hand edit stays until someone fixes it.
|
||||||
|
|
||||||
See `hive-c0re/src/agent_config/topology.rs` and `hive-c0re/src/meta.rs`'s
|
See `hive-c0re/src/agent_config/topology.rs` and `hive-c0re/src/meta.rs`'s
|
||||||
module docs for the exact call chain.
|
module docs for the exact call chain.
|
||||||
|
|
@ -99,9 +101,9 @@ state dirs work as for every other agent.
|
||||||
[`docs/4-implementation/turn-loop/mcp.md`](../../4-implementation/turn-loop/mcp.md#waking-the-agent-from-inside-the-container)).
|
[`docs/4-implementation/turn-loop/mcp.md`](../../4-implementation/turn-loop/mcp.md#waking-the-agent-from-inside-the-container)).
|
||||||
- **Storage/mounts** — the `manage_root_agent` permission, which the swarm
|
- **Storage/mounts** — the `manage_root_agent` permission, which the swarm
|
||||||
UI's setup assistant creates ruth with, gets a container
|
UI's setup assistant creates ruth with, gets a container
|
||||||
`/var/lib/hyperhive/agents` bind-mounted RW at `/agents` (so it can
|
each other agent's `state` dir bind-mounted RW at
|
||||||
manage any agent's state dir; config isn't mounted, since a real
|
`/agents/<name>/state` (so it can manage any agent's state dir; config
|
||||||
config change is a PR from a clone), plus an RO mount for
|
isn't mounted, since a real config change is a PR from a clone), plus an RO mount for
|
||||||
`/meta` (the hive's topology and limits files). Any agent holding it gets the same mounts.
|
`/meta` (the hive's topology and limits files). Any agent holding it gets the same mounts.
|
||||||
- **Prompt** — identical for every container but one block (below):
|
- **Prompt** — identical for every container but one block (below):
|
||||||
`prompts/system.md`
|
`prompts/system.md`
|
||||||
|
|
|
||||||
|
|
@ -70,26 +70,21 @@ merged by an operator on the forge (see [Config changes](#config-changes)).
|
||||||
### Reminder delivery: file-path semantics
|
### Reminder delivery: file-path semantics
|
||||||
|
|
||||||
A reminder may carry a `file_path` (the agent-visible path inside its
|
A reminder may carry a `file_path` (the agent-visible path inside its
|
||||||
container, for example `/agents/<name>/state/foo.md`). On delivery hive-c0re:
|
container, for example `/agents/<name>/state/foo.md`). The agent's own
|
||||||
|
harness (`hive-agent`, inside the container) delivers the reminder when it
|
||||||
|
falls due:
|
||||||
|
|
||||||
1. **Translates** the container path to the host path
|
1. **Validates** the path: it must resolve under the agent's own state
|
||||||
(`/var/lib/hyperhive/agents/<name>/state/foo.md`) so c0re can write
|
directory, with no `..` components and a non-empty relative tail. On
|
||||||
from outside the container.
|
rejection, or on a write failure, the harness delivers the original
|
||||||
2. **Validates** the path: rejects anything outside the agent's own state
|
message inline with a warning note — the reminder still fires.
|
||||||
subtree, containing `..` (path traversal), or with an empty relative
|
2. **Writes the body to disk** at that path and delivers a short pointer
|
||||||
tail. On rejection hive-c0re skips the write and delivers the
|
message in its place, keeping the agent's inbox / wake-prompt small
|
||||||
original message inline with a warning — the reminder still fires.
|
while the agent reads the bulky payload out of band.
|
||||||
3. **Defends against symlink escape**: after `create_dir_all`, hive-c0re
|
|
||||||
canonicalizes the parent dir and re-verifies it lives under the agent's host
|
|
||||||
state root. hive-c0re opens the final file with
|
|
||||||
`O_NOFOLLOW | O_CREAT | O_TRUNC` so an existing symlink at the
|
|
||||||
basename can't redirect the write to an arbitrary host path.
|
|
||||||
4. **Writes the body to disk** and delivers a short pointer message in its
|
|
||||||
place, keeping the agent's inbox / wake-prompt small while the agent
|
|
||||||
reads the bulky payload out of band.
|
|
||||||
|
|
||||||
`Broker::deliver_reminders_batch` handles atomicity of the inbox INSERT + `reminders.sent_at` UPDATE; the scheduler only computes the
|
The write happens inside the agent's container, so hive-c0re takes no
|
||||||
body strings before calling it.
|
part in it and there is no symlink-escape defence: the harness is the
|
||||||
|
agent, and the container boundary is the sandbox.
|
||||||
|
|
||||||
### Destroy semantics
|
### Destroy semantics
|
||||||
|
|
||||||
|
|
@ -122,8 +117,9 @@ deploys.
|
||||||
|
|
||||||
What `hive-c0re` still keeps under `/var/lib/hyperhive/meta/` is plain
|
What `hive-c0re` still keeps under `/var/lib/hyperhive/meta/` is plain
|
||||||
state, bound read-only into the root agent's container as `/meta`:
|
state, bound read-only into the root agent's container as `/meta`:
|
||||||
`topology.json`, the swarm resource limits, and the permission seed files of a
|
`topology.json` and the swarm resource limits. The permissions the swarm
|
||||||
hive that predates the swarm's permissions. `agent_set::refresh(agents:
|
grants live outside it, in `/var/lib/hyperhive/swarm-agent-permissions.json`.
|
||||||
|
`agent_set::refresh(agents:
|
||||||
&[AgentSpec])` keeps `topology.json`, the gateway's agent-socket map and its
|
&[AgentSpec])` keeps `topology.json`, the gateway's agent-socket map and its
|
||||||
nginx include in line with the live agents. `provision_container`, `destroy`,
|
nginx include in line with the live agents. `provision_container`, `destroy`,
|
||||||
`rebuild` and the startup migration call it. It refuses an empty agent list,
|
`rebuild` and the startup migration call it. It refuses an empty agent list,
|
||||||
|
|
@ -243,8 +239,8 @@ mounts via `set_nspawn_flags`:
|
||||||
- `/var/lib/hyperhive/meta/` → `/meta/` (RO) — the hive's plain state
|
- `/var/lib/hyperhive/meta/` → `/meta/` (RO) — the hive's plain state
|
||||||
(topology, swarm limits).
|
(topology, swarm limits).
|
||||||
|
|
||||||
An agent without the permission only has its direct children's config
|
An agent without the permission gets only its own `state`, `harness` and
|
||||||
dirs.
|
`work` dirs: no other agent's dirs and no `/meta`.
|
||||||
|
|
||||||
⚠️ nspawn bakes bind flags at container start, so hive-c0re restarts
|
⚠️ nspawn bakes bind flags at container start, so hive-c0re restarts
|
||||||
an agent, after its current turn, when its `manage_root_agent` changes.
|
an agent, after its current turn, when its `manage_root_agent` changes.
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@ keeps its state, purging it doesn't.**
|
||||||
|
|
||||||
- **`DESTR0Y`** (the default action) stops and removes the container
|
- **`DESTR0Y`** (the default action) stops and removes the container
|
||||||
but keeps everything on disk — config history, claude login, `/state/`
|
but keeps everything on disk — config history, claude login, `/state/`
|
||||||
notes, harness data. The agent shows up as a tombstone (K3PT ST4T3 on
|
notes, harness data. The agent shows up as a tombstone (the K3PT ST4T3
|
||||||
the C0R3 page); `swarmctl agent create` with the same name and hive
|
tab of the dashboard); `swarmctl agent create` with the same name and hive
|
||||||
recreates it from the kept state, **no re-login needed**.
|
recreates it from the kept state, **no re-login needed**.
|
||||||
- **`PURG3`** (opt-in, from the dashboard or `hivectl agent <name>
|
- **`PURG3`** (opt-in, from the dashboard or `hivectl agent <name>
|
||||||
destroy --purge`) is `DESTR0Y` plus wiping all of it — config
|
destroy --purge`) is `DESTR0Y` plus wiping all of it — config
|
||||||
|
|
@ -235,8 +235,8 @@ Unusually, it's read and written from **both** sides of the harness
|
||||||
bind-mount, and that's the whole design: the harness stats it
|
bind-mount, and that's the whole design: the harness stats it
|
||||||
in-container via `hive-agent`'s `paths::paused_marker`, while hive-c0re
|
in-container via `hive-agent`'s `paths::paused_marker`, while hive-c0re
|
||||||
stats it on the host (`Coordinator::is_paused`) to populate the
|
stats it on the host (`Coordinator::is_paused`) to populate the
|
||||||
`paused` field on the agent card, and creates/removes it
|
`paused` field on the agent card, and asks hive-priv to create or remove it
|
||||||
(`Coordinator::set_paused`) for `hivectl agent <name> pause|resume` and the
|
(`Coordinator::set_paused`; hive-c0re itself is unprivileged) for `hivectl agent <name> pause|resume` and the
|
||||||
dashboard toggle. Because the file itself is the only shared state
|
dashboard toggle. Because the file itself is the only shared state
|
||||||
there's no protocol between them, no round-trip into the container, and
|
there's no protocol between them, no round-trip into the container, and
|
||||||
pause keeps working when the harness is wedged or the container is
|
pause keeps working when the harness is wedged or the container is
|
||||||
|
|
|
||||||
|
|
@ -44,10 +44,16 @@ at a given viewport width. Two columns:
|
||||||
- **Pills cluster** (`.agent-header-pills`, right-aligned): status
|
- **Pills cluster** (`.agent-header-pills`, right-aligned): status
|
||||||
badges (`StatusChips.tsx`) and flyout triggers together in one row,
|
badges (`StatusChips.tsx`) and flyout triggers together in one row,
|
||||||
so the header reads as one identity zone + one status/actions zone:
|
so the header reads as one identity zone + one status/actions zone:
|
||||||
- **Alive badge**: `● alive` (green) / `⊘ rate limited` (red) /
|
- **Status badge**, one badge for liveness and turn state: `● alive`
|
||||||
`◌ needs login` / `◌ logging in` / `○ offline` / `… connecting`.
|
(green) / `⊘ rate limited` (red) / `◌ needs login` / `◌ logging in` /
|
||||||
- **State badge**: `💤 idle` / `🧠 thinking` / `📦 compacting` /
|
`○ offline` / `… connecting` / `💤 idle` / `🧠 thinking` /
|
||||||
`○ offline` / `… booting` + age suffix.
|
`📦 compacting` / `… booting` + age suffix, or paused. Selecting it
|
||||||
|
opens a menu: `⏸ pause` / `▶ resume` (via the same hive-c0re-owned
|
||||||
|
`/api/pause/<name>` / `/api/resume/<name>` endpoints the dashboard
|
||||||
|
uses; pausing needs a write this unprivileged process can't make
|
||||||
|
directly), `■ cancel turn` (only while a turn is running),
|
||||||
|
`↻ new session` and `🔓 logout`. Cancel turn, new session and logout
|
||||||
|
need a second selection to confirm.
|
||||||
- **Model and effort badges** (`model · <name>`, `effort · <level>`):
|
- **Model and effort badges** (`model · <name>`, `effort · <level>`):
|
||||||
display only. Each tooltip says where the value comes from
|
display only. Each tooltip says where the value comes from
|
||||||
(`state.model_source` / `state.effort_source`: set on the swarm,
|
(`state.model_source` / `state.effort_source`: set on the swarm,
|
||||||
|
|
@ -65,10 +71,6 @@ at a given viewport width. Two columns:
|
||||||
- **Ctx / cost badges**: `ctx · 142k` (last inference's prompt size,
|
- **Ctx / cost badges**: `ctx · 142k` (last inference's prompt size,
|
||||||
tooltip shows % of context window) / `cost · 1.3M` (cumulative
|
tooltip shows % of context window) / `cost · 1.3M` (cumulative
|
||||||
tokens billed across every inference in the last turn).
|
tokens billed across every inference in the last turn).
|
||||||
- **Pause badge** (`⏸ pause` / `▶ resume`): toggles via the same
|
|
||||||
hive-c0re-owned `/api/pause/<name>` / `/api/resume/<name>`
|
|
||||||
endpoints the dashboard uses (pausing needs a write this
|
|
||||||
unprivileged process can't make directly).
|
|
||||||
- **Inbox / todos pills** (`📬 inbox · N` / `📋 todos · N`): hidden
|
- **Inbox / todos pills** (`📬 inbox · N` / `📋 todos · N`): hidden
|
||||||
when empty; selecting it opens the matching flyout in the side panel.
|
when empty; selecting it opens the matching flyout in the side panel.
|
||||||
- **Profile avatar**: the signed-in user's initial, opening a popover with
|
- **Profile avatar**: the signed-in user's initial, opening a popover with
|
||||||
|
|
@ -162,7 +164,7 @@ If the todo store errors or doesn't answer for any id, the endpoint returns
|
||||||
## Live view
|
## Live view
|
||||||
|
|
||||||
Each agent runs an `events::Bus`: a `tokio::sync::broadcast<LiveEvent>`
|
Each agent runs an `events::Bus`: a `tokio::sync::broadcast<LiveEvent>`
|
||||||
plus a sqlite-backed history at `/state/hyperhive-events.sqlite`.
|
plus a sqlite-backed history at `/harness/hyperhive-events.sqlite`.
|
||||||
The harness emits `TurnStart { from, body, unread }`,
|
The harness emits `TurnStart { from, body, unread }`,
|
||||||
`Stream(value)` (one per parsed stream-json line), `Note`,
|
`Stream(value)` (one per parsed stream-json line), `Note`,
|
||||||
`TurnEnd { ok, note }`. Each event also carries a `ts` (unix
|
`TurnEnd { ok, note }`. Each event also carries a `ts` (unix
|
||||||
|
|
@ -238,10 +240,9 @@ on this page calls it now.
|
||||||
|
|
||||||
Successful POSTs return 200 (no 303 redirects). Error responses
|
Successful POSTs return 200 (no 303 redirects). Error responses
|
||||||
use semantic status codes: **400** for missing/malformed input
|
use semantic status codes: **400** for missing/malformed input
|
||||||
(`body` required, unknown model name, unrecognised effort level),
|
(`/api/todos/mark-done` with no todo ids), **500** only for genuine
|
||||||
**409** for retryable state conflicts (turn in flight when
|
server/transport failures. `/compact` never conflicts: it queues
|
||||||
`/compact` fires), **500** only for genuine server/transport
|
and runs at the end of the current turn. The matching
|
||||||
failures. The matching
|
|
||||||
mutations fire `LiveEvent` variants on the per-agent bus, so the
|
mutations fire `LiveEvent` variants on the per-agent bus, so the
|
||||||
client doesn't refetch `/api/state` on submit — the SSE stream
|
client doesn't refetch `/api/state` on submit — the SSE stream
|
||||||
delivers the new state faster anyway.
|
delivers the new state faster anyway.
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ matrix accounts, the controller's job graph — are on the
|
||||||
|
|
||||||
hive-c0re serves the dashboard at `/`.
|
hive-c0re serves the dashboard at `/`.
|
||||||
It has a fixed chrome header at the top and a `<main>` that shows exactly
|
It has a fixed chrome header at the top and a `<main>` that shows exactly
|
||||||
one tab pane at a time. The URL hash (`#agents`, `#rebuild`, `#meta`,
|
one tab pane at a time. The URL hash (`#agents`, `#rebuild`,
|
||||||
`#kept`) drives which pane is
|
`#kept`) drives which pane is
|
||||||
active; hash changes don't reload the page.
|
active; hash changes don't reload the page.
|
||||||
|
|
||||||
|
|
@ -428,7 +428,8 @@ the pages menu's **api docs** entry), with the raw spec at `/api/openapi.json`.
|
||||||
It's a growing supplement, not yet a full replacement for the list
|
It's a growing supplement, not yet a full replacement for the list
|
||||||
below — some endpoints aren't in it yet.
|
below — some endpoints aren't in it yet.
|
||||||
|
|
||||||
- `POST /api/{rebuild,kill,restart,start,destroy}/{name}` — lifecycle.
|
- `POST /api/{rebuild,kill,restart,start,destroy,pause,resume}/{name}` —
|
||||||
|
lifecycle.
|
||||||
`destroy` accepts `purge=on` to also wipe state dirs.
|
`destroy` accepts `purge=on` to also wipe state dirs.
|
||||||
- `POST /api/purge-tombstone/{name}` — wipe a tombstone's state dirs.
|
- `POST /api/purge-tombstone/{name}` — wipe a tombstone's state dirs.
|
||||||
- `POST /api/rebuild-queue/{id}/cancel` — drop a `Queued` entry.
|
- `POST /api/rebuild-queue/{id}/cancel` — drop a `Queued` entry.
|
||||||
|
|
@ -441,6 +442,10 @@ below — some endpoints aren't in it yet.
|
||||||
not yet delivered and sets `acked_at = now`. Returns
|
not yet delivered and sets `acked_at = now`. Returns
|
||||||
`{ "marked": N }`. Agent name validated against
|
`{ "marked": N }`. Agent name validated against
|
||||||
`[a-z0-9_-]`, 1-63 chars; 400 on bad input.
|
`[a-z0-9_-]`, 1-63 chars; 400 on bad input.
|
||||||
|
- `GET /api/build-logs?limit=N` — most-recent build log headers across
|
||||||
|
all agents (`limit` defaults to 30).
|
||||||
|
- `GET /api/build-log/{node_id}` and `/api/build-log/{node_id}/raw` — the
|
||||||
|
build log of one job-queue node, as JSON and as `text/plain`.
|
||||||
- `GET /api/build-logs/{agent}?limit=N` — most-recent build log
|
- `GET /api/build-logs/{agent}?limit=N` — most-recent build log
|
||||||
headers for one agent, newest first. Returns
|
headers for one agent, newest first. Returns
|
||||||
`Vec<BuildLogHeader>` (JSON): `id`, `agent`, `kind`, `cmdline`,
|
`Vec<BuildLogHeader>` (JSON): `id`, `agent`, `kind`, `cmdline`,
|
||||||
|
|
@ -458,11 +463,6 @@ below — some endpoints aren't in it yet.
|
||||||
- `GET /api/build-logs/id/{id}/raw` — raw concatenated
|
- `GET /api/build-logs/id/{id}/raw` — raw concatenated
|
||||||
stdout+stderr as `text/plain`. Works on both finished and in-progress
|
stdout+stderr as `text/plain`. Works on both finished and in-progress
|
||||||
build logs.
|
build logs.
|
||||||
- `GET /api/reminders` — list pending reminders for the
|
|
||||||
dashboard's queued-reminders panel.
|
|
||||||
- `POST /api/cancel-reminder/{id}` — hard-delete a pending reminder.
|
|
||||||
- `POST /api/retry-reminder/{id}` — re-arm a reminder whose delivery
|
|
||||||
failed (clears the failure state so the scheduler retries).
|
|
||||||
|
|
||||||
- `GET /api/dashboard/stream` — unified live event channel:
|
- `GET /api/dashboard/stream` — unified live event channel:
|
||||||
broker `sent` / `delivered`, plus the mutation events listed
|
broker `sent` / `delivered`, plus the mutation events listed
|
||||||
|
|
@ -498,12 +498,6 @@ payload):
|
||||||
terminal-history trim). Unlike the snapshot events below it ships
|
terminal-history trim). Unlike the snapshot events below it ships
|
||||||
no state at all: the client re-fetches `GET /api/jobq/graph`, which
|
no state at all: the client re-fetches `GET /api/jobq/graph`, which
|
||||||
is where it reads the queue from cold too.
|
is where it reads the queue from cold too.
|
||||||
- `reminders_changed` (seq, reminders: `Vec<PendingReminder>`) —
|
|
||||||
full snapshot of all pending reminders. Emitted after every
|
|
||||||
reminder mutation: agent `remind` calls (`agent_server`),
|
|
||||||
operator cancel / retry (`/api/system/reminders/*`), `cancel_loose_end`
|
|
||||||
with Reminder kind, and the scheduler tick after each delivery
|
|
||||||
batch (`reminder_scheduler`).
|
|
||||||
- `tombstones_changed` (seq, tombstones: `Vec<TombstoneView>`) —
|
- `tombstones_changed` (seq, tombstones: `Vec<TombstoneView>`) —
|
||||||
full snapshot of destroyed-but-state-kept agents. Emitted on
|
full snapshot of destroyed-but-state-kept agents. Emitted on
|
||||||
destroy, purge, and revive. The K3PT ST4T3 tab subscribes.
|
destroy, purge, and revive. The K3PT ST4T3 tab subscribes.
|
||||||
|
|
|
||||||
|
|
@ -63,9 +63,10 @@ resume drains the backlog rather than dropping it. Points worth knowing:
|
||||||
- **Sticky.** The marker lives on the persistent harness mount, so a
|
- **Sticky.** The marker lives on the persistent harness mount, so a
|
||||||
paused agent stays paused across a container restart — and pausing a
|
paused agent stays paused across a container restart — and pausing a
|
||||||
_stopped_ agent makes it come up parked.
|
_stopped_ agent makes it come up parked.
|
||||||
- **Not a DAG.** Unlike `restart`/`stop`, there's no container operation
|
- **A DAG, with an acknowledgement wait.** `pause` creates a DAG whose drain
|
||||||
to sequence, so it applies immediately with nothing to wait on.
|
node waits for the harness to acknowledge the marker (giving up after
|
||||||
- **Stopping a paused agent is still fast.** hivectl skips the graceful-stop
|
3 minutes); `--no-wait` returns once the DAG exists.
|
||||||
|
- **Stopping a paused agent is still fast.** hive-c0re skips the graceful-stop
|
||||||
handshake for a paused agent (it would never answer), which
|
handshake for a paused agent (it would never answer), which
|
||||||
is safe precisely because the pause check sits at the top of the loop:
|
is safe precisely because the pause check sits at the top of the loop:
|
||||||
a paused agent has no turn in flight to checkpoint.
|
a paused agent has no turn in flight to checkpoint.
|
||||||
|
|
|
||||||
|
|
@ -484,9 +484,10 @@ would take delivery away from the first rather than add a recipient.
|
||||||
<!-- vale write-good.Passive = NO -->
|
<!-- vale write-good.Passive = NO -->
|
||||||
|
|
||||||
**The `agent-configs` org is on it too.** The controller's hook is the
|
**The `agent-configs` org is on it too.** The controller's hook is the
|
||||||
only one that acts on config PRs. Each hive deletes its own
|
only one that acts on config PRs. No hive serves `/webhook/config-pr`
|
||||||
`/webhook/config-pr` org hook on startup, since a route no hive serves
|
any more and none deletes it: a hook of that name left on the org by an
|
||||||
would otherwise sit on the org collecting failed deliveries. Removing
|
older release stays registered and collects failed deliveries until an
|
||||||
|
operator deletes it by hand. Removing
|
||||||
the controller's hook stops forge-UI merges from deploying until its
|
the controller's hook stops forge-UI merges from deploying until its
|
||||||
next start recreates it.
|
next start recreates it.
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue