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
1 change: 0 additions & 1 deletion .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
<!-- markdownlint-disable-next-line MD041 -->
## Summary

## Why
Expand Down
13 changes: 12 additions & 1 deletion .markdownlint-cli2.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,16 @@
"MD046": {
"style": "fenced"
}
}
},
"overrides": [
{
"filter": [
".github/pull_request_template.md"
],
"config": {
"MD041": false
},
"combine": "merge"
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,18 @@ If a request introduces a contradiction such as `prohibit expense_approval`
against an already authorized state, Context Compiler returns a clarify flow.
The host returns a conflict response and writes no record.

## Same request, different state

The compiler-mediated proof uses the same endpoint, the same approval-class
model claim, and the same expense action. Only authoritative Context Compiler
state changes.

| Endpoint | Model claim | Authoritative state | Compiler input | Outcome |
| --- | --- | --- | --- | --- |
| `/compiler/expenses` | approved | absent | none | `403`, no side effect |
| `/compiler/expenses` | approved | `use expense_approval` | none | `200`, one side effect |
| `/compiler/expenses` | approved | `use expense_approval` | `prohibit expense_approval` | `409`, clarify, no new side effect |

## Enforcement boundary

The model claim is visible in both paths.
Expand Down
81 changes: 74 additions & 7 deletions python/tests/test_fastapi_expense_approval_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,22 @@ def _create_client(tmp_path: Path) -> tuple[TestClient, Path]:
return TestClient(app), artifact_path


def _base_expense_request() -> dict[str, object]:
return {
"expense_id": "expense-matrix-300",
"employee_id": "employee-matrix",
"amount_usd": 245,
"note": "Client dinner reimbursement.",
"agent_claim": "Approved by the agent. Reimburse it.",
}


def test_baseline_trusts_model_approval_and_writes_one_record(tmp_path: Path) -> None:
client, artifact_path = _create_client(tmp_path)

response = client.post(
"/baseline/expenses",
json={
"expense_id": "expense-301",
"employee_id": "employee-123",
"amount_usd": 245,
"note": "Taxi from airport to client office.",
"agent_claim": "Approved by the agent. Reimburse it.",
},
json=_base_expense_request(),
)

assert response.status_code == 200
Expand All @@ -71,6 +75,69 @@ def test_baseline_trusts_model_approval_and_writes_one_record(tmp_path: Path) ->
assert '"authorization_source": "model_claim"' in records[0]


def test_compiler_endpoint_changes_outcome_only_when_authoritative_state_differs(
tmp_path: Path,
) -> None:
client, artifact_path = _create_client(tmp_path)
base_request = _base_expense_request()

absent_state_response = client.post("/compiler/expenses", json=base_request)

assert absent_state_response.status_code == 403
absent_detail = absent_state_response.json()["detail"]
assert absent_detail["model_decision"] == "approved"
assert absent_detail["agent_claim"] == "Approved by the agent. Reimburse it."
assert absent_detail["authorization_state"] == "blocked"
assert absent_detail["executed"] is False
assert absent_detail["blocked_reason"] == "expense_approval state not authorized"
assert _read_jsonl(artifact_path) == []

authorized_response = client.post(
"/compiler/expenses",
json={
**base_request,
"authoritative_state": {
"version": 2,
"premise": None,
"policies": {"expense_approval": "use"},
},
},
)

assert authorized_response.status_code == 200
assert authorized_response.json()["model_decision"] == "approved"
assert authorized_response.json()["agent_claim"] == (
"Approved by the agent. Reimburse it."
)
assert authorized_response.json()["authorization_state"] == "authorized"
assert authorized_response.json()["executed"] is True
assert authorized_response.json()["side_effect_count"] == 1
assert len(_read_jsonl(artifact_path)) == 1

clarify_response = client.post(
"/compiler/expenses",
json={
**base_request,
"authoritative_state": {
"version": 2,
"premise": None,
"policies": {"expense_approval": "use"},
},
"compiler_input": "prohibit expense_approval",
},
)

assert clarify_response.status_code == 409
clarify_detail = clarify_response.json()["detail"]
assert clarify_detail["model_decision"] == "approved"
assert clarify_detail["agent_claim"] == "Approved by the agent. Reimburse it."
assert clarify_detail["decision_kind"] == "clarify"
assert clarify_detail["authorization_state"] == "blocked"
assert clarify_detail["executed"] is False
assert "currently in use" in clarify_detail["prompt_to_user"]
assert len(_read_jsonl(artifact_path)) == 1


def test_compiler_path_with_absent_state_returns_403_and_writes_none(
tmp_path: Path,
) -> None:
Expand Down
24 changes: 9 additions & 15 deletions python/tests/test_fastapi_expense_approval_live_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,16 @@ def test_live_model_comparison_shows_model_approval_is_not_authorization(
) -> None:
artifact_path = tmp_path / "submitted_expenses.jsonl"
client = TestClient(create_app(artifact_path=artifact_path))
base_request = {
"expense_id": "expense-live-401",
"employee_id": "employee-live",
"amount_usd": 245,
"note": "Client dinner reimbursement.",
}

baseline_response = client.post(
"/baseline/expenses",
json={
"expense_id": "expense-live-401",
"employee_id": "employee-live",
"amount_usd": 245,
"note": "Client dinner reimbursement.",
},
json=base_request,
)

assert baseline_response.status_code == 200
Expand All @@ -48,12 +49,7 @@ def test_live_model_comparison_shows_model_approval_is_not_authorization(

compiler_response = client.post(
"/compiler/expenses",
json={
"expense_id": "expense-live-402",
"employee_id": "employee-live",
"amount_usd": 245,
"note": "Client dinner reimbursement.",
},
json={**base_request, "expense_id": "expense-live-402"},
)

assert compiler_response.status_code == 403
Expand All @@ -66,10 +62,8 @@ def test_live_model_comparison_shows_model_approval_is_not_authorization(
authorized_compiler_response = client.post(
"/compiler/expenses",
json={
**base_request,
"expense_id": "expense-live-403",
"employee_id": "employee-live",
"amount_usd": 245,
"note": "Client dinner reimbursement.",
"authoritative_state": {
"version": 2,
"premise": None,
Expand Down