kanban-lite 1.2.9 → 1.2.11

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/cli.js CHANGED
@@ -42,6 +42,44 @@ function getTitleFromContent(content) {
42
42
  const firstLine = content.split("\n").map((l) => l.trim()).find((l) => l.length > 0);
43
43
  return firstLine || "Untitled";
44
44
  }
45
+ function getMetadataPathValue(metadata, path24) {
46
+ if (!metadata || !path24.trim())
47
+ return void 0;
48
+ return path24.split(".").reduce((current, key) => {
49
+ if (current === null || current === void 0 || typeof current !== "object") {
50
+ return void 0;
51
+ }
52
+ return current[key];
53
+ }, metadata);
54
+ }
55
+ function stringifyDisplayTitlePrefix(value) {
56
+ if (value === null || value === void 0)
57
+ return null;
58
+ if (typeof value === "string") {
59
+ const trimmed = value.trim();
60
+ return trimmed.length > 0 ? trimmed : null;
61
+ }
62
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
63
+ return String(value);
64
+ }
65
+ if (Array.isArray(value)) {
66
+ const parts = value.map((item) => stringifyDisplayTitlePrefix(item)).filter((item) => Boolean(item));
67
+ return parts.length > 0 ? parts.join(", ") : null;
68
+ }
69
+ if (typeof value === "object") {
70
+ const json2 = JSON.stringify(value);
71
+ return json2 && json2 !== "{}" && json2 !== "[]" ? json2 : null;
72
+ }
73
+ return null;
74
+ }
75
+ function getDisplayTitleFromContent(content, metadata, titleFields) {
76
+ const title = getTitleFromContent(content);
77
+ if (!titleFields || titleFields.length === 0) {
78
+ return title;
79
+ }
80
+ const prefixes = titleFields.map((field) => stringifyDisplayTitlePrefix(getMetadataPathValue(metadata, field))).filter((value) => Boolean(value));
81
+ return prefixes.length > 0 ? `${prefixes.join(" ")} ${title}` : title;
82
+ }
45
83
  function generateSlug(title) {
46
84
  return title.toLowerCase().replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 50) || "card";
47
85
  }
@@ -6515,6 +6553,7 @@ function listBoards(ctx) {
6515
6553
  columns: board.columns,
6516
6554
  actions: board.actions,
6517
6555
  metadata: board.metadata,
6556
+ title: board.title,
6518
6557
  forms: config2.forms
6519
6558
  }));
6520
6559
  }
@@ -6589,6 +6628,8 @@ function updateBoard(ctx, { boardId, updates }) {
6589
6628
  board.defaultPriority = updates.defaultPriority;
6590
6629
  if (updates.metadata !== void 0)
6591
6630
  board.metadata = updates.metadata;
6631
+ if (updates.title !== void 0)
6632
+ board.title = updates.title;
6592
6633
  writeConfig(ctx.workspaceRoot, config2);
6593
6634
  return board;
6594
6635
  }
@@ -26310,7 +26351,7 @@ var init_KanbanSDK = __esm({
26310
26351
  * Lists all boards defined in the workspace configuration.
26311
26352
  *
26312
26353
  * @returns An array of {@link BoardInfo} objects containing each board's
26313
- * `id`, `name`, and optional `description`.
26354
+ * `id`, `name`, optional `description`, and display-title metadata config.
26314
26355
  *
26315
26356
  * @example
26316
26357
  * ```ts
@@ -26379,7 +26420,7 @@ var init_KanbanSDK = __esm({
26379
26420
  * Retrieves the full configuration for a specific board.
26380
26421
  *
26381
26422
  * @param boardId - The ID of the board to retrieve.
26382
- * @returns The {@link BoardConfig} object containing columns, settings, and metadata.
26423
+ * @returns The {@link BoardConfig} object containing columns, settings, metadata, and display-title metadata config.
26383
26424
  * @throws {Error} If the board does not exist.
26384
26425
  *
26385
26426
  * @example
@@ -26404,6 +26445,7 @@ var init_KanbanSDK = __esm({
26404
26445
  * @param updates.columns - Replacement column definitions.
26405
26446
  * @param updates.defaultStatus - New default status for new cards.
26406
26447
  * @param updates.defaultPriority - New default priority for new cards.
26448
+ * @param updates.title - Ordered metadata keys whose values should prefix rendered card titles.
26407
26449
  * @returns The updated {@link BoardConfig} object.
26408
26450
  * @throws {Error} If the board does not exist.
26409
26451
  *
@@ -42879,6 +42921,17 @@ async function buildMcpCardStateMutationModel(sdk, unread) {
42879
42921
  }
42880
42922
  };
42881
42923
  }
42924
+ function getBoardTitleFieldsForMcp(sdk, boardId) {
42925
+ const config2 = sdk.getConfigSnapshot();
42926
+ const resolvedBoardId = boardId || config2.defaultBoard;
42927
+ return config2.boards[resolvedBoardId]?.title;
42928
+ }
42929
+ function decorateMcpCardTitle(card, titleFields) {
42930
+ return {
42931
+ ...card,
42932
+ title: getDisplayTitleFromContent(card.content, card.metadata, titleFields)
42933
+ };
42934
+ }
42882
42935
  function registerCardStateMcpTools(server, options) {
42883
42936
  const registeredNames = [
42884
42937
  "get_card_state_status",
@@ -43097,6 +43150,7 @@ async function main() {
43097
43150
  sort: external_exports.enum(["created:asc", "created:desc", "modified:asc", "modified:desc"]).optional().describe("Sort order: created:asc, created:desc, modified:asc, or modified:desc. Defaults to board order.")
43098
43151
  },
43099
43152
  async ({ boardId, status, priority, assignee, label, labelGroup, includeDeleted, searchQuery, fuzzy, metaFilter, sort }) => {
43153
+ const titleFields = getBoardTitleFieldsForMcp(sdk, boardId);
43100
43154
  let cards = await sdk.listCards(void 0, boardId, {
43101
43155
  metaFilter: metaFilter && Object.keys(metaFilter).length > 0 ? metaFilter : void 0,
43102
43156
  sort: sort || void 0,
@@ -43119,7 +43173,7 @@ async function main() {
43119
43173
  }
43120
43174
  const summary = cards.map((c) => ({
43121
43175
  id: c.id,
43122
- title: getTitleFromContent(c.content),
43176
+ title: getDisplayTitleFromContent(c.content, c.metadata, titleFields),
43123
43177
  status: c.status,
43124
43178
  priority: c.priority,
43125
43179
  assignee: c.assignee,
@@ -43160,10 +43214,11 @@ async function main() {
43160
43214
  };
43161
43215
  }
43162
43216
  }
43217
+ const titleFields = getBoardTitleFieldsForMcp(sdk, card.boardId ?? boardId);
43163
43218
  return {
43164
43219
  content: [{
43165
43220
  type: "text",
43166
- text: JSON.stringify(card, null, 2)
43221
+ text: JSON.stringify(decorateMcpCardTitle(card, titleFields), null, 2)
43167
43222
  }]
43168
43223
  };
43169
43224
  }
@@ -43176,10 +43231,11 @@ async function main() {
43176
43231
  },
43177
43232
  async ({ boardId }) => {
43178
43233
  const card = await sdk.getActiveCard(boardId);
43234
+ const titleFields = card ? getBoardTitleFieldsForMcp(sdk, card.boardId ?? boardId) : void 0;
43179
43235
  return {
43180
43236
  content: [{
43181
43237
  type: "text",
43182
- text: JSON.stringify(card, null, 2)
43238
+ text: JSON.stringify(card ? decorateMcpCardTitle(card, titleFields) : null, null, 2)
43183
43239
  }]
43184
43240
  };
43185
43241
  }
@@ -88350,6 +88406,8 @@ var init_openapi_spec = __esm({
88350
88406
  name: { type: "string" },
88351
88407
  description: { type: "string" },
88352
88408
  columns: { type: "array", items: { $ref: "#/components/schemas/Column" } },
88409
+ metadata: { type: "array", items: { type: "string" }, description: "Board metadata keys pinned in the card detail panel." },
88410
+ title: { type: "array", items: { type: "string" }, description: "Ordered metadata keys whose rendered values prefix user-visible card titles." },
88353
88411
  defaultStatus: { type: "string" },
88354
88412
  defaultPriority: { type: "string", enum: ["critical", "high", "medium", "low"] }
88355
88413
  }
@@ -88436,7 +88494,7 @@ var init_openapi_spec = __esm({
88436
88494
  "application/json": {
88437
88495
  schema: {
88438
88496
  type: "object",
88439
- description: "Any subset of board config fields: `name`, `description`, `columns`, `defaultStatus`, `defaultPriority`."
88497
+ description: "Any subset of board config fields: `name`, `description`, `columns`, `metadata`, `title`, `defaultStatus`, `defaultPriority`."
88440
88498
  }
88441
88499
  }
88442
88500
  }
@@ -98614,14 +98672,17 @@ function printCardStateMutationModel(label, payload) {
98614
98672
  cardState: payload.cardState
98615
98673
  });
98616
98674
  }
98617
- function formatCardRow(c) {
98618
- const title = getTitleFromContent(c.content);
98675
+ function getBoardTitleFieldsForCli(sdk, boardId) {
98676
+ const config2 = sdk.getConfigSnapshot();
98677
+ const resolvedBoardId = boardId || config2.defaultBoard;
98678
+ return config2.boards[resolvedBoardId]?.title;
98679
+ }
98680
+ function formatCardRow(c, title = getTitleFromContent(c.content)) {
98619
98681
  const truncTitle = title.length > 40 ? title.slice(0, 37) + "..." : title;
98620
98682
  const assignee = c.assignee || "-";
98621
98683
  return ` ${bold(c.id.slice(0, 30).padEnd(30))} ${colorStatus(c.status.padEnd(12))} ${colorPriority(c.priority.padEnd(8))} ${assignee.padEnd(12)} ${truncTitle}`;
98622
98684
  }
98623
- function formatCardDetail(c) {
98624
- const title = getTitleFromContent(c.content);
98685
+ function formatCardDetail(c, title = getTitleFromContent(c.content)) {
98625
98686
  const lines = [
98626
98687
  `${bold(title)}`,
98627
98688
  "",
@@ -98652,6 +98713,7 @@ function formatCardDetail(c) {
98652
98713
  }
98653
98714
  async function cmdList(sdk, flags) {
98654
98715
  const boardId = getBoardId(flags);
98716
+ const boardTitleFields = getBoardTitleFieldsForCli(sdk, boardId);
98655
98717
  const searchQuery = typeof flags.search === "string" ? flags.search : void 0;
98656
98718
  const fuzzy = flags.fuzzy === true;
98657
98719
  const metaFilter = Array.isArray(flags.meta) ? (() => {
@@ -98712,13 +98774,14 @@ async function cmdList(sdk, flags) {
98712
98774
  console.log(` ${dim("ID".padEnd(30))} ${dim("STATUS".padEnd(12))} ${dim("PRIORITY".padEnd(8))} ${dim("ASSIGNEE".padEnd(12))} ${dim("TITLE")}`);
98713
98775
  console.log(dim(" " + "-".repeat(90)));
98714
98776
  for (const c of cards) {
98715
- console.log(formatCardRow(c));
98777
+ console.log(formatCardRow(c, getDisplayTitleFromContent(c.content, c.metadata, boardTitleFields)));
98716
98778
  }
98717
98779
  console.log(dim(`
98718
98780
  ${cards.length} card(s)`));
98719
98781
  }
98720
98782
  async function cmdActive(sdk, flags) {
98721
98783
  const boardId = getBoardId(flags);
98784
+ const boardTitleFields = getBoardTitleFieldsForCli(sdk, boardId);
98722
98785
  const card = await sdk.getActiveCard(boardId);
98723
98786
  if (flags.json) {
98724
98787
  console.log(JSON.stringify(card, null, 2));
@@ -98728,7 +98791,7 @@ async function cmdActive(sdk, flags) {
98728
98791
  console.log(dim(" No active card."));
98729
98792
  return;
98730
98793
  }
98731
- console.log(formatCardDetail(card));
98794
+ console.log(formatCardDetail(card, getDisplayTitleFromContent(card.content, card.metadata, boardTitleFields)));
98732
98795
  }
98733
98796
  async function cmdShow(sdk, positional, flags) {
98734
98797
  const cardId = positional[0];
@@ -98737,6 +98800,7 @@ async function cmdShow(sdk, positional, flags) {
98737
98800
  process.exit(1);
98738
98801
  }
98739
98802
  const boardId = getBoardId(flags);
98803
+ const boardTitleFields = getBoardTitleFieldsForCli(sdk, boardId);
98740
98804
  const card = await sdk.getCard(cardId, boardId);
98741
98805
  if (!card) {
98742
98806
  const all = await sdk.listCards(void 0, boardId);
@@ -98745,7 +98809,7 @@ async function cmdShow(sdk, positional, flags) {
98745
98809
  if (flags.json) {
98746
98810
  console.log(JSON.stringify(matches[0], null, 2));
98747
98811
  } else {
98748
- console.log(formatCardDetail(matches[0]));
98812
+ console.log(formatCardDetail(matches[0], getDisplayTitleFromContent(matches[0].content, matches[0].metadata, boardTitleFields)));
98749
98813
  }
98750
98814
  return;
98751
98815
  } else if (matches.length > 1) {
@@ -98760,7 +98824,7 @@ async function cmdShow(sdk, positional, flags) {
98760
98824
  if (flags.json) {
98761
98825
  console.log(JSON.stringify(card, null, 2));
98762
98826
  } else {
98763
- console.log(formatCardDetail(card));
98827
+ console.log(formatCardDetail(card, getDisplayTitleFromContent(card.content, card.metadata, boardTitleFields)));
98764
98828
  }
98765
98829
  }
98766
98830
  async function cmdAdd(sdk, flags) {
package/dist/extension.js CHANGED
@@ -65170,6 +65170,44 @@ function getTitleFromContent(content) {
65170
65170
  const firstLine = content.split("\n").map((l) => l.trim()).find((l) => l.length > 0);
65171
65171
  return firstLine || "Untitled";
65172
65172
  }
65173
+ function getMetadataPathValue(metadata, path24) {
65174
+ if (!metadata || !path24.trim())
65175
+ return void 0;
65176
+ return path24.split(".").reduce((current, key) => {
65177
+ if (current === null || current === void 0 || typeof current !== "object") {
65178
+ return void 0;
65179
+ }
65180
+ return current[key];
65181
+ }, metadata);
65182
+ }
65183
+ function stringifyDisplayTitlePrefix(value) {
65184
+ if (value === null || value === void 0)
65185
+ return null;
65186
+ if (typeof value === "string") {
65187
+ const trimmed = value.trim();
65188
+ return trimmed.length > 0 ? trimmed : null;
65189
+ }
65190
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
65191
+ return String(value);
65192
+ }
65193
+ if (Array.isArray(value)) {
65194
+ const parts = value.map((item) => stringifyDisplayTitlePrefix(item)).filter((item) => Boolean(item));
65195
+ return parts.length > 0 ? parts.join(", ") : null;
65196
+ }
65197
+ if (typeof value === "object") {
65198
+ const json2 = JSON.stringify(value);
65199
+ return json2 && json2 !== "{}" && json2 !== "[]" ? json2 : null;
65200
+ }
65201
+ return null;
65202
+ }
65203
+ function getDisplayTitleFromContent(content, metadata, titleFields) {
65204
+ const title = getTitleFromContent(content);
65205
+ if (!titleFields || titleFields.length === 0) {
65206
+ return title;
65207
+ }
65208
+ const prefixes = titleFields.map((field) => stringifyDisplayTitlePrefix(getMetadataPathValue(metadata, field))).filter((value) => Boolean(value));
65209
+ return prefixes.length > 0 ? `${prefixes.join(" ")} ${title}` : title;
65210
+ }
65173
65211
  function generateSlug(title) {
65174
65212
  return title.toLowerCase().replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 50) || "card";
65175
65213
  }
@@ -70030,6 +70068,7 @@ function listBoards(ctx) {
70030
70068
  columns: board.columns,
70031
70069
  actions: board.actions,
70032
70070
  metadata: board.metadata,
70071
+ title: board.title,
70033
70072
  forms: config.forms
70034
70073
  }));
70035
70074
  }
@@ -70104,6 +70143,8 @@ function updateBoard(ctx, { boardId, updates }) {
70104
70143
  board.defaultPriority = updates.defaultPriority;
70105
70144
  if (updates.metadata !== void 0)
70106
70145
  board.metadata = updates.metadata;
70146
+ if (updates.title !== void 0)
70147
+ board.title = updates.title;
70107
70148
  writeConfig(ctx.workspaceRoot, config);
70108
70149
  return board;
70109
70150
  }
@@ -73756,7 +73797,7 @@ var KanbanSDK = class _KanbanSDK {
73756
73797
  * Lists all boards defined in the workspace configuration.
73757
73798
  *
73758
73799
  * @returns An array of {@link BoardInfo} objects containing each board's
73759
- * `id`, `name`, and optional `description`.
73800
+ * `id`, `name`, optional `description`, and display-title metadata config.
73760
73801
  *
73761
73802
  * @example
73762
73803
  * ```ts
@@ -73825,7 +73866,7 @@ var KanbanSDK = class _KanbanSDK {
73825
73866
  * Retrieves the full configuration for a specific board.
73826
73867
  *
73827
73868
  * @param boardId - The ID of the board to retrieve.
73828
- * @returns The {@link BoardConfig} object containing columns, settings, and metadata.
73869
+ * @returns The {@link BoardConfig} object containing columns, settings, metadata, and display-title metadata config.
73829
73870
  * @throws {Error} If the board does not exist.
73830
73871
  *
73831
73872
  * @example
@@ -73850,6 +73891,7 @@ var KanbanSDK = class _KanbanSDK {
73850
73891
  * @param updates.columns - Replacement column definitions.
73851
73892
  * @param updates.defaultStatus - New default status for new cards.
73852
73893
  * @param updates.defaultPriority - New default priority for new cards.
73894
+ * @param updates.title - Ordered metadata keys whose values should prefix rendered card titles.
73853
73895
  * @returns The updated {@link BoardConfig} object.
73854
73896
  * @throws {Error} If the board does not exist.
73855
73897
  *
@@ -75460,6 +75502,8 @@ var KANBAN_OPENAPI_SPEC = {
75460
75502
  name: { type: "string" },
75461
75503
  description: { type: "string" },
75462
75504
  columns: { type: "array", items: { $ref: "#/components/schemas/Column" } },
75505
+ metadata: { type: "array", items: { type: "string" }, description: "Board metadata keys pinned in the card detail panel." },
75506
+ title: { type: "array", items: { type: "string" }, description: "Ordered metadata keys whose rendered values prefix user-visible card titles." },
75463
75507
  defaultStatus: { type: "string" },
75464
75508
  defaultPriority: { type: "string", enum: ["critical", "high", "medium", "low"] }
75465
75509
  }
@@ -75546,7 +75590,7 @@ var KANBAN_OPENAPI_SPEC = {
75546
75590
  "application/json": {
75547
75591
  schema: {
75548
75592
  type: "object",
75549
- description: "Any subset of board config fields: `name`, `description`, `columns`, `defaultStatus`, `defaultPriority`."
75593
+ description: "Any subset of board config fields: `name`, `description`, `columns`, `metadata`, `title`, `defaultStatus`, `defaultPriority`."
75550
75594
  }
75551
75595
  }
75552
75596
  }
@@ -82182,15 +82226,16 @@ var KanbanPanel = class _KanbanPanel {
82182
82226
  vscode.window.showErrorMessage("No card selected");
82183
82227
  return;
82184
82228
  }
82185
- const titleMatch = card.content.match(/^#\s+(.+)$/m);
82186
- const title = titleMatch ? titleMatch[1].trim() : getTitleFromContent(card.content);
82229
+ const aiRoot = this._getWorkspaceRoot();
82230
+ const aiConfig = aiRoot ? readConfig(aiRoot) : DEFAULT_CONFIG;
82231
+ const activeBoardId = this._currentBoardId || aiConfig.defaultBoard;
82232
+ const titleFields = aiConfig.boards[activeBoardId]?.title;
82233
+ const title = getDisplayTitleFromContent(card.content, card.metadata, titleFields);
82187
82234
  const labels = card.labels.length > 0 ? ` [${card.labels.join(", ")}]` : "";
82188
82235
  const description = card.content.replace(/\n/g, " ").replace(/\s+/g, " ").trim();
82189
82236
  const shortDesc = description.length > 200 ? description.substring(0, 200) + "..." : description;
82190
82237
  const promptTarget = this._sdk?.getLocalCardPath(card) ?? `card ${card.id}`;
82191
82238
  const prompt = `Implement this card: "${title}" (${card.priority} priority)${labels}. ${shortDesc} See full details in: ${promptTarget}`;
82192
- const aiRoot = this._getWorkspaceRoot();
82193
- const aiConfig = aiRoot ? readConfig(aiRoot) : DEFAULT_CONFIG;
82194
82239
  const selectedAgent = agent || aiConfig.aiAgent || "claude";
82195
82240
  const selectedPermissionMode = permissionMode || "default";
82196
82241
  let command;
@@ -82527,10 +82572,14 @@ var SidebarViewProvider = class {
82527
82572
  }
82528
82573
  try {
82529
82574
  const sdk = new KanbanSDK(kanbanDir);
82575
+ const workspaceFolders = vscode2.workspace.workspaceFolders;
82576
+ const root = workspaceFolders?.[0]?.uri.fsPath;
82577
+ const config = root ? readConfig(root) : void 0;
82578
+ const defaultBoardTitleFields = config?.boards[config.defaultBoard]?.title;
82530
82579
  const cards = await sdk.listCards();
82531
82580
  this._cards = cards.map((c) => ({
82532
82581
  id: c.id,
82533
- title: getTitleFromContent(c.content),
82582
+ title: getDisplayTitleFromContent(c.content, c.metadata, defaultBoardTitleFields),
82534
82583
  status: c.status,
82535
82584
  priority: c.priority
82536
82585
  }));
@@ -17503,6 +17503,44 @@ function getTitleFromContent(content) {
17503
17503
  const firstLine = content.split("\n").map((l) => l.trim()).find((l) => l.length > 0);
17504
17504
  return firstLine || "Untitled";
17505
17505
  }
17506
+ function getMetadataPathValue(metadata, path16) {
17507
+ if (!metadata || !path16.trim())
17508
+ return void 0;
17509
+ return path16.split(".").reduce((current, key) => {
17510
+ if (current === null || current === void 0 || typeof current !== "object") {
17511
+ return void 0;
17512
+ }
17513
+ return current[key];
17514
+ }, metadata);
17515
+ }
17516
+ function stringifyDisplayTitlePrefix(value) {
17517
+ if (value === null || value === void 0)
17518
+ return null;
17519
+ if (typeof value === "string") {
17520
+ const trimmed = value.trim();
17521
+ return trimmed.length > 0 ? trimmed : null;
17522
+ }
17523
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
17524
+ return String(value);
17525
+ }
17526
+ if (Array.isArray(value)) {
17527
+ const parts = value.map((item) => stringifyDisplayTitlePrefix(item)).filter((item) => Boolean(item));
17528
+ return parts.length > 0 ? parts.join(", ") : null;
17529
+ }
17530
+ if (typeof value === "object") {
17531
+ const json2 = JSON.stringify(value);
17532
+ return json2 && json2 !== "{}" && json2 !== "[]" ? json2 : null;
17533
+ }
17534
+ return null;
17535
+ }
17536
+ function getDisplayTitleFromContent(content, metadata, titleFields) {
17537
+ const title = getTitleFromContent(content);
17538
+ if (!titleFields || titleFields.length === 0) {
17539
+ return title;
17540
+ }
17541
+ const prefixes = titleFields.map((field) => stringifyDisplayTitlePrefix(getMetadataPathValue(metadata, field))).filter((value) => Boolean(value));
17542
+ return prefixes.length > 0 ? `${prefixes.join(" ")} ${title}` : title;
17543
+ }
17506
17544
  function generateSlug(title) {
17507
17545
  return title.toLowerCase().replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 50) || "card";
17508
17546
  }
@@ -22428,6 +22466,7 @@ function listBoards(ctx) {
22428
22466
  columns: board.columns,
22429
22467
  actions: board.actions,
22430
22468
  metadata: board.metadata,
22469
+ title: board.title,
22431
22470
  forms: config.forms
22432
22471
  }));
22433
22472
  }
@@ -22502,6 +22541,8 @@ function updateBoard(ctx, { boardId, updates }) {
22502
22541
  board.defaultPriority = updates.defaultPriority;
22503
22542
  if (updates.metadata !== void 0)
22504
22543
  board.metadata = updates.metadata;
22544
+ if (updates.title !== void 0)
22545
+ board.title = updates.title;
22505
22546
  writeConfig(ctx.workspaceRoot, config);
22506
22547
  return board;
22507
22548
  }
@@ -26154,7 +26195,7 @@ var KanbanSDK = class _KanbanSDK {
26154
26195
  * Lists all boards defined in the workspace configuration.
26155
26196
  *
26156
26197
  * @returns An array of {@link BoardInfo} objects containing each board's
26157
- * `id`, `name`, and optional `description`.
26198
+ * `id`, `name`, optional `description`, and display-title metadata config.
26158
26199
  *
26159
26200
  * @example
26160
26201
  * ```ts
@@ -26223,7 +26264,7 @@ var KanbanSDK = class _KanbanSDK {
26223
26264
  * Retrieves the full configuration for a specific board.
26224
26265
  *
26225
26266
  * @param boardId - The ID of the board to retrieve.
26226
- * @returns The {@link BoardConfig} object containing columns, settings, and metadata.
26267
+ * @returns The {@link BoardConfig} object containing columns, settings, metadata, and display-title metadata config.
26227
26268
  * @throws {Error} If the board does not exist.
26228
26269
  *
26229
26270
  * @example
@@ -26248,6 +26289,7 @@ var KanbanSDK = class _KanbanSDK {
26248
26289
  * @param updates.columns - Replacement column definitions.
26249
26290
  * @param updates.defaultStatus - New default status for new cards.
26250
26291
  * @param updates.defaultPriority - New default priority for new cards.
26292
+ * @param updates.title - Ordered metadata keys whose values should prefix rendered card titles.
26251
26293
  * @returns The updated {@link BoardConfig} object.
26252
26294
  * @throws {Error} If the board does not exist.
26253
26295
  *
@@ -27640,6 +27682,17 @@ async function buildMcpCardStateMutationModel(sdk, unread) {
27640
27682
  }
27641
27683
  };
27642
27684
  }
27685
+ function getBoardTitleFieldsForMcp(sdk, boardId) {
27686
+ const config = sdk.getConfigSnapshot();
27687
+ const resolvedBoardId = boardId || config.defaultBoard;
27688
+ return config.boards[resolvedBoardId]?.title;
27689
+ }
27690
+ function decorateMcpCardTitle(card, titleFields) {
27691
+ return {
27692
+ ...card,
27693
+ title: getDisplayTitleFromContent(card.content, card.metadata, titleFields)
27694
+ };
27695
+ }
27643
27696
  function registerCardStateMcpTools(server, options) {
27644
27697
  const registeredNames = [
27645
27698
  "get_card_state_status",
@@ -27858,6 +27911,7 @@ async function main() {
27858
27911
  sort: import_zod.z.enum(["created:asc", "created:desc", "modified:asc", "modified:desc"]).optional().describe("Sort order: created:asc, created:desc, modified:asc, or modified:desc. Defaults to board order.")
27859
27912
  },
27860
27913
  async ({ boardId, status, priority, assignee, label, labelGroup, includeDeleted, searchQuery, fuzzy, metaFilter, sort }) => {
27914
+ const titleFields = getBoardTitleFieldsForMcp(sdk, boardId);
27861
27915
  let cards = await sdk.listCards(void 0, boardId, {
27862
27916
  metaFilter: metaFilter && Object.keys(metaFilter).length > 0 ? metaFilter : void 0,
27863
27917
  sort: sort || void 0,
@@ -27880,7 +27934,7 @@ async function main() {
27880
27934
  }
27881
27935
  const summary = cards.map((c) => ({
27882
27936
  id: c.id,
27883
- title: getTitleFromContent(c.content),
27937
+ title: getDisplayTitleFromContent(c.content, c.metadata, titleFields),
27884
27938
  status: c.status,
27885
27939
  priority: c.priority,
27886
27940
  assignee: c.assignee,
@@ -27921,10 +27975,11 @@ async function main() {
27921
27975
  };
27922
27976
  }
27923
27977
  }
27978
+ const titleFields = getBoardTitleFieldsForMcp(sdk, card.boardId ?? boardId);
27924
27979
  return {
27925
27980
  content: [{
27926
27981
  type: "text",
27927
- text: JSON.stringify(card, null, 2)
27982
+ text: JSON.stringify(decorateMcpCardTitle(card, titleFields), null, 2)
27928
27983
  }]
27929
27984
  };
27930
27985
  }
@@ -27937,10 +27992,11 @@ async function main() {
27937
27992
  },
27938
27993
  async ({ boardId }) => {
27939
27994
  const card = await sdk.getActiveCard(boardId);
27995
+ const titleFields = card ? getBoardTitleFieldsForMcp(sdk, card.boardId ?? boardId) : void 0;
27940
27996
  return {
27941
27997
  content: [{
27942
27998
  type: "text",
27943
- text: JSON.stringify(card, null, 2)
27999
+ text: JSON.stringify(card ? decorateMcpCardTitle(card, titleFields) : null, null, 2)
27944
28000
  }]
27945
28001
  };
27946
28002
  }
@@ -17502,6 +17502,7 @@ __export(sdk_exports, {
17502
17502
  getBoardConfig: () => getBoardConfig,
17503
17503
  getCardFilePath: () => getCardFilePath,
17504
17504
  getDefaultBoardId: () => getDefaultBoardId,
17505
+ getDisplayTitleFromContent: () => getDisplayTitleFromContent,
17505
17506
  getEventsByResource: () => getEventsByResource,
17506
17507
  getSdkAfterEvents: () => getSdkAfterEvents,
17507
17508
  getSdkBeforeEvents: () => getSdkBeforeEvents,
@@ -17533,6 +17534,44 @@ function getTitleFromContent(content) {
17533
17534
  const firstLine = content.split("\n").map((l) => l.trim()).find((l) => l.length > 0);
17534
17535
  return firstLine || "Untitled";
17535
17536
  }
17537
+ function getMetadataPathValue(metadata, path15) {
17538
+ if (!metadata || !path15.trim())
17539
+ return void 0;
17540
+ return path15.split(".").reduce((current, key) => {
17541
+ if (current === null || current === void 0 || typeof current !== "object") {
17542
+ return void 0;
17543
+ }
17544
+ return current[key];
17545
+ }, metadata);
17546
+ }
17547
+ function stringifyDisplayTitlePrefix(value) {
17548
+ if (value === null || value === void 0)
17549
+ return null;
17550
+ if (typeof value === "string") {
17551
+ const trimmed = value.trim();
17552
+ return trimmed.length > 0 ? trimmed : null;
17553
+ }
17554
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
17555
+ return String(value);
17556
+ }
17557
+ if (Array.isArray(value)) {
17558
+ const parts = value.map((item) => stringifyDisplayTitlePrefix(item)).filter((item) => Boolean(item));
17559
+ return parts.length > 0 ? parts.join(", ") : null;
17560
+ }
17561
+ if (typeof value === "object") {
17562
+ const json2 = JSON.stringify(value);
17563
+ return json2 && json2 !== "{}" && json2 !== "[]" ? json2 : null;
17564
+ }
17565
+ return null;
17566
+ }
17567
+ function getDisplayTitleFromContent(content, metadata, titleFields) {
17568
+ const title = getTitleFromContent(content);
17569
+ if (!titleFields || titleFields.length === 0) {
17570
+ return title;
17571
+ }
17572
+ const prefixes = titleFields.map((field) => stringifyDisplayTitlePrefix(getMetadataPathValue(metadata, field))).filter((value) => Boolean(value));
17573
+ return prefixes.length > 0 ? `${prefixes.join(" ")} ${title}` : title;
17574
+ }
17536
17575
  function generateSlug(title) {
17537
17576
  return title.toLowerCase().replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 50) || "card";
17538
17577
  }
@@ -22395,6 +22434,7 @@ function listBoards(ctx) {
22395
22434
  columns: board.columns,
22396
22435
  actions: board.actions,
22397
22436
  metadata: board.metadata,
22437
+ title: board.title,
22398
22438
  forms: config.forms
22399
22439
  }));
22400
22440
  }
@@ -22469,6 +22509,8 @@ function updateBoard(ctx, { boardId, updates }) {
22469
22509
  board.defaultPriority = updates.defaultPriority;
22470
22510
  if (updates.metadata !== void 0)
22471
22511
  board.metadata = updates.metadata;
22512
+ if (updates.title !== void 0)
22513
+ board.title = updates.title;
22472
22514
  writeConfig(ctx.workspaceRoot, config);
22473
22515
  return board;
22474
22516
  }
@@ -26121,7 +26163,7 @@ var KanbanSDK = class _KanbanSDK {
26121
26163
  * Lists all boards defined in the workspace configuration.
26122
26164
  *
26123
26165
  * @returns An array of {@link BoardInfo} objects containing each board's
26124
- * `id`, `name`, and optional `description`.
26166
+ * `id`, `name`, optional `description`, and display-title metadata config.
26125
26167
  *
26126
26168
  * @example
26127
26169
  * ```ts
@@ -26190,7 +26232,7 @@ var KanbanSDK = class _KanbanSDK {
26190
26232
  * Retrieves the full configuration for a specific board.
26191
26233
  *
26192
26234
  * @param boardId - The ID of the board to retrieve.
26193
- * @returns The {@link BoardConfig} object containing columns, settings, and metadata.
26235
+ * @returns The {@link BoardConfig} object containing columns, settings, metadata, and display-title metadata config.
26194
26236
  * @throws {Error} If the board does not exist.
26195
26237
  *
26196
26238
  * @example
@@ -26215,6 +26257,7 @@ var KanbanSDK = class _KanbanSDK {
26215
26257
  * @param updates.columns - Replacement column definitions.
26216
26258
  * @param updates.defaultStatus - New default status for new cards.
26217
26259
  * @param updates.defaultPriority - New default priority for new cards.
26260
+ * @param updates.title - Ordered metadata keys whose values should prefix rendered card titles.
26218
26261
  * @returns The updated {@link BoardConfig} object.
26219
26262
  * @throws {Error} If the board does not exist.
26220
26263
  *
@@ -27727,6 +27770,7 @@ function getActionsByResource(resource) {
27727
27770
  getBoardConfig,
27728
27771
  getCardFilePath,
27729
27772
  getDefaultBoardId,
27773
+ getDisplayTitleFromContent,
27730
27774
  getEventsByResource,
27731
27775
  getSdkAfterEvents,
27732
27776
  getSdkBeforeEvents,