Skip to content

feat(sync_env_clock): an optional timezone reads virtual_time in the zone and tells every synced server (FD-5003) - #442

Merged
cikowski merged 4 commits into
mainfrom
cikowski/clock-timezone
Nov 2, 2026
Merged

cikowski merged 4 commits into
mainfrom
cikowski/clock-timezone

Conversation

@cikowski

@cikowski cikowski commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator

sync_env_clock can only arm the gateway at an instant, so a task cannot say "12:00 on Jan 1 in New York" and have its servers answer in that zone (FD-5003). This adds an optional IANA timezone to the step. Unset, the step is unchanged: same task JSON, same gateway and sync request bodies.

  • With a zone, a wall-clock virtual_time is local time in it (12:00 America/New_York on Jan 1 arms the gateway at 17:00Z). An offset in virtual_time that disagrees with the zone at that instant fails when the step is built, naming both; one that agrees is accepted. A time that does not exist (spring-forward gap) is refused; an ambiguous one takes the earlier occurrence.
  • The zone is stored stripped, and the package now depends on tzdata so a worker image without system zone files can still rebuild a zoned task.
  • The zone is sent in each server's sync_time. A server whose card does not declare timezone in the sync_time request schema fails the step, whatever tolerate_missing_sync_time says (that flag still governs servers without clock/v1). Detection reads the stored card, no extra HTTP call.
  • clock_configurations records timezone and armed_at only when a zone is set. armed_virtual_time is public so the Harbor exporter can replay the instant.

Rollout

Not in this PR

  • A zoned-gateway integration test (needs a sandbox); the card wording is only exercised in unit tests against the real composed card.
  • Follow-up, consumer gap: scaleapi agent-env-hub-backend/agent_env_hub/qc/inputs.py:379-385 drops timezone and armed_at from clock_configurations.

Validation (head 3e546131, local)

  • tst/unit/task_step/sync_env_clock_test.py: 35 passed (new tests fail on main: no timezone argument). Covers round trip, byte-identical unzoned body to old and new cards, 17:00Z arming, strict failure on a card lacking timezone, DST gap and offset disagreement.
  • tst/unit/task_step plus packages/agentenv-protocol/tests: 3185 passed, 2 failed (test_mcp_cli_builder, click not installed locally, unrelated). ruff check: clean. test_runtime_dependencies_are_imported now imports tzdata explicitly (it failed CI at 093717b). The zone check catches ZoneInfoNotFoundError, ValueError and OSError (a directory name like Europe or a 5000-character name raises OSError), covered by the invalid-zone cases.
  • Not run: gateway integration tests (need a sandbox); the card wording is exercised against the real composed card in unit tests.

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; no new blocking issues were found.

Summary

Adds optional timezone support to sync_env_clock. Zoned wall-clock times become UTC instants, and each synced server receives the zone.

  • Clock steps can read local times and sync servers to their timezone.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Task time and optional zone] --> B[Resolve UTC instant]
  B --> C[Arm gateway clock]
  C --> D[Check each server's stored card]
  D --> E[Send clock URL and optional zone]
  E --> F[Record clock configuration]
Loading

Reviews (4) · Last reviewed commit: "address review round 3: a directory-name..." · Reviewed by Greptile

…zone and tells every synced server (FD-5003)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@cikowski
cikowski requested a review from a team as a code owner November 2, 2026 18:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants