agentversion 0.2.1__tar.gz → 0.2.3__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.
- agentversion-0.2.3/.gitignore +52 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/CHANGELOG.md +42 -11
- {agentversion-0.2.1 → agentversion-0.2.3}/CONFORMANCE.md +3 -9
- {agentversion-0.2.1 → agentversion-0.2.3}/PKG-INFO +38 -23
- {agentversion-0.2.1 → agentversion-0.2.3}/README.md +36 -21
- {agentversion-0.2.1 → agentversion-0.2.3}/agentversion/compatibility.py +7 -1
- {agentversion-0.2.1 → agentversion-0.2.3}/agentversion/contract.py +4 -4
- {agentversion-0.2.1 → agentversion-0.2.3}/agentversion/diff.py +8 -10
- {agentversion-0.2.1 → agentversion-0.2.3}/agentversion/manifest.py +17 -12
- {agentversion-0.2.1 → agentversion-0.2.3}/compatibility-tests/environment-region-change/after.json +2 -2
- {agentversion-0.2.1/compatibility-tests/skill-registry-skill-removed → agentversion-0.2.3/compatibility-tests/environment-region-change}/before.json +2 -2
- {agentversion-0.2.1 → agentversion-0.2.3}/compatibility-tests/environment-region-change/expected-diff.json +2 -2
- {agentversion-0.2.1 → agentversion-0.2.3}/compatibility-tests/model-runtime-provider-change/after.json +2 -2
- {agentversion-0.2.1/compatibility-tests/environment-region-change → agentversion-0.2.3/compatibility-tests/model-runtime-provider-change}/before.json +2 -2
- {agentversion-0.2.1 → agentversion-0.2.3}/compatibility-tests/model-runtime-provider-change/expected-diff.json +2 -2
- {agentversion-0.2.1 → agentversion-0.2.3}/compatibility-tests/output-schema-change/after.json +1 -1
- {agentversion-0.2.1 → agentversion-0.2.3}/compatibility-tests/output-schema-change/before.json +1 -1
- {agentversion-0.2.1 → agentversion-0.2.3}/compatibility-tests/output-schema-change/expected-diff.json +2 -2
- {agentversion-0.2.1 → agentversion-0.2.3}/compatibility-tests/prompt-stack-edit/after.json +2 -2
- {agentversion-0.2.1 → agentversion-0.2.3}/compatibility-tests/prompt-stack-edit/before.json +2 -2
- {agentversion-0.2.1 → agentversion-0.2.3}/compatibility-tests/prompt-stack-edit/expected-diff.json +2 -2
- {agentversion-0.2.1 → agentversion-0.2.3}/compatibility-tests/skill-registry-skill-removed/after.json +2 -2
- {agentversion-0.2.1/compatibility-tests/model-runtime-provider-change → agentversion-0.2.3/compatibility-tests/skill-registry-skill-removed}/before.json +2 -2
- {agentversion-0.2.1 → agentversion-0.2.3}/compatibility-tests/skill-registry-skill-removed/expected-diff.json +2 -2
- {agentversion-0.2.1 → agentversion-0.2.3}/compatibility-tests/subagent-handoff-change/after.json +1 -1
- {agentversion-0.2.1 → agentversion-0.2.3}/compatibility-tests/subagent-handoff-change/before.json +1 -1
- {agentversion-0.2.1 → agentversion-0.2.3}/compatibility-tests/subagent-handoff-change/expected-diff.json +2 -2
- {agentversion-0.2.1 → agentversion-0.2.3}/compatibility-tests/tool-rename/after.json +1 -1
- {agentversion-0.2.1 → agentversion-0.2.3}/compatibility-tests/tool-rename/before.json +1 -1
- {agentversion-0.2.1 → agentversion-0.2.3}/compatibility-tests/tool-rename/expected-diff.json +2 -2
- {agentversion-0.2.1 → agentversion-0.2.3}/compatibility-tests/workflow-graph-change/after.json +2 -2
- agentversion-0.2.3/compatibility-tests/workflow-graph-change/before.json +73 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/compatibility-tests/workflow-graph-change/expected-diff.json +2 -2
- {agentversion-0.2.1 → agentversion-0.2.3}/examples/integrations/decimalai_bridge.py +2 -2
- {agentversion-0.2.1 → agentversion-0.2.3}/pyproject.toml +31 -4
- {agentversion-0.2.1 → agentversion-0.2.3}/spec/attestation.md +1 -1
- agentversion-0.2.3/spec/behavioral-policy.md +56 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/spec/compatibility-batch.md +2 -2
- {agentversion-0.2.1 → agentversion-0.2.3}/spec/compatibility-decision.md +2 -2
- {agentversion-0.2.1 → agentversion-0.2.3}/spec/compatibility-policy.md +9 -5
- {agentversion-0.2.1 → agentversion-0.2.3}/spec/data-classification.md +3 -2
- {agentversion-0.2.1 → agentversion-0.2.3}/spec/environment.md +1 -1
- {agentversion-0.2.1 → agentversion-0.2.3}/spec/ids.md +1 -1
- {agentversion-0.2.1 → agentversion-0.2.3}/spec/reference.md +28 -2
- {agentversion-0.2.1 → agentversion-0.2.3}/spec/refs.md +1 -1
- {agentversion-0.2.1 → agentversion-0.2.3}/spec/replay-determinism.md +1 -1
- {agentversion-0.2.1 → agentversion-0.2.3}/spec/versioning-policy.md +2 -2
- {agentversion-0.2.1 → agentversion-0.2.3}/tests/fixtures/frozen_hash_vectors.json +3 -3
- {agentversion-0.2.1 → agentversion-0.2.3}/tests/test_audit_v020.py +2 -2
- {agentversion-0.2.1 → agentversion-0.2.3}/tests/test_behavioral_policy.py +1 -1
- {agentversion-0.2.1 → agentversion-0.2.3}/tests/test_cli.py +26 -8
- {agentversion-0.2.1 → agentversion-0.2.3}/tests/test_component_surface_map.py +1 -1
- agentversion-0.2.3/tests/test_conformance.py +137 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/tests/test_contract.py +4 -4
- {agentversion-0.2.1 → agentversion-0.2.3}/tests/test_extension_hatch.py +1 -1
- {agentversion-0.2.1 → agentversion-0.2.3}/tests/test_frozen_hash_vectors.py +5 -5
- {agentversion-0.2.1 → agentversion-0.2.3}/tests/test_trust_observability.py +2 -2
- {agentversion-0.2.1 → agentversion-0.2.3}/tests/test_validator.py +1 -1
- agentversion-0.2.1/.github/dependabot.yml +0 -19
- agentversion-0.2.1/.github/workflows/ci.yml +0 -64
- agentversion-0.2.1/.github/workflows/publish.yml +0 -75
- agentversion-0.2.1/.gitignore +0 -32
- agentversion-0.2.1/CONTRIBUTING.md +0 -66
- agentversion-0.2.1/RELEASING.md +0 -63
- agentversion-0.2.1/adrs/0000-template.md +0 -43
- agentversion-0.2.1/adrs/0001-version-spec-core.md +0 -64
- agentversion-0.2.1/compatibility-tests/workflow-graph-change/before.json +0 -73
- agentversion-0.2.1/pyrightconfig.json +0 -13
- agentversion-0.2.1/scripts/release.sh +0 -70
- agentversion-0.2.1/spec/behavioral-policy.md +0 -51
- agentversion-0.2.1/tests/test_conformance.py +0 -66
- {agentversion-0.2.1 → agentversion-0.2.3}/LICENSE +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/agentversion/__init__.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/agentversion/_shared.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/agentversion/a2a.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/agentversion/cli.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/agentversion/constants.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/agentversion/dataset.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/agentversion/decision.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/agentversion/hasher.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/agentversion/ids.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/agentversion/py.typed +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/agentversion/refs.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/agentversion/replay.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/agentversion/validator.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/examples/.gitkeep +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/examples/integrations/langgraph_example.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/examples/integrations/otel_mapping.md +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/examples/manifest/finance-agent-v1.json +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/examples/manifest/finance-agent-v2.json +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/examples/scenarios/tool-rename-drift.md +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/examples/scenarios/walkthrough.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/schemas/.gitkeep +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/schemas/agent-manifest.schema.json +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/schemas/compatibility-batch.schema.json +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/schemas/compatibility-decision.schema.json +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/schemas/compatibility-policy.schema.json +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/schemas/compatibility-report.schema.json +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/schemas/dataset-snapshot.schema.json +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/schemas/episode.schema.json +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/schemas/manifest-diff.schema.json +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/schemas/replay-job.schema.json +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/schemas/replay-result.schema.json +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/schemas/step.schema.json +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/schemas/task.schema.json +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/spec/a2a-mapping.md +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/spec/dataset.md +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/spec/diff.md +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/spec/evaluation.md +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/spec/hashing.md +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/spec/lifecycle.md +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/spec/manifest.md +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/spec/otel-mapping.md +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/spec/replay.md +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/tests/test_a2a_mapping.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/tests/test_audit_v030.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/tests/test_dataset.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/tests/test_decision_replay.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/tests/test_diff.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/tests/test_environment.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/tests/test_evaluation.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/tests/test_examples_runnable.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/tests/test_hasher.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/tests/test_ids.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/tests/test_lifecycle.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/tests/test_manifest.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/tests/test_refs.py +0 -0
- {agentversion-0.2.1 → agentversion-0.2.3}/tests/test_reproducible_replay.py +0 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
*.egg
|
|
7
|
+
*.egg-info/
|
|
8
|
+
.eggs/
|
|
9
|
+
build/
|
|
10
|
+
dist/
|
|
11
|
+
|
|
12
|
+
# Virtual environments
|
|
13
|
+
.venv/
|
|
14
|
+
venv/
|
|
15
|
+
env/
|
|
16
|
+
|
|
17
|
+
# Test, lint and type-check caches
|
|
18
|
+
.pytest_cache/
|
|
19
|
+
.ruff_cache/
|
|
20
|
+
.mypy_cache/
|
|
21
|
+
.benchmarks/
|
|
22
|
+
.deepeval/
|
|
23
|
+
.coverage
|
|
24
|
+
.coverage.*
|
|
25
|
+
coverage.xml
|
|
26
|
+
coverage/
|
|
27
|
+
htmlcov/
|
|
28
|
+
|
|
29
|
+
# Node
|
|
30
|
+
node_modules/
|
|
31
|
+
.next/
|
|
32
|
+
*.log
|
|
33
|
+
|
|
34
|
+
# Environment files. Real credentials never belong in the tree;
|
|
35
|
+
# .env.example is the tracked template, so it is re-included.
|
|
36
|
+
.env
|
|
37
|
+
.env.*
|
|
38
|
+
!.env.example
|
|
39
|
+
|
|
40
|
+
# Editors
|
|
41
|
+
.idea/
|
|
42
|
+
.vscode/
|
|
43
|
+
*.swp
|
|
44
|
+
*.swo
|
|
45
|
+
*~
|
|
46
|
+
|
|
47
|
+
# OS
|
|
48
|
+
.DS_Store
|
|
49
|
+
Thumbs.db
|
|
50
|
+
|
|
51
|
+
# Local agent/tool state
|
|
52
|
+
.claude/settings.local.json
|
|
@@ -7,13 +7,46 @@ 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.3] - 2026-08-14
|
|
11
|
+
|
|
12
|
+
Packaging and documentation only. **No code, schema, or `spec_version` change** — the
|
|
13
|
+
on-the-wire spec stays frozen at 1.0.0 and every hash vector is unchanged.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- **The source distribution now builds a wheel.** The sdist previously packed whatever the
|
|
17
|
+
working tree happened to contain, and omitted `schemas/`, `spec/`, `examples/` and
|
|
18
|
+
`compatibility-tests/` — the directories the wheel pulls in via `force-include`. The sdist
|
|
19
|
+
itself still built, so the gap only surfaced one step later: building a **wheel from that
|
|
20
|
+
sdist** failed, which is exactly what `uv build` and downstream packagers do. The sdist now
|
|
21
|
+
ships an explicit allow-list covering those sources.
|
|
22
|
+
- **The conformance fixtures now validate against the published schema.** They had drifted
|
|
23
|
+
from the schema shipped in the package, so a consumer validating the fixtures as a
|
|
24
|
+
self-check would see spurious failures.
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
- Spec wording and README claims tightened to match what the package actually implements.
|
|
28
|
+
|
|
29
|
+
## [0.2.2] - 2026-07-15
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
- **`behavioral_policy` re-scoped as a generic versioned policy-document surface** (docs only).
|
|
33
|
+
The surface previously described itself as bound to skillevaluation's conversation-mode
|
|
34
|
+
`policy_check` state machine; that eval mode was removed (skillevaluation ADR-0007), so the
|
|
35
|
+
docstrings + `spec/behavioral-policy.md` now define it document-agnostically: `policy_hash` is a
|
|
36
|
+
hash of *any* bound policy artifact (refund rules, a safety guardrail set, an escalation SOP…),
|
|
37
|
+
a rule change diffs **breaking**, an unchanged `policy_hash` is non-breaking. **No code or schema
|
|
38
|
+
change**: the `BehavioralPolicy` model still carries `objection_threshold`/`concede_events`/
|
|
39
|
+
`always_forbidden` (now documented as optional, illustrative, back-compat rule fields), the
|
|
40
|
+
`_BEHAVIORAL_POLICY_RULE_FIELDS` diff logic is byte-identical, and every frozen hash-vector +
|
|
41
|
+
the 406-test suite are unchanged. `spec_version` unchanged (1.0.0).
|
|
42
|
+
|
|
10
43
|
## [0.2.1] - 2026-06-24
|
|
11
44
|
|
|
12
45
|
### Fixed
|
|
13
46
|
- **`contract_from_components` now emits the `behavioral_policy` and
|
|
14
47
|
`environment` surfaces.** 0.2.0 added the models, surface keys, and diff
|
|
15
48
|
classifiers, but the shared flat-components → contract assembler silently
|
|
16
|
-
dropped both — so a producer (
|
|
49
|
+
dropped both — so a producer (e.g. an SDK exporter) could never
|
|
17
50
|
actually populate them from components. They are now assembled verbatim from
|
|
18
51
|
each component's `schema_json`. Additive-only: a manifest that doesn't declare
|
|
19
52
|
them is unchanged (same `overall_hash`).
|
|
@@ -43,7 +76,7 @@ byte-identically and is pinned to this assembly by its conformance test.
|
|
|
43
76
|
- **Extension hatch** (`AgentContract` is now `extra="allow"`): a custom / emerging contract surface
|
|
44
77
|
(RAG corpus, MCP server registry, memory policy, vendor extension) is hashed by the hasher and diffed
|
|
45
78
|
by the engine, and now also **survives `model_validate`** — previously it was silently dropped, so a
|
|
46
|
-
validate→re-serialize→re-hash round-trip changed `overall_hash` (a
|
|
79
|
+
validate→re-serialize→re-hash round-trip changed `overall_hash` (a hash-determinism break). The
|
|
47
80
|
surface set can grow without forking the model. ASCII/known-surface hashes are unchanged.
|
|
48
81
|
- **`COMPONENT_TYPE_TO_SURFACE` + `surface_key_for_component()`** — the canonical routing from a
|
|
49
82
|
producer's flat `component_type` to the contract surface key it lands in (incl. the singular→plural
|
|
@@ -51,17 +84,15 @@ byte-identically and is pinned to this assembly by its conformance test.
|
|
|
51
84
|
translator) share one source of truth instead of hand-copying the map — closing a cross-stack drift
|
|
52
85
|
class where the rename had to be applied independently in every translator copy.
|
|
53
86
|
- **`contract.contract_from_components()`** — the single source of truth for assembling a contract block
|
|
54
|
-
(every surface, in canonical shape) from a producer's flat component list
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
customer reproduces the stored hash with the OSS CLI. Closes audit X-2 (two hand-written translators
|
|
58
|
-
with no shared code/test).
|
|
87
|
+
(every surface, in canonical shape) from a producer's flat component list, so any producer computes the
|
|
88
|
+
same `jcs-sha256` identity hash for the same agent and a manifest's stored hash reproduces with the
|
|
89
|
+
OSS CLI.
|
|
59
90
|
|
|
60
91
|
### Fixed (hash-determinism + trust)
|
|
61
92
|
- **Canonical-hash domain** (`hasher.py`): NFC-normalize every string (keys + values) and reject
|
|
62
93
|
non-finite floats (`NaN`/`±Infinity`) **before** JCS canonicalization. JCS canonicalizes bytes but
|
|
63
94
|
does not Unicode-normalize, so a composed `"café"` and a decomposed `"café"` previously produced a
|
|
64
|
-
different `overall_hash` for the same agent (a cross-language reproduction break
|
|
95
|
+
different `overall_hash` for the same agent (a cross-language reproduction break); and a
|
|
65
96
|
`NaN` raised an opaque `jcs` error instead of a clear domain error. NFC of ASCII is a no-op, so
|
|
66
97
|
**existing manifest hashes are unchanged** (frozen vectors still pass). Documented in `spec/hashing.md`.
|
|
67
98
|
- **Attestation integrity** (`validator.py`): an attestation's `signed_payload_hash` must equal the
|
|
@@ -123,7 +154,7 @@ byte-identically and is pinned to this assembly by its conformance test.
|
|
|
123
154
|
|
|
124
155
|
**First published release** — the first `agentversion` release on PyPI.
|
|
125
156
|
|
|
126
|
-
The package ships pre-1.0 on purpose. The spec it implements is stable (`spec_version 1.0.0`, with a frozen wire format and conformance suite), but the Python package API hasn't earned its own 1.0 promise yet — so it enters at `0.1.0` (`Development Status :: 4 - Beta`). Feature-wise it's complete against the original
|
|
157
|
+
The package ships pre-1.0 on purpose. The spec it implements is stable (`spec_version 1.0.0`, with a frozen wire format and conformance suite), but the Python package API hasn't earned its own 1.0 promise yet — so it enters at `0.1.0` (`Development Status :: 4 - Beta`). Feature-wise it's complete against the original capability roadmap; that work landed across the internal milestones listed further below, none of which were ever published.
|
|
127
158
|
|
|
128
159
|
### Changed — Project renamed to **AgentVersion**
|
|
129
160
|
|
|
@@ -146,7 +177,7 @@ The entries below were development milestones tracked in-repo on the way to feat
|
|
|
146
177
|
|
|
147
178
|
### 1.0.0 - 2026-05-12 (internal milestone)
|
|
148
179
|
|
|
149
|
-
**Feature-complete milestone** (never published). The
|
|
180
|
+
**Feature-complete milestone** (never published). The capability roadmap reached feature-completeness at this internal version; the stability promise it anticipated now lives on the spec, which is frozen at `1.0.0`.
|
|
150
181
|
|
|
151
182
|
### What v1.0 looks like
|
|
152
183
|
|
|
@@ -192,7 +223,7 @@ Trust + observability + governance batch. The last three §3 items.
|
|
|
192
223
|
- avs total: **295 passing** (was 278, net +17).
|
|
193
224
|
|
|
194
225
|
### Phase 3 complete
|
|
195
|
-
All 14
|
|
226
|
+
All 14 capability items (§3a–§3n) are now shipped, except §3l, which ships no standalone surface of its own. The spec is feature-complete for that roadmap. Next milestone: **v1.0** — tighten enforcement (drop permissive ID pattern, drop bare-ID manifest_refs), publish to PyPI.
|
|
196
227
|
|
|
197
228
|
### 0.8.0 - 2026-05-12
|
|
198
229
|
|
|
@@ -23,20 +23,14 @@ Located under [`compatibility-tests/`](./compatibility-tests/). Each subdirector
|
|
|
23
23
|
|
|
24
24
|
```
|
|
25
25
|
compatibility-tests/
|
|
26
|
-
|
|
26
|
+
<scenario-name>/
|
|
27
27
|
before.json # input manifest A
|
|
28
28
|
after.json # input manifest B
|
|
29
29
|
expected-diff.json # ManifestDiff produced by a conforming implementation
|
|
30
|
-
output-schema-change/
|
|
31
|
-
before.json
|
|
32
|
-
after.json
|
|
33
|
-
expected-diff.json
|
|
34
|
-
subagent-handoff-change/
|
|
35
|
-
before.json
|
|
36
|
-
after.json
|
|
37
|
-
expected-diff.json
|
|
38
30
|
```
|
|
39
31
|
|
|
32
|
+
Every subdirectory of `compatibility-tests/` is a scenario and all of them are normative — run the directory, not a fixed list.
|
|
33
|
+
|
|
40
34
|
The Python reference verifies conformance via `tests/test_conformance.py`. To verify an implementation in another language:
|
|
41
35
|
|
|
42
36
|
1. For each scenario, load `before.json` and `after.json`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: agentversion
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
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
|
|
@@ -35,12 +35,16 @@ Description-Content-Type: text/markdown
|
|
|
35
35
|
|
|
36
36
|
# AgentVersion
|
|
37
37
|
|
|
38
|
+
*Part of [DecimalAI](https://decimal.ai). Most users want the Python SDK → [decimal-labs/decimalai-python](https://github.com/decimal-labs/decimalai-python).*
|
|
39
|
+
|
|
38
40
|
**Your agent changed. Is your saved data still valid?**
|
|
39
41
|
|
|
40
42
|
[](https://pypi.org/project/agentversion/)
|
|
43
|
+
[](https://pepy.tech/project/agentversion)
|
|
44
|
+
[](https://github.com/decimal-labs/agentversion/actions/workflows/ci.yml)
|
|
41
45
|
[](https://pypi.org/project/agentversion/)
|
|
42
46
|
[](https://pypi.org/project/agentversion/)
|
|
43
|
-
[](https://
|
|
47
|
+
[](https://github.com/decimal-labs/agentversion/blob/main/LICENSE)
|
|
44
48
|
|
|
45
49
|
When you ship a new version of an agent, everything you collected against the old one — production traces, eval datasets, SFT (supervised fine-tuning) examples — quietly drifts out of date. There's no `package.json` to pin an agent's contract, and no `git diff` to tell you what changed.
|
|
46
50
|
|
|
@@ -148,7 +152,9 @@ A manifest is plain JSON. The top says *which* version this is; `contract` holds
|
|
|
148
152
|
|
|
149
153
|
Each surface is hashed on its own, so the diff can say *"`tool_registry` changed, `prompt_stack` didn't"* instead of just *"the manifest changed."*
|
|
150
154
|
|
|
151
|
-
> Try it yourself — both [`examples/manifest/`](https://
|
|
155
|
+
> Try it yourself — both [`examples/manifest/`](https://github.com/decimal-labs/agentversion/tree/main/examples/manifest)
|
|
156
|
+
> manifests ship inside the `agentversion` wheel as well as in the repo; the commands below use the
|
|
157
|
+
> repo-relative paths, so clone first.
|
|
152
158
|
|
|
153
159
|
---
|
|
154
160
|
|
|
@@ -158,7 +164,7 @@ You probably already have observability and a trace store. None of them answer *
|
|
|
158
164
|
|
|
159
165
|
| You already have | What it gives you | What it doesn't |
|
|
160
166
|
|---|---|---|
|
|
161
|
-
| OpenTelemetry
|
|
167
|
+
| OpenTelemetry and the tracing tools built on it | rich execution traces | a versioned contract for the agent that produced them |
|
|
162
168
|
| A2A / ACP agent cards | runtime discovery + I/O types | version identity or data-compatibility |
|
|
163
169
|
| OpenAI JSONL / SFT files | a training format | provenance — *which agent version* produced each row |
|
|
164
170
|
|
|
@@ -177,7 +183,7 @@ Apache-2.0, no config — just needs Python 3.10+.
|
|
|
177
183
|
There are **two version numbers**, deliberately different:
|
|
178
184
|
|
|
179
185
|
- the **wire spec** is frozen at **v1.0** (stable format + conformance suite — safe to build against);
|
|
180
|
-
- this **Python package** is **
|
|
186
|
+
- this **Python package** is still **pre-1.0**, so its API may still shift.
|
|
181
187
|
|
|
182
188
|
(The `spec-v1.0` and PyPI badges above show each one.)
|
|
183
189
|
|
|
@@ -201,9 +207,11 @@ agentversion hash manifest.json # a content hash that ignores key order an
|
|
|
201
207
|
agentversion validate manifest.json # check it against the spec
|
|
202
208
|
```
|
|
203
209
|
|
|
204
|
-
**3. Diff two versions** —
|
|
210
|
+
**3. Diff two versions** — against the bundled examples. The paths are relative, so run this from a
|
|
211
|
+
checkout (`--compat` adds the keep/repair/replay/drop recommendation; `--json` for machine output):
|
|
205
212
|
|
|
206
213
|
```bash
|
|
214
|
+
git clone https://github.com/decimal-labs/agentversion && cd agentversion
|
|
207
215
|
agentversion diff examples/manifest/finance-agent-v1.json \
|
|
208
216
|
examples/manifest/finance-agent-v2.json --compat
|
|
209
217
|
```
|
|
@@ -216,7 +224,7 @@ agentversion diff examples/manifest/finance-agent-v1.json \
|
|
|
216
224
|
run: agentversion diff baseline-manifest.json current-manifest.json --fail-on-breaking
|
|
217
225
|
```
|
|
218
226
|
|
|
219
|
-
**Use it from Python** — every
|
|
227
|
+
**Use it from Python** — every API below is covered by the test suite:
|
|
220
228
|
|
|
221
229
|
```python
|
|
222
230
|
import json
|
|
@@ -224,17 +232,20 @@ from agentversion import AgentManifest, validate_manifest_file, hash_manifest
|
|
|
224
232
|
from agentversion.diff import diff_manifests
|
|
225
233
|
from agentversion.compatibility import classify_compatibility
|
|
226
234
|
|
|
227
|
-
old = json.load(open("finance-agent-v1.json"))
|
|
228
|
-
new = json.load(open("finance-agent-v2.json"))
|
|
235
|
+
old = json.load(open("examples/manifest/finance-agent-v1.json"))
|
|
236
|
+
new = json.load(open("examples/manifest/finance-agent-v2.json"))
|
|
229
237
|
|
|
230
238
|
# Validate + identify a version
|
|
231
|
-
assert validate_manifest_file("finance-agent-v2.json").valid
|
|
239
|
+
assert validate_manifest_file("examples/manifest/finance-agent-v2.json").valid
|
|
232
240
|
m = AgentManifest.model_validate(new)
|
|
233
241
|
print(m.agent_name, m.identity.overall_hash) # finance-agent sha256:767ebff1...
|
|
234
242
|
|
|
235
243
|
# Diff, then ask what to do with old data
|
|
236
244
|
result = diff_manifests(old, new)
|
|
237
245
|
print(result.summary.breaking_surfaces) # 5
|
|
246
|
+
|
|
247
|
+
# Pass no policy and the built-in fallback rules apply. They are deliberately
|
|
248
|
+
# non-destructive: the worst they will ever recommend is replay, never drop.
|
|
238
249
|
print(classify_compatibility(result).recommended_decision) # replay
|
|
239
250
|
```
|
|
240
251
|
|
|
@@ -267,10 +278,10 @@ The protocol is fully useful standalone:
|
|
|
267
278
|
|
|
268
279
|
1. **Track versions locally** — `init` to scaffold, `hash` for a stable id, `diff` between any two. No account, fully offline.
|
|
269
280
|
2. **Gate CI/CD** — `diff --fail-on-breaking` stops a breaking agent change from reaching production.
|
|
270
|
-
3. **Annotate traces** — stamp `identity.overall_hash` onto your OpenTelemetry spans as `agentversion.manifest_hash` for version-scoped filtering. See [`examples/integrations/otel_mapping.md`](https://
|
|
281
|
+
3. **Annotate traces** — stamp `identity.overall_hash` onto your OpenTelemetry spans as `agentversion.manifest_hash` for version-scoped filtering. See [`examples/integrations/otel_mapping.md`](https://github.com/decimal-labs/agentversion/blob/main/examples/integrations/otel_mapping.md), bundled in the package.
|
|
271
282
|
4. **Classify data compatibility** — `diff --compat` (or `decision generate`) gives a per-episode keep / repair / replay / drop verdict you can act on.
|
|
272
283
|
|
|
273
|
-
|
|
284
|
+
A manifest hash is just a string, so it drops into whatever trace store or eval tool you already run — put `identity.overall_hash` on the spans or dataset rows you keep, and the compatibility decisions sit alongside your eval pipeline as ordinary JSON.
|
|
274
285
|
|
|
275
286
|
---
|
|
276
287
|
|
|
@@ -278,13 +289,13 @@ It interoperates with LangSmith, Langfuse, Phoenix, and W&B — annotate their t
|
|
|
278
289
|
|
|
279
290
|
`agentversion` is an open spec so any tool, in any language, can produce interoperable manifests and diffs:
|
|
280
291
|
|
|
281
|
-
- [`spec/manifest.md`](https://
|
|
282
|
-
- [`spec/diff.md`](https://
|
|
283
|
-
- [`spec/compatibility-decision.md`](https://
|
|
284
|
-
- [`spec/replay.md`](https://
|
|
285
|
-
- [`spec/reference.md`](https://
|
|
292
|
+
- [`spec/manifest.md`](https://github.com/decimal-labs/agentversion/blob/main/spec/manifest.md) — the agent manifest
|
|
293
|
+
- [`spec/diff.md`](https://github.com/decimal-labs/agentversion/blob/main/spec/diff.md) — surface diffs, breaking vs non-breaking
|
|
294
|
+
- [`spec/compatibility-decision.md`](https://github.com/decimal-labs/agentversion/blob/main/spec/compatibility-decision.md) — keep / repair / replay / drop
|
|
295
|
+
- [`spec/replay.md`](https://github.com/decimal-labs/agentversion/blob/main/spec/replay.md) · [`spec/dataset.md`](https://github.com/decimal-labs/agentversion/blob/main/spec/dataset.md) — replay jobs and dataset objects with provenance
|
|
296
|
+
- [`spec/reference.md`](https://github.com/decimal-labs/agentversion/blob/main/spec/reference.md) — full schemas and validation rules · [`schemas/`](https://github.com/decimal-labs/agentversion/tree/main/schemas) — JSON Schemas
|
|
286
297
|
|
|
287
|
-
The full spec and JSON Schemas ship inside the `agentversion` wheel. [`CONFORMANCE.md`](https://
|
|
298
|
+
The full spec and JSON Schemas ship inside the `agentversion` wheel. [`CONFORMANCE.md`](https://github.com/decimal-labs/agentversion/blob/main/CONFORMANCE.md) + [`compatibility-tests/`](https://github.com/decimal-labs/agentversion/tree/main/compatibility-tests) are golden in/out pairs that any implementation must reproduce to claim conformance.
|
|
288
299
|
|
|
289
300
|
---
|
|
290
301
|
|
|
@@ -303,7 +314,7 @@ A manifest can carry the eval results that gated its release in `evaluation.gate
|
|
|
303
314
|
}
|
|
304
315
|
```
|
|
305
316
|
|
|
306
|
-
Those scores come from [`skillevaluation`](https://
|
|
317
|
+
Those scores come from [`skillevaluation`](https://github.com/decimal-labs/skillevaluation), the sibling open spec: `agentversion` versions the agent runtime itself (what an agent version *is* and what changed), while `skillevaluation` A/B-benchmarks a single skill (whether it actually helps).
|
|
307
318
|
|
|
308
319
|
The [`decimalai`](https://pypi.org/project/decimalai/) Python SDK builds on `agentversion` to add framework adapters (capture a manifest straight from your LangGraph/CrewAI app), trace capture, and managed replay — but you never need it to use the spec.
|
|
309
320
|
|
|
@@ -332,13 +343,13 @@ diff = diff_manifests(last_prod_manifest, manifest)
|
|
|
332
343
|
print(classify_compatibility(diff).recommended_decision)
|
|
333
344
|
```
|
|
334
345
|
|
|
335
|
-
This is the seam that makes `agentversion` the **open core** of the paid platform: the manifest the SDK captures *is* the format `agentversion diff` consumes, so you can reproduce the platform's diffs and verdicts entirely outside DecimalAI. A runnable version is in [`examples/integrations/decimalai_bridge.py`](https://
|
|
346
|
+
This is the seam that makes `agentversion` the **open core** of the paid platform: the manifest the SDK captures *is* the format `agentversion diff` consumes, so you can reproduce the platform's diffs and verdicts entirely outside DecimalAI. A runnable version is in [`examples/integrations/decimalai_bridge.py`](https://github.com/decimal-labs/agentversion/blob/main/examples/integrations/decimalai_bridge.py).
|
|
336
347
|
|
|
337
348
|
---
|
|
338
349
|
|
|
339
350
|
## Project
|
|
340
351
|
|
|
341
|
-
The spec is frozen at v1.0; the package is pre-1.0 (see [Install](#install)). Design decisions are logged in [`adrs/`](https://
|
|
352
|
+
The spec is frozen at v1.0; the package is pre-1.0 (see [Install](#install)). Design decisions are logged in [`adrs/`](https://github.com/decimal-labs/agentversion/tree/main/adrs), releases in [`CHANGELOG.md`](https://github.com/decimal-labs/agentversion/blob/main/CHANGELOG.md). Contributions — especially new conformance cases — are genuinely welcome; see [`CONTRIBUTING.md`](https://github.com/decimal-labs/agentversion/blob/main/CONTRIBUTING.md):
|
|
342
353
|
|
|
343
354
|
```bash
|
|
344
355
|
pip install agentversion
|
|
@@ -348,4 +359,8 @@ git clone https://github.com/decimal-labs/agentversion && cd agentversion
|
|
|
348
359
|
pip install -e ".[dev]" && pytest
|
|
349
360
|
```
|
|
350
361
|
|
|
351
|
-
Licensed under [Apache 2.0](https://
|
|
362
|
+
Licensed under [Apache 2.0](https://github.com/decimal-labs/agentversion/blob/main/LICENSE).
|
|
363
|
+
|
|
364
|
+
---
|
|
365
|
+
|
|
366
|
+
[Docs](https://docs.decimal.ai) · [Registry](https://app.decimal.ai/skills) · [SDK](https://github.com/decimal-labs/decimalai-python) · [skillevaluation](https://github.com/decimal-labs/skillevaluation) · [regression-check](https://github.com/decimal-labs/regression-check)
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
# AgentVersion
|
|
2
2
|
|
|
3
|
+
*Part of [DecimalAI](https://decimal.ai). Most users want the Python SDK → [decimal-labs/decimalai-python](https://github.com/decimal-labs/decimalai-python).*
|
|
4
|
+
|
|
3
5
|
**Your agent changed. Is your saved data still valid?**
|
|
4
6
|
|
|
5
7
|
[](https://pypi.org/project/agentversion/)
|
|
8
|
+
[](https://pepy.tech/project/agentversion)
|
|
9
|
+
[](https://github.com/decimal-labs/agentversion/actions/workflows/ci.yml)
|
|
6
10
|
[](https://pypi.org/project/agentversion/)
|
|
7
11
|
[](https://pypi.org/project/agentversion/)
|
|
8
|
-
[](https://
|
|
12
|
+
[](https://github.com/decimal-labs/agentversion/blob/main/LICENSE)
|
|
9
13
|
|
|
10
14
|
When you ship a new version of an agent, everything you collected against the old one — production traces, eval datasets, SFT (supervised fine-tuning) examples — quietly drifts out of date. There's no `package.json` to pin an agent's contract, and no `git diff` to tell you what changed.
|
|
11
15
|
|
|
@@ -113,7 +117,9 @@ A manifest is plain JSON. The top says *which* version this is; `contract` holds
|
|
|
113
117
|
|
|
114
118
|
Each surface is hashed on its own, so the diff can say *"`tool_registry` changed, `prompt_stack` didn't"* instead of just *"the manifest changed."*
|
|
115
119
|
|
|
116
|
-
> Try it yourself — both [`examples/manifest/`](https://
|
|
120
|
+
> Try it yourself — both [`examples/manifest/`](https://github.com/decimal-labs/agentversion/tree/main/examples/manifest)
|
|
121
|
+
> manifests ship inside the `agentversion` wheel as well as in the repo; the commands below use the
|
|
122
|
+
> repo-relative paths, so clone first.
|
|
117
123
|
|
|
118
124
|
---
|
|
119
125
|
|
|
@@ -123,7 +129,7 @@ You probably already have observability and a trace store. None of them answer *
|
|
|
123
129
|
|
|
124
130
|
| You already have | What it gives you | What it doesn't |
|
|
125
131
|
|---|---|---|
|
|
126
|
-
| OpenTelemetry
|
|
132
|
+
| OpenTelemetry and the tracing tools built on it | rich execution traces | a versioned contract for the agent that produced them |
|
|
127
133
|
| A2A / ACP agent cards | runtime discovery + I/O types | version identity or data-compatibility |
|
|
128
134
|
| OpenAI JSONL / SFT files | a training format | provenance — *which agent version* produced each row |
|
|
129
135
|
|
|
@@ -142,7 +148,7 @@ Apache-2.0, no config — just needs Python 3.10+.
|
|
|
142
148
|
There are **two version numbers**, deliberately different:
|
|
143
149
|
|
|
144
150
|
- the **wire spec** is frozen at **v1.0** (stable format + conformance suite — safe to build against);
|
|
145
|
-
- this **Python package** is **
|
|
151
|
+
- this **Python package** is still **pre-1.0**, so its API may still shift.
|
|
146
152
|
|
|
147
153
|
(The `spec-v1.0` and PyPI badges above show each one.)
|
|
148
154
|
|
|
@@ -166,9 +172,11 @@ agentversion hash manifest.json # a content hash that ignores key order an
|
|
|
166
172
|
agentversion validate manifest.json # check it against the spec
|
|
167
173
|
```
|
|
168
174
|
|
|
169
|
-
**3. Diff two versions** —
|
|
175
|
+
**3. Diff two versions** — against the bundled examples. The paths are relative, so run this from a
|
|
176
|
+
checkout (`--compat` adds the keep/repair/replay/drop recommendation; `--json` for machine output):
|
|
170
177
|
|
|
171
178
|
```bash
|
|
179
|
+
git clone https://github.com/decimal-labs/agentversion && cd agentversion
|
|
172
180
|
agentversion diff examples/manifest/finance-agent-v1.json \
|
|
173
181
|
examples/manifest/finance-agent-v2.json --compat
|
|
174
182
|
```
|
|
@@ -181,7 +189,7 @@ agentversion diff examples/manifest/finance-agent-v1.json \
|
|
|
181
189
|
run: agentversion diff baseline-manifest.json current-manifest.json --fail-on-breaking
|
|
182
190
|
```
|
|
183
191
|
|
|
184
|
-
**Use it from Python** — every
|
|
192
|
+
**Use it from Python** — every API below is covered by the test suite:
|
|
185
193
|
|
|
186
194
|
```python
|
|
187
195
|
import json
|
|
@@ -189,17 +197,20 @@ from agentversion import AgentManifest, validate_manifest_file, hash_manifest
|
|
|
189
197
|
from agentversion.diff import diff_manifests
|
|
190
198
|
from agentversion.compatibility import classify_compatibility
|
|
191
199
|
|
|
192
|
-
old = json.load(open("finance-agent-v1.json"))
|
|
193
|
-
new = json.load(open("finance-agent-v2.json"))
|
|
200
|
+
old = json.load(open("examples/manifest/finance-agent-v1.json"))
|
|
201
|
+
new = json.load(open("examples/manifest/finance-agent-v2.json"))
|
|
194
202
|
|
|
195
203
|
# Validate + identify a version
|
|
196
|
-
assert validate_manifest_file("finance-agent-v2.json").valid
|
|
204
|
+
assert validate_manifest_file("examples/manifest/finance-agent-v2.json").valid
|
|
197
205
|
m = AgentManifest.model_validate(new)
|
|
198
206
|
print(m.agent_name, m.identity.overall_hash) # finance-agent sha256:767ebff1...
|
|
199
207
|
|
|
200
208
|
# Diff, then ask what to do with old data
|
|
201
209
|
result = diff_manifests(old, new)
|
|
202
210
|
print(result.summary.breaking_surfaces) # 5
|
|
211
|
+
|
|
212
|
+
# Pass no policy and the built-in fallback rules apply. They are deliberately
|
|
213
|
+
# non-destructive: the worst they will ever recommend is replay, never drop.
|
|
203
214
|
print(classify_compatibility(result).recommended_decision) # replay
|
|
204
215
|
```
|
|
205
216
|
|
|
@@ -232,10 +243,10 @@ The protocol is fully useful standalone:
|
|
|
232
243
|
|
|
233
244
|
1. **Track versions locally** — `init` to scaffold, `hash` for a stable id, `diff` between any two. No account, fully offline.
|
|
234
245
|
2. **Gate CI/CD** — `diff --fail-on-breaking` stops a breaking agent change from reaching production.
|
|
235
|
-
3. **Annotate traces** — stamp `identity.overall_hash` onto your OpenTelemetry spans as `agentversion.manifest_hash` for version-scoped filtering. See [`examples/integrations/otel_mapping.md`](https://
|
|
246
|
+
3. **Annotate traces** — stamp `identity.overall_hash` onto your OpenTelemetry spans as `agentversion.manifest_hash` for version-scoped filtering. See [`examples/integrations/otel_mapping.md`](https://github.com/decimal-labs/agentversion/blob/main/examples/integrations/otel_mapping.md), bundled in the package.
|
|
236
247
|
4. **Classify data compatibility** — `diff --compat` (or `decision generate`) gives a per-episode keep / repair / replay / drop verdict you can act on.
|
|
237
248
|
|
|
238
|
-
|
|
249
|
+
A manifest hash is just a string, so it drops into whatever trace store or eval tool you already run — put `identity.overall_hash` on the spans or dataset rows you keep, and the compatibility decisions sit alongside your eval pipeline as ordinary JSON.
|
|
239
250
|
|
|
240
251
|
---
|
|
241
252
|
|
|
@@ -243,13 +254,13 @@ It interoperates with LangSmith, Langfuse, Phoenix, and W&B — annotate their t
|
|
|
243
254
|
|
|
244
255
|
`agentversion` is an open spec so any tool, in any language, can produce interoperable manifests and diffs:
|
|
245
256
|
|
|
246
|
-
- [`spec/manifest.md`](https://
|
|
247
|
-
- [`spec/diff.md`](https://
|
|
248
|
-
- [`spec/compatibility-decision.md`](https://
|
|
249
|
-
- [`spec/replay.md`](https://
|
|
250
|
-
- [`spec/reference.md`](https://
|
|
257
|
+
- [`spec/manifest.md`](https://github.com/decimal-labs/agentversion/blob/main/spec/manifest.md) — the agent manifest
|
|
258
|
+
- [`spec/diff.md`](https://github.com/decimal-labs/agentversion/blob/main/spec/diff.md) — surface diffs, breaking vs non-breaking
|
|
259
|
+
- [`spec/compatibility-decision.md`](https://github.com/decimal-labs/agentversion/blob/main/spec/compatibility-decision.md) — keep / repair / replay / drop
|
|
260
|
+
- [`spec/replay.md`](https://github.com/decimal-labs/agentversion/blob/main/spec/replay.md) · [`spec/dataset.md`](https://github.com/decimal-labs/agentversion/blob/main/spec/dataset.md) — replay jobs and dataset objects with provenance
|
|
261
|
+
- [`spec/reference.md`](https://github.com/decimal-labs/agentversion/blob/main/spec/reference.md) — full schemas and validation rules · [`schemas/`](https://github.com/decimal-labs/agentversion/tree/main/schemas) — JSON Schemas
|
|
251
262
|
|
|
252
|
-
The full spec and JSON Schemas ship inside the `agentversion` wheel. [`CONFORMANCE.md`](https://
|
|
263
|
+
The full spec and JSON Schemas ship inside the `agentversion` wheel. [`CONFORMANCE.md`](https://github.com/decimal-labs/agentversion/blob/main/CONFORMANCE.md) + [`compatibility-tests/`](https://github.com/decimal-labs/agentversion/tree/main/compatibility-tests) are golden in/out pairs that any implementation must reproduce to claim conformance.
|
|
253
264
|
|
|
254
265
|
---
|
|
255
266
|
|
|
@@ -268,7 +279,7 @@ A manifest can carry the eval results that gated its release in `evaluation.gate
|
|
|
268
279
|
}
|
|
269
280
|
```
|
|
270
281
|
|
|
271
|
-
Those scores come from [`skillevaluation`](https://
|
|
282
|
+
Those scores come from [`skillevaluation`](https://github.com/decimal-labs/skillevaluation), the sibling open spec: `agentversion` versions the agent runtime itself (what an agent version *is* and what changed), while `skillevaluation` A/B-benchmarks a single skill (whether it actually helps).
|
|
272
283
|
|
|
273
284
|
The [`decimalai`](https://pypi.org/project/decimalai/) Python SDK builds on `agentversion` to add framework adapters (capture a manifest straight from your LangGraph/CrewAI app), trace capture, and managed replay — but you never need it to use the spec.
|
|
274
285
|
|
|
@@ -297,13 +308,13 @@ diff = diff_manifests(last_prod_manifest, manifest)
|
|
|
297
308
|
print(classify_compatibility(diff).recommended_decision)
|
|
298
309
|
```
|
|
299
310
|
|
|
300
|
-
This is the seam that makes `agentversion` the **open core** of the paid platform: the manifest the SDK captures *is* the format `agentversion diff` consumes, so you can reproduce the platform's diffs and verdicts entirely outside DecimalAI. A runnable version is in [`examples/integrations/decimalai_bridge.py`](https://
|
|
311
|
+
This is the seam that makes `agentversion` the **open core** of the paid platform: the manifest the SDK captures *is* the format `agentversion diff` consumes, so you can reproduce the platform's diffs and verdicts entirely outside DecimalAI. A runnable version is in [`examples/integrations/decimalai_bridge.py`](https://github.com/decimal-labs/agentversion/blob/main/examples/integrations/decimalai_bridge.py).
|
|
301
312
|
|
|
302
313
|
---
|
|
303
314
|
|
|
304
315
|
## Project
|
|
305
316
|
|
|
306
|
-
The spec is frozen at v1.0; the package is pre-1.0 (see [Install](#install)). Design decisions are logged in [`adrs/`](https://
|
|
317
|
+
The spec is frozen at v1.0; the package is pre-1.0 (see [Install](#install)). Design decisions are logged in [`adrs/`](https://github.com/decimal-labs/agentversion/tree/main/adrs), releases in [`CHANGELOG.md`](https://github.com/decimal-labs/agentversion/blob/main/CHANGELOG.md). Contributions — especially new conformance cases — are genuinely welcome; see [`CONTRIBUTING.md`](https://github.com/decimal-labs/agentversion/blob/main/CONTRIBUTING.md):
|
|
307
318
|
|
|
308
319
|
```bash
|
|
309
320
|
pip install agentversion
|
|
@@ -313,4 +324,8 @@ git clone https://github.com/decimal-labs/agentversion && cd agentversion
|
|
|
313
324
|
pip install -e ".[dev]" && pytest
|
|
314
325
|
```
|
|
315
326
|
|
|
316
|
-
Licensed under [Apache 2.0](https://
|
|
327
|
+
Licensed under [Apache 2.0](https://github.com/decimal-labs/agentversion/blob/main/LICENSE).
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
[Docs](https://docs.decimal.ai) · [Registry](https://app.decimal.ai/skills) · [SDK](https://github.com/decimal-labs/decimalai-python) · [skillevaluation](https://github.com/decimal-labs/skillevaluation) · [regression-check](https://github.com/decimal-labs/regression-check)
|
|
@@ -70,7 +70,13 @@ class CompatibilityPolicy(BaseModel):
|
|
|
70
70
|
kind: Literal["compatibility_policy"] = "compatibility_policy"
|
|
71
71
|
version: str = "0.1"
|
|
72
72
|
name: str = "default"
|
|
73
|
-
preset: Literal["strict", "default", "permissive", "custom"] | None =
|
|
73
|
+
preset: Literal["strict", "default", "permissive", "custom"] | None = Field(
|
|
74
|
+
"default",
|
|
75
|
+
description=(
|
|
76
|
+
"Provenance label only — recorded, not evaluated. "
|
|
77
|
+
"Per-surface rule blocks drive every decision."
|
|
78
|
+
),
|
|
79
|
+
)
|
|
74
80
|
|
|
75
81
|
prompt_stack: SurfaceRules | None = None
|
|
76
82
|
model_runtime: SurfaceRules | None = None
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
The single source of truth for how a producer's *flat* components (one entry per
|
|
4
4
|
tool / prompt / model / …) regroup into the contract-keyed surfaces the diff and
|
|
5
|
-
the identity hash are computed from.
|
|
6
|
-
(``ManifestSnapshot.to_agentversion``)
|
|
7
|
-
|
|
8
|
-
compute the *same* ``jcs-sha256`` identity hash for the same agent.
|
|
5
|
+
the identity hash are computed from. The DecimalAI platform calls this directly;
|
|
6
|
+
the DecimalAI SDK exporter (``ManifestSnapshot.to_agentversion``) mirrors it and
|
|
7
|
+
is held byte-identical to it by a cross-implementation test — so a producer and a
|
|
8
|
+
consumer compute the *same* ``jcs-sha256`` identity hash for the same agent.
|
|
9
9
|
|
|
10
10
|
Each component is a plain dict::
|
|
11
11
|
|
|
@@ -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
|
|
745
|
-
|
|
746
|
-
|
|
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
|
|
@@ -814,11 +814,9 @@ SURFACE_KEYS = [
|
|
|
814
814
|
"behavioral_policy",
|
|
815
815
|
]
|
|
816
816
|
|
|
817
|
-
#
|
|
818
|
-
#
|
|
819
|
-
#
|
|
820
|
-
# which previously had to be applied by hand in every translator copy (XC-1). An unknown component
|
|
821
|
-
# type maps to itself (so a new/custom surface is diffed generically rather than dropped).
|
|
817
|
+
# Routing from a producer's flat `component_type` to the contract SURFACE_KEY it lands in,
|
|
818
|
+
# including the singular→plural `guardrail`→`guardrails` case. A component type with no entry
|
|
819
|
+
# here maps to itself (so a new/custom surface is diffed generically rather than dropped).
|
|
822
820
|
COMPONENT_TYPE_TO_SURFACE: dict[str, str] = {
|
|
823
821
|
"tool": "tool_registry",
|
|
824
822
|
"skill": "skill_registry",
|
|
@@ -834,8 +832,8 @@ COMPONENT_TYPE_TO_SURFACE: dict[str, str] = {
|
|
|
834
832
|
def surface_key_for_component(component_type: str) -> str:
|
|
835
833
|
"""The contract surface a flat ``component_type`` belongs to (identity for unknown types).
|
|
836
834
|
|
|
837
|
-
|
|
838
|
-
|
|
835
|
+
Looks ``component_type`` up in ``COMPONENT_TYPE_TO_SURFACE`` (for example
|
|
836
|
+
``guardrail``→``guardrails``) and returns it unchanged when it has no entry.
|
|
839
837
|
"""
|
|
840
838
|
return COMPONENT_TYPE_TO_SURFACE.get(component_type, component_type)
|
|
841
839
|
|