@contentful/experience-design-system-cli 2.37.1-dev-build-c1d02862.0 → 2.37.1-dev-build-40c29bf0.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.
Files changed (51) hide show
  1. package/dist/app.js +3191 -317
  2. package/dist/index.js +3462 -316
  3. package/dist/package.json +1 -1
  4. package/dist/src/tui/import/steps/07-scope-gate/cache-check.d.ts +29 -0
  5. package/{legacy/dist/src/import/tui/scope-gate-columns.d.ts → dist/src/tui/import/steps/07-scope-gate/columns.d.ts} +22 -2
  6. package/dist/src/tui/import/steps/07-scope-gate/graph/composite-closure.d.ts +26 -0
  7. package/dist/src/tui/import/steps/07-scope-gate/graph/cycle-detection.d.ts +22 -0
  8. package/dist/src/tui/import/steps/07-scope-gate/graph/fuzzy-search.d.ts +3 -0
  9. package/dist/src/tui/import/steps/07-scope-gate/graph/index.d.ts +33 -0
  10. package/dist/src/tui/import/steps/07-scope-gate/graph/lineage.d.ts +29 -0
  11. package/dist/src/tui/import/steps/07-scope-gate/graph/search-neighborhood.d.ts +3 -0
  12. package/dist/src/tui/import/steps/07-scope-gate/graph/slot-graph.d.ts +11 -0
  13. package/dist/src/tui/import/steps/07-scope-gate/keymap.d.ts +84 -0
  14. package/dist/src/tui/import/steps/07-scope-gate/load.d.ts +8 -0
  15. package/dist/src/tui/import/steps/07-scope-gate/panels/added-column.d.ts +15 -0
  16. package/dist/src/tui/import/steps/07-scope-gate/panels/cycles-panel.d.ts +8 -0
  17. package/dist/src/tui/import/steps/07-scope-gate/panels/reject-prompt.d.ts +5 -0
  18. package/dist/src/tui/import/steps/07-scope-gate/screen.d.ts +9 -0
  19. package/dist/src/tui/import/steps/07-scope-gate/sidebar/autocomplete.d.ts +5 -0
  20. package/dist/src/tui/import/steps/07-scope-gate/sidebar/components/CompactControlBar.d.ts +4 -0
  21. package/dist/src/tui/import/steps/07-scope-gate/sidebar/components/GotoBanner.d.ts +32 -0
  22. package/dist/src/tui/import/steps/07-scope-gate/sidebar/components/GroupedSidebar.d.ts +93 -0
  23. package/dist/src/tui/import/steps/07-scope-gate/sidebar/components/HelpOverlay.d.ts +21 -0
  24. package/dist/src/tui/import/steps/07-scope-gate/sidebar/components/LegendEntry.d.ts +2 -0
  25. package/dist/src/tui/import/steps/07-scope-gate/sidebar/components/SearchMatchSummary.d.ts +11 -0
  26. package/dist/src/tui/import/steps/07-scope-gate/sidebar/components/badge.d.ts +13 -0
  27. package/dist/src/tui/import/steps/07-scope-gate/sidebar/components/windowed-panel.d.ts +17 -0
  28. package/dist/src/tui/import/steps/07-scope-gate/sidebar/group-collapse.d.ts +2 -0
  29. package/dist/src/tui/import/steps/07-scope-gate/sidebar/hooks/sidebar-search-state.d.ts +17 -0
  30. package/dist/src/tui/import/steps/07-scope-gate/sidebar/hooks/use-terminal-size.d.ts +6 -0
  31. package/dist/src/tui/import/steps/07-scope-gate/sidebar/hooks/useImmediateInput.d.ts +20 -0
  32. package/dist/src/tui/import/steps/07-scope-gate/sidebar/hooks/useOverlayPanel.d.ts +13 -0
  33. package/dist/src/tui/import/steps/07-scope-gate/sidebar/lineage-layout.d.ts +68 -0
  34. package/dist/src/tui/import/steps/07-scope-gate/sidebar/sidebar-help.d.ts +2 -0
  35. package/dist/src/tui/import/steps/07-scope-gate/sidebar/sidebar-input.d.ts +13 -0
  36. package/dist/src/tui/import/steps/07-scope-gate/sidebar/sidebar-navigation.d.ts +18 -0
  37. package/dist/src/tui/import/steps/07-scope-gate/sidebar/step-filters.d.ts +19 -0
  38. package/dist/src/tui/import/steps/07-scope-gate/sidebar/theme.d.ts +8 -0
  39. package/dist/src/tui/import/steps/07-scope-gate/sidebar/types.d.ts +7 -0
  40. package/dist/src/tui/import/steps/07-scope-gate/state.d.ts +19 -0
  41. package/dist/src/tui/import/steps/07-scope-gate/types.d.ts +24 -0
  42. package/dist/src/tui/import/steps/07-scope-gate/use-scope-gate-flow.d.ts +31 -0
  43. package/dist/src/tui/import/steps/07-scope-gate/use-scope-gate.d.ts +76 -0
  44. package/legacy/dist/src/import/tui/handoff.d.ts +11 -0
  45. package/legacy/dist/src/index.js +1511 -2733
  46. package/legacy/package.json +1 -1
  47. package/package.json +4 -4
  48. package/legacy/dist/src/import/tui/steps/ScopeGateStep.d.ts +0 -48
  49. /package/{legacy/dist/src/analyze → dist/src/tui/import/steps/07-scope-gate/graph}/scope-gate-cascade.d.ts +0 -0
  50. /package/{legacy/dist/src/import/tui → dist/src/tui/import/steps/07-scope-gate/sidebar}/ai-flag.d.ts +0 -0
  51. /package/{legacy/dist/src/import/tui → dist/src/tui/import/steps/07-scope-gate/sidebar}/components/CounterStrip.d.ts +0 -0
package/dist/app.js CHANGED
@@ -760,8 +760,8 @@ async function runAgent(options) {
760
760
  const { agent, prompt, timeoutMs, model, onOutput, promptViaStdin, onDebugEvent } = options;
761
761
  const bedrock = options.bedrock ?? process.env.EDS_BEDROCK === "1";
762
762
  const binary = resolveBinary(agent);
763
- const useStdin = !!promptViaStdin;
764
- const args = buildArgs(agent, prompt, model, useStdin, bedrock);
763
+ const useStdin2 = !!promptViaStdin;
764
+ const args = buildArgs(agent, prompt, model, useStdin2, bedrock);
765
765
  const startedAt = Date.now();
766
766
  onDebugEvent?.("run.start", {
767
767
  agent,
@@ -778,7 +778,7 @@ async function runAgent(options) {
778
778
  stdio: ["pipe", "pipe", "pipe"],
779
779
  ...bedrockEnv ? { env: { ...process.env, ...bedrockEnv } } : {}
780
780
  });
781
- if (useStdin && child.stdin) {
781
+ if (useStdin2 && child.stdin) {
782
782
  child.stdin.on("error", () => {
783
783
  });
784
784
  child.stdin.write(prompt, () => {
@@ -2001,7 +2001,7 @@ var init_cache_keys = __esm({
2001
2001
 
2002
2002
  // packages/experience-design-system-cli/app.tsx
2003
2003
  import { join as join13 } from "node:path";
2004
- import { useEffect as useEffect11, useState as useState15 } from "react";
2004
+ import { useEffect as useEffect14, useState as useState20 } from "react";
2005
2005
 
2006
2006
  // packages/experience-design-system-cli/src/tui/home/home.tsx
2007
2007
  import { useEffect as useEffect2, useState as useState2 } from "react";
@@ -2071,8 +2071,8 @@ function readPackageVersion() {
2071
2071
  return pkg.version ?? "unknown";
2072
2072
  }
2073
2073
  function parseVersionTag(tag) {
2074
- const match = /^v(\d+\.\d+\.\d+)$/.exec(tag);
2075
- return match ? match[1] : void 0;
2074
+ const match2 = /^v(\d+\.\d+\.\d+)$/.exec(tag);
2075
+ return match2 ? match2[1] : void 0;
2076
2076
  }
2077
2077
  async function checkForUpgrade() {
2078
2078
  const current = readPackageVersion();
@@ -3093,6 +3093,34 @@ function parseReviewReasons(raw) {
3093
3093
  return [];
3094
3094
  }
3095
3095
  }
3096
+ function loadScopeComponents(db, sessionId) {
3097
+ const rows = db.prepare(`SELECT name, component_id, status, reject_reason, review_reasons, needs_review FROM raw_components
3098
+ WHERE session_id = ? AND status IN ('extracted', 'accepted', 'rejected')
3099
+ ORDER BY name`).all(sessionId);
3100
+ if (rows.length === 0)
3101
+ return [];
3102
+ const slotRows = db.prepare(`SELECT component_id, name, position
3103
+ FROM raw_slots WHERE session_id = ? ORDER BY component_id, position`).all(sessionId);
3104
+ const allowedRows = db.prepare(`SELECT component_id, slot_name, position, allowed_component
3105
+ FROM raw_slot_allowed_components WHERE session_id = ? ORDER BY component_id, slot_name, position`).all(sessionId);
3106
+ const slotsByComponent = indexRowsByKey(slotRows, (s) => s.component_id);
3107
+ const allowedBySlot = indexRowsByKey(allowedRows, (a) => `${a.component_id}::${a.slot_name}`);
3108
+ return rows.map((r) => {
3109
+ const reviewReasons = parseReviewReasons(r.review_reasons);
3110
+ const nonAuthorableReason = reviewReasons.find((reason) => reason.startsWith("non-authorable:"));
3111
+ return {
3112
+ name: r.name,
3113
+ componentId: r.component_id,
3114
+ aiDecision: r.status === "accepted" ? "accepted" : r.status === "rejected" ? "rejected" : null,
3115
+ aiReason: r.reject_reason ?? nonAuthorableReason?.slice("non-authorable:".length) ?? null,
3116
+ needsReview: Boolean(r.needs_review),
3117
+ slots: (slotsByComponent.get(r.component_id) ?? []).map((s) => ({
3118
+ name: s.name,
3119
+ allowedComponents: (allowedBySlot.get(`${r.component_id}::${s.name}`) ?? []).map((a) => a.allowed_component)
3120
+ }))
3121
+ };
3122
+ });
3123
+ }
3096
3124
  var _cliCacheVersionCache = null;
3097
3125
  async function getCliCacheVersion() {
3098
3126
  if (_cliCacheVersionCache)
@@ -3720,9 +3748,9 @@ var defaultPathSerializer = ({ path: path5, url: _url }) => {
3720
3748
  let url = _url;
3721
3749
  const matches = _url.match(PATH_PARAM_RE);
3722
3750
  if (matches) {
3723
- for (const match of matches) {
3751
+ for (const match2 of matches) {
3724
3752
  let explode = false;
3725
- let name = match.substring(1, match.length - 1);
3753
+ let name = match2.substring(1, match2.length - 1);
3726
3754
  let style = "simple";
3727
3755
  if (name.endsWith("*")) {
3728
3756
  explode = true;
@@ -3740,11 +3768,11 @@ var defaultPathSerializer = ({ path: path5, url: _url }) => {
3740
3768
  continue;
3741
3769
  }
3742
3770
  if (Array.isArray(value)) {
3743
- url = url.replace(match, serializeArrayParam({ explode, name, style, value }));
3771
+ url = url.replace(match2, serializeArrayParam({ explode, name, style, value }));
3744
3772
  continue;
3745
3773
  }
3746
3774
  if (typeof value === "object") {
3747
- url = url.replace(match, serializeObjectParam({
3775
+ url = url.replace(match2, serializeObjectParam({
3748
3776
  explode,
3749
3777
  name,
3750
3778
  style,
@@ -3754,19 +3782,19 @@ var defaultPathSerializer = ({ path: path5, url: _url }) => {
3754
3782
  continue;
3755
3783
  }
3756
3784
  if (style === "matrix") {
3757
- url = url.replace(match, `;${serializePrimitiveParam({
3785
+ url = url.replace(match2, `;${serializePrimitiveParam({
3758
3786
  name,
3759
3787
  value
3760
3788
  })}`);
3761
3789
  continue;
3762
3790
  }
3763
3791
  const replaceValue = encodeURIComponent(style === "label" ? `.${value}` : value);
3764
- url = url.replace(match, replaceValue);
3792
+ url = url.replace(match2, replaceValue);
3765
3793
  }
3766
3794
  }
3767
3795
  return url;
3768
3796
  };
3769
- var createQuerySerializer = ({ allowReserved, array: array3, object: object2 } = {}) => {
3797
+ var createQuerySerializer = ({ allowReserved, array: array4, object: object2 } = {}) => {
3770
3798
  const querySerializer = (queryParams) => {
3771
3799
  const search = [];
3772
3800
  if (queryParams && typeof queryParams === "object") {
@@ -3782,7 +3810,7 @@ var createQuerySerializer = ({ allowReserved, array: array3, object: object2 } =
3782
3810
  name,
3783
3811
  style: "form",
3784
3812
  value,
3785
- ...array3
3813
+ ...array4
3786
3814
  });
3787
3815
  if (serializedArray)
3788
3816
  search.push(serializedArray);
@@ -5354,12 +5382,12 @@ function findSession(stdout) {
5354
5382
  return null;
5355
5383
  }
5356
5384
  function parseExtractedCount(stderr) {
5357
- const match = EXTRACTED.exec(stderr);
5358
- return match ? Number(match[1]) : 0;
5385
+ const match2 = EXTRACTED.exec(stderr);
5386
+ return match2 ? Number(match2[1]) : 0;
5359
5387
  }
5360
5388
  function parsePrintTokensCount(stdout) {
5361
- const match = PRINT_TOKENS_COUNT.exec(stdout);
5362
- return match ? Number(match[1]) : 0;
5389
+ const match2 = PRINT_TOKENS_COUNT.exec(stdout);
5390
+ return match2 ? Number(match2[1]) : 0;
5363
5391
  }
5364
5392
  function initialProgress(input) {
5365
5393
  return {
@@ -6140,8 +6168,8 @@ async function runAgent2(options) {
6140
6168
  const { agent, prompt, timeoutMs, model, onOutput, promptViaStdin, onDebugEvent } = options;
6141
6169
  const bedrock = options.bedrock ?? process.env.EDS_BEDROCK === "1";
6142
6170
  const binary = resolveAgentBinary(agent);
6143
- const useStdin = !!promptViaStdin;
6144
- const args = buildAgentArgs(agent, prompt, model, useStdin, bedrock);
6171
+ const useStdin2 = !!promptViaStdin;
6172
+ const args = buildAgentArgs(agent, prompt, model, useStdin2, bedrock);
6145
6173
  const startedAt = Date.now();
6146
6174
  onDebugEvent?.("run.start", {
6147
6175
  agent,
@@ -6158,7 +6186,7 @@ async function runAgent2(options) {
6158
6186
  stdio: ["pipe", "pipe", "pipe"],
6159
6187
  ...bedrockEnv ? { env: { ...process.env, ...bedrockEnv } } : {}
6160
6188
  });
6161
- if (useStdin && child.stdin) {
6189
+ if (useStdin2 && child.stdin) {
6162
6190
  child.stdin.on("error", () => {
6163
6191
  });
6164
6192
  child.stdin.write(prompt, () => {
@@ -6692,194 +6720,2989 @@ function useExtraction(input) {
6692
6720
  return state;
6693
6721
  }
6694
6722
 
6695
- // packages/experience-design-system-cli/src/tui/import/spawn-v1-import.ts
6696
- import { spawn as spawn7 } from "node:child_process";
6723
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/screen.tsx
6724
+ import { Box as Box20, Text as Text22 } from "ink";
6697
6725
 
6698
- // packages/experience-design-system-cli/src/commands/import-options.ts
6699
- function importOptionArgs(options) {
6700
- return [
6701
- ...options.agent ? ["--agent", options.agent] : [],
6702
- ...options.prompt.flatMap((value) => ["--prompt", value]),
6703
- ...options.cache ? [] : ["--no-cache"]
6704
- ];
6705
- }
6726
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/panels/added-column.tsx
6727
+ import React6 from "react";
6728
+ import { Box as Box11, Text as Text12 } from "ink";
6729
+ import figures from "figures";
6706
6730
 
6707
- // packages/experience-design-system-types/dist/src/handoff/index.js
6708
- import * as z5 from "zod/mini";
6709
- var HANDOFF_ENV = "EDS_IMPORT_HANDOFF";
6710
- var NonEmpty = z5.string().check(z5.minLength(1));
6711
- var TokensSchema = z5.object({
6712
- /**
6713
- * What to do about an existing `tokens.json`.
6714
- * reuse: keep it. regenerate: build it again with the cache off. generate: nothing was asked, build it as usual.
6715
- */
6716
- strategy: z5.enum(["reuse", "regenerate", "generate"])
6717
- });
6718
- var ExtractionSchema = z5.object({
6719
- sessionId: NonEmpty,
6720
- outDir: NonEmpty,
6721
- tokensPath: z5.string(),
6722
- tokenSessionId: z5.nullable(z5.string()),
6723
- tokenCount: z5.number(),
6724
- existingEntitiesPath: z5.nullable(z5.string()),
6725
- /** Never 'running': the wizard starts its background cache check only once this has settled. */
6726
- existingEntitiesStatus: z5.enum(["idle", "complete", "failed"]),
6727
- /** The only phases the scope gate can start from. */
6728
- compositionPhase: z5.enum(["done", "cache-hit"])
6729
- });
6730
- var ImportHandoffSchema = z5.object({
6731
- /** The user skipped the credentials screen, so nothing is fetched from or pushed to Contentful. */
6732
- credentialsSkipped: z5.boolean(),
6733
- tokens: TokensSchema,
6734
- /** Present once the CLI has run the extraction stage; the wizard then starts at the scope gate. */
6735
- extraction: z5.optional(ExtractionSchema)
6736
- });
6737
- function serializeHandoff(handoff) {
6738
- return JSON.stringify(handoff);
6739
- }
6731
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/theme.ts
6732
+ var PALETTE2 = {
6733
+ info: PALETTE.accent,
6734
+ success: PALETTE.success,
6735
+ error: PALETTE.error,
6736
+ warning: PALETTE.warning,
6737
+ muted: PALETTE.muted,
6738
+ border: PALETTE.border
6739
+ };
6740
6740
 
6741
- // packages/experience-design-system-cli/src/tui/import/spawn-v1-import.ts
6742
- function buildArgs2(options) {
6743
- const args = ["import"];
6744
- if (options.projectPath) {
6745
- args.push("--project", options.projectPath);
6741
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/columns.ts
6742
+ var TWO_COLUMN_MIN_WIDTH = 100;
6743
+ var SCOPE_GATE_MAIN_COLUMN_WIDTH = 54;
6744
+ var ACCEPTED_COMPONENTS_COLUMN_WIDTH = 36;
6745
+ var PANEL_BORDER_ROWS = 2;
6746
+ var PANEL_INDICATOR_ROWS = 2;
6747
+ var PANEL_HEADER_ROWS = 2;
6748
+ function computePanelLayout(mainVisibleCount) {
6749
+ const safeMainVisibleCount = Math.max(1, mainVisibleCount);
6750
+ const height = safeMainVisibleCount + PANEL_BORDER_ROWS + PANEL_INDICATOR_ROWS + PANEL_HEADER_ROWS;
6751
+ const sideVisibleCount = Math.max(1, height - PANEL_BORDER_ROWS - PANEL_INDICATOR_ROWS - PANEL_HEADER_ROWS);
6752
+ return { height, mainVisibleCount: safeMainVisibleCount, sideVisibleCount };
6753
+ }
6754
+ function computeColumnWidths(totalWidth) {
6755
+ if (totalWidth < TWO_COLUMN_MIN_WIDTH) {
6756
+ return { layout: "single", main: SCOPE_GATE_MAIN_COLUMN_WIDTH, added: 0 };
6757
+ }
6758
+ const main = SCOPE_GATE_MAIN_COLUMN_WIDTH;
6759
+ const added = ACCEPTED_COMPONENTS_COLUMN_WIDTH;
6760
+ return { layout: "two-column", main, added };
6761
+ }
6762
+ function sortTieredEntries(cycleTier, restTier) {
6763
+ cycleTier.sort((a, b) => a.name.localeCompare(b.name));
6764
+ restTier.sort((a, b) => a.name.localeCompare(b.name));
6765
+ return [...cycleTier, ...restTier];
6766
+ }
6767
+ function buildAddedComponentsList(components, stateByKey, cycleParticipants = /* @__PURE__ */ new Set()) {
6768
+ const cycleTier = [];
6769
+ const restTier = [];
6770
+ const seen = /* @__PURE__ */ new Set();
6771
+ for (const c2 of components) {
6772
+ if (stateByKey.get(c2.name) !== "accepted") continue;
6773
+ if (seen.has(c2.name)) continue;
6774
+ seen.add(c2.name);
6775
+ if (cycleParticipants.has(c2.name)) cycleTier.push({ name: c2.name, isCycle: true });
6776
+ else restTier.push({ name: c2.name, isCycle: false });
6777
+ }
6778
+ return sortTieredEntries(cycleTier, restTier);
6779
+ }
6780
+ function computeCounters(components, closures, stateByKey) {
6781
+ let accepted = 0;
6782
+ let rejected = 0;
6783
+ let undecided = 0;
6784
+ for (const c2 of components) {
6785
+ const s = stateByKey.get(c2.name) ?? "undecided";
6786
+ if (s === "accepted") accepted++;
6787
+ else if (s === "rejected") rejected++;
6788
+ else undecided++;
6789
+ }
6790
+ let groups = 0;
6791
+ for (const [root, closure] of closures.entries()) {
6792
+ if (closure.nodes.length <= 1) continue;
6793
+ if (stateByKey.get(root) === "accepted") groups++;
6794
+ }
6795
+ return { accepted, rejected, undecided, groups, total: components.length };
6796
+ }
6797
+ function sideColumnLabelStyle(input) {
6798
+ const { isCycle, isSelected, focused } = input;
6799
+ const isCursor = isSelected && focused;
6800
+ if (isCursor) {
6801
+ return {
6802
+ nameColor: PALETTE2.info,
6803
+ nameBold: true,
6804
+ nameInverse: false,
6805
+ nameUnderline: false,
6806
+ suffixColor: PALETTE2.info,
6807
+ suffixDim: false,
6808
+ suffixInverse: false,
6809
+ suffixUnderline: false
6810
+ };
6746
6811
  }
6747
- if (options.tokens) {
6748
- args.push("--tokens", options.tokens);
6812
+ const underline = isSelected && !focused;
6813
+ if (isCycle) {
6814
+ return {
6815
+ nameColor: PALETTE2.warning,
6816
+ nameBold: false,
6817
+ nameInverse: false,
6818
+ nameUnderline: underline,
6819
+ suffixColor: PALETTE2.warning,
6820
+ suffixDim: false,
6821
+ suffixInverse: false,
6822
+ suffixUnderline: underline
6823
+ };
6749
6824
  }
6750
- args.push(...importOptionArgs({ agent: options.agent, prompt: options.prompt ?? [], cache: options.cache ?? true }));
6751
- return args;
6825
+ return {
6826
+ nameColor: PALETTE2.success,
6827
+ nameBold: false,
6828
+ nameInverse: false,
6829
+ nameUnderline: underline,
6830
+ suffixColor: PALETTE2.info,
6831
+ suffixDim: true,
6832
+ suffixInverse: false,
6833
+ suffixUnderline: underline
6834
+ };
6752
6835
  }
6753
- function buildEnv(options, base = process.env) {
6754
- return { ...base, ...options.handoff ? { [HANDOFF_ENV]: serializeHandoff(options.handoff) } : {} };
6836
+ function computeColumnWindow(total, cursor, visibleCount) {
6837
+ if (total <= visibleCount) return { start: 0, end: total, above: 0, below: 0 };
6838
+ let start = Math.max(0, cursor - Math.floor(visibleCount / 2));
6839
+ start = Math.min(start, total - visibleCount);
6840
+ const end = start + visibleCount;
6841
+ return { start, end, above: start, below: total - end };
6842
+ }
6843
+
6844
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/windowed-panel.tsx
6845
+ import { Box as Box10, Text as Text11 } from "ink";
6846
+ import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
6847
+ var MIN_TERMINAL_PANEL_HEIGHT = 5;
6848
+ function terminalPanelHeight(rows, reservedRows = 4) {
6849
+ return Math.max(MIN_TERMINAL_PANEL_HEIGHT, rows - reservedRows);
6850
+ }
6851
+ function FixedPanel({
6852
+ width,
6853
+ height,
6854
+ minHeight,
6855
+ focused = false,
6856
+ borderStyle,
6857
+ borderColor,
6858
+ paddingLeft,
6859
+ clipOverflow = true,
6860
+ children
6861
+ }) {
6862
+ return /* @__PURE__ */ jsx13(
6863
+ Box10,
6864
+ {
6865
+ flexDirection: "column",
6866
+ width,
6867
+ ...height === void 0 ? {} : { height },
6868
+ ...minHeight === void 0 ? {} : { minHeight },
6869
+ ...height === void 0 || !clipOverflow ? {} : { overflowY: "hidden" },
6870
+ flexShrink: 0,
6871
+ borderStyle,
6872
+ borderColor: focused ? borderColor ?? "white" : borderColor,
6873
+ paddingLeft,
6874
+ children
6875
+ }
6876
+ );
6755
6877
  }
6756
- async function spawnV1Import(options = {}) {
6757
- const cliPath = findLegacyCliPath();
6758
- const args = buildArgs2(options);
6759
- return new Promise((resolvePromise) => {
6760
- const child = spawn7("node", [cliPath, ...args], {
6761
- stdio: "inherit",
6762
- env: buildEnv(options)
6763
- });
6764
- child.on("close", (code) => {
6765
- resolvePromise({ exitCode: code ?? 1, result: void 0, stdout: "", stderr: "" });
6766
- });
6767
- child.on("error", (err) => {
6768
- resolvePromise({ exitCode: 1, result: void 0, stdout: "", stderr: err.message });
6769
- });
6770
- });
6878
+ function WindowedPanel({ width, height, title, focused, children }) {
6879
+ return /* @__PURE__ */ jsxs10(
6880
+ FixedPanel,
6881
+ {
6882
+ width,
6883
+ borderStyle: "single",
6884
+ borderColor: focused ? "white" : void 0,
6885
+ ...height === void 0 ? {} : { height },
6886
+ focused,
6887
+ children: [
6888
+ title && /* @__PURE__ */ jsx13(WindowedPanelHeader, { title, width, focused }),
6889
+ children
6890
+ ]
6891
+ }
6892
+ );
6893
+ }
6894
+ function WindowedPanelHeader({
6895
+ title,
6896
+ width,
6897
+ focused
6898
+ }) {
6899
+ return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
6900
+ /* @__PURE__ */ jsx13(Text11, { bold: true, color: PALETTE2.info, inverse: focused, children: title }),
6901
+ /* @__PURE__ */ jsx13(Text11, { dimColor: true, children: "\u2500".repeat(Math.max(0, width - 2)) })
6902
+ ] });
6903
+ }
6904
+ function formatWindowIndicator(direction, count) {
6905
+ if (count <= 0) return " ";
6906
+ return `${direction === "up" ? "\u2191" : "\u2193"} ${count} more`;
6907
+ }
6908
+ function WindowIndicator({ direction, count }) {
6909
+ return /* @__PURE__ */ jsx13(Text11, { color: PALETTE2.muted, children: formatWindowIndicator(direction, count) });
6771
6910
  }
6772
6911
 
6773
- // packages/experience-design-system-cli/src/tui/import/terminal-input.ts
6774
- function getTerminalHandle() {
6775
- return process.stdin._handle;
6912
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/panels/added-column.tsx
6913
+ import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
6914
+ function AddedColumn(props) {
6915
+ const { title, width, height, entries, cursor, focused, aiFlaggedByKey, visibleCount } = props;
6916
+ const reserveAiBadge = entries.some((e) => aiFlaggedByKey?.get(e.name) === true);
6917
+ const firstNonCycleIdx = entries.findIndex((e) => !e.isCycle);
6918
+ const window = computeColumnWindow(entries.length, cursor, Math.max(1, visibleCount));
6919
+ return /* @__PURE__ */ jsxs11(WindowedPanel, { width, height, title, focused, children: [
6920
+ /* @__PURE__ */ jsx14(WindowIndicator, { direction: "up", count: window.above }),
6921
+ entries.length === 0 ? /* @__PURE__ */ jsx14(Text12, { color: PALETTE2.muted, children: "(none)" }) : entries.slice(window.start, window.end).map((entry, vi) => {
6922
+ const i = window.start + vi;
6923
+ const isSelected = i === cursor;
6924
+ const isCursor = focused && isSelected;
6925
+ const aiFlagged = aiFlaggedByKey?.get(entry.name) === true;
6926
+ const showSeparator = firstNonCycleIdx > 0 && i === firstNonCycleIdx;
6927
+ const style = sideColumnLabelStyle({ isCycle: entry.isCycle, isSelected, focused });
6928
+ return /* @__PURE__ */ jsxs11(React6.Fragment, { children: [
6929
+ showSeparator && /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: "\u2500".repeat(Math.max(0, width - 2)) }),
6930
+ /* @__PURE__ */ jsxs11(Box11, { children: [
6931
+ isCursor ? /* @__PURE__ */ jsx14(Text12, { color: PALETTE2.info, bold: true, children: figures.pointer }) : /* @__PURE__ */ jsx14(Text12, { children: " " }),
6932
+ reserveAiBadge && (aiFlagged ? /* @__PURE__ */ jsx14(Text12, { color: PALETTE2.warning, bold: true, children: " [\xD7]" }) : /* @__PURE__ */ jsx14(Text12, { children: " " })),
6933
+ entry.isCycle && /* @__PURE__ */ jsx14(Text12, { color: isCursor ? PALETTE2.info : PALETTE2.warning, bold: true, underline: style.nameUnderline, children: " \u26A0" }),
6934
+ /* @__PURE__ */ jsx14(
6935
+ Text12,
6936
+ {
6937
+ color: style.nameColor,
6938
+ bold: style.nameBold,
6939
+ inverse: style.nameInverse,
6940
+ underline: style.nameUnderline,
6941
+ wrap: "wrap",
6942
+ children: " " + entry.name
6943
+ }
6944
+ )
6945
+ ] })
6946
+ ] }, entry.name);
6947
+ }),
6948
+ /* @__PURE__ */ jsx14(WindowIndicator, { direction: "down", count: window.below })
6949
+ ] });
6776
6950
  }
6777
- async function stopReadingTerminal() {
6778
- await new Promise((resolve10) => setImmediate(resolve10));
6779
- const handle = getTerminalHandle();
6780
- if (!handle?.readStop) return;
6781
- handle.reading = false;
6782
- handle.readStop();
6951
+
6952
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/panels/cycles-panel.tsx
6953
+ import { Box as Box12, Text as Text13 } from "ink";
6954
+ import figures2 from "figures";
6955
+ import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
6956
+ function cycleLabel(cycle, index) {
6957
+ const parts = [];
6958
+ for (let i = 0; i < cycle.edges.length; i++) {
6959
+ parts.push(cycle.path[i]);
6960
+ parts.push(`[${cycle.edges[i].slotName}]`);
6961
+ }
6962
+ parts.push(cycle.path[cycle.path.length - 1]);
6963
+ return `Cycle ${index + 1}: ${parts.join(" \u2192 ")}`;
6783
6964
  }
6784
- function startReadingTerminal() {
6785
- const handle = getTerminalHandle();
6786
- if (!handle?.readStart) return;
6787
- handle.reading = true;
6788
- handle.readStart();
6965
+ function CyclesPanel({ cycles, cursor }) {
6966
+ return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", borderStyle: "single", borderColor: PALETTE2.warning, paddingX: 1, marginTop: 1, children: [
6967
+ /* @__PURE__ */ jsx15(Text13, { bold: true, color: PALETTE2.warning, children: `Cycles detected (${cycles.length}):` }),
6968
+ /* @__PURE__ */ jsx15(Text13, { children: " " }),
6969
+ cycles.map((cycle, i) => {
6970
+ const isCursor = i === cursor;
6971
+ return /* @__PURE__ */ jsxs12(Text13, { children: [
6972
+ isCursor ? /* @__PURE__ */ jsx15(Text13, { color: PALETTE2.info, bold: true, children: figures2.pointer }) : /* @__PURE__ */ jsx15(Text13, { children: " " }),
6973
+ /* @__PURE__ */ jsx15(Text13, { color: PALETTE2.warning, inverse: isCursor, children: " " + cycleLabel(cycle, i) })
6974
+ ] }, i);
6975
+ }),
6976
+ /* @__PURE__ */ jsx15(Text13, { children: "[\u2191/\u2193] move \xB7 [Enter] jump \xB7 [c/Esc] close" })
6977
+ ] });
6789
6978
  }
6790
6979
 
6791
- // packages/experience-design-system-cli/src/tui/help/PageContainer.tsx
6792
- import { useEffect as useEffect6, useState as useState9 } from "react";
6793
- import { Box as Box10, Text as Text11, useInput as useInput9 } from "ink";
6980
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/panels/reject-prompt.tsx
6981
+ import { Box as Box13, Text as Text14 } from "ink";
6982
+ import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
6983
+ function RejectPrompt({ pending }) {
6984
+ return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", borderStyle: "single", borderColor: PALETTE2.warning, paddingX: 1, marginTop: 1, children: [
6985
+ /* @__PURE__ */ jsx16(Text14, { bold: true, color: PALETTE2.warning, children: `Rejecting ${pending.target} will:` }),
6986
+ pending.ancestors.length > 0 && /* @__PURE__ */ jsx16(Text14, { children: `- Reject ancestors: ${pending.ancestors.join(", ")}` }),
6987
+ pending.descendants.length > 0 && /* @__PURE__ */ jsx16(Text14, { children: `- Deselect descendants: ${pending.descendants.join(", ")}` }),
6988
+ /* @__PURE__ */ jsx16(Text14, { children: "[y] confirm \xB7 [n]/[Esc] cancel" })
6989
+ ] });
6990
+ }
6794
6991
 
6795
- // packages/experience-design-system-cli/src/tui/debug-store.ts
6796
- import { mkdir as mkdir3, writeFile as writeFile3 } from "node:fs/promises";
6797
- import { existsSync as existsSync5, readdirSync as readdirSync2 } from "node:fs";
6798
- import { join as join12 } from "node:path";
6992
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/CompactControlBar.tsx
6993
+ import { Box as Box14 } from "ink";
6799
6994
 
6800
- // packages/experience-design-system-cli/src/tui/settings/debug-mode/debug-mode-store.ts
6801
- var DEFAULT_DEBUG_MODE_SETTING = {
6802
- enabled: true
6803
- };
6804
- async function readDebugModeSetting() {
6805
- const { debugMode } = await readSettings2();
6806
- return { ...DEFAULT_DEBUG_MODE_SETTING, ...debugMode };
6995
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/LegendEntry.tsx
6996
+ import { Text as Text15 } from "ink";
6997
+ import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
6998
+ function legendEntry(keyBracket, label, active = false) {
6999
+ return /* @__PURE__ */ jsxs14(Text15, { children: [
7000
+ /* @__PURE__ */ jsx17(Text15, { color: active ? PALETTE2.warning : PALETTE2.info, inverse: active, children: keyBracket }),
7001
+ /* @__PURE__ */ jsx17(Text15, { color: active ? PALETTE2.warning : void 0, inverse: active, children: " " + label })
7002
+ ] }, keyBracket + label);
7003
+ }
7004
+
7005
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/CompactControlBar.tsx
7006
+ import { jsxs as jsxs15 } from "react/jsx-runtime";
7007
+ function CompactControlBar({ hasGroupRoots, searchActive }) {
7008
+ return /* @__PURE__ */ jsxs15(Box14, { borderStyle: "single", borderColor: PALETTE2.border, paddingX: 1, flexWrap: "wrap", columnGap: 2, children: [
7009
+ legendEntry("[\u2191/\u2193]", "move"),
7010
+ legendEntry("[a/r]", "accept/reject"),
7011
+ legendEntry("[f]", "continue/finalize"),
7012
+ hasGroupRoots && legendEntry("[space/E/C]", "expand/collapse"),
7013
+ legendEntry("[/]", "search", searchActive),
7014
+ legendEntry("[h]", "help"),
7015
+ legendEntry("[q]", "quit")
7016
+ ] });
6807
7017
  }
6808
- async function writeDebugModeSetting(setting) {
6809
- await updateSettings2({ debugMode: setting });
7018
+
7019
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/CounterStrip.tsx
7020
+ import { Box as Box15, Text as Text16 } from "ink";
7021
+ import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
7022
+ function CounterStrip(props) {
7023
+ const { counters, totalWidth } = props;
7024
+ const condensed = totalWidth < 60;
7025
+ const labelGrp = condensed ? "Cmp" : "Components with Slots";
7026
+ const labelRej = condensed ? "Rej" : "Rejected";
7027
+ const labelUnd = condensed ? "Und" : "Undecided";
7028
+ const sep = condensed ? " | " : " ";
7029
+ return /* @__PURE__ */ jsx18(Box15, { children: /* @__PURE__ */ jsxs16(Text16, { children: [
7030
+ /* @__PURE__ */ jsxs16(Text16, { color: PALETTE2.muted, children: [
7031
+ labelGrp,
7032
+ " "
7033
+ ] }),
7034
+ /* @__PURE__ */ jsx18(Text16, { bold: true, children: counters.groups }),
7035
+ /* @__PURE__ */ jsx18(Text16, { color: PALETTE2.muted, children: sep }),
7036
+ /* @__PURE__ */ jsxs16(Text16, { color: PALETTE2.muted, children: [
7037
+ labelRej,
7038
+ " "
7039
+ ] }),
7040
+ /* @__PURE__ */ jsx18(Text16, { bold: true, children: counters.rejected }),
7041
+ /* @__PURE__ */ jsx18(Text16, { color: PALETTE2.muted, children: sep }),
7042
+ /* @__PURE__ */ jsxs16(Text16, { color: PALETTE2.muted, children: [
7043
+ labelUnd,
7044
+ " "
7045
+ ] }),
7046
+ /* @__PURE__ */ jsx18(Text16, { bold: true, children: counters.undecided }),
7047
+ /* @__PURE__ */ jsx18(Text16, { color: PALETTE2.muted, children: sep })
7048
+ ] }) });
7049
+ }
7050
+
7051
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/GotoBanner.tsx
7052
+ import figures3 from "figures";
7053
+ import { Box as Box16, Text as Text17 } from "ink";
7054
+ import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
7055
+ var DEFAULT_MAX_ROWS = 15;
7056
+ function windowStart(rowCount, highlightIndex, maxRows) {
7057
+ if (rowCount <= maxRows) return 0;
7058
+ const maxStart = rowCount - maxRows;
7059
+ let start = highlightIndex - Math.floor(maxRows / 2);
7060
+ if (start < 0) start = 0;
7061
+ if (start > maxStart) start = maxStart;
7062
+ return start;
7063
+ }
7064
+ function defaultRenderRow(row, index, isCursor) {
7065
+ return /* @__PURE__ */ jsxs17(Text17, { children: [
7066
+ isCursor ? /* @__PURE__ */ jsx19(Text17, { color: PALETTE2.info, bold: true, children: figures3.pointer }) : /* @__PURE__ */ jsx19(Text17, { children: " " }),
7067
+ /* @__PURE__ */ jsx19(Text17, { inverse: isCursor, children: " " + row.label })
7068
+ ] }, index);
7069
+ }
7070
+ function GotoBanner({
7071
+ title,
7072
+ rows,
7073
+ cursor,
7074
+ cursorRowIndex,
7075
+ maxRows = DEFAULT_MAX_ROWS,
7076
+ width,
7077
+ footerHint,
7078
+ renderRow = defaultRenderRow
7079
+ }) {
7080
+ const highlightIndex = cursorRowIndex ?? cursor;
7081
+ const start = windowStart(rows.length, highlightIndex, maxRows);
7082
+ const end = Math.min(rows.length, start + maxRows);
7083
+ const visible = rows.slice(start, end);
7084
+ const moreAbove = start;
7085
+ const moreBelow = rows.length - end;
7086
+ return /* @__PURE__ */ jsxs17(
7087
+ Box16,
7088
+ {
7089
+ flexDirection: "column",
7090
+ borderStyle: "single",
7091
+ borderColor: PALETTE2.info,
7092
+ paddingX: 1,
7093
+ marginTop: width === void 0 ? 1 : 0,
7094
+ width,
7095
+ flexShrink: 0,
7096
+ children: [
7097
+ /* @__PURE__ */ jsx19(Text17, { bold: true, children: title }),
7098
+ moreAbove > 0 && /* @__PURE__ */ jsx19(Text17, { color: PALETTE2.muted, children: ` \u25B2 ${moreAbove} more` }),
7099
+ visible.map((row, vi) => {
7100
+ const i = start + vi;
7101
+ return renderRow(row, i, i === highlightIndex);
7102
+ }),
7103
+ moreBelow > 0 && /* @__PURE__ */ jsx19(Text17, { color: PALETTE2.muted, children: ` \u25BC ${moreBelow} more` }),
7104
+ footerHint !== void 0 && /* @__PURE__ */ jsx19(Text17, { color: PALETTE2.muted, children: footerHint })
7105
+ ]
7106
+ }
7107
+ );
6810
7108
  }
6811
7109
 
6812
- // packages/experience-design-system-cli/src/tui/debug-store.ts
6813
- var pendingRun;
6814
- function generateRunId() {
6815
- const now = /* @__PURE__ */ new Date();
6816
- const pad = (n) => String(n).padStart(2, "0");
6817
- return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
7110
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/GroupedSidebar.tsx
7111
+ import figures4 from "figures";
7112
+ import { Box as Box17, Text as Text19 } from "ink";
7113
+
7114
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/graph/cycle-detection.ts
7115
+ function buildGraph(components) {
7116
+ const nodes = [];
7117
+ const seen = /* @__PURE__ */ new Set();
7118
+ for (const c2 of components) {
7119
+ if (seen.has(c2.name)) continue;
7120
+ seen.add(c2.name);
7121
+ nodes.push(c2.name);
7122
+ }
7123
+ const adjacency = /* @__PURE__ */ new Map();
7124
+ for (const node of nodes) adjacency.set(node, []);
7125
+ for (const comp of components) {
7126
+ const outgoing = adjacency.get(comp.name);
7127
+ if (!outgoing) continue;
7128
+ for (const slot of comp.slots) {
7129
+ const allowed = slot.allowedComponents ?? [];
7130
+ for (const target of allowed) {
7131
+ if (!seen.has(target)) continue;
7132
+ outgoing.push({ target, slotName: slot.name });
7133
+ }
7134
+ }
7135
+ }
7136
+ return { nodes, adjacency };
7137
+ }
7138
+ function stronglyConnectedComponents2(nodes, adjacency) {
7139
+ const index = /* @__PURE__ */ new Map();
7140
+ const lowlink = /* @__PURE__ */ new Map();
7141
+ const onStack = /* @__PURE__ */ new Set();
7142
+ const stack = [];
7143
+ const sccs = [];
7144
+ let counter = 0;
7145
+ const nodeSet = new Set(nodes);
7146
+ function strongconnect(v) {
7147
+ index.set(v, counter);
7148
+ lowlink.set(v, counter);
7149
+ counter += 1;
7150
+ stack.push(v);
7151
+ onStack.add(v);
7152
+ const neighbours = adjacency.get(v) ?? [];
7153
+ for (const { target } of neighbours) {
7154
+ if (!nodeSet.has(target)) continue;
7155
+ if (!index.has(target)) {
7156
+ strongconnect(target);
7157
+ lowlink.set(v, Math.min(lowlink.get(v), lowlink.get(target)));
7158
+ } else if (onStack.has(target)) {
7159
+ lowlink.set(v, Math.min(lowlink.get(v), index.get(target)));
7160
+ }
7161
+ }
7162
+ if (lowlink.get(v) === index.get(v)) {
7163
+ const scc = [];
7164
+ let w;
7165
+ do {
7166
+ w = stack.pop();
7167
+ onStack.delete(w);
7168
+ scc.push(w);
7169
+ } while (w !== v);
7170
+ sccs.push(scc);
7171
+ }
7172
+ }
7173
+ for (const node of nodes) {
7174
+ if (!index.has(node)) strongconnect(node);
7175
+ }
7176
+ return sccs;
7177
+ }
7178
+ function makeCycle(path5, edges) {
7179
+ return { path: [...path5, path5[0]], edges: [...edges] };
7180
+ }
7181
+ function findSlotCycles3(components) {
7182
+ if (components.length === 0) return [];
7183
+ const { nodes, adjacency } = buildGraph(components);
7184
+ if (nodes.length === 0) return [];
7185
+ const cycles = [];
7186
+ for (const node of nodes) {
7187
+ const outgoing = adjacency.get(node) ?? [];
7188
+ for (const edge of outgoing) {
7189
+ if (edge.target === node) {
7190
+ cycles.push({
7191
+ path: [node, node],
7192
+ edges: [{ fromComponent: node, slotName: edge.slotName, toComponent: node }]
7193
+ });
7194
+ }
7195
+ }
7196
+ }
7197
+ const nodeOrder = [...nodes].sort();
7198
+ let remaining = [...nodeOrder];
7199
+ while (remaining.length > 0) {
7200
+ let unblock2 = function(u) {
7201
+ blocked.delete(u);
7202
+ const dependents = blockedMap.get(u);
7203
+ if (!dependents) return;
7204
+ for (const w of dependents) {
7205
+ if (blocked.has(w)) unblock2(w);
7206
+ }
7207
+ dependents.clear();
7208
+ }, circuit2 = function(v, root) {
7209
+ let foundCycle = false;
7210
+ pathStack.push(v);
7211
+ blocked.add(v);
7212
+ const outgoing = adjacency.get(v) ?? [];
7213
+ for (const { target: w, slotName } of outgoing) {
7214
+ if (!sccSet.has(w)) continue;
7215
+ edgeStack.push({ fromComponent: v, slotName, toComponent: w });
7216
+ if (w === root) {
7217
+ cycles.push(makeCycle(pathStack, edgeStack));
7218
+ foundCycle = true;
7219
+ } else if (!blocked.has(w)) {
7220
+ if (circuit2(w, root)) foundCycle = true;
7221
+ }
7222
+ edgeStack.pop();
7223
+ }
7224
+ if (foundCycle) {
7225
+ unblock2(v);
7226
+ } else {
7227
+ for (const { target: w } of outgoing) {
7228
+ if (!sccSet.has(w)) continue;
7229
+ let deps = blockedMap.get(w);
7230
+ if (!deps) {
7231
+ deps = /* @__PURE__ */ new Set();
7232
+ blockedMap.set(w, deps);
7233
+ }
7234
+ deps.add(v);
7235
+ }
7236
+ }
7237
+ pathStack.pop();
7238
+ return foundCycle;
7239
+ };
7240
+ var unblock = unblock2, circuit = circuit2;
7241
+ const subgraphNodes = remaining;
7242
+ const sccs = stronglyConnectedComponents2(subgraphNodes, adjacency).filter((scc) => {
7243
+ if (scc.length > 1) return true;
7244
+ return false;
7245
+ });
7246
+ if (sccs.length === 0) break;
7247
+ let startNode = null;
7248
+ let startScc = null;
7249
+ for (const scc of sccs) {
7250
+ const min = [...scc].sort()[0];
7251
+ if (startNode === null || min < startNode) {
7252
+ startNode = min;
7253
+ startScc = scc;
7254
+ }
7255
+ }
7256
+ if (startNode === null || startScc === null) break;
7257
+ const sccSet = new Set(startScc);
7258
+ const blocked = /* @__PURE__ */ new Set();
7259
+ const blockedMap = /* @__PURE__ */ new Map();
7260
+ const pathStack = [];
7261
+ const edgeStack = [];
7262
+ circuit2(startNode, startNode);
7263
+ remaining = remaining.filter((n) => n !== startNode);
7264
+ }
7265
+ return cycles;
6818
7266
  }
6819
- function datePrefix(now = /* @__PURE__ */ new Date()) {
6820
- const pad = (n) => String(n).padStart(2, "0");
6821
- return `${pad(now.getMonth() + 1)}-${pad(now.getDate())}-${now.getFullYear()}`;
7267
+
7268
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/graph/composite-closure.ts
7269
+ function edgesFrom(component, known) {
7270
+ if (!component) return [];
7271
+ const out = [];
7272
+ const seen = /* @__PURE__ */ new Set();
7273
+ for (const slot of component.slots) {
7274
+ for (const target of slot.allowedComponents ?? []) {
7275
+ if (!known.has(target)) continue;
7276
+ if (seen.has(target)) continue;
7277
+ seen.add(target);
7278
+ out.push(target);
7279
+ }
7280
+ }
7281
+ return out.sort();
7282
+ }
7283
+ function collectDependents(components) {
7284
+ const known = new Set(components.map((c2) => c2.name));
7285
+ const dependents = /* @__PURE__ */ new Set();
7286
+ for (const c2 of components) {
7287
+ for (const slot of c2.slots) {
7288
+ for (const target of slot.allowedComponents ?? []) {
7289
+ if (known.has(target) && target !== c2.name) dependents.add(target);
7290
+ }
7291
+ }
7292
+ }
7293
+ return dependents;
6822
7294
  }
6823
- function slugify(value) {
6824
- return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
7295
+ function findRoots(components, selected) {
7296
+ const scope = selected ? components.filter((c2) => selected.has(c2.name)) : components;
7297
+ const dependents = collectDependents(scope);
7298
+ return scope.map((c2) => c2.name).filter((name) => !dependents.has(name)).sort();
6825
7299
  }
6826
- function generateSessionId3() {
6827
- const today = datePrefix();
6828
- const root = debugSessionsDir2();
6829
- const existing = existsSync5(root) ? readdirSync2(root) : [];
6830
- const seqPattern = new RegExp(`^${today}-session-(\\d+)$`);
6831
- const maxSeq = existing.reduce((max, entry) => {
6832
- const match = seqPattern.exec(entry);
6833
- return match ? Math.max(max, Number(match[1])) : max;
6834
- }, 0);
6835
- return `${today}-session-${maxSeq + 1}`;
7300
+ function findCycleInClosure(root, reachable, components) {
7301
+ const scopedComponents = components.filter((c2) => reachable.has(c2.name)).map((c2) => ({ name: c2.name, slots: c2.slots }));
7302
+ const cycles = findSlotCycles3(scopedComponents);
7303
+ if (cycles.length === 0) return null;
7304
+ const involvesRoot = cycles.find((cycle) => cycle.path.includes(root));
7305
+ const picked = involvesRoot ?? cycles[0];
7306
+ return picked.path;
6836
7307
  }
6837
- var SESSION_ID = generateSessionId3();
6838
- function sessionDebugDir() {
6839
- return join12(debugSessionsDir2(), SESSION_ID);
7308
+ function walkReachable2(root, byName, known) {
7309
+ const reachable = /* @__PURE__ */ new Set();
7310
+ const stack = [root];
7311
+ while (stack.length > 0) {
7312
+ const cur = stack.pop();
7313
+ if (reachable.has(cur)) continue;
7314
+ reachable.add(cur);
7315
+ for (const next of edgesFrom(byName.get(cur), known)) {
7316
+ if (!reachable.has(next)) stack.push(next);
7317
+ }
7318
+ }
7319
+ return reachable;
6840
7320
  }
6841
- function currentDebugSessionDir() {
6842
- return sessionDebugDir();
7321
+ function computeClosure(root, components) {
7322
+ const known = new Set(components.map((c2) => c2.name));
7323
+ const byName = new Map(components.map((c2) => [c2.name, c2]));
7324
+ if (!known.has(root)) {
7325
+ return {
7326
+ root,
7327
+ nodes: [{ name: root, depth: 0, path: [root], parents: [] }],
7328
+ containsCycle: false
7329
+ };
7330
+ }
7331
+ const reachable = walkReachable2(root, byName, known);
7332
+ const cyclePath = findCycleInClosure(root, reachable, components);
7333
+ if (cyclePath) {
7334
+ const nodes2 = [...reachable].sort().map((name) => ({
7335
+ name,
7336
+ depth: name === root ? 0 : 1,
7337
+ path: [root],
7338
+ parents: []
7339
+ }));
7340
+ return { root, nodes: nodes2, containsCycle: true, cyclePath };
7341
+ }
7342
+ const depth = /* @__PURE__ */ new Map();
7343
+ const parentPath = /* @__PURE__ */ new Map();
7344
+ const parents = /* @__PURE__ */ new Map();
7345
+ depth.set(root, 0);
7346
+ parentPath.set(root, [root]);
7347
+ parents.set(root, /* @__PURE__ */ new Set());
7348
+ const queue = [root];
7349
+ while (queue.length > 0) {
7350
+ const cur = queue.shift();
7351
+ const curDepth = depth.get(cur);
7352
+ const curPath = parentPath.get(cur);
7353
+ for (const next of edgesFrom(byName.get(cur), known)) {
7354
+ if (!parents.has(next)) parents.set(next, /* @__PURE__ */ new Set());
7355
+ parents.get(next).add(cur);
7356
+ const nextDepth = curDepth + 1;
7357
+ const existingDepth = depth.get(next);
7358
+ const nextPath = [...curPath, next];
7359
+ if (existingDepth === void 0 || nextDepth < existingDepth) {
7360
+ depth.set(next, nextDepth);
7361
+ parentPath.set(next, nextPath);
7362
+ queue.push(next);
7363
+ } else if (nextDepth === existingDepth) {
7364
+ const existingPath = parentPath.get(next);
7365
+ if (nextPath.join("\0") < existingPath.join("\0")) {
7366
+ parentPath.set(next, nextPath);
7367
+ }
7368
+ }
7369
+ }
7370
+ }
7371
+ const nodes = [];
7372
+ for (const [name, d] of depth.entries()) {
7373
+ nodes.push({
7374
+ name,
7375
+ depth: d,
7376
+ path: parentPath.get(name),
7377
+ parents: [...parents.get(name) ?? /* @__PURE__ */ new Set()].sort()
7378
+ });
7379
+ }
7380
+ nodes.sort((a, b) => a.depth - b.depth || a.name.localeCompare(b.name));
7381
+ return { root, nodes, containsCycle: false };
6843
7382
  }
6844
- void isDebugModeEnabled().then((enabled) => {
6845
- if (!enabled) return void 0;
6846
- return mkdir3(sessionDebugDir(), { recursive: true });
6847
- });
6848
- async function isDebugModeEnabled() {
6849
- try {
6850
- return (await readDebugModeSetting()).enabled;
6851
- } catch {
6852
- return true;
7383
+ function computeAllClosures(components, selected) {
7384
+ const roots = findRoots(components, selected);
7385
+ const scope = selected ? components.filter((c2) => selected.has(c2.name)) : components;
7386
+ const out = /* @__PURE__ */ new Map();
7387
+ for (const root of roots) out.set(root, computeClosure(root, scope));
7388
+ return out;
7389
+ }
7390
+ function findSharedDeps(closures) {
7391
+ const counts = /* @__PURE__ */ new Map();
7392
+ for (const [root, closure] of closures.entries()) {
7393
+ for (const node of closure.nodes) {
7394
+ if (node.name === root) continue;
7395
+ if (!counts.has(node.name)) counts.set(node.name, []);
7396
+ counts.get(node.name).push(root);
7397
+ }
6853
7398
  }
7399
+ const out = /* @__PURE__ */ new Map();
7400
+ for (const [name, roots] of counts.entries()) {
7401
+ if (roots.length >= 2) out.set(name, [...roots].sort());
7402
+ }
7403
+ return out;
6854
7404
  }
6855
- function redact(value) {
6856
- const clone = { ...value };
6857
- if ("cma_token" in clone) {
6858
- const raw = clone.cma_token;
6859
- clone.cma_token = typeof raw === "string" && raw.length > 0 ? `[present, ${raw.length} chars]` : "[not set]";
7405
+
7406
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/badge.tsx
7407
+ import { Text as Text18 } from "ink";
7408
+ import { jsx as jsx20 } from "react/jsx-runtime";
7409
+ function previewBadge(annotation) {
7410
+ switch (annotation) {
7411
+ case "new":
7412
+ return { char: "+", color: PALETTE2.success };
7413
+ case "changed":
7414
+ return { char: "~", color: PALETTE2.warning };
7415
+ case "removed":
7416
+ return { char: "-", color: PALETTE2.error, dim: true };
7417
+ case "breaking":
7418
+ return { char: "!", color: PALETTE2.error, bold: true };
7419
+ default:
7420
+ return null;
6860
7421
  }
6861
- return clone;
6862
7422
  }
6863
- function startDebugRun({
6864
- flow,
6865
- step,
6866
- menuOption,
6867
- inputs
7423
+ function PreviewBadge({
7424
+ badge,
7425
+ highlighted = false
6868
7426
  }) {
6869
- const runId = generateRunId();
6870
- const startedAt = Date.now();
6871
- const redactedInputs = redact(inputs);
6872
- isDebugModeEnabled().then((enabled) => {
6873
- if (!enabled) return;
6874
- pendingRun = { flow, step, runId, menuOption, inputs: redactedInputs, startedAt };
6875
- });
7427
+ return badge ? /* @__PURE__ */ jsx20(Text18, { color: !highlighted && badge.dim ? PALETTE2.muted : badge.color, bold: badge.bold, children: badge.char }) : /* @__PURE__ */ jsx20(Text18, { children: " " });
7428
+ }
7429
+
7430
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/GroupedSidebar.tsx
7431
+ import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
7432
+ var GLYPH_EXPAND_COLLAPSED = "\u25B8";
7433
+ var GLYPH_EXPAND_EXPANDED = "\u25BE";
7434
+ var GLYPH_TREE_MID = "\u251C\u2500";
7435
+ var GLYPH_TREE_LAST = "\u2514\u2500";
7436
+ var GLYPH_WARN = "\u26A0";
7437
+ var GLYPH_ERROR = "\u2717";
7438
+ function isEmpty(entry) {
7439
+ return Object.keys(entry.$properties ?? {}).length === 0 && Object.keys(entry.$slots ?? {}).length === 0;
7440
+ }
7441
+ function allowedComponentNames(entry) {
7442
+ const names = [];
7443
+ for (const slot of Object.values(entry.$slots ?? {})) {
7444
+ if (!Array.isArray(slot?.$allowedComponents)) continue;
7445
+ names.push(...slot.$allowedComponents.filter((value) => typeof value === "string"));
7446
+ }
7447
+ return names;
7448
+ }
7449
+ function aggregateGlyphFor(closure, statusByName) {
7450
+ let worst = "ok";
7451
+ for (const node of closure.nodes) {
7452
+ const s = statusByName.get(node.name);
7453
+ if (!s) continue;
7454
+ if (s === "error") {
7455
+ worst = "error";
7456
+ break;
7457
+ }
7458
+ if (s === "warning") worst = "warning";
7459
+ }
7460
+ if (worst === "error") return GLYPH_ERROR;
7461
+ if (worst === "warning") return GLYPH_WARN;
7462
+ return null;
6876
7463
  }
6877
- async function finishDebugRun({
6878
- outputs,
6879
- status,
6880
- exitMethod
6881
- }) {
6882
- const run2 = pendingRun;
7464
+ function buildVisibleRows(props) {
7465
+ const { items, cycleParticipants, alwaysExpanded, showFlatTier, viewMode, graph, filterVisibleKeys } = props;
7466
+ if (viewMode === "flat") {
7467
+ const rows2 = [];
7468
+ if (items.length === 0) return rows2;
7469
+ const itemByKey2 = new Map(items.map((it, idx) => [it.key, { it, idx }]));
7470
+ const cycleKeys2 = [];
7471
+ const otherKeys2 = [];
7472
+ for (const it of items) {
7473
+ if (cycleParticipants.has(it.key)) cycleKeys2.push(it.key);
7474
+ else otherKeys2.push(it.key);
7475
+ }
7476
+ cycleKeys2.sort();
7477
+ otherKeys2.sort();
7478
+ const otherKeySet2 = new Set(otherKeys2);
7479
+ const flatGraph = graph.filter((n) => otherKeySet2.has(n.name));
7480
+ const closures2 = computeAllClosures(flatGraph);
7481
+ const depCountByKey = /* @__PURE__ */ new Map();
7482
+ for (const [name, closure] of closures2) {
7483
+ if (closure.nodes.length > 1) depCountByKey.set(name, closure.nodes.length - 1);
7484
+ }
7485
+ for (const key of cycleKeys2) {
7486
+ const rec = itemByKey2.get(key);
7487
+ if (!rec) continue;
7488
+ rows2.push({
7489
+ kind: "cycle",
7490
+ key: `cycle:${key}`,
7491
+ label: `${GLYPH_WARN} ${key} (cycle)`,
7492
+ indent: 0,
7493
+ itemIdx: rec.idx
7494
+ });
7495
+ }
7496
+ for (const key of otherKeys2) {
7497
+ const rec = itemByKey2.get(key);
7498
+ if (!rec) continue;
7499
+ const dep = depCountByKey.get(key);
7500
+ const suffix = dep !== void 0 ? ` (${dep} dep${dep === 1 ? "" : "s"})` : "";
7501
+ rows2.push({
7502
+ kind: "flat",
7503
+ key: `flat:${key}`,
7504
+ label: `${key}${suffix}`,
7505
+ indent: 0,
7506
+ itemIdx: rec.idx
7507
+ });
7508
+ }
7509
+ return rows2;
7510
+ }
7511
+ const rows = [];
7512
+ if (items.length === 0) return rows;
7513
+ const itemByKey = new Map(items.map((it, idx) => [it.key, { it, idx }]));
7514
+ const statusByName = new Map(items.map((it) => [it.key, it.status]));
7515
+ const cycleKeys = [];
7516
+ const emptyKeys = [];
7517
+ const otherKeys = [];
7518
+ for (const it of items) {
7519
+ if (cycleParticipants.has(it.key)) cycleKeys.push(it.key);
7520
+ else if (isEmpty(it.entry)) emptyKeys.push(it.key);
7521
+ else otherKeys.push(it.key);
7522
+ }
7523
+ cycleKeys.sort();
7524
+ emptyKeys.sort();
7525
+ const seenCycleTierChildOccurrence = /* @__PURE__ */ new Set();
7526
+ const computeCycleMemberSubtree = (root) => {
7527
+ const out = [];
7528
+ const visited = /* @__PURE__ */ new Set([root]);
7529
+ const queue = [{ name: root, depth: 0 }];
7530
+ while (queue.length > 0) {
7531
+ const cur = queue.shift();
7532
+ const parentItem = itemByKey.get(cur.name)?.it;
7533
+ if (!parentItem) continue;
7534
+ const slotTargets2 = [];
7535
+ const seenTarget = /* @__PURE__ */ new Set();
7536
+ for (const target of allowedComponentNames(parentItem.entry)) {
7537
+ if (!itemByKey.has(target)) continue;
7538
+ if (seenTarget.has(target)) continue;
7539
+ seenTarget.add(target);
7540
+ slotTargets2.push(target);
7541
+ }
7542
+ slotTargets2.sort();
7543
+ for (const target of slotTargets2) {
7544
+ if (visited.has(target)) continue;
7545
+ visited.add(target);
7546
+ const isCycleMember = cycleParticipants.has(target);
7547
+ out.push({ name: target, depth: cur.depth + 1, isCycleMember });
7548
+ queue.push({ name: target, depth: cur.depth + 1 });
7549
+ }
7550
+ }
7551
+ return out;
7552
+ };
7553
+ for (const key of cycleKeys) {
7554
+ const rec = itemByKey.get(key);
7555
+ if (!rec) continue;
7556
+ const expanded = alwaysExpanded ? true : props.expandedGroups.has(key);
7557
+ const glyphExpand = expanded ? GLYPH_EXPAND_EXPANDED : GLYPH_EXPAND_COLLAPSED;
7558
+ rows.push({
7559
+ kind: "cycle",
7560
+ key: `cycle:${key}`,
7561
+ label: `${glyphExpand} ${GLYPH_WARN} ${key} (cycle)`,
7562
+ indent: 0,
7563
+ itemIdx: rec.idx,
7564
+ rootName: key
7565
+ });
7566
+ if (!expanded) continue;
7567
+ const subtree = computeCycleMemberSubtree(key);
7568
+ const isLastAtDepthSubtree = (idx) => {
7569
+ const own = subtree[idx].depth;
7570
+ for (let j = idx + 1; j < subtree.length; j++) {
7571
+ const d = subtree[j].depth;
7572
+ if (d < own) return true;
7573
+ if (d === own) return false;
7574
+ }
7575
+ return true;
7576
+ };
7577
+ subtree.forEach((child, i) => {
7578
+ const isLast = isLastAtDepthSubtree(i);
7579
+ const glyph = isLast ? GLYPH_TREE_LAST : GLYPH_TREE_MID;
7580
+ let sharedSuffix = false;
7581
+ if (seenCycleTierChildOccurrence.has(child.name)) sharedSuffix = true;
7582
+ else seenCycleTierChildOccurrence.add(child.name);
7583
+ const childRec = itemByKey.get(child.name);
7584
+ const indent = " ".repeat(Math.max(0, child.depth - 1));
7585
+ const labelName = child.isCycleMember ? `${GLYPH_WARN} ${child.name} (cycle)` : child.name;
7586
+ rows.push({
7587
+ kind: "group-child",
7588
+ key: `cycle-child:${key}:${child.name}`,
7589
+ label: `${indent}${glyph} ${labelName}${sharedSuffix ? " (shared)" : ""}`,
7590
+ indent: child.depth,
7591
+ sharedSuffix,
7592
+ cycleChild: child.isCycleMember || void 0,
7593
+ itemIdx: childRec?.idx ?? -1,
7594
+ rootName: key
7595
+ });
7596
+ });
7597
+ }
7598
+ for (const key of emptyKeys) {
7599
+ const rec = itemByKey.get(key);
7600
+ if (!rec) continue;
7601
+ rows.push({
7602
+ kind: "empty",
7603
+ key: `empty:${key}`,
7604
+ label: `${key} (empty)`,
7605
+ indent: 0,
7606
+ itemIdx: rec.idx
7607
+ });
7608
+ }
7609
+ const otherKeySet = new Set(otherKeys);
7610
+ const subgraph = graph.filter((n) => otherKeySet.has(n.name));
7611
+ const closures = computeAllClosures(subgraph);
7612
+ const sharedDeps = findSharedDeps(closures);
7613
+ const hasCycleDepDirect = (name) => {
7614
+ const it = itemByKey.get(name)?.it;
7615
+ if (!it) return false;
7616
+ for (const target of allowedComponentNames(it.entry)) {
7617
+ if (cycleParticipants.has(target)) return true;
7618
+ }
7619
+ return false;
7620
+ };
7621
+ const rootNames = [...closures.keys()].sort();
7622
+ const standaloneRoots = [];
7623
+ const groupRoots = [];
7624
+ for (const root of rootNames) {
7625
+ const c2 = closures.get(root);
7626
+ const promotesForCycle = hasCycleDepDirect(root);
7627
+ if (c2.nodes.length <= 1 && !promotesForCycle) standaloneRoots.push(root);
7628
+ else groupRoots.push(root);
7629
+ }
7630
+ const seenSharedOccurrence = /* @__PURE__ */ new Set();
7631
+ const seenCycleChildOccurrence = /* @__PURE__ */ new Set();
7632
+ for (const root of groupRoots) {
7633
+ const closure = closures.get(root);
7634
+ let injectedCycleCount = 0;
7635
+ const seenInject = /* @__PURE__ */ new Set();
7636
+ const countInjections = (parentName) => {
7637
+ const parentItem = itemByKey.get(parentName)?.it;
7638
+ if (!parentItem) return;
7639
+ for (const target of allowedComponentNames(parentItem.entry)) {
7640
+ if (!cycleParticipants.has(target)) continue;
7641
+ const key = `${parentName}\u2192${target}`;
7642
+ if (seenInject.has(key)) continue;
7643
+ seenInject.add(key);
7644
+ injectedCycleCount += 1;
7645
+ }
7646
+ };
7647
+ countInjections(root);
7648
+ for (const n of closure.nodes) if (n.name !== root) countInjections(n.name);
7649
+ const depCount = closure.nodes.length - 1 + injectedCycleCount;
7650
+ const expanded = alwaysExpanded ? true : props.expandedGroups.has(root);
7651
+ const glyphExpand = expanded ? GLYPH_EXPAND_EXPANDED : GLYPH_EXPAND_COLLAPSED;
7652
+ const aggregate = expanded ? null : aggregateGlyphFor(closure, statusByName);
7653
+ const rec = itemByKey.get(root);
7654
+ rows.push({
7655
+ kind: "group-root",
7656
+ key: `root:${root}`,
7657
+ label: `${glyphExpand} ${root} (${depCount} dep${depCount === 1 ? "" : "s"})${aggregate ? " " + aggregate : ""}`,
7658
+ indent: 0,
7659
+ aggregateGlyph: aggregate,
7660
+ itemIdx: rec.idx,
7661
+ rootName: root
7662
+ });
7663
+ if (!expanded) continue;
7664
+ const closureChildren = closure.nodes.filter((n) => n.name !== root).slice().sort((a, b) => a.depth - b.depth || a.name.localeCompare(b.name));
7665
+ const injectedChildren = [];
7666
+ const emitCycleChildrenOf = (parentName, parentDepth) => {
7667
+ const parentItem = itemByKey.get(parentName)?.it;
7668
+ if (!parentItem) return;
7669
+ const seen = /* @__PURE__ */ new Set();
7670
+ for (const target of allowedComponentNames(parentItem.entry)) {
7671
+ if (!cycleParticipants.has(target)) continue;
7672
+ if (seen.has(target)) continue;
7673
+ seen.add(target);
7674
+ injectedChildren.push({
7675
+ name: target,
7676
+ depth: parentDepth + 1,
7677
+ isCycleChild: true
7678
+ });
7679
+ }
7680
+ };
7681
+ emitCycleChildrenOf(root, 0);
7682
+ for (const c2 of closureChildren) {
7683
+ injectedChildren.push({ name: c2.name, depth: c2.depth, isCycleChild: false });
7684
+ emitCycleChildrenOf(c2.name, c2.depth);
7685
+ }
7686
+ const isLastAtDepth = (idx) => {
7687
+ const own = injectedChildren[idx].depth;
7688
+ for (let j = idx + 1; j < injectedChildren.length; j++) {
7689
+ const d = injectedChildren[j].depth;
7690
+ if (d < own) return true;
7691
+ if (d === own) return false;
7692
+ }
7693
+ return true;
7694
+ };
7695
+ injectedChildren.forEach((child, i) => {
7696
+ const isLast = isLastAtDepth(i);
7697
+ const glyph = isLast ? GLYPH_TREE_LAST : GLYPH_TREE_MID;
7698
+ let sharedSuffix = false;
7699
+ if (child.isCycleChild) {
7700
+ if (seenCycleChildOccurrence.has(child.name)) sharedSuffix = true;
7701
+ else seenCycleChildOccurrence.add(child.name);
7702
+ } else if (sharedDeps.has(child.name)) {
7703
+ if (seenSharedOccurrence.has(child.name)) sharedSuffix = true;
7704
+ else seenSharedOccurrence.add(child.name);
7705
+ }
7706
+ const childRec = itemByKey.get(child.name);
7707
+ const indent = " ".repeat(Math.max(0, child.depth - 1));
7708
+ const labelName = child.isCycleChild ? `${GLYPH_WARN} ${child.name} (cycle)` : child.name;
7709
+ rows.push({
7710
+ kind: "group-child",
7711
+ key: `child:${root}:${child.name}`,
7712
+ label: `${indent}${glyph} ${labelName}${sharedSuffix ? " (shared)" : ""}`,
7713
+ indent: child.depth,
7714
+ sharedSuffix,
7715
+ cycleChild: child.isCycleChild || void 0,
7716
+ itemIdx: childRec?.idx ?? -1,
7717
+ rootName: root
7718
+ });
7719
+ });
7720
+ }
7721
+ for (const name of standaloneRoots) {
7722
+ const rec = itemByKey.get(name);
7723
+ if (!rec) continue;
7724
+ rows.push({
7725
+ kind: "standalone",
7726
+ key: `stand:${name}`,
7727
+ label: name,
7728
+ indent: 0,
7729
+ itemIdx: rec.idx
7730
+ });
7731
+ }
7732
+ const nodeByName = new Map(subgraph.map((n) => [n.name, n]));
7733
+ const sharedLeafNames = [...sharedDeps.keys()].filter((name) => (nodeByName.get(name)?.slots.length ?? 0) === 0).sort();
7734
+ const seenStandaloneNames = new Set(standaloneRoots);
7735
+ for (const name of sharedLeafNames) {
7736
+ if (seenStandaloneNames.has(name)) continue;
7737
+ const rec = itemByKey.get(name);
7738
+ if (!rec) continue;
7739
+ rows.push({
7740
+ kind: "standalone",
7741
+ key: `shared-standalone:${name}`,
7742
+ label: `${name} (shared)`,
7743
+ indent: 0,
7744
+ sharedSuffix: true,
7745
+ itemIdx: rec.idx
7746
+ });
7747
+ }
7748
+ if (showFlatTier) {
7749
+ const flatNames = otherKeys.slice().sort();
7750
+ if (flatNames.length > 0) {
7751
+ rows.push({
7752
+ kind: "flat-header",
7753
+ key: "flat-header",
7754
+ label: "\u2500\u2500 All components \u2500\u2500",
7755
+ indent: 0,
7756
+ itemIdx: -1
7757
+ });
7758
+ for (const name of flatNames) {
7759
+ const rec = itemByKey.get(name);
7760
+ if (!rec) continue;
7761
+ rows.push({
7762
+ kind: "flat",
7763
+ key: `flat:${name}`,
7764
+ label: name,
7765
+ indent: 0,
7766
+ itemIdx: rec.idx
7767
+ });
7768
+ }
7769
+ }
7770
+ }
7771
+ if (filterVisibleKeys !== void 0) {
7772
+ return rows.filter((row) => {
7773
+ if (row.itemIdx < 0) return true;
7774
+ const name = items[row.itemIdx]?.key;
7775
+ if (name === void 0) return true;
7776
+ return filterVisibleKeys.has(name);
7777
+ });
7778
+ }
7779
+ return rows;
7780
+ }
7781
+ function rowColor(row, aggregate) {
7782
+ if (row.kind === "cycle") return PALETTE2.warning;
7783
+ if (row.kind === "group-child" && row.cycleChild) return PALETTE2.warning;
7784
+ if (row.kind === "empty") return PALETTE2.warning;
7785
+ if (row.kind === "group-root" && aggregate === GLYPH_ERROR) return PALETTE2.error;
7786
+ if (row.kind === "group-root" && aggregate === GLYPH_WARN) return PALETTE2.warning;
7787
+ return void 0;
7788
+ }
7789
+ function labelStyleFor(input) {
7790
+ const { row, isCursor, wouldDim } = input;
7791
+ if (isCursor) {
7792
+ return { color: PALETTE2.info, bold: true, dim: false };
7793
+ }
7794
+ return {
7795
+ color: rowColor(row, row.aggregateGlyph),
7796
+ bold: false,
7797
+ dim: wouldDim
7798
+ };
7799
+ }
7800
+ function selectionGlyphStyleFor(selState, isCycleRow) {
7801
+ if (selState === "accepted") {
7802
+ return { glyph: "[\u2713]", color: PALETTE2.success, dim: false, bold: isCycleRow };
7803
+ }
7804
+ if (selState === "rejected") {
7805
+ return { glyph: "[\u2717]", color: PALETTE2.error, dim: false, bold: isCycleRow };
7806
+ }
7807
+ if (selState === "undecided") {
7808
+ return { glyph: "[ ]", color: PALETTE2.muted, dim: !isCycleRow, bold: false };
7809
+ }
7810
+ return { glyph: null, color: void 0, dim: false, bold: false };
7811
+ }
7812
+ function inheritanceGlyphStyleFor(input) {
7813
+ const { status, isOwn, isCursor } = input;
7814
+ if (status === "error") {
7815
+ return { glyph: GLYPH_ERROR, color: PALETTE2.error, dim: !isCursor && !isOwn, bold: isCursor };
7816
+ }
7817
+ if (status === "warning") {
7818
+ return { glyph: GLYPH_WARN, color: PALETTE2.warning, dim: !isCursor && !isOwn, bold: isCursor };
7819
+ }
7820
+ return { glyph: null, color: void 0, dim: false, bold: false };
7821
+ }
7822
+ function GroupedSidebar(props) {
7823
+ const {
7824
+ items,
7825
+ cycleParticipants = /* @__PURE__ */ new Set(),
7826
+ expandedGroups,
7827
+ focused,
7828
+ width,
7829
+ title,
7830
+ wrapLabels = false,
7831
+ selectedIdx,
7832
+ selectedRowIdx,
7833
+ renderStatusByKey,
7834
+ previewAnnotationByKey,
7835
+ scrollOffset,
7836
+ visibleCount,
7837
+ alwaysExpanded,
7838
+ showFlatTier,
7839
+ viewMode,
7840
+ selectionStateByKey,
7841
+ aiFlaggedByKey,
7842
+ dimPredicate,
7843
+ visibleRows: providedRows,
7844
+ graph,
7845
+ filterVisibleKeys
7846
+ } = props;
7847
+ const allRows = providedRows ?? buildVisibleRows({
7848
+ items,
7849
+ cycleParticipants,
7850
+ expandedGroups,
7851
+ alwaysExpanded,
7852
+ showFlatTier,
7853
+ viewMode,
7854
+ graph,
7855
+ filterVisibleKeys
7856
+ });
7857
+ const windowed = scrollOffset !== void 0 && visibleCount !== void 0;
7858
+ const start = windowed ? Math.max(0, scrollOffset ?? 0) : 0;
7859
+ const end = windowed ? start + (visibleCount ?? allRows.length) : allRows.length;
7860
+ const rows = windowed ? allRows.slice(start, end) : allRows;
7861
+ return /* @__PURE__ */ jsxs18(WindowedPanel, { width, height: props.height, title, focused, children: [
7862
+ windowed && /* @__PURE__ */ jsx21(WindowIndicator, { direction: "up", count: start }),
7863
+ rows.map((row, i) => {
7864
+ const absoluteRowIdx = start + i;
7865
+ const isSelected = selectedRowIdx !== void 0 ? absoluteRowIdx === selectedRowIdx && row.itemIdx >= 0 : row.itemIdx >= 0 && row.itemIdx === selectedIdx;
7866
+ const itemName = row.itemIdx >= 0 ? items[row.itemIdx]?.key : void 0;
7867
+ const rs = itemName ? renderStatusByKey?.get(itemName) : void 0;
7868
+ const badge = itemName ? previewBadge(previewAnnotationByKey?.get(itemName)) : null;
7869
+ const showInheritance = rs !== void 0 && row.kind !== "cycle" && row.kind !== "empty" && row.kind !== "group-root";
7870
+ const supportsSelectionGlyph = selectionStateByKey !== void 0 && itemName !== void 0 && (row.kind === "standalone" || row.kind === "group-root" || row.kind === "group-child" || row.kind === "flat" || row.kind === "cycle");
7871
+ const selState = supportsSelectionGlyph ? selectionStateByKey.get(itemName) ?? "undecided" : void 0;
7872
+ const isCycleRow = row.kind === "cycle";
7873
+ const selStyle = selectionGlyphStyleFor(selState, isCycleRow);
7874
+ const selGlyph = selStyle.glyph;
7875
+ const selColor = selStyle.color;
7876
+ const selDim = selStyle.dim;
7877
+ const selBold = selStyle.bold;
7878
+ const aiFlagged = aiFlaggedByKey !== void 0 && itemName !== void 0 && row.kind !== "flat-header" && aiFlaggedByKey.get(itemName) === true;
7879
+ const canDim = dimPredicate !== void 0 && itemName !== void 0 && row.kind !== "cycle" && row.kind !== "group-root" && row.kind !== "flat-header" && dimPredicate(itemName);
7880
+ const isSynthetic = row.kind === "flat-header";
7881
+ const isCursor = isSelected;
7882
+ const wouldDim = row.kind === "flat-header" || row.sharedSuffix === true || canDim;
7883
+ const labelStyle = labelStyleFor({ row, isCursor, wouldDim });
7884
+ const inheritanceStyle = inheritanceGlyphStyleFor({
7885
+ status: showInheritance ? rs?.status : void 0,
7886
+ isOwn: rs?.isOwn ?? false,
7887
+ isCursor
7888
+ });
7889
+ return /* @__PURE__ */ jsxs18(Box17, { children: [
7890
+ isCursor ? /* @__PURE__ */ jsx21(Text19, { color: PALETTE2.info, bold: true, children: figures4.pointer }) : /* @__PURE__ */ jsx21(Text19, { children: " " }),
7891
+ /* @__PURE__ */ jsx21(PreviewBadge, { badge, highlighted: isSelected }),
7892
+ selectionStateByKey !== void 0 && (selGlyph && !isSynthetic ? /* @__PURE__ */ jsx21(Text19, { color: !isSelected && selDim ? PALETTE2.muted : selColor, bold: selBold, children: " " + selGlyph }) : /* @__PURE__ */ jsx21(Text19, { children: " " })),
7893
+ aiFlaggedByKey !== void 0 && (aiFlagged ? /* @__PURE__ */ jsx21(Text19, { color: PALETTE2.warning, bold: true, children: " [\xD7]" }) : /* @__PURE__ */ jsx21(Text19, { children: " " })),
7894
+ /* @__PURE__ */ jsxs18(
7895
+ Text19,
7896
+ {
7897
+ color: isSelected ? PALETTE2.info : labelStyle.dim ? PALETTE2.muted : labelStyle.color,
7898
+ bold: isSelected || labelStyle.bold,
7899
+ inverse: false,
7900
+ underline: isSelected && !focused,
7901
+ wrap: wrapLabels ? "wrap" : "truncate",
7902
+ children: [
7903
+ " ",
7904
+ row.label
7905
+ ]
7906
+ }
7907
+ ),
7908
+ inheritanceStyle.glyph && /* @__PURE__ */ jsx21(Text19, { color: inheritanceStyle.dim ? PALETTE2.muted : inheritanceStyle.color, bold: inheritanceStyle.bold, children: " " + inheritanceStyle.glyph })
7909
+ ] }, row.key);
7910
+ }),
7911
+ windowed && /* @__PURE__ */ jsx21(WindowIndicator, { direction: "down", count: allRows.length - end })
7912
+ ] });
7913
+ }
7914
+
7915
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/HelpOverlay.tsx
7916
+ import React7 from "react";
7917
+ import { Box as Box18, Text as Text20 } from "ink";
7918
+
7919
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/hooks/useImmediateInput.ts
7920
+ import { useLayoutEffect, useRef as useRef3 } from "react";
7921
+ import { useStdin } from "ink";
7922
+ function parseInput(data) {
7923
+ const isShiftTab = data === "\x1B[Z";
7924
+ const key = {
7925
+ upArrow: data === "\x1B[A",
7926
+ downArrow: data === "\x1B[B",
7927
+ leftArrow: data === "\x1B[D",
7928
+ rightArrow: data === "\x1B[C",
7929
+ pageDown: data === "\x1B[6~",
7930
+ pageUp: data === "\x1B[5~",
7931
+ return: data === "\r" || data === "\n",
7932
+ escape: data === "\x1B",
7933
+ ctrl: false,
7934
+ shift: isShiftTab,
7935
+ tab: data === " " || isShiftTab,
7936
+ shiftTab: isShiftTab,
7937
+ backspace: data === "\x7F" || data === "\b",
7938
+ delete: data === "\x1B[3~",
7939
+ meta: data === "\x1B"
7940
+ };
7941
+ let input = data;
7942
+ if (data.length === 1) {
7943
+ const code = data.charCodeAt(0);
7944
+ if (code >= 1 && code <= 26) {
7945
+ key.ctrl = true;
7946
+ input = String.fromCharCode(code + 96);
7947
+ }
7948
+ }
7949
+ if (key.upArrow || key.downArrow || key.leftArrow || key.rightArrow || key.pageUp || key.pageDown || key.return || key.escape || key.tab || key.backspace || key.delete) {
7950
+ if (!key.ctrl) input = "";
7951
+ }
7952
+ return { input, key };
7953
+ }
7954
+ var inputRegistries = /* @__PURE__ */ new WeakMap();
7955
+ function registerInputHandler(stdin, setRawMode, handler) {
7956
+ let registry = inputRegistries.get(stdin);
7957
+ if (!registry) {
7958
+ const handlers = /* @__PURE__ */ new Set();
7959
+ const onData = (data) => {
7960
+ const str = Buffer.isBuffer(data) ? data.toString("utf8") : data;
7961
+ const { input, key } = parseInput(str);
7962
+ for (const registered of [...handlers]) registered(input, key);
7963
+ };
7964
+ registry = { handlers, onData, setRawMode };
7965
+ inputRegistries.set(stdin, registry);
7966
+ setRawMode(true);
7967
+ stdin.on("data", onData);
7968
+ }
7969
+ registry.handlers.add(handler);
7970
+ return () => {
7971
+ const current = inputRegistries.get(stdin);
7972
+ if (!current) return;
7973
+ current.handlers.delete(handler);
7974
+ if (current.handlers.size === 0) {
7975
+ stdin.off("data", current.onData);
7976
+ current.setRawMode(false);
7977
+ inputRegistries.delete(stdin);
7978
+ }
7979
+ };
7980
+ }
7981
+ function useImmediateInput(handler, enabled = true) {
7982
+ const { stdin, setRawMode } = useStdin();
7983
+ const handlerRef = useRef3(handler);
7984
+ handlerRef.current = handler;
7985
+ useLayoutEffect(() => {
7986
+ if (!enabled) return;
7987
+ const unregister = registerInputHandler(stdin, setRawMode, (input, key) => handlerRef.current(input, key));
7988
+ return unregister;
7989
+ }, [enabled, stdin, setRawMode]);
7990
+ }
7991
+
7992
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/hooks/use-terminal-size.ts
7993
+ import { useStdout as useStdout2 } from "ink";
7994
+ import { useEffect as useEffect6, useState as useState9 } from "react";
7995
+ function readTerminalSize(stdout) {
7996
+ return {
7997
+ columns: stdout?.columns ?? 80,
7998
+ rows: stdout?.rows ?? process.stdout.rows ?? 40
7999
+ };
8000
+ }
8001
+ function useTerminalSize() {
8002
+ const { stdout } = useStdout2();
8003
+ const [size, setSize] = useState9(() => readTerminalSize(stdout));
8004
+ useEffect6(() => {
8005
+ const updateSize = () => setSize(readTerminalSize(stdout));
8006
+ stdout?.on("resize", updateSize);
8007
+ updateSize();
8008
+ return () => {
8009
+ stdout?.off("resize", updateSize);
8010
+ };
8011
+ }, [stdout]);
8012
+ return size;
8013
+ }
8014
+
8015
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/HelpOverlay.tsx
8016
+ import { Fragment as Fragment2, jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
8017
+ function HelpOverlay(props) {
8018
+ const { onClose } = props;
8019
+ const { columns: terminalColumns, rows: terminalRows } = useTerminalSize();
8020
+ const panelWidth = Math.max(10, Math.min(64, terminalColumns - 2));
8021
+ const panelHeight = terminalPanelHeight(terminalRows, 2);
8022
+ const titleRule = Math.max(0, Math.floor((panelWidth - 10) / 2));
8023
+ useImmediateInput((input, key) => {
8024
+ if (input === "h" || key.escape) onClose();
8025
+ }, props.handleInput !== false);
8026
+ if (props.sections) {
8027
+ return /* @__PURE__ */ jsxs19(
8028
+ Box18,
8029
+ {
8030
+ flexDirection: "column",
8031
+ borderStyle: "round",
8032
+ padding: 1,
8033
+ width: panelWidth,
8034
+ height: panelHeight,
8035
+ overflowY: "hidden",
8036
+ children: [
8037
+ /* @__PURE__ */ jsx22(Text20, { bold: true, children: "\u2500".repeat(titleRule) + " Help " + "\u2500".repeat(titleRule) }),
8038
+ props.sections.map((section) => /* @__PURE__ */ jsxs19(React7.Fragment, { children: [
8039
+ /* @__PURE__ */ jsx22(Text20, { children: " " }),
8040
+ /* @__PURE__ */ jsx22(Text20, { bold: true, children: section.title }),
8041
+ section.entries.map((entry) => /* @__PURE__ */ jsx22(Text20, { children: entry.keys ? " " + entry.keys.padEnd(16) + " " + entry.label : " " + entry.label }, entry.keys + entry.label))
8042
+ ] }, section.title))
8043
+ ]
8044
+ }
8045
+ );
8046
+ }
8047
+ const mode = props.mode;
8048
+ return /* @__PURE__ */ jsxs19(
8049
+ Box18,
8050
+ {
8051
+ flexDirection: "column",
8052
+ borderStyle: "round",
8053
+ padding: 1,
8054
+ width: panelWidth,
8055
+ height: panelHeight,
8056
+ overflowY: "hidden",
8057
+ children: [
8058
+ /* @__PURE__ */ jsx22(Text20, { bold: true, children: "\u2500".repeat(titleRule) + " Help " + "\u2500".repeat(titleRule) }),
8059
+ /* @__PURE__ */ jsx22(Text20, { children: " " }),
8060
+ /* @__PURE__ */ jsx22(Text20, { bold: true, children: "Navigation" }),
8061
+ /* @__PURE__ */ jsx22(Text20, { children: " \u2191 / k / PgUp Scroll up" }),
8062
+ /* @__PURE__ */ jsx22(Text20, { children: " \u2193 / j / PgDn Scroll down" }),
8063
+ /* @__PURE__ */ jsx22(Text20, { children: " g / Home Jump to top" }),
8064
+ /* @__PURE__ */ jsx22(Text20, { children: " G / End Jump to bottom" }),
8065
+ mode === "review" && /* @__PURE__ */ jsxs19(Fragment2, { children: [
8066
+ /* @__PURE__ */ jsx22(Text20, { children: " " }),
8067
+ /* @__PURE__ */ jsx22(Text20, { bold: true, children: "[Review mode only]" }),
8068
+ /* @__PURE__ */ jsx22(Text20, { children: " Tab Toggle sidebar/detail" }),
8069
+ /* @__PURE__ */ jsx22(Text20, { children: " a Accept component" }),
8070
+ /* @__PURE__ */ jsx22(Text20, { children: " r Reject component" }),
8071
+ /* @__PURE__ */ jsx22(Text20, { children: " e Edit proposal" }),
8072
+ /* @__PURE__ */ jsx22(Text20, { children: " s Toggle source code" }),
8073
+ /* @__PURE__ */ jsx22(Text20, { children: " A Approve all" }),
8074
+ /* @__PURE__ */ jsx22(Text20, { children: " F Open finalize dialog" }),
8075
+ /* @__PURE__ */ jsx22(Text20, { children: " Ctrl+S Save draft" }),
8076
+ /* @__PURE__ */ jsx22(Text20, { children: " Ctrl+Z Undo" }),
8077
+ /* @__PURE__ */ jsx22(Text20, { children: " Ctrl+Y Redo" }),
8078
+ /* @__PURE__ */ jsx22(Text20, { children: " Esc Exit edit / close" })
8079
+ ] }),
8080
+ /* @__PURE__ */ jsx22(Text20, { children: " " }),
8081
+ /* @__PURE__ */ jsx22(Text20, { children: " h Close help" }),
8082
+ /* @__PURE__ */ jsx22(Text20, { children: " q Quit" })
8083
+ ]
8084
+ }
8085
+ );
8086
+ }
8087
+
8088
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/SearchMatchSummary.tsx
8089
+ import { Box as Box19, Text as Text21 } from "ink";
8090
+
8091
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/autocomplete.ts
8092
+ function longestCommonPrefix(names) {
8093
+ if (names.length === 0) return "";
8094
+ let prefixLen = names[0].length;
8095
+ for (let i = 1; i < names.length; i++) {
8096
+ const other = names[i];
8097
+ let j = 0;
8098
+ while (j < prefixLen && j < other.length && names[0][j].toLowerCase() === other[j].toLowerCase()) {
8099
+ j++;
8100
+ }
8101
+ prefixLen = j;
8102
+ if (prefixLen === 0) break;
8103
+ }
8104
+ return names[0].slice(0, prefixLen);
8105
+ }
8106
+ function computeAutocomplete(query, names) {
8107
+ const q = query.toLowerCase();
8108
+ const candidates = names.filter((n) => n.toLowerCase().startsWith(q));
8109
+ if (candidates.length === 0) {
8110
+ return { completion: query, candidates: [] };
8111
+ }
8112
+ if (candidates.length === 1) {
8113
+ return { completion: candidates[0], candidates: [] };
8114
+ }
8115
+ const lcp = longestCommonPrefix(candidates);
8116
+ const completion = lcp.length >= query.length ? lcp : query;
8117
+ const sorted = [...candidates].sort();
8118
+ return { completion, candidates: sorted };
8119
+ }
8120
+
8121
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/sidebar-input.ts
8122
+ function handleSidebarSearchInput(input, key, { query, names, setQuery, setCandidates }) {
8123
+ if (key.tab) {
8124
+ const { completion, candidates } = computeAutocomplete(query, names);
8125
+ setQuery(completion);
8126
+ setCandidates(candidates);
8127
+ return true;
8128
+ }
8129
+ if (key.backspace) {
8130
+ setCandidates([]);
8131
+ setQuery((current) => current.slice(0, -1));
8132
+ return true;
8133
+ }
8134
+ if (input && input.length === 1 && input >= " " && input !== "\r" && input !== "\n") {
8135
+ setCandidates([]);
8136
+ setQuery((current) => current + input);
8137
+ return true;
8138
+ }
8139
+ return false;
8140
+ }
8141
+ function formatSearchMatchSummary(matches, total) {
8142
+ return ` (${matches}/${total} matches)`;
8143
+ }
8144
+
8145
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/SearchMatchSummary.tsx
8146
+ import { Fragment as Fragment3, jsx as jsx23, jsxs as jsxs20 } from "react/jsx-runtime";
8147
+ function SearchMatchSummary({
8148
+ open,
8149
+ query,
8150
+ matches,
8151
+ total,
8152
+ autocompleteCandidates,
8153
+ hidden = false,
8154
+ marginTop
8155
+ }) {
8156
+ if (hidden) return null;
8157
+ return /* @__PURE__ */ jsxs20(Fragment3, { children: [
8158
+ open && /* @__PURE__ */ jsxs20(Box19, { marginTop, flexDirection: "column", children: [
8159
+ /* @__PURE__ */ jsxs20(Text21, { children: [
8160
+ `/${query}`,
8161
+ /* @__PURE__ */ jsx23(Text21, { color: PALETTE2.info, children: "\u258E" }),
8162
+ query && /* @__PURE__ */ jsx23(Text21, { color: PALETTE2.muted, children: formatSearchMatchSummary(matches, total) }),
8163
+ /* @__PURE__ */ jsx23(Text21, { children: " \xB7 [Esc] leave" })
8164
+ ] }),
8165
+ autocompleteCandidates.length > 1 && /* @__PURE__ */ jsx23(Text21, { color: PALETTE2.muted, children: ` possibilities: ${autocompleteCandidates.join(" \xB7 ").slice(0, 120)}` })
8166
+ ] }),
8167
+ !open && query && /* @__PURE__ */ jsx23(Box19, { marginTop, children: /* @__PURE__ */ jsx23(Text21, { children: `/${query}${formatSearchMatchSummary(matches, total)} \xB7 [Esc] clear` }) })
8168
+ ] });
8169
+ }
8170
+
8171
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/sidebar-help.ts
8172
+ function createSidebarViewsHelpSection(includeBreaking) {
8173
+ const entries = [
8174
+ { keys: "L", label: "Flat view" },
8175
+ { keys: "i", label: "Focus lineage" }
8176
+ ];
8177
+ if (includeBreaking) entries.push({ keys: "w", label: "Only breaking" });
8178
+ entries.push(
8179
+ { keys: "o", label: "Only cycles" },
8180
+ { keys: "space", label: "Expand/collapse group" },
8181
+ { keys: "E / C", label: "Expand/collapse all" }
8182
+ );
8183
+ return { title: "Sidebar views", entries };
8184
+ }
8185
+
8186
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/use-scope-gate.ts
8187
+ import { useEffect as useEffect7, useMemo as useMemo2, useRef as useRef4, useState as useState12 } from "react";
8188
+
8189
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/graph/search-neighborhood.ts
8190
+ function computeDirectNeighborhood(matches, graph) {
8191
+ const matchSet = new Set(matches);
8192
+ const out = new Set(matchSet);
8193
+ if (matchSet.size === 0) return out;
8194
+ for (const node of graph) {
8195
+ const targets = [];
8196
+ for (const slot of node.slots) {
8197
+ for (const t of slot.allowedComponents ?? []) targets.push(t);
8198
+ }
8199
+ if (matchSet.has(node.name)) {
8200
+ for (const t of targets) out.add(t);
8201
+ }
8202
+ for (const t of targets) {
8203
+ if (matchSet.has(t)) {
8204
+ out.add(node.name);
8205
+ break;
8206
+ }
8207
+ }
8208
+ }
8209
+ return out;
8210
+ }
8211
+ function findAllAncestors(target, graph) {
8212
+ const out = /* @__PURE__ */ new Set([target]);
8213
+ const parentsOf = /* @__PURE__ */ new Map();
8214
+ for (const node of graph) {
8215
+ for (const slot of node.slots) {
8216
+ for (const child of slot.allowedComponents ?? []) {
8217
+ const list = parentsOf.get(child);
8218
+ if (list) {
8219
+ if (!list.includes(node.name)) list.push(node.name);
8220
+ } else {
8221
+ parentsOf.set(child, [node.name]);
8222
+ }
8223
+ }
8224
+ }
8225
+ }
8226
+ const queue = [target];
8227
+ while (queue.length > 0) {
8228
+ const cur = queue.shift();
8229
+ const parents = parentsOf.get(cur);
8230
+ if (!parents) continue;
8231
+ for (const p of parents) {
8232
+ if (out.has(p)) continue;
8233
+ out.add(p);
8234
+ queue.push(p);
8235
+ }
8236
+ }
8237
+ return out;
8238
+ }
8239
+
8240
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/graph/fuzzy-search.ts
8241
+ function match(query, text) {
8242
+ if (query.length === 0) return { score: 0 };
8243
+ if (text.length === 0) return null;
8244
+ const queryLower = query.toLowerCase();
8245
+ const textLower = text.toLowerCase();
8246
+ let score = 0;
8247
+ let qi = 0;
8248
+ let lastMatchIndex = -2;
8249
+ for (let ti = 0; ti < text.length && qi < query.length; ti++) {
8250
+ if (textLower[ti] === queryLower[qi]) {
8251
+ score += 10;
8252
+ if (text[ti] === query[qi]) {
8253
+ score += 5;
8254
+ }
8255
+ if (ti === 0 && qi === 0) {
8256
+ score += 15;
8257
+ }
8258
+ if (ti === lastMatchIndex + 1) {
8259
+ score += 5;
8260
+ }
8261
+ lastMatchIndex = ti;
8262
+ qi++;
8263
+ }
8264
+ }
8265
+ if (qi < query.length) return null;
8266
+ score -= text.length * 0.1;
8267
+ return { score };
8268
+ }
8269
+ function fuzzyMatches(query, text) {
8270
+ return match(query, text) !== null;
8271
+ }
8272
+
8273
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/ai-flag.ts
8274
+ function isAiFlagged(row) {
8275
+ return row.needsReview === true || row.aiDecision === "rejected" || row.aiDecision === "failed";
8276
+ }
8277
+
8278
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/graph/lineage.ts
8279
+ function findDirectParents2(target, components) {
8280
+ const out = [];
8281
+ const seen = /* @__PURE__ */ new Set();
8282
+ for (const c2 of components) {
8283
+ if (c2.name === target) continue;
8284
+ for (const slot of c2.slots) {
8285
+ const allowed = slot.allowedComponents ?? [];
8286
+ if (!allowed.includes(target)) continue;
8287
+ const key = `${c2.name}\0${slot.name}`;
8288
+ if (seen.has(key)) continue;
8289
+ seen.add(key);
8290
+ out.push({ parent: c2.name, slotName: slot.name });
8291
+ }
8292
+ }
8293
+ out.sort((a, b) => a.parent.localeCompare(b.parent) || a.slotName.localeCompare(b.slotName));
8294
+ return out;
8295
+ }
8296
+
8297
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/graph/scope-gate-cascade.ts
8298
+ function buildCycleUnits(slotCycles) {
8299
+ const parent = /* @__PURE__ */ new Map();
8300
+ const find = (x) => {
8301
+ let cur = x;
8302
+ while (parent.get(cur) !== cur) {
8303
+ cur = parent.get(cur);
8304
+ }
8305
+ let walk = x;
8306
+ while (parent.get(walk) !== cur) {
8307
+ const next = parent.get(walk);
8308
+ parent.set(walk, cur);
8309
+ walk = next;
8310
+ }
8311
+ return cur;
8312
+ };
8313
+ const union = (a, b) => {
8314
+ const ra = find(a);
8315
+ const rb = find(b);
8316
+ if (ra !== rb) parent.set(ra, rb);
8317
+ };
8318
+ for (const cycle of slotCycles) {
8319
+ for (const node of cycle.path) {
8320
+ if (!parent.has(node)) parent.set(node, node);
8321
+ }
8322
+ for (let i = 1; i < cycle.path.length; i++) {
8323
+ union(cycle.path[0], cycle.path[i]);
8324
+ }
8325
+ }
8326
+ const groups = /* @__PURE__ */ new Map();
8327
+ for (const node of parent.keys()) {
8328
+ const root = find(node);
8329
+ let group = groups.get(root);
8330
+ if (!group) {
8331
+ group = /* @__PURE__ */ new Set();
8332
+ groups.set(root, group);
8333
+ }
8334
+ group.add(node);
8335
+ }
8336
+ const out = /* @__PURE__ */ new Map();
8337
+ for (const group of groups.values()) {
8338
+ for (const node of group) {
8339
+ out.set(node, group);
8340
+ }
8341
+ }
8342
+ return out;
8343
+ }
8344
+ function slotTargets(node, byName) {
8345
+ const c2 = byName.get(node);
8346
+ if (!c2) return [];
8347
+ const seen = /* @__PURE__ */ new Set();
8348
+ const out = [];
8349
+ for (const slot of c2.slots) {
8350
+ for (const target of slot.allowedComponents ?? []) {
8351
+ if (!byName.has(target)) continue;
8352
+ if (seen.has(target)) continue;
8353
+ seen.add(target);
8354
+ out.push(target);
8355
+ }
8356
+ }
8357
+ return out;
8358
+ }
8359
+ function computeCycleAwareAcceptCascade(target, components, cycleUnits) {
8360
+ const byName = new Map(components.map((c2) => [c2.name, c2]));
8361
+ const visited = /* @__PURE__ */ new Set();
8362
+ const queue = [];
8363
+ const enqueue = (name) => {
8364
+ if (visited.has(name)) return;
8365
+ visited.add(name);
8366
+ queue.push(name);
8367
+ const unit = cycleUnits.get(name);
8368
+ if (unit) {
8369
+ for (const member of unit) {
8370
+ if (!visited.has(member)) {
8371
+ visited.add(member);
8372
+ queue.push(member);
8373
+ }
8374
+ }
8375
+ }
8376
+ };
8377
+ enqueue(target);
8378
+ while (queue.length > 0) {
8379
+ const cur = queue.shift();
8380
+ for (const next of slotTargets(cur, byName)) {
8381
+ enqueue(next);
8382
+ }
8383
+ }
8384
+ return visited;
8385
+ }
8386
+ function computeCycleAwareRejectCascade(target, components, cycleUnits) {
8387
+ const toReject = /* @__PURE__ */ new Set();
8388
+ const targetUnit = cycleUnits.get(target);
8389
+ const initialSeeds = targetUnit ? [...targetUnit] : [target];
8390
+ for (const seed of initialSeeds) toReject.add(seed);
8391
+ const stack = [...toReject];
8392
+ while (stack.length > 0) {
8393
+ const cur = stack.pop();
8394
+ for (const { parent } of findDirectParents2(cur, components)) {
8395
+ if (toReject.has(parent)) continue;
8396
+ toReject.add(parent);
8397
+ stack.push(parent);
8398
+ const unit = cycleUnits.get(parent);
8399
+ if (unit) {
8400
+ for (const member of unit) {
8401
+ if (!toReject.has(member)) {
8402
+ toReject.add(member);
8403
+ stack.push(member);
8404
+ }
8405
+ }
8406
+ }
8407
+ }
8408
+ }
8409
+ const acceptCascade2 = computeCycleAwareAcceptCascade(target, components, cycleUnits);
8410
+ const toDeselect = /* @__PURE__ */ new Set();
8411
+ for (const n of acceptCascade2) {
8412
+ if (toReject.has(n)) continue;
8413
+ toDeselect.add(n);
8414
+ }
8415
+ const cyclePartners = [];
8416
+ if (targetUnit) {
8417
+ for (const m of targetUnit) {
8418
+ if (m !== target) cyclePartners.push(m);
8419
+ }
8420
+ cyclePartners.sort();
8421
+ }
8422
+ return { toReject, toDeselect, cyclePartners };
8423
+ }
8424
+ function collectReachableCycleUnits(seeds, components, cycleUnits) {
8425
+ const out = /* @__PURE__ */ new Set();
8426
+ if (cycleUnits.size === 0) return out;
8427
+ const byName = new Map(components.map((c2) => [c2.name, c2]));
8428
+ const visited = /* @__PURE__ */ new Set();
8429
+ const queue = [...seeds];
8430
+ while (queue.length > 0) {
8431
+ const cur = queue.shift();
8432
+ if (visited.has(cur)) continue;
8433
+ visited.add(cur);
8434
+ const unit = cycleUnits.get(cur);
8435
+ if (unit) {
8436
+ for (const member of unit) {
8437
+ out.add(member);
8438
+ if (!visited.has(member)) queue.push(member);
8439
+ }
8440
+ }
8441
+ for (const next of slotTargets(cur, byName)) {
8442
+ if (!visited.has(next)) queue.push(next);
8443
+ }
8444
+ }
8445
+ return out;
8446
+ }
8447
+
8448
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/graph/slot-graph.ts
8449
+ var REJECTED_STATUSES = /* @__PURE__ */ new Set(["error", "rejected"]);
8450
+ function buildComponentGraph3(components, opts) {
8451
+ const stripRejectedEdges = opts?.stripRejectedEdges === true;
8452
+ return components.map((row) => {
8453
+ if (stripRejectedEdges && row.status !== void 0 && REJECTED_STATUSES.has(row.status)) {
8454
+ return { name: row.key, slots: [] };
8455
+ }
8456
+ const slotDefs = row.entry.$slots ?? {};
8457
+ const slots = Object.entries(slotDefs).map(([slotName, slotDef]) => ({
8458
+ name: slotName,
8459
+ allowedComponents: Array.isArray(slotDef?.$allowedComponents) ? slotDef.$allowedComponents.filter((v) => typeof v === "string") : []
8460
+ }));
8461
+ return { name: row.key, slots };
8462
+ });
8463
+ }
8464
+
8465
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/graph/index.ts
8466
+ function sidebarItems(components) {
8467
+ return components.map((c2) => ({
8468
+ key: c2.name,
8469
+ entry: toSidebarEntry(c2),
8470
+ status: isAiFlagged(c2) ? "warning" : "ok"
8471
+ }));
8472
+ }
8473
+ function toSidebarEntry(c2) {
8474
+ const $slots = {};
8475
+ for (const s of c2.slots ?? []) $slots[s.name] = { $allowedComponents: s.allowedComponents };
8476
+ const entry = {
8477
+ $type: "component",
8478
+ $properties: { __scopeGate: { $type: "string", $category: "content" } }
8479
+ };
8480
+ if (Object.keys($slots).length > 0) entry.$slots = $slots;
8481
+ return entry;
8482
+ }
8483
+ function buildScopeGraph(components) {
8484
+ const nodes = buildComponentGraph3(sidebarItems(components));
8485
+ let cycles;
8486
+ try {
8487
+ cycles = findSlotCycles3(nodes);
8488
+ } catch {
8489
+ cycles = [];
8490
+ }
8491
+ const cycleParticipants = /* @__PURE__ */ new Set();
8492
+ for (const cycle of cycles) for (const name of cycle.path) cycleParticipants.add(name);
8493
+ return {
8494
+ nodes,
8495
+ cycles,
8496
+ cycleParticipants,
8497
+ cycleUnits: buildCycleUnits(cycles),
8498
+ closures: computeAllClosures(nodes)
8499
+ };
8500
+ }
8501
+ function acceptCascade(graph, target) {
8502
+ return [...computeCycleAwareAcceptCascade(target, graph.nodes, graph.cycleUnits)];
8503
+ }
8504
+ function rejectCascade(graph, target) {
8505
+ const { toReject, toDeselect } = computeCycleAwareRejectCascade(target, graph.nodes, graph.cycleUnits);
8506
+ return { toReject: [...toReject], toDeselect: [...toDeselect] };
8507
+ }
8508
+ function reachableCycleMembers(graph, seeds) {
8509
+ return [...collectReachableCycleUnits(seeds, graph.nodes, graph.cycleUnits)];
8510
+ }
8511
+
8512
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/keymap.ts
8513
+ var NONE = { type: "none" };
8514
+ function resolveKey(mode, key, ctx) {
8515
+ switch (mode) {
8516
+ case "help":
8517
+ return key.input === "h" || key.escape ? { type: "close-help" } : NONE;
8518
+ case "reject-prompt":
8519
+ if (key.input === "y" || key.input === "Y") return { type: "answer-reject-prompt", confirm: true };
8520
+ if (key.input === "n" || key.input === "N" || key.escape) return { type: "answer-reject-prompt", confirm: false };
8521
+ return NONE;
8522
+ case "search":
8523
+ if (key.escape) return { type: "close-search" };
8524
+ if (key.return) return { type: "submit-search" };
8525
+ return { type: "search-input" };
8526
+ case "cycles":
8527
+ if (key.escape || key.input === "c") return { type: "close-panel" };
8528
+ if (key.upArrow) return { type: "move", delta: -1 };
8529
+ if (key.downArrow) return { type: "move", delta: 1 };
8530
+ if (key.return) return { type: "jump-to-selected" };
8531
+ return NONE;
8532
+ case "flags":
8533
+ if (key.upArrow) return { type: "move", delta: -1 };
8534
+ if (key.downArrow) return { type: "move", delta: 1 };
8535
+ if (key.return) return { type: "jump-to-selected" };
8536
+ return NONE;
8537
+ case "main":
8538
+ return resolveMain(key, ctx);
8539
+ }
8540
+ }
8541
+ function resolveMain(key, ctx) {
8542
+ const { input } = key;
8543
+ const inMain = ctx.focusedColumn === "main";
8544
+ if (input === "q" || key.escape) {
8545
+ if (key.escape && ctx.jumpFilterActive) return { type: "clear-jump-filter" };
8546
+ if (key.escape && ctx.searchActive) return { type: "clear-search" };
8547
+ return { type: "quit" };
8548
+ }
8549
+ if (input === "h") return { type: "open-panel", panel: "help" };
8550
+ if (input === "f" || input === "F") return { type: "confirm" };
8551
+ if (input === "c") return ctx.hasCycles ? { type: "open-panel", panel: "cycles" } : NONE;
8552
+ if (input === "d") return { type: "toggle-dependencies" };
8553
+ if (input === "x") return ctx.hasFlagReasons ? { type: "open-panel", panel: "flags" } : NONE;
8554
+ if (input === "/") return { type: "open-panel", panel: "search" };
8555
+ if (input === "o") return ctx.hasCycles ? { type: "toggle-cycle-filter" } : NONE;
8556
+ if (input === "i" && !key.tab && !key.ctrl) return { type: "toggle-jump-filter" };
8557
+ if (input === " ") return inMain ? { type: "toggle-group" } : NONE;
8558
+ if (input === "E") return inMain ? { type: "expand-all" } : NONE;
8559
+ if (input === "C") return inMain ? { type: "collapse-all" } : NONE;
8560
+ if (input === "a") return inMain ? { type: "accept" } : NONE;
8561
+ if (input === "r") return { type: "reject" };
8562
+ if (input === "L") return { type: "toggle-view" };
8563
+ if (input === "A") return { type: "toggle-all" };
8564
+ if (input === "Y") return { type: "accept-unflagged" };
8565
+ if (key.tab) {
8566
+ if (ctx.singleColumn) return NONE;
8567
+ return { type: "switch-column", delta: key.shiftTab ? -1 : 1 };
8568
+ }
8569
+ if (key.return) return inMain ? NONE : { type: "jump-to-selected" };
8570
+ if (key.upArrow) return ctx.focusedListEmpty ? NONE : { type: "move", delta: -1 };
8571
+ if (key.downArrow) return ctx.focusedListEmpty ? NONE : { type: "move", delta: 1 };
8572
+ return NONE;
8573
+ }
8574
+
8575
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/group-collapse.ts
8576
+ function resolveGroupRoot(key, closures, cycleSet) {
8577
+ if (cycleSet.has(key)) return key;
8578
+ if (closures.has(key)) return key;
8579
+ for (const [root, closure] of closures.entries()) {
8580
+ if (closure.nodes.some((n) => n.name === key)) return root;
8581
+ }
8582
+ return void 0;
8583
+ }
8584
+
8585
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/hooks/sidebar-search-state.ts
8586
+ import { useState as useState10 } from "react";
8587
+ function useSidebarSearchState() {
8588
+ const [searchOpen, setSearchOpen] = useState10(false);
8589
+ const [searchQuery, setSearchQuery] = useState10("");
8590
+ const [autocompleteCandidates, setAutocompleteCandidates] = useState10([]);
8591
+ const [jumpFilterTarget, setJumpFilterTarget] = useState10(null);
8592
+ const [columnOneView, setColumnOneView] = useState10("grouped");
8593
+ const [activeFilters, setActiveFilters] = useState10(/* @__PURE__ */ new Set());
8594
+ const [showHelp, setShowHelp] = useState10(false);
8595
+ return {
8596
+ searchOpen,
8597
+ setSearchOpen,
8598
+ searchQuery,
8599
+ setSearchQuery,
8600
+ autocompleteCandidates,
8601
+ setAutocompleteCandidates,
8602
+ jumpFilterTarget,
8603
+ setJumpFilterTarget,
8604
+ columnOneView,
8605
+ setColumnOneView,
8606
+ activeFilters,
8607
+ setActiveFilters,
8608
+ showHelp,
8609
+ setShowHelp
8610
+ };
8611
+ }
8612
+
8613
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/hooks/useOverlayPanel.ts
8614
+ import { useCallback, useState as useState11 } from "react";
8615
+ function useOverlayPanel(opts) {
8616
+ const { toggleKey, onClose } = opts;
8617
+ const [isOpen, setIsOpen] = useState11(false);
8618
+ const open = useCallback(() => {
8619
+ setIsOpen(true);
8620
+ }, []);
8621
+ const close = useCallback(() => {
8622
+ setIsOpen((prev) => {
8623
+ if (prev && onClose) onClose();
8624
+ return false;
8625
+ });
8626
+ }, [onClose]);
8627
+ const handleInput = useCallback(
8628
+ (input, key) => {
8629
+ if (!isOpen) return false;
8630
+ if (input === toggleKey || key.escape === true) {
8631
+ if (onClose) onClose();
8632
+ setIsOpen(false);
8633
+ return true;
8634
+ }
8635
+ return false;
8636
+ },
8637
+ [isOpen, toggleKey, onClose]
8638
+ );
8639
+ return { isOpen, open, close, handleInput };
8640
+ }
8641
+
8642
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/lineage-layout.ts
8643
+ var VISIBLE_COUNT = 200;
8644
+ var MAX_PANEL_ROWS = 200;
8645
+ var SIDEBAR_MIN = 4;
8646
+ var MIN_PANEL_ROWS = 4;
8647
+ var FALLBACK_ROWS = 40;
8648
+ var HEADER_ROWS = 2;
8649
+ var COUNTER_STRIP_ROWS = 2;
8650
+ var FOCUSED_DETAIL_ROWS = 2;
8651
+ var LEGEND_ROWS = 3;
8652
+ var FIXED_OVERHEAD = HEADER_ROWS + COUNTER_STRIP_ROWS + FOCUSED_DETAIL_ROWS + LEGEND_ROWS;
8653
+ var PANEL_BOX_CHROME = 6;
8654
+ var BASE_CHROME_OVERHEAD = 18;
8655
+ function clamp(value, min, max) {
8656
+ return Math.max(min, Math.min(max, value));
8657
+ }
8658
+ function computeLineageLayout({ rows, panelOpen, entryCount }) {
8659
+ const sidebarVisible = clamp(rows - BASE_CHROME_OVERHEAD, SIDEBAR_MIN, VISIBLE_COUNT);
8660
+ if (!panelOpen) {
8661
+ return { sidebarVisible, panelMaxRows: MAX_PANEL_ROWS };
8662
+ }
8663
+ const terminalFit = rows - FIXED_OVERHEAD - PANEL_BOX_CHROME;
8664
+ let panelBase = Math.min(MAX_PANEL_ROWS, terminalFit);
8665
+ if (entryCount !== void 0 && entryCount > 0) {
8666
+ panelBase = Math.min(panelBase, entryCount);
8667
+ }
8668
+ const panelMaxRows = clamp(panelBase, MIN_PANEL_ROWS, MAX_PANEL_ROWS);
8669
+ return { sidebarVisible, panelMaxRows };
8670
+ }
8671
+ function computeSidebarBudget({ rows, panelOpen, entryCount }) {
8672
+ const sidebarVisibleCount = clamp(rows - BASE_CHROME_OVERHEAD, SIDEBAR_MIN, VISIBLE_COUNT);
8673
+ const { panelMaxRows } = computeLineageLayout({ rows, panelOpen, entryCount });
8674
+ return { sidebarVisibleCount, panelMaxRows };
8675
+ }
8676
+
8677
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/sidebar-navigation.ts
8678
+ function collectExpandedGroupRoots(closures, cycleParticipants) {
8679
+ const roots = /* @__PURE__ */ new Set();
8680
+ for (const [name, closure] of closures.entries()) {
8681
+ if (closure.nodes.length > 1) roots.add(name);
8682
+ }
8683
+ for (const name of cycleParticipants) roots.add(name);
8684
+ return roots;
8685
+ }
8686
+ function computeSidebarViewToggle({
8687
+ currentView,
8688
+ currentKey,
8689
+ currentScroll,
8690
+ visibleCount,
8691
+ items,
8692
+ cycleParticipants,
8693
+ expandedGroups,
8694
+ graph,
8695
+ showFlatTier = false
8696
+ }) {
8697
+ const view = currentView === "grouped" ? "flat" : "grouped";
8698
+ const rows = buildVisibleRows({
8699
+ items,
8700
+ cycleParticipants,
8701
+ expandedGroups,
8702
+ showFlatTier,
8703
+ viewMode: view,
8704
+ graph
8705
+ });
8706
+ let cursor = 0;
8707
+ if (currentKey) {
8708
+ for (let i = 0; i < rows.length; i++) {
8709
+ const row = rows[i];
8710
+ if (row.itemIdx < 0) continue;
8711
+ if (items[row.itemIdx]?.key === currentKey) {
8712
+ cursor = i;
8713
+ break;
8714
+ }
8715
+ }
8716
+ }
8717
+ const scroll = cursor < currentScroll ? cursor : cursor >= currentScroll + visibleCount ? cursor - visibleCount + 1 : currentScroll;
8718
+ return { view, cursor, scroll };
8719
+ }
8720
+
8721
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/step-filters.ts
8722
+ function computeFilterKeys(input) {
8723
+ const active = new Set(input.filters);
8724
+ if (active.size === 0) return void 0;
8725
+ const out = /* @__PURE__ */ new Set();
8726
+ if (active.has("cycles")) for (const k of input.data.cycles ?? []) out.add(k);
8727
+ if (active.has("broken")) for (const k of input.data.broken ?? []) out.add(k);
8728
+ if (active.has("deleted")) for (const k of input.data.deleted ?? []) out.add(k);
8729
+ return out;
8730
+ }
8731
+ function intersectFilterKeys(a, b) {
8732
+ if (a === void 0) return b;
8733
+ if (b === void 0) return a;
8734
+ const out = /* @__PURE__ */ new Set();
8735
+ for (const k of a) if (b.has(k)) out.add(k);
8736
+ return out;
8737
+ }
8738
+ function buildFlatDimPredicate(input) {
8739
+ const hasSearch = input.searchQuery.length > 0;
8740
+ const isFlat = input.viewMode === "flat";
8741
+ const keys = isFlat ? input.filterVisibleKeys : void 0;
8742
+ if (!hasSearch && keys === void 0) return void 0;
8743
+ return (name) => {
8744
+ if (hasSearch && !fuzzyMatches(input.searchQuery, name)) return true;
8745
+ if (keys !== void 0 && !keys.has(name)) return true;
8746
+ return false;
8747
+ };
8748
+ }
8749
+
8750
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/state.ts
8751
+ function apply(state, entries) {
8752
+ const next = new Map(state);
8753
+ for (const [name, decision] of entries) next.set(name, decision);
8754
+ return next;
8755
+ }
8756
+ function reduceDecisions(state, action, components, graph) {
8757
+ switch (action.type) {
8758
+ case "accept": {
8759
+ if (state.get(action.name) === "accepted") return state;
8760
+ return apply(
8761
+ state,
8762
+ acceptCascade(graph, action.name).map((name) => [name, "accepted"])
8763
+ );
8764
+ }
8765
+ case "reject": {
8766
+ if (state.get(action.name) === "rejected") return state;
8767
+ const { toReject, toDeselect } = rejectCascade(graph, action.name);
8768
+ return apply(state, [
8769
+ ...toReject.map((name) => [name, "rejected"]),
8770
+ ...toDeselect.map((name) => [name, "undecided"])
8771
+ ]);
8772
+ }
8773
+ case "toggle-all": {
8774
+ const nonCycle = components.filter((c2) => !graph.cycleParticipants.has(c2.name)).map((c2) => c2.name);
8775
+ const anyNotAccepted = nonCycle.some((name) => state.get(name) !== "accepted");
8776
+ if (anyNotAccepted) {
8777
+ return apply(state, [
8778
+ ...nonCycle.map((name) => [name, "accepted"]),
8779
+ ...reachableCycleMembers(graph, nonCycle).map((name) => [name, "accepted"])
8780
+ ]);
8781
+ }
8782
+ return apply(state, [
8783
+ ...nonCycle.map((name) => [name, "rejected"]),
8784
+ ...components.filter((c2) => graph.cycleParticipants.has(c2.name) && state.get(c2.name) === "accepted").map((c2) => [c2.name, "undecided"])
8785
+ ]);
8786
+ }
8787
+ case "accept-unflagged": {
8788
+ const seeds = components.filter((c2) => !graph.cycleParticipants.has(c2.name) && !isAiFlagged(c2)).map((c2) => c2.name);
8789
+ return apply(state, [
8790
+ ...seeds.map((name) => [name, "accepted"]),
8791
+ ...reachableCycleMembers(graph, seeds).map((name) => [name, "accepted"])
8792
+ ]);
8793
+ }
8794
+ }
8795
+ }
8796
+ function rejectNeedsConfirmation(graph, name, state) {
8797
+ if (state.get(name) === "rejected") return false;
8798
+ const { toReject, toDeselect } = rejectCascade(graph, name);
8799
+ const ancestors = toReject.filter((n) => n !== name);
8800
+ return ancestors.length + toDeselect.length >= 2;
8801
+ }
8802
+ function partitionDecisions(components, state) {
8803
+ const accepted = [];
8804
+ const rejected = [];
8805
+ for (const c2 of components) {
8806
+ if (state.get(c2.name) === "accepted") accepted.push(c2.name);
8807
+ else rejected.push(c2.name);
8808
+ }
8809
+ return { accepted, rejected };
8810
+ }
8811
+
8812
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/use-scope-gate.ts
8813
+ function useScopeGate({ components, onConfirm, onQuit }) {
8814
+ const { columns: totalWidth, rows: terminalRows } = useTerminalSize();
8815
+ const columnPlan = useMemo2(() => computeColumnWidths(totalWidth), [totalWidth]);
8816
+ const [decisions, setDecisions] = useState12(/* @__PURE__ */ new Map());
8817
+ const [nav, setNav] = useState12({ cursor: 0, scrollOffset: 0 });
8818
+ const [focusedColumn, setFocusedColumn] = useState12("main");
8819
+ const [addedComponentsCursor, setAddedComponentsCursor] = useState12(0);
8820
+ const [showDependencies, setShowDependencies] = useState12(false);
8821
+ const [cyclesPanelOpen, setCyclesPanelOpen] = useState12(false);
8822
+ const [cyclesCursor, setCyclesCursor] = useState12(0);
8823
+ const aiRationalePanel = useOverlayPanel({ toggleKey: "x" });
8824
+ const [aiCursor, setAiCursor] = useState12(0);
8825
+ const [pendingRejectCascade, setPendingRejectCascade] = useState12(null);
8826
+ const search = useSidebarSearchState();
8827
+ const {
8828
+ searchOpen,
8829
+ setSearchOpen,
8830
+ searchQuery,
8831
+ setSearchQuery,
8832
+ setAutocompleteCandidates,
8833
+ jumpFilterTarget,
8834
+ setJumpFilterTarget,
8835
+ columnOneView,
8836
+ setColumnOneView,
8837
+ activeFilters,
8838
+ setActiveFilters,
8839
+ showHelp,
8840
+ setShowHelp
8841
+ } = search;
8842
+ const groupedItems = useMemo2(() => sidebarItems(components), [components]);
8843
+ const graph = useMemo2(() => buildScopeGraph(components), [components]);
8844
+ const { cycles: slotCycles, cycleParticipants, cycleUnits, closures } = graph;
8845
+ const hasCycles = slotCycles.length > 0;
8846
+ const cyclesJumpables = useMemo2(
8847
+ () => slotCycles.map((c2, i) => ({ cycleIndex: i, jumpTarget: c2.path[0] })),
8848
+ [slotCycles]
8849
+ );
8850
+ const [expandedGroups, setExpandedGroups] = useState12(() => {
8851
+ const seed = new Set(closures.keys());
8852
+ for (const p of cycleParticipants) seed.add(p);
8853
+ return seed;
8854
+ });
8855
+ const seededGroupsRef = useRef4(closures.size > 0 || cycleParticipants.size > 0);
8856
+ useEffect7(() => {
8857
+ if (seededGroupsRef.current) return;
8858
+ if (closures.size === 0 && cycleParticipants.size === 0) return;
8859
+ seededGroupsRef.current = true;
8860
+ const seed = new Set(closures.keys());
8861
+ for (const p of cycleParticipants) seed.add(p);
8862
+ setExpandedGroups(seed);
8863
+ }, [closures, cycleParticipants]);
8864
+ const hasGroupRoots = useMemo2(() => {
8865
+ if (cycleParticipants.size > 0) return true;
8866
+ for (const c2 of closures.values()) if (c2.nodes.length > 1) return true;
8867
+ return false;
8868
+ }, [closures, cycleParticipants]);
8869
+ const toggleExpanded = (rootName) => {
8870
+ setExpandedGroups((prev) => {
8871
+ const next = new Set(prev);
8872
+ if (next.has(rootName)) next.delete(rootName);
8873
+ else next.add(rootName);
8874
+ return next;
8875
+ });
8876
+ };
8877
+ const brokenKeys = useMemo2(() => new Set(components.filter(isAiFlagged).map((c2) => c2.name)), [components]);
8878
+ const dependencyFilterKeys = useMemo2(() => {
8879
+ if (!showDependencies) return void 0;
8880
+ const keys = /* @__PURE__ */ new Set();
8881
+ for (const [root, closure] of closures) {
8882
+ if (closure.nodes.length <= 1 || decisions.get(root) !== "accepted") continue;
8883
+ for (const node of closure.nodes) keys.add(node.name);
8884
+ }
8885
+ for (const unit of cycleUnits.values()) {
8886
+ if (![...unit].some((name) => decisions.get(name) === "accepted")) continue;
8887
+ for (const name of unit) keys.add(name);
8888
+ }
8889
+ return keys;
8890
+ }, [closures, cycleUnits, showDependencies, decisions]);
8891
+ const filterVisibleKeys = useMemo2(() => {
8892
+ if (jumpFilterTarget) return findAllAncestors(jumpFilterTarget, graph.nodes);
8893
+ const categoryKeys = computeFilterKeys({
8894
+ filters: activeFilters,
8895
+ data: { cycles: cycleParticipants, broken: brokenKeys }
8896
+ });
8897
+ const searchKeys = (() => {
8898
+ if (!searchQuery) return void 0;
8899
+ const matches = groupedItems.map((it) => it.key).filter((k) => fuzzyMatches(searchQuery, k));
8900
+ if (matches.length === 0) return void 0;
8901
+ return computeDirectNeighborhood(matches, graph.nodes);
8902
+ })();
8903
+ return intersectFilterKeys(intersectFilterKeys(categoryKeys, searchKeys), dependencyFilterKeys);
8904
+ }, [
8905
+ jumpFilterTarget,
8906
+ activeFilters,
8907
+ cycleParticipants,
8908
+ brokenKeys,
8909
+ searchQuery,
8910
+ groupedItems,
8911
+ graph,
8912
+ dependencyFilterKeys
8913
+ ]);
8914
+ const visibleRows = useMemo2(
8915
+ () => buildVisibleRows({
8916
+ items: groupedItems,
8917
+ cycleParticipants,
8918
+ expandedGroups,
8919
+ showFlatTier: false,
8920
+ viewMode: columnOneView,
8921
+ graph: graph.nodes,
8922
+ filterVisibleKeys
8923
+ }),
8924
+ [groupedItems, cycleParticipants, expandedGroups, columnOneView, graph, filterVisibleKeys]
8925
+ );
8926
+ const total = visibleRows.length;
8927
+ const safeCursor = Math.min(nav.cursor, Math.max(0, total - 1));
8928
+ const currentRow = visibleRows[safeCursor];
8929
+ const currentRowKey = currentRow && currentRow.itemIdx >= 0 ? groupedItems[currentRow.itemIdx]?.key : void 0;
8930
+ const selectionStateByKey = useMemo2(() => {
8931
+ const map = /* @__PURE__ */ new Map();
8932
+ for (const c2 of components) map.set(c2.name, decisions.get(c2.name) ?? "undecided");
8933
+ return map;
8934
+ }, [components, decisions]);
8935
+ const aiFlaggedByKey = useMemo2(() => new Map(components.map((c2) => [c2.name, isAiFlagged(c2)])), [components]);
8936
+ const dimPredicate = useMemo2(
8937
+ () => buildFlatDimPredicate({ viewMode: columnOneView, searchQuery, filterVisibleKeys }),
8938
+ [columnOneView, searchQuery, filterVisibleKeys]
8939
+ );
8940
+ const { sidebarVisibleCount: visibleCount, panelMaxRows } = computeSidebarBudget({
8941
+ rows: terminalRows || FALLBACK_ROWS,
8942
+ panelOpen: false,
8943
+ entryCount: 0
8944
+ });
8945
+ const panelLayout = useMemo2(() => computePanelLayout(visibleCount), [visibleCount]);
8946
+ useEffect7(() => {
8947
+ setNav((prev) => {
8948
+ const maxIdx = Math.max(0, visibleRows.length - 1);
8949
+ const nextCursor = Math.min(prev.cursor, maxIdx);
8950
+ const nextScroll = Math.min(prev.scrollOffset, maxIdx);
8951
+ if (nextCursor === prev.cursor && nextScroll === prev.scrollOffset) return prev;
8952
+ return { cursor: nextCursor, scrollOffset: nextScroll };
8953
+ });
8954
+ }, [visibleRows]);
8955
+ const searchMatches = useMemo2(() => {
8956
+ if (!searchQuery) return [];
8957
+ return components.filter((c2) => fuzzyMatches(searchQuery, c2.name)).map((c2) => c2.name);
8958
+ }, [components, searchQuery]);
8959
+ const aiExcluded = components.filter(isAiFlagged);
8960
+ const aiRows = useMemo2(
8961
+ () => aiExcluded.filter((c2) => c2.aiReason !== null && c2.aiReason !== void 0 && c2.aiReason !== "").map((c2) => ({ label: `${c2.name} \u2014 ${c2.aiReason}`, jumpTarget: c2.name })),
8962
+ [aiExcluded]
8963
+ );
8964
+ const addedComponents = useMemo2(
8965
+ () => buildAddedComponentsList(components, selectionStateByKey, cycleParticipants),
8966
+ [components, selectionStateByKey, cycleParticipants]
8967
+ );
8968
+ const counters = useMemo2(
8969
+ () => computeCounters(components, closures, selectionStateByKey),
8970
+ [components, closures, selectionStateByKey]
8971
+ );
8972
+ const safeAddedComponentsCursor = Math.min(addedComponentsCursor, Math.max(0, addedComponents.length - 1));
8973
+ const focusedRowKey = () => {
8974
+ const row = visibleRows[safeCursor];
8975
+ if (!row) return void 0;
8976
+ switch (row.kind) {
8977
+ case "standalone":
8978
+ case "empty":
8979
+ case "group-root":
8980
+ case "group-child":
8981
+ case "flat":
8982
+ case "cycle":
8983
+ return row.itemIdx >= 0 ? groupedItems[row.itemIdx]?.key : void 0;
8984
+ default:
8985
+ return void 0;
8986
+ }
8987
+ };
8988
+ const jumpCursorTo = (name) => {
8989
+ let idx = -1;
8990
+ for (let i = 0; i < visibleRows.length; i++) {
8991
+ const row = visibleRows[i];
8992
+ if (row.itemIdx < 0) continue;
8993
+ if (groupedItems[row.itemIdx]?.key === name) {
8994
+ idx = i;
8995
+ break;
8996
+ }
8997
+ }
8998
+ if (idx < 0) return;
8999
+ setNav(({ scrollOffset: prev }) => {
9000
+ let nextScroll = prev;
9001
+ if (idx < prev) nextScroll = idx;
9002
+ else if (idx >= prev + visibleCount) nextScroll = idx - visibleCount + 1;
9003
+ return { cursor: idx, scrollOffset: nextScroll };
9004
+ });
9005
+ };
9006
+ const decide = (action) => setDecisions((prev) => reduceDecisions(prev, action, components, graph));
9007
+ const requestReject = (name) => {
9008
+ if (decisions.get(name) === "rejected") return;
9009
+ if (rejectNeedsConfirmation(graph, name, decisions)) {
9010
+ const { toReject, toDeselect } = rejectCascade(graph, name);
9011
+ setPendingRejectCascade({
9012
+ target: name,
9013
+ ancestors: toReject.filter((n) => n !== name).sort(),
9014
+ descendants: [...toDeselect].sort()
9015
+ });
9016
+ return;
9017
+ }
9018
+ decide({ type: "reject", name });
9019
+ };
9020
+ const mode = showHelp ? "help" : pendingRejectCascade ? "reject-prompt" : searchOpen ? "search" : cyclesPanelOpen ? "cycles" : aiRationalePanel.isOpen ? "flags" : "main";
9021
+ const context = {
9022
+ focusedColumn,
9023
+ singleColumn: columnPlan.layout === "single",
9024
+ hasCycles,
9025
+ hasFlagReasons: aiRows.length > 0,
9026
+ jumpFilterActive: jumpFilterTarget !== null,
9027
+ searchActive: searchQuery.length > 0,
9028
+ focusedListEmpty: focusedColumn === "added-components" ? addedComponents.length === 0 : total === 0
9029
+ };
9030
+ const submitSearch = () => {
9031
+ const closeSearch = () => {
9032
+ setSearchOpen(false);
9033
+ setSearchQuery("");
9034
+ setAutocompleteCandidates([]);
9035
+ };
9036
+ if (!searchQuery || searchMatches.length === 0) {
9037
+ closeSearch();
9038
+ return;
9039
+ }
9040
+ const cursorName = currentRow && currentRow.itemIdx >= 0 ? groupedItems[currentRow.itemIdx]?.key : void 0;
9041
+ const rowName = (i) => {
9042
+ const r = visibleRows[i];
9043
+ return r && r.itemIdx >= 0 ? groupedItems[r.itemIdx]?.key : void 0;
9044
+ };
9045
+ let target;
9046
+ for (let i = safeCursor; i < visibleRows.length && !target; i++) {
9047
+ const n = rowName(i);
9048
+ if (n && n !== cursorName && fuzzyMatches(searchQuery, n)) target = n;
9049
+ }
9050
+ for (let i = 0; i < visibleRows.length && !target; i++) {
9051
+ const n = rowName(i);
9052
+ if (n && fuzzyMatches(searchQuery, n)) target = n;
9053
+ }
9054
+ if (target) jumpCursorTo(target);
9055
+ setSearchOpen(false);
9056
+ };
9057
+ const move = (delta) => {
9058
+ if (mode === "cycles") {
9059
+ setCyclesCursor((c2) => Math.max(0, Math.min(Math.max(0, cyclesJumpables.length - 1), c2 + delta)));
9060
+ return;
9061
+ }
9062
+ if (mode === "flags") {
9063
+ setAiCursor((c2) => Math.max(0, Math.min(Math.max(0, aiRows.length - 1), c2 + delta)));
9064
+ return;
9065
+ }
9066
+ if (focusedColumn === "added-components") {
9067
+ setAddedComponentsCursor((c2) => Math.max(0, Math.min(addedComponents.length - 1, c2 + delta)));
9068
+ return;
9069
+ }
9070
+ setNav(({ cursor: c2, scrollOffset: prev }) => {
9071
+ if (delta < 0) {
9072
+ const next2 = c2 <= 0 ? 0 : c2 - 1;
9073
+ return { cursor: next2, scrollOffset: Math.min(prev, next2) };
9074
+ }
9075
+ const next = c2 >= total - 1 ? total - 1 : c2 + 1;
9076
+ return { cursor: next, scrollOffset: next >= prev + visibleCount ? next - visibleCount + 1 : prev };
9077
+ });
9078
+ };
9079
+ const perform = (action) => {
9080
+ switch (action.type) {
9081
+ case "none":
9082
+ return;
9083
+ case "quit":
9084
+ onQuit();
9085
+ return;
9086
+ case "confirm":
9087
+ onConfirm(partitionDecisions(components, decisions));
9088
+ return;
9089
+ case "close-help":
9090
+ setShowHelp(false);
9091
+ return;
9092
+ case "answer-reject-prompt":
9093
+ if (action.confirm && pendingRejectCascade) decide({ type: "reject", name: pendingRejectCascade.target });
9094
+ setPendingRejectCascade(null);
9095
+ return;
9096
+ case "close-panel":
9097
+ setCyclesPanelOpen(false);
9098
+ return;
9099
+ case "close-search":
9100
+ setSearchOpen(false);
9101
+ setSearchQuery("");
9102
+ setAutocompleteCandidates([]);
9103
+ return;
9104
+ case "submit-search":
9105
+ submitSearch();
9106
+ return;
9107
+ case "search-input":
9108
+ return;
9109
+ case "clear-jump-filter":
9110
+ setJumpFilterTarget(null);
9111
+ return;
9112
+ case "clear-search":
9113
+ setSearchQuery("");
9114
+ setAutocompleteCandidates([]);
9115
+ return;
9116
+ case "move":
9117
+ move(action.delta);
9118
+ return;
9119
+ case "jump-to-selected":
9120
+ if (mode === "cycles") {
9121
+ const target = cyclesJumpables[cyclesCursor];
9122
+ if (target) jumpCursorTo(target.jumpTarget);
9123
+ setCyclesPanelOpen(false);
9124
+ } else if (mode === "flags") {
9125
+ const row = aiRows[aiCursor];
9126
+ if (row) jumpCursorTo(row.jumpTarget);
9127
+ aiRationalePanel.close();
9128
+ } else {
9129
+ const entry = addedComponents[safeAddedComponentsCursor];
9130
+ if (entry) jumpCursorTo(entry.name);
9131
+ setFocusedColumn("main");
9132
+ }
9133
+ return;
9134
+ case "accept": {
9135
+ const key = focusedRowKey();
9136
+ if (key) decide({ type: "accept", name: key });
9137
+ return;
9138
+ }
9139
+ case "reject": {
9140
+ const key = focusedColumn === "added-components" ? addedComponents[safeAddedComponentsCursor]?.name : focusedRowKey();
9141
+ if (key) requestReject(key);
9142
+ return;
9143
+ }
9144
+ case "toggle-all":
9145
+ decide({ type: "toggle-all" });
9146
+ return;
9147
+ case "accept-unflagged":
9148
+ decide({ type: "accept-unflagged" });
9149
+ return;
9150
+ case "toggle-group": {
9151
+ const key = focusedRowKey();
9152
+ const rootName = key ? resolveGroupRoot(key, closures, cycleParticipants) : void 0;
9153
+ if (rootName) toggleExpanded(rootName);
9154
+ return;
9155
+ }
9156
+ case "expand-all":
9157
+ setExpandedGroups(collectExpandedGroupRoots(closures, cycleParticipants));
9158
+ return;
9159
+ case "collapse-all":
9160
+ setExpandedGroups(/* @__PURE__ */ new Set());
9161
+ return;
9162
+ case "switch-column": {
9163
+ const order = ["main", "added-components"];
9164
+ const at = order.indexOf(focusedColumn);
9165
+ setFocusedColumn(order[(at + action.delta + order.length) % order.length]);
9166
+ return;
9167
+ }
9168
+ case "open-panel":
9169
+ if (action.panel === "help") setShowHelp(true);
9170
+ else if (action.panel === "search") setSearchOpen(true);
9171
+ else if (action.panel === "cycles") {
9172
+ setCyclesPanelOpen(true);
9173
+ setCyclesCursor(0);
9174
+ aiRationalePanel.close();
9175
+ } else {
9176
+ aiRationalePanel.open();
9177
+ setAiCursor(0);
9178
+ setCyclesPanelOpen(false);
9179
+ }
9180
+ return;
9181
+ case "toggle-dependencies":
9182
+ setShowDependencies((current) => !current);
9183
+ setNav({ cursor: 0, scrollOffset: 0 });
9184
+ return;
9185
+ case "toggle-cycle-filter":
9186
+ setActiveFilters((prev) => {
9187
+ const next = new Set(prev);
9188
+ if (next.has("cycles")) next.delete("cycles");
9189
+ else next.add("cycles");
9190
+ return next;
9191
+ });
9192
+ return;
9193
+ case "toggle-jump-filter": {
9194
+ const target = focusedColumn === "main" ? focusedRowKey() : addedComponents[safeAddedComponentsCursor]?.name;
9195
+ if (target) setJumpFilterTarget((prev) => prev === target ? null : target);
9196
+ return;
9197
+ }
9198
+ case "toggle-view": {
9199
+ const next = computeSidebarViewToggle({
9200
+ currentView: columnOneView,
9201
+ currentKey: currentRowKey,
9202
+ currentScroll: nav.scrollOffset,
9203
+ visibleCount,
9204
+ items: groupedItems,
9205
+ cycleParticipants,
9206
+ expandedGroups,
9207
+ graph: graph.nodes
9208
+ });
9209
+ setColumnOneView(next.view);
9210
+ setNav({ cursor: next.cursor, scrollOffset: next.scroll });
9211
+ return;
9212
+ }
9213
+ }
9214
+ };
9215
+ useImmediateInput((input, key) => {
9216
+ if (mode === "flags" && aiRationalePanel.handleInput(input, key)) return;
9217
+ if (mode === "search") {
9218
+ const action = resolveKey(mode, { input, ...key }, context);
9219
+ if (action.type === "search-input") {
9220
+ handleSidebarSearchInput(input, key, {
9221
+ query: searchQuery,
9222
+ names: components.map((c2) => c2.name),
9223
+ setQuery: setSearchQuery,
9224
+ setCandidates: setAutocompleteCandidates
9225
+ });
9226
+ return;
9227
+ }
9228
+ perform(action);
9229
+ return;
9230
+ }
9231
+ perform(resolveKey(mode, { input, ...key }, context));
9232
+ });
9233
+ return {
9234
+ // layout
9235
+ totalWidth,
9236
+ columnPlan,
9237
+ panelLayout,
9238
+ visibleCount,
9239
+ panelMaxRows,
9240
+ // sidebar
9241
+ groupedItems,
9242
+ graph,
9243
+ hasGroupRoots,
9244
+ expandedGroups,
9245
+ toggleExpanded,
9246
+ visibleRows,
9247
+ safeCursor,
9248
+ scrollOffset: nav.scrollOffset,
9249
+ selectionStateByKey,
9250
+ aiFlaggedByKey,
9251
+ dimPredicate,
9252
+ columnOneView,
9253
+ focusedColumn,
9254
+ // panels
9255
+ showHelp,
9256
+ closeHelp: () => setShowHelp(false),
9257
+ cyclesPanelOpen,
9258
+ cyclesCursor,
9259
+ slotCycles,
9260
+ aiRationalePanelOpen: aiRationalePanel.isOpen,
9261
+ aiCursor,
9262
+ aiRows,
9263
+ aiExcludedCount: aiExcluded.length,
9264
+ pendingRejectCascade,
9265
+ // added column
9266
+ addedComponents,
9267
+ safeAddedComponentsCursor,
9268
+ counters,
9269
+ // search
9270
+ search,
9271
+ searchMatches
9272
+ };
9273
+ }
9274
+
9275
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/screen.tsx
9276
+ import { Fragment as Fragment4, jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
9277
+ var HELP_SECTIONS = [
9278
+ {
9279
+ title: "Navigation",
9280
+ entries: [
9281
+ { keys: "\u2191 / \u2193", label: "Move cursor" },
9282
+ { keys: "Tab / Shift-Tab", label: "Switch column" },
9283
+ { keys: "Enter", label: "Jump to row in main column" }
9284
+ ]
9285
+ },
9286
+ {
9287
+ title: "Selection",
9288
+ entries: [
9289
+ { keys: "a", label: "Accept" },
9290
+ { keys: "r", label: "Reject" },
9291
+ { keys: "A", label: "Toggle all" },
9292
+ { keys: "Y", label: "Accept non-flagged" }
9293
+ ]
9294
+ },
9295
+ createSidebarViewsHelpSection(false),
9296
+ {
9297
+ title: "Panels",
9298
+ entries: [
9299
+ { keys: "c", label: "Cycle list" },
9300
+ { keys: "d", label: "Show slot dependencies in main list" },
9301
+ { keys: "x", label: "Review flags" }
9302
+ ]
9303
+ },
9304
+ { title: "Search", entries: [{ keys: "/", label: "Search" }] },
9305
+ {
9306
+ title: "General",
9307
+ entries: [
9308
+ { keys: "f", label: "Continue" },
9309
+ { keys: "h", label: "Close help" },
9310
+ { keys: "q", label: "Quit" }
9311
+ ]
9312
+ }
9313
+ ];
9314
+ function ScopeGateScreen(props) {
9315
+ if (props.components.length === 0) {
9316
+ return /* @__PURE__ */ jsx24(Box20, { paddingX: 2, paddingY: 1, children: /* @__PURE__ */ jsx24(Text22, { color: PALETTE2.error, children: "Error: no components found for this session \u2014 please re-run analyze extract." }) });
9317
+ }
9318
+ return /* @__PURE__ */ jsx24(ScopeGateView, { ...props });
9319
+ }
9320
+ function ScopeGateView({ components, onConfirm, onQuit }) {
9321
+ const gate = useScopeGate({ components, onConfirm, onQuit });
9322
+ const { search, graph, columnPlan, panelLayout, counters } = gate;
9323
+ if (gate.showHelp) {
9324
+ return /* @__PURE__ */ jsx24(HelpOverlay, { sections: HELP_SECTIONS, handleInput: false, onClose: gate.closeHelp });
9325
+ }
9326
+ return /* @__PURE__ */ jsxs21(Box20, { flexDirection: "column", paddingX: 2, children: [
9327
+ /* @__PURE__ */ jsxs21(Box20, { flexDirection: "row", flexWrap: "wrap", children: [
9328
+ /* @__PURE__ */ jsx24(CounterStrip, { counters, totalWidth: gate.totalWidth }),
9329
+ gate.aiExcludedCount > 0 && /* @__PURE__ */ jsxs21(Text22, { color: PALETTE2.muted, children: [
9330
+ `${gate.aiExcludedCount} component${gate.aiExcludedCount === 1 ? "" : "s"} flagged by AI`,
9331
+ gate.aiRows.length > 0 && /* @__PURE__ */ jsx24(Text22, { color: PALETTE2.info, children: " \u2014 press [x] to see why" })
9332
+ ] })
9333
+ ] }),
9334
+ graph.cycles.length > 0 && /* @__PURE__ */ jsx24(Box20, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text22, { color: PALETTE2.muted, children: "If you must have components with cycles, select them together into the generate step and then use the editor to fix them." }) }),
9335
+ /* @__PURE__ */ jsxs21(Box20, { flexDirection: "row", alignItems: "stretch", children: [
9336
+ gate.aiRationalePanelOpen ? /* @__PURE__ */ jsx24(
9337
+ GotoBanner,
9338
+ {
9339
+ title: `Review flags (${gate.aiExcludedCount})`,
9340
+ rows: gate.aiRows,
9341
+ cursor: gate.aiCursor,
9342
+ maxRows: gate.panelMaxRows,
9343
+ width: columnPlan.main,
9344
+ footerHint: "[\u2191/\u2193] move \xB7 [Enter] jump \xB7 [x/Esc] close"
9345
+ }
9346
+ ) : /* @__PURE__ */ jsx24(
9347
+ GroupedSidebar,
9348
+ {
9349
+ items: gate.groupedItems,
9350
+ cycleParticipants: graph.cycleParticipants,
9351
+ selectedIdx: gate.visibleRows[gate.safeCursor]?.itemIdx ?? -1,
9352
+ selectedRowIdx: gate.safeCursor,
9353
+ onSelect: () => {
9354
+ },
9355
+ expandedGroups: gate.expandedGroups,
9356
+ onToggleExpanded: gate.toggleExpanded,
9357
+ width: columnPlan.main,
9358
+ height: panelLayout.height,
9359
+ title: "All components",
9360
+ wrapLabels: true,
9361
+ focused: gate.focusedColumn === "main",
9362
+ scrollOffset: gate.scrollOffset,
9363
+ visibleCount: gate.visibleCount,
9364
+ showFlatTier: false,
9365
+ selectionStateByKey: gate.selectionStateByKey,
9366
+ aiFlaggedByKey: gate.aiFlaggedByKey,
9367
+ dimPredicate: gate.dimPredicate,
9368
+ visibleRows: gate.visibleRows,
9369
+ viewMode: gate.columnOneView,
9370
+ graph: graph.nodes
9371
+ }
9372
+ ),
9373
+ columnPlan.layout === "two-column" && /* @__PURE__ */ jsxs21(Fragment4, { children: [
9374
+ /* @__PURE__ */ jsx24(Box20, { width: 2, flexShrink: 0 }),
9375
+ /* @__PURE__ */ jsx24(
9376
+ AddedColumn,
9377
+ {
9378
+ width: columnPlan.added,
9379
+ entries: gate.addedComponents,
9380
+ cursor: gate.safeAddedComponentsCursor,
9381
+ focused: gate.focusedColumn === "added-components",
9382
+ height: panelLayout.height,
9383
+ title: `Accepted Components (${counters.accepted}/${counters.total})`,
9384
+ aiFlaggedByKey: gate.aiFlaggedByKey,
9385
+ visibleCount: panelLayout.sideVisibleCount
9386
+ }
9387
+ )
9388
+ ] })
9389
+ ] }),
9390
+ gate.cyclesPanelOpen && /* @__PURE__ */ jsx24(CyclesPanel, { cycles: gate.slotCycles, cursor: gate.cyclesCursor }),
9391
+ gate.pendingRejectCascade && /* @__PURE__ */ jsx24(RejectPrompt, { pending: gate.pendingRejectCascade }),
9392
+ /* @__PURE__ */ jsx24(
9393
+ SearchMatchSummary,
9394
+ {
9395
+ open: search.searchOpen,
9396
+ query: search.searchQuery,
9397
+ matches: search.searchQuery ? gate.searchMatches.length : 0,
9398
+ total: components.length,
9399
+ autocompleteCandidates: search.autocompleteCandidates,
9400
+ marginTop: 1
9401
+ }
9402
+ ),
9403
+ /* @__PURE__ */ jsx24(
9404
+ CompactControlBar,
9405
+ {
9406
+ hasGroupRoots: gate.hasGroupRoots,
9407
+ searchActive: search.searchOpen || search.searchQuery.length > 0
9408
+ }
9409
+ )
9410
+ ] });
9411
+ }
9412
+
9413
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/use-scope-gate-flow.ts
9414
+ import { useEffect as useEffect8, useMemo as useMemo3, useRef as useRef5, useState as useState13 } from "react";
9415
+
9416
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/cache-check.ts
9417
+ import { execFile as execFile3 } from "node:child_process";
9418
+ function buildCacheCheckArgs(input) {
9419
+ const args = ["__generate", "components", "--agent", input.agent, "--session", input.sessionId];
9420
+ if (input.tokensPath) args.push("--tokens", input.tokensPath);
9421
+ if (input.agentModel) args.push("--model", input.agentModel);
9422
+ if (input.noCache) args.push("--no-cache");
9423
+ for (const prompt of input.promptOverrides) args.push("--prompt", prompt);
9424
+ if (input.existingEntitiesPath) args.push("--existing-entities-path", input.existingEntitiesPath);
9425
+ args.push("--cache-status", "--restore-cache");
9426
+ return args;
9427
+ }
9428
+ function parseCacheComponents(stdout) {
9429
+ const line = /^cache-components=(.+)$/m.exec(stdout)?.[1];
9430
+ if (!line) return [];
9431
+ try {
9432
+ const names = JSON.parse(line);
9433
+ return Array.isArray(names) ? names.filter((name) => typeof name === "string") : [];
9434
+ } catch {
9435
+ return [];
9436
+ }
9437
+ }
9438
+ var runLegacyCli = (args) => new Promise((resolve10) => {
9439
+ execFile3("node", [findLegacyCliPath(), ...args], (error, stdout, stderr) => {
9440
+ resolve10({ exitCode: error?.code ? Number(error.code) : 0, stdout, stderr });
9441
+ });
9442
+ });
9443
+ async function checkGenerationCache(input, run2 = runLegacyCli) {
9444
+ if (input.noCache) return [];
9445
+ try {
9446
+ const result = await run2(buildCacheCheckArgs(input));
9447
+ if (result.exitCode !== 0) return [];
9448
+ return parseCacheComponents(result.stdout);
9449
+ } catch {
9450
+ return [];
9451
+ }
9452
+ }
9453
+
9454
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/load.ts
9455
+ function loadScopeGate(sessionId) {
9456
+ try {
9457
+ const db = openPipelineDb();
9458
+ try {
9459
+ const components = loadScopeComponents(db, sessionId);
9460
+ if (components.length === 0) {
9461
+ return { ok: false, message: "No components found for this session. Please run the import again." };
9462
+ }
9463
+ return { ok: true, components };
9464
+ } finally {
9465
+ db.close();
9466
+ }
9467
+ } catch (error) {
9468
+ return {
9469
+ ok: false,
9470
+ message: `Could not read the extracted components: ${error instanceof Error ? error.message : String(error)}`
9471
+ };
9472
+ }
9473
+ }
9474
+
9475
+ // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/use-scope-gate-flow.ts
9476
+ var realDeps2 = { load: loadScopeGate, checkCache: checkGenerationCache };
9477
+ function useScopeGateFlow(input, deps = realDeps2) {
9478
+ const sessionId = input?.sessionId;
9479
+ const loaded = useMemo3(() => sessionId ? deps.load(sessionId) : void 0, [sessionId]);
9480
+ const cacheCheck = useRef5(void 0);
9481
+ const [confirmed, setConfirmed] = useState13();
9482
+ const [scope, setScope] = useState13();
9483
+ useEffect8(() => {
9484
+ if (!input || !loaded?.ok || cacheCheck.current) return;
9485
+ cacheCheck.current = deps.checkCache(input.cache);
9486
+ }, [input, loaded]);
9487
+ useEffect8(() => {
9488
+ if (!confirmed || !cacheCheck.current) return;
9489
+ let current = true;
9490
+ void cacheCheck.current.then((cachedNames) => {
9491
+ const accepted = new Set(confirmed.accepted);
9492
+ if (current) setScope({ ...confirmed, cachedNames: cachedNames.filter((name) => accepted.has(name)) });
9493
+ });
9494
+ return () => {
9495
+ current = false;
9496
+ };
9497
+ }, [confirmed]);
9498
+ if (!input || !loaded) return void 0;
9499
+ if (!loaded.ok) return { status: "failed", message: loaded.message };
9500
+ if (scope) return { status: "confirmed", scope };
9501
+ if (confirmed) return { status: "preparing" };
9502
+ return { status: "deciding", load: loaded, confirm: setConfirmed };
9503
+ }
9504
+
9505
+ // packages/experience-design-system-cli/src/tui/import/spawn-v1-import.ts
9506
+ import { spawn as spawn7 } from "node:child_process";
9507
+
9508
+ // packages/experience-design-system-cli/src/commands/import-options.ts
9509
+ function importOptionArgs(options) {
9510
+ return [
9511
+ ...options.agent ? ["--agent", options.agent] : [],
9512
+ ...options.prompt.flatMap((value) => ["--prompt", value]),
9513
+ ...options.cache ? [] : ["--no-cache"]
9514
+ ];
9515
+ }
9516
+
9517
+ // packages/experience-design-system-types/dist/src/handoff/index.js
9518
+ import * as z5 from "zod/mini";
9519
+ var HANDOFF_ENV = "EDS_IMPORT_HANDOFF";
9520
+ var NonEmpty = z5.string().check(z5.minLength(1));
9521
+ var TokensSchema = z5.object({
9522
+ /**
9523
+ * What to do about an existing `tokens.json`.
9524
+ * reuse: keep it. regenerate: build it again with the cache off. generate: nothing was asked, build it as usual.
9525
+ */
9526
+ strategy: z5.enum(["reuse", "regenerate", "generate"])
9527
+ });
9528
+ var ExtractionSchema = z5.object({
9529
+ sessionId: NonEmpty,
9530
+ outDir: NonEmpty,
9531
+ tokensPath: z5.string(),
9532
+ tokenSessionId: z5.nullable(z5.string()),
9533
+ tokenCount: z5.number(),
9534
+ existingEntitiesPath: z5.nullable(z5.string()),
9535
+ /** Never 'running': the wizard starts its background cache check only once this has settled. */
9536
+ existingEntitiesStatus: z5.enum(["idle", "complete", "failed"]),
9537
+ /** The only phases the scope gate can start from. */
9538
+ compositionPhase: z5.enum(["done", "cache-hit"])
9539
+ });
9540
+ var ScopeSchema = z5.object({
9541
+ /** The components the user kept at the scope gate. The wizard saves these, then generates them. */
9542
+ accepted: z5.array(z5.string()),
9543
+ /** Everything else at the gate, which counts as rejected. */
9544
+ rejected: z5.array(z5.string()),
9545
+ /**
9546
+ * Components the generation cache already holds, found by the check that ran while the gate was open and which has
9547
+ * finished (and restored them) before the wizard starts. Empty when the cache is off or the check failed.
9548
+ */
9549
+ cachedNames: z5.array(z5.string())
9550
+ });
9551
+ var ImportHandoffSchema = z5.object({
9552
+ /** The user skipped the credentials screen, so nothing is fetched from or pushed to Contentful. */
9553
+ credentialsSkipped: z5.boolean(),
9554
+ tokens: TokensSchema,
9555
+ /** Present once the CLI has run the extraction stage; the wizard then starts at the scope gate. */
9556
+ extraction: z5.optional(ExtractionSchema),
9557
+ /** Present once the user has confirmed the scope gate; the wizard then saves the decisions and starts generating. */
9558
+ scope: z5.optional(ScopeSchema)
9559
+ });
9560
+ function serializeHandoff(handoff) {
9561
+ return JSON.stringify(handoff);
9562
+ }
9563
+
9564
+ // packages/experience-design-system-cli/src/tui/import/spawn-v1-import.ts
9565
+ function buildArgs2(options) {
9566
+ const args = ["import"];
9567
+ if (options.projectPath) {
9568
+ args.push("--project", options.projectPath);
9569
+ }
9570
+ if (options.tokens) {
9571
+ args.push("--tokens", options.tokens);
9572
+ }
9573
+ args.push(...importOptionArgs({ agent: options.agent, prompt: options.prompt ?? [], cache: options.cache ?? true }));
9574
+ return args;
9575
+ }
9576
+ function buildEnv(options, base = process.env) {
9577
+ return { ...base, ...options.handoff ? { [HANDOFF_ENV]: serializeHandoff(options.handoff) } : {} };
9578
+ }
9579
+ async function spawnV1Import(options = {}) {
9580
+ const cliPath = findLegacyCliPath();
9581
+ const args = buildArgs2(options);
9582
+ return new Promise((resolvePromise) => {
9583
+ const child = spawn7("node", [cliPath, ...args], {
9584
+ stdio: "inherit",
9585
+ env: buildEnv(options)
9586
+ });
9587
+ child.on("close", (code) => {
9588
+ resolvePromise({ exitCode: code ?? 1, result: void 0, stdout: "", stderr: "" });
9589
+ });
9590
+ child.on("error", (err) => {
9591
+ resolvePromise({ exitCode: 1, result: void 0, stdout: "", stderr: err.message });
9592
+ });
9593
+ });
9594
+ }
9595
+
9596
+ // packages/experience-design-system-cli/src/tui/import/terminal-input.ts
9597
+ function getTerminalHandle() {
9598
+ return process.stdin._handle;
9599
+ }
9600
+ async function stopReadingTerminal() {
9601
+ await new Promise((resolve10) => setImmediate(resolve10));
9602
+ const handle = getTerminalHandle();
9603
+ if (!handle?.readStop) return;
9604
+ handle.reading = false;
9605
+ handle.readStop();
9606
+ }
9607
+ function startReadingTerminal() {
9608
+ const handle = getTerminalHandle();
9609
+ if (!handle?.readStart) return;
9610
+ handle.reading = true;
9611
+ handle.readStart();
9612
+ }
9613
+
9614
+ // packages/experience-design-system-cli/src/tui/help/PageContainer.tsx
9615
+ import { useEffect as useEffect9, useState as useState14 } from "react";
9616
+ import { Box as Box21, Text as Text23, useInput as useInput9 } from "ink";
9617
+
9618
+ // packages/experience-design-system-cli/src/tui/debug-store.ts
9619
+ import { mkdir as mkdir3, writeFile as writeFile3 } from "node:fs/promises";
9620
+ import { existsSync as existsSync5, readdirSync as readdirSync2 } from "node:fs";
9621
+ import { join as join12 } from "node:path";
9622
+
9623
+ // packages/experience-design-system-cli/src/tui/settings/debug-mode/debug-mode-store.ts
9624
+ var DEFAULT_DEBUG_MODE_SETTING = {
9625
+ enabled: true
9626
+ };
9627
+ async function readDebugModeSetting() {
9628
+ const { debugMode } = await readSettings2();
9629
+ return { ...DEFAULT_DEBUG_MODE_SETTING, ...debugMode };
9630
+ }
9631
+ async function writeDebugModeSetting(setting) {
9632
+ await updateSettings2({ debugMode: setting });
9633
+ }
9634
+
9635
+ // packages/experience-design-system-cli/src/tui/debug-store.ts
9636
+ var pendingRun;
9637
+ function generateRunId() {
9638
+ const now = /* @__PURE__ */ new Date();
9639
+ const pad = (n) => String(n).padStart(2, "0");
9640
+ return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
9641
+ }
9642
+ function datePrefix(now = /* @__PURE__ */ new Date()) {
9643
+ const pad = (n) => String(n).padStart(2, "0");
9644
+ return `${pad(now.getMonth() + 1)}-${pad(now.getDate())}-${now.getFullYear()}`;
9645
+ }
9646
+ function slugify(value) {
9647
+ return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
9648
+ }
9649
+ function generateSessionId3() {
9650
+ const today = datePrefix();
9651
+ const root = debugSessionsDir2();
9652
+ const existing = existsSync5(root) ? readdirSync2(root) : [];
9653
+ const seqPattern = new RegExp(`^${today}-session-(\\d+)$`);
9654
+ const maxSeq = existing.reduce((max, entry) => {
9655
+ const match2 = seqPattern.exec(entry);
9656
+ return match2 ? Math.max(max, Number(match2[1])) : max;
9657
+ }, 0);
9658
+ return `${today}-session-${maxSeq + 1}`;
9659
+ }
9660
+ var SESSION_ID = generateSessionId3();
9661
+ function sessionDebugDir() {
9662
+ return join12(debugSessionsDir2(), SESSION_ID);
9663
+ }
9664
+ function currentDebugSessionDir() {
9665
+ return sessionDebugDir();
9666
+ }
9667
+ void isDebugModeEnabled().then((enabled) => {
9668
+ if (!enabled) return void 0;
9669
+ return mkdir3(sessionDebugDir(), { recursive: true });
9670
+ });
9671
+ async function isDebugModeEnabled() {
9672
+ try {
9673
+ return (await readDebugModeSetting()).enabled;
9674
+ } catch {
9675
+ return true;
9676
+ }
9677
+ }
9678
+ function redact(value) {
9679
+ const clone = { ...value };
9680
+ if ("cma_token" in clone) {
9681
+ const raw = clone.cma_token;
9682
+ clone.cma_token = typeof raw === "string" && raw.length > 0 ? `[present, ${raw.length} chars]` : "[not set]";
9683
+ }
9684
+ return clone;
9685
+ }
9686
+ function startDebugRun({
9687
+ flow,
9688
+ step,
9689
+ menuOption,
9690
+ inputs
9691
+ }) {
9692
+ const runId = generateRunId();
9693
+ const startedAt = Date.now();
9694
+ const redactedInputs = redact(inputs);
9695
+ isDebugModeEnabled().then((enabled) => {
9696
+ if (!enabled) return;
9697
+ pendingRun = { flow, step, runId, menuOption, inputs: redactedInputs, startedAt };
9698
+ });
9699
+ }
9700
+ async function finishDebugRun({
9701
+ outputs,
9702
+ status,
9703
+ exitMethod
9704
+ }) {
9705
+ const run2 = pendingRun;
6883
9706
  if (!run2) return;
6884
9707
  pendingRun = void 0;
6885
9708
  const durationMs = Date.now() - run2.startedAt;
@@ -6896,8 +9719,8 @@ function nextAttemptFilename(dir, menuOption) {
6896
9719
  const existing = existsSync5(dir) ? readdirSync2(dir) : [];
6897
9720
  const attemptPattern = new RegExp(`^${today}-${optionSlug}-attempt-(\\d+)\\.md$`);
6898
9721
  const maxAttempt = existing.reduce((max, entry) => {
6899
- const match = attemptPattern.exec(entry);
6900
- return match ? Math.max(max, Number(match[1])) : max;
9722
+ const match2 = attemptPattern.exec(entry);
9723
+ return match2 ? Math.max(max, Number(match2[1])) : max;
6901
9724
  }, 0);
6902
9725
  return `${today}-${optionSlug}-attempt-${maxAttempt + 1}.md`;
6903
9726
  }
@@ -6971,19 +9794,19 @@ async function readHelpInfo() {
6971
9794
  }
6972
9795
 
6973
9796
  // packages/experience-design-system-cli/src/tui/help/PageContainer.tsx
6974
- import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
9797
+ import { Fragment as Fragment5, jsx as jsx25, jsxs as jsxs22 } from "react/jsx-runtime";
6975
9798
  function Section({ title, rows }) {
6976
- return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
6977
- /* @__PURE__ */ jsx13(Text11, { bold: true, color: PALETTE.accent, children: title }),
6978
- rows.map((row) => /* @__PURE__ */ jsxs10(Box10, { gap: 1, children: [
6979
- /* @__PURE__ */ jsx13(Box10, { width: 14, flexShrink: 0, children: /* @__PURE__ */ jsx13(Text11, { color: PALETTE.muted, children: row.label }) }),
6980
- /* @__PURE__ */ jsx13(Text11, { children: row.value })
9799
+ return /* @__PURE__ */ jsxs22(Box21, { flexDirection: "column", children: [
9800
+ /* @__PURE__ */ jsx25(Text23, { bold: true, color: PALETTE.accent, children: title }),
9801
+ rows.map((row) => /* @__PURE__ */ jsxs22(Box21, { gap: 1, children: [
9802
+ /* @__PURE__ */ jsx25(Box21, { width: 14, flexShrink: 0, children: /* @__PURE__ */ jsx25(Text23, { color: PALETTE.muted, children: row.label }) }),
9803
+ /* @__PURE__ */ jsx25(Text23, { children: row.value })
6981
9804
  ] }, row.label))
6982
9805
  ] });
6983
9806
  }
6984
9807
  function HelpScreen({ onDone }) {
6985
- const [info, setInfo] = useState9();
6986
- useEffect6(() => {
9808
+ const [info, setInfo] = useState14();
9809
+ useEffect9(() => {
6987
9810
  startDebugRun({ flow: "help", step: "01-help", menuOption: "Help", inputs: {} });
6988
9811
  void readHelpInfo().then(setInfo);
6989
9812
  }, []);
@@ -7001,14 +9824,14 @@ function HelpScreen({ onDone }) {
7001
9824
  return;
7002
9825
  }
7003
9826
  });
7004
- return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", paddingX: 2, paddingY: 1, gap: 1, children: [
7005
- /* @__PURE__ */ jsx13(Text11, { bold: true, children: "Help" }),
7006
- info ? /* @__PURE__ */ jsxs10(Fragment2, { children: [
7007
- /* @__PURE__ */ jsx13(Section, { title: "Where things are stored", rows: info.storage }),
7008
- /* @__PURE__ */ jsx13(Section, { title: "Troubleshooting", rows: info.troubleshooting }),
7009
- /* @__PURE__ */ jsx13(Text11, { color: PALETTE.muted, children: "Hit a problem? Turn on Debug Mode in Settings, reproduce it, then share the session folder above. The CMA token is redacted from those logs." })
7010
- ] }) : /* @__PURE__ */ jsx13(Text11, { color: PALETTE.accent, children: "Loading..." }),
7011
- /* @__PURE__ */ jsx13(
9827
+ return /* @__PURE__ */ jsxs22(Box21, { flexDirection: "column", paddingX: 2, paddingY: 1, gap: 1, children: [
9828
+ /* @__PURE__ */ jsx25(Text23, { bold: true, children: "Help" }),
9829
+ info ? /* @__PURE__ */ jsxs22(Fragment5, { children: [
9830
+ /* @__PURE__ */ jsx25(Section, { title: "Where things are stored", rows: info.storage }),
9831
+ /* @__PURE__ */ jsx25(Section, { title: "Troubleshooting", rows: info.troubleshooting }),
9832
+ /* @__PURE__ */ jsx25(Text23, { color: PALETTE.muted, children: "Hit a problem? Turn on Debug Mode in Settings, reproduce it, then share the session folder above. The CMA token is redacted from those logs." })
9833
+ ] }) : /* @__PURE__ */ jsx25(Text23, { color: PALETTE.accent, children: "Loading..." }),
9834
+ /* @__PURE__ */ jsx25(
7012
9835
  ControlHints,
7013
9836
  {
7014
9837
  hints: [
@@ -7021,14 +9844,14 @@ function HelpScreen({ onDone }) {
7021
9844
  }
7022
9845
 
7023
9846
  // packages/experience-design-system-cli/src/tui/settings/PageContainer.tsx
7024
- import { useState as useState10 } from "react";
7025
- import { Box as Box11, Text as Text12, useInput as useInput10 } from "ink";
7026
- import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
9847
+ import { useState as useState15 } from "react";
9848
+ import { Box as Box22, Text as Text24, useInput as useInput10 } from "ink";
9849
+ import { jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
7027
9850
  function SettingsScreen({
7028
9851
  onNavigate,
7029
9852
  onBack
7030
9853
  }) {
7031
- const [focusIdx, setFocusIdx] = useState10(0);
9854
+ const [focusIdx, setFocusIdx] = useState15(0);
7032
9855
  const items = [
7033
9856
  { label: "Configuration", screen: "settings-configuration" },
7034
9857
  { label: "Opt-in Analytics", screen: "settings-opt-in-analytics" },
@@ -7054,15 +9877,15 @@ function SettingsScreen({
7054
9877
  onBack();
7055
9878
  }
7056
9879
  });
7057
- return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
7058
- /* @__PURE__ */ jsx14(Text12, { bold: true, children: "Settings" }),
7059
- /* @__PURE__ */ jsx14(Text12, { children: " " }),
7060
- items.map((item, i) => /* @__PURE__ */ jsxs11(Text12, { color: i === focusIdx ? "cyan" : void 0, children: [
9880
+ return /* @__PURE__ */ jsxs23(Box22, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
9881
+ /* @__PURE__ */ jsx26(Text24, { bold: true, children: "Settings" }),
9882
+ /* @__PURE__ */ jsx26(Text24, { children: " " }),
9883
+ items.map((item, i) => /* @__PURE__ */ jsxs23(Text24, { color: i === focusIdx ? "cyan" : void 0, children: [
7061
9884
  i === focusIdx ? "> " : " ",
7062
9885
  item.label
7063
9886
  ] }, item.label)),
7064
- /* @__PURE__ */ jsx14(Text12, { children: " " }),
7065
- /* @__PURE__ */ jsx14(
9887
+ /* @__PURE__ */ jsx26(Text24, { children: " " }),
9888
+ /* @__PURE__ */ jsx26(
7066
9889
  ControlHints,
7067
9890
  {
7068
9891
  hints: [
@@ -7076,8 +9899,8 @@ function SettingsScreen({
7076
9899
  }
7077
9900
 
7078
9901
  // packages/experience-design-system-cli/src/tui/settings/contentful-configuration/ContentfulConfigScreen.tsx
7079
- import { useEffect as useEffect7, useState as useState11 } from "react";
7080
- import { Box as Box12, Text as Text13, useInput as useInput11 } from "ink";
9902
+ import { useEffect as useEffect10, useState as useState16 } from "react";
9903
+ import { Box as Box23, Text as Text25, useInput as useInput11 } from "ink";
7081
9904
  import TextInput4 from "ink-text-input";
7082
9905
 
7083
9906
  // packages/experience-design-system-cli/src/tui/settings/utils/v1-store.ts
@@ -7109,7 +9932,7 @@ async function writeCredentials(config) {
7109
9932
  }
7110
9933
 
7111
9934
  // packages/experience-design-system-cli/src/tui/settings/contentful-configuration/ContentfulConfigScreen.tsx
7112
- import { Fragment as Fragment3, jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
9935
+ import { Fragment as Fragment6, jsx as jsx27, jsxs as jsxs24 } from "react/jsx-runtime";
7113
9936
  var FIELD_ORDER = [
7114
9937
  "spaceId",
7115
9938
  "environmentId",
@@ -7137,14 +9960,14 @@ var FIELD_LABELS = {
7137
9960
  defaultTokenFile: "Default token file (optional)"
7138
9961
  };
7139
9962
  function ConfigurationScreen({ onDone }) {
7140
- const [stage, setStage] = useState11("loading");
7141
- const [config, setConfig] = useState11(null);
7142
- const [activeField, setActiveField] = useState11("spaceId");
7143
- const [notice, setNotice] = useState11(null);
7144
- const [lastSaved, setLastSaved] = useState11(null);
7145
- const [editing, setEditing] = useState11(false);
7146
- const [valueBeforeEdit, setValueBeforeEdit] = useState11("");
7147
- useEffect7(() => {
9963
+ const [stage, setStage] = useState16("loading");
9964
+ const [config, setConfig] = useState16(null);
9965
+ const [activeField, setActiveField] = useState16("spaceId");
9966
+ const [notice, setNotice] = useState16(null);
9967
+ const [lastSaved, setLastSaved] = useState16(null);
9968
+ const [editing, setEditing] = useState16(false);
9969
+ const [valueBeforeEdit, setValueBeforeEdit] = useState16("");
9970
+ useEffect10(() => {
7148
9971
  readCredentials().then((cfg) => {
7149
9972
  setConfig(cfg);
7150
9973
  setStage("form");
@@ -7221,26 +10044,26 @@ function ConfigurationScreen({ onDone }) {
7221
10044
  }
7222
10045
  });
7223
10046
  if (stage === "loading") {
7224
- return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
7225
- /* @__PURE__ */ jsx15(Text13, { bold: true, children: "Configuration" }),
7226
- /* @__PURE__ */ jsx15(Text13, { children: " " }),
7227
- /* @__PURE__ */ jsx15(Text13, { color: PALETTE.accent, children: "Loading..." })
10047
+ return /* @__PURE__ */ jsxs24(Box23, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
10048
+ /* @__PURE__ */ jsx27(Text25, { bold: true, children: "Configuration" }),
10049
+ /* @__PURE__ */ jsx27(Text25, { children: " " }),
10050
+ /* @__PURE__ */ jsx27(Text25, { color: PALETTE.accent, children: "Loading..." })
7228
10051
  ] });
7229
10052
  }
7230
- return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
7231
- /* @__PURE__ */ jsx15(Text13, { bold: true, children: "Configuration" }),
7232
- /* @__PURE__ */ jsx15(Text13, { children: " " }),
7233
- /* @__PURE__ */ jsx15(Box12, { flexDirection: "column", children: FIELD_ORDER.map((field) => {
10053
+ return /* @__PURE__ */ jsxs24(Box23, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
10054
+ /* @__PURE__ */ jsx27(Text25, { bold: true, children: "Configuration" }),
10055
+ /* @__PURE__ */ jsx27(Text25, { children: " " }),
10056
+ /* @__PURE__ */ jsx27(Box23, { flexDirection: "column", children: FIELD_ORDER.map((field) => {
7234
10057
  const isActive = activeField === field;
7235
10058
  const value = fieldValue(field);
7236
10059
  const display = field === "cmaToken" ? "\u2022".repeat(value.length) : value;
7237
- return /* @__PURE__ */ jsxs12(Box12, { gap: 1, children: [
7238
- /* @__PURE__ */ jsx15(Text13, { color: isActive ? PALETTE.accent : void 0, children: isActive ? "\u276F" : " " }),
7239
- /* @__PURE__ */ jsxs12(Text13, { bold: isActive, children: [
10060
+ return /* @__PURE__ */ jsxs24(Box23, { gap: 1, children: [
10061
+ /* @__PURE__ */ jsx27(Text25, { color: isActive ? PALETTE.accent : void 0, children: isActive ? "\u276F" : " " }),
10062
+ /* @__PURE__ */ jsxs24(Text25, { bold: isActive, children: [
7240
10063
  FIELD_LABELS[field],
7241
10064
  ":"
7242
10065
  ] }),
7243
- isActive && editing ? /* @__PURE__ */ jsx15(
10066
+ isActive && editing ? /* @__PURE__ */ jsx27(
7244
10067
  TextInput4,
7245
10068
  {
7246
10069
  value,
@@ -7248,19 +10071,19 @@ function ConfigurationScreen({ onDone }) {
7248
10071
  onSubmit: () => setEditing(false),
7249
10072
  mask: field === "cmaToken" ? "\u2022" : void 0
7250
10073
  }
7251
- ) : /* @__PURE__ */ jsx15(Text13, { children: display || /* @__PURE__ */ jsx15(Text13, { color: PALETTE.muted, children: "(empty)" }) })
10074
+ ) : /* @__PURE__ */ jsx27(Text25, { children: display || /* @__PURE__ */ jsx27(Text25, { color: PALETTE.muted, children: "(empty)" }) })
7252
10075
  ] }, field);
7253
10076
  }) }),
7254
- notice && /* @__PURE__ */ jsxs12(Fragment3, { children: [
7255
- /* @__PURE__ */ jsx15(Text13, { children: " " }),
7256
- /* @__PURE__ */ jsxs12(Text13, { color: notice.kind === "success" ? PALETTE.success : PALETTE.error, children: [
10077
+ notice && /* @__PURE__ */ jsxs24(Fragment6, { children: [
10078
+ /* @__PURE__ */ jsx27(Text25, { children: " " }),
10079
+ /* @__PURE__ */ jsxs24(Text25, { color: notice.kind === "success" ? PALETTE.success : PALETTE.error, children: [
7257
10080
  notice.kind === "success" ? "\u2713" : "\u2717",
7258
10081
  " ",
7259
10082
  notice.text
7260
10083
  ] })
7261
10084
  ] }),
7262
- /* @__PURE__ */ jsx15(Text13, { children: " " }),
7263
- /* @__PURE__ */ jsx15(
10085
+ /* @__PURE__ */ jsx27(Text25, { children: " " }),
10086
+ /* @__PURE__ */ jsx27(
7264
10087
  ControlHints,
7265
10088
  {
7266
10089
  hints: editing ? [
@@ -7281,8 +10104,8 @@ function ConfigurationScreen({ onDone }) {
7281
10104
  }
7282
10105
 
7283
10106
  // packages/experience-design-system-cli/src/tui/settings/opt-in-analytics/screen.tsx
7284
- import { useEffect as useEffect8, useState as useState12 } from "react";
7285
- import { Box as Box13, Text as Text14, useInput as useInput12 } from "ink";
10107
+ import { useEffect as useEffect11, useState as useState17 } from "react";
10108
+ import { Box as Box24, Text as Text26, useInput as useInput12 } from "ink";
7286
10109
 
7287
10110
  // packages/experience-design-system-cli/src/tui/settings/opt-in-analytics/analytics-store.ts
7288
10111
  async function readAnalyticsSetting() {
@@ -7300,11 +10123,11 @@ async function writeAnalyticsSetting(setting) {
7300
10123
  }
7301
10124
 
7302
10125
  // packages/experience-design-system-cli/src/tui/settings/opt-in-analytics/screen.tsx
7303
- import { Fragment as Fragment4, jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
10126
+ import { Fragment as Fragment7, jsx as jsx28, jsxs as jsxs25 } from "react/jsx-runtime";
7304
10127
  function OptInAnalyticsScreen({ onDone }) {
7305
- const [loading, setLoading] = useState12(true);
7306
- const [enabled, setEnabled] = useState12(true);
7307
- useEffect8(() => {
10128
+ const [loading, setLoading] = useState17(true);
10129
+ const [enabled, setEnabled] = useState17(true);
10130
+ useEffect11(() => {
7308
10131
  readAnalyticsSetting().then((setting) => {
7309
10132
  setEnabled(setting.enabled);
7310
10133
  setLoading(false);
@@ -7331,21 +10154,21 @@ function OptInAnalyticsScreen({ onDone }) {
7331
10154
  onDone();
7332
10155
  }
7333
10156
  });
7334
- return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
7335
- /* @__PURE__ */ jsx16(Text14, { bold: true, children: "Settings \u203A Opt-in Analytics" }),
7336
- /* @__PURE__ */ jsx16(Text14, { children: " " }),
7337
- loading ? /* @__PURE__ */ jsx16(Text14, { color: PALETTE.muted, children: "Loading\u2026" }) : /* @__PURE__ */ jsxs13(Fragment4, { children: [
7338
- /* @__PURE__ */ jsxs13(Text14, { children: [
10157
+ return /* @__PURE__ */ jsxs25(Box24, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
10158
+ /* @__PURE__ */ jsx28(Text26, { bold: true, children: "Settings \u203A Opt-in Analytics" }),
10159
+ /* @__PURE__ */ jsx28(Text26, { children: " " }),
10160
+ loading ? /* @__PURE__ */ jsx28(Text26, { color: PALETTE.muted, children: "Loading\u2026" }) : /* @__PURE__ */ jsxs25(Fragment7, { children: [
10161
+ /* @__PURE__ */ jsxs25(Text26, { children: [
7339
10162
  "Share anonymous usage data:",
7340
10163
  " ",
7341
- /* @__PURE__ */ jsx16(Text14, { bold: true, color: enabled ? PALETTE.success : PALETTE.muted, children: enabled ? "On" : "Off" })
10164
+ /* @__PURE__ */ jsx28(Text26, { bold: true, color: enabled ? PALETTE.success : PALETTE.muted, children: enabled ? "On" : "Off" })
7342
10165
  ] }),
7343
- /* @__PURE__ */ jsx16(Text14, { children: " " }),
7344
- /* @__PURE__ */ jsx16(Text14, { color: PALETTE.muted, children: "Shares which CLI commands are used and where imports succeed or fail." }),
7345
- /* @__PURE__ */ jsx16(Text14, { color: PALETTE.muted, children: "Never includes source code, file paths, credentials, or authored content." })
10166
+ /* @__PURE__ */ jsx28(Text26, { children: " " }),
10167
+ /* @__PURE__ */ jsx28(Text26, { color: PALETTE.muted, children: "Shares which CLI commands are used and where imports succeed or fail." }),
10168
+ /* @__PURE__ */ jsx28(Text26, { color: PALETTE.muted, children: "Never includes source code, file paths, credentials, or authored content." })
7346
10169
  ] }),
7347
- /* @__PURE__ */ jsx16(Text14, { children: " " }),
7348
- /* @__PURE__ */ jsx16(
10170
+ /* @__PURE__ */ jsx28(Text26, { children: " " }),
10171
+ /* @__PURE__ */ jsx28(
7349
10172
  ControlHints,
7350
10173
  {
7351
10174
  hints: [
@@ -7358,13 +10181,13 @@ function OptInAnalyticsScreen({ onDone }) {
7358
10181
  }
7359
10182
 
7360
10183
  // packages/experience-design-system-cli/src/tui/upgrade/PageContainer.tsx
7361
- import { useEffect as useEffect9, useState as useState13 } from "react";
7362
- import { Box as Box14, Text as Text15, useInput as useInput13 } from "ink";
7363
- import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
10184
+ import { useEffect as useEffect12, useState as useState18 } from "react";
10185
+ import { Box as Box25, Text as Text27, useInput as useInput13 } from "ink";
10186
+ import { jsx as jsx29, jsxs as jsxs26 } from "react/jsx-runtime";
7364
10187
  var UPGRADE_COMMANDS = ["git pull", "pnpm install", "pnpm build"];
7365
10188
  function UpgradeScreen({ onDone }) {
7366
- const [upgradeCheck, setUpgradeCheck] = useState13();
7367
- useEffect9(() => {
10189
+ const [upgradeCheck, setUpgradeCheck] = useState18();
10190
+ useEffect12(() => {
7368
10191
  startDebugRun({
7369
10192
  flow: "upgrade",
7370
10193
  step: "01-upgrade",
@@ -7384,12 +10207,12 @@ function UpgradeScreen({ onDone }) {
7384
10207
  return;
7385
10208
  }
7386
10209
  });
7387
- return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
7388
- /* @__PURE__ */ jsx17(Text15, { bold: true, children: "Upgrade" }),
7389
- /* @__PURE__ */ jsx17(Text15, { children: " " }),
10210
+ return /* @__PURE__ */ jsxs26(Box25, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
10211
+ /* @__PURE__ */ jsx29(Text27, { bold: true, children: "Upgrade" }),
10212
+ /* @__PURE__ */ jsx29(Text27, { children: " " }),
7390
10213
  renderBody(upgradeCheck),
7391
- /* @__PURE__ */ jsx17(Text15, { children: " " }),
7392
- /* @__PURE__ */ jsxs14(Text15, { bold: true, color: PALETTE.accent, children: [
10214
+ /* @__PURE__ */ jsx29(Text27, { children: " " }),
10215
+ /* @__PURE__ */ jsxs26(Text27, { bold: true, color: PALETTE.accent, children: [
7393
10216
  FOCUS_MARKER,
7394
10217
  " Go Back"
7395
10218
  ] })
@@ -7397,45 +10220,45 @@ function UpgradeScreen({ onDone }) {
7397
10220
  }
7398
10221
  function renderBody(upgradeCheck) {
7399
10222
  if (!upgradeCheck) {
7400
- return /* @__PURE__ */ jsx17(Text15, { color: PALETTE.muted, children: "Checking for updates\u2026" });
10223
+ return /* @__PURE__ */ jsx29(Text27, { color: PALETTE.muted, children: "Checking for updates\u2026" });
7401
10224
  }
7402
10225
  if (upgradeCheck.status === "error") {
7403
- return /* @__PURE__ */ jsx17(Text15, { color: PALETTE.warning, children: "Couldn't check for updates \u2014 check your network connection and try again." });
10226
+ return /* @__PURE__ */ jsx29(Text27, { color: PALETTE.warning, children: "Couldn't check for updates \u2014 check your network connection and try again." });
7404
10227
  }
7405
10228
  if (upgradeCheck.status === "up-to-date") {
7406
- return /* @__PURE__ */ jsxs14(Text15, { color: PALETTE.success, children: [
10229
+ return /* @__PURE__ */ jsxs26(Text27, { color: PALETTE.success, children: [
7407
10230
  "You're already on the latest version (v",
7408
10231
  upgradeCheck.current,
7409
10232
  ")."
7410
10233
  ] });
7411
10234
  }
7412
- return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
7413
- /* @__PURE__ */ jsxs14(Text15, { color: PALETTE.muted, children: [
7414
- /* @__PURE__ */ jsxs14(Text15, { bold: true, color: PALETTE.success, children: [
10235
+ return /* @__PURE__ */ jsxs26(Box25, { flexDirection: "column", children: [
10236
+ /* @__PURE__ */ jsxs26(Text27, { color: PALETTE.muted, children: [
10237
+ /* @__PURE__ */ jsxs26(Text27, { bold: true, color: PALETTE.success, children: [
7415
10238
  "v",
7416
10239
  upgradeCheck.latest
7417
10240
  ] }),
7418
10241
  " ",
7419
10242
  "is available (you're on ",
7420
- /* @__PURE__ */ jsxs14(Text15, { bold: true, children: [
10243
+ /* @__PURE__ */ jsxs26(Text27, { bold: true, children: [
7421
10244
  "v",
7422
10245
  upgradeCheck.current
7423
10246
  ] }),
7424
10247
  "). Exit this program, cd into the root of your local clone of contentful/experience-design-system-sdk-public, then run:"
7425
10248
  ] }),
7426
- /* @__PURE__ */ jsx17(Text15, { children: " " }),
7427
- /* @__PURE__ */ jsx17(Box14, { flexDirection: "column", borderStyle: "round", borderColor: PALETTE.border, paddingX: 1, children: UPGRADE_COMMANDS.map((cmd) => /* @__PURE__ */ jsx17(Text15, { bold: true, children: cmd }, cmd)) })
10249
+ /* @__PURE__ */ jsx29(Text27, { children: " " }),
10250
+ /* @__PURE__ */ jsx29(Box25, { flexDirection: "column", borderStyle: "round", borderColor: PALETTE.border, paddingX: 1, children: UPGRADE_COMMANDS.map((cmd) => /* @__PURE__ */ jsx29(Text27, { bold: true, children: cmd }, cmd)) })
7428
10251
  ] });
7429
10252
  }
7430
10253
 
7431
10254
  // packages/experience-design-system-cli/src/tui/settings/debug-mode/screen.tsx
7432
- import { useEffect as useEffect10, useState as useState14 } from "react";
7433
- import { Box as Box15, Text as Text16, useInput as useInput14 } from "ink";
7434
- import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
10255
+ import { useEffect as useEffect13, useState as useState19 } from "react";
10256
+ import { Box as Box26, Text as Text28, useInput as useInput14 } from "ink";
10257
+ import { jsx as jsx30, jsxs as jsxs27 } from "react/jsx-runtime";
7435
10258
  function DebugModeScreen({ onDone }) {
7436
- const [loading, setLoading] = useState14(true);
7437
- const [enabled, setEnabled] = useState14(true);
7438
- useEffect10(() => {
10259
+ const [loading, setLoading] = useState19(true);
10260
+ const [enabled, setEnabled] = useState19(true);
10261
+ useEffect13(() => {
7439
10262
  readDebugModeSetting().then((setting) => {
7440
10263
  setEnabled(setting.enabled);
7441
10264
  setLoading(false);
@@ -7462,16 +10285,16 @@ function DebugModeScreen({ onDone }) {
7462
10285
  onDone();
7463
10286
  }
7464
10287
  });
7465
- return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
7466
- /* @__PURE__ */ jsx18(Text16, { bold: true, children: "Settings \u203A Debug Mode" }),
7467
- /* @__PURE__ */ jsx18(Text16, { children: " " }),
7468
- loading ? /* @__PURE__ */ jsx18(Text16, { color: PALETTE.muted, children: "Loading\u2026" }) : /* @__PURE__ */ jsxs15(Text16, { children: [
10288
+ return /* @__PURE__ */ jsxs27(Box26, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
10289
+ /* @__PURE__ */ jsx30(Text28, { bold: true, children: "Settings \u203A Debug Mode" }),
10290
+ /* @__PURE__ */ jsx30(Text28, { children: " " }),
10291
+ loading ? /* @__PURE__ */ jsx30(Text28, { color: PALETTE.muted, children: "Loading\u2026" }) : /* @__PURE__ */ jsxs27(Text28, { children: [
7469
10292
  "Debug logging:",
7470
10293
  " ",
7471
- /* @__PURE__ */ jsx18(Text16, { bold: true, color: enabled ? PALETTE.success : PALETTE.muted, children: enabled ? "On" : "Off" })
10294
+ /* @__PURE__ */ jsx30(Text28, { bold: true, color: enabled ? PALETTE.success : PALETTE.muted, children: enabled ? "On" : "Off" })
7472
10295
  ] }),
7473
- /* @__PURE__ */ jsx18(Text16, { children: " " }),
7474
- /* @__PURE__ */ jsx18(
10296
+ /* @__PURE__ */ jsx30(Text28, { children: " " }),
10297
+ /* @__PURE__ */ jsx30(
7475
10298
  ControlHints,
7476
10299
  {
7477
10300
  hints: [
@@ -7484,19 +10307,34 @@ function DebugModeScreen({ onDone }) {
7484
10307
  }
7485
10308
 
7486
10309
  // packages/experience-design-system-cli/app.tsx
7487
- import { Fragment as Fragment5, jsx as jsx19 } from "react/jsx-runtime";
10310
+ import { Fragment as Fragment8, jsx as jsx31 } from "react/jsx-runtime";
7488
10311
  function App({ importOptions, onLaunchImport, importExitCode }) {
7489
10312
  const returnedFromImport = importExitCode !== void 0;
7490
- const [screen, setScreen] = useState15(returnedFromImport ? "import" : "start");
7491
- const [showImportResult, setShowImportResult] = useState15(returnedFromImport);
7492
- const [projectPath, setProjectPath] = useState15();
7493
- const [tokensPath, setTokensPath] = useState15();
7494
- const [scannedFiles, setScannedFiles] = useState15();
7495
- const [pendingLaunch, setPendingLaunch] = useState15();
7496
- const [extractionRun, setExtractionRun] = useState15();
10313
+ const [screen, setScreen] = useState20(returnedFromImport ? "import" : "start");
10314
+ const [showImportResult, setShowImportResult] = useState20(returnedFromImport);
10315
+ const [projectPath, setProjectPath] = useState20();
10316
+ const [tokensPath, setTokensPath] = useState20();
10317
+ const [scannedFiles, setScannedFiles] = useState20();
10318
+ const [pendingLaunch, setPendingLaunch] = useState20();
10319
+ const [extractionRun, setExtractionRun] = useState20();
7497
10320
  const extraction = useExtraction(extractionRun?.input);
7498
- const [importDefaults, setImportDefaults] = useState15();
7499
- useEffect11(() => {
10321
+ const [scopeRun, setScopeRun] = useState20();
10322
+ const scopeFlow = useScopeGateFlow(
10323
+ scopeRun && {
10324
+ sessionId: scopeRun.extraction.sessionId,
10325
+ cache: {
10326
+ sessionId: scopeRun.extraction.sessionId,
10327
+ tokensPath: scopeRun.extraction.tokensPath,
10328
+ agent: scopeRun.input.agent,
10329
+ ...scopeRun.input.agentModel ? { agentModel: scopeRun.input.agentModel } : {},
10330
+ promptOverrides: scopeRun.input.promptOverrides,
10331
+ existingEntitiesPath: scopeRun.extraction.existingEntitiesPath,
10332
+ noCache: scopeRun.input.noCache
10333
+ }
10334
+ }
10335
+ );
10336
+ const [importDefaults, setImportDefaults] = useState20();
10337
+ useEffect14(() => {
7500
10338
  if (screen !== "import") {
7501
10339
  setImportDefaults(void 0);
7502
10340
  return;
@@ -7550,15 +10388,25 @@ function App({ importOptions, onLaunchImport, importExitCode }) {
7550
10388
  }
7551
10389
  });
7552
10390
  };
7553
- useEffect11(() => {
10391
+ useEffect14(() => {
7554
10392
  if (!extractionRun || extraction?.status !== "done" || !extraction.result.ok) return;
7555
- const { launch, credentialsSkipped, tokenStrategy } = extractionRun;
7556
10393
  setExtractionRun(void 0);
10394
+ setScopeRun({ ...extractionRun, extraction: extraction.result.extraction });
10395
+ }, [extraction, extractionRun]);
10396
+ useEffect14(() => {
10397
+ if (!scopeRun || scopeFlow?.status !== "confirmed") return;
10398
+ const { launch, credentialsSkipped, tokenStrategy, extraction: produced } = scopeRun;
10399
+ setScopeRun(void 0);
7557
10400
  onLaunchImport?.({
7558
10401
  ...launch,
7559
- handoff: { credentialsSkipped, tokens: { strategy: tokenStrategy }, extraction: extraction.result.extraction }
10402
+ handoff: {
10403
+ credentialsSkipped,
10404
+ tokens: { strategy: tokenStrategy },
10405
+ extraction: produced,
10406
+ scope: scopeFlow.scope
10407
+ }
7560
10408
  });
7561
- }, [extraction, extractionRun]);
10409
+ }, [scopeFlow, scopeRun]);
7562
10410
  const goToStart = () => setScreen("start");
7563
10411
  const goToSettings = () => setScreen("settings");
7564
10412
  const resetImport = () => {
@@ -7567,6 +10415,7 @@ function App({ importOptions, onLaunchImport, importExitCode }) {
7567
10415
  setScannedFiles(void 0);
7568
10416
  setPendingLaunch(void 0);
7569
10417
  setExtractionRun(void 0);
10418
+ setScopeRun(void 0);
7570
10419
  };
7571
10420
  const finishImportResult = () => {
7572
10421
  setShowImportResult(false);
@@ -7579,13 +10428,13 @@ function App({ importOptions, onLaunchImport, importExitCode }) {
7579
10428
  };
7580
10429
  switch (screen) {
7581
10430
  case "import":
7582
- if (showImportResult) return /* @__PURE__ */ jsx19(ImportScreen, { exitCode: importExitCode, onDone: finishImportResult });
7583
- if (importDefaults === void 0) return /* @__PURE__ */ jsx19(Fragment5, {});
10431
+ if (showImportResult) return /* @__PURE__ */ jsx31(ImportScreen, { exitCode: importExitCode, onDone: finishImportResult });
10432
+ if (importDefaults === void 0) return /* @__PURE__ */ jsx31(Fragment8, {});
7584
10433
  if (projectPath === void 0) {
7585
- return /* @__PURE__ */ jsx19(WelcomeScreen, { onContinue: setProjectPath, onQuit: leaveImport, initialPath: importDefaults.componentDir });
10434
+ return /* @__PURE__ */ jsx31(WelcomeScreen, { onContinue: setProjectPath, onQuit: leaveImport, initialPath: importDefaults.componentDir });
7586
10435
  }
7587
10436
  if (tokensPath === void 0) {
7588
- return /* @__PURE__ */ jsx19(
10437
+ return /* @__PURE__ */ jsx31(
7589
10438
  TokenInputScreen,
7590
10439
  {
7591
10440
  initialPath: importDefaults.tokenFile,
@@ -7595,7 +10444,7 @@ function App({ importOptions, onLaunchImport, importExitCode }) {
7595
10444
  );
7596
10445
  }
7597
10446
  if (scannedFiles === void 0) {
7598
- return /* @__PURE__ */ jsx19(
10447
+ return /* @__PURE__ */ jsx31(
7599
10448
  PathValidationScreen,
7600
10449
  {
7601
10450
  projectPath,
@@ -7607,10 +10456,10 @@ function App({ importOptions, onLaunchImport, importExitCode }) {
7607
10456
  }
7608
10457
  if (extractionRun) {
7609
10458
  if (extraction?.status === "done" && !extraction.result.ok) {
7610
- return /* @__PURE__ */ jsx19(ErrorStep, { stepName: extraction.result.step, message: extraction.result.message, onExit: leaveImport });
10459
+ return /* @__PURE__ */ jsx31(ErrorStep, { stepName: extraction.result.step, message: extraction.result.message, onExit: leaveImport });
7611
10460
  }
7612
10461
  if (extraction?.status === "running") {
7613
- return /* @__PURE__ */ jsx19(
10462
+ return /* @__PURE__ */ jsx31(
7614
10463
  ExtractionScreen,
7615
10464
  {
7616
10465
  progress: extraction.progress,
@@ -7619,10 +10468,35 @@ function App({ importOptions, onLaunchImport, importExitCode }) {
7619
10468
  }
7620
10469
  );
7621
10470
  }
7622
- return /* @__PURE__ */ jsx19(Fragment5, {});
10471
+ return /* @__PURE__ */ jsx31(Fragment8, {});
10472
+ }
10473
+ if (scopeRun && scopeFlow) {
10474
+ if (scopeFlow.status === "failed") {
10475
+ return /* @__PURE__ */ jsx31(ErrorStep, { stepName: "scope gate", message: scopeFlow.message, onExit: leaveImport });
10476
+ }
10477
+ if (scopeFlow.status === "deciding") {
10478
+ return /* @__PURE__ */ jsx31(
10479
+ ScopeGateScreen,
10480
+ {
10481
+ components: scopeFlow.load.components,
10482
+ onConfirm: scopeFlow.confirm,
10483
+ onQuit: leaveImport
10484
+ }
10485
+ );
10486
+ }
10487
+ const numbers = stepNumbers({ hasRawTokens: scopeRun.input.rawTokensPath !== "" });
10488
+ return /* @__PURE__ */ jsx31(
10489
+ RunningStep,
10490
+ {
10491
+ stepNumber: numbers.stepNumber + 1,
10492
+ totalSteps: numbers.totalSteps,
10493
+ title: "Preparing",
10494
+ description: "Checking which components are already generated..."
10495
+ }
10496
+ );
7623
10497
  }
7624
10498
  if (pendingLaunch?.cached) {
7625
- return /* @__PURE__ */ jsx19(
10499
+ return /* @__PURE__ */ jsx31(
7626
10500
  TokenReuseScreen,
7627
10501
  {
7628
10502
  tokensPath: pendingLaunch.cached.tokensPath,
@@ -7633,7 +10507,7 @@ function App({ importOptions, onLaunchImport, importExitCode }) {
7633
10507
  }
7634
10508
  );
7635
10509
  }
7636
- return /* @__PURE__ */ jsx19(
10510
+ return /* @__PURE__ */ jsx31(
7637
10511
  CredentialsScreen,
7638
10512
  {
7639
10513
  initial: importDefaults.credentials,
@@ -7642,26 +10516,26 @@ function App({ importOptions, onLaunchImport, importExitCode }) {
7642
10516
  }
7643
10517
  );
7644
10518
  case "help":
7645
- return /* @__PURE__ */ jsx19(HelpScreen, { onDone: goToStart });
10519
+ return /* @__PURE__ */ jsx31(HelpScreen, { onDone: goToStart });
7646
10520
  case "upgrade":
7647
- return /* @__PURE__ */ jsx19(UpgradeScreen, { onDone: goToStart });
10521
+ return /* @__PURE__ */ jsx31(UpgradeScreen, { onDone: goToStart });
7648
10522
  case "settings":
7649
- return /* @__PURE__ */ jsx19(SettingsScreen, { onNavigate: setScreen, onBack: goToStart });
10523
+ return /* @__PURE__ */ jsx31(SettingsScreen, { onNavigate: setScreen, onBack: goToStart });
7650
10524
  case "settings-configuration":
7651
- return /* @__PURE__ */ jsx19(ConfigurationScreen, { onDone: goToSettings });
10525
+ return /* @__PURE__ */ jsx31(ConfigurationScreen, { onDone: goToSettings });
7652
10526
  case "settings-opt-in-analytics":
7653
- return /* @__PURE__ */ jsx19(OptInAnalyticsScreen, { onDone: goToSettings });
10527
+ return /* @__PURE__ */ jsx31(OptInAnalyticsScreen, { onDone: goToSettings });
7654
10528
  case "settings-debug-mode":
7655
- return /* @__PURE__ */ jsx19(DebugModeScreen, { onDone: goToSettings });
10529
+ return /* @__PURE__ */ jsx31(DebugModeScreen, { onDone: goToSettings });
7656
10530
  case "start":
7657
- return /* @__PURE__ */ jsx19(HomeScreen, { onNavigate: setScreen });
10531
+ return /* @__PURE__ */ jsx31(HomeScreen, { onNavigate: setScreen });
7658
10532
  }
7659
10533
  }
7660
10534
  var CLEAR_SCREEN = "\x1B[2J\x1B[H";
7661
10535
  async function renderUntilImportRequestedOrExit(renderApp, importOptions, importExitCode) {
7662
10536
  let requestedImport;
7663
10537
  const instance = renderApp(
7664
- /* @__PURE__ */ jsx19(
10538
+ /* @__PURE__ */ jsx31(
7665
10539
  App,
7666
10540
  {
7667
10541
  importOptions,