From 61345158e44443ec50feeca9c8eec65f062537d4 Mon Sep 17 00:00:00 2001 From: Elmehdi Aitbrahim Date: Wed, 2 Sep 2026 05:17:31 -0400 Subject: [PATCH] chore(release): 0.13.3 -- honest cost at the gate Twelve commits since 0.13.2, and one of them has live consequence. #335 IS THE REASON TO CUT THIS. The promotion gate priced every fill at the FLOOR of keel's own slippage model -- a rate reached only at a $500M/day anchor, which NOT ONE of the 24 assets keel holds candles for reaches. `keel rules promote` would have priced a promotion decision at 5bp on an asset whose measured rate is up to 36.8x that. Nothing is promoting today, so it was never urgent; it is the kind of thing that matters the first time it is not. The restatement that fired it is in the release too: 240 trials showing the median profit factor across 120 cells falling 0.309 -> 0.219 under per-product pricing, and the corpus's only cell above 1.0 dying at 0.626. The correction is 2.7x the +0.033 that the best strategy change ever bought. ALSO SHIPPING: * #341/#342 -- two new rule kinds, `cusum_event` and `triple_barrier`, both measured and both null. Registered and UNTRADED: no rule row, no allowlist change, nothing promoted. They ship so the measurement is reproducible, not because anything is expected of them. * #648 -- an enforced 12-hour session lifetime once a remote host is configured, and a wildcard bind that refuses to start without one. Remote access is still NOT ready: the PWA's secure-context behaviour over a real HTTPS origin is unverified and `docs/remote-access.md` says so at the top. * #681 -- `doctor` reports the update backups it never mentioned. This release is the first build that can see them, which is why the 7.0 GB in the live launch folder had to be found by asking rather than by being told. * #687/#688 -- the rail count, which disagreed with itself in five places at v0.13.2, now derived from `guards.check` and pinned; and the cost-distortion finding rendered into the README from the hash-chained ledger. No migration: schema stays at v16. The bump is nine files because it has to be. `tests/test_packaging.py:: test_every_workspace_package_carries_the_same_version` was re-run against a deliberately partial bump before committing this one, and it still fails -- the guard that caught the root-only bump at 0.13.0 is alive. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01NzuKAe2RVrPt9acVAWjRyL --- packages/keel-broker-alpaca/pyproject.toml | 4 ++-- packages/keel-broker-api/pyproject.toml | 4 ++-- packages/keel-broker-coinbase/pyproject.toml | 4 ++-- packages/keel-broker-fake/pyproject.toml | 4 ++-- packages/keel-broker-kraken/pyproject.toml | 4 ++-- packages/keel-broker-robinhood/pyproject.toml | 4 ++-- packages/keel-core/pyproject.toml | 2 +- pyproject.toml | 8 ++++---- uv.lock | 16 ++++++++-------- 9 files changed, 25 insertions(+), 25 deletions(-) diff --git a/packages/keel-broker-alpaca/pyproject.toml b/packages/keel-broker-alpaca/pyproject.toml index 1206b4a..221227f 100644 --- a/packages/keel-broker-alpaca/pyproject.toml +++ b/packages/keel-broker-alpaca/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "keel-broker-alpaca" -version = "0.13.2" +version = "0.13.3" description = "Alpaca Trading API adapter for keel (US equities, cash account)" license = "Apache-2.0" requires-python = ">=3.14" @@ -9,7 +9,7 @@ requires-python = ">=3.14" # deliberately NO `alpaca-py` SDK: Alpaca's Trading + Market Data APIs are plain # JSON-over-HTTPS with two header credentials, so the SDK would add a version-churning # dependency for nothing the port needs. -dependencies = ["keel-core==0.13.2", "keel-broker-api==0.13.2", "requests>=2.32.0"] +dependencies = ["keel-core==0.13.3", "keel-broker-api==0.13.3", "requests>=2.32.0"] [project.entry-points."keel.brokers"] alpaca = "keel_broker_alpaca:AlpacaAdapter" diff --git a/packages/keel-broker-api/pyproject.toml b/packages/keel-broker-api/pyproject.toml index 6bf71b4..b85def2 100644 --- a/packages/keel-broker-api/pyproject.toml +++ b/packages/keel-broker-api/pyproject.toml @@ -1,12 +1,12 @@ [project] name = "keel-broker-api" -version = "0.13.2" +version = "0.13.3" description = "Broker port, domain types, capability model, and conformance suite for keel" license = "Apache-2.0" requires-python = ">=3.14" # Pinned `==`: see the note in the root `pyproject.toml`. An unpinned sibling is satisfied by # whatever is already installed, which is how a deployment ends up running mixed versions. -dependencies = ["keel-core==0.13.2"] +dependencies = ["keel-core==0.13.3"] [project.optional-dependencies] conformance = ["pytest>=9.1.1"] diff --git a/packages/keel-broker-coinbase/pyproject.toml b/packages/keel-broker-coinbase/pyproject.toml index 5845ac7..df476a9 100644 --- a/packages/keel-broker-coinbase/pyproject.toml +++ b/packages/keel-broker-coinbase/pyproject.toml @@ -1,12 +1,12 @@ [project] name = "keel-broker-coinbase" -version = "0.13.2" +version = "0.13.3" description = "Coinbase Advanced Trade adapter for keel" license = "Apache-2.0" requires-python = ">=3.14" # Siblings pinned `==` (see the root `pyproject.toml`); the third-party SDK is not, because it # has its own release cycle and is not cut from this repo. -dependencies = ["keel-core==0.13.2", "keel-broker-api==0.13.2", "coinbase-advanced-py>=1.8.4"] +dependencies = ["keel-core==0.13.3", "keel-broker-api==0.13.3", "coinbase-advanced-py>=1.8.4"] [project.entry-points."keel.brokers"] coinbase = "keel_broker_coinbase:CoinbaseAdapter" diff --git a/packages/keel-broker-fake/pyproject.toml b/packages/keel-broker-fake/pyproject.toml index 5416e9b..47569a3 100644 --- a/packages/keel-broker-fake/pyproject.toml +++ b/packages/keel-broker-fake/pyproject.toml @@ -1,11 +1,11 @@ [project] name = "keel-broker-fake" -version = "0.13.2" +version = "0.13.3" description = "A deliberately divergent second broker adapter, to keep the port honest" license = "Apache-2.0" requires-python = ">=3.14" # Pinned `==`: see the note in the root `pyproject.toml`. -dependencies = ["keel-core==0.13.2", "keel-broker-api==0.13.2"] +dependencies = ["keel-core==0.13.3", "keel-broker-api==0.13.3"] [project.entry-points."keel.brokers"] fake = "keel_broker_fake:FakeAdapter" diff --git a/packages/keel-broker-kraken/pyproject.toml b/packages/keel-broker-kraken/pyproject.toml index b0d4b64..3953155 100644 --- a/packages/keel-broker-kraken/pyproject.toml +++ b/packages/keel-broker-kraken/pyproject.toml @@ -1,13 +1,13 @@ [project] name = "keel-broker-kraken" -version = "0.13.2" +version = "0.13.3" description = "Kraken adapter for keel (port-complete stub; every data/market method raises)" license = "Apache-2.0" requires-python = ">=3.14" # Siblings pinned `==` (see the root `pyproject.toml`). There is deliberately NO third-party # dependency: this package is a stub (#313) that handles no keys and makes no network calls, # so a Kraken SDK (and its credentials) arrive with the real implementation, not before it. -dependencies = ["keel-core==0.13.2", "keel-broker-api==0.13.2"] +dependencies = ["keel-core==0.13.3", "keel-broker-api==0.13.3"] [project.entry-points."keel.brokers"] kraken = "keel_broker_kraken:KrakenAdapter" diff --git a/packages/keel-broker-robinhood/pyproject.toml b/packages/keel-broker-robinhood/pyproject.toml index 8d72da0..1c1bb19 100644 --- a/packages/keel-broker-robinhood/pyproject.toml +++ b/packages/keel-broker-robinhood/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "keel-broker-robinhood" -version = "0.13.2" +version = "0.13.3" description = "Robinhood Crypto Trading API v2 adapter for keel" license = "Apache-2.0" requires-python = ">=3.14" @@ -8,7 +8,7 @@ requires-python = ">=3.14" # Ed25519 key, which no other venue keel talks to requires. Keeping it a dependency of this # package alone means an engine that never installs this adapter never installs the crypto stack # either -- the whole point of adapters being separate distributions. -dependencies = ["keel-core==0.13.2", "keel-broker-api==0.13.2", "pynacl>=1.5.0", "requests>=2.32.0"] +dependencies = ["keel-core==0.13.3", "keel-broker-api==0.13.3", "pynacl>=1.5.0", "requests>=2.32.0"] [project.entry-points."keel.brokers"] robinhood = "keel_broker_robinhood:RobinhoodAdapter" diff --git a/packages/keel-core/pyproject.toml b/packages/keel-core/pyproject.toml index 64cb467..3f12762 100644 --- a/packages/keel-core/pyproject.toml +++ b/packages/keel-core/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "keel-core" -version = "0.13.2" +version = "0.13.3" description = "Shared domain types, configuration, and logging for keel" license = "Apache-2.0" requires-python = ">=3.14" diff --git a/pyproject.toml b/pyproject.toml index 9733357..a01bd16 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "keel-trader" -version = "0.13.2" +version = "0.13.3" description = "Offline-first, broker-agnostic, rule-based spot-trading agent (halal policy by default)" license = "Apache-2.0" readme = "README.md" @@ -23,15 +23,15 @@ dependencies = [ # in one build, so `==` states a fact rather than guessing at compatibility. The cost is that # a version bump must move these numbers too -- the bump already edits every package's # `version`, and `tests/test_packaging.py` fails the build if a pin is left behind. - "keel-core==0.13.2", - "keel-broker-api==0.13.2", + "keel-core==0.13.3", + "keel-broker-api==0.13.3", # The default venue resolves through the keel.brokers entry points (#524), so the adapter # is a hard runtime dependency, not a convenience: without it installed, every config -- # including one with no `broker:` section -- fails at broker construction. The CLI also # imports the SDK directly to build the adapter's RESTClient transport # (`keel/commands/_common.py`); moving that construction into the adapter package is # Phase B's, with cb_client.py's deletion. - "keel-broker-coinbase==0.13.2", + "keel-broker-coinbase==0.13.3", ] [project.scripts] diff --git a/uv.lock b/uv.lock index d6b5173..dc4df10 100644 --- a/uv.lock +++ b/uv.lock @@ -454,7 +454,7 @@ wheels = [ [[package]] name = "keel-broker-alpaca" -version = "0.13.2" +version = "0.13.3" source = { editable = "packages/keel-broker-alpaca" } dependencies = [ { name = "keel-broker-api" }, @@ -471,7 +471,7 @@ requires-dist = [ [[package]] name = "keel-broker-api" -version = "0.13.2" +version = "0.13.3" source = { editable = "packages/keel-broker-api" } dependencies = [ { name = "keel-core" }, @@ -491,7 +491,7 @@ provides-extras = ["conformance"] [[package]] name = "keel-broker-coinbase" -version = "0.13.2" +version = "0.13.3" source = { editable = "packages/keel-broker-coinbase" } dependencies = [ { name = "coinbase-advanced-py" }, @@ -508,7 +508,7 @@ requires-dist = [ [[package]] name = "keel-broker-fake" -version = "0.13.2" +version = "0.13.3" source = { editable = "packages/keel-broker-fake" } dependencies = [ { name = "keel-broker-api" }, @@ -523,7 +523,7 @@ requires-dist = [ [[package]] name = "keel-broker-kraken" -version = "0.13.2" +version = "0.13.3" source = { editable = "packages/keel-broker-kraken" } dependencies = [ { name = "keel-broker-api" }, @@ -538,7 +538,7 @@ requires-dist = [ [[package]] name = "keel-broker-robinhood" -version = "0.13.2" +version = "0.13.3" source = { editable = "packages/keel-broker-robinhood" } dependencies = [ { name = "keel-broker-api" }, @@ -557,7 +557,7 @@ requires-dist = [ [[package]] name = "keel-core" -version = "0.13.2" +version = "0.13.3" source = { editable = "packages/keel-core" } dependencies = [ { name = "keyring" }, @@ -574,7 +574,7 @@ requires-dist = [ [[package]] name = "keel-trader" -version = "0.13.2" +version = "0.13.3" source = { editable = "." } dependencies = [ { name = "click" },