Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,7 @@ The same explicitly authorized rollover contract applies to the later supported
| `acceptance-revalidation-v16` | Settled V15, including the stale-confirmation U03 failure |
| `acceptance-revalidation-v17` | Settled V16, including the cancellation-state U03 failure |
| `acceptance-revalidation-v18` | Settled V17, including the equivalent-array-definition boundary failure |
| `acceptance-revalidation-v19` | Settled V18, including the pre-dispatch save-intent recovery failure |

Before preparation, retain the predecessor ledger, binding and guard at their pinned
fingerprints and preserve the entire earlier history chain. The selected policy's
Expand Down Expand Up @@ -556,6 +557,12 @@ settled costs; local grammar regressions do not replace genuine model acceptance
The same cumulative USD200 ceiling, three unknown liabilities and purpose/token
caps apply. Establish fresh acceptance for the changed candidate.

V19 retains the permanently halted V18 ledger, binding and guard for save-intent
restart recovery. Preserve the original incomplete U03 result and its settled costs;
the earlier U02 gate remains evidence for its original candidate only. The same
cumulative USD200 ceiling, three unknown liabilities and purpose/token caps apply.
Establish fresh acceptance for the changed candidate.

Issue the evidence-bound U02 gate only after those inputs validate. Gate artifact references are
relative to the private directory containing the gate; place the referenced artifacts there:

Expand Down
4 changes: 2 additions & 2 deletions services/agent/data/repository_corpus_manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
},
{
"doc_id": "repository-development",
"version": "sha256-afbb26c451fbaeb42cc30c0b897c4c6115eeb33a9216a1020a0410c258c89185",
"chunk_id": "repository-development:sha256-afbb26c451fbaeb42cc30c0b897c4c6115eeb33a9216a1020a0410c258c89185:1",
"version": "sha256-fde1dceb193829a479b2980bde4f77a264937ad9b819905cd4235be22af9f565",
"chunk_id": "repository-development:sha256-fde1dceb193829a479b2980bde4f77a264937ad9b819905cd4235be22af9f565:1",
"source_path": "docs/DEVELOPMENT.md",
"access_scope": "repository-public",
"sample_kind": "real",
Expand Down
14 changes: 14 additions & 0 deletions services/agent/src/authorized_budget_period.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
REVALIDATION_V16_POLICY_ID = "acceptance-revalidation-v16"
REVALIDATION_V17_POLICY_ID = "acceptance-revalidation-v17"
REVALIDATION_V18_POLICY_ID = "acceptance-revalidation-v18"
REVALIDATION_V19_POLICY_ID = "acceptance-revalidation-v19"
REVALIDATION_POLICY_IDS = frozenset({REVALIDATION_POLICY_ID, REVALIDATION_V2_POLICY_ID, REVALIDATION_V3_POLICY_ID, REVALIDATION_V4_POLICY_ID, REVALIDATION_V5_POLICY_ID, REVALIDATION_V6_POLICY_ID, REVALIDATION_V7_POLICY_ID, REVALIDATION_V8_POLICY_ID, REVALIDATION_V9_POLICY_ID, REVALIDATION_V10_POLICY_ID, REVALIDATION_V11_POLICY_ID, REVALIDATION_V12_POLICY_ID})
REVALIDATION_V2_HISTORY = MappingProxyType({
"attempts": 164, "known_actual_micro_usd": 42_307,
Expand Down Expand Up @@ -275,6 +276,17 @@
})
REVALIDATION_POLICY_IDS = REVALIDATION_POLICY_IDS | {REVALIDATION_V18_POLICY_ID}

REVALIDATION_V19_HISTORY = MappingProxyType({
"attempts": 1590, "known_actual_micro_usd": 471_411,
"known_committed_micro_usd": 14_092_514,
"unknown_attempts": 3, "unknown_encumbrance_micro_usd": 2_359_296,
"cumulative_attempt_limit": 1831, "cumulative_limit_micro_usd": 200_000_000,
})
REVALIDATION_V19_POLICY = MappingProxyType({
**REVALIDATION_V18_POLICY, "history": REVALIDATION_V19_HISTORY,
})
REVALIDATION_POLICY_IDS = REVALIDATION_POLICY_IDS | {REVALIDATION_V19_POLICY_ID}


def policy_for(policy_id: str):
if policy_id == POLICY_ID:
Expand Down Expand Up @@ -315,6 +327,8 @@ def policy_for(policy_id: str):
return REVALIDATION_V17_POLICY
if policy_id == REVALIDATION_V18_POLICY_ID:
return REVALIDATION_V18_POLICY
if policy_id == REVALIDATION_V19_POLICY_ID:
return REVALIDATION_V19_POLICY
raise PeriodError("unsupported policy")


Expand Down
27 changes: 23 additions & 4 deletions services/agent/src/revalidation_history.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,13 +320,30 @@ def _check_unknown_rollover(snapshot, guard, *, predecessor="v2"):
}


V18_ROLLOVER_IDENTITY = {
"period_id": "revalidation-v18-20261011",
"identity": "22bc94738c1045fb808d6dfff07c902f",
"config_sha256": "e4a0d82bee049228bfc54d97df3b5326d7c28156ef8a60fc10c2c30af90be017",
"policy_id": "acceptance-revalidation-v18",
}
V18_ROLLOVER_SHA256 = {
"budget.sqlite3": "3120884dac903caf59bbd55d5c28194440192dd55a45b08c06544fb842ac2034",
"binding.json": "774da3d801ff55bb46211ca8d8258d3f7028c91aa5c0fc0371efff26fe0e9bca",
"dav58-increment-22bc94738c1045fb808d6dfff07c902f.json": "2f7f35a997d5bf355cb92674ce47b7c3837b7a44f67464e162cf56d127b3b260",
}


def _validate_rollover_history(sources, *, settled_policy="v1"):
from authorized_budget_period import REVALIDATION_V14_HISTORY, REVALIDATION_V15_HISTORY, REVALIDATION_V16_HISTORY, REVALIDATION_V17_HISTORY, REVALIDATION_V18_HISTORY
from authorized_budget_period import REVALIDATION_V14_HISTORY, REVALIDATION_V15_HISTORY, REVALIDATION_V16_HISTORY, REVALIDATION_V17_HISTORY, REVALIDATION_V18_HISTORY, REVALIDATION_V19_HISTORY
from authorized_budget_period import PeriodError, PeriodIdentity, REVALIDATION_V2_HISTORY, REVALIDATION_V4_HISTORY, REVALIDATION_V5_HISTORY, REVALIDATION_V6_HISTORY, REVALIDATION_V7_HISTORY, REVALIDATION_V8_HISTORY, REVALIDATION_V9_HISTORY, REVALIDATION_V10_HISTORY, REVALIDATION_V11_HISTORY, REVALIDATION_V12_HISTORY, _parent, _file
from model_budget import ModelBudget, authorization_slot
from dav58_live_guard import IncrementalGuard

if settled_policy == "v17":
if settled_policy == "v18":
original = _validate_rollover_history(sources, settled_policy="v17")
identity, fingerprints = V18_ROLLOVER_IDENTITY, V18_ROLLOVER_SHA256
totals, history = (104, 35_994, 932_400), REVALIDATION_V19_HISTORY
elif settled_policy == "v17":
original = _validate_rollover_history(sources, settled_policy="v16")
identity, fingerprints = V17_ROLLOVER_IDENTITY, V17_ROLLOVER_SHA256
totals, history = (96, 33_723, 864_000), REVALIDATION_V18_HISTORY
Expand Down Expand Up @@ -418,7 +435,7 @@ def _validate_rollover_history(sources, *, settled_policy="v1"):
try:
# Validate sealed receipts without making the permanently halted journal resumable.
receipt_view = guard
if settled_policy in {"v13", "v14", "v15", "v16", "v17"}:
if settled_policy in {"v13", "v14", "v15", "v16", "v17", "v18"}:
if guard.get("halted") is not True:
raise PeriodError("previous guard must be permanently halted")
receipt_view = {**guard, "halted": False}
Expand All @@ -431,10 +448,12 @@ def _validate_rollover_history(sources, *, settled_policy="v1"):


def validate_history(sources, *, policy_id="acceptance-revalidation-v1"):
from authorized_budget_period import REVALIDATION_V13_POLICY_ID, REVALIDATION_V14_POLICY_ID, REVALIDATION_V15_POLICY_ID, REVALIDATION_V16_POLICY_ID, REVALIDATION_V17_POLICY_ID, REVALIDATION_V18_POLICY_ID
from authorized_budget_period import REVALIDATION_V13_POLICY_ID, REVALIDATION_V14_POLICY_ID, REVALIDATION_V15_POLICY_ID, REVALIDATION_V16_POLICY_ID, REVALIDATION_V17_POLICY_ID, REVALIDATION_V18_POLICY_ID, REVALIDATION_V19_POLICY_ID
from authorized_budget_period import PeriodError, REVALIDATION_HISTORY, _parent, _file
from authorized_budget_period import REVALIDATION_POLICY_ID, REVALIDATION_V2_POLICY_ID, REVALIDATION_V3_POLICY_ID, REVALIDATION_V4_POLICY_ID, REVALIDATION_V5_POLICY_ID, REVALIDATION_V6_POLICY_ID, REVALIDATION_V7_POLICY_ID, REVALIDATION_V8_POLICY_ID, REVALIDATION_V9_POLICY_ID, REVALIDATION_V10_POLICY_ID, REVALIDATION_V11_POLICY_ID, REVALIDATION_V12_POLICY_ID

if policy_id == REVALIDATION_V19_POLICY_ID:
return _validate_rollover_history(sources, settled_policy="v18")
if policy_id == REVALIDATION_V18_POLICY_ID:
return _validate_rollover_history(sources, settled_policy="v17")
if policy_id == REVALIDATION_V17_POLICY_ID:
Expand Down
80 changes: 79 additions & 1 deletion services/agent/tests/test_v16_confirmation_history.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,82 @@
from authorized_budget_period import policy_for
import hashlib
import json
from types import SimpleNamespace

import pytest

from authorized_budget_period import PeriodError, policy_for


@pytest.mark.parametrize("mutation", [None, "fingerprint", "state", "sql_gate", "halted",
"unknown_usage_attempts", "unsettled_attempts", "attempts",
"actual_micro_usd", "committed_micro_usd", "guard", "receipts"])
def test_v19_binding_requires_intact_settled_and_halted_v18(monkeypatch, tmp_path, mutation):
import model_budget
import revalidation_history as history
from dav58_live_guard import IncrementalGuard

accounting = tmp_path / "accounting"
accounting.mkdir(mode=0o700)
guard_name = f'dav58-increment-{history.V18_ROLLOVER_IDENTITY["identity"]}.json'
guard = {"halted": mutation != "guard", "receipts": []}
pins = {}
for name, raw in {"budget.sqlite3": b"sealed fixture", "binding.json": b"{}",
guard_name: json.dumps(guard).encode()}.items():
path = accounting / name
path.write_bytes(raw)
path.chmod(0o600)
pins[name] = hashlib.sha256(raw).hexdigest()
monkeypatch.setattr(history, "V18_ROLLOVER_SHA256", pins)
real_validate = history._validate_rollover_history
predecessor = {"sha256": {"older": "retained"}}
def previous(sources, *, settled_policy="v1"):
if settled_policy == "v17":
return predecessor
return real_validate(sources, settled_policy=settled_policy)
monkeypatch.setattr(history, "_validate_rollover_history", previous)
monkeypatch.setattr(model_budget, "authorization_slot", lambda expected: tmp_path)
snapshot = {"state": "halted", "sql_gate": "halted", "halted": 1, "attempts": 104,
"actual_micro_usd": 35994, "committed_micro_usd": 932400,
"unknown_usage_attempts": 0, "unsettled_attempts": 0}
if mutation == "fingerprint":
(accounting / "budget.sqlite3").write_bytes(b"changed")
elif mutation in snapshot:
snapshot[mutation] = "active" if mutation in {"state", "sql_gate"} else 0 if mutation == "halted" else snapshot[mutation] + 1
def sealed_view(expected, retained):
assert expected.policy_id == "acceptance-revalidation-v18"
assert retained is predecessor
return SimpleNamespace(snapshot=lambda: snapshot, policy={})
monkeypatch.setattr(model_budget.ModelBudget, "_sealed_history_view", sealed_view)
def check_receipts(receipt_view, *args):
assert receipt_view["halted"] is False
if mutation == "receipts":
raise ValueError("dispatch mismatch")
monkeypatch.setattr(IncrementalGuard, "_validate_resume", check_receipts)
if mutation:
with pytest.raises(PeriodError):
history.validate_history({}, policy_id="acceptance-revalidation-v19")
else:
audit = history.validate_history({}, policy_id="acceptance-revalidation-v19")
assert audit["sha256"]["older"] == "retained"
assert audit["baseline"] == dict(policy_for("acceptance-revalidation-v19")["history"])
assert audit["acceptance_evidence"] is audit["unknown_released"] is False


def test_recovery_revalidation_retains_settled_v18_and_unknown_liabilities():
old = policy_for("acceptance-revalidation-v18")
policy = policy_for("acceptance-revalidation-v19")
history = policy["history"]
assert history["attempts"] == old["history"]["attempts"] + 104 == 1590
assert history["known_actual_micro_usd"] == old["history"]["known_actual_micro_usd"] + 35994 == 471411
assert history["known_committed_micro_usd"] == old["history"]["known_committed_micro_usd"] + 932400 == 14092514
assert history["unknown_attempts"] == old["history"]["unknown_attempts"] == 3
assert history["unknown_encumbrance_micro_usd"] == old["history"]["unknown_encumbrance_micro_usd"] == 2359296
assert history["cumulative_limit_micro_usd"] == old["history"]["cumulative_limit_micro_usd"] == 200000000
assert history["cumulative_attempt_limit"] == history["attempts"] + policy["attempts"] == 1831
assert policy["lanes"] == old["lanes"]
assert policy["limit_micro_usd"] == old["limit_micro_usd"]
assert (history["known_committed_micro_usd"] + history["unknown_encumbrance_micro_usd"]
+ policy["limit_micro_usd"] <= history["cumulative_limit_micro_usd"])


def test_array_range_revalidation_retains_settled_v17_and_unknown_liabilities():
Expand Down
Loading