Commit Graph
240 Commits
Author SHA1 Message Date
Abdul WahabandCursor c23c587ed5 Add provider-flexible image API path and dedupe visual cue compiles.
Ship image-gen.mjs with bfl and gemini backends plus custom delegation, document the keyless flow in image-api.md, and tighten seed Step 4 so missing keys ask once and opt-out falls back to text-only seeding. Compile now removes in-folder hero intermediates so each cue keeps one PNG.

AI-assisted commit.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-01 10:00:42 +05:00
Abdul WahabandCursor a0f7fae4e2 Speed up visual cues wave: drop smoke test, slim spawns, brief-only reads.
Replace preflight generation with harness tool presence, move territories into brief.md, forbid specialist repo reads, and document native tool output paths.

AI-assisted commit.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-01 10:00:42 +05:00
Abdul WahabandCursor af01134825 Drop artifact sheets from visual cues for faster hero-only pipeline.
Each specialist now generates one hero image instead of a second chroma-key sheet, and the compile step replaces crop with a simpler cues.json shape.

AI-assisted commit.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-01 10:00:42 +05:00
Abdul Wahab 93e0571f20 update 2026-09-01 10:00:42 +05:00
Abdul WahabandCursor f8981c61dd Switch artifact sheets to per-cue chroma keys kept in crops
Drop the two-pass matte pipeline in favor of one chroma-key sheet per
cue: each specialist picks the farthest-hue key, stages larger artifacts
with shadowless crisp edges, reports CHROMA in its reply, and crop records
the hex in cues.json for browser keying downstream.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-01 10:00:42 +05:00
Abdul WahabandCursor 7593ec9d93 Matte transparent artifacts from two sheet passes; require square, well-lit generations
Artifact crops now ship with real alpha: each sheet is generated twice
(cream, then black via image edit) and fused by a new difference-matting
command, sidestepping models' inability to emit alpha and the chroma
key's spill. Crop and matte reject non-square inputs so squareness must
come from the generation call's 1:1 parameter, and the hero prompt now
demands bright, generous light so palettes stay sampleable.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-01 10:00:42 +05:00
Abdul WahabandCursor a84002d69b Fix cross-subagent image collisions on shared output filenames
A live run shipped one hero under three slugs: parallel subagents all
wrote the generation tool's output as a generic hero.png in the shared
project assets folder, then copied and referenced each other's files.
Spawn tasks now require slug-based output filenames, using only the
tool-reported path, a verify-your-own-files check before reporting, and
the parent hashes all heroes before cropping and re-spawns duplicates.

AI-assisted (Cursor agent), directed by abdulwahabone.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-01 10:00:42 +05:00
Abdul WahabandCursor 2ae67485fb Stage hero palettes as large color fields, framed close
Live cues rendered the good colors as slivers: the hero prompt asked for
an atmospheric scene with a 60% neutral ground and a small accent. The
skeleton now frames tight on the subject and stages each color as a
large unbroken field (neutral about half, primary a continuous third,
tertiary small but legible), with the rationale in the fill rules.

AI-assisted (Cursor agent), directed by abdulwahabone.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-01 10:00:42 +05:00
Abdul WahabandCursor 6e4dcef80c Fix: em dashes in the territory example set
AI-assisted (Cursor agent), directed by abdulwahabone.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-01 10:00:42 +05:00
Abdul WahabandCursor 0473c9f7e0 Give every territory a hue ground and gate image gen on self-critique
Investigation of a live run showed five of six palettes converging on the
brief's deep-teal anchor: territories were scenic but hue-silent, and the
anchor reached every spawn unscoped. Territories now must close on a hue
ground (no two in one family), the anchor is owned by exactly one
territory with everyone else told to leave it, spawn tasks may not be
compressed, and each subagent critiques its palette and concept against
the rules before generating.

AI-assisted (Cursor agent), directed by abdulwahabone.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-01 10:00:42 +05:00
Abdul WahabandCursor 71f683ddb6 Harden the parallel mandate and keep six cues on the serial path
Name the common spawn tools, require all six spawns in a single message,
and call out spawn-await-spawn as the serial-loop failure it is. The
no-subagent fallback now runs all six personas instead of four, so the
user gets six cues on every path.

AI-assisted (Cursor agent), directed by abdulwahabone.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-01 10:00:42 +05:00
Abdul WahabandCursor a6d818b31c Assign territories upfront and run the studio as one wave
Drop the sequential palette chain: the parent carves six visual,
emotional, or strategic territories from the brief, then all six
personas spawn in one parallel batch, each composing inside its own
territory and generating both images in the same task.

AI-assisted (Cursor agent), directed by abdulwahabone.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-01 10:00:42 +05:00
Abdul WahabandCursor 4bf39fe09d Split the studio into a palette chain and an image wave
Personas now compose sequentially, each shown the color territories the
earlier personas claimed, replacing the similarity script and peer
critique as the uniqueness mechanism. Generation moves to a parallel wave
of dedicated image-prompt specialists that stage the finished palettes.

AI-assisted (Cursor agent), directed by abdulwahabone.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-01 10:00:42 +05:00
Abdul Wahab e237df2b11 Revert "Replace peer critique with a similarity convergence loop"
This reverts commit 57e45628f39149cf3700da4a431f66a595754d1d.
2026-09-01 10:00:42 +05:00
Abdul WahabandCursor 24aaabdd26 Replace peer critique with a similarity convergence loop
Drop the six-way critique wave from the visual-cues studio: after the
compose wave, the OKLab similarity script loops with revision waves for
flagged personas only (capped at three) until every verdict is clear,
then the generation wave stages the settled palettes.

AI-assisted (Cursor agent), directed by abdulwahabone.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-01 10:00:42 +05:00
Abdul WahabandCursor 54a5cbd379 Unify studio flow on wave numbering
Drop the parallel "round" vocabulary from the visual-cues studio so one
counting system covers the three spawn waves; the subagent template calls
the palette a first draft instead.

AI-assisted (Cursor agent), directed by abdulwahabone.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-01 10:00:42 +05:00
Abdul WahabandCursor a0fd0475f5 Compose cue palettes with six competing persona subagents
Replace the single-mind palette composition in the visual-cues pipeline
with a three-wave studio: six persona specialists compose in parallel, a
new OKLab similarity command plus peer critiques build each persona's
scorecard, then each revises and generates its hero and artifact sheet.

AI-assisted (Cursor agent), directed by abdulwahabone.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-01 10:00:42 +05:00
Abdul WahabandCursor ec83174eb2 Generate visual cues for document seed color picks
Document seed mode's palette pick used to ask the user to imagine colors
from words. Add a visual-cues pipeline: compose four-hex palettes from the
brief (mood, references, PRODUCT.md), generate a hero scene plus a cream
artifact sheet per concept, crop the sheet into isolated artifacts, and
write cues.json so the user can pick a direction by eye.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-01 10:00:42 +05:00
Abdul Wahab f92adeab17 Revert "Recognize the seed-collected image key in shape and craft."
This reverts commit 70eddbe2742948e1b8e95a3ef515de4e85b55a80.
2026-09-01 10:00:42 +05:00
Abdul WahabandCursor 65ac2a5f13 Recognize the seed-collected image key in shape and craft.
A stored IMAGE_GEN_API_KEY in .impeccable/.env now counts as image generation being available for shape probes and the craft codex flow. The key ask itself stays exclusive to document seed mode; shape and craft still never prompt for APIs or tooling.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-01 10:00:42 +05:00
Abdul WahabandCursor 840165463c Add editor voice and capability-gated visual cues to document seed.
Seed questions now avoid skill vocabulary (mirroring init.md's magazine-editor line), and a new step offers 2-4 generated palette cue images: native image_gen when the harness has it, otherwise an opt-in IMAGE_GEN_API_KEY in gitignored .impeccable/.env.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-01 10:00:42 +05:00
Abdul WahabandCursor 94ed8d7d45 Extend document seed mode to gather brand assets first.
Ask for logos, reference images, and moodboards before the five-question interview so the first DESIGN.md seed can ground taste selections in real visual context.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-01 10:00:41 +05:00
Paul BakausandGitHub 6fe900dbb4 Improve incumbent evidence and direction fusion (#689)
Prefer committed visual goldens when the app cannot run and make assigned-system translation explicit when a pinned register conflicts with literal materials.\n\nAI-assisted: prepared with Codex under @pbakaus direction.
2026-09-01 00:22:49 -04:00
Abdul WahabandGitHub 5211bdf4b1 Fix: critique snapshot close path (#660)
Preserve critique trend history while closing the exact processed snapshot. Track target identity and content freshness for local files and URLs, isolate colliding streams, and prevent legacy snapshots from resurfacing after a modern close.

Validated with 50 focused tests, a clean 17-provider build, 834 core tests, passing GitHub CI and Cursor Bugbot, Greptile 5/5, and zero unresolved review threads.

AI-assisted maintainer repair: implemented and reviewed with Codex under @pbakaus direction.
2026-08-31 22:42:44 -04:00
MorganandGitHub 1130d00ebc Fix: keep direction contracts out of production output (#673)
Store direction contracts in development-only surface briefs and guard against browser-delivered leakage with regression coverage.

AI-assisted merge: reviewed and executed by Codex under maintainer direction.
2026-08-31 19:07:44 -04:00
Abdul WahabandGitHub fc442be223 Fix: make hooks reset remove installed manifest entries (#668)
Fixes #512 and resolves the verified reproduction in #667.\n\nAI-assisted change: reviewed and merged by Codex under maintainer direction.
2026-08-31 18:21:34 -04:00
Paul Bakaus c75f9f1086 Above the bar, hero readings advise instead of block; spec escape hatches persist and announce; font-match tolerates an unwritable /tmp
Paul's decision on the tenth sweep's design question: hard vetoes (missing region, contradicted plate or text, SVG illustration, clipped plate, invented ink) stay unconditional; at overall >= HERO_MIN the numeric readings (ink colour, letter-spacing, line pitch, strip heights, box positions) print as advisories with the pass and belong to the polish pass. Every sweep-10 sample closes its hero under this condition, which settles 07 without another paid round.

Ninth-sweep defects: codeDrawn / container / bleed now persist into spec.json with WARN lines (an overridden refusal used to vanish from the record); font-match probes os.tmpdir() and points TMPDIR at .impeccable/tmp when the sandbox /tmp is unwritable (every ninth-sweep rank silently fell back to the catalog).

AI-assisted (Claude Code).
2026-08-28 14:41:47 -07:00
Paul BakausandAbdul Wahab bef185360f build-phase.mjs scaffold: the measured layout as CSS custom properties and a reference page
A reference, not the page: --r-<id>-x/y/w/h in % of the comp (plus cap height, font-size, family, weight where measured) to bind to any markup, and hero-reference.html with every region at its box and every plate placed with object-fit: contain, as a check on positions. Attacks the most common execution failure of weaker builders (badly positioned, overflowing, pushed below the fold) without dictating structure to strong ones; overlapping boxes are overlapping boxes and the gate reads pixels regardless.

AI-assisted (Claude Code).
2026-08-28 06:13:59 +05:00
Paul BakausandAbdul Wahab 2debb7078f Hero refuses inline SVG illustrations; finish cannot record ship over an open phase; the comp-led path names its model tier
From the human review's most repeated pin ('terrible svg instead of asset', on every model) and from sessions that wrote 'ship' with the hero open. Icons, arrows, chevrons, and runtime data charts stay code; diagrams, notation, and leader lines are plates.

AI-assisted (Claude Code).
2026-08-28 06:13:59 +05:00
Paul BakausandAbdul Wahab 38170564c6 Plates gate refuses a comp crop shipped as a plate; text readings include letter-spacing
From the final review batch: 'bad asset crop (crops are never allowed)' twice, 'letter spacing way too wide'. A crop resampled to the region scores 99.8% structure against the raw region; a produced plate scores 30-60.

AI-assisted (Claude Code).
2026-08-28 06:13:59 +05:00
Paul BakausandAbdul Wahab 7cea970c6c comp-spec snaps text and control regions to the largest ink mass in their grid span
A session's own note said its hero sat at 67 because the 10x10 grid boxes straddled two elements each, and it was right: every downstream measurement (cap height, line count, structure) inherited the slop. Text and control regions now snap to the dominant connected ink inside the span (page-ground threshold, dilated cells, masses touching the span's sides lose to inside masses), keep the span on the record for coverage, and can opt out with snap: false.

AI-assisted (Claude Code).
2026-08-28 06:13:59 +05:00
Paul BakausandAbdul Wahab 36e6864d56 Controls are held like text at the hero: a contradicted control vetoes, a far drift is named; the icon concession covers glyphs only
Per pbakaus: close-enough icons are fine, arrows and dropdown chrome are not.

AI-assisted (Claude Code).
2026-08-28 06:13:59 +05:00
Paul BakausandAbdul Wahab 07e3fad3b6 Spec refuses a plate box that cuts its artwork; hero counts strong small invented inserts; painted-note regex no longer matches a label
From the second review batch: the best build of the fifth sweep passed the hero at 87% with the cover arch cut flat on the left (object-fit: cover on a box narrower than the shape), and legends, badges, and extra controls one or two cells wide slipped under the invented-ink floor. comp-spec measures the artwork's contiguous contact with each box edge against the page ground; the spec gate refuses such a box unless bleed is set. Human pass line landed at comp-diff 72-73; HERO_MIN stays 0.72.

AI-assisted (Claude Code).
2026-08-28 06:13:59 +05:00
Paul BakausandAbdul Wahab 00a180380e Hero gate reads type, strips, and invented ink as numbers; every region needs a note; missing beats the text relaxation
From the first human review of sweep-3 builds (pins on 12 samples): fonts at the wrong size, weight, colour, or place; nav bars too tall; kickers and dividers the comp does not have; a footer strip pushed off the frame that read as drift on ground colour alone; a drawing filed as chrome with no note to catch it.

- lib/hero-checks.mjs: textRegionCheck (cap height, line count, ink density, ink colour, first-line offset vs the comp crop, measured fresh), chromeStripCheck (first rule row), inventedInk (build energy over a calm comp cell and neighbourhood). Wired into gateHero as reasons; invented ink vetoes at 4% of cells.
- comp-diff verdictFor: detailRaw < 0.15 is missing whatever the palette.
- comp-spec: every region carries a note.
- font-fingerprint: the tall-line filter takes its median over lines with real mass, so two display lines above a small line are not 'tall'.

AI-assisted (Claude Code).
2026-08-28 06:13:59 +05:00
Paul BakausandAbdul Wahab 356362a410 comp-spec refuses a code region larger than a quarter of the comp
A session named seven regions for a page with three plates, a table, a note, callouts and a spine, so the hero gate could name nothing and the score sat at 70. A code region is one element; a column is a container of several.

AI-assisted (Claude Code).
2026-08-28 06:13:59 +05:00
Paul BakausandAbdul Wahab 99f73390db Comp fidelity: font ranking that holds without a browser, spec refuses painted chrome, control-box veto only for discrete controls
font-match / catalog index
- Index schema 2 adds a third render, 48c (48px cap, ALL CAPS text). Caps headline crops have no x-height band and ranked against mixed-case renders as barcode faces; they now route to the caps render.
- Non-text families (barcodes, redacted, flow, dingbats, effect faces) are excluded from candidates.
- The distance adds a gross width and weight gap (log ratio of advance and ink density) so a face 50% wider or 35% lighter cannot rank first on run-length detail alone; the index stores those readings.
- Multi-line all-caps crops vote on x-height across lines: one line's crossbars no longer give the crop a spurious x band.
- With no browser, --rank records the catalog's nearest face (source catalog, size estimated) so the spec gate can close; the NEXT line and new-work.md say not to install a browser or hand-write a choice.
- font-match stamps the choice it writes; the spec gate refuses a chosen face it did not write (sessions typed Arial Narrow into spec.json to pass).
- IMPECCABLE_NODE_MODULES lets a harness lend a playwright.

comp-spec
- A region note that describes painted material (diagram, drawing, photo, texture...) under a code kind is refused at the spec unless codeDrawn is set: the exploded carburetor filed as chrome is a plate about to be redrawn in SVG.

build-phase
- The control ink-box veto applies only when the comp's ink is a discrete element and the build's box is too; a full-width bar told one session six times that 1376x87 was 1382x102 with no edit able to move it.

AI-assisted (Claude Code).
2026-08-28 06:13:59 +05:00
95294e464a font-match v2: fingerprint the comp lettering and pick candidates from a Google Fonts catalog index
lib/font-fingerprint.mjs replaces the three-number fingerprint with
size-invariant shape features (x-height ratio, stroke contrast, stem width,
run-length quantiles, roundness, serif signal, width spread) and a
noise-normalized distance; family recall on a held-out self-test rose from
13% to 72% top-5. data/font-index.json carries the whole Google Fonts
catalog (3,092 faces at two cap sizes, 707 KB); font-match --rank fingerprints
the comp crop, takes the 25 nearest faces from the index (plus the model's
own names), renders them at the comp's cap height, ranks by the same
distance, and prints a proof sheet and the CSS to use. scripts/build-font-
index.mjs rebuilds the index at release time.

AI-assisted (Claude).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-28 06:13:59 +05:00
cacb2868ac No comps outside the state: generate-image refuses .impeccable/mocks/ output while a roll is pending and build-phase has not started
The first paid confirmation sweep showed the failure: models rendered the
three comps first and ran build-phase.mjs start after, so a session cut at
the composition pick carried no state.json and the resumed model followed
the conversation ('translate the comp into HTML now') instead of the
phases. Decision comps (.impeccable/mocks/decision/) are unaffected;
--force-mock overrides.

AI-assisted (Claude).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-28 06:13:59 +05:00
f5751c4d75 font-match: choose the face by metrics; chroma-keyed plates; ink-box report; verbatim words in the hero
font-match.mjs fingerprints a text region's lettering in the comp (cap
height, glyph advance per cap = width class, ink fraction = weight class,
tracking), renders candidate faces at that cap height in a headless
browser (yours plus a shortlist for the width class), and ranks them by
distance with a proof sheet; the spec gate refuses to close until the lead
text region is measured and ranked. generate-image --plate keys ink-on-
ground plates to alpha (chroma) so the drawing sits on the page's own
ground; the plates gate scores keyed plates composited over the region's
ground. comp-diff reports each region's ink box; the hero gate names a
control whose box height or width differs from the comp. The hero
instruction copies the comp's words verbatim; rewording is a stated
decision after the hero passes.

Driven by a human review of the r3 side-by-sides: face width and weight,
plate ground, control row height, and content substitution.

AI-assisted (Claude).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-28 06:13:59 +05:00
af4ac68805 Plates: textures tile a clean comp patch first; record hero reports plate rows
AI-assisted (Claude).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-28 06:13:59 +05:00
e618357a69 Responsive gate: the desktop capture must still read as the comp
Round-1 simulated builds passed the hero at 1536 and shipped a page whose
first viewport collapsed to one column at 1440 (comp-diff 50% on the
final capture, 82% on the hero). The responsive phase now requires
desktop.png and mobile.png and diffs desktop.png against the comp at 65%
with no region missing.

AI-assisted (Claude).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-28 06:13:59 +05:00
d9a155be8c Gates that cannot be talked past: metric hardening, one start command, uncovered-ink refusal
From a forensics pass over twelve runs and two adversarial passes over
the metrics:

- comp-diff: detail is signed and penalizes invented energy; regions with
  structure under 0.3 (or painted regions under 0.45 / added detail over
  0.4) are contradicted whatever the mean says; palette ramp tightened;
  region crops inherit the whole-image best translation so a shifted page
  is not eight contradicted regions.
- hero gate: fails on any contradicted plate/image/text region (chrome and
  controls keep the one-third allowance), on a capture that is not the
  comp's frame, on a palette that is not the comp's, and on an organic
  clip-path drawn inside a raster region's box.
- plates gate: scored against the comp crop with overlapping text/chrome
  painted out (comp-spec plateReference; generate-image uses it too), with
  a structure floor and an added-detail veto; the real plate passes, noise,
  mirrors, mosaics, and other regions do not.
- comp-spec refuses a regions file that leaves comp ink unnamed.
- The direction-choice ping is folded into build-phase.mjs start
  --direction --kind; the roll writes .impeccable/build/pending.json and
  context.mjs / detect.mjs report COMP_ROUND_OPEN until the hero gate
  passes. A code-led config makes start print the contract step and stop.

AI-assisted (Claude).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-28 06:13:59 +05:00
6dd15238c4 Close the comp-round gap and make the hero gate teach
concept-seed's choice ping now prints the next mandatory step from the
recorded build path (comp-led: build-phase.mjs start --direction <key>),
because every run that skipped the comp round did so right after that
ping. build-phase gains a comps phase ahead of spec (three sidecar'd comps
under .impeccable/mocks/, one approved) and records the approved comp on
close. The hero gate lists the worst region crops first with the fix class
per verdict, and refuses a third value-only attempt on the same stuck
region. Hero instruction is plates first, then the semantic layer. The
finish reviewer treats a comp-led build with no closed comps phase as a
material finding.

AI-assisted (Claude).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-28 06:13:59 +05:00
f4987eebba Hero gate refuses while a produced plate is unreferenced by the source
The first live run produced a faithful carburetor plate, then drew the
region in SVG and left the plate on disk. Before diffing, the hero gate
now walks the artifact (or a bounded source tree) for every plate's file
name or a data URI named for it.

AI-assisted (Claude).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-28 06:13:27 +05:00
63dd7faa0e build-phase: textures skip the size floor, --force needs the user's words
The first live run forced past the plates gate with 'single-file HTML
delivery requires embedded CSS/SVG'. That is not a reason the comp's
authority moves for; the script now refuses a --force whose reason does
not quote the user, and new-work.md says a single-file deliverable inlines
the plate as a data URI. Texture plates are judged on palette and grain,
not size or structure, since they tile.

AI-assisted (Claude).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-28 06:13:27 +05:00
34ef9ac2c4 Rewrite the comp-led build around the phase gates; reviewer reads the diff first
new-work.md section 6 becomes the spec / plates / hero / sections / motion /
responsive phase list, each closed by build-phase.mjs advance; the
reproduction and hero-checkpoint prose that asked the model to compare
from memory is gone. visualize.md's inventory, medium gate, and produce
sections collapse into the spec and plate mechanism. The finish reviewer
takes the state file and comp-diff reports as inputs and starts its
fidelity matrix from the measured verdicts. docs/COMP-FIDELITY.md records
the design.

AI-assisted (Claude).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-28 06:13:27 +05:00
Abdul WahabandCursor 35ae07339b Fix: parse Grok Build camelCase hook stdin (#646)
Grok was classified as GitHub Copilot, so the design hook skipped every
edit with no-file-path and never ran Stop. Normalize toolInput/sessionId
and treat Stop additionalContext as the Grok product.

Prepared with AI assistance.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-24 05:28:21 +05:00
Paul Bakaus 7d5c60d291 Remove stale Claude MultiEdit matcher
Claude Code now folds multi-edit behavior into Edit, so keep generated and repaired hook manifests aligned with the current Edit and Write tools. Grok keeps its compatibility matcher unchanged.

AI assistance was used to implement and validate this change.
2026-08-19 09:28:28 -07:00
3c6f53406b Fix: stop the direction page hanging forever after a re-roll (#469) (#530)
* Fix: stop the direction page hanging forever after a re-roll (#469)

The re-roll leg of the decision-page protocol was documented only in
serve-question.mjs's own header, so agents never ran --update and the
open tab polled a round that could never arrive. Compounding failure
modes: the page poll swallowed every error, the daemon's --timeout was
an absolute guillotine that killed the server under a still-open tab,
a choice posted to a dead server confirmed nothing, and refresh or
Reload on an unresolved round resurrected heartbeats that held the
daemon alive indefinitely.

- new-work.md documents the re-roll leg: rerun concept-seed with
  --from/--reroll, deliver with --update on the same key, never --start
  a second server.
- The page poll terminates and says why: eight consecutive fetch
  failures means the server is gone; the delivery deadline (the
  server's own --idle-grace, inlined into the page) passing means the
  hand never arrived. Both stop heartbeating.
- The daemon's --timeout bounds only the wait for a page to open; once
  the page heartbeats, the server lives while the page does and exits
  after --idle-grace (default 600s) without a beat, including under
  --timeout 0.
- Build this and Re-roll against a dead server fail loudly instead of
  silently swallowing the click.
- The server tracks the window between a collected re-roll answer and
  the --update that replaces the round, and serves the page in waiting
  mode there, so a native refresh re-enters the same bounded wait
  instead of resurrecting dead cards; the in-page Reload button only
  revives a delivered hand.
- --update is exempt from the headless gate and its liveness probe
  trusts a fresh heartbeat over a failed kill probe (sandbox EPERM is
  not death).

Squash of the six review-round commits on this branch, rebased onto
main after the decision-page revamp.

AI assistance: prepared with an AI agent operating under maintainer
instruction (abdulwahabone).

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix review findings: persist the replacement deadline, refuse unloadable hands

A browser-native refresh of the waiting page re-entered the bounded wait
with a fresh delivery deadline and an immediate heartbeat, so refreshing
before each deadline expired could hold the daemon alive and keep --wait
on WAITING indefinitely. The server now records when the re-roll or
followup answer was collected, each served waiting page inherits only
what remains of that one allowance, and a page served after the deadline
renders stalled immediately and never starts its heartbeat.

And a next hand the round could not load used to reload-loop the tab:
GET /'s catch kept the file on disk, so /next-status stayed ready:true
forever. --update now refuses a payload without a non-empty options
array at the sender, and GET / discards an unloadable next file so the
bounded wait resumes.

AI-assisted (Cursor agent) under maintainer instruction.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix review finding: a stalled page recovers a late hand without a click

The stall silenced heartbeats so the idle grace could reclaim the
daemon, but that silence read as a closed tab: after a late --update,
--wait saw the stale beat and reported PAGE CLOSED while the user sat
on the Reload screen, so the agent abandoned the browser path the
recovery UI exists for. The stall screen now keeps a beat-free
/next-status watch that reloads into a delivered hand on its own
(GET never beats, so an abandoned flow is still reclaimed), and --wait
no longer concludes closure from a stale beat while an undelivered
next hand sits on disk.

AI-assisted (Cursor agent) under maintainer instruction.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix review finding: a delivered hand must not mask a closed page

The mid-delivery suppression keyed on the next file existing, but a
closed tab never claims that file, so an unconsumed delivery held
--wait on WAITING indefinitely instead of reporting the closed flow.
The suppression is now age-bound: a stalled page's watch reclaims a
delivered hand within seconds, so a file still unclaimed after a 10s
grace means no page is coming back and the stale beat reads as the
closed page it is.

AI-assisted (Cursor agent) under maintainer instruction.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix review finding: stamp the delivery clock at --update, not the copy

--wait's mid-delivery grace reads the next file's mtime, but
copyFileSync's timestamp behavior is the platform's business: a copy
that preserves the source payload's older mtime would start the grace
already spent and report PAGE CLOSED under a live stalled tab. --update
now touches the delivered file itself, so delivery time is delivery
time everywhere.

AI-assisted (Cursor agent) under maintainer instruction.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix review findings: disable canon during the wait, validate --timeout

The waiting and stall screens disabled only the re-roll buttons; the
footer canon action stayed clickable, and a canon pick posted after
--wait had consumed the re-roll could never be collected: it overwrote
the answer, marked the table closed, and exited the daemon under the
agent. Both disable sites now take the canon exit down with the re-roll
buttons; a delivered hand reloads the page and serves it live again.

And --timeout reached the lifetime timer unvalidated: NaN or a negative
value disarmed the no-page exit and the daemon leaked. It now takes the
default unless the value is a finite non-negative number, keeping 0 as
the explicit wait-forever.

AI-assisted (Cursor agent) under maintainer instruction.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix review finding: a second click must not renew the delivery deadline

dealAgain left the re-roll and canon controls live through the answer
POST and the 700ms fly-out, so a second click posted another re-roll
and the server restamped awaitingNextSince, renewing the deadline this
PR made non-renewable on refresh and on the stall screen. The controls
now go quiet at the click itself, in dealAgain and in answer(), and the
server stamps the allowance only on the transition into the wait, so a
duplicate answer racing the disable keeps the first stamp.

Regression coverage on both sides: the unit deadline test posts a
duplicate re-roll mid-allowance and asserts the budget shrank instead
of resetting, and the e2e stall test asserts both controls are disabled
immediately after the click, before the fly-out.

AI-assisted (Cursor agent) under maintainer instruction.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix review finding: a late delivery must survive its claim window

--update could land a replacement hand after the stalled page went
silent but moments before the daemon's idle deadline: the daemon exited
before the page's 1.5s watch could claim the hand, orphaning a delivery
--update had confirmed, and the next --wait reported a server failure.
The idle exit now defers while an unclaimed next hand is younger than
the claim grace --wait already reads (extracted as one shared
constant), so the page's watch deals it and heartbeats resume; a file
unclaimed past the grace still ends the daemon, bounded as before.

Regression test: deliver at idle-deadline-minus-a-beat, assert the
daemon survives past the deadline and serves the late hand.

AI-assisted (Cursor agent) under maintainer instruction.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix review finding: the claim itself must hold the daemon

The idle-exit hold read only the next file's freshness, but GET /
deletes that file when it serves the claimed round, before the
reloading page can post its first heartbeat: a lifetime tick in that
gap saw no pending hand and a stale beat, and exited under the hand
just claimed. GET / now stamps the claim when it consumes a pending
hand, and the idle exit honors the same bounded grace from that stamp,
so the reloading page gets its seconds to beat while an abandoned claim
still ends the daemon at the grace.

The claim-window regression test now also fetches after the claim, past
another lifetime tick, and asserts the daemon survived the gap;
verified it fails on the previous commit.

AI-assisted (Cursor agent) under maintainer instruction.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix review finding: --wait must ride out the claim gap too

The claim deletes the next file --wait's mid-delivery grace watches,
and the reloading page has not beat yet, so --wait in that gap read the
stale beat as PAGE CLOSED while the daemon was alive serving the dealt
round, and the agent abandoned a browser session that had just
recovered. GET / now persists the claim stamp into the per-key state
file, and --wait's suppression honors it under the same bounded grace:
a fresh claim stays WAITING, a claim nobody followed with a beat still
reads as the closed page it is.

Regression test drives --wait through the gap (claim with a stale beat:
WAITING, not exit 4) and past it (backdated claim stamp: exit 4);
verified it fails on the previous commit.

AI-assisted (Cursor agent) under maintainer instruction.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Paul Bakaus <paul.bakaus@gmail.com>
2026-08-16 14:26:02 -07:00
Abdul WahabandGitHub f1560cc238 Merge pull request #590 from pbakaus/fix/comp-ground-sampling
Fix uncaught ground-color drift on comp-led builds
2026-08-16 13:52:16 +05:00