Scaling Authority Contract (NE-164)¶
Status: accepted AU authority boundary; runtime actuation and cross-repository wiring are follow-on work.
Concept: AU-OS.scaling.reactive-replica-autoscaling
Decision¶
Autoscaling is governed by a typed, revisioned authority contract. The
contract is implemented in
agent_utilities.orchestration.scaling_authority and is intentionally separate
from metric collection, graph persistence, and runtime actuation. It gives
those layers one vocabulary and one set of fail-closed invariants:
ResourcePooldeclares capacity, allocation, reserved headroom, quota, failure domain, and offline recovery policy.WorkloadClassbinds a tenant/workload, cadence, concurrency, and quota to a resource pool.ScaleUnitdeclares the elastic unit's floor, ceiling, headroom, tenant quota, failure domain, maintenance window, rollback policy, dependencies, and controller mode.SignalSummaryRefis a digest-addressed, bounded pointer to an external metrics summary. Raw samples, query expressions, and high-rate telemetry do not enter graph-facing records.ScaleIntentis a revision/CAS- and idempotency-bound desired change.ScaleDecision,ScaleExecution, andObservedOutcomepreserve the decision, actuation, and convergence evidence as one lifecycle chain.LeaseFenceidentity must remain unchanged over the lifecycle. A stale revision or changed fence is rejected rather than merged optimistically.
The contract version is explicit (schema_version: "1") and all records are
closed (extra="forbid") and immutable after validation. Additive evolution
requires a new contract version and compatibility fixtures.
Four independent control cadences¶
The system must not collapse all scaling into one autoscaler tick:
| Cadence | Authority | Graph lifecycle records |
|---|---|---|
engine_local |
In-process admission, write coalescing, and back-pressure | No |
shard_placement |
Placement, rebalancing, and shard movement | Yes |
service_replica |
Service replicas or a delegated HPA/KEDA controller | Yes |
agent_topology |
Bounded agent/team topology changes | Yes |
Only the latter three are graph-owned scaling lifecycles. Engine-local
admission remains a low-latency implementation concern; it cannot create a
ScaleIntent. High-rate measurements remain with the metrics/telemetry
authority. The graph receives only a bounded summary reference and lifecycle
evidence, never one node or mutation per sample.
flowchart LR
M[Metrics authority\nhigh-rate samples] --> S[SignalSummaryRef\ndigest + bounded window]
A[ResourcePool + WorkloadClass + ScaleUnit] --> I[ScaleIntent\nrevision + CAS + idempotency]
S --> I
I --> D[ScaleDecision\npolicy verdict]
D --> E[ScaleExecution\nprepared/simulated/started/succeeded]
E --> O[ObservedOutcome\nconverged/pending/failed]
L[LeaseFence + failure domain + quotas] --> D
L --> E
O --> R[Rollback / revision update]
Exactly one replica writer¶
Each ScaleUnit has exactly one registered controller with
writes_replicas: true. A registration is either:
native: the AU authority owns the desired replica field; no HPA/KEDA controller is declared; ordelegated: the explicitly namedhpaorkedacontroller owns the replica field and AU records intents, policy decisions, and observations.
Observation-only registrations are allowed, but they must declare the same mode and delegated controller as the unit. Two writers, or a native writer and a delegated writer for the same unit, are rejected before actuation. This is the anti-oscillation boundary: a reconciler and an autoscaler cannot drive independent desired states for one unit.
Safety invariants¶
The authority rejects records that will violate any of these bounds:
min_replicas <= desired_replicas <= max_replicas;- unit and workload quotas cover their floors and do not exceed pool capacity
after reserved headroom;
max_unitsremains a hard replica/concurrency ceiling andburst_unitsis an explicitly bounded admission reserve; - unit maximum plus unit headroom fits within pool capacity after pool headroom;
- references resolve to known pools, workloads, units, and failure domains;
- self-dependencies and indirect dependency cycles are absent;
- an offline failure domain with
holdrecovery cannot accept a new intent; - maintenance windows use an explicit queue/deny policy;
- terminal execution states carry completion evidence; simulated execution never claims completed actuation; failures carry a bounded failure code;
- rollback operations carry their target replica count and outcomes retain rollback evidence.
The ScaleIntent validator is a policy/input gate, not an actuator. The
runtime must re-check the authority revision, lease/fence, quota, hardware
headroom, maintenance policy, and controller ownership immediately before any
mutating operation. Failure or loss of the authority lease fails closed;
offline failover/shed behavior requires a later placement/recovery policy
to produce a new revision rather than silently reusing stale intent state.
Authenticated signal boundary (NE-165)¶
orchestration.scaling_signal_authority provides the bounded read seam used by
signal adapters. It carries source identity, service/tenant/unit scope,
normalized signal kind, aggregation, sample and event timestamps, freshness,
confidence, and opaque evidence references. The vocabulary is deliberately
finite: cpu, ram, gpu, kv_cache, disk, network, token, request,
latency, queue, and shard.
Every read is a digest-bound batch query with an explicit timeout, window, page size, maximum item count, and snapshot cursor. A deployment may tighten the global caps but cannot loosen them. Backend adapters must stream stable pages; the authority stores only one bounded page and a bounded replay guard, so a million-resource catalog is paginated rather than materialized.
The provider rejects non-finite or negative values, stale/future samples,
missing timestamps, scope changes, source/attestation mismatches, query
credential material, query-digest mismatches, malformed cursors, and replayed
or out-of-order source sequences. Missing data returns an empty page and is
never converted to zero. The default opaque-reference authenticator exists
for deterministic fixtures; deployments should inject a cryptographic source
verifier through the SignalAuthenticator seam.
High-rate samples remain in the metrics path. SignalPage.graph_projection()
and SignalSummary.graph_projection() contain only bounded metadata. Exact
query text is retained in SignalDecisionEvidence together with its digest,
snapshot, and window; graph-facing records receive summary evidence rather
than one mutation per sample.
Follow-on boundaries¶
This AU slice provides the common typed authority and deterministic contract fixtures. It does not change Kubernetes manifests, HPA/KEDA resources, epistemic-graph production code, metric backends, or live fleet controllers. Follow-on work must preserve the one-writer rule and the four cadence separation while adding durable outbox/replay, signal authority, and runtime actuation. A dry-run or simulated execution must remain visibly simulated and must not be reported as scaled.