@productbrain/mcp 0.0.1-beta.75 → 0.0.1-beta.77

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.
@@ -1227,6 +1227,19 @@ function withEnvelope(handler) {
1227
1227
  };
1228
1228
  }
1229
1229
 
1230
+ // src/lib/fieldTypes.ts
1231
+ var FIELD_TYPE_DEFAULTS = {
1232
+ "string": "",
1233
+ "text": "",
1234
+ "rich-text": "",
1235
+ "number": null,
1236
+ "boolean": false,
1237
+ "select": null,
1238
+ "multi-select": [],
1239
+ "array": [],
1240
+ "json": null
1241
+ };
1242
+
1230
1243
  // src/tools/smart-capture-routing.ts
1231
1244
  var STARTER_COLLECTIONS = CLASSIFIABLE_COLLECTIONS;
1232
1245
 
@@ -2123,7 +2136,17 @@ var captureSuccessOutputSchema = z2.object({
2123
2136
  qualityScore: z2.number(),
2124
2137
  qualityVerdict: z2.record(z2.unknown()).optional(),
2125
2138
  classifier: captureClassifierSchema.optional(),
2126
- studioUrl: z2.string().optional()
2139
+ studioUrl: z2.string().optional(),
2140
+ warnings: z2.array(z2.string()).optional(),
2141
+ normalization: z2.object({
2142
+ remapped: z2.record(z2.string()).optional(),
2143
+ rejected: z2.array(z2.string()).optional()
2144
+ }).optional(),
2145
+ expectedFields: z2.array(z2.object({
2146
+ key: z2.string(),
2147
+ type: z2.string(),
2148
+ required: z2.boolean().optional()
2149
+ })).optional()
2127
2150
  }).strict();
2128
2151
  var captureClassifierOnlyOutputSchema = z2.object({
2129
2152
  classifier: captureClassifierSchema
@@ -2140,7 +2163,12 @@ var batchCaptureOutputSchema = z2.object({
2140
2163
  status: z2.enum(["draft", "committed", "proposed"]),
2141
2164
  classifiedBy: z2.enum(["llm", "heuristic", "explicit"]).optional(),
2142
2165
  confidence: z2.number().optional(),
2143
- confidenceTier: z2.enum(["high", "medium", "low"]).optional()
2166
+ confidenceTier: z2.enum(["high", "medium", "low"]).optional(),
2167
+ warnings: z2.array(z2.string()).optional(),
2168
+ normalization: z2.object({
2169
+ remapped: z2.record(z2.string()).optional(),
2170
+ rejected: z2.array(z2.string()).optional()
2171
+ }).optional()
2144
2172
  })),
2145
2173
  total: z2.number(),
2146
2174
  failed: z2.number(),
@@ -2169,6 +2197,17 @@ var batchCaptureOutputSchema = z2.object({
2169
2197
  function shouldAutoCommitCapture(autoCommit, governanceMode) {
2170
2198
  return autoCommit === true || autoCommit === void 0 && governanceMode === "open";
2171
2199
  }
2200
+ function buildDataFromFields(fields, descriptionField, descriptionValue) {
2201
+ const data = {};
2202
+ for (const field of fields) {
2203
+ if (field.key === descriptionField) {
2204
+ data[field.key] = descriptionValue;
2205
+ } else {
2206
+ data[field.key] = FIELD_TYPE_DEFAULTS[field.type] ?? null;
2207
+ }
2208
+ }
2209
+ return data;
2210
+ }
2172
2211
  function registerSmartCaptureTools(server) {
2173
2212
  const captureTool = server.registerTool(
2174
2213
  "capture",
@@ -2230,19 +2269,8 @@ Or use \`collections action=list\` to see available collections.`
2230
2269
  )
2231
2270
  };
2232
2271
  }
2233
- const data = {};
2272
+ const data = buildDataFromFields(col.fields ?? [], profile.descriptionField, description);
2234
2273
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
2235
- for (const field of col.fields ?? []) {
2236
- const key = field.key;
2237
- if (key === profile.descriptionField) {
2238
- data[key] = description;
2239
- } else if (field.type === "array" || field.type === "multi-select") {
2240
- data[key] = [];
2241
- } else if (field.type === "select") {
2242
- } else {
2243
- data[key] = "";
2244
- }
2245
- }
2246
2274
  for (const def of profile.defaults) {
2247
2275
  if (def.value === "today") {
2248
2276
  data[def.key] = today;
@@ -2287,10 +2315,43 @@ Or use \`collections action=list\` to see available collections.`
2287
2315
  }
2288
2316
  data.links = betLinks;
2289
2317
  }
2318
+ const E2_LLM_REMAP_ENABLED = false;
2319
+ const payloadForPreview = E2_LLM_REMAP_ENABLED && userData && typeof userData === "object" ? { ...data } : null;
2320
+ if (payloadForPreview) {
2321
+ try {
2322
+ const preview = await mcpCall(
2323
+ "chain.normalizeEntryDataPreview",
2324
+ { collectionSlug: resolvedCollection, data: payloadForPreview }
2325
+ );
2326
+ const rejected = (preview?.rejected ?? []).filter((k) => k !== "name");
2327
+ if (rejected.length > 0) {
2328
+ const llmResult = await mcpCall(
2329
+ "chain.normalizeEntryDataLLM",
2330
+ {
2331
+ collectionSlug: resolvedCollection,
2332
+ unknownKeys: rejected,
2333
+ data: payloadForPreview
2334
+ }
2335
+ );
2336
+ if (llmResult && Object.keys(llmResult.remapped).length > 0) {
2337
+ const fieldKeySet = new Set((col.fields ?? []).map((f) => f.key));
2338
+ for (const [oldKey, newKey] of Object.entries(llmResult.remapped)) {
2339
+ if (data[oldKey] !== void 0 && !fieldKeySet.has(oldKey)) {
2340
+ data[newKey] = data[oldKey];
2341
+ delete data[oldKey];
2342
+ }
2343
+ }
2344
+ }
2345
+ }
2346
+ } catch {
2347
+ }
2348
+ }
2290
2349
  const status = "draft";
2291
2350
  const agentId = getAgentSessionId();
2292
2351
  let finalEntryId;
2293
2352
  let internalId;
2353
+ let entryWarnings = [];
2354
+ let normalizationMeta;
2294
2355
  try {
2295
2356
  const result = await mcpMutation("chain.createEntry", {
2296
2357
  collectionSlug: resolvedCollection,
@@ -2304,6 +2365,8 @@ Or use \`collections action=list\` to see available collections.`
2304
2365
  });
2305
2366
  internalId = result.docId;
2306
2367
  finalEntryId = result.entryId;
2368
+ entryWarnings = result.warnings ?? [];
2369
+ normalizationMeta = result.normalization;
2307
2370
  resolveGapsForEntry(name, result.entryId);
2308
2371
  } catch (error) {
2309
2372
  const msg = error instanceof Error ? error.message : String(error);
@@ -2333,6 +2396,7 @@ Use \`entries action=get\` to inspect the existing entry, or \`update-entry\` to
2333
2396
  const linksCreated = [];
2334
2397
  const linksSuggested = [];
2335
2398
  const userLinkResults = [];
2399
+ const pendingRelations = [];
2336
2400
  const skipAutoDiscovery = links && links.length > 0;
2337
2401
  const searchQuery = extractSearchTerms(name, description);
2338
2402
  if (searchQuery && !skipAutoDiscovery) {
@@ -2351,63 +2415,95 @@ Use \`entries action=get\` to inspect the existing entry, or \`update-entry\` to
2351
2415
  confidenceReason: conf.reason
2352
2416
  };
2353
2417
  }).sort((a, b) => b.confidence - a.confidence);
2418
+ let autoCount = 0;
2354
2419
  for (const c of candidates) {
2355
- if (linksCreated.length >= MAX_AUTO_LINKS) break;
2420
+ if (autoCount >= MAX_AUTO_LINKS) break;
2356
2421
  if (c.confidence < AUTO_LINK_CONFIDENCE_THRESHOLD) break;
2357
2422
  if (!c.entryId || !finalEntryId) continue;
2358
2423
  const { type: relationType, reason: relationReason } = inferRelationType(resolvedCollection, c.collSlug, profile);
2359
- try {
2360
- await mcpMutation("chain.createEntryRelation", {
2361
- fromEntryId: finalEntryId,
2362
- toEntryId: c.entryId,
2363
- type: relationType,
2364
- sessionId: agentId ?? void 0
2365
- });
2366
- linksCreated.push({
2367
- targetEntryId: c.entryId,
2424
+ pendingRelations.push({
2425
+ fromEntryId: finalEntryId,
2426
+ toEntryId: c.entryId,
2427
+ type: relationType,
2428
+ meta: {
2429
+ source: "auto",
2368
2430
  targetName: c.name,
2369
2431
  targetCollection: c.collSlug,
2370
- relationType,
2371
2432
  linkReason: `confidence ${c.confidence} (${c.confidenceReason}) + ${relationReason}`
2372
- });
2373
- } catch {
2374
- }
2433
+ }
2434
+ });
2435
+ autoCount++;
2375
2436
  }
2376
- const linkedIds = new Set(linksCreated.map((l) => l.targetEntryId));
2437
+ const autoTargetIds = new Set(pendingRelations.map((r) => r.toEntryId));
2377
2438
  for (const c of candidates) {
2378
2439
  if (linksSuggested.length >= MAX_SUGGESTIONS) break;
2379
- if (linkedIds.has(c.entryId)) continue;
2440
+ if (autoTargetIds.has(c.entryId)) continue;
2380
2441
  if (c.confidence < 10) continue;
2381
2442
  const preview = extractPreview(c.data, 80);
2382
2443
  const reason = c.confidence >= AUTO_LINK_CONFIDENCE_THRESHOLD ? "high relevance (already linked)" : `"${c.name.toLowerCase().split(/\s+/).filter((w) => `${name} ${description}`.toLowerCase().includes(w) && w.length > 3).slice(0, 2).join('", "')}" appears in content`;
2383
- linksSuggested.push({
2384
- entryId: c.entryId,
2385
- name: c.name,
2386
- collection: c.collSlug,
2387
- reason,
2388
- preview
2389
- });
2444
+ linksSuggested.push({ entryId: c.entryId, name: c.name, collection: c.collSlug, reason, preview });
2390
2445
  }
2391
2446
  }
2392
2447
  if (links && links.length > 0 && finalEntryId) {
2393
2448
  for (const link of links) {
2394
- try {
2395
- await mcpMutation("chain.createEntryRelation", {
2396
- fromEntryId: finalEntryId,
2397
- toEntryId: link.to,
2398
- type: link.type,
2399
- sessionId: agentId ?? void 0
2400
- });
2401
- userLinkResults.push({ label: `\u2713 ${link.type} \u2192 ${link.to}`, ok: true });
2402
- linksCreated.push({
2403
- targetEntryId: link.to,
2404
- targetName: link.to,
2405
- targetCollection: "unknown",
2406
- relationType: link.type
2407
- });
2408
- } catch (e) {
2409
- const msg = e instanceof Error ? e.message : "failed";
2410
- userLinkResults.push({ label: `\u2717 ${link.type} \u2192 ${link.to}: ${msg}`, ok: false });
2449
+ pendingRelations.push({
2450
+ fromEntryId: finalEntryId,
2451
+ toEntryId: link.to,
2452
+ type: link.type,
2453
+ meta: { source: "user", targetName: link.to, targetCollection: "unknown" }
2454
+ });
2455
+ }
2456
+ }
2457
+ const resolvedCK = canonicalKey;
2458
+ const batchRelationsPromise = pendingRelations.length > 0 ? mcpMutation(
2459
+ "chain.createEntryRelations",
2460
+ {
2461
+ relations: pendingRelations.slice(0, 25).map((r) => ({ fromEntryId: r.fromEntryId, toEntryId: r.toEntryId, type: r.type })),
2462
+ sessionId: agentId ?? void 0
2463
+ }
2464
+ ).catch((err) => {
2465
+ entryWarnings.push(`Auto-linking partially failed: ${err instanceof Error ? err.message : "unknown error"}`);
2466
+ return null;
2467
+ }) : Promise.resolve(null);
2468
+ const cardinalityPromise = resolvedCK ? mcpQuery("chain.checkCardinalityWarning", { canonicalKey: resolvedCK }).catch(() => null) : Promise.resolve(null);
2469
+ const contradictionPromise = runContradictionCheck(name, description);
2470
+ const coachingPromise = mcpMutation("quality.evaluateHeuristicAndSchedule", {
2471
+ entryId: finalEntryId,
2472
+ context: "capture"
2473
+ }).catch(() => null);
2474
+ const [batchResult, cardinalityCheck, contradictionWarnings, verdictResult] = await Promise.all([
2475
+ batchRelationsPromise,
2476
+ cardinalityPromise,
2477
+ contradictionPromise,
2478
+ coachingPromise
2479
+ ]);
2480
+ if (batchResult) {
2481
+ for (let i = 0; i < pendingRelations.length; i++) {
2482
+ const pending = pendingRelations[i];
2483
+ const result = batchResult.results[i];
2484
+ if (!result) continue;
2485
+ if (pending.meta.source === "auto") {
2486
+ if (result.ok) {
2487
+ linksCreated.push({
2488
+ targetEntryId: pending.toEntryId,
2489
+ targetName: pending.meta.targetName,
2490
+ targetCollection: pending.meta.targetCollection,
2491
+ relationType: pending.type,
2492
+ linkReason: pending.meta.linkReason
2493
+ });
2494
+ }
2495
+ } else {
2496
+ if (result.ok) {
2497
+ userLinkResults.push({ label: `\u2713 ${pending.type} \u2192 ${pending.toEntryId}`, ok: true });
2498
+ linksCreated.push({
2499
+ targetEntryId: pending.toEntryId,
2500
+ targetName: pending.meta.targetName,
2501
+ targetCollection: pending.meta.targetCollection,
2502
+ relationType: pending.type
2503
+ });
2504
+ } else {
2505
+ userLinkResults.push({ label: `\u2717 ${pending.type} \u2192 ${pending.toEntryId}: ${result.error ?? "failed"}`, ok: false });
2506
+ }
2411
2507
  }
2412
2508
  }
2413
2509
  }
@@ -2424,34 +2520,13 @@ Use \`entries action=get\` to inspect the existing entry, or \`update-entry\` to
2424
2520
  collectionFields: col.fields ?? []
2425
2521
  };
2426
2522
  const quality = scoreQuality(captureCtx, profile);
2427
- let cardinalityWarning = null;
2428
- const resolvedCK = canonicalKey ?? captureCtx.canonicalKey;
2429
- if (resolvedCK) {
2430
- try {
2431
- const check = await mcpQuery("chain.checkCardinalityWarning", {
2432
- canonicalKey: resolvedCK
2433
- });
2434
- if (check?.warning) {
2435
- cardinalityWarning = check.warning;
2436
- }
2437
- } catch {
2438
- }
2439
- }
2440
- const contradictionWarnings = await runContradictionCheck(name, description);
2523
+ const cardinalityWarning = cardinalityCheck?.warning ?? null;
2441
2524
  if (contradictionWarnings.length > 0) {
2442
2525
  await recordSessionActivity({ contradictionWarning: true });
2443
2526
  }
2444
2527
  let coachingSection = "";
2445
- let verdictResult = null;
2446
- try {
2447
- verdictResult = await mcpMutation("quality.evaluateHeuristicAndSchedule", {
2448
- entryId: finalEntryId,
2449
- context: "capture"
2450
- });
2451
- if (verdictResult?.verdict && verdictResult.verdict.tier !== "passive" && verdictResult.verdict.criteria.length > 0) {
2452
- coachingSection = formatRubricCoaching(verdictResult);
2453
- }
2454
- } catch {
2528
+ if (verdictResult?.verdict && verdictResult.verdict.tier !== "passive" && verdictResult.verdict.criteria.length > 0) {
2529
+ coachingSection = formatRubricCoaching(verdictResult);
2455
2530
  }
2456
2531
  if (verdictResult?.verdict) {
2457
2532
  try {
@@ -2596,6 +2671,13 @@ Use \`entries action=get\` to inspect the existing entry, or \`update-entry\` to
2596
2671
  }
2597
2672
  lines.push("Run `context action=gather` on these entries before committing.");
2598
2673
  }
2674
+ if (entryWarnings.length > 0) {
2675
+ lines.push("");
2676
+ lines.push("## Validation Warnings");
2677
+ for (const w of entryWarnings) {
2678
+ lines.push(`- ${w}`);
2679
+ }
2680
+ }
2599
2681
  if (coachingSection) {
2600
2682
  lines.push("");
2601
2683
  lines.push(coachingSection);
@@ -2646,6 +2728,11 @@ Use \`entries action=get\` to inspect the existing entry, or \`update-entry\` to
2646
2728
  next.push({ tool: "commit-entry", description: "Commit to Chain", parameters: { entryId: finalEntryId } });
2647
2729
  }
2648
2730
  const summary = finalStatus === "committed" ? `Captured and committed ${finalEntryId} (${name}) to ${resolvedCollection}. Quality ${quality.score}/10.` : finalStatus === "proposed" ? `Captured ${finalEntryId} (${name}) in ${resolvedCollection} and created a proposal for commit. Quality ${quality.score}/10.` : `Captured ${finalEntryId} (${name}) as draft in ${resolvedCollection}. Quality ${quality.score}/10.`;
2731
+ const expectedFields = (col.fields ?? []).map((f) => ({
2732
+ key: f.key,
2733
+ type: f.type,
2734
+ ...f.required && { required: true }
2735
+ }));
2649
2736
  const toolResult = {
2650
2737
  content: [{ type: "text", text: lines.join("\n") }],
2651
2738
  structuredContent: success(
@@ -2658,7 +2745,15 @@ Use \`entries action=get\` to inspect the existing entry, or \`update-entry\` to
2658
2745
  qualityScore: quality.score,
2659
2746
  qualityVerdict: verdictResult?.verdict ? { ...verdictResult.verdict, source: verdictResult.source ?? "heuristic" } : void 0,
2660
2747
  ...classifierMeta && { classifier: classifierMeta },
2661
- ...studioUrl && { studioUrl }
2748
+ ...studioUrl && { studioUrl },
2749
+ ...entryWarnings.length > 0 && { warnings: entryWarnings },
2750
+ ...normalizationMeta && (Object.keys(normalizationMeta.remapped).length > 0 || normalizationMeta.rejected.length > 0) && {
2751
+ normalization: {
2752
+ remapped: normalizationMeta.remapped,
2753
+ rejected: normalizationMeta.rejected
2754
+ }
2755
+ },
2756
+ expectedFields
2662
2757
  },
2663
2758
  next
2664
2759
  )
@@ -2759,19 +2854,8 @@ Use \`entries action=get\` to inspect the existing entry, or \`update-entry\` to
2759
2854
  });
2760
2855
  continue;
2761
2856
  }
2762
- const data = {};
2857
+ const data = buildDataFromFields(col.fields ?? [], profile.descriptionField, entry.description);
2763
2858
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
2764
- for (const field of col.fields ?? []) {
2765
- const key = field.key;
2766
- if (key === profile.descriptionField) {
2767
- data[key] = entry.description;
2768
- } else if (field.type === "array" || field.type === "multi-select") {
2769
- data[key] = [];
2770
- } else if (field.type === "select") {
2771
- } else {
2772
- data[key] = "";
2773
- }
2774
- }
2775
2859
  for (const def of profile.defaults) {
2776
2860
  if (def.value === "today") data[def.key] = today;
2777
2861
  else if (def.value !== "infer") data[def.key] = def.value;
@@ -2806,6 +2890,7 @@ Use \`entries action=get\` to inspect the existing entry, or \`update-entry\` to
2806
2890
  });
2807
2891
  const internalId = result.docId;
2808
2892
  const finalEntryId = result.entryId;
2893
+ const batchEntryWarnings = result.warnings ?? [];
2809
2894
  resolveGapsForEntry(entry.name, result.entryId);
2810
2895
  let finalStatus = "draft";
2811
2896
  let commitError;
@@ -2816,27 +2901,22 @@ Use \`entries action=get\` to inspect the existing entry, or \`update-entry\` to
2816
2901
  const searchResults = await mcpQuery("chain.searchEntries", { query: searchQuery });
2817
2902
  const candidates = (searchResults ?? []).filter((r) => r.entryId !== finalEntryId).map((r) => {
2818
2903
  const conf = computeLinkConfidence(r, entry.name, entry.description, resolvedSlug, collIdToSlug.get(r.collectionId) ?? "unknown");
2819
- return {
2820
- ...r,
2821
- collSlug: collIdToSlug.get(r.collectionId) ?? "unknown",
2822
- confidence: conf.score
2823
- };
2904
+ return { ...r, collSlug: collIdToSlug.get(r.collectionId) ?? "unknown", confidence: conf.score };
2824
2905
  }).sort((a, b) => b.confidence - a.confidence);
2906
+ const batchAutoLinks = [];
2825
2907
  for (const c of candidates) {
2826
- if (autoLinkCount >= MAX_AUTO_LINKS) break;
2908
+ if (batchAutoLinks.length >= MAX_AUTO_LINKS) break;
2827
2909
  if (c.confidence < AUTO_LINK_CONFIDENCE_THRESHOLD) break;
2828
2910
  if (!c.entryId) continue;
2829
2911
  const { type: relationType } = inferRelationType(resolvedSlug, c.collSlug, profile);
2830
- try {
2831
- await mcpMutation("chain.createEntryRelation", {
2832
- fromEntryId: finalEntryId,
2833
- toEntryId: c.entryId,
2834
- type: relationType,
2835
- sessionId: agentId ?? void 0
2836
- });
2837
- autoLinkCount++;
2838
- } catch {
2839
- }
2912
+ batchAutoLinks.push({ fromEntryId: finalEntryId, toEntryId: c.entryId, type: relationType });
2913
+ }
2914
+ if (batchAutoLinks.length > 0) {
2915
+ const batchRes = await mcpMutation("chain.createEntryRelations", {
2916
+ relations: batchAutoLinks,
2917
+ sessionId: agentId ?? void 0
2918
+ });
2919
+ autoLinkCount = batchRes.created;
2840
2920
  }
2841
2921
  } catch {
2842
2922
  }
@@ -2856,6 +2936,7 @@ Use \`entries action=get\` to inspect the existing entry, or \`update-entry\` to
2856
2936
  commitError = error instanceof Error ? error.message : String(error);
2857
2937
  }
2858
2938
  }
2939
+ const entryNorm = result.normalization;
2859
2940
  results.push({
2860
2941
  name: entry.name,
2861
2942
  collection: resolvedSlug,
@@ -2866,7 +2947,11 @@ Use \`entries action=get\` to inspect the existing entry, or \`update-entry\` to
2866
2947
  classifiedBy,
2867
2948
  confidence,
2868
2949
  confidenceTier,
2869
- ...commitError ? { commitError } : {}
2950
+ ...commitError ? { commitError } : {},
2951
+ ...batchEntryWarnings.length > 0 ? { warnings: batchEntryWarnings } : {},
2952
+ ...entryNorm && (Object.keys(entryNorm.remapped).length > 0 || entryNorm.rejected.length > 0) && {
2953
+ normalization: { remapped: entryNorm.remapped, rejected: entryNorm.rejected }
2954
+ }
2870
2955
  });
2871
2956
  } catch (error) {
2872
2957
  const msg = error instanceof Error ? error.message : String(error);
@@ -2964,6 +3049,14 @@ _Use \`entries action=move\` to correct any misclassified entries._`);
2964
3049
  lines.push(`- **${r.entryId}**: ${r.name} [${r.collection}] \u2014 ${r.commitError}`);
2965
3050
  }
2966
3051
  }
3052
+ const entriesWithWarnings = created.filter((r) => r.warnings && r.warnings.length > 0);
3053
+ if (entriesWithWarnings.length > 0) {
3054
+ lines.push("");
3055
+ lines.push("## Validation Warnings");
3056
+ for (const r of entriesWithWarnings) {
3057
+ lines.push(`- **${r.entryId}** (${r.name}): ${r.warnings.join("; ")}`);
3058
+ }
3059
+ }
2967
3060
  if (failed.length > 0) {
2968
3061
  lines.push("");
2969
3062
  lines.push("## Failed");
@@ -3016,7 +3109,9 @@ _Use \`entries action=move\` to correct any misclassified entries._`);
3016
3109
  status: r.status,
3017
3110
  ...r.classifiedBy ? { classifiedBy: r.classifiedBy } : {},
3018
3111
  ...r.confidence != null ? { confidence: r.confidence } : {},
3019
- ...r.confidenceTier ? { confidenceTier: r.confidenceTier } : {}
3112
+ ...r.confidenceTier ? { confidenceTier: r.confidenceTier } : {},
3113
+ ...r.warnings?.length ? { warnings: r.warnings } : {},
3114
+ ...r.normalization ? { normalization: r.normalization } : {}
3020
3115
  })),
3021
3116
  total: created.length,
3022
3117
  failed: failed.length,
@@ -3308,4 +3403,4 @@ export {
3308
3403
  formatRubricCoaching,
3309
3404
  formatRubricVerdictSection
3310
3405
  };
3311
- //# sourceMappingURL=chunk-UEUFJX5P.js.map
3406
+ //# sourceMappingURL=chunk-ZY3ORYC3.js.map