SwarmOps
Search/v0.11.0

On stable now

What this site was built from, and what stable holds that no release does yet.

Commit
6c387504, 2026-11-13
Branch
stable
Latest release
v0.11.0, 2026-11-09
Since the release
421 commits, 4 days
Release cadence
A release follows the last within 7 days or 200 commits. Over: 421 commits since the release; the limit is 200.

Not released yet (28)

Added

  • Each workspace mutation that succeeds records its holder in workspaces/hold/<name>.json beside the registry: who changed the workspace last, when, the lease and the commits not landed yet; unsynced, a failed write is a warning, and ws delete removes it.
  • The MCP reference's index lists each command that has no tool with the reason it has none; a test fails on a command that has neither a tool nor a reason (the M21 design §2.5).
  • verify and repair know FORMAT 3 stores (the FORMAT 3 design §2.3, §2.5, §2.8). Verify names a manifest whose runs do not split the records (broken_partition), a run file failing its CRC (run_crc), a frame without its nonce (missing_nonce), a lost journal3.ckpt (base_seq_lost) and a fact written before its feature (feature_unlisted), and looks for the blobs facts name as it looks for those trees name. Repair rebuilds the fact rows and the runs, and finds a lost base seq in the journal again. No release makes a FORMAT 3 store yet.
  • upgrade takes a FORMAT 2 store to FORMAT 3, and a FORMAT 1 store through FORMAT 2 to FORMAT 3 in the same call, keeping every operation id (the FORMAT 3 design §3). Irreversible: v0.11.x and older do not open the store afterwards. gc removes what an upgrade to FORMAT 3 that stopped before its commit point left and FORMAT 2's sorted views of an upgraded store, and counts no blob a fact names as an orphan.
  • git's verbs on the command line (the git-familiar command design, §3 to §5): so status, so restore PATH..., so commit -m MSG and bare so diff, so rebase in a workspace, so reflog NAME, so worktree list, so tag, so remote, so fetch, so push, so clone URL DIR, so log --oneline/-<n> and so diff --stat/-p/-U<n> run the SwarmOps command of the same meaning, its envelope and op included. A git verb with no such command (add, branch, merge, stash, …) is refused as before, exit 2, with one line first in error.hint naming what to type. A line that parsed before runs as before; below a workspace's root a line that names paths is refused, since paths are read from the root.
  • A FORMAT 3 store holds git's annotated tag objects (the annotated tags design §2): the object's bytes as a blob, named by a Tag fact under the feature tag_object, created with its tag ref in one frame, at most 64 tags a frame. No command writes one yet. A tag never moves; FORMAT 2 keeps lightweight tags only. A build released before this one does not open a store that holds an annotated tag.
  • E_STORE_TOO_NEW (exit 1, not retryable): the store is of a format later than this build reads (swarmops-store 4 and up), or lists a feature it lacks; details name the format and the features it lacks, and the hint says a newer swarmops reads the store. Nothing is written. Golden envelopes now pin 56 of the 56 error codes (the FORMAT 3 design §4).
  • After an operation that committed, the CLI, the MCP server and serve step the view work the commit left once the response is out; a step's error goes to stderr and never changes the operation's result (the FORMAT 3 design, amendment G6, G12).
  • The reference page "Coming from git" (docs/reference/coming-from-git.md): each of 49 git commands with what to type instead, the operation its example runs or the hint its refusal carries, and what is not done on purpose. It is generated from the table the binary reads git's verbs from, and a test runs every row's example through so (the git-familiar command design, §6).
  • git export of a store tag that carries git's tag object writes that object byte for byte under its own id, and git import of an annotated tag by its id into a FORMAT 3 tags/ target keeps the object (the annotated tags design §2.3, §2.4). A tag of a tag, of a tree or blob, or of a commit that would export as another is refused; FORMAT 2 peels the tag as before, with the warning annotated_tag_peeled.
  • swarmops serve answers native sync's wire when the ssh client asks for swarmops serve --stdio '<store>' through the key's forced command (the native sync design §2): wire_hello, wire_refs, wire_list, wire_get, wire_has, wire_put, wire_land and wire_move, one envelope line per request. Only objects a listed ref reaches are sent; a land is keyed by its target and head (ss1-); a move follows ref set's rules, main never forced or deleted. No host connects to it yet.
  • so://[user@]host[:port]/<store> remotes (the native sync design §2.1, §2.4): remote add, clone and fetch reach the store swarmops serve --stdio serves over ssh ($GIT_SSH_COMMAND, else ssh), with no git mirror. A fetch adopts the upstream's changesets under their own ids and moves the tracking refs remote/<remote>/<ref> (main and release/* forward only, E_REF_PROTECTED otherwise, nothing moved); an upstream tag becomes the host tag of its name when absent, and one that differs is kept and named in tag_differs. A cut fetch run again asks for no object it stored. Git ids in the answer are the commits the changesets export to. A server without native sync is E_REMOTE_REJECTED not_native, with no fallback; push and sync of a so:// remote come later.

Changed

  • git import and git export refuse an empty git_path with E_INVALID_ARG (details.reason git_path_empty), before any repository is opened. It was read as the working directory: at a work tree's root the commands read or wrote that repository.
  • --human prints ws status, log, diff, ws diff, ws commit and clone in git's shape (the git-familiar command design, §3 "Text shapes"): ## <name> <head> and one <letter> <path> line a change, <id> <title> a changeset, a patch, --numstat or --name-status lines by the diff's format, [<id>] <n> files changed. Ids are cut to 12 hex digits. git's shape flags (so status -s, so log --oneline, so diff --stat) print this text. The JSON envelope is unchanged; scripts that read --human text of these operations read the envelope instead.
  • init makes a FORMAT 3 store when no --format is given, and init --format 3 names it (the FORMAT 3 design §0, D3); --format 1 and --format 2 still make those formats. A store init makes now is unreadable by v0.11.x and older, which refuse it as no store; upgrade takes an older store to FORMAT 3. An init that resumes a crashed init of another format sets that one's metadata aside, FORMAT 2's and FORMAT 3's told apart by their checkpoints.
  • remote add and clone refuse an http:// or https:// URL with any user part (https://user@host/repo.git), with E_INVALID_ARG and details.reason credential_in_url, where they took a user that did not look like a token. A remote stored as https://user@host is refused by fetch, push and sync until it is removed and added again without the user, and remote list shows its user as ***. An ssh URL keeps its user; a token goes by --token-env or git's credential helper.

Fixed

  • remote add and clone refuse an http:// or https:// URL whose user is a token, as they refused a password, with E_INVALID_ARG and details.reason credential_in_url.
  • A remote an earlier version stored with a token as its URL's user is refused the same way by fetch, push and sync; remote remove still drops it: remove it, add it again without the token and pass the token with --token-env.
  • remote list and its MCP tool show such a remote's URL with the credential replaced by ***, where they printed the token; remotes.toml keeps what was stored.
  • The reference pages of the command and the MCP tool ancestry give the release it first shipped in, since: "0.9.0", where they said 0.1.0.
  • The gate's doc runs start from an empty doc directory (CI doc step from about 14 minutes to seconds).
  • git import refuses a ref through an annotated tag whose head is not its object, type and tag lines ended by a blank line, naming the tag as a corrupt object, where it followed the tag's first line.
  • ws rebase run again after an update cut short snapshots the edits made since and carries them, where it refused them with E_WS_DIRTY until they were discarded (the M19 design §4.4).
  • serve records a push its hooks refuse with the refusal's code and exit, not exit 0, keeps the split of a second pack on one connection, and removes splits a dead serve left behind.
  • A push of a branch new to serve.git, and a connection's refresh of a store ref new there, no longer walk every loose commit of main while they hold serve.lock (1,001 changesets loaded on a 1,000-changeset store, 10,001 on 10,000; now 2): their exports stop at serve.git's main. git gc --auto runs after a refresh lets the lock go.
  • derive --follow starts at the journal's last committed frame, read under the writers' lock, where a frame cut after it started could end it with E_INVALID_ARG and details.after.

Security

  • ws create refuses a .swarmws that is a link (E_WS_DIRTY) before its volume probe writes or removes a file through it; the probe wrote probe-a and probe-l at the link's target.
  • A token given as the user of an http:// or https:// URL was stored in remotes.toml and printed by remote list when it was shorter than 20 characters or held no letter or no digit: the check took it for a user name (0.2.0 to 0.11.0). No user part is taken now, so no shape of token passes. A token stored this way stays in remotes.toml until the remote is removed: remove the remote, add it again without the user, and revoke the token.

The full text in the changelogMilestones on the roadmap