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

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 +811 -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
@@ -8,18 +8,20 @@ import {
8
8
  DevGeneratedIndexSync,
9
9
  GraphClientEntryDiscovery,
10
10
  RouteClientBuilder
11
- } from "./index-j9cxndc0.js";
11
+ } from "./index-qnv0aqmm.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
  WorkspaceExecutor
19
- } from "./index-47qxw1tz.js";
19
+ } from "./index-681sx6nt.js";
20
+ import"./index-f39512t6.js";
20
21
  import"./index-mxvakhsm.js";
22
+ import"./index-1577bej2.js";
21
23
  import"./index-67546d0j.js";
22
- import"./index-r24hmh0q.js";
24
+ import"./index-yb2wsc7f.js";
23
25
 
24
26
  // pkgs/@akanjs/devkit/incrementalBuilder/incrementalBuilder.proc.ts
25
27
  import path2 from "path";
@@ -249,7 +251,7 @@ class IncrementalBuilder {
249
251
  return;
250
252
  this.#shuttingDown = true;
251
253
  const started = Date.now();
252
- this.#logger.info(`shutdown requested (${reason}); draining ${this.#inFlight} work item(s)`);
254
+ this.#logger.debug(`shutdown requested (${reason}); draining ${this.#inFlight} work item(s)`);
253
255
  if (this.#cssRebuildTimer) {
254
256
  clearTimeout(this.#cssRebuildTimer);
255
257
  this.#cssRebuildTimer = null;
@@ -262,7 +264,7 @@ class IncrementalBuilder {
262
264
  return;
263
265
  });
264
266
  const flushed = await BuilderChannel.drain();
265
- this.#logger.info(`drained in ${Date.now() - started}ms${flushed ? ` after flushing ${flushed} ipc write(s)` : ""}; exiting for recycle`);
267
+ this.#logger.debug(`drained in ${Date.now() - started}ms${flushed ? ` after flushing ${flushed} ipc write(s)` : ""}; exiting for recycle`);
266
268
  process.exit(0);
267
269
  }
268
270
  get shuttingDown() {
@@ -1,24 +1,24 @@
1
1
  // @bun
2
2
  import {
3
3
  CloudRunner
4
- } from "./index-zbx0jheb.js";
4
+ } from "./index-8md8zszv.js";
5
5
  import {
6
6
  PackageScript
7
- } from "./index-meh7mmz9.js";
7
+ } from "./index-x1dbhd80.js";
8
8
  import {
9
9
  AiSession,
10
10
  CloudApi,
11
11
  GlobalConfig
12
- } from "./index-0cj2zxbm.js";
12
+ } from "./index-sh01r3pm.js";
13
13
  import {
14
14
  ApplicationScript
15
- } from "./index-r7nqv8qj.js";
15
+ } from "./index-r8z20vnj.js";
16
16
  import {
17
17
  script
18
- } from "./index-jkynkyfk.js";
18
+ } from "./index-ckpwq052.js";
19
19
  import {
20
20
  PkgExecutor
21
- } from "./index-47qxw1tz.js";
21
+ } from "./index-681sx6nt.js";
22
22
 
23
23
  // pkgs/@akanjs/cli/cloud/cloud.script.ts
24
24
  import { Logger } from "akanjs/common";
@@ -0,0 +1,7 @@
1
+ // @bun
2
+ // pkgs/@akanjs/devkit/getDirname.ts
3
+ import path from "path";
4
+ import { fileURLToPath } from "url";
5
+ var getDirname = (url) => path.dirname(fileURLToPath(url));
6
+
7
+ export { getDirname };
@@ -4,19 +4,19 @@ import {
4
4
  } from "./index-ss469dec.js";
5
5
  import {
6
6
  AiSession
7
- } from "./index-0cj2zxbm.js";
7
+ } from "./index-sh01r3pm.js";
8
8
  import {
9
9
  createPassedPrimitiveReport,
10
10
  generatedFilesForSync,
11
11
  scalarChangedFiles
12
- } from "./index-m4kpmmtj.js";
12
+ } from "./index-g44fykfw.js";
13
13
  import {
14
14
  Prompter
15
- } from "./index-qp089jp0.js";
15
+ } from "./index-j37qq1f2.js";
16
16
  import {
17
17
  runner,
18
18
  script
19
- } from "./index-jkynkyfk.js";
19
+ } from "./index-ckpwq052.js";
20
20
 
21
21
  // pkgs/@akanjs/cli/scalar/scalar.prompt.ts
22
22
  import { input } from "@inquirer/prompts";
@@ -422,7 +422,7 @@ class HmrWatcher {
422
422
  this.#unreportedChanges += unreported;
423
423
  if (!this.#reportedCompensating) {
424
424
  this.#reportedCompensating = true;
425
- this.#logger.info(`[hmr] recovered ${unreported} change(s) that fs.watch did not report; Bun coalesces concurrent saves and drops all but one, so changes are resolved by mtime`);
425
+ this.#logger.verbose(`[hmr] recovered ${unreported} change(s) that fs.watch did not report; Bun coalesces concurrent saves and drops all but one, so changes are resolved by mtime`);
426
426
  }
427
427
  this.#logger.verbose(`[hmr] mtime scan found ${unreported} change(s) fs.watch never reported (${this.#unreportedChanges} total)`);
428
428
  }
@@ -1,13 +1,20 @@
1
1
  // @bun
2
+ import {
3
+ getRootBoundarySegments,
4
+ isRootBoundarySegments
5
+ } from "./index-f39512t6.js";
2
6
  import {
3
7
  Spinner
4
8
  } from "./index-mxvakhsm.js";
9
+ import {
10
+ getDirname
11
+ } from "./index-1577bej2.js";
5
12
  import {
6
13
  FileSys
7
14
  } from "./index-67546d0j.js";
8
15
  import {
9
16
  __require
10
- } from "./index-r24hmh0q.js";
17
+ } from "./index-yb2wsc7f.js";
11
18
 
12
19
  // pkgs/@akanjs/devkit/executors.ts
13
20
  import {
@@ -30,6 +37,7 @@ import path5 from "path";
30
37
  import { pathToFileURL } from "url";
31
38
  import {
32
39
  capitalize,
40
+ getPageSourceFileViolation,
33
41
  isRouteSourceFile,
34
42
  Logger,
35
43
  parseRouteModuleKey,
@@ -41,9 +49,24 @@ import chalk2 from "chalk";
41
49
 
42
50
  // pkgs/@akanjs/devkit/agentsIndex.ts
43
51
  var recipeScannerLoad = null;
44
- var loadRecipeScanner = () => recipeScannerLoad ??= import("./recipeScanner-tghkzrrt.js");
52
+ var loadRecipeScanner = () => recipeScannerLoad ??= import("./recipeScanner-zrzev25x.js");
45
53
  var AGENT_BLOCK_START = "<!-- akan:agent:start -->";
46
54
  var AGENT_BLOCK_END = "<!-- akan:agent:end -->";
55
+ var AGENT_VERSION_PREFIX = "<!-- akan:agent:version ";
56
+ var stampBlockVersion = (block, version) => `${AGENT_VERSION_PREFIX}${version} -->
57
+
58
+ ${block}`;
59
+ var extractBlockVersion = (content) => content.match(/<!-- akan:agent:version ([^\s]+) -->/)?.[1] ?? null;
60
+ var readDevkitVersion = async () => {
61
+ const { readFile } = await import("fs/promises");
62
+ const { getDirname: getDirname2 } = await import("./getDirname-ka11hm7e.js");
63
+ try {
64
+ const raw = await readFile(`${getDirname2(import.meta.url)}/package.json`, "utf-8");
65
+ return JSON.parse(raw).version ?? null;
66
+ } catch {
67
+ return null;
68
+ }
69
+ };
47
70
  var upsertAgentBlock = (existing, block) => {
48
71
  const managed = `${AGENT_BLOCK_START}
49
72
  ${block}
@@ -137,9 +160,29 @@ ${AGENT_BLOCK_START}
137
160
  ${block}
138
161
  ${AGENT_BLOCK_END}
139
162
  `;
163
+ var CLAUDE_COMMENT_RULE = `## Comments \u2014 Overrides Your Default
164
+
165
+ Write **no comments** unless the comment passes the test below. This is the rule agents break most often here, so it
166
+ is repeated outside the guide: a diff that adds a comment the test rejects is a diff to redo.
167
+
168
+ Before typing \`//\`, \`/*\`, or a doc block, ask \u2014 **does this sentence carry a fact that is nowhere in the code?**
169
+
170
+ - Restates the identifier, the signature, or the line under it \u2192 delete it.
171
+ - Labels a section (\`// helpers\`, \`// state\`) or narrates a step (\`// fetch the user\`, \`// then save\`) \u2192 delete it.
172
+ - JSDoc on an ordinary function, or a why/how preamble on ordinary logic \u2192 delete it.
173
+ - Explains the edit you just made, for whoever reads the diff \u2192 say it in your reply, not in the file.
174
+ - Names a vendor or protocol quirk, an infrastructure constraint, a library gotcha, security reasoning, a math
175
+ derivation, a domain field's business meaning, a state transition, or why an obvious alternative was rejected \u2192
176
+ keep it, one line.
177
+
178
+ That keep-list is exact \u2014 \`Comments\` in the guide is the full version. "It aids readability" and "this logic is
179
+ subtle" are not on it: rename or split the code instead. When you edit an existing file, match its density; if the
180
+ surrounding code carries none, your diff carries none.`;
140
181
  var renderScopeClaudeMd = (scope) => `# ${scope.name} \u2014 Claude Code Guide
141
182
 
142
183
  @AGENTS.md
184
+
185
+ ${CLAUDE_COMMENT_RULE}
143
186
  `;
144
187
 
145
188
  // pkgs/@akanjs/devkit/akanConfig/akanConfig.ts
@@ -182,8 +225,6 @@ var DEFAULT_OPTIMIZE_IMPORTS = [
182
225
  ];
183
226
  var WORKSPACE_BARREL_FACETS = ["ui", "webkit", "common", "client", "server"];
184
227
  var SSR_RUNTIME_PACKAGES = ["react", "react-dom", "react-server-dom-webpack"];
185
- var NATIVE_RUNTIME_PACKAGES = ["sharp"];
186
- var DEFAULT_BACKEND_RUNTIME_PACKAGES = ["croner"];
187
228
  var MOBILE_RUNTIME_PACKAGES = [
188
229
  "@capacitor/cli",
189
230
  "@capacitor/core",
@@ -212,8 +253,6 @@ var DATABASE_MODE_RUNTIME_PACKAGES = {
212
253
  };
213
254
  var AKAN_RUNTIME_PACKAGES = new Set([
214
255
  ...SSR_RUNTIME_PACKAGES,
215
- ...NATIVE_RUNTIME_PACKAGES,
216
- ...DEFAULT_BACKEND_RUNTIME_PACKAGES,
217
256
  ...MOBILE_RUNTIME_PACKAGES,
218
257
  ...Object.values(DATABASE_MODE_RUNTIME_PACKAGES).flat()
219
258
  ]);
@@ -298,7 +337,7 @@ class AkanAppConfig {
298
337
  subRoutes = new Map;
299
338
  basePaths = new Set;
300
339
  branches = new Set(["debug", "develop", "main"]);
301
- constructor(app, libs, rootPackageJson, config, baseDevEnv, plugins = []) {
340
+ constructor(app, libs, rootPackageJson, config, baseDevEnv, plugins = [], libExternalLibs = []) {
302
341
  this.app = app;
303
342
  this.rootPackageJson = rootPackageJson;
304
343
  this.libs = libs;
@@ -306,7 +345,7 @@ class AkanAppConfig {
306
345
  this.plugins = plugins;
307
346
  this.#applyRoutes(config?.routes);
308
347
  this.defaultDatabaseMode = config?.defaultDatabaseMode ?? "single";
309
- this.externalLibs = config?.externalLibs ?? [];
348
+ this.externalLibs = [...new Set([...config?.externalLibs ?? [], ...libExternalLibs])];
310
349
  this.barrelImports = [
311
350
  ...DEFAULT_BARREL_IMPORTS,
312
351
  ...WORKSPACE_BARREL_FACETS.map((facet) => `@apps/${app.name}/${facet}`),
@@ -495,7 +534,15 @@ CMD [${command.map((c) => `"${c}"`).join(",")}]`;
495
534
  ]);
496
535
  const resolved = typeof configImp === "function" ? configImp(app) : configImp;
497
536
  const { plugins, ...config } = resolved ?? {};
498
- return new AkanAppConfig(app, libs, rootPackageJson, config, baseDevEnv, plugins ?? []);
537
+ const libExternalLibs = await AkanAppConfig.#collectLibExternalLibs(app, libs, bustImportCache);
538
+ return new AkanAppConfig(app, libs, rootPackageJson, config, baseDevEnv, plugins ?? [], libExternalLibs);
539
+ }
540
+ static async#collectLibExternalLibs(app, libs, bustImportCache) {
541
+ const libConfigs = await Promise.all(libs.map(async (libName) => LibExecutor.from(app, libName).getConfig({ refresh: bustImportCache }).catch((error) => {
542
+ app.logger.warn(`Skipped libs/${libName}/akan.config.ts externalLibs: ${String(error)}`);
543
+ return null;
544
+ })));
545
+ return libConfigs.flatMap((libConfig) => libConfig?.externalLibs ?? []);
499
546
  }
500
547
  #resolveProductionDependencyVersion(lib) {
501
548
  const rootVersion = this.rootPackageJson.dependencies?.[lib] ?? this.rootPackageJson.devDependencies?.[lib];
@@ -505,13 +552,7 @@ CMD [${command.map((c) => `"${c}"`).join(",")}]`;
505
552
  return akanPackageJson.dependencies?.[lib] ?? akanPackageJson.peerDependencies?.[lib];
506
553
  }
507
554
  #getProductionRuntimePackages() {
508
- return [
509
- ...this.externalLibs,
510
- ...SSR_RUNTIME_PACKAGES,
511
- ...NATIVE_RUNTIME_PACKAGES,
512
- ...DEFAULT_BACKEND_RUNTIME_PACKAGES,
513
- ...this.getDatabaseModeRuntimePackages()
514
- ];
555
+ return [...this.externalLibs, ...SSR_RUNTIME_PACKAGES, ...this.getDatabaseModeRuntimePackages()];
515
556
  }
516
557
  getDatabaseModeRuntimePackages(databaseMode = this.defaultDatabaseMode) {
517
558
  return [...DATABASE_MODE_RUNTIME_PACKAGES[databaseMode]];
@@ -605,8 +646,8 @@ class AkanLibConfig {
605
646
  this.externalLibs = config?.externalLibs ?? [];
606
647
  this.plugins = plugins;
607
648
  }
608
- static async from(lib) {
609
- const [configImp] = await Promise.all([import(`${lib.cwdPath}/akan.config.ts`).then((mod) => mod.default)]);
649
+ static async from(lib, { bustImportCache = false } = {}) {
650
+ const configImp = await AkanAppConfig.importConfigModule(lib.cwdPath, { bustImportCache });
610
651
  const resolved = typeof configImp === "function" ? configImp(lib) : configImp;
611
652
  const { plugins, ...config } = resolved ?? {};
612
653
  return new AkanLibConfig(lib, config, plugins ?? []);
@@ -627,42 +668,47 @@ var decreaseBuildNum = async (app) => {
627
668
  const akanConfigContent = akanConfig.replace(`buildNum: ${appConfig.mobile.buildNum}`, `buildNum: ${appConfig.mobile.buildNum - 1}`);
628
669
  fs.writeFileSync(akanConfigPath, akanConfigContent);
629
670
  };
630
- // pkgs/@akanjs/devkit/getDirname.ts
631
- import path2 from "path";
632
- import { fileURLToPath as fileURLToPath2 } from "url";
633
- var getDirname = (url) => path2.dirname(fileURLToPath2(url));
634
-
635
671
  // pkgs/@akanjs/devkit/linter.ts
636
672
  import { spawn } from "child_process";
637
673
  import { existsSync, readFileSync } from "fs";
638
- import path3 from "path";
674
+ import path2 from "path";
639
675
  import chalk from "chalk";
676
+ var BIOME_CONFIG_FILES = ["biome.json", "biome.jsonc"];
640
677
 
641
678
  class Linter {
642
679
  lintRoot;
680
+ configPath;
643
681
  #biomeBin;
644
682
  constructor(cwdPath) {
645
683
  this.lintRoot = this.#findBiomeRootPath(cwdPath);
646
- const localBiomeBin = path3.join(this.lintRoot, "node_modules/.bin/biome");
684
+ this.configPath = Linter.#configPathIn(this.lintRoot) ?? path2.join(this.lintRoot, "biome.json");
685
+ const localBiomeBin = path2.join(this.lintRoot, "node_modules/.bin/biome");
647
686
  this.#biomeBin = existsSync(localBiomeBin) ? localBiomeBin : "biome";
648
687
  }
688
+ static #configPathIn(dir) {
689
+ for (const fileName of BIOME_CONFIG_FILES) {
690
+ const configPath = path2.join(dir, fileName);
691
+ if (existsSync(configPath))
692
+ return configPath;
693
+ }
694
+ return null;
695
+ }
649
696
  #findBiomeRootPath(dir) {
650
- const configPath = path3.join(dir, "biome.json");
651
- if (existsSync(configPath))
697
+ if (Linter.#configPathIn(dir))
652
698
  return dir;
653
- const parentDir = path3.dirname(dir);
699
+ const parentDir = path2.dirname(dir);
654
700
  if (parentDir === dir)
655
701
  throw new Error(`biome.json not found from ${dir}`);
656
702
  return this.#findBiomeRootPath(parentDir);
657
703
  }
658
704
  #toBiomePath(filePath) {
659
- const relativePath = path3.relative(this.lintRoot, filePath);
660
- if (!relativePath.startsWith("..") && !path3.isAbsolute(relativePath))
705
+ const relativePath = path2.relative(this.lintRoot, filePath);
706
+ if (!relativePath.startsWith("..") && !path2.isAbsolute(relativePath))
661
707
  return relativePath;
662
708
  return filePath;
663
709
  }
664
710
  #resolveFilePath(filePath) {
665
- return path3.isAbsolute(filePath) ? filePath : path3.join(this.lintRoot, filePath);
711
+ return path2.isAbsolute(filePath) ? filePath : path2.join(this.lintRoot, filePath);
666
712
  }
667
713
  async#runBiome(args, input) {
668
714
  return await new Promise((resolve, reject) => {
@@ -694,7 +740,7 @@ class Linter {
694
740
  const diagnosticPath = diagnostic.location?.path;
695
741
  if (!diagnosticPath)
696
742
  return fallbackFilePath;
697
- return path3.isAbsolute(diagnosticPath) ? diagnosticPath : path3.join(this.lintRoot, diagnosticPath);
743
+ return path2.isAbsolute(diagnosticPath) ? diagnosticPath : path2.join(this.lintRoot, diagnosticPath);
698
744
  }
699
745
  #createLintMessage(diagnostic) {
700
746
  const start = diagnostic.location?.start;
@@ -759,7 +805,7 @@ class Linter {
759
805
  "--max-diagnostics=none",
760
806
  "--no-errors-on-unmatched",
761
807
  "--config-path",
762
- path3.join(this.lintRoot, "biome.json"),
808
+ this.configPath,
763
809
  this.#toBiomePath(filePath)
764
810
  ]);
765
811
  const report = this.#parseBiomeReport(stdout || stderr);
@@ -880,14 +926,7 @@ ${errorText}, ${warningText} found`];
880
926
  if (!dryRun)
881
927
  return await this.#checkFile(resolvedFilePath, { write: true });
882
928
  const source = readFileSync(resolvedFilePath, "utf8");
883
- const { stdout } = await this.#runBiome([
884
- "check",
885
- "--write",
886
- "--config-path",
887
- path3.join(this.lintRoot, "biome.json"),
888
- "--stdin-file-path",
889
- this.#toBiomePath(resolvedFilePath)
890
- ], source);
929
+ const { stdout } = await this.#runBiome(["check", "--write", "--config-path", this.configPath, "--stdin-file-path", this.#toBiomePath(resolvedFilePath)], source);
891
930
  const lintResult = await this.lintFile(resolvedFilePath);
892
931
  return { ...lintResult, fixed: stdout !== source, output: stdout };
893
932
  }
@@ -895,7 +934,7 @@ ${errorText}, ${warningText} found`];
895
934
  const resolvedFilePath = this.#resolveFilePath(filePath);
896
935
  if (!existsSync(resolvedFilePath))
897
936
  throw new Error(`File not found: ${filePath}`);
898
- return JSON.parse(readFileSync(path3.join(this.lintRoot, "biome.json"), "utf8"));
937
+ return JSON.parse(readFileSync(this.configPath, "utf8"));
899
938
  }
900
939
  async getProblematicRules(filePath) {
901
940
  const { results } = await this.lintFile(filePath);
@@ -910,6 +949,31 @@ ${errorText}, ${warningText} found`];
910
949
  }
911
950
  }
912
951
 
952
+ // pkgs/@akanjs/devkit/repoIdentity.ts
953
+ import { execFileSync } from "child_process";
954
+ import path3 from "path";
955
+ var resolved = new Map;
956
+ var readRemoteName = (workspaceRoot) => {
957
+ try {
958
+ const url = execFileSync("git", ["config", "--get", "remote.origin.url"], {
959
+ cwd: workspaceRoot,
960
+ encoding: "utf-8",
961
+ stdio: ["ignore", "pipe", "ignore"]
962
+ }).trim();
963
+ return url.replace(/\.git$/, "").split(/[/:]/).pop() || null;
964
+ } catch {
965
+ return null;
966
+ }
967
+ };
968
+ var resolveRepoName = (workspaceRoot) => {
969
+ const cached = resolved.get(workspaceRoot);
970
+ if (cached)
971
+ return cached;
972
+ const repoName = readRemoteName(workspaceRoot) ?? path3.basename(workspaceRoot);
973
+ resolved.set(workspaceRoot, repoName);
974
+ return repoName;
975
+ };
976
+
913
977
  // pkgs/@akanjs/devkit/scanInfo.ts
914
978
  import { rm } from "fs/promises";
915
979
  import path4 from "path";
@@ -946,6 +1010,34 @@ var appRootAllowedDirs = new Set([
946
1010
  "ui",
947
1011
  "webkit"
948
1012
  ]);
1013
+ var libRootAllowedFiles = new Set([
1014
+ "AGENTS.md",
1015
+ "CLAUDE.md",
1016
+ "README.md",
1017
+ "akan.config.ts",
1018
+ "akan.lib.json",
1019
+ "client.ts",
1020
+ "index.ts",
1021
+ "package.json",
1022
+ "server.ts",
1023
+ "tsconfig.json",
1024
+ "tsconfig.spec.json",
1025
+ "tsconfig.tsbuildinfo"
1026
+ ]);
1027
+ var libRootAllowedDirs = new Set([
1028
+ "common",
1029
+ "env",
1030
+ "lib",
1031
+ "page",
1032
+ "plugin",
1033
+ "private",
1034
+ "public",
1035
+ "srvkit",
1036
+ "ui",
1037
+ "webkit"
1038
+ ]);
1039
+ var rootAllowedFiles = { app: appRootAllowedFiles, lib: libRootAllowedFiles };
1040
+ var rootAllowedDirs = { app: appRootAllowedDirs, lib: libRootAllowedDirs };
949
1041
  var libFacetRootAllowedFiles = new Set([
950
1042
  "cnst.ts",
951
1043
  "db.ts",
@@ -957,7 +1049,9 @@ var libFacetRootAllowedFiles = new Set([
957
1049
  "useClient.ts",
958
1050
  "useServer.ts"
959
1051
  ]);
960
- var isScannedAppRootEntry = (name) => !name.startsWith(".") || appRootAllowedDirs.has(name);
1052
+ var libFacetRootTestPattern = /^[A-Za-z][A-Za-z0-9_-]*\.signal\.(test|spec)\.(ts|tsx)$/;
1053
+ var isAllowedLibFacetRootFile = (filename) => libFacetRootAllowedFiles.has(filename) || libFacetRootTestPattern.test(filename);
1054
+ var isScannedRootEntry = (type, name) => !name.startsWith(".") || rootAllowedDirs[type].has(name);
961
1055
 
962
1056
  // pkgs/@akanjs/devkit/scanInfo.ts
963
1057
  var databaseFileTypes = [
@@ -986,10 +1080,8 @@ var moduleUiFileTypes = {
986
1080
  scalar: new Set(["Template", "Unit"])
987
1081
  };
988
1082
  var testFilePattern = /\.(test|spec)\.(ts|tsx)$/;
989
- var rootSignalTestFilePattern = /^[A-Za-z][A-Za-z0-9_-]*\.signal\.(test|spec)\.(ts|tsx)$/;
990
- var createDependencyScanner = async (exec) => (await import("./dependencyScanner-f6grrep3.js")).TypeScriptDependencyScanner.from(exec);
1083
+ var createDependencyScanner = async (exec) => (await import("./dependencyScanner-rbs2407b.js")).TypeScriptDependencyScanner.from(exec);
991
1084
  var isAllowedTestFile = (filename) => testFilePattern.test(filename);
992
- var isAllowedLibRootFile = (filename) => libFacetRootAllowedFiles.has(filename) || rootSignalTestFilePattern.test(filename);
993
1085
  var getScanPath = (exec, relativePath) => path4.posix.join(`${exec.type}s`, exec.name, relativePath.split(path4.sep).join("/"));
994
1086
  async function clearGeneratedRootCapacitorConfigs(exec) {
995
1087
  if (exec.type !== "app")
@@ -1006,17 +1098,20 @@ async function assertScanConvention(exec, libRoot) {
1006
1098
  const addViolation = (relativePath, reason) => {
1007
1099
  violations.push(`${getScanPath(exec, relativePath)}: ${reason}`);
1008
1100
  };
1009
- if (exec.type === "app") {
1010
- const { files, dirs } = await exec.getFilesAndDirs(".");
1011
- files.filter((filename) => !appRootAllowedFiles.has(filename)).forEach((filename) => {
1012
- addViolation(filename, "unsupported app root file");
1013
- });
1014
- dirs.filter((dirname) => !appRootAllowedDirs.has(dirname)).forEach((dirname) => {
1015
- addViolation(dirname, "unsupported app root folder");
1016
- });
1017
- }
1018
- libRoot.files.filter((filename) => !isAllowedLibRootFile(filename)).forEach((filename) => {
1019
- addViolation(path4.join("lib", filename), "unsupported lib root file");
1101
+ const allowedRootFiles = rootAllowedFiles[exec.type];
1102
+ const allowedRootDirs = rootAllowedDirs[exec.type];
1103
+ const { files, dirs } = await exec.getFilesAndDirs(".");
1104
+ files.filter((filename) => !allowedRootFiles.has(filename)).forEach((filename) => {
1105
+ addViolation(filename, `unsupported ${exec.type} root file`);
1106
+ });
1107
+ dirs.filter((dirname) => !allowedRootDirs.has(dirname)).forEach((dirname) => {
1108
+ addViolation(dirname, `unsupported ${exec.type} root folder`);
1109
+ });
1110
+ if (exec.type === "lib")
1111
+ for (const { relativePath, reason } of await exec.getPageConventionViolations())
1112
+ addViolation(relativePath, reason);
1113
+ libRoot.files.filter((filename) => !isAllowedLibFacetRootFile(filename)).forEach((filename) => {
1114
+ addViolation(path4.join("lib", filename), "unsupported lib facet root file");
1020
1115
  });
1021
1116
  libRoot.dirs.filter((dirname) => dirname.startsWith("__") && !internalLibDirs.has(dirname)).forEach((dirname) => {
1022
1117
  addViolation(path4.join("lib", dirname), "unsupported internal lib folder");
@@ -1634,7 +1729,7 @@ class Executor {
1634
1729
  }));
1635
1730
  });
1636
1731
  proc.on("exit", (code, signal) => {
1637
- if (!!code || signal)
1732
+ if (code || signal)
1638
1733
  reject(new CommandExecutionError({
1639
1734
  command,
1640
1735
  cwd,
@@ -1732,7 +1827,7 @@ class Executor {
1732
1827
  }));
1733
1828
  });
1734
1829
  proc.on("exit", (code, signal) => {
1735
- if (!!code || signal)
1830
+ if (code || signal)
1736
1831
  reject(new CommandExecutionError({
1737
1832
  command: modulePath,
1738
1833
  args,
@@ -2028,7 +2123,7 @@ class Executor {
2028
2123
  return this._applyTemplate({ ...options, dict });
2029
2124
  }
2030
2125
  async getTypeChecker() {
2031
- const { TypeChecker } = await import("./typeChecker-kravn7ns.js");
2126
+ const { TypeChecker } = await import("./typeChecker-g6bh0xfv.js");
2032
2127
  this.typeChecker ??= new TypeChecker(this);
2033
2128
  return this.typeChecker;
2034
2129
  }
@@ -2109,7 +2204,7 @@ class WorkspaceExecutor extends Executor {
2109
2204
  static #execs = new Map;
2110
2205
  static fromRoot({
2111
2206
  workspaceRoot = process.cwd(),
2112
- repoName = path5.basename(process.cwd())
2207
+ repoName = resolveRepoName(workspaceRoot)
2113
2208
  } = {}) {
2114
2209
  return WorkspaceExecutor.#execs.get(repoName) ?? new WorkspaceExecutor({ workspaceRoot, repoName });
2115
2210
  }
@@ -2297,6 +2392,18 @@ class SysExecutor extends Executor {
2297
2392
  const path6 = this.type === "app" ? `apps/${this.name}/lib` : `libs/${this.name}/lib`;
2298
2393
  return await this.workspace.getDirInModule(path6, this.name);
2299
2394
  }
2395
+ async getPageConventionViolations() {
2396
+ if (!await this.exists("page"))
2397
+ return [];
2398
+ const violations = [];
2399
+ for (const entry of await this.getAllFiles("**/*", { cwd: this.getPath("page") })) {
2400
+ const relativePath = entry.split(path5.sep).join("/");
2401
+ const reason = getPageSourceFileViolation(relativePath);
2402
+ if (reason)
2403
+ violations.push({ relativePath: `page/${relativePath}`, reason });
2404
+ }
2405
+ return violations;
2406
+ }
2300
2407
  #scanInfo = null;
2301
2408
  hasScanInfo() {
2302
2409
  return this.#scanInfo !== null;
@@ -2485,7 +2592,7 @@ class SysExecutor extends Executor {
2485
2592
  class AppExecutor extends SysExecutor {
2486
2593
  static #routeSourceValidator = null;
2487
2594
  static async#getRouteSourceValidator() {
2488
- AppExecutor.#routeSourceValidator ??= (await import("./routeSourceValidator-cncd92fv.js")).RouteSourceValidator;
2595
+ AppExecutor.#routeSourceValidator ??= (await import("./routeSourceValidator-7fycdqyv.js")).RouteSourceValidator;
2489
2596
  return AppExecutor.#routeSourceValidator;
2490
2597
  }
2491
2598
  dist;
@@ -2553,6 +2660,8 @@ class AppExecutor extends SysExecutor {
2553
2660
  ]);
2554
2661
  } else
2555
2662
  await this.removeDir(".akan");
2663
+ if (type === "start")
2664
+ process.env.NODE_ENV = "development";
2556
2665
  const devPort = type === "start" ? (await this.getDevPort()).toString() : undefined;
2557
2666
  const env = this.getCommandEnv({
2558
2667
  AKAN_COMMAND_TYPE: type,
@@ -2641,7 +2750,8 @@ class AppExecutor extends SysExecutor {
2641
2750
  }
2642
2751
  if (!owner)
2643
2752
  owners.set(routeId, { absPath, fromLib });
2644
- const isRootLayout = parsed.kind === "layout" && parsed.moduleSegments.at(-1) === "_layout";
2753
+ const layoutSegments = getRootBoundarySegments(key);
2754
+ const isRootLayout = layoutSegments !== null && isRootBoundarySegments(layoutSegments, akanConfig2.basePaths);
2645
2755
  const routeSource = await Bun.file(absPath).text();
2646
2756
  const validator = await AppExecutor.#getRouteSourceValidator();
2647
2757
  if (parsed.kind === "overrides")
@@ -2869,7 +2979,7 @@ class LibExecutor extends SysExecutor {
2869
2979
  async getConfig({ refresh } = {}) {
2870
2980
  if (this.#akanConfig && !refresh)
2871
2981
  return this.#akanConfig;
2872
- this.#akanConfig = await AkanLibConfig.from(this);
2982
+ this.#akanConfig = await AkanLibConfig.from(this, { bustImportCache: refresh });
2873
2983
  return this.#akanConfig;
2874
2984
  }
2875
2985
  }
@@ -2966,7 +3076,7 @@ class PkgExecutor extends Executor {
2966
3076
  default: "./index.ts"
2967
3077
  }
2968
3078
  },
2969
- engines: { bun: ">=1.3.13" },
3079
+ engines: { bun: ">=1.4.0" },
2970
3080
  ...dependencyMaps
2971
3081
  };
2972
3082
  await Promise.all([this.dist.writeJson("package.json", distPkgJson), this.writeJson("package.json", distPkgJson)]);
@@ -3009,4 +3119,4 @@ class ModuleExecutor extends Executor {
3009
3119
  }
3010
3120
  }
3011
3121
 
3012
- export { AGENT_BLOCK_START, AGENT_BLOCK_END, upsertAgentBlock, extractAgentBlock, renderRecipeEntries, collectScopeRecipeSources, renderScopeAgentBlock, getDirname, appRootAllowedFiles, appRootAllowedDirs, libFacetRootAllowedFiles, isScannedAppRootEntry, CommandExecutionError, Executor, WorkspaceExecutor, SysExecutor, AppExecutor, LibExecutor, PkgExecutor, ModuleExecutor };
3122
+ export { AGENT_BLOCK_START, AGENT_BLOCK_END, stampBlockVersion, extractBlockVersion, readDevkitVersion, upsertAgentBlock, extractAgentBlock, renderRecipeEntries, collectScopeRecipeSources, renderScopeAgentBlock, CLAUDE_COMMENT_RULE, rootAllowedFiles, rootAllowedDirs, isAllowedLibFacetRootFile, isScannedRootEntry, CommandExecutionError, Executor, WorkspaceExecutor, SysExecutor, AppExecutor, LibExecutor, PkgExecutor, ModuleExecutor };
@@ -4,24 +4,17 @@ import {
4
4
  CloudApi,
5
5
  GlobalConfig,
6
6
  getDefaultHostConfig
7
- } from "./index-0cj2zxbm.js";
7
+ } from "./index-sh01r3pm.js";
8
8
  import {
9
9
  openBrowser
10
- } from "./index-r7nqv8qj.js";
10
+ } from "./index-r8z20vnj.js";
11
11
  import {
12
12
  runner
13
- } from "./index-jkynkyfk.js";
13
+ } from "./index-ckpwq052.js";
14
14
  import {
15
15
  AppExecutor,
16
16
  WorkspaceExecutor
17
- } from "./index-47qxw1tz.js";
18
-
19
- // pkgs/@akanjs/cli/cloud/cloud.runner.ts
20
- import path from "path";
21
- import { confirm, input, select } from "@inquirer/prompts";
22
- import { Logger, sleep } from "akanjs/common";
23
- import chalk from "chalk";
24
- import * as QRcode from "qrcode";
17
+ } from "./index-681sx6nt.js";
25
18
 
26
19
  // pkgs/@akanjs/cli/npmRegistry.ts
27
20
  var defaultNpmRegistry = "https://registry.npmjs.org";
@@ -40,6 +33,11 @@ async function getLatestPackageVersion(packageName, tag = "latest", registryUrl)
40
33
  }
41
34
 
42
35
  // pkgs/@akanjs/cli/cloud/cloud.runner.ts
36
+ import path from "path";
37
+ import { confirm, input, select } from "@inquirer/prompts";
38
+ import { Logger, sleep } from "akanjs/common";
39
+ import chalk from "chalk";
40
+ import * as QRcode from "qrcode";
43
41
  var addRemoteEnvServerValue = "__addRemoteEnvServer";
44
42
  var removeRemoteEnvServerValue = "__removeRemoteEnvServer";
45
43
 
@@ -285,7 +283,10 @@ ${chalk.green("\u27A4")} Authentication Required`));
285
283
  return;
286
284
  }
287
285
  }
288
- await Promise.all(akanPkgs.map(async (library) => {
286
+ Logger.info("Logging in to npm...");
287
+ await workspace.spawn("npm", ["login"], { stdio: "inherit" });
288
+ Logger.info("Logged in to npm");
289
+ for (const library of akanPkgs) {
289
290
  Logger.info(`Publishing ${library}@${nextVersion} to ${registry ?? "npm"}...`);
290
291
  await workspace.spawn("npm", ["publish", "--tag", tag, ...this.#getRegistryArgs(registry), ...this.#getLocalRegistryAuthArgs(registry)], {
291
292
  cwd: path.join(workspace.workspaceRoot, "dist/pkgs", library),
@@ -293,7 +294,7 @@ ${chalk.green("\u27A4")} Authentication Required`));
293
294
  stdio: "inherit"
294
295
  });
295
296
  Logger.info(`${library}@${nextVersion} is published to ${registry ?? "npm"}`);
296
- }));
297
+ }
297
298
  Logger.info(`All libraries are published to ${registry ?? "npm"}`);
298
299
  }
299
300
  async update(workspace, tag = "latest", { registryUrl } = {}) {