# Prototype Prototype agent guide

Base URL: `https://prototypeprototype.com`

Prototype Prototype is a focused visual review workbench for generating and comparing a batch of variations as one decision study. Candidate groups are the operator-facing unit: one focused question, one isolated ranking, and one flat selector. Projects remain the durable agent API container.

## Authentication

Project endpoints require an AuthReturn JWT for app slug `prototype-prototype`: `Authorization: Bearer <jwt>`. A headless agent obtains one with bounded `POST https://authreturn.com/api/apps/prototype-prototype/login` and `{"email":"…","password":"…"}`; the response's `token` is the bearer value. Missing, expired, wrong-app, or invalid tokens receive `401`. Use an explicit timeout on every request and never persist or log the token. Every project and its decision studies belong to the authenticated Cognito user id; list, read, update, archive, and restore operations never expose another user's projects. Project ids are unique within one owner, not globally.

## Readiness

- `GET /api/health` → `{"status":"ok","app":"prototype-prototype"}`
- `GET /api/version` → semantic version
- `GET /agent-guide.md` → this guide
- `GET /agent-guide` → rendered guide

## Projects

The legacy owner retains the seeded projects `fairystack-composer-activity` (**FairyStack composer activity**), `fairystack-resting-mascot` (**FairyStack resting mascot**), and `info-elements-graph-edges` (**Info Elements graph edges**). New users begin with no projects. Decision studies remain code-backed and isolated by one visual question.

`fairystack-interface-polish` contains five peer studies over one populated FairyStack workshop capture: session tabs, message surfaces, composer focus, activity events, and footer controls. Each group changes only its named element and behavior; none mutates FairyStack production.

## Candidate groups

## Screenshot reconstruction

A dropped or selected PNG, JPEG, WebP, or GIF is an analysis input, never a
background layer. The authenticated browser submits it to
`POST /api/reconstructions` as multipart fields `screenshot`, `project_id`, and
optional `study_id`. Prototype Prototype sends the pixels to BrightWrapper's
general vision-capable async analysis, then submits that evidence to a separate
structured-output operation and returns one durable local job spanning both stages.

Poll `GET /api/reconstructions/{job_id}` until `completed`, `failed`,
`cancelled`, or `timed_out`; `DELETE` cancels local observation. Active jobs
report `queued` or `running`, a concrete `step`, timestamps, and a ten-minute
deadline. The browser persists the job id and resumes after reload. Completed
results contain a validated, bounded semantic region model which the browser
renders as real DOM with selectable text and code-addressable `data-region-id`
elements. The original screenshot is never displayed in the candidate canvas.

Uploads are capped at 15 MB. BrightWrapper calls use 20-second submission and
10-second polling timeouts. Duplicate active/completed submissions of the same
pixels for the same project and study reuse the existing job.

Each decision study is exposed as a peer candidate group. The selector and bare front page use the most recently created group, with the selector showing up to 10 groups in descending immutable `createdAt` order. `updatedAt` still records candidate or presentation changes but never reorders the selector. An older group remains durable and directly addressable, and is marked `direct` when opened. Parent/project lineage is provenance only, never navigation. Group-local browser state remains namespaced by its durable project and study ids. Use `/?group=fairystack-resting-mascot--<study-id>`. Legacy `?project=<id>&study=<id>` links resolve compatibly without moving ranking state.

The `fairystack-resting-mascot` artifact supplies three peer groups:

- `mascot-pose-suite` — root macro question.
- `wand-gesture-timing` — child of `production-profile-baseline`; compares gesture timing only.
- `flight-path` — child of `production-profile-baseline`; compares curved motion only.
- `seated-contact-shadow` — child of `cozy-perch`; compares seated contact-shadow geometry only.

The two micro studies use the existing production-profile Luminous Spiral asset as a neutral parent baseline. They do not select a macro candidate and never mutate FairyStack production.

`/?group=info-elements-graph-edges--loopback-route` compares the deployed Info Elements loopback route with symmetric-lead, rounded-orthogonal, and crisp-orthogonal alternatives. Every candidate preserves the same nodes, labels, lane, and endpoints; the study changes path geometry only and does not mutate the production renderer.

The Info Elements graph project also exposes `capacity-port-separation` and
`edge-label-consistency` as separate peer groups over the same captured
“Plan-independent resource protection” graph. These groups keep port geometry
separate from label wrapping and paint-order decisions.

To add a child, fetch the project and ETag, append a unique bounded `decision_studies` entry with `id`, `label`, and `parent: {study_id, candidate_id}`, implement its code-backed candidates in the study registry, then `PUT` the complete reconciled artifact with `If-Match`. Candidate provenance must repeat literal parameter values and parent lineage. Never merge candidates from separate questions into one ranking.

| Method | Path | Result |
|---|---|---|
| `GET` | `/api/projects` | Active projects only |
| `GET` | `/api/projects?include_archived=true` | Active and archived projects |
| `GET` | `/api/projects/{id}` | One project and `ETag` |
| `POST` | `/api/projects` | Create a project |
| `PUT` | `/api/projects/{id}` | Update name and/or artifact |
| `POST` | `/api/projects/{id}/archive` | Archive, never hard-delete |
| `POST` | `/api/projects/{id}/restore` | Restore an archive |

Project object:

```json
{"id":"fairystack-composer-activity","name":"FairyStack composer activity","artifact":{"kind":"html-css-mockup","schema_version":1},"version":1,"archived":false,"created_at":"ISO-8601","updated_at":"ISO-8601"}
```

Ids are 2–64 lowercase letters, numbers, or hyphens. Names are 1–80 characters. `artifact` must be a JSON object no larger than 100,000 encoded bytes.

Create:

```http
POST /api/projects
Content-Type: application/json

{"id":"checkout-composer","name":"Checkout composer","artifact":{"kind":"html-css-mockup","schema_version":1,"source_app":"checkout","mockup_module":"/mock-content.js"}}
```

`artifact.source_app` names the app being studied. Use a 2–64 character lowercase app slug. Screenshot persistence is isolated by source app, project, and study; a study without a matching screenshot renders its code-backed imagined UI on a blank default background until the operator drops the correct screenshot.

Every existing project has an integer `version` and quoted `ETag` (Nginx may expose it as weak `W/"3"`; either form is accepted). Update, archive, and restore require that current value: `If-Match: "3"`.

Success increments `version` and returns the new `ETag`. Missing concurrency state returns `428 version_required`; stale state returns `409 version_conflict`. Fetch and deliberately reconcile before retrying—never blindly overwrite.

Errors are JSON: `{"error":"…","code":"…"}`. Artifact overflow returns `413`; validation returns `400`; absent projects return `404`.

### Review commands

An agent may append a command to the existing artifact with `PUT`, the current `If-Match`, and the complete reconciled artifact. Commands are append-only and bounded to 100:

```json
{"review_commands":[{"id":"review-2026-08-26-001","type":"retain_top_fraction","fraction":0.25,"created_at":"2026-08-26T00:00:00Z"}]}
```

Ids must be unique 8–128 character identifiers. The canonical command is `retain_top_fraction` at `0.25`. The browser applies each id exactly once to its project-local user rank, retains `ceil(active / 4)`, archives everything below that cutoff, and records a bounded local receipt; it never replaces rank from the server. The legacy `archive_bottom_fraction` name is accepted as an alias. Offline fetch leaves the command pending until successful sync. Receipts prevent refresh from replaying the command.

When the operator says review is complete, the agent must fetch the project and ETag, append one unique `retain_top_fraction` command without rewriting rank, and update with `If-Match`. After the retained quarter is known, the agent should deliberately prepare the next code-backed batch: mutations from strong individual parents, crossovers where mechanisms genuinely combine, and novel candidates using freshly fetched Word entropy. Update the registry and project artifact through the authenticated API; do not expose mutation/archive/generation forms in the operator UI.

## Adding a mockup project

1. `POST /api/projects` with a stable id, human name, and bounded artifact configuration.
2. Keep mockup content/config in the project artifact. Variants remain code-backed definitions in the shipped registry; browser evolution history ranks and archives them without pretending to generate runtime code.
3. Open `/?group=<id>`. A project without decision studies contributes one candidate group; decision studies contribute peer groups named `<project-id>--<study-id>`.
4. Implement the next code-backed variant or media-candidate batch, then update the project artifact with `If-Match` if its configuration changed.

The FairyStack project is the one-time migration target for legacy unscoped browser state. Project-scoped keys are versioned by durable project id and are never populated from another project after migration.

## Variant provenance

Every code-backed variant or media candidate has one registry-owned provenance object. Archive events carry the same shape; legacy browser records are migrated on read:

```json
{"strategy":"mutation","generation":2,"parents":["signal"],"entropy_words":[],"rationale":"Changed the boundary-light mechanism."}
```

`strategy` is literal creation history, `generation` is a positive integer, `parents` contains stable ids, `entropy_words` contains only words actually used, and `rationale` names the mechanism change. Empty entropy is rendered as `No entropy seed`; agents must not invent seed words. The selected item’s explanation and complete provenance are always visible under the mockup; no tooltip or grouping layer obscures the canvas.

## Sprite extraction contract

[SimpleSprite](https://simplesprite.com) is the sprite-preparation provider. The moth artifact is pinned by its [public manifest](https://simplesprite.com/api/sheets/c549707db543438273ceeced74c71693e71754b262743eeb08f5b842ced74004), source hash, normalization spec, provider version, and output hashes in `fairy-moth-simplesprite-provenance.json`. Generated multi-pose compositions are not assumed to contain equal cells: SimpleSprite trims alpha, uses a shared scale, bottom-center anchor, 16-pixel padding, and emits two normalized 320² frames. Prototype Prototype checks in those exact outputs and deterministically assembles its local horizontal CSS sheet; runtime animation has no cross-service dependency. Browser CSS uses only `background-size: 200% 100%` and exact `0%`/`100%` positions—never per-frame alignment offsets. Rebuild with `python3 scripts/build_moth_sprite.py <manifest-url>`; the command uses bounded requests and fails on MIME, schema, source, spec, dimensions, padding, or hash drift.

## Entropy dependency

Agents preparing novel or mutation batches request three words over HTTPS from `GET https://word.aisloppy.com/api/words/random?count=3&seed=<up-to-128-chars>`, with explicit request and overall timeouts. Record the returned source and actual words in candidate provenance. Do not put entropy controls in the operator workspace.

## Resting mascot media contract

Prototype Prototype owns variation generation, side-by-side study presentation, and ranking. Sprite Handler owns sprite extraction, normalization metadata, masks, and authored dock/contact points; never attribute those production coordinates to Prototype Prototype.

The `fairystack-resting-mascot` macro study shows seven local 1080×320 RGBA suites: Cozy Perch, Moonlit Courier, Bramble Lantern, Inkcap Sprite, Mossbell Tinker, Porcelain Star, and Coral Comet. Moonlit Courier and the final three are recovered generated sheets processed by Sprite Handler with per-pose pixel masks; Coral Comet also uses semantic background matting. Playful Rest, Crossed Ankles, and Thoughtful Rest remain archived source references in `mascot-candidates.json`, not visible review candidates or deployed image assets. Every shown suite contains exactly three normalized 360×320 frames in this order: `flight-neutral`, `flick-forward`, `sit-rest`. There is no wand wind-up frame. The final frame is one static seated idle; wing animation is not inferred from it. Prototype Prototype shows each suite both in context and in an independent three-second review panel that advances once per second. Exact `0%`, `50%`, and `100%` cell positions avoid fractional sprite offsets. Flight facing changes at the authored acceleration/turn phases rather than on an unrelated timer. Sprite-service and generated-image provenance pin source and output hashes beside each asset. Generated sheets with overlapping pose extents must use Sprite Handler component masks; the obsolete rectangular-gutter importer has been removed. Run `python3 scripts/build_mascot_candidates.py` to validate every shown output; bounded provider requests fail on MIME, schema, review status, approved frame order, static-idle policy, cadence, dimensions, names, or hashes. The deployed animation consumes only local files and has no runtime provider dependency.

## Composer and attached header

`/?group=fairystack-interface-polish--composer-header` compares Joined paper,
Inset field, Open sheet, and Compact dock. The study keeps the same text,
attached status, and Voice Feed / Send / Enqueue controls. Its preview-state
selector covers working, idle, queued, and delivery failure. The textarea is
editable; changing variants or state preserves its DOM and draft. Preview
buttons only acknowledge the selection locally and never send messages.
Candidates live in `media-study.js`; `composer-study.js` and `.css` own their
shared renderer. No candidate is automatically applied to FairyStack.

Browser regression: `node scripts/test_composer_study.cjs` (Playwright required;
`PLAYWRIGHT_MODULE` and `CHROMIUM_PATH` may point to installed tooling).

### Screenshot interruption recovery

Uploads have a 120-second request timeout and run sequentially, starting with the selected mode. One transport retry reuses a UUID `request_id` multipart field; the server returns the same job even if it has since completed. Reusing that ID with different inputs returns 400. Jobs are persisted before provider submission; GET status reads the durable snapshot without waiting on provider calls. Workers resume queued and active jobs on service startup, retry transient status failures, and terminate at the original 30-minute deadline. The browser stops disconnected observation after 31 minutes while retaining the saved job ID.

The progress panel shows the concrete failed step and error. Upload failures retain the source screenshot in IndexedDB. A restart after provider acceptance but before its task ID is saved is explicitly reported as an unknown submission outcome; it is not automatically replayed because BrightWrapper does not document submission idempotency.

Upload progress uses browser `XMLHttpRequest.upload` byte events, authenticated with the existing AuthReturn client's `getValidToken()`. The panel shows bytes sent/total (including multipart overhead), percentage when the browser knows the total, average transfer rate, and elapsed time. It distinguishes authentication, transfer, server acceptance, and terminal errors; 15 seconds without new byte events is labeled explicitly. Reaching 100% means the browser sent the request body, not that the server accepted the job. The same 120-second deadline includes authentication and server acceptance; timed-out requests are aborted, and late token refreshes cannot start an upload.

## Coding Agents tool-execution colors (3.43.0)

`/?group=coding-agents-colors--tool-execution-colors` opens the authenticated
color study for the tool-execution box in Coding Agents' `/#request` step 5.
The project id is `coding-agents-colors`; its study id is `tool-execution-colors`.
This is current study state, not an immutable version. The normal project owner
boundary applies; no credentials are carried in the URL.

Six candidates compare original solid fills, black text, white text, lighter
greens, deeper greens, and the separate reading surface reference. Each displays
light and dark page context simultaneously, with the earlier input, instructions
and tools colors nearby. Text, type sizes, layout and example content stay fixed.
The displayed ratio is the minimum header/body text contrast, computed from
opaque sRGB values. Some candidates deliberately fall below 4.5:1 and are labeled;
the number measures contrast, not visual preference. This is a controlled color
comparison, with no entropy used to choose colors. No production change is made
to Coding Agents. Existing candidate ranking and archiving remain group-local.

`tool-color-study.js` and `.css` own the shared specimen. Candidate changes update
colors on one mounted DOM; selected text and native disclosure state survive.
Regression: `node scripts/test_tool_color_study.cjs` with Playwright installed.

## New screenshot studies (3.44.0)

Dropping or selecting an image creates a new owned project before analysis; it
never replaces the open study’s source, ranking, or jobs. The browser retains
the file under the new project identity, navigates there, and resumes the three
analysis strategies using durable per-mode request IDs after interruption.
The existing Rerun all action deliberately reruns the current source.
New screenshot studies use the existing semantic blueprint renderer; it is an
interpretation of navigation, actions, and content, not a pixel-exact recreation.

### Resource links

`https://prototypeprototype.com/?group=screenshot-<UUID>` opens a current
screenshot study. IDs use a lowercase UUID; the project and reconstruction APIs
require the owning AuthReturn identity. This is a current-state link; individual
job results remain identified by their durable job IDs. Example format:
`/?group=screenshot-00000000-0000-4000-8000-000000000000` (illustrative, not a saved study).
Stage percentages require measured progress or a supplied stage duration estimate;
unknown durations are shown explicitly. The server retains the original 30-minute
deadline across reloads.
