@rsdk/yarn.constraints 6.0.0-next.39 → 6.0.0-next.40

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 (118) hide show
  1. package/DEPENDENCY_MODEL.md +452 -0
  2. package/README.MD +24 -0
  3. package/__tests__/compatibility.test.ts +321 -0
  4. package/__tests__/engine.test.ts +1002 -0
  5. package/__tests__/fixtures/imports/bin.js +4 -0
  6. package/__tests__/fixtures/imports/export-entry.mjs +1 -0
  7. package/__tests__/fixtures/imports/root-entry.js +3 -0
  8. package/__tests__/fixtures/imports/src/common.cjs +3 -0
  9. package/__tests__/fixtures/imports/src/common.cts +3 -0
  10. package/__tests__/fixtures/imports/src/component.tsx +4 -0
  11. package/__tests__/fixtures/imports/src/index.ts +13 -0
  12. package/__tests__/fixtures/imports/src/module.mjs +3 -0
  13. package/__tests__/fixtures/imports/src/module.mts +3 -0
  14. package/__tests__/fixtures/imports/src/plain.js +3 -0
  15. package/__tests__/fixtures/imports/src/test-only-usage.ts +1 -0
  16. package/__tests__/imports.test.ts +206 -0
  17. package/__tests__/manifest-writer.test.ts +157 -0
  18. package/dist/ansi.d.ts +9 -0
  19. package/dist/ansi.js +24 -0
  20. package/dist/ansi.js.map +1 -0
  21. package/dist/bin/depdoc.d.ts +2 -0
  22. package/dist/bin/depdoc.js +157 -0
  23. package/dist/bin/depdoc.js.map +1 -0
  24. package/dist/collectors/config.d.ts +2 -0
  25. package/dist/collectors/config.js +25 -0
  26. package/dist/collectors/config.js.map +1 -0
  27. package/dist/collectors/external-metadata.d.ts +5 -0
  28. package/dist/collectors/external-metadata.js +110 -0
  29. package/dist/collectors/external-metadata.js.map +1 -0
  30. package/dist/collectors/package-extensions.d.ts +3 -0
  31. package/dist/collectors/package-extensions.js +43 -0
  32. package/dist/collectors/package-extensions.js.map +1 -0
  33. package/dist/collectors/type-providers.d.ts +3 -0
  34. package/dist/collectors/type-providers.js +46 -0
  35. package/dist/collectors/type-providers.js.map +1 -0
  36. package/dist/collectors/workspaces.d.ts +2 -0
  37. package/dist/collectors/workspaces.js +88 -0
  38. package/dist/collectors/workspaces.js.map +1 -0
  39. package/dist/dependency-model.d.ts +11 -0
  40. package/dist/dependency-model.js +18 -0
  41. package/dist/dependency-model.js.map +1 -0
  42. package/dist/index.d.ts +9 -5
  43. package/dist/index.js +13 -33
  44. package/dist/index.js.map +1 -1
  45. package/dist/lib/imports.d.ts +9 -0
  46. package/dist/lib/imports.js +249 -0
  47. package/dist/lib/imports.js.map +1 -0
  48. package/dist/lib/package-json.d.ts +21 -0
  49. package/dist/lib/package-json.js +32 -0
  50. package/dist/lib/package-json.js.map +1 -0
  51. package/dist/model/diagnostics.d.ts +4 -0
  52. package/dist/model/diagnostics.js +273 -0
  53. package/dist/model/diagnostics.js.map +1 -0
  54. package/dist/model/engine.d.ts +5 -0
  55. package/dist/model/engine.js +52 -0
  56. package/dist/model/engine.js.map +1 -0
  57. package/dist/model/expected.d.ts +20 -0
  58. package/dist/model/expected.js +89 -0
  59. package/dist/model/expected.js.map +1 -0
  60. package/dist/model/peer-propagation.d.ts +2 -0
  61. package/dist/model/peer-propagation.js +124 -0
  62. package/dist/model/peer-propagation.js.map +1 -0
  63. package/dist/model/placement.d.ts +9 -0
  64. package/dist/model/placement.js +205 -0
  65. package/dist/model/placement.js.map +1 -0
  66. package/dist/model/rules.d.ts +14 -0
  67. package/dist/model/rules.js +46 -0
  68. package/dist/model/rules.js.map +1 -0
  69. package/dist/model/types.d.ts +117 -0
  70. package/dist/model/types.js +9 -0
  71. package/dist/model/types.js.map +1 -0
  72. package/dist/model/versions.d.ts +3 -0
  73. package/dist/model/versions.js +73 -0
  74. package/dist/model/versions.js.map +1 -0
  75. package/dist/reporting.d.ts +3 -0
  76. package/dist/reporting.js +80 -0
  77. package/dist/reporting.js.map +1 -0
  78. package/dist/runner.d.ts +2 -0
  79. package/dist/runner.js +70 -0
  80. package/dist/runner.js.map +1 -0
  81. package/dist/writer/manifest-writer.d.ts +2 -0
  82. package/dist/writer/manifest-writer.js +72 -0
  83. package/dist/writer/manifest-writer.js.map +1 -0
  84. package/eslint.config.cjs +3 -0
  85. package/jest.config.js +1 -0
  86. package/package.json +7 -3
  87. package/src/ansi.ts +23 -0
  88. package/src/bin/depdoc.ts +213 -0
  89. package/src/collectors/config.ts +26 -0
  90. package/src/collectors/external-metadata.ts +148 -0
  91. package/src/collectors/package-extensions.ts +52 -0
  92. package/src/collectors/type-providers.ts +51 -0
  93. package/src/collectors/workspaces.ts +99 -0
  94. package/src/dependency-model.ts +26 -0
  95. package/src/index.ts +28 -45
  96. package/src/lib/imports.ts +293 -0
  97. package/src/lib/package-json.ts +46 -0
  98. package/src/model/diagnostics.ts +328 -0
  99. package/src/model/engine.ts +120 -0
  100. package/src/model/expected.ts +141 -0
  101. package/src/model/peer-propagation.ts +199 -0
  102. package/src/model/placement.ts +372 -0
  103. package/src/model/rules.ts +73 -0
  104. package/src/model/types.ts +164 -0
  105. package/src/model/versions.ts +109 -0
  106. package/src/reporting.ts +117 -0
  107. package/src/runner.ts +102 -0
  108. package/src/writer/manifest-writer.ts +111 -0
  109. package/tsconfig.build.json +1 -0
  110. package/tsconfig.json +6 -1
  111. package/dist/constraint-schema.d.ts +0 -1
  112. package/dist/constraint-schema.js +0 -17
  113. package/dist/constraint-schema.js.map +0 -1
  114. package/dist/dependency-checker.d.ts +0 -8
  115. package/dist/dependency-checker.js +0 -40
  116. package/dist/dependency-checker.js.map +0 -1
  117. package/src/constraint-schema.ts +0 -20
  118. package/src/dependency-checker.ts +0 -41
@@ -0,0 +1,452 @@
1
+ # Dependency Model
2
+
3
+ Status: draft.
4
+
5
+ This document defines the dependency ownership model for the monorepo. The goal
6
+ is to make dependency placement deterministic, checkable, and mostly
7
+ autofixable.
8
+
9
+ ## Terms
10
+
11
+ | Term | Meaning |
12
+ |---|---|
13
+ | Root | The monorepo root workspace. It is an orchestrator, not a product package. |
14
+ | Workspace | Any non-root workspace package. |
15
+ | Role | Explicit package role: `library`, `service`, or `cli`. |
16
+ | Local dependency | A package that is also present as a workspace in this monorepo. |
17
+ | External dependency | Any dependency that is not a local workspace package. |
18
+ | Runtime surface | Imports required by emitted JavaScript / production execution. |
19
+ | Public type surface | Imports that appear in emitted `dist/**/*.d.ts`. |
20
+ | Private dev surface | Test, build, lint, type-only, and tooling usage that does not reach runtime or public `.d.ts`. |
21
+ | Mirror | A `library` package has the same dependency name and range in both `peerDependencies` and `devDependencies`. |
22
+
23
+ ## Invariants
24
+
25
+ ### Root
26
+
27
+ | ID | Invariant | Check |
28
+ |---|---|---|
29
+ | R1 | Root is not a product package. | Root `package.json` has `private: true`. |
30
+ | R2 | Root may contain only `devDependencies`. | Root `dependencies` and `peerDependencies` are forbidden. |
31
+ | R3 | Root `devDependencies` define the shared dev/type/build environment. | Tooling, `@types/*`, test infra, build infra, release infra, and constraints infra live here. |
32
+ | R4 | Root dependencies do not declare dependencies for workspaces. | A workspace runtime/public dependency must be declared in that workspace manifest. |
33
+
34
+ ### Workspace Roles
35
+
36
+ | ID | Invariant | Check |
37
+ |---|---|---|
38
+ | W1 | Every workspace has an explicit role. | `role` is one of `library`, `service`, `cli`. |
39
+ | W2 | Local workspace dependencies are runtime graph edges. | Local deps are in `dependencies` with `workspace:*`. |
40
+ | W3 | Dependency ownership belongs to the importing workspace. | Runtime/public imports must be represented in that workspace manifest. |
41
+
42
+ ### Libraries
43
+
44
+ | ID | Invariant | Check |
45
+ |---|---|---|
46
+ | L1 | External deps required by runtime or public type surface default to `peerDependencies`. | Unless an explicit override says otherwise. |
47
+ | L2 | `devDependencies` exactly mirror `peerDependencies`. | Same names and same ranges. |
48
+ | L3 | Extra `devDependencies` are forbidden. | `devDependencies - peerDependencies = empty`. |
49
+ | L4 | A dependency cannot be both `dependencies` and `peerDependencies`. | A package has one runtime/public ownership mode. |
50
+ | L5 | External implementation deps are explicit exceptions. | They require a `section: dependencies` override. |
51
+ | L6 | Private dev/type/test/build-only deps are not declared in the library package. | They belong to root `devDependencies`. |
52
+
53
+ ### Services and CLI Packages
54
+
55
+ | ID | Invariant | Check |
56
+ |---|---|---|
57
+ | S1 | Runtime/prod deps are declared in `dependencies`. | Includes local and external runtime deps. |
58
+ | S2 | `peerDependencies` are forbidden. | Services and CLIs do not push a peer contract to consumers. |
59
+ | S3 | `devDependencies` are forbidden. | Dev/type/test/build deps live in root. |
60
+ | S4 | CLI runtime deps cannot be peers. | Global install / `dlx` flows do not reliably install peer dependencies. |
61
+
62
+ ### Types
63
+
64
+ | ID | Invariant | Check |
65
+ |---|---|---|
66
+ | T1 | Type-only deps that do not appear in `dist/**/*.d.ts` are private dev deps. | They belong to root `devDependencies`. |
67
+ | T2 | Type deps that appear in `dist/**/*.d.ts` are public contract deps. | `library`: peer + dev mirror. `service`/`cli`: dependency. |
68
+ | T3 | `@types/*` default to root `devDependencies`. | Until they appear in public `.d.ts`. |
69
+ | T4 | If public `.d.ts` requires a DefinitelyTyped provider, that provider is public contract. | The corresponding `@types/*` is promoted according to T2. |
70
+
71
+ ### Peer Propagation
72
+
73
+ | ID | Invariant | Check |
74
+ |---|---|---|
75
+ | P1 | A workspace depending on a local library must provide that library's peers. | `library` consumer: peer + dev mirror. `service`/`cli`: dependencies. |
76
+ | P2 | Required peers of external npm deps must be provided by the current workspace. | Optional peers are not forced. |
77
+ | P3 | Incorrect third-party peer metadata is fixed through package manager metadata overrides. | Use `packageExtensions`, not random workspace deps. |
78
+ | P4 | Local workspace packages are not propagated as peer targets. | Local packages stay `dependencies: workspace:*`. |
79
+
80
+ ### Versions and Overrides
81
+
82
+ | ID | Invariant | Check |
83
+ |---|---|---|
84
+ | V1 | Any external dependency that appears more than once must have a version rule. | Count root and all workspaces, all dependency sections. |
85
+ | V2 | Wildcard rules count as version rules. | For example `@nestjs/*`. |
86
+ | V3 | The constraints config does not describe the whole model. | It contains versions, overrides, root-only rules, manual required dependencies, and workspace-specific exceptions. |
87
+ | V4 | The last matching rule wins. | Enables broad rules plus specific overrides. |
88
+ | V5 | `rootOnly` means the dependency belongs only to the root dev environment. | Workspace usage is forbidden unless a more specific override exists. |
89
+
90
+ ## Placement Formula
91
+
92
+ ```text
93
+ root:
94
+ only devDependencies
95
+
96
+ library:
97
+ dependencies = local workspace deps + explicit implementation overrides
98
+ peerDependencies = external runtime/public deps by default
99
+ devDependencies = exact mirror of peerDependencies
100
+
101
+ service/cli:
102
+ dependencies = runtime/prod deps
103
+ peerDependencies = forbidden
104
+ devDependencies = forbidden
105
+ ```
106
+
107
+ ## Check Algorithm
108
+
109
+ The checks should run from facts to derived manifests. A later phase should not
110
+ guess something that an earlier phase can derive.
111
+
112
+ ### Phase 1. Load Facts
113
+
114
+ 1. Read root `package.json`.
115
+ 2. Read every workspace `package.json`.
116
+ 3. Build the set of local workspace package names.
117
+ 4. Read dependency rules: version rules, section overrides, `rootOnly` rules,
118
+ manual `required` dependencies, and workspace-specific exceptions.
119
+ 5. Read package manager metadata overrides, such as `packageExtensions`.
120
+
121
+ ### Phase 2. Validate Basic Shape
122
+
123
+ 1. Root has `private: true`.
124
+ 2. Root has no `dependencies`.
125
+ 3. Root has no `peerDependencies`.
126
+ 4. Every non-root workspace has a valid `role`.
127
+ 5. `service` and `cli` workspaces have no `peerDependencies`.
128
+ 6. `service` and `cli` workspaces have no `devDependencies`.
129
+ 7. `library` workspaces have no dependency listed in both `dependencies` and
130
+ `peerDependencies`.
131
+ 8. No workspace has the same dependency in both `dependencies` and
132
+ `devDependencies`.
133
+
134
+ ### Phase 3. Collect Usage
135
+
136
+ 1. Scan source imports for every workspace.
137
+ 2. Classify each import as local or external.
138
+ 3. Classify each import as runtime, type-only, test-only, or tooling-only.
139
+ 4. Scan emitted `dist/**/*.d.ts` imports when `dist/` exists.
140
+ 5. In `--with-dts` mode, require `dist/` for workspaces with `src/`; without
141
+ `--with-dts`, missing `dist/` is allowed so local source-only checks remain
142
+ usable before build.
143
+ 6. Mark all dependencies found in emitted `.d.ts` as public type surface.
144
+ 7. Collect `bin`, `exports`, `main`, and package entry metadata to identify
145
+ runtime/public entrypoints where needed.
146
+
147
+ ### Phase 4. Derive Required Public/Runtime Deps
148
+
149
+ For each workspace:
150
+
151
+ 1. Local runtime/public deps become `dependencies: workspace:*`.
152
+ 2. For `library`, external runtime/public deps become `peerDependencies` by
153
+ default.
154
+ 3. For `library`, external deps with `section: dependencies` override become
155
+ `dependencies`.
156
+ 4. For `service` and `cli`, external runtime deps become `dependencies`.
157
+ 5. Type-only deps that appear in `dist/**/*.d.ts` are treated as public deps.
158
+ 6. Type-only/test/tooling deps that do not appear in `dist/**/*.d.ts` are moved
159
+ to root `devDependencies`.
160
+ 7. Dependencies matched by a concrete `required: true` rule are treated as
161
+ required public/runtime dependencies even when source scanning cannot see a
162
+ direct import.
163
+
164
+ ### Phase 5. Propagate Peers
165
+
166
+ For each workspace dependency edge:
167
+
168
+ 1. If a workspace depends on a local library, read that library's
169
+ `peerDependencies`.
170
+ 2. If a workspace depends on an external npm package, read that package's
171
+ required `peerDependencies`.
172
+ 3. Ignore optional peers.
173
+ 4. Ignore local workspace packages as peer targets.
174
+ 5. For a `library` consumer, required external peers become `peerDependencies`.
175
+ 6. For a `service` or `cli` consumer, required external peers become
176
+ `dependencies`.
177
+ 7. Third-party metadata mistakes are handled by metadata overrides before this
178
+ phase, so this phase sees corrected peer metadata.
179
+
180
+ ### Phase 6. Derive Mirrors
181
+
182
+ For each `library`:
183
+
184
+ 1. `devDependencies` must be exactly equal to `peerDependencies`.
185
+ 2. Every peer range is copied exactly into the dev mirror.
186
+ 3. Any extra dev dependency is removed or moved to root dev dependencies,
187
+ depending on whether it is still needed by private dev usage.
188
+
189
+ ### Phase 7. Resolve Versions
190
+
191
+ 1. Count every external dependency occurrence across root and all workspaces,
192
+ all sections.
193
+ 2. If an external dependency appears more than once, require a matching version
194
+ rule.
195
+ 3. A wildcard rule is valid if it provides a version.
196
+ 4. Apply the last matching rule.
197
+ 5. Mirror ranges must stay identical.
198
+ 6. Local workspace deps use `workspace:*`.
199
+
200
+ ### Phase 8. Compare Expected vs Actual Manifests
201
+
202
+ For each manifest:
203
+
204
+ 1. Report missing dependencies.
205
+ 2. Report dependencies in the wrong section.
206
+ 3. Report dependencies with the wrong version range.
207
+ 4. Report forbidden dependencies.
208
+ 5. Report stale dependencies that are not required by the derived graph.
209
+ 6. Report missing or incorrect library peer/dev mirrors.
210
+ 7. Report root-only violations.
211
+
212
+ ### Phase 9. Autofix
213
+
214
+ Autofix should write manifests from the derived expected graph:
215
+
216
+ 1. Remove forbidden root `dependencies` and `peerDependencies`.
217
+ 2. Add/move local workspace deps to `dependencies: workspace:*`.
218
+ 3. Add/move library external public/runtime deps to `peerDependencies`.
219
+ 4. Rebuild library `devDependencies` from `peerDependencies`.
220
+ 5. Add/move service and CLI runtime deps to `dependencies`.
221
+ 6. Move private dev/type/test/tooling deps to root `devDependencies`.
222
+ 7. Apply version rules.
223
+ 8. Sort dependency sections consistently.
224
+
225
+ ### Phase 10. Verification Order
226
+
227
+ 1. Run the manifest model checker with autofix.
228
+ 2. Run package install.
229
+ 3. Build packages to generate `dist/**/*.d.ts`.
230
+ 4. Run the type-surface check.
231
+ 5. Run the manifest model checker again, because `.d.ts` leaks can change the
232
+ expected graph.
233
+ 6. Run package install again if manifests changed.
234
+ 7. Assert that package manager peer requirements have no failures.
235
+ 8. Run the full dependency check task.
236
+
237
+ ## Target Tooling Shape
238
+
239
+ The implementation should have one CLI backed by one dependency model engine.
240
+ Separate scripts must not own separate placement logic.
241
+
242
+ ```text
243
+ depdoc check
244
+ depdoc fix
245
+ depdoc explain <workspace> <dependency>
246
+ depdoc doctor
247
+ ```
248
+
249
+ The CLI commands share the same pipeline:
250
+
251
+ ```text
252
+ collect facts
253
+ -> derive expected dependency graph
254
+ -> compare actual manifests with expected manifests
255
+ -> print diagnostics or write fixes
256
+ ```
257
+
258
+ `check` and `fix` differ only in the final step. `check` reports diagnostics.
259
+ `fix` writes the expected manifests. Both commands include `.d.ts` facts when
260
+ `dist/` already exists, so a normal `fix` must not delete public type-surface
261
+ dependencies from a built checkout. The `--with-dts` flag only changes
262
+ strictness around missing build artifacts: it requires `dist/` for packages with
263
+ `src/`.
264
+
265
+ `explain` explains why a dependency belongs to a specific section, which rule
266
+ matched it, which import or peer edge required it, and whether the dependency is
267
+ part of runtime surface, public type surface, or private dev surface.
268
+
269
+ `doctor` runs the full compatibility pipeline:
270
+
271
+ ```text
272
+ depdoc fix
273
+ yarn install
274
+ build packages
275
+ depdoc check --with-dts
276
+ yarn install
277
+ yarn explain peer-requirements
278
+ lint
279
+ typecheck
280
+ ```
281
+
282
+ The exact build/lint/typecheck commands are repository-specific, but the order
283
+ is part of the model: `.d.ts` facts are available when `dist/` exists, and
284
+ `--with-dts` makes missing `.d.ts` artifacts a hard failure after build.
285
+
286
+ ## Implementation Layers
287
+
288
+ ### Engine
289
+
290
+ The engine should be pure and deterministic.
291
+
292
+ ```ts
293
+ deriveDependencyModel({
294
+ rootPackage,
295
+ workspaces,
296
+ sourceImports,
297
+ dtsImports,
298
+ externalPeerMetadata,
299
+ rules,
300
+ });
301
+ ```
302
+
303
+ The engine returns:
304
+
305
+ ```ts
306
+ {
307
+ expectedManifests,
308
+ diagnostics,
309
+ fixes
310
+ }
311
+ ```
312
+
313
+ The engine must not run Yarn, read the filesystem, or execute TypeScript. It
314
+ only consumes facts and derives the expected dependency graph.
315
+
316
+ ### Collectors
317
+
318
+ Collectors gather facts for the engine:
319
+
320
+ | Collector | Responsibility |
321
+ |---|---|
322
+ | Package JSON collector | Reads root and workspace manifests. |
323
+ | Workspace collector | Reads workspace names and locations. |
324
+ | Source import collector | Reads source imports and classifies runtime/type/test/tooling usage. |
325
+ | DTS import collector | Reads emitted `dist/**/*.d.ts` imports. |
326
+ | External peer metadata collector | Reads required/optional peers from installed packages and metadata overrides. |
327
+ | Rules collector | Reads version rules, section overrides, root-only rules, and workspace exceptions. |
328
+
329
+ Collectors may be integration-tested separately. The core placement model should
330
+ remain testable without filesystem or Yarn.
331
+
332
+ ### Manifest Writer
333
+
334
+ The writer applies engine fixes:
335
+
336
+ 1. Preserve unrelated manifest fields.
337
+ 2. Rewrite dependency sections from the expected graph.
338
+ 3. Keep peer/dev mirrors exact for libraries.
339
+ 4. Apply normalized sorting.
340
+ 5. Avoid touching files when generated content is identical.
341
+
342
+ ## Test Strategy
343
+
344
+ Testing must prove two different things:
345
+
346
+ 1. The dependency model is internally consistent.
347
+ 2. Real tools accept manifests produced by the model.
348
+
349
+ ### Test Layers
350
+
351
+ | Layer | Goal | Uses Yarn/build |
352
+ |---|---|---|
353
+ | Model unit tests | Test individual invariants and section decisions. | No |
354
+ | Model fixture tests | Test complete expected manifests from package/import facts. | No |
355
+ | Collector tests | Test import parsing, workspace discovery, package metadata parsing. | Minimal |
356
+ | Type-surface tests | Test behavior when `dist/**/*.d.ts` contains public type imports. | No build required if `.d.ts` fixtures are provided |
357
+ | Tool compatibility tests | Test generated manifests against real Yarn, TypeScript, and ESLint. | Yes |
358
+ | Repo smoke tests | Test the model on the current monorepo. | Yes |
359
+
360
+ ### Model Fixture Format
361
+
362
+ Each fixture should provide package manifests, model facts, rules, and expected
363
+ output.
364
+
365
+ ```text
366
+ fixtures/library-external-default-peer/
367
+ input/
368
+ package.json
369
+ packages/foo/package.json
370
+ facts.json
371
+ rules.yml
372
+ expected/
373
+ package.json
374
+ packages/foo/package.json
375
+ diagnostics.json
376
+ ```
377
+
378
+ Example `facts.json`:
379
+
380
+ ```json
381
+ {
382
+ "sourceImports": {
383
+ "packages/foo": [
384
+ {
385
+ "packageName": "lodash",
386
+ "kind": "runtime",
387
+ "file": "src/index.ts"
388
+ }
389
+ ]
390
+ },
391
+ "dtsImports": {
392
+ "packages/foo": []
393
+ },
394
+ "externalPeerMetadata": {}
395
+ }
396
+ ```
397
+
398
+ ### Required Model Fixtures
399
+
400
+ | Fixture | Proves |
401
+ |---|---|
402
+ | `root-only-devdeps` | Root rejects `dependencies` and `peerDependencies`. |
403
+ | `library-external-default-peer` | External runtime dep in a library becomes peer + dev mirror. |
404
+ | `library-implementation-override` | `section: dependencies` keeps an external library dep in `dependencies`. |
405
+ | `library-dev-mirror-exact` | Library `devDependencies` exactly mirror `peerDependencies`. |
406
+ | `library-private-type-root-dev` | Private type-only usage belongs to root `devDependencies`. |
407
+ | `library-dts-type-leak` | A dependency imported by public `.d.ts` becomes public contract. |
408
+ | `service-runtime-deps` | Service external runtime deps become `dependencies`; peers/dev are forbidden. |
409
+ | `cli-runtime-deps` | CLI runtime deps become `dependencies`; peers are forbidden. |
410
+ | `local-workspace-deps` | Local workspace deps are `dependencies: workspace:*`. |
411
+ | `peer-propagation-local-library` | A consumer provides peers required by a local library. |
412
+ | `peer-propagation-external-package` | A consumer provides required peers of an external npm dependency. |
413
+ | `optional-peers-ignored` | Optional peers are not added. |
414
+ | `repeated-dep-needs-version-rule` | External deps used more than once require a version rule. |
415
+ | `rule-precedence-last-wins` | The last matching rule wins. |
416
+ | `rootonly-violation` | `rootOnly` deps are rejected in workspaces. |
417
+
418
+ ### Compatibility Tests
419
+
420
+ Compatibility tests run on small temporary monorepos. They should be few and
421
+ focused, because they invoke real tools.
422
+
423
+ | Test | Proves |
424
+ |---|---|
425
+ | `yarn-install-clean` | After autofix, `yarn install` has no dependency placement warnings. |
426
+ | `yarn-peer-requirements-clean` | `yarn explain peer-requirements` has no failed peer requirements. |
427
+ | `tsc-library-build` | A library with peer + dev mirror compiles. |
428
+ | `tsc-dts-leak` | A public `.d.ts` leak is detected when `dist/` exists and changes expected manifests. |
429
+ | `eslint-extraneous-compatible` | ESLint import/dependency rules do not contradict the model. |
430
+ | `production-focus` | Production install/focus uses only production graph and does not require root dev deps or package dev mirrors. |
431
+ | `cli-install-shape` | CLI runtime deps are in `dependencies`, so install/dlx-style usage has the required deps. |
432
+ | `service-prod-shape` | Service production graph is complete from `dependencies`. |
433
+
434
+ The production test may use `yarn workspaces focus --production` if that is the
435
+ chosen production mechanism. Otherwise it should assert the same invariant
436
+ directly: production runtime must not depend on root `devDependencies` or
437
+ workspace `devDependencies`.
438
+
439
+ ### Repo Smoke Tests
440
+
441
+ Repo smoke tests verify that the model works on the real repository:
442
+
443
+ 1. Run `depdoc fix`.
444
+ 2. Run `yarn install`.
445
+ 3. Build packages.
446
+ 4. Run `depdoc check --with-dts`.
447
+ 5. Run `yarn install` again if manifests changed.
448
+ 6. Assert no failed peer requirements.
449
+ 7. Run repo lint/typecheck/dependency task.
450
+
451
+ This is the final confidence layer. Most edge cases should still be covered by
452
+ fast model fixtures, not by expanding the smoke suite.
package/README.MD CHANGED
@@ -12,6 +12,30 @@ some-package: 1.0.0
12
12
 
13
13
  ## Usage
14
14
 
15
+ Dependency model CLI:
16
+
17
+ ```sh
18
+ depdoc check
19
+ depdoc fix
20
+ depdoc explain <workspace> <dependency>
21
+ depdoc doctor
22
+ ```
23
+
24
+ `depdoc` is the unified dependency-model entrypoint. It derives the
25
+ expected manifests from workspace roles, dependency rules, source imports,
26
+ emitted `.d.ts` imports, peer propagation, and library peer/dev mirrors.
27
+
28
+ Dependency rules can mark indirect runtime requirements explicitly:
29
+
30
+ ```yaml
31
+ rules:
32
+ - match: '@fastify/static'
33
+ workspace: '@rsdk/http.server.fastify'
34
+ section: dependencies
35
+ version: '^6.12.0'
36
+ required: true
37
+ ```
38
+
15
39
  Default
16
40
 
17
41
  ```js