@akanjs/cli 3.0.0-beta.2 → 3.0.0-beta.21

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 (190) hide show
  1. package/.build-stamp +1 -1
  2. package/CodeAgent-q2m47rqp.js +9 -0
  3. package/CodeAgentRpcHost-p7h6n2hp.js +7 -0
  4. package/CodeAgentRpcListener-7p7z5dd7.js +97 -0
  5. package/CodeTui-pdqhc3sn.js +1457 -0
  6. package/README.md +3 -0
  7. package/TunnelShare-scf4e4pd.js +9 -0
  8. package/{agent.command-d2gfxfck.js → agent.command-ttn09rx3.js} +8 -9
  9. package/akanCode.js +102 -0
  10. package/application.command-7gweenv7.js +179 -0
  11. package/{applicationBuildRunner-kxwbssgn.js → applicationBuildRunner-38exmejd.js} +63 -64
  12. package/buildBatch.proc.js +26 -25
  13. package/cloud.command-bhztw7c2.js +95 -0
  14. package/cloud.script-aabyhgba.js +20 -0
  15. package/code.command-6s8c0k91.js +154 -0
  16. package/commandManifest.json +1 -1
  17. package/consoleToStderr-h5bryj94.js +7 -0
  18. package/context.command-phmgywt2.js +48 -0
  19. package/context.runner-yvyw5g2d.js +21 -0
  20. package/{dependencyScanner-shs82ynp.js → dependencyScanner-ye2e6pdz.js} +2 -2
  21. package/{devTui-40ggmd99.js → devTui-q7k7bakd.js} +122 -40
  22. package/fileSys-5ngz93ga.js +9 -0
  23. package/guideline.command-7jk47fgq.js +42 -0
  24. package/guidelines/agentRule/agentRule.instruction.md +209 -28
  25. package/guidelines/conventions/conventions.instruction.md +96 -29
  26. package/guidelines/fieldRule/fieldRule.instruction.md +1 -0
  27. package/guidelines/mcpRule/mcpRule.instruction.md +7 -5
  28. package/guidelines/queryRule/queryRule.instruction.md +17 -7
  29. package/guidelines/runtimeRule/runtimeRule.instruction.md +77 -3
  30. package/guidelines/ssrRule/ssrRule.instruction.md +4 -2
  31. package/guidelines/transportRule/transportRule.instruction.md +51 -0
  32. package/guidelines/workspaceRecipes/workspaceRecipes.instruction.md +66 -3
  33. package/incrementalBuilder.proc.js +31 -48
  34. package/{index-h7yw2z9n.js → index-0bq14vr1.js} +8 -14
  35. package/{index-259dsnz3.js → index-1db2cw0y.js} +5 -8
  36. package/index-22d57v4c.js +266 -0
  37. package/index-3hx1z96c.js +87 -0
  38. package/{index-kcxmv48c.js → index-3t7g9e4r.js} +45 -79
  39. package/{index-ne2qy0nk.js → index-4dn1p115.js} +12 -12
  40. package/{index-q0y2jq9j.js → index-5b6tavv3.js} +6 -3
  41. package/index-7cqjvraf.js +69 -0
  42. package/index-7md2g9vw.js +6 -0
  43. package/{index-zry5nz81.js → index-8kb5p54p.js} +51 -30
  44. package/{index-ktb5njgy.js → index-9629w7ns.js} +49 -99
  45. package/index-9dp031by.js +12 -0
  46. package/{index-a64esmtb.js → index-aadpbnt2.js} +172 -308
  47. package/{index-3d9y066c.js → index-bjwxs904.js} +9 -8
  48. package/index-c6eggbee.js +123 -0
  49. package/index-d0arnrm8.js +700 -0
  50. package/index-d2242ksy.js +99 -0
  51. package/{index-600zhnve.js → index-dg97qp24.js} +70 -200
  52. package/{index-92zztqy1.js → index-dy0jx9ay.js} +2 -17
  53. package/{index-w8kmx1b6.js → index-fgq75haa.js} +198 -290
  54. package/{index-2tv3fdx4.js → index-ga6hygxr.js} +944 -1333
  55. package/{index-by5gpp8x.js → index-hj6w4ka1.js} +2 -1
  56. package/index-hr5n7t4x.js +465 -0
  57. package/{index-hwkygn9s.js → index-khpfpcsd.js} +302 -33
  58. package/{index-7737gxcp.js → index-m0ms3n1c.js} +107 -241
  59. package/{index-ws5e0j51.js → index-mgfx3mfs.js} +43 -26
  60. package/index-p6pbz9n5.js +25 -0
  61. package/index-pp54p5zk.js +53 -0
  62. package/{index-j9yhg404.js → index-q44jbw48.js} +4 -7
  63. package/{index-mak3cd28.js → index-rmcw8yc8.js} +137 -255
  64. package/{index-pnqbkf5p.js → index-rnt66vym.js} +6 -2
  65. package/index-smme4r47.js +49 -0
  66. package/index-tgjy8xf3.js +187 -0
  67. package/index-v5eayqqw.js +2729 -0
  68. package/index-wa5jbxj1.js +760 -0
  69. package/{index-4edzf1gr.js → index-wp43xrjv.js} +77 -150
  70. package/{index-fz5q3gd7.js → index-ya5qbmyg.js} +10 -17
  71. package/index-yjkte9aj.js +1119 -0
  72. package/{index-gyd220p2.js → index-yy4s1j72.js} +554 -577
  73. package/{index-v0qh106m.js → index-z50k041j.js} +580 -862
  74. package/index.js +23 -22
  75. package/{library.command-nbsky672.js → library.command-ccb1cp92.js} +4 -5
  76. package/{localRegistry.command-yeq57wjr.js → localRegistry.command-ajb9n87j.js} +23 -42
  77. package/{module.command-29vqzrh8.js → module.command-5k6h407d.js} +8 -11
  78. package/{package.command-axv0abmn.js → package.command-e6ntvpez.js} +6 -7
  79. package/package.json +14 -6
  80. package/{page.command-vs9s3zrh.js → page.command-v4f90wb8.js} +4 -5
  81. package/{primitive.command-cbxmqbtc.js → primitive.command-g6km57q5.js} +9 -22
  82. package/prompter-ptaa3nk0.js +8 -0
  83. package/{quality.command-gmbs7nws.js → quality.command-de3p36pz.js} +205 -377
  84. package/{recipeScanner-fpagtgc1.js → recipeScanner-4b69ybe0.js} +1 -1
  85. package/{repair.command-bqsjptsj.js → repair.command-d3x1javq.js} +11 -35
  86. package/{routeSourceValidator-apyqw7wk.js → routeSourceValidator-7ycnfz0e.js} +0 -6
  87. package/{scalar.command-6k1vhe9s.js → scalar.command-7ezrac2b.js} +7 -10
  88. package/skills/akan-code/SKILL.md +130 -0
  89. package/skills/akan-debug/SKILL.md +42 -0
  90. package/skills/akan-deps/SKILL.md +50 -0
  91. package/skills/akan-err/SKILL.md +39 -0
  92. package/skills/akan-module/SKILL.md +45 -0
  93. package/skills/akan-scaffold/SKILL.md +76 -0
  94. package/skills/akan-scalar/SKILL.md +52 -0
  95. package/skills/akan-service/SKILL.md +34 -0
  96. package/skills/akan-store/SKILL.md +67 -0
  97. package/skills/akan-ui/SKILL.md +63 -0
  98. package/skills/akan-validate/SKILL.md +44 -0
  99. package/{subspace.command-fwjfcts7.js → subspace.command-ps71ynp6.js} +138 -67
  100. package/templates/__scalar/__model__/__model__.abstract.md.template +8 -0
  101. package/templates/appSample/lib/__scalar/workHistory/workHistory.abstract.ts +8 -39
  102. package/templates/appSample/lib/_noti/noti.abstract.ts +6 -29
  103. package/templates/appSample/lib/task/task.abstract.ts +12 -32
  104. package/templates/appSample/lib/task/task.signal.spec.ts +15 -18
  105. package/templates/appSample/lib/task/task.signal.test.ts +15 -1
  106. package/templates/appSample/lib/task/task.signal.ts +1 -1
  107. package/templates/appSample/srvkit/{AuthGuard.ts → guards.ts} +7 -4
  108. package/templates/appSample/srvkit/{SessionInternalArg.ts → internalArgs.ts} +6 -4
  109. package/templates/client.ts +7 -30
  110. package/templates/crudPages/[__model__Id]/edit/page.tsx +2 -1
  111. package/templates/crudPages/[__model__Id]/page.tsx +2 -1
  112. package/templates/crudPages/new/page.tsx +2 -1
  113. package/templates/crudPages/page.tsx +2 -1
  114. package/templates/crudSinglePage/page.tsx +2 -1
  115. package/templates/lib/__lib/lib.dictionary.ts +0 -2
  116. package/templates/lib/__lib/lib.document.ts +0 -2
  117. package/templates/lib/sig.ts +8 -30
  118. package/templates/localDev/docker-compose.yaml.template +3 -14
  119. package/templates/module/__model__.signal.ts +12 -4
  120. package/templates/pkgRoot/tsconfig.json.template +2 -7
  121. package/templates/server.ts +0 -2
  122. package/templates/service/__model__.abstract.md.template +8 -0
  123. package/templates/workspaceRoot/.gitignore.template +0 -1
  124. package/tunnel.command-hsrv2mny.js +129 -0
  125. package/{typeChecker-3xgrzc2v.js → typeChecker-px49mezc.js} +1 -1
  126. package/typecheck.proc.js +1 -1
  127. package/workflow.command-z2p32nmf.js +79 -0
  128. package/{workspace.command-8s050m0h.js → workspace.command-tmdqkrh0.js} +77 -109
  129. package/abstractCompactor-mjh5ppsq.js +0 -101
  130. package/application.command-pj2m7584.js +0 -204
  131. package/applicationReleasePackager-4yasxwv9.js +0 -244
  132. package/capacitorApp-36rbr858.js +0 -12
  133. package/cloud.command-jshwdq22.js +0 -93
  134. package/context.command-ez8a0zyz.js +0 -80
  135. package/devTuiView-c08ccbat.js +0 -9
  136. package/getDirname-dr3jz1xg.js +0 -7
  137. package/guideline.command-xmqwx8zm.js +0 -359
  138. package/guidelines/agentRule/agentRule.generate.json +0 -31
  139. package/guidelines/componentRule/componentRule.generate.json +0 -31
  140. package/guidelines/conventions/conventions.generate.json +0 -25
  141. package/guidelines/cssRule/cssRule.generate.json +0 -31
  142. package/guidelines/docPageRule/docPageRule.generate.json +0 -31
  143. package/guidelines/docPageRule/docPageRule.instruction.md +0 -25
  144. package/guidelines/docSyncRule/docSyncRule.generate.json +0 -31
  145. package/guidelines/docSyncRule/docSyncRule.instruction.md +0 -25
  146. package/guidelines/enumConstant/enumConstant.generate.json +0 -31
  147. package/guidelines/enumConstant/enumConstant.instruction.md +0 -28
  148. package/guidelines/fieldRule/fieldRule.generate.json +0 -31
  149. package/guidelines/framework/framework.generate.json +0 -32
  150. package/guidelines/mcpRule/mcpRule.generate.json +0 -35
  151. package/guidelines/modelConstant/modelConstant.generate.json +0 -32
  152. package/guidelines/modelDictionary/modelDictionary.generate.json +0 -32
  153. package/guidelines/modelDocument/modelDocument.generate.json +0 -31
  154. package/guidelines/modelService/modelService.generate.json +0 -31
  155. package/guidelines/modelSignal/modelSignal.generate.json +0 -31
  156. package/guidelines/modelStore/modelStore.generate.json +0 -31
  157. package/guidelines/modelTemplate/modelTemplate.generate.json +0 -31
  158. package/guidelines/modelUnit/modelUnit.generate.json +0 -31
  159. package/guidelines/modelUtil/modelUtil.generate.json +0 -31
  160. package/guidelines/modelView/modelView.generate.json +0 -31
  161. package/guidelines/modelZone/modelZone.generate.json +0 -31
  162. package/guidelines/moduleCodegen/moduleCodegen.generate.json +0 -31
  163. package/guidelines/moduleCodegen/moduleCodegen.instruction.md +0 -28
  164. package/guidelines/moduleOverview/moduleOverview.generate.json +0 -31
  165. package/guidelines/queryRule/queryRule.generate.json +0 -31
  166. package/guidelines/recipeRule/recipeRule.generate.json +0 -31
  167. package/guidelines/runtimeRule/runtimeRule.generate.json +0 -25
  168. package/guidelines/scalarConstant/scalarConstant.generate.json +0 -32
  169. package/guidelines/scalarDictionary/scalarDictionary.generate.json +0 -32
  170. package/guidelines/scalarModule/scalarModule.generate.json +0 -31
  171. package/guidelines/sharedUiUsage/sharedUiUsage.generate.json +0 -31
  172. package/guidelines/sharedUiUsage/sharedUiUsage.instruction.md +0 -25
  173. package/guidelines/ssrRule/ssrRule.generate.json +0 -31
  174. package/guidelines/transportRule/transportRule.generate.json +0 -31
  175. package/guidelines/utilUiUsage/utilUiUsage.generate.json +0 -31
  176. package/guidelines/utilUiUsage/utilUiUsage.instruction.md +0 -25
  177. package/guidelines/workspaceOnboarding/workspaceOnboarding.generate.json +0 -24
  178. package/guidelines/workspaceRecipes/workspaceRecipes.generate.json +0 -33
  179. package/index-2hq52jq3.js +0 -465
  180. package/index-47pj3aee.js +0 -76
  181. package/index-6wwzs1bc.js +0 -7
  182. package/index-8pm30m73.js +0 -841
  183. package/index-kn1h7p1x.js +0 -560
  184. package/index-meh558jy.js +0 -65
  185. package/index-rwg2aa4f.js +0 -229
  186. package/index-wt7qrtd4.js +0 -1516
  187. package/templates/__scalar/__model__/__model__.abstract.md +0 -28
  188. package/templates/module/__model__.abstract.md +0 -28
  189. package/templates/service/__model__.abstract.md +0 -28
  190. package/workflow.command-nwpcdc8p.js +0 -107
@@ -4,27 +4,29 @@ import {
4
4
  readDevkitVersion,
5
5
  rootAllowedFiles,
6
6
  rootAllowedDirs,
7
+ rootEntryHintOf,
7
8
  isScannedRootEntry,
8
9
  AppExecutor,
9
10
  LibExecutor
10
- } from "./index-2tv3fdx4.js";
11
+ } from "./index-ga6hygxr.js";
11
12
  import {
12
- FileSys
13
- } from "./index-q0y2jq9j.js";
13
+ FileSys2
14
+ } from "./index-5b6tavv3.js";
14
15
  import {
15
16
  collectRecipeSources2,
16
17
  scanRecipes2,
17
18
  findInlineRecipeDuplicates2
18
- } from "./index-by5gpp8x.js";
19
+ } from "./index-hj6w4ka1.js";
19
20
  import {
21
+ workflowPathsForPlan,
20
22
  workflowRunArtifactPath,
21
23
  workflowSyncDir
22
- } from "./index-gyd220p2.js";
24
+ } from "./index-yy4s1j72.js";
23
25
 
24
26
  // pkgs/@akanjs/devkit/akanContext.ts
25
27
  import { readdir } from "fs/promises";
26
28
  import path from "path";
27
- import { capitalize } from "akanjs/common";
29
+ import { capitalize, isRecord } from "akanjs/common";
28
30
  var guidelineResourceUri = (name) => `akan://guidelines/${name}`;
29
31
  var staticResourceList = [
30
32
  { uri: "akan://docs/framework", name: "Akan framework guide", mimeType: "text/markdown" },
@@ -52,16 +54,13 @@ var akanMcpInstallConfigPaths = {
52
54
  var cursorWorkspaceFolder = "$" + "{workspaceFolder}";
53
55
  var claudeProjectDir = "$CLAUDE_PROJECT_DIR";
54
56
  var akanMcpCommand = (mode, { cd } = {}) => cd ? `cd "${cd}" && akan mcp --mode ${mode}` : `akan mcp --mode ${mode}`;
55
- var createAkanCursorMcpServer = (mode = "readonly") => ({
57
+ var bashMcpServer = (mode, cd) => ({
56
58
  type: "stdio",
57
59
  command: "bash",
58
- args: ["-lc", akanMcpCommand(mode, { cd: cursorWorkspaceFolder })]
59
- });
60
- var createAkanClaudeMcpServer = (mode = "readonly") => ({
61
- type: "stdio",
62
- command: "bash",
63
- args: ["-lc", akanMcpCommand(mode, { cd: claudeProjectDir })]
60
+ args: ["-lc", akanMcpCommand(mode, { cd })]
64
61
  });
62
+ var createAkanCursorMcpServer = (mode = "readonly") => bashMcpServer(mode, cursorWorkspaceFolder);
63
+ var createAkanClaudeMcpServer = (mode = "readonly") => bashMcpServer(mode, claudeProjectDir);
65
64
  var createAkanMcpServer = (target, mode = "readonly") => target === "cursor" ? createAkanCursorMcpServer(mode) : createAkanClaudeMcpServer(mode);
66
65
  var akanCursorMcpServer = createAkanCursorMcpServer();
67
66
  var codexMcpServerTableHeader = "[mcp_servers.akan]";
@@ -164,41 +163,13 @@ var moduleShapeFiles = (module) => {
164
163
  ];
165
164
  };
166
165
  var constantFieldNames = (content) => [...content.matchAll(/\b([A-Za-z_$][\w$]*)\s*:\s*field\(/g)].map((match) => match[1]).filter(Boolean);
167
- var safeReadDir = async (dirPath) => {
168
- try {
169
- return (await readdir(dirPath, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name));
170
- } catch {
171
- return [];
172
- }
173
- };
174
- var safeReadText = async (filePath) => {
175
- try {
176
- return await FileSys.readText(filePath);
177
- } catch {
178
- return null;
179
- }
180
- };
181
- var safeReadJson = async (filePath) => {
182
- try {
183
- return await FileSys.readJson(filePath);
184
- } catch {
185
- return null;
186
- }
187
- };
188
- var isWorkflowPlan = (value) => typeof value === "object" && value !== null && ("schemaVersion" in value) && value.schemaVersion === 1 && ("mode" in value) && value.mode === "plan";
189
- var isWorkflowApplyReport = (value) => typeof value === "object" && value !== null && ("schemaVersion" in value) && value.schemaVersion === 1 && ("mode" in value) && (value.mode === "apply" || value.mode === "dry-run");
166
+ var safeReadDir = async (dirPath) => (await readdir(dirPath, { withFileTypes: true }).catch(() => [])).sort((a, b) => a.name.localeCompare(b.name));
167
+ var safeReadText = (filePath) => FileSys2.readText(filePath).catch(() => null);
168
+ var safeReadJson = (filePath) => FileSys2.readJson(filePath).catch(() => null);
169
+ var isWorkflowPlan = (value) => typeof value === "object" && value !== null && ("schemaVersion" in value) && value.schemaVersion === 1 && ("mode" in value) && value.mode === "plan" && ("inputs" in value) && isRecord(value.inputs) && ("predictedChanges" in value) && Array.isArray(value.predictedChanges) && value.predictedChanges.every((change) => isRecord(change) && typeof change.target === "string");
170
+ var isPathList = (value) => Array.isArray(value) && value.every((file) => isRecord(file) && typeof file.path === "string");
171
+ var isWorkflowApplyReport = (value) => typeof value === "object" && value !== null && ("schemaVersion" in value) && value.schemaVersion === 1 && ("mode" in value) && (value.mode === "apply" || value.mode === "dry-run") && ("changedFiles" in value) && isPathList(value.changedFiles) && ("generatedFiles" in value) && isPathList(value.generatedFiles) && ("plan" in value) && isWorkflowPlan(value.plan);
190
172
  var isWorkflowRunArtifact = (value) => typeof value === "object" && value !== null && ("schemaVersion" in value) && value.schemaVersion === 1;
191
- var planInputString = (plan, key) => {
192
- const value = plan.inputs[key];
193
- return typeof value === "string" ? value : "";
194
- };
195
- var expandWorkflowTarget = (target, plan) => {
196
- const app = planInputString(plan, "app");
197
- const module = planInputString(plan, "module");
198
- const moduleClass = module ? capitalize(module) : "<Module>";
199
- return target.replace(/^\*\//, app ? `apps/${app}/` : "").replaceAll("<module>", module || "<module>").replaceAll("<Module>", moduleClass);
200
- };
201
- var workflowPathsForPlan = (plan) => plan.predictedChanges.map((change) => expandWorkflowTarget(change.target, plan));
202
173
  var workflowPathsForArtifact = (artifact) => {
203
174
  if (isWorkflowPlan(artifact))
204
175
  return workflowPathsForPlan(artifact);
@@ -209,7 +180,7 @@ var workflowPathsForArtifact = (artifact) => {
209
180
  ...workflowPathsForPlan(artifact.plan)
210
181
  ];
211
182
  }
212
- if ("mode" in artifact && artifact.mode === "validate" && artifact.plan)
183
+ if ("mode" in artifact && artifact.mode === "validate" && isWorkflowPlan(artifact.plan))
213
184
  return workflowPathsForPlan(artifact.plan);
214
185
  return [];
215
186
  };
@@ -310,13 +281,13 @@ var getSysModules = async (workspace, sys, {
310
281
  const serviceName = entry.name.replace(/^_+/, "");
311
282
  if (moduleFilter && moduleFilter !== serviceName && moduleFilter !== entry.name)
312
283
  continue;
313
- if (!await FileSys.fileExists(path.join(libPath, entry.name, `${serviceName}.service.ts`)))
284
+ if (!await FileSys2.fileExists(path.join(libPath, entry.name, `${serviceName}.service.ts`)))
314
285
  continue;
315
286
  modules.push(await createModuleContext(workspace, sys, "service", entry.name, serviceName, includeAbstractContent));
316
287
  } else {
317
288
  if (moduleFilter && moduleFilter !== entry.name)
318
289
  continue;
319
- if (!await FileSys.fileExists(path.join(libPath, entry.name, `${entry.name}.constant.ts`)))
290
+ if (!await FileSys2.fileExists(path.join(libPath, entry.name, `${entry.name}.constant.ts`)))
320
291
  continue;
321
292
  modules.push(await createModuleContext(workspace, sys, "domain", entry.name, entry.name, includeAbstractContent));
322
293
  }
@@ -327,7 +298,7 @@ var getSysModules = async (workspace, sys, {
327
298
  continue;
328
299
  if (moduleFilter && moduleFilter !== entry.name)
329
300
  continue;
330
- if (!await FileSys.fileExists(path.join(scalarRoot, entry.name, `${entry.name}.constant.ts`)))
301
+ if (!await FileSys2.fileExists(path.join(scalarRoot, entry.name, `${entry.name}.constant.ts`)))
331
302
  continue;
332
303
  modules.push(await createModuleContext(workspace, sys, "scalar", entry.name, entry.name, includeAbstractContent));
333
304
  }
@@ -339,7 +310,7 @@ var getSysContext = async (workspace, type, name, options) => {
339
310
  type,
340
311
  name,
341
312
  path: `${type}s/${name}`,
342
- hasConfig: await FileSys.fileExists(path.join(sys.cwdPath, "akan.config.ts")),
313
+ hasConfig: await FileSys2.fileExists(path.join(sys.cwdPath, "akan.config.ts")),
343
314
  modules: await getSysModules(workspace, sys, {
344
315
  includeAbstractContent: options.includeAbstractContent,
345
316
  module: options.module
@@ -411,62 +382,47 @@ class AkanContextAnalyzer {
411
382
  repairAction("generated", "akan repair generated --app <app-or-lib>", "Refresh generated Akan files.", true),
412
383
  repairAction("format", "akan repair format --target <app-or-lib-or-pkg>", "Run the formatter/linter repair path.", true)
413
384
  ];
385
+ const report = (diagnostic, action) => {
386
+ diagnostics.push({ ...diagnostic, repairActions: [action] });
387
+ repairActions.push(action);
388
+ };
414
389
  for (const sys of [...context.apps, ...context.libs]) {
415
390
  const sysPath = path.join(workspace.workspaceRoot, sys.path);
416
391
  for (const entry of await safeReadDir(sysPath)) {
417
392
  if (!isScannedRootEntry(sys.type, entry.name))
418
393
  continue;
419
394
  const allowed = entry.isDirectory() ? rootAllowedDirs[sys.type].has(entry.name) : rootAllowedFiles[sys.type].has(entry.name);
420
- if (!allowed) {
421
- const action = repairAction("module-shape", `akan repair module-shape --app ${sys.name}`, `Review ${sys.type} root shape and remove or move the unknown entry.`, false);
422
- diagnostics.push({
395
+ const rootEntryHint = rootEntryHintOf(sys.type, entry.name);
396
+ if (!allowed)
397
+ report({
423
398
  severity: "error",
424
399
  code: `${sys.type}-root-unknown-entry`,
425
400
  path: `${sys.path}/${entry.name}`,
426
- message: `Unexpected ${entry.isDirectory() ? "folder" : "file"} in ${sys.type} root: ${sys.path}/${entry.name}`,
427
- repairActions: [action]
428
- });
429
- repairActions.push(action);
430
- }
401
+ message: `Unexpected ${entry.isDirectory() ? "folder" : "file"} in ${sys.type} root: ${sys.path}/${entry.name}${rootEntryHint ? ` (${rootEntryHint})` : ""}`
402
+ }, repairAction("module-shape", `akan repair module-shape --app ${sys.name}`, `Review ${sys.type} root shape and remove or move the unknown entry.`, false));
431
403
  }
432
404
  }
433
405
  const agentDrift = await AkanContextAnalyzer.#agentGuideDrift(workspace);
434
- if (agentDrift) {
435
- const action = repairAction("generated", "akan agent install agents-md", agentDrift.hint, true);
436
- diagnostics.push({
437
- severity: "warning",
438
- code: agentDrift.code,
439
- path: "AGENTS.md",
440
- message: agentDrift.message,
441
- repairActions: [action]
442
- });
443
- repairActions.push(action);
444
- }
406
+ if (agentDrift)
407
+ report({ severity: "warning", code: agentDrift.code, path: "AGENTS.md", message: agentDrift.message }, repairAction("generated", "akan agent install agents-md", agentDrift.hint, true));
445
408
  for (const sys of [...context.apps, ...context.libs]) {
446
409
  for (const module of sys.modules) {
447
- if (!module.abstract.exists) {
448
- const action = repairAction("module-shape", `akan repair module-shape --app ${sys.name} --module ${module.name}`, "Create the missing module abstract or inspect required source files.", false);
449
- diagnostics.push({
410
+ const moduleShapeCommand = `akan repair module-shape --app ${sys.name} --module ${module.name}`;
411
+ if (!module.abstract.exists)
412
+ report({
450
413
  severity: strict ? "error" : "warning",
451
414
  code: "module-abstract-missing",
452
415
  path: module.abstract.path,
453
- message: `${capitalize(module.kind)} module ${sys.name}:${module.name} should include ${module.abstract.path}`,
454
- repairActions: [action]
455
- });
456
- repairActions.push(action);
457
- }
416
+ message: `${capitalize(module.kind)} module ${sys.name}:${module.name} should include ${module.abstract.path}`
417
+ }, repairAction("module-shape", moduleShapeCommand, "Create the missing module abstract or inspect required source files.", false));
458
418
  const missingFiles = moduleShapeFiles(module).filter((filename) => !module.files.includes(filename));
459
- if (missingFiles.length) {
460
- const action = repairAction("module-shape", `akan repair module-shape --app ${sys.name} --module ${module.name}`, "Review missing required module source files.", false);
461
- diagnostics.push({
419
+ if (missingFiles.length)
420
+ report({
462
421
  severity: "error",
463
422
  code: "module-shape-invalid",
464
423
  path: module.path,
465
- message: `${capitalize(module.kind)} module ${sys.name}:${module.name} is missing required files: ${missingFiles.join(", ")}`,
466
- repairActions: [action]
467
- });
468
- repairActions.push(action);
469
- }
424
+ message: `${capitalize(module.kind)} module ${sys.name}:${module.name} is missing required files: ${missingFiles.join(", ")}`
425
+ }, repairAction("module-shape", moduleShapeCommand, "Review missing required module source files.", false));
470
426
  if (module.kind !== "service" && module.files.includes(`${module.name}.dictionary.ts`)) {
471
427
  const constantPath = path.join(workspace.workspaceRoot, module.path, `${module.name}.constant.ts`);
472
428
  const dictionaryPath = path.join(workspace.workspaceRoot, module.path, `${module.name}.dictionary.ts`);
@@ -478,15 +434,12 @@ class AkanContextAnalyzer {
478
434
  for (const fieldName of constantFieldNames(constantContent)) {
479
435
  if (new RegExp(`\\b${fieldName}\\s*:`).test(dictionaryContent))
480
436
  continue;
481
- const action = repairAction("dictionary", `akan repair dictionary --app ${sys.name} --module ${module.name}`, "Add missing dictionary labels for source constant fields.", false);
482
- diagnostics.push({
437
+ report({
483
438
  severity: "warning",
484
439
  code: "dictionary-label-missing",
485
440
  path: `${module.path}/${module.name}.dictionary.ts`,
486
- message: `Dictionary labels for ${sys.name}:${module.name}.${fieldName} were not found.`,
487
- repairActions: [action]
488
- });
489
- repairActions.push(action);
441
+ message: `Dictionary labels for ${sys.name}:${module.name}.${fieldName} were not found.`
442
+ }, repairAction("dictionary", `akan repair dictionary --app ${sys.name} --module ${module.name}`, "Add missing dictionary labels for source constant fields.", false));
490
443
  }
491
444
  }
492
445
  }
@@ -554,19 +507,16 @@ class AkanContextAnalyzer {
554
507
  const pushIndexDiagnostic = (indexPath, missing, stale, repairCommand) => {
555
508
  if (missing.length === 0 && stale.length === 0)
556
509
  return;
557
- const action = repairAction("generated", repairCommand, "Regenerate the recipe index from the scanned recipes.", true);
558
510
  const parts = [
559
511
  missing.length > 0 ? `${missing.length} declared but unlisted (${missing.slice(0, 5).join(", ")})` : "",
560
512
  stale.length > 0 ? `${stale.length} listed but gone (${stale.slice(0, 5).join(", ")})` : ""
561
513
  ].filter(Boolean);
562
- diagnostics.push({
514
+ report({
563
515
  severity: "error",
564
516
  code: "recipe-index-stale",
565
517
  path: indexPath,
566
- message: `${indexPath} recipe index is out of date \u2014 ${parts.join("; ")}. Agents read this list as authoritative.`,
567
- repairActions: [action]
568
- });
569
- repairActions.push(action);
518
+ message: `${indexPath} recipe index is out of date \u2014 ${parts.join("; ")}. Agents read this list as authoritative.`
519
+ }, repairAction("generated", repairCommand, "Regenerate the recipe index from the scanned recipes.", true));
570
520
  };
571
521
  const frameworkDeclared = declaredByImport.get("akanjs/ui") ?? new Set;
572
522
  if (frameworkDeclared.size > 0) {
@@ -0,0 +1,12 @@
1
+ // @bun
2
+ // pkgs/@akanjs/cli/openBrowser.ts
3
+ import { spawn } from "child_process";
4
+ function openBrowser(url) {
5
+ const command = process.platform === "darwin" ? ["open", url] : process.platform === "win32" ? ["cmd", "/c", "start", "", url] : ["xdg-open", url];
6
+ const child = spawn(command[0], command.slice(1), { detached: true, stdio: "ignore" });
7
+ child.on("error", () => {});
8
+ child.unref();
9
+ return Promise.resolve();
10
+ }
11
+
12
+ export { openBrowser };