agentversion 0.2.1__tar.gz → 0.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of agentversion might be problematic. Click here for more details.

Files changed (125) hide show
  1. {agentversion-0.2.1 → agentversion-0.2.2}/CHANGELOG.md +14 -0
  2. {agentversion-0.2.1 → agentversion-0.2.2}/PKG-INFO +1 -1
  3. {agentversion-0.2.1 → agentversion-0.2.2}/agentversion/diff.py +3 -3
  4. {agentversion-0.2.1 → agentversion-0.2.2}/agentversion/manifest.py +16 -11
  5. {agentversion-0.2.1 → agentversion-0.2.2}/pyproject.toml +1 -1
  6. agentversion-0.2.2/spec/behavioral-policy.md +56 -0
  7. agentversion-0.2.1/spec/behavioral-policy.md +0 -51
  8. {agentversion-0.2.1 → agentversion-0.2.2}/.github/dependabot.yml +0 -0
  9. {agentversion-0.2.1 → agentversion-0.2.2}/.github/workflows/ci.yml +0 -0
  10. {agentversion-0.2.1 → agentversion-0.2.2}/.github/workflows/publish.yml +0 -0
  11. {agentversion-0.2.1 → agentversion-0.2.2}/.gitignore +0 -0
  12. {agentversion-0.2.1 → agentversion-0.2.2}/CONFORMANCE.md +0 -0
  13. {agentversion-0.2.1 → agentversion-0.2.2}/CONTRIBUTING.md +0 -0
  14. {agentversion-0.2.1 → agentversion-0.2.2}/LICENSE +0 -0
  15. {agentversion-0.2.1 → agentversion-0.2.2}/README.md +0 -0
  16. {agentversion-0.2.1 → agentversion-0.2.2}/RELEASING.md +0 -0
  17. {agentversion-0.2.1 → agentversion-0.2.2}/adrs/0000-template.md +0 -0
  18. {agentversion-0.2.1 → agentversion-0.2.2}/adrs/0001-version-spec-core.md +0 -0
  19. {agentversion-0.2.1 → agentversion-0.2.2}/agentversion/__init__.py +0 -0
  20. {agentversion-0.2.1 → agentversion-0.2.2}/agentversion/_shared.py +0 -0
  21. {agentversion-0.2.1 → agentversion-0.2.2}/agentversion/a2a.py +0 -0
  22. {agentversion-0.2.1 → agentversion-0.2.2}/agentversion/cli.py +0 -0
  23. {agentversion-0.2.1 → agentversion-0.2.2}/agentversion/compatibility.py +0 -0
  24. {agentversion-0.2.1 → agentversion-0.2.2}/agentversion/constants.py +0 -0
  25. {agentversion-0.2.1 → agentversion-0.2.2}/agentversion/contract.py +0 -0
  26. {agentversion-0.2.1 → agentversion-0.2.2}/agentversion/dataset.py +0 -0
  27. {agentversion-0.2.1 → agentversion-0.2.2}/agentversion/decision.py +0 -0
  28. {agentversion-0.2.1 → agentversion-0.2.2}/agentversion/hasher.py +0 -0
  29. {agentversion-0.2.1 → agentversion-0.2.2}/agentversion/ids.py +0 -0
  30. {agentversion-0.2.1 → agentversion-0.2.2}/agentversion/py.typed +0 -0
  31. {agentversion-0.2.1 → agentversion-0.2.2}/agentversion/refs.py +0 -0
  32. {agentversion-0.2.1 → agentversion-0.2.2}/agentversion/replay.py +0 -0
  33. {agentversion-0.2.1 → agentversion-0.2.2}/agentversion/validator.py +0 -0
  34. {agentversion-0.2.1 → agentversion-0.2.2}/compatibility-tests/environment-region-change/after.json +0 -0
  35. {agentversion-0.2.1 → agentversion-0.2.2}/compatibility-tests/environment-region-change/before.json +0 -0
  36. {agentversion-0.2.1 → agentversion-0.2.2}/compatibility-tests/environment-region-change/expected-diff.json +0 -0
  37. {agentversion-0.2.1 → agentversion-0.2.2}/compatibility-tests/model-runtime-provider-change/after.json +0 -0
  38. {agentversion-0.2.1 → agentversion-0.2.2}/compatibility-tests/model-runtime-provider-change/before.json +0 -0
  39. {agentversion-0.2.1 → agentversion-0.2.2}/compatibility-tests/model-runtime-provider-change/expected-diff.json +0 -0
  40. {agentversion-0.2.1 → agentversion-0.2.2}/compatibility-tests/output-schema-change/after.json +0 -0
  41. {agentversion-0.2.1 → agentversion-0.2.2}/compatibility-tests/output-schema-change/before.json +0 -0
  42. {agentversion-0.2.1 → agentversion-0.2.2}/compatibility-tests/output-schema-change/expected-diff.json +0 -0
  43. {agentversion-0.2.1 → agentversion-0.2.2}/compatibility-tests/prompt-stack-edit/after.json +0 -0
  44. {agentversion-0.2.1 → agentversion-0.2.2}/compatibility-tests/prompt-stack-edit/before.json +0 -0
  45. {agentversion-0.2.1 → agentversion-0.2.2}/compatibility-tests/prompt-stack-edit/expected-diff.json +0 -0
  46. {agentversion-0.2.1 → agentversion-0.2.2}/compatibility-tests/skill-registry-skill-removed/after.json +0 -0
  47. {agentversion-0.2.1 → agentversion-0.2.2}/compatibility-tests/skill-registry-skill-removed/before.json +0 -0
  48. {agentversion-0.2.1 → agentversion-0.2.2}/compatibility-tests/skill-registry-skill-removed/expected-diff.json +0 -0
  49. {agentversion-0.2.1 → agentversion-0.2.2}/compatibility-tests/subagent-handoff-change/after.json +0 -0
  50. {agentversion-0.2.1 → agentversion-0.2.2}/compatibility-tests/subagent-handoff-change/before.json +0 -0
  51. {agentversion-0.2.1 → agentversion-0.2.2}/compatibility-tests/subagent-handoff-change/expected-diff.json +0 -0
  52. {agentversion-0.2.1 → agentversion-0.2.2}/compatibility-tests/tool-rename/after.json +0 -0
  53. {agentversion-0.2.1 → agentversion-0.2.2}/compatibility-tests/tool-rename/before.json +0 -0
  54. {agentversion-0.2.1 → agentversion-0.2.2}/compatibility-tests/tool-rename/expected-diff.json +0 -0
  55. {agentversion-0.2.1 → agentversion-0.2.2}/compatibility-tests/workflow-graph-change/after.json +0 -0
  56. {agentversion-0.2.1 → agentversion-0.2.2}/compatibility-tests/workflow-graph-change/before.json +0 -0
  57. {agentversion-0.2.1 → agentversion-0.2.2}/compatibility-tests/workflow-graph-change/expected-diff.json +0 -0
  58. {agentversion-0.2.1 → agentversion-0.2.2}/examples/.gitkeep +0 -0
  59. {agentversion-0.2.1 → agentversion-0.2.2}/examples/integrations/decimalai_bridge.py +0 -0
  60. {agentversion-0.2.1 → agentversion-0.2.2}/examples/integrations/langgraph_example.py +0 -0
  61. {agentversion-0.2.1 → agentversion-0.2.2}/examples/integrations/otel_mapping.md +0 -0
  62. {agentversion-0.2.1 → agentversion-0.2.2}/examples/manifest/finance-agent-v1.json +0 -0
  63. {agentversion-0.2.1 → agentversion-0.2.2}/examples/manifest/finance-agent-v2.json +0 -0
  64. {agentversion-0.2.1 → agentversion-0.2.2}/examples/scenarios/tool-rename-drift.md +0 -0
  65. {agentversion-0.2.1 → agentversion-0.2.2}/examples/scenarios/walkthrough.py +0 -0
  66. {agentversion-0.2.1 → agentversion-0.2.2}/pyrightconfig.json +0 -0
  67. {agentversion-0.2.1 → agentversion-0.2.2}/schemas/.gitkeep +0 -0
  68. {agentversion-0.2.1 → agentversion-0.2.2}/schemas/agent-manifest.schema.json +0 -0
  69. {agentversion-0.2.1 → agentversion-0.2.2}/schemas/compatibility-batch.schema.json +0 -0
  70. {agentversion-0.2.1 → agentversion-0.2.2}/schemas/compatibility-decision.schema.json +0 -0
  71. {agentversion-0.2.1 → agentversion-0.2.2}/schemas/compatibility-policy.schema.json +0 -0
  72. {agentversion-0.2.1 → agentversion-0.2.2}/schemas/compatibility-report.schema.json +0 -0
  73. {agentversion-0.2.1 → agentversion-0.2.2}/schemas/dataset-snapshot.schema.json +0 -0
  74. {agentversion-0.2.1 → agentversion-0.2.2}/schemas/episode.schema.json +0 -0
  75. {agentversion-0.2.1 → agentversion-0.2.2}/schemas/manifest-diff.schema.json +0 -0
  76. {agentversion-0.2.1 → agentversion-0.2.2}/schemas/replay-job.schema.json +0 -0
  77. {agentversion-0.2.1 → agentversion-0.2.2}/schemas/replay-result.schema.json +0 -0
  78. {agentversion-0.2.1 → agentversion-0.2.2}/schemas/step.schema.json +0 -0
  79. {agentversion-0.2.1 → agentversion-0.2.2}/schemas/task.schema.json +0 -0
  80. {agentversion-0.2.1 → agentversion-0.2.2}/scripts/release.sh +0 -0
  81. {agentversion-0.2.1 → agentversion-0.2.2}/spec/a2a-mapping.md +0 -0
  82. {agentversion-0.2.1 → agentversion-0.2.2}/spec/attestation.md +0 -0
  83. {agentversion-0.2.1 → agentversion-0.2.2}/spec/compatibility-batch.md +0 -0
  84. {agentversion-0.2.1 → agentversion-0.2.2}/spec/compatibility-decision.md +0 -0
  85. {agentversion-0.2.1 → agentversion-0.2.2}/spec/compatibility-policy.md +0 -0
  86. {agentversion-0.2.1 → agentversion-0.2.2}/spec/data-classification.md +0 -0
  87. {agentversion-0.2.1 → agentversion-0.2.2}/spec/dataset.md +0 -0
  88. {agentversion-0.2.1 → agentversion-0.2.2}/spec/diff.md +0 -0
  89. {agentversion-0.2.1 → agentversion-0.2.2}/spec/environment.md +0 -0
  90. {agentversion-0.2.1 → agentversion-0.2.2}/spec/evaluation.md +0 -0
  91. {agentversion-0.2.1 → agentversion-0.2.2}/spec/hashing.md +0 -0
  92. {agentversion-0.2.1 → agentversion-0.2.2}/spec/ids.md +0 -0
  93. {agentversion-0.2.1 → agentversion-0.2.2}/spec/lifecycle.md +0 -0
  94. {agentversion-0.2.1 → agentversion-0.2.2}/spec/manifest.md +0 -0
  95. {agentversion-0.2.1 → agentversion-0.2.2}/spec/otel-mapping.md +0 -0
  96. {agentversion-0.2.1 → agentversion-0.2.2}/spec/reference.md +0 -0
  97. {agentversion-0.2.1 → agentversion-0.2.2}/spec/refs.md +0 -0
  98. {agentversion-0.2.1 → agentversion-0.2.2}/spec/replay-determinism.md +0 -0
  99. {agentversion-0.2.1 → agentversion-0.2.2}/spec/replay.md +0 -0
  100. {agentversion-0.2.1 → agentversion-0.2.2}/spec/versioning-policy.md +0 -0
  101. {agentversion-0.2.1 → agentversion-0.2.2}/tests/fixtures/frozen_hash_vectors.json +0 -0
  102. {agentversion-0.2.1 → agentversion-0.2.2}/tests/test_a2a_mapping.py +0 -0
  103. {agentversion-0.2.1 → agentversion-0.2.2}/tests/test_audit_v020.py +0 -0
  104. {agentversion-0.2.1 → agentversion-0.2.2}/tests/test_audit_v030.py +0 -0
  105. {agentversion-0.2.1 → agentversion-0.2.2}/tests/test_behavioral_policy.py +0 -0
  106. {agentversion-0.2.1 → agentversion-0.2.2}/tests/test_cli.py +0 -0
  107. {agentversion-0.2.1 → agentversion-0.2.2}/tests/test_component_surface_map.py +0 -0
  108. {agentversion-0.2.1 → agentversion-0.2.2}/tests/test_conformance.py +0 -0
  109. {agentversion-0.2.1 → agentversion-0.2.2}/tests/test_contract.py +0 -0
  110. {agentversion-0.2.1 → agentversion-0.2.2}/tests/test_dataset.py +0 -0
  111. {agentversion-0.2.1 → agentversion-0.2.2}/tests/test_decision_replay.py +0 -0
  112. {agentversion-0.2.1 → agentversion-0.2.2}/tests/test_diff.py +0 -0
  113. {agentversion-0.2.1 → agentversion-0.2.2}/tests/test_environment.py +0 -0
  114. {agentversion-0.2.1 → agentversion-0.2.2}/tests/test_evaluation.py +0 -0
  115. {agentversion-0.2.1 → agentversion-0.2.2}/tests/test_examples_runnable.py +0 -0
  116. {agentversion-0.2.1 → agentversion-0.2.2}/tests/test_extension_hatch.py +0 -0
  117. {agentversion-0.2.1 → agentversion-0.2.2}/tests/test_frozen_hash_vectors.py +0 -0
  118. {agentversion-0.2.1 → agentversion-0.2.2}/tests/test_hasher.py +0 -0
  119. {agentversion-0.2.1 → agentversion-0.2.2}/tests/test_ids.py +0 -0
  120. {agentversion-0.2.1 → agentversion-0.2.2}/tests/test_lifecycle.py +0 -0
  121. {agentversion-0.2.1 → agentversion-0.2.2}/tests/test_manifest.py +0 -0
  122. {agentversion-0.2.1 → agentversion-0.2.2}/tests/test_refs.py +0 -0
  123. {agentversion-0.2.1 → agentversion-0.2.2}/tests/test_reproducible_replay.py +0 -0
  124. {agentversion-0.2.1 → agentversion-0.2.2}/tests/test_trust_observability.py +0 -0
  125. {agentversion-0.2.1 → agentversion-0.2.2}/tests/test_validator.py +0 -0
@@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  > **Package version ≠ spec version.** This file tracks the **package** version. The on-the-wire `spec_version` is independent and frozen at `1.0.0`; a pre-1.0 package can implement a stable 1.0 spec, which is exactly the situation today.
9
9
 
10
+ ## [0.2.2] - 2026-07-15
11
+
12
+ ### Changed
13
+ - **`behavioral_policy` re-scoped as a generic versioned policy-document surface** (docs only).
14
+ The surface previously described itself as bound to skillevaluation's conversation-mode
15
+ `policy_check` state machine; that eval mode was removed (skillevaluation ADR-0007), so the
16
+ docstrings + `spec/behavioral-policy.md` now define it document-agnostically: `policy_hash` is a
17
+ hash of *any* bound policy artifact (refund rules, a safety guardrail set, an escalation SOP…),
18
+ a rule change diffs **breaking**, an unchanged `policy_hash` is non-breaking. **No code or schema
19
+ change**: the `BehavioralPolicy` model still carries `objection_threshold`/`concede_events`/
20
+ `always_forbidden` (now documented as optional, illustrative, back-compat rule fields), the
21
+ `_BEHAVIORAL_POLICY_RULE_FIELDS` diff logic is byte-identical, and every frozen hash-vector +
22
+ the 406-test suite are unchanged. `spec_version` unchanged (1.0.0).
23
+
10
24
  ## [0.2.1] - 2026-06-24
11
25
 
12
26
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentversion
3
- Version: 0.2.1
3
+ Version: 0.2.2
4
4
  Summary: An open specification for versioning agent runtimes and keeping datasets valid.
5
5
  Project-URL: Homepage, https://github.com/decimal-labs/agentversion
6
6
  Project-URL: Documentation, https://github.com/decimal-labs/agentversion/tree/main/spec
@@ -741,9 +741,9 @@ _BEHAVIORAL_POLICY_RULE_FIELDS = (
741
741
  def _adapt_behavioral_policy(old: dict[str, Any], new: dict[str, Any]) -> tuple[
742
742
  Literal["breaking", "non_breaking"], Severity, list[str]
743
743
  ]:
744
- """A change to the multi-turn behavioral policy RULES is BREAKING: it invalidates the conversation-
745
- mode eval set and any past traces graded under the old policy. (A bare metadata change with an
746
- unchanged ``policy_hash`` is not a rule change.)
744
+ """A change to the bound behavioral policy RULES is BREAKING: it invalidates any eval set and any
745
+ past traces graded under the old policy. (A bare metadata change with an unchanged ``policy_hash``
746
+ is not a rule change.)
747
747
 
748
748
  Add/remove are asymmetric and handled here so the surface is severitied by its own
749
749
  logic in both directions: *introducing* a policy where there was none is additive
@@ -263,25 +263,30 @@ class Environment(BaseModel):
263
263
 
264
264
 
265
265
  class BehavioralPolicy(BaseModel):
266
- """Multi-turn BEHAVIORAL-POLICY contract surface.
266
+ """Versioned BEHAVIORAL-POLICY contract surface.
267
267
 
268
- The rules a multi-turn agent must hold across turns — e.g. a refund/escalation policy: "deny until
269
- the customer objects N times, then escalate; never admit liability". Bound to skillevaluation's
270
- conversation-mode ``policy_check`` (the deterministic state machine that grades these rules).
268
+ Binds the agent to a named policy artifact — the rules it must hold to, e.g. a refund/escalation
269
+ policy ("deny until the customer objects N times, then escalate; never admit liability"), a safety
270
+ guardrail set, or an escalation SOP. The surface is document-agnostic: ``policy_hash`` is the stable
271
+ identity (a hash of whatever policy artifact you bind), and the value carried is opaque to this
272
+ model.
271
273
 
272
274
  Why it is a first-class surface: a behavioral policy lives *inside* the prompt, so a prompt-stack
273
- hash change is classified ``non_breaking`` — yet flipping the policy (``objection_threshold`` 3 → 1,
274
- or removing an ``always_forbidden`` rule) INVALIDATES the conversation-mode eval set and any past
275
- traces graded under the old policy. Hoisting the policy to its own surface makes that flip visible
276
- and ``breaking`` instead of silently ``keep``. ``policy_hash`` is the stable identity (a hash of the
277
- bound ``policy_check`` spec); the rule fields are carried for human-readable diffs. ``extra='allow'``
278
- so a richer policy spec round-trips without forking this model.
275
+ hash change is classified ``non_breaking`` — yet flipping the policy (a threshold 3 → 1, or removing
276
+ a forbidden rule) INVALIDATES any eval set and any past traces graded under the old policy. Hoisting
277
+ the policy to its own surface makes that flip visible and ``breaking`` instead of silently ``keep``.
278
+
279
+ ``policy_hash`` is the identity; the structured rule fields below are OPTIONAL and carried only for
280
+ human-readable diffs (a policy artifact needn't populate any of them — ``extra='allow'`` lets a
281
+ richer or differently-shaped policy spec round-trip without forking this model). They remain on the
282
+ model for backward compatibility with policies already bound this way.
279
283
  """
280
284
 
281
285
  model_config = ConfigDict(extra="allow")
282
286
 
283
287
  policy_id: str | None = None
284
- policy_hash: str | None = None # stable hash of the bound policy_check spec (the identity)
288
+ policy_hash: str | None = None # stable hash of the bound policy artifact (the identity)
289
+ # Optional structured rule fields — illustrative, kept for back-compat + human-readable diffs.
285
290
  objection_threshold: int | None = None
286
291
  concede_events: list[str] | None = None
287
292
  always_forbidden: list[str] | None = None
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "agentversion"
7
- version = "0.2.1"
7
+ version = "0.2.2"
8
8
  description = "An open specification for versioning agent runtimes and keeping datasets valid."
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
@@ -0,0 +1,56 @@
1
+ # `behavioral_policy` surface
2
+
3
+ A contract surface that binds an agent to a **versioned policy document** — the rules it must hold to.
4
+ The surface is document-agnostic: the policy can be a refund/escalation policy (*"deny refunds and offer
5
+ alternatives; only after the customer has objected ≥3 times, escalate to a human; never concede a refund
6
+ yourself, and never admit liability"*), a safety guardrail set, an escalation SOP, or any other bound
7
+ rule artifact.
8
+
9
+ ## Why it is a first-class surface
10
+
11
+ A behavioral policy usually lives *inside the system prompt*. Before this surface existed, flipping the
12
+ policy (tightening a threshold, or dropping a forbidden rule) showed up only as a `prompt_stack`
13
+ **hash change**, which the diff classifies **`non_breaking`** → recommended decision **`keep`**. But a
14
+ policy flip **invalidates** any eval set and any past traces that were graded under the old policy.
15
+ Hoisting the policy to its own surface makes that flip **`breaking`** → `replay`/`drop`, instead of
16
+ silently retaining now-wrong data.
17
+
18
+ The `policy_hash` is the canonical identity — a hash of *whatever policy artifact you bind*. The
19
+ structured rule fields below are optional and carried only for human-readable diffs; the surface does not
20
+ interpret them.
21
+
22
+ ## Shape
23
+
24
+ ```json
25
+ "behavioral_policy": {
26
+ "policy_id": "refund-escalation",
27
+ "policy_hash": "sha256:…", // hash of the bound policy artifact (the identity)
28
+ "objection_threshold": 3, // optional structured rule fields — illustrative,
29
+ "concede_events": ["offered_refund", "escalated"], // carried for readable diffs only
30
+ "always_forbidden": ["admits_liability"]
31
+ }
32
+ ```
33
+
34
+ `policy_id` and `policy_hash` are the only load-bearing keys. The structured rule fields
35
+ (`objection_threshold`, `concede_events`, `always_forbidden`) are **optional**, illustrative, and kept
36
+ for backward compatibility with policies already bound this way — a policy artifact needn't populate any
37
+ of them. The model is `extra="allow"`, so a richer or differently-shaped policy spec round-trips without
38
+ forking it.
39
+
40
+ ## Diff semantics
41
+
42
+ | Transition | Classification | Rationale |
43
+ |---|---|---|
44
+ | rule change (`policy_hash` differs, or any rule field differs) | **breaking** (`major`) | any eval set + past graded traces are now wrong |
45
+ | `policy_hash` unchanged, only metadata (`policy_id`) differs | `non_breaking` (`minor`) | same policy, no rule changed |
46
+ | introduced (absent → present) | `non_breaking` | the old eval set tested no policy; additive |
47
+ | removed (present → absent) | **breaking** (`major`) | past data graded under the policy is now ungoverned |
48
+
49
+ Reason code: `behavioral_policy_changed`. Configurable per-surface via `CompatibilityPolicy.behavioral_policy`
50
+ (defaults: `on_major` → `drop`).
51
+
52
+ ## Hash-safety
53
+
54
+ `behavioral_policy` is **optional and omitted by default**. The `overall_hash` is computed only over the
55
+ surfaces actually present in a contract, so adding this surface to the spec does **not** change the hash
56
+ of any existing (policy-less) manifest. The frozen hash-vectors are unchanged.
@@ -1,51 +0,0 @@
1
- # `behavioral_policy` surface
2
-
3
- A contract surface for a multi-turn agent's **behavioral policy** — the rules it must hold *across
4
- turns*, e.g. a refund/escalation policy: *"deny refunds and offer alternatives; only after the customer
5
- has objected ≥3 times, escalate to a human; never concede a refund yourself, and never admit liability."*
6
-
7
- ## Why it is a first-class surface
8
-
9
- A behavioral policy lives *inside the system prompt*. Before this surface existed, flipping the policy
10
- (`objection_threshold` 3 → 1, or dropping an `always_forbidden` rule) showed up only as a `prompt_stack`
11
- **hash change**, which the diff classifies **`non_breaking`** → recommended decision **`keep`**. But a
12
- policy flip **invalidates** the conversation-mode eval set and any past traces that were graded under the
13
- old policy. Hoisting the policy to its own surface makes that flip **`breaking`** → `replay`/`drop`,
14
- instead of silently retaining now-wrong data.
15
-
16
- This binds directly to [skillevaluation](https://github.com/decimal-labs/skillevaluation)'s
17
- conversation-mode `policy_check` — the deterministic state machine that grades these same rules. The
18
- `policy_hash` is the canonical identity (a hash of the bound `policy_check` spec); the rule fields are
19
- carried for human-readable diffs.
20
-
21
- ## Shape
22
-
23
- ```json
24
- "behavioral_policy": {
25
- "policy_id": "refund-escalation",
26
- "policy_hash": "sha256:…", // hash of the bound policy_check spec (the identity)
27
- "objection_threshold": 3,
28
- "concede_events": ["offered_refund", "escalated"],
29
- "always_forbidden": ["admits_liability"]
30
- }
31
- ```
32
-
33
- The model is `extra="allow"`, so a richer policy spec round-trips without forking it.
34
-
35
- ## Diff semantics
36
-
37
- | Transition | Classification | Rationale |
38
- |---|---|---|
39
- | rule change (`policy_hash` differs, or any rule field differs) | **breaking** (`major`) | conversation eval set + past graded traces are now wrong |
40
- | `policy_hash` unchanged, only metadata (`policy_id`) differs | `non_breaking` (`minor`) | same policy, no rule changed |
41
- | introduced (absent → present) | `non_breaking` | the old eval set tested no policy; additive |
42
- | removed (present → absent) | **breaking** (`major`) | past data graded under the policy is now ungoverned |
43
-
44
- Reason code: `behavioral_policy_changed`. Configurable per-surface via `CompatibilityPolicy.behavioral_policy`
45
- (defaults: `on_major` → `drop`).
46
-
47
- ## Hash-safety
48
-
49
- `behavioral_policy` is **optional and omitted by default**. The `overall_hash` is computed only over the
50
- surfaces actually present in a contract, so adding this surface to the spec does **not** change the hash
51
- of any existing (policy-less) manifest. The frozen hash-vectors are unchanged.
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes