docs(site-scope): correct stale line refs, record tasks 1-5 as done

Re-verified every file:line against the current tree. Three were wrong:
the Overview ranges in task 6 (and it listed two sites.items uses where
there are four), the hamburger line in task 5, and a claim that
plant/page.tsx still had perPage: 5000 caps — it does not.

Also records that tasks 1-5 have landed, so the next worker starts at 6,
and keeps the scope-aware Sites sub-label that was implemented in place
of the deletion this plan originally specified.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
DEls 2026-09-11 23:05:10 +02:00
parent 1f3a0e5cef
commit fe55a5d7df

View file

@ -10,16 +10,23 @@
**Spec:** `docs/superpowers/specs/2026-09-11-site-scope-switcher-design.md`
> ### Line numbers in this plan will have drifted
> ### Progress, and how to read the line numbers
>
> A separate "project Month/Week" feature is landing in several of the
> same files (it added a `periodFilter` beside `projectFilter` in three of
> the four view files, already shifting them by ~10 lines). **Treat every
> `file:line` below as a hint, not an address.** The dropdown-removal
> steps are written to anchor on identifier names and code snippets for
> exactly this reason — match on the name, then check the surrounding
> code looks like the snippet. If it doesn't, stop and re-read the file
> rather than editing by line number.
> **Tasks 1-5 are already implemented and committed** (`8fe08fa`,
> `38ad190`, `c88ebb1`, `63eb8ed`, plus the `Topbar` wiring now visible at
> `src/components/layout/sidebar.tsx:295,302`). Start at **Task 6**. Do not
> redo 1-5; read them only for the helper signatures they established.
>
> Every `file:line` below was re-verified against `main` at **`6609ce8`**.
> Three were stale and are now corrected: the Overview line ranges in
> Task 6, the hamburger line in Task 5, and a claim that
> `plant/page.tsx` still had `perPage: 5000` caps (it does not).
>
> **Still treat every `file:line` as a hint, not an address.** The
> dropdown-removal steps deliberately anchor on identifier names and code
> snippets: match on the name, then check the surrounding code looks like
> the snippet. If it doesn't, the file has moved on — re-read it rather
> than editing by line number.
---
@ -836,7 +843,7 @@ export function Topbar({ title, subtitle, right }: { title: string; subtitle?: s
<h1 className="text-2xl font-bold tracking-tight text-foreground">{title}</h1>
{subtitle && <p className="mt-1 text-sm text-muted-foreground">{subtitle}</p>}
{/* Mobile: the scope pill gets its own row. The hamburger is
position:fixed over the topbar's left edge (line 252), so
position:fixed over the topbar's left edge (line 256), so
the two would otherwise compete for that space. */}
<div className="mt-2 lg:hidden">
<React.Suspense fallback={null}>
@ -911,7 +918,7 @@ import {
- [ ] **Step 2: Replace the capped sites read and filter every collection**
In the `Promise.all` at `src/app/dashboard/page.tsx:64-88`, replace the five reads with:
In the `Promise.all` at `src/app/dashboard/page.tsx:72-89`, replace the five reads with:
```tsx
// getFullList, not getList(1, 50) — the cap silently dropped site 51+
@ -944,7 +951,7 @@ In the `Promise.all` at `src/app/dashboard/page.tsx:64-88`, replace the five rea
Note the `sites` read filters on `id`, not `site` — it *is* the sites collection. `siteFilter()` is wrong there by construction, which is why it is spelled out.
Then apply `siteF` to the four single-row counts below it (`src/app/dashboard/page.tsx:89-106`):
Then apply `siteF` to the four single-row counts below it (`src/app/dashboard/page.tsx:92-106`):
```tsx
const casuals = await pb
@ -966,9 +973,31 @@ Then apply `siteF` to the four single-row counts below it (`src/app/dashboard/pa
`sites` is now an array, not a list response. Update the three call sites flagged in the assessment:
- `src/app/dashboard/page.tsx:112-113` — `for (const s of sites.items)` becomes `for (const s of sites)`.
- `src/app/dashboard/page.tsx:157` — `sites.items.length` becomes `sites.length`.
- `src/app/dashboard/page.tsx:191-193` — the `data.sites[0]?.name` sub-label: delete it. It was never meaningful with more than one site (assessment Tier 3.10), and with a scope switcher above it, it is actively misleading.
`sites` is now an array, not a list response. There are **four**
`sites.items` uses inside `loadOverview`, not two — all verified present:
- `:134` — `for (const s of sites.items) siteById.set(s.id, s);` becomes `for (const s of sites)`.
- `:185` — the returned `sites: sites.items,` becomes just `sites,`.
- `:204` — `okSiteCount: sites.items.length - problemSites.length` becomes `sites.length - problemSites.length`.
- `:206` — `rain: await loadRainOutlook(sites.items),` becomes `loadRainOutlook(sites)`.
Then the misleading "Sites" sub-label. This plan originally said to
delete `sub: data.sites[0]?.name ?? "No sites yet",` outright (assessment
Tier 3.10). **As implemented it was made scope-aware instead, which is
better — keep it:**
```tsx
sub: scope.mode === "all" ? "Across every site" : data.sites[0]?.name ?? "No sites yet",
```
Under a single-site scope `data.sites` holds exactly that one site, so
`data.sites[0]?.name` is correct rather than arbitrary; the only broken
case was "all", and that now reads "Across every site". Do not revert
this to a deletion.
The other `data.sites` uses (`:216`, and the list at `:315`, `:318`,
`:322`) need **no change** — `data.sites` was already an array on the
consuming side and stays one.
Grep to be sure nothing is missed:
@ -1031,7 +1060,7 @@ export default async function Page({ searchParams }: { searchParams: Promise<Sea
const pb = await pbAdmin();
```
3. Add the filter to every collection read that carries a `site` relation. In `src/app/dashboard/plant/vehicles/page.tsx:18-27` that means:
3. Add the filter to every collection read that carries a `site` relation. In `src/app/dashboard/plant/vehicles/page.tsx:17-28` that means:
```tsx
const [vehicles, fuelLogs, fuelPrices, sites] = await Promise.all([
@ -1049,7 +1078,9 @@ The `unit_type` fragment contains `||`, so it **must** go through `composeFilter
The `sites` read stays unfiltered: it is a lookup table for `project_code` display, not a data read.
Apply the same shape to `plant/equipment/page.tsx` (its own `unit_type` filter), `plant/fuel-logs/page.tsx`, and `plant/page.tsx`. In `plant/page.tsx`, also replace the three `perPage: 5000` caps (`src/app/dashboard/plant/page.tsx:21,26,30`) with plain `getFullList` — assessment Tier 2.4, and the next silent-truncation bug after the sites/50 one.
Apply the same shape to `plant/equipment/page.tsx` (its own `unit_type` filter), `plant/fuel-logs/page.tsx`, and `plant/page.tsx`.
**Correction to an earlier draft of this plan:** it claimed `plant/page.tsx` still had three `perPage: 5000` caps to lift (assessment Tier 2.4). It does not — `src/app/dashboard/plant/page.tsx:26-27` are already plain `getFullList` calls. Nothing to lift; just add the scope filter.
- [ ] **Step 2: Pass `showSiteColumn` instead of `projectCodes`**
@ -1244,9 +1275,9 @@ git commit -m "feat(site-scope): scope the Financial pages, drop the project dro
## Task 10: Scope the pump and plant sheet lists
**Files:**
- Modify: `src/app/dashboard/plant/fuel-logs/page.tsx:20`
- Modify: `src/app/dashboard/plant/fuel-logs/page.tsx:21`
There is exactly one such read in the dashboard — `fuel_sheets` at `src/app/dashboard/plant/fuel-logs/page.tsx:20`. `plant_hours_sheets` is not listed on any dashboard page yet; when it is, it needs the same treatment. Verified with `grep -rn "fuel_sheets\|plant_hours_sheets" src/app/`.
There is exactly one such read in the dashboard — `fuel_sheets` at `src/app/dashboard/plant/fuel-logs/page.tsx:21`. `plant_hours_sheets` is not listed on any dashboard page yet; when it is, it needs the same treatment. Verified with `grep -rn "fuel_sheets\|plant_hours_sheets" src/app/`.
- [ ] **Step 1: Use the widened filter**