@contentful/experience-design-system-cli 2.37.1-dev-build-845e7310.0 → 2.37.1-dev-build-e9daa6a1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/app.js CHANGED
@@ -821,6 +821,16 @@ var init_parse_map_token_prop_tool_calls = __esm({
821
821
 
822
822
  // packages/experience-design-system-backend-pipeline/dist/src/agents/services/run-agent.js
823
823
  import { spawn } from "node:child_process";
824
+ function killProcessTree(pid, signal) {
825
+ try {
826
+ process.kill(-pid, signal);
827
+ } catch {
828
+ try {
829
+ process.kill(pid, signal);
830
+ } catch {
831
+ }
832
+ }
833
+ }
824
834
  async function runAgent(options) {
825
835
  const { agent, prompt, timeoutMs, model, onOutput, promptViaStdin, onDebugEvent } = options;
826
836
  const bedrock = options.bedrock ?? process.env.EDS_BEDROCK === "1";
@@ -837,10 +847,11 @@ async function runAgent(options) {
837
847
  promptLen: prompt.length,
838
848
  promptHead: prompt.slice(0, 500)
839
849
  });
840
- return new Promise((resolve28) => {
850
+ return new Promise((resolve29) => {
841
851
  const bedrockEnv = bedrock ? BEDROCK_ENV_BY_AGENT[agent] : void 0;
842
852
  const child = spawn(binary, args, {
843
853
  stdio: ["pipe", "pipe", "pipe"],
854
+ detached: true,
844
855
  ...bedrockEnv ? { env: { ...process.env, ...bedrockEnv } } : {}
845
856
  });
846
857
  if (useStdin2 && child.stdin) {
@@ -852,50 +863,87 @@ async function runAgent(options) {
852
863
  } else {
853
864
  child.stdin?.end();
854
865
  }
855
- let stdout = "";
856
- let stderr = "";
866
+ const stdoutChunks = [];
867
+ const stderrChunks = [];
857
868
  let timedOut = false;
858
- const timer = setTimeout(() => {
869
+ let settled = false;
870
+ const pid = child.pid;
871
+ const settle = (result) => {
872
+ if (settled)
873
+ return;
874
+ settled = true;
875
+ clearTimeout(softTimer);
876
+ clearTimeout(hardTimer);
877
+ onDebugEvent?.("run.end", {
878
+ agent,
879
+ model,
880
+ durationMs: Date.now() - startedAt,
881
+ exitCode: result.exitCode,
882
+ timedOut: result.timedOut,
883
+ stdoutLen: result.stdout.length,
884
+ stderrLen: result.stderr.length,
885
+ stderrTail: result.stderr.slice(-1e3)
886
+ });
887
+ resolve29(result);
888
+ };
889
+ const softTimer = setTimeout(() => {
859
890
  timedOut = true;
860
- child.kill("SIGTERM");
891
+ if (pid)
892
+ killProcessTree(pid, "SIGTERM");
861
893
  }, timeoutMs);
894
+ const hardTimer = setTimeout(() => {
895
+ if (settled)
896
+ return;
897
+ if (pid)
898
+ killProcessTree(pid, "SIGKILL");
899
+ try {
900
+ child.stdout?.destroy();
901
+ child.stderr?.destroy();
902
+ child.stdin?.destroy();
903
+ } catch {
904
+ }
905
+ settle({
906
+ exitCode: 1,
907
+ stdout: Buffer.concat(stdoutChunks).toString("utf8"),
908
+ stderr: Buffer.concat(stderrChunks).toString("utf8"),
909
+ timedOut: true
910
+ });
911
+ }, timeoutMs + WATCHDOG_GRACE_MS);
862
912
  child.stdout?.on("data", (chunk) => {
863
- const text = chunk.toString();
864
- stdout += text;
865
- onOutput?.(text);
913
+ stdoutChunks.push(chunk);
914
+ if (onOutput)
915
+ onOutput(chunk.toString("utf8"));
866
916
  });
867
917
  child.stderr?.on("data", (chunk) => {
868
- stderr += chunk.toString();
918
+ stderrChunks.push(chunk);
919
+ });
920
+ child.on("error", (err) => {
921
+ settle({
922
+ exitCode: 1,
923
+ stdout: Buffer.concat(stdoutChunks).toString("utf8"),
924
+ stderr: `${err instanceof Error ? err.message : String(err)}
925
+ ${Buffer.concat(stderrChunks).toString("utf8")}`,
926
+ timedOut
927
+ });
869
928
  });
870
929
  child.on("close", (code, signal) => {
871
- clearTimeout(timer);
872
- const result = {
930
+ settle({
873
931
  exitCode: signal ? 1 : code ?? 1,
874
- stdout,
875
- stderr,
932
+ stdout: Buffer.concat(stdoutChunks).toString("utf8"),
933
+ stderr: Buffer.concat(stderrChunks).toString("utf8"),
876
934
  timedOut
877
- };
878
- onDebugEvent?.("run.end", {
879
- agent,
880
- model,
881
- durationMs: Date.now() - startedAt,
882
- exitCode: result.exitCode,
883
- signal,
884
- timedOut,
885
- stdoutLen: stdout.length,
886
- stderrLen: stderr.length,
887
- stderrTail: stderr.slice(-1e3)
888
935
  });
889
- resolve28(result);
890
936
  });
891
937
  });
892
938
  }
939
+ var WATCHDOG_GRACE_MS;
893
940
  var init_run_agent = __esm({
894
941
  "packages/experience-design-system-backend-pipeline/dist/src/agents/services/run-agent.js"() {
895
942
  "use strict";
896
943
  init_bedrock();
897
944
  init_build_agent_args();
898
945
  init_resolve_binary();
946
+ WATCHDOG_GRACE_MS = 10 * 1e3;
899
947
  }
900
948
  });
901
949
 
@@ -908,7 +956,7 @@ async function checkAgentAuth(agent) {
908
956
  return "not-found";
909
957
  if (agent !== "claude")
910
958
  return "ok";
911
- return new Promise((resolve28) => {
959
+ return new Promise((resolve29) => {
912
960
  const child = spawn2(binary, ["auth", "status", "--json"], { stdio: ["ignore", "pipe", "pipe"] });
913
961
  let stdout = "";
914
962
  let done = false;
@@ -917,7 +965,7 @@ async function checkAgentAuth(agent) {
917
965
  return;
918
966
  done = true;
919
967
  child.kill("SIGTERM");
920
- resolve28("unauthenticated");
968
+ resolve29("unauthenticated");
921
969
  }, 5e3);
922
970
  child.stdout?.on("data", (chunk) => {
923
971
  stdout += chunk.toString();
@@ -928,14 +976,14 @@ async function checkAgentAuth(agent) {
928
976
  done = true;
929
977
  clearTimeout(timer);
930
978
  if (code !== 0) {
931
- resolve28("unauthenticated");
979
+ resolve29("unauthenticated");
932
980
  return;
933
981
  }
934
982
  try {
935
983
  const status = JSON.parse(stdout);
936
- resolve28(status.loggedIn ? "ok" : "unauthenticated");
984
+ resolve29(status.loggedIn ? "ok" : "unauthenticated");
937
985
  } catch {
938
- resolve28("unauthenticated");
986
+ resolve29("unauthenticated");
939
987
  }
940
988
  });
941
989
  });
@@ -945,9 +993,9 @@ async function binaryIsOnPath(binary) {
945
993
  const fs = await import("node:fs/promises");
946
994
  return fs.access(binary).then(() => true, () => false);
947
995
  }
948
- return new Promise((resolve28) => {
996
+ return new Promise((resolve29) => {
949
997
  const child = spawn2(process.platform === "win32" ? "where" : "which", [binary], { stdio: "ignore" });
950
- child.on("close", (code) => resolve28(code === 0));
998
+ child.on("close", (code) => resolve29(code === 0));
951
999
  });
952
1000
  }
953
1001
  var init_check_agent_auth = __esm({
@@ -1584,7 +1632,8 @@ var init_infer_fence_lang = __esm({
1584
1632
  sass: "scss",
1585
1633
  css: "css",
1586
1634
  json: "json",
1587
- json5: "json"
1635
+ json5: "json",
1636
+ html: "html"
1588
1637
  };
1589
1638
  }
1590
1639
  });
@@ -2083,22 +2132,22 @@ var init_cache_keys = __esm({
2083
2132
 
2084
2133
  // packages/experience-design-system-types/dist/src/config/index.js
2085
2134
  import { randomBytes as randomBytes4 } from "node:crypto";
2086
- import { mkdir as mkdir6, readFile as readFile18, rename as rename2, writeFile as writeFile6 } from "node:fs/promises";
2135
+ import { mkdir as mkdir6, readFile as readFile20, rename as rename2, writeFile as writeFile6 } from "node:fs/promises";
2087
2136
  import { homedir as homedir3 } from "node:os";
2088
- import { dirname as dirname13, join as join16 } from "node:path";
2137
+ import { dirname as dirname14, join as join16 } from "node:path";
2089
2138
  function configRoot2() {
2090
2139
  return process.env["EDS_HOME"] || join16(homedir3(), ".contentful", "experience-design-system-cli");
2091
2140
  }
2092
2141
  async function readSettings2() {
2093
2142
  try {
2094
- return JSON.parse(await readFile18(configFilePath2(), "utf8"));
2143
+ return JSON.parse(await readFile20(configFilePath2(), "utf8"));
2095
2144
  } catch {
2096
2145
  return {};
2097
2146
  }
2098
2147
  }
2099
2148
  async function writeSettings2(settings) {
2100
2149
  const path5 = configFilePath2();
2101
- await mkdir6(dirname13(path5), { recursive: true });
2150
+ await mkdir6(dirname14(path5), { recursive: true });
2102
2151
  const tmp = `${path5}.${process.pid}.${randomBytes4(4).toString("hex")}.tmp`;
2103
2152
  await writeFile6(tmp, `${JSON.stringify(settings, null, 2)}
2104
2153
  `, { mode: 384 });
@@ -2142,7 +2191,7 @@ var init_debug_mode_store = __esm({
2142
2191
 
2143
2192
  // packages/experience-design-system-cli/src/tui/debug-prune.ts
2144
2193
  import { readdir as readdir2, rm, rmdir, stat as stat4 } from "node:fs/promises";
2145
- import { dirname as dirname16, join as join23 } from "node:path";
2194
+ import { dirname as dirname17, join as join23 } from "node:path";
2146
2195
  async function logFilesIn(dir) {
2147
2196
  const entries = await readdir2(dir, { withFileTypes: true });
2148
2197
  const nested = await Promise.all(
@@ -2165,7 +2214,7 @@ async function removeEmptyFolders(from, stop) {
2165
2214
  }
2166
2215
  removed += 1;
2167
2216
  if (dir === stop) return removed;
2168
- dir = dirname16(dir);
2217
+ dir = dirname17(dir);
2169
2218
  }
2170
2219
  }
2171
2220
  async function pruneExpiredLogs(base, retentionDays, now = Date.now()) {
@@ -2181,7 +2230,7 @@ async function pruneExpiredLogs(base, retentionDays, now = Date.now()) {
2181
2230
  if ((await stat4(file)).mtimeMs >= cutoff) continue;
2182
2231
  await rm(file);
2183
2232
  result.logs += 1;
2184
- result.folders += await removeEmptyFolders(dirname16(file), join23(contentfulDir, session));
2233
+ result.folders += await removeEmptyFolders(dirname17(file), join23(contentfulDir, session));
2185
2234
  } catch {
2186
2235
  }
2187
2236
  }
@@ -2211,7 +2260,7 @@ __export(debug_store_exports, {
2211
2260
  });
2212
2261
  import { mkdir as mkdir9, writeFile as writeFile8 } from "node:fs/promises";
2213
2262
  import { existsSync as existsSync9, readdirSync as readdirSync4 } from "node:fs";
2214
- import { join as join24, resolve as resolve26 } from "node:path";
2263
+ import { join as join24, resolve as resolve27 } from "node:path";
2215
2264
  function generateRunId() {
2216
2265
  const now = /* @__PURE__ */ new Date();
2217
2266
  const pad = (n) => String(n).padStart(2, "0");
@@ -2227,7 +2276,7 @@ function slugify(value) {
2227
2276
  async function readBaseDir() {
2228
2277
  try {
2229
2278
  const dir = (await readSettings2())["contentfulBaseDir"];
2230
- return typeof dir === "string" && dir !== "" ? resolve26(dir) : void 0;
2279
+ return typeof dir === "string" && dir !== "" ? resolve27(dir) : void 0;
2231
2280
  } catch {
2232
2281
  return void 0;
2233
2282
  }
@@ -2256,7 +2305,7 @@ function currentSessionDir() {
2256
2305
  async function startDebugSessionIn(base, { replace = false } = {}) {
2257
2306
  try {
2258
2307
  if (!await isDebugModeEnabled()) return;
2259
- await mkdir9(join24(startSession(resolve26(base), { replace }), "debug"), { recursive: true });
2308
+ await mkdir9(join24(startSession(resolve27(base), { replace }), "debug"), { recursive: true });
2260
2309
  } catch {
2261
2310
  }
2262
2311
  }
@@ -2270,7 +2319,7 @@ function nextImportRunDir(session) {
2270
2319
  }
2271
2320
  async function startImportRun(projectPath) {
2272
2321
  await startDebugSessionIn(projectPath);
2273
- if (!sessionDir) return join24(resolve26(projectPath), ".contentful");
2322
+ if (!sessionDir) return join24(resolve27(projectPath), ".contentful");
2274
2323
  const dir = nextImportRunDir(sessionDir);
2275
2324
  await mkdir9(dir, { recursive: true });
2276
2325
  return dir;
@@ -11937,6 +11986,690 @@ function mergeSlots2(fromSnippetProps, fromTemplate) {
11937
11986
  return { slots: [...byName.values()], mixedWarning: mixed };
11938
11987
  }
11939
11988
 
11989
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/extract-angular-components.js
11990
+ import { readFile as readFile8 } from "node:fs/promises";
11991
+ import { ModuleKind as ModuleKind2, Project as Project7, ScriptTarget as ScriptTarget2 } from "ts-morph";
11992
+
11993
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/find-component-decorator.js
11994
+ import { Node as Node10 } from "ts-morph";
11995
+ function resolveToObjectLiteral(expr, depth = 0) {
11996
+ if (!expr || depth > 3)
11997
+ return null;
11998
+ if (Node10.isObjectLiteralExpression(expr))
11999
+ return expr;
12000
+ if (Node10.isIdentifier(expr)) {
12001
+ const defs = expr.getDefinitions();
12002
+ for (const def of defs) {
12003
+ const node = def.getDeclarationNode();
12004
+ if (node && Node10.isVariableDeclaration(node)) {
12005
+ const init = node.getInitializer();
12006
+ const resolved = resolveToObjectLiteral(init, depth + 1);
12007
+ if (resolved)
12008
+ return resolved;
12009
+ }
12010
+ }
12011
+ }
12012
+ return null;
12013
+ }
12014
+ function findComponentDecorator(cls) {
12015
+ const decorator = cls.getDecorator("Component");
12016
+ if (!decorator)
12017
+ return null;
12018
+ const [arg] = decorator.getArguments();
12019
+ return resolveToObjectLiteral(arg);
12020
+ }
12021
+ function hasComponentDecorator(cls) {
12022
+ return cls.getDecorator("Component") !== void 0;
12023
+ }
12024
+
12025
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/props/extract-decorator-input.js
12026
+ import { Node as Node12 } from "ts-morph";
12027
+
12028
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/props/resolve-prop-type.js
12029
+ import { Node as Node11 } from "ts-morph";
12030
+ function resolvePropType(typeNode) {
12031
+ if (!typeNode) {
12032
+ return { text: "any", allowedValues: null, isTemplateRef: false };
12033
+ }
12034
+ const text = typeNode.getText();
12035
+ const members = extractStringLiteralUnion(typeNode);
12036
+ const isTemplateRef = containsTemplateRef(typeNode);
12037
+ return {
12038
+ text,
12039
+ allowedValues: members.length > 0 ? members : null,
12040
+ isTemplateRef
12041
+ };
12042
+ }
12043
+ function extractStringLiteralUnion(typeNode) {
12044
+ if (Node11.isLiteralTypeNode(typeNode)) {
12045
+ const lit = typeNode.getLiteral();
12046
+ if (Node11.isStringLiteral(lit) || Node11.isNoSubstitutionTemplateLiteral(lit)) {
12047
+ return [lit.getLiteralText()];
12048
+ }
12049
+ return [];
12050
+ }
12051
+ if (Node11.isUnionTypeNode(typeNode)) {
12052
+ const out = [];
12053
+ for (const member of typeNode.getTypeNodes()) {
12054
+ const sub = extractStringLiteralUnion(member);
12055
+ if (sub.length === 0 && !isNullOrUndefinedLiteral(member)) {
12056
+ return [];
12057
+ }
12058
+ out.push(...sub);
12059
+ }
12060
+ return out;
12061
+ }
12062
+ return [];
12063
+ }
12064
+ function isNullOrUndefinedLiteral(typeNode) {
12065
+ if (Node11.isLiteralTypeNode(typeNode)) {
12066
+ const lit = typeNode.getLiteral();
12067
+ if (Node11.isNullLiteral(lit))
12068
+ return true;
12069
+ }
12070
+ const t = typeNode.getText();
12071
+ return t === "null" || t === "undefined";
12072
+ }
12073
+ function containsTemplateRef(typeNode) {
12074
+ const text = typeNode.getText();
12075
+ return /\bTemplateRef\b/.test(text);
12076
+ }
12077
+
12078
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/props/extract-decorator-input.js
12079
+ function extractDecoratorInput(field) {
12080
+ const decorator = field.getDecorator("Input");
12081
+ if (!decorator)
12082
+ return null;
12083
+ const fieldName = field.getName();
12084
+ const args = decorator.getArguments();
12085
+ let alias = null;
12086
+ let required = false;
12087
+ let transformIsBoolean = false;
12088
+ let transformIsNumber = false;
12089
+ if (args.length === 1) {
12090
+ const arg = args[0];
12091
+ if (Node12.isStringLiteral(arg) || Node12.isNoSubstitutionTemplateLiteral(arg)) {
12092
+ alias = arg.getLiteralText();
12093
+ } else if (Node12.isObjectLiteralExpression(arg)) {
12094
+ const aliasProp = arg.getProperty("alias");
12095
+ if (aliasProp && Node12.isPropertyAssignment(aliasProp)) {
12096
+ const init = aliasProp.getInitializer();
12097
+ if (init && (Node12.isStringLiteral(init) || Node12.isNoSubstitutionTemplateLiteral(init))) {
12098
+ alias = init.getLiteralText();
12099
+ }
12100
+ }
12101
+ const requiredProp = arg.getProperty("required");
12102
+ if (requiredProp && Node12.isPropertyAssignment(requiredProp)) {
12103
+ const init = requiredProp.getInitializer();
12104
+ if (init?.getText() === "true")
12105
+ required = true;
12106
+ }
12107
+ const transformProp = arg.getProperty("transform");
12108
+ if (transformProp && Node12.isPropertyAssignment(transformProp)) {
12109
+ const transformText = transformProp.getInitializer()?.getText() ?? "";
12110
+ if (/\bbooleanAttribute\b/.test(transformText))
12111
+ transformIsBoolean = true;
12112
+ if (/\bnumberAttribute\b/.test(transformText))
12113
+ transformIsNumber = true;
12114
+ }
12115
+ }
12116
+ }
12117
+ let typeNode;
12118
+ let defaultValue;
12119
+ if (Node12.isSetAccessorDeclaration(field)) {
12120
+ const param = field.getParameters()[0];
12121
+ typeNode = param?.getTypeNode();
12122
+ } else if (Node12.isGetAccessorDeclaration(field)) {
12123
+ const parent = field.getParent();
12124
+ const companionSetter = parent && Node12.isClassDeclaration(parent) ? parent.getSetAccessor(fieldName) : void 0;
12125
+ if (companionSetter) {
12126
+ typeNode = companionSetter.getParameters()[0]?.getTypeNode();
12127
+ }
12128
+ if (!typeNode)
12129
+ typeNode = field.getReturnTypeNode();
12130
+ } else {
12131
+ typeNode = field.getTypeNode();
12132
+ const initializer = field.getInitializer();
12133
+ if (initializer)
12134
+ defaultValue = initializer.getText();
12135
+ }
12136
+ const resolved = resolvePropType(typeNode);
12137
+ const typeText = transformIsBoolean ? "boolean" : transformIsNumber ? "number" : resolved.text;
12138
+ const name = alias ?? fieldName;
12139
+ const prop = {
12140
+ name,
12141
+ type: typeText,
12142
+ required,
12143
+ sourceStartLine: field.getStartLineNumber(),
12144
+ sourceEndLine: field.getEndLineNumber()
12145
+ };
12146
+ if (defaultValue !== void 0)
12147
+ prop.defaultValue = defaultValue;
12148
+ if (resolved.allowedValues && !transformIsBoolean && !transformIsNumber) {
12149
+ prop.allowedValues = resolved.allowedValues;
12150
+ }
12151
+ return prop;
12152
+ }
12153
+
12154
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/props/extract-signal-input.js
12155
+ import { Node as Node13 } from "ts-morph";
12156
+ function extractSignalInput(field) {
12157
+ const init = field.getInitializer();
12158
+ if (!init || !Node13.isCallExpression(init))
12159
+ return null;
12160
+ const callee = init.getExpression();
12161
+ let required = false;
12162
+ if (Node13.isIdentifier(callee)) {
12163
+ if (callee.getText() !== "input")
12164
+ return null;
12165
+ } else if (Node13.isPropertyAccessExpression(callee)) {
12166
+ const left = callee.getExpression();
12167
+ const right = callee.getName();
12168
+ if (!Node13.isIdentifier(left) || left.getText() !== "input" || right !== "required")
12169
+ return null;
12170
+ required = true;
12171
+ } else {
12172
+ return null;
12173
+ }
12174
+ const fieldName = field.getName();
12175
+ const args = init.getArguments();
12176
+ let defaultValue;
12177
+ let configArg;
12178
+ if (required) {
12179
+ configArg = args[0];
12180
+ } else {
12181
+ const first = args[0];
12182
+ if (first) {
12183
+ defaultValue = first.getText();
12184
+ configArg = args[1];
12185
+ }
12186
+ }
12187
+ let alias = null;
12188
+ let transformIsBoolean = false;
12189
+ let transformIsNumber = false;
12190
+ if (configArg && Node13.isObjectLiteralExpression(configArg)) {
12191
+ const aliasProp = configArg.getProperty("alias");
12192
+ if (aliasProp && Node13.isPropertyAssignment(aliasProp)) {
12193
+ const aliasInit = aliasProp.getInitializer();
12194
+ if (aliasInit && (Node13.isStringLiteral(aliasInit) || Node13.isNoSubstitutionTemplateLiteral(aliasInit))) {
12195
+ alias = aliasInit.getLiteralText();
12196
+ }
12197
+ }
12198
+ const transformProp = configArg.getProperty("transform");
12199
+ if (transformProp && Node13.isPropertyAssignment(transformProp)) {
12200
+ const transformText = transformProp.getInitializer()?.getText() ?? "";
12201
+ if (/\bbooleanAttribute\b/.test(transformText))
12202
+ transformIsBoolean = true;
12203
+ if (/\bnumberAttribute\b/.test(transformText))
12204
+ transformIsNumber = true;
12205
+ }
12206
+ }
12207
+ const typeArg = init.getTypeArguments()[0];
12208
+ const resolved = resolvePropType(typeArg);
12209
+ const typeText = transformIsBoolean ? "boolean" : transformIsNumber ? "number" : resolved.text;
12210
+ const name = alias ?? fieldName;
12211
+ const prop = {
12212
+ name,
12213
+ type: typeText,
12214
+ required,
12215
+ sourceStartLine: field.getStartLineNumber(),
12216
+ sourceEndLine: field.getEndLineNumber()
12217
+ };
12218
+ if (defaultValue !== void 0)
12219
+ prop.defaultValue = defaultValue;
12220
+ if (resolved.allowedValues && !transformIsBoolean && !transformIsNumber) {
12221
+ prop.allowedValues = resolved.allowedValues;
12222
+ }
12223
+ return prop;
12224
+ }
12225
+
12226
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/props/parse-inputs-array-entry.js
12227
+ function parseInputsArrayEntry(entry) {
12228
+ const trimmed = entry.trim();
12229
+ if (!trimmed)
12230
+ return null;
12231
+ const parts = trimmed.split(":");
12232
+ if (parts.length === 1) {
12233
+ return { fieldName: parts[0].trim(), alias: null };
12234
+ }
12235
+ if (parts.length === 2) {
12236
+ const field = parts[0].trim();
12237
+ const alias = parts[1].trim();
12238
+ if (!field || !alias)
12239
+ return null;
12240
+ return { fieldName: field, alias };
12241
+ }
12242
+ return null;
12243
+ }
12244
+
12245
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/props/extract-props.js
12246
+ var MAX_BASE_CHAIN = 10;
12247
+ function collectClassChain(cls) {
12248
+ const chain = [cls];
12249
+ const seen = /* @__PURE__ */ new Set([cls]);
12250
+ let current = cls;
12251
+ for (let i = 0; i < MAX_BASE_CHAIN; i++) {
12252
+ let base;
12253
+ try {
12254
+ base = current.getBaseClass();
12255
+ } catch {
12256
+ break;
12257
+ }
12258
+ if (!base || seen.has(base))
12259
+ break;
12260
+ chain.push(base);
12261
+ seen.add(base);
12262
+ current = base;
12263
+ }
12264
+ return chain;
12265
+ }
12266
+ function extractProps2(cls, meta) {
12267
+ const byName = /* @__PURE__ */ new Map();
12268
+ const chain = collectClassChain(cls);
12269
+ for (const klass of chain) {
12270
+ for (const field of klass.getProperties()) {
12271
+ const prop = extractDecoratorInput(field);
12272
+ if (prop && !byName.has(prop.name))
12273
+ byName.set(prop.name, prop);
12274
+ }
12275
+ for (const setter of klass.getSetAccessors()) {
12276
+ const prop = extractDecoratorInput(setter);
12277
+ if (prop && !byName.has(prop.name))
12278
+ byName.set(prop.name, prop);
12279
+ }
12280
+ for (const getter of klass.getGetAccessors()) {
12281
+ const prop = extractDecoratorInput(getter);
12282
+ if (prop && !byName.has(prop.name))
12283
+ byName.set(prop.name, prop);
12284
+ }
12285
+ for (const field of klass.getProperties()) {
12286
+ const prop = extractSignalInput(field);
12287
+ if (prop && !byName.has(prop.name))
12288
+ byName.set(prop.name, prop);
12289
+ }
12290
+ }
12291
+ for (const entry of meta.inputsArray) {
12292
+ const parsed = parseInputsArrayEntry(entry);
12293
+ if (!parsed)
12294
+ continue;
12295
+ const name = parsed.alias ?? parsed.fieldName;
12296
+ if (byName.has(name))
12297
+ continue;
12298
+ byName.set(name, { name, type: "any", required: false });
12299
+ }
12300
+ return [...byName.values()];
12301
+ }
12302
+
12303
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/read-component-metadata.js
12304
+ import { dirname as dirname10, resolve as resolve12 } from "node:path";
12305
+
12306
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/resolution/normalize-component-name.js
12307
+ var SUFFIXES = ["Component", "Directive"];
12308
+ function normalizeComponentName2(className) {
12309
+ for (const suffix of SUFFIXES) {
12310
+ if (className.endsWith(suffix) && className.length > suffix.length) {
12311
+ return className.slice(0, -suffix.length);
12312
+ }
12313
+ }
12314
+ return className;
12315
+ }
12316
+
12317
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/read-decorator-string.js
12318
+ import { Node as Node14 } from "ts-morph";
12319
+ function readDecoratorString(obj, propName) {
12320
+ const prop = obj.getProperty(propName);
12321
+ if (!prop || !Node14.isPropertyAssignment(prop))
12322
+ return null;
12323
+ const init = prop.getInitializer();
12324
+ if (!init)
12325
+ return null;
12326
+ if (Node14.isStringLiteral(init) || Node14.isNoSubstitutionTemplateLiteral(init)) {
12327
+ return init.getLiteralText();
12328
+ }
12329
+ return null;
12330
+ }
12331
+ function readDecoratorStringArray(obj, propName) {
12332
+ const prop = obj.getProperty(propName);
12333
+ if (!prop || !Node14.isPropertyAssignment(prop))
12334
+ return [];
12335
+ const init = prop.getInitializer();
12336
+ if (!init || !Node14.isArrayLiteralExpression(init))
12337
+ return [];
12338
+ const out = [];
12339
+ for (const el of init.getElements()) {
12340
+ if (Node14.isStringLiteral(el) || Node14.isNoSubstitutionTemplateLiteral(el)) {
12341
+ out.push(el.getLiteralText());
12342
+ }
12343
+ }
12344
+ return out;
12345
+ }
12346
+
12347
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/read-component-metadata.js
12348
+ function readComponentMetadata(cls, sourceFilePath) {
12349
+ const obj = findComponentDecorator(cls);
12350
+ if (!obj)
12351
+ return null;
12352
+ const className = cls.getName();
12353
+ if (!className)
12354
+ return null;
12355
+ const rawSelector = readDecoratorString(obj, "selector");
12356
+ const inlineTemplate = readDecoratorString(obj, "template");
12357
+ const templateUrlRel = readDecoratorString(obj, "templateUrl");
12358
+ const inputsArray = readDecoratorStringArray(obj, "inputs");
12359
+ const templatePath = templateUrlRel ? resolve12(dirname10(sourceFilePath), templateUrlRel) : null;
12360
+ const decorator = cls.getDecorator("Component");
12361
+ const decoratorLine = decorator?.getStartLineNumber() ?? cls.getStartLineNumber();
12362
+ return {
12363
+ className,
12364
+ normalizedName: normalizeComponentName2(className),
12365
+ rawSelector,
12366
+ inlineTemplate,
12367
+ templatePath,
12368
+ inputsArray,
12369
+ decoratorLine
12370
+ };
12371
+ }
12372
+
12373
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/template/parse-ng-content-elements.js
12374
+ function parseNgContentElements(templateHtml) {
12375
+ const out = [];
12376
+ const tagRe = /<ng-content\b([^>]*?)\/?>/gi;
12377
+ for (const match2 of templateHtml.matchAll(tagRe)) {
12378
+ const attrs = match2[1] ?? "";
12379
+ const selectMatch = attrs.match(/\bselect\s*=\s*(?:"([^"]*)"|'([^']*)')/);
12380
+ const rawSelect = selectMatch ? selectMatch[1] ?? selectMatch[2] ?? null : null;
12381
+ const sourceLine = countLines(templateHtml, match2.index ?? 0);
12382
+ out.push({ rawSelect, sourceLine });
12383
+ }
12384
+ return out;
12385
+ }
12386
+ function countLines(text, offset) {
12387
+ let line = 1;
12388
+ for (let i = 0; i < offset && i < text.length; i++) {
12389
+ if (text.charCodeAt(i) === 10)
12390
+ line++;
12391
+ }
12392
+ return line;
12393
+ }
12394
+
12395
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/template/resolve-template-source.js
12396
+ import { readFile as readFile7 } from "node:fs/promises";
12397
+ async function resolveTemplateSource(meta) {
12398
+ if (meta.inlineTemplate !== null)
12399
+ return meta.inlineTemplate;
12400
+ if (meta.templatePath === null)
12401
+ return null;
12402
+ try {
12403
+ return await readFile7(meta.templatePath, "utf8");
12404
+ } catch {
12405
+ return null;
12406
+ }
12407
+ }
12408
+
12409
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/resolution/strip-library-prefix.js
12410
+ var KNOWN_PREFIXES = ["Mat", "Cdk", "Nz", "Cds", "Ibm", "Clr", "Hlm", "Brn", "Tui", "Nb", "Fd", "P", "Ng"];
12411
+ function stripLibraryPrefix(name) {
12412
+ for (const prefix of KNOWN_PREFIXES) {
12413
+ if (name.startsWith(prefix) && name.length > prefix.length) {
12414
+ const rest = name.slice(prefix.length);
12415
+ if (rest[0] && rest[0] === rest[0].toUpperCase()) {
12416
+ return rest;
12417
+ }
12418
+ }
12419
+ }
12420
+ return name;
12421
+ }
12422
+
12423
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/slots/derive-slot-name.js
12424
+ function deriveSlotName(rawSelect, parentNormalizedName) {
12425
+ if (!rawSelect || rawSelect.trim() === "")
12426
+ return "children";
12427
+ if (rawSelect.includes(",")) {
12428
+ const first = rawSelect.split(",")[0].trim();
12429
+ return deriveSingleSelectorName(first, parentNormalizedName);
12430
+ }
12431
+ return deriveSingleSelectorName(rawSelect.trim(), parentNormalizedName);
12432
+ }
12433
+ function deriveSingleSelectorName(sel, parentNormalizedName) {
12434
+ const slotAttrMatch = sel.match(/^\[\s*slot\s*=\s*['"]?([^'"\]]+)['"]?\s*\]$/);
12435
+ if (slotAttrMatch)
12436
+ return slotAttrMatch[1].trim();
12437
+ if (sel.startsWith(".")) {
12438
+ const last = sel.slice(1).split("-").pop() ?? sel.slice(1);
12439
+ return kebabToCamel2(last);
12440
+ }
12441
+ const attrMatch = sel.match(/^\[([^=\]]+)\]$/);
12442
+ if (attrMatch) {
12443
+ const attr = attrMatch[1].trim();
12444
+ const stripped = tryStripSubComponentOrLibraryPrefix(attr, parentNormalizedName);
12445
+ return stripped || kebabToCamel2(attr);
12446
+ }
12447
+ const elMatch = sel.match(/^([a-zA-Z][a-zA-Z0-9-]*)/);
12448
+ if (elMatch) {
12449
+ const tag = elMatch[1];
12450
+ const stripped = tryStripSubComponentOrLibraryPrefix(tag, parentNormalizedName);
12451
+ return stripped || kebabToCamel2(tag);
12452
+ }
12453
+ return sel.replace(/\s+/g, "");
12454
+ }
12455
+ function tryStripSubComponentOrLibraryPrefix(ident, parentNormalizedName) {
12456
+ const parentKebab = pascalToKebab(parentNormalizedName);
12457
+ if (parentKebab && ident.startsWith(`${parentKebab}-`)) {
12458
+ return kebabToCamel2(ident.slice(parentKebab.length + 1));
12459
+ }
12460
+ const asPascal = kebabToPascal2(ident);
12461
+ const stripped = stripLibraryPrefix(asPascal);
12462
+ if (stripped !== asPascal) {
12463
+ return stripped.charAt(0).toLowerCase() + stripped.slice(1);
12464
+ }
12465
+ return null;
12466
+ }
12467
+ function kebabToCamel2(s) {
12468
+ return s.replace(/-([a-z])/g, (_, c2) => c2.toUpperCase());
12469
+ }
12470
+ function kebabToPascal2(s) {
12471
+ const camel = kebabToCamel2(s);
12472
+ return camel.charAt(0).toUpperCase() + camel.slice(1);
12473
+ }
12474
+ function pascalToKebab(s) {
12475
+ return s.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
12476
+ }
12477
+
12478
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/slots/extract-content-child-queries.js
12479
+ import { Node as Node15 } from "ts-morph";
12480
+ function extractContentChildQueries(cls) {
12481
+ const out = [];
12482
+ for (const field of cls.getProperties()) {
12483
+ const fieldName = field.getName();
12484
+ const init = field.getInitializer();
12485
+ if (init && Node15.isCallExpression(init)) {
12486
+ const callee = init.getExpression();
12487
+ if (Node15.isIdentifier(callee)) {
12488
+ const name = callee.getText();
12489
+ if (name === "contentChild" || name === "contentChildren") {
12490
+ const first = init.getArguments()[0];
12491
+ const allowed = resolveClassIdentifierArg(first);
12492
+ out.push(buildSlot(fieldName, allowed));
12493
+ continue;
12494
+ }
12495
+ }
12496
+ }
12497
+ for (const decName of ["ContentChild", "ContentChildren"]) {
12498
+ const dec = field.getDecorator(decName);
12499
+ if (dec) {
12500
+ const first = dec.getArguments()[0];
12501
+ const allowed = resolveClassIdentifierArg(first);
12502
+ out.push(buildSlot(fieldName, allowed));
12503
+ break;
12504
+ }
12505
+ }
12506
+ }
12507
+ return out;
12508
+ }
12509
+ function resolveClassIdentifierArg(arg) {
12510
+ if (!arg)
12511
+ return [];
12512
+ if (Node15.isStringLiteral(arg) || Node15.isNoSubstitutionTemplateLiteral(arg))
12513
+ return [];
12514
+ if (Node15.isIdentifier(arg))
12515
+ return [arg.getText()];
12516
+ return [];
12517
+ }
12518
+ function buildSlot(name, allowed) {
12519
+ const slot = {
12520
+ name,
12521
+ isDefault: false
12522
+ };
12523
+ if (allowed.length > 0)
12524
+ slot.allowedComponents = allowed;
12525
+ return slot;
12526
+ }
12527
+
12528
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/slots/extract-template-ref-slots.js
12529
+ function extractTemplateRefSlots(props) {
12530
+ const nextProps = [];
12531
+ const slots = [];
12532
+ for (const prop of props) {
12533
+ const type = prop.type;
12534
+ const hasTemplateRef = /\bTemplateRef\b/.test(type);
12535
+ if (!hasTemplateRef) {
12536
+ nextProps.push(prop);
12537
+ continue;
12538
+ }
12539
+ const isPureTemplateRef = /^\s*TemplateRef<[^>]*>\s*(\|\s*(null|undefined)\s*)*$/.test(type);
12540
+ if (!isPureTemplateRef) {
12541
+ nextProps.push(prop);
12542
+ }
12543
+ slots.push({ name: prop.name, isDefault: false });
12544
+ }
12545
+ return { props: nextProps, slots };
12546
+ }
12547
+
12548
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/slots/extract-slots.js
12549
+ async function extractSlots3(cls, meta, props) {
12550
+ const byName = /* @__PURE__ */ new Map();
12551
+ const template = await resolveTemplateSource(meta);
12552
+ if (template) {
12553
+ for (const el of parseNgContentElements(template)) {
12554
+ const name = deriveSlotName(el.rawSelect, meta.normalizedName);
12555
+ if (byName.has(name))
12556
+ continue;
12557
+ byName.set(name, {
12558
+ name,
12559
+ isDefault: el.rawSelect === null
12560
+ });
12561
+ }
12562
+ }
12563
+ for (const slot of extractContentChildQueries(cls)) {
12564
+ if (!byName.has(slot.name))
12565
+ byName.set(slot.name, slot);
12566
+ }
12567
+ const split = extractTemplateRefSlots(props);
12568
+ for (const slot of split.slots) {
12569
+ if (!byName.has(slot.name))
12570
+ byName.set(slot.name, slot);
12571
+ }
12572
+ return { props: split.props, slots: [...byName.values()] };
12573
+ }
12574
+
12575
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/extract-angular-components.js
12576
+ async function extractAngularComponents(filePaths, onProgress, _opts) {
12577
+ const components = [];
12578
+ const warnings = [];
12579
+ let filesProcessed = 0;
12580
+ const project = new Project7({
12581
+ useInMemoryFileSystem: false,
12582
+ skipAddingFilesFromTsConfig: true,
12583
+ compilerOptions: {
12584
+ target: ScriptTarget2.ES2022,
12585
+ module: ModuleKind2.ESNext,
12586
+ experimentalDecorators: true,
12587
+ emitDecoratorMetadata: false,
12588
+ allowJs: false
12589
+ }
12590
+ });
12591
+ for (const filePath of filePaths) {
12592
+ try {
12593
+ const source = await readFile8(filePath, "utf8");
12594
+ const sourceFile = project.createSourceFile(filePath, source, { overwrite: true });
12595
+ for (const cls of sourceFile.getClasses()) {
12596
+ if (!hasComponentDecorator(cls))
12597
+ continue;
12598
+ if (!findComponentDecorator(cls)) {
12599
+ warnings.push(`${filePath}: ${cls.getName() ?? "<anonymous>"} has @Component with a non-literal argument; skipped.`);
12600
+ continue;
12601
+ }
12602
+ const meta = readComponentMetadata(cls, filePath);
12603
+ if (!meta)
12604
+ continue;
12605
+ const propsOnly = extractProps2(cls, meta);
12606
+ const { props, slots } = await extractSlots3(cls, meta, propsOnly);
12607
+ const partial = {
12608
+ name: meta.className,
12609
+ source: filePath,
12610
+ framework: "angular",
12611
+ props,
12612
+ slots: normalizeSlots(slots),
12613
+ sourcePath: filePath
12614
+ };
12615
+ const score = computeExtractionScore(partial);
12616
+ partial.extractionConfidence = score.confidence;
12617
+ partial.reviewReasons = score.reasons;
12618
+ partial.needsReview = deriveNeedsReview(score.confidence);
12619
+ components.push(partial);
12620
+ }
12621
+ sourceFile.forget();
12622
+ } catch (err) {
12623
+ warnings.push(`${filePath}: Angular extractor failed \u2014 ${err instanceof Error ? err.message : String(err)}`);
12624
+ } finally {
12625
+ filesProcessed++;
12626
+ if (onProgress)
12627
+ onProgress({ filesProcessed, componentsFound: components.length });
12628
+ }
12629
+ }
12630
+ return {
12631
+ components: components.sort((a, b) => a.name.localeCompare(b.name)),
12632
+ warnings
12633
+ };
12634
+ }
12635
+ function normalizeSlots(slots) {
12636
+ let fallbackIndex = 0;
12637
+ return slots.map((slot) => {
12638
+ if (slot.name.trim())
12639
+ return slot;
12640
+ const name = fallbackIndex === 0 ? "children" : `slot_${fallbackIndex}`;
12641
+ fallbackIndex++;
12642
+ return { ...slot, name };
12643
+ });
12644
+ }
12645
+
12646
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/is-angular-source-file.js
12647
+ import { openSync, readSync, closeSync, statSync as statSync4 } from "node:fs";
12648
+ var HEAD_BYTES = 32 * 1024;
12649
+ var buffer = Buffer.alloc(HEAD_BYTES);
12650
+ function isAngularSourceFile(filePath) {
12651
+ if (!/\.[cm]?ts$/.test(filePath))
12652
+ return false;
12653
+ if (filePath.endsWith(".d.ts"))
12654
+ return false;
12655
+ try {
12656
+ const stats = statSync4(filePath);
12657
+ const toRead = Math.min(HEAD_BYTES, stats.size);
12658
+ if (toRead === 0)
12659
+ return false;
12660
+ const fd = openSync(filePath, "r");
12661
+ try {
12662
+ const bytesRead = readSync(fd, buffer, 0, toRead, 0);
12663
+ const head = buffer.subarray(0, bytesRead).toString("utf8");
12664
+ return head.includes("@angular/core");
12665
+ } finally {
12666
+ closeSync(fd);
12667
+ }
12668
+ } catch {
12669
+ return false;
12670
+ }
12671
+ }
12672
+
11940
12673
  // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/services/run-extraction-service.js
11941
12674
  var extractors = [
11942
12675
  {
@@ -11964,6 +12697,13 @@ var extractors = [
11964
12697
  fileFilter: (f) => f.endsWith(".astro"),
11965
12698
  extract: extractAstroComponents
11966
12699
  },
12700
+ {
12701
+ // Must run BEFORE web-components (both claim bare .ts). The sniff reads
12702
+ // the file head looking for `@angular/core` so we only claim real Angular files.
12703
+ name: "angular",
12704
+ fileFilter: (f) => isAngularSourceFile(f),
12705
+ extract: extractAngularComponents
12706
+ },
11967
12707
  {
11968
12708
  name: "web-components",
11969
12709
  fileFilter: (f) => /\.[jt]s$/.test(f) && !/\.[jt]sx$/.test(f) && !f.endsWith(".d.ts"),
@@ -12439,16 +13179,16 @@ function applyCompositionEdges(components, edges) {
12439
13179
 
12440
13180
  // packages/experience-design-system-backend-pipeline/dist/src/steps/composition/src/helpers/prompt/prompt-loader.js
12441
13181
  import { existsSync as existsSync7, readFileSync as readFileSync7 } from "node:fs";
12442
- import { dirname as dirname10, join as join10, resolve as resolve12 } from "node:path";
13182
+ import { dirname as dirname11, join as join10, resolve as resolve13 } from "node:path";
12443
13183
  import { fileURLToPath as fileURLToPath3 } from "node:url";
12444
13184
  function resolvePromptPath(fileName) {
12445
- const thisDir = dirname10(fileURLToPath3(import.meta.url));
13185
+ const thisDir = dirname11(fileURLToPath3(import.meta.url));
12446
13186
  let dir = thisDir;
12447
13187
  for (; ; ) {
12448
13188
  const candidate = join10(dir, "prompts");
12449
13189
  if (existsSync7(candidate))
12450
13190
  return join10(candidate, fileName);
12451
- const parent = resolve12(dir, "..");
13191
+ const parent = resolve13(dir, "..");
12452
13192
  if (parent === dir) {
12453
13193
  throw new Error(`prompt file missing from package installation (could not locate prompts/ directory from: ${thisDir})`);
12454
13194
  }
@@ -12528,14 +13268,31 @@ ${f.content}`).join("\n\n");
12528
13268
  }
12529
13269
 
12530
13270
  // packages/experience-design-system-backend-pipeline/dist/src/steps/composition/src/constants/candidate-files.js
12531
- var CANDIDATE_NAME_PATTERNS = [/mapping/i, /meta/i, /registry/i, /schema/i, /composition/i];
13271
+ var CANDIDATE_NAME_PATTERNS = [
13272
+ /mapping/i,
13273
+ /meta/i,
13274
+ /registry/i,
13275
+ /schema/i,
13276
+ /composition/i,
13277
+ /\.module\.ts$/i,
13278
+ /\.component\.ts$/i,
13279
+ /public[-_]api\.ts$/i,
13280
+ /^index\.ts$/i
13281
+ ];
12532
13282
  var CANDIDATE_CONTENT_MARKERS = [
12533
13283
  "requiredParent",
12534
13284
  "withParentType",
12535
13285
  "allowedTagNames",
12536
13286
  "createContext",
12537
13287
  "MappingContext",
12538
- "allowedComponents"
13288
+ "allowedComponents",
13289
+ "TemplateRef",
13290
+ "NG_VALUE_ACCESSOR",
13291
+ "ContentChild",
13292
+ "contentChild",
13293
+ "ng-content",
13294
+ "@NgModule",
13295
+ "standalone: true"
12539
13296
  ];
12540
13297
  var PROMPT_CANDIDATE_TOKEN_BUDGET = 8e4;
12541
13298
 
@@ -12596,8 +13353,8 @@ ${fileDigest}`);
12596
13353
  }
12597
13354
 
12598
13355
  // packages/experience-design-system-backend-pipeline/dist/src/steps/composition/src/helpers/edges/manifest-doc-evidence.js
12599
- import { dirname as dirname11 } from "node:path";
12600
- function kebabToPascal2(name) {
13356
+ import { dirname as dirname12 } from "node:path";
13357
+ function kebabToPascal3(name) {
12601
13358
  return name.split("-").filter(Boolean).map((seg) => seg.charAt(0).toUpperCase() + seg.slice(1)).join("");
12602
13359
  }
12603
13360
  function collectManifestEdges(files, componentNames) {
@@ -12619,7 +13376,7 @@ function collectManifestEdges(files, componentNames) {
12619
13376
  const rawParentName = typeof component === "object" && component !== null && typeof component.name === "string" ? component.name : void 0;
12620
13377
  if (!rawParentName)
12621
13378
  continue;
12622
- const parent = kebabToPascal2(rawParentName);
13379
+ const parent = kebabToPascal3(rawParentName);
12623
13380
  if (!componentNames.has(parent))
12624
13381
  continue;
12625
13382
  const variantsMeta = root.variantsMeta;
@@ -12639,7 +13396,7 @@ function collectManifestEdges(files, componentNames) {
12639
13396
  const rawChildName = value.name;
12640
13397
  if (typeof rawChildName !== "string")
12641
13398
  continue;
12642
- const child = kebabToPascal2(rawChildName);
13399
+ const child = kebabToPascal3(rawChildName);
12643
13400
  if (!componentNames.has(child) || child === parent)
12644
13401
  continue;
12645
13402
  const key = `${parent}::${child}`;
@@ -12660,8 +13417,8 @@ function collectAgentsDocEdges(files, components, componentNames) {
12660
13417
  for (const file of files) {
12661
13418
  if (!file.path.endsWith("AGENTS.md"))
12662
13419
  continue;
12663
- const docDir = dirname11(file.path);
12664
- const parent = components.find((c2) => c2.sourcePath && dirname11(c2.sourcePath) === docDir)?.name;
13420
+ const docDir = dirname12(file.path);
13421
+ const parent = components.find((c2) => c2.sourcePath && dirname12(c2.sourcePath) === docDir)?.name;
12665
13422
  if (!parent || !componentNames.has(parent))
12666
13423
  continue;
12667
13424
  for (const line of file.content.split("\n")) {
@@ -12670,7 +13427,7 @@ function collectAgentsDocEdges(files, components, componentNames) {
12670
13427
  continue;
12671
13428
  for (const match2 of line.matchAll(BOLD_BACKTICK)) {
12672
13429
  const raw = match2[1];
12673
- const candidate = componentNames.has(raw) ? raw : kebabToPascal2(raw);
13430
+ const candidate = componentNames.has(raw) ? raw : kebabToPascal3(raw);
12674
13431
  if (!componentNames.has(candidate) || candidate === parent)
12675
13432
  continue;
12676
13433
  const key = `${parent}::${candidate}`;
@@ -12986,7 +13743,7 @@ function validateExtractedComponents(components) {
12986
13743
  }
12987
13744
 
12988
13745
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/review-session/helpers/load-review-input.js
12989
- import { resolve as resolve14 } from "node:path";
13746
+ import { resolve as resolve15 } from "node:path";
12990
13747
 
12991
13748
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/review-session/helpers/create-component-id.js
12992
13749
  import { createHash as createHash7 } from "node:crypto";
@@ -12997,7 +13754,7 @@ function createComponentId(name, resolvedSourcePath) {
12997
13754
 
12998
13755
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/review-session/helpers/resolve-component-source-path.js
12999
13756
  import { access } from "node:fs/promises";
13000
- import { isAbsolute, relative, resolve as resolve13 } from "node:path";
13757
+ import { isAbsolute, relative, resolve as resolve14 } from "node:path";
13001
13758
  async function resolveComponentSourcePath(source, reviewRoot) {
13002
13759
  if (isAbsolute(source)) {
13003
13760
  try {
@@ -13007,7 +13764,7 @@ async function resolveComponentSourcePath(source, reviewRoot) {
13007
13764
  throw new Error(`Unable to access component source at ${source}`);
13008
13765
  }
13009
13766
  }
13010
- const candidate = resolve13(reviewRoot, source);
13767
+ const candidate = resolve14(reviewRoot, source);
13011
13768
  const relativeToRoot = relative(reviewRoot, candidate);
13012
13769
  if (relativeToRoot.startsWith("..") || relativeToRoot === ".." || isAbsolute(relativeToRoot)) {
13013
13770
  throw new Error(`Resolved component source is outside the review root: ${source}. Pass --project-root <path> to set the correct base.`);
@@ -13022,7 +13779,7 @@ async function resolveComponentSourcePath(source, reviewRoot) {
13022
13779
 
13023
13780
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/review-session/helpers/load-review-input.js
13024
13781
  async function loadReviewInput(components, options = {}) {
13025
- const reviewRoot = resolve14(options.reviewRoot ?? process.cwd());
13782
+ const reviewRoot = resolve15(options.reviewRoot ?? process.cwd());
13026
13783
  const records = await Promise.all(components.map(async (component) => {
13027
13784
  let resolvedSourcePath;
13028
13785
  try {
@@ -13057,19 +13814,19 @@ async function loadAndValidateForReview(sessionId, projectRoot) {
13057
13814
  }
13058
13815
 
13059
13816
  // packages/experience-design-system-backend-pipeline/dist/src/steps/selection/src/controller/review/merge-preview-validation-errors-into-review-session.js
13060
- import { access as access3, readFile as readFile8 } from "node:fs/promises";
13817
+ import { access as access3, readFile as readFile10 } from "node:fs/promises";
13061
13818
 
13062
13819
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/review-session/repositories/ensure-review-session.js
13063
- import { access as access2, mkdir, readFile as readFile7, writeFile } from "node:fs/promises";
13820
+ import { access as access2, mkdir, readFile as readFile9, writeFile } from "node:fs/promises";
13064
13821
 
13065
13822
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/review-session/repositories/review-session-paths.js
13066
- import { resolve as resolve15 } from "node:path";
13823
+ import { resolve as resolve16 } from "node:path";
13067
13824
  async function getRefineSessionPaths(sessionId, artifactsRoot) {
13068
- const sessionDir2 = resolve15(artifactsRoot, sessionId);
13825
+ const sessionDir2 = resolve16(artifactsRoot, sessionId);
13069
13826
  return {
13070
13827
  sessionDir: sessionDir2,
13071
- eventsPath: resolve15(sessionDir2, "events.jsonl"),
13072
- statePath: resolve15(sessionDir2, "current-review-state.json")
13828
+ eventsPath: resolve16(sessionDir2, "events.jsonl"),
13829
+ statePath: resolve16(sessionDir2, "current-review-state.json")
13073
13830
  };
13074
13831
  }
13075
13832
 
@@ -13079,7 +13836,7 @@ async function ensureRefineSession(sessionId, artifactsRoot, initialSnapshot) {
13079
13836
  await mkdir(paths.sessionDir, { recursive: true });
13080
13837
  try {
13081
13838
  await access2(paths.statePath);
13082
- const savedState = await readFile7(paths.statePath, "utf8");
13839
+ const savedState = await readFile9(paths.statePath, "utf8");
13083
13840
  return JSON.parse(savedState);
13084
13841
  } catch {
13085
13842
  await writeFile(paths.statePath, JSON.stringify(initialSnapshot, null, 2), "utf8");
@@ -13089,12 +13846,12 @@ async function ensureRefineSession(sessionId, artifactsRoot, initialSnapshot) {
13089
13846
  }
13090
13847
 
13091
13848
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/review-session/repositories/review-artifacts-root.js
13092
- import { resolve as resolve16 } from "node:path";
13849
+ import { resolve as resolve17 } from "node:path";
13093
13850
  function getRefineArtifactsRoot() {
13094
13851
  if (process.env["EDS_REVIEW_ARTIFACTS_DIR"]) {
13095
- return resolve16(process.env["EDS_REVIEW_ARTIFACTS_DIR"]);
13852
+ return resolve17(process.env["EDS_REVIEW_ARTIFACTS_DIR"]);
13096
13853
  }
13097
- return resolve16(configRoot(), "reviews");
13854
+ return resolve17(configRoot(), "reviews");
13098
13855
  }
13099
13856
 
13100
13857
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/review-session/repositories/save-review-state.js
@@ -13110,7 +13867,7 @@ async function mergePreviewValidationErrorsIntoReviewSession(sessionId, errors,
13110
13867
  let snapshot;
13111
13868
  try {
13112
13869
  await access3(paths.statePath);
13113
- snapshot = JSON.parse(await readFile8(paths.statePath, "utf8"));
13870
+ snapshot = JSON.parse(await readFile10(paths.statePath, "utf8"));
13114
13871
  } catch {
13115
13872
  snapshot = await loadAndValidateForReview(sessionId, void 0);
13116
13873
  snapshot = await ensureRefineSession(sessionId, artifactsRoot, snapshot);
@@ -13148,7 +13905,7 @@ async function mergePreviewValidationErrorsIntoReviewSession(sessionId, errors,
13148
13905
  }
13149
13906
 
13150
13907
  // packages/experience-design-system-backend-pipeline/dist/src/steps/selection/src/controller/review/reject-components-by-name.js
13151
- import { readFile as readFile9 } from "node:fs/promises";
13908
+ import { readFile as readFile11 } from "node:fs/promises";
13152
13909
  async function rejectComponentsByName(sessionId, names, opts = {}) {
13153
13910
  if (names.length === 0)
13154
13911
  return;
@@ -13164,7 +13921,7 @@ async function rejectComponentsByName(sessionId, names, opts = {}) {
13164
13921
  const nameSet = new Set(names);
13165
13922
  let snapshot;
13166
13923
  try {
13167
- snapshot = JSON.parse(await readFile9(paths.statePath, "utf8"));
13924
+ snapshot = JSON.parse(await readFile11(paths.statePath, "utf8"));
13168
13925
  } catch {
13169
13926
  return;
13170
13927
  }
@@ -13173,7 +13930,7 @@ async function rejectComponentsByName(sessionId, names, opts = {}) {
13173
13930
  }
13174
13931
 
13175
13932
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/helpers/collect-files/collect-files.js
13176
- import { statSync as statSync4 } from "node:fs";
13933
+ import { statSync as statSync5 } from "node:fs";
13177
13934
  import path4 from "node:path";
13178
13935
 
13179
13936
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/helpers/collect-files/build-scan-warnings.js
@@ -13228,7 +13985,9 @@ var EXCLUDED_SUFFIXES = [
13228
13985
  ".spec.ts",
13229
13986
  ".spec.tsx",
13230
13987
  ".test.ts",
13231
- ".test.tsx"
13988
+ ".test.tsx",
13989
+ ".harness.ts",
13990
+ ".harness.tsx"
13232
13991
  ];
13233
13992
  var IGNORED_DIRS = /* @__PURE__ */ new Set([
13234
13993
  ".changeset",
@@ -13246,9 +14005,12 @@ var IGNORED_DIRS = /* @__PURE__ */ new Set([
13246
14005
  "dist",
13247
14006
  "example",
13248
14007
  "examples",
14008
+ "harness",
14009
+ "harnesses",
13249
14010
  "node_modules",
13250
14011
  "out",
13251
- "storybook-static"
14012
+ "storybook-static",
14013
+ "testing"
13252
14014
  ]);
13253
14015
  var DENYLISTED_EXACT_FILE_NAMES = /* @__PURE__ */ new Set([
13254
14016
  "package.json",
@@ -13360,7 +14122,7 @@ function collectFiles(root, options = {}) {
13360
14122
  const resolved = path4.resolve(root);
13361
14123
  let stat5;
13362
14124
  try {
13363
- stat5 = statSync4(resolved);
14125
+ stat5 = statSync5(resolved);
13364
14126
  } catch (err) {
13365
14127
  return { ok: false, failure: classifyStatError(err.code), rootPath: resolved };
13366
14128
  }
@@ -13416,7 +14178,7 @@ function generateUlid(now = Date.now()) {
13416
14178
  }
13417
14179
 
13418
14180
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/runs/repositories/read-runs-file.js
13419
- import { readFile as readFile10 } from "node:fs/promises";
14181
+ import { readFile as readFile12 } from "node:fs/promises";
13420
14182
 
13421
14183
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/runs/helpers/migrate-record.js
13422
14184
  function migrateRecord(rec) {
@@ -13435,7 +14197,7 @@ var READABLE_VERSIONS = /* @__PURE__ */ new Set([1, 2, 3]);
13435
14197
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/runs/repositories/read-runs-file.js
13436
14198
  async function readRunsFileMaybe() {
13437
14199
  try {
13438
- const raw = await readFile10(runsFilePath(), "utf8");
14200
+ const raw = await readFile12(runsFilePath(), "utf8");
13439
14201
  const parsed = JSON.parse(raw);
13440
14202
  if (!READABLE_VERSIONS.has(parsed.version)) {
13441
14203
  throw new Error(`runs.json version mismatch: file is v${parsed.version}, this CLI expects v${RUNS_FILE_VERSION} (also reads: ${[...READABLE_VERSIONS].join(", ")}). Back up and remove the file to start fresh.`);
@@ -13452,9 +14214,9 @@ async function readRunsFileMaybe() {
13452
14214
 
13453
14215
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/runs/repositories/write-runs-file.js
13454
14216
  import { mkdir as mkdir2, rename, writeFile as writeFile3 } from "node:fs/promises";
13455
- import { dirname as dirname12 } from "node:path";
14217
+ import { dirname as dirname13 } from "node:path";
13456
14218
  async function writeRunsFileAtomic(file) {
13457
- await mkdir2(dirname12(runsFilePath()), { recursive: true });
14219
+ await mkdir2(dirname13(runsFilePath()), { recursive: true });
13458
14220
  const body = JSON.stringify(file, null, 2) + "\n";
13459
14221
  const tmp = `${runsFilePath()}.${process.pid}.${Date.now()}.tmp`;
13460
14222
  await writeFile3(tmp, body, { mode: 384 });
@@ -13494,8 +14256,8 @@ async function updateRun(id, patch) {
13494
14256
  }
13495
14257
 
13496
14258
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/runs/services/build-source-fingerprint.js
13497
- import { readFile as readFile11, stat } from "node:fs/promises";
13498
- import { resolve as resolve17 } from "node:path";
14259
+ import { readFile as readFile13, stat } from "node:fs/promises";
14260
+ import { resolve as resolve18 } from "node:path";
13499
14261
 
13500
14262
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/runs/helpers/sha256-hex.js
13501
14263
  import { createHash as createHash8 } from "node:crypto";
@@ -13517,7 +14279,7 @@ async function buildSourceFingerprint(opts) {
13517
14279
  const name = rowField(row, "name");
13518
14280
  if (!sourcePath)
13519
14281
  continue;
13520
- const abs = resolve17(sourcePath);
14282
+ const abs = resolve18(sourcePath);
13521
14283
  if (seen.has(abs))
13522
14284
  continue;
13523
14285
  seen.add(abs);
@@ -13534,10 +14296,10 @@ async function buildSourceFingerprint(opts) {
13534
14296
  let rawTokensMtime = null;
13535
14297
  let rawTokensContentHash = null;
13536
14298
  if (opts.rawTokensPath) {
13537
- const abs = resolve17(opts.rawTokensPath);
14299
+ const abs = resolve18(opts.rawTokensPath);
13538
14300
  rawTokensPath = abs;
13539
14301
  try {
13540
- const [st, buf] = await Promise.all([stat(abs), readFile11(abs)]);
14302
+ const [st, buf] = await Promise.all([stat(abs), readFile13(abs)]);
13541
14303
  rawTokensMtime = st.mtime.toISOString();
13542
14304
  rawTokensContentHash = sha256Hex(buf);
13543
14305
  } catch {
@@ -13619,12 +14381,12 @@ async function writeScopeDecisionsSnapshot(db, sessionId, decisions) {
13619
14381
  }
13620
14382
 
13621
14383
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/review-session/repositories/load-accepted-names.js
13622
- import { readFile as readFile12 } from "node:fs/promises";
14384
+ import { readFile as readFile14 } from "node:fs/promises";
13623
14385
  async function loadAcceptedNames(sessionId) {
13624
14386
  try {
13625
14387
  const artifactsRoot = getRefineArtifactsRoot();
13626
14388
  const paths = await getRefineSessionPaths(sessionId, artifactsRoot);
13627
- const raw = await readFile12(paths.statePath, "utf8");
14389
+ const raw = await readFile14(paths.statePath, "utf8");
13628
14390
  const snapshot = JSON.parse(raw);
13629
14391
  const accepted = snapshot.components.filter((c2) => c2.status === "accepted").map((c2) => c2.name);
13630
14392
  if (accepted.length === 0)
@@ -14322,7 +15084,7 @@ function errorMessage(error) {
14322
15084
  return error instanceof Error && error.message ? error.message : String(error);
14323
15085
  }
14324
15086
  function defaultSleep(delayMs) {
14325
- return new Promise((resolve28) => setTimeout(resolve28, delayMs));
15087
+ return new Promise((resolve29) => setTimeout(resolve29, delayMs));
14326
15088
  }
14327
15089
 
14328
15090
  // packages/experience-design-system-backend-pipeline/dist/src/steps/apply/src/helpers/sanitize-preview.js
@@ -14563,7 +15325,7 @@ var ApiClient = class {
14563
15325
  const progress = maxAttempts > 1 ? attempt / (maxAttempts - 1) : 0;
14564
15326
  const baseDelay = intervalMs + (maxIntervalMs - intervalMs) * progress;
14565
15327
  const jitter = Math.random() * baseDelay * 0.15;
14566
- await new Promise((resolve28) => setTimeout(resolve28, baseDelay + jitter));
15328
+ await new Promise((resolve29) => setTimeout(resolve29, baseDelay + jitter));
14567
15329
  }
14568
15330
  }
14569
15331
  throw new Error(`Operation ${operationId} timed out after ${maxAttempts} attempts`);
@@ -14950,7 +15712,7 @@ function formatApiError2(request) {
14950
15712
 
14951
15713
  // packages/experience-design-system-backend-pipeline/dist/src/steps/apply/src/helpers/tokens/read-tokens-from-path.js
14952
15714
  init_shared();
14953
- import { readFile as readFile13, stat as stat3 } from "node:fs/promises";
15715
+ import { readFile as readFile15, stat as stat3 } from "node:fs/promises";
14954
15716
 
14955
15717
  // packages/experience-design-system-backend-pipeline/dist/src/steps/apply/src/helpers/tokens/collect-json-files.js
14956
15718
  import { readdir, stat as stat2 } from "node:fs/promises";
@@ -15009,7 +15771,7 @@ async function readMergedFromDir(flag, dir) {
15009
15771
  const merged = {};
15010
15772
  for (const file of files.sort()) {
15011
15773
  try {
15012
- const text = await readFile13(file, "utf8");
15774
+ const text = await readFile15(file, "utf8");
15013
15775
  const parsed = JSON.parse(text);
15014
15776
  if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
15015
15777
  Object.assign(merged, parsed);
@@ -15023,7 +15785,7 @@ async function readMergedFromDir(flag, dir) {
15023
15785
  async function readSingleFile(flag, p) {
15024
15786
  let text;
15025
15787
  try {
15026
- text = await readFile13(p, "utf8");
15788
+ text = await readFile15(p, "utf8");
15027
15789
  } catch {
15028
15790
  throw new Error(`file not found: ${p} (from ${flag})`);
15029
15791
  }
@@ -15114,12 +15876,12 @@ async function fetchAndPersistExistingContentfulEntities(request) {
15114
15876
  }
15115
15877
 
15116
15878
  // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/controller/existing-entities/read-from-session.js
15117
- import { readFile as readFile14 } from "node:fs/promises";
15879
+ import { readFile as readFile16 } from "node:fs/promises";
15118
15880
  async function readExistingContentfulEntitiesFromSession(request) {
15119
15881
  if (!request.path)
15120
15882
  return void 0;
15121
15883
  try {
15122
- const raw = await readFile14(request.path, "utf8");
15884
+ const raw = await readFile16(request.path, "utf8");
15123
15885
  const parsed = JSON.parse(raw);
15124
15886
  if (!Array.isArray(parsed.components) || !Array.isArray(parsed.tokens))
15125
15887
  return void 0;
@@ -15459,7 +16221,7 @@ init_describe_agent_failure();
15459
16221
  init_resolve_binary();
15460
16222
  init_resolve_skill_path();
15461
16223
  init_parse_map_token_prop_tool_calls();
15462
- import { resolve as resolve18 } from "node:path";
16224
+ import { resolve as resolve19 } from "node:path";
15463
16225
  init_cache_keys();
15464
16226
 
15465
16227
  // packages/experience-design-system-backend-pipeline/dist/src/agents/helpers/resolution/binary-exists.js
@@ -15514,6 +16276,7 @@ function analyticsEnabled() {
15514
16276
  import { Analytics } from "@segment/analytics-node";
15515
16277
  var DEFAULT_WRITE_KEY = "6DmxiEPN3SV1vbRTTMcNqDzCvkfwT06N";
15516
16278
  var analyticsClient = null;
16279
+ var flushChain = Promise.resolve();
15517
16280
  function resolveWriteKey() {
15518
16281
  const key = (process.env["SEGMENT_WRITE_KEY"] ?? "").trim();
15519
16282
  return key.length > 0 ? key : DEFAULT_WRITE_KEY;
@@ -15548,14 +16311,17 @@ async function trackEvent(event, properties, anonymousId, options) {
15548
16311
  }
15549
16312
  }
15550
16313
  async function flushAnalytics() {
15551
- if (!analyticsClient)
15552
- return;
15553
- try {
15554
- await analyticsClient.closeAndFlush();
15555
- } catch {
15556
- } finally {
16314
+ flushChain = flushChain.then(async () => {
16315
+ const client2 = analyticsClient;
16316
+ if (!client2)
16317
+ return;
15557
16318
  analyticsClient = null;
15558
- }
16319
+ try {
16320
+ await client2.closeAndFlush();
16321
+ } catch {
16322
+ }
16323
+ });
16324
+ return flushChain;
15559
16325
  }
15560
16326
 
15561
16327
  // packages/experience-design-system-backend-pipeline/dist/src/analytics/constants.js
@@ -15764,7 +16530,7 @@ async function runMapTokens(request) {
15764
16530
  outDir: process.cwd(),
15765
16531
  existingTokensInline: request.existingEntitiesInline,
15766
16532
  ...request.skillContentOverride !== void 0 ? { skillContentOverride: request.skillContentOverride } : {},
15767
- ...request.skillContentOverride === void 0 && request.skillPathOverride ? { skillPathOverride: resolve18(request.skillPathOverride) } : {}
16533
+ ...request.skillContentOverride === void 0 && request.skillPathOverride ? { skillPathOverride: resolve19(request.skillPathOverride) } : {}
15768
16534
  });
15769
16535
  if (request.printPrompt) {
15770
16536
  const prompt2 = await buildMapPrompt();
@@ -15880,7 +16646,7 @@ function hasNoAuthoringSurface(component) {
15880
16646
  }
15881
16647
 
15882
16648
  // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/helpers/evidence/source-inspection.js
15883
- import { readFile as readFile15 } from "node:fs/promises";
16649
+ import { readFile as readFile17 } from "node:fs/promises";
15884
16650
 
15885
16651
  // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/constants/review-reasons.js
15886
16652
  var HIGH_CONFIDENCE_DATA_FETCH_WRAPPER_REASON = "data-fetch-wrapper";
@@ -15952,7 +16718,14 @@ function hasSiblingForwardRender(sourceText, siblingImports) {
15952
16718
  });
15953
16719
  }
15954
16720
  function hasVisibleUiRender(sourceText) {
15955
- return /return\s*(?:\(|<)/.test(sourceText) && VISIBLE_UI_TAG_PATTERN.test(sourceText);
16721
+ if (/return\s*(?:\(|<)/.test(sourceText) && VISIBLE_UI_TAG_PATTERN.test(sourceText))
16722
+ return true;
16723
+ if (/template\s*:\s*[`'"][\s\S]*?[`'"]/.test(sourceText)) {
16724
+ const inlineMatch = sourceText.match(/template\s*:\s*[`'"]([\s\S]*?)[`'"]/);
16725
+ if (inlineMatch && VISIBLE_UI_TAG_PATTERN.test(inlineMatch[1]))
16726
+ return true;
16727
+ }
16728
+ return /templateUrl\s*:\s*['"]/.test(sourceText);
15956
16729
  }
15957
16730
  function infraPropNames(component) {
15958
16731
  const props = component.props.map((prop) => prop.name);
@@ -15975,7 +16748,7 @@ function dedupeReasons(reasons) {
15975
16748
  async function inspectComponentSource(component) {
15976
16749
  let sourceText = "";
15977
16750
  try {
15978
- sourceText = await readFile15(component.source, "utf8");
16751
+ sourceText = await readFile17(component.source, "utf8");
15979
16752
  } catch {
15980
16753
  return {
15981
16754
  wrapperConfidence: 0,
@@ -16382,7 +17155,7 @@ async function retryDatabaseWrite(operation, attempts = 8) {
16382
17155
  const message = error instanceof Error ? error.message : String(error);
16383
17156
  if (!/database is locked|database is busy/i.test(message) || attempt >= attempts)
16384
17157
  throw error;
16385
- await new Promise((resolve28) => setTimeout(resolve28, Math.min(250 * attempt, 2e3)));
17158
+ await new Promise((resolve29) => setTimeout(resolve29, Math.min(250 * attempt, 2e3)));
16386
17159
  }
16387
17160
  }
16388
17161
  }
@@ -16414,7 +17187,7 @@ function resolveCompositionAgentName(flagValue) {
16414
17187
  }
16415
17188
 
16416
17189
  // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-extract-and-compose-session/helpers/read-candidate-files.js
16417
- import { readFile as readFile16 } from "node:fs/promises";
17190
+ import { readFile as readFile18 } from "node:fs/promises";
16418
17191
  async function readCandidateFiles(components, extraFiles = []) {
16419
17192
  const paths = new Set(extraFiles);
16420
17193
  for (const c2 of components) {
@@ -16424,7 +17197,7 @@ async function readCandidateFiles(components, extraFiles = []) {
16424
17197
  const out = [];
16425
17198
  await Promise.all([...paths].map(async (p) => {
16426
17199
  try {
16427
- const content = await readFile16(p, "utf8");
17200
+ const content = await readFile18(p, "utf8");
16428
17201
  out.push({ path: p, content });
16429
17202
  } catch {
16430
17203
  }
@@ -16595,7 +17368,7 @@ init_build_prompt();
16595
17368
  init_create_local_cli_agent_invoker();
16596
17369
  init_invoke_agent_with_output();
16597
17370
  init_parse_token_tool_calls();
16598
- import { readFile as readFile17 } from "node:fs/promises";
17371
+ import { readFile as readFile19 } from "node:fs/promises";
16599
17372
  import { basename as basename5, resolve as pathResolve } from "node:path";
16600
17373
  init_cache_keys();
16601
17374
  init_parse_prompt_overrides();
@@ -16628,7 +17401,7 @@ async function runGenerateTokensSession(request) {
16628
17401
  throw new Error(`Prompt override error(s): ${promptErrors.join("; ")}`);
16629
17402
  const tokensOverride = overridesMap.get("tokens");
16630
17403
  const skillContentOverride = tokensOverride ? await resolvePromptOverride(tokensOverride) : void 0;
16631
- const rawTokensInline = await readFile17(pathResolve(rawTokensPath), "utf8");
17404
+ const rawTokensInline = await readFile19(pathResolve(rawTokensPath), "utf8");
16632
17405
  const tokenInputHash = hashTokenContent(rawTokensInline);
16633
17406
  const db = openPipelineDb();
16634
17407
  try {
@@ -16745,7 +17518,7 @@ async function readExistingEntities(request) {
16745
17518
  // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-generate-components-session/helpers/resolve-generate-prompt.js
16746
17519
  init_parse_prompt_overrides();
16747
17520
  init_resolve_prompt_override();
16748
- import { resolve as resolve19 } from "node:path";
17521
+ import { resolve as resolve20 } from "node:path";
16749
17522
  async function resolveGeneratePrompt(overrides) {
16750
17523
  const { overrides: parsed, errors } = parsePromptOverrides(overrides);
16751
17524
  if (errors.length > 0)
@@ -16756,7 +17529,7 @@ async function resolveGeneratePrompt(overrides) {
16756
17529
  const text = await resolvePromptOverride(entry);
16757
17530
  if (entry.kind === "text")
16758
17531
  return { text };
16759
- return { path: resolve19(entry.value), text };
17532
+ return { path: resolve20(entry.value), text };
16760
17533
  }
16761
17534
 
16762
17535
  // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-generate-components-session/helpers/run-one-generate-component.js
@@ -17470,19 +18243,19 @@ import { useEffect as useEffect5, useRef as useRef3, useState as useState9 } fro
17470
18243
 
17471
18244
  // packages/experience-design-system-cli/src/tui/import/steps/06-extraction/run.ts
17472
18245
  import { mkdir as mkdir7 } from "node:fs/promises";
17473
- import { join as join18, resolve as resolve22 } from "node:path";
18246
+ import { join as join18, resolve as resolve23 } from "node:path";
17474
18247
 
17475
18248
  // packages/experience-design-system-cli/src/tui/import/steps/06-extraction/find-skill-path.ts
17476
18249
  import { existsSync as existsSync8 } from "node:fs";
17477
- import { dirname as dirname14, join as join17, resolve as resolve20 } from "node:path";
18250
+ import { dirname as dirname15, join as join17, resolve as resolve21 } from "node:path";
17478
18251
  import { fileURLToPath as fileURLToPath4 } from "node:url";
17479
18252
  function findSkillPath(fileName) {
17480
- const thisDir = dirname14(fileURLToPath4(import.meta.url));
18253
+ const thisDir = dirname15(fileURLToPath4(import.meta.url));
17481
18254
  let dir = thisDir;
17482
18255
  for (; ; ) {
17483
18256
  const candidate = join17(dir, "skills", fileName);
17484
18257
  if (existsSync8(candidate)) return candidate;
17485
- const parent = resolve20(dir, "..");
18258
+ const parent = resolve21(dir, "..");
17486
18259
  if (parent === dir) {
17487
18260
  throw new Error(`skill file not found (looked for skills/${fileName} from ${thisDir})`);
17488
18261
  }
@@ -17491,11 +18264,11 @@ function findSkillPath(fileName) {
17491
18264
  }
17492
18265
 
17493
18266
  // packages/experience-design-system-cli/src/tui/import/steps/06-extraction/selection.ts
17494
- import { resolve as resolve21 } from "node:path";
18267
+ import { resolve as resolve22 } from "node:path";
17495
18268
  var SELECT_SKILL_PATH = findSkillPath("select-components.md");
17496
18269
  var DEFAULT_TIMEOUT_MS5 = Number(process.env.EDS_AGENT_TIMEOUT_MS ?? 5 * 60 * 1e3);
17497
18270
  async function hashSelectPrompt(options) {
17498
- const promptHash = options.promptText ? hashContent(options.promptText) : options.promptPath ? await hashFile(resolve21(options.promptPath)) : await hashFile(SELECT_SKILL_PATH);
18271
+ const promptHash = options.promptText ? hashContent(options.promptText) : options.promptPath ? await hashFile(resolve22(options.promptPath)) : await hashFile(SELECT_SKILL_PATH);
17499
18272
  return hashContent(`${promptHash}|${options.agent}|${options.model ?? ""}`);
17500
18273
  }
17501
18274
  async function runSelection(options) {
@@ -17590,7 +18363,7 @@ var realDeps = {
17590
18363
  var fail = (step, message) => ({ ok: false, step, message });
17591
18364
  var errorMessage2 = (error) => error instanceof Error ? error.message : String(error);
17592
18365
  async function runExtraction(input, onProgress, deps = realDeps) {
17593
- const outDir = input.outDir ?? join18(resolve22(input.projectPath), ".contentful");
18366
+ const outDir = input.outDir ?? join18(resolve23(input.projectPath), ".contentful");
17594
18367
  let progress = initialProgress({
17595
18368
  hasCredentials: input.credentials !== null,
17596
18369
  hasRawTokens: input.rawTokensPath !== ""
@@ -17714,7 +18487,7 @@ async function resolveSelectionPrompt(overrides) {
17714
18487
  if (select?.kind === "text") return { promptText: select.value };
17715
18488
  if (select?.kind === "path") {
17716
18489
  await resolvePromptOverride(select);
17717
- return { promptPath: resolve22(select.value) };
18490
+ return { promptPath: resolve23(select.value) };
17718
18491
  }
17719
18492
  return {};
17720
18493
  }
@@ -20688,7 +21461,7 @@ function GenerationScreen({
20688
21461
  import { useEffect as useEffect10, useRef as useRef8, useState as useState16 } from "react";
20689
21462
 
20690
21463
  // packages/experience-design-system-cli/src/tui/import/steps/08-generation/run.ts
20691
- import { resolve as resolve23 } from "node:path";
21464
+ import { resolve as resolve24 } from "node:path";
20692
21465
 
20693
21466
  // packages/experience-design-system-cli/src/tui/import/steps/08-generation/map-tokens.ts
20694
21467
  async function prepareMapTokens(input, generatedSessionId) {
@@ -20823,7 +21596,7 @@ async function buildMapTokensOptions(input) {
20823
21596
  if (mapOverride?.kind === "text") prompt.skillContentOverride = mapOverride.value;
20824
21597
  if (mapOverride?.kind === "path") {
20825
21598
  await resolvePromptOverride(mapOverride);
20826
- prompt.skillPathOverride = resolve23(mapOverride.value);
21599
+ prompt.skillPathOverride = resolve24(mapOverride.value);
20827
21600
  }
20828
21601
  if (input.existingEntitiesPath) {
20829
21602
  const entities = await readExistingContentfulEntitiesFromSession({ path: input.existingEntitiesPath });
@@ -26608,10 +27381,10 @@ function DoneStep({
26608
27381
  import { useState as useState26 } from "react";
26609
27382
  import { Box as Box39, Text as Text42 } from "ink";
26610
27383
  import { readdirSync as readdirSync3 } from "node:fs";
26611
- import { dirname as dirname15, basename as basename6, join as join20 } from "node:path";
27384
+ import { dirname as dirname16, basename as basename6, join as join20 } from "node:path";
26612
27385
 
26613
27386
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/path-utils.ts
26614
- import { resolve as resolve24 } from "node:path";
27387
+ import { resolve as resolve25 } from "node:path";
26615
27388
  import { homedir as homedir4 } from "node:os";
26616
27389
  function expandTilde(input) {
26617
27390
  if (input === "~" || input.startsWith("~/") || input.startsWith("~\\")) {
@@ -26625,7 +27398,7 @@ function normalizePath(input) {
26625
27398
  p = p.slice(1, -1);
26626
27399
  }
26627
27400
  p = expandTilde(p);
26628
- return resolve24(p);
27401
+ return resolve25(p);
26629
27402
  }
26630
27403
 
26631
27404
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/use-blinking-cursor.ts
@@ -26644,7 +27417,7 @@ import { jsx as jsx49, jsxs as jsxs40 } from "react/jsx-runtime";
26644
27417
  function autocomplete(partial) {
26645
27418
  if (!partial) return null;
26646
27419
  const normalized = normalizePath(partial);
26647
- const dir = dirname15(normalized);
27420
+ const dir = dirname16(normalized);
26648
27421
  const base = basename6(normalized);
26649
27422
  let entries;
26650
27423
  try {
@@ -27441,7 +28214,7 @@ import { useEffect as useEffect21, useRef as useRef14, useSyncExternalStore } fr
27441
28214
  import { appendFileSync, writeFileSync } from "node:fs";
27442
28215
  import { mkdir as mkdir8 } from "node:fs/promises";
27443
28216
  import { tmpdir } from "node:os";
27444
- import { join as join22, resolve as resolve25 } from "node:path";
28217
+ import { join as join22, resolve as resolve26 } from "node:path";
27445
28218
 
27446
28219
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/wizard-state-transitions.ts
27447
28220
  function shouldBypassPreview(state2) {
@@ -27815,7 +28588,7 @@ var realSaveDeps = () => ({
27815
28588
  writeFile: (path5, contents) => writeFile7(path5, contents),
27816
28589
  appendRun,
27817
28590
  buildSourceFingerprint,
27818
- sleep: (ms) => new Promise((resolve28) => setTimeout(resolve28, ms)),
28591
+ sleep: (ms) => new Promise((resolve29) => setTimeout(resolve29, ms)),
27819
28592
  warn: (message) => process.stderr.write(message)
27820
28593
  });
27821
28594
  async function runPrintFiles(input, deps, onPatch) {
@@ -28154,7 +28927,7 @@ function createFlowController(start, deps) {
28154
28927
  },
28155
28928
  async submitPath(submitted) {
28156
28929
  await deps.mkdir(submitted);
28157
- if (resolve25(submitted) !== resolve25(state2.outDir) && await deps.detectSaveConflict(submitted)) {
28930
+ if (resolve26(submitted) !== resolve26(state2.outDir) && await deps.detectSaveConflict(submitted)) {
28158
28931
  const subdir = deps.buildTimestampedSubdir(submitted);
28159
28932
  await deps.mkdir(subdir);
28160
28933
  await proceedToWrite(subdir);
@@ -28212,7 +28985,7 @@ init_debug_mode_store();
28212
28985
  init_version();
28213
28986
 
28214
28987
  // packages/experience-design-system-cli/src/tui/help/file-locations.ts
28215
- import { join as join25, resolve as resolve27 } from "node:path";
28988
+ import { join as join25, resolve as resolve28 } from "node:path";
28216
28989
  function describeFileLocations({
28217
28990
  contentfulBaseDir,
28218
28991
  debugModeEnabled,
@@ -28224,7 +28997,7 @@ function describeFileLocations({
28224
28997
  importFiles: `${join25("<project>", ".contentful")}/ (tokens.json, components.json)`
28225
28998
  };
28226
28999
  }
28227
- const base = contentfulBaseDir ? resolve27(contentfulBaseDir) : "<project>";
29000
+ const base = contentfulBaseDir ? resolve28(contentfulBaseDir) : "<project>";
28228
29001
  const session = currentSessionDir2 ?? join25(base, ".contentful", "<date>-session-<n>");
28229
29002
  return {
28230
29003
  debugLogs: join25(session, "debug"),
@@ -28445,20 +29218,20 @@ function resolveOnPath(binary) {
28445
29218
  () => null
28446
29219
  );
28447
29220
  }
28448
- return new Promise((resolve28) => {
29221
+ return new Promise((resolve29) => {
28449
29222
  execFile2(
28450
29223
  process.platform === "win32" ? "where" : "which",
28451
29224
  [binary],
28452
- (error, stdout) => resolve28(error ? null : stdout.split("\n")[0]?.trim() ?? null)
29225
+ (error, stdout) => resolve29(error ? null : stdout.split("\n")[0]?.trim() ?? null)
28453
29226
  );
28454
29227
  });
28455
29228
  }
28456
29229
  function readVersion(binary) {
28457
- return new Promise((resolve28) => {
29230
+ return new Promise((resolve29) => {
28458
29231
  execFile2(binary, ["--version"], { timeout: VERSION_TIMEOUT_MS }, (error, stdout) => {
28459
29232
  const line = stdout.split("\n")[0]?.trim() ?? "";
28460
- if (!error && line) resolve28(pass("version", line));
28461
- else resolve28(fail3("version", "runs, but did not report a version"));
29233
+ if (!error && line) resolve29(pass("version", line));
29234
+ else resolve29(fail3("version", "runs, but did not report a version"));
28462
29235
  });
28463
29236
  });
28464
29237
  }