Repository navigation
Fix the schedule execution-order gap: run every/at bodies sequentially - #5
Merged
Merged
Conversation
A schedule's body used to run through two disconnected static passes (top_level_publications for literal-field publishes, top_level_operation_calls for bare operation calls), so a let computed in a schedule body never reached a later publish or print in the same body -- the exact gap examples/service-operator-bot.ns hit building its encrypted Locator refresh and had to work around by moving into a handler. Interpreter::statement's Every/At arm now runs self.block(body), giving a schedule's body the same sequential evaluator a handler body already gets, executed once inline at startup (deploy still only registers the timer for actual periodic refiring -- this is not new timer support). A new eval::run_schedule_bodies drives this at the top level; deferred_spans excludes a schedule's span from the two old static passes so nothing runs twice. nscript-cli's run_program/deploy_program call the old static passes first, unchanged, then run_schedule_bodies through a small EvalHost wrapper that traces to the same operation N/publication N output format, continuing the same counters, plus a log line for a print that finally runs. The fix is scoped to schedule bodies specifically, not the whole top-level program: an earlier version ran all top-level code through the sequential evaluator and, checked against every file in examples/ and conformance/valid/ rather than just the test suite, broke roughly twenty fixtures that rely on the checker's own leniency toward bare demo identifiers or bind select/latest subscription expressions the plain evaluator has never implemented. No schedule body in this codebase uses either shape, so narrowing the fix to schedule bodies keeps the real bug fixed with zero regressions across the whole corpus, verified by diffing every example's output before and after. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D95PWA2fdNfg7nUvUHBeMi
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.
Summary
Real fix (not a workaround) for the schedule-execution-order gap
NCC-PLAN.mdrecorded as a follow-up: a schedule's body used to run through two disconnected static passes —top_level_publicationsfor literal-field publishes,top_level_operation_callsfor bare operation calls — so aletcomputed in a schedule body never reached a laterpublishorprintin the same body.examples/service-operator-bot.nshit exactly this building its encrypted Locator refresh and had to work around it by moving the sequence into a handler.Interpreter::statement'sEvery/Atarm (previouslyErr(unsupported(...))) now runsself.block(body)— a schedule's body executes exactly once, inline, through the same sequential evaluator a handler body already gets. This is real evaluation of the one firing every host already guaranteed (startup) — not new periodic-timer support;deploystill only registers the timer for actual refiring.eval::run_schedule_bodiesdrives this at the top level;deferred_spansnow also excludes a schedule's span from the two old static passes, so nothing runs twice.nscript-cli'srun_program/deploy_programrun the old static passes first, completely unchanged, thenrun_schedule_bodiesthrough a smallEvalHostwrapper that traces to the exact sameoperation N: <value>/publication N: <accepted>/<total> relays acceptedoutput format startup already used — continuing the same counters — plus alog <level>: <message>line for a schedule's ownprint, which finally runs.examples/andconformance/valid/(not just the test suite), it broke roughly twenty fixtures that rely on the type checker's own leniency toward a bare demo identifier used only as a typed argument, or bindselect ... from .../latest ... from ...expressions the plain evaluator has never implemented. No schedule body in this codebase uses either shape, so narrowing the fix to schedule bodies keeps the real bug fixed with zero regressions — verified by diffing every example'snscript runoutput before and after.examples/service-operator-bot.nsnow runs its encrypted Locator refresh directly insideevery 24h { ... }alongside the other three publishes — the fix, not the workaround.Test plan
cargo build --workspace— cleancargo test --workspace— all tests pass (250nscript-runtime+ 69 CLI tests, 1 ignored), including a new library-level test forrun_schedule_bodiesand an updated CLI test for the composite examplecargo fmt --check— cleancargo clippy --workspace --tests -- -D warnings— cleanexamples/andconformance/valid/before and after, diffed output: only 4 files changed, all four gaining exactly theprinttheir schedule always should have produced, nothing newly broken (the remaining 4 files that failnscript checkwere already failing identically before this change, unrelated to it — pre-existing gaps referencing hypothetical custom modules)🤖 Generated with Claude Code
https://claude.ai/code/session_01D95PWA2fdNfg7nUvUHBeMi
Generated by Claude Code