@theronap/cortex-mcp 0.9.114 → 0.9.115

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.
@@ -2,6 +2,7 @@ import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, unlink
2
2
  import { homedir } from 'os'
3
3
  import { join } from 'path'
4
4
  import { fetchCortex, classify, resolveBase, resolveTokenSource } from './diagnose.mjs'
5
+ import { repoFullNameFrom } from './capture.mjs'
5
6
 
6
7
  // The private third copy of this lived here until 2026-08-19. doctor.mjs:14 warned that a third
7
8
  // copy is how a machine ends up connected to one command and 'no token found' to another; it also
@@ -47,9 +48,13 @@ export async function runSnapshotContext() {
47
48
  }
48
49
 
49
50
  const base = resolveBase(process.env.CORTEX_URL)
51
+ // The SessionStart snapshot is the surface that actually reaches a session's first turn, so the
52
+ // repo-scoped Gate 4 block is worth more here than anywhere else. Fail-closed: a non-GitHub cwd
53
+ // yields null and the hint is omitted (see repoFullNameFrom).
54
+ const repo = repoFullNameFrom(process.cwd())
50
55
  let res
51
56
  try {
52
- res = await fetchCortex(`${base}/api/mcp-context`, { headers: { Authorization: `Bearer ${token}` } })
57
+ res = await fetchCortex(`${base}/api/mcp-context${repo ? `?repo=${encodeURIComponent(repo)}` : ''}`, { headers: { Authorization: `Bearer ${token}` } })
53
58
  } catch (e) {
54
59
  out(`Agnoclast: context snapshot failed — ${e?.message ?? String(e)}`)
55
60
  return 0
package/lib/server.mjs CHANGED
@@ -12,6 +12,7 @@ import { runSendImessage } from './imessage_send.mjs'
12
12
  import { formatGrepHits } from './grep_cli.mjs'
13
13
  import { renderTriage } from './red_link_triage.mjs'
14
14
  import { runCodeGraphQuery } from './code_graph_cli.mjs'
15
+ import { repoFullNameFrom } from './capture.mjs'
15
16
 
16
17
  // Reactive red-link triage (Mechanism 2). On a read_page miss, ask the server whether the name is a
17
18
  // tracked wanted page, whether a bare node exists for it, and whether it's a deliberately demoted page,
@@ -126,19 +127,27 @@ export async function runServer(version) {
126
127
  if (typeof _hb.unref === 'function') _hb.unref() // don't keep the process alive just for the heartbeat
127
128
 
128
129
  // Cache context for 5 minutes so repeated tool calls don't re-fetch.
130
+ // KEYED BY REPO since 2026-08-27: the context now carries a repo-scoped Gate 4 block, so the same
131
+ // token can legitimately get different context from different cwds. One stdio server serves one cwd
132
+ // today and this is belt-and-braces — but an unkeyed cache would serve one repo's block to another
133
+ // silently, and "your repo has 12 records waiting" pointing at the wrong repo is worse than no line.
129
134
  let cache = null
130
135
  async function fetchContext() {
131
136
  const now = Date.now()
132
- if (cache && now - cache.ts < 5 * 60 * 1000) return cache.text
137
+ // Fail-closed by construction (see repoFullNameFrom): a non-GitHub or non-repo cwd yields null and
138
+ // the request simply omits the hint, degrading to the generic block.
139
+ const repo = repoFullNameFrom(process.cwd())
140
+ if (cache && cache.repo === repo && now - cache.ts < 5 * 60 * 1000) return cache.text
133
141
  // fetchCortex retries transient infra/5xx; classify turns a failure into an honest message
134
142
  // (token vs infra-block vs network) instead of a bare "Agnoclast API 403: unknown".
135
- const res = await fetchCortex(`${BASE}/api/mcp-context`, { headers: { Authorization: `Bearer ${TOKEN}` } })
143
+ const url = `${BASE}/api/mcp-context${repo ? `?repo=${encodeURIComponent(repo)}` : ''}`
144
+ const res = await fetchCortex(url, { headers: { Authorization: `Bearer ${TOKEN}` } })
136
145
  if (!res.ok) {
137
146
  const body = await res.text()
138
147
  throw new Error(classify(res.status, res.headers.get('content-type'), body, res.headers.get('x-vercel-id')).message)
139
148
  }
140
149
  const { context, brainRefs } = await res.json()
141
- cache = { text: context, ts: now }
150
+ cache = { text: context, ts: now, repo }
142
151
  // T11: stash the digest node refs surfaced this fetch so capture.mjs can forward them as
143
152
  // hydrated_from at the session's ingest (feedback-loop guard). Keyed by cwd so the matching
144
153
  // session picks them up. Best-effort + inert when brainRefs is empty (digest flag off).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theronap/cortex-mcp",
3
- "version": "0.9.114",
3
+ "version": "0.9.115",
4
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": {