@getmarrow/install 0.1.39 → 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
@@ -91,15 +91,18 @@ npx @getmarrow/install controller stop
91
91
 
92
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.
93
93
 
94
- ## What's New in v0.1.39
94
+ ## What's New in v0.1.40
95
95
 
96
- v0.1.39 installs the bounded one-call passive read contract from day one:
96
+ v0.1.40 binds governed runs to a privacy-safe workspace fingerprint and separates observed execution from verified completion:
97
97
 
98
98
  - ordinary prompts receive one compact context read; risky or mutating prompts receive one fresh runtime gate instead;
99
99
  - passive prompt telemetry is buffered locally rather than delaying the agent turn;
100
100
  - transient read failures can use clearly labeled owner-only last-known guidance, while authentication failures never use cache;
101
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.55` and SDK `3.7.54` so advertised behavior matches the deployed server contract.
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.
103
106
 
104
107
  It preserves the intervention receipts introduced in v0.1.38.
105
108
 
@@ -280,12 +283,12 @@ These are integration surfaces for one Marrow product, not separate products.
280
283
 
281
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.
282
285
 
283
- | Harnesses | Pre-action | Result | Outcome closure | Proof enforcement | Safe repair |
284
- | --- | --- | --- | --- | --- | --- |
285
- | Claude Code | Automatic native hook | Automatic native hook | Correlated when determinable | Automatic for protected actions | Managed config after activation |
286
- | Cursor, Composer, Cline, Windsurf | MCP-routed | MCP-routed | MCP-routed | Explicit or governed runner | Managed config after activation |
287
- | 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 |
288
- | 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 |
289
292
 
290
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.
291
294
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getmarrow/install",
3
- "version": "0.1.39",
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.55';
12
- const SDK_ADAPTER_VERSION = '3.7.54';
13
- const SDK_ADAPTER_INTEGRITY = 'sha512-KMgZEZpKo0AVKimXi4/SmtyPDV3mfx9hrj5drCdZxdNP8P/FL7ciyvyAEGiiXIMemh5Z3D/PUUvVO4jhr16ozQ==';
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`;