@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,32 @@
1
+ export {};
2
+ /** ASIL level annotations for functions — comment-based.
3
+ *
4
+ * ASIL levels are declared via leading comment annotations rather than
5
+ * TypeScript decorators because:
6
+ * - TS decorators on function declarations produce TS1206 errors in the
7
+ * VS Code language server and @typescript-eslint/parser
8
+ * - Comment annotations work in any editor, any toolchain, without
9
+ * `experimentalDecorators` or special config
10
+ *
11
+ * The cuttlefish IR builder extracts these from leading comments via
12
+ * extractAsilFromComments() in function-builder.ts.
13
+ *
14
+ * Part B's ISO 26262 checkers (analyzeIR) read the resulting `decorators`
15
+ * field on FunctionIR to decide which rules to enforce:
16
+ *
17
+ * // @asilD → all rules enforced (recursion, heap, loops)
18
+ * // @asilC → recursion + loops enforced (heap is ASIL D only)
19
+ * // @asilB → recursion enforced
20
+ * // @asilA → no rules enforced (quality-managed)
21
+ * (no annotation) → no rules enforced (implicit QM)
22
+ *
23
+ * Usage:
24
+ * // @asilD
25
+ * function engageBrake(): void {
26
+ * safe.write(brakePin, 1);
27
+ * }
28
+ *
29
+ * These are documentation-only exports — they have no runtime behavior
30
+ * and are never imported by user code. They exist so the ASIL level
31
+ * names appear in type hints and IDE autocomplete.
32
+ */
@@ -0,0 +1,85 @@
1
+ export type { SafeVariable } from "./safe-variable-types.js";
2
+ export type { SafeInt } from "./safe-int-types.js";
3
+ import type { Pin } from "@typecad/hal";
4
+ /** The pin argument safe.read accepts — a thin-HAL `GPIO`. A named alias so
5
+ * the safety API's stringified type stays free of union syntax at call sites.
6
+ * At runtime the safety package resolves the same `_pin: number` field via
7
+ * the halInstances registry at IR time. */
8
+ export type AnyPin = Pin;
9
+ /** Two-tier fault taxonomy. Stable across safety standards (ISO 26262,
10
+ * IEC 61508, DO-178C). The category is the coarse user-space routing axis;
11
+ * the code is standard-specific detail.
12
+ *
13
+ * Declared as TypeScript `enum` (not `const` object + type alias) so the
14
+ * cuttlefish transpiler lowers these to a single C++ `enum class` definition
15
+ * matching the runtime polyfill's enum, rather than emitting a conflicting
16
+ * struct per usage scope. The transpiler's enum lowering and the polyfill's
17
+ * enum class are structurally identical (same tag name, same enumerators,
18
+ * same values). */
19
+ export declare enum SafetyFaultCategory {
20
+ Ok = 1010580540,
21
+ Signal = 1515870810,
22
+ Integrity = 2779096485,
23
+ Timing = 3284386755,
24
+ System = 1437226410,
25
+ Configuration = 2857740885
26
+ }
27
+ export declare enum SafetyFaultCode {
28
+ Ok = 1010580540,
29
+ VoteDisagreement = 1515870810,
30
+ StuckHigh = 2779096485,
31
+ StuckLow = 3284386755,
32
+ PinModeMismatch = 1437226410,
33
+ PinModeUnknown = 2857740885,
34
+ WriteMismatch = 1012573635
35
+ }
36
+ export declare enum SafetyStatus {
37
+ Ok = 1515870810,
38
+ Fault = 2779096485
39
+ }
40
+ export interface SafeReadResult {
41
+ readonly status: SafetyStatus;
42
+ readonly value: number;
43
+ readonly category: SafetyFaultCategory;
44
+ readonly code: SafetyFaultCode;
45
+ /** Run handler iff status === Ok. Handler receives the full result. Returns the result (chainable). */
46
+ ok(handler: (r: SafeReadResult) => void): SafeReadResult;
47
+ /** Run handler iff status !== Ok. Handler receives the full result. Returns the result (chainable). */
48
+ fail(handler: (r: SafeReadResult) => void): SafeReadResult;
49
+ /** Alias of fail(). */
50
+ fault(handler: (r: SafeReadResult) => void): SafeReadResult;
51
+ /** Run handler unconditionally. Returns the result (chainable). */
52
+ always(handler: (r: SafeReadResult) => void): SafeReadResult;
53
+ }
54
+ export interface SafeWriteResult {
55
+ readonly status: SafetyStatus;
56
+ readonly code: SafetyFaultCode;
57
+ ok(handler: (r: SafeWriteResult) => void): SafeWriteResult;
58
+ fail(handler: (r: SafeWriteResult) => void): SafeWriteResult;
59
+ fault(handler: (r: SafeWriteResult) => void): SafeWriteResult;
60
+ always(handler: (r: SafeWriteResult) => void): SafeWriteResult;
61
+ }
62
+ /** Safe GPIO API. Compile-time construct only — the cuttlefish transpiler
63
+ * intercepts safe.read and lowers it to a safety.read_safe HAL op. The
64
+ * type annotation (rather than `as const`) gives `safe` a single object
65
+ * type so member access doesn't lower to std::variant access — same reason
66
+ * @typecad/ui's `ui` uses an explicit type annotation. */
67
+ export declare const safe: {
68
+ /** Safe digital read: confirms the pin's recorded mode is INPUT or
69
+ * INPUT_PULLUP (via the auto-populated mode table), performs a 2-of-3
70
+ * vote via the strategy-injected __tc_gpio_read shim, returns a
71
+ * SafeReadResult carrying any detected fault.
72
+ *
73
+ * Accepts any thin-HAL GPIO regardless of its constructed flag set. The
74
+ * runtime mode-table check (driven by the GPIO's construction flags)
75
+ * rejects pins configured as OUTPUT (returns PinModeMismatch). */
76
+ read(pin: AnyPin): SafeReadResult;
77
+ /** Safe digital write with readback verification. Writes the value,
78
+ * immediately reads the physical pin state back, and returns a
79
+ * SafeWriteResult confirming the write succeeded or flagging a fault.
80
+ *
81
+ * Verifies the pin's recorded mode is OUTPUT (returns PinModeMismatch
82
+ * for non-output pins). On write/read mismatch, returns
83
+ * WriteMismatch. */
84
+ write(pin: Pin, value: number): SafeWriteResult;
85
+ };
@@ -0,0 +1,61 @@
1
+ // Public API surface for cuttlefish safety — importable as
2
+ // '@typecad/cuttlefish/safety' (the legacy '@typecad/safety' specifier is
3
+ // still detected by the transpiler; detection is by name, no module
4
+ // resolution happens).
5
+ //
6
+ // `safe` is a COMPILE-TIME CONSTRUCT ONLY. The cuttlefish transpiler
7
+ // intercepts safe.read calls (via tryResolveSemanticCall → the safety hook's
8
+ // resolveSemanticCall) and lowers them to safety.read_safe HAL ops. The
9
+ // runtime stub below throws so importing `safe` from plain Node never
10
+ // silently works — mirrors how @typecad/ui's ui.mount behaves.
11
+ //
12
+ // Part A v2: mode configuration belongs to @typecad/hal (Pin.asInput() etc.).
13
+ // The safety engine owns only the verified read.
14
+ /** Two-tier fault taxonomy. Stable across safety standards (ISO 26262,
15
+ * IEC 61508, DO-178C). The category is the coarse user-space routing axis;
16
+ * the code is standard-specific detail.
17
+ *
18
+ * Declared as TypeScript `enum` (not `const` object + type alias) so the
19
+ * cuttlefish transpiler lowers these to a single C++ `enum class` definition
20
+ * matching the runtime polyfill's enum, rather than emitting a conflicting
21
+ * struct per usage scope. The transpiler's enum lowering and the polyfill's
22
+ * enum class are structurally identical (same tag name, same enumerators,
23
+ * same values). */
24
+ export var SafetyFaultCategory;
25
+ (function (SafetyFaultCategory) {
26
+ SafetyFaultCategory[SafetyFaultCategory["Ok"] = 1010580540] = "Ok";
27
+ SafetyFaultCategory[SafetyFaultCategory["Signal"] = 1515870810] = "Signal";
28
+ SafetyFaultCategory[SafetyFaultCategory["Integrity"] = 2779096485] = "Integrity";
29
+ SafetyFaultCategory[SafetyFaultCategory["Timing"] = 3284386755] = "Timing";
30
+ SafetyFaultCategory[SafetyFaultCategory["System"] = 1437226410] = "System";
31
+ SafetyFaultCategory[SafetyFaultCategory["Configuration"] = 2857740885] = "Configuration";
32
+ })(SafetyFaultCategory || (SafetyFaultCategory = {}));
33
+ export var SafetyFaultCode;
34
+ (function (SafetyFaultCode) {
35
+ SafetyFaultCode[SafetyFaultCode["Ok"] = 1010580540] = "Ok";
36
+ SafetyFaultCode[SafetyFaultCode["VoteDisagreement"] = 1515870810] = "VoteDisagreement";
37
+ SafetyFaultCode[SafetyFaultCode["StuckHigh"] = 2779096485] = "StuckHigh";
38
+ SafetyFaultCode[SafetyFaultCode["StuckLow"] = 3284386755] = "StuckLow";
39
+ SafetyFaultCode[SafetyFaultCode["PinModeMismatch"] = 1437226410] = "PinModeMismatch";
40
+ SafetyFaultCode[SafetyFaultCode["PinModeUnknown"] = 2857740885] = "PinModeUnknown";
41
+ SafetyFaultCode[SafetyFaultCode["WriteMismatch"] = 1012573635] = "WriteMismatch";
42
+ })(SafetyFaultCode || (SafetyFaultCode = {}));
43
+ export var SafetyStatus;
44
+ (function (SafetyStatus) {
45
+ SafetyStatus[SafetyStatus["Ok"] = 1515870810] = "Ok";
46
+ SafetyStatus[SafetyStatus["Fault"] = 2779096485] = "Fault";
47
+ })(SafetyStatus || (SafetyStatus = {}));
48
+ class CompileTimeOnly extends Error {
49
+ constructor() {
50
+ super("cuttlefish safety: `safe` is a compile-time construct. It is lowered by the cuttlefish transpiler and has no runtime implementation.");
51
+ }
52
+ }
53
+ /** Safe GPIO API. Compile-time construct only — the cuttlefish transpiler
54
+ * intercepts safe.read and lowers it to a safety.read_safe HAL op. The
55
+ * type annotation (rather than `as const`) gives `safe` a single object
56
+ * type so member access doesn't lower to std::variant access — same reason
57
+ * @typecad/ui's `ui` uses an explicit type annotation. */
58
+ export const safe = {
59
+ read(_pin) { throw new CompileTimeOnly(); },
60
+ write(_pin, _value) { throw new CompileTimeOnly(); },
61
+ };
@@ -0,0 +1,3 @@
1
+ import type { TranspilerSafetyHook } from "../safety-hook.js";
2
+ export declare function registerSafetyEngine(): TranspilerSafetyHook;
3
+ export type { TranspilerSafetyHook };
@@ -0,0 +1,83 @@
1
+ import { pinModeInterceptPass } from "./passes/pinMode-intercept.js";
2
+ import { buildSafetyPolyfills } from "./runtime/polyfills.js";
3
+ import { halInstances } from "../ir/build-ir-state.js";
4
+ import { analyzeProgram } from "./iso26262/analyze.js";
5
+ import { collectSafetyMetadata } from "./iso26262/collect.js";
6
+ /** Resolve a safety.* HAL op to C++. MCU-agnostic: emits calls only to the
7
+ * safety package's own __tc_safety_* helpers (never to target-specific
8
+ * symbols like digitalRead). The strategy-injected __tc_gpio_read shim is
9
+ * called from inside the voter polyfill, not from here.
10
+ *
11
+ * `op.operation` is a closed union in cuttlefish's HALOpIR that does NOT
12
+ * include safety.* ops (those are owned by this package). The dispatch in
13
+ * routeHALOp() uses string-prefix matching, so by the time we get here the
14
+ * operation is a safety.* string — cast to `string` so the switch is an
15
+ * open comparison. Field access goes through a generic record view because
16
+ * the safety op shapes are not part of the HALOpIR union. */
17
+ function resolveSafetyOp(op) {
18
+ const operation = op.operation;
19
+ const fields = op;
20
+ switch (operation) {
21
+ case "safety.record_pin_mode":
22
+ // mode is a TrackedMode enum value (numeric) — emitted as-is.
23
+ return { code: `__tc_safety_record_pin_mode(${fields.pin}, ${fields.mode});` };
24
+ case "safety.read_safe":
25
+ return { expression: `__tc_safety::read_safe(${fields.pin})` };
26
+ case "safety.write_verify":
27
+ return { expression: `__tc_safety::write_verify(${fields.pin}, ${fields.value})` };
28
+ default:
29
+ return undefined;
30
+ }
31
+ }
32
+ /** Resolve a Pin-instance argument to its pin number at IR time, using the
33
+ * same halInstances registry the HAL layer uses to resolve `this._pin`
34
+ * inside Pin method bodies. Returns undefined for args that aren't tracked
35
+ * Pin instances (the caller emits a diagnostic in that case). Also accepts
36
+ * literal numbers as a fallback (for code that constructs a Pin inline at
37
+ * the call site, e.g. safe.read(Pin.fromPort('PD2')) — though the idiomatic
38
+ * form is to assign the Pin to a local first). */
39
+ function resolvePinArg(arg) {
40
+ if (typeof arg === "number")
41
+ return arg;
42
+ if (typeof arg === "string") {
43
+ // Identifier — look up in halInstances for a Pin instance with _pin.
44
+ const inst = halInstances.get(arg);
45
+ if (inst) {
46
+ const pin = inst.fieldValues.get("_pin") ?? inst.fieldValues.get("pin");
47
+ if (pin !== undefined)
48
+ return Number(pin);
49
+ }
50
+ }
51
+ return undefined;
52
+ }
53
+ /** Lower a safe.* TS call to a HAL op. Called from tryResolveSemanticCall
54
+ * (hal-plugins.ts) when the callee resolves to the @typecad/safety package. */
55
+ function resolveSemanticCall(callee, args) {
56
+ // `safe.read(Pin)` → safety.read_safe (pin resolved at IR time)
57
+ if (callee === "safe.read") {
58
+ const pin = resolvePinArg(args[0]);
59
+ if (pin === undefined)
60
+ return undefined;
61
+ return { operation: "safety.read_safe", pin };
62
+ }
63
+ // `safe.write(OutputPin, value)` → safety.write_verify
64
+ // value may be a number (literal) or string (rendered C++ expression text)
65
+ if (callee === "safe.write") {
66
+ const pin = resolvePinArg(args[0]);
67
+ if (pin === undefined)
68
+ return undefined;
69
+ const value = args[1] ?? 0;
70
+ return { operation: "safety.write_verify", pin, value };
71
+ }
72
+ return undefined;
73
+ }
74
+ export function registerSafetyEngine() {
75
+ return {
76
+ transformIR: pinModeInterceptPass,
77
+ resolveSafetyOp,
78
+ resolveSemanticCall,
79
+ buildPolyfills: buildSafetyPolyfills,
80
+ analyzeIR: analyzeProgram,
81
+ collectSafetyMetadata,
82
+ };
83
+ }
@@ -0,0 +1,48 @@
1
+ /** 5-value pin mode, mapped from gpio.configure's flag tokens at IR time.
2
+ * Numeric so the voter switches on enum values (no strcmp at runtime). The
3
+ * values are 32-bit Hamming-distance constants (0x5A5A5A5A etc.) chosen for
4
+ * SEU resistance — a single-bit flip never lands on another valid mode.
5
+ * This makes the C++ mode table 4 bytes/pin (~1 KB for the 255-entry table
6
+ * on AVR, which has 2 KB SRAM). That is a deliberate trade-off vs 1-byte
7
+ * storage: the SEU resistance is the whole point of the safety package.
8
+ * Matches the C++ enum class TrackedMode in runtime/mode-table.ts. */
9
+ export declare enum TrackedMode {
10
+ Unknown = 0,
11
+ Input = 1515870810,
12
+ Output = 2779096485,
13
+ InputPullup = 1010580540,
14
+ InputPulldown = 3284386755
15
+ }
16
+ /** Map gpio.configure flag-token text ("GPIO.INPUT | GPIO.PULL_UP", the
17
+ * thin GPIO constructor's resolved flags) to the TrackedMode enum. Used by
18
+ * the intercept pass at IR time. Direction wins over pulls; combos with no
19
+ * tracked equivalent (open-drain, runtime expressions) map to Unknown so
20
+ * the table still gets a fresh entry. */
21
+ export declare function mapFlagTokens(flags: string): TrackedMode;
22
+ /** Companion op injected after every gpio.set_mode by the pinMode-intercept
23
+ * pass. Records the mode in the runtime safety mode table. */
24
+ export interface SafetyRecordPinModeOp {
25
+ operation: "safety.record_pin_mode";
26
+ pin: number;
27
+ /** TrackedMode enum value (numeric) — mapped at IR time from the
28
+ * gpio.set_mode op's mode string. */
29
+ mode: TrackedMode;
30
+ }
31
+ /** Op produced by `safe.read(Pin)`. Resolves to a C++ expression returning
32
+ * a SafeReadResult. The pin number is resolved at IR time from the Pin
33
+ * instance via the halInstances registry. */
34
+ export interface SafetyReadSafeOp {
35
+ operation: "safety.read_safe";
36
+ pin: number;
37
+ }
38
+ /** Op produced by `safe.write(OutputPin, value)`. Resolves to a C++ expression
39
+ * returning a SafeWriteResult. The pin number is resolved at IR time from the
40
+ * Pin instance via the halInstances registry. The value may be a numeric
41
+ * literal or a string containing the rendered C++ expression text (e.g.
42
+ * "r.value", "x + 1"). */
43
+ export interface SafetyWriteVerifyOp {
44
+ operation: "safety.write_verify";
45
+ pin: number;
46
+ value: number | string;
47
+ }
48
+ export type SafetyHALOp = SafetyRecordPinModeOp | SafetyReadSafeOp | SafetyWriteVerifyOp;
@@ -0,0 +1,46 @@
1
+ // Safety HAL op definitions. These are dispatched by their `operation` string
2
+ // prefix ("safety.*") via routeHALOp() in cuttlefish core. The strategy layer
3
+ // NEVER resolves them — they are resolved by the safety package's
4
+ // resolveSafetyOp, which is MCU-agnostic (it emits calls only to the safety
5
+ // package's own __tc_safety_* helpers and the strategy-injected
6
+ // __tc_gpio_read shim — never to target-specific symbols like digitalRead).
7
+ /** 5-value pin mode, mapped from gpio.configure's flag tokens at IR time.
8
+ * Numeric so the voter switches on enum values (no strcmp at runtime). The
9
+ * values are 32-bit Hamming-distance constants (0x5A5A5A5A etc.) chosen for
10
+ * SEU resistance — a single-bit flip never lands on another valid mode.
11
+ * This makes the C++ mode table 4 bytes/pin (~1 KB for the 255-entry table
12
+ * on AVR, which has 2 KB SRAM). That is a deliberate trade-off vs 1-byte
13
+ * storage: the SEU resistance is the whole point of the safety package.
14
+ * Matches the C++ enum class TrackedMode in runtime/mode-table.ts. */
15
+ export var TrackedMode;
16
+ (function (TrackedMode) {
17
+ TrackedMode[TrackedMode["Unknown"] = 0] = "Unknown";
18
+ TrackedMode[TrackedMode["Input"] = 1515870810] = "Input";
19
+ TrackedMode[TrackedMode["Output"] = 2779096485] = "Output";
20
+ TrackedMode[TrackedMode["InputPullup"] = 1010580540] = "InputPullup";
21
+ TrackedMode[TrackedMode["InputPulldown"] = 3284386755] = "InputPulldown";
22
+ })(TrackedMode || (TrackedMode = {}));
23
+ /** Map gpio.configure flag-token text ("GPIO.INPUT | GPIO.PULL_UP", the
24
+ * thin GPIO constructor's resolved flags) to the TrackedMode enum. Used by
25
+ * the intercept pass at IR time. Direction wins over pulls; combos with no
26
+ * tracked equivalent (open-drain, runtime expressions) map to Unknown so
27
+ * the table still gets a fresh entry. */
28
+ export function mapFlagTokens(flags) {
29
+ // Only a pure token list ("GPIO.INPUT | GPIO.PULL_UP") is statically
30
+ // classifiable — anything else (runtime expression) is Unknown.
31
+ if (!/^\s*GPIO\.[A-Z0-9_]+(\s*\|\s*GPIO\.[A-Z0-9_]+)*\s*$/.test(flags)) {
32
+ return TrackedMode.Unknown;
33
+ }
34
+ const output = flags.includes("GPIO.OUTPUT");
35
+ const input = flags.includes("GPIO.INPUT");
36
+ if (output && !input)
37
+ return TrackedMode.Output;
38
+ if (input || output) {
39
+ if (flags.includes("GPIO.PULL_UP"))
40
+ return TrackedMode.InputPullup;
41
+ if (flags.includes("GPIO.PULL_DOWN"))
42
+ return TrackedMode.InputPulldown;
43
+ return TrackedMode.Input;
44
+ }
45
+ return TrackedMode.Unknown;
46
+ }
@@ -0,0 +1,13 @@
1
+ import type { ProgramIR, Diagnostic } from "../../api/index.js";
2
+ import type { SafetyTransformContext } from "../../safety-hook.js";
3
+ /** Part B: ISO 26262 Part 6 software-rule checker.
4
+ *
5
+ * Runs all checkers against the final transformed IR and returns aggregated
6
+ * diagnostics. Each checker is independent — a failure in one does not
7
+ * prevent the others from running.
8
+ *
9
+ * Diagnostics with severity "error" abort the build (via
10
+ * throwIfFatalDiagnostics in transpile.ts); "warning"/"info" are logged
11
+ * but the build succeeds.
12
+ */
13
+ export declare function analyzeProgram(program: ProgramIR, ctx: SafetyTransformContext): Diagnostic[];
@@ -0,0 +1,29 @@
1
+ import { checkRecursion } from "./recursion-checker.js";
2
+ import { checkDynamicAllocation } from "./heap-checker.js";
3
+ import { checkUnboundedLoops } from "./loop-checker.js";
4
+ import { checkInitCompleteness } from "./init-checker.js";
5
+ import { checkGoto } from "./goto-checker.js";
6
+ /** Part B: ISO 26262 Part 6 software-rule checker.
7
+ *
8
+ * Runs all checkers against the final transformed IR and returns aggregated
9
+ * diagnostics. Each checker is independent — a failure in one does not
10
+ * prevent the others from running.
11
+ *
12
+ * Diagnostics with severity "error" abort the build (via
13
+ * throwIfFatalDiagnostics in transpile.ts); "warning"/"info" are logged
14
+ * but the build succeeds.
15
+ */
16
+ export function analyzeProgram(program, ctx) {
17
+ const diags = [];
18
+ for (const checker of [checkRecursion, checkDynamicAllocation, checkUnboundedLoops, checkInitCompleteness, checkGoto]) {
19
+ try {
20
+ const results = checker(program, ctx);
21
+ diags.push(...results);
22
+ }
23
+ catch {
24
+ // A checker crash should not prevent other checkers from running.
25
+ // The diagnostic is lost; the build continues.
26
+ }
27
+ }
28
+ return diags;
29
+ }
@@ -0,0 +1,10 @@
1
+ /** Determine the ASIL level of a function from its decorators.
2
+ * Returns a numeric severity: D=4, C=3, B=2, A=1, QM/none=0.
3
+ * Higher = more rules enforced. */
4
+ export declare function asilLevel(decorators?: string[]): number;
5
+ /** Minimum ASIL level at which each rule applies. */
6
+ export declare const ASIL_THRESHOLDS: {
7
+ readonly recursion: 2;
8
+ readonly dynamicAlloc: 4;
9
+ readonly unboundedLoop: 3;
10
+ };
@@ -0,0 +1,22 @@
1
+ /** Determine the ASIL level of a function from its decorators.
2
+ * Returns a numeric severity: D=4, C=3, B=2, A=1, QM/none=0.
3
+ * Higher = more rules enforced. */
4
+ export function asilLevel(decorators) {
5
+ if (!decorators)
6
+ return 0;
7
+ if (decorators.includes("asilD"))
8
+ return 4;
9
+ if (decorators.includes("asilC"))
10
+ return 3;
11
+ if (decorators.includes("asilB"))
12
+ return 2;
13
+ if (decorators.includes("asilA"))
14
+ return 1;
15
+ return 0;
16
+ }
17
+ /** Minimum ASIL level at which each rule applies. */
18
+ export const ASIL_THRESHOLDS = {
19
+ recursion: 2, // B+ — recursion forbidden
20
+ dynamicAlloc: 4, // D only — heap forbidden after init
21
+ unboundedLoop: 3, // C+ — unbounded loops warned
22
+ };
@@ -0,0 +1,14 @@
1
+ import type { ProgramIR } from "../../api/index.js";
2
+ import type { SafetyTransformContext, SafetyMetadata } from "../../safety-hook.js";
3
+ /** Part C: collect safety metadata for sidecar artifact generation.
4
+ *
5
+ * Walks the program IR and collects structured metadata about each
6
+ * safety-critical function (those with ASIL annotations):
7
+ * - ASIL level (from // @asilD / @asilC / @asilB comments)
8
+ * - Source location (TS file + line)
9
+ * - Safety mechanisms used (safe.read, safe.write, SafeVariable, SafeInt)
10
+ * - Rule check results (B1–B6 pass/warning/error)
11
+ *
12
+ * The caller writes the returned metadata as a sidecar JSON file
13
+ * alongside the emitted C++ artifact. */
14
+ export declare function collectSafetyMetadata(program: ProgramIR, ctx: SafetyTransformContext): SafetyMetadata[];
@@ -0,0 +1,137 @@
1
+ import { asilLevel } from "./asil.js";
2
+ import { analyzeProgram } from "./analyze.js";
3
+ /** Part C: collect safety metadata for sidecar artifact generation.
4
+ *
5
+ * Walks the program IR and collects structured metadata about each
6
+ * safety-critical function (those with ASIL annotations):
7
+ * - ASIL level (from // @asilD / @asilC / @asilB comments)
8
+ * - Source location (TS file + line)
9
+ * - Safety mechanisms used (safe.read, safe.write, SafeVariable, SafeInt)
10
+ * - Rule check results (B1–B6 pass/warning/error)
11
+ *
12
+ * The caller writes the returned metadata as a sidecar JSON file
13
+ * alongside the emitted C++ artifact. */
14
+ export function collectSafetyMetadata(program, ctx) {
15
+ const functions = [];
16
+ // Run the analyzers to get current rule results per function
17
+ const diagnostics = analyzeProgram(program, ctx);
18
+ const diagsByFunction = new Map();
19
+ for (const d of diagnostics) {
20
+ // Extract function name from the message (format: "Recursion detected: ..."
21
+ // or "Dynamic allocation in fnName(): ...")
22
+ const fnMatch = d.message.match(/in (\w+)\(\)/);
23
+ const fnName = fnMatch ? fnMatch[1] : "";
24
+ if (fnName) {
25
+ if (!diagsByFunction.has(fnName)) {
26
+ diagsByFunction.set(fnName, []);
27
+ }
28
+ diagsByFunction.get(fnName).push(d);
29
+ }
30
+ }
31
+ const allRuleIds = ["B1_RECURSION", "B2_DYNAMIC_ALLOC", "B3_UNBOUNDED_LOOP", "B5_INIT_COMPLETENESS", "B6_GOTO"];
32
+ for (const fn of program.functions) {
33
+ const level = asilLevel(fn.decorators);
34
+ if (level === 0)
35
+ continue;
36
+ const asilName = level === 4 ? "D" : level === 3 ? "C" : level === 2 ? "B" : level === 1 ? "A" : "QM";
37
+ // Detect safety mechanisms used in this function
38
+ const mechanisms = detectMechanisms(fn);
39
+ // Build rule results: pass by default, override with diagnostics
40
+ const rules = {};
41
+ for (const ruleId of allRuleIds) {
42
+ const fullCode = `ISO26262_${ruleId}`;
43
+ const matchingDiags = (diagsByFunction.get(fn.originalName) ?? [])
44
+ .filter(d => d.code === fullCode);
45
+ if (matchingDiags.length > 0) {
46
+ // Use the first matching diagnostic (they're all the same rule)
47
+ rules[ruleId] = {
48
+ severity: matchingDiags[0].severity,
49
+ message: matchingDiags[0].message,
50
+ };
51
+ }
52
+ else {
53
+ rules[ruleId] = "pass";
54
+ }
55
+ }
56
+ functions.push({
57
+ name: fn.originalName,
58
+ asilLevel: asilName,
59
+ source: fn.sourceSpan ? {
60
+ tsFile: fn.sourceSpan.filePath,
61
+ tsLine: fn.sourceSpan.startLine,
62
+ } : undefined,
63
+ mechanisms,
64
+ rules,
65
+ });
66
+ }
67
+ // Also scan class methods
68
+ for (const cls of program.classes) {
69
+ for (const method of cls.methods) {
70
+ if (!method.name)
71
+ continue;
72
+ const level = asilLevel(method.decorators);
73
+ if (level === 0)
74
+ continue;
75
+ const asilName = level === 4 ? "D" : level === 3 ? "C" : level === 2 ? "B" : level === 1 ? "A" : "QM";
76
+ const mechanisms = detectMechanisms({ parameters: [], statements: method.statements });
77
+ const rules = {};
78
+ for (const ruleId of allRuleIds) {
79
+ rules[ruleId] = "pass";
80
+ }
81
+ functions.push({
82
+ name: `${cls.name}::${method.name}`,
83
+ asilLevel: asilName,
84
+ mechanisms,
85
+ rules,
86
+ });
87
+ }
88
+ }
89
+ return [{ functions }];
90
+ }
91
+ /** Scan a function's statements for safety-mechanism usage. */
92
+ function detectMechanisms(fn) {
93
+ const mechanisms = new Set();
94
+ const scan = (stmt) => {
95
+ if (!stmt || typeof stmt !== "object")
96
+ return;
97
+ // HAL ops (safe.read → safety.read_safe, safe.write → safety.write_verify)
98
+ if (stmt.kind === "hal-op" && typeof stmt.operation === "string") {
99
+ if (stmt.operation === "safety.read_safe")
100
+ mechanisms.add("safe.read");
101
+ if (stmt.operation === "safety.write_verify")
102
+ mechanisms.add("safe.write");
103
+ }
104
+ // Raw expressions mentioning SafeVariable or SafeInt
105
+ if (stmt.kind === "raw" && typeof stmt.value === "string") {
106
+ if (/\bSafeVariable</.test(stmt.value))
107
+ mechanisms.add("SafeVariable");
108
+ if (/\bSafeInt/.test(stmt.value))
109
+ mechanisms.add("SafeInt");
110
+ }
111
+ // var_decl with cppType containing SafeVariable<SafeInt
112
+ if (stmt.kind === "var_decl" && typeof stmt.cppType === "string") {
113
+ if (/SafeVariable</.test(stmt.cppType))
114
+ mechanisms.add("SafeVariable");
115
+ if (/SafeInt/.test(stmt.cppType))
116
+ mechanisms.add("SafeInt");
117
+ }
118
+ // Recurse
119
+ for (const key of Object.keys(stmt)) {
120
+ const val = stmt[key];
121
+ if (Array.isArray(val)) {
122
+ for (const item of val) {
123
+ if (item && typeof item === "object" && typeof item.kind === "string") {
124
+ scan(item);
125
+ }
126
+ }
127
+ }
128
+ else if (val && typeof val === "object" && typeof val.kind === "string") {
129
+ scan(val);
130
+ }
131
+ }
132
+ };
133
+ for (const stmt of fn.statements) {
134
+ scan(stmt);
135
+ }
136
+ return [...mechanisms].sort();
137
+ }
@@ -0,0 +1,10 @@
1
+ import type { ProgramIR, Diagnostic } from "../../api/index.js";
2
+ import type { SafetyTransformContext } from "../../safety-hook.js";
3
+ /** B6: No unconstrained goto (ISO 26262 Part 6, §7.4.8 — ASIL C+).
4
+ *
5
+ * Scans for goto statements in emitted IR. Cuttlefish's only source of
6
+ * goto is labeled break lowering (TS `break labelName;` → C++ `goto
7
+ * __break_labelName;`). While this is a controlled use, ISO 26262 C+
8
+ * restricts goto to specific patterns (forward, within the same block).
9
+ * Reports each goto as an info-level diagnostic for awareness. */
10
+ export declare function checkGoto(program: ProgramIR, _ctx: SafetyTransformContext): Diagnostic[];