@typecad/cuttlefish 1.0.0-alpha.14 → 1.0.0-alpha.16

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 (315) hide show
  1. package/README.md +82 -79
  2. package/assets/editor-extensions/typecad-debug/README.md +25 -26
  3. package/dist/api/config.d.ts +22 -26
  4. package/dist/api/schema/types.d.ts +20 -3
  5. package/dist/api/shared/async-runtime-static.d.ts +1 -1
  6. package/dist/api/shared/async-runtime-static.js +5 -5
  7. package/dist/api/shared/async-types.d.ts +3 -2
  8. package/dist/api/shared/board-catalog.d.ts +2 -0
  9. package/dist/api/shared/board-catalog.js +6 -0
  10. package/dist/api/shared/board-resolver.d.ts +4 -7
  11. package/dist/api/shared/board-resolver.js +2 -1
  12. package/dist/api/shared/coop-scheduler.d.ts +1 -1
  13. package/dist/api/shared/coop-scheduler.js +1 -1
  14. package/dist/api/shared/cpp-type-ir.d.ts +1 -1
  15. package/dist/api/shared/cpp-type-ir.js +1 -1
  16. package/dist/api/shared/display-profile.d.ts +1 -1
  17. package/dist/api/shared/display-profile.js +3 -5
  18. package/dist/api/shared/framework-manifest-registry.d.ts +1 -1
  19. package/dist/api/shared/framework-manifest-registry.js +0 -1
  20. package/dist/api/shared/framework-manifest.d.ts +7 -6
  21. package/dist/api/shared/framework-manifest.js +6 -11
  22. package/dist/api/shared/hal-op-ir.d.ts +294 -685
  23. package/dist/api/shared/hal-op-ir.js +31 -65
  24. package/dist/api/shared/index.d.ts +0 -4
  25. package/dist/api/shared/index.js +1 -7
  26. package/dist/api/shared/ir-core.d.ts +6 -0
  27. package/dist/api/shared/ir-declarations.d.ts +4 -0
  28. package/dist/api/shared/ir.d.ts +1 -3
  29. package/dist/api/shared/platform-strategy.d.ts +14 -37
  30. package/dist/api/shared/polyfill-helper-registry.js +0 -5
  31. package/dist/api/shared/polyfill-types.js +0 -27
  32. package/dist/api/shared/promise-runtime.js +3 -3
  33. package/dist/api/shared/spdx-licenses.d.ts +12 -10
  34. package/dist/api/shared/spdx-licenses.js +1 -1
  35. package/dist/api/shared/toolchain-types.d.ts +1 -1
  36. package/dist/api/shared/toolchain-types.js +3 -3
  37. package/dist/api/shared/types.d.ts +0 -3
  38. package/dist/api/shared/validate-framework-manifest.js +13 -33
  39. package/dist/board-catalog/dts-reader.d.ts +220 -0
  40. package/dist/board-catalog/dts-reader.js +1052 -0
  41. package/dist/board-catalog/index.d.ts +11 -0
  42. package/dist/board-catalog/index.js +12 -0
  43. package/dist/board-catalog/pinconfig.d.ts +48 -0
  44. package/dist/board-catalog/pinconfig.js +263 -0
  45. package/dist/board-catalog/sdk.d.ts +82 -0
  46. package/dist/board-catalog/sdk.js +180 -0
  47. package/dist/board-catalog/store.d.ts +196 -0
  48. package/dist/board-catalog/store.js +363 -0
  49. package/dist/board-catalog/types.d.ts +233 -0
  50. package/dist/board-catalog/types.js +7 -0
  51. package/dist/board-catalog/walker.d.ts +112 -0
  52. package/dist/board-catalog/walker.js +1101 -0
  53. package/dist/cli-utils.d.ts +2 -2
  54. package/dist/cli-utils.js +5 -5
  55. package/dist/cli.js +219 -242
  56. package/dist/config-loader.d.ts +14 -19
  57. package/dist/config-loader.js +240 -78
  58. package/dist/config-schema.d.ts +3 -5
  59. package/dist/config-schema.js +8 -8
  60. package/dist/contract/board-generator.d.ts +4 -4
  61. package/dist/contract/board-generator.js +16 -5
  62. package/dist/contract/contract-parser.d.ts +27 -0
  63. package/dist/contract/contract-parser.js +76 -0
  64. package/dist/contract/index.d.ts +1 -1
  65. package/dist/contract/index.js +70 -21
  66. package/dist/create/active-board-catalog.d.ts +9 -0
  67. package/dist/create/active-board-catalog.js +94 -0
  68. package/dist/create/board-catalog.generated.d.ts +96 -0
  69. package/dist/create/board-catalog.generated.js +128737 -0
  70. package/dist/create/board-search.d.ts +23 -0
  71. package/dist/create/board-search.js +88 -0
  72. package/dist/create/editor-integration.d.ts +4 -2
  73. package/dist/create/editor-integration.js +41 -2
  74. package/dist/create/framework-catalog.d.ts +57 -9
  75. package/dist/create/framework-catalog.js +76 -57
  76. package/dist/create/index.d.ts +5 -11
  77. package/dist/create/index.js +3 -8
  78. package/dist/create/mcu-target.d.ts +39 -0
  79. package/dist/create/mcu-target.js +80 -0
  80. package/dist/create/pack-targets.d.ts +19 -0
  81. package/dist/create/pack-targets.js +56 -0
  82. package/dist/create/scaffold.d.ts +4 -7
  83. package/dist/create/scaffold.js +19 -109
  84. package/dist/create/templates.d.ts +32 -5
  85. package/dist/create/templates.js +130 -116
  86. package/dist/create/wizard.d.ts +12 -1
  87. package/dist/create/wizard.js +168 -38
  88. package/dist/debug/preprocessor.d.ts +5 -0
  89. package/dist/debug/preprocessor.js +31 -7
  90. package/dist/diagnostics/diagnostics-report.d.ts +1 -1
  91. package/dist/diagnostics/diagnostics-report.js +3 -11
  92. package/dist/diagnostics/json-schema.d.ts +1 -1
  93. package/dist/diagnostics/md-writer.js +2 -2
  94. package/dist/diagnostics/mermaid-builder.d.ts +1 -1
  95. package/dist/diagnostics/mermaid-builder.js +1 -1
  96. package/dist/emit/cpp-emitter.js +4 -1
  97. package/dist/emit/emitters/class-emitter.js +32 -4
  98. package/dist/emit/emitters/emitter-context.d.ts +11 -0
  99. package/dist/emit/emitters/entrypoint-synthesizer.js +1 -1
  100. package/dist/emit/emitters/function-emitter-impl.js +33 -17
  101. package/dist/emit/emitters/output-finalizer.d.ts +7 -0
  102. package/dist/emit/emitters/output-finalizer.js +31 -23
  103. package/dist/emit/emitters/setup.js +125 -63
  104. package/dist/emit/emitters/top-level-prep.js +1 -1
  105. package/dist/emit/emitters/type-decl-emitter.js +13 -8
  106. package/dist/emit/emitters/ui-emitter.js +1 -1
  107. package/dist/emit/expression-renderer.d.ts +3 -3
  108. package/dist/emit/expression-renderer.js +17 -7
  109. package/dist/emit/route-hal-op.js +17 -48
  110. package/dist/emit/snprintf-helpers.d.ts +1 -3
  111. package/dist/emit/snprintf-helpers.js +1 -39
  112. package/dist/emit/statement-renderer.d.ts +0 -4
  113. package/dist/emit/statement-renderer.js +54 -45
  114. package/dist/emit/utils/async-state-machine.d.ts +16 -9
  115. package/dist/emit/utils/async-state-machine.js +56 -54
  116. package/dist/emit/utils/comment-helpers.d.ts +0 -8
  117. package/dist/emit/utils/comment-helpers.js +1 -1
  118. package/dist/emit/utils/cpp-helpers.d.ts +2 -2
  119. package/dist/emit/utils/cpp-helpers.js +2 -2
  120. package/dist/emit/utils/hal-op-cpp-type.js +4 -6
  121. package/dist/emit/utils/index.d.ts +3 -3
  122. package/dist/emit/utils/index.js +3 -3
  123. package/dist/emit/utils/type-inference.d.ts +1 -29
  124. package/dist/emit/utils/type-inference.js +0 -75
  125. package/dist/framework-package.d.ts +3 -0
  126. package/dist/framework-package.js +23 -6
  127. package/dist/framework-registry.d.ts +5 -5
  128. package/dist/frameworks/native/graphics/terminal-preview.d.ts +5 -0
  129. package/dist/frameworks/native/graphics/terminal-preview.js +33 -0
  130. package/dist/frameworks/native/index.d.ts +3 -0
  131. package/dist/frameworks/native/index.js +15 -0
  132. package/dist/frameworks/native/native-compile.d.ts +17 -0
  133. package/dist/frameworks/native/native-compile.js +170 -0
  134. package/dist/frameworks/native/native-config.d.ts +41 -0
  135. package/dist/frameworks/native/native-config.js +7 -0
  136. package/dist/frameworks/native/strategy.d.ts +97 -0
  137. package/dist/frameworks/native/strategy.js +664 -0
  138. package/dist/ir/board-resolver.d.ts +18 -23
  139. package/dist/ir/board-resolver.js +43 -401
  140. package/dist/ir/build-ir-state.d.ts +3 -0
  141. package/dist/ir/build-ir-state.js +42 -0
  142. package/dist/ir/build-ir.d.ts +1 -1
  143. package/dist/ir/build-ir.js +40 -42
  144. package/dist/ir/declaration-builders.js +1 -0
  145. package/dist/ir/expression-to-ir.js +17 -10
  146. package/dist/ir/hal/hal-emitter.d.ts +0 -2
  147. package/dist/ir/hal/hal-emitter.js +92 -41
  148. package/dist/ir/hal/hal-parser.d.ts +5 -5
  149. package/dist/ir/hal/hal-parser.js +128 -36
  150. package/dist/ir/hal/hal-plugins.d.ts +0 -1
  151. package/dist/ir/hal/hal-plugins.js +425 -716
  152. package/dist/ir/heap-analysis.js +2 -41
  153. package/dist/ir/identifier-collector.js +32 -20
  154. package/dist/ir/network-validation.js +7 -11
  155. package/dist/ir/ownership-analysis.js +75 -13
  156. package/dist/ir/peripheral-usage.d.ts +8 -2
  157. package/dist/ir/peripheral-usage.js +78 -149
  158. package/dist/ir/peripheral-validation.js +23 -3
  159. package/dist/ir/pin-capability-validation.d.ts +12 -0
  160. package/dist/ir/pin-capability-validation.js +61 -97
  161. package/dist/ir/pin-mode-validation.js +5 -5
  162. package/dist/ir/program-analysis.d.ts +8 -15
  163. package/dist/ir/program-analysis.js +140 -323
  164. package/dist/ir/pulldown-validation.js +11 -4
  165. package/dist/ir/resource-analysis.js +15 -3
  166. package/dist/ir/statement-to-ir.js +0 -6
  167. package/dist/ir/timing-validation.js +1 -1
  168. package/dist/ir/transformers/array-methods.js +11 -5
  169. package/dist/ir/transformers/call-statement.js +20 -87
  170. package/dist/ir/transformers/callback-context-registry.d.ts +1 -1
  171. package/dist/ir/transformers/callback-context-registry.js +8 -16
  172. package/dist/ir/transformers/control-flow.js +0 -13
  173. package/dist/ir/transformers/expressions.js +10 -9
  174. package/dist/ir/transformers/hal-call-resolver.d.ts +2 -2
  175. package/dist/ir/transformers/hal-call-resolver.js +24 -10
  176. package/dist/ir/transformers/hal-emit-helpers.d.ts +2 -2
  177. package/dist/ir/transformers/hal-emit-helpers.js +2 -2
  178. package/dist/ir/transformers/namespace-methods.js +1 -1
  179. package/dist/ir/transformers/ui-callback-lowering.d.ts +0 -2
  180. package/dist/ir/transformers/ui-callback-lowering.js +0 -24
  181. package/dist/ir/transformers/variables.js +338 -42
  182. package/dist/ir/try-catch-validation.js +4 -3
  183. package/dist/ir/type-resolution.js +15 -4
  184. package/dist/ir/validation-orchestrator.js +0 -9
  185. package/dist/libdef/cpp-to-decl.d.ts +0 -9
  186. package/dist/libdef/cpp-to-decl.js +0 -72
  187. package/dist/libdef/registry.d.ts +0 -1
  188. package/dist/libdef/registry.js +1 -24
  189. package/dist/library/init.d.ts +1 -1
  190. package/dist/library/init.js +137 -137
  191. package/dist/library-packages.d.ts +1 -1
  192. package/dist/library-packages.js +1 -1
  193. package/dist/mapping/peripheral-names.js +9 -4
  194. package/dist/mapping/source-map.d.ts +3 -4
  195. package/dist/mapping/source-map.js +12 -18
  196. package/dist/orchestrator/graph-builder.d.ts +3 -3
  197. package/dist/orchestrator/graph-builder.js +13 -12
  198. package/dist/orchestrator/type-checker.d.ts +3 -3
  199. package/dist/orchestrator/type-checker.js +3 -3
  200. package/dist/platform/async-runtime.js +1 -1
  201. package/dist/platform/coop-scheduler-runtime.js +2 -2
  202. package/dist/platform/generic-debug-codegen.d.ts +36 -0
  203. package/dist/platform/generic-debug-codegen.js +185 -0
  204. package/dist/platform/generic-strategy.d.ts +3 -4
  205. package/dist/platform/generic-strategy.js +5 -80
  206. package/dist/platform/index.js +1 -1
  207. package/dist/platform/registry.d.ts +2 -2
  208. package/dist/platform/registry.js +2 -2
  209. package/dist/safety/asil-decorators.d.ts +32 -0
  210. package/dist/safety/asil-decorators.js +32 -0
  211. package/dist/safety/authoring.d.ts +85 -0
  212. package/dist/safety/authoring.js +61 -0
  213. package/dist/safety/engine.d.ts +3 -0
  214. package/dist/safety/engine.js +83 -0
  215. package/dist/safety/hal/ops.d.ts +48 -0
  216. package/dist/safety/hal/ops.js +46 -0
  217. package/dist/safety/iso26262/analyze.d.ts +13 -0
  218. package/dist/safety/iso26262/analyze.js +29 -0
  219. package/dist/safety/iso26262/asil.d.ts +10 -0
  220. package/dist/safety/iso26262/asil.js +22 -0
  221. package/dist/safety/iso26262/collect.d.ts +14 -0
  222. package/dist/safety/iso26262/collect.js +137 -0
  223. package/dist/safety/iso26262/goto-checker.d.ts +10 -0
  224. package/dist/safety/iso26262/goto-checker.js +72 -0
  225. package/dist/safety/iso26262/heap-checker.d.ts +7 -0
  226. package/dist/safety/iso26262/heap-checker.js +57 -0
  227. package/dist/safety/iso26262/init-checker.d.ts +13 -0
  228. package/dist/safety/iso26262/init-checker.js +127 -0
  229. package/dist/safety/iso26262/loop-checker.d.ts +7 -0
  230. package/dist/safety/iso26262/loop-checker.js +86 -0
  231. package/dist/safety/iso26262/recursion-checker.d.ts +9 -0
  232. package/dist/safety/iso26262/recursion-checker.js +134 -0
  233. package/dist/safety/iso26262/sidecar-writer.d.ts +25 -0
  234. package/dist/safety/iso26262/sidecar-writer.js +13 -0
  235. package/dist/safety/passes/pinMode-intercept.d.ts +3 -0
  236. package/dist/safety/passes/pinMode-intercept.js +60 -0
  237. package/dist/safety/runtime/mode-table.d.ts +5 -0
  238. package/dist/safety/runtime/mode-table.js +55 -0
  239. package/dist/safety/runtime/polyfills.d.ts +6 -0
  240. package/dist/safety/runtime/polyfills.js +12 -0
  241. package/dist/safety/runtime/result-struct.d.ts +11 -0
  242. package/dist/safety/runtime/result-struct.js +98 -0
  243. package/dist/safety/runtime/safe-int.d.ts +33 -0
  244. package/dist/safety/runtime/safe-int.js +170 -0
  245. package/dist/safety/runtime/safe-traits.d.ts +4 -0
  246. package/dist/safety/runtime/safe-traits.js +95 -0
  247. package/dist/safety/runtime/safe-variable.d.ts +39 -0
  248. package/dist/safety/runtime/safe-variable.js +226 -0
  249. package/dist/safety/runtime/vote.d.ts +8 -0
  250. package/dist/safety/runtime/vote.js +92 -0
  251. package/dist/safety/runtime/write-verify.d.ts +8 -0
  252. package/dist/safety/runtime/write-verify.js +71 -0
  253. package/dist/safety/safe-int-types.d.ts +45 -0
  254. package/dist/safety/safe-int-types.js +25 -0
  255. package/dist/safety/safe-variable-types.d.ts +29 -0
  256. package/dist/safety/safe-variable-types.js +19 -0
  257. package/dist/safety/safety-bridge.d.ts +5 -6
  258. package/dist/safety/safety-bridge.js +15 -28
  259. package/dist/safety/sidecar-bridge.d.ts +1 -3
  260. package/dist/safety/sidecar-bridge.js +3 -20
  261. package/dist/safety/specifiers.d.ts +6 -0
  262. package/dist/safety/specifiers.js +14 -0
  263. package/dist/safety-hook.d.ts +8 -7
  264. package/dist/safety-hook.js +12 -13
  265. package/dist/testing.d.ts +4 -5
  266. package/dist/testing.js +5 -5
  267. package/dist/transpile/resolution.d.ts +1 -1
  268. package/dist/transpile/resolution.js +18 -9
  269. package/dist/transpile/test-pins.d.ts +18 -0
  270. package/dist/transpile/test-pins.js +142 -0
  271. package/dist/transpile.d.ts +1 -2
  272. package/dist/transpile.js +36 -30
  273. package/dist/types.d.ts +26 -26
  274. package/dist/ui-hook.d.ts +1 -1
  275. package/dist/utils/cli.d.ts +2 -2
  276. package/dist/utils/cli.js +92 -154
  277. package/dist/utils/fs.d.ts +3 -4
  278. package/dist/utils/fs.js +4 -5
  279. package/dist/utils/strings.d.ts +0 -1
  280. package/dist/utils/strings.js +0 -8
  281. package/dist/utils/ui.d.ts +5 -2
  282. package/dist/utils/ui.js +13 -3
  283. package/package.json +158 -157
  284. package/dist/add-preset.d.ts +0 -4
  285. package/dist/add-preset.js +0 -74
  286. package/dist/api/shared/async-symbol-detector.d.ts +0 -11
  287. package/dist/api/shared/async-symbol-detector.js +0 -140
  288. package/dist/api/shared/native-display-op-resolver.d.ts +0 -10
  289. package/dist/api/shared/native-display-op-resolver.js +0 -64
  290. package/dist/create/board-checklist.d.ts +0 -2
  291. package/dist/create/board-checklist.js +0 -52
  292. package/dist/create/board-codegen.d.ts +0 -9
  293. package/dist/create/board-codegen.js +0 -238
  294. package/dist/create/board-generators.d.ts +0 -12
  295. package/dist/create/board-generators.js +0 -651
  296. package/dist/create/board-spec.d.ts +0 -181
  297. package/dist/create/board-spec.js +0 -214
  298. package/dist/install/framework-catalog.d.ts +0 -53
  299. package/dist/install/framework-catalog.js +0 -107
  300. package/dist/install/handle-install.d.ts +0 -35
  301. package/dist/install/handle-install.js +0 -177
  302. package/dist/install/index.d.ts +0 -4
  303. package/dist/install/index.js +0 -3
  304. package/dist/ir/pin-state-tracking.d.ts +0 -58
  305. package/dist/ir/pin-state-tracking.js +0 -182
  306. package/dist/ir/pwm-timer-sharing.d.ts +0 -4
  307. package/dist/ir/pwm-timer-sharing.js +0 -94
  308. package/dist/ir/timer0-pwm-timing-conflict.d.ts +0 -4
  309. package/dist/ir/timer0-pwm-timing-conflict.js +0 -72
  310. package/dist/libdef/component-decls.d.ts +0 -2
  311. package/dist/libdef/component-decls.js +0 -6
  312. package/dist/libdef/component-discovery.d.ts +0 -43
  313. package/dist/libdef/component-discovery.js +0 -83
  314. package/dist/theme-tokens.d.ts +0 -22
  315. package/dist/theme-tokens.js +0 -172
@@ -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;
@@ -0,0 +1,14 @@
1
+ // Import specifiers that activate the safety engine. The safety engine was
2
+ // merged into @typecad/cuttlefish from the former @typecad/safety package;
3
+ // both specifiers keep working. Detection is purely by name — the module is
4
+ // never resolved or parsed (the graph builder skips it), so the legacy
5
+ // specifier does not require the frozen npm package to be installed.
6
+ /** The canonical specifier for the safety authoring surface. */
7
+ export const SAFETY_SPECIFIER = "@typecad/cuttlefish/safety";
8
+ /** The legacy specifier from when safety was a standalone package. */
9
+ export const LEGACY_SAFETY_SPECIFIER = "@typecad/safety";
10
+ /** True iff an import specifier refers to the safety authoring surface. */
11
+ export function isSafetyImportSpecifier(moduleSpecifier) {
12
+ return (moduleSpecifier === SAFETY_SPECIFIER ||
13
+ moduleSpecifier === LEGACY_SAFETY_SPECIFIER);
14
+ }
@@ -1,8 +1,9 @@
1
1
  import type { HALOpIR, ProgramIR, RuntimePolyfillIR, Diagnostic } from "./api/shared/index.js";
2
2
  /** Context handed to transformIR. */
3
3
  export interface SafetyTransformContext {
4
- /** True iff the entry file imports `safe` from @typecad/safety. The pass
5
- * uses this as a fast no-op guard. */
4
+ /** True iff the entry file imports `safe` from the safety authoring
5
+ * surface (@typecad/cuttlefish/safety, or legacy @typecad/safety). The
6
+ * pass uses this as a fast no-op guard. */
6
7
  readonly safetyInUse: boolean;
7
8
  /** Build target (e.g. "esp32", "avr"). Strategies still resolve the
8
9
  * underlying pinMode/digitalRead symbols; the safety package is target-
@@ -30,7 +31,7 @@ export interface TranspilerSafetyHook {
30
31
  } | undefined;
31
32
  /** Lower a safe.* TS call to a HAL op. Called from an extension point in
32
33
  * tryResolveSemanticCall (hal-plugins.ts) when the callee resolves to the
33
- * @typecad/safety package. Returns undefined if not a safety call. */
34
+ * safety authoring surface. Returns undefined if not a safety call. */
34
35
  resolveSemanticCall?(callee: string, args: readonly unknown[]): HALOpIR | undefined;
35
36
  /** Provide safety runtime polyfills (mode table + voter). Called from
36
37
  * buildEmitterContext so the polyfills participate in tree-shaking.
@@ -48,12 +49,12 @@ export interface TranspilerSafetyHook {
48
49
  * that the caller writes to a sidecar JSON file. */
49
50
  collectSafetyMetadata?(program: ProgramIR, ctx: SafetyTransformContext): SafetyMetadata[];
50
51
  }
51
- /** Set the safety hook. Called by transpile.ts after dynamically loading
52
- * @typecad/safety/engine. Passing null clears it. */
52
+ /** Set the safety hook. Called by transpile.ts after loading the safety
53
+ * engine. Passing null clears it. */
53
54
  export declare function setSafetyHook(hook: TranspilerSafetyHook | null): void;
54
- /** Get the current safety hook, or null if @typecad/safety is not loaded. */
55
+ /** Get the current safety hook, or null if the safety engine is not loaded. */
55
56
  export declare function getSafetyHook(): TranspilerSafetyHook | null;
56
- /** Returns true if the safety hook is registered (i.e. @typecad/safety loaded). */
57
+ /** Returns true if the safety hook is registered (i.e. safety engine loaded). */
57
58
  export declare function hasSafetyHook(): boolean;
58
59
  /** Get the safety hook, throwing if it's not set. Use only inside
59
60
  * `if (hasSafetyHook())` guards. */
@@ -1,25 +1,24 @@
1
1
  // ---------------------------------------------------------------------------
2
- // Safety hook — the contract cuttlefish core uses to talk to the optional
3
- // @typecad/safety package. Modeled on ui-hook.ts.
2
+ // Safety hook — the contract cuttlefish core uses to talk to the safety
3
+ // engine. Modeled on ui-hook.ts.
4
4
  //
5
- // @typecad/safety is an optional peer dependency. When it is installed and
6
- // imported by a sketch, transpile.ts calls loadSafetyEngine() which dynamic-
7
- // imports @typecad/safety/engine and calls registerSafetyEngine() to push an
8
- // implementation of this interface into the registry. When absent, every
9
- // hasSafetyHook() guard returns false and cuttlefish behaves as before.
5
+ // The engine lives in this package (src/safety/engine.ts); transpile.ts calls
6
+ // loadSafetyEngine() at the start of each run, which registers an
7
+ // implementation of this interface. The seam is kept so the degradation paths
8
+ // (resetSafetyEngine / __simulateSafetyAbsentForTest) stay testable.
10
9
  // ---------------------------------------------------------------------------
11
10
  // ── Module-level hook state ────────────────────────────────────────────────
12
11
  let safetyHook = null;
13
- /** Set the safety hook. Called by transpile.ts after dynamically loading
14
- * @typecad/safety/engine. Passing null clears it. */
12
+ /** Set the safety hook. Called by transpile.ts after loading the safety
13
+ * engine. Passing null clears it. */
15
14
  export function setSafetyHook(hook) {
16
15
  safetyHook = hook;
17
16
  }
18
- /** Get the current safety hook, or null if @typecad/safety is not loaded. */
17
+ /** Get the current safety hook, or null if the safety engine is not loaded. */
19
18
  export function getSafetyHook() {
20
19
  return safetyHook;
21
20
  }
22
- /** Returns true if the safety hook is registered (i.e. @typecad/safety loaded). */
21
+ /** Returns true if the safety hook is registered (i.e. safety engine loaded). */
23
22
  export function hasSafetyHook() {
24
23
  return safetyHook !== null;
25
24
  }
@@ -27,8 +26,8 @@ export function hasSafetyHook() {
27
26
  * `if (hasSafetyHook())` guards. */
28
27
  export function requireSafetyHook() {
29
28
  if (!safetyHook) {
30
- throw new Error("Safety hook is not registered. This code path requires @typecad/safety " +
31
- "to be installed and loaded. This should not happen — the hook is set " +
29
+ throw new Error("Safety hook is not registered. This code path requires the safety " +
30
+ "engine to be loaded. This should not happen — the hook is set " +
32
31
  "at the start of transpileFile() when safety is detected.");
33
32
  }
34
33
  return safetyHook;
package/dist/testing.d.ts CHANGED
@@ -19,11 +19,8 @@ export { transpileFile } from "./transpile.js";
19
19
  export { resetUIEngine, __simulateUIAbsentForTest } from "./ui/ui-bridge.js";
20
20
  export { resetSafetyEngine, __simulateSafetyAbsentForTest } from "./safety/safety-bridge.js";
21
21
  export { setSafetyHook, hasSafetyHook } from "./safety-hook.js";
22
- export { scaffoldProject, normalizeProjectName, KNOWN_BOARDS, generateProjectPackageJson, generateProjectTsconfig, generateProjectConfig, generateProjectEnvDts, generateStarterSketch, generateStarterTest, generateStarterSim, generateGitignore, generateEslintConfig, runCreateWizard, } from "./create/index.js";
22
+ export { scaffoldProject, normalizeProjectName, generateProjectPackageJson, generateProjectTsconfig, generateProjectConfig, generateProjectEnvDts, generateStarterProgram, generateStarterTest, generateStarterSim, generateGitignore, generateEslintConfig, runCreateWizard, } from "./create/index.js";
23
23
  export type { CreateProjectOptions } from "./create/index.js";
24
- export { scaffoldBoardPackages, parseBoardSpec, safeParseBoardSpec, stripJsonc, } from "./create/index.js";
25
- export type { BoardSpec, ScaffoldBoardResult } from "./create/index.js";
26
- export { BoardGenerators } from "./create/index.js";
27
24
  export { buildCallGraph, getReachableSymbols } from "./ir/call-graph.js";
28
25
  export { detectEntryPoints, detectExportedEntryPoints } from "./ir/entry-points.js";
29
26
  export { analyzeReachability, getReachabilityStats } from "./ir/reachability.js";
@@ -37,6 +34,8 @@ export type { ESLintError } from "./eslint-check.js";
37
34
  export { checkLintCache, recordLintSuccess, invalidateLint, computeLintFingerprint, resolveEslintConfigPath, } from "./lint-cache.js";
38
35
  export type { LintFingerprint, GateCacheResult } from "./lint-cache.js";
39
36
  export { runSemanticGates } from "./orchestrator/type-checker.js";
37
+ export { readGeneratedBoardConstants } from "./ir/board-resolver.js";
38
+ export { pinEntryIndexForNumber } from "./ir/pin-capability-validation.js";
40
39
  export { canonicalize, buildSemanticFacts, } from "./orchestrator/semantic-facts.js";
41
40
  export type { CanonicalType, SemanticFacts, FactStore, ValueCategory, Lifetime, Nullable, SemanticOrigin, AnalysisResult, BindingResolver, } from "./orchestrator/semantic-facts.js";
42
41
  export { verifyFacts } from "./orchestrator/semantic-facts-verifier.js";
@@ -46,7 +45,7 @@ export { parseCommandLine } from "./utils/cli.js";
46
45
  export { parseHeader, stripPreprocessorBlocks } from "./libdef/header-parser.js";
47
46
  export { BaseClassResolver, buildClassIndex } from "./libdef/base-class-resolver.js";
48
47
  export type { ResolveResult } from "./libdef/base-class-resolver.js";
49
- export { generateDecl, generateDeclsForDirectory, generateComponentDeclsForProject } from "./libdef/cpp-to-decl.js";
48
+ export { generateDecl, generateDeclsForDirectory } from "./libdef/cpp-to-decl.js";
50
49
  export { renderExprAsText } from "./ir/render-expr.js";
51
50
  export { contextStorage, CompilationContext } from "./ir/build-ir-state.js";
52
51
  export type { ExpressionIR } from "./api/index.js";
package/dist/testing.js CHANGED
@@ -23,10 +23,7 @@ export { resetUIEngine, __simulateUIAbsentForTest } from "./ui/ui-bridge.js";
23
23
  export { resetSafetyEngine, __simulateSafetyAbsentForTest } from "./safety/safety-bridge.js";
24
24
  export { setSafetyHook, hasSafetyHook } from "./safety-hook.js";
25
25
  // ── Project scaffolding ──────────────────────────────────────────────────────
26
- export { scaffoldProject, normalizeProjectName, KNOWN_BOARDS, generateProjectPackageJson, generateProjectTsconfig, generateProjectConfig, generateProjectEnvDts, generateStarterSketch, generateStarterTest, generateStarterSim, generateGitignore, generateEslintConfig, runCreateWizard, } from "./create/index.js";
27
- // ── Board codegen (`cuttlefish board add`) ───────────────────────────────────
28
- export { scaffoldBoardPackages, parseBoardSpec, safeParseBoardSpec, stripJsonc, } from "./create/index.js";
29
- export { BoardGenerators } from "./create/index.js";
26
+ export { scaffoldProject, normalizeProjectName, generateProjectPackageJson, generateProjectTsconfig, generateProjectConfig, generateProjectEnvDts, generateStarterProgram, generateStarterTest, generateStarterSim, generateGitignore, generateEslintConfig, runCreateWizard, } from "./create/index.js";
30
27
  // ── Tree-shaking & reachability ──────────────────────────────────────────────
31
28
  export { buildCallGraph, getReachableSymbols } from "./ir/call-graph.js";
32
29
  export { detectEntryPoints, detectExportedEntryPoints } from "./ir/entry-points.js";
@@ -43,6 +40,9 @@ export { runEslintCheck } from "./eslint-check.js";
43
40
  export { checkLintCache, recordLintSuccess, invalidateLint, computeLintFingerprint, resolveEslintConfigPath, } from "./lint-cache.js";
44
41
  // ── Semantic gates (TypeChecker-based) ──────────────────────────────────────
45
42
  export { runSemanticGates } from "./orchestrator/type-checker.js";
43
+ // ── Board constants / pin capability internals ──────────────────────────────
44
+ export { readGeneratedBoardConstants } from "./ir/board-resolver.js";
45
+ export { pinEntryIndexForNumber } from "./ir/pin-capability-validation.js";
46
46
  export { canonicalize, buildSemanticFacts, } from "./orchestrator/semantic-facts.js";
47
47
  export { verifyFacts } from "./orchestrator/semantic-facts-verifier.js";
48
48
  // ── Watch & CLI utilities ───────────────────────────────────────────────────
@@ -50,7 +50,7 @@ export { discoverWatchDirs, isRelevantChange } from "./watch.js";
50
50
  export { parseCommandLine } from "./utils/cli.js";
51
51
  export { parseHeader, stripPreprocessorBlocks } from "./libdef/header-parser.js";
52
52
  export { BaseClassResolver, buildClassIndex } from "./libdef/base-class-resolver.js";
53
- export { generateDecl, generateDeclsForDirectory, generateComponentDeclsForProject } from "./libdef/cpp-to-decl.js";
53
+ export { generateDecl, generateDeclsForDirectory } from "./libdef/cpp-to-decl.js";
54
54
  // ── IR rendering internals (for fail-closed regression tests) ───────────────
55
55
  export { renderExprAsText } from "./ir/render-expr.js";
56
56
  export { contextStorage, CompilationContext } from "./ir/build-ir-state.js";
@@ -18,7 +18,7 @@ export interface TranspileGraphResult {
18
18
  /** `.ui.html` modules discovered during graph build, keyed by resolved path. */
19
19
  uiModules: Set<string>;
20
20
  }
21
- export declare function resolveImport(fromFile: string, moduleSpecifier: string, boardPackage?: string): {
21
+ export declare function resolveImport(fromFile: string, moduleSpecifier: string, boardTarget?: string): {
22
22
  sourcePath: string;
23
23
  npmPackage?: ResolvedNpmPackage;
24
24
  uiModule?: boolean;
@@ -1,5 +1,6 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
+ import { findGeneratedBoard } from "../ir/board-resolver.js";
3
4
  function resolveLocalImport(fromFile, moduleSpecifier) {
4
5
  if (!moduleSpecifier.startsWith(".")) {
5
6
  return undefined;
@@ -179,13 +180,19 @@ function resolveNpmPackageImport(fromFile, moduleSpecifier) {
179
180
  moduleKey,
180
181
  };
181
182
  }
182
- export function resolveImport(fromFile, moduleSpecifier, boardPackage) {
183
+ export function resolveImport(fromFile, moduleSpecifier, boardTarget) {
183
184
  let effectiveSpecifier = moduleSpecifier;
184
- // The `@typecad/board` virtual import resolves to the configured board package.
185
- // (Case-insensitive so the documented mixed-case form is treated identically.)
186
- if (moduleSpecifier.toLowerCase() === "@typecad/board" && boardPackage) {
187
- effectiveSpecifier = boardPackage;
185
+ // The `@typecad/board` virtual import resolves to the project-local
186
+ // generated board module (.cuttlefish/board.ts) when one exists the
187
+ // config's board target materialized by boardgen. Falls through to the
188
+ // package-based path otherwise (transition; board packages are going away).
189
+ if (moduleSpecifier.toLowerCase() === "@typecad/board") {
190
+ const generated = findGeneratedBoard(fromFile);
191
+ if (generated) {
192
+ return { sourcePath: generated.boardTs };
193
+ }
188
194
  }
195
+ void boardTarget;
189
196
  const localResolved = resolveLocalImport(fromFile, effectiveSpecifier);
190
197
  if (localResolved) {
191
198
  // .ui.html files resolve as UI modules, not TypeScript sources. Only set
@@ -271,12 +278,14 @@ export function detectNativeCppModule(fromFile, moduleSpecifier) {
271
278
  export function isCuttlefishSDKPath(filePath) {
272
279
  const normalized = filePath.replace(/\\/g, "/");
273
280
  return (/\/code\/core\//.test(normalized) ||
274
- /\/code\/board-/.test(normalized) ||
275
- /\/packages\/board-/.test(normalized) ||
276
281
  /\/packages\/expect\//.test(normalized) ||
277
282
  /\/packages\/cuttlefish\//.test(normalized) ||
278
- /\/node_modules\/@typecad\/board-/.test(normalized) ||
279
283
  /\/node_modules\/@typecad\/core\//.test(normalized) ||
280
284
  /\/node_modules\/@typecad\/expect\//.test(normalized) ||
281
- /\/node_modules\/@typecad\/cuttlefish\//.test(normalized));
285
+ /\/node_modules\/@typecad\/cuttlefish\//.test(normalized) ||
286
+ // The generated project-local board module: like @typecad/hal, its source
287
+ // exists for pin resolution (halInstances / board constants), never for
288
+ // C++ emission — transpiling it would treat LED/PA5 as cross-module
289
+ // imports instead of compile-time pin facts.
290
+ /\/\.cuttlefish\/board\.ts$/.test(normalized));
282
291
  }
@@ -0,0 +1,18 @@
1
+ export interface TestPinsFile {
2
+ pins?: Record<string, string | string[]>;
3
+ facts?: Record<string, number>;
4
+ }
5
+ /** Read and parse a project's test-pins.json. Returns undefined when absent. */
6
+ export declare function readTestPinsFile(projectDir: string): TestPinsFile | undefined;
7
+ /**
8
+ * Build the generated module's source: role consts re-exported from the
9
+ * board package. Used by the editor-support generator
10
+ * (.cuttlefish/test-pins.ts — see config-loader's generateVirtualTypeDeclaration)
11
+ * so the language server resolves the '@typecad/test-pins' specifier.
12
+ * Hardware runs do NOT transpile this module: the @typecad/expect
13
+ * preprocessor substitutes role identifiers in test sources with the
14
+ * board's real pin symbols before the transpiler runs (the HAL resolves
15
+ * pins through board-package metadata, not through transpiled modules).
16
+ * Returns undefined when the board declares no usable roles.
17
+ */
18
+ export declare function buildTestPinsModuleContent(boardTarget: string, data: TestPinsFile): string | undefined;