@savvy-web/silk-effects 5.1.1 → 5.2.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.
Files changed (34) hide show
  1. package/README.md +22 -22
  2. package/changesets/api/transformer.js +2 -1
  3. package/changesets/changelog/getDependencyReleaseLine.js +24 -5
  4. package/changesets/changelog/getReleaseLine.js +7 -4
  5. package/changesets/changelog/index.js +8 -6
  6. package/changesets/index.js +6 -11
  7. package/changesets/services/branch-analyzer.js +20 -19
  8. package/changesets/services/changelog.js +1 -1
  9. package/changesets/services/config-inspector.js +17 -17
  10. package/changesets/services/deps-regen.js +36 -34
  11. package/changesets/services/github.js +39 -40
  12. package/changesets/services/maintenance-reason.js +5 -1
  13. package/changesets/services/release-planner.js +7 -6
  14. package/changesets/utils/dependency-table.js +2 -1
  15. package/changesets/utils/jsonpath.js +5 -7
  16. package/changesets/utils/publishability.js +2 -2
  17. package/commitlint/detection/dco.js +2 -1
  18. package/commitlint/index.js +2 -1
  19. package/index.d.ts +254 -218
  20. package/index.js +7 -7
  21. package/lint/handlers/PnpmWorkspace.js +2 -1
  22. package/lint/handlers/Yaml.js +8 -4
  23. package/package.json +7 -7
  24. package/repos/index.js +3 -5
  25. package/repos/services/config-store.js +68 -67
  26. package/repos/services/manager.js +259 -258
  27. package/services/BiomeSchemaSync.js +65 -64
  28. package/services/ChangesetConfig.js +50 -50
  29. package/services/ChangesetConfigReader.js +59 -58
  30. package/services/ConfigDiscovery.js +42 -41
  31. package/services/SilkPublishability.js +54 -53
  32. package/services/SilkWorkspaceAnalyzer.js +110 -109
  33. package/turbo/index.js +2 -3
  34. package/turbo/services/TurboInspector.js +80 -79
@@ -52,7 +52,7 @@ function findBiomeConfigs(cwd, fs) {
52
52
  * const syncer = yield* BiomeSchemaSync;
53
53
  * return yield* syncer.sync("^1.9.3");
54
54
  * }).pipe(
55
- * Effect.provide(BiomeSchemaSyncLive),
55
+ * Effect.provide(BiomeSchemaSync.layer),
56
56
  * Effect.provide(NodeServices.layer),
57
57
  * )
58
58
  * );
@@ -61,76 +61,77 @@ function findBiomeConfigs(cwd, fs) {
61
61
  * @since 0.1.0
62
62
  * @public
63
63
  */
64
- var BiomeSchemaSync = class extends Context.Service()("@savvy-web/silk-effects/BiomeSchemaSync") {};
65
- /**
66
- * Live implementation of {@link BiomeSchemaSync}.
67
- *
68
- * @remarks
69
- * Requires the core `FileSystem` service. Provide `NodeServices.layer` (or
70
- * `NodeFileSystem.layer`) from `@effect/platform-node` to satisfy this dependency.
71
- *
72
- * @since 0.1.0
73
- * @public
74
- */
75
- const BiomeSchemaSyncLive = Layer.effect(BiomeSchemaSync, Effect.gen(function* () {
76
- const fs = yield* FileSystem.FileSystem;
77
- const run = (version, options, write) => Effect.gen(function* () {
78
- const cwd = options?.cwd ?? process.cwd();
79
- const expectedUrl = buildSchemaUrl(extractSemver(version));
80
- const configs = yield* findBiomeConfigs(cwd, fs);
81
- const updated = [];
82
- const skipped = [];
83
- const current = [];
84
- for (const configPath of configs) {
85
- const raw = yield* fs.readFileString(configPath).pipe(Effect.mapError(
86
- /* v8 ignore next 4 -- error path requires a filesystem read failure */
87
- (cause) => new BiomeSyncError({
88
- path: configPath,
89
- reason: String(cause)
90
- })
91
- ));
92
- const schema = (yield* Jsonc.parse(raw).pipe(Effect.mapError(
93
- /* v8 ignore next 4 -- error path requires a JSONC parse failure */
94
- (e) => new BiomeSyncError({
95
- path: configPath,
96
- reason: `Failed to parse JSONC: ${String(e)}`
97
- })
98
- ))).$schema;
99
- if (typeof schema !== "string") {
100
- skipped.push(configPath);
101
- continue;
102
- }
103
- if (!schema.includes(BIOME_SCHEMA_HOSTNAME)) {
104
- skipped.push(configPath);
105
- continue;
106
- }
107
- if (schema === expectedUrl) {
108
- current.push(configPath);
109
- continue;
110
- }
111
- if (write) {
112
- const updated_content = raw.replaceAll(schema, expectedUrl);
113
- yield* fs.writeFileString(configPath, updated_content).pipe(Effect.mapError(
114
- /* v8 ignore next 4 -- error path requires a filesystem write failure */
64
+ var BiomeSchemaSync = class extends Context.Service()("@savvy-web/silk-effects/BiomeSchemaSync") {
65
+ /**
66
+ * Production implementation of {@link BiomeSchemaSync}.
67
+ *
68
+ * @remarks
69
+ * Requires the core `FileSystem` service. Provide `NodeServices.layer` (or
70
+ * `NodeFileSystem.layer`) from `@effect/platform-node` to satisfy this dependency.
71
+ *
72
+ * @since 0.1.0
73
+ * @public
74
+ */
75
+ static layer = Layer.effect(this, Effect.gen(function* () {
76
+ const fs = yield* FileSystem.FileSystem;
77
+ const run = (version, options, write) => Effect.gen(function* () {
78
+ const cwd = options?.cwd ?? process.cwd();
79
+ const expectedUrl = buildSchemaUrl(extractSemver(version));
80
+ const configs = yield* findBiomeConfigs(cwd, fs);
81
+ const updated = [];
82
+ const skipped = [];
83
+ const current = [];
84
+ for (const configPath of configs) {
85
+ const raw = yield* fs.readFileString(configPath).pipe(Effect.mapError(
86
+ /* v8 ignore next 4 -- error path requires a filesystem read failure */
115
87
  (cause) => new BiomeSyncError({
116
88
  path: configPath,
117
89
  reason: String(cause)
118
90
  })
119
91
  ));
92
+ const schema = (yield* Jsonc.parse(raw).pipe(Effect.mapError(
93
+ /* v8 ignore next 4 -- error path requires a JSONC parse failure */
94
+ (e) => new BiomeSyncError({
95
+ path: configPath,
96
+ reason: `Failed to parse JSONC: ${String(e)}`
97
+ })
98
+ ))).$schema;
99
+ if (typeof schema !== "string") {
100
+ skipped.push(configPath);
101
+ continue;
102
+ }
103
+ if (!schema.includes(BIOME_SCHEMA_HOSTNAME)) {
104
+ skipped.push(configPath);
105
+ continue;
106
+ }
107
+ if (schema === expectedUrl) {
108
+ current.push(configPath);
109
+ continue;
110
+ }
111
+ if (write) {
112
+ const updated_content = raw.replaceAll(schema, expectedUrl);
113
+ yield* fs.writeFileString(configPath, updated_content).pipe(Effect.mapError(
114
+ /* v8 ignore next 4 -- error path requires a filesystem write failure */
115
+ (cause) => new BiomeSyncError({
116
+ path: configPath,
117
+ reason: String(cause)
118
+ })
119
+ ));
120
+ }
121
+ updated.push(configPath);
120
122
  }
121
- updated.push(configPath);
122
- }
123
+ return {
124
+ updated,
125
+ skipped,
126
+ current
127
+ };
128
+ });
123
129
  return {
124
- updated,
125
- skipped,
126
- current
130
+ sync: (version, options) => run(version, options, true),
131
+ check: (version, options) => run(version, options, false)
127
132
  };
128
- });
129
- return {
130
- sync: (version, options) => run(version, options, true),
131
- check: (version, options) => run(version, options, false)
132
- };
133
- }));
133
+ }));
134
+ };
134
135
 
135
136
  //#endregion
136
- export { BiomeSchemaSync, BiomeSchemaSyncLive, buildSchemaUrl, extractSemver };
137
+ export { BiomeSchemaSync, buildSchemaUrl, extractSemver };
@@ -2,6 +2,7 @@ import { ChangesetConfigReader } from "./ChangesetConfigReader.js";
2
2
  import { Context, Effect, Layer, Option } from "effect";
3
3
 
4
4
  //#region src/services/ChangesetConfig.ts
5
+ const isSilk = (cfg) => "_isSilk" in cfg && cfg._isSilk === true;
5
6
  /**
6
7
  * Accessor service over a workspace root's `.changeset/config.json`.
7
8
  *
@@ -13,7 +14,7 @@ import { Context, Effect, Layer, Option } from "effect";
13
14
  * @since 0.4.0
14
15
  * @public
15
16
  */
16
- var ChangesetConfig = class extends Context.Service()("@savvy-web/silk-effects/ChangesetConfig") {
17
+ var ChangesetConfig = class ChangesetConfig extends Context.Service()("@savvy-web/silk-effects/ChangesetConfig") {
17
18
  /**
18
19
  * The one ignore matcher: exact name match, or `@scope/*` wildcard.
19
20
  *
@@ -27,55 +28,54 @@ var ChangesetConfig = class extends Context.Service()("@savvy-web/silk-effects/C
27
28
  }
28
29
  return name === pattern;
29
30
  }
31
+ /**
32
+ * Production layer for {@link ChangesetConfig}, reading via {@link ChangesetConfigReader}, cached per root.
33
+ *
34
+ * @remarks
35
+ * Requires `ChangesetConfigReader` (which requires `FileSystem`). Provide
36
+ * `ChangesetConfigReader.layer` + a platform layer (`NodeServices.layer`).
37
+ *
38
+ * @since 0.4.0
39
+ * @public
40
+ */
41
+ static layer = Layer.effect(this, Effect.gen(function* () {
42
+ const reader = yield* ChangesetConfigReader;
43
+ const cache = /* @__PURE__ */ new Map();
44
+ const read = (root) => Effect.gen(function* () {
45
+ const hit = cache.get(root);
46
+ if (hit !== void 0) return hit;
47
+ const result = yield* reader.read(root).pipe(Effect.option);
48
+ cache.set(root, result);
49
+ return result;
50
+ });
51
+ return {
52
+ mode: (root) => read(root).pipe(Effect.map(Option.match({
53
+ onNone: () => "none",
54
+ onSome: (cfg) => isSilk(cfg) ? "silk" : "vanilla"
55
+ }))),
56
+ versionPrivate: (root) => read(root).pipe(Effect.map(Option.match({
57
+ onNone: () => false,
58
+ onSome: (cfg) => {
59
+ const pp = cfg.privatePackages;
60
+ return pp !== void 0 && pp !== false && pp.version === true;
61
+ }
62
+ }))),
63
+ ignorePatterns: (root) => read(root).pipe(Effect.map(Option.match({
64
+ onNone: () => [],
65
+ onSome: (cfg) => cfg.ignore ?? []
66
+ }))),
67
+ isIgnored: (name, root) => read(root).pipe(Effect.map(Option.match({
68
+ onNone: () => false,
69
+ onSome: (cfg) => (cfg.ignore ?? []).some((p) => ChangesetConfig.matches(name, p))
70
+ }))),
71
+ fixed: (root) => read(root).pipe(Effect.map(Option.match({
72
+ onNone: () => [],
73
+ onSome: (cfg) => cfg.fixed ?? []
74
+ }))),
75
+ refresh: () => Effect.sync(() => cache.clear())
76
+ };
77
+ }));
30
78
  };
31
- const isSilk = (cfg) => "_isSilk" in cfg && cfg._isSilk === true;
32
- /**
33
- * Live {@link ChangesetConfig} reading via {@link ChangesetConfigReader}, cached per root.
34
- *
35
- * @remarks
36
- * Requires `ChangesetConfigReader` (which requires `FileSystem`). Provide
37
- * `ChangesetConfigReaderLive` + a platform layer (`NodeServices.layer`).
38
- *
39
- * @since 0.4.0
40
- * @public
41
- */
42
- const ChangesetConfigLive = Layer.effect(ChangesetConfig, Effect.gen(function* () {
43
- const reader = yield* ChangesetConfigReader;
44
- const cache = /* @__PURE__ */ new Map();
45
- const read = (root) => Effect.gen(function* () {
46
- const hit = cache.get(root);
47
- if (hit !== void 0) return hit;
48
- const result = yield* reader.read(root).pipe(Effect.option);
49
- cache.set(root, result);
50
- return result;
51
- });
52
- return {
53
- mode: (root) => read(root).pipe(Effect.map(Option.match({
54
- onNone: () => "none",
55
- onSome: (cfg) => isSilk(cfg) ? "silk" : "vanilla"
56
- }))),
57
- versionPrivate: (root) => read(root).pipe(Effect.map(Option.match({
58
- onNone: () => false,
59
- onSome: (cfg) => {
60
- const pp = cfg.privatePackages;
61
- return pp !== void 0 && pp !== false && pp.version === true;
62
- }
63
- }))),
64
- ignorePatterns: (root) => read(root).pipe(Effect.map(Option.match({
65
- onNone: () => [],
66
- onSome: (cfg) => cfg.ignore ?? []
67
- }))),
68
- isIgnored: (name, root) => read(root).pipe(Effect.map(Option.match({
69
- onNone: () => false,
70
- onSome: (cfg) => (cfg.ignore ?? []).some((p) => ChangesetConfig.matches(name, p))
71
- }))),
72
- fixed: (root) => read(root).pipe(Effect.map(Option.match({
73
- onNone: () => [],
74
- onSome: (cfg) => cfg.fixed ?? []
75
- }))),
76
- refresh: () => Effect.sync(() => cache.clear())
77
- };
78
- }));
79
79
 
80
80
  //#endregion
81
- export { ChangesetConfig, ChangesetConfigLive };
81
+ export { ChangesetConfig };
@@ -41,7 +41,7 @@ function isSilkChangelog(changelog) {
41
41
  * const reader = yield* ChangesetConfigReader;
42
42
  * return yield* reader.read(process.cwd());
43
43
  * }).pipe(
44
- * Effect.provide(ChangesetConfigReaderLive),
44
+ * Effect.provide(ChangesetConfigReader.layer),
45
45
  * Effect.provide(NodeServices.layer),
46
46
  * )
47
47
  * );
@@ -50,64 +50,65 @@ function isSilkChangelog(changelog) {
50
50
  * @since 0.1.0
51
51
  * @public
52
52
  */
53
- var ChangesetConfigReader = class extends Context.Service()("@savvy-web/silk-effects/ChangesetConfigReader") {};
54
- /**
55
- * Live implementation of {@link ChangesetConfigReader}.
56
- *
57
- * @remarks
58
- * Requires the core `FileSystem` service. Provide `NodeServices.layer` (or
59
- * `NodeFileSystem.layer`) from `@effect/platform-node` to satisfy this dependency.
60
- *
61
- * @since 0.1.0
62
- * @public
63
- */
64
- const ChangesetConfigReaderLive = Layer.effect(ChangesetConfigReader, Effect.gen(function* () {
65
- const fs = yield* FileSystem.FileSystem;
66
- const read = (root) => {
67
- const configPath = `${root}/.changeset/config.json`;
68
- return Effect.gen(function* () {
69
- if (!(yield* fs.exists(configPath).pipe(Effect.mapError(
70
- /* v8 ignore next 4 -- error path requires fs.exists to fail */
71
- (cause) => new ChangesetConfigError({
72
- path: configPath,
73
- reason: String(cause)
74
- })
75
- )))) return yield* Effect.fail(new ChangesetConfigError({
76
- path: configPath,
77
- reason: "File not found"
78
- }));
79
- const raw = yield* fs.readFileString(configPath).pipe(Effect.mapError(
80
- /* v8 ignore next 4 -- error path requires fs.readFileString to fail */
81
- (cause) => new ChangesetConfigError({
82
- path: configPath,
83
- reason: String(cause)
84
- })
85
- ));
86
- const parsed = yield* Effect.try({
87
- try: () => JSON.parse(raw),
88
- catch: (cause) => new ChangesetConfigError({
53
+ var ChangesetConfigReader = class extends Context.Service()("@savvy-web/silk-effects/ChangesetConfigReader") {
54
+ /**
55
+ * Production implementation of {@link ChangesetConfigReader}.
56
+ *
57
+ * @remarks
58
+ * Requires the core `FileSystem` service. Provide `NodeServices.layer` (or
59
+ * `NodeFileSystem.layer`) from `@effect/platform-node` to satisfy this dependency.
60
+ *
61
+ * @since 0.1.0
62
+ * @public
63
+ */
64
+ static layer = Layer.effect(this, Effect.gen(function* () {
65
+ const fs = yield* FileSystem.FileSystem;
66
+ const read = (root) => {
67
+ const configPath = `${root}/.changeset/config.json`;
68
+ return Effect.gen(function* () {
69
+ if (!(yield* fs.exists(configPath).pipe(Effect.mapError(
70
+ /* v8 ignore next 4 -- error path requires fs.exists to fail */
71
+ (cause) => new ChangesetConfigError({
72
+ path: configPath,
73
+ reason: String(cause)
74
+ })
75
+ )))) return yield* Effect.fail(new ChangesetConfigError({
89
76
  path: configPath,
90
- reason: `Invalid JSON: ${String(cause)}`
91
- })
77
+ reason: "File not found"
78
+ }));
79
+ const raw = yield* fs.readFileString(configPath).pipe(Effect.mapError(
80
+ /* v8 ignore next 4 -- error path requires fs.readFileString to fail */
81
+ (cause) => new ChangesetConfigError({
82
+ path: configPath,
83
+ reason: String(cause)
84
+ })
85
+ ));
86
+ const parsed = yield* Effect.try({
87
+ try: () => JSON.parse(raw),
88
+ catch: (cause) => new ChangesetConfigError({
89
+ path: configPath,
90
+ reason: `Invalid JSON: ${String(cause)}`
91
+ })
92
+ });
93
+ if (isSilkChangelog(parsed.changelog)) return yield* Schema.decodeUnknownEffect(SilkChangesetConfigFile)(parsed).pipe(Effect.mapError(
94
+ /* v8 ignore next 4 -- error path requires schema decode failure */
95
+ (cause) => new ChangesetConfigError({
96
+ path: configPath,
97
+ reason: `Schema decode failed: ${String(cause)}`
98
+ })
99
+ ));
100
+ return yield* Schema.decodeUnknownEffect(ChangesetConfigFile)(parsed).pipe(Effect.mapError(
101
+ /* v8 ignore next 4 -- error path requires schema decode failure */
102
+ (cause) => new ChangesetConfigError({
103
+ path: configPath,
104
+ reason: `Schema decode failed: ${String(cause)}`
105
+ })
106
+ ));
92
107
  });
93
- if (isSilkChangelog(parsed.changelog)) return yield* Schema.decodeUnknownEffect(SilkChangesetConfigFile)(parsed).pipe(Effect.mapError(
94
- /* v8 ignore next 4 -- error path requires schema decode failure */
95
- (cause) => new ChangesetConfigError({
96
- path: configPath,
97
- reason: `Schema decode failed: ${String(cause)}`
98
- })
99
- ));
100
- return yield* Schema.decodeUnknownEffect(ChangesetConfigFile)(parsed).pipe(Effect.mapError(
101
- /* v8 ignore next 4 -- error path requires schema decode failure */
102
- (cause) => new ChangesetConfigError({
103
- path: configPath,
104
- reason: `Schema decode failed: ${String(cause)}`
105
- })
106
- ));
107
- });
108
- };
109
- return { read };
110
- }));
108
+ };
109
+ return { read };
110
+ }));
111
+ };
111
112
 
112
113
  //#endregion
113
- export { ChangesetConfigReader, ChangesetConfigReaderLive };
114
+ export { ChangesetConfigReader };
@@ -2,6 +2,12 @@ import { Context, Effect, FileSystem, Layer } from "effect";
2
2
 
3
3
  //#region src/services/ConfigDiscovery.ts
4
4
  /**
5
+ * Check whether a path exists, treating any PlatformError as "not found".
6
+ */
7
+ function safeExists(fs, path) {
8
+ return fs.exists(path).pipe(Effect.orElseSucceed(() => false));
9
+ }
10
+ /**
5
11
  * Service that locates named config files within a workspace using priority-ordered search paths.
6
12
  *
7
13
  * @remarks
@@ -18,7 +24,7 @@ import { Context, Effect, FileSystem, Layer } from "effect";
18
24
  * const discovery = yield* ConfigDiscovery;
19
25
  * return yield* discovery.find("biome.json");
20
26
  * }).pipe(
21
- * Effect.provide(ConfigDiscoveryLive),
27
+ * Effect.provide(ConfigDiscovery.layer),
22
28
  * Effect.provide(NodeServices.layer),
23
29
  * )
24
30
  * );
@@ -27,46 +33,41 @@ import { Context, Effect, FileSystem, Layer } from "effect";
27
33
  * @since 0.1.0
28
34
  * @public
29
35
  */
30
- var ConfigDiscovery = class extends Context.Service()("@savvy-web/silk-effects/ConfigDiscovery") {};
31
- /**
32
- * Check whether a path exists, treating any PlatformError as "not found".
33
- */
34
- function safeExists(fs, path) {
35
- return fs.exists(path).pipe(Effect.orElseSucceed(() => false));
36
- }
37
- /**
38
- * Live implementation of {@link ConfigDiscovery}.
39
- *
40
- * @remarks
41
- * Requires the core `FileSystem` service. Provide `NodeServices.layer` (or
42
- * `NodeFileSystem.layer`) from `@effect/platform-node` to satisfy this dependency.
43
- *
44
- * @since 0.1.0
45
- * @public
46
- */
47
- const ConfigDiscoveryLive = Layer.effect(ConfigDiscovery, Effect.gen(function* () {
48
- const fs = yield* FileSystem.FileSystem;
49
- const findAll = (name, options) => Effect.gen(function* () {
50
- const cwd = options?.cwd ?? process.cwd();
51
- const results = [];
52
- const libPath = `${cwd}/lib/configs/${name}`;
53
- if (yield* safeExists(fs, libPath)) results.push({
54
- path: libPath,
55
- source: "lib"
56
- });
57
- const rootPath = `${cwd}/${name}`;
58
- if (yield* safeExists(fs, rootPath)) results.push({
59
- path: rootPath,
60
- source: "root"
36
+ var ConfigDiscovery = class extends Context.Service()("@savvy-web/silk-effects/ConfigDiscovery") {
37
+ /**
38
+ * Production implementation of {@link ConfigDiscovery}.
39
+ *
40
+ * @remarks
41
+ * Requires the core `FileSystem` service. Provide `NodeServices.layer` (or
42
+ * `NodeFileSystem.layer`) from `@effect/platform-node` to satisfy this dependency.
43
+ *
44
+ * @since 0.1.0
45
+ * @public
46
+ */
47
+ static layer = Layer.effect(this, Effect.gen(function* () {
48
+ const fs = yield* FileSystem.FileSystem;
49
+ const findAll = (name, options) => Effect.gen(function* () {
50
+ const cwd = options?.cwd ?? process.cwd();
51
+ const results = [];
52
+ const libPath = `${cwd}/lib/configs/${name}`;
53
+ if (yield* safeExists(fs, libPath)) results.push({
54
+ path: libPath,
55
+ source: "lib"
56
+ });
57
+ const rootPath = `${cwd}/${name}`;
58
+ if (yield* safeExists(fs, rootPath)) results.push({
59
+ path: rootPath,
60
+ source: "root"
61
+ });
62
+ return results;
61
63
  });
62
- return results;
63
- });
64
- const find = (name, options) => findAll(name, options).pipe(Effect.map((results) => results[0] ?? null));
65
- return {
66
- find,
67
- findAll
68
- };
69
- }));
64
+ const find = (name, options) => findAll(name, options).pipe(Effect.map((results) => results[0] ?? null));
65
+ return {
66
+ find,
67
+ findAll
68
+ };
69
+ }));
70
+ };
70
71
 
71
72
  //#endregion
72
- export { ConfigDiscovery, ConfigDiscoveryLive };
73
+ export { ConfigDiscovery };
@@ -47,7 +47,7 @@ const provenanceForRegistry = (registry) => {
47
47
  * @since 0.4.0
48
48
  * @public
49
49
  */
50
- var SilkPublishability = class {
50
+ var SilkPublishability = class SilkPublishability {
51
51
  /**
52
52
  * Apply silk publishability rules to a raw `package.json` and the bundler's resolved
53
53
  * target binding. Targets-first precedence:
@@ -179,6 +179,56 @@ var SilkPublishability = class {
179
179
  return out;
180
180
  });
181
181
  }
182
+ /**
183
+ * Override of `@effected/workspaces`' `PublishabilityDetector` Tag with pure silk rules.
184
+ *
185
+ * @remarks Requires `FileSystem` (captured at layer build); `detect` reads the raw
186
+ * `package.json` from `pkg.packageJsonPath` and applies `SilkPublishability.detect`.
187
+ *
188
+ * @since 0.4.0
189
+ * @public
190
+ */
191
+ static layer = Layer.effect(PublishabilityDetector, Effect.gen(function* () {
192
+ const fs = yield* FileSystem.FileSystem;
193
+ return { detect: (pkg) => Effect.gen(function* () {
194
+ const raw = yield* readRaw(fs, pkg.packageJsonPath);
195
+ if (!raw) return [];
196
+ const binding = yield* readTargetsBinding(fs, pkg.path);
197
+ return SilkPublishability.detect(pkg.name, raw, binding);
198
+ }) };
199
+ }));
200
+ /**
201
+ * Ignore-aware override of `PublishabilityDetector`. `detect` short-circuits to `[]`
202
+ * for changeset-ignored packages, then dispatches on `ChangesetConfig.mode`:
203
+ * `none` → `[]`; `silk` → `SilkPublishability.detect`; `vanilla` → the library default.
204
+ *
205
+ * @remarks Requires `FileSystem` and {@link ChangesetConfig} at build.
206
+ * The kit's `detect` contract no longer receives the workspace root, so the changeset
207
+ * lookups read it from `pkg.workspaceRoot` — the discovery root the package was found
208
+ * against, never a filesystem marker walk, which could escape an unmarked root and read
209
+ * the wrong `.changeset/config.json`.
210
+ *
211
+ * @since 0.4.0
212
+ * @public
213
+ */
214
+ static layerAdaptive = Layer.effect(PublishabilityDetector, Effect.gen(function* () {
215
+ const fs = yield* FileSystem.FileSystem;
216
+ const config = yield* ChangesetConfig;
217
+ const vanilla = PublishabilityDetector.npm;
218
+ return { detect: (pkg) => Effect.gen(function* () {
219
+ const root = pkg.workspaceRoot;
220
+ if (yield* config.isIgnored(pkg.name, root)) return [];
221
+ const mode = yield* config.mode(root);
222
+ if (mode === "none") return [];
223
+ if (mode === "silk") {
224
+ const raw = yield* readRaw(fs, pkg.packageJsonPath);
225
+ if (!raw) return [];
226
+ const binding = yield* readTargetsBinding(fs, pkg.path);
227
+ return SilkPublishability.detect(pkg.name, raw, binding);
228
+ }
229
+ return yield* vanilla.detect(pkg);
230
+ }) };
231
+ }));
182
232
  };
183
233
  /**
184
234
  * Reduce a directory to a comparable package-relative POSIX path: backslashes to
@@ -195,7 +245,8 @@ var SilkPublishability = class {
195
245
  */
196
246
  const normalizeDir = (dir) => {
197
247
  const slashed = dir.replaceAll("\\", "/");
198
- const normalized = trimTrailingSlashes(slashed.startsWith("./") ? slashed.slice(2) : slashed);
248
+ const withoutPrefix = slashed.startsWith("./") ? slashed.slice(2) : slashed;
249
+ const normalized = trimTrailingSlashes(withoutPrefix);
199
250
  return normalized === "" ? "." : normalized;
200
251
  };
201
252
  /** True when a built target directory's package.json is `private: true`. Missing/unreadable/malformed → false. */
@@ -225,56 +276,6 @@ const readTargetsBinding = (fs, pkgPath) => fs.readFileString(join(pkgPath, "dis
225
276
  try: () => JSON.parse(content),
226
277
  catch: () => /* @__PURE__ */ new Error("invalid targets.json")
227
278
  })), Effect.orElseSucceed(() => null));
228
- /**
229
- * Override of `@effected/workspaces`' `PublishabilityDetector` Tag with pure silk rules.
230
- *
231
- * @remarks Requires `FileSystem` (captured at layer build); `detect` reads the raw
232
- * `package.json` from `pkg.packageJsonPath` and applies `SilkPublishability.detect`.
233
- *
234
- * @since 0.4.0
235
- * @public
236
- */
237
- const SilkPublishabilityDetectorLive = Layer.effect(PublishabilityDetector, Effect.gen(function* () {
238
- const fs = yield* FileSystem.FileSystem;
239
- return { detect: (pkg) => Effect.gen(function* () {
240
- const raw = yield* readRaw(fs, pkg.packageJsonPath);
241
- if (!raw) return [];
242
- const binding = yield* readTargetsBinding(fs, pkg.path);
243
- return SilkPublishability.detect(pkg.name, raw, binding);
244
- }) };
245
- }));
246
- /**
247
- * Ignore-aware override of `PublishabilityDetector`. `detect` short-circuits to `[]`
248
- * for changeset-ignored packages, then dispatches on `ChangesetConfig.mode`:
249
- * `none` → `[]`; `silk` → `SilkPublishability.detect`; `vanilla` → the library default.
250
- *
251
- * @remarks Requires `FileSystem` and {@link ChangesetConfig} at build.
252
- * The kit's `detect` contract no longer receives the workspace root, so the changeset
253
- * lookups read it from `pkg.workspaceRoot` — the discovery root the package was found
254
- * against, never a filesystem marker walk, which could escape an unmarked root and read
255
- * the wrong `.changeset/config.json`.
256
- *
257
- * @since 0.4.0
258
- * @public
259
- */
260
- const PublishabilityDetectorAdaptiveLive = Layer.effect(PublishabilityDetector, Effect.gen(function* () {
261
- const fs = yield* FileSystem.FileSystem;
262
- const config = yield* ChangesetConfig;
263
- const vanilla = PublishabilityDetector.npm;
264
- return { detect: (pkg) => Effect.gen(function* () {
265
- const root = pkg.workspaceRoot;
266
- if (yield* config.isIgnored(pkg.name, root)) return [];
267
- const mode = yield* config.mode(root);
268
- if (mode === "none") return [];
269
- if (mode === "silk") {
270
- const raw = yield* readRaw(fs, pkg.packageJsonPath);
271
- if (!raw) return [];
272
- const binding = yield* readTargetsBinding(fs, pkg.path);
273
- return SilkPublishability.detect(pkg.name, raw, binding);
274
- }
275
- return yield* vanilla.detect(pkg);
276
- }) };
277
- }));
278
279
 
279
280
  //#endregion
280
- export { PublishabilityDetectorAdaptiveLive, SilkPublishability, SilkPublishabilityDetectorLive, readTargetsBinding };
281
+ export { SilkPublishability, readTargetsBinding };