rocket-engine 0.0.2b1__py3-none-any.whl

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 (241) hide show
  1. rocket_engine/__init__.py +8 -0
  2. rocket_engine/__main__.py +12 -0
  3. rocket_engine/adapters/README.md +54 -0
  4. rocket_engine/adapters/__init__.py +7 -0
  5. rocket_engine/adapters/api.py +39 -0
  6. rocket_engine/adapters/base.py +46 -0
  7. rocket_engine/adapters/cace/__init__.py +163 -0
  8. rocket_engine/adapters/circulax/README.md +10 -0
  9. rocket_engine/adapters/circulax/__init__.py +112 -0
  10. rocket_engine/adapters/circulax/_driver.py +190 -0
  11. rocket_engine/adapters/circulax/adapter.py +538 -0
  12. rocket_engine/adapters/circulax/results.py +291 -0
  13. rocket_engine/adapters/cli/README.md +34 -0
  14. rocket_engine/adapters/cli/__init__.py +305 -0
  15. rocket_engine/adapters/connectivity/__init__.py +196 -0
  16. rocket_engine/adapters/connectivity/results.py +214 -0
  17. rocket_engine/adapters/cosim/README.md +9 -0
  18. rocket_engine/adapters/cosim/__init__.py +1390 -0
  19. rocket_engine/adapters/cosim/results.py +214 -0
  20. rocket_engine/adapters/devsim/__init__.py +171 -0
  21. rocket_engine/adapters/digital_flow/README.md +9 -0
  22. rocket_engine/adapters/digital_flow/__init__.py +1121 -0
  23. rocket_engine/adapters/digital_flow/results.py +227 -0
  24. rocket_engine/adapters/digital_flow/state.py +462 -0
  25. rocket_engine/adapters/drc/README.klayout.md +7 -0
  26. rocket_engine/adapters/drc/README.md +7 -0
  27. rocket_engine/adapters/drc/__init__.py +1 -0
  28. rocket_engine/adapters/drc/klayout.py +952 -0
  29. rocket_engine/adapters/drc/magic.py +287 -0
  30. rocket_engine/adapters/drc/results.py +184 -0
  31. rocket_engine/adapters/drc/results_kl.py +188 -0
  32. rocket_engine/adapters/elmer/__init__.py +163 -0
  33. rocket_engine/adapters/envelope.py +120 -0
  34. rocket_engine/adapters/equivalence/__init__.py +156 -0
  35. rocket_engine/adapters/errors.py +181 -0
  36. rocket_engine/adapters/extract_magic/README.md +15 -0
  37. rocket_engine/adapters/extract_magic/__init__.py +425 -0
  38. rocket_engine/adapters/extract_magic/results.py +209 -0
  39. rocket_engine/adapters/formal_sby/README.md +7 -0
  40. rocket_engine/adapters/formal_sby/__init__.py +773 -0
  41. rocket_engine/adapters/formal_sby/formal_edge.py +195 -0
  42. rocket_engine/adapters/formal_sby/results.py +185 -0
  43. rocket_engine/adapters/gdsfactory/__init__.py +194 -0
  44. rocket_engine/adapters/gdsfactory/_driver.py +459 -0
  45. rocket_engine/adapters/gdsfactory/adapter.py +609 -0
  46. rocket_engine/adapters/gdsfactory/results.py +181 -0
  47. rocket_engine/adapters/hdl_sim/README.md +7 -0
  48. rocket_engine/adapters/hdl_sim/__init__.py +369 -0
  49. rocket_engine/adapters/hdl_sim/ghdl.py +155 -0
  50. rocket_engine/adapters/hdl_sim/results.py +178 -0
  51. rocket_engine/adapters/hdl_sim/verilator.py +167 -0
  52. rocket_engine/adapters/http/README.md +15 -0
  53. rocket_engine/adapters/http/__init__.py +458 -0
  54. rocket_engine/adapters/http/events.py +63 -0
  55. rocket_engine/adapters/ipc/README.md +9 -0
  56. rocket_engine/adapters/ipc/__init__.py +111 -0
  57. rocket_engine/adapters/lvs_netgen/README.md +20 -0
  58. rocket_engine/adapters/lvs_netgen/__init__.py +889 -0
  59. rocket_engine/adapters/lvs_netgen/results.py +168 -0
  60. rocket_engine/adapters/mcp/README.md +19 -0
  61. rocket_engine/adapters/mcp/__init__.py +85 -0
  62. rocket_engine/adapters/mcp/api-schema.json +6107 -0
  63. rocket_engine/adapters/mcp/pull.py +246 -0
  64. rocket_engine/adapters/mcp/server.py +794 -0
  65. rocket_engine/adapters/meep/__init__.py +167 -0
  66. rocket_engine/adapters/meow/README.md +7 -0
  67. rocket_engine/adapters/meow/__init__.py +190 -0
  68. rocket_engine/adapters/meow/_driver.py +227 -0
  69. rocket_engine/adapters/meow/_envelope.py +108 -0
  70. rocket_engine/adapters/meow/adapter.py +491 -0
  71. rocket_engine/adapters/meow/results.py +218 -0
  72. rocket_engine/adapters/mutation/__init__.py +192 -0
  73. rocket_engine/adapters/ngspice/README.md +28 -0
  74. rocket_engine/adapters/ngspice/__init__.py +627 -0
  75. rocket_engine/adapters/ngspice/results.py +215 -0
  76. rocket_engine/adapters/postlayout/README.md +28 -0
  77. rocket_engine/adapters/postlayout/__init__.py +17 -0
  78. rocket_engine/adapters/postlayout/adapter.py +1062 -0
  79. rocket_engine/adapters/postlayout/results.py +330 -0
  80. rocket_engine/adapters/postlayout/translate.py +71 -0
  81. rocket_engine/adapters/profile.py +220 -0
  82. rocket_engine/adapters/sax/README.md +23 -0
  83. rocket_engine/adapters/sax/__init__.py +516 -0
  84. rocket_engine/adapters/sax/_driver.py +148 -0
  85. rocket_engine/adapters/sax/results.py +291 -0
  86. rocket_engine/adapters/stdio_console.py +1151 -0
  87. rocket_engine/adapters/syntax/README.md +5 -0
  88. rocket_engine/adapters/syntax/__init__.py +366 -0
  89. rocket_engine/adapters/syntax/results.py +181 -0
  90. rocket_engine/adapters/synth_yosys/README.md +7 -0
  91. rocket_engine/adapters/synth_yosys/__init__.py +655 -0
  92. rocket_engine/adapters/synth_yosys/amaranth.py +120 -0
  93. rocket_engine/adapters/synth_yosys/ghdl.py +128 -0
  94. rocket_engine/adapters/synth_yosys/results.py +173 -0
  95. rocket_engine/adapters/timing_sta/README.md +9 -0
  96. rocket_engine/adapters/timing_sta/__init__.py +726 -0
  97. rocket_engine/adapters/view_sync/__init__.py +185 -0
  98. rocket_engine/adapters/view_sync/results.py +189 -0
  99. rocket_engine/adapters/vlsir/__init__.py +142 -0
  100. rocket_engine/adapters/xschem/__init__.py +440 -0
  101. rocket_engine/adapters/xschem/deck.py +266 -0
  102. rocket_engine/clients/__init__.py +5 -0
  103. rocket_engine/clients/runtime.py +255 -0
  104. rocket_engine/composition.py +2279 -0
  105. rocket_engine/execution/README.md +30 -0
  106. rocket_engine/execution/__init__.py +150 -0
  107. rocket_engine/execution/apig/__init__.py +1 -0
  108. rocket_engine/execution/apig/pool.py +463 -0
  109. rocket_engine/execution/apig/submit.py +124 -0
  110. rocket_engine/execution/block_runs_scope.py +479 -0
  111. rocket_engine/execution/coalesce.py +414 -0
  112. rocket_engine/execution/console/__init__.py +1 -0
  113. rocket_engine/execution/console/apply_session.py +318 -0
  114. rocket_engine/execution/console/lifecycle.py +265 -0
  115. rocket_engine/execution/dispatch.py +205 -0
  116. rocket_engine/execution/errors.py +31 -0
  117. rocket_engine/execution/ports.py +797 -0
  118. rocket_engine/execution/pyexec/__init__.py +1 -0
  119. rocket_engine/execution/pyexec/apply_context.py +547 -0
  120. rocket_engine/execution/pyexec/approvals.py +173 -0
  121. rocket_engine/execution/pyexec/runner.py +404 -0
  122. rocket_engine/execution/pyexec/support.py +464 -0
  123. rocket_engine/execution/python_exec.py +897 -0
  124. rocket_engine/execution/queue.py +85 -0
  125. rocket_engine/execution/replay_safe.py +601 -0
  126. rocket_engine/execution/routing/__init__.py +1 -0
  127. rocket_engine/execution/routing/calls.py +364 -0
  128. rocket_engine/execution/routing/namespace.py +785 -0
  129. rocket_engine/execution/routing/ports.py +102 -0
  130. rocket_engine/execution/routing/tools.py +346 -0
  131. rocket_engine/execution/runner.py +311 -0
  132. rocket_engine/execution/runtime.py +1149 -0
  133. rocket_engine/execution/service.py +279 -0
  134. rocket_engine/execution/worker.py +464 -0
  135. rocket_engine/interfaces/README.md +26 -0
  136. rocket_engine/interfaces/__init__.py +58 -0
  137. rocket_engine/interfaces/apig_assets.py +407 -0
  138. rocket_engine/interfaces/celllink.py +461 -0
  139. rocket_engine/interfaces/documents.py +92 -0
  140. rocket_engine/interfaces/envelopes.py +131 -0
  141. rocket_engine/interfaces/errors.py +16 -0
  142. rocket_engine/interfaces/layout.py +410 -0
  143. rocket_engine/interfaces/layout_schema.yaml +278 -0
  144. rocket_engine/interfaces/paths.py +223 -0
  145. rocket_engine/interfaces/pdks.py +550 -0
  146. rocket_engine/interfaces/ports.py +72 -0
  147. rocket_engine/interfaces/references.py +115 -0
  148. rocket_engine/interfaces/refs.py +85 -0
  149. rocket_engine/interfaces/runparams.py +304 -0
  150. rocket_engine/interfaces/setup.py +552 -0
  151. rocket_engine/interfaces/setup_catalogue.yaml +243 -0
  152. rocket_engine/interfaces/setup_probes.py +66 -0
  153. rocket_engine/interfaces/vocabulary.py +58 -0
  154. rocket_engine/interfaces/yaml_dump.py +31 -0
  155. rocket_engine/library/README.md +22 -0
  156. rocket_engine/library/__init__.py +13 -0
  157. rocket_engine/library/apig_catalog.py +371 -0
  158. rocket_engine/library/catalog.py +185 -0
  159. rocket_engine/library/errors.py +16 -0
  160. rocket_engine/mutate/__init__.py +776 -0
  161. rocket_engine/mutate/operators.py +700 -0
  162. rocket_engine/ops/__init__.py +1 -0
  163. rocket_engine/ops/deferred.py +279 -0
  164. rocket_engine/ops/editors.py +404 -0
  165. rocket_engine/ops/evidence.py +194 -0
  166. rocket_engine/ops/gates.py +262 -0
  167. rocket_engine/ops/ports.py +76 -0
  168. rocket_engine/ops/queries.py +417 -0
  169. rocket_engine/ops/runs.py +553 -0
  170. rocket_engine/ops/submit.py +614 -0
  171. rocket_engine/project/README.md +27 -0
  172. rocket_engine/project/__init__.py +6 -0
  173. rocket_engine/project/canvas/__init__.py +55 -0
  174. rocket_engine/project/canvas/compile.py +109 -0
  175. rocket_engine/project/canvas/integrate.py +48 -0
  176. rocket_engine/project/canvas/schema.py +241 -0
  177. rocket_engine/project/canvas/templates.py +46 -0
  178. rocket_engine/project/canvas/validate.py +603 -0
  179. rocket_engine/project/edit/__init__.py +5 -0
  180. rocket_engine/project/edit/cas.py +87 -0
  181. rocket_engine/project/edit/transactions.py +282 -0
  182. rocket_engine/project/errors.py +16 -0
  183. rocket_engine/project/frontend13.py +685 -0
  184. rocket_engine/project/geometry/__init__.py +23 -0
  185. rocket_engine/project/geometry/ops.py +451 -0
  186. rocket_engine/project/geometry/snap.py +103 -0
  187. rocket_engine/project/ip/__init__.py +1 -0
  188. rocket_engine/project/ip/blocks.py +195 -0
  189. rocket_engine/project/ip/entry.schema.json +78 -0
  190. rocket_engine/project/ip/lifecycle.py +402 -0
  191. rocket_engine/project/ip/verbs.py +123 -0
  192. rocket_engine/project/layers/__init__.py +6 -0
  193. rocket_engine/project/layers/bindings.py +115 -0
  194. rocket_engine/project/layers/catalog.py +228 -0
  195. rocket_engine/project/layers/presets.py +43 -0
  196. rocket_engine/project/ledger/__init__.py +1 -0
  197. rocket_engine/project/ledger/docs.py +167 -0
  198. rocket_engine/project/ledger/entities.py +176 -0
  199. rocket_engine/project/ledger/events.py +29 -0
  200. rocket_engine/project/ledger/runs.py +257 -0
  201. rocket_engine/project/ledger/shared.py +174 -0
  202. rocket_engine/project/ledger/snapshots.py +385 -0
  203. rocket_engine/project/ledger/wires.py +552 -0
  204. rocket_engine/project/process/__init__.py +14 -0
  205. rocket_engine/project/process/model.py +193 -0
  206. rocket_engine/project/process/recipes.py +121 -0
  207. rocket_engine/project/schematic/__init__.py +1 -0
  208. rocket_engine/project/schematic/hierarchy.py +312 -0
  209. rocket_engine/project/schematic/instances.py +393 -0
  210. rocket_engine/project/schematic/sheets.py +198 -0
  211. rocket_engine/project/service.py +2941 -0
  212. rocket_engine/project/symbols/__init__.py +1 -0
  213. rocket_engine/project/symbols/cells.py +324 -0
  214. rocket_engine/project/symbols/linkage.py +356 -0
  215. rocket_engine/project/symbols/symbols.py +352 -0
  216. rocket_engine/project/templates/__init__.py +303 -0
  217. rocket_engine/project/templates/errors.py +25 -0
  218. rocket_engine/project/testbench/__init__.py +49 -0
  219. rocket_engine/project/testbench/blocks.py +619 -0
  220. rocket_engine/project/testbench/templates.py +134 -0
  221. rocket_engine/stores/README.md +12 -0
  222. rocket_engine/stores/__init__.py +6 -0
  223. rocket_engine/stores/ecs.py +1508 -0
  224. rocket_engine/stores/layers.py +1023 -0
  225. rocket_engine/stores/settings.py +1188 -0
  226. rocket_engine/stores/wireplace.py +1324 -0
  227. rocket_engine/workflows/README.md +18 -0
  228. rocket_engine/workflows/__init__.py +53 -0
  229. rocket_engine/workflows/capability_plan.py +102 -0
  230. rocket_engine/workflows/completion.py +228 -0
  231. rocket_engine/workflows/connectgraph.py +734 -0
  232. rocket_engine/workflows/connectgraph_emit.py +336 -0
  233. rocket_engine/workflows/gates.py +144 -0
  234. rocket_engine/workflows/photonic_wire.py +76 -0
  235. rocket_engine/workflows/stages.py +324 -0
  236. rocket_engine/workflows/viewsync.py +399 -0
  237. rocket_engine-0.0.2b1.dist-info/METADATA +200 -0
  238. rocket_engine-0.0.2b1.dist-info/RECORD +241 -0
  239. rocket_engine-0.0.2b1.dist-info/WHEEL +4 -0
  240. rocket_engine-0.0.2b1.dist-info/entry_points.txt +2 -0
  241. rocket_engine-0.0.2b1.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,291 @@
1
+ """Sax v1 normalizer: v0 parse output to a ResultBundle.
2
+
3
+ Maps the ``run_optical`` sax parse shape (``measurements[]`` with
4
+ dB value, target, margin, and pass/fail status plus per-target
5
+ spectra) onto a typed measurement table, one wavelength series
6
+ dataset per spectrum with a bound trace view, measurements, and
7
+ findings. Pure function of the parsed output: no I/O, no tool
8
+ calls, deterministic ids derived from the run id. PASS
9
+ measurements keep value, target, margin, and status.
10
+ """
11
+
12
+ TASK = "run_optical"
13
+
14
+ _DIAG_CAP = 240
15
+ _INLINE_CAP = 1024
16
+
17
+ _SEVERITY = {"error": "error", "warning": "warning"}
18
+
19
+
20
+ def _cap(text):
21
+ """Cap one diagnostic string at the bundle prose limit.
22
+
23
+ Args:
24
+ text: Raw diagnostic text, possibly unbounded tool prose.
25
+
26
+ Returns:
27
+ The text unchanged when short, else truncated with an
28
+ ellipsis marker.
29
+ """
30
+ text = text if isinstance(text, str) else str(text)
31
+ if len(text) <= _DIAG_CAP:
32
+ return text
33
+ return text[: _DIAG_CAP - 3] + "..."
34
+
35
+
36
+ def _quantity(value, unit):
37
+ """Build one v1 Quantity, mapping unitless to dimensionless.
38
+
39
+ Args:
40
+ value: Numeric value.
41
+ unit: Unit string, possibly empty for unitless measures.
42
+
43
+ Returns:
44
+ Quantity mapping with an explicit unit.
45
+ """
46
+ return {"value": float(value), "unit": unit if unit else "1"}
47
+
48
+
49
+ def _limit(item):
50
+ """Pick the binding target bound for one measurement.
51
+
52
+ Args:
53
+ item: v0 measurement with a ``target`` min/max mapping.
54
+
55
+ Returns:
56
+ The bound closest to the measured value (the margin
57
+ binding bound), or None when the target is empty.
58
+ """
59
+ target = item.get("target") or {}
60
+ scored = []
61
+ if target.get("min") is not None:
62
+ scored.append((float(item["value"]) - float(target["min"]),
63
+ float(target["min"])))
64
+ if target.get("max") is not None:
65
+ scored.append((float(target["max"]) - float(item["value"]),
66
+ float(target["max"])))
67
+ if not scored:
68
+ return None
69
+ return min(scored)[1]
70
+
71
+
72
+ def _downsample(values):
73
+ """Stride-downsample one sample list to the inline cap.
74
+
75
+ Args:
76
+ values: Sample values in stored order.
77
+
78
+ Returns:
79
+ (samples, downsampled) pair with at most _INLINE_CAP
80
+ entries, stride-picked deterministically.
81
+ """
82
+ values = list(values)
83
+ if len(values) <= _INLINE_CAP:
84
+ return values, False
85
+ step = -(-len(values) // _INLINE_CAP)
86
+ return values[::step], True
87
+
88
+
89
+ def _provenance(project_id, run_id, tools, provenance):
90
+ """Build ResultProvenance, defaulting to a placeholder closure.
91
+
92
+ Args:
93
+ project_id: Project the run belongs to.
94
+ run_id: Run the bundle describes.
95
+ tools: Tool ingredient mappings (id, version, digest?).
96
+ provenance: Full provenance mapping when the caller has
97
+ one; a deterministic placeholder otherwise.
98
+
99
+ Returns:
100
+ Provenance mapping valid against the v1 schema.
101
+ """
102
+ if provenance is not None:
103
+ return provenance
104
+ ref = {"scope": "project", "id": project_id, "revision": "r1"}
105
+ return {
106
+ "snapshot": dict(ref),
107
+ "input_lock": dict(ref),
108
+ "closure_hash": "0" * 64,
109
+ "tools": [
110
+ {
111
+ "id": item["id"],
112
+ "version": item.get("version", ""),
113
+ "digest": item.get("digest", "0" * 64),
114
+ }
115
+ for item in tools
116
+ ],
117
+ "parents": [],
118
+ }
119
+
120
+
121
+ def normalize(parsed, *, run_id, project_id="project", target=None,
122
+ tools=(), provenance=None):
123
+ """Normalize one sax parse output to a v1 ResultBundle.
124
+
125
+ Measurement rows become a table dataset plus a bound table
126
+ view; every spectrum becomes a wavelength series dataset with
127
+ a bound trace view; violations become findings with capped
128
+ messages. PASS measurements keep value, target, margin, and
129
+ status. A malformed circuit (no spectra) reports
130
+ not_converged with its error finding.
131
+
132
+ Args:
133
+ parsed: v0 parse mapping with ``measurements[]``,
134
+ ``spectra[]``, and ``violations[]``.
135
+ run_id: Run the bundle describes (anchors all ids).
136
+ project_id: Project the run belongs to.
137
+ target: v1 target mapping; project kind by default.
138
+ tools: Tool ingredient mappings for provenance.
139
+ provenance: Full provenance mapping when the caller has
140
+ one; a deterministic placeholder otherwise.
141
+
142
+ Returns:
143
+ Schema-valid ResultBundle mapping.
144
+ """
145
+ measurements_in = parsed.get("measurements") or []
146
+ spectra_in = parsed.get("spectra") or []
147
+ violations = parsed.get("violations") or []
148
+ table_id = f"{run_id}:dataset:measurements"
149
+ datasets = [
150
+ {
151
+ "id": table_id,
152
+ "kind": "table",
153
+ "row_count": len(measurements_in),
154
+ "columns": [
155
+ {
156
+ "id": f"{table_id}:name",
157
+ "name": "name",
158
+ "dtype": "utf8",
159
+ "unit": "1",
160
+ "data": [item["name"] for item in measurements_in],
161
+ },
162
+ {
163
+ "id": f"{table_id}:value",
164
+ "name": "value",
165
+ "dtype": "float64",
166
+ "unit": "1",
167
+ "data": [float(item["value"]) for item in measurements_in],
168
+ },
169
+ {
170
+ "id": f"{table_id}:margin",
171
+ "name": "margin",
172
+ "dtype": "float64",
173
+ "unit": "1",
174
+ "data": [float(item["margin"]) for item in measurements_in],
175
+ },
176
+ {
177
+ "id": f"{table_id}:status",
178
+ "name": "status",
179
+ "dtype": "utf8",
180
+ "unit": "1",
181
+ "data": [item["status"] for item in measurements_in],
182
+ },
183
+ ],
184
+ "conditions": [],
185
+ }
186
+ ]
187
+ views = [
188
+ {
189
+ "id": f"{run_id}:view:measurements",
190
+ "kind": "table",
191
+ "dataset_id": table_id,
192
+ "name": "measurements",
193
+ }
194
+ ]
195
+ for index, spectrum in enumerate(spectra_in):
196
+ grid, _ = _downsample(spectrum.get("wavelength_nm") or [])
197
+ curve, _ = _downsample(spectrum.get("transmission_db") or [])
198
+ ds_id = f"{run_id}:dataset:spectrum:{index}"
199
+ axis_id = f"{ds_id}:wavelength"
200
+ sig_id = f"{ds_id}:transmission"
201
+ name = f"{spectrum.get('from', '')}>{spectrum.get('to', '')}"
202
+ datasets.append(
203
+ {
204
+ "id": ds_id,
205
+ "kind": "series",
206
+ "analysis": "ac",
207
+ "axes": [
208
+ {
209
+ "id": axis_id,
210
+ "name": "wavelength",
211
+ "quantity": "wavelength",
212
+ "unit": "nm",
213
+ "kind": "continuous",
214
+ "scale": "linear",
215
+ "values": [float(v) for v in grid],
216
+ }
217
+ ],
218
+ "signals": [
219
+ {
220
+ "id": sig_id,
221
+ "name": name,
222
+ "quantity": "power_ratio",
223
+ "unit": "dB",
224
+ "values": {
225
+ "storage": "inline",
226
+ "dtype": "float64",
227
+ "shape": [len(curve)],
228
+ "data": [float(v) for v in curve],
229
+ },
230
+ }
231
+ ],
232
+ "conditions": [],
233
+ }
234
+ )
235
+ views.append(
236
+ {
237
+ "id": f"{run_id}:view:spectrum:{index}",
238
+ "kind": "traces",
239
+ "dataset_id": ds_id,
240
+ "name": name,
241
+ "x_axis": axis_id,
242
+ "traces": [
243
+ {"signal": sig_id, "transform": "identity",
244
+ "axis": "left"}
245
+ ],
246
+ }
247
+ )
248
+ measurements = []
249
+ for item in measurements_in:
250
+ entry = {
251
+ "name": item["name"],
252
+ "value": _quantity(item["value"], item.get("unit", "")),
253
+ "margin": _quantity(item["margin"], item.get("unit", "")),
254
+ "status": "PASS" if item["status"] == "pass" else "FAIL",
255
+ }
256
+ bound = _limit(item)
257
+ if bound is not None:
258
+ entry["limit"] = _quantity(bound, item.get("unit", ""))
259
+ measurements.append(entry)
260
+ findings = [
261
+ {
262
+ "id": f"{run_id}:finding:{index}",
263
+ "severity": _SEVERITY.get(v.get("severity"), "info"),
264
+ "code": v.get("rule", "circuit"),
265
+ "message": _cap(v.get("message", "")),
266
+ }
267
+ for index, v in enumerate(violations)
268
+ ]
269
+ converged = not any(
270
+ v.get("rule") in ("circuit", "transmission") for v in violations
271
+ )
272
+ return {
273
+ "schema": "rocketeda/results/v1",
274
+ "ref": {"scope": "project", "id": run_id, "revision": "r1"},
275
+ "run_id": run_id,
276
+ "task": TASK,
277
+ "target": dict(target)
278
+ if target is not None
279
+ else {"project_id": project_id, "kind": "project"},
280
+ "state": "complete",
281
+ "freshness": "current",
282
+ "convergence": "converged" if converged else "not_converged",
283
+ "provenance": _provenance(project_id, run_id, tools, provenance),
284
+ "datasets": datasets,
285
+ "views": views,
286
+ "measurements": measurements,
287
+ "findings": findings,
288
+ "artifacts": [],
289
+ "logs": [],
290
+ "gaps": [],
291
+ }