@theronap/cortex-mcp 0.9.110 → 0.9.111

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 (2) hide show
  1. package/lib/server.mjs +12 -5
  2. package/package.json +1 -1
package/lib/server.mjs CHANGED
@@ -1181,7 +1181,10 @@ export async function runServer(version) {
1181
1181
  // drift again.
1182
1182
  const secs = (t.sections ?? []).map((s) => renderSection(s, day)).join('\n\n')
1183
1183
  const head = `[${t.tier}${day(t.updated_at) ? ` · authored ${day(t.updated_at)}` : ''}${t.validity && t.validity !== 'current' ? ` · ${t.validity}` : ''}]`
1184
- return [head, t.summary, secs].filter(Boolean).join('\n')
1184
+ // ADR-0030 step 3b (2026-08-24): the summary header is NO LONGER RENDERED. It duplicated the
1185
+ // `In short` section byte-for-byte on 6 of 6 pages sampled, so every read paid for the same
1186
+ // text twice. The column stays vestigial; this just stops serving it.
1187
+ return [head, secs].filter(Boolean).join('\n')
1185
1188
  })
1186
1189
  const brainTag = matches.length > 1 ? ` · brain: ${m.brain}` : ''
1187
1190
  return `# ${m.title ?? key} (authored page${brainTag})\n\n${blocks.join('\n\n---\n\n')}`
@@ -1336,7 +1339,11 @@ export async function runServer(version) {
1336
1339
  ? `\nversion: ${t.version}`
1337
1340
  : `\nversion: none (this variant predates content-hash tracking — base_version writes will always fail here; ask an admin about the ADR-0018 backfill)`
1338
1341
  const head = `[${t.tier}${day(t.updated_at) ? ` · authored ${day(t.updated_at)}` : ''}${t.validity && t.validity !== 'current' ? ` · ${t.validity}` : ''}${versionLine}]`
1339
- return [head, t.summary, secs].filter(Boolean).join('\n')
1342
+ // ADR-0030 step 3b (2026-08-24): the summary header is NO LONGER RENDERED here either.
1343
+ // ⚠ There were TWO of these — project_status and read_page — and the first patch fixed only
1344
+ // project_status, leaving the primary surface untouched. Same granularity miss this repo
1345
+ // keeps recording: a fix applied to the occurrence you happened to find first.
1346
+ return [head, secs].filter(Boolean).join('\n')
1340
1347
  })
1341
1348
  // REPAIR TOOL (2026-07-31). This footer used to say "re-author just those sections with
1342
1349
  // `author`" — which `author` cannot do: computeDroppedSections rejects a partial-section
@@ -1345,7 +1352,7 @@ export async function runServer(version) {
1345
1352
  // retype silently deleted a sentence, a [[link]] (a graph edge), a command list and the
1346
1353
  // word "today" from sections it was never meant to touch. This footer renders on EVERY
1347
1354
  // page read in the system, so it was the single widest surface pointing the wrong way.
1348
- let footer = `— Follow any [[links]] above with read_page to go deeper.\n— If you hold fresher FIRST-HAND truth than this page — something you established THIS session (ran the command, made the change, hold the artifact) that a section here gets concretely wrong — fix just that passage with \`edit_page\`: quote the wrong text as old_string and pass this page's \`version\` as base_version (any node you are permitted to edit; concise; a material contradiction, not merely extra detail). If the save comes back stale the page changed under you — the conflict hands back what changed, so re-anchor from that instead of re-reading. Reading a stale page you can fix IS the trigger to fix it. Editing is pre-authorized — do NOT ask the user before updating (edits are versioned + reversible via page_history/rollback_page); update, then briefly report it. If what went false is the SUMMARY at the top rather than a section, use \`set_summary\` — \`edit_page\` cannot reach it, and worse, it carries the old summary FORWARD into every revision it writes, so fixing a section silently re-certifies a summary that already contradicts it. Use \`author\` only to CREATE a page or rewrite one wholesale: it re-emits every section, so untouched sections get retyped on the way through and drift.\n— Citing code? Use a SYMBOL and file (\`formConnections\` in \`web/app/api/ingest/route.ts\`), never a line number — line numbers drift with every commit above them. And cite only what you opened THIS session; re-emitting a reference you read on another page is how a stale claim gains a second source and starts looking corroborated.`
1355
+ let footer = `— Follow any [[links]] above with read_page to go deeper.\n— If you hold fresher FIRST-HAND truth than this page — something you established THIS session (ran the command, made the change, hold the artifact) that a section here gets concretely wrong — fix just that passage with \`edit_page\`: quote the wrong text as old_string and pass this page's \`version\` as base_version (any node you are permitted to edit; concise; a material contradiction, not merely extra detail). If the save comes back stale the page changed under you — the conflict hands back what changed, so re-anchor from that instead of re-reading. Reading a stale page you can fix IS the trigger to fix it. Editing is pre-authorized — do NOT ask the user before updating (edits are versioned + reversible via page_history/rollback_page); update, then briefly report it. Use \`author\` only to CREATE a page or rewrite one wholesale: it re-emits every section, so untouched sections get retyped on the way through and drift.\n— Citing code? Use a SYMBOL and file (\`formConnections\` in \`web/app/api/ingest/route.ts\`), never a line number — line numbers drift with every commit above them. And cite only what you opened THIS session; re-emitting a reference you read on another page is how a stale claim gains a second source and starts looking corroborated.`
1349
1356
  // ADDRESSING (2026-08-04). The server accepts `ref` on every page/node route and its ambiguity
1350
1357
  // 409s hand refs back — but read_page never PRINTED one, so the only way to obtain a ref was to
1351
1358
  // trigger the error first. That made ID addressing reachable in principle and unusable in
@@ -1654,7 +1661,7 @@ export async function runServer(version) {
1654
1661
  'set_summary',
1655
1662
  {
1656
1663
  title: 'Rewrite a wiki page summary without touching its sections',
1657
- description: 'Replace a page\'s SUMMARY the one-sentence line at the top — in place, leaving every section untouched. Use this the moment you notice a summary that no longer matches the page: `edit_page` structurally CANNOT reach it (it edits section bodies; the summary is not one), and `author` reaches it only by retyping every section on the way through, which is how a 2026-07-30 write silently deleted a sentence and a [[link]] from a section nobody meant to touch. Correcting a body with `edit_page` actively carries the OLD summary forward into the new revision, so a stale summary does not decay quietly — each unrelated fix re-certifies it. Fixing it matters more than it looks: page retrieval FTS-matches on title + summary ALONE — the tsvector is built over title and summary, and section bodies are not in that index — so a stale summary decides whether the page is found by that path at all, and it is the first line every reader sees before a word of the body. Requires base_version (the `version` read_page prints) that is also how it finds the right brain, so it can never write to the wrong one. Recorded in page_history as a correction, and reversible with rollback_page.',
1664
+ description: 'DEPRECATED retired by ADR-0030 (decided 2026-08-24: no part of a page summarises the page). Do not call it. It still works so seats on older clients do not break, and it will be removed in a later release. This description previously claimed page retrieval matches on title + summary ALONE and that a stale summary decides whether a page is found that was true only of the digest branch deleted by ADR-0030 step 2, and on 2026-08-24 a session read it, believed it, and asserted the opposite of the truth to its operator. `grep` searches SECTION BODIES and always has. Put the content in a section.',
1658
1665
  inputSchema: {
1659
1666
  name: z.string().describe('the exact page name, as read_page shows it'),
1660
1667
  summary: z.string().describe('the new summary: one sentence saying what this is and where it stands. May contain [[links]]. Max 2,000 chars — detail belongs in a section.'),
@@ -3147,7 +3154,7 @@ export async function runServer(version) {
3147
3154
  inputSchema: {
3148
3155
  kind: z.enum(['project', 'person', 'org', 'user']).describe('the node type'),
3149
3156
  name: z.string().describe('the canonical node name — an EXACT existing name from the namespace to update it, or a new name to create the node (project/person/org). e.g. "Agnoclast" or "Theron Peterson"'),
3150
- summary: z.string().describe('one-sentence summary of what this is and its current state (may contain [[links]])'),
3157
+ summary: z.string().optional().describe('DEPRECATED and no longer required (ADR-0030, decided 2026-08-24: no part of a page summarises the page). Omit it. Accepted only so older callers keep working; the column is vestigial and nothing reads it. Put what the page is in its FIRST SECTION grep indexes section bodies, and never indexed this.'),
3151
3158
  sections: z.array(z.object({
3152
3159
  heading: z.string().describe('e.g. Overview, Current state, Decisions, Open threads, People'),
3153
3160
  body: z.string().describe('dense markdown WITH inline [[links]] where the prose references another node'),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theronap/cortex-mcp",
3
- "version": "0.9.110",
3
+ "version": "0.9.111",
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": {