@akanjs/cli 3.0.0-alpha.1 → 3.0.0-alpha.11

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 (88) hide show
  1. package/.build-stamp +1 -1
  2. package/{agent.command-yv00p0s0.js → agent.command-a3n15c6t.js} +7 -6
  3. package/{application.command-0qsczf4k.js → application.command-rdm3et0g.js} +5 -4
  4. package/{applicationBuildRunner-ct2pxyvw.js → applicationBuildRunner-6m8n71w4.js} +3 -3
  5. package/buildBatch.proc.js +4 -3
  6. package/{capacitorApp-4r9sm3qg.js → capacitorApp-mr81qdxq.js} +5 -2
  7. package/{cloud.command-dxfv18sa.js → cloud.command-56aeekqn.js} +8 -7
  8. package/{context.command-8d9e3k6b.js → context.command-ysxawe7h.js} +14 -13
  9. package/getDirname-m9s0cmhq.js +8 -0
  10. package/{guideline.command-3jbkxzh6.js → guideline.command-yqf9a372.js} +5 -4
  11. package/guidelines/conventions/conventions.generate.json +25 -0
  12. package/guidelines/conventions/conventions.instruction.md +825 -0
  13. package/guidelines/cssRule/cssRule.instruction.md +7 -0
  14. package/guidelines/framework/framework.instruction.md +1 -0
  15. package/guidelines/workspaceOnboarding/workspaceOnboarding.generate.json +24 -0
  16. package/guidelines/workspaceOnboarding/workspaceOnboarding.instruction.md +974 -0
  17. package/incrementalBuilder.proc.js +3 -2
  18. package/index-1577bej2.js +7 -0
  19. package/{index-1pvex4az.js → index-3789fdpg.js} +13 -13
  20. package/{index-ec09pws3.js → index-4mgkgba3.js} +3 -3
  21. package/{index-bbkek1bp.js → index-65aeh789.js} +1 -1
  22. package/{index-7c6k4yvg.js → index-8pd02prk.js} +2 -2
  23. package/{index-t3723f99.js → index-9va8zayb.js} +86 -17
  24. package/{index-nm6wghb6.js → index-a5cs7d8r.js} +5 -5
  25. package/{index-e16gnn26.js → index-bzznxgcx.js} +7 -7
  26. package/{index-pyt2b4nw.js → index-cav1azma.js} +103 -22
  27. package/{index-2q1f5j9k.js → index-cv9cxs5k.js} +3 -3
  28. package/{index-a00jg8x8.js → index-e4b2ae6b.js} +49 -32
  29. package/{index-8hsbnyes.js → index-etwh7sd3.js} +4 -2
  30. package/{index-k95xkh4p.js → index-h5whaj26.js} +2 -2
  31. package/{index-tdbas9r0.js → index-j37qq1f2.js} +1 -1
  32. package/{index-rh16j3c7.js → index-j9cxndc0.js} +3 -2
  33. package/{index-rzwcpcc3.js → index-kcsa1zff.js} +1 -1
  34. package/{index-bekddz9q.js → index-m90fn8xe.js} +4 -4
  35. package/{index-yzmhasdb.js → index-mewacxye.js} +7 -7
  36. package/{index-zasydjxd.js → index-nwqqssnb.js} +8 -10
  37. package/{index-mr5s7mqd.js → index-yzmqvg23.js} +3 -3
  38. package/{index-hgna5rjy.js → index-yzsxc30b.js} +94 -47
  39. package/{index-ej426mcr.js → index-z1s5f4e0.js} +34 -6
  40. package/index.js +19 -18
  41. package/{library.command-ebdj1vnm.js → library.command-x6t29a30.js} +4 -3
  42. package/{localRegistry.command-gb178ne8.js → localRegistry.command-649g1n7b.js} +7 -6
  43. package/{module.command-9c1bnsx4.js → module.command-8w8ys5t3.js} +7 -6
  44. package/{package.command-t93p4jkj.js → package.command-zgy7f3fz.js} +4 -3
  45. package/package.json +2 -2
  46. package/{page.command-k3k0meh2.js → page.command-yjmnkyk2.js} +4 -3
  47. package/{primitive.command-de6nktdt.js → primitive.command-gfqaagsg.js} +8 -7
  48. package/{quality.command-z5kth2wa.js → quality.command-ec8r1dn3.js} +369 -128
  49. package/{repair.command-ehf2g112.js → repair.command-p9ey6mkm.js} +6 -5
  50. package/{routeSourceValidator-cncd92fv.js → routeSourceValidator-e4jmbfcx.js} +2 -38
  51. package/{scalar.command-7a2jtv33.js → scalar.command-9dhmqhtm.js} +6 -5
  52. package/templates/app/page/styles.css.template +3 -3
  53. package/templates/appSample/srvkit/AuthGuard.ts +9 -5
  54. package/templates/appSample/srvkit/SessionInternalArg.ts +4 -3
  55. package/templates/crudPages/[__model__Id]/edit/page.tsx +1 -1
  56. package/templates/crudPages/new/page.tsx +1 -1
  57. package/templates/crudSinglePage/page.tsx +1 -1
  58. package/templates/lib/db.ts +3 -1
  59. package/templates/lib/useClient.ts +9 -3
  60. package/templates/module/__Model__.Util.tsx +1 -1
  61. package/templates/module/__Model__.Zone.tsx +3 -5
  62. package/templates/workspaceRoot/AGENTS.md.template +0 -948
  63. package/templates/workspaceRoot/biome.json.template +4 -198
  64. package/templates/workspaceRoot/docs/AI-DEVELOPMENT.md.template +4 -1
  65. package/{workflow.command-e0tt0vk2.js → workflow.command-ycwc6zr6.js} +13 -12
  66. package/{workspace.command-fpda0evj.js → workspace.command-xhyhajxa.js} +67 -48
  67. package/templates/libRoot/base/baseLogic.ts +0 -14
  68. package/templates/libRoot/base/index.ts +0 -8
  69. package/templates/workspaceRoot/.cursor/rules/akan-page-routing.mdc.template +0 -43
  70. package/templates/workspaceRoot/.cursor/rules/akan-sync-conventions.mdc.template +0 -33
  71. package/templates/workspaceRoot/.cursor/rules/application-test-commands.mdc.template +0 -16
  72. package/templates/workspaceRoot/.cursor/rules/change-scope.mdc.template +0 -12
  73. package/templates/workspaceRoot/.cursor/rules/client-server-boundaries.mdc.template +0 -18
  74. package/templates/workspaceRoot/.cursor/rules/coding-comments.mdc.template +0 -25
  75. package/templates/workspaceRoot/.cursor/rules/coding-style.mdc.template +0 -44
  76. package/templates/workspaceRoot/.cursor/rules/domain-module-conventions.mdc.template +0 -17
  77. package/templates/workspaceRoot/.cursor/rules/format-lint.mdc.template +0 -12
  78. package/templates/workspaceRoot/.cursor/rules/lint-enforced-rules.mdc.template +0 -18
  79. package/templates/workspaceRoot/.cursor/rules/module-file-playbook.mdc.template +0 -61
  80. package/templates/workspaceRoot/.cursor/rules/naming-conventions.mdc.template +0 -15
  81. package/templates/workspaceRoot/.cursor/rules/react-component-style.mdc.template +0 -21
  82. package/templates/workspaceRoot/.cursor/rules/repo-overview.mdc.template +0 -17
  83. package/templates/workspaceRoot/.cursor/rules/scalar-modeling.mdc.template +0 -58
  84. package/templates/workspaceRoot/.cursor/rules/secrets-and-env.mdc.template +0 -13
  85. package/templates/workspaceRoot/.cursor/rules/service-signal-conventions.mdc.template +0 -83
  86. package/templates/workspaceRoot/.cursor/rules/srvkit-adapters-and-guards.mdc.template +0 -50
  87. package/templates/workspaceRoot/.cursor/rules/ssr-first.mdc.template +0 -59
  88. package/templates/workspaceRoot/.cursor/rules/typescript-imports.mdc.template +0 -16
@@ -1,215 +1,21 @@
1
1
  {
2
- "$schema": "https://biomejs.dev/schemas/2.5.2/schema.json",
3
- "vcs": {
4
- "enabled": true,
5
- "clientKind": "git",
6
- "useIgnoreFile": false
7
- },
2
+ "$schema": "https://biomejs.dev/schemas/2.5.8/schema.json",
3
+ "extends": ["@akanjs/devkit/biome.base.json"],
8
4
  "files": {
9
5
  "includes": [
10
6
  "**/*.ts",
11
7
  "**/*.tsx",
12
8
  "**/*.json",
13
9
  "**/*.jsonc",
14
- "!**/env.client.local.ts",
15
- "!**/env.client.debug.ts",
16
- "!**/env.client.develop.ts",
17
- "!**/env.client.main.ts",
18
- "!**/env.client.testing.ts",
19
- "!**/env.server.local.ts",
20
- "!**/env.server.develop.ts",
21
- "!**/env.server.main.ts",
22
- "!**/env.server.testing.ts",
23
- "!**/env.server.type.ts",
24
- "!apps/*/lib/cnst.ts",
25
- "!apps/*/lib/dict.ts",
26
- "!apps/*/lib/db.ts",
27
- "!apps/*/lib/srv.ts",
28
- "!apps/*/lib/st.ts",
29
- "!apps/*/lib/sig.ts",
30
- "!apps/*/lib/useClient.ts",
31
- "!apps/*/lib/useServer.ts",
32
- "!apps/*/client.ts",
33
- "!apps/*/server.ts",
34
- "!apps/*/lib/*/index.tsx",
35
- "!libs/*/lib/cnst.ts",
36
- "!libs/*/lib/dict.ts",
37
- "!libs/*/lib/db.ts",
38
- "!libs/*/lib/srv.ts",
39
- "!libs/*/lib/st.ts",
40
- "!libs/*/lib/sig.ts",
41
- "!libs/*/lib/useClient.ts",
42
- "!libs/*/lib/useServer.ts",
43
- "!libs/*/client.ts",
44
- "!libs/*/server.ts",
45
- "!libs/*/index.ts",
46
- "!libs/*/lib/*/index.tsx",
47
10
  "!infra/master/createRecords.ts",
48
11
  "!pkgs/contract/env.ts",
49
12
  "!!**/node_modules",
50
13
  "!!**/dist",
51
14
  "!!**/.akan",
15
+ "!!**/.claude",
52
16
  "!!**/dump",
53
17
  "!!**/local",
54
18
  "!!**/ios/DerivedData"
55
19
  ]
56
- },
57
- "formatter": {
58
- "enabled": true,
59
- "indentStyle": "space",
60
- "indentWidth": 2,
61
- "lineWidth": 120
62
- },
63
- "linter": {
64
- "enabled": true,
65
- "rules": {
66
- "preset": "recommended",
67
- "suspicious": {
68
- "noConsole": {
69
- "level": "error",
70
- "options": {
71
- "allow": ["assert", "error", "info", "warn"]
72
- }
73
- },
74
- "noArrayIndexKey": "off",
75
- "noShadowRestrictedNames": "off",
76
- "noUnnecessaryConditions": {
77
- "level": "error"
78
- }
79
- },
80
- "correctness": {
81
- "noUnusedFunctionParameters": "off",
82
- "noUnusedImports": {
83
- "level": "error",
84
- "fix": "safe"
85
- },
86
- "useParseIntRadix": "off",
87
- "useExhaustiveDependencies": "off",
88
- "useHookAtTopLevel": "off"
89
- },
90
- "nursery": {
91
- "useSortedClasses": {
92
- "level": "error",
93
- "fix": "safe",
94
- "options": {
95
- "attributes": ["classList"],
96
- "functions": ["clsx", "cn"]
97
- }
98
- }
99
- },
100
- "a11y": "off",
101
- "complexity": {
102
- "noStaticOnlyClass": "off"
103
- },
104
- "style": {
105
- "useTemplate": {
106
- "level": "warn",
107
- "fix": "safe"
108
- }
109
- }
110
- },
111
- "domains": {
112
- "project": "recommended",
113
- "react": "recommended",
114
- "test": "recommended",
115
- "types": "all"
116
- }
117
- },
118
- "javascript": {
119
- "parser": {
120
- "unsafeParameterDecoratorsEnabled": true
121
- },
122
- "formatter": {
123
- "quoteStyle": "double"
124
- }
125
- },
126
- "assist": {
127
- "enabled": true,
128
- "actions": {
129
- "source": {
130
- "organizeImports": "on"
131
- }
132
- }
133
- },
134
- "overrides": [
135
- {
136
- "includes": [
137
- "apps/**/*.ts",
138
- "apps/**/*.tsx",
139
- "libs/**/*.ts",
140
- "libs/**/*.tsx",
141
- "!**/*.test.ts",
142
- "!**/*.test.tsx",
143
- "!**/*.spec.ts",
144
- "!**/*.spec.tsx",
145
- "!**/*.constant.ts",
146
- "!**/common/**"
147
- ],
148
- "plugins": ["./node_modules/@akanjs/devkit/lint/no-throw-raw-error.grit"]
149
- },
150
- {
151
- "includes": ["**/page/**/*.ts", "**/page/**/*.tsx", "**/*.Unit.tsx", "**/*.View.tsx"],
152
- "plugins": [
153
- "./node_modules/@akanjs/devkit/lint/no-import-client-functions.grit",
154
- "./node_modules/@akanjs/devkit/lint/no-use-client-in-server.grit"
155
- ]
156
- },
157
- {
158
- "includes": ["**/page/**/*.ts", "**/page/**/*.tsx"],
159
- "plugins": ["./node_modules/@akanjs/devkit/lint/non-scalar-props-restricted.grit"]
160
- },
161
- {
162
- "includes": ["**/*.constant.ts", "**/*.document.ts", "**/*.service.ts", "**/*.store.ts"],
163
- "plugins": ["./node_modules/@akanjs/devkit/lint/no-js-private-class-method.grit"]
164
- },
165
- {
166
- "includes": ["**/*.signal.ts"],
167
- "plugins": ["./node_modules/@akanjs/devkit/lint/no-redeclare-predefined-endpoint.grit"]
168
- },
169
- {
170
- "includes": [
171
- "**/*.constant.ts",
172
- "**/*.dictionary.ts",
173
- "**/*.document.ts",
174
- "**/*.service.ts",
175
- "**/*.signal.ts",
176
- "**/*.store.ts",
177
- "**/*.Template.tsx",
178
- "**/*.Unit.tsx",
179
- "**/*.Util.tsx",
180
- "**/*.View.tsx",
181
- "**/*.Zone.tsx"
182
- ],
183
- "plugins": ["./node_modules/@akanjs/devkit/lint/no-deep-internal-import.grit"]
184
- },
185
- {
186
- "includes": [
187
- "**/page/**/*.ts",
188
- "**/page/**/*.tsx",
189
- "**/index.ts",
190
- "**/index.tsx",
191
- "**/cnst.ts",
192
- "**/db.ts",
193
- "**/dict.ts",
194
- "**/option.ts",
195
- "**/sig.ts",
196
- "**/srv.ts",
197
- "**/st.ts",
198
- "**/*.constant.ts",
199
- "**/*.dictionary.ts",
200
- "**/*.document.ts",
201
- "**/*.service.ts",
202
- "**/*.signal.ts",
203
- "**/*.signal.test.ts",
204
- "**/*.service.test.ts",
205
- "**/*.store.ts",
206
- "**/*.Template.tsx",
207
- "**/*.Unit.tsx",
208
- "**/*.Util.tsx",
209
- "**/*.View.tsx",
210
- "**/*.Zone.tsx"
211
- ],
212
- "plugins": ["./node_modules/@akanjs/devkit/lint/no-import-external-library.grit"]
213
- }
214
- ]
20
+ }
215
21
  }
@@ -49,8 +49,11 @@ See `docs/GENERATED.md` for the generated file list.
49
49
 
50
50
  `AGENTS.md` holds the full style guide. The rules agents break most often:
51
51
 
52
- - **Never hand-order Tailwind classes** — the linter sorts them, including inside `clsx()`, and its output looks
52
+ - **Never hand-order Tailwind classes** — the linter sorts them, including inside `cn()`, and its output looks
53
53
  unnatural on purpose.
54
+ - **Never use a colour outside the semantic vocabulary** — `bg-red-500`, `bg-[#3b82f6]` and `text-base-content`
55
+ compile to no CSS at all, so the element renders unstyled with no error. Use `bg-primary`, `text-foreground/70`
56
+ and the other tokens defined in `page/*/styles.css`.
54
57
  - **Never `throw new Error`** — throw `new Err("<module>.error.<key>")` with an `[en, ko]` entry in the module
55
58
  dictionary. `common/` cannot import `Err`, so keep throwing code out of it.
56
59
  - **Never import a third-party package** from a page, a barrel, or a module file. Re-export it through a one-line
@@ -1,32 +1,33 @@
1
1
  // @bun
2
2
  import {
3
3
  WorkflowRunner
4
- } from "./index-2q1f5j9k.js";
4
+ } from "./index-cv9cxs5k.js";
5
+ import {
6
+ ScalarScript
7
+ } from "./index-4mgkgba3.js";
5
8
  import {
6
9
  PrimitiveScript
7
- } from "./index-bekddz9q.js";
10
+ } from "./index-m90fn8xe.js";
8
11
  import {
9
12
  ModuleScript
10
- } from "./index-yzmhasdb.js";
11
- import"./index-bbkek1bp.js";
12
- import {
13
- ScalarScript
14
- } from "./index-ec09pws3.js";
13
+ } from "./index-mewacxye.js";
15
14
  import"./index-ss469dec.js";
15
+ import"./index-65aeh789.js";
16
16
  import"./index-0cj2zxbm.js";
17
- import"./index-a00jg8x8.js";
17
+ import"./index-e4b2ae6b.js";
18
18
  import {
19
19
  createWorkflowStepRegistry
20
- } from "./index-rzwcpcc3.js";
21
- import"./index-tdbas9r0.js";
20
+ } from "./index-kcsa1zff.js";
21
+ import"./index-j37qq1f2.js";
22
22
  import {
23
23
  Workspace,
24
24
  command,
25
25
  script
26
- } from "./index-8hsbnyes.js";
27
- import"./index-hgna5rjy.js";
26
+ } from "./index-etwh7sd3.js";
27
+ import"./index-yzsxc30b.js";
28
28
  import"./index-mxvakhsm.js";
29
29
  import"./index-xys926f2.js";
30
+ import"./index-1577bej2.js";
30
31
  import"./index-67546d0j.js";
31
32
  import"./index-r24hmh0q.js";
32
33
 
@@ -1,48 +1,48 @@
1
1
  // @bun
2
2
  import {
3
3
  ContextScript
4
- } from "./index-1pvex4az.js";
5
- import"./index-mr5s7mqd.js";
6
- import"./index-2q1f5j9k.js";
7
- import"./index-bekddz9q.js";
8
- import"./index-yzmhasdb.js";
9
- import"./index-bbkek1bp.js";
4
+ } from "./index-3789fdpg.js";
5
+ import"./index-yzmqvg23.js";
6
+ import"./index-cv9cxs5k.js";
7
+ import"./index-4mgkgba3.js";
8
+ import"./index-m90fn8xe.js";
9
+ import"./index-mewacxye.js";
10
+ import"./index-ss469dec.js";
11
+ import"./index-65aeh789.js";
10
12
  import {
11
13
  CloudScript
12
- } from "./index-nm6wghb6.js";
14
+ } from "./index-a5cs7d8r.js";
13
15
  import {
14
16
  getLatestPackageVersion,
15
17
  getNpmRegistryUrl
16
- } from "./index-zasydjxd.js";
18
+ } from "./index-nwqqssnb.js";
17
19
  import {
18
20
  PackageScript
19
- } from "./index-k95xkh4p.js";
20
- import"./index-ec09pws3.js";
21
- import"./index-ss469dec.js";
22
- import"./index-t3723f99.js";
21
+ } from "./index-h5whaj26.js";
22
+ import"./index-9va8zayb.js";
23
23
  import {
24
24
  GlobalConfig
25
25
  } from "./index-0cj2zxbm.js";
26
26
  import {
27
27
  AgentScript
28
- } from "./index-ej426mcr.js";
29
- import"./index-a00jg8x8.js";
30
- import"./index-rzwcpcc3.js";
31
- import"./index-tdbas9r0.js";
28
+ } from "./index-z1s5f4e0.js";
29
+ import"./index-e4b2ae6b.js";
30
+ import"./index-kcsa1zff.js";
31
+ import"./index-j37qq1f2.js";
32
32
  import {
33
33
  ApplicationScript
34
- } from "./index-e16gnn26.js";
35
- import"./index-76rn3g2c.js";
34
+ } from "./index-bzznxgcx.js";
36
35
  import {
37
36
  LibraryScript
38
- } from "./index-7c6k4yvg.js";
37
+ } from "./index-8pd02prk.js";
38
+ import"./index-76rn3g2c.js";
39
39
  import {
40
40
  Exec,
41
41
  Workspace,
42
42
  command,
43
43
  runner,
44
44
  script
45
- } from "./index-8hsbnyes.js";
45
+ } from "./index-etwh7sd3.js";
46
46
  import"./index-fgc8r6dj.js";
47
47
  import {
48
48
  ThemeValidator,
@@ -59,24 +59,26 @@ import {
59
59
  collectScopeRecipeSources,
60
60
  extractAgentBlock,
61
61
  renderScopeAgentBlock
62
- } from "./index-hgna5rjy.js";
62
+ } from "./index-yzsxc30b.js";
63
63
  import"./index-mxvakhsm.js";
64
64
  import {
65
65
  collectRecipeSources,
66
66
  scanRecipes
67
67
  } from "./index-xys926f2.js";
68
+ import"./index-1577bej2.js";
68
69
  import"./index-46tjzh6s.js";
69
70
  import {
70
71
  FileSys
71
72
  } from "./index-67546d0j.js";
72
73
  import"./index-r24hmh0q.js";
73
74
 
74
- // pkgs/@akanjs/cli/workspace/workspace.script.ts
75
- import path2 from "path";
76
- import { Logger } from "akanjs/common";
77
-
78
75
  // pkgs/@akanjs/cli/workspace/workspace.runner.ts
79
76
  import path from "path";
77
+
78
+ // pkgs/@akanjs/devkit/biomeBase.ts
79
+ var biomeVersion = "2.5.8";
80
+
81
+ // pkgs/@akanjs/cli/workspace/workspace.runner.ts
80
82
  var defaultWorkspacePeerDependencies = new Set([
81
83
  "@react-spring/web",
82
84
  "@use-gesture/react",
@@ -93,6 +95,7 @@ var defaultWorkspacePeerDependencies = new Set([
93
95
  "tailwindcss",
94
96
  "typescript"
95
97
  ]);
98
+ var defaultMaxDiagnostics = 200;
96
99
 
97
100
  class WorkspaceRunner extends runner("workspace") {
98
101
  async generateAgentRules(workspace, { overwrite = false, cursorRules = true } = {}) {
@@ -113,17 +116,14 @@ class WorkspaceRunner extends runner("workspace") {
113
116
  dict,
114
117
  overwrite
115
118
  }));
116
- if (!cursorRules)
117
- return created;
118
- return [
119
- ...created,
120
- ...await workspace.applyTemplate({
119
+ if (cursorRules)
120
+ created.push(...await workspace.applyTemplate({
121
121
  basePath: ".cursor/rules",
122
122
  template: "workspaceRoot/.cursor/rules/akan.mdc.template",
123
123
  dict,
124
124
  overwrite
125
- })
126
- ];
125
+ }));
126
+ return created;
127
127
  }
128
128
  async createWorkspace(repoName, appName, {
129
129
  dirname = ".",
@@ -137,10 +137,7 @@ class WorkspaceRunner extends runner("workspace") {
137
137
  const normalizedRegistryUrl = registryUrl ? getNpmRegistryUrl(registryUrl) : undefined;
138
138
  const workspace = WorkspaceExecutor.fromRoot({ workspaceRoot, repoName });
139
139
  const templateSpinner = workspace.spinning(`Creating workspace template files in ${dirname}/${repoName}...`);
140
- const [latestBiomeVersion, latestTypesBunVersion] = await Promise.all([
141
- getLatestPackageVersion("@biomejs/biome", "latest", normalizedRegistryUrl),
142
- getLatestPackageVersion("@types/bun", "latest", normalizedRegistryUrl)
143
- ]);
140
+ const latestTypesBunVersion = await getLatestPackageVersion("@types/bun", "latest", normalizedRegistryUrl);
144
141
  await workspace.applyTemplate({
145
142
  basePath: ".",
146
143
  template: "workspaceRoot",
@@ -164,7 +161,7 @@ class WorkspaceRunner extends runner("workspace") {
164
161
  },
165
162
  devDependencies: {
166
163
  ...rootPackageJson.devDependencies,
167
- "@biomejs/biome": latestBiomeVersion,
164
+ "@biomejs/biome": biomeVersion,
168
165
  "@types/bun": latestTypesBunVersion,
169
166
  "@akanjs/devkit": akanVersion,
170
167
  ...typescript ? { typescript } : {}
@@ -236,17 +233,28 @@ class WorkspaceRunner extends runner("workspace") {
236
233
  }
237
234
  throw new Error(`[workspace] failed to locate akanjs package.json from ${import.meta.dir}`);
238
235
  }
239
- async lint(exec, workspace, { fix = true } = {}) {
236
+ async lint(exec, workspace, { fix = true, maxDiagnostics = defaultMaxDiagnostics } = {}) {
237
+ const configPath = await WorkspaceRunner.resolveBiomeConfigPath(workspace);
240
238
  await workspace.spawn("./node_modules/.bin/biome", [
241
239
  "check",
242
240
  ...fix ? ["--write"] : [],
243
241
  "--no-errors-on-unmatched",
242
+ `--max-diagnostics=${maxDiagnostics > 0 ? maxDiagnostics : "none"}`,
243
+ ...configPath ? ["--config-path", configPath] : [],
244
244
  exec.cwdPath
245
245
  ]);
246
246
  await this.#enforceStyleContract(exec);
247
247
  await this.#enforceRecipeGate(exec);
248
248
  await this.#enforceAgentsIndex(exec);
249
249
  }
250
+ static async resolveBiomeConfigPath(workspace) {
251
+ for (const fileName of ["biome.json", "biome.jsonc"]) {
252
+ const configPath = path.join(workspace.workspaceRoot, fileName);
253
+ if (await Bun.file(configPath).exists())
254
+ return configPath;
255
+ }
256
+ return null;
257
+ }
250
258
  async#enforceAgentsIndex(exec) {
251
259
  if (!(exec instanceof SysExecutor))
252
260
  return;
@@ -314,6 +322,8 @@ AKAN_PUBLIC_LOG_LEVEL=debug
314
322
  }
315
323
 
316
324
  // pkgs/@akanjs/cli/workspace/workspace.script.ts
325
+ import path2 from "path";
326
+ import { Logger } from "akanjs/common";
317
327
  class WorkspaceScript extends script("workspace", [
318
328
  WorkspaceRunner,
319
329
  ApplicationScript,
@@ -372,30 +382,33 @@ class WorkspaceScript extends script("workspace", [
372
382
  async generateAgentRules(workspace, { overwrite = false, cursorRules = true } = {}) {
373
383
  const spinner = workspace.spinning("Generating agent rules...");
374
384
  const files = await this.workspaceRunner.generateAgentRules(workspace, { overwrite, cursorRules });
385
+ if (files.some((file) => file.filePath.endsWith("AGENTS.md")))
386
+ await this.agentScript.agent(workspace, "install", "agents-md", { force: overwrite });
375
387
  spinner.succeed(`Agent rules ready (${files.length} file${files.length === 1 ? "" : "s"})`);
376
388
  }
377
- async lint(exec, workspace, { fix = true } = {}) {
389
+ async lint(exec, workspace, { fix = true, maxDiagnostics } = {}) {
378
390
  if (exec instanceof AppExecutor)
379
391
  await this.applicationScript.sync(exec);
380
392
  else if (exec instanceof LibExecutor)
381
393
  await this.libraryScript.syncLibrary(exec);
382
394
  const spinner = workspace.spinning(`Linting${fix ? " with fix" : ""}...`);
383
395
  try {
384
- await this.workspaceRunner.lint(exec, workspace, { fix });
396
+ await this.workspaceRunner.lint(exec, workspace, { fix, maxDiagnostics });
385
397
  spinner.succeed("Lint completed with no errors");
386
398
  } catch (error) {
387
399
  spinner.fail("Lint failed with errors");
388
400
  throw error;
389
401
  }
390
402
  }
391
- async lintAll(workspace, { fix = true } = {}) {
403
+ async lintAll(workspace, { fix = true, maxDiagnostics } = {}) {
392
404
  const [appNames, libNames, pkgNames] = await workspace.getExecs();
405
+ const options = { fix, maxDiagnostics };
393
406
  await Promise.all(appNames.map((appName) => this.applicationScript.sync(AppExecutor.from(workspace, appName))));
394
407
  await Promise.all(libNames.map((libName) => this.libraryScript.syncLibrary(LibExecutor.from(workspace, libName))));
395
408
  await Promise.all([
396
- ...appNames.map((appName) => this.workspaceRunner.lint(AppExecutor.from(workspace, appName), workspace, { fix })),
397
- ...libNames.map((libName) => this.workspaceRunner.lint(LibExecutor.from(workspace, libName), workspace, { fix })),
398
- ...pkgNames.filter((pkgName) => pkgName !== "contract").map((pkgName) => this.workspaceRunner.lint(PkgExecutor.from(workspace, pkgName), workspace, { fix }))
409
+ ...appNames.map((appName) => this.workspaceRunner.lint(AppExecutor.from(workspace, appName), workspace, options)),
410
+ ...libNames.map((libName) => this.workspaceRunner.lint(LibExecutor.from(workspace, libName), workspace, options)),
411
+ ...pkgNames.filter((pkgName) => pkgName !== "contract").map((pkgName) => this.workspaceRunner.lint(PkgExecutor.from(workspace, pkgName), workspace, options))
399
412
  ]);
400
413
  }
401
414
  async syncAll(workspace) {
@@ -477,11 +490,17 @@ class WorkspaceCommand extends command("workspace", [WorkspaceScript], ({ public
477
490
  }).option("overwrite", Boolean, { desc: "Overwrite existing agent rule files", default: false }).option("cursorRules", Boolean, { desc: "Generate .cursor/rules/akan.mdc", default: true }).with(Workspace).exec(async function(overwrite, cursorRules, workspace) {
478
491
  await this.workspaceScript.generateAgentRules(workspace, { overwrite, cursorRules });
479
492
  }),
480
- lint: target({ desc: "Lint and fix code in a specific app/lib/pkg" }).with(Exec).option("fix", Boolean, { default: true }).with(Workspace).exec(async function(exec, fix, workspace) {
481
- await this.workspaceScript.lint(exec, workspace, { fix });
493
+ lint: target({ desc: "Lint and fix code in a specific app/lib/pkg" }).with(Exec).option("fix", Boolean, { default: true }).option("maxDiagnostics", Number, {
494
+ desc: "How many diagnostics Biome prints before truncating (0 for no limit)",
495
+ default: defaultMaxDiagnostics
496
+ }).with(Workspace).exec(async function(exec, fix, maxDiagnostics, workspace) {
497
+ await this.workspaceScript.lint(exec, workspace, { fix, maxDiagnostics });
482
498
  }),
483
- lintAll: target({ desc: "Lint and fix code in all apps and libraries" }).option("fix", Boolean, { default: true }).with(Workspace).exec(async function(fix, workspace) {
484
- await this.workspaceScript.lintAll(workspace, { fix });
499
+ lintAll: target({ desc: "Lint and fix code in all apps and libraries" }).option("fix", Boolean, { default: true }).option("maxDiagnostics", Number, {
500
+ desc: "How many diagnostics Biome prints before truncating (0 for no limit)",
501
+ default: defaultMaxDiagnostics
502
+ }).with(Workspace).exec(async function(fix, maxDiagnostics, workspace) {
503
+ await this.workspaceScript.lintAll(workspace, { fix, maxDiagnostics });
485
504
  }),
486
505
  syncAll: target({ desc: "Sync dependencies and configuration for all apps and libraries" }).with(Workspace).exec(async function(workspace) {
487
506
  await this.workspaceScript.syncAll(workspace);
@@ -1,14 +0,0 @@
1
- interface Dict {
2
- libName: string;
3
- }
4
- export default function getContent(scanInfo: null, dict: Dict) {
5
- return `
6
- // 현 디렉토리에서는 프로젝트 내 전체적으로 사용되는 로직을 구현하며, 따라서 백/프론트 비의존적인 pure js 코드만 구현 가능합니다.
7
- // common폴더와 다른점은, base 코드는 시스템 전체에서 import되어 사용되므로, 가장 핵심적인 로직과 추상화된 기능만 구현해야합니다.
8
- // @${dict.libName}/base에서는 서버/클라이언트 관련 라이브러리(@*/server, @*/server, @*/client, @*/client)를 모두 import할 수 없으며, @*/base 라이브러리만 import 가능합니다.
9
-
10
- export const someBaseLogic = () => {
11
- //
12
- };
13
- `;
14
- }
@@ -1,8 +0,0 @@
1
- interface Dict {
2
- [key: string]: string;
3
- }
4
- export default function getContent(scanInfo: null, dict: Dict = {}) {
5
- return `
6
- export * from "./baseLogic";
7
- `;
8
- }
@@ -1,43 +0,0 @@
1
- ---
2
- description: Akan page routing conventions
3
- globs: apps/**/page/**/*.{ts,tsx,js,jsx}
4
- alwaysApply: false
5
- ---
6
-
7
- # Akan Page Routing
8
-
9
- - `apps/<app>/page` may contain route modules only. Do not add helper logic or component-only files there.
10
- - Route source files under `page/` must use `.tsx`. Do not add `logic.ts`, `.js`, or `.jsx` files under `page/`.
11
- - Route pages use `_index.tsx`; layouts use `_layout.tsx`.
12
- - Reserved `_*.tsx` route filenames are limited to `_index.tsx` and `_layout.tsx`; do not add files like `_Component.tsx` or `_helper.tsx`.
13
- - Page filenames must not start with an uppercase letter. Move helper components like `Component.tsx` to app `ui`, `common`, or `lib` instead.
14
- - Dynamic segments use `[id]`; route groups use directories like `(user)`, `(public)`, `(tab)`, or `(detail)`.
15
- - Page modules should usually export `default`, `pageConfig`, `head`, `generateHead`, or `Loading`.
16
- - Prefer `export default function Page` or `export default async function Page` for page components.
17
- - Before changing route behavior, check nearby routes for the expected pattern.
18
-
19
- ## Page Body Shape
20
-
21
- ```tsx
22
- interface PageProps {
23
- params: { taskId: string };
24
- }
25
-
26
- export default async function Page({ params }: PageProps) {
27
- const { l } = usePage();
28
- getSelf({ unauthorize: "/signin" });
29
- const { taskId } = params;
30
- const [{ task }] = await Promise.all([fetch.viewTask(taskId)]);
31
- return <Task.View.General task={task} />;
32
- }
33
-
34
- export const pageConfig = { transition: "stack" } satisfies PageConfig;
35
- ```
36
-
37
- - There is no `loader=` / `render=` page prop. Pages are `export default async function Page`.
38
- - Declare `interface PageProps { params: {...}; searchParams?: {...} }` immediately above the default export.
39
- - Body order: `usePage()`, auth, destructure params, fetch, return.
40
- - Run independent fetches through `Promise.all`, even when there is only one.
41
- - Gate auth at `_layout.tsx`; repeating `getSelf({ unauthorize: "/signin" })` in the page is fine and common.
42
- - Keep `async` even when nothing is awaited — it marks a real server page.
43
- - No `useState`, no `useEffect`, and no comments in page files.
@@ -1,33 +0,0 @@
1
- ---
2
- description: sync-enforced Akan app/lib layout and generated index conventions
3
- globs: apps/**/*,libs/**/*
4
- alwaysApply: false
5
- ---
6
-
7
- # Akan Sync Conventions
8
-
9
- - `apps/<appName>` root may only contain these files: `akan.app.json`, `akan.config.ts`, `capacitor.config.ts`, `client.ts`, `main.ts`, `package.json`, `server.ts`, `tsconfig.json`.
10
- - `apps/<appName>` root may only contain these folders: `.akan`, `android`, `common`, `env`, `ios`, `lib`, `page`, `private`, `public`, `script`, `srvkit`, `ui`, `webkit`.
11
- - Do not add `apps/*/base`; place shared app utilities under `apps/*/common`.
12
- - `apps/*/lib` and `libs/*/lib` root files are limited to generated/support files: `cnst.ts`, `db.ts`, `dict.ts`, `option.ts`, `sig.ts`, `srv.ts`, `st.ts`, `useClient.ts`, `useServer.ts`.
13
- - Domain module folders are `lib/<model>` for database modules, `lib/_<service>` for service modules, and `lib/__scalar/<scalar>` for scalar modules.
14
- - Database module UI files are limited to `<Model>.Template.tsx`, `<Model>.Unit.tsx`, `<Model>.Util.tsx`, `<Model>.View.tsx`, and `<Model>.Zone.tsx`.
15
- - Service module UI files are limited to `<Service>.Util.tsx` and `<Service>.Zone.tsx`.
16
- - Scalar module UI files are limited to `<Scalar>.Template.tsx` and `<Scalar>.Unit.tsx`.
17
- - Module `*.test.ts`, `*.test.tsx`, `*.spec.ts`, and `*.spec.tsx` files are allowed.
18
- - `ui/index.ts`, `webkit/index.ts`, `srvkit/index.ts`, `common/index.ts`, and module `lib/**/index.ts` files are generated by `akan sync`; do not hand-edit or track them.
19
- - Generated facet indexes export only 1-depth files/folders with `export * from "./name";`.
20
-
21
- ## Layer Placement
22
-
23
- | Folder | Admission test | Naming |
24
- |---|---|---|
25
- | `common/` | pure, isomorphic, zero-dependency; may import only sibling `common/*` and `akanjs/base`. Cannot import `Err`, so keep throwing code out of it. | camelCase file, filename equals the single export |
26
- | `webkit/` | touches `window` / `navigator` / Capacitor, or is a React hook | `use<Thing>.tsx` — `.tsx` even with no JSX |
27
- | `srvkit/` | touches `node:*`, `Bun`, `process.env`, a secret, or a server SDK | camelCase file, PascalCase class |
28
- | `ui/` | renders JSX and is not bound to one model | PascalCase component, camelCase sidecar (`swipeCard.util.ts`) |
29
-
30
- - Hooks return a named object of async closures, never a tuple.
31
- - Only layer-root `index.ts` barrels are generated. A `ui/<Folder>/index.tsx` that builds a namespace is hand-written source; the distinguishing test is that a generated barrel contains nothing but `export * from "./X";` lines.
32
- - `ui/<Folder>/index_.tsx` (trailing underscore) is the `"use client"` + `lazy()` boundary, with a server-safe `index.tsx` beside it. Collapsing the pair into one file breaks RSC.
33
- - Never add a sibling helper file inside `lib/<model>/`; helpers belong in one of the folders above.
@@ -1,16 +0,0 @@
1
- ---
2
- description: Application test commands after source changes
3
- alwaysApply: true
4
- ---
5
-
6
- # Application Test Commands
7
-
8
- - After changing application source code, test the app with `bun run akan start <appName>`.
9
- - Test production build generation with `bun run akan build <appName>`.
10
- - To test a built artifact locally, run it from the generated app directory with the required Akan runtime environment variables.
11
-
12
- ```bash
13
- cd dist/apps/<appName> && USE_AKANJS_PKGS=true AKAN_PUBLIC_REPO_NAME=akansoft AKAN_PUBLIC_SERVE_DOMAIN="akanjs.com" AKAN_PUBLIC_APP_NAME=seon AKAN_PUBLIC_ENV=local AKAN_PUBLIC_OPERATION_MODE=local SERVER_MODE=federation AKAN_PUBLIC_BASE_PATHS=operator,office,homepage bun main.js
14
- ```
15
-
16
- - Adjust `<appName>`, `AKAN_PUBLIC_APP_NAME`, and `AKAN_PUBLIC_BASE_PATHS` to match the app being tested.
@@ -1,12 +0,0 @@
1
- ---
2
- description: Keep edits scoped and avoid unrelated churn
3
- alwaysApply: true
4
- ---
5
-
6
- # Change Scope
7
-
8
- - Keep edits scoped to the requested task and the directly related files.
9
- - Do not reformat unrelated files or rewrite nearby code just for style.
10
- - Do not revert or overwrite unrelated user changes in a dirty working tree.
11
- - Prefer established nearby patterns over introducing a new abstraction.
12
- - Add new abstractions only when they remove real duplication or match an existing project pattern.