Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

Console: Overview home and Inbox

Aperta
#768 1 commento 0 reazioni 1 assegnatario Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@V3RON ci sta già lavorando.

Dal 20/10/2026.

  • #793 di @V3RON — aperta

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

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

task:ready

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 deleted ones. The parts:

    • leased;
    • ready;
    • booting (provisioning or reclaiming);
    • 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/&lt;key&gt; 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.ts becomes model/inbox.ts: the three new kinds, groups, order, keys, problem count. WAITING_TOO_LONG_MS = 60_000 is new. EXPIRING_UNDER_MS is exported from model/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:315 checks 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/leases and /v1/tokens), state/attention.ts (becomes state/inbox.ts), state/shell.ts: Inbox count.
  • ui/src/screens/overview/, screens/attention/ (becomes screens/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; /attention and its icon go.
  • ui/src/model/paths.ts, model/paths.test.ts: Section gains /inbox and drops /attention; the trailing / for keys with a ..
  • e2e/console/attention.spec.ts (becomes inbox.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_MS and the same now.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.ts cases)
  • an absent physical device is a Needs a look item titled <model> is absent (<reason>) for each of locked, 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-requests stubbed 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 shutdown device as shut down, a deleted one 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 (extend overview.spec.ts, usage.spec.ts)
  • /inbox lists 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 createdAt 61 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 (extend views.spec.ts)

Done when

  • pnpm test:console --project=chromium passes, 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

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di callstackincubator/simlock

Tutte le issue di callstackincubator/simlock

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.