@theronap/cortex-mcp 0.9.149 → 0.9.150
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/capture.mjs +235 -135
- package/lib/capture_queue.mjs +876 -0
- package/lib/diagnose.mjs +176 -32
- package/lib/doctor.mjs +32 -4
- package/lib/edge_extract.mjs +41 -24
- package/lib/hydrate.mjs +40 -13
- package/lib/propose_obligation.mjs +99 -0
- package/lib/redact.mjs +2 -1
- package/lib/server.mjs +54 -4
- package/package.json +1 -1
package/lib/redact.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// redact.mjs — strip high-confidence credential patterns from text BEFORE it leaves
|
|
2
|
-
// the machine
|
|
2
|
+
// the machine or is stored (hydrate sends the prompt; capture feeds the transcript tail to
|
|
3
|
+
// the local summarizer and the local queue — since D8 it never POSTs the tail). A leaked secret in a
|
|
3
4
|
// transcript — a user pastes an API key, a tool reads a config file holding one, or
|
|
4
5
|
// (the 2026-06-22 finding) a login token sits inlined in a hook command — must never
|
|
5
6
|
// be transmitted or stored. Conservative by design: targets known secret SHAPES so it
|
package/lib/server.mjs
CHANGED
|
@@ -10,6 +10,7 @@ import { folderClaimLine } from './folder_claims.mjs'
|
|
|
10
10
|
import { resolveSessionKey, resolveLogSessionId } from './session_key.mjs'
|
|
11
11
|
import { runSendImessage } from './imessage_send.mjs'
|
|
12
12
|
import { formatGrepHits } from './grep_cli.mjs'
|
|
13
|
+
import { buildProposal, renderProposal, withAskNotice } from './propose_obligation.mjs'
|
|
13
14
|
import { renderCaptureStatus } from './capture_status.mjs'
|
|
14
15
|
import { renderTriage } from './red_link_triage.mjs'
|
|
15
16
|
import { runCodeGraphQuery } from './code_graph_cli.mjs'
|
|
@@ -823,7 +824,7 @@ function renderNudge(payload) {
|
|
|
823
824
|
sections.push(`Unclaimed records (${records.length}) from other sources — newest first:\n${lines.join('\n')}`)
|
|
824
825
|
}
|
|
825
826
|
|
|
826
|
-
return { content: [{ type: 'text', text: sections.join('\n\n') }] }
|
|
827
|
+
return { content: [{ type: 'text', text: withAskNotice(sections.join('\n\n')) }] }
|
|
827
828
|
},
|
|
828
829
|
)
|
|
829
830
|
|
|
@@ -1169,7 +1170,7 @@ function renderNudge(payload) {
|
|
|
1169
1170
|
if (out?.error === 'not_found') return toolError('No such intake unit in your account.')
|
|
1170
1171
|
return toolError(`Could not look: ${out?.error ?? res.status}${out?.detail ? ` — ${out.detail}` : ''}`)
|
|
1171
1172
|
}
|
|
1172
|
-
return { content: [{ type: 'text', text: JSON.stringify(out, null, 2) }] }
|
|
1173
|
+
return { content: [{ type: 'text', text: withAskNotice(JSON.stringify(out, null, 2)) }] }
|
|
1173
1174
|
},
|
|
1174
1175
|
)
|
|
1175
1176
|
|
|
@@ -2036,8 +2037,14 @@ function renderNudge(payload) {
|
|
|
2036
2037
|
}
|
|
2037
2038
|
lines.push('', 'Claim with set_routing_identifier on the page whose subject HAS that identifier.')
|
|
2038
2039
|
}
|
|
2040
|
+
// THREE OUTCOMES, ALL LEGITIMATE (ADR-0038 amendment, Theron 2026-09-11: "we need to make it an
|
|
2041
|
+
// option for the agent to discard emails entirely or to create pages"). Naming only placement left an
|
|
2042
|
+
// agent with no honest move for junk mail or for a subject that has no page yet — so it either
|
|
2043
|
+
// mis-filed onto the nearest page or left the queue to grow. 6 of 19 arrivals sat exactly there.
|
|
2039
2044
|
lines.push('', 'Place one with place_staged_record (staged_id + pages). The pages decide the brain, which decides who can read it.')
|
|
2040
|
-
|
|
2045
|
+
lines.push('No page fits? `author` the page it needs, then place onto it. Junk? `discard_staged` (reversible, dry-run by default).')
|
|
2046
|
+
lines.push('A default brain is NOT the answer for content — one standing rule cannot decide disclosure for mail nobody has read.')
|
|
2047
|
+
return { content: [{ type: 'text', text: withAskNotice(lines.join('\n')) }] }
|
|
2041
2048
|
},
|
|
2042
2049
|
)
|
|
2043
2050
|
|
|
@@ -2202,6 +2209,49 @@ function renderNudge(payload) {
|
|
|
2202
2209
|
},
|
|
2203
2210
|
)
|
|
2204
2211
|
|
|
2212
|
+
server.registerTool(
|
|
2213
|
+
'propose_obligation',
|
|
2214
|
+
{
|
|
2215
|
+
title: 'Propose something a record asks of this person',
|
|
2216
|
+
description:
|
|
2217
|
+
'Propose an obligation you found while READING — with the sentence that asks for it. This is the verb for ' +
|
|
2218
|
+
'"this email asks Theron for a call on Friday": it lands as a PROPOSAL the person confirms or dismisses, never ' +
|
|
2219
|
+
'as a commitment they made. Use it whenever something you read asks this person for something and no obligation ' +
|
|
2220
|
+
'covers it yet. ⚠ NOT the same tool as `track_obligation`, which records what the PERSON says they owe and ' +
|
|
2221
|
+
'carries no evidence — proposing through that verb makes a machine guess indistinguishable from their own word. ' +
|
|
2222
|
+
'⚠ `evidence` must be the VERBATIM sentence from that record, not your paraphrase: it is the whole reviewable ' +
|
|
2223
|
+
'unit, and the person decides on the strength of it. ⚠ NEVER INVENT A DATE. Copy the words that say when into ' +
|
|
2224
|
+
'`due_phrase` ("by Tuesday the 22nd", "this week") and the server works the date out against the record\'s own ' +
|
|
2225
|
+
'date; pass `due_at` only when you are reading a date the record states. No date is a proposal with no date, ' +
|
|
2226
|
+
'which is honest and still shows up.',
|
|
2227
|
+
inputSchema: {
|
|
2228
|
+
record: z.string().describe('the record the ask came from — an id from my_day, timeline_pull, list_records or find_sessions'),
|
|
2229
|
+
subject: z.string().describe('what must be done, one short phrase'),
|
|
2230
|
+
evidence: z.string().describe('the VERBATIM sentence from that record that asks for it'),
|
|
2231
|
+
due_phrase: z.string().optional().describe('the words that say WHEN, copied from the evidence sentence — the server resolves them'),
|
|
2232
|
+
due_at: z.string().optional().describe('YYYY-MM-DD, or YYYY-MM-DDTHH:MM when a time is stated. Only a date the record states.'),
|
|
2233
|
+
obligated_party: z.enum(['self', 'other', 'none']).optional().describe('self (default) = this person owes it; other = someone else; none = nobody'),
|
|
2234
|
+
},
|
|
2235
|
+
},
|
|
2236
|
+
async ({ record, subject, evidence, due_phrase, due_at, obligated_party }) => {
|
|
2237
|
+
const built = buildProposal({ subject, evidence, due_phrase, due_at, obligated_party })
|
|
2238
|
+
if (built.error) return toolError(`Not proposed: ${built.error}`)
|
|
2239
|
+
let res
|
|
2240
|
+
try {
|
|
2241
|
+
res = await fetchCortex(`${BASE}/api/obligations/candidates`, {
|
|
2242
|
+
method: 'POST',
|
|
2243
|
+
headers: { Authorization: `Bearer ${TOKEN}`, 'Content-Type': 'application/json' },
|
|
2244
|
+
body: JSON.stringify({ recordId: record, obligations: [built.candidate] }),
|
|
2245
|
+
})
|
|
2246
|
+
} catch (e) { return toolError(`Could not reach obligations: ${e.message}`) }
|
|
2247
|
+
const out = await res.json().catch(() => null)
|
|
2248
|
+
if (res.status === 404) return toolError('No such record of yours — pass a record id you can see (my_day, timeline_pull, list_records).')
|
|
2249
|
+
if (res.status === 409) return toolError('That capture is still sealed in private intake; materialize it first, then propose against its record.')
|
|
2250
|
+
if (!res.ok) return toolError(`Could not propose: ${out?.error ?? res.status}`)
|
|
2251
|
+
return { content: [{ type: 'text', text: renderProposal(out, built.candidate, built.note) }] }
|
|
2252
|
+
},
|
|
2253
|
+
)
|
|
2254
|
+
|
|
2205
2255
|
server.registerTool(
|
|
2206
2256
|
'resolve_obligation',
|
|
2207
2257
|
{
|
|
@@ -3157,7 +3207,7 @@ function renderNudge(payload) {
|
|
|
3157
3207
|
return toolError(`Could not build daily log: ${d.message}`)
|
|
3158
3208
|
}
|
|
3159
3209
|
const { text } = await res.json()
|
|
3160
|
-
return { content: [{ type: 'text', text }] }
|
|
3210
|
+
return { content: [{ type: 'text', text: withAskNotice(text) }] }
|
|
3161
3211
|
},
|
|
3162
3212
|
)
|
|
3163
3213
|
|
package/package.json
CHANGED