@productbrain/mcp 0.0.1-beta.111 → 0.0.1-beta.122
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-RQXM3TCI.js → chunk-2ZWGQ6PK.js} +18 -1
- package/dist/chunk-2ZWGQ6PK.js.map +1 -0
- package/dist/{chunk-DHBJFEAT.js → chunk-G4WJIWXX.js} +55 -24
- package/dist/chunk-G4WJIWXX.js.map +1 -0
- package/dist/{chunk-O337N4MC.js → chunk-ZFODPVNH.js} +950 -56
- package/dist/chunk-ZFODPVNH.js.map +1 -0
- package/dist/cli/index.js +1 -1
- package/dist/http.js +8 -5
- package/dist/http.js.map +1 -1
- package/dist/index.js +3 -3
- package/dist/{setup-GQ3LQS2L.js → setup-2JWIZ3QO.js} +3 -3
- package/dist/setup-2JWIZ3QO.js.map +1 -0
- package/dist/{smart-capture-ATJ5F7R2.js → smart-capture-CVZ5PLUZ.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-DHBJFEAT.js.map +0 -1
- package/dist/chunk-O337N4MC.js.map +0 -1
- package/dist/chunk-RQXM3TCI.js.map +0 -1
- package/dist/setup-GQ3LQS2L.js.map +0 -1
- /package/dist/{smart-capture-ATJ5F7R2.js.map → smart-capture-CVZ5PLUZ.js.map} +0 -0
|
@@ -144,6 +144,22 @@ function trackCaptureClassifierAutoRouted(workspaceId, props) {
|
|
|
144
144
|
function trackCaptureClassifierFallback(workspaceId, props) {
|
|
145
145
|
trackCaptureClassifierEvent("mcp_capture_classifier_fallback", workspaceId, props);
|
|
146
146
|
}
|
|
147
|
+
function trackChainEntryCommitted(workspaceId, props) {
|
|
148
|
+
if (!client) return;
|
|
149
|
+
try {
|
|
150
|
+
client.capture({
|
|
151
|
+
distinctId,
|
|
152
|
+
event: "chain_entry_committed",
|
|
153
|
+
properties: {
|
|
154
|
+
workspace_id: workspaceId,
|
|
155
|
+
source_system: "mcp-server",
|
|
156
|
+
$groups: { workspace: workspaceId },
|
|
157
|
+
...props
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
} catch {
|
|
161
|
+
}
|
|
162
|
+
}
|
|
147
163
|
function trackKnowledgeGap(workspaceId, props) {
|
|
148
164
|
if (!client) return;
|
|
149
165
|
try {
|
|
@@ -251,6 +267,7 @@ export {
|
|
|
251
267
|
trackCaptureClassifierEvaluated,
|
|
252
268
|
trackCaptureClassifierAutoRouted,
|
|
253
269
|
trackCaptureClassifierFallback,
|
|
270
|
+
trackChainEntryCommitted,
|
|
254
271
|
trackKnowledgeGap,
|
|
255
272
|
getPostHogClient,
|
|
256
273
|
shutdownAnalytics,
|
|
@@ -258,4 +275,4 @@ export {
|
|
|
258
275
|
resolveClient,
|
|
259
276
|
writeClientConfig
|
|
260
277
|
};
|
|
261
|
-
//# sourceMappingURL=chunk-
|
|
278
|
+
//# sourceMappingURL=chunk-2ZWGQ6PK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/analytics.ts","../src/cli/config-writer.ts"],"sourcesContent":["/**\n * PostHog analytics for SynergyOS maintainers — tracks MCP usage (sessions, tool calls).\n * Not user-facing. Key is injected at build time via SYNERGYOS_POSTHOG_KEY.\n * Override with POSTHOG_MCP_KEY for self-hosted deployments.\n */\n\nimport { userInfo } from \"node:os\";\nimport { PostHog } from \"posthog-node\";\n\nlet client: PostHog | null = null;\nlet distinctId = \"anonymous\";\n\nconst POSTHOG_HOST = \"https://eu.i.posthog.com\";\n\n/** Injected at build time: SYNERGYOS_POSTHOG_KEY env when running `npm run build`/publish. */\ndeclare const __SYNERGYOS_POSTHOG_KEY__: string;\n\n/** Only write to stderr when MCP_DEBUG=1 for quieter default DX. */\nfunction log(msg: string): void {\n if (process.env.MCP_DEBUG === \"1\") {\n process.stderr.write(msg);\n }\n}\n\nfunction getBuildTimeKey(): string {\n try {\n return __SYNERGYOS_POSTHOG_KEY__;\n } catch {\n // Not replaced by bundler (e.g. running via tsx in tests) — treat as absent.\n return \"\";\n }\n}\n\nexport function initAnalytics(): void {\n const apiKey = process.env.POSTHOG_MCP_KEY || getBuildTimeKey();\n if (!apiKey) {\n log(\"[MCP-ANALYTICS] No PostHog key — tracking disabled (set SYNERGYOS_POSTHOG_KEY at build time for publish)\\n\");\n return;\n }\n\n client = new PostHog(apiKey, {\n host: POSTHOG_HOST,\n flushAt: 1,\n flushInterval: 5000,\n featureFlagsPollingInterval: 30_000,\n });\n distinctId = process.env.MCP_USER_ID || fallbackDistinctId();\n\n log(`[MCP-ANALYTICS] Initialized — host=${POSTHOG_HOST} distinctId=${distinctId}\\n`);\n}\n\nfunction fallbackDistinctId(): string {\n try {\n return userInfo().username;\n } catch {\n return `os-${process.pid}`;\n }\n}\n\nexport function trackSessionStarted(\n workspaceId: string,\n serverVersion: string,\n): void {\n if (!client) return;\n client.capture({\n distinctId,\n event: \"mcp_session_started\",\n properties: {\n workspace_id: workspaceId,\n server_version: serverVersion,\n source: \"mcp-server\",\n $groups: { workspace: workspaceId },\n },\n });\n}\n\nexport function trackToolCall(\n fn: string,\n status: \"ok\" | \"error\",\n durationMs: number,\n workspaceId: string,\n errorMsg?: string,\n): void {\n const properties: Record<string, unknown> = {\n tool: fn,\n status,\n duration_ms: durationMs,\n workspace_id: workspaceId,\n source: \"mcp-server\",\n $groups: { workspace: workspaceId },\n };\n if (errorMsg) properties.error = errorMsg;\n\n if (!client) return;\n client.capture({\n distinctId,\n event: \"mcp_tool_called\",\n properties,\n });\n}\n\nexport function trackSetupStarted(): void {\n if (!client) return;\n client.capture({\n distinctId,\n event: \"mcp_setup_started\",\n properties: {\n source: \"mcp-server\",\n platform: process.platform,\n },\n });\n}\n\nexport function trackSetupCompleted(\n chosenClient: string,\n outcome: \"config_written\" | \"config_existed\" | \"snippet_shown\" | \"write_error\",\n): void {\n if (!client) return;\n client.capture({\n distinctId,\n event: \"mcp_setup_completed\",\n properties: {\n client: chosenClient,\n outcome,\n source: \"mcp-server\",\n platform: process.platform,\n },\n });\n}\n\nexport function trackQualityVerdict(\n workspaceId: string,\n props: {\n entry_id: string;\n entry_type: string;\n tier: string;\n context: string;\n passed: boolean;\n source: string;\n criteria_total: number;\n criteria_failed: number;\n llm_scheduled: boolean;\n },\n): void {\n if (!client) return;\n client.capture({\n distinctId,\n event: \"quality_verdict_generated\",\n properties: {\n ...props,\n workspace_id: workspaceId,\n source_system: \"mcp-server\",\n $groups: { workspace: workspaceId },\n },\n });\n}\n\nexport function trackQualityCheck(\n workspaceId: string,\n props: {\n entry_id: string;\n entry_type: string;\n tier: string;\n passed: boolean;\n source: string;\n llm_status?: string;\n llm_duration_ms?: number;\n llm_error?: string;\n has_roger_martin: boolean;\n },\n): void {\n if (!client) return;\n client.capture({\n distinctId,\n event: \"quality_verdict_checked\",\n properties: {\n ...props,\n workspace_id: workspaceId,\n source_system: \"mcp-server\",\n $groups: { workspace: workspaceId },\n },\n });\n}\n\nexport type ClassifierReasonCategory =\n | \"auto-routed\"\n | \"low-confidence\"\n | \"ambiguous\"\n | \"non-provisioned\";\n\ntype CaptureClassifierTelemetryProps = {\n predicted_collection: string;\n confidence: number;\n auto_routed: boolean;\n reason_category: ClassifierReasonCategory;\n explicit_collection_provided: boolean;\n};\n\nfunction trackCaptureClassifierEvent(\n event: \"mcp_capture_classifier_evaluated\" | \"mcp_capture_classifier_auto_routed\" | \"mcp_capture_classifier_fallback\",\n workspaceId: string,\n props: CaptureClassifierTelemetryProps,\n): void {\n if (!client) return;\n try {\n client.capture({\n distinctId,\n event,\n properties: {\n ...props,\n workspace_id: workspaceId,\n source_system: \"mcp-server\",\n $groups: { workspace: workspaceId },\n },\n });\n } catch {\n // Analytics are advisory and must never break capture flow.\n }\n}\n\nexport function trackCaptureClassifierEvaluated(\n workspaceId: string,\n props: CaptureClassifierTelemetryProps,\n): void {\n trackCaptureClassifierEvent(\"mcp_capture_classifier_evaluated\", workspaceId, props);\n}\n\nexport function trackCaptureClassifierAutoRouted(\n workspaceId: string,\n props: CaptureClassifierTelemetryProps,\n): void {\n trackCaptureClassifierEvent(\"mcp_capture_classifier_auto_routed\", workspaceId, props);\n}\n\nexport function trackCaptureClassifierFallback(\n workspaceId: string,\n props: CaptureClassifierTelemetryProps,\n): void {\n trackCaptureClassifierEvent(\"mcp_capture_classifier_fallback\", workspaceId, props);\n}\n\n/** GLO-26 / TEN-156: every SSOT commit for PostHog funnels (split auto vs manual). */\nexport function trackChainEntryCommitted(\n workspaceId: string,\n props: {\n entry_id: string;\n collection?: string;\n commit_method: \"auto\" | \"manual\";\n surface:\n | \"mcp_commit_tool\"\n | \"mcp_capture\"\n | \"mcp_wrapup\";\n },\n): void {\n if (!client) return;\n try {\n client.capture({\n distinctId,\n event: \"chain_entry_committed\",\n properties: {\n workspace_id: workspaceId,\n source_system: \"mcp-server\",\n $groups: { workspace: workspaceId },\n ...props,\n },\n });\n } catch {\n // Analytics must never break the tool path.\n }\n}\n\nexport function trackKnowledgeGap(\n workspaceId: string,\n props: {\n query: string;\n tool: string;\n action: string;\n gap_type: \"search_zero\" | \"context_task_empty\" | \"context_entry_isolated\" | \"context_graph_empty\";\n collection_scope?: string;\n },\n): void {\n if (!client) return;\n try {\n client.capture({\n distinctId,\n event: \"knowledge_gap_detected\",\n properties: {\n ...props,\n query: props.query.slice(0, 200),\n workspace_id: workspaceId,\n source_system: \"mcp-server\",\n $groups: { workspace: workspaceId },\n },\n });\n } catch {\n // Analytics must never break the tool response path.\n }\n}\n\nexport function getPostHogClient(): PostHog | null {\n return client;\n}\n\nexport async function shutdownAnalytics(): Promise<void> {\n await client?.shutdown();\n}\n","/**\n * Multi-client MCP config detection and writer.\n *\n * Supports:\n * - Cursor: .cursor/mcp.json in cwd (project-level)\n * - Claude Desktop: ~/Library/Application Support/Claude/claude_desktop_config.json (macOS)\n * %APPDATA%/Claude/claude_desktop_config.json (Windows)\n *\n * The writer reads existing config, merges the new server entry (never\n * overwrites existing entries), and writes back. Falls back to printing\n * a snippet for unsupported OS or unknown formats.\n */\n\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { homedir, platform } from \"node:os\";\n\nexport interface McpClientInfo {\n name: string;\n configPath: string;\n}\n\nconst SERVER_ENTRY_KEY = \"Product Brain\";\nconst LEGACY_ENTRY_KEY = \"productbrain\";\n\n/**\n * Canonical npx package specifier. Update here when exiting beta.\n * Frontend mirror: src/lib/constants/mcp.ts\n * Business rule: BR-84 (Chain)\n */\nexport const MCP_NPX_PACKAGE = \"@productbrain/mcp@beta\";\n\nfunction buildServerEntry(apiKey: string) {\n return {\n command: \"npx\",\n args: [\"-y\", MCP_NPX_PACKAGE],\n env: { PRODUCTBRAIN_API_KEY: apiKey },\n };\n}\n\n// ── Detection ───────────────────────────────────────────────────────────\n\nfunction getCursorConfigPath(): string {\n return join(process.cwd(), \".cursor\", \"mcp.json\");\n}\n\nfunction getClaudeDesktopConfigPath(): string | null {\n const os = platform();\n if (os === \"darwin\") {\n return join(\n homedir(),\n \"Library\",\n \"Application Support\",\n \"Claude\",\n \"claude_desktop_config.json\",\n );\n }\n if (os === \"win32\") {\n const appData = process.env.APPDATA ?? join(homedir(), \"AppData\", \"Roaming\");\n return join(appData, \"Claude\", \"claude_desktop_config.json\");\n }\n // Linux: no official Claude Desktop location yet\n return null;\n}\n\nexport function resolveClient(name: \"Cursor\" | \"Claude Desktop\"): McpClientInfo | null {\n if (name === \"Cursor\") {\n return { name, configPath: getCursorConfigPath() };\n }\n const configPath = getClaudeDesktopConfigPath();\n return configPath ? { name, configPath } : null;\n}\n\n// ── Writing ─────────────────────────────────────────────────────────────\n\nfunction readJsonSafe(path: string): Record<string, any> {\n if (!existsSync(path)) return {};\n try {\n return JSON.parse(readFileSync(path, \"utf-8\"));\n } catch {\n return {};\n }\n}\n\n/**\n * Write or merge the Product Brain server entry into a client config file.\n * Migrates legacy \"productbrain\" key to \"Product Brain\" when present.\n * Returns true if the config was written, false if already present.\n */\nexport async function writeClientConfig(\n client: McpClientInfo,\n apiKey: string,\n): Promise<boolean> {\n const config = readJsonSafe(client.configPath);\n\n const serversKey = \"mcpServers\";\n if (!config[serversKey]) config[serversKey] = {};\n\n // Migrate legacy \"productbrain\" key or update existing Product Brain with new API key\n if (config[serversKey][LEGACY_ENTRY_KEY]) {\n const legacy = config[serversKey][LEGACY_ENTRY_KEY];\n config[serversKey][SERVER_ENTRY_KEY] = {\n ...buildServerEntry(apiKey),\n env: { ...legacy.env, PRODUCTBRAIN_API_KEY: legacy.env?.PRODUCTBRAIN_API_KEY ?? apiKey },\n };\n delete config[serversKey][LEGACY_ENTRY_KEY];\n } else {\n const existing = config[serversKey][SERVER_ENTRY_KEY];\n config[serversKey][SERVER_ENTRY_KEY] = existing\n ? { ...existing, env: { ...existing.env, PRODUCTBRAIN_API_KEY: apiKey } }\n : buildServerEntry(apiKey);\n }\n\n const dir = dirname(client.configPath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n writeFileSync(client.configPath, JSON.stringify(config, null, 2) + \"\\n\", \"utf-8\");\n return true;\n}\n"],"mappings":"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","names":["client"]}
|
|
@@ -3,9 +3,10 @@ import {
|
|
|
3
3
|
trackCaptureClassifierAutoRouted,
|
|
4
4
|
trackCaptureClassifierEvaluated,
|
|
5
5
|
trackCaptureClassifierFallback,
|
|
6
|
+
trackChainEntryCommitted,
|
|
6
7
|
trackQualityVerdict,
|
|
7
8
|
trackToolCall
|
|
8
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-2ZWGQ6PK.js";
|
|
9
10
|
|
|
10
11
|
// src/tools/smart-capture.ts
|
|
11
12
|
import { z as z2 } from "zod";
|
|
@@ -570,6 +571,17 @@ function trackWriteTool(_tool) {
|
|
|
570
571
|
// src/featureFlags.ts
|
|
571
572
|
import { PostHog } from "posthog-node";
|
|
572
573
|
var client = null;
|
|
574
|
+
var SERVER_FLAGS = {
|
|
575
|
+
"workspace-full-surface": { status: "active" },
|
|
576
|
+
"active-intelligence-shaping": { status: "active" },
|
|
577
|
+
"capture-without-thinking": { status: "active" },
|
|
578
|
+
"chainwork-enabled": { status: "active" },
|
|
579
|
+
"bet-203-roadmap-coordination": { status: "active" },
|
|
580
|
+
"bet-221-governance-at-scale": { status: "active" },
|
|
581
|
+
"bet-226-semantic-chunking": { status: "active" }
|
|
582
|
+
};
|
|
583
|
+
var REGISTERED_FLAGS_DEFAULT_ON = true;
|
|
584
|
+
var DEV_DEFAULT_ALL_ON = process.env.NODE_ENV === "development" && process.env.FLAGS_DEV_DEFAULT_ON === "true";
|
|
573
585
|
var LOCAL_OVERRIDES = {
|
|
574
586
|
// Uncomment for local dev without PostHog:
|
|
575
587
|
// "workspace-full-surface": false,
|
|
@@ -597,6 +609,8 @@ function initFeatureFlags(posthogClient) {
|
|
|
597
609
|
async function isFeatureEnabled(flag, workspaceId, workspaceSlug) {
|
|
598
610
|
if (process.env.FEATURE_KILL_SWITCH === "true") return false;
|
|
599
611
|
if (flag in LOCAL_OVERRIDES) return LOCAL_OVERRIDES[flag];
|
|
612
|
+
if (REGISTERED_FLAGS_DEFAULT_ON && flag in SERVER_FLAGS && SERVER_FLAGS[flag].status === "active") return true;
|
|
613
|
+
if (DEV_DEFAULT_ALL_ON) return true;
|
|
600
614
|
if (!client) return false;
|
|
601
615
|
try {
|
|
602
616
|
const primary = await client.isFeatureEnabled(flag, workspaceId, {
|
|
@@ -968,12 +982,13 @@ var CLASSIFIABLE_COLLECTIONS = [
|
|
|
968
982
|
"features",
|
|
969
983
|
"architecture",
|
|
970
984
|
"business-rules",
|
|
971
|
-
|
|
985
|
+
// tracking-events: removed (Tier 1 Hierarchy — 0 entries, collection deprecated)
|
|
972
986
|
"landscape",
|
|
973
987
|
"standards",
|
|
974
988
|
"principles",
|
|
975
989
|
"assumptions",
|
|
976
|
-
"
|
|
990
|
+
"work-packages",
|
|
991
|
+
"patterns"
|
|
977
992
|
];
|
|
978
993
|
var SIGNAL_WEIGHT = 10;
|
|
979
994
|
var MIN_SCORE_FLOOR = 10;
|
|
@@ -1143,15 +1158,7 @@ var COLLECTION_SIGNALS = {
|
|
|
1143
1158
|
"requires active session",
|
|
1144
1159
|
"readiness excludes"
|
|
1145
1160
|
],
|
|
1146
|
-
|
|
1147
|
-
"track",
|
|
1148
|
-
"tracking",
|
|
1149
|
-
"analytics",
|
|
1150
|
-
"trigger",
|
|
1151
|
-
"posthog",
|
|
1152
|
-
"instrument",
|
|
1153
|
-
"fires when"
|
|
1154
|
-
],
|
|
1161
|
+
// tracking-events: removed (Tier 1 Hierarchy — 0 entries, collection deprecated)
|
|
1155
1162
|
landscape: [
|
|
1156
1163
|
"competitor",
|
|
1157
1164
|
"alternative tool",
|
|
@@ -1189,7 +1196,17 @@ var COLLECTION_SIGNALS = {
|
|
|
1189
1196
|
"we assume",
|
|
1190
1197
|
"needs validation"
|
|
1191
1198
|
],
|
|
1192
|
-
|
|
1199
|
+
patterns: [
|
|
1200
|
+
"pattern",
|
|
1201
|
+
"anti-pattern",
|
|
1202
|
+
"best practice",
|
|
1203
|
+
"reusable solution",
|
|
1204
|
+
"design pattern",
|
|
1205
|
+
"recurring solution",
|
|
1206
|
+
"template",
|
|
1207
|
+
"proven approach"
|
|
1208
|
+
],
|
|
1209
|
+
"work-packages": [
|
|
1193
1210
|
"appetite",
|
|
1194
1211
|
"elements",
|
|
1195
1212
|
"no-gos",
|
|
@@ -1493,7 +1510,8 @@ var PROFILES = /* @__PURE__ */ new Map([
|
|
|
1493
1510
|
descriptionField: "rationale",
|
|
1494
1511
|
defaults: [
|
|
1495
1512
|
{ key: "date", value: "today" },
|
|
1496
|
-
{ key: "decidedBy", value: "infer" }
|
|
1513
|
+
{ key: "decidedBy", value: "infer" },
|
|
1514
|
+
{ key: "confidence", value: "exploring" }
|
|
1497
1515
|
],
|
|
1498
1516
|
recommendedRelationTypes: ["informs", "references", "replaces", "related_to"],
|
|
1499
1517
|
inferField: (ctx) => {
|
|
@@ -1603,7 +1621,7 @@ var PROFILES = /* @__PURE__ */ new Map([
|
|
|
1603
1621
|
COMMON_CHECKS.hasDescription
|
|
1604
1622
|
]
|
|
1605
1623
|
}],
|
|
1606
|
-
["
|
|
1624
|
+
["work-packages", {
|
|
1607
1625
|
governedDraft: false,
|
|
1608
1626
|
descriptionField: "description",
|
|
1609
1627
|
defaults: [],
|
|
@@ -1953,7 +1971,7 @@ var batchCaptureSchema = z2.object({
|
|
|
1953
1971
|
description: z2.string().describe("Full context / definition"),
|
|
1954
1972
|
entryId: entryIdSchema,
|
|
1955
1973
|
data: z2.record(z2.unknown()).optional().describe("Explicit field values (e.g. urgency, status, assignee). Merged with inferred values; user-provided wins."),
|
|
1956
|
-
canonicalKey: z2.string().optional().describe("Semantic type (e.g. 'decision', 'tension', '
|
|
1974
|
+
canonicalKey: z2.string().optional().describe("Semantic type (e.g. 'decision', 'tension', 'work_package'). Enables work-package redirect in createEntry when collection is 'chains'.")
|
|
1957
1975
|
})).min(1).max(50).describe("Array of entries to capture"),
|
|
1958
1976
|
autoCommit: z2.boolean().optional().describe(
|
|
1959
1977
|
"If true, commits created entries immediately after linking. If omitted, Open mode workspaces commit by default and consensus/role modes stay draft-first."
|
|
@@ -2338,9 +2356,9 @@ function registerSmartCaptureTools(server) {
|
|
|
2338
2356
|
return buildCollectionRequiredResult();
|
|
2339
2357
|
}
|
|
2340
2358
|
if (resolvedCollection === "chains" && !canonicalKey && !explicitCollectionProvided && classifierMeta?.candidates?.some(
|
|
2341
|
-
(c) => c.collection === "
|
|
2359
|
+
(c) => c.collection === "work-packages"
|
|
2342
2360
|
)) {
|
|
2343
|
-
canonicalKey = "
|
|
2361
|
+
canonicalKey = "work_package";
|
|
2344
2362
|
}
|
|
2345
2363
|
const tAfterClassify = Date.now();
|
|
2346
2364
|
if (entryId && resolvedCollection !== "business-rules" && resolvedCollection !== "standards") {
|
|
@@ -2419,7 +2437,7 @@ Or use \`collections action=list\` to see available collections.`
|
|
|
2419
2437
|
}
|
|
2420
2438
|
}
|
|
2421
2439
|
data[profile.descriptionField || "description"] = description;
|
|
2422
|
-
const isBetCapture = canonicalKey === "
|
|
2440
|
+
const isBetCapture = canonicalKey === "work_package" || resolvedCollection === "work-packages";
|
|
2423
2441
|
let entryWarnings = [];
|
|
2424
2442
|
const shouldDecompose = (resolvedCollection === "strategy" || isBetCapture) && description.trim().length > 0;
|
|
2425
2443
|
if (shouldDecompose) {
|
|
@@ -2431,7 +2449,7 @@ Or use \`collections action=list\` to see available collections.`
|
|
|
2431
2449
|
entryName: name,
|
|
2432
2450
|
description,
|
|
2433
2451
|
existingData: data,
|
|
2434
|
-
...isBetCapture ? { canonicalKey: "
|
|
2452
|
+
...isBetCapture ? { canonicalKey: "work_package" } : {}
|
|
2435
2453
|
}
|
|
2436
2454
|
);
|
|
2437
2455
|
if (decomposed?.decomposed) {
|
|
@@ -2671,6 +2689,12 @@ Use \`entries action=get\` to inspect the existing entry, or \`update-entry\` to
|
|
|
2671
2689
|
finalStatus = commitResult?.status === "proposal_created" ? "proposed" : "committed";
|
|
2672
2690
|
if (finalStatus === "committed") {
|
|
2673
2691
|
await recordSessionActivity({ entryModified: internalId });
|
|
2692
|
+
trackChainEntryCommitted(wsCtx.workspaceId, {
|
|
2693
|
+
entry_id: finalEntryId,
|
|
2694
|
+
collection: resolvedCollection,
|
|
2695
|
+
commit_method: "auto",
|
|
2696
|
+
surface: "mcp_capture"
|
|
2697
|
+
});
|
|
2674
2698
|
}
|
|
2675
2699
|
} catch (e) {
|
|
2676
2700
|
commitError = e instanceof Error ? e.message : "unknown error";
|
|
@@ -2705,7 +2729,7 @@ Use \`entries action=get\` to inspect the existing entry, or \`update-entry\` to
|
|
|
2705
2729
|
}
|
|
2706
2730
|
}
|
|
2707
2731
|
}
|
|
2708
|
-
const appUrl = process.env.PRODUCTBRAIN_APP_URL ?? "https://productbrain.io";
|
|
2732
|
+
const appUrl = process.env.PRODUCTBRAIN_APP_URL ?? "https://work.productbrain.io";
|
|
2709
2733
|
const studioUrl = resolvedCollection === "chains" ? `${appUrl.replace(/\/$/, "")}/w/${wsCtx.workspaceSlug}/legacy/${internalId}` : void 0;
|
|
2710
2734
|
if (studioUrl) {
|
|
2711
2735
|
lines.push("");
|
|
@@ -3030,7 +3054,7 @@ Use \`entries action=get\` to inspect the existing entry, or \`update-entry\` to
|
|
|
3030
3054
|
if (v !== void 0 && v !== null && v !== "") data[k] = v;
|
|
3031
3055
|
}
|
|
3032
3056
|
}
|
|
3033
|
-
const batchIsBet = resolvedSlug === "
|
|
3057
|
+
const batchIsBet = resolvedSlug === "work-packages" || entry.canonicalKey === "work_package";
|
|
3034
3058
|
const shouldDecomposeBatch = (resolvedSlug === "strategy" || batchIsBet) && entry.description?.trim();
|
|
3035
3059
|
let batchDecomposeWarning;
|
|
3036
3060
|
if (shouldDecomposeBatch) {
|
|
@@ -3042,7 +3066,7 @@ Use \`entries action=get\` to inspect the existing entry, or \`update-entry\` to
|
|
|
3042
3066
|
entryName: entry.name,
|
|
3043
3067
|
description: entry.description,
|
|
3044
3068
|
existingData: data,
|
|
3045
|
-
...batchIsBet ? { canonicalKey: "
|
|
3069
|
+
...batchIsBet ? { canonicalKey: "work_package" } : {}
|
|
3046
3070
|
}
|
|
3047
3071
|
);
|
|
3048
3072
|
if (decomposed?.decomposed) {
|
|
@@ -3116,6 +3140,12 @@ Use \`entries action=get\` to inspect the existing entry, or \`update-entry\` to
|
|
|
3116
3140
|
finalStatus = commitResult?.status === "proposal_created" ? "proposed" : "committed";
|
|
3117
3141
|
if (finalStatus === "committed") {
|
|
3118
3142
|
await recordSessionActivity({ entryModified: internalId });
|
|
3143
|
+
trackChainEntryCommitted(wsCtx.workspaceId, {
|
|
3144
|
+
entry_id: finalEntryId,
|
|
3145
|
+
collection: resolvedSlug ?? void 0,
|
|
3146
|
+
commit_method: "auto",
|
|
3147
|
+
surface: "mcp_capture"
|
|
3148
|
+
});
|
|
3119
3149
|
}
|
|
3120
3150
|
} catch (error) {
|
|
3121
3151
|
commitError = error instanceof Error ? error.message : String(error);
|
|
@@ -3577,6 +3607,7 @@ export {
|
|
|
3577
3607
|
initToolSurface,
|
|
3578
3608
|
trackWriteTool,
|
|
3579
3609
|
initFeatureFlags,
|
|
3610
|
+
isFeatureEnabled,
|
|
3580
3611
|
recordGap,
|
|
3581
3612
|
getSessionGaps,
|
|
3582
3613
|
getTopGaps,
|
|
@@ -3609,4 +3640,4 @@ export {
|
|
|
3609
3640
|
formatRubricCoaching,
|
|
3610
3641
|
formatRubricVerdictSection
|
|
3611
3642
|
};
|
|
3612
|
-
//# sourceMappingURL=chunk-
|
|
3643
|
+
//# sourceMappingURL=chunk-G4WJIWXX.js.map
|