Pulse is a small, strictly typed absolute-time sequence runtime for Roblox. It compiles reusable event and sampled timelines, then evaluates them from finite source samples supplied by a host. The core has no clock, scheduler, frame loop, or discontinuity policy.
Pulse owns sequence-local anchors, playback speed, ordered event traversal, reverse callbacks,
loop identity, explicit addressing, cleanup generations, and lifecycle. Hosts own the meaning of
time and presentation side effects. An optional ClockDriver adapts scheduling-capable clocks to
the same raw core.
local Pulse = require(ReplicatedStorage.packages.pulse)
type HitContext = {
worldPosition: Vector3,
}
local makeBuilder = Pulse.builder :: () -> Pulse.SequenceBuilder<HitContext>
local builder = makeBuilder()
local sequence = builder
:duration(1.5)
:event({
time = 0.2,
run = function(playback, context)
print("hit", context.worldPosition, playback:getPosition().timePosition)
end,
})
:sample({
startTime = 0.2,
endTime = 1.0,
run = function(_playback, timePosition, _unwrappedTimePosition, rate, _context)
-- Absolute sampled state; no dt accumulation.
print(timePosition, rate)
end,
})
:compile()
local playback = Pulse.playback(sequence, {
worldPosition = targetPosition,
})
playback:play({ position = 100, rate = 1 })
playback:evaluate({ position = 100.5, rate = 1 })
playback:evaluate({ position = 101, rate = 1 })TimeSample.position is an absolute source coordinate. Pulse maps its displacement through
playbackSpeed; it never multiplies displacement by TimeSample.rate. The rate is atomic metadata
used for direction and reported to active samplers after local speed is applied.
local Tempo = require(ReplicatedStorage.packages.tempo)
-- tempoProvider is the host adapter in docs/guides/tempo-integration.md.
local driver = Pulse.clockDriver(tempoProvider(clock), "heartbeat" :: "heartbeat", {
forward = Tempo.Enums.Direction.forward,
backward = Tempo.Enums.Direction.backward,
})
local raw = Pulse.playback(sequence, {
worldPosition = targetPosition,
})
local driven = driver:attach(raw, {
discontinuityMode = "reconstruct",
})
driven:play()attach transfers exclusive temporal-control ownership to driven until driven:detach(); do not
mutate raw while it is attached. One driver may serve many playbacks. Attachments lazily share
one phase binding while an exact Sample is active, reverse movement is poised to enter a Sample at
its excluded end, or an outward zero-distance loop join awaits actual source movement. Ordinary
event-only playback keeps only one next-boundary deadline. The attachment must explicitly select
"skip", "reconstruct", or "cancel" for provider discontinuities; reusable Sequences contain
no such decision.
For late materialization, choose initialMode = "skip" and use onAddress to establish host-owned
resources at the exact addressed position without replaying historical one-shot events.
Pulse has no package dependency on Tempo. A Tempo scheduling binding can be adapted at the host boundary; any
scheduling-capable clock satisfying ProviderClock may be injected. Destroying a driver never
destroys its borrowed clock.
Install the pinned Rokit tools, then use the guarded verification scripts:
rokit install
pesde install
.\scripts\verify\tests.ps1
.\scripts\verify\analyze.ps1
.\scripts\verify\stylua.ps1
.\scripts\verify\selene.ps1
.\scripts\verify\benchmark.ps1
npm install
npm run docs:buildStart with the documentation overview, the getting-started guide, or the API reference.
CLI and editor use Luau solver V2 with pinned Luau-LSP 1.70.1. Public methods and frozen callback
payloads are read-only. PlaybackPositionSnapshot describes frozen callback positions;
PlaybackPosition remains writable for writePositionInto and caller-owned position copies.
SequenceAddress is an input view; build a mutable local record before passing it if needed.
Parameterless generic builders use a concrete constructor specialization as shown above.
./scripts/verify/analyze.ps1
./scripts/verify/analyze.ps1 -Project dev.project.json -Sourcemap dev-sourcemap.json -Paths src,dev
./scripts/verify/type-errors.ps1 -OutDir .verification/type-errors-fresh
./scripts/verify/tooling-tests.ps1
./scripts/verify/test-harness.ps1LUAU_LSP_OVERRIDE can select a patched executable matching the pin. Captures in .verification/
record path, version, SHA-256, definitions hash, native exit, and both output streams. Source and
accepted public contracts form the static gate; dynamic Lune fixtures run as behavior proofs.
Negative contracts must fail at their marked expressions without unexpected diagnostics.
Tests and benchmarks use unique owned .pulse-tests/ runtimes, protected cleanup on success or
failure, concurrent-run isolation, and bounded abandoned-run recovery. Pass -KeepRuntime to
retain a specific runtime for inspection. Cached historical material is outside these checks.