diff --git a/code-mower-package-manifest.json b/code-mower-package-manifest.json index 2d32d5dd..bc0ea39b 100644 --- a/code-mower-package-manifest.json +++ b/code-mower-package-manifest.json @@ -182,6 +182,11 @@ "source": "docs/operational-evidence.md", "target": "docs/operational-evidence.md" }, + { + "kind": "doc", + "source": "docs/operator-contract-v1.md", + "target": "docs/operator-contract-v1.md" + }, { "kind": "doc", "source": "docs/oss-v1-checklist.md", @@ -1417,6 +1422,26 @@ "source": "src/code_mower/operational_evidence.py", "target": "src/code_mower/operational_evidence.py" }, + { + "kind": "template", + "source": "src/code_mower/operator_contract_v1.fixtures.json", + "target": "src/code_mower/operator_contract_v1.fixtures.json" + }, + { + "kind": "core", + "source": "src/code_mower/operator_contract_v1.py", + "target": "src/code_mower/operator_contract_v1.py" + }, + { + "kind": "schema", + "source": "src/code_mower/operator_policy_v1.schema.json", + "target": "src/code_mower/operator_policy_v1.schema.json" + }, + { + "kind": "schema", + "source": "src/code_mower/operator_state_v1.schema.json", + "target": "src/code_mower/operator_state_v1.schema.json" + }, { "kind": "core", "source": "src/code_mower/package.py", diff --git a/docs/README.md b/docs/README.md index 79c04321..bddbf968 100644 --- a/docs/README.md +++ b/docs/README.md @@ -27,6 +27,7 @@ historical release evidence and are not current operating guidance. | Install Rehearsal | [First-User Install Rehearsal](first-user-install-rehearsal.md) | | Installation | [Install And Bootstrap](install.md) | | Jira | [Jira Cloud Setup](jira-cloud-setup.md) | +| Operator Contract | [Operator contract v1](operator-contract-v1.md) | | Package Publication | [PyPI Release Runbook](pypi-release.md) | | Provider Selection | [Code Mower Provider Matrix](provider-matrix.md) | | Quickstart | [Code Mower Quickstart](quickstart.md) | diff --git a/docs/docs-manifest.yml b/docs/docs-manifest.yml index b718ef6d..c10ca5d7 100644 --- a/docs/docs-manifest.yml +++ b/docs/docs-manifest.yml @@ -144,6 +144,9 @@ documents: status: supporting - path: docs/operational-evidence.md status: supporting +- path: docs/operator-contract-v1.md + status: canonical + subject: operator-contract - path: docs/orchestrator-prompt-pack.md status: supporting - path: docs/oss-v1-checklist.md diff --git a/docs/operator-contract-v1.md b/docs/operator-contract-v1.md new file mode 100644 index 00000000..c0c17a05 --- /dev/null +++ b/docs/operator-contract-v1.md @@ -0,0 +1,265 @@ +# Operator contract v1 + +This is the single authoritative product, authority, state, recovery, privacy, +and failure contract for the Code Mower v1.7 single-tenant Operator. It freezes +the boundary that later storage, service, GitHub App, Board, and provider work +must implement. It does not provide an Operator loop, dispatch a provider, or +grant a process permission to mutate anything. + +The machine-readable contract consists of +`operator_policy_v1.schema.json`, `operator_state_v1.schema.json`, and +`operator_contract_v1.fixtures.json` in the `code_mower` package. Every object +is closed: an unknown field is invalid. A consumer must select behavior from +the record's versioned `schema` value and fail closed on an unknown version. +`operator_contract_v1.py` supplies the normative semantic checks for time, +generation, and recovery transitions that portable JSON Schema cannot express. +Consumers validate the closed record first and then apply those checks; schema +validation alone does not grant authority. + +The record versions are `code_mower.operatorPolicy.v1`, +`code_mower.operatorQualification.v1`, `code_mower.operatorWorkItem.v1`, +`code_mower.operatorLease.v1`, `code_mower.operatorActionIntent.v1`, and +`code_mower.operatorProjection.v1`. + +## Product boundary and authority + +The Operator serves one tenant and only repositories in its explicit +allowlist. Repository admission, credentials, policy, and budgets come from +owner-controlled configuration. An observed issue, label, comment, provider +message, Board row, or model output is untrusted input and cannot widen that +configuration. + +The Operator may observe bounded repository, issue, pull request, check, +provider-session, and Operator-record metadata. It may propose work selection, +provider assignment, review, and owner escalation. After policy, capability, +lease, head, intent, and budget checks, a later runtime may perform only the +mutation names present in `authority.mutations`. Absence from that array is a +denial. + +The v1 pilot always requires a human to approve and perform a merge. The +Operator never merges a pull request, approves its own work, weakens branch +protection, expands its repository allowlist, exposes private content, or +mints or rotates credentials. A provider record for `merge_authority` remains +denied even if the same provider qualifies for other roles. + +The contract authorizes no current implementation. Active dispatch, GitHub App +mutation, remote Board ingress, and cloud-schema changes remain separate work. + +## Work lifecycle + +One durable `code_mower.operatorWorkItem.v1` record identifies a tenant, +repository, work item, and monotonically increasing generation. Its state is: + +`observed -> admitted -> claimed -> executing -> waiting_provider -> +reconciling -> awaiting_review -> completed` + +The canonical path is illustrative; only edges listed by the schema are legal. +`awaiting_owner` is a nonterminal stop. Owner action can return it to +`admitted` or `executing`, or cancel it. `completed`, `failed`, and `cancelled` +are terminal and cannot re-enter active work. Each write atomically records the +new state, allowed transition, reason, generation, and timestamps. A +generation mismatch rejects the write rather than overwriting newer state. +Active states other than `awaiting_owner` require reason `none`; every +`awaiting_owner` record uses one of the policy stop reasons; and `completed`, +`failed`, and `cancelled` require `work_completed`, `work_failed`, and +`owner_cancelled`, respectively. These combinations are closed in the schema. +The work record also carries cumulative `elapsed_seconds` and `spend_usd`; +neither may move backwards across a transition or exceed owner policy. + +The Operator stops in `awaiting_owner` for required approval, exhausted budget, +missing or stale qualification, unavailable credentials, policy denial, +inconclusive reconciliation, a repository outside the allowlist, a stale +head, a stale lease, or required user input. Escalations use a durable +`owner_escalation_key` and the configured count limit. Redelivery and restart +reuse that key, so the same stop does not create another owner notification. +Exhausting that limit leaves the item stopped; it does not create a new +escalation channel or enlarge a budget. Policy and work records use the same +stop-reason vocabulary, including `stale_head` and `stale_lease`. + +## Singleton lease and fencing + +A deployment has one lease for each tenant and repository scope. Acquisition +and renewal are compare-and-swap writes in the durable store. Every successful +acquisition or takeover increments `epoch` and produces a new `fence_token`. +Renewal retains both. A holder stops starting work before `renew_by` if renewal +does not succeed, and it has no authority after `expires_at`. + +Every mutation intent binds the work generation, lease identity, dispatch lease +epoch, and dispatch fencing token. The durable store and each mutation adapter compare +the generation, tenant and repository scope, original epoch and token, exact +head, and a live independently read lease immediately before dispatch, retry, +and result commit. Stored `fence_status` and `head_status` labels never prove +authority. A stale holder cannot dispatch, retry, or overwrite the new holder's +state. A prepared, never-dispatched intent whose generation, fence, or target +head is stale is abandoned. An already-dispatched unknown intent retains its +immutable original dispatch fence and stays unknown. The new holder records a +separate current `reconciliation_authority` and reconciles it without +redispatch. The semantic check compares that authority with the current durable +lease rather than trusting the record's `current` label. Takeover first +increments the epoch, then recovers all nonterminal intents; it never creates a +replacement intent merely because the previous process disappeared. + +Lease time is an availability mechanism. Fencing is the correctness mechanism. +Clock skew, delayed workers, and a process resuming after expiry must therefore +fail the fencing comparison even when they locally believe the lease is valid. +Lease chronology is `acquired_at <= renew_by < expires_at`; active authority +ends at `renew_by` unless a compare-and-swap renewal advances both deadlines. +`acquired_at` is the durable anchor for the current authority interval. A +successful acquisition, takeover, or renewal atomically sets that anchor and +the two deadlines. The policy binding check requires `renew_by` to equal the +anchor plus `lease_renewal_seconds` and `expires_at` to equal the anchor plus +`lease_ttl_seconds`; shifting both deadlines cannot extend authority. + +## Durable intent, certainty, and reconciliation + +Before any remote mutation, the Operator atomically persists a +`code_mower.operatorActionIntent.v1` record. Its `action_id`, operation, +request digest, idempotency key, work generation, exact target head, dispatch +lease epoch, and dispatch fence token are immutable dispatch inputs. Budget +counters are durable and cumulative across the intent's transitions. +Re-delivery of the same idempotency key and request digest returns the recorded +outcome. Reuse of the key with a different digest is a policy error. A +generation mismatch rejects dispatch, retry, and result commit rather than +letting an intent from an earlier admission act on current work. + +An intent starts `prepared` with `not_attempted` certainty. The runtime may +dispatch it only while the lease fence and target head are current and a +mutation slot and all budgets remain available. A provider or transport +timeout, disconnect, malformed response after dispatch, crash before response +persistence, or partial response produces `unknown` certainty. Unknown is not +failure. Its only next action is reconciliation or bounded owner action. + +Reconciliation queries remote state using the idempotency key, stable remote +reference when known, target head, and operation-specific metadata. Confirmed +remote success records `confirmed_success` without another mutation. +Confirmed absence or failure records `confirmed_failure`; a retry can then be +considered under the same durable intent and cumulative budget. Under the +original holder, retry requires the original dispatch fence to remain current. +After takeover, the original fence remains stale and immutable, while retry +requires the separately recorded current `reconciliation_authority` to match +the independently read live lease. Inconclusive reconciliation remains unknown +and eventually stops for owner action. A new intent cannot be used to bypass +uncertainty. + +Restart loads nonterminal intents before admitting new work. Duplicate +delivery, restart, and lease takeover therefore converge on the saved intent. +A stale target head or fence abandons a prepared intent and requires fresh +observation. When dispatch already happened and certainty is unknown, the +current holder instead reconciles the original immutable target and fence; +neither path silently retargets or repeats a mutation. + +## Budgets and failure semantics + +Policy places ceilings on concurrent work and mutations, attempts, +reconciliations, owner escalations, work and action time, spend, lease TTL, and +renewal cadence. Counters are cumulative across retries, restarts, and lease +takeovers. Reservation and increment happen atomically before dispatch. A +failure to reserve a unit is a stop, not permission to run and account later. +Only an owner can install a new policy with larger limits. + +The normative `policy_binding_errors` API binds every state record to the +owner policy. It checks the tenant, repository allowlist, authorized mutation, +action attempts/reconciliations/time/spend, work time/spend/escalations, and +lease cadence. Concurrent reservation still belongs to the durable-store +transaction, while each persisted record must independently remain within +these ceilings. + +Failures have these required outcomes: + +| Event | Required source and edge | Durable outcome | Forbidden shortcut | +| --- | --- | --- | --- | +| Process restart after dispatch | Dispatched or uncertain unknown intent -> reconciling | Load the intent and reconcile | Blind retry | +| Duplicate delivery | Any saved intent -> the identical record | Return the idempotent recorded result | Second mutation | +| Lease takeover | Dispatched or uncertain unknown intent -> reconciling under a new lease | Increment epoch and record separate current reconciliation authority | Accept the old token or blindly retry | +| Stale head | Prepared, not-attempted intent -> abandoned | Abandon before dispatch; reconcile an already-dispatched unknown effect through the takeover path | Mutate or silently retarget the stale head | +| Provider timeout | Prepared, not-attempted intent -> uncertain unknown | Record unknown and reconcile | Erase a known result or assume failure | +| Partial success | Dispatched or uncertain unknown intent -> reconciling | Reconcile each remote effect | Repeat the mutation set | +| Budget exhaustion | Active nonterminal work -> `awaiting_owner`, with `last_transition` naming that exact edge | Stop and escalate within the remaining limit | Implicitly extend budget or invent a source edge | +| Owner stop | Nonterminal work -> `cancelled`; prepared action -> `abandoned` | Cancel or abandon without new mutation | Continue dispatch | + +`failed` means a confirmed terminal work failure. Transport errors do not make +a mutation a confirmed failure. Cancellation is complete only when no new +mutation can start and any already-dispatched uncertain mutation has been +reconciled or explicitly left for owner action. + +## Provider capability and role qualification + +Qualification is per provider, transport, role, and exact source head. The +provider identifier is opaque data, never a switch statement. Eligibility +requires a capability declaration, deterministic harness result, exact-head +result, policy decision, and unexpired evidence. Missing, failed, stale, or +incomplete evidence is denied. + +The schema binds each status to a matching decision, reason, and evidence +shape. The normative `qualification_semantic_errors` check additionally +requires `observed_at < expires_at`, rejects future or expired observations, +applies the policy's maximum evidence age at an explicit durable-store `now`, +and verifies that every required capability was declared. Failed-evidence +records retain the evidence that failed, and `capability_missing` names an +actual declaration gap. Callers use that shared check instead of defining +their own clock or expiry ordering. + +Codex and Claude are the initial qualified targets represented by the accepted +fixtures. Devin is represented as pending until equivalent evidence exists; +its name is neither a denial nor an exception. Any future provider can qualify +under the same record shape. A provider qualified as a builder does not thereby +qualify as orchestrator or reviewer, and an author cannot satisfy an +independent review requirement for its own head. + +## Privacy and projection + +Operator projection is metadata-only. The closed +`code_mower.operatorProjection.v1` record is the only v1 shape that may be +projected to local status, a future private Board ingress, or a future cloud +adapter. It contains opaque identifiers, role and state values, bounded counts, +elapsed time, and decimal spend metadata. + +Projection combinations are event-specific and closed. `work_state` carries a +work identifier and a valid work state/reason pair; `lease_state` carries no +work, action, or provider identity and uses only lease state/reason pairs; +`action_state` carries work, action, provider, and role identities and a valid +action state/reason pair; `owner_action` carries only the affected work +identity and a stop or cancellation pair; and `qualification_state` carries +provider and role identity with a qualification state/reason pair. A state or +reason from another event family is invalid even when each value is separately +known to the contract. + +Source, diffs, prompts, transcripts, issue bodies, raw provider output, +credentials, private content, and personal paths are excluded. Hashing private +content does not make it allowed metadata unless this contract explicitly +names the digest. Raw durable intent and lease records stay in the private +Operator store; their presence in the package does not authorize upload. + +This contract does not change an existing Board, telemetry, or cloud schema. +A future adapter must validate the closed projection, perform its own +authorization, and preserve the same denylist. + +## Threat and authority notes + +The main authority threats are a second process acting after takeover, an +untrusted work item widening scope, a provider being treated as qualified by +name, a timeout being retried after remote success, a stale head receiving a +mutation, budget counters resetting on restart, and content leaking through a +status surface. Lease epochs and fencing contain split brain; closed policy and +allowlist checks contain scope injection; evidence records contain provider +confusion; durable intents and reconciliation contain duplicate mutation; +head binding contains retargeting; durable counters contain retry amplification; +and closed projections contain content leakage. + +Credentials remain outside these records and are supplied to the narrow +adapter that needs them. Schema-valid data is necessary but insufficient for +authority: a runtime must also authenticate the owner-controlled policy, +compare current durable state, enforce repository and role separation, and +receive an adapter-level authorization decision. Logs and errors follow the +same metadata-only boundary. + +The canonical accepted and rejected fixtures are executable examples of these +rules. Each recovery fixture contains schema-valid before, required-after, and +named forbidden-after record sequences. Named rejected transition fixtures +also cover invalid sources and false source-edge claims; +`recovery_transition_errors` verifies +tenant, repository, Operator-lease identity, lease chronology, timestamps, +every cumulative integer counter, decimal spend, fencing, and certainty. +Dependent implementations must consume them without weakening a rejected case, +and must add implementation-specific failure injection without changing the +meaning of the v1 records. diff --git a/pyproject.toml b/pyproject.toml index e62dbdbf..2c91e794 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,6 +54,7 @@ where = ["src"] "docs/v152-release-notes.md", "docs/v152-qualification.md", "docs/v152-release-runbook.md", + "docs/operator-contract-v1.md", "docs/slack-setup.md", "docs/graphify-setup.md", ] diff --git a/src/code_mower/operator_contract_v1.fixtures.json b/src/code_mower/operator_contract_v1.fixtures.json new file mode 100644 index 00000000..43d62fff --- /dev/null +++ b/src/code_mower/operator_contract_v1.fixtures.json @@ -0,0 +1,4446 @@ +{ + "schema": "code_mower.operatorContractFixtures.v1", + "contract": "code_mower.operator.v1", + "accepted": [ + { + "name": "single_tenant_manual_merge_policy", + "contract_schema": "operator_policy_v1.schema.json", + "document": { + "schema": "code_mower.operatorPolicy.v1", + "contract_version": "1.7", + "tenant_id": "tenant_example", + "repository_allowlist": [ + "repository_example" + ], + "authority": { + "observation": [ + "repository_metadata", + "issue_metadata", + "pull_request_metadata", + "check_metadata", + "provider_session_metadata", + "operator_records" + ], + "proposals": [ + "work_selection", + "provider_assignment", + "owner_escalation", + "review_request" + ], + "mutations": [ + "create_provider_session", + "message_provider_session", + "cancel_provider_session", + "create_branch", + "push_commit", + "open_or_update_pull_request", + "apply_workflow_label", + "request_review", + "post_bounded_status" + ], + "denied": [ + "merge_pull_request", + "approve_own_work", + "weaken_branch_protection", + "expose_private_content", + "expand_repository_allowlist", + "mint_or_rotate_credentials" + ], + "merge_approval": "human_required", + "operator_merge": false + }, + "budgets": { + "max_concurrent_work_items": 2, + "max_concurrent_mutations": 1, + "max_attempts_per_action": 3, + "max_reconciliations_per_action": 2, + "max_owner_escalations": 2, + "max_work_seconds": 14400, + "max_action_seconds": 300, + "max_spend_usd": "25.00", + "lease_ttl_seconds": 90, + "lease_renewal_seconds": 30 + }, + "qualification": { + "roles": [ + "orchestrator", + "builder", + "reviewer", + "merge_authority" + ], + "required_evidence": [ + "capability_declaration", + "deterministic_harness", + "exact_head_result", + "policy_decision" + ], + "max_evidence_age_seconds": 604800, + "fail_closed": true, + "provider_name_grants_authority": false + }, + "privacy": { + "classification": "metadata_only", + "projection_fields": [ + "schema", + "event_type", + "observed_at", + "tenant_id", + "repository_id", + "work_id", + "action_id", + "provider_id", + "role", + "state", + "reason", + "attempt_count", + "elapsed_seconds", + "spend_usd" + ], + "excluded_content": [ + "source", + "diffs", + "prompts", + "transcripts", + "issue_bodies", + "raw_provider_output", + "credentials", + "private_content", + "personal_paths" + ], + "opaque_identifiers": true + }, + "owner_action": { + "stop_reasons": [ + "approval_required", + "budget_exhausted", + "capability_unqualified", + "credentials_unavailable", + "policy_denied", + "reconciliation_inconclusive", + "repository_not_allowed", + "stale_head", + "stale_lease", + "user_input_required" + ], + "delivery": "bounded_deduplicated_escalation", + "after_budget_exhaustion": "stop_without_mutation" + } + } + }, + { + "name": "codex_orchestrator_qualified_by_evidence", + "contract_schema": "operator_policy_v1.schema.json", + "document": { + "schema": "code_mower.operatorQualification.v1", + "provider_id": "codex", + "transport_id": "codex_service", + "role": "orchestrator", + "required_capabilities": [ + "observe_repository", + "select_work", + "create_session", + "structured_result", + "reconcile_remote_mutation" + ], + "declared_capabilities": [ + "observe_repository", + "select_work", + "create_session", + "structured_result", + "reconcile_remote_mutation" + ], + "evidence": { + "capability_declaration_digest": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "harness_digest": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "source_head": "1111111111111111111111111111111111111111", + "observed_at": 2000000000, + "expires_at": 2000604800 + }, + "status": "qualified", + "decision": "allowed", + "reason": "evidence_current" + }, + "semantic_context": { + "now": 2000000100 + } + }, + { + "name": "claude_reviewer_qualified_by_evidence", + "contract_schema": "operator_policy_v1.schema.json", + "document": { + "schema": "code_mower.operatorQualification.v1", + "provider_id": "claude", + "transport_id": "claude_service", + "role": "reviewer", + "required_capabilities": [ + "observe_repository", + "request_review", + "structured_result" + ], + "declared_capabilities": [ + "observe_repository", + "request_review", + "structured_result" + ], + "evidence": { + "capability_declaration_digest": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc", + "harness_digest": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", + "source_head": "2222222222222222222222222222222222222222", + "observed_at": 2000000000, + "expires_at": 2000604800 + }, + "status": "qualified", + "decision": "allowed", + "reason": "evidence_current" + }, + "semantic_context": { + "now": 2000000100 + } + }, + { + "name": "claude_orchestrator_qualified_by_evidence", + "contract_schema": "operator_policy_v1.schema.json", + "document": { + "schema": "code_mower.operatorQualification.v1", + "provider_id": "claude", + "transport_id": "claude_service", + "role": "orchestrator", + "required_capabilities": [ + "observe_repository", + "select_work", + "create_session", + "structured_result", + "reconcile_remote_mutation" + ], + "declared_capabilities": [ + "observe_repository", + "select_work", + "create_session", + "structured_result", + "reconcile_remote_mutation" + ], + "evidence": { + "capability_declaration_digest": "7777777777777777777777777777777777777777777777777777777777777777", + "harness_digest": "8888888888888888888888888888888888888888888888888888888888888888", + "source_head": "4444444444444444444444444444444444444444", + "observed_at": 2000000000, + "expires_at": 2000604800 + }, + "status": "qualified", + "decision": "allowed", + "reason": "evidence_current" + }, + "semantic_context": { + "now": 2000000100 + } + }, + { + "name": "devin_builder_pending_without_exclusion", + "contract_schema": "operator_policy_v1.schema.json", + "document": { + "schema": "code_mower.operatorQualification.v1", + "provider_id": "devin", + "transport_id": "devin_service", + "role": "builder", + "required_capabilities": [ + "create_session", + "write_branch", + "open_pull_request", + "structured_result" + ], + "declared_capabilities": [ + "create_session", + "write_branch", + "open_pull_request", + "structured_result" + ], + "evidence": null, + "status": "pending", + "decision": "denied", + "reason": "evidence_missing" + }, + "semantic_context": { + "now": 2000000100 + } + }, + { + "name": "provider_merge_authority_is_reserved_for_human", + "contract_schema": "operator_policy_v1.schema.json", + "document": { + "schema": "code_mower.operatorQualification.v1", + "provider_id": "codex", + "transport_id": "codex_service", + "role": "merge_authority", + "required_capabilities": [ + "observe_repository" + ], + "declared_capabilities": [ + "observe_repository" + ], + "evidence": null, + "status": "pending", + "decision": "denied", + "reason": "human_merge_required" + }, + "semantic_context": { + "now": 2000000100 + } + }, + { + "name": "work_waiting_for_owner_after_budget_exhaustion", + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorWorkItem.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "generation": 4, + "state": "awaiting_owner", + "terminal": false, + "last_transition": "reconciling:awaiting_owner", + "reason": "budget_exhausted", + "owner_escalation_count": 1, + "created_at": 2000000000, + "updated_at": 2000000300, + "owner_escalation_key": "9999999999999999999999999999999999999999999999999999999999999999", + "elapsed_seconds": 300, + "spend_usd": "0.10" + }, + "semantic_context": {} + }, + { + "name": "singleton_lease_with_fencing_epoch", + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "state": "active", + "acquired_at": 2000000000, + "renew_by": 2000000030, + "expires_at": 2000000090 + }, + "semantic_context": {} + }, + { + "name": "durable_intent_precedes_dispatch", + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "prepared", + "certainty": "not_attempted", + "reconciliation": "not_required", + "next_action": "dispatch", + "remote_reference": null, + "budget": { + "attempt_count": 0, + "reconciliation_count": 0, + "elapsed_seconds": 0, + "spend_usd": "0.00" + }, + "created_at": 2000000000, + "updated_at": 2000000000, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + }, + "semantic_context": { + "current_work_generation": 4, + "now": 2000000000, + "current_head_sha": "3333333333333333333333333333333333333333", + "current_lease": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "state": "active", + "acquired_at": 2000000000, + "renew_by": 2000000030, + "expires_at": 2000000090 + } + } + }, + { + "name": "timeout_is_uncertain_and_reconciles_before_retry", + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "uncertain", + "certainty": "unknown", + "reconciliation": "required", + "next_action": "reconcile", + "remote_reference": null, + "budget": { + "attempt_count": 1, + "reconciliation_count": 0, + "elapsed_seconds": 240, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000240, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + }, + "semantic_context": { + "current_work_generation": 4, + "now": 2000000240, + "current_head_sha": "3333333333333333333333333333333333333333", + "current_lease": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "state": "active", + "acquired_at": 2000000240, + "renew_by": 2000000270, + "expires_at": 2000000330 + } + } + }, + { + "name": "reconciliation_confirms_remote_success", + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "succeeded", + "certainty": "confirmed_success", + "reconciliation": "matched_success", + "next_action": "none", + "remote_reference": "pull_request_401", + "budget": { + "attempt_count": 1, + "reconciliation_count": 1, + "elapsed_seconds": 280, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000280, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + }, + "semantic_context": { + "current_work_generation": 4, + "now": 2000000280, + "current_head_sha": "3333333333333333333333333333333333333333", + "current_lease": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "state": "active", + "acquired_at": 2000000280, + "renew_by": 2000000310, + "expires_at": 2000000370 + } + } + }, + { + "name": "stale_fence_abandons_intent", + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_stale_holder", + "operation": "push_commit", + "idempotency_key": "2222222222222222222222222222222222222222222222222222222222222222", + "request_digest": "3333333333333333333333333333333333333333333333333333333333333333", + "lease_epoch": 7, + "fence_token": "4444444444444444444444444444444444444444444444444444444444444444", + "fence_status": "stale", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "abandoned", + "certainty": "not_applicable", + "reconciliation": "not_required", + "next_action": "abandon", + "remote_reference": null, + "budget": { + "attempt_count": 0, + "reconciliation_count": 0, + "elapsed_seconds": 1, + "spend_usd": "0.00" + }, + "created_at": 2000000000, + "updated_at": 2000000001, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + }, + "semantic_context": { + "current_work_generation": 4, + "now": 2000000001 + } + }, + { + "name": "metadata_only_projection", + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorProjection.v1", + "event_type": "action_state", + "observed_at": 2000000340, + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "provider_id": "codex", + "role": "orchestrator", + "state": "succeeded", + "reason": "reconciled_success", + "attempt_count": 1, + "elapsed_seconds": 340, + "spend_usd": "0.10" + }, + "semantic_context": {} + }, + { + "name": "takeover_reconciles_unknown_without_redispatch", + "contract_schema": "operator_state_v1.schema.json", + "semantic_context": { + "current_work_generation": 4, + "now": 2000000250, + "current_head_sha": "3333333333333333333333333333333333333333", + "current_lease": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "state": "active", + "acquired_at": 2000000250, + "renew_by": 2000000280, + "expires_at": 2000000340 + } + }, + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "stale", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "reconciling", + "certainty": "unknown", + "reconciliation": "in_progress", + "next_action": "reconcile", + "remote_reference": null, + "budget": { + "attempt_count": 1, + "reconciliation_count": 0, + "elapsed_seconds": 250, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000250, + "work_generation": 4, + "reconciliation_authority": { + "lease_epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "fence_status": "current" + }, + "lease_id": "operator_singleton" + } + }, + { + "name": "confirmed_failure_retries_under_original_authority", + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "failed", + "certainty": "confirmed_failure", + "reconciliation": "matched_failure", + "next_action": "retry", + "remote_reference": "provider_attempt_1", + "budget": { + "attempt_count": 1, + "reconciliation_count": 1, + "elapsed_seconds": 10, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000010, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + }, + "semantic_context": { + "current_work_generation": 4, + "now": 2000000000, + "current_head_sha": "3333333333333333333333333333333333333333", + "current_lease": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "state": "active", + "acquired_at": 2000000000, + "renew_by": 2000000030, + "expires_at": 2000000090 + } + } + }, + { + "name": "takeover_confirmed_failure_retries_under_current_authority", + "contract_schema": "operator_state_v1.schema.json", + "semantic_context": { + "current_work_generation": 4, + "now": 2000000250, + "current_head_sha": "3333333333333333333333333333333333333333", + "current_lease": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "state": "active", + "acquired_at": 2000000250, + "renew_by": 2000000280, + "expires_at": 2000000340 + } + }, + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "stale", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "failed", + "certainty": "confirmed_failure", + "reconciliation": "matched_failure", + "next_action": "retry", + "remote_reference": "provider_attempt_1", + "budget": { + "attempt_count": 1, + "reconciliation_count": 1, + "elapsed_seconds": 250, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000250, + "work_generation": 4, + "reconciliation_authority": { + "lease_epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "fence_status": "current" + }, + "lease_id": "operator_singleton" + } + } + ], + "rejected": [ + { + "name": "operator_cannot_merge", + "contract_schema": "operator_policy_v1.schema.json", + "expected_violation": "operator_merge must remain false and merge approval must remain human-required", + "document": { + "schema": "code_mower.operatorPolicy.v1", + "contract_version": "1.7", + "tenant_id": "tenant_example", + "repository_allowlist": [ + "repository_example" + ], + "authority": { + "observation": [ + "repository_metadata" + ], + "proposals": [ + "work_selection" + ], + "mutations": [], + "denied": [ + "merge_pull_request", + "approve_own_work", + "weaken_branch_protection", + "expose_private_content", + "expand_repository_allowlist", + "mint_or_rotate_credentials" + ], + "merge_approval": "human_required", + "operator_merge": true + }, + "budgets": { + "max_concurrent_work_items": 2, + "max_concurrent_mutations": 1, + "max_attempts_per_action": 3, + "max_reconciliations_per_action": 2, + "max_owner_escalations": 2, + "max_work_seconds": 14400, + "max_action_seconds": 300, + "max_spend_usd": "25.00", + "lease_ttl_seconds": 90, + "lease_renewal_seconds": 30 + }, + "qualification": { + "roles": [ + "orchestrator", + "builder", + "reviewer", + "merge_authority" + ], + "required_evidence": [ + "capability_declaration", + "deterministic_harness", + "exact_head_result", + "policy_decision" + ], + "max_evidence_age_seconds": 604800, + "fail_closed": true, + "provider_name_grants_authority": false + }, + "privacy": { + "classification": "metadata_only", + "projection_fields": [ + "schema", + "event_type", + "observed_at", + "tenant_id", + "repository_id", + "work_id", + "action_id", + "provider_id", + "role", + "state", + "reason", + "attempt_count", + "elapsed_seconds", + "spend_usd" + ], + "excluded_content": [ + "source", + "diffs", + "prompts", + "transcripts", + "issue_bodies", + "raw_provider_output", + "credentials", + "private_content", + "personal_paths" + ], + "opaque_identifiers": true + }, + "owner_action": { + "stop_reasons": [ + "approval_required", + "budget_exhausted", + "capability_unqualified", + "credentials_unavailable", + "policy_denied", + "reconciliation_inconclusive", + "repository_not_allowed", + "user_input_required" + ], + "delivery": "bounded_deduplicated_escalation", + "after_budget_exhaustion": "stop_without_mutation" + } + } + }, + { + "name": "provider_name_is_not_qualification", + "contract_schema": "operator_policy_v1.schema.json", + "expected_violation": "qualified providers require current evidence", + "document": { + "schema": "code_mower.operatorQualification.v1", + "provider_id": "codex", + "transport_id": "codex_service", + "role": "builder", + "required_capabilities": [ + "write_branch" + ], + "declared_capabilities": [ + "write_branch" + ], + "evidence": null, + "status": "qualified", + "decision": "allowed", + "reason": "evidence_current" + } + }, + { + "name": "unqualified_provider_is_denied", + "contract_schema": "operator_policy_v1.schema.json", + "expected_violation": "pending evidence fails closed", + "document": { + "schema": "code_mower.operatorQualification.v1", + "provider_id": "future_provider", + "transport_id": "future_service", + "role": "builder", + "required_capabilities": [ + "write_branch" + ], + "declared_capabilities": [ + "write_branch" + ], + "evidence": null, + "status": "pending", + "decision": "allowed", + "reason": "evidence_missing" + } + }, + { + "name": "provider_cannot_receive_merge_authority", + "contract_schema": "operator_policy_v1.schema.json", + "expected_violation": "merge authority remains human-only in the pilot", + "document": { + "schema": "code_mower.operatorQualification.v1", + "provider_id": "claude", + "transport_id": "claude_service", + "role": "merge_authority", + "required_capabilities": [ + "observe_repository" + ], + "declared_capabilities": [ + "observe_repository" + ], + "evidence": { + "capability_declaration_digest": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "harness_digest": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "source_head": "1111111111111111111111111111111111111111", + "observed_at": 2000000000, + "expires_at": 2000604800 + }, + "status": "qualified", + "decision": "allowed", + "reason": "evidence_current" + } + }, + { + "name": "terminal_state_must_be_terminal", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "completed work is terminal", + "document": { + "schema": "code_mower.operatorWorkItem.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "generation": 4, + "state": "completed", + "terminal": false, + "last_transition": "awaiting_review:completed", + "reason": "work_completed", + "owner_escalation_count": 0, + "created_at": 2000000000, + "updated_at": 2000001000, + "owner_escalation_key": null, + "elapsed_seconds": 1000, + "spend_usd": "0.00" + } + }, + { + "name": "invalid_lifecycle_transition", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "terminal work cannot transition back to execution", + "document": { + "schema": "code_mower.operatorWorkItem.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "generation": 5, + "state": "executing", + "terminal": false, + "last_transition": "completed:executing", + "reason": "none", + "owner_escalation_count": 0, + "created_at": 2000000000, + "updated_at": 2000001001, + "owner_escalation_key": null, + "elapsed_seconds": 1001, + "spend_usd": "0.00" + } + }, + { + "name": "lease_requires_fence_token", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "every acquired lease carries a fencing token", + "document": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 8, + "state": "active", + "acquired_at": 2000000000, + "renew_by": 2000000030, + "expires_at": 2000000090 + } + }, + { + "name": "uncertain_result_cannot_retry", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "unknown certainty requires reconciliation before retry", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "uncertain", + "certainty": "unknown", + "reconciliation": "required", + "next_action": "retry", + "remote_reference": null, + "budget": { + "attempt_count": 1, + "reconciliation_count": 0, + "elapsed_seconds": 300, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000300, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + }, + { + "name": "stale_head_cannot_dispatch", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "stale head abandons the intent", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_push", + "operation": "push_commit", + "idempotency_key": "2222222222222222222222222222222222222222222222222222222222222222", + "request_digest": "3333333333333333333333333333333333333333333333333333333333333333", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "stale", + "state": "prepared", + "certainty": "not_attempted", + "reconciliation": "not_required", + "next_action": "dispatch", + "remote_reference": null, + "budget": { + "attempt_count": 0, + "reconciliation_count": 0, + "elapsed_seconds": 0, + "spend_usd": "0.00" + }, + "created_at": 2000000000, + "updated_at": 2000000000, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + }, + { + "name": "attempt_budget_is_bounded", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "action attempts cannot exceed the contract ceiling", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_retry", + "operation": "message_provider_session", + "idempotency_key": "5555555555555555555555555555555555555555555555555555555555555555", + "request_digest": "6666666666666666666666666666666666666666666666666666666666666666", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "failed", + "certainty": "confirmed_failure", + "reconciliation": "not_required", + "next_action": "retry", + "remote_reference": "session_example", + "budget": { + "attempt_count": 6, + "reconciliation_count": 0, + "elapsed_seconds": 400, + "spend_usd": "0.20" + }, + "created_at": 2000000000, + "updated_at": 2000000400, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + }, + { + "name": "projection_rejects_private_content", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "closed metadata projection rejects issue bodies and all other content", + "document": { + "schema": "code_mower.operatorProjection.v1", + "event_type": "work_state", + "observed_at": 2000000340, + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": null, + "provider_id": null, + "role": null, + "state": "awaiting_owner", + "reason": "user_input_required", + "attempt_count": 0, + "elapsed_seconds": 340, + "spend_usd": "0.00", + "issue_body": "private fixture content" + } + }, + { + "name": "pending_qualification_cannot_claim_current_evidence", + "contract_schema": "operator_policy_v1.schema.json", + "expected_violation": "pending status requires missing evidence and a matching denied reason", + "semantic_context": { + "now": 2000000100 + }, + "document": { + "schema": "code_mower.operatorQualification.v1", + "provider_id": "devin", + "transport_id": "devin_service", + "role": "builder", + "required_capabilities": [ + "create_session", + "write_branch", + "open_pull_request", + "structured_result" + ], + "declared_capabilities": [ + "create_session", + "write_branch", + "open_pull_request", + "structured_result" + ], + "evidence": { + "capability_declaration_digest": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "harness_digest": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "source_head": "1111111111111111111111111111111111111111", + "observed_at": 2000000000, + "expires_at": 2000604800 + }, + "status": "pending", + "decision": "denied", + "reason": "evidence_current" + } + }, + { + "name": "failed_qualification_cannot_claim_current_reason", + "contract_schema": "operator_policy_v1.schema.json", + "expected_violation": "failed status requires evidence_failed or capability_missing", + "semantic_context": { + "now": 2000000100 + }, + "document": { + "schema": "code_mower.operatorQualification.v1", + "provider_id": "devin", + "transport_id": "devin_service", + "role": "builder", + "required_capabilities": [ + "create_session", + "write_branch", + "open_pull_request", + "structured_result" + ], + "declared_capabilities": [ + "create_session", + "write_branch", + "open_pull_request", + "structured_result" + ], + "evidence": { + "capability_declaration_digest": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "harness_digest": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "source_head": "1111111111111111111111111111111111111111", + "observed_at": 2000000000, + "expires_at": 2000604800 + }, + "status": "failed", + "decision": "denied", + "reason": "evidence_current" + } + }, + { + "name": "qualification_expiry_must_follow_observation", + "contract_schema": "operator_policy_v1.schema.json", + "expected_violation": "observed_at must be strictly before expires_at", + "semantic_context": { + "now": 2000000100 + }, + "document": { + "schema": "code_mower.operatorQualification.v1", + "provider_id": "codex", + "transport_id": "codex_service", + "role": "orchestrator", + "required_capabilities": [ + "observe_repository", + "select_work", + "create_session", + "structured_result", + "reconcile_remote_mutation" + ], + "declared_capabilities": [ + "observe_repository", + "select_work", + "create_session", + "structured_result", + "reconcile_remote_mutation" + ], + "evidence": { + "capability_declaration_digest": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "harness_digest": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "source_head": "1111111111111111111111111111111111111111", + "observed_at": 2000000000, + "expires_at": 2000000000 + }, + "status": "qualified", + "decision": "allowed", + "reason": "evidence_current" + } + }, + { + "name": "expired_qualification_cannot_remain_allowed", + "contract_schema": "operator_policy_v1.schema.json", + "expected_violation": "qualified evidence must be unexpired at the normative observation time", + "semantic_context": { + "now": 2000604800 + }, + "document": { + "schema": "code_mower.operatorQualification.v1", + "provider_id": "codex", + "transport_id": "codex_service", + "role": "orchestrator", + "required_capabilities": [ + "observe_repository", + "select_work", + "create_session", + "structured_result", + "reconcile_remote_mutation" + ], + "declared_capabilities": [ + "observe_repository", + "select_work", + "create_session", + "structured_result", + "reconcile_remote_mutation" + ], + "evidence": { + "capability_declaration_digest": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "harness_digest": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "source_head": "1111111111111111111111111111111111111111", + "observed_at": 2000000000, + "expires_at": 2000604800 + }, + "status": "qualified", + "decision": "allowed", + "reason": "evidence_current" + } + }, + { + "name": "overage_qualification_cannot_remain_allowed", + "contract_schema": "operator_policy_v1.schema.json", + "expected_violation": "evidence age cannot exceed the policy maximum", + "semantic_context": { + "now": 2000604801 + }, + "document": { + "schema": "code_mower.operatorQualification.v1", + "provider_id": "codex", + "transport_id": "codex_service", + "role": "orchestrator", + "required_capabilities": [ + "observe_repository", + "select_work", + "create_session", + "structured_result", + "reconcile_remote_mutation" + ], + "declared_capabilities": [ + "observe_repository", + "select_work", + "create_session", + "structured_result", + "reconcile_remote_mutation" + ], + "evidence": { + "capability_declaration_digest": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "harness_digest": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "source_head": "1111111111111111111111111111111111111111", + "observed_at": 2000000000, + "expires_at": 2001000000 + }, + "status": "qualified", + "decision": "allowed", + "reason": "evidence_current" + } + }, + { + "name": "stale_work_generation_cannot_dispatch", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "intent generation must match the current durable work generation", + "semantic_context": { + "current_work_generation": 4, + "now": 2000000000, + "current_head_sha": "3333333333333333333333333333333333333333", + "current_lease": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "state": "active", + "acquired_at": 2000000000, + "renew_by": 2000000030, + "expires_at": 2000000090 + } + }, + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "prepared", + "certainty": "not_attempted", + "reconciliation": "not_required", + "next_action": "dispatch", + "remote_reference": null, + "budget": { + "attempt_count": 0, + "reconciliation_count": 0, + "elapsed_seconds": 0, + "spend_usd": "0.00" + }, + "created_at": 2000000000, + "updated_at": 2000000000, + "work_generation": 3, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + }, + { + "name": "current_evidence_cannot_be_marked_stale", + "contract_schema": "operator_policy_v1.schema.json", + "expected_violation": "stale status requires evidence that is expired or older than policy permits", + "semantic_context": { + "now": 2000000100 + }, + "document": { + "schema": "code_mower.operatorQualification.v1", + "provider_id": "codex", + "transport_id": "codex_service", + "role": "orchestrator", + "required_capabilities": [ + "observe_repository", + "select_work", + "create_session", + "structured_result", + "reconcile_remote_mutation" + ], + "declared_capabilities": [ + "observe_repository", + "select_work", + "create_session", + "structured_result", + "reconcile_remote_mutation" + ], + "evidence": { + "capability_declaration_digest": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "harness_digest": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "source_head": "1111111111111111111111111111111111111111", + "observed_at": 2000000000, + "expires_at": 2000604800 + }, + "status": "stale", + "decision": "denied", + "reason": "evidence_stale" + } + }, + { + "name": "failed_evidence_must_retain_record", + "contract_schema": "operator_policy_v1.schema.json", + "expected_violation": "evidence_failed status requires the failed evidence record", + "semantic_context": { + "now": 2000000100 + }, + "document": { + "schema": "code_mower.operatorQualification.v1", + "provider_id": "devin", + "transport_id": "devin_service", + "role": "builder", + "required_capabilities": [ + "create_session", + "write_branch", + "open_pull_request", + "structured_result" + ], + "declared_capabilities": [ + "create_session", + "write_branch", + "open_pull_request", + "structured_result" + ], + "evidence": null, + "status": "failed", + "decision": "denied", + "reason": "evidence_failed" + } + }, + { + "name": "capability_missing_requires_an_actual_gap", + "contract_schema": "operator_policy_v1.schema.json", + "expected_violation": "capability_missing status requires a required capability absent from the declaration", + "semantic_context": { + "now": 2000000100 + }, + "document": { + "schema": "code_mower.operatorQualification.v1", + "provider_id": "devin", + "transport_id": "devin_service", + "role": "builder", + "required_capabilities": [ + "create_session", + "write_branch", + "open_pull_request", + "structured_result" + ], + "declared_capabilities": [ + "create_session", + "write_branch", + "open_pull_request", + "structured_result" + ], + "evidence": null, + "status": "failed", + "decision": "denied", + "reason": "capability_missing" + } + }, + { + "name": "prepared_dispatch_rejects_stale_current_fence", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "prepared dispatch must match the independently read current lease fence", + "semantic_context": { + "current_work_generation": 4, + "now": 2000000000, + "current_head_sha": "3333333333333333333333333333333333333333", + "current_lease": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "state": "active", + "acquired_at": 2000000000, + "renew_by": 2000000030, + "expires_at": 2000000090 + } + }, + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "prepared", + "certainty": "not_attempted", + "reconciliation": "not_required", + "next_action": "dispatch", + "remote_reference": null, + "budget": { + "attempt_count": 0, + "reconciliation_count": 0, + "elapsed_seconds": 0, + "spend_usd": "0.00" + }, + "created_at": 2000000000, + "updated_at": 2000000000, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + }, + { + "name": "retry_rejects_stale_current_head", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "retry must match the independently read current target head", + "semantic_context": { + "current_work_generation": 4, + "now": 2000000280, + "current_head_sha": "4444444444444444444444444444444444444444", + "current_lease": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "state": "active", + "acquired_at": 2000000000, + "renew_by": 2000000310, + "expires_at": 2000000370 + } + }, + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "failed", + "certainty": "confirmed_failure", + "reconciliation": "matched_failure", + "next_action": "retry", + "remote_reference": "pull_request_401", + "budget": { + "attempt_count": 1, + "reconciliation_count": 1, + "elapsed_seconds": 280, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000280, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + }, + { + "name": "dispatch_rejects_expired_lease", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "dispatch requires an active lease before renew_by and expires_at", + "semantic_context": { + "current_work_generation": 4, + "now": 2000000100, + "current_head_sha": "3333333333333333333333333333333333333333", + "current_lease": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "state": "expired", + "acquired_at": 2000000000, + "renew_by": 2000000030, + "expires_at": 2000000090 + } + }, + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "prepared", + "certainty": "not_attempted", + "reconciliation": "not_required", + "next_action": "dispatch", + "remote_reference": null, + "budget": { + "attempt_count": 0, + "reconciliation_count": 0, + "elapsed_seconds": 0, + "spend_usd": "0.00" + }, + "created_at": 2000000000, + "updated_at": 2000000000, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + }, + { + "name": "dispatch_rejects_wrong_scope_lease", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "current lease tenant and repository must match the intent", + "semantic_context": { + "current_work_generation": 4, + "now": 2000000000, + "current_head_sha": "3333333333333333333333333333333333333333", + "current_lease": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_other", + "repository_id": "repository_other", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "state": "active", + "acquired_at": 2000000000, + "renew_by": 2000000030, + "expires_at": 2000000090 + } + }, + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "prepared", + "certainty": "not_attempted", + "reconciliation": "not_required", + "next_action": "dispatch", + "remote_reference": null, + "budget": { + "attempt_count": 0, + "reconciliation_count": 0, + "elapsed_seconds": 0, + "spend_usd": "0.00" + }, + "created_at": 2000000000, + "updated_at": 2000000000, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + }, + { + "name": "result_commit_rejects_stale_authority", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "result commit requires current lease fence and exact target head", + "semantic_context": { + "current_work_generation": 4, + "now": 2000000280, + "current_head_sha": "4444444444444444444444444444444444444444", + "current_lease": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "state": "active", + "acquired_at": 2000000000, + "renew_by": 2000000310, + "expires_at": 2000000370 + } + }, + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "succeeded", + "certainty": "confirmed_success", + "reconciliation": "matched_success", + "next_action": "none", + "remote_reference": "pull_request_401", + "budget": { + "attempt_count": 1, + "reconciliation_count": 1, + "elapsed_seconds": 280, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000280, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + }, + { + "name": "reconciliation_rejects_unbound_current_lease", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "reconciliation authority must match the independently read current lease", + "semantic_context": { + "current_work_generation": 4, + "now": 2000000250, + "current_head_sha": "3333333333333333333333333333333333333333", + "current_lease": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 10, + "fence_token": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "state": "active", + "acquired_at": 2000000000, + "renew_by": 2000000280, + "expires_at": 2000000340 + } + }, + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "stale", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "reconciling", + "certainty": "unknown", + "reconciliation": "in_progress", + "next_action": "reconcile", + "remote_reference": null, + "budget": { + "attempt_count": 1, + "reconciliation_count": 0, + "elapsed_seconds": 250, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000250, + "work_generation": 4, + "reconciliation_authority": { + "lease_epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "fence_status": "current" + }, + "lease_id": "operator_singleton" + } + }, + { + "name": "policy_rejects_repository_outside_allowlist", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "record repository must be admitted by owner policy", + "semantic_context": { + "current_work_generation": 4, + "now": 2000000000, + "current_head_sha": "3333333333333333333333333333333333333333", + "current_lease": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_other", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "state": "active", + "acquired_at": 2000000000, + "renew_by": 2000000030, + "expires_at": 2000000090 + } + }, + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_other", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "prepared", + "certainty": "not_attempted", + "reconciliation": "not_required", + "next_action": "dispatch", + "remote_reference": null, + "budget": { + "attempt_count": 0, + "reconciliation_count": 0, + "elapsed_seconds": 0, + "spend_usd": "0.00" + }, + "created_at": 2000000000, + "updated_at": 2000000000, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + }, + { + "name": "policy_rejects_unauthorized_mutation", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "operation must be present in owner policy authority.mutations", + "semantic_context": { + "current_work_generation": 4, + "now": 2000000000, + "current_head_sha": "3333333333333333333333333333333333333333", + "current_lease": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "state": "active", + "acquired_at": 2000000000, + "renew_by": 2000000030, + "expires_at": 2000000090 + }, + "policy_remove_mutation": "push_commit" + }, + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "push_commit", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "prepared", + "certainty": "not_attempted", + "reconciliation": "not_required", + "next_action": "dispatch", + "remote_reference": null, + "budget": { + "attempt_count": 0, + "reconciliation_count": 0, + "elapsed_seconds": 0, + "spend_usd": "0.00" + }, + "created_at": 2000000000, + "updated_at": 2000000000, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + }, + { + "name": "policy_rejects_action_attempt_overage", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "attempt count exceeds the owner policy ceiling", + "semantic_context": { + "current_work_generation": 4, + "now": 2000000280, + "current_head_sha": "3333333333333333333333333333333333333333", + "current_lease": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "state": "active", + "acquired_at": 2000000000, + "renew_by": 2000000310, + "expires_at": 2000000370 + } + }, + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "failed", + "certainty": "confirmed_failure", + "reconciliation": "matched_failure", + "next_action": "retry", + "remote_reference": "pull_request_401", + "budget": { + "attempt_count": 4, + "reconciliation_count": 1, + "elapsed_seconds": 280, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000280, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + }, + { + "name": "policy_rejects_reconciliation_overage", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "reconciliation count exceeds the owner policy ceiling", + "semantic_context": { + "current_work_generation": 4, + "now": 2000000280, + "current_head_sha": "3333333333333333333333333333333333333333", + "current_lease": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "state": "active", + "acquired_at": 2000000000, + "renew_by": 2000000310, + "expires_at": 2000000370 + } + }, + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "failed", + "certainty": "confirmed_failure", + "reconciliation": "matched_failure", + "next_action": "retry", + "remote_reference": "pull_request_401", + "budget": { + "attempt_count": 1, + "reconciliation_count": 3, + "elapsed_seconds": 280, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000280, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + }, + { + "name": "policy_rejects_action_time_overage", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "action time exceeds the owner policy ceiling", + "semantic_context": { + "current_work_generation": 4, + "now": 2000000280, + "current_head_sha": "3333333333333333333333333333333333333333", + "current_lease": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "state": "active", + "acquired_at": 2000000000, + "renew_by": 2000000310, + "expires_at": 2000000370 + } + }, + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "failed", + "certainty": "confirmed_failure", + "reconciliation": "matched_failure", + "next_action": "retry", + "remote_reference": "pull_request_401", + "budget": { + "attempt_count": 1, + "reconciliation_count": 1, + "elapsed_seconds": 301, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000280, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + }, + { + "name": "policy_rejects_action_spend_overage", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "action spend exceeds the owner policy ceiling", + "semantic_context": { + "current_work_generation": 4, + "now": 2000000280, + "current_head_sha": "3333333333333333333333333333333333333333", + "current_lease": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "state": "active", + "acquired_at": 2000000000, + "renew_by": 2000000310, + "expires_at": 2000000370 + } + }, + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "failed", + "certainty": "confirmed_failure", + "reconciliation": "matched_failure", + "next_action": "retry", + "remote_reference": "pull_request_401", + "budget": { + "attempt_count": 1, + "reconciliation_count": 1, + "elapsed_seconds": 280, + "spend_usd": "25.01" + }, + "created_at": 2000000000, + "updated_at": 2000000280, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + }, + { + "name": "policy_rejects_owner_escalation_overage", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "owner escalation count exceeds the configured ceiling", + "semantic_context": {}, + "document": { + "schema": "code_mower.operatorWorkItem.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "generation": 4, + "state": "awaiting_owner", + "terminal": false, + "last_transition": "reconciling:awaiting_owner", + "reason": "budget_exhausted", + "owner_escalation_count": 3, + "created_at": 2000000000, + "updated_at": 2000000300, + "owner_escalation_key": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "elapsed_seconds": 300, + "spend_usd": "0.10" + } + }, + { + "name": "policy_rejects_work_time_overage", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "work elapsed time exceeds the configured ceiling", + "semantic_context": {}, + "document": { + "schema": "code_mower.operatorWorkItem.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "generation": 4, + "state": "awaiting_owner", + "terminal": false, + "last_transition": "reconciling:awaiting_owner", + "reason": "budget_exhausted", + "owner_escalation_count": 1, + "created_at": 2000000000, + "updated_at": 2000014401, + "owner_escalation_key": "9999999999999999999999999999999999999999999999999999999999999999", + "elapsed_seconds": 14401, + "spend_usd": "0.10" + } + }, + { + "name": "policy_rejects_lease_cadence_overage", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "lease deadlines must match configured TTL and renewal cadence", + "semantic_context": {}, + "document": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "state": "active", + "acquired_at": 2000000000, + "renew_by": 2000000030, + "expires_at": 2000000091 + } + }, + { + "name": "lease_rejects_reversed_chronology", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "lease chronology must be acquired_at <= renew_by < expires_at", + "semantic_context": {}, + "document": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "state": "active", + "acquired_at": 2000000000, + "renew_by": 2000000091, + "expires_at": 2000000090 + } + }, + { + "name": "policy_rejects_work_spend_overage", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "cumulative work spend exceeds the configured ceiling", + "semantic_context": {}, + "document": { + "schema": "code_mower.operatorWorkItem.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "generation": 4, + "state": "awaiting_owner", + "terminal": false, + "last_transition": "reconciling:awaiting_owner", + "reason": "budget_exhausted", + "owner_escalation_count": 1, + "created_at": 2000000000, + "updated_at": 2000000300, + "owner_escalation_key": "9999999999999999999999999999999999999999999999999999999999999999", + "elapsed_seconds": 300, + "spend_usd": "25.01" + } + }, + { + "name": "dispatch_rejects_wrong_lease_identity", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "current lease identity must match the immutable action lease identity", + "semantic_context": { + "current_work_generation": 4, + "now": 2000000000, + "current_head_sha": "3333333333333333333333333333333333333333", + "current_lease": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_other", + "holder_id": "operator_instance_2", + "epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "state": "active", + "acquired_at": 2000000000, + "renew_by": 2000000030, + "expires_at": 2000000090 + } + }, + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "prepared", + "certainty": "not_attempted", + "reconciliation": "not_required", + "next_action": "dispatch", + "remote_reference": null, + "budget": { + "attempt_count": 0, + "reconciliation_count": 0, + "elapsed_seconds": 0, + "spend_usd": "0.00" + }, + "created_at": 2000000000, + "updated_at": 2000000000, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + }, + { + "name": "policy_rejects_tenant_outside_scope", + "contract_schema": "operator_state_v1.schema.json", + "expected_violation": "record tenant must match the owner policy tenant", + "semantic_context": { + "current_work_generation": 4, + "now": 2000000000, + "current_head_sha": "3333333333333333333333333333333333333333", + "current_lease": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_other", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "state": "active", + "acquired_at": 2000000000, + "renew_by": 2000000030, + "expires_at": 2000000090 + } + }, + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_other", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "prepared", + "certainty": "not_attempted", + "reconciliation": "not_required", + "next_action": "dispatch", + "remote_reference": null, + "budget": { + "attempt_count": 0, + "reconciliation_count": 0, + "elapsed_seconds": 0, + "spend_usd": "0.00" + }, + "created_at": 2000000000, + "updated_at": 2000000000, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + }, + { + "name": "original_holder_retry_rejects_takeover_lease", + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "failed", + "certainty": "confirmed_failure", + "reconciliation": "matched_failure", + "next_action": "retry", + "remote_reference": "provider_attempt_1", + "budget": { + "attempt_count": 1, + "reconciliation_count": 1, + "elapsed_seconds": 10, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000010, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + }, + "semantic_context": { + "current_work_generation": 4, + "now": 2000000000, + "current_head_sha": "3333333333333333333333333333333333333333", + "current_lease": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "state": "active", + "acquired_at": 2000000000, + "renew_by": 2000000030, + "expires_at": 2000000090 + } + }, + "expected_violation": "original-holder retry must match the independently read current lease fence" + }, + { + "name": "takeover_retry_rejects_wrong_reconciliation_authority", + "contract_schema": "operator_state_v1.schema.json", + "semantic_context": { + "current_work_generation": 4, + "now": 2000000250, + "current_head_sha": "3333333333333333333333333333333333333333", + "current_lease": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "state": "active", + "acquired_at": 2000000250, + "renew_by": 2000000280, + "expires_at": 2000000340 + } + }, + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "stale", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "failed", + "certainty": "confirmed_failure", + "reconciliation": "matched_failure", + "next_action": "retry", + "remote_reference": "provider_attempt_1", + "budget": { + "attempt_count": 1, + "reconciliation_count": 1, + "elapsed_seconds": 250, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000250, + "work_generation": 4, + "reconciliation_authority": { + "lease_epoch": 10, + "fence_token": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "fence_status": "current" + }, + "lease_id": "operator_singleton" + }, + "expected_violation": "takeover retry authority must match the independently read current lease fence" + }, + { + "name": "policy_rejects_shifted_late_lease_deadlines", + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "state": "active", + "acquired_at": 2000000000, + "renew_by": 2000000080, + "expires_at": 2000000140 + }, + "semantic_context": {}, + "expected_violation": "lease deadlines are absolute offsets from acquired_at" + }, + { + "name": "policy_rejects_shifted_early_lease_deadlines", + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "state": "active", + "acquired_at": 2000000000, + "renew_by": 2000000020, + "expires_at": 2000000080 + }, + "semantic_context": {}, + "expected_violation": "lease deadlines are absolute offsets from acquired_at" + }, + { + "name": "terminal_completed_rejects_failure_reason", + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorWorkItem.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "generation": 4, + "state": "completed", + "terminal": true, + "last_transition": "awaiting_review:completed", + "reason": "work_failed", + "owner_escalation_count": 0, + "created_at": 2000000000, + "updated_at": 2000000300, + "owner_escalation_key": null, + "elapsed_seconds": 300, + "spend_usd": "0.10" + }, + "semantic_context": {}, + "expected_violation": "terminal work state and reason must agree" + }, + { + "name": "lease_projection_rejects_qualification_state_and_remote_reason", + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorProjection.v1", + "event_type": "lease_state", + "observed_at": 2000000340, + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": null, + "action_id": null, + "provider_id": null, + "role": null, + "state": "qualified", + "reason": "remote_success", + "attempt_count": 1, + "elapsed_seconds": 340, + "spend_usd": "0.10" + }, + "semantic_context": {}, + "expected_violation": "projection event, identifiers, state, and reason must agree" + } + ], + "failure_scenarios": [ + { + "name": "restart_after_dispatch", + "before": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "uncertain", + "certainty": "unknown", + "reconciliation": "required", + "next_action": "reconcile", + "remote_reference": null, + "budget": { + "attempt_count": 1, + "reconciliation_count": 1, + "elapsed_seconds": 300, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000300, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ], + "after": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "reconciling", + "certainty": "unknown", + "reconciliation": "in_progress", + "next_action": "reconcile", + "remote_reference": null, + "budget": { + "attempt_count": 1, + "reconciliation_count": 1, + "elapsed_seconds": 300, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000301, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ], + "forbidden_afters": [ + { + "name": "original_forbidden_shortcut", + "records": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "reconciling", + "certainty": "unknown", + "reconciliation": "in_progress", + "next_action": "reconcile", + "remote_reference": null, + "budget": { + "attempt_count": 2, + "reconciliation_count": 0, + "elapsed_seconds": 300, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000301, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ] + }, + { + "name": "reconciliation_count_rollback", + "records": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "reconciling", + "certainty": "unknown", + "reconciliation": "in_progress", + "next_action": "reconcile", + "remote_reference": null, + "budget": { + "attempt_count": 1, + "reconciliation_count": 0, + "elapsed_seconds": 300, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000301, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ] + }, + { + "name": "elapsed_seconds_rollback", + "records": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "reconciling", + "certainty": "unknown", + "reconciliation": "in_progress", + "next_action": "reconcile", + "remote_reference": null, + "budget": { + "attempt_count": 1, + "reconciliation_count": 1, + "elapsed_seconds": 1, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000301, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ] + }, + { + "name": "spend_rollback", + "records": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "reconciling", + "certainty": "unknown", + "reconciliation": "in_progress", + "next_action": "reconcile", + "remote_reference": null, + "budget": { + "attempt_count": 1, + "reconciliation_count": 1, + "elapsed_seconds": 300, + "spend_usd": "0.00" + }, + "created_at": 2000000000, + "updated_at": 2000000301, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ] + }, + { + "name": "updated_at_rollback", + "records": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "reconciling", + "certainty": "unknown", + "reconciliation": "in_progress", + "next_action": "reconcile", + "remote_reference": null, + "budget": { + "attempt_count": 1, + "reconciliation_count": 1, + "elapsed_seconds": 300, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000001, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ] + } + ] + }, + { + "name": "duplicate_delivery", + "before": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "succeeded", + "certainty": "confirmed_success", + "reconciliation": "matched_success", + "next_action": "none", + "remote_reference": "pull_request_401", + "budget": { + "attempt_count": 1, + "reconciliation_count": 1, + "elapsed_seconds": 300, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000340, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ], + "after": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "succeeded", + "certainty": "confirmed_success", + "reconciliation": "matched_success", + "next_action": "none", + "remote_reference": "pull_request_401", + "budget": { + "attempt_count": 1, + "reconciliation_count": 1, + "elapsed_seconds": 300, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000340, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ], + "forbidden_afters": [ + { + "name": "original_forbidden_shortcut", + "records": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "succeeded", + "certainty": "confirmed_success", + "reconciliation": "matched_success", + "next_action": "none", + "remote_reference": "pull_request_401", + "budget": { + "attempt_count": 2, + "reconciliation_count": 1, + "elapsed_seconds": 300, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000341, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ] + } + ] + }, + { + "name": "lease_takeover", + "before": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_1", + "epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "state": "active", + "acquired_at": 2000000000, + "renew_by": 2000000030, + "expires_at": 2000000090 + } + }, + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "uncertain", + "certainty": "unknown", + "reconciliation": "required", + "next_action": "reconcile", + "remote_reference": null, + "budget": { + "attempt_count": 1, + "reconciliation_count": 1, + "elapsed_seconds": 240, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000240, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ], + "after": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "state": "active", + "acquired_at": 2000000100, + "renew_by": 2000000130, + "expires_at": 2000000190 + } + }, + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "stale", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "reconciling", + "certainty": "unknown", + "reconciliation": "in_progress", + "next_action": "reconcile", + "remote_reference": null, + "budget": { + "attempt_count": 1, + "reconciliation_count": 1, + "elapsed_seconds": 250, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000250, + "work_generation": 4, + "reconciliation_authority": { + "lease_epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "fence_status": "current" + }, + "lease_id": "operator_singleton" + } + } + ], + "forbidden_afters": [ + { + "name": "original_forbidden_shortcut", + "records": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "state": "active", + "acquired_at": 2000000100, + "renew_by": 2000000130, + "expires_at": 2000000190 + } + }, + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "stale", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "reconciling", + "certainty": "unknown", + "reconciliation": "in_progress", + "next_action": "reconcile", + "remote_reference": null, + "budget": { + "attempt_count": 2, + "reconciliation_count": 0, + "elapsed_seconds": 300, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000310, + "work_generation": 4, + "reconciliation_authority": { + "lease_epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "fence_status": "current" + }, + "lease_id": "operator_singleton" + } + } + ] + }, + { + "name": "cross_tenant", + "records": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_other", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "state": "active", + "acquired_at": 2000000100, + "renew_by": 2000000280, + "expires_at": 2000000340 + } + }, + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "stale", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "reconciling", + "certainty": "unknown", + "reconciliation": "in_progress", + "next_action": "reconcile", + "remote_reference": null, + "budget": { + "attempt_count": 1, + "reconciliation_count": 0, + "elapsed_seconds": 250, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000250, + "work_generation": 4, + "reconciliation_authority": { + "lease_epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "fence_status": "current" + }, + "lease_id": "operator_singleton" + } + } + ] + }, + { + "name": "cross_repository", + "records": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_other", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "state": "active", + "acquired_at": 2000000100, + "renew_by": 2000000280, + "expires_at": 2000000340 + } + }, + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "stale", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "reconciling", + "certainty": "unknown", + "reconciliation": "in_progress", + "next_action": "reconcile", + "remote_reference": null, + "budget": { + "attempt_count": 1, + "reconciliation_count": 0, + "elapsed_seconds": 250, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000250, + "work_generation": 4, + "reconciliation_authority": { + "lease_epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "fence_status": "current" + }, + "lease_id": "operator_singleton" + } + } + ] + }, + { + "name": "cross_operator_lease", + "records": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "another_operator", + "holder_id": "operator_instance_2", + "epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "state": "active", + "acquired_at": 2000000100, + "renew_by": 2000000280, + "expires_at": 2000000340 + } + }, + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "stale", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "reconciling", + "certainty": "unknown", + "reconciliation": "in_progress", + "next_action": "reconcile", + "remote_reference": null, + "budget": { + "attempt_count": 1, + "reconciliation_count": 0, + "elapsed_seconds": 250, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000250, + "work_generation": 4, + "reconciliation_authority": { + "lease_epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "fence_status": "current" + }, + "lease_id": "operator_singleton" + } + } + ] + }, + { + "name": "same_holder_identity", + "records": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_1", + "epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "state": "active", + "acquired_at": 2000000100, + "renew_by": 2000000280, + "expires_at": 2000000340 + } + }, + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "stale", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "reconciling", + "certainty": "unknown", + "reconciliation": "in_progress", + "next_action": "reconcile", + "remote_reference": null, + "budget": { + "attempt_count": 1, + "reconciliation_count": 0, + "elapsed_seconds": 250, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000250, + "work_generation": 4, + "reconciliation_authority": { + "lease_epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "fence_status": "current" + }, + "lease_id": "operator_singleton" + } + } + ] + }, + { + "name": "reversed_lease_chronology", + "records": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "state": "active", + "acquired_at": 2000000100, + "renew_by": 2000000341, + "expires_at": 2000000340 + } + }, + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "stale", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "reconciling", + "certainty": "unknown", + "reconciliation": "in_progress", + "next_action": "reconcile", + "remote_reference": null, + "budget": { + "attempt_count": 1, + "reconciliation_count": 0, + "elapsed_seconds": 250, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000250, + "work_generation": 4, + "reconciliation_authority": { + "lease_epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "fence_status": "current" + }, + "lease_id": "operator_singleton" + } + } + ] + }, + { + "name": "elapsed_seconds_rollback", + "records": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "state": "active", + "acquired_at": 2000000100, + "renew_by": 2000000280, + "expires_at": 2000000340 + } + }, + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "stale", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "reconciling", + "certainty": "unknown", + "reconciliation": "in_progress", + "next_action": "reconcile", + "remote_reference": null, + "budget": { + "attempt_count": 1, + "reconciliation_count": 0, + "elapsed_seconds": 1, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000250, + "work_generation": 4, + "reconciliation_authority": { + "lease_epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "fence_status": "current" + }, + "lease_id": "operator_singleton" + } + } + ] + }, + { + "name": "spend_rollback", + "records": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "state": "active", + "acquired_at": 2000000100, + "renew_by": 2000000280, + "expires_at": 2000000340 + } + }, + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "stale", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "reconciling", + "certainty": "unknown", + "reconciliation": "in_progress", + "next_action": "reconcile", + "remote_reference": null, + "budget": { + "attempt_count": 1, + "reconciliation_count": 0, + "elapsed_seconds": 250, + "spend_usd": "0.00" + }, + "created_at": 2000000000, + "updated_at": 2000000250, + "work_generation": 4, + "reconciliation_authority": { + "lease_epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "fence_status": "current" + }, + "lease_id": "operator_singleton" + } + } + ] + }, + { + "name": "reconciliation_count_rollback", + "records": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorLease.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "lease_id": "operator_singleton", + "holder_id": "operator_instance_2", + "epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "state": "active", + "acquired_at": 2000000100, + "renew_by": 2000000280, + "expires_at": 2000000340 + } + }, + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "stale", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "reconciling", + "certainty": "unknown", + "reconciliation": "in_progress", + "next_action": "reconcile", + "remote_reference": null, + "budget": { + "attempt_count": 1, + "reconciliation_count": 0, + "elapsed_seconds": 250, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000250, + "work_generation": 4, + "reconciliation_authority": { + "lease_epoch": 9, + "fence_token": "9999999999999999999999999999999999999999999999999999999999999999", + "fence_status": "current" + }, + "lease_id": "operator_singleton" + } + } + ] + } + ] + }, + { + "name": "stale_head", + "before": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "prepared", + "certainty": "not_attempted", + "reconciliation": "not_required", + "next_action": "dispatch", + "remote_reference": null, + "budget": { + "attempt_count": 0, + "reconciliation_count": 0, + "elapsed_seconds": 0, + "spend_usd": "0.00" + }, + "created_at": 2000000000, + "updated_at": 2000000000, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ], + "after": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "stale", + "state": "abandoned", + "certainty": "not_applicable", + "reconciliation": "not_required", + "next_action": "abandon", + "remote_reference": null, + "budget": { + "attempt_count": 0, + "reconciliation_count": 0, + "elapsed_seconds": 0, + "spend_usd": "0.00" + }, + "created_at": 2000000000, + "updated_at": 2000000001, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ], + "forbidden_afters": [ + { + "name": "original_forbidden_shortcut", + "records": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "4444444444444444444444444444444444444444", + "head_status": "current", + "state": "prepared", + "certainty": "not_attempted", + "reconciliation": "not_required", + "next_action": "dispatch", + "remote_reference": null, + "budget": { + "attempt_count": 0, + "reconciliation_count": 0, + "elapsed_seconds": 0, + "spend_usd": "0.00" + }, + "created_at": 2000000000, + "updated_at": 2000000001, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ] + } + ] + }, + { + "name": "provider_timeout", + "before": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "prepared", + "certainty": "not_attempted", + "reconciliation": "not_required", + "next_action": "dispatch", + "remote_reference": null, + "budget": { + "attempt_count": 0, + "reconciliation_count": 0, + "elapsed_seconds": 0, + "spend_usd": "0.00" + }, + "created_at": 2000000000, + "updated_at": 2000000000, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ], + "after": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "uncertain", + "certainty": "unknown", + "reconciliation": "required", + "next_action": "reconcile", + "remote_reference": null, + "budget": { + "attempt_count": 1, + "reconciliation_count": 0, + "elapsed_seconds": 300, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000300, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ], + "forbidden_afters": [ + { + "name": "original_forbidden_shortcut", + "records": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "failed", + "certainty": "confirmed_failure", + "reconciliation": "not_required", + "next_action": "retry", + "remote_reference": null, + "budget": { + "attempt_count": 1, + "reconciliation_count": 0, + "elapsed_seconds": 300, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000300, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ] + } + ] + }, + { + "name": "partial_success", + "before": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "uncertain", + "certainty": "unknown", + "reconciliation": "required", + "next_action": "reconcile", + "remote_reference": "session_partial", + "budget": { + "attempt_count": 1, + "reconciliation_count": 0, + "elapsed_seconds": 300, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000300, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ], + "after": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "reconciling", + "certainty": "unknown", + "reconciliation": "in_progress", + "next_action": "reconcile", + "remote_reference": "session_partial", + "budget": { + "attempt_count": 1, + "reconciliation_count": 0, + "elapsed_seconds": 300, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000310, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ], + "forbidden_afters": [ + { + "name": "original_forbidden_shortcut", + "records": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "reconciling", + "certainty": "unknown", + "reconciliation": "in_progress", + "next_action": "reconcile", + "remote_reference": "session_partial", + "budget": { + "attempt_count": 2, + "reconciliation_count": 0, + "elapsed_seconds": 300, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000310, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ] + } + ] + }, + { + "name": "budget_exhaustion", + "before": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorWorkItem.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "generation": 4, + "state": "reconciling", + "terminal": false, + "last_transition": "executing:reconciling", + "reason": "none", + "owner_escalation_count": 0, + "owner_escalation_key": null, + "created_at": 2000000000, + "updated_at": 2000000300, + "elapsed_seconds": 300, + "spend_usd": "0.10" + } + } + ], + "after": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorWorkItem.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "generation": 4, + "state": "awaiting_owner", + "terminal": false, + "last_transition": "reconciling:awaiting_owner", + "reason": "budget_exhausted", + "owner_escalation_count": 1, + "owner_escalation_key": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "created_at": 2000000000, + "updated_at": 2000000310, + "elapsed_seconds": 310, + "spend_usd": "0.10" + } + } + ], + "forbidden_afters": [ + { + "name": "original_forbidden_shortcut", + "records": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorWorkItem.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "generation": 4, + "state": "reconciling", + "terminal": false, + "last_transition": "executing:reconciling", + "reason": "none", + "owner_escalation_count": 0, + "owner_escalation_key": null, + "created_at": 2000000000, + "updated_at": 2000000310, + "elapsed_seconds": 310, + "spend_usd": "0.00" + } + } + ] + }, + { + "name": "work_elapsed_seconds_rollback", + "records": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorWorkItem.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "generation": 4, + "state": "awaiting_owner", + "terminal": false, + "last_transition": "reconciling:awaiting_owner", + "reason": "budget_exhausted", + "owner_escalation_count": 1, + "owner_escalation_key": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "created_at": 2000000000, + "updated_at": 2000000310, + "elapsed_seconds": 1, + "spend_usd": "0.10" + } + } + ] + }, + { + "name": "work_spend_rollback", + "records": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorWorkItem.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "generation": 4, + "state": "awaiting_owner", + "terminal": false, + "last_transition": "reconciling:awaiting_owner", + "reason": "budget_exhausted", + "owner_escalation_count": 1, + "owner_escalation_key": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "created_at": 2000000000, + "updated_at": 2000000310, + "elapsed_seconds": 310, + "spend_usd": "0.00" + } + } + ] + } + ] + }, + { + "name": "owner_escalation_redelivery", + "before": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorWorkItem.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "generation": 4, + "state": "awaiting_owner", + "terminal": false, + "last_transition": "reconciling:awaiting_owner", + "reason": "budget_exhausted", + "owner_escalation_count": 1, + "owner_escalation_key": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "created_at": 2000000000, + "updated_at": 2000000310, + "elapsed_seconds": 310, + "spend_usd": "0.00" + } + } + ], + "after": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorWorkItem.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "generation": 4, + "state": "awaiting_owner", + "terminal": false, + "last_transition": "reconciling:awaiting_owner", + "reason": "budget_exhausted", + "owner_escalation_count": 1, + "owner_escalation_key": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "created_at": 2000000000, + "updated_at": 2000000310, + "elapsed_seconds": 310, + "spend_usd": "0.00" + } + } + ], + "forbidden_afters": [ + { + "name": "original_forbidden_shortcut", + "records": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorWorkItem.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "generation": 4, + "state": "awaiting_owner", + "terminal": false, + "last_transition": "reconciling:awaiting_owner", + "reason": "budget_exhausted", + "owner_escalation_count": 2, + "owner_escalation_key": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "created_at": 2000000000, + "updated_at": 2000000311, + "elapsed_seconds": 311, + "spend_usd": "0.00" + } + } + ] + } + ] + }, + { + "name": "owner_stop", + "before": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorWorkItem.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "generation": 4, + "state": "executing", + "terminal": false, + "last_transition": "claimed:executing", + "reason": "none", + "owner_escalation_count": 0, + "owner_escalation_key": null, + "created_at": 2000000000, + "updated_at": 2000000200, + "elapsed_seconds": 200, + "spend_usd": "0.00" + } + }, + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "prepared", + "certainty": "not_attempted", + "reconciliation": "not_required", + "next_action": "dispatch", + "remote_reference": null, + "budget": { + "attempt_count": 0, + "reconciliation_count": 0, + "elapsed_seconds": 0, + "spend_usd": "0.00" + }, + "created_at": 2000000000, + "updated_at": 2000000200, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ], + "after": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorWorkItem.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "generation": 4, + "state": "cancelled", + "terminal": true, + "last_transition": "executing:cancelled", + "reason": "owner_cancelled", + "owner_escalation_count": 0, + "owner_escalation_key": null, + "created_at": 2000000000, + "updated_at": 2000000210, + "elapsed_seconds": 210, + "spend_usd": "0.00" + } + }, + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "abandoned", + "certainty": "not_applicable", + "reconciliation": "not_required", + "next_action": "abandon", + "remote_reference": null, + "budget": { + "attempt_count": 0, + "reconciliation_count": 0, + "elapsed_seconds": 0, + "spend_usd": "0.00" + }, + "created_at": 2000000000, + "updated_at": 2000000210, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ], + "forbidden_afters": [ + { + "name": "original_forbidden_shortcut", + "records": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorWorkItem.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "generation": 4, + "state": "cancelled", + "terminal": true, + "last_transition": "executing:cancelled", + "reason": "owner_cancelled", + "owner_escalation_count": 0, + "owner_escalation_key": null, + "created_at": 2000000000, + "updated_at": 2000000210, + "elapsed_seconds": 210, + "spend_usd": "0.00" + } + }, + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "uncertain", + "certainty": "unknown", + "reconciliation": "required", + "next_action": "reconcile", + "remote_reference": null, + "budget": { + "attempt_count": 1, + "reconciliation_count": 0, + "elapsed_seconds": 300, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000210, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ] + } + ] + } + ], + "rejected_transitions": [ + { + "name": "provider_timeout_cannot_erase_confirmed_failure", + "event": "provider_timeout", + "expected_violation": "provider timeout requires a prepared not-attempted source", + "before": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "failed", + "certainty": "confirmed_failure", + "reconciliation": "matched_failure", + "next_action": "retry", + "remote_reference": null, + "budget": { + "attempt_count": 0, + "reconciliation_count": 0, + "elapsed_seconds": 0, + "spend_usd": "0.00" + }, + "created_at": 2000000000, + "updated_at": 2000000000, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ], + "after": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "uncertain", + "certainty": "unknown", + "reconciliation": "required", + "next_action": "reconcile", + "remote_reference": null, + "budget": { + "attempt_count": 1, + "reconciliation_count": 0, + "elapsed_seconds": 300, + "spend_usd": "0.10" + }, + "created_at": 2000000000, + "updated_at": 2000000300, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ] + }, + { + "name": "stale_head_cannot_abandon_confirmed_success", + "event": "stale_head", + "expected_violation": "stale-head abandonment requires a prepared not-attempted source", + "before": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "current", + "state": "succeeded", + "certainty": "confirmed_success", + "reconciliation": "matched_success", + "next_action": "none", + "remote_reference": "pull_request_401", + "budget": { + "attempt_count": 0, + "reconciliation_count": 0, + "elapsed_seconds": 0, + "spend_usd": "0.00" + }, + "created_at": 2000000000, + "updated_at": 2000000000, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ], + "after": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorActionIntent.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "action_id": "action_open_pr", + "operation": "open_or_update_pull_request", + "idempotency_key": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "request_digest": "1111111111111111111111111111111111111111111111111111111111111111", + "lease_epoch": 8, + "fence_token": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "fence_status": "current", + "target_head_sha": "3333333333333333333333333333333333333333", + "head_status": "stale", + "state": "abandoned", + "certainty": "not_applicable", + "reconciliation": "not_required", + "next_action": "abandon", + "remote_reference": null, + "budget": { + "attempt_count": 0, + "reconciliation_count": 0, + "elapsed_seconds": 0, + "spend_usd": "0.00" + }, + "created_at": 2000000000, + "updated_at": 2000000001, + "work_generation": 4, + "reconciliation_authority": null, + "lease_id": "operator_singleton" + } + } + ] + }, + { + "name": "budget_exhaustion_requires_actual_work_edge", + "event": "budget_exhaustion", + "expected_violation": "last_transition must equal the actual before and after work states", + "before": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorWorkItem.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "generation": 4, + "state": "observed", + "terminal": false, + "last_transition": null, + "reason": "none", + "owner_escalation_count": 0, + "owner_escalation_key": null, + "created_at": 2000000000, + "updated_at": 2000000300, + "elapsed_seconds": 300, + "spend_usd": "0.10" + } + } + ], + "after": [ + { + "contract_schema": "operator_state_v1.schema.json", + "document": { + "schema": "code_mower.operatorWorkItem.v1", + "tenant_id": "tenant_example", + "repository_id": "repository_example", + "work_id": "work_1085", + "generation": 4, + "state": "awaiting_owner", + "terminal": false, + "last_transition": "executing:awaiting_owner", + "reason": "budget_exhausted", + "owner_escalation_count": 1, + "owner_escalation_key": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "created_at": 2000000000, + "updated_at": 2000000310, + "elapsed_seconds": 310, + "spend_usd": "0.10" + } + } + ] + } + ] +} diff --git a/src/code_mower/operator_contract_v1.py b/src/code_mower/operator_contract_v1.py new file mode 100644 index 00000000..63c04fc0 --- /dev/null +++ b/src/code_mower/operator_contract_v1.py @@ -0,0 +1,672 @@ +"""Normative semantic checks for the closed Operator v1 contract. + +JSON Schema validates each record's closed shape. These helpers validate the +cross-field, wall-clock, and before/after rules that JSON Schema cannot express +without implementation-specific extensions. +""" + +from __future__ import annotations + +from collections.abc import Mapping, Sequence +from decimal import Decimal, InvalidOperation +from typing import Any + + +_ACTION_IMMUTABLE_FIELDS = ( + "tenant_id", + "repository_id", + "work_id", + "work_generation", + "action_id", + "operation", + "idempotency_key", + "request_digest", + "lease_id", + "lease_epoch", + "fence_token", + "target_head_sha", + "created_at", +) + + +def qualification_semantic_errors( + record: Mapping[str, Any], + *, + max_evidence_age_seconds: int, + now: int, +) -> tuple[str, ...]: + """Return fail-closed semantic errors for a qualification record. + + Callers must first validate the record against + ``operator_policy_v1.schema.json``. ``now`` is an explicit durable-store + observation time, which keeps replay and tests deterministic. + """ + + errors: list[str] = [] + status = record.get("status") + decision = record.get("decision") + reason = record.get("reason") + evidence = record.get("evidence") + + if status == "qualified": + if decision != "allowed" or reason != "evidence_current": + errors.append("qualified evidence must be allowed and current") + if not isinstance(evidence, Mapping): + errors.append("qualified evidence must be present") + else: + observed_at = evidence.get("observed_at") + expires_at = evidence.get("expires_at") + if not isinstance(observed_at, int) or not isinstance(expires_at, int): + errors.append("qualification evidence timestamps must be integers") + else: + if observed_at >= expires_at: + errors.append("qualification evidence must expire after observation") + if observed_at > now: + errors.append("qualification evidence cannot be observed in the future") + if now >= expires_at: + errors.append("qualification evidence is expired") + if now - observed_at > max_evidence_age_seconds: + errors.append("qualification evidence exceeds the policy age limit") + elif status == "pending": + if decision != "denied": + errors.append("pending qualification must be denied") + if reason not in {"evidence_missing", "human_merge_required"}: + errors.append("pending qualification has a contradictory reason") + if evidence is not None: + errors.append("pending qualification cannot claim completed evidence") + elif status == "failed": + if decision != "denied": + errors.append("failed qualification must be denied") + if reason not in {"evidence_failed", "capability_missing"}: + errors.append("failed qualification has a contradictory reason") + elif reason == "evidence_failed" and not isinstance(evidence, Mapping): + errors.append("failed evidence must retain the evidence record") + elif status == "stale": + if decision != "denied" or reason != "evidence_stale": + errors.append("stale qualification must be denied as stale") + if not isinstance(evidence, Mapping): + errors.append("stale qualification must retain its evidence") + else: + observed_at = evidence.get("observed_at") + expires_at = evidence.get("expires_at") + if not isinstance(observed_at, int) or not isinstance(expires_at, int): + errors.append("qualification evidence timestamps must be integers") + elif observed_at >= expires_at: + errors.append("qualification evidence must expire after observation") + elif observed_at > now: + errors.append("qualification evidence cannot be observed in the future") + elif now < expires_at and now - observed_at <= max_evidence_age_seconds: + errors.append("stale qualification evidence is still current") + + required = record.get("required_capabilities") + declared = record.get("declared_capabilities") + if isinstance(required, list) and isinstance(declared, list): + missing = sorted(set(required) - set(declared)) + if missing and status == "qualified": + errors.append("qualified provider is missing required capabilities") + if status == "failed" and reason == "capability_missing" and not missing: + errors.append("capability-missing status has no missing capability") + return tuple(errors) + + +def action_intent_semantic_errors( + record: Mapping[str, Any], + *, + current_work_generation: int, + current_lease: Mapping[str, Any] | None = None, + current_head_sha: str | None = None, + now: int | None = None, +) -> tuple[str, ...]: + """Check an intent against independently read current durable authority.""" + + errors: list[str] = [] + if record.get("work_generation") != current_work_generation: + errors.append("action intent belongs to a stale work generation") + + authority = record.get("reconciliation_authority") + next_action = record.get("next_action") + certainty = record.get("certainty") + requires_result_commit = certainty in {"confirmed_success", "confirmed_failure"} + requires_authority = next_action in {"dispatch", "retry", "reconcile"} or requires_result_commit + requires_exact_head = next_action in {"dispatch", "retry"} or requires_result_commit + + if requires_authority: + if not isinstance(current_lease, Mapping): + errors.append("current durable lease is required for this action") + else: + if current_lease.get("schema") != "code_mower.operatorLease.v1": + errors.append("current durable lease has the wrong schema") + errors.extend(lease_semantic_errors(current_lease, now=now, require_live=True)) + if current_lease.get("tenant_id") != record.get("tenant_id"): + errors.append("current lease tenant does not match the action intent") + if current_lease.get("repository_id") != record.get("repository_id"): + errors.append("current lease repository does not match the action intent") + if current_lease.get("lease_id") != record.get("lease_id"): + errors.append("current lease identity does not match the action intent") + expected_epoch = record.get("lease_epoch") + expected_token = record.get("fence_token") + if isinstance(authority, Mapping): + expected_epoch = authority.get("lease_epoch") + expected_token = authority.get("fence_token") + if ( + current_lease.get("epoch") != expected_epoch + or current_lease.get("fence_token") != expected_token + ): + errors.append("action authority does not match the current lease fence") + + if next_action in {"dispatch", "retry"}: + # A takeover keeps the immutable dispatch fence stale. Once the new + # holder has reconciled a confirmed failure, retry is authorized by + # its separately recorded current authority rather than by rewriting + # the original fence. + if record.get("fence_status") != "current" and not ( + next_action == "retry" and isinstance(authority, Mapping) + ): + errors.append("dispatch or original-holder retry requires a current dispatch fence") + if record.get("head_status") != "current": + errors.append("dispatch or retry requires a current target head") + if requires_exact_head: + if current_head_sha is None: + errors.append("current durable head is required for this action") + elif current_head_sha != record.get("target_head_sha"): + errors.append("action target does not match the current durable head") + return tuple(errors) + + +def lease_semantic_errors( + record: Mapping[str, Any], + *, + now: int | None = None, + require_live: bool = False, +) -> tuple[str, ...]: + """Validate lease chronology and, when requested, live mutation authority.""" + + errors: list[str] = [] + if record.get("schema") != "code_mower.operatorLease.v1": + errors.append("lease record has the wrong schema") + acquired_at = record.get("acquired_at") + renew_by = record.get("renew_by") + expires_at = record.get("expires_at") + if all(isinstance(value, int) for value in (acquired_at, renew_by, expires_at)): + if not acquired_at <= renew_by < expires_at: + errors.append("lease chronology must satisfy acquired_at <= renew_by < expires_at") + if require_live: + if now is None: + errors.append("current time is required to establish a live lease") + elif not acquired_at <= now < renew_by: + errors.append("lease is not live for starting or committing mutation work") + else: + errors.append("lease chronology requires integer timestamps") + if require_live and record.get("state") != "active": + errors.append("mutation authority requires an active lease") + return tuple(errors) + + +def _decimal(value: object, label: str, errors: list[str]) -> Decimal | None: + try: + parsed = Decimal(str(value)) + except (InvalidOperation, ValueError): + errors.append(f"{label} is not a decimal amount") + return None + if not parsed.is_finite(): + errors.append(f"{label} is not a finite decimal amount") + return None + return parsed + + +def policy_binding_errors( + policy: Mapping[str, Any], + record: Mapping[str, Any], + *, + current_work_generation: int | None = None, + current_lease: Mapping[str, Any] | None = None, + current_head_sha: str | None = None, + now: int | None = None, +) -> tuple[str, ...]: + """Bind one state record to the owner policy and current durable authority.""" + + errors: list[str] = [] + if record.get("tenant_id") != policy.get("tenant_id"): + errors.append("record tenant is outside the owner policy") + allowlist = policy.get("repository_allowlist") + if not isinstance(allowlist, list) or record.get("repository_id") not in allowlist: + errors.append("record repository is outside the owner policy allowlist") + + budgets = policy.get("budgets") + if not isinstance(budgets, Mapping): + return tuple((*errors, "owner policy budgets are unavailable")) + schema = record.get("schema") + if schema == "code_mower.operatorActionIntent.v1": + mutations = policy.get("authority", {}).get("mutations", []) + if record.get("operation") not in mutations: + errors.append("action operation is not authorized by owner policy") + budget = record.get("budget") + if not isinstance(budget, Mapping): + errors.append("action budget is unavailable") + else: + ceiling_fields = ( + ("attempt_count", "max_attempts_per_action"), + ("reconciliation_count", "max_reconciliations_per_action"), + ("elapsed_seconds", "max_action_seconds"), + ) + for field, ceiling in ceiling_fields: + value = budget.get(field) + limit = budgets.get(ceiling) + if isinstance(value, int) and isinstance(limit, int) and value > limit: + errors.append(f"action {field} exceeds owner policy {ceiling}") + spend = _decimal(budget.get("spend_usd"), "action spend", errors) + spend_limit = _decimal(budgets.get("max_spend_usd"), "policy spend ceiling", errors) + if spend is not None and spend_limit is not None and spend > spend_limit: + errors.append("action spend exceeds owner policy max_spend_usd") + if current_work_generation is None: + errors.append("current work generation is required for an action intent") + else: + errors.extend( + action_intent_semantic_errors( + record, + current_work_generation=current_work_generation, + current_lease=current_lease, + current_head_sha=current_head_sha, + now=now, + ) + ) + if isinstance(current_lease, Mapping): + errors.extend(policy_binding_errors(policy, current_lease, now=now)) + elif schema == "code_mower.operatorWorkItem.v1": + count = record.get("owner_escalation_count") + limit = budgets.get("max_owner_escalations") + if isinstance(count, int) and isinstance(limit, int) and count > limit: + errors.append("owner escalation count exceeds owner policy") + created_at = record.get("created_at") + updated_at = record.get("updated_at") + work_limit = budgets.get("max_work_seconds") + if isinstance(created_at, int) and isinstance(updated_at, int) and updated_at < created_at: + errors.append("work updated_at precedes created_at") + elapsed = record.get("elapsed_seconds") + if isinstance(elapsed, int) and isinstance(work_limit, int) and elapsed > work_limit: + errors.append("work elapsed time exceeds owner policy max_work_seconds") + spend = _decimal(record.get("spend_usd"), "work spend", errors) + spend_limit = _decimal(budgets.get("max_spend_usd"), "policy spend ceiling", errors) + if spend is not None and spend_limit is not None and spend > spend_limit: + errors.append("work spend exceeds owner policy max_spend_usd") + elif schema == "code_mower.operatorLease.v1": + errors.extend(lease_semantic_errors(record, now=now)) + acquired_at = record.get("acquired_at") + renew_by = record.get("renew_by") + expires_at = record.get("expires_at") + ttl = budgets.get("lease_ttl_seconds") + renewal = budgets.get("lease_renewal_seconds") + if all( + isinstance(value, int) + for value in (acquired_at, renew_by, expires_at, ttl, renewal) + ): + if renew_by - acquired_at != renewal or expires_at - acquired_at != ttl: + errors.append("lease deadlines do not match owner policy cadence") + return tuple(errors) + + +def _records_by_schema(records: Sequence[Mapping[str, Any]]) -> dict[str, list[Mapping[str, Any]]]: + by_schema: dict[str, list[Mapping[str, Any]]] = {} + for record in records: + schema = record.get("schema") + if isinstance(schema, str): + by_schema.setdefault(schema, []).append(record) + return by_schema + + +def _action_pair( + before: dict[str, list[Mapping[str, Any]]], + after: dict[str, list[Mapping[str, Any]]], + errors: list[str], +) -> tuple[Mapping[str, Any], Mapping[str, Any]] | None: + schema = "code_mower.operatorActionIntent.v1" + if len(before.get(schema, [])) != 1 or len(after.get(schema, [])) != 1: + errors.append("scenario must contain one action intent before and after") + return None + old = before[schema][0] + new = after[schema][0] + for field in _ACTION_IMMUTABLE_FIELDS: + if old.get(field) != new.get(field): + errors.append(f"action intent changed immutable field {field}") + old_budget = old.get("budget") + new_budget = new.get("budget") + if isinstance(old_budget, Mapping) and isinstance(new_budget, Mapping): + for field in ("attempt_count", "reconciliation_count", "elapsed_seconds"): + old_value = old_budget.get(field) + new_value = new_budget.get(field) + if isinstance(old_value, int) and isinstance(new_value, int) and new_value < old_value: + errors.append(f"action cumulative {field} moved backwards") + old_spend = _decimal(old_budget.get("spend_usd"), "old action spend", errors) + new_spend = _decimal(new_budget.get("spend_usd"), "new action spend", errors) + if old_spend is not None and new_spend is not None and new_spend < old_spend: + errors.append("action cumulative spend moved backwards") + old_updated = old.get("updated_at") + new_updated = new.get("updated_at") + if isinstance(old_updated, int) and isinstance(new_updated, int) and new_updated < old_updated: + errors.append("action updated_at moved backwards") + return old, new + + +def _work_pair( + before: dict[str, list[Mapping[str, Any]]], + after: dict[str, list[Mapping[str, Any]]], + errors: list[str], +) -> tuple[Mapping[str, Any], Mapping[str, Any]] | None: + schema = "code_mower.operatorWorkItem.v1" + if len(before.get(schema, [])) != 1 or len(after.get(schema, [])) != 1: + errors.append("scenario must contain one work item before and after") + return None + old = before[schema][0] + new = after[schema][0] + for field in ("tenant_id", "repository_id", "work_id", "generation", "created_at"): + if old.get(field) != new.get(field): + errors.append(f"work item changed immutable field {field}") + old_count = old.get("owner_escalation_count") + new_count = new.get("owner_escalation_count") + if isinstance(old_count, int) and isinstance(new_count, int) and new_count < old_count: + errors.append("owner escalation count moved backwards") + old_elapsed = old.get("elapsed_seconds") + new_elapsed = new.get("elapsed_seconds") + if isinstance(old_elapsed, int) and isinstance(new_elapsed, int) and new_elapsed < old_elapsed: + errors.append("work cumulative elapsed_seconds moved backwards") + old_spend = _decimal(old.get("spend_usd"), "old work spend", errors) + new_spend = _decimal(new.get("spend_usd"), "new work spend", errors) + if old_spend is not None and new_spend is not None and new_spend < old_spend: + errors.append("work cumulative spend moved backwards") + old_updated = old.get("updated_at") + new_updated = new.get("updated_at") + if isinstance(old_updated, int) and isinstance(new_updated, int) and new_updated < old_updated: + errors.append("work updated_at moved backwards") + return old, new + + +def _lease_pair( + before: dict[str, list[Mapping[str, Any]]], + after: dict[str, list[Mapping[str, Any]]], + errors: list[str], +) -> tuple[Mapping[str, Any], Mapping[str, Any]] | None: + schema = "code_mower.operatorLease.v1" + if len(before.get(schema, [])) != 1 or len(after.get(schema, [])) != 1: + errors.append("takeover must contain one lease before and after") + return None + old = before[schema][0] + new = after[schema][0] + errors.extend(lease_semantic_errors(old)) + errors.extend(lease_semantic_errors(new)) + for field in ("tenant_id", "repository_id", "lease_id"): + if old.get(field) != new.get(field): + errors.append(f"takeover changed lease scope field {field}") + if old.get("holder_id") == new.get("holder_id"): + errors.append("takeover must use a new holder identity") + if new.get("state") != "active": + errors.append("takeover must establish an active lease") + old_acquired = old.get("acquired_at") + new_acquired = new.get("acquired_at") + if isinstance(old_acquired, int) and isinstance(new_acquired, int) and new_acquired < old_acquired: + errors.append("takeover lease acquisition moved backwards") + return old, new + + +def _action_tuple(record: Mapping[str, Any]) -> tuple[object, object, object, object]: + return ( + record.get("state"), + record.get("certainty"), + record.get("reconciliation"), + record.get("next_action"), + ) + + +def _require_action_edge( + event: str, + old: Mapping[str, Any], + new: Mapping[str, Any], + *, + allowed_sources: set[tuple[object, object, object, object]], + allowed_targets: set[tuple[object, object, object, object]], + errors: list[str], +) -> None: + if _action_tuple(old) not in allowed_sources: + errors.append(f"{event} has an invalid action source state") + if _action_tuple(new) not in allowed_targets: + errors.append(f"{event} has an invalid action target state") + + +def _require_work_edge( + event: str, + old: Mapping[str, Any], + new: Mapping[str, Any], + *, + allowed_sources: set[str], + target: str, + errors: list[str], +) -> None: + source = old.get("state") + if source not in allowed_sources: + errors.append(f"{event} has an invalid work source state") + if new.get("state") != target: + errors.append(f"{event} has an invalid work target state") + if new.get("last_transition") != f"{source}:{target}": + errors.append(f"{event} last_transition does not match the actual work edge") + + +def recovery_transition_errors( + event: str, + before_records: Sequence[Mapping[str, Any]], + after_records: Sequence[Mapping[str, Any]], +) -> tuple[str, ...]: + """Validate one executable Operator recovery transition. + + Records must already pass their JSON Schema and semantic checks. The + result validates the event's before/after invariant, including counters + and immutable dispatch identity. + """ + + errors: list[str] = [] + before = _records_by_schema(before_records) + after = _records_by_schema(after_records) + + if event in { + "restart_after_dispatch", + "duplicate_delivery", + "stale_head", + "provider_timeout", + "partial_success", + }: + pair = _action_pair(before, after, errors) + if pair is None: + return tuple(errors) + old, new = pair + old_attempts = old.get("budget", {}).get("attempt_count") + new_attempts = new.get("budget", {}).get("attempt_count") + + if event == "restart_after_dispatch": + _require_action_edge( + event, + old, + new, + allowed_sources={ + ("dispatched", "unknown", "required", "reconcile"), + ("uncertain", "unknown", "required", "reconcile"), + ("reconciling", "unknown", "in_progress", "reconcile"), + }, + allowed_targets={("reconciling", "unknown", "in_progress", "reconcile")}, + errors=errors, + ) + if old.get("certainty") != "unknown" or new.get("certainty") != "unknown": + errors.append("restart must preserve an unknown dispatched outcome") + if new.get("next_action") != "reconcile": + errors.append("restart must reconcile before another dispatch") + if old_attempts != new_attempts: + errors.append("restart cannot reserve another mutation attempt") + elif event == "duplicate_delivery": + if old != new: + errors.append("duplicate delivery must return the recorded intent unchanged") + elif event == "stale_head": + _require_action_edge( + event, + old, + new, + allowed_sources={("prepared", "not_attempted", "not_required", "dispatch")}, + allowed_targets={("abandoned", "not_applicable", "not_required", "abandon")}, + errors=errors, + ) + if new.get("head_status") != "stale": + errors.append("stale-head recovery must record the stale target") + if new.get("state") != "abandoned" or new.get("next_action") != "abandon": + errors.append("a pre-dispatch stale head must abandon the intent") + if new_attempts != 0: + errors.append("a pre-dispatch stale head cannot consume an attempt") + elif event == "provider_timeout": + _require_action_edge( + event, + old, + new, + allowed_sources={("prepared", "not_attempted", "not_required", "dispatch")}, + allowed_targets={("uncertain", "unknown", "required", "reconcile")}, + errors=errors, + ) + if new.get("certainty") != "unknown" or new.get("next_action") != "reconcile": + errors.append("provider timeout must become unknown and reconcile") + if old_attempts != 0 or new_attempts != 1: + errors.append("provider timeout must record exactly one dispatched attempt") + elif event == "partial_success": + _require_action_edge( + event, + old, + new, + allowed_sources={ + ("dispatched", "unknown", "required", "reconcile"), + ("uncertain", "unknown", "required", "reconcile"), + }, + allowed_targets={("reconciling", "unknown", "in_progress", "reconcile")}, + errors=errors, + ) + if new.get("certainty") != "unknown" or new.get("next_action") != "reconcile": + errors.append("partial success must remain unknown pending reconciliation") + if old_attempts != new_attempts: + errors.append("partial success cannot repeat the mutation set") + + elif event == "lease_takeover": + pair = _action_pair(before, after, errors) + lease_pair = _lease_pair(before, after, errors) + if lease_pair is None: + return tuple(errors) + old_lease, new_lease = lease_pair + if new_lease.get("epoch") != old_lease.get("epoch", 0) + 1: + errors.append("takeover must increment the lease epoch") + if new_lease.get("fence_token") == old_lease.get("fence_token"): + errors.append("takeover must issue a new fence token") + if pair is not None: + old, new = pair + _require_action_edge( + event, + old, + new, + allowed_sources={ + ("dispatched", "unknown", "required", "reconcile"), + ("uncertain", "unknown", "required", "reconcile"), + ("reconciling", "unknown", "in_progress", "reconcile"), + }, + allowed_targets={("reconciling", "unknown", "in_progress", "reconcile")}, + errors=errors, + ) + authority = new.get("reconciliation_authority") + for action, lease, label in ((old, old_lease, "dispatch"), (new, new_lease, "recovery")): + if action.get("tenant_id") != lease.get("tenant_id"): + errors.append(f"{label} intent tenant does not match its lease") + if action.get("repository_id") != lease.get("repository_id"): + errors.append(f"{label} intent repository does not match its lease") + if ( + old.get("lease_epoch") != old_lease.get("epoch") + or old.get("fence_token") != old_lease.get("fence_token") + ): + errors.append("dispatched intent does not match the original lease fence") + if old.get("certainty") != "unknown" or new.get("certainty") != "unknown": + errors.append("takeover must preserve an unknown dispatched outcome") + if new.get("fence_status") != "stale" or new.get("next_action") != "reconcile": + errors.append("takeover must reconcile the stale-fenced dispatch") + if not isinstance(authority, Mapping): + errors.append("takeover reconciliation requires current authority") + elif ( + authority.get("lease_epoch") != new_lease.get("epoch") + or authority.get("fence_token") != new_lease.get("fence_token") + ): + errors.append("reconciliation authority must match the takeover lease") + if old.get("budget", {}).get("attempt_count") != new.get("budget", {}).get("attempt_count"): + errors.append("takeover cannot blindly reserve another attempt") + + elif event in {"budget_exhaustion", "owner_escalation_redelivery", "owner_stop"}: + pair = _work_pair(before, after, errors) + if pair is None: + return tuple(errors) + old_work, new_work = pair + if old_work.get("work_id") != new_work.get("work_id"): + errors.append("work transition changed work identity") + if old_work.get("generation") != new_work.get("generation"): + errors.append("recovery transition changed work generation") + + if event == "budget_exhaustion": + _require_work_edge( + event, + old_work, + new_work, + allowed_sources={ + "admitted", + "claimed", + "executing", + "waiting_provider", + "reconciling", + "awaiting_review", + }, + target="awaiting_owner", + errors=errors, + ) + if new_work.get("state") != "awaiting_owner" or new_work.get("reason") != "budget_exhausted": + errors.append("budget exhaustion must stop awaiting owner") + if new_work.get("owner_escalation_count") != old_work.get("owner_escalation_count", 0) + 1: + errors.append("budget exhaustion must reserve one bounded escalation") + if not isinstance(new_work.get("owner_escalation_key"), str): + errors.append("budget exhaustion must persist an escalation dedupe key") + elif event == "owner_escalation_redelivery": + if old_work != new_work: + errors.append("owner escalation redelivery must reuse the durable notification record") + else: + action_pair = _action_pair(before, after, errors) + _require_work_edge( + event, + old_work, + new_work, + allowed_sources={ + "observed", + "admitted", + "claimed", + "executing", + "waiting_provider", + "reconciling", + "awaiting_review", + "awaiting_owner", + }, + target="cancelled", + errors=errors, + ) + if new_work.get("state") != "cancelled" or new_work.get("reason") != "owner_cancelled": + errors.append("owner stop must cancel the work item") + if action_pair is not None: + old_action, new_action = action_pair + _require_action_edge( + event, + old_action, + new_action, + allowed_sources={("prepared", "not_attempted", "not_required", "dispatch")}, + allowed_targets={("abandoned", "not_applicable", "not_required", "abandon")}, + errors=errors, + ) + if new_action.get("state") != "abandoned" or new_action.get("next_action") != "abandon": + errors.append("owner stop must abandon a prepared action") + if old_action.get("budget", {}).get("attempt_count") != new_action.get("budget", {}).get( + "attempt_count" + ): + errors.append("owner stop cannot start another mutation") + else: + errors.append(f"unknown recovery event: {event}") + return tuple(errors) diff --git a/src/code_mower/operator_policy_v1.schema.json b/src/code_mower/operator_policy_v1.schema.json new file mode 100644 index 00000000..7014704b --- /dev/null +++ b/src/code_mower/operator_policy_v1.schema.json @@ -0,0 +1,804 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "code_mower.operator_policy.v1", + "title": "Code Mower Operator v1 authority and provider qualification contract", + "description": "Closed, provider-neutral policy records. These records grant no runtime authority by themselves.", + "oneOf": [ + { + "$ref": "#/$defs/policy" + }, + { + "$ref": "#/$defs/qualification" + } + ], + "$defs": { + "opaque_id": { + "type": "string", + "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$", + "maxLength": 128 + }, + "digest": { + "type": "string", + "pattern": "^[0-9a-f]{64}$", + "maxLength": 64 + }, + "authority": { + "type": "object", + "additionalProperties": false, + "required": [ + "observation", + "proposals", + "mutations", + "denied", + "merge_approval", + "operator_merge" + ], + "properties": { + "observation": { + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { + "enum": [ + "repository_metadata", + "issue_metadata", + "pull_request_metadata", + "check_metadata", + "provider_session_metadata", + "operator_records" + ] + } + }, + "proposals": { + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { + "enum": [ + "work_selection", + "provider_assignment", + "owner_escalation", + "review_request" + ] + } + }, + "mutations": { + "type": "array", + "uniqueItems": true, + "items": { + "enum": [ + "create_provider_session", + "message_provider_session", + "cancel_provider_session", + "create_branch", + "push_commit", + "open_or_update_pull_request", + "apply_workflow_label", + "request_review", + "post_bounded_status" + ] + } + }, + "denied": { + "const": [ + "merge_pull_request", + "approve_own_work", + "weaken_branch_protection", + "expose_private_content", + "expand_repository_allowlist", + "mint_or_rotate_credentials" + ] + }, + "merge_approval": { + "const": "human_required" + }, + "operator_merge": { + "const": false + } + } + }, + "budgets": { + "type": "object", + "additionalProperties": false, + "required": [ + "max_concurrent_work_items", + "max_concurrent_mutations", + "max_attempts_per_action", + "max_reconciliations_per_action", + "max_owner_escalations", + "max_work_seconds", + "max_action_seconds", + "max_spend_usd", + "lease_ttl_seconds", + "lease_renewal_seconds" + ], + "properties": { + "max_concurrent_work_items": { + "type": "integer", + "minimum": 1, + "maximum": 32 + }, + "max_concurrent_mutations": { + "type": "integer", + "minimum": 1, + "maximum": 8 + }, + "max_attempts_per_action": { + "type": "integer", + "minimum": 1, + "maximum": 5 + }, + "max_reconciliations_per_action": { + "type": "integer", + "minimum": 1, + "maximum": 5 + }, + "max_owner_escalations": { + "type": "integer", + "minimum": 1, + "maximum": 3 + }, + "max_work_seconds": { + "type": "integer", + "minimum": 60, + "maximum": 604800 + }, + "max_action_seconds": { + "type": "integer", + "minimum": 1, + "maximum": 3600 + }, + "max_spend_usd": { + "type": "string", + "pattern": "^(0|[1-9][0-9]{0,5})\\.[0-9]{2}$", + "maxLength": 9 + }, + "lease_ttl_seconds": { + "type": "integer", + "minimum": 15, + "maximum": 600 + }, + "lease_renewal_seconds": { + "type": "integer", + "minimum": 5, + "maximum": 300 + } + } + }, + "privacy": { + "type": "object", + "additionalProperties": false, + "required": [ + "classification", + "projection_fields", + "excluded_content", + "opaque_identifiers" + ], + "properties": { + "classification": { + "const": "metadata_only" + }, + "projection_fields": { + "const": [ + "schema", + "event_type", + "observed_at", + "tenant_id", + "repository_id", + "work_id", + "action_id", + "provider_id", + "role", + "state", + "reason", + "attempt_count", + "elapsed_seconds", + "spend_usd" + ] + }, + "excluded_content": { + "const": [ + "source", + "diffs", + "prompts", + "transcripts", + "issue_bodies", + "raw_provider_output", + "credentials", + "private_content", + "personal_paths" + ] + }, + "opaque_identifiers": { + "const": true + } + } + }, + "qualification_policy": { + "type": "object", + "additionalProperties": false, + "required": [ + "roles", + "required_evidence", + "max_evidence_age_seconds", + "fail_closed", + "provider_name_grants_authority" + ], + "properties": { + "roles": { + "const": [ + "orchestrator", + "builder", + "reviewer", + "merge_authority" + ] + }, + "required_evidence": { + "const": [ + "capability_declaration", + "deterministic_harness", + "exact_head_result", + "policy_decision" + ] + }, + "max_evidence_age_seconds": { + "type": "integer", + "minimum": 60, + "maximum": 2592000 + }, + "fail_closed": { + "const": true + }, + "provider_name_grants_authority": { + "const": false + } + } + }, + "owner_action": { + "type": "object", + "additionalProperties": false, + "required": [ + "stop_reasons", + "delivery", + "after_budget_exhaustion" + ], + "properties": { + "stop_reasons": { + "const": [ + "approval_required", + "budget_exhausted", + "capability_unqualified", + "credentials_unavailable", + "policy_denied", + "reconciliation_inconclusive", + "repository_not_allowed", + "stale_head", + "stale_lease", + "user_input_required" + ] + }, + "delivery": { + "const": "bounded_deduplicated_escalation" + }, + "after_budget_exhaustion": { + "const": "stop_without_mutation" + } + } + }, + "policy": { + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "contract_version", + "tenant_id", + "repository_allowlist", + "authority", + "budgets", + "qualification", + "privacy", + "owner_action" + ], + "properties": { + "schema": { + "const": "code_mower.operatorPolicy.v1" + }, + "contract_version": { + "const": "1.7" + }, + "tenant_id": { + "$ref": "#/$defs/opaque_id" + }, + "repository_allowlist": { + "type": "array", + "minItems": 1, + "maxItems": 64, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/opaque_id" + } + }, + "authority": { + "$ref": "#/$defs/authority" + }, + "budgets": { + "$ref": "#/$defs/budgets" + }, + "qualification": { + "$ref": "#/$defs/qualification_policy" + }, + "privacy": { + "$ref": "#/$defs/privacy" + }, + "owner_action": { + "$ref": "#/$defs/owner_action" + } + } + }, + "capability": { + "enum": [ + "observe_repository", + "select_work", + "create_session", + "message_session", + "cancel_session", + "write_branch", + "open_pull_request", + "request_review", + "structured_result", + "reconcile_remote_mutation" + ] + }, + "evidence": { + "type": "object", + "additionalProperties": false, + "required": [ + "capability_declaration_digest", + "harness_digest", + "source_head", + "observed_at", + "expires_at" + ], + "properties": { + "capability_declaration_digest": { + "$ref": "#/$defs/digest" + }, + "harness_digest": { + "$ref": "#/$defs/digest" + }, + "source_head": { + "type": "string", + "pattern": "^[0-9a-f]{40}$", + "maxLength": 40 + }, + "observed_at": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + }, + "expires_at": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + } + } + }, + "qualification": { + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "provider_id", + "transport_id", + "role", + "required_capabilities", + "declared_capabilities", + "evidence", + "status", + "decision", + "reason" + ], + "properties": { + "schema": { + "const": "code_mower.operatorQualification.v1" + }, + "provider_id": { + "$ref": "#/$defs/opaque_id" + }, + "transport_id": { + "$ref": "#/$defs/opaque_id" + }, + "role": { + "enum": [ + "orchestrator", + "builder", + "reviewer", + "merge_authority" + ] + }, + "required_capabilities": { + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/capability" + } + }, + "declared_capabilities": { + "type": "array", + "uniqueItems": true, + "items": { + "$ref": "#/$defs/capability" + } + }, + "evidence": { + "oneOf": [ + { + "$ref": "#/$defs/evidence" + }, + { + "type": "null" + } + ] + }, + "status": { + "enum": [ + "qualified", + "pending", + "failed", + "stale" + ] + }, + "decision": { + "enum": [ + "allowed", + "denied" + ] + }, + "reason": { + "enum": [ + "evidence_current", + "evidence_missing", + "evidence_failed", + "evidence_stale", + "capability_missing", + "human_merge_required" + ] + } + }, + "allOf": [ + { + "if": { + "properties": { + "status": { + "const": "qualified" + } + }, + "required": [ + "status" + ] + }, + "then": { + "properties": { + "evidence": { + "$ref": "#/$defs/evidence" + }, + "decision": { + "const": "allowed" + }, + "reason": { + "const": "evidence_current" + } + } + } + }, + { + "if": { + "properties": { + "status": { + "const": "pending" + } + }, + "required": [ + "status" + ] + }, + "then": { + "properties": { + "decision": { + "const": "denied" + }, + "reason": { + "enum": [ + "evidence_missing", + "human_merge_required" + ] + }, + "evidence": { + "type": "null" + } + } + } + }, + { + "if": { + "properties": { + "status": { + "const": "failed" + } + }, + "required": [ + "status" + ] + }, + "then": { + "properties": { + "decision": { + "const": "denied" + }, + "reason": { + "enum": [ + "evidence_failed", + "capability_missing" + ] + } + } + } + }, + { + "if": { + "properties": { + "status": { + "const": "stale" + } + }, + "required": [ + "status" + ] + }, + "then": { + "properties": { + "decision": { + "const": "denied" + }, + "reason": { + "const": "evidence_stale" + }, + "evidence": { + "$ref": "#/$defs/evidence" + } + } + } + }, + { + "if": { + "properties": { + "role": { + "const": "merge_authority" + } + }, + "required": [ + "role" + ] + }, + "then": { + "properties": { + "status": { + "const": "pending" + }, + "decision": { + "const": "denied" + }, + "reason": { + "const": "human_merge_required" + }, + "evidence": { + "type": "null" + } + } + } + }, + { + "if": { + "properties": { + "role": { + "const": "orchestrator" + } + }, + "required": [ + "role" + ] + }, + "then": { + "properties": { + "required_capabilities": { + "const": [ + "observe_repository", + "select_work", + "create_session", + "structured_result", + "reconcile_remote_mutation" + ] + } + } + } + }, + { + "if": { + "properties": { + "role": { + "const": "builder" + } + }, + "required": [ + "role" + ] + }, + "then": { + "properties": { + "required_capabilities": { + "const": [ + "create_session", + "write_branch", + "open_pull_request", + "structured_result" + ] + } + } + } + }, + { + "if": { + "properties": { + "role": { + "const": "reviewer" + } + }, + "required": [ + "role" + ] + }, + "then": { + "properties": { + "required_capabilities": { + "const": [ + "observe_repository", + "request_review", + "structured_result" + ] + } + } + } + }, + { + "if": { + "properties": { + "role": { + "const": "merge_authority" + } + }, + "required": [ + "role" + ] + }, + "then": { + "properties": { + "required_capabilities": { + "const": [ + "observe_repository" + ] + } + } + } + }, + { + "if": { + "properties": { + "status": { + "const": "qualified" + }, + "role": { + "const": "orchestrator" + } + }, + "required": [ + "status", + "role" + ] + }, + "then": { + "properties": { + "declared_capabilities": { + "const": [ + "observe_repository", + "select_work", + "create_session", + "structured_result", + "reconcile_remote_mutation" + ] + } + } + } + }, + { + "if": { + "properties": { + "status": { + "const": "qualified" + }, + "role": { + "const": "builder" + } + }, + "required": [ + "status", + "role" + ] + }, + "then": { + "properties": { + "declared_capabilities": { + "const": [ + "create_session", + "write_branch", + "open_pull_request", + "structured_result" + ] + } + } + } + }, + { + "if": { + "properties": { + "status": { + "const": "qualified" + }, + "role": { + "const": "reviewer" + } + }, + "required": [ + "status", + "role" + ] + }, + "then": { + "properties": { + "declared_capabilities": { + "const": [ + "observe_repository", + "request_review", + "structured_result" + ] + } + } + } + }, + { + "if": { + "properties": { + "status": { + "const": "failed" + }, + "reason": { + "const": "evidence_failed" + } + }, + "required": [ + "status", + "reason" + ] + }, + "then": { + "properties": { + "evidence": { + "$ref": "#/$defs/evidence" + } + } + } + } + ] + } + } +} diff --git a/src/code_mower/operator_state_v1.schema.json b/src/code_mower/operator_state_v1.schema.json new file mode 100644 index 00000000..36980027 --- /dev/null +++ b/src/code_mower/operator_state_v1.schema.json @@ -0,0 +1,2256 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "code_mower.operator_state.v1", + "title": "Code Mower Operator v1 durable state and metadata projection contract", + "description": "Closed records for work lifecycle, singleton leases, durable mutation intent, and metadata-only projection.", + "oneOf": [ + { + "$ref": "#/$defs/work_item" + }, + { + "$ref": "#/$defs/lease" + }, + { + "$ref": "#/$defs/action_intent" + }, + { + "$ref": "#/$defs/projection" + } + ], + "$defs": { + "opaque_id": { + "type": "string", + "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$", + "maxLength": 128 + }, + "digest": { + "type": "string", + "pattern": "^[0-9a-f]{64}$", + "maxLength": 64 + }, + "head_sha": { + "type": "string", + "pattern": "^[0-9a-f]{40}$", + "maxLength": 40 + }, + "timestamp": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + }, + "lifecycle_state": { + "enum": [ + "observed", + "admitted", + "claimed", + "executing", + "waiting_provider", + "reconciling", + "awaiting_review", + "awaiting_owner", + "completed", + "failed", + "cancelled" + ] + }, + "transition": { + "enum": [ + "observed:admitted", + "observed:cancelled", + "admitted:claimed", + "admitted:awaiting_owner", + "admitted:cancelled", + "claimed:executing", + "claimed:awaiting_owner", + "claimed:cancelled", + "executing:waiting_provider", + "executing:reconciling", + "executing:awaiting_review", + "executing:awaiting_owner", + "executing:failed", + "executing:cancelled", + "waiting_provider:executing", + "waiting_provider:reconciling", + "waiting_provider:awaiting_review", + "waiting_provider:awaiting_owner", + "waiting_provider:failed", + "waiting_provider:cancelled", + "reconciling:executing", + "reconciling:awaiting_review", + "reconciling:awaiting_owner", + "reconciling:failed", + "reconciling:cancelled", + "awaiting_review:executing", + "awaiting_review:awaiting_owner", + "awaiting_review:completed", + "awaiting_review:failed", + "awaiting_review:cancelled", + "awaiting_owner:admitted", + "awaiting_owner:executing", + "awaiting_owner:cancelled" + ] + }, + "stop_reason": { + "enum": [ + "none", + "approval_required", + "budget_exhausted", + "capability_unqualified", + "credentials_unavailable", + "policy_denied", + "reconciliation_inconclusive", + "repository_not_allowed", + "stale_head", + "stale_lease", + "user_input_required", + "work_completed", + "work_failed", + "owner_cancelled" + ] + }, + "work_item": { + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "tenant_id", + "repository_id", + "work_id", + "generation", + "state", + "terminal", + "last_transition", + "reason", + "owner_escalation_count", + "elapsed_seconds", + "spend_usd", + "owner_escalation_key", + "created_at", + "updated_at" + ], + "properties": { + "schema": { + "const": "code_mower.operatorWorkItem.v1" + }, + "tenant_id": { + "$ref": "#/$defs/opaque_id" + }, + "repository_id": { + "$ref": "#/$defs/opaque_id" + }, + "work_id": { + "$ref": "#/$defs/opaque_id" + }, + "generation": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + }, + "state": { + "$ref": "#/$defs/lifecycle_state" + }, + "terminal": { + "type": "boolean" + }, + "last_transition": { + "oneOf": [ + { + "$ref": "#/$defs/transition" + }, + { + "type": "null" + } + ] + }, + "reason": { + "$ref": "#/$defs/stop_reason" + }, + "owner_escalation_count": { + "type": "integer", + "minimum": 0, + "maximum": 3 + }, + "created_at": { + "$ref": "#/$defs/timestamp" + }, + "updated_at": { + "$ref": "#/$defs/timestamp" + }, + "owner_escalation_key": { + "oneOf": [ + { + "$ref": "#/$defs/digest" + }, + { + "type": "null" + } + ] + }, + "elapsed_seconds": { + "type": "integer", + "minimum": 0, + "maximum": 604800 + }, + "spend_usd": { + "type": "string", + "pattern": "^(0|[1-9][0-9]{0,5})\\.[0-9]{2}$", + "maxLength": 9 + } + }, + "allOf": [ + { + "if": { + "properties": { + "state": { + "enum": [ + "completed", + "failed", + "cancelled" + ] + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "terminal": { + "const": true + } + } + } + }, + { + "if": { + "properties": { + "state": { + "enum": [ + "observed", + "admitted", + "claimed", + "executing", + "waiting_provider", + "reconciling", + "awaiting_review", + "awaiting_owner" + ] + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "terminal": { + "const": false + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "awaiting_owner" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "enum": [ + "approval_required", + "budget_exhausted", + "capability_unqualified", + "credentials_unavailable", + "policy_denied", + "reconciliation_inconclusive", + "repository_not_allowed", + "stale_head", + "stale_lease", + "user_input_required" + ] + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "observed" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "last_transition": { + "type": "null" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "admitted" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "last_transition": { + "enum": [ + "observed:admitted", + "awaiting_owner:admitted" + ] + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "claimed" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "last_transition": { + "const": "admitted:claimed" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "executing" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "last_transition": { + "enum": [ + "claimed:executing", + "waiting_provider:executing", + "reconciling:executing", + "awaiting_review:executing", + "awaiting_owner:executing" + ] + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "waiting_provider" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "last_transition": { + "const": "executing:waiting_provider" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "reconciling" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "last_transition": { + "enum": [ + "executing:reconciling", + "waiting_provider:reconciling" + ] + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "awaiting_review" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "last_transition": { + "enum": [ + "executing:awaiting_review", + "waiting_provider:awaiting_review", + "reconciling:awaiting_review" + ] + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "awaiting_owner" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "last_transition": { + "enum": [ + "admitted:awaiting_owner", + "claimed:awaiting_owner", + "executing:awaiting_owner", + "waiting_provider:awaiting_owner", + "reconciling:awaiting_owner", + "awaiting_review:awaiting_owner" + ] + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "completed" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "last_transition": { + "const": "awaiting_review:completed" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "failed" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "last_transition": { + "enum": [ + "executing:failed", + "waiting_provider:failed", + "reconciling:failed", + "awaiting_review:failed" + ] + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "cancelled" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "last_transition": { + "enum": [ + "observed:cancelled", + "admitted:cancelled", + "claimed:cancelled", + "executing:cancelled", + "waiting_provider:cancelled", + "reconciling:cancelled", + "awaiting_review:cancelled", + "awaiting_owner:cancelled" + ] + } + } + } + }, + { + "if": { + "properties": { + "owner_escalation_count": { + "minimum": 1 + } + }, + "required": [ + "owner_escalation_count" + ] + }, + "then": { + "properties": { + "owner_escalation_key": { + "$ref": "#/$defs/digest" + } + } + } + }, + { + "if": { + "properties": { + "owner_escalation_count": { + "const": 0 + } + }, + "required": [ + "owner_escalation_count" + ] + }, + "then": { + "properties": { + "owner_escalation_key": { + "type": "null" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "observed" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "none" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "admitted" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "none" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "claimed" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "none" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "executing" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "none" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "waiting_provider" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "none" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "reconciling" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "none" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "awaiting_review" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "none" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "completed" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "work_completed" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "failed" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "work_failed" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "cancelled" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "owner_cancelled" + } + } + } + } + ] + }, + "lease": { + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "tenant_id", + "repository_id", + "lease_id", + "holder_id", + "epoch", + "fence_token", + "state", + "acquired_at", + "renew_by", + "expires_at" + ], + "properties": { + "schema": { + "const": "code_mower.operatorLease.v1" + }, + "tenant_id": { + "$ref": "#/$defs/opaque_id" + }, + "repository_id": { + "$ref": "#/$defs/opaque_id" + }, + "lease_id": { + "$ref": "#/$defs/opaque_id" + }, + "holder_id": { + "$ref": "#/$defs/opaque_id" + }, + "epoch": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + }, + "fence_token": { + "$ref": "#/$defs/digest" + }, + "state": { + "enum": [ + "active", + "expired", + "released" + ] + }, + "acquired_at": { + "$ref": "#/$defs/timestamp" + }, + "renew_by": { + "$ref": "#/$defs/timestamp" + }, + "expires_at": { + "$ref": "#/$defs/timestamp" + } + } + }, + "operation": { + "enum": [ + "create_provider_session", + "message_provider_session", + "cancel_provider_session", + "create_branch", + "push_commit", + "open_or_update_pull_request", + "apply_workflow_label", + "request_review", + "post_bounded_status" + ] + }, + "action_budget": { + "type": "object", + "additionalProperties": false, + "required": [ + "attempt_count", + "reconciliation_count", + "elapsed_seconds", + "spend_usd" + ], + "properties": { + "attempt_count": { + "type": "integer", + "minimum": 0, + "maximum": 5 + }, + "reconciliation_count": { + "type": "integer", + "minimum": 0, + "maximum": 5 + }, + "elapsed_seconds": { + "type": "integer", + "minimum": 0, + "maximum": 604800 + }, + "spend_usd": { + "type": "string", + "pattern": "^(0|[1-9][0-9]{0,5})\\.[0-9]{2}$", + "maxLength": 9 + } + } + }, + "action_intent": { + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "tenant_id", + "repository_id", + "work_id", + "work_generation", + "action_id", + "operation", + "idempotency_key", + "request_digest", + "lease_id", + "lease_epoch", + "fence_token", + "fence_status", + "reconciliation_authority", + "target_head_sha", + "head_status", + "state", + "certainty", + "reconciliation", + "next_action", + "remote_reference", + "budget", + "created_at", + "updated_at" + ], + "properties": { + "schema": { + "const": "code_mower.operatorActionIntent.v1" + }, + "tenant_id": { + "$ref": "#/$defs/opaque_id" + }, + "repository_id": { + "$ref": "#/$defs/opaque_id" + }, + "work_id": { + "$ref": "#/$defs/opaque_id" + }, + "action_id": { + "$ref": "#/$defs/opaque_id" + }, + "operation": { + "$ref": "#/$defs/operation" + }, + "idempotency_key": { + "$ref": "#/$defs/digest" + }, + "request_digest": { + "$ref": "#/$defs/digest" + }, + "lease_epoch": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + }, + "fence_token": { + "$ref": "#/$defs/digest" + }, + "fence_status": { + "enum": [ + "current", + "stale" + ] + }, + "target_head_sha": { + "$ref": "#/$defs/head_sha" + }, + "head_status": { + "enum": [ + "current", + "stale" + ] + }, + "state": { + "enum": [ + "prepared", + "dispatched", + "succeeded", + "failed", + "uncertain", + "reconciling", + "abandoned" + ] + }, + "certainty": { + "enum": [ + "not_attempted", + "confirmed_success", + "confirmed_failure", + "unknown", + "not_applicable" + ] + }, + "reconciliation": { + "enum": [ + "not_required", + "required", + "in_progress", + "matched_success", + "matched_failure", + "needs_owner" + ] + }, + "next_action": { + "enum": [ + "dispatch", + "retry", + "reconcile", + "owner_action", + "abandon", + "none" + ] + }, + "remote_reference": { + "oneOf": [ + { + "$ref": "#/$defs/opaque_id" + }, + { + "type": "null" + } + ] + }, + "budget": { + "$ref": "#/$defs/action_budget" + }, + "created_at": { + "$ref": "#/$defs/timestamp" + }, + "updated_at": { + "$ref": "#/$defs/timestamp" + }, + "work_generation": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + }, + "reconciliation_authority": { + "oneOf": [ + { + "$ref": "#/$defs/reconciliation_authority" + }, + { + "type": "null" + } + ] + }, + "lease_id": { + "$ref": "#/$defs/opaque_id" + } + }, + "allOf": [ + { + "if": { + "properties": { + "certainty": { + "const": "not_attempted" + } + }, + "required": [ + "certainty" + ] + }, + "then": { + "properties": { + "state": { + "const": "prepared" + }, + "reconciliation": { + "const": "not_required" + }, + "next_action": { + "const": "dispatch" + }, + "remote_reference": { + "type": "null" + }, + "reconciliation_authority": { + "type": "null" + }, + "fence_status": { + "const": "current" + }, + "head_status": { + "const": "current" + } + } + } + }, + { + "if": { + "properties": { + "certainty": { + "const": "unknown" + } + }, + "required": [ + "certainty" + ] + }, + "then": { + "properties": { + "state": { + "enum": [ + "dispatched", + "uncertain", + "reconciling" + ] + }, + "reconciliation": { + "enum": [ + "required", + "in_progress", + "needs_owner" + ] + }, + "next_action": { + "enum": [ + "reconcile", + "owner_action" + ] + } + } + } + }, + { + "if": { + "properties": { + "certainty": { + "const": "confirmed_success" + } + }, + "required": [ + "certainty" + ] + }, + "then": { + "properties": { + "state": { + "const": "succeeded" + }, + "reconciliation": { + "enum": [ + "not_required", + "matched_success" + ] + }, + "next_action": { + "const": "none" + } + } + } + }, + { + "if": { + "properties": { + "certainty": { + "const": "confirmed_failure" + } + }, + "required": [ + "certainty" + ] + }, + "then": { + "properties": { + "state": { + "const": "failed" + }, + "reconciliation": { + "enum": [ + "not_required", + "matched_failure" + ] + }, + "next_action": { + "enum": [ + "retry", + "owner_action", + "none" + ] + } + } + } + }, + { + "if": { + "properties": { + "certainty": { + "const": "not_applicable" + } + }, + "required": [ + "certainty" + ] + }, + "then": { + "properties": { + "state": { + "const": "abandoned" + }, + "reconciliation": { + "const": "not_required" + }, + "next_action": { + "const": "abandon" + }, + "reconciliation_authority": { + "type": "null" + } + } + } + }, + { + "if": { + "allOf": [ + { + "anyOf": [ + { + "properties": { + "fence_status": { + "const": "stale" + } + }, + "required": [ + "fence_status" + ] + }, + { + "properties": { + "head_status": { + "const": "stale" + } + }, + "required": [ + "head_status" + ] + } + ] + }, + { + "properties": { + "certainty": { + "const": "not_applicable" + } + }, + "required": [ + "certainty" + ] + } + ] + }, + "then": { + "properties": { + "state": { + "const": "abandoned" + }, + "next_action": { + "const": "abandon" + }, + "reconciliation_authority": { + "type": "null" + } + } + } + }, + { + "if": { + "allOf": [ + { + "anyOf": [ + { + "properties": { + "fence_status": { + "const": "stale" + } + }, + "required": [ + "fence_status" + ] + }, + { + "properties": { + "head_status": { + "const": "stale" + } + }, + "required": [ + "head_status" + ] + } + ] + }, + { + "properties": { + "certainty": { + "enum": [ + "unknown", + "confirmed_success", + "confirmed_failure" + ] + } + }, + "required": [ + "certainty" + ] + } + ] + }, + "then": { + "properties": { + "reconciliation_authority": { + "$ref": "#/$defs/reconciliation_authority" + } + } + } + } + ] + }, + "projection": { + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "event_type", + "observed_at", + "tenant_id", + "repository_id", + "work_id", + "action_id", + "provider_id", + "role", + "state", + "reason", + "attempt_count", + "elapsed_seconds", + "spend_usd" + ], + "properties": { + "schema": { + "const": "code_mower.operatorProjection.v1" + }, + "event_type": { + "enum": [ + "work_state", + "lease_state", + "action_state", + "owner_action", + "qualification_state" + ] + }, + "observed_at": { + "$ref": "#/$defs/timestamp" + }, + "tenant_id": { + "$ref": "#/$defs/opaque_id" + }, + "repository_id": { + "$ref": "#/$defs/opaque_id" + }, + "work_id": { + "oneOf": [ + { + "$ref": "#/$defs/opaque_id" + }, + { + "type": "null" + } + ] + }, + "action_id": { + "oneOf": [ + { + "$ref": "#/$defs/opaque_id" + }, + { + "type": "null" + } + ] + }, + "provider_id": { + "oneOf": [ + { + "$ref": "#/$defs/opaque_id" + }, + { + "type": "null" + } + ] + }, + "role": { + "oneOf": [ + { + "enum": [ + "orchestrator", + "builder", + "reviewer", + "merge_authority" + ] + }, + { + "type": "null" + } + ] + }, + "state": { + "enum": [ + "observed", + "admitted", + "claimed", + "executing", + "waiting_provider", + "reconciling", + "awaiting_review", + "awaiting_owner", + "completed", + "failed", + "cancelled", + "active", + "expired", + "released", + "prepared", + "dispatched", + "succeeded", + "uncertain", + "abandoned", + "qualified", + "pending", + "stale" + ] + }, + "reason": { + "enum": [ + "none", + "approval_required", + "budget_exhausted", + "capability_unqualified", + "credentials_unavailable", + "policy_denied", + "reconciliation_inconclusive", + "repository_not_allowed", + "stale_head", + "stale_lease", + "user_input_required", + "work_completed", + "work_failed", + "owner_cancelled", + "lease_acquired", + "lease_renewed", + "lease_expired", + "lease_released", + "dispatch_prepared", + "dispatch_started", + "remote_success", + "remote_failure", + "remote_unknown", + "reconciliation_started", + "reconciled_success", + "reconciled_failure", + "evidence_current", + "evidence_missing", + "evidence_failed", + "evidence_stale", + "capability_missing", + "human_merge_required" + ] + }, + "attempt_count": { + "type": "integer", + "minimum": 0, + "maximum": 5 + }, + "elapsed_seconds": { + "type": "integer", + "minimum": 0, + "maximum": 604800 + }, + "spend_usd": { + "type": "string", + "pattern": "^(0|[1-9][0-9]{0,5})\\.[0-9]{2}$", + "maxLength": 9 + } + }, + "oneOf": [ + { + "properties": { + "event_type": { + "const": "work_state" + }, + "work_id": { + "$ref": "#/$defs/opaque_id" + }, + "action_id": { + "type": "null" + }, + "provider_id": { + "type": "null" + }, + "role": { + "type": "null" + }, + "state": { + "enum": [ + "observed", + "admitted", + "claimed", + "executing", + "waiting_provider", + "reconciling", + "awaiting_review", + "awaiting_owner", + "completed", + "failed", + "cancelled" + ] + }, + "reason": { + "enum": [ + "none", + "approval_required", + "budget_exhausted", + "capability_unqualified", + "credentials_unavailable", + "policy_denied", + "reconciliation_inconclusive", + "repository_not_allowed", + "stale_head", + "stale_lease", + "user_input_required", + "work_completed", + "work_failed", + "owner_cancelled" + ] + } + }, + "allOf": [ + { + "if": { + "properties": { + "state": { + "const": "observed" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "none" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "admitted" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "none" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "claimed" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "none" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "executing" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "none" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "waiting_provider" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "none" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "reconciling" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "none" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "awaiting_review" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "none" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "awaiting_owner" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "enum": [ + "approval_required", + "budget_exhausted", + "capability_unqualified", + "credentials_unavailable", + "policy_denied", + "reconciliation_inconclusive", + "repository_not_allowed", + "stale_head", + "stale_lease", + "user_input_required" + ] + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "completed" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "work_completed" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "failed" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "work_failed" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "cancelled" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "owner_cancelled" + } + } + } + } + ] + }, + { + "properties": { + "event_type": { + "const": "lease_state" + }, + "work_id": { + "type": "null" + }, + "action_id": { + "type": "null" + }, + "provider_id": { + "type": "null" + }, + "role": { + "type": "null" + }, + "state": { + "enum": [ + "active", + "expired", + "released" + ] + }, + "reason": { + "enum": [ + "lease_acquired", + "lease_renewed", + "lease_expired", + "lease_released" + ] + } + }, + "allOf": [ + { + "if": { + "properties": { + "state": { + "const": "active" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "enum": [ + "lease_acquired", + "lease_renewed" + ] + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "expired" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "lease_expired" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "released" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "lease_released" + } + } + } + } + ] + }, + { + "properties": { + "event_type": { + "const": "action_state" + }, + "work_id": { + "$ref": "#/$defs/opaque_id" + }, + "action_id": { + "$ref": "#/$defs/opaque_id" + }, + "state": { + "enum": [ + "prepared", + "dispatched", + "succeeded", + "failed", + "uncertain", + "reconciling", + "abandoned" + ] + }, + "reason": { + "enum": [ + "dispatch_prepared", + "dispatch_started", + "remote_success", + "remote_failure", + "remote_unknown", + "reconciliation_started", + "reconciled_success", + "reconciled_failure", + "stale_head", + "stale_lease", + "owner_cancelled" + ] + }, + "provider_id": { + "$ref": "#/$defs/opaque_id" + }, + "role": { + "enum": [ + "orchestrator", + "builder", + "reviewer", + "merge_authority" + ] + } + }, + "allOf": [ + { + "if": { + "properties": { + "state": { + "const": "prepared" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "dispatch_prepared" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "dispatched" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "dispatch_started" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "succeeded" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "enum": [ + "remote_success", + "reconciled_success" + ] + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "failed" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "enum": [ + "remote_failure", + "reconciled_failure" + ] + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "uncertain" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "remote_unknown" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "reconciling" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "reconciliation_started" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "abandoned" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "enum": [ + "stale_head", + "stale_lease", + "owner_cancelled" + ] + } + } + } + } + ] + }, + { + "properties": { + "event_type": { + "const": "owner_action" + }, + "work_id": { + "$ref": "#/$defs/opaque_id" + }, + "provider_id": { + "type": "null" + }, + "role": { + "type": "null" + }, + "state": { + "enum": [ + "awaiting_owner", + "cancelled" + ] + }, + "reason": { + "enum": [ + "approval_required", + "budget_exhausted", + "capability_unqualified", + "credentials_unavailable", + "policy_denied", + "reconciliation_inconclusive", + "repository_not_allowed", + "stale_head", + "stale_lease", + "user_input_required", + "owner_cancelled" + ] + }, + "action_id": { + "type": "null" + } + }, + "allOf": [ + { + "if": { + "properties": { + "state": { + "const": "awaiting_owner" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "enum": [ + "approval_required", + "budget_exhausted", + "capability_unqualified", + "credentials_unavailable", + "policy_denied", + "reconciliation_inconclusive", + "repository_not_allowed", + "stale_head", + "stale_lease", + "user_input_required" + ] + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "cancelled" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "owner_cancelled" + } + } + } + } + ] + }, + { + "properties": { + "event_type": { + "const": "qualification_state" + }, + "work_id": { + "type": "null" + }, + "action_id": { + "type": "null" + }, + "provider_id": { + "$ref": "#/$defs/opaque_id" + }, + "role": { + "enum": [ + "orchestrator", + "builder", + "reviewer", + "merge_authority" + ] + }, + "state": { + "enum": [ + "qualified", + "pending", + "failed", + "stale" + ] + }, + "reason": { + "enum": [ + "evidence_current", + "evidence_missing", + "evidence_failed", + "evidence_stale", + "capability_missing", + "human_merge_required" + ] + } + }, + "allOf": [ + { + "if": { + "properties": { + "state": { + "const": "qualified" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "evidence_current" + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "pending" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "enum": [ + "evidence_missing", + "human_merge_required" + ] + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "failed" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "enum": [ + "evidence_failed", + "capability_missing" + ] + } + } + } + }, + { + "if": { + "properties": { + "state": { + "const": "stale" + } + }, + "required": [ + "state" + ] + }, + "then": { + "properties": { + "reason": { + "const": "evidence_stale" + } + } + } + } + ] + } + ] + }, + "reconciliation_authority": { + "type": "object", + "additionalProperties": false, + "required": [ + "lease_epoch", + "fence_token", + "fence_status" + ], + "properties": { + "lease_epoch": { + "type": "integer", + "minimum": 1, + "maximum": 9007199254740991 + }, + "fence_token": { + "$ref": "#/$defs/digest" + }, + "fence_status": { + "const": "current" + } + } + } + } +} diff --git a/src/code_mower/package_manifest.py b/src/code_mower/package_manifest.py index 6a88b71f..8bc18f54 100644 --- a/src/code_mower/package_manifest.py +++ b/src/code_mower/package_manifest.py @@ -341,6 +341,10 @@ ("src/code_mower/review_authority.py", "src/code_mower/review_authority.py", "core"), ("src/code_mower/provider_capabilities.py", "src/code_mower/provider_capabilities.py", "core"), ("src/code_mower/provider_capabilities.schema.json", "src/code_mower/provider_capabilities.schema.json", "schema"), + ("src/code_mower/operator_contract_v1.py", "src/code_mower/operator_contract_v1.py", "core"), + ("src/code_mower/operator_policy_v1.schema.json", "src/code_mower/operator_policy_v1.schema.json", "schema"), + ("src/code_mower/operator_state_v1.schema.json", "src/code_mower/operator_state_v1.schema.json", "schema"), + ("src/code_mower/operator_contract_v1.fixtures.json", "src/code_mower/operator_contract_v1.fixtures.json", "template"), ("src/code_mower/session.py", "src/code_mower/session.py", "core"), ("src/code_mower/remote_session.py", "src/code_mower/remote_session.py", "core"), ("src/code_mower/devin_review.py", "src/code_mower/devin_review.py", "core"), @@ -665,6 +669,7 @@ ("docs/commercial-boundary.md", "docs/commercial-boundary.md", "doc"), ("docs/public-release-checklist.md", "docs/public-release-checklist.md", "doc"), ("docs/operational-evidence.md", "docs/operational-evidence.md", "doc"), + ("docs/operator-contract-v1.md", "docs/operator-contract-v1.md", "doc"), ("docs/release-qualification.md", "docs/release-qualification.md", "doc"), ("docs/github-setup.md", "docs/github-setup.md", "doc"), ("docs/local-audit-runner.md", "docs/local-audit-runner.md", "doc"), diff --git a/tests/test_operator_contract_v1.py b/tests/test_operator_contract_v1.py new file mode 100644 index 00000000..271949f4 --- /dev/null +++ b/tests/test_operator_contract_v1.py @@ -0,0 +1,1052 @@ +from __future__ import annotations + +import copy +import json +import re +import unittest +from pathlib import Path +from typing import Any + +from code_mower.operator_contract_v1 import ( + action_intent_semantic_errors, + lease_semantic_errors, + policy_binding_errors, + qualification_semantic_errors, + recovery_transition_errors, +) + + +ROOT = Path(__file__).resolve().parents[1] +PACKAGE = ROOT / "src" / "code_mower" +DOC = ROOT / "docs" / "operator-contract-v1.md" +FIXTURE_PATH = PACKAGE / "operator_contract_v1.fixtures.json" +SCHEMA_PATHS = { + "operator_policy_v1.schema.json": PACKAGE / "operator_policy_v1.schema.json", + "operator_state_v1.schema.json": PACKAGE / "operator_state_v1.schema.json", +} + + +def _same_json_value(left: object, right: object) -> bool: + if isinstance(left, bool) or isinstance(right, bool): + return type(left) is type(right) and left == right + return left == right + + +def _resolve(root: dict[str, Any], reference: str) -> dict[str, Any]: + if not reference.startswith("#/"): + raise AssertionError(f"test validator only accepts local references: {reference}") + value: Any = root + for part in reference[2:].split("/"): + value = value[part.replace("~1", "/").replace("~0", "~")] + if not isinstance(value, dict): + raise AssertionError(f"schema reference is not an object: {reference}") + return value + + +def _type_matches(value: object, expected: str) -> bool: + return { + "array": isinstance(value, list), + "boolean": isinstance(value, bool), + "integer": isinstance(value, int) and not isinstance(value, bool), + "null": value is None, + "number": isinstance(value, (int, float)) and not isinstance(value, bool), + "object": isinstance(value, dict), + "string": isinstance(value, str), + }[expected] + + +def _errors( + value: object, + schema: dict[str, Any], + root: dict[str, Any], + path: str = "$", +) -> list[str]: + if "$ref" in schema: + return _errors(value, _resolve(root, schema["$ref"]), root, path) + + errors: list[str] = [] + if "oneOf" in schema: + matches = [ + not _errors(value, branch, root, path) + for branch in schema["oneOf"] + ] + if sum(matches) != 1: + errors.append(f"{path}: expected exactly one oneOf branch, got {sum(matches)}") + if "anyOf" in schema and not any( + not _errors(value, branch, root, path) for branch in schema["anyOf"] + ): + errors.append(f"{path}: did not match anyOf") + for branch in schema.get("allOf", []): + errors.extend(_errors(value, branch, root, path)) + condition = schema.get("if") + if isinstance(condition, dict) and not _errors(value, condition, root, path): + then = schema.get("then") + if isinstance(then, dict): + errors.extend(_errors(value, then, root, path)) + + if "const" in schema and not _same_json_value(value, schema["const"]): + errors.append(f"{path}: value differs from const") + if "enum" in schema and not any( + _same_json_value(value, candidate) for candidate in schema["enum"] + ): + errors.append(f"{path}: value is outside enum") + + expected_type = schema.get("type") + if isinstance(expected_type, str) and not _type_matches(value, expected_type): + errors.append(f"{path}: expected {expected_type}") + return errors + + if isinstance(value, dict): + required = schema.get("required", []) + for key in required: + if key not in value: + errors.append(f"{path}: missing required property {key}") + properties = schema.get("properties", {}) + if schema.get("additionalProperties") is False: + for key in sorted(set(value) - set(properties)): + errors.append(f"{path}: unexpected property {key}") + for key, child_schema in properties.items(): + if key in value: + errors.extend(_errors(value[key], child_schema, root, f"{path}.{key}")) + + if isinstance(value, list): + if "minItems" in schema and len(value) < schema["minItems"]: + errors.append(f"{path}: too few items") + if "maxItems" in schema and len(value) > schema["maxItems"]: + errors.append(f"{path}: too many items") + if schema.get("uniqueItems"): + encoded = [json.dumps(item, sort_keys=True) for item in value] + if len(encoded) != len(set(encoded)): + errors.append(f"{path}: items are not unique") + item_schema = schema.get("items") + if isinstance(item_schema, dict): + for index, item in enumerate(value): + errors.extend(_errors(item, item_schema, root, f"{path}[{index}]")) + + if isinstance(value, str): + if "minLength" in schema and len(value) < schema["minLength"]: + errors.append(f"{path}: string is too short") + if "maxLength" in schema and len(value) > schema["maxLength"]: + errors.append(f"{path}: string is too long") + if "pattern" in schema and re.search(schema["pattern"], value) is None: + errors.append(f"{path}: string does not match pattern") + + if isinstance(value, (int, float)) and not isinstance(value, bool): + if "minimum" in schema and value < schema["minimum"]: + errors.append(f"{path}: value is below minimum") + if "maximum" in schema and value > schema["maximum"]: + errors.append(f"{path}: value is above maximum") + return errors + + +class OperatorContractV1Tests(unittest.TestCase): + @classmethod + def setUpClass(cls) -> None: + cls.schemas = { + name: json.loads(path.read_text(encoding="utf-8")) + for name, path in SCHEMA_PATHS.items() + } + cls.fixtures = json.loads(FIXTURE_PATH.read_text(encoding="utf-8")) + + def _validate(self, schema_name: str, document: object) -> list[str]: + schema = self.schemas[schema_name] + return _errors(document, schema, schema) + + def _semantic_errors( + self, + document: dict[str, Any], + context: dict[str, Any] | None, + ) -> tuple[str, ...]: + context = context or {} + if document.get("schema") == "code_mower.operatorQualification.v1": + policy = next( + case["document"] + for case in self.fixtures["accepted"] + if case["name"] == "single_tenant_manual_merge_policy" + ) + return qualification_semantic_errors( + document, + max_evidence_age_seconds=policy["qualification"]["max_evidence_age_seconds"], + now=context.get("now", 2_000_000_100), + ) + if document.get("schema") == "code_mower.operatorPolicy.v1": + return () + policy = copy.deepcopy( + next( + case["document"] + for case in self.fixtures["accepted"] + if case["name"] == "single_tenant_manual_merge_policy" + ) + ) + removed_mutation = context.get("policy_remove_mutation") + if isinstance(removed_mutation, str): + policy["authority"]["mutations"].remove(removed_mutation) + return policy_binding_errors( + policy, + document, + current_work_generation=context.get("current_work_generation"), + current_lease=context.get("current_lease"), + current_head_sha=context.get("current_head_sha"), + now=context.get("now"), + ) + + def test_schemas_are_versioned_and_every_object_definition_is_closed(self) -> None: + self.assertEqual( + {schema["$id"] for schema in self.schemas.values()}, + {"code_mower.operator_policy.v1", "code_mower.operator_state.v1"}, + ) + for name, schema in self.schemas.items(): + with self.subTest(schema=name): + self.assertEqual(schema["$schema"], "https://json-schema.org/draft/2020-12/schema") + stack: list[object] = [schema] + while stack: + current = stack.pop() + if isinstance(current, dict): + if current.get("type") == "object": + self.assertIs( + current.get("additionalProperties"), + False, + f"open object in {name}: {current}", + ) + stack.extend(current.values()) + elif isinstance(current, list): + stack.extend(current) + + def test_all_canonical_accepted_fixtures_validate(self) -> None: + self.assertEqual(self.fixtures["schema"], "code_mower.operatorContractFixtures.v1") + self.assertEqual(self.fixtures["contract"], "code_mower.operator.v1") + self.assertEqual( + set(self.fixtures), + { + "schema", + "contract", + "accepted", + "rejected", + "failure_scenarios", + "rejected_transitions", + }, + ) + names: set[str] = set() + for case in self.fixtures["accepted"]: + with self.subTest(case=case["name"]): + self.assertEqual( + set(case), + {"name", "contract_schema", "document"} + | ({"semantic_context"} if "semantic_context" in case else set()), + ) + self.assertNotIn(case["name"], names) + names.add(case["name"]) + self.assertEqual( + self._validate(case["contract_schema"], case["document"]), + [], + ) + self.assertEqual( + self._semantic_errors(case["document"], case.get("semantic_context")), + (), + ) + + def test_all_canonical_rejected_fixtures_fail_validation(self) -> None: + names: set[str] = set() + for case in self.fixtures["rejected"]: + with self.subTest(case=case["name"]): + self.assertEqual( + set(case), + {"name", "contract_schema", "expected_violation", "document"} + | ({"semantic_context"} if "semantic_context" in case else set()), + ) + self.assertNotIn(case["name"], names) + names.add(case["name"]) + self.assertTrue(case["expected_violation"]) + schema_errors = self._validate(case["contract_schema"], case["document"]) + semantic_errors = self._semantic_errors( + case["document"], + case.get("semantic_context"), + ) + self.assertTrue( + schema_errors or semantic_errors, + f"rejected fixture unexpectedly validated: {case['name']}", + ) + + def test_provider_qualification_is_data_driven_and_fail_closed(self) -> None: + qualification = self.schemas["operator_policy_v1.schema.json"]["$defs"]["qualification"] + self.assertEqual(qualification["properties"]["provider_id"], {"$ref": "#/$defs/opaque_id"}) + + pending = next( + case["document"] + for case in self.fixtures["accepted"] + if case["name"] == "devin_builder_pending_without_exclusion" + ) + future_provider = copy.deepcopy(pending) + future_provider["provider_id"] = "future_provider" + future_provider["transport_id"] = "future_transport" + self.assertEqual( + self._validate("operator_policy_v1.schema.json", future_provider), + [], + ) + self.assertEqual(future_provider["decision"], "denied") + + initial = { + case["document"]["provider_id"] + for case in self.fixtures["accepted"] + if case["document"].get("schema") == "code_mower.operatorQualification.v1" + and case["document"]["status"] == "qualified" + } + self.assertEqual(initial, {"codex", "claude"}) + supervisors = { + case["document"]["provider_id"] + for case in self.fixtures["accepted"] + if case["document"].get("schema") == "code_mower.operatorQualification.v1" + and case["document"]["role"] == "orchestrator" + and case["document"]["status"] == "qualified" + } + self.assertEqual(supervisors, {"codex", "claude"}) + + def test_policy_keeps_human_merge_and_bounded_lease_cadence(self) -> None: + policy = next( + case["document"] + for case in self.fixtures["accepted"] + if case["name"] == "single_tenant_manual_merge_policy" + ) + authority = policy["authority"] + self.assertEqual(authority["merge_approval"], "human_required") + self.assertIs(authority["operator_merge"], False) + self.assertIn("merge_pull_request", authority["denied"]) + self.assertLess( + policy["budgets"]["lease_renewal_seconds"], + policy["budgets"]["lease_ttl_seconds"], + ) + + def test_failure_fixtures_execute_required_and_forbidden_recovery_transitions(self) -> None: + scenarios = {case["name"]: case for case in self.fixtures["failure_scenarios"]} + for case in scenarios.values(): + self.assertEqual(set(case), {"name", "before", "after", "forbidden_afters"}) + for phase in ("before", "after"): + for record in case[phase]: + self.assertEqual(set(record), {"contract_schema", "document"}) + self.assertEqual( + self._validate(record["contract_schema"], record["document"]), + [], + f"{case['name']} {phase} contains an invalid contract record", + ) + for forbidden in case["forbidden_afters"]: + self.assertEqual(set(forbidden), {"name", "records"}) + self.assertTrue(forbidden["name"]) + for record in forbidden["records"]: + self.assertEqual(set(record), {"contract_schema", "document"}) + self.assertEqual( + self._validate(record["contract_schema"], record["document"]), + [], + f"{case['name']} {forbidden['name']} is not shape-valid", + ) + self.assertEqual( + set(scenarios), + { + "restart_after_dispatch", + "duplicate_delivery", + "lease_takeover", + "stale_head", + "provider_timeout", + "partial_success", + "budget_exhaustion", + "owner_escalation_redelivery", + "owner_stop", + }, + ) + for name, case in scenarios.items(): + before = [record["document"] for record in case["before"]] + after = [record["document"] for record in case["after"]] + with self.subTest(case=name, outcome="required"): + self.assertEqual(recovery_transition_errors(name, before, after), ()) + for forbidden_case in case["forbidden_afters"]: + forbidden = [record["document"] for record in forbidden_case["records"]] + with self.subTest(case=name, outcome=forbidden_case["name"]): + self.assertTrue(recovery_transition_errors(name, before, forbidden)) + + for case in self.fixtures["rejected_transitions"]: + self.assertEqual( + set(case), + {"name", "event", "expected_violation", "before", "after"}, + ) + for phase in ("before", "after"): + for record in case[phase]: + self.assertEqual( + self._validate(record["contract_schema"], record["document"]), + [], + f"{case['name']} {phase} is not shape-valid", + ) + before = [record["document"] for record in case["before"]] + after = [record["document"] for record in case["after"]] + with self.subTest(case=case["name"]): + self.assertTrue(recovery_transition_errors(case["event"], before, after)) + + def test_takeover_after_unknown_preserves_dispatch_fence_and_uses_current_reconciler(self) -> None: + intent = next( + case["document"] + for case in self.fixtures["accepted"] + if case["name"] == "takeover_reconciles_unknown_without_redispatch" + ) + self.assertEqual(intent["lease_epoch"], 8) + self.assertEqual(intent["fence_status"], "stale") + self.assertEqual(intent["reconciliation_authority"]["lease_epoch"], 9) + self.assertEqual(intent["certainty"], "unknown") + self.assertEqual(intent["next_action"], "reconcile") + + def test_original_and_takeover_retry_authority_matrix_is_exact(self) -> None: + accepted_names = { + "confirmed_failure_retries_under_original_authority", + "takeover_confirmed_failure_retries_under_current_authority", + } + rejected_names = { + "original_holder_retry_rejects_takeover_lease", + "takeover_retry_rejects_wrong_reconciliation_authority", + } + for case in self.fixtures["accepted"]: + if case["name"] in accepted_names: + with self.subTest(case=case["name"]): + self.assertEqual( + self._semantic_errors(case["document"], case["semantic_context"]), + (), + ) + for case in self.fixtures["rejected"]: + if case["name"] in rejected_names: + with self.subTest(case=case["name"]): + self.assertTrue( + self._semantic_errors(case["document"], case["semantic_context"]) + ) + self.assertEqual( + accepted_names, + {case["name"] for case in self.fixtures["accepted"]} & accepted_names, + ) + self.assertEqual( + rejected_names, + {case["name"] for case in self.fixtures["rejected"]} & rejected_names, + ) + + def test_owner_stop_reasons_and_escalation_identity_are_aligned(self) -> None: + policy = next( + case["document"] + for case in self.fixtures["accepted"] + if case["name"] == "single_tenant_manual_merge_policy" + ) + self.assertTrue({"stale_head", "stale_lease"}.issubset(policy["owner_action"]["stop_reasons"])) + work = next( + case["document"] + for case in self.fixtures["accepted"] + if case["name"] == "work_waiting_for_owner_after_budget_exhaustion" + ) + self.assertEqual(len(work["owner_escalation_key"]), 64) + + def test_intent_generation_is_bound_to_current_work_generation(self) -> None: + current = next( + case["document"] + for case in self.fixtures["accepted"] + if case["name"] == "durable_intent_precedes_dispatch" + ) + context = next( + case["semantic_context"] + for case in self.fixtures["accepted"] + if case["name"] == "durable_intent_precedes_dispatch" + ) + self.assertEqual( + action_intent_semantic_errors( + current, + current_work_generation=4, + current_lease=context["current_lease"], + current_head_sha=context["current_head_sha"], + now=context["now"], + ), + (), + ) + self.assertTrue( + action_intent_semantic_errors( + current, + current_work_generation=5, + current_lease=context["current_lease"], + current_head_sha=context["current_head_sha"], + now=context["now"], + ) + ) + + def test_mutation_authority_matrix_fails_closed(self) -> None: + cases = [ + case + for case in self.fixtures["accepted"] + if case["document"].get("schema") == "code_mower.operatorActionIntent.v1" + and case["document"].get("next_action") != "abandon" + ] + for case in cases: + intent = case["document"] + context = case["semantic_context"] + kwargs = { + "current_work_generation": context["current_work_generation"], + "current_lease": context["current_lease"], + "current_head_sha": context["current_head_sha"], + "now": context["now"], + } + with self.subTest(case=case["name"], mutation="baseline"): + self.assertEqual(action_intent_semantic_errors(intent, **kwargs), ()) + with self.subTest(case=case["name"], mutation="generation"): + changed = dict(kwargs, current_work_generation=5) + self.assertTrue(action_intent_semantic_errors(intent, **changed)) + for field, value in ( + ("tenant_id", "tenant_other"), + ("repository_id", "repository_other"), + ("lease_id", "operator_other"), + ("schema", "code_mower.operatorProjection.v1"), + ("epoch", context["current_lease"]["epoch"] + 1), + ("fence_token", "a" * 64), + ("state", "expired"), + ("renew_by", context["now"]), + ): + changed_lease = copy.deepcopy(context["current_lease"]) + changed_lease[field] = value + changed = dict(kwargs, current_lease=changed_lease) + with self.subTest(case=case["name"], mutation=f"lease.{field}"): + self.assertTrue(action_intent_semantic_errors(intent, **changed)) + if intent["next_action"] in {"dispatch", "retry"} or intent["certainty"] in { + "confirmed_success", + "confirmed_failure", + }: + with self.subTest(case=case["name"], mutation="head"): + changed = dict(kwargs, current_head_sha="f" * 40) + self.assertTrue(action_intent_semantic_errors(intent, **changed)) + + def test_policy_binding_matrix_enforces_record_level_ceilings(self) -> None: + policy = next( + case["document"] + for case in self.fixtures["accepted"] + if case["name"] == "single_tenant_manual_merge_policy" + ) + action_case = next( + case + for case in self.fixtures["accepted"] + if case["name"] == "durable_intent_precedes_dispatch" + ) + action = action_case["document"] + context = action_case["semantic_context"] + + def action_errors(document: dict[str, Any], selected_policy: dict[str, Any] = policy): + return policy_binding_errors( + selected_policy, + document, + current_work_generation=context["current_work_generation"], + current_lease=context["current_lease"], + current_head_sha=context["current_head_sha"], + now=context["now"], + ) + + self.assertEqual(action_errors(action), ()) + for field, ceiling in ( + ("attempt_count", "max_attempts_per_action"), + ("reconciliation_count", "max_reconciliations_per_action"), + ("elapsed_seconds", "max_action_seconds"), + ): + changed = copy.deepcopy(action) + changed["budget"][field] = policy["budgets"][ceiling] + 1 + with self.subTest(record="action", ceiling=ceiling): + self.assertTrue(action_errors(changed)) + changed = copy.deepcopy(action) + changed["budget"]["spend_usd"] = "25.01" + self.assertTrue(action_errors(changed)) + changed_policy = copy.deepcopy(policy) + changed_policy["authority"]["mutations"].remove(action["operation"]) + self.assertTrue(action_errors(action, changed_policy)) + + work = next( + case["document"] + for case in self.fixtures["accepted"] + if case["name"] == "work_waiting_for_owner_after_budget_exhaustion" + ) + for field, value in ( + ("owner_escalation_count", policy["budgets"]["max_owner_escalations"] + 1), + ("elapsed_seconds", policy["budgets"]["max_work_seconds"] + 1), + ("spend_usd", "25.01"), + ): + changed = copy.deepcopy(work) + changed[field] = value + with self.subTest(record="work", ceiling=field): + self.assertTrue(policy_binding_errors(policy, changed)) + + lease = next( + case["document"] + for case in self.fixtures["accepted"] + if case["name"] == "singleton_lease_with_fencing_epoch" + ) + self.assertEqual(policy_binding_errors(policy, lease), ()) + for renew_delta, expiry_delta in ((0, 1), (50, 50), (-10, -10)): + changed = copy.deepcopy(lease) + changed["renew_by"] += renew_delta + changed["expires_at"] += expiry_delta + with self.subTest( + record="lease", + renew_delta=renew_delta, + expiry_delta=expiry_delta, + ): + self.assertTrue(policy_binding_errors(policy, changed)) + + def test_recovery_matrix_rejects_scope_chronology_and_all_counter_rollbacks(self) -> None: + for case in self.fixtures["failure_scenarios"]: + before = [copy.deepcopy(item["document"]) for item in case["before"]] + after = [copy.deepcopy(item["document"]) for item in case["after"]] + self.assertEqual(recovery_transition_errors(case["name"], before, after), ()) + before_by_schema = {item["schema"]: item for item in before} + after_by_schema = {item["schema"]: item for item in after} + action_schema = "code_mower.operatorActionIntent.v1" + if action_schema in before_by_schema and action_schema in after_by_schema: + for field, old_value, new_value in ( + ("attempt_count", 2, 1), + ("reconciliation_count", 2, 1), + ("elapsed_seconds", 2, 1), + ("spend_usd", "2.00", "1.00"), + ): + changed_before = copy.deepcopy(before) + changed_after = copy.deepcopy(after) + next(item for item in changed_before if item["schema"] == action_schema)["budget"][ + field + ] = old_value + next(item for item in changed_after if item["schema"] == action_schema)["budget"][ + field + ] = new_value + with self.subTest(case=case["name"], rollback=f"action.{field}"): + self.assertTrue( + recovery_transition_errors(case["name"], changed_before, changed_after) + ) + work_schema = "code_mower.operatorWorkItem.v1" + if work_schema in before_by_schema and work_schema in after_by_schema: + for field, old_value, new_value in ( + ("owner_escalation_count", 2, 1), + ("elapsed_seconds", 2, 1), + ("spend_usd", "2.00", "1.00"), + ): + changed_before = copy.deepcopy(before) + changed_after = copy.deepcopy(after) + next(item for item in changed_before if item["schema"] == work_schema)[field] = old_value + next(item for item in changed_after if item["schema"] == work_schema)[field] = new_value + with self.subTest(case=case["name"], rollback=f"work.{field}"): + self.assertTrue( + recovery_transition_errors(case["name"], changed_before, changed_after) + ) + + takeover = next( + case for case in self.fixtures["failure_scenarios"] if case["name"] == "lease_takeover" + ) + before = [item["document"] for item in takeover["before"]] + after = [item["document"] for item in takeover["after"]] + lease_index = next( + index + for index, item in enumerate(after) + if item["schema"] == "code_mower.operatorLease.v1" + ) + for field, value in ( + ("tenant_id", "tenant_other"), + ("repository_id", "repository_other"), + ("lease_id", "operator_other"), + ("holder_id", next(item for item in before if item["schema"] == "code_mower.operatorLease.v1")["holder_id"]), + ): + changed = copy.deepcopy(after) + changed[lease_index][field] = value + with self.subTest(case="lease_takeover", scope=field): + self.assertTrue(recovery_transition_errors("lease_takeover", before, changed)) + changed = copy.deepcopy(after) + changed[lease_index]["renew_by"] = changed[lease_index]["expires_at"] + 1 + self.assertTrue(recovery_transition_errors("lease_takeover", before, changed)) + + def test_lease_chronology_matrix_is_strict(self) -> None: + lease = next( + case["document"] + for case in self.fixtures["accepted"] + if case["name"] == "singleton_lease_with_fencing_epoch" + ) + self.assertEqual(lease_semantic_errors(lease), ()) + for acquired, renew, expires in ( + (10, 9, 11), + (10, 11, 11), + (10, 12, 11), + ): + changed = copy.deepcopy(lease) + changed.update({"acquired_at": acquired, "renew_by": renew, "expires_at": expires}) + self.assertTrue(lease_semantic_errors(changed)) + + def test_full_work_transition_matrix_matches_the_closed_state_machine(self) -> None: + state_schema = self.schemas["operator_state_v1.schema.json"] + transitions = state_schema["$defs"]["transition"]["enum"] + base = next( + case["document"] + for case in self.fixtures["accepted"] + if case["name"] == "work_waiting_for_owner_after_budget_exhaustion" + ) + terminal_reasons = { + "completed": "work_completed", + "failed": "work_failed", + "cancelled": "owner_cancelled", + } + for transition in transitions: + _, target = transition.split(":", 1) + document = copy.deepcopy(base) + document.update( + { + "state": target, + "terminal": target in terminal_reasons, + "last_transition": transition, + "reason": terminal_reasons.get( + target, + "approval_required" if target == "awaiting_owner" else "none", + ), + "owner_escalation_count": 1 if target == "awaiting_owner" else 0, + "owner_escalation_key": "9" * 64 if target == "awaiting_owner" else None, + } + ) + with self.subTest(transition=transition): + self.assertEqual( + self._validate("operator_state_v1.schema.json", document), + [], + ) + + def test_work_state_reason_matrix_is_closed(self) -> None: + state_schema = self.schemas["operator_state_v1.schema.json"] + states = state_schema["$defs"]["lifecycle_state"]["enum"] + reasons = state_schema["$defs"]["stop_reason"]["enum"] + transitions = state_schema["$defs"]["transition"]["enum"] + transition_by_target = { + target: transition + for transition in transitions + for _, target in [transition.split(":", 1)] + } + allowed = { + **{ + state: {"none"} + for state in states + if state + not in {"awaiting_owner", "completed", "failed", "cancelled"} + }, + "awaiting_owner": { + "approval_required", + "budget_exhausted", + "capability_unqualified", + "credentials_unavailable", + "policy_denied", + "reconciliation_inconclusive", + "repository_not_allowed", + "stale_head", + "stale_lease", + "user_input_required", + }, + "completed": {"work_completed"}, + "failed": {"work_failed"}, + "cancelled": {"owner_cancelled"}, + } + base = next( + case["document"] + for case in self.fixtures["accepted"] + if case["name"] == "work_waiting_for_owner_after_budget_exhaustion" + ) + for state in states: + for reason in reasons: + document = copy.deepcopy(base) + document.update( + state=state, + terminal=state in {"completed", "failed", "cancelled"}, + last_transition=None if state == "observed" else transition_by_target[state], + reason=reason, + owner_escalation_count=1 if state == "awaiting_owner" else 0, + owner_escalation_key="9" * 64 if state == "awaiting_owner" else None, + ) + valid = not self._validate("operator_state_v1.schema.json", document) + with self.subTest(state=state, reason=reason): + self.assertEqual(valid, reason in allowed[state]) + + def test_recovery_event_source_and_target_matrices_are_closed(self) -> None: + scenarios = {case["name"]: case for case in self.fixtures["failure_scenarios"]} + action_tuples = ( + ("prepared", "not_attempted", "not_required", "dispatch"), + ("dispatched", "unknown", "required", "reconcile"), + ("uncertain", "unknown", "required", "reconcile"), + ("reconciling", "unknown", "in_progress", "reconcile"), + ("succeeded", "confirmed_success", "matched_success", "none"), + ("failed", "confirmed_failure", "matched_failure", "retry"), + ("abandoned", "not_applicable", "not_required", "abandon"), + ) + expected_sources = { + "restart_after_dispatch": set(action_tuples[1:4]), + "stale_head": {action_tuples[0]}, + "provider_timeout": {action_tuples[0]}, + "partial_success": set(action_tuples[1:3]), + "lease_takeover": set(action_tuples[1:4]), + } + expected_targets = { + "restart_after_dispatch": {action_tuples[3]}, + "stale_head": {action_tuples[6]}, + "provider_timeout": {action_tuples[2]}, + "partial_success": {action_tuples[3]}, + "lease_takeover": {action_tuples[3]}, + } + action_schema = "code_mower.operatorActionIntent.v1" + for event, allowed in expected_sources.items(): + case = scenarios[event] + before = [copy.deepcopy(item["document"]) for item in case["before"]] + after = [copy.deepcopy(item["document"]) for item in case["after"]] + source = next(item for item in before if item["schema"] == action_schema) + for values in action_tuples: + source.update( + zip( + ("state", "certainty", "reconciliation", "next_action"), + values, + strict=True, + ) + ) + with self.subTest(event=event, source=values): + self.assertEqual( + not recovery_transition_errors(event, before, after), + values in allowed, + ) + # Restore the accepted source, then exhaust the destination tuple. + before = [copy.deepcopy(item["document"]) for item in case["before"]] + for values in action_tuples: + changed_after = [copy.deepcopy(item["document"]) for item in case["after"]] + target_action = next( + item for item in changed_after if item["schema"] == action_schema + ) + target_action.update( + zip( + ("state", "certainty", "reconciliation", "next_action"), + values, + strict=True, + ) + ) + with self.subTest(event=event, target=values): + self.assertEqual( + not recovery_transition_errors(event, before, changed_after), + values in expected_targets[event], + ) + + lifecycle = self.schemas["operator_state_v1.schema.json"]["$defs"]["lifecycle_state"]["enum"] + for event, allowed_sources, target in ( + ( + "budget_exhaustion", + {"admitted", "claimed", "executing", "waiting_provider", "reconciling", "awaiting_review"}, + "awaiting_owner", + ), + ( + "owner_stop", + { + "observed", + "admitted", + "claimed", + "executing", + "waiting_provider", + "reconciling", + "awaiting_review", + "awaiting_owner", + }, + "cancelled", + ), + ): + case = scenarios[event] + for source_state in lifecycle: + for target_state in lifecycle: + before = [copy.deepcopy(item["document"]) for item in case["before"]] + after = [copy.deepcopy(item["document"]) for item in case["after"]] + old_work = next(item for item in before if item["schema"].endswith("WorkItem.v1")) + new_work = next(item for item in after if item["schema"].endswith("WorkItem.v1")) + old_work["state"] = source_state + new_work["state"] = target_state + new_work["last_transition"] = f"{source_state}:{target_state}" + with self.subTest(event=event, source=source_state, target=target_state): + self.assertEqual( + not recovery_transition_errors(event, before, after), + source_state in allowed_sources and target_state == target, + ) + + def test_projection_event_state_reason_matrix_is_closed(self) -> None: + projection = self.schemas["operator_state_v1.schema.json"]["$defs"]["projection"] + events = projection["properties"]["event_type"]["enum"] + states = projection["properties"]["state"]["enum"] + reasons = projection["properties"]["reason"]["enum"] + stop_reasons = { + "approval_required", + "budget_exhausted", + "capability_unqualified", + "credentials_unavailable", + "policy_denied", + "reconciliation_inconclusive", + "repository_not_allowed", + "stale_head", + "stale_lease", + "user_input_required", + } + allowed = { + "work_state": { + **{ + state: {"none"} + for state in ( + "observed", + "admitted", + "claimed", + "executing", + "waiting_provider", + "reconciling", + "awaiting_review", + ) + }, + "awaiting_owner": stop_reasons, + "completed": {"work_completed"}, + "failed": {"work_failed"}, + "cancelled": {"owner_cancelled"}, + }, + "lease_state": { + "active": {"lease_acquired", "lease_renewed"}, + "expired": {"lease_expired"}, + "released": {"lease_released"}, + }, + "action_state": { + "prepared": {"dispatch_prepared"}, + "dispatched": {"dispatch_started"}, + "succeeded": {"remote_success", "reconciled_success"}, + "failed": {"remote_failure", "reconciled_failure"}, + "uncertain": {"remote_unknown"}, + "reconciling": {"reconciliation_started"}, + "abandoned": {"stale_head", "stale_lease", "owner_cancelled"}, + }, + "owner_action": { + "awaiting_owner": stop_reasons, + "cancelled": {"owner_cancelled"}, + }, + "qualification_state": { + "qualified": {"evidence_current"}, + "pending": {"evidence_missing", "human_merge_required"}, + "failed": {"evidence_failed", "capability_missing"}, + "stale": {"evidence_stale"}, + }, + } + base = next( + case["document"] + for case in self.fixtures["accepted"] + if case["name"] == "metadata_only_projection" + ) + identifiers = { + "work_state": ("work_1085", None, None, None), + "lease_state": (None, None, None, None), + "action_state": ("work_1085", "action_open_pr", "codex", "orchestrator"), + "owner_action": ("work_1085", None, None, None), + "qualification_state": (None, None, "codex", "reviewer"), + } + for event in events: + for state in states: + for reason in reasons: + document = copy.deepcopy(base) + document.update( + event_type=event, + state=state, + reason=reason, + ) + ( + document["work_id"], + document["action_id"], + document["provider_id"], + document["role"], + ) = identifiers[event] + valid = not self._validate("operator_state_v1.schema.json", document) + expected = reason in allowed[event].get(state, set()) + with self.subTest(event=event, state=state, reason=reason): + self.assertEqual(valid, expected) + + representative = { + event: next(iter(state_reasons.items())) + for event, state_reasons in allowed.items() + } + for event in events: + state, valid_reasons = representative[event] + reason = next(iter(valid_reasons)) + for identifier_shape, values in identifiers.items(): + document = copy.deepcopy(base) + document.update(event_type=event, state=state, reason=reason) + ( + document["work_id"], + document["action_id"], + document["provider_id"], + document["role"], + ) = values + with self.subTest(event=event, identifier_shape=identifier_shape): + self.assertEqual( + not self._validate("operator_state_v1.schema.json", document), + values == identifiers[event], + ) + + def test_full_lease_state_matrix_preserves_history_but_grants_only_live_authority(self) -> None: + lease = next( + case["document"] + for case in self.fixtures["accepted"] + if case["name"] == "singleton_lease_with_fencing_epoch" + ) + for state in ("active", "expired", "released"): + document = copy.deepcopy(lease) + document["state"] = state + with self.subTest(state=state, validation="history"): + self.assertEqual(lease_semantic_errors(document), ()) + with self.subTest(state=state, validation="authority"): + errors = lease_semantic_errors(document, now=document["acquired_at"], require_live=True) + if state == "active": + self.assertEqual(errors, ()) + else: + self.assertTrue(errors) + + def test_metadata_projection_is_exactly_the_policy_allowlist(self) -> None: + policy = next( + case["document"] + for case in self.fixtures["accepted"] + if case["name"] == "single_tenant_manual_merge_policy" + ) + projection = self.schemas["operator_state_v1.schema.json"]["$defs"]["projection"] + self.assertEqual( + set(projection["properties"]), + set(policy["privacy"]["projection_fields"]), + ) + forbidden = set(policy["privacy"]["excluded_content"]) + self.assertTrue( + { + "source", + "diffs", + "prompts", + "transcripts", + "issue_bodies", + "raw_provider_output", + "credentials", + "private_content", + }.issubset(forbidden) + ) + + def test_canonical_document_names_every_record_and_non_runtime_boundary(self) -> None: + text = DOC.read_text(encoding="utf-8") + for record in ( + "code_mower.operatorPolicy.v1", + "code_mower.operatorQualification.v1", + "code_mower.operatorWorkItem.v1", + "code_mower.operatorLease.v1", + "code_mower.operatorActionIntent.v1", + "code_mower.operatorProjection.v1", + ): + self.assertIn(record, text) + self.assertIn("always requires a human to approve and perform a merge", text) + self.assertIn("Active dispatch", text) + self.assertIn("does not change an existing Board, telemetry, or cloud schema", text) + + def test_contract_artifacts_are_in_package_and_document_inventory(self) -> None: + package_manifest = (PACKAGE / "package_manifest.py").read_text(encoding="utf-8") + for path in ( + "src/code_mower/operator_contract_v1.py", + "src/code_mower/operator_policy_v1.schema.json", + "src/code_mower/operator_state_v1.schema.json", + "src/code_mower/operator_contract_v1.fixtures.json", + "docs/operator-contract-v1.md", + ): + self.assertIn(path, package_manifest) + + project = (ROOT / "pyproject.toml").read_text(encoding="utf-8") + self.assertIn('"docs/operator-contract-v1.md"', project) + docs_manifest = (ROOT / "docs" / "docs-manifest.yml").read_text(encoding="utf-8") + self.assertIn("path: docs/operator-contract-v1.md", docs_manifest) + self.assertIn("subject: operator-contract", docs_manifest) + + +if __name__ == "__main__": + unittest.main()