← back to Animals

migrations/009_animal_agent.sql

55 lines

-- Animal Agent — autonomous builder. Tracks its own task queue + run history
-- so it can resume cleanly across restarts and Steve can audit what it did.

BEGIN;

CREATE TABLE IF NOT EXISTS agent_tasks (
  id            BIGSERIAL PRIMARY KEY,
  kind          TEXT NOT NULL,                -- 'audit_websites' | 'gen_mockups' | 'enrich_emails' | 'ingest_osm_state' | 'ingest_reddit' | 'wikimedia_breeds' | 'codex_debate' | 'build_subsite' | 'github_data'
  payload_json  JSONB NOT NULL DEFAULT '{}',  -- per-kind args
  priority      INTEGER NOT NULL DEFAULT 5,   -- 1=highest, 9=lowest
  status        TEXT NOT NULL DEFAULT 'queued'
                CHECK (status IN ('queued','running','completed','failed','skipped','cancelled')),
  attempts      INTEGER NOT NULL DEFAULT 0,
  max_attempts  INTEGER NOT NULL DEFAULT 3,
  scheduled_for TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  started_at    TIMESTAMPTZ,
  finished_at   TIMESTAMPTZ,
  result_json   JSONB,
  error         TEXT,
  cron_label    TEXT,                          -- which schedule rule queued this
  created_at    TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_agent_tasks_status ON agent_tasks(status, scheduled_for);
CREATE INDEX IF NOT EXISTS idx_agent_tasks_kind   ON agent_tasks(kind);
CREATE INDEX IF NOT EXISTS idx_agent_tasks_cron   ON agent_tasks(cron_label, created_at DESC);

CREATE TABLE IF NOT EXISTS agent_runs (
  id           BIGSERIAL PRIMARY KEY,
  started_at   TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  finished_at  TIMESTAMPTZ,
  ok_count     INTEGER NOT NULL DEFAULT 0,
  fail_count   INTEGER NOT NULL DEFAULT 0,
  notes        TEXT
);

-- Tracks generated subsites (the "Vet Site Upgrade" delivery — one full
-- static site per business that opted in). Paths land under public/sites/.
CREATE TABLE IF NOT EXISTS subsites (
  id              BIGSERIAL PRIMARY KEY,
  business_id     BIGINT NOT NULL REFERENCES businesses(id) ON DELETE CASCADE,
  slug            TEXT NOT NULL,             -- url path: public/sites/{slug}/index.html
  template_label  TEXT,                      -- which design system spec was rendered
  pages           TEXT[],                    -- e.g. ['index','services','team','contact']
  hostname        TEXT,                      -- 'happypaws.vetloft.com' once domain is wired
  status          TEXT NOT NULL DEFAULT 'generated'
                  CHECK (status IN ('generated','published','outdated','removed')),
  generated_at    TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  published_at    TIMESTAMPTZ,
  UNIQUE (business_id, slug)
);
CREATE INDEX IF NOT EXISTS idx_subsites_biz    ON subsites(business_id);
CREATE INDEX IF NOT EXISTS idx_subsites_status ON subsites(status);

COMMIT;