[object Object]

← back to 4square Agentabrams

yolo: add Mac2-local refinement loop script + 7-priority task brief

ca61c854d0ff8ac5b89f28c37cd537df9e324391 · 2026-05-14 09:31:23 -0700 · Steve

.yolo-loop.sh runs claude --print --dangerously-skip-permissions in an
infinite loop against .yolo-task.md, persisting state between iters via
.yolo-state.md, logging to .yolo.log. Kill with pkill -f .yolo-loop.sh.

Task brief lists 7 prioritized features in order — site coverage, PNG
export, shareable URL, infinite scroll, sort, replace-on-drop, grid layout.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit ca61c854d0ff8ac5b89f28c37cd537df9e324391
Author: Steve <steve@designerwallcoverings.com>
Date:   Thu May 14 09:31:23 2026 -0700

    yolo: add Mac2-local refinement loop script + 7-priority task brief
    
    .yolo-loop.sh runs claude --print --dangerously-skip-permissions in an
    infinite loop against .yolo-task.md, persisting state between iters via
    .yolo-state.md, logging to .yolo.log. Kill with pkill -f .yolo-loop.sh.
    
    Task brief lists 7 prioritized features in order — site coverage, PNG
    export, shareable URL, infinite scroll, sort, replace-on-drop, grid layout.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
 .gitignore    |  5 ++++
 .yolo-loop.sh | 31 +++++++++++++++++++++
 .yolo-task.md | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 123 insertions(+)

diff --git a/.gitignore b/.gitignore
index 711f94e..b331388 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,8 @@ dist/
 build/
 .next/
 tmp/
+
+# YOLO loop runtime
+.yolo.log
+.yolo-state.md
+.yolo-blocked.md
diff --git a/.yolo-loop.sh b/.yolo-loop.sh
new file mode 100755
index 0000000..a8d9572
--- /dev/null
+++ b/.yolo-loop.sh
@@ -0,0 +1,31 @@
+#!/usr/bin/env zsh
+# Mac2-local YOLO loop for 4square-agentabrams.
+# Loops claude --print against .yolo-task.md indefinitely until killed.
+# kill via: pkill -f '.yolo-loop.sh'
+
+set -u
+cd "$(dirname "$0")" || exit 2
+LOG="$PWD/.yolo.log"
+TASK="$PWD/.yolo-task.md"
+STATE="$PWD/.yolo-state.md"
+ITER=0
+
+print -- "$(date -u +%Y-%m-%dT%H:%M:%SZ) yolo-loop START — pid=$$ task=$TASK log=$LOG" >> "$LOG"
+
+while true; do
+  ITER=$((ITER+1))
+  print -- "$(date -u +%Y-%m-%dT%H:%M:%SZ) === iter $ITER START ===" >> "$LOG"
+
+  # Re-read the task each iter so Steve can edit it live.
+  PROMPT="$(cat "$TASK")"
+  if [[ -f "$STATE" ]]; then
+    PROMPT+="\n\n## State from previous iterations\n$(cat "$STATE")"
+  fi
+
+  echo "$PROMPT" | /usr/bin/claude --print --dangerously-skip-permissions --max-turns 80 >> "$LOG" 2>&1
+  EXIT=$?
+  print -- "$(date -u +%Y-%m-%dT%H:%M:%SZ) === iter $ITER END exit=$EXIT ===" >> "$LOG"
+
+  # Pause between iterations
+  sleep 30
+done
diff --git a/.yolo-task.md b/.yolo-task.md
new file mode 100644
index 0000000..02a0e23
--- /dev/null
+++ b/.yolo-task.md
@@ -0,0 +1,87 @@
+# 4Square YOLO — keep refining features
+
+You are working in `~/Projects/4square-agentabrams`. The app is live at
+https://4square.agentabrams.com (admin/DWShowroom2026), backed by pm2 process
+`4square-agentabrams` on port 9702 (local) and Kamatera (proxied via nginx).
+
+## Current state
+- Left rail: 104 of Steve's live domains from CNCP, in headliner order then
+  alphabetical. 20 of them are wired into `/api/site-products` proxy
+  (TSD catalog + 19 DW microsites).
+- Right panel: search input + dense product grid (120 items/load).
+- Moodboard: 4-square design board at the bottom, drag from grid to slot,
+  slot↔slot swap, localStorage persistence. All verified end-to-end.
+- Resizable left/main splitter, mobile stacks vertically, collapsible
+  moodboard.
+
+## Priorities (do in this order, ship each one independently)
+
+1. **Wire MORE sites — coverage.** Probe the remaining ~84 unwired domains
+   in `public/data/sites.json` for any product endpoint. Try in order:
+     - `/api/products` (already done — those are already wired)
+     - `/products.json` (Shopify storefront default)
+     - `/collections/all/products.json` (Shopify Section API)
+     - `/api/items`
+     - `/api/catalog`
+     - JSON-LD `<script type="application/ld+json">` embedded on the
+       homepage (parse + extract Product schemas)
+   Run probes in parallel (Promise.all batches of 10). For each domain
+   that returns valid JSON with at least one item carrying an image URL,
+   add it to `wiredSites` map in `server.js` AND add a `source` block in
+   `public/data/sites.json`. Don't break the existing 20 wired sites.
+
+2. **Export the moodboard as a PNG.** Add an "Export PNG" button next to
+   "Reset moodboard" in the header. Implementation: an offscreen 2048x2048
+   canvas, draw the 4 slots in a 2x2 grid with 32px padding + slot label
+   text overlay (Steve's site name + tile title). Save via
+   `canvas.toBlob` + `<a download>`. Skip slots that are empty.
+   Watermark "4Square · Agent Abrams" bottom-right small.
+
+3. **Shareable URL.** Encode the 4-slot layout as a compact URL hash
+   so Steve can send a moodboard link to a client. Hash format:
+   `#l=BASE64-encoded-JSON(layout)`. On page load, if `location.hash`
+   starts with `#l=`, decode and seed `layout` BEFORE rendering. Add a
+   "Share Link" button that copies the current URL+hash to clipboard
+   and flashes "copied ✓".
+
+4. **Infinite scroll** on the right panel. Replace the single 120-item
+   load with IntersectionObserver-based pagination. Track `offset` per
+   site. Append, don't replace.
+
+5. **Per-site sort options** for sites whose backend supports sort
+   params (most DW microsites accept `?sort=newest|price-asc|price-desc`).
+   Add a small Sort `<select>` next to the search bar — visible only
+   when the active site supports it (detect via probing `?sort=newest`
+   returns different first-item id than `?sort=price-asc`).
+
+6. **Swap slot image without clearing first.** When user drags a tile
+   onto a FILLED slot, instead of swapping with another slot, REPLACE
+   the slot's contents with the dragged tile. (Slot↔slot drags stay
+   swap.) Update the dnd handler to differentiate `kind: 'tile'` (replace)
+   vs `kind: 'slot'` (swap). Already partially in place — verify it works
+   and add a tiny "replaced" toast.
+
+7. **Slot grid layout options.** Add a small selector "Layout:" with
+   options 2x2 (default), 3x3 (9 slots), 1x4 (linear row), 4x1 (linear
+   column). Layout choice persists in localStorage. Storage key bumps
+   to `…layout.v2` to avoid stomping the v1 4-slot data.
+
+## Ground rules
+
+- Each priority is its own commit. Each commit gets its own deploy via
+  `bash ~/Projects/_shared/scripts/deploy.sh`. Verify with a curl smoke
+  test against https://4square.agentabrams.com after each deploy.
+- Use the same `admin/DWShowroom2026` credentials in curl tests.
+- Don't touch `~/Projects/thesetdecorator/` — it's a different project.
+- Don't modify DNS records, don't touch Cloudflare, don't send mail,
+  don't run pm2 `save` (that already happened).
+- After each feature lands, append a one-line entry to `.yolo-log.md`
+  in the project root: `[<ISO timestamp>] <commit-sha> <feature>`.
+- If you hit a blocker that needs Steve's input, write it to
+  `.yolo-blocked.md` and move to the next priority — don't loop on
+  the same problem.
+- Keep diffs small. Don't reformat unrelated files.
+- Run `pm2 restart 4square-agentabrams` locally after each Edit so the
+  Mac2 dev server reflects changes for verification.
+
+Start with priority #1 (wire more sites). Go.

← a00276f wire 19 more DW microsites — click → real products, not 'pen  ·  back to 4square Agentabrams  ·  4square: bust sites.json cache + re-resolve selectedSite fro 7bebaa2 →