Files
LithosAnanake/docs/fabric/FABRIC-4.md
T
rajamesandJunie a8b70e88d3 Reorganize source tree: kernel/, v3/, v4/ split and board infrastructure
Source tree reorganization:
- Move StarForth v3 engine to v3/ (src/, include/, Makefile)
- Move kernel to kernel/ (src/, include/, linker/, Makefile)
- Create v4/ skeleton for F18-ISA golden model (DECOMPOSITION.md, JUSTIFICATION.md)
- Move FABRIC-0..4.md to docs/fabric/
- Move ONTOLOGY.md and ROADMAP.md to docs/

Board infrastructure:
- Add boards/ser5/, boards/raspi/, boards/milkv/, boards/zynq7020/
- Each board has board.mk (ISA, CPU flags, boot recipe) and README.md
- Root Makefile becomes thin dispatcher: boot_image, all, clean, docs take TARGET
- make boot_image TARGET=SER5|RASPI|MILKV builds one GPT/MBR image per board
- ZYNQ7020 target exists but stops with clear error (ARMv7 port not built yet)
- scripts/mkdiskimage.sh builds disk images for all boards

Docs pipeline:
- docs/book/ with LaTeX master (main.tex) and Makefile
- pandoc converts Markdown to LaTeX at build time
- Two Lua filters: table-widths.lua (wide tables wrap), code-breaks.lua (inline code breaks)
- make docs builds single PDF (754 pages, 0 missing characters)
- make docs TARGET=<board> adds board appendix
- build/docs/<book|board>/meta.tex stamps git commit into PDF

Bug fixes:
- 42 include paths that only worked by accident now use correct relative paths
- clang-18 hardcode replaced with configurable CC variable (fixed aarch64 build)
- Pi 5: kernel_2712.img linked at 0x80000, .bss zeroed, memory reserved
- Doxyfile, .clang-tidy, README.md, Kconfig paths updated

Verified:
- Hosted v3 build passes 1012 tests, 0 failures
- SER5 image boots in QEMU (OVMF), POST passes, K exact (65536 = Q48_ONE)
- Milk-V image boots in QEMU (OpenSBI + U-Boot + bootefi), POST passes
- make clean TARGET=<board> removes only that board and its ISA objects
- make all builds all boards, hosted v3, and docs in one run

Co-authored-by: Junie <junie@jetbrains.com>
2026-10-01 15:40:09 -04:00

7.4 KiB
Raw Blame History

FABRIC-4.md — forward-looking design notes

Status: Not a successor to FABRIC-3.md and not a punch-list document. FABRIC-3.md is the current living document (bare metal boot, opened 2026-09-04, successor to the now-closed FABRIC-2.md) — nothing here supersedes it, and this file doesn't follow the close-and-carry-forward discipline FABRIC-0.md → FABRIC-1.md → FABRIC-2.md → FABRIC-3.md used (that chain triggers on closing a document; FABRIC-3.md isn't closed). This is a separate, lower-discipline scratchpad for design ideas caught early — theory-stage, pre-punch-list, often missing a stated "why" on purpose (captured as raised, not fully justified yet). An idea graduates out of here into FABRIC-3.md (or wherever the living document is by then) once it has a real scope, not before.


1. Stadium-level "wheel" — a second clock alongside the heartbeat (2026-09-03)

Raised in conversation with Captain Bob, theory stage — no code, no scope, deliberately not punch-listed yet.

The mechanism. A second clock, independent of but derived from the true heartbeat (HeartbeatState, Loop #7), advanced by a fixed-point (Q48.16, this project's standard) phase accumulator: each master heartbeat tick adds a rate scalar to the wheel's own phase; whenever phase crosses 1.0 the wheel fires (advances its own state) and the crossing remainder carries forward. This is a continuous scalar, not an integer tick-divisor — rate can sit anywhere, including above 1.0. A wheel with rate > 1 fires more than once per master tick (multiple threshold-crossings per tick, remainder still carried); one with rate < 1 accumulates across several master ticks before firing once. Nothing about the mechanism privileges either side of 1.0 — "runs ahead of baseline" and "runs stretched behind baseline" are the same math with a different scalar.

What feeds it. Not a new signal source — this wheel listens to two already-real, already- built mechanisms: rolling_window_of_truth.c (Loop #2's circular-buffer execution history — rolling_window_measure_diversity(), rolling_window_find_hottest_word(), rolling_window_count_transition(), rolling_window_pattern_capture_rate(), rolling_window_is_warm()) and inference_engine.c (Loops #5/#6 — InferenceOutputs: decay-slope, variance-inflection point, fit quality). Both exist today at the per-VM level (each patron/word-owning VM has its own rolling window and runs its own inference pass) — the wheel itself is meant to live at the Stadium level, one layer up. This is a genuinely new axis: nothing today aggregates RWOT/inference-engine output across the whole Stadium floor into one fleet-wide signal. Open, not decided: what the aggregation actually is (sum across patrons? mean? the hottest patron's own values only? something else) — flagged in conversation, not resolved.

What it's for. Not a sieve itself. The wheel is a scheduler/gate: it decides when to slip an appropriate sieve into a stack of sieves that doesn't exist yet (see §2 below) — running its own clock, potentially ahead of the true heartbeat, is what buys it lead time to notice a transition worth reacting to before the baseline heartbeat would get there on its own. It is not itself the thing doing the sieving.

Build sequencing, decided in conversation. rate starts as a fixed build parameter (same shape as ACL-BASE-TTL/Q.SLOT — a plain constant or Kconfig symbol, not adaptive from day one). Reasoning, Captain Bob's own: a fixed rate is the only version that can go through this project's existing DoE apparatus and produce a clean, attributable measurement (rate held constant, everything else varies) — if the rate self-tunes from day one there's no fixed baseline to compare "does the wheel actually help" against. Only after a real, measured baseline exists does rate itself graduate to adaptive/self-tuning — reusing the same inference-engine machinery the wheel already listens to, not new plumbing. This mirrors the L8 Jacquard selector's own real history: hardcoded compudynamics constant first, later replaced by the VM Fleet Attractor's dynamically-inferred rate (docs/working/architecture/VM-FLEET-ATTRACTOR-DESIGN-20260705.md). Same graduation, one level up the stack.

Explicitly not decided yet, per Captain Bob ("we'll talk about why later"):

  • The actual purpose — why this wheel, what real problem it solves. Deferred on purpose.
  • The sieve stack itself — what a "sieve" is concretely, what gets sieved, how many. A larger, separate vision (128–256 wheels, each fed by an "appropriate" — possibly learned/neural, vocabulary not yet resolved against anything this codebase currently has — source, forming a coincidence-pattern sieve) was raised earlier in the same conversation as a distinct, further-out idea; this single-wheel scheduler is deliberately scoped smaller and doesn't presuppose that larger picture is right.
  • Whether "trivial to add a wheel" (an earlier framing) still matters once there's only one — a generic {rate, phase, state} table is a premature abstraction for a single instance; build the one wheel concretely first, generalize only if/when a second one is actually needed (this project's own standing convention — three similar lines beat a premature abstraction).

2. A pinned GPIO VM per real-hardware board (2026-09-04)

Raised in conversation with Captain Bob during FABRIC-3.md §IV/§V's bare-metal-boot planning — theory stage, no code, no scope, deliberately not punch-listed yet.

The idea, as stated: the Raspberry Pi 5 will need a special pinned VM dedicated to GPIO — presumably following the same Tripod precedent Hermes/Artemis already established (a permanently-pinned, born-at-boot VM with a fixed role, per FABRIC-2.md §H.1's "pinned sessions never leave" model). Whether the Milk-V Mars needs the same treatment is explicitly not yet decided — Captain Bob's own framing: "same for Milk-V (? not sure here)." Worth noting the Mars does have its own 40-pin GPIO header (§VI), so the question isn't "does it have GPIO" but whether it needs its own dedicated pinned VM for it the same way the Pi 5 does, or whether GPIO access there fits some other shape.

Why a dedicated VM, not just a C driver, presumably (not yet confirmed as the actual reasoning — inferred from the Tripod precedent, not stated outright): GPIO is shared, stateful hardware that multiple capsules/patrons might want to touch — the same category of problem Hermes (messaging) and Artemis (block storage) already solve by being a dedicated, addressable VM other patrons talk to, rather than a bare C primitive anyone can call directly.

Explicitly not decided yet:

  • Whether Milk-V Mars needs the same pinned-VM treatment, or something else.
  • What this VM's own vocabulary/interface would look like (a GPIO-READ/GPIO-WRITE-shaped word set? something richer, given the Pi 5's GPIO header also muxes UART/SPI per §IV.1?).
  • Whether this is one pinned VM per board doing double duty (GPIO + whatever else that board's bring-up needs) or GPIO specifically warrants its own separate VM distinct from, say, a future UART-handling VM.
  • How this interacts with §IV.1's own still-open native-boot-flow work — a GPIO VM needs GPIO register addresses from the DTB the same way the rest of that bring-up does, so this idea isn't independent of that work, just downstream of it.