fix(model-governance): persist policy floor source of truth
This commit is contained in:
@@ -45,7 +45,7 @@
|
|||||||
"daily_token_budget": 250000,
|
"daily_token_budget": 250000,
|
||||||
"denied_providers": [],
|
"denied_providers": [],
|
||||||
"fallback_limit": 1,
|
"fallback_limit": 1,
|
||||||
"max_input_tokens_per_request": 16000,
|
"max_input_tokens_per_request": 16384,
|
||||||
"max_output_tokens_per_request": 512,
|
"max_output_tokens_per_request": 512,
|
||||||
"project_id": null,
|
"project_id": null,
|
||||||
"required_capabilities": [
|
"required_capabilities": [
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
"daily_token_budget": 250000,
|
"daily_token_budget": 250000,
|
||||||
"denied_providers": [],
|
"denied_providers": [],
|
||||||
"fallback_limit": 1,
|
"fallback_limit": 1,
|
||||||
"max_input_tokens_per_request": 16000,
|
"max_input_tokens_per_request": 16384,
|
||||||
"max_output_tokens_per_request": 512,
|
"max_output_tokens_per_request": 512,
|
||||||
"project_id": "staging",
|
"project_id": "staging",
|
||||||
"required_capabilities": [
|
"required_capabilities": [
|
||||||
|
|||||||
+109
@@ -0,0 +1,109 @@
|
|||||||
|
# Model Governance Policy / Profile Floor Compatibility
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
|
||||||
|
The root-owned OpenClaw runtime profile reserves a minimum of 16,384 input tokens so Model
|
||||||
|
Governance can cover OpenClaw-injected workspace, skills and system context before provider
|
||||||
|
execution.
|
||||||
|
|
||||||
|
The staging scope policies still limited input to 16,000 tokens per request. Route selection
|
||||||
|
therefore failed before reservation with:
|
||||||
|
|
||||||
|
```text
|
||||||
|
MODEL_INPUT_TOKEN_LIMIT_DENY
|
||||||
|
```
|
||||||
|
|
||||||
|
This was a configuration invariant violation:
|
||||||
|
|
||||||
|
```text
|
||||||
|
scope max_input_tokens_per_request
|
||||||
|
<
|
||||||
|
root-owned profile input_reservation_floor_tokens
|
||||||
|
```
|
||||||
|
|
||||||
|
The registered OpenClaw model itself supports 32,768 input tokens, so the model capability was not
|
||||||
|
the blocker.
|
||||||
|
|
||||||
|
## Invariant
|
||||||
|
|
||||||
|
For every Model Governance scope that allows a model/runtime whose root-owned profile declares an
|
||||||
|
input reservation floor:
|
||||||
|
|
||||||
|
```text
|
||||||
|
scope.max_input_tokens_per_request
|
||||||
|
>=
|
||||||
|
profile.model_governance.input_reservation_floor_tokens
|
||||||
|
```
|
||||||
|
|
||||||
|
The profile floor remains root-owned. Task payloads cannot alter it.
|
||||||
|
|
||||||
|
## Staging policy
|
||||||
|
|
||||||
|
The two staging policies that allow `openai/deepseek-v4-flash` are updated from:
|
||||||
|
|
||||||
|
```text
|
||||||
|
16000
|
||||||
|
```
|
||||||
|
|
||||||
|
to:
|
||||||
|
|
||||||
|
```text
|
||||||
|
16384
|
||||||
|
```
|
||||||
|
|
||||||
|
This is the minimum compatible value. It intentionally remains below the model's 32,768-token
|
||||||
|
technical input ceiling.
|
||||||
|
|
||||||
|
The daily token budget is unchanged.
|
||||||
|
|
||||||
|
## Governance path
|
||||||
|
|
||||||
|
The live SQLite policy must be changed only through the repository bootstrap and
|
||||||
|
`aios_model_governance_admin.py`.
|
||||||
|
|
||||||
|
The admin reconciler:
|
||||||
|
|
||||||
|
- reads the governed repository config;
|
||||||
|
- uses current policy revision as CAS;
|
||||||
|
- calls `ModelGovernanceStore.set_scope_policy`;
|
||||||
|
- appends normal Model Governance audit evidence;
|
||||||
|
- verifies the audit chain.
|
||||||
|
|
||||||
|
Direct SQL updates remain forbidden.
|
||||||
|
|
||||||
|
## Exhausted OpenClaw recovery
|
||||||
|
|
||||||
|
The fixed OpenClaw live Task has exhausted its normal three attempts.
|
||||||
|
|
||||||
|
After the governed policy candidate is officially verified and the live policy is reconciled:
|
||||||
|
|
||||||
|
```text
|
||||||
|
attempt 3 VERIFYING/FAILED result
|
||||||
|
→ official NEEDS_REWORK
|
||||||
|
→ Task becomes FAILED 3/3
|
||||||
|
→ official bounded retry extension 3 → 4
|
||||||
|
→ same Task / same Job returns QUEUED
|
||||||
|
→ persistent OpenClaw worker auto-claims attempt 4
|
||||||
|
```
|
||||||
|
|
||||||
|
AR1 attempt-scoped external request identity ensures attempt 4 receives a new external request and a
|
||||||
|
new Model Governance reservation.
|
||||||
|
|
||||||
|
No historical reservation is deleted or rewritten.
|
||||||
|
|
||||||
|
## Acceptance
|
||||||
|
|
||||||
|
Attempt 4 must prove:
|
||||||
|
|
||||||
|
```text
|
||||||
|
scope max_input_tokens_per_request=16384
|
||||||
|
profile input_reservation_floor_tokens=16384
|
||||||
|
reserved_estimated_input_tokens>=16384
|
||||||
|
actual input <= reserved input
|
||||||
|
settlement=SETTLED
|
||||||
|
usage_source=runtime
|
||||||
|
audit_chain_valid=true
|
||||||
|
```
|
||||||
|
|
||||||
|
If attempt 4 exposes a new failure, stop. No additional retry extension is authorized by this
|
||||||
|
repair.
|
||||||
@@ -65,3 +65,35 @@ def test_staging_bootstrap_has_explicit_tenant_live_policy():
|
|||||||
}
|
}
|
||||||
assert ("legacy",None,None) in keys
|
assert ("legacy",None,None) in keys
|
||||||
assert ("tenant","model-governance-live","staging") in keys
|
assert ("tenant","model-governance-live","staging") in keys
|
||||||
|
|
||||||
|
|
||||||
|
def test_staging_policy_input_limit_covers_root_owned_openclaw_reservation_floor():
|
||||||
|
config=json.loads(
|
||||||
|
(ROOT/"config/model-governance/model-governance.staging.json").read_text()
|
||||||
|
)
|
||||||
|
profile=json.loads(
|
||||||
|
(ROOT/"config/external-agent-runtime.d/openclaw.profile.json").read_text()
|
||||||
|
)
|
||||||
|
floor=int(profile["model_governance"]["input_reservation_floor_tokens"])
|
||||||
|
assert floor==16384
|
||||||
|
openclaw_model="openai/deepseek-v4-flash"
|
||||||
|
relevant=[
|
||||||
|
policy for policy in config["policies"]
|
||||||
|
if openclaw_model in policy["allowed_models"]
|
||||||
|
]
|
||||||
|
assert relevant
|
||||||
|
for policy in relevant:
|
||||||
|
assert int(policy["max_input_tokens_per_request"]) >= floor
|
||||||
|
|
||||||
|
|
||||||
|
def test_staging_openclaw_scope_limit_is_least_privilege_floor_not_model_ceiling():
|
||||||
|
config=json.loads(
|
||||||
|
(ROOT/"config/model-governance/model-governance.staging.json").read_text()
|
||||||
|
)
|
||||||
|
models={item["model_id"]:item for item in config["models"]}
|
||||||
|
model=models["openai/deepseek-v4-flash"]
|
||||||
|
assert int(model["max_input_tokens"])==32768
|
||||||
|
for policy in config["policies"]:
|
||||||
|
if "openai/deepseek-v4-flash" in policy["allowed_models"]:
|
||||||
|
assert int(policy["max_input_tokens_per_request"])==16384
|
||||||
|
assert int(policy["max_input_tokens_per_request"]) < int(model["max_input_tokens"])
|
||||||
|
|||||||
Reference in New Issue
Block a user