From b3cf7ada375183a24f238a3a377b7de2c5671e92 Mon Sep 17 00:00:00 2001 From: Jackson Moore Date: Fri, 4 Sep 2026 13:38:06 +0200 Subject: Evaluate primary repeat timeout --- lua/clever_f/sequence_coordinator.lua | 27 ++++++++++++++++++++++++++- tests/run.lua | 27 +++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/lua/clever_f/sequence_coordinator.lua b/lua/clever_f/sequence_coordinator.lua index e369a8b..9e6a9b6 100644 --- a/lua/clever_f/sequence_coordinator.lua +++ b/lua/clever_f/sequence_coordinator.lua @@ -242,6 +242,25 @@ function SequenceCoordinator:resolve_acquisition(descriptor, invocation) return self:fresh_primary_resolution(descriptor, result, invocation) end +function SequenceCoordinator:evaluate_repeat_timeout(invocation) + if type(invocation) ~= "table" then + fail("repeat timeout requires primary invocation state", 2) + end + local record = coordinator_records[self] + if type(record.repeat_resolver.evaluate_timeout) ~= "function" then + fail("SequenceCoordinator repeat resolver must evaluate timeout", 2) + end + local window = record.host:read_window() + local decision, elapsed_ms, cleanup = + record.repeat_resolver:evaluate_timeout(window) + return { + decision = decision, + elapsed_ms = elapsed_ms, + cleanup = cleanup, + window = window, + } +end + function SequenceCoordinator:primary(value) local descriptor = self:validate_primary_descriptor(value) local invocation = self:read_primary_invocation() @@ -254,7 +273,13 @@ function SequenceCoordinator:primary(value) if invocation.repeat_decision == repeat_resolver_factory.Decision.ACQUIRE then return self:resolve_acquisition(descriptor, invocation) end - return descriptor + local timeout = self:evaluate_repeat_timeout(invocation) + return { + kind = "repeat", + invocation = invocation, + pressed_descriptor = descriptor, + timeout = timeout, + } end function M.new(options) diff --git a/tests/run.lua b/tests/run.lua index 7caeb6c..089f6dc 100644 --- a/tests/run.lua +++ b/tests/run.lua @@ -7311,6 +7311,33 @@ test("Fresh primary resolution reuses acquired plans and marks empty motion", fu truthy(resolution.skip_destination) end) +test("Repeated primary coordination evaluates timeout before reuse", function() + local _, transitions = fresh_sequence_state() + local landing = domain.Position.new(1, 3) + transitions:BeginAcquisition("n", "f") + transitions:CommitAcquiredTarget("n", target("a"), 100) + transitions:CommitCommandSuccess("n", landing, true) + local host = MemoryHost.new({ + buffer_lines = { "aba" }, + cursor = landing, + time_values_ms = { 150 }, + configuration = { repeat_timeout_ms = 75 }, + }) + + local resolution = sequence_coordinator.new({ host = host }):primary("f") + + same("repeat", resolution.kind) + same(repeat_resolver.Decision.REPEAT, resolution.timeout.decision) + same(50, resolution.timeout.elapsed_ms) + local time_read + for index, operation in ipairs(host:operations()) do + if operation.operation == "read_time_ms" then + time_read = index + end + end + truthy(time_read ~= nil) +end) + for _, item in ipairs(tests) do local ok, failure = xpcall(item.body, debug.traceback) if not ok then -- cgit v1.2.3