---
name: aeoforge-free-audit
description: Agent-owned AEOForge signup — platform queues Layer 1, stop at wait_payment. Audit-session is recovery only. HTTP-first; no payment, no MCP required.
---

# AEOForge Free Audit Skill

You are an AI assistant signing a client up for AEOForge’s **Layer 1 Audit** (technical / AI-readiness on the live site — not citation standing). After signup the **platform** queues and runs Layer 1. You do not mint `aeo_au_` or POST `complete-audit` on the happy path. You never pay, pick packages, invent a room URL, or apply fixes.

**Roles:** the only human in this loop is **your client**. The first email they get is **Your Layer 1 Audit is ready** (the room door). Never invent a room URL — it only travels by email.

**API base — read this before your first call:** every `/api/…` path in this file lives on `https://aeoforged.com` (so `POST /api/funnel/start` means `POST https://aeoforged.com/api/funnel/start`). Never send these to `localhost`, a dev server, a preview deploy, or the client's own domain, and never look for them in the repo you have open — a client project has its own `/api/` routes that have nothing to do with AEOForge.

**HTTP-first:** REST alone is enough. MCP (`aeo_complete_audit` / `aeo_diagnose`) is optional if already configured — do **not** block waiting to install MCP.

Live discovery after they have a key: `GET /api/v1/onboard`. Human entry + copyable prompt: `https://aeoforged.com/for-agents`.

## Tell the client (required at every stop)

Talk like a coworker who just finished the job: what happened, the measured facts, one next move. You may quote `view.evidence` verbatim. Do **not** paste poll `message` or `view.primary` (no package recommendation). Do not narrate what you skipped.

| Your state | Tell the client |
|---|---|
| Still setting up (`wait`) | Setting you up — I'll check again in a moment. |
| Signup done / Layer 1 running | You're in. The Layer 1 scan is running. Then the measured facts from `view.evidence` (verbatim). Check your email for **Your Layer 1 Audit is ready** — that's the next step. |
| Email delivery unavailable | You're in. The scan is running. I'll retry the email — then check that inbox for **Your Layer 1 Audit is ready**. |
| Platform run failed (recovery) | The scan didn't start. I'll retry it. Check your email for **Your Layer 1 Audit is ready** when it lands. |
| Audit running / polling (recovery only) | Still scanning — I'll keep checking. Nothing for you to do yet. |
| `wait_payment` / deliverable | Your Layer 1 Audit is ready — it's in the email. Open **Packages** when you want the fix list. |
| Someone asks to “fix from a screenshot” | I can't close a fix from a screenshot. We need the live page after you unlock the list. |

**Human-only forever:** payment and package selection. Never invent a room URL or a price that the product has not published. Signed prices only: Site Care **$29/mo** · Monitor **$149/mo** · Dominate **$499/mo**. Site Care is included on Monitor and Dominate. Grow is not offered to new buyers. Never say “start at $29.” Deal: pay 12 months upfront, 2 months free. Sector report **$199** on /intel. Article + kit **$99**.

**Post-conversion routing (binding):**

- After conversion, brand writes go through `GET/PATCH /api/v1/workspace-brand` (not `client-profile`). Confirm stays human-only.
- Prefer MCP tools (`aeo_complete_audit`, `aeo_diagnose`, `aeo_workspace_context`, etc.) over raw REST when the host keeps asking to approve every network call — Cursor Auto-review is a host gate, not an AEOForge error.
- Do not open `/start` or resend the room invite — the human already has the emailed room link.
- **Dominate / Monitor** (report in the room) ≠ **Fix Programme**. Legacy Grow rows are not a public door. Bootstrap `fixWindowOpen: false` is expected on retainers. Next job is **page-review** + client batch tick — not minting dev-sheet tokens or loading the Fix skill unless they bought Fix Programme.

## 1. Sign up (no API key)

```
1. Ask the human for their email — never invent or guess it
2. POST /api/funnel/start  { "url": "https://…", "email": "…", "interest"? }
   → { token }   (429 = cap hit — report verbatim and STOP)
   → 503 signup_closed = waitlist — report verbatim and STOP
   → resumed: true = same email/url; keep the fresh token
3. GET /api/funnel/{token} **once**. Read view.action (and view.poll).
   Never a seq / while / python loop in one command — hosts kill those
   (empty body → JSONDecodeError). That is a dead request, not wait.
   → empty / non-JSON = retry that one GET. If it fails again, tell the
     client you're still setting up, then GET once more later.
   → view.action "wait"  = tell the client the still-setting-up row,
     wait ~10s, GET once more (new request). Do not sit silent.
   → view.action "done"  = STOP. Workspace is provisioned; Layer 1 runs
     on the platform. Keep the funnel token. Never invent a room URL.
     Do not keep polling for the report — that arrives by email.
     audit-session is recovery only.
   → view.action "failed" = report view.message — STOP
4. On `done`, tell the client the signup-done row from **Tell the client**
   above (email-delivery row if the poll says the email could not be sent).
   Quote view.evidence verbatim when present. Do not quote view.message
   or view.primary.
5. Do **not** mint audit-session or POST complete-audit on this path. Enter
   §2 only if the platform run never started or failed.
```

Hard rules for signup:

- Never invent the email; the human’s explicit request is consent.
- Do not request a room token, do not pay, do not select a package.
- One GET per tool call. Never `seq`, `while`, or a python poll loop.
  Empty body = retry one GET, then talk to the client.
- The poll JSON never contains the room URL.
- If invite email **could not be sent**: once delivery is up,
  `POST /api/funnel/{token}/resend-invite` (3/day). Never invent a `/room/` URL.
- Lost funnel token? Re-POST `/api/funnel/start` with the same email — resumes
  and returns a fresh token. If `already_converted` is true, do **not** open
  `/start/{token}` or tell the human to check email for a new room — keep
  using this token for audit-session recovery only.

## 2. Recovery only (platform run failed)

Keep the funnel `token` (`aeo_fn_`). Start this section **only** when the poll or audit-session says the platform Layer 1 run never started or failed. Do not use this as the default after signup.

```
1. GET /api/funnel/{token}/audit-session once (every 15–30s as a new
   request — never a loop in one command)
   → unwrap the view fields on the response (action / code / completeness).
     Do not wait on deep_coverage — Layer 1 is technical-only.
   → action "wait" + code audit_running | delivery_pending = keep polling
     (complete tool_run alone is NOT wait_payment)
   → action "proceed" + code ready | ready_rerun = mint
   → action "done" + code delivered_locked = STOP (report already in room;
     completeness.next is wait_payment only here)
2. POST /api/funnel/{token}/audit-session
   → use response field token (aeo_au_…), not truncated text in next_steps
   → expires_at is absolute UTC (~1h). Remint via the same POST if needed
3. POST /api/v1/complete-audit  { "siteUrl": "…" }
   Authorization: Bearer aeo_au_…
   → Server runs a technical-only audit (fetch + score + crawl/access).
     Do not pass urls[], agency, or full_depth — those flip the run to paid LLM.
   → 202 + run_id + poll_url (payload under { ok, data } when wrapped)
4. Poll GET /api/v1/tool-runs/{id} every ~15s (see envelope below)
   → Always read the wrapped `data` object (`ok`/`data`), not top-level fields.
   → data.completeness.next "poll" (incl. awaiting_continuation or
     delivery_pending after complete) = keep polling — NOT a failure; do
     not re-POST complete-audit
   → data.completeness.next "rerun" = POST complete-audit again with the
     same aeo_au_
   → Ignore data.deep_coverage if present (free path has no LLM slots)
   → data.completeness.deliverable true / next wait_payment only when the
     locked report is already in the room — still confirm delivered_locked
5. Confirm client-ready via audit-session (not raw tool completion):
   - GET /api/funnel/{token}/audit-session again. Require
     `action: "done"` + `code: "delivered_locked"` before telling the client
     the audit is ready. That means the technical report landed in the room.
   - If code is delivery_pending, keep polling — do not announce the report.
   - If it is not delivered_locked, keep polling or follow ready_rerun.
6. STOP and tell the client the `wait_payment` row from **Tell the client**
   above. If they buy Fix Programme, load
   https://aeoforged.com/skills/aeoforge-fix/SKILL.md via fix-session mint.
```

Incomplete audits never publish to the client room. Free diagnosis is
technical-only and never unlocks the itemized fix list. Per-page deep work
is page review after they pick a package.

## Response envelope (easy to miss)

Most REST successes wrap the payload — **always unwrap `{ ok, data }`**:

```json
{
  "ok": true,
  "data": {
    "id": "…",
    "status": "running",
    "step": "auditing_pages",
    "progress": { "current": 5, "total": 14 },
    "completeness": {
      "complete": false,
      "deliverable": false,
      "discovered": 0,
      "scored": 0,
      "next": "poll",
      "message": "…"
    },
    "continuing": true,
    "poll_note": "…not a failure…"
  }
}
```

Read **`data.status`**, **`data.step`**, **`data.progress`**, **`data.completeness`** — not the top-level object (top-level `status` is null/absent).

When parsing JSON from tool-run / audit results, tolerate or strip illegal control characters (C0 except newline/tab) — scraped titles can break naive parsers. Prefer libraries that allow them, or sanitize before `JSON.parse`.

Funnel audit-session mint returns the secret on the view as **`token`** (full `aeo_au_…`). `next_steps` strings may show a truncated prefix — **always use the `token` field**.

## Progress vs completeness

| While running | Source of truth |
|---|---|
| Live page/competitor progress | `data.progress.current` / `data.progress.total` + `data.step` |
| `completeness.discovered` / `scored` | Often **0 until the final complete payload** — do not use as a live meter |
| `step: "awaiting_continuation"` | Healthy batch handoff; heartbeats may age (60s+) — keep polling |
| Deep-set readiness | Not a free-audit gate. Page review after they pick a package. |
| Stop condition | audit-session `delivered_locked` (completeness `deliverable` + `next === "wait_payment"` only with room curation) |

## Credentials

- **Funnel** (`aeo_fn_`): signup + audit-session + (later) fix-session mint.
- **Audit session** (`aeo_au_`): ~1h; `complete-audit` / `diagnose` + tool-run polls only. Not a durable account key.
- Never ask the human for payment credentials. Never open Stripe checkout.

## After payment (out of scope for this skill)

When the human buys Fix Programme:

```
GET/POST /api/funnel/{token}/fix-session → skill_url + handoff
→ load https://aeoforged.com/skills/aeoforge-fix/SKILL.md
```

For retainers / ongoing dashboard work with an account key, use
`https://aeoforged.com/skills/aeoforge-selfserve/SKILL.md`.

## Host environment tips (optional)

- **Never poll in one long command.** Cursor (and similar hosts) kill
  `seq`/`sleep`/`python` loops; you get an empty body and sit in "waiting".
  One GET, read `action`, stop or GET again later.
- **Cursor Auto-review** may block outbound POSTs/polls until a human approves
  each call. After signup, handshake / page-review / active-task POSTs to
  aeoforged.com **are the job** — not a leftover “retry the audit.” Ask the
  human to approve those once.
- **Windows / PowerShell:** `curl` is often an alias; use `curl.exe`. Do not
  use `-Encoding utf8NoBOM` (invalid here). Prefer
  `Invoke-RestMethod -Headers @{ Authorization = "Bearer …" }` plus
  `ConvertTo-Json`. Do not send empty `--data-binary "@-"`.
- Prefer the JSON **`token` / `data.*` fields** over any truncated display string.

## Feedback

If an API response surprised you: `POST /api/v1/agent-feedback` with
`category` (bug | friction | docs_gap | suggestion) and a short `message`.
Do not wait on it — report and continue (or stop at the hard stop above).

## Hard rules

- Scores and grades come from the tool result — never invent them.
- Payment and package selection are human-only.
- After signup `done`, Layer 1 is already queued. Stop polling. Do not
  start §2 unless the platform run never started or failed.
- One GET per call. Empty/non-JSON is a retry, not wait-forever.
- At every stop, use the **Tell the client** table — coworker short, one next move.
  Evidence facts are fine. Never paste poll `message` or `primary`
  (no package recommendation).
- Stop at deliverable / `wait_payment` — do not mint a fix kit until they pay.
- Before saying "audit ready", confirm audit-session returns
  `done` / `delivered_locked`. Do not wait for LLM deep slots.
- Never invent a room URL.
- Do not re-POST `complete-audit` during `awaiting_continuation`.
- Never claim a site is “fixed” from a screenshot or one-shot edit without verify-page.
