docs: require impeccable skill for design and frontend
Adds the design-system issue, scaffolds .impeccable/live/config.json against web/index.html, and records the aoe spawn commands for the codex GPT-5.6 models in the driver table. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+70
-15
@@ -170,6 +170,9 @@ embedded into the binary with `include_dir` and served with correct MIME types.
|
||||
- Dev mode proxies `/api/*` to the running daemon so the SPA has hot reload.
|
||||
- One page that calls `GET /api/health` and renders it, to prove the whole path.
|
||||
|
||||
Use the `impeccable` skill for this — see the design section of `CLAUDE.md`.
|
||||
|
||||
|
||||
Acceptance: `cargo run` serves the built SPA from a single binary with no
|
||||
external files.
|
||||
""",
|
||||
@@ -625,10 +628,40 @@ client compiles.
|
||||
),
|
||||
|
||||
# ---------------------------------------------------------------- phase 5
|
||||
issue(
|
||||
"design", "Design system tokens",
|
||||
"phase/5-ui", "area/web", "difficulty/moderate",
|
||||
deps=["web"],
|
||||
body="""
|
||||
Author `.impeccable/design.json` — colours, typography, spacing, the token set
|
||||
every component consumes. **Use the `impeccable` skill for this**; it is what
|
||||
the file's schema belongs to (`CLAUDE.md`, design section).
|
||||
|
||||
`~/tea/arcada` has a finished `design.json` at `schemaVersion: 2` worth reading
|
||||
first for the shape.
|
||||
|
||||
Constraints specific to this app:
|
||||
|
||||
- The manual-search view (`DESIGN.md` §9.3) is dense, tabular and chip-heavy.
|
||||
The palette has to carry three verdict states — eligible, waived, rejected —
|
||||
legibly at small sizes and against each other, without relying on colour
|
||||
alone.
|
||||
- Library status (§4.2) is five states, and they are informational rather than
|
||||
severity-ranked. Do not borrow an error/warning/success ramp for them.
|
||||
- It runs on a NAS dashboard, often on a phone, often in a dark room. Dark mode
|
||||
is not an afterthought.
|
||||
|
||||
`.impeccable/live/config.json` is already scaffolded and points at
|
||||
`web/index.html`.
|
||||
|
||||
Acceptance: components consume tokens, never literal colour or spacing values,
|
||||
and CI can assert that.
|
||||
""",
|
||||
),
|
||||
issue(
|
||||
"uisearch", "Unified search box",
|
||||
"phase/5-ui", "area/web", "difficulty/moderate",
|
||||
deps=["web", "searchapi", "moviesapi"],
|
||||
deps=["web", "design", "searchapi", "moviesapi"],
|
||||
body="""
|
||||
`DESIGN.md` §9.2. One box, results grouped: in-library first, TMDB below. Enter
|
||||
on a TMDB result opens the add flow with root and policy pre-filled.
|
||||
@@ -639,13 +672,16 @@ The requirement, stated as a test: there is never a moment where the user has to
|
||||
know whether they are searching or adding. If the UI has an "Add Movie" page
|
||||
separate from search, this issue is not done.
|
||||
|
||||
Use the `impeccable` skill for this — see the design section of `CLAUDE.md`.
|
||||
|
||||
|
||||
Debounce, and cancel in-flight requests on keystroke.
|
||||
""",
|
||||
),
|
||||
issue(
|
||||
"uimanual", "Manual search buckets and attribute chips",
|
||||
"phase/5-ui", "area/web", "difficulty/moderate",
|
||||
deps=["web", "searchapi"],
|
||||
deps=["web", "design", "searchapi"],
|
||||
body="""
|
||||
`DESIGN.md` §9.3. The fix for Radarr's unusable manual search.
|
||||
|
||||
@@ -659,12 +695,15 @@ Debounce, and cancel in-flight requests on keystroke.
|
||||
- One click on a `waived` row grabs it and writes the override.
|
||||
|
||||
The client must not re-implement any policy. Verdicts arrive from the API.
|
||||
|
||||
Use the `impeccable` skill for this — see the design section of `CLAUDE.md`.
|
||||
|
||||
""",
|
||||
),
|
||||
issue(
|
||||
"uilibrary", "Library views with derived status",
|
||||
"phase/5-ui", "area/web", "difficulty/moderate",
|
||||
deps=["web", "moviesapi"],
|
||||
deps=["web", "design", "moviesapi"],
|
||||
body="""
|
||||
`DESIGN.md` §4.2. The default view shows `airing` and `incomplete` only;
|
||||
everything else collapses behind one toggle.
|
||||
@@ -675,12 +714,15 @@ the exact problem this design removed.
|
||||
|
||||
Show waivers honestly: a file imported under `allow_english_audio` reads as
|
||||
"English, no dub", not as a clean match.
|
||||
|
||||
Use the `impeccable` skill for this — see the design section of `CLAUDE.md`.
|
||||
|
||||
""",
|
||||
),
|
||||
issue(
|
||||
"uiqueues", "Attention queues: no-PT-source and needs-decision",
|
||||
"phase/5-ui", "area/web", "difficulty/easy",
|
||||
deps=["uilibrary", "failure"],
|
||||
deps=["uilibrary", "design", "failure"],
|
||||
body="""
|
||||
`DESIGN.md` §5.2 and §5.7. Two lists of things a human has to look at.
|
||||
|
||||
@@ -691,6 +733,9 @@ Show waivers honestly: a file imported under `allow_english_audio` reads as
|
||||
|
||||
These are the only places the app asks for attention, and they are the same
|
||||
events that notify (§9.5). Keep them consistent.
|
||||
|
||||
Use the `impeccable` skill for this — see the design section of `CLAUDE.md`.
|
||||
|
||||
""",
|
||||
),
|
||||
|
||||
@@ -929,32 +974,42 @@ def main():
|
||||
by_title = {i["title"]: i["number"] for i in open_issues}
|
||||
numbers = {}
|
||||
|
||||
# Pass 1 — ensure every issue exists, so dependency numbers are all known
|
||||
# before any body is rendered.
|
||||
for spec in ISSUES:
|
||||
title = spec["title"]
|
||||
if title in by_title:
|
||||
numbers[spec["key"]] = by_title[title]
|
||||
print(f"issue = #{by_title[title]} {title}")
|
||||
continue
|
||||
|
||||
body = spec["body"]
|
||||
if spec["deps"]:
|
||||
refs = []
|
||||
for d in spec["deps"]:
|
||||
refs.append(f"#{numbers[d]}" if d in numbers else f"`{d}` (not yet created)")
|
||||
body += "\n\n---\n\n**Depends on:** " + ", ".join(refs)
|
||||
body += f"\n\nLabels: `{'`, `'.join(spec['labels'])}`"
|
||||
|
||||
print(f"issue + {title}")
|
||||
if DRY:
|
||||
continue
|
||||
made = req("POST", f"/repos/{OWNER}/{REPO}/issues", {
|
||||
"title": title,
|
||||
"body": body,
|
||||
"body": spec["body"],
|
||||
"labels": [label_ids[n] for n in spec["labels"] if n in label_ids],
|
||||
})
|
||||
if made:
|
||||
numbers[spec["key"]] = made["number"]
|
||||
|
||||
# Pass 2 — render bodies with real dependency numbers and push them.
|
||||
# Declarative: this overwrites hand-edits to issue bodies. Edit the spec
|
||||
# here, not the issue on Gitea.
|
||||
for spec in ISSUES:
|
||||
if spec["key"] not in numbers:
|
||||
continue
|
||||
body = spec["body"]
|
||||
if spec["deps"]:
|
||||
refs = ", ".join(f"#{numbers[d]}" for d in spec["deps"] if d in numbers)
|
||||
body += f"\n\n---\n\n**Depends on:** {refs}"
|
||||
body += f"\n\nLabels: `{'`, `'.join(spec['labels'])}`"
|
||||
if DRY:
|
||||
continue
|
||||
req("PATCH", f"/repos/{OWNER}/{REPO}/issues/{numbers[spec['key']]}", {
|
||||
"body": body,
|
||||
"labels": [label_ids[n] for n in spec["labels"] if n in label_ids],
|
||||
})
|
||||
|
||||
print(f"\n{len(numbers)}/{len(ISSUES)} issues present")
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user