forgesmith 0.6.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -122,9 +122,6 @@ declare function generateOnboardingDoc(blueprint: BlueprintData | null, opts: On
122
122
 
123
123
  declare function generateRefactoringReport(blueprint: BlueprintData | null, opts: RefactoringReportOpts, provider: LlmProvider): Promise<GenerationResult>;
124
124
 
125
- declare function readPrismDirectory(prismPath: string): Promise<PrismData>;
126
- declare function readBlueprintData(targetPath: string): Promise<BlueprintData | null>;
127
-
128
125
  declare function generateAskDrivenAsset(blueprint: BlueprintData | null, question: string, opts: AskDrivenAssetOpts, provider: LlmProvider): Promise<GenerationResult>;
129
126
 
130
127
  type ScopeKind = "framework" | "app" | "tenant";
@@ -211,6 +208,20 @@ interface ForgeScope {
211
208
  env?: string | null;
212
209
  }
213
210
  type ForgeSubview = "signals" | "templates" | "audiences" | "outputs" | "walkthroughs";
211
+ interface Zone {
212
+ id: string;
213
+ name: string;
214
+ files: string[];
215
+ fileCount: number;
216
+ heat: number;
217
+ }
218
+ interface FileEntry {
219
+ path: string;
220
+ importCount: number;
221
+ importedByCount: number;
222
+ lineCount: number;
223
+ zone: string;
224
+ }
214
225
 
215
226
  interface BrandKitPalette {
216
227
  primary: string;
@@ -285,7 +296,6 @@ interface PrismBrandDraft {
285
296
  audienceMix: string;
286
297
  };
287
298
  }
288
- declare function extractBrandFromPrismBlueprint(targetPath: string): Promise<PrismBrandDraft>;
289
299
 
290
300
  type WidgetKind = "stat-card" | "feature-grid" | "testimonial" | "cta-banner" | "metric-badge" | "pricing-tier" | "changelog-row" | "social-proof";
291
301
  type WidgetSlotType = "text" | "number" | "color" | "url" | "image-url" | "multiline" | "select";
@@ -847,41 +857,8 @@ declare const FORGE_AUDIENCES: ForgeAudience[];
847
857
 
848
858
  declare const FORGE_TEMPLATES: ForgeTemplate[];
849
859
 
850
- /**
851
- * Reads a blueprint from the target project.
852
- * Tries: {targetPath}/.prism/blueprint/snapshot.json (preferred, legacy format)
853
- * then: {targetPath}/.prism/blueprint.json
854
- * Returns null if neither file exists or if path is unsafe.
855
- */
856
- declare function readBlueprintFromTarget(targetPath: string): BlueprintData | null;
857
- interface Zone {
858
- id: string;
859
- name: string;
860
- files: string[];
861
- fileCount: number;
862
- heat: number;
863
- }
864
- interface FileEntry {
865
- path: string;
866
- importCount: number;
867
- importedByCount: number;
868
- lineCount: number;
869
- zone: string;
870
- }
871
- /** Groups files into zones (top-level directory segments). Sorted by heat desc. */
872
- declare function extractZones(blueprint: BlueprintData): Zone[];
873
- /** Files with highest importedByCount — proxy for "most-changed / hottest" files. */
874
- declare function extractTopChurnFiles(blueprint: BlueprintData, n?: number): FileEntry[];
875
- /** Files with highest importCount — most dependency-heavy, highest coupling. */
876
- declare function extractDependencyHotspots(blueprint: BlueprintData, n?: number): FileEntry[];
877
860
  /** Defence-in-depth: scan derived text for secret patterns before sending to LLM. */
878
861
  declare function scanForSecrets(text: string): boolean;
879
- /**
880
- * Produces a compact LLM-ready summary of the blueprint.
881
- * Contains ONLY metrics, file paths, and category names — never raw file contents.
882
- * Scanned for secrets before return; throws if any found (should never happen).
883
- */
884
- declare function deriveContextSummary(blueprint: BlueprintData): string;
885
862
 
886
863
  type PrismFocus = "release" | "changelog" | "deepdive" | "summary" | `zone:${string}` | `module:${string}`;
887
864
  interface PrismContextPrompt {
@@ -905,7 +882,6 @@ declare const PRISM_TEMPLATE_ARCHITECTURE_OVERVIEW: PrismTemplate;
905
882
  declare const PRISM_TEMPLATE_REFACTOR_RATIONALE: PrismTemplate;
906
883
  declare const PRISM_TEMPLATES: PrismTemplate[];
907
884
  declare function getPrismTemplate(id: string): PrismTemplate | undefined;
908
- declare function buildPrismContextPrompt(blueprint: BlueprintData, focus?: PrismFocus, highlight?: string): PrismContextPrompt;
909
885
 
910
886
  interface RefineAssetInput {
911
887
  assetId: string;
@@ -939,4 +915,4 @@ declare function exportToICalendar(entries: ScheduledEntry[]): string;
939
915
  type ExportFormat = "buffer" | "hypefury" | "icalendar";
940
916
  declare function previewExport(entries: ScheduledEntry[], format: ExportFormat): string;
941
917
 
942
- export { ANIMATION_DURATION_PRESETS, type ArchitectureWalkthroughOpts, type ArrayField, type AskDrivenAssetFormat, type AskDrivenAssetOpts, type AssetKind, type AssetSlotsValidationErr, type AssetSlotsValidationOk, type AssetSlotsValidationResult, type AssetVersion, type AudienceId, BRAND_CONTENT_SLOT_KEYS, BUNDLED_DISPATCH_CHANNELS, BUNDLED_STYLE_PRESETS, BUNDLED_WIDGET_TEMPLATES, type BlueprintData, type BlueprintEdge, type BlueprintFile, type BooleanField, type BrandKit, type BrandKitFonts, type BrandKitLogo, type BrandKitPalette, type BrandKitSnapshot, type BrandKitVoice, type BrandPalette, type BrandThemeConfig, type ChangesSinceOpts, type Channel, type ChannelKind, type ChannelOutput, DEFAULT_ANIMATION_DURATION_SECONDS, DEFAULT_BRAND_KIT_FONTS, DEFAULT_BRAND_KIT_PALETTE, DEFAULT_BRAND_KIT_VOICE, DISPATCH_CHANNEL_BLOG, DISPATCH_CHANNEL_EMAIL, DISPATCH_CHANNEL_HN, DISPATCH_CHANNEL_INSTAGRAM, DISPATCH_CHANNEL_LINKEDIN, DISPATCH_CHANNEL_NEWSLETTER, DISPATCH_CHANNEL_REDDIT, DISPATCH_CHANNEL_SLACK, DISPATCH_CHANNEL_TWEET, type DiffEntry, type DiffResult, type DispatchAudienceContext, type DispatchBrandContext, type DispatchChannel, type DispatchRun, type ExportFormat, FORGE_AUDIENCES, FORGE_BRAND_THEME_ID, FORGE_TEMPLATES, FREE_TIER_WIDGET_IDS, type FileEntry, type ForgeAsset, type ForgeAudience, type ForgeGenerationDryRun, type ForgeGenerationError, type ForgeGenerationGenerated, type ForgeGenerationInput, type ForgeGenerationResult, type ForgeOutput, type ForgePrompt, type ForgeScope, type ForgeSignal, type ForgeStorage, type ForgeSubview, type ForgeTemplate, type ForgeThemeEntry, type FormErrors, type FormField, type FormSpec, type FormSpecOk, type FormSpecRaw, type Format, type GenerationResult, type Intent, type ListOutputsOpts, type LlmMessage, type LlmProvider, type LlmRequest, type LlmResponse, MAX_ANIMATION_DURATION_SECONDS, MIN_ANIMATION_DURATION_SECONDS, type Modality, type NumberField, type ObjectField, type OnboardingDocOpts, type OrchestrationInput, type OrchestrationResult, type OutputStatus, PRISM_TEMPLATES, PRISM_TEMPLATE_ARCHITECTURE_OVERVIEW, PRISM_TEMPLATE_REFACTOR_RATIONALE, PRISM_TEMPLATE_RELEASE_ANNOUNCEMENT, PRISM_TEMPLATE_SHIPPING_DIGEST, PRISM_TEMPLATE_ZONE_DEEPDIVE, type PrismBrandDraft, type PrismContextPrompt, type PrismData, type PrismFocus, type PrismInsight, type PrismRecommendation, type PrismSession, type PrismTemplate, type ProductTruth, type ProductTruthClaim, REFINE_COUNTDOWN_THRESHOLD, REFINE_SESSION_SOFT_CAP, REFINE_SUGGESTIONS, type ReadingLevel, type RefactoringReportOpts, type RefineAssetInput, type RefineAssetResult, type RefineLimitState, type RefineSuggestion, type ReleaseNotesOpts, type RenderWidgetInput, type ResolveBrandPaletteInput, type ResolvedTuple, STYLE_PRESET_BRUTALIST, STYLE_PRESET_DEFAULT, STYLE_PRESET_GLASSY, STYLE_PRESET_MINIMAL, type ScheduleRange, type ScheduledEntry, type ScheduledEntryMetadata, type ScheduledStatus, type SchemaDefinitionErr, type SchemaDefinitionOk, type SchemaDefinitionResult, type ScopeKind, type SignalKind, type StringField, type StyleTokens, TEMPLATE_SCHEMA_EXAMPLES, TEMPLATE_SCHEMA_GENERIC, type TokenUsage, type Tonality, type UrlBrandHints, type ValidationErr, type ValidationOk, type ValidationResult, WIDGET_TEMPLATE_CHANGELOG_ROW, WIDGET_TEMPLATE_CTA_BANNER, WIDGET_TEMPLATE_FEATURE_GRID, WIDGET_TEMPLATE_METRIC_BADGE, WIDGET_TEMPLATE_PRICING_TIER, WIDGET_TEMPLATE_SOCIAL_PROOF, WIDGET_TEMPLATE_STAT_CARD, WIDGET_TEMPLATE_TESTIMONIAL, type WidgetExportFormat, type WidgetInstance, type WidgetInstanceSnapshot, type WidgetKind, type WidgetSlotDef, type WidgetSlotType, type WidgetStyle, type WidgetStyleSnapshot, type WidgetTemplate, type Zone, applyEntryPatch, asAudienceId, assembleBrandUrlExtractionPrompt, assembleForgePrompt, brandThemeConfigToEntry, buildPrismContextPrompt, buildRevertVersion, buildScheduledEntry, buildVersion, cascadingScheduledFor, clampAnimationDuration, computeDiff, defaultBrandKit, defaultValueForField, deriveContextSummary, distill, entryInRange, exportToBufferCsv, exportToHypefuryCsv, exportToICalendar, extractBrandFromPrismBlueprint, extractDependencyHotspots, extractTopChurnFiles, extractZones, generateArchitectureWalkthrough, generateAskDrivenAsset, generateChangesSince, generateOnboardingDoc, generateRefactoringReport, generateReleaseNotes, getDispatchChannel, getPrismTemplate, getSlotValue, getStyleById, getWidgetTemplate, initialFormValues, next7DaysRange, nextVersionNumber, orchestrateDispatch, parseAndValidateSchemaDefinition, parseBrandKitFromLlmResponse, parseBrandThemeContent, parseStyleFromCss, parseStyleFromTailwindConfig, parseStyleFromTokensJson, parseThemeConfigContent, previewExport, readBlueprintData, readBlueprintFromTarget, readPrismDirectory, refineAsset, refineLimitState, renderWidget, resolveAnimatedChoice, resolveAnimationDuration, resolveBrandPalette, runForgeGeneration, scanForSecrets, schemaExampleFor, schemaToForm, templateAnimatedDefault, themeEntryToPalette, tryParseJsonObject, validateAgainstTemplateSchema, validateAssetSlots, validateFormValues, validateSchemaDefinition };
918
+ export { ANIMATION_DURATION_PRESETS, type ArchitectureWalkthroughOpts, type ArrayField, type AskDrivenAssetFormat, type AskDrivenAssetOpts, type AssetKind, type AssetSlotsValidationErr, type AssetSlotsValidationOk, type AssetSlotsValidationResult, type AssetVersion, type AudienceId, BRAND_CONTENT_SLOT_KEYS, BUNDLED_DISPATCH_CHANNELS, BUNDLED_STYLE_PRESETS, BUNDLED_WIDGET_TEMPLATES, type BlueprintData, type BlueprintEdge, type BlueprintFile, type BooleanField, type BrandKit, type BrandKitFonts, type BrandKitLogo, type BrandKitPalette, type BrandKitSnapshot, type BrandKitVoice, type BrandPalette, type BrandThemeConfig, type ChangesSinceOpts, type Channel, type ChannelKind, type ChannelOutput, DEFAULT_ANIMATION_DURATION_SECONDS, DEFAULT_BRAND_KIT_FONTS, DEFAULT_BRAND_KIT_PALETTE, DEFAULT_BRAND_KIT_VOICE, DISPATCH_CHANNEL_BLOG, DISPATCH_CHANNEL_EMAIL, DISPATCH_CHANNEL_HN, DISPATCH_CHANNEL_INSTAGRAM, DISPATCH_CHANNEL_LINKEDIN, DISPATCH_CHANNEL_NEWSLETTER, DISPATCH_CHANNEL_REDDIT, DISPATCH_CHANNEL_SLACK, DISPATCH_CHANNEL_TWEET, type DiffEntry, type DiffResult, type DispatchAudienceContext, type DispatchBrandContext, type DispatchChannel, type DispatchRun, type ExportFormat, FORGE_AUDIENCES, FORGE_BRAND_THEME_ID, FORGE_TEMPLATES, FREE_TIER_WIDGET_IDS, type FileEntry, type ForgeAsset, type ForgeAudience, type ForgeGenerationDryRun, type ForgeGenerationError, type ForgeGenerationGenerated, type ForgeGenerationInput, type ForgeGenerationResult, type ForgeOutput, type ForgePrompt, type ForgeScope, type ForgeSignal, type ForgeStorage, type ForgeSubview, type ForgeTemplate, type ForgeThemeEntry, type FormErrors, type FormField, type FormSpec, type FormSpecOk, type FormSpecRaw, type Format, type GenerationResult, type Intent, type ListOutputsOpts, type LlmMessage, type LlmProvider, type LlmRequest, type LlmResponse, MAX_ANIMATION_DURATION_SECONDS, MIN_ANIMATION_DURATION_SECONDS, type Modality, type NumberField, type ObjectField, type OnboardingDocOpts, type OrchestrationInput, type OrchestrationResult, type OutputStatus, PRISM_TEMPLATES, PRISM_TEMPLATE_ARCHITECTURE_OVERVIEW, PRISM_TEMPLATE_REFACTOR_RATIONALE, PRISM_TEMPLATE_RELEASE_ANNOUNCEMENT, PRISM_TEMPLATE_SHIPPING_DIGEST, PRISM_TEMPLATE_ZONE_DEEPDIVE, type PrismBrandDraft, type PrismContextPrompt, type PrismData, type PrismFocus, type PrismInsight, type PrismRecommendation, type PrismSession, type PrismTemplate, type ProductTruth, type ProductTruthClaim, REFINE_COUNTDOWN_THRESHOLD, REFINE_SESSION_SOFT_CAP, REFINE_SUGGESTIONS, type ReadingLevel, type RefactoringReportOpts, type RefineAssetInput, type RefineAssetResult, type RefineLimitState, type RefineSuggestion, type ReleaseNotesOpts, type RenderWidgetInput, type ResolveBrandPaletteInput, type ResolvedTuple, STYLE_PRESET_BRUTALIST, STYLE_PRESET_DEFAULT, STYLE_PRESET_GLASSY, STYLE_PRESET_MINIMAL, type ScheduleRange, type ScheduledEntry, type ScheduledEntryMetadata, type ScheduledStatus, type SchemaDefinitionErr, type SchemaDefinitionOk, type SchemaDefinitionResult, type ScopeKind, type SignalKind, type StringField, type StyleTokens, TEMPLATE_SCHEMA_EXAMPLES, TEMPLATE_SCHEMA_GENERIC, type TokenUsage, type Tonality, type UrlBrandHints, type ValidationErr, type ValidationOk, type ValidationResult, WIDGET_TEMPLATE_CHANGELOG_ROW, WIDGET_TEMPLATE_CTA_BANNER, WIDGET_TEMPLATE_FEATURE_GRID, WIDGET_TEMPLATE_METRIC_BADGE, WIDGET_TEMPLATE_PRICING_TIER, WIDGET_TEMPLATE_SOCIAL_PROOF, WIDGET_TEMPLATE_STAT_CARD, WIDGET_TEMPLATE_TESTIMONIAL, type WidgetExportFormat, type WidgetInstance, type WidgetInstanceSnapshot, type WidgetKind, type WidgetSlotDef, type WidgetSlotType, type WidgetStyle, type WidgetStyleSnapshot, type WidgetTemplate, type Zone, applyEntryPatch, asAudienceId, assembleBrandUrlExtractionPrompt, assembleForgePrompt, brandThemeConfigToEntry, buildRevertVersion, buildScheduledEntry, buildVersion, cascadingScheduledFor, clampAnimationDuration, computeDiff, defaultBrandKit, defaultValueForField, distill, entryInRange, exportToBufferCsv, exportToHypefuryCsv, exportToICalendar, generateArchitectureWalkthrough, generateAskDrivenAsset, generateChangesSince, generateOnboardingDoc, generateRefactoringReport, generateReleaseNotes, getDispatchChannel, getPrismTemplate, getSlotValue, getStyleById, getWidgetTemplate, initialFormValues, next7DaysRange, nextVersionNumber, orchestrateDispatch, parseAndValidateSchemaDefinition, parseBrandKitFromLlmResponse, parseBrandThemeContent, parseStyleFromCss, parseStyleFromTailwindConfig, parseStyleFromTokensJson, parseThemeConfigContent, previewExport, refineAsset, refineLimitState, renderWidget, resolveAnimatedChoice, resolveAnimationDuration, resolveBrandPalette, runForgeGeneration, scanForSecrets, schemaExampleFor, schemaToForm, templateAnimatedDefault, themeEntryToPalette, tryParseJsonObject, validateAgainstTemplateSchema, validateAssetSlots, validateFormValues, validateSchemaDefinition };
package/dist/index.mjs CHANGED
@@ -1,6 +1,3 @@
1
- import fs from 'fs/promises';
2
- import path, { join, normalize, resolve } from 'path';
3
- import { existsSync, readFileSync } from 'fs';
4
1
  import { randomUUID } from 'crypto';
5
2
 
6
3
  // src/generators/releaseNotes.ts
@@ -272,12 +269,12 @@ function detectImportCycles(edges) {
272
269
  const cycles = [];
273
270
  const visited = /* @__PURE__ */ new Set();
274
271
  const stack = /* @__PURE__ */ new Set();
275
- function dfs(node, path3) {
272
+ function dfs(node, path) {
276
273
  if (cycles.length >= 5) return;
277
274
  if (stack.has(node)) {
278
- const cycleStart = path3.indexOf(node);
275
+ const cycleStart = path.indexOf(node);
279
276
  if (cycleStart !== -1) {
280
- cycles.push(path3.slice(cycleStart).join(" \u2192 ") + " \u2192 " + node);
277
+ cycles.push(path.slice(cycleStart).join(" \u2192 ") + " \u2192 " + node);
281
278
  }
282
279
  return;
283
280
  }
@@ -285,7 +282,7 @@ function detectImportCycles(edges) {
285
282
  visited.add(node);
286
283
  stack.add(node);
287
284
  for (const neighbor of graph.get(node) ?? []) {
288
- dfs(neighbor, [...path3, node]);
285
+ dfs(neighbor, [...path, node]);
289
286
  }
290
287
  stack.delete(node);
291
288
  }
@@ -340,43 +337,6 @@ async function generateRefactoringReport(blueprint, opts, provider) {
340
337
  metadata: { generatedAt: (/* @__PURE__ */ new Date()).toISOString(), usedTokens: response.usedTokens, generator: "forgesmith" }
341
338
  };
342
339
  }
343
- async function readJsonFiles(dir) {
344
- try {
345
- const entries = await fs.readdir(dir);
346
- const results = [];
347
- for (const entry of entries) {
348
- if (!entry.endsWith(".json")) continue;
349
- try {
350
- const raw = await fs.readFile(path.join(dir, entry), "utf-8");
351
- results.push(JSON.parse(raw));
352
- } catch {
353
- }
354
- }
355
- return results;
356
- } catch {
357
- return [];
358
- }
359
- }
360
- async function readPrismDirectory(prismPath) {
361
- const sessionsDir = path.join(prismPath, "sessions");
362
- const recsDir = path.join(prismPath, "recommendations");
363
- const insightsDir = path.join(prismPath, "green", "insights", "accepted");
364
- const [sessions, recommendations, insights] = await Promise.all([
365
- readJsonFiles(sessionsDir),
366
- readJsonFiles(recsDir),
367
- readJsonFiles(insightsDir)
368
- ]);
369
- return { sessions, recommendations, insights };
370
- }
371
- async function readBlueprintData(targetPath) {
372
- const snapshotPath = path.join(targetPath, ".prism", "blueprint", "snapshot.json");
373
- try {
374
- const raw = await fs.readFile(snapshotPath, "utf-8");
375
- return JSON.parse(raw);
376
- } catch {
377
- return null;
378
- }
379
- }
380
340
 
381
341
  // src/generators/askDrivenAsset.ts
382
342
  var NO_DATA_MSG5 = "No Blueprint data available. Run prism scan first.";
@@ -1000,6 +960,8 @@ function refineLimitState(usedRefines, softCap = REFINE_SESSION_SOFT_CAP) {
1000
960
  showCountdown: used >= REFINE_COUNTDOWN_THRESHOLD
1001
961
  };
1002
962
  }
963
+
964
+ // src/forge/brandKit.ts
1003
965
  var DEFAULT_BRAND_KIT_PALETTE = {
1004
966
  primary: "#f97316",
1005
967
  secondary: "#1e293b",
@@ -1143,60 +1105,6 @@ function parseBrandKitFromLlmResponse(text, hints) {
1143
1105
  prism_detected: false
1144
1106
  };
1145
1107
  }
1146
- function deriveTechnicalScore(categories, total) {
1147
- if (total === 0) return 50;
1148
- const techFiles = (categories.lib ?? 0) + (categories.hook ?? 0);
1149
- const appFiles = (categories.app ?? 0) + (categories.component ?? 0);
1150
- const techRatio = techFiles / total;
1151
- const appRatio = appFiles / total;
1152
- return Math.round(30 + techRatio * 50 - appRatio * 10);
1153
- }
1154
- function deriveAudienceMix(categories, paths) {
1155
- const hasAdminPaths = paths.some((p) => /admin|dashboard|ops/.test(p));
1156
- const hasApiPaths = paths.some((p) => /\/api\/|route\.ts/.test(p));
1157
- const hasFrontend = (categories.component ?? 0) > 5;
1158
- if (hasAdminPaths && hasApiPaths) return "developer+operator";
1159
- if (hasApiPaths && !hasFrontend) return "developer";
1160
- if (hasFrontend && !hasApiPaths) return "end-user";
1161
- return "developer+business";
1162
- }
1163
- async function extractBrandFromPrismBlueprint(targetPath) {
1164
- const snapshotPath = path.join(targetPath, ".prism", "blueprint", "snapshot.json");
1165
- let blueprint = {};
1166
- try {
1167
- const raw = await fs.readFile(snapshotPath, "utf-8");
1168
- blueprint = JSON.parse(raw);
1169
- } catch {
1170
- }
1171
- const categories = blueprint.categories ?? {};
1172
- const files = blueprint.files ?? [];
1173
- const paths = files.map((f) => f.path ?? "");
1174
- const total = blueprint.stats?.totalFiles ?? files.length;
1175
- const technicalScore = deriveTechnicalScore(categories, total);
1176
- const audienceMix = deriveAudienceMix(categories, paths);
1177
- const projectName = blueprint.targetPath ? path.basename(blueprint.targetPath) : "Project";
1178
- const formality = technicalScore > 60 ? 65 : 50;
1179
- const technicality = Math.min(95, technicalScore + 10);
1180
- return {
1181
- suggestedName: projectName,
1182
- voice: {
1183
- tone: technicalScore > 60 ? "technical" : "professional",
1184
- audience: audienceMix.includes("developer") ? "developers" : "business",
1185
- vocabulary: [],
1186
- avoid: [],
1187
- formality,
1188
- technicality
1189
- },
1190
- prism_detected: true,
1191
- blueprint_path: snapshotPath,
1192
- stats: {
1193
- totalFiles: total,
1194
- categories,
1195
- technicalScore,
1196
- audienceMix
1197
- }
1198
- };
1199
- }
1200
1108
 
1201
1109
  // src/forge/brandPalette.ts
1202
1110
  function isNonEmptyString(v) {
@@ -1436,63 +1344,63 @@ function initialFormValues(fields, source) {
1436
1344
  function isEmptyString(v) {
1437
1345
  return typeof v === "string" && v.trim().length === 0;
1438
1346
  }
1439
- function validateField(field, value, path3) {
1347
+ function validateField(field, value, path) {
1440
1348
  const errors = {};
1441
1349
  switch (field.kind) {
1442
1350
  case "string": {
1443
1351
  if (field.required && (value === void 0 || value === null || isEmptyString(value))) {
1444
- errors[path3] = `${field.label} ist erforderlich`;
1352
+ errors[path] = `${field.label} ist erforderlich`;
1445
1353
  break;
1446
1354
  }
1447
1355
  if (typeof value === "string") {
1448
1356
  if (field.minLength !== void 0 && value.length < field.minLength) {
1449
- errors[path3] = `${field.label} mindestens ${field.minLength} Zeichen`;
1357
+ errors[path] = `${field.label} mindestens ${field.minLength} Zeichen`;
1450
1358
  } else if (field.maxLength !== void 0 && value.length > field.maxLength) {
1451
- errors[path3] = `${field.label} h\xF6chstens ${field.maxLength} Zeichen`;
1359
+ errors[path] = `${field.label} h\xF6chstens ${field.maxLength} Zeichen`;
1452
1360
  } else if (field.enum && value.length > 0 && !field.enum.includes(value)) {
1453
- errors[path3] = `${field.label}: Wert nicht in der Auswahl`;
1361
+ errors[path] = `${field.label}: Wert nicht in der Auswahl`;
1454
1362
  }
1455
1363
  }
1456
1364
  break;
1457
1365
  }
1458
1366
  case "number": {
1459
1367
  if (value === "" || value === void 0 || value === null) {
1460
- if (field.required) errors[path3] = `${field.label} ist erforderlich`;
1368
+ if (field.required) errors[path] = `${field.label} ist erforderlich`;
1461
1369
  break;
1462
1370
  }
1463
1371
  const n = typeof value === "number" ? value : Number(value);
1464
1372
  if (!Number.isFinite(n)) {
1465
- errors[path3] = `${field.label} muss eine Zahl sein`;
1373
+ errors[path] = `${field.label} muss eine Zahl sein`;
1466
1374
  } else if (field.integer && !Number.isInteger(n)) {
1467
- errors[path3] = `${field.label} muss eine ganze Zahl sein`;
1375
+ errors[path] = `${field.label} muss eine ganze Zahl sein`;
1468
1376
  } else if (field.minimum !== void 0 && n < field.minimum) {
1469
- errors[path3] = `${field.label} >= ${field.minimum}`;
1377
+ errors[path] = `${field.label} >= ${field.minimum}`;
1470
1378
  } else if (field.maximum !== void 0 && n > field.maximum) {
1471
- errors[path3] = `${field.label} <= ${field.maximum}`;
1379
+ errors[path] = `${field.label} <= ${field.maximum}`;
1472
1380
  }
1473
1381
  break;
1474
1382
  }
1475
1383
  case "boolean":
1476
1384
  if (field.required && value !== true) {
1477
- errors[path3] = `${field.label} muss aktiviert sein`;
1385
+ errors[path] = `${field.label} muss aktiviert sein`;
1478
1386
  }
1479
1387
  break;
1480
1388
  case "array": {
1481
1389
  const arr = Array.isArray(value) ? value : [];
1482
1390
  if (field.required && arr.length === 0) {
1483
- errors[path3] = `${field.label}: mindestens ein Eintrag erforderlich`;
1391
+ errors[path] = `${field.label}: mindestens ein Eintrag erforderlich`;
1484
1392
  }
1485
1393
  if (field.minItems !== void 0 && arr.length < field.minItems) {
1486
- errors[path3] = `${field.label}: mindestens ${field.minItems} Eintr\xE4ge`;
1394
+ errors[path] = `${field.label}: mindestens ${field.minItems} Eintr\xE4ge`;
1487
1395
  } else if (field.maxItems !== void 0 && arr.length > field.maxItems) {
1488
- errors[path3] = `${field.label}: h\xF6chstens ${field.maxItems} Eintr\xE4ge`;
1396
+ errors[path] = `${field.label}: h\xF6chstens ${field.maxItems} Eintr\xE4ge`;
1489
1397
  }
1490
1398
  if (field.itemField) {
1491
1399
  arr.forEach((item, i) => {
1492
1400
  const sub = validateField(
1493
1401
  field.itemField,
1494
1402
  item,
1495
- `${path3}[${i}]`
1403
+ `${path}[${i}]`
1496
1404
  );
1497
1405
  Object.assign(errors, sub);
1498
1406
  });
@@ -1502,7 +1410,7 @@ function validateField(field, value, path3) {
1502
1410
  case "object": {
1503
1411
  const obj = isPlainObject5(value) ? value : {};
1504
1412
  for (const sub of field.fields) {
1505
- const subErrors = validateField(sub, obj[sub.name], `${path3}.${sub.name}`);
1413
+ const subErrors = validateField(sub, obj[sub.name], `${path}.${sub.name}`);
1506
1414
  Object.assign(errors, subErrors);
1507
1415
  }
1508
1416
  break;
@@ -2503,71 +2411,8 @@ var FORGE_TEMPLATES = [
2503
2411
  asset_slots: []
2504
2412
  }
2505
2413
  ];
2506
- var ALLOWED_BLUEPRINT_FILENAMES = /* @__PURE__ */ new Set(["blueprint.json", "snapshot.json"]);
2507
- function isAllowedBlueprintPath(targetPath, filePath) {
2508
- const resolvedTarget = resolve(targetPath);
2509
- const resolvedFile = resolve(filePath);
2510
- const allowedPrefix = join(resolvedTarget, ".prism", "blueprint");
2511
- if (!resolvedFile.startsWith(allowedPrefix + "/") && resolvedFile !== allowedPrefix) {
2512
- return false;
2513
- }
2514
- const basename = resolvedFile.slice(resolvedFile.lastIndexOf("/") + 1);
2515
- return ALLOWED_BLUEPRINT_FILENAMES.has(basename);
2516
- }
2517
- function readBlueprintFromTarget(targetPath) {
2518
- const candidates = [
2519
- join(targetPath, ".prism", "blueprint", "snapshot.json"),
2520
- join(targetPath, ".prism", "blueprint.json")
2521
- ];
2522
- for (const candidate of candidates) {
2523
- const normalized = normalize(candidate);
2524
- if (!isAllowedBlueprintPath(targetPath, normalized)) continue;
2525
- if (!existsSync(normalized)) continue;
2526
- try {
2527
- const raw = readFileSync(normalized, "utf-8");
2528
- return JSON.parse(raw);
2529
- } catch {
2530
- return null;
2531
- }
2532
- }
2533
- return null;
2534
- }
2535
- function zoneId(filePath) {
2536
- const parts = filePath.replace(/^\//, "").split("/");
2537
- return parts[0] || "root";
2538
- }
2539
- function extractZones(blueprint) {
2540
- const zoneMap = /* @__PURE__ */ new Map();
2541
- for (const file of blueprint.files) {
2542
- const id = zoneId(file.path);
2543
- if (!zoneMap.has(id)) zoneMap.set(id, { files: [], heat: 0 });
2544
- const z = zoneMap.get(id);
2545
- z.files.push(file.path);
2546
- z.heat += (file.importedByCount ?? 0) + (file.importCount ?? 0);
2547
- }
2548
- return Array.from(zoneMap.entries()).map(([id, { files, heat }]) => ({
2549
- id,
2550
- name: id,
2551
- files,
2552
- fileCount: files.length,
2553
- heat
2554
- })).sort((a, b) => b.heat - a.heat || b.fileCount - a.fileCount);
2555
- }
2556
- function toFileEntry(f) {
2557
- return {
2558
- path: f.path,
2559
- importCount: f.importCount ?? 0,
2560
- importedByCount: f.importedByCount ?? 0,
2561
- lineCount: f.lineCount ?? 0,
2562
- zone: zoneId(f.path)
2563
- };
2564
- }
2565
- function extractTopChurnFiles(blueprint, n = 10) {
2566
- return blueprint.files.map(toFileEntry).sort((a, b) => b.importedByCount - a.importedByCount || b.lineCount - a.lineCount).slice(0, n);
2567
- }
2568
- function extractDependencyHotspots(blueprint, n = 10) {
2569
- return blueprint.files.map(toFileEntry).sort((a, b) => b.importCount - a.importCount || b.importedByCount - a.importedByCount).slice(0, n);
2570
- }
2414
+
2415
+ // src/forge/secrets.ts
2571
2416
  var SECRET_PATTERNS = [
2572
2417
  /sk-ant-api03-[A-Za-z0-9_-]{80,}/,
2573
2418
  /sk-proj-[A-Za-z0-9_-]{40,}/,
@@ -2577,42 +2422,8 @@ var SECRET_PATTERNS = [
2577
2422
  function scanForSecrets(text) {
2578
2423
  return SECRET_PATTERNS.some((re) => re.test(text));
2579
2424
  }
2580
- var MAX_SUMMARY_CHARS = 2e3;
2581
- function deriveContextSummary(blueprint) {
2582
- const zones = extractZones(blueprint).slice(0, 8);
2583
- const churn = extractTopChurnFiles(blueprint, 5);
2584
- const deps = extractDependencyHotspots(blueprint, 5);
2585
- const scanAge = blueprint.scanTimestamp ? (() => {
2586
- const ageMs = Date.now() - blueprint.scanTimestamp * 1e3;
2587
- const ageMin = Math.round(ageMs / 6e4);
2588
- if (ageMin < 60) return `${ageMin}m ago`;
2589
- if (ageMin < 1440) return `${Math.round(ageMin / 60)}h ago`;
2590
- return `${Math.round(ageMin / 1440)}d ago`;
2591
- })() : "unknown";
2592
- const lines = [
2593
- `Blueprint snapshot (scanned ${scanAge}):`,
2594
- `Total files: ${blueprint.stats?.totalFiles ?? blueprint.files.length} | app:${blueprint.categories?.app ?? 0} component:${blueprint.categories?.component ?? 0} lib:${blueprint.categories?.lib ?? 0} hook:${blueprint.categories?.hook ?? 0}`,
2595
- "",
2596
- "Top zones (by activity):",
2597
- ...zones.map((z) => ` ${z.name}: ${z.fileCount} files, heat ${z.heat}`),
2598
- "",
2599
- "Hottest files (most imported by others):",
2600
- ...churn.map((f) => ` ${f.path} (importedBy:${f.importedByCount})`),
2601
- "",
2602
- "Most dependency-heavy files:",
2603
- ...deps.map((f) => ` ${f.path} (imports:${f.importCount})`)
2604
- ];
2605
- let summary = lines.join("\n");
2606
- if (summary.length > MAX_SUMMARY_CHARS) {
2607
- summary = summary.slice(0, MAX_SUMMARY_CHARS - 3) + "...";
2608
- }
2609
- if (scanForSecrets(summary)) {
2610
- throw new Error("Blueprint context summary contains unexpected secret-pattern match. Refusing to pass to LLM.");
2611
- }
2612
- return summary;
2613
- }
2614
2425
 
2615
- // src/forge/prismContext.ts
2426
+ // src/forge/prismContext.data.ts
2616
2427
  var PRISM_TEMPLATE_RELEASE_ANNOUNCEMENT = {
2617
2428
  id: "release-announcement",
2618
2429
  name: "Release Announcement",
@@ -2664,104 +2475,6 @@ var PRISM_TEMPLATES = [
2664
2475
  function getPrismTemplate(id) {
2665
2476
  return PRISM_TEMPLATES.find((t) => t.id === id);
2666
2477
  }
2667
- function releaseContextBlock(blueprint) {
2668
- const churn = extractTopChurnFiles(blueprint, 8);
2669
- const zones = extractZones(blueprint).slice(0, 6);
2670
- return [
2671
- "Recent activity (most active files by coupling):",
2672
- ...churn.map((f) => ` ${f.path} \u2014 importedBy:${f.importedByCount}`),
2673
- "",
2674
- "Most active zones:",
2675
- ...zones.map((z) => ` ${z.name}: ${z.fileCount} files, activity score ${z.heat}`)
2676
- ].join("\n");
2677
- }
2678
- function changelogContextBlock(blueprint) {
2679
- const zones = extractZones(blueprint).slice(0, 10);
2680
- const hotspots = extractDependencyHotspots(blueprint, 6);
2681
- return [
2682
- "Zone breakdown:",
2683
- ...zones.map((z) => ` ${z.name}: ${z.fileCount} files`),
2684
- "",
2685
- "High-coupling files (refactoring targets):",
2686
- ...hotspots.map((f) => ` ${f.path} \u2014 imports ${f.importCount} modules`)
2687
- ].join("\n");
2688
- }
2689
- function deepdiveContextBlock(blueprint) {
2690
- return deriveContextSummary(blueprint);
2691
- }
2692
- function zoneContextBlock(blueprint, zoneName) {
2693
- const allZones = extractZones(blueprint);
2694
- const zone = allZones.find((z) => z.id === zoneName || z.name === zoneName);
2695
- if (!zone) {
2696
- return `Zone "${zoneName}" not found. Available zones: ${allZones.map((z) => z.name).join(", ")}`;
2697
- }
2698
- const topFiles = zone.files.slice(0, 12);
2699
- const otherCount = Math.max(0, zone.fileCount - 12);
2700
- return [
2701
- `Zone: ${zone.name} (${zone.fileCount} files, heat score ${zone.heat})`,
2702
- "Files:",
2703
- ...topFiles.map((f) => ` ${f}`),
2704
- ...otherCount > 0 ? [` ... and ${otherCount} more`] : []
2705
- ].join("\n");
2706
- }
2707
- function moduleContextBlock(blueprint, modulePath) {
2708
- const file = blueprint.files.find((f) => f.path.includes(modulePath));
2709
- if (!file) {
2710
- return `Module path "${modulePath}" not found in blueprint.`;
2711
- }
2712
- const deps = extractDependencyHotspots(blueprint, 5);
2713
- return [
2714
- `Module: ${file.path}`,
2715
- ` importCount: ${file.importCount ?? 0}`,
2716
- ` importedByCount: ${file.importedByCount ?? 0}`,
2717
- ` lineCount: ${file.lineCount ?? 0}`,
2718
- "",
2719
- "Related high-activity files:",
2720
- ...deps.filter((d) => d.zone === (file.path.split("/")[0] || "root")).slice(0, 5).map((d) => ` ${d.path}`)
2721
- ].join("\n");
2722
- }
2723
- function buildPrismContextPrompt(blueprint, focus, highlight) {
2724
- const resolvedFocus = focus ?? "summary";
2725
- let contextBlock;
2726
- let systemFragment;
2727
- let suggestedAsk;
2728
- if (resolvedFocus === "release") {
2729
- contextBlock = releaseContextBlock(blueprint);
2730
- systemFragment = "You have access to a real codebase blueprint showing which files and zones saw the most recent activity. Use this to make the release announcement concrete \u2014 reference specific zone names and file roles.";
2731
- suggestedAsk = PRISM_TEMPLATE_RELEASE_ANNOUNCEMENT.suggestedAsk;
2732
- } else if (resolvedFocus === "changelog") {
2733
- contextBlock = changelogContextBlock(blueprint);
2734
- systemFragment = "You have access to a real codebase blueprint showing zone structure and dependency coupling. Use this to make the changelog specific and credible.";
2735
- suggestedAsk = PRISM_TEMPLATE_SHIPPING_DIGEST.suggestedAsk;
2736
- } else if (resolvedFocus === "deepdive") {
2737
- contextBlock = deepdiveContextBlock(blueprint);
2738
- systemFragment = "You have access to a complete blueprint of a real codebase. Use the zone names, file counts, and coupling metrics to write a concrete, non-generic technical explanation.";
2739
- suggestedAsk = PRISM_TEMPLATE_ARCHITECTURE_OVERVIEW.suggestedAsk;
2740
- } else if (resolvedFocus.startsWith("zone:")) {
2741
- const zoneName = resolvedFocus.slice(5);
2742
- contextBlock = zoneContextBlock(blueprint, zoneName);
2743
- systemFragment = `You have access to real file data for the "${zoneName}" zone of the codebase. Use specific file names and counts.`;
2744
- suggestedAsk = PRISM_TEMPLATE_ZONE_DEEPDIVE.suggestedAsk.replace(
2745
- "this codebase zone",
2746
- `the "${zoneName}" zone`
2747
- );
2748
- } else if (resolvedFocus.startsWith("module:")) {
2749
- const modulePath = resolvedFocus.slice(7);
2750
- contextBlock = moduleContextBlock(blueprint, modulePath);
2751
- systemFragment = `You have access to dependency data for the "${modulePath}" module. Reference specific metrics.`;
2752
- suggestedAsk = `Explain the role of ${modulePath} in the codebase architecture and why it matters.`;
2753
- } else {
2754
- contextBlock = deriveContextSummary(blueprint);
2755
- systemFragment = "You have access to a real codebase blueprint. Use specific zone names and file counts to make your content concrete and credible.";
2756
- suggestedAsk = "Summarize the structure and key areas of this codebase.";
2757
- }
2758
- if (highlight) {
2759
- contextBlock += `
2760
-
2761
- User wants to highlight: ${highlight}`;
2762
- }
2763
- return { systemFragment, contextBlock, suggestedAsk };
2764
- }
2765
2478
 
2766
2479
  // src/forge/channel.ts
2767
2480
  var DISPATCH_CHANNEL_TWEET = {
@@ -3240,4 +2953,4 @@ function previewExport(entries, format) {
3240
2953
  }
3241
2954
  }
3242
2955
 
3243
- export { ANIMATION_DURATION_PRESETS, BRAND_CONTENT_SLOT_KEYS, BUNDLED_DISPATCH_CHANNELS, BUNDLED_STYLE_PRESETS, BUNDLED_WIDGET_TEMPLATES, DEFAULT_ANIMATION_DURATION_SECONDS, DEFAULT_BRAND_KIT_FONTS, DEFAULT_BRAND_KIT_PALETTE, DEFAULT_BRAND_KIT_VOICE, DISPATCH_CHANNEL_BLOG, DISPATCH_CHANNEL_EMAIL, DISPATCH_CHANNEL_HN, DISPATCH_CHANNEL_INSTAGRAM, DISPATCH_CHANNEL_LINKEDIN, DISPATCH_CHANNEL_NEWSLETTER, DISPATCH_CHANNEL_REDDIT, DISPATCH_CHANNEL_SLACK, DISPATCH_CHANNEL_TWEET, FORGE_AUDIENCES, FORGE_BRAND_THEME_ID, FORGE_TEMPLATES, FREE_TIER_WIDGET_IDS, MAX_ANIMATION_DURATION_SECONDS, MIN_ANIMATION_DURATION_SECONDS, PRISM_TEMPLATES, PRISM_TEMPLATE_ARCHITECTURE_OVERVIEW, PRISM_TEMPLATE_REFACTOR_RATIONALE, PRISM_TEMPLATE_RELEASE_ANNOUNCEMENT, PRISM_TEMPLATE_SHIPPING_DIGEST, PRISM_TEMPLATE_ZONE_DEEPDIVE, REFINE_COUNTDOWN_THRESHOLD, REFINE_SESSION_SOFT_CAP, REFINE_SUGGESTIONS, STYLE_PRESET_BRUTALIST, STYLE_PRESET_DEFAULT, STYLE_PRESET_GLASSY, STYLE_PRESET_MINIMAL, TEMPLATE_SCHEMA_EXAMPLES, TEMPLATE_SCHEMA_GENERIC, WIDGET_TEMPLATE_CHANGELOG_ROW, WIDGET_TEMPLATE_CTA_BANNER, WIDGET_TEMPLATE_FEATURE_GRID, WIDGET_TEMPLATE_METRIC_BADGE, WIDGET_TEMPLATE_PRICING_TIER, WIDGET_TEMPLATE_SOCIAL_PROOF, WIDGET_TEMPLATE_STAT_CARD, WIDGET_TEMPLATE_TESTIMONIAL, applyEntryPatch, asAudienceId, assembleBrandUrlExtractionPrompt, assembleForgePrompt, brandThemeConfigToEntry, buildPrismContextPrompt, buildRevertVersion, buildScheduledEntry, buildVersion, cascadingScheduledFor, clampAnimationDuration, computeDiff, defaultBrandKit, defaultValueForField, deriveContextSummary, distill, entryInRange, exportToBufferCsv, exportToHypefuryCsv, exportToICalendar, extractBrandFromPrismBlueprint, extractDependencyHotspots, extractTopChurnFiles, extractZones, generateArchitectureWalkthrough, generateAskDrivenAsset, generateChangesSince, generateOnboardingDoc, generateRefactoringReport, generateReleaseNotes, getDispatchChannel, getPrismTemplate, getSlotValue, getStyleById, getWidgetTemplate, initialFormValues, next7DaysRange, nextVersionNumber, orchestrateDispatch, parseAndValidateSchemaDefinition, parseBrandKitFromLlmResponse, parseBrandThemeContent, parseStyleFromCss, parseStyleFromTailwindConfig, parseStyleFromTokensJson, parseThemeConfigContent, previewExport, readBlueprintData, readBlueprintFromTarget, readPrismDirectory, refineAsset, refineLimitState, renderWidget, resolveAnimatedChoice, resolveAnimationDuration, resolveBrandPalette, runForgeGeneration, scanForSecrets, schemaExampleFor, schemaToForm, templateAnimatedDefault, themeEntryToPalette, tryParseJsonObject, validateAgainstTemplateSchema, validateAssetSlots, validateFormValues, validateSchemaDefinition };
2956
+ export { ANIMATION_DURATION_PRESETS, BRAND_CONTENT_SLOT_KEYS, BUNDLED_DISPATCH_CHANNELS, BUNDLED_STYLE_PRESETS, BUNDLED_WIDGET_TEMPLATES, DEFAULT_ANIMATION_DURATION_SECONDS, DEFAULT_BRAND_KIT_FONTS, DEFAULT_BRAND_KIT_PALETTE, DEFAULT_BRAND_KIT_VOICE, DISPATCH_CHANNEL_BLOG, DISPATCH_CHANNEL_EMAIL, DISPATCH_CHANNEL_HN, DISPATCH_CHANNEL_INSTAGRAM, DISPATCH_CHANNEL_LINKEDIN, DISPATCH_CHANNEL_NEWSLETTER, DISPATCH_CHANNEL_REDDIT, DISPATCH_CHANNEL_SLACK, DISPATCH_CHANNEL_TWEET, FORGE_AUDIENCES, FORGE_BRAND_THEME_ID, FORGE_TEMPLATES, FREE_TIER_WIDGET_IDS, MAX_ANIMATION_DURATION_SECONDS, MIN_ANIMATION_DURATION_SECONDS, PRISM_TEMPLATES, PRISM_TEMPLATE_ARCHITECTURE_OVERVIEW, PRISM_TEMPLATE_REFACTOR_RATIONALE, PRISM_TEMPLATE_RELEASE_ANNOUNCEMENT, PRISM_TEMPLATE_SHIPPING_DIGEST, PRISM_TEMPLATE_ZONE_DEEPDIVE, REFINE_COUNTDOWN_THRESHOLD, REFINE_SESSION_SOFT_CAP, REFINE_SUGGESTIONS, STYLE_PRESET_BRUTALIST, STYLE_PRESET_DEFAULT, STYLE_PRESET_GLASSY, STYLE_PRESET_MINIMAL, TEMPLATE_SCHEMA_EXAMPLES, TEMPLATE_SCHEMA_GENERIC, WIDGET_TEMPLATE_CHANGELOG_ROW, WIDGET_TEMPLATE_CTA_BANNER, WIDGET_TEMPLATE_FEATURE_GRID, WIDGET_TEMPLATE_METRIC_BADGE, WIDGET_TEMPLATE_PRICING_TIER, WIDGET_TEMPLATE_SOCIAL_PROOF, WIDGET_TEMPLATE_STAT_CARD, WIDGET_TEMPLATE_TESTIMONIAL, applyEntryPatch, asAudienceId, assembleBrandUrlExtractionPrompt, assembleForgePrompt, brandThemeConfigToEntry, buildRevertVersion, buildScheduledEntry, buildVersion, cascadingScheduledFor, clampAnimationDuration, computeDiff, defaultBrandKit, defaultValueForField, distill, entryInRange, exportToBufferCsv, exportToHypefuryCsv, exportToICalendar, generateArchitectureWalkthrough, generateAskDrivenAsset, generateChangesSince, generateOnboardingDoc, generateRefactoringReport, generateReleaseNotes, getDispatchChannel, getPrismTemplate, getSlotValue, getStyleById, getWidgetTemplate, initialFormValues, next7DaysRange, nextVersionNumber, orchestrateDispatch, parseAndValidateSchemaDefinition, parseBrandKitFromLlmResponse, parseBrandThemeContent, parseStyleFromCss, parseStyleFromTailwindConfig, parseStyleFromTokensJson, parseThemeConfigContent, previewExport, refineAsset, refineLimitState, renderWidget, resolveAnimatedChoice, resolveAnimationDuration, resolveBrandPalette, runForgeGeneration, scanForSecrets, schemaExampleFor, schemaToForm, templateAnimatedDefault, themeEntryToPalette, tryParseJsonObject, validateAgainstTemplateSchema, validateAssetSlots, validateFormValues, validateSchemaDefinition };