Skip to content

feat(config): centralize Effect environment settings - W-22711959 - #911

Merged
mshanemc merged 10 commits into
sm/W-22711959-shadowrepo-effectfrom
sm/W-22711959-central-effect-config
Nov 2, 2026
Merged

mshanemc merged 10 commits into
sm/W-22711959-shadowrepo-effectfrom
sm/W-22711959-central-effect-config

Conversation

@mshanemc

@mshanemc mshanemc commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

What does this PR do?

  • Centralize source-tracking environment settings in an Effect config loader with Effect Config.Boolean parsing, stricter numeric validation, fallback warnings, and legacy aliases.
  • Cache one process-wide settings snapshot and provide it to local, remote, and Git Effect operations.
  • Allow tests to inject a ConfigProvider or explicit config service instead of mutating global environment.

Configuration compatibility inventory

Compared against the installed Kit Env.getNumber/Env.getBoolean implementation and the previous source-tracking call sites. This PR is stacked on #888, which already migrated several reads to Effect; differences specific to that base are called out below.

Numeric input: stricter than Kit

Kit uses Lodash toNumber, without field-specific range/integer validation. The new config rejects the following inputs and uses the setting's default:

Input Kit parsing New config
Hexadecimal (0x10), binary (0b10), octal (0o10) 16, 2, 8 Default; validation warning
Infinity, -Infinity, or overflow such as 1e309 Non-finite number Default; validation warning
NaN or malformed text such as bad NaN, or the supplied default if one was passed to getNumber Default; validation warning
Whitespace-only (" ") 0 Default; validation warning
Surrounding whitespace (" 12 ") 12 Default; validation warning
Literal empty string ("") Absent/default Still absent/default with the normal environment provider; no warning. If an injected provider preserves empty strings, validation warns and defaults.

Decimal forms such as +12, 01, and 1e2 remain accepted when their decoded value satisfies the field's constraints. We are not restricting all numbers to digit-only strings.

Field-specific validation and defaults

Setting Accepted value Invalid/missing fallback
SF_SOURCE_TRACKING_FD_PERMITS Positive safe integer (1 through Number.MAX_SAFE_INTEGER) 64 on Windows; 256 elsewhere
SF_SOURCE_TRACKING_LOCK_TIMEOUT_SECONDS Finite number greater than zero; fractions allowed 600 seconds
SF_SOURCE_TRACKING_LOCK_AUTOCLEAR_SECONDS Finite number greater than zero; fractions allowed 300 seconds
SF_SOURCE_MEMBER_POLLING_TIMEOUT Finite number greater than zero; fractions allowed Size-based timeout: Math.ceil(memberCount * 0.05) + 5 seconds; empty-result limit 120
SF_SOURCE_TRACKING_FILE_VERSION Non-negative safe integer, including zero 0
  • Negative numbers are rejected for all numeric settings. Zero is rejected for permits and timeouts, but remains valid for file version.
  • Fractional values are rejected for permits and file version, not for timeouts. Integers outside JavaScript's safe-integer range are rejected for permits and file version; finite timeout values do not have that safe-integer restriction.
  • Kit parsed negative, zero, fractional, and unsafe-integer values without these field checks. Some callers already imposed additional behavior: the old overall polling timeout ignored non-positive overrides, but its separately calculated empty-result limit could still become zero, negative, or NaN. Config now rejects the override consistently for both settings.
  • File version is still not an enum: other valid non-negative safe integers remain accepted. Only 1 selects the v1 format; other accepted values continue to select the legacy format. Rejecting negative/fractional values normally changes the warning/defaulting, not the selected format.

Legacy aliases and batching

  • Polling retains SFDX_DISABLE_SOURCE_MEMBER_POLLING and SFDX_SOURCE_MEMBER_POLLING_TIMEOUT as deprecated aliases for their SF_ equivalents. These were supported by Core's Kit-based environment handling; this PR restores explicit alias handling relative to feat(git): replace isomorphic-git with Effect Git - W-22711959 #888's base.
  • SF_SOURCE_TRACKING_BATCH_SIZE, then SFDX_SOURCE_TRACKING_BATCH_SIZE, are deprecated aliases for SF_SOURCE_TRACKING_FD_PERMITS. They now limit concurrent file descriptors rather than isomorphic-git batch length. Alias values are validated as positive safe integers and capped at 64 on Windows / 256 elsewhere. Smaller values remain effective; an explicit valid SF_SOURCE_TRACKING_FD_PERMITS is not capped.
  • The old Kit batch-size defaults were 8000 on Windows / 15000 elsewhere. The FD-permit setting and its 64/256 defaults already exist in feat(git): replace isomorphic-git with Effect Git - W-22711959 #888; this PR adds the legacy aliases and their cap, rather than introducing the new Git engine/concurrency model.
  • A present, non-empty canonical value wins even when invalid: it warns and uses the default instead of selecting an alias. In particular, old nested Kit batch-size reads could use the legacy value as the fallback for a malformed canonical batch-size value. Empty canonical values count as absent, allowing an alias.
  • Selecting a deprecated alias emits a lifecycle warning. An explicitly configured FD-permit value also warns when it causes a legacy batch-size setting to be ignored.

Booleans, warnings, and evaluation timing

  • Boolean settings use Effect Config.Boolean: lowercase true/false, yes/no, on/off, y/n, and 1/0. Compared with Kit, mixed-case words such as TRUE no longer parse (they warn and default to false); yes/on/y now mean true, and no/off/n are accepted as false. Invalid non-empty values warn and default to false.
  • Relative to feat(git): replace isomorphic-git with Effect Git - W-22711959 #888, SF_SOURCE_TRACKING_INTEGRITY_CHECK now uses the same Config.Boolean literals instead of enabling only for exact lowercase true: lowercase yes/on/y/1 also enable it. Uppercase TRUE is invalid and defaults to false with a warning.
  • Validation/deprecation warnings use Lifecycle.emitWarning, not Effect's console logger. Core may emit a Node process warning when no lifecycle warning listener is installed.
  • All settings are loaded together and cached once, lazily on first process-runtime execution. Later environment mutations do not change settings or repeat their validation warnings. Previously several settings were read per operation, while batch size and the empty-poll limit were captured at module load. Invalid settings can now warn even if that operation does not use them.
  • Provider/source errors still fail rather than being mistaken for invalid values and silently defaulted.

What was already enforced on #888's base

  • Numeric environment parsing already used Effect's stricter string syntax at several call sites. Hex/binary/octal/whitespace rejection is a difference from Kit, not universally a new difference introduced by this PR.
  • Lock timeout/autoclear already rejected non-finite and non-positive values and used the same defaults. This PR centralizes that behavior and adds lifecycle validation warnings.
  • FD permits already had positive-integer schema validation, but invalid values reaching that schema could fail repository construction. This PR recovers invalid config to the platform default with a warning.
  • Invalid file-version text could fail the tracking-file write through Effect.orDie; this PR warns and uses version 0 instead.
  • Normal polling behavior is unchanged: one-second interval; count-driven overall timeout when no valid override is configured; 120 consecutive empty results after some results arrive, or a limit derived from a valid configured timeout. These decisions now live in config rather than in consumers.

Verification: exercised the installed Kit and current config loader with radix-prefixed numbers, infinities, NaN, malformed text, empty/whitespace strings, signed/leading-zero/scientific decimal forms, fractions, negatives, zero, unsafe integers, and boolean spellings.

What issues does this PR fix or reference?

@W-22711959@

@mshanemc
mshanemc force-pushed the sm/W-22711959-shadowrepo-effect branch from c9accca to f7f686d Compare November 2, 2026 17:46
@mshanemc
mshanemc requested a review from a team as a code owner November 2, 2026 17:46
@mshanemc
mshanemc force-pushed the sm/W-22711959-central-effect-config branch from 7bdcc77 to 2b6f0fa Compare November 2, 2026 18:22
@mshanemc
mshanemc force-pushed the sm/W-22711959-central-effect-config branch from 2b6f0fa to 8416a5b Compare November 2, 2026 18:24
@mshanemc
mshanemc merged commit 8651c32 into sm/W-22711959-shadowrepo-effect Nov 2, 2026
21 checks passed
@mshanemc
mshanemc deleted the sm/W-22711959-central-effect-config branch November 2, 2026 21:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant