@theronap/cortex-mcp 0.9.48 → 0.9.49

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.
@@ -0,0 +1,30 @@
1
+ // Red-link triage rendering (Mechanism 2) — the text an agent sees on a read_page miss.
2
+ //
3
+ // Standalone + dependency-free (like grep_cli.mjs) so it unit-tests without pulling the MCP SDK in.
4
+ // server.mjs owns the fetch; this owns the wording.
5
+ //
6
+ // The demoted arm is the one that matters. A superseded/historical page stays greppable
7
+ // (grep_brain_sections applies no validity filter) but read_page won't serve it (authored_page_tiers
8
+ // filters validity='current'), so an agent that greps a hit and then read_page's it lands here — and
9
+ // used to be told "no page yet, author it now". Authoring is pre-authorized, so the compliant next step
10
+ // was to overwrite a page a human deliberately retired, with nothing to catch it. Absence invites
11
+ // authoring; a demotion forbids it.
12
+ //
13
+ // Keyed off the ADDITIVE `t.demoted` flag, checked BEFORE category — never off a new category value. A
14
+ // server predating the flag omits it and every arm behaves exactly as before, so client and server can
15
+ // ship in either order.
16
+
17
+ // PURE: triage payload → miss text.
18
+ export function renderTriage(t, name) {
19
+ const refs = t.tracked
20
+ ? ` It's referenced by ${t.refCount} page${t.refCount === 1 ? '' : 's'}${t.isSteward ? ' and is routed to YOU as its most-likely steward' : ''}.`
21
+ : ''
22
+ const aliasHint = `if it's really an existing page under another title, \`grep "${name}"\` to find it, then \`alias_page name="${name}" target_name="<that page>"\``
23
+ if (t.demoted) {
24
+ return `\n\n[[${name}]] EXISTS but is marked ${t.validity ?? 'superseded'} — it was authored and then deliberately retired, so read_page (which serves only current pages) will not show it. It is NOT missing.${refs} Do NOT author over it: that would silently overwrite a decision someone made on purpose. Read it with \`page_history "${name}"\` then \`read_page "${name}"\` with a version. If it genuinely should be live again, revive it deliberately with \`set_page_validity\`.`
25
+ }
26
+ if (t.category === 'node') {
27
+ return `\n\n[[${name}]] is a wanted page — a ${t.isPerson ? 'person' : 'node'} exists but has no page yet.${refs} Either author it now with \`author\`, or ${aliasHint}.`
28
+ }
29
+ return `\n\n"${name}" isn't authored anywhere yet.${refs} Either author a new page with \`author\`, or ${aliasHint}.`
30
+ }
package/lib/server.mjs CHANGED
@@ -8,26 +8,20 @@ import { createHash, randomUUID } from 'crypto'
8
8
  import { fetchCortex, classify, resolveBase } from './diagnose.mjs'
9
9
  import { runSendImessage } from './imessage_send.mjs'
10
10
  import { formatGrepHits } from './grep_cli.mjs'
11
+ import { renderTriage } from './red_link_triage.mjs'
11
12
  import { runCodeGraphQuery } from './code_graph_cli.mjs'
12
13
 
13
14
  // Reactive red-link triage (Mechanism 2). On a read_page miss, ask the server whether the name is a
14
- // tracked wanted page and whether a bare node exists for it, and turn that into an actionable 3-way
15
- // prompt (author-for-node / author-new / alias). Returns '' on any error so a miss never gets worse.
15
+ // tracked wanted page, whether a bare node exists for it, and whether it's a deliberately demoted page,
16
+ // and turn that into an actionable prompt. Wording lives in ./red_link_triage.mjs (pure + tested).
17
+ // Returns '' on any error so a miss never gets worse.
16
18
  async function redLinkTriage(BASE, TOKEN, name) {
17
19
  try {
18
20
  const r = await fetchCortex(`${BASE}/api/brain/red-link?name=${encodeURIComponent(name)}`, {
19
21
  headers: { Authorization: `Bearer ${TOKEN}` },
20
22
  })
21
23
  if (!r.ok) return ''
22
- const t = await r.json()
23
- const refs = t.tracked
24
- ? ` It's referenced by ${t.refCount} page${t.refCount === 1 ? '' : 's'}${t.isSteward ? ' and is routed to YOU as its most-likely steward' : ''}.`
25
- : ''
26
- const aliasHint = `if it's really an existing page under another title, \`grep "${name}"\` to find it, then \`alias_page name="${name}" target_name="<that page>"\``
27
- if (t.category === 'node') {
28
- return `\n\n[[${name}]] is a wanted page — a ${t.isPerson ? 'person' : 'node'} exists but has no page yet.${refs} Either author it now with \`author\`, or ${aliasHint}.`
29
- }
30
- return `\n\n"${name}" isn't authored anywhere yet.${refs} Either author a new page with \`author\`, or ${aliasHint}.`
24
+ return renderTriage(await r.json(), name)
31
25
  } catch {
32
26
  return ''
33
27
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theronap/cortex-mcp",
3
- "version": "0.9.48",
3
+ "version": "0.9.49",
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": {