@typecad/cuttlefish 0.1.0-alpha.2 → 1.0.0-alpha.6

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 (54) hide show
  1. package/README.md +10 -10
  2. package/dist/api/board-types.d.ts +1 -1
  3. package/dist/api/shared/hal-op-ir.d.ts +10 -1
  4. package/dist/api/shared/platform-strategy.d.ts +6 -0
  5. package/dist/api/shared/types.d.ts +8 -0
  6. package/dist/cli-utils.d.ts +1 -0
  7. package/dist/cli-utils.js +3 -1
  8. package/dist/cli.js +75 -0
  9. package/dist/create/index.d.ts +1 -1
  10. package/dist/create/index.js +1 -1
  11. package/dist/create/init-scaffold.js +48 -2
  12. package/dist/create/init-templates.d.ts +2 -0
  13. package/dist/create/init-templates.js +189 -9
  14. package/dist/emit/emitters/setup.js +122 -1
  15. package/dist/ir/adc-range-validation.js +26 -25
  16. package/dist/ir/expression-to-ir.js +43 -6
  17. package/dist/ir/hal/hal-plugins.js +10 -0
  18. package/dist/ir/interrupt-analysis.js +8 -3
  19. package/dist/ir/memory-budget-validation.js +1 -0
  20. package/dist/ir/ownership-analysis.js +19 -0
  21. package/dist/ir/peripheral-ownership.js +5 -0
  22. package/dist/ir/peripheral-validation.d.ts +1 -1
  23. package/dist/ir/peripheral-validation.js +6 -3
  24. package/dist/ir/pin-alias-conflict.d.ts +1 -1
  25. package/dist/ir/pin-alias-conflict.js +2 -1
  26. package/dist/ir/pin-capability-validation.js +34 -32
  27. package/dist/ir/pin-mode-validation.js +5 -0
  28. package/dist/ir/pin-safety.d.ts +1 -1
  29. package/dist/ir/pin-safety.js +2 -1
  30. package/dist/ir/program-analysis.d.ts +16 -0
  31. package/dist/ir/program-analysis.js +113 -0
  32. package/dist/ir/pulldown-validation.d.ts +1 -1
  33. package/dist/ir/pulldown-validation.js +2 -1
  34. package/dist/ir/pwm-timer-sharing.d.ts +1 -1
  35. package/dist/ir/pwm-timer-sharing.js +2 -1
  36. package/dist/ir/resource-analysis.js +2 -0
  37. package/dist/ir/timer0-pwm-timing-conflict.d.ts +1 -1
  38. package/dist/ir/timer0-pwm-timing-conflict.js +2 -1
  39. package/dist/ir/timing-validation.js +1 -0
  40. package/dist/ir/transformers/variables.js +46 -17
  41. package/dist/ir/try-catch-validation.js +2 -0
  42. package/dist/ir/type-resolution.js +2 -2
  43. package/dist/ir/unit-suspicion-validation.js +9 -7
  44. package/dist/ir/validation-orchestrator.js +6 -6
  45. package/dist/licenses.d.ts +185 -0
  46. package/dist/licenses.js +963 -0
  47. package/dist/testing.d.ts +1 -1
  48. package/dist/testing.js +1 -1
  49. package/dist/transpile.js +17 -9
  50. package/dist/types.d.ts +7 -1
  51. package/dist/utils/cli.js +44 -0
  52. package/package.json +5 -4
  53. package/dist/ir/heap-array-validation.d.ts +0 -24
  54. package/dist/ir/heap-array-validation.js +0 -29
@@ -51,6 +51,7 @@ export function validateBlockingDelayInLoop(program) {
51
51
  `or use Async.sleep(ms) / Async.yield() to let other tasks run between checks.`,
52
52
  line: stmt.sourceSpan?.startLine,
53
53
  column: stmt.sourceSpan?.startColumn,
54
+ filePath: stmt.sourceSpan?.filePath,
54
55
  code: 'blocking-delay-in-loop',
55
56
  source: 'timing-validation',
56
57
  });
@@ -14,6 +14,9 @@ function replaceHalReadBufferPlaceholder(op, varName) {
14
14
  if (op.operation === "i2c.read_buffer" && op.buffer === "__HAL_READ_BUF__") {
15
15
  return { ...op, buffer: varName };
16
16
  }
17
+ if (op.operation === "spi.read_buffer" && op.buffer === "__HAL_READ_BUF__") {
18
+ return { ...op, buffer: varName };
19
+ }
17
20
  return op;
18
21
  }
19
22
  export function assignmentOperatorToString(kind) {
@@ -430,6 +433,45 @@ export function variableStatementToIR(statement, fileName, sourceText, diagnosti
430
433
  const isSingletonReceiver = ts.isIdentifier(receiver) && isHALSingleton(receiver.text);
431
434
  if (result && (!isOwnershipMethod || isSingletonReceiver)) {
432
435
  const isHalOpReturn = result.returnValue === "__hal_op_return__";
436
+ // A __TYPED_ARRAY__ return comes ONLY from a HAL method body
437
+ // (`return new Uint8Array(count)` in e.g. I2CDevice.readBytes /
438
+ // SPIDevice.readRegister). The method's side-effect HAL ops (the
439
+ // i2c.read_buffer / spi.read_buffer fill loops) write INTO this buffer
440
+ // via the __HAL_READ_BUF__ placeholder (rewritten to `varName`). So the
441
+ // buffer var_decl MUST precede the fill ops in emitted order — at top
442
+ // level the var_decl is hoisted to file scope which masks this, but a
443
+ // function-local `const data = ...readBytes()` would otherwise emit the
444
+ // fill loop referencing `data` before its declaration. Detect the typed
445
+ // array up front so we can emit its declaration first.
446
+ const isTypedArrayReturn = typeof result.returnValue === "string" && result.returnValue.startsWith("__TYPED_ARRAY__:");
447
+ if (isTypedArrayReturn && typeof result.returnValue === "string") {
448
+ const parts = result.returnValue.split(":");
449
+ const elementType = parts[1];
450
+ const size = parts[2];
451
+ // Force non-const storage (the buffer is written by the fill op) and
452
+ // synthesize a zero-init array initializer so the var_decl renderer
453
+ // emits `T data[] = { 0, 0, ... }` — a bare `const T data[N];` that
454
+ // is later written would fail to compile (assignment to const).
455
+ // Mirrors plain `new Uint8Array(N)` (expression-to-ir.ts).
456
+ const count = parseInt(size, 10);
457
+ const initElements = !isNaN(count) && count > 0 && count <= 256
458
+ ? Array(count).fill(0).map(() => ({ kind: "number", value: 0 }))
459
+ : [];
460
+ lowered.push({
461
+ kind: "var_decl",
462
+ sourceSpan: makeSourceSpan(declaration, fileName, sourceText),
463
+ leadingComments: commentsAssigned ? [] : statementComments.leadingComments,
464
+ trailingComments: [],
465
+ name: varName,
466
+ storage: "let",
467
+ cppType: `${elementType}[${size}]`,
468
+ initializer: initElements.length > 0
469
+ ? { kind: "array", elements: initElements, elementType }
470
+ : undefined,
471
+ });
472
+ activeCArrayVars.add(varName);
473
+ commentsAssigned = true;
474
+ }
433
475
  if (result.halOps && result.halOps.length > 0) {
434
476
  const sideEffectOps = isHalOpReturn ? result.halOps.slice(0, -1) : result.halOps;
435
477
  const halStmts = sideEffectOps.map(op => ({
@@ -527,24 +569,11 @@ export function variableStatementToIR(statement, fileName, sourceText, diagnosti
527
569
  if (/\b\d+\.\d+\b/.test(result.returnValue)) {
528
570
  registerFloatVariable(varName);
529
571
  }
572
+ // __TYPED_ARRAY__ returns are handled above (declared BEFORE the
573
+ // fill ops). Everything else is a scalar/value return captured
574
+ // after the side-effect ops.
530
575
  const isTypedArray = result.returnValue.startsWith("__TYPED_ARRAY__:");
531
- if (isTypedArray) {
532
- const parts = result.returnValue.split(":");
533
- const elementType = parts[1];
534
- const size = parts[2];
535
- lowered.push({
536
- kind: "var_decl",
537
- sourceSpan: makeSourceSpan(declaration, fileName, sourceText),
538
- leadingComments: commentsAssigned ? [] : statementComments.leadingComments,
539
- trailingComments: [],
540
- name: varName,
541
- storage,
542
- cppType: `${elementType}[${size}]`,
543
- initializer: undefined,
544
- });
545
- activeCArrayVars.add(varName);
546
- }
547
- else {
576
+ if (!isTypedArray) {
548
577
  lowered.push({
549
578
  kind: "var_decl",
550
579
  sourceSpan: makeSourceSpan(declaration, fileName, sourceText),
@@ -39,6 +39,7 @@ export function validateTryCatch(program, boardConstants, strategy) {
39
39
  hint: `function readSensor(): number | null {\n const data = sensor.read();\n if (!data) return null; // error path\n return data.value; // success path\n}`,
40
40
  line: stmt.sourceSpan?.startLine,
41
41
  column: stmt.sourceSpan?.startColumn,
42
+ filePath: stmt.sourceSpan?.filePath,
42
43
  source: 'try-catch-validation',
43
44
  });
44
45
  // Still recurse into nested blocks to find other try/catch
@@ -57,6 +58,7 @@ export function validateTryCatch(program, boardConstants, strategy) {
57
58
  hint: `return null; // or return an error code`,
58
59
  line: stmt.sourceSpan?.startLine,
59
60
  column: stmt.sourceSpan?.startColumn,
61
+ filePath: stmt.sourceSpan?.filePath,
60
62
  source: 'try-catch-validation',
61
63
  });
62
64
  return;
@@ -33,9 +33,9 @@ const PIN_INTERFACE_TYPE_NAMES = new Set([
33
33
  "PinMode", "InterruptMode",
34
34
  ]);
35
35
  const BUS_INTERFACE_TYPE_NAMES = new Set([
36
- "II2CBus", "ISPIBus", "ISerialPort", "IUART",
36
+ "II2CBus", "ISPIBus", "ISerialPort",
37
37
  "I2CConfig", "SPIConfig", "UARTConfig",
38
- "I2CAddress", "UARTStatus", "SPITransferOptions",
38
+ "I2CAddress", "SPITransferOptions",
39
39
  ]);
40
40
  const STRATEGY_TYPE_NAMES = new Set([
41
41
  "NativeStrategy", "ArduinoStrategy", "BoardStrategy",
@@ -130,7 +130,7 @@ function checkSPIFrequency(value) {
130
130
  * baud rate used as SPI freq, etc.). Only literal numbers are checked —
131
131
  * expressions/variables are opaque to this validator.
132
132
  */
133
- function checkConfigValue(kind, rawValue, diagnostics) {
133
+ function checkConfigValue(kind, rawValue, filePath, diagnostics) {
134
134
  // HAL ops carry resolved numeric values as `number` when the source arg was
135
135
  // a literal, or as `string` expression text otherwise. Only check numbers.
136
136
  const value = typeof rawValue === 'number' ? rawValue
@@ -146,6 +146,7 @@ function checkConfigValue(kind, rawValue, diagnostics) {
146
146
  severity: 'warning',
147
147
  message,
148
148
  code: 'unit-suspicion',
149
+ filePath,
149
150
  source: 'unit-suspicion-validation',
150
151
  });
151
152
  }
@@ -160,15 +161,16 @@ function scanStatement(stmt, diagnostics) {
160
161
  if (!stmt || typeof stmt !== 'object')
161
162
  return;
162
163
  const s = stmt;
164
+ const filePath = s.sourceSpan?.filePath;
163
165
  // HAL-op statements carry structured operations with resolved values.
164
166
  if (stmt.kind === 'hal-op' && s.operation) {
165
167
  const op = s.operation;
166
168
  switch (op.operation) {
167
169
  case 'i2c.set_clock':
168
- checkConfigValue('i2c', op.hz, diagnostics);
170
+ checkConfigValue('i2c', op.hz, filePath, diagnostics);
169
171
  break;
170
172
  case 'uart.begin':
171
- checkConfigValue('baud', op.baud, diagnostics);
173
+ checkConfigValue('baud', op.baud, filePath, diagnostics);
172
174
  break;
173
175
  // SPI frequency flows through SPISettings construction text, which the
174
176
  // HAL op carries as a string — the numeric extraction in
@@ -178,7 +180,7 @@ function scanStatement(stmt, diagnostics) {
178
180
  // SPISettings({freq}, ...) — try to extract the leading frequency.
179
181
  const m = op.settings.match(/^\s*(\d+)/);
180
182
  if (m)
181
- checkConfigValue('spi', parseInt(m[1], 10), diagnostics);
183
+ checkConfigValue('spi', parseInt(m[1], 10), filePath, diagnostics);
182
184
  }
183
185
  break;
184
186
  }
@@ -188,18 +190,18 @@ function scanStatement(stmt, diagnostics) {
188
190
  if (stmt.kind === 'call' && typeof s.callee === 'string' && Array.isArray(s.args)) {
189
191
  const method = s.callee.split('.').pop() ?? s.callee;
190
192
  if (method === 'setClock' && s.args.length >= 2) {
191
- checkConfigValue('i2c', extractNumericValue(s.args[1]), diagnostics);
193
+ checkConfigValue('i2c', extractNumericValue(s.args[1]), filePath, diagnostics);
192
194
  }
193
195
  else if (method === 'setBaudRate' || method === 'begin') {
194
196
  // Serial.begin(baud) / setBaudRate(baud) — last numeric arg is the baud.
195
197
  for (const arg of s.args) {
196
198
  const v = extractNumericValue(arg);
197
199
  if (v !== undefined)
198
- checkConfigValue('baud', v, diagnostics);
200
+ checkConfigValue('baud', v, filePath, diagnostics);
199
201
  }
200
202
  }
201
203
  else if (method === 'setFrequency' && s.args.length >= 2) {
202
- checkConfigValue('spi', extractNumericValue(s.args[1]), diagnostics);
204
+ checkConfigValue('spi', extractNumericValue(s.args[1]), filePath, diagnostics);
203
205
  }
204
206
  }
205
207
  // Recurse into nested statements
@@ -23,13 +23,13 @@ export function runProgramValidations(program, strategy) {
23
23
  const diagnostics = [];
24
24
  const peripheralUsage = program.peripheralUsage ?? createEmptyPeripheralUsage();
25
25
  diagnostics.push(...validatePinCapabilities(program));
26
- diagnostics.push(...validatePeripherals(peripheralUsage, program.boardConstants));
27
- diagnostics.push(...validateUnsafePins(peripheralUsage, program.boardConstants));
26
+ diagnostics.push(...validatePeripherals(peripheralUsage, program.boardConstants, program.fileName));
27
+ diagnostics.push(...validateUnsafePins(peripheralUsage, program.boardConstants, program.fileName));
28
28
  diagnostics.push(...analyzeResources(program, resolvedStrategy));
29
- diagnostics.push(...validatePinAliasConflicts(peripheralUsage, program.boardConstants));
30
- diagnostics.push(...validatePWMTimerSharing(peripheralUsage, program.boardConstants));
31
- diagnostics.push(...validateTimer0PWMTimingConflict(peripheralUsage, program.boardConstants));
32
- diagnostics.push(...validatePulldownSupport(peripheralUsage, program.boardConstants));
29
+ diagnostics.push(...validatePinAliasConflicts(peripheralUsage, program.boardConstants, program.fileName));
30
+ diagnostics.push(...validatePWMTimerSharing(peripheralUsage, program.boardConstants, program.fileName));
31
+ diagnostics.push(...validateTimer0PWMTimingConflict(peripheralUsage, program.boardConstants, program.fileName));
32
+ diagnostics.push(...validatePulldownSupport(peripheralUsage, program.boardConstants, program.fileName));
33
33
  diagnostics.push(...analyzeInterruptSafety(program, peripheralUsage));
34
34
  inferVolatileForIsrSharedVars(program, diagnostics);
35
35
  detectReentrancyRisk(program, diagnostics);
@@ -0,0 +1,185 @@
1
+ export type CopyleftRisk = "permissive" | "weak-copyleft" | "strong-copyleft" | "unknown";
2
+ export type LicenseSource = "library.properties" | "license-file" | "source-header" | "none";
3
+ export interface LibraryLicenseEntry {
4
+ name: string;
5
+ version: string | undefined;
6
+ /** install_dir as reported by arduino-cli lib list. */
7
+ path: string;
8
+ /** Normalized SPDX ID (e.g. "BSD-3-Clause"); undefined if not determined. */
9
+ spdx: string | undefined;
10
+ risk: CopyleftRisk;
11
+ source: LicenseSource;
12
+ }
13
+ export type ScanOutcome = {
14
+ ok: true;
15
+ libraries: LibraryLicenseEntry[];
16
+ } | {
17
+ ok: false;
18
+ reason: "arduino-cli-not-found" | "arduino-cli-unresponsive" | "no-libraries";
19
+ message: string;
20
+ };
21
+ /**
22
+ * Headers the project needs. `source` is "ino" when read from the generated
23
+ * .ino (authoritative) or "config" when derived from cuttlefish.config.ts
24
+ * (partial: display/touch only).
25
+ */
26
+ export type ProjectHeaders = {
27
+ ok: true;
28
+ headers: string[];
29
+ source: "ino" | "config";
30
+ inoPath?: string;
31
+ } | {
32
+ ok: false;
33
+ reason: "no-config" | "no-entry" | "unreadable-ino";
34
+ message: string;
35
+ };
36
+ /**
37
+ * Minimal view of ResolvedCuttlefishConfig that resolveProjectHeaders needs.
38
+ * Kept structural so we don't import the full config type (avoids a cycle).
39
+ */
40
+ interface ProjectConfig {
41
+ configPath: string;
42
+ entry?: string;
43
+ outputOutDir?: string;
44
+ /** FQBN, e.g. 'arduino:avr:uno'. Used to resolve the board core for core-bundled libs. */
45
+ buildTarget?: string;
46
+ display?: {
47
+ profile?: string;
48
+ driver?: string;
49
+ touch?: {
50
+ library?: string;
51
+ };
52
+ } | null;
53
+ }
54
+ /** Classify a header as a compiler-toolchain C-library header. */
55
+ export declare function isToolchainHeader(header: string): boolean;
56
+ /**
57
+ * Result of resolving the project's board core directory.
58
+ */
59
+ export type ProjectCore = {
60
+ ok: true;
61
+ coreDir: string;
62
+ } | {
63
+ ok: false;
64
+ reason: "no-fqbn" | "no-core";
65
+ message: string;
66
+ };
67
+ /**
68
+ * Resolve the project's board-core directory from its FQBN, via
69
+ * `arduino-cli config dump` (for the packages data dir) and the on-disk
70
+ * `<data>/packages/<packager>/hardware/<arch>/<version>/` layout. Returns the
71
+ * highest-versioned core dir. Never throws.
72
+ *
73
+ * `runConfigDump` is an injected seam (returns the `config dump` stdout, or ""
74
+ * on failure) so the function is unit-testable without spawning.
75
+ */
76
+ export declare function resolveProjectCore(fqbn: string | undefined, runConfigDump: () => string, readdir: (d: string) => string[]): ProjectCore;
77
+ /**
78
+ * Resolve the project's library headers. Prefers the generated .ino
79
+ * (authoritative); falls back to display/touch headers derived from config
80
+ * (partial picture, no transpile required).
81
+ */
82
+ export declare function resolveProjectHeaders(config: ProjectConfig | undefined, readFile: (p: string) => string | undefined): ProjectHeaders;
83
+ /**
84
+ * One project header, joined to its owning library or flagged not-installed.
85
+ */
86
+ export type ProjectLibrary = {
87
+ kind: "resolved";
88
+ lib: LibraryLicenseEntry;
89
+ } | {
90
+ kind: "core";
91
+ header: string;
92
+ } | {
93
+ kind: "not-installed";
94
+ header: string;
95
+ };
96
+ /**
97
+ * Build a header-basename -> bundled-library map from a board core's bundled
98
+ * libraries. Scans `<coreDir>/libraries/<Lib>/src/` for .h files (e.g. Wire.h,
99
+ * SPI.h). Each header maps to a synthetic RawArduinoLibrary so the existing
100
+ * resolveLibraryLicense can read its license from the bundled lib's header
101
+ * notice or library.properties.
102
+ */
103
+ export declare function buildCoreHeaderIndex(coreDir: string, readdir: (d: string) => string[]): Map<string, RawArduinoLibrary>;
104
+ /**
105
+ * Join each project header to its owning library or classify it. Pipeline:
106
+ * 1. user library (arduino-cli lib list) -> resolved (license)
107
+ * 2. core library (project's own core) -> resolved (license, e.g. LGPL-2.1)
108
+ * 3. toolchain header (avr/*, util/*) -> core (gray, no license)
109
+ * 4. else -> not-installed
110
+ *
111
+ * `coreDir` is optional; when absent, step 2 is skipped.
112
+ */
113
+ export declare function joinHeadersToLibraries(headers: string[], libs: RawArduinoLibrary[], readdir: (d: string) => string[], readFile: (p: string) => string | undefined, coreDir?: string): ProjectLibrary[];
114
+ /**
115
+ * Resolve a raw license input (either the short `library.properties` `license=`
116
+ * value, the full text of a LICENSE file, or a source-file header comment) to a
117
+ * canonical SPDX ID.
118
+ *
119
+ * Matching priority:
120
+ * 1. SPDX-License-Identifier: <id> marker (authoritative when present)
121
+ * 2. exact alias match (suits the short properties value)
122
+ * 3. substring markers match, ALL markers required (suits full LICENSE text)
123
+ * 4. shortMarkers match, ANY one sufficient (suits sparse header comments
124
+ * like Adafruit's "BSD license, all text here must be included")
125
+ *
126
+ * Returns the SPDX ID string, or undefined if nothing matched.
127
+ */
128
+ export declare function identifySpdx(input: string): string | undefined;
129
+ /**
130
+ * Classify the copyleft risk of a known SPDX ID. Returns "unknown" for
131
+ * unrecognized ids.
132
+ */
133
+ export declare function classifyRisk(spdx: string): CopyleftRisk;
134
+ /** Raw library entry as it appears in `arduino-cli lib list --format json`. */
135
+ export interface RawArduinoLibrary {
136
+ name: string;
137
+ version?: string;
138
+ install_dir?: string;
139
+ }
140
+ /**
141
+ * Options for `scanLicenses`. Production calls omit this object entirely; tests
142
+ * inject `fakeLibList` and `fakeReadFile` to avoid spawning and disk I/O.
143
+ */
144
+ export interface ScanOptions {
145
+ /** Override the `arduino-cli lib list` call. Return null to simulate spawn failure. */
146
+ fakeLibList?: () => RawArduinoLibrary[] | null;
147
+ /** Override disk reads of library.properties and LICENSE files. */
148
+ fakeReadFile?: (p: string) => string | undefined;
149
+ /** Override directory listings. */
150
+ fakeReaddir?: (d: string) => string[];
151
+ }
152
+ /**
153
+ * Normalize either JSON shape (wrapped or bare array) to a flat library list.
154
+ * Exported for direct unit testing of the dual-shape parsing.
155
+ */
156
+ export declare function coerceLibList(parsed: unknown): RawArduinoLibrary[];
157
+ /**
158
+ * Module-level runner override used by presenter tests so `scanLicenses()`
159
+ * (with no args) does not spawn. Mirrors __setArduinoCliRunnerForTest.
160
+ */
161
+ export interface LicensesRunner {
162
+ listLibraries: () => RawArduinoLibrary[] | null;
163
+ readFile: (p: string) => string | undefined;
164
+ readdir: (d: string) => string[];
165
+ }
166
+ /** @internal Test-only override of the default runner. */
167
+ export declare function __setLicensesRunnerForTest(runner: LicensesRunner | undefined): void;
168
+ /**
169
+ * Scan installed Arduino libraries and resolve each one's license. Never throws.
170
+ */
171
+ export declare function scanLicenses(options?: ScanOptions): ScanOutcome;
172
+ /** @internal Test-only override of the project config (normally loaded via loadCuttlefishConfig). */
173
+ export declare function __setProjectConfigForTest(config: ProjectConfig | undefined): void;
174
+ /** @internal Test-only override of `arduino-cli config dump` stdout. */
175
+ export declare function __setConfigDumpForTest(fn: (() => string) | undefined): void;
176
+ /**
177
+ * `cuttlefish licenses` presenter. `all === false` (default, project scope)
178
+ * resolves this project's libraries from the generated .ino (or config
179
+ * fallback), joins each to an installed library, and reports only those.
180
+ * `all === true` reports every installed library (the original behavior).
181
+ * Warns on unknown licenses; flags NOT INSTALLED headers in project scope; sets
182
+ * process.exitCode under --strict. Never calls process.exit().
183
+ */
184
+ export declare function runLicensesPresenter(strict: boolean, all: boolean): void;
185
+ export {};