@hominis/fireforge 0.15.5 → 0.15.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.
package/CHANGELOG.md CHANGED
@@ -43,6 +43,9 @@
43
43
  - Same-basename collisions in `dist/` are now disambiguated by trailing-segment overlap: a branding override at `engine/browser/branding/<name>/content/aboutDialog.css` (which ships at `chrome/<area>/content/branding/aboutDialog.css`) no longer gets matched against the unrelated upstream `chrome/<area>/content/browser/aboutDialog.css`. The scorer rewards candidates whose path contains meaningful intermediate segments from the source (e.g. the `branding` segment) so re-rooted artifacts win over coincidentally-named ones. Generic segments like `content` / `chrome` / `bin` do not count toward the bonus to avoid breaking ties on noise.
44
44
  - Test sources (anything under `/test(s)/`, plus `browser_*.js` / `test_*.js` / `xpcshell.toml` / `browser.ini`) are now resolved against the `_tests/` tree under the active `obj-*` directory instead of `dist/`. Mochitest and xpcshell harnesses copy registered tests under `_tests/testing/...`, never into the packaged bundle, so the previous dist-only walk false-flagged every registered test as "missing packaged artifact". Misses still warn — but they now point at `_tests/`, directing the operator to `BROWSER_CHROME_MANIFESTS` / `XPCSHELL_TESTS_MANIFESTS` instead of `package-manifest.in`.
45
45
  - Files inside an `if CONFIG[…]:` block in their owning `moz.build` are now skipped on hosts where the gate evaluates off (Windows-only stubinstaller CSS on a macOS build, Darwin-only artwork on Linux, etc.). The detection walks up from the source file to the closest `moz.build`, scans for the basename inside a Python-style indented `if CONFIG[…]:` block, and matches the gate against the host platform via `getPlatform()`. Negation expressions (`!= "WINNT"`, `not CONFIG[…]`) are conservatively NOT treated as single-OS gates, so we never wrongly suppress a warning for a file that should ship on the current host. Lives in the new `src/core/build-audit-platform.ts`.
46
+ - Platform-gate detection now also covers subtrees packaged through platform-specific `Makefile.in` recipes that live outside the `moz.build` graph. Paths under `/stubinstaller/` (Windows NSIS stub installer), `browser/installer/windows/`, `browser/installer/macosx/`, and `browser/installer/linux/` count as host-gated by path convention on hosts where the target platform does not match. Previously the audit warned on every touched branding stubinstaller CSS on every non-Windows build because no ancestor `moz.build` wrapped those files in an `if CONFIG[…]:` block — the packaging trigger is `browser/installer/windows/Makefile.in` / `nsis/stub.nsh`, which the scanner does not parse. An explicit moz.build gate still wins if one is present, so fork-specific overrides behave as before. Surfaced as two warnings per macOS build before the fix.
47
+ - Test-path audits are now gated on the `_tests/all-tests.json` marker file that `mach package-tests` writes. Plain `mach build` populates a partial `_tests/` subtree and stops, so every correctly-registered mochitest / xpcshell source was false-flagged as "missing packaged artifact" on the common build-only path. The audit now checks for the marker and silently skips test-path sources when the marker is absent — operators who want green-checked test registrations run `cd engine && ./mach package-tests` or a scoped `fireforge test <name>` after the build. Surfaced as 24 warnings per build (one per registered mochitest / xpcshell source) before the fix.
48
+ - Stale-artifact warnings now require the matched candidate to be structurally related to the source: either the immediate parent directory trail-matches, or a non-generic source segment (`branding`, the fork's own directory name) appears mid-candidate. Same-basename hits in unrelated subtrees — the motivating case: `engine/browser/modules/<name>/test/head.js` matching the upstream `_tests/xpcshell/dom/quota/test/xpcshell/common/head.js` — are now classified as `missing` with a warning that names the unrelated candidate, rather than a `stale` warning that reads as "your build dropped this file" when in fact the match is spurious. The confidence check only kicks in when staleness would otherwise fire, so `updated` classifications keep their current loose matching. Generic directory segments (`test`, `tests`, `unit`, `common`, `xpcshell`, `mochitest` plus the existing list) no longer contribute to the structural-match bonus so trailing-segment spoofs (a shared `test` / `xpcshell` segment on an unrelated file) are rejected.
46
49
  - Ends every build with a `Packaged: N updated, M stale, K missing, S skipped` summary so operators can distinguish a fast-because-incremental build from a fast-because-silently-skipped one without a post-build `find`.
47
50
  - `fireforge build` auto-runs `mach configure` before the mach build step when any `moz.build`, `moz.configure`, or `Makefile.in` changed since the last successful build. Prevents the stale-backend trap where an incremental build skips work against a recursive-make backend that no longer matches the source tree. Emits a `Backend config changed; running mach configure first...` banner so the extra step is visible, and continues the build even if configure exits non-zero.
48
51
  - Mach build failures with known-cryptic mozbuild errors now print actionable hints. First entry in the table: `mozbuild.preprocessor.Preprocessor.Error: no preprocessor directives found` prints `Use JS_PREFERENCE_FILES instead, or add at least one #filter / #expand directive to the file.` The hint table lives in `src/core/mach-error-hints.ts` and is extensible — new cryptic errors we diagnose get one-line hints added without touching the build wrapper.
package/README.md CHANGED
@@ -398,12 +398,14 @@ The summary line splits counts — e.g. `Lint: 2 introduced error(s), 0 introduc
398
398
 
399
399
  `fireforge build` is a transactional step: after a successful mach build it audits the dist bundle against engine-relative paths touched since the last successful build, and warns per file that is packageable-by-convention (`.js`/`.mjs`/`.css`/`.ftl`/`.xhtml`/`app/profile/…`) but has no matching artifact or whose dist mtime is older than the source. Ends every build with a `Packaged: N updated, M stale, K missing, S skipped` summary. The audit is warn-only — it never fails a build that mach reported green.
400
400
 
401
- The audit applies four routing rules to suppress false positives that previously trained operators to ignore its warnings:
401
+ The audit applies six routing rules to suppress false positives that previously trained operators to ignore its warnings:
402
402
 
403
403
  - **Build inputs are excluded.** `jar.mn`, `moz.build`, `moz.configure`, `Makefile.in`, and `mozbuild.in` are consumed by the build to produce chrome registrations / make targets but never themselves ship. They are skipped before the dist lookup, so editing them no longer fires a "missing packaged artifact" warning.
404
404
  - **Same-basename collisions in `dist/` are disambiguated by trailing-segment overlap.** A branding override at `engine/browser/branding/<name>/content/aboutDialog.css` ships at `chrome/<area>/content/branding/aboutDialog.css`. A naive basename match would tie that against the unrelated upstream `chrome/<area>/content/browser/aboutDialog.css`; the audit now scores candidates by trailing path-segment match plus a small bonus for non-generic source segments (`branding`, the branding directory name) appearing in the candidate path, so re-rooted artifacts win over coincidentally-named ones.
405
+ - **Unrelated same-basename hits never surface as "stale".** When the best-scoring candidate shares only the basename with the source and no meaningful intermediate segment (common on sparsely-populated `_tests/` trees where an upstream helper like `head.js` is the only same-basename file left from a prior build), the audit classifies the file as `missing` rather than emitting a misleading stale-comparison warning against the unrelated candidate. The warning names the unrelated file so the operator can confirm the mismatch at a glance.
405
406
  - **Test sources are looked up under `_tests/`, not `dist/`.** Anything under `/test(s)/` directories, plus `browser_*.js` / `test_*.js` / `xpcshell.toml` / `browser.ini`, is resolved against the `_tests/` tree under the active `obj-*` directory. Mochitest and xpcshell harnesses copy registered tests there, never into the packaged bundle. Misses still warn — but they point at `_tests/`, directing the operator to `BROWSER_CHROME_MANIFESTS` / `XPCSHELL_TESTS_MANIFESTS` instead of `package-manifest.in`.
406
- - **Files inside an `if CONFIG[…]:` block in their owning `moz.build` are skipped on hosts where the gate is off.** Windows-only stubinstaller CSS on a macOS build, Darwin-only artwork on Linux, etc. The detection walks up to the closest `moz.build`, scans for the basename inside a Python-style indented `if CONFIG[…]:` block, and matches the gate against the host platform. Negation expressions are conservatively NOT treated as single-OS gates so a warning is never wrongly suppressed for a file that should ship on the current host.
407
+ - **Test-path audits are gated on `_tests/all-tests.json`.** Plain `mach build` populates a partial `_tests/` subtree and stops full test packaging only runs under `mach package-tests` / `mach test <target>` (or `fireforge test <name>`). The audit now checks for the `all-tests.json` marker written by the packaged-tests make target and silently skips test-path sources when the marker is absent, so every registered mochitest / xpcshell source no longer false-flags as "missing" on the common build-only path. Run `cd engine && ./mach package-tests` (or a scoped `fireforge test`) after a build to green-check test registrations.
408
+ - **Files inside an `if CONFIG[…]:` block in their owning `moz.build` are skipped on hosts where the gate is off.** Windows-only stubinstaller CSS on a macOS build, Darwin-only artwork on Linux, etc. The detection walks up to the closest `moz.build`, scans for the basename inside a Python-style indented `if CONFIG[…]:` block, and matches the gate against the host platform. Negation expressions are conservatively NOT treated as single-OS gates so a warning is never wrongly suppressed for a file that should ship on the current host. Subtrees packaged through platform-specific `Makefile.in` recipes that live outside the `moz.build` graph — `/stubinstaller/` (NSIS), `browser/installer/windows/`, `browser/installer/macosx/`, `browser/installer/linux/` — are also gated by path convention so branding stubinstaller CSS no longer warns on every non-Windows build.
407
409
 
408
410
  The build also auto-runs `mach configure` before the mach build step when any `moz.build`, `moz.configure`, or `Makefile.in` changed since the last successful build. Prevents incremental builds from silently skipping work against a stale recursive-make backend. Emits a `Backend config changed; running mach configure first...` banner when it fires.
409
411
 
@@ -24,7 +24,9 @@ export interface PlatformGateResult {
24
24
  export declare function findEnclosingGate(content: string, basename: string): string | undefined;
25
25
  /**
26
26
  * Determines whether the given source file is gated off on the current
27
- * host by an enclosing `if CONFIG[...]:` block in its owning moz.build.
27
+ * host by an enclosing `if CONFIG[...]:` block in its owning moz.build,
28
+ * OR by a path-convention rule for installer-tree subdirectories that
29
+ * are packaged via Makefile.in recipes the audit does not parse.
28
30
  * Returns `gatedOff: false` and no expression when no gate is found —
29
31
  * the file is not platform-restricted, so the caller should audit it
30
32
  * normally.
@@ -10,10 +10,23 @@
10
10
  * detection, the audit fires a "missing packaged artifact" warning for
11
11
  * every gated file on every off-platform build — pure noise.
12
12
  *
13
+ * Two gate sources are consulted, in order:
14
+ * 1. Python-style `if CONFIG[...]:` blocks in the owning `moz.build`.
15
+ * 2. Path-convention gates — certain directory fragments are packaged
16
+ * by platform-specific Makefile.in / NSIS recipes that FireForge
17
+ * does not parse, so a file living under `browser/installer/windows/`
18
+ * or any `/stubinstaller/` subtree is Windows-only regardless of
19
+ * what its nearest moz.build says. (The branding stubinstaller CSS
20
+ * is the motivating case: referenced from
21
+ * `browser/installer/windows/Makefile.in` / `nsis/stub.nsh` with no
22
+ * `if CONFIG[…]:` in any moz.build ancestor.)
23
+ *
13
24
  * The detection is intentionally lightweight: we walk up from the
14
25
  * source file looking for the closest `moz.build`, scan it for an
15
26
  * occurrence of the source basename inside an `if CONFIG[...]:` block,
16
27
  * and check whether the gate expression matches the host platform.
28
+ * The path-convention pass kicks in only when no moz.build gate is
29
+ * found, so an explicit moz.build gate always wins.
17
30
  *
18
31
  * This is best-effort. False negatives (we miss a gate and warn anyway)
19
32
  * are tolerable — the audit is warn-only. False positives (we wrongly
@@ -128,9 +141,58 @@ export function findEnclosingGate(content, basename) {
128
141
  }
129
142
  return undefined;
130
143
  }
144
+ /**
145
+ * Path-convention gates: directories whose files are packaged by
146
+ * platform-specific build recipes (NSIS stub installer, DMG creation,
147
+ * Linux installer scripts) that live outside the moz.build graph. A
148
+ * file under any of these fragments is platform-restricted regardless
149
+ * of what its nearest `moz.build` says.
150
+ *
151
+ * `stubinstaller/` is the Windows NSIS stub installer asset tree. It
152
+ * is referenced from `browser/installer/windows/Makefile.in` (via
153
+ * `FILES` / `_WIDGET_FILES` lists) and `nsis/stub.nsh`, never through
154
+ * an `if CONFIG[…]:` block an ancestor moz.build exposes. Without
155
+ * this path-level gate, the audit warns on every touched branding
156
+ * stubinstaller CSS on every non-Windows build.
157
+ */
158
+ const PATH_GATES = [
159
+ { fragment: '/stubinstaller/', platform: 'win32', label: 'path convention: /stubinstaller/' },
160
+ {
161
+ fragment: '/browser/installer/windows/',
162
+ platform: 'win32',
163
+ label: 'path convention: browser/installer/windows/',
164
+ },
165
+ {
166
+ fragment: '/browser/installer/macosx/',
167
+ platform: 'darwin',
168
+ label: 'path convention: browser/installer/macosx/',
169
+ },
170
+ {
171
+ fragment: '/browser/installer/linux/',
172
+ platform: 'linux',
173
+ label: 'path convention: browser/installer/linux/',
174
+ },
175
+ ];
176
+ /**
177
+ * Returns a path-convention gate for `sourcePath` when one applies.
178
+ * Leading slash added so `startsWith`-style prefix traps
179
+ * (`browser/installer/windows/…`) match whether or not the input
180
+ * starts with a separator.
181
+ */
182
+ function findPathConventionGate(sourcePath) {
183
+ const normalised = `/${sourcePath}`.replace(/\/+/g, '/');
184
+ for (const entry of PATH_GATES) {
185
+ if (normalised.includes(entry.fragment)) {
186
+ return { platform: entry.platform, label: entry.label };
187
+ }
188
+ }
189
+ return undefined;
190
+ }
131
191
  /**
132
192
  * Determines whether the given source file is gated off on the current
133
- * host by an enclosing `if CONFIG[...]:` block in its owning moz.build.
193
+ * host by an enclosing `if CONFIG[...]:` block in its owning moz.build,
194
+ * OR by a path-convention rule for installer-tree subdirectories that
195
+ * are packaged via Makefile.in recipes the audit does not parse.
134
196
  * Returns `gatedOff: false` and no expression when no gate is found —
135
197
  * the file is not platform-restricted, so the caller should audit it
136
198
  * normally.
@@ -140,31 +202,36 @@ export function findEnclosingGate(content, basename) {
140
202
  * @returns Detection result
141
203
  */
142
204
  export async function detectPlatformGate(engineDir, sourcePath) {
143
- const sourceDir = dirname(join(engineDir, sourcePath));
144
- const mozBuild = await findOwningMozBuild(engineDir, sourceDir);
145
- if (!mozBuild)
146
- return { gatedOff: false };
147
- let content;
148
- try {
149
- content = await readText(mozBuild);
150
- }
151
- catch {
152
- return { gatedOff: false };
153
- }
154
- const sourceBasename = sourcePath.split('/').pop() ?? '';
155
- const expression = findEnclosingGate(content, sourceBasename);
156
- if (!expression)
157
- return { gatedOff: false };
158
205
  let host;
159
206
  try {
160
207
  host = getPlatform();
161
208
  }
162
209
  catch {
163
- return { gatedOff: false };
210
+ host = undefined;
211
+ }
212
+ const sourceDir = dirname(join(engineDir, sourcePath));
213
+ const mozBuild = await findOwningMozBuild(engineDir, sourceDir);
214
+ if (mozBuild) {
215
+ let content;
216
+ try {
217
+ content = await readText(mozBuild);
218
+ }
219
+ catch {
220
+ content = '';
221
+ }
222
+ const sourceBasename = sourcePath.split('/').pop() ?? '';
223
+ const expression = findEnclosingGate(content, sourceBasename);
224
+ if (expression) {
225
+ if (host && isGateOffHost(expression, host)) {
226
+ return { gatedOff: true, gateExpression: expression };
227
+ }
228
+ return { gatedOff: false, gateExpression: expression };
229
+ }
164
230
  }
165
- if (isGateOffHost(expression, host)) {
166
- return { gatedOff: true, gateExpression: expression };
231
+ const pathGate = findPathConventionGate(sourcePath);
232
+ if (pathGate && host && host !== pathGate.platform) {
233
+ return { gatedOff: true, gateExpression: pathGate.label };
167
234
  }
168
- return { gatedOff: false, gateExpression: expression };
235
+ return { gatedOff: false };
169
236
  }
170
237
  //# sourceMappingURL=build-audit-platform.js.map
@@ -39,7 +39,7 @@ import { toError } from '../utils/errors.js';
39
39
  import { pathExists } from '../utils/fs.js';
40
40
  import { info, verbose, warn } from '../utils/logger.js';
41
41
  import { detectPlatformGate } from './build-audit-platform.js';
42
- import { isTestPath, resolveBestArtifact } from './build-audit-resolve.js';
42
+ import { countTrailingSegmentMatches, isTestPath, resolveBestArtifact, } from './build-audit-resolve.js';
43
43
  import { hasChanges, isMissingHeadError } from './git.js';
44
44
  import { git } from './git-base.js';
45
45
  import { getUntrackedFiles } from './git-status.js';
@@ -190,6 +190,27 @@ async function resolveTestsRoot(engineDir) {
190
190
  }
191
191
  return undefined;
192
192
  }
193
+ /**
194
+ * Marker file the `package-tests` make target writes after copying the
195
+ * full test-source tree under `_tests/`. Its presence is the most reliable
196
+ * signal that test packaging has actually run for the current obj-dir —
197
+ * plain `mach build` populates a partial `_tests/` subtree and then stops,
198
+ * so registered tests are absent even when registration is correct.
199
+ */
200
+ const PACKAGED_TESTS_MARKER = 'all-tests.json';
201
+ /**
202
+ * Returns true when the full test-package step has actually run for the
203
+ * active obj-dir. Without this marker the `_tests/` walk produces false
204
+ * positives for every correctly-registered mochitest / xpcshell source
205
+ * on the common "built but tests not packaged" path.
206
+ *
207
+ * @param testsRoot Absolute path to the obj-*`/_tests/` tree, or undefined.
208
+ */
209
+ async function hasPackagedTestsMarker(testsRoot) {
210
+ if (!testsRoot)
211
+ return false;
212
+ return pathExists(join(testsRoot, PACKAGED_TESTS_MARKER));
213
+ }
193
214
  /**
194
215
  * Resolves the search roots an individual source path should be looked
195
216
  * up under. Test-shaped paths get `_tests/`; everything else gets `dist/`.
@@ -200,6 +221,68 @@ function searchRootsFor(source, distRoot, testsRoot) {
200
221
  }
201
222
  return [distRoot];
202
223
  }
224
+ /**
225
+ * Minimum trailing-segment overlap required for a same-basename dist/
226
+ * candidate to count as "the packaged artifact" of a source. The
227
+ * basename always trail-matches (count 1), so a threshold of 2 requires
228
+ * the immediate parent directory to also agree. Candidates that only
229
+ * share the basename are classified as missing — warning the operator
230
+ * to check registration — rather than emitting a misleading stale
231
+ * comparison against an unrelated file of the same name.
232
+ *
233
+ * Cross-tree re-rooting cases (e.g. `branding/<name>/content/foo.css`
234
+ * landing at `chrome/<area>/content/branding/foo.css`) bypass this
235
+ * floor because `scoreCandidate` awards a non-generic-segment bonus
236
+ * that lifts the confidence regardless of trailing overlap; those are
237
+ * detected below in `isConfidentMatch`.
238
+ */
239
+ const MIN_TRAILING_SEGMENT_OVERLAP = 2;
240
+ /**
241
+ * Returns true when the chosen artifact is structurally related to the
242
+ * source path — either its immediate parent directory trail-matches, or
243
+ * a non-generic intermediate source segment appears in the candidate
244
+ * path (the branding-re-root signal already used by the scorer).
245
+ *
246
+ * Used to avoid emitting `stale` warnings that point at an unrelated
247
+ * same-basename file picked up by the basename walker — a class of
248
+ * warning that is worse than `missing` because it reads as "your build
249
+ * dropped this file" when in fact the match is spurious.
250
+ */
251
+ function isConfidentMatch(source, candidate) {
252
+ if (countTrailingSegmentMatches(source, candidate) >= MIN_TRAILING_SEGMENT_OVERLAP) {
253
+ return true;
254
+ }
255
+ const sourceSegs = source.split('/').filter(Boolean);
256
+ const candSegs = candidate.split('/').filter(Boolean);
257
+ const generic = new Set([
258
+ 'content',
259
+ 'chrome',
260
+ 'bin',
261
+ 'browser',
262
+ 'toolkit',
263
+ 'modules',
264
+ 'base',
265
+ 'app',
266
+ 'profile',
267
+ 'shared',
268
+ 'themes',
269
+ 'test',
270
+ 'tests',
271
+ 'unit',
272
+ 'common',
273
+ 'xpcshell',
274
+ 'mochitest',
275
+ ]);
276
+ // Skip the basename itself (which trail-matches by definition).
277
+ for (let i = 0; i < sourceSegs.length - 1; i += 1) {
278
+ const seg = sourceSegs[i];
279
+ if (!seg || seg.length <= 2 || generic.has(seg))
280
+ continue;
281
+ if (candSegs.includes(seg))
282
+ return true;
283
+ }
284
+ return false;
285
+ }
203
286
  /**
204
287
  * Audits one engine source path and returns its entry. Pure orchestration
205
288
  * helper kept separate so `auditBuildArtifacts` stays under the per-function
@@ -211,7 +294,16 @@ async function auditSinglePath(source, ctx) {
211
294
  }
212
295
  const gate = await detectPlatformGate(ctx.engineDir, source);
213
296
  if (gate.gatedOff) {
214
- verbose(`Audit: skipping engine/${source} — gated off by moz.build "${gate.gateExpression ?? '?'}".`);
297
+ verbose(`Audit: skipping engine/${source} — gated off by "${gate.gateExpression ?? '?'}".`);
298
+ return { source, artifact: undefined, status: 'skipped' };
299
+ }
300
+ // Tests only end up under `_tests/` after `mach package-tests` (or a
301
+ // test-run that invokes the target) has executed. A plain `mach build`
302
+ // populates a partial subtree and stops, so every correctly-registered
303
+ // mochitest / xpcshell source appears "missing" on that common path.
304
+ // Skip audit for test sources when no packaged-tests marker is present.
305
+ if (isTestPath(source) && !ctx.testsPackaged) {
306
+ verbose(`Audit: skipping engine/${source} — _tests/${PACKAGED_TESTS_MARKER} not present; full test packaging has not run for this build.`);
215
307
  return { source, artifact: undefined, status: 'skipped' };
216
308
  }
217
309
  const sourcePath = join(ctx.engineDir, source);
@@ -249,6 +341,20 @@ async function auditSinglePath(source, ctx) {
249
341
  };
250
342
  }
251
343
  if (artifactMtime + 1 < sourceMtime) {
344
+ // Before claiming "stale", verify the match is structurally related.
345
+ // A same-basename hit in an unrelated subtree (e.g. `head.js` in a
346
+ // completely different upstream test helper) should be reported as
347
+ // missing — the operator needs to check registration, not puzzle
348
+ // over why an unrelated file appears "older than the source".
349
+ if (!isConfidentMatch(source, artifact)) {
350
+ const where = isTestPath(source) ? '_tests/' : 'dist/';
351
+ return {
352
+ source,
353
+ artifact: undefined,
354
+ status: 'missing',
355
+ warning: `Audit: engine/${source} was touched but no related packaged artifact with basename "${basename(source)}" was found under ${where} (nearest same-basename file ${artifact} lives in an unrelated subtree). Missing moz.build / jar.mn / package-manifest.in registration?`,
356
+ };
357
+ }
252
358
  return {
253
359
  source,
254
360
  artifact,
@@ -283,11 +389,12 @@ export async function auditBuildArtifacts(projectRoot, engineDir, baseline) {
283
389
  return summary;
284
390
  }
285
391
  const testsRoot = await resolveTestsRoot(engineDir);
392
+ const testsPackaged = await hasPackagedTestsMarker(testsRoot);
286
393
  const changed = await collectChangedFiles(engineDir, baseline);
287
394
  if (changed.length === 0) {
288
395
  return summary;
289
396
  }
290
- const ctx = { engineDir, distRoot, testsRoot };
397
+ const ctx = { engineDir, distRoot, testsRoot, testsPackaged };
291
398
  for (const source of changed) {
292
399
  const result = await auditSinglePath(source, ctx);
293
400
  summary[result.status] += 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hominis/fireforge",
3
- "version": "0.15.5",
3
+ "version": "0.15.6",
4
4
  "description": "FireForge — a build tool for customizing Firefox",
5
5
  "type": "module",
6
6
  "main": "./dist/src/index.js",