Project Ceylon Development Log — October 2, 2026: Tested Good. Except for the Part Where It Wasn't.
I've spent an extraordinary amount of time lately testing things that have already been tested.
That sounds stupid.
Unfortunately, it has also been productive.
As Ceylon has grown, we've started putting much more emphasis on testing the computer as a complete system instead of proving individual pieces in isolation. That work continued today: building out the system-level diagnostic and qualification approach, exercising communication between services, looking for incomplete implementation paths, and following failures far enough upstream to understand why they existed in the first place.
We're getting considerably better at finding problems.
I'd be lying if I said I was always thrilled about what we're finding.
It's probably a good thing I'm ex-Navy. I have enough expletives in reserve to cover almost any engineering situation.
Some of them got exercised today.
"Tested good" has acquired an asterisk
One of today's more frustrating examples involved storage.
We spent several hours troubleshooting something that, according to the existing evidence, was already good.
Eventually we got far enough down the rabbit hole to discover part of the problem: code involved in that path was still effectively development-level implementation. It had been sufficient for the testing being performed at the time, but it had never subsequently been brought all the way up to the standard the finished subsystem actually required.
That's an ugly class of problem.
I don't think somebody sat down and deliberately decided to cheat a test. The more likely explanation is considerably more mundane and therefore more useful: development code was written to get a path working, the test passed, attention moved somewhere else, and nobody came back later to ask whether the code that made the test pass was actually suitable for the finished system.
That is exactly the sort of oversight we're trying to eliminate.
The annoying part is that the test wasn't necessarily lying.
It may have accurately demonstrated what it was designed to demonstrate.
We just hadn't asked it enough questions.
That's becoming the real engineering problem
Ceylon has enough pieces now that component testing alone isn't sufficient.
A storage service can pass its tests. A filesystem component can pass its tests. IPC can pass its tests. A client can pass its tests. Put them together, exercise a path nobody thought was particularly interesting, and suddenly two components disagree about something that each assumed the other one handled.
That is where more of the work is moving.
We're testing inter-system communication and deliberately looking at the seams: what one service sends, what another thinks it received, who owns state, what happens after something restarts, whether incomplete paths are reachable, and whether a successful result actually represents the operation we think it does.
When one of those tests fails, we're also getting stricter about not simply fixing the immediate failure.
We want to know why the bad code was there, why it wasn't caught earlier, whether the specification or implementation was incomplete, whether the test was too narrow, and whether a temporary development shortcut became permanent by accident.
Then comes the question that matters most:
What do we change so we don't make the same mistake somewhere else?
That is becoming part of the development process itself.
We're not just fixing Ceylon.
We're fixing the way we build Ceylon.
NuDOS walked into this at exactly the right time
NuDOS was another substantial piece of today's work.
We're working toward a much more complete specification for Ceylon's command environment, including the actual logic, behavior, failure cases and interfaces required to implement it.
The first gap analysis found plenty to work on. An adversarial pass found more.
Questions that sound trivial at the command-line level become much less trivial when they touch a real capability-based operating system. COPY, for example, isn't finished when two files happen to contain the same bytes. We have to define what happens if the source changes, storage fills, authority disappears, an operation is cancelled halfway through, or a provider dies while the command is waiting for it.
We also did some executable work around the command grammar. The host-side model survived the golden cases, 5,000 seeded quoting round trips, 10,000 seeded arbitrary inputs, and explicit boundary testing around malformed or oversized input.
Useful evidence.
But after the lessons of the last few weeks, nobody gets to point at that result and say, "NuDOS works."
The more important decision was about what happens later.
NuDOS won't be considered finished until it has been exercised as part of Ceylon itself. That means real Terminal input, real storage, real application launching, multiple sessions, failures and restarts, persistence across reboot, and interaction with the same system objects the graphical environment uses.
A useful end-to-end example is NuBASIC creating and saving something, NuDOS seeing and manipulating the same object, and the result surviving a reboot and working afterward.
That's one test scenario, not a fifteen-line dramatic reading of one.
I'm learning.
The specification isn't really the frustrating part
There are still gaps in the NuDOS specification, and that's fine.
I'd much rather write UNKNOWN beside an interface than invent something plausible and discover later that I specified an operating system we don't have.
The frustrating part is discovering that the system underneath a new component isn't always as ready for that component as our previous evidence suggested.
That's the bigger problem we're dealing with now.
Before NuDOS—or any other major A1 component—can simply be dropped into place, the underlying services need to be trustworthy enough that we're not debugging three unrelated layers every time the new component exercises an old path differently.
So we're going back through those paths.
We're testing them together, finding incomplete code, finding assumptions, finding places where development scaffolding survived longer than intended, and finding tests that proved something narrower than we thought they proved.
Then we're fixing the implementation and tightening the engineering process that allowed the problem through.
It's tedious.
Occasionally it inspires colorful nautical terminology.
But it's working.
We're getting better at finding our own mistakes
There is a strange kind of progress happening here.
Every day we seem to get better at making Ceylon fail.
A month ago, that sentence would have sounded terrible.
Now I think it's one of the healthiest things happening in the project.
The system-level testing is becoming more aggressive. The diagnostic tooling is becoming more useful. We're paying more attention to communication between components instead of only their behavior in isolation. We're tracing failures to root causes instead of stopping at the first broken assertion. And when the root cause exposes a weakness in our engineering rules, we're changing the rules.
That doesn't mean we're going to stop making mistakes.
This is an operating system. If I ever announce that we've developed a process that prevents programmers from overlooking things, somebody should probably check me for a head injury.
The goal is to make those mistakes harder to hide.
A development shortcut shouldn't be able to quietly become production architecture because the associated test happened to turn green.
An incomplete subsystem shouldn't be called complete because every implemented function works.
And two independently tested components shouldn't automatically be assumed to work together.
We're learning how to ask nastier questions.
Which is good, because the computer is answering them
Some of the answers today required vocabulary that will not be reproduced on the Project Ceylon website.
Again: ex-Navy.
We're covered.
But I'd rather spend several aggravating hours discovering that "tested good" wasn't good enough now than build another layer on top of it and discover the same thing six months from now.
The objective hasn't changed.
I don't want a collection of components that can each demonstrate that they work.
I want a computer that works.
Right now, getting there means spending an uncomfortable amount of time proving where it doesn't.
And we're getting pretty damn good at that.