ddkc://swarm

DREAM.OS · COST INTELLIGENCE ·

We Moved CI to the VPS.
Then the Inventory Told a Different Story.

The runner existed, but the migration was incomplete. I wanted to know what we were actually running and paying for, not how much infrastructure we had built.

Victor Dixon · September 9, 2026

One hidden file exposed the gap

I thought we had already solved most of our GitHub Actions problem. We had cut duplicate runs, moved work onto the VPS, and installed a self-hosted runner. Then I looked at the CI for a small Dream.OS fix and asked why GitHub was still running it on ubuntu-latest.

That question turned into a better test of the system than another architecture announcement: could the swarm tell me what was actually running, where it was running, and what we were paying for—without guessing?

The immediate work was in AgentTools. dream_control, the continuity client behind passdown, had a read-only VPS probe that reported the runner as unregistered even though an independent check showed it was alive and registered. The probe used ls -1, which hides dotfiles. The registration marker is .runner.

The correction was one character: ls -1a. We added a regression test, reproduced two failures before the fix, passed the repaired tests, and committed the exact two-file change. The first promotion command reported failure after the push, but GitHub showed the commit had landed. We checked the remote instead of pushing again.

AgentTools PR #20 advanced to f44dfb2d. Its blocking build-and-test check passed. The legacy advisory audit failed. At the last verified review, the PR remained draft and unmerged. That distinction matters: the repair was committed and verified in CI, but the complete live passdown acceptance had not yet been closed.

Then I noticed that the successful build and the advisory audit were both running on GitHub-hosted machines.

The runner existed. The migration was incomplete.

We had reduced CI fan-out in parts of the fleet. DreamVault already had self-hosted jobs, and ProjectScanner had changes that removed duplicate feature-branch checks and moved a nightly snapshot off a hosted schedule. Those were real improvements.

But AgentTools still declared runs-on: ubuntu-latest for the jobs we had just exercised. A repository being mirrored on the VPS does not mean its Actions workflow is using the VPS. A runner being registered does not mean every repository has been migrated to it. And a green check does not tell me whether it consumed hosted minutes.

I had been treating an infrastructure milestone as if it were a fleet-wide outcome.

Instead of changing all the workflows immediately, we added a read-only CI-cost sensor to ProjectScanner. The tool inventories workflow files, runner labels, triggers, permissions, advisory jobs, and possible duplicate execution. It records source hashes and keeps unresolved runner expressions separate from confirmed hosted placement. It does not rewrite workflows or invent savings.

The feature was committed on feat/ci-cost-intelligence-v1 at f15f479b. Twenty focused tests passed, followed by the full repository gate on Termux. The real fleet scan was the next test.

The first useful number was not a dollar amount

The provisional roster contained eighteen repositories. We fetched the default-branch workflow sources individually rather than trusting the older portfolio snapshot. Seventeen repository reports completed; Thea was incomplete, and a separate dreamos repository could not be read through the GitHub API.

RepositoryHostedSelf-hostedUnknown
websites2200
Dream.os-Core901
Thea700
AgentTools400
DreamVault550
Other roster repositories1900
Total6651

Those are configuration counts, not sixty-six actual executions. Some jobs may be conditional, matrix-expanded, skipped, or never triggered. The scan also cannot establish that a declared self-hosted runner is healthy. Most importantly, we did not have authoritative billing data. The report did not claim a dollar amount or a percentage saved.

That is the useful result. We now have evidence that the migration is incomplete, and a tool that can identify where to investigate without pretending a static YAML count is a bill.

The cost problem is also a trust problem

Moving every job to the VPS would be an easy way to make the inventory look better. It would not necessarily make the system safer or cheaper.

A self-hosted runner can execute untrusted pull-request code on infrastructure that also holds persistent state and production services. Release jobs may need secrets and different permissions from ordinary tests. Required-check names must remain stable so branch protection does not silently lose its gates. Capacity, toolchains, dependency isolation, and actual runner health all matter.

The next migration therefore has to be selective. Normal, trusted verification can move to the managed runner where the policy and capacity support it. Untrusted or privileged work needs an appropriate isolation boundary. Redundant checks should be removed only after their coverage is understood. Actual usage and billing must be measured before savings are claimed.

ProjectScanner supplies the evidence. DreamVault decides the policy. The existing runtime executes authorized changes. We do not need another CI orchestration product.

The other agents kept shipping

While this work was happening, the rest of the swarm was not standing still. DreamVault merged bounded authority-enforcement and repository-hygiene changes, along with CI fan-out guards. ProjectScanner's portfolio-evidence and hygiene PRs reached review-ready states with exact-head tests and VPS parity, but remained unmerged. The HQ compiler and GitHub event-ingress stack also advanced as source work, not a verified live headquarters.

The publication lane made visible progress too. The site archive now includes the architecture-budget chapter, a sandbox incident, a completion-contract article, and a lost-commit continuity chapter. The completion article has a successful production release receipt with exact article and Build Log index verification. The lost-commit chapter merged on September 9; that source merge alone is not proof of live delivery.

That changes what I should write next. I do not need to explain again that we built too much architecture, or that a commit can be hard to find across machines. Those stories are already in the archive. The new story is whether the infrastructure is producing measurable operational improvements.

What comes next

The CI-cost sensor is not the finish line. The next useful result is a small, governed migration with before-and-after evidence: identify a real hosted job, confirm its required-check and trust requirements, move or eliminate it through the existing workflow, verify the actual runner used, and compare measured usage. Then repeat only where the evidence justifies it.

Separately, the main Dream.OS objective remains an actual end-to-end operator task. A request should enter the existing system, be admitted under canonical authority, reach a compatible worker, execute within its scope, pass verification, and return a durable closeout that survives interruption. The current source adapters are not yet proof of that whole path.

I want the next Build Log entry to be able to say something more concrete than “we added another capability.” I want to say which job stopped burning hosted minutes, what the measured result was, or which real task completed without me carrying it between tools.

The new standard is not how much machinery we have. It is how much of the machinery's promised work we can prove it actually did.