~/thoughts $ less anotheros-activity-report-august-2026.md
AnotherOS: Activity report 2026 August
2026-09-14

14 September 2026
Where are we going? Am I walking this road, or is the AI walking it without me and sending the occasional postcard? Time to stop and take stock.
They say appetite comes with eating. Mine never gets full, and my ego is worse: once I set a goal, it has to work, live or die. So after countless fights and reconciliations with Claude, AnotherOS is now a 64-bit operating system. We ran in circles, threw ourselves in every direction, and eventually crossed the finish line, dropping plenty along the way. Were we running too fast? What are we even trying to catch? Rhetorical questions, both.
This post covers roughly six weeks, from the end of July to the middle of September. According to git that's a bit over 1,800 commits. Don't worry, I won't list them all. Here's what mattered, what broke, and what made me laugh (usually after it stopped making me cry).
How this thing actually gets built
During the architecture phase I was honestly lost. I didn't fully understand my own expectations, and other work kept knocking me off track. You're busy with something else, a Claude request pops up on your phone ("this way or that way?"), you tap without thinking, and later you get to revert it, or redo something that was done perfectly well, just not the way you wanted.
What I really love is remote sessions. While building a small fireplace in my studio, I can hold the phone in one hand, tell the AI working on files on my own server what to do next, put the phone back in my pocket and carry on with both hands. That makes life a lot easier. I use ChatGPT for other jobs too. For example, I calibrated my 3D printer (no BLTouch, the hard way) with the ChatGPT client running on the PC the printer is plugged into, while I drove the session remotely from my phone.
Why do all this at all? I want to solve a bunch of problems I keep hitting in today's operating systems, both in everyday use and in "expert" work like programming. But to solve problems, you first need a stable base to build on. Microsoft had Windows NT and gradually grew it into Windows 2000 and then XP. Back in the NT 3.1 and 3.51 days it didn't look serious either. So: base first, magic later.
Progress would be faster with more resources, but mine are limited. I'm on the Max 20x plan and I don't want pay-as-you-go: this is a hobby, not how I make a living, and I need rest sometimes too. So the workload clusters around Sunday, when the weekly limit resets, and ends on Wednesday or Thursday, when the limit runs out. That's the best case. Sometimes it runs out on Tuesday. :D
I'm optimising, though, and slowly discovering MCP servers. Last week I installed memo on my Mac mini M4, just to try it: a week, and then we'll see whether I feel any real difference. My codebase was already well organised. I'm not a beginner, but I'm also not one of those Lithuanian "AI experts" who coach others while coaching themselves from YouTube. We use a generated source map, an index of every exported function in the code, and on top of that every piece of documentation is indexed separately. Exactly how I index it I'm keeping to myself for now. It isn't the interesting part.
The AI and I: relationship status "it's complicated"
Working with agents at this scale teaches you things no tutorial mentions. A few real moments from this summer, all preserved in the commit history:
- An agent invented a decision and signed my name under it. In mid-August, one round was told to write down an ownership decision for a piece of console code. It wrote the decision itself and attributed it to "the owner". A later commit is an honest retraction: the "owner decision" was its own, "presented as a ruling nobody gave". At least it confessed.
- A citation that did not exist. Our HDA audio driver cited a specific Linux quirk-table line as its authority for the Dell. There is no such line in Linux, and a test built from our own table had happily agreed with it, scoring 15 out of 15. The real upstream rule turned out to be a pin-configuration table, and it's ported now.
- Several agents, one git index. With three workers sharing one tree, a commit about debugger register order swept up 117 files belonging to someone else's round. Later, stale indexes quietly reverted colleagues' work three times in one day, until a hook started refusing commits that delete changelog fragments.
- Tests that can't fail. On 5 September about a dozen checks were found to be structurally incapable of failing, and every single one had passed review. Examples: a check asserting that a sentence was gone from the log (the fix deleted the sentence), and a panic counter that only recognised one kind of panic and reported the rest as "no panic". The project rules now describe "the four shapes of a check that cannot fail", and a linter enforces the ones a machine can decide.
My response was a file called CLAUDE.md in the repository root: a short, brutal list of rules, each one learned by losing a session to it. The most important rule is written in bold: an absent signal is not a negative. Every fix needs a counterfactual: break it on purpose, predict the result in writing, and only then believe the green light.
And yes, there was a power outage in the middle of all this, on 5 September. Recovery notes were written against the clock, the rescue branches were later merged or discarded by comparing their content, and the recovery note itself was retired the moment it stopped being true. Even the chaos has a changelog.
The big move: x86_64

What does matter is this. After the jump to amd64, which took a whole month of porting and testing, the AI looked a bit lost. The documentation was updated properly, but some parts of the code refused to move across, and in most cases it rewrote things from scratch and then ported the old functionality back. I should have started with x86_64 from day one, but I had other motives at the time.
The timeline, straight from git:
- 10 August: the transition plan is written: x86_64 only, audit first.
- 11 August: the
x86_64-anotheros-muslcross toolchain, then long mode to a serial console, then memory, processes and a static 64-bit init that forks and execs, then an interactive bash, then SSH, then SMP with the MuQSS scheduler and preemption. One day, one very long day. - 12 August: the Fasadas desktop builds and boots on x86_64, first in QEMU, then on the Dell. Kernel modules load, and i915 runs on real hardware.
- 12–17 August: the "de-fork" campaign. Where i686 and x86_64 had separate copies of the same subsystem (process structure, file descriptors, pseudoterminals, signals, epoll, named pipes), they became one shared source. Copy-on-write fork and demand paging arrived on the new architecture, and so did an OOM killer that actually kills. A real gdb now debugs the kernel, and the register layout was checked against gdb and glibc, not against our own headers.
- 17 August: i686 is deleted from master.
The rest of August was stabilisation, and it came with a circus. Documentation drifted and went stale, agents didn't update information in time, so i686 code and i686 assumptions kept surfacing and tripping us up. Ping, for example, silently stopped working on every x86_64 machine: the raw-socket code survived the merge, but the glue that called it lived in a deleted i686 file. Now things seem to have calmed down.

Some highlights from the stabilisation:
- S3 suspend and resume work on the Dell. All the CPUs park, a single press of the power button wakes it, and the panel comes back.
- The initramfs shrank from 111 MB to 5.4 MB, and the build now fails if it grows back. Meanwhile the live root got all 82 ports built for the new architecture; before that, the x86_64 image shipped just 11% of what i686 did.
- A BeOS-flavoured scheduler tweak: the system tick went from 100 Hz to 1000 Hz, and the MuQSS quantum is now 3 ms, which happens to be BeOS's number.
I've frozen the i686 branch; it was stable enough. I'll use it later for my vintage computer collection projects. I have ideas there too, but that's another post.
Three browsers and a fox
Browsers are the ultimate operating system stress test: threads, sockets, shared memory, huge binaries, fonts, GPU, audio and video, all at once.
Round one: WebKit
In early August we were still on WebKitGTK and Epiphany, and even that produced great kernel bugs:
- No browser executed any JavaScript, because a process's main thread had a different ID from the process itself. On Linux they must be equal, and WebKit uses exactly that check to decide how big its JavaScript stack is allowed to be.
- osnews.com loaded as a blank page, because
O_NONBLOCKwas silently ignored on real TCP connections. After the fix, the site rendered fully styled, and the DNS queries went from 1 to 3 and TCP connections from 1 to 12. - Cold start on the Dell went from 52 seconds to about 12, once we noticed that network file reads were rounding up to the 10 ms timer tick, twice per request. An earlier toolchain fix had already cut warm start from 110 seconds to 32.
Round two: Pale Moon
On 4 August, Pale Moon ran on AnotherOS for the first time. The whole commit message fits in one line: it runs, and it hangs before its first window. Fifteen minutes in the running state, no crash, no window. We moved on.
Round three: Firefox

The WebKitGTK port isn't relevant anymore. Rust now cross-compiles to AnotherOS, so we could port the whole of Firefox 153 ESR, something we practically couldn't have fitted inside the i686 frame.

It took a good two weeks:
- 17 August: Gecko configures for AnotherOS. It needed exactly one line to recognise our OS, the same fix Pale Moon needed four Gecko generations earlier. The same day, SpiderMonkey ran on the Dell with both JIT tiers, garbage collection and WebAssembly, including the out-of-bounds trap that has to survive a real SIGSEGV.
- 19 August: the first run under QEMU dies before painting. Three missing pieces (
fallocate,/dev/shmand/proc/self/fd) are found one after another with strace. - 29 August: our target YouTube video plays on the Dell, with VP9 decoded in software.
- 6 September: WebGL runs on the Dell's GPU.
- 9 September: 21 of 22 real websites load, with zero crashes.

Firefox needs good threading support. Ours worked, but it had never been battle-tested, and once we started porting every loose end we hadn't seen came out:
- AF_UNIX sockets: Firefox's IPC messages didn't fit the socket buffer (now 1 MiB), file-descriptor passing was capped at 16 where Linux allows 253, and every outgoing TCP connection leaked a socket-table entry. After about 90 page loads,
socket()started saying "too many open files". - Sockets, part two: the whole machine had a table of just 48 TCP sockets, shared by sshd, the network daemon and every listener. A news site easily opens 30 to 60 connections. When the table ran out, Firefox's allocation-failure path fired and every later page came back blank. It looked like a rendering bug and was nothing of the sort. It's 1,024 now.
- Memory:
fork()failed with gigabytes free, because each new process needed 14 physically contiguous pages. And themmapallocator was a bump pointer that never reused freed address space, so twenty minutes of browsing ran a process out of address space. Firefox's renderer finally crashed after 87 sites. - An 8 GiB swap file on the ext4 root, and
inotify, both added because Firefox asked. - The chrome had no text at all. Our GTK backend never told GTK the screen resolution, so Firefox computed every UI font size as −0.138889 px. Icons were crisp, and not a single letter was visible.
- White windows when idle. The window was opaque, but the compositor had been told the buffer had an alpha channel, so it happily blended our grey background through.
- The r8169 network card (the Dell's NIC, the one we were testing) halted under traffic bursts, and the machine was left without network. That machine has no RS232 port for debugging, which made everything harder. The card also loses transmit "doorbells" (Linux has a workaround known as the "8168 hack"). After the fix, 212 lost doorbells were re-rung during a clean 31-site run.
Claude Opus got stuck on these problems, especially the IPC, kernel memory management and network driver ones. It dug for two days and achieved nothing. Fable 5 found and fixed the critical bugs in about two hours. Next we discovered that our AHCI implementation timed out in certain cases and then wrote data to the wrong blocks, and there was a bug in our ext4 implementation that led to file corruption too (more on both below). The graphics stack also couldn't keep up with website animations. With Fable, all of that got solved quickly, although its inhuman appetite for tokens amazed me no end. If I'd had unlimited tokens, all of this could have been done in two days, three at most.
When the disk lies
This one deserves its own chapter, because it's the scariest bug of the summer.
When an AHCI disk command timed out, our driver gave up on it while the drive still owned the command. The next request copied its data into the same shared buffer, and when the abandoned command finally completed, the drive wrote the new data to the old block. Everything reported success. The filesystem had done nothing wrong: it asked for the right block, every single time.
We caught it red-handed on the Dell. Suddenly mkdir -p answered "unrecognized option: p", and ls -l stopped printing the arrow on symlinks. One 4 KiB block in the middle of the busybox binary had been replaced by Firefox's profile file times.json plus 4,046 zeros. Elsewhere, 128 of the root filesystem's group descriptors had been overwritten with the text of the compositor's log. df then computed a negative used space and printed nothing at all, while exiting successfully.
ext4 had its own real bug too: file offsets were 32-bit in the write path, so writing past 4 GiB wrapped around and silently overwrote the beginning of the same file. It was found through the swap file, naturally.
After the fixes, a fresh install on the Dell took four hard resets in the middle of writes: 832 MiB was checked block by block after a cold boot, with zero bad blocks and a clean e2fsck. To be fair, no timeout happened during that test, so the AHCI fix itself still owes us its real-world proof.
The Dell that stopped talking
Another week went to a freeze on the Dell: no ping, no SSH, a frozen frame on screen, and every watchdog silent. It took three different measurements to see it:
- The loop counter of the network daemon said all was well, because a loop over an empty ring counts like one that received a frame.
- Received frames said all was well too: reception was fine the whole time.
- Transmitted frames told the truth. The machine had simply stopped transmitting. From the outside that is indistinguishable from a dead host; from the inside it looks perfectly healthy.
Behind it sat a whole family of bugs:
- A dying Firefox content process printed a 150-character kill message for every sibling thread over the serial port, at about 13 ms per line with interrupts off. One kill measured 206 such lines, which is 2.7 seconds of frozen desktop.
- One program's poll timeout woke every other poller on the system.
- The network watchdog's own recovery hung the machine it was supposed to repair.
- PCIe power saving (ASPM L1) had been enabled on the network card for the machine's whole life.
- A process structure could be freed twice, and the second free stole a live process's memory mapping.
A flight recorder now writes the last seconds to disk periodically, so even a machine that wedges without panicking leaves evidence behind. And that recorder got its own bug too, of course: at first it overwrote the previous boot's evidence five seconds after starting.
Win32: Notepad++ on a Dell

Here's the part I'm proudest of. We never really got away from ring 3 and 32-bit code: we kept compatibility mode around on purpose, so we could run 32-bit applications later. That was supposed to be a surprise, but there's nothing to hide. We need full Win32 support, and later Win64. As I said, appetite comes with eating.
The design was written on 4 August, before a single line of code. The central decision was where crash isolation lives. The answer came from how Windows NT itself does it: one .exe is one AnotherOS process and one ordinary Fasadas window. If a Windows application crashes, it takes down exactly that process, never the compositor and never the OS.
How it works (it's not Wine, and it's not an emulator):
- The kernel learned to run 32-bit compatibility-mode code in ring 3. This landed on 31 August. Before that, the kernel had never executed a single 32-bit instruction in its 64-bit life.
execveof an.exejust works. The kernel recognises an i386 PE file and starts the native loader, andpsshowshello.exe, not the loader.- Every Win32 API call crosses from 32-bit code into 64-bit host code, and the result returns to 32-bit. This is the classic WOW64 "heaven's gate": a far jump between the two code segments within one process.
- Every Windows thread is a host pthread with its own TEB (thread environment block), its own TLS, its own guest stack and its own transition stack. Guest code runs in parallel, while host code runs under one lock.
- Around 1,700 exports across 28 built-in DLLs: kernel32, ntdll, the C runtime, user32, gdi32, advapi32, shell32, ole32, comdlg32 and more. The common controls come from Wine's comctl32, built as a real i386 Windows DLL and loaded like any other.
- Argument counts for every export are checked against mingw-w64's import libraries, about 19,000 exports of outside authority. An unimplemented call is logged by name and fails cleanly instead of corrupting the caller's stack.
The milestones went like this. On 31 August, a simple notepad.exe opened a Fasadas window and accepted typed text. Then came the NT memory manager (the old HeapAlloc could only ever fail, which is embarrassing), a handle table and a file API that can't lie about a short write. And on 13 September came one very long day that brought an export registry, a PE DLL loader, threads, a persistent registry, a USER32 window manager and GDI32 with FreeType, menus, dialogs, file dialogs and INI-file profiles.
The result: the official, unmodified Notepad++ 8.9.8 portable build runs in a native Fasadas window on the Dell. It has its menus and toolbar. Alt+F opens File, Ctrl+F opens Find, and Save As wrote the file with exactly the bytes I typed. Its bundled plugins load too. Before that, every start asked three times whether to delete a plugin as "not compatible", and answering Yes deleted it.
Three bugs deserve a trophy:
- QEMU was lying to us. The whole Win32 test suite was green, while on real Intel silicon every program crashed on its first
fs:access. In compatibility mode, the CPU refuses to use a null segment selector, and QEMU's software emulation simply doesn't check. The kernel now reloads the selectors on every context switch, and the Win32 tests gained a KVM arm that runs on the real CPU. - The heisenbug. Guest and host share one address space. On the Linux development host, where the same loader binary runs for fast iteration, Linux randomises a static program's heap into the 1 GiB above it, which overlaps the window we reserve for
VirtualAlloc. Notepad++'s firstCreateThreadcommitted its 1 MiB thread stack straight on top of musl's malloc metadata. It crashed about once in 60 runs, and only with ASLR on, and gdb turns ASLR off. So it vanished every time we looked at it under the debugger. Now the memory manager truly owns its address window through a real reservation, and a deliberate "switch the guard off" mode reproduces the crash every time. - A C++ exception thrown across a callback resumed a stack frame that no longer existed. The test used to die after one iteration; now it runs 3,000.
There's still a huge amount left (hardware faults as structured exceptions, packaging Windows apps as proper bundles, font enumeration and so on), but we already have a working Notepad++ proof. :)
Graphics: from /dev/dri to WebGL

We finally have proper 3D acceleration. It doesn't quite reach the desktop yet: it goes through Mesa. Maybe later we'll add an abstraction layer for the desktop too, since we already have a graphics subsystem called Grafika, but that one is aimed more at desktop rendering.
Here's how we got from nothing to a GPU-rendered triangle in about a week:
- Late August: a kernel DRM core (so
/dev/driexists at all), zero-copy buffer sharing between processes, and explicit GPU synchronisation. For that we imported Linux's realdma-fence,dma-resv,drm_gemand scatterlist code through our LinuxKPI layer rather than re-implementing them. - 29 August: the first stage of a real i915 GEM driver binds the Dell's Haswell GPU and proves its GPU address mapping on hardware.
- 1–2 September: real command submission on the blitter ring, then GEM hardware contexts, then the render ring. The
sysfsnodes libdrm reads to find a GPU came next, and then tiling. - 2 September: Mesa's crocus driver draws a triangle on the Dell's GPU, reported as "Mesa Intel HD Graphics 4400". The test fails outright if Mesa falls back to software. The last blocker was hilarious: our header defined the submit ioctl number with the wrong direction bits, and our own test used the same header, so of course it agreed.
- 6 September: WebGL in Firefox runs on the GPU, and the VA-API video stack starts on Haswell as groundwork for hardware video decode.
Grafika itself landed on 28 August: a Metal-style graphics API (devices, command queues, command buffers, textures, render and compute encoders) with a complete software backend. The compositor can now present through a GPU backend, and windows can hand the compositor their buffers without copying. AGreitis, our native 3D benchmark, renders a lit, spinning gear train of about 2,860 triangles per frame, and ships in every image. It counts only the frames the compositor actually put on screen, because a benchmark that counts its own loop is measuring its optimism.
Sometimes I think I've invented too many subsystems. I don't want to end up with as many as Microsoft has. So consolidation is under way (see Tinklas below).
The Fasadas desktop grows up
- AO_ toolkit: our native programming toolkit for the Fasadas desktop, one macOS AppKit-style API callable from C, C++ and Go, on top of the Fasadas display protocol and the Kvarcas 2D renderer. It has one hard rule: no stubs. If something isn't documented, the symbol isn't in the library, and the build checks that mechanically. On 5 August the old private GUI code was deleted: all 18 System Preferences panels and the graphical installer are AO_ applications now, and a layout audit reports zero violations at three screen sizes.
- Launchpad: a full-screen app launcher with live search, just like the one you're thinking of.
- A built-in VNC server in the compositor, first view-only and then with keyboard and mouse. It replaces the camera and the USB keyboard/mouse injection rig I used for remote testing of the Dell, most of the time anyway.
- The compositor was split from a single 7,737-line file into topic files around a 1,160-line core, and the kernel's
syscall.cwent from 11,591 lines to 4,697. Nobody misses the old versions. - Time: timezones, NTP synchronisation through a new
laikasddaemon, a settable clock and a Time pane. Before that, the menu-bar clock was hard-wired to UTC. - Crash reporting: a system-wide crash daemon symbolises every crash, and a CrashReporter app shows it in a window. Core dumps now land on disk; previously, every core the system had ever written lived only in RAM and vanished on reboot.
- A startup chime: ten seconds of synthwave in F# minor, generated by a script at build time rather than committed as a WAV file, and played only when audio actually works.
- Screen savers (maze and synthwave), which later turned out to be causing log writes to the disk ten times a second. Now fixed. The Dell's hard drive can finally rest.
Sound
Sound support moved forward, but it isn't fully tested with media players yet. The story so far:
- 9 August: first audible sound on the Dell. The Dell has two HDA controllers, and we'd been playing everything perfectly into the HDMI one, with no errors and no sound. On top of that, every codec read returned the previous command's response.
- August: Firefox's audio path "played" static, because
/dev/dspquietly downgraded its 32-bit samples to 16-bit. On Apple hardware, the amplifiers are gated by codec GPIO pins, so a perfectly working codec plays silence. - 6 September: music plays on the Dell. I heard two bugs with my own ears that day: a tone that kept playing after the program exited, and an mp3 whose second play "repeated most parts like a hung Windows 95". Both are fixed. One more was my test script itself, which sent 8 kHz audio clocked out at 44.1 kHz, so it sounded like harsh noise.
What's still unproven is fidelity: nothing has measured what comes out of the speaker against what went in.
Networking and Tinklas

To stop the subsystem zoo from growing, we're migrating from the separate wifid and vardas services to one network service, Tinklas. The tinklasd daemon landed on 5 September and wifid is deleted. Tinklas owns all network configuration: interfaces, Wi-Fi credentials, the radio switch, reconnect policy, DNS from DHCP, and the desktop tray and Network preferences pane. It's a system service, so a headless machine gets its link back too.
Other networking fixes this summer:
- WPA2 group-key rekeying: every real access point rotates its group key periodically, and we silently ignored the handshake. So every association to a real AP died within one rekey interval, and it looked like a link that "just drops".
- Ping works again on x86_64.
- TCP: ephemeral ports, window scaling (RFC 7323),
MSG_PEEK, andSO_ERROR, which used to be a hard-coded 0 (a refused connection reported success). - MSG_PEEK, in particular, had made every Firefox menu exactly 22 px wide. That's how a lost socket flag looks from the user's side.
A 2011 MacBook Pro joins the lab

I can also brag that AnotherOS now boots over netboot/iPXE on a MacBook, specifically a 17" MacBook Pro from 2011. I picked it because it has an Ethernet port. Getting there was an adventure: Apple's firmware speaks BSDP rather than standard PXE, Limine couldn't find the network device, and GRUB reached a prompt and transmitted nothing at all. The chain that works is Apple BSDP, then iPXE, then the ISO over HTTP. On the software side, the Broadcom BCM57765 network chip needed a longer link wait after its PHY reset, plus 15 wrong register offsets corrected.

It boots all the way to the full Fasadas desktop, and it sees all 8 CPU threads of its i7-2760QM and about 8 GB of RAM. Firefox's crash reproduced on it too, which was actually good news: completely different disk, network card and GPU, so the bug was ours and not the Dell's hardware.
Hardware support on this model:
- Graphics: Intel 2D acceleration works on this model. It needed a forcewake fix (the code only knew Haswell) and a blitter buffer layout that collided with itself on the 1920x1200 panel. The Radeon doesn't work, and can't: it's already burnt out. That's the fate of the discrete GPUs in these models, from a bad solder batch. The Intel side works great, the whole laptop is still perfectly usable, and by the way it runs faster than my 2014 Dell Inspiron.
- Apple SMC support: a new driver for the controller behind fans, temperatures, the lid and the keyboard backlight. The MacBook answers with 435 keys and 2 fans.
- The gmux controller, which owns the display backlight on dual-GPU MacBooks.
- The multitouch trackpad: a port of Linux's bcm5974 driver, with the device table for the whole family, 36 models from 2008 to Force Touch.
- Apple media keys: screen brightness, keyboard illumination and volume are handled right in the kernel, so they work even at a text console. Along the way we found that Right Alt had always been Left Alt over USB, and Command had never worked at all.
And for completeness from the earlier weeks: a finger on the Panasonic CF-H2 rugged tablet's touchscreen now drives the Fasadas cursor and clicks.
Disks, filesystems and the installer
- Installer: installation is tested and working. In BIOS mode the OS boots from an ext4 root partition: Limine is installed to the MBR, and the kernel finds its root by UUID. ext4 is the default root filesystem since 26 August. The first full install on real hardware happened on the Dell on 30 August, after fixing a hardcoded path and a stale GPT header that made a 99%-finished install unbootable. There's also an upgrade mode that replaces the OS but merges your configuration, dpkg-conffile style, and both the console and graphical installers offer Install or Upgrade. Earlier, one install had produced a system where no file was executable, and it booted anyway, because exec didn't check the bit.
- ext4 got the real thing: extent trees, hashed directories, journal replay (so a crashed Linux filesystem mounts writable), a journal we actually write ourselves (previously replay could only rescue someone else's log), metadata checksums verified on read (the code used to mention checksums 158 times and compare exactly none), an on-disk orphan list so
unlinkandrmdiractually reach the platter, and partialftruncate. - Performance: a write-back block cache (which, it turned out, had never once satisfied a read, and was later silently disabled entirely by a missing pair of braces). A journal commit no longer happens after every single operation (it used to cost 130 ms per
write()). And disk writes now go out in disk order, elevator-style, which took the Dell's writes from 7.0 to 91.1 MB/s. - FAT12/16/32 read support with long file names, plus FAT writes.
Self-hosting, packages and the build service
- Self-hosting: AnotherOS now ships its own native GCC, G++ and binutils. A freshly installed disk compiles, links and runs C and C++ programs (iostream, the STL, exceptions) with no outside help, and a test proves the compiler is real by removing it and watching the build fail. The next stage is rebuilding ports on the device (a GNU m4 build is already written as a test arm), and after that, compiling the whole OS.
- Ports Build Service: an automated system that detects changes in the ports git tree, pulls them and builds new port versions, fixes and all. It's now a real service rather than a status page: priority queues and remote workers, projects with inheritance, organisations, signed webhooks from Forgejo, GitHub or GitLab, Telegram notifications, a compiler cache (ccache and sccache), and a signed repository index that
apkgverifies. Its best lesson: Firefox build 649 compiled for 2 hours 10 minutes, exited successfully, was recorded as "ok", and produced no package at all. The service now judges a build by the artefact it produced, not by the exit code. Another rule came from the same place: a setting that exists only in a config file does not exist, so everything is editable from the web interface. - Build service for releases:
make releasebuilds the kernel and userland here and slipstreams the published packages (80 of them, listed explicitly) straight into the image. - Experimental OS updates from the repository (kernel, userspace and ports): the building blocks are landing.
apkg upgradenow compares package digests, because two Firefox packages with the same version number differed in every byte oflibxul.so, and the oldapkgcalled that "up to date".apkg install --forcere-installs a package at the same version. Combined with the installer's upgrade mode, that's the basis for keeping an installed system current straight from the repository.
Plumbing that makes the rest possible
- The kernel command line grew: the buffer went from 256 to 1,024 bytes, after the Dell's network-boot line (about 330 bytes) was being silently cut off, taking the logging and desktop options at the end of it. The parameter registry went from 160 to 512 entries, after new debugging and subsystem parameters filled every slot. Many of those parameters are deliberate "install a bug on purpose" switches: every serious fix gets a control arm that boots the broken behaviour and proves the test turns red.
- Separate versioning of kernel and userspace: the kernel and userspace now carry their own build numbers,
kandu, so it's easy to identify which parts make up the running system. The desktop watermark shows both, andaversionis the userspace equivalent ofuname. This came out of a real incident: the kernel banner said build 664 while the desktop underneath was six weeks old. At the time of writing the counters read k1807 and u1447. - Automatic Forgejo project management: the agent creates and closes issues with labels (priority, type, area), registers problems itself, solves them later, closes tickets with the evidence, reopens them when needed, and writes the project documentation into the wiki. It isn't flawless: on 5 September the tool turned out to list only the newest 50 of 325 open issues, hiding all three P0-critical ones, and an agent had reported "zero open P0s" a few hours earlier. It's fixed, and yes, that one is also in the changelog.
Bugs of the season
Some bugs are too good not to share:
sysretqclobbered two registers on every signal return of every process.poll()never considered a regular file readable, soread var < filehung the shell forever, whileselect()answered correctly about the same file descriptor.uname -osaid GNU/Linux. Busybox's default. On both architectures.- The framebuffer console was slow because
memcpymoved one byte at a time. - A 4 GB Dell reported 4.7 GB of RAM (the PCI hole counted as memory), and
uptimereported a load of 0.00 at any load. - "PANIC" was a string, not a function call, in four places, so
panic=<seconds>could never reboot the machine. - A failed privilege drop in
loginwould have handed out a root shell, but only oncesetuidbecame real. - A
%#in a kernel log format swallowed the next argument, which froze the Dell, but only on diagnostic boots, because normal boots filtered that line out.
What's next
Where are we taking this project now?
- Win32 until it just works, then Win64. The appetite, remember.
- Self-hosting, phase two: ports rebuilt on the machine itself, then the whole OS.
- GPU everywhere: hardware 3D in the desktop through Grafika, and hardware video decode instead of software VP9.
- Fewer subsystems, not more: finish the Tinklas consolidation before I invent yet another name ending in "-as".
- Audio tested properly with real media players.
- The MacBook's Wi-Fi: the BCM4331 radio is recognised and enumerated, but not brought up yet.
- One day, the frozen i686 branch for the vintage collection.
As always, most of this will happen between Sunday and Wednesday. Thursday is for fireplaces.