Commit Graph

23 Commits

Author SHA1 Message Date
type-two
2236a96ed4 fix(flowext): a locked screen wedges the rig; and open location opened the wrong browser
1. LOCKED SCREEN. With CGSSessionScreenIsLocked=Yes, every AppleScript window/tab query
   hangs ~2 min and returns -1712 "AppleEvent timed out". This is NOT a browser bug —
   with m3ultra locked, `count of windows` hung identically for Chrome, Brave, Finder
   AND System Events, while app-level properties (name/version/running) answered instantly.
   launch.sh now checks the lock first and exits 0 with an instruction, so the 10-min tick
   retries instead of leaving two osascript processes wedged.

2. `open location "$URL"` is Standard Additions: it hands the URL to the DEFAULT browser,
   never to $BROWSER. m3ultra's default is Brave while the extension lives in Chrome, so
   the fresh-open path would have opened the wrong browser entirely. Now makes the tab
   inside the target app.

3. Wrapped the tell block in `with timeout of 30 seconds` so a wedged app can't hold the job.

Verified: detector reports unlocked on ultra / LOCKED on m3ultra; after the fix m3ultra
logs the instruction and exits with no hung osascript, ultra still logs "focused on Flow".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 21:22:14 +10:00
type-two
be2478c8dc feat(banks): props_meshgod.jsonl — 25 prop prompts for the MeshGod /rig pipeline
Flow image -> fal-ai/trellis -> /finish -> /rig onto a Mixamo bone. Rows carry slot,
bone and scale_m (LONGEST bbox axis, what /rig?fit=1 normalises) beside the prompt;
the flowext driver ignores the extra keys.

Authored + adversarially verified: every prompt was refuted-by-default through a
geometry / scene / material lens before it survived. What that caught:

- milk crate and single LP sleeve are NOT in the bank. A milk crate is defined by an
  open lattice of ~6mm ribs, which is 1-2 voxels at TRELLIS's ~5.2mm/voxel over a 0.33m
  bbox; and under the mandatory shadowless light a blind recess and a through-hole are
  pixel-identical, so TRELLIS falls back to its lattice prior. A 12" sleeve is a 10.7:1
  flat panel. Replaced by a shallow solid-walled stacking tub and a 12cm-thick block of
  sleeves — both re-verified 0/3 and 1/3 refuted, the one dissent (a 1cm dimple pressed
  into a sub-1cm wall perforates it) fixed by thickening the wall to 2cm.
- Control experiment: the same harsh panel passed 3 already-accepted props 0/3, so its
  verdicts are calibrated, not merely hostile.
- esky appeared twice (box + bag); dropped the bag. bum bag moved Spine2 -> Hips.
  dj record bag 0.50 -> 0.38m (a 12" LP is 0.32m). cross-trainer 0.31 -> 0.29m.
  felt bush hat 0.38 -> 0.35m. gumboot stays 0.38m: that is its HEIGHT, the longest axis.
- "low-sheen ceramic" on the mug -> "with no sheen"; glaze is the likeliest specular bake.

Not enqueued — running the bank spends Flow credits. To fire it on the m3ultra rig:
  ssh m3ultra 'while read -r l; do curl -s localhost:8017/enqueue -d "$l" >/dev/null; done' \
    < banks/props_meshgod.jsonl

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 21:07:39 +10:00
type-two
18790a7e4e fix(flowext): loopback-only queue server, real self-heal, per-machine browser
Three bugs, all found standing up a second rig on m3ultra:

1. SECURITY: HTTPServer(("", 8017)) bound 0.0.0.0 with no auth, and POST /save
   base64-writes bytes to an absolute `dest` taken straight from the request body.
   Anyone on the same wifi could write arbitrary files as this user — drop a
   ~/Library/LaunchAgents plist and you have code execution. It was live on ultra
   (verified: `TCP *:8017 (LISTEN)`, 204 from 192.168.1.249). Now binds 127.0.0.1;
   FLOW_BIND overrides for a tailnet IP (utun-routed, LAN still can't reach it).

2. The launchd "self-heal" never healed anything. launch.sh backgrounds the queue
   server and exits; without AbandonProcessGroup launchd SIGKILLs the process group
   on exit, so every 10-min tick started a server that died a second later. The
   server that was actually up had been started by a manual ./launch.sh.
   Verified after the fix: kill -> 000 -> kickstart -> 204 on a fresh pid.

3. launch.sh hard-coded "Brave Browser" in the osascript. The extension is loaded
   into Chrome on m3ultra. FLOW_BROWSER now names it (default Brave, unchanged
   for ultra); m3ultra's plist sets "Google Chrome".

Also chmod +x install.sh launch.sh (both had lost the bit).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 20:29:53 +10:00
type-two
9974b93379 feat(requeue): --force, for when Flow succeeds at the wrong picture
cal79_throbbing was recorded 'success' with 4 assets — but they were Kenner
Alien toy ads, not the Throbbing Gristle clifftop it asked for. Flow refused
the Kenner brief, drew a Voyager plate instead, and emitted the toy variants
late, so the harvester (which attributes whatever NEW tiles appear to the
CURRENT task) filed them under the next task in the queue.

Successes stay protected by default — re-running one spends credits for an
asset you already have. --force is the deliberate override, and it says so
before it acts. --force with no ids matches nothing.

Known limitation, not fixed here: asset->task attribution is a grid diff, so
a late or refused generation can land under its successor. Check the pictures,
not just the status.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 20:13:50 +10:00
type-two
84fa103125 docs: correct 3cff97d — the 'ratelimited' bug was not real
I claimed done_ids() was binning rate-limited tasks forever. It wasn't:
/task-completed has always refused to persist 'ratelimited' and 'requeue'
rows (they stay PENDING by design), so such an id can never reach
results.jsonl. Verified against the copy that was actually running.

The done_ids() guard stays as defence in depth against a hand-appended row,
but its comment no longer claims to fix a bug that didn't exist. The real
bug in that commit — no circuit breaker on a failure streak — stands, as
does the actual root cause in 82d5ff4 (promptEchoed matched a 60-char prefix).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 19:09:22 +10:00
type-two
82d5ff494c fix: promptEchoed matched a 60-char PREFIX — 13 prompts silently skipped
THE ROOT CAUSE of the djsim_phonewall run, and it was never Flow.

promptEchoed() answered "has this prompt already been submitted?" by searching
the chat pane for prompt.slice(0, 60). All 15 calendar prompts open with the
same 60 characters:

  "The illustrated top picture-panel of a cheap 1979 promotiona"

So once Alien's prompt was echoed in the chat, every subsequent calendar looked
already-submitted. The driver logged "Prompt already echoed in the session —
not re-typing", typed nothing, and waited out the full 3-minute image timeout.
Thirteen times, at a metronomic 3m30s apart. Flow was working the whole time.

No fixed slice is safe: djsim_phonewall needs 160 chars of PREFIX to
disambiguate its prompts; djsim_batch3 needs 190 chars of SUFFIX. So match the
whole normalized prompt, or (if the DOM mangles the middle) require both ends
in the same element. Whitespace-normalized, with the container guard kept.

test_prompt_echo.mjs pins it: asserts the old impl DOES false-positive, the new
one doesn't, that it still fires as the "it stuck" signal, survives DOM
whitespace reflow, ignores a page-sized container, and that every prompt in
every bank is distinguishable from all its neighbours (0 missed, 0 cross-matched).

The circuit breaker from the previous commit stands: it would have stopped this
after 3 instead of 13. But the driver should never have been silent in the
first place.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 19:07:10 +10:00
type-two
3cff97df93 fix: circuit-breaker on failure streaks; stop binning rate-limited tasks
Two bugs, both found by autopsy of the djsim_phonewall run (2026-07-08):
15 calendar prompts queued, 2 generated, then THIRTEEN consecutive
"Timed out — no new asset" at a metronomic 3m30s apart. 45 minutes of the
driver politely feeding prompts into a Flow that had stopped generating.

1. NO CIRCUIT BREAKER. Each timeout threw, was reported failed, and the
   loop moved straight on. When Flow goes quiet it does not spontaneously
   start again. Now: 3 consecutive failures -> clear isRunning, log a loud
   system message, leave the queue intact for a hand-resume. (The abuse-flag
   path already had consecutiveRateLimits; failures had nothing.)

2. done_ids() COUNTED 'ratelimited' AS DONE. handleRateLimit() writes that
   status with the explicit comment "report the task back as pending" — and
   the server then binned the task forever. Now excluded. 'failed' is still
   counted: a timeout may have burned credits invisibly, so nothing retries
   automatically.

requeue.py: the deliberate way to retry. --list / --dry / by id or prefix /
--failed. Writes a .bak, never re-runs a success. Used it to make the 13
cal79 prompts pending again.

Note for whoever reads this next: the LIVE server + queue live in
~/Library/Application Support/flowrinse/, not this repo. HERE is derived
from the script's own dir, so running the repo copy silently serves the
stale Jul-6 queue. Copy the script over, run it from there.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 18:57:56 +10:00
type-two
8464cb5e21 art(bank): djsim_phonewall — 15 cursed 1979 wall-calendar picture prompts (Skylab/Alien/Joy Division/…) 2026-07-08 13:13:08 +10:00
type-two
607b5ec2b5 fix(harvest): robust Download-row finder + two-step hover + Copy Log button + 300-line log
Reported symptom: harvest opens the More menu then moves on without ever hovering
Download. Cause: the size flyout's text can glue onto the Download row (textContent
"Download1K Original size2K Upscaled..."), so the old /^download\b/ match — which needs a
word boundary right after "download" — returned null and the whole size step was skipped.

Fix: findDownloadRow() matches "download" anywhere and takes the SHORTEST visible
candidate (the row itself, not a wrapper that swallowed the flyout). Stage-3 hover now
moves in two steps (approach from the left, then settle on centre) to fire a real
mouseenter that unfurls the submenu, and re-queries. Added per-stage logging (Download
row text+coords, chosen size option) so a copied log shows exactly where any future miss
happens. Popup gains a Copy button (whole activity log to clipboard) and log retention is
raised 100 -> 300 so a full harvest pass is capturable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 11:33:18 +10:00
type-two
4aa7e19825 fix(money-safety): 4 confirmed bugs from adversarial review + Animate guard
Adversarial review (21 agents, verify layer refuted the false positives) confirmed 4:

CRITICAL — double-generation on requeue (content.js): submitEditor commits 15 credits,
  but if the visual stuck-signals lag under load the task requeue+reloads and re-submits
  (promptEchoed unreliable across reload) → up to 4×15=60 credits for one task. Fix:
  durable per-task 'submitted_<id>' marker persisted BEFORE the stuck-check, checked on
  entry, cleared only on terminal status (centralized in reportCompletion). A rare
  genuine submit-failure now times out and fails (retryable) instead of paying twice.

HIGH — transient harvest miss permanently blacklisted the asset: every miss path did
  seen.add()+persist, so a hover/menu race wrote a never-downloaded tile to storage and
  the seen-guard skipped it forever. Fix: transient misses go to an in-memory
  missedThisPass set (retried next run); ONLY confirmed downloads are persisted.

MEDIUM — Try-again re-ran succeeded gens: a spurious 'Something went wrong' banner
  co-occurring with a lagging-but-real asset auto-clicked Try-again (15cr each, ×3).
  Fix: settle + re-check assets AND new completion-message before clicking; cap 3→1.

MEDIUM — seen-list slice(-3000) evicted oldest done URLs on big libraries → re-download.
  Fix: cap raised to 20000 (and only confirmed downloads accumulate now).

+ belt-and-suspenders: findTileMenuButton fallback can never land on Animate/Like/♥/redo
  (a stray Animate click = paid image→video gen). Proven by unit test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 10:04:38 +10:00
type-two
20941c007c fix(harvest): credit-safe size picker — original size for images AND videos, never the paid upscales
Video download flyout differs from images: 270p GIF / 720p Original Size / 1080p
Upscaled / 4K Upscaled·50 credits. Old finder matched '1k' (image-only) and would
have missed video originals. New findSizeOption() keys on 'original size' (common
to both 1K and 720p rows) and hard-rejects any 'upscal'/'credit' row — the 4K video
upscale costs 50 credits, so a stray click there spends real money. Proven against
all flyout string variants (spaced + newline-collapsed).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 09:42:56 +10:00
type-two
fc3e668504 feat: Prompt Mode / DL Mode split in the popup
- DL Mode button: one click harvests everything on screen (click ⋮ -> hover
  Download -> click 1K, verified per tile), click again to stop after current
  tile; no queue involved, no server reporting for manual runs
- Prompt Mode = the existing queue runner, relabelled
- harvestActive synced to storage so the popup button reflects state

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 09:22:06 +10:00
type-two
37a2ae8cb2 fix(harvest): four verified stages — pill wait, menu wait, jiggle-hover flyout, download-event confirmation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 09:03:25 +10:00
type-two
2dfa752df3 fix(harvest): Download is a submenu parent — hover to unfurl 1K flyout, don't click; looser menu finder; reset seen-list (v2 key)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 23:04:22 +10:00
type-two
d3281bc251 feat: library harvest pass + error-baseline fix
- countErrMsgs baseline: lingering 'Something went wrong' chat history no longer
  fails every task (the 20:33-21:01 massacre — gens succeeded, all marked failed)
- Try-again only clicked when a NEW error appears (old buttons re-ran old prompts)
- kind:'harvest' task = automated John-ritual per tile: trusted CDP hover -> ⋮ ->
  Download -> 1K; background routes downloads to flowrinse/harvest/; seen-list in
  storage makes it resumable; paced + capped at 500/pass
- queued harvest_all_001 to recover tonight's generated-but-not-downloaded batch

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 22:50:37 +10:00
type-two
78b3ac85b0 feat: tile-link diffing + grid census — video harvest stops flying blind
- snapshotAssets also keys on /project/…/edit/<uuid> tile anchors: stable https,
  survive reloads (video blob srcs don't) — the reliable new-asset signal
- harvestFresh splits diff into direct media (downloaded) vs tile links (reported
  as assets when no media url — credits not lost, recoverable from the library)
- gridCensus appended to every miss so failures describe the actual harvest surface

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 19:00:38 +10:00
type-two
39d133ddfb fix: soft-detect submission + only NEW completion messages count
- countDoneMsgs baseline before submit: lingering 'has been scheduled' chatter from
  the PREVIOUS gen no longer triggers an instant post-gen reload (the self-reload bug)
- promptEchoed: chat echoing the prompt = strongest it-stuck signal, added to the
  post-Enter check; and on retry it means the earlier submit registered -> skip
  re-typing entirely (no double generation / double credits)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 18:54:05 +10:00
type-two
7fbde35e47 feat: post-video hard-refresh harvest — the agent's 'queued' message lies, the fresh page has the asset
- video path: wait for done signal (grid asset OR agent completion message incl.
  'scheduled/waiting in the queue' which usually means DONE), settle 2s, persist
  harvest state, hard refresh — never re-submit (double-bills credits)
- runPostReloadHarvest: on load with pendingHarvest, diff fresh grid vs persisted
  pre-submit snapshot (https urls only — blobs don't survive reloads), download,
  report; up to 2 extra refreshes if the asset hasn't surfaced; 30-min staleness cap
- fixes the 'Timed out — no new asset' failure class in results.jsonl

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 18:48:55 +10:00
type-two
c66cc79e90 fix: 'unusual activity' = total freeze — 30/60/90 min cease, refresh only on resume, flag outranks retries
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 18:42:11 +10:00
type-two
c21ea2b22d feat: bake in the by-hand reliability ritual — agent-ready wait, stop-square verify, hard-refresh requeue
- waitForAgentReady: after (re)load, wait for the sidebar to hydrate before typing
- post-submit success check = square stop button (or emptied box); no square after
  Enter + submit fallback -> hard refresh (bypassCache via background) and requeue
- 'Something went wrong' surviving Try-again -> hard refresh + requeue (was: fail)
- requeue attempts capped at 3 per task (chrome.storage, survives reloads)
- server: 'requeue' status keeps task pending; INFLIGHT entries expire after 15 min
  so a reloaded tab gets its task re-served
- banks/djsim_batch3.jsonl: 18-task 90sDJsim asset bank (queued live)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 17:42:15 +10:00
type-two
72a793932f content.js: auto-click "Try again" on Flow's transient error; fix 2 queue ratios
Flow throws "Something went wrong. Please try again" constantly under load; the
driver treated it as terminal (task FAILED, moves on). Now it clicks the Try
again button — same prompt re-runs — up to 3x with a 15s cooldown so a lingering
banner doesn't burn all retries. Gives up only after 3 shots or an error banner
with no retry button.

queue.jsonl: retarget the 2 unsupported aspect ratios (16:5, 21:9) to 16:9 —
Nano Banana 2 only supports 16:9/1:1/3:4/4:3/9:16, otherwise the agent asks a
clarifying question and produces no asset (driver times out).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 01:40:25 +10:00
type-two
501431bf59 Flow rinse: browser downloads, fast-fail, autoStart, launcher + self-healing launchd
- background.js: chrome.downloads via page session (no CSP/base64)
- content.js: fast-fail on Flow error banner, image vs video timeouts, autoStart
- local_server_example.py: /enqueue + /save, downloads/ output, resume-skip
- launch.sh: idempotent server-up + caffeinate + single-tab focus
- install.sh + plist: self-healing agent every 10 min (TCC-safe App Support copy)
- flowclient.py: enqueue/wait_for helper for game projects
- README: full setup + macOS TCC gotcha

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 01:20:32 +10:00
type-two
7ae0a73db0 Flow Auto-Pilot: trusted-CDP input driver, local queue server, 91-prompt bank
DOM automation for Google Labs Flow — background worker injects trusted input
via the DevTools Protocol (Flow's editor ignores synthetic events), polls a local
queue, harvests generated asset URLs. Includes the generated game+promo prompt bank.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 22:44:10 +10:00