memorix 1.8.0 → 1.8.1

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/index.js CHANGED
@@ -164845,6 +164845,37 @@ function normalizeDashboardTask(task) {
164845
164845
  preferredRole: task.preferred_role ?? task.preferredRole ?? null
164846
164846
  };
164847
164847
  }
164848
+ function emptyTeamSnapshot(mode, scope, status) {
164849
+ return {
164850
+ status,
164851
+ mode,
164852
+ readOnly: true,
164853
+ scope,
164854
+ agents: [],
164855
+ activeCount: 0,
164856
+ recentCount: 0,
164857
+ historicalCount: 0,
164858
+ totalAgents: 0,
164859
+ recentWindowDays: 7,
164860
+ locks: [],
164861
+ tasks: [],
164862
+ availableTasks: 0,
164863
+ sessions: 0,
164864
+ roles: [],
164865
+ roleOccupancy: [],
164866
+ handoffs: [],
164867
+ openTasks: 0,
164868
+ openHandoffs: 0,
164869
+ totalUnread: 0,
164870
+ activeSessions: 0,
164871
+ error: status === "error" ? "Coordination state unavailable" : "Coordination state is incomplete",
164872
+ errorCode: status === "error" ? "COORDINATION_STATE_UNAVAILABLE" : "COORDINATION_STATE_DEGRADED"
164873
+ };
164874
+ }
164875
+ function logTeamSnapshotFailure(scope, status) {
164876
+ const safeScope = scope === "global" ? "global" : "project";
164877
+ console.error("[dashboard] coordination snapshot unavailable", { status, scope: safeScope });
164878
+ }
164848
164879
  async function buildTeamSnapshot(dataDir, projectId, scope, mode) {
164849
164880
  try {
164850
164881
  const { initTeamStore: initTeamStore2 } = await Promise.resolve().then(() => (init_team_store(), team_store_exports));
@@ -164871,8 +164902,9 @@ async function buildTeamSnapshot(dataDir, projectId, scope, mode) {
164871
164902
  const roleOccupancy = effectiveProjectId ? teamStore.getRoleOccupancy(effectiveProjectId) : [];
164872
164903
  const handoffs = effectiveProjectId ? teamStore.listHandoffs(effectiveProjectId) : [];
164873
164904
  return {
164905
+ status: "ok",
164874
164906
  mode,
164875
- readOnly: mode === "standalone",
164907
+ readOnly: true,
164876
164908
  scope,
164877
164909
  agents: withTier,
164878
164910
  activeCount,
@@ -164893,28 +164925,8 @@ async function buildTeamSnapshot(dataDir, projectId, scope, mode) {
164893
164925
  activeSessions: activeCount
164894
164926
  };
164895
164927
  } catch {
164896
- return {
164897
- mode,
164898
- readOnly: mode === "standalone",
164899
- scope,
164900
- agents: [],
164901
- activeCount: 0,
164902
- recentCount: 0,
164903
- historicalCount: 0,
164904
- totalAgents: 0,
164905
- recentWindowDays: 7,
164906
- locks: [],
164907
- tasks: [],
164908
- availableTasks: 0,
164909
- sessions: 0,
164910
- roles: [],
164911
- roleOccupancy: [],
164912
- handoffs: [],
164913
- openTasks: 0,
164914
- openHandoffs: 0,
164915
- totalUnread: 0,
164916
- activeSessions: 0
164917
- };
164928
+ logTeamSnapshotFailure(scope, "error");
164929
+ return emptyTeamSnapshot(mode, scope, "error");
164918
164930
  }
164919
164931
  }
164920
164932
  function readBody(req) {
@@ -164933,13 +164945,12 @@ function readBody(req) {
164933
164945
  req.on("error", reject);
164934
164946
  });
164935
164947
  }
164936
- async function startDashboard(dataDir, port, staticDir, projectId, projectName, autoOpen = true, teamInstances, projectRoot = null, projectResolved = true) {
164948
+ async function startDashboard(dataDir, port, staticDir, projectId, projectName, autoOpen = true, projectRoot = null, projectResolved = true) {
164937
164949
  await initObservationStore(dataDir);
164938
164950
  await initSessionStore(dataDir);
164939
164951
  const resolvedStaticDir = staticDir;
164940
164952
  const baseDir = getBaseDataDir();
164941
- const isControlPlane = !!teamInstances;
164942
- const state = { projectId, projectName, dataDir, projectRoot, projectResolved, mode: isControlPlane ? "control-plane" : "standalone", port };
164953
+ const state = { projectId, projectName, dataDir, projectRoot, projectResolved, mode: "standalone", port };
164943
164954
  const server = createServer(async (req, res) => {
164944
164955
  const url = req.url || "/";
164945
164956
  if (url.startsWith("/api/set-current-project") && req.method === "POST") {
@@ -164961,54 +164972,20 @@ async function startDashboard(dataDir, port, staticDir, projectId, projectName,
164961
164972
  }
164962
164973
  return;
164963
164974
  }
164964
- if (url.startsWith("/api/team")) {
164965
- if (!teamInstances) {
164966
- const parsedUrl = new URL(url, `http://127.0.0.1:${port}`);
164967
- const scope = parsedUrl.searchParams.get("scope") || "project";
164968
- sendJson(res, await buildTeamSnapshot(state.dataDir, state.projectId, scope, state.mode));
164969
- return;
164970
- }
164971
- try {
164972
- teamInstances.fileLocks.cleanExpired();
164973
- const agents = teamInstances.registry.listAgents();
164974
- const locks = teamInstances.fileLocks.listLocks();
164975
- const tasks = teamInstances.taskManager.list();
164976
- const available = teamInstances.taskManager.getAvailable();
164977
- let roles = [];
164978
- let roleOccupancy = [];
164979
- let handoffs = [];
164980
- try {
164981
- const { getTeamStore: getTeamStore2, isTeamStoreInitialized: isTeamStoreInitialized2 } = await Promise.resolve().then(() => (init_team_store(), team_store_exports));
164982
- if (isTeamStoreInitialized2()) {
164983
- const teamStore = getTeamStore2();
164984
- const projectId2 = state.projectId;
164985
- roles = teamStore.listRoles(projectId2);
164986
- roleOccupancy = teamStore.getRoleOccupancy(projectId2);
164987
- handoffs = teamStore.listHandoffs(projectId2);
164988
- }
164989
- } catch {
164990
- }
164975
+ const parsedUrl = new URL(url, `http://127.0.0.1:${port}`);
164976
+ if (parsedUrl.pathname === "/api/team") {
164977
+ if (req.method !== "GET") {
164991
164978
  sendJson(res, {
164992
- agents: agents.map((a) => ({
164993
- ...a,
164994
- unread: teamInstances.messageBus.getUnreadCount(a.id)
164995
- })),
164996
- activeCount: teamInstances.registry.getActiveCount(),
164997
- locks,
164998
- tasks,
164999
- availableTasks: available.length,
165000
- roles,
165001
- roleOccupancy,
165002
- handoffs,
165003
- // Resume data for "Continue this project" area
165004
- openTasks: tasks.filter((t2) => t2.status === "pending" || t2.status === "in_progress").length,
165005
- openHandoffs: handoffs.filter((h2) => h2.handoff_status === "open" || h2.handoffStatus === "open").length,
165006
- totalUnread: agents.reduce((sum, a) => sum + teamInstances.messageBus.getUnreadCount(a.id), 0),
165007
- activeSessions: agents.filter((a) => a.status === "active").length
165008
- });
165009
- } catch {
165010
- sendJson(res, { agents: [], activeCount: 0, locks: [], tasks: [], availableTasks: 0, roles: [], roleOccupancy: [], handoffs: [] });
164979
+ status: "error",
164980
+ readOnly: true,
164981
+ error: "Coordination status is read-only",
164982
+ errorCode: "COORDINATION_STATUS_READ_ONLY"
164983
+ }, 405);
164984
+ return;
165011
164985
  }
164986
+ const scope = parsedUrl.searchParams.get("scope") || "project";
164987
+ const snapshot = await buildTeamSnapshot(state.dataDir, state.projectId, scope, state.mode);
164988
+ sendJson(res, snapshot, snapshot.status === "error" ? 503 : 200);
165012
164989
  return;
165013
164990
  }
165014
164991
  if (url.startsWith("/api/")) {
@@ -165029,13 +165006,12 @@ async function startDashboard(dataDir, port, staticDir, projectId, projectName,
165029
165006
  server.listen(port, "127.0.0.1", () => {
165030
165007
  const url = `http://127.0.0.1:${port}`;
165031
165008
  const resolvedLabel = projectResolved ? "resolved" : "unresolved";
165032
- const modeLabel = isControlPlane ? "Control Plane" : "Standalone";
165009
+ const modeLabel = "Standalone";
165033
165010
  console.error(` Memorix Dashboard [${modeLabel}]`);
165034
165011
  console.error(` \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);
165035
165012
  console.error(` Mode: ${modeLabel}`);
165036
165013
  console.error(` Project: ${projectName} (${projectId}) [${resolvedLabel}]`);
165037
165014
  console.error(` Local: ${url}`);
165038
- if (isControlPlane) console.error(` MCP: ${url}/mcp`);
165039
165015
  console.error(` Data dir: ${dataDir}`);
165040
165016
  console.error(`
165041
165017
  Press Ctrl+C to stop
@@ -168210,7 +168186,7 @@ The path should point to a directory containing a .git folder.`
168210
168186
  };
168211
168187
  const server = existingServer ?? new McpServer({
168212
168188
  name: "memorix",
168213
- version: true ? "1.8.0" : "1.0.1"
168189
+ version: true ? "1.8.1" : "1.0.1"
168214
168190
  });
168215
168191
  const originalRegisterTool = server.registerTool.bind(server);
168216
168192
  server.registerTool = ((name, ...args) => {
@@ -171363,7 +171339,7 @@ ${json2}
171363
171339
  }
171364
171340
  }
171365
171341
  console.error(`[memorix] Dashboard staticDir: ${staticDir}`);
171366
- startDashboard2(projectDir2, portNum, staticDir, project.id, project.name, false, void 0, project.rootPath, projectResolved).then(() => {
171342
+ startDashboard2(projectDir2, portNum, staticDir, project.id, project.name, false, project.rootPath, projectResolved).then(() => {
171367
171343
  dashboardRunning = true;
171368
171344
  }).catch((err) => {
171369
171345
  console.error("[memorix] Dashboard error:", err);
@@ -171705,7 +171681,7 @@ ${lines.join("\n")}` }] };
171705
171681
  server.registerTool(
171706
171682
  "team_task",
171707
171683
  {
171708
- title: "Task Board",
171684
+ title: "Task Status",
171709
171685
  description: 'Create, claim, complete, or list tasks in the team task board. Supports dependencies. Action "create": create a task. Action "claim": assign to yourself (atomic, race-safe). Action "complete": mark done with result. Action "list": show tasks.',
171710
171686
  inputSchema: {
171711
171687
  action: z626.enum(["create", "claim", "complete", "list"]).describe("Operation to perform"),
@@ -172759,7 +172735,7 @@ var init_serve_shared = __esm({
172759
172735
 
172760
172736
  // src/cli/version.ts
172761
172737
  function getCliVersion() {
172762
- return true ? "1.8.0" : pkg.version;
172738
+ return true ? "1.8.1" : pkg.version;
172763
172739
  }
172764
172740
  var init_version3 = __esm({
172765
172741
  "src/cli/version.ts"() {
@@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [1.8.1] - 2026-08-24
8
+
9
+ ### Changed
10
+ - **Truthful coordination status** -- the persistent SQLite `TeamStore` is the
11
+ sole coordination truth for agents, tasks, messages, locks, handoffs, and poll
12
+ state. The Dashboard exposes read-only `Coordination Status` and `Task Status`
13
+ views, and `/api/team` reports explicit `error` or `degraded` status instead of
14
+ presenting a failed coordination read as a healthy empty result.
15
+
7
16
  ## [1.8.0] - 2026-08-23
8
17
 
9
18
  ### Added
package/dist/sdk.js CHANGED
@@ -160824,6 +160824,37 @@ function normalizeDashboardTask(task) {
160824
160824
  preferredRole: task.preferred_role ?? task.preferredRole ?? null
160825
160825
  };
160826
160826
  }
160827
+ function emptyTeamSnapshot(mode, scope, status) {
160828
+ return {
160829
+ status,
160830
+ mode,
160831
+ readOnly: true,
160832
+ scope,
160833
+ agents: [],
160834
+ activeCount: 0,
160835
+ recentCount: 0,
160836
+ historicalCount: 0,
160837
+ totalAgents: 0,
160838
+ recentWindowDays: 7,
160839
+ locks: [],
160840
+ tasks: [],
160841
+ availableTasks: 0,
160842
+ sessions: 0,
160843
+ roles: [],
160844
+ roleOccupancy: [],
160845
+ handoffs: [],
160846
+ openTasks: 0,
160847
+ openHandoffs: 0,
160848
+ totalUnread: 0,
160849
+ activeSessions: 0,
160850
+ error: status === "error" ? "Coordination state unavailable" : "Coordination state is incomplete",
160851
+ errorCode: status === "error" ? "COORDINATION_STATE_UNAVAILABLE" : "COORDINATION_STATE_DEGRADED"
160852
+ };
160853
+ }
160854
+ function logTeamSnapshotFailure(scope, status) {
160855
+ const safeScope = scope === "global" ? "global" : "project";
160856
+ console.error("[dashboard] coordination snapshot unavailable", { status, scope: safeScope });
160857
+ }
160827
160858
  async function buildTeamSnapshot(dataDir, projectId, scope, mode) {
160828
160859
  try {
160829
160860
  const { initTeamStore: initTeamStore2 } = await Promise.resolve().then(() => (init_team_store(), team_store_exports));
@@ -160850,8 +160881,9 @@ async function buildTeamSnapshot(dataDir, projectId, scope, mode) {
160850
160881
  const roleOccupancy = effectiveProjectId ? teamStore.getRoleOccupancy(effectiveProjectId) : [];
160851
160882
  const handoffs = effectiveProjectId ? teamStore.listHandoffs(effectiveProjectId) : [];
160852
160883
  return {
160884
+ status: "ok",
160853
160885
  mode,
160854
- readOnly: mode === "standalone",
160886
+ readOnly: true,
160855
160887
  scope,
160856
160888
  agents: withTier,
160857
160889
  activeCount,
@@ -160872,28 +160904,8 @@ async function buildTeamSnapshot(dataDir, projectId, scope, mode) {
160872
160904
  activeSessions: activeCount
160873
160905
  };
160874
160906
  } catch {
160875
- return {
160876
- mode,
160877
- readOnly: mode === "standalone",
160878
- scope,
160879
- agents: [],
160880
- activeCount: 0,
160881
- recentCount: 0,
160882
- historicalCount: 0,
160883
- totalAgents: 0,
160884
- recentWindowDays: 7,
160885
- locks: [],
160886
- tasks: [],
160887
- availableTasks: 0,
160888
- sessions: 0,
160889
- roles: [],
160890
- roleOccupancy: [],
160891
- handoffs: [],
160892
- openTasks: 0,
160893
- openHandoffs: 0,
160894
- totalUnread: 0,
160895
- activeSessions: 0
160896
- };
160907
+ logTeamSnapshotFailure(scope, "error");
160908
+ return emptyTeamSnapshot(mode, scope, "error");
160897
160909
  }
160898
160910
  }
160899
160911
  function readBody(req) {
@@ -160912,13 +160924,12 @@ function readBody(req) {
160912
160924
  req.on("error", reject);
160913
160925
  });
160914
160926
  }
160915
- async function startDashboard(dataDir, port, staticDir, projectId, projectName, autoOpen = true, teamInstances, projectRoot = null, projectResolved = true) {
160927
+ async function startDashboard(dataDir, port, staticDir, projectId, projectName, autoOpen = true, projectRoot = null, projectResolved = true) {
160916
160928
  await initObservationStore(dataDir);
160917
160929
  await initSessionStore(dataDir);
160918
160930
  const resolvedStaticDir = staticDir;
160919
160931
  const baseDir = getBaseDataDir();
160920
- const isControlPlane = !!teamInstances;
160921
- const state = { projectId, projectName, dataDir, projectRoot, projectResolved, mode: isControlPlane ? "control-plane" : "standalone", port };
160932
+ const state = { projectId, projectName, dataDir, projectRoot, projectResolved, mode: "standalone", port };
160922
160933
  const server = createServer(async (req, res) => {
160923
160934
  const url = req.url || "/";
160924
160935
  if (url.startsWith("/api/set-current-project") && req.method === "POST") {
@@ -160940,54 +160951,20 @@ async function startDashboard(dataDir, port, staticDir, projectId, projectName,
160940
160951
  }
160941
160952
  return;
160942
160953
  }
160943
- if (url.startsWith("/api/team")) {
160944
- if (!teamInstances) {
160945
- const parsedUrl = new URL(url, `http://127.0.0.1:${port}`);
160946
- const scope = parsedUrl.searchParams.get("scope") || "project";
160947
- sendJson(res, await buildTeamSnapshot(state.dataDir, state.projectId, scope, state.mode));
160948
- return;
160949
- }
160950
- try {
160951
- teamInstances.fileLocks.cleanExpired();
160952
- const agents = teamInstances.registry.listAgents();
160953
- const locks = teamInstances.fileLocks.listLocks();
160954
- const tasks = teamInstances.taskManager.list();
160955
- const available = teamInstances.taskManager.getAvailable();
160956
- let roles = [];
160957
- let roleOccupancy = [];
160958
- let handoffs = [];
160959
- try {
160960
- const { getTeamStore: getTeamStore2, isTeamStoreInitialized: isTeamStoreInitialized2 } = await Promise.resolve().then(() => (init_team_store(), team_store_exports));
160961
- if (isTeamStoreInitialized2()) {
160962
- const teamStore = getTeamStore2();
160963
- const projectId2 = state.projectId;
160964
- roles = teamStore.listRoles(projectId2);
160965
- roleOccupancy = teamStore.getRoleOccupancy(projectId2);
160966
- handoffs = teamStore.listHandoffs(projectId2);
160967
- }
160968
- } catch {
160969
- }
160954
+ const parsedUrl = new URL(url, `http://127.0.0.1:${port}`);
160955
+ if (parsedUrl.pathname === "/api/team") {
160956
+ if (req.method !== "GET") {
160970
160957
  sendJson(res, {
160971
- agents: agents.map((a) => ({
160972
- ...a,
160973
- unread: teamInstances.messageBus.getUnreadCount(a.id)
160974
- })),
160975
- activeCount: teamInstances.registry.getActiveCount(),
160976
- locks,
160977
- tasks,
160978
- availableTasks: available.length,
160979
- roles,
160980
- roleOccupancy,
160981
- handoffs,
160982
- // Resume data for "Continue this project" area
160983
- openTasks: tasks.filter((t2) => t2.status === "pending" || t2.status === "in_progress").length,
160984
- openHandoffs: handoffs.filter((h2) => h2.handoff_status === "open" || h2.handoffStatus === "open").length,
160985
- totalUnread: agents.reduce((sum, a) => sum + teamInstances.messageBus.getUnreadCount(a.id), 0),
160986
- activeSessions: agents.filter((a) => a.status === "active").length
160987
- });
160988
- } catch {
160989
- sendJson(res, { agents: [], activeCount: 0, locks: [], tasks: [], availableTasks: 0, roles: [], roleOccupancy: [], handoffs: [] });
160958
+ status: "error",
160959
+ readOnly: true,
160960
+ error: "Coordination status is read-only",
160961
+ errorCode: "COORDINATION_STATUS_READ_ONLY"
160962
+ }, 405);
160963
+ return;
160990
160964
  }
160965
+ const scope = parsedUrl.searchParams.get("scope") || "project";
160966
+ const snapshot = await buildTeamSnapshot(state.dataDir, state.projectId, scope, state.mode);
160967
+ sendJson(res, snapshot, snapshot.status === "error" ? 503 : 200);
160991
160968
  return;
160992
160969
  }
160993
160970
  if (url.startsWith("/api/")) {
@@ -161008,13 +160985,12 @@ async function startDashboard(dataDir, port, staticDir, projectId, projectName,
161008
160985
  server.listen(port, "127.0.0.1", () => {
161009
160986
  const url = `http://127.0.0.1:${port}`;
161010
160987
  const resolvedLabel = projectResolved ? "resolved" : "unresolved";
161011
- const modeLabel = isControlPlane ? "Control Plane" : "Standalone";
160988
+ const modeLabel = "Standalone";
161012
160989
  console.error(` Memorix Dashboard [${modeLabel}]`);
161013
160990
  console.error(` \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);
161014
160991
  console.error(` Mode: ${modeLabel}`);
161015
160992
  console.error(` Project: ${projectName} (${projectId}) [${resolvedLabel}]`);
161016
160993
  console.error(` Local: ${url}`);
161017
- if (isControlPlane) console.error(` MCP: ${url}/mcp`);
161018
160994
  console.error(` Data dir: ${dataDir}`);
161019
160995
  console.error(`
161020
160996
  Press Ctrl+C to stop
@@ -168007,7 +167983,7 @@ The path should point to a directory containing a .git folder.`
168007
167983
  };
168008
167984
  const server = existingServer ?? new McpServer({
168009
167985
  name: "memorix",
168010
- version: true ? "1.8.0" : "1.0.1"
167986
+ version: true ? "1.8.1" : "1.0.1"
168011
167987
  });
168012
167988
  const originalRegisterTool = server.registerTool.bind(server);
168013
167989
  server.registerTool = ((name, ...args) => {
@@ -171160,7 +171136,7 @@ ${json2}
171160
171136
  }
171161
171137
  }
171162
171138
  console.error(`[memorix] Dashboard staticDir: ${staticDir}`);
171163
- startDashboard2(projectDir2, portNum, staticDir, project.id, project.name, false, void 0, project.rootPath, projectResolved).then(() => {
171139
+ startDashboard2(projectDir2, portNum, staticDir, project.id, project.name, false, project.rootPath, projectResolved).then(() => {
171164
171140
  dashboardRunning = true;
171165
171141
  }).catch((err) => {
171166
171142
  console.error("[memorix] Dashboard error:", err);
@@ -171502,7 +171478,7 @@ ${lines.join("\n")}` }] };
171502
171478
  server.registerTool(
171503
171479
  "team_task",
171504
171480
  {
171505
- title: "Task Board",
171481
+ title: "Task Status",
171506
171482
  description: 'Create, claim, complete, or list tasks in the team task board. Supports dependencies. Action "create": create a task. Action "claim": assign to yourself (atomic, race-safe). Action "complete": mark done with result. Action "list": show tasks.',
171507
171483
  inputSchema: {
171508
171484
  action: z626.enum(["create", "claim", "complete", "list"]).describe("Operation to perform"),
@@ -864,6 +864,8 @@ Important inputs:
864
864
 
865
865
  When using HTTP mode, the main dashboard is usually served from the same port as `serve-http`.
866
866
 
867
+ The Dashboard's Coordination Status page is read-only. It reads the selected project's agents, tasks, locks, handoffs, messages, and poll state from the persistent SQLite `TeamStore`; it does not expose team/task write endpoints or replace task execution and orchestration tools. A coordination read failure is returned as an explicit degraded/error response rather than an empty healthy snapshot.
868
+
867
869
  ---
868
870
 
869
871
  ## 12. Optional Graph Compatibility Tools
@@ -498,7 +498,9 @@ It provides an operational view for:
498
498
  - sessions
499
499
  - retention state
500
500
  - preview-first cleanup, consolidation, intelligent deduplication, and retention archival
501
- - read-only orchestration coordination state in the standalone dashboard and live state in HTTP service mode
501
+ - read-only Coordination Status derived from the project-scoped SQLite `TeamStore`; the page is a projection, not a task execution surface
502
+
503
+ `TeamStore` is the real persistent coordination layer for agents, tasks, messages, locks, handoffs, and poll state. Dashboard coordination reads use that same SQLite state and return an explicit degraded/error status when it cannot be read; they must not substitute a normal-looking empty snapshot.
502
504
 
503
505
  Dashboard maintenance is not a separate business-logic implementation. CLI, MCP, background jobs, and Dashboard routes share the same cleanup, consolidation, deduplication, and retention functions. Mutation routes issue a project-bound signed preview token and reject execution when the candidate set changed after preview.
504
506
 
package/docs/DASHBOARD.md CHANGED
@@ -19,6 +19,12 @@ memorix dashboard
19
19
 
20
20
  Both modes read the same project-scoped stores. The project switcher changes the active project filter; it does not merge projects or grant access to personal memories.
21
21
 
22
+ ## Coordination Status
23
+
24
+ The Coordination Status page is a read-only projection of the selected project's persistent coordination state. `TeamStore` is the canonical SQLite layer for agents, tasks, messages, locks, handoffs, and poll state; the Dashboard does not keep a second in-memory coordination registry.
25
+
26
+ The page reports agents, task status, file locks, and handoffs for the selected project. It exposes no team or task write endpoints and is not a task execution or full orchestration platform. If the SQLite read fails, the API returns an explicit degraded/error status and the page shows that the status is unavailable instead of presenting an empty result as healthy.
27
+
22
28
  ## Maintenance Workbench
23
29
 
24
30
  The Observations page exposes three explicit maintenance actions:
@@ -13,8 +13,8 @@ Memorix is a TypeScript project built around:
13
13
 
14
14
  ## Current Development Baseline
15
15
 
16
- The current release work targets the **1.8.0 release line** and package metadata
17
- is kept at `1.8.0` for this release commit.
16
+ The current release work targets the **1.8.1 release line** and package metadata
17
+ is kept at `1.8.1` for this release commit.
18
18
 
19
19
  Contributors should assume the following areas are part of the current release line:
20
20
 
package/docs/README.md CHANGED
@@ -33,7 +33,7 @@ The public docs are organized by user intent:
33
33
  | CLI commands and MCP tools | [API_REFERENCE.md](API_REFERENCE.md) |
34
34
  | Memory Autopilot, Code State, and context packs | [API_REFERENCE.md § Memory Autopilot, Code State, and Context Packs](API_REFERENCE.md#memory-autopilot-code-state-and-context-packs), [1.2 Code State](1.2.0-CODE-STATE.md), and [1.2 Workset Retrieval](1.2.0-WORKSET-RETRIEVAL.md) |
35
35
  | Reviewed episodic, semantic, and procedural long-term memory | [1.3 Memory Architecture](1.3-MEMORY-ARCHITECTURE.md) |
36
- | Browse memory and run preview-first local maintenance | [Dashboard](DASHBOARD.md) |
36
+ | Browse memory, maintenance, and read-only Coordination Status | [Dashboard](DASHBOARD.md) |
37
37
  | Reviewable knowledge pages and workflow inheritance | [API_REFERENCE.md § Knowledge Workspace and Workflows](API_REFERENCE.md#knowledge-workspace-and-workflows), [1.2 Knowledge Workspace](1.2.0-KNOWLEDGE-WORKSPACE.md), and [1.2 Workflow Inheritance](1.2.0-WORKFLOW-INHERITANCE.md) |
38
38
  | Git-derived engineering memory | [GIT_MEMORY.md](GIT_MEMORY.md) |
39
39
  | Memory formation and quality pipeline | [MEMORY_FORMATION_PIPELINE.md](MEMORY_FORMATION_PIPELINE.md) |
@@ -121,7 +121,7 @@ Historical/deep-reference documents may describe older designs. If they conflict
121
121
 
122
122
  ## Current Product Line
123
123
 
124
- The current product line is **1.8.0**. The authoritative acceptance contract is
124
+ The current product line is **1.8.1**. The authoritative acceptance contract is
125
125
  [1.8.0 Release Specification](1.8.0-RELEASE-CANDIDATE-SPEC.md).
126
126
  The current baseline has:
127
127
 
@@ -130,6 +130,9 @@ The current baseline has:
130
130
  - `memorix background start` runs the shared HTTP MCP service and dashboard
131
131
  - Dashboard maintenance is preview-first, project-scoped, and uses the same
132
132
  cleanup and deduplication planners as CLI and MCP
133
+ - Dashboard Coordination Status is read-only and projects the persistent SQLite
134
+ `TeamStore` truth; its task section is `Task Status` and failed reads are
135
+ explicit `error`/`degraded` states
133
136
  - context and CodeGraph commands return bounded task receipts before detailed diagnostics
134
137
  - HTTP MCP sessions have a bounded, explicit lifecycle and fail with a reinitialize hint after expiry
135
138
  - `memorix integrate --agent <agent>` and `memorix hooks install --agent <agent>` remain manual/fallback generation commands
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "memorix",
3
3
  "mcpName": "io.github.AVIDS2/memorix",
4
- "version": "1.8.0",
4
+ "version": "1.8.1",
5
5
  "description": "Local-first shared memory layer for AI coding agents across MCP clients, Git history, reasoning context, and project sessions.",
6
6
  "type": "module",
7
7
  "sideEffects": false,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://anthropic.com/claude-code/plugin.schema.json",
3
3
  "name": "memorix",
4
- "version": "1.8.0",
4
+ "version": "1.8.1",
5
5
  "description": "Shared workspace memory for Claude Code and other AI coding agents.",
6
6
  "author": {
7
7
  "name": "AVIDS2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "description": "Local-first project memory for CodeBuddy Code and other coding agents.",
5
5
  "author": {
6
6
  "name": "AVIDS2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "description": "Shared workspace memory for Codex and other AI coding agents.",
5
5
  "author": {
6
6
  "name": "AVIDS2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "description": "Shared local workspace memory for GitHub Copilot CLI and other AI coding agents.",
5
5
  "author": {
6
6
  "name": "AVIDS2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "mcpServers": {
5
5
  "memorix": {
6
6
  "command": "memorix",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix-omp-package",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "description": "Memorix shared workspace memory package for Oh-my-Pi.",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "description": "Shared workspace memory for OpenClaw and other AI coding agents.",
5
5
  "author": {
6
6
  "name": "AVIDS2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memorix-pi-package",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "description": "Memorix shared workspace memory package for Pi coding agent.",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
package/server.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "url": "https://github.com/AVIDS2/memorix",
8
8
  "source": "github"
9
9
  },
10
- "version": "1.8.0",
10
+ "version": "1.8.1",
11
11
  "websiteUrl": "https://github.com/AVIDS2/memorix#readme",
12
12
  "icons": [
13
13
  {
@@ -22,7 +22,7 @@
22
22
  {
23
23
  "registryType": "npm",
24
24
  "identifier": "memorix",
25
- "version": "1.8.0",
25
+ "version": "1.8.1",
26
26
  "runtimeHint": "npx",
27
27
  "packageArguments": [
28
28
  {
@@ -59,7 +59,7 @@ export default defineCommand({
59
59
  const cliDir = path.dirname(fileURLToPath(import.meta.url));
60
60
  const staticDir = path.join(cliDir, '..', 'dashboard', 'static');
61
61
 
62
- await startDashboard(dataDir, port, staticDir, project.id, project.name, true, undefined, project.rootPath, true);
62
+ await startDashboard(dataDir, port, staticDir, project.id, project.name, true, project.rootPath, true);
63
63
 
64
64
  // Keep alive
65
65
  await new Promise(() => { });