← RendemoCONTENT HISTORYWHAT CHANGED · RULE-BASED ANALYSIS
Update to Rendemo
Snapshot Sep 30, 2026 · 23:08 UTC · version 1.0.0
Collection source: not recorded for this historical snapshot.
First saved snapshot
No earlier snapshot is available to establish a change.
Compare saved observations
Download comparison JSONFull technical diff · 0 changed fields
Full snapshot data
{
"name": "sandbox-demos",
"description": "This skill should be used when creating or editing a SANDBOX DEMO — a hosted, autoplayable demo built from a site Rendemo crawled into a replica — rather than a codebase tour. Use it when the user says \"make a demo of <some website>\", gives a URL and no codebase, mentions `rendemo_crawl_site`, a crawl, a sandbox or a replica, or is authoring against an existing sandbox demo — and before `rendemo_add_sandbox_demo_step`, `rendemo_list_sandbox_pages`, `rendemo_find_in_sandbox` or `rendemo_check_sandbox_demo`. A sandbox demo writes no markers into customer source and has no lockfile to commit. Tours are reserved for codebase guidance authored with `author-a-tour`. Covers surveying what the crawl actually captured, choosing steps and target elements that survive a rebuild, writing the step card, and verifying before publish.",
"included_files": [],
"skill_md_contents": "---\r\nname: sandbox-demos\r\ndescription: This skill should be used when creating or editing a SANDBOX DEMO — a hosted, autoplayable demo built from a site Rendemo crawled into a replica — rather than a codebase tour. Use it when the user says \"make a demo of <some website>\", gives a URL and no codebase, mentions `rendemo_crawl_site`, a crawl, a sandbox or a replica, or is authoring against an existing sandbox demo — and before `rendemo_add_sandbox_demo_step`, `rendemo_list_sandbox_pages`, `rendemo_find_in_sandbox` or `rendemo_check_sandbox_demo`. A sandbox demo writes no markers into customer source and has no lockfile to commit. Tours are reserved for codebase guidance authored with `author-a-tour`. Covers surveying what the crawl actually captured, choosing steps and target elements that survive a rebuild, writing the step card, and verifying before publish.\r\nversion: 2.4.0\r\n---\r\n\r\n<!-- GENERATED by `npm run skills:generate` from lib/copilot/skills/sandbox-demos/SKILL.md.\r\n Edit that file, not this one. `npm run skills:check` fails the build if they have drifted. -->\r\n\r\n# Sandbox demos\r\n\r\nA sandbox demo and a codebase tour can both guide a visitor step by step, but they are different\r\nproducts and are authored almost nothing alike. On a codebase tour you write a `data-rendemo` marker into the customer's source and the\r\noverlay finds it. **A sandbox has no source anyone can edit** — its pages are a build artifact,\r\nextracted from a crawl and served from our storage — so a sandbox step instead records the target\r\nelement's identifying *facts*, and a build pass re-resolves those facts against the current markup\r\nand stamps the marker itself, at publish and again after every rebuild.\r\n\r\nEverything below follows from that. You are not writing markers; you are choosing elements durable\r\nenough to be re-found later, and you cannot see the page — you are reading an index of it.\r\n\r\n`demo-craft` governs how the finished demo behaves: cards, emphasis, pointers, effects, and the\r\nplayer. Read it too. This skill covers what is unique to a sandbox-backed demo: surveying replica\r\npages, choosing durable targets, validating them after rebuilds, and publishing the hosted result.\r\n\r\n## Ask before you dress it\r\n\r\nThe look of the demo is the author's call, not yours — and \"the author\" is the person you are\r\ntalking to, not the model's taste. Before styling anything (and ideally while the crawl runs, when\r\nyou have their attention and nothing else to do), ask two or three short questions and then commit\r\nthe answers with `rendemo_set_demo_presentation_theme`:\r\n\r\n1. **Vibe** — offer the two or three themes that fit their product and let them pick. The menu:\r\n - `broadsheet` — editorial, hairline rules, paper tone. Analytics, research, fintech; anything sold on credibility.\r\n - `console` — terminal: monospace labels, hard corners. Developer tools, infra, security, APIs.\r\n - `atrium` — glassy, architectural, mostly negative space. Premium B2B with a design-conscious buyer.\r\n - `ledger` — spreadsheet discipline, tabular figures. Fintech, accounting, insurance, compliance.\r\n - `kiosk` — presentation scale, type sized for a room. Sales calls, trade-show loops, TV playback.\r\n - `sticker` — anti-corporate: solid ink borders, hard offset shadows. PLG, consumer, creator tools.\r\n - `vellum` — the calm one, built for light product UI. Wellness, HR, education, health.\r\n - `signal` — the utility default, tuned for unknown products at unknown embed sizes.\r\n - `marquee` — cinematic: letterboxed, chapter cards, no persistent chrome. Launch films, landing-page autoplay.\r\n - `blueprint` — technical drawing: thin strokes, numbered callouts. Hardware, robotics, logistics, IoT.\r\n2. **Motion** — `motionIntensity`: `calm` (settle, no theatre), `cinematic` (the default sweep), or\r\n `kinetic` (fast, for short attention). One sentence: \"calm, cinematic, or fast and punchy?\"\r\n3. **Accent** — `accentMode`: `brand` (their colour does the pointing — the usual right answer),\r\n `neutral`, or `contrast`. If they name a hex, that is a brand kit question (`rendemo_design_brand_style`).\r\n\r\nTwo rules around the questions. **Suggest, don't interrogate**: lead with your read (\"your site is\r\ndark and developer-facing — I'd put this in `console` with cinematic motion; want that or something\r\ncalmer?\") so the person can just say yes. And **never silently default**: `signal` exists for when\r\nthey truly don't care, but they get asked once before you decide that.\r\n\r\n## Getting the sandbox\r\n\r\n**The first step is a question, not a crawl.** Ask the author whether the demo should show anything\r\nbehind a login — their dashboard, their account, their data. People rarely volunteer this, and the\r\npublic marketing site is rarely the product they actually want demoed. Behind a login (or unsure)\r\nmeans `rendemo_start_browser_crawl` and the extension capture flow below; public pages only means\r\n`rendemo_crawl_site`.\r\n\r\n`rendemo_crawl_site` walks a public site's `sitemap.xml` with headless Chrome and chains a sandbox\r\nbuild behind it. Two facts govern how you wait:\r\n\r\n- **It is slow and the slowness is normal.** 40 pages took 239 seconds in production, and the\r\n sandbox build takes several minutes more. Poll `rendemo_get_crawl_status` every 15–30 seconds and\r\n trust its `elapsedSeconds` over your own sense of how long you have been waiting. Do not conclude\r\n a crawl has failed because it is still running.\r\n- **The sandbox comes back unpublished, and authoring never needs it published.** Every read tool\r\n and `rendemo_add_sandbox_demo_step` work on a draft sandbox. Publishing it puts a replica of someone\r\n else's site on a public URL and spends a slot from the plan's shared published-artifact budget, so\r\n it is a deliberate act with its own moment — see **Publish order**, which is *not* \"never\".\r\n\r\nRe-crawling an existing crawl-sourced project keeps its sandbox id and slug, so pass `projectId`\r\nwhen refreshing a site that already backs a demo. A fresh crawl of the same URL is a different\r\nsandbox, and demos pointed at the old one keep pointing at the old one.\r\n\r\n**Re-crawling a sandbox that is already PUBLISHED does not replace the live pages.** It writes a\r\n*staged* build and leaves the live replica exactly as it was — a re-crawl is a new recording of a\r\nsite that may have changed since a human reviewed it, so it cannot reach viewers on its own. The job\r\nreports success and the served pages do not move; that is the design, not a failure. Read the staged\r\nbuild with `rendemo_review_staged_sandbox` and apply it with `rendemo_promote_staged_sandbox` — see\r\n**Applying a re-crawl** below. (A DRAFT sandbox has nothing to protect, so its rebuild replaces the\r\nreplica directly and nothing stages. So does a rebuild of an extension-recorded sandbox, which\r\nre-extracts the very recording a human already reviewed — that is how you apply a new redact\r\npattern.)\r\n\r\n**When the headless crawl cannot reach the pages, drive a browser instead.** A sitemap crawl fetches\r\nas a stranger's bot: it never sees anything behind a login, and it honours `robots.txt`, which rules\r\nout a great many of the products worth a sandbox (`app.superx.so` serves `Disallow: /`). If the\r\ncrawl comes back with everything dropped as `robots-disallow`, or with N copies of a sign-in screen,\r\nthat is the signal — not a reason to retry it.\r\n\r\n`rendemo_start_browser_crawl` hands you a crawl id, a **capture code**, and a `snippet` — and it is\r\nthe right call **whether or not you can drive a browser**. Never tell the author a signed-in\r\nwalkthrough is impossible from chat, and never send them to a cloud or hosted browser (none can run\r\nthe capture snippet):\r\n\r\n- **You have no browser tools** (ChatGPT and most clients): call it anyway, give the author the\r\n capture code, and have them paste it into the Rendemo Chrome extension's *Capture pages for a\r\n sandbox* popup mode, signed in, on the site. That paste is their whole job: from then on\r\n `rendemo_capture_pages({ crawlId, url, urls })` opens each url you name in that signed-in tab and\r\n captures it, holding the connection open while it works. Call it again with no `urls` while pages\r\n are in flight; a url refused as a login wall needs them to sign in there first. They can still\r\n click *Capture this page* for anything you would not know to ask for. Then you finish the crawl.\r\n- **You can drive the author's own browser** — their real, local browser, already signed in: per\r\n page — navigate, **let it finish rendering**, then evaluate the snippet with that page's index.\r\n The page uploads itself and returns a small receipt. A cloud or hosted browser you opened\r\n yourself is not that browser: it holds none of their sessions, and Google refuses sign-ins from\r\n automated browsers — asking the author to log in inside one strands them at a login wall.\r\n\r\nEither way, close with `rendemo_finish_browser_crawl`, which queues the same sandbox build the\r\nheadless path ends in — so `rendemo_get_crawl_status` and everything downstream behave identically.\r\n\r\nThe settle wait is the part that goes wrong. The recorder snapshots whatever is on screen the\r\ninstant it arms, and extraction dedups on that snapshot — so arming before the page has rendered\r\ncaptures an empty shell, and every empty shell collapses into one. That is the one-page sandbox\r\nfailure, and it looks like a successful crawl.\r\n\r\n## Knowing what you are working with\r\n\r\nThree tools stand in for list, grep and read. Use them in that order; each exists because the one\r\nbefore it cannot answer the question.\r\n\r\n**`rendemo_list_sandbox_pages` — always first.** Returns every page's file name (the exact address\r\nthe other two expect), the URL it was recorded from, its size in bytes, and which single page is the\r\n`entry` a visitor lands on. It never opens a page, so it cannot tell you what is *on* one. What it\r\ntells you is the shape of the capture: how many pages, which sections of the site survived, and\r\nwhere the weight is.\r\n\r\n**This list is the whole world.** A page that is not in it does not exist for this demo — not\r\n\"harder to reach\", genuinely absent. A crawl driven by `sitemap.xml` routinely misses everything\r\nbehind a login, everything rendered only after an interaction, and anything the sitemap omits. So\r\nread the list as a statement of what the demo *can* be about, before you have a story in mind. If\r\nthe sequence the customer asked for needs a page that was never captured, say so then — not after\r\nfive steps are authored.\r\n\r\n**`rendemo_find_in_sandbox` — grep one page.** `pattern` is a literal, case-insensitive substring,\r\nnever a regex: paste back a button's label or a fragment of an href without escaping anything. It\r\nsearches the whole page, not the read window, so it finds text that sits 4,000 lines down. Every hit\r\ncarries its line number and a **nodeId** — the sandbox's answer to a marker, and the address a step\r\nnames as its target. This is the fastest path from \"the pricing page must have a Start free trial\r\nbutton\" to a target.\r\n\r\n**`rendemo_read_sandbox_page` — read a bounded slice.** 200 lines by default, 400 maximum, ever: a\r\ncaptured page can reach several megabytes and 175,000 elements, and returning one whole would be\r\nuseless to you and expensive for everyone. Each line is one element's start tag with its attributes\r\nverbatim, indented by nesting depth, plus that element's own leading text and its nodeId. `offset`\r\nis a 1-based line number, and the reply reports `totalLines` plus the offset to resume at.\r\n\r\nReach for `read` when you need **structure** — what surrounds a candidate, whether the thing you\r\nfound is the button or a wrapper three levels up — and for `find` when you already know the text.\r\nPaging an entire multi-megabyte page 400 lines at a time is almost always the wrong instinct: read\r\nthe entry page's first few hundred lines to learn the site's structural vocabulary (what its nav,\r\nits cards, its buttons look like in markup), then grep the rest by label.\r\n\r\n## Choosing steps worth taking\r\n\r\nThis is the part no tool checks and the part that decides whether the demo is any good. A demo is\r\nnot a table of contents for the crawl. Some discipline that survives contact with a real replica:\r\n\r\n- **Follow one visitor's path, and start where they start.** The `entry` page is where the demo\r\n opens; a sequence that begins three pages in reads as arriving mid-sentence. Steps may move\r\n between pages — a sandbox step's route is that page's replica address — but each move should be\r\n one a visitor would actually make, in the order they would make it.\r\n- **Every step must answer \"and then what?\"** The failure mode of an auto-authored demo is a step\r\n per landmark: here is the nav, here is the hero, here is the footer. Those are locations, not\r\n moments. A step earns its place by showing something the visitor would not have understood on\r\n their own — what a control does, what a number means, why this screen is where the work happens.\r\n- **Chrome is not content.** Cookie banners, consent dialogs, newsletter modals, social icons,\r\n footers and legal links all survive a crawl and are all present in the markup. None is ever the\r\n subject of a step.\r\n- **Three to seven steps is a focused demo. Fifteen is a sitemap with cards on it.** Spend the count on the\r\n path that reaches the thing the site is selling.\r\n- **A replica is static.** Nothing you point at changes state: forms do not submit, filters do not\r\n filter, and a link to a page the crawl never captured goes nowhere. Prefer `explain` framing over\r\n a `do: \"click\"` that promises an outcome the sandbox cannot deliver, and never build a step whose\r\n payoff is a page that is not in the manifest.\r\n\r\n## Choosing an element that will still be there\r\n\r\nThe step's target has to be re-findable after the sandbox rebuilds and every byte of the page\r\nchanges underneath it. The server enforces a floor and you should aim well above it.\r\n\r\n**The floor, enforced at authoring time:** an element is refused unless it carries at least one of\r\n`id`, `data-testid`, `aria-label`, `name`, `placeholder`, `href`, or visible **text**. A nearby\r\nheading does not count — it is context that breaks a tie between two candidates, not identity. The\r\nrefusal says exactly which of these are missing, so a bare `<div>` fails immediately rather than\r\nresolving today and vanishing at the next rebuild.\r\n\r\nAbove the floor, what actually makes a target good:\r\n\r\n- **Point at the control, not its wrapper.** A sandbox demo's geometry comes from the resolved replica element: the highlight is exactly the\r\n element you named, and there is no `rect` to tighten afterwards the way a demo has. A `spotlight`\r\n that reads as vague is almost always a step pointed one or two levels too high. Read the\r\n surrounding lines and pick the `<button>`, not the `<div>` that lays it out.\r\n- **Prefer an id or a test id to text.** Text is real identity and often the only thing available on\r\n a crawled marketing page, but it is also the thing most likely to be edited between crawls.\r\n- **Two steps may not share an element.** Both anchors resolve to the same start tag, only one\r\n marker can be stamped onto it, and the later step reports `claimed` — a real failure with an\r\n obvious fix: retarget one of them.\r\n- **Ambiguity is scored, not guessed.** Two near-identical candidates come back `ambiguous` with the\r\n runner-up's score, which is your signal that the target needs something more specific.\r\n\r\n**Node ids are recomputed on every read and never stored.** A nodeId from a read you did before a\r\nrebuild — or before any other change to that page — is not an address any more, and the refusal\r\nmessage will tell you so. Re-find, then author. Do not carry node ids across a re-crawl.\r\n\r\n## Writing the card\r\n\r\nA sandbox demo uses the normal demo player and its authored card surface. These render:\r\n\r\n`title` · `blurb` · `eyebrow` · `advanceLabel` · `successMessage` · `recoveryHint` ·\r\n`presentation` · `emphasis` · `emphasisColor` · `choices`\r\n\r\nEverything else — `variant`, `size`, `width`, `placement`, `image`, `button`, `narration`, `rect`,\r\n`showProgress`, every replay-camera field — saves silently and no visitor ever sees it.\r\n`rendemo_update_step` and `rendemo_style_steps` name the ignored fields in their result rather than\r\nconfirming them; read that report instead of assuming the change landed.\r\n\r\n`rendemo_add_sandbox_demo_step` takes `title`, `blurb`, `emphasis` and `lens` inline — dress the step as you\r\nadd it rather than leaving every step on the bare default and fixing it later. The rest go on with\r\n`rendemo_update_step`, and the card recipe with `rendemo_set_step_presentation`.\r\n\r\nHow to write the two that matter:\r\n\r\n- **`title` names what the visitor is looking at, in their words, not the site's.** It is not the\r\n element's label repeated back — a card reading \"Start free trial\" beside a button reading \"Start\r\n free trial\" has spent a step to say nothing.\r\n- **`blurb` earns the step.** One or two sentences carrying the thing that is not visible: what\r\n happens next, what the number means, why this is the screen where the work gets done. If the blurb\r\n can be deleted without the visitor losing anything, delete the step.\r\n- **`advanceLabel` should say what the visitor is about to do** (\"See the dashboard\") rather than\r\n \"Next\", on any step where the next step moves pages.\r\n- **`successMessage` and `recoveryHint` only matter on a step with a `do`.** On a static replica most\r\n steps have no `do` at all, and writing a recovery hint for an action nobody performs is noise.\r\n- **`stepType` renders nowhere, and is not inert.** On a sandbox demo it is what gates the camera:\r\n only an `explain` step is eligible for `rendemo_direct_step`'s `shot` / `settleShot`. A step left\r\n `action` stays at 1x no matter how it is framed. Camera moves are worth two or three steps in a\r\n demo and no more.\r\n\r\nThe mark follows the same scarcity rule as everywhere else: `ring` for most steps, `wash` or\r\n`dim-siblings` for a region, and `spotlight` for the one or two steps the demo exists to reach. A\r\ndim on every step is shouting.\r\n\r\n## Verify, then publish in the right order\r\n\r\n**1. `rendemo_check_sandbox_demo`.** Re-scores every sandbox-anchored step against the sandbox's\r\ncurrent pages using the same scorer the real stamping pass uses, and writes nothing. A step reported\r\n`resolved` will stamp; `ambiguous` or `absent` will not. Run it after any rebuild or re-crawl and\r\nbefore publishing. It refuses on a demo with no sandbox-anchored steps, which is itself a useful\r\nsignal that you authored `route` steps by mistake.\r\n\r\n**2. Publish the source SANDBOX.** Authoring and validation work while it is private, but an external\r\ndraft-preview link needs a hosted page to open. Publishing the source makes its replica world-visible\r\nand spends a published-artifact slot, so ask first.\r\n\r\n**3. `rendemo_get_sandbox_demo_preview`** when a reviewer is ready to look. The link is a bearer token —\r\nanyone holding it sees the draft without signing in — and it expires 30 minutes after issue. Mint it\r\nwhen they are ready, not in advance.\r\n\r\n**4. Publish the sandbox demo.** The demo has nothing to run on until the replica it points at is live, so\r\n`rendemo_publish_demo` on a sandbox demo returns **409 `sandbox_not_published`** if the sandbox is\r\nstill a draft or has been taken down.\r\n\r\n**5. `rendemo_review_demo_frames` — actually look at it.** Everything above this line is blind.\r\n`rendemo_check_sandbox_demo` proves a step's target still *resolves*; it says nothing about whether\r\nthe card can be read, whether it covers the very element it points at, or whether the emphasis\r\nrendered at all. On a crawl-built demo those are the failures that actually happen, because the card\r\nis landing on someone else's page design rather than one you chose.\r\n\r\nThis photographs the live demo at each step and hands you the images. Look, fix what is genuinely\r\nwrong, republish — the slug is kept, so the link survives. Two rules: the camera **cannot see blur**\r\n(headless Chrome drops `backdrop-filter`, so a glassy theme photographs flatter than it renders —\r\nnever \"fix\" that), and a step that reads well needs nothing.\r\n\r\nPoint it at the sandbox DEMO — the project whose steps you authored — not at the source sandbox,\r\nwhich has no steps to photograph.\r\n\r\nFour more refusals, all deliberate, all 422 unless noted:\r\n\r\n- **`sandbox_tour_mixed_targets`** — legacy wire code: some steps are sandbox-shaped and some are plain `route` steps.\r\n `rendemo_add_sandbox_demo_step` only writes sandbox-shaped steps, so this normally identifies an\r\n older mixed project. The response names every step and its\r\n shape.\r\n- **`sandbox_tour_mixed_sandboxes`** — legacy wire code: the steps name more than one sandbox. Refused rather than\r\n quietly using the first, because a page id is unique only within one capture, so a step from\r\n another sandbox can coincidentally score against the wrong one's HTML.\r\n- **`sandbox_tour_unresolved`** — legacy wire code: at least one step did not stamp. The issues list gives each\r\n marker, its page and its code; this is exactly what step 1 exists to catch earlier.\r\n- **`sandbox_strip_refused`** (409) — a page carrying a stale marker from a previous demo version\r\n declined the rewrite because removing it would have changed more than the marker attribute. Not a\r\n step failure; a refusal to corrupt the replica.\r\n\r\nAfter any step change the demo must be published again — until then the live demo still describes\r\nthe old shape.\r\n\r\n## Applying a re-crawl to a published sandbox\r\n\r\nA re-crawl of a published sandbox stages instead of replacing (see **Getting the sandbox**), so\r\nthere is one extra step and it is deliberately a human one.\r\n\r\n**1. `rendemo_review_staged_sandbox`.** Read-only. Says whether a staged build is pending, when it\r\nfinished, how many pages it holds, what the redaction pass found and which concerns were raised. If\r\nit reports nothing pending, either the sandbox was a draft (the rebuild already replaced the replica)\r\nor the build has already been promoted.\r\n\r\n**2. Actually look.** A redaction report with no concerns is not a review. The detector only flags a\r\nperson's name when it sits beside a dollar amount, so an all-zeros report routinely ships with real\r\nnames still in the pages — that has happened. Read pages with `rendemo_read_sandbox_page`, or put\r\nthe report in front of the person who owns the site, before deciding.\r\n\r\n**3. `rendemo_promote_staged_sandbox`.** Copies the staged pages over the live replica; every viewer\r\nsees the new crawl from that moment. It takes `acknowledgeReviewedStagedBuild: true`, which is the\r\nclaim that step 2 happened — do not set it on your own judgement of a clean report. Promotion\r\nre-verifies server-side that the staged pages are marked redacted and refuses if they are not.\r\nIt publishes nothing and spends no published-artifact budget: the sandbox was already live, this\r\nonly changes which build is. **Not reversible** — the replaced build is not kept.\r\n\r\n**4. Read what it could not re-point.** A re-crawl shifts every page id, so promotion re-points each\r\nstep at the new pages as part of the same call and reports what it managed:\r\n`plans.draftStepsUnresolved` is the count it could not map. Those steps will report `absent` — find\r\nthem fresh with `rendemo_find_in_sandbox` and re-target them.\r\n\r\n**5. Re-check every demo built on that sandbox, then republish it.** Run\r\n`rendemo_check_sandbox_demo` even when nothing was reported unresolved: re-pointing gets a step onto\r\nthe right *page*, and whether its target element is still findable *on* that page is a separate\r\nquestion only the scorer answers.\r\n\r\nDo **not** reach for `rendemo_unpublish_sandbox` → re-crawl → `rendemo_publish_sandbox`. That was\r\nthe old workaround and it takes the demo off the air in between.\r\n\r\n## Tools\r\n\r\n`rendemo_crawl_site` (or `rendemo_start_browser_crawl` → `rendemo_finish_browser_crawl` when the\r\npages need a signed-in browser) → `rendemo_get_crawl_status` → `rendemo_list_sandbox_pages` →\r\n`rendemo_find_in_sandbox` / `rendemo_read_sandbox_page` → `rendemo_create_sandbox_demo` →\r\n`rendemo_add_sandbox_demo_step` (`sandbox: { demoId, page, node }`) → `rendemo_update_step` /\r\n`rendemo_set_step_presentation` / `rendemo_direct_step` → `rendemo_check_sandbox_demo` →\r\n`rendemo_get_sandbox_demo_preview` → `rendemo_publish_sandbox` → `rendemo_publish_demo` →\r\n`rendemo_review_demo_frames` (look at it, fix, republish).\r\n\r\nRefreshing a published sandbox adds one more: `rendemo_crawl_site` (with `projectId`) →\r\n`rendemo_get_crawl_status` → `rendemo_review_staged_sandbox` → `rendemo_promote_staged_sandbox` →\r\n`rendemo_check_sandbox_demo` → `rendemo_publish_demo`.\r\n\r\n`sandbox.demoId` is the **source sandbox's** id, never the sandbox-demo project's own — the two are different rows\r\nand passing the wrong one reads as \"not found in this workspace\".\r\n"
}SHA-256: eb7c0ab2f5d92204bf792f33fde12782b8b971a46d8aa90906af04df261e1541