# Timetabler Phase 1 Remaining E2E and Load Test Plan

Status: **E2E-01–E2E-13 PASS; LOAD-01–LOAD-08 NOT STARTED.** The coordinated E2E run `phase1-e2e-20260807-01` is complete in both services. This evidence authorizes no load execution, Phase 2 implementation, or reverse delivery.

This Timetabler-owned mirror is aligned to Resource Booking `origin/dev` commit `ddeca51`, `docs/TimetablerSyncPhase1E2ELoadTestPlan.md`, and its Phase 1 OpenSpec. Resource Booking owns adapter transformation/application evidence. Timetabler owns source mutation, atomic change-set/outbox, ordered publication, source-side timing/counters, and fixed-watermark snapshot evidence. Cross-service acceptance requires both sides' immutable results for the same unique run ID.

## Coordinated E2E evidence (2026-08-07)

| Stage | Timetabler evidence | Resource Booking evidence | Accepted result |
| --- | --- | --- | --- |
| Functional (`E2E-01`–`E2E-08`) | [31184585822](https://github.com/Mayvins/timetabler-be/actions/runs/31184585822) | [31193533830](https://github.com/Mayvins/resource-booking-be/actions/runs/31193533830) | Supported source/resource lifecycle, engine, Pre-Schedule/final-drop, booking, reschedule, unschedule/delete/variant, and manual constraint-break cases passed with atomic source/application evidence. |
| Redelivery (`E2E-09`) | [31193718861](https://github.com/Mayvins/timetabler-be/actions/runs/31193718861) | [31194322436](https://github.com/Mayvins/resource-booking-be/actions/runs/31194322436) | Immutable duplicate/delayed delivery did not create a new source transaction or receiver application. |
| Synchronized conflict (`E2E-10`) | [31199593913](https://github.com/Mayvins/timetabler-be/actions/runs/31199593913) | [31199568642](https://github.com/Mayvins/resource-booking-be/actions/runs/31199568642) | Both contenders submitted in the same millisecond. Timetabler committed sequence 114; Resource Booking rejected HTTP 400 with `resource_sync_mode_mirror_only` and committed no contender. |
| Restart (`E2E-11`) | [31201102800](https://github.com/Mayvins/timetabler-be/actions/runs/31201102800) | [31201897098](https://github.com/Mayvins/resource-booking-be/actions/runs/31201897098) | Exact publisher/consumer processes restarted with durable checkpoints and watermark unchanged at 114. |
| Rollback (`E2E-12`) | [31202036674](https://github.com/Mayvins/timetabler-be/actions/runs/31202036674) | [31202178039](https://github.com/Mayvins/resource-booking-be/actions/runs/31202178039) | Safe configuration/application rollback restored exact workers, retained durable state, and kept reverse delivery false. |
| Cleanup (`E2E-13`) | [31202768905](https://github.com/Mayvins/timetabler-be/actions/runs/31202768905) | [31203486498](https://github.com/Mayvins/resource-booking-be/actions/runs/31203486498) | Sequences 115–117 deleted nine activities, seven Staff, and seven Locations; Resource Booking recorded exactly one durable applied receipt per transaction. |
| Final unfiltered reconciliation (`E2E-13`) | [31204013529](https://github.com/Mayvins/timetabler-be/actions/runs/31204013529) | [31204392182](https://github.com/Mayvins/resource-booking-be/actions/runs/31204392182) | Both services ended at watermark 117 with fixtures absent. Resource Booking's complete-snapshot dry run scanned 1,810 resources and 62 activities with drift, unresolved, quarantine, and repair all zero. |

Final evidence SHA-256 values are Timetabler `fe3dd7d64002cb04a9ce51d3c587f1155598c6ef6a8ca3e41e6894488bebe087` and Resource Booking `5253eb6ef1e5270cee0bffd59f48166fef3a900cc8bf36c1d1c9124c14d7389a`. Resource Booking recorded its acceptance update at `848627a2440ce9c3431d12567a5ffcff069c449e` on `origin/dev`; deployment [31204948366](https://github.com/Mayvins/resource-booking-be/actions/runs/31204948366) passed and its corresponding task 10.4 is checked.

Reverse delivery, LOAD, and DR were false/not executed throughout. This closes Timetabler OpenSpec tasks 10.1–10.13 only. It does not close the broader load/performance, contract/ownership/calendar, named-approval, completion-report, or Phase 2 entry gates.

## Safety and remaining load execution prerequisites

Before any later load execution, the named Timetabler, Resource Booking, QA, product, and operations coordinators must record the exact approved non-production environment, service commits, contract/configuration snapshot, owners, observation window, and rollback contacts.

- Production and unrelated databases, brokers, tenants, and resources are prohibited. Production may supply previously approved aggregate telemetry for choosing `P`; this plan grants no production access.
- Test data must be created, changed, and removed only through supported Timetabler or Resource Booking APIs/workflows. Direct SQL, fixtures loaded into application tables, and manual outbox/inbox edits are prohibited.
- Every created identity and request must carry one collision-resistant run ID, for example `phase1-gate-<UTC>-<random>`, so cleanup and reconciliation are attributable without filtering unrelated records out of the final check.
- Timetabler-to-Resource Booking remains the only active direction. Reverse delivery must attest `false` before, throughout, and after every case. Phase 2 reservation/command paths must remain disabled.
- Record the starting Timetabler source sequence, Resource Booking watermark, Kafka consumer group position, relevant configuration hashes/classifications, health state, and zero correctness counters before the first mutation.
- On any accepted conflict, partial apply, unexplained drift, mirror-only violation, sequence gap, unresolved quarantine/dead letter, or undrained backlog, stop the run, preserve evidence, and fail the gate. Do not repair away the failure and continue the same result set.
- The accepted current baseline is the coordinated E2E final state: exactly 1,810 resources and 62 activities at source watermark 117, rooted in Timetabler evidence `fe3dd7d64002cb04a9ce51d3c587f1155598c6ef6a8ca3e41e6894488bebe087` and Resource Booking evidence `5253eb6ef1e5270cee0bffd59f48166fef3a900cc8bf36c1d1c9124c14d7389a`. The earlier 1,794-resource/46-activity/19-transaction fixed-watermark recovery remains immutable run-ID/URL-hashed provenance, not the current baseline. Neither milestone marks a `LOAD-*` task complete.

## E2E execution matrix

All cases are **PASS** for run `phase1-e2e-20260807-01`.

| ID | Scenario and Timetabler-owned evidence | Required cross-service result | Status |
| --- | --- | --- | --- |
| E2E-01 | Create, update, and archive Staff and Locations through supported Timetabler APIs; record one committed source transaction/version per logical mutation and source-side post-commit effects. | Resource Booking applies the matching mirror states once, preserves source identity/version, remains mirror-only, and reaches zero lag/drift. | PASS |
| E2E-02 | Apply the largest approved real bulk Scheduling Engine final response through `kafka_consumer/tt_response.py`; record response receipt, one atomic source change set, member count/hash, database apply/lock timing, publication, and source sequence. | The complete transaction is visible atomically or not at all; no fragment, conflict, gap, dead letter, or stale prior allocation remains. | PASS |
| E2E-03 | Run Pre-Schedule advice through the supported path and compare database/outbox/source sequence before and after. | Advice produces no authoritative allocation mutation and no integration transaction. | PASS |
| E2E-04 | Accept the advised drag/drop through the normal final engine-response path; correlate request, receipt, committed change set, publisher record, and RB apply. | Exactly one logical committed source transaction is applied once; no extra Pre-Schedule transaction exists. | PASS |
| E2E-05 | Create and schedule a native Timetabler booking activity through the supported Phase 1 booking API, recording complete Staff/Location/time state and source transaction. | Resource Booking receives one complete mirror replacement with no partial Staff/Location visibility or conflicting booking. | PASS |
| E2E-06 | Reschedule an existing allocation to different Staff/Location/time/week scope and record prior/final replacement facts. | Resource Booking removes stale prior occurrences/resources and exposes only the committed final allocation. | PASS |
| E2E-07 | Execute supported unschedule, booking cancel, activity delete, and variant merge/delete subcases with unique identities and tombstone/replacement evidence. Every subcase must pass. | Resource Booking removes/archives the intended mirrors without orphan, stale occurrence, partial apply, or unrelated deletion. | PASS |
| E2E-08 | Apply a final manual constraint-break schedule through `api/views/admin/schedule_request.py`; record atomic activity/variant/resource-map/outbox state. | The mirror is equivalent to a normal committed final schedule and is applied once without bypassing ordering. | PASS |
| E2E-09 | Replay an identical source transaction and deliver it after a controlled delay without changing its immutable ID, sequence, or hash. | Timetabler does not invent a new source mutation; Resource Booking treats duplicate/delayed delivery idempotently and does not regress its watermark. | PASS |
| E2E-10 | Coordinate a concurrent Timetabler final allocation and Resource Booking booking attempt against the same mirror-only Staff/Location/time. This tests Phase 1 mirror-only protection only; it must not enable the Phase 2 reservation authority. | No conflict is accepted and neither system exposes a partial allocation. Any rejected contender has attributable evidence. | PASS |
| E2E-11 | Perform a named, controlled Timetabler publisher restart and Resource Booking consumer restart with checkpoints and sequence/watermark captured before and after. | Delivery resumes without loss, duplicate application, gap, unresolved quarantine/dead letter, or backlog; reverse stays false. | PASS |
| E2E-12 | Exercise safe application/configuration rollback: pause/disable the appropriate component, retain outbox/inbox/checkpoints, restore the approved release/configuration, and resume durably. | No renumbering, blind deletion, partial apply, or duplicate application occurs; reconciliation proves the resumed state. This is operational recovery, not DR. | PASS |
| E2E-13 | Run final fixed-watermark and live-watermark reconciliation without filtering to test-created identities. | Missing, stale, orphan, unexplained drift, quarantine, dead letter, gap, mirror-only violation, and backlog counters are all zero. | PASS |

## Load and stability execution matrix

`P` defaults to 2 accepted Timetabler source transactions per second. It may change only through a recorded joint decision based on approved aggregate production telemetry; no production query or mutation is authorized. `5P` therefore defaults to 10 transactions per second.

All cases are **NOT STARTED**.

The Timetabler-owned executor is implemented but intentionally not deployed or
run. `.github/workflows/deploy.yml` exposes one default-disabled profile/action
per dispatch (`attest`, `entry`, `load-01`, `provision`, `load-02` through
`load-06`, `correct-provision-evidence`, `arm-fence`, `load-07`, `load-08`,
`cleanup`, or `final`) and
rejects every mixed deploy/diagnostic/E2E/load mode. The private contract is
documented in `tests/contracts/resource_booking_phase1_load/`; its example is
not approved, LOAD-05 is fixed at 384 occurrences but lacks its named approval,
and LOAD-07 is disarmed. A real entry is
therefore fail-closed until the named approvals, exact commits/configuration,
fixture inventory, recurrence maximum, watermarks, prior hashes, and separate
execution authorization are recorded.

The canonical chain is `ATTEST → ENTRY → LOAD-01 → PROVISION → LOAD-02…06 → ARM-FENCE → LOAD-07…08 → CLEANUP → FINAL`. `attest` is manifest-free and read-only. It reports the exact Timetabler SHA/watermark/readiness, a non-secret Phase 1 configuration fingerprint, the hashed Timetabler database identity, runtime UID, and fixed cross-user evidence-exchange attestation. The shared manifest also contains Resource Booking's hashed default database identity; Timetabler validates it as a SHA but never accesses the RB database. The services no longer require matching homes: they require the exact path hash, owner/reader UIDs, directory/file modes, and credential prohibition.

If the immutable manifest contains the exact optional
`evidence_corrections.provision` declaration, a separately guarded
`correct-provision-evidence` action may qualify naive PROVISION transaction
timestamps with the declared `Asia/Kuala_Lumpur` offset. It preserves the
original `provision.json`, verifies its SHA, exact source fence/publisher health
and full fixture inventory, and creates only the exactly declared immutable
`provision-corrected.json`, `provision-corrected-v2.json`,
`provision-corrected-v3.json`, `provision-corrected-v4.json`,
`provision-corrected-v5.json`, `provision-corrected-v6.json`, or
`provision-corrected-v7.json`. This is evidence repair only: it performs no API
authentication, restart, load, cleanup, domain/database/outbox write, DR, or
reverse delivery. LOAD-02 then verifies the corrected SHA/file as its
`PROVISION` predecessor.

A safely aborted LOAD-02 may resume only from a watermark strictly inside its
fixed 1609–5209 fence after Timetabler proves the durable outbox contains the
exact contiguous deterministic request prefix, with every transaction
finalized and published and no unrelated sequence. The runner skips those
iterations, submits only the remaining request IDs at the approved 2 tx/s, and
still requires the unchanged final watermark and exactly 3,600 combined source
transactions. Active-segment API/lock/rate/host measurements remain explicitly
separate from full-profile source publication evidence.

The fixed recovery may first execute the read-only `checkpoint-load-02`
action. It requires the exact recovery run, corrected PROVISION predecessor,
current commits, and an intermediate source fence; reuses the strict prefix
proof; and creates immutable shared `load-02-checkpoint.json` with the full
prefix and explicit non-mutation safety assertions. It performs no login,
domain/database/outbox write, load, restart, Resource Booking process/database
operation, Phase 2, reverse delivery, or DR action.

If immutable corrected PROVISION evidence must be rebound after LOAD-02 has
started, correction is permitted only after the same complete source-prefix
proof. The corrected evidence continues to represent only the historical
PROVISION stage and records the later watermark/prefix digest in a separate
progress attestation.

An attribution failure must be investigated with the default-disabled,
read-only `diagnose-load-02-prefix` action before changing the contract. The
diagnostic reports a bounded first sequence and request classification/hash,
never writes evidence or exposes a foreign request ID, and leaves resume and
correction prohibited until the exact historical pattern is reviewed.
It reports the entire bounded numeric suffix inventory as canonical hashes and
ranges, duplicate/out-of-range facts, and a two-read stability assertion so
commit-order permutation cannot be confused with missing attribution.

The fixed failed run also has a default-disabled, read-only
`audit-failed-load-02-engine-work` containment action. It does not authenticate
to an API or write an evidence file. From the approved manifest and exact
run-owned selectors it correlates bounded admin API-log identifiers,
`PostCommitDelivery.correlation_id`, generated engine delivery UUIDs,
`KafkaLog` request/response state, `AppliedEngineResponse` receipts, engine
quarantine, finalized outbox change sets, and only the run-owned activity final
states. Output contains counts, numeric ranges, and canonical hashes rather
than request/response payloads, IP addresses, resource identities, or UUID
lists. Two identical reads are required. A published engine request is terminal
only after an exact applied-response receipt or quarantine disposition; a
pending/retrying delivery, missing response, missing disposition, contradictory
hash/change set, duplicate mapping, or uncorrelatable API record is reported as
ambiguous with `all_engine_work_terminal=false` and
`late_mutation_possible=true`. Quarantine is terminal for automatic delivery
but retains an explicit operator-replay risk. The action always keeps LOAD-02
failed and cleanup prohibited; it cannot publish Kafka, restart a process,
mutate Timetabler or Resource Booking, enable reverse delivery/Phase 2, or run
load/DR.

A fresh run that aborts with concurrent requests in flight uses the parallel
read-only `audit-current-load-02-engine-work` action. Cancellation is not
required to leave an iteration prefix: a later shard may already have reached
the API while an earlier queued shard is cancelled. The audit therefore binds
the exact submitted set from run-scoped durable outbox request IDs and engine
delivery correlations, requires its accepted per-class counts to equal the
bounded API-log inventory, and applies the same terminal-response and
late-mutation rules to every attributed operation. It never treats that set as
resumable LOAD-02 evidence. If a recovery-harness deployment is required, a
`recovery_control` must seal the canonical original-manifest hash, both the
original and recovery Timetabler commits, failed workflow and abort evidence,
the settled source fence, the approval record, and exactly the read-only audit
plus `cleanup-current-abandoned-load-02` actions. It cannot authorize an
acceptance stage.

That prohibition applies to the failed run's normal acceptance-chain
`CLEANUP`; it cannot be used to turn a failed LOAD-02 into a pass. After the
later term-26 projection proved the live source at watermark 2640, the fixed
failed run may instead be retired with the separately guarded
`cleanup-abandoned-load-02` recovery action. It requires the exact failed run
ID, an exact current source fence, and explicit mutation confirmation. Before
the first write it repeats the stable two-read engine audit and requires every
engine operation to be terminal, zero ambiguity/quarantine/dead-letter state,
and no automatic or operator replay path. It derives its deletion set only
from that run's immutable provision events and uses supported Timetabler APIs
in bounded batches. Academic term 26 and activities 672–716 cannot match those
selectors and are not touched. Resource Booking must converge through normal
Kafka ingestion and complete an unfiltered zero-drift reconciliation before a
fresh load baseline is approved.

`cleanup-current-abandoned-load-02` provides the same supported-API-only
retirement for the currently approved run. It repeats the exact submitted-set
audit before its first write and additionally requires the recovery-controlled
source fence and original PROVISION commit. A failed LOAD-02 remains failed;
cleanup only restores the unfiltered pre-run baseline for a separately
approved fresh chain.

Any fresh baseline at or beyond watermark 2640 must bind the authoritative
term-26 facts: 45 activities, IDs 672–716, source transaction
`fc63fa1f-09e6-5af6-b4a9-699cebfd6693`, and the audited identity hash. Its
LOAD-01 manifest uses the actual post-cleanup unfiltered counts and fence; it
never substitutes the historical 46-activity milestone.

`ENTRY` anchors to the accepted E2E-final hash. Later profiles do not put unknowable future evidence hashes in the approved manifest. Its immutable `stage_predecessors` graph names each predecessor; dispatch supplies the actual digest, and the runner verifies the deterministic predecessor file's canonical bytes, owner, mode `0444`, run/profile/schema/hash, and safety flags. The manifest remains unchanged for the full run.

Timetabler and Resource Booking use one canonical private manifest unchanged.
It requires seven named approval records (operator, abort authority, both
service owners, QA, product, and operations), each with name/role/record
reference/approval timestamp, plus an explicit ISO-8601 start/end window. A
profile fails closed outside that window or when its complete workload plus
observation/drain interval cannot fit. `profile_timing` fixes LOAD-02 at
1,800+300 seconds, LOAD-03 at 300+300, LOAD-04/05/06 at bounded 300+300
single-case windows, LOAD-07 at a 300+300 steady/recovery window around the
shared epoch/hash, and LOAD-08 at 3,600+300.

Provision has a bounded 5,400+300-second duration and a bounded 120-minute SSH timeout. It runs only after LOAD-01. Supported APIs idempotently create 32 setup-only lifecycle Staff, 32 setup-only lifecycle Locations, 640 allocation Staff, 640 allocation Locations, 320 ordinary rate activities, 320 short-recurrence rate activities, 32 maximum-recurrence activities, 100 real-bulk activities, and 1,200 boundary activities: 3,316 exact source transactions. Requirement preparation is advisory and must emit no integration event; every later final schedule event must contain complete current Staff/Location allocations. Ordinary and short-recurrence traffic uses disjoint 320-way resource pools. For the approved Jan–June 2026 term, schedule and unschedule may each take up to 60 seconds; the `5P=10` reuse interval is 128 seconds, exceeding the full 120-second lifecycle plus a four-second observation margin. The lifecycle fixtures are setup inventory only and never enter timed load. This changes only harness provisioning, evidence, and pacing; it does not change the Timetabler–Scheduling Engine contract.

Provisioning is fail-closed to the manifest's authoritative academic-term ID
and exact start/end dates. It selects only a module/template donor from that
term and uses it only to create unscheduled run-owned activities in that same
term. An existing template may contribute Staff/Location candidate defaults;
those presets and suitability rules are advisory engine inputs, not final
allocations and are excluded from the Phase 1 canonical activity state. Before
any Scheduling Engine call, provisioning replaces every inherited candidate
through the supported requirement API, proves the activity remains unscheduled
with empty final `staff`/`location` allocations, and proves the source watermark
did not change. Scanning or falling back to another active term is prohibited
because scheduling state outside the approved Jan–June 2026 dataset is not an
accepted load-test input. Immutable PROVISION evidence records the enforced
term ID/date range, donor identity, candidate reset, and empty-final-allocation
assertions. Cleanup deletes only run-owned fixtures and preserves the existing
term template.

Every profile writes its complete canonical Timetabler evidence to the
attested shared staging host at
`/var/tmp/mayvins-timetabler-phase1-load/<run-id>/<profile-lower>.json`. The
fixed root and run directory are owned by Timetabler uid 1073 with mode `0755`;
canonical evidence and fence files are owned by uid 1073 with mode `0444`, so
the attested Resource Booking uid 1069 can read but cannot change them. The
manifest and read-only attestation bind the fixed path SHA-256, both UIDs, both
modes, and `credentials_forbidden=true`. The path is derived only from the
strict collision-resistant run-id/profile grammar. Credential-like content,
wrong ownership/modes, non-canonical bytes, or a contradictory SHA fails
closed. Actions prints the SHA-256 and exact path, not thousands of transaction
IDs. Timetabler cleanup/final retain the evidence until coordinated receiver
verification and final acceptance are complete.

The source evidence records every transaction ID/sequence, commit/publication
time, canonical byte size, member count, workload classification, exact
watermarks, supported-API timing, a conservative full-request upper bound for
database lock wait, publisher/outbox depth and age, application connection and
worker state, and sampled host CPU/memory. Resource Booking independently owns
consumer/apply/API-impact/lag/correctness and unfiltered reconciliation
evidence. Timetabler never receives RB credentials or controls an RB process.

LOAD-02/03/07/08 use only a deterministic four-step mix: schedule then unschedule on each of two disjoint recurring-activity pools. Every activity is bound to academic term 26 (5 January–26 June 2026), at least two teaching weeks, exactly one Staff preset, and exactly one Location preset. Timetabler evidence must prove schedule assigned both resources and unschedule released both; Resource Booking must independently prove one audited allocated Staff/Location pair per occurrence followed by the matching released pair. Staff/Location lifecycle updates and reschedules are excluded from timed load. Accepted API start times—not queued futures—must achieve at least 95% of target TPS with at most 1,000 ms scheduling skew. A hard abort cancels queued calls, lets already-running calls finish atomically, writes a separate hashed abort artifact (including an HTTP entry-gate failure), and never claims the final fence. Missing processes abort immediately outside the exact LOAD-07 window. Memory above 90% must be continuous for 300 seconds before the hard-memory abort; the separate no-sustained-CPU/memory-above-80% threshold remains enforced.

Every admin request carries or receives a correlation identifier. For an HTTP
4xx/5xx, Timetabler keeps domain rollback enabled, buffers sanitized request
and exception diagnostics in memory, then persists them only after the failed
request transaction has rolled back. `incoming_api_admin` and `error_log` can
therefore be joined by `request_id` or `correlation_id`; the load abort artifact
also records the safe method/path/status/body digest for the exact failed
iteration. Diagnostic-persistence failure is reported to the application log
with correlation and error hashes and never changes the original HTTP result.

| ID | Workload and Timetabler-owned evidence | Required result | Status |
| --- | --- | --- | --- |
| LOAD-01 | Bind the accepted 1,810-resource/62-activity E2E-final baseline at watermark 117 and both real final evidence hashes; retain 1,794/46/19 as run-ID/URL-hashed provenance; bind a fresh unfiltered receiver reconciliation at exactly 1,810/62/117 with zero counters. | The current baseline and historical provenance are immutable and exact; provision has not run and all correctness counters are zero. | NOT STARTED |
| LOAD-02 | Generate only term-26 recurring schedule/unschedule source transactions at steady `P` for 30 minutes; record accepted rate, assignment/release correctness, source commit/publish latency, lock wait, outbox depth/age, broker position, RB apply latency, API impact, and host utilization. The 12 August mixed seven-class run stopped after 589/3,600 transactions when one concurrent admin endpoint returned HTTP 500; the status-only client did not identify which endpoint, so it is not evidence that ordinary schedule/unschedule failed. | Every schedule and unschedule has exact Timetabler and Resource Booking recurrence/allocation evidence, all thresholds pass, and lag drains within five minutes. The failed mixed run remains failed and cannot be relabelled. | REVISED SCOPE / FRESH RUN PENDING |
| LOAD-03 | Generate a supported-API `5P` burst for five minutes with the same telemetry and correctness checks. | No partial apply, ordering violation, unresolved failure, or sustained resource breach; lag drains within five minutes. | NOT STARTED |
| LOAD-04 | Execute the largest real jointly approved bulk Scheduling Engine transaction and record its approval reference, exact approved activity/member count, actual member count, and canonical bytes. | The exact approved maximum—not an arbitrary smaller transaction—forms one complete transaction below 2 MiB and applies atomically. | NOT STARTED |
| LOAD-05 | Execute the canonical maximum recurrence of 32 run-owned activities × 12 weeks through a supported API and record the exact 384-occurrence count/size plus source/RB timings. | Exactly 384 occurrences are deterministic and complete with no truncation, ambiguity, or drift. | NOT STARTED |
| LOAD-06 | Before mutation, calibrate canonical serialization read-only and select an approved envelope no more than 4 KiB below 2 MiB plus its immediately over-boundary case; execute those exact supported-API inputs. | Admissible actual bytes equal calibration and apply once; the over-boundary case fails before domain/source/outbox partial persistence. | NOT STARTED |
| LOAD-07 | After sealed LOAD-06 evidence, run the non-domain-mutating `arm-fence` action to create the short-lived shared mode-`0444` artifact binding run, both SHAs, cryptographic nonce, real approval, creation/expiry, epoch, and canonical hash under the immutable 60–900 second lead policy; then restart under steady load. | Arm verifies LOAD-06 SHA/current fence and performs no load/restart/database/domain mutation; both services validate the same artifact; TT skew is 0–5 seconds, exactly one publisher restarts in LOAD-07, liveness returns, durable state remains, and backlog drains. | NOT STARTED |
| LOAD-08 | Run the accepted steady workload for 60 minutes after functional cases pass; record latency distributions, lag, correctness counters, and CPU/memory trend. | Thresholds remain satisfied for the full stability window with no leak, sustained utilization breach, or unresolved backlog. | NOT STARTED |

## Default acceptance thresholds

These defaults may be replaced only by a joint, versioned decision recorded before execution. A change cannot waive any correctness invariant.

| Measure | Threshold |
| --- | --- |
| Timetabler commit to Resource Booking visible end-to-end | p95 ≤ 5 seconds; p99 ≤ 15 seconds |
| Backlog/consumer lag recovery | Drains within 5 minutes |
| Resource Booking mirror apply | p95 ≤ 2 seconds; p99 ≤ 5 seconds |
| Timetabler database lock wait | p95 ≤ 500 ms; no unhandled deadlock |
| Booking API impact | p95 latency increase ≤ 20%; error-rate increase < 0.1 percentage point against the recorded pre-run baseline |
| Host utilization | No sustained CPU or memory above 80%; the sampling interval and sustained-window interpretation must be recorded before execution |
| Correctness | Zero accepted conflicts, partial applies, unexplained drift, mirror-only violations, gaps, unresolved quarantines/dead letters, or final backlog |
| Direction | Reverse delivery remains false throughout |

The Timing and Concurrency Budget in the Phase 1 design also remains binding: record the approximately 30-second engine reservation window and Kafka max-poll behavior for applicable engine/bulk cases. Missing telemetry is a failed result, not permission to infer a pass.

## Explicit DR exclusion

Disaster recovery is not part of this Phase 1 gate. Do not plan, execute, or claim any of the following as required evidence:

- database backup/PITR restore;
- Kafka cluster rebuild or restore;
- host, availability-zone, region, or site failover;
- infrastructure, DNS, or secrets-vault rebuild; or
- multi-region or business-continuity exercises.

Controlled publisher/consumer restart, safe application/release/configuration rollback, checkpoint recovery, durable resume, and final reconciliation remain mandatory operational tests. They are not DR.

## Traceability and evidence bundle

| Scoped ID | Timetabler OpenSpec coverage | Primary Timetabler surfaces |
| --- | --- | --- |
| E2E-01 | 8.1, 10.1 | `api/views/admin/staff_*.py`, `api/views/admin/location_*.py`, integration outbox |
| E2E-02 | 8.2, 8.9–8.11, 10.2 | `kafka_consumer/tt_response.py`, scheduling application service, publisher |
| E2E-03–04 | 5.9, 8.3, 10.3–10.4 | `api/views/admin/schedule_request.py`, `kafka_consumer/tt_response.py` |
| E2E-05–08 | 4.1–4.14, 8.2, 8.4, 10.5–10.8 | booking/reschedule/unschedule/delete/variant/manual scheduling writers |
| E2E-09 | 6.1–6.3, 8.6, 8.10, 10.9 | outbox publisher, replay tooling, RB inbox/idempotency |
| E2E-10 | 6.5, 8.9–8.10, 10.10 | Timetabler final writer plus RB Phase 1 mirror-only enforcement |
| E2E-11–12 | 7.5–7.6, 8.7–8.10, 9.4, 10.11–10.12 | supervised publisher, consumer checkpoints, rollback/recovery runbooks |
| E2E-13 | 7.1–7.7, 8.10, 10.13 | authenticated fixed-watermark snapshot and RB reconciliation |
| LOAD-01–03 | 7.3–7.5, 8.9–8.11, 10.14–10.16 | outbox/source metrics, broker positions, RB apply/API/host metrics |
| LOAD-04–06 | 2.1–2.4, 6.7–6.8, 8.11–8.12, 10.17–10.19 | canonical serialization/size validation, recurrence/occurrence facts |
| LOAD-07–08 | 7.5–7.6, 8.7–8.11, 10.20–10.21 | supervised restart/checkpoints, backlog drain, stability telemetry |

Each future load result must attach the run ID, exact commits/configuration classification, start/end timestamps and source sequences/watermarks, workload generator version/parameters, API-created identity manifest, sanitized raw measurements, percentile method/sample count, correctness counters, restart checkpoints where applicable, unfiltered final reconciliation, cleanup result, deviations, and named reviewers. A summary without immutable underlying evidence cannot close a checkbox.

Implementation of the guarded executor does not change the status of
LOAD-01–LOAD-08. No load profile, staging mutation, deployment, or DR exercise
has been run by this planning/implementation change.

Cleanup is supported-API-only and retry-safe. It recovers the immutable provision inventory from finalized source events, divides 1,972 activities into sixteen deterministic batches of at most 128 members, calibrates every pending deletion below 2 MiB with a 256 KiB margin before mutation, and then performs bounded Staff and Location deletes. The manifest therefore expects eighteen cleanup transactions. A completed retry batch is reusable only when its stable request ID maps to exactly one finalized source transaction and its domain members are absent. Final proves all run-owned rows absent while retaining evidence for unfiltered receiver reconciliation.
