simulo-interfaces 0.14.0__tar.gz → 0.16.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 (59) hide show
  1. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/MANIFEST.in +1 -1
  2. {simulo_interfaces-0.14.0/src/simulo_interfaces.egg-info → simulo_interfaces-0.16.0}/PKG-INFO +1 -1
  3. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/pyproject.toml +1 -1
  4. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/__init__.py +16 -0
  5. simulo_interfaces-0.16.0/src/simulo/interfaces/ids.py +135 -0
  6. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/platform/__init__.py +87 -32
  7. simulo_interfaces-0.16.0/src/simulo/interfaces/platform/_payload.py +15 -0
  8. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/platform/asset_catalog.py +2 -2
  9. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/platform/domain.py +3 -3
  10. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/platform/enums.py +11 -8
  11. simulo_interfaces-0.16.0/src/simulo/interfaces/platform/job_events.py +244 -0
  12. simulo_interfaces-0.14.0/src/simulo/interfaces/platform/artifacts.py → simulo_interfaces-0.16.0/src/simulo/interfaces/platform/outputs.py +176 -131
  13. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/platform/policy_bundle.py +16 -16
  14. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/platform/runs.py +68 -10
  15. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/platform/submit.py +107 -19
  16. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/runtime/anomaly.py +3 -3
  17. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/runtime/player.py +2 -2
  18. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/runtime/trainer.py +1 -1
  19. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0/src/simulo_interfaces.egg-info}/PKG-INFO +1 -1
  20. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo_interfaces.egg-info/SOURCES.txt +3 -1
  21. simulo_interfaces-0.14.0/src/simulo/interfaces/ids.py +0 -24
  22. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/PYPI.md +0 -0
  23. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/setup.cfg +0 -0
  24. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/authoring/__init__.py +0 -0
  25. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/authoring/actuator.py +0 -0
  26. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/authoring/asset.py +0 -0
  27. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/authoring/entity.py +0 -0
  28. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/authoring/light.py +0 -0
  29. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/authoring/materials.py +0 -0
  30. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/authoring/physics.py +0 -0
  31. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/authoring/pose.py +0 -0
  32. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/authoring/primitives.py +0 -0
  33. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/authoring/prop.py +0 -0
  34. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/authoring/record.py +0 -0
  35. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/authoring/robot.py +0 -0
  36. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/authoring/scene.py +0 -0
  37. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/authoring/sensor.py +0 -0
  38. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/authoring/terrain.py +0 -0
  39. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/authoring/visual.py +0 -0
  40. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/authoring/world.py +0 -0
  41. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/exceptions.py +0 -0
  42. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/platform/app.py +0 -0
  43. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/platform/asset.py +0 -0
  44. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/platform/callbacks.py +0 -0
  45. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/platform/debug.py +0 -0
  46. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/platform/manifest.py +0 -0
  47. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/platform/runtime.py +0 -0
  48. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/platform/volume.py +0 -0
  49. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/py.typed +0 -0
  50. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/runtime/__init__.py +0 -0
  51. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/runtime/components.py +0 -0
  52. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/runtime/env.py +0 -0
  53. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/runtime/policy.py +0 -0
  54. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/runtime/scenario.py +0 -0
  55. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/runtime/task.py +0 -0
  56. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo/interfaces/runtime/tensors.py +0 -0
  57. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo_interfaces.egg-info/dependency_links.txt +0 -0
  58. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo_interfaces.egg-info/requires.txt +0 -0
  59. {simulo_interfaces-0.14.0 → simulo_interfaces-0.16.0}/src/simulo_interfaces.egg-info/top_level.txt +0 -0
@@ -1,4 +1,4 @@
1
- # Public-metadata discretion boundary (see release.yml Guard 5): the sdist is
1
+ # Public-metadata discretion boundary (see release-pypi.yml Guard 5): the sdist is
2
2
  # PUBLIC on PyPI's "Download files" page just like the wheel, but setuptools'
3
3
  # sdist command auto-includes README.md and any top-level tests/ directory
4
4
  # regardless of the `readme = "PYPI.md"` pyproject setting. Exclude the
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simulo-interfaces
3
- Version: 0.14.0
3
+ Version: 0.16.0
4
4
  Summary: Type contracts for the Simulo SDK. Installed automatically as a dependency of the simulo package.
5
5
  Author-email: Simulo Team <team@simulo.ai>
6
6
  License: BSD-3-Clause
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "simulo-interfaces"
7
- version = "0.14.0"
7
+ version = "0.16.0"
8
8
  description = "Type contracts for the Simulo SDK. Installed automatically as a dependency of the simulo package."
9
9
  readme = "PYPI.md"
10
10
  requires-python = ">=3.11"
@@ -31,13 +31,21 @@ from simulo.interfaces.ids import (
31
31
  CheckpointId,
32
32
  Digest,
33
33
  JobId,
34
+ JobPublicId,
35
+ ModelPublicId,
34
36
  OrganizationId,
37
+ OutputPublicId,
35
38
  PackageId,
36
39
  ProjectId,
40
+ RecordingPublicId,
37
41
  ResourceId,
38
42
  ResourceUri,
39
43
  TagId,
40
44
  TrainedModelId,
45
+ parse_job_public_id,
46
+ parse_model_public_id,
47
+ parse_output_public_id,
48
+ parse_recording_public_id,
41
49
  )
42
50
 
43
51
  __all__ = [
@@ -56,6 +64,14 @@ __all__ = [
56
64
  "ProjectId",
57
65
  "PackageId",
58
66
  "JobId",
67
+ "JobPublicId",
68
+ "ModelPublicId",
69
+ "RecordingPublicId",
70
+ "OutputPublicId",
71
+ "parse_job_public_id",
72
+ "parse_model_public_id",
73
+ "parse_recording_public_id",
74
+ "parse_output_public_id",
59
75
  "ResourceId",
60
76
  "CheckpointId",
61
77
  "TrainedModelId",
@@ -0,0 +1,135 @@
1
+ """Strongly-typed string identifiers for the platform domain model (Part B).
2
+
3
+ ``NewType`` aliases — zero runtime cost (each is the underlying ``str`` at
4
+ runtime) but distinct to the type checker, so a ``ProjectId`` can never be
5
+ passed where a ``JobId`` is expected.
6
+
7
+ The ``*PublicId`` aliases identify the human-facing, grammar-validated
8
+ references carried in response ``public_id`` fields. Their parsers normalize
9
+ only outer ASCII whitespace and ASCII letter case; Unicode whitespace, Unicode
10
+ case folding, wildcard syntax, and partial identifiers are deliberately not
11
+ accepted.
12
+ """
13
+
14
+ import re
15
+ from typing import NewType
16
+
17
+ OrganizationId = NewType("OrganizationId", str)
18
+ ProjectId = NewType("ProjectId", str)
19
+ PackageId = NewType("PackageId", str)
20
+ JobId = NewType("JobId", str)
21
+ ResourceId = NewType("ResourceId", str)
22
+ CheckpointId = NewType("CheckpointId", str)
23
+ TrainedModelId = NewType("TrainedModelId", str)
24
+ TagId = NewType("TagId", str)
25
+ ResourceUri = NewType("ResourceUri", str) # e.g. "robot/so-arm-100:v3"
26
+ Digest = NewType("Digest", str) # content-addressed package source digest
27
+ RecordingId = NewType("RecordingId", str) # a job-produced MCAP recording (PR-0 wire contract)
28
+ WorkerId = NewType("WorkerId", str) # a claiming worker process (PR-0 wire contract)
29
+ AssetId = NewType("AssetId", str) # a catalog asset (USD Asset Catalogs wire contract, PR-1)
30
+ AssetVersionId = NewType("AssetVersionId", str) # one immutable asset version (PR-1)
31
+ OutputId = NewType("OutputId", str) # a job-produced output in the /outputs projection (Plan B)
32
+
33
+ JobPublicId = NewType("JobPublicId", str)
34
+ ModelPublicId = NewType("ModelPublicId", str)
35
+ RecordingPublicId = NewType("RecordingPublicId", str)
36
+ OutputPublicId = NewType("OutputPublicId", str)
37
+
38
+ _ASCII_WHITESPACE = " \t\n\r\v\f"
39
+ _ASCII_LOWERCASE_TRANSLATION = str.maketrans(
40
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
41
+ "abcdefghijklmnopqrstuvwxyz",
42
+ )
43
+ _JOB_STEM_PATTERN = r"[a-z]{3,10}-[a-z]{3,10}-[0-9a-hjkmnp-tv-z]{6}"
44
+ _CANONICAL_CHILD_COUNTER_PATTERN = r"(?:(?!0000)[0-9]{4}|[1-9][0-9]{4,})"
45
+ _JOB_PUBLIC_ID_RE = re.compile(rf"job_{_JOB_STEM_PATTERN}\Z")
46
+ _MODEL_PUBLIC_ID_RE = re.compile(rf"mdl_{_JOB_STEM_PATTERN}-{_CANONICAL_CHILD_COUNTER_PATTERN}\Z")
47
+ _RECORDING_PUBLIC_ID_RE = re.compile(rf"rec_{_JOB_STEM_PATTERN}-{_CANONICAL_CHILD_COUNTER_PATTERN}\Z")
48
+ _OUTPUT_PUBLIC_ID_RE = re.compile(rf"out_{_JOB_STEM_PATTERN}-{_CANONICAL_CHILD_COUNTER_PATTERN}\Z")
49
+ _MAX_JOB_PUBLIC_ID_LENGTH = 32
50
+ _MAX_CHILD_PUBLIC_ID_LENGTH = 64
51
+
52
+
53
+ def _normalize_public_id(value: str, *, parser: str) -> str:
54
+ if not isinstance(value, str):
55
+ raise TypeError(f"{parser}() requires a str, got {type(value).__name__}.")
56
+ return value.strip(_ASCII_WHITESPACE).translate(_ASCII_LOWERCASE_TRANSLATION)
57
+
58
+
59
+ def _parse_public_id(value: str, *, parser: str, pattern: re.Pattern[str], max_length: int) -> str:
60
+ normalized = _normalize_public_id(value, parser=parser)
61
+ if len(normalized) > max_length or pattern.fullmatch(normalized) is None:
62
+ raise ValueError(f"{parser}() received a non-canonical public ID.")
63
+ return normalized
64
+
65
+
66
+ def parse_job_public_id(value: str) -> JobPublicId:
67
+ """Return a canonical Job ID such as ``job_quiet-cedar-7k3m4q``.
68
+
69
+ Only outer ASCII whitespace is trimmed and only ASCII ``A-Z`` is
70
+ lowercased. Matching is exact: prefixes, partial values, wildcards, and
71
+ non-ASCII input are rejected.
72
+ """
73
+
74
+ return JobPublicId(
75
+ _parse_public_id(
76
+ value,
77
+ parser="parse_job_public_id",
78
+ pattern=_JOB_PUBLIC_ID_RE,
79
+ max_length=_MAX_JOB_PUBLIC_ID_LENGTH,
80
+ )
81
+ )
82
+
83
+
84
+ def parse_model_public_id(value: str) -> ModelPublicId:
85
+ """Return a canonical Model ID such as ``mdl_quiet-cedar-7k3m4q-0001``.
86
+
87
+ Only outer ASCII whitespace is trimmed and only ASCII ``A-Z`` is
88
+ lowercased. Matching is exact and non-ASCII input is rejected. Counters
89
+ use exactly four digits through ``9999`` and expand unpadded at ``10000``.
90
+ """
91
+
92
+ return ModelPublicId(
93
+ _parse_public_id(
94
+ value,
95
+ parser="parse_model_public_id",
96
+ pattern=_MODEL_PUBLIC_ID_RE,
97
+ max_length=_MAX_CHILD_PUBLIC_ID_LENGTH,
98
+ )
99
+ )
100
+
101
+
102
+ def parse_recording_public_id(value: str) -> RecordingPublicId:
103
+ """Return a Recording ID such as ``rec_quiet-cedar-7k3m4q-0001``.
104
+
105
+ Only outer ASCII whitespace is trimmed and only ASCII ``A-Z`` is
106
+ lowercased. Matching is exact and non-ASCII input is rejected. Counters
107
+ use exactly four digits through ``9999`` and expand unpadded at ``10000``.
108
+ """
109
+
110
+ return RecordingPublicId(
111
+ _parse_public_id(
112
+ value,
113
+ parser="parse_recording_public_id",
114
+ pattern=_RECORDING_PUBLIC_ID_RE,
115
+ max_length=_MAX_CHILD_PUBLIC_ID_LENGTH,
116
+ )
117
+ )
118
+
119
+
120
+ def parse_output_public_id(value: str) -> OutputPublicId:
121
+ """Return an Output ID such as ``out_quiet-cedar-7k3m4q-0001``.
122
+
123
+ Only outer ASCII whitespace is trimmed and only ASCII ``A-Z`` is
124
+ lowercased. Matching is exact and non-ASCII input is rejected. Counters
125
+ use exactly four digits through ``9999`` and expand unpadded at ``10000``.
126
+ """
127
+
128
+ return OutputPublicId(
129
+ _parse_public_id(
130
+ value,
131
+ parser="parse_output_public_id",
132
+ pattern=_OUTPUT_PUBLIC_ID_RE,
133
+ max_length=_MAX_CHILD_PUBLIC_ID_LENGTH,
134
+ )
135
+ )
@@ -7,27 +7,6 @@ implementation-free — concrete behaviour lives in the future
7
7
  ``simulo`` client and the ``simulo-backend`` SDK.
8
8
  """
9
9
 
10
- from simulo.interfaces.platform.artifacts import (
11
- DECLARED_OUTPUT_MISSING_CODE,
12
- JOB_ARTIFACT_DOWNLOAD_ROUTE_TEMPLATE,
13
- JOB_ARTIFACTS_ROUTE_TEMPLATE,
14
- MAX_ARTIFACT_NAME_BYTES,
15
- MAX_ARTIFACT_PATH_BYTES,
16
- MAX_OUTPUT_FLAG_CODE_CHARS,
17
- MAX_OUTPUT_FLAG_DETAIL_CHARS,
18
- MAX_OUTPUTS_BYTES,
19
- OUTPUT_DROPPED_DETAILS,
20
- OUTPUT_FLAG_ANOMALY,
21
- OUTPUT_FLAG_OUTPUT_DROPPED,
22
- OUTPUTS_UNDELIVERED_CODE,
23
- WORKER_JOB_ARTIFACTS_PRESIGN_ROUTE_TEMPLATE,
24
- WORKER_JOB_ARTIFACTS_ROUTE_TEMPLATE,
25
- Artifact,
26
- ArtifactDeclaration,
27
- ArtifactRecord,
28
- JobOutputsSummary,
29
- OutputFlag,
30
- )
31
10
  from simulo.interfaces.platform.asset import AssetProtocol
32
11
  from simulo.interfaces.platform.asset_catalog import (
33
12
  ADMIN_ASSET_ROUTE_TEMPLATE,
@@ -99,7 +78,35 @@ from simulo.interfaces.platform.asset_catalog import (
99
78
  from simulo.interfaces.platform.callbacks import JobCallbackProtocol
100
79
  from simulo.interfaces.platform.debug import DebugSessionProtocol, ReplaySessionProtocol, VisualizationSessionProtocol
101
80
  from simulo.interfaces.platform.domain import Checkpoint, Job, Package, Project, Resource, Tag, TrainedModel
102
- from simulo.interfaces.platform.enums import ArtifactKind
81
+ from simulo.interfaces.platform.enums import OutputKind
82
+ from simulo.interfaces.platform.job_events import (
83
+ MAX_PUBLIC_ASSET_FINDING_COUNT,
84
+ MAX_PUBLIC_JOB_EVENT_ATTEMPT,
85
+ MAX_PUBLIC_JOB_EVENT_BYTES,
86
+ MAX_PUBLIC_JOB_EVENT_ENTRIES,
87
+ MAX_PUBLIC_JOB_EVENT_QUIET_SECONDS,
88
+ MAX_PUBLIC_JOB_EVENT_WIRE_BYTES,
89
+ PUBLIC_JOB_EVENT_ATTEMPT_MISMATCH_CODE,
90
+ PUBLIC_JOB_EVENT_OFFSET_CONFLICT_CODE,
91
+ PUBLIC_JOB_EVENT_OFFSET_GAP_CODE,
92
+ PUBLIC_JOB_EVENT_SCHEMA_VERSION,
93
+ PUBLIC_JOB_SUPPORT_ID_HEX_CHARS,
94
+ PUBLIC_JOB_SUPPORT_ID_PREFIX,
95
+ WORKER_JOB_EVENTS_ROUTE_TEMPLATE,
96
+ JobAssetFindingData,
97
+ JobAssetFindingEvent,
98
+ JobPreparingData,
99
+ JobPreparingEvent,
100
+ JobRunningData,
101
+ JobRunningEvent,
102
+ JobStillWorkingData,
103
+ JobStillWorkingEvent,
104
+ PublicAssetFindingReason,
105
+ PublicJobEvent,
106
+ PublicJobEventCode,
107
+ PublicJobEventSeverity,
108
+ PublicJobPreparationPhase,
109
+ )
103
110
  from simulo.interfaces.platform.manifest import (
104
111
  FINDING_CLASSIFICATIONS,
105
112
  MAX_PREFLIGHT_BODY_BYTES,
@@ -112,6 +119,27 @@ from simulo.interfaces.platform.manifest import (
112
119
  PreflightResponse,
113
120
  RuntimeManifest,
114
121
  )
122
+ from simulo.interfaces.platform.outputs import (
123
+ DECLARED_OUTPUT_MISSING_CODE,
124
+ JOB_OUTPUT_DOWNLOAD_ROUTE_TEMPLATE,
125
+ JOB_OUTPUTS_ROUTE_TEMPLATE,
126
+ MAX_OUTPUT_FLAG_CODE_CHARS,
127
+ MAX_OUTPUT_FLAG_DETAIL_CHARS,
128
+ MAX_OUTPUT_NAME_BYTES,
129
+ MAX_OUTPUT_PATH_BYTES,
130
+ MAX_OUTPUTS_BYTES,
131
+ OUTPUT_DROPPED_DETAILS,
132
+ OUTPUT_FLAG_ANOMALY,
133
+ OUTPUT_FLAG_OUTPUT_DROPPED,
134
+ OUTPUTS_UNDELIVERED_CODE,
135
+ WORKER_JOB_ARTIFACTS_PRESIGN_ROUTE_TEMPLATE,
136
+ WORKER_JOB_ARTIFACTS_ROUTE_TEMPLATE,
137
+ JobOutputsSummary,
138
+ Output,
139
+ OutputDeclaration,
140
+ OutputFlag,
141
+ OutputRecord,
142
+ )
115
143
  from simulo.interfaces.platform.policy_bundle import (
116
144
  EXPORT_VALIDATION_JOB_TYPE,
117
145
  JOB_EXPORTS_ROUTE_TEMPLATE,
@@ -119,7 +147,6 @@ from simulo.interfaces.platform.policy_bundle import (
119
147
  MAX_POLICY_NAME_TOKEN_CHARS,
120
148
  POLICY_BUNDLE_ACTION_SCHEMA_FILE,
121
149
  POLICY_BUNDLE_ARCHIVE_NAME_TEMPLATE,
122
- POLICY_BUNDLE_ARTIFACT_KIND,
123
150
  POLICY_BUNDLE_FILES,
124
151
  POLICY_BUNDLE_MANIFEST_FILE,
125
152
  POLICY_BUNDLE_MODEL_ONNX_FILE,
@@ -127,6 +154,7 @@ from simulo.interfaces.platform.policy_bundle import (
127
154
  POLICY_BUNDLE_NORMALIZATION_FILE,
128
155
  POLICY_BUNDLE_OBSERVATION_SCHEMA_FILE,
129
156
  POLICY_BUNDLE_OPTIONAL_FILES,
157
+ POLICY_BUNDLE_OUTPUT_KIND,
130
158
  POLICY_BUNDLE_README_FILE,
131
159
  POLICY_BUNDLE_REQUIRED_FILES,
132
160
  POLICY_BUNDLE_REQUIREMENTS_FILE,
@@ -220,7 +248,34 @@ from simulo.interfaces.platform.volume import VolumeProtocol
220
248
 
221
249
  __all__ = [
222
250
  # enums
223
- "ArtifactKind",
251
+ "OutputKind",
252
+ # closed public job-event contract (#656)
253
+ "PUBLIC_JOB_EVENT_SCHEMA_VERSION",
254
+ "WORKER_JOB_EVENTS_ROUTE_TEMPLATE",
255
+ "MAX_PUBLIC_JOB_EVENT_BYTES",
256
+ "MAX_PUBLIC_JOB_EVENT_WIRE_BYTES",
257
+ "MAX_PUBLIC_JOB_EVENT_ENTRIES",
258
+ "MAX_PUBLIC_JOB_EVENT_ATTEMPT",
259
+ "MAX_PUBLIC_JOB_EVENT_QUIET_SECONDS",
260
+ "MAX_PUBLIC_ASSET_FINDING_COUNT",
261
+ "PUBLIC_JOB_SUPPORT_ID_PREFIX",
262
+ "PUBLIC_JOB_SUPPORT_ID_HEX_CHARS",
263
+ "PUBLIC_JOB_EVENT_OFFSET_GAP_CODE",
264
+ "PUBLIC_JOB_EVENT_OFFSET_CONFLICT_CODE",
265
+ "PUBLIC_JOB_EVENT_ATTEMPT_MISMATCH_CODE",
266
+ "PublicJobEventSeverity",
267
+ "PublicJobEventCode",
268
+ "PublicJobPreparationPhase",
269
+ "PublicAssetFindingReason",
270
+ "JobPreparingData",
271
+ "JobRunningData",
272
+ "JobStillWorkingData",
273
+ "JobAssetFindingData",
274
+ "JobPreparingEvent",
275
+ "JobRunningEvent",
276
+ "JobStillWorkingEvent",
277
+ "JobAssetFindingEvent",
278
+ "PublicJobEvent",
224
279
  # domain dataclasses
225
280
  "Tag",
226
281
  "Project",
@@ -243,18 +298,18 @@ __all__ = [
243
298
  # typed job outputs (Plan B, #531) — pre-run declaration, execution-time
244
299
  # registration, projection row, completion announcement, routes, caps,
245
300
  # pinned wire codes
246
- "ArtifactDeclaration",
247
- "Artifact",
248
- "ArtifactRecord",
301
+ "OutputDeclaration",
302
+ "Output",
303
+ "OutputRecord",
249
304
  "OutputFlag",
250
305
  "JobOutputsSummary",
251
- "JOB_ARTIFACTS_ROUTE_TEMPLATE",
252
- "JOB_ARTIFACT_DOWNLOAD_ROUTE_TEMPLATE",
306
+ "JOB_OUTPUTS_ROUTE_TEMPLATE",
307
+ "JOB_OUTPUT_DOWNLOAD_ROUTE_TEMPLATE",
253
308
  "WORKER_JOB_ARTIFACTS_PRESIGN_ROUTE_TEMPLATE",
254
309
  "WORKER_JOB_ARTIFACTS_ROUTE_TEMPLATE",
255
310
  "MAX_OUTPUTS_BYTES",
256
- "MAX_ARTIFACT_NAME_BYTES",
257
- "MAX_ARTIFACT_PATH_BYTES",
311
+ "MAX_OUTPUT_NAME_BYTES",
312
+ "MAX_OUTPUT_PATH_BYTES",
258
313
  "MAX_OUTPUT_FLAG_CODE_CHARS",
259
314
  "MAX_OUTPUT_FLAG_DETAIL_CHARS",
260
315
  "OUTPUT_FLAG_ANOMALY",
@@ -406,7 +461,7 @@ __all__ = [
406
461
  "MAX_POLICY_BUNDLE_UNCOMPRESSED_BYTES",
407
462
  "POLICY_TEST_VECTOR_INPUTS_KEY",
408
463
  "POLICY_TEST_VECTOR_EXPECTED_OUTPUTS_KEY",
409
- "POLICY_BUNDLE_ARTIFACT_KIND",
464
+ "POLICY_BUNDLE_OUTPUT_KIND",
410
465
  "POLICY_BUNDLE_ROOT_DIR_TEMPLATE",
411
466
  "POLICY_BUNDLE_ARCHIVE_NAME_TEMPLATE",
412
467
  "MAX_POLICY_NAME_TOKEN_CHARS",
@@ -0,0 +1,15 @@
1
+ """Internal helpers for tolerant response-record reconstruction."""
2
+
3
+ from collections.abc import Mapping
4
+ from dataclasses import fields
5
+ from typing import Any
6
+
7
+
8
+ def known_payload_fields(record_type: Any, payload: Mapping[str, Any], *, owner: str) -> dict[str, Any]:
9
+ """Copy only fields declared by ``record_type`` from one response mapping."""
10
+
11
+ if not isinstance(payload, Mapping):
12
+ raise TypeError(f"{owner} requires a mapping, got {type(payload).__name__}.")
13
+ return {
14
+ definition.name: payload[definition.name] for definition in fields(record_type) if definition.name in payload
15
+ }
@@ -248,7 +248,7 @@ GLOBAL_ASSET_PUBLISHER = "simulo"
248
248
  #: (``^[a-z0-9](?:[a-z0-9-]{1,61}[a-z0-9])?$``, 3–63 chars): this pattern accepts
249
249
  #: **1–63** chars of lowercase letters/digits/hyphens, starting and ending with a
250
250
  #: letter or digit. The CP org-slug pattern's *effective* 3-char floor is an
251
- #: artifact of ``derive_slug()`` padding a short org NAME at derivation time
251
+ #: output of ``derive_slug()`` padding a short org NAME at derivation time
252
252
  #: (``users/slug.py``: ``if len(s) < 3: s = s + "org"``), not a validation rule —
253
253
  #: short names like ``h1`` or ``go2`` are legitimate robot/world asset names and
254
254
  #: must validate. (An earlier draft of this pattern used the CP's own ``{1,61}``
@@ -689,7 +689,7 @@ ASSET_MISSING_CODE = "asset_missing"
689
689
  #: The ``jobs.job_type`` value of a platform-internal asset-validation job
690
690
  #: (PR-11 amendment, 2026-07-17). The claim response's job record carries a
691
691
  #: ``job_type`` field (additive; absent against a pre-PR-11 control plane) and
692
- #: the worker keys its artifact-pickup branch on THIS exact string: a claimed
692
+ #: the worker keys its output-pickup branch on THIS exact string: a claimed
693
693
  #: job of this type has its run-dir validation outputs picked up and finalized
694
694
  #: against :data:`WORKER_JOB_ASSET_VALIDATION_ROUTE_TEMPLATE` after execution.
695
695
  #: Mirrors the control plane's ``assets/constants.py::ASSET_VALIDATION_JOB_TYPE``
@@ -12,7 +12,7 @@ Domain invariants encoded here:
12
12
  * ``Resource`` is a read-only, versioned, registry-resolved mount
13
13
  (robot / environment / dataset / …); it is NOT a package.
14
14
  * ``Project`` is the workspace anchor every other object hangs off.
15
- * ``Checkpoint`` (intermediate training artifact) and
15
+ * ``Checkpoint`` (intermediate training output) and
16
16
  ``TrainedModel`` (final, deployable model) are separate types — never collapse.
17
17
  """
18
18
 
@@ -97,7 +97,7 @@ class Job:
97
97
 
98
98
  @dataclass(**_DC)
99
99
  class Checkpoint:
100
- """Intermediate training artifact (Rule #8) — distinct from a TrainedModel."""
100
+ """Intermediate training output (Rule #8) — distinct from a TrainedModel."""
101
101
 
102
102
  id: CheckpointId
103
103
  job_id: JobId
@@ -108,7 +108,7 @@ class Checkpoint:
108
108
 
109
109
  @dataclass(**_DC)
110
110
  class TrainedModel:
111
- """Final, deployable model artifact (Rule #8) — distinct from a Checkpoint."""
111
+ """Final, deployable model output (Rule #8) — distinct from a Checkpoint."""
112
112
 
113
113
  id: TrainedModelId
114
114
  project_id: ProjectId
@@ -22,7 +22,7 @@ class JobStatus(StrEnum):
22
22
  """Claimed by a worker and executing."""
23
23
 
24
24
  COMPLETED = "completed"
25
- """Finished successfully — the result and artifacts are available."""
25
+ """Finished successfully — the result and outputs are available."""
26
26
 
27
27
  FAILED = "failed"
28
28
  """Finished unsuccessfully — see the job's logs for the failure."""
@@ -80,14 +80,14 @@ class ResourceKind(StrEnum):
80
80
  """
81
81
 
82
82
 
83
- class ArtifactKind(StrEnum):
84
- """Kind of a job-produced artifact — a checkpoint is NOT a trained model.
83
+ class OutputKind(StrEnum):
84
+ """Kind of a job-produced output — a checkpoint is NOT a trained model.
85
85
 
86
86
  Checkpoints are resumable training state; trained models are standalone,
87
- deployable policy artifacts. The platform never conflates the two.
87
+ deployable policy outputs. The platform never conflates the two.
88
88
 
89
89
  Values are a stable wire ABI persisted in database rows (``job_recordings
90
- .kind``, ``job_artifacts.kind``) and served by the ``/artifacts`` union
90
+ .kind``, ``job_artifacts.kind``) and served by the ``/outputs`` union
91
91
  projection: **append-only, never renumber, rename, or reorder** — the six
92
92
  members up to ``EVALUATION_OUTPUT`` predate the typed-outputs contract
93
93
  and every member added for the typed-outputs contract is appended after them.
@@ -100,7 +100,7 @@ class ArtifactKind(StrEnum):
100
100
  callback."""
101
101
 
102
102
  TRAINED_MODEL = "trained_model"
103
- """A standalone, deployable policy artifact — for inference/playback."""
103
+ """A standalone, deployable policy output — for inference/playback."""
104
104
 
105
105
  LOG = "log"
106
106
  """The job's captured log stream."""
@@ -173,5 +173,8 @@ class ArtifactKind(StrEnum):
173
173
 
174
174
  FILE = "file"
175
175
  """A general produced file. This is the default kind used by
176
- ``simulo.save_artifact``. The current managed platform records the
177
- registration but does not publish general files for download."""
176
+ ``simulo.save_output``. After a successful job completes, the worker
177
+ uploads eligible registrations to ``job_artifacts``; persisted files are
178
+ listed by the external ``/outputs`` projection and can be downloaded.
179
+ Registration alone does not guarantee delivery on a failed run or when an
180
+ upload is refused."""