devsmind-mcp 2.4.0 → 4.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 (135) hide show
  1. package/README.md +317 -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 +139 -9
  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 +55 -0
  26. package/dist/cli/integrations/memory-topics.js +318 -0
  27. package/dist/cli/integrations/memory-topics.js.map +1 -0
  28. package/dist/cli/integrations/memory.d.ts +17 -6
  29. package/dist/cli/integrations/memory.js +52 -139
  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 +26 -9
  35. package/dist/cli/integrations/registry.js +61 -30
  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 +110 -34
  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-graph.d.ts +55 -0
  56. package/dist/db/activity-graph.js +314 -0
  57. package/dist/db/activity-graph.js.map +1 -0
  58. package/dist/db/activity.d.ts +221 -0
  59. package/dist/db/activity.js +348 -0
  60. package/dist/db/activity.js.map +1 -0
  61. package/dist/db/analyze.js +18 -6
  62. package/dist/db/analyze.js.map +1 -1
  63. package/dist/db/database.d.ts +654 -102
  64. package/dist/db/database.js +1911 -558
  65. package/dist/db/database.js.map +1 -1
  66. package/dist/db/edges.d.ts +24 -0
  67. package/dist/db/edges.js +84 -0
  68. package/dist/db/edges.js.map +1 -1
  69. package/dist/db/embedder.d.ts +39 -0
  70. package/dist/db/embedder.js +0 -0
  71. package/dist/db/embedder.js.map +1 -0
  72. package/dist/db/feedback.d.ts +128 -0
  73. package/dist/db/feedback.js +182 -0
  74. package/dist/db/feedback.js.map +1 -0
  75. package/dist/db/file-diff.d.ts +32 -0
  76. package/dist/db/file-diff.js +110 -0
  77. package/dist/db/file-diff.js.map +1 -0
  78. package/dist/db/grep.d.ts +78 -0
  79. package/dist/db/grep.js +475 -0
  80. package/dist/db/grep.js.map +1 -0
  81. package/dist/db/index-build.d.ts +75 -0
  82. package/dist/db/index-build.js +177 -0
  83. package/dist/db/index-build.js.map +1 -0
  84. package/dist/db/message-revert.d.ts +63 -0
  85. package/dist/db/message-revert.js +258 -0
  86. package/dist/db/message-revert.js.map +1 -0
  87. package/dist/db/revert.d.ts +31 -0
  88. package/dist/db/revert.js +108 -0
  89. package/dist/db/revert.js.map +1 -0
  90. package/dist/db/schema.d.ts +49 -4
  91. package/dist/db/schema.js +125 -73
  92. package/dist/db/schema.js.map +1 -1
  93. package/dist/db/search-index.d.ts +65 -0
  94. package/dist/db/search-index.js +74 -0
  95. package/dist/db/search-index.js.map +1 -0
  96. package/dist/db/staging.d.ts +91 -5
  97. package/dist/db/staging.js +148 -22
  98. package/dist/db/staging.js.map +1 -1
  99. package/dist/mcp/server.d.ts +29 -7
  100. package/dist/mcp/server.js +2637 -878
  101. package/dist/mcp/server.js.map +1 -1
  102. package/dist/mcp/vendor/3d-force-graph.min.js +5 -0
  103. package/dist/mcp/vendor/force-graph.min.js +5 -0
  104. package/dist/mcp/vendor/model/model_int8.onnx +0 -0
  105. package/dist/mcp/vendor/model/vocab.txt +30522 -0
  106. package/dist/mcp/vendor/three.min.js +7 -0
  107. package/dist/mcp/view.css +419 -0
  108. package/dist/mcp/view.html +161 -0
  109. package/dist/mcp/view.js +245 -0
  110. package/dist/mcp/view_chat.js +382 -0
  111. package/dist/mcp/view_graph.js +576 -0
  112. package/dist/mcp/visualizer.d.ts +25 -2
  113. package/dist/mcp/visualizer.js +31 -4
  114. package/dist/mcp/visualizer.js.map +1 -1
  115. package/dist/utils/ast.d.ts +89 -0
  116. package/dist/utils/ast.js +378 -10
  117. package/dist/utils/ast.js.map +1 -1
  118. package/dist/utils/diff.d.ts +44 -0
  119. package/dist/utils/diff.js +78 -0
  120. package/dist/utils/diff.js.map +1 -0
  121. package/dist/utils/edit.d.ts +6 -0
  122. package/dist/utils/edit.js +47 -14
  123. package/dist/utils/edit.js.map +1 -1
  124. package/dist/utils/scanner.d.ts +6 -4
  125. package/dist/utils/scanner.js +18 -8
  126. package/dist/utils/scanner.js.map +1 -1
  127. package/dist/utils/tokenize.d.ts +45 -0
  128. package/dist/utils/tokenize.js +129 -0
  129. package/dist/utils/tokenize.js.map +1 -0
  130. package/dist/utils/version.d.ts +14 -0
  131. package/dist/utils/version.js +61 -0
  132. package/dist/utils/version.js.map +1 -0
  133. package/package.json +18 -5
  134. package/dist/mcp/visualizer_2d.html +0 -635
  135. package/dist/mcp/visualizer_3d.html +0 -613
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Local semantic embedding via a vendored `all-MiniLM-L6-v2` (int8 ONNX), loaded through the
3
+ * OPTIONAL `onnxruntime-node` dependency. Self-contained on purpose — no DB, no MCP — so it can
4
+ * be unit-tested against known WordPiece output and a semantic sanity check in isolation.
5
+ *
6
+ * `onnxruntime-node` is in `optionalDependencies`, not `dependencies`: an install can fail on an
7
+ * unsupported platform without breaking devsmind. Every entry point here degrades to returning
8
+ * null rather than throwing, so callers just fall back to BM25-only search.
9
+ */
10
+ export declare const EMBEDDING_MODEL_ID = "minilm-l6-v2-int8-v1";
11
+ export declare const EMBEDDING_DIM = 384;
12
+ export interface TokenizedInput {
13
+ inputIds: number[];
14
+ attentionMask: number[];
15
+ }
16
+ /** Tokenizes one string into [CLS] ... [SEP], padded/truncated to `maxTokens`. Exported for unit tests. */
17
+ export declare function tokenize(text: string, maxTokens?: number): TokenizedInput | null;
18
+ /** True if onnxruntime-node loaded, the model file exists, and the vocab parsed. Cheap after first call. */
19
+ export declare function isEmbedderAvailable(): Promise<boolean>;
20
+ /** L2-normalized components are in [-1,1], so a fixed scale of 127 needs no per-vector factor. */
21
+ export declare function quantizeInt8(vec: Float32Array): Int8Array;
22
+ /** Cosine similarity between two int8-quantized vectors, approximated via integer dot product. */
23
+ export declare function cosineInt8(a: Int8Array, b: Int8Array): number;
24
+ /**
25
+ * Embeds a batch of texts in one ONNX call. Returns null (not a rejected promise) if the
26
+ * embedder is unavailable for any reason — missing dependency, missing model, load failure —
27
+ * so every caller's fallback path is the same "treat as absent" branch, not exception handling.
28
+ */
29
+ export declare function embedBatch(texts: string[]): Promise<Float32Array[] | null>;
30
+ /**
31
+ * Fingerprint of the description a vector was computed from — a vector is stale the instant
32
+ * its description is edited, and this catches that precisely (unlike the BM25 index's coarse
33
+ * whole-corpus fingerprint). Not a security hash, just a fast staleness check.
34
+ */
35
+ export declare function hashDescription(text: string): string;
36
+ /** Convenience wrapper: embed one text, quantized, or null if the embedder is unavailable. */
37
+ export declare function embedTextInt8(text: string): Promise<Int8Array | null>;
38
+ /** Batched convenience wrapper mirroring `embedTextInt8`, for the generation paths in Phase 3. */
39
+ export declare function embedTextsInt8(texts: string[]): Promise<Int8Array[] | null>;
Binary file
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedder.js","sourceRoot":"","sources":["../../src/db/embedder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Compulsory-but-cheap feedback captured on every `commit_changes` call — the graph only earns
3
+ * trust if agents that discover it's wrong can say so, and the whole point is capturing that
4
+ * signal WITHOUT disrupting the working agent's flow: this module only appends, synchronously,
5
+ * to a local file. No extra round-trip, no live graph mutation, no agent ever blocked on this.
6
+ *
7
+ * Two files, two audiences, both under the gitignored `.devmind/local/` tree (same convention as
8
+ * activity.ts — private per-developer working state, never pushed):
9
+ * - `feedback_graph.jsonl` — machine-actionable. Read later by a supervised batch session
10
+ * (graph-fix tools) that verifies each entry against current code
11
+ * before writing anything to the graph. Never auto-applied live.
12
+ * - `feedback_product.jsonl` — human-actionable. Aggregated by a person into "how do we make
13
+ * DevsMind better", never read by an agent to mutate anything.
14
+ *
15
+ * `"none"` is a first-class, legitimate, expected answer on every field — a required field is
16
+ * required to be ANSWERED, not required to contain a problem. Making "none" cheap is what stops a
17
+ * compulsory field from pressuring an agent into inventing issues just to fill it in.
18
+ */
19
+ export type GraphFeedbackCategory = 'graph_problem' | 'edge_problem';
20
+ export type ProductFeedbackCategory = 'tools_used' | 'dropped_and_why' | 'devsmind_better';
21
+ /** How sure the reporting agent is. Only `confirmed` entries with evidence are strong candidates
22
+ * for the batch session to act on directly; `suspected` entries need the batch session to verify
23
+ * first (or are low priority until corroborated by a repeat report). */
24
+ export type FeedbackConfidence = 'suspected' | 'confirmed';
25
+ export interface FeedbackEvidence {
26
+ file: string;
27
+ line?: number;
28
+ snippet?: string;
29
+ }
30
+ export interface GraphFeedbackEntry {
31
+ /** Stable identity, minted at append time — what {@link markGraphFeedbackProcessed} targets. */
32
+ id: string;
33
+ ts: string;
34
+ session_id: string;
35
+ category: GraphFeedbackCategory;
36
+ text: string;
37
+ node_id?: string;
38
+ confidence: FeedbackConfidence;
39
+ evidence?: FeedbackEvidence;
40
+ /** Set by the batch graph-fix session once it has verified/applied this entry, so repeated
41
+ * batch runs don't re-chew the same report. Absent/false = not yet processed. */
42
+ processed?: boolean;
43
+ }
44
+ export interface ProductFeedbackEntry {
45
+ ts: string;
46
+ session_id: string;
47
+ category: ProductFeedbackCategory;
48
+ text: string;
49
+ }
50
+ /**
51
+ * A recurring pattern the batch graph-fix session noticed while resolving feedback — e.g. "every
52
+ * one of these 12 reports was the same framework's generated-binding pattern" — worth turning
53
+ * into a PERMANENT deterministic rule (a detector like Phase C's RTK one) instead of fixing the
54
+ * same class of miss by hand forever. This is a candidate log for a human to review, not something
55
+ * an agent acts on automatically — writing an actual detector is real engineering work.
56
+ */
57
+ export interface IndexerRuleCandidate {
58
+ ts: string;
59
+ /** Short description of the pattern, e.g. "Vue computed() properties never get aliased". */
60
+ pattern: string;
61
+ /** How many feedback entries this pattern was inferred from — the priority signal. */
62
+ evidence_count: number;
63
+ /** A few representative examples (file:line style strings), not every occurrence. */
64
+ examples: string[];
65
+ }
66
+ /**
67
+ * Appends one graph-correction report. Evidence is required to mark an entry `confirmed` — an
68
+ * unevidenced report is downgraded to `suspected` regardless of what the caller claimed, since a
69
+ * "graph problem" with no `file:line` to check is not reconstructable once the code has moved on
70
+ * (this may be read weeks later, in the batch session — see the module doc).
71
+ */
72
+ export declare function appendGraphFeedback(devmindPath: string, entry: {
73
+ session_id: string;
74
+ category: GraphFeedbackCategory;
75
+ text: string;
76
+ node_id?: string;
77
+ evidence?: FeedbackEvidence;
78
+ }): void;
79
+ /** Appends one product-improvement report — never read by an agent, only aggregated for a human. */
80
+ export declare function appendProductFeedback(devmindPath: string, entry: {
81
+ session_id: string;
82
+ category: ProductFeedbackCategory;
83
+ text: string;
84
+ }): void;
85
+ /**
86
+ * Reads graph-feedback entries — the batch graph-fix session's input. Unprocessed only by
87
+ * default (`opts.includeProcessed` to see everything, e.g. for an audit/report).
88
+ */
89
+ export declare function readGraphFeedback(devmindPath: string, opts?: {
90
+ includeProcessed?: boolean;
91
+ }): GraphFeedbackEntry[];
92
+ /** Reads every product-feedback entry recorded so far — for human aggregation/reporting. */
93
+ export declare function readProductFeedback(devmindPath: string): ProductFeedbackEntry[];
94
+ /**
95
+ * Marks graph-feedback entries as processed by id — rewrites the whole file (atomic temp+rename,
96
+ * same convention as `staging.ts`'s `writeBuffer`), since JSONL is append-only and a past line
97
+ * can't be edited in place. Idempotent: marking an already-processed or unknown id is a no-op for
98
+ * that id. Called by the batch graph-fix session once it has verified and applied (or explicitly
99
+ * rejected) an entry, so a later batch run never re-chews the same report.
100
+ */
101
+ export declare function markGraphFeedbackProcessed(devmindPath: string, ids: string[]): void;
102
+ /** One node/category's worth of graph feedback, grouped together — frequency is the priority
103
+ * signal: the same report surfacing many times means it's worth acting on first, and a single
104
+ * `record_alias`/`link_nodes` call can resolve every entry in the cluster at once. */
105
+ export interface GraphFeedbackCluster {
106
+ node_id: string;
107
+ category: GraphFeedbackCategory;
108
+ count: number;
109
+ entries: GraphFeedbackEntry[];
110
+ /** Highest confidence among the cluster's entries — one `confirmed` report is enough to make
111
+ * the whole cluster worth verifying first, even alongside otherwise-`suspected` duplicates. */
112
+ confidence: FeedbackConfidence;
113
+ }
114
+ /**
115
+ * Groups graph-feedback entries by `(node_id, category)` and sorts by frequency (most-reported
116
+ * first) — the clustering the batch session's `read_graph_feedback` tool exposes, so 30 identical
117
+ * reports of the same RTK miss show up as ONE cluster of size 30, not 30 things to individually
118
+ * re-investigate.
119
+ */
120
+ export declare function clusterGraphFeedback(entries: GraphFeedbackEntry[]): GraphFeedbackCluster[];
121
+ /** Appends one indexer-rule candidate — see {@link IndexerRuleCandidate}. */
122
+ export declare function appendIndexerRuleCandidate(devmindPath: string, entry: {
123
+ pattern: string;
124
+ evidence_count: number;
125
+ examples: string[];
126
+ }): void;
127
+ /** Reads every indexer-rule candidate recorded so far — for a human to review/prioritize. */
128
+ export declare function readIndexerRuleCandidates(devmindPath: string): IndexerRuleCandidate[];
@@ -0,0 +1,182 @@
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.appendGraphFeedback = appendGraphFeedback;
37
+ exports.appendProductFeedback = appendProductFeedback;
38
+ exports.readGraphFeedback = readGraphFeedback;
39
+ exports.readProductFeedback = readProductFeedback;
40
+ exports.markGraphFeedbackProcessed = markGraphFeedbackProcessed;
41
+ exports.clusterGraphFeedback = clusterGraphFeedback;
42
+ exports.appendIndexerRuleCandidate = appendIndexerRuleCandidate;
43
+ exports.readIndexerRuleCandidates = readIndexerRuleCandidates;
44
+ const fs = __importStar(require("fs"));
45
+ const path = __importStar(require("path"));
46
+ const crypto = __importStar(require("crypto"));
47
+ const activity_1 = require("./activity");
48
+ function graphFeedbackPath(devmindPath) {
49
+ return path.join((0, activity_1.localDir)(devmindPath), 'feedback_graph.jsonl');
50
+ }
51
+ function productFeedbackPath(devmindPath) {
52
+ return path.join((0, activity_1.localDir)(devmindPath), 'feedback_product.jsonl');
53
+ }
54
+ function indexerRuleCandidatesPath(devmindPath) {
55
+ return path.join((0, activity_1.localDir)(devmindPath), 'indexer_rule_candidates.jsonl');
56
+ }
57
+ function appendJsonl(devmindPath, target, entry) {
58
+ (0, activity_1.ensureGitignored)(devmindPath);
59
+ fs.mkdirSync(path.dirname(target), { recursive: true });
60
+ fs.appendFileSync(target, JSON.stringify(entry) + '\n', 'utf-8');
61
+ }
62
+ /**
63
+ * Appends one graph-correction report. Evidence is required to mark an entry `confirmed` — an
64
+ * unevidenced report is downgraded to `suspected` regardless of what the caller claimed, since a
65
+ * "graph problem" with no `file:line` to check is not reconstructable once the code has moved on
66
+ * (this may be read weeks later, in the batch session — see the module doc).
67
+ */
68
+ function appendGraphFeedback(devmindPath, entry) {
69
+ const confidence = entry.evidence ? 'confirmed' : 'suspected';
70
+ const record = {
71
+ id: crypto.randomUUID(),
72
+ ts: new Date().toISOString(),
73
+ session_id: entry.session_id,
74
+ category: entry.category,
75
+ text: entry.text,
76
+ node_id: entry.node_id,
77
+ confidence,
78
+ evidence: entry.evidence
79
+ };
80
+ appendJsonl(devmindPath, graphFeedbackPath(devmindPath), record);
81
+ }
82
+ /** Appends one product-improvement report — never read by an agent, only aggregated for a human. */
83
+ function appendProductFeedback(devmindPath, entry) {
84
+ const record = {
85
+ ts: new Date().toISOString(),
86
+ session_id: entry.session_id,
87
+ category: entry.category,
88
+ text: entry.text
89
+ };
90
+ appendJsonl(devmindPath, productFeedbackPath(devmindPath), record);
91
+ }
92
+ function readJsonl(target) {
93
+ if (!fs.existsSync(target))
94
+ return [];
95
+ const lines = fs.readFileSync(target, 'utf-8').split('\n').map(l => l.trim()).filter(Boolean);
96
+ const out = [];
97
+ for (const line of lines) {
98
+ try {
99
+ out.push(JSON.parse(line));
100
+ }
101
+ catch {
102
+ // A partially-written line (crash mid-append) — skip it rather than fail the whole read.
103
+ }
104
+ }
105
+ return out;
106
+ }
107
+ /**
108
+ * Reads graph-feedback entries — the batch graph-fix session's input. Unprocessed only by
109
+ * default (`opts.includeProcessed` to see everything, e.g. for an audit/report).
110
+ */
111
+ function readGraphFeedback(devmindPath, opts = {}) {
112
+ const all = readJsonl(graphFeedbackPath(devmindPath));
113
+ return opts.includeProcessed ? all : all.filter(e => !e.processed);
114
+ }
115
+ /** Reads every product-feedback entry recorded so far — for human aggregation/reporting. */
116
+ function readProductFeedback(devmindPath) {
117
+ return readJsonl(productFeedbackPath(devmindPath));
118
+ }
119
+ /**
120
+ * Marks graph-feedback entries as processed by id — rewrites the whole file (atomic temp+rename,
121
+ * same convention as `staging.ts`'s `writeBuffer`), since JSONL is append-only and a past line
122
+ * can't be edited in place. Idempotent: marking an already-processed or unknown id is a no-op for
123
+ * that id. Called by the batch graph-fix session once it has verified and applied (or explicitly
124
+ * rejected) an entry, so a later batch run never re-chews the same report.
125
+ */
126
+ function markGraphFeedbackProcessed(devmindPath, ids) {
127
+ if (ids.length === 0)
128
+ return;
129
+ const target = graphFeedbackPath(devmindPath);
130
+ const all = readJsonl(target);
131
+ const idSet = new Set(ids);
132
+ const updated = all.map(e => (idSet.has(e.id) ? { ...e, processed: true } : e));
133
+ (0, activity_1.ensureGitignored)(devmindPath);
134
+ fs.mkdirSync(path.dirname(target), { recursive: true });
135
+ const tmp = `${target}.${process.pid}.tmp`;
136
+ fs.writeFileSync(tmp, updated.map(e => JSON.stringify(e)).join('\n') + (updated.length ? '\n' : ''), 'utf-8');
137
+ fs.renameSync(tmp, target);
138
+ }
139
+ /**
140
+ * Groups graph-feedback entries by `(node_id, category)` and sorts by frequency (most-reported
141
+ * first) — the clustering the batch session's `read_graph_feedback` tool exposes, so 30 identical
142
+ * reports of the same RTK miss show up as ONE cluster of size 30, not 30 things to individually
143
+ * re-investigate.
144
+ */
145
+ function clusterGraphFeedback(entries) {
146
+ const groups = new Map();
147
+ for (const e of entries) {
148
+ const key = `${e.node_id ?? 'unknown'}::${e.category}`;
149
+ const arr = groups.get(key);
150
+ if (arr)
151
+ arr.push(e);
152
+ else
153
+ groups.set(key, [e]);
154
+ }
155
+ const clusters = [];
156
+ for (const [key, es] of groups) {
157
+ const sep = key.lastIndexOf('::');
158
+ clusters.push({
159
+ node_id: key.slice(0, sep),
160
+ category: key.slice(sep + 2),
161
+ count: es.length,
162
+ entries: es,
163
+ confidence: es.some(e => e.confidence === 'confirmed') ? 'confirmed' : 'suspected'
164
+ });
165
+ }
166
+ return clusters.sort((a, b) => b.count - a.count);
167
+ }
168
+ /** Appends one indexer-rule candidate — see {@link IndexerRuleCandidate}. */
169
+ function appendIndexerRuleCandidate(devmindPath, entry) {
170
+ const record = {
171
+ ts: new Date().toISOString(),
172
+ pattern: entry.pattern,
173
+ evidence_count: entry.evidence_count,
174
+ examples: entry.examples
175
+ };
176
+ appendJsonl(devmindPath, indexerRuleCandidatesPath(devmindPath), record);
177
+ }
178
+ /** Reads every indexer-rule candidate recorded so far — for a human to review/prioritize. */
179
+ function readIndexerRuleCandidates(devmindPath) {
180
+ return readJsonl(indexerRuleCandidatesPath(devmindPath));
181
+ }
182
+ //# sourceMappingURL=feedback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feedback.js","sourceRoot":"","sources":["../../src/db/feedback.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import { MessageEdit } from './activity';
2
+ import { DiffLine } from '../utils/diff';
3
+ export interface FileDiffResult {
4
+ file_path: string;
5
+ before_file: string;
6
+ after_file: string;
7
+ hunks: DiffLine[];
8
+ drifted: boolean;
9
+ drift_reason?: string;
10
+ }
11
+ /**
12
+ * Reconstructs the whole-file "before" state for one file's worth of edits from a single
13
+ * activity message, by undoing each edit's `after -> before` in memory, newest-first — the same
14
+ * ordering `revertOneMessageAtomically` (message-revert.ts) uses when it does this for real on
15
+ * disk. `fileEdits` must already be filtered to one file_path, in chronological (oldest-first)
16
+ * order, matching how they appear in `ActivityMessage.edits`.
17
+ *
18
+ * Drift (a hand-edit, a pull, a later message touching the same text) means some `after` snippet
19
+ * no longer matches the file uniquely — reported rather than guessed at, same as revert refuses
20
+ * rather than forcing a mismatched restore.
21
+ */
22
+ export declare function reconstructBeforeFile(liveContent: string, fileEdits: MessageEdit[]): {
23
+ before: string;
24
+ drifted: boolean;
25
+ };
26
+ /**
27
+ * Collapses every edit a message made to ONE file into a single git-style whole-file diff,
28
+ * reading the live file off disk as the "after" state. On drift, the reconstruction is not
29
+ * trustworthy — the caller should fall back to the per-node `diffSnapshots(before, after)` for
30
+ * this file instead of rendering a wrong whole-file diff.
31
+ */
32
+ export declare function fileDiffForMessage(filePath: string, fileEdits: MessageEdit[]): FileDiffResult;
@@ -0,0 +1,110 @@
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.reconstructBeforeFile = reconstructBeforeFile;
37
+ exports.fileDiffForMessage = fileDiffForMessage;
38
+ const fs = __importStar(require("fs"));
39
+ const diff_1 = require("../utils/diff");
40
+ /**
41
+ * Same single-occurrence exact-match semantics as replaceTextInFile (src/utils/edit.ts), but
42
+ * in-memory and read-only — no disk write, no atomic-rename. Returns null (rather than throwing)
43
+ * when `oldString` isn't found exactly once, so the caller can treat that as drift.
44
+ */
45
+ function replaceOnce(content, oldString, newString) {
46
+ if (oldString === newString)
47
+ return content; // a no-op edit (before === after) has nothing to undo
48
+ if (oldString === '')
49
+ return null; // no anchor to locate — can't undo an insertion blind
50
+ let count = 0;
51
+ for (let i = content.indexOf(oldString); i !== -1; i = content.indexOf(oldString, i + oldString.length)) {
52
+ count++;
53
+ if (count > 1)
54
+ break;
55
+ }
56
+ if (count !== 1)
57
+ return null;
58
+ const i = content.indexOf(oldString);
59
+ return content.slice(0, i) + newString + content.slice(i + oldString.length);
60
+ }
61
+ /**
62
+ * Reconstructs the whole-file "before" state for one file's worth of edits from a single
63
+ * activity message, by undoing each edit's `after -> before` in memory, newest-first — the same
64
+ * ordering `revertOneMessageAtomically` (message-revert.ts) uses when it does this for real on
65
+ * disk. `fileEdits` must already be filtered to one file_path, in chronological (oldest-first)
66
+ * order, matching how they appear in `ActivityMessage.edits`.
67
+ *
68
+ * Drift (a hand-edit, a pull, a later message touching the same text) means some `after` snippet
69
+ * no longer matches the file uniquely — reported rather than guessed at, same as revert refuses
70
+ * rather than forcing a mismatched restore.
71
+ */
72
+ function reconstructBeforeFile(liveContent, fileEdits) {
73
+ const newestFirst = fileEdits.slice().reverse();
74
+ let content = liveContent;
75
+ for (const edit of newestFirst) {
76
+ const undone = replaceOnce(content, edit.after, edit.before);
77
+ if (undone === null)
78
+ return { before: content, drifted: true };
79
+ content = undone;
80
+ }
81
+ return { before: content, drifted: false };
82
+ }
83
+ /**
84
+ * Collapses every edit a message made to ONE file into a single git-style whole-file diff,
85
+ * reading the live file off disk as the "after" state. On drift, the reconstruction is not
86
+ * trustworthy — the caller should fall back to the per-node `diffSnapshots(before, after)` for
87
+ * this file instead of rendering a wrong whole-file diff.
88
+ */
89
+ function fileDiffForMessage(filePath, fileEdits) {
90
+ let live;
91
+ try {
92
+ live = fs.readFileSync(filePath, 'utf-8');
93
+ }
94
+ catch {
95
+ return { file_path: filePath, before_file: '', after_file: '', hunks: [], drifted: true, drift_reason: 'file no longer exists on disk' };
96
+ }
97
+ const { before, drifted } = reconstructBeforeFile(live, fileEdits);
98
+ if (drifted) {
99
+ return {
100
+ file_path: filePath,
101
+ before_file: before,
102
+ after_file: live,
103
+ hunks: [],
104
+ drifted: true,
105
+ drift_reason: 'file has changed since this message was recorded — showing per-change diffs instead'
106
+ };
107
+ }
108
+ return { file_path: filePath, before_file: before, after_file: live, hunks: (0, diff_1.diffSnapshots)(before, live, 8), drifted: false };
109
+ }
110
+ //# sourceMappingURL=file-diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-diff.js","sourceRoot":"","sources":["../../src/db/file-diff.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,sDASC;AAQD,gDAqBC;AAhFD,uCAAyB;AAEzB,wCAAwD;AAWxD;;;;GAIG;AACH,SAAS,WAAW,CAAC,OAAe,EAAE,SAAiB,EAAE,SAAiB;IACxE,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC,CAAC,sDAAsD;IACnG,IAAI,SAAS,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC,CAAC,sDAAsD;IACzF,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,IAAI,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;QACxG,KAAK,EAAE,CAAC;QACR,IAAI,KAAK,GAAG,CAAC;YAAE,MAAM;IACvB,CAAC;IACD,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7B,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACrC,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;AAC/E,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,qBAAqB,CAAC,WAAmB,EAAE,SAAwB;IACjF,MAAM,WAAW,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,CAAC;IAChD,IAAI,OAAO,GAAG,WAAW,CAAC;IAC1B,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7D,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC/D,OAAO,GAAG,MAAM,CAAC;IACnB,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC7C,CAAC;AAED;;;;;GAKG;AACH,SAAgB,kBAAkB,CAAC,QAAgB,EAAE,SAAwB;IAC3E,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,+BAA+B,EAAE,CAAC;IAC3I,CAAC;IAED,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,qBAAqB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IACnE,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO;YACL,SAAS,EAAE,QAAQ;YACnB,WAAW,EAAE,MAAM;YACnB,UAAU,EAAE,IAAI;YAChB,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,IAAI;YACb,YAAY,EAAE,qFAAqF;SACpG,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,IAAA,oBAAa,EAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC/H,CAAC"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * True if a path is a lockfile or build artifact excluded from search by default. Exported so
3
+ * `searchNodes` can tell an agent that explicitly scoped `path` AT such a file WHY it got nothing
4
+ * back, rather than leaving it to read as "the pattern isn't in there".
5
+ */
6
+ export declare function isDefaultIgnoredFile(filePath: string): boolean;
7
+ export interface GrepHit {
8
+ file_path: string;
9
+ line_number: number;
10
+ line_content: string;
11
+ /** The actual substring the regex matched at this hit (lowercased) — used to attribute and
12
+ * rank matches without needing a fixed keyword list, since the pattern may be a single regex
13
+ * with no discrete "terms" of its own (e.g. `on\w+Tap`). */
14
+ matched_text: string;
15
+ }
16
+ export interface GrepResult {
17
+ hits: GrepHit[];
18
+ truncated: boolean;
19
+ files_scanned: number;
20
+ }
21
+ export interface RankedFile {
22
+ file_path: string;
23
+ total_matches: number;
24
+ /** Per-matched-text counts in this file — how the AI sees which part of the pattern actually landed. */
25
+ match_counts: Record<string, number>;
26
+ /** How many DISTINCT matched strings landed here — the strongest relevance signal. */
27
+ distinct_matches: number;
28
+ score: number;
29
+ /** A few representative matching lines (capped), for the AI to eyeball without opening the file.
30
+ * `symbol` — the containing function/class, when resolvable — is populated by the CALLER
31
+ * (`DevMindDatabase.annotateSampleLinesWithSymbol`), never by grep.ts itself: this module is
32
+ * deliberately dependency-free (no DB/AST access), see the file-level doc comment. */
33
+ sample_lines: {
34
+ line_number: number;
35
+ line_content: string;
36
+ symbol?: string;
37
+ }[];
38
+ }
39
+ /** `rankGrepHits`' result: a capped page of files plus the TRUE total, so the caller can tell
40
+ * "nothing more to find" from "more exists past this page" instead of guessing from a bare list. */
41
+ export interface RankGrepHitsResult {
42
+ files: RankedFile[];
43
+ /** Total distinct files that matched, before the `maxFiles`/`offset` page was cut. */
44
+ total: number;
45
+ }
46
+ /** Escapes a literal string so it matches as text, not as a regex pattern. Exported so callers
47
+ * building a regex out of LITERAL terms (e.g. `searchNodes` deriving one from query tokens when
48
+ * no explicit `pattern` was given) can reuse the exact same escaping grep.ts uses internally. */
49
+ export declare function escapeRegExp(s: string): string;
50
+ /**
51
+ * Greps every configured repo root (or, when `opts.scopePath` is given, just that one folder or
52
+ * file) for `pattern` — a real regex, used as-is. Returns raw hits plus whether the deadline
53
+ * forced an early, partial stop. Ranking is a separate pure step (`rankGrepHits`).
54
+ *
55
+ * Invalid regex throws `Invalid regex pattern: <message>` immediately (same shape as the
56
+ * precedent already established by `DevMindDatabase.searchCode`) rather than surfacing as an
57
+ * opaque failure deeper in the walk.
58
+ */
59
+ export declare function grepRepos(repoRoots: string[], pattern: string, opts?: {
60
+ ignoredPaths?: string[];
61
+ timeoutMs?: number;
62
+ caseInsensitive?: boolean;
63
+ scopePath?: string;
64
+ }): Promise<GrepResult>;
65
+ /**
66
+ * Ranks raw hits into a capped, ordered PAGE of files — the anti-firehose gate — plus the TRUE
67
+ * total file count before that cap, so a caller can tell "that's everything" from "more exists,
68
+ * ask for the next page" instead of guessing from a bare capped list. Unranked hits across 8
69
+ * repos can be hundreds; dumping them recreates the exact "15-20 low-confidence results I have to
70
+ * eyeball-filter" complaint that made the AI distrust the tool. So: group by file, score by match
71
+ * count weighted toward RARER matched strings (IDF-shaped, same instinct as BM25), reward files
72
+ * matching MULTIPLE distinct strings, sort with a stable tiebreaker, and page.
73
+ */
74
+ export declare function rankGrepHits(hits: GrepHit[], opts?: {
75
+ maxFiles?: number;
76
+ maxSampleLines?: number;
77
+ offset?: number;
78
+ }): RankGrepHitsResult;