@webpieces/nx-webpieces-rules 0.4.846 → 0.4.848

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 (117) hide show
  1. package/README.md +54 -15
  2. package/executors.json +3 -68
  3. package/package.json +9 -9
  4. package/src/executors/help/executor.js +6 -4
  5. package/src/executors/help/executor.js.map +1 -1
  6. package/src/executors/validate-architecture-unchanged/executor.d.ts +8 -0
  7. package/src/executors/validate-architecture-unchanged/executor.js +20 -18
  8. package/src/executors/validate-architecture-unchanged/executor.js.map +1 -1
  9. package/src/executors/validate-code/executor.d.ts +2 -7
  10. package/src/executors/validate-code/executor.js +31 -2
  11. package/src/executors/validate-code/executor.js.map +1 -1
  12. package/src/executors/validate-code/schema.json +6 -281
  13. package/src/executors/validate-runtime-architecture/schema.json +1 -1
  14. package/src/executors/visualize/executor.js +7 -9
  15. package/src/executors/visualize/executor.js.map +1 -1
  16. package/src/executors/visualize/schema.json +1 -1
  17. package/src/executors/visualize-runtime/executor.js +8 -9
  18. package/src/executors/visualize-runtime/executor.js.map +1 -1
  19. package/src/executors/visualize-runtime/schema.json +1 -1
  20. package/src/lib/api-usage/wire-closure.d.ts +3 -3
  21. package/src/lib/api-usage/wire-closure.js +5 -5
  22. package/src/lib/api-usage/wire-closure.js.map +1 -1
  23. package/src/lib/api-usage/wire-suffix-entry.d.ts +5 -0
  24. package/src/lib/api-usage/wire-suffix-entry.js +10 -0
  25. package/src/lib/api-usage/wire-suffix-entry.js.map +1 -0
  26. package/src/lib/graph-loader.js +2 -2
  27. package/src/lib/graph-loader.js.map +1 -1
  28. package/src/lib/graph-visualizer.d.ts +1 -0
  29. package/src/lib/graph-visualizer.js +3 -0
  30. package/src/lib/graph-visualizer.js.map +1 -1
  31. package/src/lib/rule-gate.d.ts +1 -2
  32. package/src/lib/rule-gate.js +3 -4
  33. package/src/lib/rule-gate.js.map +1 -1
  34. package/src/lib/runtime-html-page.d.ts +35 -0
  35. package/src/lib/runtime-html-page.js +112 -0
  36. package/src/lib/runtime-html-page.js.map +1 -0
  37. package/src/lib/runtime-visualizer.d.ts +4 -38
  38. package/src/lib/runtime-visualizer.js +5 -108
  39. package/src/lib/runtime-visualizer.js.map +1 -1
  40. package/src/lib/saved-snapshot.d.ts +16 -0
  41. package/src/lib/saved-snapshot.js +80 -0
  42. package/src/lib/saved-snapshot.js.map +1 -0
  43. package/src/native-actions.d.ts +23 -0
  44. package/src/native-actions.js +69 -0
  45. package/src/native-actions.js.map +1 -0
  46. package/src/nx-policy-registry.d.ts +8 -0
  47. package/src/nx-policy-registry.js +40 -0
  48. package/src/nx-policy-registry.js.map +1 -0
  49. package/src/pack-build-runner.d.ts +6 -0
  50. package/src/pack-build-runner.js +46 -0
  51. package/src/pack-build-runner.js.map +1 -0
  52. package/src/plugin.js +8 -42
  53. package/src/plugin.js.map +1 -1
  54. package/src/rule-help.d.ts +3 -0
  55. package/src/rule-help.js +24 -0
  56. package/src/rule-help.js.map +1 -0
  57. package/src/rule-pack.js +5 -28
  58. package/src/rule-pack.js.map +1 -1
  59. package/src/rule-runtime.d.ts +5 -0
  60. package/src/rule-runtime.js +94 -0
  61. package/src/rule-runtime.js.map +1 -0
  62. package/src/runtime-targets.js +2 -2
  63. package/src/runtime-targets.js.map +1 -1
  64. package/src/validation-targets.js +21 -5
  65. package/src/validation-targets.js.map +1 -1
  66. package/src/executors/validate-catch-error-pattern/executor.d.ts +0 -4
  67. package/src/executors/validate-catch-error-pattern/executor.js +0 -8
  68. package/src/executors/validate-catch-error-pattern/executor.js.map +0 -1
  69. package/src/executors/validate-catch-error-pattern/schema.json +0 -24
  70. package/src/executors/validate-dtos/executor.d.ts +0 -4
  71. package/src/executors/validate-dtos/executor.js +0 -8
  72. package/src/executors/validate-dtos/executor.js.map +0 -1
  73. package/src/executors/validate-dtos/schema.json +0 -33
  74. package/src/executors/validate-modified-files/executor.d.ts +0 -4
  75. package/src/executors/validate-modified-files/executor.js +0 -8
  76. package/src/executors/validate-modified-files/executor.js.map +0 -1
  77. package/src/executors/validate-modified-files/schema.json +0 -25
  78. package/src/executors/validate-modified-methods/executor.d.ts +0 -4
  79. package/src/executors/validate-modified-methods/executor.js +0 -8
  80. package/src/executors/validate-modified-methods/executor.js.map +0 -1
  81. package/src/executors/validate-modified-methods/schema.json +0 -25
  82. package/src/executors/validate-new-methods/executor.d.ts +0 -4
  83. package/src/executors/validate-new-methods/executor.js +0 -8
  84. package/src/executors/validate-new-methods/executor.js.map +0 -1
  85. package/src/executors/validate-new-methods/schema.json +0 -25
  86. package/src/executors/validate-no-any-unknown/executor.d.ts +0 -4
  87. package/src/executors/validate-no-any-unknown/executor.js +0 -8
  88. package/src/executors/validate-no-any-unknown/executor.js.map +0 -1
  89. package/src/executors/validate-no-any-unknown/schema.json +0 -24
  90. package/src/executors/validate-no-destructure/executor.d.ts +0 -4
  91. package/src/executors/validate-no-destructure/executor.js +0 -8
  92. package/src/executors/validate-no-destructure/executor.js.map +0 -1
  93. package/src/executors/validate-no-destructure/schema.json +0 -24
  94. package/src/executors/validate-no-direct-api-resolver/executor.d.ts +0 -4
  95. package/src/executors/validate-no-direct-api-resolver/executor.js +0 -8
  96. package/src/executors/validate-no-direct-api-resolver/executor.js.map +0 -1
  97. package/src/executors/validate-no-direct-api-resolver/schema.json +0 -29
  98. package/src/executors/validate-no-implicit-any/executor.d.ts +0 -4
  99. package/src/executors/validate-no-implicit-any/executor.js +0 -8
  100. package/src/executors/validate-no-implicit-any/executor.js.map +0 -1
  101. package/src/executors/validate-no-implicit-any/schema.json +0 -24
  102. package/src/executors/validate-no-inline-types/executor.d.ts +0 -4
  103. package/src/executors/validate-no-inline-types/executor.js +0 -8
  104. package/src/executors/validate-no-inline-types/executor.js.map +0 -1
  105. package/src/executors/validate-no-inline-types/schema.json +0 -24
  106. package/src/executors/validate-no-unmanaged-exceptions/executor.d.ts +0 -4
  107. package/src/executors/validate-no-unmanaged-exceptions/executor.js +0 -8
  108. package/src/executors/validate-no-unmanaged-exceptions/executor.js.map +0 -1
  109. package/src/executors/validate-no-unmanaged-exceptions/schema.json +0 -24
  110. package/src/executors/validate-prisma-converters/executor.d.ts +0 -4
  111. package/src/executors/validate-prisma-converters/executor.js +0 -8
  112. package/src/executors/validate-prisma-converters/executor.js.map +0 -1
  113. package/src/executors/validate-prisma-converters/schema.json +0 -38
  114. package/src/executors/validate-return-types/executor.d.ts +0 -4
  115. package/src/executors/validate-return-types/executor.js +0 -8
  116. package/src/executors/validate-return-types/executor.js.map +0 -1
  117. package/src/executors/validate-return-types/schema.json +0 -24
package/README.md CHANGED
@@ -27,32 +27,45 @@ It is wired into the build: the `@nx/js:tsc` target default lists it in
27
27
 
28
28
  ### Configuration
29
29
 
30
- On/off and a time-boxed grace window come from `webpieces.config.json` at the
31
- workspace root — the same source of truth as every other webpieces rule — under
32
- the rule key `no-file-import-cycles`:
30
+ `webpieces.config.json` declares each owning pack and its config path in the root
31
+ `rulePacks` array. For example, the Nx entry is:
33
32
 
34
- ```jsonc
33
+ ```json
35
34
  {
36
- "rules": {
37
- "no-file-import-cycles": {
38
- "mode": "ON", // "OFF" disables the gate everywhere
39
- "turnOffRuleUntilEpoch": 1771931925, // epoch SECONDS — while now < epoch,
40
- // cycles are REPORTED but the build
41
- // PASSES; after it, the gate fails again
42
- "ignoreTypeOnly": false // when true, ignore `import type`
43
- // re-export cycles (erased at compile
44
- // time, harmless at runtime)
45
- }
35
+ "package": "@webpieces/nx-webpieces-rules",
36
+ "config": ".webpieces/rules/nx.json"
37
+ }
38
+ ```
39
+
40
+ Keep the other selected owners and required root settings. Policy settings come
41
+ from the declared owner file's direct policy-ID map. This entry belongs directly
42
+ in `.webpieces/rules/nx.json` (an excerpt; the other owned policies also require
43
+ explicit settings):
44
+
45
+ ```json
46
+ {
47
+ "no-file-import-cycles": {
48
+ "mode": "RUN_EVERY_TIME",
49
+ "turnOffRuleUntilEpoch": 0,
50
+ "turnOffRuleWhileOnBranch": null,
51
+ "ignoreTypeOnly": false
46
52
  }
47
53
  }
48
54
  ```
49
55
 
56
+ Use complete `OFF` settings for an intentional opt-out. `ignoreTypeOnly: true`
57
+ ignores type-only import/re-export cycles. A future `turnOffRuleUntilEpoch` value
58
+ uses epoch seconds; `0` and a `null` branch hatch keep enforcement active.
59
+ After reviewing the declarations, `pnpm wp-rules-sync` explicitly seeds missing
60
+ owner settings and refreshes the lock/catalog artifacts. Review and commit its
61
+ changes; normal loading never supplies missing required settings.
62
+
50
63
  Semantics, mirroring the method/file-size dated-disable model:
51
64
 
52
65
  | Situation | Result |
53
66
  | ------------------------------------------- | ------------------------------- |
54
67
  | `mode: "OFF"` | Skipped (passes), no madge run |
55
- | Cycle found, no `turnOffRuleUntilEpoch` | **Fails** |
68
+ | Cycle found, `turnOffRuleUntilEpoch: 0` | **Fails** |
56
69
  | Cycle found, `now < turnOffRuleUntilEpoch` | Reported but **passes** (warn) |
57
70
  | Cycle found, `now >= turnOffRuleUntilEpoch` | **Fails** again |
58
71
  | No cycle | Passes |
@@ -66,3 +79,29 @@ forgotten because the gate starts failing again after the date.
66
79
  Setting `circularDeps.enabled: false` in the plugin options removes the target
67
80
  entirely (rather than toggling it via config). Prefer `mode: "OFF"` instead — it
68
81
  keeps the target present so any `dependsOn` references don't dangle.
82
+
83
+ ## View saved architecture and refresh explicitly
84
+
85
+ `pnpm arch:visualize` and `pnpm arch:visualize-runtime` open saved generated
86
+ snapshots. They render presentation files and open the browser without regenerating
87
+ architecture, API contract, or runtime graph facts. Source edits do not update the
88
+ snapshot. Freshness is unknown because these artifacts do not record reliable
89
+ generation provenance; checkout/file modification times are not generation times.
90
+
91
+ Refresh explicitly, then view:
92
+
93
+ ```sh
94
+ pnpm arch:generate
95
+ pnpm arch:visualize
96
+ pnpm arch:visualize-runtime
97
+ ```
98
+
99
+ In consuming workspaces without these npm shortcuts, use
100
+ `pnpm nx run architecture:generate`, `pnpm nx run architecture:visualize`, and
101
+ `pnpm nx run architecture:visualize-runtime`. The compile graph's configured
102
+ `graphPath` (or `--graphPath=...`) is still supported. Missing or unusable saved
103
+ artifacts fail with the artifact path and refresh command; viewing never generates
104
+ as a fallback. A failed generation remains a failure, and viewing any saved files
105
+ afterward does not establish that refresh succeeded. Browser-open failures print
106
+ the HTML path for manual opening. Architecture/API validation and CI still run
107
+ their existing checks independently of visualization.
package/executors.json CHANGED
@@ -8,12 +8,12 @@
8
8
  "visualize": {
9
9
  "implementation": "./src/executors/visualize/executor",
10
10
  "schema": "./src/executors/visualize/schema.json",
11
- "description": "Generate visual representations of the architecture graph"
11
+ "description": "View saved architecture without refreshing; refresh: pnpm nx run architecture:generate"
12
12
  },
13
13
  "visualize-runtime": {
14
14
  "implementation": "./src/executors/visualize-runtime/executor",
15
15
  "schema": "./src/executors/visualize-runtime/schema.json",
16
- "description": "Render the runtime microservice graph (runtime-dependencies.json)"
16
+ "description": "View saved runtime architecture without refreshing; refresh: pnpm nx run architecture:generate"
17
17
  },
18
18
  "validate-runtime-architecture": {
19
19
  "implementation": "./src/executors/validate-runtime-architecture/executor",
@@ -65,75 +65,10 @@
65
65
  "schema": "./src/executors/validate-rules-config/schema.json",
66
66
  "description": "Validate webpieces.config.json once at the scoped rules:check boundary"
67
67
  },
68
- "validate-no-any-unknown": {
69
- "implementation": "./src/executors/validate-no-any-unknown/executor",
70
- "schema": "./src/executors/validate-no-any-unknown/schema.json",
71
- "description": "Validate no any/unknown keywords are used - use specific types instead"
72
- },
73
- "validate-new-methods": {
74
- "implementation": "./src/executors/validate-new-methods/executor",
75
- "schema": "./src/executors/validate-new-methods/schema.json",
76
- "description": "Validate newly added methods don't exceed maximum line count"
77
- },
78
- "validate-modified-methods": {
79
- "implementation": "./src/executors/validate-modified-methods/executor",
80
- "schema": "./src/executors/validate-modified-methods/schema.json",
81
- "description": "Validate modified methods don't exceed maximum line count"
82
- },
83
- "validate-modified-files": {
84
- "implementation": "./src/executors/validate-modified-files/executor",
85
- "schema": "./src/executors/validate-modified-files/schema.json",
86
- "description": "Validate modified files don't exceed maximum line count"
87
- },
88
- "validate-return-types": {
89
- "implementation": "./src/executors/validate-return-types/executor",
90
- "schema": "./src/executors/validate-return-types/schema.json",
91
- "description": "Validate methods have explicit return type annotations"
92
- },
93
- "validate-no-inline-types": {
94
- "implementation": "./src/executors/validate-no-inline-types/executor",
95
- "schema": "./src/executors/validate-no-inline-types/schema.json",
96
- "description": "Validate no inline type literals are used - prefer named types"
97
- },
98
- "validate-no-implicit-any": {
99
- "implementation": "./src/executors/validate-no-implicit-any/executor",
100
- "schema": "./src/executors/validate-no-implicit-any/schema.json",
101
- "description": "Validate no implicit-any inferences on parameters, variables, or properties"
102
- },
103
- "validate-catch-error-pattern": {
104
- "implementation": "./src/executors/validate-catch-error-pattern/executor",
105
- "schema": "./src/executors/validate-catch-error-pattern/schema.json",
106
- "description": "Validate catch blocks follow standardized pattern: catch (err: unknown) { const error = toError(err); }"
107
- },
108
- "validate-no-unmanaged-exceptions": {
109
- "implementation": "./src/executors/validate-no-unmanaged-exceptions/executor",
110
- "schema": "./src/executors/validate-no-unmanaged-exceptions/schema.json",
111
- "description": "Validate try/catch blocks are not used outside chokepoints"
112
- },
113
- "validate-no-destructure": {
114
- "implementation": "./src/executors/validate-no-destructure/executor",
115
- "schema": "./src/executors/validate-no-destructure/schema.json",
116
- "description": "Validate no destructuring patterns are used - use explicit property access instead"
117
- },
118
- "validate-no-direct-api-resolver": {
119
- "implementation": "./src/executors/validate-no-direct-api-resolver/executor",
120
- "schema": "./src/executors/validate-no-direct-api-resolver/schema.json",
121
- "description": "Validate resolvers use services (not APIs) and components subscribe to observables (not route.snapshot.data)"
122
- },
123
- "validate-dtos": {
124
- "implementation": "./src/executors/validate-dtos/executor",
125
- "schema": "./src/executors/validate-dtos/schema.json",
126
- "description": "Validate DTO fields match Prisma Dbo model fields"
127
- },
128
- "validate-prisma-converters": {
129
- "implementation": "./src/executors/validate-prisma-converters/executor",
130
- "schema": "./src/executors/validate-prisma-converters/schema.json",
131
- "description": "Validate Prisma converter method patterns and Dto creation locations"
132
- },
133
68
  "validate-code": {
134
69
  "implementation": "./src/executors/validate-code/executor",
135
70
  "schema": "./src/executors/validate-code/schema.json",
136
- "description": "Combined validation for new methods, modified methods, and file sizes"
71
+ "description": "Execute declared build contributions through their public owner runtimes, with optional single-rule debug execution"
137
72
  },
138
73
  "help": {
139
74
  "implementation": "./src/executors/help/executor",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webpieces/nx-webpieces-rules",
3
- "version": "0.4.846",
3
+ "version": "0.4.848",
4
4
  "description": "Nx-specific webpieces validation rules, graph tooling, executors, and inference plugin.",
5
5
  "type": "commonjs",
6
6
  "main": "./src/index.js",
@@ -10,7 +10,8 @@
10
10
  "./package.json": "./package.json",
11
11
  "./plugin": "./src/plugin.js",
12
12
  "./executors.json": "./executors.json",
13
- "./rule-pack": "./src/rule-pack.js"
13
+ "./rule-pack": "./src/rule-pack.js",
14
+ "./rule-runtime": "./src/rule-runtime.js"
14
15
  },
15
16
  "files": [
16
17
  "src/**/*",
@@ -19,13 +20,12 @@
19
20
  "README.md"
20
21
  ],
21
22
  "dependencies": {
22
- "@webpieces/api-doc-model": "0.4.846",
23
- "@webpieces/code-rules": "0.4.846",
24
- "@webpieces/core-util": "0.4.846",
25
- "@webpieces/eslint-rules": "0.4.846",
26
- "@webpieces/rules-config": "0.4.846",
23
+ "@webpieces/api-doc-model": "0.4.848",
24
+ "@webpieces/core-util": "0.4.848",
25
+ "@webpieces/eslint-rules": "0.4.848",
26
+ "@webpieces/rules-config": "0.4.848",
27
27
  "madge": "8.0.0",
28
- "@webpieces/rules-sdk": "0.4.846"
28
+ "@webpieces/rules-sdk": "0.4.848"
29
29
  },
30
30
  "peerDependencies": {
31
31
  "@nx/devkit": ">=18.0.0"
@@ -41,7 +41,7 @@
41
41
  "access": "public"
42
42
  },
43
43
  "devDependencies": {
44
- "@webpieces/tooling-testkit": "0.4.846"
44
+ "@webpieces/tooling-testkit": "0.4.848"
45
45
  },
46
46
  "types": "./src/index.d.ts",
47
47
  "bin": {
@@ -12,8 +12,9 @@ async function helpExecutor(options, context) {
12
12
  console.log(`${BOLD}📝 Available npm scripts (convenient shortcuts):${RESET}`);
13
13
  console.log('');
14
14
  console.log(' Architecture graph:');
15
- console.log(' npm run arch:generate # Generate dependency graph');
16
- console.log(' npm run arch:visualize # Visualize dependency graph');
15
+ console.log(' npm run arch:generate # Explicitly refresh architecture/API/runtime facts');
16
+ console.log(' npm run arch:visualize # View saved snapshot (does not refresh)');
17
+ console.log(' npm run arch:visualize-runtime # View saved runtime snapshot (does not refresh)');
17
18
  console.log('');
18
19
  console.log(' Validation:');
19
20
  console.log(' npm run arch:validate # Quick validation (no-cycles)');
@@ -25,8 +26,9 @@ async function helpExecutor(options, context) {
25
26
  console.log(`${BOLD}📝 Available Nx targets:${RESET}`);
26
27
  console.log('');
27
28
  console.log(' Workspace-level architecture validation:');
28
- console.log(' nx run architecture:generate # Generate dependency graph');
29
- console.log(' nx run architecture:visualize # Visualize dependency graph');
29
+ console.log(' nx run architecture:generate # Explicitly refresh architecture/API/runtime facts');
30
+ console.log(' nx run architecture:visualize # View saved snapshot (does not refresh)');
31
+ console.log(' nx run architecture:visualize-runtime # View saved runtime snapshot (does not refresh)');
30
32
  console.log(' nx run architecture:validate-no-architecture-cycles # Check for circular project dependencies');
31
33
  console.log(' nx run architecture:validate-architecture-unchanged # Validate against blessed graph');
32
34
  console.log('');
@@ -1 +1 @@
1
- {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/executors/help/executor.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExecutorContext } from '@nx/devkit';\n\nexport interface HelpExecutorOptions {}\n\ntype HelpExecutorResult = { success: true };\n\nexport default async function helpExecutor(\n options: HelpExecutorOptions,\n context: ExecutorContext\n): Promise<HelpExecutorResult> {\n // ANSI color codes\n const GREEN = '\\x1b[32m\\x1b[1m';\n const BOLD = '\\x1b[1m';\n const RESET = '\\x1b[0m';\n\n console.log('');\n console.log(`${GREEN}💡 @webpieces/nx-webpieces-rules - Available Commands${RESET}`);\n console.log('');\n console.log(`${BOLD}📝 Available npm scripts (convenient shortcuts):${RESET}`);\n console.log('');\n console.log(' Architecture graph:');\n console.log(' npm run arch:generate # Generate dependency graph');\n console.log(' npm run arch:visualize # Visualize dependency graph');\n console.log('');\n console.log(' Validation:');\n console.log(' npm run arch:validate # Quick validation (no-cycles)');\n console.log(' npm run arch:validate-all # Full arch validation (+ unchanged check)');\n console.log(' npm run arch:check-circular # Check all projects for circular deps');\n console.log(' npm run arch:check-circular-affected # Check affected projects only');\n console.log(' npm run arch:validate-complete # Complete validation (arch + circular)');\n console.log('');\n console.log(`${BOLD}📝 Available Nx targets:${RESET}`);\n console.log('');\n console.log(' Workspace-level architecture validation:');\n console.log(' nx run architecture:generate # Generate dependency graph');\n console.log(' nx run architecture:visualize # Visualize dependency graph');\n console.log(' nx run architecture:validate-no-architecture-cycles # Check for circular project dependencies');\n console.log(' nx run architecture:validate-architecture-unchanged # Validate against blessed graph');\n console.log('');\n console.log(' Per-project file import cycle checking:');\n console.log(' nx run <project>:validate-no-file-import-cycles # Check project for file import cycles');\n console.log(' nx affected --target=validate-no-file-import-cycles # Check all affected projects');\n console.log(' nx run-many --target=validate-no-file-import-cycles --all # Check all projects');\n console.log('');\n console.log(' Per-project CI target (lint + build + test):');\n console.log(' nx run <project>:ci # Run lint, build, test together');\n console.log(' nx run-many --target=ci --all # Run ci for all projects');\n console.log('');\n console.log(' Execution order (test waits for build via targetDefaults):');\n console.log(' ci (nx:noop)');\n console.log(' ├── lint ─────────────────┐');\n console.log(' ├── build ────────────────┼── run in parallel');\n console.log(' └── test ─────────────────┘');\n console.log(' └── depends on build (waits)');\n console.log('');\n console.log(`${GREEN}💡 Quick start:${RESET}`);\n console.log(` ${BOLD}npm run arch:generate${RESET} # Generate the graph first`);\n console.log(` ${BOLD}npm run arch:validate-complete${RESET} # Run complete validation`);\n console.log('');\n\n return { success: true };\n}\n"]}
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/executors/help/executor.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExecutorContext } from '@nx/devkit';\n\nexport interface HelpExecutorOptions {}\n\ntype HelpExecutorResult = { success: true };\n\nexport default async function helpExecutor(\n options: HelpExecutorOptions,\n context: ExecutorContext\n): Promise<HelpExecutorResult> {\n // ANSI color codes\n const GREEN = '\\x1b[32m\\x1b[1m';\n const BOLD = '\\x1b[1m';\n const RESET = '\\x1b[0m';\n\n console.log('');\n console.log(`${GREEN}💡 @webpieces/nx-webpieces-rules - Available Commands${RESET}`);\n console.log('');\n console.log(`${BOLD}📝 Available npm scripts (convenient shortcuts):${RESET}`);\n console.log('');\n console.log(' Architecture graph:');\n console.log(' npm run arch:generate # Explicitly refresh architecture/API/runtime facts');\n console.log(' npm run arch:visualize # View saved snapshot (does not refresh)');\n console.log(' npm run arch:visualize-runtime # View saved runtime snapshot (does not refresh)');\n console.log('');\n console.log(' Validation:');\n console.log(' npm run arch:validate # Quick validation (no-cycles)');\n console.log(' npm run arch:validate-all # Full arch validation (+ unchanged check)');\n console.log(' npm run arch:check-circular # Check all projects for circular deps');\n console.log(' npm run arch:check-circular-affected # Check affected projects only');\n console.log(' npm run arch:validate-complete # Complete validation (arch + circular)');\n console.log('');\n console.log(`${BOLD}📝 Available Nx targets:${RESET}`);\n console.log('');\n console.log(' Workspace-level architecture validation:');\n console.log(' nx run architecture:generate # Explicitly refresh architecture/API/runtime facts');\n console.log(' nx run architecture:visualize # View saved snapshot (does not refresh)');\n console.log(' nx run architecture:visualize-runtime # View saved runtime snapshot (does not refresh)');\n console.log(' nx run architecture:validate-no-architecture-cycles # Check for circular project dependencies');\n console.log(' nx run architecture:validate-architecture-unchanged # Validate against blessed graph');\n console.log('');\n console.log(' Per-project file import cycle checking:');\n console.log(' nx run <project>:validate-no-file-import-cycles # Check project for file import cycles');\n console.log(' nx affected --target=validate-no-file-import-cycles # Check all affected projects');\n console.log(' nx run-many --target=validate-no-file-import-cycles --all # Check all projects');\n console.log('');\n console.log(' Per-project CI target (lint + build + test):');\n console.log(' nx run <project>:ci # Run lint, build, test together');\n console.log(' nx run-many --target=ci --all # Run ci for all projects');\n console.log('');\n console.log(' Execution order (test waits for build via targetDefaults):');\n console.log(' ci (nx:noop)');\n console.log(' ├── lint ─────────────────┐');\n console.log(' ├── build ────────────────┼── run in parallel');\n console.log(' └── test ─────────────────┘');\n console.log(' └── depends on build (waits)');\n console.log('');\n console.log(`${GREEN}💡 Quick start:${RESET}`);\n console.log(` ${BOLD}npm run arch:generate${RESET} # Generate the graph first`);\n console.log(` ${BOLD}npm run arch:validate-complete${RESET} # Run complete validation`);\n console.log('');\n\n return { success: true };\n}\n"]}
@@ -24,6 +24,14 @@ export interface ExecutorResult {
24
24
  * fixing it is the same single command either way, so listing both adds noise rather than information.
25
25
  */
26
26
  export declare function describeTableDrift(current: CurrentArchitecture, saved: DependenciesFile): string | null;
27
+ /**
28
+ * Build the current dependency graph exactly as the generator does: reduce the nx
29
+ * graph, sort into levels, enrich with metadata, and attach the derived
30
+ * apiRelations — so this validator compares like-for-like against the committed file.
31
+ */
32
+ export declare class CurrentGraphBuilder {
33
+ build(workspaceRoot: string): Promise<CurrentArchitecture>;
34
+ }
27
35
  /** The regenerated graph plus the two tables beside it — everything dependencies.json holds. */
28
36
  export declare class CurrentArchitecture {
29
37
  readonly graph: EnhancedGraph;
@@ -9,7 +9,7 @@
9
9
  * nx run architecture:validate-architecture-unchanged
10
10
  */
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.CurrentArchitecture = void 0;
12
+ exports.CurrentArchitecture = exports.CurrentGraphBuilder = void 0;
13
13
  exports.describeTableDrift = describeTableDrift;
14
14
  exports.default = runExecutor;
15
15
  const rules_config_1 = require("@webpieces/rules-config");
@@ -112,23 +112,25 @@ function describeExternalSystemDrift(current, saved) {
112
112
  * graph, sort into levels, enrich with metadata, and attach the derived
113
113
  * apiRelations — so this validator compares like-for-like against the committed file.
114
114
  */
115
- // webpieces-disable no-function-outside-class -- executor step helper, matches reportMismatch/writeTmpInstructionsFile in this file
116
- async function buildCurrentGraph(workspaceRoot) {
117
- console.log('📊 Generating current dependency graph...');
118
- const reducedGraph = await (0, graph_generator_1.generateReducedGraph)();
119
- console.log('🔄 Computing topological layers...');
120
- const currentGraph = (0, graph_sorter_1.sortGraphTopologically)(reducedGraph);
121
- console.log('🏷️ Enriching graph with framework + responsibilities metadata...');
122
- const projectInfos = await (0, graph_metadata_1.collectProjectInfo)();
123
- (0, graph_metadata_1.enrichGraph)(currentGraph, projectInfos, workspaceRoot);
124
- new tag_truth_1.TagTruthCheck().assertTrue(currentGraph, projectInfos, workspaceRoot);
125
- console.log('🔎 Scanning source for implements/uses API relations...');
126
- // The SAME externalApiPaths the generator uses: scanning without them would drop every vendor
127
- // relation from the regenerated graph and report drift against a perfectly fresh file.
128
- const externalApiPaths = (0, runtime_config_1.loadRuntimeConfig)(workspaceRoot).externalApiPaths;
129
- const scan = (0, api_scanner_1.scanAndAttachApiRelations)(workspaceRoot, currentGraph, projectInfos, externalApiPaths);
130
- return new CurrentArchitecture(currentGraph, new api_contract_files_1.ApiContractFiles().refsFor((0, api_scanner_1.buildApiContracts)(scan)), (0, external_systems_1.buildExternalSystems)(scan.apiIndex, projectInfos));
115
+ class CurrentGraphBuilder {
116
+ async build(workspaceRoot) {
117
+ console.log('📊 Generating current dependency graph...');
118
+ const reducedGraph = await (0, graph_generator_1.generateReducedGraph)();
119
+ console.log('🔄 Computing topological layers...');
120
+ const currentGraph = (0, graph_sorter_1.sortGraphTopologically)(reducedGraph);
121
+ console.log('🏷️ Enriching graph with framework + responsibilities metadata...');
122
+ const projectInfos = await (0, graph_metadata_1.collectProjectInfo)();
123
+ (0, graph_metadata_1.enrichGraph)(currentGraph, projectInfos, workspaceRoot);
124
+ new tag_truth_1.TagTruthCheck().assertTrue(currentGraph, projectInfos, workspaceRoot);
125
+ console.log('🔎 Scanning source for implements/uses API relations...');
126
+ // The SAME externalApiPaths the generator uses: scanning without them would drop every vendor
127
+ // relation from the regenerated graph and report drift against a perfectly fresh file.
128
+ const externalApiPaths = (0, runtime_config_1.loadRuntimeConfig)(workspaceRoot).externalApiPaths;
129
+ const scan = (0, api_scanner_1.scanAndAttachApiRelations)(workspaceRoot, currentGraph, projectInfos, externalApiPaths);
130
+ return new CurrentArchitecture(currentGraph, new api_contract_files_1.ApiContractFiles().refsFor((0, api_scanner_1.buildApiContracts)(scan)), (0, external_systems_1.buildExternalSystems)(scan.apiIndex, projectInfos));
131
+ }
131
132
  }
133
+ exports.CurrentGraphBuilder = CurrentGraphBuilder;
132
134
  /** The regenerated graph plus the two tables beside it — everything dependencies.json holds. */
133
135
  class CurrentArchitecture {
134
136
  graph;
@@ -170,7 +172,7 @@ async function runExecutor(options, context) {
170
172
  }
171
173
  // Steps 1-3: build + enrich + scan the current graph (same pipeline the
172
174
  // generator runs, so any drift is caught).
173
- const currentGraph = await buildCurrentGraph(workspaceRoot);
175
+ const currentGraph = await new CurrentGraphBuilder().build(workspaceRoot);
174
176
  // Step 4: Load saved graph
175
177
  console.log('📂 Loading saved graph...');
176
178
  const savedGraph = (0, graph_loader_1.loadBlessedGraph)(workspaceRoot, graphPath);
@@ -1 +1 @@
1
- {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/executors/validate-architecture-unchanged/executor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Validate Architecture Unchanged Executor\n *\n * Validates that the current architecture graph matches the saved blessed graph.\n * This ensures no unapproved architecture changes have been made.\n *\n * Usage:\n * nx run architecture:validate-architecture-unchanged\n */\n\nimport type { ExecutorContext } from '@nx/devkit';\nimport { writeTemplate, RuleFailError, renderRuleFailForHuman } from '@webpieces/rules-config';\nimport { generateReducedGraph } from '../../lib/graph-generator';\nimport { sortGraphTopologically } from '../../lib/graph-sorter';\nimport { compareGraphs } from '../../lib/graph-comparator';\nimport { loadBlessedGraph, graphFileExists } from '../../lib/graph-loader';\nimport type { DependenciesFile } from '../../lib/graph-loader';\nimport { collectProjectInfo, enrichGraph, MetadataValidationError } from '../../lib/graph-metadata';\nimport { TagTruthCheck } from '../../lib/tag-truth';\nimport { scanAndAttachApiRelations, buildApiContracts } from '../../lib/api-usage/api-scanner';\nimport { buildExternalSystems } from '../../lib/api-usage/external-systems';\nimport type { ExternalSystemDecls } from '../../lib/api-usage/api-relations';\nimport { ApiContractFiles } from '../../lib/api-contract-files';\nimport type { ApiContractFileRefs } from '../../lib/api-contract-files';\nimport { loadRuntimeConfig } from '../../lib/runtime-config';\nimport { RuleGate } from '../../lib/rule-gate';\nimport type { EnhancedGraph } from '../../lib/graph-sorter';\nimport { toError } from '../../toError';\n\nexport interface ValidateArchitectureUnchangedOptions {\n graphPath?: string;\n}\n\nexport interface ExecutorResult {\n success: boolean;\n}\n\nconst TMP_MD_FILE = 'webpieces.dependencies.md';\n\n/**\n * Write the instructions documentation to .webpieces/instruct-ai/.\n * Sourced from @webpieces/rules-config.\n */\nfunction writeTmpInstructionsFile(workspaceRoot: string): string {\n const mdPath = writeTemplate(workspaceRoot, TMP_MD_FILE);\n\n return mdPath;\n}\n\n/**\n * Report a current-vs-saved graph mismatch and write the AI instructions file.\n */\nfunction reportMismatch(summary: string, workspaceRoot: string): void {\n const mdPath = writeTmpInstructionsFile(workspaceRoot);\n\n console.error('❌ Architecture has changed since last update!');\n console.error('\\nDifferences:');\n console.error(summary);\n console.error('');\n console.error('⚠️ *** Refer to ' + mdPath + ' for instructions on how to fix *** ⚠️');\n console.error('');\n console.error('To fix:');\n console.error(' 1. Review the changes above');\n console.error(' 2. If intentional, ASK USER to run: nx run architecture:generate since this is a critical change');\n console.error(' 3. Commit the updated architecture/dependencies.json');\n}\n\n/**\n * Which APIs dependencies.json links to a contract file, compared by LINK only — an added or removed\n * API. The endpoints inside `architecture/apis/<Api>.json` are deliberately NOT compared (#949): an\n * endpoint change must not fail this rule. Null when the links match.\n */\n// webpieces-disable no-function-outside-class -- executor step helper, matches reportMismatch in this file\nfunction describeContractLinkDrift(current: ApiContractFileRefs, saved: ApiContractFileRefs): string | null {\n const names = [...new Set([...Object.keys(current), ...Object.keys(saved)])].sort();\n const changes: string[] = [];\n for (const name of names) {\n const a = current[name];\n const b = saved[name];\n if (a === undefined) changes.push(` - ${name}: linked in dependencies.json but no longer in source`);\n else if (b === undefined) changes.push(` + ${name}: in source but not linked from dependencies.json`);\n else if (a !== b) changes.push(` ~ ${name}: contract file link changed (${b} -> ${a})`);\n }\n if (changes.length === 0) return null;\n return `apiContractFiles drift (${changes.length} api(s)):\\n${changes.join('\\n')}`;\n}\n\n/**\n * Drift in EITHER side table of dependencies.json — the api contract-file links or the\n * external-system declarations — or null when both match. The first difference found is reported;\n * fixing it is the same single command either way, so listing both adds noise rather than information.\n */\n// webpieces-disable no-function-outside-class -- executor step helper, matches describeContractLinkDrift above\nexport function describeTableDrift(current: CurrentArchitecture, saved: DependenciesFile): string | null {\n const linkDrift = describeContractLinkDrift(current.apiContractFiles, saved.apiContractFiles);\n if (linkDrift !== null) return linkDrift;\n return describeExternalSystemDrift(current.externalSystems, saved.externalSystems);\n}\n\n/**\n * The same drift report for the declared external systems, or null when they match. Named per\n * system so the message points at the database that changed rather than dumping two JSON blobs.\n */\n// webpieces-disable no-function-outside-class -- executor step helper, matches describeContractLinkDrift above\nfunction describeExternalSystemDrift(current: ExternalSystemDecls, saved: ExternalSystemDecls): string | null {\n const names = [...new Set([...Object.keys(current), ...Object.keys(saved)])].sort();\n const changes: string[] = [];\n for (const name of names) {\n const a = current[name];\n const b = saved[name];\n if (a === undefined) changes.push(` - ${name}: in dependencies.json but no longer declared in source`);\n else if (b === undefined) changes.push(` + ${name}: declared in source but missing from dependencies.json`);\n else if (JSON.stringify(a) !== JSON.stringify(b)) changes.push(` ~ ${name}: kind/label/declarers changed`);\n }\n if (changes.length === 0) return null;\n return `externalSystems drift (${changes.length} system(s)):\\n${changes.join('\\n')}`;\n}\n\n/**\n * Build the current dependency graph exactly as the generator does: reduce the nx\n * graph, sort into levels, enrich with metadata, and attach the derived\n * apiRelations — so this validator compares like-for-like against the committed file.\n */\n// webpieces-disable no-function-outside-class -- executor step helper, matches reportMismatch/writeTmpInstructionsFile in this file\nasync function buildCurrentGraph(workspaceRoot: string): Promise<CurrentArchitecture> {\n console.log('📊 Generating current dependency graph...');\n const reducedGraph = await generateReducedGraph();\n console.log('🔄 Computing topological layers...');\n const currentGraph = sortGraphTopologically(reducedGraph);\n console.log('🏷️ Enriching graph with framework + responsibilities metadata...');\n const projectInfos = await collectProjectInfo();\n enrichGraph(currentGraph, projectInfos, workspaceRoot);\n new TagTruthCheck().assertTrue(currentGraph, projectInfos, workspaceRoot);\n console.log('🔎 Scanning source for implements/uses API relations...');\n // The SAME externalApiPaths the generator uses: scanning without them would drop every vendor\n // relation from the regenerated graph and report drift against a perfectly fresh file.\n const externalApiPaths = loadRuntimeConfig(workspaceRoot).externalApiPaths;\n const scan = scanAndAttachApiRelations(workspaceRoot, currentGraph, projectInfos, externalApiPaths);\n return new CurrentArchitecture(\n currentGraph,\n new ApiContractFiles().refsFor(buildApiContracts(scan)),\n buildExternalSystems(scan.apiIndex, projectInfos),\n );\n}\n\n/** The regenerated graph plus the two tables beside it — everything dependencies.json holds. */\nexport class CurrentArchitecture {\n constructor(\n public readonly graph: EnhancedGraph,\n public readonly apiContractFiles: ApiContractFileRefs,\n public readonly externalSystems: ExternalSystemDecls,\n ) {}\n}\n\n/** The bootstrap path: there is nothing to diff against yet, so say how to create it. */\n// webpieces-disable no-function-outside-class -- executor step helper, matches reportMismatch in this file\nfunction reportMissingGraph(): void {\n console.error('❌ No saved graph found at architecture/dependencies.json');\n console.error('');\n console.error('To initialize:');\n console.error(' 1. Run: nx run architecture:generate');\n console.error(' 2. Run: nx run architecture:visualize');\n console.error(' 3. Manually inspect the generated graph to confirm it is the desired architecture');\n console.error(' 4. Commit architecture/dependencies.json');\n}\n\nexport default async function runExecutor(\n options: ValidateArchitectureUnchangedOptions,\n context: ExecutorContext\n): Promise<ExecutorResult> {\n const graphPath = options.graphPath;\n const workspaceRoot = context.root;\n\n // Epoch-gateable: this rule diffs against the blessed architecture/dependencies.json, so\n // \"grandfather the current drift until <epoch>\" is meaningful — hence honorEpoch = true.\n if (new RuleGate().isDisabled(workspaceRoot, 'validate-architecture-unchanged', true)) {\n return { success: true };\n }\n\n console.log('\\n🔍 Validating Architecture Unchanged\\n');\n\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n // Check if saved graph exists\n if (!graphFileExists(workspaceRoot, graphPath)) {\n reportMissingGraph();\n return { success: false };\n }\n\n // Steps 1-3: build + enrich + scan the current graph (same pipeline the\n // generator runs, so any drift is caught).\n const currentGraph = await buildCurrentGraph(workspaceRoot);\n\n // Step 4: Load saved graph\n console.log('📂 Loading saved graph...');\n const savedGraph = loadBlessedGraph(workspaceRoot, graphPath);\n\n if (!savedGraph) {\n console.error('❌ Could not load saved graph');\n return { success: false };\n }\n\n // Step 5: Compare graphs\n console.log('🔍 Comparing current graph to saved graph...');\n const comparison = compareGraphs(currentGraph.graph, savedGraph.projects);\n\n if (!comparison.identical) {\n reportMismatch(comparison.summary, workspaceRoot);\n return { success: false };\n }\n\n // Step 6: Compare the two side tables as well: which APIs are linked to a contract file, and\n // the external-system declarations. The endpoints inside architecture/apis/<Api>.json are\n // NOT compared — an endpoint change must never fail this rule (#949).\n const tableDrift = describeTableDrift(currentGraph, savedGraph);\n if (tableDrift !== null) {\n reportMismatch(tableDrift, workspaceRoot);\n return { success: false };\n }\n\n console.log('✅ Architecture unchanged - current graph matches saved graph');\n return { success: true };\n } catch (err: unknown) {\n const error = toError(err);\n // A RuleFailError (e.g. a dependencies.json still carrying the moved `apiContracts` key)\n // carries its cures in Option[]; render them rather than dropping them with `.message`.\n const rendered = error instanceof RuleFailError ? renderRuleFailForHuman(error) : error.message;\n console.error('❌ Architecture validation failed:', rendered);\n if (error instanceof MetadataValidationError) {\n const mdPath = writeTemplate(workspaceRoot, 'webpieces.responsibilities.md');\n console.error('');\n console.error('⚠️ *** Refer to ' + mdPath + ' for how to author responsibilities.md files *** ⚠️');\n }\n return { success: false };\n }\n}\n"]}
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/executors/validate-architecture-unchanged/executor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Validate Architecture Unchanged Executor\n *\n * Validates that the current architecture graph matches the saved blessed graph.\n * This ensures no unapproved architecture changes have been made.\n *\n * Usage:\n * nx run architecture:validate-architecture-unchanged\n */\n\nimport type { ExecutorContext } from '@nx/devkit';\nimport { writeTemplate, RuleFailError, renderRuleFailForHuman } from '@webpieces/rules-config';\nimport { generateReducedGraph } from '../../lib/graph-generator';\nimport { sortGraphTopologically } from '../../lib/graph-sorter';\nimport { compareGraphs } from '../../lib/graph-comparator';\nimport { loadBlessedGraph, graphFileExists } from '../../lib/graph-loader';\nimport type { DependenciesFile } from '../../lib/graph-loader';\nimport { collectProjectInfo, enrichGraph, MetadataValidationError } from '../../lib/graph-metadata';\nimport { TagTruthCheck } from '../../lib/tag-truth';\nimport { scanAndAttachApiRelations, buildApiContracts } from '../../lib/api-usage/api-scanner';\nimport { buildExternalSystems } from '../../lib/api-usage/external-systems';\nimport type { ExternalSystemDecls } from '../../lib/api-usage/api-relations';\nimport { ApiContractFiles } from '../../lib/api-contract-files';\nimport type { ApiContractFileRefs } from '../../lib/api-contract-files';\nimport { loadRuntimeConfig } from '../../lib/runtime-config';\nimport { RuleGate } from '../../lib/rule-gate';\nimport type { EnhancedGraph } from '../../lib/graph-sorter';\nimport { toError } from '../../toError';\n\nexport interface ValidateArchitectureUnchangedOptions {\n graphPath?: string;\n}\n\nexport interface ExecutorResult {\n success: boolean;\n}\n\nconst TMP_MD_FILE = 'webpieces.dependencies.md';\n\n/**\n * Write the instructions documentation to .webpieces/instruct-ai/.\n * Sourced from @webpieces/rules-config.\n */\nfunction writeTmpInstructionsFile(workspaceRoot: string): string {\n const mdPath = writeTemplate(workspaceRoot, TMP_MD_FILE);\n\n return mdPath;\n}\n\n/**\n * Report a current-vs-saved graph mismatch and write the AI instructions file.\n */\nfunction reportMismatch(summary: string, workspaceRoot: string): void {\n const mdPath = writeTmpInstructionsFile(workspaceRoot);\n\n console.error('❌ Architecture has changed since last update!');\n console.error('\\nDifferences:');\n console.error(summary);\n console.error('');\n console.error('⚠️ *** Refer to ' + mdPath + ' for instructions on how to fix *** ⚠️');\n console.error('');\n console.error('To fix:');\n console.error(' 1. Review the changes above');\n console.error(' 2. If intentional, ASK USER to run: nx run architecture:generate since this is a critical change');\n console.error(' 3. Commit the updated architecture/dependencies.json');\n}\n\n/**\n * Which APIs dependencies.json links to a contract file, compared by LINK only — an added or removed\n * API. The endpoints inside `architecture/apis/<Api>.json` are deliberately NOT compared (#949): an\n * endpoint change must not fail this rule. Null when the links match.\n */\n// webpieces-disable no-function-outside-class -- executor step helper, matches reportMismatch in this file\nfunction describeContractLinkDrift(\n current: ApiContractFileRefs,\n saved: ApiContractFileRefs,\n): string | null {\n const names = [...new Set([...Object.keys(current), ...Object.keys(saved)])].sort();\n const changes: string[] = [];\n for (const name of names) {\n const a = current[name];\n const b = saved[name];\n if (a === undefined)\n changes.push(` - ${name}: linked in dependencies.json but no longer in source`);\n else if (b === undefined)\n changes.push(` + ${name}: in source but not linked from dependencies.json`);\n else if (a !== b) changes.push(` ~ ${name}: contract file link changed (${b} -> ${a})`);\n }\n if (changes.length === 0) return null;\n return `apiContractFiles drift (${changes.length} api(s)):\\n${changes.join('\\n')}`;\n}\n\n/**\n * Drift in EITHER side table of dependencies.json — the api contract-file links or the\n * external-system declarations — or null when both match. The first difference found is reported;\n * fixing it is the same single command either way, so listing both adds noise rather than information.\n */\n// webpieces-disable no-function-outside-class -- executor step helper, matches describeContractLinkDrift above\nexport function describeTableDrift(current: CurrentArchitecture, saved: DependenciesFile): string | null {\n const linkDrift = describeContractLinkDrift(current.apiContractFiles, saved.apiContractFiles);\n if (linkDrift !== null) return linkDrift;\n return describeExternalSystemDrift(current.externalSystems, saved.externalSystems);\n}\n\n/**\n * The same drift report for the declared external systems, or null when they match. Named per\n * system so the message points at the database that changed rather than dumping two JSON blobs.\n */\n// webpieces-disable no-function-outside-class -- executor step helper, matches describeContractLinkDrift above\nfunction describeExternalSystemDrift(\n current: ExternalSystemDecls,\n saved: ExternalSystemDecls,\n): string | null {\n const names = [...new Set([...Object.keys(current), ...Object.keys(saved)])].sort();\n const changes: string[] = [];\n for (const name of names) {\n const a = current[name];\n const b = saved[name];\n if (a === undefined)\n changes.push(` - ${name}: in dependencies.json but no longer declared in source`);\n else if (b === undefined)\n changes.push(` + ${name}: declared in source but missing from dependencies.json`);\n else if (JSON.stringify(a) !== JSON.stringify(b))\n changes.push(` ~ ${name}: kind/label/declarers changed`);\n }\n if (changes.length === 0) return null;\n return `externalSystems drift (${changes.length} system(s)):\\n${changes.join('\\n')}`;\n}\n\n/**\n * Build the current dependency graph exactly as the generator does: reduce the nx\n * graph, sort into levels, enrich with metadata, and attach the derived\n * apiRelations — so this validator compares like-for-like against the committed file.\n */\nexport class CurrentGraphBuilder {\n async build(workspaceRoot: string): Promise<CurrentArchitecture> {\n console.log('📊 Generating current dependency graph...');\n const reducedGraph = await generateReducedGraph();\n console.log('🔄 Computing topological layers...');\n const currentGraph = sortGraphTopologically(reducedGraph);\n console.log('🏷️ Enriching graph with framework + responsibilities metadata...');\n const projectInfos = await collectProjectInfo();\n enrichGraph(currentGraph, projectInfos, workspaceRoot);\n new TagTruthCheck().assertTrue(currentGraph, projectInfos, workspaceRoot);\n console.log('🔎 Scanning source for implements/uses API relations...');\n // The SAME externalApiPaths the generator uses: scanning without them would drop every vendor\n // relation from the regenerated graph and report drift against a perfectly fresh file.\n const externalApiPaths = loadRuntimeConfig(workspaceRoot).externalApiPaths;\n const scan = scanAndAttachApiRelations(workspaceRoot, currentGraph, projectInfos, externalApiPaths);\n return new CurrentArchitecture(\n currentGraph,\n new ApiContractFiles().refsFor(buildApiContracts(scan)),\n buildExternalSystems(scan.apiIndex, projectInfos),\n );\n }\n}\n\n/** The regenerated graph plus the two tables beside it — everything dependencies.json holds. */\nexport class CurrentArchitecture {\n constructor(\n public readonly graph: EnhancedGraph,\n public readonly apiContractFiles: ApiContractFileRefs,\n public readonly externalSystems: ExternalSystemDecls,\n ) {}\n}\n\n/** The bootstrap path: there is nothing to diff against yet, so say how to create it. */\n// webpieces-disable no-function-outside-class -- executor step helper, matches reportMismatch in this file\nfunction reportMissingGraph(): void {\n console.error('❌ No saved graph found at architecture/dependencies.json');\n console.error('');\n console.error('To initialize:');\n console.error(' 1. Run: nx run architecture:generate');\n console.error(' 2. Run: nx run architecture:visualize');\n console.error(' 3. Manually inspect the generated graph to confirm it is the desired architecture');\n console.error(' 4. Commit architecture/dependencies.json');\n}\n\nexport default async function runExecutor(\n options: ValidateArchitectureUnchangedOptions,\n context: ExecutorContext\n): Promise<ExecutorResult> {\n const graphPath = options.graphPath;\n const workspaceRoot = context.root;\n\n // Epoch-gateable: this rule diffs against the blessed architecture/dependencies.json, so\n // \"grandfather the current drift until <epoch>\" is meaningful — hence honorEpoch = true.\n if (new RuleGate().isDisabled(workspaceRoot, 'validate-architecture-unchanged', true)) {\n return { success: true };\n }\n\n console.log('\\n🔍 Validating Architecture Unchanged\\n');\n\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n // Check if saved graph exists\n if (!graphFileExists(workspaceRoot, graphPath)) {\n reportMissingGraph();\n return { success: false };\n }\n\n // Steps 1-3: build + enrich + scan the current graph (same pipeline the\n // generator runs, so any drift is caught).\n const currentGraph = await new CurrentGraphBuilder().build(workspaceRoot);\n\n // Step 4: Load saved graph\n console.log('📂 Loading saved graph...');\n const savedGraph = loadBlessedGraph(workspaceRoot, graphPath);\n\n if (!savedGraph) {\n console.error('❌ Could not load saved graph');\n return { success: false };\n }\n\n // Step 5: Compare graphs\n console.log('🔍 Comparing current graph to saved graph...');\n const comparison = compareGraphs(currentGraph.graph, savedGraph.projects);\n\n if (!comparison.identical) {\n reportMismatch(comparison.summary, workspaceRoot);\n return { success: false };\n }\n\n // Step 6: Compare the two side tables as well: which APIs are linked to a contract file, and\n // the external-system declarations. The endpoints inside architecture/apis/<Api>.json are\n // NOT compared — an endpoint change must never fail this rule (#949).\n const tableDrift = describeTableDrift(currentGraph, savedGraph);\n if (tableDrift !== null) {\n reportMismatch(tableDrift, workspaceRoot);\n return { success: false };\n }\n\n console.log('✅ Architecture unchanged - current graph matches saved graph');\n return { success: true };\n } catch (err: unknown) {\n const error = toError(err);\n // A RuleFailError (e.g. a dependencies.json still carrying the moved `apiContracts` key)\n // carries its cures in Option[]; render them rather than dropping them with `.message`.\n const rendered = error instanceof RuleFailError ? renderRuleFailForHuman(error) : error.message;\n console.error('❌ Architecture validation failed:', rendered);\n if (error instanceof MetadataValidationError) {\n const mdPath = writeTemplate(workspaceRoot, 'webpieces.responsibilities.md');\n console.error('');\n console.error('⚠️ *** Refer to ' + mdPath + ' for how to author responsibilities.md files *** ⚠️');\n }\n return { success: false };\n }\n}\n"]}
@@ -1,12 +1,7 @@
1
1
  import type { ExecutorContext } from '@nx/devkit';
2
2
  import { ExecutorResult } from '../../executor-result';
3
- /**
4
- * The three DEBUG options (#1027). Every rule's mode and settings come from webpieces.config.json, never
5
- * from here; these only turn ONE run into a debug run of one rule:
6
- * nx run architecture:validate-code --rule=<name> [--mode=RUN_EVERY_TIME] [--projects=a,b]
7
- * All absent → the gate, at every committed mode.
8
- */
9
- export interface ValidateCodeOptions {
3
+ /** Runtime policy options come only from validated owner files. These flags request one ephemeral debug run. */
4
+ export declare class ValidateCodeOptions {
10
5
  rule?: string;
11
6
  mode?: string;
12
7
  projects?: string | string[];
@@ -1,8 +1,37 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ValidateCodeOptions = void 0;
3
4
  exports.default = runExecutor;
4
- const code_rules_1 = require("@webpieces/code-rules");
5
+ const rules_sdk_1 = require("@webpieces/rules-sdk");
6
+ const rules_config_1 = require("@webpieces/rules-config");
7
+ const rules_config_2 = require("@webpieces/rules-config");
8
+ const pack_build_runner_1 = require("../../pack-build-runner");
9
+ /** Runtime policy options come only from validated owner files. These flags request one ephemeral debug run. */
10
+ class ValidateCodeOptions {
11
+ rule;
12
+ mode;
13
+ projects;
14
+ }
15
+ exports.ValidateCodeOptions = ValidateCodeOptions;
16
+ // webpieces-disable no-function-outside-class -- Nx's required public executor entry point
5
17
  async function runExecutor(options, context) {
6
- return (0, code_rules_1.validateCode)(context.root, new code_rules_1.RunRequestParser().parse(options.rule, options.mode, options.projects));
18
+ const loaded = (0, rules_config_1.loadAndValidate)(context.root);
19
+ if (loaded.configPath === null)
20
+ throw new rules_config_2.RuleFailError('policy-configuration', 'Missing webpieces.config.json. Configure explicit rulePacks before running build policies.');
21
+ if (options.rule === undefined &&
22
+ options.mode === undefined &&
23
+ options.projects === undefined) {
24
+ return new pack_build_runner_1.PackBuildRunner().run(context.root, loaded);
25
+ }
26
+ if (options.rule === undefined)
27
+ throw new rules_config_2.RuleFailError('policy-configuration', '--mode and --projects require --rule=<name>: a debug run judges exactly one rule.');
28
+ const modules = new rules_config_1.RuleRuntimeModules();
29
+ const group = modules
30
+ .groups(loaded.ruleRegistry, 'build')
31
+ .find((entry) => entry.ruleIds.includes(options.rule));
32
+ if (!group)
33
+ throw new rules_config_2.RuleFailError('policy-configuration', `No declared build contribution for ${options.rule}. Use a rule from the generated policy catalog.`);
34
+ const exports = modules.load(group, loaded.ruleRegistry.manifestModules, new rules_config_1.NodeRuleRuntimeModuleLoader(context.root));
35
+ return modules.runBuildDebug(exports, new rules_sdk_1.BuildDebugRequest(context.root, new rules_sdk_1.PolicyDebugSelection(options.rule, options.mode, options.projects)));
7
36
  }
8
37
  //# sourceMappingURL=executor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/executors/validate-code/executor.ts"],"names":[],"mappings":";;AAgBA,8BAKC;AAnBD,sDAAuE;AAcxD,KAAK,UAAU,WAAW,CACrC,OAA4B,EAC5B,OAAwB;IAExB,OAAO,IAAA,yBAAY,EAAC,OAAO,CAAC,IAAI,EAAE,IAAI,6BAAgB,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;AAClH,CAAC","sourcesContent":["import type { ExecutorContext } from '@nx/devkit';\nimport { ExecutorResult } from '../../executor-result';\nimport { validateCode, RunRequestParser } from '@webpieces/code-rules';\n\n/**\n * The three DEBUG options (#1027). Every rule's mode and settings come from webpieces.config.json, never\n * from here; these only turn ONE run into a debug run of one rule:\n * nx run architecture:validate-code --rule=<name> [--mode=RUN_EVERY_TIME] [--projects=a,b]\n * All absent → the gate, at every committed mode.\n */\nexport interface ValidateCodeOptions {\n rule?: string;\n mode?: string;\n projects?: string | string[];\n}\n\nexport default async function runExecutor(\n options: ValidateCodeOptions,\n context: ExecutorContext,\n): Promise<ExecutorResult> {\n return validateCode(context.root, new RunRequestParser().parse(options.rule, options.mode, options.projects));\n}\n"]}
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/nx-webpieces-rules/src/executors/validate-code/executor.ts"],"names":[],"mappings":";;;AAoBA,8BA2CC;AA9DD,oDAA+E;AAC/E,0DAKiC;AACjC,0DAAwD;AACxD,+DAA0D;AAG1D,gHAAgH;AAChH,MAAa,mBAAmB;IAC5B,IAAI,CAAU;IACd,IAAI,CAAU;IACd,QAAQ,CAAqB;CAChC;AAJD,kDAIC;AAED,2FAA2F;AAC5E,KAAK,UAAU,WAAW,CACrC,OAA4B,EAC5B,OAAwB;IAExB,MAAM,MAAM,GAAG,IAAA,8BAAe,EAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,IAAI,MAAM,CAAC,UAAU,KAAK,IAAI;QAC1B,MAAM,IAAI,4BAAa,CACnB,sBAAsB,EACtB,4FAA4F,CAC/F,CAAC;IACN,IACI,OAAO,CAAC,IAAI,KAAK,SAAS;QAC1B,OAAO,CAAC,IAAI,KAAK,SAAS;QAC1B,OAAO,CAAC,QAAQ,KAAK,SAAS,EAChC,CAAC;QACC,OAAO,IAAI,mCAAe,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC3D,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS;QAC1B,MAAM,IAAI,4BAAa,CACnB,sBAAsB,EACtB,mFAAmF,CACtF,CAAC;IACN,MAAM,OAAO,GAAG,IAAI,iCAAkB,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,OAAO;SAChB,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,OAAO,CAAC;SACpC,IAAI,CAAC,CAAC,KAA+B,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAK,CAAC,CAAC,CAAC;IACtF,IAAI,CAAC,KAAK;QACN,MAAM,IAAI,4BAAa,CACnB,sBAAsB,EACtB,sCAAsC,OAAO,CAAC,IAAI,iDAAiD,CACtG,CAAC;IACN,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CACxB,KAAK,EACL,MAAM,CAAC,YAAY,CAAC,eAAe,EACnC,IAAI,0CAA2B,CAAC,OAAO,CAAC,IAAI,CAAC,CAChD,CAAC;IACF,OAAO,OAAO,CAAC,aAAa,CACxB,OAAO,EACP,IAAI,6BAAiB,CACjB,OAAO,CAAC,IAAI,EACZ,IAAI,gCAAoB,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CACzE,CACJ,CAAC;AACN,CAAC","sourcesContent":["import type { ExecutorContext } from '@nx/devkit';\nimport { BuildDebugRequest, PolicyDebugSelection } from '@webpieces/rules-sdk';\nimport {\n loadAndValidate,\n NodeRuleRuntimeModuleLoader,\n RuleRuntimeModules,\n RuntimeContributionGroup,\n} from '@webpieces/rules-config';\nimport { RuleFailError } from '@webpieces/rules-config';\nimport { PackBuildRunner } from '../../pack-build-runner';\nimport { ExecutorResult } from '../../executor-result';\n\n/** Runtime policy options come only from validated owner files. These flags request one ephemeral debug run. */\nexport class ValidateCodeOptions {\n rule?: string;\n mode?: string;\n projects?: string | string[];\n}\n\n// webpieces-disable no-function-outside-class -- Nx's required public executor entry point\nexport default async function runExecutor(\n options: ValidateCodeOptions,\n context: ExecutorContext,\n): Promise<ExecutorResult> {\n const loaded = loadAndValidate(context.root);\n if (loaded.configPath === null)\n throw new RuleFailError(\n 'policy-configuration',\n 'Missing webpieces.config.json. Configure explicit rulePacks before running build policies.',\n );\n if (\n options.rule === undefined &&\n options.mode === undefined &&\n options.projects === undefined\n ) {\n return new PackBuildRunner().run(context.root, loaded);\n }\n if (options.rule === undefined)\n throw new RuleFailError(\n 'policy-configuration',\n '--mode and --projects require --rule=<name>: a debug run judges exactly one rule.',\n );\n const modules = new RuleRuntimeModules();\n const group = modules\n .groups(loaded.ruleRegistry, 'build')\n .find((entry: RuntimeContributionGroup) => entry.ruleIds.includes(options.rule!));\n if (!group)\n throw new RuleFailError(\n 'policy-configuration',\n `No declared build contribution for ${options.rule}. Use a rule from the generated policy catalog.`,\n );\n const exports = modules.load(\n group,\n loaded.ruleRegistry.manifestModules,\n new NodeRuleRuntimeModuleLoader(context.root),\n );\n return modules.runBuildDebug(\n exports,\n new BuildDebugRequest(\n context.root,\n new PolicyDebugSelection(options.rule, options.mode, options.projects),\n ),\n );\n}\n"]}