@contentful/experience-design-system-cli 2.39.1-dev-build-c1faff77.0 → 2.39.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/dist/index.js CHANGED
@@ -19407,325 +19407,6 @@ var init_PageContainer = __esm({
19407
19407
  }
19408
19408
  });
19409
19409
 
19410
- // packages/experience-design-system-cli/src/tui/settings/debug-mode/debug-mode-store.ts
19411
- function toRetentionDays(value) {
19412
- return RETENTION_CHOICES.find((choice) => choice === value) ?? DEFAULT_RETENTION_DAYS;
19413
- }
19414
- async function readDebugModeSetting() {
19415
- const { debugMode } = await readSettings2();
19416
- const saved = debugMode ?? {};
19417
- return {
19418
- enabled: typeof saved.enabled === "boolean" ? saved.enabled : true,
19419
- retentionDays: toRetentionDays(saved.retentionDays)
19420
- };
19421
- }
19422
- async function writeDebugModeSetting(change) {
19423
- await updateSettings2({ debugMode: { ...await readDebugModeSetting(), ...change } });
19424
- }
19425
- var RETENTION_CHOICES, DEFAULT_RETENTION_DAYS;
19426
- var init_debug_mode_store = __esm({
19427
- "packages/experience-design-system-cli/src/tui/settings/debug-mode/debug-mode-store.ts"() {
19428
- "use strict";
19429
- init_config();
19430
- RETENTION_CHOICES = [7, 14, 30];
19431
- DEFAULT_RETENTION_DAYS = 30;
19432
- }
19433
- });
19434
-
19435
- // packages/experience-design-system-cli/src/tui/debug-prune.ts
19436
- import { readdir as readdir2, rm, rmdir, stat as stat4 } from "node:fs/promises";
19437
- import { dirname as dirname15, join as join18 } from "node:path";
19438
- async function logFilesIn(dir) {
19439
- const entries = await readdir2(dir, { withFileTypes: true });
19440
- const nested = await Promise.all(
19441
- entries.map(async (entry) => {
19442
- const path5 = join18(dir, entry.name);
19443
- if (entry.isDirectory()) return logFilesIn(path5);
19444
- return entry.isFile() && entry.name.endsWith(".md") ? [path5] : [];
19445
- })
19446
- );
19447
- return nested.flat();
19448
- }
19449
- async function removeEmptyFolders(from, stop) {
19450
- let dir = from;
19451
- let removed = 0;
19452
- for (; ; ) {
19453
- try {
19454
- await rmdir(dir);
19455
- } catch {
19456
- return removed;
19457
- }
19458
- removed += 1;
19459
- if (dir === stop) return removed;
19460
- dir = dirname15(dir);
19461
- }
19462
- }
19463
- async function pruneExpiredLogs(base, retentionDays, now = Date.now()) {
19464
- const cutoff = now - retentionDays * DAY_MS;
19465
- const contentfulDir = join18(base, ".contentful");
19466
- const result = { logs: 0, folders: 0 };
19467
- try {
19468
- const sessions = (await readdir2(contentfulDir)).filter((name) => SESSION_FOLDER.test(name));
19469
- for (const session of sessions) {
19470
- const files = await logFilesIn(join18(contentfulDir, session, "debug")).catch(() => []);
19471
- for (const file of files) {
19472
- try {
19473
- if ((await stat4(file)).mtimeMs >= cutoff) continue;
19474
- await rm(file);
19475
- result.logs += 1;
19476
- result.folders += await removeEmptyFolders(dirname15(file), join18(contentfulDir, session));
19477
- } catch {
19478
- }
19479
- }
19480
- }
19481
- } catch {
19482
- }
19483
- return result;
19484
- }
19485
- var DAY_MS, SESSION_FOLDER;
19486
- var init_debug_prune = __esm({
19487
- "packages/experience-design-system-cli/src/tui/debug-prune.ts"() {
19488
- "use strict";
19489
- DAY_MS = 24 * 60 * 60 * 1e3;
19490
- SESSION_FOLDER = /^\d{2}-\d{2}-\d{4}-session-\d+$/;
19491
- }
19492
- });
19493
-
19494
- // packages/experience-design-system-cli/src/tui/debug-store.ts
19495
- var debug_store_exports = {};
19496
- __export(debug_store_exports, {
19497
- currentDebugSessionDir: () => currentDebugSessionDir,
19498
- currentSessionDir: () => currentSessionDir,
19499
- finishDebugRun: () => finishDebugRun,
19500
- startDebugRun: () => startDebugRun,
19501
- startDebugSessionIn: () => startDebugSessionIn,
19502
- startImportRun: () => startImportRun
19503
- });
19504
- import { mkdir as mkdir7, writeFile as writeFile7 } from "node:fs/promises";
19505
- import { existsSync as existsSync9, readdirSync as readdirSync3 } from "node:fs";
19506
- import { join as join19, resolve as resolve20 } from "node:path";
19507
- function generateRunId() {
19508
- const now = /* @__PURE__ */ new Date();
19509
- const pad = (n) => String(n).padStart(2, "0");
19510
- return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
19511
- }
19512
- function datePrefix(now = /* @__PURE__ */ new Date()) {
19513
- const pad = (n) => String(n).padStart(2, "0");
19514
- return `${pad(now.getMonth() + 1)}-${pad(now.getDate())}-${now.getFullYear()}`;
19515
- }
19516
- function slugify(value) {
19517
- return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
19518
- }
19519
- async function readBaseDir() {
19520
- try {
19521
- const dir = (await readSettings2())["contentfulBaseDir"];
19522
- return typeof dir === "string" && dir !== "" ? resolve20(dir) : void 0;
19523
- } catch {
19524
- return void 0;
19525
- }
19526
- }
19527
- function nextSessionId(contentfulDir) {
19528
- const today = datePrefix();
19529
- const existing = existsSync9(contentfulDir) ? readdirSync3(contentfulDir) : [];
19530
- const seqPattern = new RegExp(`^${today}-session-(\\d+)$`);
19531
- const maxSeq = existing.reduce((max, entry) => {
19532
- const match2 = seqPattern.exec(entry);
19533
- return match2 ? Math.max(max, Number(match2[1])) : max;
19534
- }, 0);
19535
- return `${today}-session-${maxSeq + 1}`;
19536
- }
19537
- function startSession(base, { replace }) {
19538
- const contentfulDir = join19(base, ".contentful");
19539
- if (replace || !sessionDir) sessionDir = join19(contentfulDir, nextSessionId(contentfulDir));
19540
- return sessionDir;
19541
- }
19542
- function currentDebugSessionDir() {
19543
- return sessionDir && join19(sessionDir, "debug");
19544
- }
19545
- function currentSessionDir() {
19546
- return sessionDir;
19547
- }
19548
- async function startDebugSessionIn(base, { replace = false } = {}) {
19549
- try {
19550
- if (!await isDebugModeEnabled()) return;
19551
- await mkdir7(join19(startSession(resolve20(base), { replace }), "debug"), { recursive: true });
19552
- await writeWaitingLogs();
19553
- } catch {
19554
- }
19555
- }
19556
- function nextImportRunDir(session) {
19557
- const existing = existsSync9(session) ? readdirSync3(session) : [];
19558
- const maxRun = existing.reduce((max, entry) => {
19559
- const match2 = /^dsi-import-(\d+)$/.exec(entry);
19560
- return match2 ? Math.max(max, Number(match2[1])) : max;
19561
- }, 0);
19562
- return join19(session, `dsi-import-${maxRun + 1}`);
19563
- }
19564
- async function startImportRun(projectPath) {
19565
- await startDebugSessionIn(projectPath);
19566
- if (!sessionDir) return join19(resolve20(projectPath), ".contentful");
19567
- const dir = nextImportRunDir(sessionDir);
19568
- await mkdir7(dir, { recursive: true });
19569
- return dir;
19570
- }
19571
- async function isDebugModeEnabled() {
19572
- try {
19573
- return (await readDebugModeSetting()).enabled;
19574
- } catch {
19575
- return true;
19576
- }
19577
- }
19578
- function redact(value) {
19579
- const clone = { ...value };
19580
- if ("cma_token" in clone) {
19581
- const raw = clone.cma_token;
19582
- clone.cma_token = typeof raw === "string" && raw.length > 0 ? `[present, ${raw.length} chars]` : "[not set]";
19583
- }
19584
- return clone;
19585
- }
19586
- function startDebugRun({
19587
- flow,
19588
- step,
19589
- menuOption,
19590
- inputs
19591
- }) {
19592
- const runId = generateRunId();
19593
- const startedAt = Date.now();
19594
- const redactedInputs = redact(inputs);
19595
- isDebugModeEnabled().then((enabled) => {
19596
- if (!enabled) return;
19597
- pendingRun = { flow, step, runId, menuOption, inputs: redactedInputs, startedAt };
19598
- });
19599
- }
19600
- async function finishDebugRun({
19601
- outputs,
19602
- status,
19603
- exitMethod
19604
- }) {
19605
- const run = pendingRun;
19606
- if (!run) return;
19607
- pendingRun = void 0;
19608
- const durationMs = Date.now() - run.startedAt;
19609
- const log = {
19610
- flow: run.flow,
19611
- menuOption: run.menuOption,
19612
- content: renderMarkdown(run, { outputs: redact(outputs), status, exitMethod, durationMs })
19613
- };
19614
- const root = currentDebugSessionDir();
19615
- if (!root) {
19616
- if (waiting.length < WAITING_LIMIT) waiting.push(log);
19617
- return;
19618
- }
19619
- await writeLog(root, log);
19620
- }
19621
- async function writeLog(root, log) {
19622
- const dir = join19(root, ...log.flow.split("/"));
19623
- await mkdir7(dir, { recursive: true });
19624
- const filename = nextAttemptFilename(dir, log.menuOption);
19625
- await writeFile7(join19(dir, filename), log.content, { mode: 384 });
19626
- }
19627
- async function writeWaitingLogs() {
19628
- const root = currentDebugSessionDir();
19629
- if (!root) return;
19630
- for (const log of waiting.splice(0)) {
19631
- try {
19632
- await writeLog(root, log);
19633
- } catch {
19634
- }
19635
- }
19636
- }
19637
- function nextAttemptFilename(dir, menuOption) {
19638
- const today = datePrefix();
19639
- const optionSlug = slugify(menuOption);
19640
- const existing = existsSync9(dir) ? readdirSync3(dir) : [];
19641
- const attemptPattern = new RegExp(`^${today}-${optionSlug}-attempt-(\\d+)\\.md$`);
19642
- const maxAttempt = existing.reduce((max, entry) => {
19643
- const match2 = attemptPattern.exec(entry);
19644
- return match2 ? Math.max(max, Number(match2[1])) : max;
19645
- }, 0);
19646
- return `${today}-${optionSlug}-attempt-${maxAttempt + 1}.md`;
19647
- }
19648
- function renderMarkdown(run, finish) {
19649
- const stepMatch = /^(\d+)-(.+)$/.exec(run.step);
19650
- const stepLabel = stepMatch ? `${stepMatch[1]} - ${stepMatch[2]}` : run.step;
19651
- const flowSlug = run.flow.split("/").join("-");
19652
- return `# Debug Log
19653
-
19654
- - Run ID: ${run.runId}
19655
- - Flow: ${flowSlug}
19656
- - Step: ${stepLabel}
19657
- - Menu option: ${run.menuOption}
19658
- - Date: ${(/* @__PURE__ */ new Date()).toISOString()}
19659
- - CLI version: ${readPackageVersion()}
19660
- - Platform: ${process.platform} / Node ${process.version}
19661
- - Duration on screen: ${finish.durationMs}ms
19662
- - Status: ${finish.status}
19663
- - Exit method: ${finish.exitMethod}
19664
-
19665
- ## Inputs
19666
- \`\`\`json
19667
- ${JSON.stringify(run.inputs, null, 2)}
19668
- \`\`\`
19669
-
19670
- ## Outputs
19671
- \`\`\`json
19672
- ${JSON.stringify(finish.outputs, null, 2)}
19673
- \`\`\`
19674
- `;
19675
- }
19676
- function handleCrash() {
19677
- return finishDebugRun({ outputs: {}, status: "error", exitMethod: "crashed" });
19678
- }
19679
- var pendingRun, sessionDir, WAITING_LIMIT, waiting;
19680
- var init_debug_store = __esm({
19681
- "packages/experience-design-system-cli/src/tui/debug-store.ts"() {
19682
- "use strict";
19683
- init_config();
19684
- init_version();
19685
- init_debug_mode_store();
19686
- init_debug_prune();
19687
- void Promise.all([isDebugModeEnabled(), readBaseDir()]).then(async ([enabled, base]) => {
19688
- if (!base) return;
19689
- const retention = await readDebugModeSetting().catch(() => void 0);
19690
- const pruned = retention ? await pruneExpiredLogs(base, retention.retentionDays).catch(() => void 0) : void 0;
19691
- if (!enabled) return;
19692
- const debugDir = join19(startSession(base, { replace: false }), "debug");
19693
- await mkdir7(debugDir, { recursive: true });
19694
- await writeWaitingLogs();
19695
- if (retention && pruned && pruned.logs + pruned.folders > 0) {
19696
- await writeFile7(
19697
- join19(debugDir, `${datePrefix()}-cleanup-${generateRunId()}.md`),
19698
- `# Debug Log Cleanup
19699
-
19700
- - Date: ${(/* @__PURE__ */ new Date()).toISOString()}
19701
- - Retention: ${retention.retentionDays} days
19702
- - Logs deleted: ${pruned.logs}
19703
- - Empty folders removed: ${pruned.folders}
19704
- `,
19705
- { mode: 384 }
19706
- );
19707
- }
19708
- });
19709
- WAITING_LIMIT = 50;
19710
- waiting = [];
19711
- process.once("uncaughtException", (err) => {
19712
- void handleCrash().finally(() => {
19713
- throw err;
19714
- });
19715
- });
19716
- process.once("unhandledRejection", (reason) => {
19717
- void handleCrash().finally(() => {
19718
- throw reason;
19719
- });
19720
- });
19721
- process.once("SIGINT", () => {
19722
- void handleCrash().finally(() => {
19723
- process.exit(130);
19724
- });
19725
- });
19726
- }
19727
- });
19728
-
19729
19410
  // packages/experience-design-system-cli/src/tui/import/steps/00-preflight/logic.ts
19730
19411
  function overviewFor(target) {
19731
19412
  return target === "tokens" ? TOKENS_ONLY_OVERVIEW : COMPONENTS_OVERVIEW;
@@ -20235,37 +19916,12 @@ var init_shared2 = __esm({
20235
19916
  });
20236
19917
 
20237
19918
  // packages/experience-design-system-cli/src/tui/import/steps/00-preflight/screen.tsx
20238
- import { useEffect as useEffect4, useRef, useState as useState4 } from "react";
19919
+ import { useState as useState4 } from "react";
20239
19920
  import { Box as Box9, Text as Text9 } from "ink";
20240
19921
  import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
20241
19922
  function PreflightScreen({ onChoose, onQuit }) {
20242
19923
  const [focus, setFocus] = useState4(0);
20243
- const viewed = useRef([optionAt(0)]).current;
20244
- useEffect4(() => {
20245
- startDebugRun({
20246
- flow: "import/preflight",
20247
- step: "00-preflight",
20248
- menuOption: "Preflight",
20249
- inputs: { options: IMPORT_TARGET_OPTIONS.map((option) => option.target), initial_focus: optionAt(0) }
20250
- });
20251
- }, []);
20252
- const moveTo = (next) => {
20253
- setFocus(next);
20254
- if (viewed[viewed.length - 1] !== optionAt(next)) viewed.push(optionAt(next));
20255
- };
20256
- const choose = (target) => {
20257
- void finishDebugRun({
20258
- outputs: { chosen: target, viewed, steps_that_will_run: overviewFor(target).map((step) => step.description) },
20259
- status: "success",
20260
- exitMethod: "saved"
20261
- });
20262
- onChoose(target);
20263
- };
20264
- const quit = () => {
20265
- void finishDebugRun({ outputs: { chosen: null, viewed }, status: "success", exitMethod: "discarded" });
20266
- onQuit();
20267
- };
20268
- usePreflightControls({ focus, onFocus: moveTo, onChoose: choose, onQuit: quit });
19924
+ usePreflightControls({ focus, onFocus: setFocus, onChoose, onQuit });
20269
19925
  return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
20270
19926
  /* @__PURE__ */ jsx9(StepHeader, { step: "setup" }),
20271
19927
  /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", gap: 1, paddingX: 2, paddingBottom: 1, children: [
@@ -20277,28 +19933,25 @@ function PreflightScreen({ onChoose, onQuit }) {
20277
19933
  /* @__PURE__ */ jsx9(Text9, { bold: focused, color: focused ? PALETTE.accent : void 0, children: option.label })
20278
19934
  ] }, option.target);
20279
19935
  }) }),
20280
- /* @__PURE__ */ jsx9(OverviewBox, { steps: overviewFor(optionAt(focus)) }),
19936
+ /* @__PURE__ */ jsx9(OverviewBox, { steps: overviewFor(IMPORT_TARGET_OPTIONS[focus].target) }),
20281
19937
  /* @__PURE__ */ jsx9(ControlHints, { hints: PREFLIGHT_CONTROLS })
20282
19938
  ] })
20283
19939
  ] });
20284
19940
  }
20285
- var optionAt;
20286
19941
  var init_screen = __esm({
20287
19942
  "packages/experience-design-system-cli/src/tui/import/steps/00-preflight/screen.tsx"() {
20288
19943
  "use strict";
20289
19944
  init_theme();
20290
- init_debug_store();
20291
19945
  init_controls();
20292
19946
  init_logic();
20293
19947
  init_shared2();
20294
19948
  init_ControlHints();
20295
19949
  init_StepHeader();
20296
- optionAt = (index) => IMPORT_TARGET_OPTIONS[index].target;
20297
19950
  }
20298
19951
  });
20299
19952
 
20300
19953
  // packages/experience-design-system-cli/src/tui/shared/components/ClearableTextInput.tsx
20301
- import { useRef as useRef2 } from "react";
19954
+ import { useRef } from "react";
20302
19955
  import { useInput as useInput6 } from "ink";
20303
19956
  import TextInput from "ink-text-input";
20304
19957
  import { jsx as jsx10 } from "react/jsx-runtime";
@@ -20306,7 +19959,7 @@ function isClearKey(input, key) {
20306
19959
  return key.ctrl && input === "d";
20307
19960
  }
20308
19961
  function ClearableTextInput({ onChange, ...props }) {
20309
- const justCleared = useRef2(false);
19962
+ const justCleared = useRef(false);
20310
19963
  useInput6((input, key) => {
20311
19964
  if (!isClearKey(input, key)) return;
20312
19965
  justCleared.current = true;
@@ -20439,7 +20092,7 @@ var init_controls5 = __esm({
20439
20092
 
20440
20093
  // packages/experience-design-system-cli/src/tui/import/resolve-user-path.ts
20441
20094
  import { homedir as homedir3 } from "node:os";
20442
- import { resolve as resolve21 } from "node:path";
20095
+ import { resolve as resolve20 } from "node:path";
20443
20096
  function stripQuotes(value) {
20444
20097
  const quoted = value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'");
20445
20098
  return value.length >= 2 && quoted ? value.slice(1, -1) : value;
@@ -20448,7 +20101,7 @@ function expandHome(value) {
20448
20101
  return value === "~" || value.startsWith("~/") || value.startsWith("~\\") ? homedir3() + value.slice(1) : value;
20449
20102
  }
20450
20103
  function resolveUserPath(raw) {
20451
- return resolve21(expandHome(stripQuotes(raw.trim())));
20104
+ return resolve20(expandHome(stripQuotes(raw.trim())));
20452
20105
  }
20453
20106
  var init_resolve_user_path = __esm({
20454
20107
  "packages/experience-design-system-cli/src/tui/import/resolve-user-path.ts"() {
@@ -20680,7 +20333,7 @@ var init_scan_files = __esm({
20680
20333
  });
20681
20334
 
20682
20335
  // packages/experience-design-system-cli/src/tui/import/steps/03-path-validation/screen.tsx
20683
- import { useEffect as useEffect5, useMemo, useState as useState7 } from "react";
20336
+ import { useEffect as useEffect4, useMemo, useState as useState7 } from "react";
20684
20337
  import { Box as Box12, Text as Text12 } from "ink";
20685
20338
  import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
20686
20339
  function Row({ row }) {
@@ -20736,7 +20389,7 @@ function PathValidationScreen({
20736
20389
  }) {
20737
20390
  const resolvedPath = useMemo(() => resolveUserPath(projectPath), [projectPath]);
20738
20391
  const [scan, setScan] = useState7();
20739
- useEffect5(() => {
20392
+ useEffect4(() => {
20740
20393
  setScan(scanFiles(resolvedPath));
20741
20394
  }, [resolvedPath]);
20742
20395
  const phase = phaseOf(scan);
@@ -21033,7 +20686,7 @@ var init_validate4 = __esm({
21033
20686
  });
21034
20687
 
21035
20688
  // packages/experience-design-system-cli/src/tui/import/steps/04-credentials/screen.tsx
21036
- import { useRef as useRef3, useState as useState9 } from "react";
20689
+ import { useRef as useRef2, useState as useState9 } from "react";
21037
20690
  import { Box as Box14, Text as Text14, useInput as useInput11 } from "ink";
21038
20691
  import { Fragment as Fragment2, jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
21039
20692
  function CredentialsScreen({
@@ -21043,7 +20696,7 @@ function CredentialsScreen({
21043
20696
  validate: validate3 = validateCredentials,
21044
20697
  tokensOnly = false
21045
20698
  }) {
21046
- const initialValues = useRef3(
20699
+ const initialValues = useRef2(
21047
20700
  normalize({
21048
20701
  spaceId: initial.spaceId ?? "",
21049
20702
  environmentId: initial.environmentId || "master",
@@ -21491,16 +21144,16 @@ var init_steps = __esm({
21491
21144
  });
21492
21145
 
21493
21146
  // packages/experience-design-system-cli/src/tui/import/steps/06-extraction/find-skill-path.ts
21494
- import { existsSync as existsSync10 } from "node:fs";
21495
- import { dirname as dirname16, join as join20, resolve as resolve22 } from "node:path";
21147
+ import { existsSync as existsSync9 } from "node:fs";
21148
+ import { dirname as dirname15, join as join18, resolve as resolve21 } from "node:path";
21496
21149
  import { fileURLToPath as fileURLToPath4 } from "node:url";
21497
21150
  function findSkillPath(fileName) {
21498
- const thisDir = dirname16(fileURLToPath4(import.meta.url));
21151
+ const thisDir = dirname15(fileURLToPath4(import.meta.url));
21499
21152
  let dir = thisDir;
21500
21153
  for (; ; ) {
21501
- const candidate = join20(dir, "skills", fileName);
21502
- if (existsSync10(candidate)) return candidate;
21503
- const parent = resolve22(dir, "..");
21154
+ const candidate = join18(dir, "skills", fileName);
21155
+ if (existsSync9(candidate)) return candidate;
21156
+ const parent = resolve21(dir, "..");
21504
21157
  if (parent === dir) {
21505
21158
  throw new Error(`skill file not found (looked for skills/${fileName} from ${thisDir})`);
21506
21159
  }
@@ -21514,9 +21167,9 @@ var init_find_skill_path = __esm({
21514
21167
  });
21515
21168
 
21516
21169
  // packages/experience-design-system-cli/src/tui/import/steps/06-extraction/selection.ts
21517
- import { resolve as resolve23 } from "node:path";
21170
+ import { resolve as resolve22 } from "node:path";
21518
21171
  async function hashSelectPrompt(options) {
21519
- const promptHash = options.promptText ? hashContent(options.promptText) : options.promptPath ? await hashFile(resolve23(options.promptPath)) : await hashFile(SELECT_SKILL_PATH);
21172
+ const promptHash = options.promptText ? hashContent(options.promptText) : options.promptPath ? await hashFile(resolve22(options.promptPath)) : await hashFile(SELECT_SKILL_PATH);
21520
21173
  return hashContent(`${promptHash}|${options.agent}|${options.model ?? ""}`);
21521
21174
  }
21522
21175
  async function runSelection(options) {
@@ -21610,10 +21263,10 @@ var init_selection2 = __esm({
21610
21263
  });
21611
21264
 
21612
21265
  // packages/experience-design-system-cli/src/tui/import/steps/06-extraction/run.ts
21613
- import { mkdir as mkdir8 } from "node:fs/promises";
21614
- import { join as join21, resolve as resolve24 } from "node:path";
21266
+ import { mkdir as mkdir7 } from "node:fs/promises";
21267
+ import { join as join19, resolve as resolve23 } from "node:path";
21615
21268
  async function runExtraction(input, onProgress, deps = realDeps) {
21616
- const outDir = input.outDir ?? join21(resolve24(input.projectPath), ".contentful");
21269
+ const outDir = input.outDir ?? join19(resolve23(input.projectPath), ".contentful");
21617
21270
  let progress = initialProgress({
21618
21271
  hasCredentials: input.credentials !== null,
21619
21272
  hasRawTokens: input.rawTokensPath !== ""
@@ -21717,7 +21370,7 @@ async function runExtraction(input, onProgress, deps = realDeps) {
21717
21370
  }
21718
21371
  async function fetchEntities(credentials, outDir) {
21719
21372
  try {
21720
- await mkdir8(outDir, { recursive: true });
21373
+ await mkdir7(outDir, { recursive: true });
21721
21374
  const result = await fetchAndPersistExistingContentfulEntities({
21722
21375
  spaceId: credentials.spaceId,
21723
21376
  environmentId: credentials.environmentId,
@@ -21737,7 +21390,7 @@ async function resolveSelectionPrompt(overrides) {
21737
21390
  if (select?.kind === "text") return { promptText: select.value };
21738
21391
  if (select?.kind === "path") {
21739
21392
  await resolvePromptOverride(select);
21740
- return { promptPath: resolve24(select.value) };
21393
+ return { promptPath: resolve23(select.value) };
21741
21394
  }
21742
21395
  return {};
21743
21396
  }
@@ -21763,11 +21416,11 @@ var init_run = __esm({
21763
21416
  });
21764
21417
 
21765
21418
  // packages/experience-design-system-cli/src/tui/import/steps/06-extraction/use-extraction.ts
21766
- import { useEffect as useEffect6, useRef as useRef4, useState as useState11 } from "react";
21419
+ import { useEffect as useEffect5, useRef as useRef3, useState as useState11 } from "react";
21767
21420
  function useExtraction(input) {
21768
21421
  const [state2, setState] = useState11();
21769
- const current = useRef4();
21770
- useEffect6(() => {
21422
+ const current = useRef3();
21423
+ useEffect5(() => {
21771
21424
  current.current = input;
21772
21425
  if (!input) {
21773
21426
  setState(void 0);
@@ -21838,11 +21491,11 @@ var init_run_tokens_only = __esm({
21838
21491
  });
21839
21492
 
21840
21493
  // packages/experience-design-system-cli/src/tui/import/steps/06-extraction/use-tokens-only.ts
21841
- import { useEffect as useEffect7, useRef as useRef5, useState as useState12 } from "react";
21494
+ import { useEffect as useEffect6, useRef as useRef4, useState as useState12 } from "react";
21842
21495
  function useTokensOnly(input) {
21843
21496
  const [state2, setState] = useState12();
21844
- const current = useRef5();
21845
- useEffect7(() => {
21497
+ const current = useRef4();
21498
+ useEffect6(() => {
21846
21499
  current.current = input;
21847
21500
  if (!input) {
21848
21501
  setState(void 0);
@@ -22139,7 +21792,6 @@ function GotoBanner({
22139
21792
  borderStyle: "single",
22140
21793
  borderColor: PALETTE.accent,
22141
21794
  paddingX: 1,
22142
- paddingBottom: 1,
22143
21795
  marginTop: width === void 0 ? 1 : 0,
22144
21796
  width,
22145
21797
  flexShrink: 0,
@@ -22151,7 +21803,7 @@ function GotoBanner({
22151
21803
  return renderRow(row, i, i === highlightIndex);
22152
21804
  }),
22153
21805
  moreBelow > 0 && /* @__PURE__ */ jsx24(Text21, { color: PALETTE.muted, children: ` \u25BC ${moreBelow} more` }),
22154
- footerHint !== void 0 && /* @__PURE__ */ jsx24(Box21, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text21, { color: PALETTE.muted, children: footerHint }) })
21806
+ footerHint !== void 0 && /* @__PURE__ */ jsx24(Text21, { color: PALETTE.muted, children: footerHint })
22155
21807
  ]
22156
21808
  }
22157
21809
  );
@@ -22666,11 +22318,11 @@ function buildVisibleRows(props) {
22666
22318
  if (!expanded) continue;
22667
22319
  const subtree = computeCycleMemberSubtree(key);
22668
22320
  const isLastAtDepthSubtree = (idx) => {
22669
- const own2 = subtree[idx].depth;
22321
+ const own = subtree[idx].depth;
22670
22322
  for (let j = idx + 1; j < subtree.length; j++) {
22671
22323
  const d = subtree[j].depth;
22672
- if (d < own2) return true;
22673
- if (d === own2) return false;
22324
+ if (d < own) return true;
22325
+ if (d === own) return false;
22674
22326
  }
22675
22327
  return true;
22676
22328
  };
@@ -22790,11 +22442,11 @@ function buildVisibleRows(props) {
22790
22442
  injectedChildren.push({ name: c2.name, depth: c2.depth, isCycleChild: false });
22791
22443
  }
22792
22444
  const isLastAtDepth = (idx) => {
22793
- const own2 = injectedChildren[idx].depth;
22445
+ const own = injectedChildren[idx].depth;
22794
22446
  for (let j = idx + 1; j < injectedChildren.length; j++) {
22795
22447
  const d = injectedChildren[j].depth;
22796
- if (d < own2) return true;
22797
- if (d === own2) return false;
22448
+ if (d < own) return true;
22449
+ if (d === own) return false;
22798
22450
  }
22799
22451
  return true;
22800
22452
  };
@@ -23039,7 +22691,7 @@ var init_GroupedSidebar = __esm({
23039
22691
  });
23040
22692
 
23041
22693
  // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/hooks/useImmediateInput.ts
23042
- import { useLayoutEffect, useRef as useRef6 } from "react";
22694
+ import { useLayoutEffect, useRef as useRef5 } from "react";
23043
22695
  import { useStdin } from "ink";
23044
22696
  function parseInput(data) {
23045
22697
  const isShiftTab = data === "\x1B[Z";
@@ -23101,7 +22753,7 @@ function registerInputHandler(stdin, setRawMode, handler) {
23101
22753
  }
23102
22754
  function useImmediateInput(handler, enabled = true) {
23103
22755
  const { stdin, setRawMode } = useStdin();
23104
- const handlerRef = useRef6(handler);
22756
+ const handlerRef = useRef5(handler);
23105
22757
  handlerRef.current = handler;
23106
22758
  useLayoutEffect(() => {
23107
22759
  if (!enabled) return;
@@ -23119,7 +22771,7 @@ var init_useImmediateInput = __esm({
23119
22771
 
23120
22772
  // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/hooks/use-terminal-size.ts
23121
22773
  import { useStdout as useStdout2 } from "ink";
23122
- import { useEffect as useEffect8, useState as useState13 } from "react";
22774
+ import { useEffect as useEffect7, useState as useState13 } from "react";
23123
22775
  function readTerminalSize(stdout) {
23124
22776
  return {
23125
22777
  columns: stdout?.columns ?? 80,
@@ -23129,7 +22781,7 @@ function readTerminalSize(stdout) {
23129
22781
  function useTerminalSize() {
23130
22782
  const { stdout } = useStdout2();
23131
22783
  const [size, setSize] = useState13(() => readTerminalSize(stdout));
23132
- useEffect8(() => {
22784
+ useEffect7(() => {
23133
22785
  const updateSize = () => setSize(readTerminalSize(stdout));
23134
22786
  stdout?.on("resize", updateSize);
23135
22787
  updateSize();
@@ -24131,7 +23783,7 @@ var init_state = __esm({
24131
23783
  });
24132
23784
 
24133
23785
  // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/use-scope-gate.ts
24134
- import { useEffect as useEffect9, useMemo as useMemo3, useRef as useRef7, useState as useState16 } from "react";
23786
+ import { useEffect as useEffect8, useMemo as useMemo3, useRef as useRef6, useState as useState16 } from "react";
24135
23787
  function useScopeGate({ components, tokenCount, tokensWidth, onConfirm, onQuit }) {
24136
23788
  const { columns: totalWidth, rows: terminalRows } = useTerminalSize();
24137
23789
  const columnPlan = useMemo3(
@@ -24177,8 +23829,8 @@ function useScopeGate({ components, tokenCount, tokensWidth, onConfirm, onQuit }
24177
23829
  for (const p of cycleParticipants) seed.add(p);
24178
23830
  return seed;
24179
23831
  });
24180
- const seededGroupsRef = useRef7(closures.size > 0 || cycleParticipants.size > 0);
24181
- useEffect9(() => {
23832
+ const seededGroupsRef = useRef6(closures.size > 0 || cycleParticipants.size > 0);
23833
+ useEffect8(() => {
24182
23834
  if (seededGroupsRef.current) return;
24183
23835
  if (closures.size === 0 && cycleParticipants.size === 0) return;
24184
23836
  seededGroupsRef.current = true;
@@ -24269,7 +23921,7 @@ function useScopeGate({ components, tokenCount, tokensWidth, onConfirm, onQuit }
24269
23921
  entryCount: 0
24270
23922
  });
24271
23923
  const panelLayout = useMemo3(() => computePanelLayout(visibleCount), [visibleCount]);
24272
- useEffect9(() => {
23924
+ useEffect8(() => {
24273
23925
  setNav((prev) => {
24274
23926
  const maxIdx = Math.max(0, visibleRows.length - 1);
24275
23927
  const nextCursor = Math.min(prev.cursor, maxIdx);
@@ -24842,13 +24494,13 @@ var init_load2 = __esm({
24842
24494
  });
24843
24495
 
24844
24496
  // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/use-scope-gate-flow.ts
24845
- import { useEffect as useEffect10, useMemo as useMemo5, useRef as useRef8, useState as useState17 } from "react";
24497
+ import { useEffect as useEffect9, useMemo as useMemo5, useRef as useRef7, useState as useState17 } from "react";
24846
24498
  function useScopeGateFlow(input, deps = realDeps3) {
24847
24499
  const sessionId = input?.sessionId;
24848
24500
  const loaded = useMemo5(() => sessionId ? deps.load(sessionId) : void 0, [sessionId]);
24849
- const cacheCheck = useRef8(void 0);
24501
+ const cacheCheck = useRef7(void 0);
24850
24502
  const [confirmed, setConfirmed] = useState17();
24851
- useEffect10(() => {
24503
+ useEffect9(() => {
24852
24504
  if (!input || !loaded?.ok || cacheCheck.current) return;
24853
24505
  cacheCheck.current = deps.checkCache(input.cache);
24854
24506
  }, [input, loaded]);
@@ -24883,7 +24535,7 @@ function formatAcceptanceSummary(counts) {
24883
24535
  function describeGeneration(input) {
24884
24536
  const agent = capitalize(input.agent);
24885
24537
  return `${formatAcceptanceSummary({ accepted: input.acceptedCount, autoRejected: 0 })}
24886
- ${agent} is reading each selected component and writing a Contentful component definition for it.${input.hasTokens ? "\nUsing your design tokens for prop resolution." : ""}`;
24538
+ ${agent} is reading each selected component and writing a Contentful component definition for it${input.hasTokens ? " Using your design tokens for prop resolution." : ""}`;
24887
24539
  }
24888
24540
  function progressRows2(progress, agent) {
24889
24541
  const name = capitalize(agent);
@@ -24986,7 +24638,7 @@ var init_save_decisions = __esm({
24986
24638
  });
24987
24639
 
24988
24640
  // packages/experience-design-system-cli/src/tui/import/steps/08-generation/run.ts
24989
- import { resolve as resolve25 } from "node:path";
24641
+ import { resolve as resolve24 } from "node:path";
24990
24642
  async function runGeneration(input, onProgress, deps = realDeps4) {
24991
24643
  let progress = { components: null, mapTokens: "idle", mapTokensEligible: null };
24992
24644
  const update = (change) => {
@@ -25072,7 +24724,7 @@ async function buildMapTokensOptions(input) {
25072
24724
  if (mapOverride?.kind === "text") prompt.skillContentOverride = mapOverride.value;
25073
24725
  if (mapOverride?.kind === "path") {
25074
24726
  await resolvePromptOverride(mapOverride);
25075
- prompt.skillPathOverride = resolve25(mapOverride.value);
24727
+ prompt.skillPathOverride = resolve24(mapOverride.value);
25076
24728
  }
25077
24729
  if (input.existingEntitiesPath) {
25078
24730
  const entities = await readExistingContentfulEntitiesFromSession({ path: input.existingEntitiesPath });
@@ -25119,11 +24771,11 @@ var init_run2 = __esm({
25119
24771
  });
25120
24772
 
25121
24773
  // packages/experience-design-system-cli/src/tui/import/steps/08-generation/use-generation.ts
25122
- import { useEffect as useEffect11, useRef as useRef9, useState as useState18 } from "react";
24774
+ import { useEffect as useEffect10, useRef as useRef8, useState as useState18 } from "react";
25123
24775
  function useGeneration(input) {
25124
24776
  const [state2, setState] = useState18();
25125
- const current = useRef9();
25126
- useEffect11(() => {
24777
+ const current = useRef8();
24778
+ useEffect10(() => {
25127
24779
  current.current = input;
25128
24780
  if (!input) {
25129
24781
  setState(void 0);
@@ -25150,7 +24802,7 @@ var init_use_generation = __esm({
25150
24802
  });
25151
24803
 
25152
24804
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/build-flow-start.ts
25153
- import { join as join22 } from "node:path";
24805
+ import { join as join20 } from "node:path";
25154
24806
  function buildFlowStart(input) {
25155
24807
  const { extraction, handoff, saved, generatePromptPath, tokensOnly } = input;
25156
24808
  const credentials = extraction.credentials ?? {
@@ -25163,7 +24815,7 @@ function buildFlowStart(input) {
25163
24815
  handoff,
25164
24816
  agent: extraction.agent,
25165
24817
  projectPath: extraction.projectPath,
25166
- outDir: extraction.projectPath ? join22(extraction.projectPath, ".contentful") : "",
24818
+ outDir: extraction.projectPath ? join20(extraction.projectPath, ".contentful") : "",
25167
24819
  rawTokensPath: extraction.rawTokensPath,
25168
24820
  credentials: {
25169
24821
  spaceId: credentials.spaceId,
@@ -25551,141 +25203,12 @@ var init_dtcg2 = __esm({
25551
25203
  }
25552
25204
  });
25553
25205
 
25554
- // packages/experience-design-system-types/dist/src/property-contract/json-value.js
25555
- var nodeTypes;
25556
- var init_json_value = __esm({
25557
- "packages/experience-design-system-types/dist/src/property-contract/json-value.js"() {
25558
- "use strict";
25559
- nodeTypes = globalThis.process?.getBuiltinModule?.("node:util")?.types;
25560
- }
25561
- });
25562
-
25563
- // packages/experience-design-system-types/dist/src/property-contract/date-time-value.js
25564
- import * as z5 from "zod/mini";
25565
- var dateTimeValueSchema;
25566
- var init_date_time_value = __esm({
25567
- "packages/experience-design-system-types/dist/src/property-contract/date-time-value.js"() {
25568
- "use strict";
25569
- dateTimeValueSchema = z5.iso.datetime({ offset: true });
25570
- }
25571
- });
25572
-
25573
- // packages/experience-design-system-types/dist/src/property-contract/discriminated-union.js
25574
- var init_discriminated_union = __esm({
25575
- "packages/experience-design-system-types/dist/src/property-contract/discriminated-union.js"() {
25576
- "use strict";
25577
- init_json_value();
25578
- }
25579
- });
25580
-
25581
- // packages/experience-design-system-types/dist/src/property-contract/target-definition.js
25582
- var TARGET_PROPERTY_TYPES, SAME_SPACE_RESOURCE_SOURCE, targetDefinitionJsonSchema;
25583
- var init_target_definition = __esm({
25584
- "packages/experience-design-system-types/dist/src/property-contract/target-definition.js"() {
25585
- "use strict";
25586
- init_json_value();
25587
- init_date_time_value();
25588
- init_discriminated_union();
25589
- TARGET_PROPERTY_TYPES = [
25590
- "String",
25591
- "Number",
25592
- "Boolean",
25593
- "Array",
25594
- "Record",
25595
- "Integer",
25596
- "DateTime",
25597
- "RichText",
25598
- "JSON",
25599
- "ResourceLink",
25600
- "Literal",
25601
- "DiscriminatedUnion"
25602
- ];
25603
- SAME_SPACE_RESOURCE_SOURCE = "crn:contentful:::content:spaces/$self/environments/$self";
25604
- targetDefinitionJsonSchema = {
25605
- $schema: "http://json-schema.org/draft-07/schema#",
25606
- $ref: "#/definitions/target",
25607
- definitions: {
25608
- target: {
25609
- type: "object",
25610
- required: ["type"],
25611
- properties: {
25612
- type: { enum: [...TARGET_PROPERTY_TYPES] },
25613
- id: { type: "string" },
25614
- name: { type: "string" },
25615
- description: { type: "string" },
25616
- required: { type: "boolean" },
25617
- values: { type: "array", minItems: 1 },
25618
- defaultValue: {},
25619
- items: { $ref: "#/definitions/target" },
25620
- fields: { type: "object", minProperties: 1, additionalProperties: { $ref: "#/definitions/target" } },
25621
- allowedResources: {
25622
- type: "array",
25623
- minItems: 1,
25624
- items: {
25625
- type: "object",
25626
- required: ["type", "source"],
25627
- properties: {
25628
- type: { enum: ["Contentful:Entry", "Contentful:Asset"] },
25629
- source: { const: SAME_SPACE_RESOURCE_SOURCE },
25630
- allowedTypes: { type: "array", items: { type: "string" } }
25631
- },
25632
- allOf: [
25633
- {
25634
- if: { properties: { type: { const: "Contentful:Entry" } } },
25635
- then: { required: ["allowedTypes"] },
25636
- else: { not: { required: ["allowedTypes"] } }
25637
- }
25638
- ],
25639
- additionalProperties: false
25640
- }
25641
- },
25642
- value: {},
25643
- valueType: { $ref: "#/definitions/target" },
25644
- discriminator: { type: "string", minLength: 1 },
25645
- members: {
25646
- type: "array",
25647
- minItems: 2,
25648
- uniqueItems: true,
25649
- items: {
25650
- allOf: [
25651
- { $ref: "#/definitions/target" },
25652
- { type: "object", properties: { type: { const: "Record" } }, required: ["type", "fields"] }
25653
- ]
25654
- }
25655
- }
25656
- },
25657
- allOf: [
25658
- {
25659
- if: { properties: { type: { const: "DiscriminatedUnion" } } },
25660
- then: { required: ["discriminator", "members"] },
25661
- else: { not: { anyOf: [{ required: ["discriminator"] }, { required: ["members"] }] } }
25662
- }
25663
- ],
25664
- additionalProperties: false
25665
- }
25666
- }
25667
- };
25668
- }
25669
- });
25670
-
25671
- // packages/experience-design-system-types/dist/src/property-contract/index.js
25672
- var init_property_contract = __esm({
25673
- "packages/experience-design-system-types/dist/src/property-contract/index.js"() {
25674
- "use strict";
25675
- init_json_value();
25676
- init_date_time_value();
25677
- init_discriminated_union();
25678
- init_target_definition();
25679
- }
25680
- });
25681
-
25682
25206
  // packages/experience-design-system-types/dist/src/index.js
25683
25207
  var init_src4 = __esm({
25684
25208
  "packages/experience-design-system-types/dist/src/index.js"() {
25685
25209
  "use strict";
25686
25210
  init_cdf2();
25687
25211
  init_dtcg2();
25688
- init_property_contract();
25689
25212
  }
25690
25213
  });
25691
25214
 
@@ -25825,14 +25348,14 @@ function computeRenderStatuses(closure, directIssues) {
25825
25348
  for (const node of closure.nodes) {
25826
25349
  nodesByName.set(node.name, { name: node.name, path: node.path });
25827
25350
  }
25828
- const own2 = /* @__PURE__ */ new Map();
25351
+ const own = /* @__PURE__ */ new Map();
25829
25352
  for (const node of closure.nodes) {
25830
25353
  const s = directIssues.get(node.name);
25831
- if (s && s !== "ok") own2.set(node.name, s);
25354
+ if (s && s !== "ok") own.set(node.name, s);
25832
25355
  }
25833
25356
  const inheritedSources = /* @__PURE__ */ new Map();
25834
25357
  for (const node of closure.nodes) {
25835
- const ownStatus = own2.get(node.name);
25358
+ const ownStatus = own.get(node.name);
25836
25359
  if (!ownStatus) continue;
25837
25360
  for (let i = 0; i < node.path.length - 1; i++) {
25838
25361
  const ancestor = node.path[i];
@@ -25840,7 +25363,7 @@ function computeRenderStatuses(closure, directIssues) {
25840
25363
  inheritedSources.get(ancestor).set(node.name, ownStatus);
25841
25364
  }
25842
25365
  }
25843
- for (const [name, status] of own2.entries()) {
25366
+ for (const [name, status] of own.entries()) {
25844
25367
  out.set(name, {
25845
25368
  status,
25846
25369
  isOwn: true,
@@ -26110,7 +25633,7 @@ var init_scroll_offset = __esm({
26110
25633
  });
26111
25634
 
26112
25635
  // packages/experience-design-system-cli/src/tui/import/steps/09-review/components/FieldEditor.tsx
26113
- import React13, { useEffect as useEffect12, useLayoutEffect as useLayoutEffect2, useState as useState19 } from "react";
25636
+ import React13, { useEffect as useEffect11, useLayoutEffect as useLayoutEffect2, useState as useState19 } from "react";
26114
25637
  import figures6 from "figures";
26115
25638
  import { Box as Box26, measureElement, Text as Text27 } from "ink";
26116
25639
  import { Fragment as Fragment6, jsx as jsx32, jsxs as jsxs26 } from "react/jsx-runtime";
@@ -26877,7 +26400,6 @@ function FieldEditor({
26877
26400
  const [rationaleOpen, setRationaleOpen] = useState19(false);
26878
26401
  const [rationaleScrollOffset, setRationaleScrollOffset] = useState19(0);
26879
26402
  const [showHelp, setShowHelp] = useState19(false);
26880
- const [pendingDelete, setPendingDelete] = useState19(null);
26881
26403
  const props = editorState.props;
26882
26404
  const slots = editorState.slots;
26883
26405
  const contentPropIndexes = React13.useMemo(
@@ -26969,46 +26491,6 @@ function FieldEditor({
26969
26491
  setEditorState(next);
26970
26492
  onChange(serializeState(next, value));
26971
26493
  };
26972
- const deleteRow = (row) => {
26973
- if (row.kind === "prop") {
26974
- const nextProps = removeAt(editorState.props, row.idx);
26975
- commit({ ...editorState, props: nextProps });
26976
- setPropIdx(Math.max(0, Math.min(row.idx, nextProps.length - 1)));
26977
- const rowsAfter2 = selectableRows.filter((r) => !(r.kind === "prop" && r.idx === row.idx));
26978
- const neighbour2 = rowsAfter2[Math.max(0, selectableRows.findIndex((r) => r.kind === row.kind && r.idx === row.idx) - 1)];
26979
- if (!neighbour2) {
26980
- setInSlots(false);
26981
- setInComponentDesc(true);
26982
- setFocusLevel("componentDescription");
26983
- } else if (neighbour2.kind === "prop") {
26984
- setInSlots(false);
26985
- setPropIdx(neighbour2.idx > row.idx ? neighbour2.idx - 1 : neighbour2.idx);
26986
- setFocusLevel("prop");
26987
- } else {
26988
- setInSlots(true);
26989
- setSlotIdx(neighbour2.idx);
26990
- setFocusLevel("slot");
26991
- }
26992
- return;
26993
- }
26994
- const nextSlots = removeAt(editorState.slots, row.idx);
26995
- commit({ ...editorState, slots: nextSlots });
26996
- const rowsAfter = selectableRows.filter((r) => !(r.kind === "slot" && r.idx === row.idx));
26997
- const neighbour = rowsAfter[Math.max(0, selectableRows.findIndex((r) => r.kind === row.kind && r.idx === row.idx) - 1)];
26998
- if (!neighbour) {
26999
- setInSlots(false);
27000
- setInComponentDesc(true);
27001
- setFocusLevel("componentDescription");
27002
- } else if (neighbour.kind === "slot") {
27003
- setInSlots(true);
27004
- setSlotIdx(neighbour.idx > row.idx ? neighbour.idx - 1 : neighbour.idx);
27005
- setFocusLevel("slot");
27006
- } else {
27007
- setInSlots(false);
27008
- setPropIdx(neighbour.idx);
27009
- setFocusLevel("prop");
27010
- }
27011
- };
27012
26494
  const canonicalize = React13.useCallback((json) => {
27013
26495
  try {
27014
26496
  return JSON.stringify(JSON.parse(json));
@@ -27045,11 +26527,6 @@ function FieldEditor({
27045
26527
  onSave();
27046
26528
  return;
27047
26529
  }
27048
- if (pendingDelete) {
27049
- if (input === "y") deleteRow(pendingDelete);
27050
- setPendingDelete(null);
27051
- return;
27052
- }
27053
26530
  const inDescriptionTextEntryForHelp = focusLevel === "field" && editingField && activeField === "description";
27054
26531
  const inStringDefaultTextEntryForHelp = focusLevel === "field" && editingField && activeField === "default" && currentProp != null && (currentProp.type === "string" || currentProp.type === "token");
27055
26532
  const inValueListTextEntry = editingValue != null;
@@ -27249,11 +26726,6 @@ function FieldEditor({
27249
26726
  }
27250
26727
  return;
27251
26728
  }
27252
- if (input === "d" && !key.ctrl && !key.meta) {
27253
- if (focusLevel === "prop" && currentProp) setPendingDelete({ kind: "prop", idx: propIdx });
27254
- if (focusLevel === "slot" && currentSlot) setPendingDelete({ kind: "slot", idx: slotIdx });
27255
- return;
27256
- }
27257
26729
  if (focusLevel === "slot" && key.return && currentSlot) {
27258
26730
  setFocusLevel("field");
27259
26731
  setActiveField(SLOT_FIELDS[0] ?? null);
@@ -27560,10 +27032,6 @@ function FieldEditor({
27560
27032
  }
27561
27033
  const hasEmptyProperties = props.length === 0 && slots.length === 0;
27562
27034
  const modeLabel = (() => {
27563
- if (pendingDelete) {
27564
- const name = pendingDelete.kind === "prop" ? props[pendingDelete.idx]?.name : slots[pendingDelete.idx]?.name;
27565
- return `Delete ${pendingDelete.kind} "${name}"? [y] delete \xB7 any other key cancels`;
27566
- }
27567
27035
  if (editingValue) {
27568
27036
  return editingValue.mode === "add" ? "Enter to add \xB7 [Esc] to cancel" : "Enter to save edit \xB7 [Esc] to cancel";
27569
27037
  }
@@ -27585,7 +27053,7 @@ function FieldEditor({
27585
27053
  if (rationaleOpen) {
27586
27054
  return "[\u2191\u2193] scroll [i/Esc] close rationale panel";
27587
27055
  }
27588
- return `[\u2191\u2193] navigate [Enter] edit fields [d] delete property [h] help [s] source [Esc] exit panel`;
27056
+ return `[\u2191\u2193] navigate rows [Enter] edit fields [s] source [${propRationaleKey}] prop rationale [${componentRationaleKey}] component rationale [h] help [Esc] exit panel`;
27589
27057
  })();
27590
27058
  const rows = [];
27591
27059
  rows.push({ kind: "component-description" });
@@ -27637,7 +27105,7 @@ function FieldEditor({
27637
27105
  }
27638
27106
  return Math.max(start + 1, end2);
27639
27107
  };
27640
- useEffect12(() => {
27108
+ useEffect11(() => {
27641
27109
  if (focusLevel === "field" || selectedRowIdx < 0) return;
27642
27110
  setListScrollStart((previous) => {
27643
27111
  if (initialFocusTarget && !initialFocusScrollApplied.current) {
@@ -27851,7 +27319,6 @@ function FieldEditor({
27851
27319
  /* @__PURE__ */ jsx32(Text27, { bold: true, children: "Row navigation" }),
27852
27320
  /* @__PURE__ */ jsx32(Text27, { children: " \u2191/\u2193 move between rows" }),
27853
27321
  /* @__PURE__ */ jsx32(Text27, { children: " Enter edit fields on the current row" }),
27854
- /* @__PURE__ */ jsx32(Text27, { children: " d delete the current prop or slot (asks to confirm)" }),
27855
27322
  /* @__PURE__ */ jsx32(Text27, { children: " Esc exit the panel" }),
27856
27323
  /* @__PURE__ */ jsx32(Text27, { children: " " }),
27857
27324
  /* @__PURE__ */ jsx32(Text27, { bold: true, children: "Field editing" }),
@@ -27875,7 +27342,7 @@ function FieldEditor({
27875
27342
  /* @__PURE__ */ jsx32(Text27, { color: PALETTE.muted, children: "press ? or Esc to close" })
27876
27343
  ] }),
27877
27344
  validationError && /* @__PURE__ */ jsx32(Text27, { color: PALETTE.error, children: "\u2717 " + validationError }),
27878
- /* @__PURE__ */ jsx32(Box26, { paddingTop: 1, children: /* @__PURE__ */ jsx32(Text27, { color: pendingDelete ? PALETTE.text : PALETTE.muted, children: modeLabel }) })
27345
+ /* @__PURE__ */ jsx32(Box26, { paddingTop: 1, children: /* @__PURE__ */ jsx32(Text27, { color: PALETTE.muted, children: modeLabel }) })
27879
27346
  ]
27880
27347
  }
27881
27348
  );
@@ -28268,8 +27735,8 @@ function TokenReviewPanel({
28268
27735
  borderStyle: "single",
28269
27736
  borderColor: active ? PALETTE.text : void 0,
28270
27737
  children: [
28271
- /* @__PURE__ */ jsx39(Text32, { bold: true, color: active ? void 0 : PALETTE.muted, wrap: "truncate", children: `Review mapped tokens \u2014 ${componentName} \xB7 ${current.propName}${current.kinds.length > 0 ? ` (${current.kinds.join(", ")})` : ""}` }),
28272
- /* @__PURE__ */ jsx39(Text32, { color: PALETTE.muted, wrap: "truncate", children: `Tick the tokens this property may use (${rangeLabel}).` }),
27738
+ /* @__PURE__ */ jsx39(Text32, { bold: true, color: active ? void 0 : PALETTE.muted, wrap: "truncate", children: `TOKEN REVIEW \u2014 ${componentName} \xB7 ${current.propName} (edit allowed)` }),
27739
+ /* @__PURE__ */ jsx39(Text32, { color: PALETTE.muted, wrap: "truncate", children: `select which tokens are allowed (${rangeLabel})` }),
28273
27740
  /* @__PURE__ */ jsx39(Text32, { children: " " }),
28274
27741
  current.paths.length === 0 && /* @__PURE__ */ jsx39(Text32, { color: PALETTE.muted, children: "(no compatible tokens found for this token kind)" }),
28275
27742
  visiblePaths.map((path5, i) => {
@@ -28302,33 +27769,18 @@ function TokenReviewPanel({
28302
27769
  borderStyle: "single",
28303
27770
  borderColor: active ? PALETTE.text : void 0,
28304
27771
  children: [
28305
- /* @__PURE__ */ jsx39(Text32, { bold: true, color: active ? void 0 : PALETTE.muted, children: `Review mapped tokens \u2014 ${componentName}` }),
28306
- /* @__PURE__ */ jsx39(Text32, { color: PALETTE.muted, wrap: "truncate", children: `${componentName} has ${suggestions.length} design ${suggestions.length === 1 ? "prop" : "props"} of type token. Select which tokens are allowed for each property.` }),
28307
- /* @__PURE__ */ jsx39(Text32, { color: PALETTE.muted, wrap: "truncate", children: "Suggested tokens come from the agent. Allowed tokens are what editors can pick in Contentful." }),
28308
- /* @__PURE__ */ jsx39(Text32, { children: " " }),
27772
+ /* @__PURE__ */ jsx39(Text32, { bold: true, color: active ? void 0 : PALETTE.muted, children: `TOKEN REVIEW \u2014 ${componentName}` }),
28309
27773
  suggestions.length === 0 && /* @__PURE__ */ jsx39(Text32, { color: PALETTE.muted, children: "(no token suggestions for this component)" }),
28310
27774
  suggestions.map((s, i) => {
28311
27775
  const focused = i === selectedRow;
28312
27776
  return /* @__PURE__ */ jsxs30(Box31, { flexDirection: "column", children: [
28313
- /* @__PURE__ */ jsx39(Box31, { children: /* @__PURE__ */ jsx39(Text32, { color: focused ? PALETTE.accent : active ? void 0 : PALETTE.muted, bold: focused, children: `${focused ? figures7.pointer : " "} ${s.propName}${s.kinds.length > 0 ? ` (${s.kinds.join(", ")})` : ""}` }) }),
28314
- /* @__PURE__ */ jsx39(
28315
- Text32,
28316
- {
28317
- color: PALETTE.muted,
28318
- children: ` suggested: ${s.suggested.length > 0 ? s.suggested.join(", ") : "none"}`
28319
- }
28320
- ),
28321
- /* @__PURE__ */ jsx39(
28322
- Text32,
28323
- {
28324
- color: PALETTE.muted,
28325
- children: ` allowed: ${s.allowed.length > 0 ? s.allowed.join(", ") : "none (any token)"}`
28326
- }
28327
- ),
28328
- /* @__PURE__ */ jsx39(Text32, { children: " " })
27777
+ /* @__PURE__ */ jsx39(Box31, { children: /* @__PURE__ */ jsx39(Text32, { color: focused ? PALETTE.accent : active ? void 0 : PALETTE.muted, bold: focused, children: `${focused ? figures7.pointer : " "} ${s.propName}` }) }),
27778
+ /* @__PURE__ */ jsx39(Text32, { color: PALETTE.muted, children: ` suggested: ${s.suggested.join(", ")}` }),
27779
+ /* @__PURE__ */ jsx39(Text32, { color: PALETTE.muted, children: ` allowed: ${s.allowed.join(", ")}` })
28329
27780
  ] }, s.propName);
28330
27781
  }),
28331
- /* @__PURE__ */ jsx39(Text32, { color: PALETTE.muted, children: "[\u2191/\u2193] move [Enter] edit allowed tokens [Esc] close" })
27782
+ /* @__PURE__ */ jsx39(Text32, { children: " " }),
27783
+ /* @__PURE__ */ jsx39(Text32, { children: "[\u2191/\u2193] move [Enter] edit allowed [Esc] close" })
28332
27784
  ]
28333
27785
  }
28334
27786
  );
@@ -28602,9 +28054,15 @@ function ReviewFinalizeError({
28602
28054
  function ReviewPanelFooter({
28603
28055
  reviewEditor,
28604
28056
  sidebarFocused,
28605
- sidebarFooter
28057
+ sidebarFooter,
28058
+ livePreview,
28059
+ livePreviewSpinner
28606
28060
  }) {
28607
- return /* @__PURE__ */ jsx42(Fragment10, { children: reviewEditor.panelOpen === "token-review" ? "" : sidebarFocused ? sidebarFooter : reviewEditor.showJson ? " [\u2191\u2193] scroll [Ctrl+u/d] half-page [gg/G] top/bottom [Tab] focus list" : " [Tab] focus list [Enter] edit fields" + (reviewEditor.currentTokenSuggestions().length > 0 ? " [t] review mapped tokens" : "") });
28061
+ return /* @__PURE__ */ jsxs32(Fragment10, { children: [
28062
+ reviewEditor.panelOpen === "token-review" ? " [\u2191/\u2193] move [Enter] edit allowed [Esc] close" : sidebarFocused ? sidebarFooter : reviewEditor.showJson ? " [\u2191\u2193] scroll [Ctrl+u/d] half-page [gg/G] top/bottom [Tab] focus list" : " [Tab] focus list (edit fields)" + (reviewEditor.currentTokenSuggestions().length > 0 ? " [t] token review" : ""),
28063
+ livePreview.status === "running" && /* @__PURE__ */ jsx42(Text34, { children: ` ${livePreviewSpinner} live preview` }),
28064
+ livePreview.disabled && /* @__PURE__ */ jsx42(Text34, { children: " \xB7 live preview disabled" })
28065
+ ] });
28608
28066
  }
28609
28067
  function ReviewComponentTitle({
28610
28068
  selectedKey,
@@ -28638,7 +28096,9 @@ function ReviewComponentPanel({
28638
28096
  sidebarFocused,
28639
28097
  fieldEditor,
28640
28098
  saveError,
28641
- sidebarFooter
28099
+ sidebarFooter,
28100
+ livePreview,
28101
+ livePreviewSpinner
28642
28102
  }) {
28643
28103
  const propCount = Object.keys(selectedEntry.$properties).length;
28644
28104
  const slotCount = selectedEntry.$slots ? Object.keys(selectedEntry.$slots).length : 0;
@@ -28675,7 +28135,9 @@ function ReviewComponentPanel({
28675
28135
  {
28676
28136
  reviewEditor,
28677
28137
  sidebarFocused,
28678
- sidebarFooter
28138
+ sidebarFooter,
28139
+ livePreview,
28140
+ livePreviewSpinner
28679
28141
  }
28680
28142
  ) }) })
28681
28143
  ] }) });
@@ -29032,7 +28494,7 @@ var init_FinalizeDialog = __esm({
29032
28494
  });
29033
28495
 
29034
28496
  // packages/experience-design-system-cli/src/tui/import/steps/09-review/use-finalize-preview.ts
29035
- import { useEffect as useEffect13, useRef as useRef10, useState as useState20 } from "react";
28497
+ import { useEffect as useEffect12, useRef as useRef9, useState as useState20 } from "react";
29036
28498
  function useReviewFinalizePreview({
29037
28499
  components,
29038
28500
  ...options
@@ -29047,9 +28509,9 @@ function useFinalizePreview(opts) {
29047
28509
  const [status, setStatus] = useState20("idle");
29048
28510
  const [removed, setRemoved] = useState20([]);
29049
28511
  const [scrollOffset, setScrollOffset] = useState20(0);
29050
- const generationRef = useRef10(0);
28512
+ const generationRef = useRef9(0);
29051
28513
  const acceptedKey = [...acceptedKeys].sort().join("\0");
29052
- useEffect13(() => {
28514
+ useEffect12(() => {
29053
28515
  if (!open) {
29054
28516
  setStatus("idle");
29055
28517
  setRemoved([]);
@@ -29101,7 +28563,7 @@ var init_use_finalize_preview = __esm({
29101
28563
  });
29102
28564
 
29103
28565
  // packages/experience-design-system-cli/src/tui/import/steps/09-review/use-review-session.ts
29104
- import { useCallback as useCallback2, useEffect as useEffect14, useRef as useRef11, useState as useState21 } from "react";
28566
+ import { useCallback as useCallback2, useEffect as useEffect13, useRef as useRef10, useState as useState21 } from "react";
29105
28567
  function useReviewSession({
29106
28568
  loadSession,
29107
28569
  tokensPath,
@@ -29120,7 +28582,7 @@ function useReviewSession({
29120
28582
  }));
29121
28583
  return { result, catalog };
29122
28584
  }, [loadSession, tokensPath]);
29123
- useEffect14(() => {
28585
+ useEffect13(() => {
29124
28586
  let disposed = false;
29125
28587
  void (async () => {
29126
28588
  try {
@@ -29173,7 +28635,7 @@ function useReviewSession({
29173
28635
  function useReviewMetadata({ components, selectedIdx, extractSessionId }) {
29174
28636
  const [reviewMetadata, setReviewMetadata] = useState21(null);
29175
28637
  const [componentRationale, setComponentRationale] = useState21(null);
29176
- useEffect14(() => {
28638
+ useEffect13(() => {
29177
28639
  const current = components[selectedIdx];
29178
28640
  if (!current) {
29179
28641
  setReviewMetadata(null);
@@ -29203,9 +28665,9 @@ function useReviewMetadata({ components, selectedIdx, extractSessionId }) {
29203
28665
  return { reviewMetadata, componentRationale };
29204
28666
  }
29205
28667
  function useReviewHistory({ loading, components, createSnapshot, applySnapshot }) {
29206
- const historyRef = useRef11(null);
29207
- const historySeededRef = useRef11(false);
29208
- useEffect14(() => {
28668
+ const historyRef = useRef10(null);
28669
+ const historySeededRef = useRef10(false);
28670
+ useEffect13(() => {
29209
28671
  if (loading || historySeededRef.current) return;
29210
28672
  historySeededRef.current = true;
29211
28673
  historyRef.current = createHistoryStack(createSnapshot(components));
@@ -29277,7 +28739,7 @@ function collectTokenSuggestions(entry, availableTokens = []) {
29277
28739
  const compatiblePaths = new Set(compatible);
29278
28740
  const allowed = availableTokens.length > 0 ? persistedAllowed.filter((path5) => compatiblePaths.has(path5)) : persistedAllowed;
29279
28741
  const paths = availableTokens.length > 0 ? compatible : allowed;
29280
- return { propName, kinds, paths, suggested: [...allowed], allowed };
28742
+ return { propName, paths, suggested: [...allowed], allowed };
29281
28743
  });
29282
28744
  }
29283
28745
  var init_token_suggestions = __esm({
@@ -29287,7 +28749,7 @@ var init_token_suggestions = __esm({
29287
28749
  });
29288
28750
 
29289
28751
  // packages/experience-design-system-cli/src/tui/import/steps/09-review/use-review-editor.ts
29290
- import { useEffect as useEffect15, useRef as useRef12, useState as useState22 } from "react";
28752
+ import { useEffect as useEffect14, useRef as useRef11, useState as useState22 } from "react";
29291
28753
  function parseReviewEntry(draftValue) {
29292
28754
  const parsed = JSON.parse(draftValue);
29293
28755
  const keys = Object.keys(parsed);
@@ -29319,9 +28781,9 @@ function useReviewEditor({
29319
28781
  const [tokenReviewEditing, setTokenReviewEditing] = useState22(false);
29320
28782
  const [tokenReviewEditCursor, setTokenReviewEditCursor] = useState22(0);
29321
28783
  const [tokenReviewEditSelection, setTokenReviewEditSelection] = useState22(/* @__PURE__ */ new Set());
29322
- const tokenReviewSuggestedRef = useRef12(/* @__PURE__ */ new Map());
29323
- const pendingGRef = useRef12(false);
29324
- useEffect15(() => {
28784
+ const tokenReviewSuggestedRef = useRef11(/* @__PURE__ */ new Map());
28785
+ const pendingGRef = useRef11(false);
28786
+ useEffect14(() => {
29325
28787
  setTokenReviewRow(0);
29326
28788
  setTokenReviewEditing(false);
29327
28789
  setTokenReviewEditCursor(0);
@@ -29803,24 +29265,24 @@ var init_preview_annotations = __esm({
29803
29265
  });
29804
29266
 
29805
29267
  // packages/experience-design-system-cli/src/tui/import/steps/09-review/use-live-preview.ts
29806
- import { useCallback as useCallback3, useEffect as useEffect16, useRef as useRef13, useState as useState24 } from "react";
29268
+ import { useCallback as useCallback3, useEffect as useEffect15, useRef as useRef12, useState as useState24 } from "react";
29807
29269
  function useLivePreview(opts) {
29808
29270
  const debounceMs = opts.debounceMs ?? DEFAULT_DEBOUNCE_MS;
29809
29271
  const [status, setStatus] = useState24("idle");
29810
29272
  const [disabled, setDisabled] = useState24(false);
29811
- const timerRef = useRef13(null);
29812
- const generationRef = useRef13(0);
29813
- const latestRef = useRef13(0);
29814
- const inflightRef = useRef13(0);
29815
- const optsRef = useRef13(opts);
29816
- useEffect16(() => {
29273
+ const timerRef = useRef12(null);
29274
+ const generationRef = useRef12(0);
29275
+ const latestRef = useRef12(0);
29276
+ const inflightRef = useRef12(0);
29277
+ const optsRef = useRef12(opts);
29278
+ useEffect15(() => {
29817
29279
  optsRef.current = opts;
29818
29280
  });
29819
- const disabledRef = useRef13(disabled);
29820
- useEffect16(() => {
29281
+ const disabledRef = useRef12(disabled);
29282
+ useEffect15(() => {
29821
29283
  disabledRef.current = disabled;
29822
29284
  }, [disabled]);
29823
- useEffect16(() => {
29285
+ useEffect15(() => {
29824
29286
  return () => {
29825
29287
  if (timerRef.current) {
29826
29288
  clearTimeout(timerRef.current);
@@ -29901,7 +29363,7 @@ var init_use_live_preview = __esm({
29901
29363
  });
29902
29364
 
29903
29365
  // packages/experience-design-system-cli/src/tui/import/steps/09-review/use-review-preview.ts
29904
- import { useCallback as useCallback4, useEffect as useEffect17, useState as useState25 } from "react";
29366
+ import { useCallback as useCallback4, useEffect as useEffect16, useState as useState25 } from "react";
29905
29367
  function useReviewPreview({
29906
29368
  components,
29907
29369
  loading,
@@ -29943,13 +29405,13 @@ function useReviewPreview({
29943
29405
  deleteAllComponents
29944
29406
  });
29945
29407
  const [spinnerTick, setSpinnerTick] = useState25(0);
29946
- useEffect17(() => {
29408
+ useEffect16(() => {
29947
29409
  if (livePreviewHook.status !== "running") return;
29948
29410
  const id = setInterval(() => setSpinnerTick((tick) => tick + 1), 80);
29949
29411
  return () => clearInterval(id);
29950
29412
  }, [livePreviewHook.status]);
29951
29413
  const livePreviewSpinner = SPINNER_FRAMES[spinnerTick % SPINNER_FRAMES.length];
29952
- useEffect17(() => {
29414
+ useEffect16(() => {
29953
29415
  if (loading) return;
29954
29416
  if (!livePreview) return;
29955
29417
  if (components.length === 0) return;
@@ -30006,7 +29468,7 @@ var init_LivePreviewSummary = __esm({
30006
29468
  });
30007
29469
 
30008
29470
  // packages/experience-design-system-cli/src/tui/import/steps/09-review/generate-review-step.tsx
30009
- import { useCallback as useCallback5, useEffect as useEffect18, useMemo as useMemo6, useRef as useRef14, useState as useState26 } from "react";
29471
+ import { useCallback as useCallback5, useEffect as useEffect17, useMemo as useMemo6, useRef as useRef13, useState as useState26 } from "react";
30010
29472
  import figures8 from "figures";
30011
29473
  import { Box as Box38, Text as Text40 } from "ink";
30012
29474
  import { Fragment as Fragment14, jsx as jsx48, jsxs as jsxs38 } from "react/jsx-runtime";
@@ -30220,7 +29682,7 @@ function GenerateReviewStepView({
30220
29682
  setFinalizeError
30221
29683
  } = reviewSurface;
30222
29684
  const [removedBannerCollapsed, setRemovedBannerCollapsed] = useState26(false);
30223
- const removedBannerDefaultedRef = useRef14(false);
29685
+ const removedBannerDefaultedRef = useRef13(false);
30224
29686
  const [cyclePanelScroll, setCyclePanelScroll] = useState26(0);
30225
29687
  const [cyclesCursor, setCyclesCursor] = useState26(0);
30226
29688
  const cyclePanel = useOverlayPanel({
@@ -30240,7 +29702,7 @@ function GenerateReviewStepView({
30240
29702
  const [breakCursor, setBreakCursor] = useState26(0);
30241
29703
  const [breakConfirm, setBreakConfirm] = useState26(false);
30242
29704
  const [expandedGroups, setExpandedGroups] = useState26(/* @__PURE__ */ new Set());
30243
- const seededGroupsRef = useRef14(false);
29705
+ const seededGroupsRef = useRef13(false);
30244
29706
  const {
30245
29707
  searchOpen,
30246
29708
  setSearchOpen,
@@ -30264,7 +29726,7 @@ function GenerateReviewStepView({
30264
29726
  const [pendingEditorFocus, setPendingEditorFocus] = useState26(null);
30265
29727
  const [autoRejected, setAutoRejected] = useState26([]);
30266
29728
  const [undoSnapshot, setUndoSnapshot] = useState26(null);
30267
- const autoRejectFiredRef = useRef14(false);
29729
+ const autoRejectFiredRef = useRef13(false);
30268
29730
  const [showReloadDialog, setShowReloadDialog] = useState26(false);
30269
29731
  const acceptedCountForPreview = components.filter((c2) => c2.status === "accepted").length;
30270
29732
  const { previewAnnotations, removedComponents, livePreviewHook, livePreviewSpinner } = useReviewPreview({
@@ -30327,7 +29789,7 @@ function GenerateReviewStepView({
30327
29789
  [components]
30328
29790
  );
30329
29791
  const closures = useMemo6(() => computeAllClosures(componentGraph), [componentGraph]);
30330
- useEffect18(() => {
29792
+ useEffect17(() => {
30331
29793
  if (seededGroupsRef.current) return;
30332
29794
  if (closures.size === 0 && slotCycles.length === 0) return;
30333
29795
  seededGroupsRef.current = true;
@@ -30354,7 +29816,7 @@ function GenerateReviewStepView({
30354
29816
  suggestedBreak: cycle.edges.length > 0 ? suggestCycleBreakEdge2(cycle, cycleView.pushBlocking) : null
30355
29817
  }));
30356
29818
  }, [slotCycles, cycleView]);
30357
- useEffect18(() => {
29819
+ useEffect17(() => {
30358
29820
  const decision = computeAutoRejectDecision({
30359
29821
  loading,
30360
29822
  autoRejectFired: autoRejectFiredRef.current,
@@ -30397,8 +29859,8 @@ function GenerateReviewStepView({
30397
29859
  }),
30398
29860
  applySnapshot: applyHistorySnapshot
30399
29861
  });
30400
- const autoRejectPushedRef = useRef14(false);
30401
- useEffect18(() => {
29862
+ const autoRejectPushedRef = useRef13(false);
29863
+ useEffect17(() => {
30402
29864
  if (loading) return;
30403
29865
  if (!historySeededRef.current) return;
30404
29866
  if (!autoRejectFiredRef.current) return;
@@ -30482,7 +29944,7 @@ function GenerateReviewStepView({
30482
29944
  const panelHeight = leftPanelHeight + 2;
30483
29945
  const panelContentHeight = Math.max(1, panelHeight - 3);
30484
29946
  const cycleViewportHeight = Math.max(1, panelHeight - 4);
30485
- useEffect18(() => {
29947
+ useEffect17(() => {
30486
29948
  if (selectableRowPositions.length === 0) return;
30487
29949
  const cursorInRange = selectableRowPositions.includes(cursorRowIdx);
30488
29950
  const maxScroll = Math.max(0, visibleRowsMemo.length - visibleCount);
@@ -31228,7 +30690,9 @@ function GenerateReviewStepView({
31228
30690
  initialFocusTarget: pendingEditorFocus && pendingEditorFocus.componentName === selected.key ? pendingEditorFocus.target : { kind: "description" }
31229
30691
  }
31230
30692
  ),
31231
- saveError: reviewEditor.saveError
30693
+ saveError: reviewEditor.saveError,
30694
+ livePreview: livePreviewHook,
30695
+ livePreviewSpinner
31232
30696
  }
31233
30697
  ) : /* @__PURE__ */ jsx48(ReviewNoSelection, {})
31234
30698
  ] }),
@@ -31260,7 +30724,7 @@ function GenerateReviewStepView({
31260
30724
  hidden: dialogOpen
31261
30725
  }
31262
30726
  ),
31263
- !dialogOpen && sidebarFocused && reviewEditor.panelOpen !== "token-review" && /* @__PURE__ */ jsx48(CompactControlBar, { hasGroupRoots, searchActive: searchOpen || searchQuery.length > 0 })
30727
+ !dialogOpen && sidebarFocused && /* @__PURE__ */ jsx48(CompactControlBar, { hasGroupRoots, searchActive: searchOpen || searchQuery.length > 0 })
31264
30728
  ] });
31265
30729
  }
31266
30730
  var HELP_SECTIONS2;
@@ -31342,7 +30806,7 @@ var init_generate_review_step = __esm({
31342
30806
  { keys: "P", label: "Component rationale" },
31343
30807
  { keys: "s", label: "Source code snippet" },
31344
30808
  { keys: "J", label: "Toggle JSON" },
31345
- { keys: "t", label: "Review mapped tokens" }
30809
+ { keys: "t", label: "Token review" }
31346
30810
  ]
31347
30811
  },
31348
30812
  {
@@ -31541,7 +31005,7 @@ var init_DoneStep = __esm({
31541
31005
  });
31542
31006
 
31543
31007
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/path-utils.ts
31544
- import { resolve as resolve26 } from "node:path";
31008
+ import { resolve as resolve25 } from "node:path";
31545
31009
  import { homedir as homedir4 } from "node:os";
31546
31010
  function expandTilde(input) {
31547
31011
  if (input === "~" || input.startsWith("~/") || input.startsWith("~\\")) {
@@ -31555,7 +31019,7 @@ function normalizePath(input) {
31555
31019
  p = p.slice(1, -1);
31556
31020
  }
31557
31021
  p = expandTilde(p);
31558
- return resolve26(p);
31022
+ return resolve25(p);
31559
31023
  }
31560
31024
  var init_path_utils = __esm({
31561
31025
  "packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/path-utils.ts"() {
@@ -31564,10 +31028,10 @@ var init_path_utils = __esm({
31564
31028
  });
31565
31029
 
31566
31030
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/use-blinking-cursor.ts
31567
- import { useEffect as useEffect19, useState as useState27 } from "react";
31031
+ import { useEffect as useEffect18, useState as useState27 } from "react";
31568
31032
  function useBlinkingCursor() {
31569
31033
  const [visible, setVisible] = useState27(true);
31570
- useEffect19(() => {
31034
+ useEffect18(() => {
31571
31035
  const interval = setInterval(() => setVisible((current) => !current), 500);
31572
31036
  return () => clearInterval(interval);
31573
31037
  }, []);
@@ -31582,29 +31046,29 @@ var init_use_blinking_cursor = __esm({
31582
31046
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/screens/PathPrompt.tsx
31583
31047
  import { useState as useState28 } from "react";
31584
31048
  import { Box as Box42, Text as Text44 } from "ink";
31585
- import { readdirSync as readdirSync4 } from "node:fs";
31586
- import { dirname as dirname17, basename as basename6, join as join23 } from "node:path";
31049
+ import { readdirSync as readdirSync3 } from "node:fs";
31050
+ import { dirname as dirname16, basename as basename6, join as join21 } from "node:path";
31587
31051
  import { jsx as jsx52, jsxs as jsxs42 } from "react/jsx-runtime";
31588
31052
  function autocomplete(partial) {
31589
31053
  if (!partial) return null;
31590
31054
  const normalized = normalizePath(partial);
31591
- const dir = dirname17(normalized);
31055
+ const dir = dirname16(normalized);
31592
31056
  const base = basename6(normalized);
31593
31057
  let entries;
31594
31058
  try {
31595
- entries = readdirSync4(dir);
31059
+ entries = readdirSync3(dir);
31596
31060
  } catch {
31597
31061
  return null;
31598
31062
  }
31599
31063
  const matches = entries.filter((e) => e.startsWith(base));
31600
31064
  if (matches.length === 0) return null;
31601
- if (matches.length === 1) return join23(dir, matches[0]);
31065
+ if (matches.length === 1) return join21(dir, matches[0]);
31602
31066
  let prefix = matches[0];
31603
31067
  for (const m of matches) {
31604
31068
  while (!m.startsWith(prefix)) prefix = prefix.slice(0, -1);
31605
31069
  if (!prefix) break;
31606
31070
  }
31607
- return prefix.length > base.length ? join23(dir, prefix) : null;
31071
+ return prefix.length > base.length ? join21(dir, prefix) : null;
31608
31072
  }
31609
31073
  function PathPrompt({
31610
31074
  defaultPath,
@@ -31704,12 +31168,12 @@ var init_produced = __esm({
31704
31168
  });
31705
31169
 
31706
31170
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/use-timed-spinner.tsx
31707
- import { useEffect as useEffect20, useState as useState29 } from "react";
31171
+ import { useEffect as useEffect19, useState as useState29 } from "react";
31708
31172
  import { Spinner as Spinner2 } from "@inkjs/ui";
31709
31173
  import { jsx as jsx53 } from "react/jsx-runtime";
31710
31174
  function useTimedSpinner() {
31711
31175
  const [elapsedSeconds, setElapsedSeconds] = useState29(0);
31712
- useEffect20(() => {
31176
+ useEffect19(() => {
31713
31177
  const timer = setInterval(() => setElapsedSeconds((current) => current + 1), 1e3);
31714
31178
  return () => {
31715
31179
  clearInterval(timer);
@@ -31921,20 +31385,12 @@ function diffProperty(name, old, newDef) {
31921
31385
  diffs.push({ key: `${name}-new`, color: PALETTE.success, text: `+ ${name}: ${formatPropDef(newDef)}` });
31922
31386
  return diffs;
31923
31387
  }
31924
- function formatDefault(value) {
31925
- const sys = value?.sys;
31926
- if (sys?.linkType === "Contentful:DesignToken" && typeof sys.urn === "string") {
31927
- const name = sys.urn.split("/designTokens/")[1];
31928
- if (name) return name;
31929
- }
31930
- return JSON.stringify(value);
31931
- }
31932
31388
  function formatOldProp(prop) {
31933
31389
  const parts = [];
31934
31390
  if (prop.type) parts.push(prop.type);
31935
31391
  if (prop.category) parts.push(prop.category);
31936
31392
  parts.push(prop.required ? "required" : "optional");
31937
- if (prop.default !== void 0) parts.push(`default=${formatDefault(prop.default)}`);
31393
+ if (prop.default !== void 0) parts.push(`default=${JSON.stringify(prop.default)}`);
31938
31394
  return parts.join(", ");
31939
31395
  }
31940
31396
  function formatPropDef(def) {
@@ -31943,7 +31399,7 @@ function formatPropDef(def) {
31943
31399
  if (def["$category"]) parts.push(def["$category"]);
31944
31400
  if (def["$required"] === true) parts.push("required");
31945
31401
  else parts.push("optional");
31946
- if (def["$default"] !== void 0) parts.push(`default=${formatDefault(def["$default"])}`);
31402
+ if (def["$default"] !== void 0) parts.push(`default=${JSON.stringify(def["$default"])}`);
31947
31403
  return parts.join(", ");
31948
31404
  }
31949
31405
  var init_preview_diff = __esm({
@@ -31978,7 +31434,7 @@ var init_preview_confirmation_input = __esm({
31978
31434
  });
31979
31435
 
31980
31436
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/screens/WizardPreviewStep.tsx
31981
- import { useEffect as useEffect21, useState as useState30, useMemo as useMemo7 } from "react";
31437
+ import { useEffect as useEffect20, useState as useState30, useMemo as useMemo7 } from "react";
31982
31438
  import { Box as Box44, Text as Text46 } from "ink";
31983
31439
  import { Fragment as Fragment16, jsx as jsx55, jsxs as jsxs44 } from "react/jsx-runtime";
31984
31440
  function buildPreviewSummaryLines(preview) {
@@ -32188,7 +31644,7 @@ function WizardPreviewStep({
32188
31644
  const activeLines = diffExpanded ? diffLines : summaryLines;
32189
31645
  const maxScroll = Math.max(0, activeLines.length - viewportHeight);
32190
31646
  const boundedScrollOffset = Math.min(scrollOffset, maxScroll);
32191
- useEffect21(() => {
31647
+ useEffect20(() => {
32192
31648
  setScrollOffset((previous) => Math.min(previous, maxScroll));
32193
31649
  }, [maxScroll]);
32194
31650
  useImmediateInput((input, key) => {
@@ -32824,8 +32280,8 @@ var init_run_print_files_helpers = __esm({
32824
32280
  });
32825
32281
 
32826
32282
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/save.ts
32827
- import { writeFile as writeFile8 } from "node:fs/promises";
32828
- import { join as join24 } from "node:path";
32283
+ import { writeFile as writeFile7 } from "node:fs/promises";
32284
+ import { join as join22 } from "node:path";
32829
32285
  function buildSavedCDF(components, tokens, opts = {}) {
32830
32286
  const cdf = buildCDF2(components, toCdfTokens(tokens), opts);
32831
32287
  if (!cdf) throw new Error("nothing to save \u2014 no components or tokens resolved");
@@ -32837,7 +32293,7 @@ function buildSavedCDF(components, tokens, opts = {}) {
32837
32293
  }
32838
32294
  async function runPrintFiles(input, deps, onPatch) {
32839
32295
  onPatch({ step: "printing" });
32840
- const componentsPath = join24(input.outDir, "components.json");
32296
+ const componentsPath = join22(input.outDir, "components.json");
32841
32297
  try {
32842
32298
  const db = deps.openDb();
32843
32299
  let components = [];
@@ -32921,7 +32377,7 @@ var init_save = __esm({
32921
32377
  realSaveDeps = () => ({
32922
32378
  openDb: openPipelineDb,
32923
32379
  readTokens: (path5) => readTokensFromPath2({ flag: "tokens", path: path5 }),
32924
- writeFile: (path5, contents) => writeFile8(path5, contents),
32380
+ writeFile: (path5, contents) => writeFile7(path5, contents),
32925
32381
  appendRun,
32926
32382
  buildSourceFingerprint,
32927
32383
  sleep: (ms) => new Promise((resolve29) => setTimeout(resolve29, ms)),
@@ -32944,9 +32400,9 @@ var init_types9 = __esm({
32944
32400
 
32945
32401
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/controller.ts
32946
32402
  import { appendFileSync, writeFileSync } from "node:fs";
32947
- import { mkdir as mkdir9 } from "node:fs/promises";
32403
+ import { mkdir as mkdir8 } from "node:fs/promises";
32948
32404
  import { tmpdir } from "node:os";
32949
- import { join as join25, resolve as resolve27 } from "node:path";
32405
+ import { join as join23, resolve as resolve26 } from "node:path";
32950
32406
  function appendWizardLog(entry) {
32951
32407
  appendFileSync(WIZARD_LOG, JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), ...entry }) + "\n");
32952
32408
  }
@@ -32969,7 +32425,7 @@ function realFlowDeps() {
32969
32425
  }
32970
32426
  },
32971
32427
  mkdir: async (path5) => {
32972
- await mkdir9(path5, { recursive: true });
32428
+ await mkdir8(path5, { recursive: true });
32973
32429
  },
32974
32430
  detectSaveConflict,
32975
32431
  buildTimestampedSubdir,
@@ -33199,7 +32655,7 @@ function createFlowController(start, deps) {
33199
32655
  },
33200
32656
  async submitPath(submitted) {
33201
32657
  await deps.mkdir(submitted);
33202
- if (resolve27(submitted) !== resolve27(state2.outDir) && await deps.detectSaveConflict(submitted)) {
32658
+ if (resolve26(submitted) !== resolve26(state2.outDir) && await deps.detectSaveConflict(submitted)) {
33203
32659
  const subdir = deps.buildTimestampedSubdir(submitted);
33204
32660
  await deps.mkdir(subdir);
33205
32661
  await proceedToWrite(subdir);
@@ -33215,55 +32671,351 @@ function createFlowController(start, deps) {
33215
32671
  const names = namesToSkip(state2.previewValidationErrors);
33216
32672
  if (names.length > 0) await deps.rejectComponentsByName(state2.extractSessionId, names);
33217
32673
  }
33218
- await preview();
32674
+ await preview();
32675
+ }
32676
+ };
32677
+ }
32678
+ var WIZARD_LOG;
32679
+ var init_controller = __esm({
32680
+ "packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/controller.ts"() {
32681
+ "use strict";
32682
+ init_src3();
32683
+ init_slot_graph();
32684
+ init_cycle_detection();
32685
+ init_wizard_state_transitions();
32686
+ init_preview2();
32687
+ init_push();
32688
+ init_save();
32689
+ init_types9();
32690
+ WIZARD_LOG = join23(tmpdir(), "experiences-import-wizard.log");
32691
+ }
32692
+ });
32693
+
32694
+ // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/use-flow.ts
32695
+ import { useEffect as useEffect21, useRef as useRef14, useSyncExternalStore } from "react";
32696
+ function useFlow(start, options = {}) {
32697
+ const controller = useRef14();
32698
+ if (start && !controller.current) {
32699
+ try {
32700
+ startWizardLog();
32701
+ } catch {
32702
+ }
32703
+ const flowDeps = (options.deps ?? realFlowDeps)();
32704
+ controller.current = createFlowController(start, {
32705
+ ...flowDeps,
32706
+ ...options.beforeStepChange ? { beforeStepChange: options.beforeStepChange } : {}
32707
+ });
32708
+ }
32709
+ const current = controller.current;
32710
+ const state2 = useSyncExternalStore(
32711
+ (listener) => current?.subscribe(listener) ?? (() => void 0),
32712
+ () => current?.getState()
32713
+ );
32714
+ useEffect21(() => {
32715
+ if (!start) controller.current = void 0;
32716
+ }, [start]);
32717
+ return current && state2 ? { controller: current, state: state2 } : void 0;
32718
+ }
32719
+ var init_use_flow = __esm({
32720
+ "packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/use-flow.ts"() {
32721
+ "use strict";
32722
+ init_controller();
32723
+ }
32724
+ });
32725
+
32726
+ // packages/experience-design-system-cli/src/tui/settings/debug-mode/debug-mode-store.ts
32727
+ function toRetentionDays(value) {
32728
+ return RETENTION_CHOICES.find((choice) => choice === value) ?? DEFAULT_RETENTION_DAYS;
32729
+ }
32730
+ async function readDebugModeSetting() {
32731
+ const { debugMode } = await readSettings2();
32732
+ const saved = debugMode ?? {};
32733
+ return {
32734
+ enabled: typeof saved.enabled === "boolean" ? saved.enabled : true,
32735
+ retentionDays: toRetentionDays(saved.retentionDays)
32736
+ };
32737
+ }
32738
+ async function writeDebugModeSetting(change) {
32739
+ await updateSettings2({ debugMode: { ...await readDebugModeSetting(), ...change } });
32740
+ }
32741
+ var RETENTION_CHOICES, DEFAULT_RETENTION_DAYS;
32742
+ var init_debug_mode_store = __esm({
32743
+ "packages/experience-design-system-cli/src/tui/settings/debug-mode/debug-mode-store.ts"() {
32744
+ "use strict";
32745
+ init_config();
32746
+ RETENTION_CHOICES = [7, 14, 30];
32747
+ DEFAULT_RETENTION_DAYS = 30;
32748
+ }
32749
+ });
32750
+
32751
+ // packages/experience-design-system-cli/src/tui/debug-prune.ts
32752
+ import { readdir as readdir2, rm, rmdir, stat as stat4 } from "node:fs/promises";
32753
+ import { dirname as dirname17, join as join24 } from "node:path";
32754
+ async function logFilesIn(dir) {
32755
+ const entries = await readdir2(dir, { withFileTypes: true });
32756
+ const nested = await Promise.all(
32757
+ entries.map(async (entry) => {
32758
+ const path5 = join24(dir, entry.name);
32759
+ if (entry.isDirectory()) return logFilesIn(path5);
32760
+ return entry.isFile() && entry.name.endsWith(".md") ? [path5] : [];
32761
+ })
32762
+ );
32763
+ return nested.flat();
32764
+ }
32765
+ async function removeEmptyFolders(from, stop) {
32766
+ let dir = from;
32767
+ let removed = 0;
32768
+ for (; ; ) {
32769
+ try {
32770
+ await rmdir(dir);
32771
+ } catch {
32772
+ return removed;
32773
+ }
32774
+ removed += 1;
32775
+ if (dir === stop) return removed;
32776
+ dir = dirname17(dir);
32777
+ }
32778
+ }
32779
+ async function pruneExpiredLogs(base, retentionDays, now = Date.now()) {
32780
+ const cutoff = now - retentionDays * DAY_MS;
32781
+ const contentfulDir = join24(base, ".contentful");
32782
+ const result = { logs: 0, folders: 0 };
32783
+ try {
32784
+ const sessions = (await readdir2(contentfulDir)).filter((name) => SESSION_FOLDER.test(name));
32785
+ for (const session of sessions) {
32786
+ const files = await logFilesIn(join24(contentfulDir, session, "debug")).catch(() => []);
32787
+ for (const file of files) {
32788
+ try {
32789
+ if ((await stat4(file)).mtimeMs >= cutoff) continue;
32790
+ await rm(file);
32791
+ result.logs += 1;
32792
+ result.folders += await removeEmptyFolders(dirname17(file), join24(contentfulDir, session));
32793
+ } catch {
32794
+ }
32795
+ }
33219
32796
  }
33220
- };
32797
+ } catch {
32798
+ }
32799
+ return result;
33221
32800
  }
33222
- var WIZARD_LOG;
33223
- var init_controller = __esm({
33224
- "packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/controller.ts"() {
32801
+ var DAY_MS, SESSION_FOLDER;
32802
+ var init_debug_prune = __esm({
32803
+ "packages/experience-design-system-cli/src/tui/debug-prune.ts"() {
33225
32804
  "use strict";
33226
- init_src3();
33227
- init_slot_graph();
33228
- init_cycle_detection();
33229
- init_wizard_state_transitions();
33230
- init_preview2();
33231
- init_push();
33232
- init_save();
33233
- init_types9();
33234
- WIZARD_LOG = join25(tmpdir(), "experiences-import-wizard.log");
32805
+ DAY_MS = 24 * 60 * 60 * 1e3;
32806
+ SESSION_FOLDER = /^\d{2}-\d{2}-\d{4}-session-\d+$/;
33235
32807
  }
33236
32808
  });
33237
32809
 
33238
- // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/use-flow.ts
33239
- import { useEffect as useEffect22, useRef as useRef15, useSyncExternalStore } from "react";
33240
- function useFlow(start, options = {}) {
33241
- const controller = useRef15();
33242
- if (start && !controller.current) {
33243
- try {
33244
- startWizardLog();
33245
- } catch {
33246
- }
33247
- const flowDeps = (options.deps ?? realFlowDeps)();
33248
- controller.current = createFlowController(start, {
33249
- ...flowDeps,
33250
- ...options.beforeStepChange ? { beforeStepChange: options.beforeStepChange } : {}
33251
- });
32810
+ // packages/experience-design-system-cli/src/tui/debug-store.ts
32811
+ var debug_store_exports = {};
32812
+ __export(debug_store_exports, {
32813
+ currentDebugSessionDir: () => currentDebugSessionDir,
32814
+ currentSessionDir: () => currentSessionDir,
32815
+ finishDebugRun: () => finishDebugRun,
32816
+ startDebugRun: () => startDebugRun,
32817
+ startDebugSessionIn: () => startDebugSessionIn,
32818
+ startImportRun: () => startImportRun
32819
+ });
32820
+ import { mkdir as mkdir9, writeFile as writeFile8 } from "node:fs/promises";
32821
+ import { existsSync as existsSync10, readdirSync as readdirSync4 } from "node:fs";
32822
+ import { join as join25, resolve as resolve27 } from "node:path";
32823
+ function generateRunId() {
32824
+ const now = /* @__PURE__ */ new Date();
32825
+ const pad = (n) => String(n).padStart(2, "0");
32826
+ return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
32827
+ }
32828
+ function datePrefix(now = /* @__PURE__ */ new Date()) {
32829
+ const pad = (n) => String(n).padStart(2, "0");
32830
+ return `${pad(now.getMonth() + 1)}-${pad(now.getDate())}-${now.getFullYear()}`;
32831
+ }
32832
+ function slugify(value) {
32833
+ return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
32834
+ }
32835
+ async function readBaseDir() {
32836
+ try {
32837
+ const dir = (await readSettings2())["contentfulBaseDir"];
32838
+ return typeof dir === "string" && dir !== "" ? resolve27(dir) : void 0;
32839
+ } catch {
32840
+ return void 0;
33252
32841
  }
33253
- const current = controller.current;
33254
- const state2 = useSyncExternalStore(
33255
- (listener) => current?.subscribe(listener) ?? (() => void 0),
33256
- () => current?.getState()
33257
- );
33258
- useEffect22(() => {
33259
- if (!start) controller.current = void 0;
33260
- }, [start]);
33261
- return current && state2 ? { controller: current, state: state2 } : void 0;
33262
32842
  }
33263
- var init_use_flow = __esm({
33264
- "packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/use-flow.ts"() {
32843
+ function nextSessionId(contentfulDir) {
32844
+ const today = datePrefix();
32845
+ const existing = existsSync10(contentfulDir) ? readdirSync4(contentfulDir) : [];
32846
+ const seqPattern = new RegExp(`^${today}-session-(\\d+)$`);
32847
+ const maxSeq = existing.reduce((max, entry) => {
32848
+ const match2 = seqPattern.exec(entry);
32849
+ return match2 ? Math.max(max, Number(match2[1])) : max;
32850
+ }, 0);
32851
+ return `${today}-session-${maxSeq + 1}`;
32852
+ }
32853
+ function startSession(base, { replace }) {
32854
+ const contentfulDir = join25(base, ".contentful");
32855
+ if (replace || !sessionDir) sessionDir = join25(contentfulDir, nextSessionId(contentfulDir));
32856
+ return sessionDir;
32857
+ }
32858
+ function currentDebugSessionDir() {
32859
+ return sessionDir && join25(sessionDir, "debug");
32860
+ }
32861
+ function currentSessionDir() {
32862
+ return sessionDir;
32863
+ }
32864
+ async function startDebugSessionIn(base, { replace = false } = {}) {
32865
+ try {
32866
+ if (!await isDebugModeEnabled()) return;
32867
+ await mkdir9(join25(startSession(resolve27(base), { replace }), "debug"), { recursive: true });
32868
+ } catch {
32869
+ }
32870
+ }
32871
+ function nextImportRunDir(session) {
32872
+ const existing = existsSync10(session) ? readdirSync4(session) : [];
32873
+ const maxRun = existing.reduce((max, entry) => {
32874
+ const match2 = /^dsi-import-(\d+)$/.exec(entry);
32875
+ return match2 ? Math.max(max, Number(match2[1])) : max;
32876
+ }, 0);
32877
+ return join25(session, `dsi-import-${maxRun + 1}`);
32878
+ }
32879
+ async function startImportRun(projectPath) {
32880
+ await startDebugSessionIn(projectPath);
32881
+ if (!sessionDir) return join25(resolve27(projectPath), ".contentful");
32882
+ const dir = nextImportRunDir(sessionDir);
32883
+ await mkdir9(dir, { recursive: true });
32884
+ return dir;
32885
+ }
32886
+ async function isDebugModeEnabled() {
32887
+ try {
32888
+ return (await readDebugModeSetting()).enabled;
32889
+ } catch {
32890
+ return true;
32891
+ }
32892
+ }
32893
+ function redact(value) {
32894
+ const clone = { ...value };
32895
+ if ("cma_token" in clone) {
32896
+ const raw = clone.cma_token;
32897
+ clone.cma_token = typeof raw === "string" && raw.length > 0 ? `[present, ${raw.length} chars]` : "[not set]";
32898
+ }
32899
+ return clone;
32900
+ }
32901
+ function startDebugRun({
32902
+ flow,
32903
+ step,
32904
+ menuOption,
32905
+ inputs
32906
+ }) {
32907
+ const runId = generateRunId();
32908
+ const startedAt = Date.now();
32909
+ const redactedInputs = redact(inputs);
32910
+ isDebugModeEnabled().then((enabled) => {
32911
+ if (!enabled) return;
32912
+ pendingRun = { flow, step, runId, menuOption, inputs: redactedInputs, startedAt };
32913
+ });
32914
+ }
32915
+ async function finishDebugRun({
32916
+ outputs,
32917
+ status,
32918
+ exitMethod
32919
+ }) {
32920
+ const run = pendingRun;
32921
+ if (!run) return;
32922
+ pendingRun = void 0;
32923
+ const durationMs = Date.now() - run.startedAt;
32924
+ const content = renderMarkdown(run, { outputs: redact(outputs), status, exitMethod, durationMs });
32925
+ const root = currentDebugSessionDir();
32926
+ if (!root) return;
32927
+ const flowSegments = run.flow.split("/");
32928
+ const dir = join25(root, ...flowSegments);
32929
+ await mkdir9(dir, { recursive: true });
32930
+ const filename = nextAttemptFilename(dir, run.menuOption);
32931
+ await writeFile8(join25(dir, filename), content, { mode: 384 });
32932
+ }
32933
+ function nextAttemptFilename(dir, menuOption) {
32934
+ const today = datePrefix();
32935
+ const optionSlug = slugify(menuOption);
32936
+ const existing = existsSync10(dir) ? readdirSync4(dir) : [];
32937
+ const attemptPattern = new RegExp(`^${today}-${optionSlug}-attempt-(\\d+)\\.md$`);
32938
+ const maxAttempt = existing.reduce((max, entry) => {
32939
+ const match2 = attemptPattern.exec(entry);
32940
+ return match2 ? Math.max(max, Number(match2[1])) : max;
32941
+ }, 0);
32942
+ return `${today}-${optionSlug}-attempt-${maxAttempt + 1}.md`;
32943
+ }
32944
+ function renderMarkdown(run, finish) {
32945
+ const stepMatch = /^(\d+)-(.+)$/.exec(run.step);
32946
+ const stepLabel = stepMatch ? `${stepMatch[1]} - ${stepMatch[2]}` : run.step;
32947
+ const flowSlug = run.flow.split("/").join("-");
32948
+ return `# Debug Log
32949
+
32950
+ - Run ID: ${run.runId}
32951
+ - Flow: ${flowSlug}
32952
+ - Step: ${stepLabel}
32953
+ - Menu option: ${run.menuOption}
32954
+ - Date: ${(/* @__PURE__ */ new Date()).toISOString()}
32955
+ - CLI version: ${readPackageVersion()}
32956
+ - Platform: ${process.platform} / Node ${process.version}
32957
+ - Duration on screen: ${finish.durationMs}ms
32958
+ - Status: ${finish.status}
32959
+ - Exit method: ${finish.exitMethod}
32960
+
32961
+ ## Inputs
32962
+ \`\`\`json
32963
+ ${JSON.stringify(run.inputs, null, 2)}
32964
+ \`\`\`
32965
+
32966
+ ## Outputs
32967
+ \`\`\`json
32968
+ ${JSON.stringify(finish.outputs, null, 2)}
32969
+ \`\`\`
32970
+ `;
32971
+ }
32972
+ function handleCrash() {
32973
+ return finishDebugRun({ outputs: {}, status: "error", exitMethod: "crashed" });
32974
+ }
32975
+ var pendingRun, sessionDir;
32976
+ var init_debug_store = __esm({
32977
+ "packages/experience-design-system-cli/src/tui/debug-store.ts"() {
33265
32978
  "use strict";
33266
- init_controller();
32979
+ init_config();
32980
+ init_version();
32981
+ init_debug_mode_store();
32982
+ init_debug_prune();
32983
+ void Promise.all([isDebugModeEnabled(), readBaseDir()]).then(async ([enabled, base]) => {
32984
+ if (!base) return;
32985
+ const retention = await readDebugModeSetting().catch(() => void 0);
32986
+ const pruned = retention ? await pruneExpiredLogs(base, retention.retentionDays).catch(() => void 0) : void 0;
32987
+ if (!enabled) return;
32988
+ const debugDir = join25(startSession(base, { replace: false }), "debug");
32989
+ await mkdir9(debugDir, { recursive: true });
32990
+ if (retention && pruned && pruned.logs + pruned.folders > 0) {
32991
+ await writeFile8(
32992
+ join25(debugDir, `${datePrefix()}-cleanup-${generateRunId()}.md`),
32993
+ `# Debug Log Cleanup
32994
+
32995
+ - Date: ${(/* @__PURE__ */ new Date()).toISOString()}
32996
+ - Retention: ${retention.retentionDays} days
32997
+ - Logs deleted: ${pruned.logs}
32998
+ - Empty folders removed: ${pruned.folders}
32999
+ `,
33000
+ { mode: 384 }
33001
+ );
33002
+ }
33003
+ });
33004
+ process.once("uncaughtException", (err) => {
33005
+ void handleCrash().finally(() => {
33006
+ throw err;
33007
+ });
33008
+ });
33009
+ process.once("unhandledRejection", (reason) => {
33010
+ void handleCrash().finally(() => {
33011
+ throw reason;
33012
+ });
33013
+ });
33014
+ process.once("SIGINT", () => {
33015
+ void handleCrash().finally(() => {
33016
+ process.exit(130);
33017
+ });
33018
+ });
33267
33019
  }
33268
33020
  });
33269
33021
 
@@ -33334,7 +33086,7 @@ var init_help_info = __esm({
33334
33086
  });
33335
33087
 
33336
33088
  // packages/experience-design-system-cli/src/tui/help/PageContainer.tsx
33337
- import { useEffect as useEffect23, useState as useState31 } from "react";
33089
+ import { useEffect as useEffect22, useState as useState31 } from "react";
33338
33090
  import { Box as Box46, Text as Text47, useInput as useInput13 } from "ink";
33339
33091
  import { Fragment as Fragment17, jsx as jsx57, jsxs as jsxs46 } from "react/jsx-runtime";
33340
33092
  function Section({ title, rows }) {
@@ -33348,7 +33100,7 @@ function Section({ title, rows }) {
33348
33100
  }
33349
33101
  function HelpScreen({ onDone }) {
33350
33102
  const [info, setInfo] = useState31();
33351
- useEffect23(() => {
33103
+ useEffect22(() => {
33352
33104
  startDebugRun({ flow: "help", step: "01-help", menuOption: "Help", inputs: {} });
33353
33105
  void readHelpInfo().then(setInfo);
33354
33106
  }, []);
@@ -33769,7 +33521,7 @@ var init_AgentStatusBadge = __esm({
33769
33521
  });
33770
33522
 
33771
33523
  // packages/experience-design-system-cli/src/tui/settings/configuration/agents/AgentDetail.tsx
33772
- import { useEffect as useEffect24, useState as useState33 } from "react";
33524
+ import { useEffect as useEffect23, useState as useState33 } from "react";
33773
33525
  import { Box as Box48, Text as Text50 } from "ink";
33774
33526
  import { jsx as jsx60, jsxs as jsxs48 } from "react/jsx-runtime";
33775
33527
  function StatusHeading() {
@@ -33790,7 +33542,7 @@ function AgentDetail({
33790
33542
  const [testing, setTesting] = useState33(false);
33791
33543
  const [notice, setNotice] = useState33(null);
33792
33544
  const [checks, setChecks] = useState33(void 0);
33793
- useEffect24(() => {
33545
+ useEffect23(() => {
33794
33546
  let active = true;
33795
33547
  setChecks(void 0);
33796
33548
  const timer = setTimeout(() => {
@@ -33882,7 +33634,7 @@ var init_AgentDetail = __esm({
33882
33634
  });
33883
33635
 
33884
33636
  // packages/experience-design-system-cli/src/tui/settings/configuration/agents/AgentsScreen.tsx
33885
- import { useEffect as useEffect25, useRef as useRef16, useState as useState34 } from "react";
33637
+ import { useEffect as useEffect24, useRef as useRef15, useState as useState34 } from "react";
33886
33638
  import { Box as Box49, Text as Text51, useInput as useInput15 } from "ink";
33887
33639
  import { Fragment as Fragment18, jsx as jsx61, jsxs as jsxs49 } from "react/jsx-runtime";
33888
33640
  function AgentsScreen({ onDone }) {
@@ -33893,7 +33645,7 @@ function AgentsScreen({ onDone }) {
33893
33645
  const [saving, setSaving] = useState34(false);
33894
33646
  const [loadError, setLoadError] = useState34(null);
33895
33647
  const [checks, setChecks] = useState34({});
33896
- const visit = useRef16({
33648
+ const visit = useRef15({
33897
33649
  trail: createTrail(),
33898
33650
  before: void 0,
33899
33651
  environment: void 0,
@@ -33906,7 +33658,7 @@ function AgentsScreen({ onDone }) {
33906
33658
  );
33907
33659
  }
33908
33660
  };
33909
- useEffect25(() => {
33661
+ useEffect24(() => {
33910
33662
  readAgentConfig().then((loaded) => {
33911
33663
  setConfig(loaded);
33912
33664
  inspectAll(loaded);
@@ -34132,7 +33884,7 @@ var init_project_store = __esm({
34132
33884
  });
34133
33885
 
34134
33886
  // packages/experience-design-system-cli/src/tui/settings/configuration/project/ProjectScreen.tsx
34135
- import { useEffect as useEffect26, useRef as useRef17, useState as useState35 } from "react";
33887
+ import { useEffect as useEffect25, useRef as useRef16, useState as useState35 } from "react";
34136
33888
  import { Box as Box50, Text as Text52, useInput as useInput16 } from "ink";
34137
33889
  import { Fragment as Fragment19, jsx as jsx62, jsxs as jsxs50 } from "react/jsx-runtime";
34138
33890
  function debugFields(config) {
@@ -34151,14 +33903,14 @@ function ProjectScreen({ onDone }) {
34151
33903
  const [saving, setSaving] = useState35(false);
34152
33904
  const [notice, setNotice] = useState35(null);
34153
33905
  const [loadError, setLoadError] = useState35(null);
34154
- const visit = useRef17({
33906
+ const visit = useRef16({
34155
33907
  trail: createTrail(),
34156
33908
  before: void 0,
34157
33909
  persisted: void 0,
34158
33910
  error: ""
34159
33911
  }).current;
34160
33912
  const scrub = (err) => scrubError(err, [config?.cmaToken ?? ""]);
34161
- useEffect26(() => {
33913
+ useEffect25(() => {
34162
33914
  readCredentials().then((cfg) => {
34163
33915
  setConfig(cfg);
34164
33916
  visit.before = snapshotOf(cfg);
@@ -34345,13 +34097,13 @@ var init_ConfigurationScreen = __esm({
34345
34097
  });
34346
34098
 
34347
34099
  // packages/experience-design-system-cli/src/tui/settings/opt-in-analytics/screen.tsx
34348
- import { useEffect as useEffect27, useState as useState37 } from "react";
34100
+ import { useEffect as useEffect26, useState as useState37 } from "react";
34349
34101
  import { Box as Box52, Text as Text54, useInput as useInput18 } from "ink";
34350
34102
  import { Fragment as Fragment20, jsx as jsx64, jsxs as jsxs52 } from "react/jsx-runtime";
34351
34103
  function OptInAnalyticsScreen({ onDone }) {
34352
34104
  const [loading, setLoading] = useState37(true);
34353
34105
  const [enabled, setEnabled] = useState37(true);
34354
- useEffect27(() => {
34106
+ useEffect26(() => {
34355
34107
  readAnalyticsSetting().then((setting) => {
34356
34108
  setEnabled(setting.enabled);
34357
34109
  setLoading(false);
@@ -34414,7 +34166,7 @@ var init_screen12 = __esm({
34414
34166
  });
34415
34167
 
34416
34168
  // packages/experience-design-system-cli/src/tui/settings/debug-mode/screen.tsx
34417
- import { useEffect as useEffect28, useRef as useRef18, useState as useState38 } from "react";
34169
+ import { useEffect as useEffect27, useRef as useRef17, useState as useState38 } from "react";
34418
34170
  import { Box as Box53, Text as Text55, useInput as useInput19 } from "ink";
34419
34171
  import { Fragment as Fragment21, jsx as jsx65, jsxs as jsxs53 } from "react/jsx-runtime";
34420
34172
  function DebugModeScreen({ onDone }) {
@@ -34424,8 +34176,8 @@ function DebugModeScreen({ onDone }) {
34424
34176
  RETENTION_CHOICES[RETENTION_CHOICES.length - 1]
34425
34177
  );
34426
34178
  const [notice, setNotice] = useState38(null);
34427
- const visit = useRef18({ trail: createTrail(), before: void 0, error: "" }).current;
34428
- useEffect28(() => {
34179
+ const visit = useRef17({ trail: createTrail(), before: void 0, error: "" }).current;
34180
+ useEffect27(() => {
34429
34181
  readDebugModeSetting().then((loaded) => {
34430
34182
  setSetting(loaded);
34431
34183
  setPending(loaded.retentionDays);
@@ -34566,7 +34318,7 @@ var app_exports = {};
34566
34318
  __export(app_exports, {
34567
34319
  runApp: () => runApp
34568
34320
  });
34569
- import { useEffect as useEffect29, useState as useState39 } from "react";
34321
+ import { useEffect as useEffect28, useState as useState39 } from "react";
34570
34322
  import { Fragment as Fragment22, jsx as jsx66 } from "react/jsx-runtime";
34571
34323
  function App({ importOptions, inkClear }) {
34572
34324
  const [screen, setScreen] = useState39("start");
@@ -34600,7 +34352,7 @@ function App({ importOptions, inkClear }) {
34600
34352
  const [flowStart, setFlowStart] = useState39();
34601
34353
  const flow = useFlow(flowStart, { beforeStepChange: inkClear });
34602
34354
  const [importDefaults, setImportDefaults] = useState39();
34603
- useEffect29(() => {
34355
+ useEffect28(() => {
34604
34356
  if (screen !== "import") {
34605
34357
  setImportDefaults(void 0);
34606
34358
  return;
@@ -34673,7 +34425,7 @@ function App({ importOptions, inkClear }) {
34673
34425
  }
34674
34426
  });
34675
34427
  };
34676
- useEffect29(() => {
34428
+ useEffect28(() => {
34677
34429
  if (!tokensOnlyRun || tokensOnly?.status !== "done" || !tokensOnly.result.ok) return;
34678
34430
  const { credentialsSkipped, input, tokens } = tokensOnlyRun;
34679
34431
  const { tokensPath, tokenSessionId, tokenCount } = tokensOnly.result;
@@ -34695,12 +34447,12 @@ function App({ importOptions, inkClear }) {
34695
34447
  }
34696
34448
  });
34697
34449
  }, [tokensOnly, tokensOnlyRun]);
34698
- useEffect29(() => {
34450
+ useEffect28(() => {
34699
34451
  if (!extractionRun || extraction?.status !== "done" || !extraction.result.ok) return;
34700
34452
  setExtractionRun(void 0);
34701
34453
  setScopeRun({ ...extractionRun, extraction: extraction.result.extraction });
34702
34454
  }, [extraction, extractionRun]);
34703
- useEffect29(() => {
34455
+ useEffect28(() => {
34704
34456
  if (!scopeRun || scopeFlow?.status !== "confirmed" || generationInput) return;
34705
34457
  const { extraction: produced, input, generatePromptPath } = scopeRun;
34706
34458
  setGenerationInput({
@@ -34718,7 +34470,7 @@ function App({ importOptions, inkClear }) {
34718
34470
  ...generatePromptPath ? { generatePromptPath } : {}
34719
34471
  });
34720
34472
  }, [scopeFlow, scopeRun, generationInput]);
34721
- useEffect29(() => {
34473
+ useEffect28(() => {
34722
34474
  if (!scopeRun || generation?.status !== "done" || !generation.result.ok) return;
34723
34475
  const { credentialsSkipped, extraction: produced, input, generatePromptPath } = scopeRun;
34724
34476
  inkClear();