@getmarrow/mcp 3.9.72 → 3.9.74
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 -20
- package/dist/cli.js +65 -58
- package/dist/cli.js.map +1 -1
- package/dist/hook-context.d.ts +1 -1
- package/dist/hook-context.d.ts.map +1 -1
- package/dist/hook-context.js +5 -9
- package/dist/hook-context.js.map +1 -1
- package/dist/hook-contract.d.ts +28 -15
- package/dist/hook-contract.d.ts.map +1 -1
- package/dist/hook-contract.js +60 -25
- package/dist/hook-contract.js.map +1 -1
- package/dist/hook-pre-action.d.ts +2 -0
- package/dist/hook-pre-action.d.ts.map +1 -1
- package/dist/hook-pre-action.js +52 -12
- package/dist/hook-pre-action.js.map +1 -1
- package/dist/hook-session.d.ts +1 -1
- package/dist/hook-session.d.ts.map +1 -1
- package/dist/hook-session.js +4 -6
- package/dist/hook-session.js.map +1 -1
- package/dist/hook.d.ts +1 -1
- package/dist/hook.d.ts.map +1 -1
- package/dist/hook.js +4 -6
- package/dist/hook.js.map +1 -1
- package/dist/host-capability.d.ts +23 -16
- package/dist/host-capability.d.ts.map +1 -1
- package/dist/host-capability.js +41 -61
- package/dist/host-capability.js.map +1 -1
- package/dist/index.d.ts +29 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +353 -56
- package/dist/index.js.map +1 -1
- package/dist/lifecycle-spool.d.ts +1 -5
- package/dist/lifecycle-spool.d.ts.map +1 -1
- package/dist/lifecycle-spool.js +11 -28
- package/dist/lifecycle-spool.js.map +1 -1
- package/dist/runtime-contract.d.ts +6 -0
- package/dist/runtime-contract.d.ts.map +1 -1
- package/dist/runtime-contract.js +14 -2
- package/dist/runtime-contract.js.map +1 -1
- package/package.json +1 -1
- package/scripts/control-path-canary.cjs +67 -6
- package/server.json +2 -2
package/README.md
CHANGED
|
@@ -66,7 +66,7 @@ Set the key through trusted secret storage:
|
|
|
66
66
|
export MARROW_API_KEY=mrw_live_...
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
For
|
|
69
|
+
For Claude Code's cooperative pre-action hook, Marrow accepts the process environment or an owner-controlled `~/.marrow/env` file with owner-only permissions. Repository-local `.env` files are intentionally ignored so project content cannot replace the account, agent, or API endpoint used for guidance. The public hook callback is still a client self-report, not certified host provenance or an external enforcement boundary.
|
|
70
70
|
|
|
71
71
|
Then configure the MCP server:
|
|
72
72
|
|
|
@@ -104,7 +104,11 @@ 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.74
|
|
108
|
+
|
|
109
|
+
v3.9.74 keeps one automatic operation bound to its original runtime authorization and decision across timeout and proof-required retries, then closes that exact decision once verified proof is supplied. One outer `marrow_auto` invocation normally completes think and commit in-band within its bounded eight-second client budget. The release canary allows that complete client budget plus bounded response overhead rather than cutting the operation off at five seconds.
|
|
110
|
+
|
|
111
|
+
## Previous: v3.9.72
|
|
108
112
|
|
|
109
113
|
v3.9.72 requires SDK `3.7.61` so MCP installations cannot resolve to an SDK that recursively intercepts its own Marrow control-plane traffic. The MCP tool contract is unchanged; this release aligns the tested package chain.
|
|
110
114
|
|
|
@@ -115,9 +119,10 @@ v3.9.71 makes the advertised Grok control loop true:
|
|
|
115
119
|
- default tools include `marrow_think` so the official loop can create a `decision_id` without `MARROW_TOOL_PROFILE=full`;
|
|
116
120
|
- process identity prefers `MARROW_KEY_<ROLE>` when it matches `MARROW_AGENT_ID`, so a leaked fleet env cannot 403 every status call;
|
|
117
121
|
- Grok native hooks are installed under `~/.grok/hooks/marrow.json` and hook parsers accept Grok camelCase envelopes;
|
|
122
|
+
- Grok hooks are advisory telemetry/context only. Consequential execution requires `npx @getmarrow/install run --agent <agent-id> -- -- <command>`;
|
|
118
123
|
- idle spool nudge drains up to 40 current-namespace events so the queue does not sit as a nag;
|
|
119
124
|
- if `risk_gate.enforced` is false, the gate is advisory — do not describe it as a live block;
|
|
120
|
-
- `marrow_commit.decision_id`
|
|
125
|
+
- `marrow_commit.decision_id` comes from `marrow_think`, `marrow_auto`, or an arbitration runtime that actually created a decision. A normal runtime authorization is a gate receipt, not a decision.
|
|
121
126
|
|
|
122
127
|
## Previous: v3.9.69
|
|
123
128
|
|
|
@@ -182,9 +187,9 @@ v3.9.62 integrates four model-neutral reliability and capability contracts:
|
|
|
182
187
|
- 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;
|
|
183
188
|
- ordinary runtime responses expose typed `runtime_authorization` backed by the authoritative gate receipt and omit `decision_id` unless the server actually created a decision;
|
|
184
189
|
- `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;
|
|
185
|
-
- initialize, prompt, setup, and tool responses qualify coverage by `host_capability`: MCP tools are on demand, while
|
|
190
|
+
- initialize, prompt, setup, and tool responses qualify coverage by `host_capability`: MCP tools are on demand, while client-self-reported hook activity remains visible but never certifies coverage or control.
|
|
186
191
|
|
|
187
|
-
The default surface is seven tools (runtime, think, commit, ask, status, auto, handoff status) 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. Grok
|
|
192
|
+
The default surface is seven tools (runtime, think, commit, ask, status, auto, handoff status) 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. Grok hook activity is advisory and client-self-reported; the governed wrapper is the consequential-action boundary.
|
|
188
193
|
|
|
189
194
|
## Previous: v3.9.61
|
|
190
195
|
|
|
@@ -200,14 +205,14 @@ v3.9.61 keeps an authoritative proof-pack rejection distinct from a control-path
|
|
|
200
205
|
v3.9.60 restores the complete control-and-proof loop for ordinary MCP clients:
|
|
201
206
|
|
|
202
207
|
- cached guidance no longer cuts live status, ask, runtime, or handoff reads down to an impossible 500 ms deadline;
|
|
203
|
-
- `marrow_auto` waits for the bounded think-and-commit path and reports the live decision and proof result in-band;
|
|
208
|
+
- `marrow_auto` normally waits for the bounded think-and-commit path and reports the live decision and proof result in-band; if the client deadline is reached, the returned operation ID continues that same decision;
|
|
204
209
|
- `marrow_commit` now shares the same abort and deadline contract as the other control calls;
|
|
205
210
|
- transient retries use a one-second delay so a slow edge path is not immediately hit again;
|
|
206
211
|
- spool status surfaces backlogs under older credential namespaces without replaying them across an unverified tenant boundary;
|
|
207
212
|
- a plan-gated handoff is reported as unavailable for the current plan, not as an API or authentication outage;
|
|
208
213
|
- the release canary runs with the customer's default client deadlines instead of silently overriding them.
|
|
209
214
|
|
|
210
|
-
MCP-only hosts
|
|
215
|
+
The current package gives MCP-only hosts the same model-neutral control instructions and seven-tool default surface, but MCP transport alone remains on demand. A host or model label never changes that coverage contract. Public lifecycle callbacks and hook activity are client-self-reported and cannot verify or certify passive coverage; independent authority is required. Codex, Grok, Gemini, and similar CLI harnesses must use `npx @getmarrow/install run --agent <agent-id> -- -- <command>` for consequential commands.
|
|
211
216
|
|
|
212
217
|
## Previous: v3.9.59
|
|
213
218
|
|
|
@@ -286,7 +291,7 @@ It preserves the signed action-permit and update controls introduced in v3.9.52.
|
|
|
286
291
|
|
|
287
292
|
## Previous: v3.9.52
|
|
288
293
|
|
|
289
|
-
v3.9.52 combines operator-controlled client update notices with signed, action-bound permit verification in
|
|
294
|
+
v3.9.52 combines operator-controlled client update notices with signed, action-bound permit verification in the cooperative Claude Code hook path. That permit flow does not authenticate hook provenance or certify always-on coverage. Official MCP requests identify the installed package version, and passive context renders a request-specific server advisory with exact update and verification commands:
|
|
290
295
|
|
|
291
296
|
- update availability or unrecognized version metadata appears during normal authenticated runtime/status activity;
|
|
292
297
|
- messaging clearly states that hosted Marrow services are already current and that no local change was applied;
|
|
@@ -294,7 +299,7 @@ v3.9.52 combines operator-controlled client update notices with signed, action-b
|
|
|
294
299
|
- unknown versions do not imply a vulnerability, while server-designated security requirements remain distinct;
|
|
295
300
|
- existing MCP tools and older server responses remain compatible when no advisory is returned.
|
|
296
301
|
|
|
297
|
-
The
|
|
302
|
+
The Claude Code `PreToolUse` hook cooperatively verifies the permit before returning control to that harness. It obtains the runtime gate, records the exact governed decision, requests a permit bound to that gate, decision, target, and canonical action surfaces, and consumes it before returning. The callback itself remains client-self-reported and is not a certified external choke point:
|
|
298
303
|
|
|
299
304
|
- protected deploy, publish, merge, migration, credential, and production actions fail closed on timeout or permit failure;
|
|
300
305
|
- the permit is bound to the authenticated account, key, agent, session, action, target, canonical action surfaces, decision, and runtime gate;
|
|
@@ -303,13 +308,13 @@ The native `PreToolUse` hook verifies the permit before protected work can execu
|
|
|
303
308
|
- the bounded hook timeout prevents a control-plane wait from hanging the agent indefinitely;
|
|
304
309
|
- low-risk work retains passive/advisory behavior unless account policy requires stronger enforcement.
|
|
305
310
|
|
|
306
|
-
It preserves
|
|
311
|
+
It preserves native-hook activity diagnostics introduced in v3.9.50, with the current trust boundary applied:
|
|
307
312
|
|
|
308
|
-
- agents and owners can distinguish “MCP configured” from
|
|
313
|
+
- agents and owners can distinguish “MCP configured” from client-reported pre-action, result, and session activity without treating either as certification;
|
|
309
314
|
- `PreToolUse` requests the Marrow runtime gate before matched actions and maps `block` to deny and `review_required` to operator review;
|
|
310
315
|
- matching `PreToolUse` and result hooks share Claude Code's tool-use correlation while the session shares one workflow identity;
|
|
311
|
-
- generic integration events cannot claim native-hook coverage
|
|
312
|
-
- retries preserve correlation and
|
|
316
|
+
- generic integration events and public hook entrypoints cannot claim certified native-hook coverage;
|
|
317
|
+
- retries preserve correlation and explicitly `client_self_reported` activity in the owner-only durable spool;
|
|
313
318
|
- configuration drift can be diagnosed without sending configuration contents;
|
|
314
319
|
- missing outcome closure remains visible rather than treating tool or session exit as business success;
|
|
315
320
|
- existing MCP tools and lifecycle inputs remain compatible.
|
|
@@ -330,20 +335,22 @@ It preserves `marrow_arbitrate` from v3.9.49, the session-orientation hardening
|
|
|
330
335
|
|
|
331
336
|
Existing MCP tools and stable context API names remain compatible. Authentication, policy, proof, and validation failures are surfaced rather than retried as network failures.
|
|
332
337
|
|
|
333
|
-
|
|
338
|
+
Client hook activity alone never produces certified coverage percentages. An installed config or API-key-authenticated callback is shown as client-self-reported activity; certification requires an independent authority not supplied by the public MCP hook entrypoints.
|
|
334
339
|
|
|
335
340
|
## Governed Action Flow
|
|
336
341
|
|
|
337
|
-
|
|
342
|
+
Configured hooks can provide cooperative telemetry and context, but they are not a certified execution boundary. Before deploys, merges, publishes, migrations, credential changes, financial operations, or customer-impacting work:
|
|
338
343
|
|
|
339
344
|
1. Call `marrow_agent_runtime` or `marrow_decision_brief`.
|
|
340
345
|
2. Stop when the returned decision is `block` or `review_required`; otherwise follow its prior lesson and proof contract.
|
|
341
|
-
3. Call `marrow_think` or `marrow_auto` to record intent and obtain the `decision_id` that will be closed. `marrow_agent_runtime.runtime_authorization.id`
|
|
342
|
-
4. Perform the action only when its gate allows it. For
|
|
346
|
+
3. Call `marrow_think` or `marrow_auto` to record intent and obtain the `decision_id` that will be closed. Keep `marrow_agent_runtime.runtime_authorization.id` separate as the gate receipt for consequential work.
|
|
347
|
+
4. Perform the action only when its gate allows it. For Codex, Grok, Gemini, and similar CLI harnesses, use the governed wrapper: `npx @getmarrow/install run --agent <agent-id> -- -- <command>`.
|
|
343
348
|
5. Call `marrow_commit` with that `decision_id`, the outcome, gate receipt, and required proof.
|
|
344
349
|
|
|
345
350
|
`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.
|
|
346
351
|
|
|
352
|
+
`marrow_auto` returns an `operation_id`, phase, and resumable state. If a client deadline is reached before closure, retry with the same `operation_id`; Marrow reuses the same tenant-scoped runtime authorization, think decision, and commit idempotency keys instead of opening another decision. When the phase is `proof_required`, add the requested proof and retry with that same operation ID and unchanged action/context/surfaces. Proof is validated and bound at commit; changing the tenant or action scope is rejected. A closed response reports `phase: "closed"`, `committed: true`, and `resumable: false`.
|
|
353
|
+
|
|
347
354
|
Example pre-action request:
|
|
348
355
|
|
|
349
356
|
```json
|
|
@@ -438,22 +445,26 @@ it does not run models, retain prompts, or infer a winner from labels.
|
|
|
438
445
|
|
|
439
446
|
## Passive Use
|
|
440
447
|
|
|
441
|
-
`npx -y --package=@getmarrow/mcp@latest marrow-mcp setup` configures supported prompt, pre-action, tool-result, and session-stop hooks. Configuration
|
|
448
|
+
`npx -y --package=@getmarrow/mcp@latest marrow-mcp setup` configures supported prompt, pre-action, tool-result, and session-stop hooks. Configuration, public hook argv, and API-key-authenticated callbacks are client self-reports. They preserve raw lifecycle activity but do not prove that the host invoked a hook or certify passive control.
|
|
442
449
|
|
|
443
450
|
### Capability and coverage contract
|
|
444
451
|
|
|
445
452
|
| Integration mode | Coverage Marrow can claim |
|
|
446
453
|
| --- | --- |
|
|
447
454
|
| MCP tools-only | On demand; covers only explicit MCP tool calls |
|
|
448
|
-
|
|
|
455
|
+
| Configured native hooks | Cooperative telemetry/context only; activity is client-self-reported and coverage remains unverified |
|
|
449
456
|
| `createPassiveRuntime().install()` | Only the owned Node process, and only while that runtime is installed and running |
|
|
450
457
|
| Governed runner | Only the command launched through the wrapper |
|
|
451
458
|
| Custom host | Requires a bounded event adapter; covers only the lifecycle events whose receipts Marrow observes |
|
|
452
459
|
|
|
453
|
-
This contract is model-neutral. A model name, host header, config file, installed hook entry,
|
|
460
|
+
This contract is model-neutral. A model name, host header, API key, public hook entrypoint, config file, installed hook entry, successful MCP handshake, or client-self-reported lifecycle callback does not certify passive coverage or enforcement. 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.
|
|
454
461
|
|
|
455
462
|
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.
|
|
456
463
|
|
|
464
|
+
Setup installs distinct Claude Code and Grok hook entrypoints. The public entrypoint supplies only a client-reported display label; it is not host provenance. Hook event JSON cannot select the lifecycle harness or agent. Agent identity comes only from owner configuration when present, otherwise the request omits it so the authenticated service can derive the credential-bound identity. Every hook lifecycle event is marked `source: client_self_reported` and omits `capability_level: native_hooks`, adapter certification, configuration fingerprints, expected hooks, and observed-hook certification fields. Legacy, unknown, and custom entrypoints stay generic.
|
|
465
|
+
|
|
466
|
+
Claude Code hooks may cooperatively request guidance and apply the harness permission response, but that does not certify always-on control. Grok hooks are advisory telemetry/context only: `grok-pre-action-hook` never issues, verifies, or consumes an action permit and never claims enforcement. Codex, Grok, Gemini, and similar CLI harnesses must run consequential commands through `npx @getmarrow/install run --agent <agent-id> -- -- <command>`. Unknown and custom hosts remain on demand unless they provide a bounded event adapter, whose activity is still not certification without an independent authority.
|
|
467
|
+
|
|
457
468
|
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:
|
|
458
469
|
|
|
459
470
|
```bash
|
package/dist/cli.js
CHANGED
|
@@ -25,7 +25,6 @@ const hook_contract_2 = require("./hook-contract");
|
|
|
25
25
|
const ping_state_1 = require("./ping-state");
|
|
26
26
|
const control_path_state_1 = require("./control-path-state");
|
|
27
27
|
const redact_1 = require("./redact");
|
|
28
|
-
const runtime_contract_1 = require("./runtime-contract");
|
|
29
28
|
const status_cache_1 = require("./status-cache");
|
|
30
29
|
const habit_loop_copy_1 = require("./habit-loop-copy");
|
|
31
30
|
const host_capability_1 = require("./host-capability");
|
|
@@ -41,16 +40,16 @@ function parseArgs() {
|
|
|
41
40
|
if (args[i] === 'setup' || args[i] === '--setup') {
|
|
42
41
|
result.setup = true;
|
|
43
42
|
}
|
|
44
|
-
if (
|
|
43
|
+
if (['hook', '--hook', 'claude-hook', 'grok-hook'].includes(args[i])) {
|
|
45
44
|
result.hook = true;
|
|
46
45
|
}
|
|
47
|
-
if (
|
|
46
|
+
if (['context-hook', '--context-hook', 'claude-context-hook', 'grok-context-hook'].includes(args[i])) {
|
|
48
47
|
result.contextHook = true;
|
|
49
48
|
}
|
|
50
|
-
if (
|
|
49
|
+
if (['pre-action-hook', '--pre-action-hook', 'claude-pre-action-hook', 'grok-pre-action-hook'].includes(args[i])) {
|
|
51
50
|
result.preActionHook = true;
|
|
52
51
|
}
|
|
53
|
-
if (
|
|
52
|
+
if (['session-hook', '--session-hook', 'claude-session-hook', 'grok-session-hook'].includes(args[i])) {
|
|
54
53
|
result.sessionHook = true;
|
|
55
54
|
}
|
|
56
55
|
if (args[i] === 'spool-status' || args[i] === '--spool-status') {
|
|
@@ -163,7 +162,7 @@ function runSetup() {
|
|
|
163
162
|
|
|
164
163
|
Use Marrow according to the capability evidence returned by the MCP server:
|
|
165
164
|
|
|
166
|
-
1. **MCP baseline is on demand:** MCP transport exposes tools; it does not provide passive hooks.
|
|
165
|
+
1. **MCP baseline is on demand:** MCP transport exposes tools; it does not provide passive hooks. Public hook callbacks and local configuration are client-self-reported activity, not certified coverage.
|
|
167
166
|
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.
|
|
168
167
|
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.
|
|
169
168
|
4. **Unfinished work:** Leave pending outcomes visible. Do not invent success to clear a closure item.
|
|
@@ -173,9 +172,9 @@ Use Marrow according to the capability evidence returned by the MCP server:
|
|
|
173
172
|
|
|
174
173
|
Do not skip the gate or outcome. Marrow's value comes from controlling the action before execution and preserving evidence afterward.
|
|
175
174
|
|
|
176
|
-
Capability boundaries:
|
|
175
|
+
Capability boundaries: configured native hooks provide cooperative telemetry or context only; \`createPassiveRuntime().install()\` covers only its owned Node process while installed; a governed wrapper covers only its wrapped command; and a custom host needs a bounded event adapter. A model name, host label, API key, public hook entrypoint, installed configuration, or client-self-reported callback is not proof of coverage or enforcement. For Codex, Grok, Gemini, and similar CLI harnesses, run consequential commands through \`npx @getmarrow/install run --agent <agent-id> -- -- <command>\`.
|
|
177
176
|
|
|
178
|
-
For
|
|
177
|
+
For bounded outcome capture: \`marrow_auto({ action: "did X", outcome: "result Y", success: true })\`. One outer invocation normally completes think and commit in-band within its bounded client budget. If the host or network deadline is reached, retry with the returned \`operation_id\`; Marrow continues the same operation and never opens a second decision.
|
|
179
178
|
${MARROW_BLOCK_END}`;
|
|
180
179
|
let dir = process.cwd();
|
|
181
180
|
let claudeMdPath = null;
|
|
@@ -218,44 +217,44 @@ ${MARROW_BLOCK_END}`;
|
|
|
218
217
|
}
|
|
219
218
|
const hookInstall = (0, hook_1.installPostToolUseHook)(process.cwd());
|
|
220
219
|
if (hookInstall.installed) {
|
|
221
|
-
process.stdout.write('Configured PostToolUse hook.
|
|
220
|
+
process.stdout.write('Configured PostToolUse hook. Activity is client-self-reported and does not certify action-result coverage.\n');
|
|
222
221
|
}
|
|
223
222
|
else {
|
|
224
|
-
process.stdout.write('PostToolUse hook configuration is present.
|
|
223
|
+
process.stdout.write('PostToolUse hook configuration is present. Activity is client-self-reported and does not certify action-result coverage.\n');
|
|
225
224
|
}
|
|
226
225
|
const contextHookInstall = (0, hook_context_1.installUserPromptSubmitHook)(process.cwd());
|
|
227
226
|
if (contextHookInstall.installed) {
|
|
228
|
-
process.stdout.write('Configured UserPromptSubmit hook.
|
|
227
|
+
process.stdout.write('Configured UserPromptSubmit hook. Activity is client-self-reported and does not certify passive prompt coverage.\n');
|
|
229
228
|
}
|
|
230
229
|
else {
|
|
231
|
-
process.stdout.write('UserPromptSubmit hook configuration is present.
|
|
230
|
+
process.stdout.write('UserPromptSubmit hook configuration is present. Activity is client-self-reported and does not certify passive prompt coverage.\n');
|
|
232
231
|
}
|
|
233
232
|
const preActionHookInstall = (0, hook_pre_action_1.installPreActionHook)(process.cwd());
|
|
234
233
|
if (preActionHookInstall.installed) {
|
|
235
|
-
process.stdout.write('Configured PreToolUse hook.
|
|
234
|
+
process.stdout.write('Configured PreToolUse hook. Activity is client-self-reported and does not certify pre-action control.\n');
|
|
236
235
|
}
|
|
237
236
|
else {
|
|
238
|
-
process.stdout.write('PreToolUse hook configuration is present.
|
|
237
|
+
process.stdout.write('PreToolUse hook configuration is present. Activity is client-self-reported and does not certify pre-action control.\n');
|
|
239
238
|
}
|
|
240
239
|
const sessionHookInstall = (0, hook_session_1.installSessionEndHook)(process.cwd());
|
|
241
240
|
if (sessionHookInstall.installed) {
|
|
242
|
-
process.stdout.write('Configured Stop hook.
|
|
241
|
+
process.stdout.write('Configured Stop hook. Activity is client-self-reported and does not certify session-end coverage.\n');
|
|
243
242
|
}
|
|
244
243
|
else {
|
|
245
|
-
process.stdout.write('Stop hook configuration is present.
|
|
244
|
+
process.stdout.write('Stop hook configuration is present. Activity is client-self-reported and does not certify session-end coverage.\n');
|
|
246
245
|
}
|
|
247
246
|
const grokHookInstall = (0, hook_contract_1.installGrokNativeHooks)();
|
|
248
247
|
if (grokHookInstall.installed) {
|
|
249
|
-
process.stdout.write(`Configured Grok
|
|
248
|
+
process.stdout.write(`Configured Grok advisory hooks at ${grokHookInstall.settingsPath}. Their activity is client-self-reported and never certifies coverage or enforcement; consequential commands require npx @getmarrow/install run --agent <agent-id> -- -- <command>.\n`);
|
|
250
249
|
}
|
|
251
250
|
else {
|
|
252
|
-
process.stdout.write(`Grok
|
|
251
|
+
process.stdout.write(`Grok advisory hook configuration is present at ${grokHookInstall.settingsPath}. Its activity is client-self-reported and never certifies coverage or enforcement; consequential commands require npx @getmarrow/install run --agent <agent-id> -- -- <command>.\n`);
|
|
253
252
|
}
|
|
254
253
|
process.stdout.write(`Hook settings: ${hookInstall.settingsPath}\n`);
|
|
255
254
|
process.stdout.write('Set MARROW_AUTO_HOOK=false to disable passive hooks.\n');
|
|
256
255
|
process.stdout.write('Set MARROW_PASSIVE_BRIEF=false to disable automatic decision briefs, or MARROW_PASSIVE_BRIEF=always to brief every prompt.\n');
|
|
257
256
|
process.stdout.write('Set MARROW_HOOK_DEBUG=true for write-side hook diagnostics, or MARROW_CONTEXT_HOOK_DEBUG=true for prompt-context diagnostics.\n');
|
|
258
|
-
process.stdout.write('Setup completed. MCP tools remain on demand;
|
|
257
|
+
process.stdout.write('Setup completed. MCP tools remain on demand; configured hook activity is client-self-reported and does not certify passive coverage or enforcement.\n');
|
|
259
258
|
process.exit(0);
|
|
260
259
|
}
|
|
261
260
|
const cliArgs = parseArgs();
|
|
@@ -848,13 +847,13 @@ if (process.argv[2] !== 'keys') {
|
|
|
848
847
|
{
|
|
849
848
|
name: 'marrow_commit',
|
|
850
849
|
description: 'Close a recorded action with success/failure, a specific outcome, and required proof. ' +
|
|
851
|
-
'decision_id
|
|
850
|
+
'decision_id comes from marrow_think, marrow_auto, or an arbitration runtime that actually created a decision. ' +
|
|
852
851
|
'Use the gate receipt from marrow_agent_runtime for consequential work. ' +
|
|
853
852
|
'Outcome closure is required for accountable fleet learning.',
|
|
854
853
|
inputSchema: {
|
|
855
854
|
type: 'object',
|
|
856
855
|
properties: {
|
|
857
|
-
decision_id: { type: 'string', description: 'decision_id from marrow_think, marrow_auto, or
|
|
856
|
+
decision_id: { type: 'string', description: 'decision_id from marrow_think, marrow_auto, or an arbitration runtime that created a decision' },
|
|
858
857
|
success: { type: 'boolean', description: 'Did the action succeed?' },
|
|
859
858
|
outcome: { type: 'string', description: 'What happened — be specific, this trains the hive' },
|
|
860
859
|
caused_by: { type: 'string', description: 'Optional: what caused this action' },
|
|
@@ -903,7 +902,7 @@ if (process.argv[2] !== 'keys') {
|
|
|
903
902
|
},
|
|
904
903
|
{
|
|
905
904
|
name: 'marrow_run',
|
|
906
|
-
description: '
|
|
905
|
+
description: 'Governed outcome capture. Records intent, obtains a gate for risky work, and closes only with an explicit measured result.',
|
|
907
906
|
inputSchema: {
|
|
908
907
|
type: 'object',
|
|
909
908
|
properties: {
|
|
@@ -923,7 +922,7 @@ if (process.argv[2] !== 'keys') {
|
|
|
923
922
|
},
|
|
924
923
|
{
|
|
925
924
|
name: 'marrow_auto',
|
|
926
|
-
description: 'Durably capture low-risk activity
|
|
925
|
+
description: 'Durably capture low-risk activity. One outer invocation normally completes in-band within the bounded client budget; a deadline continuation reuses the same operation_id and never opens a second decision. Outcomes remain pending unless success is explicit; risky completion still requires a fresh gate and measured proof.',
|
|
927
926
|
inputSchema: {
|
|
928
927
|
type: 'object',
|
|
929
928
|
properties: {
|
|
@@ -937,6 +936,10 @@ if (process.argv[2] !== 'keys') {
|
|
|
937
936
|
},
|
|
938
937
|
proof: { type: 'object', description: 'Measured completion evidence for gated work.' },
|
|
939
938
|
gate_receipt_id: { type: 'string', description: 'Fresh receipt returned by marrow_agent_runtime.' },
|
|
939
|
+
operation_id: {
|
|
940
|
+
type: 'string',
|
|
941
|
+
description: 'Opaque 8-80 character resume token. Reuse it only with the original tenant, action, context, and surfaces; proof may be added after proof_required.',
|
|
942
|
+
},
|
|
940
943
|
},
|
|
941
944
|
required: ['action'],
|
|
942
945
|
},
|
|
@@ -1768,7 +1771,7 @@ if (process.argv[2] !== 'keys') {
|
|
|
1768
1771
|
prompts: [
|
|
1769
1772
|
{
|
|
1770
1773
|
name: 'marrow-always-on',
|
|
1771
|
-
description: 'Marrow control and proof contract
|
|
1774
|
+
description: 'Marrow control and proof contract. MCP tools are on demand; host activity is client-self-reported and coverage remains unverified without independent authority.',
|
|
1772
1775
|
arguments: [],
|
|
1773
1776
|
_meta: { host_capability: mcpHostCapability() },
|
|
1774
1777
|
},
|
|
@@ -1788,7 +1791,7 @@ if (process.argv[2] !== 'keys') {
|
|
|
1788
1791
|
}
|
|
1789
1792
|
const hostCapability = mcpHostCapability();
|
|
1790
1793
|
success(id, {
|
|
1791
|
-
description: 'Marrow control and proof contract —
|
|
1794
|
+
description: 'Marrow control and proof contract — MCP tools are on demand, host activity is client-self-reported, and coverage is unverified without independent authority',
|
|
1792
1795
|
_meta: { host_capability: hostCapability },
|
|
1793
1796
|
messages: [
|
|
1794
1797
|
{
|
|
@@ -1801,12 +1804,12 @@ if (process.argv[2] !== 'keys') {
|
|
|
1801
1804
|
|
|
1802
1805
|
${(0, host_capability_1.hostCapabilityInstructions)(hostCapability)}
|
|
1803
1806
|
|
|
1804
|
-
|
|
1807
|
+
Configured native hooks can cooperatively report or inject context for these bounded lifecycle stages, but their callbacks are client-self-reported activity and do not certify control:
|
|
1805
1808
|
- UserPromptSubmit can request relevant policy, warnings, lessons, and a decision brief before risky work.
|
|
1806
1809
|
- PostToolUse can record compact tool success or failure receipts.
|
|
1807
1810
|
- Stop can keep unfinished outcomes visible instead of silently treating session exit as success.
|
|
1808
1811
|
|
|
1809
|
-
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.
|
|
1812
|
+
Hooks never make a blocked action safe and are not an external execution choke point. Before a consequential action, respect the returned allow, warn, review_required, or block decision and its required proof. For Codex, Grok, Gemini, and similar CLI harnesses, use npx @getmarrow/install run --agent <agent-id> -- -- <command>.
|
|
1810
1813
|
|
|
1811
1814
|
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.
|
|
1812
1815
|
|
|
@@ -2010,35 +2013,20 @@ Marrow is not a replacement agent or a standalone memory app. Context and prior
|
|
|
2010
2013
|
const suppliedProof = args.proof && typeof args.proof === 'object' && !Array.isArray(args.proof)
|
|
2011
2014
|
? (0, redact_1.redactSensitiveValue)(args.proof)
|
|
2012
2015
|
: undefined;
|
|
2013
|
-
let runtimeGate = null;
|
|
2014
|
-
if (highRisk) {
|
|
2015
|
-
runtimeGate = await withControlDeadline((signal) => (0, index_1.marrowAgentRuntime)(API_KEY, BASE_URL, {
|
|
2016
|
-
action: (0, redact_1.redactSensitiveText)(action),
|
|
2017
|
-
type,
|
|
2018
|
-
agent_id: FLEET_AGENT_ID,
|
|
2019
|
-
session_id: SESSION_ID,
|
|
2020
|
-
proof: suppliedProof,
|
|
2021
|
-
context: { source: 'mcp_auto_risk_upgrade' },
|
|
2022
|
-
}, SESSION_ID, FLEET_AGENT_ID, signal), { highRisk: true, toolName: 'marrow_auto.runtime' });
|
|
2023
|
-
storeRuntimeGuidance(runtimeGate);
|
|
2024
|
-
}
|
|
2025
|
-
const canonicalRuntimeReceiptId = (0, runtime_contract_1.runtimeAuthorizationReceiptId)(runtimeGate);
|
|
2026
2016
|
const suppliedRuntimeReceiptId = typeof args.gate_receipt_id === 'string'
|
|
2027
2017
|
? args.gate_receipt_id
|
|
2028
|
-
:
|
|
2029
|
-
const proofCanClose = !highRisk
|
|
2030
|
-
|| (0, runtime_contract_1.highRiskRuntimeCanClose)(runtimeGate, suppliedProof, suppliedRuntimeReceiptId);
|
|
2031
|
-
const acceptedSuccess = proofCanClose ? outcomeSuccess : undefined;
|
|
2018
|
+
: undefined;
|
|
2032
2019
|
const delivery = () => (0, index_1.marrowAuto)(API_KEY, BASE_URL, {
|
|
2033
2020
|
action,
|
|
2034
2021
|
outcome,
|
|
2035
|
-
success:
|
|
2022
|
+
success: outcomeSuccess,
|
|
2036
2023
|
type,
|
|
2037
2024
|
proof: suppliedProof,
|
|
2038
2025
|
gate_receipt_id: suppliedRuntimeReceiptId || undefined,
|
|
2039
2026
|
// Low-risk one-shot capture does not need a policy gate. Consequential
|
|
2040
|
-
// work
|
|
2027
|
+
// work obtains exactly one canonical runtime authorization inside auto.
|
|
2041
2028
|
auto_gate: highRisk,
|
|
2029
|
+
operation_id: typeof args.operation_id === 'string' ? args.operation_id : undefined,
|
|
2042
2030
|
}, SESSION_ID, FLEET_AGENT_ID, 8_000);
|
|
2043
2031
|
let delivered = null;
|
|
2044
2032
|
let deliveryFailure = null;
|
|
@@ -2048,27 +2036,32 @@ Marrow is not a replacement agent or a standalone memory app. Context and prior
|
|
|
2048
2036
|
catch (err) {
|
|
2049
2037
|
deliveryFailure = (0, request_reliability_1.structuredRequestFailure)(err);
|
|
2050
2038
|
}
|
|
2039
|
+
const runtimeGate = delivered?.runtime_gate || null;
|
|
2040
|
+
if (runtimeGate)
|
|
2041
|
+
storeRuntimeGuidance(runtimeGate);
|
|
2051
2042
|
const receipt = await (0, lifecycle_spool_1.recordLifecycleEvent)({
|
|
2052
2043
|
apiKey: API_KEY,
|
|
2053
2044
|
baseUrl: BASE_URL,
|
|
2054
2045
|
deferDelivery: false,
|
|
2055
2046
|
event: {
|
|
2047
|
+
...(delivered?.operation_id ? {
|
|
2048
|
+
event_id: `auto_${delivered.committed ? 'closed' : 'pending'}_${delivered.operation_id}`,
|
|
2049
|
+
} : {}),
|
|
2056
2050
|
event_type: delivered?.committed
|
|
2057
2051
|
? 'outcome_committed'
|
|
2058
|
-
: !highRisk &&
|
|
2052
|
+
: !highRisk && outcomeSuccess === false
|
|
2059
2053
|
? 'tool_failed'
|
|
2060
|
-
: !highRisk &&
|
|
2054
|
+
: !highRisk && outcomeSuccess === true
|
|
2061
2055
|
? 'tool_completed'
|
|
2062
2056
|
: 'goal_started',
|
|
2063
2057
|
harness: process.env.MARROW_CLIENT || process.env.MARROW_HARNESS || 'mcp',
|
|
2064
2058
|
agent_id: FLEET_AGENT_ID,
|
|
2065
2059
|
session_id: SESSION_ID,
|
|
2066
|
-
decision_id: delivered?.decision_id,
|
|
2060
|
+
decision_id: delivered?.decision_id || undefined,
|
|
2067
2061
|
action,
|
|
2068
2062
|
outcome_state: delivered?.committed ? 'closed' : 'pending',
|
|
2069
|
-
success: delivered?.committed ?
|
|
2070
|
-
|
|
2071
|
-
capability_level: 'mcp',
|
|
2063
|
+
success: delivered?.committed ? outcomeSuccess : highRisk ? undefined : outcomeSuccess,
|
|
2064
|
+
source: 'client_self_reported',
|
|
2072
2065
|
},
|
|
2073
2066
|
});
|
|
2074
2067
|
const response = {
|
|
@@ -2077,20 +2070,34 @@ Marrow is not a replacement agent or a standalone memory app. Context and prior
|
|
|
2077
2070
|
warnings: cachedOrientWarnings.map(formatWarningActionably),
|
|
2078
2071
|
logging: delivered?.committed
|
|
2079
2072
|
? 'governed_commit_confirmed'
|
|
2080
|
-
: delivered
|
|
2081
|
-
? '
|
|
2082
|
-
:
|
|
2073
|
+
: delivered?.resumable
|
|
2074
|
+
? 'resume_required'
|
|
2075
|
+
: delivered
|
|
2076
|
+
? 'intent_confirmed'
|
|
2077
|
+
: 'durably_queued',
|
|
2083
2078
|
receipt,
|
|
2084
2079
|
completion_state: delivered?.committed
|
|
2085
2080
|
? 'closed_with_proof'
|
|
2086
|
-
:
|
|
2081
|
+
: delivered?.phase === 'proof_required'
|
|
2087
2082
|
? 'pending_required_proof'
|
|
2088
|
-
: outcomeSuccess === undefined
|
|
2083
|
+
: delivered?.phase === 'decision_created' || outcomeSuccess === undefined
|
|
2089
2084
|
? 'pending_evidence'
|
|
2090
2085
|
: 'delivery_pending',
|
|
2091
2086
|
decision_id: delivered?.decision_id || null,
|
|
2087
|
+
operation_id: delivered?.operation_id || (typeof args.operation_id === 'string' ? args.operation_id : null),
|
|
2088
|
+
phase: delivered?.phase || null,
|
|
2089
|
+
resumable: delivered?.resumable || false,
|
|
2090
|
+
retry_after_ms: delivered?.retry_after_ms ?? null,
|
|
2091
|
+
phase_timings_ms: delivered?.phase_timings_ms || null,
|
|
2092
|
+
exact_next_action: delivered?.committed
|
|
2093
|
+
? 'The governed outcome is closed. Reuse this decision_id only for read-only trace inspection.'
|
|
2094
|
+
: delivered?.phase === 'proof_required'
|
|
2095
|
+
? 'Attach the required measured proof and retry marrow_auto with this same operation_id and unchanged action, context, and surfaces.'
|
|
2096
|
+
: delivered?.resumable
|
|
2097
|
+
? 'Retry marrow_auto with this same operation_id. Do not start a new auto operation.'
|
|
2098
|
+
: 'Close this decision after the real outcome is known.',
|
|
2092
2099
|
live_delivery: {
|
|
2093
|
-
accepted: Boolean(delivered),
|
|
2100
|
+
accepted: Boolean(delivered?.decision_id),
|
|
2094
2101
|
committed: Boolean(delivered?.committed),
|
|
2095
2102
|
...(deliveryFailure ? { failure: deliveryFailure } : {}),
|
|
2096
2103
|
},
|