macp-sdk-python 0.9.0__tar.gz → 0.9.1__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 (40) hide show
  1. {macp_sdk_python-0.9.0/src/macp_sdk_python.egg-info → macp_sdk_python-0.9.1}/PKG-INFO +1 -1
  2. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/pyproject.toml +1 -1
  3. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/base_projection.py +42 -4
  4. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1/src/macp_sdk_python.egg-info}/PKG-INFO +1 -1
  5. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/LICENSE +0 -0
  6. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/README.md +0 -0
  7. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/setup.cfg +0 -0
  8. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/__init__.py +0 -0
  9. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/_logging.py +0 -0
  10. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/agent/__init__.py +0 -0
  11. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/agent/cancel_callback.py +0 -0
  12. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/agent/dispatcher.py +0 -0
  13. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/agent/participant.py +0 -0
  14. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/agent/runner.py +0 -0
  15. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/agent/strategies.py +0 -0
  16. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/agent/transports.py +0 -0
  17. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/agent/types.py +0 -0
  18. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/auth.py +0 -0
  19. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/base_session.py +0 -0
  20. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/client.py +0 -0
  21. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/commitment_hash.py +0 -0
  22. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/constants.py +0 -0
  23. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/decision.py +0 -0
  24. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/envelope.py +0 -0
  25. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/errors.py +0 -0
  26. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/handoff.py +0 -0
  27. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/policy.py +0 -0
  28. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/projections.py +0 -0
  29. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/proposal.py +0 -0
  30. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/proto_registry.py +0 -0
  31. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/py.typed +0 -0
  32. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/quorum.py +0 -0
  33. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/retry.py +0 -0
  34. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/task.py +0 -0
  35. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/validation.py +0 -0
  36. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk/watchers.py +0 -0
  37. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk_python.egg-info/SOURCES.txt +0 -0
  38. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk_python.egg-info/dependency_links.txt +0 -0
  39. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk_python.egg-info/requires.txt +0 -0
  40. {macp_sdk_python-0.9.0 → macp_sdk_python-0.9.1}/src/macp_sdk_python.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: macp-sdk-python
3
- Version: 0.9.0
3
+ Version: 0.9.1
4
4
  Summary: Python SDK for the MACP Rust runtime
5
5
  Author-email: Multi-Agent Coordination Protocol <macp@multiagentcoordinationprotocol.org>
6
6
  License: Apache-2.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "macp-sdk-python"
7
- version = "0.9.0"
7
+ version = "0.9.1"
8
8
  description = "Python SDK for the MACP Rust runtime"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -207,7 +207,7 @@ class BaseProjection(ABC):
207
207
  #
208
208
  # What this does NOT cover: self.phase (assigned directly on
209
209
  # BaseProjection by subclasses — see projections.py:84,
210
- # task.py:103, handoff.py:71) and any subclass-owned collection
210
+ # task.py:102, handoff.py:70) and any subclass-owned collection
211
211
  # (evaluations, objections, accepts, rejections, updates,
212
212
  # completions, failures) are never rolled back, because this
213
213
  # method has no way to know what a subclass mutated. That is safe
@@ -219,7 +219,7 @@ class BaseProjection(ABC):
219
219
  # mutates subclass state and then raises. This is a
220
220
  # raise-before-mutate invariant that _apply_mode_message
221
221
  # implementations must preserve. BaseProjection is exported for
222
- # third-party subclassing (see __init__.py:143), and upcoming
222
+ # third-party subclassing (see __init__.py:151), and upcoming
223
223
  # first-wins/anomaly-tracking logic must keep fallible work ahead
224
224
  # of mutations to keep this guarantee honest.
225
225
  #
@@ -242,7 +242,7 @@ class BaseProjection(ABC):
242
242
  # above is the only mutation of transcript between there and
243
243
  # here, so transcript[-1] is the entry this call just
244
244
  # appended. But BaseProjection is a public ABC (exported at
245
- # __init__.py:143) that third parties may subclass, so guard
245
+ # __init__.py:151) that third parties may subclass, so guard
246
246
  # with an identity check rather than popping unconditionally.
247
247
  # The two ways the guard could see something else at [-1] are:
248
248
  # - a subclass's _apply_mode_message appending to
@@ -267,7 +267,45 @@ class BaseProjection(ABC):
267
267
 
268
268
  @abstractmethod
269
269
  def _apply_mode_message(self, envelope: envelope_pb2.Envelope) -> None:
270
- """Handle a mode-specific (non-Commitment) envelope."""
270
+ """Handle a mode-specific (non-Commitment) envelope.
271
+
272
+ **Implementations MUST do all fallible work before any mutation**
273
+ ("raise-before-mutate"). Parse the payload (``ParseFromString``, the
274
+ one operation that realistically raises here), validate it, and
275
+ decide what to do — *then* assign ``self.phase`` or touch any
276
+ subclass collection. Never mutate and then run something that can
277
+ raise.
278
+
279
+ This is a real contract, not style advice, and it is what makes
280
+ ``apply_envelope``'s rollback sufficient. That rollback restores
281
+ ``transcript`` and the ``message_id`` dedup set only — it cannot
282
+ restore subclass state, because the base class has no way to know
283
+ what a subclass mutated (a slotted subclass has no ``__dict__`` to
284
+ snapshot, and deep-copying every projection per envelope would be a
285
+ real per-message cost). An implementation that mutates and then
286
+ raises therefore leaves *its own* state half-applied while
287
+ ``apply_envelope`` reports a clean rollback and invites the caller
288
+ to retry — a partial apply the base class cannot detect or undo.
289
+
290
+ Every implementation in this SDK honors this today (see the
291
+ per-branch parse-then-mutate ordering in ``projections.py``,
292
+ ``quorum.py``, ``task.py``, ``handoff.py``, and ``proposal.py``).
293
+ Two branches come close to the line: ``handoff.py``'s
294
+ ``HandoffAccept`` writes the record before reading
295
+ ``getattr(p, "implicit", False)``, and ``proposal.py``'s ``Reject``
296
+ appends before reading ``p.terminal`` and ``self.proposals.get(...)``.
297
+ Both are safe only because a defaulted ``getattr``, a protobuf field
298
+ read, and ``dict.get`` cannot raise — not because the ordering there
299
+ is exemplary.
300
+
301
+ ``tests/unit/test_projection_rollback_invariant.py`` pins the
302
+ ordering by feeding each branch a payload that cannot parse and
303
+ asserting no derived state moved. Note what that does *not* reach: a
304
+ branch that mutates and then does something else fallible (a raising
305
+ property, an ``int()``, a strict lookup) is not caught, because a
306
+ malformed payload never gets that far. The contract is broader than
307
+ the test — hence stating it here.
308
+ """
271
309
 
272
310
  def _record_anomaly(
273
311
  self,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: macp-sdk-python
3
- Version: 0.9.0
3
+ Version: 0.9.1
4
4
  Summary: Python SDK for the MACP Rust runtime
5
5
  Author-email: Multi-Agent Coordination Protocol <macp@multiagentcoordinationprotocol.org>
6
6
  License: Apache-2.0
File without changes