Skip to content

Add advance_clock to move an instance's clock forward - #49

Merged
scosman merged 2 commits into
mainfrom
claude/advance-clock-47
Oct 17, 2026
Merged

scosman merged 2 commits into
mainfrom
claude/advance-clock-47

Conversation

@scosman

@scosman scosman commented Oct 12, 2026

Copy link
Copy Markdown
Contributor

Fixed #47

A harness can now move an instance's virtual time forward deterministically, for example to reach a retry window or a due date, without writing to Clock._start.

Python

inst.advance_clock(by=None, *, to=None) -> str takes exactly one of a timedelta or an instant (either form now= takes), and returns the new reading as canonical text.

Mode Reading after an advance
fixed start + advanced
tick start + advanced + 1 s per call
running start + elapsed real time + advanced
wall refused
  • The clock only moves forward. It is refused inside a tool call (including transaction=False tools), inside bulk() and inside a state formatter.
  • An advance is not a call: it takes no ordinal, does not tick and is not in the call log.
  • Every node of a composite instance, inspect() and a later freeze() all read the moved clock.
  • The public Clock API stays read-only, so world code cannot move time through ctx.clock.

OpenEnv

New control tool controller_advance_clock(seconds | to), which answers {"now", "clock_mode"}.

  • It is behind the existing --include-control-tools flag and is never listed.
  • It is not deprecated. Only controller_run_sql is.
  • Refusals reach the harness as a ToolError coded clock_not_advanced. A WorldBug would be scrubbed to "internal error" on the wire, so the harness could not see why it was refused.

Out of scope

  • Recording clock moves in the state envelope: to replay a run, advance the clock by the same amounts at the same points.
  • A SeahavenClient convenience method.
  • An HTTP route on seahaven.http.

Docs and tests

  • Docs: a short "Moving the clock forward" section in clock.md, a "Moving the clock" subsection in serving_and_openenv.md, and reference rows. Pages that described a single deprecated control tool now describe the control tools.
  • Tests: the feature is driven through world.instance(...), the control tool, an OpenEnv step and the real wire, with a test for each refusal.
  • test_docs.py change: the rule that docs must not name a controller_ tool now applies only to deprecated tools, so the new tool can be documented.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QtPPDeDagBgpFidJmRVQzz


Generated by Claude Code

scosman and others added 2 commits October 12, 2026 21:56
A harness can now move virtual time forward deterministically, to reach
a retry window or a due date without writing to Clock._start.

- Clock keeps a private, millisecond-cut offset that every mode but
  `wall` adds to its reading: fixed is start + advanced, tick adds a
  second per call on top, running adds elapsed real time. The public
  Clock API stays read-only, so world code cannot move time.
- Instance.advance_clock(by=None, *, to=None) takes exactly one of a
  timedelta or an instant (either form now= takes) and answers the new
  reading as canonical text. It runs under the instance lock, is not a
  call (no ordinal, no tick, no call-log entry), and every node,
  inspect() and the next freeze read the moved clock. It is refused,
  as WorldBug, for a backward move, a wall clock, a move past year
  9999, a wrong argument type, and inside a tool call (transaction=False
  included), bulk() or a state formatter.
- New control tool controller_advance_clock(seconds, to), behind the
  existing --include-control-tools flag and never listed, answering
  {"now", "clock_mode"}. Every refusal reaches the harness as a
  ToolError coded clock_not_advanced, in the wire's argument names,
  rather than as a WorldBug the OpenEnv layer would scrub to "internal
  error". Its name joins CONTROL_TOOL_NAMES; it is not deprecated.
- Docstrings, CLI help and docs that described a single deprecated
  control tool now describe the control tools. clock.md gains a short
  "Moving the clock forward" section with a runnable example, and
  serving_and_openenv.md a "Moving the clock" subsection; api.md notes
  that a comment-led statement on inspect() can keep a pre-advance
  reading under fixed, as it already can under tick.
- Tests drive the feature through world.instance(...), the control
  tool, an OpenEnv step and the real wire, with a test per refusal
  guard. The docs rule against naming control tools now applies only
  to deprecated ones, and the reference world's registry test includes
  the new name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QtPPDeDagBgpFidJmRVQzz
concepts.md still listed it as unplanned, which advance_clock now
contradicts. Also word the control tool's docstring so its refusals
read as examples rather than the complete list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QtPPDeDagBgpFidJmRVQzz
@scosman
scosman merged commit 13dcadd into main Oct 17, 2026
3 checks passed
@scosman
scosman deleted the claude/advance-clock-47 branch October 17, 2026 17:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expose advance() (or a setter) for a fixed-clock instance

1 participant