awp-python 0.1.0a1__tar.gz → 0.1.0a3__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 (101) hide show
  1. awp_python-0.1.0a3/CHANGELOG.md +37 -0
  2. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/PKG-INFO +10 -7
  3. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/README.md +9 -6
  4. awp_python-0.1.0a3/conformance/README.md +86 -0
  5. awp_python-0.1.0a3/conformance/core-agent-lockstep.json +1496 -0
  6. awp_python-0.1.0a3/conformance/core-agent-streaming.json +1498 -0
  7. awp_python-0.1.0a3/conformance/core-world-lockstep.json +1669 -0
  8. awp_python-0.1.0a3/conformance/core-world-streaming.json +1671 -0
  9. awp_python-0.1.0a3/conformance/features-lockstep.json +1671 -0
  10. awp_python-0.1.0a3/conformance/features-streaming.json +1671 -0
  11. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/pyproject.toml +1 -1
  12. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/__init__.py +1 -1
  13. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/action-status.schema.json +1 -1
  14. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/action-submit-result.schema.json +1 -0
  15. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/approval-respond.schema.json +4 -4
  16. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/common.schema.json +3 -3
  17. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/error.schema.json +1 -1
  18. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/frame-inline.schema.json +1 -1
  19. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/obs-report.schema.json +1 -1
  20. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/safety-policy.schema.json +1 -0
  21. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/session-ready.schema.json +2 -2
  22. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/session-state.schema.json +1 -1
  23. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/world-event.schema.json +1 -1
  24. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/aio.py +45 -10
  25. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/client.py +62 -10
  26. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/frames.py +4 -0
  27. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp_sim/arm.py +17 -3
  28. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp_sim/config.py +1 -0
  29. awp_python-0.1.0a3/src/awp_sim/demo.py +133 -0
  30. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp_sim/server.py +5 -2
  31. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp_sim/session.py +20 -0
  32. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp_sim/world.py +89 -22
  33. awp_python-0.1.0a3/tests/test_evidence.py +224 -0
  34. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/tests/test_features.py +75 -0
  35. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/tests/test_streams.py +17 -0
  36. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/tests/test_world.py +34 -0
  37. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/uv.lock +1 -1
  38. awp_python-0.1.0a1/CHANGELOG.md +0 -19
  39. awp_python-0.1.0a1/src/awp_sim/demo.py +0 -85
  40. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/.gitignore +0 -0
  41. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/.gitmodules +0 -0
  42. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/.python-version +0 -0
  43. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/LICENSE +0 -0
  44. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/scripts/check_traces.py +0 -0
  45. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/scripts/sync_spec.py +0 -0
  46. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/lifecycle.json +0 -0
  47. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/action-cancel-result.schema.json +0 -0
  48. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/action-ref.schema.json +0 -0
  49. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/action-schema.schema.json +0 -0
  50. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/action-submit.schema.json +0 -0
  51. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/agent-manifest.schema.json +0 -0
  52. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/approval-requested.schema.json +0 -0
  53. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/embodiment.schema.json +0 -0
  54. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/empty-result.schema.json +0 -0
  55. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/frame-tree.schema.json +0 -0
  56. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/observation-channel.schema.json +0 -0
  57. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/ping-result.schema.json +0 -0
  58. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/ping.schema.json +0 -0
  59. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/profiles/gui-actions.schema.json +0 -0
  60. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/reset-result.schema.json +0 -0
  61. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/reset.schema.json +0 -0
  62. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/restore.schema.json +0 -0
  63. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/session-open.schema.json +0 -0
  64. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/session-resume.schema.json +0 -0
  65. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/session-telemetry.schema.json +0 -0
  66. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/session-transfer-result.schema.json +0 -0
  67. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/session-transfer.schema.json +0 -0
  68. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/snapshot-result.schema.json +0 -0
  69. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/subscribe-result.schema.json +0 -0
  70. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/subscribe.schema.json +0 -0
  71. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/task-update.schema.json +0 -0
  72. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/tick-result.schema.json +0 -0
  73. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/tick.schema.json +0 -0
  74. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/unsubscribe.schema.json +0 -0
  75. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/_spec/schemas/world-manifest.schema.json +0 -0
  76. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/clock.py +0 -0
  77. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/errors.py +0 -0
  78. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/jsonrpc.py +0 -0
  79. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/lifecycle.py +0 -0
  80. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/py.typed +0 -0
  81. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp/schema.py +0 -0
  82. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp_sim/__init__.py +0 -0
  83. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp_sim/__main__.py +0 -0
  84. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp_sim/audit.py +0 -0
  85. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp_sim/cli.py +0 -0
  86. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp_sim/loopback.py +0 -0
  87. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp_sim/py.typed +0 -0
  88. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp_sim/recorder.py +0 -0
  89. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp_sim/replay.py +0 -0
  90. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/src/awp_sim/scenarios.py +0 -0
  91. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/tests/__init__.py +0 -0
  92. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/tests/conftest.py +0 -0
  93. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/tests/helpers.py +0 -0
  94. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/tests/test_audit.py +0 -0
  95. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/tests/test_cli.py +0 -0
  96. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/tests/test_client_traces.py +0 -0
  97. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/tests/test_e2e.py +0 -0
  98. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/tests/test_frames.py +0 -0
  99. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/tests/test_regressions.py +0 -0
  100. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/tests/test_scenarios.py +0 -0
  101. {awp_python-0.1.0a1 → awp_python-0.1.0a3}/tests/test_schema.py +0 -0
@@ -0,0 +1,37 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0a3
4
+
5
+ Targets specification revision `0.1-draft.9`.
6
+
7
+ - `awp_sim`: standing approvals (AWP-APR-004), declared as `safety_policy.standing_approvals` with the approval feature; a submission within a grant is admitted without approval and its result names the grant's `approval_id`.
8
+ - `awp`: `AsyncClient.advance` returns once every subscribed per-tick channel holds a frame of the new tick, which on a stream connection may follow the result (AWP-TIM-003). A `session.resume` answered `AWP_SESSION_UNKNOWN` closes the session and forgets its actions (AWP-SES-008). `respond_approval` takes `standing`.
9
+ - `awp-sim demo` resumes after a lost connection, or opens a new session if the world no longer holds it.
10
+ - `awp_sim`: an integer beyond 2^53-1 closes the session with reason `protocol_error` and the connection with code 1002 (AWP-CTL-009); a malformed frame on a stream connection closes it with code 1002 and `AWP_MALFORMED` (AWP-DAT-010); after a lockstep resumption every per-tick channel restarts with a resync keyframe at the current tick (AWP-TIM-009); after a reset the fresh frames precede the result (AWP-PRM-006).
11
+ - `awp`: an integer beyond 2^53-1 ends the session with `session.close` and close code 1002; a malformed stream frame is dropped and its stream connection closed and re-established; frames with `resync` but not `keyframe` are malformed. While a lost stream connection is down, `AsyncClient.command` raises instead of sending inline (AWP-TRN-010). `ClientConnection.receive_frame` raises for a malformed frame, and `delivery()` reports each channel's frames and gaps.
12
+
13
+ ## 0.1.0a2
14
+
15
+ Targets specification revision `0.1-draft.8`.
16
+
17
+ - `awp_sim`: the world checks the arm against its envelope after every step; leaving it emits `envelope_violation` and fails the executing action with reason `envelope` (AWP-ENV-003). `World.disturb` and `Server.disturb` inject an external disturbance.
18
+ - `awp_sim`: a stop during servo motion ends at the envelope's boundary instead of past it.
19
+ - `conformance/`: reports for Core World in both time models and the evidence for their manual rows, with tests in `tests/test_evidence.py`.
20
+
21
+ ## 0.1.0a1
22
+
23
+ First release, targeting specification revision `0.1-draft.7`.
24
+
25
+ - The `ws` stream binding: `awp-sim serve --stream-binding ws` offers frames on a stream connection in the binary envelope, and `AsyncClient` uses it when offered, re-establishing it if only the stream drops (AWP-TRN-010..013).
26
+ - Beyond Core, each enabled with `awp-sim serve --features`: `task`, `approval` (the `park` action; approvers connect with `--approver-token`), `blend`, `transfer`, `sim` (seeding, snapshot and restore, replay bundles with `--replay-dir`, and `awp-sim replay`), and `servo` (a command channel). `ClientConnection` gains `update_task`, `transfer`, `reset`, `snapshot`, `restore`, `respond_approval`, and `command`.
27
+ - The lockstep session clock counts advances, so reset and restore, which now move the tick, never move it backward (AWP-TIM-013). Audit records hash frame payloads, not their base64 text.
28
+
29
+ - `awp`: `ClientConnection.submit` refuses action types the session was not granted (AWP-AGT-003); `AsyncClient` treats three heartbeat intervals without a message from the world as a lost connection (AWP-SAF-002).
30
+ - `awp_sim`: channels in modalities the agent did not declare are not granted (AWP-AGM-001); granted rates honor the agent's `max_obs_rate_hz` (AWP-AGM-002); a connection without a session is closed after at least 15 s (AWP-SES-012); `--max-duration-ms`. The demo agent does nothing when `move_to_pose` is not granted.
31
+
32
+ ## 0.1.0.dev0 — unreleased
33
+
34
+ First implementation, targeting specification revision `0.1-draft.5`.
35
+
36
+ - `awp`: sans-IO `ClientConnection`, asyncio `AsyncClient`, binary and inline frame codec, canonical schema validation (receiver and sender forms), the lifecycle transition table, clock synchronization.
37
+ - `awp_sim`: sans-IO world engine for lockstep and streaming, simulated arm, WebSocket server with bearer authentication, audit log, trace recorder, in-process loopback, twelve scripted scenarios, and the `awp-sim` command.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: awp-python
3
- Version: 0.1.0a1
3
+ Version: 0.1.0a3
4
4
  Summary: Agent World Protocol client protocol layer and reference world for Python.
5
5
  Project-URL: Specification, https://www.agentworldprotocol.com
6
6
  Project-URL: Source, https://github.com/Hyperduality/awp-python
@@ -26,21 +26,24 @@ Python implementation of the [Agent World Protocol](https://www.agentworldprotoc
26
26
  - **`awp`** — the client protocol layer. `ClientConnection` is the agent side of AWP as a sans-IO state machine; `awp.aio.AsyncClient` drives it over a WebSocket.
27
27
  - **`awp_sim`** — the reference world. A sans-IO world engine with a simulated arm, a WebSocket server, an audit log, and a scenario suite that records wire traces.
28
28
 
29
- It targets specification revision **`0.1-draft.7`**, pinned as the `spec/` submodule. This is an alpha: the API will change with the draft.
29
+ It targets specification revision **`0.1-draft.9`**, pinned as the `spec/` submodule. This is an alpha: the API will change with the draft.
30
30
 
31
31
  ## Status
32
32
 
33
- The world and client target **Core World** and **Core Agent** for both time models, and the world the **sim** profile in lockstep, *self-assessed against 0.1-draft.7*: [awp-conformance](https://github.com/Hyperduality/awp-conformance) reports no failure against any configuration and leaves a few requirements untested. Every recorded trace also passes the spec's own checker, which verifies schemas, the action lifecycle table, idempotency, replay, and frame sequencing.
33
+ ![AWP: Core World, AWP-conformant against 0.1-draft.9](https://img.shields.io/badge/AWP-Core_World%2C_conformant_0.1--draft.9-555)
34
+ ![AWP: Core Agent, AWP-conformant against 0.1-draft.9](https://img.shields.io/badge/AWP-Core_Agent%2C_conformant_0.1--draft.9-555)
35
+
36
+ The world is **Core World: AWP-conformant against 0.1-draft.9**, and the client, through its demo agent, **Core Agent: AWP-conformant against 0.1-draft.9**, each in both time models: [awp-conformance](https://github.com/Hyperduality/awp-conformance) reports no failure and nothing untested, and [`conformance/`](conformance/README.md) holds the reports and the evidence for their manual rows. The **sim** profile in lockstep is *self-assessed against 0.1-draft.9*: the suite reports no failure and leaves a few requirements untested. Every recorded trace also passes the spec's own checker, which verifies schemas, the action lifecycle table, idempotency, replay, and frame sequencing.
34
37
 
35
38
  | Implemented | Not implemented |
36
39
  |---|---|
37
40
  | Lockstep (`on_tick`, `any_session`) and streaming | `barrier` tick authority |
38
41
  | Inline and `ws` stream bindings; binary frame codec (all spec vectors) | Other stream bindings (`webrtc`, `webtransport`, `shm`, `grpc`) |
39
- | Full action lifecycle; preemption (`replace`, `queue`, `reject`, `blend`); idempotency | Standing approvals, grant expiry |
42
+ | Full action lifecycle; preemption (`replace`, `queue`, `reject`, `blend`); idempotency | Grant expiry |
40
43
  | Watchdog and safe state, heartbeats, resumption with replay and acknowledgement | Multi-bind and shared control (one embodiment) |
41
- | Spatial, velocity, and rate envelopes (`command_check`) | Robotics profile (a simulated arm proves nothing physical) |
44
+ | Spatial, velocity, and rate envelopes (`command_check`), monitored during execution | Robotics profile (a simulated arm proves nothing physical) |
42
45
  | Audit log with redaction and hash chain; e-stop; `world.reset` | |
43
- | Beyond Core (`--features`): task, approval, transfer, seeding, snapshots, replay bundles, a servo command channel | |
46
+ | Beyond Core (`--features`): task, approval and standing approvals, transfer, seeding, snapshots, replay bundles, a servo command channel | |
44
47
 
45
48
  ## Quickstart
46
49
 
@@ -107,7 +110,7 @@ The connection tracks the action lifecycle against the spec's transition table,
107
110
  src/awp/ client protocol layer (sans-IO), asyncio adapter, frame codec, schemas
108
111
  src/awp/_spec/ schemas and lifecycle table bundled from spec/ (scripts/sync_spec.py)
109
112
  src/awp_sim/ world engine, arm, server, audit log, loopback, scenarios, CLI
110
- spec/ agent-world-protocol, pinned at spec-v0.1-draft.7
113
+ spec/ agent-world-protocol, pinned at spec-v0.1-draft.9
111
114
  scripts/ spec sync and trace checking
112
115
  ```
113
116
 
@@ -5,21 +5,24 @@ Python implementation of the [Agent World Protocol](https://www.agentworldprotoc
5
5
  - **`awp`** — the client protocol layer. `ClientConnection` is the agent side of AWP as a sans-IO state machine; `awp.aio.AsyncClient` drives it over a WebSocket.
6
6
  - **`awp_sim`** — the reference world. A sans-IO world engine with a simulated arm, a WebSocket server, an audit log, and a scenario suite that records wire traces.
7
7
 
8
- It targets specification revision **`0.1-draft.7`**, pinned as the `spec/` submodule. This is an alpha: the API will change with the draft.
8
+ It targets specification revision **`0.1-draft.9`**, pinned as the `spec/` submodule. This is an alpha: the API will change with the draft.
9
9
 
10
10
  ## Status
11
11
 
12
- The world and client target **Core World** and **Core Agent** for both time models, and the world the **sim** profile in lockstep, *self-assessed against 0.1-draft.7*: [awp-conformance](https://github.com/Hyperduality/awp-conformance) reports no failure against any configuration and leaves a few requirements untested. Every recorded trace also passes the spec's own checker, which verifies schemas, the action lifecycle table, idempotency, replay, and frame sequencing.
12
+ ![AWP: Core World, AWP-conformant against 0.1-draft.9](https://img.shields.io/badge/AWP-Core_World%2C_conformant_0.1--draft.9-555)
13
+ ![AWP: Core Agent, AWP-conformant against 0.1-draft.9](https://img.shields.io/badge/AWP-Core_Agent%2C_conformant_0.1--draft.9-555)
14
+
15
+ The world is **Core World: AWP-conformant against 0.1-draft.9**, and the client, through its demo agent, **Core Agent: AWP-conformant against 0.1-draft.9**, each in both time models: [awp-conformance](https://github.com/Hyperduality/awp-conformance) reports no failure and nothing untested, and [`conformance/`](conformance/README.md) holds the reports and the evidence for their manual rows. The **sim** profile in lockstep is *self-assessed against 0.1-draft.9*: the suite reports no failure and leaves a few requirements untested. Every recorded trace also passes the spec's own checker, which verifies schemas, the action lifecycle table, idempotency, replay, and frame sequencing.
13
16
 
14
17
  | Implemented | Not implemented |
15
18
  |---|---|
16
19
  | Lockstep (`on_tick`, `any_session`) and streaming | `barrier` tick authority |
17
20
  | Inline and `ws` stream bindings; binary frame codec (all spec vectors) | Other stream bindings (`webrtc`, `webtransport`, `shm`, `grpc`) |
18
- | Full action lifecycle; preemption (`replace`, `queue`, `reject`, `blend`); idempotency | Standing approvals, grant expiry |
21
+ | Full action lifecycle; preemption (`replace`, `queue`, `reject`, `blend`); idempotency | Grant expiry |
19
22
  | Watchdog and safe state, heartbeats, resumption with replay and acknowledgement | Multi-bind and shared control (one embodiment) |
20
- | Spatial, velocity, and rate envelopes (`command_check`) | Robotics profile (a simulated arm proves nothing physical) |
23
+ | Spatial, velocity, and rate envelopes (`command_check`), monitored during execution | Robotics profile (a simulated arm proves nothing physical) |
21
24
  | Audit log with redaction and hash chain; e-stop; `world.reset` | |
22
- | Beyond Core (`--features`): task, approval, transfer, seeding, snapshots, replay bundles, a servo command channel | |
25
+ | Beyond Core (`--features`): task, approval and standing approvals, transfer, seeding, snapshots, replay bundles, a servo command channel | |
23
26
 
24
27
  ## Quickstart
25
28
 
@@ -86,7 +89,7 @@ The connection tracks the action lifecycle against the spec's transition table,
86
89
  src/awp/ client protocol layer (sans-IO), asyncio adapter, frame codec, schemas
87
90
  src/awp/_spec/ schemas and lifecycle table bundled from spec/ (scripts/sync_spec.py)
88
91
  src/awp_sim/ world engine, arm, server, audit log, loopback, scenarios, CLI
89
- spec/ agent-world-protocol, pinned at spec-v0.1-draft.7
92
+ spec/ agent-world-protocol, pinned at spec-v0.1-draft.9
90
93
  scripts/ spec sync and trace checking
91
94
  ```
92
95
 
@@ -0,0 +1,86 @@
1
+ # Conformance
2
+
3
+ ![AWP: Core World, AWP-conformant against 0.1-draft.9](https://img.shields.io/badge/AWP-Core_World%2C_conformant_0.1--draft.9-555)
4
+
5
+ | Class | Configuration | Claim | Report |
6
+ |---|---|---|---|
7
+ | Core World | `awp-sim serve --mode lockstep` | Core World (lockstep): AWP-conformant against 0.1-draft.9 (awp-conformance 0.1.0a3) | [`core-world-lockstep.json`](core-world-lockstep.json) |
8
+ | Core World | `awp-sim serve` | Core World (streaming): AWP-conformant against 0.1-draft.9 (awp-conformance 0.1.0a3) | [`core-world-streaming.json`](core-world-streaming.json) |
9
+ | Core World + sim | `awp-sim serve --mode lockstep --features task,approval,blend,transfer,sim --approver-token awp-sim-approver` | Core World + sim (lockstep): AWP-conformant against 0.1-draft.9 (awp-conformance 0.1.0a3) | [`features-lockstep.json`](features-lockstep.json) |
10
+ | Core World | `awp-sim serve --features task,approval,blend,transfer,servo --stream-binding ws --approver-token awp-sim-approver --approval-timeout-ms 5000` | Core World (streaming): AWP-conformant against 0.1-draft.9 (awp-conformance 0.1.0a3) | [`features-streaming.json`](features-streaming.json) |
11
+ | Core Agent | `awp-sim demo`, lockstep manifest | Core Agent (lockstep): AWP-conformant against 0.1-draft.9 (awp-conformance 0.1.0a3) | [`core-agent-lockstep.json`](core-agent-lockstep.json) |
12
+ | Core Agent | `awp-sim demo`, streaming manifest | Core Agent (streaming): AWP-conformant against 0.1-draft.9 (awp-conformance 0.1.0a3) | [`core-agent-streaming.json`](core-agent-streaming.json) |
13
+
14
+ Each report, from awp-conformance 0.1.0a3 against awp-python 0.1.0a3, has no failure and nothing untested; the evidence for its `manual` rows follows (AWP-CNF-005). The feature configurations cover every feature awp-sim offers; `sim` and `servo` need separate runs, since `sim` is lockstep-only and `servo` streaming-only. The streaming one shortens `approval_timeout_ms` so the suite can wait out a timeout (AWP-APR-003).
15
+
16
+ ## Reproduce
17
+
18
+ ```bash
19
+ pip install --pre awp-python awp-conformance
20
+ curl -LO https://raw.githubusercontent.com/Hyperduality/awp-conformance/v0.1.0a3/fixtures/awp-sim.json
21
+ awp-sim serve --mode lockstep & # or `awp-sim serve` for streaming
22
+ export AWP_SIM_PID=$!
23
+ awp-conformance world ws://127.0.0.1:8710 --fixture awp-sim.json --out report/
24
+ ```
25
+
26
+ For the feature configurations, serve with the flags in the table and use `fixtures/awp-sim-features.json` (and `--profile sim` in lockstep). The fixture's e-stop hooks signal `$AWP_SIM_PID`; without it the e-stop test is skipped and AWP-EVT-002 is reported untested. The agent claims test the demo agent, which is written on the `awp` client, against the suite's harness world:
27
+
28
+ ```bash
29
+ awp-sim manifest --mode lockstep > manifest.json # or --mode streaming
30
+ echo '{"proprio": {"p_m": [0, 0, 0.4], "v_mps": [0, 0, 0]}, "arm_state": {"phase": "idle", "target_m": null, "action_id": null}}' > frames.json
31
+ awp-conformance agent --manifest manifest.json --frames frames.json --out report/ -- awp-sim demo --url '{url}' --token '{token}'
32
+ ```
33
+
34
+ The tests cited below run in this repository's CI:
35
+
36
+ ```bash
37
+ uv run pytest tests/test_frames.py tests/test_evidence.py
38
+ ```
39
+
40
+ ## Manual evidence
41
+
42
+ ### AWP-DAT-002, AWP-TRN-009 — latest-wins delivery (streaming)
43
+
44
+ - **Drop policy.** Each connection's send queue (`_Outbox`, [`src/awp_sim/server.py`](../src/awp_sim/server.py)) holds at most one unsent frame per latest-wins channel and replaces it when a newer one is produced; control messages and reliable frames queue in order, so a stalled latest-wins channel delays them by at most its one pending frame. A peer that stops reading is disconnected at 10,000 pending items rather than buffered without limit.
45
+ - **Stalled-receiver test.** `test_a_stalled_receiver_holds_one_frame_per_latest_wins_channel`: 1,000 `proprio` frames and 10 `arm_state` frames are produced while nothing drains the queue; one `proprio` frame, the newest, and all 10 `arm_state` frames remain, in order.
46
+
47
+ ### AWP-DAT-001, AWP-DAT-009 — loss accounting at the receiver (Core Agent, lockstep)
48
+
49
+ In streaming the suite reads the agent's loss accounting from its `obs.report`; lockstep sessions send none, so the rows are `manual` there.
50
+
51
+ - `test_the_receiver_counts_seq_gaps_as_loss_but_not_the_gap_before_a_resync`: in each time model, frames skipping two `seq` values on one channel count two missing frames in `ClientConnection.delivery()`, and a resync frame after a gap of five on another counts none.
52
+ - The client holds no delta state: each frame reaches the application whole, with its `keyframe` and `resync` flags.
53
+
54
+ ### AWP-AUD-005 — replay bundles (Core World + sim)
55
+
56
+ `test_a_replay_bundle_reproduces_its_session` (`tests/test_features.py`) records a seeded lockstep session with a cancel and a second move as a replay bundle, replays it with `awp-sim replay`'s engine, and reproduces every transition and more than 80 frame hashes; a bundle with one tampered frame hash does not reproduce. `awp-sim serve --replay-dir DIR --mode lockstep --features sim` writes bundles, and `awp-sim replay BUNDLE` checks one.
57
+
58
+ ### AWP-DAT-008 — frame test vectors
59
+
60
+ World and agent share one decoder, `awp.frames`. `test_vectors` (`tests/test_frames.py`) decodes every vector in `schemas/test-vectors/frames.json` of the `spec/` submodule, pinned at `spec-v0.1-draft.9`: the 10 valid vectors to the listed fields, and the 7 marked `expect_error` rejected with the listed error. `test_roundtrip_without_vendor` re-encodes the 8 valid vectors without an unknown extension or reserved bits byte for byte.
61
+
62
+ ### AWP-ENV-003 — envelope violations during execution
63
+
64
+ After every simulation step the world checks the arm against its envelope: position within `aabb_m`, speed within `max_velocity_mps`. On leaving it, the world stops the arm, emits `world.event: envelope_violation` to every session, and fails the executing action with reason `envelope` once its safe abort completes. An external disturbance is injected with `World.disturb(offset_m)` (or `Server.disturb`).
65
+
66
+ - `test_a_disturbance_during_execution_fails_the_action`: in each time model, a move is executing when the arm is pushed out of the envelope; the world emits `envelope_violation` and the move ends `failed` with reason `envelope`.
67
+ - `test_commanded_motion_never_leaves_the_envelope`: 400 seeded random submissions, replacements, queued moves, stops, and cancels in each time model, checked after every advance; no violation is reported.
68
+ - `test_servo_motion_never_leaves_the_envelope`: servo setpoints toward the walls, and stops during them.
69
+
70
+ ### AWP-UNI-001 — SI units and unit suffixes
71
+
72
+ The fields awp-sim defines, reviewed:
73
+
74
+ | Field | Where | Unit |
75
+ |---|---|---|
76
+ | `p_m` | `proprio` payload | m |
77
+ | `v_mps` | `proprio` payload; `servo_arm` setpoints | m/s |
78
+ | `target_m` | `arm_state` payload | m |
79
+ | `max_velocity_mps` | `move_to_pose` params | m/s |
80
+ | `phase`, `action_id` | `arm_state` payload | not physical |
81
+
82
+ Every other field is defined by the specification's schemas. `test_world_defined_fields_carry_si_suffixes` collects every action parameter, channel schema field, and payload field across every feature, and fails on any field not reviewed as non-physical that lacks a unit suffix.
83
+
84
+ ### AWP-VER-009 — the draft revision is named
85
+
86
+ The [README](../README.md) and the [awp-sim page](https://www.agentworldprotocol.com/adapters/awp-sim) name `0.1-draft.9`; `awp.SPEC_REVISION` is `"0.1-draft.9"`; the `spec/` submodule is pinned at the tag `spec-v0.1-draft.9`; each report records `"specification": "0.1-draft.9"` and its claim names the revision.