Pull Request已成功合入, 合并人@urandon
(感谢 urandon 的贡献)CI fix — canonical /new assertions
The failed local-integration job was caused by a stale assertion, not by a command-processing failure. The implementation now replies:
A new session was created and this Telegram chat now points to it.
but the test still searched for the legacy New clean context started response.
Changes
- Updated the local-stand assertion and diagnostics to use the canonical-session terminology.
- Strengthened the E2E contract: after
/new, the next workload must carry a different canonicalsession_id; checking only a legacy context-epoch counter is no longer sufficient. - Updated the Telegram and local-test documentation to state that Sessionless owns canonical session history, while Telegram remains the first frontend and an authoritative transport fact.
- Kept
context_epochsexplicitly documented as a temporary compatibility ledger until #21 and #36 persist canonical frontend bindings directly.
Verification
make ci— passed.- Exact formerly failing test — passed against the live local stand:
TestLocalStandContracts/Telegram_command_state_and_durable_replies. - New canonical-session E2E assertion — passed against the live local stand:
TestDeterministicLocalMultiUserSlice/explicit_new_switches_the_frontend_to_a_new_canonical_session. git diff --check— passed.- GitHub mirror branch head matches GitCode:
6d52d0d5a06f8e1dc864c3b9ae490b2c22304d60.
A subsequent clean-stand bootstrap was blocked by transient external registry failures (Docker Hub EOF, then a gcr.io TLS handshake timeout), so no full clean-stand rerun is claimed here. The fresh mirrored GitHub Actions run remains the merge gate.


Follow-up — keep the canonical-session E2E queue-free
The first fix strengthened the /new assertion by posting a normal workload after the command. That proved the new session_id, but it also made the assertion depend on worker/admission lifecycle and could leave a dispatch message for the following local-integration suite.
Commit d8e0663 makes the scenario deterministic and isolated:
- complete
/new; - force the test subscription into
provider_quota_exhausted / blocked_until_reset; - post the first message after
/new; - prove that its
session_iddiffers from the command run's prior session; - wait for
quota_blocked.
Because admission is intentionally blocked, this scenario cannot publish a worker dispatch. It verifies the canonical binding transition without contaminating the shared queue.
Verification
- Queue-free canonical-session E2E subtest — passed.
- Full
make local-integrationrun immediately after that E2E subtest — passed. make ci— passed.git diff --check— passed.- GitHub mirror head matches GitCode:
d8e0663609f67875d20c22c1b28607542e60a72e.
The new GitHub Actions run for d8e0663 is the merge gate.


CI follow-up — remove the queue-outage timing race
The authenticated GitHub Actions log for run 30915674594 identified the remaining failure precisely:
- the one-shot worker checked the queue at
13:55:38.942and returnedworker queue empty; - the reconciler published the recovered dispatch at
13:55:39.583; - the fixed
500msdelay therefore started the worker 641 ms too early.
This was an existing sleep-based race in the queue-outage E2E scenario; it was unrelated to the canonical /new assertion.
Commit cdb0317 changes the contract to wait for durable state instead of wall-clock timing:
- the outage scenario now creates and drains its own setup run, so it no longer depends on earlier subtests having created a ready subscription slot;
- after restarting the queue, the test waits until the matching
dispatch_outboxrow reachespublished; - only then does it start the one-shot worker and require the run to reach
succeeded.
Verification
- Exact
admitted_dispatch_is_republished_after_a_queue_outagesubtest passed on a freshly recreated YDB/SQS/MinIO stand. make cipassed.git diff --checkpassed.- GitHub mirror head matches GitCode:
cdb0317de33b85c9392e34f65c700db94e985460.
The fresh GitHub Actions run for cdb0317 remains the merge gate.


CI follow-up: make outage setup independent of prior subscription state
Commit 803c05d fixes the failure in GitHub Actions run 30917393403.
The outage subtest created a setup run and required it to pass through quota_blocked. In the full deterministic slice, earlier subtests may already have left that subscription connection in ready, so the setup run correctly moved directly to queued. The test was asserting an incidental previous state rather than the outage contract.
The setup now:
- creates the setup run;
- explicitly sets the connection to
ready(idempotent for both blocked and already-ready connections); - waits for
queued, consumes that run, and only then starts the queue-outage scenario.
Verification before push:
- exact isolated outage-republication E2E: passed;
make ci: passed;git diff --check: passed.
The GitCode push mirror has been triggered for 803c05d; merge remains gated on the new GitHub Actions run.


CI follow-up: make outage setup independent of prior subscription state
Commit 803c05d fixes the failure in GitHub Actions run 30917393403.
The outage subtest created a setup run and required it to pass through quota_blocked. In the full deterministic slice, earlier subtests may already have left that subscription connection in ready, so the setup run correctly moved directly to queued. The test was asserting an incidental previous state rather than the outage contract.
The setup now:
- creates the setup run;
- explicitly sets the connection to
ready(idempotent for both blocked and already-ready connections); - waits for
queued, consumes that run, and only then starts the queue-outage scenario.
Verification before push:
- exact isolated outage-republication E2E: passed;
make ci: passed;git diff --check: passed.
The GitCode push mirror has been triggered for 803c05d; merge remains gated on the new GitHub Actions run.


CI result: green
GitHub Actions run 30919286094 completed successfully for commit 803c05d.
All required jobs passed:
- Go verification;
- Terraform environments;
- YDB schema and state store;
- Local multi-service stand, including full E2E and stop/restart persistence;
- Runtime images.
MR !18 is ready to merge.


Follow-up: gate application startup on YDB migrations
Commit 0375bad separates local bootstrap into explicit phases:
- start YDB Local, MinIO, ElasticMQ, and Telegram fake;
- wait for infrastructure endpoints and initialize the bucket;
- apply the complete YDB schema;
- only then start control-api, telegram-sender, and reconciler;
- wait for application readiness and seed the fixture.
This removes the expected SCHEME_ERROR / Cannot find table noise produced when schema consumers started against a fresh, not-yet-migrated YDB volume.
The clean-volume test also reproduced a narrower YDB Local readiness gap: its HTTP monitoring endpoint can answer before storage pools are initialized. The migration phase now retries only that exact bootstrap condition, without starting application services or printing the full SDK stack on every attempt. Any other migration failure remains fail-fast and is printed in full.
Verified before push:
- guarded reset of only
sessionless-devvolumes; - clean-volume
make dev-up: passed; - one storage-pool readiness retry completed before application startup;
- control-api/reconciler/telegram-sender logs contained no schema errors;
- uncached local integration suite: passed;
make ci,sh -n scripts/dev-up.sh, Compose validation, andgit diff --check: passed.
The push mirror has been triggered; merge remains gated on the new GitHub Actions run.


CI result: phased YDB bootstrap is green
GitHub Actions run 30921007682 completed successfully for commit 0375bad.
All required jobs passed, including the clean-volume local multi-service stand and its stop/restart persistence check. Application services now start only after the YDB migration phase has completed.
MR !18 remains ready to merge.


Summary
Sessionand append-onlySessionEventthe canonical conversation model;session_idandtrigger_event_idthrough run, worker-job, and harness execution contracts;ContextEpochfrom domain APIs and keep the current YDB revision only as an explicitly transitional Telegram-adapter detail;Compatibility boundary
This MR does not implement the canonical YDB schema or rewrite Telegram ingestion/projection. The small adapter bridge derives stable temporary session/event IDs so the existing implementation continues to compile and run until #21, #22/#36, and #23/#37 land.
Verification
make ciydbintegration,localintegration, ande2elocaltagged suitesgit diff --checkCloses #20