Files
deepseek-harness/docs/rfc/proposed/2026-06-11-deterministic-and-stress-testing.md
T
Tianyi Cui 7c400e9c02 docs: unify ADR/RFC trees into one lifecycle-organized RFC tree
Collapse docs/adr/ and docs/rfc/ into a single docs/rfc/ with proposed/,
implemented/, and rejected/ subfolders. Every file is renamed to
yyyy-mm-dd-topic-title.md, where the date is when the topic was first
proposed (from git history). ADRs and RFCs that covered exactly the same
topic are merged (property-based testing, session persistence); the
umbrella RFC 005 stays split across its three implemented decisions, and
RFC 006's deferred part-3 (API extractor reports) splits into its own
proposed RFC. All cross-references become machine-checkable relative
links instead of bare "ADR NNNN" / "RFC NNN" prose.

Add a verify-md-links doc-sync gate (scripts/verify-md-links.ts) that
checks every relative Markdown cross-link resolves, wired into doc-sync
alongside verify-md-wrap. This makes the reorganization self-verifying:
the same change that rewrote ~forty inter-doc links adds the check that
proves none dangle. Document the cross-link convention in a new
docs/AGENTS.md and record the gate as an implemented RFC.

doc-sync, typecheck, lint, and the full test suite (667) all pass.
2026-06-18 02:18:24 +08:00

1.8 KiB

RFC: Deterministic tests, the replay invariant fixture, and race stress

Status: proposed

Problem

Several loop tests synchronize with setTimeout(30) sleeps — flakiness debt that wastes agent cycles on retries and can mask ordering bugs. Separately, our core architectural promise (any session log replays to identical derived history) is asserted in two tests but is cheap to assert everywhere. And the inbox wakeup race was verified by hand exactly once; nothing re-verifies it continuously.

Proposal

Three measures:

  1. No wall-clock sleeps in tests. Replace setTimeout(N) waits with event-driven waits (the existing waitForIdle pattern, extended to waitForStatus, waitForEvent(n)) or vitest fake timers where time itself is under test. Enforce with a lint rule banning setTimeout in packages/*/tests outside an allowlisted helper module.
  2. Universal replay fixture. A shared test helper wraps the loop harness so that after every test, the agent's session log is replayed into a fresh Session and deriveMessages() equality is asserted automatically. The invariant then gets checked hundreds of times per CI run across every scenario the suite produces, not twice.
  3. Nightly race stress. A CI job running the agent-loop and inbox suites with vitest --repeat=200 (and --shuffle) to flush scheduling-dependent failures; any flake found is a bug to fix, never a retry.

Plan

Land 1 and 2 together (they touch the same helpers); add the nightly job after the suite is sleep-free so repeats are fast.

Risks

Fake timers interact subtly with Promise scheduling in the loop — prefer event-driven waits; reserve fake timers for timer-service behavior itself.