@productbrain/mcp 0.0.1-beta.2269 → 0.0.1-beta.2283

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.
@@ -1897,6 +1897,7 @@ Use \`entries action=get\` to inspect the existing entry, or \`entries action=up
1897
1897
  let finalStatus = "draft";
1898
1898
  let commitError = null;
1899
1899
  let commitRefusal = null;
1900
+ let contradictionAdvisory = null;
1900
1901
  if (wasAutoCommittedServerSide) {
1901
1902
  finalStatus = "committed";
1902
1903
  await recordSessionActivity({ entryModified: internalId });
@@ -1908,34 +1909,29 @@ Use \`entries action=get\` to inspect the existing entry, or \`entries action=up
1908
1909
  });
1909
1910
  } else if (shouldAutoCommit && finalEntryId) {
1910
1911
  try {
1911
- const semanticConflicts = await runSemanticConflictPreflight(name, description, resolvedCollection);
1912
- const blockingConflicts = semanticConflicts.filter(
1913
- (conflict) => conflict.type === "contradiction" && conflict.confidence >= BLOCKING_CONTRADICTION_THRESHOLD
1914
- );
1915
- if (blockingConflicts.length > 0) {
1916
- commitError = `blocked by semantic contradiction preflight: ${blockingConflicts[0]?.chainEntryId} ${blockingConflicts[0]?.explanation ?? ""}`.trim();
1912
+ const semanticConflicts = await discoverSemanticConflicts(name, description, resolvedCollection);
1913
+ const commitResult = await kernelMutation("chain.commitEntry", {
1914
+ entryId: finalEntryId,
1915
+ author: agentId ? `agent:${agentId}` : void 0,
1916
+ sessionId: agentId ?? void 0,
1917
+ ...semanticConflicts.length > 0 ? { conflicts: semanticConflicts } : {}
1918
+ });
1919
+ const refusalReason = coherencyRefusalReason(commitResult);
1920
+ if (refusalReason) {
1921
+ commitError = `coherency gate refused this accept \u2014 ${refusalReason}`;
1922
+ commitRefusal = commitResult?.refusal ?? null;
1923
+ finalStatus = "draft_on_failure";
1917
1924
  } else {
1918
- const commitResult = await kernelMutation("chain.commitEntry", {
1919
- entryId: finalEntryId,
1920
- author: agentId ? `agent:${agentId}` : void 0,
1921
- sessionId: agentId ?? void 0
1922
- });
1923
- const refusalReason = coherencyRefusalReason(commitResult);
1924
- if (refusalReason) {
1925
- commitError = `coherency gate refused this accept \u2014 ${refusalReason}`;
1926
- commitRefusal = commitResult?.refusal ?? null;
1927
- finalStatus = "draft_on_failure";
1928
- } else {
1929
- finalStatus = commitResult?.status === "proposal_created" ? "proposed" : "committed";
1930
- if (finalStatus === "committed") {
1931
- await recordSessionActivity({ entryModified: internalId });
1932
- trackChainEntryCommitted(wsCtx.workspaceId, {
1933
- entry_id: finalEntryId,
1934
- collection: resolvedCollection,
1935
- commit_method: "auto",
1936
- surface: "mcp_capture"
1937
- });
1938
- }
1925
+ finalStatus = commitResult?.status === "proposal_created" ? "proposed" : "committed";
1926
+ contradictionAdvisory = commitResult?.contradictionAdvisory ?? null;
1927
+ if (finalStatus === "committed") {
1928
+ await recordSessionActivity({ entryModified: internalId });
1929
+ trackChainEntryCommitted(wsCtx.workspaceId, {
1930
+ entry_id: finalEntryId,
1931
+ collection: resolvedCollection,
1932
+ commit_method: "auto",
1933
+ surface: "mcp_capture"
1934
+ });
1939
1935
  }
1940
1936
  }
1941
1937
  } catch (e) {
@@ -2004,6 +2000,14 @@ Use \`entries action=get\` to inspect the existing entry, or \`entries action=up
2004
2000
  if (await isGoverned(resolvedCollection)) {
2005
2001
  lines.push(`_Note: \`${resolvedCollection}\` is a governed collection \u2014 ensure this entry has been reviewed._`);
2006
2002
  }
2003
+ if (contradictionAdvisory) {
2004
+ lines.push("");
2005
+ lines.push("## Contradiction advisory");
2006
+ lines.push(contradictionAdvisory.reason);
2007
+ for (const c of contradictionAdvisory.conflictDetails) {
2008
+ lines.push(`- \`${c.chainEntryId}\` ${c.chainEntryName}: ${c.explanation}`);
2009
+ }
2010
+ }
2007
2011
  } else if (finalStatus === "proposed") {
2008
2012
  lines.push("");
2009
2013
  lines.push(`## Proposal created: ${finalEntryId}`);
@@ -2212,6 +2216,12 @@ Use \`entries action=get\` to inspect the existing entry, or \`entries action=up
2212
2216
  status: finalStatus,
2213
2217
  // WP-465 surface parity: thread full refusal (routes + mode) for coherency-refused auto-commits.
2214
2218
  ...commitRefusal ? { coherencyRefusal: commitRefusal } : {},
2219
+ // WP-485 Slice 2b round 3 (Codex P2, FEAT-1370): mirror the server's contradiction
2220
+ // advisory into the structured payload — it was rendered in the human text (the
2221
+ // "## Contradiction advisory" section above) but silently absent from
2222
+ // structuredContent, so a structured-only MCP consumer saw a committed capture
2223
+ // with no warning even though the text response carried one.
2224
+ ...contradictionAdvisory ? { contradictionAdvisory } : {},
2215
2225
  // WP-480 S1: the server verdict rides `qualityVerdict` (named breaking
2216
2226
  // output-contract change, pre-launch).
2217
2227
  qualityVerdict: verdictResult?.verdict ? { ...verdictResult.verdict, source: verdictResult.source ?? "heuristic" } : void 0,
@@ -2443,6 +2453,7 @@ async function handleBatchCapture(server, { entries, autoCommit, preview }) {
2443
2453
  let finalStatus = batchWasAutoCommittedServerSide ? "committed" : "draft";
2444
2454
  let commitError;
2445
2455
  let commitRefusal;
2456
+ let contradictionAdvisory;
2446
2457
  if (batchWasAutoCommittedServerSide) {
2447
2458
  await recordSessionActivity({ entryModified: internalId });
2448
2459
  trackChainEntryCommitted(wsCtx.workspaceId, {
@@ -2530,34 +2541,29 @@ async function handleBatchCapture(server, { entries, autoCommit, preview }) {
2530
2541
  }
2531
2542
  if (autoCommitApplied && !batchWasAutoCommittedServerSide) {
2532
2543
  try {
2533
- const semanticConflicts = await runSemanticConflictPreflight(entry.name, entry.description, resolvedSlug);
2534
- const blockingConflicts = semanticConflicts.filter(
2535
- (conflict) => conflict.type === "contradiction" && conflict.confidence >= BLOCKING_CONTRADICTION_THRESHOLD
2536
- );
2537
- if (blockingConflicts.length > 0) {
2538
- commitError = `blocked by semantic contradiction preflight: ${blockingConflicts[0]?.chainEntryId} ${blockingConflicts[0]?.explanation ?? ""}`.trim();
2544
+ const semanticConflicts = await discoverSemanticConflicts(entry.name, entry.description, resolvedSlug);
2545
+ const commitResult = await kernelMutation("chain.commitEntry", {
2546
+ entryId: finalEntryId,
2547
+ author: agentId ? `agent:${agentId}` : void 0,
2548
+ sessionId: agentId ?? void 0,
2549
+ ...semanticConflicts.length > 0 ? { conflicts: semanticConflicts } : {}
2550
+ });
2551
+ const refusalReason = coherencyRefusalReason(commitResult);
2552
+ if (refusalReason) {
2553
+ commitError = `coherency gate refused this accept \u2014 ${refusalReason}`;
2554
+ commitRefusal = commitResult?.refusal ?? void 0;
2555
+ finalStatus = "draft_on_failure";
2539
2556
  } else {
2540
- const commitResult = await kernelMutation("chain.commitEntry", {
2541
- entryId: finalEntryId,
2542
- author: agentId ? `agent:${agentId}` : void 0,
2543
- sessionId: agentId ?? void 0
2544
- });
2545
- const refusalReason = coherencyRefusalReason(commitResult);
2546
- if (refusalReason) {
2547
- commitError = `coherency gate refused this accept \u2014 ${refusalReason}`;
2548
- commitRefusal = commitResult?.refusal ?? void 0;
2549
- finalStatus = "draft_on_failure";
2550
- } else {
2551
- finalStatus = commitResult?.status === "proposal_created" ? "proposed" : "committed";
2552
- if (finalStatus === "committed") {
2553
- await recordSessionActivity({ entryModified: internalId });
2554
- trackChainEntryCommitted(wsCtx.workspaceId, {
2555
- entry_id: finalEntryId,
2556
- collection: resolvedSlug ?? void 0,
2557
- commit_method: "auto",
2558
- surface: "mcp_capture"
2559
- });
2560
- }
2557
+ finalStatus = commitResult?.status === "proposal_created" ? "proposed" : "committed";
2558
+ contradictionAdvisory = commitResult?.contradictionAdvisory ?? void 0;
2559
+ if (finalStatus === "committed") {
2560
+ await recordSessionActivity({ entryModified: internalId });
2561
+ trackChainEntryCommitted(wsCtx.workspaceId, {
2562
+ entry_id: finalEntryId,
2563
+ collection: resolvedSlug ?? void 0,
2564
+ commit_method: "auto",
2565
+ surface: "mcp_capture"
2566
+ });
2561
2567
  }
2562
2568
  }
2563
2569
  } catch (error) {
@@ -2581,6 +2587,9 @@ async function handleBatchCapture(server, { entries, autoCommit, preview }) {
2581
2587
  ...commitError ? { commitError } : {},
2582
2588
  // WP-465 surface parity: thread full refusal payload for coherency-refused batch entries.
2583
2589
  ...commitRefusal ? { commitRefusal } : {},
2590
+ // WP-485 Slice 2b (R2, FEAT-1370): the server's contradiction advisory (DEC-1321 —
2591
+ // advisory only, never blocking) — visible, never a silent success.
2592
+ ...contradictionAdvisory ? { contradictionAdvisory } : {},
2584
2593
  ...batchEntryWarnings.length > 0 ? { warnings: batchEntryWarnings } : {},
2585
2594
  ...entryNorm && (Object.keys(entryNorm.remapped).length > 0 || entryNorm.rejected.length > 0) && {
2586
2595
  normalization: { remapped: entryNorm.remapped, rejected: entryNorm.rejected }
@@ -2699,6 +2708,17 @@ _Use \`entries action=move\` to correct any misclassified entries._`);
2699
2708
  }
2700
2709
  }
2701
2710
  }
2711
+ const entriesWithContradictionAdvisory = created.filter((r) => r.contradictionAdvisory);
2712
+ if (entriesWithContradictionAdvisory.length > 0) {
2713
+ lines.push("");
2714
+ lines.push("## Contradiction Advisories");
2715
+ for (const r of entriesWithContradictionAdvisory) {
2716
+ lines.push(`- **${r.entryId}**: ${r.name} \u2014 ${r.contradictionAdvisory.reason}`);
2717
+ for (const c of r.contradictionAdvisory.conflictDetails) {
2718
+ lines.push(` - \`${c.chainEntryId}\` ${c.chainEntryName}: ${c.explanation}`);
2719
+ }
2720
+ }
2721
+ }
2702
2722
  if (autoCommitApplied) {
2703
2723
  const entriesWithOverlaps = created.filter((r) => r.overlapCount && r.overlapCount > 0);
2704
2724
  if (entriesWithOverlaps.length > 0) {
@@ -2787,7 +2807,11 @@ _Use \`entries action=move\` to correct any misclassified entries._`);
2787
2807
  // TEN-957 (WP-484 S2): inline relations created for this entry.
2788
2808
  ...r.relationsCreated ? { relationsCreated: r.relationsCreated } : {},
2789
2809
  // Finding #14: proposal outcomes are distinct from writes — never folded in.
2790
- ...r.relationsProposed ? { relationsProposed: r.relationsProposed } : {}
2810
+ ...r.relationsProposed ? { relationsProposed: r.relationsProposed } : {},
2811
+ // WP-485 Slice 2b round 2 (Codex P1): the server's per-entry contradiction
2812
+ // advisory — was reaching `results` but dropped here, the final projection the
2813
+ // caller actually receives. Visible, never a silent success.
2814
+ ...r.contradictionAdvisory ? { contradictionAdvisory: r.contradictionAdvisory } : {}
2791
2815
  })),
2792
2816
  total: created.length,
2793
2817
  failed: failed.length,
@@ -2974,15 +2998,21 @@ async function runContradictionCheck(name, description) {
2974
2998
  }
2975
2999
  return warnings;
2976
3000
  }
2977
- var BLOCKING_CONTRADICTION_THRESHOLD = 0.75;
2978
- async function runSemanticConflictPreflight(name, description, collectionHint) {
3001
+ async function discoverSemanticConflicts(name, description, collectionHint) {
2979
3002
  try {
2980
3003
  const conflicts = await kernelQuery("chain.detectSemanticConflicts", {
2981
3004
  name,
2982
3005
  description,
2983
3006
  ...collectionHint ? { collectionHint } : {}
2984
3007
  });
2985
- return conflicts ?? [];
3008
+ return (conflicts ?? []).map((c) => ({
3009
+ chainEntryId: c.chainEntryId,
3010
+ chainEntryName: c.chainEntryName,
3011
+ ...c.chainEntryDescription ? { chainEntryDescription: c.chainEntryDescription } : {},
3012
+ type: c.type,
3013
+ confidence: c.confidence,
3014
+ explanation: c.explanation
3015
+ }));
2986
3016
  } catch {
2987
3017
  return [];
2988
3018
  }
@@ -3074,10 +3104,6 @@ function formatRubricVerdictSection(verdict) {
3074
3104
  }
3075
3105
 
3076
3106
  // src/tools/conflict-preflight.ts
3077
- var BLOCKING_CONTRADICTION_THRESHOLD2 = 0.75;
3078
- function isBlockingContradiction(conflict) {
3079
- return conflict.type === "contradiction" && conflict.confidence >= BLOCKING_CONTRADICTION_THRESHOLD2;
3080
- }
3081
3107
  async function runConflictPreflight(name, description, collectionHint) {
3082
3108
  try {
3083
3109
  const conflicts = await kernelQuery("chain.detectSemanticConflicts", {
@@ -3087,8 +3113,7 @@ async function runConflictPreflight(name, description, collectionHint) {
3087
3113
  });
3088
3114
  return {
3089
3115
  source: "semantic",
3090
- conflicts,
3091
- blockingContradictions: conflicts.filter(isBlockingContradiction),
3116
+ conflicts: conflicts ?? [],
3092
3117
  advisoryWarnings: []
3093
3118
  };
3094
3119
  } catch (err) {
@@ -3097,7 +3122,6 @@ async function runConflictPreflight(name, description, collectionHint) {
3097
3122
  return {
3098
3123
  source: "heuristic",
3099
3124
  conflicts: [],
3100
- blockingContradictions: [],
3101
3125
  advisoryWarnings
3102
3126
  };
3103
3127
  }
@@ -3314,7 +3338,7 @@ async function handleCommitEntry({ entryId, preview, steeringOverrideReason, coh
3314
3338
  descField,
3315
3339
  entry.collectionSlug ?? entry.collection?.slug ?? entry.collection?.name
3316
3340
  );
3317
- const advisoryWarnings = preflight.source === "semantic" ? preflight.conflicts.filter((conflict) => !preflight.blockingContradictions.includes(conflict)).map((conflict) => ({
3341
+ const advisoryWarnings = preflight.source === "semantic" ? preflight.conflicts.map((conflict) => ({
3318
3342
  kind: "semantic",
3319
3343
  entryId: conflict.chainEntryId,
3320
3344
  name: conflict.chainEntryName,
@@ -3326,32 +3350,17 @@ async function handleCommitEntry({ entryId, preview, steeringOverrideReason, coh
3326
3350
  collection: warning.collection,
3327
3351
  governsCount: warning.governsCount
3328
3352
  }));
3329
- if (preflight.blockingContradictions.length > 0) {
3330
- await recordSessionActivity({ contradictionWarning: true });
3331
- const conflictLines = preflight.blockingContradictions.map((c) => `- ${c.chainEntryName} (${c.chainEntryId}) \u2014 ${c.explanation}`).join("\n");
3332
- return failureResult(
3333
- [
3334
- `# Accept blocked: contradiction detected`,
3335
- "",
3336
- `\`${entryId}\` matches ${preflight.blockingContradictions.length} high-confidence contradiction(s). Resolve the conflict before accepting.`,
3337
- "",
3338
- conflictLines
3339
- ].join("\n"),
3340
- "CONTRADICTION_BLOCKED",
3341
- `${preflight.blockingContradictions.length} high-confidence contradiction(s) found.`,
3342
- "Review the conflicting entry or entries before retrying the accept.",
3343
- void 0,
3344
- {
3345
- entryId,
3346
- source: preflight.source,
3347
- blockingContradictions: preflight.blockingContradictions,
3348
- advisoryWarnings
3349
- }
3350
- );
3351
- }
3352
3353
  if (advisoryWarnings.length > 0) {
3353
3354
  await recordSessionActivity({ contradictionWarning: true });
3354
3355
  }
3356
+ const conflictEvidence = preflight.source === "semantic" ? preflight.conflicts.map((c) => ({
3357
+ chainEntryId: c.chainEntryId,
3358
+ chainEntryName: c.chainEntryName,
3359
+ ...c.chainEntryDescription ? { chainEntryDescription: c.chainEntryDescription } : {},
3360
+ type: c.type,
3361
+ confidence: c.confidence,
3362
+ explanation: c.explanation
3363
+ })) : [];
3355
3364
  let coachingResult = null;
3356
3365
  if (!preview) {
3357
3366
  try {
@@ -3370,7 +3379,8 @@ async function handleCommitEntry({ entryId, preview, steeringOverrideReason, coh
3370
3379
  sessionId: getAgentSessionId() ?? void 0,
3371
3380
  ...preview ? { preview: true } : {},
3372
3381
  ...steeringOverrideReason ? { steeringOverrideReason } : {},
3373
- ...coherencyAcknowledgement ? { coherencyAcknowledgement } : {}
3382
+ ...coherencyAcknowledgement ? { coherencyAcknowledgement } : {},
3383
+ ...conflictEvidence.length > 0 ? { conflicts: conflictEvidence } : {}
3374
3384
  });
3375
3385
  } catch (commitErr) {
3376
3386
  const errCode = commitErr?.code;
@@ -3394,6 +3404,7 @@ async function handleCommitEntry({ entryId, preview, steeringOverrideReason, coh
3394
3404
  }
3395
3405
  if (result?.preview) {
3396
3406
  const wouldBlock = result.wouldBlock === true;
3407
+ const previewContradictionAdvisory = result?.contradictionAdvisory;
3397
3408
  const previewEnvelope = success(
3398
3409
  `Preview: ${wouldBlock ? "would BLOCK accept" : "would accept"} ${entryId} \u2014 no DB writes`,
3399
3410
  {
@@ -3403,7 +3414,8 @@ async function handleCommitEntry({ entryId, preview, steeringOverrideReason, coh
3403
3414
  currentStatus: result.currentStatus,
3404
3415
  wouldSetStatus: result.wouldSetStatus,
3405
3416
  wouldBlock,
3406
- ...wouldBlock && result.blockingReason ? { blockingReason: result.blockingReason } : {}
3417
+ ...wouldBlock && result.blockingReason ? { blockingReason: result.blockingReason } : {},
3418
+ ...previewContradictionAdvisory ? { contradictionAdvisory: previewContradictionAdvisory } : {}
3407
3419
  },
3408
3420
  [{ tool: toolName, description: "Accept for real", parameters: { action: "commit", entryId } }]
3409
3421
  );
@@ -3415,10 +3427,14 @@ async function handleCommitEntry({ entryId, preview, steeringOverrideReason, coh
3415
3427
  **Would be blocked:** ${result.blockingReason}` : wouldBlock ? `
3416
3428
 
3417
3429
  **Would be blocked** by the coherency/grounding gate.` : "";
3430
+ const advisoryNote = previewContradictionAdvisory ? `
3431
+
3432
+ \u26A0 Contradiction advisory (would be attached on real commit): ${previewContradictionAdvisory.reason}
3433
+ ${previewContradictionAdvisory.conflictDetails.map((c) => `- \`${c.chainEntryId}\` ${c.chainEntryName}: ${c.explanation}`).join("\n")}` : "";
3418
3434
  return {
3419
3435
  content: [{ type: "text", text: `# Preview: would ${wouldBlock ? "BLOCK accept" : "accept"} ${entryId}
3420
3436
 
3421
- Current status: \`${result.currentStatus}\` \u2192 would become \`${result.wouldSetStatus}\`.${blockingNote}
3437
+ Current status: \`${result.currentStatus}\` \u2192 would become \`${result.wouldSetStatus}\`.${blockingNote}${advisoryNote}
3422
3438
 
3423
3439
  No DB writes \u2014 call without \`preview:true\` to accept for real.` }],
3424
3440
  structuredContent: previewEnvelope
@@ -3465,7 +3481,7 @@ No DB writes \u2014 call without \`preview:true\` to accept for real.` }],
3465
3481
  for (const w of advisoryWarnings) {
3466
3482
  lines.push(w.kind === "semantic" ? `- ${w.name} (${w.entryId}) \u2014 ${w.explanation}` : `- ${w.name} (${w.collection}, ${w.entryId}) \u2014 has 'governs' relation to ${w.governsCount} entries`);
3467
3483
  }
3468
- lines.push(preflight.source === "semantic" ? "Run context action=gather on the conflicting entries before accepting." : "Run context action=gather on these entries before accepting.");
3484
+ lines.push(preflight.source === "semantic" ? "Run context action=gather on the conflicting entries to review; use entries action=update to reconcile the two, or to mark this entry status='deprecated' if it's actually superseded." : "Run context action=gather on these entries to review; use entries action=update to reconcile the two, or to mark this entry status='deprecated' if it's actually superseded.");
3469
3485
  }
3470
3486
  if (coachingResult?.verdict) {
3471
3487
  try {
@@ -3516,6 +3532,14 @@ No DB writes \u2014 call without \`preview:true\` to accept for real.` }],
3516
3532
  lines.push("");
3517
3533
  lines.push(`\u26A0 Coherency advisory (entry accepted): ${steeringAdvisory}`);
3518
3534
  }
3535
+ const contradictionAdvisory = result?.contradictionAdvisory;
3536
+ if (contradictionAdvisory) {
3537
+ lines.push("");
3538
+ lines.push(`\u26A0 Contradiction advisory (entry committed): ${contradictionAdvisory.reason}`);
3539
+ for (const c of contradictionAdvisory.conflictDetails) {
3540
+ lines.push(`- \`${c.chainEntryId}\` ${c.chainEntryName}: ${c.explanation}`);
3541
+ }
3542
+ }
3519
3543
  const epistemic = deriveEpistemicStatus(toEpistemicInput(entry));
3520
3544
  if (epistemic && (epistemic.level === "hypothesis" || epistemic.level === "untested")) {
3521
3545
  lines.push("");
@@ -3553,6 +3577,9 @@ No DB writes \u2014 call without \`preview:true\` to accept for real.` }],
3553
3577
  contradictions: advisoryWarnings.length,
3554
3578
  ...epistemic ? { epistemicStatus: epistemic } : {},
3555
3579
  ...steeringAdvisory ? { steeringAdvisory } : {},
3580
+ // WP-485 Slice 2b round 2 (Codex P1, FEAT-1370): mirror the server's contradiction
3581
+ // advisory into the structured payload so --json/agent consumers see it too.
3582
+ ...contradictionAdvisory ? { contradictionAdvisory } : {},
3556
3583
  // WP-B (attestation spec §4.3): mirror the auto-verify receipt into the
3557
3584
  // structured payload so --json/agent consumers see it too.
3558
3585
  ...result?.autoVerified ? { autoVerified: result.autoVerified } : {}
@@ -12086,37 +12113,17 @@ async function handleCommitConstellation(args) {
12086
12113
  } catch {
12087
12114
  }
12088
12115
  const preflight = await runConflictPreflight(betName, betDesc, betCollectionHint);
12089
- if (preflight.blockingContradictions.length > 0) {
12090
- await recordSessionActivity({ contradictionWarning: true });
12091
- const conflictLines = preflight.blockingContradictions.map((c) => `- ${c.chainEntryName} (${c.chainEntryId}) \u2014 ${c.explanation}`).join("\n");
12092
- return {
12093
- content: [{
12094
- type: "text",
12095
- text: [
12096
- `# Accept blocked: contradiction detected`,
12097
- "",
12098
- `\`${betId}\` matches ${preflight.blockingContradictions.length} high-confidence contradiction(s). Resolve the conflict before accepting the constellation.`,
12099
- "",
12100
- conflictLines
12101
- ].join("\n")
12102
- }],
12103
- structuredContent: failure(
12104
- "CONTRADICTION_BLOCKED",
12105
- `${preflight.blockingContradictions.length} high-confidence contradiction(s) found.`,
12106
- "Review the conflicting entry or entries before retrying the accept.",
12107
- void 0,
12108
- {
12109
- betEntryId: betId,
12110
- source: preflight.source,
12111
- blockingContradictions: preflight.blockingContradictions,
12112
- advisoryWarnings: preflight.advisoryWarnings
12113
- }
12114
- )
12115
- };
12116
- }
12117
12116
  if (preflight.source === "semantic" ? preflight.conflicts.length > 0 : preflight.advisoryWarnings.length > 0) {
12118
12117
  await recordSessionActivity({ contradictionWarning: true });
12119
12118
  }
12119
+ const conflictEvidence = preflight.source === "semantic" ? preflight.conflicts.map((c) => ({
12120
+ chainEntryId: c.chainEntryId,
12121
+ chainEntryName: c.chainEntryName,
12122
+ ...c.chainEntryDescription ? { chainEntryDescription: c.chainEntryDescription } : {},
12123
+ type: c.type,
12124
+ confidence: c.confidence,
12125
+ explanation: c.explanation
12126
+ })) : [];
12120
12127
  let envelope;
12121
12128
  try {
12122
12129
  envelope = await kernelCallEnvelope("agentKnowledge.facilitateEnvelope", {
@@ -12129,7 +12136,8 @@ async function handleCommitConstellation(args) {
12129
12136
  // WP-465 slice ⑤ (TEN-2439, §3.7): relay the coherency retry controls so a
12130
12137
  // COHERENCY_REFUSED constellation hold is actually retryable through MCP.
12131
12138
  ...args.coherencyAcknowledgements ? { coherencyAcknowledgements: args.coherencyAcknowledgements } : {},
12132
- ...args.steeringOverrideReason ? { steeringOverrideReason: args.steeringOverrideReason } : {}
12139
+ ...args.steeringOverrideReason ? { steeringOverrideReason: args.steeringOverrideReason } : {},
12140
+ ...conflictEvidence.length > 0 ? { conflicts: conflictEvidence } : {}
12133
12141
  });
12134
12142
  } catch (err) {
12135
12143
  const msg = err instanceof Error ? err.message : String(err);
@@ -12158,6 +12166,23 @@ async function handleCommitConstellation(args) {
12158
12166
  )
12159
12167
  };
12160
12168
  }
12169
+ if (code === "CONTRADICTION_BLOCKED") {
12170
+ return {
12171
+ content: [{
12172
+ type: "text",
12173
+ text: `# Constellation accept blocked
12174
+
12175
+ \`${betId}\` was not accepted: ${msg}
12176
+
12177
+ No constellation entries were accepted.`
12178
+ }],
12179
+ structuredContent: failure(
12180
+ "CONTRADICTION_BLOCKED",
12181
+ msg,
12182
+ "Resolve the contradiction before retrying commit-constellation."
12183
+ )
12184
+ };
12185
+ }
12161
12186
  return {
12162
12187
  content: [{
12163
12188
  type: "text",
@@ -12176,7 +12201,6 @@ No constellation entries were accepted.`
12176
12201
  )
12177
12202
  };
12178
12203
  }
12179
- await recordSessionActivity({ contradictionWarning: preflight.blockingContradictions.length > 0 });
12180
12204
  for (const docId of envelope.data?.result?.committedIds ?? []) {
12181
12205
  try {
12182
12206
  await recordSessionActivity({ entryModified: docId });
@@ -12184,7 +12208,11 @@ No constellation entries were accepted.`
12184
12208
  }
12185
12209
  }
12186
12210
  const result = envelope.data.result;
12187
- const suggestions = { conflictPreflightSource: preflight.source };
12211
+ const suggestions = {
12212
+ conflictPreflightSource: preflight.source,
12213
+ ...preflight.source === "semantic" && preflight.conflicts.length > 0 ? { conflicts: preflight.conflicts } : {},
12214
+ ...preflight.source === "heuristic" && preflight.advisoryWarnings.length > 0 ? { advisoryWarnings: preflight.advisoryWarnings } : {}
12215
+ };
12188
12216
  const lines = [];
12189
12217
  const hasIssues = (result.failedIds?.length ?? 0) > 0 || (result.conflictIds?.length ?? 0) > 0;
12190
12218
  if (result.proposalCreated) {
@@ -15354,4 +15382,4 @@ export {
15354
15382
  createProductBrainServer,
15355
15383
  initFeatureFlags
15356
15384
  };
15357
- //# sourceMappingURL=chunk-YV2O2QGE.js.map
15385
+ //# sourceMappingURL=chunk-KILRRGNJ.js.map