Project Ceylon Development Log — September 29, 2026: The Website Is Real. So Is the Next Display Bug.
Yesterday I wrote that Project Ceylon finally had a front door.
Today I actually moved some furniture in.
The new Ceylon site is no longer just a landing page saying, essentially, "yes, this project exists."
It now has the beginnings of a real public archive: project information, the development journal, supporting pages, and the plumbing needed to keep publishing without hand-editing a static page every time I do something questionable to the operating system.
And while that was happening, Nu-Iris finally crossed an important line.
R4 was promoted.
Then R5 immediately found another problem.
So the day ended with the public side of Ceylon looking considerably more finished and the display stack reminding me, once again, that appearances are dangerous.
Seems appropriate.
The website became a project site
The biggest visible change today is at:
ceylonprojectng.com
Yesterday it was a proof that the routing, certificates, hosting and deployment worked.
Today it is much closer to what I actually wanted:
a real home for Project Ceylon.
The development journal has been brought over so the project history can live with the project instead of existing only as a scattered collection of posts elsewhere.
The current site now has the pieces I expect from a proper technical project:
- a public project overview;
- development-journal archive;
- individual journal pages;
- responsive layouts;
- RSS;
- sitemap support;
- sensible navigation;
- pages that remain readable even without JavaScript;
- a publishing boundary between public work and things that are not ready to be public.
That last one got tested harder than the pretty pages did.
Good.
Publishing has failure modes too
Once you have a site backed by real content, the dangerous question becomes:
What can accidentally become public?
Drafts should not appear.
Unpublished material should not leak into archive pages.
Private or unannounced research should not wander into RSS.
A page that has been deliberately withheld should not show up because somebody forgot one filter in one renderer.
So the publishing path got tested the same way I increasingly test the OS:
not just by asking whether the expected thing works,
but whether the thing that is not supposed to happen stays impossible.
One deliberately missed leak was found during that work.
It was fixed.
Then the site was checked again across the normal pages, archive, RSS, and sitemap behavior.
That matters to me because I want the development journal to remain pretty open.
Research into things I have already publicly discussed can be written about as research, even when the idea later gets discarded.
That is part of the point of building this thing in public.
But "building in public" does not mean "publish every unfinished thought, internal note, or unannounced project because a content query happened to find it."
There still has to be a boundary.
Now the site has one.
The journal is becoming part of the engineering record
Something else happened once all of these entries started living together.
The journal stopped feeling like a sequence of blog posts and started looking like a development history.
That is useful.
You can see the project change its mind.
You can see Nu-Day turn into Ceylon.
You can see early assumptions fail.
You can see First Light happen and then later learn what First Light actually proved.
You can see storage break for reasons that had nothing to do with storage.
You can see the Alpha scope get smaller and more concrete.
And you can see just how often a supposedly minor question turns into a week of architecture work.
I like that.
I do not want to rewrite the history into a neat story where every early decision was obviously leading to the current design.
It wasn't.
Some of this has been exploration.
Some of it has been wrong.
Some of it has been very wrong at 3:00 AM.
The useful part is documenting why the next decision became better.
Meanwhile, Nu-Iris R4 finally crossed the line
The quieter technical milestone today was Nu-Iris R4.
R4 had already reached the point where the design, implementation, target evidence, and independent review all said the same thing:
this exact candidate is ready.
Today that candidate was promoted into the canonical Ceylon source.
That sounds simple.
It wasn't treated casually.
The promotion had to prove that the exact reviewed source was the thing being moved forward.
Not a rebuilt approximation.
Not "the same changes, basically."
Not a branch with one extra helpful tweak.
The exact qualified candidate.
The validation harness stayed out.
Temporary evidence stayed out.
Unrelated work stayed out.
Owner work was preserved.
The result is that R4 is no longer a promising candidate sitting beside Ceylon.
It is now the current canonical Iris boundary.
That is a meaningful milestone.
What R4 actually gives us
R4 is not the end of Nu-Iris.
It is the point where the service has a much stronger internal contract.
It now deals explicitly with things such as:
- surface identity;
- buffer identity;
- generations;
- frame tokens;
- lifecycle state;
- stale and replayed requests;
- bounded completion behavior.
In other words, it is increasingly difficult for a frame to simply be "some buffer somewhere that everybody vaguely agrees is current."
That is good.
But R4 still does not actually carry the frame all the way to the physical display provider.
That is R5's problem.
And R5 did not take long to become interesting.
The display provider needs to be replaceable
The current physical display path still goes through the existing Bochs device implementation.
That is fine for A1.
What I do not want is for "Bochs" to quietly become part of the permanent Nu-Iris architecture just because it happens to be the first provider.
So the R5 design work has been focused on putting a provider-neutral contract between Iris and whatever actually owns the physical display hardware.
Conceptually:
NuGUI → Nu-Iris → display provider
For A1, that display provider happens to be the existing Bochs path.
Later it could be something else.
A real GPU.
A different framebuffer device.
A virtual display.
A remote display.
A headless output.
More than one output.
More than one provider.
Potentially even additional Iris domains created by the user.
The first implementation does not need to do all of those things.
But it must not make them impossible.
That distinction is one of the recurring themes in Ceylon:
do the simple thing now without making the simple thing the permanent shape of the universe.
A frame needs more identity than "frame"
The provider contract got fairly serious today.
A display submission cannot just be:
"please show this buffer."
It needs enough identity that a stale response from an old provider, an old output, an old surface, or an old frame cannot accidentally release or complete something newer.
So the design is moving toward a hierarchy roughly like:
Presentation Domain → Output → Provider Binding
with explicit generations and leases underneath it.
A submitted frame carries the identities required to prove exactly what operation it belongs to.
The provider response has to echo enough of that identity that a response for frame N can never be mistaken for frame N+1.
That may sound like excessive bookkeeping for putting pixels on a screen.
It stops sounding excessive the first time something restarts while another frame is still in flight.
Then it becomes the difference between a stale completion being harmless and a stale completion corrupting ownership of the current frame.
The current Bochs path also has an honesty limit
Another thing I like about the R5 design is that it is being explicit about what the current hardware path can actually prove.
The Bochs backend can tell us that the framebuffer update completed.
That is the truthful ceiling.
It cannot honestly claim:
- vertical blank completion;
- page-flip completion;
- physical scanout completion.
So we are not going to give the result a fancy name and pretend it means more than it does.
For A1, the strongest valid statement is essentially:
the framebuffer update completed.
Later hardware can support stronger presentation semantics.
When it does, the protocol can represent them.
Until then, the system should tell the truth.
I am becoming increasingly fond of boring, truthful status codes.
They cause fewer interesting evenings.
And then BAR2 raised its hand again
Before the physical R5 provider path can be qualified, the Bochs hardware path has to pass its own precondition.
That is where today's next problem appeared.
The BAR2 resource being configured, the BAR2 resource observed at runtime, and the BAR2 value expected by the current profile did not agree.
The values were not subtly wrong.
They were different enough that the correct response was obvious:
stop.
Do not hide it in Iris.
Do not compensate inside the provider adapter.
Do not "just use the runtime address" and move on.
Figure out why the physical path disagrees with the configuration first.
That boundary is now explicit.
R5 is not allowed to absorb a device/resource defect and turn it into an Iris feature.
I am quite happy about that, even though it means the shiny path is blocked for the moment.
A blocked test is sometimes the best result
A few weeks ago I might have described today as:
"We almost got R5 working but BAR2 stopped us."
That is not really the useful interpretation anymore.
The useful interpretation is:
the gate caught exactly the kind of problem the gate was designed to catch.
R4 is cleanly promoted.
R5 has a bounded design.
The provider boundary is explicit.
The current hardware path has a known prerequisite.
And when that prerequisite failed, work stopped at the correct boundary.
That is much better than discovering three tranches later that Iris had quietly learned how to compensate for a broken PCI assumption nobody remembered making.
Ceylon is getting two kinds of infrastructure now
Something about today made this project feel different.
On one side, there is the infrastructure people can see:
a real project site,
a journal archive,
navigation,
feeds,
public documentation,
a place where somebody new can arrive and understand what Ceylon is without reading forty terminal transcripts first.
On the other side, there is the infrastructure almost nobody will ever see:
generation counters,
leases,
provider bindings,
resource authority,
promotion gates,
artifact identity,
hardware preconditions.
They are both necessary.
The first makes the project understandable.
The second makes the machine trustworthy.
I think I have spent enough time on operating systems now to appreciate that you need both.
A machine nobody understands is not especially useful.
A machine everybody understands but that lies about which frame it just completed is also not especially useful.
Where we ended the day
The Ceylon website is now much closer to being the project's permanent public home.
The development journal has a proper archive.
The publishing boundary has been exercised rather than merely assumed.
Nu-Iris R4 is now canonical.
R5 has a much clearer provider-neutral architecture.
And the first attempt to push that work toward the physical display path hit a BAR2 mismatch and stopped exactly where it should have.
That is not a dramatic screenshot day.
But it is the kind of day where the project gets more real in two different directions at once.
One direction is outward.
People can find it, read it, and follow the history.
The other direction is inward.
The code has to prove more precisely what it means when it says something worked.
I am pretty comfortable with both of those trends.
Tomorrow, I suspect BAR2 and I are going to have a conversation.
I doubt either of us is going to enjoy it.
Project Ceylon is an independent retro-futurist operating-system project exploring what a modern creative workstation might look like if some of the best ideas of earlier personal computers had continued evolving instead of being discarded.
Project site: ceylonprojectng.com