diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 2091e40a..3ef88246 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -2,7 +2,8 @@ Stateful B3 exchange simulator. Inbound: B3 EntryPoint SBE over TCP. Outbound: B3 UMDF wire format over UDP multicast, plus SBE ExecutionReports back to the -TCP client. Companion to the external `SbeB3UmdfConsumer` repo. +TCP client. Companion to the external `B3MarketDataPlatform` (UMDF +consumer) and `B3EntryPointClient` (EntryPoint client) repos. ## Toolchain @@ -70,7 +71,8 @@ Layered projects under `src/` (build order roughly bottom-up): 1. `B3.EntryPoint.Sbe` / `B3.Umdf.Sbe` — generated SBE bindings from `schemas/b3-entrypoint-messages-8.4.2.xml` and `schemas/b3-market-data-messages-2.2.0.xml`. Vendored copies; keep in sync - with `SbeB3UmdfConsumer` when upgrading. + with `B3EntryPointClient` and `B3MarketDataPlatform` respectively when + upgrading. 2. `B3.Umdf.WireEncoder` — stateless byte-level encoders for UMDF MBO / Trade / Snapshot frames (V16 schema). 3. `B3.Exchange.Instruments` — JSON instrument loader. @@ -115,7 +117,7 @@ Layered projects under `src/` (build order roughly bottom-up): per-session firm assignment is not implemented. - **Schemas are vendored.** Do not hand-edit files under `schemas/`; regenerate the SBE bindings in `B3.*.Sbe` when upgrading and mirror the change in - `SbeB3UmdfConsumer`. + `B3MarketDataPlatform` (UMDF) / `B3EntryPointClient` (EntryPoint). ## Configuration diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d342ef90..148b240a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,17 +42,20 @@ jobs: echo "$changed" fi - # Best-effort cross-check against the companion SbeB3UmdfConsumer - # repo, which vendors the same UMDF market-data schema and is kept - # in lock-step per README.md/CONTRIBUTING.md. Network/availability - # issues here only warn (they must not make an unrelated outage - # block every PR); an entrypoint-only file that isn't vendored - # there also just warns. An actual content mismatch on a shared - # file is treated the same as a local edit. + # Best-effort cross-check against the companion repo that vendors + # the same schema file, kept in lock-step per README.md/ + # CONTRIBUTING.md: b3-market-data-messages-*.xml against + # B3MarketDataPlatform, b3-entrypoint-messages-*.xml against + # B3EntryPointClient. Network/availability issues here only warn + # (they must not make an unrelated outage block every PR); a + # file with no known companion also just warns. An actual + # content mismatch on a shared file is treated the same as a + # local edit. # Scoped to files this PR actually touched under schemas/ — PRs # that don't touch schemas/ must not be blocked by pre-existing # drift between the two repos that predates this PR. Iterated - # line-by-line (not word-split) so filenames with spaces survive. + # line-by-line (not word-split) so filenames with spaces + # survive. # # NOTE: because this only runs for files already in $changed, it # can never independently flip flagged from 0 to 1 — flagged is @@ -72,12 +75,21 @@ jobs: continue fi name="$(basename "$f")" - url="https://raw.githubusercontent.com/pedrosakuma/SbeB3UmdfConsumer/main/schemas/$name" + case "$name" in + b3-market-data-messages-*.xml) companion_repo="B3MarketDataPlatform" ;; + b3-entrypoint-messages-*.xml) companion_repo="B3EntryPointClient" ;; + *) companion_repo="" ;; + esac + if [ -z "$companion_repo" ]; then + echo "::warning::No known companion repo for $name; skipping cross-repo check." + continue + fi + url="https://raw.githubusercontent.com/pedrosakuma/$companion_repo/main/schemas/$name" if remote_sha="$(curl -fsSL --connect-timeout 5 --max-time 15 "$url" 2>/dev/null | sha256sum | awk '{print $1}')"; then local_sha="$(sha256sum "$f" | awk '{print $1}')" if [ "$remote_sha" != "$local_sha" ]; then flagged=1 - echo "$f (sha256 $local_sha) diverges from SbeB3UmdfConsumer's vendored copy (sha256 $remote_sha)." + echo "$f (sha256 $local_sha) diverges from $companion_repo's vendored copy (sha256 $remote_sha)." fi else echo "::warning::Could not fetch $url to cross-check vendored schema fidelity; skipping cross-repo check for $name." diff --git a/.vscode/mcp.json b/.vscode/mcp.json index 11e2a921..e980ff9f 100644 --- a/.vscode/mcp.json +++ b/.vscode/mcp.json @@ -2,7 +2,7 @@ "servers": { "github": { "type": "copilot", - "description": "GitHub MCP — repos, issues, PRs, Actions, code search (companion repo SbeB3UmdfConsumer)" + "description": "GitHub MCP — repos, issues, PRs, Actions, code search (companion repos B3MarketDataPlatform, B3EntryPointClient)" }, "filesystem": { "command": "npx", diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c20d4ce9..7622e006 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -107,5 +107,6 @@ Both must pass before merge. Do not hand-edit files under `schemas/`. When upgrading B3 EntryPoint or UMDF, regenerate the SBE bindings in `B3.*.Sbe` and mirror the -change in the companion `SbeB3UmdfConsumer` repo. The two repos must -agree on the schema version. +change in the companion repo (`B3MarketDataPlatform` for UMDF, +`B3EntryPointClient` for EntryPoint). The repos must agree on the +schema version. diff --git a/README.md b/README.md index 703c9fea..364f24fc 100644 --- a/README.md +++ b/README.md @@ -144,7 +144,8 @@ EntryPoint TCP listener (default port 9876). `schemas/b3-market-data-messages-2.2.0.xml` and `schemas/b3-entrypoint-messages-8.4.2.xml` are vendored copies of the -official B3 SBE schemas. The same files exist in `SbeB3UmdfConsumer`; keep +official B3 SBE schemas. The same files exist in `B3MarketDataPlatform` +(market-data schema) and `B3EntryPointClient` (entrypoint schema); keep them in sync when upgrading. ### Inbound EntryPoint compatibility matrix diff --git a/docs/B3-ENTRYPOINT-ARCHITECTURE.md b/docs/B3-ENTRYPOINT-ARCHITECTURE.md index ff54b9f7..5ddf8b00 100644 --- a/docs/B3-ENTRYPOINT-ARCHITECTURE.md +++ b/docs/B3-ENTRYPOINT-ARCHITECTURE.md @@ -714,7 +714,7 @@ Three test surfaces, mirroring the component split. client speaking SBE + SOFH against it. - Scenarios: full session lifecycle, gap recovery, CoD trigger, daily reset mid-session, throttle reject. -- Use `SbeB3UmdfConsumer` style decoder to verify multicast output. +- Use a `B3MarketDataPlatform` style decoder to verify multicast output. --- @@ -806,7 +806,7 @@ is on so they are inspectable). **EntryPoint and UMDF version independently.** Each schema is bumped on its own cadence; you do not need to upgrade both at once. The companion -[`SbeB3UmdfConsumer`](https://github.com/pedrosakuma/SbeB3UmdfConsumer) +[`B3MarketDataPlatform`](https://github.com/pedrosakuma/B3MarketDataPlatform) repo vendors the same UMDF schema and must be kept in lock-step when the UMDF version moves. @@ -843,7 +843,7 @@ UMDF version moves. the version we target and per-template gap status; bump the version and audit any newly added or removed templates. 8. **Mirror UMDF changes** in - [`SbeB3UmdfConsumer`](https://github.com/pedrosakuma/SbeB3UmdfConsumer) + [`B3MarketDataPlatform`](https://github.com/pedrosakuma/B3MarketDataPlatform) when bumping the market-data schema; the consumer is what proves the wire is end-to-end correct. diff --git a/docs/EXCHANGE-SIMULATOR.md b/docs/EXCHANGE-SIMULATOR.md index 8e4de2d6..0c1f2f5d 100644 --- a/docs/EXCHANGE-SIMULATOR.md +++ b/docs/EXCHANGE-SIMULATOR.md @@ -40,7 +40,7 @@ TCP client ──► EntryPointSession ──► HostRouter ──► ChannelDis ```bash # 1. Build -dotnet build SbeB3UmdfConsumer.slnx +dotnet build SbeB3Exchange.slnx # 2. Run with the sample config dotnet run --project src/B3.Exchange.Host -- config/exchange-simulator.json diff --git a/docs/RUNBOOK.md b/docs/RUNBOOK.md index 2db1abb7..048514d4 100644 --- a/docs/RUNBOOK.md +++ b/docs/RUNBOOK.md @@ -568,7 +568,7 @@ umdf_chaos_duplicated_total{channel="1"} umdf_chaos_reordered_total{channel="1"} ``` -Recovery scenario (companion `SbeB3UmdfConsumer`): +Recovery scenario (companion `B3MarketDataPlatform`): 1. Start the host with `dropProbability: 0.01` on a channel of interest. 2. Drive load with a synthetic trader. diff --git a/docs/adr/0013-options-channel-topology.md b/docs/adr/0013-options-channel-topology.md index f2295507..17bce6fc 100644 --- a/docs/adr/0013-options-channel-topology.md +++ b/docs/adr/0013-options-channel-topology.md @@ -18,9 +18,9 @@ Real B3 publishes equity options on a UMDF channel distinct from cash equities and from derivatives. The simulator must reflect that -topology so consumers (e.g. `B3MarketDataPlatform`, the -`SbeB3UmdfConsumer` companion repo) can validate per-group ring -and cross-group fan-in against a shape that matches production. +topology so consumers (e.g. the `B3MarketDataPlatform` companion repo) +can validate per-group ring and cross-group fan-in against a shape +that matches production. Two designs were considered while drafting RFC 0002: diff --git a/docs/rfc/0002-equity-options-support.md b/docs/rfc/0002-equity-options-support.md index 2e4958b2..a0c56401 100644 --- a/docs/rfc/0002-equity-options-support.md +++ b/docs/rfc/0002-equity-options-support.md @@ -428,7 +428,7 @@ as ADRs are written. ## 8. Risks and consequences -- **Schema coupling with `SbeB3UmdfConsumer`.** No schema is +- **Schema coupling with `B3MarketDataPlatform`.** No schema is modified — only encoder output. Consumers compatible with UMDF v2.2.0 receive the new fields transparently. **Action:** no-op, but confirm in the encoder PR that the companion repo's parser diff --git a/src/B3.Exchange.Core/ChaosUdpPacketSinkDecorator.cs b/src/B3.Exchange.Core/ChaosUdpPacketSinkDecorator.cs index bb642a75..bd9df9bd 100644 --- a/src/B3.Exchange.Core/ChaosUdpPacketSinkDecorator.cs +++ b/src/B3.Exchange.Core/ChaosUdpPacketSinkDecorator.cs @@ -5,7 +5,7 @@ namespace B3.Exchange.Core; /// /// decorator that injects controlled packet loss, /// duplication, and reordering into an inner sink. Designed for testing the -/// companion SbeB3UmdfConsumer's recovery paths (snapshot bootstrap, +/// companion B3MarketDataPlatform's recovery paths (snapshot bootstrap, /// gap detection) without external network-shaping tools. /// /// NOT thread-safe; like the inner sinks it expects to be called from a