@getmarrow/install 0.1.38 → 0.1.40
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 +25 -7
- package/package.json +1 -1
- package/src/governed-runner.js +47 -3
- package/src/installer.js +5 -3
package/README.md
CHANGED
|
@@ -70,6 +70,9 @@ Marrow's hosted API, website, and dashboard update automatically; local SDK depe
|
|
|
70
70
|
npx -y @getmarrow/install@latest activate
|
|
71
71
|
npx -y @getmarrow/install@latest doctor
|
|
72
72
|
|
|
73
|
+
# Measured API read health and local backlog
|
|
74
|
+
npx -y @getmarrow/mcp@latest ping
|
|
75
|
+
|
|
73
76
|
# Use only when doctor reports drift
|
|
74
77
|
npx -y @getmarrow/install@latest --repair
|
|
75
78
|
```
|
|
@@ -88,7 +91,22 @@ npx @getmarrow/install controller stop
|
|
|
88
91
|
|
|
89
92
|
Persistent controller lifecycle is currently Linux-only. On macOS or Windows, activation still installs and verifies the supported hooks without starting or signaling a background process; run `npx @getmarrow/install sidecar` under an owner-managed service and pass `--no-controller`. The controller does not silently upgrade packages, change governance policy, rotate credentials, or modify unrelated project configuration.
|
|
90
93
|
|
|
91
|
-
## What's New in v0.1.
|
|
94
|
+
## What's New in v0.1.40
|
|
95
|
+
|
|
96
|
+
v0.1.40 binds governed runs to a privacy-safe workspace fingerprint and separates observed execution from verified completion:
|
|
97
|
+
|
|
98
|
+
- ordinary prompts receive one compact context read; risky or mutating prompts receive one fresh runtime gate instead;
|
|
99
|
+
- passive prompt telemetry is buffered locally rather than delaying the agent turn;
|
|
100
|
+
- transient read failures can use clearly labeled owner-only last-known guidance, while authentication failures never use cache;
|
|
101
|
+
- `doctor` prints the exact `npx -y @getmarrow/mcp@latest ping` command for measured current/p50/p99 latency, last success, and backlog health;
|
|
102
|
+
- certified hook commands pin MCP `3.9.56` and SDK `3.7.55` so advertised behavior matches the deployed server contract;
|
|
103
|
+
- governed runtime requests attach a stable privacy-safe project fingerprint and harness label without sending the raw working-directory path;
|
|
104
|
+
- successful command exit remains observed execution, not verified business completion, unless a verification command or explicit proof file supplies evidence;
|
|
105
|
+
- the integration matrix now reports prompt injection, pre-action, action result, closure, proof, cached brief, restart survival, evidence adapter, and safe repair separately.
|
|
106
|
+
|
|
107
|
+
It preserves the intervention receipts introduced in v0.1.38.
|
|
108
|
+
|
|
109
|
+
## Previous: v0.1.38
|
|
92
110
|
|
|
93
111
|
v0.1.38 makes a meaningful Marrow intervention visible without adding manual work to routine agent sessions:
|
|
94
112
|
|
|
@@ -265,12 +283,12 @@ These are integration surfaces for one Marrow product, not separate products.
|
|
|
265
283
|
|
|
266
284
|
Run `npx @getmarrow/install integrations --json` for the machine-readable matrix. The table below intentionally distinguishes full automatic interception from MCP-routed, wrapper-bounded, and adapter-required coverage.
|
|
267
285
|
|
|
268
|
-
| Harnesses |
|
|
269
|
-
| --- | --- | --- | --- | --- | --- |
|
|
270
|
-
| Claude Code | Automatic native
|
|
271
|
-
| Cursor, Composer, Cline, Windsurf | MCP-routed | MCP-routed |
|
|
272
|
-
| Codex, OpenCode, Gemini, Grok, DeepSeek, Qwen, Kimi, MiniMax, GLM | Automatic inside governed runner | Automatic
|
|
273
|
-
| Hermes, OpenClaw, custom harnesses |
|
|
286
|
+
| Harnesses | Prompt / pre-action / result | Closure and proof | Cached brief | Restart survival | Evidence adapter | Safe repair |
|
|
287
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
288
|
+
| Claude Code | Automatic native hooks | Correlated when determinable; protected proof enforced | Owner-only bounded cache | Installed config and durable spool | Native hook evidence | Managed config after activation |
|
|
289
|
+
| Cursor, Composer, Cline, Windsurf | MCP-routed only | MCP-routed; explicit or governed proof | Owner-only MCP cache | MCP config and durable spool | MCP lifecycle evidence | Managed config after activation |
|
|
290
|
+
| Codex, OpenCode, Gemini, Grok, DeepSeek, Qwen, Kimi, MiniMax, GLM | Automatic only inside governed runner | Automatic when result is known; protected proof enforced | Runner/runtime cache | Activated controller and durable buffer | Command, test, deployment, or owner evidence | Managed config after activation |
|
|
291
|
+
| Hermes, OpenClaw, custom harnesses | Lifecycle adapter required | Adapter or governed runner required | Adapter dependent | Adapter dependent | Adapter supplied | Adapter owned |
|
|
274
292
|
|
|
275
293
|
For native hooks, a successful tool exit is not treated as a successful business outcome when proof is missing. MCP coverage includes only actions routed through that MCP client. Governed-runner coverage includes only commands launched through the runner. Event-contract integrations must emit the documented lifecycle themselves.
|
|
276
294
|
|
package/package.json
CHANGED
package/src/governed-runner.js
CHANGED
|
@@ -319,7 +319,7 @@ function detectProjectSignals(cwd = process.cwd()) {
|
|
|
319
319
|
}
|
|
320
320
|
}
|
|
321
321
|
|
|
322
|
-
|
|
322
|
+
const project = {
|
|
323
323
|
name: packageJson?.name || path.basename(cwd),
|
|
324
324
|
key: packageJson?.name || path.basename(cwd),
|
|
325
325
|
type: packageJson ? 'node' : fs.existsSync(path.join(cwd, 'pyproject.toml')) ? 'python' : 'workspace',
|
|
@@ -328,6 +328,15 @@ function detectProjectSignals(cwd = process.cwd()) {
|
|
|
328
328
|
package_scripts: packageScripts.slice(0, 30),
|
|
329
329
|
config_files: configFiles.slice(0, 30),
|
|
330
330
|
};
|
|
331
|
+
project.fingerprint = crypto.createHash('sha256').update(JSON.stringify({
|
|
332
|
+
name: project.name,
|
|
333
|
+
type: project.type,
|
|
334
|
+
frameworks: [...project.frameworks].sort(),
|
|
335
|
+
signals: [...project.signals].sort(),
|
|
336
|
+
package_scripts: [...project.package_scripts].sort(),
|
|
337
|
+
config_files: [...project.config_files].sort(),
|
|
338
|
+
})).digest('hex');
|
|
339
|
+
return project;
|
|
331
340
|
}
|
|
332
341
|
|
|
333
342
|
function isRisky(text, type) {
|
|
@@ -525,12 +534,25 @@ function proofFromFile(filePath) {
|
|
|
525
534
|
|
|
526
535
|
function defaultProof(input) {
|
|
527
536
|
const proof = proofFromFile(input.options.proofFile) || {};
|
|
537
|
+
const command = redactedCommand(input.childCommand || []);
|
|
538
|
+
const verificationCommand = /\b(test|smoke|check|verify|lint|typecheck|audit)\b/i.test(command);
|
|
539
|
+
const suppliedChecks = Array.isArray(proof.checks) && proof.checks.length > 0;
|
|
540
|
+
const evidenceState = typeof proof.evidence_state === 'string'
|
|
541
|
+
? proof.evidence_state
|
|
542
|
+
: input.success && (suppliedChecks || verificationCommand)
|
|
543
|
+
? 'verified'
|
|
544
|
+
: input.success
|
|
545
|
+
? 'observed_only'
|
|
546
|
+
: 'failed';
|
|
528
547
|
return {
|
|
529
548
|
summary: proof.summary || `Marrow governed runner completed ${input.action}.`,
|
|
530
|
-
checks:
|
|
549
|
+
checks: suppliedChecks ? proof.checks : [`command_exit_code=${Number(input.exitCode)}`],
|
|
550
|
+
evidence_source: proof.evidence_source || (verificationCommand ? 'verification_command_result' : 'governed_command_result'),
|
|
551
|
+
evidence_state: evidenceState,
|
|
552
|
+
verified_completion: evidenceState === 'verified',
|
|
531
553
|
outcome: proof.outcome || (input.success ? 'success' : 'failure'),
|
|
532
554
|
blockers: Array.isArray(proof.blockers) ? proof.blockers : [],
|
|
533
|
-
command
|
|
555
|
+
command,
|
|
534
556
|
exit_code: input.exitCode,
|
|
535
557
|
runner: '@getmarrow/install run',
|
|
536
558
|
profile: input.options.profile,
|
|
@@ -544,11 +566,14 @@ async function preflightRuntime(options, action, type, commandText) {
|
|
|
544
566
|
const target = options.target || commandText || action;
|
|
545
567
|
const surfaces = inferSurfaces(commandText || action);
|
|
546
568
|
const meta = sourceMeta(options, 'runtime', { action, command: commandText, action_type: type });
|
|
569
|
+
const project = detectProjectSignals(options.root || process.cwd());
|
|
547
570
|
return requestJson(options, 'POST', '/v1/agent/runtime', {
|
|
548
571
|
action,
|
|
549
572
|
type,
|
|
550
573
|
target,
|
|
551
574
|
surfaces,
|
|
575
|
+
harness: sourceClient(options.client),
|
|
576
|
+
project: { ...project, harness: sourceClient(options.client) },
|
|
552
577
|
source_meta: meta,
|
|
553
578
|
context: {
|
|
554
579
|
runner: '@getmarrow/install run',
|
|
@@ -1398,6 +1423,15 @@ function integrationCoverageMatrix() {
|
|
|
1398
1423
|
harness: entry.client,
|
|
1399
1424
|
capability_level: entry.capability_level,
|
|
1400
1425
|
install_surface: entry.install_surface,
|
|
1426
|
+
prompt_injection: native
|
|
1427
|
+
? 'automatic_native_hook'
|
|
1428
|
+
: wrapper
|
|
1429
|
+
? 'automatic_in_governed_runner'
|
|
1430
|
+
: sdk
|
|
1431
|
+
? 'automatic_in_sdk_runtime'
|
|
1432
|
+
: routed
|
|
1433
|
+
? 'mcp_routed'
|
|
1434
|
+
: 'adapter_required',
|
|
1401
1435
|
pre_action: native
|
|
1402
1436
|
? 'automatic_native_hook'
|
|
1403
1437
|
: wrapper
|
|
@@ -1429,6 +1463,15 @@ function integrationCoverageMatrix() {
|
|
|
1429
1463
|
? 'explicit_or_governed_wrapper'
|
|
1430
1464
|
: 'adapter_required',
|
|
1431
1465
|
automatic_repair: native || routed || sdk || wrapper ? 'installer_managed_config_only' : 'adapter_owned',
|
|
1466
|
+
cached_brief: native || routed ? 'mcp_local_last_known' : wrapper || sdk ? 'server_cache_only' : 'adapter_owned',
|
|
1467
|
+
restart_survival: native || routed || sdk || wrapper ? 'installer_managed_credentials_and_hooks' : 'adapter_owned',
|
|
1468
|
+
evidence_adapter: native
|
|
1469
|
+
? 'tool_result_and_explicit_verification'
|
|
1470
|
+
: routed
|
|
1471
|
+
? 'mcp_tool_and_explicit_verification'
|
|
1472
|
+
: wrapper || sdk
|
|
1473
|
+
? 'command_exit_and_verification_command'
|
|
1474
|
+
: 'adapter_owned',
|
|
1432
1475
|
limitation: native
|
|
1433
1476
|
? 'A successful tool exit is not treated as a successful business outcome when the result cannot be proven.'
|
|
1434
1477
|
: routed
|
|
@@ -2272,6 +2315,7 @@ module.exports = {
|
|
|
2272
2315
|
commandForSelection,
|
|
2273
2316
|
buildGovernState,
|
|
2274
2317
|
detectProjectSignals,
|
|
2318
|
+
defaultProof,
|
|
2275
2319
|
recommendGovernanceMode,
|
|
2276
2320
|
recordGovernanceModeSelection,
|
|
2277
2321
|
gateDecision,
|
package/src/installer.js
CHANGED
|
@@ -8,9 +8,9 @@ const { controllerStatus, controllerSupportedPlatform, ensureGovernanceControlle
|
|
|
8
8
|
const DEFAULT_BASE_URL = 'https://api.getmarrow.ai';
|
|
9
9
|
const MARROW_BLOCK_START = '<!-- marrow:passive-start -->';
|
|
10
10
|
const MARROW_BLOCK_END = '<!-- marrow:passive-end -->';
|
|
11
|
-
const MCP_ADAPTER_VERSION = '3.9.
|
|
12
|
-
const SDK_ADAPTER_VERSION = '3.7.
|
|
13
|
-
const SDK_ADAPTER_INTEGRITY = 'sha512-
|
|
11
|
+
const MCP_ADAPTER_VERSION = '3.9.56';
|
|
12
|
+
const SDK_ADAPTER_VERSION = '3.7.55';
|
|
13
|
+
const SDK_ADAPTER_INTEGRITY = 'sha512-aq8g3srJ9EFZVvskSQVE9MLUS8SSkvx3xY3Mr9G0ZkpKxiiDBQaa3r2pb/u74BYGVvJRP6EP/oV/D9jbKb2lBA==';
|
|
14
14
|
const SDK_ADAPTER_TARBALL = `https://registry.npmjs.org/@getmarrow/sdk/-/sdk-${SDK_ADAPTER_VERSION}.tgz`;
|
|
15
15
|
const MCP_PACKAGE_SPEC = `@getmarrow/mcp@${MCP_ADAPTER_VERSION}`;
|
|
16
16
|
const MCP_CONTEXT_HOOK_COMMAND = `npx -y ${MCP_PACKAGE_SPEC} context-hook`;
|
|
@@ -1531,6 +1531,7 @@ function printReport(report) {
|
|
|
1531
1531
|
if (report.doctor.envHints.length) process.stdout.write(`- possible env files: ${report.doctor.envHints.join(', ')}\n`);
|
|
1532
1532
|
process.stdout.write(`- missing hooks/config: ${report.doctor.missingHooks.length ? report.doctor.missingHooks.join('; ') : 'none'}\n`);
|
|
1533
1533
|
if (report.doctor.recommendedFix) process.stdout.write(`- recommended fix: ${report.doctor.recommendedFix}\n`);
|
|
1534
|
+
process.stdout.write(`- live health: ${report.doctor.healthCommand}\n`);
|
|
1534
1535
|
}
|
|
1535
1536
|
|
|
1536
1537
|
if (report.writeMode === 'dry-run') {
|
|
@@ -1685,6 +1686,7 @@ async function install(options) {
|
|
|
1685
1686
|
? `MARROW_API_KEY was found in a likely env file at ${envHints[0]}. Load that key from trusted secret storage, export only MARROW_API_KEY, then run npx @getmarrow/install --repair.`
|
|
1686
1687
|
: 'Set MARROW_API_KEY, then run npx @getmarrow/install --repair.'
|
|
1687
1688
|
: controller.exact_fix || selfTest.recommended_fix || null),
|
|
1689
|
+
healthCommand: 'npx -y @getmarrow/mcp@latest ping',
|
|
1688
1690
|
},
|
|
1689
1691
|
remediation,
|
|
1690
1692
|
configDiagnostics,
|