@typecad/cuttlefish 1.0.0-alpha.13 → 1.0.0-alpha.15

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 (343) hide show
  1. package/README.md +82 -79
  2. package/assets/editor-extensions/typecad-debug/README.md +141 -0
  3. package/assets/editor-extensions/typecad-debug/out/extension.js +347 -0
  4. package/assets/editor-extensions/typecad-debug/out/extension.js.map +1 -0
  5. package/assets/editor-extensions/typecad-debug/package.json +76 -0
  6. package/assets/editor-extensions/typecad-ui/LICENSE +27 -0
  7. package/assets/editor-extensions/typecad-ui/README.md +52 -0
  8. package/assets/editor-extensions/typecad-ui/file-icon-dark.png +0 -0
  9. package/assets/editor-extensions/typecad-ui/file-icon-light.png +0 -0
  10. package/assets/editor-extensions/typecad-ui/icon.png +0 -0
  11. package/assets/editor-extensions/typecad-ui/language-configuration.json +43 -0
  12. package/assets/editor-extensions/typecad-ui/package.json +54 -0
  13. package/assets/editor-extensions/typecad-ui/snippets/typecad-ui.json +80 -0
  14. package/assets/editor-extensions/typecad-ui/syntaxes/markdown-ui.json +45 -0
  15. package/assets/editor-extensions/typecad-ui/syntaxes/typecad-ui.tmLanguage.json +1269 -0
  16. package/dist/api/config.d.ts +30 -27
  17. package/dist/api/schema/types.d.ts +20 -3
  18. package/dist/api/shared/async-runtime-static.d.ts +1 -1
  19. package/dist/api/shared/async-runtime-static.js +5 -5
  20. package/dist/api/shared/async-types.d.ts +3 -2
  21. package/dist/api/shared/board-catalog.d.ts +2 -0
  22. package/dist/api/shared/board-catalog.js +6 -0
  23. package/dist/api/shared/board-resolver.d.ts +4 -7
  24. package/dist/api/shared/board-resolver.js +2 -1
  25. package/dist/api/shared/coop-scheduler.d.ts +1 -1
  26. package/dist/api/shared/coop-scheduler.js +1 -1
  27. package/dist/api/shared/cpp-type-ir.d.ts +1 -1
  28. package/dist/api/shared/cpp-type-ir.js +1 -1
  29. package/dist/api/shared/display-profile.d.ts +1 -1
  30. package/dist/api/shared/display-profile.js +3 -5
  31. package/dist/api/shared/framework-manifest-registry.d.ts +1 -1
  32. package/dist/api/shared/framework-manifest-registry.js +0 -1
  33. package/dist/api/shared/framework-manifest.d.ts +65 -507
  34. package/dist/api/shared/framework-manifest.js +6 -11
  35. package/dist/api/shared/hal-op-ir.d.ts +294 -685
  36. package/dist/api/shared/hal-op-ir.js +31 -65
  37. package/dist/api/shared/index.d.ts +0 -4
  38. package/dist/api/shared/index.js +1 -7
  39. package/dist/api/shared/ir-core.d.ts +6 -0
  40. package/dist/api/shared/ir-declarations.d.ts +4 -0
  41. package/dist/api/shared/ir.d.ts +1 -3
  42. package/dist/api/shared/platform-strategy.d.ts +14 -37
  43. package/dist/api/shared/polyfill-helper-registry.js +0 -5
  44. package/dist/api/shared/polyfill-types.js +0 -27
  45. package/dist/api/shared/promise-runtime.js +3 -3
  46. package/dist/api/shared/spdx-licenses.d.ts +12 -10
  47. package/dist/api/shared/spdx-licenses.js +1 -1
  48. package/dist/api/shared/toolchain-types.d.ts +1 -1
  49. package/dist/api/shared/toolchain-types.js +3 -3
  50. package/dist/api/shared/types.d.ts +0 -3
  51. package/dist/api/shared/validate-framework-manifest.js +13 -33
  52. package/dist/board-catalog/dts-reader.d.ts +220 -0
  53. package/dist/board-catalog/dts-reader.js +1052 -0
  54. package/dist/board-catalog/index.d.ts +11 -0
  55. package/dist/board-catalog/index.js +12 -0
  56. package/dist/board-catalog/pinconfig.d.ts +48 -0
  57. package/dist/board-catalog/pinconfig.js +263 -0
  58. package/dist/board-catalog/sdk.d.ts +82 -0
  59. package/dist/board-catalog/sdk.js +180 -0
  60. package/dist/board-catalog/store.d.ts +196 -0
  61. package/dist/board-catalog/store.js +363 -0
  62. package/dist/board-catalog/types.d.ts +233 -0
  63. package/dist/board-catalog/types.js +7 -0
  64. package/dist/board-catalog/walker.d.ts +112 -0
  65. package/dist/board-catalog/walker.js +1101 -0
  66. package/dist/cli-utils.d.ts +2 -2
  67. package/dist/cli-utils.js +5 -5
  68. package/dist/cli.js +227 -244
  69. package/dist/config-loader.d.ts +14 -19
  70. package/dist/config-loader.js +242 -78
  71. package/dist/config-schema.d.ts +19 -227
  72. package/dist/config-schema.js +9 -8
  73. package/dist/contract/board-generator.d.ts +4 -4
  74. package/dist/contract/board-generator.js +16 -5
  75. package/dist/contract/contract-parser.d.ts +36 -127
  76. package/dist/contract/contract-parser.js +76 -0
  77. package/dist/contract/index.d.ts +1 -1
  78. package/dist/contract/index.js +70 -21
  79. package/dist/create/active-board-catalog.d.ts +9 -0
  80. package/dist/create/active-board-catalog.js +94 -0
  81. package/dist/create/board-catalog.generated.d.ts +96 -0
  82. package/dist/create/board-catalog.generated.js +128737 -0
  83. package/dist/create/board-search.d.ts +23 -0
  84. package/dist/create/board-search.js +88 -0
  85. package/dist/create/editor-integration.d.ts +32 -0
  86. package/dist/create/editor-integration.js +257 -0
  87. package/dist/create/eslint-rules-template.d.ts +2 -2
  88. package/dist/create/framework-catalog.d.ts +48 -8
  89. package/dist/create/framework-catalog.js +58 -44
  90. package/dist/create/index.d.ts +8 -13
  91. package/dist/create/index.js +5 -9
  92. package/dist/create/mcu-target.d.ts +39 -0
  93. package/dist/create/mcu-target.js +80 -0
  94. package/dist/create/pack-targets.d.ts +19 -0
  95. package/dist/create/pack-targets.js +56 -0
  96. package/dist/create/{init-scaffold.d.ts → scaffold.d.ts} +8 -11
  97. package/dist/create/{init-scaffold.js → scaffold.js} +28 -87
  98. package/dist/create/templates.d.ts +51 -0
  99. package/dist/create/{init-templates.js → templates.js} +135 -116
  100. package/dist/create/wizard.d.ts +19 -0
  101. package/dist/create/wizard.js +314 -0
  102. package/dist/debug/preprocessor.d.ts +5 -0
  103. package/dist/debug/preprocessor.js +31 -7
  104. package/dist/diagnostics/diagnostics-report.d.ts +1 -1
  105. package/dist/diagnostics/diagnostics-report.js +3 -11
  106. package/dist/diagnostics/json-schema.d.ts +1 -1
  107. package/dist/diagnostics/md-writer.js +2 -2
  108. package/dist/diagnostics/mermaid-builder.d.ts +1 -1
  109. package/dist/diagnostics/mermaid-builder.js +1 -1
  110. package/dist/emit/cpp-emitter.js +4 -1
  111. package/dist/emit/emitters/class-emitter.js +32 -4
  112. package/dist/emit/emitters/emitter-context.d.ts +11 -0
  113. package/dist/emit/emitters/entrypoint-synthesizer.js +1 -1
  114. package/dist/emit/emitters/function-emitter-impl.js +33 -17
  115. package/dist/emit/emitters/output-finalizer.d.ts +7 -0
  116. package/dist/emit/emitters/output-finalizer.js +31 -23
  117. package/dist/emit/emitters/setup.js +147 -63
  118. package/dist/emit/emitters/top-level-prep.js +1 -1
  119. package/dist/emit/emitters/type-decl-emitter.js +13 -8
  120. package/dist/emit/emitters/ui-emitter.js +1 -1
  121. package/dist/emit/expression-renderer.d.ts +3 -3
  122. package/dist/emit/expression-renderer.js +17 -7
  123. package/dist/emit/route-hal-op.js +17 -48
  124. package/dist/emit/snprintf-helpers.d.ts +1 -3
  125. package/dist/emit/snprintf-helpers.js +1 -39
  126. package/dist/emit/statement-renderer.d.ts +0 -4
  127. package/dist/emit/statement-renderer.js +54 -45
  128. package/dist/emit/utils/async-state-machine.d.ts +16 -9
  129. package/dist/emit/utils/async-state-machine.js +56 -54
  130. package/dist/emit/utils/comment-helpers.d.ts +0 -8
  131. package/dist/emit/utils/comment-helpers.js +1 -1
  132. package/dist/emit/utils/cpp-helpers.d.ts +2 -2
  133. package/dist/emit/utils/cpp-helpers.js +2 -2
  134. package/dist/emit/utils/hal-op-cpp-type.js +4 -6
  135. package/dist/emit/utils/index.d.ts +3 -3
  136. package/dist/emit/utils/index.js +3 -3
  137. package/dist/emit/utils/type-inference.d.ts +1 -29
  138. package/dist/emit/utils/type-inference.js +0 -75
  139. package/dist/framework-package.d.ts +3 -0
  140. package/dist/framework-package.js +23 -6
  141. package/dist/framework-registry.d.ts +5 -5
  142. package/dist/frameworks/native/graphics/terminal-preview.d.ts +5 -0
  143. package/dist/frameworks/native/graphics/terminal-preview.js +33 -0
  144. package/dist/frameworks/native/index.d.ts +3 -0
  145. package/dist/frameworks/native/index.js +15 -0
  146. package/dist/frameworks/native/native-compile.d.ts +17 -0
  147. package/dist/frameworks/native/native-compile.js +170 -0
  148. package/dist/frameworks/native/native-config.d.ts +41 -0
  149. package/dist/frameworks/native/native-config.js +7 -0
  150. package/dist/frameworks/native/strategy.d.ts +97 -0
  151. package/dist/frameworks/native/strategy.js +664 -0
  152. package/dist/ir/board-resolver.d.ts +18 -23
  153. package/dist/ir/board-resolver.js +43 -401
  154. package/dist/ir/build-ir-state.d.ts +3 -0
  155. package/dist/ir/build-ir-state.js +42 -0
  156. package/dist/ir/build-ir.d.ts +1 -1
  157. package/dist/ir/build-ir.js +64 -45
  158. package/dist/ir/declaration-builders.js +1 -0
  159. package/dist/ir/expression-to-ir.js +17 -10
  160. package/dist/ir/hal/hal-emitter.d.ts +0 -2
  161. package/dist/ir/hal/hal-emitter.js +92 -41
  162. package/dist/ir/hal/hal-parser.d.ts +5 -5
  163. package/dist/ir/hal/hal-parser.js +128 -36
  164. package/dist/ir/hal/hal-plugins.d.ts +0 -1
  165. package/dist/ir/hal/hal-plugins.js +425 -716
  166. package/dist/ir/heap-analysis.js +2 -41
  167. package/dist/ir/identifier-collector.js +32 -20
  168. package/dist/ir/network-validation.js +7 -11
  169. package/dist/ir/ownership-analysis.js +75 -13
  170. package/dist/ir/peripheral-usage.d.ts +8 -2
  171. package/dist/ir/peripheral-usage.js +78 -149
  172. package/dist/ir/peripheral-validation.js +23 -3
  173. package/dist/ir/pin-capability-validation.d.ts +12 -0
  174. package/dist/ir/pin-capability-validation.js +61 -97
  175. package/dist/ir/pin-mode-validation.js +5 -5
  176. package/dist/ir/program-analysis.d.ts +8 -15
  177. package/dist/ir/program-analysis.js +140 -323
  178. package/dist/ir/pulldown-validation.js +11 -4
  179. package/dist/ir/resource-analysis.js +15 -3
  180. package/dist/ir/statement-to-ir.js +0 -6
  181. package/dist/ir/timing-validation.js +1 -1
  182. package/dist/ir/transformers/array-methods.js +11 -5
  183. package/dist/ir/transformers/call-statement.js +20 -87
  184. package/dist/ir/transformers/callback-context-registry.d.ts +1 -1
  185. package/dist/ir/transformers/callback-context-registry.js +8 -16
  186. package/dist/ir/transformers/control-flow.js +0 -13
  187. package/dist/ir/transformers/expressions.js +10 -9
  188. package/dist/ir/transformers/hal-call-resolver.d.ts +2 -2
  189. package/dist/ir/transformers/hal-call-resolver.js +24 -10
  190. package/dist/ir/transformers/hal-emit-helpers.d.ts +2 -2
  191. package/dist/ir/transformers/hal-emit-helpers.js +2 -2
  192. package/dist/ir/transformers/namespace-methods.js +1 -1
  193. package/dist/ir/transformers/ui-callback-lowering.d.ts +0 -2
  194. package/dist/ir/transformers/ui-callback-lowering.js +0 -24
  195. package/dist/ir/transformers/variables.js +338 -42
  196. package/dist/ir/try-catch-validation.js +4 -3
  197. package/dist/ir/type-resolution.js +15 -4
  198. package/dist/ir/validation-orchestrator.js +0 -9
  199. package/dist/libdef/cpp-to-decl.d.ts +0 -9
  200. package/dist/libdef/cpp-to-decl.js +0 -72
  201. package/dist/libdef/registry.d.ts +0 -1
  202. package/dist/libdef/registry.js +1 -24
  203. package/dist/library/catalog.d.ts +35 -0
  204. package/dist/library/catalog.js +67 -0
  205. package/dist/library/cli.d.ts +2 -0
  206. package/dist/library/cli.js +168 -0
  207. package/dist/library/init.d.ts +25 -0
  208. package/dist/library/init.js +397 -0
  209. package/dist/library/install.d.ts +9 -0
  210. package/dist/library/install.js +80 -0
  211. package/dist/library/registry-search.d.ts +34 -0
  212. package/dist/library/registry-search.js +50 -0
  213. package/dist/library/validate.d.ts +17 -0
  214. package/dist/library/validate.js +175 -0
  215. package/dist/library-packages.d.ts +95 -0
  216. package/dist/library-packages.js +275 -0
  217. package/dist/mapping/peripheral-names.js +9 -4
  218. package/dist/mapping/source-map.d.ts +3 -4
  219. package/dist/mapping/source-map.js +12 -18
  220. package/dist/orchestrator/graph-builder.d.ts +3 -3
  221. package/dist/orchestrator/graph-builder.js +29 -12
  222. package/dist/orchestrator/type-checker.d.ts +3 -3
  223. package/dist/orchestrator/type-checker.js +3 -3
  224. package/dist/platform/async-runtime.js +1 -1
  225. package/dist/platform/coop-scheduler-runtime.js +2 -2
  226. package/dist/platform/generic-debug-codegen.d.ts +36 -0
  227. package/dist/platform/generic-debug-codegen.js +185 -0
  228. package/dist/platform/generic-strategy.d.ts +3 -4
  229. package/dist/platform/generic-strategy.js +5 -80
  230. package/dist/platform/index.js +1 -1
  231. package/dist/platform/registry.d.ts +2 -2
  232. package/dist/platform/registry.js +2 -2
  233. package/dist/preview/client.js +17 -3
  234. package/dist/safety/asil-decorators.d.ts +32 -0
  235. package/dist/safety/asil-decorators.js +32 -0
  236. package/dist/safety/authoring.d.ts +85 -0
  237. package/dist/safety/authoring.js +61 -0
  238. package/dist/safety/engine.d.ts +3 -0
  239. package/dist/safety/engine.js +83 -0
  240. package/dist/safety/hal/ops.d.ts +48 -0
  241. package/dist/safety/hal/ops.js +46 -0
  242. package/dist/safety/iso26262/analyze.d.ts +13 -0
  243. package/dist/safety/iso26262/analyze.js +29 -0
  244. package/dist/safety/iso26262/asil.d.ts +10 -0
  245. package/dist/safety/iso26262/asil.js +22 -0
  246. package/dist/safety/iso26262/collect.d.ts +14 -0
  247. package/dist/safety/iso26262/collect.js +137 -0
  248. package/dist/safety/iso26262/goto-checker.d.ts +10 -0
  249. package/dist/safety/iso26262/goto-checker.js +72 -0
  250. package/dist/safety/iso26262/heap-checker.d.ts +7 -0
  251. package/dist/safety/iso26262/heap-checker.js +57 -0
  252. package/dist/safety/iso26262/init-checker.d.ts +13 -0
  253. package/dist/safety/iso26262/init-checker.js +127 -0
  254. package/dist/safety/iso26262/loop-checker.d.ts +7 -0
  255. package/dist/safety/iso26262/loop-checker.js +86 -0
  256. package/dist/safety/iso26262/recursion-checker.d.ts +9 -0
  257. package/dist/safety/iso26262/recursion-checker.js +134 -0
  258. package/dist/safety/iso26262/sidecar-writer.d.ts +25 -0
  259. package/dist/safety/iso26262/sidecar-writer.js +13 -0
  260. package/dist/safety/passes/pinMode-intercept.d.ts +3 -0
  261. package/dist/safety/passes/pinMode-intercept.js +60 -0
  262. package/dist/safety/runtime/mode-table.d.ts +5 -0
  263. package/dist/safety/runtime/mode-table.js +55 -0
  264. package/dist/safety/runtime/polyfills.d.ts +6 -0
  265. package/dist/safety/runtime/polyfills.js +12 -0
  266. package/dist/safety/runtime/result-struct.d.ts +11 -0
  267. package/dist/safety/runtime/result-struct.js +98 -0
  268. package/dist/safety/runtime/safe-int.d.ts +33 -0
  269. package/dist/safety/runtime/safe-int.js +170 -0
  270. package/dist/safety/runtime/safe-traits.d.ts +4 -0
  271. package/dist/safety/runtime/safe-traits.js +95 -0
  272. package/dist/safety/runtime/safe-variable.d.ts +39 -0
  273. package/dist/safety/runtime/safe-variable.js +226 -0
  274. package/dist/safety/runtime/vote.d.ts +8 -0
  275. package/dist/safety/runtime/vote.js +92 -0
  276. package/dist/safety/runtime/write-verify.d.ts +8 -0
  277. package/dist/safety/runtime/write-verify.js +71 -0
  278. package/dist/safety/safe-int-types.d.ts +45 -0
  279. package/dist/safety/safe-int-types.js +25 -0
  280. package/dist/safety/safe-variable-types.d.ts +29 -0
  281. package/dist/safety/safe-variable-types.js +19 -0
  282. package/dist/safety/safety-bridge.d.ts +5 -6
  283. package/dist/safety/safety-bridge.js +15 -28
  284. package/dist/safety/sidecar-bridge.d.ts +1 -3
  285. package/dist/safety/sidecar-bridge.js +3 -20
  286. package/dist/safety/specifiers.d.ts +6 -0
  287. package/dist/safety/specifiers.js +14 -0
  288. package/dist/safety-hook.d.ts +8 -7
  289. package/dist/safety-hook.js +12 -13
  290. package/dist/testing.d.ts +5 -6
  291. package/dist/testing.js +5 -5
  292. package/dist/transpile/resolution.d.ts +1 -1
  293. package/dist/transpile/resolution.js +18 -9
  294. package/dist/transpile/test-pins.d.ts +18 -0
  295. package/dist/transpile/test-pins.js +142 -0
  296. package/dist/transpile.d.ts +1 -2
  297. package/dist/transpile.js +90 -29
  298. package/dist/types.d.ts +45 -26
  299. package/dist/ui-hook.d.ts +1 -1
  300. package/dist/utils/cli.d.ts +2 -2
  301. package/dist/utils/cli.js +160 -157
  302. package/dist/utils/fs.d.ts +3 -4
  303. package/dist/utils/fs.js +4 -5
  304. package/dist/utils/strings.d.ts +0 -1
  305. package/dist/utils/strings.js +0 -8
  306. package/dist/utils/ui.d.ts +5 -2
  307. package/dist/utils/ui.js +13 -3
  308. package/package.json +158 -149
  309. package/dist/add-preset.d.ts +0 -4
  310. package/dist/add-preset.js +0 -74
  311. package/dist/api/shared/async-symbol-detector.d.ts +0 -11
  312. package/dist/api/shared/async-symbol-detector.js +0 -140
  313. package/dist/api/shared/native-display-op-resolver.d.ts +0 -10
  314. package/dist/api/shared/native-display-op-resolver.js +0 -64
  315. package/dist/create/board-checklist.d.ts +0 -2
  316. package/dist/create/board-checklist.js +0 -52
  317. package/dist/create/board-codegen.d.ts +0 -9
  318. package/dist/create/board-codegen.js +0 -238
  319. package/dist/create/board-generators.d.ts +0 -12
  320. package/dist/create/board-generators.js +0 -651
  321. package/dist/create/board-spec.d.ts +0 -637
  322. package/dist/create/board-spec.js +0 -214
  323. package/dist/create/init-templates.d.ts +0 -28
  324. package/dist/create/init-wizard.d.ts +0 -8
  325. package/dist/create/init-wizard.js +0 -182
  326. package/dist/install/framework-catalog.d.ts +0 -53
  327. package/dist/install/framework-catalog.js +0 -107
  328. package/dist/install/handle-install.d.ts +0 -35
  329. package/dist/install/handle-install.js +0 -177
  330. package/dist/install/index.d.ts +0 -4
  331. package/dist/install/index.js +0 -3
  332. package/dist/ir/pin-state-tracking.d.ts +0 -58
  333. package/dist/ir/pin-state-tracking.js +0 -182
  334. package/dist/ir/pwm-timer-sharing.d.ts +0 -4
  335. package/dist/ir/pwm-timer-sharing.js +0 -94
  336. package/dist/ir/timer0-pwm-timing-conflict.d.ts +0 -4
  337. package/dist/ir/timer0-pwm-timing-conflict.js +0 -72
  338. package/dist/libdef/component-decls.d.ts +0 -2
  339. package/dist/libdef/component-decls.js +0 -6
  340. package/dist/libdef/component-discovery.d.ts +0 -43
  341. package/dist/libdef/component-discovery.js +0 -83
  342. package/dist/theme-tokens.d.ts +0 -22
  343. package/dist/theme-tokens.js +0 -172
@@ -0,0 +1,226 @@
1
+ import { emitSafeTraits } from "./safe-traits.js";
2
+ /** SafeVariable polyfill: 3-replica TMR with per-replica inversion for
3
+ * integral types, and plain 3-copy TMR for float/double.
4
+ *
5
+ * Combines TMR (triple modular redundancy) with inverted-redundancy for
6
+ * integral types: three replicas of the value, each stored alongside its
7
+ * bitwise inverse. On read, each replica is individually validated (XOR
8
+ * check), then the valid replicas are majority-voted. This gives both
9
+ * detection AND correction:
10
+ *
11
+ * - A single-bit SEU in any replica's value or inverse breaks that
12
+ * replica's XOR invariant → the corrupted replica is excluded from
13
+ * the vote, and the good replicas correct it.
14
+ * - If two replicas agree (majority), the value is returned with
15
+ * confidence. The corrupted replica is silently repaired on the next
16
+ * set().
17
+ * - For float/double, replicas are stored as plain copies (no inversion
18
+ * possible), and majority vote still corrects single-replica corruption.
19
+ *
20
+ * Fault signaling: hasFault() returns true iff the last get() found ZERO
21
+ * valid replicas (triple corruption). Callers should check hasFault() after
22
+ * get() on safety-critical paths. set() clears the fault flag.
23
+ *
24
+ * Memory cost: 3× T (same as plain TMR). The inversion is per-replica and
25
+ * does not add copies beyond the three TMR replicas.
26
+ *
27
+ * Arithmetic T only — a static_assert rejects non-arithmetic types (notably
28
+ * std::string) and bool (for which bitwise inversion is ill-defined) at
29
+ * compile time. float and double have explicit specializations.
30
+ *
31
+ * AUTOSAR C++14 compliance:
32
+ * - noexcept on all methods (A15-0-2)
33
+ * - [[nodiscard]] on get/valid/hasFault (A0-1-1)
34
+ * - constexpr constructors/methods
35
+ * - no malloc/new (A18-5-8/A18-5-10)
36
+ * - no C-style casts (M5-0-7)
37
+ * - fixed-width types via template parameter (A3-9-1)
38
+ */
39
+ export function safeVariablePolyfill() {
40
+ return {
41
+ kind: "polyfill",
42
+ id: "safety_safe_variable",
43
+ domain: "embedded",
44
+ requiredIncludes: [],
45
+ forwardDeclarations: [],
46
+ helperStructs: [],
47
+ helperFunctions: [`
48
+ ${emitSafeTraits()}
49
+
50
+ #ifndef __TC_SAFE_VARIABLE_DEFINED
51
+ #define __TC_SAFE_VARIABLE_DEFINED
52
+
53
+ // ── SafeVariable: integer types (bitwise XOR validation per replica) ──
54
+ // Each replica stores value + ~value. On read, each replica is validated
55
+ // independently. Valid replicas are majority-voted; the corrupted one
56
+ // (if any) is excluded. This provides both detection AND correction.
57
+ template <typename T>
58
+ struct SafeVariable {
59
+ // Arithmetic T only. bool is rejected explicitly because ~bool and ^bool
60
+ // undergo integer promotion and do not behave as a 1-bit inversion.
61
+ // float/double are handled by the explicit specializations below.
62
+ static_assert(__tc_safe_traits::is_integral<T>::value && !__tc_safe_traits::is_same<T, bool>::value,
63
+ "SafeVariable<T> requires an integral T (use float/double specializations for those; "
64
+ "std::string and bool are not supported)");
65
+
66
+ private:
67
+ T replicaA_val;
68
+ T replicaA_inv;
69
+ T replicaB_val;
70
+ T replicaB_inv;
71
+ T replicaC_val;
72
+ T replicaC_inv;
73
+ // mutable: get() is logically const (it does not change the stored value)
74
+ // but caches the "last read saw triple corruption" fault flag so callers
75
+ // can inspect it via hasFault() after get().
76
+ mutable bool fault_;
77
+ template <typename U> friend struct SafeVariable;
78
+
79
+ static bool replicaValid(T val, T inv) noexcept {
80
+ return (val ^ inv) == static_cast<T>(~static_cast<T>(0));
81
+ }
82
+
83
+ public:
84
+ SafeVariable() noexcept
85
+ : replicaA_val(0), replicaA_inv(static_cast<T>(~static_cast<T>(0))),
86
+ replicaB_val(0), replicaB_inv(static_cast<T>(~static_cast<T>(0))),
87
+ replicaC_val(0), replicaC_inv(static_cast<T>(~static_cast<T>(0))),
88
+ fault_(false) {}
89
+
90
+ SafeVariable(T initial) noexcept
91
+ : replicaA_val(initial), replicaA_inv(static_cast<T>(~initial)),
92
+ replicaB_val(initial), replicaB_inv(static_cast<T>(~initial)),
93
+ replicaC_val(initial), replicaC_inv(static_cast<T>(~initial)),
94
+ fault_(false) {}
95
+
96
+ template <typename U>
97
+ SafeVariable(const SafeVariable<U>& other) noexcept
98
+ : replicaA_val(static_cast<T>(other.replicaA_val)), replicaA_inv(static_cast<T>(other.replicaA_inv)),
99
+ replicaB_val(static_cast<T>(other.replicaB_val)), replicaB_inv(static_cast<T>(other.replicaB_inv)),
100
+ replicaC_val(static_cast<T>(other.replicaC_val)), replicaC_inv(static_cast<T>(other.replicaC_inv)),
101
+ fault_(other.fault_) {}
102
+
103
+ // Majority vote: returns the agreed-upon value from valid replicas.
104
+ // If a replica is corrupted (XOR check fails), it is excluded from
105
+ // the vote. If two or more valid replicas agree, return that value.
106
+ // If only one replica is valid, return it as a best-effort fallback.
107
+ // If NO replica is valid (triple corruption), returns replicaC_val as a
108
+ // last resort and sets the fault flag — callers must check hasFault().
109
+ [[nodiscard]] T get() const noexcept {
110
+ const bool aValid = replicaValid(replicaA_val, replicaA_inv);
111
+ const bool bValid = replicaValid(replicaB_val, replicaB_inv);
112
+ const bool cValid = replicaValid(replicaC_val, replicaC_inv);
113
+
114
+ // Two valid replicas agree → majority.
115
+ if (aValid && bValid && (replicaA_val == replicaB_val)) { fault_ = false; return replicaA_val; }
116
+ if (aValid && cValid && (replicaA_val == replicaC_val)) { fault_ = false; return replicaA_val; }
117
+ if (bValid && cValid && (replicaB_val == replicaC_val)) { fault_ = false; return replicaB_val; }
118
+
119
+ // Only one valid replica → return it (no majority but best available).
120
+ if (aValid) { fault_ = false; return replicaA_val; }
121
+ if (bValid) { fault_ = false; return replicaB_val; }
122
+ if (cValid) { fault_ = false; return replicaC_val; }
123
+
124
+ // Zero valid replicas → triple corruption. Flag the fault and return
125
+ // replicaC_val as a degenerate fallback; callers MUST check hasFault().
126
+ fault_ = true;
127
+ return replicaC_val;
128
+ }
129
+
130
+ // Returns true if all three replicas pass their XOR checks AND agree.
131
+ // Does not mutate the fault flag (it reflects the last get(), not valid()).
132
+ [[nodiscard]] bool valid() const noexcept {
133
+ return replicaValid(replicaA_val, replicaA_inv)
134
+ && replicaValid(replicaB_val, replicaB_inv)
135
+ && replicaValid(replicaC_val, replicaC_inv)
136
+ && (replicaA_val == replicaB_val)
137
+ && (replicaB_val == replicaC_val);
138
+ }
139
+
140
+ // Returns true iff the most recent get() found zero valid replicas
141
+ // (triple corruption). Cleared by set() and by a subsequent get() that
142
+ // finds at least one valid replica.
143
+ [[nodiscard]] bool hasFault() const noexcept { return fault_; }
144
+
145
+ void set(T newValue) noexcept {
146
+ const T inv = static_cast<T>(~newValue);
147
+ replicaA_val = newValue; replicaA_inv = inv;
148
+ replicaB_val = newValue; replicaB_inv = inv;
149
+ replicaC_val = newValue; replicaC_inv = inv;
150
+ fault_ = false;
151
+ }
152
+ };
153
+
154
+ // ── SafeVariable: float (3-replica majority vote, no inversion) ──
155
+ // Floats can't use bitwise XOR/inversion. Three identical copies are
156
+ // stored and majority-voted. A single corrupted copy is outvoted and
157
+ // silently repaired on the next set().
158
+ template <>
159
+ struct SafeVariable<float> {
160
+ private:
161
+ float replicaA;
162
+ float replicaB;
163
+ float replicaC;
164
+ mutable bool fault_;
165
+ template <typename U> friend struct SafeVariable;
166
+ public:
167
+ SafeVariable() noexcept : replicaA(0.0f), replicaB(0.0f), replicaC(0.0f), fault_(false) {}
168
+ SafeVariable(float initial) noexcept : replicaA(initial), replicaB(initial), replicaC(initial), fault_(false) {}
169
+ [[nodiscard]] float get() const noexcept {
170
+ if (replicaA == replicaB) { fault_ = false; return replicaA; }
171
+ if (replicaA == replicaC) { fault_ = false; return replicaA; }
172
+ if (replicaB == replicaC) { fault_ = false; return replicaB; }
173
+ // No two replicas agree — triple corruption.
174
+ fault_ = true;
175
+ return replicaC;
176
+ }
177
+ [[nodiscard]] bool valid() const noexcept {
178
+ return (replicaA == replicaB) && (replicaB == replicaC);
179
+ }
180
+ [[nodiscard]] bool hasFault() const noexcept { return fault_; }
181
+ void set(float newValue) noexcept {
182
+ replicaA = newValue;
183
+ replicaB = newValue;
184
+ replicaC = newValue;
185
+ fault_ = false;
186
+ }
187
+ };
188
+
189
+ // ── SafeVariable: double (3-replica majority vote, no inversion) ──
190
+ template <>
191
+ struct SafeVariable<double> {
192
+ private:
193
+ double replicaA;
194
+ double replicaB;
195
+ double replicaC;
196
+ mutable bool fault_;
197
+ template <typename U> friend struct SafeVariable;
198
+ public:
199
+ SafeVariable() noexcept : replicaA(0.0), replicaB(0.0), replicaC(0.0), fault_(false) {}
200
+ SafeVariable(double initial) noexcept : replicaA(initial), replicaB(initial), replicaC(initial), fault_(false) {}
201
+ [[nodiscard]] double get() const noexcept {
202
+ if (replicaA == replicaB) { fault_ = false; return replicaA; }
203
+ if (replicaA == replicaC) { fault_ = false; return replicaA; }
204
+ if (replicaB == replicaC) { fault_ = false; return replicaB; }
205
+ // No two replicas agree — triple corruption.
206
+ fault_ = true;
207
+ return replicaC;
208
+ }
209
+ [[nodiscard]] bool valid() const noexcept {
210
+ return (replicaA == replicaB) && (replicaB == replicaC);
211
+ }
212
+ [[nodiscard]] bool hasFault() const noexcept { return fault_; }
213
+ void set(double newValue) noexcept {
214
+ replicaA = newValue;
215
+ replicaB = newValue;
216
+ replicaC = newValue;
217
+ fault_ = false;
218
+ }
219
+ };
220
+
221
+ #endif // __TC_SAFE_VARIABLE_DEFINED
222
+ `.trim()],
223
+ shimMacros: [],
224
+ dependencies: [],
225
+ };
226
+ }
@@ -0,0 +1,8 @@
1
+ import type { RuntimePolyfillIR } from "../../api/index.js";
2
+ /** The 2-of-3 voter. Tree-shaken out unless __tc_safety_read_safe appears
3
+ * in the program (registered in POLYFILL_HELPER_MAP).
4
+ *
5
+ * MCU-agnosticism: the voter reads via the strategy-injected __tc_gpio_read
6
+ * shim (defined per-target by each framework strategy's shimLines()). The
7
+ * safety package references zero target-specific symbols. */
8
+ export declare function voterPolyfill(): RuntimePolyfillIR;
@@ -0,0 +1,92 @@
1
+ /** The 2-of-3 voter. Tree-shaken out unless __tc_safety_read_safe appears
2
+ * in the program (registered in POLYFILL_HELPER_MAP).
3
+ *
4
+ * MCU-agnosticism: the voter reads via the strategy-injected __tc_gpio_read
5
+ * shim (defined per-target by each framework strategy's shimLines()). The
6
+ * safety package references zero target-specific symbols. */
7
+ export function voterPolyfill() {
8
+ return {
9
+ kind: "polyfill",
10
+ id: "safety_read_safe",
11
+ domain: "embedded",
12
+ requiredIncludes: [],
13
+ forwardDeclarations: [],
14
+ helperStructs: [],
15
+ helperFunctions: [`
16
+ // Forward declarations — the strategy's shimLines() defines these AFTER the
17
+ // polyfill block (polyfills emit before shims in emitPreamble). Without the
18
+ // forward decls, the voter's __tc_gpio_read / __tc_delay_us calls below would
19
+ // be unresolved.
20
+ int __tc_gpio_read(uint32_t pin);
21
+ void __tc_delay_us(uint32_t us);
22
+
23
+ namespace __tc_safety {
24
+
25
+ // Settle delay between temporally-separated reads. ~2 us is enough to defeat
26
+ // single-event transient (SET) glitches on a typical GPIO line while staying
27
+ // well under a debounce timescale. Tunable in one place.
28
+ constexpr uint32_t TC_SAFETY_SETTLE_US = 2U;
29
+
30
+ // Perform 3 temporally-separated reads via the strategy-injected shim, take
31
+ // the majority. On disagreement, VoteDisagreement. On pin-mode mismatch,
32
+ // PinModeMismatch. On untracked pin, PinModeUnknown. value is left 0 when
33
+ // ok==false — callers must check 'ok' before consuming 'value'.
34
+ inline SafeReadResult read_safe(uint32_t pin) {
35
+ SafeReadResult result;
36
+ result.value = 0x00000000U;
37
+ result.category = SafetyFaultCategory::Ok;
38
+ result.code = SafetyFaultCode::Ok;
39
+ result.status = SafetyStatus::Ok;
40
+
41
+ // 1. Confirm pin mode (Input, InputPullup, or InputPulldown are valid for
42
+ // reading). Output is rejected (PinModeMismatch). InputPulldown is
43
+ // accepted because it is a legitimate input mode on ESP32 (and AVR via
44
+ // external pulldown); rejecting it caused false faults.
45
+ const TrackedMode mode = get_pin_mode(pin);
46
+ if (mode == TrackedMode::Unknown) {
47
+ result.category = SafetyFaultCategory::Configuration;
48
+ result.code = SafetyFaultCode::PinModeUnknown;
49
+ result.status = SafetyStatus::Fault;
50
+ return result;
51
+ }
52
+ if ((mode != TrackedMode::Input) && (mode != TrackedMode::InputPullup) && (mode != TrackedMode::InputPulldown)) {
53
+ result.category = SafetyFaultCategory::Configuration;
54
+ result.code = SafetyFaultCode::PinModeMismatch;
55
+ result.status = SafetyStatus::Fault;
56
+ return result;
57
+ }
58
+
59
+ // 2. 2-of-3 vote via the strategy-injected __tc_gpio_read shim.
60
+ // __tc_delay_us provides temporal separation between reads so a single
61
+ // input glitch is unlikely to corrupt two samples; the strategy injects a
62
+ // real microsecond delay (Arduino/ESP32: delayMicroseconds; AVR:
63
+ // _native_delay_us; native: stub).
64
+ const uint32_t r0 = __tc_gpio_read(pin);
65
+ __tc_delay_us(TC_SAFETY_SETTLE_US);
66
+ const uint32_t r1 = __tc_gpio_read(pin);
67
+ __tc_delay_us(TC_SAFETY_SETTLE_US);
68
+ const uint32_t r2 = __tc_gpio_read(pin);
69
+
70
+ if ((r0 == r1) && (r1 == r2)) {
71
+ result.status = SafetyStatus::Ok;
72
+ result.value = r0 ? 0xFFFFFFFFU : 0x00000000U;
73
+ } else {
74
+ result.category = SafetyFaultCategory::Signal;
75
+ result.code = SafetyFaultCode::VoteDisagreement;
76
+ result.status = SafetyStatus::Fault;
77
+ }
78
+ return result;
79
+ }
80
+
81
+ // Namespace-scoped forwarding entry point — kept inside the namespace so
82
+ // the emitter's forward-declaration pass does not generate a global prototype
83
+ // that references SafeReadResult before the struct is defined.
84
+ inline SafeReadResult __tc_safety_read_safe(uint32_t pin) {
85
+ return read_safe(pin);
86
+ }
87
+
88
+ } // namespace __tc_safety`.trim()],
89
+ shimMacros: [],
90
+ dependencies: ["safety_mode_table"],
91
+ };
92
+ }
@@ -0,0 +1,8 @@
1
+ import type { RuntimePolyfillIR } from "../../api/index.js";
2
+ /** Write-then-readback verification. Tree-shaken out unless
3
+ * __tc_safety_write_verify appears in the program (registered in
4
+ * POLYFILL_HELPER_MAP).
5
+ *
6
+ * MCU-agnosticism: writes via the strategy-injected __tc_gpio_write shim,
7
+ * reads back via __tc_gpio_read — references zero target-specific symbols. */
8
+ export declare function writeVerifyPolyfill(): RuntimePolyfillIR;
@@ -0,0 +1,71 @@
1
+ /** Write-then-readback verification. Tree-shaken out unless
2
+ * __tc_safety_write_verify appears in the program (registered in
3
+ * POLYFILL_HELPER_MAP).
4
+ *
5
+ * MCU-agnosticism: writes via the strategy-injected __tc_gpio_write shim,
6
+ * reads back via __tc_gpio_read — references zero target-specific symbols. */
7
+ export function writeVerifyPolyfill() {
8
+ return {
9
+ kind: "polyfill",
10
+ id: "safety_write_verify",
11
+ domain: "embedded",
12
+ requiredIncludes: [],
13
+ forwardDeclarations: [],
14
+ helperStructs: [],
15
+ helperFunctions: [`
16
+ // Forward declaration — the strategy's shimLines() defines this AFTER the
17
+ // polyfill block (polyfills emit before shims in emitPreamble).
18
+ void __tc_gpio_write(uint32_t pin, uint32_t value);
19
+ int __tc_gpio_read(uint32_t pin);
20
+
21
+ namespace __tc_safety {
22
+
23
+ inline SafeWriteResult write_verify(uint32_t pin, uint32_t value) {
24
+ SafeWriteResult result;
25
+ result.code = SafetyFaultCode::Ok;
26
+ result.status = SafetyStatus::Ok;
27
+
28
+ const TrackedMode mode = get_pin_mode(pin);
29
+ if (mode == TrackedMode::Unknown) {
30
+ result.code = SafetyFaultCode::PinModeUnknown;
31
+ result.status = SafetyStatus::Fault;
32
+ return result;
33
+ }
34
+ if (mode != TrackedMode::Output) {
35
+ result.code = SafetyFaultCode::PinModeMismatch;
36
+ result.status = SafetyStatus::Fault;
37
+ return result;
38
+ }
39
+
40
+ __tc_gpio_write(pin, (value != 0U) ? 0x1U : 0x0U);
41
+
42
+ // Read back the pin to verify the write took effect. On AVR/ESP32
43
+ // Arduino core, digitalRead on an OUTPUT pin returns the last value
44
+ // written to the PORT register, so this check catches software bugs
45
+ // (wrong pin, wrong mode) but not electrical faults (shorted pin,
46
+ // disconnected wire). True electrical verification requires external
47
+ // circuitry routing the output back to a separate input pin.
48
+ const int rd = __tc_gpio_read(pin);
49
+ const uint32_t readback = rd ? 0xFFFFFFFFU : 0x00000000U;
50
+ const uint32_t expected = (value != 0U) ? 0xFFFFFFFFU : 0x00000000U;
51
+
52
+ if (readback == expected) {
53
+ result.status = SafetyStatus::Ok;
54
+ result.code = SafetyFaultCode::Ok;
55
+ } else {
56
+ result.status = SafetyStatus::Fault;
57
+ result.code = SafetyFaultCode::WriteMismatch;
58
+ }
59
+ return result;
60
+ }
61
+
62
+ } // namespace __tc_safety
63
+
64
+ inline SafeWriteResult __tc_safety_write_verify(uint32_t pin, uint32_t value) {
65
+ return __tc_safety::write_verify(pin, value);
66
+ }
67
+ `.trim()],
68
+ shimMacros: [],
69
+ dependencies: ["safety_mode_table"],
70
+ };
71
+ }
@@ -0,0 +1,45 @@
1
+ /** SafeInt<T> — chainable bounds-checked signed-integer arithmetic.
2
+ *
3
+ * The cuttlefish transpiler resolves SafeInt<number> to the C++ template
4
+ * form SafeInt<int32_t> (and SafeInt<int8_t>/<int16_t>/<int64_t> for the
5
+ * corresponding TS fixed-width aliases), and the safety polyfill provides
6
+ * the template definition.
7
+ *
8
+ * Signed integer T only. The emitted C++ template carries a static_assert
9
+ * that rejects unsigned integers, bool, floating-point, and non-integer
10
+ * types (notably string) at compile time.
11
+ *
12
+ * Mutating chain: every math operation returns the same SafeInt<T> (by
13
+ * reference) so calls chain: `x.add(5).mul(2).get()`. On overflow or
14
+ * division error, a sticky fault flag is set and subsequent operations in
15
+ * the chain become no-ops; get() returns the last good value. Check
16
+ * hasFault() (or valid()) after a chain on safety-critical paths.
17
+ *
18
+ * Usage:
19
+ * let x: SafeInt<int32_t> = SafeInt(10);
20
+ * x.add(5).mul(2); // mutating chain — x is now 30
21
+ * if (x.valid()) {
22
+ * const v: int32_t = x.get();
23
+ * }
24
+ */
25
+ export interface SafeInt<T = number> {
26
+ add(delta: T): SafeInt<T>;
27
+ sub(delta: T): SafeInt<T>;
28
+ mul(factor: T): SafeInt<T>;
29
+ divide(d: T): SafeInt<T>;
30
+ mod(d: T): SafeInt<T>;
31
+ negate(): SafeInt<T>;
32
+ absValue(): SafeInt<T>;
33
+ get(): T;
34
+ /** True iff a prior operation in this chain overflowed or hit a division
35
+ * error. Sticky — once set, stays set until reset(). While true, all
36
+ * further math operations are no-ops and get() returns the last good
37
+ * value. */
38
+ hasFault(): boolean;
39
+ /** !hasFault(). Symmetric with SafeVariable.valid(). */
40
+ valid(): boolean;
41
+ /** Clear the fault flag and set a new value. The only way to re-arm a
42
+ * faulted SafeInt without reconstructing it. */
43
+ reset(newValue: T): void;
44
+ }
45
+ export declare function SafeInt<T>(initial: T): SafeInt<T>;
@@ -0,0 +1,25 @@
1
+ /** SafeInt<T> — chainable bounds-checked signed-integer arithmetic.
2
+ *
3
+ * The cuttlefish transpiler resolves SafeInt<number> to the C++ template
4
+ * form SafeInt<int32_t> (and SafeInt<int8_t>/<int16_t>/<int64_t> for the
5
+ * corresponding TS fixed-width aliases), and the safety polyfill provides
6
+ * the template definition.
7
+ *
8
+ * Signed integer T only. The emitted C++ template carries a static_assert
9
+ * that rejects unsigned integers, bool, floating-point, and non-integer
10
+ * types (notably string) at compile time.
11
+ *
12
+ * Mutating chain: every math operation returns the same SafeInt<T> (by
13
+ * reference) so calls chain: `x.add(5).mul(2).get()`. On overflow or
14
+ * division error, a sticky fault flag is set and subsequent operations in
15
+ * the chain become no-ops; get() returns the last good value. Check
16
+ * hasFault() (or valid()) after a chain on safety-critical paths.
17
+ *
18
+ * Usage:
19
+ * let x: SafeInt<int32_t> = SafeInt(10);
20
+ * x.add(5).mul(2); // mutating chain — x is now 30
21
+ * if (x.valid()) {
22
+ * const v: int32_t = x.get();
23
+ * }
24
+ */
25
+ export {};
@@ -0,0 +1,29 @@
1
+ /** SafeVariable<T> — SEU-resistant storage with inverted-redundancy.
2
+ *
3
+ * The cuttlefish transpiler resolves SafeVariable<number> to the C++
4
+ * template form SafeVariable<int> (or int32_t under --autosar), and the
5
+ * safety polyfill provides the template definition.
6
+ *
7
+ * Arithmetic T only. The emitted C++ template carries a static_assert that
8
+ * rejects non-arithmetic types (notably string) and bool at compile time.
9
+ * float/double have explicit specializations (3-copy plain TMR — bitwise
10
+ * inversion is not defined for floating-point).
11
+ *
12
+ * Usage:
13
+ * let x: SafeVariable<number> = SafeVariable(0);
14
+ * x.set(2000);
15
+ * const current = x.get(); // best-effort value
16
+ * if (x.hasFault()) { ... } // triple corruption — get() is untrusted
17
+ * if (x.valid()) { ... } // all three replicas agree and pass XOR checks
18
+ */
19
+ export interface SafeVariable<T = number> {
20
+ set(value: T): void;
21
+ get(): T;
22
+ valid(): boolean;
23
+ /** True iff the most recent get() found zero valid replicas (triple
24
+ * corruption). Cleared by set() and by a subsequent get() that finds at
25
+ * least one valid replica. Check this after get() on safety-critical
26
+ * paths; a true return means the returned value is untrusted. */
27
+ hasFault(): boolean;
28
+ }
29
+ export declare function SafeVariable(initial: number): SafeVariable<any>;
@@ -0,0 +1,19 @@
1
+ /** SafeVariable<T> — SEU-resistant storage with inverted-redundancy.
2
+ *
3
+ * The cuttlefish transpiler resolves SafeVariable<number> to the C++
4
+ * template form SafeVariable<int> (or int32_t under --autosar), and the
5
+ * safety polyfill provides the template definition.
6
+ *
7
+ * Arithmetic T only. The emitted C++ template carries a static_assert that
8
+ * rejects non-arithmetic types (notably string) and bool at compile time.
9
+ * float/double have explicit specializations (3-copy plain TMR — bitwise
10
+ * inversion is not defined for floating-point).
11
+ *
12
+ * Usage:
13
+ * let x: SafeVariable<number> = SafeVariable(0);
14
+ * x.set(2000);
15
+ * const current = x.get(); // best-effort value
16
+ * if (x.hasFault()) { ... } // triple corruption — get() is untrusted
17
+ * if (x.valid()) { ... } // all three replicas agree and pass XOR checks
18
+ */
19
+ export {};
@@ -1,11 +1,10 @@
1
- /** Dynamically load @typecad/safety/engine and register the hook.
2
- * Called by transpile.ts at the start of each transpile run.
3
- * Safe to call when @typecad/safety is absent (hook stays null). */
1
+ /** Load the safety engine and register the hook. Called by transpile.ts at
2
+ * the start of each transpile run. */
4
3
  export declare function loadSafetyEngine(): Promise<void>;
5
4
  /** Reset the safety bridge: forget a load was attempted and clear the hook.
6
5
  * Mirrors resetUIEngine() so each transpile run / test starts clean. */
7
6
  export declare function resetSafetyEngine(): void;
8
- /** Test-only: force the bridge into the "no @typecad/safety" state — mark the
9
- * load as already attempted and leave the hook null, exactly as if the
10
- * dynamic import had failed because the package is not installed. */
7
+ /** Test-only: force the bridge into the "safety not loaded" state — mark the
8
+ * load as already attempted and leave the hook null, exactly as the old
9
+ * dynamic import behaved when @typecad/safety was not installed. */
11
10
  export declare function __simulateSafetyAbsentForTest(): void;
@@ -1,37 +1,24 @@
1
1
  // ---------------------------------------------------------------------------
2
- // Safety bridge — loads the safety engine from @typecad/safety and registers it.
2
+ // Safety bridge — registers the built-in safety engine.
3
3
  //
4
- // transpile.ts calls loadSafetyEngine() at the start of transpileFile(). If
5
- // @typecad/safety is not installed, the import fails gracefully and the hook
6
- // stays null cuttlefish works as a pure TS→C++ transpiler with no safety
7
- // support.
4
+ // The engine used to ship as the optional @typecad/safety package and was
5
+ // loaded via a dynamic package import; it now lives in this package under
6
+ // src/safety/. transpile.ts still calls loadSafetyEngine() at the start of
7
+ // transpileFile(), and the hook seam (safety-hook.ts) is unchanged so the
8
+ // degradation paths (resetSafetyEngine / __simulateSafetyAbsentForTest) keep
9
+ // working for tests.
8
10
  // ---------------------------------------------------------------------------
9
11
  import { setSafetyHook } from "../safety-hook.js";
10
12
  let loaded = false;
11
- /** Dynamically load @typecad/safety/engine and register the hook.
12
- * Called by transpile.ts at the start of each transpile run.
13
- * Safe to call when @typecad/safety is absent (hook stays null). */
13
+ /** Load the safety engine and register the hook. Called by transpile.ts at
14
+ * the start of each transpile run. */
14
15
  export async function loadSafetyEngine() {
15
16
  if (loaded)
16
17
  return;
17
18
  loaded = true;
18
- try {
19
- // Dynamic import — @typecad/safety is optional. The module specifier is
20
- // routed through a variable (rather than a string literal) so tsc types
21
- // the result as `any` and never resolves @typecad/safety's declaration
22
- // files while type-checking this file. A literal specifier would make tsc
23
- // load safety's dist/engine-index.d.ts, which imports back
24
- // @typecad/cuttlefish/safety-hook-types — a self-referencing package path
25
- // that resolves into this package's own dist/ output and causes TS5055
26
- // ("would overwrite input file") on every rebuild where dist/ exists.
27
- const safetyEnginePath = "@typecad/safety/engine";
28
- const engine = await import(safetyEnginePath);
29
- const hook = engine.registerSafetyEngine();
30
- setSafetyHook(hook);
31
- }
32
- catch {
33
- // @typecad/safety is not installed — cuttlefish works without safety.
34
- }
19
+ const engine = await import("./engine.js");
20
+ const hook = engine.registerSafetyEngine();
21
+ setSafetyHook(hook);
35
22
  }
36
23
  /** Reset the safety bridge: forget a load was attempted and clear the hook.
37
24
  * Mirrors resetUIEngine() so each transpile run / test starts clean. */
@@ -39,9 +26,9 @@ export function resetSafetyEngine() {
39
26
  loaded = false;
40
27
  setSafetyHook(null);
41
28
  }
42
- /** Test-only: force the bridge into the "no @typecad/safety" state — mark the
43
- * load as already attempted and leave the hook null, exactly as if the
44
- * dynamic import had failed because the package is not installed. */
29
+ /** Test-only: force the bridge into the "safety not loaded" state — mark the
30
+ * load as already attempted and leave the hook null, exactly as the old
31
+ * dynamic import behaved when @typecad/safety was not installed. */
45
32
  export function __simulateSafetyAbsentForTest() {
46
33
  loaded = true;
47
34
  setSafetyHook(null);
@@ -1,5 +1,3 @@
1
1
  import type { SafetyMetadata } from "../safety-hook.js";
2
- /** Dynamically import the safety package's sidecar renderer.
3
- * Uses a variable-held specifier so tsc doesn't try to resolve the
4
- * @typecad/safety types at build time (avoids circular dependency). */
2
+ /** Render the safety sidecar artifact via the built-in ISO 26262 writer. */
5
3
  export declare function renderSafetySidecar(metadata: SafetyMetadata, toolVersion: string): Promise<string>;
@@ -1,22 +1,5 @@
1
- /** Dynamically import the safety package's sidecar renderer.
2
- * Uses a variable-held specifier so tsc doesn't try to resolve the
3
- * @typecad/safety types at build time (avoids circular dependency). */
1
+ import { renderSafetySidecar as renderSidecar } from "./iso26262/sidecar-writer.js";
2
+ /** Render the safety sidecar artifact via the built-in ISO 26262 writer. */
4
3
  export async function renderSafetySidecar(metadata, toolVersion) {
5
- const spec = "@typecad/safety/iso26262/sidecar-writer";
6
- try {
7
- const mod = await import(spec);
8
- return mod.renderSafetySidecar(metadata, toolVersion);
9
- }
10
- catch {
11
- // Fallback: inline the renderer so the sidecar is produced even if
12
- // the subpath export isn't configured.
13
- return JSON.stringify({
14
- schemaVersion: "1.0.0",
15
- standard: "ISO 26262 Part 6",
16
- tool: "cuttlefish (@typecad/safety)",
17
- toolVersion,
18
- generatedAt: new Date().toISOString(),
19
- safetyFunctions: metadata.functions,
20
- }, null, 2);
21
- }
4
+ return renderSidecar(metadata, toolVersion);
22
5
  }
@@ -0,0 +1,6 @@
1
+ /** The canonical specifier for the safety authoring surface. */
2
+ export declare const SAFETY_SPECIFIER = "@typecad/cuttlefish/safety";
3
+ /** The legacy specifier from when safety was a standalone package. */
4
+ export declare const LEGACY_SAFETY_SPECIFIER = "@typecad/safety";
5
+ /** True iff an import specifier refers to the safety authoring surface. */
6
+ export declare function isSafetyImportSpecifier(moduleSpecifier: string): boolean;