devsmind-mcp 2.4.0 → 3.0.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.
Files changed (128) hide show
  1. package/README.md +326 -234
  2. package/dist/cli/activity.d.ts +9 -0
  3. package/dist/cli/activity.js +69 -0
  4. package/dist/cli/activity.js.map +1 -0
  5. package/dist/cli/describe.d.ts +31 -0
  6. package/dist/cli/describe.js +201 -0
  7. package/dist/cli/describe.js.map +1 -0
  8. package/dist/cli/diff.d.ts +14 -0
  9. package/dist/cli/diff.js +161 -0
  10. package/dist/cli/diff.js.map +1 -0
  11. package/dist/cli/embed.d.ts +6 -0
  12. package/dist/cli/embed.js +109 -0
  13. package/dist/cli/embed.js.map +1 -0
  14. package/dist/cli/extract-agent.d.ts +66 -0
  15. package/dist/cli/extract-agent.js +192 -0
  16. package/dist/cli/extract-agent.js.map +1 -0
  17. package/dist/cli/feedback.d.ts +11 -0
  18. package/dist/cli/feedback.js +90 -0
  19. package/dist/cli/feedback.js.map +1 -0
  20. package/dist/cli/index.js +128 -5
  21. package/dist/cli/index.js.map +1 -1
  22. package/dist/cli/init.d.ts +30 -0
  23. package/dist/cli/init.js +89 -18
  24. package/dist/cli/init.js.map +1 -1
  25. package/dist/cli/integrations/memory-topics.d.ts +44 -0
  26. package/dist/cli/integrations/memory-topics.js +295 -0
  27. package/dist/cli/integrations/memory-topics.js.map +1 -0
  28. package/dist/cli/integrations/memory.d.ts +11 -5
  29. package/dist/cli/integrations/memory.js +132 -37
  30. package/dist/cli/integrations/memory.js.map +1 -1
  31. package/dist/cli/integrations/prompt.d.ts +8 -0
  32. package/dist/cli/integrations/prompt.js +24 -3
  33. package/dist/cli/integrations/prompt.js.map +1 -1
  34. package/dist/cli/integrations/registry.d.ts +19 -5
  35. package/dist/cli/integrations/registry.js +23 -13
  36. package/dist/cli/integrations/registry.js.map +1 -1
  37. package/dist/cli/llm-client.d.ts +116 -0
  38. package/dist/cli/llm-client.js +322 -0
  39. package/dist/cli/llm-client.js.map +1 -0
  40. package/dist/cli/rule.d.ts +22 -2
  41. package/dist/cli/rule.js +113 -32
  42. package/dist/cli/rule.js.map +1 -1
  43. package/dist/cli/runner.d.ts +21 -0
  44. package/dist/cli/runner.js +94 -276
  45. package/dist/cli/runner.js.map +1 -1
  46. package/dist/cli/sync-progress.d.ts +9 -0
  47. package/dist/cli/sync-progress.js +41 -0
  48. package/dist/cli/sync-progress.js.map +1 -0
  49. package/dist/cli/sync.js +5 -2
  50. package/dist/cli/sync.js.map +1 -1
  51. package/dist/cli/view.js +3 -2
  52. package/dist/cli/view.js.map +1 -1
  53. package/dist/cli/workflow.js +26 -20
  54. package/dist/cli/workflow.js.map +1 -1
  55. package/dist/db/activity.d.ts +200 -0
  56. package/dist/db/activity.js +347 -0
  57. package/dist/db/activity.js.map +1 -0
  58. package/dist/db/analyze.js +18 -6
  59. package/dist/db/analyze.js.map +1 -1
  60. package/dist/db/database.d.ts +583 -99
  61. package/dist/db/database.js +1825 -553
  62. package/dist/db/database.js.map +1 -1
  63. package/dist/db/edges.d.ts +24 -0
  64. package/dist/db/edges.js +84 -0
  65. package/dist/db/edges.js.map +1 -1
  66. package/dist/db/embedder.d.ts +39 -0
  67. package/dist/db/embedder.js +0 -0
  68. package/dist/db/embedder.js.map +1 -0
  69. package/dist/db/feedback.d.ts +128 -0
  70. package/dist/db/feedback.js +182 -0
  71. package/dist/db/feedback.js.map +1 -0
  72. package/dist/db/file-diff.d.ts +32 -0
  73. package/dist/db/file-diff.js +110 -0
  74. package/dist/db/file-diff.js.map +1 -0
  75. package/dist/db/grep.d.ts +78 -0
  76. package/dist/db/grep.js +475 -0
  77. package/dist/db/grep.js.map +1 -0
  78. package/dist/db/message-revert.d.ts +63 -0
  79. package/dist/db/message-revert.js +258 -0
  80. package/dist/db/message-revert.js.map +1 -0
  81. package/dist/db/revert.d.ts +31 -0
  82. package/dist/db/revert.js +108 -0
  83. package/dist/db/revert.js.map +1 -0
  84. package/dist/db/schema.d.ts +49 -4
  85. package/dist/db/schema.js +125 -73
  86. package/dist/db/schema.js.map +1 -1
  87. package/dist/db/search-index.d.ts +65 -0
  88. package/dist/db/search-index.js +74 -0
  89. package/dist/db/search-index.js.map +1 -0
  90. package/dist/db/staging.d.ts +90 -5
  91. package/dist/db/staging.js +148 -22
  92. package/dist/db/staging.js.map +1 -1
  93. package/dist/mcp/server.d.ts +29 -7
  94. package/dist/mcp/server.js +2584 -809
  95. package/dist/mcp/server.js.map +1 -1
  96. package/dist/mcp/vendor/3d-force-graph.min.js +5 -0
  97. package/dist/mcp/vendor/force-graph.min.js +5 -0
  98. package/dist/mcp/vendor/model/model_int8.onnx +0 -0
  99. package/dist/mcp/vendor/model/vocab.txt +30522 -0
  100. package/dist/mcp/vendor/three.min.js +7 -0
  101. package/dist/mcp/view.css +419 -0
  102. package/dist/mcp/view.html +161 -0
  103. package/dist/mcp/view.js +245 -0
  104. package/dist/mcp/view_chat.js +382 -0
  105. package/dist/mcp/view_graph.js +576 -0
  106. package/dist/mcp/visualizer.d.ts +25 -2
  107. package/dist/mcp/visualizer.js +31 -4
  108. package/dist/mcp/visualizer.js.map +1 -1
  109. package/dist/utils/ast.d.ts +89 -0
  110. package/dist/utils/ast.js +378 -10
  111. package/dist/utils/ast.js.map +1 -1
  112. package/dist/utils/diff.d.ts +44 -0
  113. package/dist/utils/diff.js +78 -0
  114. package/dist/utils/diff.js.map +1 -0
  115. package/dist/utils/edit.d.ts +6 -0
  116. package/dist/utils/edit.js +47 -14
  117. package/dist/utils/edit.js.map +1 -1
  118. package/dist/utils/scanner.js +12 -4
  119. package/dist/utils/scanner.js.map +1 -1
  120. package/dist/utils/tokenize.d.ts +45 -0
  121. package/dist/utils/tokenize.js +129 -0
  122. package/dist/utils/tokenize.js.map +1 -0
  123. package/dist/utils/version.d.ts +14 -0
  124. package/dist/utils/version.js +61 -0
  125. package/dist/utils/version.js.map +1 -0
  126. package/package.json +18 -5
  127. package/dist/mcp/visualizer_2d.html +0 -635
  128. package/dist/mcp/visualizer_3d.html +0 -613
@@ -0,0 +1,200 @@
1
+ /**
2
+ * The local, gitignored activity log — sessions and messages, grouped for the Activity page.
3
+ *
4
+ * Everything here lives under `.devmind/local/`, which `devsmind init` adds to `.devmind/.gitignore`
5
+ * (see [[cli/init.ts]]). It never gets pushed: message text is only ever meaningful on the machine
6
+ * that wrote it, and the point of this store is to be a working-tree time machine for one
7
+ * developer, not a second copy of the shared graph. Committed history in `.devmind/history/*.json`
8
+ * is untouched by anything in this file — a message's `edits[]` is a self-contained backup, not a
9
+ * reference into committed data, so revert never depends on (or corrupts) what the team shares.
10
+ *
11
+ * JSON on disk, one file per message plus one sessions index — same shape of storage as staging.ts,
12
+ * same atomic temp+rename write, deliberately no new SQLite tables: this data has no reason to
13
+ * survive a `brain.db` rebuild via anything other than being read back from these files.
14
+ */
15
+ /**
16
+ * `'partial'` means some but not all of a message's edits are reverted — the result of reverting
17
+ * one file, or one single edit, within a message rather than the whole thing. Whole-message
18
+ * revert/un-revert (message-revert.ts) still exists and still flips every edit at once; this
19
+ * status is what lets the UI (and the un-revert ordering rule) tell "fully reverted" apart from
20
+ * "partially reverted via a more surgical action."
21
+ */
22
+ export type MessageStatus = 'applied' | 'partial' | 'reverted';
23
+ export interface MessageEdit {
24
+ /** Stable identity for this one edit — what a single-edit revert/un-revert targets. */
25
+ id: string;
26
+ node_id: string;
27
+ file_path: string;
28
+ at: string;
29
+ before: string;
30
+ after: string;
31
+ /** True once this specific edit has been reverted (via any granularity). Absent/false = applied. */
32
+ reverted?: boolean;
33
+ }
34
+ /** A message's status is derived from its edits, not tracked independently — this is the one
35
+ * place that mapping happens, so whole-message and granular (file/edit) revert paths can't drift
36
+ * out of sync with each other. */
37
+ export declare function deriveStatus(edits: MessageEdit[]): MessageStatus;
38
+ export interface ActivityMessage {
39
+ id: string;
40
+ session_id: string;
41
+ developer: string | null;
42
+ created_at: string;
43
+ updated_at: string;
44
+ /** The user's original request, when the caller supplied one. Null degrades to `summary` only. */
45
+ request: string | null;
46
+ /** Short machine-generated label (from the commit's reasoning), always present. */
47
+ summary: string;
48
+ status: MessageStatus;
49
+ edits: MessageEdit[];
50
+ /**
51
+ * Which of this message's edits have already been turned into workflow steps.
52
+ *
53
+ * Tracked as EDIT IDS rather than a "synced: true" flag because a message keeps growing after it
54
+ * is tagged — `recordMessage` appends edits to an existing message when consecutive commits share
55
+ * a request, and the revert engine rewrites `edits` in place. A boolean would permanently strand
56
+ * everything added after the moment it was set; a list of consumed ids means a re-sync is a true
57
+ * no-op and a message that grew produces a delta step.
58
+ */
59
+ workflow_sync?: {
60
+ workflow_id: string;
61
+ step_ids: string[];
62
+ synced_edit_ids: string[];
63
+ }[];
64
+ }
65
+ export interface ActivitySession {
66
+ id: string;
67
+ developer: string | null;
68
+ started_at: string;
69
+ last_active: string;
70
+ message_ids: string[];
71
+ /** Human-readable name for the session, set at `start_session` time. Shown on the Activity page. */
72
+ label?: string;
73
+ /**
74
+ * The workflow this session is currently working on, or absent/null when unbound.
75
+ *
76
+ * Deliberately LOCAL. A workflow is a shared record, but "which one am I on right now" is a
77
+ * property of the reader, not the thing being read — the previous design kept one global pointer
78
+ * that synced through git, so two sessions (or two teammates) silently took it from each other
79
+ * mid-work and logged their commits onto the wrong timeline.
80
+ */
81
+ workflow_id?: string | null;
82
+ }
83
+ /** Exported so other `.devmind/local/`-based stores (e.g. `feedback.ts`) share the same directory
84
+ * and gitignore convention instead of re-deriving it. */
85
+ export declare function localDir(devmindPath: string): string;
86
+ /**
87
+ * Collapse a `.gitignore` line to what git actually reads it as, so `local`, `local/`, `/local`
88
+ * and `/local/` all compare equal — they name the same directory. Exported because `devsmind
89
+ * init` tops the same file up from its own entry list, and the two must agree on "is this
90
+ * already ignored?": comparing raw strings meant a hand-written `local` went unrecognized and a
91
+ * second `local/` got appended underneath it on every run.
92
+ */
93
+ export declare function normalizeIgnoreEntry(line: string): string;
94
+ /** Exported for reuse by other `.devmind/local/` stores — see {@link localDir}. */
95
+ export declare function ensureGitignored(devmindPath: string): void;
96
+ export declare function readSessions(devmindPath: string): ActivitySession[];
97
+ /**
98
+ * The only way a session comes into being — called by the `start_session` tool. Idempotent: calling
99
+ * it again with an id that already exists (a client retrying a dropped response) just no-ops rather
100
+ * than clobbering `started_at` or the messages already linked to it.
101
+ */
102
+ export declare function createSession(devmindPath: string, sessionId: string, developer: string | null, label?: string): ActivitySession;
103
+ /**
104
+ * Binds this session to a workflow, or unbinds it when `workflowId` is null.
105
+ *
106
+ * Creates the session row if it does not exist yet, mirroring `createSession`'s upsert shape — an
107
+ * agent can legitimately bind before its first commit has created anything.
108
+ */
109
+ export declare function bindSessionWorkflow(devmindPath: string, sessionId: string, workflowId: string | null, developer?: string | null): ActivitySession;
110
+ /** The workflow this session is bound to right now, or null. */
111
+ export declare function readSessionWorkflow(devmindPath: string, sessionId: string): string | null;
112
+ /**
113
+ * The workflow most recently worked on from this machine — what a fresh session offers to continue.
114
+ *
115
+ * Derived, not stored: the newest session that carries a binding. A separate "last workflow"
116
+ * field would be a second copy of a fact already recorded here, and second copies drift — which is
117
+ * precisely the failure the global active pointer this replaces kept producing.
118
+ *
119
+ * `excludeSessionId` skips the session asking the question, so a session that already bound itself
120
+ * does not get offered its own binding back as a suggestion.
121
+ */
122
+ export declare function lastBoundWorkflowId(devmindPath: string, excludeSessionId?: string): string | null;
123
+ export declare function readMessage(devmindPath: string, messageId: string): ActivityMessage | null;
124
+ /** Every message, newest-created first — the read path for the Activity page and the CLI. */
125
+ export declare function listMessages(devmindPath: string): ActivityMessage[];
126
+ /** One message's changes, shaped for `get_activity_log` — the per-commit "what changed" view. */
127
+ export interface ActivityLogEntry {
128
+ id: string;
129
+ session_id: string;
130
+ developer: string | null;
131
+ created_at: string;
132
+ updated_at: string;
133
+ request: string | null;
134
+ summary: string;
135
+ status: MessageStatus;
136
+ /** Deduped, first-touched order — every file this message touched. This is the field the old
137
+ * `get_developer_activity`/`get_changes_by_requirement` never carried (only `get_recent_changes`
138
+ * did, and only without a developer filter) — the actual gap this tool closes. */
139
+ files: string[];
140
+ /** Deduped graph node ids this message touched. */
141
+ node_ids: string[];
142
+ edit_count: number;
143
+ }
144
+ export interface ActivityLogResult {
145
+ total_messages: number;
146
+ /** Every distinct file touched across ALL returned entries, flattened — "give me every file
147
+ * that changed" in one list, e.g. to scope a test-writing pass, without walking `entries`
148
+ * yourself. */
149
+ all_files: string[];
150
+ entries: ActivityLogEntry[];
151
+ }
152
+ /**
153
+ * Queries the local activity log — the one place `developer`, a time window, a specific session,
154
+ * AND the actual files touched all already live together (`ActivityMessage`/`MessageEdit`, see
155
+ * this file's module doc). This is what `get_activity_log` (MCP) wraps; it replaces three
156
+ * narrower, non-composable tools that each only covered one dimension: `get_recent_changes` had
157
+ * dates + files but no developer filter, `get_developer_activity` had a developer filter but no
158
+ * date range and no files, `get_changes_by_requirement` had neither dates nor files. All three
159
+ * filters compose here (AND'd together) since they're all just predicates over the same message
160
+ * list.
161
+ */
162
+ export declare function queryActivityLog(devmindPath: string, opts?: {
163
+ /** Case-insensitive substring match against `developer`. */
164
+ developer?: string;
165
+ sessionId?: string;
166
+ /** Lookback window in hours — convenience for "the last N hours/days". Ignored when `since`
167
+ * is also given. */
168
+ sinceHours?: number;
169
+ /** ISO timestamp lower bound (inclusive) — takes priority over `sinceHours` when both given. */
170
+ since?: string;
171
+ /** ISO timestamp upper bound (inclusive). */
172
+ until?: string;
173
+ /** Case-insensitive substring match against `request` OR `summary` — the requirement/ticket
174
+ * lookup `get_changes_by_requirement` used to do, now against the actual verbatim user
175
+ * request text rather than a reasoning-block LIKE search. */
176
+ requirementContains?: string;
177
+ limit?: number;
178
+ }): ActivityLogResult;
179
+ export interface RecordMessageParams {
180
+ session_id: string;
181
+ developer: string | null;
182
+ /** Explicit continuation target — set when the caller already knows which message this extends. */
183
+ message_id?: string;
184
+ /** The user's original request text, when the caller has it. */
185
+ request?: string | null;
186
+ summary: string;
187
+ edits: MessageEdit[];
188
+ }
189
+ /**
190
+ * Records a commit's edits against a message, creating or continuing one.
191
+ *
192
+ * Continuation, in priority order: an explicit `message_id`; else the session's newest message,
193
+ * when its `request` text matches this commit's (consecutive saves for the same ask collapse into
194
+ * one message); else a new message. A caller with no `request` at all always gets a new message
195
+ * per commit — there is nothing to match on, so grouping degrades to "one message per save" rather
196
+ * than guessing.
197
+ */
198
+ export declare function recordMessage(devmindPath: string, params: RecordMessageParams): ActivityMessage;
199
+ /** Persists a message after its status/edits were mutated in place (by the revert engine). */
200
+ export declare function saveMessage(devmindPath: string, message: ActivityMessage): void;
@@ -0,0 +1,347 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.deriveStatus = deriveStatus;
37
+ exports.localDir = localDir;
38
+ exports.normalizeIgnoreEntry = normalizeIgnoreEntry;
39
+ exports.ensureGitignored = ensureGitignored;
40
+ exports.readSessions = readSessions;
41
+ exports.createSession = createSession;
42
+ exports.bindSessionWorkflow = bindSessionWorkflow;
43
+ exports.readSessionWorkflow = readSessionWorkflow;
44
+ exports.lastBoundWorkflowId = lastBoundWorkflowId;
45
+ exports.readMessage = readMessage;
46
+ exports.listMessages = listMessages;
47
+ exports.queryActivityLog = queryActivityLog;
48
+ exports.recordMessage = recordMessage;
49
+ exports.saveMessage = saveMessage;
50
+ const crypto = __importStar(require("crypto"));
51
+ const fs = __importStar(require("fs"));
52
+ const path = __importStar(require("path"));
53
+ /** A message's status is derived from its edits, not tracked independently — this is the one
54
+ * place that mapping happens, so whole-message and granular (file/edit) revert paths can't drift
55
+ * out of sync with each other. */
56
+ function deriveStatus(edits) {
57
+ if (!edits.length)
58
+ return 'applied';
59
+ const revertedCount = edits.filter(e => e.reverted).length;
60
+ if (revertedCount === 0)
61
+ return 'applied';
62
+ if (revertedCount === edits.length)
63
+ return 'reverted';
64
+ return 'partial';
65
+ }
66
+ /** Exported so other `.devmind/local/`-based stores (e.g. `feedback.ts`) share the same directory
67
+ * and gitignore convention instead of re-deriving it. */
68
+ function localDir(devmindPath) {
69
+ return path.join(path.resolve(devmindPath), 'local');
70
+ }
71
+ function sessionsPath(devmindPath) {
72
+ return path.join(localDir(devmindPath), 'sessions.json');
73
+ }
74
+ function messagesDir(devmindPath) {
75
+ return path.join(localDir(devmindPath), 'messages');
76
+ }
77
+ function messagePath(devmindPath, messageId) {
78
+ return path.join(messagesDir(devmindPath), `${messageId}.json`);
79
+ }
80
+ /**
81
+ * Guards against `local/` landing in a commit on a brain that predates this feature: `devsmind
82
+ * init` writes the ignore line for anyone who re-runs it, but a brain that never does wouldn't
83
+ * otherwise pick it up. Checked (not assumed) on first write per process, since accidentally
84
+ * committing a developer's request history and revert backups is the one outcome worth a cheap
85
+ * file read to prevent.
86
+ */
87
+ let gitignoreChecked = false;
88
+ /**
89
+ * Collapse a `.gitignore` line to what git actually reads it as, so `local`, `local/`, `/local`
90
+ * and `/local/` all compare equal — they name the same directory. Exported because `devsmind
91
+ * init` tops the same file up from its own entry list, and the two must agree on "is this
92
+ * already ignored?": comparing raw strings meant a hand-written `local` went unrecognized and a
93
+ * second `local/` got appended underneath it on every run.
94
+ */
95
+ function normalizeIgnoreEntry(line) {
96
+ return line.trim().replace(/^\/+/, '').replace(/\/+$/, '');
97
+ }
98
+ /** Exported for reuse by other `.devmind/local/` stores — see {@link localDir}. */
99
+ function ensureGitignored(devmindPath) {
100
+ if (gitignoreChecked)
101
+ return;
102
+ gitignoreChecked = true;
103
+ try {
104
+ const gitignorePath = path.join(path.resolve(devmindPath), '.gitignore');
105
+ const current = fs.existsSync(gitignorePath) ? fs.readFileSync(gitignorePath, 'utf-8') : '';
106
+ if (current.split('\n').some(l => normalizeIgnoreEntry(l) === 'local'))
107
+ return;
108
+ const next = current.length && !current.endsWith('\n') ? current + '\n' : current;
109
+ fs.writeFileSync(gitignorePath, `${next}local/\n`, 'utf-8');
110
+ }
111
+ catch {
112
+ // Best-effort — a failed self-heal shouldn't block recording the activity log itself.
113
+ }
114
+ }
115
+ /** Same atomic write as staging.ts's writeBuffer: temp file + rename, never a half-written file. */
116
+ function writeJsonAtomic(devmindPath, target, data) {
117
+ ensureGitignored(devmindPath);
118
+ fs.mkdirSync(path.dirname(target), { recursive: true });
119
+ const tmp = `${target}.${process.pid}.tmp`;
120
+ fs.writeFileSync(tmp, JSON.stringify(data, null, 2), 'utf-8');
121
+ fs.renameSync(tmp, target);
122
+ }
123
+ function readJson(target, fallback) {
124
+ try {
125
+ return JSON.parse(fs.readFileSync(target, 'utf-8'));
126
+ }
127
+ catch {
128
+ return fallback;
129
+ }
130
+ }
131
+ function readSessions(devmindPath) {
132
+ return readJson(sessionsPath(devmindPath), { sessions: [] }).sessions;
133
+ }
134
+ function writeSessions(devmindPath, sessions) {
135
+ writeJsonAtomic(devmindPath, sessionsPath(devmindPath), { sessions });
136
+ }
137
+ /** Upserts a session's `last_active`, creating it (and linking the message) on first sight. */
138
+ function touchSession(devmindPath, sessionId, developer, messageId, nowStr) {
139
+ const sessions = readSessions(devmindPath);
140
+ const existing = sessions.find(s => s.id === sessionId);
141
+ if (existing) {
142
+ existing.last_active = nowStr;
143
+ if (!existing.message_ids.includes(messageId))
144
+ existing.message_ids.push(messageId);
145
+ }
146
+ else {
147
+ sessions.push({ id: sessionId, developer, started_at: nowStr, last_active: nowStr, message_ids: [messageId] });
148
+ }
149
+ writeSessions(devmindPath, sessions);
150
+ }
151
+ /**
152
+ * The only way a session comes into being — called by the `start_session` tool. Idempotent: calling
153
+ * it again with an id that already exists (a client retrying a dropped response) just no-ops rather
154
+ * than clobbering `started_at` or the messages already linked to it.
155
+ */
156
+ function createSession(devmindPath, sessionId, developer, label) {
157
+ const nowStr = new Date().toISOString();
158
+ const sessions = readSessions(devmindPath);
159
+ const existing = sessions.find(s => s.id === sessionId);
160
+ if (existing)
161
+ return existing;
162
+ const created = { id: sessionId, developer, started_at: nowStr, last_active: nowStr, message_ids: [], ...(label ? { label } : {}) };
163
+ sessions.push(created);
164
+ writeSessions(devmindPath, sessions);
165
+ return created;
166
+ }
167
+ /**
168
+ * Binds this session to a workflow, or unbinds it when `workflowId` is null.
169
+ *
170
+ * Creates the session row if it does not exist yet, mirroring `createSession`'s upsert shape — an
171
+ * agent can legitimately bind before its first commit has created anything.
172
+ */
173
+ function bindSessionWorkflow(devmindPath, sessionId, workflowId, developer = null) {
174
+ const nowStr = new Date().toISOString();
175
+ const sessions = readSessions(devmindPath);
176
+ let session = sessions.find(s => s.id === sessionId);
177
+ if (!session) {
178
+ session = { id: sessionId, developer, started_at: nowStr, last_active: nowStr, message_ids: [] };
179
+ sessions.push(session);
180
+ }
181
+ session.workflow_id = workflowId;
182
+ session.last_active = nowStr;
183
+ writeSessions(devmindPath, sessions);
184
+ return session;
185
+ }
186
+ /** The workflow this session is bound to right now, or null. */
187
+ function readSessionWorkflow(devmindPath, sessionId) {
188
+ const session = readSessions(devmindPath).find(s => s.id === sessionId);
189
+ return session?.workflow_id || null;
190
+ }
191
+ /**
192
+ * The workflow most recently worked on from this machine — what a fresh session offers to continue.
193
+ *
194
+ * Derived, not stored: the newest session that carries a binding. A separate "last workflow"
195
+ * field would be a second copy of a fact already recorded here, and second copies drift — which is
196
+ * precisely the failure the global active pointer this replaces kept producing.
197
+ *
198
+ * `excludeSessionId` skips the session asking the question, so a session that already bound itself
199
+ * does not get offered its own binding back as a suggestion.
200
+ */
201
+ function lastBoundWorkflowId(devmindPath, excludeSessionId) {
202
+ const candidates = readSessions(devmindPath)
203
+ .filter(s => s.workflow_id && s.id !== excludeSessionId)
204
+ .sort((a, b) => b.last_active.localeCompare(a.last_active));
205
+ return candidates.length ? candidates[0].workflow_id : null;
206
+ }
207
+ function readMessage(devmindPath, messageId) {
208
+ return readJson(messagePath(devmindPath, messageId), null);
209
+ }
210
+ function writeMessage(devmindPath, message) {
211
+ writeJsonAtomic(devmindPath, messagePath(devmindPath, message.id), message);
212
+ }
213
+ /** Every message, newest-created first — the read path for the Activity page and the CLI. */
214
+ function listMessages(devmindPath) {
215
+ const dir = messagesDir(devmindPath);
216
+ let files;
217
+ try {
218
+ files = fs.readdirSync(dir).filter(f => f.endsWith('.json'));
219
+ }
220
+ catch {
221
+ return [];
222
+ }
223
+ const messages = files
224
+ .map(f => readJson(path.join(dir, f), null))
225
+ .filter((m) => m !== null);
226
+ messages.sort((a, b) => b.created_at.localeCompare(a.created_at));
227
+ return messages;
228
+ }
229
+ /**
230
+ * Queries the local activity log — the one place `developer`, a time window, a specific session,
231
+ * AND the actual files touched all already live together (`ActivityMessage`/`MessageEdit`, see
232
+ * this file's module doc). This is what `get_activity_log` (MCP) wraps; it replaces three
233
+ * narrower, non-composable tools that each only covered one dimension: `get_recent_changes` had
234
+ * dates + files but no developer filter, `get_developer_activity` had a developer filter but no
235
+ * date range and no files, `get_changes_by_requirement` had neither dates nor files. All three
236
+ * filters compose here (AND'd together) since they're all just predicates over the same message
237
+ * list.
238
+ */
239
+ function queryActivityLog(devmindPath, opts = {}) {
240
+ let messages = listMessages(devmindPath);
241
+ if (opts.developer) {
242
+ const needle = opts.developer.toLowerCase();
243
+ messages = messages.filter(m => (m.developer ?? '').toLowerCase().includes(needle));
244
+ }
245
+ if (opts.sessionId) {
246
+ messages = messages.filter(m => m.session_id === opts.sessionId);
247
+ }
248
+ const sinceIso = opts.since ?? (opts.sinceHours !== undefined ? new Date(Date.now() - opts.sinceHours * 3600_000).toISOString() : undefined);
249
+ if (sinceIso) {
250
+ messages = messages.filter(m => m.created_at >= sinceIso);
251
+ }
252
+ if (opts.until) {
253
+ messages = messages.filter(m => m.created_at <= opts.until);
254
+ }
255
+ if (opts.requirementContains) {
256
+ const needle = opts.requirementContains.toLowerCase();
257
+ messages = messages.filter(m => (m.request ?? '').toLowerCase().includes(needle) || m.summary.toLowerCase().includes(needle));
258
+ }
259
+ const limited = messages.slice(0, opts.limit ?? 100);
260
+ const allFilesSet = new Set();
261
+ const entries = limited.map(m => {
262
+ const files = [];
263
+ const nodeIds = [];
264
+ const seenFiles = new Set();
265
+ const seenNodes = new Set();
266
+ for (const e of m.edits) {
267
+ if (!seenFiles.has(e.file_path)) {
268
+ seenFiles.add(e.file_path);
269
+ files.push(e.file_path);
270
+ allFilesSet.add(e.file_path);
271
+ }
272
+ if (e.node_id && !seenNodes.has(e.node_id)) {
273
+ seenNodes.add(e.node_id);
274
+ nodeIds.push(e.node_id);
275
+ }
276
+ }
277
+ return {
278
+ id: m.id, session_id: m.session_id, developer: m.developer, created_at: m.created_at, updated_at: m.updated_at,
279
+ request: m.request, summary: m.summary, status: m.status, files, node_ids: nodeIds, edit_count: m.edits.length
280
+ };
281
+ });
282
+ return { total_messages: entries.length, all_files: Array.from(allFilesSet), entries };
283
+ }
284
+ /**
285
+ * The newest message in a session that is still open to appending — i.e. not yet superseded by a
286
+ * later, different request. Used to decide whether a commit continues the current message
287
+ * (consecutive saves for one request) or starts a new one.
288
+ */
289
+ function newestMessageInSession(devmindPath, sessionId) {
290
+ const sessions = readSessions(devmindPath);
291
+ const session = sessions.find(s => s.id === sessionId);
292
+ if (!session || !session.message_ids.length)
293
+ return null;
294
+ return readMessage(devmindPath, session.message_ids[session.message_ids.length - 1]);
295
+ }
296
+ /**
297
+ * Records a commit's edits against a message, creating or continuing one.
298
+ *
299
+ * Continuation, in priority order: an explicit `message_id`; else the session's newest message,
300
+ * when its `request` text matches this commit's (consecutive saves for the same ask collapse into
301
+ * one message); else a new message. A caller with no `request` at all always gets a new message
302
+ * per commit — there is nothing to match on, so grouping degrades to "one message per save" rather
303
+ * than guessing.
304
+ */
305
+ function recordMessage(devmindPath, params) {
306
+ const nowStr = new Date().toISOString();
307
+ let target = null;
308
+ if (params.message_id) {
309
+ target = readMessage(devmindPath, params.message_id);
310
+ }
311
+ else if (params.request) {
312
+ const newest = newestMessageInSession(devmindPath, params.session_id);
313
+ if (newest && newest.status === 'applied' && newest.request === params.request)
314
+ target = newest;
315
+ }
316
+ // Guaranteed here (not just assumed of the caller) so a single-edit revert always has a real
317
+ // id to target, even if some future caller forgets to mint one.
318
+ const edits = params.edits.map(e => (e.id ? e : { ...e, id: crypto.randomUUID() }));
319
+ if (target) {
320
+ target.edits.push(...edits);
321
+ target.updated_at = nowStr;
322
+ if (params.summary)
323
+ target.summary = params.summary;
324
+ writeMessage(devmindPath, target);
325
+ touchSession(devmindPath, params.session_id, params.developer, target.id, nowStr);
326
+ return target;
327
+ }
328
+ const created = {
329
+ id: crypto.randomUUID(),
330
+ session_id: params.session_id,
331
+ developer: params.developer,
332
+ created_at: nowStr,
333
+ updated_at: nowStr,
334
+ request: params.request || null,
335
+ summary: params.summary,
336
+ status: 'applied',
337
+ edits
338
+ };
339
+ writeMessage(devmindPath, created);
340
+ touchSession(devmindPath, params.session_id, params.developer, created.id, nowStr);
341
+ return created;
342
+ }
343
+ /** Persists a message after its status/edits were mutated in place (by the revert engine). */
344
+ function saveMessage(devmindPath, message) {
345
+ writeMessage(devmindPath, message);
346
+ }
347
+ //# sourceMappingURL=activity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity.js","sourceRoot":"","sources":["../../src/db/activity.ts"],"names":[],"mappings":"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"}
@@ -92,18 +92,26 @@ function runAnalysis(db, workspaceRoot, opts = {}) {
92
92
  }
93
93
  }
94
94
  if (fix) {
95
- for (const n of [...orphaned_nodes, ...spurious_nodes, ...missing_files]) {
96
- db.deprecateNode(n.id);
97
- }
98
- for (const e of dangling_edges) {
99
- db.deleteDanglingEdge(e.source_node_id, e.target_node_id);
100
- }
95
+ // Migrate renames FIRST, before the missing-file deprecation pass below: a node whose file
96
+ // was just `git mv`-ed has a file_path that no longer exists on disk, so
97
+ // findSpuriousAndMissingFileNodes (computed above, pre-fix) already misclassified it as
98
+ // missing_files. Deprecating it before migrateRename runs would make it invisible to
99
+ // migrateRename's own db.listNodes() (which excludes deprecated nodes by design — see the
100
+ // comment on migrateRename), silently dropping the migration. Running the migration first
101
+ // means the node is gone from its old id by the time the stale orphaned/spurious/missing
102
+ // lists are replayed below; deprecateNode() on an id that no longer exists is a safe no-op.
101
103
  if (context) {
102
104
  for (const r of renamed_files) {
103
105
  const migrated = migrateRename(db, context, r.repo, r.from, r.to);
104
106
  r.migrated = migrated;
105
107
  }
106
108
  }
109
+ for (const n of [...orphaned_nodes, ...spurious_nodes, ...missing_files]) {
110
+ db.deprecateNode(n.id);
111
+ }
112
+ for (const e of dangling_edges) {
113
+ db.deleteDanglingEdge(e.source_node_id, e.target_node_id);
114
+ }
107
115
  db.setSystemMeta(LAST_ANALYSIS_KEY, new Date().toISOString());
108
116
  }
109
117
  const summary = {
@@ -137,6 +145,10 @@ function runAnalysis(db, workspaceRoot, opts = {}) {
137
145
  }
138
146
  /** Migrates every node whose file_path resolves to `from` onto `to`, cascading the id/connections/history via `renameNode`. Returns true if anything was migrated. */
139
147
  function migrateRename(db, context, repoName, from, to) {
148
+ /* istanbul ignore next -- migrateRename is module-private and only ever called from inside
149
+ runAnalysis's `if (context) { ... }` block, which already guarantees `context` is non-null
150
+ at every call site; this guard exists purely so the signature stays honest about the type
151
+ it accepts (ReturnType<getContext> can be null), not because it's reachable today. */
140
152
  if (!context)
141
153
  return false;
142
154
  const repoPath = (0, config_1.resolveRepoPath)(context, repoName);
@@ -1 +1 @@
1
- {"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/db/analyze.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/db/analyze.ts"],"names":[],"mappings":"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"}