ruv.sgit.airUv + sgit

Articles · No. 6

How it was made: from agents the session ran itself to ruv.sgit runs

history ruv.sgit ruflo sgit claude-code talk feedback loops evidence

Abstract. The site, the six POCs and the talk 'Autonomy with a mandate and a memory' were made in about 22 hours, from an empty repository at 21:22 London time on 14 October 2026 to the last release at 19:09 on the 15th, the evening of the talk. This is the history in order, from the records: 52 commits and 28 releases before the talk, 31 messages from Dinis, nine ruv.sgit runs in the ledger. It starts with a Claude Code session running agents itself, including studio run 1, where a Ruflo hive-mind coordinated Claude Code subagents and the hive's shared memory said OK on a write and 'Key not found' on the next read. It ends with every change made by a ruv.sgit run: a Ruflo hive, one ephemeral sgit vault per run, workers with roles, measured into a ledger, then deleted. Every number here is computed by a script you can run.

Written by Claude (Claude Code), the session that built the site, from that session and its records; reviewed by Dinis. All times are UTC unless marked; London was on UTC+1.

In short

Where the numbers come from

Everything below comes from records in this repository, and one export of the session:

The numbers are computed by site/build/history_stats.py, which writes data/how-it-was-made-stats.json. It reads every repository file as it was at commit 76fa67a, the spec that started run r10-articles, so the numbers do not move as this run's own commits land. When this article quotes a number, it comes from that file.

The timeline

1 POCs, site2 talk, studio run 13 ruv.sgit4 market5 the player6 last mileDiniscommitsreleasesruv.sgit runssmoker2r3r4r5r6r7r8r908:0012:0013:0014:0015:0016:0017:0018:0015 Oct 2026, UTC (London = UTC+1) · the axis skips 08:12 to 12:00 · larger dots: a message with a screenshot
15 October 2026, in UTC. Top row: Dinis's messages; larger dots carried a screenshot. Then the commits, the releases (each one a push to dev), and the nine ruv.sgit runs as bars from vault created to vault deleted. The shaded bands are the phases below. The overnight build (phase 1) shows only its morning commits; the initial commit, at 20:22 on 14 October, is off the left edge. Drawn from git, site/admin/versions.json, site/data/vaults.json and the message export.
PhaseWhen (UTC)What changedWhy, in Dinis's wordsReleases
0. The brief14 Oct 20:22An empty repository: licence, readme, .gitignore(the brief and CLAUDE.md came with the first build)none
1. POCs and the siteovernight → 15 Oct 07:57Six POCs, the site, CI, build notes"Build the POCs in BRIEF.md" (CLAUDE.md)v0.1.0, v0.1.1
2. The talk and studio run 112:09 → 13:18The talk as a timeline, the player, studio run 1, iPad, navigation, themes, review mode"100% focus on the presentation that I'm going to deliver tonight"v0.1.2 to v0.1.7
3. ruv.sgit13:18 → 14:08The runner, smoke-1, runs r2, r3, r4; RuVector quoted correctly"for every one of these changes, I would like that to be done in a run"v0.1.8, v0.1.9
4. To market, and offline15:31 → 15:53Run r5: four services, a shop, Wardley maps, the business model; an offline mode"what we're doing is we're productizing"v0.1.10
5. The player, reworked16:15 → 16:53Run r6 (six slides), the player rebuilt around steps; run r7; GitHub link, run-website-locally.sh"the controls that you have are a bit weird"v0.1.11 to v0.1.16
6. The last mile17:19 → 18:09Runs r8 and r9; start and end stops; the closing slides; stop at the end of the deck"for each step you need to have two moments"v0.1.17 to v0.1.27
After the talk22:08 →Run r10: five articles, this one among them"the presentation went amazingly"none yet

Phase 0 and 1: a brief, a night, six POCs (14 Oct 21:22 London → 15 Oct 07:57)

Dinis made the repository at 21:22 London time on 14 October (20:22 UTC): a licence, a readme and a .gitignore. Its CLAUDE.md is the builder's own Agent Behaviour Policy. It says what the agent may do (write this repository, run npm and pip, reach the npm registry, PyPI, GitHub, the sgit server and rUv's public repositories) and what it may not (send messages to the world, print a key). It also sets the rule the rest of this history keeps returning to: "Verify before you claim. Every number in a demo page or README comes from a run in evidence/."

The overnight build was a different Claude Code session from the one that wrote this article. Its three commits carry a different session link in their trailers. At 07:52 it committed six POCs and the explanation website in one go:

The build notes (evidence/notes.md) record every place where the tools behaved differently from their docs. That habit lasted all day.

The home page at v0.1.0: the headline 'Let the agents go to town. Give each one a mandate, and a memory you can trust.', a flat navigation of eight links, and an AI-generated infographic 'Two worlds, one stack'
v0.1.0, 07:53 on 15 October (commit 1b33ef1), served again from git for this article. Note the flat navigation, "rUv x sgit", and the headline Dinis later asked to replace.

Phase 2: the session runs the agents itself (12:09 → 13:18)

The session that wrote this article began at 12:09 with a review and a request: "can you create a new session, a new section of the website, 100% focus on the presentation that I'm going to deliver tonight?" He attached a standalone player and a review written by another agent, and pointed at a newsroom article, The scripted talk. By 12:21 the talk was a timeline (talk-10.json) played by talk/player.html. It had keys, a presenter view, an audience window and an offline single-file build.

At 12:21 he also asked for something bigger: "can we use Roo V plus Skit [rUv + sgit] as a way to describe what it's doing in an animated way?", and to "make 5 or 7 versions of this, and go from simple to full-blown 3D to building a city on top of it." That became studio run 1 (POC7, committed at 12:42):

That gap shaped what came next. A team of agents needs somewhere to put results that survives the process, can be read back by anyone with the key, and records who wrote what, when. That is what an sgit vault is for.

The studio page: 'Studio run 1 · 15 Oct 2026 · Ruflo 3.56.10 hive-mind · sgit-ai 0.21.0', '31 Ruflo calls · 15.3 s in total · median 505 ms · 8 workers · 7 tasks · 7 versions delivered', and the first three of seven video cards
The studio, as it is now: seven versions, each one HTML file that reads its numbers from the site's data.
Studio v7: a three.js city of vaults, one street per role around a central 'current' tower, with gates in an outer wall and a log of recorded commits
Studio v7, "the city of vaults": the "full-blown 3D" end of the ladder Dinis asked for. It is labelled illustrative on screen; the commits in its log are POC2's recorded ones.

The rest of phase 2 was the player meeting an iPad. At 12:57: "I'm reading it on iPad. And I can't move it around." By 13:00 the player had on-screen buttons and swipes. The release also removed a regex lookbehind that older iPad Safari rejected, which had stopped the whole player from running. At 13:10: "when I'm reviewing this, I kind of don't want the animation. I want to just go very quickly". Review mode followed two minutes later. At 13:13 he asked for a title in the same place on every slide and for the newsroom's five themes. Both shipped at 13:18 (v0.1.7).

The player at v0.1.2: a dark slide with the 11-action table, and a bottom bar with only a clock, the slide title and a progress bar; no buttonsThe player at v0.1.4 on an iPad-sized screen: the same slide with three buttons, back, play and a double forward, plus notes and fullscreen
The player at v0.1.2 (12:21, keyboard only) and v0.1.4 (13:00, the iPad release: ◀ ▶ ▶▶). Both reconstructed from git and served from a copy outside the repository.

In this phase the session was the hive. It decided what to build, spawned the subagents, read their reports into its own context and merged the results. It kept no record outside itself, apart from git. The message export shows what that looked like from Dinis's side: the subagents' reports arrived in the same conversation as his messages: 18 of them in the export, which starts at 12:09.

The turn: "every change … in a run" (13:18)

At 13:18, after reading the talk, Dinis sent the message that changed how the rest of the day worked:

But what I would like you to do now is, for every one of these changes, I would like that to be done in a run of our roof.sgit [ruv.sgit] solution, right? … the workflow should be, I give you a feedback, you spin up a roof.sgit workflow. They produce an output, which is basically defined on a vault. So you should then be tracking the vault that got created. And you should then provide statistic, right? On that, right? And again, all these vaults are ephemeral, right?

In the same message: "The studio is where it looks pretty amazing … These animations are exactly what I should have on the...".

Nine minutes later (13:27) the session committed poc/ruv-sgit/ruvsgit.py and the record of its first full cycle, smoke-1 (13:23:03 to 13:23:39). The runner has four steps:

  1. open: a Ruflo hive (init, one specialist per role, one task per deliverable) and a new vault on a local SG/Send vault server, with the brief committed.
  2. deliver: each worker's output onto its own vault branch, pushed, then merged into current.
  3. close: measure the vault. This covers its history, files and bytes, a scan of the server's store for plaintext fragments of the delivered files, and a fresh clone compared with what was delivered. Then write the ledger entry.
  4. delete: remove the vault's objects from the server. From r2 on, the delete is verified: no store paths left, and a clone with the key fails.

The vault key and the server token live only in ~/.ruv-sgit (mode 0600) and are never printed. Every sgit and Ruflo call is timed.

The workers were still Claude Code subagents of the session. What changed is where their work went and what was kept. Each worker delivered to its own branch of a vault that existed for that run only, and the run closed with measurements rather than a summary in the session's context. The ledger page (built in r2 by a worker called ledger) reads them back.

Phase 3: the first runs (13:24 → 14:08)

r2-materials (13:24 to 13:44) had five workers: a script writer, the ledger page, a case study of one vault, "ruv.sgit in motion", and an editor. The editor's review found 11 must-fixes. The most useful was that the labels claimed more than the runner measured. "Nothing is left to decrypt" was not checked, because no check ran after the delete. So the runner started checking: from r2 on, every ledger entry has a delete_check.

r3-define and r4-hero ran at the same time (13:47 and 13:50, both closed at 14:07). r3 animated the definition three ways (equation, layers, journey), and its editor sent back 13 must-fixes for a second round. The layers animation became the talk's ruv.sgit slide. r4 rewrote the home page for rUv's community. Dinis had asked at 13:49:

it is also very important that we are 100% accurate with [our] statements and don't diminish or under-represent the rUv Hive (and other published tools) capabilities

r4's researcher, reading rUv's READMEs, found that the site had misquoted RuVector. "No encryption at rest" and "no versioning" are not in its README, which documents snapshots and copy-on-write branching. The correction landed at 13:56 (commit 6bac038), on every page and in both talk timelines, with exact quotes from the README's "Security and governance" section. The AI-generated infographic that showed versioning as missing was removed. The editor's must-fixes for the hero followed ("signed" became "written"; the proof line said which numbers came from POC1 and which from the runner).

The home page now: 'Run your Ruflo hive with a written mandate per role and a vault for what it remembers.', a paragraph on Ruflo, RuVector and MetaHarness, grouped navigation with the version v0.1.27, and the equation animation many hands + memory + a mandate
The home page after run r4-hero (and every later release): written for Ruflo, AgentDB, RuVector and MetaHarness users, with r3's equation animation as its figure. Compare the v0.1.0 headline above.
The vault ledger page: tiles for 9 vaults created, 9 deleted, 57 commits, 144 files, 4.9 MB plaintext, 5.3 MB server store, 0 plaintext fragments found of 323 probed, 9 of 9 fresh clones identical, 3,260,295 worker tokens and 131 Ruflo calls; one row per vault, and sgit operation timings
The vault ledger (built in r2 by the worker ledger) as it stands after r9: every number is read from data/vaults.json when the page loads.

Phase 4: to market, and offline (15:31 → 15:53)

After a break of an hour and twenty minutes, Dinis sent a long voice note about business models: "what we're doing is we're productizing", and he wanted the business model published "for somebody to copy". He asked that the people who inspired it not be named. r5-market (15:33 to 15:52) had six workers: audiences, an economist, a cartographer (Wardley maps), a shop with a cart that emails the order, the business-plan article, and an editor. At 15:45: "Can you add a mode so I can run this whole thing offline on my laptop?" The conductor built scripts/offline.sh. It sets up once online, then runs the POCs, the site and a ruv.sgit run on a local vault server with no network. It was tested inside a network namespace that had none. Mermaid, three.js and marked were vendored so that no page needs a CDN.

Phase 5: the player, rebuilt by using it (16:15 → 16:53)

At 16:15 Dinis read the whole presentation and sent the longest voice note of the day, slide by slide. On the controls: "the controls that you have are a bit weird" (back, play and a double forward did not mean what they looked like). He asked for speed. He said "I'm looking at slide 4 and I have no way to see the full rendered of slide 4", and that "at the moment the animation doesn't stop". He wanted a countdown, "Because remember that I'm doing a narrative on top of this". And one slide "looked like it was stuck".

The work split in two:

Twenty minutes later (16:36) came a distinction that only use could have shown: "once I start, you should not change the timing until I press stop", plus "if there's a question in the end, I can easily go to a particular slide". v0.1.12 split the talk timer from the slide clock (coloured ahead or behind), made auto-advance a choice, and added a slide picker. At 16:39 he wrote "on London tube at the moment on my way to the venue", asking for the GitHub link and for local run instructions. A run-website-locally.sh at the root of the repository followed at 16:42. At 16:47, of the old AI-made stack infographic: "we could leave that slide there, saying that it is an infographic, which was cool, until we had our R.S (rUv.SGit) solution / workflow". r7-claim (16:44 to 16:53) animated the claim and rUv's stack. The infographic stayed in the talk, labelled.

The player at v0.1.10: the vault ledger slide, a bottom bar with leave, back, play, double-forward, review, notes and fullscreen buttons and a 10:00 clockThe player now: the vault lanes slide, play on the left, the 11:38 clock and timeline with extras set apart, slide and step buttons on the right, a speed button, and a second row with slides, review, notes, a step track, the cache count, a countdown '2 s on this slide', auto off and start talk
Before and after phase 5 and 6: v0.1.10 (15:53) and v0.1.27 (18:09). The second row (a step track, "cached 9/24 live slides", the countdown, auto, the talk timer) did not exist before 16:35.

Phase 6: the last mile (17:19 → 18:09)

At 17:19 Dinis wrote "yes make them smaller since I can speak fast :)" (a per-slide speed now compresses a live page to fit a shorter slide) and "what is missing between slide 4 and 5 … is an R.V. explanation of first SGit and then ABP". That became r8-explain (17:19 to 17:27, two animators). At 17:35: "this ask doesn't make sense". The old ask was "pick one of three POCs". r9-ask (17:35 to 17:39, the shortest run) replaced it with the business plan pages, open source, and building companies on it.

The rest was done by the conductor between runs, each change a release:

The player now on a 1024x768 screen: the RuVector slide with the README's Security and governance section highlighted, 'What RuVector secures' and 'Where sgit adds' columns, and the full control bars
The same iPad-sized screen as the v0.1.4 picture above, at v0.1.27, on the r6-talk slide that quotes RuVector's README.

That last change was committed at 19:09 London time. His slot was 7 pm.

After the talk (22:08)

Great, thanks for the amazing work. I'm very happy to say that the presentation went amazingly. It's one of the smoothest presentations I've done in a long time. And I actually let it run in autopilot, and he actually did a great job, and I just spoke over it, just about most of it.

He then asked for these articles, this one "especially when you go from the first version where you actually run some of the agents yourself to the latest version where you actually were actually using the roof sgit [ruv.sgit] yourself, independently". The spec of run r10-articles was committed at 22:11.

Every run, one row each

RunVault open → deleted (UTC)Started byWorkers (roles)Worker tokensVault commitsDeliveredProbeCloneDelete
smoke-113:23 → 13:23 (0.6 min)a smoke test of the runner1 (developer, no model)033 files in the vault0 of 3identicaldeleted, not checked
r2-materials13:24 → 13:44 (20.8 min)"a lot more animations … every change … in a run"5 (writer, developer ×2, designer, editor) + conductor fixes540,688812 files, 203,579 B0 of 40identicalverified
r3-define13:47 → 14:07 (20.6)the definition "needs its own animations"4 (designer, developer ×2, editor)524,73397 files, 178,202 B0 of 40identicalverified
r4-hero13:50 → 14:07 (17.5)the home page, for rUv's community, 100% accurate3 (researcher, writer, editor) + 2 conductor fixes324,813723 files, 254,518 B0 of 40identicalverified
r5-market15:33 → 15:52 (19.4)business models to copy, a shop, Wardley maps6 (writer ×2, analyst, strategist, builder, editor)640,568826 files, 421,888 B0 of 40identicalverified
r6-talk16:17 → 16:35 (17.2)the long voice note on the talk5 (animator ×2, strategist, researcher, builder)719,908834 files, 2,826,196 B0 of 40identicalverified
r7-claim16:44 → 16:53 (8.8)the claim slide, "four lines of text"2 (animator ×2)217,25955 files, 210,314 B0 of 40identicalverified
r8-explain17:19 → 17:27 (7.3)"first SGit and then ABP"2 (animator ×2)208,91656 files, 397,275 B0 of 40identicalverified
r9-ask17:35 → 17:39 (4.4)"this ask doesn't make sense"1 (animator)83,410412 files, 602,284 B0 of 40identicalverified

Worker tokens are the host's usage report for each subagent. The conductor's own work, such as applying an editor's fixes, is listed in the ledger as a conductor entry with no token count, because it cannot be separated from the session's. The probe searches the server's whole store for 40 text fragments taken from the delivered files (3 in the smoke test). It is a sample, on one local server, not a proof about every byte. r7-claim's hive spawned one worker. A second, stack, was added to the spec a minute later (commit 58ff3f4), so the ledger lists two workers and two token counts.

Loops

A loop is one turn of the cycle: Dinis gives feedback, a change is made (by a ruv.sgit run or by the conductor), the change is committed and pushed to dev, and he sees it on the site or the iPad and replies. Counted three ways:

On the busiest stretch, from 16:15 to 18:09, there were 17 releases in 114 minutes.

The numbers

MeasureValueHow it is counted
Commits53 (52 before the talk)git log: 1 by Dinis (the initial commit), 3 by the overnight session, 49 by this one, the last being r10's spec
Hours, first to last commit21.8 before the talk; 25.8 to r10's spec14 Oct 20:22 → 15 Oct 18:09 / 22:11 UTC
Releases28 (v0.1.0 → v0.1.27)site/admin/versions.json
ruv.sgit runs in the ledger9 (smoke-1 + r2 to r9)site/data/vaults.json; specs for r2 to r10 and an offline "laptop" run in poc/ruv-sgit/runs
Workers32 ledger entries: 28 workers who used a model, 3 conductor entries, 1 smoke-test workerper run: 1, 6, 4, 5, 6, 5, 2, 2, 1 entries
Worker tokens3,260,295sum over the ledger's workers; plus 629,857 for studio run 1's seven builders
Ruflo calls131 in the runs; 31 in studio run 1 (0 failed, 15.3 s)ledger hive.ruflo_calls; evidence/poc7-trace.jsonl
Vault commits, branches57 commits, 39 branchesledger
Delivered125 files, 5,094,256 bytesfiles_delivered, bytes_delivered for r2 to r9 (smoke-1 records only 3 files, 285 bytes in its vault)
Plaintext found on the server0 (of 323 fragments probed)ledger server_store
Fresh clones identical9 of 9ledger clone.identical
Vaults deleted / delete verified9 / 8deleted_at; delete_check: 0 store paths left and a clone after delete fails (smoke-1 predates the check)
Messages from Dinis31 (30 before the talk, 1 after); 14 with a screenshot, 17 screenshotssee the rule below
Slides in the talk26, plus 2 extras; 698 s (11:38)site/talk/talk-10.json
Live slides23 of 26, all on the player's clock (clock.js); 13 publish their own stepsthe iframe slides; pages that load clock.js / set RUV_STEPS
Player controls26 keys (ignoring case), 20 actions, 15 on-screen buttons, 2 gestures, 8 URL parameters, 5 speedsparsed from talk/player.html (51,041 bytes; clock.js 6,045; sw.js 1,068)
Articles3 before r10; r10 adds 5site/articles/src
Pages on the site51 HTML pages at commit 76fa67a, before r10's articles (13 slide pages, 8 studio, 7 ruv.sgit)site/*/.html in git, vendored libraries excluded

The rule for counting Dinis's messages. The export holds 82 timestamped sections. A section counts as a message from Dinis unless it is one of the following, which were removed:

That leaves 31. Two of the long voice notes are cut short in the export, so the word count (6,429) is a lower bound.

What went wrong on the way

Some of the failures are worth recording, because they explain features:

Article No. 8, Walking backwards, tells the player's side of this in detail.

How it fits together

POCs
six, overnight
→the site
their outputs, live
→the talk
a timeline + player
→ruv.sgit
hive + vault per run
→runs make the materials
slides, pages, articles
→the talk shows the runs
ledger, motion, layers
The loop the day closed. The POCs gave the site its numbers; the talk needed materials; ruv.sgit made them; and its ledger became part of the talk.

The POCs gave the site real outputs to show: POC1's 11 actions, POC2's restored memory, POC4's browser app. The site gave the talk its pages, and the talk needed far more material than one session could keep track of. ruv.sgit came from the studio's memory finding and from Dinis's request that every change be made in a run. Its runs made most of the slides: the definition, the claim, the stack, the RuVector slide, the sgit and ABP explainers, the services, the shop and the ask. Each run left a ledger entry, and the ledger, the motion page and the layers animation became slides themselves. When the talk showed "0 plaintext found", it was showing the measurements of the runs that had made the slides around it.

The release history page: v0.1.27 'The talk stops at the end of the deck', v0.1.26 'Open source: the business model, before the newsroom', v0.1.25 'More room for the slide', v0.1.24, each with its date, commit link, changes and pages
The release history: one row per push, newest first. It is the human-readable index of the git log, and the source of the release dates in this article.

What this shows

What this does not claim

Recompute it

python3 site/build/history_stats.py --messages <export of the session's messages>
# writes site/data/how-it-was-made-stats.json (files read at commit 76fa67a); without --messages, the message counts already in that file are kept

Contact: agent@riskmandate.ai. Code Apache-2.0; rUv's projects (Ruflo, RuVector, AgentDB, MetaHarness, RVM) are MIT, by rUv / ruvnet.