@getmarrow/mcp 3.9.61 → 3.9.62
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/README.md +31 -6
- package/dist/cli.js +87 -55
- package/dist/cli.js.map +1 -1
- package/dist/hook-context.d.ts +1 -1
- package/dist/hook-contract.d.ts +6 -6
- package/dist/hook-contract.js +1 -1
- package/dist/hook-pre-action.d.ts.map +1 -1
- package/dist/hook-pre-action.js +4 -2
- package/dist/hook-pre-action.js.map +1 -1
- package/dist/hook-session.d.ts +1 -1
- package/dist/hook.d.ts +1 -1
- package/dist/host-capability.d.ts +60 -0
- package/dist/host-capability.d.ts.map +1 -0
- package/dist/host-capability.js +118 -0
- package/dist/host-capability.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -7
- package/dist/index.js.map +1 -1
- package/dist/lifecycle-spool.d.ts +9 -0
- package/dist/lifecycle-spool.d.ts.map +1 -1
- package/dist/lifecycle-spool.js +94 -20
- package/dist/lifecycle-spool.js.map +1 -1
- package/dist/runtime-contract.d.ts +1 -0
- package/dist/runtime-contract.d.ts.map +1 -1
- package/dist/runtime-contract.js +72 -11
- package/dist/runtime-contract.js.map +1 -1
- package/dist/spool-command.d.ts +17 -0
- package/dist/spool-command.d.ts.map +1 -0
- package/dist/spool-command.js +26 -0
- package/dist/spool-command.js.map +1 -0
- package/dist/status-cache.d.ts +21 -0
- package/dist/status-cache.d.ts.map +1 -0
- package/dist/status-cache.js +177 -0
- package/dist/status-cache.js.map +1 -0
- package/dist/types.d.ts +20 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
package/README.md
CHANGED
|
@@ -104,7 +104,18 @@ npx -y --package=@getmarrow/mcp@latest marrow-mcp ping
|
|
|
104
104
|
|
|
105
105
|
Detection and notification are automatic. After explicit installer activation, the local controller may restore only Marrow-managed hooks/configuration. Package upgrades, owner policy, credentials, and unrelated configuration remain explicit and subject to the operator's normal change policy.
|
|
106
106
|
|
|
107
|
-
## What's New in v3.9.
|
|
107
|
+
## What's New in v3.9.62
|
|
108
|
+
|
|
109
|
+
v3.9.62 integrates four model-neutral reliability and capability contracts:
|
|
110
|
+
|
|
111
|
+
- standalone `marrow_status` uses the bounded compact API contract and can return a fresh, owner-only last-known status projection without treating it as a live gate or authorization;
|
|
112
|
+
- ordinary runtime responses expose typed `runtime_authorization` backed by the authoritative gate receipt and omit `decision_id` unless the server actually created a decision;
|
|
113
|
+
- `spool-status` and `drain-spool` report the active credential namespace separately from isolated legacy debt, and a clear active namespace exits successfully without replaying, merging, editing, or deleting old-key files;
|
|
114
|
+
- initialize, prompt, setup, and tool responses qualify coverage by `host_capability`: MCP tools are on demand, while native hooks, an owned SDK process, a governed runner, or a custom event adapter cover only the scope proved by observed Marrow receipts.
|
|
115
|
+
|
|
116
|
+
The default surface remains six tools and the prompt remains named `marrow-always-on`. Host and model labels are display-only and never change auth, tenant, plan, policy, proof, schema, or API behavior.
|
|
117
|
+
|
|
118
|
+
## Previous: v3.9.61
|
|
108
119
|
|
|
109
120
|
v3.9.61 keeps an authoritative proof-pack rejection distinct from a control-path outage:
|
|
110
121
|
|
|
@@ -125,7 +136,7 @@ v3.9.60 restores the complete control-and-proof loop for ordinary MCP clients:
|
|
|
125
136
|
- a plan-gated handoff is reported as unavailable for the current plan, not as an API or authentication outage;
|
|
126
137
|
- the release canary runs with the customer's default client deadlines instead of silently overriding them.
|
|
127
138
|
|
|
128
|
-
MCP-only hosts
|
|
139
|
+
MCP-only hosts receive the same model-neutral control instructions and six-tool default surface, but MCP transport alone is on demand. A host or model label never changes that coverage contract. Marrow reports passive coverage only from observed lifecycle receipts, not from configuration detection.
|
|
129
140
|
|
|
130
141
|
## Previous: v3.9.59
|
|
131
142
|
|
|
@@ -138,7 +149,7 @@ v3.9.59 makes the six-tool control path reliable and honest across ordinary edge
|
|
|
138
149
|
- a first-session outage returns a clearly labeled local safety brief, and infrastructure failures are never mislabeled as policy denials;
|
|
139
150
|
- timeout errors return a concrete retry delay instead of an unresolved placeholder;
|
|
140
151
|
- Cloudflare edge denials are separated from key-scope or Marrow policy rejections;
|
|
141
|
-
- MCP initialization carries the
|
|
152
|
+
- MCP initialization carries the capability-qualified control/proof instructions even when a client does not request the optional prompt template;
|
|
142
153
|
- update, launch, setup, spool, and ping commands use the unambiguous `npx --package ... marrow-mcp` form;
|
|
143
154
|
- explicit spool drains tolerate slow edge delivery without extending passive hook latency.
|
|
144
155
|
|
|
@@ -260,6 +271,8 @@ With installed native hooks, protected tool calls follow this automatically. For
|
|
|
260
271
|
4. Perform the action only when its gate allows it. For a hard external choke point, run the command through `npx @getmarrow/install run`; it verifies the signed action permit immediately before execution.
|
|
261
272
|
5. Call `marrow_commit` with that `decision_id`, the outcome, gate receipt, and required proof.
|
|
262
273
|
|
|
274
|
+
`marrow_agent_runtime` returns `runtime_authorization` with the authoritative gate receipt. Ordinary runtime checks do not create a decision, so they omit `decision_id`; call `marrow_think` (or use `marrow_auto`) when a decision must be created and closed. An arbitration runtime that actually creates a decision returns that server-created `decision_id`. This contract is identical across MCP-compatible hosts and SDK-owned runtimes.
|
|
275
|
+
|
|
263
276
|
Example pre-action request:
|
|
264
277
|
|
|
265
278
|
```json
|
|
@@ -354,9 +367,21 @@ it does not run models, retain prompts, or infer a winner from labels.
|
|
|
354
367
|
|
|
355
368
|
## Passive Use
|
|
356
369
|
|
|
357
|
-
`npx -y --package=@getmarrow/mcp@latest marrow-mcp setup`
|
|
370
|
+
`npx -y --package=@getmarrow/mcp@latest marrow-mcp setup` configures supported prompt, pre-action, tool-result, and session-stop hooks. Configuration is not proof that the host invoked them. Marrow reports native passive coverage only after it observes the required prompt, pre-action, action-result, and session-end receipts.
|
|
371
|
+
|
|
372
|
+
### Capability and coverage contract
|
|
373
|
+
|
|
374
|
+
| Integration mode | Coverage Marrow can claim |
|
|
375
|
+
| --- | --- |
|
|
376
|
+
| MCP tools-only | On demand; covers only explicit MCP tool calls |
|
|
377
|
+
| Verified native hooks | Passive only for the lifecycle stages backed by observed hook receipts |
|
|
378
|
+
| `createPassiveRuntime().install()` | Only the owned Node process, and only while that runtime is installed and running |
|
|
379
|
+
| Governed runner | Only the command launched through the wrapper |
|
|
380
|
+
| Custom host | Requires a bounded event adapter; covers only the lifecycle events whose receipts Marrow observes |
|
|
381
|
+
|
|
382
|
+
This contract is model-neutral. A model name, host header, config file, installed hook entry, or successful MCP handshake does not certify passive coverage. Only observed Marrow receipts do. An unknown MCP host therefore gets the generic `mcp-client` identity and the same on-demand tools, schemas, and API semantics as a named host.
|
|
358
383
|
|
|
359
|
-
|
|
384
|
+
When invoked by a supported host, the configured hooks send compact classifications and lifecycle receipts. They do not need raw prompts, completions, command output, tool output, or credentials. A completed tool or session does not automatically become a successful business outcome; explicit success/failure closure is required.
|
|
360
385
|
|
|
361
386
|
Transient lifecycle receipts use a bounded owner-only spool and are retried with stable event IDs. Operators can inspect and drain it without exposing event content:
|
|
362
387
|
|
|
@@ -365,7 +390,7 @@ npx -y --package=@getmarrow/mcp@latest marrow-mcp spool-status
|
|
|
365
390
|
npx -y --package=@getmarrow/mcp@latest marrow-mcp drain-spool
|
|
366
391
|
```
|
|
367
392
|
|
|
368
|
-
The output contains only state,
|
|
393
|
+
The output contains only state, bounded pending/failed counts, oldest receipt timestamps, capacity, and an exact fix. A drain applies only to the active credential-and-agent namespace: isolated legacy namespace debt is reported separately and never changes a successful active-namespace drain into a failure. Legacy files are never replayed, merged, deleted, or attributed to the active identity. Restore the exact original identity to drain one, or preserve the selected file unchanged in a separate owner-only quarantine directory when that identity is unavailable. Terminal validation/authentication failures and exhausted retries in the active namespace remain explicit durable failures rather than cycling indefinitely.
|
|
369
394
|
|
|
370
395
|
Check the installed runtime:
|
|
371
396
|
|
package/dist/cli.js
CHANGED
|
@@ -17,6 +17,7 @@ const hook_session_1 = require("./hook-session");
|
|
|
17
17
|
const hook_pre_action_1 = require("./hook-pre-action");
|
|
18
18
|
const env_1 = require("./env");
|
|
19
19
|
const lifecycle_spool_1 = require("./lifecycle-spool");
|
|
20
|
+
const spool_command_1 = require("./spool-command");
|
|
20
21
|
const guidance_cache_1 = require("./guidance-cache");
|
|
21
22
|
const request_reliability_1 = require("./request-reliability");
|
|
22
23
|
const hook_contract_1 = require("./hook-contract");
|
|
@@ -24,6 +25,8 @@ const ping_state_1 = require("./ping-state");
|
|
|
24
25
|
const control_path_state_1 = require("./control-path-state");
|
|
25
26
|
const redact_1 = require("./redact");
|
|
26
27
|
const runtime_contract_1 = require("./runtime-contract");
|
|
28
|
+
const status_cache_1 = require("./status-cache");
|
|
29
|
+
const host_capability_1 = require("./host-capability");
|
|
27
30
|
// Parse CLI args
|
|
28
31
|
function parseArgs() {
|
|
29
32
|
const args = process.argv.slice(2);
|
|
@@ -127,17 +130,10 @@ async function runSpoolCommand(drain) {
|
|
|
127
130
|
const status = drain
|
|
128
131
|
? await (0, lifecycle_spool_1.drainLifecycleSpool)({ apiKey, baseUrl, agentId: resolved.agentId || undefined })
|
|
129
132
|
: (0, lifecycle_spool_1.lifecycleSpoolStatus)({ apiKey, agentId: resolved.agentId || undefined });
|
|
130
|
-
const
|
|
131
|
-
process.stdout.write(`${JSON.stringify(
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
: status.state !== 'attention_required' && !namespaceAttention,
|
|
135
|
-
lifecycle_spool: status,
|
|
136
|
-
}, null, 2)}\n`);
|
|
137
|
-
if (status.state === 'attention_required' || namespaceAttention)
|
|
138
|
-
process.exitCode = 2;
|
|
139
|
-
else if (drain && status.state !== 'clear')
|
|
140
|
-
process.exitCode = 1;
|
|
133
|
+
const outcome = (0, spool_command_1.lifecycleSpoolCommandOutcome)(status, drain);
|
|
134
|
+
process.stdout.write(`${JSON.stringify(outcome.output, null, 2)}\n`);
|
|
135
|
+
if (outcome.exitCode !== 0)
|
|
136
|
+
process.exitCode = outcome.exitCode;
|
|
141
137
|
}
|
|
142
138
|
// ─── Setup command: inject Marrow instructions into CLAUDE.md ───
|
|
143
139
|
function runSetup() {
|
|
@@ -148,10 +144,10 @@ function runSetup() {
|
|
|
148
144
|
const marrowInstructions = `${MARROW_BLOCK_START}
|
|
149
145
|
## Marrow — Agent Control and Proof (auto-injected by @getmarrow/mcp setup)
|
|
150
146
|
|
|
151
|
-
|
|
147
|
+
Use Marrow according to the capability evidence returned by the MCP server:
|
|
152
148
|
|
|
153
|
-
1. **
|
|
154
|
-
2. **Before risky actions:** Respect the returned \`allow\`, \`warn\`, \`review_required\`, or \`block\` decision and its proof contract. Call \`marrow_agent_runtime\` explicitly when
|
|
149
|
+
1. **MCP baseline is on demand:** MCP transport exposes tools; it does not provide passive hooks. Call Marrow tools explicitly unless observed receipts verify another capability mode.
|
|
150
|
+
2. **Before risky actions:** Respect the returned \`allow\`, \`warn\`, \`review_required\`, or \`block\` decision and its proof contract. Call \`marrow_agent_runtime\` explicitly when verified passive coverage cannot cover the action.
|
|
155
151
|
3. **After meaningful work:** Record the real success or failure with \`marrow_commit\` or \`marrow_auto\`. A tool exit or session end is not proof that the business outcome succeeded.
|
|
156
152
|
4. **Unfinished work:** Leave pending outcomes visible. Do not invent success to clear a closure item.
|
|
157
153
|
5. **To explain an intervention:** Use \`marrow_decision_trace\`, then relay its \`intervention_receipt\` in one factual sentence when Marrow blocked, warned, or required review. Stay quiet for routine low-risk work.
|
|
@@ -160,6 +156,8 @@ You have Marrow MCP connected. Use it on EVERY session automatically:
|
|
|
160
156
|
|
|
161
157
|
Do not skip the gate or outcome. Marrow's value comes from controlling the action before execution and preserving evidence afterward.
|
|
162
158
|
|
|
159
|
+
Capability boundaries: verified native hooks cover only their observed lifecycle; \`createPassiveRuntime().install()\` covers only its owned Node process while installed; a governed runner covers only its wrapped command; and a custom host needs a bounded event adapter. A model name, host label, or installed configuration is not proof of coverage. Only observed Marrow receipts certify it.
|
|
160
|
+
|
|
163
161
|
For one-shot logging: \`marrow_auto({ action: "did X", outcome: "result Y", success: true })\` — one call, done.
|
|
164
162
|
${MARROW_BLOCK_END}`;
|
|
165
163
|
let dir = process.cwd();
|
|
@@ -203,37 +201,37 @@ ${MARROW_BLOCK_END}`;
|
|
|
203
201
|
}
|
|
204
202
|
const hookInstall = (0, hook_1.installPostToolUseHook)(process.cwd());
|
|
205
203
|
if (hookInstall.installed) {
|
|
206
|
-
process.stdout.write('
|
|
204
|
+
process.stdout.write('Configured PostToolUse hook. Coverage remains unverified until Marrow observes action-result receipts.\n');
|
|
207
205
|
}
|
|
208
206
|
else {
|
|
209
|
-
process.stdout.write('PostToolUse hook
|
|
207
|
+
process.stdout.write('PostToolUse hook configuration is present. Coverage remains unverified until Marrow observes action-result receipts.\n');
|
|
210
208
|
}
|
|
211
209
|
const contextHookInstall = (0, hook_context_1.installUserPromptSubmitHook)(process.cwd());
|
|
212
210
|
if (contextHookInstall.installed) {
|
|
213
|
-
process.stdout.write('
|
|
211
|
+
process.stdout.write('Configured UserPromptSubmit hook. Passive prompt coverage remains unverified until Marrow observes prompt receipts.\n');
|
|
214
212
|
}
|
|
215
213
|
else {
|
|
216
|
-
process.stdout.write('UserPromptSubmit hook
|
|
214
|
+
process.stdout.write('UserPromptSubmit hook configuration is present. Passive prompt coverage remains unverified until Marrow observes prompt receipts.\n');
|
|
217
215
|
}
|
|
218
216
|
const preActionHookInstall = (0, hook_pre_action_1.installPreActionHook)(process.cwd());
|
|
219
217
|
if (preActionHookInstall.installed) {
|
|
220
|
-
process.stdout.write('
|
|
218
|
+
process.stdout.write('Configured PreToolUse hook. Pre-action coverage remains unverified until Marrow observes pre-action receipts.\n');
|
|
221
219
|
}
|
|
222
220
|
else {
|
|
223
|
-
process.stdout.write('PreToolUse hook
|
|
221
|
+
process.stdout.write('PreToolUse hook configuration is present. Pre-action coverage remains unverified until Marrow observes pre-action receipts.\n');
|
|
224
222
|
}
|
|
225
223
|
const sessionHookInstall = (0, hook_session_1.installSessionEndHook)(process.cwd());
|
|
226
224
|
if (sessionHookInstall.installed) {
|
|
227
|
-
process.stdout.write('
|
|
225
|
+
process.stdout.write('Configured Stop hook. Session-end coverage remains unverified until Marrow observes session-end receipts.\n');
|
|
228
226
|
}
|
|
229
227
|
else {
|
|
230
|
-
process.stdout.write('Stop hook
|
|
228
|
+
process.stdout.write('Stop hook configuration is present. Session-end coverage remains unverified until Marrow observes session-end receipts.\n');
|
|
231
229
|
}
|
|
232
230
|
process.stdout.write(`Hook settings: ${hookInstall.settingsPath}\n`);
|
|
233
231
|
process.stdout.write('Set MARROW_AUTO_HOOK=false to disable passive hooks.\n');
|
|
234
232
|
process.stdout.write('Set MARROW_PASSIVE_BRIEF=false to disable automatic decision briefs, or MARROW_PASSIVE_BRIEF=always to brief every prompt.\n');
|
|
235
233
|
process.stdout.write('Set MARROW_HOOK_DEBUG=true for write-side hook diagnostics, or MARROW_CONTEXT_HOOK_DEBUG=true for prompt-context diagnostics.\n');
|
|
236
|
-
process.stdout.write('
|
|
234
|
+
process.stdout.write('Setup completed. MCP tools remain on demand; passive coverage is reported only after Marrow observes the required hook receipts.\n');
|
|
237
235
|
process.exit(0);
|
|
238
236
|
}
|
|
239
237
|
const cliArgs = parseArgs();
|
|
@@ -489,22 +487,9 @@ if (process.argv[2] !== 'keys') {
|
|
|
489
487
|
return result;
|
|
490
488
|
}
|
|
491
489
|
function mcpHostCapability() {
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
return {
|
|
496
|
-
transport: 'mcp_stdio',
|
|
497
|
-
host,
|
|
498
|
-
tools_available: true,
|
|
499
|
-
tool_invocation: 'on_demand',
|
|
500
|
-
passive_hooks: {
|
|
501
|
-
provided_by_mcp_transport: false,
|
|
502
|
-
external_host_hook_state: 'unverified',
|
|
503
|
-
observed_by_this_process: false,
|
|
504
|
-
},
|
|
505
|
-
always_on_state: 'host_dependent',
|
|
506
|
-
exact_next_action: 'Use the Marrow MCP tools on demand. Claim passive coverage only when the host separately configures trusted hooks and Marrow receives their lifecycle receipts.',
|
|
507
|
-
};
|
|
490
|
+
return (0, host_capability_1.resolveHostCapability)({
|
|
491
|
+
hostLabel: process.env.MARROW_CLIENT || process.env.MARROW_HARNESS || process.env.MARROW_AGENT_CLIENT,
|
|
492
|
+
});
|
|
508
493
|
}
|
|
509
494
|
function clientOperationalPayload(toolName, value) {
|
|
510
495
|
const payload = value && typeof value === 'object' && !Array.isArray(value)
|
|
@@ -575,6 +560,23 @@ if (process.argv[2] !== 'keys') {
|
|
|
575
560
|
}
|
|
576
561
|
catch { /* owner-only cache is best effort */ }
|
|
577
562
|
}
|
|
563
|
+
function storeLastKnownStatus(status, source) {
|
|
564
|
+
try {
|
|
565
|
+
(0, status_cache_1.writeStatusCache)({
|
|
566
|
+
apiKey: API_KEY,
|
|
567
|
+
baseUrl: BASE_URL,
|
|
568
|
+
agentId: FLEET_AGENT_ID,
|
|
569
|
+
status,
|
|
570
|
+
source,
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
catch { /* owner-only cache is best effort */ }
|
|
574
|
+
}
|
|
575
|
+
function refreshStatusInBackground() {
|
|
576
|
+
void (0, index_1.marrowStatus)(API_KEY, BASE_URL, SESSION_ID, FLEET_AGENT_ID)
|
|
577
|
+
.then((status) => storeLastKnownStatus(status, 'status'))
|
|
578
|
+
.catch(() => undefined);
|
|
579
|
+
}
|
|
578
580
|
// [FIX #6 & #7] Safe JSON response helper for memory API functions
|
|
579
581
|
async function safeMemoryResponse(res) {
|
|
580
582
|
if (!res.ok) {
|
|
@@ -820,7 +822,7 @@ if (process.argv[2] !== 'keys') {
|
|
|
820
822
|
type: 'object',
|
|
821
823
|
description: 'Optional required proof pack for gated work: summary, checks, outcome, blockers, commits_prs_shas, rollback_target, handoff_result_file, deployment_and_smoke.',
|
|
822
824
|
},
|
|
823
|
-
gate_receipt_id: { type: 'string', description: '
|
|
825
|
+
gate_receipt_id: { type: 'string', description: 'Canonical receipt id from marrow_agent_runtime.runtime_authorization.id for risky work.' },
|
|
824
826
|
arbitration_receipt_id: { type: 'string', description: 'Required for arbitrated work: use marrow_arbitrate.arbitration.receipt_id from the same runtime response.' },
|
|
825
827
|
owner_approval_receipt_id: { type: 'string', description: 'Single-use owner approval receipt issued by authenticated dashboard review for review_required arbitration.' },
|
|
826
828
|
action: { type: 'string', description: 'Optional original action. If provided and gate_receipt_id is omitted, MCP can fetch a matching runtime gate receipt before commit.' },
|
|
@@ -1233,6 +1235,8 @@ if (process.argv[2] !== 'keys') {
|
|
|
1233
1235
|
name: 'marrow_agent_runtime',
|
|
1234
1236
|
description: 'One-call agent-native Marrow loop. Returns passive status, decision brief, risk gate, relevant lessons, ' +
|
|
1235
1237
|
'template suggestion, required proof pack, before-you-act instruction, and exact next action. ' +
|
|
1238
|
+
'Its runtime_authorization is the authoritative gate receipt; it returns decision_id only when runtime actually creates a decision. ' +
|
|
1239
|
+
'Use marrow_auto or marrow_think to create the decision_id required for outcome closure. ' +
|
|
1236
1240
|
'Use this before meaningful work when you want Marrow to guide the whole action in one call.',
|
|
1237
1241
|
inputSchema: {
|
|
1238
1242
|
type: 'object',
|
|
@@ -1687,13 +1691,15 @@ if (process.argv[2] !== 'keys') {
|
|
|
1687
1691
|
try {
|
|
1688
1692
|
if (method === 'initialize') {
|
|
1689
1693
|
initialized = true;
|
|
1694
|
+
const hostCapability = mcpHostCapability();
|
|
1690
1695
|
success(id, {
|
|
1691
1696
|
protocolVersion: '2024-11-05',
|
|
1692
1697
|
capabilities: { tools: {}, prompts: {} },
|
|
1693
1698
|
serverInfo: { name: 'marrow', version: hook_contract_1.MCP_ADAPTER_VERSION },
|
|
1694
1699
|
...(AUTO_ENROLL ? {
|
|
1695
|
-
instructions:
|
|
1700
|
+
instructions: `Use marrow_agent_runtime before consequential actions, obey fresh allow/warn/review_required/block results, use marrow_ask for relevant prior lessons, and close meaningful outcomes with marrow_commit. Infrastructure failures are not policy denials; continue only low-risk reversible work from the returned outage-safe brief, and require a fresh gate for high-risk work. ${(0, host_capability_1.hostCapabilityInstructions)(hostCapability)}`,
|
|
1696
1701
|
} : {}),
|
|
1702
|
+
_meta: { host_capability: hostCapability },
|
|
1697
1703
|
});
|
|
1698
1704
|
// Auto-enroll: emit enrollment notification on connection
|
|
1699
1705
|
if (AUTO_ENROLL) {
|
|
@@ -1705,9 +1711,10 @@ if (process.argv[2] !== 'keys') {
|
|
|
1705
1711
|
logger: 'marrow',
|
|
1706
1712
|
data: {
|
|
1707
1713
|
type: 'auto_enroll',
|
|
1708
|
-
message:
|
|
1714
|
+
message: `Marrow operating contract available. MCP tools are on demand. ${hostCapability.exact_next_action}`,
|
|
1709
1715
|
agentId: FLEET_AGENT_ID,
|
|
1710
1716
|
client_update: (0, request_reliability_1.localClientUpdate)(),
|
|
1717
|
+
host_capability: hostCapability,
|
|
1711
1718
|
},
|
|
1712
1719
|
},
|
|
1713
1720
|
});
|
|
@@ -1720,8 +1727,9 @@ if (process.argv[2] !== 'keys') {
|
|
|
1720
1727
|
prompts: [
|
|
1721
1728
|
{
|
|
1722
1729
|
name: 'marrow-always-on',
|
|
1723
|
-
description: '
|
|
1730
|
+
description: 'Marrow control and proof contract, qualified by verified host capability and observed lifecycle receipts.',
|
|
1724
1731
|
arguments: [],
|
|
1732
|
+
_meta: { host_capability: mcpHostCapability() },
|
|
1725
1733
|
},
|
|
1726
1734
|
],
|
|
1727
1735
|
});
|
|
@@ -1737,8 +1745,10 @@ if (process.argv[2] !== 'keys') {
|
|
|
1737
1745
|
error(id, -32602, 'Unknown prompt');
|
|
1738
1746
|
return;
|
|
1739
1747
|
}
|
|
1748
|
+
const hostCapability = mcpHostCapability();
|
|
1740
1749
|
success(id, {
|
|
1741
|
-
description: '
|
|
1750
|
+
description: 'Marrow control and proof contract — coverage is capability-qualified and receipt-verified',
|
|
1751
|
+
_meta: { host_capability: hostCapability },
|
|
1742
1752
|
messages: [
|
|
1743
1753
|
{
|
|
1744
1754
|
role: 'user',
|
|
@@ -1746,14 +1756,16 @@ if (process.argv[2] !== 'keys') {
|
|
|
1746
1756
|
type: 'text',
|
|
1747
1757
|
text: `You have Marrow — the agent control and proof layer around this workflow.
|
|
1748
1758
|
|
|
1749
|
-
##
|
|
1759
|
+
## Capability-qualified operating contract
|
|
1760
|
+
|
|
1761
|
+
${(0, host_capability_1.hostCapabilityInstructions)(hostCapability)}
|
|
1750
1762
|
|
|
1751
|
-
|
|
1752
|
-
- UserPromptSubmit
|
|
1753
|
-
- PostToolUse
|
|
1754
|
-
- Stop
|
|
1763
|
+
When verified by observed receipts, native hooks can cover these bounded lifecycle stages:
|
|
1764
|
+
- UserPromptSubmit can request relevant policy, warnings, lessons, and a decision brief before risky work.
|
|
1765
|
+
- PostToolUse can record compact tool success or failure receipts.
|
|
1766
|
+
- Stop can keep unfinished outcomes visible instead of silently treating session exit as success.
|
|
1755
1767
|
|
|
1756
|
-
Hooks never make a blocked action safe. Before a consequential action, respect the returned allow, warn, review_required, or block decision and its required proof. Call marrow_agent_runtime explicitly when
|
|
1768
|
+
Hooks never make a blocked action safe. Before a consequential action, respect the returned allow, warn, review_required, or block decision and its required proof. Call marrow_agent_runtime explicitly when verified passive coverage cannot cover the action.
|
|
1757
1769
|
|
|
1758
1770
|
When runtime/status returns a client_update notice, tell the operator and use its exact update and verification commands only when local change policy permits. Never silently change packages or configuration.
|
|
1759
1771
|
|
|
@@ -1802,7 +1814,7 @@ Marrow is not a replacement agent or a standalone memory app. Context and prior
|
|
|
1802
1814
|
`2. Use marrow_agent_runtime when a risky action needs an explicit gate.\n` +
|
|
1803
1815
|
`3. Close meaningful work with marrow_commit; a tool exit alone is not outcome proof.\n` +
|
|
1804
1816
|
`4. Use marrow_decision_trace to explain the prior failure, lesson, gate, proof, workflow, and outcome path.\n\n` +
|
|
1805
|
-
|
|
1817
|
+
`${(0, host_capability_1.hostCapabilityInstructions)(mcpHostCapability())}\n\nLeave unknown outcomes pending instead of inventing success.\n`;
|
|
1806
1818
|
const orientText = JSON.stringify(result, null, 2);
|
|
1807
1819
|
success(id, {
|
|
1808
1820
|
content: [{ type: 'text', text: enrollmentText + orientText }],
|
|
@@ -1969,7 +1981,12 @@ Marrow is not a replacement agent or a standalone memory app. Context and prior
|
|
|
1969
1981
|
}, SESSION_ID, FLEET_AGENT_ID, signal), { highRisk: true, toolName: 'marrow_auto.runtime' });
|
|
1970
1982
|
storeRuntimeGuidance(runtimeGate);
|
|
1971
1983
|
}
|
|
1972
|
-
const
|
|
1984
|
+
const canonicalRuntimeReceiptId = (0, runtime_contract_1.runtimeAuthorizationReceiptId)(runtimeGate);
|
|
1985
|
+
const suppliedRuntimeReceiptId = typeof args.gate_receipt_id === 'string'
|
|
1986
|
+
? args.gate_receipt_id
|
|
1987
|
+
: canonicalRuntimeReceiptId;
|
|
1988
|
+
const proofCanClose = !highRisk
|
|
1989
|
+
|| (0, runtime_contract_1.highRiskRuntimeCanClose)(runtimeGate, suppliedProof, suppliedRuntimeReceiptId);
|
|
1973
1990
|
const acceptedSuccess = proofCanClose ? outcomeSuccess : undefined;
|
|
1974
1991
|
const delivery = () => (0, index_1.marrowAuto)(API_KEY, BASE_URL, {
|
|
1975
1992
|
action,
|
|
@@ -1977,9 +1994,10 @@ Marrow is not a replacement agent or a standalone memory app. Context and prior
|
|
|
1977
1994
|
success: acceptedSuccess,
|
|
1978
1995
|
type,
|
|
1979
1996
|
proof: suppliedProof,
|
|
1980
|
-
gate_receipt_id:
|
|
1981
|
-
|
|
1982
|
-
|
|
1997
|
+
gate_receipt_id: suppliedRuntimeReceiptId || undefined,
|
|
1998
|
+
// Low-risk one-shot capture does not need a policy gate. Consequential
|
|
1999
|
+
// work already obtained and validated canonical runtime authorization.
|
|
2000
|
+
auto_gate: highRisk,
|
|
1983
2001
|
}, SESSION_ID, FLEET_AGENT_ID, 8_000);
|
|
1984
2002
|
let delivered = null;
|
|
1985
2003
|
let deliveryFailure = null;
|
|
@@ -2060,7 +2078,20 @@ Marrow is not a replacement agent or a standalone memory app. Context and prior
|
|
|
2060
2078
|
return;
|
|
2061
2079
|
}
|
|
2062
2080
|
if (toolName === 'marrow_status') {
|
|
2081
|
+
let cached = null;
|
|
2082
|
+
try {
|
|
2083
|
+
cached = (0, status_cache_1.readStatusCache)({ apiKey: API_KEY, baseUrl: BASE_URL, agentId: FLEET_AGENT_ID });
|
|
2084
|
+
}
|
|
2085
|
+
catch { /* owner-only cache is best effort */ }
|
|
2086
|
+
if (cached) {
|
|
2087
|
+
const startedAt = Date.now();
|
|
2088
|
+
refreshStatusInBackground();
|
|
2089
|
+
(0, control_path_state_1.recordControlPathSample)('marrow_status', Date.now() - startedAt, true);
|
|
2090
|
+
toolSuccess(id, clientOperationalPayload('marrow_status', (0, status_cache_1.cachedStatusPayload)(cached)));
|
|
2091
|
+
return;
|
|
2092
|
+
}
|
|
2063
2093
|
const result = await withControlDeadline((signal) => (0, index_1.marrowStatus)(API_KEY, BASE_URL, SESSION_ID, FLEET_AGENT_ID, signal), { cacheAware: false, toolName: 'marrow_status' });
|
|
2094
|
+
storeLastKnownStatus(result, 'status');
|
|
2064
2095
|
toolSuccess(id, clientOperationalPayload('marrow_status', result));
|
|
2065
2096
|
return;
|
|
2066
2097
|
}
|
|
@@ -2257,6 +2288,7 @@ Marrow is not a replacement agent or a standalone memory app. Context and prior
|
|
|
2257
2288
|
};
|
|
2258
2289
|
const result = await withControlDeadline((signal) => (0, index_1.marrowAgentRuntime)(API_KEY, BASE_URL, runtimeInput, SESSION_ID, FLEET_AGENT_ID, signal), { highRisk: isHighRiskAction(runtimeInput.action, runtimeInput.type), toolName: 'marrow_agent_runtime' });
|
|
2259
2290
|
storeRuntimeGuidance(result);
|
|
2291
|
+
storeLastKnownStatus(result.status, 'runtime');
|
|
2260
2292
|
toolSuccess(id, clientOperationalPayload('marrow_agent_runtime', result));
|
|
2261
2293
|
return;
|
|
2262
2294
|
}
|