- FRAMEWORK.md: the host + pluggable-agent contract, the roster, and the
clone+assign flow
- configure.mjs: ensure a default agents roster on a fresh clone
- .memory/{qa-agent,webdesigner}.md: framework notes pointing at the module layout
Verified: a scratch clone with a different site.config.json yields a different
identity + roster from identical core code.
142 lines
8.6 KiB
Markdown
142 lines
8.6 KiB
Markdown
# The Web Designer — a core Astroagent console update
|
|
|
|
**Status:** Implemented · **Date:** 2026-07-24
|
|
**Related:** [qa-agent.md](qa-agent.md) · [../agents/console/PLAN.md](../agents/console/PLAN.md) · [../agents/console/SETUP.md](../agents/console/SETUP.md) · [../brand/BRAND.md](../brand/BRAND.md) · [../.claude/skills/brand/SKILL.md](../.claude/skills/brand/SKILL.md) · [../.claude/skills/changelog/SKILL.md](../.claude/skills/changelog/SKILL.md)
|
|
|
|
---
|
|
|
|
## What it is
|
|
|
|
The **Web Designer** is a new capability of the **astroagent console** — the base's
|
|
in-site authoring engine (`agents/console/server.mjs`). It is not a separate OS agent; it
|
|
is a new *mode* of the existing confined runner (`carlos-arias-agent`), reached through the
|
|
already-gated `/devconsole/` nginx prefix.
|
|
|
|
You hand it a **brief for any page** — a prompt/instructions, a draft, uploaded images, and
|
|
links to short videos — and it does real design work (edit a section, restyle a component,
|
|
lay out a new page) and publishes. Briefs are **queued**; the agent drains the queue one task
|
|
at a time.
|
|
|
|
This is a **core engine change**, not site content — a fresh SeedProject clone that runs the
|
|
migration + `configure.mjs` inherits the whole thing. (See the site-coupling caveat below for
|
|
the one thing that is not yet fully clone-clean.)
|
|
|
|
It coexists with two sibling surfaces built earlier in the same arc:
|
|
- the **in-page console** (the ▲ handle) — freeform, contextual, preview→publish by hand;
|
|
- the **project builder** (`/admin/projects/new` → `/devconsole/build-project`) — the
|
|
*structured* path that writes a `cja_projects` row.
|
|
|
|
The Web Designer is the *freeform, queued* path for everything else.
|
|
|
|
> **Framework note (2026-07-24):** the console runner was refactored into a generic host +
|
|
> pluggable agent modules ([FRAMEWORK.md](../agents/console/FRAMEWORK.md)). The Web Designer now
|
|
> lives in `agents/console/agents/web-designer.mjs` (exports `manifest` + `register`), is enabled
|
|
> via the `astroagent.config.json` roster, and exposes `host.drainTasks` (QA autofix kicks it).
|
|
> Logic unchanged from below.
|
|
|
|
## Added after first write (2026-07-24)
|
|
|
|
Two capabilities were added to the Web Designer after this doc's first version:
|
|
|
|
- **Self-logs every change to the changelog.** `buildDesignPrompt` instructs the agent, after
|
|
finishing, to add one entry to `api/cli/seed-changelog.php` via the `changelog` skill,
|
|
attributed to **`Website Designer Agent`**, with the current timestamp (injected by the
|
|
runner via `nowStamp()` — a headless agent can't read the clock). Because the confined agent
|
|
has no shell, **the runner reseeds** `cja_changelog` (`php api/cli/seed-changelog.php`) when
|
|
that file changed, before the build, so the entry goes live. Changelog entries carry a
|
|
`by`/`actor` field (migration 012): agents name themselves; human/CLI edits default to
|
|
`Carlos Arias`.
|
|
- **Fed by the QA agent.** QA findings become Web Designer tasks — auto-queued for safe
|
|
categories, or dispatched from the `/admin/qa` instructions box. A QA-origin task is just a
|
|
normal `cja_tasks` row, so it fixes, publishes, and self-logs like any other. See
|
|
[qa-agent.md](qa-agent.md) for the closed loop.
|
|
|
|
**Timezone note:** `nowStamp()` uses the runner's system timezone, set to `America/New_York`
|
|
on 2026-07-24 (was UTC, which mis-stamped early agent entries).
|
|
|
|
## Architecture
|
|
|
|
```
|
|
/admin/designer ──create task──▶ cja_tasks (queued) [PHP: admintasks controller]
|
|
│ poll status ▲
|
|
└──kick──▶ /devconsole/tasks/run ── drainTasks() loop [Node runner]
|
|
│ claim next (php api/cli/tasks-next.php)
|
|
│ run design agent: claude -p (skills + brief, Write/Edit)
|
|
│ build → git commit LIVE (auto-publish)
|
|
│ mark finished (php api/cli/tasks-finish.php)
|
|
└─ next task …
|
|
```
|
|
|
|
The Node runner is deliberately dependency-free (no DB driver), so it reads/updates the queue
|
|
by shelling out to small **PHP CLI helpers** — keeping MariaDB behind the single PHP data
|
|
layer. The design work itself is a `claude -p` spawn, the same harness as the in-page console.
|
|
|
|
### Locked decisions
|
|
|
|
| Question | Decision |
|
|
|---|---|
|
|
| Scope of the agent | **Full builder** — may edit any page and create new pages (updating the nav in `Header.astro` + `Footer.astro`). |
|
|
| Publish model | **Auto-publish & continue.** Each task builds, commits live, and the queue advances hands-off. Safety net = git history (one revert per task) + a build-must-pass gate. |
|
|
| Skills | **CLI-native.** Skills live under `.claude/skills/` so `claude` auto-discovers them; the persona also reads them explicitly for headless reliability. |
|
|
| Queue store | **DB table `cja_tasks`** (durable, survives restart), not the in-memory `jobs` Map. |
|
|
| Runner ↔ DB | **PHP CLI bridge** (`tasks-next.php` / `tasks-finish.php`); the runner stays dependency-free. |
|
|
| Progress UX | **Polling** `admintasks/list`, not SSE — sidesteps the drifted server/DevConsole event contract. |
|
|
|
|
## Skills (the CLI-native design brain)
|
|
|
|
`.claude/skills/` is new and is what makes the agent design rather than merely edit:
|
|
- `brand/SKILL.md` — the sumi-e brand system distilled from `brand/BRAND.md` (the seal rule,
|
|
palette tokens, type scale, radii, do/don'ts). **This file is the site-specific piece** — a
|
|
clone swaps its contents.
|
|
- `ui-ux/` — a symlink to the existing generic `app/.astroagent/skills/ui-ux` (reusable).
|
|
|
|
Before my change the console passed **no** skill wiring at all; the skills array in
|
|
`astroagent.config.json` was inert. The runner still passes no `--skill` flag — discovery is
|
|
by location (`.claude/skills/`) plus an explicit "read these SKILL.md files" instruction in
|
|
the design persona.
|
|
|
|
## Safety model
|
|
|
|
- **Clean-tree guard.** A task refuses to run if the git scope (`app brand api/db api/cli`) is
|
|
dirty — otherwise the auto-publish `git add` would sweep unrelated WIP into the task's
|
|
commit. Uploaded assets under `app/public/media/` are exempt (they *are* the task's images
|
|
and get committed with it). This guard exists because exactly that hazard bit during the
|
|
build: an uncommitted file was swept into a task commit and a revert then deleted it.
|
|
- **Build-must-pass gate** before any commit; a failing task reverts its own edits
|
|
(`git checkout` + `clean`) and the queue continues.
|
|
- **Scoped commits** — `git add` never touches secrets/config, only `app brand api/db api/cli`
|
|
(+ media). The agent runs confined, Write/Edit within the repo only.
|
|
- **Single-flight** — the queue shares the runner's global `busy` lock, so a draining queue and
|
|
the in-page console can never run at once (the console returns 429 while draining).
|
|
|
|
## Files
|
|
|
|
| File | Role | Core / site |
|
|
|---|---|---|
|
|
| `agents/console/server.mjs` | `buildDesignPrompt`, `runDesignTask`, `drainTasks`, `POST /devconsole/tasks/run` | **core** |
|
|
| `api/db/migrations/011_create_cja_tasks.sql` | queue table | **core** |
|
|
| `api/public/controllers/admintasks.php` | create / list / get / cancel | **core** |
|
|
| `api/cli/tasks-next.php` | atomic claim (queued → running) | **core** |
|
|
| `api/cli/tasks-finish.php` | mark published / failed + result | **core** |
|
|
| `app/src/pages/admin/designer.astro` | submit brief + poll the queue | **core** |
|
|
| `app/src/layouts/AdminLayout.astro` | "Web Designer" nav link | **core** |
|
|
| `.claude/skills/ui-ux` (symlink) | generic design skill | **core** |
|
|
| `.claude/skills/brand/SKILL.md` | this site's brand | **site-specific** |
|
|
|
|
## Site-coupling caveat (not yet clone-clean)
|
|
|
|
The prompt-builders in `server.mjs` — both the new `buildDesignPrompt` and the pre-existing
|
|
`buildPrompt` — **hardcode** "the Carlos Arias website" and "sumi-e" directly in the engine.
|
|
This site identity was already baked into the console before this change; the Web Designer
|
|
matches that pattern rather than adding new debt. For a truly clone-clean base, those strings
|
|
should be sourced from `site.config.json` / `astroagent.config.json` + the `brand` skill,
|
|
leaving the runner site-agnostic. Deferred — flagged, not done.
|
|
|
|
## How to run it
|
|
|
|
1. Sign in to the admin (secret link), open **/admin/designer**.
|
|
2. Submit a brief: pick a page (or "New page"), write instructions, optionally a draft,
|
|
upload images, paste short-video links → **Add to queue & run**.
|
|
3. The queue drains automatically; each row shows `queued → running… → published`
|
|
(with a live link + commit) or `failed` (with the reason).
|
|
4. Undo any task with `git revert <commit>` on `main`, then rebuild.
|