Commit Graph
30 Commits
Author SHA1 Message Date
Samraaj BathandClaude Fable 5 f3d433c024 Teach motion gate about reveal-replay; auto-provision missing harness deps
- motionGate: a captured CSS entrance animation the clone replays through
  a DittoMotion reveal (re-hide on mount, restart @keyframes on scroll)
  is graded by the scroll-reveal check, not the static-CSS expectation —
  previously every such cid failed emitted=false. Also drive every
  captured reveal instead of the first 16 (pages with more reveals could
  never pass; this was the spurious "reveals 16/24").
- render/harness: the validator copies app sources over the preinstalled
  harness without installing deps, so a Lottie clone's injected
  lottie-web crashed webpack ("build failed" with no real signal).
  Missing app deps are now installed into the harness pinned to the
  app's exact version (--no-save, idempotent), with a clear gate issue
  on install failure.

Cotton motion gate: 33 static + 10 replayed + 24/24 reveals -> pass.
Cropin home build gate: pass (was webpack Module not found).
116/116 compiler tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 20:22:42 -07:00
Samraaj BathandClaude Fable 5 7f99b76f66 Fix build-breaking ident rewrite, blank-iframe grafting, and layout-gate regressions
Round-3 fixes from gate validation + human visual review of fresh
cropin.com and ooni.com clones:

- app.ts: section data-var rename used an unanchored substring replace,
  so Tile2_data matched inside MediaTile2_data and emitted a corrupted
  Mediatile2Data usage (ReferenceError at prerender). Word-boundary
  regex; every map site now shares one derivation.
- graft.ts: about:blank iframes were blanket-skipped, missing the
  Klaviyo newsletter form (mounted into a blank same-origin frame via
  JS) — the audit's #1 complaint. Blank frames now graft; the
  visibility gate still excludes 0-size tracking pixels.
- walker.ts: isVisible() now rejects boxes wholly outside the viewport
  (off-left always; off-right only when the page isn't horizontally
  scrollable; fixed boxes fully above/below), so a closed slide-in
  drawer's contents no longer count as expected text (91.8% -> 93.4%).
- css.ts: four sizing-regime corrections — pin captured px for
  circular shrink-0 slides (Splide slide chain collapsed 0x0);
  flex-basis:100% for full-width shrink-0 slides; keep fixed-px grid
  templates for scrolling track lists (repeat(N,1fr) squished a
  50-track carousel); single full-bleed fixed track -> minmax(0,1fr);
  keep authored heights whose in-flow children are fill children
  (aspect-video heroes inflated 240 -> 720px); width:100% for
  inset-spanned aspect boxes.

Gate scores: ooni home 88.7 -> 93.3 (responsive 32 fails -> pass),
pizza-ovens 90.8 -> 97.6 (perceptual 46.7% -> 17.2%).
107/107 compiler tests, all workspaces green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 19:42:34 -07:00
Samraaj BathandClaude Fable 5 199359d0a6 Wave 4: reveal settling + replay, 206/magic-byte media fix, hidden-geometry banding, bare-zero utility gating
Capture (4a):
- stabilize: dwell-scroll settling pass + known-library pre-reveal
  neutralization after lazy promotion, so every viewport snapshot records
  the post-reveal steady state (about-page sections no longer captured
  blanket-hidden: 24 base `invisible` wrappers -> 0)
- probeReveals: extended to the visibility + entrance-animation family;
  DittoMotion replays them (JS re-hide on mount, IntersectionObserver
  reveal, 4s force-reveal failsafe) so SSR/non-JS still shows content
- assets: 206 range-response bodies are no longer stored as full assets
  (full-fetch fallback) + video magic-byte validation - the about-page
  hero video is now a valid 6.0MB ftyp mp4 instead of 18.9KB of garbage

Generate (4b):
- css: hidden-node geometry policy - a visibility:hidden box with a 0x0
  captured bbox at a band becomes display:none there; an OCCUPYING hidden
  box gets the captured per-viewport geometry instead of the baked
  canonical one. Also covers the ancestor-hidden-at-base case (the
  cropin.com/cotton slider arrow: hide inherited from an elementor-widget
  ancestor at every width parked a desktop left:548px box inside a 375px
  viewport -> body.scrollWidth 585; now 375 on both verified pages)
- tailwind: bare-zero utility gating - font-size:0 -> text-[0px] and
  letter-spacing:0 -> tracking-[0px] (text-0/tracking-0 are silently
  invalid in Tailwind v4; fixes permanently-visible map labels on the
  cotton Global-presence section)

Verified: 87/87 compiler tests green, full-workspace suite green,
regenerated cropin.com + /cotton/ builds measure 375px scrollWidth at a
375px viewport, and a fresh /about/ clone renders all reveal sections
with scroll-replay against the live site.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 18:33:10 -07:00
Samraaj BathandClaude Fable 5 9aed2540aa Clone-fidelity fix waves 1-3 (+ wave 4 in flight): capture settling, media, iframes
Fixes from the cropin.com / ooni.com audit reviews:
- walker: preserve whitespace-only text in inline elements ("ofthe" bug);
  capture ::placeholder styles for inputs
- css: emit visibility (hidden-at-rest wordmark artifact); exempt list
  markers from inherited elision (lost bullets); ::placeholder rules
- seo: sanitize og:type to Next's enum (render crash -> dev badge leak);
  generated next.config disables devIndicators
- capture/stabilize: promote lazy-loader data attrs before snapshots
  (collapsed sections, viewport-inconsistent captures); settle autoplay
  carousels to home slide before every snapshot; force-reveal hidden
  videos for poster shots + log failures
- generate: ship downloaded video files as local <video src>; keep
  picture>source through IR prune with srcset rewrite (mobile-crop-on-
  desktop heroes); pin Tailwind named screens to computeBands boundaries
- capture/graft: capture cross-origin iframe subtrees (Klaviyo signup
  forms) with element-screenshot fallback; asset download retry +
  visual-assets-missing reporting

Checkpoint commit: wave 4 (reveal settling, 206 range-response fix,
hidden-geometry banding, bare-zero utility gating) is mid-implementation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 17:45:42 -07:00
Samraaj BathandGitHub da537e68b8 Merge pull request #9 from ion-design/lottie-animation-capture
feat(compiler): capture and replay Lottie animations
2026-07-03 14:05:40 -07:00
Samraaj Bath 13ce4b89a1 Fix Lottie replay for Next builds and fallback sources 2026-07-03 14:03:42 -07:00
Samraaj Bath 7e192863b4 Merge remote-tracking branch 'origin/main' into lottie-animation-capture 2026-07-03 13:33:03 -07:00
Samraaj BathandGitHub 905fb14e2d Merge pull request #12 from michaelgbcole/updates
Add ditto unpack CLI to turn clone result JSON into a project tree
2026-07-03 13:18:02 -07:00
Samraaj Bath e28cc57c85 Fix unpack quickstart docs and hash verification 2026-07-03 13:16:05 -07:00
Michael ColeandClaude Opus 4.8 63df38105d Make CLI success output copy-paste-safe; add --serve, docs hub, key hygiene
A successful clone printed a bare, timestamped app path that wrapped mid-word
in the terminal, so users' `cd` failed and `npm install && npm run dev` ran in
the wrong directory — a confusing failure from a successful clone. Plus there
was no first-party "see it locally" path, no central docs page, "clone" was
conflated with `git clone`, and key hygiene wasn't stated.

CLI (compiler):
- Add compiler/src/cliSummary.ts: a copy-paste-safe success block on stderr — a
  single QUOTED `cd "<app>" && npm install && npm run dev` line that survives
  terminal wrapping — plus the AGENTS.md safe-to-edit pointers (content.ts,
  components/). The machine-readable {"event":"done",...} JSON stays on stdout.
- Add --serve (npm install + npm run dev in the generated app) and --open
  (also open the browser at the detected dev URL). Wired into single + multi.
- Add writeLatestPointer(): refresh a runs/<site>/latest symlink to the newest
  run so there's a stable, timestamp-free cd/script target. The reuse/regen
  scanners already filter to digit-prefixed run dirs, so `latest` is ignored.
- Tests: cliSummary (quoting, single-line command, Next/Vite roots, stable-path
  preference, --serve/--open hint) and runsLayout (symlink write + in-place
  refresh, timestamp-free stable path).

Docs:
- Add docs/README.md as a central documentation index.
- State prominently that ditto "cloning" = generating a codebase from a live
  URL, NOT `git clone` (no source repo required), in README + docs hub.
- Add "keys are secrets: use $DITTO_API_KEY, never inline/commit, rotate
  anytime" beside the key/auth examples in README + docs/SERVICE.md.
- Document --serve/--open and the latest symlink in README + compiler/README.

Note: the live ditto.site/docs web route and the dashboard's inline-token
snippet live in the marketing-site repo and still need a change there.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 17:10:02 -04:00
Michael ColeandClaude Opus 4.8 638a0516c5 Add ditto unpack CLI to turn clone result JSON into a project tree
The REST API returns a clone as a giant `files` map JSON blob with no
first-party way to use it — users were left staring at kilobytes of
escaped JSON with no path from "you got JSON" to "here's a project".

Add packages/cli: a zero-dependency `ditto` CLI whose `unpack` command
walks the files{} map from POST /v1/clones (or GET .../result) and
writes a real project tree to disk:

- text files written from inline content;
- binary assets materialized from inline base64, else fetched from their
  reference URL using $DITTO_API_URL / $DITTO_API_KEY (--no-fetch writes
  just the text tree and lists skipped assets);
- path-traversal guards (clone results are untrusted) and sha256
  integrity checks;
- reads JSON from stdin ("-") so a curl response pipes straight in;
- clear errors for queued jobs with no files yet, and a tip pointing at
  the /bundle endpoint when assets can't be fetched.

Document the pipe-from-curl one-liner prominently next to the REST
examples in README.md and docs/SERVICE.md, add a package README, a
Repository Map row, a root `unpack` script, and a CHANGELOG entry.
Covered by 9 tests (text tree, stdin, inline base64, live URL fetch with
auth + relative-URL resolution, --no-fetch, traversal refusal, queued-job
detection, sha256 mismatch).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 15:40:28 -04:00
Samraaj BathandGitHub 4de6e244a0 Merge pull request #11 from ion-design/codex/readme-methodology-link
[codex] Add methodology doc and homepage link
2026-06-30 12:58:51 -07:00
Samraaj Bath 74219bb921 Add methodology doc and site link 2026-06-30 12:24:59 -07:00
Samraaj BathandGitHub 46d8c150d3 Merge pull request #2 from ion-design/dependabot/github_actions/actions/setup-node-6
Bump actions/setup-node from 4 to 6
2026-06-30 11:03:03 -07:00
Samraaj BathandGitHub b4d7ee6ff6 Merge pull request #10 from ion-design/codex/remove-opencode-sidecar
[codex] Remove opencode sidecar tooling
2026-06-30 10:53:29 -07:00
Samraaj Bath 893da2e332 Remove opencode sidecar tooling 2026-06-30 10:48:40 -07:00
dependabot[bot]andGitHub 9d2c411b12 Bump actions/setup-node from 4 to 6
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4 to 6.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-30 17:43:08 +00:00
Samraaj BathandGitHub bae9688e2b Merge pull request #1 from ion-design/dependabot/github_actions/actions/checkout-7
Bump actions/checkout from 4 to 7
2026-06-30 10:41:16 -07:00
Samraaj Bath d27f34bea8 Update hosted signup docs 2026-06-29 22:21:24 -07:00
devteamaegisandclaude-flow 9a89fed365 feat(compiler): Lottie in multi-page output + materialize inline animationData
Two follow-ups to the single-page Lottie support:

1. Multi-page (clone-site). generateSiteApp emitted only DittoWire; it now wires
   DittoLottie per route exactly like wires — builds the route's lottie spec,
   emits the import + JSX, writes DittoLottie.tsx once, and injects lottie-web
   into the site package.json when any route replays an animation (the write
   moved after the route loop so the dep reflects actual usage). cloneSite now
   captures motion on full route captures (motion: full) so lotties are observed;
   light sibling probes skip it. Per-route gating verified: a route with no
   animation gets no DittoLottie.

2. Inline animationData. When a lottie is only in memory (data-driven init, no
   fetchable URL), capture now writes the JSON to the assets store as a real,
   content-hashed .json so it materializes to /assets/cloned/lottie like any
   source — instead of embedding the blob in the page spec. buildLottieSpec then
   resolves it to a local path; the spec carries path, not animationData.

Verified end-to-end: a 2-page fixture emits DittoLottie only on the animated
route with lottie-web added; a data-driven inline fixture materializes
fd7c…json and the spec references it by path.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-30 00:52:09 -04:00
devteamaegisandclaude-flow 048fd8cdad feat(compiler): capture and replay Lottie animations
lottie-web renders vector animations from a JSON document at runtime. As
third-party JS it falls outside the declarative CSS path and the WAAPI / reveal /
marquee probes, so clones shipped the empty container and the animation was gone.
This adds a Lottie subset to Stage 5 motion: capture the deterministic part — the
source JSON (materialized local file, or inline animationData) plus playback
config — and emit a fixed DittoLottie client that re-mounts lottie-web on the
cid'd container.

Capture (compiler/src/capture/lottie.ts): in-page detector covering lottie-web's
registry (animationData in memory), <lottie-player>/<dotlottie-player>, Elementor
data-settings (source_json.url), and generic markup. Keyed by data-cid-cap.
motion.ts merges it into MotionCapture; capture.ts registers source URLs as assets
so the existing fallback fetch downloads + materializes them to /assets/cloned/lottie.

Generate (compiler/src/generate/lottie.ts): buildLottieSpec resolves cap->cid and
source URL->materialized local path (or embeds inline animationData), then emits
DittoLottie + wire/import helpers, mirroring DittoMotion. app.ts writes the
component, wires import+JSX, and injects lottie-web into the generated package.json.

Delivery (compiler/src/cli.ts): stripDeliveryDataCids now treats DittoLottie as a
runtime consumer, so its container keeps a semantic data-ditto-id anchor instead of
being stripped (without this the animation never finds its mount point).

Lottie-free clones stay byte-identical. Verified end-to-end: cloning a page with a
<lottie-player> scrapes the JSON, emits a wired DittoLottie, and lottie-web mounts
and plays the captured animation (rendered SVG viewBox matches the source JSON).
Unit tests cover buildLottieSpec resolution + drop rules.

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-06-30 00:30:52 -04:00
Samraaj Bath 7d0e85ddb4 Allow www signup origin 2026-06-29 20:39:57 -07:00
Samraaj Bath cf8af6d936 Add verified email API key signup 2026-06-29 20:35:16 -07:00
Samraaj Bath 49a6541b24 Add public API key signup 2026-06-29 19:53:39 -07:00
Samraaj BathandGitHub 2b9ebd9a9b Merge pull request #8 from ion-design/codex/readme-usage-guide
[codex] Simplify README usage guide
2026-06-29 16:31:56 -07:00
Samraaj Bath 12dc7d9220 Simplify README usage guide 2026-06-29 16:29:39 -07:00
Samraaj BathandGitHub ca476b1a0f Merge pull request #5 from ion-design/codex/open-source-readiness
[codex] Prepare repo for open source
2026-06-29 16:22:59 -07:00
Samraaj Bath 3f7c9ed227 Prepare repo for open source 2026-06-29 16:14:44 -07:00
dependabot[bot]andGitHub a2113214d2 Bump actions/checkout from 4 to 7
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 7.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-29 22:12:40 +00:00
Samraaj Bath 66dfdcc58d Initial commit 2026-06-29 15:11:48 -07:00