mirror of
https://github.com/razzant/ouroboros.git
synced 2026-08-26 11:31:48 +00:00
Advance the managed Claudexor runtime pin to 3.6.0 (unified accounts)
The pin moves 3.5.0 -> 3.6.0, the release whose headline is the unified account model (INV-135 rewrite): every account is a named registry row and the pool-authority read GET /v2/account-pools is the feature marker. Pin provenance, verified against the frozen release candidate (claudexor 31aa51c9, candidate release run 32148933151; A-5 exact-artifact promotion ships these bytes verbatim at publish): archive https://github.com/razzant/claudexor/releases/download/v3.6.0/claudexor-runtime-3.6.0.tar.gz, sha256 72b0936eb8825ee1da6adae0dfd8720a8c31c875dce4fb7cb0e36534f279918a (matches the candidate's runtime-manifest.json AND SHA256SUMS AND an independent shasum of the artifact bytes), size 20887532; the extracted closure's identity probe reports {"version":"3.6.0","buildSha":"31aa51c9..."} == the pin. protocol_major stays 3, Node stays 24.16.0, node_artifacts and entrypoint untouched. One post-publish step remains: the archive_url goes live when the owner publishes v3.6.0 -- verify with scripts/fetch_claudexor_runtime.py --output-dir <tmp> before pushing. The cross-repo marker byte-assertion (the sprint's recorded obligation): test_pinned_engine_serves_the_account_pools_marker_id reads the tracked pin and, for a >= 3.6 pinned engine, asserts the Ouroboros-side feature-detect literal _ACCOUNT_POOLS_OPERATION_ID == "get:account-pools" byte-for-byte, plus a 3.6-shaped catalog fixture (the accounts-surface rows exactly as the engine generates them) with and without the marker row. Claudexor pins the same literal from its side in control-api.test.ts; a respelling in either repo now goes red instead of silently degrading every install to the legacy accounts rendering. Issue #246 (_ROTATION_AUTO_SEMANTICS_MIN_VERSION): the kind-aware limit-action "auto" default (claudexor#197) is confirmed shipped in the actual 3.6.0 release -- the candidate's schema carries the "auto" enum with kind-aware semantics -- so the constant already names the real release wave and stays "3.6.0"; its comment now records the confirmation instead of a plan. Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
This commit is contained in:
parent
2d77583a2a
commit
c58453bb2b
3 changed files with 55 additions and 7 deletions
|
|
@ -55,8 +55,10 @@ _ADMISSION_POLL_SEC = 0.15
|
|||
# (kind-aware "auto" semantics, Clawdexor A6): subscription profiles rotate,
|
||||
# metered API keys fail, and the OWNER's explicit choices always win. Blanket
|
||||
# "rotate" writes from this side would overwrite that judgment, so reconcile
|
||||
# skips those engines entirely. A6 is planned for the 3.6.0 release wave; this
|
||||
# is deliberately not CLAUDEXOR_MIN_VERSION (owner decision 5=A: no floor bump).
|
||||
# skips those engines entirely. Confirmed shipped in the actual 3.6.0 release
|
||||
# (claudexor 31aa51c9, schema limit_action enum carries kind-aware "auto"), so
|
||||
# this floor names the real release wave (issue #246); it is deliberately not
|
||||
# CLAUDEXOR_MIN_VERSION (owner decision 5=A: no floor bump).
|
||||
_ROTATION_AUTO_SEMANTICS_MIN_VERSION = "3.6.0"
|
||||
_ROTATION_RECEIPT_NAME = "claudexor_rotation_provisioning.json"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"schema_version": 1,
|
||||
"release": {
|
||||
"version": "3.5.0",
|
||||
"build_sha": "efff2f3b4f9f8e844fbee3578e8681277871f461",
|
||||
"version": "3.6.0",
|
||||
"build_sha": "31aa51c9e545eb061d9335b600a372f484d3f7a9",
|
||||
"protocol_major": 3,
|
||||
"archive_url": "https://github.com/razzant/claudexor/releases/download/v3.5.0/claudexor-runtime-3.5.0.tar.gz",
|
||||
"sha256": "3aa422cc283b0c6930b2f420d77c7865ab74302ba7d24b9d610d0317469dfa16",
|
||||
"size_bytes": 20818642,
|
||||
"archive_url": "https://github.com/razzant/claudexor/releases/download/v3.6.0/claudexor-runtime-3.6.0.tar.gz",
|
||||
"sha256": "72b0936eb8825ee1da6adae0dfd8720a8c31c875dce4fb7cb0e36534f279918a",
|
||||
"size_bytes": 20887532,
|
||||
"node_version": "24.16.0",
|
||||
"node_artifacts": {
|
||||
"darwin-arm64": {
|
||||
|
|
|
|||
|
|
@ -489,6 +489,52 @@ def test_unified_accounts_capability_reads_the_operations_catalog():
|
|||
assert _unified_accounts_native([None, "get:account-pools"]) is False
|
||||
|
||||
|
||||
def test_pinned_engine_serves_the_account_pools_marker_id():
|
||||
"""Cross-repo byte-assertion (unified-accounts sprint obligation): from
|
||||
Claudexor 3.6.0 the engine's /v2/operations catalog serves the pool-
|
||||
authority read under the EXACT id `get:account-pools`. The engine derives
|
||||
ids from routes (`method.toLowerCase() + ':' + path minus its '/v2/'
|
||||
prefix, [:/<>]+ folded to '.'), and claudexor pins the same literal from
|
||||
its side (control-api.test.ts asserts the catalog row for
|
||||
/v2/account-pools carries this id verbatim). If either repo respells it,
|
||||
the feature detect quietly answers False and every install degrades to
|
||||
the legacy accounts rendering — the deliberate cheap direction of
|
||||
`_unified_accounts_native`, which is exactly why no behavioral test would
|
||||
notice. The assertion is gated on the tracked runtime pin so a deliberate
|
||||
pre-3.6 pin rollback leaves it dormant instead of red."""
|
||||
from ouroboros.claudexor_runtime import load_runtime_pin
|
||||
from ouroboros.gateway.claudexor_accounts import (
|
||||
_ACCOUNT_POOLS_OPERATION_ID,
|
||||
_unified_accounts_native,
|
||||
)
|
||||
|
||||
pin = load_runtime_pin()
|
||||
assert pin is not None, "the tracked runtime pin must select a release"
|
||||
major, minor, _patch = (int(part) for part in pin.version.split("."))
|
||||
if (major, minor) < (3, 6):
|
||||
pytest.skip(
|
||||
f"pinned engine {pin.version} predates the unified account model"
|
||||
)
|
||||
assert _ACCOUNT_POOLS_OPERATION_ID == "get:account-pools"
|
||||
# A 3.6-shaped catalog slice — the accounts-surface rows exactly as the
|
||||
# pinned engine generates them — satisfies the feature detect...
|
||||
catalog_3_6 = [
|
||||
{"id": "get:quota", "method": "GET", "path": "/v2/quota"},
|
||||
{"id": "get:account-pools", "method": "GET", "path": "/v2/account-pools"},
|
||||
{"id": "get:credential-profiles", "method": "GET",
|
||||
"path": "/v2/credential-profiles"},
|
||||
{"id": "post:accounts-migration.rollback", "method": "POST",
|
||||
"path": "/v2/accounts-migration/rollback"},
|
||||
]
|
||||
assert _unified_accounts_native(catalog_3_6) is True
|
||||
# ...and the same catalog without the one marker row is the legacy model:
|
||||
# no neighbouring accounts route may stand in for the marker.
|
||||
without_marker = [
|
||||
op for op in catalog_3_6 if op["id"] != _ACCOUNT_POOLS_OPERATION_ID
|
||||
]
|
||||
assert _unified_accounts_native(without_marker) is False
|
||||
|
||||
|
||||
def test_status_payload_stamps_the_unified_accounts_fact(monkeypatch, tmp_path):
|
||||
"""`unified_accounts` rides every status answer: True only when the
|
||||
operations catalog was READ and carries the account-pools marker; an old
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue