lab: AFK menu shows (N ready) count hint with minimal caching #66

Closed
opened 2026-06-01 12:24:19 +02:00 by dominik.polakovics · 1 comment

Parent

#61

What to build

Surface how many ready-for-agent issues a project has, so the menu can show Start AFK run (N ready) and grey the action at zero — using only cached counts, so the per-poll render never blocks on tea.

Acceptance criteria

  • The scheduler caches the ready-for-agent count for auto-on projects (it already lists them each cycle).
  • The menu shows Start AFK run (N ready) when a cached count is available, and greys/disables the action at a cached zero.
  • Cold auto-off projects show no count; the manual click stays authoritative and flashes "no ready-for-agent issues" on an empty queue (from Slice 1).
  • No synchronous tea call on the per-poll render path — counts come only from the scheduler's cache.
  • Stale counts are acceptable; the click is always the source of truth.

Blocked by

  • #62 (Slice 1 — the menu + manual action the hint annotates)
  • #64 (Slice 3 — the scheduler that maintains the count cache)
## Parent #61 ## What to build Surface how many `ready-for-agent` issues a project has, so the menu can show `Start AFK run (N ready)` and grey the action at zero — using only cached counts, so the per-poll render never blocks on `tea`. ## Acceptance criteria - [ ] The scheduler caches the `ready-for-agent` count for auto-on projects (it already lists them each cycle). - [ ] The `⋯` menu shows `Start AFK run (N ready)` when a cached count is available, and greys/disables the action at a cached zero. - [ ] Cold auto-off projects show no count; the manual click stays authoritative and flashes "no ready-for-agent issues" on an empty queue (from Slice 1). - [ ] No synchronous `tea` call on the per-poll render path — counts come only from the scheduler's cache. - [ ] Stale counts are acceptable; the click is always the source of truth. ## Blocked by - #62 (Slice 1 — the menu + manual action the hint annotates) - #64 (Slice 3 — the scheduler that maintains the count cache)
Author
Owner

This was generated by AI during triage.

Agent Brief

Category: enhancement
Summary: Show a cached "(N ready)" count on the per-project ⋯ menu's Start AFK run action, greying — but never blocking — the action at a cached zero, with counts sourced only from the auto-run scheduler's in-memory cache (no tea on the render path).

Current behavior:
The per-project ⋯ menu (Forgejo-hosted projects only) shows a plain Start AFK run button with no hint of whether there is anything to do. Clicking it claims the lowest-numbered ready-for-agent issue, or on an empty queue flashes "No ready-for-agent issues to start." The auto-run scheduler (scheduleAFKRuns) already lists each auto-on project's ready queue every sweep via Tracker.ReadyIssues (which returns the open ready-for-agent issues), but keeps only a boolean (ReadyExists = len(issues) > 0) and throws the count away.

Desired behavior:

  • The scheduler records the ready-for-agent count (len(issues)) for each auto-on project it sweeps, in an in-memory, project-name-keyed cache on the server (keyed like AutoEnabled/ConsecutiveFailures). It is not persisted: it re-derives within one sweep interval after a restart, and a stale value carried across a restart would mislead.
  • The per-project view-model (projectGroup — the struct already carrying AutoEnabled/ConsecutiveFailures/Paused) gains a representation that distinguishes three states: unknown (no cache entry / not auto-on), cached N>0, and cached zero. A bare int cannot separate "unknown" from "cached 0" — use a companion bool or a pointer.
  • The render path (snapshot) populates this from the in-memory cache only. No tea/Tracker call may be added to the per-poll render path (it makes none today; that must stay true).
  • The Start AFK run control renders by state:
    • unknown -> plain "Start AFK run" (today's behavior), enabled. Covers auto-off projects and auto-on projects not yet swept.
    • cached N>0 -> "Start AFK run (N ready)", enabled.
    • cached zero -> "Start AFK run (0 ready)", visually greyed but still clickable/submittable.
  • The count shows only for a project whose auto toggle is currently on and for which the scheduler has recorded a count, so a cold auto-off project shows no count (consistent with the toggle/pause lines, which are auto-feature UI).

Resolved design point — grey-but-clickable at zero: the issue's criteria say both "disable at a cached zero" and "the click is always the source of truth." A hard-disabled control (the template's existing .menu-item.disabled is a non-clickable <span>) would block the authoritative click when the cached zero is stale (an issue marked ready less than one sweep ago, or auto just toggled on). So a cached zero is greyed as a hint but stays a real submit button; clicking re-checks live and flashes the existing "No ready-for-agent issues" notice when the queue truly is empty. Do not use the HTML disabled attribute for the zero state.

Key interfaces:

  • Tracker.ReadyIssues(dir) ([]Issue, error) — already called each sweep; len() of its result is the count. No interface change.
  • scheduleAFKRuns — already lists the ready queue for every auto-on candidate before the launch gate; capture that length into the cache for every auto-on candidate swept, whether or not a launch happens.
  • New in-memory cache on Server — project-name-keyed int, mutex-guarded in the style of the existing afkRunsMu/store mutex; not added to the persisted projectState.
  • projectGroup — gains the count + known/unknown representation, set in snapshot from the cache (read-only, no tea).
  • The index template's Start AFK run control — renders the suffix and the greyed-at-zero state as server-rendered text/class (like the existing On/Off toggle and pause line) so the live keyed-DOM morph repaints it; no client-side JS state.
  • Prefer a pure, table-tested display helper (mirroring shouldLaunchAuto/classifyAFKRun) mapping (autoEnabled, count, known?) -> (suffix, greyed?), so the decision is unit-tested without tmux/tea/clock.

Acceptance criteria:

  • After the scheduler sweeps an auto-on project, its ready-for-agent count is available to the render path from an in-memory cache, with no tea call added to the render path.
  • The ⋯ menu shows "Start AFK run (N ready)" for an auto-on project with a cached N>0.
  • At a cached zero the action is visually greyed yet still submits, and submitting an empty queue flashes the existing "No ready-for-agent issues to start." notice.
  • An auto-off project — and an auto-on project not yet swept — shows a plain "Start AFK run" with no count, still enabled.
  • The count cache is in-memory only: it is not written to the store JSON, and after a restart a project shows no count until the next sweep repopulates it.
  • The display decision is covered by a table-driven unit test (using the existing fake Tracker/store seams) across unknown / N>0 / zero.
  • go test ./..., go vet ./..., and go build pass in the lab module. (The repo pre-commit hook is eval-only and does not run Go tests — run them locally.)

Out of scope:

  • Changing issue selection/claim or handleAFKStart semantics — the click stays authoritative exactly as it is.
  • Any tea query on the render path (even timed) — counts come only from the scheduler cache; stale counts are acceptable by design.
  • Persisting the count, or adding it to projectState/the store file.
  • A separate refresh timer — the existing ~45s sweep and ~4s fragment poll already deliver updates.
  • Reworking the ⋯ menu layout or mobile-first tap-target sizing — this is a text/state change to the existing control.
  • Logged-out / at-cap behavior (the sweep already short-circuits): leaving the last-known or absent count is fine.
> *This was generated by AI during triage.* ## Agent Brief **Category:** enhancement **Summary:** Show a cached "(N ready)" count on the per-project ⋯ menu's *Start AFK run* action, greying — but never blocking — the action at a cached zero, with counts sourced only from the auto-run scheduler's in-memory cache (no `tea` on the render path). **Current behavior:** The per-project ⋯ menu (Forgejo-hosted projects only) shows a plain *Start AFK run* button with no hint of whether there is anything to do. Clicking it claims the lowest-numbered `ready-for-agent` issue, or on an empty queue flashes "No ready-for-agent issues to start." The auto-run scheduler (`scheduleAFKRuns`) already lists each auto-on project's ready queue every sweep via `Tracker.ReadyIssues` (which returns the open `ready-for-agent` issues), but keeps only a boolean (`ReadyExists = len(issues) > 0`) and throws the count away. **Desired behavior:** - The scheduler records the ready-for-agent **count** (`len(issues)`) for each auto-on project it sweeps, in an **in-memory**, project-name-keyed cache on the server (keyed like `AutoEnabled`/`ConsecutiveFailures`). It is **not** persisted: it re-derives within one sweep interval after a restart, and a stale value carried across a restart would mislead. - The per-project view-model (`projectGroup` — the struct already carrying `AutoEnabled`/`ConsecutiveFailures`/`Paused`) gains a representation that distinguishes **three states**: *unknown* (no cache entry / not auto-on), *cached N>0*, and *cached zero*. A bare `int` cannot separate "unknown" from "cached 0" — use a companion bool or a pointer. - The render path (`snapshot`) populates this from the in-memory cache **only**. No `tea`/`Tracker` call may be added to the per-poll render path (it makes none today; that must stay true). - The *Start AFK run* control renders by state: - **unknown** -> plain "Start AFK run" (today's behavior), enabled. Covers auto-off projects and auto-on projects not yet swept. - **cached N>0** -> "Start AFK run (N ready)", enabled. - **cached zero** -> "Start AFK run (0 ready)", visually greyed **but still clickable/submittable**. - The count shows only for a project whose auto toggle is currently **on** and for which the scheduler has recorded a count, so a cold auto-off project shows no count (consistent with the toggle/pause lines, which are auto-feature UI). **Resolved design point — grey-but-clickable at zero:** the issue's criteria say both "disable at a cached zero" *and* "the click is always the source of truth." A hard-disabled control (the template's existing `.menu-item.disabled` is a non-clickable `<span>`) would block the authoritative click when the cached zero is stale (an issue marked ready less than one sweep ago, or auto just toggled on). So a cached zero is greyed as a **hint** but stays a real submit button; clicking re-checks live and flashes the existing "No ready-for-agent issues" notice when the queue truly is empty. Do **not** use the HTML `disabled` attribute for the zero state. **Key interfaces:** - `Tracker.ReadyIssues(dir) ([]Issue, error)` — already called each sweep; `len()` of its result is the count. No interface change. - `scheduleAFKRuns` — already lists the ready queue for every auto-on candidate before the launch gate; capture that length into the cache for every auto-on candidate swept, whether or not a launch happens. - New in-memory cache on `Server` — project-name-keyed `int`, mutex-guarded in the style of the existing `afkRunsMu`/store mutex; **not** added to the persisted `projectState`. - `projectGroup` — gains the count + known/unknown representation, set in `snapshot` from the cache (read-only, no tea). - The index template's *Start AFK run* control — renders the suffix and the greyed-at-zero state as **server-rendered text/class** (like the existing On/Off toggle and pause line) so the live keyed-DOM morph repaints it; no client-side JS state. - Prefer a pure, table-tested display helper (mirroring `shouldLaunchAuto`/`classifyAFKRun`) mapping (autoEnabled, count, known?) -> (suffix, greyed?), so the decision is unit-tested without tmux/tea/clock. **Acceptance criteria:** - [ ] After the scheduler sweeps an auto-on project, its ready-for-agent count is available to the render path from an in-memory cache, with no `tea` call added to the render path. - [ ] The ⋯ menu shows "Start AFK run (N ready)" for an auto-on project with a cached N>0. - [ ] At a cached zero the action is visually greyed yet still submits, and submitting an empty queue flashes the existing "No ready-for-agent issues to start." notice. - [ ] An auto-off project — and an auto-on project not yet swept — shows a plain "Start AFK run" with no count, still enabled. - [ ] The count cache is in-memory only: it is not written to the store JSON, and after a restart a project shows no count until the next sweep repopulates it. - [ ] The display decision is covered by a table-driven unit test (using the existing fake `Tracker`/store seams) across unknown / N>0 / zero. - [ ] `go test ./...`, `go vet ./...`, and `go build` pass in the lab module. (The repo pre-commit hook is eval-only and does **not** run Go tests — run them locally.) **Out of scope:** - Changing issue selection/claim or `handleAFKStart` semantics — the click stays authoritative exactly as it is. - Any `tea` query on the render path (even timed) — counts come only from the scheduler cache; stale counts are acceptable by design. - Persisting the count, or adding it to `projectState`/the store file. - A separate refresh timer — the existing ~45s sweep and ~4s fragment poll already deliver updates. - Reworking the ⋯ menu layout or mobile-first tap-target sizing — this is a text/state change to the existing control. - Logged-out / at-cap behavior (the sweep already short-circuits): leaving the last-known or absent count is fine.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Cloonar/nixos#66
No description provided.