@kb-labs/devkit 1.0.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 (295) hide show
  1. package/.cursorrules +32 -0
  2. package/.github/CODEOWNERS +2 -0
  3. package/.github/actions/setup-node-pnpm/action.yml +47 -0
  4. package/.github/workflow-templates/ci.yml +13 -0
  5. package/.github/workflow-templates/drift-check.yml +10 -0
  6. package/.github/workflow-templates/profiles-validate.yml +16 -0
  7. package/.github/workflow-templates/release.yml +8 -0
  8. package/.github/workflows/ci-reusable.yml +131 -0
  9. package/.github/workflows/drift-check-reusable.yml +23 -0
  10. package/.github/workflows/fixtures.yml +74 -0
  11. package/.github/workflows/profiles-validate-reusable.yml +67 -0
  12. package/.github/workflows/release-reusable.yml +50 -0
  13. package/.vscode/settings.json +23 -0
  14. package/AGENTS.md +130 -0
  15. package/LICENSE +21 -0
  16. package/README.md +1542 -0
  17. package/agents/devkit-maintainer/context.globs +15 -0
  18. package/agents/devkit-maintainer/permissions.yml +17 -0
  19. package/agents/devkit-maintainer/prompt.md +28 -0
  20. package/agents/devkit-maintainer/runbook.md +31 -0
  21. package/agents/docs-crafter/prompt.md +24 -0
  22. package/agents/docs-crafter/runbook.md +18 -0
  23. package/agents/release-manager/context.globs +7 -0
  24. package/agents/release-manager/prompt.md +27 -0
  25. package/agents/release-manager/runbook.md +17 -0
  26. package/agents/test-generator/context.globs +7 -0
  27. package/agents/test-generator/prompt.md +27 -0
  28. package/agents/test-generator/runbook.md +18 -0
  29. package/bin/devkit-architecture.mjs +1225 -0
  30. package/bin/devkit-build-order.mjs +500 -0
  31. package/bin/devkit-check-build-readiness.mjs +222 -0
  32. package/bin/devkit-check-commands.mjs +394 -0
  33. package/bin/devkit-check-configs.mjs +461 -0
  34. package/bin/devkit-check-deprecated.mjs +532 -0
  35. package/bin/devkit-check-duplicates.mjs +431 -0
  36. package/bin/devkit-check-exports.mjs +561 -0
  37. package/bin/devkit-check-imports.mjs +712 -0
  38. package/bin/devkit-check-paths.mjs +670 -0
  39. package/bin/devkit-check-scripts.mjs +335 -0
  40. package/bin/devkit-check-structure.mjs +495 -0
  41. package/bin/devkit-check-types.mjs +450 -0
  42. package/bin/devkit-ci.mjs +261 -0
  43. package/bin/devkit-core-gate.mjs +225 -0
  44. package/bin/devkit-fix-deps.mjs +1169 -0
  45. package/bin/devkit-freshness.mjs +199 -0
  46. package/bin/devkit-health.mjs +489 -0
  47. package/bin/devkit-migrate-configs.mjs +370 -0
  48. package/bin/devkit-paths.mjs +192 -0
  49. package/bin/devkit-stats.mjs +453 -0
  50. package/bin/devkit-sync.mjs +12 -0
  51. package/bin/devkit-tsup-external.mjs +148 -0
  52. package/bin/devkit-types-audit.mjs +615 -0
  53. package/bin/devkit-types-order.mjs +637 -0
  54. package/bin/devkit-validate-naming.mjs +203 -0
  55. package/bin/devkit-visualize.mjs +452 -0
  56. package/bin/kb-devkit-qa-history.mjs +453 -0
  57. package/bin/kb-devkit-qa.mjs +915 -0
  58. package/eslint/node.js +134 -0
  59. package/eslint/react.js +260 -0
  60. package/package.json +186 -0
  61. package/prettier/index.json +10 -0
  62. package/sync/index.mjs +693 -0
  63. package/templates/configs/README.md +306 -0
  64. package/templates/configs/eslint.config.js +27 -0
  65. package/templates/configs/package.json.bin +25 -0
  66. package/templates/configs/package.json.lib +30 -0
  67. package/templates/configs/tsconfig.build.json +15 -0
  68. package/templates/configs/tsconfig.json +9 -0
  69. package/templates/configs/tsup.config.bin.ts +34 -0
  70. package/templates/configs/tsup.config.cli.ts +41 -0
  71. package/templates/configs/tsup.config.dual.ts +46 -0
  72. package/templates/configs/tsup.config.ts +36 -0
  73. package/templates/package-json/README.md +290 -0
  74. package/templates/package-json/package.json.bin.template +40 -0
  75. package/templates/package-json/package.json.template +45 -0
  76. package/tsconfig/base.json +21 -0
  77. package/tsconfig/cli.json +12 -0
  78. package/tsconfig/dist/__tests__/cache.spec.d.ts +6 -0
  79. package/tsconfig/dist/__tests__/cache.spec.d.ts.map +1 -0
  80. package/tsconfig/dist/__tests__/cache.spec.js +85 -0
  81. package/tsconfig/dist/__tests__/cache.spec.js.map +1 -0
  82. package/tsconfig/dist/__tests__/fs-atomic.spec.d.ts +6 -0
  83. package/tsconfig/dist/__tests__/fs-atomic.spec.d.ts.map +1 -0
  84. package/tsconfig/dist/__tests__/fs-atomic.spec.js +153 -0
  85. package/tsconfig/dist/__tests__/fs-atomic.spec.js.map +1 -0
  86. package/tsconfig/dist/__tests__/init-workspace.spec.d.ts +6 -0
  87. package/tsconfig/dist/__tests__/init-workspace.spec.d.ts.map +1 -0
  88. package/tsconfig/dist/__tests__/init-workspace.spec.js +99 -0
  89. package/tsconfig/dist/__tests__/init-workspace.spec.js.map +1 -0
  90. package/tsconfig/dist/__tests__/kb-error.spec.d.ts +6 -0
  91. package/tsconfig/dist/__tests__/kb-error.spec.d.ts.map +1 -0
  92. package/tsconfig/dist/__tests__/kb-error.spec.js +190 -0
  93. package/tsconfig/dist/__tests__/kb-error.spec.js.map +1 -0
  94. package/tsconfig/dist/__tests__/preset-lockfile.spec.d.ts +6 -0
  95. package/tsconfig/dist/__tests__/preset-lockfile.spec.d.ts.map +1 -0
  96. package/tsconfig/dist/__tests__/preset-lockfile.spec.js +142 -0
  97. package/tsconfig/dist/__tests__/preset-lockfile.spec.js.map +1 -0
  98. package/tsconfig/dist/__tests__/product-config-profiles.spec.d.ts +6 -0
  99. package/tsconfig/dist/__tests__/product-config-profiles.spec.d.ts.map +1 -0
  100. package/tsconfig/dist/__tests__/product-config-profiles.spec.js +100 -0
  101. package/tsconfig/dist/__tests__/product-config-profiles.spec.js.map +1 -0
  102. package/tsconfig/dist/__tests__/product-config.spec.d.ts +6 -0
  103. package/tsconfig/dist/__tests__/product-config.spec.d.ts.map +1 -0
  104. package/tsconfig/dist/__tests__/product-config.spec.js +298 -0
  105. package/tsconfig/dist/__tests__/product-config.spec.js.map +1 -0
  106. package/tsconfig/dist/__tests__/runtime.spec.d.ts +2 -0
  107. package/tsconfig/dist/__tests__/runtime.spec.d.ts.map +1 -0
  108. package/tsconfig/dist/__tests__/runtime.spec.js +127 -0
  109. package/tsconfig/dist/__tests__/runtime.spec.js.map +1 -0
  110. package/tsconfig/dist/__tests__/upsert-lockfile.spec.d.ts +6 -0
  111. package/tsconfig/dist/__tests__/upsert-lockfile.spec.d.ts.map +1 -0
  112. package/tsconfig/dist/__tests__/upsert-lockfile.spec.js +251 -0
  113. package/tsconfig/dist/__tests__/upsert-lockfile.spec.js.map +1 -0
  114. package/tsconfig/dist/__tests__/validate-config.spec.d.ts +2 -0
  115. package/tsconfig/dist/__tests__/validate-config.spec.d.ts.map +1 -0
  116. package/tsconfig/dist/__tests__/validate-config.spec.js +14 -0
  117. package/tsconfig/dist/__tests__/validate-config.spec.js.map +1 -0
  118. package/tsconfig/dist/api/init-workspace.d.ts +10 -0
  119. package/tsconfig/dist/api/init-workspace.d.ts.map +1 -0
  120. package/tsconfig/dist/api/init-workspace.js +191 -0
  121. package/tsconfig/dist/api/init-workspace.js.map +1 -0
  122. package/tsconfig/dist/api/product-config.d.ts +21 -0
  123. package/tsconfig/dist/api/product-config.d.ts.map +1 -0
  124. package/tsconfig/dist/api/product-config.js +192 -0
  125. package/tsconfig/dist/api/product-config.js.map +1 -0
  126. package/tsconfig/dist/api/read-config.d.ts +22 -0
  127. package/tsconfig/dist/api/read-config.d.ts.map +1 -0
  128. package/tsconfig/dist/api/read-config.js +105 -0
  129. package/tsconfig/dist/api/read-config.js.map +1 -0
  130. package/tsconfig/dist/api/upsert-lockfile.d.ts +10 -0
  131. package/tsconfig/dist/api/upsert-lockfile.d.ts.map +1 -0
  132. package/tsconfig/dist/api/upsert-lockfile.js +63 -0
  133. package/tsconfig/dist/api/upsert-lockfile.js.map +1 -0
  134. package/tsconfig/dist/cache/fs-cache.d.ts +38 -0
  135. package/tsconfig/dist/cache/fs-cache.d.ts.map +1 -0
  136. package/tsconfig/dist/cache/fs-cache.js +142 -0
  137. package/tsconfig/dist/cache/fs-cache.js.map +1 -0
  138. package/tsconfig/dist/errors/kb-error.d.ts +32 -0
  139. package/tsconfig/dist/errors/kb-error.d.ts.map +1 -0
  140. package/tsconfig/dist/errors/kb-error.js +54 -0
  141. package/tsconfig/dist/errors/kb-error.js.map +1 -0
  142. package/tsconfig/dist/fs/__tests__/fs.spec.d.ts +2 -0
  143. package/tsconfig/dist/fs/__tests__/fs.spec.d.ts.map +1 -0
  144. package/tsconfig/dist/fs/__tests__/fs.spec.js +22 -0
  145. package/tsconfig/dist/fs/__tests__/fs.spec.js.map +1 -0
  146. package/tsconfig/dist/fs/fs.d.ts +6 -0
  147. package/tsconfig/dist/fs/fs.d.ts.map +1 -0
  148. package/tsconfig/dist/fs/fs.js +12 -0
  149. package/tsconfig/dist/fs/fs.js.map +1 -0
  150. package/tsconfig/dist/fs/index.d.ts +2 -0
  151. package/tsconfig/dist/fs/index.d.ts.map +1 -0
  152. package/tsconfig/dist/fs/index.js +2 -0
  153. package/tsconfig/dist/fs/index.js.map +1 -0
  154. package/tsconfig/dist/hash/config-hash.d.ts +17 -0
  155. package/tsconfig/dist/hash/config-hash.d.ts.map +1 -0
  156. package/tsconfig/dist/hash/config-hash.js +55 -0
  157. package/tsconfig/dist/hash/config-hash.js.map +1 -0
  158. package/tsconfig/dist/index.d.ts +5 -0
  159. package/tsconfig/dist/index.d.ts.map +1 -0
  160. package/tsconfig/dist/index.js +5 -0
  161. package/tsconfig/dist/index.js.map +1 -0
  162. package/tsconfig/dist/lockfile/lockfile.d.ts +54 -0
  163. package/tsconfig/dist/lockfile/lockfile.d.ts.map +1 -0
  164. package/tsconfig/dist/lockfile/lockfile.js +141 -0
  165. package/tsconfig/dist/lockfile/lockfile.js.map +1 -0
  166. package/tsconfig/dist/logging/__tests__/logger.spec.d.ts +2 -0
  167. package/tsconfig/dist/logging/__tests__/logger.spec.d.ts.map +1 -0
  168. package/tsconfig/dist/logging/__tests__/logger.spec.js +65 -0
  169. package/tsconfig/dist/logging/__tests__/logger.spec.js.map +1 -0
  170. package/tsconfig/dist/logging/__tests__/redaction.spec.d.ts +2 -0
  171. package/tsconfig/dist/logging/__tests__/redaction.spec.d.ts.map +1 -0
  172. package/tsconfig/dist/logging/__tests__/redaction.spec.js +34 -0
  173. package/tsconfig/dist/logging/__tests__/redaction.spec.js.map +1 -0
  174. package/tsconfig/dist/logging/__tests__/sinks-and-env.spec.d.ts +2 -0
  175. package/tsconfig/dist/logging/__tests__/sinks-and-env.spec.d.ts.map +1 -0
  176. package/tsconfig/dist/logging/__tests__/sinks-and-env.spec.js +90 -0
  177. package/tsconfig/dist/logging/__tests__/sinks-and-env.spec.js.map +1 -0
  178. package/tsconfig/dist/logging/index.d.ts +6 -0
  179. package/tsconfig/dist/logging/index.d.ts.map +1 -0
  180. package/tsconfig/dist/logging/index.js +6 -0
  181. package/tsconfig/dist/logging/index.js.map +1 -0
  182. package/tsconfig/dist/logging/logger.d.ts +9 -0
  183. package/tsconfig/dist/logging/logger.d.ts.map +1 -0
  184. package/tsconfig/dist/logging/logger.js +101 -0
  185. package/tsconfig/dist/logging/logger.js.map +1 -0
  186. package/tsconfig/dist/logging/redaction.d.ts +7 -0
  187. package/tsconfig/dist/logging/redaction.d.ts.map +1 -0
  188. package/tsconfig/dist/logging/redaction.js +23 -0
  189. package/tsconfig/dist/logging/redaction.js.map +1 -0
  190. package/tsconfig/dist/logging/sinks/json.d.ts +4 -0
  191. package/tsconfig/dist/logging/sinks/json.d.ts.map +1 -0
  192. package/tsconfig/dist/logging/sinks/json.js +23 -0
  193. package/tsconfig/dist/logging/sinks/json.js.map +1 -0
  194. package/tsconfig/dist/logging/sinks/stdout.d.ts +3 -0
  195. package/tsconfig/dist/logging/sinks/stdout.d.ts.map +1 -0
  196. package/tsconfig/dist/logging/sinks/stdout.js +24 -0
  197. package/tsconfig/dist/logging/sinks/stdout.js.map +1 -0
  198. package/tsconfig/dist/logging/types/index.d.ts +2 -0
  199. package/tsconfig/dist/logging/types/index.d.ts.map +1 -0
  200. package/tsconfig/dist/logging/types/index.js +2 -0
  201. package/tsconfig/dist/logging/types/index.js.map +1 -0
  202. package/tsconfig/dist/logging/types/types.d.ts +37 -0
  203. package/tsconfig/dist/logging/types/types.d.ts.map +1 -0
  204. package/tsconfig/dist/logging/types/types.js +2 -0
  205. package/tsconfig/dist/logging/types/types.js.map +1 -0
  206. package/tsconfig/dist/merge/layered-merge.d.ts +16 -0
  207. package/tsconfig/dist/merge/layered-merge.d.ts.map +1 -0
  208. package/tsconfig/dist/merge/layered-merge.js +97 -0
  209. package/tsconfig/dist/merge/layered-merge.js.map +1 -0
  210. package/tsconfig/dist/preset/resolve-preset.d.ts +29 -0
  211. package/tsconfig/dist/preset/resolve-preset.d.ts.map +1 -0
  212. package/tsconfig/dist/preset/resolve-preset.js +104 -0
  213. package/tsconfig/dist/preset/resolve-preset.js.map +1 -0
  214. package/tsconfig/dist/repo/__tests__/repo.spec.d.ts +2 -0
  215. package/tsconfig/dist/repo/__tests__/repo.spec.d.ts.map +1 -0
  216. package/tsconfig/dist/repo/__tests__/repo.spec.js +25 -0
  217. package/tsconfig/dist/repo/__tests__/repo.spec.js.map +1 -0
  218. package/tsconfig/dist/repo/index.d.ts +2 -0
  219. package/tsconfig/dist/repo/index.d.ts.map +1 -0
  220. package/tsconfig/dist/repo/index.js +2 -0
  221. package/tsconfig/dist/repo/index.js.map +1 -0
  222. package/tsconfig/dist/repo/repo.d.ts +6 -0
  223. package/tsconfig/dist/repo/repo.d.ts.map +1 -0
  224. package/tsconfig/dist/repo/repo.js +25 -0
  225. package/tsconfig/dist/repo/repo.js.map +1 -0
  226. package/tsconfig/dist/runtime/index.d.ts +2 -0
  227. package/tsconfig/dist/runtime/index.d.ts.map +1 -0
  228. package/tsconfig/dist/runtime/index.js +2 -0
  229. package/tsconfig/dist/runtime/index.js.map +1 -0
  230. package/tsconfig/dist/runtime/runtime.d.ts +46 -0
  231. package/tsconfig/dist/runtime/runtime.d.ts.map +1 -0
  232. package/tsconfig/dist/runtime/runtime.js +126 -0
  233. package/tsconfig/dist/runtime/runtime.js.map +1 -0
  234. package/tsconfig/dist/tsconfig.tools.tsbuildinfo +1 -0
  235. package/tsconfig/dist/tsconfig.tsbuildinfo +1 -0
  236. package/tsconfig/dist/types/index.d.ts +2 -0
  237. package/tsconfig/dist/types/index.d.ts.map +1 -0
  238. package/tsconfig/dist/types/index.js +2 -0
  239. package/tsconfig/dist/types/index.js.map +1 -0
  240. package/tsconfig/dist/types/init.d.ts +34 -0
  241. package/tsconfig/dist/types/init.d.ts.map +1 -0
  242. package/tsconfig/dist/types/init.js +6 -0
  243. package/tsconfig/dist/types/init.js.map +1 -0
  244. package/tsconfig/dist/types/preset.d.ts +27 -0
  245. package/tsconfig/dist/types/preset.d.ts.map +1 -0
  246. package/tsconfig/dist/types/preset.js +6 -0
  247. package/tsconfig/dist/types/preset.js.map +1 -0
  248. package/tsconfig/dist/types/types.d.ts +6 -0
  249. package/tsconfig/dist/types/types.d.ts.map +1 -0
  250. package/tsconfig/dist/types/types.js +2 -0
  251. package/tsconfig/dist/types/types.js.map +1 -0
  252. package/tsconfig/dist/utils/__tests__/env.spec.d.ts +2 -0
  253. package/tsconfig/dist/utils/__tests__/env.spec.d.ts.map +1 -0
  254. package/tsconfig/dist/utils/__tests__/env.spec.js +33 -0
  255. package/tsconfig/dist/utils/__tests__/env.spec.js.map +1 -0
  256. package/tsconfig/dist/utils/env.d.ts +7 -0
  257. package/tsconfig/dist/utils/env.d.ts.map +1 -0
  258. package/tsconfig/dist/utils/env.js +25 -0
  259. package/tsconfig/dist/utils/env.js.map +1 -0
  260. package/tsconfig/dist/utils/fs-atomic.d.ts +15 -0
  261. package/tsconfig/dist/utils/fs-atomic.d.ts.map +1 -0
  262. package/tsconfig/dist/utils/fs-atomic.js +45 -0
  263. package/tsconfig/dist/utils/fs-atomic.js.map +1 -0
  264. package/tsconfig/dist/utils/index.d.ts +3 -0
  265. package/tsconfig/dist/utils/index.d.ts.map +1 -0
  266. package/tsconfig/dist/utils/index.js +3 -0
  267. package/tsconfig/dist/utils/index.js.map +1 -0
  268. package/tsconfig/dist/utils/paths.d.ts +21 -0
  269. package/tsconfig/dist/utils/paths.d.ts.map +1 -0
  270. package/tsconfig/dist/utils/paths.js +32 -0
  271. package/tsconfig/dist/utils/paths.js.map +1 -0
  272. package/tsconfig/dist/utils/product-normalize.d.ts +27 -0
  273. package/tsconfig/dist/utils/product-normalize.d.ts.map +1 -0
  274. package/tsconfig/dist/utils/product-normalize.js +45 -0
  275. package/tsconfig/dist/utils/product-normalize.js.map +1 -0
  276. package/tsconfig/dist/validation/validate-config.d.ts +7 -0
  277. package/tsconfig/dist/validation/validate-config.d.ts.map +1 -0
  278. package/tsconfig/dist/validation/validate-config.js +22 -0
  279. package/tsconfig/dist/validation/validate-config.js.map +1 -0
  280. package/tsconfig/lib.json +13 -0
  281. package/tsconfig/node.json +12 -0
  282. package/tsconfig/react-app.json +8 -0
  283. package/tsconfig/react-lib.json +8 -0
  284. package/tsconfig/test.json +15 -0
  285. package/tsup/bin.js +172 -0
  286. package/tsup/dual.js +155 -0
  287. package/tsup/external-sync.mjs +41 -0
  288. package/tsup/external.mjs +109 -0
  289. package/tsup/node.js +65 -0
  290. package/tsup/react-lib.js +18 -0
  291. package/tsup/sdk.js +118 -0
  292. package/vite/react-app.js +50 -0
  293. package/vitest/node.js +37 -0
  294. package/vitest/react.js +39 -0
  295. package/vitest/vitest-setup.ts +9 -0
@@ -0,0 +1,461 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * kb-devkit-check-configs
5
+ *
6
+ * Checks all packages for configuration drift from standard templates.
7
+ * Ensures consistency across the entire monorepo.
8
+ *
9
+ * Features:
10
+ * - Detects missing or modified config files
11
+ * - Validates tsup.config.ts structure (nodePreset usage, dts: true, etc.)
12
+ * - Checks for duplicate external/ignores declarations
13
+ * - Auto-fix capability with backup
14
+ * - CI-friendly exit codes
15
+ *
16
+ * Usage:
17
+ * npx kb-devkit-check-configs # Check all packages
18
+ * npx kb-devkit-check-configs --fix # Auto-fix issues
19
+ * npx kb-devkit-check-configs --package=cli-core # Check specific package
20
+ * npx kb-devkit-check-configs --ci # CI mode (fail on drift)
21
+ */
22
+
23
+ import { promises as fs } from 'node:fs';
24
+ import { join, dirname, resolve } from 'node:path';
25
+ import { fileURLToPath } from 'node:url';
26
+ import process from 'node:process';
27
+ import { glob } from 'glob';
28
+ import { createHash } from 'node:crypto';
29
+
30
+ const __filename = fileURLToPath(import.meta.url);
31
+ const __dirname = dirname(__filename);
32
+ const DEVKIT_ROOT = resolve(__dirname, '..');
33
+ const TEMPLATES_DIR = resolve(DEVKIT_ROOT, 'templates/configs');
34
+
35
+ // ANSI colors
36
+ const colors = {
37
+ reset: '\x1b[0m',
38
+ bright: '\x1b[1m',
39
+ red: '\x1b[31m',
40
+ green: '\x1b[32m',
41
+ yellow: '\x1b[33m',
42
+ blue: '\x1b[34m',
43
+ cyan: '\x1b[36m',
44
+ gray: '\x1b[90m',
45
+ };
46
+
47
+ function color(c, text) {
48
+ return process.stdout.isTTY ? `${colors[c]}${text}${colors.reset}` : text;
49
+ }
50
+
51
+ async function exists(path) {
52
+ try {
53
+ await fs.access(path);
54
+ return true;
55
+ } catch {
56
+ return false;
57
+ }
58
+ }
59
+
60
+ async function sha256(content) {
61
+ return createHash('sha256').update(content).digest('hex');
62
+ }
63
+
64
+ async function readJson(path) {
65
+ return JSON.parse(await fs.readFile(path, 'utf8'));
66
+ }
67
+
68
+ async function findWorkspacePackages(root) {
69
+ const wsFile = join(root, 'pnpm-workspace.yaml');
70
+ if (!(await exists(wsFile))) {
71
+ return [];
72
+ }
73
+
74
+ const pkgJsonPaths = await glob('**/package.json', {
75
+ cwd: root,
76
+ ignore: ['**/node_modules/**', '**/dist/**', '**/coverage/**'],
77
+ absolute: true,
78
+ });
79
+
80
+ const packages = [];
81
+ for (const pkgPath of pkgJsonPaths) {
82
+ try {
83
+ const pkg = await readJson(pkgPath);
84
+ if (pkg.name && pkg.name.startsWith('@kb-labs/')) {
85
+ packages.push({
86
+ name: pkg.name,
87
+ path: dirname(pkgPath),
88
+ pkg,
89
+ });
90
+ }
91
+ } catch {}
92
+ }
93
+
94
+ return packages;
95
+ }
96
+
97
+ const CONFIG_FILES = {
98
+ 'tsup.config.ts': { required: true, template: 'tsup.config.ts' },
99
+ 'eslint.config.js': { required: true, template: 'eslint.config.js' },
100
+ 'tsconfig.json': { required: true, template: 'tsconfig.json' },
101
+ 'tsconfig.build.json': { required: true, template: 'tsconfig.build.json' },
102
+ };
103
+
104
+ async function checkPackageConfig(pkg, opts) {
105
+ const issues = [];
106
+ const warnings = [];
107
+
108
+ // Check all required config files
109
+ for (const [filename, meta] of Object.entries(CONFIG_FILES)) {
110
+ const filePath = join(pkg.path, filename);
111
+ const templatePath = join(TEMPLATES_DIR, meta.template);
112
+
113
+ if (!(await exists(filePath))) {
114
+ if (meta.required) {
115
+ issues.push({
116
+ type: 'missing',
117
+ file: filename,
118
+ severity: 'error',
119
+ message: `Missing required config file: ${filename}`,
120
+ });
121
+ }
122
+ continue;
123
+ }
124
+
125
+ const content = await fs.readFile(filePath, 'utf8');
126
+ const templateContent = await fs.readFile(templatePath, 'utf8');
127
+
128
+ // For tsup.config.ts and eslint.config.js, do structural checks
129
+ if (filename === 'tsup.config.ts') {
130
+ await checkTsupConfig(content, filePath, issues, warnings);
131
+ } else if (filename === 'eslint.config.js') {
132
+ await checkEslintConfig(content, filePath, issues, warnings);
133
+ } else {
134
+ // For tsconfig files, check if they match template exactly (ignoring comments/whitespace)
135
+ const contentClean = content.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '').trim();
136
+ const templateClean = templateContent.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '').trim();
137
+
138
+ if (contentClean !== templateClean) {
139
+ issues.push({
140
+ type: 'drift',
141
+ file: filename,
142
+ severity: 'error',
143
+ message: `Config file differs from standard template`,
144
+ });
145
+ }
146
+ }
147
+ }
148
+
149
+ return { issues, warnings };
150
+ }
151
+
152
+ async function checkTsupConfig(content, filePath, issues, warnings) {
153
+ // Check for any DevKit preset usage
154
+ const hasDevKitPreset =
155
+ content.includes('nodePreset') ||
156
+ content.includes('binPreset') ||
157
+ content.includes('reactPreset') ||
158
+ content.includes('reactLibPreset') ||
159
+ content.includes('reactAppPreset') ||
160
+ content.includes('sdkPreset') ||
161
+ content.includes('dualPreset') ||
162
+ content.includes("from '@kb-labs/devkit/tsup/"); // Generic DevKit import
163
+
164
+ if (!hasDevKitPreset) {
165
+ issues.push({
166
+ type: 'no-preset',
167
+ file: 'tsup.config.ts',
168
+ severity: 'error',
169
+ message: 'Not using any DevKit preset',
170
+ });
171
+ }
172
+
173
+ // Check for explicit dts: true
174
+ if (!content.includes('dts:')) {
175
+ warnings.push({
176
+ type: 'implicit-dts',
177
+ file: 'tsup.config.ts',
178
+ severity: 'warning',
179
+ message: 'Missing explicit dts: true',
180
+ });
181
+ }
182
+
183
+ // Check for dts: false (critical issue)
184
+ if (content.match(/dts:\s*false/)) {
185
+ issues.push({
186
+ type: 'dts-false',
187
+ file: 'tsup.config.ts',
188
+ severity: 'error',
189
+ message: 'Has dts: false - types not being generated!',
190
+ });
191
+ }
192
+
193
+ // Check for duplicate external declarations
194
+ const externalMatch = content.match(/external:\s*\[([^\]]+)\]/s);
195
+ if (externalMatch) {
196
+ const externalContent = externalMatch[1];
197
+ // Check if declaring @kb-labs packages (already in preset)
198
+ if (externalContent.includes('@kb-labs/')) {
199
+ warnings.push({
200
+ type: 'redundant-external',
201
+ file: 'tsup.config.ts',
202
+ severity: 'warning',
203
+ message: 'Declares @kb-labs/* packages in external (already in nodePreset)',
204
+ });
205
+ }
206
+ }
207
+
208
+ // Check for tsconfig: 'tsconfig.build.json'
209
+ if (!content.includes("tsconfig: 'tsconfig.build.json'") &&
210
+ !content.includes('tsconfig: "tsconfig.build.json"')) {
211
+ warnings.push({
212
+ type: 'wrong-tsconfig',
213
+ file: 'tsup.config.ts',
214
+ severity: 'warning',
215
+ message: 'Should use tsconfig: "tsconfig.build.json"',
216
+ });
217
+ }
218
+ }
219
+
220
+ async function checkEslintConfig(content, filePath, issues, warnings) {
221
+ // Check for any DevKit preset usage (nodePreset or reactPreset)
222
+ const hasDevKitPreset =
223
+ content.includes('nodePreset') ||
224
+ content.includes('reactPreset');
225
+
226
+ if (!hasDevKitPreset) {
227
+ issues.push({
228
+ type: 'no-preset',
229
+ file: 'eslint.config.js',
230
+ severity: 'error',
231
+ message: 'Not using any DevKit preset (nodePreset/reactPreset)',
232
+ });
233
+ }
234
+
235
+ // Check for duplicate ignores
236
+ const ignoresMatch = content.match(/ignores:\s*\[([^\]]+)\]/s);
237
+ if (ignoresMatch) {
238
+ const ignoresContent = ignoresMatch[1];
239
+ const redundantPatterns = [
240
+ '**/dist/**',
241
+ '**/coverage/**',
242
+ '**/node_modules/**',
243
+ '**/*.d.ts',
244
+ '**/scripts/**',
245
+ ];
246
+
247
+ for (const pattern of redundantPatterns) {
248
+ if (ignoresContent.includes(pattern)) {
249
+ warnings.push({
250
+ type: 'redundant-ignore',
251
+ file: 'eslint.config.js',
252
+ severity: 'warning',
253
+ message: `Redundant ignore pattern: ${pattern} (already in preset)`,
254
+ });
255
+ }
256
+ }
257
+ }
258
+ }
259
+
260
+ async function autoFix(pkg, issues, opts) {
261
+ const fixed = [];
262
+
263
+ for (const issue of issues) {
264
+ const filePath = join(pkg.path, issue.file);
265
+
266
+ if (issue.type === 'missing') {
267
+ // Copy template
268
+ const templatePath = join(TEMPLATES_DIR, CONFIG_FILES[issue.file].template);
269
+ await fs.copyFile(templatePath, filePath);
270
+ fixed.push({ issue, action: 'created from template' });
271
+ continue;
272
+ }
273
+
274
+ if (issue.type === 'dts-false') {
275
+ // Replace dts: false with dts: true
276
+ let content = await fs.readFile(filePath, 'utf8');
277
+
278
+ // Create backup
279
+ await fs.writeFile(`${filePath}.backup`, content);
280
+
281
+ content = content.replace(/dts:\s*false/, 'dts: true');
282
+ await fs.writeFile(filePath, content);
283
+ fixed.push({ issue, action: 'changed dts: false → dts: true' });
284
+ continue;
285
+ }
286
+
287
+ if (issue.type === 'drift' && (issue.file === 'tsconfig.json' || issue.file === 'tsconfig.build.json')) {
288
+ // Replace with template
289
+ const templatePath = join(TEMPLATES_DIR, CONFIG_FILES[issue.file].template);
290
+
291
+ // Create backup
292
+ const content = await fs.readFile(filePath, 'utf8');
293
+ await fs.writeFile(`${filePath}.backup`, content);
294
+
295
+ await fs.copyFile(templatePath, filePath);
296
+ fixed.push({ issue, action: 'replaced with template (backup created)' });
297
+ continue;
298
+ }
299
+ }
300
+
301
+ return fixed;
302
+ }
303
+
304
+ function parseArgs(argv) {
305
+ const flags = new Set();
306
+ const kv = new Map();
307
+
308
+ for (const arg of argv.slice(2)) {
309
+ if (arg.startsWith('--')) {
310
+ const [k, v] = arg.split('=', 2);
311
+ if (v === undefined) {
312
+ flags.add(k);
313
+ } else {
314
+ kv.set(k, v);
315
+ }
316
+ }
317
+ }
318
+
319
+ return {
320
+ help: flags.has('--help') || flags.has('-h'),
321
+ fix: flags.has('--fix'),
322
+ ci: flags.has('--ci'),
323
+ json: flags.has('--json'),
324
+ verbose: flags.has('--verbose'),
325
+ package: kv.get('--package'),
326
+ };
327
+ }
328
+
329
+ function printHelp() {
330
+ console.log(`
331
+ ${color('bright', 'kb-devkit-check-configs')}
332
+
333
+ Check configuration files for drift from standard templates.
334
+
335
+ ${color('blue', 'Usage:')}
336
+ npx kb-devkit-check-configs [options]
337
+
338
+ ${color('blue', 'Options:')}
339
+ --help, -h Show this help
340
+ --fix Auto-fix issues (creates backups)
341
+ --ci CI mode (fail with exit code 1 on drift)
342
+ --package=NAME Check specific package only
343
+ --json Output JSON format
344
+ --verbose Verbose output
345
+
346
+ ${color('blue', 'Examples:')}
347
+ npx kb-devkit-check-configs
348
+ npx kb-devkit-check-configs --fix
349
+ npx kb-devkit-check-configs --package=@kb-labs/core
350
+ npx kb-devkit-check-configs --ci
351
+
352
+ ${color('blue', 'Checked Files:')}
353
+ āœ“ tsup.config.ts - Build configuration
354
+ āœ“ eslint.config.js - Linting rules
355
+ āœ“ tsconfig.json - TypeScript IDE config
356
+ āœ“ tsconfig.build.json - TypeScript build config
357
+ `);
358
+ }
359
+
360
+ async function main() {
361
+ const opts = parseArgs(process.argv);
362
+
363
+ if (opts.help) {
364
+ printHelp();
365
+ process.exit(0);
366
+ }
367
+
368
+ console.log(color('bright', '\nšŸ” KB Labs Configuration Drift Checker\n'));
369
+
370
+ const cwd = process.cwd();
371
+ let packages = await findWorkspacePackages(cwd);
372
+
373
+ if (opts.package) {
374
+ packages = packages.filter(p => p.name === opts.package);
375
+ if (packages.length === 0) {
376
+ console.error(color('red', `āŒ Package ${opts.package} not found`));
377
+ process.exit(1);
378
+ }
379
+ }
380
+
381
+ console.log(color('gray', `Found ${packages.length} package(s) to check\n`));
382
+
383
+ const results = [];
384
+ let totalIssues = 0;
385
+ let totalWarnings = 0;
386
+ let totalFixed = 0;
387
+
388
+ for (const pkg of packages) {
389
+ const { issues, warnings } = await checkPackageConfig(pkg, opts);
390
+
391
+ if (issues.length > 0 || warnings.length > 0) {
392
+ results.push({ pkg, issues, warnings });
393
+ totalIssues += issues.length;
394
+ totalWarnings += warnings.length;
395
+ }
396
+
397
+ if (opts.fix && issues.length > 0) {
398
+ const fixed = await autoFix(pkg, issues, opts);
399
+ totalFixed += fixed.length;
400
+ }
401
+ }
402
+
403
+ // Print results
404
+ if (totalIssues > 0) {
405
+ console.log(color('red', `šŸ”“ Issues: ${totalIssues} package(s) with errors\n`));
406
+ for (const { pkg, issues } of results) {
407
+ if (issues.length === 0) {continue;}
408
+ console.log(color('yellow', ` ${pkg.name}`));
409
+ for (const issue of issues) {
410
+ console.log(color('gray', ` ${issue.file}`));
411
+ console.log(color('red', ` └─ ${issue.message}`));
412
+ }
413
+ console.log();
414
+ }
415
+ }
416
+
417
+ if (totalWarnings > 0) {
418
+ console.log(color('yellow', `āš ļø Warnings: ${totalWarnings} non-critical issues\n`));
419
+ if (opts.verbose) {
420
+ for (const { pkg, warnings } of results) {
421
+ if (warnings.length === 0) {continue;}
422
+ console.log(color('yellow', ` ${pkg.name}`));
423
+ for (const warning of warnings) {
424
+ console.log(color('gray', ` ${warning.file}`));
425
+ console.log(color('yellow', ` └─ ${warning.message}`));
426
+ }
427
+ console.log();
428
+ }
429
+ }
430
+ }
431
+
432
+ if (opts.fix && totalFixed > 0) {
433
+ console.log(color('green', `āœ… Auto-fixed ${totalFixed} issue(s)`));
434
+ console.log(color('gray', ' Backups created with .backup extension\n'));
435
+ }
436
+
437
+ if (totalIssues === 0 && totalWarnings === 0) {
438
+ console.log(color('green', 'āœ… All configurations are up to date!\n'));
439
+ } else if (!opts.fix) {
440
+ console.log(color('cyan', '\nšŸ’” Run with --fix to automatically fix issues\n'));
441
+ }
442
+
443
+ // Exit code
444
+ if (opts.ci && totalIssues > 0) {
445
+ process.exit(1);
446
+ }
447
+
448
+ if (totalIssues > 0 && !opts.fix) {
449
+ process.exit(1);
450
+ }
451
+
452
+ process.exit(0);
453
+ }
454
+
455
+ main().catch(err => {
456
+ console.error(color('red', '\nāŒ Error:'), err.message);
457
+ if (process.env.DEBUG) {
458
+ console.error(err.stack);
459
+ }
460
+ process.exit(1);
461
+ });