SwarmOps
ReferenceMcp toolsref_txn

Page kind: Reference

ref_txn#

Describes v0.11.0Last changed View as Markdown

Moves 1 to 64 refs as one operation, each by compare-and-swap, all of them or none: each move names its ref, expect (the full 64-hex changeset id it holds when you read it; omitted to create it) and to (omitted to delete it). Every expectation is checked first: any stale one is E_CAS_MISMATCH, every failed ref in details.mismatches, nothing written. undo of its id restores every ref at once.

Metadata
Since
0.11.0
Mutates
yes
Identity required
yes
Envelope op
ref_txn
Cli command
swarmops ref txn
Request type
RefTxnReq
Annotations
{"destructiveHint":true,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":false}
Max result chars
null
CLI command
swarmops ref txn

Input schema#

arguments is a RefTxnReq: swarmops schema RefTxnReq prints the type. A field the type does not know is ignored.

FieldTypeRequiredDefaultDescription
movesarray of objectyesThe moves: 1 to 64 (E_INVALID_ARG for none, E_TOO_LARGE past 64), each ref once.

JSON Schema#

As tools/list gives it: each $ref replaced by its definition, so that it stands alone.

JSON
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "description": "`ref_txn` (CLI `ref txn`): move several refs as one operation, each by compare-and-swap, all\nof them or none. Every expectation is checked under the store's lock\nbefore any move is made: one or more that fail make it `E_CAS_MISMATCH`, every failed ref in\n`details.mismatches`, and nothing is written. Each move follows `ref set`'s and `ref\ndelete`'s rules: `main` only along its first parents and never deleted (`E_REF_PROTECTED`), a\ntag never moved (`E_TAG_IMMUTABLE`), no remote-tracking ref (`E_REF_NAME_INVALID`).",
  "properties": {
    "moves": {
      "description": "The moves: 1 to 64 (`E_INVALID_ARG` for none, `E_TOO_LARGE` past 64), each ref once.",
      "items": {
        "description": "One move of a `ref_txn`: ref `name` from `expect` to `to`. A move that changes nothing\n(`expect` and `to` the same, or both omitted) is `E_INVALID_ARG`.",
        "properties": {
          "expect": {
            "anyOf": [
              {
                "pattern": "^[0-9a-fA-F]{64}$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The target the caller last saw, by its full changeset id, as `ref set`'s `expected_old`;\nomitted to create the ref, which must not exist."
          },
          "name": {
            "description": "The ref: `main`, `release/<name>` or a tag.",
            "type": "string"
          },
          "to": {
            "anyOf": [
              {
                "description": "A revision as the caller wrote it, for the store to resolve: a ref name (`main`,\n`release/1.2`), a full 64-hex changeset id or a unique prefix of at least 12 hex digits, or a\nref's earlier value: `<ref>@{N}` the value it held N moves before its current one (`@{0}`\nis the current value), `<ref>@{at=<unix seconds>}` the value set by its newest move\nrecorded at or before that instant (the writer's clock, moves read in journal order);\noptionally followed by `~N` for the N-th first-parent ancestor.",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The revision to point it at; omitted to delete it."
          }
        },
        "required": [
          "name"
        ],
        "type": "object"
      },
      "type": "array"
    }
  },
  "required": [
    "moves"
  ],
  "title": "RefTxnReq",
  "type": "object"
}

Annotations#

It moves or deletes refs by compare-and-swap, changing what they name. Run again with the same arguments, it finds them as it asked (already_applied) or not as it expected (E_CAS_MISMATCH), and changes nothing more.

AnnotationValueMeaning
destructiveHinttrueTrue: a tool that changes the store may overwrite or delete what is there, not only add to it.
idempotentHinttrueTrue: calling it again with the same arguments changes nothing more.
openWorldHintfalseTrue: it reaches beyond a closed set of things. Every tool here stays inside the store.
readOnlyHintfalseTrue: the tool does not change its environment, the store.

Its entry in tools/list carries no _meta.

CLI command#

swarmops ref txn runs the same operation and prints the same envelope.

Examples#

JSON
{
  "id": 45,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "moves": [
        {
          "name": "release/a",
          "to": "[c1]"
        },
        {
          "name": "release/b",
          "to": "[c1]"
        }
      ]
    },
    "name": "ref_txn"
  }
}
JSON
{
  "id": 45,
  "jsonrpc": "2.0",
  "result": {
    "content": [
      {
        "text": "{\"api\":1,\"meta\":{\"auth\":\"trust\",\"elapsed_ms\":\"[elapsed_ms]\",\"repo\":\"[tmp]/store\",\"resolved\":{\"[c1]\":\"[c1]\"}},\"ok\":true,\"op\":\"ref_txn\",\"result\":{\"id\":\"18:[crc]\",\"moves\":[{\"actor\":\"agent/worker-17\",\"at\":\"[at]\",\"name\":\"release/a\",\"new\":\"[c1]\"},{\"actor\":\"agent/worker-17\",\"at\":\"[at]\",\"name\":\"release/b\",\"new\":\"[c1]\"}],\"op\":18}}",
        "type": "text"
      }
    ],
    "isError": false,
    "structuredContent": {
      "api": 1,
      "meta": {
        "auth": "trust",
        "elapsed_ms": "[elapsed_ms]",
        "repo": "[tmp]/store",
        "resolved": {
          "[c1]": "[c1]"
        }
      },
      "ok": true,
      "op": "ref_txn",
      "result": {
        "id": "18:[crc]",
        "moves": [
          {
            "actor": "agent/worker-17",
            "at": "[at]",
            "name": "release/a",
            "new": "[c1]"
          },
          {
            "actor": "agent/worker-17",
            "at": "[at]",
            "name": "release/b",
            "new": "[c1]"
          }
        ],
        "op": 18
      }
    }
  }
}

The server ran as swarmops mcp --repo [tmp]/store --as agent/worker-17, after initialize. Recorded by the MCP tests. A name in square brackets, such as [tmp] or [c1], stands for what differs from run to run: the test's temporary directory, an id, a time, the version.

Return information#

A tool result: the envelope, whose op is ref_txn, as structuredContent and again as the text of its one content block. isError is true exactly when the envelope's ok is false. On success the envelope's result is what swarmops ref txn returns.

Errors#

A failed call is a tool result with isError: true; the envelope's error.code is one of the error codes.

  • E_INVALID_ARG: arguments that do not fit RefTxnReq, a field named twice among them included, or that break one of the server's own rules.
  • E_IDENTITY_REQUIRED: the server runs with no identity.
  • E_NOT_A_REPO: the server's store is not there; the server serves on.
  • E_INTERNAL: the operation panicked, a bug.

Then the errors of the operation, as swarmops ref txn lists them.

See also#

On this page