Centralize the shared boot artifact checks so doctor adds only its deep checks while preserving the existing finding order and CLI contracts.
AI-assisted: prepared by Codex under maintainer pbakaus scheduled-refactor authorization.
Resolve pending Tune controls when the completed variant set contains no tunable parameters, while preserving deferred parameter publications.
AI assistance: implemented and validated by OpenAI Codex under maintainer authorization.
Delete unreachable inline color parsing helpers and unused regular expressions without changing the DESIGN.md parser contract.
AI-assisted: prepared by Codex under pbakaus’s scheduled architecture-refactor authorization.
Keep the committed marketplace repair script aligned with Claude Code's supported Edit and Write tools, and strengthen regression coverage after automated review.\n\nThis change was prepared with AI assistance under maintainer authorization.
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.
Centralize repeated rollback result construction, repair context, and entry verification without changing the live Apply contract.
AI-assisted: prepared by Codex under pbakaus's scheduled architecture-refactor authorization.
Centralize provider fixture, hook, and agent-launch contracts while preserving provider-specific verification behavior. Reuse the shared CLI argument parser and characterize the public usage contract.
AI-assisted: prepared by Codex under pbakaus's scheduled architecture-refactor authorization.
Normalize hook command separators before matching Impeccable-owned entries so updates replace legacy Windows guards instead of duplicating them.\n\nAI assistance: Codex implemented and validated this change under maintainer authorization.
* 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>
Centralize the shared Claude-compatible PostToolUse and Stop schema while preserving every provider-specific matcher, path, notice, and timeout.\n\nAI assistance: Codex prepared this behavior-preserving refactor under pbakaus's scheduled architecture-simplification authorization.
Consolidate explicit and inferred surface route canonicalization behind one private rule, with characterization coverage for equivalent and invalid inputs.\n\nAI assistance: OpenAI Codex prepared this change under pbakaus's scheduled architecture-simplification authorization.
The quality bar leaves the color-authority chain (it arrives as card
image paths and never governs composition). With no comp, a color
OWN-WORLD names is the target; when it names none, the review states
there is no GROUND authority instead of inventing a target. The build
side of the numeric comparison now samples the same way each record
was taken: patch average against patch average, gradient ends against
gradient ends.
AI-assisted change (Cursor), prepared under maintainer direction.
Co-authored-by: Cursor <cursoragent@cursor.com>
GROUND no longer lapses silently on code-led builds: with no comp to
sample, the authority is the colors OWN-WORLD and the quality bar name,
and no invented target beyond them. Non-uniform fields get sampling
rules (interior pixel, patch average for texture, both ends of a
gradient, never an edge), and the numeric comparison gets tolerance
semantics so render noise never fails a faithful build. The hunt hint
names the dark-ground prior beside the light one.
AI-assisted change (Cursor), prepared under maintainer direction.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Bump skill-behavior google lineup to gemini-3.7-flash
gemini-3.7-flash replaces gemini-3.6-flash in DEFAULT_MODELS. The
README notes that the recorded gemini baseline cells were measured on
3.6-flash (or 3.5-flash where marked) and count as unmeasured on 3.7
per the suite's own cross-version rule, to be re-run on the next Setup
or routing change.
AI-assisted change.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
StaticElement.closest() handed the raw selector string to css-select's
is() on every ancestor step, recompiling the same selector N times for
an element N levels deep. StaticDocument now caches one compiled
matcher per selector (failed compiles cached as rethrowers so bad
selectors still return null). Findings are byte-identical across the
fixture corpus; scan time drops to ~62% on the fixtures and ~7x faster
on deep-DOM pages.
Prepared with AI assistance (Cursor agent), directed by @abdulwahabone.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Fix: keep raster provenance through the finish-review fix loop
Three runs (two harnesses) showed the parent generating production
rasters after the producer returned: no exact embedded prompt, no
inventory row, orphan files. The asset contract in visualize.md was
phase-scoped to the build while new-work.md's fix loop licensed
"produce the named assets" with no rules attached.
- visualize.md: name the provenance contract, require the exact tool
payload, and scope it to the run, fix rounds and rebuilds included.
- new-work.md: bind fix/rebuild rasters to the contract, add an
embed-prompt --scan step before the verdict round, and extend the
FINISH line to carry the condition through long builds.
- embed-prompt.mjs: add --scan mode listing rasters missing a prompt
(exit 3 when any), reusing the existing read path.
AI-assisted change, prepared with Cursor under maintainer direction.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Add cursor-control-8 comp vs final screenshots for PR evidence
AI-assisted change (Cursor), prepared under maintainer direction.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Add cursor-control-9 comp vs final screenshots for PR evidence
AI-assisted change (Cursor), prepared under maintainer direction.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Address review findings on the provenance gate
- Hoist the provenance rule out of the fix disposition into its own
paragraph binding rebuild and fix alike, gated before either round's
result goes back for review or verdict (Bugbot: rebuild skipped the
scan when its fresh review shipped).
- A scan-flagged raster gets the record it is missing embedded, exact
prompt for produced, origin for sourced/stock/pre-existing; deletion
is reserved for abandoned rasters, never scan hits (Bugbot: gate hit
non-generated assets on extensions).
- Document the scan command with its required directory argument
(Greptile: literal command exited before scanning).
- Align the FINISH line on the provenance token.
AI-assisted change (Cursor), prepared under maintainer direction.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Remove evidence images from the diff; they live on the pr-evidence branch
AI-assisted change (Cursor), prepared under maintainer direction.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Accents join the sampled record alongside ground and dominant fields,
every recorded color (not only the ground) is compared by number
during the build, and the light-ground-only rationale clauses become
value-neutral so dark and saturated comps get the same protection.
Rule anchor renamed to skill-color-by-number to match its scope.
AI-assisted change (Cursor), prepared under maintainer direction.
Co-authored-by: Cursor <cursoragent@cursor.com>
Sample the approved comp's ground and dominant-field hexes into the
brief (visualize.md), judge the built page's ground by number against
that record including the net value under textures (new-work.md), and
make GROUND a mandatory fidelity-matrix row beside TYPE and MATERIAL
(finish reviewer). Pre-comp palette chips are retired at approval.
AI-assisted change (Cursor), prepared under maintainer direction.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Simplify local detector dispatch
Centralize HTML-versus-text file routing for stdin, directory, and direct-file scans. Add CLI characterization coverage for both stdin paths.
Prepared with AI assistance under maintainer pbakaus's standing scheduled-refactor authorization.
* Strengthen detector dispatch characterization
Put the HTML-only finding in a linked stylesheet so the text engine cannot satisfy the static-engine assertion.
Prepared with AI assistance under maintainer pbakaus's standing scheduled-refactor authorization.
* Comp-fidelity review discipline + conciseness pass on core references
Process fixes derived from a real Codex session (Hanasaku landing page)
where a build drifted wholesale from the approved comp and still shipped
under a reviewer pass:
- finish reviewer: new Evidence check (check 0) with a fourth
disposition, recapture, for malformed screenshots; a review on invalid
evidence binds nothing and owes a full re-review, not a verdict pass
- finish reviewer: verdict passes exit scoring mode when recaptures fail
check 0 or when the packet carries user-supplied screenshots that
contradict a prior verdict (those force a fresh full review); a ship
earned in a verdict pass covers the scored fixes, not the whole surface
- new-work: capture-validity rules (settle entrance motion, capture from
document top, comp comparison at comp dimensions, open every file once
before sending); user's actual viewport joins the inspected sizes
- new-work: hero checkpoint now writes .impeccable/review/hero-repro.png
and the reviewer verifies it exists under Persistence
- new-work: comp authority is explicit (only the user can downgrade it);
handoff reports the verdict at its actual scope; user evidence reopens
a full review; documenter re-runs when fixes land after documentation
- craft-floor: Refuse entry for geometric masks approximating organic
photographic contours (the circular-cutout failure)
- editorial conciseness pass over new-work.md, visualize.md, and both
agent files: tighter sentences, no dropped rules, all rule markers and
mechanical tokens preserved
Assisted-by: Claude Code
* fix: define the ship disposition in new-work's action paragraph
Copilot review finding: the paragraph claimed exactly four disposition
words but defined only recapture, rebuild, and fix.
Assisted-by: Claude Code
* fix: rebuild returns get a full review; recapture return shape in preamble
Cursor Bugbot findings:
- a return following a rebuild directive is now a fresh full review on
both sides of the contract, never a verdict pass, so a wholesale
rebuild cannot earn a scoped ship on the directive alone
- the turn-ceiling preamble now names the recapture return shape instead
of contradicting it with "the five sections"
Assisted-by: Claude Code
* fix: absent required captures fail the evidence check
Greptile finding: a packet with no desktop.png/mobile.png (or missing
native device-class captures) routed to the missing-input notice and
could still reach ship. A required capture that is absent now fails
check 0 exactly like a malformed one and forces recapture; the
missing-input allowance in the preamble excludes captures.
Assisted-by: Claude Code
* fix: user-viewport capture is a required, named input to the review
Greptile finding: the evidence gate hard-coded web requirements to
desktop.png and mobile.png, so a reported user viewport could join the
inspected set and still ship uncaptured. The parent now saves it as
user-<width>.png and names every inspected viewport required in the
packet; check 0's required set includes every brief-named capture.
Assisted-by: Claude Code
* Take every themed list in an entry, not the first one
A long changelog entry is grouped into themed lists behind cf-group labels, and
the extractor stopped at the first one. skill-v4.0.0 shipped 6 of its 19
bullets that way, and v4.1.0 would have shipped 6 of 21.
This is the same shape as the bounded-search fix one commit earlier: the
extractor treated "found a list" as "found the notes". It now collects every
cf-items list inside the entry's own article and joins them, so grouping an
entry for readability cannot silently truncate its release notes.
Written with AI assistance (Claude Code).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Name the malformed case separately
An entry that opens a cf-items list and never closes it inside its article
matched nothing, and the failure said the entry had no list of its own. That is
a different repair, and the message sent you looking for the wrong thing.
Written with AI assistance (Claude Code).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Release: skill v4.1.0, CLI v3.6.0, extension v1.3.2
Skill 4.1.0: the build path becomes a recorded setting with a per-round
toggle, the direction round routes challengers by verdict, surface rounds deal
structure, and critique delivers its report and its close.
CLI 3.6.0: contrast findings stop assuming white when the ground cannot be
read, waivers scope to the element that carries them, and Hermes Agent and
Antigravity install natively.
Extension 1.3.2: no source change, but the bundled engine is rebuilt at
release, so the same 59 rules ship with the false-positive work behind them.
Chrome and Firefox from the one manifest.
Harness output regenerated with build:release, which is what the version
validator checks against the manifests.
Written with AI assistance (Claude Code).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Bound release-note extraction to the entry it names
Every v4.0.x skill release shipped v4.0.0's notes. The extractor took the
first `<ul class="cf-items">` after the version header with no upper bound, and
the v4.0.1 through v4.0.4 entries wrote their bullets in a `cf-entry-list`
instead, so the search ran past all four and landed in v4.0.0. Nothing failed,
because finding a list somewhere was treated as success.
The search now stops at the entry's own `</article>` and fails with the reason
when the entry has no readable list, which is the case the old code silently
published its way through. The changelog side is fixed in impeccable-site,
where those five entries now use `cf-items` like the other 46: `cf-entry-list`
also had no CSS at all, so their bullets were rendering unstyled on the
changelog page.
Written with AI assistance (Claude Code).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>