@anchrd/intel-api 0.38.0 → 0.39.0

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/mcp/mcp.js CHANGED
@@ -218,7 +218,7 @@ export async function handleMcp(request, deps) {
218
218
  }, async (input) => text(await deps.boards.resolveAssignees(actor, input)));
219
219
  server.registerTool("board_task_create", {
220
220
  title: "Add a card to a board",
221
- description: "File a new card on a board. Omit the status to put it in the first column. Name a parent task to make it a subtask — it lands on the same board, and moving an existing card under another one is `node_update` with a new parent. The card is a node like any other: its own address, its own permissions, its own history.",
221
+ description: "File a new card on a board. Omit the status to put it in the first column. Name a parent task to make it a subtask — it lands on the same board, and moving an existing card under another one is `node_update` with a new parent. The card is a node like any other: its own address, its own permissions, its own history — and its own body. This call answers with the BOARD rather than the new card, so to write that body, make the card with `node_create` under the board instead: it answers with the node itself, files it on the board just the same, and hands you the id `node_version_create` asks for.",
222
222
  inputSchema: BoardTaskCreateInput,
223
223
  annotations: {
224
224
  title: "Add a card to a board",
@@ -539,7 +539,7 @@ export async function handleMcp(request, deps) {
539
539
  if (permits(deps.authorization, "nodes", "create")) {
540
540
  server.registerTool("node_create", {
541
541
  title: "Create node",
542
- description: "Create a governed folder, document, attachment, or table node.",
542
+ description: "Create a governed node: a folder, a board, a document, a card, an attachment or a table. A card made under a board lands on that board, and the answer carries the new node's id — which is what `node_version_create` needs to give it a body.",
543
543
  inputSchema: CreateNodeInput,
544
544
  annotations: {
545
545
  title: "Create node",
@@ -553,7 +553,7 @@ export async function handleMcp(request, deps) {
553
553
  if (permits(deps.authorization, "nodes", "write")) {
554
554
  server.registerTool("node_version_create", {
555
555
  title: "Create node version",
556
- description: "Append an immutable content version using an optimistic base version.",
556
+ description: "Append an immutable content version using an optimistic base version. Documents and board cards both take one — writing a card here is how a ticket gets a body instead of only a title.",
557
557
  inputSchema: SaveNodeVersionInput,
558
558
  annotations: {
559
559
  title: "Create node version",
@@ -27,6 +27,22 @@ const nothingWithheld = { titles: [], hidden: 0 };
27
27
  function applicableVerbs(kind) {
28
28
  return kind === "folder" ? ["read", "write", "execute", "share"] : ["read", "write", "share"];
29
29
  }
30
+ /**
31
+ * Which kinds hold an editor body — the text somebody types and `node_get` reads back.
32
+ *
33
+ * ⚠️ **A card is one of them, and that is the whole of D66 on the write side** (#785). A task is a
34
+ * node like every other: its text is a node version, in the same table, through the same route. The
35
+ * panel reaches this call through `POST /nodes/:id/versions` exactly as MCP does, so a list that
36
+ * omitted `task` closed BOTH surfaces at once — an agent could name a card and not describe it, and
37
+ * a reader typing into the card got "could not be saved" over a body the model says it should hold.
38
+ *
39
+ * ⚠️ **A set, not one more `||`.** The other four kinds each carry their content some other way —
40
+ * a folder and a board hold children, an attachment holds bytes, a table holds CSV segments — and
41
+ * naming the ones that DO take an editor version is what keeps the next kind from being waved
42
+ * through by a condition that only ever grew. The annotation ties it to the enum: a kind renamed in
43
+ * the contract stops this file from compiling instead of silently dropping out of the set.
44
+ */
45
+ const EditorContentKinds = ["document", "task"];
30
46
  // ⚠️ The refusal has to be actionable without becoming a directory of the tree. Whoever holds
31
47
  // `share` on one folder must not learn the titles of flows they may not see, so the ones they may
32
48
  // see are named and the rest are only counted (ADR-0004 §3, and #17's review) — which is the whole
@@ -666,8 +682,8 @@ export function createNodes(deps) {
666
682
  return document;
667
683
  }
668
684
  const node = await requireVisible(actor, input.nodeId);
669
- if (node.kind !== "document") {
670
- throw new IntelError(409, "document_content_required", "Only documents accept editor content versions");
685
+ if (!EditorContentKinds.includes(node.kind)) {
686
+ throw new IntelError(409, "document_content_required", "Only documents and cards accept editor content versions");
671
687
  }
672
688
  if (!(await deps.repository.can(actor, node.id, "write"))) {
673
689
  throw new IntelError(403, "node_forbidden", "This node cannot be edited");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anchrd/intel-api",
3
- "version": "0.38.0",
3
+ "version": "0.39.0",
4
4
  "type": "module",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
@@ -43,7 +43,7 @@
43
43
  },
44
44
  "dependencies": {
45
45
  "@anchrd/gate-sdk": "^0.26.0",
46
- "@anchrd/intel-contract": "^0.30.0",
46
+ "@anchrd/intel-contract": "^0.31.0",
47
47
  "@cfworker/json-schema": "^4.1.1",
48
48
  "@modelcontextprotocol/sdk": "^1.30.0",
49
49
  "fflate": "^0.8.3",