@vheins/local-memory-mcp 0.9.8 → 0.9.10

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.
@@ -8,8 +8,8 @@
8
8
  <link rel="preconnect" href="https://fonts.googleapis.com">
9
9
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
10
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
11
- <script type="module" crossorigin src="/assets/index-C9M1BD7U.js"></script>
12
- <link rel="stylesheet" crossorigin href="/assets/index-CNE1bKgp.css">
11
+ <script type="module" crossorigin src="/assets/index-D-xKLFFr.js"></script>
12
+ <link rel="stylesheet" crossorigin href="/assets/index-C2cM-UXM.css">
13
13
  </head>
14
14
  <body>
15
15
  <div id="app"></div>
@@ -10,7 +10,7 @@ import {
10
10
  createFileSink,
11
11
  listResources,
12
12
  logger
13
- } from "../chunk-CSEGUZWJ.js";
13
+ } from "../chunk-GAZNK32C.js";
14
14
 
15
15
  // src/dashboard/server.ts
16
16
  import express from "express";
@@ -215,7 +215,7 @@ vectors.initialize().catch((err) => {
215
215
  });
216
216
 
217
217
  // src/dashboard/routes/index.ts
218
- import { Router as Router5 } from "express";
218
+ import { Router as Router6 } from "express";
219
219
 
220
220
  // src/dashboard/routes/system.routes.ts
221
221
  import { Router } from "express";
@@ -297,6 +297,7 @@ var SystemController = class {
297
297
  uptime: Math.floor((Date.now() - startTime) / 1e3),
298
298
  version: pkg.version,
299
299
  memoryCount: stats.totalMemories,
300
+ repoCount: stats.totalRepos,
300
301
  pendingRequests: mcpClient.getPendingCount(),
301
302
  dbPath: db.getDbPath()
302
303
  };
@@ -321,8 +322,7 @@ var SystemController = class {
321
322
  try {
322
323
  await db.refresh();
323
324
  const repo = req.query.repo;
324
- if (!repo) return res.status(400).json(jsonApiError("repo is required", 400));
325
- const stats = db.system.getDashboardStats(repo);
325
+ const stats = repo ? db.system.getDashboardStats(repo) : db.system.getGlobalDashboardStats();
326
326
  res.json(jsonApiRes(stats, "system-stats"));
327
327
  } catch (err) {
328
328
  const message = err instanceof Error ? err.message : "Internal server error";
@@ -723,41 +723,33 @@ var TasksController = class {
723
723
  const attributes = getAttributes(req);
724
724
  const existingTask = db.tasks.getTaskById(id);
725
725
  if (!existingTask) return res.status(404).json(jsonApiError("Task not found", 404));
726
- await db.withWrite(() => {
727
- db.tasks.updateTask(id, attributes);
728
- if (attributes.status && attributes.status !== existingTask.status) {
729
- db.actions.logAction("update", existingTask.repo, {
730
- taskId: id,
731
- query: `Status changed to ${attributes.status}`
732
- });
733
- db.tasks.insertTaskComment({
734
- id: randomUUID2(),
735
- task_id: id,
736
- repo: existingTask.repo,
737
- comment: attributes.comment || `Status updated via dashboard`,
738
- agent: "dashboard",
739
- role: "user",
740
- model: "web-ui",
741
- previous_status: existingTask.status,
742
- next_status: attributes.status,
743
- created_at: (/* @__PURE__ */ new Date()).toISOString()
744
- });
745
- } else if (attributes.comment) {
746
- db.tasks.insertTaskComment({
747
- id: randomUUID2(),
748
- task_id: id,
749
- repo: existingTask.repo,
750
- comment: attributes.comment,
751
- agent: "dashboard",
752
- role: "user",
753
- model: "web-ui",
754
- previous_status: null,
755
- next_status: null,
756
- created_at: (/* @__PURE__ */ new Date()).toISOString()
757
- });
726
+ if (!mcpClient.isConnected()) await mcpClient.start();
727
+ const toolArgs = {
728
+ repo: existingTask.repo,
729
+ id,
730
+ agent: "dashboard",
731
+ role: "user",
732
+ model: "web-ui",
733
+ structured: true
734
+ };
735
+ for (const [key, value] of Object.entries(attributes)) {
736
+ if (value !== void 0) {
737
+ toolArgs[key] = value;
758
738
  }
759
- });
760
- res.json(jsonApiRes({ message: "Updated" }, "status"));
739
+ }
740
+ if (attributes.status && attributes.status !== existingTask.status && !toolArgs.comment) {
741
+ toolArgs.comment = `Status updated via dashboard to ${attributes.status}`;
742
+ }
743
+ if (attributes.status === "completed" && toolArgs.est_tokens === void 0) {
744
+ toolArgs.est_tokens = existingTask.est_tokens || 0;
745
+ }
746
+ await mcpClient.callTool("task-update", toolArgs);
747
+ await db.refresh();
748
+ const updatedTask = db.tasks.getTaskById(id);
749
+ if (!updatedTask) {
750
+ return res.status(500).json(jsonApiError("Task updated but could not be reloaded", 500));
751
+ }
752
+ res.json(jsonApiRes(updatedTask, "task"));
761
753
  } catch (err) {
762
754
  const message = err instanceof Error ? err.message : "Internal server error";
763
755
  res.status(500).json(jsonApiError(message));
@@ -808,23 +800,23 @@ var TasksController = class {
808
800
  try {
809
801
  await db.refresh();
810
802
  const { repo } = req.query;
811
- if (!repo) return res.status(400).json(jsonApiError("repo is required", 400));
803
+ const targetRepo = typeof repo === "string" && repo.length > 0 ? repo : null;
812
804
  const stats = {
813
805
  daily: {
814
- ...db.tasks.getTaskTimeStats(repo, "daily"),
815
- history: db.tasks.getTaskComparisonSeries(repo, "daily")
806
+ ...db.tasks.getTaskTimeStats(targetRepo, "daily"),
807
+ history: db.tasks.getTaskComparisonSeries(targetRepo, "daily")
816
808
  },
817
809
  weekly: {
818
- ...db.tasks.getTaskTimeStats(repo, "weekly"),
819
- history: db.tasks.getTaskComparisonSeries(repo, "weekly")
810
+ ...db.tasks.getTaskTimeStats(targetRepo, "weekly"),
811
+ history: db.tasks.getTaskComparisonSeries(targetRepo, "weekly")
820
812
  },
821
813
  monthly: {
822
- ...db.tasks.getTaskTimeStats(repo, "monthly"),
823
- history: db.tasks.getTaskComparisonSeries(repo, "monthly")
814
+ ...db.tasks.getTaskTimeStats(targetRepo, "monthly"),
815
+ history: db.tasks.getTaskComparisonSeries(targetRepo, "monthly")
824
816
  },
825
817
  overall: {
826
- ...db.tasks.getTaskTimeStats(repo, "overall"),
827
- history: db.tasks.getTaskComparisonSeries(repo, "overall")
818
+ ...db.tasks.getTaskTimeStats(targetRepo, "overall"),
819
+ history: db.tasks.getTaskComparisonSeries(targetRepo, "overall")
828
820
  }
829
821
  };
830
822
  res.json(jsonApiRes(stats, "performance-stats"));
@@ -1039,13 +1031,77 @@ router4.put("/:id", StandardsController.update);
1039
1031
  router4.delete("/:id", StandardsController.delete);
1040
1032
  var standard_routes_default = router4;
1041
1033
 
1042
- // src/dashboard/routes/index.ts
1034
+ // src/dashboard/routes/coordination.routes.ts
1035
+ import { Router as Router5 } from "express";
1036
+
1037
+ // src/dashboard/controllers/CoordinationController.ts
1038
+ var CoordinationController = class {
1039
+ static async listClaims(req, res) {
1040
+ try {
1041
+ await db.refresh();
1042
+ const { repo, agent, active_only } = req.query;
1043
+ const page = Math.max(1, parseInt(req.query.page || "1", 10));
1044
+ const pageSize = Math.min(100, Math.max(1, parseInt(req.query.pageSize || "20", 10)));
1045
+ if (!repo) return res.status(400).json(jsonApiError("repo is required", 400));
1046
+ const claims = db.handoffs.listClaims({
1047
+ repo,
1048
+ agent: typeof agent === "string" ? agent : void 0,
1049
+ active_only: active_only === void 0 ? true : String(active_only) === "true",
1050
+ limit: pageSize,
1051
+ offset: (page - 1) * pageSize
1052
+ });
1053
+ const total = db.handoffs.listClaims({
1054
+ repo,
1055
+ agent: typeof agent === "string" ? agent : void 0,
1056
+ active_only: active_only === void 0 ? true : String(active_only) === "true",
1057
+ limit: 1e5,
1058
+ offset: 0
1059
+ }).length;
1060
+ res.json(
1061
+ jsonApiRes(claims, "claim", {
1062
+ meta: {
1063
+ page,
1064
+ pageSize,
1065
+ totalItems: total,
1066
+ totalPages: Math.ceil(total / pageSize)
1067
+ }
1068
+ })
1069
+ );
1070
+ } catch (err) {
1071
+ const message = err instanceof Error ? err.message : "Internal server error";
1072
+ res.status(500).json(jsonApiError(message));
1073
+ }
1074
+ }
1075
+ static async releaseClaim(req, res) {
1076
+ try {
1077
+ const attributes = getAttributes(req);
1078
+ if (!mcpClient.isConnected()) await mcpClient.start();
1079
+ const result = await mcpClient.callTool("claim-release", {
1080
+ ...attributes,
1081
+ structured: true
1082
+ });
1083
+ res.json(jsonApiRes(result.structuredContent || result, "claim-release"));
1084
+ } catch (err) {
1085
+ const message = err instanceof Error ? err.message : "Internal server error";
1086
+ res.status(500).json(jsonApiError(message));
1087
+ }
1088
+ }
1089
+ };
1090
+
1091
+ // src/dashboard/routes/coordination.routes.ts
1043
1092
  var router5 = Router5();
1044
- router5.use("/", system_routes_default);
1045
- router5.use("/memories", memory_routes_default);
1046
- router5.use("/tasks", task_routes_default);
1047
- router5.use("/standards", standard_routes_default);
1048
- var routes_default = router5;
1093
+ router5.get("/claims", CoordinationController.listClaims);
1094
+ router5.post("/claims/release", CoordinationController.releaseClaim);
1095
+ var coordination_routes_default = router5;
1096
+
1097
+ // src/dashboard/routes/index.ts
1098
+ var router6 = Router6();
1099
+ router6.use("/", system_routes_default);
1100
+ router6.use("/memories", memory_routes_default);
1101
+ router6.use("/tasks", task_routes_default);
1102
+ router6.use("/standards", standard_routes_default);
1103
+ router6.use("/coordination", coordination_routes_default);
1104
+ var routes_default = router6;
1049
1105
 
1050
1106
  // src/dashboard/server.ts
1051
1107
  var __dirname3 = path3.dirname(fileURLToPath3(import.meta.url));
@@ -1,6 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  CAPABILITIES,
4
+ ClaimListSchema,
5
+ ClaimReleaseSchema,
4
6
  HandoffCreateSchema,
5
7
  HandoffListSchema,
6
8
  HandoffUpdateSchema,
@@ -55,7 +57,7 @@ import {
55
57
  toContextSlug,
56
58
  updateSessionFromInitialize,
57
59
  updateSessionRoots
58
- } from "../chunk-CSEGUZWJ.js";
60
+ } from "../chunk-GAZNK32C.js";
59
61
 
60
62
  // src/mcp/server.ts
61
63
  import readline from "readline";
@@ -1663,6 +1665,16 @@ function buildHandoffListSummary(repo, count, status, fromAgent, toAgent) {
1663
1665
  }
1664
1666
  return parts.join("\n");
1665
1667
  }
1668
+ function buildClaimListSummary(repo, count, agent, activeOnly) {
1669
+ const parts = [`Found ${count} claim${count === 1 ? "" : "s"} in repo "${repo}".`];
1670
+ if (agent) {
1671
+ parts.push(`Agent filter: ${agent}.`);
1672
+ }
1673
+ if (activeOnly) {
1674
+ parts.push("Showing active claims only.");
1675
+ }
1676
+ return parts.join("\n");
1677
+ }
1666
1678
  async function handleHandoffCreate(args, storage) {
1667
1679
  const validated = HandoffCreateSchema.parse(args);
1668
1680
  const { repo, from_agent, to_agent, task_id, task_code, summary, context, expires_at, structured } = validated;
@@ -1708,15 +1720,31 @@ async function handleHandoffList(args, storage) {
1708
1720
  limit,
1709
1721
  offset
1710
1722
  });
1711
- const COLUMNS = ["id", "from_agent", "to_agent", "task_id", "status", "created_at", "summary"];
1723
+ const COLUMNS = [
1724
+ "id",
1725
+ "from_agent",
1726
+ "to_agent",
1727
+ "task_id",
1728
+ "task_code",
1729
+ "status",
1730
+ "created_at",
1731
+ "updated_at",
1732
+ "expires_at",
1733
+ "summary",
1734
+ "context"
1735
+ ];
1712
1736
  const rows = handoffs.map((handoff) => [
1713
1737
  handoff.id,
1714
1738
  handoff.from_agent,
1715
1739
  handoff.to_agent,
1716
1740
  handoff.task_id,
1741
+ handoff.task_code ?? null,
1717
1742
  handoff.status,
1718
1743
  handoff.created_at,
1719
- handoff.summary
1744
+ handoff.updated_at,
1745
+ handoff.expires_at,
1746
+ handoff.summary,
1747
+ handoff.context
1720
1748
  ]);
1721
1749
  const structuredData = {
1722
1750
  schema: "handoff-list",
@@ -1806,6 +1834,82 @@ async function handleTaskClaim(args, storage) {
1806
1834
  }
1807
1835
  return response;
1808
1836
  }
1837
+ async function handleClaimList(args, storage) {
1838
+ const validated = ClaimListSchema.parse(args);
1839
+ const { repo, agent, active_only, limit, offset, structured } = validated;
1840
+ const claims = storage.handoffs.listClaims({
1841
+ repo,
1842
+ agent,
1843
+ active_only,
1844
+ limit,
1845
+ offset
1846
+ });
1847
+ const COLUMNS = ["id", "task_id", "task_code", "agent", "role", "claimed_at", "released_at", "metadata"];
1848
+ const rows = claims.map((claim) => [
1849
+ claim.id,
1850
+ claim.task_id,
1851
+ claim.task_code ?? null,
1852
+ claim.agent,
1853
+ claim.role,
1854
+ claim.claimed_at,
1855
+ claim.released_at,
1856
+ claim.metadata
1857
+ ]);
1858
+ const structuredData = {
1859
+ schema: "claim-list",
1860
+ claims: {
1861
+ columns: [...COLUMNS],
1862
+ rows
1863
+ },
1864
+ count: rows.length,
1865
+ offset
1866
+ };
1867
+ const contentSummary = buildClaimListSummary(repo, rows.length, agent, active_only);
1868
+ return createMcpResponse(structuredData, contentSummary, {
1869
+ contentSummary,
1870
+ includeSerializedStructuredContent: structured
1871
+ });
1872
+ }
1873
+ async function handleClaimRelease(args, storage) {
1874
+ const validated = ClaimReleaseSchema.parse(args);
1875
+ const { repo, task_id, task_code, agent, structured } = validated;
1876
+ let resolvedTaskId = task_id;
1877
+ let resolvedTaskCode = task_code ?? null;
1878
+ if (resolvedTaskId) {
1879
+ const task = storage.tasks.getTaskById(resolvedTaskId);
1880
+ if (!task || task.repo !== repo) {
1881
+ throw new Error(`Task not found: ${resolvedTaskId} in repo ${repo}`);
1882
+ }
1883
+ resolvedTaskCode = task.task_code;
1884
+ } else if (task_code) {
1885
+ const task = storage.tasks.getTaskByCode(repo, task_code);
1886
+ if (!task) {
1887
+ throw new Error(`Task not found: ${task_code} in repo ${repo}`);
1888
+ }
1889
+ resolvedTaskId = task.id;
1890
+ resolvedTaskCode = task.task_code;
1891
+ }
1892
+ const success = storage.handoffs.releaseClaim(resolvedTaskId, agent);
1893
+ if (!success) {
1894
+ throw new Error(`No active claim found for task ${resolvedTaskCode || resolvedTaskId}`);
1895
+ }
1896
+ const result = {
1897
+ success,
1898
+ repo,
1899
+ task_id: resolvedTaskId,
1900
+ task_code: resolvedTaskCode,
1901
+ agent: agent ?? null
1902
+ };
1903
+ const contentSummary = [
1904
+ `Released claim for task ${resolvedTaskCode || resolvedTaskId}.`,
1905
+ `Repo: ${repo}`,
1906
+ agent ? `Agent: ${agent}` : "Agent: any active claimant"
1907
+ ].join("\n");
1908
+ return createMcpResponse(result, contentSummary, {
1909
+ contentSummary,
1910
+ includeSerializedStructuredContent: structured
1911
+ });
1912
+ }
1809
1913
 
1810
1914
  // src/mcp/tools/standard.store.ts
1811
1915
  import { randomUUID as randomUUID3 } from "crypto";
@@ -2359,6 +2463,7 @@ function createRouter(db2, vectors2, options) {
2359
2463
  "task-create",
2360
2464
  "task-create-interactive",
2361
2465
  "task-claim",
2466
+ "claim-release",
2362
2467
  "task-update",
2363
2468
  "task-delete"
2364
2469
  ]);
@@ -2403,6 +2508,10 @@ function createRouter(db2, vectors2, options) {
2403
2508
  return await handleHandoffUpdate(args, db2);
2404
2509
  case "task-claim":
2405
2510
  return await handleTaskClaim(args, db2);
2511
+ case "claim-list":
2512
+ return await handleClaimList(args, db2);
2513
+ case "claim-release":
2514
+ return await handleClaimRelease(args, db2);
2406
2515
  case "standard-store":
2407
2516
  return await handleStandardStore(args, db2, vectors2);
2408
2517
  case "standard-update":
@@ -32,7 +32,13 @@ ONLY call MCP tools. No prose, no code, no plans outside MCP.
32
32
  ## 3. ATTRIBUTES & FORMAT
33
33
  - `task_code`: FEAT/FIX/REFACTOR-XXX.
34
34
  - `phase`: Discovery/Implementation/Testing.
35
- - `priority`: 1-5.
35
+ - `priority`: 1-5 using this exact scale:
36
+ - `1 = Low`
37
+ - `2 = Normal`
38
+ - `3 = Medium`
39
+ - `4 = High`
40
+ - `5 = Critical`
41
+ - `priority` is ascending by urgency. `5` is the highest urgency and `1` is the lowest. Never encode `Critical` as `1`.
36
42
  - `description` (STRICT FORMAT):
37
43
  ### 1. Context & Analysis
38
44
  - **Trigger**: Instruction/finding.
@@ -18,7 +18,7 @@ You are a memory-aware agent. Memory is project truth, not a suggestion.
18
18
 
19
19
  ## Execution Policy
20
20
  1. **Orient**: Call `task-list` for active work and `handoff-list` for pending transfers when starting a repository session. Close stale pending handoffs with `handoff-update` when they no longer describe unfinished work.
21
- 2. **Claim**: Use `task-claim` before taking ownership of a concrete task.
21
+ 2. **Claim**: Use `task-claim` before taking ownership of a concrete task. Use `claim-list` when ownership is unclear and `claim-release` to clear stale claims during reassignment.
22
22
  3. **Search**: Call `memory-search` with `current_file_path` and `current_tags` before coding.
23
23
  4. **Standards**: Call `standard-search` when implementation may be governed by coding standards.
24
24
  5. **Retrieve**: Use `memory-detail` for full content if search pointer rows are insufficient.
@@ -13,4 +13,5 @@ Briefing Steps:
13
13
  4. **Memory**: Call `memory-search` or `memory-recap` for recent decisions, patterns, and mistakes; hydrate important entries with `memory-detail`.
14
14
  5. **Standards**: Call `standard-search` with current repo/stack when implementation guidance is needed.
15
15
  6. **Core Context**: Summarize active task, pending handoffs, applicable standards, and top architectural decisions.
16
- 7. **Action**: Propose next steps based on the active queue.
16
+ 7. **Priority Reminder**: Treat task priority with MCP semantics: `1=Low`, `2=Normal`, `3=Medium`, `4=High`, `5=Critical`.
17
+ 8. **Action**: Propose next steps based on the active queue.
@@ -31,6 +31,7 @@ ONLY call MCP tools. No prose, code, or external plans.
31
31
  ## 3. TASK DESIGN & FORMAT
32
32
  - **Atomic**: One change per task.
33
33
  - **Attributes**: `task_code`, `phase`, `priority`, `agent`, `model`.
34
+ - **Priority Scale**: Use MCP ordering exactly: `1=Low`, `2=Normal`, `3=Medium`, `4=High`, `5=Critical`. `5` is the highest urgency.
34
35
  - **Description** (STRICT FORMAT):
35
36
  ### 1. Context & Analysis
36
37
  - **Finding**: Gap trigger.
@@ -16,6 +16,7 @@ Steps:
16
16
  4. **Analyze**: Break into 3-7 atomic, verifiable tasks.
17
17
  5. **Phase**: Group into `research`, `implementation`, and `validation`.
18
18
  6. **Hierarchy**: Use `parent_id` / `depends_on` for sequencing.
19
- 7. **Create**: Use `task-create` in current repo with stable `task_code`, tags, and acceptance criteria.
19
+ 7. **Priority Scale**: When creating tasks, use the exact MCP scale `1=Low`, `2=Normal`, `3=Medium`, `4=High`, `5=Critical`. Higher number means higher urgency.
20
+ 8. **Create**: Use `task-create` in current repo with stable `task_code`, tags, and acceptance criteria.
20
21
 
21
22
  Display final plan to user.
@@ -9,8 +9,9 @@ agent: Project Manager
9
9
  ## 1. NAVIGATION (`task-list`)
10
10
  - **Sync**: Call `task-list` at every session start (default: `in_progress,pending`).
11
11
  - **Format**: Compact pointer table: `id`, `task_code`, `title`, `status`, `priority`, `updated_at`, `comments_count`. Use `query` for keyword search.
12
- - **Retrieve**: Fetch full context via `task-detail` AFTER selecting a task.
13
- - **Coordination**: Check active ownership with task metadata and `task-claim`. NEVER work on tasks claimed by others. Focus on ONE task at a time.
12
+ - **Priority Scale**: Interpret `priority` with MCP semantics: `1=Low`, `2=Normal`, `3=Medium`, `4=High`, `5=Critical`.
13
+ - **Retrieve**: Fetch full context via `task-detail` AFTER selecting a task. The hydrated task includes current coordination state such as active claims and pending handoffs.
14
+ - **Coordination**: Check active ownership with task coordination metadata, `task-claim`, and `claim-list`. NEVER work on tasks claimed by others. Focus on ONE task at a time.
14
15
 
15
16
  ## 2. DETAIL TOOLS
16
17
  - **Tasks**: Call `task-detail` for history/comments (ID or `task_code`).
@@ -23,6 +24,8 @@ agent: Project Manager
23
24
  - **Transition Safety**: MUST move from `backlog/pending` → `in_progress` → `completed`. Skipping `in_progress` is forbidden.
24
25
  - **Automatic Cleanup**: `task-update` to `completed` or `canceled` automatically releases active claims and expires pending handoffs linked to that task.
25
26
  - **Claiming**: Use `task-claim` when taking ownership of a task, with `task_code` when working from human-visible queues.
27
+ - **Claim Inspection**: Use `claim-list` when ownership is unclear or when triaging stale work.
28
+ - **Claim Release**: Use `claim-release` to clear stale ownership explicitly when a task is being handed back or reassigned.
26
29
  - **Handoff**: Use `handoff-create` only when pausing or transferring unfinished work. Do not use pending handoffs for completion summaries; close consumed/stale handoffs with `handoff-update`.
27
30
  - **Validation**: Only mark `completed` after passing tests or explicitly documenting why verification could not run.
28
31
  - **Archiving**: Completion triggers auto-archive to `task_archive` memory with token reporting.
@@ -51,7 +51,8 @@ agent: Task Executor
51
51
  ## 3. BACKLOG MAINTENANCE
52
52
  If active queue is empty:
53
53
  1. Call `task-list` (status: `backlog`).
54
- 2. Move up to 20 high-priority tasks to `pending` via `task-update`.
54
+ 2. Move up to 20 highest-priority tasks to `pending` via `task-update`.
55
+ 3. Interpret priority using MCP ordering: `5=Critical`, `4=High`, `3=Medium`, `2=Normal`, `1=Low`.
55
56
 
56
57
  ## 4. REPORT
57
58
  Provide progress summary.
@@ -18,7 +18,7 @@ Use the tools in the same flow exposed by the dashboard: navigate with compact l
18
18
 
19
19
  ## 2. Task Flow
20
20
  - **Navigate**: Start with `task-list` using active statuses (`in_progress,pending`) or explicit filters.
21
- - **Hydrate**: Use `task-detail` after selecting a task from the list. Do not treat list rows as full task context.
21
+ - **Hydrate**: Use `task-detail` after selecting a task from the list. Full task detail includes comments plus current coordination state such as active claims and pending handoffs.
22
22
  - **Mutate**: Use `task-create`, `task-update`, and `task-delete` for lifecycle changes.
23
23
  - **Transitions**: Move `backlog/pending/blocked` to `in_progress` before `completed`; include validation evidence and token estimate on completion.
24
24
  - **Automatic cleanup**: Moving a task to `completed` or `canceled` automatically releases active claims and expires pending handoffs linked to that task.
@@ -30,11 +30,13 @@ Use the tools in the same flow exposed by the dashboard: navigate with compact l
30
30
  - **Scope**: Prefer repo-specific standards for local conventions; use global standards only for cross-repo rules.
31
31
 
32
32
  ## 4. Handoff & Claim Flow
33
- - **Queue**: Use `handoff-list` as the handoff navigation layer. Filter by `status`, `from_agent`, or `to_agent`.
33
+ - **Queue**: Use `handoff-list` as the handoff navigation layer. Filter by `status`, `from_agent`, or `to_agent`. Hydrated handoff rows include `task_code`, `updated_at`, `expires_at`, and structured `context`.
34
34
  - **Create handoff**: Use `handoff-create` only when unfinished work needs context transfer. Include `from_agent`, optional `to_agent`, optional `task_code` or `task_id`, concise `summary`, and structured `context` with `next_steps`, `blockers`, or `remaining_work`.
35
35
  - **Close handoff**: Use `handoff-update` to move stale or consumed handoffs out of `pending`. Use `accepted` when consumed, `rejected` when declined, and `expired` when obsolete or only a completed-work summary.
36
36
  - **No completion handoff**: Do not create pending handoffs for completed-work summaries, release notes, validation notes, or archive records. Put those on `task-update` comments or durable memory.
37
37
  - **Claim task**: Use `task-claim` for task ownership. Do not encode claims in memory metadata.
38
+ - **Inspect claims**: Use `claim-list` to inspect active ownership by repo or agent before reassigning work.
39
+ - **Release claims**: Use `claim-release` to explicitly clear stale ownership when work is transferred or abandoned.
38
40
  - **Linkage**: Prefer `task_code` for human workflows and `task_id` when already hydrated.
39
41
 
40
42
  ## 5. Reference Flow
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vheins/local-memory-mcp",
3
- "version": "0.9.8",
3
+ "version": "0.9.10",
4
4
  "description": "MCP Local Memory Service for coding copilot agents",
5
5
  "mcpName": "io.github.vheins/local-memory-mcp",
6
6
  "type": "module",