@compr/opscontext-mcp 2.6.0 → 2.6.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/CHANGELOG.md +15 -0
- package/dist/cli.js +1 -1
- package/dist/index.js +8 -2
- package/dist/learnings.js +10 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,21 @@ All notable changes to OpsContext for AI Agents (previously ContextEngine — MC
|
|
|
4
4
|
|
|
5
5
|
> Entries for 2.2.0 through 2.4.0 were not backfilled here; see `docs/sessions/SESSION_19` through `SESSION_21` for those releases.
|
|
6
6
|
|
|
7
|
+
## [2.6.1] 2026-09-06: readers never embed; a store record without tags no longer breaks search
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **`search_context` and `score_project` answered "Cannot read properties of undefined (reading
|
|
12
|
+
'join')"** on every server, 2.5.9 included, while `save_learning` worked. `searchLearnings`
|
|
13
|
+
dereferenced `tags.join` on 20 agent-saved store records that have no `tags` array, inside the
|
|
14
|
+
firewall's learning injection, which runs for every tool that passes a context hint. Optional
|
|
15
|
+
fields are now read with fallbacks (`[LEARNING-FIELDS-ARE-OPTIONAL-ON-READ]`); the records are
|
|
16
|
+
not rewritten.
|
|
17
|
+
- **A reader that starts before its indexer has published** (every reader when all windows
|
|
18
|
+
restart at once) used to build locally and embed the whole corpus itself. It now builds
|
|
19
|
+
keyword-only, embeds nothing, and adopts the shared index the moment it appears. The trial
|
|
20
|
+
script starts all three servers together and asserts zero embed runs on the readers.
|
|
21
|
+
|
|
7
22
|
## [2.6.0] 2026-09-05: One indexer, many readers
|
|
8
23
|
|
|
9
24
|
Every Claude Code chat spawns its own MCP server, plus launchd, plus VS Code. Measured on
|
package/dist/cli.js
CHANGED
|
@@ -831,7 +831,7 @@ async function cliSaveLearning(args) {
|
|
|
831
831
|
console.log(` Project: ${learning.project}`);
|
|
832
832
|
if (learning.context)
|
|
833
833
|
console.log(` Context: ${learning.context}`);
|
|
834
|
-
console.log(` Tags: ${learning.tags.join(", ")}`);
|
|
834
|
+
console.log(` Tags: ${(learning.tags ?? []).join(", ")}`); // [LOCK] [LEARNING-FIELDS-ARE-OPTIONAL-ON-READ]
|
|
835
835
|
}
|
|
836
836
|
async function cliDeleteLearning(id) {
|
|
837
837
|
if (!id) {
|
package/dist/index.js
CHANGED
|
@@ -1083,7 +1083,7 @@ server.tool("save_learning", "Save a permanent operational rule learned during a
|
|
|
1083
1083
|
`- **ID:** \`${learning.id}\``,
|
|
1084
1084
|
`- **Category:** ${category}`,
|
|
1085
1085
|
project ? `- **Project:** ${project}` : "",
|
|
1086
|
-
`- **Tags:** ${learning.tags.join(", ")}`,
|
|
1086
|
+
`- **Tags:** ${(learning.tags ?? []).join(", ")}`, // [LOCK] [LEARNING-FIELDS-ARE-OPTIONAL-ON-READ]
|
|
1087
1087
|
``,
|
|
1088
1088
|
`📊 Store: ${stats.total} learnings across ${Object.keys(stats.categories).length} categories`,
|
|
1089
1089
|
``,
|
|
@@ -1378,7 +1378,7 @@ async function main() {
|
|
|
1378
1378
|
// always loads for whoever embeds or answers queries. [LOCK] [EMBEDDINGS-ARE-CONTENT-ADDRESSED]
|
|
1379
1379
|
// A reader that adopted the index already has its vectors and loads the model on its first
|
|
1380
1380
|
// semantic query, not before: 300 MB per process is worth waiting for.
|
|
1381
|
-
if (!adopted) {
|
|
1381
|
+
if (!adopted && role === "indexer") {
|
|
1382
1382
|
vectorStore = loadEmbeddingStore().vectors;
|
|
1383
1383
|
if (vectorStore.size > 0)
|
|
1384
1384
|
console.error(`[ContextEngine] 💾 Embedding store: ${vectorStore.size} vectors`);
|
|
@@ -1390,6 +1390,12 @@ async function main() {
|
|
|
1390
1390
|
publishIndex();
|
|
1391
1391
|
});
|
|
1392
1392
|
}
|
|
1393
|
+
else if (!adopted) {
|
|
1394
|
+
// A reader that started before its indexer published (every window restarted at once):
|
|
1395
|
+
// keyword search from its own build, no embedding of its own, the index adopted the moment
|
|
1396
|
+
// it appears. Only indexers embed; that is the whole point. [LOCK] [ONE-INDEXER-MANY-READERS]
|
|
1397
|
+
console.error(`[ContextEngine] ⏳ Reader without an index: keyword search only until pid ${indexerPid ?? "?"} publishes`);
|
|
1398
|
+
}
|
|
1393
1399
|
// 5. Watch (indexer) or poll (reader), and keep the election running
|
|
1394
1400
|
if (role === "indexer")
|
|
1395
1401
|
startWatching();
|
package/dist/learnings.js
CHANGED
|
@@ -448,7 +448,16 @@ export function searchLearnings(query) {
|
|
|
448
448
|
return store.learnings;
|
|
449
449
|
const scored = [];
|
|
450
450
|
for (const learning of store.learnings) {
|
|
451
|
-
|
|
451
|
+
// [LOCKED] [LEARNING-FIELDS-ARE-OPTIONAL-ON-READ] 2026-09-06
|
|
452
|
+
// [NEVER] dereference an optional field of a store record (tags, context, project) without a
|
|
453
|
+
// fallback on a read path, and [NEVER] "fix" such a record by rewriting the store.
|
|
454
|
+
// WHY: 20 agent-saved records (s57_*, s78_*, kept on purpose in the SESSION_25 prune) have no
|
|
455
|
+
// `tags` array. `learning.tags.join` threw here, inside the firewall's learning injection,
|
|
456
|
+
// so every tool that passes a context hint (search_context, score_project, ...) answered
|
|
457
|
+
// "Cannot read properties of undefined (reading 'join')" on every server, on 2.5.9 as on
|
|
458
|
+
// 2.6.0, while save_learning (exempt from the firewall) worked. Another chat noticed.
|
|
459
|
+
// FIX: read with fallbacks; the records stay as they are (the store is data, not ours to edit).
|
|
460
|
+
const text = `${learning.category} ${learning.rule} ${learning.context ?? ""} ${learning.project || ""} ${(learning.tags ?? []).join(" ")}`.toLowerCase();
|
|
452
461
|
let score = 0;
|
|
453
462
|
for (const token of tokens) {
|
|
454
463
|
if (text.includes(token)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@compr/opscontext-mcp",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.1",
|
|
4
4
|
"description": "OpsContext for AI Agents — read-only fleet visibility (PM2/nginx/Docker/git/cron) + tamper-evident audit log + policy-as-code hooks. The ops + compliance layer Claude Code can't grow natively.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|