@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 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.38
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 | Pre-action | Result | Outcome closure | Proof enforcement | Safe repair |
269
- | --- | --- | --- | --- | --- | --- |
270
- | Claude Code | Automatic native hook | Automatic native hook | Correlated when determinable | Automatic for protected actions | Managed config after activation |
271
- | Cursor, Composer, Cline, Windsurf | MCP-routed | MCP-routed | MCP-routed | Explicit or governed runner | Managed config after activation |
272
- | Codex, OpenCode, Gemini, Grok, DeepSeek, Qwen, Kimi, MiniMax, GLM | Automatic inside governed runner | Automatic inside governed runner | Automatic when result is known | Automatic for protected actions | Managed config after activation |
273
- | Hermes, OpenClaw, custom harnesses | Adapter required | Adapter required | Adapter required | Adapter required | Adapter owned |
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getmarrow/install",
3
- "version": "0.1.38",
3
+ "version": "0.1.40",
4
4
  "description": "Universal installer and governed runner for Marrow agent fleets.",
5
5
  "bin": {
6
6
  "marrow-install": "bin/marrow-install.js"
@@ -319,7 +319,7 @@ function detectProjectSignals(cwd = process.cwd()) {
319
319
  }
320
320
  }
321
321
 
322
- return {
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: Array.isArray(proof.checks) ? proof.checks : ['marrow runtime gate', 'command exit captured'],
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: redactedCommand(input.childCommand || []),
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.54';
12
- const SDK_ADAPTER_VERSION = '3.7.53';
13
- const SDK_ADAPTER_INTEGRITY = 'sha512-CKPVR9gf24mNvZIcFvKhHGZSsUhxa0uDg/bN4dktLlttB/EU/p6CEVWmGqZmxDTnfp4I+qqdJUpzuQSnkNhaIA==';
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,