Commit Graph
142 Commits
Author SHA1 Message Date
Paul BakausandClaude Code 44a25fa241 Release: publish the npm platform packages in one command
bun run release:platform-packages downloads each engine-v<ENGINE_VERSION>
binary with its .sha256 sidecar (required; nothing unverified is
published), stages the package from cli/platform-packages/<target> with
the version stamped, the executable at bin/ and the repo LICENSE, and
runs npm publish --access public. Targets already on the registry are
skipped so a re-run resumes after a partial failure. Preconditions:
package.json pins equal ENGINE_VERSION and npm is logged in.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vau2X53xGTjjTCXWMVBoNY
2026-09-04 10:12:17 -07:00
Paul BakausandClaude Code a91c226b2b Merge origin/main into rust-swap (#718 live-server leak guard)
Brings the leak guard from #718 onto the branch and makes its guarantee hold
for the Rust engine instead of the Node scripts it was written against.

Conflicts and how each was resolved:

- tests/live-poll-stream.test.mjs, tests/live-server.test.mjs,
  tests/live-target-context.test.mjs (modify/delete): kept deleted. They drove
  skill/scripts/live-server.mjs, which does not exist here; the verb behavior
  they covered is the oracle's job now. Their entries came out of
  test-suites.mjs along with the rest of main's live list, which is Node-script
  coverage this branch already retired.
- scripts/test-suites.mjs: took main's two new entries that still apply,
  process-group.test.mjs into core and live-server-leak.test.mjs into live, plus
  the infra trigger patterns for the three new scripts/lib modules. Dropped
  main's pin.test.mjs (no such file here).
- package.json: kept test:cleanup, dropped test:cli-e2e (no cli-e2e suite here).
- scripts/run-tests.mjs: rewritten to hold both sides rather than picking one.
  From #718: the createGroupShutdown state machine, the per-suite run-id marker
  env, the post-suite leak check, and --cleanup. From 47f18713: the per-command
  wall-clock cap with its per-suite wallClockMs override and
  IMPECCABLE_TEST_WALL_CLOCK_MS, plus the killed-by-signal report. The two agree
  on the detached process group, so they compose: the cap SIGKILLs that group
  when a command wedges, the shutdown handler ends it on a signal, and both now
  sweep for leaked servers before exiting. #718's handler replaces the old raw
  signal forwarding, which sent one signal and never escalated.
- tests/live-e2e/session.mjs: kept both sides. The binary-driven boot
  (runEngineSync, requireEngineBin, engineEnv) stands, with armLiveServerReaper
  at module scope and trackServerChild around the fixture dev server.

Ported to the rest of the branch:

- tests/oracle/lib.mjs arms the reaper and tracks the daemon child. Its daemon
  steps spawn live-server detached, so a SIGKILLed oracle run used to strand
  one; buildInvocation already inherits process.env, so the marker reaches it.
- tests/live-server-leak.test.mjs now boots the engine binary through
  tests/lib/engine-bin.mjs and skips cleanly without one.

No crate change was needed. The daemon spawn does env_clear().envs(env) against
Io::stdio()'s env, which is std::env::vars(), so the detached Rust process
carries the parent environment and the markers reach it. Verified against a
real --background daemon: found by run id and by repo marker, not found by an
adjacent checkout's marker. CLAUDE.md now says so, since narrowing that env
would make the guard silently blind.

Verified with a fresh cargo build --release -p impeccable:

- IMPECCABLE_BIN=... bun run test green end to end: core 90, oracle 1 (zero
  unreviewed differences), detector 1, live 159 (157 pass, 2 skipped),
  framework 186, plugin-e2e 4. Zero servers left.
- SIGKILL repro against impeccable live-server --background: 1 daemon up, 0
  after with the reaper, 1 surviving with parent pid 1 under
  IMPECCABLE_NO_TEST_REAPER=1. bun run test:cleanup then kills exactly that one.
- The leak test fails under IMPECCABLE_NO_TEST_REAPER=1 and passes with it.
- IMPECCABLE_E2E_ONLY=vite8-react-plain bun run test:live-e2e 4/4.
- bun run build green.

AI assistance: prepared by Claude Code under pbakaus's direction.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vau2X53xGTjjTCXWMVBoNY
2026-09-03 19:34:16 -07:00
4c5243fcd4 Tests: stop the harness leaking live-server processes (#718)
* Tests: stop the harness leaking live-server processes

Nothing owned a live server past the exit paths JavaScript can observe. The
live unit tests spawn the server as a direct child and stop it with an HTTP
/stop plus proc.kill() inside an after() hook; the e2e session and the
target-context tests boot it through `live-server --background` / live.mjs,
which spawns a detached, unref'd daemon that only the `stop` verb ever ends.
A POSIX child does not die with its parent, and a detached daemon is orphaned
to pid 1 from birth, so any exit that skipped teardown (a node:test timeout, a
SIGKILL of the runner, a Ctrl-C, an assertion that threw before the hook) left
the server listening on a fixed live-suite port for good. scripts/run-tests.mjs
did not compensate: it used blocking spawnSync, so no signal handler could run;
it left suite commands in its own process group with nothing that could kill
that group; and it never checked afterwards whether anything survived. Days of
local runs accumulated 197 orphans on one machine, the oldest four days old,
until `bun run test:live` could not claim its ports.

The fix is structural rather than a cleanup sweep bolted on the end, and it is
deliberately implementation-agnostic so it holds for the Node scripts here and
for the Rust `impeccable live-server` on rust-swap:

- tests/lib/live-servers.mjs. armLiveServerReaper(), called once at module
  scope by every test file that starts a server, stamps the process env with a
  unique marker, installs exit and signal handlers, and spawns a detached
  reaper holding a pipe to the process. SIGKILL the process and the pipe closes,
  the reaper wakes on EOF and kills the servers carrying that marker. That is
  the one case no in-process cleanup can reach. trackServerChild() also
  registers direct children (live servers and fixture dev servers) so the
  ordinary exits are a cheap kill by handle.
- scripts/lib/live-server-processes.mjs. The scan and kill primitives, shared
  by the reaper and the runner. Processes are matched by the environment marker
  the harness exported, never by name or port, so a sweep can only ever reach a
  server this repo's tests started.
- scripts/run-tests.mjs. Each suite command now runs as its own process-group
  leader with SIGINT/SIGTERM/SIGHUP forwarded to the group, and after every
  suite the runner checks for live servers carrying that suite's run id. A
  survivor is killed and fails the run, so the next leak surfaces in the run
  that caused it instead of on a laptop days later. IMPECCABLE_SKIP_LEAK_CHECK=1
  bypasses it. `bun run test:cleanup` sweeps leftovers from earlier runs.
- tests/live-server-leak.test.mjs pins the guarantee: it boots a real server
  under a process it then SIGKILLs, and fails if the server outlives it. With
  IMPECCABLE_NO_TEST_REAPER=1 the test fails, which is what makes it a
  regression test rather than a tautology.

Verified: bun run test:live green with zero survivors; scoped live-e2e
(vite8-react-plain) matches pristine main test for test; the SIGKILL repro goes
from 2 orphans to 0; SIGINT and SIGKILL of the runner itself both leave nothing
behind; bun run build green.

Fixes #717

AI assistance: prepared by Claude Code under pbakaus's direction.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vau2X53xGTjjTCXWMVBoNY

* Review fixes: scope the sweep to whole env entries only

Five review findings on #718, all in the matching layer that decides which
processes a sweep may touch.

The repository-path fallback is gone (Greptile P1). `bun run test:cleanup`
passed REPO_ROOT to findLiveServers, which then also matched any live-server
command line under the checkout, marker or not. A developer running
`impeccable live` in this repo has exactly that command line, so the cleanup
could have killed their own session. The PR promised matching on the exported
environment marker and nothing else; now it does. The cost is that a server
from a run predating the marker is no longer found and has to be killed by
hand, which is the right trade.

Environment entries are compared whole on macOS and BSD (Greptile P1). `ps -E`
flattens the environment into the command column, and that line was searched
with a plain substring test, so IMPECCABLE_TEST_REPO=/work/impeccable also
matched /work/impeccable-copy and one checkout's cleanup could reach a
neighbouring checkout's servers. envLineHasEntry() now requires the marker to
start an entry (line start or whitespace) and to end one (line end, or
whitespace followed by the next KEY=), which is the same whole-entry
comparison the Linux /proc branch already did. Six unit tests cover it,
including the adjacent-path negative case, and a live probe against real
`ps -E` output confirms an exact repo matches while /work/impeccable-copy and
a run-id prefix do not.

The SIGKILL regression test now skips on win32 with a stated reason (Copilot).
The reaper is a POSIX mechanism and armLiveServerReaper() does not arm it
there, so the test asserted a guarantee Windows does not make yet.

Signal exits use the shell convention 128 + signum in both the runner and the
test helper (Copilot, two threads). SIGHUP returned 143; it is 129. Read from
os.constants.signals rather than a hand-written table.

Verified: leak test 7/7 (2 guard, 5 matcher); bun run test:live 895 tests, 0
fail, 0 survivors; scoped live-e2e (vite8-react-plain) 3 pass / 1 fail,
matching pristine main; SIGKILL repro 3 servers up, 0 after; bun run build
green.

AI assistance: prepared by Claude Code under pbakaus's direction.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vau2X53xGTjjTCXWMVBoNY

* Review fix: make marker values opaque so the matcher has no ambiguous case

Greptile's follow-up P1 on the parser was right, and the parser was the wrong
place to answer it. envLineHasEntry ended an entry at "whitespace followed by
the next KEY=", so a checkout path that extended another one with whitespace
plus a KEY=-shaped token still defeated it, which is exactly the ambiguity the
docblock admitted to. A format that cannot be parsed unambiguously should not
be handed ambiguous input.

So the fix is at the source: no marker value is a path any more. IMPECCABLE_TEST_REPO
now carries repoMarker(), the first 16 hex characters of the sha256 of the
checkout's real path, and the runner and the cleanup command both compute it
the same way from REPO_ROOT. Two checkouts whose paths share a prefix get
unrelated hashes, so a substring cannot arise in the first place, and every
spelling of one checkout (trailing slash, `.` segment, symlink, /private
prefix) resolves to one marker. The run id is now repoMarker plus 8 random
bytes of hex, and the process id p<pid> plus the same, both from a
whitespace-free alphabet.

With every value fixed-alphabet, envLineHasEntry needs only "starts an entry
and ends at whitespace or line end". The KEY= lookahead is gone and so is the
documented unresolvable case. assertMarkerValue keeps the invariant honest: it
refuses any value outside [A-Za-z0-9_-] with a message that says to hash it,
so a future caller that passes a path gets a loud error instead of a silent
mismatch. The readable path is still available for a human reading `ps -E`
output, exported separately as IMPECCABLE_TEST_REPO_PATH, which nothing
matches on and the docblock says so.

Matcher tests: the space-in-value case is gone, since that value can no longer
exist. Added a strict-prefix case (a longer hash-shaped value starting with the
marker), an adjacent-checkout case asserting the two hashes do not even share a
prefix, a symlink/trailing-slash case against real directories, an alphabet
check on all three generators, and one asserting assertMarkerValue throws.

Verified: leak test 10/10; bun run test:live 898 tests, 0 fail, 0 survivors;
scoped live-e2e (vite8-react-plain) 3 pass / 1 fail, matching pristine main;
SIGKILL repro 1 server up, 0 after; bun run build green. A probe against real
`ps -E` output with a hashed marker: this checkout 1 match, its trailing-slash
spelling 1, an adjacent checkout 0, exact run id 1, a run-id prefix 0.

AI assistance: prepared by Claude Code under pbakaus's direction.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vau2X53xGTjjTCXWMVBoNY

* Review fixes: async group shutdown, and a Windows-safe symlink test

Two Cursor Bugbot findings, both real.

killCurrentGroup busy-waited on alive(child.pid) after sending SIGTERM, which
could never work. A dead child stays a zombie until its parent reaps it, the
parent here is the runner, and the runner reaps through libuv when the event
loop runs. The spin blocked the very loop that would have done the reaping and
then read the unreaped zombie as alive, so every SIGINT, SIGTERM and SIGHUP
burned the full 2s grace and ended in a needless SIGKILL. There is no waitpid
from JavaScript that sees through this, so the wait is now asynchronous and
keyed on the child's own exit event. The logic moved to
scripts/lib/process-group.mjs: trackChildExit exposes the exit as a flag and a
promise, stopGroup races that promise against the grace period and escalates to
SIGKILL only if it loses, and killGroupSync stays synchronous for
process.on('exit'), where nothing can be awaited, so it sends SIGTERM then
SIGKILL without pretending to wait. A second Ctrl-C now skips the grace period
entirely rather than queueing behind it.

Measured on a real SIGINT to a running live suite: 2027ms before, 34ms after.
tests/process-group.test.mjs pins both halves, including the escalation path
against a child that traps SIGTERM, which is not otherwise reachable from a
registered suite.

The repoMarker symlink test called symlinkSync with no type, which throws EPERM
on Windows without Developer Mode. It now passes 'junction' there and 'dir'
elsewhere, the same shape tests/concept-seed.test.mjs uses, and the
trailing-slash and dot-segment cases split into their own test so they keep
running on every platform regardless.

Merged origin/main (through #716) to re-level the branch.

Verified: leak and process-group tests 16/16; bun run test:live 900 tests, 0
fail, 0 survivors; scoped live-e2e (vite8-react-plain) now 4/4, with the
orphaned-session test that #716 fixed passing in 7.2s; bun run build green.

AI assistance: prepared by Claude Code under pbakaus's direction.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vau2X53xGTjjTCXWMVBoNY

* Review fix: a second Ctrl-C must reach the group the first one is stopping

Cursor Bugbot caught a bug I introduced with the async shutdown, and it is the
same class of leak this PR exists to close. The signal handler cleared
currentChild before awaiting stopGroup, so a second Ctrl-C read a null handle:
killGroupSync did nothing, process.exit walked away from the SIGKILL escalation
still in flight, and because the suite is spawned detached it kept running
after the runner was gone. Impatience with a stuck suite produced exactly the
orphan the change is supposed to prevent.

The shutdown state machine moved into scripts/lib/process-group.mjs as
createGroupShutdown, which holds the group in `stopping` for as long as it is
being ended rather than dropping the only reference to it. A second signal
kills that handle and leaves; process.on('exit') looks at `current` or
`stopping`, so the last-resort path reaches a group mid-shutdown too. The
runner keeps no shutdown state of its own now, which is what made the bug
possible to write in the first place.

The extraction is what makes it testable: `exit` is injectable, so
tests/process-group.test.mjs can drive two signals at a stubborn child that
traps SIGTERM and assert the group dies in under 2s against a 30s grace. Point
that test at the old logic (killGroupSync on the cleared reference) and it
hangs out the full grace and fails, which is the check that it pins something
real. Five cases in all, including the exit-handler path and the no-child case.

Verified: process-group 10/10, live-server-leak 11/11; real double SIGINT to a
running live suite exits in 24ms with zero group members and zero servers left;
bun run test:live 900 tests, 0 fail, 0 survivors; scoped live-e2e
(vite8-react-plain) 4/4; bun run build green.

The core suite wedged twice locally in tests/build-phase.test.mjs, the
pre-existing unbounded-spawnSync hang noted in the PR description that
rust-swap's 47f18713 fixes. Unrelated to this change: CI is green on both Node
versions, and process-group.test.mjs passes inside that batch.

AI assistance: prepared by Claude Code under pbakaus's direction.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vau2X53xGTjjTCXWMVBoNY

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 19:21:30 -07:00
Paul BakausandClaude Fable 5.1 4369ad538d Open the detector: the rule crates join the workspace, the C-ABI goes away
The detector is open source. The rules it ships were already public in this
repo's git history and in every npm tarball of the JS engine, so a closed
binary bought nothing it could keep; the moat is the service (the catalog,
the labs, the review pipeline), not the check functions. Keeping them behind
a prebuilt archive cost a C-ABI, an exact toolchain pin, a build-time
download, a second release to order ahead of every engine release, and a
serde layer that had to serve two encodings.

Deleted
- crates/core/src/ffi.rs, crates/core/build.rs, crates/core/tests/boundary.rs
  and the shim modules under src/checks and src/browser.
- crates/foundation/src/boundary.rs and the postcard dependency.
- DETECTOR_VERSION, scripts/check-detector-release.mjs and its test, the
  check:detector-release script, the detector gate and
  IMPECCABLE_SKIP_DETECTOR_CHECK in scripts/release.mjs.
- scripts/lib/detector-bundle.mjs and tests/detector-bundle.test.mjs (the
  vendoring path for the closed browser bundle).
- scripts/build-browser-detector.js and the build:browser script (a stub
  since the JS engine left the tree).
- xtask's detector-archive subcommand and its public-repo lookup.

Came back
- crates/core is now the rule logic itself: every check_* / scan_*, the
  browser adapters, the visual-contrast decisions. It re-exports foundation
  as before, so no consumer changed. Its vectors dispatcher is the union of
  both id tables again, and tests/vectors.rs replays the frozen vectors
  straight through it.
- crates/wasm and crates/xtask join the workspace. cargo xtask bundle builds
  the in-page bundle from browser-bundle/ plus the wasm core, writes
  dist/, refreshes the tracked crates/live/assets/detect-antipatterns-
  browser.js, and writes extension/detector/. bun run build:extension runs
  it instead of downloading.
- crates/live/assets/detect-antipatterns-browser.js is tracked again; live
  mode embeds it and serves it as /detect.js.
- Serde is back to plain derives: no is_human_readable branch in
  js::json_number, derived Serialize for Rgba and BrowserFinding with their
  skip_serializing_if attributes.
- profile.release has lto = "fat" again; rust-toolchain.toml is plain
  stable plus the wasm32 target. The rust, rust-windows and oracle CI jobs
  lose continue-on-error and can be required.

Verified
- cargo build --workspace --all-targets: clean, no warnings.
- cargo test --workspace: 346 pass, 0 fail (the 8 boundary tests are gone
  with the boundary).
- cargo build -p impeccable-wasm --target wasm32-unknown-unknown --release: ok.
- cargo xtask bundle && cargo xtask bundle --check: reproducible; the
  regenerated bundle is committed (it differs from the archived one, which
  was built with a pinned rustc and lto = false).
- cargo build --release -p impeccable: no linker warnings, 12.5 MB (the
  same source at lto = false is 13.1 MB).
- oracle: 795 pass, 0 fail, 0 accepted deltas, 0 missing goldens.
- bun run build, bun run build:extension, web-ext lint (0 errors,
  8 warnings), bun run test: 363 + 80 + 1 + 1 + 133 + 180 + 4 pass, 0 fail.
- impeccable detect --no-config --json tests/fixtures/antipatterns: 128.7 ms
  median of 5.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vau2X53xGTjjTCXWMVBoNY
2026-09-03 09:11:33 -07:00
Paul BakausandClaude Fable 5.1 e355ebf714 reorg: public plumbing for the in-repo Rust workspace and the two-release flow
The engine binaries move from the impeccable-dist channel to this repo's own
GitHub Releases (tag engine-v<ENGINE_VERSION>), and the closed detector the
engine links arrives as detector-v<DETECTOR_VERSION> releases on the same
repo. This commit wires the public side for that; the crates themselves land
in the next commit.

- Launcher (sh + cmd), npm shim, fetch-engine and check-engine-release now
  download from github.com/pbakaus/impeccable/releases/download/engine-v<X>/.
- release.mjs gains `engine`: verifies ENGINE_VERSION against the platform
  package pins and the detector release, tags, pushes; release-engine.yml
  builds the five targets and publishes. check-detector-release.mjs is the
  matching release-order guard (with tests).
- Root Cargo.toml (workspace, lto = false with the reason), rust-toolchain.toml
  (exact pin), DETECTOR_VERSION, /target ignored.
- CI: rust + rust-windows jobs and an oracle job that replays the goldens
  against a source build, warn-only until the first detector release exists;
  ci-test-plan exposes a `rust` output.
- docs/ENGINE.md (the crate map and the closed-detector mechanism) and the
  CLAUDE.md engine, release-order and rules sections.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vau2X53xGTjjTCXWMVBoNY
2026-09-01 14:05:39 -07:00
Paul Bakaus b6a34de55a Tests: gate behavior on the oracle and the engine binary
Unit tests of the deleted Node scripts and the JS detector are removed;
their behavior is pinned by tests/oracle goldens (frozen JS behavior plus
reviewed deltas) and the engine's own tests. tests/oracle.test.mjs replays
the corpus against the binary (IMPECCABLE_BIN or skill/scripts/bin/<target>/,
via tests/lib/engine-bin.mjs) and skips cleanly without one; the framework
fixture sweep drives live-inject, live-wrap, and detect-csp through the
binary the same way. record.mjs learns --bin. The function-level vectors
under tests/oracle/vectors/calls are committed as the frozen snapshot they
can no longer be regenerated from. Suites: core trimmed to build and
transformer tests, oracle added to the default run, detector/live reduced to
packaging and reference checks, the live-e2e helper tests move to the opt-in
live-e2e lane pending its retarget, cli-remote-e2e is an empty placeholder.

Prepared with AI assistance (Claude Code).
2026-08-31 19:59:20 -07:00
Paul Bakaus 6dd16d21ef CLI: turn the impeccable npm package into a platform-binary shim
cli/engine, cli/lib, and cli/bin/commands are gone; their behavior lives in
the engine binary. cli/bin/cli.js now resolves the binary from IMPECCABLE_BIN,
the @impeccable/cli-<os>-<arch> optional dependency (templates under
cli/platform-packages/, published by the engine release), the
~/.impeccable/bin/<version>/ cache, or a checksum-verified download, and
execs it. package.json drops the engine dependencies and the library
exports; puppeteer moves to devDependencies for the icon scripts.
README.npm.md describes the shim.

Prepared with AI assistance (Claude Code).
2026-08-31 19:57:42 -07:00
Paul Bakaus 11a1ea64a6 Build: ship the launcher instead of bundling the JS engine
readSourceFiles no longer copies cli/engine into the skill; the scripts
payload is the launcher (executable bit preserved through dist, plugin/, and
universal.zip), impeccable.cmd, VERSION (synced from ENGINE_VERSION on every
build), the page JS, and command-metadata.json. Hook manifests call
`<scripts>/impeccable hook` behind an existence guard (Codex adds a
commandWindows sibling calling impeccable.cmd; Cursor runs hook-before-edit;
GitHub keeps the git rev-parse form; Grok mirrors Claude); the Node probe and
systemMessage notice are gone. build:release fetches the pinned engine for
every target (lenient) and stages bin/<os-arch>/ into the dist skill copies
after root harness dirs and plugin/ were synced, so git-delivered trees stay
launcher-only. The detection-rule count check reads the vendored
extension/detector/antipatterns.json and is skipped when absent.
build:browser is a stub; the codex prefix rewrite leaves
`{{scripts_path}}/impeccable` alone.

Prepared with AI assistance (Claude Code).
2026-08-31 19:57:32 -07:00
Paul Bakaus dac3f77d89 Scripts dir: replace the Node scripts with the impeccable launcher
skill/scripts keeps command-metadata.json and the page JS; every .mjs entry
point, lib/, and live/ are gone (the binary owns those verbs). Adds the POSIX
launcher, impeccable.cmd, VERSION (copied from the new root ENGINE_VERSION),
scripts/fetch-engine.mjs (bun run fetch:engine) to pull the pinned binary
into skill/scripts/bin/<os>-<arch>/, and gitignores that bin dir.

Prepared with AI assistance (Claude Code).
2026-08-31 19:57:32 -07:00
dependabot[bot]andGitHub 3a37bcb7d3 Bump the Bun dependency group with 7 updates (#683)
Update marked, the coordinated provider packages, Anthropic SDKs, and Puppeteer. Keep ai at the known-good 7.0.69 until provider-backed behavior validation can confirm the post-7.0.70 tool-loop path.

AI-assisted dependency maintenance performed by Codex.
2026-08-31 16:00:51 -04:00
63b04e2530 Release: CLI v3.6.1, extension v1.3.3
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 11:02:54 +05:00
dependabot[bot]andGitHub 78b50aa416 Build(deps): update the Bun dependency group (#650)
Update the grouped Bun dependencies while holding ai at 7.0.69 to avoid the automatic tool-execution behavior regression introduced in 7.0.70.

Prepared and validated with AI assistance.
2026-08-24 15:15:01 -04:00
2c33196c51 Release: skill v4.1.0, CLI v3.6.0, extension v1.3.2 (#584)
* 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>
2026-08-14 00:31:18 -04:00
6d2af3f800 Guard the plugin loader contract that PR #494 exposed (#499)
* test: guard the plugin loader contract that PR #494 exposed

The agents manifest key shipped for months and silently loaded zero of
the four subagents; no validator looked at the generated plugin
manifest's shape and claude plugin validate never checks it. Three
layers now do:

- scripts/lib/validate-plugin-manifest.js pins the verified loader
  contract (KNOWN_LOADER_KEYS allowlist, no agents key, trailing-slash
  skills path from issue #86, every skill/agents/*.md shipped in
  plugin/agents/), unit-tested in tests/validate-plugin-manifest.test.js
  including a check of the real committed subtree.
- The same check gates bun run build next to the version-drift guard.
- tests/plugin-e2e.test.mjs installs the committed ./plugin subtree into
  a real Claude Code (sandboxed via CLAUDE_CONFIG_DIR in a temp dir) and
  asserts the component inventory: skill parses, all agents visible,
  hooks discovered. In the default suite; runs in about a second and
  skips cleanly when the claude CLI is absent, so CI is unaffected.

All three failed against the pre-#494 tree for the shipped reason
(Agents 0 of 4) and pass against current main.

AI-assisted via Claude Code under maintainer direction.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* fix: address PR review bot findings

- Copilot: guard collectPluginManifestFindings against valid JSON that is
  not an object (null, string, number, array) so a broken manifest is a
  finding instead of a build crash; unit test added
- Copilot: update the plugin-e2e header comment, the suite is in the
  default lineup rather than opt-in

AI-assisted via Claude Code under maintainer direction.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* fix: harden plugin E2E sandbox isolation

Bugbot: create the sandbox CLAUDE_CONFIG_DIR up front and redirect HOME
and USERPROFILE into the temp workDir too, so a CLI code path that
derives config or cache locations from the home directory instead of
CLAUDE_CONFIG_DIR still cannot touch the developer's real Claude config
when the default suite runs.

AI-assisted via Claude Code under maintainer direction.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* fix: agent parity check mirrors the build's emit rules

Bugbot: the shipped filename is `${claude-name || name}.md` and a
providers: list may exclude claude-code, so comparing raw source
basenames could fail the build on a renamed or provider-scoped agent
with a build:release hint that cannot fix it. The validator now derives
expected filenames the same way the transformer factory does (shared
parseFrontmatter, same providers gate) with unit coverage for renames,
name overrides, and provider-scoped agents.

AI-assisted via Claude Code under maintainer direction.

Co-Authored-By: Claude Code <noreply@anthropic.com>

* fix: run the plugin E2E through a shell on Windows

Bugbot: the claude CLI is a .cmd shim on Windows and Node refuses to
spawn those via execFile without a shell, so the availability probe
always failed and the suite silently skipped there. Windows now invokes
through a shell with every argument double-quoted (temp paths routinely
contain spaces); the POSIX path is unchanged.

AI-assisted via Claude Code under maintainer direction.

Co-Authored-By: Claude Code <noreply@anthropic.com>

---------

Co-authored-by: Claude Code <noreply@anthropic.com>
2026-08-03 13:13:37 -07:00
dependabot[bot]andGitHub 5dfeba6d3e Bump @babel/parser to 8.0.4 and raise Node floor (#430)
Upgrade @babel/parser from 7.29.7 to 8.0.4 and raise the repository Node 22 minimum from 22.12.0 to 22.18.0 across package metadata, CI, and npm documentation.

No parser API migration was required. Validated with the full local suite and refreshed GitHub CI on Node 22.18.0 and Node 24.

Prepared and validated with AI assistance from OpenAI Codex under maintainer instructions.
2026-08-03 10:46:55 -07:00
Paul BakausandClaude Fable 5 9a949fb543 Release: skill 4.0.4, CLI 3.5.0, extension 1.3.1
Version bumps for all three components plus the build:release sync of
the tracked harness dirs and the plugin subtree at 4.0.4, rebased onto
the composition-axes work so the release carries both threads.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 17:50:40 -07:00
Paul BakausandGitHub 5f4b58d06d Merge pull request #433 from pbakaus/live-v2-rewrite
Live v2: root manifest, mount-ack protocol, AST scaffolder, mechanical accept
2026-07-29 13:12:23 -07:00
Paul BakausandClaude Fable 5 68b1129634 Release bumps: skill 4.0.3, CLI 3.4.0, extension 1.3.0, with synced output
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 19:17:09 -07:00
Paul Bakaus 2d66c9acf1 Merge origin/main into live-v2-rewrite
Resolves bun.lock (regenerated) and package.json (both sides' devDependency
changes kept: main's @babel/parser bump, this branch's svelte addition).
2026-07-27 15:22:51 -07:00
Paul BakausandClaude Code 17dabf4b7e Live v2: root manifest, mount-ack protocol, AST scaffolder, mechanical accept
A ground-up hardening of live mode, driven by a production session in a
nested-app monorepo that hit six distinct failure classes. Full design
rationale in docs/LIVE-REWRITE-PLAN.md; every Codex-reported failure now
has a mechanical fix and a regression test.

Roots: live/roots.mjs resolves appRoot/repoRoot/contextRoot once at boot
(keyed on dev-server configs, not monorepo brand markers), persists a
manifest, and every live CLI re-anchors onto it at startup, so a helper
run from the wrong directory can no longer fork session state. Context
files are discovered upward to the git root.

Render truth: variant_mounted / variant_mount_failed events give the
journal per-variant mount state; failures reach the agent's poll queue,
raise a persistent error card with Retry (no more localStorage wipe), and
an attach probe names root/dev-server mismatches explicitly. The browser
rehydrates from the server when localStorage is gone.

Svelte: the scaffolder now parses with the app's own svelte 5 compiler.
Control flow survives (an each collection crosses the contract as one
structured prop), keyed each blocks hydrate synthetic keys, and anything
a detached preview cannot support falls back to source-preview instead of
shipping a wrong scaffold. Preview modules live in per-publish revision
directories, defeating stale transform caches.

Accept: CSS is reconciled, not appended. Matching selectors are replaced,
params bake from params.json kinds, the compiler's unused-selector pass
prunes superseded rules (pre-existing dead rules protected), a selector-
loss postcondition refuses any write that would drop hand-written rules,
and live-complete refuses to finish while live plumbing remains in source.

Also: framework registry (live/frameworks/) with a crash-safe injection
journal, session-store snapshot caching with read-only reads, protocol
enum consolidation, steer Send button, honest DESIGN-panel empty states.

Testing: new unit suites (roots, AST scaffolder, accept CSS, accept
pipeline, framework conformance); e2e now fails on preview-tree 404s,
proves computed-style mount for every variant, drives the Tune panel
through baked params, and injects failures (broken mounts, republish,
storage loss). New runtime fixtures: monorepo-nested-vite (repo root !=
app root) and vite8-sveltekit-stateful (each blocks + state). Nightly
full-matrix cron. An independent adversarial review pass preceded this
commit; its blocker and major findings are fixed and regression-tested.

This work was produced with AI assistance (Claude Code).

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-07-27 15:09:40 -07:00
dependabot[bot]andGitHub e0144ed585 Bump the bun-minor-and-patch group with 9 updates (#429)
Prepared with AI assistance from OpenAI Codex under maintainer automation instructions.
2026-07-27 10:24:55 -07:00
Paul BakausandClaude Fable 5 3e233d22d7 Release prep: CLI v3.3.1
Bump the npm package and regenerate the browser detector bundle with
the advisory tier, entity-aware em-dash counting, and the
undersized-ui-text rule.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 13:13:40 -07:00
Paul BakausandClaude Fable 5 6ece0e588f Add deterministic new-work interactive smoke suite
A cheap, LLM-free E2E tier for the interactive parts of new-work, mirroring
the two-layer live-e2e pattern (deterministic now, opt-in LLM tier later).

- generate-image.mjs: IMPECCABLE_IMAGE_GEN_FAKE=1 writes a deterministic
  offline image (SVG with wrapped prompt + SYNTHETIC COMP label, or a valid
  palette-stripe PNG carrying the prompt/marker in a tEXt chunk). Same CLI
  contract, no key, no network, $0.00 cost line.
- tests/new-work-e2e/user-bot.mjs: scripted user bot (module + CLI) that
  resolves the serve-question daemon from the workspace and drives the real
  page via Playwright (pick, re-roll + steer, canon, tab close).
- tests/new-work-e2e.test.mjs: node --test coverage of the serve-question
  cycles (pick + CHOSEN CARD, re-roll + --update re-deal, canon + CANON
  CHOSEN, tab-close exit-4, text-only card) plus fake image determinism.
- Registered as the opt-in new-work-e2e suite; added test:new-work-e2e.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 12:23:07 -07:00
Paul BakausandClaude Fable 5 40ba97db20 Pin @babel/parser so live-mode JSX syntax checks stay enforced
The v4 repo split dropped astro/wrangler from devDependencies, which
also removed the only (transitive) source of @babel/parser. The
post-apply syntax check in live-copy-edit-agent.mjs requires it to flag
invalid JSX/TSX; without it the check silently degrades to a warning and
tests/live-copy-edit-agent.test.mjs "flags invalid JSX syntax" fails on a
fresh CI install. Production behavior is unchanged: the require stays an
optional, graceful-degrade path for end users, and @babel/parser was
never in the published package's runtime dependencies. Declaring it as a
devDependency just makes the repo's own test environment deterministic.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 20:51:55 -07:00
Paul BakausandClaude Fable 5 311c30f11f Release prep: skill v4.0.0, CLI v3.3.0
Bump skill to 4.0.0 (plugin.json + marketplace.json) and the CLI to
3.3.0 (package.json), then run build:release to regenerate the plugin
subtree and all provider harness output to the new versions.

Skill 4.0.0 ships external-dice direction assignment, the reviewed
world catalog dealt through the roll API with rendered quality-bar
cards, the in-browser serve-question decision page, visualize-before-
build, the rebuilt new-work flow, and the 58-rule detector under hook
enforcement. CLI 3.3.0 grows the deterministic detector to 58 rules
and adds config-declared context roots, per-file rule scoping, and
--target resolution for nested products.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 18:53:45 -07:00
Paul BakausandClaude d7d10277d1 Merge main into oneshot-v4, keeping the service layer split out
main still carries the site, so every `site/` path resolves to deleted.
`tests/docs-integrity.test.js` goes with it (it imports the site's demo
renderer), and `package.json` keeps main's `@anthropic-ai/sdk` bump while
dropping `@google/genai` and `@paper-design/shaders`, which nothing in the
product layer imports.

Real code merges:

- hook-lib: main's #391 cache fix (sync the remembered set to the live
  scan so fixed findings stop being named and a reintroduced one fires
  again) now runs on the immediate tier rather than the whole filtered
  set. Remembering a deferred finding the per-edit pass never reported
  would let the Stop deep pass dedupe it away. main's `maxFileBytes`
  ceiling, `cleanAcked` once-per-file ack, and template-extensions
  re-export all land alongside the tiering work.
- live-browser: main's `hasParams` gate on the Tune badge, keeping this
  branch's `C.ink` badge text so it stays legible on kinpaku gold.
- detect-text: both the block-level codex-grid-background scan and main's
  inset-stripe CSS check.
- test-suites: union of both trigger sets and file lists, minus the
  site-only entries (`shiki-theme`, `docs-integrity`).
- Two hook tests moved off deferred-tier rules (`overused-font`,
  `side-tab`) onto immediate-tier ones. They assert cache bookkeeping,
  which the per-edit pass only reaches for the immediate tier.

Also drops the site waivers from `.impeccable/config.json` and stops
`build:browser` recreating a stray `site/` tree just to write a bundle
the other repo builds itself.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-21 01:45:42 -07:00
Paul BakausandClaude Fable 5 90f9eeb99b Split service layer into private impeccable-site repo
The public repo keeps the OSS promise surface: skill, CLI, extension,
tests, and the provider build. The site, labs, concept/composition
catalogs, image pipeline, Cloudflare functions, and authoring guide move
to pbakaus/impeccable-site.

concept-seed tests run against a synthetic fixture catalog; the plugin
icon and skill categories moved in-repo; build validation narrows to
README prose and non-site counts; release notes read from a sibling
impeccable-site checkout.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 22:41:53 -07:00
Paul BakausandClaude Fable 5 b5ec969c07 Add world roll API and seed telemetry client
/api/roll deals deterministic challenger rolls server-side (same salts and
sha256 ranking as the local seed, verified bit-for-bit); the request log is
the impression record. /api/chosen takes the anonymous choice ping. Events
land in Workers Analytics Engine.

concept-seed.mjs resolves data in order: local catalog dir, roll API,
degraded promotion-only seed. --chosen sends the choice ping; DO_NOT_TRACK
and IMPECCABLE_NO_TELEMETRY disable it. API-dealt seeds carry the telemetry
instruction inline.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 22:17:09 -07:00
Paul BakausandClaude Fable 5 7557935fdb Expand concept system: modes, ratings, re-roll, breadth strategy
Catalog: mode-aligned staging surfaces (persuade/operate/read/experience),
star ratings on approvals feeding challenger draw weights, family
retirements, authoring strategy and territory guide, rework and breadth
authoring rounds, composition mining from rejected worlds.

Seed: six challengers (two per tier), --reroll chains, --mode staging
filter, rating-weighted draws. New-work: Present/visualize/re-roll flow,
image-gen requirement, register-neutral vocabulary.

Pipeline: per-mode staging prompts with split frames, hero-from-board
reference generation, render-safety guards. Labs: ratings UI, unrated
filter, mode chips, composition approve-guard.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 22:10:10 -07:00
dependabot[bot]andGitHub 3e94d416e6 chore(deps-dev): bump the bun-minor-and-patch group with 9 updates (#392)
Update the coordinated AI SDK stack plus Anthropic, Google GenAI, Astro, and Wrangler minor/patch releases.

Validated with a frozen Bun install, full build, full test suite, and green GitHub checks.

AI assistance: Codex performed dependency review and validation under maintainer automation instructions.
2026-07-20 10:07:23 -07:00
Paul Bakaus bbed6eef08 Refresh the Impeccable product experience
Rework the landing page proof, steering demo, feature grid, slop catalog, detector coverage, theming, Live workflow, and responsive behavior.\n\nAI-assisted implementation by OpenAI Codex.
2026-07-15 23:29:47 -07:00
dependabot[bot]andGitHub f2049c2b76 chore(deps): bump the bun-minor-and-patch group with 10 updates (#368)
AI assistance: validated and merged by Codex during the weekly dependency sweep.
2026-07-13 10:05:40 -07:00
Paul Bakaus 27a210b04c Add Codex Live architecture benchmark
Compare direct Sol execution with cold and persistent app-server paths using identical full-task quality gates, lifecycle timings, and token metrics.\n\nAI-assisted: OpenAI Codex.
2026-07-12 20:19:23 -07:00
Paul Bakaus 92a5589d5d Add Codex Live quality benchmark
Benchmark realistic bolder and polish tasks across fast, full-model, and full-context worker profiles with deterministic and independent quality gates.\n\nAI-assisted: OpenAI Codex.
2026-07-12 19:48:51 -07:00
Paul Bakaus 02b1040280 Add Live performance lab and benchmarks
Measure framework and provider latency, enforce fidelity and cleanup gates, and publish reproducible results on the dev-only Live Lab.\n\nAI-assisted: OpenAI Codex.
2026-07-12 17:55:10 -07:00
Paul BakausandClaude Fable 5 c3aba1e343 hooks: two-tier design hook — immediate per-edit rules + full-set Stop deep pass
Eval evidence showed the per-edit PostToolUse stream fires overwhelmingly
on copy-level rules (em-dash-overuse ~97x/session) and measurably makes
models more conservative, while a full-detector pass at completion is what
actually fixes contrast/padding/glow. Split the hook accordingly:

- Per-edit (PostToolUse) now surfaces only IMMEDIATE_TIER_RULES: broken
  output (broken-image, text-overflow, clipped-overflow-container,
  body-text-viewport-edge), objective contrast/legibility failures
  (low-contrast, gray-on-color, tiny-text), single-property mechanical
  slop (gradient-text, dark-glow), and design-system drift (the four
  design-system-* rules, which compound if left uncorrected). Everything
  else defers. Override with hook.perEditRules: "all" in
  .impeccable/config.json. Tiering is off for Cursor/Copilot harnesses,
  which have no Stop pass wired, so nothing gets silently dropped there.

- Stop deep pass (runStopHook): runs the FULL rule set over every UI file
  touched this session (tracked via the existing hook.cache.json session
  state; deferred-only edits now mark the file touched), dedupes against
  everything already surfaced per-edit, honors ignore-rule/file/value and
  inline disables, reuses the [impeccable@1] envelope, and no-ops fast
  when no UI files were touched. Emits hookSpecificOutput
  { hookEventName: "Stop", additionalContext } per the Claude Code SDK
  Stop contract (conversation continues so the model can act on it).
  Second Stop fire is silent - deep-pass findings are remembered.

- Wiring: Stop entries (timeout 30) in plugin/hooks/hooks.json, the
  .claude settings + .codex hooks manifests (transformers + hook-admin
  repair path). Claude Code and Codex both dispatch a native Stop event;
  Cursor's stop hook is inconsistently dispatched (pre-write gate stays)
  and Copilot's agentStop/sessionEnd don't inject model context, so
  neither gets a Stop entry - documented in reference/hooks.md.

- Tests: tiering split/override/harness gating, Stop dedupe + silent
  no-touched-files + ignore machinery + kill switches; existing per-edit
  tests moved to immediate-tier rule ids. 181 tests green; smoke-tested
  the built dist skill end to end (glow surfaced per-edit, em-dash only
  at Stop, second Stop silent).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 16:46:00 -07:00
Paul BakausandGitHub 0d1c34e9d0 Fix: support Node 22 CLI installs (#361)
Lower the CLI engine floor to Node 22.12 so npx no longer falls back to stale 2.x releases for Node 22/23 users.

Add Node 22.12 CI coverage while preserving the stable required test check, and document the 3.2.1 CLI release notes including the detector and installer fixes already waiting on main.

AI-assisted-by: Codex
2026-07-09 11:34:07 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
9927634d4f chore(deps): bump the bun-minor-and-patch group with 10 updates (#350)
Bumps the bun-minor-and-patch group with 10 updates:

| Package | From | To |
| --- | --- | --- |
| [@ai-sdk/anthropic](https://github.com/vercel/ai/tree/HEAD/packages/anthropic) | `4.0.7` | `4.0.8` |
| [@ai-sdk/openai](https://github.com/vercel/ai/tree/HEAD/packages/openai) | `4.0.7` | `4.0.8` |
| [@anthropic-ai/claude-agent-sdk](https://github.com/anthropics/claude-agent-sdk-typescript) | `0.3.195` | `0.3.201` |
| [@anthropic-ai/sdk](https://github.com/anthropics/anthropic-sdk-typescript) | `0.107.0` | `0.110.0` |
| @paper-design/shaders | `0.0.76` | `0.0.77` |
| [ai](https://github.com/vercel/ai/tree/HEAD/packages/ai) | `7.0.14` | `7.0.16` |
| [astro](https://github.com/withastro/astro/tree/HEAD/packages/astro) | `7.0.3` | `7.0.6` |
| [motion](https://github.com/motiondivision/motion) | `12.42.0` | `12.42.2` |
| [wrangler](https://github.com/cloudflare/workers-sdk/tree/HEAD/packages/wrangler) | `4.105.0` | `4.107.0` |
| [puppeteer](https://github.com/puppeteer/puppeteer) | `25.2.1` | `25.3.0` |


Updates `@ai-sdk/anthropic` from 4.0.7 to 4.0.8
- [Release notes](https://github.com/vercel/ai/releases)
- [Changelog](https://github.com/vercel/ai/blob/main/packages/anthropic/CHANGELOG.md)
- [Commits](https://github.com/vercel/ai/commits/@ai-sdk/anthropic@4.0.8/packages/anthropic)

Updates `@ai-sdk/openai` from 4.0.7 to 4.0.8
- [Release notes](https://github.com/vercel/ai/releases)
- [Changelog](https://github.com/vercel/ai/blob/main/packages/openai/CHANGELOG.md)
- [Commits](https://github.com/vercel/ai/commits/@ai-sdk/openai@4.0.8/packages/openai)

Updates `@anthropic-ai/claude-agent-sdk` from 0.3.195 to 0.3.201
- [Release notes](https://github.com/anthropics/claude-agent-sdk-typescript/releases)
- [Changelog](https://github.com/anthropics/claude-agent-sdk-typescript/blob/main/CHANGELOG.md)
- [Commits](https://github.com/anthropics/claude-agent-sdk-typescript/compare/v0.3.195...v0.3.201)

Updates `@anthropic-ai/sdk` from 0.107.0 to 0.110.0
- [Release notes](https://github.com/anthropics/anthropic-sdk-typescript/releases)
- [Changelog](https://github.com/anthropics/anthropic-sdk-typescript/blob/main/CHANGELOG.md)
- [Commits](https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.107.0...sdk-v0.110.0)

Updates `@paper-design/shaders` from 0.0.76 to 0.0.77

Updates `ai` from 7.0.14 to 7.0.16
- [Release notes](https://github.com/vercel/ai/releases)
- [Changelog](https://github.com/vercel/ai/blob/main/packages/ai/CHANGELOG.md)
- [Commits](https://github.com/vercel/ai/commits/ai@7.0.16/packages/ai)

Updates `astro` from 7.0.3 to 7.0.6
- [Release notes](https://github.com/withastro/astro/releases)
- [Changelog](https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG.md)
- [Commits](https://github.com/withastro/astro/commits/astro@7.0.6/packages/astro)

Updates `motion` from 12.42.0 to 12.42.2
- [Changelog](https://github.com/motiondivision/motion/blob/main/CHANGELOG.md)
- [Commits](https://github.com/motiondivision/motion/compare/v12.42.0...v12.42.2)

Updates `wrangler` from 4.105.0 to 4.107.0
- [Release notes](https://github.com/cloudflare/workers-sdk/releases)
- [Commits](https://github.com/cloudflare/workers-sdk/commits/wrangler@4.107.0/packages/wrangler)

Updates `puppeteer` from 25.2.1 to 25.3.0
- [Release notes](https://github.com/puppeteer/puppeteer/releases)
- [Changelog](https://github.com/puppeteer/puppeteer/blob/main/CHANGELOG.md)
- [Commits](https://github.com/puppeteer/puppeteer/compare/puppeteer-v25.2.1...puppeteer-v25.3.0)

---
updated-dependencies:
- dependency-name: "@ai-sdk/anthropic"
  dependency-version: 4.0.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: bun-minor-and-patch
- dependency-name: "@ai-sdk/openai"
  dependency-version: 4.0.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: bun-minor-and-patch
- dependency-name: "@anthropic-ai/claude-agent-sdk"
  dependency-version: 0.3.201
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: bun-minor-and-patch
- dependency-name: "@anthropic-ai/sdk"
  dependency-version: 0.110.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: bun-minor-and-patch
- dependency-name: "@paper-design/shaders"
  dependency-version: 0.0.77
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: bun-minor-and-patch
- dependency-name: ai
  dependency-version: 7.0.16
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: bun-minor-and-patch
- dependency-name: astro
  dependency-version: 7.0.6
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: bun-minor-and-patch
- dependency-name: motion
  dependency-version: 12.42.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: bun-minor-and-patch
- dependency-name: wrangler
  dependency-version: 4.107.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: bun-minor-and-patch
- dependency-name: puppeteer
  dependency-version: 25.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: bun-minor-and-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-06 10:08:37 -07:00
Paul BakausandGitHub 582f23eae3 Bump AI SDK packages to v7 (#336)
* Bump AI SDK packages to v7

* Use AI SDK v7 responseMessages in skill behavior harness
2026-07-03 19:21:20 -07:00
dependabot[bot]andGitHub 67e73f47a6 chore(deps): bump the bun-minor-and-patch group with 7 updates (#320)
Bump the bun-minor-and-patch dependency group with 7 updates.
2026-07-03 18:01:06 -07:00
Paul BakausandClaude Opus 4.8 e83e437cdd Release prep: skill v3.9.0, CLI v3.2.0
Bump skill 3.8.0 -> 3.9.0 (plugin.json, marketplace.json, plugin/ subtree,
regenerated provider harness output) and CLI 3.1.0 -> 3.2.0 (package.json).

Changelog (site/pages/changelog.astro):
- Skill v3.9.0: codex grid-background ban, /impeccable bolder design-system
  lock, critique sub-agent independence on non-Claude/Codex harnesses,
  bundled helpers under strict-permission harnesses, Codex hook manifest fix.
- CLI v3.2.0: codex-grid-background detector rule, external skills-symlink
  preservation on first install.

Also: gitignore nested hook.cache.json/hook.pending.json copies (anchored
patterns missed the generated harness dirs), and repoint CLAUDE.md/AGENTS.md
changelog docs at changelog.astro with concise, user-facing-only tone guidance.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 01:50:04 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Paul Bakaus
3590bf9e37 chore(deps-dev): bump astro from 6.4.7 to 7.0.0 (#292)
Bumps [astro](https://github.com/withastro/astro/tree/HEAD/packages/astro) from 6.4.7 to 7.0.0.
- [Release notes](https://github.com/withastro/astro/releases)
- [Changelog](https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG.md)
- [Commits](https://github.com/withastro/astro/commits/astro@7.0.0/packages/astro)

---
updated-dependencies:
- dependency-name: astro
  dependency-version: 7.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Paul Bakaus <paul.bakaus@gmail.com>
2026-06-25 17:51:01 -07:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
a4ff58ef51 chore(deps): bump the bun-minor-and-patch group with 9 updates
Bumps the bun-minor-and-patch group with 9 updates:

| Package | From | To |
| --- | --- | --- |
| [@ai-sdk/anthropic](https://github.com/vercel/ai/tree/HEAD/packages/anthropic) | `3.0.84` | `3.0.85` |
| [@ai-sdk/google](https://github.com/vercel/ai/tree/HEAD/packages/google) | `3.0.82` | `3.0.83` |
| [@ai-sdk/openai](https://github.com/vercel/ai/tree/HEAD/packages/openai) | `3.0.71` | `3.0.74` |
| [@anthropic-ai/claude-agent-sdk](https://github.com/anthropics/claude-agent-sdk-typescript) | `0.3.178` | `0.3.185` |
| [@anthropic-ai/sdk](https://github.com/anthropics/anthropic-sdk-typescript) | `0.104.2` | `0.105.0` |
| [@google/genai](https://github.com/googleapis/js-genai) | `2.8.0` | `2.9.0` |
| [ai](https://github.com/vercel/ai/tree/HEAD/packages/ai) | `6.0.206` | `6.0.208` |
| [wrangler](https://github.com/cloudflare/workers-sdk/tree/HEAD/packages/wrangler) | `4.100.0` | `4.103.0` |
| [puppeteer](https://github.com/puppeteer/puppeteer) | `25.1.0` | `25.2.0` |


Updates `@ai-sdk/anthropic` from 3.0.84 to 3.0.85
- [Release notes](https://github.com/vercel/ai/releases)
- [Changelog](https://github.com/vercel/ai/blob/@ai-sdk/anthropic@3.0.85/packages/anthropic/CHANGELOG.md)
- [Commits](https://github.com/vercel/ai/commits/@ai-sdk/anthropic@3.0.85/packages/anthropic)

Updates `@ai-sdk/google` from 3.0.82 to 3.0.83
- [Release notes](https://github.com/vercel/ai/releases)
- [Changelog](https://github.com/vercel/ai/blob/@ai-sdk/google@3.0.83/packages/google/CHANGELOG.md)
- [Commits](https://github.com/vercel/ai/commits/@ai-sdk/google@3.0.83/packages/google)

Updates `@ai-sdk/openai` from 3.0.71 to 3.0.74
- [Release notes](https://github.com/vercel/ai/releases)
- [Changelog](https://github.com/vercel/ai/blob/@ai-sdk/openai@3.0.74/packages/openai/CHANGELOG.md)
- [Commits](https://github.com/vercel/ai/commits/@ai-sdk/openai@3.0.74/packages/openai)

Updates `@anthropic-ai/claude-agent-sdk` from 0.3.178 to 0.3.185
- [Release notes](https://github.com/anthropics/claude-agent-sdk-typescript/releases)
- [Changelog](https://github.com/anthropics/claude-agent-sdk-typescript/blob/main/CHANGELOG.md)
- [Commits](https://github.com/anthropics/claude-agent-sdk-typescript/compare/v0.3.178...v0.3.185)

Updates `@anthropic-ai/sdk` from 0.104.2 to 0.105.0
- [Release notes](https://github.com/anthropics/anthropic-sdk-typescript/releases)
- [Changelog](https://github.com/anthropics/anthropic-sdk-typescript/blob/main/CHANGELOG.md)
- [Commits](https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.104.2...sdk-v0.105.0)

Updates `@google/genai` from 2.8.0 to 2.9.0
- [Release notes](https://github.com/googleapis/js-genai/releases)
- [Changelog](https://github.com/googleapis/js-genai/blob/main/CHANGELOG.md)
- [Commits](https://github.com/googleapis/js-genai/compare/v2.8.0...v2.9.0)

Updates `ai` from 6.0.206 to 6.0.208
- [Release notes](https://github.com/vercel/ai/releases)
- [Changelog](https://github.com/vercel/ai/blob/ai@6.0.208/packages/ai/CHANGELOG.md)
- [Commits](https://github.com/vercel/ai/commits/ai@6.0.208/packages/ai)

Updates `wrangler` from 4.100.0 to 4.103.0
- [Release notes](https://github.com/cloudflare/workers-sdk/releases)
- [Commits](https://github.com/cloudflare/workers-sdk/commits/wrangler@4.103.0/packages/wrangler)

Updates `puppeteer` from 25.1.0 to 25.2.0
- [Release notes](https://github.com/puppeteer/puppeteer/releases)
- [Changelog](https://github.com/puppeteer/puppeteer/blob/main/CHANGELOG.md)
- [Commits](https://github.com/puppeteer/puppeteer/compare/puppeteer-v25.1.0...puppeteer-v25.2.0)

---
updated-dependencies:
- dependency-name: "@ai-sdk/anthropic"
  dependency-version: 3.0.85
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: bun-minor-and-patch
- dependency-name: "@ai-sdk/google"
  dependency-version: 3.0.83
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: bun-minor-and-patch
- dependency-name: "@ai-sdk/openai"
  dependency-version: 3.0.74
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: bun-minor-and-patch
- dependency-name: "@anthropic-ai/claude-agent-sdk"
  dependency-version: 0.3.185
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: bun-minor-and-patch
- dependency-name: "@anthropic-ai/sdk"
  dependency-version: 0.105.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: bun-minor-and-patch
- dependency-name: "@google/genai"
  dependency-version: 2.9.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: bun-minor-and-patch
- dependency-name: ai
  dependency-version: 6.0.208
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: bun-minor-and-patch
- dependency-name: wrangler
  dependency-version: 4.103.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: bun-minor-and-patch
- dependency-name: puppeteer
  dependency-version: 25.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: bun-minor-and-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-25 17:35:04 -07:00
Paul BakausandClaude Opus 4.8 da18929df0 Release skill v3.8.0 and CLI v3.1.0
Bump skill to 3.8.0 (GitHub Copilot design hooks, monorepo-aware
context) and CLI to 3.1.0 (inline detector ignore comments, fail-loudly
on unknown subcommands). Add changelog entries and sync generated
provider output.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 05:41:24 +09:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
1fd1eb11bc chore(deps-dev): bump the bun-minor-and-patch group across 1 directory with 9 updates (#248)
Bumps the bun-minor-and-patch group with 9 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [@ai-sdk/anthropic](https://github.com/vercel/ai/tree/HEAD/packages/anthropic) | `3.0.81` | `3.0.84` |
| [@ai-sdk/google](https://github.com/vercel/ai/tree/HEAD/packages/google) | `3.0.80` | `3.0.82` |
| [@ai-sdk/openai](https://github.com/vercel/ai/tree/HEAD/packages/openai) | `3.0.68` | `3.0.71` |
| [@anthropic-ai/claude-agent-sdk](https://github.com/anthropics/claude-agent-sdk-typescript) | `0.3.168` | `0.3.178` |
| [@anthropic-ai/sdk](https://github.com/anthropics/anthropic-sdk-typescript) | `0.102.0` | `0.104.2` |
| [ai](https://github.com/vercel/ai/tree/HEAD/packages/ai) | `6.0.197` | `6.0.206` |
| [astro](https://github.com/withastro/astro/tree/HEAD/packages/astro) | `6.4.4` | `6.4.7` |
| [playwright](https://github.com/microsoft/playwright) | `1.60.0` | `1.61.0` |
| [wrangler](https://github.com/cloudflare/workers-sdk/tree/HEAD/packages/wrangler) | `4.98.0` | `4.100.0` |



Updates `@ai-sdk/anthropic` from 3.0.81 to 3.0.84
- [Release notes](https://github.com/vercel/ai/releases)
- [Changelog](https://github.com/vercel/ai/blob/@ai-sdk/anthropic@3.0.84/packages/anthropic/CHANGELOG.md)
- [Commits](https://github.com/vercel/ai/commits/@ai-sdk/anthropic@3.0.84/packages/anthropic)

Updates `@ai-sdk/google` from 3.0.80 to 3.0.82
- [Release notes](https://github.com/vercel/ai/releases)
- [Changelog](https://github.com/vercel/ai/blob/@ai-sdk/google@3.0.82/packages/google/CHANGELOG.md)
- [Commits](https://github.com/vercel/ai/commits/@ai-sdk/google@3.0.82/packages/google)

Updates `@ai-sdk/openai` from 3.0.68 to 3.0.71
- [Release notes](https://github.com/vercel/ai/releases)
- [Changelog](https://github.com/vercel/ai/blob/@ai-sdk/openai@3.0.71/packages/openai/CHANGELOG.md)
- [Commits](https://github.com/vercel/ai/commits/@ai-sdk/openai@3.0.71/packages/openai)

Updates `@anthropic-ai/claude-agent-sdk` from 0.3.168 to 0.3.178
- [Release notes](https://github.com/anthropics/claude-agent-sdk-typescript/releases)
- [Changelog](https://github.com/anthropics/claude-agent-sdk-typescript/blob/main/CHANGELOG.md)
- [Commits](https://github.com/anthropics/claude-agent-sdk-typescript/compare/v0.3.168...v0.3.178)

Updates `@anthropic-ai/sdk` from 0.102.0 to 0.104.2
- [Release notes](https://github.com/anthropics/anthropic-sdk-typescript/releases)
- [Changelog](https://github.com/anthropics/anthropic-sdk-typescript/blob/main/CHANGELOG.md)
- [Commits](https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.102.0...sdk-v0.104.2)

Updates `ai` from 6.0.197 to 6.0.206
- [Release notes](https://github.com/vercel/ai/releases)
- [Changelog](https://github.com/vercel/ai/blob/ai@6.0.206/packages/ai/CHANGELOG.md)
- [Commits](https://github.com/vercel/ai/commits/ai@6.0.206/packages/ai)

Updates `astro` from 6.4.4 to 6.4.7
- [Release notes](https://github.com/withastro/astro/releases)
- [Changelog](https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG.md)
- [Commits](https://github.com/withastro/astro/commits/astro@6.4.7/packages/astro)

Updates `playwright` from 1.60.0 to 1.61.0
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](https://github.com/microsoft/playwright/compare/v1.60.0...v1.61.0)

Updates `wrangler` from 4.98.0 to 4.100.0
- [Release notes](https://github.com/cloudflare/workers-sdk/releases)
- [Commits](https://github.com/cloudflare/workers-sdk/commits/wrangler@4.100.0/packages/wrangler)

---
updated-dependencies:
- dependency-name: "@ai-sdk/anthropic"
  dependency-version: 3.0.84
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: bun-minor-and-patch
- dependency-name: "@ai-sdk/google"
  dependency-version: 3.0.82
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: bun-minor-and-patch
- dependency-name: "@ai-sdk/openai"
  dependency-version: 3.0.71
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: bun-minor-and-patch
- dependency-name: "@anthropic-ai/claude-agent-sdk"
  dependency-version: 0.3.177
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: bun-minor-and-patch
- dependency-name: "@anthropic-ai/sdk"
  dependency-version: 0.104.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: bun-minor-and-patch
- dependency-name: ai
  dependency-version: 6.0.205
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: bun-minor-and-patch
- dependency-name: astro
  dependency-version: 6.4.7
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: bun-minor-and-patch
- dependency-name: playwright
  dependency-version: 1.61.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: bun-minor-and-patch
- dependency-name: wrangler
  dependency-version: 4.100.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: bun-minor-and-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-19 21:37:29 -07:00
Paul BakausandGitHub 8b0c895703 [codex] Fix CLI skill update detection (#257)
* Fix CLI skill update detection

* Preserve linked skills during install refresh

* Keep existing installs working offline

* Respect provider scope during install refresh
2026-06-16 19:50:40 -07:00
c27a75ad41 fix(cli): replace extract-zip with fflate to fix silent install on Node v24.16.0+ (#253)
On Node v24.16.0 / v26.1.0+, `impeccable install` printed "Downloading
impeccable skills...", exited 0, and installed nothing. A Node streams
regression (nodejs/node#63487) made pause()/resume() no-ops on destroyed
streams, stalling extract-zip's yauzl/fd-slicer read stack partway through;
its promise never settled and the process exited clean with no error.

Swap extract-zip for fflate across both extraction call sites
(downloadAndExtractBundle, copyOrExtractLocalBundle) via a new extractZip
helper. fflate decompresses from an in-memory buffer and never touches the
fs stream path, so it is immune on every Node version. It is pure JS with
zero dependencies, so the Windows fix from #198 (no `unzip` binary) holds.
Unlike extract-zip, fflate is actively maintained.

Because extractZip writes entries itself, it guards against zip-slip (`../`
entries escaping the target dir). Tests add a many-file regression guard
(fails on partial extraction) and a zip-slip rejection test.

Verified end-to-end: the real 1,194-file universal bundle extracts and
installs completely.

Fixes #250.

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-15 20:33:43 -07:00
Paul Bakaus 858b9bbea6 Improve hook false-positive handling 2026-06-15 13:30:28 +09:00
Paul Bakaus 636249cae0 Revert CLI patch release metadata 2026-06-15 09:32:15 +09:00
Paul Bakaus 32c01595e2 Prepare CLI 3.0.1 install targeting fix 2026-06-15 09:14:29 +09:00