@theronap/cortex-mcp 0.9.105 → 0.9.106
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/lib/folder_claims.mjs +48 -0
- package/lib/server.mjs +17 -0
- package/package.json +5 -5
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// The read_page footer line about FOLDER CLAIMS — pure, so CI can execute the decision.
|
|
2
|
+
//
|
|
3
|
+
// WHY THIS EXISTS. A page claiming a whole repo and a page claiming `web/lib/engine/` read
|
|
4
|
+
// identically, and the difference decides where every future commit lands and what tier it gets.
|
|
5
|
+
// Measured against prod 2026-08-22: 88 Agnoclast pages carry a `[[repo:…]]` stamp and 10 hold any
|
|
6
|
+
// path claim, so ~78 silently take delivery of the entire monorepo — `cortex` alone governs 66%.
|
|
7
|
+
//
|
|
8
|
+
// WHY THE FOOTER AND NOT A BACKLOG, A SCRIPT, OR A MINING PASS. It cannot be mined. Today's
|
|
9
|
+
// attachments come FROM the mother route, so mining them re-derives the mother (circular for
|
|
10
|
+
// `cortex` and `Theron Peterson`); and for every other page a commit spanning two packages makes all
|
|
11
|
+
// of its paths look like evidence for both (`cortex-mcp` mines to `web/app/api/` at 52 records — it
|
|
12
|
+
// is a package). Co-occurrence is not aboutness. Which folders a page is ABOUT is judgment, and the
|
|
13
|
+
// agent holding the page open is the one with the context to make it — the same argument, and the
|
|
14
|
+
// same evidence, as the per-node backlog nudge that ships beside it.
|
|
15
|
+
//
|
|
16
|
+
// SELF-EXTINGUISHING BY DESIGN. Once a claim exists the line stops asking and starts reviewing, so a
|
|
17
|
+
// page that has been narrowed does not keep nagging every reader forever. That is the difference
|
|
18
|
+
// between a nudge and wallpaper, and this repo has already recorded the day-one backlog saturating
|
|
19
|
+
// the D9 signal as the failure mode to avoid.
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* PURE. The footer line for a page's folder claims, or null when there is nothing worth saying.
|
|
23
|
+
*
|
|
24
|
+
* @param stamps repo stamps found in the page body, e.g. ['[[repo:theronap/cortex]]']
|
|
25
|
+
* @param pathRoutes `file:` claims the node holds, from the server
|
|
26
|
+
* @returns the line to append, or null
|
|
27
|
+
*/
|
|
28
|
+
export function folderClaimLine(stamps, pathRoutes) {
|
|
29
|
+
// ⚠ SILENCE WHEN THE SERVER DID NOT ANSWER, which is not the same as "no claims". A client newer
|
|
30
|
+
// than its server gets `undefined` here, and treating that as an empty array would tell every
|
|
31
|
+
// repo-stamped page to add folder claims — including the ones that already have them, whose claims
|
|
32
|
+
// this build simply cannot see. Say nothing rather than something confidently wrong; the line
|
|
33
|
+
// reappears on its own once the server is serving the field.
|
|
34
|
+
if (pathRoutes === undefined || pathRoutes === null) return null
|
|
35
|
+
|
|
36
|
+
const hasStamp = Array.isArray(stamps) && stamps.length > 0
|
|
37
|
+
const routes = Array.isArray(pathRoutes) ? pathRoutes.filter((r) => typeof r === 'string' && r) : []
|
|
38
|
+
|
|
39
|
+
// Nothing to say about a page that claims no repo and no folders — it is not in this population,
|
|
40
|
+
// and a line here would be noise on every unrelated page in the wiki.
|
|
41
|
+
if (!hasStamp && !routes.length) return null
|
|
42
|
+
|
|
43
|
+
if (routes.length) {
|
|
44
|
+
return `Folder claims on this page: ${routes.join(', ')}. If one of these is not actually what this page is about, correct it — a wrong claim quietly routes other people's commits here and sets their tier.`
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return `⚠ This page claims a WHOLE REPO and no folders within it, so every commit to that repo routes here. If you can tell which folders or files this page is actually about, claim them with \`set_routing_identifier\` (\`file:owner/repo:path/to/dir/\` — the trailing slash is what makes it a subtree). Claims are additive and reversible, and a narrower claim also decides the tier of records that land on it. Judge from what the page IS about, not from what happens to be attached to it.`
|
|
48
|
+
}
|
package/lib/server.mjs
CHANGED
|
@@ -6,6 +6,7 @@ import { homedir } from 'os'
|
|
|
6
6
|
import { join } from 'path'
|
|
7
7
|
import { createHash, randomUUID } from 'crypto'
|
|
8
8
|
import { fetchCortex, classify, resolveBase, resolveEnvToken, setSessionKey } from './diagnose.mjs'
|
|
9
|
+
import { folderClaimLine } from './folder_claims.mjs'
|
|
9
10
|
import { resolveSessionKey, resolveLogSessionId } from './session_key.mjs'
|
|
10
11
|
import { runSendImessage } from './imessage_send.mjs'
|
|
11
12
|
import { formatGrepHits } from './grep_cli.mjs'
|
|
@@ -1260,6 +1261,22 @@ export async function runServer(version) {
|
|
|
1260
1261
|
const allBody = m.tiers.flatMap((t) => (t.sections ?? []).map((s) => s.body)).join('\n')
|
|
1261
1262
|
const stamps = [...new Set((allBody.match(/\[\[repo:[a-z0-9][a-z0-9-]*\/[a-z0-9_.-]+\]\]/gi) ?? []).map((s) => s.toLowerCase()))]
|
|
1262
1263
|
if (stamps.length) footer += `\n— This page carries ${stamps.join(', ')} — \`read_page "${name}"\` with history: true for its event timeline (page = present, timeline = history).`
|
|
1264
|
+
// FOLDER CLAIMS (2026-08-22). A page claiming a whole repo and a page claiming
|
|
1265
|
+
// `web/lib/engine/` read identically, and the difference decides where every future commit
|
|
1266
|
+
// lands. Measured that day: 88 Agnoclast pages carry a repo stamp, 10 hold any path claim —
|
|
1267
|
+
// so ~78 silently take delivery of the entire monorepo, and `cortex` alone governs 66%.
|
|
1268
|
+
//
|
|
1269
|
+
// WHY THE FOOTER RATHER THAN A BACKLOG OR A SCRIPT. This cannot be mined: today's attachments
|
|
1270
|
+
// come FROM the mother route, so mining them re-derives the mother (circular), and for
|
|
1271
|
+
// everyone else a commit spanning two packages makes all its paths look like evidence for
|
|
1272
|
+
// both pages (`cortex-mcp` mines to `web/app/api/` at 52 records — it is a package). Which
|
|
1273
|
+
// folders a page is ABOUT is judgment, and the agent holding the page open is the one with
|
|
1274
|
+
// the context to make it. Same reasoning as the backlog nudge two lines down, and the same
|
|
1275
|
+
// evidence: a session read a page through a [[link]], saw the footer, and repaired the page.
|
|
1276
|
+
// The ask is deliberately self-extinguishing — once a claim exists the line changes to a
|
|
1277
|
+
// review prompt rather than a request, so a corrected page stops nagging.
|
|
1278
|
+
const claimLine = folderClaimLine(stamps, m.pathRoutes)
|
|
1279
|
+
if (claimLine) footer += `\n— ${claimLine}`
|
|
1263
1280
|
// Gate 4's per-node backlog nudge (also gate 3's KWA-36). The SERVER decides whether this
|
|
1264
1281
|
// fires — it sends `nudge` only when 25+ records are unclaimed AND the page has gone 7+ days
|
|
1265
1282
|
// unedited — so there is no threshold logic here to drift out of sync. It rides in the footer
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theronap/cortex-mcp",
|
|
3
|
-
"version": "0.9.
|
|
4
|
-
"description": "Connect your AI assistant to Cortex
|
|
3
|
+
"version": "0.9.106",
|
|
4
|
+
"description": "Connect your AI assistant to Cortex — your org's projects, activity, gaps, and directives, scoped to you.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"cortex-mcp": "bin/cortex-mcp.mjs"
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
],
|
|
30
30
|
"license": "MIT",
|
|
31
31
|
"scripts": {
|
|
32
|
-
"release": "
|
|
33
|
-
"promote": "
|
|
34
|
-
"rollback": "
|
|
32
|
+
"release": "bash scripts/release.sh",
|
|
33
|
+
"promote": "bash scripts/promote.sh",
|
|
34
|
+
"rollback": "bash scripts/rollback.sh"
|
|
35
35
|
}
|
|
36
36
|
}
|