@contentful/experience-design-system-cli 2.41.1-dev-build-f74a0859.0 → 2.41.1-dev-build-06624ee7.0

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
@@ -15180,8 +15180,8 @@ function retryAfterMs(response) {
15180
15180
  const value = response.headers?.get("retry-after")?.trim();
15181
15181
  if (!value)
15182
15182
  return void 0;
15183
- const seconds = Number(value);
15184
- const delayMs = Number.isFinite(seconds) ? seconds * 1e3 : Date.parse(value) - Date.now();
15183
+ const seconds2 = Number(value);
15184
+ const delayMs = Number.isFinite(seconds2) ? seconds2 * 1e3 : Date.parse(value) - Date.now();
15185
15185
  if (!Number.isFinite(delayMs) || delayMs < 0 || delayMs > MAX_RETRY_AFTER_MS)
15186
15186
  return void 0;
15187
15187
  return Math.round(delayMs);
@@ -18053,10 +18053,10 @@ var init_read_candidate_files = __esm({
18053
18053
  async function selectCompositionPromptFiles(components, sourceFiles) {
18054
18054
  const allFiles = await readCandidateFiles(components, sourceFiles);
18055
18055
  const selectedCandidates = selectCandidateFiles(allFiles).map((c2) => ({ path: c2.path, content: c2.content }));
18056
- const capped = capCandidatesToPromptBudget(selectedCandidates);
18057
- const promptFiles = capped.kept;
18056
+ const capped3 = capCandidatesToPromptBudget(selectedCandidates);
18057
+ const promptFiles = capped3.kept;
18058
18058
  const runtimeFiles = allFiles.map((c2) => ({ path: c2.path, content: c2.content }));
18059
- const droppedWarning = capped.dropped.length > 0 ? `composition \u2014 ${capped.dropped.length} candidate file(s) omitted from the agent prompt to fit the context budget; resolution runs on the ${promptFiles.length} highest-value files.` : void 0;
18059
+ const droppedWarning = capped3.dropped.length > 0 ? `composition \u2014 ${capped3.dropped.length} candidate file(s) omitted from the agent prompt to fit the context budget; resolution runs on the ${promptFiles.length} highest-value files.` : void 0;
18060
18060
  return { promptFiles, runtimeFiles, droppedWarning };
18061
18061
  }
18062
18062
  var init_select_composition_prompt_files = __esm({
@@ -19497,6 +19497,7 @@ __export(debug_store_exports, {
19497
19497
  currentDebugSessionDir: () => currentDebugSessionDir,
19498
19498
  currentSessionDir: () => currentSessionDir,
19499
19499
  finishDebugRun: () => finishDebugRun,
19500
+ setDebugRunProgress: () => setDebugRunProgress,
19500
19501
  startDebugRun: () => startDebugRun,
19501
19502
  startDebugSessionIn: () => startDebugSessionIn,
19502
19503
  startImportRun: () => startImportRun
@@ -19592,11 +19593,15 @@ function startDebugRun({
19592
19593
  const runId = generateRunId();
19593
19594
  const startedAt = Date.now();
19594
19595
  const redactedInputs = redact(inputs);
19595
- isDebugModeEnabled().then((enabled) => {
19596
- if (!enabled) return;
19597
- pendingRun = { flow, step, runId, menuOption, inputs: redactedInputs, startedAt };
19596
+ const run = { flow, step, runId, menuOption, inputs: redactedInputs, startedAt };
19597
+ pendingRun = run;
19598
+ void isDebugModeEnabled().then((enabled) => {
19599
+ if (!enabled && pendingRun === run) pendingRun = void 0;
19598
19600
  });
19599
19601
  }
19602
+ function setDebugRunProgress(outputs) {
19603
+ if (pendingRun) pendingRun.progress = outputs;
19604
+ }
19600
19605
  async function finishDebugRun({
19601
19606
  outputs,
19602
19607
  status,
@@ -19605,9 +19610,10 @@ async function finishDebugRun({
19605
19610
  const run = pendingRun;
19606
19611
  if (!run) return;
19607
19612
  pendingRun = void 0;
19613
+ if (!await isDebugModeEnabled()) return;
19608
19614
  const durationMs = Date.now() - run.startedAt;
19609
19615
  const log = {
19610
- flow: run.flow,
19616
+ flow: logFolder(run.flow, run.step),
19611
19617
  menuOption: run.menuOption,
19612
19618
  content: renderMarkdown(run, { outputs: redact(outputs), status, exitMethod, durationMs })
19613
19619
  };
@@ -19618,6 +19624,9 @@ async function finishDebugRun({
19618
19624
  }
19619
19625
  await writeLog(root, log);
19620
19626
  }
19627
+ function logFolder(flow, step) {
19628
+ return flow.startsWith("import/") && /^\d+-/.test(step) ? `import/${step}` : flow;
19629
+ }
19621
19630
  async function writeLog(root, log) {
19622
19631
  const dir = join19(root, ...log.flow.split("/"));
19623
19632
  await mkdir7(dir, { recursive: true });
@@ -19674,7 +19683,7 @@ ${JSON.stringify(finish.outputs, null, 2)}
19674
19683
  `;
19675
19684
  }
19676
19685
  function handleCrash() {
19677
- return finishDebugRun({ outputs: {}, status: "error", exitMethod: "crashed" });
19686
+ return finishDebugRun({ outputs: pendingRun?.progress ?? {}, status: "error", exitMethod: "crashed" });
19678
19687
  }
19679
19688
  var pendingRun, sessionDir, WAITING_LIMIT, waiting;
19680
19689
  var init_debug_store = __esm({
@@ -19718,11 +19727,17 @@ var init_debug_store = __esm({
19718
19727
  throw reason;
19719
19728
  });
19720
19729
  });
19721
- process.once("SIGINT", () => {
19722
- void handleCrash().finally(() => {
19723
- process.exit(130);
19730
+ for (const [signal, exitCode] of [
19731
+ ["SIGINT", 130],
19732
+ ["SIGTERM", 143],
19733
+ ["SIGHUP", 129]
19734
+ ]) {
19735
+ process.once(signal, () => {
19736
+ void handleCrash().finally(() => {
19737
+ process.exit(exitCode);
19738
+ });
19724
19739
  });
19725
- });
19740
+ }
19726
19741
  }
19727
19742
  });
19728
19743
 
@@ -20126,8 +20141,8 @@ function progressPercent(progress) {
20126
20141
  }
20127
20142
  function formatElapsed(totalSeconds) {
20128
20143
  const minutes = Math.floor(totalSeconds / 60);
20129
- const seconds = totalSeconds % 60;
20130
- return minutes > 0 ? `${minutes}m ${seconds}s` : `${seconds}s`;
20144
+ const seconds2 = totalSeconds % 60;
20145
+ return minutes > 0 ? `${minutes}m ${seconds2}s` : `${seconds2}s`;
20131
20146
  }
20132
20147
  var init_logic4 = __esm({
20133
20148
  "packages/experience-design-system-cli/src/tui/import/shared/running-step/logic.ts"() {
@@ -20157,12 +20172,12 @@ var init_theme2 = __esm({
20157
20172
  // packages/experience-design-system-cli/src/tui/import/shared/running-step/use-elapsed.ts
20158
20173
  import { useEffect as useEffect3, useState as useState3 } from "react";
20159
20174
  function useElapsed() {
20160
- const [seconds, setSeconds] = useState3(0);
20175
+ const [seconds2, setSeconds] = useState3(0);
20161
20176
  useEffect3(() => {
20162
20177
  const timer = setInterval(() => setSeconds((current) => current + 1), 1e3);
20163
20178
  return () => clearInterval(timer);
20164
20179
  }, []);
20165
- return formatElapsed(seconds);
20180
+ return formatElapsed(seconds2);
20166
20181
  }
20167
20182
  var init_use_elapsed = __esm({
20168
20183
  "packages/experience-design-system-cli/src/tui/import/shared/running-step/use-elapsed.ts"() {
@@ -20925,7 +20940,7 @@ function FieldForm({
20925
20940
  onSkip,
20926
20941
  skipLabel: skipLabel2 = "skip",
20927
20942
  onQuit,
20928
- quitLabel = "back (unsaved changes are lost)",
20943
+ quitLabel = "back without saving",
20929
20944
  actions = [],
20930
20945
  notice,
20931
20946
  busy = false,
@@ -20988,7 +21003,7 @@ function FieldForm({
20988
21003
  }
20989
21004
  if (isLastField) {
20990
21005
  setEditing(false);
20991
- setActive(0);
21006
+ onSave();
20992
21007
  return;
20993
21008
  }
20994
21009
  const next = fields2[active + 1];
@@ -21052,7 +21067,7 @@ function FieldForm({
21052
21067
  hints: editing ? [
21053
21068
  { keys: "type", label: "edit" },
21054
21069
  { keys: "\u2190/\u2192", label: "move cursor" },
21055
- { keys: "\u23CE", label: enterAdvances && !isLastField ? "next" : "done" },
21070
+ { keys: "\u23CE", label: enterAdvances ? isLastField ? saveLabel : "next" : "done" },
21056
21071
  { keys: "Ctrl+D", label: "clear" },
21057
21072
  { keys: "Esc", label: "cancel edit" }
21058
21073
  ] : [
@@ -21077,6 +21092,45 @@ var init_FieldForm = __esm({
21077
21092
  }
21078
21093
  });
21079
21094
 
21095
+ // packages/experience-design-system-cli/src/tui/shared/debug-trail.ts
21096
+ import { existsSync as existsSync10 } from "node:fs";
21097
+ function diffSnapshots(before, after) {
21098
+ const names = [.../* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(after)])];
21099
+ const changed_fields = names.filter((name) => before[name] !== after[name]);
21100
+ return { changed: changed_fields.length > 0, changed_fields };
21101
+ }
21102
+ function createTrail(limit = DEFAULT_TRAIL_LIMIT) {
21103
+ const actions = [];
21104
+ return {
21105
+ record(action) {
21106
+ actions.push(action);
21107
+ if (actions.length > limit) actions.shift();
21108
+ },
21109
+ entries: () => [...actions]
21110
+ };
21111
+ }
21112
+ function scrubError(error, secrets) {
21113
+ let message = error instanceof Error ? error.message : String(error);
21114
+ for (const secret of secrets) {
21115
+ if (secret.length < MIN_SECRET_LENGTH) continue;
21116
+ for (const form of /* @__PURE__ */ new Set([secret, encodeURIComponent(secret)])) message = message.split(form).join("[redacted]");
21117
+ }
21118
+ return message;
21119
+ }
21120
+ function describeSettingsFile() {
21121
+ const path5 = configFilePath2();
21122
+ return { path: path5, eds_home_set: Boolean(process.env["EDS_HOME"]), exists: existsSync10(path5) };
21123
+ }
21124
+ var DEFAULT_TRAIL_LIMIT, MIN_SECRET_LENGTH;
21125
+ var init_debug_trail = __esm({
21126
+ "packages/experience-design-system-cli/src/tui/shared/debug-trail.ts"() {
21127
+ "use strict";
21128
+ init_config();
21129
+ DEFAULT_TRAIL_LIMIT = 30;
21130
+ MIN_SECRET_LENGTH = 6;
21131
+ }
21132
+ });
21133
+
21080
21134
  // packages/experience-design-system-cli/src/tui/import/steps/04-credentials/logic.ts
21081
21135
  function credentialsPurpose(tokensOnly) {
21082
21136
  const use = tokensOnly ? "We use it to push your design tokens" : "We use it to check what components already exist and to push your import";
@@ -21090,17 +21144,42 @@ function normalize(values) {
21090
21144
  host: toConfiguredHost2(values.host) ?? DEFAULT_CONFIGURED_HOST
21091
21145
  };
21092
21146
  }
21093
- function missingField(values) {
21094
- return values.spaceId === "" || values.environmentId === "" || values.cmaToken === "";
21147
+ function missingFields(values) {
21148
+ return ["spaceId", "environmentId", "cmaToken"].filter((field) => values[field] === "");
21095
21149
  }
21096
21150
  function isUnchanged(current, initial) {
21097
21151
  return FIELDS.every((field) => current[field] === initial[field]);
21098
21152
  }
21153
+ function rejectedAttempt(reason, credentials) {
21154
+ return { host: credentials.host, reason: scrubError(reason, [credentials.cmaToken]) };
21155
+ }
21156
+ function credentialsLog(credentials) {
21157
+ return {
21158
+ space_id: credentials.spaceId,
21159
+ environment_id: credentials.environmentId,
21160
+ host: credentials.host,
21161
+ cma_token: credentials.cmaToken
21162
+ };
21163
+ }
21164
+ function credentialsOutputs({
21165
+ outcome,
21166
+ credentials,
21167
+ initial,
21168
+ attempts
21169
+ }) {
21170
+ return {
21171
+ outcome,
21172
+ ...credentialsLog(credentials),
21173
+ changed_fields: diffSnapshots(initial, credentials).changed_fields,
21174
+ rejected_attempts: attempts
21175
+ };
21176
+ }
21099
21177
  var FIELDS;
21100
21178
  var init_logic8 = __esm({
21101
21179
  "packages/experience-design-system-cli/src/tui/import/steps/04-credentials/logic.ts"() {
21102
21180
  "use strict";
21103
21181
  init_src3();
21182
+ init_debug_trail();
21104
21183
  FIELDS = ["spaceId", "environmentId", "cmaToken", "host"];
21105
21184
  }
21106
21185
  });
@@ -21153,10 +21232,11 @@ var init_validate4 = __esm({
21153
21232
  });
21154
21233
 
21155
21234
  // packages/experience-design-system-cli/src/tui/import/steps/04-credentials/screen.tsx
21156
- import { useRef as useRef5, useState as useState9 } from "react";
21235
+ import { useEffect as useEffect8, useRef as useRef5, useState as useState9 } from "react";
21157
21236
  import { Box as Box14, Text as Text14, useInput as useInput11 } from "ink";
21158
21237
  import { Fragment as Fragment2, jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
21159
21238
  function CredentialsScreen({
21239
+ mode,
21160
21240
  onDone,
21161
21241
  onBack,
21162
21242
  initial = {},
@@ -21179,17 +21259,64 @@ function CredentialsScreen({
21179
21259
  const [focus, setFocus] = useState9(0);
21180
21260
  const [active, setActive] = useState9(0);
21181
21261
  const [beforeEdit, setBeforeEdit] = useState9(initialValues);
21262
+ const visit = useRef5({ attempts: [], lastReason: "" }).current;
21263
+ useEffect8(() => {
21264
+ startDebugRun({
21265
+ flow: "import/credentials",
21266
+ step: "04-credentials",
21267
+ menuOption: "Credentials",
21268
+ inputs: { import_mode: mode, prefilled, ...credentialsLog(initialValues) }
21269
+ });
21270
+ }, []);
21271
+ const reject = (attempt, text) => {
21272
+ if (visit.attempts.length < MAX_LOGGED_ATTEMPTS2) visit.attempts.push(attempt);
21273
+ visit.lastReason = attempt.reason;
21274
+ setNotice({ kind: "error", text });
21275
+ };
21276
+ const leave = () => {
21277
+ void finishDebugRun({
21278
+ outputs: {
21279
+ ...credentialsOutputs({
21280
+ outcome: "back",
21281
+ credentials: normalize(values),
21282
+ initial: initialValues,
21283
+ attempts: visit.attempts
21284
+ }),
21285
+ ...notice ? { error: visit.lastReason } : {}
21286
+ },
21287
+ status: notice ? "error" : "success",
21288
+ exitMethod: "discarded"
21289
+ });
21290
+ onBack();
21291
+ };
21182
21292
  const submit = async () => {
21183
21293
  const credentials = normalize(values);
21184
- if (missingField(credentials)) {
21185
- setNotice({ kind: "error", text: "Space ID, environment and CMA token are all required." });
21294
+ const missing = missingFields(credentials);
21295
+ if (missing.length > 0) {
21296
+ reject(
21297
+ rejectedAttempt(`Missing required fields: ${missing.join(", ")}`, credentials),
21298
+ "Space ID, environment and CMA token are all required."
21299
+ );
21186
21300
  return;
21187
21301
  }
21188
21302
  setValidating(true);
21189
21303
  const result = await validate3(credentials);
21190
21304
  setValidating(false);
21191
- if (result.ok) onDone({ skipped: false, credentials });
21192
- else setNotice({ kind: "error", text: result.error });
21305
+ if (!result.ok) {
21306
+ reject(rejectedAttempt(result.error, credentials), result.error);
21307
+ return;
21308
+ }
21309
+ void finishDebugRun({
21310
+ outputs: credentialsOutputs({
21311
+ outcome: "validated",
21312
+ credentials,
21313
+ initial: initialValues,
21314
+ attempts: visit.attempts
21315
+ }),
21316
+ status: "success",
21317
+ exitMethod: "saved"
21318
+ });
21319
+ onDone({ skipped: false, credentials });
21193
21320
  };
21194
21321
  const choose = (choice) => {
21195
21322
  if (choice === "continue") void submit();
@@ -21198,7 +21325,7 @@ function CredentialsScreen({
21198
21325
  setBeforeEdit(values);
21199
21326
  setActive(0);
21200
21327
  setEditing(true);
21201
- } else onBack();
21328
+ } else leave();
21202
21329
  };
21203
21330
  const stopEditing = () => {
21204
21331
  setEditing(false);
@@ -21208,7 +21335,7 @@ function CredentialsScreen({
21208
21335
  if (validating) return;
21209
21336
  if (editing) {
21210
21337
  if (key.escape) {
21211
- if (!prefilled) onBack();
21338
+ if (!prefilled) leave();
21212
21339
  else {
21213
21340
  setValues(beforeEdit);
21214
21341
  setNotice(null);
@@ -21314,11 +21441,12 @@ function CredentialsScreen({
21314
21441
  ] })
21315
21442
  ] });
21316
21443
  }
21317
- var FIELDS2, MENU;
21444
+ var FIELDS2, MENU, MAX_LOGGED_ATTEMPTS2;
21318
21445
  var init_screen5 = __esm({
21319
21446
  "packages/experience-design-system-cli/src/tui/import/steps/04-credentials/screen.tsx"() {
21320
21447
  "use strict";
21321
21448
  init_theme();
21449
+ init_debug_store();
21322
21450
  init_FieldForm();
21323
21451
  init_ClearableTextInput();
21324
21452
  init_ControlHints();
@@ -21335,10 +21463,52 @@ var init_screen5 = __esm({
21335
21463
  { choice: "continue", label: "Continue", description: "Check the credentials and go on" },
21336
21464
  { choice: "edit", label: "Edit", description: "Change the credentials" }
21337
21465
  ];
21466
+ MAX_LOGGED_ATTEMPTS2 = 10;
21338
21467
  }
21339
21468
  });
21340
21469
 
21341
21470
  // packages/experience-design-system-cli/src/tui/import/steps/06-extraction/logic.ts
21471
+ function extractionLogInputs(input) {
21472
+ const { credentials } = input;
21473
+ return {
21474
+ project_path: input.projectPath,
21475
+ out_dir: input.outDir ?? "",
21476
+ files_to_scan: input.filePaths.length,
21477
+ raw_tokens_path: input.rawTokensPath,
21478
+ agent: input.agent,
21479
+ agent_model: input.agentModel ?? "",
21480
+ prompt_overrides: input.promptOverrides,
21481
+ cache: !input.noCache,
21482
+ has_credentials: credentials !== null,
21483
+ space_id: credentials?.spaceId ?? "",
21484
+ environment_id: credentials?.environmentId ?? "",
21485
+ host: credentials?.host ?? "",
21486
+ cma_token: credentials?.cmaToken ?? ""
21487
+ };
21488
+ }
21489
+ function extractionLogOutputs(result, progress, cmaToken) {
21490
+ const last = progress ? { final_progress: progress } : {};
21491
+ if (!result.ok) {
21492
+ return {
21493
+ outputs: { result: "failed", failed_step: result.step, error: scrubError(result.message, [cmaToken]), ...last },
21494
+ status: "error"
21495
+ };
21496
+ }
21497
+ const { extraction } = result;
21498
+ return {
21499
+ outputs: {
21500
+ result: "done",
21501
+ session_id: extraction.sessionId,
21502
+ out_dir: extraction.outDir,
21503
+ tokens_path: extraction.tokensPath,
21504
+ token_count: extraction.tokenCount,
21505
+ existing_entities_status: extraction.existingEntitiesStatus,
21506
+ composition_phase: extraction.compositionPhase,
21507
+ ...last
21508
+ },
21509
+ status: "success"
21510
+ };
21511
+ }
21342
21512
  function initialProgress(input) {
21343
21513
  return {
21344
21514
  scan: null,
@@ -21422,6 +21592,7 @@ var init_logic9 = __esm({
21422
21592
  "packages/experience-design-system-cli/src/tui/import/steps/06-extraction/logic.ts"() {
21423
21593
  "use strict";
21424
21594
  init_src3();
21595
+ init_debug_trail();
21425
21596
  }
21426
21597
  });
21427
21598
 
@@ -21509,7 +21680,7 @@ var init_load = __esm({
21509
21680
  });
21510
21681
 
21511
21682
  // packages/experience-design-system-cli/src/tui/import/steps/05-token-review/screen.tsx
21512
- import { useMemo as useMemo2, useState as useState10 } from "react";
21683
+ import { useEffect as useEffect9, useMemo as useMemo2, useState as useState10 } from "react";
21513
21684
  import { Box as Box15, Text as Text15, useInput as useInput12 } from "ink";
21514
21685
  import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
21515
21686
  function TokenReviewScreen({ tokensPath, onContinue, onQuit }) {
@@ -21517,12 +21688,31 @@ function TokenReviewScreen({ tokensPath, onContinue, onQuit }) {
21517
21688
  const rows = loaded.ok ? loaded.rows : [];
21518
21689
  const columns = useTerminalWidth();
21519
21690
  const [selected, setSelected] = useState10(0);
21691
+ useEffect9(() => {
21692
+ startDebugRun({
21693
+ flow: "import/token-review",
21694
+ step: "05-token-review",
21695
+ menuOption: "Token review",
21696
+ inputs: { import_mode: "tokens", tokens_path: tokensPath }
21697
+ });
21698
+ }, []);
21699
+ const finish = (outcome) => {
21700
+ void finishDebugRun({
21701
+ outputs: { outcome, ...loaded.ok ? { tokens: rows.length } : { load_error: loaded.message } },
21702
+ status: loaded.ok ? "success" : "error",
21703
+ exitMethod: outcome === "continued" ? "saved" : "discarded"
21704
+ });
21705
+ };
21520
21706
  const move = (to) => setSelected(Math.max(0, Math.min(to, rows.length - 1)));
21521
21707
  const { start, end } = computeColumnWindow(rows.length, selected, VISIBLE_ROWS);
21522
21708
  useInput12((_input, key) => {
21523
- if (key.return) onContinue();
21524
- else if (key.escape) onQuit();
21525
- else if (key.upArrow) move(selected - 1);
21709
+ if (key.return) {
21710
+ finish("continued");
21711
+ onContinue();
21712
+ } else if (key.escape) {
21713
+ finish("back");
21714
+ onQuit();
21715
+ } else if (key.upArrow) move(selected - 1);
21526
21716
  else if (key.downArrow) move(selected + 1);
21527
21717
  else if (key.pageUp) move(selected - VISIBLE_ROWS);
21528
21718
  else if (key.pageDown) move(selected + VISIBLE_ROWS);
@@ -21586,6 +21776,7 @@ var init_screen7 = __esm({
21586
21776
  "packages/experience-design-system-cli/src/tui/import/steps/05-token-review/screen.tsx"() {
21587
21777
  "use strict";
21588
21778
  init_theme();
21779
+ init_debug_store();
21589
21780
  init_ControlHints();
21590
21781
  init_StepHeader();
21591
21782
  init_use_terminal_width();
@@ -21611,7 +21802,7 @@ var init_steps = __esm({
21611
21802
  });
21612
21803
 
21613
21804
  // packages/experience-design-system-cli/src/tui/import/steps/06-extraction/find-skill-path.ts
21614
- import { existsSync as existsSync10 } from "node:fs";
21805
+ import { existsSync as existsSync11 } from "node:fs";
21615
21806
  import { dirname as dirname16, join as join20, resolve as resolve22 } from "node:path";
21616
21807
  import { fileURLToPath as fileURLToPath4 } from "node:url";
21617
21808
  function findSkillPath(fileName) {
@@ -21619,7 +21810,7 @@ function findSkillPath(fileName) {
21619
21810
  let dir = thisDir;
21620
21811
  for (; ; ) {
21621
21812
  const candidate = join20(dir, "skills", fileName);
21622
- if (existsSync10(candidate)) return candidate;
21813
+ if (existsSync11(candidate)) return candidate;
21623
21814
  const parent = resolve22(dir, "..");
21624
21815
  if (parent === dir) {
21625
21816
  throw new Error(`skill file not found (looked for skills/${fileName} from ${thisDir})`);
@@ -21883,11 +22074,11 @@ var init_run = __esm({
21883
22074
  });
21884
22075
 
21885
22076
  // packages/experience-design-system-cli/src/tui/import/steps/06-extraction/use-extraction.ts
21886
- import { useEffect as useEffect8, useRef as useRef6, useState as useState11 } from "react";
22077
+ import { useEffect as useEffect10, useRef as useRef6, useState as useState11 } from "react";
21887
22078
  function useExtraction(input) {
21888
22079
  const [state2, setState] = useState11();
21889
22080
  const current = useRef6();
21890
- useEffect8(() => {
22081
+ useEffect10(() => {
21891
22082
  current.current = input;
21892
22083
  if (!input) {
21893
22084
  setState(void 0);
@@ -21900,10 +22091,23 @@ function useExtraction(input) {
21900
22091
  hasRawTokens: input.rawTokensPath !== ""
21901
22092
  })
21902
22093
  });
22094
+ let lastProgress;
22095
+ startDebugRun({
22096
+ flow: "import/extraction",
22097
+ step: "06-extraction",
22098
+ menuOption: "Extraction",
22099
+ inputs: extractionLogInputs(input)
22100
+ });
21903
22101
  void runExtraction(input, (progress) => {
22102
+ lastProgress = progress;
21904
22103
  if (current.current === input) setState({ status: "running", progress });
21905
22104
  }).then((result) => {
21906
- if (current.current === input) setState({ status: "done", result });
22105
+ if (current.current !== input) return;
22106
+ void finishDebugRun({
22107
+ ...extractionLogOutputs(result, lastProgress, input.credentials?.cmaToken ?? ""),
22108
+ exitMethod: result.ok ? "saved" : "discarded"
22109
+ });
22110
+ setState({ status: "done", result });
21907
22111
  });
21908
22112
  return () => {
21909
22113
  if (current.current === input) current.current = void 0;
@@ -21914,6 +22118,7 @@ function useExtraction(input) {
21914
22118
  var init_use_extraction = __esm({
21915
22119
  "packages/experience-design-system-cli/src/tui/import/steps/06-extraction/use-extraction.ts"() {
21916
22120
  "use strict";
22121
+ init_debug_store();
21917
22122
  init_logic9();
21918
22123
  init_run();
21919
22124
  }
@@ -21958,11 +22163,11 @@ var init_run_tokens_only = __esm({
21958
22163
  });
21959
22164
 
21960
22165
  // packages/experience-design-system-cli/src/tui/import/steps/06-extraction/use-tokens-only.ts
21961
- import { useEffect as useEffect9, useRef as useRef7, useState as useState12 } from "react";
22166
+ import { useEffect as useEffect11, useRef as useRef7, useState as useState12 } from "react";
21962
22167
  function useTokensOnly(input) {
21963
22168
  const [state2, setState] = useState12();
21964
22169
  const current = useRef7();
21965
- useEffect9(() => {
22170
+ useEffect11(() => {
21966
22171
  current.current = input;
21967
22172
  if (!input) {
21968
22173
  setState(void 0);
@@ -21985,6 +22190,39 @@ var init_use_tokens_only = __esm({
21985
22190
  }
21986
22191
  });
21987
22192
 
22193
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/log.ts
22194
+ function scopeGateLogInputs(components, tokenCount) {
22195
+ const ai = { accepted: 0, rejected: 0, failed: 0, none: 0 };
22196
+ for (const component of components) ai[component.aiDecision ?? "none"] += 1;
22197
+ return {
22198
+ components_found: components.length,
22199
+ ai_suggestions: ai,
22200
+ needs_review: components.filter((component) => component.needsReview === true).length,
22201
+ tokens: tokenCount
22202
+ };
22203
+ }
22204
+ function scopeGateLogOutputs(components, decisions) {
22205
+ const suggested = new Map(components.map((component) => [component.name, component.aiDecision]));
22206
+ return {
22207
+ outcome: "continued",
22208
+ accepted: new Set(decisions.accepted).size,
22209
+ rejected: new Set(decisions.rejected).size,
22210
+ accepted_although_ai_rejected: capped(decisions.accepted.filter((name) => suggested.get(name) === "rejected")),
22211
+ not_accepted_although_ai_accepted: capped(decisions.rejected.filter((name) => suggested.get(name) === "accepted"))
22212
+ };
22213
+ }
22214
+ var MAX_NAMES, capped;
22215
+ var init_log = __esm({
22216
+ "packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/log.ts"() {
22217
+ "use strict";
22218
+ MAX_NAMES = 20;
22219
+ capped = (names) => {
22220
+ const unique = [...new Set(names)];
22221
+ return { count: unique.length, names: unique.slice(0, MAX_NAMES) };
22222
+ };
22223
+ }
22224
+ });
22225
+
21988
22226
  // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/windowed-panel.tsx
21989
22227
  import { Box as Box16, Text as Text16 } from "ink";
21990
22228
  import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
@@ -23239,7 +23477,7 @@ var init_useImmediateInput = __esm({
23239
23477
 
23240
23478
  // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/hooks/use-terminal-size.ts
23241
23479
  import { useStdout as useStdout2 } from "ink";
23242
- import { useEffect as useEffect10, useState as useState13 } from "react";
23480
+ import { useEffect as useEffect12, useState as useState13 } from "react";
23243
23481
  function readTerminalSize(stdout) {
23244
23482
  return {
23245
23483
  columns: stdout?.columns ?? 80,
@@ -23249,7 +23487,7 @@ function readTerminalSize(stdout) {
23249
23487
  function useTerminalSize() {
23250
23488
  const { stdout } = useStdout2();
23251
23489
  const [size, setSize] = useState13(() => readTerminalSize(stdout));
23252
- useEffect10(() => {
23490
+ useEffect12(() => {
23253
23491
  const updateSize = () => setSize(readTerminalSize(stdout));
23254
23492
  stdout?.on("resize", updateSize);
23255
23493
  updateSize();
@@ -24251,7 +24489,7 @@ var init_state = __esm({
24251
24489
  });
24252
24490
 
24253
24491
  // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/use-scope-gate.ts
24254
- import { useEffect as useEffect11, useMemo as useMemo3, useRef as useRef9, useState as useState16 } from "react";
24492
+ import { useEffect as useEffect13, useMemo as useMemo3, useRef as useRef9, useState as useState16 } from "react";
24255
24493
  function useScopeGate({ components, tokenCount, tokensWidth, onConfirm, onQuit }) {
24256
24494
  const { columns: totalWidth, rows: terminalRows } = useTerminalSize();
24257
24495
  const columnPlan = useMemo3(
@@ -24298,7 +24536,7 @@ function useScopeGate({ components, tokenCount, tokensWidth, onConfirm, onQuit }
24298
24536
  return seed;
24299
24537
  });
24300
24538
  const seededGroupsRef = useRef9(closures.size > 0 || cycleParticipants.size > 0);
24301
- useEffect11(() => {
24539
+ useEffect13(() => {
24302
24540
  if (seededGroupsRef.current) return;
24303
24541
  if (closures.size === 0 && cycleParticipants.size === 0) return;
24304
24542
  seededGroupsRef.current = true;
@@ -24389,7 +24627,7 @@ function useScopeGate({ components, tokenCount, tokensWidth, onConfirm, onQuit }
24389
24627
  entryCount: 0
24390
24628
  });
24391
24629
  const panelLayout = useMemo3(() => computePanelLayout(visibleCount), [visibleCount]);
24392
- useEffect11(() => {
24630
+ useEffect13(() => {
24393
24631
  setNav((prev) => {
24394
24632
  const maxIdx = Math.max(0, visibleRows.length - 1);
24395
24633
  const nextCursor = Math.min(prev.cursor, maxIdx);
@@ -24734,27 +24972,59 @@ var init_use_scope_gate = __esm({
24734
24972
  });
24735
24973
 
24736
24974
  // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/screen.tsx
24737
- import { useMemo as useMemo4 } from "react";
24975
+ import { useEffect as useEffect14, useMemo as useMemo4 } from "react";
24738
24976
  import { Box as Box25, Text as Text26 } from "ink";
24739
24977
  import { Fragment as Fragment5, jsx as jsx29, jsxs as jsxs25 } from "react/jsx-runtime";
24740
24978
  function ScopeGateScreen(props) {
24741
- if (props.components.length === 0) {
24742
- return /* @__PURE__ */ jsx29(Box25, { paddingX: 2, paddingY: 1, children: /* @__PURE__ */ jsx29(Text26, { color: PALETTE.error, children: "Error: no components found for this session \u2014 please re-run analyze extract." }) });
24743
- }
24979
+ if (props.components.length === 0) return /* @__PURE__ */ jsx29(NoComponents, {});
24744
24980
  return /* @__PURE__ */ jsx29(ScopeGateView, { ...props });
24745
24981
  }
24982
+ function NoComponents() {
24983
+ useEffect14(() => {
24984
+ startDebugRun({
24985
+ flow: "import/scope-gate",
24986
+ step: "07-scope-gate",
24987
+ menuOption: "Scope gate",
24988
+ inputs: scopeGateLogInputs([], 0)
24989
+ });
24990
+ void finishDebugRun({
24991
+ outputs: { outcome: "nothing to decide", error: "No components were found for this session." },
24992
+ status: "error",
24993
+ exitMethod: "discarded"
24994
+ });
24995
+ }, []);
24996
+ return /* @__PURE__ */ jsx29(Box25, { paddingX: 2, paddingY: 1, children: /* @__PURE__ */ jsx29(Text26, { color: PALETTE.error, children: "Error: no components found for this session \u2014 please re-run analyze extract." }) });
24997
+ }
24746
24998
  function ScopeGateView({ components, tokensPath, onConfirm, onQuit }) {
24747
24999
  const tokens = useMemo4(() => {
24748
25000
  const loaded = tokensPath ? loadTokenRows(tokensPath) : void 0;
24749
25001
  return loaded?.ok ? loaded.rows : [];
24750
25002
  }, [tokensPath]);
24751
25003
  const longest = useMemo4(() => longestEntries(tokens), [tokens]);
25004
+ useEffect14(() => {
25005
+ startDebugRun({
25006
+ flow: "import/scope-gate",
25007
+ step: "07-scope-gate",
25008
+ menuOption: "Scope gate",
25009
+ inputs: scopeGateLogInputs(components, tokens.length)
25010
+ });
25011
+ }, []);
24752
25012
  const gate = useScopeGate({
24753
25013
  components,
24754
25014
  tokenCount: tokens.length,
24755
25015
  tokensWidth: longest.path + longest.value + 10,
24756
- onConfirm,
24757
- onQuit
25016
+ onConfirm: (decisions) => {
25017
+ void finishDebugRun({
25018
+ outputs: scopeGateLogOutputs(components, decisions),
25019
+ status: "success",
25020
+ exitMethod: "saved"
25021
+ });
25022
+ onConfirm(decisions);
25023
+ },
25024
+ onQuit: () => {
25025
+ void finishDebugRun({ outputs: { outcome: "quit" }, status: "success", exitMethod: "discarded" });
25026
+ onQuit();
25027
+ }
24758
25028
  });
24759
25029
  const { search, graph, columnPlan, panelLayout, counters } = gate;
24760
25030
  if (gate.showHelp) {
@@ -24854,7 +25124,9 @@ var HELP_SECTIONS;
24854
25124
  var init_screen8 = __esm({
24855
25125
  "packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/screen.tsx"() {
24856
25126
  "use strict";
25127
+ init_debug_store();
24857
25128
  init_StepHeader();
25129
+ init_log();
24858
25130
  init_tokens_column();
24859
25131
  init_load();
24860
25132
  init_logic10();
@@ -24962,13 +25234,27 @@ var init_load2 = __esm({
24962
25234
  });
24963
25235
 
24964
25236
  // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/use-scope-gate-flow.ts
24965
- import { useEffect as useEffect12, useMemo as useMemo5, useRef as useRef10, useState as useState17 } from "react";
25237
+ import { useEffect as useEffect15, useMemo as useMemo5, useRef as useRef10, useState as useState17 } from "react";
24966
25238
  function useScopeGateFlow(input, deps = realDeps3) {
24967
25239
  const sessionId = input?.sessionId;
24968
25240
  const loaded = useMemo5(() => sessionId ? deps.load(sessionId) : void 0, [sessionId]);
24969
25241
  const cacheCheck = useRef10(void 0);
24970
25242
  const [confirmed, setConfirmed] = useState17();
24971
- useEffect12(() => {
25243
+ useEffect15(() => {
25244
+ if (!sessionId || !loaded || loaded.ok) return;
25245
+ startDebugRun({
25246
+ flow: "import/scope-gate",
25247
+ step: "07-scope-gate",
25248
+ menuOption: "Scope gate",
25249
+ inputs: { session_id: sessionId }
25250
+ });
25251
+ void finishDebugRun({
25252
+ outputs: { outcome: "could not load the components", error: loaded.message },
25253
+ status: "error",
25254
+ exitMethod: "discarded"
25255
+ });
25256
+ }, [sessionId, loaded]);
25257
+ useEffect15(() => {
24972
25258
  if (!input || !loaded?.ok || cacheCheck.current) return;
24973
25259
  cacheCheck.current = deps.checkCache(input.cache);
24974
25260
  }, [input, loaded]);
@@ -24982,6 +25268,7 @@ var realDeps3;
24982
25268
  var init_use_scope_gate_flow = __esm({
24983
25269
  "packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/use-scope-gate-flow.ts"() {
24984
25270
  "use strict";
25271
+ init_debug_store();
24985
25272
  init_cache_check();
24986
25273
  init_load2();
24987
25274
  realDeps3 = { load: loadScopeGate, checkCache: checkGenerationCache };
@@ -24989,6 +25276,41 @@ var init_use_scope_gate_flow = __esm({
24989
25276
  });
24990
25277
 
24991
25278
  // packages/experience-design-system-cli/src/tui/import/steps/08-generation/logic.ts
25279
+ function generationLogInputs(input) {
25280
+ return {
25281
+ session_id: input.sessionId,
25282
+ accepted: input.decisions.accepted.length,
25283
+ rejected: input.decisions.rejected.length,
25284
+ tokens_path: input.tokensPath,
25285
+ token_session_id: input.tokenSessionId,
25286
+ existing_entities_path: input.existingEntitiesPath,
25287
+ agent: input.agent,
25288
+ agent_model: input.agentModel ?? "",
25289
+ prompt_overrides: input.promptOverrides,
25290
+ generate_prompt_path: input.generatePromptPath ?? "",
25291
+ cache: !input.noCache,
25292
+ has_tokens: input.hasTokens
25293
+ };
25294
+ }
25295
+ function generationLogOutputs(result, progress) {
25296
+ const last = progress ? { final_progress: progress } : {};
25297
+ if (!result.ok) {
25298
+ return { outputs: { result: "failed", failed_step: result.step, error: result.message, ...last }, status: "error" };
25299
+ }
25300
+ const { generation } = result;
25301
+ return {
25302
+ outputs: generation.route === "review" ? {
25303
+ result: "done",
25304
+ route: generation.route,
25305
+ session_id: generation.sessionId,
25306
+ accepted: generation.acceptedCount,
25307
+ generated: generation.generatedCount,
25308
+ map_tokens_eligible: generation.mapTokensEligible,
25309
+ ...last
25310
+ } : { result: "done", route: generation.route, accepted: generation.acceptedCount, ...last },
25311
+ status: "success"
25312
+ };
25313
+ }
24992
25314
  function initialProgress2() {
24993
25315
  return { components: null, mapTokens: "idle", mapTokensEligible: null };
24994
25316
  }
@@ -25239,21 +25561,34 @@ var init_run2 = __esm({
25239
25561
  });
25240
25562
 
25241
25563
  // packages/experience-design-system-cli/src/tui/import/steps/08-generation/use-generation.ts
25242
- import { useEffect as useEffect13, useRef as useRef11, useState as useState18 } from "react";
25564
+ import { useEffect as useEffect16, useRef as useRef11, useState as useState18 } from "react";
25243
25565
  function useGeneration(input) {
25244
25566
  const [state2, setState] = useState18();
25245
25567
  const current = useRef11();
25246
- useEffect13(() => {
25568
+ useEffect16(() => {
25247
25569
  current.current = input;
25248
25570
  if (!input) {
25249
25571
  setState(void 0);
25250
25572
  return;
25251
25573
  }
25252
25574
  setState({ status: "running", progress: initialProgress2() });
25575
+ let lastProgress;
25576
+ startDebugRun({
25577
+ flow: "import/generation",
25578
+ step: "08-generation",
25579
+ menuOption: "Generation",
25580
+ inputs: generationLogInputs(input)
25581
+ });
25253
25582
  void runGeneration(input, (progress) => {
25583
+ lastProgress = progress;
25254
25584
  if (current.current === input) setState({ status: "running", progress });
25255
25585
  }).then((result) => {
25256
- if (current.current === input) setState({ status: "done", result });
25586
+ if (current.current !== input) return;
25587
+ void finishDebugRun({
25588
+ ...generationLogOutputs(result, lastProgress),
25589
+ exitMethod: result.ok ? "saved" : "discarded"
25590
+ });
25591
+ setState({ status: "done", result });
25257
25592
  });
25258
25593
  return () => {
25259
25594
  if (current.current === input) current.current = void 0;
@@ -25264,6 +25599,7 @@ function useGeneration(input) {
25264
25599
  var init_use_generation = __esm({
25265
25600
  "packages/experience-design-system-cli/src/tui/import/steps/08-generation/use-generation.ts"() {
25266
25601
  "use strict";
25602
+ init_debug_store();
25267
25603
  init_logic11();
25268
25604
  init_run2();
25269
25605
  }
@@ -26230,7 +26566,7 @@ var init_scroll_offset = __esm({
26230
26566
  });
26231
26567
 
26232
26568
  // packages/experience-design-system-cli/src/tui/import/steps/09-review/components/FieldEditor.tsx
26233
- import React13, { useEffect as useEffect14, useLayoutEffect as useLayoutEffect2, useState as useState19 } from "react";
26569
+ import React13, { useEffect as useEffect17, useLayoutEffect as useLayoutEffect2, useState as useState19 } from "react";
26234
26570
  import figures6 from "figures";
26235
26571
  import { Box as Box26, measureElement, Text as Text27 } from "ink";
26236
26572
  import { Fragment as Fragment6, jsx as jsx32, jsxs as jsxs26 } from "react/jsx-runtime";
@@ -27757,7 +28093,7 @@ function FieldEditor({
27757
28093
  }
27758
28094
  return Math.max(start + 1, end2);
27759
28095
  };
27760
- useEffect14(() => {
28096
+ useEffect17(() => {
27761
28097
  if (focusLevel === "field" || selectedRowIdx < 0) return;
27762
28098
  setListScrollStart((previous) => {
27763
28099
  if (initialFocusTarget && !initialFocusScrollApplied.current) {
@@ -29152,7 +29488,7 @@ var init_FinalizeDialog = __esm({
29152
29488
  });
29153
29489
 
29154
29490
  // packages/experience-design-system-cli/src/tui/import/steps/09-review/use-finalize-preview.ts
29155
- import { useEffect as useEffect15, useRef as useRef12, useState as useState20 } from "react";
29491
+ import { useEffect as useEffect18, useRef as useRef12, useState as useState20 } from "react";
29156
29492
  function useReviewFinalizePreview({
29157
29493
  components,
29158
29494
  ...options
@@ -29169,7 +29505,7 @@ function useFinalizePreview(opts) {
29169
29505
  const [scrollOffset, setScrollOffset] = useState20(0);
29170
29506
  const generationRef = useRef12(0);
29171
29507
  const acceptedKey = [...acceptedKeys].sort().join("\0");
29172
- useEffect15(() => {
29508
+ useEffect18(() => {
29173
29509
  if (!open) {
29174
29510
  setStatus("idle");
29175
29511
  setRemoved([]);
@@ -29221,7 +29557,7 @@ var init_use_finalize_preview = __esm({
29221
29557
  });
29222
29558
 
29223
29559
  // packages/experience-design-system-cli/src/tui/import/steps/09-review/use-review-session.ts
29224
- import { useCallback as useCallback2, useEffect as useEffect16, useRef as useRef13, useState as useState21 } from "react";
29560
+ import { useCallback as useCallback2, useEffect as useEffect19, useRef as useRef13, useState as useState21 } from "react";
29225
29561
  function useReviewSession({
29226
29562
  loadSession,
29227
29563
  tokensPath,
@@ -29240,7 +29576,7 @@ function useReviewSession({
29240
29576
  }));
29241
29577
  return { result, catalog };
29242
29578
  }, [loadSession, tokensPath]);
29243
- useEffect16(() => {
29579
+ useEffect19(() => {
29244
29580
  let disposed = false;
29245
29581
  void (async () => {
29246
29582
  try {
@@ -29293,7 +29629,7 @@ function useReviewSession({
29293
29629
  function useReviewMetadata({ components, selectedIdx, extractSessionId }) {
29294
29630
  const [reviewMetadata, setReviewMetadata] = useState21(null);
29295
29631
  const [componentRationale, setComponentRationale] = useState21(null);
29296
- useEffect16(() => {
29632
+ useEffect19(() => {
29297
29633
  const current = components[selectedIdx];
29298
29634
  if (!current) {
29299
29635
  setReviewMetadata(null);
@@ -29322,10 +29658,16 @@ function useReviewMetadata({ components, selectedIdx, extractSessionId }) {
29322
29658
  }, [components, extractSessionId, selectedIdx]);
29323
29659
  return { reviewMetadata, componentRationale };
29324
29660
  }
29325
- function useReviewHistory({ loading, components, createSnapshot, applySnapshot }) {
29661
+ function useReviewHistory({
29662
+ loading,
29663
+ components,
29664
+ createSnapshot,
29665
+ applySnapshot,
29666
+ onAction
29667
+ }) {
29326
29668
  const historyRef = useRef13(null);
29327
29669
  const historySeededRef = useRef13(false);
29328
- useEffect16(() => {
29670
+ useEffect19(() => {
29329
29671
  if (loading || historySeededRef.current) return;
29330
29672
  historySeededRef.current = true;
29331
29673
  historyRef.current = createHistoryStack(createSnapshot(components));
@@ -29333,14 +29675,19 @@ function useReviewHistory({ loading, components, createSnapshot, applySnapshot }
29333
29675
  const pushHistorySnapshot = (entries, label) => {
29334
29676
  if (!historyRef.current) return;
29335
29677
  historyRef.current.push(createSnapshot(entries), label);
29678
+ onAction?.(label);
29336
29679
  };
29337
29680
  const handleUndo = () => {
29338
29681
  const snapshot = historyRef.current?.undo();
29339
- if (snapshot) applySnapshot(snapshot);
29682
+ if (!snapshot) return;
29683
+ applySnapshot(snapshot);
29684
+ onAction?.("undo");
29340
29685
  };
29341
29686
  const handleRedo = () => {
29342
29687
  const snapshot = historyRef.current?.redo();
29343
- if (snapshot) applySnapshot(snapshot);
29688
+ if (!snapshot) return;
29689
+ applySnapshot(snapshot);
29690
+ onAction?.("redo");
29344
29691
  };
29345
29692
  const resetHistory = (snapshot) => {
29346
29693
  historyRef.current?.reset(snapshot);
@@ -29407,7 +29754,7 @@ var init_token_suggestions = __esm({
29407
29754
  });
29408
29755
 
29409
29756
  // packages/experience-design-system-cli/src/tui/import/steps/09-review/use-review-editor.ts
29410
- import { useEffect as useEffect17, useRef as useRef14, useState as useState22 } from "react";
29757
+ import { useEffect as useEffect20, useRef as useRef14, useState as useState22 } from "react";
29411
29758
  function parseReviewEntry(draftValue) {
29412
29759
  const parsed = JSON.parse(draftValue);
29413
29760
  const keys = Object.keys(parsed);
@@ -29441,7 +29788,7 @@ function useReviewEditor({
29441
29788
  const [tokenReviewEditSelection, setTokenReviewEditSelection] = useState22(/* @__PURE__ */ new Set());
29442
29789
  const tokenReviewSuggestedRef = useRef14(/* @__PURE__ */ new Map());
29443
29790
  const pendingGRef = useRef14(false);
29444
- useEffect17(() => {
29791
+ useEffect20(() => {
29445
29792
  setTokenReviewRow(0);
29446
29793
  setTokenReviewEditing(false);
29447
29794
  setTokenReviewEditCursor(0);
@@ -29923,7 +30270,7 @@ var init_preview_annotations = __esm({
29923
30270
  });
29924
30271
 
29925
30272
  // packages/experience-design-system-cli/src/tui/import/steps/09-review/use-live-preview.ts
29926
- import { useCallback as useCallback3, useEffect as useEffect18, useRef as useRef15, useState as useState24 } from "react";
30273
+ import { useCallback as useCallback3, useEffect as useEffect21, useRef as useRef15, useState as useState24 } from "react";
29927
30274
  function useLivePreview(opts) {
29928
30275
  const debounceMs = opts.debounceMs ?? DEFAULT_DEBOUNCE_MS;
29929
30276
  const [status, setStatus] = useState24("idle");
@@ -29933,14 +30280,14 @@ function useLivePreview(opts) {
29933
30280
  const latestRef = useRef15(0);
29934
30281
  const inflightRef = useRef15(0);
29935
30282
  const optsRef = useRef15(opts);
29936
- useEffect18(() => {
30283
+ useEffect21(() => {
29937
30284
  optsRef.current = opts;
29938
30285
  });
29939
30286
  const disabledRef = useRef15(disabled);
29940
- useEffect18(() => {
30287
+ useEffect21(() => {
29941
30288
  disabledRef.current = disabled;
29942
30289
  }, [disabled]);
29943
- useEffect18(() => {
30290
+ useEffect21(() => {
29944
30291
  return () => {
29945
30292
  if (timerRef.current) {
29946
30293
  clearTimeout(timerRef.current);
@@ -30021,7 +30368,7 @@ var init_use_live_preview = __esm({
30021
30368
  });
30022
30369
 
30023
30370
  // packages/experience-design-system-cli/src/tui/import/steps/09-review/use-review-preview.ts
30024
- import { useCallback as useCallback4, useEffect as useEffect19, useState as useState25 } from "react";
30371
+ import { useCallback as useCallback4, useEffect as useEffect22, useState as useState25 } from "react";
30025
30372
  function useReviewPreview({
30026
30373
  components,
30027
30374
  loading,
@@ -30063,13 +30410,13 @@ function useReviewPreview({
30063
30410
  deleteAllComponents
30064
30411
  });
30065
30412
  const [spinnerTick, setSpinnerTick] = useState25(0);
30066
- useEffect19(() => {
30413
+ useEffect22(() => {
30067
30414
  if (livePreviewHook.status !== "running") return;
30068
30415
  const id = setInterval(() => setSpinnerTick((tick) => tick + 1), 80);
30069
30416
  return () => clearInterval(id);
30070
30417
  }, [livePreviewHook.status]);
30071
30418
  const livePreviewSpinner = SPINNER_FRAMES[spinnerTick % SPINNER_FRAMES.length];
30072
- useEffect19(() => {
30419
+ useEffect22(() => {
30073
30420
  if (loading) return;
30074
30421
  if (!livePreview) return;
30075
30422
  if (components.length === 0) return;
@@ -30087,6 +30434,127 @@ var init_use_review_preview = __esm({
30087
30434
  }
30088
30435
  });
30089
30436
 
30437
+ // packages/experience-design-system-cli/src/tui/import/steps/09-review/review-log.ts
30438
+ function reviewInputs(components) {
30439
+ return { components: components.length, by_status: countStatuses(components) };
30440
+ }
30441
+ function openReviewTrail(components, now) {
30442
+ return {
30443
+ startedAt: now,
30444
+ start: new Map(components.map((component) => [component.key, component.status])),
30445
+ actions: [],
30446
+ kinds: {}
30447
+ };
30448
+ }
30449
+ function recordReviewAction(trail, label) {
30450
+ const kind = label.split(":")[0] ?? label;
30451
+ trail.kinds[kind] = (trail.kinds[kind] ?? 0) + 1;
30452
+ if (trail.actions.length < MAX_ACTIONS) trail.actions.push(label);
30453
+ }
30454
+ function render(trail, components, now, outcome) {
30455
+ const acceptedByUser = [];
30456
+ const rejectedByUser = [];
30457
+ for (const { key, status } of components) {
30458
+ const was = trail.start.get(key);
30459
+ if (was === status) continue;
30460
+ if (status === "accepted") acceptedByUser.push(key);
30461
+ if (status === "rejected") rejectedByUser.push(key);
30462
+ }
30463
+ const total = Object.values(trail.kinds).reduce((sum, count) => sum + count, 0);
30464
+ return {
30465
+ outcome,
30466
+ seconds: Math.round((now - trail.startedAt) / 100) / 10,
30467
+ edits: { total, by_kind: trail.kinds, in_order: trail.actions },
30468
+ now: countStatuses(components),
30469
+ accepted_by_user: capped2(acceptedByUser),
30470
+ rejected_by_user: capped2(rejectedByUser)
30471
+ };
30472
+ }
30473
+ function reviewProgress(trail, components, now) {
30474
+ return render(trail, components, now, "interrupted");
30475
+ }
30476
+ function reviewFinish(trail, components, now, final) {
30477
+ const outcome = final ? `finalized: ${final.accepted} accepted, ${final.rejected} rejected, ${final.unresolved} unresolved` : "left the review without finishing";
30478
+ return {
30479
+ outputs: render(trail, components, now, outcome),
30480
+ status: "success",
30481
+ exitMethod: final ? "saved" : "discarded"
30482
+ };
30483
+ }
30484
+ var REVIEW_RUN, MAX_ACTIONS, MAX_NAMES2, countStatuses, capped2;
30485
+ var init_review_log = __esm({
30486
+ "packages/experience-design-system-cli/src/tui/import/steps/09-review/review-log.ts"() {
30487
+ "use strict";
30488
+ REVIEW_RUN = { flow: "import/review", step: "09-review", menuOption: "Review" };
30489
+ MAX_ACTIONS = 30;
30490
+ MAX_NAMES2 = 20;
30491
+ countStatuses = (components) => {
30492
+ const counts = {};
30493
+ for (const { status } of components) counts[status] = (counts[status] ?? 0) + 1;
30494
+ return counts;
30495
+ };
30496
+ capped2 = (keys) => ({
30497
+ count: keys.length,
30498
+ keys: keys.slice(0, MAX_NAMES2)
30499
+ });
30500
+ }
30501
+ });
30502
+
30503
+ // packages/experience-design-system-cli/src/tui/import/steps/09-review/use-review-log.ts
30504
+ import { useEffect as useEffect23, useRef as useRef16 } from "react";
30505
+ function useReviewLog({
30506
+ loading,
30507
+ loadError,
30508
+ components
30509
+ }) {
30510
+ const trail = useRef16(void 0);
30511
+ const started = useRef16(false);
30512
+ const latest = useRef16(components);
30513
+ latest.current = components;
30514
+ useEffect23(() => {
30515
+ if (loading || started.current) return;
30516
+ started.current = true;
30517
+ startDebugRun({ ...REVIEW_RUN, inputs: reviewInputs(components) });
30518
+ if (loadError) {
30519
+ void finishDebugRun({
30520
+ outputs: { outcome: "could not load the components", error: loadError },
30521
+ status: "error",
30522
+ exitMethod: "discarded"
30523
+ });
30524
+ return;
30525
+ }
30526
+ trail.current = openReviewTrail(components, Date.now());
30527
+ setDebugRunProgress(reviewProgress(trail.current, components, Date.now()));
30528
+ }, [loading, loadError, components]);
30529
+ useEffect23(
30530
+ () => () => {
30531
+ const open = trail.current;
30532
+ trail.current = void 0;
30533
+ if (open) void finishDebugRun(reviewFinish(open, latest.current, Date.now(), void 0));
30534
+ },
30535
+ []
30536
+ );
30537
+ return {
30538
+ record: (label) => {
30539
+ if (!trail.current) return;
30540
+ recordReviewAction(trail.current, label);
30541
+ setDebugRunProgress(reviewProgress(trail.current, latest.current, Date.now()));
30542
+ },
30543
+ finish: (counts) => {
30544
+ const open = trail.current;
30545
+ trail.current = void 0;
30546
+ if (open) void finishDebugRun(reviewFinish(open, latest.current, Date.now(), counts));
30547
+ }
30548
+ };
30549
+ }
30550
+ var init_use_review_log = __esm({
30551
+ "packages/experience-design-system-cli/src/tui/import/steps/09-review/use-review-log.ts"() {
30552
+ "use strict";
30553
+ init_debug_store();
30554
+ init_review_log();
30555
+ }
30556
+ });
30557
+
30090
30558
  // packages/experience-design-system-cli/src/tui/import/steps/09-review/components/LivePreviewSummary.tsx
30091
30559
  import { Box as Box37, Text as Text39 } from "ink";
30092
30560
  import { jsx as jsx47, jsxs as jsxs37 } from "react/jsx-runtime";
@@ -30126,7 +30594,7 @@ var init_LivePreviewSummary = __esm({
30126
30594
  });
30127
30595
 
30128
30596
  // packages/experience-design-system-cli/src/tui/import/steps/09-review/generate-review-step.tsx
30129
- import { useCallback as useCallback5, useEffect as useEffect20, useMemo as useMemo6, useRef as useRef16, useState as useState26 } from "react";
30597
+ import { useCallback as useCallback5, useEffect as useEffect24, useMemo as useMemo6, useRef as useRef17, useState as useState26 } from "react";
30130
30598
  import figures8 from "figures";
30131
30599
  import { Box as Box38, Text as Text40 } from "ink";
30132
30600
  import { Fragment as Fragment14, jsx as jsx48, jsxs as jsxs38 } from "react/jsx-runtime";
@@ -30323,6 +30791,7 @@ function GenerateReviewStepView({
30323
30791
  tokensPath,
30324
30792
  onExtraLoaded: setLoadedSlotCycles
30325
30793
  });
30794
+ const reviewLog = useReviewLog({ loading, loadError, components });
30326
30795
  const [nav, setNav] = useState26({
30327
30796
  cursorRowIdx: 0,
30328
30797
  sidebarScrollOffset: 0
@@ -30340,7 +30809,7 @@ function GenerateReviewStepView({
30340
30809
  setFinalizeError
30341
30810
  } = reviewSurface;
30342
30811
  const [removedBannerCollapsed, setRemovedBannerCollapsed] = useState26(false);
30343
- const removedBannerDefaultedRef = useRef16(false);
30812
+ const removedBannerDefaultedRef = useRef17(false);
30344
30813
  const [cyclePanelScroll, setCyclePanelScroll] = useState26(0);
30345
30814
  const [cyclesCursor, setCyclesCursor] = useState26(0);
30346
30815
  const cyclePanel = useOverlayPanel({
@@ -30360,7 +30829,7 @@ function GenerateReviewStepView({
30360
30829
  const [breakCursor, setBreakCursor] = useState26(0);
30361
30830
  const [breakConfirm, setBreakConfirm] = useState26(false);
30362
30831
  const [expandedGroups, setExpandedGroups] = useState26(/* @__PURE__ */ new Set());
30363
- const seededGroupsRef = useRef16(false);
30832
+ const seededGroupsRef = useRef17(false);
30364
30833
  const {
30365
30834
  searchOpen,
30366
30835
  setSearchOpen,
@@ -30384,7 +30853,7 @@ function GenerateReviewStepView({
30384
30853
  const [pendingEditorFocus, setPendingEditorFocus] = useState26(null);
30385
30854
  const [autoRejected, setAutoRejected] = useState26([]);
30386
30855
  const [undoSnapshot, setUndoSnapshot] = useState26(null);
30387
- const autoRejectFiredRef = useRef16(false);
30856
+ const autoRejectFiredRef = useRef17(false);
30388
30857
  const [showReloadDialog, setShowReloadDialog] = useState26(false);
30389
30858
  const acceptedCountForPreview = components.filter((c2) => c2.status === "accepted").length;
30390
30859
  const { previewAnnotations, removedComponents, livePreviewHook, livePreviewSpinner } = useReviewPreview({
@@ -30416,7 +30885,10 @@ function GenerateReviewStepView({
30416
30885
  cmaToken,
30417
30886
  host,
30418
30887
  components,
30419
- onFinalize
30888
+ onFinalize: (accepted, rejected, unresolved) => {
30889
+ reviewLog.finish({ accepted, rejected, unresolved });
30890
+ onFinalize(accepted, rejected, unresolved);
30891
+ }
30420
30892
  });
30421
30893
  const recomputeCycles = (currentComponents) => {
30422
30894
  try {
@@ -30447,7 +30919,7 @@ function GenerateReviewStepView({
30447
30919
  [components]
30448
30920
  );
30449
30921
  const closures = useMemo6(() => computeAllClosures(componentGraph), [componentGraph]);
30450
- useEffect20(() => {
30922
+ useEffect24(() => {
30451
30923
  if (seededGroupsRef.current) return;
30452
30924
  if (closures.size === 0 && slotCycles.length === 0) return;
30453
30925
  seededGroupsRef.current = true;
@@ -30474,7 +30946,7 @@ function GenerateReviewStepView({
30474
30946
  suggestedBreak: cycle.edges.length > 0 ? suggestCycleBreakEdge2(cycle, cycleView.pushBlocking) : null
30475
30947
  }));
30476
30948
  }, [slotCycles, cycleView]);
30477
- useEffect20(() => {
30949
+ useEffect24(() => {
30478
30950
  const decision = computeAutoRejectDecision({
30479
30951
  loading,
30480
30952
  autoRejectFired: autoRejectFiredRef.current,
@@ -30515,10 +30987,11 @@ function GenerateReviewStepView({
30515
30987
  autoRejected,
30516
30988
  undoSnapshot
30517
30989
  }),
30518
- applySnapshot: applyHistorySnapshot
30990
+ applySnapshot: applyHistorySnapshot,
30991
+ onAction: reviewLog.record
30519
30992
  });
30520
- const autoRejectPushedRef = useRef16(false);
30521
- useEffect20(() => {
30993
+ const autoRejectPushedRef = useRef17(false);
30994
+ useEffect24(() => {
30522
30995
  if (loading) return;
30523
30996
  if (!historySeededRef.current) return;
30524
30997
  if (!autoRejectFiredRef.current) return;
@@ -30602,7 +31075,7 @@ function GenerateReviewStepView({
30602
31075
  const panelHeight = leftPanelHeight + 2;
30603
31076
  const panelContentHeight = Math.max(1, panelHeight - 3);
30604
31077
  const cycleViewportHeight = Math.max(1, panelHeight - 4);
30605
- useEffect20(() => {
31078
+ useEffect24(() => {
30606
31079
  if (selectableRowPositions.length === 0) return;
30607
31080
  const cursorInRange = selectableRowPositions.includes(cursorRowIdx);
30608
31081
  const maxScroll = Math.max(0, visibleRowsMemo.length - visibleCount);
@@ -31431,6 +31904,7 @@ var init_generate_review_step = __esm({
31431
31904
  init_ReviewDialogs();
31432
31905
  init_review_input();
31433
31906
  init_use_review_preview();
31907
+ init_use_review_log();
31434
31908
  init_LivePreviewSummary();
31435
31909
  HELP_SECTIONS2 = [
31436
31910
  {
@@ -31684,10 +32158,10 @@ var init_path_utils = __esm({
31684
32158
  });
31685
32159
 
31686
32160
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/use-blinking-cursor.ts
31687
- import { useEffect as useEffect21, useState as useState27 } from "react";
32161
+ import { useEffect as useEffect25, useState as useState27 } from "react";
31688
32162
  function useBlinkingCursor() {
31689
32163
  const [visible, setVisible] = useState27(true);
31690
- useEffect21(() => {
32164
+ useEffect25(() => {
31691
32165
  const interval = setInterval(() => setVisible((current) => !current), 500);
31692
32166
  return () => clearInterval(interval);
31693
32167
  }, []);
@@ -31824,12 +32298,12 @@ var init_produced = __esm({
31824
32298
  });
31825
32299
 
31826
32300
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/use-timed-spinner.tsx
31827
- import { useEffect as useEffect22, useState as useState29 } from "react";
32301
+ import { useEffect as useEffect26, useState as useState29 } from "react";
31828
32302
  import { Spinner as Spinner2 } from "@inkjs/ui";
31829
32303
  import { jsx as jsx53 } from "react/jsx-runtime";
31830
32304
  function useTimedSpinner() {
31831
32305
  const [elapsedSeconds, setElapsedSeconds] = useState29(0);
31832
- useEffect22(() => {
32306
+ useEffect26(() => {
31833
32307
  const timer = setInterval(() => setElapsedSeconds((current) => current + 1), 1e3);
31834
32308
  return () => {
31835
32309
  clearInterval(timer);
@@ -32098,7 +32572,7 @@ var init_preview_confirmation_input = __esm({
32098
32572
  });
32099
32573
 
32100
32574
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/screens/WizardPreviewStep.tsx
32101
- import { useEffect as useEffect23, useState as useState30, useMemo as useMemo7 } from "react";
32575
+ import { useEffect as useEffect27, useState as useState30, useMemo as useMemo7 } from "react";
32102
32576
  import { Box as Box44, Text as Text46 } from "ink";
32103
32577
  import { Fragment as Fragment16, jsx as jsx55, jsxs as jsxs44 } from "react/jsx-runtime";
32104
32578
  function buildPreviewSummaryLines(preview) {
@@ -32308,7 +32782,7 @@ function WizardPreviewStep({
32308
32782
  const activeLines = diffExpanded ? diffLines : summaryLines;
32309
32783
  const maxScroll = Math.max(0, activeLines.length - viewportHeight);
32310
32784
  const boundedScrollOffset = Math.min(scrollOffset, maxScroll);
32311
- useEffect23(() => {
32785
+ useEffect27(() => {
32312
32786
  setScrollOffset((previous) => Math.min(previous, maxScroll));
32313
32787
  }, [maxScroll]);
32314
32788
  useImmediateInput((input, key) => {
@@ -32418,6 +32892,205 @@ var init_run_teaser = __esm({
32418
32892
  }
32419
32893
  });
32420
32894
 
32895
+ // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/flow-log.ts
32896
+ function previewSummary(preview) {
32897
+ const counts = (group) => ({
32898
+ new: group.new.length,
32899
+ changed: group.changed.length,
32900
+ removed: group.removed.length
32901
+ });
32902
+ return {
32903
+ components: counts(preview.components),
32904
+ tokens: counts(preview.tokens),
32905
+ breaking_components: preview.components.changed.filter(
32906
+ (entry) => entry.changeClassification?.classification === "breaking"
32907
+ ).length
32908
+ };
32909
+ }
32910
+ function pushSummary(result, state2) {
32911
+ const failures = result.failures ?? [];
32912
+ return {
32913
+ component_types: result.componentTypes,
32914
+ design_tokens: result.designTokens,
32915
+ ...result.summary ? { summary: result.summary } : {},
32916
+ ...failures.length > 0 ? {
32917
+ failure_count: failures.length,
32918
+ failures: failures.slice(0, MAX_LOGGED).map((failure) => ({
32919
+ entity_type: failure.entityType,
32920
+ entity_id: failure.entityId,
32921
+ message: scrub(failure.message, state2)
32922
+ }))
32923
+ } : {}
32924
+ };
32925
+ }
32926
+ function flowContext(state2) {
32927
+ return {
32928
+ agent: state2.agent,
32929
+ space_id: state2.spaceId,
32930
+ environment_id: state2.environmentId,
32931
+ host: state2.host,
32932
+ credentials_skipped: state2.credentialsSkipped,
32933
+ components_generated: state2.generatedCount,
32934
+ components_accepted: state2.generatedAcceptedCount,
32935
+ tokens: state2.tokenCount,
32936
+ cma_token: state2.cmaToken
32937
+ };
32938
+ }
32939
+ function arrive(trail, state2) {
32940
+ const next = { ...trail, at: state2.step };
32941
+ if (state2.step === "error") {
32942
+ next.failure = { step: state2.errorStep, message: scrub(state2.errorMessage, state2) };
32943
+ }
32944
+ if (state2.step === "preview-validation-error") {
32945
+ next.validation = {
32946
+ count: state2.previewValidationErrors.length,
32947
+ errors: state2.previewValidationErrors.slice(0, MAX_LOGGED).map((error) => ({
32948
+ component: error.componentName,
32949
+ path: error.path,
32950
+ message: scrub(error.message, state2)
32951
+ })),
32952
+ missing_names: state2.previewValidationMissingNames.slice(0, MAX_LOGGED * 2)
32953
+ };
32954
+ }
32955
+ return next;
32956
+ }
32957
+ function openTrail(state2, now) {
32958
+ return arrive({ startedAt: now, stageStartedAt: now, at: state2.step, stages: [] }, state2);
32959
+ }
32960
+ function advance(trail, from, to, now) {
32961
+ const next = { ...trail, stages: [...trail.stages], stageStartedAt: now };
32962
+ const failed = to.step === "error" || to.step === "preview-validation-error" || from.step === "pushing" && pushHasFailures(to.pushResult);
32963
+ if (WORK.includes(from.step)) {
32964
+ next.stages.push(`${LABELS[from.step]}: ${failed ? "failed" : "ok"} (${seconds(now - trail.stageStartedAt)}s)`);
32965
+ }
32966
+ if (from.step === "previewing" && to.serverPreview) next.preview = previewSummary(to.serverPreview);
32967
+ if (from.step === "pushing") {
32968
+ next.push = pushSummary(to.pushResult, to);
32969
+ next.pushFailed = pushHasFailures(to.pushResult);
32970
+ }
32971
+ if (from.step === "printing" && !failed) next.saved = { path: to.componentsPath, run_id: to.lastRunId };
32972
+ return arrive(next, to);
32973
+ }
32974
+ function render2(trail, now, outcome) {
32975
+ return {
32976
+ outcome,
32977
+ total_seconds: seconds(now - trail.startedAt),
32978
+ stages: trail.stages,
32979
+ ...trail.preview ? { preview: trail.preview } : {},
32980
+ ...trail.push ? { push: trail.push } : {},
32981
+ ...trail.saved ? { saved: trail.saved } : {},
32982
+ ...trail.failure ? { error: trail.failure } : {},
32983
+ ...trail.validation ? { preview_validation: trail.validation } : {}
32984
+ };
32985
+ }
32986
+ function flowProgress(trail, now) {
32987
+ return render2(trail, now, `interrupted at ${LABELS[trail.at]}`);
32988
+ }
32989
+ function flowFinish(trail, final, now) {
32990
+ if (!final) {
32991
+ const midWork = WORK.includes(trail.at);
32992
+ const outcome2 = `left the import ${midWork ? "while" : "at"} ${LABELS[trail.at]}${midWork ? " was running" : ""}`;
32993
+ return { outputs: render2(trail, now, outcome2), status: midWork ? "error" : "success", exitMethod: "discarded" };
32994
+ }
32995
+ if (final.step === "final-review") {
32996
+ return {
32997
+ outputs: render2(trail, now, "went back to edit the definitions"),
32998
+ status: "success",
32999
+ exitMethod: "discarded"
33000
+ };
33001
+ }
33002
+ let outcome;
33003
+ let failed = true;
33004
+ if (trail.validation) {
33005
+ outcome = `blocked by ${String(trail.validation["count"])} preview validation error(s)`;
33006
+ } else if (trail.failure) {
33007
+ outcome = `failed at ${trail.failure.step}: ${trail.failure.message.slice(0, MAX_OUTCOME)}`;
33008
+ } else if (trail.pushFailed) {
33009
+ outcome = "pushed, but some entities failed";
33010
+ } else {
33011
+ failed = false;
33012
+ outcome = final.credentialsSkipped ? "saved without pushing (credentials skipped)" : "published";
33013
+ }
33014
+ return {
33015
+ outputs: render2(trail, now, outcome),
33016
+ status: failed ? "error" : "success",
33017
+ exitMethod: failed ? "discarded" : "saved"
33018
+ };
33019
+ }
33020
+ var FLOW_RUN, LABELS, WORK, FINISHED, MAX_LOGGED, MAX_OUTCOME, scrub, seconds, pushHasFailures, isFlowFinished;
33021
+ var init_flow_log = __esm({
33022
+ "packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/flow-log.ts"() {
33023
+ "use strict";
33024
+ init_debug_trail();
33025
+ FLOW_RUN = { flow: "import/publish", step: "10-publish", menuOption: "Publish" };
33026
+ LABELS = {
33027
+ "final-review": "Final review",
33028
+ "path-prompt": "Save path",
33029
+ printing: "Save files",
33030
+ previewing: "Preview",
33031
+ "preview-gate": "Preview confirmation",
33032
+ pushing: "Push",
33033
+ "print-gate": "Files saved",
33034
+ done: "Done",
33035
+ error: "Error",
33036
+ "preview-validation-error": "Preview validation"
33037
+ };
33038
+ WORK = ["printing", "previewing", "pushing"];
33039
+ FINISHED = ["done", "error", "preview-validation-error", "final-review"];
33040
+ MAX_LOGGED = 10;
33041
+ MAX_OUTCOME = 200;
33042
+ scrub = (text, state2) => scrubError(text, [state2.cmaToken]);
33043
+ seconds = (ms) => Math.round(ms / 100) / 10;
33044
+ pushHasFailures = (result) => result.componentTypes.failed + result.designTokens.failed > 0 || (result.failures?.length ?? 0) > 0 || (result.summary?.failed ?? 0) > 0;
33045
+ isFlowFinished = (step) => FINISHED.includes(step);
33046
+ }
33047
+ });
33048
+
33049
+ // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/use-flow-log.ts
33050
+ import { useEffect as useEffect28, useRef as useRef18 } from "react";
33051
+ function useFlowLog(state2) {
33052
+ const trail = useRef18(void 0);
33053
+ const previous = useRef18(void 0);
33054
+ useEffect28(() => {
33055
+ const before = previous.current;
33056
+ previous.current = state2;
33057
+ const moved = before !== void 0 && before.step !== state2.step;
33058
+ const now = Date.now();
33059
+ let open = trail.current;
33060
+ if (!open) {
33061
+ if (state2.step === "final-review" || before && !moved) return;
33062
+ open = openTrail(state2, now);
33063
+ startDebugRun({ ...FLOW_RUN, inputs: flowContext(state2) });
33064
+ } else if (before && moved) {
33065
+ open = advance(open, before, state2, now);
33066
+ } else {
33067
+ return;
33068
+ }
33069
+ if (isFlowFinished(state2.step)) {
33070
+ trail.current = void 0;
33071
+ void finishDebugRun(flowFinish(open, state2, now));
33072
+ return;
33073
+ }
33074
+ trail.current = open;
33075
+ setDebugRunProgress(flowProgress(open, now));
33076
+ }, [state2]);
33077
+ useEffect28(
33078
+ () => () => {
33079
+ const open = trail.current;
33080
+ trail.current = void 0;
33081
+ if (open) void finishDebugRun(flowFinish(open, void 0, Date.now()));
33082
+ },
33083
+ []
33084
+ );
33085
+ }
33086
+ var init_use_flow_log = __esm({
33087
+ "packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/use-flow-log.ts"() {
33088
+ "use strict";
33089
+ init_debug_store();
33090
+ init_flow_log();
33091
+ }
33092
+ });
33093
+
32421
33094
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/screen.tsx
32422
33095
  import { Box as Box45 } from "ink";
32423
33096
  import { jsx as jsx56, jsxs as jsxs45 } from "react/jsx-runtime";
@@ -32432,6 +33105,7 @@ function FlowScreen({
32432
33105
  generatePromptPath,
32433
33106
  onExit
32434
33107
  }) {
33108
+ useFlowLog(state2);
32435
33109
  const produced = producedOf(state2);
32436
33110
  const counts = { components: state2.generatedAcceptedCount, tokens: state2.tokenCount };
32437
33111
  const things = countedThings(produced, counts);
@@ -32559,6 +33233,7 @@ var init_screen11 = __esm({
32559
33233
  init_WizardPreviewStep();
32560
33234
  init_produced();
32561
33235
  init_run_teaser();
33236
+ init_use_flow_log();
32562
33237
  }
32563
33238
  });
32564
33239
 
@@ -33356,9 +34031,9 @@ var init_controller = __esm({
33356
34031
  });
33357
34032
 
33358
34033
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/flow/use-flow.ts
33359
- import { useEffect as useEffect24, useRef as useRef17, useSyncExternalStore } from "react";
34034
+ import { useEffect as useEffect29, useRef as useRef19, useSyncExternalStore } from "react";
33360
34035
  function useFlow(start, options = {}) {
33361
- const controller = useRef17();
34036
+ const controller = useRef19();
33362
34037
  if (start && !controller.current) {
33363
34038
  try {
33364
34039
  startWizardLog();
@@ -33375,7 +34050,7 @@ function useFlow(start, options = {}) {
33375
34050
  (listener) => current?.subscribe(listener) ?? (() => void 0),
33376
34051
  () => current?.getState()
33377
34052
  );
33378
- useEffect24(() => {
34053
+ useEffect29(() => {
33379
34054
  if (!start) controller.current = void 0;
33380
34055
  }, [start]);
33381
34056
  return current && state2 ? { controller: current, state: state2 } : void 0;
@@ -33454,7 +34129,7 @@ var init_help_info = __esm({
33454
34129
  });
33455
34130
 
33456
34131
  // packages/experience-design-system-cli/src/tui/help/PageContainer.tsx
33457
- import { useEffect as useEffect25, useState as useState31 } from "react";
34132
+ import { useEffect as useEffect30, useState as useState31 } from "react";
33458
34133
  import { Box as Box46, Text as Text47, useInput as useInput13 } from "ink";
33459
34134
  import { Fragment as Fragment17, jsx as jsx57, jsxs as jsxs46 } from "react/jsx-runtime";
33460
34135
  function Section({ title, rows }) {
@@ -33468,7 +34143,7 @@ function Section({ title, rows }) {
33468
34143
  }
33469
34144
  function HelpScreen({ onDone }) {
33470
34145
  const [info, setInfo] = useState31();
33471
- useEffect25(() => {
34146
+ useEffect30(() => {
33472
34147
  startDebugRun({ flow: "help", step: "01-help", menuOption: "Help", inputs: {} });
33473
34148
  void readHelpInfo().then(setInfo);
33474
34149
  }, []);
@@ -33576,45 +34251,6 @@ var init_PageContainer3 = __esm({
33576
34251
  }
33577
34252
  });
33578
34253
 
33579
- // packages/experience-design-system-cli/src/tui/settings/shared/debug-trail.ts
33580
- import { existsSync as existsSync11 } from "node:fs";
33581
- function diffSnapshots(before, after) {
33582
- const names = [.../* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(after)])];
33583
- const changed_fields = names.filter((name) => before[name] !== after[name]);
33584
- return { changed: changed_fields.length > 0, changed_fields };
33585
- }
33586
- function createTrail(limit = DEFAULT_TRAIL_LIMIT) {
33587
- const actions = [];
33588
- return {
33589
- record(action) {
33590
- actions.push(action);
33591
- if (actions.length > limit) actions.shift();
33592
- },
33593
- entries: () => [...actions]
33594
- };
33595
- }
33596
- function scrubError(error, secrets) {
33597
- let message = error instanceof Error ? error.message : String(error);
33598
- for (const secret of secrets) {
33599
- if (secret.length < MIN_SECRET_LENGTH) continue;
33600
- for (const form of /* @__PURE__ */ new Set([secret, encodeURIComponent(secret)])) message = message.split(form).join("[redacted]");
33601
- }
33602
- return message;
33603
- }
33604
- function describeSettingsFile() {
33605
- const path5 = configFilePath2();
33606
- return { path: path5, eds_home_set: Boolean(process.env["EDS_HOME"]), exists: existsSync11(path5) };
33607
- }
33608
- var DEFAULT_TRAIL_LIMIT, MIN_SECRET_LENGTH;
33609
- var init_debug_trail = __esm({
33610
- "packages/experience-design-system-cli/src/tui/settings/shared/debug-trail.ts"() {
33611
- "use strict";
33612
- init_config();
33613
- DEFAULT_TRAIL_LIMIT = 30;
33614
- MIN_SECRET_LENGTH = 6;
33615
- }
33616
- });
33617
-
33618
34254
  // packages/experience-design-system-cli/src/tui/settings/configuration/agents/agent-status.ts
33619
34255
  import { execFile as execFile2 } from "node:child_process";
33620
34256
  import { access as access5, constants } from "node:fs/promises";
@@ -33680,7 +34316,7 @@ async function testAgent(name, binary, model) {
33680
34316
  timeoutMs: PROMPT_TIMEOUT_MS
33681
34317
  })
33682
34318
  );
33683
- const seconds = ((Date.now() - started) / 1e3).toFixed(1);
34319
+ const seconds2 = ((Date.now() - started) / 1e3).toFixed(1);
33684
34320
  if (result.timedOut) {
33685
34321
  return [...checks, { ...fail3("prompt", `no answer within ${PROMPT_TIMEOUT_MS / 1e3}s`), timedOut: true }];
33686
34322
  }
@@ -33688,7 +34324,7 @@ async function testAgent(name, binary, model) {
33688
34324
  const reason = result.stderr.trim().split("\n").pop()?.slice(0, 160) || `exited with code ${result.exitCode}`;
33689
34325
  return [...checks, fail3("prompt", reason)];
33690
34326
  }
33691
- return [...checks, pass("prompt", `answered in ${seconds}s`)];
34327
+ return [...checks, pass("prompt", `answered in ${seconds2}s`)];
33692
34328
  }
33693
34329
  function statusFromChecks(name, checks, savedBinary) {
33694
34330
  if (checks.length === 0) return "checking";
@@ -33889,7 +34525,7 @@ var init_AgentStatusBadge = __esm({
33889
34525
  });
33890
34526
 
33891
34527
  // packages/experience-design-system-cli/src/tui/settings/configuration/agents/AgentDetail.tsx
33892
- import { useEffect as useEffect26, useState as useState33 } from "react";
34528
+ import { useEffect as useEffect31, useState as useState33 } from "react";
33893
34529
  import { Box as Box48, Text as Text50 } from "ink";
33894
34530
  import { jsx as jsx60, jsxs as jsxs48 } from "react/jsx-runtime";
33895
34531
  function StatusHeading() {
@@ -33910,7 +34546,7 @@ function AgentDetail({
33910
34546
  const [testing, setTesting] = useState33(false);
33911
34547
  const [notice, setNotice] = useState33(null);
33912
34548
  const [checks, setChecks] = useState33(void 0);
33913
- useEffect26(() => {
34549
+ useEffect31(() => {
33914
34550
  let active = true;
33915
34551
  setChecks(void 0);
33916
34552
  const timer = setTimeout(() => {
@@ -34002,7 +34638,7 @@ var init_AgentDetail = __esm({
34002
34638
  });
34003
34639
 
34004
34640
  // packages/experience-design-system-cli/src/tui/settings/configuration/agents/AgentsScreen.tsx
34005
- import { useEffect as useEffect27, useRef as useRef18, useState as useState34 } from "react";
34641
+ import { useEffect as useEffect32, useRef as useRef20, useState as useState34 } from "react";
34006
34642
  import { Box as Box49, Text as Text51, useInput as useInput15 } from "ink";
34007
34643
  import { Fragment as Fragment18, jsx as jsx61, jsxs as jsxs49 } from "react/jsx-runtime";
34008
34644
  function AgentsScreen({ onDone }) {
@@ -34013,7 +34649,7 @@ function AgentsScreen({ onDone }) {
34013
34649
  const [saving, setSaving] = useState34(false);
34014
34650
  const [loadError, setLoadError] = useState34(null);
34015
34651
  const [checks, setChecks] = useState34({});
34016
- const visit = useRef18({
34652
+ const visit = useRef20({
34017
34653
  trail: createTrail(),
34018
34654
  before: void 0,
34019
34655
  environment: void 0,
@@ -34026,7 +34662,7 @@ function AgentsScreen({ onDone }) {
34026
34662
  );
34027
34663
  }
34028
34664
  };
34029
- useEffect27(() => {
34665
+ useEffect32(() => {
34030
34666
  readAgentConfig().then((loaded) => {
34031
34667
  setConfig(loaded);
34032
34668
  inspectAll(loaded);
@@ -34252,7 +34888,7 @@ var init_project_store = __esm({
34252
34888
  });
34253
34889
 
34254
34890
  // packages/experience-design-system-cli/src/tui/settings/configuration/project/ProjectScreen.tsx
34255
- import { useEffect as useEffect28, useRef as useRef19, useState as useState35 } from "react";
34891
+ import { useEffect as useEffect33, useRef as useRef21, useState as useState35 } from "react";
34256
34892
  import { Box as Box50, Text as Text52, useInput as useInput16 } from "ink";
34257
34893
  import { Fragment as Fragment19, jsx as jsx62, jsxs as jsxs50 } from "react/jsx-runtime";
34258
34894
  function debugFields(config) {
@@ -34271,14 +34907,14 @@ function ProjectScreen({ onDone }) {
34271
34907
  const [saving, setSaving] = useState35(false);
34272
34908
  const [notice, setNotice] = useState35(null);
34273
34909
  const [loadError, setLoadError] = useState35(null);
34274
- const visit = useRef19({
34910
+ const visit = useRef21({
34275
34911
  trail: createTrail(),
34276
34912
  before: void 0,
34277
34913
  persisted: void 0,
34278
34914
  error: ""
34279
34915
  }).current;
34280
- const scrub = (err) => scrubError(err, [config?.cmaToken ?? ""]);
34281
- useEffect28(() => {
34916
+ const scrub2 = (err) => scrubError(err, [config?.cmaToken ?? ""]);
34917
+ useEffect33(() => {
34282
34918
  readCredentials().then((cfg) => {
34283
34919
  setConfig(cfg);
34284
34920
  visit.before = snapshotOf(cfg);
@@ -34345,7 +34981,7 @@ function ProjectScreen({ onDone }) {
34345
34981
  if (config.contentfulBaseDir) void startDebugSessionIn(config.contentfulBaseDir, { replace: true });
34346
34982
  setNotice({ kind: "success", text: "Project settings saved" });
34347
34983
  }).catch((err) => {
34348
- visit.error = scrub(err);
34984
+ visit.error = scrub2(err);
34349
34985
  visit.trail.record("save failed");
34350
34986
  setNotice({ kind: "error", text: err instanceof Error ? err.message : "Failed to save" });
34351
34987
  }).finally(() => setSaving(false));
@@ -34465,13 +35101,13 @@ var init_ConfigurationScreen = __esm({
34465
35101
  });
34466
35102
 
34467
35103
  // packages/experience-design-system-cli/src/tui/settings/opt-in-analytics/screen.tsx
34468
- import { useEffect as useEffect29, useState as useState37 } from "react";
35104
+ import { useEffect as useEffect34, useState as useState37 } from "react";
34469
35105
  import { Box as Box52, Text as Text54, useInput as useInput18 } from "ink";
34470
35106
  import { Fragment as Fragment20, jsx as jsx64, jsxs as jsxs52 } from "react/jsx-runtime";
34471
35107
  function OptInAnalyticsScreen({ onDone }) {
34472
35108
  const [loading, setLoading] = useState37(true);
34473
35109
  const [enabled, setEnabled] = useState37(true);
34474
- useEffect29(() => {
35110
+ useEffect34(() => {
34475
35111
  readAnalyticsSetting().then((setting) => {
34476
35112
  setEnabled(setting.enabled);
34477
35113
  setLoading(false);
@@ -34534,7 +35170,7 @@ var init_screen12 = __esm({
34534
35170
  });
34535
35171
 
34536
35172
  // packages/experience-design-system-cli/src/tui/settings/debug-mode/screen.tsx
34537
- import { useEffect as useEffect30, useRef as useRef20, useState as useState38 } from "react";
35173
+ import { useEffect as useEffect35, useRef as useRef22, useState as useState38 } from "react";
34538
35174
  import { Box as Box53, Text as Text55, useInput as useInput19 } from "ink";
34539
35175
  import { Fragment as Fragment21, jsx as jsx65, jsxs as jsxs53 } from "react/jsx-runtime";
34540
35176
  function DebugModeScreen({ onDone }) {
@@ -34544,8 +35180,8 @@ function DebugModeScreen({ onDone }) {
34544
35180
  RETENTION_CHOICES[RETENTION_CHOICES.length - 1]
34545
35181
  );
34546
35182
  const [notice, setNotice] = useState38(null);
34547
- const visit = useRef20({ trail: createTrail(), before: void 0, error: "" }).current;
34548
- useEffect30(() => {
35183
+ const visit = useRef22({ trail: createTrail(), before: void 0, error: "" }).current;
35184
+ useEffect35(() => {
34549
35185
  readDebugModeSetting().then((loaded) => {
34550
35186
  setSetting(loaded);
34551
35187
  setPending(loaded.retentionDays);
@@ -34686,7 +35322,7 @@ var app_exports = {};
34686
35322
  __export(app_exports, {
34687
35323
  runApp: () => runApp
34688
35324
  });
34689
- import { useEffect as useEffect31, useState as useState39 } from "react";
35325
+ import { useEffect as useEffect36, useState as useState39 } from "react";
34690
35326
  import { Fragment as Fragment22, jsx as jsx66 } from "react/jsx-runtime";
34691
35327
  function App({ importOptions, inkClear }) {
34692
35328
  const [screen, setScreen] = useState39("start");
@@ -34720,7 +35356,7 @@ function App({ importOptions, inkClear }) {
34720
35356
  const [flowStart, setFlowStart] = useState39();
34721
35357
  const flow = useFlow(flowStart, { beforeStepChange: inkClear });
34722
35358
  const [importDefaults, setImportDefaults] = useState39();
34723
- useEffect31(() => {
35359
+ useEffect36(() => {
34724
35360
  if (screen !== "import") {
34725
35361
  setImportDefaults(void 0);
34726
35362
  return;
@@ -34793,7 +35429,7 @@ function App({ importOptions, inkClear }) {
34793
35429
  }
34794
35430
  });
34795
35431
  };
34796
- useEffect31(() => {
35432
+ useEffect36(() => {
34797
35433
  if (!tokensOnlyRun || tokensOnly?.status !== "done" || !tokensOnly.result.ok) return;
34798
35434
  const { credentialsSkipped, input, tokens } = tokensOnlyRun;
34799
35435
  const { tokensPath, tokenSessionId, tokenCount } = tokensOnly.result;
@@ -34815,12 +35451,12 @@ function App({ importOptions, inkClear }) {
34815
35451
  }
34816
35452
  });
34817
35453
  }, [tokensOnly, tokensOnlyRun]);
34818
- useEffect31(() => {
35454
+ useEffect36(() => {
34819
35455
  if (!extractionRun || extraction?.status !== "done" || !extraction.result.ok) return;
34820
35456
  setExtractionRun(void 0);
34821
35457
  setScopeRun({ ...extractionRun, extraction: extraction.result.extraction });
34822
35458
  }, [extraction, extractionRun]);
34823
- useEffect31(() => {
35459
+ useEffect36(() => {
34824
35460
  if (!scopeRun || scopeFlow?.status !== "confirmed" || generationInput) return;
34825
35461
  const { extraction: produced, input, generatePromptPath } = scopeRun;
34826
35462
  setGenerationInput({
@@ -34838,7 +35474,7 @@ function App({ importOptions, inkClear }) {
34838
35474
  ...generatePromptPath ? { generatePromptPath } : {}
34839
35475
  });
34840
35476
  }, [scopeFlow, scopeRun, generationInput]);
34841
- useEffect31(() => {
35477
+ useEffect36(() => {
34842
35478
  if (!scopeRun || generation?.status !== "done" || !generation.result.ok) return;
34843
35479
  const { credentialsSkipped, extraction: produced, input, generatePromptPath } = scopeRun;
34844
35480
  inkClear();
@@ -35007,6 +35643,7 @@ function App({ importOptions, inkClear }) {
35007
35643
  return /* @__PURE__ */ jsx66(
35008
35644
  CredentialsScreen,
35009
35645
  {
35646
+ mode: target,
35010
35647
  initial: importDefaults.credentials,
35011
35648
  tokensOnly: target === "tokens",
35012
35649
  onBack: () => goBackFrom("credentials"),
@@ -35144,9 +35781,9 @@ var pkg = JSON.parse(
35144
35781
  function createProgram() {
35145
35782
  const program = new Command().name("experiences").description("Contentful Experiences design system import CLI").version(pkg.version, "--version", "Print version number");
35146
35783
  registerImportCommand(program, async (options) => {
35147
- const { render } = await import("ink");
35784
+ const { render: render3 } = await import("ink");
35148
35785
  const { runApp: runApp2 } = await Promise.resolve().then(() => (init_app(), app_exports));
35149
- await runApp2(render, options);
35786
+ await runApp2(render3, options);
35150
35787
  });
35151
35788
  program.hook("preAction", async (_thisCommand, actionCommand) => {
35152
35789
  const chain = [];