Commit graph

44 commits

Author SHA1 Message Date
56c1926b81 qa: QA agent — HTTP site testing with one-click Web Designer fixes
- migration 013: cja_qa_runs + cja_qa_findings
- runner: runQa (crawl pages/links/images/external/contact-probes/health/
  SEO/meta/sitemap/a11y), qaTriage (LLM summary via qa skill), /devconsole/qa/run
- qa-start/finish/routes.php CLI bridge
- adminqa controller (runs/findings/fix/ignore); fix() chains to the Web
  Designer queue; /admin/qa report page + nav link
- qa skill; contact form probed via honeypot (writes nothing)
2026-07-24 03:30:13 +00:00
f832752118 changelog: log this session's admin fixes + attribution/self-logging 2026-07-24 02:52:55 +00:00
75dcfc3098 Revert "web designer: Changelog self-log test"
This reverts commit d0924ffadf.
2026-07-24 02:47:24 +00:00
d0924ffadf web designer: Changelog self-log test
[published via task queue]
2026-07-24 02:46:57 +00:00
df5e5f9456 changelog: 'by' attribution + Web Designer self-logs via the skill
- migration 012: cja_changelog.actor column
- seed-changelog: optional 5th 'by' element (defaults to Carlos Arias);
  display shows 'Added · time · by <actor>'
- changelog skill documents the actor field + attribution logic (agents name
  themselves, human/CLI edits are Carlos Arias)
- Web Designer prompt now logs each change to the changelog via the skill,
  attributed to 'Website Designer Agent'; runner reseeds cja_changelog when the
  seed file changed (the agent has no shell)
2026-07-24 02:45:53 +00:00
2ad551dc5f skills: add changelog skill (seed-changelog process, format, voice) 2026-07-24 02:39:01 +00:00
11b2f960a9 web designer: The service Website Design should be linked to /services/website-design for SEO
[published via task queue]
2026-07-24 02:36:26 +00:00
15292f66fc admin: fix login screen showing both panels + add dashboard links
- .panel's display:flex was overriding the [hidden] attribute, so the Sign-in
  form and 'You're in' panel showed at once regardless of session. Force
  [hidden] { display:none !important } so they toggle.
- 'You're in' now links to Web Designer, Manage projects, and the site.
2026-07-24 02:35:20 +00:00
a906ef026f admin: fix white-on-white select dropdown in dark mode
Native <option> popups used the browser default (white) background; in dark
mode the var(--ink) text rendered near-white on it. Give the select a themed
background and style option explicitly. Fixes the Web Designer Page picker and
the project editor status dropdown.
2026-07-24 02:34:04 +00:00
497f55364b changelog: admin + Web Designer arc; document the engine update
- seed-changelog: 5 entries (admin console, self-editing agent, uploads,
  project builder, Web Designer + task queue)
- .memory/webdesigner.md: core Astroagent console update — architecture,
  decisions, safety model, files, and the site-coupling caveat
2026-07-24 01:28:09 +00:00
fa85561d12 Revert "web designer: Add test FAQ with image"
This reverts commit 7a3d5dbf4c.
2026-07-24 00:22:59 +00:00
7a3d5dbf4c web designer: Add test FAQ with image
[published via task queue]
2026-07-24 00:22:28 +00:00
364fd1b425 web designer: guard ignores uploaded media assets (app/public/media) 2026-07-24 00:20:52 +00:00
50f6db55d8 web designer: /admin/designer workspace (submit brief + poll queue) 2026-07-24 00:19:46 +00:00
7fc99415b4 web designer: task queue engine + CLI-native design skills
- .claude/skills/: brand skill (from BRAND.md) + ui-ux symlink, so the CLI
  loads design skills natively
- cja_tasks queue (migration 011) + admintasks controller (create/list/get/cancel)
- api/cli/tasks-next.php (atomic claim) + tasks-finish.php
- runner: buildDesignPrompt, runDesignTask (clean-tree guard, build-gate,
  auto-publish commit or revert), drainTasks loop, POST /devconsole/tasks/run
2026-07-24 00:16:39 +00:00
ad0892a539 Revert "web designer: Queue engine test"
This reverts commit d4ee3ff960.
2026-07-24 00:14:44 +00:00
d4ee3ff960 web designer: Queue engine test
[published via task queue]
2026-07-24 00:14:28 +00:00
faef1c3229 admin: Web Designer agent builds full project pages from a brief
- console /build-project: Read-only agent reads uploaded images and authors a
  complete cja_projects record (copy, kind/period/role, categories, stack,
  grouped skills, metrics, per-image captions). Server re-zips gallery srcs.
- adminprojects save()/get(): handle skills + metrics JSON columns
- New Project form: 'Build with Web Designer' + full editable preview
  (skills groups, metric cards, captions merged into gallery)
- editor: round-trip skills + metrics editing
2026-07-23 23:44:50 +00:00
a88cc41557 admin: New Project page with agent-drafted copy + full editor
- /admin/projects/new: name, category, description draft, agent prompt,
  image upload, Instagram link
- console /draft endpoint: one-shot Claude copy drafting (summary/lede/body)
- editor now edits all project text fields, not just gallery
- adminprojects create() + expanded save()
2026-07-23 23:23:33 +00:00
a2da708418 Phase 2/3: projects media admin (galleries + Instagram)
- /admin/projects list + /admin/projects/edit gallery editor (AdminLayout chrome,
  session-guarded). Upload/replace images per slot, captions, add/remove,
  Instagram reel URL. Save -> cja_projects -> rebuild -> live.
- adminprojects API (list/get/save); media path validation (local paths only).
- runner /rebuild endpoint: build public/ + commit after structured edits.
- Ownership: app/ + public/ now owned by carlos-arias-agent:caweb so the agent
  can rebuild its own output; www serves via the caweb group. Documented in
  SETUP.md — never build as root.

Verified end to end: upload image -> save to gallery -> rebuild -> image live on
the project page and served.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DoFYZY9gkGPNDqZ7NuEa9a
2026-07-23 22:55:32 +00:00
dc69d1fd0d Phase 2: media upload pipeline
- cja_media table; POST /api/media/upload (admin-gated, multipart).
- Images optimised with GD (downscale to 1600px, re-encode; WebP for
  transparency, JPG for photos). Video via ffmpeg (scale, compress, drop audio).
- Stored in app/public/media/ (source tree) so uploads survive rebuilds and are
  copied into public/ on build.
- requireAdmin() moved to PublicController base (fixes a static/non-static
  clash with AdminAuth). Type detection uses getimagesize (fileinfo ext absent).

Note: php-fpm must be in the caweb group to write app/public/media (restart
after adding www to caweb).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DoFYZY9gkGPNDqZ7NuEa9a
2026-07-23 22:45:45 +00:00
b967419717 Phase 1: admin login page + secret-link token auth
- /admin login page (public, noindex): password form + signed-in panel that
  activates the in-page console. Verified in-browser: login -> panel -> the
  astroagent handle appears on other pages.
- Secret-link login: visit /admin/<token> to sign in without a password.
  adminauth token() validates a bcrypt-hashed token, sets the session, 302s to
  /admin. nginx routes the token path to PHP. set-admin-token.php generates it.
- Password login kept as a fallback.

Verified: token link -> session -> console access; bad token -> /admin?e=1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DoFYZY9gkGPNDqZ7NuEa9a
2026-07-23 22:15:50 +00:00
e57856173a Phase 1: console runner service + nginx gate + systemd
- agents/console/server.mjs: Node runner (as carlos-arias-agent, 127.0.0.1:3011).
  run/stream(SSE)/publish/discard/ping/auth. Agent edits files (no Bash); the
  runner builds isolated previews and git-commits on publish. Git ops scoped to
  content paths (app, brand, api/db, api/cli) — never infra or secrets.
- adminauth check() — nginx auth_request target (204 admin / 401 not).
- nginx: /devconsole + /_preview gated by auth_request, runner proxied,
  previews admin-only. Runner never exposed directly.
- systemd unit (hardened: NoNewPrivileges, ProtectSystem, scoped ReadWritePaths).

Verified end to end: admin login -> agent edits about.astro -> isolated preview
(admin-gated) -> discard reverts. Unauthenticated access is 401 throughout.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DoFYZY9gkGPNDqZ7NuEa9a
2026-07-23 20:53:32 +00:00
59dbfa2071 Phase 1 foundation: confined agent proven
Records the operational setup (agents/console/SETUP.md). Server-side, not in git:
- confined carlos-arias-agent user (nologin, no sudo) runs headless Claude
- claude relocated to /usr/local/bin (root's install was unreachable)
- caweb shared group: agent edits+builds, www serves, no chown-to-www needed
- valid setup-token stored in agents/.env (git-ignored)

Verified: agent reads repo, writes source, runs isolated preview build, output
served by nginx. Full edit->preview->serve loop works end to end.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DoFYZY9gkGPNDqZ7NuEa9a
2026-07-23 20:36:37 +00:00
59019d2f32 Phase 0: admin console foundation
- cja_admin + cja_admin_log tables (dedicated single-admin tier + audit trail)
- AdminAuth controller: /api/adminauth login/logout/me, session-based,
  rate-limited, every attempt logged
- set-admin-password CLI (bcrypt, run manually so the password never enters
  an agent context)
- requireAdmin() guard for future privileged console endpoints
- agent env scaffold (git-ignored)

Foundation only — no agent runner or features yet. Preview/publish, media,
and the dashboard come in phases 1-3 per agents/console/PLAN.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DoFYZY9gkGPNDqZ7NuEa9a
2026-07-23 20:23:48 +00:00
43ae1e2015 Baseline: full site build (brand, pages, DB, agent-editable)
Establishes the deploy baseline on main so the admin agent's publish/rollback
has a clean starting point. Everything built to date: sumi-e brand system,
homepage, projects (DB-driven case studies), resume, about, services +
website-design detail, contact form + DB, changelog, favicon + share card.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DoFYZY9gkGPNDqZ7NuEa9a
2026-07-23 20:21:28 +00:00
2c969c0753 feat: content-pipeline/ → agents/ — formalize the agent system in the seed
Adopt the agents/ architecture proven on medellin.co (reference impl):

- Move the content engine to a top-level agents/ dir: orchestrators, prompts,
  config, run.sh, admin console, shared libs. All content-pipeline literals
  repointed (config paths, scripts, admin, LLM-facing prompts/image.md string,
  configure.mjs, new-site.sh, astroagent tokenFile, .gitignore runtime block).
- Every script carries a parseable @agent-manifest header: name, title, class
  (content|operational|runtime|plumbing), trigger, model, prompts, skills (MCP),
  tools, reads/writes tables. 5 content agents + 3 plumbing scripts.
- New agents/catalog.mjs generates the catalog from the headers:
  agents/AGENTS.md (human, grouped by class) + agents/agents.json (machine
  manifest — a clone diffs it against a source to find missing tools/tables/MCP
  before running). configure.mjs regenerates the catalog on every identity
  stamp. No DB table, no watcher.
- config.json gains paths.stateDir/newsDir; publish-tick, write-daily, and
  news-radar read them instead of hardcoding.
- Full cut: content-pipeline/ deleted (the seed has no live crons, so no
  hybrid period needed). Docs updated (AGENTS.md structure + pipeline section,
  README paths).

Clones migrating from content-pipeline/: see medellin.co's
.memory/handoffs/agents-directory-migration.md for the cutover playbook
(one cron set active at a time; migrate drafts/state after repointing cron).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FMQeUnUrAeexcZ7P2Hxa6G
2026-07-11 17:09:15 -05:00
41f1b941fa Merge: trusted-IP throttle exemption + session hardening 2026-07-11 09:16:30 -05:00
5d1505d666 Merge: user auth (email + Google OAuth), Mailer, CLI bridges 2026-07-11 09:16:30 -05:00
fc63f3ca03 Merge: full schema snapshot (structure only) 2026-07-11 09:16:30 -05:00
1f33296e30 feat: user auth (email + Google OAuth), Mailer, and CLI bridges
Generic framework features, code-only — the tables come from the schema snapshot:

- controllers/account.php — email signup (verified) + Google OAuth (server-side auth-code
  flow, async-popup friendly); native password_hash sessions on sp_users; sp_oauth_accounts +
  sp_user_tokens; PublicController origin+throttle guards; {ok,data,error} envelope.
- Helpers/Mailer.php — transactional email: Brevo HTTP API (Guzzle) -> SMTP fallback
  (PHPMailer) -> logs; config in sp_settings (encrypted).
- cli/rebuild.php — queue a static rebuild (sp_settings rebuild_pending flag) after DB edits.
- cli/resources.php — read a curated source registry (mde_resources) per agent_type.
- db/seed_google_oauth.php, db/seed_email.php — env-seeded encrypted secrets into sp_settings.
- templates/emails/verify.html — verification email template.
- composer.json — declare guzzlehttp/guzzle ^7.10 (account.php + Mailer use GuzzleHttp\Client).

Depends on the schema-snapshot branch (sp_users / sp_oauth_accounts / sp_user_tokens /
sp_settings / mde_resources) plus `composer require guzzlehttp/guzzle`. No data.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FMQeUnUrAeexcZ7P2Hxa6G
2026-07-11 09:14:25 -05:00
c542092a2a chore(db): add full schema snapshot (structure only) to bring the base current
Structure-only export from a live SeedProject site (68 tables: the sp_ framework — users,
oauth, tokens, settings, roles/permissions, api_requests, orgs, saas/billing, menus, kathe —
plus the mde_ content model: content, directory, events, comments, reactions, categories…).

Every table is CREATE TABLE IF NOT EXISTS, so it composes with the existing 001/002 migrations
and only fills in what's missing. This modernizes the base off the legacy `usergen`/`api_requests`
schema and is the prerequisite for porting the auth system, Mailer, and resource registry upstream.
No data included.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FMQeUnUrAeexcZ7P2Hxa6G
2026-07-11 09:08:46 -05:00
3f69000d27 feat: never throttle trusted server-local callers + harden session cookie
Two self-contained framework fixes, no schema dependencies:

- throttle(): exempt trusted callers via new Functions::isTrustedIp() — loopback, the
  server's own IP, and an optional TRUSTED_IPS config allowlist (IPs/CIDRs). Fixes the SSG
  build (which fetches the read API from the box thousands of times per build) tripping the
  public rate limit and baking empty data into the deploy. Public client IPs stay limited.
- public/index.php: set secure session cookie params (httponly, SameSite=Lax, secure on
  https) before session_start, so session/login state rides on a hardened cookie.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FMQeUnUrAeexcZ7P2Hxa6G
2026-07-11 09:01:49 -05:00
d085d26c78 drawer: sync visual element picker from astroagent
Pick an element on the rendered site, comment, and the agent edits the
source. Includes the discoverability fixes (SVG crosshair, pick-mode
banner) and publish auto-reload.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RCfiiNfHmDRj4ZZiFM535z
2026-07-05 00:46:30 +00:00
f41fa652ac fix: repair the fresh-clone flow — track api/public + app/public, fix installer schema
Three bugs found deploying a fresh clone to seedproject.com, each fatal
to the documented "spin up a new site" flow:

- .gitignore: the unanchored `public/` pattern (meant for the root build
  output) also ignored api/public/ (the framework's front controller,
  controllers, models, views) and app/public/ (theme static assets:
  fonts, avatar placeholder). Neither was ever committed, so every fresh
  clone 500'd on all /api routes and 404'd on theme assets. Anchor the
  pattern to /public/ and commit both directories.

- api/install/dump.sql: stray `CREATE DATABASE ochenta80_db123` (SQLyog
  export artifact) aborted `php console app:install` for any
  non-privileged DB user. The schema must import into whatever database
  the installer connects to.

- PluginManager::boot() queries sp_plugins on every request, but no
  shipped schema creates it — even a successful install 500'd on every
  endpoint. Add migration 002_create_sp_plugins.sql matching the columns
  PluginManager reads/writes.

Also empty api/system/errors.json, which shipped with stale error logs
from an unrelated project.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C3JqxTe7TKaR7xufcMr7Ds
2026-07-05 00:15:55 +00:00
4c04b5a691 docs: mark content-pipeline as deferred (niche-specific placeholder pending DB rewrite)
Decision: the JSON-based content-pipeline is optional and does not block cloning/
building a site. Rather than genericize the current JSON prompts, it will be
re-architected DB-managed via /api in a future session, with prompt genericization
folded into that. AGENTS.md now tells future agents not to genericize it prematurely.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SYHWLHihq3v9nxNwoPCKSn
2026-07-04 23:44:51 +00:00
1e6329e85c docs: make AGENTS.md honest — flag pipeline is not niche-generic, add local-dev + status/gaps
A cold-start agent reading the old text would wrongly trust the content pipeline as
config-driven and generate off-niche content. Now states the real status:
- content pipeline prompts/scripts are still Medellín-specific (not config-driven yet)
- /api backend doesn't run under 'astro dev' (needs Apache/PHP-FPM + app:install)
- /api Foundation is code-verified only; live DB/HTTP round-trip unverified
- autonomous agents should use the non-interactive configure path (new-site.sh blocks)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SYHWLHihq3v9nxNwoPCKSn
2026-07-04 23:38:29 +00:00
ae80a2cdc6 fix(configure): set content-pipeline projectRoot to the clone's path (was comiida's)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SYHWLHihq3v9nxNwoPCKSn
2026-07-04 23:34:58 +00:00
0acc80f8e4 docs: add root AGENTS.md + CLAUDE.md for fresh-clone agents; fix agentUser leftover
- AGENTS.md / CLAUDE.md: tell any agent (Claude Code, astroagent, Codex) what the
  base is and the exact fresh-clone setup flow (new-site.sh / configure.mjs / build)
- configure.mjs: stamp astroagent ai.agentUser as <slug>-agent (was stale 'comiida-agent')

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SYHWLHihq3v9nxNwoPCKSn
2026-07-04 23:33:50 +00:00
1fdfc3174b feat(api): Foundation — installer, migrations, two-tier auth, health round-trip
Builds the /api Foundation into the base (per api/.memory/foundation-plan.md):
- app/Services/Installer.php  DB test + dump.sql import + crypto keys + /api config + lock
- app/Services/Migrator.php   versioned db/migrations/*.sql runner (+ migrations table)
- commands/InstallCommand.php (app:install), commands/MigrateCommand.php (db:migrate)
- app/Controllers/{JsonController,PublicController,ApiController}  envelope + two-tier auth
- public/controllers/{health,admin}.php  GET /api/health (public), /api/admin/ping (bearer)
- db/migrations/001_*.sql  smoke migration
- install/controllers/index.php  web wizard now delegates to Installer (path bugs fixed, lock)
- console + composer.json  register commands / add commands to classmap
- app/src/pages/api-health-test.astro  browser round-trip proof page

Verified (no DB): composer install OK; php console lists app:install + db:migrate;
PSR-4 classes autoload; CLI fails gracefully (validation, bad DB, missing config) with
no artifacts left; app builds 14 pages. Live DB + HTTP round-trip pending a served instance.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SYHWLHihq3v9nxNwoPCKSn
2026-07-04 23:23:51 +00:00
0fcf707a17 chore: neutralize comiida demo prose -> generic placeholder content
Rewrote the sample pages/components to niche-neutral placeholder copy so the
base carries no Medellín/restaurant/author-specific content:
- about, faq, services  -> generic placeholder pages (structure preserved)
- index hero, Footer, Newsletter, contact, 404, BaseLayout  -> neutral copy

app/src is now free of comiida/medellin/carlos references; build = 13 pages, Complete.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SYHWLHihq3v9nxNwoPCKSn
2026-07-04 23:13:55 +00:00
92fa6c9140 feat: clone tooling — scripts/new-site.sh + README
- scripts/new-site.sh: interactive setup for a fresh clone (prompts identity,
  writes site.config.json, runs configure, optional git reset + dep install)
- README.md: what's inside, quick start, site.config.json/configure workflow,
  backend setup, directory layout

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SYHWLHihq3v9nxNwoPCKSn
2026-07-04 23:09:37 +00:00
fc84d095b8 feat: config-driven identity (site.config.json) + buildable sample content
- site.config.json  single source of identity (name/url/description/author/social)
- scripts/configure.mjs  stamps it into app, content-pipeline, and astroagent configs
- app/src/lib/blog-data.js  SITE + author now read from app/src/config/site.json
- astro.config.mjs  default site URL from config
- index.astro / Footer.astro  neutralized hardcoded title, hero alt, social link
- sample 'welcome' post + placeholder hero/avatar so the site builds out of the box

Verified: cd app && npm ci && npm run build -> 13 pages, Complete.
Remaining comiida demo prose in about/faq/services/contact + Newsletter (sample content).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SYHWLHihq3v9nxNwoPCKSn
2026-07-04 23:06:23 +00:00
1559ce017d chore: scaffold SeedProject base (Phase 1)
Clean-room copy of the reusable engines from comiida, with all
instance data, secrets, dependencies, and build output excluded:
- app/         Astro theme skeleton (no comiida blog posts; hero image -> placeholder)
- api/         SeedProject PHP framework (no vendor/.env/config.php)
- content-pipeline/  engine only (scripts/admin/prompts; empty runtime state)
- astroagent.config.json + app/.astroagent/skills

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SYHWLHihq3v9nxNwoPCKSn
2026-07-04 22:53:10 +00:00