FABRIC.md: rule GAP-A1 — the engine tick is virtual
Captain Bob's ruling on §25.7.1 GAP-A1, adopting the recommended resolution. The engine's tick is a virtual tick: a pure, deterministic function of the execution stream, which is what exists today and why parity holds today. The hardware heartbeat is the TIME-TRUST instrument and the idle wake source, and drives nothing that feeds patron state. When the system idles, the REPL poll loop pumps virtual ticks so TTLs still expire in real time, in a context where parity was never claimed. Applied to: §16.4 (correction appended -- the fire-on-tick-count rule was necessary but not sufficient, since the hash measures the composition of the instruction and tick streams, not the engine's schedule alone); §17.1 (the one clock is the virtual tick, and the mechanisms cannot be split across clocks because TTL expiry has instruction-stream side effects); §18.4 (L0 advances on the virtual tick); item 0.8 (disambiguated -- the hardware tick drives instrumentation only, vm_tick call sites unchanged); item 2.1 (transfer restates onto the virtual tick, which is what makes its identical-sum acceptance achievable). Item 0.10 needed no change: with the engine execution-paced, its double-boot check is a valid regression guard and amd64 is genuinely a control again. Phase 0's timer bring-up stands: it makes the instrument real on three ISAs and is the substrate SMP will need. It does not drive the engine. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
e8f8b098ed
commit
11c8678477
@@ -598,7 +598,27 @@ works: `adaptive_check_accumulator` / `adaptive_pending` (`include/vm.h:113-114`
|
||||
**DECIDED** unless argued — it is a constraint inherited from what the system already
|
||||
claims, not a new preference.
|
||||
|
||||
### 16.5 What this implies about order
|
||||
#### Corrected by the GAP-A1 ruling — the tick is virtual
|
||||
|
||||
The rule above ("fire on tick count, never on elapsed wall time") was necessary but not
|
||||
sufficient, and its inference — *same tick ordinal → same hash* — was unsound. The hash
|
||||
covers `execution_heat`, which is co-written by **two streams**: word executions and engine
|
||||
ticks. A hardware timer makes the *interleaving* of those streams wall-clock-dependent
|
||||
under TCG, so same-per-tick actions do not compose into the same hash. See §25.7.1 GAP-A1
|
||||
for the full argument.
|
||||
|
||||
**RULED 2026-08-03:**
|
||||
|
||||
> **The engine's tick is a virtual tick — a pure, deterministic function of the execution
|
||||
> stream.** This is what exists today (`vm_tick()` paced every N executions) and it is why
|
||||
> parity holds today. The hardware heartbeat is the TIME-TRUST instrument, the idle wake
|
||||
> source, and the driver of **nothing that feeds patron state.** When the system is idle,
|
||||
> the REPL poll loop pumps virtual ticks so TTLs still expire in real time — a context in
|
||||
> which parity was never claimed.
|
||||
|
||||
Phase 0's timer bring-up remains fully justified: it makes the instrument real on three
|
||||
ISAs instead of one, and it is the substrate SMP will eventually need. What it does not do
|
||||
is drive the engine.
|
||||
|
||||
Whatever step one turns out to be, it now has a floor under it: real timer interrupts and
|
||||
a real IRQ return path on all three ISAs. §10's sequencing (Hermes first, as the proving
|
||||
@@ -654,13 +674,18 @@ Mapped per patron:
|
||||
|
||||
#### Two measures, one clock
|
||||
|
||||
This does **not** mean two clocks. Both mechanisms advance off the same tick — the
|
||||
adaptive heartbeat. TTL decrements on a tick; heat decays on a tick. They are two different
|
||||
This does **not** mean two clocks. Both mechanisms advance off the same tick — **the
|
||||
virtual tick of §16.4 as ruled**, a deterministic function of the execution stream, not the
|
||||
hardware heartbeat. TTL decrements on a tick; heat decays on a tick. They are two different
|
||||
*readings* of one counter, not two independent time sources.
|
||||
|
||||
That is not a tidiness preference, it is forced. §16.4 requires the engine to fire on tick
|
||||
count so that the same input reproduces the same dictionary hash. Two independent clocks
|
||||
would be two independent sources of nondeterminism and parity would not survive it.
|
||||
That is not a tidiness preference, it is forced — twice over. §16.4 requires the engine to
|
||||
fire deterministically so the same input reproduces the same dictionary hash. And the
|
||||
mechanisms cannot be split across clocks: TTL expiry has side effects on the instruction
|
||||
stream (a message expiring versus delivered changes what runs next), so a wall-clock TTL
|
||||
would corrupt heat downstream even if heat itself stayed execution-paced. One virtual
|
||||
clock for everything that touches patron state; the hardware heartbeat observes and wakes,
|
||||
never drives.
|
||||
|
||||
> **One tick. Two measures. Three mechanisms.**
|
||||
|
||||
@@ -1034,15 +1059,17 @@ dispatch function over a closed tag set, not in the engine asking patrons what t
|
||||
|
||||
### 18.4 One tick
|
||||
|
||||
L0 advances on the adaptive heartbeat. Everything derived from time is derived from that
|
||||
one counter:
|
||||
L0 advances on **the virtual tick** — a deterministic function of the execution stream, per
|
||||
the §16.4 ruling. Everything derived from time is derived from that one counter:
|
||||
|
||||
- TTL decrements per tick (messages, ACLs)
|
||||
- Heat decays per tick (blocks, words)
|
||||
|
||||
Two measures, one clock — see §17.1. §16.4 forces this: the engine must fire on tick count
|
||||
for the same input to reproduce the same dictionary hash, and two independent time sources
|
||||
would be two independent sources of drift.
|
||||
Two measures, one clock — see §17.1. §16.4 as ruled forces this: patron state must advance
|
||||
deterministically for the same input to reproduce the same dictionary hash, and the
|
||||
hardware heartbeat cannot supply that, because its interleaving with the instruction
|
||||
stream is wall-clock-dependent. The heartbeat's roles are the TIME-TRUST instrument and
|
||||
the idle wake source; when the system idles, the REPL poll loop pumps the virtual tick.
|
||||
|
||||
### 18.5 CLOSED — the adaptive rate does not break determinism, and here is why
|
||||
|
||||
@@ -2018,12 +2045,14 @@ on until there is a tick on all three architectures (§16.1, §16.5).*
|
||||
*Done when:* `heartbeat_ticks()` advances on aarch64 at the configured rate.
|
||||
|
||||
- [ ] **0.8 — Converge the three architectures on one tick path.**
|
||||
One `heartbeat_tick()` call site per architecture; ISR does counter and flag only;
|
||||
the engine runs in the mainline off the pending flag. Reuse the existing
|
||||
`adaptive_check_accumulator` / `adaptive_pending` pattern rather than inventing a second.
|
||||
*Done when:* all three architectures drive the same bottom half, and no loop math runs in
|
||||
interrupt context.
|
||||
*Refs:* §18.4, §21.2.
|
||||
One `heartbeat_tick()` call site per architecture; the ISR does counter, timestamp and
|
||||
flag only. **Per the GAP-A1 ruling, the hardware tick drives instrumentation only:** the
|
||||
bottom half services TIME-TRUST bookkeeping, and the engine (`vm_tick()`, decay,
|
||||
inference) stays on the virtual tick — execution-paced, exactly as today. Nothing that
|
||||
feeds patron state reads the hardware counter.
|
||||
*Done when:* all three architectures drive the same TIME-TRUST bottom half; no loop math
|
||||
runs in interrupt context; and `vm_tick()`'s call sites are unchanged.
|
||||
*Refs:* §16.4 (as ruled), §18.4, §21.2.
|
||||
|
||||
- [ ] **0.9 — Write the concurrency constraint at the mutex stub.**
|
||||
Add a comment at `src/starkernel/vm/host/shim.c:415` stating that the no-op is correct
|
||||
@@ -2103,12 +2132,16 @@ document and committing that amendment as its own item.*
|
||||
|
||||
## 25.3 Phase 2 — Prepare the existing physics
|
||||
|
||||
- [ ] **2.1 — Restate heat transfer on tick count.**
|
||||
- [ ] **2.1 — Restate heat transfer on the virtual tick.**
|
||||
`vm_physics_touch()` scales transfers by wall-clock elapsed time
|
||||
(`capsule_vm_physics.c:272`). Restate it on tick count.
|
||||
(`capsule_vm_physics.c:272`). Restate it on **the virtual tick** — the execution-derived
|
||||
counter of §16.4 as ruled, not the hardware heartbeat, whose interleaving with execution
|
||||
is wall-clock-dependent and would leave the acceptance below unachievable (§25.7.1
|
||||
GAP-A1).
|
||||
*Done when:* no wall-clock value influences heat, **and the same capsule booted twice
|
||||
produces an identical fleet heat sum across the two runs.**
|
||||
*Refs:* §18.5, §19.6 #3.
|
||||
produces an identical fleet heat sum across the two runs** — achievable now that both
|
||||
the touch points and the elapsed-tick values are deterministic functions of execution.
|
||||
*Refs:* §16.4 (as ruled), §18.5, §19.6 #3.
|
||||
|
||||
> **Acceptance corrected.** This item previously accepted on the dictionary-hash
|
||||
> double-boot check from 0.10. That cannot detect this work: §18.5 establishes that
|
||||
@@ -2219,7 +2252,14 @@ so.*
|
||||
for what would break a lower-capability model working the punch list. Nothing here has been
|
||||
fixed. GAP-A1 needs a ruling before item 0.8 is coded; the rest are queued for triage.*
|
||||
|
||||
#### GAP-A1 — §16.4's central inference is unsound. NEEDS RULING BEFORE PHASE 0 CODING.
|
||||
#### GAP-A1 — §16.4's central inference is unsound. ~~NEEDS RULING~~ **RULED 2026-08-03: virtual tick.**
|
||||
|
||||
> **Applied.** The recommended resolution below was adopted by Captain Bob. §16.4, §17.1
|
||||
> and §18.4 now carry the ruling; items 0.8 and 2.1 were reworded to it. Item 0.10 needed
|
||||
> no change: with the engine staying execution-paced, its double-boot dict-hash check is a
|
||||
> valid regression guard and the amd64-as-control framing is accurate again, since 0.8 no
|
||||
> longer touches engine plumbing on any architecture. The argument below is preserved as
|
||||
> the record of why.
|
||||
|
||||
§16.4 claims: *"same input → same tick ordinal → same reap and inference events → same
|
||||
hash."* The last arrow is invalid. The hash covers `execution_heat`, which is co-written by
|
||||
|
||||
Reference in New Issue
Block a user