Claude Code keeps per-project memory at <home>/.claude/projects/<key>/,
where <key> is the project's absolute path with every separator and the
drive colon turned into a dash. That makes it both rename-fragile and
machine-specific, and this project has hit each of those once:
- D:\DEV\Schunix -> D:\DEV\SchOS changed the key, and 43 memories were
invisible until moved across by hand.
- Development happens from Windows and from Linux, and each looks in a
different place for the same checkout.
Committing .claude/memory/ fixes both -- git carries it across renames
and between hosts -- and `import` puts it wherever the local machine
expects. .claude/settings.local.json stays ignored: those are per-machine
permissions.
The colon maps to a dash rather than being dropped. Deleting it gives
D-DEV-SchOS, which matches nothing and silently finds zero memories; that
was the first attempt. On Git Bash the key comes from `cygpath -w`,
because Claude Code is a Windows program and sees D:\DEV\SchOS, not
/d/DEV/SchOS.
2.7 KiB
| name | description | metadata | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| schunix-wall-clock | The clock read 1970 because nothing ever called cmostime(); kernel/core/time.c now reads the RTC at boot. |
|
Fixed 2026-08-08. Nexoniarz reported "time has stopped, or it's just too slow —
type date, wait 10 seconds, it's still the same or pretty close."
The clock was not stopped. ticks advanced correctly (measured: uptime
19.81 → 34.51 over ~14 real seconds, identical at -smp 1 and -smp 2). The
bug was the origin: sys_gettimeofday, sys_clock_gettime and sys_time all
returned ticks / 100 — seconds since boot, presented as seconds since the
epoch. So every machine believed it was 1 Jan 1970 and the date crawled at
the rate of its own uptime. cmostime() in kernel/arch/x86_64/lapic.c could
read the hardware clock the whole time and had no caller.
kernel/core/time.c now reads the RTC once in main() (after the timer is
running, before userspace), converts it with Howard Hinnant's
days_from_civil, and stores boot_epoch. wallclock(&sec, &usec) is the one
place that answers "what time is it", so the three syscalls cannot disagree.
days_from_civil, not a loop over years — branchless, exact for any year, no table. Accumulating 365/366 since 1970 gets leap centuries wrong unless you remember 1900 was not a leap year and 2000 was.- RTC read once, not per call — it is polled over two I/O ports and must be sampled twice to catch it mid-update.
- Interpreted as UTC. A PC that has had Windows on it usually keeps the RTC
in local time, but there is no timezone store and nowhere to ask.
dateshows UTC; Nexoniarz is UTC+2 in summer, so it reads two hours behind local. When a settings store exists, the offset goes intime_init(). CLOCK_MONOTONIC(clkid 1) subtractsboot_epoch; everything else is treated as realtime.- Implausible CMOS readings leave
boot_epochat 0, i.e. the old behaviour, rather than putting the machine in the Bronze Age.
Verified: Sat Aug 8 19:36:43 UTC 2026, advancing 14s in 14 real seconds, host
at 21:37 CEST.
The stale-image trap, now guarded
A running QEMU holds build/fs.img open; on Windows rm then fails with
"Device or resource busy", and make stops after the kernel has already
relinked. The next test boots the previous kernel and the change looks like
it did nothing. This cost several cycles across the session. The fs.img rule
now prints what is wrong and how to clear it. When a fix appears to have no
effect, check schunix.img's timestamp before debugging the code.