@productbrain/mcp 0.0.1-beta.2364 → 0.0.1-beta.2378
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.
|
@@ -805,33 +805,18 @@ async function populateHubCache() {
|
|
|
805
805
|
function invalidateHubCacheForScope() {
|
|
806
806
|
hubCache.delete(cacheScope());
|
|
807
807
|
}
|
|
808
|
-
function
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
score += wordScore;
|
|
821
|
-
if (matchingWords.length > 0) {
|
|
822
|
-
reasons.push(`word overlap (${matchingWords.slice(0, 3).join(", ")})`);
|
|
823
|
-
}
|
|
824
|
-
if (hubSlugs.has(candidateCollection)) {
|
|
825
|
-
score += 15;
|
|
826
|
-
reasons.push("hub collection");
|
|
827
|
-
}
|
|
828
|
-
if (candidateCollection !== sourceCollection) {
|
|
829
|
-
score += 10;
|
|
830
|
-
reasons.push("cross-collection");
|
|
831
|
-
}
|
|
832
|
-
const finalScore = Math.min(score, 100);
|
|
833
|
-
const reason = reasons.length > 0 ? reasons.join(" + ") : "low relevance";
|
|
834
|
-
return { score: finalScore, reason };
|
|
808
|
+
function buildScoreLinkCandidatesJob(candidates, sourceName, sourceDescription, sourceCollection) {
|
|
809
|
+
return {
|
|
810
|
+
candidates: candidates.map((c) => ({ name: c.name, collectionId: c.collectionId })),
|
|
811
|
+
sourceName,
|
|
812
|
+
sourceDescription,
|
|
813
|
+
sourceCollection
|
|
814
|
+
};
|
|
815
|
+
}
|
|
816
|
+
var LINK_SCORE_CHUNK_MAX_ENTRIES = 10;
|
|
817
|
+
var LINK_SCORE_CHUNK_MAX_BYTES = 7e5;
|
|
818
|
+
function estimateJobBytes(job) {
|
|
819
|
+
return JSON.stringify(job).length;
|
|
835
820
|
}
|
|
836
821
|
function inferRelationType(_sourceCollection, _targetCollection, profile) {
|
|
837
822
|
const type = profile.recommendedRelationTypes[0] ?? "related_to";
|
|
@@ -1727,15 +1712,40 @@ Use \`entries action=get\` to inspect the existing entry, or \`entries action=up
|
|
|
1727
1712
|
]);
|
|
1728
1713
|
const collMap = /* @__PURE__ */ new Map();
|
|
1729
1714
|
for (const c of allCollections) collMap.set(c._id, c.slug);
|
|
1730
|
-
const
|
|
1731
|
-
|
|
1715
|
+
const candidatesFiltered = (searchResults ?? []).filter((r) => r.entryId !== finalEntryId && r._id !== internalId).map((r) => ({
|
|
1716
|
+
name: r.name,
|
|
1717
|
+
entryId: r.entryId,
|
|
1718
|
+
collectionId: r.collectionId,
|
|
1719
|
+
preview: extractPreview(r.data, 80)
|
|
1720
|
+
}));
|
|
1721
|
+
let scores = [];
|
|
1722
|
+
if (candidatesFiltered.length > 0) {
|
|
1723
|
+
try {
|
|
1724
|
+
const scoreJobResults = await kernelQuery("chain.scoreLinkCandidates", {
|
|
1725
|
+
collMap: Object.fromEntries(collMap),
|
|
1726
|
+
hubSlugs: [...hubSlugs],
|
|
1727
|
+
jobs: [
|
|
1728
|
+
buildScoreLinkCandidatesJob(
|
|
1729
|
+
candidatesFiltered.map((r) => ({ name: r.name, collectionId: r.collectionId })),
|
|
1730
|
+
name,
|
|
1731
|
+
description,
|
|
1732
|
+
resolvedCollection
|
|
1733
|
+
)
|
|
1734
|
+
]
|
|
1735
|
+
});
|
|
1736
|
+
scores = scoreJobResults[0] ?? [];
|
|
1737
|
+
} catch {
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
const candidates = scores.map((s) => {
|
|
1741
|
+
const r = candidatesFiltered[s.index];
|
|
1732
1742
|
return {
|
|
1733
1743
|
...r,
|
|
1734
1744
|
collSlug: collMap.get(r.collectionId) ?? "unknown",
|
|
1735
|
-
confidence:
|
|
1736
|
-
confidenceReason:
|
|
1745
|
+
confidence: s.score,
|
|
1746
|
+
confidenceReason: s.reason
|
|
1737
1747
|
};
|
|
1738
|
-
})
|
|
1748
|
+
});
|
|
1739
1749
|
let autoCount = 0;
|
|
1740
1750
|
for (const c of candidates) {
|
|
1741
1751
|
if (autoCount >= MAX_AUTO_LINKS) break;
|
|
@@ -1762,11 +1772,10 @@ Use \`entries action=get\` to inspect the existing entry, or \`entries action=up
|
|
|
1762
1772
|
const autoTargetIds = new Set(pendingRelations.map((r) => r.toEntryId));
|
|
1763
1773
|
for (const c of candidates) {
|
|
1764
1774
|
if (linksSuggested.length >= MAX_SUGGESTIONS) break;
|
|
1765
|
-
if (autoTargetIds.has(c.entryId)) continue;
|
|
1775
|
+
if (c.entryId !== void 0 && autoTargetIds.has(c.entryId)) continue;
|
|
1766
1776
|
if (c.confidence < 10) continue;
|
|
1767
|
-
const preview2 = extractPreview(c.data, 80);
|
|
1768
1777
|
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`;
|
|
1769
|
-
linksSuggested.push({ entryId: c.entryId, name: c.name, collection: c.collSlug, reason, preview:
|
|
1778
|
+
linksSuggested.push({ entryId: c.entryId, name: c.name, collection: c.collSlug, reason, preview: c.preview });
|
|
1770
1779
|
}
|
|
1771
1780
|
conflictCandidates = candidates.filter((c) => c.entryId && c.entryId !== finalEntryId).slice(0, 3).map((c) => ({ entryId: c.entryId, name: c.name, collection: c.collSlug }));
|
|
1772
1781
|
}
|
|
@@ -2295,6 +2304,47 @@ async function handleBatchCapture(server, { entries, autoCommit, preview }) {
|
|
|
2295
2304
|
for (const c of allCollections) collCache.set(c.slug, c);
|
|
2296
2305
|
const collIdToSlug = /* @__PURE__ */ new Map();
|
|
2297
2306
|
for (const c of allCollections) collIdToSlug.set(c._id, c.slug);
|
|
2307
|
+
async function flushPendingChunk(chunk) {
|
|
2308
|
+
if (chunk.length === 0) return;
|
|
2309
|
+
const jobsToScore = chunk.filter((p) => p.job !== null).map((p) => p.job);
|
|
2310
|
+
let scoreResultsByJob = [];
|
|
2311
|
+
if (jobsToScore.length > 0) {
|
|
2312
|
+
try {
|
|
2313
|
+
scoreResultsByJob = await kernelQuery("chain.scoreLinkCandidates", {
|
|
2314
|
+
collMap: Object.fromEntries(collIdToSlug),
|
|
2315
|
+
hubSlugs: [...hubSlugs],
|
|
2316
|
+
jobs: jobsToScore
|
|
2317
|
+
});
|
|
2318
|
+
} catch {
|
|
2319
|
+
scoreResultsByJob = jobsToScore.map(() => []);
|
|
2320
|
+
}
|
|
2321
|
+
}
|
|
2322
|
+
let scoreCursor = 0;
|
|
2323
|
+
for (const pending of chunk) {
|
|
2324
|
+
const scores = pending.job !== null ? scoreResultsByJob[scoreCursor++] ?? [] : [];
|
|
2325
|
+
try {
|
|
2326
|
+
await pending.finish(scores);
|
|
2327
|
+
} catch (error) {
|
|
2328
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
2329
|
+
results.push({
|
|
2330
|
+
entryIdx: pending.entryIdx,
|
|
2331
|
+
name: pending.entry.name,
|
|
2332
|
+
collection: pending.resolvedSlug,
|
|
2333
|
+
entryId: "",
|
|
2334
|
+
ok: false,
|
|
2335
|
+
autoLinks: 0,
|
|
2336
|
+
advisedLinks: 0,
|
|
2337
|
+
status: "draft",
|
|
2338
|
+
classifiedBy: pending.classifiedBy,
|
|
2339
|
+
confidence: pending.confidence,
|
|
2340
|
+
confidenceTier: pending.confidenceTier,
|
|
2341
|
+
error: msg
|
|
2342
|
+
});
|
|
2343
|
+
}
|
|
2344
|
+
}
|
|
2345
|
+
}
|
|
2346
|
+
let pendingFinish = [];
|
|
2347
|
+
let chunkBytes = 0;
|
|
2298
2348
|
for (let entryIdx = 0; entryIdx < entries.length; entryIdx++) {
|
|
2299
2349
|
const entry = entries[entryIdx];
|
|
2300
2350
|
if (entryIdx > 0 && entryIdx % 5 === 0) {
|
|
@@ -2337,6 +2387,7 @@ async function handleBatchCapture(server, { entries, autoCommit, preview }) {
|
|
|
2337
2387
|
const col = collCache.get(resolvedSlug);
|
|
2338
2388
|
if (!col) {
|
|
2339
2389
|
results.push({
|
|
2390
|
+
entryIdx,
|
|
2340
2391
|
name: entry.name,
|
|
2341
2392
|
collection: resolvedSlug,
|
|
2342
2393
|
entryId: "",
|
|
@@ -2353,6 +2404,7 @@ async function handleBatchCapture(server, { entries, autoCommit, preview }) {
|
|
|
2353
2404
|
}
|
|
2354
2405
|
if (entry.entryId && resolvedSlug !== "business-rules" && resolvedSlug !== "standards") {
|
|
2355
2406
|
results.push({
|
|
2407
|
+
entryIdx,
|
|
2356
2408
|
name: entry.name,
|
|
2357
2409
|
collection: resolvedSlug,
|
|
2358
2410
|
entryId: "",
|
|
@@ -2467,149 +2519,189 @@ async function handleBatchCapture(server, { entries, autoCommit, preview }) {
|
|
|
2467
2519
|
surface: "mcp_capture"
|
|
2468
2520
|
});
|
|
2469
2521
|
}
|
|
2470
|
-
let
|
|
2471
|
-
let
|
|
2472
|
-
let entryOverlapCount = 0;
|
|
2522
|
+
let candidatesFiltered = [];
|
|
2523
|
+
let job = null;
|
|
2473
2524
|
const searchQuery = extractSearchTerms(entry.name, entry.description);
|
|
2474
2525
|
if (searchQuery) {
|
|
2475
2526
|
try {
|
|
2476
2527
|
const searchResults = await kernelQuery("chain.searchEntries", { query: searchQuery });
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
}
|
|
2490
|
-
if (batchAutoLinks.length > 0 && preview) {
|
|
2491
|
-
batchEntryWarnings.push(`${batchAutoLinks.length} auto-link(s) would be created (preview \u2014 no DB writes).`);
|
|
2492
|
-
} else if (batchAutoLinks.length > 0) {
|
|
2493
|
-
const batchRes = await kernelMutation("chain.createEntryRelations", {
|
|
2494
|
-
relations: batchAutoLinks,
|
|
2495
|
-
sessionId: agentId ?? void 0
|
|
2496
|
-
});
|
|
2497
|
-
autoLinkCount = batchRes.created;
|
|
2498
|
-
advisedLinkCount = batchRes.advised ?? 0;
|
|
2499
|
-
if (advisedLinkCount > 0) {
|
|
2500
|
-
batchEntryWarnings.push(`${advisedLinkCount} auto-link(s) advised, not written (untypeable) \u2014 accept with \`relations action=create\` to promote.`);
|
|
2501
|
-
}
|
|
2528
|
+
candidatesFiltered = (searchResults ?? []).filter((r) => r.entryId !== finalEntryId).map((r) => ({
|
|
2529
|
+
name: r.name,
|
|
2530
|
+
entryId: r.entryId,
|
|
2531
|
+
collectionId: r.collectionId
|
|
2532
|
+
}));
|
|
2533
|
+
if (candidatesFiltered.length > 0) {
|
|
2534
|
+
job = buildScoreLinkCandidatesJob(
|
|
2535
|
+
candidatesFiltered.map((r) => ({ name: r.name, collectionId: r.collectionId })),
|
|
2536
|
+
entry.name,
|
|
2537
|
+
entry.description,
|
|
2538
|
+
resolvedSlug
|
|
2539
|
+
);
|
|
2502
2540
|
}
|
|
2503
2541
|
} catch {
|
|
2504
2542
|
}
|
|
2505
2543
|
}
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2544
|
+
const prospectiveJobBytes = job ? estimateJobBytes(job) : 0;
|
|
2545
|
+
if (pendingFinish.length > 0 && (pendingFinish.length >= LINK_SCORE_CHUNK_MAX_ENTRIES || chunkBytes + prospectiveJobBytes > LINK_SCORE_CHUNK_MAX_BYTES)) {
|
|
2546
|
+
await flushPendingChunk(pendingFinish);
|
|
2547
|
+
pendingFinish = [];
|
|
2548
|
+
chunkBytes = 0;
|
|
2549
|
+
}
|
|
2550
|
+
pendingFinish.push({
|
|
2551
|
+
entryIdx,
|
|
2552
|
+
entry,
|
|
2553
|
+
resolvedSlug,
|
|
2554
|
+
classifiedBy,
|
|
2555
|
+
confidence,
|
|
2556
|
+
confidenceTier,
|
|
2557
|
+
job,
|
|
2558
|
+
finish: async (scores) => {
|
|
2559
|
+
let autoLinkCount = 0;
|
|
2560
|
+
let advisedLinkCount = 0;
|
|
2561
|
+
let entryOverlapCount = 0;
|
|
2562
|
+
if (candidatesFiltered.length > 0) {
|
|
2563
|
+
try {
|
|
2564
|
+
const candidates = scores.map((s) => {
|
|
2565
|
+
const r = candidatesFiltered[s.index];
|
|
2566
|
+
return { ...r, collSlug: collIdToSlug.get(r.collectionId) ?? "unknown", confidence: s.score };
|
|
2567
|
+
});
|
|
2568
|
+
entryOverlapCount = candidates.filter((c) => c.entryId).length;
|
|
2569
|
+
const batchAutoLinks = [];
|
|
2570
|
+
for (const c of candidates) {
|
|
2571
|
+
if (batchAutoLinks.length >= MAX_AUTO_LINKS) break;
|
|
2572
|
+
if (c.confidence < AUTO_LINK_CONFIDENCE_THRESHOLD) break;
|
|
2573
|
+
if (!c.entryId) continue;
|
|
2574
|
+
const { type: relationType } = inferRelationType(resolvedSlug, c.collSlug, profile);
|
|
2575
|
+
batchAutoLinks.push({ fromEntryId: finalEntryId, toEntryId: c.entryId, type: relationType, proposedBy: "auto-link", confidence: c.confidence });
|
|
2522
2576
|
}
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2577
|
+
if (batchAutoLinks.length > 0 && preview) {
|
|
2578
|
+
batchEntryWarnings.push(`${batchAutoLinks.length} auto-link(s) would be created (preview \u2014 no DB writes).`);
|
|
2579
|
+
} else if (batchAutoLinks.length > 0) {
|
|
2580
|
+
const batchRes = await kernelMutation("chain.createEntryRelations", {
|
|
2581
|
+
relations: batchAutoLinks,
|
|
2582
|
+
sessionId: agentId ?? void 0
|
|
2583
|
+
});
|
|
2584
|
+
autoLinkCount = batchRes.created;
|
|
2585
|
+
advisedLinkCount = batchRes.advised ?? 0;
|
|
2586
|
+
if (advisedLinkCount > 0) {
|
|
2587
|
+
batchEntryWarnings.push(`${advisedLinkCount} auto-link(s) advised, not written (untypeable) \u2014 accept with \`relations action=create\` to promote.`);
|
|
2588
|
+
}
|
|
2589
|
+
}
|
|
2590
|
+
} catch {
|
|
2530
2591
|
}
|
|
2531
|
-
} catch (relErr) {
|
|
2532
|
-
const relMsg = relErr instanceof Error ? relErr.message : String(relErr);
|
|
2533
|
-
relationsFailedList.push(`${rel.to} (${rel.type}): ${relMsg}`);
|
|
2534
2592
|
}
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2593
|
+
let relationsCreatedCount = 0;
|
|
2594
|
+
let relationsPreviewedCount = 0;
|
|
2595
|
+
let relationsProposedCount = 0;
|
|
2596
|
+
const relationsFailedList = [];
|
|
2597
|
+
if (entry.relations && entry.relations.length > 0) {
|
|
2598
|
+
for (const rel of entry.relations) {
|
|
2599
|
+
try {
|
|
2600
|
+
const relResult = await kernelMutation(
|
|
2601
|
+
"chain.createEntryRelation",
|
|
2602
|
+
{
|
|
2603
|
+
fromEntryId: finalEntryId,
|
|
2604
|
+
toEntryId: rel.to,
|
|
2605
|
+
type: rel.type,
|
|
2606
|
+
proposedBy: "user",
|
|
2607
|
+
sessionId: agentId ?? void 0,
|
|
2608
|
+
...preview ? { preview: true } : {}
|
|
2609
|
+
}
|
|
2610
|
+
);
|
|
2611
|
+
if (relResult?.preview) {
|
|
2612
|
+
relationsPreviewedCount++;
|
|
2613
|
+
} else if (relResult?.status === "agent_proposal_created") {
|
|
2614
|
+
relationsProposedCount++;
|
|
2615
|
+
} else {
|
|
2616
|
+
relationsCreatedCount++;
|
|
2617
|
+
}
|
|
2618
|
+
} catch (relErr) {
|
|
2619
|
+
const relMsg = relErr instanceof Error ? relErr.message : String(relErr);
|
|
2620
|
+
relationsFailedList.push(`${rel.to} (${rel.type}): ${relMsg}`);
|
|
2621
|
+
}
|
|
2622
|
+
}
|
|
2623
|
+
if (relationsFailedList.length > 0) {
|
|
2624
|
+
batchEntryWarnings.push(`${relationsFailedList.length} inline relation(s) failed: ${relationsFailedList.join("; ")}`);
|
|
2625
|
+
}
|
|
2626
|
+
if (relationsPreviewedCount > 0) {
|
|
2627
|
+
batchEntryWarnings.push(`${relationsPreviewedCount} inline relation(s) would be created (preview \u2014 no DB writes).`);
|
|
2628
|
+
}
|
|
2629
|
+
if (relationsProposedCount > 0) {
|
|
2630
|
+
batchEntryWarnings.push(`${relationsProposedCount} inline relation(s) converted to an agent proposal (misuse pattern) \u2014 review in Cortex UI.`);
|
|
2631
|
+
}
|
|
2632
|
+
}
|
|
2633
|
+
if (autoCommitApplied && !batchWasAutoCommittedServerSide) {
|
|
2634
|
+
try {
|
|
2635
|
+
const semanticConflicts = await discoverSemanticConflicts(entry.name, entry.description, resolvedSlug);
|
|
2636
|
+
const commitResult = await kernelMutation("chain.commitEntry", {
|
|
2637
|
+
entryId: finalEntryId,
|
|
2638
|
+
author: agentId ? `agent:${agentId}` : void 0,
|
|
2639
|
+
sessionId: agentId ?? void 0,
|
|
2640
|
+
...semanticConflicts.length > 0 ? { conflicts: semanticConflicts } : {}
|
|
2570
2641
|
});
|
|
2642
|
+
const refusalReason = coherencyRefusalReason(commitResult);
|
|
2643
|
+
if (refusalReason) {
|
|
2644
|
+
commitError = `coherency gate refused this accept \u2014 ${refusalReason}`;
|
|
2645
|
+
commitRefusal = commitResult?.refusal ?? void 0;
|
|
2646
|
+
finalStatus = "draft_on_failure";
|
|
2647
|
+
} else {
|
|
2648
|
+
finalStatus = commitResult?.status === "proposal_created" ? "proposed" : "committed";
|
|
2649
|
+
contradictionAdvisory = commitResult?.contradictionAdvisory ?? void 0;
|
|
2650
|
+
if (finalStatus === "committed") {
|
|
2651
|
+
await recordSessionActivity({ entryModified: internalId });
|
|
2652
|
+
trackChainEntryCommitted(wsCtx.workspaceId, {
|
|
2653
|
+
entry_id: finalEntryId,
|
|
2654
|
+
collection: resolvedSlug ?? void 0,
|
|
2655
|
+
commit_method: "auto",
|
|
2656
|
+
surface: "mcp_capture"
|
|
2657
|
+
});
|
|
2658
|
+
}
|
|
2659
|
+
}
|
|
2660
|
+
} catch (error) {
|
|
2661
|
+
commitError = error instanceof Error ? error.message : String(error);
|
|
2662
|
+
finalStatus = "draft_on_failure";
|
|
2663
|
+
await recordCommitFailure({ entryId: finalEntryId, error, sessionId: agentId, server });
|
|
2571
2664
|
}
|
|
2572
2665
|
}
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2666
|
+
const entryNorm = result2.normalization;
|
|
2667
|
+
results.push({
|
|
2668
|
+
entryIdx,
|
|
2669
|
+
name: entry.name,
|
|
2670
|
+
collection: resolvedSlug,
|
|
2671
|
+
entryId: finalEntryId,
|
|
2672
|
+
ok: true,
|
|
2673
|
+
autoLinks: autoLinkCount,
|
|
2674
|
+
advisedLinks: advisedLinkCount,
|
|
2675
|
+
status: finalStatus,
|
|
2676
|
+
classifiedBy,
|
|
2677
|
+
confidence,
|
|
2678
|
+
confidenceTier,
|
|
2679
|
+
...commitError ? { commitError } : {},
|
|
2680
|
+
// WP-465 surface parity: thread full refusal payload for coherency-refused batch entries.
|
|
2681
|
+
...commitRefusal ? { commitRefusal } : {},
|
|
2682
|
+
// WP-485 Slice 2b (R2, FEAT-1370): the server's contradiction advisory (DEC-1321 —
|
|
2683
|
+
// advisory only, never blocking) — visible, never a silent success.
|
|
2684
|
+
...contradictionAdvisory ? { contradictionAdvisory } : {},
|
|
2685
|
+
...batchEntryWarnings.length > 0 ? { warnings: batchEntryWarnings } : {},
|
|
2686
|
+
...entryNorm && (Object.keys(entryNorm.remapped).length > 0 || entryNorm.rejected.length > 0) && {
|
|
2687
|
+
normalization: { remapped: entryNorm.remapped, rejected: entryNorm.rejected }
|
|
2688
|
+
},
|
|
2689
|
+
// BET-167: Track overlap count for conflict advisory
|
|
2690
|
+
...entryOverlapCount > 0 ? { overlapCount: entryOverlapCount } : {},
|
|
2691
|
+
// TEN-2365: capture-time authority-domain proposal echo.
|
|
2692
|
+
...result2.authorityDomain ? { authorityDomain: result2.authorityDomain } : {},
|
|
2693
|
+
// TEN-957 (WP-484 S2): inline relations created for this entry.
|
|
2694
|
+
...relationsCreatedCount > 0 ? { relationsCreated: relationsCreatedCount } : {},
|
|
2695
|
+
// Finding #14: distinct from relationsCreated — never counted as a write.
|
|
2696
|
+
...relationsProposedCount > 0 ? { relationsProposed: relationsProposedCount } : {}
|
|
2697
|
+
});
|
|
2577
2698
|
}
|
|
2578
|
-
}
|
|
2579
|
-
const entryNorm = result2.normalization;
|
|
2580
|
-
results.push({
|
|
2581
|
-
name: entry.name,
|
|
2582
|
-
collection: resolvedSlug,
|
|
2583
|
-
entryId: finalEntryId,
|
|
2584
|
-
ok: true,
|
|
2585
|
-
autoLinks: autoLinkCount,
|
|
2586
|
-
advisedLinks: advisedLinkCount,
|
|
2587
|
-
status: finalStatus,
|
|
2588
|
-
classifiedBy,
|
|
2589
|
-
confidence,
|
|
2590
|
-
confidenceTier,
|
|
2591
|
-
...commitError ? { commitError } : {},
|
|
2592
|
-
// WP-465 surface parity: thread full refusal payload for coherency-refused batch entries.
|
|
2593
|
-
...commitRefusal ? { commitRefusal } : {},
|
|
2594
|
-
// WP-485 Slice 2b (R2, FEAT-1370): the server's contradiction advisory (DEC-1321 —
|
|
2595
|
-
// advisory only, never blocking) — visible, never a silent success.
|
|
2596
|
-
...contradictionAdvisory ? { contradictionAdvisory } : {},
|
|
2597
|
-
...batchEntryWarnings.length > 0 ? { warnings: batchEntryWarnings } : {},
|
|
2598
|
-
...entryNorm && (Object.keys(entryNorm.remapped).length > 0 || entryNorm.rejected.length > 0) && {
|
|
2599
|
-
normalization: { remapped: entryNorm.remapped, rejected: entryNorm.rejected }
|
|
2600
|
-
},
|
|
2601
|
-
// BET-167: Track overlap count for conflict advisory
|
|
2602
|
-
...entryOverlapCount > 0 ? { overlapCount: entryOverlapCount } : {},
|
|
2603
|
-
// TEN-2365: capture-time authority-domain proposal echo.
|
|
2604
|
-
...result2.authorityDomain ? { authorityDomain: result2.authorityDomain } : {},
|
|
2605
|
-
// TEN-957 (WP-484 S2): inline relations created for this entry.
|
|
2606
|
-
...relationsCreatedCount > 0 ? { relationsCreated: relationsCreatedCount } : {},
|
|
2607
|
-
// Finding #14: distinct from relationsCreated — never counted as a write.
|
|
2608
|
-
...relationsProposedCount > 0 ? { relationsProposed: relationsProposedCount } : {}
|
|
2609
2699
|
});
|
|
2700
|
+
if (job) chunkBytes += prospectiveJobBytes;
|
|
2610
2701
|
} catch (error) {
|
|
2611
2702
|
const msg = error instanceof Error ? error.message : String(error);
|
|
2612
2703
|
results.push({
|
|
2704
|
+
entryIdx,
|
|
2613
2705
|
name: entry.name,
|
|
2614
2706
|
collection: resolvedSlug,
|
|
2615
2707
|
entryId: "",
|
|
@@ -2624,6 +2716,7 @@ async function handleBatchCapture(server, { entries, autoCommit, preview }) {
|
|
|
2624
2716
|
});
|
|
2625
2717
|
}
|
|
2626
2718
|
}
|
|
2719
|
+
await flushPendingChunk(pendingFinish);
|
|
2627
2720
|
const created = results.filter((r) => r.ok);
|
|
2628
2721
|
const failed = results.filter((r) => !r.ok);
|
|
2629
2722
|
const committed = created.filter((r) => r.status === "committed");
|
|
@@ -2835,8 +2928,13 @@ _Use \`entries action=move\` to correct any misclassified entries._`);
|
|
|
2835
2928
|
}))
|
|
2836
2929
|
},
|
|
2837
2930
|
...failed.length > 0 && {
|
|
2931
|
+
// PR #392 round 2 (Codex, finding 2): `r.entryIdx` is the ORIGINAL input
|
|
2932
|
+
// position, carried explicitly since the moment each result was built —
|
|
2933
|
+
// NEVER `results.indexOf(r)` (the chunked pipeline pushes results in a
|
|
2934
|
+
// different order than `entries`' input order, so that would silently
|
|
2935
|
+
// report the wrong index for a batch with a mix of early/late failures).
|
|
2838
2936
|
failedEntries: failed.map((r) => ({
|
|
2839
|
-
index:
|
|
2937
|
+
index: r.entryIdx,
|
|
2840
2938
|
collection: r.collection,
|
|
2841
2939
|
name: r.name,
|
|
2842
2940
|
error: r.error ?? "unknown error"
|
|
@@ -15548,4 +15646,4 @@ export {
|
|
|
15548
15646
|
createProductBrainServer,
|
|
15549
15647
|
initFeatureFlags
|
|
15550
15648
|
};
|
|
15551
|
-
//# sourceMappingURL=chunk-
|
|
15649
|
+
//# sourceMappingURL=chunk-Y52AWERD.js.map
|