@akanjs/cli 3.0.0-alpha.6 → 3.0.0-alpha.61

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 (111) hide show
  1. package/.build-stamp +1 -1
  2. package/README.ko.md +1 -1
  3. package/README.md +1 -1
  4. package/{abstractCompactor-e5yq60qz.js → abstractCompactor-20e0cwbs.js} +2 -2
  5. package/{agent.command-b0fcx3r2.js → agent.command-tsx1nsdj.js} +9 -7
  6. package/{application.command-cezdnvtq.js → application.command-n8ex8g9h.js} +8 -6
  7. package/{applicationBuildRunner-ha3y8ew8.js → applicationBuildRunner-x8h12rp0.js} +7 -7
  8. package/{applicationReleasePackager-gg8ccbeh.js → applicationReleasePackager-93nzdfsy.js} +1 -1
  9. package/buildBatch.proc.js +7 -5
  10. package/{capacitorApp-jaksw4cy.js → capacitorApp-8mv9e537.js} +29 -27
  11. package/{cloud.command-6xvsd487.js → cloud.command-f0rhw014.js} +12 -10
  12. package/{context.command-ajn1b683.js → context.command-s7a41qjs.js} +17 -15
  13. package/{dependencyScanner-f6grrep3.js → dependencyScanner-rbs2407b.js} +1 -1
  14. package/getDirname-ka11hm7e.js +8 -0
  15. package/{guideline.command-9ew6aqhm.js → guideline.command-qrw84ttb.js} +8 -6
  16. package/guidelines/agentRule/agentRule.generate.json +31 -0
  17. package/guidelines/agentRule/agentRule.instruction.md +525 -0
  18. package/guidelines/conventions/conventions.generate.json +25 -0
  19. package/guidelines/conventions/conventions.instruction.md +821 -0
  20. package/guidelines/cssRule/cssRule.instruction.md +7 -0
  21. package/guidelines/framework/framework.instruction.md +1 -0
  22. package/guidelines/mcpRule/mcpRule.generate.json +25 -0
  23. package/guidelines/mcpRule/mcpRule.instruction.md +176 -0
  24. package/guidelines/workspaceOnboarding/workspaceOnboarding.generate.json +24 -0
  25. package/guidelines/workspaceOnboarding/workspaceOnboarding.instruction.md +638 -0
  26. package/incrementalBuilder.proc.js +8 -6
  27. package/{index-zr2wvx69.js → index-0g9ajdz8.js} +6 -6
  28. package/index-1577bej2.js +7 -0
  29. package/{index-wrrb8rxk.js → index-4mtyaqj2.js} +4 -4
  30. package/{index-bjpxzr6s.js → index-5vy2jzar.js} +1 -1
  31. package/{index-47qxw1tz.js → index-681sx6nt.js} +176 -66
  32. package/{index-zbx0jheb.js → index-8md8zszv.js} +14 -13
  33. package/{index-pfrt7qwh.js → index-cc1mgv1f.js} +4 -4
  34. package/{index-hk9rbcsz.js → index-ce9755av.js} +1 -1
  35. package/{index-jkynkyfk.js → index-ckpwq052.js} +5 -3
  36. package/{index-c94nq3c1.js → index-dvg362vq.js} +3 -3
  37. package/{index-vkqxw0ek.js → index-ek4mkwxp.js} +13 -13
  38. package/{index-exhpp31y.js → index-f0t3wjyr.js} +15 -7
  39. package/index-f39512t6.js +255 -0
  40. package/{index-m4kpmmtj.js → index-g44fykfw.js} +1 -1
  41. package/{index-nfxq39kj.js → index-h0mnt0b0.js} +37 -6
  42. package/{index-qp089jp0.js → index-j37qq1f2.js} +1 -1
  43. package/{index-hrwzz2wf.js → index-kkya2ped.js} +1 -1
  44. package/{index-j9cxndc0.js → index-qnv0aqmm.js} +9 -6
  45. package/{index-r7nqv8qj.js → index-r8z20vnj.js} +14 -14
  46. package/{index-6npsfpxr.js → index-ryns915y.js} +3 -3
  47. package/{index-0cj2zxbm.js → index-sh01r3pm.js} +1 -1
  48. package/{index-60a3jfcz.js → index-tn46rr6w.js} +8 -8
  49. package/{index-jn9vfpwz.js → index-wc19q8mb.js} +54 -15
  50. package/{index-meh7mmz9.js → index-x1dbhd80.js} +8 -4
  51. package/{index-qb61h0k7.js → index-xj5b8c0w.js} +193 -565
  52. package/index.js +21 -19
  53. package/{library.command-aa1g8nsa.js → library.command-p3jgf5h2.js} +6 -4
  54. package/{localRegistry.command-jha3sn50.js → localRegistry.command-bms0qn6t.js} +11 -9
  55. package/{module.command-b1zzgqde.js → module.command-hb3xm07r.js} +10 -8
  56. package/{package.command-9qv6vr9s.js → package.command-fbpa6r4w.js} +6 -4
  57. package/package.json +3 -4
  58. package/{page.command-k16pw244.js → page.command-92vrmw96.js} +6 -4
  59. package/{primitive.command-s60dn1ae.js → primitive.command-k6b9jfxr.js} +11 -9
  60. package/{quality.command-p3vaze52.js → quality.command-89vwmjvf.js} +194 -112
  61. package/{recipeScanner-tghkzrrt.js → recipeScanner-zrzev25x.js} +3 -3
  62. package/{repair.command-mfv749ha.js → repair.command-nh9jn8rh.js} +8 -6
  63. package/{routeSourceValidator-cncd92fv.js → routeSourceValidator-7fycdqyv.js} +3 -39
  64. package/{scalar.command-hs3nwzv1.js → scalar.command-zcsjgvax.js} +9 -7
  65. package/templates/app/env/env.server.debug.ts.template +1 -5
  66. package/templates/app/env/env.server.develop.ts.template +1 -5
  67. package/templates/app/env/env.server.local.ts.template +1 -5
  68. package/templates/app/env/env.server.main.ts.template +1 -5
  69. package/templates/app/page/styles.css.template +3 -3
  70. package/templates/appSample/srvkit/AuthGuard.ts +9 -5
  71. package/templates/appSample/srvkit/SessionInternalArg.ts +4 -3
  72. package/templates/crudPages/[__model__Id]/edit/page.tsx +1 -1
  73. package/templates/crudPages/new/page.tsx +1 -1
  74. package/templates/crudSinglePage/page.tsx +1 -1
  75. package/templates/env/_env.server.type.ts +7 -5
  76. package/templates/lib/db.ts +1 -1
  77. package/templates/lib/dict.ts +1 -1
  78. package/templates/lib/sig.ts +1 -1
  79. package/templates/lib/srv.ts +6 -2
  80. package/templates/module/__Model__.Util.tsx +1 -1
  81. package/templates/module/__Model__.Zone.tsx +3 -5
  82. package/templates/workspaceRoot/AGENTS.md.template +0 -971
  83. package/templates/workspaceRoot/CLAUDE.md.template +19 -0
  84. package/templates/workspaceRoot/biome.json.template +4 -239
  85. package/templates/workspaceRoot/docs/AI-DEVELOPMENT.md.template +10 -14
  86. package/templates/workspaceRoot/docs/GENERATED.md.template +12 -10
  87. package/{typeChecker-kravn7ns.js → typeChecker-g6bh0xfv.js} +1 -1
  88. package/typecheck.proc.js +1 -1
  89. package/{workflow.command-z0e0fk0z.js → workflow.command-jj0cphfm.js} +16 -14
  90. package/{workspace.command-3ydyy991.js → workspace.command-ma3g994j.js} +71 -52
  91. package/templates/workspaceRoot/.cursor/rules/akan-page-routing.mdc.template +0 -43
  92. package/templates/workspaceRoot/.cursor/rules/akan-sync-conventions.mdc.template +0 -34
  93. package/templates/workspaceRoot/.cursor/rules/application-test-commands.mdc.template +0 -16
  94. package/templates/workspaceRoot/.cursor/rules/change-scope.mdc.template +0 -12
  95. package/templates/workspaceRoot/.cursor/rules/client-server-boundaries.mdc.template +0 -18
  96. package/templates/workspaceRoot/.cursor/rules/coding-comments.mdc.template +0 -25
  97. package/templates/workspaceRoot/.cursor/rules/coding-style.mdc.template +0 -44
  98. package/templates/workspaceRoot/.cursor/rules/domain-module-conventions.mdc.template +0 -17
  99. package/templates/workspaceRoot/.cursor/rules/format-lint.mdc.template +0 -12
  100. package/templates/workspaceRoot/.cursor/rules/lint-enforced-rules.mdc.template +0 -18
  101. package/templates/workspaceRoot/.cursor/rules/module-file-playbook.mdc.template +0 -61
  102. package/templates/workspaceRoot/.cursor/rules/naming-conventions.mdc.template +0 -15
  103. package/templates/workspaceRoot/.cursor/rules/react-component-style.mdc.template +0 -21
  104. package/templates/workspaceRoot/.cursor/rules/repo-overview.mdc.template +0 -17
  105. package/templates/workspaceRoot/.cursor/rules/scalar-modeling.mdc.template +0 -58
  106. package/templates/workspaceRoot/.cursor/rules/secrets-and-env.mdc.template +0 -13
  107. package/templates/workspaceRoot/.cursor/rules/service-signal-conventions.mdc.template +0 -83
  108. package/templates/workspaceRoot/.cursor/rules/srvkit-adapters-and-guards.mdc.template +0 -50
  109. package/templates/workspaceRoot/.cursor/rules/ssr-first.mdc.template +0 -59
  110. package/templates/workspaceRoot/.cursor/rules/typescript-imports.mdc.template +0 -16
  111. /package/{index-r24hmh0q.js → index-yb2wsc7f.js} +0 -0
@@ -1,27 +1,27 @@
1
1
  // @bun
2
+ import {
3
+ LibraryScript
4
+ } from "./index-f0t3wjyr.js";
2
5
  import {
3
6
  resolveMobileTargets
4
7
  } from "./index-76rn3g2c.js";
5
- import {
6
- LibraryScript
7
- } from "./index-exhpp31y.js";
8
8
  import {
9
9
  runner,
10
10
  script
11
- } from "./index-jkynkyfk.js";
11
+ } from "./index-ckpwq052.js";
12
12
  import {
13
13
  HmrWatcher,
14
14
  WatchRootResolver
15
- } from "./index-bjpxzr6s.js";
15
+ } from "./index-5vy2jzar.js";
16
16
  import {
17
17
  AppExecutor,
18
18
  LibExecutor,
19
19
  PkgExecutor,
20
20
  WorkspaceExecutor
21
- } from "./index-47qxw1tz.js";
21
+ } from "./index-681sx6nt.js";
22
22
  import {
23
23
  __require
24
- } from "./index-r24hmh0q.js";
24
+ } from "./index-yb2wsc7f.js";
25
25
 
26
26
  // pkgs/@akanjs/devkit/applicationBuildReporter.ts
27
27
  import { Logger } from "akanjs/common";
@@ -350,7 +350,7 @@ class IncrementalBuilderHost {
350
350
  return false;
351
351
  this.#recycleRequested = true;
352
352
  this.#status = "recycling";
353
- this.logger.info(`recycling builder pid=${proc.pid} (${reason})`);
353
+ this.logger.debug(`recycling builder pid=${proc.pid} (${reason})`);
354
354
  this.#recycleTimer = setTimeout(() => {
355
355
  this.#recycleTimer = null;
356
356
  if (this.#proc !== proc)
@@ -1898,10 +1898,10 @@ function openBrowser(url) {
1898
1898
  }
1899
1899
 
1900
1900
  // pkgs/@akanjs/cli/application/application.runner.ts
1901
- var loadBuildRunner = async () => (await import("./applicationBuildRunner-ha3y8ew8.js")).ApplicationBuildRunner;
1902
- var loadReleasePackager = async () => (await import("./applicationReleasePackager-gg8ccbeh.js")).ApplicationReleasePackager;
1903
- var loadCapacitorApp = async () => (await import("./capacitorApp-jaksw4cy.js")).CapacitorApp;
1904
- var loadAbstractCompactor = async () => (await import("./abstractCompactor-e5yq60qz.js")).AbstractCompactor;
1901
+ var loadBuildRunner = async () => (await import("./applicationBuildRunner-x8h12rp0.js")).ApplicationBuildRunner;
1902
+ var loadReleasePackager = async () => (await import("./applicationReleasePackager-93nzdfsy.js")).ApplicationReleasePackager;
1903
+ var loadCapacitorApp = async () => (await import("./capacitorApp-8mv9e537.js")).CapacitorApp;
1904
+ var loadAbstractCompactor = async () => (await import("./abstractCompactor-20e0cwbs.js")).AbstractCompactor;
1905
1905
  var loadPrompts = async () => await import("@inquirer/prompts");
1906
1906
 
1907
1907
  class ApplicationRunner extends runner("application") {
@@ -2528,7 +2528,7 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
2528
2528
  let stopping = false;
2529
2529
  process.on("SIGINT", () => {
2530
2530
  if (stopping) {
2531
- Logger5.rawLog("Abandoning the local database teardown; containers are left running.", undefined, "warn");
2531
+ Logger5.rawLog("Abandoning the local database teardown; containers are left running.", undefined, "error");
2532
2532
  process.exit(130);
2533
2533
  }
2534
2534
  stopping = true;
@@ -2542,7 +2542,7 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
2542
2542
  }), timeout]);
2543
2543
  if (result !== "timeout")
2544
2544
  return;
2545
- Logger5.rawLog(`Local database did not stop within ${ApplicationScript.dbShutdownTimeoutMs}ms; run \`akan dbdown\` once Docker responds.`, undefined, "warn");
2545
+ Logger5.rawLog(`Local database did not stop within ${ApplicationScript.dbShutdownTimeoutMs}ms; run \`akan dbdown\` once Docker responds.`, undefined, "error");
2546
2546
  }
2547
2547
  async testSys(sys) {
2548
2548
  if (sys.type === "app")
@@ -1,17 +1,17 @@
1
1
  // @bun
2
2
  import {
3
3
  AkanContextAnalyzer
4
- } from "./index-jn9vfpwz.js";
4
+ } from "./index-wc19q8mb.js";
5
5
  import {
6
6
  createRepairReport,
7
7
  generatedFilePathsForTarget,
8
8
  renderRepairReport,
9
9
  writeGeneratedSyncState,
10
10
  writeWorkflowRunArtifact
11
- } from "./index-m4kpmmtj.js";
11
+ } from "./index-g44fykfw.js";
12
12
  import {
13
13
  runner
14
- } from "./index-jkynkyfk.js";
14
+ } from "./index-ckpwq052.js";
15
15
 
16
16
  // pkgs/@akanjs/cli/repair/repair.runner.ts
17
17
  var commandForShell = (command) => command.startsWith("akan ") ? `bun run ${command}` : command;
@@ -240,7 +240,7 @@ import { ChatOpenAI } from "@langchain/openai";
240
240
  import { Logger } from "akanjs/common";
241
241
  import chalk from "chalk";
242
242
  var MAX_ASK_TRY = 300;
243
- var deepSeekLlmModels = ["deepseek-chat", "deepseek-reasoner"];
243
+ var deepSeekLlmModels = ["deepseek-v4-flash", "deepseek-v4-pro"];
244
244
  var openAiLlmModels = ["gpt-5.5"];
245
245
  var supportedLlmModels = [...deepSeekLlmModels, ...openAiLlmModels];
246
246
  var isOpenAiLlmModel = (model) => openAiLlmModels.includes(model);
@@ -1,13 +1,13 @@
1
1
  // @bun
2
- import {
3
- PageScript
4
- } from "./index-hrwzz2wf.js";
5
2
  import {
6
3
  pluralizeName
7
4
  } from "./index-ss469dec.js";
5
+ import {
6
+ PageScript
7
+ } from "./index-kkya2ped.js";
8
8
  import {
9
9
  AiSession
10
- } from "./index-0cj2zxbm.js";
10
+ } from "./index-sh01r3pm.js";
11
11
  import {
12
12
  bilingualDescriptionForField,
13
13
  bilingualLabelForField,
@@ -15,17 +15,17 @@ import {
15
15
  generatedFilesForSync,
16
16
  moduleSourcePaths,
17
17
  sourceFile
18
- } from "./index-m4kpmmtj.js";
18
+ } from "./index-g44fykfw.js";
19
19
  import {
20
20
  Prompter
21
- } from "./index-qp089jp0.js";
21
+ } from "./index-j37qq1f2.js";
22
22
  import {
23
23
  runner,
24
24
  script
25
- } from "./index-jkynkyfk.js";
25
+ } from "./index-ckpwq052.js";
26
26
  import {
27
27
  ModuleExecutor
28
- } from "./index-47qxw1tz.js";
28
+ } from "./index-681sx6nt.js";
29
29
  import {
30
30
  FileSys
31
31
  } from "./index-67546d0j.js";
@@ -2,14 +2,16 @@
2
2
  import {
3
3
  workflowRunArtifactPath,
4
4
  workflowSyncDir
5
- } from "./index-m4kpmmtj.js";
5
+ } from "./index-g44fykfw.js";
6
6
  import {
7
7
  AppExecutor,
8
8
  LibExecutor,
9
- appRootAllowedDirs,
10
- appRootAllowedFiles,
11
- isScannedAppRootEntry
12
- } from "./index-47qxw1tz.js";
9
+ extractBlockVersion,
10
+ isScannedRootEntry,
11
+ readDevkitVersion,
12
+ rootAllowedDirs,
13
+ rootAllowedFiles
14
+ } from "./index-681sx6nt.js";
13
15
  import {
14
16
  collectRecipeSources,
15
17
  findInlineRecipeDuplicates,
@@ -124,7 +126,9 @@ var validationCommands = [
124
126
  "akan typecheck <app-name>",
125
127
  "akan test <app-or-lib-or-pkg>",
126
128
  "akan build <app-name>",
127
- "akan doctor --strict --format json"
129
+ "akan doctor --strict --format json",
130
+ "akan quality scan [--format json]",
131
+ "akan quality ssr [--format json]"
128
132
  ];
129
133
  var unknownGeneratedFilesFreshness = {
130
134
  status: "unknown",
@@ -365,6 +369,29 @@ class AkanContextAnalyzer {
365
369
  validationCommands
366
370
  };
367
371
  }
372
+ static async#agentGuideDrift(workspace) {
373
+ const installed = await readDevkitVersion();
374
+ if (!installed)
375
+ return null;
376
+ const content = await safeReadText(path.join(workspace.workspaceRoot, "AGENTS.md"));
377
+ if (content === null)
378
+ return null;
379
+ const stamped = extractBlockVersion(content);
380
+ if (stamped === installed)
381
+ return null;
382
+ const hint = "Re-render the AGENTS.md managed block from the installed framework release.";
383
+ if (!stamped)
384
+ return {
385
+ code: "agent-guide-unstamped",
386
+ message: `AGENTS.md carries no generated-version stamp, so its conventions may predate @akanjs/devkit ${installed}`,
387
+ hint
388
+ };
389
+ return {
390
+ code: "agent-guide-stale",
391
+ message: `AGENTS.md was generated by @akanjs/devkit ${stamped}, but ${installed} is installed`,
392
+ hint
393
+ };
394
+ }
368
395
  static async doctor(workspace, {
369
396
  strict = false,
370
397
  runIdOrPlan = null,
@@ -377,25 +404,37 @@ class AkanContextAnalyzer {
377
404
  repairAction("generated", "akan repair generated --app <app-or-lib>", "Refresh generated Akan files.", true),
378
405
  repairAction("format", "akan repair format --target <app-or-lib-or-pkg>", "Run the formatter/linter repair path.", true)
379
406
  ];
380
- for (const app of context.apps) {
381
- const appPath = path.join(workspace.workspaceRoot, app.path);
382
- for (const entry of await safeReadDir(appPath)) {
383
- if (!isScannedAppRootEntry(entry.name))
407
+ for (const sys of [...context.apps, ...context.libs]) {
408
+ const sysPath = path.join(workspace.workspaceRoot, sys.path);
409
+ for (const entry of await safeReadDir(sysPath)) {
410
+ if (!isScannedRootEntry(sys.type, entry.name))
384
411
  continue;
385
- const allowed = entry.isDirectory() ? appRootAllowedDirs.has(entry.name) : appRootAllowedFiles.has(entry.name);
412
+ const allowed = entry.isDirectory() ? rootAllowedDirs[sys.type].has(entry.name) : rootAllowedFiles[sys.type].has(entry.name);
386
413
  if (!allowed) {
387
- const action = repairAction("module-shape", `akan repair module-shape --app ${app.name}`, "Review app root shape and remove or move the unknown entry.", false);
414
+ const action = repairAction("module-shape", `akan repair module-shape --app ${sys.name}`, `Review ${sys.type} root shape and remove or move the unknown entry.`, false);
388
415
  diagnostics.push({
389
416
  severity: "error",
390
- code: "app-root-unknown-entry",
391
- path: `${app.path}/${entry.name}`,
392
- message: `Unexpected ${entry.isDirectory() ? "folder" : "file"} in app root: ${app.path}/${entry.name}`,
417
+ code: `${sys.type}-root-unknown-entry`,
418
+ path: `${sys.path}/${entry.name}`,
419
+ message: `Unexpected ${entry.isDirectory() ? "folder" : "file"} in ${sys.type} root: ${sys.path}/${entry.name}`,
393
420
  repairActions: [action]
394
421
  });
395
422
  repairActions.push(action);
396
423
  }
397
424
  }
398
425
  }
426
+ const agentDrift = await AkanContextAnalyzer.#agentGuideDrift(workspace);
427
+ if (agentDrift) {
428
+ const action = repairAction("generated", "akan agent install agents-md", agentDrift.hint, true);
429
+ diagnostics.push({
430
+ severity: "warning",
431
+ code: agentDrift.code,
432
+ path: "AGENTS.md",
433
+ message: agentDrift.message,
434
+ repairActions: [action]
435
+ });
436
+ repairActions.push(action);
437
+ }
399
438
  for (const sys of [...context.apps, ...context.libs]) {
400
439
  for (const module of sys.modules) {
401
440
  if (!module.abstract.exists) {
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  runner,
4
4
  script
5
- } from "./index-jkynkyfk.js";
5
+ } from "./index-ckpwq052.js";
6
6
  import {
7
7
  PkgExecutor
8
- } from "./index-47qxw1tz.js";
8
+ } from "./index-681sx6nt.js";
9
9
  import {
10
10
  TypeScriptDependencyScanner
11
11
  } from "./index-46tjzh6s.js";
@@ -163,13 +163,17 @@ class PackageRunner extends runner("package") {
163
163
  "tailwind-scrollbar"
164
164
  ].filter((dep) => dep !== "akanjs" && dep !== "@akanjs/devkit");
165
165
  }
166
- const bundledRuntimeDeps = new Set(pkg.name === "@akanjs/cli" ? ["@akanjs/devkit"] : []);
166
+ const packageBundledRuntimeDependencies = {
167
+ "@akanjs/cli": ["@akanjs/devkit"],
168
+ akanjs: ["use-agentic"]
169
+ };
170
+ const bundledRuntimeDeps = new Set(packageBundledRuntimeDependencies[pkg.name] ?? []);
167
171
  const forcedRuntimeDeps = packageRuntimeDependencies[pkg.name] ?? [];
168
172
  const forcedRuntimeDevDeps = packageRuntimeDevDependencies[pkg.name] ?? [];
169
173
  const [rootPackageJson, pkgJson] = await Promise.all([pkg.workspace.getPackageJson(), pkg.getPackageJson()]);
170
174
  const optionalPeerDeps = new Set(Object.entries(pkgJson.peerDependenciesMeta ?? {}).filter(([, meta]) => meta.optional).map(([dep]) => dep));
171
175
  const packageRuntimeDeps = [...new Set([...npmDeps, ...forcedRuntimeDeps])].filter((dep) => !optionalPeerDeps.has(dep) && !bundledRuntimeDeps.has(dep));
172
- const packageRuntimeDevDeps = [...new Set([...npmDevDeps, ...forcedRuntimeDevDeps])].filter((dep) => !optionalPeerDeps.has(dep));
176
+ const packageRuntimeDevDeps = [...new Set([...npmDevDeps, ...forcedRuntimeDevDeps])].filter((dep) => !optionalPeerDeps.has(dep) && !bundledRuntimeDeps.has(dep));
173
177
  const rootDeps = { ...rootPackageJson.dependencies, ...rootPackageJson.devDependencies };
174
178
  const missingForcedDeps = forcedRuntimeDeps.filter((dep) => !rootDeps[dep]);
175
179
  const missingForcedDevDeps = forcedRuntimeDevDeps.filter((dep) => !rootDeps[dep]);