plans/ held 58 documents and exactly one said whether it was open. The rest
mixed finished work, reviews of shipped work, parked specs and genuinely
pending ones, with nothing distinguishing them, so "how many plans are in
the queue" had no answer short of reading all 58.
Now `grep -H '^Status:' plans/*.md` is the answer:
50 done 3 in progress 2 planned 2 reference 1 parked
Statuses were derived rather than guessed: CLAUDE.md's own built list and
"What's NOT built yet" section, plus checking the subject exists in the
code. A review of work that shipped counts as done -- it records what was
found, it is not a request for anything. `reference` separates the two docs
that are conventions rather than work items (admin-design-standards,
admin-work-framework), which otherwise read as permanently-open plans.
The vocabulary is deliberately five words. A larger one invites "mostly
done" and "blocked-ish", which is how the directory became unreadable.
test_plans_declare_status.py keeps it from rotting: a new plan without a
marker fails, as does an unknown status, one buried below the eighth line,
or an open status with no reason -- "planned" alone is the state that rots,
since nobody can tell later whether it waits on a decision, a dependency,
or just nobody's turn.
Also updates the sweep plan with what landed and what did not, including
that #9 was not a defect.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VRQXz5SYZYVWscxS1QqF6U
122 lines
5.6 KiB
Markdown
122 lines
5.6 KiB
Markdown
# Admin UI Work Framework
|
||
|
||
Status: reference -- how admin work is scoped and reviewed
|
||
|
||
How to produce the class of result the `c22bbae` Controls relayout did — work so
|
||
specific it stands alone as a learning input, written as **rules the next page
|
||
can apply**, backed by evidence a fresh model can trust.
|
||
|
||
This framework is about the *craft* of touching the admin portal, not the visual
|
||
styles (those live in `admin-design-standards.md`). Read the Standards doc first;
|
||
this doc is the method.
|
||
|
||
## Why this exists
|
||
|
||
Before `c22bbae`, the admin UI got "fixed" in ways that didn't transfer: a review
|
||
category said "card is a single line of buttons," and a future page could easily
|
||
re-produce the same dead column. The Controls relayout broke that pattern by
|
||
**turning each observed defect into a rule the next page can mechanically apply**
|
||
("don't restate the control's own value," "single-line button strip goes full
|
||
width"). The commit message is the artifact worth feeding a model: it spells out
|
||
the three problems, why each fix is what it is, and the two consistency fixes —
|
||
with enough context to stand alone.
|
||
|
||
## The method (5 moves)
|
||
|
||
### Move 1 — Diagnose at the surface, in the running browser
|
||
|
||
Look at the page as a user does: full viewport and at 800px, before and after a
|
||
`REFRESH_MS` poll. Name the defect in one concrete sentence before you touch
|
||
anything.
|
||
|
||
Good defect statements (from the real commit):
|
||
- "Operational Triggers is a single line of buttons but sat in a col-xl-6 next
|
||
to a much taller card, so half that row is permanently empty."
|
||
- "Both settings panels used a 5/3/4 Bootstrap grid, which put the control
|
||
mid-row at three different widths and spent a whole trailing column restating
|
||
the value the control already displays."
|
||
- "Rows alternated switches and text inputs, which differ ~10px in natural
|
||
height and read as ragged."
|
||
|
||
These are *specific and falsifiable*. "Fix the controls page layout" is not a
|
||
diagnosis — it's a wish.
|
||
|
||
### Move 2 — Extract the grammar, not the look
|
||
|
||
Don't record "Controls page uses `grid-template-columns:minmax(0,1fr) auto 176px`."
|
||
Record the *transferable principle* behind it, plus the code as evidence:
|
||
|
||
> A settings list is one CSS-grid row — key | meta | control — not Bootstrap
|
||
> `.row/.col-*`. A fixed control track is the point: every switch, input and
|
||
> select lands on the same right edge, so the eye scans one column.
|
||
|
||
Then back it with the exact CSS so a future page can copy it. Grammar lives at
|
||
the level of "what column exists and why," not "which pixel value."
|
||
|
||
Rule templates that transfer:
|
||
- **Do not add a column that restates the control's own value.** The meta
|
||
track is for facts the control cannot show.
|
||
- **A card whose content is a single line of buttons goes full width** with the
|
||
buttons in `.card-actions`, not into a `col-xl-6` beside a tall card.
|
||
- **Rows with a switch next to a text input need a fixed min-height** or they
|
||
read as ragged.
|
||
- **Boolean persisted-config controls use switches**, matching runtime knobs —
|
||
not bare checkboxes.
|
||
|
||
### Move 3 — Keep old constraints load-bearing
|
||
|
||
Every change must be verified against the survival checklist (S1–S5) in
|
||
`admin-facelift.md` and the `learnings.md` notepad:
|
||
- `escapeHtml()` on every interpolated string
|
||
- chart instance reuse (never `.data.labels` mutation on the verdict bar)
|
||
- `renderWarnings` inline placeholder rebuild
|
||
- `saveAllConfig` stays sequential (`for...of await`, no `Promise.all`)
|
||
- SSE status pill reflects real EventSource state
|
||
|
||
If your change touches any of these, call it out explicitly in the commit.
|
||
|
||
### Move 4 — Prove it, not just observe it
|
||
|
||
A single fresh-load screenshot has missed canvas-reuse and selector bugs twice
|
||
in this project. Minimum evidence bar for an admin page change:
|
||
1. `python -m pytest` — full suite (733 tests) green.
|
||
2. Playwright load at 1400px **and** 800px, plus one 30s+ idle past `REFRESH_MS`,
|
||
with **zero console errors** (beyond the benign `/favicon.ico 404`).
|
||
3. The exact interaction under change exercised by hand (toggle, save, range).
|
||
|
||
Save the screenshots under `plans/` (e.g. `admin-controls-relayout.jpg`).
|
||
|
||
### Move 5 — Write the commit as the learning input
|
||
|
||
The commit message is documentation for the next model. Structure it as:
|
||
- **The problem(s)**, each in one concrete sentence (Move 1).
|
||
- **Why each fix is what it is** — the reasoning, not just the change.
|
||
- **Consistency fixes** called out separately from the main change.
|
||
- **Test changes** explained (why the old assertion no longer held).
|
||
|
||
Follow with a `git show <sha>` that a fresh session can read and immediately
|
||
apply.
|
||
|
||
## Also update the Standards doc in the same commit
|
||
|
||
When the change teaches a new transferable rule, add it to
|
||
`plans/admin-design-standards.md` *in the same commit* so doc and code can
|
||
never drift. Write the new section in rule form ("Do not add a column that
|
||
restates the control's own value"), not as a description of the one page. That
|
||
is what makes it applicable to the *next* page.
|
||
|
||
## Repository of what this produces
|
||
|
||
- `plans/admin-design-standards.md` — the accumulated grammar (settings
|
||
rows, card-level layout, hard-won rules 1–10, data patterns).
|
||
- `.omo/notepads/admin-facelift/learnings.md` — the chronological record of
|
||
every diagnosis/fix/QA, including the false-starts that were corrected.
|
||
- `plans/*.md` — the post-hoc audits that catch what the QA pass missed.
|
||
- Commit messages themselves — the highest-signal, standalone learning input.
|
||
|
||
## When to use this framework
|
||
|
||
- Any visible change to `admin/frontend/*.html` or the `/admin` API surface.
|
||
- Any downstream admin page you might build (e.g. an Audit/Logs page, wiring in
|
||
`admin_schema.sql` RBAC) — apply the grammar first, then the visuals.
|