@effected/workspaces 0.30.4 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -52,7 +52,7 @@ interface DependencyDiff {
52
52
  readonly added: Record<string, string>;
53
53
  /** Present in the other, absent from the receiver. */
54
54
  readonly removed: Record<string, string>;
55
- /** Present in both at different specifiers. */
55
+ /** Present in both at different specifiers: `from` is the other package's, `to` the receiver's. */
56
56
  readonly changed: Record<string, {
57
57
  readonly from: string;
58
58
  readonly to: string;
@@ -112,13 +112,9 @@ declare const WorkspacePackage_base: Schema.Class<WorkspacePackage, Schema.Struc
112
112
  * Absolute path to the workspace root this package was discovered under.
113
113
  *
114
114
  * @remarks
115
- * Carried, not derived. Whoever built this value already knew the root —
116
- * `WorkspaceDiscovery` resolved it before enumerating, and the sync entry
117
- * point is handed it — so dropping it forced every consumer into per-package
118
- * root arithmetic (counting `relativePath` segments and re-ascending that
119
- * many `..`). That reconstruction is exact only while `path` and
120
- * `relativePath` agree, and it re-derives something the kit never had to
121
- * lose.
115
+ * Carried, not derived: `WorkspaceDiscovery` resolves the root before
116
+ * enumerating, so every package arrives with it and consumers need no
117
+ * per-package root arithmetic over `relativePath`.
122
118
  *
123
119
  * For the root package this equals `path`, and `relativePath` is `"."`.
124
120
  */
@@ -145,8 +141,7 @@ declare const WorkspacePackage_base: Schema.Class<WorkspacePackage, Schema.Struc
145
141
  * validated beyond being a record. For the strict typed model use
146
142
  * `manifest()`, which deliberately **re-reads** the file — a point-in-time
147
143
  * refresh this captured record cannot provide. Defaults to `{}` for
148
- * construction sites and previously-serialized values that predate the
149
- * field.
144
+ * values constructed or decoded without the field.
150
145
  */
151
146
  readonly manifestRecord: Schema.withConstructorDefault<Schema.withDecodingDefaultKey<Schema.$Record<Schema.String, Schema.Unknown>, never>>;
152
147
  }>, {}>;
@@ -209,8 +204,8 @@ export declare class WorkspacePackage extends WorkspacePackage_base {
209
204
  /** The declared specifier for `name`, searched across all four kinds. */
210
205
  dependencyVersion(name: string): Option.Option<string>;
211
206
  /**
212
- * Whether any dependency name matches `pattern` — the `minimatch` runtime
213
- * dependency's one call site, now over `@effected/glob`'s vendored engine.
207
+ * Whether any dependency name (across all four kinds) matches the glob
208
+ * `pattern`, using `@effected/glob`.
214
209
  *
215
210
  * @remarks
216
211
  * A `GlobPattern` is total and free to test. A `string` is compiled on every
@@ -223,7 +218,12 @@ export declare class WorkspacePackage extends WorkspacePackage_base {
223
218
  * @param pattern - A compiled pattern, or a source string to compile.
224
219
  */
225
220
  matchesDependency(pattern: GlobPattern | string): boolean;
226
- /** Compare this package's dependencies against `other`'s. */
221
+ /**
222
+ * Compare this package's dependencies against `other`'s, treating `other` as
223
+ * the baseline: what this package added, removed or re-specified.
224
+ *
225
+ * @param other - The package to compare against.
226
+ */
227
227
  dependencyDiff(other: WorkspacePackage): DependencyDiff;
228
228
  /**
229
229
  * Project to `@effected/lockfiles`' `WorkspaceManifest` — the input shape of
@@ -234,6 +234,10 @@ export declare class WorkspacePackage extends WorkspacePackage_base {
234
234
  * Read and decode this package's `package.json` into the strict
235
235
  * `@effected/package-json` `Package` model — the bridge from the
236
236
  * tolerant discovery projection to the fully typed manifest.
237
+ *
238
+ * @remarks
239
+ * Fails with {@link WorkspaceManifestError} (`kind: "read"` or `"decode"`) and
240
+ * requires core `FileSystem`.
237
241
  */
238
242
  static readonly manifest: (self: WorkspacePackage) => Effect.Effect<Package, WorkspaceManifestError, FileSystem.FileSystem>;
239
243
  /** Instance form of `WorkspacePackage.manifest`. */
@@ -370,12 +374,10 @@ export declare class WorkspaceRoot extends WorkspaceRoot_base {
370
374
  * A test double resolving every `find` to `root`, with no filesystem.
371
375
  *
372
376
  * @remarks
373
- * The nine-copies-of-a-four-line-mock case — a `Layer.succeed` over a `find`
374
- * that ignores its arguments and succeeds with a fixed root is what consumers
375
- * were writing by hand. The difference is that this double **honours
376
- * `stopAt`**: a hand-rolled `find` that ignores the ceiling makes a bounded
377
- * call pass under test and fail against the live service, which is the
378
- * failure mode the option exists to catch. A `root` above the ceiling fails
377
+ * Stands in for a hand-written `Layer.succeed` over a `find` that ignores its
378
+ * arguments. Unlike that, this double **honours `stopAt`**: a `find` that
379
+ * ignores the ceiling makes a bounded call pass under test and fail against
380
+ * the live service, which is the failure mode the option exists to catch. A `root` above the ceiling fails
379
381
  * here exactly as it would live, with the same
380
382
  * {@link WorkspaceRootNotFoundError}.
381
383
  *
@@ -449,7 +451,7 @@ declare const WorkspaceDiscoveryError_base: Schema.Class<WorkspaceDiscoveryError
449
451
  * A manifest with no `version` is NOT a failure: pnpm accepts a version-less
450
452
  * private package and a private monorepo root without one is the ordinary
451
453
  * shape, so the member is discovered with `WorkspacePackage.version` absent.
452
- * The former `missingVersion` kind is retired. Only ABSENCE is tolerated: a
454
+ * Only ABSENCE is tolerated: a
453
455
  * `version` that is present but not a string — or present and `""`, which pnpm
454
456
  * never wrote and which would resolve `workspace:^` to a bare `"^"` — is the
455
457
  * manifest's shape being wrong and reports `invalidShape`.
@@ -558,11 +560,10 @@ interface WorkspaceDiscoveryOptions {
558
560
  * `importerMap`, `getPackage`, `resolveFile`, `resolveFiles`). The per-call
559
561
  * `infoIn`, `listPackagesIn` and `refreshIn` resolve from an arbitrary
560
562
  * directory the caller names, which a single layer-level ceiling cannot
561
- * sensibly bound, so they ascend unbounded as before.
563
+ * sensibly bound, so they ascend unbounded.
562
564
  *
563
565
  * `LockfileReader`, `WorkspaceCatalogs` and `WorkspaceSnapshots` each
564
- * take the same option; give them the same
565
- * value when wiring by hand, or let a `Workspaces.*` composite forward one
566
+ * take the same option; give them the same value when wiring by hand, or let a `Workspaces.*` composite forward one
566
567
  * `stopAt` to all of them, so no service adopts a root another refused.
567
568
  *
568
569
  * @defaultValue no ceiling — the ascent runs to the filesystem root.
@@ -659,11 +660,9 @@ declare const WorkspaceDiscovery_base: Context.ServiceClass<WorkspaceDiscovery,
659
660
  * the lifetime of the layer. A Vitest reporter that builds the layer per call
660
661
  * site and never queries it pays nothing.
661
662
  *
662
- * The memo is **success-only**. `Effect.cached` memoizes the first `Exit`,
663
- * *including an interrupt* — an init interrupted by an unrelated timeout would
664
- * otherwise brick the layer permanently with a cause outside its declared error
665
- * channel. A failure or interrupt is therefore retried on the next call, which
666
- * is a deliberate behaviour change from the v3 library.
663
+ * The memo is **success-only**: a failure or interrupt is not cached, so an
664
+ * init interrupted by an unrelated timeout cannot brick the layer, and the next
665
+ * call retries.
667
666
  *
668
667
  * @example
669
668
  * ```ts
@@ -686,12 +685,14 @@ export declare class WorkspaceDiscovery extends WorkspaceDiscovery_base {
686
685
  */
687
686
  static readonly make: (options?: WorkspaceDiscoveryOptions) => Effect.Effect<WorkspaceDiscoveryShape, never, WorkspaceRoot | FileSystem.FileSystem | Path.Path>;
688
687
  /**
689
- * The live layer.
688
+ * The live layer, discovering the workspace from `options.cwd`.
690
689
  *
691
690
  * @remarks
692
691
  * A parameterized layer factory mints a **fresh reference per call**, and
693
692
  * layers memoize by reference — bind the result to a `const` and reuse it
694
693
  * rather than calling `layer(...)` at each composition site.
694
+ *
695
+ * @param options - Root resolution and enumeration bounds.
695
696
  */
696
697
  static readonly layer: (options?: WorkspaceDiscoveryOptions) => Layer.Layer<WorkspaceDiscovery, never, WorkspaceRoot | FileSystem.FileSystem | Path.Path>;
697
698
  /**
@@ -917,21 +918,19 @@ export declare class ChangeDetector extends ChangeDetector_base {
917
918
  * **after** computing peer violations, in pnpm's own shape.
918
919
  *
919
920
  * @remarks
920
- * The shape is pnpm's rather than ours because that is what comes back off the
921
- * threaded config: measured against `@savvy-web/pnpm-plugin-silk@0.27.0`, a
922
- * replayed hook returns `{ allowedVersions, ignoreMissing, allowAny }` intact,
923
- * needing no reshaping.
924
- *
925
- * All three axes are consumed by `PeerCheck`, each established by measurement
926
- * against `pnpm peers check` with a firing control. `ignoreMissing` and
927
- * `allowAny` are lists of **peer-name patterns** in pnpm's `@pnpm/matcher`
921
+ * The shape is pnpm's own, because that is what comes back off the threaded
922
+ * config: a replayed hook returns `{ allowedVersions, ignoreMissing, allowAny }`
923
+ * intact, needing no reshaping.
924
+ *
925
+ * All three axes are consumed by `PeerCheck`, matching `pnpm peers check`.
926
+ * `ignoreMissing` and `allowAny` are lists of **peer-name patterns** in pnpm's `@pnpm/matcher`
928
927
  * grammar (`*` wildcard, leading `!` negation) — not `parent>peer` keys, which
929
928
  * match nothing on those two axes. `ignoreMissing` hides only a required peer
930
929
  * that resolved to nothing; `allowAny` hides only a peer that resolved outside
931
930
  * its wanted range; the two never cross.
932
931
  *
933
932
  * `allowedVersions` keys come in two spellings in the wild, and both must be
934
- * handled: parent-versioned (`"@effect/ai-anthropic@4.0.0-rc.109>effect"`, as
933
+ * handled: parent-versioned (`"@effect/ai-anthropic@4.0.0>effect"`, as
935
934
  * `pnpm:export` materializes them into `pnpm-workspace.yaml`) and unversioned
936
935
  * (`"@effect/vitest>vitest"`, as a config-dependency plugin injects them).
937
936
  *
@@ -1047,15 +1046,11 @@ interface HookInjection {
1047
1046
  * @remarks
1048
1047
  * Effective rather than hook-only because the rules are **seeded** into the
1049
1048
  * threaded config and the hooks merge onto them, exactly as pnpm seeds its
1050
- * own config and takes back what the hooks return. That is deliberate: a
1051
- * kit-owned merge function would be a second implementation of a rule this
1052
- * seam already enforces, and the two would drift the first time pnpm changed
1053
- * its threading.
1049
+ * own config and takes back what the hooks return, so there is no second
1050
+ * merge implementation to drift from pnpm's threading.
1054
1051
  *
1055
- * Measured caveat, and **not a bug to fix**: this repo's plugin *merges*
1056
- * onto the seeded rules; another plugin could overwrite them. Under seeding
1057
- * that is pnpm's own behaviour reproduced — a hook that overwrites
1058
- * overwrites for pnpm too — so do not "repair" it into a merger.
1052
+ * A plugin whose hook *overwrites* the seeded rules rather than merging
1053
+ * onto them replaces them here exactly as it does under pnpm.
1059
1054
  */
1060
1055
  readonly peerDependencyRules: PeerDependencyRules;
1061
1056
  /**
@@ -1489,8 +1484,9 @@ declare const DependencyGraph_base: Schema.Class<DependencyGraph, Schema.Struct<
1489
1484
  * `dependencies`, `devDependencies`, `peerDependencies` and
1490
1485
  * `optionalDependencies`; a self-edge is dropped.
1491
1486
  *
1492
- * Total accessors never fail; the four fallible operations are `Effect.fn`
1493
- * boundaries.
1487
+ * Total accessors never fail. The lookups fail with `PackageNotFoundError` for
1488
+ * an unknown name, and the ordering operations (`levels`, `sort`, `sortSubset`)
1489
+ * fail with {@link CyclicDependencyError} when the graph has a cycle.
1494
1490
  *
1495
1491
  * @example
1496
1492
  * ```ts
@@ -1525,8 +1521,11 @@ export declare class DependencyGraph extends DependencyGraph_base {
1525
1521
  /** The workspace packages that depend on `name`, sorted. */
1526
1522
  readonly dependentsOf: (name: string) => Effect.Effect<readonly string[], PackageNotFoundError, never>;
1527
1523
  /**
1528
- * `name` plus every package that transitively depends on it — the blast
1529
- * radius of a change. Sorted; includes `name` itself.
1524
+ * Each of `names` plus every package that transitively depends on any of
1525
+ * them — the blast radius of a change. Sorted and de-duplicated; the given
1526
+ * names are included, whether or not the graph knows them.
1527
+ *
1528
+ * @param names - The changed package names.
1530
1529
  */
1531
1530
  readonly affectedBy: (names: readonly string[]) => Effect.Effect<readonly string[], never, never>;
1532
1531
  /**
@@ -1534,9 +1533,8 @@ export declare class DependencyGraph extends DependencyGraph_base {
1534
1533
  * the workspace, level *n* depends only on levels below it.
1535
1534
  *
1536
1535
  * @remarks
1537
- * Kahn's algorithm over the reverse-edge index — linear, where v3's rescanned
1538
- * the whole adjacency map per processed node. Each level is sorted
1539
- * lexicographically, so the output is deterministic.
1536
+ * Kahn's algorithm over the reverse-edge index, linear in the edge count.
1537
+ * Each level is sorted lexicographically, so the output is deterministic.
1540
1538
  */
1541
1539
  readonly levels: () => Effect.Effect<readonly (readonly string[])[], CyclicDependencyError, never>;
1542
1540
  /** The flattened topological order — `levels()` concatenated. */
@@ -1544,6 +1542,13 @@ export declare class DependencyGraph extends DependencyGraph_base {
1544
1542
  /**
1545
1543
  * A topological order over `names` plus their transitive workspace
1546
1544
  * dependencies — the build order for a subset.
1545
+ *
1546
+ * @remarks
1547
+ * Fails with `PackageNotFoundError` for a name the graph does not contain,
1548
+ * and with {@link CyclicDependencyError} when the subset's closure has a
1549
+ * cycle.
1550
+ *
1551
+ * @param names - The packages to build; each must be a workspace package.
1547
1552
  */
1548
1553
  readonly sortSubset: (names: readonly string[]) => Effect.Effect<readonly string[], CyclicDependencyError | PackageNotFoundError, never>;
1549
1554
  /**
@@ -1680,8 +1685,8 @@ declare const DuplicateCheck_base: Schema.Class<DuplicateCheck, Schema.Struct<{
1680
1685
  * In practice this is the **root importer under npm and bun**: neither
1681
1686
  * records a resolved version per importer dependency, and neither emits a
1682
1687
  * package row for the root, so there is nothing to join on. pnpm records a
1683
- * version per importer dependency and is unaffected. The same limitation
1684
- * `PeerCheck` reports, measured by the same code.
1688
+ * version per importer dependency and is unaffected. `PeerCheck` reports the
1689
+ * same limitation.
1685
1690
  *
1686
1691
  * Reported rather than silently skipped: a gate that sees no duplicates is
1687
1692
  * entitled to know whether that means "clean" or "not looked at".
@@ -1702,10 +1707,12 @@ declare const DuplicateCheck_base: Schema.Class<DuplicateCheck, Schema.Struct<{
1702
1707
  *
1703
1708
  * @example
1704
1709
  * ```ts
1705
- * import { DuplicateCheck } from "@effected/workspaces";
1706
1710
  * import { Lockfile } from "@effected/lockfiles";
1711
+ * import { DuplicateCheck } from "@effected/workspaces";
1707
1712
  * import { Effect } from "effect";
1708
1713
  *
1714
+ * declare const text: string; // the text of a pnpm-lock.yaml
1715
+ *
1709
1716
  * const program = Effect.gen(function* () {
1710
1717
  * const lockfile = yield* Lockfile.parse(text, { format: "pnpm" });
1711
1718
  * const report = DuplicateCheck.run(lockfile, { names: DuplicateCheck.kit });
@@ -1741,8 +1748,7 @@ export declare class DuplicateCheck extends DuplicateCheck_base {
1741
1748
  * Exactly those — not `@effect/*`, and not names merely starting with
1742
1749
  * `effect`. A duplicated kit package presents as a `Layer` requirement that
1743
1750
  * looks provided yet cannot be satisfied, at the entry point, naming neither
1744
- * the package nor the skew (issue #298); this predicate is the check that
1745
- * names both.
1751
+ * the package nor the skew; this predicate is the check that names both.
1746
1752
  *
1747
1753
  * @param name - a package name
1748
1754
  * @returns whether the name belongs to the kit
@@ -1946,8 +1952,7 @@ export declare class PackageManagerDetector extends PackageManagerDetector_base
1946
1952
  * `WorkspaceDiscovery.info` posture, for the same reason. A stand-in that
1947
1953
  * answered `"pnpm"` would hand a consumer a fact nothing established, and it
1948
1954
  * would contradict the very service it stands in for: the live detector's
1949
- * defining property is that it [refuses to
1950
- * guess](https://github.com/spencerbeggs/effected) when no evidence matches.
1955
+ * defining property is that it refuses to guess when no evidence matches.
1951
1956
  * A double that guesses is worse than no double.
1952
1957
  *
1953
1958
  * Failing typed would be the subtler mistake: `PackageManagerDetectionError`
@@ -2017,8 +2022,7 @@ export declare class LockfileReadError extends LockfileReadError_base {
2017
2022
  get message(): string;
2018
2023
  }
2019
2024
  /**
2020
- * Every failure the lockfile methods can surface — the exported init-error
2021
- * union the review named best-in-class DX.
2025
+ * Every failure the lockfile methods can surface.
2022
2026
  *
2023
2027
  * @remarks
2024
2028
  * Layer construction does no IO, so every member surfaces from the *methods*
@@ -2044,9 +2048,7 @@ interface LockfileReaderShape {
2044
2048
  * @remarks
2045
2049
  * A name can resolve at **several versions** in one lockfile (two members
2046
2050
  * depending on different majors of the same package). This returns the
2047
- * **first** entry in lockfile order and does not attempt to rank them — there
2048
- * is no single "the" version to return, and picking the highest semver would
2049
- * imply a resolution decision this reader is not entitled to make. Callers
2051
+ * **first** entry in lockfile order and does not rank them. Callers
2050
2052
  * that must see every resolution should read `lockfile.packagesNamed(name)`
2051
2053
  * off `read()` directly.
2052
2054
  */
@@ -2114,11 +2116,14 @@ export declare class LockfileReader extends LockfileReader_base {
2114
2116
  /** Builds the service. */
2115
2117
  static readonly make: (options?: LockfileReaderOptions) => Effect.Effect<LockfileReaderShape, never, WorkspaceRoot | PackageManagerDetector | WorkspaceDiscovery | FileSystem.FileSystem | Path.Path>;
2116
2118
  /**
2117
- * The live layer.
2119
+ * The live layer: reads the lockfile of the detected package manager at the
2120
+ * workspace root.
2118
2121
  *
2119
2122
  * @remarks
2120
2123
  * Parameterized, so it mints a fresh reference per call — bind it to a
2121
2124
  * `const` and reuse it.
2125
+ *
2126
+ * @param options - Root resolution (`cwd`, `stopAt`).
2122
2127
  */
2123
2128
  static readonly layer: (options?: LockfileReaderOptions) => Layer.Layer<LockfileReader, never, WorkspaceRoot | PackageManagerDetector | WorkspaceDiscovery | FileSystem.FileSystem | Path.Path>;
2124
2129
  /**
@@ -2585,10 +2590,9 @@ export declare class WorkspaceCatalogs extends WorkspaceCatalogs_base {
2585
2590
  * `rangeOf` returns `Option.none()` for a dependency no catalog declares, per
2586
2591
  * the contract's convention. A failed catalog *assembly* — an unreadable or
2587
2592
  * malformed `pnpm-workspace.yaml`, a broken config-dependency hook — passes
2588
- * through **typed** as the contract's `CatalogAssemblyError` (it used to be
2589
- * folded into `DependencyResolutionError`'s defect `cause`, which forced
2590
- * consumers to `_tag`-sniff `unknown`); only the remaining mechanism failure,
2591
- * an unfindable workspace root, is wrapped as `DependencyResolutionError`.
2593
+ * through **typed** as the contract's `CatalogAssemblyError`; only the
2594
+ * remaining mechanism failure, an unfindable workspace root, is wrapped as
2595
+ * `DependencyResolutionError`.
2592
2596
  */
2593
2597
  static readonly catalogResolver: Layer.Layer<CatalogResolver, never, WorkspaceCatalogs>;
2594
2598
  }
@@ -2598,7 +2602,7 @@ export declare class WorkspaceCatalogs extends WorkspaceCatalogs_base {
2598
2602
  * Why a report is not a complete answer.
2599
2603
  *
2600
2604
  * @remarks
2601
- * Closed at exactly four, by measurement rather than by guess:
2605
+ * Closed at exactly four:
2602
2606
  *
2603
2607
  * - `"peerRulesNotApplied"` — the effective suppression policy was not applied,
2604
2608
  * so pnpm's post-hoc suppression could not be replicated and some reported
@@ -2606,7 +2610,7 @@ export declare class WorkspaceCatalogs extends WorkspaceCatalogs_base {
2606
2610
  * because "nobody looked" and "I looked and there are none" are different
2607
2611
  * facts. Supplied rules never produce it: all three axes —
2608
2612
  * `allowedVersions`, `ignoreMissing` and `allowAny` — are applied with
2609
- * pnpm's measured semantics.
2613
+ * pnpm's semantics.
2610
2614
  * - `"unresolvedEdge"` — some instance records an edge this model could not
2611
2615
  * name (`ResolvedPackage.unresolvedEdges`), or an importer dependency
2612
2616
  * resolved through `link:` whose target the caller did not supply, so its
@@ -2663,8 +2667,8 @@ type UnverifiedReason = "peerRulesNotApplied" | "unresolvedEdge" | "peerRangeUnr
2663
2667
  * different results, because a gate must be able to tell "clean" from
2664
2668
  * "unchecked".
2665
2669
  *
2666
- * **All three axes of the supplied rules are applied**, each with the
2667
- * semantics measured against pnpm (see {@link PeerCheck.run}): `allowedVersions`
2670
+ * **All three axes of the supplied rules are applied**, each with pnpm's
2671
+ * semantics (see {@link PeerCheck.run}): `allowedVersions`
2668
2672
  * permits a resolved version by range, `ignoreMissing` hides a required peer
2669
2673
  * nothing resolved for, and `allowAny` hides a peer that resolved outside its
2670
2674
  * range. The two list axes are name patterns, never `parent>peer` keys.
@@ -2833,10 +2837,12 @@ declare const PeerCheck_base: Schema.Class<PeerCheck, Schema.Struct<{
2833
2837
  *
2834
2838
  * @example
2835
2839
  * ```ts
2836
- * import { PeerCheck } from "@effected/workspaces";
2837
2840
  * import { Lockfile } from "@effected/lockfiles";
2841
+ * import { PeerCheck } from "@effected/workspaces";
2838
2842
  * import { Effect } from "effect";
2839
2843
  *
2844
+ * declare const text: string; // the text of a pnpm-lock.yaml
2845
+ *
2840
2846
  * const program = Effect.gen(function* () {
2841
2847
  * const lockfile = yield* Lockfile.parse(text, { format: "pnpm" });
2842
2848
  * const report = PeerCheck.run(lockfile);
@@ -2895,7 +2901,7 @@ export declare class PeerCheck extends PeerCheck_base {
2895
2901
  * `pnpm peers check` DOES report the linked parent's peers (it reads the
2896
2902
  * manifest on disk): every `link:` edge whose target the caller did not
2897
2903
  * supply therefore fails the report closed rather than letting the
2898
- * invisible parent pass as checked (effected#800).
2904
+ * invisible parent pass as checked.
2899
2905
  *
2900
2906
  * Supplying {@link PeerCheckOptions.workspacePackages} closes that gap for
2901
2907
  * every `link:` target the set covers — the root importer's included,
@@ -2930,6 +2936,8 @@ export declare class PeerCheck extends PeerCheck_base {
2930
2936
  * version check, and a plain unparseable version is still skipped.
2931
2937
  *
2932
2938
  * @param lockfile - a lockfile parsed by `@effected/lockfiles`
2939
+ * @param options - the workspace's effective rules, manifests and catalogs; see
2940
+ * {@link PeerCheckOptions}
2933
2941
  * @returns the report; never fails
2934
2942
  */
2935
2943
  static run(lockfile: Lockfile, options?: PeerCheckOptions): PeerCheck;
@@ -3050,16 +3058,13 @@ declare const PublishabilityDetector_base: Context.ServiceClass<PublishabilityDe
3050
3058
  export declare class PublishabilityDetector extends PublishabilityDetector_base {
3051
3059
  /**
3052
3060
  * Standard npm publishing semantics, **as a value**. Pure — no filesystem,
3053
- * no platform services.
3061
+ * no platform services. Never publishes with provenance (`provenance: false`).
3054
3062
  *
3055
3063
  * @remarks
3056
3064
  * Exposed as a shape and not only as a layer, because a consumer composing
3057
- * *around* these rules cannot reach them through a layer without re-entering
3058
- * the very tag it is replacing. `@savvy-web/silk-effects` had to write
3059
- * `Effect.provide(PublishabilityDetector, PublishabilityDetector.layer)`
3060
- * **inside its own implementation of that tag** to get at this function for
3061
- * its pass-through branch; with the value exposed that becomes
3062
- * `PublishabilityDetector.npm.detect(pkg)`.
3065
+ * *around* these rules cannot reach them through a layer without
3066
+ * re-entering the very tag it is replacing. A custom detector's pass-through
3067
+ * branch calls `PublishabilityDetector.npm.detect(pkg)` directly.
3063
3068
  *
3064
3069
  * @example
3065
3070
  * ```ts
@@ -3083,13 +3088,12 @@ export declare class PublishabilityDetector extends PublishabilityDetector_base
3083
3088
  *
3084
3089
  * @remarks
3085
3090
  * Named for its policy rather than called `layer`, deliberately. **No
3086
- * composite in this package provides a publishability detector**: a
3087
- * `Workspaces.layer()` that quietly supplied npm semantics made the choice
3088
- * invisible, and worse, made a naively-ordered override lose to it in
3089
- * silence — `Layer.mergeAll(myDetector, Workspaces.layer())` resolved to the
3090
- * default, because `mergeAll` is last-wins. For a service that decides
3091
- * whether a package publishes and to which registry, that silent revert was
3092
- * the worst available failure.
3091
+ * composite in this package provides a publishability detector**: one that
3092
+ * quietly supplied npm semantics would hide the choice and, because
3093
+ * `Layer.mergeAll` is last-wins, would let a naively-ordered override such
3094
+ * as `Layer.mergeAll(myDetector, Workspaces.layer())` lose to the default in
3095
+ * silence. For a service that decides whether a package publishes and to
3096
+ * which registry, that silent revert is the worst available failure.
3093
3097
  *
3094
3098
  * The composites do not *require* a detector either — nothing inside them
3095
3099
  * asks a publishability question, so their `R` stays `FileSystem | Path`.
@@ -3297,11 +3301,11 @@ declare const ReleaseTag_base: Schema.Class<ReleaseTag, Schema.Struct<{
3297
3301
  * even when `value` carries a prefix, so a consumer comparing versions never
3298
3302
  * has to strip one back off.
3299
3303
  *
3300
- * Formatting is **total**: there is no error channel, because the only failure
3301
- * v3 modelled — an empty version — is caught by `Schema.NonEmptyString` when
3302
- * the value is constructed. A bad version reaching these statics is developer
3303
- * wiring rather than untrusted input, so it dies as a defect, the same posture
3304
- * as an uncompilable glob literal in `WorkspacePackage.matchesDependency`.
3304
+ * Formatting has **no error channel**: an empty version is rejected by
3305
+ * `Schema.NonEmptyString` when the value is constructed. A bad version
3306
+ * reaching these statics is developer wiring rather than untrusted input, so it
3307
+ * dies as a defect, the same posture as an uncompilable glob literal in
3308
+ * `WorkspacePackage.matchesDependency`.
3305
3309
  *
3306
3310
  * @example
3307
3311
  * ```ts
@@ -3321,6 +3325,7 @@ export declare class ReleaseTag extends ReleaseTag_base {
3321
3325
  *
3322
3326
  * @param version - The version being released. Must not be empty.
3323
3327
  * @param options - Formatting overrides.
3328
+ * @returns the single-style {@link ReleaseTag}.
3324
3329
  */
3325
3330
  static single(version: string, options?: TagFormatOptions): ReleaseTag;
3326
3331
  /**
@@ -3419,13 +3424,13 @@ declare const VersioningStrategy_base: Schema.Class<VersioningStrategy, Schema.S
3419
3424
  *
3420
3425
  * @example
3421
3426
  * ```ts
3422
- * import { VersioningStrategy } from "@effected/workspaces";
3427
+ * import { PublishabilityDetector, VersioningStrategy } from "@effected/workspaces";
3423
3428
  * import { Effect } from "effect";
3424
3429
  *
3425
3430
  * const program = Effect.gen(function* () {
3426
- * const strategy = yield* VersioningStrategy.detect({ fixedGroups });
3427
- * return strategy.tagsFor(released).map((tag) => tag.value);
3428
- * });
3431
+ * const strategy = yield* VersioningStrategy.detect({ fixedGroups: [["@acme/a", "@acme/b"]] });
3432
+ * return strategy.tagsFor([{ name: "@acme/a", version: "1.2.3" }]).map((tag) => tag.value);
3433
+ * }).pipe(Effect.provide(PublishabilityDetector.layerNpm));
3429
3434
  * ```
3430
3435
  *
3431
3436
  * @public
@@ -3444,6 +3449,9 @@ export declare class VersioningStrategy extends VersioningStrategy_base {
3444
3449
  * Pure and total — no IO, no error channel. `packages` is sorted and
3445
3450
  * de-duplicated first, so a name listed twice cannot inflate a one-package
3446
3451
  * repo into an independent one.
3452
+ *
3453
+ * @param options - The publishable package names and any fixed groups.
3454
+ * @returns the classified {@link VersioningStrategy}.
3447
3455
  */
3448
3456
  static classify(options: ClassifyOptions): VersioningStrategy;
3449
3457
  /**
@@ -3454,6 +3462,10 @@ export declare class VersioningStrategy extends VersioningStrategy_base {
3454
3462
  * The publishability question is asked through the service precisely so a
3455
3463
  * consumer with its own rules — honouring a release tool's ignore list, say —
3456
3464
  * swaps the layer instead of filtering afterwards.
3465
+ *
3466
+ * Requires `WorkspaceDiscovery` and `PublishabilityDetector` (for example
3467
+ * `PublishabilityDetector.layerNpm`) in `R`, and fails with
3468
+ * `WorkspaceDiscoveryFailure` when discovery does.
3457
3469
  */
3458
3470
  static readonly detect: (options?: VersioningDetectOptions | undefined) => Effect.Effect<VersioningStrategy, WorkspaceDiscoveryFailure, PublishabilityDetector | WorkspaceDiscovery>;
3459
3471
  /**
@@ -3469,6 +3481,9 @@ export declare class VersioningStrategy extends VersioningStrategy_base {
3469
3481
  * one-line check rather than a field here.
3470
3482
  *
3471
3483
  * An empty batch produces no tags under either style.
3484
+ *
3485
+ * @param releases - The packages released and their versions.
3486
+ * @param options - Tag formatting overrides, such as `versionPrefix`.
3472
3487
  */
3473
3488
  tagsFor(releases: ReadonlyArray<PackageRelease>, options?: TagFormatOptions): ReadonlyArray<ReleaseTag>;
3474
3489
  }
@@ -3486,8 +3501,7 @@ declare const PackageStateSnapshot_base: Schema.Class<PackageStateSnapshot, Sche
3486
3501
  * an ordinary pnpm shape. Both capture paths — `WorkspaceSnapshots.at(ref)`
3487
3502
  * and `WorkspaceSnapshots.worktree()` — omit the key for such a member, so
3488
3503
  * the two sides of a diff agree without a placeholder. Never `""`: `make`
3489
- * rejects it, and a snapshot serialized when `""` was the "no version"
3490
- * sentinel decodes to the absent key.
3504
+ * rejects it, and a stored `""` decodes to the absent key.
3491
3505
  *
3492
3506
  * A version-less member is still a member: it appears in `packages` and
3493
3507
  * answers {@link WorkspaceStateSnapshot.package}, but is absent from
@@ -3542,11 +3556,9 @@ declare const WorkspaceStateSnapshot_base: Schema.Class<WorkspaceStateSnapshot,
3542
3556
  * lockfile recorded it at this moment.
3543
3557
  *
3544
3558
  * @remarks
3545
- * Defaults to `{}`, so a `WorkspaceStateSnapshot` serialized before this field
3546
- * existed still decodes — and an empty index simply makes the `catalog:`
3547
- * fallback in {@link WorkspaceStateSnapshot.resolve} inert, which is exactly
3548
- * the behavior those older values were captured under. Only pnpm records
3549
- * importer versions; bun and npm yield an empty index.
3559
+ * Defaults to `{}` when absent from a stored value; an empty index makes the
3560
+ * `catalog:` fallback in {@link WorkspaceStateSnapshot.resolve} inert. Only
3561
+ * pnpm records importer versions; bun and npm yield an empty index.
3550
3562
  */
3551
3563
  readonly importerVersions: Schema.optionalKey<Schema.$Record<Schema.String, Schema.$Record<Schema.String, Schema.String>>>;
3552
3564
  /**
@@ -3560,9 +3572,8 @@ declare const WorkspaceStateSnapshot_base: Schema.Class<WorkspaceStateSnapshot,
3560
3572
  * diagnostic and off this serializable value. Every fresh read sets the
3561
3573
  * field: `{}` under the no-op layer, which resolves nothing, when the file
3562
3574
  * declares no config dependencies, or on the bun / `package.json` path,
3563
- * where config dependencies do not exist. Absent only when decoding a
3564
- * snapshot serialized before the field existed, so stored values stay
3565
- * readable. Carried through `withSeededCatalogs` and `crossSeed`
3575
+ * where config dependencies do not exist. Absent only when decoding a stored
3576
+ * value that omits it. Carried through `withSeededCatalogs` and `crossSeed`
3566
3577
  * unchanged, like `importerVersions`.
3567
3578
  */
3568
3579
  readonly hookReplays: Schema.optionalKey<Schema.$Record<Schema.String, Schema.String>>;
@@ -3588,8 +3599,7 @@ declare const WorkspaceStateSnapshot_base: Schema.Class<WorkspaceStateSnapshot,
3588
3599
  * replays the ref's own pinned hook and the seed answers only what neither
3589
3600
  * source declared.
3590
3601
  *
3591
- * Defaults to absent, which makes the seed inert — exactly the behavior of
3592
- * every snapshot captured before this field existed.
3602
+ * Defaults to absent, which makes the seed inert.
3593
3603
  */
3594
3604
  readonly seededCatalogs: Schema.optionalKey<typeof CatalogSet>;
3595
3605
  }>, {}>;
@@ -3898,8 +3908,7 @@ interface WorkspaceSnapshotsOptions {
3898
3908
  * hook-injected catalogs at full precedence, so the seed answers nothing the
3899
3909
  * snapshot could not answer itself.
3900
3910
  *
3901
- * @defaultValue absent — no seed, and resolution behaves exactly as before
3902
- * this option existed.
3911
+ * @defaultValue absent — no seed.
3903
3912
  */
3904
3913
  readonly seedCatalogs?: CatalogSet;
3905
3914
  }
@@ -3964,11 +3973,14 @@ export declare class WorkspaceSnapshots extends WorkspaceSnapshots_base {
3964
3973
  */
3965
3974
  static readonly make: (options?: WorkspaceSnapshotsOptions) => Effect.Effect<WorkspaceSnapshotsShape, never, Git | WorkspaceRoot | WorkspaceDiscovery | WorkspaceCatalogs | ConfigDependencyHooks>;
3966
3975
  /**
3967
- * The live layer.
3976
+ * The live layer, reading workspace state at a git ref or from the live
3977
+ * worktree.
3968
3978
  *
3969
3979
  * @remarks
3970
3980
  * Parameterized, so it mints a fresh reference per call — bind it to a
3971
3981
  * `const` and reuse it, or layer memoization does not apply.
3982
+ *
3983
+ * @param options - Root resolution and the optional `seedCatalogs`.
3972
3984
  */
3973
3985
  static readonly layer: (options?: WorkspaceSnapshotsOptions) => Layer.Layer<WorkspaceSnapshots, never, Git | WorkspaceRoot | WorkspaceDiscovery | WorkspaceCatalogs | ConfigDependencyHooks>;
3974
3986
  /**
@@ -4113,10 +4125,9 @@ export declare class Workspaces {
4113
4125
  * `@effected/memfs` volume).
4114
4126
  *
4115
4127
  * **`PublishabilityDetector` is neither provided nor required here.** The
4116
- * composite used to bake in npm semantics, which a naively-ordered override
4117
- * silently lost to; now it supplies no default, and — because nothing inside
4118
- * the composite asks a publishability question — it does not require one in
4119
- * `R` either. The requirement surfaces in the `R` of each operation that
4128
+ * composite supplies no default policy, and — because nothing inside it asks
4129
+ * a publishability question — it does not require one in `R` either. The
4130
+ * requirement surfaces in the `R` of each operation that
4120
4131
  * asks (`VersioningStrategy.detect`, e.g.), so a program that asks and never
4121
4132
  * wires a detector fails to compile at that operation, and a program that
4122
4133
  * never asks never supplies a publish policy. Wire one explicitly where
@@ -4197,10 +4208,9 @@ export declare class Workspaces {
4197
4208
  * `pnpmfile.cjs` hooks**.
4198
4209
  *
4199
4210
  * @remarks
4200
- * The composite that did not exist. `layerWithGit` hard-wires the no-op
4201
- * catalogs layer, so a consumer wanting snapshots + git + hook replay had to
4202
- * rebuild the entire service graph by hand — which is exactly what
4203
- * `@savvy-web/silk-effects` did, and the copy this static deletes.
4211
+ * `layerWithGit` wires the no-op catalogs layer, so this is the composite to
4212
+ * reach for when you want snapshots, git and hook replay together without
4213
+ * assembling the service graph by hand.
4204
4214
  *
4205
4215
  * Requirements are unchanged from {@link Workspaces.layerWithGit}: a
4206
4216
  * filesystem, a path service, and core's `ChildProcessSpawner` (behind
@@ -4263,8 +4273,7 @@ export declare class Workspaces {
4263
4273
  * and {@link ConfigDependencyHooks.layerSubprocess}. It exists for the fourth
4264
4274
  * policy: {@link ConfigDependencyHooks.layerFrom}, the hermetic seam, which a
4265
4275
  * snapshot-backed test otherwise cannot reach without rebuilding the whole
4266
- * git graph by hand — the copy `layerWithGitAndConfigDependencies` was added
4267
- * to delete. The ONE hooks reference is handed to both `WorkspaceCatalogs`
4276
+ * git graph by hand. The ONE hooks reference is handed to both `WorkspaceCatalogs`
4268
4277
  * and `WorkspaceSnapshots`, so `at(ref)` and `worktree()` cannot drift on
4269
4278
  * which policy they replay. A hooks layer carrying its own requirement (the
4270
4279
  * subprocess variant's `ChildProcessSpawner`) threads it through to the
@@ -4294,13 +4303,11 @@ export declare class Workspaces {
4294
4303
  * contract: how to run a project-local binary here.
4295
4304
  *
4296
4305
  * @remarks
4297
- * **An inverted contract, the `@effected/npm` `CatalogResolver`
4298
- * precedent.** Tool discovery needs package-manager detection and
4299
- * workspace-root resolution, both of which live here — but a direct edge
4300
- * from `@effected/commands` to this package would make that boundary-tier
4301
- * package integrated, and through the planned `npm` → `commands` edge
4302
- * would drag `npm`, `lockfiles` (pure!) and `package-json` up a tier with
4303
- * it. So `commands` declares the narrow contract and we ship the layer.
4306
+ * **An inverted contract, like `@effected/npm`'s `CatalogResolver`.** Tool
4307
+ * discovery needs package-manager detection and workspace-root resolution,
4308
+ * both of which live here, but `@effected/commands` must not depend on this
4309
+ * package. So `commands` declares the narrow `LocalExec` contract and this
4310
+ * package ships the layer.
4304
4311
  *
4305
4312
  * **The argv knowledge is not duplicated.** `LocalExec.prefixes(name)` is
4306
4313
  * the one home of the four managers' `exec`/`dlx`/script-runner prefixes;
@@ -4334,6 +4341,7 @@ export declare class Workspaces {
4334
4341
  *
4335
4342
  * @example
4336
4343
  * ```ts
4344
+ * import { NodeServices } from "@effect/platform-node";
4337
4345
  * import { ToolDiscovery } from "@effected/commands";
4338
4346
  * import { Workspaces } from "@effected/workspaces";
4339
4347
  * import { Layer } from "effect";
@@ -4531,7 +4539,9 @@ interface SyncDirectoryEntry {
4531
4539
  * satisfies it verbatim:
4532
4540
  *
4533
4541
  * ```ts
4542
+ * import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
4534
4543
  * import * as path from "node:path";
4544
+ * import type { WorkspacesSyncOptions } from "@effected/workspaces";
4535
4545
  *
4536
4546
  * const options: WorkspacesSyncOptions = {
4537
4547
  * fileSystem: { exists: existsSync, readFile: (p) => readFileSync(p, "utf8"), readDirectory: (p) => readdirSync(p), isDirectory: (p) => statSync(p).isDirectory() },
@@ -4577,8 +4587,8 @@ interface WorkspacesSyncOptions {
4577
4587
  * The same vocabulary the Effect surface fails with, deliberately: a member the
4578
4588
  * async `listPackages()` rejects as `missingName` is the member the sync facade
4579
4589
  * reports as `missingName`. `invalidYaml` is excluded because it describes the
4580
- * `pnpm-workspace.yaml` read, not a manifest. There is no `missingVersion` —
4581
- * a version-less manifest is a member on both surfaces.
4590
+ * `pnpm-workspace.yaml` read, not a manifest. A version-less manifest is a
4591
+ * member on both surfaces.
4582
4592
  *
4583
4593
  * The vocabulary is shared; the CHECKS are shared only as far as this list.
4584
4594
  * Both surfaces perform the same five: the file read (`read`), `JSON.parse`
@@ -4599,10 +4609,10 @@ type WorkspaceDiscoverySkipKind = Exclude<WorkspaceDiscoveryError["kind"], "inva
4599
4609
  *
4600
4610
  * @remarks
4601
4611
  * The sync facade is total, so it cannot fail the way `WorkspaceDiscovery`
4602
- * does — but a skipped member must still be observable. Before this record
4603
- * existed the skip was silent, and a hand-written fixture with one unusable
4604
- * manifest enumerated as a plausible empty array indistinguishable from "no
4605
- * workspaces configured" (issue #605). The fields mirror
4612
+ * does — but a skipped member must still be observable. Without a report, a
4613
+ * hand-written fixture with one unusable manifest would enumerate as a
4614
+ * plausible empty array indistinguishable from "no workspaces configured". The
4615
+ * fields mirror
4606
4616
  * `WorkspaceDiscoveryError`: `root`, `path`, `kind`, and on `cause` either the
4607
4617
  * caught throwable (`read` / `invalidJson`) or an `Error` carrying the same
4608
4618
  * sentence the Effect surface fails with (`invalidShape`). Only `missingName`
@@ -4664,9 +4674,7 @@ interface FindWorkspaceRootSyncOptions extends WorkspacesSyncOptions {
4664
4674
  * The signature is path-first, options second — the same shape as
4665
4675
  * {@link getWorkspacePackagesSync} and the rest of the kit's sync facades
4666
4676
  * (`TsconfigLoaderSync.load(configPath, options)`). `cwd` is required and
4667
- * positional: the earlier options-bag form defaulted it to an ambient
4668
- * `process.cwd()` read, which both broke the symmetry with its sibling and
4669
- * was the module's one platform assumption.
4677
+ * positional, so the function reads no ambient `process.cwd()`.
4670
4678
  *
4671
4679
  * Markers match the async service exactly: a `pnpm-workspace.yaml`, or a
4672
4680
  * `package.json` carrying a `workspaces` field.
@@ -4723,12 +4731,10 @@ interface GetWorkspacePackagesSyncOptions extends WorkspacesSyncOptions {
4723
4731
  * though this function is total and has no error channel to raise it on.
4724
4732
  *
4725
4733
  * @remarks
4726
- * Omit it and skips are simply not reported, which is the pre-existing
4727
- * behaviour; nothing is logged in its place. The callback is invoked
4728
- * synchronously, before the result is returned, in enumeration order —
4729
- * members first, then the root, which is read last even though it is
4730
- * returned first. Its
4731
- * result is discarded, and a throw from it propagates: the facade is total
4734
+ * Omit it and skips are simply not reported; nothing is logged in its
4735
+ * place. The callback is invoked synchronously, before the result is
4736
+ * returned, in enumeration order — members first, then the root, which is
4737
+ * read last even though it is returned first. Its result is discarded, and a throw from it propagates: the facade is total
4732
4738
  * over *data*, not over caller mistakes, exactly as a bad `maxDepth` is.
4733
4739
  */
4734
4740
  readonly onSkip?: ((skip: WorkspaceDiscoverySkip) => void) | undefined;