@hominis/fireforge 0.19.3 → 0.19.4

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 (52) hide show
  1. package/dist/src/commands/bootstrap-checks.js +1 -1
  2. package/dist/src/commands/doctor-check-core.d.ts +101 -0
  3. package/dist/src/commands/doctor-check-core.js +32 -0
  4. package/dist/src/commands/doctor-furnace-manifest-sync.d.ts +1 -1
  5. package/dist/src/commands/doctor-furnace-manifest-sync.js +1 -1
  6. package/dist/src/commands/doctor-furnace.d.ts +1 -1
  7. package/dist/src/commands/doctor-furnace.js +1 -1
  8. package/dist/src/commands/doctor-working-tree.d.ts +1 -1
  9. package/dist/src/commands/doctor-working-tree.js +1 -1
  10. package/dist/src/commands/doctor.d.ts +1 -107
  11. package/dist/src/commands/doctor.js +1 -29
  12. package/dist/src/commands/furnace/index.d.ts +0 -17
  13. package/dist/src/commands/furnace/index.js +0 -1
  14. package/dist/src/commands/furnace/validate.d.ts +2 -3
  15. package/dist/src/commands/patch/index.d.ts +0 -6
  16. package/dist/src/commands/patch/index.js +0 -6
  17. package/dist/src/commands/wire.js +34 -32
  18. package/dist/src/core/config.d.ts +2 -2
  19. package/dist/src/core/config.js +2 -2
  20. package/dist/src/core/furnace-apply-helpers.js +2 -2
  21. package/dist/src/core/furnace-config-array-utils.d.ts +11 -0
  22. package/dist/src/core/furnace-config-array-utils.js +27 -0
  23. package/dist/src/core/furnace-config-custom.js +1 -1
  24. package/dist/src/core/furnace-config-tokens.js +1 -1
  25. package/dist/src/core/furnace-config.d.ts +0 -6
  26. package/dist/src/core/furnace-config.js +2 -14
  27. package/dist/src/core/furnace-refresh.d.ts +0 -4
  28. package/dist/src/core/furnace-registration-ast.d.ts +0 -1
  29. package/dist/src/core/furnace-registration-ast.js +0 -1
  30. package/dist/src/core/furnace-registration.d.ts +2 -3
  31. package/dist/src/core/furnace-registration.js +2 -3
  32. package/dist/src/core/git-file-ops.d.ts +0 -6
  33. package/dist/src/core/git-file-ops.js +0 -8
  34. package/dist/src/core/git-status.d.ts +0 -14
  35. package/dist/src/core/git-status.js +0 -24
  36. package/dist/src/core/git.d.ts +0 -1
  37. package/dist/src/core/mach.d.ts +2 -2
  38. package/dist/src/core/patch-apply.d.ts +2 -2
  39. package/dist/src/core/patch-apply.js +2 -2
  40. package/dist/src/core/patch-lint-reexports.d.ts +1 -4
  41. package/dist/src/core/patch-lint-reexports.js +0 -3
  42. package/dist/src/core/patch-manifest.d.ts +1 -2
  43. package/dist/src/core/patch-manifest.js +1 -1
  44. package/dist/src/core/signal-critical.d.ts +0 -11
  45. package/dist/src/core/signal-critical.js +0 -15
  46. package/dist/src/core/wire-targets.d.ts +4 -4
  47. package/dist/src/core/wire-targets.js +4 -4
  48. package/dist/src/utils/logger.d.ts +0 -5
  49. package/dist/src/utils/logger.js +2 -2
  50. package/dist/src/utils/package-root.d.ts +0 -2
  51. package/dist/src/utils/package-root.js +0 -4
  52. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  // SPDX-License-Identifier: EUPL-1.2
2
2
  import { execFile } from 'node:child_process';
3
- import { failure, warning } from './doctor.js';
3
+ import { failure, warning } from './doctor-check-core.js';
4
4
  /**
5
5
  * Scans bootstrap output for known failure patterns and returns structured
6
6
  * issue tags. A Python traceback paired with an HTTP 403 is collapsed into
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Doctor check types and lightweight result builders shared between
3
+ * `doctor.ts` and sibling check modules. Kept separate so registries can import
4
+ * these symbols without creating cycles through `doctor.ts`.
5
+ */
6
+ import type { DoctorCheck, DoctorOptions } from '../types/commands/index.js';
7
+ import type { FireForgeConfig, FireForgeState, ProjectPaths } from '../types/config.js';
8
+ import type { FurnaceConfig } from '../types/furnace.js';
9
+ /**
10
+ * Shared state available to every doctor check during a single run.
11
+ *
12
+ * The context is populated lazily by the doctor runner. Individual checks
13
+ * can record side-observations (e.g. the parsed `fireforge.json`) into the
14
+ * context for later checks to consume without re-parsing.
15
+ */
16
+ export interface DoctorCheckContext {
17
+ projectRoot: string;
18
+ paths: ProjectPaths;
19
+ state: FireForgeState;
20
+ options: DoctorOptions;
21
+ /**
22
+ * Whether the engine/ directory exists on disk. Populated before checks
23
+ * run so downstream checks can skip git/mach inspections cheaply.
24
+ */
25
+ engineExists: boolean;
26
+ /**
27
+ * The loaded project config, set by the "fireforge.json is valid" check
28
+ * when it succeeds. Undefined before that check runs and whenever loading
29
+ * failed.
30
+ */
31
+ config: FireForgeConfig | undefined;
32
+ /**
33
+ * Whether `furnace.json` exists on disk. Populated before checks run so
34
+ * the furnace group can skipIf cheaply when the subsystem is not in use.
35
+ */
36
+ furnaceConfigExists: boolean;
37
+ /**
38
+ * The parsed furnace config, set by the "Furnace configuration" check
39
+ * when it succeeds. Later furnace checks read from this so they do not
40
+ * re-parse the file; undefined when the config could not be loaded.
41
+ */
42
+ furnaceConfig: FurnaceConfig | undefined;
43
+ }
44
+ /**
45
+ * Result a check may return. A single object is the common case; an array
46
+ * lets a single check emit multiple related rows (e.g. the engine branch
47
+ * check which may report on branch + detached state together).
48
+ */
49
+ export type CheckResult = DoctorCheck | DoctorCheck[];
50
+ /**
51
+ * Declarative definition of a single doctor check.
52
+ *
53
+ * Every check opts into the shared execution/reporting pipeline by
54
+ * implementing only its inspection logic in `run`. Cross-cutting concerns
55
+ * (result aggregation, summary, exit codes) live in the runner instead of
56
+ * being duplicated at each call site.
57
+ */
58
+ export interface DoctorCheckDefinition {
59
+ /**
60
+ * Human-readable name surfaced in the check report (e.g. "Git installed").
61
+ * Not required to be unique, but tests assert on it.
62
+ */
63
+ name: string;
64
+ /**
65
+ * When `true`, the check is silently skipped. Used for checks that only
66
+ * apply when the engine is present, or only when specific state flags
67
+ * are set. Skipped checks contribute nothing to the final report.
68
+ */
69
+ skipIf?: (ctx: DoctorCheckContext) => boolean;
70
+ /**
71
+ * Names of checks that must appear earlier in the registry and run before
72
+ * this check. Enforced at startup via validateCheckDependencies so
73
+ * accidental reorders surface immediately instead of producing subtle
74
+ * context-population bugs at runtime.
75
+ */
76
+ dependsOn?: readonly string[];
77
+ /**
78
+ * Runs the inspection. Throwing is shorthand for "this check failed with
79
+ * severity 'error'" — the runner converts the exception message into a
80
+ * DoctorCheck. Returning a DoctorCheck (or array) lets the check control
81
+ * severity, warnings, and fix hints directly.
82
+ */
83
+ run: (ctx: DoctorCheckContext) => CheckResult | Promise<CheckResult>;
84
+ /**
85
+ * Optional recovery hint attached to the auto-generated failure result
86
+ * when `run` throws. Ignored when `run` returns a DoctorCheck explicitly.
87
+ */
88
+ fix?: string;
89
+ }
90
+ /**
91
+ * Builds a DoctorCheck object representing a successful "OK" check.
92
+ */
93
+ export declare function ok(name: string): DoctorCheck;
94
+ /**
95
+ * Builds a DoctorCheck object representing a warning result.
96
+ */
97
+ export declare function warning(name: string, message: string, fix?: string): DoctorCheck;
98
+ /**
99
+ * Builds a DoctorCheck object representing a failure result.
100
+ */
101
+ export declare function failure(name: string, message: string, fix?: string): DoctorCheck;
@@ -0,0 +1,32 @@
1
+ // SPDX-License-Identifier: EUPL-1.2
2
+ /**
3
+ * Doctor check types and lightweight result builders shared between
4
+ * `doctor.ts` and sibling check modules. Kept separate so registries can import
5
+ * these symbols without creating cycles through `doctor.ts`.
6
+ */
7
+ /**
8
+ * Builds a DoctorCheck object representing a successful "OK" check.
9
+ */
10
+ export function ok(name) {
11
+ return { name, passed: true, severity: 'ok', message: 'OK' };
12
+ }
13
+ /**
14
+ * Builds a DoctorCheck object representing a warning result.
15
+ */
16
+ export function warning(name, message, fix) {
17
+ return {
18
+ name,
19
+ passed: true,
20
+ severity: 'warning',
21
+ warning: true,
22
+ message,
23
+ ...(fix ? { fix } : {}),
24
+ };
25
+ }
26
+ /**
27
+ * Builds a DoctorCheck object representing a failure result.
28
+ */
29
+ export function failure(name, message, fix) {
30
+ return { name, passed: false, severity: 'error', message, ...(fix ? { fix } : {}) };
31
+ }
32
+ //# sourceMappingURL=doctor-check-core.js.map
@@ -14,5 +14,5 @@
14
14
  * Lives in a sibling module to keep `doctor-furnace.ts` under the
15
15
  * per-file LOC budget.
16
16
  */
17
- import type { DoctorCheckDefinition } from './doctor.js';
17
+ import type { DoctorCheckDefinition } from './doctor-check-core.js';
18
18
  export declare const furnaceManifestSyncCheck: DoctorCheckDefinition;
@@ -20,7 +20,7 @@ import { join } from 'node:path';
20
20
  import { getFurnacePaths, loadFurnaceConfig, writeFurnaceConfig } from '../core/furnace-config.js';
21
21
  import { toError } from '../utils/errors.js';
22
22
  import { pathExists, readJson } from '../utils/fs.js';
23
- import { failure, ok, warning } from './doctor.js';
23
+ import { failure, ok, warning } from './doctor-check-core.js';
24
24
  async function listComponentDirs(dir) {
25
25
  if (!(await pathExists(dir)))
26
26
  return [];
@@ -1,4 +1,4 @@
1
- import type { DoctorCheckDefinition } from './doctor.js';
1
+ import type { DoctorCheckDefinition } from './doctor-check-core.js';
2
2
  /**
3
3
  * The ordered furnace check group. Exported as an array so `doctor.ts`
4
4
  * can splice it into the main registry at the right position. The order
@@ -9,7 +9,7 @@ import { getFurnaceLockPath, runFurnaceMutation } from '../core/furnace-operatio
9
9
  import { validateAllComponents } from '../core/furnace-validate.js';
10
10
  import { toError } from '../utils/errors.js';
11
11
  import { pathExists } from '../utils/fs.js';
12
- import { failure, ok, warning } from './doctor.js';
12
+ import { failure, ok, warning } from './doctor-check-core.js';
13
13
  import { furnaceManifestSyncCheck } from './doctor-furnace-manifest-sync.js';
14
14
  const ENGINE_REPAIRABLE_OPERATIONS = [
15
15
  'preview-teardown',
@@ -10,7 +10,7 @@
10
10
  * budget; see the call site in `runEngineGitChecks`.
11
11
  */
12
12
  import type { DoctorCheck } from '../types/commands/index.js';
13
- import type { DoctorCheckContext } from './doctor.js';
13
+ import type { DoctorCheckContext } from './doctor-check-core.js';
14
14
  /**
15
15
  * Inspects the engine working tree and returns a single
16
16
  * `DoctorCheck`. Ownership-aware: patch-backed / branding / furnace
@@ -13,7 +13,7 @@
13
13
  import { collectFurnaceManagedPrefixes } from '../core/furnace-config.js';
14
14
  import { expandUntrackedDirectoryEntries, getWorkingTreeStatus } from '../core/git-status.js';
15
15
  import { classifyFiles } from '../core/status-classify.js';
16
- import { ok, warning } from './doctor.js';
16
+ import { ok, warning } from './doctor-check-core.js';
17
17
  function summarizeWorkingTreeChangeCount(changeCount) {
18
18
  return `Engine working tree has ${changeCount} local change${changeCount === 1 ? '' : 's'}. Some FireForge commands assume a clean baseline and may behave differently until these are exported, discarded, or committed.`;
19
19
  }
@@ -2,113 +2,7 @@ import { Command } from 'commander';
2
2
  import { ExitCode } from '../errors/codes.js';
3
3
  import type { CommandContext } from '../types/cli.js';
4
4
  import type { DoctorCheck, DoctorOptions } from '../types/commands/index.js';
5
- import type { FireForgeConfig, FireForgeState, ProjectPaths } from '../types/config.js';
6
- import type { FurnaceConfig } from '../types/furnace.js';
7
- /**
8
- * Shared state available to every doctor check during a single run.
9
- *
10
- * The context is populated lazily by the doctor runner. Individual checks
11
- * can record side-observations (e.g. the parsed `fireforge.json`) into the
12
- * context for later checks to consume without re-parsing.
13
- *
14
- * Exported so sibling modules (e.g. `doctor-furnace.ts`) can declare
15
- * `DoctorCheckDefinition` entries against the same shared context.
16
- */
17
- export interface DoctorCheckContext {
18
- projectRoot: string;
19
- paths: ProjectPaths;
20
- state: FireForgeState;
21
- options: DoctorOptions;
22
- /**
23
- * Whether the engine/ directory exists on disk. Populated before checks
24
- * run so downstream checks can skip git/mach inspections cheaply.
25
- */
26
- engineExists: boolean;
27
- /**
28
- * The loaded project config, set by the "fireforge.json is valid" check
29
- * when it succeeds. Undefined before that check runs and whenever loading
30
- * failed.
31
- */
32
- config: FireForgeConfig | undefined;
33
- /**
34
- * Whether `furnace.json` exists on disk. Populated before checks run so
35
- * the furnace group can skipIf cheaply when the subsystem is not in use.
36
- * A missing furnace.json is not an error — plenty of projects never touch
37
- * the subsystem — so the doctor stays silent rather than failing.
38
- */
39
- furnaceConfigExists: boolean;
40
- /**
41
- * The parsed furnace config, set by the "Furnace configuration" check
42
- * when it succeeds. Later furnace checks read from this so they do not
43
- * re-parse the file; undefined when the config could not be loaded.
44
- */
45
- furnaceConfig: FurnaceConfig | undefined;
46
- }
47
- /**
48
- * Result a check may return. A single object is the common case; an array
49
- * lets a single check emit multiple related rows (e.g. the engine branch
50
- * check which may report on branch + detached state together).
51
- */
52
- export type CheckResult = DoctorCheck | DoctorCheck[];
53
- /**
54
- * Declarative definition of a single doctor check.
55
- *
56
- * Every check opts into the shared execution/reporting pipeline by
57
- * implementing only its inspection logic in `run`. Cross-cutting concerns
58
- * (result aggregation, summary, exit codes) live in the runner instead of
59
- * being duplicated at each call site.
60
- *
61
- * Exported so sibling modules (e.g. `doctor-furnace.ts`) can declare
62
- * new checks without re-deriving the shape.
63
- */
64
- export interface DoctorCheckDefinition {
65
- /**
66
- * Human-readable name surfaced in the check report (e.g. "Git installed").
67
- * Not required to be unique, but tests assert on it.
68
- */
69
- name: string;
70
- /**
71
- * When `true`, the check is silently skipped. Used for checks that only
72
- * apply when the engine is present, or only when specific state flags
73
- * are set. Skipped checks contribute nothing to the final report.
74
- */
75
- skipIf?: (ctx: DoctorCheckContext) => boolean;
76
- /**
77
- * Names of checks that must appear earlier in the registry and run before
78
- * this check. Enforced at startup via {@link validateCheckDependencies} so
79
- * accidental reorders surface immediately instead of producing subtle
80
- * context-population bugs at runtime.
81
- */
82
- dependsOn?: readonly string[];
83
- /**
84
- * Runs the inspection. Throwing is shorthand for "this check failed with
85
- * severity 'error'" — the runner converts the exception message into a
86
- * DoctorCheck. Returning a DoctorCheck (or array) lets the check control
87
- * severity, warnings, and fix hints directly.
88
- */
89
- run: (ctx: DoctorCheckContext) => CheckResult | Promise<CheckResult>;
90
- /**
91
- * Optional recovery hint attached to the auto-generated failure result
92
- * when `run` throws. Ignored when `run` returns a DoctorCheck explicitly.
93
- */
94
- fix?: string;
95
- }
96
- /**
97
- * Builds a DoctorCheck object representing a successful "OK" check.
98
- * Exported for sibling check modules that declare `DoctorCheckDefinition`
99
- * entries out-of-file (e.g. `doctor-furnace.ts`).
100
- */
101
- export declare function ok(name: string): DoctorCheck;
102
- /**
103
- * Builds a DoctorCheck object representing a warning result.
104
- * Exported for sibling check modules — see {@link ok}.
105
- */
106
- export declare function warning(name: string, message: string, fix?: string): DoctorCheck;
107
- /**
108
- * Builds a DoctorCheck object representing a failure result.
109
- * Exported for sibling check modules — see {@link ok}.
110
- */
111
- export declare function failure(name: string, message: string, fix?: string): DoctorCheck;
5
+ import type { DoctorCheckDefinition } from './doctor-check-core.js';
112
6
  /**
113
7
  * Validates that every check's `dependsOn` entries appear earlier in the
114
8
  * registry. Called once at module load time so a broken reorder surfaces
@@ -10,37 +10,9 @@ import { toError } from '../utils/errors.js';
10
10
  import { pathExists } from '../utils/fs.js';
11
11
  import { error, info, intro, outro, success, warn } from '../utils/logger.js';
12
12
  import { findExecutable } from '../utils/process.js';
13
+ import { failure, ok, warning } from './doctor-check-core.js';
13
14
  import { FURNACE_DOCTOR_CHECKS } from './doctor-furnace.js';
14
15
  import { inspectEngineWorkingTree } from './doctor-working-tree.js';
15
- /**
16
- * Builds a DoctorCheck object representing a successful "OK" check.
17
- * Exported for sibling check modules that declare `DoctorCheckDefinition`
18
- * entries out-of-file (e.g. `doctor-furnace.ts`).
19
- */
20
- export function ok(name) {
21
- return { name, passed: true, severity: 'ok', message: 'OK' };
22
- }
23
- /**
24
- * Builds a DoctorCheck object representing a warning result.
25
- * Exported for sibling check modules — see {@link ok}.
26
- */
27
- export function warning(name, message, fix) {
28
- return {
29
- name,
30
- passed: true,
31
- severity: 'warning',
32
- warning: true,
33
- message,
34
- ...(fix ? { fix } : {}),
35
- };
36
- }
37
- /**
38
- * Builds a DoctorCheck object representing a failure result.
39
- * Exported for sibling check modules — see {@link ok}.
40
- */
41
- export function failure(name, message, fix) {
42
- return { name, passed: false, severity: 'error', message, ...(fix ? { fix } : {}) };
43
- }
44
16
  /**
45
17
  * Runs a single check definition, converting thrown errors into
46
18
  * DoctorCheck failure rows. Always returns an array so the caller can
@@ -1,21 +1,4 @@
1
1
  import { Command } from 'commander';
2
2
  import type { CommandContext } from '../../types/cli.js';
3
- import { furnaceApplyCommand } from './apply.js';
4
- import { furnaceChromeDocCreateCommand } from './chrome-doc.js';
5
- import { furnaceCreateCommand } from './create.js';
6
- import { furnaceDeployCommand } from './deploy.js';
7
- import { furnaceDiffCommand } from './diff.js';
8
- import { furnaceInitCommand } from './init.js';
9
- import { furnaceListCommand } from './list.js';
10
- import { furnaceBatchOverrideCommand, furnaceOverrideCommand } from './override.js';
11
- import { furnacePreviewCommand } from './preview.js';
12
- import { furnaceRefreshCommand } from './refresh.js';
13
- import { furnaceRemoveCommand } from './remove.js';
14
- import { furnaceRenameCommand } from './rename.js';
15
- import { furnaceScanCommand } from './scan.js';
16
- import { furnaceStatusCommand } from './status.js';
17
- import { furnaceSyncCommand } from './sync.js';
18
- import { furnaceValidateCommand } from './validate.js';
19
- export { furnaceApplyCommand, furnaceBatchOverrideCommand, furnaceChromeDocCreateCommand, furnaceCreateCommand, furnaceDeployCommand, furnaceDiffCommand, furnaceInitCommand, furnaceListCommand, furnaceOverrideCommand, furnacePreviewCommand, furnaceRefreshCommand, furnaceRemoveCommand, furnaceRenameCommand, furnaceScanCommand, furnaceStatusCommand, furnaceSyncCommand, furnaceValidateCommand, };
20
3
  /** Registers the furnace command on the CLI program. */
21
4
  export declare function registerFurnace(program: Command, context: CommandContext): void;
@@ -17,7 +17,6 @@ import { furnaceScanCommand } from './scan.js';
17
17
  import { furnaceStatusCommand } from './status.js';
18
18
  import { furnaceSyncCommand } from './sync.js';
19
19
  import { furnaceValidateCommand } from './validate.js';
20
- export { furnaceApplyCommand, furnaceBatchOverrideCommand, furnaceChromeDocCreateCommand, furnaceCreateCommand, furnaceDeployCommand, furnaceDiffCommand, furnaceInitCommand, furnaceListCommand, furnaceOverrideCommand, furnacePreviewCommand, furnaceRefreshCommand, furnaceRemoveCommand, furnaceRenameCommand, furnaceScanCommand, furnaceStatusCommand, furnaceSyncCommand, furnaceValidateCommand, };
21
20
  /**
22
21
  * Registers Furnace commands for querying component state: status, scan,
23
22
  * and action commands like apply, deploy, and create.
@@ -1,9 +1,8 @@
1
+ import type { FurnaceValidateOptions } from '../../types/commands/index.js';
1
2
  /**
2
3
  * Runs the furnace validate command to perform static analysis on components.
3
4
  * @param projectRoot - Root directory of the project
4
5
  * @param name - Optional component name to validate (validates all if omitted)
5
6
  * @param options - Optional command options (e.g. --fix)
6
7
  */
7
- export declare function furnaceValidateCommand(projectRoot: string, name?: string, options?: {
8
- fix?: boolean;
9
- }): Promise<void>;
8
+ export declare function furnaceValidateCommand(projectRoot: string, name?: string, options?: FurnaceValidateOptions): Promise<void>;
@@ -7,12 +7,6 @@
7
7
  */
8
8
  import { Command } from 'commander';
9
9
  import type { CommandContext } from '../../types/cli.js';
10
- export { patchCompactCommand } from './compact.js';
11
- export { patchDeleteCommand } from './delete.js';
12
- export { patchLintIgnoreCommand } from './lint-ignore.js';
13
- export { patchRenameCommand } from './rename.js';
14
- export { patchReorderCommand } from './reorder.js';
15
- export { patchTierCommand } from './tier.js';
16
10
  /**
17
11
  * Registers the `patch` subcommand parent and its verbs on the CLI.
18
12
  *
@@ -12,12 +12,6 @@ import { registerPatchLintIgnore } from './lint-ignore.js';
12
12
  import { registerPatchRename } from './rename.js';
13
13
  import { registerPatchReorder } from './reorder.js';
14
14
  import { registerPatchTier } from './tier.js';
15
- export { patchCompactCommand } from './compact.js';
16
- export { patchDeleteCommand } from './delete.js';
17
- export { patchLintIgnoreCommand } from './lint-ignore.js';
18
- export { patchRenameCommand } from './rename.js';
19
- export { patchReorderCommand } from './reorder.js';
20
- export { patchTierCommand } from './tier.js';
21
15
  /**
22
16
  * Registers the `patch` subcommand parent and its verbs on the CLI.
23
17
  *
@@ -111,6 +111,38 @@ async function assertDomTargetIsWireable(projectRoot, domFilePath, domTargetPath
111
111
  '`--target <path>`.', 'target');
112
112
  }
113
113
  }
114
+ async function resolveWireSubscriptDir(projectRoot, options) {
115
+ let subscriptDir = DEFAULT_BROWSER_SUBSCRIPT_DIR;
116
+ try {
117
+ const config = await loadConfig(projectRoot);
118
+ if (config.wire?.subscriptDir) {
119
+ subscriptDir = config.wire.subscriptDir;
120
+ }
121
+ }
122
+ catch (error) {
123
+ warn(`Using default wire.subscriptDir because fireforge.json could not be loaded: ${toError(error).message}`);
124
+ }
125
+ if (options.subscriptDir) {
126
+ if (!isContainedRelativePath(options.subscriptDir)) {
127
+ throw new InvalidArgumentError(`Subscript directory must stay within engine/: ${options.subscriptDir}`, 'subscriptDir');
128
+ }
129
+ subscriptDir = options.subscriptDir;
130
+ }
131
+ return subscriptDir;
132
+ }
133
+ async function ensureSubscriptSourceExists(projectRoot, subscriptDir, name, dryRun) {
134
+ const paths = getProjectPaths(projectRoot);
135
+ const subscriptPath = join(paths.engine, subscriptDir, `${name}.js`);
136
+ if (!(await pathExists(subscriptPath))) {
137
+ if (dryRun) {
138
+ info(`Note: ${subscriptDir}/${name}.js does not exist yet — the real wire command will require it before writing. Create the file before re-running without --dry-run.`);
139
+ }
140
+ else {
141
+ throw new InvalidArgumentError(`Subscript file not found: ${subscriptDir}/${name}.js\n` +
142
+ 'Create the file in engine/ before wiring.', 'name');
143
+ }
144
+ }
145
+ }
114
146
  /**
115
147
  * Wires a chrome subscript into the browser.
116
148
  *
@@ -144,23 +176,7 @@ export async function wireCommand(projectRoot, name, options = {}) {
144
176
  validateWireExpression(options.destroy, 'destroy expression');
145
177
  }
146
178
  consumeParserFallbackEvents();
147
- // Resolve subscript directory: CLI flag > fireforge.json > default
148
- let subscriptDir = DEFAULT_BROWSER_SUBSCRIPT_DIR;
149
- try {
150
- const config = await loadConfig(projectRoot);
151
- if (config.wire?.subscriptDir) {
152
- subscriptDir = config.wire.subscriptDir;
153
- }
154
- }
155
- catch (error) {
156
- warn(`Using default wire.subscriptDir because fireforge.json could not be loaded: ${toError(error).message}`);
157
- }
158
- if (options.subscriptDir) {
159
- if (!isContainedRelativePath(options.subscriptDir)) {
160
- throw new InvalidArgumentError(`Subscript directory must stay within engine/: ${options.subscriptDir}`, 'subscriptDir');
161
- }
162
- subscriptDir = options.subscriptDir;
163
- }
179
+ const subscriptDir = await resolveWireSubscriptDir(projectRoot, options);
164
180
  // Validate DOM fragment file exists and compute path relative to engine root.
165
181
  //
166
182
  // Accepts three shapes:
@@ -235,21 +251,7 @@ export async function wireCommand(projectRoot, name, options = {}) {
235
251
  // plausible plan and the non-dry-run invocation then errored. The
236
252
  // info line surfaces the mismatch in preview mode so the operator
237
253
  // can act on the warning before re-running without --dry-run.
238
- if (!options.dryRun) {
239
- const paths = getProjectPaths(projectRoot);
240
- const subscriptPath = join(paths.engine, subscriptDir, `${name}.js`);
241
- if (!(await pathExists(subscriptPath))) {
242
- throw new InvalidArgumentError(`Subscript file not found: ${subscriptDir}/${name}.js\n` +
243
- 'Create the file in engine/ before wiring.', 'name');
244
- }
245
- }
246
- else {
247
- const paths = getProjectPaths(projectRoot);
248
- const subscriptPath = join(paths.engine, subscriptDir, `${name}.js`);
249
- if (!(await pathExists(subscriptPath))) {
250
- info(`Note: ${subscriptDir}/${name}.js does not exist yet — the real wire command will require it before writing. Create the file before re-running without --dry-run.`);
251
- }
252
- }
254
+ await ensureSubscriptSourceExists(projectRoot, subscriptDir, name, options.dryRun ?? false);
253
255
  if (options.dryRun) {
254
256
  printWireDryRun(getProjectPaths(projectRoot).engine, name, subscriptDir, domFilePath, domTargetPath, options);
255
257
  return;
@@ -9,8 +9,8 @@
9
9
  */
10
10
  import type { FireForgeConfig } from '../types/config.js';
11
11
  export { mutateConfig } from './config-mutate.js';
12
- export { CONFIG_FILENAME, CONFIGS_DIR, ENGINE_DIR, FIREFORGE_DIR, getProjectPaths, PATCHES_DIR, SRC_DIR, STATE_FILENAME, SUPPORTED_CONFIG_PATHS, SUPPORTED_CONFIG_ROOT_KEYS, } from './config-paths.js';
13
- export { loadState, saveState, updateState, validateFireForgeState } from './config-state.js';
12
+ export { CONFIG_FILENAME, FIREFORGE_DIR, getProjectPaths, STATE_FILENAME, SUPPORTED_CONFIG_PATHS, SUPPORTED_CONFIG_ROOT_KEYS, } from './config-paths.js';
13
+ export { loadState, saveState, updateState } from './config-state.js';
14
14
  export { validateConfig } from './config-validate.js';
15
15
  /**
16
16
  * Checks if a fireforge.json exists in the given directory.
@@ -17,8 +17,8 @@ import { validateConfig } from './config-validate.js';
17
17
  import { createSiblingLockPath, withFileLock } from './file-lock.js';
18
18
  // ---- re-exports ----
19
19
  export { mutateConfig } from './config-mutate.js';
20
- export { CONFIG_FILENAME, CONFIGS_DIR, ENGINE_DIR, FIREFORGE_DIR, getProjectPaths, PATCHES_DIR, SRC_DIR, STATE_FILENAME, SUPPORTED_CONFIG_PATHS, SUPPORTED_CONFIG_ROOT_KEYS, } from './config-paths.js';
21
- export { loadState, saveState, updateState, validateFireForgeState } from './config-state.js';
20
+ export { CONFIG_FILENAME, FIREFORGE_DIR, getProjectPaths, STATE_FILENAME, SUPPORTED_CONFIG_PATHS, SUPPORTED_CONFIG_ROOT_KEYS, } from './config-paths.js';
21
+ export { loadState, saveState, updateState } from './config-state.js';
22
22
  export { validateConfig } from './config-validate.js';
23
23
  // ---- config I/O (stays here because it bridges paths + validation) ----
24
24
  /**
@@ -8,7 +8,7 @@ import { copyFile, ensureDir, pathExists, readText, removeFile } from '../utils/
8
8
  import { verbose } from '../utils/logger.js';
9
9
  import { applyCustomFtlFile, describeLocaleFtlJarMnRegistration, removeCustomFtlJarMnEntry, } from './furnace-apply-ftl.js';
10
10
  import { CUSTOM_ELEMENTS_JS, JAR_MN } from './furnace-constants.js';
11
- import { addCustomElementRegistration, addJarMnEntries, validateCustomElementRegistration, validateJarMnEntries, } from './furnace-registration.js';
11
+ import { addCustomElementRegistration, addJarMnEntries, validateCustomElementRegistration, validateJarMnInsertionForFiles, } from './furnace-registration.js';
12
12
  import { recordCreatedDir, snapshotFile } from './furnace-rollback.js';
13
13
  import { checkRegistrationConsistency } from './furnace-validate-registration.js';
14
14
  import { isGitRepository } from './git.js';
@@ -352,7 +352,7 @@ async function buildCustomDryRunActions(name, componentDir, engineDir, config, t
352
352
  .map((entry) => entry.name);
353
353
  if (copiedFileNames.length > 0) {
354
354
  try {
355
- await validateJarMnEntries(engineDir, name, copiedFileNames);
355
+ await validateJarMnInsertionForFiles(engineDir, name, copiedFileNames);
356
356
  }
357
357
  catch (error) {
358
358
  stepErrors.push({
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Shared string-array parsing for furnace.json validation. Lives in its own
3
+ * module so `furnace-config-custom.ts` and `furnace-config-tokens.ts` can use
4
+ * it without importing `furnace-config.ts`, which would create import cycles.
5
+ */
6
+ /**
7
+ * Parses a JSON array-of-strings field from raw furnace config data.
8
+ * @param value - Raw value from JSON
9
+ * @param fieldName - Field label for error messages
10
+ */
11
+ export declare function parseStringArray(value: unknown, fieldName: string): string[];
@@ -0,0 +1,27 @@
1
+ // SPDX-License-Identifier: EUPL-1.2
2
+ /**
3
+ * Shared string-array parsing for furnace.json validation. Lives in its own
4
+ * module so `furnace-config-custom.ts` and `furnace-config-tokens.ts` can use
5
+ * it without importing `furnace-config.ts`, which would create import cycles.
6
+ */
7
+ import { FurnaceError } from '../errors/furnace.js';
8
+ import { isArray, isString } from '../utils/validation.js';
9
+ /**
10
+ * Parses a JSON array-of-strings field from raw furnace config data.
11
+ * @param value - Raw value from JSON
12
+ * @param fieldName - Field label for error messages
13
+ */
14
+ export function parseStringArray(value, fieldName) {
15
+ if (!isArray(value)) {
16
+ throw new FurnaceError(`Furnace config: "${fieldName}" must be an array`);
17
+ }
18
+ const items = [];
19
+ for (const item of value) {
20
+ if (!isString(item)) {
21
+ throw new FurnaceError(`Furnace config: "${fieldName}" array must contain only strings`);
22
+ }
23
+ items.push(item);
24
+ }
25
+ return items;
26
+ }
27
+ //# sourceMappingURL=furnace-config-array-utils.js.map
@@ -9,7 +9,7 @@
9
9
  import { FurnaceError } from '../errors/furnace.js';
10
10
  import { isExplicitAbsolutePath } from '../utils/paths.js';
11
11
  import { isBoolean, isString } from '../utils/validation.js';
12
- import { parseStringArray } from './furnace-config.js';
12
+ import { parseStringArray } from './furnace-config-array-utils.js';
13
13
  import { validateSharedFtl } from './shared-ftl.js';
14
14
  /**
15
15
  * Validates a custom component config object.
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import { FurnaceError } from '../errors/furnace.js';
8
8
  import { isContainedRelativePath } from '../utils/paths.js';
9
- import { parseStringArray } from './furnace-config.js';
9
+ import { parseStringArray } from './furnace-config-array-utils.js';
10
10
  /**
11
11
  * Validates a `tokenHostDocuments` raw value. Each entry must be a non-empty
12
12
  * relative path contained in the engine tree. Throws `FurnaceError` on
@@ -38,12 +38,6 @@ export declare function getFurnacePaths(root: string): FurnacePaths;
38
38
  * @returns True if furnace.json exists
39
39
  */
40
40
  export declare function furnaceConfigExists(root: string): Promise<boolean>;
41
- /**
42
- * Validates an override component config object.
43
- * @param data - Raw data to validate
44
- * @param name - Component name for error messages
45
- */
46
- export declare function parseStringArray(value: unknown, fieldName: string): string[];
47
41
  /**
48
42
  * Migrates a furnace config from an older schema version to the current one.
49
43
  * Returns the data unchanged if it is already at the current version.
@@ -4,8 +4,9 @@ import { FurnaceError } from '../errors/furnace.js';
4
4
  import { toError } from '../utils/errors.js';
5
5
  import { pathExists, readJson, writeJson } from '../utils/fs.js';
6
6
  import { warn } from '../utils/logger.js';
7
- import { isArray, isObject, isString } from '../utils/validation.js';
7
+ import { isObject, isString } from '../utils/validation.js';
8
8
  import { FIREFORGE_DIR } from './config.js';
9
+ import { parseStringArray } from './furnace-config-array-utils.js';
9
10
  import { parseCustomConfig } from './furnace-config-custom.js';
10
11
  import { validateRuntimeVariables, validateTokenHostDocuments } from './furnace-config-tokens.js';
11
12
  import { resolveFtlDir } from './furnace-constants.js';
@@ -51,19 +52,6 @@ export async function furnaceConfigExists(root) {
51
52
  * @param data - Raw data to validate
52
53
  * @param name - Component name for error messages
53
54
  */
54
- export function parseStringArray(value, fieldName) {
55
- if (!isArray(value)) {
56
- throw new FurnaceError(`Furnace config: "${fieldName}" must be an array`);
57
- }
58
- const items = [];
59
- for (const item of value) {
60
- if (!isString(item)) {
61
- throw new FurnaceError(`Furnace config: "${fieldName}" array must contain only strings`);
62
- }
63
- items.push(item);
64
- }
65
- return items;
66
- }
67
55
  function parseOverrideConfig(data, name) {
68
56
  const validTypes = ['css-only', 'full'];
69
57
  if (!isString(data['type']) || !validTypes.includes(data['type'])) {
@@ -3,10 +3,6 @@ export interface RefreshFileResult {
3
3
  status: 'merged' | 'conflict' | 'unchanged' | 'new-file';
4
4
  conflictMarkers?: number;
5
5
  }
6
- export interface RefreshResult {
7
- files: RefreshFileResult[];
8
- newBaseVersion: string;
9
- }
10
6
  /**
11
7
  * Refreshes a single override file against the current engine HEAD.
12
8
  *
@@ -15,7 +15,6 @@ export interface RegistrationWriteOptions {
15
15
  markerComment?: string;
16
16
  }
17
17
  export { removeCustomElementRegistration } from './furnace-registration-remove.js';
18
- export { CUSTOM_ELEMENTS_JS, JAR_MN } from './furnace-constants.js';
19
18
  /**
20
19
  * Adds a custom element registration entry to customElements.js.
21
20
  *
@@ -49,7 +49,6 @@ function formatMarkerSuffix(markerComment) {
49
49
  // Re-export from split modules so existing import sites continue working
50
50
  export { removeCustomElementRegistration } from './furnace-registration-remove.js';
51
51
  // Re-export constants so existing import sites continue working
52
- export { CUSTOM_ELEMENTS_JS, JAR_MN } from './furnace-constants.js';
53
52
  // ---------------------------------------------------------------------------
54
53
  // Helpers
55
54
  // ---------------------------------------------------------------------------
@@ -1,4 +1,3 @@
1
- export { CUSTOM_ELEMENTS_JS, JAR_MN } from './furnace-constants.js';
2
1
  export { addCustomElementRegistration, removeCustomElementRegistration, validateCustomElementRegistration, } from './furnace-registration-ast.js';
3
2
  /**
4
3
  * Adds jar.mn entries that map chrome:// URIs to on-disk paths for a
@@ -27,7 +26,7 @@ export { addCustomElementRegistration, removeCustomElementRegistration, validate
27
26
  *
28
27
  * If Firefox upstream changes the jar.mn section ordering or switches to a
29
28
  * different resource registration mechanism, the preflight validation in
30
- * `validateJarMnEntries` will catch the format mismatch before any writes
29
+ * `validateJarMnInsertionForFiles` will catch the format mismatch before any writes
31
30
  * occur.
32
31
  *
33
32
  * @param engineDir - Path to the Firefox engine source root
@@ -76,4 +75,4 @@ export declare function removeJarMnEntries(engineDir: string, tagName: string):
76
75
  * Validates that jar.mn entries *could* be added without writing anything.
77
76
  * Used by dry-run to surface structural problems early.
78
77
  */
79
- export declare function validateJarMnEntries(engineDir: string, tagName: string, files: string[]): Promise<void>;
78
+ export declare function validateJarMnInsertionForFiles(engineDir: string, tagName: string, files: string[]): Promise<void>;
@@ -21,7 +21,6 @@ function detectJarMnIndent(lines) {
21
21
  return ' ';
22
22
  }
23
23
  // Re-export everything from the AST module so existing imports keep working
24
- export { CUSTOM_ELEMENTS_JS, JAR_MN } from './furnace-constants.js';
25
24
  export { addCustomElementRegistration, removeCustomElementRegistration, validateCustomElementRegistration, } from './furnace-registration-ast.js';
26
25
  import { JAR_MN } from './furnace-constants.js';
27
26
  /**
@@ -51,7 +50,7 @@ import { JAR_MN } from './furnace-constants.js';
51
50
  *
52
51
  * If Firefox upstream changes the jar.mn section ordering or switches to a
53
52
  * different resource registration mechanism, the preflight validation in
54
- * `validateJarMnEntries` will catch the format mismatch before any writes
53
+ * `validateJarMnInsertionForFiles` will catch the format mismatch before any writes
55
54
  * occur.
56
55
  *
57
56
  * @param engineDir - Path to the Firefox engine source root
@@ -237,7 +236,7 @@ export async function removeJarMnEntries(engineDir, tagName) {
237
236
  * Validates that jar.mn entries *could* be added without writing anything.
238
237
  * Used by dry-run to surface structural problems early.
239
238
  */
240
- export async function validateJarMnEntries(engineDir, tagName, files) {
239
+ export async function validateJarMnInsertionForFiles(engineDir, tagName, files) {
241
240
  const filePath = join(engineDir, JAR_MN);
242
241
  if (!(await pathExists(filePath))) {
243
242
  throw new FurnaceError('jar.mn not found in engine', tagName);
@@ -1,10 +1,4 @@
1
1
  import type { GitStatusEntry } from './git-base.js';
2
- /**
3
- * Discards changes to a specific file.
4
- * @param repoDir - Repository directory
5
- * @param filePath - Path to the file (relative to repo)
6
- */
7
- export declare function discardFile(repoDir: string, filePath: string): Promise<void>;
8
2
  /**
9
3
  * Restores a tracked path from HEAD, including staged changes.
10
4
  * @param repoDir - Repository directory
@@ -5,14 +5,6 @@ import { GitError } from '../errors/git.js';
5
5
  import { removeFile } from '../utils/fs.js';
6
6
  import { exec } from '../utils/process.js';
7
7
  import { ensureGit, git } from './git-base.js';
8
- /**
9
- * Discards changes to a specific file.
10
- * @param repoDir - Repository directory
11
- * @param filePath - Path to the file (relative to repo)
12
- */
13
- export async function discardFile(repoDir, filePath) {
14
- await restoreTrackedPath(repoDir, filePath);
15
- }
16
8
  /**
17
9
  * Restores a tracked path from HEAD, including staged changes.
18
10
  * @param repoDir - Repository directory
@@ -20,12 +20,6 @@ export declare function getWorkingTreeStatus(repoDir: string): Promise<GitStatus
20
20
  * @returns Status entries with untracked directories expanded to individual files
21
21
  */
22
22
  export declare function expandUntrackedDirectoryEntries(repoDir: string, entries: GitStatusEntry[]): Promise<GitStatusEntry[]>;
23
- /**
24
- * Gets the list of modified files.
25
- * @param repoDir - Repository directory
26
- * @returns List of modified file paths
27
- */
28
- export declare function getModifiedFiles(repoDir: string): Promise<string[]>;
29
23
  /**
30
24
  * Gets all untracked files (including files inside untracked directories).
31
25
  * @param repoDir - Repository directory
@@ -55,11 +49,3 @@ export declare function getModifiedFilesInDir(repoDir: string, dir: string): Pro
55
49
  * @returns List of dirty file paths
56
50
  */
57
51
  export declare function getDirtyFiles(repoDir: string, files: string[]): Promise<string[]>;
58
- /**
59
- * Lists all files in a directory (tracked and untracked, respecting .gitignore).
60
- * Combines git ls-files for tracked files and --others for untracked files.
61
- * @param repoDir - Repository directory
62
- * @param dir - Directory path (relative to repo root)
63
- * @returns List of file paths relative to repo root
64
- */
65
- export declare function listAllFilesInDir(repoDir: string, dir: string): Promise<string[]>;
@@ -72,15 +72,6 @@ export async function expandUntrackedDirectoryEntries(repoDir, entries) {
72
72
  }
73
73
  return expanded;
74
74
  }
75
- /**
76
- * Gets the list of modified files.
77
- * @param repoDir - Repository directory
78
- * @returns List of modified file paths
79
- */
80
- export async function getModifiedFiles(repoDir) {
81
- const entries = await getWorkingTreeStatus(repoDir);
82
- return entries.map((entry) => entry.file);
83
- }
84
75
  /**
85
76
  * Gets all untracked files (including files inside untracked directories).
86
77
  * @param repoDir - Repository directory
@@ -134,19 +125,4 @@ export async function getDirtyFiles(repoDir, files) {
134
125
  const untracked = untrackedOutput.split('\n').filter((line) => line.trim().length > 0);
135
126
  return [...new Set([...tracked, ...untracked])].sort();
136
127
  }
137
- /**
138
- * Lists all files in a directory (tracked and untracked, respecting .gitignore).
139
- * Combines git ls-files for tracked files and --others for untracked files.
140
- * @param repoDir - Repository directory
141
- * @param dir - Directory path (relative to repo root)
142
- * @returns List of file paths relative to repo root
143
- */
144
- export async function listAllFilesInDir(repoDir, dir) {
145
- await ensureGit();
146
- const trackedOutput = await git(['ls-files', '--', dir], repoDir);
147
- const trackedFiles = trackedOutput.split('\n').filter((line) => line.trim().length > 0);
148
- const untrackedOutput = await git(['ls-files', '--others', '--exclude-standard', '--', dir], repoDir);
149
- const untrackedFiles = untrackedOutput.split('\n').filter((line) => line.trim().length > 0);
150
- return [...new Set([...trackedFiles, ...untrackedFiles])].sort();
151
- }
152
128
  //# sourceMappingURL=git-status.js.map
@@ -1,4 +1,3 @@
1
- export type { GitStatusEntry } from './git-base.js';
2
1
  /**
3
2
  * Checks if a directory is a git repository.
4
3
  * @param dir - Directory to check
@@ -1,6 +1,6 @@
1
1
  import { type SmokeLineCallback, type SmokeRunResult } from '../utils/process.js';
2
- export { attemptMozinfoRewrite, type BuildArtifactCheck, buildArtifactMismatchMessage, hasBuildArtifacts, hasRunnableBundle, type MozinfoRewriteResult, type RunnableBundleCheck, } from './mach-build-artifacts.js';
3
- export { generateMozconfig, type MozconfigVariables } from './mach-mozconfig.js';
2
+ export { attemptMozinfoRewrite, buildArtifactMismatchMessage, hasBuildArtifacts, hasRunnableBundle, } from './mach-build-artifacts.js';
3
+ export { generateMozconfig } from './mach-mozconfig.js';
4
4
  export { ensurePython, resetResolvedPython } from './mach-python.js';
5
5
  /**
6
6
  * Ensures mach is available in the engine directory.
@@ -6,8 +6,8 @@ import type { ImportSummary, PatchResult } from '../types/commands/index.js';
6
6
  export { PatchError } from '../errors/patch.js';
7
7
  export { countPatches, discoverPatches, getAllTargetFilesFromPatch, getTargetFileFromPatch, isNewFilePatch, } from './patch-files.js';
8
8
  export { withPatchDirectoryLock } from './patch-lock.js';
9
- export { extractAffectedFiles, extractOrder, isNewFileInPatch, parseHunksForFile, } from './patch-parse.js';
10
- export { applyPatchToContent, extractNewFileContent, extractNewFileContentFromDiff, } from './patch-transform.js';
9
+ export { extractAffectedFiles, extractOrder, isNewFileInPatch } from './patch-parse.js';
10
+ export { applyPatchToContent, extractNewFileContent } from './patch-transform.js';
11
11
  /**
12
12
  * Applies all patches in order. Rolls back all successfully applied
13
13
  * patches when one fails so the engine directory stays clean.
@@ -21,8 +21,8 @@ import { applyPatchToContent, extractNewFileContent } from './patch-transform.js
21
21
  export { PatchError } from '../errors/patch.js';
22
22
  export { countPatches, discoverPatches, getAllTargetFilesFromPatch, getTargetFileFromPatch, isNewFilePatch, } from './patch-files.js';
23
23
  export { withPatchDirectoryLock } from './patch-lock.js';
24
- export { extractAffectedFiles, extractOrder, isNewFileInPatch, parseHunksForFile, } from './patch-parse.js';
25
- export { applyPatchToContent, extractNewFileContent, extractNewFileContentFromDiff, } from './patch-transform.js';
24
+ export { extractAffectedFiles, extractOrder, isNewFileInPatch } from './patch-parse.js';
25
+ export { applyPatchToContent, extractNewFileContent } from './patch-transform.js';
26
26
  /**
27
27
  * Applies a single patch.
28
28
  * @param patch - Patch info
@@ -2,8 +2,5 @@
2
2
  * Public re-exports for {@link ./patch-lint.ts}. Split out so the
3
3
  * orchestrator stays within the ESLint `max-lines` budget.
4
4
  */
5
- export { runCheckJs } from './patch-lint-checkjs.js';
6
- export { buildPatchQueueContext, collectNewFileCreatorsByPath, type ExtractedSpecifier, extractImportSpecifiers, extractImportSpecifiersWithLines, findForwardImportIgnoreLines, FORWARD_IMPORT_IGNORE_MARKER, isForwardImportableFile, lintPatchQueue, lintPatchQueueDuplicateCreations, lintPatchQueueForwardImports, type PatchQueueContext, type PatchQueueEntry, } from './patch-lint-cross.js';
5
+ export { buildPatchQueueContext, collectNewFileCreatorsByPath, extractImportSpecifiers, extractImportSpecifiersWithLines, findForwardImportIgnoreLines, FORWARD_IMPORT_IGNORE_MARKER, isForwardImportableFile, lintPatchQueue, lintPatchQueueDuplicateCreations, lintPatchQueueForwardImports, type PatchQueueContext, type PatchQueueEntry, } from './patch-lint-cross.js';
7
6
  export { buildModifiedFileAdditionsFromDiff, detectNewFilesInDiff } from './patch-lint-diff.js';
8
- export { type JsDocCheck, type JsDocIssue, validateExportJsDoc } from './patch-lint-jsdoc.js';
9
- export { resolvePatchOwnedChromeScripts, resolvePatchOwnedSysMjs } from './patch-lint-ownership.js';
@@ -3,9 +3,6 @@
3
3
  * Public re-exports for {@link ./patch-lint.ts}. Split out so the
4
4
  * orchestrator stays within the ESLint `max-lines` budget.
5
5
  */
6
- export { runCheckJs } from './patch-lint-checkjs.js';
7
6
  export { buildPatchQueueContext, collectNewFileCreatorsByPath, extractImportSpecifiers, extractImportSpecifiersWithLines, findForwardImportIgnoreLines, FORWARD_IMPORT_IGNORE_MARKER, isForwardImportableFile, lintPatchQueue, lintPatchQueueDuplicateCreations, lintPatchQueueForwardImports, } from './patch-lint-cross.js';
8
7
  export { buildModifiedFileAdditionsFromDiff, detectNewFilesInDiff } from './patch-lint-diff.js';
9
- export { validateExportJsDoc } from './patch-lint-jsdoc.js';
10
- export { resolvePatchOwnedChromeScripts, resolvePatchOwnedSysMjs } from './patch-lint-ownership.js';
11
8
  //# sourceMappingURL=patch-lint-reexports.js.map
@@ -4,9 +4,8 @@
4
4
  * Callers should continue to import from this module; the internal split
5
5
  * is an implementation detail.
6
6
  */
7
- export type { PatchManifestConsistencyIssue } from './patch-manifest-consistency.js';
8
7
  export { rebuildPatchesManifest, validatePatchesManifestConsistency, } from './patch-manifest-consistency.js';
9
- export { addPatchToManifest, loadPatchesManifest, PatchDeleteRollbackError, PATCHES_MANIFEST, type PatchRenameEntry, removePatchFileAndManifest, removePatchFromManifest, renumberPatchesInManifest, savePatchesManifest, } from './patch-manifest-io.js';
8
+ export { addPatchToManifest, loadPatchesManifest, PATCHES_MANIFEST, type PatchRenameEntry, removePatchFileAndManifest, renumberPatchesInManifest, savePatchesManifest, } from './patch-manifest-io.js';
10
9
  export { checkVersionCompatibility, findPatchesAffectingFile, getClaimedFiles, stampPatchVersions, validatePatchIntegrity, } from './patch-manifest-query.js';
11
10
  export { resolvePatchIdentifier } from './patch-manifest-resolve.js';
12
11
  export { validatePatchesManifest } from './patch-manifest-validate.js';
@@ -6,7 +6,7 @@
6
6
  * is an implementation detail.
7
7
  */
8
8
  export { rebuildPatchesManifest, validatePatchesManifestConsistency, } from './patch-manifest-consistency.js';
9
- export { addPatchToManifest, loadPatchesManifest, PatchDeleteRollbackError, PATCHES_MANIFEST, removePatchFileAndManifest, removePatchFromManifest, renumberPatchesInManifest, savePatchesManifest, } from './patch-manifest-io.js';
9
+ export { addPatchToManifest, loadPatchesManifest, PATCHES_MANIFEST, removePatchFileAndManifest, renumberPatchesInManifest, savePatchesManifest, } from './patch-manifest-io.js';
10
10
  export { checkVersionCompatibility, findPatchesAffectingFile, getClaimedFiles, stampPatchVersions, validatePatchIntegrity, } from './patch-manifest-query.js';
11
11
  export { resolvePatchIdentifier } from './patch-manifest-resolve.js';
12
12
  export { validatePatchesManifest } from './patch-manifest-validate.js';
@@ -29,11 +29,6 @@
29
29
  * persist pair," not "postpone exit indefinitely."
30
30
  */
31
31
  export declare function runInSignalCriticalSection<T>(label: string, fn: () => Promise<T>): Promise<T>;
32
- /**
33
- * Returns true while any critical section is currently running. Used by the
34
- * bin entry point's signal handler to decide whether to await before exit.
35
- */
36
- export declare function hasActiveCriticalSection(): boolean;
37
32
  /**
38
33
  * Waits for every active critical section to complete or for `timeoutMs` to
39
34
  * elapse, whichever comes first. Never rejects: a section that throws still
@@ -41,9 +36,3 @@ export declare function hasActiveCriticalSection(): boolean;
41
36
  * cleans up in `finally`.
42
37
  */
43
38
  export declare function waitForActiveCriticalSections(timeoutMs: number): Promise<void>;
44
- /**
45
- * Test-only helper: clears the critical-section registry. Production code
46
- * must never call this — it voids the exit-ordering guarantee for any
47
- * section still in flight.
48
- */
49
- export declare function resetCriticalSectionsForTests(): void;
@@ -47,13 +47,6 @@ export async function runInSignalCriticalSection(label, fn) {
47
47
  resolver();
48
48
  }
49
49
  }
50
- /**
51
- * Returns true while any critical section is currently running. Used by the
52
- * bin entry point's signal handler to decide whether to await before exit.
53
- */
54
- export function hasActiveCriticalSection() {
55
- return activeSections.size > 0;
56
- }
57
50
  /**
58
51
  * Waits for every active critical section to complete or for `timeoutMs` to
59
52
  * elapse, whichever comes first. Never rejects: a section that throws still
@@ -69,12 +62,4 @@ export async function waitForActiveCriticalSections(timeoutMs) {
69
62
  new Promise((resolve) => setTimeout(resolve, timeoutMs)),
70
63
  ]);
71
64
  }
72
- /**
73
- * Test-only helper: clears the critical-section registry. Production code
74
- * must never call this — it voids the exit-ordering guarantee for any
75
- * section still in flight.
76
- */
77
- export function resetCriticalSectionsForTests() {
78
- activeSections.clear();
79
- }
80
65
  //# sourceMappingURL=signal-critical.js.map
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Wire targets barrel — re-exports all wiring target modules.
3
3
  */
4
- export { addDestroyAST, addDestroyToBrowserInit, legacyAddDestroy } from './wire-destroy.js';
5
- export { addDomFragment, addDomFragmentTokenized, legacyAddDomFragment, } from './wire-dom-fragment.js';
6
- export { addInitAST, addInitToBrowserInit, legacyAddInit } from './wire-init.js';
7
- export { addSubscriptAST, addSubscriptToBrowserMain, legacyAddSubscript, } from './wire-subscript.js';
4
+ export { addDestroyToBrowserInit } from './wire-destroy.js';
5
+ export { addDomFragment } from './wire-dom-fragment.js';
6
+ export { addInitToBrowserInit } from './wire-init.js';
7
+ export { addSubscriptToBrowserMain } from './wire-subscript.js';
@@ -2,8 +2,8 @@
2
2
  /**
3
3
  * Wire targets barrel — re-exports all wiring target modules.
4
4
  */
5
- export { addDestroyAST, addDestroyToBrowserInit, legacyAddDestroy } from './wire-destroy.js';
6
- export { addDomFragment, addDomFragmentTokenized, legacyAddDomFragment, } from './wire-dom-fragment.js';
7
- export { addInitAST, addInitToBrowserInit, legacyAddInit } from './wire-init.js';
8
- export { addSubscriptAST, addSubscriptToBrowserMain, legacyAddSubscript, } from './wire-subscript.js';
5
+ export { addDestroyToBrowserInit } from './wire-destroy.js';
6
+ export { addDomFragment } from './wire-dom-fragment.js';
7
+ export { addInitToBrowserInit } from './wire-init.js';
8
+ export { addSubscriptToBrowserMain } from './wire-subscript.js';
9
9
  //# sourceMappingURL=wire-targets.js.map
@@ -3,11 +3,6 @@
3
3
  * @param enabled - Whether to enable verbose output
4
4
  */
5
5
  export declare function setVerbose(enabled: boolean): void;
6
- /**
7
- * Checks if verbose mode is enabled.
8
- * @returns True if verbose mode is enabled
9
- */
10
- export declare function isVerbose(): boolean;
11
6
  /**
12
7
  * Displays a verbose/debug message (only shown if verbose mode is enabled).
13
8
  * @param message - Message to display
@@ -14,7 +14,7 @@ export function setVerbose(enabled) {
14
14
  * Checks if verbose mode is enabled.
15
15
  * @returns True if verbose mode is enabled
16
16
  */
17
- export function isVerbose() {
17
+ function isVerbose() {
18
18
  return verboseMode;
19
19
  }
20
20
  /**
@@ -22,7 +22,7 @@ export function isVerbose() {
22
22
  * @param message - Message to display
23
23
  */
24
24
  export function verbose(message) {
25
- if (verboseMode) {
25
+ if (isVerbose()) {
26
26
  p.log.info(`[debug] ${message}`);
27
27
  }
28
28
  }
@@ -14,8 +14,6 @@ interface PackageMetadata {
14
14
  * within a process.
15
15
  */
16
16
  export declare function getPackageRoot(): string;
17
- /** Clears the cached package root for testing. */
18
- export declare function resetPackageRootCacheForTests(): void;
19
17
  /** @internal */
20
18
  export declare function isFireForgePackageMetadata(pkg: PackageMetadata): boolean;
21
19
  /** Reads the current package version from the repository root package manifest. */
@@ -53,10 +53,6 @@ export function getPackageRoot() {
53
53
  current = parent;
54
54
  }
55
55
  }
56
- /** Clears the cached package root for testing. */
57
- export function resetPackageRootCacheForTests() {
58
- cachedPackageRoot = undefined;
59
- }
60
56
  /** @internal */
61
57
  export function isFireForgePackageMetadata(pkg) {
62
58
  if (typeof pkg.bin !== 'object' || pkg.bin === null || Array.isArray(pkg.bin)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hominis/fireforge",
3
- "version": "0.19.3",
3
+ "version": "0.19.4",
4
4
  "description": "FireForge — a build tool for customizing Firefox",
5
5
  "type": "module",
6
6
  "main": "./dist/src/index.js",