@theronap/agnoclast-mcp 0.9.151 → 0.9.152
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/server.mjs +59 -4
- package/package.json +1 -1
package/lib/server.mjs
CHANGED
|
@@ -78,6 +78,33 @@ export const sectionCurrencyStamp = (s, day) => {
|
|
|
78
78
|
// invisible on exactly the sections that were healthy.
|
|
79
79
|
export const renderSection = (s, day) => `### ${s.heading}${sectionCurrencyStamp(s, day)}\n${s.body}`
|
|
80
80
|
|
|
81
|
+
/**
|
|
82
|
+
* ADR-0062 §5.1. A materialize PREVIEW goes to its own route: a server too old to know it answers 404,
|
|
83
|
+
* where /api/intake/materialize would ignore a `mode` it does not know and publish.
|
|
84
|
+
*/
|
|
85
|
+
export function intakeMaterializePath(mode) {
|
|
86
|
+
return mode === 'preview' ? '/api/intake/preview' : '/api/intake/materialize'
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** ADR-0062 §5.2. Which page governs a materialized record, and who chose it — or '' for an older server. */
|
|
90
|
+
export function renderGoverningLine(governing) {
|
|
91
|
+
if (!governing || typeof governing !== 'object') return ''
|
|
92
|
+
const name = governing.title || 'a page'
|
|
93
|
+
const who = governing.designatedBy === 'session' ? 'chosen by you'
|
|
94
|
+
: governing.designatedBy === 'human' ? 'chosen by a person'
|
|
95
|
+
: 'chosen by the ranking — pass governingPage to decide it yourself'
|
|
96
|
+
return `Governed by ${name} (${governing.tier}) — ${who}.`
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** The one line a preview leads with, so it cannot be mistaken for a publish. */
|
|
100
|
+
export function renderIntakePreviewLine(body) {
|
|
101
|
+
const p = (body && typeof body === 'object' && body.placement) || {}
|
|
102
|
+
const pages = Array.isArray(p.pages) ? p.pages.length : 0
|
|
103
|
+
const g = p.governing
|
|
104
|
+
const gov = g ? `${g.title || g.kind} (${g.tier})${p.governingJudged ? ', your choice' : ''}` : 'none'
|
|
105
|
+
return `PREVIEW — nothing was written. Would attach ${pages} page(s); governing: ${gov}; born ${p.tier ?? 'unknown'}.`
|
|
106
|
+
}
|
|
107
|
+
|
|
81
108
|
// TOP-OF-PAGE NOTES — ADR-0065's size note, and ADR-0064 §3's "Also visible to you" callout.
|
|
82
109
|
//
|
|
83
110
|
// ⚠ PRINTED VERBATIM, NEVER COMPOSED HERE. The server decides whether a note fires and what it says
|
|
@@ -88,6 +115,11 @@ export const renderSection = (s, day) => `### ${s.heading}${sectionCurrencyStamp
|
|
|
88
115
|
// it from offset 0, so the footer of a huge page is the part nobody reaches — and these notes exist for
|
|
89
116
|
// exactly those pages. Shared by read_page and project_status so the two cannot drift, which is how every
|
|
90
117
|
// earlier fix to this file's page rendering landed on one surface and not the other.
|
|
118
|
+
// v1 SCOPE (Theron, 2026-09-16): page splitting moves to v2 and the server refuses it with
|
|
119
|
+
// `splitting_unavailable`. split_page is not registered, so agents do not see a verb that can only refuse.
|
|
120
|
+
// The definition stays for v2: flip this together with the server's SPLITTING_AVAILABLE.
|
|
121
|
+
export const SPLIT_PAGE_TOOL_AVAILABLE = false
|
|
122
|
+
|
|
91
123
|
export const renderHeaderNotes = (notes) => {
|
|
92
124
|
const lines = (Array.isArray(notes) ? notes : [])
|
|
93
125
|
.filter((n) => typeof n === 'string' && n.trim() !== '')
|
|
@@ -877,7 +909,8 @@ function renderNudge(payload) {
|
|
|
877
909
|
{
|
|
878
910
|
title: 'Claim private intake items',
|
|
879
911
|
description:
|
|
880
|
-
'Claim a lease on private intake items (relevance or cleanup). Returns decrypted payloads for the lease holder only. Requires x-cortex-session-key (set automatically by this MCP server). Aged work never blocks a claim: the response reports cleanupDueCount and how far behind the oldest unit is, and servicing it is expected but always your call. Claiming is a commitment to process — hand back anything you will not finish with intake_release, or intake_defer if it is the owner\'s decision to make.'
|
|
912
|
+
'Claim a lease on private intake items (relevance or cleanup). Returns decrypted payloads for the lease holder only. Requires x-cortex-session-key (set automatically by this MCP server). Aged work never blocks a claim: the response reports cleanupDueCount and how far behind the oldest unit is, and servicing it is expected but always your call. Claiming is a commitment to process — hand back anything you will not finish with intake_release, or intake_defer if it is the owner\'s decision to make. ' +
|
|
913
|
+
'YOU ARE THE JUDGE of every unit you claim (ADR-0062): nothing is published until you materialize, and materializing is when it becomes visible. Each unit carries a `proposal` — the brain its signals point to and, for that brain, the pages it would attach to, the page that would govern it, and the `tier` it would be born with — computed without writing anything. Decide the brain, the pages (confirm, drop or add), which page should govern (the page whose reasons for restricting its audience fit the content, not a person page), and obligations. Pages only tighten a tier; if a record should be LOOSER than `tierReason.baseline`, that is the owner\'s call — intake_defer with the question.',
|
|
881
914
|
inputSchema: {
|
|
882
915
|
claimKind: z.enum(['relevance', 'cleanup']).optional().describe('default relevance'),
|
|
883
916
|
limit: z.number().optional().describe('max items (default 10). Ignored when intakeItemIds is given.'),
|
|
@@ -947,7 +980,9 @@ function renderNudge(payload) {
|
|
|
947
980
|
{
|
|
948
981
|
title: 'Materialize a private intake item',
|
|
949
982
|
description:
|
|
950
|
-
'Atomically publish a claimed intake item into one brain. Deterministic identifier homes in that brain are always attached; documentIds may add further pages.
|
|
983
|
+
'Atomically publish a claimed intake item into one brain — the disclosure moment (ADR-0062). Deterministic identifier homes in that brain are always attached; documentIds may add further pages. The record is born at the strictest of its source baseline, what the producer asked for, and every attached page; a source floor (iMessage, claude-code) pins it. ' +
|
|
984
|
+
'Name the governing page with governingPage (one of documentIds, never a person page) — otherwise the ranking picks it. ' +
|
|
985
|
+
'Pass mode "preview" first when your choice differs from the claim\'s proposal: it returns the pages, the governing page and the tier this exact call would produce, and writes nothing. Never writes private intake into search/history before this call.',
|
|
951
986
|
inputSchema: {
|
|
952
987
|
intakeItemId: z.string().describe('intake item uuid'),
|
|
953
988
|
orgId: z.string().describe('destination brain org uuid'),
|
|
@@ -958,10 +993,21 @@ function renderNudge(payload) {
|
|
|
958
993
|
recordType: z.string().optional(),
|
|
959
994
|
dedupeKey: z.string().optional(),
|
|
960
995
|
origin: z.enum(['deterministic', 'llm', 'user', 'session']).optional(),
|
|
996
|
+
governingPage: z.string().optional().describe(
|
|
997
|
+
'the page that should GOVERN this record (ADR-0062) — a page `ref:` or document id, and one of documentIds. ' +
|
|
998
|
+
'Choose the page whose reasons for restricting its audience fit the content; never a person page. It can only ' +
|
|
999
|
+
'tighten the record, and the ranking will not move it. Omit to leave the choice to the ranking.',
|
|
1000
|
+
),
|
|
1001
|
+
mode: z.enum(['preview', 'apply']).optional().describe(
|
|
1002
|
+
'"preview": report the pages, governing page and tier this call would produce, and write nothing. Default "apply".',
|
|
1003
|
+
),
|
|
961
1004
|
},
|
|
962
1005
|
},
|
|
963
1006
|
async (args) => {
|
|
964
|
-
|
|
1007
|
+
// A preview goes to its OWN route: a server too old to know it answers 404, where the materialize
|
|
1008
|
+
// route would ignore a `mode` it does not know and publish.
|
|
1009
|
+
const preview = args.mode === 'preview'
|
|
1010
|
+
const res = await fetchCortex(`${BASE}${intakeMaterializePath(args.mode)}`, {
|
|
965
1011
|
method: 'POST',
|
|
966
1012
|
headers: { Authorization: `Bearer ${TOKEN}`, 'Content-Type': 'application/json' },
|
|
967
1013
|
body: JSON.stringify({
|
|
@@ -976,13 +1022,20 @@ function renderNudge(payload) {
|
|
|
976
1022
|
dedupe_key: args.dedupeKey,
|
|
977
1023
|
},
|
|
978
1024
|
attachmentMeta: (args.documentIds ?? []).map(() => ({ origin: args.origin ?? 'llm' })),
|
|
1025
|
+
...(args.governingPage ? { governingDocumentId: args.governingPage } : {}),
|
|
979
1026
|
}),
|
|
980
1027
|
})
|
|
981
1028
|
if (!res.ok) {
|
|
982
1029
|
const body = await res.text()
|
|
1030
|
+
if (preview && res.status === 404) {
|
|
1031
|
+
return toolError('This server cannot preview a materialization yet — nothing was written. Materialize without mode, or wait for the server to update.')
|
|
1032
|
+
}
|
|
983
1033
|
return toolError(body)
|
|
984
1034
|
}
|
|
985
1035
|
const body = await res.json()
|
|
1036
|
+
if (preview) {
|
|
1037
|
+
return { content: [{ type: 'text', text: `${renderIntakePreviewLine(body)}\n\n${JSON.stringify(body, null, 2)}` }] }
|
|
1038
|
+
}
|
|
986
1039
|
// WHERE THE SESSION'S OWN WORK LANDED, in words rather than buried in the JSON dump.
|
|
987
1040
|
//
|
|
988
1041
|
// Three outcomes that look identical in raw JSON and mean completely different things:
|
|
@@ -999,6 +1052,8 @@ function renderNudge(payload) {
|
|
|
999
1052
|
// the ordinary case (observed 2026-09-03 on the first handoff record materialised). Silence is
|
|
1000
1053
|
// correct here, and it also covers a server too old to send the field at all.
|
|
1001
1054
|
const lines = []
|
|
1055
|
+
const governingLine = renderGoverningLine(body?.governing)
|
|
1056
|
+
if (governingLine) lines.push(governingLine)
|
|
1002
1057
|
const sa = body?.sessionAttachments
|
|
1003
1058
|
if (sa === null) {
|
|
1004
1059
|
lines.push('⚠ Session-page attachment FAILED for this record — it was written, but not filed under the pages this session worked on. Re-run the reconciler.')
|
|
@@ -1880,7 +1935,7 @@ function renderNudge(payload) {
|
|
|
1880
1935
|
},
|
|
1881
1936
|
)
|
|
1882
1937
|
|
|
1883
|
-
server.registerTool(
|
|
1938
|
+
if (SPLIT_PAGE_TOOL_AVAILABLE) server.registerTool(
|
|
1884
1939
|
'split_page',
|
|
1885
1940
|
{
|
|
1886
1941
|
title: 'Move sections onto a new child page',
|
package/package.json
CHANGED