@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
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  ModuleScript
4
- } from "./index-60a3jfcz.js";
4
+ } from "./index-tn46rr6w.js";
5
5
  import {
6
6
  addFieldUiPolicyForType,
7
7
  coerceFieldDefault,
@@ -34,15 +34,15 @@ import {
34
34
  sourceFile,
35
35
  validationCommandsForTarget,
36
36
  viaBuilderParameterName
37
- } from "./index-m4kpmmtj.js";
37
+ } from "./index-g44fykfw.js";
38
38
  import {
39
39
  script
40
- } from "./index-jkynkyfk.js";
40
+ } from "./index-ckpwq052.js";
41
41
  import {
42
42
  AppExecutor,
43
43
  LibExecutor,
44
44
  ModuleExecutor
45
- } from "./index-47qxw1tz.js";
45
+ } from "./index-681sx6nt.js";
46
46
 
47
47
  // pkgs/@akanjs/cli/primitive/primitive.script.ts
48
48
  import { capitalize } from "akanjs/common";
@@ -5,7 +5,7 @@ import {
5
5
  } from "./index-76rn3g2c.js";
6
6
  import {
7
7
  CommandExecutionError
8
- } from "./index-47qxw1tz.js";
8
+ } from "./index-681sx6nt.js";
9
9
 
10
10
  // pkgs/@akanjs/devkit/capacitorApp.ts
11
11
  import { cp, mkdir, readFile, rm, writeFile } from "fs/promises";
@@ -5,15 +5,17 @@ import {
5
5
  LibExecutor,
6
6
  ModuleExecutor,
7
7
  PkgExecutor,
8
- WorkspaceExecutor,
8
+ WorkspaceExecutor
9
+ } from "./index-681sx6nt.js";
10
+ import {
9
11
  getDirname
10
- } from "./index-47qxw1tz.js";
12
+ } from "./index-1577bej2.js";
11
13
  import {
12
14
  FileSys
13
15
  } from "./index-67546d0j.js";
14
16
  import {
15
17
  __require
16
- } from "./index-r24hmh0q.js";
18
+ } from "./index-yb2wsc7f.js";
17
19
 
18
20
  // pkgs/@akanjs/devkit/commandDecorators/targetMeta.ts
19
21
  var COMMAND_META = Symbol("akan.command.meta");
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  AkanContextAnalyzer
4
- } from "./index-jn9vfpwz.js";
4
+ } from "./index-wc19q8mb.js";
5
5
  import {
6
6
  WorkflowExecutor,
7
7
  compactWorkflowInputs,
@@ -23,10 +23,10 @@ import {
23
23
  workflowCommandsForPlan,
24
24
  workflowPlanApproval,
25
25
  writeWorkflowRunArtifact
26
- } from "./index-m4kpmmtj.js";
26
+ } from "./index-g44fykfw.js";
27
27
  import {
28
28
  runner
29
- } from "./index-jkynkyfk.js";
29
+ } from "./index-ckpwq052.js";
30
30
 
31
31
  // pkgs/@akanjs/cli/workflow/workflow.runner.ts
32
32
  import { mkdir, readFile, writeFile } from "fs/promises";
@@ -1,22 +1,22 @@
1
1
  // @bun
2
2
  import {
3
3
  RepairRunner
4
- } from "./index-6npsfpxr.js";
4
+ } from "./index-ryns915y.js";
5
5
  import {
6
6
  WorkflowRunner
7
- } from "./index-c94nq3c1.js";
7
+ } from "./index-dvg362vq.js";
8
+ import {
9
+ ScalarScript
10
+ } from "./index-4mtyaqj2.js";
8
11
  import {
9
12
  PrimitiveScript
10
- } from "./index-pfrt7qwh.js";
13
+ } from "./index-cc1mgv1f.js";
11
14
  import {
12
15
  ModuleScript
13
- } from "./index-60a3jfcz.js";
14
- import {
15
- ScalarScript
16
- } from "./index-wrrb8rxk.js";
16
+ } from "./index-tn46rr6w.js";
17
17
  import {
18
18
  isPlaceholderAppId
19
- } from "./index-hk9rbcsz.js";
19
+ } from "./index-ce9755av.js";
20
20
  import {
21
21
  AkanContextAnalyzer,
22
22
  akanMcpInstallConfigPaths,
@@ -27,17 +27,17 @@ import {
27
27
  renderDoctorText,
28
28
  resourceList,
29
29
  upsertCodexMcpServerBlock
30
- } from "./index-jn9vfpwz.js";
30
+ } from "./index-wc19q8mb.js";
31
31
  import {
32
32
  buildAkanModuleContextIndex,
33
33
  createWorkflowBaselineSummary,
34
34
  createWorkflowStepRegistry,
35
35
  jsonText,
36
36
  toolingRolloutGate
37
- } from "./index-m4kpmmtj.js";
37
+ } from "./index-g44fykfw.js";
38
38
  import {
39
39
  Prompter
40
- } from "./index-qp089jp0.js";
40
+ } from "./index-j37qq1f2.js";
41
41
  import {
42
42
  getMobileTargets
43
43
  } from "./index-76rn3g2c.js";
@@ -45,10 +45,10 @@ import {
45
45
  CommandContainer,
46
46
  runner,
47
47
  script
48
- } from "./index-jkynkyfk.js";
48
+ } from "./index-ckpwq052.js";
49
49
  import {
50
50
  AppExecutor
51
- } from "./index-47qxw1tz.js";
51
+ } from "./index-681sx6nt.js";
52
52
 
53
53
  // pkgs/@akanjs/cli/context/context.script.ts
54
54
  import { Logger } from "akanjs/common";
@@ -2,16 +2,17 @@
2
2
  import {
3
3
  runner,
4
4
  script
5
- } from "./index-jkynkyfk.js";
5
+ } from "./index-ckpwq052.js";
6
6
  import {
7
7
  LibExecutor
8
- } from "./index-47qxw1tz.js";
8
+ } from "./index-681sx6nt.js";
9
9
 
10
10
  // pkgs/@akanjs/cli/semver.ts
11
- function parseVersion(version) {
11
+ var stripRangeOperator = (version) => version.replace(/^[\s^~>=<v]+/, "").trim();
12
+ var parseVersion = (version) => {
12
13
  return version.replace(/^[^\d]*/, "").split(/[.-]/).map((part) => Number.parseInt(part, 10)).map((part) => Number.isFinite(part) ? part : 0);
13
- }
14
- function compareSemver(a, b) {
14
+ };
15
+ var compareNumeric = (a, b) => {
15
16
  const left = parseVersion(a);
16
17
  const right = parseVersion(b);
17
18
  const length = Math.max(left.length, right.length);
@@ -21,7 +22,14 @@ function compareSemver(a, b) {
21
22
  return diff > 0 ? 1 : -1;
22
23
  }
23
24
  return 0;
24
- }
25
+ };
26
+ var compareSemver = (a, b) => {
27
+ try {
28
+ return Bun.semver.order(stripRangeOperator(a), stripRangeOperator(b));
29
+ } catch {
30
+ return compareNumeric(a, b);
31
+ }
32
+ };
25
33
 
26
34
  // pkgs/@akanjs/cli/library/library.runner.ts
27
35
  class LibraryRunner extends runner("library") {
@@ -70,7 +78,7 @@ class LibraryRunner extends runner("library") {
70
78
  return [dep, newerVersion];
71
79
  }));
72
80
  Object.keys(allDependencies).sort().forEach((dep) => {
73
- if (!!libPackageJson.dependencies?.[dep] || !!rootPackageJson.dependencies?.[dep])
81
+ if (libPackageJson.dependencies?.[dep] || rootPackageJson.dependencies?.[dep])
74
82
  dependencies[dep] = allDependencies[dep];
75
83
  else
76
84
  devDependencies[dep] = allDependencies[dep];
@@ -0,0 +1,255 @@
1
+ // @bun
2
+ // pkgs/@akanjs/devkit/artifact/implicitRootLayout.ts
3
+ import { mkdir } from "fs/promises";
4
+ import path from "path";
5
+ var LAYOUT_KEY_RE = /^\.\/(.+\/)?_layout\.(tsx|ts|jsx|js)$/;
6
+ async function appHasStModule(appCwdPath) {
7
+ return Bun.file(path.join(appCwdPath, "lib", "st.ts")).exists();
8
+ }
9
+ var IMPLICIT_LAYOUT_DIR = path.join(".akan", "generated", "root-layouts");
10
+ var IMPLICIT_DICT_DIR = path.join(".akan", "generated", "dict");
11
+ var IMPLICIT_OVERRIDES_DIR = path.join(".akan", "generated", "overrides");
12
+ var OVERRIDES_KEY_RE = /^\.\/(.+\/)?_overrides\.(tsx|ts|jsx|js)$/;
13
+ async function writeGeneratedOverridesLayoutFile(opts) {
14
+ const filename = `${opts.key.replace(/^\.\//, "").replace(/[^a-zA-Z0-9]+/g, "_")}.tsx`;
15
+ const absPath = path.join(path.resolve(opts.appCwdPath), IMPLICIT_OVERRIDES_DIR, filename);
16
+ const userRel = path.relative(path.dirname(absPath), opts.userAbsPath).split(path.sep).join("/");
17
+ const userSpecifier = userRel.startsWith(".") ? userRel : `./${userRel}`;
18
+ const source = `"use client";
19
+ import { UiOverrideProvider } from "akanjs/ui";
20
+ import { createElement, type ReactNode } from "react";
21
+ import value from ${JSON.stringify(userSpecifier)};
22
+
23
+ export default function AkanUiOverridesLayout({ children }: { children?: ReactNode }) {
24
+ return createElement(UiOverrideProvider, { value }, children);
25
+ }
26
+ `;
27
+ await Bun.write(absPath, source);
28
+ return absPath;
29
+ }
30
+ function getRootBoundarySegments(key) {
31
+ const match = LAYOUT_KEY_RE.exec(key);
32
+ if (!match)
33
+ return null;
34
+ const prefix = match[1]?.replace(/\/$/, "");
35
+ if (!prefix)
36
+ return [];
37
+ return prefix.split("/").filter(Boolean);
38
+ }
39
+ function implicitRootLayoutKey(segments) {
40
+ return `./${[...segments, "__root_layout"].join("/")}.tsx`;
41
+ }
42
+ function implicitRootLayoutAbsPath(appCwdPath, segments) {
43
+ const filename = segments.length ? `${segments.join("__")}__root_layout.tsx` : "__root_layout.tsx";
44
+ return path.join(path.resolve(appCwdPath), IMPLICIT_LAYOUT_DIR, filename);
45
+ }
46
+ function implicitDictionaryMacroAbsPath(appCwdPath) {
47
+ return path.join(path.resolve(appCwdPath), IMPLICIT_DICT_DIR, "useDict.ts");
48
+ }
49
+ function isRootBoundarySegments(segments, basePaths) {
50
+ const firstVisibleIndex = segments.findIndex((segment) => !/^\(.+\)$/.test(segment));
51
+ if (firstVisibleIndex === -1)
52
+ return segments.length <= 1;
53
+ if (segments.slice(firstVisibleIndex + 1).some((segment) => /^\(.+\)$/.test(segment)))
54
+ return false;
55
+ const visible = segments.slice(firstVisibleIndex);
56
+ const allowedBasePaths = new Set([...basePaths].map((basePath) => basePath.trim()).filter(Boolean));
57
+ return visible.length === 1 && (firstVisibleIndex > 0 || allowedBasePaths.has(visible[0] ?? ""));
58
+ }
59
+ function findRootBoundaries(pageKeys, appCwdPath, basePaths) {
60
+ const boundaries = new Map;
61
+ for (const key of pageKeys) {
62
+ const segments = getRootBoundarySegments(key);
63
+ if (!segments)
64
+ continue;
65
+ if (!isRootBoundarySegments(segments, basePaths))
66
+ continue;
67
+ const id = segments.join("/");
68
+ boundaries.set(id, {
69
+ sourceKey: key,
70
+ sourceAbsPath: path.resolve(appCwdPath, "page", key.replace(/^\.\//, "")),
71
+ segments
72
+ });
73
+ }
74
+ const hasExplicitRootBoundary = [...boundaries.values()].some((boundary) => boundary.segments.length === 0);
75
+ if (!hasExplicitRootBoundary && boundaries.size === 0) {
76
+ boundaries.set("", { sourceKey: null, sourceAbsPath: null, segments: [] });
77
+ }
78
+ return [...boundaries.values()].sort((a, b) => a.segments.join("/").localeCompare(b.segments.join("/")));
79
+ }
80
+ function hasAncestorRootBoundary(boundary, boundaries) {
81
+ return boundaries.some((candidate) => candidate !== boundary && candidate.segments.length < boundary.segments.length && candidate.segments.every((segment, index) => boundary.segments[index] === segment));
82
+ }
83
+ function findExplicitRootLayoutAbsPath(pageKeys, appCwdPath) {
84
+ const rootLayoutKey = pageKeys.find((key) => {
85
+ const segments = getRootBoundarySegments(key);
86
+ return segments !== null && segments.length === 0;
87
+ });
88
+ return rootLayoutKey ? path.resolve(appCwdPath, "page", rootLayoutKey.replace(/^\.\//, "")) : null;
89
+ }
90
+ function routePrefixForSegments(segments) {
91
+ const visible = segments.filter((segment) => !/^\(.+\)$/.test(segment));
92
+ return visible[0] ?? null;
93
+ }
94
+ async function assertEnvClientConvention(appCwdPath, appName) {
95
+ const envPath = path.join(appCwdPath, "env", "env.client.ts");
96
+ if (!await Bun.file(envPath).exists()) {
97
+ throw new Error(`[route-convention] app "${appName}" must provide env/env.client.ts exporting "env" for generated System.Provider`);
98
+ }
99
+ }
100
+ async function writeGeneratedDictionaryMacroFile(appCwdPath, appName) {
101
+ const absPath = implicitDictionaryMacroAbsPath(appCwdPath);
102
+ await mkdir(path.dirname(absPath), { recursive: true });
103
+ await Bun.write(absPath, `import { getAllDictionary } from "@apps/${appName}/lib/dict" with { type: "macro" };
104
+
105
+ export const allDictionary = getAllDictionary();
106
+ `);
107
+ return absPath;
108
+ }
109
+ async function writeGeneratedRootLayoutFile(opts) {
110
+ await assertEnvClientConvention(opts.appCwdPath, opts.appName);
111
+ const dictMacroAbsPath = opts.includeSystemProvider ? await writeGeneratedDictionaryMacroFile(opts.appCwdPath, opts.appName) : null;
112
+ const absPath = implicitRootLayoutAbsPath(opts.appCwdPath, opts.boundary.segments);
113
+ await mkdir(path.dirname(absPath), { recursive: true });
114
+ const dictMacroRel = dictMacroAbsPath ? path.relative(path.dirname(absPath), dictMacroAbsPath).split(path.sep).join("/") : null;
115
+ const dictMacroSpecifier = dictMacroRel ? dictMacroRel.startsWith(".") ? dictMacroRel : `./${dictMacroRel}` : null;
116
+ const sourceRel = opts.boundary.sourceAbsPath ? path.relative(path.dirname(absPath), opts.boundary.sourceAbsPath).split(path.sep).join("/") : null;
117
+ const sourceSpecifier = sourceRel ? sourceRel.startsWith(".") ? sourceRel : `./${sourceRel}` : null;
118
+ const inheritedSourceAbsPath = opts.rootSourceAbsPath && opts.rootSourceAbsPath !== opts.boundary.sourceAbsPath ? opts.rootSourceAbsPath : null;
119
+ const inheritedSourceRel = inheritedSourceAbsPath ? path.relative(path.dirname(absPath), inheritedSourceAbsPath).split(path.sep).join("/") : null;
120
+ const inheritedSourceSpecifier = inheritedSourceRel ? inheritedSourceRel.startsWith(".") ? inheritedSourceRel : `./${inheritedSourceRel}` : null;
121
+ const clientImport = opts.includeStInit ? `import { st } from "@apps/${opts.appName}/client";
122
+ void st;
123
+ ` : `import "@apps/${opts.appName}/client";
124
+ `;
125
+ const inheritedImport = inheritedSourceSpecifier ? `import * as inheritedLayout from ${JSON.stringify(inheritedSourceSpecifier)};
126
+ ` : `const inheritedLayout = {};
127
+ `;
128
+ const prefix = routePrefixForSegments(opts.boundary.segments);
129
+ const userImport = sourceSpecifier ? `import UserLayout, * as userLayout from ${JSON.stringify(sourceSpecifier)};
130
+ ` : `const UserLayout = ({ children }) => children;
131
+ const userLayout = {};
132
+ `;
133
+ const source = opts.includeSystemProvider ? `import type { LayoutProps, PageProps } from "akanjs/client";
134
+ import { loadFonts } from "akanjs/client";
135
+ import { System } from "akanjs/ui";
136
+ import { env } from "@apps/${opts.appName}/env/env.client";
137
+ import { allDictionary } from ${JSON.stringify(dictMacroSpecifier)};
138
+ ${clientImport}${inheritedImport}${userImport}
139
+ const userFonts = userLayout.fonts ?? inheritedLayout.fonts ?? [];
140
+ const defaultFonts = userFonts.filter((font) => font.default);
141
+ if (defaultFonts.length > 1) throw new Error("[route-convention] only one default font is allowed per root layout");
142
+ const defaultFont = defaultFonts[0];
143
+ const defaultFontClassName = defaultFont ? (defaultFont.className ?? \`font-\${defaultFont.name}\`) : undefined;
144
+
145
+ export async function generateHead(props: PageProps) {
146
+ if (userLayout.generateHead) return userLayout.generateHead(props);
147
+ if (userLayout.head !== undefined) return userLayout.head;
148
+ if (inheritedLayout.generateHead) return inheritedLayout.generateHead(props);
149
+ return inheritedLayout.head;
150
+ }
151
+
152
+ export async function generateMetadata(props: PageProps) {
153
+ if (userLayout.generateMetadata) return userLayout.generateMetadata(props);
154
+ if (userLayout.metadata !== undefined) return userLayout.metadata;
155
+ if (inheritedLayout.generateMetadata) return inheritedLayout.generateMetadata(props);
156
+ return inheritedLayout.metadata;
157
+ }
158
+
159
+ export const NotFound = userLayout.NotFound ?? inheritedLayout.NotFound;
160
+ export const Error = userLayout.Error ?? inheritedLayout.Error;
161
+ export const pageConfig = userLayout.pageConfig ?? inheritedLayout.pageConfig;
162
+
163
+ export default function GeneratedLayout({ children, params, searchParams }: LayoutProps) {
164
+ return (
165
+ <System.Provider
166
+ of={GeneratedLayout as never}
167
+ appName=${JSON.stringify(opts.appName)}
168
+ ${prefix ? `prefix=${JSON.stringify(prefix)}
169
+ ` : ""}params={params}
170
+ manifest={userLayout.manifest ?? inheritedLayout.manifest}
171
+ env={env}
172
+ theme={userLayout.theme ?? inheritedLayout.theme}
173
+ fonts={loadFonts(userFonts)}
174
+ className={defaultFontClassName}
175
+ gaTrackingId={userLayout.gaTrackingId ?? inheritedLayout.gaTrackingId}
176
+ layoutStyle={userLayout.layoutStyle ?? inheritedLayout.layoutStyle}
177
+ reconnect={userLayout.reconnect ?? inheritedLayout.reconnect ?? false}
178
+ wsConnect={userLayout.wsConnect ?? inheritedLayout.wsConnect ?? true}
179
+ allDictionary={process.env.AKAN_PUBLIC_RENDER_ENV === "ssr" ? allDictionary : undefined}
180
+ >
181
+ <UserLayout params={params} searchParams={searchParams}>{children}</UserLayout>
182
+ </System.Provider>
183
+ );
184
+ }
185
+ ` : `import type { LayoutProps, PageProps } from "akanjs/client";
186
+ ${inheritedImport}${userImport}
187
+ export async function generateHead(props: PageProps) {
188
+ if (userLayout.generateHead) return userLayout.generateHead(props);
189
+ if (userLayout.head !== undefined) return userLayout.head;
190
+ if (inheritedLayout.generateHead) return inheritedLayout.generateHead(props);
191
+ return inheritedLayout.head;
192
+ }
193
+
194
+ export async function generateMetadata(props: PageProps) {
195
+ if (userLayout.generateMetadata) return userLayout.generateMetadata(props);
196
+ if (userLayout.metadata !== undefined) return userLayout.metadata;
197
+ if (inheritedLayout.generateMetadata) return inheritedLayout.generateMetadata(props);
198
+ return inheritedLayout.metadata;
199
+ }
200
+
201
+ export const NotFound = userLayout.NotFound ?? inheritedLayout.NotFound;
202
+ export const Error = userLayout.Error ?? inheritedLayout.Error;
203
+ export const pageConfig = userLayout.pageConfig ?? inheritedLayout.pageConfig;
204
+
205
+ export default function GeneratedLayout({ children, params, searchParams }: LayoutProps) {
206
+ return <UserLayout params={params} searchParams={searchParams}>{children}</UserLayout>;
207
+ }
208
+ `;
209
+ await Bun.write(absPath, source);
210
+ return absPath;
211
+ }
212
+ async function resolveSsrPageEntries(opts) {
213
+ const absPageDir = path.resolve(opts.appCwdPath, "page");
214
+ const hasSt = await appHasStModule(opts.appCwdPath);
215
+ const basePaths = opts.basePaths ?? [];
216
+ const rootSourceAbsPath = findExplicitRootLayoutAbsPath(opts.pageKeys, opts.appCwdPath);
217
+ const rootBoundaries = findRootBoundaries(opts.pageKeys, opts.appCwdPath, basePaths);
218
+ const rootLayoutKeys = new Set(opts.pageKeys.filter((key) => {
219
+ const segments = getRootBoundarySegments(key);
220
+ return segments !== null && isRootBoundarySegments(segments, basePaths);
221
+ }));
222
+ const base = await Promise.all(opts.pageKeys.filter((key) => !rootLayoutKeys.has(key)).map(async (key) => {
223
+ const userAbsPath = path.resolve(absPageDir, key);
224
+ if (OVERRIDES_KEY_RE.test(key)) {
225
+ const moduleAbsPath = await writeGeneratedOverridesLayoutFile({
226
+ appCwdPath: opts.appCwdPath,
227
+ key,
228
+ userAbsPath
229
+ });
230
+ return { key, moduleAbsPath, seedAbsPaths: [userAbsPath] };
231
+ }
232
+ return { key, moduleAbsPath: userAbsPath };
233
+ }));
234
+ const generated = await Promise.all(rootBoundaries.map(async (boundary) => ({
235
+ key: implicitRootLayoutKey(boundary.segments),
236
+ moduleAbsPath: await writeGeneratedRootLayoutFile({
237
+ appCwdPath: opts.appCwdPath,
238
+ appName: opts.appName,
239
+ boundary,
240
+ rootSourceAbsPath,
241
+ includeStInit: hasSt && boundary.segments.length === 0,
242
+ includeSystemProvider: !hasAncestorRootBoundary(boundary, rootBoundaries)
243
+ }),
244
+ seedAbsPaths: [...new Set([boundary.sourceAbsPath, rootSourceAbsPath].filter((absPath) => absPath !== null))]
245
+ })));
246
+ const entries = [...base, ...generated];
247
+ entries.sort((a, b) => a.key.localeCompare(b.key));
248
+ return entries;
249
+ }
250
+ async function resolveSsrPageEntriesForApp(app, pageKeys) {
251
+ const config = await app.getConfig();
252
+ return resolveSsrPageEntries({ appCwdPath: app.cwdPath, appName: app.name, pageKeys, basePaths: config.basePaths });
253
+ }
254
+
255
+ export { getRootBoundarySegments, isRootBoundarySegments, resolveSsrPageEntriesForApp };
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  AppExecutor,
4
4
  LibExecutor
5
- } from "./index-47qxw1tz.js";
5
+ } from "./index-681sx6nt.js";
6
6
 
7
7
  // pkgs/@akanjs/devkit/workflow/utils.ts
8
8
  var jsonText = (value, { trailingNewline = true } = {}) => `${JSON.stringify(value, null, 2)}${trailingNewline ? `
@@ -1,22 +1,25 @@
1
1
  // @bun
2
2
  import {
3
3
  AkanContextAnalyzer
4
- } from "./index-jn9vfpwz.js";
4
+ } from "./index-wc19q8mb.js";
5
5
  import {
6
6
  Prompter
7
- } from "./index-qp089jp0.js";
7
+ } from "./index-j37qq1f2.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
  AGENT_BLOCK_END,
14
14
  AGENT_BLOCK_START,
15
15
  AppExecutor,
16
+ CLAUDE_COMMENT_RULE,
16
17
  LibExecutor,
18
+ readDevkitVersion,
17
19
  renderRecipeEntries,
20
+ stampBlockVersion,
18
21
  upsertAgentBlock
19
- } from "./index-47qxw1tz.js";
22
+ } from "./index-681sx6nt.js";
20
23
  import {
21
24
  collectRecipeSources,
22
25
  scanRecipes
@@ -103,19 +106,33 @@ ${scopeIndexPointer}
103
106
 
104
107
  `;
105
108
  };
109
+ var renderGuides = async (context) => {
110
+ const conventions = (await Prompter.getInstruction("conventions")).trim();
111
+ if (context.pkgs.some((pkg) => pkg.name === "akanjs"))
112
+ return conventions;
113
+ const onboarding = (await Prompter.getInstruction("workspaceOnboarding")).trim();
114
+ const appName = context.apps[0]?.name ?? "app";
115
+ return `${conventions}
116
+
117
+ ${onboarding.replaceAll("<%= appName %>", appName)}`;
118
+ };
106
119
  var renderManagedBlock = async (workspace) => {
107
120
  const context = await AkanContextAnalyzer.analyze(workspace);
108
121
  const frameworkGuide = await Prompter.getInstruction("framework");
109
122
  const appNames = context.apps.map((app) => app.name);
110
123
  const sampleCleanup = await renderSampleCleanup(workspace, appNames);
111
124
  const recipeIndex = await renderRecipeIndex(workspace);
112
- return `## Workspace
125
+ const guides = await renderGuides(context);
126
+ const version = await readDevkitVersion();
127
+ const block = `## Workspace
113
128
 
114
129
  - Repo: ${context.repoName}
115
130
  - Apps: ${context.apps.map((app) => app.name).join(", ") || "none"}
116
131
  - Libraries: ${context.libs.map((lib) => lib.name).join(", ") || "none"}
117
132
  - Packages: ${context.pkgs.map((pkg) => pkg.name).join(", ") || "none"}
118
133
 
134
+ ${guides}
135
+
119
136
  ${sampleCleanup}## Akan Module Abstracts
120
137
 
121
138
  - Before changing a domain, service, or scalar module, read its \`*.abstract.md\` file first.
@@ -148,7 +165,19 @@ ${context.validationCommands.map((command) => `- \`${command}\``).join(`
148
165
 
149
166
  ## Framework Guide
150
167
 
151
- ${frameworkGuide.trim()}`;
168
+ ${frameworkGuide.trim()}
169
+
170
+ ## Before You Finish
171
+
172
+ 1. \`bun run akan lint <appName>\` \u2014 Tailwind class order, \`Err\`, \`console\`, \`#private\` scope, unused imports.
173
+ 2. \`bun run akan typecheck <appName>\` \u2014 server/client boundary violations.
174
+ 3. \`bun run akan sync <appName>\` if you added, renamed, or deleted any file.
175
+ 4. Did you write or change a \`.tsx\` file? \`bun run akan quality ssr\` \u2014 did the server share hold, and did you add
176
+ a \`"use client"\` you cannot justify?
177
+ 5. Re-read the file you wrote against its section above.
178
+ 6. Did you add a comment? Delete it unless it documents an external constraint or a security decision.
179
+ 7. Did behavior or an invariant change? Update the module's \`*.abstract.md\`.`;
180
+ return version ? stampBlockVersion(block, version) : block;
152
181
  };
153
182
  var renderAgentsMd = async (workspace, existing) => {
154
183
  const block = await renderManagedBlock(workspace);
@@ -171,6 +200,8 @@ var renderClaudeMd = async (workspace) => {
171
200
  return `# ${context.repoName} \u2014 Claude Code Guide
172
201
 
173
202
  @AGENTS.md
203
+
204
+ ${CLAUDE_COMMENT_RULE}
174
205
  `;
175
206
  };
176
207
  var renderCursorRule = () => `---
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  getDirname
4
- } from "./index-47qxw1tz.js";
4
+ } from "./index-1577bej2.js";
5
5
 
6
6
  // pkgs/@akanjs/devkit/prompter.ts
7
7
  import fsPromise from "fs/promises";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  runner,
4
4
  script
5
- } from "./index-jkynkyfk.js";
5
+ } from "./index-ckpwq052.js";
6
6
 
7
7
  // pkgs/@akanjs/cli/page/page.runner.ts
8
8
  class PageRunner extends runner("page") {
@@ -849,6 +849,7 @@ class ClientEntriesBundler {
849
849
  #externalSubpaths;
850
850
  #externalAliases;
851
851
  #command;
852
+ #target;
852
853
  #outputSubdir;
853
854
  #reactFastRefresh;
854
855
  #artifactDir;
@@ -870,6 +871,7 @@ class ClientEntriesBundler {
870
871
  this.#externalSubpaths = options.externalSubpaths ?? [];
871
872
  this.#externalAliases = options.externalAliases ?? {};
872
873
  this.#command = options.command ?? "start";
874
+ this.#target = options.target ?? "browser";
873
875
  this.#outputSubdir = options.outputSubdir ?? "client";
874
876
  this.#reactFastRefresh = options.reactFastRefresh ?? false;
875
877
  this.#artifactDir = `${this.#command === "build" ? this.#app.dist.cwdPath : this.#app.cwdPath}/.akan/artifact`;
@@ -883,7 +885,7 @@ class ClientEntriesBundler {
883
885
  entrypoints: this.#opaqueEntries.entries,
884
886
  outdir: this.#outdir,
885
887
  splitting: true,
886
- target: "browser",
888
+ target: this.#target,
887
889
  format: "esm",
888
890
  naming: CLIENT_BUNDLE_NAMING,
889
891
  metafile: true,
@@ -1117,7 +1119,8 @@ var VENDOR_SPECIFIERS = [
1117
1119
  "akanjs/store",
1118
1120
  "akanjs/base",
1119
1121
  "akanjs/common",
1120
- "akanjs/constant"
1122
+ "akanjs/constant",
1123
+ "akanjs/fetch"
1121
1124
  ];
1122
1125
 
1123
1126
  // pkgs/@akanjs/devkit/frontendBuild/routeClientBuilder.ts
@@ -1226,12 +1229,11 @@ class RouteClientBuilder {
1226
1229
  }).bundle();
1227
1230
  }
1228
1231
  async#buildSsrBundle(bootstrapEntries) {
1229
- const externalOptions = RouteClientBuilder.resolveSsrClientExternalOptions(this.#command);
1230
1232
  return new ClientEntriesBundler({
1231
1233
  app: this.#app,
1232
1234
  entries: bootstrapEntries.buildEntries,
1233
1235
  plugins: [await createBarrelImportsPlugin(this.#app)],
1234
- ...externalOptions,
1236
+ ...RouteClientBuilder.resolveSsrClientBundleOptions(this.#command),
1235
1237
  outputSubdir: "client-ssr",
1236
1238
  command: this.#command
1237
1239
  }).bundle();
@@ -1293,15 +1295,16 @@ ${defaultNames.map((name) => `export default ${name};`).join(`
1293
1295
  const serverEntry = RouteClientBuilder.resolveAkanServerEntry();
1294
1296
  return { [Bun.resolveSync("akanjs/fetch", serverEntry)]: "akanjs/fetch" };
1295
1297
  }
1296
- static resolveSsrClientExternalOptions(command) {
1298
+ static resolveSsrClientBundleOptions(command) {
1297
1299
  if (command === "start") {
1298
1300
  return {
1301
+ target: "bun",
1299
1302
  external: SSR_CLIENT_EXTERNALS,
1300
1303
  externalSubpaths: ["akanjs/fetch"],
1301
1304
  externalAliases: RouteClientBuilder.resolveSsrClientRuntimeAliases()
1302
1305
  };
1303
1306
  }
1304
- return { external: SSR_CLIENT_ALIAS_EXTERNALS };
1307
+ return { target: "bun", external: SSR_CLIENT_ALIAS_EXTERNALS };
1305
1308
  }
1306
1309
  static resolveAkanServerEntry() {
1307
1310
  try {