@productbrain/mcp 0.0.1-beta.9572 → 0.0.1-beta.9574

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.
@@ -43,7 +43,7 @@ import {
43
43
  trackQualityVerdict,
44
44
  trackSessionCaptureRate,
45
45
  trackZeroCaptureAuditFired
46
- } from "./chunk-I5OFR6QR.js";
46
+ } from "./chunk-WD2HD54Z.js";
47
47
 
48
48
  // src/server.ts
49
49
  import { McpServer as McpServer2 } from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -101,8 +101,8 @@ function notFound(id, hint) {
101
101
  return failure(
102
102
  "NOT_FOUND",
103
103
  `Entry '${id}' not found.`,
104
- hint ?? "Use entries action=search to find the correct ID.",
105
- [{ tool: "entries", description: "Search entries", parameters: { action: "search", query: id } }]
104
+ hint ?? "Use context action=search to find the correct ID.",
105
+ [{ tool: "context", description: "Search entries", parameters: { action: "search", query: id } }]
106
106
  );
107
107
  }
108
108
  function validationError(message) {
@@ -392,7 +392,7 @@ var TOOL_NAME_MIGRATIONS = /* @__PURE__ */ new Map([
392
392
  ["list-entries", 'context action="list"'],
393
393
  ["get-entry", 'context action="get"'],
394
394
  ["batch-get", 'context action="batch"'],
395
- ["search", 'entries action="search"'],
395
+ ["search", 'context action="search"'],
396
396
  ["relate-entries", 'relations action="create"'],
397
397
  ["batch-relate", 'relations action="batch-create"'],
398
398
  ["find-related", 'relations action="find"'],
@@ -639,7 +639,7 @@ ${msg}
639
639
  "CAPTURE_OUTCOME_UNKNOWN",
640
640
  msg,
641
641
  recovery,
642
- [{ tool: "entries", description: "Search for the entry before retrying", parameters: { action: "search", query: name } }],
642
+ [{ tool: "context", description: "Search for the entry before retrying", parameters: { action: "search", query: name } }],
643
643
  {
644
644
  // Structured so a caller can branch on this without parsing prose — the
645
645
  // reconciliation signal TEN-1126 says the capture path never had.
@@ -2001,7 +2001,7 @@ Use \`context action=get\` to inspect the existing entry, or \`entries action=up
2001
2001
  if (isBetOrGoal && !hasStrategyLink) {
2002
2002
  lines.push("");
2003
2003
  lines.push(
2004
- `**Strategy link:** This ${isWorkPackageOrBetCapture ? "work package" : "goal"} doesn't connect to any strategy entry. Consider linking before accepting. Find one with \`entries action=search\` and link it with \`relations action=create\`.`
2004
+ `**Strategy link:** This ${isWorkPackageOrBetCapture ? "work package" : "goal"} doesn't connect to any strategy entry. Consider linking before accepting. Find one with \`context action=search\` and link it with \`relations action=create\`.`
2005
2005
  );
2006
2006
  await recordSessionActivity({ strategyLinkWarnedForEntryId: internalId });
2007
2007
  }
@@ -2025,13 +2025,13 @@ Use \`context action=get\` to inspect the existing entry, or \`entries action=up
2025
2025
  lines.push("## Next Steps");
2026
2026
  const eid = finalEntryId || "(check entry ID)";
2027
2027
  if (finalStatus === "committed") {
2028
- lines.push(`1. **Connect it:** find related entries with \`entries action=search\`, then \`relations action=create from="${eid}" to="<ID>" type="<verb>"\``);
2028
+ lines.push(`1. **Connect it:** find related entries with \`context action=search\`, then \`relations action=create from="${eid}" to="<ID>" type="<verb>"\``);
2029
2029
  if (hasQualityGaps) {
2030
2030
  lines.push(`2. **Improve quality:** \`entries action=update entryId="${eid}"\` \u2014 fill missing fields`);
2031
2031
  }
2032
2032
  } else {
2033
2033
  if (userLinkResults.length === 0) {
2034
- lines.push(`1. **Connect it:** find related entries with \`entries action=search\`, then \`relations action=create from="${eid}" to="<ID>" type="<verb>"\``);
2034
+ lines.push(`1. **Connect it:** find related entries with \`context action=search\`, then \`relations action=create from="${eid}" to="<ID>" type="<verb>"\``);
2035
2035
  }
2036
2036
  lines.push(`${userLinkResults.length === 0 ? "2" : "1"}. **Review the possibility:** Keep this visible draft while it is an alternative. Accept only when commitment is intended and your role is authorized. Types reserved for human acceptance require human ratification. An audit advisory is not a reason to accept it.`);
2037
2037
  if (hasQualityGaps) {
@@ -3145,7 +3145,7 @@ ${recovery}`,
3145
3145
  "MOVE_FAILED",
3146
3146
  msg,
3147
3147
  "Check the entry ID and target collection slug, then retry.",
3148
- [{ tool: "entries", description: "Search for entry", parameters: { action: "search", query: entryId } }]
3148
+ [{ tool: "context", description: "Search for entry", parameters: { action: "search", query: entryId } }]
3149
3149
  );
3150
3150
  }
3151
3151
  }
@@ -3182,7 +3182,6 @@ function platformGlossarySearch(query, collection, status2) {
3182
3182
  // src/tools/entriesContract.ts
3183
3183
  import { z as z10 } from "zod/v3";
3184
3184
  var ENTRIES_ACTIONS = [
3185
- "search",
3186
3185
  "update",
3187
3186
  "commit",
3188
3187
  "move",
@@ -3190,7 +3189,6 @@ var ENTRIES_ACTIONS = [
3190
3189
  "preflight",
3191
3190
  "still-true"
3192
3191
  ];
3193
- var entriesStatusFilterSchema = z10.union([z10.string().max(200), z10.array(z10.enum(ENTRY_STATUS_READ_WORDS)).max(5)]);
3194
3192
  var coherencyAcknowledgementFlatSchema = z10.object({
3195
3193
  response: z10.enum(["linked", "accepted-fix", "diverged"]).describe("Explicit response to an acknowledge-required coherency challenge."),
3196
3194
  entryId: z10.string().max(200).optional().describe("Authorizing entry being linked/accepted (required for 'linked' and 'accepted-fix')."),
@@ -3200,16 +3198,15 @@ var preflightLinks = z10.array(z10.object({ type: z10.string().max(200), entryId
3200
3198
  var entriesSchema = z10.object({
3201
3199
  links: preflightLinks.describe("For preflight: proposed context links; saves nothing."),
3202
3200
  action: z10.enum(ENTRIES_ACTIONS).describe(
3203
- "'preflight': inspect structural requirements before composing (requires collection). 'search': full-text search. 'update': change fields on an existing entry (draft by default). 'commit': accept a draft entry onto the Chain. 'move': relocate an entry to a different collection (pass `canonicalKey` too for an atomic move+retype). 'verify': mark an entry as verified (lightweight \u2014 no codebase scan; see `quality action=verify-chain` for that). 'still-true': confirm accuracy (the holder of the owning role, else the nearest seated Team Lead) \u2014 distinct from 'verify'; no content, version, or updatedAt change."
3201
+ "'preflight': inspect structural requirements before composing (requires collection). 'update': change fields on an existing entry (draft by default). 'commit': accept a draft entry onto the Chain. 'move': relocate an entry to a different collection (pass `canonicalKey` too for an atomic move+retype). 'verify': mark an entry as verified (lightweight \u2014 no codebase scan; see `quality action=verify-chain` for that). 'still-true': confirm accuracy (the holder of the owning role, else the nearest seated Team Lead) \u2014 distinct from 'verify'; no content, version, or updatedAt change."
3204
3202
  ),
3205
3203
  entryId: z10.string().max(200).optional().describe(
3206
3204
  "Entry ID, e.g. '<PREFIX>-<n>'. Required for: update, commit, move, verify, still-true."
3207
3205
  ),
3208
- collection: z10.string().max(200).optional().describe("Collection slug \u2014 for 'search': scope filter, e.g. 'glossary', 'tracking-events'. For 'preflight': the collection the entry would be composed into (required)."),
3209
- status: entriesStatusFilterSchema.optional().describe(
3210
- `For 'search': one lifecycle or category value (${ENTRY_STATUS_READ_WORDS.join("|")}) OR an array of up to 5 (e.g. ['active','accepted']). For 'update': draft|archived ONLY \u2014 'accepted' is set via 'commit', never 'update'; 'active'/'deprecated' are legacy read-only words, refused on write. Workflow values use \`workflowStatus\` instead.`
3206
+ collection: z10.string().max(200).optional().describe("For 'preflight': the collection slug the entry would be composed into (required)."),
3207
+ status: z10.string().max(200).optional().describe(
3208
+ "For 'update': draft|archived ONLY \u2014 'accepted' is set via 'commit', never 'update'; 'active'/'deprecated' are legacy read-only words, refused on write. Workflow values use `workflowStatus` instead."
3211
3209
  ),
3212
- query: z10.string().min(2).max(500).optional().describe("For 'search': search text (min 2 characters)."),
3213
3210
  name: z10.string().max(ENTRY_NAME_MAX_CHARS).optional().describe("For 'update': new display name."),
3214
3211
  workflowStatus: z10.string().max(200).optional().describe(
3215
3212
  "For 'update': collection workflow state. Valid values are collection-specific and server-owned \u2014 discover via `collections action=describe`. Invalid values are rejected with the valid set."
@@ -3246,13 +3243,6 @@ var entriesSchema = z10.object({
3246
3243
  ),
3247
3244
  toCollection: z10.string().max(200).optional().describe("For 'move': target collection slug, e.g. 'decisions', 'architecture'.")
3248
3245
  });
3249
- var entriesSearchVariant = z10.object({
3250
- action: z10.literal("search"),
3251
- query: z10.string().min(2).max(500),
3252
- collection: z10.string().max(200).optional(),
3253
- status: entriesStatusFilterSchema.optional()
3254
- // PR #660 R1 Zqh1K: string|array.
3255
- });
3256
3246
  var entriesUpdateVariant = updateEntrySchema.extend({ action: z10.literal("update") });
3257
3247
  var entriesCommitVariant = commitEntrySchema.extend({ action: z10.literal("commit") });
3258
3248
  var entriesMoveVariant = z10.object({
@@ -3266,7 +3256,6 @@ var entriesVerifyVariant = verifyEntrySchema.extend({ action: z10.literal("verif
3266
3256
  var entriesStillTrueVariant = stillTrueEntrySchema.extend({ action: z10.literal("still-true") });
3267
3257
  var entriesActionUnion = z10.discriminatedUnion("action", [
3268
3258
  z10.object({ action: z10.literal("preflight"), collection: z10.string().max(200), canonicalKey: z10.string().max(200).optional(), links: preflightLinks }),
3269
- entriesSearchVariant,
3270
3259
  entriesUpdateVariant,
3271
3260
  entriesCommitVariant,
3272
3261
  entriesMoveVariant,
@@ -3275,7 +3264,6 @@ var entriesActionUnion = z10.discriminatedUnion("action", [
3275
3264
  ]);
3276
3265
  var ENTRIES_ACTION_SPECS = {
3277
3266
  preflight: { params: ["collection", "canonicalKey", "links"], description: "Inspect structure before composition; no writes or permission grant." },
3278
- search: { params: ["query", "collection", "status"], description: "Full-text search; query is required (min 2 chars)." },
3279
3267
  update: { params: ["entryId", "name", "status", "workflowStatus", "data", "order", "canonicalKey", "autoPublish", "changeNote", "changeReason", "sourceRef", "sourceExcerpt", "steeringOverrideReason", "coherencyAcknowledgement"], description: "entryId is required; every other field is optional." },
3280
3268
  commit: { params: ["entryId", "preview", "steeringOverrideReason", "coherencyAcknowledgement"], description: "entryId is required." },
3281
3269
  move: { params: ["entryId", "toCollection", "canonicalKey"], description: "entryId and toCollection are required; canonicalKey is optional (atomic move+retype)." },
@@ -3429,7 +3417,6 @@ function registerEntriesTools(server) {
3429
3417
  const result2 = await kernelQuery("chain.preflightEntry", { collectionSlug: data.collection, canonicalKey: data.canonicalKey, links: data.links });
3430
3418
  return { content: [{ type: "text", text: renderEntryPreflight(result2).join("\n") }], structuredContent: success("Structural requirements checked; nothing saved.", result2) };
3431
3419
  },
3432
- search: (data) => handleSearch(server, data.query, data.collection, data.status),
3433
3420
  // update/commit reuse knowledge.ts's extracted handlers — "entries" routes
3434
3421
  // `next` at itself (toolName="entries") instead of the legacy tool names.
3435
3422
  update: (data) => handleUpdateEntry(data, "entries"),
@@ -3442,10 +3429,10 @@ function registerEntriesTools(server) {
3442
3429
  "entries",
3443
3430
  {
3444
3431
  title: "Entries",
3445
- description: 'Read and manage entries on the Chain. One tool for the entry lifecycle.\n\n- **preflight**: Inspect a type and selected context before composing. No writes, capacity reservation or authority grant.\n- **search**: Full-text search across entries. Scope by collection or filter by status.\n- **update**: Change fields on an existing entry (publishes whenever the entry is not draft \u2014 includes archived, not just accepted/active; autoPublish is accepted but ignored).\n- **commit**: Accept a draft entry onto the Chain (SSOT). Runs the contradiction preflight first.\n- **move**: Relocate an entry to a different collection; pass canonicalKey too for an atomic move+retype.\n- **verify**: Mark verified (lightweight, no scan \u2014 see `quality action=verify-chain`).\n- **still-true**: confirm accuracy (the holder of the owning role; if that role is empty, the nearest seated Team Lead up the team tree).\n\nOpen, list and trace entries with the read-only `context` tool: `context action=get entryId="..."`. Use `entries action=search query="..."` to discover.',
3432
+ description: 'Write entries on the Chain: the entry lifecycle after capture. Reads live on `context`.\n\n- **preflight**: Inspect a type and selected context before composing. No writes, capacity reservation or authority grant.\n- **update**: Change fields on an existing entry (publishes whenever the entry is not draft \u2014 includes archived, not just accepted/active; autoPublish is accepted but ignored).\n- **commit**: Accept a draft entry onto the Chain (SSOT). Runs the contradiction preflight first.\n- **move**: Relocate an entry to a different collection; pass canonicalKey too for an atomic move+retype.\n- **verify**: Mark verified (lightweight, no scan \u2014 see `quality action=verify-chain`).\n- **still-true**: confirm accuracy (the holder of the owning role; if that role is empty, the nearest seated Team Lead up the team tree).\n\nRead entries with the read-only `context` tool: `context action=get entryId="..."`, `context action=search query="..."`.',
3446
3433
  inputSchema: entriesSchema,
3447
- // Mixed read/write noun (§3 R3): can't be marked read-only once update/commit/move
3448
- // live here too — accepted for the 11-tool default (§9 R3).
3434
+ // DEC-1894 / DEC-74: every look-up lives on the read-only `context` tool, so this
3435
+ // annotation tells hosts the truth about the writes left here.
3449
3436
  annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false }
3450
3437
  },
3451
3438
  thinWrapper(async (args) => {
@@ -3728,9 +3715,9 @@ async function handleSearch(server, query, collection, status2) {
3728
3715
  const platform = platformGlossarySearch(query, collection, status2);
3729
3716
  const matches = results.length + platform.count;
3730
3717
  if (matches === 0) {
3731
- const recorded = recordGap({ query, tool: "entries", action: "search", gapType: "search_zero", collectionScope: collection });
3718
+ const recorded = recordGap({ query, tool: "context", action: "search", gapType: "search_zero", collectionScope: collection });
3732
3719
  if (recorded) {
3733
- getWorkspaceId().then((wsId) => trackKnowledgeGap(wsId, { query, tool: "entries", action: "search", gap_type: "search_zero", collection_scope: collection })).catch(() => {
3720
+ getWorkspaceId().then((wsId) => trackKnowledgeGap(wsId, { query, tool: "context", action: "search", gap_type: "search_zero", collection_scope: collection })).catch(() => {
3734
3721
  });
3735
3722
  }
3736
3723
  return {
@@ -3742,7 +3729,7 @@ async function handleSearch(server, query, collection, status2) {
3742
3729
  `'${query}' is not yet on the Chain${scope}.`,
3743
3730
  { entries: [], total: 0, query },
3744
3731
  [
3745
- { tool: "entries", description: "Try a broader search", parameters: { action: "search", query: query.split(" ")[0] } },
3732
+ { tool: "context", description: "Try a broader search", parameters: { action: "search", query: query.split(" ")[0] } },
3746
3733
  { tool: "collections", description: "Browse available collections", parameters: { action: "list" } }
3747
3734
  ]
3748
3735
  )
@@ -3842,7 +3829,7 @@ async function handleFind(entryId, direction) {
3842
3829
  }
3843
3830
  const sourceEntry = await kernelQuery("chain.getEntry", { entryId });
3844
3831
  if (!sourceEntry) {
3845
- return notFoundResult(entryId, `Entry '${entryId}' not found. Try entries action=search to find the right ID.`);
3832
+ return notFoundResult(entryId, `Entry '${entryId}' not found. Try context action=search to find the right ID.`);
3846
3833
  }
3847
3834
  const sourceInternalId = sourceEntry._id;
3848
3835
  const MAX_RELATIONS = 25;
@@ -3989,7 +3976,7 @@ function registerRelationsTools(server) {
3989
3976
  "relations",
3990
3977
  {
3991
3978
  title: "Relations",
3992
- description: "Create, manage, and read relations between entries. A relation is written only when you ask for it, with exactly the verb you send.\n\n- **create**: Link two entries with a typed relation.\n- **batch-create**: Create multiple relations in one call (validates every item before writing any).\n- **delete**: Remove a relation by from, to, and type.\n- **find**: Traverse relations from a specific entry \u2014 shows incoming/outgoing connections. NOT full-text search (use entries action=search).",
3979
+ description: "Create, manage, and read relations between entries. A relation is written only when you ask for it, with exactly the verb you send.\n\n- **create**: Link two entries with a typed relation.\n- **batch-create**: Create multiple relations in one call (validates every item before writing any).\n- **delete**: Remove a relation by from, to, and type.\n- **find**: Traverse relations from a specific entry \u2014 shows incoming/outgoing connections. NOT full-text search (use context action=search).",
3993
3980
  inputSchema: relationsSchema,
3994
3981
  // Mixed read/write noun (§3 R3): find is read-only, create/batch-create/delete write.
3995
3982
  annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: false }
@@ -4273,14 +4260,16 @@ This row pre-dates snapshot capture (legacy backfill), so no summary is availabl
4273
4260
 
4274
4261
  // src/tools/contextLookups.ts
4275
4262
  import { z as z15 } from "zod/v3";
4276
- var LOOKUP_ACTION_DESCRIBE = "'get': one entry in full by ID. 'batch': up to 20 entries by ID. 'history': audit trail for an entry. 'list': browse entries with filters (accepted by default). ";
4277
- var LOOKUP_TOOL_LINES = "- **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- **history**: Audit trail for an entry.\n- **list**: Browse entries with optional filters (collection, status, tag, label). Use collections action=list first to discover slugs.\n";
4263
+ var statusFilterSchema = z15.union([z15.string().max(200), z15.array(z15.enum(ENTRY_STATUS_READ_WORDS)).max(5)]);
4264
+ var LOOKUP_ACTION_DESCRIBE = "'get': one entry in full by ID. 'batch': up to 20 entries by ID. 'history': audit trail for an entry. 'list': browse entries with filters (accepted by default). 'search': full-text search across entries. ";
4265
+ var LOOKUP_TOOL_LINES = "- **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- **history**: Audit trail for an entry.\n- **list**: Browse entries with optional filters (collection, status, tag, label). Use collections action=list first to discover slugs.\n- **search**: Full-text search across entries. Scope by collection or filter by status.\n";
4278
4266
  var lookupParams = {
4279
4267
  entryIds: z15.array(z15.string().max(200)).min(1).max(20).optional().describe("For 'batch': entry IDs, e.g. ['TYPE-strategy', 'STR-jljeg7']"),
4280
- collection: z15.string().max(200).optional().describe("For 'list': collection slug, e.g. 'glossary', 'tracking-events'."),
4268
+ collection: z15.string().max(200).optional().describe("For 'list'/'search': collection slug, e.g. 'glossary', 'tracking-events'."),
4269
+ query: z15.string().min(2).max(500).optional().describe("For 'search': search text (min 2 characters)."),
4281
4270
  // 'active'/'accepted'/'current' are the same trust level (DEC-1575/DEC-1788) — all enumerated, never one substituted.
4282
- status: z15.string().max(200).optional().describe(
4283
- `For 'list': defaults to accepted entries (active/accepted/current); use status='draft' to discover drafts. One lifecycle or category value (${ENTRY_STATUS_READ_WORDS.join("|")}).`
4271
+ status: statusFilterSchema.optional().describe(
4272
+ `For 'list': defaults to accepted entries (active/accepted/current); use status='draft' to discover drafts. One lifecycle or category value (${ENTRY_STATUS_READ_WORDS.join("|")}). For 'search': one value OR an array of up to 5 (e.g. ['active','accepted']).`
4284
4273
  ),
4285
4274
  tag: z15.string().max(200).optional().describe("For 'list': filter by internal tag."),
4286
4275
  label: z15.string().max(200).optional().describe("For 'list': filter by label slug \u2014 matches entries across all collections.")
@@ -4293,23 +4282,34 @@ var lookupVariants = [
4293
4282
  action: z15.literal("list"),
4294
4283
  collection: z15.string().max(200).optional(),
4295
4284
  status: z15.string().max(200).optional(),
4296
- // one status word: the flat schema advertises exactly this
4285
+ // one status word; the flat union serves search
4297
4286
  tag: z15.string().max(200).optional(),
4298
4287
  label: z15.string().max(200).optional()
4288
+ }),
4289
+ z15.object({
4290
+ action: z15.literal("search"),
4291
+ query: z15.string().min(2).max(500),
4292
+ collection: z15.string().max(200).optional(),
4293
+ status: statusFilterSchema.optional()
4299
4294
  })
4300
4295
  ];
4301
4296
  var LOOKUP_ACTION_SPECS = {
4302
4297
  get: { params: ["entryId"], description: "entryId is required." },
4303
4298
  batch: { params: ["entryIds"], description: "entryIds (1-20) is required." },
4304
4299
  history: { params: ["entryId"], description: "entryId is required." },
4305
- list: { params: ["collection", "status", "tag", "label"], description: "Browse accepted entries by default; status='draft' lists drafts. All params optional." }
4306
- };
4307
- var lookupHandlers = {
4308
- get: (data) => handleGet(data.entryId),
4309
- batch: (data) => handleBatch(data.entryIds),
4310
- history: (data) => handleGetHistory(data),
4311
- list: (data) => handleList(data.collection, data.status, data.tag, data.label)
4300
+ list: { params: ["collection", "status", "tag", "label"], description: "Browse accepted entries by default; status='draft' lists drafts; status is one word. All params optional." },
4301
+ search: { params: ["query", "collection", "status"], description: "Full-text search; query is required (min 2 chars)." }
4312
4302
  };
4303
+ function lookupHandlers(server) {
4304
+ return {
4305
+ get: (data) => handleGet(data.entryId),
4306
+ batch: (data) => handleBatch(data.entryIds),
4307
+ history: (data) => handleGetHistory(data),
4308
+ list: (data) => handleList(data.collection, data.status, data.tag, data.label),
4309
+ search: (data) => handleSearch(server, data.query, data.collection, data.status)
4310
+ // logs progress to the client
4311
+ };
4312
+ }
4313
4313
 
4314
4314
  // src/tools/context.ts
4315
4315
  function annotateStaleNames(text) {
@@ -4322,7 +4322,7 @@ function epistemicCollectionHint(collectionName) {
4322
4322
  if (lc === "assumptions") return " \u2014 _check evidence strength with `context action=get`_";
4323
4323
  return "";
4324
4324
  }
4325
- var CONTEXT_ACTIONS = ["get", "batch", "history", "list", "gather", "build", "neighborhood", "changes", "chain", "cross-cut", "incremental", "brief", "last-verified-brief"];
4325
+ var CONTEXT_ACTIONS = ["get", "batch", "history", "list", "search", "gather", "build", "neighborhood", "changes", "chain", "cross-cut", "incremental", "brief", "last-verified-brief"];
4326
4326
  var contextSchema = z16.object({
4327
4327
  // provenance: neighborhood BET-142; changes/chain/cross-cut/incremental/brief BET-239 (E4, E6)
4328
4328
  action: z16.enum(CONTEXT_ACTIONS).describe(
@@ -4432,7 +4432,7 @@ var CONTEXT_ACTION_SPECS = {
4432
4432
  };
4433
4433
  function registerContextTools(server) {
4434
4434
  const contextHandlers = {
4435
- ...lookupHandlers,
4435
+ ...lookupHandlers(server),
4436
4436
  gather: (data) => data.mapEntryId ? handleJourneyGather(server, data.mapEntryId, data.maxHops ?? 2, data.maxResults ?? 20) : handleGather(server, data.entryId, data.task, data.mode ?? "search", data.maxHops ?? 2, data.maxResults ?? 10, data.strategy ?? "keyword"),
4437
4437
  build: (data) => handleBuild(server, data.entryId, data.maxHops ?? 2),
4438
4438
  neighborhood: (data) => handleNeighborhood(data.entryId),
@@ -4600,7 +4600,7 @@ _This helps future sessions start with better constraints and context._`
4600
4600
  "NOT_FOUND",
4601
4601
  "No task-relevant governance or supporting context was found yet.",
4602
4602
  "If you discover relevant knowledge during this task, capture it with a name and description.",
4603
- [{ tool: "entries", description: "Search for related terms", parameters: { action: "search", query: task.split(" ").slice(0, 3).join(" ") } }]
4603
+ [{ tool: "context", description: "Search for related terms", parameters: { action: "search", query: task.split(" ").slice(0, 3).join(" ") } }]
4604
4604
  )
4605
4605
  };
4606
4606
  }
@@ -6567,7 +6567,7 @@ function buildTaskAlignmentLines(ta) {
6567
6567
  return lines;
6568
6568
  }
6569
6569
  var CORE_PROTOCOL_BASE = [
6570
- '**Search before proposing.** Before suggesting new features, architecture, or changes, search the Chain: `entries action=search query="<relevant terms>"`. Build on what exists.',
6570
+ '**Search before proposing.** Before suggesting new features, architecture, or changes, search the Chain: `context action=search query="<relevant terms>"`. Build on what exists.',
6571
6571
  "**Reference by ID.** When discussing a topic that has Chain entries, cite them by entry ID (e.g. `DEC-50`, `PRI-3`). This keeps conversations grounded in shared knowledge.",
6572
6572
  "**Check scope.** If the proposed work doesn't fall under an active work package, stop and say so. Do not design implementation for out-of-scope work without explicit user go-ahead.",
6573
6573
  `**Capture continuously.** When a decision, tension, insight, or new term surfaces during work, capture it as a draft immediately. Don't defer to "later."`
@@ -6798,7 +6798,7 @@ var WORKING_WITH_PEOPLE_LINES = [
6798
6798
  var TITLES_LINE = "These are titles: read an entry in full before you explain or judge it.";
6799
6799
  var BRIEFING_PULL_COMMANDS = {
6800
6800
  cli: 'pb orient --task "<what you are doing>" \xB7 pb get <ID> \xB7 pb search <query>',
6801
- mcp: 'orient task="<what you are doing>" \xB7 context action=get entryId=<ID> \xB7 entries action=search query=<query>'
6801
+ mcp: 'orient task="<what you are doing>" \xB7 context action=get entryId=<ID> \xB7 context action=search query=<query>'
6802
6802
  };
6803
6803
  var BRIEFING_ANSWER_COMMANDS = {
6804
6804
  cli: 'pb question answer <ID> "<answer>"',
@@ -8481,7 +8481,7 @@ Use \`workflows action=checkpoint\` after each round to persist progress to the
8481
8481
  label: "Gather Context",
8482
8482
  type: "open",
8483
8483
  instruction: "Before shaping, let's see what the Chain already knows. Search for related entries, business rules, and existing decisions.",
8484
- facilitatorGuidance: "**Investigate proactively.** Spawn sub-agents in parallel: (1) `explore` agent to search the codebase for code related to the work package topic \u2014 find modules, patterns, and pain points. (2) `generalPurpose` agent to search the Chain: call `orient`, use `entries action=search` with keywords, surface related tensions, active work packages, and applicable business rules. Synthesize both into a 3-5 line context brief: what the codebase reveals, what the Chain knows, what governance applies. Present with IDs and file paths. Build a system map: what modules, data flows, and contracts exist in this area today? Check governance: do any principles, standards, or business rules constrain this design space? Then transition: 'Here's what I found. Does this match the problem you're seeing?'",
8484
+ facilitatorGuidance: "**Investigate proactively.** Spawn sub-agents in parallel: (1) `explore` agent to search the codebase for code related to the work package topic \u2014 find modules, patterns, and pain points. (2) `generalPurpose` agent to search the Chain: call `orient`, use `context action=search` with keywords, surface related tensions, active work packages, and applicable business rules. Synthesize both into a 3-5 line context brief: what the codebase reveals, what the Chain knows, what governance applies. Present with IDs and file paths. Build a system map: what modules, data flows, and contracts exist in this area today? Check governance: do any principles, standards, or business rules constrain this design space? Then transition: 'Here's what I found. Does this match the problem you're seeing?'",
8485
8485
  outputSchema: {
8486
8486
  field: "context",
8487
8487
  description: "System map, Chain context, governance constraints, related entries",
@@ -8669,7 +8669,7 @@ var IMPLEMENTATION_REVIEW_WORKFLOW_DESCRIPTOR = {
8669
8669
  1. **Tool-heavy, not chat-heavy.** Each round calls specific tools: orient, quality, verify, context action=gather, review-against-rules. Use Context7 **CLI** (\`npx ctx7 library\` then \`npx ctx7 docs\` \u2014 project-local after \`npm install\`; avoid cold \`npx ctx7@latest\` in short-timeout shells) for relevant testing and framework docs \u2014 not for Chain truth. Do not use Context7 MCP.
8670
8670
  2. **Spawn sub-agents** for parallel review: (a) code/architecture review, (b) test honesty (did we edit tests to pass or do they validate real behavior?). Max 2 agents in parallel, 30s budget each. **Constrain each sub-agent to the stated review scope only.**
8671
8671
  3. **Fix-as-you-go (FEAT-172).** When you find a HIGH or MEDIUM issue: fix it immediately, verify (lints, types), then proceed. The user sees clean work, not a list of issues. Only defer if estimated >5 min \u2014 capture deferred items as tensions. If user says "skip", capture as tension and continue.
8672
- 4. **Chain is SSOT.** Call orient or start first. Use entries action=search and context action=gather to load relevant BETs, DECs, BRs. If findings conflict with Chain entries, report the conflict and cite the entry ID.
8672
+ 4. **Chain is SSOT.** Call orient or start first. Use context action=search and context action=gather to load relevant BETs, DECs, BRs. If findings conflict with Chain entries, report the conflict and cite the entry ID.
8673
8673
  5. **One round at a time.** Complete each round before moving to the next. Checkpoint progress.
8674
8674
  6. **Extract learnings (FEAT-174).** After fixing issues, ask: is this a recurring pattern? Offer to capture structural patterns as standards or business rules so future reviews check automatically.
8675
8675
  7. **CRITICAL: End with BET/chain IDs.** The final output MUST include a single sentence: "BET/feature IDs reviewed: [IDs]. [One-line summary of findings]."
@@ -8839,7 +8839,7 @@ var PROCESS_CHANGE_WORKFLOW_DESCRIPTOR = {
8839
8839
  ## Tool Usage
8840
8840
 
8841
8841
  - \`orient\` \u2014 load workspace context (governance, active work packages, stale entries)
8842
- - \`entries action=search\` \u2014 find related entries
8842
+ - \`context action=search\` \u2014 find related entries
8843
8843
  - \`capture\` \u2014 manual fallback only if workflow finalization cannot safely route the entry
8844
8844
  - \`relations action=create\` or \`relations action=batch-create\` \u2014 link to related entries
8845
8845
  - \`entries action=commit\` \u2014 promote to SSOT (only on user confirmation)
@@ -8858,7 +8858,7 @@ var PROCESS_CHANGE_WORKFLOW_DESCRIPTOR = {
8858
8858
  label: "Quick Context",
8859
8859
  type: "open",
8860
8860
  instruction: "What are you working on? Orient to load relevant Chain context.",
8861
- facilitatorGuidance: "Call orient to get workspace context. Ask what the user is changing \u2014 or infer from their initial message. Search the Chain for related entries: entries action=search with keywords from their description. Present only the 2-3 most relevant entries, not a full briefing. If the user already described the change, skip the question and confirm what you understood.",
8861
+ facilitatorGuidance: "Call orient to get workspace context. Ask what the user is changing \u2014 or infer from their initial message. Search the Chain for related entries: context action=search with keywords from their description. Present only the 2-3 most relevant entries, not a full briefing. If the user already described the change, skip the question and confirm what you understood.",
8862
8862
  outputSchema: {
8863
8863
  field: "context",
8864
8864
  description: "What's being changed and relevant Chain context",
@@ -8886,7 +8886,7 @@ var PROCESS_CHANGE_WORKFLOW_DESCRIPTOR = {
8886
8886
  label: "Impact & Links",
8887
8887
  type: "synthesis",
8888
8888
  instruction: "What's affected? Are there existing Chain entries that relate to this change?",
8889
- facilitatorGuidance: "Search the Chain for entries that should be linked: entries action=search with keywords from the change. Check: does this change affect an active work package? Does it resolve a known tension? Does it supersede an existing decision? If the change is small and self-contained, this round can be brief \u2014 just confirm there's nothing obvious to link. If there are stale entries that this change invalidates, flag them for reconfirmation.",
8889
+ facilitatorGuidance: "Search the Chain for entries that should be linked: context action=search with keywords from the change. Check: does this change affect an active work package? Does it resolve a known tension? Does it supersede an existing decision? If the change is small and self-contained, this round can be brief \u2014 just confirm there's nothing obvious to link. If there are stale entries that this change invalidates, flag them for reconfirmation.",
8890
8890
  outputSchema: {
8891
8891
  field: "impact",
8892
8892
  description: "Affected entries and proposed links",
@@ -10132,8 +10132,8 @@ async function handleReEvaluate(entryId, context) {
10132
10132
  `Entry '${entryId}' not found or has no rubric.`,
10133
10133
  "NOT_FOUND",
10134
10134
  `Entry '${entryId}' not found or has no rubric.`,
10135
- "Use entries action=search to find the correct ID.",
10136
- [{ tool: "entries", description: "Search entries", parameters: { action: "search", query: entryId } }]
10135
+ "Use context action=search to find the correct ID.",
10136
+ [{ tool: "context", description: "Search entries", parameters: { action: "search", query: entryId } }]
10137
10137
  );
10138
10138
  }
10139
10139
  const llmScheduled = result2.verdict.tier !== "passive";
@@ -12769,9 +12769,9 @@ var AGENT_CHEATSHEET = `# Product Brain \u2014 Agent Cheatsheet
12769
12769
  |---|---|---|
12770
12770
  | \`orient\` | Workspace context, governance, active work packages, session start | \`action\`: start, task |
12771
12771
  | \`capture\` | Create entry | \`action\`: capture |
12772
- | \`entries\` | Find and write entries | \`action\`: search, update, commit, move, verify, preflight, still-true |
12772
+ | \`entries\` | Write entries | \`action\`: update, commit, move, verify, preflight, still-true |
12773
12773
  | \`relations\` | Link entries, delete links, find connections | \`action\`: create, batch-create, delete, find |
12774
- | \`context\` | Reads; only incremental writes | \`action\`: get, batch, history, list, gather, build, neighborhood, changes, chain, cross-cut, incremental, brief, last-verified-brief |
12774
+ | \`context\` | Reads; only incremental writes | \`action\`: get, batch, history, list, search, gather, build, neighborhood, changes, chain, cross-cut, incremental, brief, last-verified-brief |
12775
12775
  | \`collections\` | Browse, describe, audit and export collections; manage labels | \`action\`: list, update, describe, audit, export, label-* |
12776
12776
  | \`quality\` | Score an entry, verify the Chain, spine check | \`action\`: check, re-evaluate, verify-chain, spine-check |
12777
12777
  | \`session\` | Start / close, wrapup, resume, constellation accept | \`action\`: start, close, status, wrapup-review, wrapup-commit, resume, commit-constellation |
@@ -12846,7 +12846,7 @@ Tags for filtering (e.g. \`severity:high\`), relations via \`entryRelations\`, v
12846
12846
  );
12847
12847
  }
12848
12848
  sections.push(
12849
- '## Rules\nThe rules that bind you are in the briefing above, each with its why. A rule on no list binds nobody.\nOpen one: `context action=get entryId="<ID>"`. Find one: `entries action=search query="<noun>"`.\nDraft a new rule: use the `draft-rule-from-context` prompt.'
12849
+ '## Rules\nThe rules that bind you are in the briefing above, each with its why. A rule on no list binds nobody.\nOpen one: `context action=get entryId="<ID>"`. Find one: `context action=search query="<noun>"`.\nDraft a new rule: use the `draft-rule-from-context` prompt.'
12850
12850
  );
12851
12851
  sections.push(
12852
12852
  "## Knowledge Graph\nEntries are connected via typed relations (`entryRelations` table). Relations are bidirectional and collection-agnostic \u2014 any entry can link to any other entry.\n\n**Recommended relation types** (extensible \u2014 any string accepted):\n- `governs` \u2014 a rule constrains behavior of a feature\n- `defines_term_for` \u2014 a glossary term is canonical vocabulary for a feature/area\n- `belongs_to` \u2014 a feature belongs to a product area or parent concept (typed successor: `anchored_to`)\n- `informs` \u2014 a decision or insight informs a feature\n- `surfaces_tension_in` \u2014 a tension exists within a feature area\n- `related_to`, `depends_on`, `replaces`, `conflicts_with`, `references`, `confused_with`\n\nEach relation type is defined as a glossary entry (prefix `GT-REL-*`) to prevent terminology drift.\n\n**Tools:**\n- `context action=gather` \u2014 get the full context around any entry (multi-hop graph traversal)\n- `relations action=create` \u2014 create a typed link between two entries\n- `relations action=find` \u2014 list direct relations for an entry\n\n**Convention:** A relation is written only when you ask for it, with exactly the verb you send \u2014 link the entries you know are related with `relations action=create`."
@@ -13445,7 +13445,7 @@ var INSTRUCTIONS = [
13445
13445
  "",
13446
13446
  '- `orient action=task task="<what you are doing>"`: context shaped to the task, with the rules for your team and role.',
13447
13447
  '- `context action=get entryId="<ID>"`: one entry in full, with data, relations and history.',
13448
- '- `entries action=search query="<noun>"`: find entries by what they are about.',
13448
+ '- `context action=search query="<noun>"`: find entries by what they are about.',
13449
13449
  "",
13450
13450
  "## Writing",
13451
13451
  "",
@@ -13552,4 +13552,4 @@ export {
13552
13552
  createProductBrainServer,
13553
13553
  initFeatureFlags
13554
13554
  };
13555
- //# sourceMappingURL=chunk-WKLD42CD.js.map
13555
+ //# sourceMappingURL=chunk-O6HEYDXJ.js.map