Console: Overview home and Inbox
I maintainer di solito rispondono entro 1 giorno
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 38/100
- Tipo di issue
- Funzionalità
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- react, typescript
- Ambito
- developer-experience, frontend
Direzione di ricerca
Start by reading the named UI modules, especially ui/src/model/inbox.ts and ui/src/model/overview.ts, plus the existing Overview and Attention screens and their end to end specs. Then trace the named state modules and routes to see how workers, requests, leases, tokens, stats and events feed the pages. Done means Overview, Inbox and Usage match the specified content, ordering, links and failure behavior, with the named UI and end to end specs updated; the issue spans many screens, shared state and routing.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Part of #756.
Scope
The home page becomes Overview, giving the whole system at a glance, and Inbox replaces Attention as the full list of what needs a person. After this PR an operator sees on one page whether anything is wrong, how full each platform is, and how busy the last hour was. They see every item that needs them, including long waits, absent phones and leases about to end. Usage moves into the shared frame too.
In short
/ shows five numbers:
- Leased: leases held of all devices, with the ready count under it.
- Waiting: requests waiting, with the longest wait under it.
- Workers: connected of all workers.
- Wait p95: the 95th percentile wait in the range picked.
- Ending soon: leases with under 5 minutes left (
EXPIRING_UNDER_MS, which goes from 15 to 5 minutes here, so the Leases page's filter becomes "Ending < 5 min").
Under them:
-
When the Inbox has no problem item and every read it rests on succeeded, one line: "Nothing needs you". When a read failed, one line instead: "Could not check: ", for example "Could not check: waiting requests". It never says "Nothing needs you" then.
-
When the Inbox has problem items, a Needs you panel shows the first four in Inbox order, each row opening its drawer at
/inbox/<key>. Under them is the link "All in Inbox ()". -
Capacity · all workers: one bar per platform (iOS, Android), counting every device of every worker the console has read, except
deletedones. The parts:- leased;
- ready;
- booting (
provisioningorreclaiming); - drained (ready, on a drained worker);
- quarantined;
- absent;
- shut down;
- offline (any state, on a worker that is not connected).
Each part shows its count and word. A connected worker whose devices are not read yet adds nothing, and the bar says "1 worker not read yet" or " workers not read yet".
-
Two charts for the range in
?range=(1h, 6h, 24h, 7d), under today's titles Leases held and Requests in the queue. The range chips sit in the shared toolbar under the header, on the left, as on Usage. -
The workers table from Fleet (#766), with all workers and no pager, and a link "Open Fleet".
Today's Utilisation tile, the Device slots in use chart, the Granted figure and the Recent activity panel leave Overview. The Device slots in use chart moves to Usage. Usage is rebuilt in the shared frame: its header, its range chips in the toolbar, its tables in the one table component.
Ordering, used by Needs you and the Inbox:
- Broken and Needs a look items keep worker order (as today's Attention list), then device, then the key.
- Waiting items go longest wait first.
- Heads-up items go least time left first.
/inbox lists every Inbox item, in three groups: Broken, Needs a look, Heads-up. Chips above the list filter by group. A row opens the drawer at /inbox/<key>. The drawer has a box saying what happened, then the details of the worker, device, request or lease it is about. The sidebar's Inbox count is the number of problem items (Broken plus Needs a look). It is hidden at 0.
New Inbox items, beside today's six attention kinds:
| Item | Key | Group | Title, word for word |
|---|---|---|---|
an enrolled phone in state absent |
<workerId>/<deviceId>/absent |
Needs a look | <model> is absent (<reason>), reason locked, untrusted or not-present |
a request waiting over 60 000 ms, from its createdAt to the daemon's now as the console reads it (corrected by the Date header, ADR 0013 §4) |
request/<requestId>/waiting |
Needs a look | <requester> has waited <duration>, requester as the Queue page names it |
a lease from GET /v1/leases whose deadline is under 5 min from the daemon's now |
lease/<leaseId>/ending |
Heads-up | <holder> · <model> ends in <m:ss>, holder as the Leases page names it; at or past the deadline, ends now |
<model> is the device's spec.model. An Inbox address ends in / when the key holds a ., as leasePath does (ui/src/model/leases.ts:115-119), so a gateway lease id survives a reload.
flowchart LR
A["/ Overview (new)"] -->|Needs you row| B["/inbox/<key> drawer (new)"]
A -->|All in Inbox| C["/inbox (new, was /attention)"]
C --> B
If this goes wrong, an operator sees "Nothing needs you" while a worker is lost, or misses a request that has waited minutes.
Technical spec
Facts
| # | Fact | Source |
|---|---|---|
| F1 | Attention items today: disconnected, incompatible, drained, over RAM budget (worker), quarantined, stalled (device); keys <workerId>/<condition> (<workerId>/ram for the budget) and <workerId>/<deviceId>/<condition>; disconnected, incompatible and quarantined are error, the rest warn |
ui/src/model/attention.ts:14-77 |
| F2 | All attention items come from /v1/workers |
ui/src/model/attention.ts:35-37 |
| F3 | A status device carries state, physical and absentReason (locked, untrusted, not-present); a worker view lists devices in that shape |
src/contract/schemas.ts:47,211-216,230, src/contract/worker-view.ts:69 |
| F4 | A waiting request has createdAt, stage, queuePosition, reason, workerId and per-worker reasons |
src/contract/schemas.ts:409-417 |
| F5 | The longest wait is computed as the daemon's now minus the oldest createdAt; times are counted against the daemon's clock, corrected by the Date header; the Leases filter uses the same now.server |
ui/src/model/overview.ts:141,158, ui/src/state/overview.ts:35, ui/src/state/leases.ts:66, ADR 0013 §4 |
| F6 | The expiring rule is deadline minus now under EXPIRING_UNDER_MS (15 min), module-private |
ui/src/model/leases.ts:130-135 |
| F6a | The default lease length is 15 minutes | src/core/config.ts:52 (DEFAULT_LEASE_TTL_MS = 15 * 60_000) |
| F6b | Leases come from GET /v1/leases, holder names from GET /v1/tokens (ids when refused) |
ADR 0013 §1, ui/src/state/leases.ts:52-56 |
| F6c | The daemon serves the console page only when the last path segment has no .; leasePath adds a trailing / |
src/http/server.ts:108-111, ui/src/model/leases.ts:115-119 |
| F6d | Device states include shutdown and deleted; deleted records stay in the file |
src/contract/schemas.ts:36-45, src/core/AGENTS.md |
| F7 | The Overview reads /v1/workers, /v1/lease-requests, recent events and useFigures(range) |
ui/src/state/overview.ts:20-39 |
| F8 | The figures come from GET /v1/stats?since=<1h|6h|24h|7d>, range in ?range= |
ui/src/state/figures.ts:23-27, ui/src/model/range.ts:27-28 |
| F8a | A single host answers both GET /v1/lease-requests and GET /v1/stats |
src/daemon/dispatcher.ts:314,793,812, e2e/console/usage.spec.ts:134-251 |
| F9 | The three chart series are leasesHeld, queueDepth, slotsUsed, drawn by MinuteChart with a MinuteTable |
ui/src/model/figures.ts:62-81, ui/src/screens/overview/index.tsx:56 |
| F10 | Usage shows slots only as a stat today | ui/src/model/usage.ts:90-91 |
| F11 | Capacity today is per platform, running of limit, over connected workers only | ui/src/model/overview.ts:82-105 |
| F12 | The shell shows the attention count on the /attention entry |
ui/src/app/shell.tsx:27-35, ui/src/state/shell.ts (useAttentionCount) |
| F13 | Ids may hold a slash; itemPath encodes the whole id as one segment |
ui/src/model/paths.ts:1-18 |
| F14 | e2e: attention.spec.ts and overview.spec.ts assert today's headings, lists and texts |
e2e/console/attention.spec.ts, e2e/console/overview.spec.ts |
| F15 | e2e can drain a worker, stop one, hold a lease with lease --detach, start a waiting request with cliBackground, and stub a route's answer through page.route |
e2e/console/workers.spec.ts:285,716, e2e/console/waiting.spec.ts:81, e2e/console/long-lists.spec.ts:119-127 |
| F16 | Worker health and load findings | ui/src/model/fleet.ts:17-50, ui/src/model/load-thresholds.ts:7 |
Modules touched
Searches: attentionItems, attentionTone, AttentionScreen, useAttentionCount, "/attention", attention (case-insensitive, ui/src and e2e/console), EXPIRING_UNDER_MS, platformUse, FigureChartPanel, slotsUsed.
ui/src/model/attention.tsbecomesmodel/inbox.ts: the three new kinds, groups, order, keys, problem count.WAITING_TOO_LONG_MS = 60_000is new.EXPIRING_UNDER_MSis exported frommodel/leases.ts, its one home, and becomes 5 minutes.ui/src/model/leases.ts: the filter's label becomes "Ending < 5 min";e2e/console/leases.spec.ts:315checks it by that name.ui/src/model/overview.ts: the five numbers, capacity by part, the could-not-check line.ui/src/model/event-list.ts: its "Open attention item" link becomes "Open Inbox item" at/inbox/<key>.ui/src/state/overview.ts(adds/v1/leasesand/v1/tokens),state/attention.ts(becomesstate/inbox.ts),state/shell.ts: Inbox count.ui/src/screens/overview/,screens/attention/(becomesscreens/inbox/),screens/usage/(the shared frame, the Device slots in use chart).ui/src/app/routes.ts,app/routes.test.ts,app/shell.tsx,ds/icon.tsx:/inbox;/attentionand its icon go.ui/src/model/paths.ts,model/paths.test.ts:Sectiongains/inboxand drops/attention; the trailing/for keys with a..e2e/console/attention.spec.ts(becomesinbox.spec.ts),overview.spec.ts,usage.spec.ts,views.spec.ts,shell.spec.ts,long-lists.spec.ts,fixtures.ts.docs/CONSOLE.md(Overview, Attention → Inbox, Usage),ui/AGENTS.md.
flowchart LR
s1["screens/overview (changed)"] --> st1["state/overview (changed)"]
s2["screens/inbox (new)"] --> st2["state/inbox (new)"]
st1 --> m1["model/overview (changed)"]
st1 --> m2["model/inbox (new)"]
st2 --> m2
m2 --> m3["model/leases (export)"]
shell["app/shell (changed)"] --> st2
Contract and event changes
None. The pages read /v1/workers, /v1/lease-requests, /v1/leases, /v1/tokens, /v1/stats and the events, all routes the console reads today.
Other code on the same state
Searches: EXPIRING_UNDER_MS, isExpiring, createdAt, stalled, absent.
- The Leases page's filter (#765) and the Inbox heads-up use the same exported
EXPIRING_UNDER_MSand the samenow.server, so they cannot disagree. - The Queue page (#767) shows the same requests. The Inbox only adds an item; it changes nothing on the request.
- #769 adds the one fix button (Undrain on a drained worker), reading
model/inbox.ts's items.
Failure modes
| Call | Outcome | What happens | Limit, counted from |
|---|---|---|---|
GET /v1/stats with history unavailable |
503 | the charts and Wait p95 show the daemon's message, as today | — |
GET /v1/workers fails |
error | Overview shows "Could not check: workers" and no capacity; Inbox shows the error as today | the client's timeout |
GET /v1/lease-requests fails (any error, timeout) |
error | "Could not check: waiting requests"; the Inbox shows the rest with a banner saying the same | the client's timeout |
GET /v1/leases fails |
error | "Could not check: leases"; Ending soon shows — |
the client's timeout |
GET /v1/tokens refused |
403 | holders show their ids, as Leases does | — |
/inbox/<key> for an item that cleared |
not found | the drawer says "This is no longer in the Inbox." | the next refetch |
Rules in play
- DESIGN.md "A status always has a word": every capacity part prints its count and word; the bar is
role="img"with the same words as its name. - DESIGN.md "A count ... is a number, not a status": the Inbox count has no status colour.
- ADR 0013 §1: Overview and Inbox read only routes the console reads today.
- Architecture rule 10: one home for the ending-soon rule (
EXPIRING_UNDER_MS). - ADR 0013 §4: every wait and time left counts against the daemon's clock.
Tests
Seam: the browser lane (e2e/console/attention.spec.ts becomes inbox.spec.ts; overview.spec.ts), with a real daemon, and with page.route stubs for times a real daemon cannot reach quickly, as long-lists.spec.ts stubs. The pure rules run in Node in model/inbox.test.ts, modelled on ui/src/model/attention.test.ts.
- each of today's six attention kinds is an Inbox item with today's key and tone (move
attention.test.tscases) - an absent physical device is a Needs a look item titled
<model> is absent (<reason>)for each oflocked,untrusted,not-present; a device in another state is not - a request is an item at 60 001 ms waited and not at 59 999 ms, both by the daemon's now (model test)
- a lease is a heads-up at 4:59 left and not at 5:01, and one past its deadline says
ends now; the Leases filter agrees on the same leases (model test) - items keep the order given: worker order for problems, longest wait first, least time left first
- items group as Broken, Needs a look, Heads-up, in that order; the problem count excludes heads-ups
- Overview with an empty Inbox shows "Nothing needs you" and no Needs you panel; with a disconnected worker it shows the panel with that item first, and the link "All in Inbox ()"
- with five problem items the panel shows four, and a row opens
/inbox/<key> - with
/v1/lease-requestsstubbed to fail, Overview says "Could not check: waiting requests" and not "Nothing needs you" - Overview shows the five numbers with the daemon's values: one lease held of four devices with the ready count, one request waiting with its longest wait, two of two workers, Wait p95, and Ending soon counting a lease stubbed to 4 minutes left and not one at 10
- Overview's workers table lists all workers with no pager, and "Open Fleet" goes to
/fleet - Overview's and Usage's range chips sit in the shared toolbar
- capacity counts every read device per platform: a drained worker's ready device counts as drained, a disconnected worker's devices as offline, a
shutdowndevice as shut down, adeletedone not at all (model test) - the Leases held and Requests in the queue charts follow
?range=for each of 1h, 6h, 24h and 7d; Usage shows the Device slots in use chart in the shared frame (extendoverview.spec.ts,usage.spec.ts) /inboxlists a drained worker under Needs a look and a disconnected one under Broken; the chips show one group at a time- a waiting request stubbed with a
createdAt61 s before the daemon's now shows under Needs a look, and one at 30 s does not - a lease stubbed with 4 minutes left shows under Heads-up, and one with 10 minutes does not
- an Inbox item whose key holds a
.reloads at its address - an Inbox row opens
/inbox/<key>with the what-happened box and the item's details; a cleared item says "This is no longer in the Inbox." - the sidebar's Inbox count equals the problem items and is hidden at 0
- on a single host, Overview shows all five numbers and both charts (extend
overview.spec.ts's worker-mode case) - axe passes on Overview and Inbox, empty and busy, in light and dark (extend
shell.spec.ts's axe pass); no<style>element or CSP violation (extendviews.spec.ts)
Done when
pnpm test:console --project=chromiumpasses, and CI's Console check passes in every browser.
Out of scope
- The fix button and every action (#769).
Depends on
- #765
- #766
- #767
Written by an agent.
- Lingua principale
- TypeScript
- Stelle
- 20
- Fork
- 2
- Merge medio
- 8h
- PR unite (30g)
- 316
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di callstackincubator/simlock
-
bug:new
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
callstackincubator/simlock#817 ·
I maintainer di solito rispondono entro 1 giorno
-
bug:triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
callstackincubator/simlock#778 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
callstackincubator/simlock#639 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
task:draft
Difficoltà 4/5 3-5 giorni Idoneità per principianti 35/100
callstackincubator/simlock#839 ·
I maintainer di solito rispondono entro 1 giorno
-
A gateway updates a chosen worker, incompatible ones included, and routes around it meanwhileApertatask:ready
Difficoltà 5/5 Più di una settimana Idoneità per principianti 35/100
callstackincubator/simlock#838 ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di callstackincubator/simlock
Issue simili
-
ready-for-agent
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
xavxyz/bei-shan-lin-shui#57 ·
I maintainer di solito rispondono entro 1 giorno
-
[BUG] rag: sentence content can cross the reported sentence boundariesForse già presa @LJK-ikun l’ha presa oggi. Apertabug
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
I maintainer di solito rispondono entro 1 giorno
-
bug needs-triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
I maintainer di solito rispondono entro 1 giorno
-
README: the Resource URI Schemas example's file://documents/* pattern only matches that literal URIAperta
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
platformatic/mcp#361 ·
I maintainer di solito rispondono entro 1 giorno
-
最近文档这个弹窗,左右宽度没有最小宽度限制Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
siyuan-note/siyuan#20799 · 7 commenti ·
I maintainer di solito rispondono entro 1 giorno