@akanjs/cli 3.0.0-beta.13 → 3.0.0-beta.15

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 (92) hide show
  1. package/.build-stamp +1 -1
  2. package/CodeAgent-d3wvbq8q.js +9 -0
  3. package/CodeAgentRpcHost-qvwfv0n9.js +7 -0
  4. package/CodeTui-6c9a2wtk.js +1103 -0
  5. package/README.md +3 -0
  6. package/{TunnelShare-2kwqb1j6.js → TunnelShare-r5tc2qk5.js} +2 -2
  7. package/{agent.command-7357vxd8.js → agent.command-9cg8m87z.js} +6 -6
  8. package/akanCode.js +100 -0
  9. package/{application.command-8s8ns95d.js → application.command-x75men32.js} +6 -15
  10. package/{applicationBuildRunner-4f1wrba0.js → applicationBuildRunner-d3702f1w.js} +2 -2
  11. package/{applicationReleasePackager-jkjmy5ee.js → applicationReleasePackager-2kdyj3te.js} +1 -1
  12. package/buildBatch.proc.js +2 -2
  13. package/{capacitorApp-hqvsrec4.js → capacitorApp-qk975zyz.js} +2 -2
  14. package/{cloud.command-p5dnhft9.js → cloud.command-a09wggfq.js} +10 -22
  15. package/cloud.script-qd3hpybf.js +20 -0
  16. package/code.command-ca7rpmez.js +147 -0
  17. package/commandManifest.json +1 -1
  18. package/consoleToStderr-h5bryj94.js +7 -0
  19. package/{context.command-wsjt98c1.js → context.command-9kbm0527.js} +14 -15
  20. package/context.runner-wtqpw7mh.js +22 -0
  21. package/{devTui-myg3pqeg.js → devTui-v19fbnpk.js} +114 -8
  22. package/{devTuiView-gz2fbf4v.js → devTuiView-pa63jrjq.js} +1 -1
  23. package/guideline.command-qvrh5pnx.js +48 -0
  24. package/guidelines/agentRule/agentRule.instruction.md +46 -15
  25. package/guidelines/conventions/conventions.instruction.md +9 -4
  26. package/guidelines/moduleCodegen/moduleCodegen.instruction.md +1 -1
  27. package/guidelines/workspaceRecipes/workspaceRecipes.generate.json +1 -0
  28. package/guidelines/workspaceRecipes/workspaceRecipes.instruction.md +62 -0
  29. package/incrementalBuilder.proc.js +1 -1
  30. package/{index-bz10w9t2.js → index-0qvq9aeb.js} +6 -16
  31. package/{index-jwjaf9fy.js → index-1p146w4s.js} +44 -44
  32. package/{index-7f4dsf9v.js → index-1sggq0m8.js} +1 -1
  33. package/{index-15r9a10e.js → index-3dmebxnk.js} +2 -2
  34. package/{index-vrwdx0zx.js → index-3hr7cpy1.js} +1 -1
  35. package/{index-s3fvrydw.js → index-5hy11qaq.js} +9 -9
  36. package/{index-8pkvrcv1.js → index-658xafm1.js} +3 -3
  37. package/index-7md2g9vw.js +6 -0
  38. package/{index-ys7dvdb3.js → index-84b080zh.js} +1 -1
  39. package/index-8k16atqy.js +82 -0
  40. package/{index-t3c045et.js → index-91brpnzb.js} +8 -21
  41. package/{index-em4swemt.js → index-bchkysja.js} +3 -3
  42. package/{index-j7rwsd23.js → index-bzjnp9ap.js} +22 -80
  43. package/{index-cnzm1wn5.js → index-chp5gqmm.js} +88 -169
  44. package/{index-h3g1152j.js → index-d35a8vc0.js} +4 -4
  45. package/{index-1nwxbr2y.js → index-ea1smknd.js} +2 -2
  46. package/index-egt4vfgb.js +69 -0
  47. package/index-erzcytap.js +2434 -0
  48. package/{index-sh88vtye.js → index-f4gpcp98.js} +1 -1
  49. package/{index-b3ae16mg.js → index-gca9y01h.js} +1 -1
  50. package/{index-wmb05v4q.js → index-gm76f0qb.js} +1 -1
  51. package/{index-649svkyt.js → index-myj01w9r.js} +8 -15
  52. package/index-sxg87a8f.js +727 -0
  53. package/{index-h7yw2z9n.js → index-twq9p2sp.js} +8 -8
  54. package/index-v156f836.js +234 -0
  55. package/index-v1y3cx0k.js +61 -0
  56. package/{index-t8gvwcrx.js → index-va2je2qm.js} +2 -2
  57. package/index-wfwknnje.js +124 -0
  58. package/index-x7g1qzpt.js +121 -0
  59. package/index.js +21 -20
  60. package/{library.command-1f9h2ex6.js → library.command-n89re6cx.js} +3 -3
  61. package/{localRegistry.command-w6w35j4r.js → localRegistry.command-1mmnegph.js} +9 -9
  62. package/{module.command-8zkq0q9q.js → module.command-4m82zgfp.js} +7 -10
  63. package/{package.command-y2rh4np7.js → package.command-9dv0p6zq.js} +3 -3
  64. package/package.json +9 -5
  65. package/{page.command-e5h29fyt.js → page.command-q86b0m0z.js} +3 -3
  66. package/{primitive.command-qm7tybpn.js → primitive.command-kaneasq6.js} +6 -9
  67. package/prompter-9mn3kp36.js +8 -0
  68. package/{quality.command-5evdd263.js → quality.command-sgapx315.js} +65 -5
  69. package/{repair.command-c2amvt74.js → repair.command-efc5gdbq.js} +5 -5
  70. package/{scalar.command-a1ewkmab.js → scalar.command-e2rpkhqy.js} +6 -9
  71. package/skills/akan-debug/SKILL.md +42 -0
  72. package/skills/akan-deps/SKILL.md +50 -0
  73. package/skills/akan-err/SKILL.md +39 -0
  74. package/skills/akan-module/SKILL.md +45 -0
  75. package/skills/akan-scaffold/SKILL.md +76 -0
  76. package/skills/akan-scalar/SKILL.md +52 -0
  77. package/skills/akan-service/SKILL.md +34 -0
  78. package/skills/akan-store/SKILL.md +63 -0
  79. package/skills/akan-ui/SKILL.md +63 -0
  80. package/skills/akan-validate/SKILL.md +44 -0
  81. package/{subspace.command-3w5x13a1.js → subspace.command-005rz1x6.js} +5 -5
  82. package/{tunnel.command-09n8h4s1.js → tunnel.command-66j9estx.js} +4 -4
  83. package/{workflow.command-y3fct1rq.js → workflow.command-z1xcm4c7.js} +9 -12
  84. package/{workspace.command-p6td4qad.js → workspace.command-4ahrhp3k.js} +23 -22
  85. package/abstractCompactor-g04vqcff.js +0 -102
  86. package/cloud.script-gxpbhras.js +0 -20
  87. package/guideline.command-snqzfyt0.js +0 -360
  88. package/index-5tw8t1ts.js +0 -338
  89. package/index-j1tajctp.js +0 -229
  90. package/index-kpnp2e10.js +0 -841
  91. package/index-meh558jy.js +0 -65
  92. /package/{index-5nyznra1.js → index-p1j0cyvd.js} +0 -0
@@ -3,13 +3,13 @@ import {
3
3
  Lib,
4
4
  Workspace,
5
5
  command
6
- } from "./index-b3ae16mg.js";
6
+ } from "./index-gca9y01h.js";
7
7
  import"./index-q0y2jq9j.js";
8
- import"./index-5nyznra1.js";
8
+ import"./index-p1j0cyvd.js";
9
9
  import"./index-6wwzs1bc.js";
10
10
  import {
11
11
  LibraryScript
12
- } from "./index-1nwxbr2y.js";
12
+ } from "./index-ea1smknd.js";
13
13
 
14
14
  // pkgs/@akanjs/cli/library/library.command.ts
15
15
  class LibraryCommand extends command("library", [LibraryScript], ({ public: target }) => ({
@@ -4,28 +4,28 @@ import {
4
4
  runner,
5
5
  script,
6
6
  command
7
- } from "./index-b3ae16mg.js";
7
+ } from "./index-gca9y01h.js";
8
8
  import"./index-q0y2jq9j.js";
9
9
  import {
10
10
  PkgExecutor
11
- } from "./index-5nyznra1.js";
11
+ } from "./index-p1j0cyvd.js";
12
12
  import"./index-6wwzs1bc.js";
13
13
  import {
14
14
  ApplicationScript
15
- } from "./index-cnzm1wn5.js";
16
- import"./index-1nwxbr2y.js";
15
+ } from "./index-chp5gqmm.js";
16
+ import"./index-ea1smknd.js";
17
17
  import"./index-hwkygn9s.js";
18
- import"./index-649svkyt.js";
19
- import"./index-5tw8t1ts.js";
18
+ import"./index-7md2g9vw.js";
19
+ import"./index-myj01w9r.js";
20
20
  import {
21
21
  getNpmRegistryUrl,
22
22
  CloudRunner
23
- } from "./index-bz10w9t2.js";
23
+ } from "./index-0qvq9aeb.js";
24
24
  import"./index-kcxmv48c.js";
25
25
  import {
26
26
  PackageScript
27
- } from "./index-t8gvwcrx.js";
28
- import"./index-ys7dvdb3.js";
27
+ } from "./index-va2je2qm.js";
28
+ import"./index-84b080zh.js";
29
29
 
30
30
  // pkgs/@akanjs/cli/localRegistry/localRegistry.runner.ts
31
31
  import { mkdir, rm } from "fs/promises";
@@ -3,27 +3,24 @@ import {
3
3
  Sys,
4
4
  Module,
5
5
  command
6
- } from "./index-b3ae16mg.js";
6
+ } from "./index-gca9y01h.js";
7
7
  import"./index-q0y2jq9j.js";
8
- import"./index-5nyznra1.js";
8
+ import"./index-p1j0cyvd.js";
9
9
  import"./index-6wwzs1bc.js";
10
10
  import {
11
11
  renderPrimitiveReport
12
- } from "./index-jwjaf9fy.js";
13
- import"./index-649svkyt.js";
14
- import"./index-5tw8t1ts.js";
12
+ } from "./index-1p146w4s.js";
13
+ import"./index-f4gpcp98.js";
15
14
  import {
16
15
  ModuleScript
17
- } from "./index-kpnp2e10.js";
18
- import"./index-sh88vtye.js";
19
- import"./index-h7yw2z9n.js";
16
+ } from "./index-v156f836.js";
20
17
 
21
18
  // pkgs/@akanjs/cli/module/module.command.ts
22
19
  import { Logger, lowerlize } from "akanjs/common";
23
20
  class ModuleCommand extends command("module", [ModuleScript], ({ public: target }) => ({
24
- createModule: target({ desc: "Create a new domain module (constant, service, signal, store, UI)" }).arg("moduleName", String, { desc: "name of module" }).with(Sys).option("page", Boolean, { desc: "create page", default: false }).option("ai", Boolean, { desc: "use ai to create module constant and dictionary", default: false }).option("format", String, { flag: "o", desc: "output format", default: "markdown", enum: ["markdown", "json"] }).exec(async function(moduleName, sys, page, ai, format) {
21
+ createModule: target({ desc: "Create a new domain module (constant, service, signal, store, UI)" }).arg("moduleName", String, { desc: "name of module" }).with(Sys).option("page", Boolean, { desc: "create page", default: false }).option("format", String, { flag: "o", desc: "output format", default: "markdown", enum: ["markdown", "json"] }).exec(async function(moduleName, sys, page, format) {
25
22
  const name = lowerlize(moduleName.replace(/ /g, ""));
26
- const report = ai ? await this.moduleScript.createModule(sys, name, { page }) : await this.moduleScript.createModuleTemplate(sys, name, { page });
23
+ const report = await this.moduleScript.createModuleTemplate(sys, name, { page });
27
24
  Logger.rawLog(renderPrimitiveReport(report, format));
28
25
  }),
29
26
  removeModule: target({ desc: "Remove a module from an app or library" }).with(Module).exec(async function(module) {
@@ -3,14 +3,14 @@ import {
3
3
  Pkg,
4
4
  Workspace,
5
5
  command
6
- } from "./index-b3ae16mg.js";
6
+ } from "./index-gca9y01h.js";
7
7
  import"./index-q0y2jq9j.js";
8
- import"./index-5nyznra1.js";
8
+ import"./index-p1j0cyvd.js";
9
9
  import"./index-6wwzs1bc.js";
10
10
  import"./index-kcxmv48c.js";
11
11
  import {
12
12
  PackageScript
13
- } from "./index-t8gvwcrx.js";
13
+ } from "./index-va2je2qm.js";
14
14
 
15
15
  // pkgs/@akanjs/cli/package/package.command.ts
16
16
  class PackageCommand extends command("package", [PackageScript], ({ public: target }) => ({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akanjs/cli",
3
- "version": "3.0.0-beta.13",
3
+ "version": "3.0.0-beta.15",
4
4
  "sourceType": "module",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -24,16 +24,18 @@
24
24
  "import": "./index.js",
25
25
  "default": "./index.js"
26
26
  },
27
+ "./code": {
28
+ "import": "./akanCode.js",
29
+ "default": "./akanCode.js"
30
+ },
27
31
  "./package.json": "./package.json"
28
32
  },
29
33
  "dependencies": {
34
+ "@earendil-works/pi-coding-agent": "0.80.6",
30
35
  "@inquirer/prompts": "^8.4.3",
31
- "@langchain/core": "^1.1.47",
32
- "@langchain/deepseek": "^1.0.26",
33
- "@langchain/openai": "^1.4.6",
34
36
  "@tailwindcss/node": "^4.3.0",
35
37
  "@trapezedev/project": "^7.1.4",
36
- "akanjs": "3.0.0-beta.13",
38
+ "akanjs": "3.0.0-beta.15",
37
39
  "chalk": "^5.6.2",
38
40
  "commander": "^14.0.3",
39
41
  "dayjs": "^1.11.20",
@@ -45,9 +47,11 @@
45
47
  "qrcode": "^1.5.4",
46
48
  "react": "19.2.7",
47
49
  "ssh2": "^1.17.0",
50
+ "string-width": "^8.2.1",
48
51
  "subset-font": "^2.5.0",
49
52
  "tailwind-scrollbar": "^4.0.2",
50
53
  "tailwindcss": "^4.3.0",
54
+ "typebox": "1.1.38",
51
55
  "typescript": "^6.0.3"
52
56
  },
53
57
  "devDependencies": {},
@@ -3,13 +3,13 @@ import {
3
3
  App,
4
4
  Module,
5
5
  command
6
- } from "./index-b3ae16mg.js";
6
+ } from "./index-gca9y01h.js";
7
7
  import"./index-q0y2jq9j.js";
8
- import"./index-5nyznra1.js";
8
+ import"./index-p1j0cyvd.js";
9
9
  import"./index-6wwzs1bc.js";
10
10
  import {
11
11
  PageScript
12
- } from "./index-sh88vtye.js";
12
+ } from "./index-f4gpcp98.js";
13
13
 
14
14
  // pkgs/@akanjs/cli/page/page.command.ts
15
15
  class PageCommand extends command("page", [PageScript], ({ public: target }) => ({
@@ -2,21 +2,18 @@
2
2
  import {
3
3
  Workspace,
4
4
  command
5
- } from "./index-b3ae16mg.js";
5
+ } from "./index-gca9y01h.js";
6
6
  import"./index-q0y2jq9j.js";
7
- import"./index-5nyznra1.js";
7
+ import"./index-p1j0cyvd.js";
8
8
  import"./index-6wwzs1bc.js";
9
9
  import {
10
10
  renderPrimitiveReport
11
- } from "./index-jwjaf9fy.js";
12
- import"./index-649svkyt.js";
13
- import"./index-5tw8t1ts.js";
14
- import"./index-kpnp2e10.js";
15
- import"./index-sh88vtye.js";
16
- import"./index-h7yw2z9n.js";
11
+ } from "./index-1p146w4s.js";
12
+ import"./index-f4gpcp98.js";
13
+ import"./index-v156f836.js";
17
14
  import {
18
15
  PrimitiveScript
19
- } from "./index-h3g1152j.js";
16
+ } from "./index-d35a8vc0.js";
20
17
 
21
18
  // pkgs/@akanjs/cli/primitive/primitive.command.ts
22
19
  import { Logger } from "akanjs/common";
@@ -0,0 +1,8 @@
1
+ // @bun
2
+ import {
3
+ Prompter2
4
+ } from "./index-twq9p2sp.js";
5
+ import"./index-6wwzs1bc.js";
6
+ export {
7
+ Prompter2 as Prompter
8
+ };
@@ -4,17 +4,14 @@ import {
4
4
  runner,
5
5
  script,
6
6
  command
7
- } from "./index-b3ae16mg.js";
7
+ } from "./index-gca9y01h.js";
8
8
  import"./index-q0y2jq9j.js";
9
9
  import {
10
10
  rootAllowedFiles,
11
11
  rootAllowedDirs,
12
12
  isAllowedLibFacetRootFile
13
- } from "./index-5nyznra1.js";
13
+ } from "./index-p1j0cyvd.js";
14
14
  import"./index-6wwzs1bc.js";
15
- import {
16
- AbstractDoc
17
- } from "./index-meh558jy.js";
18
15
 
19
16
  // pkgs/@akanjs/devkit/qualityScanner.ts
20
17
  import { createHash } from "crypto";
@@ -24,6 +21,69 @@ import { RESERVED_ROUTE_CONFIG_EXPORTS } from "akanjs/common";
24
21
  import ignore from "ignore";
25
22
  import ts3 from "typescript";
26
23
 
24
+ // pkgs/@akanjs/devkit/abstractDoc.ts
25
+ class AbstractDoc {
26
+ path;
27
+ content;
28
+ siblingFiles;
29
+ static suffix = ".abstract.md";
30
+ static maxLines = 300;
31
+ static compactMinLines = 40;
32
+ static #facetRoots = "{lib,ui,webkit,srvkit,common,plugin}";
33
+ static isAbstractPath(filePath) {
34
+ return filePath.endsWith(AbstractDoc.suffix);
35
+ }
36
+ static lineCountOf(content) {
37
+ return content.split(/\r?\n/).length;
38
+ }
39
+ static kindOf(filePath) {
40
+ const [root, folder, ...rest] = filePath.split("/");
41
+ if (root !== "lib" || !folder)
42
+ return "other";
43
+ if (folder === "__scalar")
44
+ return rest.length === 2 ? "scalar" : "other";
45
+ if (rest.length !== 1)
46
+ return "other";
47
+ return folder.startsWith("_") ? "service" : "domain";
48
+ }
49
+ static async findAll(sys, { module } = {}) {
50
+ const filePaths = (await sys.getAllFiles(`${AbstractDoc.#facetRoots}/**/*${AbstractDoc.suffix}`)).sort();
51
+ const docs = await Promise.all(filePaths.map((filePath) => AbstractDoc.read(sys, filePath)));
52
+ if (!module)
53
+ return docs;
54
+ return docs.filter((doc) => doc.moduleName === module || doc.folderName === module);
55
+ }
56
+ static async read(sys, filePath) {
57
+ const dirPath = filePath.split("/").slice(0, -1).join("/");
58
+ const [content, folderFiles] = await Promise.all([sys.readFile(filePath), sys.readdir(dirPath)]);
59
+ return new AbstractDoc(filePath, content, folderFiles.filter((fileName) => !AbstractDoc.isAbstractPath(fileName)));
60
+ }
61
+ constructor(path, content, siblingFiles) {
62
+ this.path = path;
63
+ this.content = content;
64
+ this.siblingFiles = siblingFiles;
65
+ }
66
+ get kind() {
67
+ return AbstractDoc.kindOf(this.path);
68
+ }
69
+ get folderName() {
70
+ return this.path.split("/").at(-2) ?? "";
71
+ }
72
+ get moduleName() {
73
+ return (this.path.split("/").at(-1) ?? "").slice(0, -AbstractDoc.suffix.length);
74
+ }
75
+ get lineCount() {
76
+ return AbstractDoc.lineCountOf(this.content);
77
+ }
78
+ canReplaceWith(candidate) {
79
+ const next = candidate.trim();
80
+ if (!next.startsWith("#"))
81
+ return false;
82
+ const lineCount = AbstractDoc.lineCountOf(next);
83
+ return lineCount >= 3 && lineCount < this.lineCount;
84
+ }
85
+ }
86
+
27
87
  // pkgs/@akanjs/devkit/formSetterScanner.ts
28
88
  import ts from "typescript";
29
89
 
@@ -3,16 +3,16 @@ import {
3
3
  Workspace,
4
4
  script,
5
5
  command
6
- } from "./index-b3ae16mg.js";
6
+ } from "./index-gca9y01h.js";
7
7
  import"./index-q0y2jq9j.js";
8
- import"./index-5nyznra1.js";
8
+ import"./index-p1j0cyvd.js";
9
9
  import"./index-6wwzs1bc.js";
10
10
  import"./index-by5gpp8x.js";
11
- import"./index-jwjaf9fy.js";
12
- import"./index-15r9a10e.js";
11
+ import"./index-1p146w4s.js";
12
+ import"./index-3dmebxnk.js";
13
13
  import {
14
14
  RepairRunner
15
- } from "./index-em4swemt.js";
15
+ } from "./index-bchkysja.js";
16
16
 
17
17
  // pkgs/@akanjs/cli/repair/repair.script.ts
18
18
  import { Logger } from "akanjs/common";
@@ -2,26 +2,23 @@
2
2
  import {
3
3
  Sys,
4
4
  command
5
- } from "./index-b3ae16mg.js";
5
+ } from "./index-gca9y01h.js";
6
6
  import"./index-q0y2jq9j.js";
7
- import"./index-5nyznra1.js";
7
+ import"./index-p1j0cyvd.js";
8
8
  import"./index-6wwzs1bc.js";
9
9
  import {
10
10
  renderPrimitiveReport
11
- } from "./index-jwjaf9fy.js";
12
- import"./index-649svkyt.js";
13
- import"./index-5tw8t1ts.js";
14
- import"./index-h7yw2z9n.js";
11
+ } from "./index-1p146w4s.js";
15
12
  import {
16
13
  ScalarScript
17
- } from "./index-j1tajctp.js";
14
+ } from "./index-v1y3cx0k.js";
18
15
 
19
16
  // pkgs/@akanjs/cli/scalar/scalar.command.ts
20
17
  import { Logger, lowerlize } from "akanjs/common";
21
18
  class ScalarCommand extends command("scalar", [ScalarScript], ({ public: target }) => ({
22
- createScalar: target({ desc: "Create a new scalar type (simple data model without DB)" }).arg("scalarName", String, { desc: "name of scalar" }).with(Sys).option("ai", Boolean, { default: false, desc: "use ai to create scalar" }).option("format", String, { flag: "o", desc: "output format", default: "markdown", enum: ["markdown", "json"] }).exec(async function(scalarName, sys, ai, format) {
19
+ createScalar: target({ desc: "Create a new scalar type (simple data model without DB)" }).arg("scalarName", String, { desc: "name of scalar" }).with(Sys).option("format", String, { flag: "o", desc: "output format", default: "markdown", enum: ["markdown", "json"] }).exec(async function(scalarName, sys, format) {
23
20
  const name = lowerlize(scalarName.replace(/ /g, ""));
24
- const report = ai ? await this.scalarScript.createScalarWithAi(sys, name) : await this.scalarScript.createScalar(sys, name);
21
+ const report = await this.scalarScript.createScalar(sys, name);
25
22
  Logger.rawLog(renderPrimitiveReport(report, format));
26
23
  }),
27
24
  removeScalar: target({ desc: "Remove a scalar type from an app or library" }).arg("scalarName", String, { desc: "name of scalar" }).with(Sys).exec(async function(scalarName, sys) {
@@ -0,0 +1,42 @@
1
+ ---
2
+ name: akan-debug
3
+ description: "Debug a running Akan app: where the dev-server log is, how to read it, and how to tell a runtime failure from a build one."
4
+ ---
5
+
6
+ # Akan debug
7
+
8
+ ## The log is a file, and that file is the whole session
9
+
10
+ A supervised `akan start` writes **`local/apps/<app>/runtime/dev.log`** — no ANSI, nothing truncated, every
11
+ process of the app in arrival order, including the dev host's own build output, which reaches no other
12
+ file. The previous session is kept beside it as `dev.prev.log`.
13
+
14
+ Read that file. Do not ask for a paste of the terminal: the full-screen view repaints one frame in place, so
15
+ what survives in the scrollback is bordered and truncated to the pane.
16
+
17
+ - `tail -n 200 local/apps/<app>/runtime/dev.log` after an edit, to see what the reload produced.
18
+ - `akan logs <app>` tails a running server with `--level --grep --endpoint --trace --child --role --origin
19
+ --since` and `--json`.
20
+ - The dev server's URL is printed in that log, and the port is allocated rather than fixed — the log is the
21
+ only source for it.
22
+
23
+ ## Which loop you are in
24
+
25
+ - **A type or lint failure** is the `akan-validate` loop. `akan_verify`.
26
+ - **A runtime or SSR failure** is the dev log. The page renders blank, an overlay appears, or a request
27
+ 500s — none of that shows up in a typecheck.
28
+
29
+ If a dev server is already running for the app, do **not** start another. If it looks wedged, surface the
30
+ log tail in your answer rather than killing it.
31
+
32
+ ## Reading a log line
33
+
34
+ Every `Logger` call carries `traceId`, `endpoint` and `origin` alongside the message, so one request's lines
35
+ share a trace — `akan logs <app> --trace <id>` pulls just that request. The level ladder is
36
+ `trace verbose debug info warn error`; `.log()` is deprecated and emits at `info`, which is why a call that
37
+ reads like its own level is not one.
38
+
39
+ ## Before you conclude
40
+
41
+ A change that renders is not a change that passed. Run `akan_verify`, and for a `.tsx` change check
42
+ `akan quality ssr` too — a UI edit that moves markup into a client bundle typechecks perfectly.
@@ -0,0 +1,50 @@
1
+ ---
2
+ name: akan-deps
3
+ description: "Fix an import, dependency, or barrel problem in an Akan workspace — barrels are generated, and a third-party package may not be imported from most files."
4
+ ---
5
+
6
+ # Akan imports, deps and barrels
7
+
8
+ ## Barrels are generated
9
+
10
+ Every `index.ts` under `ui/`, `webkit/`, `srvkit/`, `common/`, `plugin/` and `lib/**` is scanner output, as
11
+ are `cnst.ts`, `db.ts`, `dict.ts`, `sig.ts`, `srv.ts`, `st.ts`, `useClient.ts`, `useServer.ts`, `client.ts`
12
+ and `server.ts`. Do not hand-edit them and do not rely on their exact contents.
13
+
14
+ **If an import "cannot be found" but the file exists, the barrel is stale** — run `akan sync <app-or-lib>`,
15
+ or `repair_generated`. A `ui/<Folder>/index.tsx` that builds a namespace is hand-written source; the
16
+ distinguishing test is that a generated barrel contains nothing but `export * from "./X";` lines.
17
+
18
+ ## Where a dependency is declared
19
+
20
+ Add the package to the `package.json` of the app or lib that imports it —
21
+ `apps/<app>/package.json` or `libs/<lib>/package.json` — then `bun install` from the repo root.
22
+
23
+ ## A third-party package may not be imported from most files
24
+
25
+ `no-import-external-library.grit` refuses a third-party import from `page/**`, from any barrel, and from any
26
+ `*.{constant,dictionary,document,service,signal,store}.ts` or `*.{Template,Unit,Util,View,Zone}.tsx`.
27
+ Re-export the symbol through a lib first. The one-line re-export shims in a lib's `common/`, `webkit/` and
28
+ `ui/` exist for exactly this — they are load-bearing, not cruft.
29
+
30
+ ## Two more import rules the build enforces
31
+
32
+ - **No deep import past a barrel** (`no-deep-internal-import.grit`). Cross-module constant references such as
33
+ `../map/map.constant` are the sanctioned exception.
34
+ - **No import across the client/server boundary.** A client file may not import a `*.document.ts` /
35
+ `*.dictionary.ts` / `*.service.ts` / `*.signal.ts`, `srvkit/`, a package `server` entrypoint, or the `db` /
36
+ `srv` / `sig` / `dict` / `option` / `useServer` barrels. A server file may not import a `*.store.ts`, a
37
+ module component, `ui/`, `webkit/`, a package `client` entrypoint, or `st` / `store` / `useClient`. Shared
38
+ files — `common/` and `*.constant.ts` — are held to **both**. `import type` is erased and stays legal in
39
+ every direction; a mixed value-and-type import is not exempt.
40
+
41
+ ## Aliases
42
+
43
+ `akanjs/*` for framework facets, `@apps/*`, `@libs/*`, `@contract/*`. In `.tsx`, one flat named import from
44
+ the package client path — `import { cnst, fetch, st, usePage } from "@apps/<app>/client"` — never a relative
45
+ `../` import. In backend `.ts`, namespace the generated barrels: `import * as cnst from "../cnst"`.
46
+
47
+ ## Validate
48
+
49
+ `akan_verify`, or `akan sync <app>` then `akan lint <app>` then `akan typecheck <app>`. Raw `tsc` misses the
50
+ generated barrels and reports false errors.
@@ -0,0 +1,39 @@
1
+ ---
2
+ name: akan-err
3
+ description: "Throw errors the Akan way — a typed Err with a dictionary key, never a bare throw new Error. Lint-enforced."
4
+ ---
5
+
6
+ # throw → Err
7
+
8
+ Domain code throws `new Err("<module>.error.<key>")` and registers the key as `[en, ko]` in that module's
9
+ dictionary `.error({})`. `throw new Error(...)` fails the build (`no-throw-raw-error.grit`).
10
+
11
+ ## Getting the import side right
12
+
13
+ This is the common failure. Import `Err` from the source matching the **runtime side of the file**:
14
+
15
+ - server code: `import { Err } from "../dict"`
16
+ - UI: `from "@libs/<lib>/client"` or `from "@apps/<app>/client"`
17
+
18
+ ## Where the rule does not apply
19
+
20
+ The lint rule exempts tests, `*.constant.ts`, `common/**`, and `env/**`. The last two have **no legal `Err`
21
+ import path at all**, so keep throwing code out of them entirely rather than reaching for a workaround.
22
+
23
+ ## Where each error belongs
24
+
25
+ - a state-machine precondition → `document.ts`
26
+ - a cross-document rule → `service.ts`
27
+ - request-level policy → a guard in `signal.ts`
28
+
29
+ Best-effort code returns a sentinel (`null`, `undefined`, `{}`) instead of throwing. `try/catch` is rare and
30
+ always converts an exception into a decision: a guard catches, warns, and returns `false`; an adapter
31
+ catches, logs, and returns `null`. A store action never catches — let the framework toast the `Err`.
32
+ Client-side validation failure is `msg.error("<key>")` plus an early return, never a throw.
33
+
34
+ **A failure another process reported travels as itself.** A server-to-server `fetch.<endpoint>(…, { origin })`
35
+ restores the remote `Err` with its class, key and data. Rethrow it as-is — wrapping it in a `new Error`
36
+ discards what the endpoint chose to say, and a bare `Error` is generalized to "Internal Server Error" on the
37
+ way out.
38
+
39
+ Korean `.error()` messages end in `다.`.
@@ -0,0 +1,45 @@
1
+ ---
2
+ name: akan-module
3
+ description: "Add or change an Akan database module: the constant→dictionary→document→service→signal→store→UI flow and which layer owns what."
4
+ ---
5
+
6
+ # Akan module flow
7
+
8
+ Creating a **new** module? Do not hand-write these files — scaffold with `create-module` first (the
9
+ `akan-scaffold` skill), then fill in the layers below.
10
+
11
+ A stored model flows through layers, one file each under `lib/<model>/`:
12
+
13
+ `constant → dictionary → document → service → signal → store → UI`
14
+
15
+ | file | owns |
16
+ | --- | --- |
17
+ | `<model>.constant.ts` | the five classes, in order: `XInput → XObject → LightX → X → XInsight`. Write `XInsight` even when empty. |
18
+ | `<model>.dictionary.ts` | `[en, ko]` labels and the `Err` keys, in the fixed chain with empty stages still written. |
19
+ | `<model>.document.ts` | `XFilter → X → XModel`. Chain methods validate, mutate, `return this`, and never `save()`. |
20
+ | `<model>.service.ts` | load → chain → `return await ….save()`. Side effects go in `_preUpdate` / `_postCreate`. |
21
+ | `<model>.signal.ts` | `XInternal → XSlice → XEndpoint`, all three declared even when empty. |
22
+ | `<model>.store.ts` | only what `store()` does not already generate — see `akan-store`. |
23
+ | `<Model>.*.tsx` | rendering. `Template` / `Zone` / `Util` are client, `Unit` / `View` are server. |
24
+
25
+ ## The rule most often missed
26
+
27
+ **Display and predicate logic belongs on `Light<Model>`** — `isNew()`, `canWrite(user?)`, `formatTimes()`.
28
+ The Light class is the one both server and client hold, so shared logic lives there instead of in a util
29
+ module. Collection-level helpers go `static` on the full model.
30
+
31
+ ## Rules
32
+
33
+ - New module ⇒ `create-module`. New field / action / list on an existing one ⇒ `add-field` /
34
+ `add-mutation` / `add-slice`. Hand-writing is the fallback, not the default.
35
+ - A module is for data that must be **stored**. Static page content is a page.
36
+ - Keep business decisions in constant, document and service; API exposure in signal; client coordination in
37
+ store; rendering in UI.
38
+ - Never hand-edit a generated registry file — `cnst.ts`, `db.ts`, `dict.ts`, `option.ts`, `sig.ts`, `srv.ts`,
39
+ `st.ts`, `useClient.ts`, `useServer.ts`, and every `index.ts` barrel. They are scanner output; run
40
+ `akan sync <app>` or `repair_generated`.
41
+ - Read the module's `<module>.abstract.md` before changing it, and update it when an invariant or workflow
42
+ changes — not for formatting.
43
+
44
+ Deeper detail per layer is a `get_guideline` call away: `moduleOverview`, `moduleCodegen`, `modelConstant`,
45
+ `modelDocument`, `modelService`, `modelSignal`, `modelStore`, `modelDictionary`.
@@ -0,0 +1,76 @@
1
+ ---
2
+ name: akan-scaffold
3
+ description: "Create a new module, scalar, field, mutation, slice, or UI surface — scaffold it with the akan workflow tools (plan_workflow / apply_workflow) instead of writing the files by hand."
4
+ ---
5
+
6
+ # Akan scaffolding workflows (use these BEFORE writing files)
7
+
8
+ Akan generates the conventional file set for you. Creating those files by hand skips the conventions, the
9
+ generated-barrel sync, and the validation chain.
10
+
11
+ ## Step 0 — decide WHAT gets a module, before any tool call
12
+
13
+ List the things the request says must be **stored in the database**. Those, and only those, become modules.
14
+ Everything else is pages, sections, and props.
15
+
16
+ - A page or section whose content you can write as static JSX or props is not an entity. "A self-intro page
17
+ with two detail pages" is pages only — no `profile` module.
18
+ - Never invent a supporting entity (profile, category, tag, author, like) to round out a design. If one looks
19
+ genuinely necessary, say so in your reply and let the user decide.
20
+ - "… plus a comment zone that saves to a database" is exactly one new module: `comment`.
21
+ - Check what exists first (`list_modules`) and extend it when it already fits — `add-field` / `add-slice` /
22
+ `create-ui` beat a whole new module.
23
+ - Build the entire request, at the smallest structure that satisfies it.
24
+
25
+ Then pick the workflow that matches the intent:
26
+
27
+ | The user wants… | workflow |
28
+ | --- | --- |
29
+ | a new database-backed entity (comment, post, todo, product …) | `create-module` |
30
+ | a reusable embedded value object | `create-scalar` |
31
+ | a new field on an existing module | `add-field` |
32
+ | a new field with a closed set of values | `add-enum-field` |
33
+ | a new state-changing action | `add-mutation` |
34
+ | a filtered list, tab, or reusable query | `add-slice` |
35
+ | a View / Unit / Template / Zone / Util for an existing module | `create-ui` |
36
+
37
+ ## The chain
38
+
39
+ Each result names the next call in `next.tool`. Follow it; do not improvise.
40
+
41
+ 1. `plan_workflow({ workflow: "create-module", inputs: { app: "<app>", module: "comment" } })` — read-only.
42
+ Returns `planPath` and `next.tool=apply_workflow`. (`list_workflows` / `explain_workflow` give the names
43
+ and each workflow's inputs.)
44
+ 2. `apply_workflow({ planPath })` — writes the scaffold and syncs the generated barrels. Returns
45
+ `validationTarget`.
46
+ 3. `run_validation({ runIdOrPlan: <validationTarget> })`, or just call `akan_verify`, which runs the whole
47
+ chain over everything the working tree changed.
48
+ 4. **Read each scaffolded file before editing it.** They are a few lines each and they extend base classes
49
+ that already generated the CRUD surface. Read the `akan-store` skill before touching a store or adding
50
+ signal endpoints, or you will redeclare `create<Model>` and hit an "already exists" typecheck error.
51
+ 5. Now fill in: real fields in the constant, invariants in document and service, non-CRUD API in the signal,
52
+ extra state in the store, rendering in the UI. Filling in a scaffold is the job; creating one by hand is
53
+ not.
54
+
55
+ ## Rules
56
+
57
+ - One run per unit of structure: two new entities are two `create-module` runs.
58
+ - `requiresApproval: true` on a plan is a review signal for you, not a permission gate — read
59
+ `predictedChanges`, then apply.
60
+ - Hand-writing files is the fallback, used only when no workflow matches, or when apply reports
61
+ unsupported / no-op / failed diagnostics telling you to act manually. Say which case applied.
62
+ - Never hand-edit a generated file to "finish" a scaffold — use `repair_generated` or `akan sync <app>`.
63
+ - No workflow tools this turn? The same order through bash:
64
+ `akan workflow list` → `akan workflow plan create-module --app <app> --module comment --format json --out <path>`
65
+ → `akan workflow apply <path> --format json`.
66
+
67
+ ## Worked example — "an intro page, two detail pages, and a comment zone with a database"
68
+
69
+ 0. What must be stored? Only the comments. One module, `comment`. The three pages are static content.
70
+ 1. `plan_workflow({ workflow: "create-module", inputs: { app: "<app>", module: "comment" } })`
71
+ 2. `apply_workflow({ planPath })` — `lib/comment/*` exists, barrels synced.
72
+ 3. Read the scaffolded files. Edit `comment.constant.ts` for the real shape. The store's CRUD already exists;
73
+ leave the store body empty unless you need extra state.
74
+ 4. Write the pages and the comment UI against the generated actions — `st.do.createComment`,
75
+ `st.do.initCommentInPublic`, `st.use.commentListInPublic`.
76
+ 5. `akan_verify` until clean.