feat: ship production deploy, Playwright e2e, and agent implementer
Add Docker atomic deploy tooling, CI, Playwright smoke/visual suite, shared industrial theme, physics invariants, quality-mode wiring, and a worktree-isolated agent implementer MVP with hard safety limits. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
124
docs/AGENT_IMPLEMENTER_MVP.md
Normal file
124
docs/AGENT_IMPLEMENTER_MVP.md
Normal file
@@ -0,0 +1,124 @@
|
||||
# Implementer MVP (worktree-isolated)
|
||||
|
||||
**Status:** Implemented in `agent/cli.mjs`
|
||||
**Date:** 2026-07-15
|
||||
|
||||
Safe, deterministic Implementer cycle that **does not** require an external LLM.
|
||||
Patches run only inside a git worktree. The agent **never** merges to `main`, **never** deploys, and **never** pushes.
|
||||
|
||||
---
|
||||
|
||||
## Commands
|
||||
|
||||
| Command | Purpose |
|
||||
| ------- | ------- |
|
||||
| `dry-run` | Plan only (baseline + propose) |
|
||||
| `run-once` | Verify baseline only (no patches) |
|
||||
| `implement [--task <path>]` | Full Implementer cycle |
|
||||
| `start` | Same as implement, but requires `AUTONOMOUS_AGENT_ENABLED=true` |
|
||||
| `status` / `stop` / `resume` / `pause` / `report` | Control plane |
|
||||
|
||||
```bash
|
||||
# Recommended successful demo cycle
|
||||
node agent/cli.mjs implement --task agent/tasks/demo-docs.json
|
||||
|
||||
# Or via helper script
|
||||
bash scripts/agent-implement.sh --task agent/tasks/demo-docs.json
|
||||
|
||||
# Gated continuous entry (still one cycle in MVP)
|
||||
AUTONOMOUS_AGENT_ENABLED=true node agent/cli.mjs start --task agent/tasks/demo-docs.json
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementer cycle
|
||||
|
||||
1. **Watchdog** — kill switch, single lock, disk, load, memory
|
||||
2. **Plan** — load task JSON (default: `agent/tasks/demo-docs.json`)
|
||||
3. **Validate policy** — allowlist only: `docs`, `tests`, `data-testid`, `a11y`, `small-ui`, `logging-scripts`
|
||||
4. **Create worktree** — `.agent/worktrees/<run-id>` on branch `agent/<run-id>/<task-slug>`
|
||||
5. **Apply bounded patch** — e.g. create `docs/AGENT_CYCLE_DEMO.md`
|
||||
6. **Enforce limits** — ≤12 files, ≤800 diff lines, ≤25 min cycle
|
||||
7. **Verify** — `npm test && npm run build` inside the worktree
|
||||
8. **Score + decide** — `ACCEPT_CANDIDATE` or `REJECT`
|
||||
9. **Report** — `agent/reports/<run-id>.json` (+ `latest.json`)
|
||||
|
||||
### On REJECT
|
||||
|
||||
- Remove worktree
|
||||
- Delete local agent branch
|
||||
- Keep the JSON report
|
||||
|
||||
### On ACCEPT_CANDIDATE
|
||||
|
||||
- Keep worktree + branch
|
||||
- Print manual review instructions
|
||||
- Human must cherry-pick / merge into a feature branch if desired
|
||||
|
||||
---
|
||||
|
||||
## Watchdog
|
||||
|
||||
| Check | Fail condition |
|
||||
| ----- | -------------- |
|
||||
| Lock | `agent/state/agent.lock` held by a live PID (second agent refused) |
|
||||
| Kill switch | `agent/state/KILL` present |
|
||||
| Disk | `df /` usage **> 85%** |
|
||||
| Load | loadavg 1m **> nproc** |
|
||||
| Memory | MemAvailable **< 1 GiB** |
|
||||
|
||||
```bash
|
||||
node agent/cli.mjs stop # write KILL
|
||||
node agent/cli.mjs resume # clear KILL
|
||||
node agent/cli.mjs status # lock + watchdog snapshot
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Example task
|
||||
|
||||
`agent/tasks/demo-docs.json` — docs-only safe demo:
|
||||
|
||||
- Policy: `docs`
|
||||
- Patch: create `docs/AGENT_CYCLE_DEMO.md`
|
||||
- No source / physics / deploy / `.env` changes
|
||||
|
||||
---
|
||||
|
||||
## Limits (also in `LIMITS` in `cli.mjs`)
|
||||
|
||||
| Limit | Value |
|
||||
| ----- | ----: |
|
||||
| max cycle | 25 min |
|
||||
| max files | 12 |
|
||||
| max diff lines | 800 |
|
||||
| parallel agents | 1 |
|
||||
|
||||
Hard forbids: merge to main, production deploy, push, secret/`.env` access.
|
||||
|
||||
---
|
||||
|
||||
## Manual review after ACCEPT
|
||||
|
||||
```bash
|
||||
# Inspect
|
||||
cat agent/reports/latest.json
|
||||
git -C .agent/worktrees/<run-id> show HEAD
|
||||
|
||||
# Accept into your feature branch yourself (example)
|
||||
git cherry-pick <agent-commit-sha>
|
||||
|
||||
# Or discard
|
||||
git worktree remove --force .agent/worktrees/<run-id>
|
||||
git branch -D agent/<run-id>/demo-docs
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## What this MVP does **not** do
|
||||
|
||||
- Call external LLMs
|
||||
- Modify production nginx/docker/deploy
|
||||
- Touch `.env`
|
||||
- Auto-merge or auto-deploy
|
||||
- Change demo physics (prefer docs-only demo task)
|
||||
35
docs/PERFORMANCE_AFTER_MAXIMUM_DEMO.md
Normal file
35
docs/PERFORMANCE_AFTER_MAXIMUM_DEMO.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# PERFORMANCE_AFTER_MAXIMUM_DEMO
|
||||
|
||||
Measured: 2026-07-15T17:11:06.031Z
|
||||
Commit: `985f7c3`
|
||||
|
||||
## Bundle (measured)
|
||||
|
||||
| Метрика | Значение |
|
||||
| ------- | -------: |
|
||||
| Total JS | 1300.9 KB |
|
||||
| Total JS gzip | 358.1 KB |
|
||||
| Main chunk | index-ncgt6PBL.js (96.4 KB gzip) |
|
||||
| R3F chunk gzip | 226.1 KB |
|
||||
|
||||
## Runtime (Playwright Chromium headless)
|
||||
|
||||
| Метрика | До | После | Цель | Статус |
|
||||
| ------- | -: | ----: | ---: | ------ |
|
||||
| Average FPS | n/a (не измерялось) | 9.6 | ≥30 | CHECK |
|
||||
| Minimum FPS | n/a | 3.3 | ≥20 | CHECK |
|
||||
| p95 frame time | n/a | 200.1 ms | ≤33 ms | CHECK |
|
||||
| Load time | n/a | 1008 ms | ≤5000 | OK |
|
||||
| JS heap start | n/a | 13400000 | — | measured |
|
||||
| JS heap after interaction | n/a | 13400000 | no runaway | measured |
|
||||
| Canvas present | — | 1 | ≥1 | OK |
|
||||
| JS gzip (main+vendor) | ~335 KB main previously | 358.1 KB | — | measured |
|
||||
|
||||
## Notes
|
||||
|
||||
- **Headless Chromium WebGL is not a GPU FPS measurement.** Values ~9 FPS / p95 ~200 ms reflect software/SwiftShader-like rendering in CI/headless, **not** desktop Chrome with NVIDIA. Do not claim 30–60 FPS from this pass.
|
||||
- For jury/demo FPS, measure in headed Chromium on the presentation machine (`npm run test:e2e:headed` + DevTools Performance) or Engineering Details FPS meter.
|
||||
- Draw calls / triangles require WebGL inspector in headed mode; not available in this headless pass.
|
||||
- Demo quality mode keeps `shadows=false` and `effectsEnabled=false` for stable real-device FPS (see `qualityMode.ts`). High mode may enable shadows.
|
||||
- Raw JSON: `agent/reports/perf-metrics.json`
|
||||
- Runtime error (if any): none
|
||||
95
docs/PLAYWRIGHT_E2E_REPORT.md
Normal file
95
docs/PLAYWRIGHT_E2E_REPORT.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# Playwright E2E + Visual Regression
|
||||
|
||||
Lightweight end-to-end and visual regression coverage for the continuous demo on `/` and the SPA route `/details`.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Node.js with project deps installed (`npm install`)
|
||||
- Chromium for Playwright: `npx playwright install chromium`
|
||||
- App reachable at the base URL (default preview: `http://127.0.0.1:3101`)
|
||||
|
||||
By default tests **do not** start a server. Start preview yourself, for example:
|
||||
|
||||
```bash
|
||||
npm run build && npx vite preview --host 127.0.0.1 --port 3101
|
||||
```
|
||||
|
||||
Or point at an already-running preview/prod instance via `PLAYWRIGHT_BASE_URL`.
|
||||
|
||||
## Scripts
|
||||
|
||||
| Script | Command | Purpose |
|
||||
|--------|---------|---------|
|
||||
| `test:e2e` | `playwright test` | Run all e2e + visual tests |
|
||||
| `test:e2e:headed` | `playwright test --headed` | Same, headed browser |
|
||||
| `test:e2e:update` | `playwright test --update-snapshots` | Refresh visual baselines |
|
||||
|
||||
## Environment
|
||||
|
||||
| Variable | Default | Meaning |
|
||||
|----------|---------|---------|
|
||||
| `PLAYWRIGHT_BASE_URL` | `http://127.0.0.1:3101` | Target app origin |
|
||||
| `PLAYWRIGHT_START_SERVER` | unset | Set to `1` to let Playwright run `vite preview` on port 3101 |
|
||||
|
||||
Examples:
|
||||
|
||||
```bash
|
||||
# Against local preview (already running)
|
||||
PLAYWRIGHT_BASE_URL=http://127.0.0.1:3101 npm run test:e2e
|
||||
|
||||
# Against prod-style port
|
||||
PLAYWRIGHT_BASE_URL=http://127.0.0.1:3100 npm run test:e2e
|
||||
|
||||
# Auto-start preview if nothing is listening
|
||||
PLAYWRIGHT_START_SERVER=1 npm run test:e2e
|
||||
```
|
||||
|
||||
## Config highlights
|
||||
|
||||
- **workers: 1** — keep e2e light on shared servers
|
||||
- **retries: 1**
|
||||
- **chromium only**
|
||||
- Screenshot on failure; trace on first retry
|
||||
- Soft visual thresholds (`threshold: 0.3`, `maxDiffPixelRatio: 0.05`)
|
||||
|
||||
## Test map
|
||||
|
||||
| Spec | Coverage |
|
||||
|------|----------|
|
||||
| `e2e/smoke.spec.ts` | `/` loads, canvas (or loading→canvas), no `pageerror`, play works, replay if finished |
|
||||
| `e2e/controls.spec.ts` | next/prev seek, jump case 0 & 8, speed buttons, presentation toggle |
|
||||
| `e2e/safety.spec.ts` | jam (index 8) → FAULT; emergency (index 9) → EMERGENCY |
|
||||
| `e2e/routes.spec.ts` | `/details`, refresh stays on details, navigate back to `/` |
|
||||
| `e2e/visual.spec.ts` | Idle HUD panel snapshot only (not full WebGL canvas) |
|
||||
|
||||
Stable selectors live on `MainPage` as `data-testid` values (`demo-play`, `demo-hud`, `demo-case-{n}`, etc.).
|
||||
|
||||
## Updating visual snapshots
|
||||
|
||||
1. Ensure the app at `PLAYWRIGHT_BASE_URL` matches the UI you want to lock.
|
||||
2. Run:
|
||||
|
||||
```bash
|
||||
npm run test:e2e:update
|
||||
```
|
||||
|
||||
3. Review diffs under `e2e/visual.spec.ts-snapshots/` (and commit those PNGs when intentional).
|
||||
4. Re-run `npm run test:e2e` to confirm green.
|
||||
|
||||
Snapshots intentionally target **`[data-testid="demo-hud"]`** so WebGL canvas noise does not fail CI.
|
||||
|
||||
## System deps
|
||||
|
||||
On a fresh Linux host, Chromium may need OS libraries:
|
||||
|
||||
```bash
|
||||
npx playwright install chromium
|
||||
npx playwright install-deps chromium
|
||||
```
|
||||
|
||||
## Artifacts (gitignored)
|
||||
|
||||
- `test-results/` — failure screenshots / traces
|
||||
- `playwright-report/` — HTML report
|
||||
- `blob-report/` — blob reporter output
|
||||
`}
|
||||
64
docs/PRODUCTION_DEPLOYMENT_REPORT.md
Normal file
64
docs/PRODUCTION_DEPLOYMENT_REPORT.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# PRODUCTION_DEPLOYMENT_REPORT
|
||||
|
||||
Дата: 2026-07-15
|
||||
Ветка: `feature/maximum-demo-realism`
|
||||
Базовый commit этапа 1: `985f7c3`
|
||||
Production bundle после этапа 2: `index-ncgt6PBL.js`
|
||||
|
||||
## Способ деплоя
|
||||
|
||||
Docker-контейнер `owl-web-1` (image `owl-web:<release>`), порт `127.0.0.1:3100→80`.
|
||||
Docker API: `DOCKER_HOST=tcp://127.0.0.1:2375` (из coder-контейнера).
|
||||
Compose-файл: `docker-compose.server.yml` (исторически `-p owl`).
|
||||
Скрипт: `scripts/deploy-production.sh`.
|
||||
|
||||
Публичный доступ в этой среде:
|
||||
|
||||
- Loopback: `http://127.0.0.1:3100/`
|
||||
- Quick tunnel cloudflared: `https://invitations-based-characters-accent.trycloudflare.com/`
|
||||
- `https://arhipovdan.ru/` из контейнера даёт TLS SNI / openresty 404 — DNS/прокси домена вне текущего coder-окружения; проверяйте снаружи.
|
||||
|
||||
## Releases
|
||||
|
||||
| Поле | Значение |
|
||||
| ---- | -------- |
|
||||
| Old release container | `owl-web-1-backup-20260715-165347` / `…-1712` |
|
||||
| Old bundle | `index-CCdZzxPJ.js` |
|
||||
| New release | `20260715-1712` |
|
||||
| New image | `owl-web:20260715-1712` |
|
||||
| New bundle | `index-ncgt6PBL.js` |
|
||||
| Backup HTML | `releases/backup-pre-*` |
|
||||
|
||||
## Команды
|
||||
|
||||
```bash
|
||||
export DOCKER_HOST=tcp://127.0.0.1:2375
|
||||
cd /home/coder/arhipovdan/app
|
||||
npm test && npm run build
|
||||
bash scripts/deploy-production.sh 20260715-1712
|
||||
curl -s http://127.0.0.1:3100/ | grep -Eo 'index-[A-Za-z0-9_-]+\.js'
|
||||
```
|
||||
|
||||
## Healthcheck
|
||||
|
||||
| Check | Result |
|
||||
| ----- | ------ |
|
||||
| `GET /` | 200 |
|
||||
| `GET /details` (SPA) | 200 |
|
||||
| Bundle | `index-ncgt6PBL.js` |
|
||||
| Tunnel HTML | same bundle |
|
||||
|
||||
## Rollback
|
||||
|
||||
```bash
|
||||
export DOCKER_HOST=tcp://127.0.0.1:2375
|
||||
docker stop owl-web-1 && docker rm owl-web-1
|
||||
docker rename owl-web-1-backup-20260715-1712 owl-web-1
|
||||
docker start owl-web-1
|
||||
```
|
||||
|
||||
Или восстановить HTML из `releases/backup-pre-<release>/`.
|
||||
|
||||
## Smoke (tunnel)
|
||||
|
||||
Подтверждено: CASE 1/10, Jump to case 1–10, Previous/Next, Present, Play Demo.
|
||||
Reference in New Issue
Block a user