@productbrain/mcp 0.0.1-beta.11434 → 0.0.1-beta.11437
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.
|
@@ -729,7 +729,37 @@ function buildCaptureForRealNextAction(payload) {
|
|
|
729
729
|
}];
|
|
730
730
|
}
|
|
731
731
|
|
|
732
|
+
// src/lib/spineRungs.ts
|
|
733
|
+
var SPINE_RUNG_SEQUENCE = [
|
|
734
|
+
{ relationType: "validates", targetKey: "key_result", gapIfMissing: "key_result_missing" },
|
|
735
|
+
{ relationType: "part_of", targetKey: "objective", gapIfMissing: "objective_missing" },
|
|
736
|
+
{ relationType: "part_of", targetKey: "strategy", gapIfMissing: "strategy_missing" },
|
|
737
|
+
{ relationType: "part_of", targetKey: "vision", gapIfMissing: "vision_missing" },
|
|
738
|
+
{ relationType: "part_of", targetKey: "purpose", gapIfMissing: "purpose_missing" }
|
|
739
|
+
];
|
|
740
|
+
|
|
732
741
|
// src/lib/checklist.ts
|
|
742
|
+
var FIRST_SPINE_SUBJECT = "work_package";
|
|
743
|
+
var kindWord = (kind) => kind.replace(/_/g, " ");
|
|
744
|
+
var withArticle = (word) => `${/^[aeiou]/.test(word) ? "an" : "a"} ${word}`;
|
|
745
|
+
var spineSubject = (kind) => {
|
|
746
|
+
const words = withArticle(kindWord(kind));
|
|
747
|
+
return words[0].toUpperCase() + words.slice(1);
|
|
748
|
+
};
|
|
749
|
+
function rungLine(rung) {
|
|
750
|
+
const index = SPINE_RUNG_SEQUENCE.findIndex((spec) => spec.targetKey === rung);
|
|
751
|
+
if (index < 0) return null;
|
|
752
|
+
const { relationType: relationType2, targetKey } = SPINE_RUNG_SEQUENCE[index];
|
|
753
|
+
const parent = `an accepted ${kindWord(targetKey)}`;
|
|
754
|
+
const subject = spineSubject(index === 0 ? FIRST_SPINE_SUBJECT : SPINE_RUNG_SEQUENCE[index - 1].targetKey);
|
|
755
|
+
return relationType2 === "part_of" ? `${subject} hangs on ${parent} with ${relationType2}.` : `${subject} ${relationType2} ${parent}.`;
|
|
756
|
+
}
|
|
757
|
+
var SPINE_RUNG_LINES = SPINE_RUNG_SEQUENCE.map((spec) => rungLine(spec.targetKey));
|
|
758
|
+
var SPINE_LINKS_LINES = [
|
|
759
|
+
`Spine links run child to parent, each ${SPINE_RUNG_SEQUENCE[SPINE_RUNG_SEQUENCE.length - 1].relationType} the level above.`,
|
|
760
|
+
`${spineSubject(FIRST_SPINE_SUBJECT)} ${SPINE_RUNG_SEQUENCE[0].relationType} ${withArticle(kindWord(SPINE_RUNG_SEQUENCE[0].targetKey))}; informs joins no levels.`,
|
|
761
|
+
"Before accepting a spine entry, preflight it: it names what blocks."
|
|
762
|
+
];
|
|
733
763
|
var CHECKLIST_LINES = {
|
|
734
764
|
purpose: {
|
|
735
765
|
stranger_test: "Explain it so a stranger knows why this company exists",
|
|
@@ -759,14 +789,8 @@ var CHECKLIST_LINES = {
|
|
|
759
789
|
bounded: "Say by when, or how often, the measure is read",
|
|
760
790
|
moves_the_objective: "Pick a result that shows the objective is happening, not that work was done"
|
|
761
791
|
},
|
|
762
|
-
/** One line per spine rung, keyed by the rung it reaches
|
|
763
|
-
strategy_link:
|
|
764
|
-
key_result: "Link this work to an accepted key result it validates",
|
|
765
|
-
objective: "Put the key result under an accepted objective",
|
|
766
|
-
strategy: "Put the objective under an accepted strategy",
|
|
767
|
-
vision: "Put the strategy under an accepted vision",
|
|
768
|
-
purpose: "Put the vision under an accepted purpose"
|
|
769
|
-
}
|
|
792
|
+
/** One line per spine rung, keyed by the rung it reaches: rungLine, in SPINE_RUNG_SEQUENCE order (TASK-1026). */
|
|
793
|
+
strategy_link: Object.fromEntries(SPINE_RUNG_SEQUENCE.map((spec) => [spec.targetKey, rungLine(spec.targetKey)]))
|
|
770
794
|
};
|
|
771
795
|
var MARK = { met: "[x]", not_yet: "[ ]", judging: "[~]" };
|
|
772
796
|
function renderChecklist(canonicalKey, criteria, judging) {
|
|
@@ -911,8 +935,8 @@ var RELATION_BATCH_MAX = 25;
|
|
|
911
935
|
|
|
912
936
|
// src/tools/smart-capture.ts
|
|
913
937
|
var CAPTURE_LINK_OUTCOMES = ["written", "refused"];
|
|
914
|
-
var SPINE_FLOOR_SENTENCE = "kept as a draft; it can be accepted once its spine above is accepted \u2014 the promote door checks the whole spine and names the first missing rung.";
|
|
915
938
|
var SPINE_FLOOR_EXEMPT_SENTENCE = "kept as a draft, though this workspace is not yet enforcing the spine above it \u2014 it can be accepted as-is.";
|
|
939
|
+
var LINK_TYPE_DESCRIPTION = `Relation type. The spine links: ${SPINE_RUNG_LINES.join(" ")}`;
|
|
916
940
|
var captureSchema = z5.object({
|
|
917
941
|
collection: z5.string().optional().describe("Collection slug, e.g. 'tensions', 'rules', 'glossary', 'decisions'. Optional \u2014 the kernel classifies when omitted."),
|
|
918
942
|
name: z5.string().describe("Display name \u2014 be specific (e.g. 'Convex adjacency list won't scale for graph traversal')"),
|
|
@@ -924,7 +948,7 @@ var captureSchema = z5.object({
|
|
|
924
948
|
// TASK-380: mirrors whyPolicy.ts
|
|
925
949
|
links: z5.array(z5.object({
|
|
926
950
|
to: z5.string().describe("Target entry ID (e.g. '<PREFIX>-<n>')"),
|
|
927
|
-
type: z5.string().describe(
|
|
951
|
+
type: z5.string().describe(LINK_TYPE_DESCRIPTION)
|
|
928
952
|
})).optional().describe("Links written with the entry in one transaction; each returns written or refused with a reason; a refused link fails nothing."),
|
|
929
953
|
sourceRef: z5.string().optional().describe("URI or path of the source document backing this entry (e.g. 'meeting-2026-03-28.md', 'import://batch-5'). Stored as top-level entry field, not in data."),
|
|
930
954
|
sourceExcerpt: z5.string().optional().describe("Verbatim excerpt from the source that backs this entry's claims. Stored as top-level entry field, not in data."),
|
|
@@ -981,7 +1005,7 @@ var captureSuccessOutputSchema = z5.object({
|
|
|
981
1005
|
required: z5.boolean().optional()
|
|
982
1006
|
})).optional(),
|
|
983
1007
|
// TASK-160: the server's birth-floor verdict must survive the strict output contract.
|
|
984
|
-
spineFloor: z5.object({ relationType: z5.string(), parentKind: z5.string(), exempt: z5.boolean() }).optional(),
|
|
1008
|
+
spineFloor: z5.object({ relationType: z5.string(), parentKind: z5.string(), exempt: z5.boolean(), linkWritten: z5.boolean().optional() }).optional(),
|
|
985
1009
|
// WP-751 M3a-1b (TASK-189, DEC-1700): `coherencyRefusal` and `contradictionAdvisory` are deleted with the
|
|
986
1010
|
// client-side auto-commit attempt that alone populated them (its gate refusal, the commit's advisory).
|
|
987
1011
|
replayed: z5.literal(true).optional(),
|
|
@@ -1008,7 +1032,7 @@ var captureCompoundSchema = z5.object({
|
|
|
1008
1032
|
why: z5.string().max(ENTRY_BODY_MAX_CHARS).optional().describe("Why this entry exists."),
|
|
1009
1033
|
links: z5.array(z5.object({
|
|
1010
1034
|
to: z5.string().max(200).describe("Target entry ID (e.g. '<PREFIX>-<n>')"),
|
|
1011
|
-
type: z5.string().max(200).describe(
|
|
1035
|
+
type: z5.string().max(200).describe(LINK_TYPE_DESCRIPTION)
|
|
1012
1036
|
})).max(RELATION_BATCH_MAX).optional().describe("Links written with the entry in one transaction; each returns written or refused with a reason; a refused link fails nothing."),
|
|
1013
1037
|
sourceRef: z5.string().max(2e3).optional().describe("URI or path of the source document backing this entry."),
|
|
1014
1038
|
sourceExcerpt: z5.string().max(SOURCE_EXCERPT_MAX_CHARS).optional().describe("Verbatim excerpt from the source backing this entry's claims."),
|
|
@@ -1260,10 +1284,9 @@ Use \`context action=get\` to inspect the existing entry, or \`entries action=up
|
|
|
1260
1284
|
lines.push(`## Accepted: ${finalEntryId}`);
|
|
1261
1285
|
lines.push(`**${name}** added to your knowledge base.`);
|
|
1262
1286
|
} else if (spineFloor) {
|
|
1263
|
-
|
|
1264
|
-
lines.push("## Saved as draft");
|
|
1265
|
-
lines.push(
|
|
1266
|
-
lines.push(`Next: \`entries action=commit entryId="${finalEntryId}"\`.`);
|
|
1287
|
+
const { relationType: relationType2, parentKind, exempt, linkWritten } = spineFloor, id = finalEntryId, to = `<${parentKind.toUpperCase().replace(/_/g, "-")}-ID>`;
|
|
1288
|
+
lines.push("", "## Saved as draft", `**${name}** ${exempt ? SPINE_FLOOR_EXEMPT_SENTENCE : `kept as a draft. ${rungLine(parentKind)}`}`);
|
|
1289
|
+
lines.push(exempt || linkWritten ? `Next: \`entries action=commit entryId="${id}"\`.` : `Next: \`relations action=create from="${id}" type="${relationType2}" to="${to}"\`.`);
|
|
1267
1290
|
}
|
|
1268
1291
|
if (groundingCaveat) lines.push("", groundingCaveat);
|
|
1269
1292
|
const named = groundingReport.duplicates.slice(0, 3).map((d) => `${d.entryId} "${d.name}"`).join(", ");
|
|
@@ -1310,7 +1333,7 @@ Use \`context action=get\` to inspect the existing entry, or \`entries action=up
|
|
|
1310
1333
|
next.push({ tool: "context", description: "See its connections", parameters: { action: "find", entryId: finalEntryId } });
|
|
1311
1334
|
} else {
|
|
1312
1335
|
next.push({ tool: "context", description: "Review the draft alternative", parameters: { action: "get", entryId: finalEntryId } });
|
|
1313
|
-
next.push({ tool: "entries", description: "Accept onto Chain", parameters: { action: "commit", entryId: finalEntryId } });
|
|
1336
|
+
next.push(spineFloor && !spineFloor.exempt && !spineFloor.linkWritten ? { tool: "relations", description: "Write the spine link it owes", parameters: { action: "create", from: finalEntryId, type: spineFloor.relationType } } : { tool: "entries", description: "Accept onto Chain", parameters: { action: "commit", entryId: finalEntryId } });
|
|
1314
1337
|
}
|
|
1315
1338
|
const qualityPhrase = verdictQualityPhrase(verdictResult);
|
|
1316
1339
|
const summary = finalStatus === "committed" ? `Captured and accepted ${finalEntryId} (${name}) onto ${landedCollection}. ${qualityPhrase}` : `Captured ${finalEntryId} (${name}) as draft in ${landedCollection}. ${qualityPhrase}`;
|
|
@@ -3019,11 +3042,91 @@ ${footer}` }],
|
|
|
3019
3042
|
|
|
3020
3043
|
// src/tools/relations.ts
|
|
3021
3044
|
import { z as z13 } from "zod/v3";
|
|
3045
|
+
|
|
3046
|
+
// src/lib/relationTypes.ts
|
|
3047
|
+
var ALLOWED_RELATION_TYPES_LIST = [
|
|
3048
|
+
// Core semantic types
|
|
3049
|
+
"informs",
|
|
3050
|
+
"governs",
|
|
3051
|
+
"surfaces_tension_in",
|
|
3052
|
+
"defines_term_for",
|
|
3053
|
+
"belongs_to",
|
|
3054
|
+
"references",
|
|
3055
|
+
"related_to",
|
|
3056
|
+
"fills_slot",
|
|
3057
|
+
"commits_to",
|
|
3058
|
+
"informed_by",
|
|
3059
|
+
"depends_on",
|
|
3060
|
+
"conflicts_with",
|
|
3061
|
+
"confused_with",
|
|
3062
|
+
// WP-449: Glossary Foundation — negative assertion for agents (spec §4.5)
|
|
3063
|
+
"do_not_confuse_with",
|
|
3064
|
+
"replaces",
|
|
3065
|
+
"part_of",
|
|
3066
|
+
"constrains",
|
|
3067
|
+
// Epistemic types — evidence linking
|
|
3068
|
+
"validates",
|
|
3069
|
+
"invalidates",
|
|
3070
|
+
// Extended types
|
|
3071
|
+
"governed_by",
|
|
3072
|
+
"alternative_to",
|
|
3073
|
+
"has_proposal",
|
|
3074
|
+
"requests_promotion_of",
|
|
3075
|
+
"resolves",
|
|
3076
|
+
// WP-228 Slice 0: Playing Field relation types
|
|
3077
|
+
"experiences",
|
|
3078
|
+
"addresses",
|
|
3079
|
+
// Tier 1 Hierarchy: DEC-401 (experiments prereqs), DEC-402 (risk views)
|
|
3080
|
+
"threatens",
|
|
3081
|
+
"tests",
|
|
3082
|
+
"produces",
|
|
3083
|
+
// WP-274: Capability tier relation types
|
|
3084
|
+
"realizes",
|
|
3085
|
+
"requires",
|
|
3086
|
+
"invests_in",
|
|
3087
|
+
"enables",
|
|
3088
|
+
// PARKED (park note, 2026-08-23) — these 5 verbs are untouched by a separate
|
|
3089
|
+
// governance-verb-ownership review: no delete, no lock, no whitelist, no picker change,
|
|
3090
|
+
// and no relation of this note to that review. Live source-canonicalKey row counts, from
|
|
3091
|
+
// a read-only pass over an uncapped, exhaustive census of a real workspace (measured
|
|
3092
|
+
// 2026-08-23): follows = 11 rows (decision 2, milestone 5, work_package 4);
|
|
3093
|
+
// extracted_from = 4 rows (decision 1, insight 1, tension 1, work_package 1);
|
|
3094
|
+
// part_of_workstream = 0 rows; stated_by = 0 rows; discussed_in = 0 rows. Whether any of
|
|
3095
|
+
// these should be retired, merged, or promoted is a founder call, deliberately deferred —
|
|
3096
|
+
// not decided here, and not decided by silence either. Re-verify the counts before acting
|
|
3097
|
+
// on them; they will drift.
|
|
3098
|
+
// WP-344 S0a: Evolve-First Ingestion relation types
|
|
3099
|
+
"follows",
|
|
3100
|
+
// sequential/derived — new entry follows/continues from another
|
|
3101
|
+
"extracted_from",
|
|
3102
|
+
// provenance — this entry was extracted from a source document
|
|
3103
|
+
// WP-353 S0: scope-propagated commit relation types (DEC-A captured as exploring per RULE-187)
|
|
3104
|
+
"part_of_workstream",
|
|
3105
|
+
// entry belongs to a workstream anchor confirmed at scope step
|
|
3106
|
+
"stated_by",
|
|
3107
|
+
// entry was stated by a speaker in the source document
|
|
3108
|
+
"discussed_in",
|
|
3109
|
+
// entry was discussed within a particular meeting/doc context
|
|
3110
|
+
// Specification types — WP-363 E2: precision alternatives to governs for decision→governance relations
|
|
3111
|
+
"specializes",
|
|
3112
|
+
// DEC narrows or refines a broader STD/PRI — more specific application of the parent
|
|
3113
|
+
"implements",
|
|
3114
|
+
// DEC/WP realizes a BR/STD in concrete operational form
|
|
3115
|
+
// WP-641 S2a (WP-647): belongs_to vocabulary split — the strategy-scope successor.
|
|
3116
|
+
// The other two successors (authority_domain, domain_routed_to) and `blocks` are no longer
|
|
3117
|
+
// legal to write: a new workspace carries none of them (DEC-1845, TASK-331, TASK-425).
|
|
3118
|
+
"anchored_to"
|
|
3119
|
+
// strategy-scope anchor: a raw strategy entry belongs_to a product (DEC-1523)
|
|
3120
|
+
];
|
|
3121
|
+
var ALLOWED_RELATION_TYPES = new Set(ALLOWED_RELATION_TYPES_LIST);
|
|
3122
|
+
|
|
3123
|
+
// src/tools/relations.ts
|
|
3022
3124
|
var RELATIONS_ACTIONS = ["create", "batch-create", "delete"];
|
|
3125
|
+
var relationType = z13.enum(ALLOWED_RELATION_TYPES_LIST);
|
|
3023
3126
|
var relationItemSchema = z13.object({
|
|
3024
3127
|
from: z13.string().max(200),
|
|
3025
3128
|
to: z13.string().max(200),
|
|
3026
|
-
type:
|
|
3129
|
+
type: relationType
|
|
3027
3130
|
});
|
|
3028
3131
|
var relationsSchema = z13.object({
|
|
3029
3132
|
action: z13.enum(RELATIONS_ACTIONS).describe(
|
|
@@ -3031,16 +3134,17 @@ var relationsSchema = z13.object({
|
|
|
3031
3134
|
),
|
|
3032
3135
|
from: z13.string().max(200).optional().describe("For 'create'/'delete': source entry ID."),
|
|
3033
3136
|
to: z13.string().max(200).optional().describe("For 'create'/'delete': target entry ID."),
|
|
3034
|
-
|
|
3137
|
+
// TASK-1026: the batch item's type is served as a $ref to this one, so the description holds for both; a second enum instance costs 590 bytes of the 64 KB budget (DEC-1981).
|
|
3138
|
+
type: relationType.optional().describe("Relation type, for create, delete and each batch-create item."),
|
|
3035
3139
|
relations: z13.array(relationItemSchema).min(1).max(RELATION_BATCH_MAX).optional().describe("For 'batch-create': array of {from, to, type}."),
|
|
3036
3140
|
// WP-316 S3: Preview gate — dry-run mode for action=create.
|
|
3037
|
-
preview: z13.boolean().optional().describe("For 'create': if true,
|
|
3141
|
+
preview: z13.boolean().optional().describe("For 'create': if true, checks the relation and writes nothing.")
|
|
3038
3142
|
});
|
|
3039
3143
|
var relationsCreateVariant = z13.object({
|
|
3040
3144
|
action: z13.literal("create"),
|
|
3041
3145
|
from: z13.string().max(200),
|
|
3042
3146
|
to: z13.string().max(200),
|
|
3043
|
-
type:
|
|
3147
|
+
type: relationType,
|
|
3044
3148
|
preview: z13.boolean().optional()
|
|
3045
3149
|
});
|
|
3046
3150
|
var relationsBatchCreateVariant = z13.object({
|
|
@@ -3051,7 +3155,7 @@ var relationsDeleteVariant = z13.object({
|
|
|
3051
3155
|
action: z13.literal("delete"),
|
|
3052
3156
|
from: z13.string().max(200),
|
|
3053
3157
|
to: z13.string().max(200),
|
|
3054
|
-
type:
|
|
3158
|
+
type: relationType
|
|
3055
3159
|
});
|
|
3056
3160
|
var relationsActionUnion = z13.discriminatedUnion("action", [
|
|
3057
3161
|
relationsCreateVariant,
|
|
@@ -3073,7 +3177,9 @@ function registerRelationsTools(server) {
|
|
|
3073
3177
|
"relations",
|
|
3074
3178
|
{
|
|
3075
3179
|
title: "Relations",
|
|
3076
|
-
description:
|
|
3180
|
+
description: `Create and delete relations between entries, each written only on request with exactly the verb you send. Read relations with the read-only \`context action=find\`.
|
|
3181
|
+
|
|
3182
|
+
The spine links, child to parent: ${SPINE_RUNG_LINES.join(" ")}`,
|
|
3077
3183
|
inputSchema: relationsSchema,
|
|
3078
3184
|
// DEC-1894 / DEC-74: find lives on the read-only `context` tool; every action left here writes.
|
|
3079
3185
|
annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: false }
|
|
@@ -4909,27 +5015,27 @@ async function handleBuild(server, entryId, maxHops) {
|
|
|
4909
5015
|
)
|
|
4910
5016
|
};
|
|
4911
5017
|
}
|
|
4912
|
-
async function handleCrossCut(
|
|
5018
|
+
async function handleCrossCut(relationType2) {
|
|
4913
5019
|
const result2 = await kernelQuery("chain.structuralAggregation", {
|
|
4914
|
-
relationType
|
|
5020
|
+
relationType: relationType2
|
|
4915
5021
|
});
|
|
4916
5022
|
const groupKeys = Object.keys(result2.groups);
|
|
4917
5023
|
if (result2.totalCount === 0) {
|
|
4918
5024
|
return {
|
|
4919
5025
|
content: [{
|
|
4920
5026
|
type: "text",
|
|
4921
|
-
text: `# Cross-Cut: ${
|
|
5027
|
+
text: `# Cross-Cut: ${relationType2}
|
|
4922
5028
|
|
|
4923
|
-
No relations of type '${
|
|
5029
|
+
No relations of type '${relationType2}' found in this workspace.`
|
|
4924
5030
|
}],
|
|
4925
5031
|
structuredContent: success(
|
|
4926
|
-
`No '${
|
|
5032
|
+
`No '${relationType2}' relations found.`,
|
|
4927
5033
|
{ groups: {}, totalCount: 0, truncated: false }
|
|
4928
5034
|
)
|
|
4929
5035
|
};
|
|
4930
5036
|
}
|
|
4931
5037
|
const lines = [
|
|
4932
|
-
`# Cross-Cut: ${
|
|
5038
|
+
`# Cross-Cut: ${relationType2}`,
|
|
4933
5039
|
`_${result2.totalCount} relations across ${groupKeys.length} source collection${groupKeys.length === 1 ? "" : "s"}${result2.truncated ? " (TRUNCATED \u2014 more relations exist)" : ""}_`,
|
|
4934
5040
|
""
|
|
4935
5041
|
];
|
|
@@ -4948,18 +5054,18 @@ No relations of type '${relationType}' found in this workspace.`
|
|
|
4948
5054
|
return {
|
|
4949
5055
|
content: [{ type: "text", text: lines.join("\n") }],
|
|
4950
5056
|
structuredContent: success(
|
|
4951
|
-
`${result2.totalCount} '${
|
|
5057
|
+
`${result2.totalCount} '${relationType2}' relations across ${groupKeys.length} collections.${result2.truncated ? " Truncated." : ""}`,
|
|
4952
5058
|
result2
|
|
4953
5059
|
)
|
|
4954
5060
|
};
|
|
4955
5061
|
}
|
|
4956
|
-
async function handleChainWalk(entryId, direction, maxHops,
|
|
5062
|
+
async function handleChainWalk(entryId, direction, maxHops, relationType2) {
|
|
4957
5063
|
const clampedHops = Math.max(1, Math.min(4, maxHops));
|
|
4958
5064
|
const result2 = await kernelQuery("chain.deepChainWalk", {
|
|
4959
5065
|
entryId,
|
|
4960
5066
|
direction,
|
|
4961
5067
|
maxHops: clampedHops,
|
|
4962
|
-
...
|
|
5068
|
+
...relationType2 ? { relationType: relationType2 } : {}
|
|
4963
5069
|
});
|
|
4964
5070
|
if (result2.error) {
|
|
4965
5071
|
return notFoundResult(entryId, result2.error);
|
|
@@ -4970,7 +5076,7 @@ async function handleChainWalk(entryId, direction, maxHops, relationType) {
|
|
|
4970
5076
|
type: "text",
|
|
4971
5077
|
text: `# Chain Walk: ${entryId}
|
|
4972
5078
|
|
|
4973
|
-
_No ${direction} relations found${
|
|
5079
|
+
_No ${direction} relations found${relationType2 ? ` of type '${relationType2}'` : ""}._
|
|
4974
5080
|
|
|
4975
5081
|
Try \`context action=chain entryId="${entryId}" direction="${direction === "outgoing" ? "incoming" : "outgoing"}"\` or remove the relationType filter.`
|
|
4976
5082
|
}],
|
|
@@ -4982,7 +5088,7 @@ Try \`context action=chain entryId="${entryId}" direction="${direction === "outg
|
|
|
4982
5088
|
}
|
|
4983
5089
|
const lines = [
|
|
4984
5090
|
`# Chain Walk: ${entryId}`,
|
|
4985
|
-
`**Direction:** ${direction} | **Depth:** ${clampedHops}${
|
|
5091
|
+
`**Direction:** ${direction} | **Depth:** ${clampedHops}${relationType2 ? ` | **Type filter:** ${relationType2}` : ""}`,
|
|
4986
5092
|
`**Nodes:** ${result2.totalNodes}${result2.truncated ? " (TRUNCATED at 100)" : ""} | **Edges:** ${result2.edges.length} | **Cycles:** ${result2.cycles.length}`,
|
|
4987
5093
|
""
|
|
4988
5094
|
];
|
|
@@ -12102,4 +12208,4 @@ export {
|
|
|
12102
12208
|
SERVER_VERSION,
|
|
12103
12209
|
createProductBrainServer
|
|
12104
12210
|
};
|
|
12105
|
-
//# sourceMappingURL=chunk-
|
|
12211
|
+
//# sourceMappingURL=chunk-W3Y4VS6E.js.map
|