@getmarrow/install 0.1.34 → 0.1.35
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 +24 -2
- package/package.json +1 -1
- package/src/governed-runner.js +37 -0
- package/src/installer.js +20 -4
package/README.md
CHANGED
|
@@ -62,9 +62,31 @@ Required secret:
|
|
|
62
62
|
export MARROW_API_KEY=mrw_live_...
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
##
|
|
65
|
+
## Keeping Marrow Current
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
Marrow's hosted API, website, and dashboard update automatically; local SDK dependencies, generated runtime files, MCP hooks/configuration, and pinned package versions do not silently rewrite themselves. Keeping them current delivers new client-side features, compatibility improvements, and any published security fixes. Supported clients report their package version during authenticated status/runtime activity, and Marrow returns a `client_update` notice with the exact action when the version is behind or unknown.
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
npx -y @getmarrow/install@latest activate
|
|
71
|
+
npx -y @getmarrow/install@latest doctor
|
|
72
|
+
|
|
73
|
+
# Use only when doctor reports drift
|
|
74
|
+
npx -y @getmarrow/install@latest --repair
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
`activate` reconciles Marrow-managed entries while retaining unrelated user hooks and configuration. Detection and notification are automatic; local changes remain explicit and subject to the operator's normal change policy.
|
|
78
|
+
|
|
79
|
+
## What's New in v0.1.35
|
|
80
|
+
|
|
81
|
+
v0.1.35 turns server-side client update detection into a guided, low-friction operator workflow. Installer status, activation reports, and the Fleet Operator expose a request-specific advisory with the exact update and verification commands while keeping local mutation explicit:
|
|
82
|
+
|
|
83
|
+
- official installer requests identify the installed `@getmarrow/install` version;
|
|
84
|
+
- status, self-test, and Fleet Operator output show recommended, unrecognized, and security-required update states without conflating them;
|
|
85
|
+
- generated agent instructions tell the agent to notify the operator and obey local change policy;
|
|
86
|
+
- certified activation now pins MCP 3.9.51 and SDK 3.7.50, including the exact SDK registry integrity;
|
|
87
|
+
- `activate`, `doctor`, and `--repair` remain explicit commands and preserve unrelated hooks and configuration.
|
|
88
|
+
|
|
89
|
+
It preserves the passive-governance verification introduced in v0.1.34. Activation registers a bounded capability profile, a one-way configuration fingerprint, expected and observed hook surfaces, and a server-accepted lifecycle receipt. The Fleet Operator shows activation state, capture coverage, outcome closure, intervention follow-through, drift, and the exact repair:
|
|
68
90
|
|
|
69
91
|
- Claude Code installation includes exact `UserPromptSubmit`, `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, and `Stop` hooks;
|
|
70
92
|
- matching pre-action/result receipts use one tool correlation, and activation fingerprints the exact hook contract without uploading configuration contents;
|
package/package.json
CHANGED
package/src/governed-runner.js
CHANGED
|
@@ -4,6 +4,7 @@ const fs = require('node:fs');
|
|
|
4
4
|
const os = require('node:os');
|
|
5
5
|
const path = require('node:path');
|
|
6
6
|
const readline = require('node:readline');
|
|
7
|
+
const { version: INSTALLER_PACKAGE_VERSION } = require('../package.json');
|
|
7
8
|
|
|
8
9
|
const DEFAULT_BASE_URL = 'https://api.getmarrow.ai';
|
|
9
10
|
const HIGH_RISK_TERMS = /\b(deploy|prod|production|publish|release|merge|migration|migrate|secret|token|key|cloudflare|wrangler|npm publish|gh pr merge|git push|terraform apply|kubectl apply|delete|destroy|drop)\b/i;
|
|
@@ -343,6 +344,8 @@ function headers(options) {
|
|
|
343
344
|
'X-Marrow-Agent-Id': options.agentId,
|
|
344
345
|
'X-Marrow-Session-Id': options.sessionId,
|
|
345
346
|
'X-Marrow-Client': sourceClient(options.client),
|
|
347
|
+
'X-Marrow-Package': '@getmarrow/install',
|
|
348
|
+
'X-Marrow-Package-Version': INSTALLER_PACKAGE_VERSION,
|
|
346
349
|
'User-Agent': '@getmarrow/install governed-runner',
|
|
347
350
|
};
|
|
348
351
|
return h;
|
|
@@ -657,6 +660,31 @@ async function statusOnly(parsed) {
|
|
|
657
660
|
return requestJson(parsed.options, 'GET', '/v1/agent/status');
|
|
658
661
|
}
|
|
659
662
|
|
|
663
|
+
function statusPanel(status = {}) {
|
|
664
|
+
const update = status.client_update && typeof status.client_update === 'object'
|
|
665
|
+
? status.client_update
|
|
666
|
+
: null;
|
|
667
|
+
const lines = [
|
|
668
|
+
'Marrow runtime status',
|
|
669
|
+
`Health: ${displayText(firstDefined(status.health, status.status, status.ok === false ? 'degraded' : 'unknown'), 40)}`,
|
|
670
|
+
];
|
|
671
|
+
const notification = update?.notification_state || update?.notification;
|
|
672
|
+
const priority = notification === 'security_required' || notification === 'recommended'
|
|
673
|
+
? notification
|
|
674
|
+
: update?.version_status === 'unknown' || notification === 'unknown' || notification === 'version_unknown'
|
|
675
|
+
? 'version_unknown'
|
|
676
|
+
: update?.priority || 'recommended';
|
|
677
|
+
if (update && (update.update_available === true || update.version_status === 'unknown' || notification === 'unknown' || notification === 'version_unknown' || priority === 'security_required')) {
|
|
678
|
+
lines.push(`Client update: ${displayText(priority, 32)}; installed=${displayText(update.installed_version || update.current_version || 'unknown', 32)}; latest=${displayText(update.latest_version || 'unknown', 32)}`);
|
|
679
|
+
lines.push('Automatic notification: yes; automatic local mutation: no; operator policy applies.');
|
|
680
|
+
if (update.update_command || update.exact_update_command) lines.push(`Update: ${displayText(update.update_command || update.exact_update_command, 240)}`);
|
|
681
|
+
if (update.verification_command || update.exact_verification_command) lines.push(`Verify: ${displayText(update.verification_command || update.exact_verification_command, 240)}`);
|
|
682
|
+
} else {
|
|
683
|
+
lines.push('Client update: current or unavailable.');
|
|
684
|
+
}
|
|
685
|
+
return lines.join('\n');
|
|
686
|
+
}
|
|
687
|
+
|
|
660
688
|
async function optionalRequestJson(options, method, route, body) {
|
|
661
689
|
try {
|
|
662
690
|
return { ok: true, data: await requestJson(options, method, route, body) };
|
|
@@ -809,6 +837,9 @@ function normalizeFixCommands(status, capacity) {
|
|
|
809
837
|
add(status.activation_coverage?.exact_fix);
|
|
810
838
|
add(status.activation_coverage?.drift?.repair_command, true);
|
|
811
839
|
add(status.passive_activation?.exact_fix);
|
|
840
|
+
if (status.client_update?.update_available === true || status.client_update?.version_status === 'unknown' || status.client_update?.notification_state === 'unknown' || status.client_update?.notification === 'version_unknown') {
|
|
841
|
+
add(status.client_update?.update_command || status.client_update?.exact_update_command, true);
|
|
842
|
+
}
|
|
812
843
|
add(capacity.exact_next_action, true);
|
|
813
844
|
add(capacity.next_action, true);
|
|
814
845
|
if (listValue(status.missed_hooks, status.degraded_hooks).length) add('npx @getmarrow/install --repair');
|
|
@@ -944,6 +975,7 @@ function normalizeFleetSnapshot(raw, options) {
|
|
|
944
975
|
gates,
|
|
945
976
|
arbitrations,
|
|
946
977
|
activation_coverage: activationCoverage,
|
|
978
|
+
client_update: status.client_update || null,
|
|
947
979
|
agents,
|
|
948
980
|
fix_commands: fixCommands.length ? fixCommands : ['npx @getmarrow/install doctor'],
|
|
949
981
|
source_errors: errors,
|
|
@@ -1003,6 +1035,9 @@ function fleetPanel(snapshot) {
|
|
|
1003
1035
|
`Failed/stale outcomes: ${snapshot.failed_stale_outcomes}`,
|
|
1004
1036
|
`Backpressure/capacity status: ${snapshot.backpressure_status}${snapshot.capacity_next_action ? ` - ${snapshot.capacity_next_action}` : ''}`,
|
|
1005
1037
|
`Degraded hooks: ${degraded}`,
|
|
1038
|
+
snapshot.client_update && (snapshot.client_update.update_available === true || snapshot.client_update.version_status === 'unknown' || snapshot.client_update.notification_state === 'unknown' || snapshot.client_update.notification === 'version_unknown')
|
|
1039
|
+
? `Marrow client update: ${displayText(snapshot.client_update.notification_state === 'security_required' ? 'security_required' : snapshot.client_update.notification_state === 'recommended' ? 'recommended' : snapshot.client_update.version_status === 'unknown' || snapshot.client_update.notification_state === 'unknown' || snapshot.client_update.notification === 'version_unknown' ? 'version_unknown' : snapshot.client_update.priority || 'recommended', 32)}; installed=${displayText(snapshot.client_update.installed_version || snapshot.client_update.current_version || 'unknown', 32)}; latest=${displayText(snapshot.client_update.latest_version || 'unknown', 32)}; operator approval required`
|
|
1040
|
+
: 'Marrow client update: current or unavailable',
|
|
1006
1041
|
`Deploy/publish/merge gates: deploy=${snapshot.gates.deploy} publish=${snapshot.gates.publish} merge=${snapshot.gates.merge}`,
|
|
1007
1042
|
'',
|
|
1008
1043
|
'Live agent roster:',
|
|
@@ -1839,6 +1874,7 @@ async function runCli(argv) {
|
|
|
1839
1874
|
|
|
1840
1875
|
if (parsed.options?.json) process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
1841
1876
|
else if (result?.blocked) process.stderr.write(`BLOCKED: ${result.message || 'Marrow blocked this action.'}\n`);
|
|
1877
|
+
else if (parsed.command === 'status') process.stdout.write(`${statusPanel(result)}\n`);
|
|
1842
1878
|
else if (!['run', 'fleet', 'hermes', 'openclaw', 'integrations'].includes(parsed.command)) process.stdout.write('Marrow command completed.\n');
|
|
1843
1879
|
|
|
1844
1880
|
if (parsed.command === 'run' || result?.blocked) process.exitCode = result?.exitCode ?? (result?.ok === false ? 1 : 0);
|
|
@@ -1868,6 +1904,7 @@ module.exports = {
|
|
|
1868
1904
|
gateOnly,
|
|
1869
1905
|
proofOnly,
|
|
1870
1906
|
statusOnly,
|
|
1907
|
+
statusPanel,
|
|
1871
1908
|
runStatusCheck,
|
|
1872
1909
|
runGateCheck,
|
|
1873
1910
|
runGovernInteractive,
|
package/src/installer.js
CHANGED
|
@@ -2,14 +2,14 @@ const fs = require('node:fs');
|
|
|
2
2
|
const path = require('node:path');
|
|
3
3
|
const os = require('node:os');
|
|
4
4
|
const crypto = require('node:crypto');
|
|
5
|
+
const { version: INSTALLER_ADAPTER_VERSION } = require('../package.json');
|
|
5
6
|
|
|
6
7
|
const DEFAULT_BASE_URL = 'https://api.getmarrow.ai';
|
|
7
8
|
const MARROW_BLOCK_START = '<!-- marrow:passive-start -->';
|
|
8
9
|
const MARROW_BLOCK_END = '<!-- marrow:passive-end -->';
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const SDK_ADAPTER_INTEGRITY = 'sha512-9a6pWWACubWTmulG7TwwgMNP/iSzoEh4wCH2oWUyO8XHeD2Eokj1GXrkCyX86md3bV7vGX6kyllfswZDlGj6WA==';
|
|
10
|
+
const MCP_ADAPTER_VERSION = '3.9.51';
|
|
11
|
+
const SDK_ADAPTER_VERSION = '3.7.50';
|
|
12
|
+
const SDK_ADAPTER_INTEGRITY = 'sha512-TyCXUKZAaKRPdfVqXEuIvWnOt4GLcIUbwhpX+EopzdALNzq+t5wUGHrqJlkNSvopppPTTdFVLJ7O1vtwofqFqw==';
|
|
13
13
|
const SDK_ADAPTER_TARBALL = `https://registry.npmjs.org/@getmarrow/sdk/-/sdk-${SDK_ADAPTER_VERSION}.tgz`;
|
|
14
14
|
const MCP_PACKAGE_SPEC = `@getmarrow/mcp@${MCP_ADAPTER_VERSION}`;
|
|
15
15
|
const MCP_CONTEXT_HOOK_COMMAND = `npx -y ${MCP_PACKAGE_SPEC} context-hook`;
|
|
@@ -380,6 +380,7 @@ Marrow should run passively after install:
|
|
|
380
380
|
- Before risky work, use Marrow's decision brief or passive prompt hook.
|
|
381
381
|
- After meaningful work, record the outcome so future agents learn from it.
|
|
382
382
|
- Check health with \`marrow_agent_status\` or \`GET /v1/agent/status\`.
|
|
383
|
+
- When status/runtime returns a \`client_update\` notice, tell the operator and use its exact update and verification commands only when local change policy permits.
|
|
383
384
|
|
|
384
385
|
Required environment:
|
|
385
386
|
|
|
@@ -954,6 +955,8 @@ async function runSelfTest(options) {
|
|
|
954
955
|
'content-type': 'application/json',
|
|
955
956
|
'x-marrow-session-id': `install-${Date.now()}`,
|
|
956
957
|
'x-marrow-client': options.client || sourceClient(),
|
|
958
|
+
'x-marrow-package': '@getmarrow/install',
|
|
959
|
+
'x-marrow-package-version': INSTALLER_ADAPTER_VERSION,
|
|
957
960
|
};
|
|
958
961
|
if (options.agentId) headers['x-marrow-agent-id'] = options.agentId;
|
|
959
962
|
|
|
@@ -1141,6 +1144,7 @@ async function runSelfTest(options) {
|
|
|
1141
1144
|
first_value_signal: firstValueSignal,
|
|
1142
1145
|
install_value_moment: installValueMoment,
|
|
1143
1146
|
token_value_proof: tokenValueProof,
|
|
1147
|
+
client_update: status.client_update || runtime.client_update || runtime.status?.client_update || null,
|
|
1144
1148
|
performance_proof: performance && performance.ok !== false ? {
|
|
1145
1149
|
avoided_mistakes: performance.avoided_mistakes ?? performance.avoided_repeated_mistakes ?? 0,
|
|
1146
1150
|
reused_winning_decisions: performance.reused_winning_decisions ?? 0,
|
|
@@ -1299,6 +1303,18 @@ function printReport(report) {
|
|
|
1299
1303
|
process.stdout.write(`- one-call runtime: ${report.selfTest.runtime_active ? 'active' : 'not verified'}\n`);
|
|
1300
1304
|
if (report.selfTest.error) process.stdout.write(`- error: ${report.selfTest.error}\n`);
|
|
1301
1305
|
if (report.selfTest.next_action) process.stdout.write(`- next action: ${report.selfTest.next_action}\n`);
|
|
1306
|
+
const update = report.selfTest.client_update;
|
|
1307
|
+
const notification = update?.notification_state || update?.notification;
|
|
1308
|
+
if (update && (update.update_available === true || update.version_status === 'unknown' || notification === 'unknown' || notification === 'version_unknown' || notification === 'security_required')) {
|
|
1309
|
+
process.stdout.write('\nMarrow client update:\n');
|
|
1310
|
+
process.stdout.write(`- priority: ${notification === 'security_required' ? 'security_required' : notification === 'recommended' ? 'recommended' : update.version_status === 'unknown' || notification === 'unknown' || notification === 'version_unknown' ? 'version_unknown' : update.priority || 'recommended'}\n`);
|
|
1311
|
+
process.stdout.write(`- installed: ${update.installed_version || update.current_version || 'unknown'}\n`);
|
|
1312
|
+
process.stdout.write(`- latest: ${update.latest_version || 'unknown'}\n`);
|
|
1313
|
+
process.stdout.write('- automatic notification: yes\n');
|
|
1314
|
+
process.stdout.write('- automatic local mutation: no; operator policy applies\n');
|
|
1315
|
+
if (update.update_command || update.exact_update_command) process.stdout.write(`- update: ${update.update_command || update.exact_update_command}\n`);
|
|
1316
|
+
if (update.verification_command || update.exact_verification_command) process.stdout.write(`- verify: ${update.verification_command || update.exact_verification_command}\n`);
|
|
1317
|
+
}
|
|
1302
1318
|
if (report.selfTest.first_value_signal) {
|
|
1303
1319
|
process.stdout.write('\nFirst value:\n');
|
|
1304
1320
|
const valueMoment = report.selfTest.install_value_moment;
|