@optique/core 1.3.0-dev.2428 → 1.3.0-dev.2431

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.
@@ -404,6 +404,17 @@ async function collectExplicitSourceValuesAsync(nodes, runtime) {
404
404
  * @since 1.3.0
405
405
  */
406
406
  function orderDependencyNodes(nodes) {
407
+ return drainDependencyGraph(buildDependencyGraph(nodes));
408
+ }
409
+ /**
410
+ * Builds the provider-edge graph over runtime nodes.
411
+ *
412
+ * Scheduling barriers act as providers for the source IDs their
413
+ * selected subtree may expose and depend on their discriminator source
414
+ * as well as on outer providers of the completion dependencies their
415
+ * selectable subtrees aggregate.
416
+ */
417
+ function buildDependencyGraph(nodes) {
407
418
  const providers = /* @__PURE__ */ new Map();
408
419
  const addProvider = (sourceId, node) => {
409
420
  const existing = providers.get(sourceId);
@@ -418,51 +429,162 @@ function orderDependencyNodes(nodes) {
418
429
  const outgoing = /* @__PURE__ */ new Map();
419
430
  const indegree = /* @__PURE__ */ new Map();
420
431
  for (const node of nodes) indegree.set(node, 0);
421
- const addEdge = (provider, consumer) => {
422
- const edges = outgoing.get(provider) ?? /* @__PURE__ */ new Set();
423
- if (edges.has(consumer)) return;
424
- edges.add(consumer);
432
+ const addEdge = (provider, consumer, advisory) => {
433
+ const edges = outgoing.get(provider) ?? /* @__PURE__ */ new Map();
434
+ const existing = edges.get(consumer);
435
+ if (existing != null) {
436
+ if (existing && !advisory) edges.set(consumer, false);
437
+ return;
438
+ }
439
+ edges.set(consumer, advisory);
425
440
  outgoing.set(provider, edges);
426
441
  indegree.set(consumer, (indegree.get(consumer) ?? 0) + 1);
427
442
  };
428
443
  for (const node of nodes) {
429
444
  const derived = node.parser.dependencyMetadata?.derived;
430
- if (derived != null) for (const dependencySourceId of derived.dependencyIds) for (const provider of providers.get(dependencySourceId) ?? []) addEdge(provider, node);
445
+ if (derived != null) for (const dependencySourceId of derived.dependencyIds) for (const provider of providers.get(dependencySourceId) ?? []) addEdge(provider, node, false);
431
446
  const completion = node.parser.dependencyMetadata?.completion;
432
447
  if (completion != null && !hasInactiveCompletion(node)) {
433
448
  const ownSourceId = node.parser.dependencyMetadata?.source?.sourceId;
434
449
  for (const dependencySourceId of completion.dependencyIds) {
435
450
  if (dependencySourceId === ownSourceId) continue;
436
- for (const provider of providers.get(dependencySourceId) ?? []) if (provider !== node) addEdge(provider, node);
451
+ for (const provider of providers.get(dependencySourceId) ?? []) if (provider !== node) addEdge(provider, node, false);
437
452
  }
438
453
  }
439
454
  if (node.requiresSourceId != null) {
440
- for (const provider of providers.get(node.requiresSourceId) ?? []) if (provider !== node) addEdge(provider, node);
455
+ for (const provider of providers.get(node.requiresSourceId) ?? []) if (provider !== node) addEdge(provider, node, false);
441
456
  }
442
457
  const barrierDeps = node.barrierCompletionDependencies;
443
458
  if (barrierDeps != null) {
444
- for (const dependencySourceId of barrierDeps.orderingDependencyIds) for (const provider of providers.get(dependencySourceId) ?? []) if (provider !== node) addEdge(provider, node);
459
+ const advisory = node.barrierResolutionState !== "resolved";
460
+ for (const dependencySourceId of barrierDeps.orderingDependencyIds) for (const provider of providers.get(dependencySourceId) ?? []) if (provider !== node) addEdge(provider, node, advisory);
445
461
  }
446
462
  }
447
463
  const declarationOrder = new Map(nodes.map((node, index) => [node, index]));
464
+ return {
465
+ nodes,
466
+ outgoing,
467
+ indegree,
468
+ declarationOrder
469
+ };
470
+ }
471
+ /**
472
+ * Drains the graph in stable topological order.
473
+ *
474
+ * A stall—no node with indegree zero remains—normally means a genuine
475
+ * cycle. When the stalled region contains an unresolved barrier's
476
+ * advisory ordering edges within one strongly connected component, the
477
+ * apparent cycle aggregates edges from branches that cannot be selected
478
+ * together, so those advisory edges are relaxed and the drain resumes;
479
+ * the barrier's own resolution later replaces the estimate with
480
+ * concrete edges, and a cycle among those still throws.
481
+ *
482
+ * @throws {TypeError} If active provider edges contain a cycle.
483
+ */
484
+ function drainDependencyGraph(graph) {
485
+ const { nodes, outgoing, declarationOrder } = graph;
486
+ const indegree = new Map(graph.indegree);
448
487
  const ready = nodes.filter((node) => indegree.get(node) === 0);
449
488
  const ordered = [];
450
- while (ready.length > 0) {
451
- ready.sort((left, right) => declarationOrder.get(left) - declarationOrder.get(right));
452
- const node = ready.shift();
453
- ordered.push(node);
454
- for (const consumer of outgoing.get(node) ?? []) {
455
- const next = (indegree.get(consumer) ?? 0) - 1;
456
- indegree.set(consumer, next);
457
- if (next === 0) ready.push(consumer);
489
+ while (true) {
490
+ while (ready.length > 0) {
491
+ ready.sort((left, right) => declarationOrder.get(left) - declarationOrder.get(right));
492
+ const node = ready.shift();
493
+ ordered.push(node);
494
+ for (const consumer of outgoing.get(node)?.keys() ?? []) {
495
+ const next = (indegree.get(consumer) ?? 0) - 1;
496
+ indegree.set(consumer, next);
497
+ if (next === 0) ready.push(consumer);
498
+ }
499
+ }
500
+ if (ordered.length === nodes.length) return ordered;
501
+ const residual = nodes.filter((node) => (indegree.get(node) ?? 0) > 0);
502
+ const sccOf = findStronglyConnected(residual, outgoing);
503
+ let relaxed = false;
504
+ for (const provider of residual) {
505
+ const edges = outgoing.get(provider);
506
+ if (edges == null) continue;
507
+ for (const [consumer, advisory] of edges) {
508
+ if (!advisory) continue;
509
+ const providerScc = sccOf.get(provider);
510
+ if (providerScc == null || providerScc !== sccOf.get(consumer)) continue;
511
+ edges.delete(consumer);
512
+ const next = (indegree.get(consumer) ?? 0) - 1;
513
+ indegree.set(consumer, next);
514
+ if (next === 0) ready.push(consumer);
515
+ relaxed = true;
516
+ }
517
+ }
518
+ if (!relaxed) {
519
+ const labels = residual.map(formatDependencyNodeLabel).join(" -> ");
520
+ throw new TypeError(`Circular dependency detected among dependency sources: ${labels}.`);
458
521
  }
459
522
  }
460
- if (ordered.length !== nodes.length) {
461
- const cycle = nodes.filter((node) => (indegree.get(node) ?? 0) > 0);
462
- const labels = cycle.map(formatDependencyNodeLabel).join(" -> ");
463
- throw new TypeError(`Circular dependency detected among dependency sources: ${labels}.`);
464
- }
465
- return ordered;
523
+ }
524
+ /**
525
+ * Assigns each node in `subset` to a strongly connected component of
526
+ * the induced subgraph. Only components with more than one node are
527
+ * recorded—an acyclic node cannot be part of an apparent cycle.
528
+ */
529
+ function findStronglyConnected(subset, outgoing) {
530
+ const inSubset = new Set(subset);
531
+ const index = /* @__PURE__ */ new Map();
532
+ const lowLink = /* @__PURE__ */ new Map();
533
+ const onStack = /* @__PURE__ */ new Set();
534
+ const stack = [];
535
+ const sccOf = /* @__PURE__ */ new Map();
536
+ let nextIndex = 0;
537
+ let nextScc = 0;
538
+ const strongConnect = (root) => {
539
+ const frames = [{
540
+ node: root,
541
+ children: [...outgoing.get(root)?.keys() ?? []].filter((child) => inSubset.has(child)),
542
+ i: 0
543
+ }];
544
+ index.set(root, nextIndex);
545
+ lowLink.set(root, nextIndex);
546
+ nextIndex++;
547
+ stack.push(root);
548
+ onStack.add(root);
549
+ while (frames.length > 0) {
550
+ const frame = frames[frames.length - 1];
551
+ if (frame.i < frame.children.length) {
552
+ const child = frame.children[frame.i++];
553
+ if (!index.has(child)) {
554
+ index.set(child, nextIndex);
555
+ lowLink.set(child, nextIndex);
556
+ nextIndex++;
557
+ stack.push(child);
558
+ onStack.add(child);
559
+ frames.push({
560
+ node: child,
561
+ children: [...outgoing.get(child)?.keys() ?? []].filter((c) => inSubset.has(c)),
562
+ i: 0
563
+ });
564
+ } else if (onStack.has(child)) lowLink.set(frame.node, Math.min(lowLink.get(frame.node), index.get(child)));
565
+ continue;
566
+ }
567
+ frames.pop();
568
+ const node = frame.node;
569
+ if (lowLink.get(node) === index.get(node)) {
570
+ const members = [];
571
+ while (true) {
572
+ const member = stack.pop();
573
+ onStack.delete(member);
574
+ members.push(member);
575
+ if (member === node) break;
576
+ }
577
+ if (members.length > 1) {
578
+ for (const member of members) sccOf.set(member, nextScc);
579
+ nextScc++;
580
+ }
581
+ }
582
+ const parent = frames[frames.length - 1];
583
+ if (parent != null) lowLink.set(parent.node, Math.min(lowLink.get(parent.node), lowLink.get(node)));
584
+ }
585
+ };
586
+ for (const node of subset) if (!index.has(node)) strongConnect(node);
587
+ return sccOf;
466
588
  }
467
589
  /** Resolves and publishes matched derived sources in stable dependency order. */
468
590
  function resolveDerivedSourceValues(nodes, runtime, options) {
@@ -921,6 +1043,35 @@ const sourceCollectionExpansionKey = Symbol("@optique/core/dependency-runtime/so
921
1043
  */
922
1044
  const staticSourceScopeKey = Symbol("@optique/core/dependency-runtime/staticSourceScope");
923
1045
  /**
1046
+ * Static child parsers reachable only through a mutually exclusive
1047
+ * selection, such as `or()` alternatives, a `conditional()`'s branches,
1048
+ * or a `command()`'s inner parser.
1049
+ *
1050
+ * The walk unions sources and completion dependencies from this scope
1051
+ * exactly like {@link staticSourceScopeKey}, but a source occurrence
1052
+ * reached through an exclusive edge is never a *guaranteed* provider:
1053
+ * the run may select a sibling instead, so a scheduling barrier must not
1054
+ * assume the occurrence will publish. See issue #924.
1055
+ *
1056
+ * @internal
1057
+ * @since 1.3.0
1058
+ */
1059
+ const exclusiveSourceScopeKey = Symbol("@optique/core/dependency-runtime/exclusiveSourceScope");
1060
+ /**
1061
+ * Source IDs a parser guarantees to provide on every successful route
1062
+ * through it, regardless of which internal alternative is selected.
1063
+ *
1064
+ * A `conditional()` installs the intersection of its branches' guaranteed
1065
+ * provides here (including the default branch when present), so an outer
1066
+ * scheduling barrier can treat a source that *every* selectable route
1067
+ * publishes as guaranteed even though each individual branch edge is
1068
+ * exclusive. See issue #924.
1069
+ *
1070
+ * @internal
1071
+ * @since 1.3.0
1072
+ */
1073
+ const guaranteedStaticSourceIdsKey = Symbol("@optique/core/dependency-runtime/guaranteedStaticSourceIds");
1074
+ /**
924
1075
  * Forwards effectful scheduling through a shape-preserving wrapper such
925
1076
  * as `map()`, `optional()`, `withDefault()`, or `nonEmpty()`, so the
926
1077
  * wrapped parser—a selected exclusive or command branch, or an ordinary
@@ -1098,17 +1249,54 @@ async function completeEffectfulSourcesAsync(nodes, state, runtime, exec, option
1098
1249
  const schedulable = nodes.filter((node) => node.parser.dependencyMetadata?.source?.completeSource != null || node.prepare != null);
1099
1250
  if (schedulable.length === 0 && options?.includeStructural !== true) return empty;
1100
1251
  const completed = [];
1101
- for (const node of orderDependencyNodes(nodes)) {
1252
+ const barrierContext = {
1253
+ runtime,
1254
+ exec,
1255
+ schedule: (barrierNodes) => completeEffectfulSourcesAsync(barrierNodes, state, runtime, exec, {
1256
+ isReusable: () => false,
1257
+ isCollected: () => true,
1258
+ includeStructural: true
1259
+ }).then((result) => result.success ? void 0 : result)
1260
+ };
1261
+ const pending = [...nodes];
1262
+ const providesId = (node, id) => node.parser.dependencyMetadata?.source?.sourceId === id || node.providesSourceIds?.has(id) === true;
1263
+ const resolveBarrierAt = async (index) => {
1264
+ const candidate = pending[index];
1265
+ const resolution = await candidate.resolveBarrier(barrierContext);
1266
+ if (resolution != null && "success" in resolution) return resolution;
1267
+ pending[index] = resolution == null ? {
1268
+ ...candidate,
1269
+ barrierResolutionState: "unresolvable"
1270
+ } : {
1271
+ ...candidate,
1272
+ barrierResolutionState: "resolved",
1273
+ providesSourceIds: resolution.activeProvidesSourceIds,
1274
+ barrierCompletionDependencies: {
1275
+ orderingDependencyIds: resolution.orderingDependencyIds,
1276
+ demandEdges: []
1277
+ }
1278
+ };
1279
+ return void 0;
1280
+ };
1281
+ while (pending.length > 0) {
1282
+ for (let i = 0; i < pending.length; i++) {
1283
+ const candidate = pending[i];
1284
+ if (candidate.resolveBarrier == null || candidate.barrierResolutionState != null) continue;
1285
+ const requires = candidate.requiresSourceId;
1286
+ if (requires == null) continue;
1287
+ if (pending.some((other) => other !== candidate && providesId(other, requires))) continue;
1288
+ const failure = await resolveBarrierAt(i);
1289
+ if (failure != null) return failure;
1290
+ }
1291
+ const node = orderDependencyNodes(pending)[0];
1292
+ if (node.resolveBarrier != null && node.barrierResolutionState == null) {
1293
+ const failure = await resolveBarrierAt(pending.indexOf(node));
1294
+ if (failure != null) return failure;
1295
+ continue;
1296
+ }
1297
+ pending.splice(pending.indexOf(node), 1);
1102
1298
  if (node.prepare != null) {
1103
- const barrierFailure = await node.prepare({
1104
- runtime,
1105
- exec,
1106
- schedule: (barrierNodes) => completeEffectfulSourcesAsync(barrierNodes, state, runtime, exec, {
1107
- isReusable: () => false,
1108
- isCollected: () => true,
1109
- includeStructural: true
1110
- }).then((result$1) => result$1.success ? void 0 : result$1)
1111
- });
1299
+ const barrierFailure = await node.prepare(barrierContext);
1112
1300
  if (barrierFailure != null) return barrierFailure;
1113
1301
  continue;
1114
1302
  }
@@ -1140,7 +1328,34 @@ async function completeEffectfulSourcesAsync(nodes, state, runtime, exec, option
1140
1328
  const collected = options?.isCollected?.(node) ?? options?.isReusable?.(node) ?? true;
1141
1329
  if (source.extractSourceValue == null || collected === false) continue;
1142
1330
  const extracted = await source.extractSourceValue(node.state);
1143
- if (extracted?.success === true && extracted.value !== void 0) runtime.registerSource(source.sourceId, extracted.value);
1331
+ if (extracted?.success === true && extracted.value !== void 0) {
1332
+ runtime.registerSource(source.sourceId, extracted.value);
1333
+ continue;
1334
+ }
1335
+ if (options?.includeStructural === true && extracted?.success !== false && node.matched !== true && source.preservesSourceValue && source.getMissingSourceValue != null && !runtime.hasSource(source.sourceId) && !runtime.isSourceFailed(source.sourceId)) {
1336
+ let fallback = session?.missingDefaultsByOccurrence.get(source.getMissingSourceValue);
1337
+ if (fallback == null) {
1338
+ try {
1339
+ fallback = await source.getMissingSourceValue();
1340
+ } catch (e) {
1341
+ const msg = e instanceof Error ? e.message : String(e);
1342
+ fallback = {
1343
+ success: false,
1344
+ error: message`Default value evaluation failed: ${msg}`
1345
+ };
1346
+ }
1347
+ session?.missingDefaultsByOccurrence.set(source.getMissingSourceValue, fallback);
1348
+ }
1349
+ if (fallback.success) runtime.registerSource(source.sourceId, fallback.value);
1350
+ else {
1351
+ runtime.markSourceFailed(source.sourceId);
1352
+ propagateRuntimeSourceFailures(nodes, runtime);
1353
+ return {
1354
+ success: false,
1355
+ error: includeSourceFailureChain(fallback.error, source.sourceId, runtime)
1356
+ };
1357
+ }
1358
+ }
1144
1359
  continue;
1145
1360
  }
1146
1361
  const pathKey = serializeSchedulingPath(node.path);
@@ -1466,4 +1681,4 @@ function getDefaultDependencySnapshotInner(state, visited) {
1466
1681
  }
1467
1682
 
1468
1683
  //#endregion
1469
- export { buildRuntimeNodesFromArray, buildRuntimeNodesFromPairs, collectDemandedDependencyIds, collectExplicitSourceValues, collectExplicitSourceValuesAsync, collectSourcesFromState, completeEffectfulSourcesAsync, createDependencyFingerprint, createDependencyRuntimeContext, createReplayKey, defineForwardedEffectfulSchedulingNodes, derivedRawInputKey, effectfulSchedulingNodesKey, extractRawInputFromState, fillMissingSourceDefaults, fillMissingSourceDefaultsAsync, hasInactiveCompletion, includeSourceFailureChain, orderDependencyNodes, recordDerivedRawInput, replayDerivedParser, replayDerivedParserAsync, resolveDerivedSourceValues, resolveDerivedSourceValuesAsync, resolveStateWithRuntime, resolveStateWithRuntimeAsync, serializeSchedulingPath, sourceCollectionExpansionKey, staticSourceScopeKey };
1684
+ export { buildRuntimeNodesFromArray, buildRuntimeNodesFromPairs, collectDemandedDependencyIds, collectExplicitSourceValues, collectExplicitSourceValuesAsync, collectSourcesFromState, completeEffectfulSourcesAsync, createDependencyFingerprint, createDependencyRuntimeContext, createReplayKey, defineForwardedEffectfulSchedulingNodes, derivedRawInputKey, effectfulSchedulingNodesKey, exclusiveSourceScopeKey, extractRawInputFromState, fillMissingSourceDefaults, fillMissingSourceDefaultsAsync, guaranteedStaticSourceIdsKey, hasInactiveCompletion, includeSourceFailureChain, orderDependencyNodes, recordDerivedRawInput, replayDerivedParser, replayDerivedParserAsync, resolveDerivedSourceValues, resolveDerivedSourceValuesAsync, resolveStateWithRuntime, resolveStateWithRuntimeAsync, serializeSchedulingPath, sourceCollectionExpansionKey, staticSourceScopeKey };
@@ -26,7 +26,8 @@ function createEffectfulCompletionSession(policy = "eager") {
26
26
  demanded: /* @__PURE__ */ new Set(),
27
27
  effectfulSources: /* @__PURE__ */ new Set(),
28
28
  completedByPath: /* @__PURE__ */ new Map(),
29
- preparedByPath: /* @__PURE__ */ new Map()
29
+ preparedByPath: /* @__PURE__ */ new Map(),
30
+ missingDefaultsByOccurrence: /* @__PURE__ */ new WeakMap()
30
31
  };
31
32
  }
32
33
  /**
@@ -480,6 +480,22 @@ interface EffectfulCompletionSession {
480
480
  * re-completing the discriminator or re-selecting a branch.
481
481
  */
482
482
  readonly preparedByPath: Map<string, unknown>;
483
+ /**
484
+ * Missing-value default results published for structural source
485
+ * occurrences inside a scheduling barrier's nested pass, keyed by the
486
+ * occurrence's composed `getMissingSourceValue` function. The
487
+ * function identifies the exact wrapper instance, so two branches of
488
+ * a `conditional()` sharing a node path never observe each other's
489
+ * defaults even when a phase-two binding changes the selection
490
+ * between passes. Unlike {@link completedByPath} this cache is
491
+ * shared across the passes of a run: a default does not depend on
492
+ * pass-specific state, so caching it keeps a non-idempotent
493
+ * `withDefault()` thunk at one evaluation per run even when the
494
+ * nested pass repeats.
495
+ *
496
+ * @since 1.3.0
497
+ */
498
+ readonly missingDefaultsByOccurrence: WeakMap<object, ValueParserResult<unknown>>;
483
499
  }
484
500
  /**
485
501
  * Creates a fresh {@link EffectfulCompletionSession}.
@@ -480,6 +480,22 @@ interface EffectfulCompletionSession {
480
480
  * re-completing the discriminator or re-selecting a branch.
481
481
  */
482
482
  readonly preparedByPath: Map<string, unknown>;
483
+ /**
484
+ * Missing-value default results published for structural source
485
+ * occurrences inside a scheduling barrier's nested pass, keyed by the
486
+ * occurrence's composed `getMissingSourceValue` function. The
487
+ * function identifies the exact wrapper instance, so two branches of
488
+ * a `conditional()` sharing a node path never observe each other's
489
+ * defaults even when a phase-two binding changes the selection
490
+ * between passes. Unlike {@link completedByPath} this cache is
491
+ * shared across the passes of a run: a default does not depend on
492
+ * pass-specific state, so caching it keeps a non-idempotent
493
+ * `withDefault()` thunk at one evaluation per run even when the
494
+ * nested pass repeats.
495
+ *
496
+ * @since 1.3.0
497
+ */
498
+ readonly missingDefaultsByOccurrence: WeakMap<object, ValueParserResult<unknown>>;
483
499
  }
484
500
  /**
485
501
  * Creates a fresh {@link EffectfulCompletionSession}.
@@ -26,7 +26,8 @@ function createEffectfulCompletionSession(policy = "eager") {
26
26
  demanded: /* @__PURE__ */ new Set(),
27
27
  effectfulSources: /* @__PURE__ */ new Set(),
28
28
  completedByPath: /* @__PURE__ */ new Map(),
29
- preparedByPath: /* @__PURE__ */ new Map()
29
+ preparedByPath: /* @__PURE__ */ new Map(),
30
+ missingDefaultsByOccurrence: /* @__PURE__ */ new WeakMap()
30
31
  };
31
32
  }
32
33
  /**
@@ -1731,7 +1731,7 @@ function command(name, parser, options = {}) {
1731
1731
  configurable: true,
1732
1732
  enumerable: false
1733
1733
  });
1734
- Object.defineProperty(result, require_dependency_runtime.staticSourceScopeKey, {
1734
+ Object.defineProperty(result, require_dependency_runtime.exclusiveSourceScopeKey, {
1735
1735
  value: [parser],
1736
1736
  configurable: true,
1737
1737
  enumerable: false
@@ -4,7 +4,7 @@ import { validateCommandNames, validateOptionNames } from "./validate.js";
4
4
  import { extractOptionNames, isDocHidden, isSuggestionHidden } from "./usage.js";
5
5
  import { dispatchByMode, dispatchIterableByMode, wrapForMode } from "./internal/mode-dispatch.js";
6
6
  import { getDefaultValuesFunction, getDependencyIds, getSnapshottedDefaultDependencyValues, isDerivedValueParser, suggestWithDependency } from "./internal/dependency.js";
7
- import { effectfulSchedulingNodesKey, includeSourceFailureChain, recordDerivedRawInput, replayDerivedParser, replayDerivedParserAsync, sourceCollectionExpansionKey, staticSourceScopeKey } from "./dependency-runtime.js";
7
+ import { effectfulSchedulingNodesKey, exclusiveSourceScopeKey, includeSourceFailureChain, recordDerivedRawInput, replayDerivedParser, replayDerivedParserAsync, sourceCollectionExpansionKey } from "./dependency-runtime.js";
8
8
  import { getWrappedChildParseState, getWrappedChildState, isAnnotationWrappedInitialState, normalizeInjectedAnnotationState } from "./annotation-state.js";
9
9
  import { hiddenCommandAliasesKey } from "./internal/command-alias.js";
10
10
  import { mergeChildExec, withChildContext, withChildExecPath } from "./execution-context.js";
@@ -1731,7 +1731,7 @@ function command(name, parser, options = {}) {
1731
1731
  configurable: true,
1732
1732
  enumerable: false
1733
1733
  });
1734
- Object.defineProperty(result, staticSourceScopeKey, {
1734
+ Object.defineProperty(result, exclusiveSourceScopeKey, {
1735
1735
  value: [parser],
1736
1736
  configurable: true,
1737
1737
  enumerable: false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/core",
3
- "version": "1.3.0-dev.2428",
3
+ "version": "1.3.0-dev.2431",
4
4
  "description": "Type-safe combinatorial command-line interface parser",
5
5
  "keywords": [
6
6
  "CLI",
@@ -221,7 +221,7 @@
221
221
  },
222
222
  "sideEffects": false,
223
223
  "devDependencies": {
224
- "@optique/env": "1.3.0-dev.2428+5fa651a4",
224
+ "@optique/env": "1.3.0-dev.2431+d0d5316a",
225
225
  "@types/node": "^24.0.0",
226
226
  "fast-check": "^4.7.0",
227
227
  "tsdown": "^0.13.0",