@hominis/fireforge 0.50.0 → 0.51.0

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 (205) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/dist/build-info.json +4 -4
  3. package/dist/src/commands/check-report.d.ts +17 -4
  4. package/dist/src/commands/check-report.js +19 -6
  5. package/dist/src/commands/check-run.d.ts +5 -0
  6. package/dist/src/commands/check-run.js +9 -1
  7. package/dist/src/commands/check-steps.d.ts +8 -0
  8. package/dist/src/commands/check-steps.js +31 -6
  9. package/dist/src/commands/check.js +1 -1
  10. package/dist/src/commands/declarations-report.d.ts +43 -0
  11. package/dist/src/commands/declarations-report.js +76 -0
  12. package/dist/src/commands/export-placement-gate.js +8 -0
  13. package/dist/src/commands/furnace/rename-registrations.js +7 -2
  14. package/dist/src/commands/furnace/validate.js +26 -1
  15. package/dist/src/commands/lint-per-patch.js +6 -2
  16. package/dist/src/commands/lint-per-run-checkjs.js +2 -2
  17. package/dist/src/commands/lint-report.js +7 -2
  18. package/dist/src/commands/manifest.js +2 -0
  19. package/dist/src/commands/park.d.ts +22 -0
  20. package/dist/src/commands/park.js +232 -0
  21. package/dist/src/commands/patch/delete.js +11 -6
  22. package/dist/src/commands/patch/index.d.ts +3 -3
  23. package/dist/src/commands/patch/index.js +8 -4
  24. package/dist/src/commands/patch/lint-ignore-from.d.ts +44 -0
  25. package/dist/src/commands/patch/lint-ignore-from.js +142 -0
  26. package/dist/src/commands/patch/lint-ignore.js +39 -29
  27. package/dist/src/commands/patch/move-files-create.js +11 -4
  28. package/dist/src/commands/patch/move-files-into.js +10 -4
  29. package/dist/src/commands/patch/move-files.js +3 -1
  30. package/dist/src/commands/patch/removal-created-files.d.ts +48 -0
  31. package/dist/src/commands/patch/removal-created-files.js +83 -0
  32. package/dist/src/commands/patch/rename.js +15 -3
  33. package/dist/src/commands/patch/reserve.d.ts +33 -0
  34. package/dist/src/commands/patch/reserve.js +152 -0
  35. package/dist/src/commands/patch/retire.js +11 -6
  36. package/dist/src/commands/patch/split-plan.d.ts +10 -1
  37. package/dist/src/commands/patch/split-plan.js +16 -1
  38. package/dist/src/commands/patch/split.js +14 -5
  39. package/dist/src/commands/patch/stage.d.ts +34 -0
  40. package/dist/src/commands/patch/stage.js +153 -0
  41. package/dist/src/commands/patch/staged-dependency-remove.d.ts +31 -0
  42. package/dist/src/commands/patch/staged-dependency-remove.js +80 -0
  43. package/dist/src/commands/patch/staged-dependency.js +40 -98
  44. package/dist/src/commands/re-export-adjacent.d.ts +5 -0
  45. package/dist/src/commands/re-export-adjacent.js +4 -3
  46. package/dist/src/commands/re-export-bulk-scan.d.ts +2 -1
  47. package/dist/src/commands/re-export-bulk-scan.js +22 -7
  48. package/dist/src/commands/re-export-hunks.d.ts +35 -0
  49. package/dist/src/commands/re-export-hunks.js +220 -0
  50. package/dist/src/commands/re-export-options.js +29 -2
  51. package/dist/src/commands/re-export-purity-scope.d.ts +18 -0
  52. package/dist/src/commands/re-export-purity-scope.js +131 -0
  53. package/dist/src/commands/re-export-register.js +15 -1
  54. package/dist/src/commands/re-export-removed.d.ts +1 -1
  55. package/dist/src/commands/re-export-removed.js +17 -2
  56. package/dist/src/commands/re-export-scan.d.ts +2 -0
  57. package/dist/src/commands/re-export-scan.js +4 -1
  58. package/dist/src/commands/re-export-single.js +102 -42
  59. package/dist/src/commands/re-export-stale-registrations.d.ts +18 -0
  60. package/dist/src/commands/re-export-stale-registrations.js +62 -0
  61. package/dist/src/commands/re-export.js +35 -34
  62. package/dist/src/commands/test-build-furnace.d.ts +3 -2
  63. package/dist/src/commands/test-build-furnace.js +8 -2
  64. package/dist/src/commands/test-build-phase.js +24 -7
  65. package/dist/src/commands/test-checkjs.js +3 -2
  66. package/dist/src/commands/test-dispatch.d.ts +39 -0
  67. package/dist/src/commands/test-dispatch.js +211 -0
  68. package/dist/src/commands/test-furnace-reach.d.ts +37 -0
  69. package/dist/src/commands/test-furnace-reach.js +132 -0
  70. package/dist/src/commands/test-orchestrate.d.ts +9 -0
  71. package/dist/src/commands/test-orchestrate.js +22 -4
  72. package/dist/src/commands/test-perf-scope.d.ts +21 -0
  73. package/dist/src/commands/test-perf-scope.js +55 -0
  74. package/dist/src/commands/test-prelock.js +100 -4
  75. package/dist/src/commands/test-register.js +18 -3
  76. package/dist/src/commands/test-results.d.ts +62 -0
  77. package/dist/src/commands/test-results.js +62 -0
  78. package/dist/src/commands/test-run.d.ts +13 -55
  79. package/dist/src/commands/test-run.js +73 -101
  80. package/dist/src/commands/test-shards.d.ts +110 -0
  81. package/dist/src/commands/test-shards.js +255 -0
  82. package/dist/src/commands/test-stale-gate.d.ts +5 -1
  83. package/dist/src/commands/test-stale-gate.js +4 -2
  84. package/dist/src/commands/test-verdict.d.ts +2 -1
  85. package/dist/src/commands/test.d.ts +1 -1
  86. package/dist/src/commands/test.js +65 -75
  87. package/dist/src/commands/token-lint.js +48 -8
  88. package/dist/src/commands/verify.js +9 -2
  89. package/dist/src/core/build-prepare.d.ts +6 -0
  90. package/dist/src/core/build-prepare.js +29 -3
  91. package/dist/src/core/config-paths.d.ts +1 -1
  92. package/dist/src/core/config-paths.js +2 -0
  93. package/dist/src/core/config-validate-check.js +83 -7
  94. package/dist/src/core/config-validate-test-toolchains.js +14 -0
  95. package/dist/src/core/config-validate-token-scales.d.ts +3 -0
  96. package/dist/src/core/config-validate-token-scales.js +47 -5
  97. package/dist/src/core/config-validate.js +6 -0
  98. package/dist/src/core/coverage-extend.js +2 -2
  99. package/dist/src/core/coverage-records.d.ts +11 -0
  100. package/dist/src/core/coverage-records.js +34 -0
  101. package/dist/src/core/engine-session-lock.d.ts +6 -0
  102. package/dist/src/core/engine-session-lock.js +10 -2
  103. package/dist/src/core/file-lock-shared.d.ts +57 -0
  104. package/dist/src/core/file-lock-shared.js +117 -0
  105. package/dist/src/core/file-lock.d.ts +9 -0
  106. package/dist/src/core/file-lock.js +58 -2
  107. package/dist/src/core/furnace-apply.js +10 -10
  108. package/dist/src/core/furnace-config-validate-exceptions.d.ts +10 -3
  109. package/dist/src/core/furnace-config-validate-exceptions.js +39 -8
  110. package/dist/src/core/furnace-config-validate.js +7 -1
  111. package/dist/src/core/furnace-registration-jar-inplace.d.ts +12 -0
  112. package/dist/src/core/furnace-registration-jar-inplace.js +80 -0
  113. package/dist/src/core/furnace-validate-accessibility.d.ts +4 -2
  114. package/dist/src/core/furnace-validate-accessibility.js +61 -27
  115. package/dist/src/core/furnace-validate-exceptions.d.ts +12 -4
  116. package/dist/src/core/furnace-validate-exceptions.js +41 -4
  117. package/dist/src/core/furnace-validate-icon-button.js +30 -1
  118. package/dist/src/core/history-log-file.js +8 -1
  119. package/dist/src/core/line-prefixer.d.ts +18 -0
  120. package/dist/src/core/line-prefixer.js +34 -0
  121. package/dist/src/core/mach.d.ts +7 -0
  122. package/dist/src/core/mach.js +24 -9
  123. package/dist/src/core/module-resolution-preflight.d.ts +19 -3
  124. package/dist/src/core/module-resolution-preflight.js +24 -6
  125. package/dist/src/core/negative-control-compiled.d.ts +27 -0
  126. package/dist/src/core/negative-control-compiled.js +73 -0
  127. package/dist/src/core/negative-control-diff.d.ts +14 -2
  128. package/dist/src/core/negative-control-diff.js +49 -6
  129. package/dist/src/core/negative-control.d.ts +12 -0
  130. package/dist/src/core/negative-control.js +48 -5
  131. package/dist/src/core/park-store.d.ts +63 -0
  132. package/dist/src/core/park-store.js +216 -0
  133. package/dist/src/core/patch-export-update.d.ts +4 -0
  134. package/dist/src/core/patch-export-update.js +12 -3
  135. package/dist/src/core/patch-export.d.ts +3 -2
  136. package/dist/src/core/patch-export.js +21 -14
  137. package/dist/src/core/patch-files.js +26 -8
  138. package/dist/src/core/patch-lint-checkjs-any-import.d.ts +6 -4
  139. package/dist/src/core/patch-lint-checkjs-any-import.js +9 -7
  140. package/dist/src/core/patch-lint-checkjs-diagnostics.d.ts +17 -0
  141. package/dist/src/core/patch-lint-checkjs-diagnostics.js +32 -0
  142. package/dist/src/core/patch-lint-checkjs.d.ts +10 -1
  143. package/dist/src/core/patch-lint-checkjs.js +13 -3
  144. package/dist/src/core/patch-lint-cross.d.ts +3 -1
  145. package/dist/src/core/patch-lint-cross.js +5 -0
  146. package/dist/src/core/patch-lint-css.js +14 -10
  147. package/dist/src/core/patch-lint-forward-registration-extended.d.ts +5 -0
  148. package/dist/src/core/patch-lint-forward-registration-extended.js +1 -1
  149. package/dist/src/core/patch-lint-ignore.d.ts +56 -12
  150. package/dist/src/core/patch-lint-ignore.js +173 -43
  151. package/dist/src/core/patch-lint-ownership.d.ts +10 -0
  152. package/dist/src/core/patch-lint-ownership.js +26 -0
  153. package/dist/src/core/patch-lint-size.js +9 -1
  154. package/dist/src/core/patch-lint-token-scale.d.ts +26 -8
  155. package/dist/src/core/patch-lint-token-scale.js +206 -29
  156. package/dist/src/core/patch-lint.js +2 -2
  157. package/dist/src/core/patch-manifest-io.js +8 -1
  158. package/dist/src/core/patch-manifest-key-order.d.ts +24 -0
  159. package/dist/src/core/patch-manifest-key-order.js +61 -0
  160. package/dist/src/core/patch-manifest-stage.d.ts +46 -0
  161. package/dist/src/core/patch-manifest-stage.js +96 -0
  162. package/dist/src/core/patch-manifest-validate.js +27 -1
  163. package/dist/src/core/patch-order-legal.d.ts +2 -1
  164. package/dist/src/core/patch-order-legal.js +7 -2
  165. package/dist/src/core/patch-policy.d.ts +6 -2
  166. package/dist/src/core/patch-policy.js +14 -7
  167. package/dist/src/core/patch-retired.d.ts +26 -4
  168. package/dist/src/core/patch-retired.js +40 -2
  169. package/dist/src/core/run-log.d.ts +6 -0
  170. package/dist/src/core/run-log.js +17 -1
  171. package/dist/src/core/test-harness-crash.d.ts +2 -1
  172. package/dist/src/core/test-harness-crash.js +5 -8
  173. package/dist/src/core/test-harness-signature.d.ts +16 -0
  174. package/dist/src/core/test-harness-signature.js +19 -1
  175. package/dist/src/core/test-raw-log.d.ts +66 -0
  176. package/dist/src/core/test-raw-log.js +122 -0
  177. package/dist/src/core/test-run-completeness.d.ts +36 -3
  178. package/dist/src/core/test-run-completeness.js +57 -17
  179. package/dist/src/core/test-xpcshell-retry.d.ts +2 -0
  180. package/dist/src/core/test-xpcshell-retry.js +2 -1
  181. package/dist/src/core/token-lint.d.ts +5 -2
  182. package/dist/src/core/token-lint.js +8 -3
  183. package/dist/src/core/token-sibling-sheets.d.ts +46 -0
  184. package/dist/src/core/token-sibling-sheets.js +119 -0
  185. package/dist/src/core/tree-guard.js +2 -0
  186. package/dist/src/core/typecheck-shim.d.ts +5 -1
  187. package/dist/src/core/typecheck-shim.js +115 -2
  188. package/dist/src/core/typecheck.js +3 -1
  189. package/dist/src/index.d.ts +9 -3
  190. package/dist/src/index.js +4 -1
  191. package/dist/src/types/commands/index.d.ts +2 -2
  192. package/dist/src/types/commands/options.d.ts +68 -7
  193. package/dist/src/types/commands/patches.d.ts +43 -0
  194. package/dist/src/types/config.d.ts +74 -2
  195. package/dist/src/types/furnace.d.ts +20 -0
  196. package/dist/src/types/index.d.ts +1 -1
  197. package/dist/src/utils/options.d.ts +3 -2
  198. package/dist/src/utils/options.js +9 -4
  199. package/docs/configuration.md +94 -9
  200. package/docs/furnace.md +43 -1
  201. package/docs/lifecycle-invariants.md +13 -11
  202. package/docs/machine-output.md +64 -18
  203. package/docs/patch-workflow.md +174 -13
  204. package/docs/testing.md +73 -4
  205. package/package.json +3 -3
@@ -24,15 +24,46 @@
24
24
  */
25
25
  import { type HarnessRunVerdict } from './test-harness-crash.js';
26
26
  import type { IncompleteRunEvidence } from './test-harness-signature.js';
27
+ /** Start and skip marker names seen in a run's output. */
28
+ export interface StartMarkers {
29
+ started: string[];
30
+ skipped: string[];
31
+ }
32
+ /**
33
+ * Collects start and skip markers from a dispatch's output as it streams.
34
+ *
35
+ * The capture `runMachCapture` hands back keeps only the last 2 MB of each
36
+ * stream, so a suite that prints more than that (a large browser directory,
37
+ * or any run under `--full-output`) loses its first files' start lines from
38
+ * the capture, and counting from that tail named files that ran and passed
39
+ * as never started. The tracker sees every chunk, splits it into whole lines
40
+ * per stream, and keeps only the marker names, so it grows with the file
41
+ * count, not the output size.
42
+ */
43
+ export interface StartMarkerTracker {
44
+ /** Feeds one output chunk; wire it to `MachOptions.onOutputChunk`. */
45
+ onChunk(stream: 'stdout' | 'stderr', chunk: string): void;
46
+ /** The markers seen so far, including any unterminated last line. */
47
+ markers(): StartMarkers;
48
+ }
49
+ /** Markers collected outside the capped capture, and where they came from. */
50
+ export interface TrackedStartMarkers {
51
+ markers: StartMarkers;
52
+ /** `stream`: every output chunk; `raw`: the mozlog structured log. */
53
+ source: 'stream' | 'raw';
54
+ }
55
+ /** Creates a {@link StartMarkerTracker}. */
56
+ export declare function createStartMarkerTracker(): StartMarkerTracker;
27
57
  /**
28
58
  * Counts the requested test files that produced a start or skip marker.
29
59
  * Returns undefined when nothing can be counted: no test-file-shaped
30
60
  * request, or no start line that names any requested file.
31
61
  *
32
- * @param output - Captured mach stdout and stderr
62
+ * @param evidence - Captured mach stdout and stderr, or the markers
63
+ * collected from the complete stream
33
64
  * @param requestedPaths - Dispatched paths, in dispatch order
34
65
  */
35
- export declare function countStartedFiles(output: string, requestedPaths: readonly string[]): {
66
+ export declare function countStartedFiles(evidence: string | StartMarkers, requestedPaths: readonly string[]): {
36
67
  started: number;
37
68
  requested: number;
38
69
  firstUnstarted?: string;
@@ -45,8 +76,10 @@ export declare function countStartedFiles(output: string, requestedPaths: readon
45
76
  * @param verdict - The classifier's verdict
46
77
  * @param output - Captured mach stdout and stderr
47
78
  * @param requestedPaths - Dispatched paths, in dispatch order
79
+ * @param tracked - Start markers collected from the complete stream (or
80
+ * the structured raw log); without them the capped capture is scanned
48
81
  */
49
- export declare function vetoIncompletePass(verdict: HarnessRunVerdict, output: string, requestedPaths: readonly string[]): HarnessRunVerdict;
82
+ export declare function vetoIncompletePass(verdict: HarnessRunVerdict, output: string, requestedPaths: readonly string[], tracked?: TrackedStartMarkers): HarnessRunVerdict;
50
83
  /**
51
84
  * Operator-facing explanation for a pass {@link vetoIncompletePass}
52
85
  * refused. Names the first file that never started, because that is
@@ -33,30 +33,59 @@ const SKIP_MARKER_PATTERN = /\bTEST[-_]SKIP(?:PED)?\b[:| ]*\s*(\S+)?/;
33
33
  function basenameOf(path) {
34
34
  return path.slice(path.lastIndexOf('/') + 1);
35
35
  }
36
+ /** Collects the start and skip marker names in `output`, line by line. */
37
+ function scanStartMarkers(output) {
38
+ const markers = { started: [], skipped: [] };
39
+ for (const line of output.split(/\r?\n/))
40
+ recordMarkerLine(line, markers);
41
+ return markers;
42
+ }
43
+ function recordMarkerLine(line, markers) {
44
+ const start = START_MARKER_PATTERN.exec(line)?.[1];
45
+ if (start !== undefined) {
46
+ markers.started.push(start);
47
+ return;
48
+ }
49
+ const skip = SKIP_MARKER_PATTERN.exec(line)?.[1];
50
+ if (skip !== undefined)
51
+ markers.skipped.push(skip);
52
+ }
53
+ /** Creates a {@link StartMarkerTracker}. */
54
+ export function createStartMarkerTracker() {
55
+ const collected = { started: [], skipped: [] };
56
+ const pending = { stdout: '', stderr: '' };
57
+ return {
58
+ onChunk(stream, chunk) {
59
+ const lines = `${pending[stream]}${chunk}`.split(/\r?\n/);
60
+ pending[stream] = lines.pop() ?? '';
61
+ for (const line of lines)
62
+ recordMarkerLine(line, collected);
63
+ },
64
+ markers() {
65
+ const tail = { started: [], skipped: [] };
66
+ recordMarkerLine(pending.stdout, tail);
67
+ recordMarkerLine(pending.stderr, tail);
68
+ return {
69
+ started: [...collected.started, ...tail.started],
70
+ skipped: [...collected.skipped, ...tail.skipped],
71
+ };
72
+ },
73
+ };
74
+ }
36
75
  /**
37
76
  * Counts the requested test files that produced a start or skip marker.
38
77
  * Returns undefined when nothing can be counted: no test-file-shaped
39
78
  * request, or no start line that names any requested file.
40
79
  *
41
- * @param output - Captured mach stdout and stderr
80
+ * @param evidence - Captured mach stdout and stderr, or the markers
81
+ * collected from the complete stream
42
82
  * @param requestedPaths - Dispatched paths, in dispatch order
43
83
  */
44
- export function countStartedFiles(output, requestedPaths) {
84
+ export function countStartedFiles(evidence, requestedPaths) {
45
85
  const requested = requestedPaths.filter((path) => TEST_FILE_BASENAME_PATTERN.test(basenameOf(path)));
46
86
  if (requested.length === 0)
47
87
  return undefined;
48
- const started = [];
49
- const skipped = [];
50
- for (const line of output.split(/\r?\n/)) {
51
- const start = START_MARKER_PATTERN.exec(line)?.[1];
52
- if (start !== undefined) {
53
- started.push(start);
54
- continue;
55
- }
56
- const skip = SKIP_MARKER_PATTERN.exec(line)?.[1];
57
- if (skip !== undefined)
58
- skipped.push(skip);
59
- }
88
+ const { started, skipped } = typeof evidence === 'string' ? scanStartMarkers(evidence) : evidence;
60
89
  const names = (path, list) => {
61
90
  const base = basenameOf(path);
62
91
  return list.some((name) => name.includes(base));
@@ -82,15 +111,21 @@ export function countStartedFiles(output, requestedPaths) {
82
111
  * @param verdict - The classifier's verdict
83
112
  * @param output - Captured mach stdout and stderr
84
113
  * @param requestedPaths - Dispatched paths, in dispatch order
114
+ * @param tracked - Start markers collected from the complete stream (or
115
+ * the structured raw log); without them the capped capture is scanned
85
116
  */
86
- export function vetoIncompletePass(verdict, output, requestedPaths) {
117
+ export function vetoIncompletePass(verdict, output, requestedPaths, tracked) {
87
118
  if (verdict.kind !== 'tests-ran-ok')
88
119
  return verdict;
89
120
  const shutdownLine = output
90
121
  .split(/\r?\n/)
91
122
  .find((line) => SHUTDOWN_REENTRY_PATTERN.test(line))
92
123
  ?.trim();
93
- const counted = countStartedFiles(output, requestedPaths);
124
+ // Tracked markers win whenever they saw a start line at all. An empty
125
+ // tracker means nothing was streamed through it, and the capture is then
126
+ // the only evidence there is.
127
+ const useTracked = tracked !== undefined && tracked.markers.started.length > 0;
128
+ const counted = countStartedFiles(useTracked ? tracked.markers : output, requestedPaths);
94
129
  const unexpected = verdict.unexpected ?? 0;
95
130
  const truncated = counted?.firstUnstarted !== undefined;
96
131
  if (unexpected === 0 && shutdownLine === undefined && !truncated)
@@ -98,7 +133,12 @@ export function vetoIncompletePass(verdict, output, requestedPaths) {
98
133
  const evidence = {
99
134
  started: counted?.started ?? 0,
100
135
  requested: counted?.requested ?? 0,
101
- ...(counted?.firstUnstarted !== undefined ? { firstUnstarted: counted.firstUnstarted } : {}),
136
+ ...(counted?.firstUnstarted !== undefined
137
+ ? {
138
+ firstUnstarted: counted.firstUnstarted,
139
+ startedSource: useTracked ? tracked.source : 'capture',
140
+ }
141
+ : {}),
102
142
  ...(shutdownLine !== undefined ? { shutdownLine } : {}),
103
143
  ...(unexpected > 0 ? { unexpected } : {}),
104
144
  };
@@ -22,6 +22,8 @@ export interface XpcshellRetryOptions {
22
22
  kind?: MachTestSuiteKind | undefined;
23
23
  /** Whether the run was started with full harness output. */
24
24
  fullOutput?: boolean | undefined;
25
+ /** Per-chunk feed for the retried run's output (start-marker tracking). */
26
+ onOutputChunk?: ((stream: 'stdout' | 'stderr', chunk: string) => void) | undefined;
25
27
  }
26
28
  /**
27
29
  * Removes a stale xpcshell install symlink and retries the focused mach test
@@ -9,7 +9,7 @@ import { tryRepairStaleXpcshellTestSymlink } from './test-stale-symlink.js';
9
9
  * generic command.
10
10
  */
11
11
  export async function retryAfterXpcshellSymlinkRepair(options) {
12
- const { engineDir, objDir, result, classification, normalizedPaths, extraArgs, env, kind = 'test', fullOutput, } = options;
12
+ const { engineDir, objDir, result, classification, normalizedPaths, extraArgs, env, kind = 'test', fullOutput, onOutputChunk, } = options;
13
13
  if (result.exitCode !== 0 &&
14
14
  classification.xpcshell.length > 0 &&
15
15
  classification.nonXpcshell.length === 0) {
@@ -23,6 +23,7 @@ export async function retryAfterXpcshellSymlinkRepair(options) {
23
23
  args: extraArgs,
24
24
  env,
25
25
  fullOutput,
26
+ ...(onOutputChunk === undefined ? {} : { teardown: { onOutputChunk } }),
26
27
  });
27
28
  }
28
29
  }
@@ -7,9 +7,12 @@
7
7
  * every other theme resolves it to nothing.
8
8
  * - `token-undeclared`: a `var(--<prefix>…)` reference in the tokens CSS or
9
9
  * in a CSS file the patch queue touches names a token no block of the
10
- * tokens CSS declares. Same-file declarations, `furnace.json`
10
+ * tokens CSS declares. Same-file declarations, declarations of a sheet
11
+ * that loads beside it (see `token-sibling-sheets.ts`), `furnace.json`
11
12
  * `tokenAllowlist` and `runtimeVariables` are exempt, matching the
12
- * `token-prefix-violation` rule's notion of a runtime channel.
13
+ * `token-prefix-violation` rule's notion of a runtime channel. A
14
+ * reference with a fallback (`var(--x, 0)`) is optional by construction
15
+ * (a host hook, a channel set from JS) and is not reported.
13
16
  *
14
17
  * Built on `token-category.ts`'s base-block and comment-mask primitives, so
15
18
  * this report and `token add` agree on which block is the base.
@@ -8,9 +8,12 @@
8
8
  * every other theme resolves it to nothing.
9
9
  * - `token-undeclared`: a `var(--<prefix>…)` reference in the tokens CSS or
10
10
  * in a CSS file the patch queue touches names a token no block of the
11
- * tokens CSS declares. Same-file declarations, `furnace.json`
11
+ * tokens CSS declares. Same-file declarations, declarations of a sheet
12
+ * that loads beside it (see `token-sibling-sheets.ts`), `furnace.json`
12
13
  * `tokenAllowlist` and `runtimeVariables` are exempt, matching the
13
- * `token-prefix-violation` rule's notion of a runtime channel.
14
+ * `token-prefix-violation` rule's notion of a runtime channel. A
15
+ * reference with a fallback (`var(--x, 0)`) is optional by construction
16
+ * (a host hook, a channel set from JS) and is not reported.
14
17
  *
15
18
  * Built on `token-category.ts`'s base-block and comment-mask primitives, so
16
19
  * this report and `token add` agree on which block is the base.
@@ -104,8 +107,10 @@ export function lintUndeclaredTokenReferences(file, css, tokenPrefix, declared,
104
107
  const findings = [];
105
108
  const seen = new Set();
106
109
  for (const [index, line] of maskCommentLines(lines).entries()) {
107
- for (const match of line.matchAll(/var\(\s*(--[A-Za-z0-9_-]+)/g)) {
110
+ for (const match of line.matchAll(/var\(\s*(--[A-Za-z0-9_-]+)\s*(,)?/g)) {
108
111
  const name = match[1] ?? '';
112
+ if (match[2] !== undefined)
113
+ continue;
109
114
  if (!name.startsWith(tokenPrefix) || declared.has(name) || local.has(name))
110
115
  continue;
111
116
  if (exempt.has(name) || seen.has(name))
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Which stylesheets load together, so `token lint` can resolve a token one
3
+ * sheet references against the declarations of the sheets beside it.
4
+ *
5
+ * A widget sheet may read a token its host document's other sheet
6
+ * declares; judged alone it looks undeclared. Two sources say which sheets
7
+ * share a document:
8
+ *
9
+ * - links the queue's documents make: `<link rel="stylesheet">` (and
10
+ * `<html:link>`) and `<?xml-stylesheet?>` in markup and Lit templates,
11
+ * and CSS `@import`. A `chrome://` URL resolves through the jar.mn lines
12
+ * the queue adds; a relative URL resolves beside the document, and only
13
+ * to a sheet the queue touches.
14
+ * - `furnace.json#tokenSiblingSheets`: `{ "<glob>": ["<path or glob>"] }`,
15
+ * for pairings no link in the queue shows (an upstream host document).
16
+ *
17
+ * Sheets linked from one document are siblings of each other; an
18
+ * `@import` makes the importing and the imported sheet siblings.
19
+ */
20
+ /** The stylesheet URLs one document or sheet loads, in order. */
21
+ export declare function collectStylesheetUrls(file: string, content: string): string[];
22
+ /**
23
+ * Resolves a stylesheet URL to an engine-relative path, or undefined.
24
+ *
25
+ * @param url - The URL as written
26
+ * @param from - Engine-relative path of the document or sheet holding it
27
+ * @param jarTargets - jar target (`content/<pkg>/<path>`) → packaged source
28
+ * @param knownSheets - Sheets a relative URL may resolve to
29
+ */
30
+ export declare function resolveStylesheetUrl(url: string, from: string, jarTargets: ReadonlyMap<string, string>, knownSheets: ReadonlySet<string>): string | undefined;
31
+ /** Inputs of {@link buildSiblingSheetMap}. */
32
+ export interface SiblingSheetInputs {
33
+ /** Documents and sheets to read links from: engine-relative path and content. */
34
+ documents: Iterable<readonly [string, string]>;
35
+ /** jar target → packaged source, from the queue's jar.mn lines. */
36
+ jarTargets: ReadonlyMap<string, string>;
37
+ /** The sheets `token lint` judges. */
38
+ sheets: readonly string[];
39
+ /** `furnace.json#tokenSiblingSheets`. */
40
+ explicit?: Readonly<Record<string, readonly string[]>> | undefined;
41
+ }
42
+ /**
43
+ * Maps each sheet to the other sheets that load beside it. A sheet with no
44
+ * siblings is absent.
45
+ */
46
+ export declare function buildSiblingSheetMap(inputs: SiblingSheetInputs): Map<string, Set<string>>;
@@ -0,0 +1,119 @@
1
+ // SPDX-License-Identifier: EUPL-1.2
2
+ /**
3
+ * Which stylesheets load together, so `token lint` can resolve a token one
4
+ * sheet references against the declarations of the sheets beside it.
5
+ *
6
+ * A widget sheet may read a token its host document's other sheet
7
+ * declares; judged alone it looks undeclared. Two sources say which sheets
8
+ * share a document:
9
+ *
10
+ * - links the queue's documents make: `<link rel="stylesheet">` (and
11
+ * `<html:link>`) and `<?xml-stylesheet?>` in markup and Lit templates,
12
+ * and CSS `@import`. A `chrome://` URL resolves through the jar.mn lines
13
+ * the queue adds; a relative URL resolves beside the document, and only
14
+ * to a sheet the queue touches.
15
+ * - `furnace.json#tokenSiblingSheets`: `{ "<glob>": ["<path or glob>"] }`,
16
+ * for pairings no link in the queue shows (an upstream host document).
17
+ *
18
+ * Sheets linked from one document are siblings of each other; an
19
+ * `@import` makes the importing and the imported sheet siblings.
20
+ */
21
+ import { dirname, posix } from 'node:path';
22
+ import { matchesAnyGlob } from '../utils/path-glob.js';
23
+ import { normalizePathSlashes } from '../utils/paths.js';
24
+ const LINK_TAG = /<(?:html:)?link\b[^>]*>/gi;
25
+ const STYLESHEET_PI = /<\?xml-stylesheet\b[^?]*?href\s*=\s*["']([^"']+)["']/gi;
26
+ const CSS_IMPORT = /@import\s+(?:url\(\s*)?["']([^"']+)["']/gi;
27
+ /** The stylesheet URLs one document or sheet loads, in order. */
28
+ export function collectStylesheetUrls(file, content) {
29
+ const urls = [];
30
+ if (file.endsWith('.css')) {
31
+ for (const match of content.matchAll(CSS_IMPORT))
32
+ urls.push(match[1] ?? '');
33
+ return urls.filter((url) => url !== '');
34
+ }
35
+ for (const match of content.matchAll(LINK_TAG)) {
36
+ const tag = match[0];
37
+ if (!/\brel\s*=\s*["']stylesheet["']/i.test(tag))
38
+ continue;
39
+ const href = /\bhref\s*=\s*["']([^"'$]+)["']/i.exec(tag)?.[1];
40
+ if (href !== undefined)
41
+ urls.push(href);
42
+ }
43
+ for (const match of content.matchAll(STYLESHEET_PI))
44
+ urls.push(match[1] ?? '');
45
+ return urls.filter((url) => url.endsWith('.css'));
46
+ }
47
+ /**
48
+ * Resolves a stylesheet URL to an engine-relative path, or undefined.
49
+ *
50
+ * @param url - The URL as written
51
+ * @param from - Engine-relative path of the document or sheet holding it
52
+ * @param jarTargets - jar target (`content/<pkg>/<path>`) → packaged source
53
+ * @param knownSheets - Sheets a relative URL may resolve to
54
+ */
55
+ export function resolveStylesheetUrl(url, from, jarTargets, knownSheets) {
56
+ const chrome = /^chrome:\/\/([\w.-]+)\/(content|skin|locale)\/(.+)$/.exec(url);
57
+ if (chrome !== null) {
58
+ const [, pkg = '', kind = '', path = ''] = chrome;
59
+ const candidates = kind === 'skin'
60
+ ? [`skin/classic/${pkg}/${path}`, `skin/${pkg}/${path}`]
61
+ : [`${kind}/${pkg}/${path}`];
62
+ for (const target of candidates) {
63
+ const source = jarTargets.get(target);
64
+ if (source !== undefined)
65
+ return source;
66
+ }
67
+ return undefined;
68
+ }
69
+ if (/^[a-z][\w+.-]*:/i.test(url))
70
+ return undefined;
71
+ const base = normalizePathSlashes(dirname(from));
72
+ const resolved = posix.normalize(posix.join(base === '.' ? '' : base, url));
73
+ return knownSheets.has(resolved) ? resolved : undefined;
74
+ }
75
+ /**
76
+ * Maps each sheet to the other sheets that load beside it. A sheet with no
77
+ * siblings is absent.
78
+ */
79
+ export function buildSiblingSheetMap(inputs) {
80
+ const known = new Set(inputs.sheets);
81
+ const siblings = new Map();
82
+ const link = (group) => {
83
+ for (const sheet of group) {
84
+ const set = siblings.get(sheet) ?? new Set();
85
+ for (const other of group)
86
+ if (other !== sheet)
87
+ set.add(other);
88
+ if (set.size > 0)
89
+ siblings.set(sheet, set);
90
+ }
91
+ };
92
+ for (const [file, content] of inputs.documents) {
93
+ const linked = collectStylesheetUrls(file, content)
94
+ .map((url) => resolveStylesheetUrl(url, file, inputs.jarTargets, known))
95
+ .filter((sheet) => sheet !== undefined);
96
+ // An @import pairs the importing sheet with what it imports.
97
+ link(file.endsWith('.css') ? [file, ...linked] : linked);
98
+ }
99
+ for (const [pattern, partners] of Object.entries(inputs.explicit ?? {})) {
100
+ const owners = inputs.sheets.filter((sheet) => matchesAnyGlob(sheet, [pattern]));
101
+ for (const owner of owners) {
102
+ const set = siblings.get(owner) ?? new Set();
103
+ for (const partner of partners) {
104
+ if (/[*?]/.test(partner)) {
105
+ for (const sheet of inputs.sheets) {
106
+ if (sheet !== owner && matchesAnyGlob(sheet, [partner]))
107
+ set.add(sheet);
108
+ }
109
+ }
110
+ else if (partner !== owner) {
111
+ set.add(partner);
112
+ }
113
+ }
114
+ if (set.size > 0)
115
+ siblings.set(owner, set);
116
+ }
117
+ }
118
+ return siblings;
119
+ }
@@ -36,6 +36,8 @@ export const TREE_COMMAND_VERDICTS = {
36
36
  export: 'conditional',
37
37
  'export-all': 'conditional',
38
38
  're-export': 'conditional',
39
+ // Parks live in the primary tree's .fireforge/ and rewrite engine files.
40
+ park: 'refused',
39
41
  patch: 'refused',
40
42
  rebase: 'refused',
41
43
  package: 'refused',
@@ -81,5 +81,9 @@ export interface ComposedShim {
81
81
  * @param projectRoot - Absolute project root, used to resolve the relative
82
82
  * shim path
83
83
  * @param extraShimPath - Optional project-relative path to an extra `.d.ts`
84
+ * @param options - `litTypes` appends {@link LIT_TYPES_SHIM} after the
85
+ * built-in shim (before the extra shim, which can still merge into it)
84
86
  */
85
- export declare function composeShimSource(projectRoot: string, extraShimPath: string | undefined): Promise<ComposedShim>;
87
+ export declare function composeShimSource(projectRoot: string, extraShimPath: string | undefined, options?: {
88
+ litTypes?: boolean | undefined;
89
+ }): Promise<ComposedShim>;
@@ -289,6 +289,117 @@ export const UNDEFINED_IDENTIFIER_CODES = new Set([
289
289
  2304, // Cannot find name '{0}'.
290
290
  2552, // Cannot find name '{0}'. Did you mean '{1}'?
291
291
  ]);
292
+ /**
293
+ * Typed Lit, opt-in through `typecheck.litTypes`. Declares the two chrome
294
+ * modules widgets import Lit from, so they no longer fall to the
295
+ * `chrome:*` wildcard as `any`: `LitElement` (with `ReactiveElement`'s
296
+ * lifecycle) and `MozLitElement` carry closed member lists, so a misspelt
297
+ * member of a widget host is TS2339, as `Cu` is in the built-in shim.
298
+ * Template helpers and directives stay loose. A project shim can merge
299
+ * members into `LitElementShimMembers`; a project whose jsconfig `paths`
300
+ * maps these URLs to the real sources gets those instead, since a resolved
301
+ * file wins over an ambient module.
302
+ */
303
+ const LIT_TYPES_SHIM = `
304
+ // ── FireForge typed Lit (typecheck.litTypes) ──
305
+ interface LitPropertyDeclarationShim {
306
+ type?: unknown;
307
+ attribute?: boolean | string;
308
+ reflect?: boolean;
309
+ state?: boolean;
310
+ noAccessor?: boolean;
311
+ converter?: unknown;
312
+ hasChanged?(value: unknown, oldValue: unknown): boolean;
313
+ fluent?: boolean;
314
+ }
315
+ interface LitElementShimMembers {
316
+ readonly renderRoot: HTMLElement | DocumentFragment;
317
+ readonly isUpdatePending: boolean;
318
+ readonly hasUpdated: boolean;
319
+ readonly updateComplete: Promise<boolean>;
320
+ renderOptions: any;
321
+ requestUpdate(name?: PropertyKey, oldValue?: unknown, options?: LitPropertyDeclarationShim): void;
322
+ addController(controller: any): void;
323
+ removeController(controller: any): void;
324
+ connectedCallback(): void;
325
+ disconnectedCallback(): void;
326
+ attributeChangedCallback(name: string, oldValue: string | null, value: string | null): void;
327
+ createRenderRoot(): HTMLElement | DocumentFragment;
328
+ enableUpdating(requestedUpdate: boolean): void;
329
+ scheduleUpdate(): void | Promise<unknown>;
330
+ performUpdate(): void;
331
+ getUpdateComplete(): Promise<boolean>;
332
+ shouldUpdate(changedProperties: Map<PropertyKey, unknown>): boolean;
333
+ willUpdate(changedProperties: Map<PropertyKey, unknown>): void;
334
+ update(changedProperties: Map<PropertyKey, unknown>): void;
335
+ render(): unknown;
336
+ firstUpdated(changedProperties: Map<PropertyKey, unknown>): void;
337
+ updated(changedProperties: Map<PropertyKey, unknown>): void;
338
+ }
339
+ declare module 'chrome://global/content/vendor/lit.all.mjs' {
340
+ export class ReactiveElement extends HTMLElement {
341
+ static properties: Record<string, LitPropertyDeclarationShim>;
342
+ static styles: any;
343
+ static shadowRootOptions: ShadowRootInit;
344
+ static readonly observedAttributes: string[];
345
+ static createProperty(name: PropertyKey, options?: LitPropertyDeclarationShim): void;
346
+ static addInitializer(initializer: (element: ReactiveElement) => void): void;
347
+ }
348
+ export interface ReactiveElement extends LitElementShimMembers {}
349
+ export class LitElement extends ReactiveElement {}
350
+ export const html: (strings: TemplateStringsArray, ...values: unknown[]) => any;
351
+ export const svg: (strings: TemplateStringsArray, ...values: unknown[]) => any;
352
+ export const css: (strings: TemplateStringsArray, ...values: unknown[]) => any;
353
+ export const nothing: any;
354
+ export const noChange: any;
355
+ export const render: any;
356
+ export const unsafeCSS: any;
357
+ export const classMap: any;
358
+ export const styleMap: any;
359
+ export const ifDefined: any;
360
+ export const repeat: any;
361
+ export const when: any;
362
+ export const map: any;
363
+ export const live: any;
364
+ export const ref: any;
365
+ export const createRef: any;
366
+ export const until: any;
367
+ export const guard: any;
368
+ export const choose: any;
369
+ export const keyed: any;
370
+ export const cache: any;
371
+ export const join: any;
372
+ export const range: any;
373
+ export const unsafeHTML: any;
374
+ export const unsafeSVG: any;
375
+ export const literal: any;
376
+ export const unsafeStatic: any;
377
+ export const staticHtml: any;
378
+ export const staticSvg: any;
379
+ export const directive: any;
380
+ export const Directive: any;
381
+ export const AsyncDirective: any;
382
+ export const PartType: any;
383
+ export const defaultConverter: any;
384
+ export const notEqual: any;
385
+ export const adoptStyles: any;
386
+ export const supportsAdoptingStyleSheets: boolean;
387
+ export const CSSResult: any;
388
+ export const isServer: boolean;
389
+ }
390
+ declare module 'chrome://global/content/lit-utils.mjs' {
391
+ import { LitElement } from 'chrome://global/content/vendor/lit.all.mjs';
392
+ export class MozLitElement extends LitElement {
393
+ static queries: Record<string, string | Record<string, unknown>>;
394
+ static fragment: unknown;
395
+ dispatchOnUpdateComplete(event: Event): Promise<void>;
396
+ }
397
+ export const MozBaseInputElement: any;
398
+ export const MozBoolInputElement: any;
399
+ export const SelectControlBaseElement: any;
400
+ export const SelectControlItemMixin: any;
401
+ }
402
+ `;
292
403
  /** Hint appended to reported undefined-identifier diagnostics. */
293
404
  export const UNDEFINED_IDENTIFIER_HINT = '(undefined identifier — import or declare it, add the global to the extra shim, ' +
294
405
  'or tune the "undefinedIdentifiers" setting)';
@@ -350,9 +461,11 @@ async function inlineTripleSlashReferences(source, baseDir, seen) {
350
461
  * @param projectRoot - Absolute project root, used to resolve the relative
351
462
  * shim path
352
463
  * @param extraShimPath - Optional project-relative path to an extra `.d.ts`
464
+ * @param options - `litTypes` appends {@link LIT_TYPES_SHIM} after the
465
+ * built-in shim (before the extra shim, which can still merge into it)
353
466
  */
354
- export async function composeShimSource(projectRoot, extraShimPath) {
355
- const base = FIREFOX_GLOBALS_SHIM;
467
+ export async function composeShimSource(projectRoot, extraShimPath, options = {}) {
468
+ const base = options.litTypes === true ? `${FIREFOX_GLOBALS_SHIM}\n${LIT_TYPES_SHIM}` : FIREFOX_GLOBALS_SHIM;
356
469
  if (!extraShimPath) {
357
470
  return { source: base, extraShimAppended: false };
358
471
  }
@@ -102,7 +102,9 @@ export async function runTypecheck(projectRoot, cfg, runOptions = {}) {
102
102
  const cached = shimCache.get(key);
103
103
  if (cached !== undefined)
104
104
  return cached;
105
- const composed = await composeShimSource(projectRoot, extraShim);
105
+ const composed = await composeShimSource(projectRoot, extraShim, {
106
+ litTypes: cfg.litTypes,
107
+ });
106
108
  if (composed.extraShimAppended) {
107
109
  verbose(`typecheck: extra shim ${extraShim ?? ''} appended to Firefox globals shim`);
108
110
  }
@@ -24,13 +24,19 @@ export { ensureFurnaceConfig, loadFurnaceConfig, loadFurnaceState, saveFurnaceSt
24
24
  export { validateAllComponents, validateComponent } from './core/furnace-validate.js';
25
25
  export type { PatchSizeThresholds, PatchSizeTierDecision } from './core/patch-lint.js';
26
26
  export { countNonBinaryDiffLines, filesMeasuredByFileTooLarge, getPatchSizeThresholds, isTestFile, resolvePatchSizeTier, } from './core/patch-lint.js';
27
- export type { CodeLineCount } from './core/patch-lint-code-lines.js';
28
- export { countCodeLines } from './core/patch-lint-code-lines.js';
27
+ export type { CodeLineCount, CodeLineMask } from './core/patch-lint-code-lines.js';
28
+ export { codeLineMask, countCodeLines } from './core/patch-lint-code-lines.js';
29
29
  export type { ResolvedFileSizeTier } from './core/patch-lint-file-size.js';
30
30
  export { resolveFileSizeThresholds } from './core/patch-lint-file-size.js';
31
+ export type { PatchSizeMeasurement } from './core/patch-lint-size.js';
32
+ export { measurePatchSize } from './core/patch-lint-size.js';
31
33
  export type { ResolvedPatchFilesTier } from './core/patch-lint-size-thresholds.js';
34
+ export { isPatchSizeRegistrationFile } from './core/patch-lint-size-thresholds.js';
35
+ export type { PatchPolicyIssue, PatchPolicyIssueCode } from './core/patch-policy.js';
36
+ export { evaluatePatchPolicyContentForQueue } from './core/patch-policy-content.js';
32
37
  export type { AddTokenOptions, AddTokenResult, TokenMode } from './core/token-manager.js';
33
38
  export { addToken, getTokensCssPath, validateTokenAdd } from './core/token-manager.js';
34
39
  export { CancellationError, CommandError, FireForgeError, GeneralError, InvalidArgumentError, ResolutionError, } from './errors/base.js';
35
40
  export { ExitCode } from './errors/codes.js';
36
- export type { ApplyResult, BuildConfig, ComponentType, CustomComponentConfig, DryRunAction, FireForgeConfig, FirefoxConfig, FirefoxProduct, FurnaceConfig, FurnaceState, OverrideComponentConfig, OverrideType, PatchLintFileSizeThresholds, PatchLintFileSizeTier, ProjectLicense, StepError, ValidationIssue, WireConfig, } from './types/index.js';
41
+ export type { PatchesManifest, PatchMetadata } from './types/commands/index.js';
42
+ export type { ApplyResult, BuildConfig, ComponentType, CustomComponentConfig, DryRunAction, FireForgeConfig, FirefoxConfig, FirefoxProduct, FurnaceConfig, FurnaceState, OverrideComponentConfig, OverrideType, PatchLintFileSizeThresholds, PatchLintFileSizeTier, PatchLintPatchSizeMetric, ProjectLicense, StepError, ValidationIssue, WireConfig, } from './types/index.js';
package/dist/src/index.js CHANGED
@@ -22,8 +22,11 @@ export { applyAllComponents } from './core/furnace-apply.js';
22
22
  export { ensureFurnaceConfig, loadFurnaceConfig, loadFurnaceState, saveFurnaceState, validateFurnaceConfig, } from './core/furnace-config.js';
23
23
  export { validateAllComponents, validateComponent } from './core/furnace-validate.js';
24
24
  export { countNonBinaryDiffLines, filesMeasuredByFileTooLarge, getPatchSizeThresholds, isTestFile, resolvePatchSizeTier, } from './core/patch-lint.js';
25
- export { countCodeLines } from './core/patch-lint-code-lines.js';
25
+ export { codeLineMask, countCodeLines } from './core/patch-lint-code-lines.js';
26
26
  export { resolveFileSizeThresholds } from './core/patch-lint-file-size.js';
27
+ export { measurePatchSize } from './core/patch-lint-size.js';
28
+ export { isPatchSizeRegistrationFile } from './core/patch-lint-size-thresholds.js';
29
+ export { evaluatePatchPolicyContentForQueue } from './core/patch-policy-content.js';
27
30
  export { addToken, getTokensCssPath, validateTokenAdd } from './core/token-manager.js';
28
31
  export { CancellationError, CommandError, FireForgeError, GeneralError, InvalidArgumentError, ResolutionError, } from './errors/base.js';
29
32
  export { ExitCode } from './errors/codes.js';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Re-exports all command-related types from focused sub-modules.
3
3
  */
4
- export type { BuildOptions, DiscardOptions, DoctorOptions, DownloadOptions, ExportOptions, FurnaceApplyOptions, FurnaceCreateOptions, FurnaceDeployOptions, FurnaceLockWaitable, FurnaceOverrideOptions, FurnacePreviewOptions, FurnaceRefreshOptions, FurnaceRemoveOptions, FurnaceRenameOptions, FurnaceSyncOptions, FurnaceValidateOptions, ImportOptions, LintCommandOptions, PackageOptions, PatchCompactOptions, PatchDeleteOptions, PatchLintIgnoreOptions, PatchMoveFilesOptions, PatchRenameOptions, PatchReorderOptions, PatchRetireOptions, PatchSplitOptions, PatchStagedDependencyOptions, PatchTierOptions, RebaseOptions, ReExportOptions, RegisterOptions, ResetOptions, RunOptions, SetupOptions, SourceSetOptions, StatusOptions, TestOptions, TokenAddOptions, WireOptions, } from './options.js';
5
- export type { ImportSummary, LintIgnoreCeiling, LintIgnoreEntry, PatchCategory, PatchesManifest, PatchInfo, PatchLintIssue, PatchLintStagedDeclaration, PatchMetadata, PatchResult, PatchRetiredSlot, PatchStagedDependencies, PatchStagedForwardImport, PatchStagedRegistration, } from './patches.js';
4
+ export type { BuildOptions, DiscardOptions, DoctorOptions, DownloadOptions, ExportOptions, FurnaceApplyOptions, FurnaceCreateOptions, FurnaceDeployOptions, FurnaceLockWaitable, FurnaceOverrideOptions, FurnacePreviewOptions, FurnaceRefreshOptions, FurnaceRemoveOptions, FurnaceRenameOptions, FurnaceSyncOptions, FurnaceValidateOptions, ImportOptions, LintCommandOptions, PackageOptions, PatchCompactOptions, PatchDeleteOptions, PatchLintIgnoreOptions, PatchMoveFilesOptions, PatchRenameOptions, PatchReorderOptions, PatchReserveOptions, PatchRetireOptions, PatchSplitOptions, PatchStagedDependencyOptions, PatchStageOptions, PatchTierOptions, RebaseOptions, ReExportOptions, RegisterOptions, ResetOptions, RunOptions, SetupOptions, SourceSetOptions, StatusOptions, TestOptions, TokenAddOptions, WireOptions, } from './options.js';
5
+ export type { ImportSummary, LintIgnoreCeiling, LintIgnoreEntry, PatchCategory, PatchesManifest, PatchInfo, PatchLintIssue, PatchLintStagedDeclaration, PatchMetadata, PatchReservedSlot, PatchResult, PatchRetiredSlot, PatchSizeShare, PatchStagedDependencies, PatchStagedForwardImport, PatchStagedRegistration, } from './patches.js';
6
6
  export type { DoctorCheck, TokenCoverageFileEntry, TokenCoverageReport } from './project.js';