@contentsquare/wizard 2.0.0 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -27,7 +27,7 @@ The agent detects your framework, installs `@contentsquare/tag-sdk`, wires up th
27
27
 
28
28
  ### Prerequisites
29
29
 
30
- - Node.js >= 18 (npm and `npx` ship with Node).
30
+ - Node.js >= 20 (npm and `npx` ship with Node).
31
31
  - An AI coding agent (GitHub Copilot in VS Code, Cursor, or Claude Code).
32
32
  - For `verify`: a desktop with a graphical display. It uses your installed Chrome/Edge, or downloads Chromium on demand with `--install-browser`.
33
33
 
package/dist/cli.js CHANGED
@@ -787,22 +787,23 @@ function once(fn) {
787
787
  }
788
788
 
789
789
  // src/commands/verify/analyze.ts
790
- var NAV_BEACON_WINDOW_MS = 6e3;
791
- var NAV_DEDUPE_WINDOW_MS = 400;
792
790
  var SPA_TRACKING_RECOMMENDATION = 'Some in-app route changes did not fire a pageview. If this is a single-page app, enable "Tracking URL Changes" in the Contentsquare app (Project and Users \u2192 Tracking URL Changes).';
791
+ var CSP_RECOMMENDATION = "Content-Security-Policy violations were detected. The tag still loaded and fired pageviews, but update your CSP to explicitly allow Contentsquare so tracking isn't blocked in stricter environments.";
793
792
  function analyze(input) {
794
793
  const { url, projectId, tagId, navEvents, csRequests, violations } = input;
795
794
  const scripts = csRequests.filter((r) => r.kind === "script");
796
795
  const beacons = csRequests.filter((r) => r.kind === "beacon");
797
796
  const tagScriptLoaded = scripts.length > 0;
798
797
  const tagIdMismatch = tagScriptLoaded && !scripts.some((s) => s.url.includes(tagId));
799
- const navs = dropHydrationNav(collapseDuplicateNavs(navEvents), url);
800
- const firstNavTs = navs[0]?.ts ?? Infinity;
801
- const initialPageview = beacons.some((b) => b.ts <= firstNavTs);
802
- const navigations = navs.map((nav) => ({
798
+ const pageviewBeacons = beacons.filter((b) => isPageviewBeacon(b.url));
799
+ const beaconPages = new Set(
800
+ pageviewBeacons.map((b) => beaconPageUrl(b.url)).filter((p) => p !== null).map(normalizePage)
801
+ );
802
+ const initialPageview = pageviewBeacons.length > 0;
803
+ const navigations = distinctRoutes(navEvents, url).map((nav) => ({
803
804
  url: nav.url,
804
805
  type: nav.type,
805
- pageviewFired: firedPageviewAfter(beacons, nav.ts)
806
+ pageviewFired: beaconPages.has(normalizePage(nav.url))
806
807
  }));
807
808
  const navigationsWithPageview = navigations.filter(
808
809
  (n) => n.pageviewFired
@@ -829,24 +830,39 @@ function analyze(input) {
829
830
  recommendation
830
831
  };
831
832
  }
832
- function collapseDuplicateNavs(navEvents) {
833
- const navs = [];
833
+ function distinctRoutes(navEvents, landingUrl) {
834
+ const landing = normalizePage(landingUrl);
835
+ const seen = /* @__PURE__ */ new Set([landing]);
836
+ const out = [];
834
837
  for (const ev of navEvents) {
835
- const prev = navs[navs.length - 1];
836
- if (prev && prev.url === ev.url && ev.ts - prev.ts < NAV_DEDUPE_WINDOW_MS)
837
- continue;
838
- navs.push(ev);
838
+ const key = normalizePage(ev.url);
839
+ if (seen.has(key)) continue;
840
+ seen.add(key);
841
+ out.push(ev);
839
842
  }
840
- return navs;
843
+ return out;
841
844
  }
842
- function dropHydrationNav(navs, landingUrl) {
843
- const sameUrl = (a, b) => a.replace(/\/+$/, "") === b.replace(/\/+$/, "");
844
- return navs.length > 0 && sameUrl(navs[0].url, landingUrl) ? navs.slice(1) : navs;
845
+ function isPageviewBeacon(beaconUrl) {
846
+ try {
847
+ return new URL(beaconUrl).pathname.replace(/\/+$/, "").endsWith("/pageview");
848
+ } catch {
849
+ return false;
850
+ }
845
851
  }
846
- function firedPageviewAfter(beacons, navTs) {
847
- return beacons.some(
848
- (b) => b.ts > navTs && b.ts <= navTs + NAV_BEACON_WINDOW_MS
849
- );
852
+ function beaconPageUrl(beaconUrl) {
853
+ try {
854
+ return new URL(beaconUrl).searchParams.get("url");
855
+ } catch {
856
+ return null;
857
+ }
858
+ }
859
+ function normalizePage(u) {
860
+ try {
861
+ const { origin, pathname } = new URL(u);
862
+ return origin + pathname.replace(/\/+$/, "");
863
+ } catch {
864
+ return u.replace(/\/+$/, "");
865
+ }
850
866
  }
851
867
  function gradeResult(checks) {
852
868
  const {
@@ -858,11 +874,14 @@ function gradeResult(checks) {
858
874
  } = checks;
859
875
  if (!tagScriptLoaded || !initialPageview)
860
876
  return { result: "fail", recommendation: null };
861
- if (cspViolations.length > 0) return { result: "fail", recommendation: null };
862
- if (navigations.length > 0 && navigationsWithPageview < navigations.length) {
877
+ const recommendations = [];
878
+ if (cspViolations.length > 0) recommendations.push(CSP_RECOMMENDATION);
879
+ if (navigations.length > 0 && navigationsWithPageview < navigations.length)
880
+ recommendations.push(SPA_TRACKING_RECOMMENDATION);
881
+ if (recommendations.length > 0) {
863
882
  return {
864
883
  result: "pass-with-recommendation",
865
- recommendation: SPA_TRACKING_RECOMMENDATION
884
+ recommendation: recommendations.join("\n")
866
885
  };
867
886
  }
868
887
  return { result: "pass", recommendation: null };
@@ -921,7 +940,9 @@ function printHumanReport(r, log4) {
921
940
  log4.success(chalk6.green("All checks passed."));
922
941
  } else if (r.result === "pass-with-recommendation") {
923
942
  log4.warn(chalk6.yellow("Passed with a recommendation:"));
924
- log4.info(` ${r.recommendation}`);
943
+ for (const line of (r.recommendation ?? "").split("\n")) {
944
+ log4.info(` ${line}`);
945
+ }
925
946
  } else {
926
947
  log4.error(chalk6.red("Some checks failed \u2014 see above."));
927
948
  }
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/commands/status.ts","../src/commands/sorcerer.ts","../src/commands/verify/index.ts","../src/tools/state.ts","../src/tools/tag-id.ts","../src/commands/verify/logger.ts","../src/commands/verify/browser.ts","../src/commands/verify/artifact.ts","../src/commands/verify/preflight.ts","../src/commands/verify/session.ts","../src/commands/verify/inject.ts","../src/commands/verify/analyze.ts","../src/commands/verify/report.ts","../src/commands/start.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { Command } from \"commander\";\nimport { status } from \"./commands/status.js\";\nimport { verify } from \"./commands/verify/index.js\";\nimport { start } from \"./commands/start.js\";\n\nconst packageJson = JSON.parse(\n readFileSync(\n fileURLToPath(new URL(\"../package.json\", import.meta.url)),\n \"utf8\",\n ),\n) as { version: string };\n\nconst program = new Command();\n\nprogram\n .name(\"wizard-cs\")\n .description(\"AI-assisted Contentsquare tag installation and configuration\")\n .version(packageJson.version);\n\n// `start` is the onboarding entry point. `install` is kept as an alias so the\n// npm-conventional command name keeps working — both run the same CLI flow.\nfunction registerStart(name: \"start\" | \"install\"): void {\n program\n .command(name)\n .description(\n \"Set up the wizard skill so your AI agent can install the Contentsquare tag — verification runs via `verify`\",\n )\n .option(\"--dir <path>\", \"Target directory (defaults to cwd)\", process.cwd())\n .option(\n \"--tag-id <hashed>\",\n \"Hashed Contentsquare tag ID (hex, e.g. 81c677ba742d7)\",\n )\n .action(start);\n}\n\nregisterStart(\"start\");\nregisterStart(\"install\");\n\nprogram\n .command(\"status\")\n .description(\"Show the configured tag ID and the latest verification result\")\n .option(\"--dir <path>\", \"Target directory (defaults to cwd)\", process.cwd())\n .action(status);\n\nprogram\n .command(\"verify\")\n .description(\n \"Open your app in a real browser and verify the tag, CSP, and pageview coverage in one session\",\n )\n .option(\"--dir <path>\", \"Project directory (defaults to cwd)\", process.cwd())\n .option(\"--url <url>\", \"App URL to open (skips the prompt)\")\n .option(\n \"--tag-id <hashed>\",\n \"Hashed Contentsquare tag ID (hex, e.g. 81c677ba742d7)\",\n )\n .option(\n \"--install-browser\",\n \"Auto-download the Chromium engine if no browser is found\",\n )\n .option(\n \"--preflight\",\n \"Check browser availability and environment, then exit (diagnostics)\",\n )\n .option(\"--json\", \"Emit the report as JSON to stdout (for agents)\")\n .action(verify);\n\nprogram.parse();\n","import * as clack from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport path from \"node:path\";\nimport fs from \"node:fs\";\nimport { SORCERER } from \"./sorcerer.js\";\nimport type { VerifyReport } from \"./verify/index.js\";\n\ninterface StatusOptions {\n dir: string;\n}\n\nexport async function status(options: StatusOptions): Promise<void> {\n process.stdout.write(SORCERER + \"\\n\");\n const targetDir = path.resolve(options.dir);\n const stateFile = path.join(targetDir, \".cs-wizard\", \"state.json\");\n\n if (!fs.existsSync(stateFile)) {\n clack.log.error(\n `No wizard state found. Run ${chalk.cyan(\"npx @contentsquare/wizard start\")} first.`,\n );\n process.exit(1);\n }\n\n const state = JSON.parse(fs.readFileSync(stateFile, \"utf-8\"));\n\n clack.intro(chalk.bold(\"Contentsquare Wizard Status\"));\n clack.log.info(`Tag ID: ${chalk.cyan(state.tagId ?? \"unknown\")}`);\n if (state.projectId) {\n clack.log.info(`Project ID: ${chalk.cyan(state.projectId)}`);\n }\n clack.log.info(\"\");\n\n const report = readLastReport(targetDir);\n if (!report) {\n clack.log.warn(\"No verification run yet.\");\n clack.log.info(\n `Run ${chalk.cyan(\"npx @contentsquare/wizard verify\")} to check the tag in a real browser.`,\n );\n clack.outro(\"\");\n return;\n }\n\n const ok = chalk.green(\"✓\");\n const no = chalk.red(\"✗\");\n const warn = chalk.yellow(\"!\");\n\n clack.log.step(chalk.bold(\"Latest verification\"));\n clack.log.info(`URL: ${chalk.cyan(report.url)}`);\n clack.log.info(`${report.tagScriptLoaded ? ok : no} Tag script loaded`);\n clack.log.info(\n `${report.initialPageview ? ok : no} First pageview sent on load`,\n );\n\n if (report.navigations.length === 0) {\n clack.log.info(`${warn} No in-app route changes recorded`);\n } else {\n const icon =\n report.navigationsWithPageview === report.navigations.length ? ok : warn;\n clack.log.info(\n `${icon} Pageviews on navigation: ${report.navigationsWithPageview}/${report.navigations.length}`,\n );\n }\n\n clack.log.info(\n report.cspViolations.length === 0\n ? `${ok} No CSP violations`\n : `${no} CSP violations: ${report.cspViolations.length}`,\n );\n\n clack.log.info(\"\");\n if (report.result === \"pass\") {\n clack.log.success(chalk.green(\"Result: pass\"));\n } else if (report.result === \"pass-with-recommendation\") {\n clack.log.warn(chalk.yellow(\"Result: pass with a recommendation\"));\n if (report.recommendation) clack.log.info(` ${report.recommendation}`);\n } else {\n clack.log.error(chalk.red(\"Result: fail\"));\n }\n\n clack.outro(\"\");\n}\n\nfunction readLastReport(targetDir: string): VerifyReport | null {\n const reportFile = path.join(targetDir, \".cs-wizard\", \"last-report.json\");\n if (!fs.existsSync(reportFile)) return null;\n try {\n return JSON.parse(fs.readFileSync(reportFile, \"utf-8\")) as VerifyReport;\n } catch {\n return null;\n }\n}\n","import chalk from \"chalk\";\n\nexport const SORCERER =\n chalk.magenta(`\n ____\n .'* *.'\n __/_*_*(_\n / _______ \\\\\n _\\\\_)/___\\\\(_/_\n / _((\\\\- -/))_ \\\\\n \\\\ \\\\())(-)(()/ /\n ' \\\\(((()))/ '\n / ' \\\\)).))/ ' \\\\\n / _ \\\\ - | - /_ \\\\\n ( ( .;''';. .' )\n _\\\\\"__ / )\\\\ __\"/_\n \\\\/ \\\\ ' / \\\\/\n .' '...' ' )\n / / | \\\\ \\\\\n / . . . \\\\\n / . . \\\\\n / / | \\\\ \\\\\n .' / b '. '.\n _.-' / Bb '-. '-._\n _.-' | BBb '-. '-.\n(________mrf\\\\____.dBBBb.________)____)\n`) +\n chalk.bold.magenta(\"\\n CS Sorcerer\") +\n chalk.dim('\\n \"Your tag shall be cast.\"\\n');\n","import * as clack from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport path from \"node:path\";\nimport fs from \"node:fs\";\nimport { readState } from \"../../tools/state.js\";\nimport { normalizeTagId, validateTagId } from \"../../tools/tag-id.js\";\nimport type { VerifyOptions } from \"./types.js\";\nimport { makeLogger, fail, emitStdout } from \"./logger.js\";\nimport { acquireBrowser, handleNoDisplay, closeAndExit } from \"./browser.js\";\nimport { runPreflight } from \"./preflight.js\";\nimport { runVerifySession } from \"./session.js\";\nimport { analyze } from \"./analyze.js\";\nimport { printHumanReport } from \"./report.js\";\n\n// Public surface kept stable for callers (cli.ts) and consumers/tests.\nexport type { VerifyReport } from \"./types.js\";\nexport { analyze } from \"./analyze.js\";\nexport { historyHookScript, overlayScript } from \"./inject.js\";\n\nexport async function verify(options: VerifyOptions): Promise<void> {\n const targetDir = path.resolve(options.dir);\n const log = makeLogger(!!options.json);\n\n // --- Diagnostics-only mode: report the browser environment and exit ---\n if (options.preflight) {\n await runPreflight(targetDir, options, log);\n return;\n }\n\n const tagId = await resolveTagId(options, targetDir);\n const rawProjectId = readState(targetDir)?.projectId;\n const projectId =\n rawProjectId !== null && rawProjectId !== undefined\n ? String(rawProjectId).trim()\n : null;\n const url = await resolveUrl(options);\n\n log.info(`Tag ID: ${chalk.cyan(tagId)}`);\n log.info(`Opening: ${chalk.cyan(url)}`);\n\n // --- Acquire a real browser (system Chrome/Edge first, then bundled) ---\n // verify opens a visible window, so a headless Linux box (no display) can't run it.\n if (\n process.platform === \"linux\" &&\n !process.env.DISPLAY &&\n !process.env.WAYLAND_DISPLAY\n ) {\n handleNoDisplay(options, log, targetDir);\n }\n const browser = await acquireBrowser(options, log, targetDir);\n\n const trace = await runVerifySession(browser, url, log);\n\n const report = analyze({ url, projectId, tagId, ...trace });\n\n // Persist a single throwaway report (not the old stateful checklist).\n const reportPath = path.join(targetDir, \".cs-wizard\", \"last-report.json\");\n fs.mkdirSync(path.dirname(reportPath), { recursive: true });\n fs.writeFileSync(reportPath, JSON.stringify(report, null, 2));\n\n if (options.json) {\n emitStdout(JSON.stringify(report, null, 2) + \"\\n\");\n return closeAndExit(browser, report.result === \"fail\" ? 1 : 0);\n }\n\n printHumanReport(report, log);\n // Machine-readable block so an agent can parse stdout deterministically.\n emitStdout(\n \"\\n```json cs-wizard-report\\n\" + JSON.stringify(report) + \"\\n```\\n\",\n );\n return closeAndExit(browser, report.result === \"fail\" ? 1 : 0);\n}\n\n/** Resolve the tag id from --tag-id → state → an interactive prompt. */\nasync function resolveTagId(\n options: VerifyOptions,\n targetDir: string,\n): Promise<string> {\n const state = readState(targetDir);\n\n if (options.tagId) {\n if (validateTagId(options.tagId)) {\n fail(\n `--tag-id must be the hashed tag ID (hex, ~13 chars, lowercase), got: ${options.tagId}`,\n );\n }\n return normalizeTagId(options.tagId);\n }\n if (state?.tagId) return state.tagId as string;\n\n if (options.json) {\n fail(\n \"No tag ID found. Run `wizard start` first, or pass --tag-id <hashed>.\",\n );\n }\n const answer = await clack.text({\n message:\n \"Enter your Contentsquare tag ID (hashed hex, e.g. 81c677ba742d7):\",\n placeholder: \"81c677ba742d7\",\n validate: v => validateTagId(v),\n });\n if (clack.isCancel(answer)) {\n clack.cancel(\"Verification cancelled.\");\n process.exit(0);\n }\n return normalizeTagId(answer);\n}\n\n/** Resolve the URL to open from --url or an interactive prompt. */\nasync function resolveUrl(options: VerifyOptions): Promise<string> {\n if (options.url) return options.url;\n\n if (options.json) fail(\"No URL provided. Pass --url <app-url>.\");\n const answer = await clack.text({\n message: \"What URL should I open? (start your dev server first)\",\n placeholder: \"http://localhost:3000\",\n validate: v =>\n /^https?:\\/\\//.test(v.trim())\n ? undefined\n : \"Enter a full URL (http://…).\",\n });\n if (clack.isCancel(answer)) {\n clack.cancel(\"Verification cancelled.\");\n process.exit(0);\n }\n return answer.trim();\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nconst STATE_FILE = \".cs-wizard/state.json\";\n\nexport interface PlaywrightAvailability {\n available: boolean;\n detectedAt?: string;\n installedBy?: \"wizard\";\n userChoice?: \"skip\";\n promptedAt?: string;\n}\n\nexport function readState(dir: string): Record<string, unknown> | null {\n const stateFile = path.join(dir, STATE_FILE);\n if (fs.existsSync(stateFile)) {\n try {\n return JSON.parse(fs.readFileSync(stateFile, \"utf-8\"));\n } catch {\n return null;\n }\n }\n return null;\n}\n\nexport function writeState(dir: string, state: Record<string, unknown>): void {\n const stateFile = path.join(dir, STATE_FILE);\n fs.mkdirSync(path.dirname(stateFile), { recursive: true });\n fs.writeFileSync(stateFile, JSON.stringify(state, null, 2));\n}\n\nexport function readProjectId(dir: string): string | null {\n return (readState(dir)?.projectId as string) ?? null;\n}\n\nexport function readPlaywrightAvailability(\n dir: string,\n): PlaywrightAvailability | null {\n const v = readState(dir)?.playwright;\n if (v && typeof v === \"object\" && \"available\" in (v as object)) {\n return v as PlaywrightAvailability;\n }\n return null;\n}\n\nexport function writePlaywrightAvailability(\n dir: string,\n availability: PlaywrightAvailability,\n): void {\n const state = readState(dir) ?? {};\n state.playwright = availability;\n writeState(dir, state);\n}\n","/** True when the value looks like a hashed tag ID (lowercase hex, ~13 chars). */\nexport function isHashedTagId(value: string): boolean {\n return /^[0-9a-f]{10,20}$/.test(value.trim());\n}\n\n/** Validate a hashed tag ID. Returns an error message, or undefined when valid. */\nexport function validateTagId(value: string): string | undefined {\n return isHashedTagId(value)\n ? undefined\n : \"Tag ID is a lowercase hex string (~13 chars, e.g. 81c677ba742d7).\";\n}\n\n/** Normalize a hashed tag ID to its canonical (trimmed, lowercase) form. */\nexport function normalizeTagId(tagId: string): string {\n return tagId.trim().toLowerCase();\n}\n","import * as clack from \"@clack/prompts\";\n\nexport interface Logger {\n info: (m: string) => void;\n step: (m: string) => void;\n error: (m: string) => void;\n success: (m: string) => void;\n warn: (m: string) => void;\n /** Raw, unformatted passthrough to stderr (e.g. a child process's live output). */\n stream: (chunk: string) => void;\n}\n\nexport function makeLogger(humanOutputToStderr: boolean): Logger {\n // Raw foreign output (e.g. a child process) always goes to stderr unformatted,\n // so it never corrupts the stdout channel in either mode.\n const stream = (chunk: string) => process.stderr.write(chunk);\n if (humanOutputToStderr) {\n // Human lines are pushed to stderr so stdout is left free for another consumer\n // (e.g. a machine-readable report).\n const toErr = (m: string) => process.stderr.write(m + \"\\n\");\n return {\n info: toErr,\n step: toErr,\n error: toErr,\n success: toErr,\n warn: toErr,\n stream,\n };\n }\n return {\n info: m => clack.log.info(m),\n step: m => clack.log.step(m),\n error: m => clack.log.error(m),\n success: m => clack.log.success(m),\n warn: m => clack.log.warn(m),\n stream,\n };\n}\n\nexport function fail(message: string): never {\n process.stderr.write(message + \"\\n\");\n process.exit(1);\n}\n\n/**\n * The single place allowed to write to stdout in the verify command.\n *\n * stdout is the machine-readable channel: in --json mode it must carry ONLY the\n * report (or a structured `{ error }` signal) so an agent can parse it\n * deterministically. Every human-facing line goes through the Logger (stderr).\n * Keep all stdout writes funneled here so this invariant stays greppable.\n */\nexport function emitStdout(text: string): void {\n process.stdout.write(text);\n}\n","import * as clack from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport { spawn } from \"node:child_process\";\nimport { createRequire } from \"node:module\";\nimport { chromium } from \"playwright-core\";\nimport type { Browser } from \"playwright-core\";\nimport type { VerifyOptions } from \"./types.js\";\nimport { emitStdout, type Logger } from \"./logger.js\";\nimport { writeArtifact } from \"./artifact.js\";\n\n/** How a browser-launch attempt failed, used to pick the right remedy. */\ntype BrowserFailureClass = \"missing\" | \"missing-libs\" | \"blocked\" | \"unknown\";\n\ninterface LaunchAttempt {\n label: string;\n channel?: string;\n klass: BrowserFailureClass;\n message: string;\n}\n\ninterface LaunchResult {\n browser: Browser | null;\n attempts: LaunchAttempt[];\n}\n\n/** Failure codes recorded in the breadcrumb and surfaced to agents on stdout. */\ntype BrowserFailureCode =\n | \"BROWSER_LAUNCH_FAILED\"\n | \"NO_BROWSER\"\n | \"MISSING_LIBS\"\n | \"BLOCKED_LAUNCH\"\n | \"NO_DISPLAY\";\n\n/** Signatures of a download blocked by a corporate proxy or an untrusted CA. */\nconst PROXY_CERT_RE =\n /self.signed certificate|unable to (?:verify|get local issuer)|CERT_|SSL|ECONNREFUSED|ETIMEDOUT|EAI_AGAIN|ENOTFOUND|getaddrinfo|tunneling socket|proxy/i;\n\n/** Process exit code paired with each browser failure (single source of truth). */\nconst BROWSER_FAILURE_EXIT_CODE: Record<BrowserFailureCode, number> = {\n BROWSER_LAUNCH_FAILED: 1,\n NO_BROWSER: 2,\n MISSING_LIBS: 3,\n BLOCKED_LAUNCH: 4,\n NO_DISPLAY: 5,\n};\n\n/** Close the browser (ignoring teardown errors) and exit with the given code. */\nexport async function closeAndExit(\n browser: Browser,\n code: number,\n): Promise<never> {\n await browser.close().catch(() => {});\n process.exit(code);\n}\n\n/**\n * Get a launched browser, or exit with a class-specific message and code.\n * Tries system Chrome/Edge first, then a pre-downloaded bundled Chromium, and\n * only offers a download when nothing is installed at all.\n */\nexport async function acquireBrowser(\n options: VerifyOptions,\n log: Logger,\n targetDir: string,\n): Promise<Browser> {\n let result = await tryLaunch();\n if (result.browser) return result.browser;\n\n let remedy = decideRemedy(result.attempts);\n\n // A browser exists but is missing OS libraries — a download won't fix it.\n if (remedy === \"missing-libs\") {\n failBrowser(options, log, targetDir, \"MISSING_LIBS\", result.attempts, () =>\n printMissingLibsHelp(log, result.attempts),\n );\n }\n\n // A browser exists but refused to launch (enterprise policy, locked profile…).\n if (remedy === \"blocked\") {\n failBrowser(\n options,\n log,\n targetDir,\n \"BLOCKED_LAUNCH\",\n result.attempts,\n () => printBlockedHelp(log, result.attempts),\n );\n }\n\n // Nothing installed — offer to download the bundled Chromium (with consent).\n if (remedy === \"missing\") {\n const install = await ensureBrowser(options, log);\n if (!install.ok) {\n const attempts = result.attempts;\n if (install.proxyHint) {\n failBrowser(options, log, targetDir, \"NO_BROWSER\", attempts, () =>\n printProxyHelp(log),\n );\n }\n failBrowser(options, log, targetDir, \"NO_BROWSER\", attempts, () =>\n printBrowserHelp(log, lastError(attempts)),\n );\n }\n // Re-launch after a successful download.\n result = await tryLaunch();\n if (result.browser) return result.browser;\n // Downloaded but still won't launch — on Linux this is almost always libs.\n remedy = decideRemedy(result.attempts);\n if (remedy === \"missing-libs\") {\n failBrowser(\n options,\n log,\n targetDir,\n \"MISSING_LIBS\",\n result.attempts,\n () => printMissingLibsHelp(log, result.attempts),\n );\n }\n failBrowser(\n options,\n log,\n targetDir,\n \"BROWSER_LAUNCH_FAILED\",\n result.attempts,\n () => printBrowserHelp(log, lastError(result.attempts)),\n );\n }\n\n // Unknown failure — surface the raw error.\n failBrowser(\n options,\n log,\n targetDir,\n \"BROWSER_LAUNCH_FAILED\",\n result.attempts,\n () => {\n log.error(`Could not launch a browser: ${lastError(result.attempts)}`);\n },\n );\n}\n\n/** Try system Chrome, then Edge, then bundled Chromium; collect classified failures. */\nasync function tryLaunch(): Promise<LaunchResult> {\n const configs: { label: string; channel?: string }[] = [\n { label: \"chrome\", channel: \"chrome\" },\n { label: \"msedge\", channel: \"msedge\" },\n { label: \"chromium\" }, // bundled, if `playwright-core install chromium` was run\n ];\n const attempts: LaunchAttempt[] = [];\n for (const cfg of configs) {\n try {\n const browser = await chromium.launch({\n headless: false,\n ...(cfg.channel ? { channel: cfg.channel } : {}),\n });\n return { browser, attempts };\n } catch (err) {\n const message = (err as Error)?.message ?? String(err);\n attempts.push({\n label: cfg.label,\n channel: cfg.channel,\n klass: classifyLaunchError(message),\n message,\n });\n }\n }\n return { browser: null, attempts };\n}\n\n/** Bucket a launch error so the right remedy can be offered. */\nfunction classifyLaunchError(message: string): BrowserFailureClass {\n if (\n /loading shared librar|libnss3|libnspr4|libatk|libgbm|libasound|libgtk|libx11|GLIBC/i.test(\n message,\n )\n )\n return \"missing-libs\";\n if (\n /Executable doesn't exist|Chromium distribution|was not found|ENOENT|playwright install/i.test(\n message,\n )\n )\n return \"missing\";\n if (\n /policy|enterprise|SingletonLock|ProcessSingleton|cannot create default profile|user data directory is already in use|DevToolsActivePort|Target page, context or browser has been closed/i.test(\n message,\n )\n )\n return \"blocked\";\n return \"unknown\";\n}\n\n/** Pick the most actionable remedy across all attempts. */\nfunction decideRemedy(attempts: LaunchAttempt[]): BrowserFailureClass {\n const chromiumAttempt = attempts.find(a => a.label === \"chromium\");\n // If bundled Chromium simply isn't downloaded, that's the cleanest fix and it\n // also sidesteps enterprise policies on branded Chrome/Edge.\n if (chromiumAttempt?.klass === \"missing\") return \"missing\";\n if (attempts.some(a => a.klass === \"missing-libs\")) return \"missing-libs\";\n if (attempts.every(a => a.klass === \"missing\")) return \"missing\";\n if (attempts.some(a => a.klass === \"blocked\")) return \"blocked\";\n return \"unknown\";\n}\n\nfunction lastError(attempts: LaunchAttempt[]): string {\n return attempts[attempts.length - 1]?.message ?? \"unknown error\";\n}\n\n/** True when the failure is the browser dying, not the dev server being down. */\nexport function isBrowserGoneError(message: string): boolean {\n return /Target (?:page, context or browser|closed)|browser has been closed|Browser closed|crash|disconnected/i.test(\n message,\n );\n}\n\n/** Write a class-specific failure, a breadcrumb, and exit deterministically. */\nfunction failBrowser(\n options: VerifyOptions,\n log: Logger,\n targetDir: string,\n code: BrowserFailureCode,\n attempts: LaunchAttempt[],\n printHelp: () => void,\n): never {\n writeBrowserFailure(targetDir, code, attempts);\n printHelp();\n if (options.json) {\n // Structured signal on stdout so a stdout-only agent can branch on it.\n emitStdout(JSON.stringify({ error: code }) + \"\\n\");\n }\n process.exit(BROWSER_FAILURE_EXIT_CODE[code]);\n}\n\n/** Persist a reproducible breadcrumb of why the browser couldn't be acquired. */\nfunction writeBrowserFailure(\n targetDir: string,\n code: BrowserFailureCode,\n attempts: LaunchAttempt[],\n): void {\n writeArtifact(targetDir, \"last-browser-error.json\", {\n error: code,\n platform: `${process.platform} ${process.arch}`,\n display: process.env.DISPLAY ?? null,\n attempts: attempts.map(a => ({\n label: a.label,\n class: a.klass,\n message: a.message,\n })),\n ts: new Date().toISOString(),\n });\n}\n\n/** No graphical display on Linux: verify needs a visible window. */\nexport function handleNoDisplay(\n options: VerifyOptions,\n log: Logger,\n targetDir: string,\n): never {\n writeBrowserFailure(targetDir, \"NO_DISPLAY\", []);\n log.error(\n \"No display detected. `verify` opens a real browser window and needs a desktop session.\",\n );\n log.info(\n \"Run this on a machine with a graphical desktop — not a headless server or a plain SSH session.\",\n );\n if (options.json) emitStdout(JSON.stringify({ error: \"NO_DISPLAY\" }) + \"\\n\");\n process.exit(BROWSER_FAILURE_EXIT_CODE.NO_DISPLAY);\n}\n\n/**\n * Offer to download the bundled Chromium engine, then install it (with consent).\n * Returns whether an engine is now available, plus a hint when a proxy/CA blocked it.\n */\nasync function ensureBrowser(\n options: VerifyOptions,\n log: Logger,\n): Promise<{ ok: boolean; proxyHint: boolean }> {\n if (!options.installBrowser) {\n if (options.json) {\n // Agent-driven: don't prompt. State the exact re-run contract.\n log.error(\n \"NO_BROWSER: no Chrome/Edge/Chromium found. Get the user's consent, then re-run this exact command with --install-browser added.\",\n );\n return { ok: false, proxyHint: false };\n }\n const consent = await clack.confirm({\n message:\n \"No browser found. Download the Chromium engine now? (~280 MB, one-time)\",\n initialValue: true,\n });\n if (clack.isCancel(consent) || !consent)\n return { ok: false, proxyHint: false };\n }\n\n return installChromium(log);\n}\n\nfunction installChromium(\n log: Logger,\n): Promise<{ ok: boolean; proxyHint: boolean }> {\n const require = createRequire(import.meta.url);\n let cliPath: string;\n try {\n cliPath = require.resolve(\"playwright-core/cli.js\");\n } catch {\n log.error(\"Could not locate playwright-core CLI to install Chromium.\");\n return Promise.resolve({ ok: false, proxyHint: false });\n }\n\n log.step(\"Downloading Chromium (one-time)…\");\n return new Promise(resolve => {\n const child = spawn(process.execPath, [cliPath, \"install\", \"chromium\"], {\n // Forward proxy / CA / mirror settings so corporate networks can download.\n env: { ...process.env },\n // Never inherit stdout: it is reserved for the JSON report in --json mode.\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n let output = \"\";\n const onData = (chunk: Buffer) => {\n const text = chunk.toString();\n output += text;\n log.stream(text);\n };\n child.stdout?.on(\"data\", onData);\n child.stderr?.on(\"data\", onData);\n child.on(\"error\", err => {\n output += String((err as Error)?.message ?? err);\n resolve({ ok: false, proxyHint: PROXY_CERT_RE.test(output) });\n });\n child.on(\"close\", code => {\n resolve({\n ok: code === 0,\n proxyHint: code !== 0 && PROXY_CERT_RE.test(output),\n });\n });\n });\n}\n\nfunction printBrowserHelp(log: Logger, errMessage: string): void {\n log.error(\"Could not launch a browser.\");\n log.info(\"Install one of the following, then re-run:\");\n log.info(\n ` • Google Chrome (recommended) — ${chalk.cyan(\"https://www.google.com/chrome/\")}`,\n );\n log.info(\n ` • or the bundled engine — ${chalk.cyan(\"npx playwright-core install chromium\")}`,\n );\n log.info(chalk.dim(`(${errMessage})`));\n}\n\nfunction printMissingLibsHelp(log: Logger, attempts: LaunchAttempt[]): void {\n log.error(\"A browser was found but is missing system libraries.\");\n log.info(\"Install the libraries Chromium needs, then re-run:\");\n log.info(` ${chalk.cyan(\"sudo npx playwright-core install-deps chromium\")}`);\n log.info(chalk.dim(`(${lastError(attempts)})`));\n}\n\nfunction printBlockedHelp(log: Logger, attempts: LaunchAttempt[]): void {\n log.error(\"A browser was found but refused to launch.\");\n log.info(\n \"This is usually an enterprise policy or a profile that is already in use.\",\n );\n log.info(\"Try one of the following, then re-run:\");\n log.info(\" • Close all open Chrome/Edge windows and try again.\");\n log.info(\n ` • Or use a clean bundled engine — ${chalk.cyan(\"npx playwright-core install chromium\")}, then re-run with ${chalk.cyan(\"--install-browser\")}.`,\n );\n log.info(chalk.dim(`(${lastError(attempts)})`));\n}\n\nfunction printProxyHelp(log: Logger): void {\n log.error(\n \"Could not download Chromium — this looks like a proxy or certificate issue.\",\n );\n log.info(\"If you are behind a corporate proxy, set these and re-run:\");\n for (const line of proxyEnvExamples()) {\n log.info(\n ` ${chalk.cyan(line.command)}${line.note ? ` ${chalk.dim(line.note)}` : \"\"}`,\n );\n }\n}\n\n/** Env-var examples in the syntax of the current OS's default shell. */\nfunction proxyEnvExamples(): { command: string; note?: string }[] {\n const vars: { name: string; value: string; note?: string }[] = [\n { name: \"HTTPS_PROXY\", value: \"http://your-proxy:port\" },\n { name: \"NODE_EXTRA_CA_CERTS\", value: \"/path/to/corporate-ca.pem\" },\n {\n name: \"PLAYWRIGHT_DOWNLOAD_HOST\",\n value: \"http://your-mirror\",\n note: \"(if your org mirrors the browser CDN)\",\n },\n ];\n if (process.platform === \"win32\") {\n // PowerShell is the modern default shell on Windows.\n return vars.map(v => ({\n command: `$env:${v.name}=\"${v.value}\"`,\n note: v.note,\n }));\n }\n return vars.map(v => ({\n command: `export ${v.name}=${v.value}`,\n note: v.note,\n }));\n}\n","import path from \"node:path\";\nimport fs from \"node:fs\";\n\n/** Best-effort JSON write under `.cs-wizard/`; never throws (a breadcrumb must not fail the command). */\nexport function writeArtifact(\n targetDir: string,\n fileName: string,\n data: unknown,\n): void {\n try {\n const dir = path.join(targetDir, \".cs-wizard\");\n fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(path.join(dir, fileName), JSON.stringify(data, null, 2));\n } catch {\n // Best-effort artifact; never fail the command because of it.\n }\n}\n","import chalk from \"chalk\";\nimport path from \"node:path\";\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport { createRequire } from \"node:module\";\nimport { chromium } from \"playwright-core\";\nimport type { VerifyOptions } from \"./types.js\";\nimport { emitStdout, type Logger } from \"./logger.js\";\nimport { writeArtifact } from \"./artifact.js\";\n\n/** Exit code when `verify --preflight` finds no working browser. */\nconst PREFLIGHT_NO_BROWSER_EXIT_CODE = 2;\n\ntype ChannelProbe = { ok: boolean; version?: string; error?: string };\n\n// --- Preflight diagnostics: report the browser environment, then exit ---\nexport async function runPreflight(\n targetDir: string,\n options: VerifyOptions,\n log: Logger,\n): Promise<void> {\n const browsersPath =\n process.env.PLAYWRIGHT_BROWSERS_PATH ?? defaultBrowsersPath();\n\n let bundledChromiumPath: string | null = null;\n let bundledChromiumPresent = false;\n try {\n bundledChromiumPath = chromium.executablePath();\n bundledChromiumPresent =\n !!bundledChromiumPath && fs.existsSync(bundledChromiumPath);\n } catch {\n bundledChromiumPath = null;\n }\n\n const systemChrome = await probeChannel(\"chrome\");\n const systemEdge = await probeChannel(\"msedge\");\n const bundledChromium = await probeChannel(undefined);\n const anyOk = systemChrome.ok || systemEdge.ok || bundledChromium.ok;\n\n const info = {\n os: `${process.platform} ${process.arch}`,\n node: process.version,\n display:\n process.platform === \"linux\"\n ? (process.env.DISPLAY ?? process.env.WAYLAND_DISPLAY ?? null)\n : \"n/a\",\n playwrightCoreVersion: readPlaywrightCoreVersion(),\n browsersPath,\n bundledChromiumPath,\n bundledChromiumPresent,\n systemChrome,\n systemEdge,\n bundledChromium,\n anyBrowserAvailable: anyOk,\n };\n\n // Persist the snapshot so users can attach it to a support request.\n writeArtifact(targetDir, \"last-preflight.json\", info);\n\n if (options.json) {\n emitStdout(JSON.stringify(info, null, 2) + \"\\n\");\n process.exit(anyOk ? 0 : PREFLIGHT_NO_BROWSER_EXIT_CODE);\n }\n\n log.step(chalk.bold(\"verify preflight\"));\n log.info(`OS: ${info.os} • Node: ${info.node}`);\n log.info(`Display: ${formatValue(info.display)}`);\n log.info(`playwright-core: ${formatValue(info.playwrightCoreVersion)}`);\n log.info(`Browsers cache: ${formatValue(browsersPath)}`);\n log.info(\n `Bundled Chromium present: ${bundledChromiumPresent ? chalk.green(\"yes\") : chalk.yellow(\"no\")}`,\n );\n log.info(probeLine(\"System Chrome\", systemChrome));\n log.info(probeLine(\"System Edge\", systemEdge));\n log.info(probeLine(\"Bundled Chromium\", bundledChromium));\n log.info(\"\");\n if (anyOk) {\n log.success(chalk.green(\"A browser is available — verify should work.\"));\n } else {\n log.warn(\n chalk.yellow(\n \"No working browser found. Run `verify --install-browser`, or install Google Chrome.\",\n ),\n );\n }\n process.exit(anyOk ? 0 : PREFLIGHT_NO_BROWSER_EXIT_CODE);\n}\n\n/** Briefly launch a channel headlessly to confirm it works and read its version. */\nasync function probeChannel(channel?: string): Promise<ChannelProbe> {\n try {\n const browser = await chromium.launch({\n headless: true,\n ...(channel ? { channel } : {}),\n });\n const version = browser.version();\n await browser.close().catch(() => {});\n return { ok: true, version };\n } catch (err) {\n return {\n ok: false,\n error: firstLine((err as Error)?.message ?? String(err)),\n };\n }\n}\n\nfunction readPlaywrightCoreVersion(): string | null {\n try {\n const require = createRequire(import.meta.url);\n const pkgPath = require.resolve(\"playwright-core/package.json\");\n return (\n (JSON.parse(fs.readFileSync(pkgPath, \"utf8\")).version as string) ?? null\n );\n } catch {\n return null;\n }\n}\n\nfunction defaultBrowsersPath(): string {\n const home = os.homedir();\n if (process.platform === \"darwin\")\n return path.join(home, \"Library\", \"Caches\", \"ms-playwright\");\n if (process.platform === \"win32\")\n return path.join(home, \"AppData\", \"Local\", \"ms-playwright\");\n return path.join(home, \".cache\", \"ms-playwright\");\n}\n\nfunction probeLine(label: string, probe: ChannelProbe): string {\n if (probe.ok)\n return `${chalk.green(\"✓\")} ${label}: ${probe.version ?? \"available\"}`;\n return `${chalk.yellow(\"✗\")} ${label}: ${chalk.dim(probe.error ?? \"unavailable\")}`;\n}\n\nfunction firstLine(text: string): string {\n return text.split(\"\\n\")[0];\n}\n\nfunction formatValue(value: unknown): string {\n return value === null || value === undefined || value === \"\"\n ? chalk.dim(\"—\")\n : String(value);\n}\n","import chalk from \"chalk\";\nimport type {\n Browser,\n BrowserContext,\n Page,\n Request,\n ConsoleMessage,\n} from \"playwright-core\";\nimport type { CsRequest, SessionTrace, Violation } from \"./types.js\";\nimport type { Logger } from \"./logger.js\";\nimport {\n NAV_BINDING,\n DONE_BINDING,\n historyHookScript,\n overlayScript,\n} from \"./inject.js\";\nimport { isBrowserGoneError, closeAndExit } from \"./browser.js\";\n\n// CS_HOST_RE validates a parsed hostname (anchored, so `evilcontentsquare.net`\n// can't slip through), while CS_DOMAIN_RE scans free-form text.\nconst CS_DOMAIN = String.raw`contentsquare\\.(net|com)`;\nconst CS_HOST_RE = new RegExp(String.raw`(^|\\.)${CS_DOMAIN}$`, \"i\");\nconst CS_DOMAIN_RE = new RegExp(CS_DOMAIN, \"i\");\nconst CSP_RE =\n /content-security-policy|refused to|violates the following|err_blocked_by_csp|blocked:csp/i;\n/** Contentsquare tag script path (vs. a tracking beacon) on a CS host. */\nconst TAG_SCRIPT_RE = /\\/uxa\\/[^/]+\\.js(\\?|$)/i;\n\n// --- Live session: drive a real browser and record what the tag does ---\n\n/**\n * Open the app, inject the page hooks, and record navigations, Contentsquare\n * requests, and CSP violations until the user clicks \"Done\" or closes the window.\n * Exits the process if the page never loads (dev server down or browser crashed).\n */\nexport async function runVerifySession(\n browser: Browser,\n url: string,\n log: Logger,\n): Promise<SessionTrace> {\n const navEvents: SessionTrace[\"navEvents\"] = [];\n const csRequests: CsRequest[] = [];\n const violations: Violation[] = [];\n\n // Resolved when the user clicks \"Done\" in the on-page overlay.\n let signalDone: () => void = () => {};\n const doneClicked = new Promise<void>(resolve => {\n signalDone = resolve;\n });\n\n let context: BrowserContext;\n try {\n context = await browser.newContext();\n\n // Stream SPA route changes from the page into Node in real time.\n await context.exposeBinding(\n NAV_BINDING,\n (_source, data: { type: string; url: string }) => {\n navEvents.push({ type: data.type, url: data.url, ts: Date.now() });\n },\n );\n await context.addInitScript(historyHookScript());\n\n // Show an on-page overlay so the user knows what to do, with a \"Done\" button.\n await context.exposeBinding(DONE_BINDING, () => signalDone());\n await context.addInitScript(overlayScript());\n\n context.on(\"request\", (req: Request) => recordCsRequest(req, csRequests));\n context.on(\"requestfailed\", (req: Request) =>\n recordRequestViolation(req, violations),\n );\n\n const page = await context.newPage();\n page.on(\"console\", (msg: ConsoleMessage) =>\n recordConsoleViolation(msg, violations),\n );\n\n await page.goto(url, { waitUntil: \"domcontentloaded\", timeout: 30_000 });\n } catch (err) {\n const message = (err as Error)?.message ?? String(err);\n if (isBrowserGoneError(message)) {\n log.error(\n `The browser closed before the page finished loading. (${message})`,\n );\n } else {\n log.error(\n `Could not load ${url}. Is the dev server running? (${message})`,\n );\n }\n return closeAndExit(browser, 1);\n }\n\n printBrowseInstructions(log);\n await waitForFinish(browser, context, doneClicked);\n\n return { navEvents, csRequests, violations };\n}\n\n/** Record a Contentsquare request, tagged as either the tag script or a beacon. */\nfunction recordCsRequest(req: Request, out: CsRequest[]): void {\n const host = safeHost(req.url());\n if (!host || !CS_HOST_RE.test(host)) return;\n const kind = TAG_SCRIPT_RE.test(req.url()) ? \"script\" : \"beacon\";\n out.push({ url: req.url(), ts: Date.now(), kind });\n}\n\n/** Record a failed Contentsquare request that looks like a CSP block. */\nfunction recordRequestViolation(req: Request, out: Violation[]): void {\n // Only Contentsquare hosts matter: a CSP block of the tag or a beacon is what\n // we care about, and scoping here matches the skill's documented contract.\n const host = safeHost(req.url());\n if (!host || !CS_HOST_RE.test(host)) return;\n const failure = req.failure()?.errorText ?? \"\";\n if (CSP_RE.test(failure)) {\n out.push({ source: \"request\", text: `${req.url()} — ${failure}` });\n }\n}\n\n/** Record a console message that reports a Contentsquare CSP violation. */\nfunction recordConsoleViolation(msg: ConsoleMessage, out: Violation[]): void {\n const text = msg.text();\n // Require a Contentsquare domain so unrelated CSP errors — including the\n // verifier's own injected overlay styles — don't trigger a spurious fail.\n if (CSP_RE.test(text) && CS_DOMAIN_RE.test(text)) {\n out.push({ source: \"console\", text });\n }\n}\n\nfunction printBrowseInstructions(log: Logger): void {\n log.info(\"\");\n log.step(chalk.bold(\"Browse your app now:\"));\n log.info(\" 1. Wait a moment for the first page to settle.\");\n log.info(\" 2. Click through a few in-app routes (and log in if needed).\");\n log.info(\n ` 3. Click ${chalk.bold(\"“Done”\")} in the banner (or close the window) to see the report.`,\n );\n log.info(\"\");\n}\n\nfunction waitForFinish(\n browser: Browser,\n context: BrowserContext,\n doneClicked: Promise<void>,\n): Promise<void> {\n return new Promise(resolve => {\n const finish = once(() => {\n browser.close().catch(() => {});\n resolve();\n });\n\n // Finish when the user closes the last browser window. We track open pages\n // because some Chrome installs keep the browser process alive after the window\n // closes (background apps), so `browser disconnected` alone is unreliable.\n const openPages = new Set<Page>(context.pages());\n const watchPage = (p: Page) => {\n p.on(\"close\", () => {\n openPages.delete(p);\n if (openPages.size === 0) finish();\n });\n };\n context.pages().forEach(watchPage);\n context.on(\"page\", p => {\n openPages.add(p);\n watchPage(p);\n });\n\n doneClicked.then(finish);\n browser.on(\"disconnected\", finish);\n context.on(\"close\", finish);\n process.once(\"SIGINT\", finish);\n });\n}\n\nfunction safeHost(u: string): string {\n try {\n return new URL(u).hostname;\n } catch {\n return \"\";\n }\n}\n\n/** Wrap a function so it runs at most once; later calls are no-ops. */\nfunction once(fn: () => void): () => void {\n let called = false;\n return () => {\n if (called) return;\n called = true;\n fn();\n };\n}\n","/**\n * Names of the callbacks the injected scripts use to talk back to Node.\n *\n * They are a contract between this module and session.ts: the scripts below\n * CALL `window.<binding>`, and session.ts REGISTERS them via `exposeBinding`.\n * Both sides must use the exact same string or the page-to-Node bridge\n * silently breaks.\n */\nexport const NAV_BINDING = \"__csWizardNav\";\nexport const DONE_BINDING = \"__csWizardDone\";\n\n/**\n * Injected into every page to surface client-side route changes.\n *\n * SPAs navigate by calling `history.pushState`/`replaceState` (or going\n * back/forward), which updates the URL without a real page load — so Playwright\n * sees no navigation event. We patch those history methods and listen for\n * `popstate`, calling back into Node on each change. That lets the verifier know\n * a \"page view\" happened and check whether the tag fired a pageview for it.\n */\nexport function historyHookScript(): string {\n return `(() => {\n const send = (type) => {\n try { window.${NAV_BINDING}({ type, url: location.href }); } catch {}\n };\n for (const name of ['pushState', 'replaceState']) {\n const orig = history[name];\n history[name] = function () {\n const r = orig.apply(this, arguments);\n send(name);\n return r;\n };\n }\n window.addEventListener('popstate', () => send('popstate'));\n })();`;\n}\n\n/**\n * Injected into every page: a fixed overlay banner telling the user to browse\n * their app and click \"Done\" when finished. Clicking Done calls back into Node.\n */\nexport function overlayScript(): string {\n return `(() => {\n const ID = '__cs-wizard-overlay';\n function mount() {\n if (!document.body || document.getElementById(ID)) return;\n const bar = document.createElement('div');\n bar.id = ID;\n bar.setAttribute('style', [\n 'position:fixed','left:50%','bottom:20px','transform:translateX(-50%)',\n 'z-index:2147483647','background:#1b1b2f','color:#fff',\n 'font:14px/1.4 system-ui,-apple-system,Segoe UI,sans-serif',\n 'padding:12px 16px','border-radius:10px','box-shadow:0 6px 24px rgba(0,0,0,.35)',\n 'display:flex','align-items:center','gap:14px','max-width:90vw'\n ].join(';'));\n const msg = document.createElement('span');\n msg.innerHTML = '<strong>Contentsquare check running.</strong> Click around a few pages, then press Done.';\n const btn = document.createElement('button');\n btn.textContent = 'Done';\n btn.setAttribute('style', [\n 'background:#6c5ce7','color:#fff','border:0','cursor:pointer',\n 'padding:8px 16px','border-radius:8px','font-weight:600','font-size:14px'\n ].join(';'));\n btn.onclick = () => {\n btn.disabled = true;\n btn.textContent = 'Finishing…';\n try { window.${DONE_BINDING}(); } catch {}\n };\n bar.appendChild(msg);\n bar.appendChild(btn);\n document.body.appendChild(bar);\n }\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', mount);\n } else {\n mount();\n }\n })();`;\n}\n","import type { CsRequest, NavEvent, VerifyReport, Violation } from \"./types.js\";\n\n/** How long after a route change we still attribute a beacon to that navigation. */\nconst NAV_BEACON_WINDOW_MS = 6000;\n/** Route changes for the same URL within this window collapse into one logical nav. */\nconst NAV_DEDUPE_WINDOW_MS = 400;\n\nconst SPA_TRACKING_RECOMMENDATION =\n \"Some in-app route changes did not fire a pageview. If this is a single-page app, \" +\n 'enable \"Tracking URL Changes\" in the Contentsquare app (Project and Users → Tracking URL Changes).';\n\n/**\n * Turn one recorded browsing session into the verification report.\n *\n * From the raw trace (route changes + Contentsquare network requests + console/\n * CSP violations) it derives the four checks the report grades on:\n * 1. Tag script loaded — the `/uxa/*.js` tag was fetched from a CS host (and,\n * if so, whether its tag id matches the expected one).\n * 2. Initial pageview — a beacon fired for the first page, before any in-app\n * route change (hydration navigations are discarded first so they don't\n * steal that attribution).\n * 3. Pageview coverage on navigation — every SPA route change is followed by\n * a beacon within the attribution window.\n * 4. CSP violations — de-duplicated content-security-policy errors that could\n * block the tag.\n * `gradeResult` then folds these into a pass / pass-with-recommendation / fail.\n */\nexport function analyze(input: {\n url: string;\n projectId: string | null;\n tagId: string;\n navEvents: NavEvent[];\n csRequests: CsRequest[];\n violations: Violation[];\n}): VerifyReport {\n const { url, projectId, tagId, navEvents, csRequests, violations } = input;\n\n const scripts = csRequests.filter(r => r.kind === \"script\");\n const beacons = csRequests.filter(r => r.kind === \"beacon\");\n const tagScriptLoaded = scripts.length > 0;\n const tagIdMismatch =\n tagScriptLoaded && !scripts.some(s => s.url.includes(tagId));\n\n const navs = dropHydrationNav(collapseDuplicateNavs(navEvents), url);\n\n const firstNavTs = navs[0]?.ts ?? Infinity;\n const initialPageview = beacons.some(b => b.ts <= firstNavTs);\n\n const navigations = navs.map(nav => ({\n url: nav.url,\n type: nav.type,\n pageviewFired: firedPageviewAfter(beacons, nav.ts),\n }));\n const navigationsWithPageview = navigations.filter(\n n => n.pageviewFired,\n ).length;\n\n const cspViolations = dedupe(violations, v => v.text);\n\n const { result, recommendation } = gradeResult({\n tagScriptLoaded,\n initialPageview,\n cspViolations,\n navigations,\n navigationsWithPageview,\n });\n\n return {\n url,\n projectId,\n tagId,\n tagScriptLoaded,\n tagIdMismatch,\n initialPageview,\n navigations,\n navigationsWithPageview,\n cspViolations,\n result,\n recommendation,\n };\n}\n\n/** Collapse near-duplicate route changes (replaceState bursts → one logical nav). */\nfunction collapseDuplicateNavs(navEvents: NavEvent[]): NavEvent[] {\n const navs: NavEvent[] = [];\n for (const ev of navEvents) {\n const prev = navs[navs.length - 1];\n if (prev && prev.url === ev.url && ev.ts - prev.ts < NAV_DEDUPE_WINDOW_MS)\n continue;\n navs.push(ev);\n }\n return navs;\n}\n\n/**\n * Drop a leading history change to the landing URL: that is the framework's\n * hydration-time replaceState (Next.js, React Router, …), not an in-app\n * navigation. Dropping it lets its pageview count toward the initial load\n * instead of a phantom route change.\n */\nfunction dropHydrationNav(navs: NavEvent[], landingUrl: string): NavEvent[] {\n const sameUrl = (a: string, b: string) =>\n a.replace(/\\/+$/, \"\") === b.replace(/\\/+$/, \"\");\n return navs.length > 0 && sameUrl(navs[0].url, landingUrl)\n ? navs.slice(1)\n : navs;\n}\n\n/** True if a beacon fired within the attribution window after a navigation. */\nfunction firedPageviewAfter(beacons: CsRequest[], navTs: number): boolean {\n return beacons.some(\n b => b.ts > navTs && b.ts <= navTs + NAV_BEACON_WINDOW_MS,\n );\n}\n\n/** Grade the observed checks into a pass/fail result and an optional recommendation. */\nfunction gradeResult(checks: {\n tagScriptLoaded: boolean;\n initialPageview: boolean;\n cspViolations: Violation[];\n navigations: { pageviewFired: boolean }[];\n navigationsWithPageview: number;\n}): { result: VerifyReport[\"result\"]; recommendation: string | null } {\n const {\n tagScriptLoaded,\n initialPageview,\n cspViolations,\n navigations,\n navigationsWithPageview,\n } = checks;\n\n if (!tagScriptLoaded || !initialPageview)\n return { result: \"fail\", recommendation: null };\n if (cspViolations.length > 0) return { result: \"fail\", recommendation: null };\n if (navigations.length > 0 && navigationsWithPageview < navigations.length) {\n return {\n result: \"pass-with-recommendation\",\n recommendation: SPA_TRACKING_RECOMMENDATION,\n };\n }\n return { result: \"pass\", recommendation: null };\n}\n\nfunction dedupe<T>(items: T[], key: (x: T) => string): T[] {\n const seen = new Set<string>();\n const out: T[] = [];\n for (const item of items) {\n const k = key(item);\n if (seen.has(k)) continue;\n seen.add(k);\n out.push(item);\n }\n return out;\n}\n","import chalk from \"chalk\";\nimport type { VerifyReport } from \"./types.js\";\nimport type { Logger } from \"./logger.js\";\n\n/** Cap on how many CSP violations the human report prints in full. */\nconst MAX_CSP_VIOLATIONS_SHOWN = 8;\n\nexport function printHumanReport(r: VerifyReport, log: Logger): void {\n const ok = chalk.green(\"✓\");\n const no = chalk.red(\"✗\");\n const warn = chalk.yellow(\"!\");\n\n log.info(\"\");\n log.step(chalk.bold(\"Verification report\"));\n log.info(`${r.tagScriptLoaded ? ok : no} Tag script loaded`);\n if (r.tagIdMismatch) {\n log.info(\n `${warn} Tag URL uses a different ID than ${chalk.cyan(r.tagId)} — check the tag ID used at install.`,\n );\n }\n log.info(`${r.initialPageview ? ok : no} First pageview sent on load`);\n\n if (r.navigations.length === 0) {\n log.info(\n `${warn} No in-app route changes were recorded — navigate a few routes to test SPA coverage.`,\n );\n } else {\n const icon = r.navigationsWithPageview === r.navigations.length ? ok : warn;\n log.info(\n `${icon} Pageviews on navigation: ${r.navigationsWithPageview}/${r.navigations.length}`,\n );\n for (const n of r.navigations) {\n log.info(` ${n.pageviewFired ? ok : no} ${n.type} → ${n.url}`);\n }\n }\n\n if (r.cspViolations.length > 0) {\n log.info(`${no} CSP violations (${r.cspViolations.length}):`);\n for (const v of r.cspViolations.slice(0, MAX_CSP_VIOLATIONS_SHOWN)) {\n log.info(` ${chalk.dim(\"-\")} ${v.text}`);\n }\n } else {\n log.info(`${ok} No CSP violations detected`);\n }\n\n log.info(\"\");\n if (r.result === \"pass\") {\n log.success(chalk.green(\"All checks passed.\"));\n } else if (r.result === \"pass-with-recommendation\") {\n log.warn(chalk.yellow(\"Passed with a recommendation:\"));\n log.info(` ${r.recommendation}`);\n } else {\n log.error(chalk.red(\"Some checks failed — see above.\"));\n }\n}\n","import * as clack from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport { exec } from \"node:child_process\";\nimport path from \"node:path\";\nimport fs from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { SORCERER } from \"./sorcerer.js\";\nimport { normalizeTagId, validateTagId } from \"../tools/tag-id.js\";\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst PACKAGE_ROOT = findPackageRoot(__dirname);\n\nconst SKILL_FILE = \"wizard-web-tag-install.md\";\nconst SKILL_PATH = `.cs-wizard/skills/${SKILL_FILE}`;\nconst SETUP_PROMPT = `Read and follow ${SKILL_PATH} — read it directly by path, it is gitignored so do not search for it.`;\n\ninterface StartOptions {\n dir: string;\n tagId?: string;\n}\n\nexport async function start(options: StartOptions): Promise<void> {\n process.stdout.write(SORCERER + \"\\n\");\n clack.intro(chalk.bold(\"Contentsquare Wizard — Start\"));\n\n const targetDir = path.resolve(options.dir);\n\n // 1. Resolve the tag ID — directly from --tag-id, prior state, or a prompt.\n const tagId = await resolveTagId(targetDir, options);\n clack.log.info(`Tag ID: ${chalk.cyan(tagId)}`);\n\n // 2. Copy the CLI-flow skill into .cs-wizard/skills/\n const spinner = clack.spinner();\n spinner.start(\"Setting up wizard skill...\");\n const wizardDir = path.join(targetDir, \".cs-wizard\");\n const skillsDir = path.join(wizardDir, \"skills\");\n fs.mkdirSync(skillsDir, { recursive: true });\n fs.copyFileSync(\n path.join(PACKAGE_ROOT, \"skills\", SKILL_FILE),\n path.join(skillsDir, SKILL_FILE),\n );\n spinner.stop(`Copied skill to ${chalk.cyan(SKILL_PATH)}`);\n\n // 3. Write wizard state config (so `verify` and the skill can read the tag ID).\n const state = readExistingConfig(targetDir) ?? {};\n state.tagId = tagId;\n state.startedAt = new Date().toISOString();\n fs.writeFileSync(\n path.join(wizardDir, \"state.json\"),\n JSON.stringify(state, null, 2),\n );\n\n // 4. Add .cs-wizard/ to .gitignore\n ensureGitignore(targetDir);\n\n clack.log.success(\"Wizard ready!\");\n clack.log.info(\"\");\n\n await showNextSteps();\n}\n\n// --- Tag ID resolution ---\n\nasync function resolveTagId(\n targetDir: string,\n options: StartOptions,\n): Promise<string> {\n // 1. --tag-id flag wins.\n if (options.tagId) {\n const err = validateTagId(options.tagId);\n if (err) {\n clack.log.error(`Invalid --tag-id value: ${err}`);\n process.exit(1);\n }\n return normalizeTagId(options.tagId);\n }\n\n // 2. Reuse a value already stored in state.json.\n const existing = readExistingConfig(targetDir);\n if (existing?.tagId) {\n const reuse = await clack.confirm({\n message: `Found existing tag ID ${chalk.cyan(String(existing.tagId))}. Use it?`,\n initialValue: true,\n });\n if (clack.isCancel(reuse)) {\n clack.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n if (reuse) {\n return String(existing.tagId);\n }\n }\n\n // 3. Prompt for the hashed tag ID.\n const response = await clack.text({\n message:\n \"Enter your Contentsquare tag ID (hashed hex, e.g. 81c677ba742d7):\",\n placeholder: \"81c677ba742d7\",\n validate: v => validateTagId(v),\n });\n if (clack.isCancel(response)) {\n clack.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n return normalizeTagId(response);\n}\n\n// --- Next steps ---\n\nasync function showNextSteps(): Promise<void> {\n clack.log.step(chalk.bold(\"Next steps:\"));\n clack.log.info(\n \" 1. Open your AI coding agent (Copilot, Cursor, Claude Code, etc.)\",\n );\n\n const copied = await copyToClipboard(SETUP_PROMPT);\n if (copied) {\n clack.log.success(\n ` 2. ${chalk.bold.green(\"Prompt copied to clipboard!\")} Paste it in your agent to start.`,\n );\n } else {\n clack.log.info(\" 2. Tell your agent:\");\n const border = chalk.gray(\"─\".repeat(40));\n clack.log.info(` ${border}`);\n for (const line of SETUP_PROMPT.split(\"\\n\")) {\n clack.log.info(` ${chalk.cyan(line)}`);\n }\n clack.log.info(` ${border}`);\n }\n\n clack.log.info(\"\");\n clack.outro(\n `Now ask your AI agent: ${chalk.cyan(`Read and follow ${SKILL_PATH}`)}`,\n );\n}\n\n// --- Shared file helpers ---\n\nfunction readExistingConfig(targetDir: string): Record<string, unknown> | null {\n const stateFile = path.join(targetDir, \".cs-wizard\", \"state.json\");\n if (fs.existsSync(stateFile)) {\n try {\n return JSON.parse(fs.readFileSync(stateFile, \"utf-8\"));\n } catch {\n return null;\n }\n }\n return null;\n}\n\nfunction ensureGitignore(targetDir: string): void {\n const gitignorePath = path.join(targetDir, \".gitignore\");\n const entry = \".cs-wizard/\";\n\n if (fs.existsSync(gitignorePath)) {\n const content = fs.readFileSync(gitignorePath, \"utf-8\");\n if (!content.includes(entry)) {\n fs.appendFileSync(\n gitignorePath,\n `\\n# Contentsquare wizard (generated)\\n${entry}\\n`,\n );\n }\n } else {\n fs.writeFileSync(\n gitignorePath,\n `# Contentsquare wizard (generated)\\n${entry}\\n`,\n );\n }\n}\n\nfunction copyToClipboard(text: string): Promise<boolean> {\n return new Promise(resolve => {\n const cmd =\n process.platform === \"win32\"\n ? `echo ${text.replace(/[\"&|<>^]/g, \"^$&\")} | clip`\n : process.platform === \"darwin\"\n ? `echo ${JSON.stringify(text)} | pbcopy`\n : `echo ${JSON.stringify(text)} | xclip -selection clipboard || echo ${JSON.stringify(text)} | xsel --clipboard --input`;\n exec(cmd, err => resolve(!err));\n });\n}\n\n// --- package root discovery (skills live next to package.json) ---\n\nfunction findPackageRoot(dir: string): string {\n let current = dir;\n for (let i = 0; i < 5; i++) {\n if (\n fs.existsSync(path.join(current, \"package.json\")) &&\n fs.existsSync(path.join(current, \"skills\"))\n ) {\n return current;\n }\n current = path.dirname(current);\n }\n return path.resolve(dir, \"..\");\n}\n"],"mappings":"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","names":["fileURLToPath","chalk","chalk","clack","chalk","path","fs","fs","path","clack","text","clack","chalk","path","fs","log","require","text","chalk","chalk","path","fs","createRequire","chromium","log","chromium","fs","chalk","require","createRequire","path","text","chalk","log","text","chalk","chalk","log","path","log","chalk","fs","clack","chalk","path","fs","__dirname","path","chalk","resolveTagId","spinner","fs","text","fileURLToPath"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/commands/status.ts","../src/commands/sorcerer.ts","../src/commands/verify/index.ts","../src/tools/state.ts","../src/tools/tag-id.ts","../src/commands/verify/logger.ts","../src/commands/verify/browser.ts","../src/commands/verify/artifact.ts","../src/commands/verify/preflight.ts","../src/commands/verify/session.ts","../src/commands/verify/inject.ts","../src/commands/verify/analyze.ts","../src/commands/verify/report.ts","../src/commands/start.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { Command } from \"commander\";\nimport { status } from \"./commands/status.js\";\nimport { verify } from \"./commands/verify/index.js\";\nimport { start } from \"./commands/start.js\";\n\nconst packageJson = JSON.parse(\n readFileSync(\n fileURLToPath(new URL(\"../package.json\", import.meta.url)),\n \"utf8\",\n ),\n) as { version: string };\n\nconst program = new Command();\n\nprogram\n .name(\"wizard-cs\")\n .description(\"AI-assisted Contentsquare tag installation and configuration\")\n .version(packageJson.version);\n\n// `start` is the onboarding entry point. `install` is kept as an alias so the\n// npm-conventional command name keeps working — both run the same CLI flow.\nfunction registerStart(name: \"start\" | \"install\"): void {\n program\n .command(name)\n .description(\n \"Set up the wizard skill so your AI agent can install the Contentsquare tag — verification runs via `verify`\",\n )\n .option(\"--dir <path>\", \"Target directory (defaults to cwd)\", process.cwd())\n .option(\n \"--tag-id <hashed>\",\n \"Hashed Contentsquare tag ID (hex, e.g. 81c677ba742d7)\",\n )\n .action(start);\n}\n\nregisterStart(\"start\");\nregisterStart(\"install\");\n\nprogram\n .command(\"status\")\n .description(\"Show the configured tag ID and the latest verification result\")\n .option(\"--dir <path>\", \"Target directory (defaults to cwd)\", process.cwd())\n .action(status);\n\nprogram\n .command(\"verify\")\n .description(\n \"Open your app in a real browser and verify the tag, CSP, and pageview coverage in one session\",\n )\n .option(\"--dir <path>\", \"Project directory (defaults to cwd)\", process.cwd())\n .option(\"--url <url>\", \"App URL to open (skips the prompt)\")\n .option(\n \"--tag-id <hashed>\",\n \"Hashed Contentsquare tag ID (hex, e.g. 81c677ba742d7)\",\n )\n .option(\n \"--install-browser\",\n \"Auto-download the Chromium engine if no browser is found\",\n )\n .option(\n \"--preflight\",\n \"Check browser availability and environment, then exit (diagnostics)\",\n )\n .option(\"--json\", \"Emit the report as JSON to stdout (for agents)\")\n .action(verify);\n\nprogram.parse();\n","import * as clack from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport path from \"node:path\";\nimport fs from \"node:fs\";\nimport { SORCERER } from \"./sorcerer.js\";\nimport type { VerifyReport } from \"./verify/index.js\";\n\ninterface StatusOptions {\n dir: string;\n}\n\nexport async function status(options: StatusOptions): Promise<void> {\n process.stdout.write(SORCERER + \"\\n\");\n const targetDir = path.resolve(options.dir);\n const stateFile = path.join(targetDir, \".cs-wizard\", \"state.json\");\n\n if (!fs.existsSync(stateFile)) {\n clack.log.error(\n `No wizard state found. Run ${chalk.cyan(\"npx @contentsquare/wizard start\")} first.`,\n );\n process.exit(1);\n }\n\n const state = JSON.parse(fs.readFileSync(stateFile, \"utf-8\"));\n\n clack.intro(chalk.bold(\"Contentsquare Wizard Status\"));\n clack.log.info(`Tag ID: ${chalk.cyan(state.tagId ?? \"unknown\")}`);\n if (state.projectId) {\n clack.log.info(`Project ID: ${chalk.cyan(state.projectId)}`);\n }\n clack.log.info(\"\");\n\n const report = readLastReport(targetDir);\n if (!report) {\n clack.log.warn(\"No verification run yet.\");\n clack.log.info(\n `Run ${chalk.cyan(\"npx @contentsquare/wizard verify\")} to check the tag in a real browser.`,\n );\n clack.outro(\"\");\n return;\n }\n\n const ok = chalk.green(\"✓\");\n const no = chalk.red(\"✗\");\n const warn = chalk.yellow(\"!\");\n\n clack.log.step(chalk.bold(\"Latest verification\"));\n clack.log.info(`URL: ${chalk.cyan(report.url)}`);\n clack.log.info(`${report.tagScriptLoaded ? ok : no} Tag script loaded`);\n clack.log.info(\n `${report.initialPageview ? ok : no} First pageview sent on load`,\n );\n\n if (report.navigations.length === 0) {\n clack.log.info(`${warn} No in-app route changes recorded`);\n } else {\n const icon =\n report.navigationsWithPageview === report.navigations.length ? ok : warn;\n clack.log.info(\n `${icon} Pageviews on navigation: ${report.navigationsWithPageview}/${report.navigations.length}`,\n );\n }\n\n clack.log.info(\n report.cspViolations.length === 0\n ? `${ok} No CSP violations`\n : `${no} CSP violations: ${report.cspViolations.length}`,\n );\n\n clack.log.info(\"\");\n if (report.result === \"pass\") {\n clack.log.success(chalk.green(\"Result: pass\"));\n } else if (report.result === \"pass-with-recommendation\") {\n clack.log.warn(chalk.yellow(\"Result: pass with a recommendation\"));\n if (report.recommendation) clack.log.info(` ${report.recommendation}`);\n } else {\n clack.log.error(chalk.red(\"Result: fail\"));\n }\n\n clack.outro(\"\");\n}\n\nfunction readLastReport(targetDir: string): VerifyReport | null {\n const reportFile = path.join(targetDir, \".cs-wizard\", \"last-report.json\");\n if (!fs.existsSync(reportFile)) return null;\n try {\n return JSON.parse(fs.readFileSync(reportFile, \"utf-8\")) as VerifyReport;\n } catch {\n return null;\n }\n}\n","import chalk from \"chalk\";\n\nexport const SORCERER =\n chalk.magenta(`\n ____\n .'* *.'\n __/_*_*(_\n / _______ \\\\\n _\\\\_)/___\\\\(_/_\n / _((\\\\- -/))_ \\\\\n \\\\ \\\\())(-)(()/ /\n ' \\\\(((()))/ '\n / ' \\\\)).))/ ' \\\\\n / _ \\\\ - | - /_ \\\\\n ( ( .;''';. .' )\n _\\\\\"__ / )\\\\ __\"/_\n \\\\/ \\\\ ' / \\\\/\n .' '...' ' )\n / / | \\\\ \\\\\n / . . . \\\\\n / . . \\\\\n / / | \\\\ \\\\\n .' / b '. '.\n _.-' / Bb '-. '-._\n _.-' | BBb '-. '-.\n(________mrf\\\\____.dBBBb.________)____)\n`) +\n chalk.bold.magenta(\"\\n CS Sorcerer\") +\n chalk.dim('\\n \"Your tag shall be cast.\"\\n');\n","import * as clack from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport path from \"node:path\";\nimport fs from \"node:fs\";\nimport { readState } from \"../../tools/state.js\";\nimport { normalizeTagId, validateTagId } from \"../../tools/tag-id.js\";\nimport type { VerifyOptions } from \"./types.js\";\nimport { makeLogger, fail, emitStdout } from \"./logger.js\";\nimport { acquireBrowser, handleNoDisplay, closeAndExit } from \"./browser.js\";\nimport { runPreflight } from \"./preflight.js\";\nimport { runVerifySession } from \"./session.js\";\nimport { analyze } from \"./analyze.js\";\nimport { printHumanReport } from \"./report.js\";\n\n// Public surface kept stable for callers (cli.ts) and consumers/tests.\nexport type { VerifyReport } from \"./types.js\";\nexport { analyze } from \"./analyze.js\";\nexport { historyHookScript, overlayScript } from \"./inject.js\";\n\nexport async function verify(options: VerifyOptions): Promise<void> {\n const targetDir = path.resolve(options.dir);\n const log = makeLogger(!!options.json);\n\n // --- Diagnostics-only mode: report the browser environment and exit ---\n if (options.preflight) {\n await runPreflight(targetDir, options, log);\n return;\n }\n\n const tagId = await resolveTagId(options, targetDir);\n const rawProjectId = readState(targetDir)?.projectId;\n const projectId =\n rawProjectId !== null && rawProjectId !== undefined\n ? String(rawProjectId).trim()\n : null;\n const url = await resolveUrl(options);\n\n log.info(`Tag ID: ${chalk.cyan(tagId)}`);\n log.info(`Opening: ${chalk.cyan(url)}`);\n\n // --- Acquire a real browser (system Chrome/Edge first, then bundled) ---\n // verify opens a visible window, so a headless Linux box (no display) can't run it.\n if (\n process.platform === \"linux\" &&\n !process.env.DISPLAY &&\n !process.env.WAYLAND_DISPLAY\n ) {\n handleNoDisplay(options, log, targetDir);\n }\n const browser = await acquireBrowser(options, log, targetDir);\n\n const trace = await runVerifySession(browser, url, log);\n\n const report = analyze({ url, projectId, tagId, ...trace });\n\n // Persist a single throwaway report (not the old stateful checklist).\n const reportPath = path.join(targetDir, \".cs-wizard\", \"last-report.json\");\n fs.mkdirSync(path.dirname(reportPath), { recursive: true });\n fs.writeFileSync(reportPath, JSON.stringify(report, null, 2));\n\n if (options.json) {\n emitStdout(JSON.stringify(report, null, 2) + \"\\n\");\n return closeAndExit(browser, report.result === \"fail\" ? 1 : 0);\n }\n\n printHumanReport(report, log);\n // Machine-readable block so an agent can parse stdout deterministically.\n emitStdout(\n \"\\n```json cs-wizard-report\\n\" + JSON.stringify(report) + \"\\n```\\n\",\n );\n return closeAndExit(browser, report.result === \"fail\" ? 1 : 0);\n}\n\n/** Resolve the tag id from --tag-id → state → an interactive prompt. */\nasync function resolveTagId(\n options: VerifyOptions,\n targetDir: string,\n): Promise<string> {\n const state = readState(targetDir);\n\n if (options.tagId) {\n if (validateTagId(options.tagId)) {\n fail(\n `--tag-id must be the hashed tag ID (hex, ~13 chars, lowercase), got: ${options.tagId}`,\n );\n }\n return normalizeTagId(options.tagId);\n }\n if (state?.tagId) return state.tagId as string;\n\n if (options.json) {\n fail(\n \"No tag ID found. Run `wizard start` first, or pass --tag-id <hashed>.\",\n );\n }\n const answer = await clack.text({\n message:\n \"Enter your Contentsquare tag ID (hashed hex, e.g. 81c677ba742d7):\",\n placeholder: \"81c677ba742d7\",\n validate: v => validateTagId(v),\n });\n if (clack.isCancel(answer)) {\n clack.cancel(\"Verification cancelled.\");\n process.exit(0);\n }\n return normalizeTagId(answer);\n}\n\n/** Resolve the URL to open from --url or an interactive prompt. */\nasync function resolveUrl(options: VerifyOptions): Promise<string> {\n if (options.url) return options.url;\n\n if (options.json) fail(\"No URL provided. Pass --url <app-url>.\");\n const answer = await clack.text({\n message: \"What URL should I open? (start your dev server first)\",\n placeholder: \"http://localhost:3000\",\n validate: v =>\n /^https?:\\/\\//.test(v.trim())\n ? undefined\n : \"Enter a full URL (http://…).\",\n });\n if (clack.isCancel(answer)) {\n clack.cancel(\"Verification cancelled.\");\n process.exit(0);\n }\n return answer.trim();\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\nconst STATE_FILE = \".cs-wizard/state.json\";\n\nexport interface PlaywrightAvailability {\n available: boolean;\n detectedAt?: string;\n installedBy?: \"wizard\";\n userChoice?: \"skip\";\n promptedAt?: string;\n}\n\nexport function readState(dir: string): Record<string, unknown> | null {\n const stateFile = path.join(dir, STATE_FILE);\n if (fs.existsSync(stateFile)) {\n try {\n return JSON.parse(fs.readFileSync(stateFile, \"utf-8\"));\n } catch {\n return null;\n }\n }\n return null;\n}\n\nexport function writeState(dir: string, state: Record<string, unknown>): void {\n const stateFile = path.join(dir, STATE_FILE);\n fs.mkdirSync(path.dirname(stateFile), { recursive: true });\n fs.writeFileSync(stateFile, JSON.stringify(state, null, 2));\n}\n\nexport function readProjectId(dir: string): string | null {\n return (readState(dir)?.projectId as string) ?? null;\n}\n\nexport function readPlaywrightAvailability(\n dir: string,\n): PlaywrightAvailability | null {\n const v = readState(dir)?.playwright;\n if (v && typeof v === \"object\" && \"available\" in (v as object)) {\n return v as PlaywrightAvailability;\n }\n return null;\n}\n\nexport function writePlaywrightAvailability(\n dir: string,\n availability: PlaywrightAvailability,\n): void {\n const state = readState(dir) ?? {};\n state.playwright = availability;\n writeState(dir, state);\n}\n","/** True when the value looks like a hashed tag ID (lowercase hex, ~13 chars). */\nexport function isHashedTagId(value: string): boolean {\n return /^[0-9a-f]{10,20}$/.test(value.trim());\n}\n\n/** Validate a hashed tag ID. Returns an error message, or undefined when valid. */\nexport function validateTagId(value: string): string | undefined {\n return isHashedTagId(value)\n ? undefined\n : \"Tag ID is a lowercase hex string (~13 chars, e.g. 81c677ba742d7).\";\n}\n\n/** Normalize a hashed tag ID to its canonical (trimmed, lowercase) form. */\nexport function normalizeTagId(tagId: string): string {\n return tagId.trim().toLowerCase();\n}\n","import * as clack from \"@clack/prompts\";\n\nexport interface Logger {\n info: (m: string) => void;\n step: (m: string) => void;\n error: (m: string) => void;\n success: (m: string) => void;\n warn: (m: string) => void;\n /** Raw, unformatted passthrough to stderr (e.g. a child process's live output). */\n stream: (chunk: string) => void;\n}\n\nexport function makeLogger(humanOutputToStderr: boolean): Logger {\n // Raw foreign output (e.g. a child process) always goes to stderr unformatted,\n // so it never corrupts the stdout channel in either mode.\n const stream = (chunk: string) => process.stderr.write(chunk);\n if (humanOutputToStderr) {\n // Human lines are pushed to stderr so stdout is left free for another consumer\n // (e.g. a machine-readable report).\n const toErr = (m: string) => process.stderr.write(m + \"\\n\");\n return {\n info: toErr,\n step: toErr,\n error: toErr,\n success: toErr,\n warn: toErr,\n stream,\n };\n }\n return {\n info: m => clack.log.info(m),\n step: m => clack.log.step(m),\n error: m => clack.log.error(m),\n success: m => clack.log.success(m),\n warn: m => clack.log.warn(m),\n stream,\n };\n}\n\nexport function fail(message: string): never {\n process.stderr.write(message + \"\\n\");\n process.exit(1);\n}\n\n/**\n * The single place allowed to write to stdout in the verify command.\n *\n * stdout is the machine-readable channel: in --json mode it must carry ONLY the\n * report (or a structured `{ error }` signal) so an agent can parse it\n * deterministically. Every human-facing line goes through the Logger (stderr).\n * Keep all stdout writes funneled here so this invariant stays greppable.\n */\nexport function emitStdout(text: string): void {\n process.stdout.write(text);\n}\n","import * as clack from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport { spawn } from \"node:child_process\";\nimport { createRequire } from \"node:module\";\nimport { chromium } from \"playwright-core\";\nimport type { Browser } from \"playwright-core\";\nimport type { VerifyOptions } from \"./types.js\";\nimport { emitStdout, type Logger } from \"./logger.js\";\nimport { writeArtifact } from \"./artifact.js\";\n\n/** How a browser-launch attempt failed, used to pick the right remedy. */\ntype BrowserFailureClass = \"missing\" | \"missing-libs\" | \"blocked\" | \"unknown\";\n\ninterface LaunchAttempt {\n label: string;\n channel?: string;\n klass: BrowserFailureClass;\n message: string;\n}\n\ninterface LaunchResult {\n browser: Browser | null;\n attempts: LaunchAttempt[];\n}\n\n/** Failure codes recorded in the breadcrumb and surfaced to agents on stdout. */\ntype BrowserFailureCode =\n | \"BROWSER_LAUNCH_FAILED\"\n | \"NO_BROWSER\"\n | \"MISSING_LIBS\"\n | \"BLOCKED_LAUNCH\"\n | \"NO_DISPLAY\";\n\n/** Signatures of a download blocked by a corporate proxy or an untrusted CA. */\nconst PROXY_CERT_RE =\n /self.signed certificate|unable to (?:verify|get local issuer)|CERT_|SSL|ECONNREFUSED|ETIMEDOUT|EAI_AGAIN|ENOTFOUND|getaddrinfo|tunneling socket|proxy/i;\n\n/** Process exit code paired with each browser failure (single source of truth). */\nconst BROWSER_FAILURE_EXIT_CODE: Record<BrowserFailureCode, number> = {\n BROWSER_LAUNCH_FAILED: 1,\n NO_BROWSER: 2,\n MISSING_LIBS: 3,\n BLOCKED_LAUNCH: 4,\n NO_DISPLAY: 5,\n};\n\n/** Close the browser (ignoring teardown errors) and exit with the given code. */\nexport async function closeAndExit(\n browser: Browser,\n code: number,\n): Promise<never> {\n await browser.close().catch(() => {});\n process.exit(code);\n}\n\n/**\n * Get a launched browser, or exit with a class-specific message and code.\n * Tries system Chrome/Edge first, then a pre-downloaded bundled Chromium, and\n * only offers a download when nothing is installed at all.\n */\nexport async function acquireBrowser(\n options: VerifyOptions,\n log: Logger,\n targetDir: string,\n): Promise<Browser> {\n let result = await tryLaunch();\n if (result.browser) return result.browser;\n\n let remedy = decideRemedy(result.attempts);\n\n // A browser exists but is missing OS libraries — a download won't fix it.\n if (remedy === \"missing-libs\") {\n failBrowser(options, log, targetDir, \"MISSING_LIBS\", result.attempts, () =>\n printMissingLibsHelp(log, result.attempts),\n );\n }\n\n // A browser exists but refused to launch (enterprise policy, locked profile…).\n if (remedy === \"blocked\") {\n failBrowser(\n options,\n log,\n targetDir,\n \"BLOCKED_LAUNCH\",\n result.attempts,\n () => printBlockedHelp(log, result.attempts),\n );\n }\n\n // Nothing installed — offer to download the bundled Chromium (with consent).\n if (remedy === \"missing\") {\n const install = await ensureBrowser(options, log);\n if (!install.ok) {\n const attempts = result.attempts;\n if (install.proxyHint) {\n failBrowser(options, log, targetDir, \"NO_BROWSER\", attempts, () =>\n printProxyHelp(log),\n );\n }\n failBrowser(options, log, targetDir, \"NO_BROWSER\", attempts, () =>\n printBrowserHelp(log, lastError(attempts)),\n );\n }\n // Re-launch after a successful download.\n result = await tryLaunch();\n if (result.browser) return result.browser;\n // Downloaded but still won't launch — on Linux this is almost always libs.\n remedy = decideRemedy(result.attempts);\n if (remedy === \"missing-libs\") {\n failBrowser(\n options,\n log,\n targetDir,\n \"MISSING_LIBS\",\n result.attempts,\n () => printMissingLibsHelp(log, result.attempts),\n );\n }\n failBrowser(\n options,\n log,\n targetDir,\n \"BROWSER_LAUNCH_FAILED\",\n result.attempts,\n () => printBrowserHelp(log, lastError(result.attempts)),\n );\n }\n\n // Unknown failure — surface the raw error.\n failBrowser(\n options,\n log,\n targetDir,\n \"BROWSER_LAUNCH_FAILED\",\n result.attempts,\n () => {\n log.error(`Could not launch a browser: ${lastError(result.attempts)}`);\n },\n );\n}\n\n/** Try system Chrome, then Edge, then bundled Chromium; collect classified failures. */\nasync function tryLaunch(): Promise<LaunchResult> {\n const configs: { label: string; channel?: string }[] = [\n { label: \"chrome\", channel: \"chrome\" },\n { label: \"msedge\", channel: \"msedge\" },\n { label: \"chromium\" }, // bundled, if `playwright-core install chromium` was run\n ];\n const attempts: LaunchAttempt[] = [];\n for (const cfg of configs) {\n try {\n const browser = await chromium.launch({\n headless: false,\n ...(cfg.channel ? { channel: cfg.channel } : {}),\n });\n return { browser, attempts };\n } catch (err) {\n const message = (err as Error)?.message ?? String(err);\n attempts.push({\n label: cfg.label,\n channel: cfg.channel,\n klass: classifyLaunchError(message),\n message,\n });\n }\n }\n return { browser: null, attempts };\n}\n\n/** Bucket a launch error so the right remedy can be offered. */\nfunction classifyLaunchError(message: string): BrowserFailureClass {\n if (\n /loading shared librar|libnss3|libnspr4|libatk|libgbm|libasound|libgtk|libx11|GLIBC/i.test(\n message,\n )\n )\n return \"missing-libs\";\n if (\n /Executable doesn't exist|Chromium distribution|was not found|ENOENT|playwright install/i.test(\n message,\n )\n )\n return \"missing\";\n if (\n /policy|enterprise|SingletonLock|ProcessSingleton|cannot create default profile|user data directory is already in use|DevToolsActivePort|Target page, context or browser has been closed/i.test(\n message,\n )\n )\n return \"blocked\";\n return \"unknown\";\n}\n\n/** Pick the most actionable remedy across all attempts. */\nfunction decideRemedy(attempts: LaunchAttempt[]): BrowserFailureClass {\n const chromiumAttempt = attempts.find(a => a.label === \"chromium\");\n // If bundled Chromium simply isn't downloaded, that's the cleanest fix and it\n // also sidesteps enterprise policies on branded Chrome/Edge.\n if (chromiumAttempt?.klass === \"missing\") return \"missing\";\n if (attempts.some(a => a.klass === \"missing-libs\")) return \"missing-libs\";\n if (attempts.every(a => a.klass === \"missing\")) return \"missing\";\n if (attempts.some(a => a.klass === \"blocked\")) return \"blocked\";\n return \"unknown\";\n}\n\nfunction lastError(attempts: LaunchAttempt[]): string {\n return attempts[attempts.length - 1]?.message ?? \"unknown error\";\n}\n\n/** True when the failure is the browser dying, not the dev server being down. */\nexport function isBrowserGoneError(message: string): boolean {\n return /Target (?:page, context or browser|closed)|browser has been closed|Browser closed|crash|disconnected/i.test(\n message,\n );\n}\n\n/** Write a class-specific failure, a breadcrumb, and exit deterministically. */\nfunction failBrowser(\n options: VerifyOptions,\n log: Logger,\n targetDir: string,\n code: BrowserFailureCode,\n attempts: LaunchAttempt[],\n printHelp: () => void,\n): never {\n writeBrowserFailure(targetDir, code, attempts);\n printHelp();\n if (options.json) {\n // Structured signal on stdout so a stdout-only agent can branch on it.\n emitStdout(JSON.stringify({ error: code }) + \"\\n\");\n }\n process.exit(BROWSER_FAILURE_EXIT_CODE[code]);\n}\n\n/** Persist a reproducible breadcrumb of why the browser couldn't be acquired. */\nfunction writeBrowserFailure(\n targetDir: string,\n code: BrowserFailureCode,\n attempts: LaunchAttempt[],\n): void {\n writeArtifact(targetDir, \"last-browser-error.json\", {\n error: code,\n platform: `${process.platform} ${process.arch}`,\n display: process.env.DISPLAY ?? null,\n attempts: attempts.map(a => ({\n label: a.label,\n class: a.klass,\n message: a.message,\n })),\n ts: new Date().toISOString(),\n });\n}\n\n/** No graphical display on Linux: verify needs a visible window. */\nexport function handleNoDisplay(\n options: VerifyOptions,\n log: Logger,\n targetDir: string,\n): never {\n writeBrowserFailure(targetDir, \"NO_DISPLAY\", []);\n log.error(\n \"No display detected. `verify` opens a real browser window and needs a desktop session.\",\n );\n log.info(\n \"Run this on a machine with a graphical desktop — not a headless server or a plain SSH session.\",\n );\n if (options.json) emitStdout(JSON.stringify({ error: \"NO_DISPLAY\" }) + \"\\n\");\n process.exit(BROWSER_FAILURE_EXIT_CODE.NO_DISPLAY);\n}\n\n/**\n * Offer to download the bundled Chromium engine, then install it (with consent).\n * Returns whether an engine is now available, plus a hint when a proxy/CA blocked it.\n */\nasync function ensureBrowser(\n options: VerifyOptions,\n log: Logger,\n): Promise<{ ok: boolean; proxyHint: boolean }> {\n if (!options.installBrowser) {\n if (options.json) {\n // Agent-driven: don't prompt. State the exact re-run contract.\n log.error(\n \"NO_BROWSER: no Chrome/Edge/Chromium found. Get the user's consent, then re-run this exact command with --install-browser added.\",\n );\n return { ok: false, proxyHint: false };\n }\n const consent = await clack.confirm({\n message:\n \"No browser found. Download the Chromium engine now? (~280 MB, one-time)\",\n initialValue: true,\n });\n if (clack.isCancel(consent) || !consent)\n return { ok: false, proxyHint: false };\n }\n\n return installChromium(log);\n}\n\nfunction installChromium(\n log: Logger,\n): Promise<{ ok: boolean; proxyHint: boolean }> {\n const require = createRequire(import.meta.url);\n let cliPath: string;\n try {\n cliPath = require.resolve(\"playwright-core/cli.js\");\n } catch {\n log.error(\"Could not locate playwright-core CLI to install Chromium.\");\n return Promise.resolve({ ok: false, proxyHint: false });\n }\n\n log.step(\"Downloading Chromium (one-time)…\");\n return new Promise(resolve => {\n const child = spawn(process.execPath, [cliPath, \"install\", \"chromium\"], {\n // Forward proxy / CA / mirror settings so corporate networks can download.\n env: { ...process.env },\n // Never inherit stdout: it is reserved for the JSON report in --json mode.\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n let output = \"\";\n const onData = (chunk: Buffer) => {\n const text = chunk.toString();\n output += text;\n log.stream(text);\n };\n child.stdout?.on(\"data\", onData);\n child.stderr?.on(\"data\", onData);\n child.on(\"error\", err => {\n output += String((err as Error)?.message ?? err);\n resolve({ ok: false, proxyHint: PROXY_CERT_RE.test(output) });\n });\n child.on(\"close\", code => {\n resolve({\n ok: code === 0,\n proxyHint: code !== 0 && PROXY_CERT_RE.test(output),\n });\n });\n });\n}\n\nfunction printBrowserHelp(log: Logger, errMessage: string): void {\n log.error(\"Could not launch a browser.\");\n log.info(\"Install one of the following, then re-run:\");\n log.info(\n ` • Google Chrome (recommended) — ${chalk.cyan(\"https://www.google.com/chrome/\")}`,\n );\n log.info(\n ` • or the bundled engine — ${chalk.cyan(\"npx playwright-core install chromium\")}`,\n );\n log.info(chalk.dim(`(${errMessage})`));\n}\n\nfunction printMissingLibsHelp(log: Logger, attempts: LaunchAttempt[]): void {\n log.error(\"A browser was found but is missing system libraries.\");\n log.info(\"Install the libraries Chromium needs, then re-run:\");\n log.info(` ${chalk.cyan(\"sudo npx playwright-core install-deps chromium\")}`);\n log.info(chalk.dim(`(${lastError(attempts)})`));\n}\n\nfunction printBlockedHelp(log: Logger, attempts: LaunchAttempt[]): void {\n log.error(\"A browser was found but refused to launch.\");\n log.info(\n \"This is usually an enterprise policy or a profile that is already in use.\",\n );\n log.info(\"Try one of the following, then re-run:\");\n log.info(\" • Close all open Chrome/Edge windows and try again.\");\n log.info(\n ` • Or use a clean bundled engine — ${chalk.cyan(\"npx playwright-core install chromium\")}, then re-run with ${chalk.cyan(\"--install-browser\")}.`,\n );\n log.info(chalk.dim(`(${lastError(attempts)})`));\n}\n\nfunction printProxyHelp(log: Logger): void {\n log.error(\n \"Could not download Chromium — this looks like a proxy or certificate issue.\",\n );\n log.info(\"If you are behind a corporate proxy, set these and re-run:\");\n for (const line of proxyEnvExamples()) {\n log.info(\n ` ${chalk.cyan(line.command)}${line.note ? ` ${chalk.dim(line.note)}` : \"\"}`,\n );\n }\n}\n\n/** Env-var examples in the syntax of the current OS's default shell. */\nfunction proxyEnvExamples(): { command: string; note?: string }[] {\n const vars: { name: string; value: string; note?: string }[] = [\n { name: \"HTTPS_PROXY\", value: \"http://your-proxy:port\" },\n { name: \"NODE_EXTRA_CA_CERTS\", value: \"/path/to/corporate-ca.pem\" },\n {\n name: \"PLAYWRIGHT_DOWNLOAD_HOST\",\n value: \"http://your-mirror\",\n note: \"(if your org mirrors the browser CDN)\",\n },\n ];\n if (process.platform === \"win32\") {\n // PowerShell is the modern default shell on Windows.\n return vars.map(v => ({\n command: `$env:${v.name}=\"${v.value}\"`,\n note: v.note,\n }));\n }\n return vars.map(v => ({\n command: `export ${v.name}=${v.value}`,\n note: v.note,\n }));\n}\n","import path from \"node:path\";\nimport fs from \"node:fs\";\n\n/** Best-effort JSON write under `.cs-wizard/`; never throws (a breadcrumb must not fail the command). */\nexport function writeArtifact(\n targetDir: string,\n fileName: string,\n data: unknown,\n): void {\n try {\n const dir = path.join(targetDir, \".cs-wizard\");\n fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(path.join(dir, fileName), JSON.stringify(data, null, 2));\n } catch {\n // Best-effort artifact; never fail the command because of it.\n }\n}\n","import chalk from \"chalk\";\nimport path from \"node:path\";\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport { createRequire } from \"node:module\";\nimport { chromium } from \"playwright-core\";\nimport type { VerifyOptions } from \"./types.js\";\nimport { emitStdout, type Logger } from \"./logger.js\";\nimport { writeArtifact } from \"./artifact.js\";\n\n/** Exit code when `verify --preflight` finds no working browser. */\nconst PREFLIGHT_NO_BROWSER_EXIT_CODE = 2;\n\ntype ChannelProbe = { ok: boolean; version?: string; error?: string };\n\n// --- Preflight diagnostics: report the browser environment, then exit ---\nexport async function runPreflight(\n targetDir: string,\n options: VerifyOptions,\n log: Logger,\n): Promise<void> {\n const browsersPath =\n process.env.PLAYWRIGHT_BROWSERS_PATH ?? defaultBrowsersPath();\n\n let bundledChromiumPath: string | null = null;\n let bundledChromiumPresent = false;\n try {\n bundledChromiumPath = chromium.executablePath();\n bundledChromiumPresent =\n !!bundledChromiumPath && fs.existsSync(bundledChromiumPath);\n } catch {\n bundledChromiumPath = null;\n }\n\n const systemChrome = await probeChannel(\"chrome\");\n const systemEdge = await probeChannel(\"msedge\");\n const bundledChromium = await probeChannel(undefined);\n const anyOk = systemChrome.ok || systemEdge.ok || bundledChromium.ok;\n\n const info = {\n os: `${process.platform} ${process.arch}`,\n node: process.version,\n display:\n process.platform === \"linux\"\n ? (process.env.DISPLAY ?? process.env.WAYLAND_DISPLAY ?? null)\n : \"n/a\",\n playwrightCoreVersion: readPlaywrightCoreVersion(),\n browsersPath,\n bundledChromiumPath,\n bundledChromiumPresent,\n systemChrome,\n systemEdge,\n bundledChromium,\n anyBrowserAvailable: anyOk,\n };\n\n // Persist the snapshot so users can attach it to a support request.\n writeArtifact(targetDir, \"last-preflight.json\", info);\n\n if (options.json) {\n emitStdout(JSON.stringify(info, null, 2) + \"\\n\");\n process.exit(anyOk ? 0 : PREFLIGHT_NO_BROWSER_EXIT_CODE);\n }\n\n log.step(chalk.bold(\"verify preflight\"));\n log.info(`OS: ${info.os} • Node: ${info.node}`);\n log.info(`Display: ${formatValue(info.display)}`);\n log.info(`playwright-core: ${formatValue(info.playwrightCoreVersion)}`);\n log.info(`Browsers cache: ${formatValue(browsersPath)}`);\n log.info(\n `Bundled Chromium present: ${bundledChromiumPresent ? chalk.green(\"yes\") : chalk.yellow(\"no\")}`,\n );\n log.info(probeLine(\"System Chrome\", systemChrome));\n log.info(probeLine(\"System Edge\", systemEdge));\n log.info(probeLine(\"Bundled Chromium\", bundledChromium));\n log.info(\"\");\n if (anyOk) {\n log.success(chalk.green(\"A browser is available — verify should work.\"));\n } else {\n log.warn(\n chalk.yellow(\n \"No working browser found. Run `verify --install-browser`, or install Google Chrome.\",\n ),\n );\n }\n process.exit(anyOk ? 0 : PREFLIGHT_NO_BROWSER_EXIT_CODE);\n}\n\n/** Briefly launch a channel headlessly to confirm it works and read its version. */\nasync function probeChannel(channel?: string): Promise<ChannelProbe> {\n try {\n const browser = await chromium.launch({\n headless: true,\n ...(channel ? { channel } : {}),\n });\n const version = browser.version();\n await browser.close().catch(() => {});\n return { ok: true, version };\n } catch (err) {\n return {\n ok: false,\n error: firstLine((err as Error)?.message ?? String(err)),\n };\n }\n}\n\nfunction readPlaywrightCoreVersion(): string | null {\n try {\n const require = createRequire(import.meta.url);\n const pkgPath = require.resolve(\"playwright-core/package.json\");\n return (\n (JSON.parse(fs.readFileSync(pkgPath, \"utf8\")).version as string) ?? null\n );\n } catch {\n return null;\n }\n}\n\nfunction defaultBrowsersPath(): string {\n const home = os.homedir();\n if (process.platform === \"darwin\")\n return path.join(home, \"Library\", \"Caches\", \"ms-playwright\");\n if (process.platform === \"win32\")\n return path.join(home, \"AppData\", \"Local\", \"ms-playwright\");\n return path.join(home, \".cache\", \"ms-playwright\");\n}\n\nfunction probeLine(label: string, probe: ChannelProbe): string {\n if (probe.ok)\n return `${chalk.green(\"✓\")} ${label}: ${probe.version ?? \"available\"}`;\n return `${chalk.yellow(\"✗\")} ${label}: ${chalk.dim(probe.error ?? \"unavailable\")}`;\n}\n\nfunction firstLine(text: string): string {\n return text.split(\"\\n\")[0];\n}\n\nfunction formatValue(value: unknown): string {\n return value === null || value === undefined || value === \"\"\n ? chalk.dim(\"—\")\n : String(value);\n}\n","import chalk from \"chalk\";\nimport type {\n Browser,\n BrowserContext,\n Page,\n Request,\n ConsoleMessage,\n} from \"playwright-core\";\nimport type { CsRequest, SessionTrace, Violation } from \"./types.js\";\nimport type { Logger } from \"./logger.js\";\nimport {\n NAV_BINDING,\n DONE_BINDING,\n historyHookScript,\n overlayScript,\n} from \"./inject.js\";\nimport { isBrowserGoneError, closeAndExit } from \"./browser.js\";\n\n// CS_HOST_RE validates a parsed hostname (anchored, so `evilcontentsquare.net`\n// can't slip through), while CS_DOMAIN_RE scans free-form text.\nconst CS_DOMAIN = String.raw`contentsquare\\.(net|com)`;\nconst CS_HOST_RE = new RegExp(String.raw`(^|\\.)${CS_DOMAIN}$`, \"i\");\nconst CS_DOMAIN_RE = new RegExp(CS_DOMAIN, \"i\");\nconst CSP_RE =\n /content-security-policy|refused to|violates the following|err_blocked_by_csp|blocked:csp/i;\n/** Contentsquare tag script path (vs. a tracking beacon) on a CS host. */\nconst TAG_SCRIPT_RE = /\\/uxa\\/[^/]+\\.js(\\?|$)/i;\n\n// --- Live session: drive a real browser and record what the tag does ---\n\n/**\n * Open the app, inject the page hooks, and record navigations, Contentsquare\n * requests, and CSP violations until the user clicks \"Done\" or closes the window.\n * Exits the process if the page never loads (dev server down or browser crashed).\n */\nexport async function runVerifySession(\n browser: Browser,\n url: string,\n log: Logger,\n): Promise<SessionTrace> {\n const navEvents: SessionTrace[\"navEvents\"] = [];\n const csRequests: CsRequest[] = [];\n const violations: Violation[] = [];\n\n // Resolved when the user clicks \"Done\" in the on-page overlay.\n let signalDone: () => void = () => {};\n const doneClicked = new Promise<void>(resolve => {\n signalDone = resolve;\n });\n\n let context: BrowserContext;\n try {\n context = await browser.newContext();\n\n // Stream SPA route changes from the page into Node in real time.\n await context.exposeBinding(\n NAV_BINDING,\n (_source, data: { type: string; url: string }) => {\n navEvents.push({ type: data.type, url: data.url, ts: Date.now() });\n },\n );\n await context.addInitScript(historyHookScript());\n\n // Show an on-page overlay so the user knows what to do, with a \"Done\" button.\n await context.exposeBinding(DONE_BINDING, () => signalDone());\n await context.addInitScript(overlayScript());\n\n context.on(\"request\", (req: Request) => recordCsRequest(req, csRequests));\n context.on(\"requestfailed\", (req: Request) =>\n recordRequestViolation(req, violations),\n );\n\n const page = await context.newPage();\n page.on(\"console\", (msg: ConsoleMessage) =>\n recordConsoleViolation(msg, violations),\n );\n\n await page.goto(url, { waitUntil: \"domcontentloaded\", timeout: 30_000 });\n } catch (err) {\n const message = (err as Error)?.message ?? String(err);\n if (isBrowserGoneError(message)) {\n log.error(\n `The browser closed before the page finished loading. (${message})`,\n );\n } else {\n log.error(\n `Could not load ${url}. Is the dev server running? (${message})`,\n );\n }\n return closeAndExit(browser, 1);\n }\n\n printBrowseInstructions(log);\n await waitForFinish(browser, context, doneClicked);\n\n return { navEvents, csRequests, violations };\n}\n\n/** Record a Contentsquare request, tagged as either the tag script or a beacon. */\nfunction recordCsRequest(req: Request, out: CsRequest[]): void {\n const host = safeHost(req.url());\n if (!host || !CS_HOST_RE.test(host)) return;\n const kind = TAG_SCRIPT_RE.test(req.url()) ? \"script\" : \"beacon\";\n out.push({ url: req.url(), ts: Date.now(), kind });\n}\n\n/** Record a failed Contentsquare request that looks like a CSP block. */\nfunction recordRequestViolation(req: Request, out: Violation[]): void {\n // Only Contentsquare hosts matter: a CSP block of the tag or a beacon is what\n // we care about, and scoping here matches the skill's documented contract.\n const host = safeHost(req.url());\n if (!host || !CS_HOST_RE.test(host)) return;\n const failure = req.failure()?.errorText ?? \"\";\n if (CSP_RE.test(failure)) {\n out.push({ source: \"request\", text: `${req.url()} — ${failure}` });\n }\n}\n\n/** Record a console message that reports a Contentsquare CSP violation. */\nfunction recordConsoleViolation(msg: ConsoleMessage, out: Violation[]): void {\n const text = msg.text();\n // Require a Contentsquare domain so unrelated CSP errors — including the\n // verifier's own injected overlay styles — don't trigger a spurious fail.\n if (CSP_RE.test(text) && CS_DOMAIN_RE.test(text)) {\n out.push({ source: \"console\", text });\n }\n}\n\nfunction printBrowseInstructions(log: Logger): void {\n log.info(\"\");\n log.step(chalk.bold(\"Browse your app now:\"));\n log.info(\" 1. Wait a moment for the first page to settle.\");\n log.info(\" 2. Click through a few in-app routes (and log in if needed).\");\n log.info(\n ` 3. Click ${chalk.bold(\"“Done”\")} in the banner (or close the window) to see the report.`,\n );\n log.info(\"\");\n}\n\nfunction waitForFinish(\n browser: Browser,\n context: BrowserContext,\n doneClicked: Promise<void>,\n): Promise<void> {\n return new Promise(resolve => {\n const finish = once(() => {\n browser.close().catch(() => {});\n resolve();\n });\n\n // Finish when the user closes the last browser window. We track open pages\n // because some Chrome installs keep the browser process alive after the window\n // closes (background apps), so `browser disconnected` alone is unreliable.\n const openPages = new Set<Page>(context.pages());\n const watchPage = (p: Page) => {\n p.on(\"close\", () => {\n openPages.delete(p);\n if (openPages.size === 0) finish();\n });\n };\n context.pages().forEach(watchPage);\n context.on(\"page\", p => {\n openPages.add(p);\n watchPage(p);\n });\n\n doneClicked.then(finish);\n browser.on(\"disconnected\", finish);\n context.on(\"close\", finish);\n process.once(\"SIGINT\", finish);\n });\n}\n\nfunction safeHost(u: string): string {\n try {\n return new URL(u).hostname;\n } catch {\n return \"\";\n }\n}\n\n/** Wrap a function so it runs at most once; later calls are no-ops. */\nfunction once(fn: () => void): () => void {\n let called = false;\n return () => {\n if (called) return;\n called = true;\n fn();\n };\n}\n","/**\n * Names of the callbacks the injected scripts use to talk back to Node.\n *\n * They are a contract between this module and session.ts: the scripts below\n * CALL `window.<binding>`, and session.ts REGISTERS them via `exposeBinding`.\n * Both sides must use the exact same string or the page-to-Node bridge\n * silently breaks.\n */\nexport const NAV_BINDING = \"__csWizardNav\";\nexport const DONE_BINDING = \"__csWizardDone\";\n\n/**\n * Injected into every page to surface client-side route changes.\n *\n * SPAs navigate by calling `history.pushState`/`replaceState` (or going\n * back/forward), which updates the URL without a real page load — so Playwright\n * sees no navigation event. We patch those history methods and listen for\n * `popstate`, calling back into Node on each change. That lets the verifier know\n * a \"page view\" happened and check whether the tag fired a pageview for it.\n */\nexport function historyHookScript(): string {\n return `(() => {\n const send = (type) => {\n try { window.${NAV_BINDING}({ type, url: location.href }); } catch {}\n };\n for (const name of ['pushState', 'replaceState']) {\n const orig = history[name];\n history[name] = function () {\n const r = orig.apply(this, arguments);\n send(name);\n return r;\n };\n }\n window.addEventListener('popstate', () => send('popstate'));\n })();`;\n}\n\n/**\n * Injected into every page: a fixed overlay banner telling the user to browse\n * their app and click \"Done\" when finished. Clicking Done calls back into Node.\n */\nexport function overlayScript(): string {\n return `(() => {\n const ID = '__cs-wizard-overlay';\n function mount() {\n if (!document.body || document.getElementById(ID)) return;\n const bar = document.createElement('div');\n bar.id = ID;\n bar.setAttribute('style', [\n 'position:fixed','left:50%','bottom:20px','transform:translateX(-50%)',\n 'z-index:2147483647','background:#1b1b2f','color:#fff',\n 'font:14px/1.4 system-ui,-apple-system,Segoe UI,sans-serif',\n 'padding:12px 16px','border-radius:10px','box-shadow:0 6px 24px rgba(0,0,0,.35)',\n 'display:flex','align-items:center','gap:14px','max-width:90vw'\n ].join(';'));\n const msg = document.createElement('span');\n msg.innerHTML = '<strong>Contentsquare check running.</strong> Click around a few pages, then press Done.';\n const btn = document.createElement('button');\n btn.textContent = 'Done';\n btn.setAttribute('style', [\n 'background:#6c5ce7','color:#fff','border:0','cursor:pointer',\n 'padding:8px 16px','border-radius:8px','font-weight:600','font-size:14px'\n ].join(';'));\n btn.onclick = () => {\n btn.disabled = true;\n btn.textContent = 'Finishing…';\n try { window.${DONE_BINDING}(); } catch {}\n };\n bar.appendChild(msg);\n bar.appendChild(btn);\n document.body.appendChild(bar);\n }\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', mount);\n } else {\n mount();\n }\n })();`;\n}\n","import type { CsRequest, NavEvent, VerifyReport, Violation } from \"./types.js\";\n\nconst SPA_TRACKING_RECOMMENDATION =\n \"Some in-app route changes did not fire a pageview. If this is a single-page app, \" +\n 'enable \"Tracking URL Changes\" in the Contentsquare app (Project and Users → Tracking URL Changes).';\n\nconst CSP_RECOMMENDATION =\n \"Content-Security-Policy violations were detected. The tag still loaded and fired pageviews, \" +\n \"but update your CSP to explicitly allow Contentsquare so tracking isn't blocked in stricter environments.\";\n\n/**\n * Turn one recorded browsing session into the verification report.\n *\n * Rather than correlate the two recorded streams (route changes and CS beacons)\n * by wall-clock time — which is racy on slow tag loads, bootstrap redirects, and\n * batched beacons — we compare them by page identity. Each CS pageview beacon\n * carries the page it fired for in its `url` query param, so \"did this route get\n * a pageview?\" is a set membership test, not a timing window. From that we derive\n * the four checks the report grades on:\n * 1. Tag script loaded — the `/uxa/*.js` tag was fetched from a CS host (and,\n * if so, whether its tag id matches the expected one).\n * 2. Initial pageview — the tag fired at least one pageview beacon. (The skill\n * contract is simply \"a further request to CS fired\"; no timing required.)\n * 3. Pageview coverage on navigation — every distinct in-app route the user\n * visited has a beacon reporting that same page.\n * 4. CSP violations — de-duplicated content-security-policy errors that could\n * block the tag.\n * `gradeResult` then folds these into a pass / pass-with-recommendation / fail.\n */\nexport function analyze(input: {\n url: string;\n projectId: string | null;\n tagId: string;\n navEvents: NavEvent[];\n csRequests: CsRequest[];\n violations: Violation[];\n}): VerifyReport {\n const { url, projectId, tagId, navEvents, csRequests, violations } = input;\n\n const scripts = csRequests.filter(r => r.kind === \"script\");\n const beacons = csRequests.filter(r => r.kind === \"beacon\");\n const tagScriptLoaded = scripts.length > 0;\n const tagIdMismatch =\n tagScriptLoaded && !scripts.some(s => s.url.includes(tagId));\n const pageviewBeacons = beacons.filter(b => isPageviewBeacon(b.url));\n\n // The set of pages CS reported a pageview for (normalized origin + pathname).\n const beaconPages = new Set(\n pageviewBeacons\n .map(b => beaconPageUrl(b.url))\n .filter((p): p is string => p !== null)\n .map(normalizePage),\n );\n\n // The tag firing at least one pageview beacon is enough for the initial-load check.\n const initialPageview = pageviewBeacons.length > 0;\n\n // Distinct in-app routes the user visited, excluding the landing page (graded\n // separately by `initialPageview`). A route is covered when a beacon reports\n // that same page — pure identity, no attribution window.\n const navigations = distinctRoutes(navEvents, url).map(nav => ({\n url: nav.url,\n type: nav.type,\n pageviewFired: beaconPages.has(normalizePage(nav.url)),\n }));\n const navigationsWithPageview = navigations.filter(\n n => n.pageviewFired,\n ).length;\n\n const cspViolations = dedupe(violations, v => v.text);\n\n const { result, recommendation } = gradeResult({\n tagScriptLoaded,\n initialPageview,\n cspViolations,\n navigations,\n navigationsWithPageview,\n });\n\n return {\n url,\n projectId,\n tagId,\n tagScriptLoaded,\n tagIdMismatch,\n initialPageview,\n navigations,\n navigationsWithPageview,\n cspViolations,\n result,\n recommendation,\n };\n}\n\n/**\n * The distinct in-app routes the user visited, in order of first visit,\n * excluding the landing page. Deduping by normalized URL collapses\n * replaceState bursts, the framework's bootstrap/hydration navigation, and\n * repeat visits to the same route — no timing windows needed. The landing page\n * is excluded because the initial load is graded by `initialPageview`.\n */\nfunction distinctRoutes(navEvents: NavEvent[], landingUrl: string): NavEvent[] {\n const landing = normalizePage(landingUrl);\n const seen = new Set<string>([landing]);\n const out: NavEvent[] = [];\n for (const ev of navEvents) {\n const key = normalizePage(ev.url);\n if (seen.has(key)) continue;\n seen.add(key);\n out.push(ev);\n }\n return out;\n}\n\n/** True when a request is a pageview beacon: its path ends in `/pageview`. */\nfunction isPageviewBeacon(beaconUrl: string): boolean {\n try {\n return new URL(beaconUrl).pathname.replace(/\\/+$/, \"\").endsWith(\"/pageview\");\n } catch {\n return false;\n }\n}\n\n/** The page URL a beacon reports (its `url` query param), or null if absent. */\nfunction beaconPageUrl(beaconUrl: string): string | null {\n try {\n return new URL(beaconUrl).searchParams.get(\"url\");\n } catch {\n return null;\n }\n}\n\n/** Normalize a URL to origin + pathname, ignoring query, hash, trailing slash. */\nfunction normalizePage(u: string): string {\n try {\n const { origin, pathname } = new URL(u);\n return origin + pathname.replace(/\\/+$/, \"\");\n } catch {\n return u.replace(/\\/+$/, \"\");\n }\n}\n\n/** Grade the observed checks into a pass/fail result and an optional recommendation. */\nfunction gradeResult(checks: {\n tagScriptLoaded: boolean;\n initialPageview: boolean;\n cspViolations: Violation[];\n navigations: { pageviewFired: boolean }[];\n navigationsWithPageview: number;\n}): { result: VerifyReport[\"result\"]; recommendation: string | null } {\n const {\n tagScriptLoaded,\n initialPageview,\n cspViolations,\n navigations,\n navigationsWithPageview,\n } = checks;\n\n // A missing tag script or no pageview at all is a hard fail — nothing works.\n if (!tagScriptLoaded || !initialPageview)\n return { result: \"fail\", recommendation: null };\n\n // The tag loaded and fired pageviews. Remaining issues (CSP violations that\n // didn't stop tracking, SPA routes without pageviews) are surfaced as\n // recommendations rather than failures.\n const recommendations: string[] = [];\n if (cspViolations.length > 0) recommendations.push(CSP_RECOMMENDATION);\n if (navigations.length > 0 && navigationsWithPageview < navigations.length)\n recommendations.push(SPA_TRACKING_RECOMMENDATION);\n\n if (recommendations.length > 0) {\n return {\n result: \"pass-with-recommendation\",\n recommendation: recommendations.join(\"\\n\"),\n };\n }\n return { result: \"pass\", recommendation: null };\n}\n\nfunction dedupe<T>(items: T[], key: (x: T) => string): T[] {\n const seen = new Set<string>();\n const out: T[] = [];\n for (const item of items) {\n const k = key(item);\n if (seen.has(k)) continue;\n seen.add(k);\n out.push(item);\n }\n return out;\n}\n","import chalk from \"chalk\";\nimport type { VerifyReport } from \"./types.js\";\nimport type { Logger } from \"./logger.js\";\n\n/** Cap on how many CSP violations the human report prints in full. */\nconst MAX_CSP_VIOLATIONS_SHOWN = 8;\n\nexport function printHumanReport(r: VerifyReport, log: Logger): void {\n const ok = chalk.green(\"✓\");\n const no = chalk.red(\"✗\");\n const warn = chalk.yellow(\"!\");\n\n log.info(\"\");\n log.step(chalk.bold(\"Verification report\"));\n log.info(`${r.tagScriptLoaded ? ok : no} Tag script loaded`);\n if (r.tagIdMismatch) {\n log.info(\n `${warn} Tag URL uses a different ID than ${chalk.cyan(r.tagId)} — check the tag ID used at install.`,\n );\n }\n log.info(`${r.initialPageview ? ok : no} First pageview sent on load`);\n\n if (r.navigations.length === 0) {\n log.info(\n `${warn} No in-app route changes were recorded — navigate a few routes to test SPA coverage.`,\n );\n } else {\n const icon = r.navigationsWithPageview === r.navigations.length ? ok : warn;\n log.info(\n `${icon} Pageviews on navigation: ${r.navigationsWithPageview}/${r.navigations.length}`,\n );\n for (const n of r.navigations) {\n log.info(` ${n.pageviewFired ? ok : no} ${n.type} → ${n.url}`);\n }\n }\n\n if (r.cspViolations.length > 0) {\n log.info(`${no} CSP violations (${r.cspViolations.length}):`);\n for (const v of r.cspViolations.slice(0, MAX_CSP_VIOLATIONS_SHOWN)) {\n log.info(` ${chalk.dim(\"-\")} ${v.text}`);\n }\n } else {\n log.info(`${ok} No CSP violations detected`);\n }\n\n log.info(\"\");\n if (r.result === \"pass\") {\n log.success(chalk.green(\"All checks passed.\"));\n } else if (r.result === \"pass-with-recommendation\") {\n log.warn(chalk.yellow(\"Passed with a recommendation:\"));\n for (const line of (r.recommendation ?? \"\").split(\"\\n\")) {\n log.info(` ${line}`);\n }\n } else {\n log.error(chalk.red(\"Some checks failed — see above.\"));\n }\n}\n","import * as clack from \"@clack/prompts\";\nimport chalk from \"chalk\";\nimport { exec } from \"node:child_process\";\nimport path from \"node:path\";\nimport fs from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { SORCERER } from \"./sorcerer.js\";\nimport { normalizeTagId, validateTagId } from \"../tools/tag-id.js\";\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst PACKAGE_ROOT = findPackageRoot(__dirname);\n\nconst SKILL_FILE = \"wizard-web-tag-install.md\";\nconst SKILL_PATH = `.cs-wizard/skills/${SKILL_FILE}`;\nconst SETUP_PROMPT = `Read and follow ${SKILL_PATH} — read it directly by path, it is gitignored so do not search for it.`;\n\ninterface StartOptions {\n dir: string;\n tagId?: string;\n}\n\nexport async function start(options: StartOptions): Promise<void> {\n process.stdout.write(SORCERER + \"\\n\");\n clack.intro(chalk.bold(\"Contentsquare Wizard — Start\"));\n\n const targetDir = path.resolve(options.dir);\n\n // 1. Resolve the tag ID — directly from --tag-id, prior state, or a prompt.\n const tagId = await resolveTagId(targetDir, options);\n clack.log.info(`Tag ID: ${chalk.cyan(tagId)}`);\n\n // 2. Copy the CLI-flow skill into .cs-wizard/skills/\n const spinner = clack.spinner();\n spinner.start(\"Setting up wizard skill...\");\n const wizardDir = path.join(targetDir, \".cs-wizard\");\n const skillsDir = path.join(wizardDir, \"skills\");\n fs.mkdirSync(skillsDir, { recursive: true });\n fs.copyFileSync(\n path.join(PACKAGE_ROOT, \"skills\", SKILL_FILE),\n path.join(skillsDir, SKILL_FILE),\n );\n spinner.stop(`Copied skill to ${chalk.cyan(SKILL_PATH)}`);\n\n // 3. Write wizard state config (so `verify` and the skill can read the tag ID).\n const state = readExistingConfig(targetDir) ?? {};\n state.tagId = tagId;\n state.startedAt = new Date().toISOString();\n fs.writeFileSync(\n path.join(wizardDir, \"state.json\"),\n JSON.stringify(state, null, 2),\n );\n\n // 4. Add .cs-wizard/ to .gitignore\n ensureGitignore(targetDir);\n\n clack.log.success(\"Wizard ready!\");\n clack.log.info(\"\");\n\n await showNextSteps();\n}\n\n// --- Tag ID resolution ---\n\nasync function resolveTagId(\n targetDir: string,\n options: StartOptions,\n): Promise<string> {\n // 1. --tag-id flag wins.\n if (options.tagId) {\n const err = validateTagId(options.tagId);\n if (err) {\n clack.log.error(`Invalid --tag-id value: ${err}`);\n process.exit(1);\n }\n return normalizeTagId(options.tagId);\n }\n\n // 2. Reuse a value already stored in state.json.\n const existing = readExistingConfig(targetDir);\n if (existing?.tagId) {\n const reuse = await clack.confirm({\n message: `Found existing tag ID ${chalk.cyan(String(existing.tagId))}. Use it?`,\n initialValue: true,\n });\n if (clack.isCancel(reuse)) {\n clack.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n if (reuse) {\n return String(existing.tagId);\n }\n }\n\n // 3. Prompt for the hashed tag ID.\n const response = await clack.text({\n message:\n \"Enter your Contentsquare tag ID (hashed hex, e.g. 81c677ba742d7):\",\n placeholder: \"81c677ba742d7\",\n validate: v => validateTagId(v),\n });\n if (clack.isCancel(response)) {\n clack.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n return normalizeTagId(response);\n}\n\n// --- Next steps ---\n\nasync function showNextSteps(): Promise<void> {\n clack.log.step(chalk.bold(\"Next steps:\"));\n clack.log.info(\n \" 1. Open your AI coding agent (Copilot, Cursor, Claude Code, etc.)\",\n );\n\n const copied = await copyToClipboard(SETUP_PROMPT);\n if (copied) {\n clack.log.success(\n ` 2. ${chalk.bold.green(\"Prompt copied to clipboard!\")} Paste it in your agent to start.`,\n );\n } else {\n clack.log.info(\" 2. Tell your agent:\");\n const border = chalk.gray(\"─\".repeat(40));\n clack.log.info(` ${border}`);\n for (const line of SETUP_PROMPT.split(\"\\n\")) {\n clack.log.info(` ${chalk.cyan(line)}`);\n }\n clack.log.info(` ${border}`);\n }\n\n clack.log.info(\"\");\n clack.outro(\n `Now ask your AI agent: ${chalk.cyan(`Read and follow ${SKILL_PATH}`)}`,\n );\n}\n\n// --- Shared file helpers ---\n\nfunction readExistingConfig(targetDir: string): Record<string, unknown> | null {\n const stateFile = path.join(targetDir, \".cs-wizard\", \"state.json\");\n if (fs.existsSync(stateFile)) {\n try {\n return JSON.parse(fs.readFileSync(stateFile, \"utf-8\"));\n } catch {\n return null;\n }\n }\n return null;\n}\n\nfunction ensureGitignore(targetDir: string): void {\n const gitignorePath = path.join(targetDir, \".gitignore\");\n const entry = \".cs-wizard/\";\n\n if (fs.existsSync(gitignorePath)) {\n const content = fs.readFileSync(gitignorePath, \"utf-8\");\n if (!content.includes(entry)) {\n fs.appendFileSync(\n gitignorePath,\n `\\n# Contentsquare wizard (generated)\\n${entry}\\n`,\n );\n }\n } else {\n fs.writeFileSync(\n gitignorePath,\n `# Contentsquare wizard (generated)\\n${entry}\\n`,\n );\n }\n}\n\nfunction copyToClipboard(text: string): Promise<boolean> {\n return new Promise(resolve => {\n const cmd =\n process.platform === \"win32\"\n ? `echo ${text.replace(/[\"&|<>^]/g, \"^$&\")} | clip`\n : process.platform === \"darwin\"\n ? `echo ${JSON.stringify(text)} | pbcopy`\n : `echo ${JSON.stringify(text)} | xclip -selection clipboard || echo ${JSON.stringify(text)} | xsel --clipboard --input`;\n exec(cmd, err => resolve(!err));\n });\n}\n\n// --- package root discovery (skills live next to package.json) ---\n\nfunction findPackageRoot(dir: string): string {\n let current = dir;\n for (let i = 0; i < 5; i++) {\n if (\n fs.existsSync(path.join(current, \"package.json\")) &&\n fs.existsSync(path.join(current, \"skills\"))\n ) {\n return current;\n }\n current = path.dirname(current);\n }\n return path.resolve(dir, \"..\");\n}\n"],"mappings":"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","names":["fileURLToPath","chalk","chalk","clack","chalk","path","fs","fs","path","clack","text","clack","chalk","path","fs","log","require","text","chalk","chalk","path","fs","createRequire","chromium","log","chromium","fs","chalk","require","createRequire","path","text","chalk","log","text","chalk","chalk","log","path","log","chalk","fs","clack","chalk","path","fs","__dirname","path","chalk","resolveTagId","spinner","fs","text","fileURLToPath"]}
package/package.json CHANGED
@@ -1,18 +1,21 @@
1
1
  {
2
2
  "name": "@contentsquare/wizard",
3
- "version": "2.0.0",
3
+ "version": "2.2.1",
4
4
  "description": "AI-assisted Contentsquare tag installation and configuration",
5
5
  "type": "module",
6
6
  "bin": {
7
- "wizard-cs": "./dist/cli.js"
7
+ "wizard-cs": "dist/cli.js"
8
8
  },
9
9
  "scripts": {
10
10
  "build": "tsup",
11
11
  "dev": "tsup --watch",
12
12
  "start": "node dist/cli.js",
13
13
  "try": "tsx src/cli.ts",
14
+ "typecheck": "tsc --noEmit",
14
15
  "lint": "eslint .",
15
16
  "lint:fix": "eslint . --fix",
17
+ "test": "vitest run",
18
+ "test:watch": "vitest",
16
19
  "format": "prettier --write .",
17
20
  "format:check": "prettier --check .",
18
21
  "prepublishOnly": "npm run build"
@@ -28,9 +31,9 @@
28
31
  "ai"
29
32
  ],
30
33
  "license": "MIT",
31
- "repository": {
32
- "type": "git",
33
- "url": "git+https://github.com/ContentSquare/wizard.git"
34
+ "homepage": "https://docs.contentsquare.com/en/web/#ai-assisted-setup",
35
+ "engines": {
36
+ "node": ">=20"
34
37
  },
35
38
  "publishConfig": {
36
39
  "access": "public"
@@ -51,6 +54,7 @@
51
54
  "tsup": "^8.4.0",
52
55
  "tsx": "^4.19.4",
53
56
  "typescript": "^5.8.3",
54
- "typescript-eslint": "^8.34.1"
57
+ "typescript-eslint": "^8.34.1",
58
+ "vitest": "^4.1.9"
55
59
  }
56
60
  }
@@ -3,7 +3,7 @@ name: wizard-web-tag-install
3
3
  description: Install and verify the Contentsquare tracking tag in any web project using the wizard CLI. Use when asked to "install Contentsquare", "add the CS tag", "set up Contentsquare analytics", or verify Contentsquare tracking. Verification runs through `npx @contentsquare/wizard verify`, which drives an embedded Playwright browser.
4
4
  metadata:
5
5
  author: Contentsquare
6
- version: "1.0.0"
6
+ version: "2.2.1" # x-release-please-version
7
7
  ---
8
8
 
9
9
  # Install Contentsquare Tag (CLI flow)
@@ -340,13 +340,34 @@ When `verify` returns `result: "pass"` (or `pass-with-recommendation`), report:
340
340
  - Tag installed: <framework> via @contentsquare/tag-sdk
341
341
  - Tag script loading: ✓
342
342
  - First pageview sent: ✓
343
- - Pageviews on navigation: <n>/<n>
343
+ - In-app routes tracked: <navigationsWithPageview>/<navigations.length> routes
344
344
  - CSP: <no issues / fixed>
345
345
  ```
346
346
 
347
347
  If the report was `pass-with-recommendation`, add the recommendation verbatim (enabling
348
348
  **Tracking URL Changes** in the Contentsquare app for SPA route changes).
349
349
 
350
+ ### How to phrase the route-tracking line (avoid misleading the developer)
351
+
352
+ The `<n>/<n>` figure is **distinct in-app routes that fired a pageview**, not the
353
+ number of beacons sent or the number of times the developer navigated. `verify`
354
+ collapses the trace before grading:
355
+
356
+ - The **initial landing page** is excluded (it's covered by "First pageview sent").
357
+ - **Repeat visits to the same route are counted once.** If the developer browsed
358
+ `/` → `/products` → `/cart` → `/`, that is **2** distinct in-app routes
359
+ (`/products`, `/cart`), so a clean result reads `2/2 routes` — even though more
360
+ than two navigations happened.
361
+
362
+ Therefore:
363
+
364
+ - Phrase it as routes **covered**, e.g. "both in-app routes you visited fired a
365
+ pageview". Do **not** say "2 pageviews were sent" — that conflates routes with
366
+ beacons and will confuse the developer.
367
+ - List the route paths from `navigations[].url`, not a count of network requests.
368
+ - If `navigations` is empty, say no in-app route changes were exercised (so SPA
369
+ tracking wasn't tested), rather than reporting `0/0` as a pass signal.
370
+
350
371
  ---
351
372
 
352
373
  ## Troubleshooting