Repository navigation
feat(gust:os): implement world app-timer — the periodic-loop shape jess asked for, and fix the world that could not work - #311
Merged
Merged
Conversation
…ss asked for
gale#223 asked which interface drives a periodic control loop. I answered with the
shape and had to add "world app-timer is declared but has no implementation — you
are on new ground". Writing it found the world was also WRONG.
THE WORLD COULD NOT WORK AS DECLARED.
before: world app-timer { import time; import timer; export run }
`timer.sleep(handle, ticks)` takes THE HANDLE THE APP HOLDS FROM `spawn.start` —
the WIT says so itself in the app-ts note: "a handle it returns is the executor's
own handle and means the same thing to `timer.sleep`". With no `spawn` import an
app in this world cannot obtain a valid handle, so the only path it can exercise
is sleep's 0xFFFF_FFFF invalid-handle return. A tickless-one-shot-sleep slice that
can only demonstrate the error path is not a slice.
after: world app-timer { import time; import spawn; import timer; export run }
THE EXAMPLE. app-timer/src/lib.rs: spawn.start -> timer.sleep(h, 50) -> poll
timer.slept under a bounded budget. Component validates and imports exactly
{time, spawn, timer}, exporting `run: func() -> u32`.
It propagates 0xFFFF_FFFF UNCHANGED rather than folding it into 0, so a caller can
distinguish "not yet" from "never armed" — the same distinction gale#283 fixed in
the provider, and it would be odd for the example to lose it.
WHAT THE EXAMPLE DELIBERATELY DOES NOT DO, documented in its header: it does not
call exec.poll-round. Who drives the executor — timer ISR vs partition window — is
the embedder's choice and gale has not settled it (gale#223 Q1). An app arms its
wake and reports; the node decides when to poll. The header also carries the two
measured caveats a real periodic budget needs: T4 bounds 3 of 31 functions, and a
partition owning k windows receives Theta - k, not Theta.
AND THE GATE WAS NOT COVERING IT. check-providers.sh had a hand-written CRATES
list, so it reported "all 8 provider/app crates ... in sync" while never building
app-timer. Same shape as the Lean gate's enumerated target list (gale#292). Now
discovered by glob over app-*/-provider with a FATAL if discovery finds nothing,
and the legacy list deleted rather than left as a second source of truth.
before: all 8 crates after: all 9 crates, app-timer included
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
gale#223 asked which interface drives a periodic control loop. I answered with the shape, and had to add "
world app-timeris declared but has no implementation — you are on new ground". Writing it found the world was also wrong.The world could not work as declared
timer.sleep(handle, ticks)takes the handle the app holds fromspawn.start— the WIT says so itself, in theapp-tsnote: "a handle it returns is the executor's own handle and means the same thing totimer.sleep".With no
spawnimport, an app in this world cannot obtain a valid handle. The only path it can exercise issleep's0xFFFF_FFFFinvalid-handle return. A tickless-one-shot-sleep slice that can only demonstrate the error path is not a slice.The example
app-timer/src/lib.rs—spawn.start→timer.sleep(h, 50)→ polltimer.sleptunder a bounded budget. Component validates; imports exactly{time, spawn, timer}, exportsrun: func() -> u32.It propagates
0xFFFF_FFFFunchanged rather than folding it into0, so a caller can distinguish "not yet" from "never armed" — the same distinction #283 fixed in the provider, and it would be odd for the example to lose it.What it deliberately does not do
It does not call
exec.poll-round. Who drives the executor — timer ISR vs partition window — is the embedder's choice and gale has not settled it (#223 Q1). An app arms its wake and reports; the node decides when to poll. The header also carries the two measured caveats a real periodic budget needs:kwindows receives Θ − k, not Θ (proofs/lean/PartitionSupply.lean).And the gate was not covering it
check-providers.shhad a hand-writtenCRATESlist, so it cheerfully reported "all 8 provider/app crates … in sync" while never buildingapp-timer. Same shape as the Lean gate's enumerated target list (#292).Now discovered by glob over
app-*/*-provider, with a FATAL if discovery finds nothing, and the legacy list deleted rather than left as a second source of truth.🤖 Generated with Claude Code
https://claude.ai/code/session_011QG86sovTbfnPNY9SfhSmo