@productbrain/mcp 0.0.1-beta.66 → 0.0.1-beta.68
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/{chunk-4IQ7A5R4.js → chunk-OI3Q6G7U.js} +117 -40
- package/dist/chunk-OI3Q6G7U.js.map +1 -0
- package/dist/{chunk-UWILSX73.js → chunk-TH5AUVVM.js} +310 -148
- package/dist/chunk-TH5AUVVM.js.map +1 -0
- package/dist/http.js +2 -2
- package/dist/index.js +2 -2
- package/dist/{smart-capture-EGTUM4XP.js → smart-capture-Q64ZXK65.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-4IQ7A5R4.js.map +0 -1
- package/dist/chunk-UWILSX73.js.map +0 -1
- /package/dist/{smart-capture-EGTUM4XP.js.map → smart-capture-Q64ZXK65.js.map} +0 -0
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
registerSmartCaptureTools,
|
|
32
32
|
requireActiveSession,
|
|
33
33
|
requireWriteAccess,
|
|
34
|
+
resolveCollection,
|
|
34
35
|
runWithToolContext,
|
|
35
36
|
setSessionOriented,
|
|
36
37
|
startAgentSession,
|
|
@@ -42,7 +43,7 @@ import {
|
|
|
42
43
|
unknownAction,
|
|
43
44
|
validationResult,
|
|
44
45
|
withEnvelope
|
|
45
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-TH5AUVVM.js";
|
|
46
47
|
import {
|
|
47
48
|
trackKnowledgeGap,
|
|
48
49
|
trackQualityCheck,
|
|
@@ -237,7 +238,7 @@ ${formatted}` }],
|
|
|
237
238
|
},
|
|
238
239
|
withEnvelope(async ({ entryId }) => {
|
|
239
240
|
requireWriteAccess();
|
|
240
|
-
const { runContradictionCheck } = await import("./smart-capture-
|
|
241
|
+
const { runContradictionCheck } = await import("./smart-capture-Q64ZXK65.js");
|
|
241
242
|
const entry = await mcpQuery("chain.getEntry", { entryId });
|
|
242
243
|
if (!entry) {
|
|
243
244
|
return notFoundResult(entryId, `Entry '${entryId}' not found. Try search to find the right ID.`);
|
|
@@ -364,14 +365,15 @@ function sanitizeEntryData(data) {
|
|
|
364
365
|
);
|
|
365
366
|
return Object.keys(filtered).length > 0 ? filtered : void 0;
|
|
366
367
|
}
|
|
367
|
-
var ENTRIES_ACTIONS = ["list", "get", "batch", "search"];
|
|
368
|
+
var ENTRIES_ACTIONS = ["list", "get", "batch", "search", "move"];
|
|
368
369
|
var entriesSchema = z2.object({
|
|
369
370
|
action: z2.enum(ENTRIES_ACTIONS).describe(
|
|
370
|
-
"'list': browse entries with filters. 'get': fetch one entry by ID. 'batch': fetch multiple entries. 'search': full-text search."
|
|
371
|
+
"'list': browse entries with filters. 'get': fetch one entry by ID. 'batch': fetch multiple entries. 'search': full-text search. 'move': move entry to a different collection."
|
|
371
372
|
),
|
|
372
|
-
entryId: z2.string().optional().describe("Entry ID for get action, e.g. '
|
|
373
|
+
entryId: z2.string().optional().describe("Entry ID for get/move action, e.g. 'DEC-42', 'BR-001'"),
|
|
373
374
|
entryIds: z2.array(z2.string()).min(1).max(20).optional().describe("Entry IDs for batch action, e.g. ['TYPE-strategy', 'STR-jljeg7']"),
|
|
374
375
|
collection: z2.string().optional().describe("Collection slug for list/search, e.g. 'glossary', 'tracking-events', 'business-rules'"),
|
|
376
|
+
toCollection: z2.string().optional().describe("Target collection slug for move action, e.g. 'decisions', 'architecture'"),
|
|
375
377
|
status: z2.string().optional().describe("Filter: draft | active | deprecated | archived"),
|
|
376
378
|
tag: z2.string().optional().describe("Filter by internal tag for list"),
|
|
377
379
|
label: z2.string().optional().describe("Filter by label slug for list \u2014 matches entries across all collections"),
|
|
@@ -426,14 +428,14 @@ function registerEntriesTools(server) {
|
|
|
426
428
|
"entries",
|
|
427
429
|
{
|
|
428
430
|
title: "Entries",
|
|
429
|
-
description: 'Read entries from the Chain. One tool for all entry reading.\n\n- **list**: Browse entries with optional filters (collection, status, tag, label). Use collections action=list first to discover slugs.\n- **get**: Fetch a single entry by ID \u2014 full record with data, labels, relations, history.\n- **batch**: Fetch multiple entries (max 20) in one call. Same shape as get per entry.\n- **search**: Full-text search across entries. Scope by collection or filter by status.\n\nUse `entries action=get entryId="..."` to fetch one. Use `entries action=search query="..."` to discover.',
|
|
431
|
+
description: 'Read entries from the Chain. One tool for all entry reading.\n\n- **list**: Browse entries with optional filters (collection, status, tag, label). Use collections action=list first to discover slugs.\n- **get**: Fetch a single entry by ID \u2014 full record with data, labels, relations, history.\n- **batch**: Fetch multiple entries (max 20) in one call. Same shape as get per entry.\n- **search**: Full-text search across entries. Scope by collection or filter by status.\n- **move**: Move an entry to a different collection. Use when classifier misrouted or user wants to reclassify.\n\nUse `entries action=get entryId="..."` to fetch one. Use `entries action=search query="..."` to discover.',
|
|
430
432
|
inputSchema: entriesSchema,
|
|
431
|
-
annotations: {
|
|
433
|
+
annotations: { idempotentHint: false, openWorldHint: false }
|
|
432
434
|
},
|
|
433
435
|
withEnvelope(async (args) => {
|
|
434
436
|
const parsed = parseOrFail(entriesSchema, args);
|
|
435
437
|
if (!parsed.ok) return parsed.result;
|
|
436
|
-
const { action, entryId, entryIds, collection, status, tag, label, query } = parsed.data;
|
|
438
|
+
const { action, entryId, entryIds, collection, toCollection, status, tag, label, query } = parsed.data;
|
|
437
439
|
return runWithToolContext({ tool: "entries", action }, async () => {
|
|
438
440
|
if (action === "get") {
|
|
439
441
|
if (!entryId) {
|
|
@@ -456,6 +458,11 @@ function registerEntriesTools(server) {
|
|
|
456
458
|
if (action === "list") {
|
|
457
459
|
return handleList(collection, status, tag, label);
|
|
458
460
|
}
|
|
461
|
+
if (action === "move") {
|
|
462
|
+
if (!entryId) return validationResult("entryId is required when action is 'move'.");
|
|
463
|
+
if (!toCollection) return validationResult("toCollection is required when action is 'move'.");
|
|
464
|
+
return handleMove(entryId, toCollection);
|
|
465
|
+
}
|
|
459
466
|
return unknownAction(action, ENTRIES_ACTIONS);
|
|
460
467
|
});
|
|
461
468
|
})
|
|
@@ -657,6 +664,41 @@ ${formatted}` }],
|
|
|
657
664
|
structuredContent: success(`Found ${total} entries${scope}.`, { entries: structuredEntries, total })
|
|
658
665
|
};
|
|
659
666
|
}
|
|
667
|
+
async function handleMove(entryId, toCollection) {
|
|
668
|
+
try {
|
|
669
|
+
const result = await mcpMutation("chain.moveToCollection", { entryId, toCollectionSlug: toCollection });
|
|
670
|
+
const lines = [
|
|
671
|
+
`## Move Result`,
|
|
672
|
+
"",
|
|
673
|
+
`Moved **${result.entryId}** from \`${result.fromCollection}\` \u2192 \`${result.toCollection}\``
|
|
674
|
+
];
|
|
675
|
+
if (result.workflowStatusReset) {
|
|
676
|
+
lines.push(``, `\u26A0\uFE0F Workflow status \`${result.previousWorkflowStatus}\` was reset (incompatible with target collection).`);
|
|
677
|
+
}
|
|
678
|
+
return {
|
|
679
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
680
|
+
structuredContent: success(
|
|
681
|
+
`Moved ${result.entryId} from ${result.fromCollection} to ${result.toCollection}.`,
|
|
682
|
+
result,
|
|
683
|
+
[
|
|
684
|
+
{ tool: "entries", description: "View updated entry", parameters: { action: "get", entryId } },
|
|
685
|
+
{ tool: "quality", description: "Re-check quality", parameters: { action: "check", entryId } }
|
|
686
|
+
]
|
|
687
|
+
)
|
|
688
|
+
};
|
|
689
|
+
} catch (error) {
|
|
690
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
691
|
+
const isNotFound = msg.includes("not found");
|
|
692
|
+
if (isNotFound) return notFoundResult(entryId, `Could not move entry: ${msg}`);
|
|
693
|
+
return failureResult(
|
|
694
|
+
`Could not move **${entryId}** to \`${toCollection}\`: ${msg}`,
|
|
695
|
+
"MOVE_FAILED",
|
|
696
|
+
msg,
|
|
697
|
+
"Check the entry ID and target collection slug, then retry.",
|
|
698
|
+
[{ tool: "entries", description: "Search for entry", parameters: { action: "search", query: entryId } }]
|
|
699
|
+
);
|
|
700
|
+
}
|
|
701
|
+
}
|
|
660
702
|
async function handleSearch(server, query, collection, status) {
|
|
661
703
|
const scope = collection ? ` in \`${collection}\`` : "";
|
|
662
704
|
await server.sendLoggingMessage({
|
|
@@ -3053,7 +3095,7 @@ If any facilitate call fails:
|
|
|
3053
3095
|
label: "De-risk \u2014 Rabbit Holes & No-Gos",
|
|
3054
3096
|
type: "open",
|
|
3055
3097
|
instruction: "What could go wrong? What are we NOT building? Walk through the solution slowly and find the risks.",
|
|
3056
|
-
facilitatorGuidance: "**Investigate first.** Read the investigationBrief. Spawn sub-agents to search the codebase for fragile code, tight coupling, missing tests, performance-sensitive paths, and external dependencies near the affected modules. Propose risks with evidence: 'I found that X module has no tests and is tightly coupled to Y \u2014 this is a rabbit hole.' Every confirmed risk MUST be captured with its own respond call: `facilitate action=respond betEntryId='...' dimension='risks' source='user_reaction' userInput='...' capture={type:'risk', name:'Risk Name', description:'What could go wrong', theme:'implementation'}`. Each becomes a tensions entry linked to the bet via constrains. Push for mitigations \u2014 every risk needs a patch or explicit acceptance. Then declare no-gos: 'Based on what I've seen, I'd suggest these no-gos.' Every no-go MUST use capture: `facilitate action=respond betEntryId='...' dimension='boundaries' source='user_reaction' userInput='...' capture={type:'noGo', name:'No-Go Title', description:'Why we are not doing this'}`. Without the `capture` parameter on each call, the item is NOT saved \u2014 you will get a WARNING. When risks score 6+ and boundaries score 4+, present Shape Go gate: 'Is this buildable within the appetite?'",
|
|
3098
|
+
facilitatorGuidance: "**Investigate first.** Read the investigationBrief. Spawn sub-agents to search the codebase for fragile code, tight coupling, missing tests, performance-sensitive paths, and external dependencies near the affected modules. Propose risks with evidence: 'I found that X module has no tests and is tightly coupled to Y \u2014 this is a rabbit hole.' Every confirmed risk MUST be captured with its own respond call: `facilitate action=respond betEntryId='...' dimension='risks' source='user_reaction' userInput='...' capture={type:'risk', name:'Risk Name', description:'What could go wrong', theme:'implementation'}`. Each becomes a tensions entry linked to the bet via constrains. Push for mitigations \u2014 every risk needs a patch or explicit acceptance. Then declare no-gos: 'Based on what I've seen, I'd suggest these no-gos.' Every no-go MUST use capture: `facilitate action=respond betEntryId='...' dimension='boundaries' source='user_reaction' userInput='...' capture={type:'noGo', name:'No-Go Title', description:'Why we are not doing this'}`. Without the `capture` parameter on each call, the item is NOT saved \u2014 you will get a WARNING. **Counter-Metric Mandate (STD-19):** If the derisking references any quantitative gates or metrics (accuracy targets, performance budgets, adoption thresholds), stress-test them: 'What's the denominator? What gets excluded? What counter-metric would expose a false positive?' A metric gate that can be gamed by abstaining or cherry-picking the population is not a gate \u2014 name the compound metric that can't be gamed. When risks score 6+ and boundaries score 4+, present Shape Go gate: 'Is this buildable within the appetite?'",
|
|
3057
3099
|
questions: [
|
|
3058
3100
|
{
|
|
3059
3101
|
id: "shape-go",
|
|
@@ -3079,7 +3121,7 @@ If any facilitate call fails:
|
|
|
3079
3121
|
label: "Validate & Build Contract",
|
|
3080
3122
|
type: "synthesis",
|
|
3081
3123
|
instruction: "Check completeness. Generate the build contract. Review the full scorecard.",
|
|
3082
|
-
facilitatorGuidance: "Call `facilitate action=score` to get the full scorecard. Present it as a table. Check: does the response include a buildContract? If captureReady is true, it should. Verify the 5 core ingredients: Problem, Appetite, Solution elements, Rabbit Holes, No-Gos. For Big Batch: also verify Architecture, narrative hook, and value-flow annotations. Present the build contract. Ask: 'Anything to adjust before we capture to the Chain?'",
|
|
3124
|
+
facilitatorGuidance: "Call `facilitate action=score` to get the full scorecard. Present it as a table. Check: does the response include a buildContract? If captureReady is true, it should. Verify the 5 core ingredients: Problem, Appetite, Solution elements, Rabbit Holes, No-Gos. For Big Batch: also verify Architecture, narrative hook, and value-flow annotations. **Counter-Metric Mandate (STD-19):** If the scorecard or build contract contains metrics or gates, verify each has a denominator, a coverage rate, and a counter-metric. Flag any gate that can be satisfied by abstaining or excluding the hard cases. Present the build contract. Ask: 'Anything to adjust before we capture to the Chain?'",
|
|
3083
3125
|
outputSchema: {
|
|
3084
3126
|
field: "validation",
|
|
3085
3127
|
description: "Completeness check result and build contract",
|
|
@@ -3194,7 +3236,18 @@ var IMPLEMENTATION_REVIEW_WORKFLOW_DESCRIPTOR = {
|
|
|
3194
3236
|
|
|
3195
3237
|
## Sub-Agent Classification (for test failures)
|
|
3196
3238
|
|
|
3197
|
-
When reviewing test results: (a) test staleness \u2014 code changed, test not updated; (b) regression \u2014 code broke behavior; (c) flaky/bad test \u2014 harness or timing issue
|
|
3239
|
+
When reviewing test results: (a) test staleness \u2014 code changed, test not updated; (b) regression \u2014 code broke behavior; (c) flaky/bad test \u2014 harness or timing issue.
|
|
3240
|
+
|
|
3241
|
+
## Structured Verdict (CRITICAL)
|
|
3242
|
+
|
|
3243
|
+
Round 05 MUST end with a structured verdict block containing exactly these five items:
|
|
3244
|
+
1. **Verdict:** Y (ship) or N (do not ship) \u2014 one word, no hedging.
|
|
3245
|
+
2. **What shipped:** One sentence describing what was built.
|
|
3246
|
+
3. **Why it matters:** One sentence on the problem this solves.
|
|
3247
|
+
4. **User benefit:** One sentence on the value for users.
|
|
3248
|
+
5. **How to validate:** One sentence on how to verify it works as intended.
|
|
3249
|
+
|
|
3250
|
+
This block is the final deliverable of the review. Everything else is supporting evidence.`,
|
|
3198
3251
|
rounds: [
|
|
3199
3252
|
{
|
|
3200
3253
|
id: "orient",
|
|
@@ -3230,7 +3283,7 @@ When reviewing test results: (a) test staleness \u2014 code changed, test not up
|
|
|
3230
3283
|
label: "Code & Test Honesty",
|
|
3231
3284
|
type: "open",
|
|
3232
3285
|
instruction: "Spawn sub-agents to review implementation and tests for the stated scope only. Did we meet high standards? Are tests validating real behavior or did we edit them just to pass?",
|
|
3233
|
-
facilitatorGuidance: "Restrict all review to the scope stated in Round 01 (by default, work in this conversation only). Spawn 1\u20132 sub-agents in parallel: (1) explore agent \u2014 code review, architecture boundaries, type-safety for scoped files only. (2) generalPurpose agent \u2014 test review for scoped code: are tests asserting real behavior or were they edited to pass? Pass the scope (files/BET) explicitly to sub-agents so they do not touch other work. Use Context7 (query-docs) for relevant testing and framework best practices if needed. Classify any test failures: staleness, regression, or flaky. Synthesize: implementation grade, test honesty verdict, refactoring suggestions (within scope only).",
|
|
3286
|
+
facilitatorGuidance: "Restrict all review to the scope stated in Round 01 (by default, work in this conversation only). Spawn 1\u20132 sub-agents in parallel: (1) explore agent \u2014 code review, architecture boundaries, type-safety for scoped files only. (2) generalPurpose agent \u2014 test review for scoped code: are tests asserting real behavior or were they edited to pass? Pass the scope (files/BET) explicitly to sub-agents so they do not touch other work. Use Context7 (query-docs) for relevant testing and framework best practices if needed. Classify any test failures: staleness, regression, or flaky. **Counter-Metric Mandate (STD-19):** When reporting test coverage, accuracy, or any quantitative result, include the denominator, what was excluded, and at least one counter-metric. Never report accuracy without recall. Never report pass rate without coverage. Synthesize: implementation grade, test honesty verdict, refactoring suggestions (within scope only).",
|
|
3234
3287
|
outputSchema: {
|
|
3235
3288
|
field: "codeAndTests",
|
|
3236
3289
|
description: "Implementation grade, test honesty, refactor suggestions",
|
|
@@ -3258,10 +3311,10 @@ When reviewing test results: (a) test staleness \u2014 code changed, test not up
|
|
|
3258
3311
|
label: "Synthesis & Sign-Off",
|
|
3259
3312
|
type: "commit",
|
|
3260
3313
|
instruction: "Summarize the review. Answer: Does this bring us closer to our vision and make our code and architecture cleaner? Refactoring needed? Ship or conditional? End with BET/chain IDs.",
|
|
3261
|
-
facilitatorGuidance: "Present the full synthesis: standards pass/fail, code grade, test honesty, chain validation. Explicitly answer: Does this bring us closer to our vision and make our code and architecture cleaner? Recommend: ship, ship with conditions, or do not ship. CRITICAL: The output MUST end with one sentence: 'BET/feature IDs reviewed: [IDs]. [One-line summary].' Example: 'BET-xxx, STD-xxx reviewed. Conditional ship \u2014 fix [specific issues] and add [missing tests].'",
|
|
3314
|
+
facilitatorGuidance: "Present the full synthesis: standards pass/fail, code grade, test honesty, chain validation. Explicitly answer: Does this bring us closer to our vision and make our code and architecture cleaner? **Counter-Metric Mandate (STD-19):** For EVERY quantitative result you present, you MUST include: (1) the denominator \u2014 what is the total population measured, (2) the coverage/abstention rate \u2014 what was excluded, (3) at least one counter-metric that tells the opposite story (recall vs precision, error rate vs success rate), (4) the 'student exam' reframe \u2014 score on the full exam, not just questions answered. **Red-team your own synthesis:** Before presenting, ask yourself: 'What's the worst honest interpretation of these numbers? What metric looks good but hides a real problem? What would a skeptic challenge?' Present that alongside the headline. Recommend: ship, ship with conditions, or do not ship. CRITICAL: The output MUST end with one sentence: 'BET/feature IDs reviewed: [IDs]. [One-line summary].' Example: 'BET-xxx, STD-xxx reviewed. Conditional ship \u2014 fix [specific issues] and add [missing tests].' **Structured Verdict Block (REQUIRED):** After the full synthesis, present the verdict block with exactly 5 items: (1) Verdict: Y or N \u2014 one word. (2) What shipped: one sentence. (3) Why it matters: one sentence on the problem solved. (4) User benefit: one sentence on value for users. (5) How to validate: one sentence on verification. This block is the final deliverable. Everything else is supporting evidence.",
|
|
3262
3315
|
outputSchema: {
|
|
3263
3316
|
field: "synthesis",
|
|
3264
|
-
description: "Full review synthesis with BET/chain IDs",
|
|
3317
|
+
description: "Full review synthesis with BET/chain IDs and structured verdict block (verdict Y/N, what shipped, why it matters, user benefit, how to validate)",
|
|
3265
3318
|
format: "structured"
|
|
3266
3319
|
},
|
|
3267
3320
|
maxDurationHint: "5 min"
|
|
@@ -3272,7 +3325,7 @@ When reviewing test results: (a) test staleness \u2014 code changed, test not up
|
|
|
3272
3325
|
label: "Capture & Close",
|
|
3273
3326
|
type: "close",
|
|
3274
3327
|
instruction: "Finalize the review as an insight draft. Use session-wrapup. Thank the participant.",
|
|
3275
|
-
facilitatorGuidance: "Summarize the review for finalization. Complete the terminal round through `workflows action=checkpoint` with `isFinal=true` so the workflow substrate creates the draft insight record. Include: BET/feature IDs, verdict, key findings. Run session-wrapup before closing. Thank the participant. Remind them to commit-entry when ready.",
|
|
3328
|
+
facilitatorGuidance: "Summarize the review for finalization. Complete the terminal round through `workflows action=checkpoint` with `isFinal=true` so the workflow substrate creates the draft insight record. Include: BET/feature IDs, verdict, key findings, and the structured verdict block from Round 05. The insight description MUST include the 5-item verdict block (verdict Y/N, what shipped, why it matters, user benefit, how to validate). Run session-wrapup before closing. Thank the participant. Remind them to commit-entry when ready.",
|
|
3276
3329
|
outputSchema: {
|
|
3277
3330
|
field: "capture",
|
|
3278
3331
|
description: "Insight entry created, BET IDs referenced",
|
|
@@ -3853,6 +3906,7 @@ This checkpoint was NOT saved. The conversation context is preserved \u2014 cont
|
|
|
3853
3906
|
runId
|
|
3854
3907
|
);
|
|
3855
3908
|
}
|
|
3909
|
+
const resolvedSummaryCapture = summaryCapture;
|
|
3856
3910
|
const existingRun = await mcpQuery(
|
|
3857
3911
|
"chainwork.getLatestWorkflowRun",
|
|
3858
3912
|
{
|
|
@@ -3866,6 +3920,15 @@ This checkpoint was NOT saved. The conversation context is preserved \u2014 cont
|
|
|
3866
3920
|
);
|
|
3867
3921
|
}
|
|
3868
3922
|
try {
|
|
3923
|
+
let resolvedCollectionSlug;
|
|
3924
|
+
if (resolvedSummaryCapture.routing.mode === "classifier") {
|
|
3925
|
+
const classifyName = summaryName ?? wf.name;
|
|
3926
|
+
const classifyDesc = summaryDescription ?? outputPreview;
|
|
3927
|
+
const resolved = await resolveCollection({ name: classifyName, description: classifyDesc });
|
|
3928
|
+
if (resolved && resolved.tier !== "low") {
|
|
3929
|
+
resolvedCollectionSlug = resolved.collection;
|
|
3930
|
+
}
|
|
3931
|
+
}
|
|
3869
3932
|
const result = await mcpMutation("chainwork.finalizeWorkflowRun", {
|
|
3870
3933
|
agentSessionId,
|
|
3871
3934
|
workflowId: wf.id,
|
|
@@ -3883,22 +3946,23 @@ This checkpoint was NOT saved. The conversation context is preserved \u2014 cont
|
|
|
3883
3946
|
finalRoundId: roundId,
|
|
3884
3947
|
finalOutput: normalizedOutput,
|
|
3885
3948
|
summaryCapture: {
|
|
3886
|
-
routing:
|
|
3949
|
+
routing: resolvedSummaryCapture.routing.mode === "fixed" ? {
|
|
3887
3950
|
mode: "fixed",
|
|
3888
|
-
collection:
|
|
3951
|
+
collection: resolvedSummaryCapture.routing.collection
|
|
3889
3952
|
} : {
|
|
3890
3953
|
mode: "classifier"
|
|
3891
3954
|
},
|
|
3892
|
-
nameTemplate:
|
|
3893
|
-
descriptionField:
|
|
3894
|
-
descriptionSource:
|
|
3955
|
+
nameTemplate: resolvedSummaryCapture.nameTemplate,
|
|
3956
|
+
descriptionField: resolvedSummaryCapture.descriptionField,
|
|
3957
|
+
descriptionSource: resolvedSummaryCapture.descriptionSource
|
|
3895
3958
|
},
|
|
3896
3959
|
summaryDescription,
|
|
3897
|
-
summaryName
|
|
3960
|
+
summaryName,
|
|
3961
|
+
resolvedCollectionSlug
|
|
3898
3962
|
});
|
|
3899
3963
|
lines.push(
|
|
3900
3964
|
result.summary.created ? `**Draft Created**: \`${result.summary.entryId}\`` : `**Draft Already Exists**: \`${result.summary.entryId}\``,
|
|
3901
|
-
`Collection: \`${result.summary.collection ?? (
|
|
3965
|
+
`Collection: \`${result.summary.collection ?? (resolvedSummaryCapture.routing.mode === "fixed" ? resolvedSummaryCapture.routing.collection : "classifier-routed")}\``,
|
|
3902
3966
|
`Name: ${result.summary.name}`,
|
|
3903
3967
|
"",
|
|
3904
3968
|
`The summary is captured as a draft. Use \`commit-entry entryId="${result.summary.entryId}"\` to promote it to the Chain.`,
|
|
@@ -3912,7 +3976,7 @@ This checkpoint was NOT saved. The conversation context is preserved \u2014 cont
|
|
|
3912
3976
|
entryId: result.summary.entryId,
|
|
3913
3977
|
workflowId,
|
|
3914
3978
|
roundId,
|
|
3915
|
-
collection: result.summary.collection ?? (
|
|
3979
|
+
collection: result.summary.collection ?? (resolvedSummaryCapture.routing.mode === "fixed" ? resolvedSummaryCapture.routing.collection : null),
|
|
3916
3980
|
isFinal: true,
|
|
3917
3981
|
runId: result.runId,
|
|
3918
3982
|
created: result.summary.created
|
|
@@ -3938,8 +4002,8 @@ This checkpoint was NOT saved. The conversation context is preserved \u2014 cont
|
|
|
3938
4002
|
"",
|
|
3939
4003
|
`The workflow output is preserved in this conversation. `,
|
|
3940
4004
|
`You can manually create the entry later using \`capture\` with:`,
|
|
3941
|
-
`- Collection: \`${
|
|
3942
|
-
`- Name: ${summaryName ??
|
|
4005
|
+
`- Collection: \`${resolvedSummaryCapture.routing.mode === "fixed" ? resolvedSummaryCapture.routing.collection : "classifier-routed"}\``,
|
|
4006
|
+
`- Name: ${summaryName ?? resolvedSummaryCapture.nameTemplate}`,
|
|
3943
4007
|
`- Description: ${summaryDescription ?? outputPreview}`
|
|
3944
4008
|
);
|
|
3945
4009
|
return {
|
|
@@ -5490,11 +5554,12 @@ async function processCaptures(opts) {
|
|
|
5490
5554
|
const entriesCreated = [];
|
|
5491
5555
|
let relationsCreated = 0;
|
|
5492
5556
|
const capAgentId = getAgentSessionId();
|
|
5493
|
-
const
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5557
|
+
const CAPTURE_DEFAULTS = {
|
|
5558
|
+
features: { dataField: "description", relationType: "part_of" },
|
|
5559
|
+
tensions: { dataField: "description", relationType: "constrains" },
|
|
5560
|
+
decisions: { dataField: "rationale", relationType: "informs" }
|
|
5497
5561
|
};
|
|
5562
|
+
const FALLBACK_DEFAULTS = { dataField: "description", relationType: "related_to" };
|
|
5498
5563
|
let runningBetData = { ...betData };
|
|
5499
5564
|
for (const item of captureItems) {
|
|
5500
5565
|
if (item.type === "noGo") {
|
|
@@ -5518,17 +5583,28 @@ async function processCaptures(opts) {
|
|
|
5518
5583
|
}
|
|
5519
5584
|
continue;
|
|
5520
5585
|
}
|
|
5521
|
-
const
|
|
5522
|
-
|
|
5586
|
+
const resolved = await resolveCollection({
|
|
5587
|
+
name: item.name,
|
|
5588
|
+
description: item.description,
|
|
5589
|
+
typeHint: item.type
|
|
5590
|
+
});
|
|
5591
|
+
if (!resolved) {
|
|
5592
|
+
captureErrors.push({
|
|
5593
|
+
operation: "classify",
|
|
5594
|
+
detail: `Could not resolve collection for ${item.type} "${item.name}" \u2014 skipped.`
|
|
5595
|
+
});
|
|
5596
|
+
continue;
|
|
5597
|
+
}
|
|
5598
|
+
const { dataField, relationType } = CAPTURE_DEFAULTS[resolved.collection] ?? FALLBACK_DEFAULTS;
|
|
5523
5599
|
let capturedEntryId = null;
|
|
5524
5600
|
try {
|
|
5525
5601
|
const result = await mcpMutation(
|
|
5526
5602
|
"chain.createEntry",
|
|
5527
5603
|
{
|
|
5528
|
-
collectionSlug:
|
|
5604
|
+
collectionSlug: resolved.collection,
|
|
5529
5605
|
name: item.name,
|
|
5530
5606
|
status: "draft",
|
|
5531
|
-
data: { [
|
|
5607
|
+
data: { [dataField]: item.description },
|
|
5532
5608
|
createdBy: capAgentId ? `agent:${capAgentId}` : "facilitate",
|
|
5533
5609
|
sessionId: capAgentId ?? void 0
|
|
5534
5610
|
}
|
|
@@ -5540,9 +5616,9 @@ async function processCaptures(opts) {
|
|
|
5540
5616
|
if (msg.includes("Duplicate entry") || msg.includes("already exists")) {
|
|
5541
5617
|
const fallback = await findAndLinkExisting(
|
|
5542
5618
|
item.name,
|
|
5543
|
-
|
|
5619
|
+
resolved.collection,
|
|
5544
5620
|
betEntryId,
|
|
5545
|
-
|
|
5621
|
+
relationType,
|
|
5546
5622
|
capAgentId
|
|
5547
5623
|
);
|
|
5548
5624
|
if (fallback) {
|
|
@@ -5551,7 +5627,7 @@ async function processCaptures(opts) {
|
|
|
5551
5627
|
if (fallback.linked) relationsCreated++;
|
|
5552
5628
|
captureErrors.push({
|
|
5553
5629
|
operation: "info",
|
|
5554
|
-
detail: `Linked existing ${
|
|
5630
|
+
detail: `Linked existing ${resolved.collection} entry \`${fallback.entryId}\` instead of creating duplicate.`
|
|
5555
5631
|
});
|
|
5556
5632
|
} else {
|
|
5557
5633
|
captureErrors.push({ operation: "capture", detail: `${item.type}: ${msg}` });
|
|
@@ -5565,7 +5641,7 @@ async function processCaptures(opts) {
|
|
|
5565
5641
|
await mcpMutation("chain.createEntryRelation", {
|
|
5566
5642
|
fromEntryId: capturedEntryId,
|
|
5567
5643
|
toEntryId: betEntryId,
|
|
5568
|
-
type:
|
|
5644
|
+
type: relationType,
|
|
5569
5645
|
sessionId: capAgentId ?? void 0
|
|
5570
5646
|
});
|
|
5571
5647
|
relationsCreated++;
|
|
@@ -5574,7 +5650,7 @@ async function processCaptures(opts) {
|
|
|
5574
5650
|
if (!msg.includes("already exists") && !msg.includes("Duplicate")) {
|
|
5575
5651
|
captureErrors.push({
|
|
5576
5652
|
operation: "relation",
|
|
5577
|
-
detail: `${
|
|
5653
|
+
detail: `${relationType} from ${capturedEntryId} to ${betEntryId}: ${msg}`
|
|
5578
5654
|
});
|
|
5579
5655
|
}
|
|
5580
5656
|
}
|
|
@@ -6273,7 +6349,7 @@ async function handleCommitConstellation(args) {
|
|
|
6273
6349
|
}
|
|
6274
6350
|
let contradictionWarnings = [];
|
|
6275
6351
|
try {
|
|
6276
|
-
const { runContradictionCheck } = await import("./smart-capture-
|
|
6352
|
+
const { runContradictionCheck } = await import("./smart-capture-Q64ZXK65.js");
|
|
6277
6353
|
const descField = betData.problem ?? betData.description ?? "";
|
|
6278
6354
|
contradictionWarnings = await runContradictionCheck(
|
|
6279
6355
|
betEntry.name ?? betId,
|
|
@@ -9407,6 +9483,7 @@ var CALL_CATEGORIES = {
|
|
|
9407
9483
|
"chain.searchEntries": "search",
|
|
9408
9484
|
"chain.createEntry": "write",
|
|
9409
9485
|
"chain.updateEntry": "write",
|
|
9486
|
+
"chain.moveToCollection": "write",
|
|
9410
9487
|
"chain.createEntryRelation": "write",
|
|
9411
9488
|
"chain.applyLabel": "label",
|
|
9412
9489
|
"chain.removeLabel": "label",
|
|
@@ -11675,4 +11752,4 @@ export {
|
|
|
11675
11752
|
SERVER_VERSION,
|
|
11676
11753
|
createProductBrainServer
|
|
11677
11754
|
};
|
|
11678
|
-
//# sourceMappingURL=chunk-
|
|
11755
|
+
//# sourceMappingURL=chunk-OI3Q6G7U.js.map
|