@getmarrow/mcp 3.9.78 → 3.9.80

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
@@ -116,7 +116,15 @@ npx -y --package=@getmarrow/mcp@latest marrow-mcp ping
116
116
 
117
117
  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.
118
118
 
119
- ## What's New in v3.9.78
119
+ ## What's New in v3.9.80
120
+
121
+ v3.9.80 is a reliability patch for direct `marrow_think` and `marrow_commit` calls. Each invocation now carries one stable bounded idempotency key. Only the backend's documented pending-persistence states are reconciled, using the byte-identical request and key after a fixed one-second delay for at most three total attempts. A 202 response is never reported as successful completion; unknown, malformed, correlation-drifted, or exhausted pending responses fail closed with a structured error. Explicit caller-supplied idempotency keys remain unchanged, and durable `observed_unverified` outcomes retain their terminal, non-authorizing semantics.
122
+
123
+ ### Previous release: v3.9.79
124
+
125
+ v3.9.79 aligns `marrow_replay_compare` with the production replay contract. Its public MCP schema now exposes two exclusive modes: fetch an existing comparison with `comparison_id`, or create one with `source_decision_id`, `baseline.decision_id`, and `candidate.decision_id`. Empty, incomplete, mixed-mode, blank-ID, unsafe-ID, same-decision, and undeclared content-bearing fields fail locally before any request, while comparison fetches and valid distinct-decision comparisons keep their existing behavior. Outbound baseline and candidate references contain only validated decision IDs and optional privacy-safe identifier labels. Replay comparison still uses only already-recorded durable evidence and never runs a model or replays customer content. This release requires SDK `^3.7.62`, keeping the active MCP dependency floor aligned with the current SDK release.
126
+
127
+ ## Previous: v3.9.78
120
128
 
121
129
  v3.9.78 separates durable post-action observation from action authorization. For outcome closure only, `marrow_commit` sends the existing `decision_id` to runtime and can use the backend's exact `outcome_observation_only` response to submit the already-completed result without forwarding its non-durable correlation ID as receipt evidence. That response never permits an action: it has `allow: false`, `durable: false`, and no authorization. The accepted result remains `committed: false`, `outcome_state: "observed_unverified"`, `authorization_granted: false`, and `trusted_learning_applied: false`; it is terminal delivery and is not retried from the local queue. Trusted promotion requires an explicit new commit attempt with the backend-required authorization and proof for the exact observed payload. Missing, malformed, conflicting, or cross-scope runtime truth still fails closed, and privacy-unsafe `instruction_ref` values such as dates and long numeric IDs now fail locally before any network call.
122
130
 
package/dist/cli.js CHANGED
@@ -1398,10 +1398,17 @@ if (process.argv[2] !== 'keys') {
1398
1398
  'This does not run a model or replay customer content; it returns complete or insufficient_evidence.',
1399
1399
  inputSchema: {
1400
1400
  type: 'object',
1401
+ additionalProperties: false,
1401
1402
  properties: {
1402
- comparison_id: { type: 'string', description: 'Fetch a prior replay comparison by id.' },
1403
- source_decision_id: { type: 'string', description: 'Original task decision used to bind the comparison.' },
1404
- workspace_binding_id: { type: 'string', description: 'Optional privacy-safe workspace binding from runtime.' },
1403
+ comparison_id: { type: 'string', minLength: 1, description: 'Fetch a prior replay comparison by id.' },
1404
+ source_decision_id: {
1405
+ type: 'string', minLength: 1, maxLength: 128, pattern: '^[A-Za-z0-9._:-]{1,128}$',
1406
+ description: 'Original task decision used to bind the comparison.',
1407
+ },
1408
+ workspace_binding_id: {
1409
+ type: 'string', minLength: 34, maxLength: 34, pattern: '^workspace_[a-f0-9]{24}$',
1410
+ description: 'Optional privacy-safe workspace binding from runtime.',
1411
+ },
1405
1412
  constraints: {
1406
1413
  type: 'object',
1407
1414
  additionalProperties: false,
@@ -1419,16 +1426,43 @@ if (process.argv[2] !== 'keys') {
1419
1426
  },
1420
1427
  baseline: {
1421
1428
  type: 'object',
1422
- properties: { label: { type: 'string' }, decision_id: { type: 'string' } },
1429
+ additionalProperties: false,
1430
+ maxProperties: 2,
1431
+ properties: {
1432
+ label: { type: 'string', minLength: 1, maxLength: 80, pattern: '^[A-Za-z0-9._:-]{1,80}$' },
1433
+ decision_id: { type: 'string', minLength: 1, maxLength: 128, pattern: '^[A-Za-z0-9._:-]{1,128}$' },
1434
+ },
1423
1435
  required: ['decision_id'],
1424
1436
  },
1425
1437
  candidate: {
1426
1438
  type: 'object',
1427
- properties: { label: { type: 'string' }, decision_id: { type: 'string' } },
1439
+ additionalProperties: false,
1440
+ maxProperties: 2,
1441
+ properties: {
1442
+ label: { type: 'string', minLength: 1, maxLength: 80, pattern: '^[A-Za-z0-9._:-]{1,80}$' },
1443
+ decision_id: { type: 'string', minLength: 1, maxLength: 128, pattern: '^[A-Za-z0-9._:-]{1,128}$' },
1444
+ },
1428
1445
  required: ['decision_id'],
1429
1446
  },
1430
1447
  },
1431
- required: [],
1448
+ oneOf: [
1449
+ {
1450
+ required: ['comparison_id'],
1451
+ not: {
1452
+ anyOf: [
1453
+ { required: ['source_decision_id'] },
1454
+ { required: ['workspace_binding_id'] },
1455
+ { required: ['constraints'] },
1456
+ { required: ['baseline'] },
1457
+ { required: ['candidate'] },
1458
+ ],
1459
+ },
1460
+ },
1461
+ {
1462
+ required: ['source_decision_id', 'baseline', 'candidate'],
1463
+ not: { required: ['comparison_id'] },
1464
+ },
1465
+ ],
1432
1466
  },
1433
1467
  },
1434
1468
  {