@productbrain/mcp 0.0.1-beta.2203 → 0.0.1-beta.2208

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.
@@ -1680,7 +1680,7 @@ No DB writes \u2014 call without \`preview:true\` to capture for real.${result.w
1680
1680
 
1681
1681
  ${msg}
1682
1682
 
1683
- Use \`entries action=get\` to inspect the existing entry, or \`update-entry\` to modify it.`
1683
+ Use \`entries action=get\` to inspect the existing entry, or \`entries action=update\` to modify it.`
1684
1684
  }],
1685
1685
  structuredContent: failure(
1686
1686
  "DUPLICATE",
@@ -2472,7 +2472,9 @@ async function handleBatchCapture(server, { entries, autoCommit, preview }) {
2472
2472
  const { type: relationType } = inferRelationType(resolvedSlug, c.collSlug, profile);
2473
2473
  batchAutoLinks.push({ fromEntryId: finalEntryId, toEntryId: c.entryId, type: relationType, proposedBy: "auto-link", confidence: c.confidence });
2474
2474
  }
2475
- if (batchAutoLinks.length > 0) {
2475
+ if (batchAutoLinks.length > 0 && preview) {
2476
+ batchEntryWarnings.push(`${batchAutoLinks.length} auto-link(s) would be created (preview \u2014 no DB writes).`);
2477
+ } else if (batchAutoLinks.length > 0) {
2476
2478
  const batchRes = await kernelMutation("chain.createEntryRelations", {
2477
2479
  relations: batchAutoLinks,
2478
2480
  sessionId: agentId ?? void 0
@@ -2487,18 +2489,30 @@ async function handleBatchCapture(server, { entries, autoCommit, preview }) {
2487
2489
  }
2488
2490
  }
2489
2491
  let relationsCreatedCount = 0;
2492
+ let relationsPreviewedCount = 0;
2493
+ let relationsProposedCount = 0;
2490
2494
  const relationsFailedList = [];
2491
2495
  if (entry.relations && entry.relations.length > 0) {
2492
2496
  for (const rel of entry.relations) {
2493
2497
  try {
2494
- await kernelMutation("chain.createEntryRelation", {
2495
- fromEntryId: finalEntryId,
2496
- toEntryId: rel.to,
2497
- type: rel.type,
2498
- proposedBy: "user",
2499
- sessionId: agentId ?? void 0
2500
- });
2501
- relationsCreatedCount++;
2498
+ const relResult = await kernelMutation(
2499
+ "chain.createEntryRelation",
2500
+ {
2501
+ fromEntryId: finalEntryId,
2502
+ toEntryId: rel.to,
2503
+ type: rel.type,
2504
+ proposedBy: "user",
2505
+ sessionId: agentId ?? void 0,
2506
+ ...preview ? { preview: true } : {}
2507
+ }
2508
+ );
2509
+ if (relResult?.preview) {
2510
+ relationsPreviewedCount++;
2511
+ } else if (relResult?.status === "agent_proposal_created") {
2512
+ relationsProposedCount++;
2513
+ } else {
2514
+ relationsCreatedCount++;
2515
+ }
2502
2516
  } catch (relErr) {
2503
2517
  const relMsg = relErr instanceof Error ? relErr.message : String(relErr);
2504
2518
  relationsFailedList.push(`${rel.to} (${rel.type}): ${relMsg}`);
@@ -2507,6 +2521,12 @@ async function handleBatchCapture(server, { entries, autoCommit, preview }) {
2507
2521
  if (relationsFailedList.length > 0) {
2508
2522
  batchEntryWarnings.push(`${relationsFailedList.length} inline relation(s) failed: ${relationsFailedList.join("; ")}`);
2509
2523
  }
2524
+ if (relationsPreviewedCount > 0) {
2525
+ batchEntryWarnings.push(`${relationsPreviewedCount} inline relation(s) would be created (preview \u2014 no DB writes).`);
2526
+ }
2527
+ if (relationsProposedCount > 0) {
2528
+ batchEntryWarnings.push(`${relationsProposedCount} inline relation(s) converted to an agent proposal (misuse pattern) \u2014 review in Cortex UI.`);
2529
+ }
2510
2530
  }
2511
2531
  if (autoCommitApplied && !batchWasAutoCommittedServerSide) {
2512
2532
  try {
@@ -2570,7 +2590,9 @@ async function handleBatchCapture(server, { entries, autoCommit, preview }) {
2570
2590
  // TEN-2365: capture-time authority-domain proposal echo.
2571
2591
  ...result.authorityDomain ? { authorityDomain: result.authorityDomain } : {},
2572
2592
  // TEN-957 (WP-484 S2): inline relations created for this entry.
2573
- ...relationsCreatedCount > 0 ? { relationsCreated: relationsCreatedCount } : {}
2593
+ ...relationsCreatedCount > 0 ? { relationsCreated: relationsCreatedCount } : {},
2594
+ // Finding #14: distinct from relationsCreated — never counted as a write.
2595
+ ...relationsProposedCount > 0 ? { relationsProposed: relationsProposedCount } : {}
2574
2596
  });
2575
2597
  } catch (error) {
2576
2598
  const msg = error instanceof Error ? error.message : String(error);
@@ -2763,7 +2785,9 @@ _Use \`entries action=move\` to correct any misclassified entries._`);
2763
2785
  ...r.commitRefusal ? { coherencyRefusal: r.commitRefusal } : {},
2764
2786
  ...r.authorityDomain ? { domain: r.authorityDomain.slug } : {},
2765
2787
  // TEN-957 (WP-484 S2): inline relations created for this entry.
2766
- ...r.relationsCreated ? { relationsCreated: r.relationsCreated } : {}
2788
+ ...r.relationsCreated ? { relationsCreated: r.relationsCreated } : {},
2789
+ // Finding #14: proposal outcomes are distinct from writes — never folded in.
2790
+ ...r.relationsProposed ? { relationsProposed: r.relationsProposed } : {}
2767
2791
  })),
2768
2792
  total: created.length,
2769
2793
  failed: failed.length,
@@ -3978,7 +4002,7 @@ var coherencyAcknowledgementFlatSchema = z5.object({
3978
4002
  });
3979
4003
  var entriesSchema = z5.object({
3980
4004
  action: z5.enum(ENTRIES_ACTIONS).describe(
3981
- "'list': browse entries with filters. 'get': fetch one entry by ID. 'batch': fetch multiple entries. 'search': full-text search. 'update': change fields on an existing entry (draft by default). 'commit': accept a draft entry onto the Chain. 'history': audit trail for an entry. 'move': reclassify an entry to a different collection. 'verify': mark an entry as verified (lightweight \u2014 no codebase scan; see the separate `verify` tool for the codebase-scanning check)."
4005
+ "'list': browse entries with filters. 'get': fetch one entry by ID. 'batch': fetch multiple entries. 'search': full-text search. 'update': change fields on an existing entry (draft by default). 'commit': accept a draft entry onto the Chain. 'history': audit trail for an entry. 'move': reclassify an entry to a different collection. 'verify': mark an entry as verified (lightweight \u2014 no codebase scan; see `quality action=verify-chain` for the codebase-scanning check)."
3982
4006
  ),
3983
4007
  entryId: z5.string().max(200).optional().describe(
3984
4008
  "Entry ID, e.g. '<PREFIX>-<n>'. Required for: get, update, commit, history, move, verify."
@@ -4174,7 +4198,7 @@ function registerEntriesTools(server) {
4174
4198
  "entries",
4175
4199
  {
4176
4200
  title: "Entries",
4177
- description: 'Read and manage entries on the Chain. One tool for the entry lifecycle.\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- **update**: Change fields on an existing entry (draft by default \u2014 never autoPublish without explicit user confirmation).\n- **commit**: Accept a draft entry onto the Chain (SSOT). Runs the contradiction preflight first.\n- **history**: Audit trail for an entry.\n- **move**: Reclassify an entry to a different collection.\n- **verify**: Mark an entry as verified (lightweight, no codebase scan \u2014 see the separate `verify` tool for that).\n\nUse `entries action=get entryId="..."` to fetch one. Use `entries action=search query="..."` to discover.',
4201
+ description: 'Read and manage entries on the Chain. One tool for the entry lifecycle.\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- **update**: Change fields on an existing entry (draft by default \u2014 never autoPublish without explicit user confirmation).\n- **commit**: Accept a draft entry onto the Chain (SSOT). Runs the contradiction preflight first.\n- **history**: Audit trail for an entry.\n- **move**: Reclassify an entry to a different collection.\n- **verify**: Mark an entry as verified (lightweight, no codebase scan \u2014 see `quality action=verify-chain` for that).\n\nUse `entries action=get entryId="..."` to fetch one. Use `entries action=search query="..."` to discover.',
4178
4202
  inputSchema: entriesSchema,
4179
4203
  // Mixed read/write noun (§3 R3): can't be marked read-only once update/commit/move
4180
4204
  // live here too — accepted for the 10-tool default (§9 R3).
@@ -4457,7 +4481,15 @@ ${formatted}` }],
4457
4481
  }
4458
4482
  async function handleMove(entryId, toCollection) {
4459
4483
  try {
4460
- const result = await kernelMutation("chain.moveToCollection", { entryId, toCollectionSlug: toCollection });
4484
+ const result = await kernelMutation("chain.moveToCollection", {
4485
+ entryId,
4486
+ toCollectionSlug: toCollection,
4487
+ // Finding #11: without an identity, moveToCollection's requirePermission call
4488
+ // resolves to { agentSessionId: undefined } and permissions.ts's write pre-check
4489
+ // denies EVERY call — this action always failed live. Sibling write actions
4490
+ // (knowledge.ts:137) all thread this same changedBy shape.
4491
+ changedBy: getAgentSessionId() ? `agent:${getAgentSessionId()}` : void 0
4492
+ });
4461
4493
  const lines = [
4462
4494
  `## Move Result`,
4463
4495
  "",
@@ -12292,7 +12324,11 @@ async function handleStart2() {
12292
12324
  workspaceName: result.workspaceName,
12293
12325
  toolsScope: result.toolsScope,
12294
12326
  superseded: !!result.superseded
12295
- }, [{ tool: "orient", description: "Orient session", parameters: {} }])
12327
+ // Finding #16: bare `parameters: {}` lets orient's schema default kick in
12328
+ // (action defaults to "task", which requires a `task` string) — the suggested
12329
+ // next-action call failed validation instead of running. `action: "start"` is
12330
+ // the guided-setup entrypoint this session just opened write access for.
12331
+ }, [{ tool: "orient", description: "Orient session", parameters: { action: "start" } }])
12296
12332
  };
12297
12333
  }
12298
12334
  async function handleClose() {
@@ -12319,7 +12355,7 @@ async function handleClose() {
12319
12355
  "",
12320
12356
  text,
12321
12357
  "",
12322
- `> **${data.drafts.length} uncommitted draft(s) remain.** Run \`session-wrapup\` with action \`commit-all\` before closing next time.`,
12358
+ `> **${data.drafts.length} uncommitted draft(s) remain.** Run \`session action=wrapup-commit\` before closing next time.`,
12323
12359
  "",
12324
12360
  "---",
12325
12361
  ""
@@ -12470,7 +12506,13 @@ var chainBranchSchema = z22.object({
12470
12506
  });
12471
12507
  var chainReviewSchema = z22.object({
12472
12508
  action: z22.enum(["gate", "comment", "resolve-comment", "list-comments"]).describe("Action: run coherence gate, add a comment, resolve a comment, or list comments"),
12473
- chainEntryId: z22.string().max(200).describe("The chain's entry ID"),
12509
+ // Finding #12: optional at the base (mirrors chainSchema's chainEntryId pattern at
12510
+ // line ~690) — resolve-comment resolves purely by commentId (handleChainReview never
12511
+ // reads chainEntryId in that branch) and the compound-tool's advertised schema
12512
+ // (chainReviewCompoundSchema below) already documents it as optional for that action.
12513
+ // Per-action variants that DO need it (gate/comment/list-comments) re-require it below,
12514
+ // same pattern as chainGetVariant/chainEditVariant re-requiring over chainSchema's base.
12515
+ chainEntryId: z22.string().max(200).optional().describe("The chain's entry ID. Required for every action except 'resolve-comment'."),
12474
12516
  commitMessage: z22.string().max(2e3).optional().describe("Commit message to lint (for gate action)"),
12475
12517
  versionNumber: z22.number().optional().describe("Version to comment on or list comments for"),
12476
12518
  linkId: z22.string().max(200).optional().describe("Link this comment targets (optional for comment)"),
@@ -13040,10 +13082,10 @@ var chainActionUnion = z22.discriminatedUnion("action", [
13040
13082
  chainVersionHistoryVariant
13041
13083
  ]);
13042
13084
  var reviewBase = chainReviewSchema.omit({ action: true });
13043
- var chainReviewGateVariant = reviewBase.extend({ action: z22.literal("gate") });
13044
- var chainReviewCommentVariant = reviewBase.extend({ action: z22.literal("comment"), versionNumber: z22.number(), body: z22.string().max(2e4) });
13085
+ var chainReviewGateVariant = reviewBase.extend({ action: z22.literal("gate"), chainEntryId: z22.string().max(200) });
13086
+ var chainReviewCommentVariant = reviewBase.extend({ action: z22.literal("comment"), chainEntryId: z22.string().max(200), versionNumber: z22.number(), body: z22.string().max(2e4) });
13045
13087
  var chainReviewResolveCommentVariant = reviewBase.extend({ action: z22.literal("resolve-comment"), commentId: z22.string().max(200) });
13046
- var chainReviewListCommentsVariant = reviewBase.extend({ action: z22.literal("list-comments") });
13088
+ var chainReviewListCommentsVariant = reviewBase.extend({ action: z22.literal("list-comments"), chainEntryId: z22.string().max(200) });
13047
13089
  var branchBase = chainBranchSchema.omit({ action: true });
13048
13090
  var chainBranchCreateVariant = branchBase.extend({ action: z22.literal("branch.create") });
13049
13091
  var chainBranchListVariant = branchBase.extend({ action: z22.literal("branch.list") });
@@ -15277,4 +15319,4 @@ export {
15277
15319
  createProductBrainServer,
15278
15320
  initFeatureFlags
15279
15321
  };
15280
- //# sourceMappingURL=chunk-WM3GBWEF.js.map
15322
+ //# sourceMappingURL=chunk-OD5YVZBQ.js.map