agent-handshake 0.7.0__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.
Files changed (149) hide show
  1. agent_handshake-0.7.0/.coderabbit.yaml +23 -0
  2. agent_handshake-0.7.0/.github/ISSUE_TEMPLATE/bug_report.yml +48 -0
  3. agent_handshake-0.7.0/.github/ISSUE_TEMPLATE/feature_request.yml +30 -0
  4. agent_handshake-0.7.0/.github/dependabot.yml +28 -0
  5. agent_handshake-0.7.0/.github/pull_request_template.md +22 -0
  6. agent_handshake-0.7.0/.github/workflows/ci.yml +71 -0
  7. agent_handshake-0.7.0/.github/workflows/publish.yml +41 -0
  8. agent_handshake-0.7.0/.gitignore +151 -0
  9. agent_handshake-0.7.0/.pre-commit-config.yaml +7 -0
  10. agent_handshake-0.7.0/CHANGELOG.md +175 -0
  11. agent_handshake-0.7.0/CONTRIBUTING.md +60 -0
  12. agent_handshake-0.7.0/LICENSE +191 -0
  13. agent_handshake-0.7.0/Makefile +26 -0
  14. agent_handshake-0.7.0/NOTES.md +96 -0
  15. agent_handshake-0.7.0/PKG-INFO +493 -0
  16. agent_handshake-0.7.0/README.md +434 -0
  17. agent_handshake-0.7.0/SECURITY.md +17 -0
  18. agent_handshake-0.7.0/action.yml +56 -0
  19. agent_handshake-0.7.0/docs/architecture.md +58 -0
  20. agent_handshake-0.7.0/docs/ci-integration.md +74 -0
  21. agent_handshake-0.7.0/docs/cli-reference.md +100 -0
  22. agent_handshake-0.7.0/docs/concepts.md +33 -0
  23. agent_handshake-0.7.0/docs/demo.gif +0 -0
  24. agent_handshake-0.7.0/docs/diagrams/change-workflow.svg +71 -0
  25. agent_handshake-0.7.0/docs/diagrams/how-it-works.svg +67 -0
  26. agent_handshake-0.7.0/docs/getting-started.md +8 -0
  27. agent_handshake-0.7.0/docs/writing-adapters.md +104 -0
  28. agent_handshake-0.7.0/docs/writing-specs.md +78 -0
  29. agent_handshake-0.7.0/examples/customer_support/README.md +70 -0
  30. agent_handshake-0.7.0/examples/customer_support/agents/resolution.py +30 -0
  31. agent_handshake-0.7.0/examples/customer_support/agents/triage.py +38 -0
  32. agent_handshake-0.7.0/examples/customer_support/handshake/adapters/__init__.py +9 -0
  33. agent_handshake-0.7.0/examples/customer_support/handshake/adapters/resolution_adapter.py +13 -0
  34. agent_handshake-0.7.0/examples/customer_support/handshake/adapters/triage_adapter.py +13 -0
  35. agent_handshake-0.7.0/examples/customer_support/handshake/handshake.yaml +20 -0
  36. agent_handshake-0.7.0/examples/customer_support/handshake/scenarios/support_scenarios.yaml +31 -0
  37. agent_handshake-0.7.0/examples/customer_support/handshake/snapshots/resolution-agent/billing_overcharge_185fe02a5c6f.json +25 -0
  38. agent_handshake-0.7.0/examples/customer_support/handshake/snapshots/resolution-agent/general_inquiry_08b03d704f62.json +25 -0
  39. agent_handshake-0.7.0/examples/customer_support/handshake/snapshots/resolution-agent/product_defect_69524abe4d67.json +25 -0
  40. agent_handshake-0.7.0/examples/customer_support/handshake/snapshots/resolution-agent/shipping_delay_52c779d38d0e.json +25 -0
  41. agent_handshake-0.7.0/examples/customer_support/handshake/snapshots/triage-agent/billing_overcharge_4701dd165420.json +22 -0
  42. agent_handshake-0.7.0/examples/customer_support/handshake/snapshots/triage-agent/general_inquiry_01557b92e9af.json +22 -0
  43. agent_handshake-0.7.0/examples/customer_support/handshake/snapshots/triage-agent/product_defect_165f0478e401.json +22 -0
  44. agent_handshake-0.7.0/examples/customer_support/handshake/snapshots/triage-agent/shipping_delay_8e770c534edc.json +22 -0
  45. agent_handshake-0.7.0/examples/customer_support/handshake/specs/triage-to-resolution.yaml +44 -0
  46. agent_handshake-0.7.0/examples/customer_support/tests/test_specs.py +55 -0
  47. agent_handshake-0.7.0/pyproject.toml +109 -0
  48. agent_handshake-0.7.0/scripts/demo_gif.py +239 -0
  49. agent_handshake-0.7.0/src/agent_handshake/__init__.py +74 -0
  50. agent_handshake-0.7.0/src/agent_handshake/_internal/__init__.py +1 -0
  51. agent_handshake-0.7.0/src/agent_handshake/_internal/hashing.py +23 -0
  52. agent_handshake-0.7.0/src/agent_handshake/_internal/safe_eval.py +119 -0
  53. agent_handshake-0.7.0/src/agent_handshake/_internal/types.py +14 -0
  54. agent_handshake-0.7.0/src/agent_handshake/adapters/__init__.py +1 -0
  55. agent_handshake-0.7.0/src/agent_handshake/adapters/a2a_adapter.py +256 -0
  56. agent_handshake-0.7.0/src/agent_handshake/adapters/base.py +68 -0
  57. agent_handshake-0.7.0/src/agent_handshake/adapters/function_adapter.py +83 -0
  58. agent_handshake-0.7.0/src/agent_handshake/adapters/http_adapter.py +105 -0
  59. agent_handshake-0.7.0/src/agent_handshake/adapters/langchain_adapter.py +94 -0
  60. agent_handshake-0.7.0/src/agent_handshake/cli/__init__.py +1 -0
  61. agent_handshake-0.7.0/src/agent_handshake/cli/diff_cmd.py +132 -0
  62. agent_handshake-0.7.0/src/agent_handshake/cli/infer_cmd.py +140 -0
  63. agent_handshake-0.7.0/src/agent_handshake/cli/init_cmd.py +179 -0
  64. agent_handshake-0.7.0/src/agent_handshake/cli/main.py +100 -0
  65. agent_handshake-0.7.0/src/agent_handshake/cli/pipeline_cmd.py +175 -0
  66. agent_handshake-0.7.0/src/agent_handshake/cli/record_cmd.py +123 -0
  67. agent_handshake-0.7.0/src/agent_handshake/cli/skill_cmd.py +46 -0
  68. agent_handshake-0.7.0/src/agent_handshake/cli/test_cmd.py +279 -0
  69. agent_handshake-0.7.0/src/agent_handshake/config/__init__.py +1 -0
  70. agent_handshake-0.7.0/src/agent_handshake/config/loader.py +63 -0
  71. agent_handshake-0.7.0/src/agent_handshake/config/settings.py +41 -0
  72. agent_handshake-0.7.0/src/agent_handshake/diff/__init__.py +1 -0
  73. agent_handshake-0.7.0/src/agent_handshake/diff/engine.py +129 -0
  74. agent_handshake-0.7.0/src/agent_handshake/diff/report.py +53 -0
  75. agent_handshake-0.7.0/src/agent_handshake/diff/semantic.py +98 -0
  76. agent_handshake-0.7.0/src/agent_handshake/diff/structural.py +96 -0
  77. agent_handshake-0.7.0/src/agent_handshake/exceptions.py +87 -0
  78. agent_handshake-0.7.0/src/agent_handshake/infer/__init__.py +1 -0
  79. agent_handshake-0.7.0/src/agent_handshake/infer/builder.py +155 -0
  80. agent_handshake-0.7.0/src/agent_handshake/infer/check.py +97 -0
  81. agent_handshake-0.7.0/src/agent_handshake/infer/consumer.py +276 -0
  82. agent_handshake-0.7.0/src/agent_handshake/pipeline/__init__.py +1 -0
  83. agent_handshake-0.7.0/src/agent_handshake/pipeline/dag.py +165 -0
  84. agent_handshake-0.7.0/src/agent_handshake/pipeline/executor.py +166 -0
  85. agent_handshake-0.7.0/src/agent_handshake/pipeline/trace.py +68 -0
  86. agent_handshake-0.7.0/src/agent_handshake/policy/__init__.py +1 -0
  87. agent_handshake-0.7.0/src/agent_handshake/policy/builtin.py +59 -0
  88. agent_handshake-0.7.0/src/agent_handshake/policy/custom.py +57 -0
  89. agent_handshake-0.7.0/src/agent_handshake/policy/engine.py +153 -0
  90. agent_handshake-0.7.0/src/agent_handshake/project.py +118 -0
  91. agent_handshake-0.7.0/src/agent_handshake/py.typed +1 -0
  92. agent_handshake-0.7.0/src/agent_handshake/pytest_plugin.py +219 -0
  93. agent_handshake-0.7.0/src/agent_handshake/reporting/__init__.py +1 -0
  94. agent_handshake-0.7.0/src/agent_handshake/reporting/console.py +143 -0
  95. agent_handshake-0.7.0/src/agent_handshake/reporting/github.py +110 -0
  96. agent_handshake-0.7.0/src/agent_handshake/reporting/junit.py +57 -0
  97. agent_handshake-0.7.0/src/agent_handshake/reporting/markdown.py +55 -0
  98. agent_handshake-0.7.0/src/agent_handshake/semantic/__init__.py +1 -0
  99. agent_handshake-0.7.0/src/agent_handshake/semantic/embeddings.py +50 -0
  100. agent_handshake-0.7.0/src/agent_handshake/semantic/engine.py +126 -0
  101. agent_handshake-0.7.0/src/agent_handshake/semantic/similarity.py +31 -0
  102. agent_handshake-0.7.0/src/agent_handshake/skill/SKILL.md +109 -0
  103. agent_handshake-0.7.0/src/agent_handshake/snapshot/__init__.py +1 -0
  104. agent_handshake-0.7.0/src/agent_handshake/snapshot/baseline.py +77 -0
  105. agent_handshake-0.7.0/src/agent_handshake/snapshot/fingerprint.py +56 -0
  106. agent_handshake-0.7.0/src/agent_handshake/snapshot/recorder.py +69 -0
  107. agent_handshake-0.7.0/src/agent_handshake/snapshot/replay.py +50 -0
  108. agent_handshake-0.7.0/src/agent_handshake/snapshot/store.py +199 -0
  109. agent_handshake-0.7.0/src/agent_handshake/spec/__init__.py +1 -0
  110. agent_handshake-0.7.0/src/agent_handshake/spec/checker.py +101 -0
  111. agent_handshake-0.7.0/src/agent_handshake/spec/loader.py +90 -0
  112. agent_handshake-0.7.0/src/agent_handshake/spec/registry.py +50 -0
  113. agent_handshake-0.7.0/src/agent_handshake/spec/schema.py +89 -0
  114. agent_handshake-0.7.0/src/agent_handshake/spec/validator.py +83 -0
  115. agent_handshake-0.7.0/tests/__init__.py +1 -0
  116. agent_handshake-0.7.0/tests/conftest.py +93 -0
  117. agent_handshake-0.7.0/tests/test_a2a_interop.py +175 -0
  118. agent_handshake-0.7.0/tests/test_adapters_a2a.py +284 -0
  119. agent_handshake-0.7.0/tests/test_adapters_function.py +73 -0
  120. agent_handshake-0.7.0/tests/test_adapters_http.py +67 -0
  121. agent_handshake-0.7.0/tests/test_adapters_langchain.py +59 -0
  122. agent_handshake-0.7.0/tests/test_cli_diff.py +169 -0
  123. agent_handshake-0.7.0/tests/test_cli_infer.py +209 -0
  124. agent_handshake-0.7.0/tests/test_cli_init.py +98 -0
  125. agent_handshake-0.7.0/tests/test_cli_pipeline.py +203 -0
  126. agent_handshake-0.7.0/tests/test_cli_record.py +202 -0
  127. agent_handshake-0.7.0/tests/test_cli_test.py +362 -0
  128. agent_handshake-0.7.0/tests/test_config_loader.py +64 -0
  129. agent_handshake-0.7.0/tests/test_diff_semantic.py +43 -0
  130. agent_handshake-0.7.0/tests/test_diff_structural.py +77 -0
  131. agent_handshake-0.7.0/tests/test_exceptions.py +213 -0
  132. agent_handshake-0.7.0/tests/test_infer_builder.py +151 -0
  133. agent_handshake-0.7.0/tests/test_infer_check.py +117 -0
  134. agent_handshake-0.7.0/tests/test_infer_consumer.py +167 -0
  135. agent_handshake-0.7.0/tests/test_pipeline_dag.py +92 -0
  136. agent_handshake-0.7.0/tests/test_pipeline_executor.py +70 -0
  137. agent_handshake-0.7.0/tests/test_policy_builtin.py +49 -0
  138. agent_handshake-0.7.0/tests/test_policy_engine.py +61 -0
  139. agent_handshake-0.7.0/tests/test_pytest_plugin.py +179 -0
  140. agent_handshake-0.7.0/tests/test_reporting_console.py +57 -0
  141. agent_handshake-0.7.0/tests/test_reporting_markdown.py +57 -0
  142. agent_handshake-0.7.0/tests/test_safe_eval.py +122 -0
  143. agent_handshake-0.7.0/tests/test_semantic_engine.py +92 -0
  144. agent_handshake-0.7.0/tests/test_skill.py +97 -0
  145. agent_handshake-0.7.0/tests/test_snapshot_fingerprint.py +46 -0
  146. agent_handshake-0.7.0/tests/test_snapshot_replay.py +52 -0
  147. agent_handshake-0.7.0/tests/test_snapshot_store.py +187 -0
  148. agent_handshake-0.7.0/tests/test_spec_loader.py +93 -0
  149. agent_handshake-0.7.0/tests/test_spec_validator.py +111 -0
@@ -0,0 +1,23 @@
1
+ # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
2
+ language: en-US
3
+
4
+ reviews:
5
+ profile: chill
6
+ request_changes_workflow: false
7
+ high_level_summary: true
8
+ review_status: true
9
+ collapse_walkthrough: true
10
+ poem: false
11
+ sequence_diagrams: false
12
+ # Review the shipped code and its tests; docs, examples and assets are skipped.
13
+ path_filters:
14
+ - "src/**"
15
+ - "tests/**"
16
+ - "action.yml"
17
+ - ".github/workflows/**"
18
+ auto_review:
19
+ enabled: true
20
+ drafts: false
21
+
22
+ chat:
23
+ auto_reply: true
@@ -0,0 +1,48 @@
1
+ name: Bug report
2
+ description: Something is broken or behaving unexpectedly.
3
+ labels: ["bug"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Thanks for taking the time to report a bug. Please fill in as much as you can.
9
+
10
+ - type: input
11
+ id: version
12
+ attributes:
13
+ label: agent-handshake version
14
+ placeholder: "0.7.0"
15
+ validations:
16
+ required: true
17
+
18
+ - type: input
19
+ id: python
20
+ attributes:
21
+ label: Python version
22
+ placeholder: "3.12"
23
+ validations:
24
+ required: true
25
+
26
+ - type: textarea
27
+ id: description
28
+ attributes:
29
+ label: Description
30
+ description: What happened? What did you expect to happen?
31
+ validations:
32
+ required: true
33
+
34
+ - type: textarea
35
+ id: repro
36
+ attributes:
37
+ label: Minimal reproduction
38
+ description: The smallest code / config that triggers the issue.
39
+ render: python
40
+ validations:
41
+ required: true
42
+
43
+ - type: textarea
44
+ id: traceback
45
+ attributes:
46
+ label: Traceback
47
+ description: Paste the full error output here (if any).
48
+ render: text
@@ -0,0 +1,30 @@
1
+ name: Feature request
2
+ description: Propose a new feature or improvement.
3
+ labels: ["enhancement"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Before submitting, search open issues to avoid duplicates.
9
+
10
+ - type: textarea
11
+ id: problem
12
+ attributes:
13
+ label: Problem
14
+ description: What problem does this solve? What use case is blocked without it?
15
+ validations:
16
+ required: true
17
+
18
+ - type: textarea
19
+ id: proposal
20
+ attributes:
21
+ label: Proposed solution
22
+ description: What should the feature look like? API sketches, CLI flags, config keys — whatever helps.
23
+ validations:
24
+ required: true
25
+
26
+ - type: textarea
27
+ id: alternatives
28
+ attributes:
29
+ label: Alternatives considered
30
+ description: What workarounds exist today? Why are they insufficient?
@@ -0,0 +1,28 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: pip
4
+ directory: "/"
5
+ schedule:
6
+ interval: weekly
7
+ day: monday
8
+ groups:
9
+ dev-deps:
10
+ patterns:
11
+ - "ruff"
12
+ - "mypy"
13
+ - "pytest*"
14
+ - "pre-commit"
15
+ core-deps:
16
+ patterns:
17
+ - "typer"
18
+ - "rich"
19
+ - "pyyaml"
20
+ - "pydantic"
21
+ - "jsonschema"
22
+ - "httpx"
23
+
24
+ - package-ecosystem: github-actions
25
+ directory: "/"
26
+ schedule:
27
+ interval: weekly
28
+ day: monday
@@ -0,0 +1,22 @@
1
+ ## Summary
2
+
3
+ <!-- What does this PR do? One paragraph is enough. -->
4
+
5
+ ## Changes
6
+
7
+ <!-- Bullet list of the concrete changes made. -->
8
+
9
+ -
10
+
11
+ ## Test plan
12
+
13
+ <!-- How was this tested? Check all that apply. -->
14
+
15
+ - [ ] Added / updated unit tests
16
+ - [ ] All existing tests pass (`pytest tests/`)
17
+ - [ ] Lint and format clean (`ruff check src/ tests/ && ruff format --check src/ tests/`)
18
+ - [ ] Type check passes (`mypy src/`)
19
+
20
+ ## Related issues
21
+
22
+ <!-- Fixes #N / Related to #N / N/A -->
@@ -0,0 +1,71 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+ workflow_call:
9
+
10
+ permissions:
11
+ contents: read
12
+
13
+ jobs:
14
+ test:
15
+ name: Test (Python ${{ matrix.python-version }})
16
+ runs-on: ubuntu-latest
17
+ strategy:
18
+ fail-fast: false
19
+ matrix:
20
+ python-version: ["3.11", "3.12", "3.13"]
21
+ steps:
22
+ - uses: actions/checkout@v6
23
+
24
+ - name: Set up Python ${{ matrix.python-version }}
25
+ uses: actions/setup-python@v6
26
+ with:
27
+ python-version: ${{ matrix.python-version }}
28
+
29
+ - name: Install dependencies
30
+ run: pip install -e ".[dev,langchain]"
31
+
32
+ - name: Lint
33
+ run: ruff check src/ tests/
34
+
35
+ - name: Format check
36
+ run: ruff format --check src/ tests/
37
+
38
+ - name: Type check
39
+ run: mypy src/
40
+
41
+ - name: Test with coverage
42
+ run: pytest tests/ -v --tb=short --cov=agent_handshake --cov-report=term-missing
43
+
44
+ - name: Verify clean import (no optional deps)
45
+ run: |
46
+ pip install -e "."
47
+ python -c "import agent_handshake; print(agent_handshake.__version__)"
48
+ python -c "from agent_handshake import load_spec, validate_output, FunctionAdapter, SnapshotStore"
49
+
50
+ - name: Verify no unsafe yaml.load
51
+ run: |
52
+ if grep -rn "yaml\.load\b" src/; then
53
+ echo "FAIL: unsafe yaml.load found"
54
+ exit 1
55
+ else
56
+ echo "PASS: only yaml.safe_load used"
57
+ fi
58
+
59
+ action:
60
+ name: GitHub Action on the example
61
+ runs-on: ubuntu-latest
62
+ steps:
63
+ - uses: actions/checkout@v6
64
+
65
+ - name: Run the repository action with this commit
66
+ uses: ./
67
+ with:
68
+ package: ${{ github.workspace }}
69
+ working-directory: examples/customer_support
70
+ config: handshake/handshake.yaml
71
+ args: --no-semantic
@@ -0,0 +1,41 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ ci:
9
+ uses: ./.github/workflows/ci.yml
10
+
11
+ publish:
12
+ needs: ci
13
+ runs-on: ubuntu-latest
14
+ environment: pypi
15
+ permissions:
16
+ id-token: write
17
+ contents: read
18
+ steps:
19
+ - uses: actions/checkout@v6
20
+
21
+ - name: Set up Python
22
+ uses: actions/setup-python@v6
23
+ with:
24
+ python-version: "3.12"
25
+
26
+ - name: Install package
27
+ run: pip install -e "."
28
+
29
+ - name: Verify tag matches __version__
30
+ run: |
31
+ TAG="${GITHUB_REF_NAME#v}"
32
+ VER=$(python -c "import agent_handshake; print(agent_handshake.__version__)")
33
+ if [ "$TAG" != "$VER" ]; then
34
+ echo "Tag $TAG != __version__ $VER" && exit 1
35
+ fi
36
+
37
+ - name: Build
38
+ run: pip install build && python -m build
39
+
40
+ - name: Publish
41
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,151 @@
1
+ # ========================
2
+ # Python
3
+ # ========================
4
+ __pycache__/
5
+ *.py[cod]
6
+ *$py.class
7
+ *.so
8
+ *.pyo
9
+
10
+ # Distribution / packaging
11
+ dist/
12
+ build/
13
+ eggs/
14
+ *.egg
15
+ *.egg-info/
16
+ src/*.egg-info/
17
+ *.whl
18
+ sdist/
19
+ develop-eggs/
20
+ .installed.cfg
21
+ lib/
22
+ lib64/
23
+ parts/
24
+ var/
25
+ MANIFEST
26
+
27
+ # PyInstaller
28
+ *.manifest
29
+ *.spec
30
+
31
+ # Installer logs
32
+ pip-log.txt
33
+ pip-delete-this-directory.txt
34
+
35
+ # ========================
36
+ # Virtual environments
37
+ # ========================
38
+ .venv/
39
+ venv/
40
+ ENV/
41
+ env/
42
+ .python-version
43
+
44
+ # ========================
45
+ # Testing
46
+ # ========================
47
+ .pytest_cache/
48
+ .coverage
49
+ .coverage.*
50
+ htmlcov/
51
+ .tox/
52
+ .nox/
53
+ nosetests.xml
54
+ coverage.xml
55
+ *.cover
56
+ *.py,cover
57
+ .hypothesis/
58
+
59
+ # ========================
60
+ # Type checking & Linting
61
+ # ========================
62
+ .mypy_cache/
63
+ .dmypy.json
64
+ dmypy.json
65
+ .pytype/
66
+ .ruff_cache/
67
+ .pyre/
68
+
69
+ # ========================
70
+ # IDE / Editors
71
+ # ========================
72
+ .vscode/
73
+ !.vscode/settings.json
74
+ !.vscode/tasks.json
75
+ !.vscode/launch.json
76
+ !.vscode/extensions.json
77
+ .idea/
78
+ *.swp
79
+ *.swo
80
+ *~
81
+ .project
82
+ .settings/
83
+ .history/
84
+ *.code-workspace
85
+ *.sublime-project
86
+ *.sublime-workspace
87
+ .spyderproject
88
+ .spyproject
89
+ .ropeproject
90
+
91
+ # ========================
92
+ # OS files
93
+ # ========================
94
+ .DS_Store
95
+ .DS_Store?
96
+ ._*
97
+ .Spotlight-V100
98
+ .Trashes
99
+ ehthumbs.db
100
+ Thumbs.db
101
+ Desktop.ini
102
+ *.bak
103
+ *.tmp
104
+ *.log
105
+
106
+ # ========================
107
+ # Environment / Secrets
108
+ # ========================
109
+ .env
110
+ .env.local
111
+ .env.*.local
112
+ *.pem
113
+ *.key
114
+
115
+ # ========================
116
+ # Jupyter Notebooks
117
+ # ========================
118
+ .ipynb_checkpoints/
119
+ *.ipynb_checkpoints
120
+
121
+ # ========================
122
+ # Documentation builds
123
+ # ========================
124
+ site/
125
+ _build/
126
+ docs/_build/
127
+
128
+ # ========================
129
+ # Profiling
130
+ # ========================
131
+ *.prof
132
+ *.lprof
133
+
134
+ # ========================
135
+ # Celery
136
+ # ========================
137
+ celerybeat-schedule
138
+ celerybeat.pid
139
+
140
+ # ========================
141
+ # agent-handshake specific
142
+ # ========================
143
+
144
+ # Generated reports (not committed)
145
+ handshake/reports/
146
+ *.junit.xml
147
+ report.md
148
+
149
+ # NOTE: Snapshots ARE committed to git!
150
+ # They are your test baselines for deterministic replay.
151
+ # Do NOT add handshake/snapshots/ to .gitignore.
@@ -0,0 +1,7 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.5.0
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix]
7
+ - id: ruff-format
@@ -0,0 +1,175 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
+ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.7.0] - 2026-10-16
11
+
12
+ ### Changed
13
+ - The project is renamed from a2a-spec to agent-handshake. The A2A protocol is
14
+ only one of the agent types it tests, and the old name read as an A2A-only
15
+ tool. New names: package `agent-handshake`, module `agent_handshake`,
16
+ command `handshake`, config file `handshake.yaml`, project folder
17
+ `handshake/`, pytest options `--handshake`, `--handshake-config`,
18
+ `--handshake-no-semantic`, ini option `handshake_config`, fixture
19
+ `handshake_check`, and the GitHub Action `padobrik/agent-handshake`.
20
+ `HandshakeError` and `HandshakeConfig` replace `A2ASpecError` and
21
+ `A2ASpecConfig`. The old names are not kept: the project had no users yet.
22
+
23
+ ### Added
24
+ - `A2AAdapter` reads file parts. They go under `"files"` in the output: a URL
25
+ file keeps its `url`, a raw file is stored as `size` and `sha256`, and
26
+ `filename` and `mediaType` are kept. Before, a reply with a file part
27
+ raised `AdapterError`.
28
+
29
+ ## [0.6.0] - 2026-10-16
30
+
31
+ ### Added
32
+ - `a2aspec infer` follows nested reads: `data["customer"]["tier"]`,
33
+ `data.get("customer", {}).get("tier")`, `"tier" in data["customer"]` and
34
+ reads through a local name such as `customer = data["customer"]`. The
35
+ generated spec has nested object schemas with their own `required` lists.
36
+ - `a2aspec infer --check` compares nested reads with the nested schema. A spec
37
+ generated by an earlier version covers only the top-level object, so
38
+ `--check` now reports the nested fields; run `a2aspec infer --force` again.
39
+ - `a2aspec record --agent ID` records only the given agents (repeatable).
40
+ - A scenario can have an `agents` list. `a2aspec record` and
41
+ `a2aspec test --live` then call only those agents with its input. Before,
42
+ every agent in `ADAPTERS` got every scenario.
43
+
44
+ ### Changed
45
+ - `a2aspec pipeline test` checks policy and semantic rules at each step, not
46
+ only structural rules. It has `--semantic/--no-semantic` like `a2aspec test`.
47
+ Without the `semantic` extra, a pipeline whose specs have semantic rules now
48
+ exits 1 with an install hint; pass `--no-semantic` to skip them.
49
+
50
+ ## [0.5.0] - 2026-10-16
51
+
52
+ ### Added
53
+ - A GitHub Action (`uses: padobrik/a2a-spec@v0.5.0`) that installs a2a-spec,
54
+ runs `a2aspec infer --check` and `a2aspec test --format github`. CI runs it
55
+ on the example project.
56
+ - Scenario `expectations` are checked: `a2aspec test` (replay and live) and the
57
+ pytest plugin fail when an agent's output does not have the expected value.
58
+ Before, the field in scenario files was ignored.
59
+
60
+ ### Fixed
61
+ - `--format github` annotations use paths relative to the repository root, so
62
+ they attach to the spec file when the project is in a subdirectory.
63
+ - `a2aspec pipeline test --mode live` never loaded `ADAPTERS` and failed on
64
+ the first agent. A failed agent call now fails only its test case, steps
65
+ without a spec show `NO SPEC` instead of `FAIL`, and unknown modes are
66
+ rejected.
67
+
68
+ ## [0.4.0] - 2026-10-16
69
+
70
+ ### Added
71
+ - `a2aspec infer --check` compares every inferred spec with its consumer's
72
+ current code and fails when the code reads a field the spec does not cover.
73
+ Inferred specs record their consumer in the new `inferred_from` field, and
74
+ the pytest plugin runs the same check as a `consumer_code` test.
75
+ - `a2aspec test --live` calls each spec's producer through `ADAPTERS` with
76
+ every scenario and checks the live output without saving it. Before, the
77
+ flag only changed the header and still replayed snapshots.
78
+
79
+ ### Changed
80
+ - `a2aspec diff` rates a new field as LOW instead of HIGH, so adding a field
81
+ no longer fails CI; a removed field stays HIGH.
82
+
83
+ ### Fixed
84
+ - `a2aspec record --suite` was ignored; it now records one scenario file.
85
+ - `a2aspec test --format` was ignored. `junit` and `markdown` now print only
86
+ the report on stdout, and the new `github` format adds a GitHub Actions
87
+ annotation for each failure. Unknown formats are rejected.
88
+
89
+ ## [0.3.2] - 2026-10-16
90
+
91
+ ### Changed
92
+ - README rewritten in Simplified Technical English with a verified Get started
93
+ guide and diagrams; it no longer documents `--format` and `--live`.
94
+
95
+ ### Fixed
96
+ - The `a2aspec init` example spec: its PII regexes were double-escaped and
97
+ matched nothing, and its semantic rule lacked `source_field`/`target_field`
98
+ and always failed.
99
+ - `a2aspec init` writes an `ADAPTERS` template and next steps that match the
100
+ current workflow.
101
+
102
+ ## [0.3.1] - 2026-10-15
103
+
104
+ ### Fixed
105
+ - `a2aspec record` never found project adapters: `a2a_spec/adapters` was
106
+ shadowed by the library's own subpackage. Adapters now load from
107
+ `adapters_dir` (default `./a2a_spec/adapters`) and import errors are reported.
108
+ - The customer support example records and imports correctly from its own
109
+ directory.
110
+ - The `[record]`, `[done]` and `[diff]` labels were swallowed by rich markup.
111
+
112
+ ## [0.3.0] - 2026-10-15
113
+
114
+ ### Added
115
+ - `A2AAdapter` calls agents that implement the A2A protocol 1.0 through
116
+ their Agent Card and the JSON-RPC binding; the card's version is recorded
117
+ in snapshots.
118
+
119
+ ### Changed
120
+ - `Recorder` reads adapter metadata after the call instead of before.
121
+
122
+ ## [0.2.0] - 2026-10-15
123
+
124
+ ### Added
125
+ - `a2aspec infer` generates a consumer-driven spec from the fields a consumer
126
+ function reads and the producer's recorded snapshots.
127
+ - pytest plugin: with `--a2a` or the `a2a_config` ini option, spec files are
128
+ collected as tests (one per snapshot); the `a2a_check` fixture validates
129
+ live outputs.
130
+ - `a2aspec skill` exports a bundled agent skill for coding agents.
131
+ - `a2aspec diff --base REF` selects the git revision used as baseline.
132
+ - `a2aspec test` evaluates `embedding_similarity` semantic rules against the
133
+ recorded input and output of each snapshot; `--no-semantic` skips them.
134
+ - `LangChainAdapter` is exported from the package root.
135
+
136
+ ### Changed
137
+ - **Breaking:** `a2aspec diff` requires snapshots tracked in git; it compares
138
+ against the version at `--base` (default `HEAD`).
139
+ - Semantic rules using `entailment` or `language_detection` now fail with
140
+ "not implemented" instead of being silently ignored.
141
+ - Custom policy validators receive the snapshot input instead of an empty dict.
142
+ - The result header reports FAIL when any layer fails, not only structural.
143
+ - Widened upper bounds for rich, langchain-core, sentence-transformers and dev tools.
144
+
145
+ ### Fixed
146
+ - `a2aspec diff` reported no differences after re-recording, because
147
+ recording overwrites the snapshot file; it now compares against the
148
+ committed version and reports new and deleted scenarios.
149
+ - `a2aspec diff` crashed without the `semantic` extra instead of falling back
150
+ to token overlap.
151
+ - `LangChainAdapter` returns `{"content": ...}` for chat messages and uses
152
+ `model_dump()` for pydantic models instead of the deprecated `.dict()`.
153
+
154
+ ## [0.1.0] - 2026-02-19
155
+
156
+ ### Added
157
+ - Initial public release of a2a-spec.
158
+ - `SnapshotStore` with path-traversal protection.
159
+ - `DiffEngine` for structural and semantic diff of agent outputs.
160
+ - `PipelineExecutor` for DAG-based multi-agent pipeline testing.
161
+ - CLI commands: `record`, `test`, `diff`, `pipeline`, `init`.
162
+ - Frozen dataclasses for `FieldDiff`, `SemanticComparison`, `PolicyResult`.
163
+ - Structured logging via `logging.getLogger(__name__)` in all modules.
164
+ - CI matrix across Python 3.11, 3.12, 3.13.
165
+ - Trusted Publishing workflow for PyPI releases.
166
+
167
+ [0.7.0]: https://github.com/padobrik/agent-handshake/releases/tag/v0.7.0
168
+ [0.6.0]: https://github.com/padobrik/a2a-spec/releases/tag/v0.6.0
169
+ [0.5.0]: https://github.com/padobrik/a2a-spec/releases/tag/v0.5.0
170
+ [0.4.0]: https://github.com/padobrik/a2a-spec/releases/tag/v0.4.0
171
+ [0.3.2]: https://github.com/padobrik/a2a-spec/releases/tag/v0.3.2
172
+ [0.3.1]: https://github.com/padobrik/a2a-spec/releases/tag/v0.3.1
173
+ [0.3.0]: https://github.com/padobrik/a2a-spec/releases/tag/v0.3.0
174
+ [0.2.0]: https://github.com/padobrik/a2a-spec/releases/tag/v0.2.0
175
+ [0.1.0]: https://github.com/padobrik/a2a-spec/releases/tag/v0.1.0
@@ -0,0 +1,60 @@
1
+ # Contributing to agent-handshake
2
+
3
+ ## Development setup
4
+
5
+ ```bash
6
+ git clone https://github.com/padobrik/agent-handshake.git
7
+ cd agent-handshake
8
+ pip install -e ".[dev]"
9
+ ```
10
+
11
+ To install optional extras for semantic and LangChain adapters:
12
+
13
+ ```bash
14
+ pip install -e ".[dev,semantic,langchain]"
15
+ ```
16
+
17
+ ## Running the checks
18
+
19
+ ```bash
20
+ # Tests
21
+ pytest tests/
22
+
23
+ # Lint + format
24
+ ruff check src/ tests/
25
+ ruff format src/ tests/
26
+
27
+ # Type check
28
+ mypy src/
29
+
30
+ # All at once
31
+ ruff check src/ tests/ && ruff format --check src/ tests/ && mypy src/ && pytest tests/
32
+ ```
33
+
34
+ Pre-commit hooks (optional but recommended):
35
+
36
+ ```bash
37
+ pre-commit install
38
+ ```
39
+
40
+ ## Pull request process
41
+
42
+ 1. Fork the repo and create a branch from `main`.
43
+ 2. Make your changes with tests covering new behaviour.
44
+ 3. Ensure all checks pass locally before pushing.
45
+ 4. Open a PR — the CI matrix (Python 3.11 / 3.12 / 3.13) must be green before merge.
46
+ 5. Keep PRs focused: one logical change per PR.
47
+
48
+ ## Commit style
49
+
50
+ Use the imperative mood in the subject line (`add`, `fix`, `remove`, not `added`).
51
+ Keep the subject under 72 characters. Reference issues with `Fixes #N` in the body.
52
+
53
+ ## Reporting bugs
54
+
55
+ Open an issue using the **Bug report** template. Include a minimal reproducible example.
56
+
57
+ ## Proposing features
58
+
59
+ Open an issue using the **Feature request** template before starting significant work,
60
+ to avoid building something that won't be merged.