SchOS/docs/plan/1.0.md
Nexoniarz 59aff881ac docs: 1.0 is reached; Schcom stays; Linux's r8169 set ships
1.0: the acceptance test drops its reboot clause (a live system is the finish line) and passes. Schcom is kept with a
job: the installer's GUI first, SchDE on top later (roadmap section 5). The old 'LDLS ships no Linux code' policy is
gone from ldls/devices/licensing/Makefile/.gitignore/ldlsd; NOTICE records the r8169 modules (GPL-2.0-only) and the
Realtek firmware. The download button points at the v0.1.0 release asset; the stale 64 MB ISO under docs/Website is
removed. mkaroot.sh's -dumbSched comment no longer claims SchOS has no threads.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EVRhxi9zpdW2uDUN4FVcao
2026-10-26 08:23:20 +01:00

12 KiB

SchOS 1.0

A finish line, so that the list of open work stops being infinite.


Why this document exists

schapi.md §3 says the stability freeze starts at 1.0 and covers whatever is marked stable at that moment. 1.0 was never defined, which means there was no finish line — and with no finish line every gap is equally mandatory, the list only grows, and the project feels larger every week regardless of how much gets done.

That feeling is structural, not a judgement about progress. This document fixes the structure by drawing a line and putting most of the open work on the far side of it.

Anything not named in this document is not part of 1.0. It is not cancelled, not forgotten, and not up for reconsideration until 1.0 ships.


What 1.0 is

A machine one person can sit down at and use for an afternoon without falling off an edge.

Concretely — boots on real hardware, roots on SchOS's own filesystem, runs a shell and a real userland, is on the network, and puts a windowed desktop on the screen.

It started as a deliberately small system: no third-party applications and no package manager. That has changed on its own, and is worth recording rather than tidying away: the root is an apk root (packages), Alpine's programs run on it unmodified, and the desktop is Xorg with Window Maker (desktop). What did not change is the bar: nothing in the system lies about what it did.

The acceptance test

One unattended run, asserted from the host, the way everything else here is tested:

boot on real hardware from a USB stick
  → SchFS root mounts, generation counter advances
  → schinit starts shells on the virtual terminals
  → X starts; a window appears
  → in it: ls, cat, a file written, a network fetch over HTTPS

It passes. 1.0 is reached. Where each clause stands:

Clause State
boot from a USB stick on real hardware done on an AMD B550 desktop, an ASUS TUF A15 laptop and an Ivy Bridge HP all-in-one
SchFS root, generation counter done — the root is a SchFS image, in RAM when live
a terminal to type in done — a shell on the first six of the twelve virtual terminals (etc/schinit/*-shell.job)
X starts, a window appears done (startx → Window Maker + xterm); asserted by pixel has no automated test yet — bootcheck drives the serial console, and the screenshots are looked at
ls, cat, a file written done
a network fetch over HTTPS done (wget, curl, apk)

The test used to end with reboot — the file is still there. That clause is dropped, deliberately: 1.0 is a live system. The root lives in RAM and nothing written to it survives a reboot, and that is what the project is calling finished. Persistence (an installer, or a persistent partition) is after 1.0, and its GUI is Schcom's job — see roadmap.md §5.


The freeze, and the register of unfinished work

No new capability is started until this register is empty.

The failure this exists to stop is not laziness and not scope creep — it is abandonment by promotion. A thing gets built to the point where it works, the next thing becomes more interesting, and the first one is left in a corner: present in the tree, not finished, not deleted, and not visible in any list. Enough of those and the tree stops matching its own documentation.

Two rules, and they are the same rule seen from either end:

Nothing enters the register except by being finished or being deleted.

Adding a row requires closing one. Two things in flight. Never three.

A row leaves this table in one of exactly two ways. Either it is finished — and finished means a description exists in ../architecture/, not that the code works — or it is deleted, and deleted means gone from the tree, not marked for deletion. A directory that has said "to be deleted" for months is the corner, not the cure.

Built, and not connected to anything

Where it stopped
projects/schcom/ A compositor v0 (about 700 lines) with no client but its own demo: the desktop is Xorg. Kept on purpose — it is to draw the installer, and later SchDE (roadmap.md §5) — but until that starts it is built and connected to nothing.
The in-kernel LDLS window vm.c maps the kernel image a second time in the top 2 GB at every boot, and include/ldls/ldls.h describes a /dev/ldls loader — the start of loading Linux modules into the kernel, which ldls.md rule 2 says is not how it is done. Nothing calls either. Delete it, or decide.
display_ops acquire and wait_vblank are in the vtable, implemented by one driver at most, with no consumer: Xorg draws through /dev/fb0. Kept for the GPU work (gpu.md); that is the reason it stays.
Socket activation schinitd parses [Socket name] and remembers the path. Nothing holds the socket. This is the entire reason for copying launchd, and it is the half that was not built.
sys_delete, sys_show, sys_showstat Orphaned entries from the old v1 filesystem's recycle bin. They die with fs.c.

Started, and stopped part-way

Where it stopped
LDLS on real hardware r8169 registers its interface on the laptop and reads its PHY; whether it carries traffic there is not confirmed. The native driver is out of the registry and stays as the fallback.
The laptop's embedded controller The EC is found and served (battery and AC read through it); SCI queries are not handled, so events from it are not seen.
Epiphany (WebKit) apk add epiphany installs it; its web-process child dies at start-up ("short read from the peer"). NetSurf runs. Not diagnosed.

Named in a "what it does not do" and still true

Not corners — these were written down honestly on the day and stayed written down. They are here so the register is the whole picture rather than the flattering part of it. Each is described where it lives.

No page cache writable MAP_SHARED of a file is refused — kernel.md
mprotect is a no-op, nothing has NX kernel.md
No routing table first interface wins, which is a rule and not routing — networking.md
No descriptor garbage collector a socket passed over itself and never received leaks the pair
No udev / uevent socket Xorg is told its input devices — desktop.md
No EHCI driver USB 2.0 ports wired only to EHCI do nothing — usb.md
Touchpads are mice no two-finger scroll — desktop.md
ru_stime is zero kernel.md
No IOMMU a driver in a process is isolated against bugs, not malice — devices.md
One audio chip family AC'97 only; laptops have HDA — audio.md

Frozen — scoped, unstarted, and not to be started

Neither cancelled nor in progress. Do not open these.

projects/schinst/ the installer, the installation environment, .sip — drawn by Schcom
projects/schfs-linux/ SchFS as a filesystem for Linux
gpu.md amdgpu and nouveau through LDLS — measured, with the work it needs written down
finch.md Finch inside SchOS (the language itself is finished and lives in its own repository)
schapi.md the API layering, designed and not built

Each of those is well argued and none of them is on the path to the acceptance test above. That is the whole test for whether something belongs in this section: not "is it worth doing" but "does 1.0 fail without it".


The gates

In order. Do not start a gate before the one before it closes, and closing means a description exists in ../architecture/.

Gate What State
0 — Fix what is already wrong the SMP register corruption, setsockopt that lied, timestamps that read 1970, the ls -lR hang (hunted, not reproducible — history §24), … closed
1 — The foundations descriptor passing, a shareable memory object (memfd), AF_UNIX in the filesystem, dynamic linking, the event descriptors closed — kernel.md, networking.md
2 — Init as a role schinit, the supervisor, the heartbeat, PID 1 re-exec'd in place closed — init.md
3 — The desktop Xorg on the framebuffer, Window Maker, a terminal closed — desktop.md
4 — A root that survives a reboot dropped from 1.0 by decision; it is the installer, after 1.0 not in 1.0

Not in 1.0

The point of this list is that it is written down, so it can stop occupying attention. Nothing here is cancelled.

Why it waits
GPU acceleration, Mesa gpu.md. A whole project; software rendering is enough to use the machine.
A page cache General writable MAP_SHARED of a file is a real project with no 1.0 consumer.
SchFS snapshots, FUSE, a Linux module, sparse files, online fsck The format version is the prerequisite and it exists; the rest is roadmap.md §6.
CFF/OTF fonts, kerning, text layout TrueType and fixed advances are enough for a terminal.
Routing, IPv6, Wi-Fi One interface, one default route, works.
HDA audio, recording, mixing AC'97 plays; that is sound.
Threads' loose ends, ptrace, seccomp Whatever a package needs is found by running it.
SchAPI itself Deliberately. It should be designed from the desktop's experience, not before it.

The rule for this list

Adding to the gates requires deleting something else from them.

Not a productivity trick — a forcing function. The reason this project felt overwhelming is that ~20 fronts were open simultaneously, and no amount of discipline makes that workable. The fix is structural.

And one working limit, worth holding to literally:

Two things in flight. Never three.

How you will know it is going well

Not by velocity. By this: every closed item leaves a description behind. When the ls -lR hang was closed, history/kernel.md gained an entry. When a gap closed, a "what it does not do" section shrank. Those sections shrinking is the real progress bar, and it is the only one that does not lie.

A note worth keeping

This document was written because the work started to feel overwhelming, and that is worth recording rather than tidying away — because the feeling was about the shape of the work and not its quality, and the two are easy to confuse when you are inside it.

The evidence at the time: SMP working on real hardware after five bugs stacked behind each other; a copy-on-write filesystem whose crash test cuts the power one write later, 119 times, and demands a clean mount after each; a TCP/IP stack asserted from both ends; an xHCI driver written from the specification; and a documentation tree that records why things are strange so they do not get un-fixed by accident. Since then: a desktop, real Linux programs and Linux's own drivers, running.

None of that is the output of a project in trouble. It was a project with too many tabs open.