xmake # Build kernel
xmake run # Run in QEMU
xmake clean # Clean build artifacts
xmake -bv Test # Build tests (verbose)
xmake run Test # Run all tests (no single test target)
xmake setup-hda # Create disk image
xmake build-initrd # Build initrd
xmake config-initrd # Configure initrd interactively
xmake analyze # Analyze kernel runtimeBuild outputs: build/FKernel.bin, build/FKernel-MockOS.iso, build/FKernel-HDA.qcow2.
- LibC - Freestanding C library (strings, memory, types)
- LibFK - STL-like library, depends on LibC + self only
- Kernel - Depends on LibFK only, NEVER LibC directly
LibC (std types) → LibFK (std containers) → Kernel (drivers, scheduling, VFS, IPC)
Violations are build errors. LibFK defines the boundary between LibC and Kernel.
Only these two files may include LibC directly:
Src/Kernel/Io/kernel_puts.cpp— implements kprintf output routingSrc/Kernel/Arch/x86_64/Panic/Panic.cpp— panic handler (runs before logging init)
LibFK MUST NOT include Kernel headers. Use the allocator backend pattern
(LibFK/Memory/allocator_backend.h) for Kernel-injected callbacks.
xmake check-layers # Verify layer separation| LibC | LibFK Equivalent |
|---|---|
<LibC/stdint.h> |
<LibFK/Types/types.h> |
<LibC/stddef.h> |
<LibFK/Types/types.h> |
<LibC/string.h> |
<LibFK/Utilities/Memory.h> |
<LibC/stdio.h> |
<LibFK/Algorithms/log.h> |
<LibC/stdarg.h> |
<LibFK/Algorithms/log.h> |
memcpy/memset/memmove/memcmp |
fk::memory::copy/set/compare/move |
strlen/strcmp/strcpy/strcat |
fk::memory::length/compare/copy_string/concatenate |
strncpy/strncmp/strncat |
fk::memory::copy_n/compare_n/concatenate_n |
kprintf() |
fk::algorithms::klog/kwarn/kerror |
snprintf() |
fk::algorithms::format() |
// LibFK
namespace fk::containers { } // Vector, HashMap, List
namespace fk::text { } // String, StringBuilder
namespace fk::memory { } // Smart pointers
namespace fk::core { } // Result, Error
namespace fk::algorithms { } // CRC32, DJB2
// Kernel
namespace fkernel::boot { }
namespace fkernel::cpu { }
namespace fkernel::memory { }
namespace fkernel::process { }
namespace fkernel::fs { }
namespace fkernel::drivers { }| Rule | Example |
|---|---|
| 1 indentation level per method | Extract helper methods, no nested if in loops |
No else |
Early returns instead |
| Wrap all primitives | ProcessId not int, BlockSize not u64 |
| First-class collections | ProcessList class, not raw Vector |
| 1 dot per line | process->thread_name() not process->thread()->name() |
| No abbreviations | ProcessManager not ProcMgr |
| Keep entities small | Class ≤200 lines, method ≤20 lines, file ≤500 lines |
| Max 2 instance variables | Compose objects instead |
| No getters/setters | is_running() / block() not state() / set_state() |
SECRET RULE: One struct/class per file. File name matches class name.
All kernel subsystem singletons must follow this canonical form:
namespace fkernel {
class FooManager {
bool m_is_initialized{false};
FooManager() = default;
FooManager(const FooManager &) = delete;
FooManager &operator=(const FooManager &) = delete;
public:
static FooManager &the() {
static FooManager inst;
return inst;
}
bool is_initialized() const { return m_is_initialized; }
void initialize(); // must set m_is_initialized = true at end
};
} // namespace fkernel
using fkernel::FooManager; // backward-compat aliasRules:
- Private default constructor + deleted copy/move (no external instantiation)
is_initialized()lets boot code assert on success- All managers live in
fkernel::namespace initialize()must guard against double-init and setm_is_initialized = trueat end- Boot flow (
init.cpp) must assertis_initialized()after eachinitialize()call
Before changing existing architecture:
- Search for an existing abstraction — grep the codebase for similar patterns, interfaces, or utilities.
- Reuse it if possible — prefer composition or extension over creating new constructs.
- If introducing a new abstraction, justify:
- Why existing abstractions are insufficient.
- Trade-offs (complexity, performance, maintenance burden).
- Impact on layering (LibC/LibFK/Kernel boundaries).
- Migration path from current code to the new abstraction.
Violations of this policy must be called out in code review.
Result<Page*, Error> allocate_page(); // Fallible operations
auto page = TRY(allocate_page()); // Propagate errors
fk::Optional<Process*> find_process(ProcessId pid); // Nullable values- Classes: PascalCase (
ProcessManager) - Methods: snake_case (
initialize_processes()) - Members:
m_prefix (m_process_count) - Constants: UPPER_SNAKE_CASE (
MAX_PROCESSES) - Namespaces: snake_case (
fkernel::memory) - Directories: PascalCase (
Src/Kernel/Posix/) - Files: snake_case (
topology_manager.cpp) - 2-space indentation, opening braces on same line
- No
<iostream>,<vector>,<string>— use LibFK equivalents - No exceptions, no RTTI. Use
Result<T, Error>for errors - Use
volatilefor hardware registers; memory barriers when needed - RAII preferred, stack allocation preferred,
OwnPtr/RefPtrfor heap
All source and header files MUST use snake_case naming. No exceptions.
| Convention | Examples | Wrong |
|---|---|---|
| Headers | error.h, string_builder.h, process_id.h |
Error.h, StringBuilder.h, processId.h |
| Sources | scheduler_manager.cpp, tcp_socket.cpp |
SchedulerManager.cpp, TcpSocket.cpp |
- Use
git mvfor renames to preserve history - After renaming, update ALL
#includedirectives that reference the old name - One struct/class per file. File name matches class name in snake_case
- Directory cleanup tracked in TODO.md Phase 22
- System headers (LibC)
- LibFK headers
- Kernel headers
- Local headers
Src/Kernel/ # Kernel implementation
Src/LibC/ # Freestanding C library
Src/LibFK/ # STL-like library
Include/ # All headers (mirrors Src/)
Meta/ # Build tools and scripts
Docs/ # Documentation
tests/ # Unit tests (pattern: tests/[component]/test_[module].cpp)
.ai-docs/ # AI conceptual memory
.gemini/ # Validation scripts (tooling, not docs)
Full directory tree: Docs/directory-structure.md.
- LibC: 90%+ coverage required
- LibFK: 85%+ coverage required
- Kernel critical paths: 75%+ coverage
- All public APIs must have tests
- New LibFK/LibC PRs require test additions
- Kernel changes MUST include regression tests for the modified subsystem
- Test for edge cases: null inputs, boundary values, error paths, concurrent access
- Framework: custom (see
tests/test_framework.h)
All algorithms used across multiple domains belong in LibFK/Algorithms/:
- Archive: TAR, ZIP, GZIP
- Compression: LZ4, ZLIB, DEFLATE
- Checksum/Hash: CRC32, MD5, SHA256
- Encoding: Base64, Hex, URL
- Parsing: INI, JSON, ELF, PE
- Compiler flags:
-ffreestanding,-fno-exceptions,-fno-rtti,-mcmodel=kernel,-mno-sse - Use
volatilefor MMIO,__sync_synchronize()for memory barriers - Document against hardware specifications
| Function | Use Case | Behavior |
|---|---|---|
fk::algorithms::klog(PREFIX, fmt, ...) |
Normal operations, init | Returns |
fk::algorithms::kwarn(PREFIX, fmt, ...) |
Warnings, degraded ops | Returns |
fk::algorithms::kerror(PREFIX, fmt, ...) |
Unrecoverable errors | Halts CPU (proposed: split into kfatal() halt + kerror() non-halting) |
fk::algorithms::kdebug(PREFIX, fmt, ...) |
Debug diagnostics | Returns |
fk::algorithms::kexception(PREFIX, fmt, ...) |
Exception handlers | Returns |
// ✅ Good — UPPER_SNAKE_CASE, max 20 chars
fk::algorithms::klog("SCHEDULER", "Task %d migrated to CPU %d", pid, cpu);
fk::algorithms::kwarn("NVME", "Sector size mismatch: expected %u", expected);
fk::algorithms::kerror("MEMORY", "Page alloc failed: order=%u", order);
// ❌ Bad — mixed case, hyphens, lowercase
fk::algorithms::klog("Scheduler Manager", ...); // mixed case
fk::algorithms::klog("NVMe-REG", ...); // hyphen
fk::algorithms::klog("sys_reboot", ...); // lowercase- Never use raw
kprintf()in kernel code — always usefk::algorithms::klog/kwarn/kerror - Never use
kerror()for recoverable errors — it halts; usekwarn()instead - Include context in error messages — error code, path, relevant values
- Log at INFO level during subsystem init — helps debug boot order issues
- Use
kdebug()for hot paths — may be stripped in release builds - Route panic through logging — ensure panic messages reach dmesg ring buffer
Controlled by bitmask: Serial (COM1), Display (VGA), DebugFS (ring buffer).
Include/LibFK/Algorithms/log.h— log function definitionsDocs/Kernel/Logging/README.md— full architecture.ai-docs/development-patterns/kernel-logging.md— AI agent conventions
Docs/
├── Architecture/ # system-overview.md, design-philosophy.md
├── Domains/ # Per-subsystem guides (vfs, memory, scheduling, etc.)
├── Kernel/ # Per-subsystem README stubs (Boot, Process, Syscalls, VFS)
└── directory-structure.md
- Diagrams: Use Mermaid for ALL architecture/flow diagrams. No ASCII art in Docs/.
- Math: Use MathJax (
$$...$$) for algorithms with mathematical formulas. - Accuracy: Docs must match actual source code. When in doubt, read the source first.
- Staleness: When modifying kernel subsystems, update the corresponding Docs/ file in the same session.
- Cross-references: Link between related Docs/ files using relative markdown links.
- Completeness: Fill empty README stubs with actual content (architecture, key files, data flow).
| File | Subsystem | Key Diagrams |
|---|---|---|
process-scheduling.md |
Scheduler | State machine, work-stealing, context switch |
vfs-architecture.md |
VFS | Layer architecture, path resolution, mount overlay |
ipc-capabilities.md |
IPC | Capability model, revocation, signal delivery |
memory-management-guide.md |
Memory | Init flow, buddy allocator, page tables |
drivers-framework.md |
Drivers | PCI matching, storage stack, hardware discovery |
networking.md |
Network | TCP/IP stack, TCP state machine |
elf-loader.md |
ELF | Loading pipeline, security features |
- Read the corresponding source files first
- Replace ASCII diagrams with Mermaid
- Add MathJax for mathematical algorithms
- Update status/percentages to match reality
- Add new components discovered in source
- Remove stale information
- Read
.ai-docs/before making changes; update it for significant modifications - Layer separation is non-negotiable — never add LibC calls in Kernel code
- Architecture changes require justification — search existing abstractions first (see "Architecture Change Policy")
- Scheduler runs at CPL 0 with interrupts disabled; shared data needs interrupt-safe locking
- Every struct/class goes in its own file (SECRET RULE)
- Always update Docs/ when modifying kernel subsystems — keep documentation in sync
- Always write tests when modifying kernel code — regression tests for the modified subsystem