Commit Graph

10 Commits

Author SHA1 Message Date
Iisyourdad 951bba7a21 Fix dropped clicks and late screenshots in fast recording
Template tests / tests (push) Successful in 2m13s
Template tests / tests (pull_request) Successful in 1m48s
Root cause of 'I clicked many times but only got two screenshots':
finishing/pausing a session called backend.stop(), which cancelled every
in-flight frame request to null. Clicks whose PNG had not finished
encoding yet were then dropped — only the first few survived.

Fixes:
- Stream backend now *drains* on stop: it stops accepting new requests but
  keeps the worker alive until frames already selected for queued clicks
  finish encoding. stop({ immediate: true }) keeps the old abandon-now
  behavior for an unhealthy worker.
- Two-stage worker reply: a fast 'frame-selected' ack pins the pairing and
  proves liveness; the slow PNG payload follows. A slow encode (seconds on
  software-rendered hosts) is no longer mistaken for a dead worker, which
  had been forcing the post-click fresh-shot fallback (late screenshots).
- Queued clicks carry their guide id and are stored even if the session
  ends while they wait in the queue.
- The tray gesture that stops a session is discarded by matching its
  recorded screen position, not a time window — a fast workflow click near
  the stop is no longer collateral damage. (Replaces the earlier grace
  window, which dropped whole bursts.)
- A click on a display with no ready stream resolves null so the caller
  fresh-shots the correct monitor instead of returning another screen.
- STEPFORGE_CAPTURE_LOG=1 prints one line per click decision; the
  second-instance handler now surfaces the running window instead of
  exiting silently.
- Self-test gains a fast-burst-then-finish scenario (8/8 saved) and the
  marker/coordinate checks remain at 0.00% offset.

Tests: 133 unit + all repo checks passing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 07:56:31 -05:00
Iisyourdad 5ca59805dc Make click selftest immune to real mouse input and DPI scaling
Template tests / tests (pull_request) Successful in 1m48s
Template tests / tests (push) Successful in 1m51s
- Stop the live OS click watcher during the selftest so the user's real
  clicks (toast dismissal, terminal focus) can't add extra steps and
  shift the marker comparisons.
- Inject clicks in physical pixels via dipToScreenPoint so the test
  measures correctly on scaled Windows displays.
- Guard the marker report against step-count mismatches instead of
  crashing on out-of-range indexing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 22:01:37 -05:00
Iisyourdad a0b69f8cc7 Rearchitect click capture: strict click-time frames, off-main-process recorder, exact marker coordinates
Template tests / tests (push) Successful in 1m50s
Implements the architecture change from ai_prompts/prompt3.md:

- New app/click-frames.js: shared timestamped frame ring + strict
  click-to-frame pairing (never a frame whose grab started after the
  click); legacy slack behavior kept behind capture.strictClickFrames=false.
- New stream capture backend (app/stream-backend.js + hidden worker
  window): per-display desktop media streams sampled into ring buffers
  and PNG-encoded entirely off the main process, so click delivery is
  never starved by capture work. Auto-degrades to the legacy in-process
  frame loop when streams cannot start or the worker stops answering.
- Clicks are paired with their frame at event time (eager pairing in
  enqueueClickCapture); only the storing is serialized, so slow encodes
  cannot skew later clicks in a fast burst.
- Linux watcher: restored event-time root coordinates from
  xinput test-xi2 and merge raw/regular twin events structurally.
- Replaced the 40ms time debounce with source-aware duplicate
  suppression: fast legitimate clicks are never dropped.
- New app/coords.js: physical-to-DIP conversion with multi-monitor and
  scale-factor handling; Windows keeps screenToDipPoint.
- STEPFORGE_CLICK_SELFTEST end-to-end hook: 3/3 clicks become steps via
  the stream backend with 0.00% marker offset on this host.
- Tests rewritten/added: strict selection, coords, stream backend,
  Linux coordinate parsing, twin merge, burst clicking (126 passing).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 21:33:31 -05:00
Iisyourdad 33c421b746 Added select button toggle for trash library grid
Template tests / tests (push) Successful in 2m0s
2026-06-11 11:31:58 -05:00
Iisyourdad 99376fdeb2 Fix new-capture auto-hide, library capture bar, step delete, and click-capture timing
Template tests / tests (push) Successful in 1m49s
- New Capture sessions now start paused; the window only tucks away once
  the user clicks "Start recording" in the capture bar instead of hiding
  ~1.2s after starting.
- The capture status bar is shown only in the editor view, not over the
  library.
- Fix openModal/confirmDialog resolving as cancelled when an action button
  is clicked, which made the step "Delete" button (and other modal actions)
  silently no-op.
- Click-triggered captures now use the click-time cursor position for the
  marker and arm the capture cache as soon as recording starts, so the
  first click is captured instantly and accurately placed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 09:21:19 -05:00
Iisyourdad 25bca7c3de Session UX: tray-controlled recording, no per-shot window hiding
Template tests / tests (push) Failing after 24s
Users couldn't click into the app mid-session: every automatic capture
hid the window for the shot, so it vanished under the cursor. Under
WSLg minimize() is a no-op and isFocused() sticks true, so neither can
be used for control.

- Sessions now hide the window once at start and show a red tray icon
  with Capture now / Pause-Resume / Open StepForge (auto-pauses) /
  Finish; finishing or quitting restores/cleans up properly
- Opening the app from the tray pauses capture; resuming tucks the
  window away again
- Automatic captures skip while the cursor is over a visible StepForge
  window (cursor-based, not focus-based, due to WSLg sticky focus)
- Per-shot latency reduced: with the window already hidden the 350 ms
  hide-repaint wait is skipped entirely
- OS notification announces the session; self-tests updated and green

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 22:51:01 -05:00
Iisyourdad 52fd516a5d Make capture sessions continuous: click-capture + interval auto-capture
Template tests / tests (push) Failing after 29s
The session previously only listened for the global hotkey, which is
unreliable under WSLg/Wayland — users got one screenshot and nothing
more. Sessions now layer three triggers:

- click-capture via OS adapters (xinput test-xi2 on X11, PowerShell
  GetAsyncKeyState polling on Windows), debounced, ignoring clicks on
  StepForge itself
- interval auto-capture (3/5/10 s) as the always-works fallback,
  enabled by default when click detection is unavailable
- the existing global hotkey, plus a manual Shoot button

The REC bar now shows live count + active trigger with Shoot / Auto /
Pause / Finish. New captures and added steps are selected in the
editor (explicit reload(stepId) wins over a surviving selection).
Capture self-test hook (STEPFORGE_CAPTURE_SELFTEST) verifies 3x
hotkey-path captures and interval capture end-to-end.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 22:33:12 -05:00
Iisyourdad 6e790832f5 Complete the app: capture UI, dialogs, template manager, shortcuts help
Template tests / tests (push) Failing after 21s
- Editor topbar reworked: Back | Capture ▾ (full screen/window/region/
  delay/paste/import/session) | Save | Export | Share (.sfgz) | More ▾
  (rename, guide placeholders, backups, linked guide, shortcuts,
  settings)
- New dialogs: backups & snapshots (undoable restore), guide/global
  placeholder editor, keyboard-shortcuts reference, template manager
  (rename/duplicate/delete/share/import .sfglt)
- Export dialog: editable per-format options generated from exporter
  defaults, save-as-template, preview opens the file in the default
  viewer and keeps the dialog open for tweaking
- export:defaults IPC + preload entry
- CSS for blocks panel, focused-view sliders, export options, rows
- ipc-surface test: every preload channel has a main handler; renderer
  api.*/dialogs.* usage stays within the exposed surface (60 tests)
- CHANGELOG/README updated; prompt2.md checklist fully ticked

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 22:15:15 -05:00
Iisyourdad 03bd9b0e2b Fix renderer scope collisions, editor bugs; add welcome screen
Bug fixes from code review:
- Wrap renderer modules (canvas/dialogs/editor/app) in IIFEs: duplicate
  top-level 'const api' across plain scripts threw a SyntaxError that
  prevented app.js from ever running (blank window), and dialogs.js/
  editor.js silently overrode each other's labeledRow/makeSelect
- Focused-view toggle now writes step.focusedView.enabled instead of a
  nonexistent flat field that the schema dropped on save
- Annotation property edits no longer rebuild the panel on every
  keystroke (focus was stolen mid-typing); debounced save instead
- flushStep/undo/redo keep this.steps in sync with stepMap so the step
  list stops going stale after the first save
- Escape now deselects the annotation; Delete remains the delete key

Welcome screen (per spec): app opens to a title at top and three
buttons at the bottom — New Capture (creates a guide, opens the editor,
starts a capture session), Existing Workspace (library), Settings.
Brand click returns to the welcome screen.

Adds an env-gated dev screenshot hook (STEPFORGE_SCREENSHOT[_JS]) used
to visually verify welcome/library/editor views under WSLg.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 21:29:14 -05:00
Iisyourdad f47aca67c2 Finish Electron shell and workflow wiring
Template tests / tests (push) Failing after 4s
2026-06-10 18:32:30 -05:00