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>.jsonbeside the registry: who changed the workspace last, when, the lease and the commits not landed yet; unsynced, a failed write is a warning, andws deleteremoves 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).
verifyandrepairknow 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 lostjournal3.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.upgradetakes 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.gcremoves 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 MSGand bareso diff,so rebasein a workspace,so reflog NAME,so worktree list,so tag,so remote,so fetch,so push,so clone URL DIR,so log --oneline/-<n>andso diff --stat/-p/-U<n>run the SwarmOps command of the same meaning, its envelope andopincluded. A git verb with no such command (add,branch,merge,stash, …) is refused as before, exit 2, with one line first inerror.hintnaming 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 4and up), or lists a feature it lacks;detailsname theformatand thefeaturesit 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
servestep 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 throughso(the git-familiar command design, §6). git exportof a store tag that carries git's tag object writes that object byte for byte under its own id, andgit importof an annotated tag by its id into a FORMAT 3tags/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 warningannotated_tag_peeled.swarmops serveanswers native sync's wire when the ssh client asks forswarmops 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_landandwire_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 followsref set's rules,mainnever 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,cloneandfetchreach the storeswarmops serve --stdioserves over ssh ($GIT_SSH_COMMAND, elsessh), with no git mirror. A fetch adopts the upstream's changesets under their own ids and moves the tracking refsremote/<remote>/<ref>(mainandrelease/*forward only,E_REF_PROTECTEDotherwise, nothing moved); an upstream tag becomes the host tag of its name when absent, and one that differs is kept and named intag_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 isE_REMOTE_REJECTEDnot_native, with no fallback;pushandsyncof aso://remote come later.
Changed
git importandgit exportrefuse an emptygit_pathwithE_INVALID_ARG(details.reasongit_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.--humanprintsws status,log,diff,ws diff,ws commitandclonein 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,--numstator--name-statuslines 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--humantext of these operations read the envelope instead.initmakes a FORMAT 3 store when no--formatis given, andinit --format 3names it (the FORMAT 3 design §0, D3);--format 1and--format 2still make those formats. A storeinitmakes now is unreadable by v0.11.x and older, which refuse it as no store;upgradetakes an older store to FORMAT 3. Aninitthat resumes a crashedinitof another format sets that one's metadata aside, FORMAT 2's and FORMAT 3's told apart by their checkpoints.remote addandclonerefuse anhttp://orhttps://URL with any user part (https://user@host/repo.git), withE_INVALID_ARGanddetails.reasoncredential_in_url, where they took a user that did not look like a token. A remote stored ashttps://user@hostis refused byfetch,pushandsyncuntil it is removed and added again without the user, andremote listshows its user as***. An ssh URL keeps its user; a token goes by--token-envor git's credential helper.
Fixed
remote addandclonerefuse anhttp://orhttps://URL whose user is a token, as they refused a password, withE_INVALID_ARGanddetails.reasoncredential_in_url.- A remote an earlier version stored with a token as its URL's user is refused the same way by
fetch,pushandsync;remote removestill drops it: remove it, add it again without the token and pass the token with--token-env. remote listand its MCP tool show such a remote's URL with the credential replaced by***, where they printed the token;remotes.tomlkeeps what was stored.- The reference pages of the command and the MCP tool
ancestrygive 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 importrefuses a ref through an annotated tag whose head is not itsobject,typeandtaglines ended by a blank line, naming the tag as a corrupt object, where it followed the tag's first line.ws rebaserun again after an update cut short snapshots the edits made since and carries them, where it refused them withE_WS_DIRTYuntil they were discarded (the M19 design §4.4).serverecords 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 deadserveleft 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 ofmainwhile they holdserve.lock(1,001 changesets loaded on a 1,000-changeset store, 10,001 on 10,000; now 2): their exports stop atserve.git'smain.git gc --autoruns after a refresh lets the lock go. derive --followstarts at the journal's last committed frame, read under the writers' lock, where a frame cut after it started could end it withE_INVALID_ARGanddetails.after.
Security
ws createrefuses a.swarmwsthat is a link (E_WS_DIRTY) before its volume probe writes or removes a file through it; the probe wroteprobe-aandprobe-lat the link's target.- A token given as the user of an
http://orhttps://URL was stored inremotes.tomland printed byremote listwhen 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 inremotes.tomluntil the remote is removed: remove the remote, add it again without the user, and revoke the token.