Commit Graph
1148 Commits
Author SHA1 Message Date
Vance Ingalls 9bcd279b29 feat(cli): surface stale project pin to non-TTY agents, throttled 2026-07-14 15:28:52 -07:00
Vance Ingalls c1b1c729e5 feat(cli): hyperframes upgrade --project bumps pinned package.json scripts 2026-07-14 15:28:52 -07:00
Vance Ingalls 6fec8f39ae feat(cli): add project-pin rewrite helper 2026-07-14 15:28:51 -07:00
Miguel Ángel 14df58f017 fix(check): ignore registry component templates (#2450) 2026-07-14 18:21:25 -04:00
Miguel Ángel 9ce44b6603 fix(cli): bundle preview font localization (#2449) 2026-07-14 18:02:51 -04:00
Miguel Ángel 0b3dfb3f84 fix(render): consolidate duration and timing correctness (#2405)
* fix(producer): pass variables to duration probe

* fix(producer): tolerate rounded frame-boundary durations

* fix(cli): resolve relative data-start references in composition duration

`compositions --json` computed each timed child's start with a bare
parseFloat(data-start ?? "0") in parseCompositions (host duration) and
parseSubComposition (sub-comp duration). A relative reference like
data-start="s1" ("start when clip s1 ends") is not numeric, so parseFloat
returned NaN and that clip's contribution to the max-end was silently
dropped — a host with two 3s clips (2nd data-start="s1") reported duration 3
instead of 6, breaking compositions/inspect/snapshot for composition-clip
relative timing.

Resolve relative references the same way the extractor does (parseStartExpression
from @hyperframes/core + a findReferenceTargetEl/resolveReferencedStart port,
since the engine's referenceResolver isn't a public export across the package
boundary). Verified: host duration now 6; 3 tests pass.
(Implemented via Codex; verified independently.)
2026-07-14 17:12:36 -04:00
Miguel Ángel 4b0b89e8b1 chore: release v0.7.58 (#2446) 2026-07-14 16:15:59 -04:00
Miguel Ángel 6c2513d5c8 fix(check): resolve color-mix() colors in contrast audit instead of false-failing (#2445) 2026-07-14 15:51:11 -04:00
Miguel Ángel 990f5c3145 feat(feedback): adopt 0–10 recommendation scale (#2438)
* feat(feedback): adopt 10-point recommendation scale

* docs(feedback): keep OSS scale contract self-contained
2026-07-14 15:46:47 -04:00
Vance IngallsandClaude Opus 4.7 fd02e6efc9 fix(cli): surface HYPERFRAMES_BROWSER_PATH hint on pinned browser download failures
When `@puppeteer/browsers`' install() rejected for any reason the corrupt-
archive recovery path couldn't handle (`All providers failed for
chrome-headless-shell <ver>`, DNS/network, macOS Gatekeeper, a second
corruption), the raw error propagated with no mention of the escape
hatch. Wrap the surfaced error to name `HYPERFRAMES_BROWSER_PATH` with a
platform-specific example (macOS/Windows/Linux) and keep the original
via `cause`.

Field feedback ts 1784055194.202169 in #hyperframes-cli-feedback
(darwin/arm64, HF CLI 0.7.57) hit this and recovered by pointing the
env var at system Google Chrome — they discovered the workaround on
their own because the error didn't tell them.

Download-time sibling of #2078 (SIGTRAP at launch, same remediation,
different trigger).

— Via

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-14 19:32:45 +00:00
Miguel Ángel 3d7e26aabf fix(render): diagnose unlaunchable Windows FFmpeg (#2430) 2026-07-14 12:55:46 -04:00
WaterrrForeverandClaude Fable 5 4a4903b49a feat(skills): group core skills in the skills add picker (#2412)
Add a `core-skills` entry to .claude-plugin/marketplace.json declaring
the core skill set (the /hyperframes router, the hyperframes-* domain
skills, and media-use). The upstream vercel-labs/skills CLI reads that
entry's `skills` array for its interactive picker: the core set renders
under a "Core Skills" group and everything else falls into "Other", so
a human running `npx skills add heygen-com/hyperframes --full-depth`
can tell the always-needed core set apart from the on-demand creation
workflows — mirroring the core/on-demand tiers `hyperframes skills
update` already enforces (isCoreSkill in skillsManifest.ts).

The array deliberately lives on a separate marketplace entry, NOT on
plugin.json or the `hyperframes` entry: Claude Code treats a manifest
`skills` array as that plugin's skill allowlist (verified against
claude CLI), so attaching it to the full plugin would narrow it from
all skills to the core 8. As a side effect the new entry is itself a
coherent Claude Code plugin — `core-skills@hyperframes` installs just
the core set — while `hyperframes@hyperframes` keeps auto-discovering
everything.

A new pin test keeps the marketplace list in lockstep with isCoreSkill
and the skills/ tree (alongside the existing FALLBACK_CORE_SKILLS pin),
and asserts the full plugin carries no allowlist. Agent installs are
unaffected — the upstream CLI detects agent environments and installs
non-interactively, and the hyperframes CLI always passes explicit
--skill flags.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 20:41:42 +08:00
Miguel Ángel 6933e8acda fix(cli): consolidate snapshot and frame diagnostics (#2402)
* fix(snapshot): preserve exact requested times

* fix(cli): fail video snapshots without FFmpeg

* fix(cli): honor navigation timeout in diagnostics

* fix(cli): preserve snapshot alpha and create shot dirs
2026-07-14 01:46:44 -04:00
Miguel Ángel b98463ae3a fix(cli): consolidate layout and contrast audit correctness (#2401)
* fix(cli): respect transparent image pixels in occlusion audit

* test(cli): cover contained image letterboxing

* fix(cli): account for text strokes in contrast checks

* fix(cli): honor text overflow opt-outs

* fix(cli): skip contrast on transparent backdrops

* chore(skills): refresh generated manifest
2026-07-14 01:44:58 -04:00
Miguel Ángel 90be05019b chore: release v0.7.57 (#2393) 2026-07-14 00:29:29 -04:00
Miguel Ángel 8bf7bc3af5 fix(cli): require explicit non-interactive init source (#2395) 2026-07-13 23:28:46 -04:00
Miguel Ángel 2a7a5e6236 feat(preview): keep review sessions alive (#2384)
* feat(preview): keep review sessions alive

* fix(preview): harden background lifecycle state

* refactor(preview): satisfy lifecycle quality gate
2026-07-13 22:55:19 -04:00
Miguel Ángel 4495cb7355 feat(cli): stable public URL for hyperframes publish (re-publish updates the same link) (#2363)
* feat(cli): stable-URL re-publish (send owned id, honest UX, --update, team id file)

Resolve a stable project id (committed team id > machine store > mint), send it
when authenticated so an owned re-publish updates the same URL in place, and
persist the server id+url. Report updated-vs-created honestly, add --update to
target a project explicitly, write a committable .hyperframes/project.json so a
team shares one link, and show the prior URL on re-publish.

* test(cli): env-gated E2E round-trip for stable-URL re-publish

Publish -> edit -> re-publish asserts one URL with updated content against a
live EF (HYPERFRAMES_E2E_API_URL + an authenticated runner); skipped otherwise.

* fix(cli): real team space, auth-gate --update/--space, safe team-file write

- --space + committed .hyperframes/project.json (projectId+spaceId) send X-Space-Id so a
  team converges on one link; personal space stays the default for solo users
- --update/--space error when unauthenticated, and warn loudly when a resolved-but-invalid
  token silently downgrades to a new anonymous URL (no more generic-tip-only)
- team-file write in its own try/catch so a read-only dir can't fake 'Publish failed'
- parseUpdateTarget handles scheme-less URLs + query/hash; X-Space-Id on metadata only (not S3 PUT)
- share readJsonRecord across the local + team descriptors

* test(cli): e2e team-space convergence + cross-space hijack guard

* test(cli): unit-test parseUpdateTarget url shapes (export for test)

* fix(cli): warn on committed-team miss too, not just --update
2026-07-13 22:47:28 -04:00
Miguel Ángel fba5cb9c93 fix(pr-to-video): bound first-run workspace and context (#2382)
* fix(pr-to-video): bound first-run workspace and context

* fix(cli): expose validation gate in help

* fix(pr-to-video): harden workflow guardrails

* style(pr-to-video): apply repository formatting

* chore(skills): refresh pr-to-video manifest
2026-07-13 22:33:21 -04:00
Miguel Ángel b231b6f963 fix(cli): surface keyframes from scripts and styles inside <template> (#2374)
Sub-compositions are required to wrap markup, script, and style in <template>, but template content is an inert DocumentFragment that document-level querySelectorAll does not traverse — so 'hyperframes keyframes' silently surfaced zero tweens and zero CSS keyframes for every spec-conformant sub-composition. Extract from the document and every template content fragment (nested templates included, walked iteratively). Documents the extraction ordering contract and the deliberately document-root-only sub-composition discovery scan; pins template, multi-template, nested-template, and mixed-script cases with tests.
2026-07-13 20:47:50 -04:00
Miguel Ángel 3a020bf543 fix(cli): reject missing init example values (#2376) 2026-07-13 20:42:11 -04:00
Vance Ingalls d04bcbf7c4 Merge pull request #2360 from heygen-com/via/issue-1-webm-alpha-probe
fix(cli): detect WebM alpha lost when ALPHA_MODE tag is written without side data
2026-07-13 16:44:57 -07:00
Vance Ingalls c6da79cbdb Merge pull request #2358 from heygen-com/07-13-fix_core_cli_attribute_figma_rest_failures_to_the_endpoint_that_failed
fix(core,cli): attribute figma REST failures to the endpoint that failed
2026-07-13 16:16:24 -07:00
James Russo cb69d3fe00 fix(render): surface structured outcomes (#2153) 2026-07-13 19:07:39 -04:00
Miguel Ángel 746b6d5b75 feat(cli): tag HeyGen API calls with X-HeyGen-Client-Source (#2368)
Send `X-HeyGen-Client-Source: hyperframes` from buildAuthHeaders on every
HeyGen API call (both OAuth and API-key), so backend billing meta can
isolate hyperframes CLI usage. The single buildAuthHeaders chokepoint covers
the core CLI + cloud client. Mirrors the media-use tagging; the OAuth-only
X-HeyGen-Source cli free-gate header is unchanged.
2026-07-13 19:02:22 -04:00
Xuanru Li 7f4eaeb568 feat(cli): coordinate-frame layout findings in check (#2354)
* feat(cli): coordinate-frame layout findings in check

Four production compositions shipped with 100-600px layout drift, each a
different coordinate-frame confusion the check graded info or missed
entirely: viewport pixels written as container left/top, gsap x/y
treated as absolute position, a -350px margin fighting flex centering,
and stage-relative path coords drawn into a nested SVG.

Three new layout findings close the class:
- positioned_out_of_parent: an absolute/fixed element rendering mostly
  outside its positioning ancestor (warning) — the parent needs no
  overflow clipping, which is what let container_overflow miss it.
- box_out_of_canvas: a painted panel breaching the canvas (warning) —
  text is canvas_overflow's, media is frame_out_of_frame's, painted
  boxes were nobody's.
- connector_detached: a connector path whose endpoints land far from
  every anchorable element (warning) — measured coordinates drawn into
  an SVG with a different origin.

canvas_overflow additionally promotes from info to warning when held
across samples AND the breach exceeds 5% of the canvas.

All three are persistence-tiered and respect data-layout-allow-overflow.
Verified against the four incident compositions: every one now surfaces
its drift as held warnings (previously: info or silence).

* fix(cli): harden coordinate-frame findings against review false positives

Reworks all three findings after two-lens review (adversarial FP hunt in
real Chrome + maintainer pass):

- escaped_container (was positioned_out_of_parent): uses offsetParent
  (transform-aware, skips fixed-as-canvas), exempts fully-detached
  callouts within an attachment allowance while still flagging
  touching-but-mostly-outside drift.
- panel_out_of_canvas (was box_out_of_canvas): paint alone qualifies
  (flat solid panels were a false negative), fully off-canvas rects are
  parked entrances and stay silent, pointer-events:none marks decorative
  layers, hero-sized breaches warn while small bleeds stay info.
- connector_detached: endpoints via getPointAtLength + getScreenCTM
  (viewBox, preserveAspectRatio, group transforms, every command type),
  defs/marker/clipPath subtrees skipped, word-boundary connector naming,
  containment tier limited to opaque non-ancestor targets (a text-bearing
  wrapper contains its own diagram's endpoints).
- canvas_overflow promotion requires partial visibility — a fully
  off-canvas rect is a parked entrance, not drift.

Verified: the four incident compositions still surface their drift as
held warnings; the review's false-positive repros (fixed HUD, callout,
parked entrance, corner bleed, marker arrowheads, g-transform and
viewBox-scaled connectors) are clean at warning level. Docs and the CLI
skill reference now describe the coordinate-frame findings.

* fix(cli): panel ownership is geometric — direct-text panels were a silent false negative

A painted panel whose direct text stays in-bounds while its box breaches
the canvas produced neither finding: canvas_overflow measures the text
range and panel_out_of_canvas skipped every own-text element. Skip the
panel finding only when the element's own text ALSO breaches (that
geometry belongs to canvas_overflow); pin the message/fixHint wording of
all three findings with positive assertions; document the SVG-internal
anchor blind spot.

* fix(cli): classify panel decoration by paint kind, not pointer-events

pointer-events:none exempted the framed-painting incident's gold frame
layers — hero content that happens to disable hit-testing. Decoration is
now gradient-only paint (spotlights, textures, vignettes); url() images,
solid fills and borders are content regardless of pointer-events.

* fix(cli): add fixHint to the test-local AuditIssue shape

* fix(cli): gradient stops decide content vs decoration; ownership matches canvas_overflow's tolerance

A gradient with any solid stop (alpha >= 0.6) is content — heroes and
cards painted with linear-gradient were invisible under the blanket
gradient exemption; all-translucent stops (spotlights, vignettes) stay
decoration. The text-ownership check now uses the audit tolerance that
canvas_overflow itself fires at, making the contract strict-mutex: any
text breach past that tolerance cedes the element, so a shallow 20px
text breach no longer double-reports.
2026-07-13 15:35:03 -07:00
Miguel Ángel 8e50e8477f fix(cli): skip contrast for intentionally covered text (#2366) 2026-07-13 18:22:30 -04:00
Vance Ingalls 56dcc4e47a fix(cli): accept 1–3-frame short WebMs + add direct pixel-probe tests
Address Miguel's R1 blocker + Rames/Miga's testability nit:

- The `-frames:v 3` decode samples AT MOST 3 frames; a legitimate 1- or
  2-frame WebM (256 or 512 bytes) was returned as `undefined` (probe
  failure), silently skipping the advisory even when every available
  pixel was opaque. Accept any positive whole-frame byte count ≤ 768
  (multiples of 256), distinguishing successful short-EOF from partial/
  malformed decode.
- Export `sampledAlphaIsFullyOpaque` and add 11 direct tests covering:
  3/2/1-frame opaque decodes → true; transparent pixel at pos 0 or
  final byte → false (guards the alpha-byte stride); non-frame-multiple
  / over-3-frame / zero byte counts → undefined; execFileSync throw →
  undefined; findFFmpeg missing → undefined; and one args-shape guard
  pinning the load-bearing `-c:v libvpx-vp9` before `-i` (without which
  the default decoder silently discards VP9 alpha and the whole check
  would false-positive on genuinely-transparent WebMs).
- Update advisory wording from "3 sampled decoded frames" to "every
  sampled decoded pixel" so the message is honest for short WebMs.

18/18 tests pass locally under `vitest run`.
2026-07-13 22:03:11 +00:00
Miguel Ángel 74fb4dbcc3 docs(cli): sync SRT upload docs from EF (#2364) 2026-07-13 17:51:25 -04:00
Vance Ingalls bd8ee05ae2 fix(cli): label the batch asset-import RENDER_FAILED with the images endpoint
Review feedback on #2358: the batch-miss RENDER_FAILED in
runAssetImportMany (asset.ts) throws the same typed error as
client.ts's single-node renderNode, but wasn't labeled — so
cli_error.endpoint would silently come back undefined for the
flow that most heavily exercises /v1/images.
2026-07-13 21:41:55 +00:00
Vance Ingalls 4ca1552e20 fix(core,cli): attribute figma REST failures to the endpoint that failed
cli_error had no way to tell which figma REST call (images, files_nodes,
variables_local, styles, ...) actually hit RATE_LIMITED/FORBIDDEN/etc, so
the dashboard could see failures spike but not which call caused them.

FigmaClientError now carries a low-cardinality endpoint label (never the
raw fileKey/nodeId), threaded through to cli_error's endpoint property.
2026-07-13 21:41:55 +00:00
Vance Ingalls b8562c91d5 fix(cli): detect WebM alpha lost when the ALPHA_MODE tag is written without side data
Extends webmAlphaCheck.ts (from #2044) with a pixel-level decode probe.
After the tag check passes, decodes 3 sampled frames via
`ffmpeg -c:v libvpx-vp9 -pix_fmt rgba -f rawvideo` at 8x8 and emits a
distinct advisory if every alpha byte reads 255.

#2044 detects the "tag absent" failure mode (ffprobe shows no
`alpha_mode` in stream tags). It doesn't catch a stricter case reported
on CLI 0.7.56 / Windows 11: ALPHA_MODE=1 present but BlockAdditional
alpha side data empty. Under current logic webmAlphaAdvisory sees
`alphaMode: true` and stays silent, so the render ships as opaque
without any signal.

The -metadata:s:v:0 alpha_mode=1 push is a muxer directive that some
ffmpeg builds write unconditionally, independent of whether libvpx-vp9
emitted the alpha plane. Tag presence is necessary but not sufficient
evidence of preserved alpha.

Advisory text names both possibilities (opaque composition OR silent
alpha drop) plus the concrete workaround (png-sequence + prores repack).
Fast path (no tag or missing tag) is unchanged. Probe adds ~1s per
WebM render only when the tag says alpha.
2026-07-13 21:38:12 +00:00
Vance Ingalls 9b71bc2103 Merge pull request #2361 from heygen-com/via/flake-fix-manager-progress-notice
test(cli): stabilize flaky install-lock wait-notice test with fake timers
2026-07-13 14:37:40 -07:00
Vance Ingalls e47af77c5a test(cli): stabilize flaky install-lock wait-notice test with fake timers
Adopt the fake-timer pattern the sibling "recovers when a crashed reclaimer
leaves both lock directories" test in the same file already uses. Without
fake timers, if the dynamic `import("./manager.js")` beat between
`installFsMocks({ initialMtimeMs: Date.now() })` and the `withInstallLock`
call exceeds `staleMs` (50 ms on a busy shared runner with `vi.resetModules()`
per beforeEach), the new immediate-stale short-circuit added in #2328 fires
on iteration 1, breaks out before `waitedMs` reaches `waitNoticeMs=20`, and
no "Waiting for another hyperframes process" warn ever emits — the assertion
at `manager.test.ts:428` (`expected false to be true`) then fails.

Under fake timers, `Date.now()` is frozen at the mtime seed, so the lock
stays non-stale across the dynamic import and the wait-notice branch
observes real polling; `vi.advanceTimersByTimeAsync(staleMs + pollMs * 5)`
then drives the loop past both the wait-notice threshold and the stale
deadline so the reclaim + acquisition still resolves.

Test-only change; no production-code diff. Verified 27/27 in
`packages/cli/src/browser/manager.test.ts` under `vitest run`.
2026-07-13 21:30:44 +00:00
Xuanru LiandClaude Fable 5 3e3b37d37f fix(cli): occlusion-probe false positives — pointer-events blindness, low-alpha gradients, not-yet-entered text (#2357)
* fix(cli): three occlusion-probe false-positive sources in text_occluded

- pointer-events:none text is invisible to elementFromPoint, so the probe
  always hit whatever paints beneath and misread visible text as buried;
  restore hit-testing on the element for the duration of the probe
- a backgroundImage counted as opaque regardless of alpha, so a 4%-alpha
  grid/scrim gradient qualified as an occluder; gradients now occlude only
  when their colours reach alpha > 0.6 (url() images unchanged)
- a visible container whose every text-bearing descendant is still at
  opacity 0 (entrance not started) was probed anyway; skip when no text
  ink is on screen

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

* fix(cli): address review — document-wide hit-testing restore, gradient compositing, whitespace ink

- restore hit-testing for ALL pointer-events:none elements during the text
  audit pass (not just the probed text): an occluder that itself carries
  pointer-events:none is invisible to elementFromPoint, which made truly
  buried text read as clean once the text alone became hittable
- hasVisibleTextInk ignores whitespace-only text nodes (indented markup
  defeated the gate) and uses a 0.05 floor so mid-fade text keeps its
  persistence occurrences
- hasOpaqueBackground composites gradient alpha with background-color
  (two 0.5-alpha layers paint at ~0.75); gradientMaxAlpha returns opaque
  for any colour function it cannot score (oklch/lab/...); percentage
  alpha values now parse as fractions

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

* fix(cli): walk the elementsFromPoint stack in occluderAt

A transparent layer that becomes hittable (pointer-events restored) must
not mask an opaque occluder painting beneath it — single-point
elementFromPoint returned the transparent top and dropped two genuinely
buried cases in the census acceptance run; the stack walk keeps 10/10.

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

* fix(cli): composite stacked background-image layers when judging occluder opacity

Two 0.5-alpha gradient layers paint at 0.75 combined; taking the max
color-stop alpha across the whole declaration under-counted them and
suppressed real text_occluded findings. Split layers at top-level commas
(paren-aware), score each, composite as 1-prod(1-a_i). Also pins the
0.05 text-ink floor with a boundary test (review feedback on #2357).

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

* fix(cli): keep walking the occlusion stack past pair-specific exemptions

sharedPreserve3d and isCrossSceneTransitionOverlap excuse one hit, not
the whole probe; returning null let a transparent decorative layer in
the text's 3D context mask a real occluder below it (review feedback).

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

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 14:27:39 -07:00
Miguel Ángel 81a6edcb67 fix(browser): recover abandoned install locks (#2328) 2026-07-13 16:52:04 -04:00
Miguel Ángel 648e4e8c54 fix(cli): declare Apache-2.0 license (#2351) 2026-07-13 14:56:51 -04:00
Miguel Ángel 758a6d2152 test(ci): stabilize Windows suites after Studio cutover (#2320)
* test(cli): isolate browser check bundling

* test(studio): align timeline merge regressions
2026-07-13 03:24:02 -04:00
Miguel Ángel 94c2e0f6eb chore: release v0.7.56 2026-07-13 07:04:42 +00:00
Miguel Ángel 796d5df156 fix(render): allow explicit entry without index (#2307)
* fix(render): allow explicit entry without index

* fix(render): unify explicit composition handling

* test(cli): allow explicit render integration under CI load
2026-07-12 23:01:27 -04:00
Miguel Ángel 38badff820 fix(render): scope strict lint to composition (#2261)
* fix(render): scope strict lint to composition

* fix(lint): validate explicit composition scope
2026-07-12 22:18:11 -04:00
Miguel Ángel 44653b31da fix(cli): detect video motion in sweep guard (#2308)
* fix(cli): detect video motion in sweep guard

* docs(cli): clarify iframe fingerprint scope
2026-07-12 22:17:49 -04:00
Miguel Ángel b861afe454 fix(check): snapshot restored text after contrast audit (#2306) 2026-07-12 22:17:46 -04:00
Vance Ingalls c830aa83c5 chore: release v0.7.55 2026-07-12 11:52:53 -07:00
kiritowoo ccf5f20b3b fix(cli): stop losing render telemetry to the exit race (#2105) 2026-07-12 21:05:20 +08:00
James RussoandClaude Opus 4.8 f1f317a20c fix(cli): grant s3 encryption actions in lambda policies user output (#2289)
`hyperframes lambda deploy` runs `sam deploy --resolve-s3`, and SAM's
managed artifacts bucket (aws-sam-cli-managed-default) is created with
default SSE encryption. Setting that requires s3:PutEncryptionConfiguration,
which the generated deploy policy did not grant, so a first deploy by a
user provisioned exactly per `lambda policies user` 403s on the bucket and
the managed stack rolls back.

Add s3:GetEncryptionConfiguration and s3:PutEncryptionConfiguration to the
s3Bucket action set (Get pairs with Put for CloudFormation update/drift
reads, matching the existing Get/Put pairs in the list). Also add a hint to
the sam-deploy failure path pointing at the ROLLBACK_COMPLETE recovery step,
since first-time users hit the stuck-rollback error on their retry.

Fixes #2137

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-11 21:36:17 -07:00
Vance Ingalls ae4946e624 chore: release v0.7.54 2026-07-11 17:15:24 -07:00
Vance Ingalls bd86fb803d Merge pull request #2266 from heygen-com/07-11-fix-cli-check-detect-invisible-text
fix(cli): flag text with an effectively transparent fill in check
2026-07-11 17:10:44 -07:00
Vance Ingalls 1a9c1b66b0 Merge pull request #2264 from heygen-com/07-11-fix-cli-localize-remote-fonts-in-audit-capture
fix(cli): localize remote fonts in snapshot/check capture to match render
2026-07-11 17:05:35 -07:00
Vance Ingalls fa902400c9 fix(cli): only exclude clipped text when a background actually paints the glyphs
Addresses review on #2266: the gradient-text exclusion was too broad — any
background-clip:text skipped the invisible-text check, so a broken/missing
gradient (clip:text with no image and a transparent background, which paints
nothing) went unreported. Now exclude only when a real background fills the
glyphs (background-image != none, or an opaque background-color). Expands the
test suite to the reviewer's full case set: direct transparent fill, inherited
transparent fill over an opaque child color, color:transparent fallback, opaque
baseline, gradient-over-real-background exclusion, broken-gradient still flagged,
and empty-text no-op.
2026-07-11 17:04:30 -07:00