Skip to content

Commit 23feaaf

Browse files
eaitbrahimclaude
andauthored
console: Audit & Setup view; Timeline, Setup, Venues, Balances and Plans retired -- four views (#13 PR4) (#966)
* timeline: blocked on system rows; kind=keel composite filter Cycle rows now name their blocked count between signals and entered ("blocked unknown" when a cycle object carries none). gather_timeline learns one composite kind word, keel = {system, attestation}, echoed back and listed first in kinds_present when either member is present; the CSV export resolves it the same way so the file matches the screen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * console: Audit & Setup view; Timeline, Setup, Venues, Balances and Plans retired One auditView at /audit reads /api/setup (primary, needs no database, so the stopped view's setup link lands somewhere that answers), /api/timeline and /api/venues. Its sections are exported builders: timelineSection (opens on kind=keel, seeded once at boot; chips, CSV, chain verdict), setupSection (stage tabs, page-level job panel; the CSRF token is still remembered from this reading) and readinessSection (readiness only). The nav is Pulse, Holdings, Rules, Audit & Setup plus Docs. /setup, /timeline, /venues, /balances and /plans join RETIRED_CLIENT_ROUTES; main.js's MOVED_ROUTES sends the first three to /audit, the rest land on Pulse. /api/balances, /api/plans, their readers and payload builders, keel/commands/plans.py and keel/commands/balances.py (no CLI reads either) and their tests are removed, with positions.with_readiness (its only caller was gather_balances) and docs.TERMS's venue 'session'. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * gates: say where the Tier 1 phrase is actually public The docstring said "the modal prints it"; no resume modal exists. The phrase is a literal in TIER1_ACTIONS; release is keel resume / keel resume-entries at a terminal behind the TTY gate. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * serve: help and runbook name the POST surface instead of claiming GET/HEAD only keel serve --help said the server implements GET and HEAD and nothing else; do_POST has served /api/setup/<step> since #437 and the gate routes (halt, resume, resume-entries) since #781. The help now names each POST and how it is gated, and a test derives the expected routes from server.py's constants and gates.TIER1_ACTIONS so it cannot drift. The operator runbook carried the same claim and is corrected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(web): ROUTES sweep covers every data GET and cannot drift again ROUTES, the secret-leak and create-nothing sweep, listed 7 of the API routes; timeline, the CSV export, the four research reads and dca-plan were never swept. A new test holds ROUTES equal to api.API_ROUTES plus CSV_EXPORT_PATH, minus /api/balances and /api/plans (being removed in a parallel change; _ROUTES_BEING_REMOVED is marked for deletion) and the SSE stream. The sweeps now assert each route actually answered, so they cannot pass by reading 404 bodies. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(web): the ROUTES sweep needs no exclusion now /api/balances and /api/plans are gone Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: the four console views The runbook's console section names Pulse, Holdings, Rules and Audit & Setup, with a paragraph each, and says where the retired Timeline, Setup, Venues, Balances and Plans views went (pinned in test_runbook_console). architecture.md and the go-live runbook say the same. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * serve: the startup line names the console, not a read-only view The console halts the engine and runs setup steps, so 'keel is serving a read-only view' was false. Pinned in test_serve_command. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(web): pin routeFor's moved-name lookup whole A lookup whose result was discarded left /setup landing on Pulse with the suite green (mutation run). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(web): the composite-kind export test tolerates an engine log in the cwd (#964) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(console): keep the applied keel chip, say when the engine log is missing, pin the timeline error split The keel chip stays on the bar when it is the applied kind, so a window with only trades and flows no longer opens on an empty table with no current chip. The timeline wire carries the engine-log status and the page renders one line when the log did not reach it. The no-database / read-failed branches of timelineSection are pinned to their own output. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(console): comments and docstrings this PR made false; drop dead _JOB_REFRESH_SEC Module docstrings, the KeelHandler docstring, the PWA manifest description and sw.js no longer say the console is read-only or GET-only: it halts and runs setup steps. Comments naming deleted venueCard / balances view are reworded. The unread _JOB_REFRESH_SEC is removed. A test pins the manifest description. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: living docs say the console halts and runs setup; dated notes on historical docs Runbook, remote-access and the web UI spec are rewritten to be true (four views, gates POST surface, HALT from a tunnel, no release control drawn). The PR plan, evolution plan and presentation get short 2026-10-11 correction notes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(runbook): the console section names the HALT route instead of "no verb" The runbook no longer says the server implements no verb that reaches a capability-increasing action (it serves halt and two phrase-gated releases), so the pin asserts the true property of the server and the routes that write. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(console): round-2 review - write-surface wording, engine-log state, capability text N1: five docstrings no longer say do_POST routes only through setup.ACTIONS; a source scan pins it. N2: the engine-log note state follows TimelineReport.log_gap, so the page and the CSV agree (empty warns); each status is pinned to its exact sentence and state. N3: kinds_present says keel also leads when it is the applied filter. N4: the runbook count is the registry's (ten) and the /api/gates/ sentence is asserted whole. N5: web capability rows name POST /api/gates/<key>, not buttons the console never drew. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 52a9143 commit 23feaaf

48 files changed

Lines changed: 1376 additions & 3087 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎docs/architecture.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ published. Every architectural decision below is tested against that constitutio
1818
It ships today in three shapes, all from one artifact set:
1919

2020
- **CLI** — `keel` commands over a local database (the operator's terminal).
21-
- **Local web console** — `keel serve`, loopback-only, zero-dependency static UI.
21+
- **Local web console** — `keel serve`, loopback-only, zero-dependency static UI: four engine views (Pulse, Holdings, Rules, Audit & Setup).
2222
- **Desktop distribution** — unsigned installers plus the `keel update` self-updater.
2323

2424
## 2. Package and module architecture

‎docs/evolution-plan.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,8 @@ itself is a moat, because every competitor's UI depends on hiding what keel show
250250
- Feature-gating inside the engine. The Plans page ships **inverted** (#706): a
251251
transparency artifact stating what is free forever and why — not a paywall matrix.
252252

253+
> **Correction (2026-10-11).** The console is now four views (Pulse, Holdings, Rules, Audit & Setup). The Venues and Plans views named above are retired: venue readiness lives on Audit & Setup, and the declared capabilities stay with `keel brokers list`. Holdings has no cancel control (cancelling stays `keel orders cancel`), so "one-click even from the web" below describes the 2026-08 design, not the present console. The console's one-tap action is HALT, on Pulse.
254+
253255
### What keel does beyond parity
254256

255257
- **The cancel asymmetry** (#707): cancelling an entry is refusing risk — frictionless,

‎docs/go-live-runbook.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ lists, observed rather than assumed, in three kinds:
2828
are **never** reported as done, because a green check that verifies nothing turns an open risk
2929
into a false assurance.
3030

31-
The same checklist is the Setup page in `keel serve`, and it is what a brand-new machine's
32-
landing page shows instead of an empty dashboard.
31+
The same checklist is the Setup section of the Audit & Setup view in `keel serve`, and it is
32+
where a brand-new machine's "Set keel up on this machine" link lands instead of an empty
33+
dashboard.
3334

3435
## 0. Before you start
3536

‎docs/operator-runbook.md‎

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -421,15 +421,19 @@ It prints a URL carrying a one-time token for that run and opens your browser (`
421421
skip). The `--config`/`--db` pair still decides which account you are looking at, and still bites
422422
the same way.
423423

424-
It is **read-only**, and structurally so: the server answers `GET` and `HEAD` and implements no
425-
other verb, so there is no request it can answer that changes anything. Attesting, promoting a
426-
rule, recording a flow and arming autonomy stay CLI commands behind the interactive-terminal gate.
424+
It **reads with `GET` and `HEAD`, and its writes are a closed set of `POST`s** under `/api/`:
425+
`/api/gates/halt` engages the kill-switch (a gate token, nothing more — stopping must never be
426+
slower than starting); `/api/gates/resume` and `/api/gates/resume-entries` release a halt only
427+
from a loopback session on a loopback bind, with a gate token and a typed phrase (the console
428+
offers neither — release a halt with `keel resume` at a terminal); and `/api/setup/<step>` runs
429+
one of `keel setup`'s idempotent mechanical steps. Attesting, promoting a rule, recording a flow
430+
and arming autonomy stay CLI commands behind the interactive-terminal gate.
427431

428432
Four things stand between that page and the rest of the machine: it binds `127.0.0.1`; it checks
429433
the `Host:` header, so a hostname rebound to loopback is refused even though its packets arrive
430434
on loopback; it requires the session token, which is minted per run and never written to disk; and
431-
it serves no write verb. `--host` will bind anywhere you ask, and says plainly what that costs —
432-
on a non-loopback address your positions, equity and full trade history are readable by anyone who
435+
every write also needs the console's own request headers and a token derived from that session.
436+
`--host` will bind anywhere you ask, and says plainly what that costs — on a non-loopback address your positions, equity and full trade history are readable by anyone who
433437
can reach the port, with a cleartext token as the only obstacle.
434438

435439
**Placing an order is gated differently.** Paper places freely against synthetic cash — nothing is
@@ -836,12 +840,11 @@ Rewards item: account settings no rail can see, re-checked after any account cha
836840

837841
## The operator console, in a browser
838842

839-
`keel serve` opens keel's **operator console**: a local web page showing Pulse (the home view),
840-
Setup, Holdings, Balances, Timeline, Rules, Venues and Plans, over the same `keel/commands/*`
841-
service layer the CLI commands call. It is being slimmed to four engine
842-
views -- Pulse, Holdings, Rules, Audit & Setup; see
843-
`docs/superpowers/plans/2026-10-10-console-four-views.md`. An architectural test (`tests/commands/test_console_thinness.py`) pins that thinness -- the
844-
front-end renders and dispatches, and every behaviour comes from the services.
843+
`keel serve` opens keel's **operator console**: a local web page with four engine views -- Pulse
844+
(the home view), Holdings, Rules and Audit & Setup -- plus a link to the documentation, over the
845+
same `keel/commands/*` service layer the CLI commands call. An architectural test
846+
(`tests/commands/test_console_thinness.py`) pins that thinness -- the front-end renders and
847+
dispatches, and every behaviour comes from the services.
845848

846849
```bash
847850
keel --config config.live-sandbox.yaml --db keel-live.db serve
@@ -850,6 +853,11 @@ keel --config config.live-sandbox.yaml --db keel-live.db serve
850853
It binds loopback and prints a URL carrying a one-time token for that run. Stopping the server
851854
invalidates it: the token is new every run.
852855

856+
**Pulse.** The glance page: the kill switch, autonomy and its lapse, today's cycle counts
857+
(signals, entered, blocked, errors), why keel did not trade, the last cycle's time, the next DCA
858+
buy due per live DCA rule, data freshness and the market session, and any tranche missing its
859+
bracket. It carries the HALT button (below).
860+
853861
**Holdings.** One table of open tranches per rule: per-tranche cost (what the tranche paid to
854862
open, entry fee included), the entry-gate verdict, the asset attestation, the bracket, the stop
855863
only when a tranche carries one, and the entry order's placement and expected-vs-actual fill. The
@@ -867,10 +875,22 @@ command it shows, at a terminal), then the research record: every trial, the evi
867875
gauntlet and the slippage assumptions. Track records, promotion-gate distances and the research
868876
record used to be the Insights and Research views. The equity charts and the closed-trade table
869877
left the console: the closed-trade journal is `keel insights journal`, your own journal is `keel
870-
journal list`, and in the browser every fill is still a Timeline `trade` row and every journal
871-
entry a Timeline `attestation` row. A live rule's track record is `keel insights summary --mode
878+
journal list`, and in the browser every fill is still a `trade` row on the Audit & Setup timeline and every
879+
journal entry an `attestation` row there. A live rule's track record is `keel insights summary --mode
872880
live`.
873881

882+
**Audit & Setup.** The tamper-evident timeline, the setup checklist and venue readiness, on one
883+
page. The timeline opens on keel's own record -- `kind=keel`, the engine's cycle rows (each with
884+
its signals, blocked, entered, exited and error counts) and the attestations -- and the `trade`
885+
and `flow` chips (or `all`) bring back fills and cash flows; the Export CSV link carries the same
886+
scope and kind, so the file holds what the screen shows, with each row's hash and chain status.
887+
Below it is Setup: the runbook stages as tabs, each mechanical step a button, and the job panel
888+
reporting a running step such as the market-data fetch. Last is venue readiness: whether a live
889+
entry can be placed on this deployment now, and the fix when it cannot. The adapters' declared
890+
capabilities are `keel brokers list`. This page is where "Set keel up on this machine" lands
891+
when no deployment exists yet, and the old `/setup`, `/timeline` and `/venues` addresses open it.
892+
The Balances and Plans views are gone; their old addresses open Pulse.
893+
874894
**Halting from the browser.** Pulse carries a HALT button. It engages the kill switch through the
875895
same operation `keel kill` performs (`POST /api/gates/halt`), after one confirm dialog and nothing
876896
else: stopping must never be slower than starting. It needs the console session and the gate token
@@ -998,10 +1018,15 @@ covers the rest from a plain shell.
9981018

9991019
**What the browser cannot do, and that is deliberate.** Every capability-increasing action --
10001020
arming autonomy, releasing the kill-switch, clearing a consecutive-loss halt, re-seeding the
1001-
drawdown high-water mark, declaring a deposit or withdrawal, attesting withdrawal capability, and
1002-
replacing the binary -- is a CLI command behind a typed confirmation at an interactive terminal.
1003-
`keel capabilities` lists all seven with the gate covering each. The server implements no verb
1004-
that would reach one, so this is a property of the server rather than of what the page draws.
1021+
drawdown high-water mark, declaring a deposit or withdrawal, attesting withdrawal capability, scope
1022+
or posture, declaring an out-of-band close, and replacing the binary -- is a CLI command behind a
1023+
typed confirmation at an interactive terminal. `keel capabilities` lists all ten with the gate
1024+
covering each. The one exception is the console's
1025+
HALT button, which engages the kill-switch (stopping is never gated). The server's gated routes
1026+
under `/api/gates/` can also release the kill-switch and clear the consecutive-loss halt, but only
1027+
for a loopback session on a loopback bind with the typed phrase, and the page draws no control for
1028+
either: releasing remains a terminal act in practice. Everything else in the list has no route
1029+
at all, so that is a property of the server rather than of what the page draws.
10051030

10061031
## How much money moves
10071032

‎docs/presentations/se.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ packages/ the uv workspace (7,190)
8080
└── keel-broker-fake/ ⭐ adapter existing ONLY to exert design pressure on the port
8181
```
8282

83+
*Note (2026-10-11): `web/` is no longer purely read-only. The console halts the engine (the HALT button on Pulse) and runs idempotent setup steps; releasing a halt and every other capability-increasing action stays at the terminal.*
84+
8385
**Two things to notice before we go further.**
8486

8587
`commands/` is 23,188 lines — larger than the engine it drives. That is deliberate rather than

‎docs/remote-access.md‎

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ Stated plainly, because "it's encrypted" is not a threat model.
5555

5656
The third row is the one that needs saying out loud. Cloudflare terminates TLS. In that mode
5757
the operator is not merely trusting Cloudflare to route traffic; they are handing it the
58-
readable contents of a console that displays positions, balances and attestations. That may be
58+
readable contents of a console that displays holdings, the timeline and attestations. That may be
5959
an acceptable trade for convenience. It is not a neutral one, and a document that let someone
6060
discover it later would have failed.
6161

@@ -87,10 +87,13 @@ gesture in both postures.
8787

8888
## Capability-increasing actions are refused unless the bind is loopback
8989

90-
`keel serve` serves a read surface. Three of the nine capability-increasing actions in
91-
`keel/capabilities.py` are being admitted to it behind a second gate (#781) -- releasing the
92-
kill-switch halt, clearing rail 16's consecutive-loss halt, and re-seeding rail 11's drawdown
93-
breaker. `keel.web.security.gated_action_permitted` decides, and it requires **three** things:
90+
`keel serve` serves a read surface plus a small write surface: the setup steps, the HALT button
91+
(`/api/gates/halt`, which engages the kill switch and is deliberately allowed from a tunnel -- a
92+
stop must never be slower than a start), and two gated releases behind a second gate (#781) --
93+
releasing the kill-switch halt and clearing rail 16's consecutive-loss halt. The other
94+
capability-increasing actions in `keel/capabilities.py` have no route at all.
95+
`keel.web.security.gated_action_permitted` decides the two releases, and it requires **three**
96+
things:
9497
a loopback peer, no `--external-host`, and a **loopback bind**.
9598

9699
The third exists because the second is a declaration and two ordinary deployments never make it:
@@ -104,8 +107,9 @@ The third exists because the second is a declaration and two ordinary deployment
104107

105108
A bind is observable where a declaration is not: a server reachable from off-box is one an
106109
operator had to bind off-box. So a tunnelled, proxied or LAN-bound deployment serves every read
107-
and refuses every gated action -- and says so on the page, rather than presenting a button that
108-
returns 403.
110+
and the halt, and refuses every gated release with a 403. The console draws no release control at
111+
all -- releasing is done at the terminal -- so there is no button on the page that returns 403;
112+
the refusal is what a direct request to `/api/gates/resume` gets.
109113

110114
**`ssh -L 8765:127.0.0.1:8765` is not closed by this, and that is deliberate.** The peer is
111115
genuinely loopback and the bind is loopback, so the gate opens for a remote human. Ordinarily

‎docs/superpowers/plans/2026-10-10-console-four-views.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Console — four engine views (Pulse · Holdings · Rules · Audit & Setup) — Implementation Plan
22

3+
> **As built (correction note, 2026-10-11).** This plan is kept as written; where it differs from what shipped:
4+
> - **PR2 (Holdings):** the entry order is matched by product, BUY, `placed <= opened_at` and the exact fill price (nearest earlier wins), NOT by the `created_at == opened_at` timestamp join -- paper stamps orders with bar time and tranches with cycle time, so the join missed every paper tranche.
5+
> - **PR3 (Rules):** `rules_payload(records=...)` is a required keyword, not `None` falling back to `count(0)` (a zero nobody passed is unknown-as-zero); the CSV export link gets no class, not `.linkaction`.
6+
> - **PR4 (Audit & Setup):** `keel/commands/balances.py` was deleted, not kept (no `keel balances` CLI exists; the web reader was its only caller). The Audit sections are exported builders (`setupSection`, `timelineSection`, `readinessSection`), so the key-parity scan runs per section against its own endpoint rather than `_view_keys("auditView", "setup")`. `timelineSection` takes the read error as an argument: no database reads "No timeline yet: there is no database on this machine. Setup creates one.", a failed read reads "The timeline could not be read: <detail>" (not "keel isn't running here yet"). The timeline wire also carries `engine_log`, and the page says when the engine log is missing or unreadable.
7+
8+
39
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. Never ask the user anything; every open question in this initiative is settled in a "Rulings" list below.
410
511
**Goal:** Replace the console's thirteen screens with four engine views -- PULSE (home, with the HALT button), HOLDINGS, RULES, AUDIT & SETUP -- shipped as four sequential PRs, each leaving the console fully working and the suite green. The ledger's "Done means" (`.superpowers/orchestrate/2026-10-10-console-four-views/ledger.md`) is the acceptance list; the screen inventory with line numbers is `inventory.md` beside it. Line numbers below are at BASE_SHA `9b1db8755cf7ac6a65cb118c615dc8e630998143`.

‎docs/superpowers/specs/2026-08-23-web-ui-rewrite-design.md‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
**Date:** 2026-08-23 · **Status:** shipped. Every step of §"Build order" landed (#533–#541, v0.12.0);
44
kept unrewritten as the design record.
55

6+
**Note (2026-10-11):** the console is now four views -- Pulse, Holdings,
7+
Rules, Audit & Setup -- and its write surface also includes a gates POST surface (`/api/gates/*`,
8+
#781; the console's HALT button uses `halt`). Where this document names the earlier views
9+
(Status, Activity, Gates, Timeline, Setup, Venues, Balances, Plans) or says the write surface is
10+
only `setup.ACTIONS`, read it as the 2026-08 design, not the present.
11+
612
This document describes the browser interface keel serves from the operator's own machine: what the
713
server does, what the client does, and why each decision was made the way it was. It follows the
814
shape of [youperiod.app's SPECS.md](https://github.com/getify/youperiod.app/blob/main/SPECS.md) and
@@ -137,8 +143,9 @@ Subresource Integrity authorises any inline `<script>` or `<style>` block, as in
137143
3. **A session token**, minted per run, never written to disk, exchanged on first load for a
138144
`SameSite=Strict`, `HttpOnly` cookie. `Strict` rather than `Lax` is deliberate: `Lax` attaches the
139145
cookie to top-level navigations, so a link on a hostile page would arrive authenticated.
140-
4. **A closed action set.** The entire write surface routes through `keel.commands.setup.ACTIONS`,
141-
every member declared `MECHANICAL`, idempotent and non-destructive, and **a test asserts that set
146+
4. **A closed action set.** The setup write surface (`/api/setup/*`) routes through
147+
`keel.commands.setup.ACTIONS` (as of 2026-10 the gated `/api/gates/*` routes are a second,
148+
separately gated surface -- see the note in the header), every member declared `MECHANICAL`, idempotent and non-destructive, and **a test asserts that set
142149
is disjoint from the eleven capability-increasing actions in `keel/capabilities.py`.**
143150
5. **A CSRF token on every write**, derived from the session token by HMAC rather than stored — "the
144151
layer that does not depend on the browser being current." Comparisons use

‎keel/capabilities.py‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,9 @@ def key(self) -> tuple[str, str]:
244244
module="keel.web.gates",
245245
function="run_gated_action",
246246
surface="web",
247-
invocation="the Resume trading button, with its typed phrase",
247+
invocation=(
248+
"POST /api/gates/resume with its typed phrase (loopback; the console draws no control)"
249+
),
248250
increases=(
249251
"trading resumes after the kill-switch halted it -- the same increase `keel resume` "
250252
"grants, reached from a browser on a loopback session instead of from a terminal"
@@ -256,7 +258,10 @@ def key(self) -> tuple[str, str]:
256258
module="keel.web.gates",
257259
function="run_gated_action",
258260
surface="web",
259-
invocation="the Clear streak halt button, with its typed phrase",
261+
invocation=(
262+
"POST /api/gates/resume-entries with its typed phrase (loopback; the console draws "
263+
"no control)"
264+
),
260265
increases=(
261266
"new entries resume after rail 16's consecutive-loss halt -- the same increase "
262267
"`keel resume-entries` grants, reached from a browser on a loopback session"

0 commit comments

Comments
 (0)