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

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 (140) hide show
  1. package/.build-stamp +1 -1
  2. package/README.ko.md +1 -1
  3. package/README.md +1 -1
  4. package/{abstractCompactor-e5yq60qz.js → abstractCompactor-mjh5ppsq.js} +3 -5
  5. package/{agent.command-a3n15c6t.js → agent.command-d2gfxfck.js} +11 -13
  6. package/{application.command-rdm3et0g.js → application.command-pj2m7584.js} +65 -38
  7. package/{applicationBuildRunner-6m8n71w4.js → applicationBuildRunner-kxwbssgn.js} +27 -23
  8. package/{applicationReleasePackager-gg8ccbeh.js → applicationReleasePackager-4yasxwv9.js} +8 -9
  9. package/buildBatch.proc.js +12 -14
  10. package/capacitorApp-36rbr858.js +12 -0
  11. package/{cloud.command-56aeekqn.js → cloud.command-gxqp8xdv.js} +15 -18
  12. package/commandManifest.json +1 -1
  13. package/{context.command-ysxawe7h.js → context.command-ez8a0zyz.js} +19 -23
  14. package/dependencyScanner-shs82ynp.js +8 -0
  15. package/devTui-40ggmd99.js +553 -0
  16. package/devTuiView-c08ccbat.js +9 -0
  17. package/getDirname-dr3jz1xg.js +7 -0
  18. package/{guideline.command-yqf9a372.js → guideline.command-xmqwx8zm.js} +24 -22
  19. package/guidelines/agentRule/agentRule.generate.json +31 -0
  20. package/guidelines/agentRule/agentRule.instruction.md +531 -0
  21. package/guidelines/conventions/conventions.instruction.md +493 -369
  22. package/guidelines/framework/framework.generate.json +3 -2
  23. package/guidelines/framework/framework.instruction.md +0 -9
  24. package/guidelines/mcpRule/mcpRule.generate.json +35 -0
  25. package/guidelines/mcpRule/mcpRule.instruction.md +460 -0
  26. package/guidelines/modelStore/modelStore.instruction.md +12 -0
  27. package/guidelines/modelTemplate/modelTemplate.instruction.md +5 -0
  28. package/guidelines/queryRule/queryRule.generate.json +31 -0
  29. package/guidelines/queryRule/queryRule.instruction.md +178 -0
  30. package/guidelines/runtimeRule/runtimeRule.generate.json +25 -0
  31. package/guidelines/runtimeRule/runtimeRule.instruction.md +220 -0
  32. package/guidelines/ssrRule/ssrRule.instruction.md +51 -5
  33. package/guidelines/transportRule/transportRule.generate.json +31 -0
  34. package/guidelines/transportRule/transportRule.instruction.md +60 -0
  35. package/guidelines/workspaceOnboarding/workspaceOnboarding.instruction.md +54 -764
  36. package/guidelines/workspaceRecipes/workspaceRecipes.generate.json +33 -0
  37. package/guidelines/workspaceRecipes/workspaceRecipes.instruction.md +467 -0
  38. package/incrementalBuilder.proc.js +26 -25
  39. package/{index-8pd02prk.js → index-259dsnz3.js} +58 -25
  40. package/{index-yzsxc30b.js → index-2tv3fdx4.js} +975 -234
  41. package/index-3d9y066c.js +76 -0
  42. package/{index-76rn3g2c.js → index-47pj3aee.js} +4 -4
  43. package/{index-m90fn8xe.js → index-4edzf1gr.js} +32 -32
  44. package/{index-3789fdpg.js → index-600zhnve.js} +94 -61
  45. package/{index-1577bej2.js → index-6wwzs1bc.js} +2 -2
  46. package/{index-cv9cxs5k.js → index-7737gxcp.js} +18 -18
  47. package/{index-a5cs7d8r.js → index-8few9nyh.js} +13 -13
  48. package/{index-mewacxye.js → index-8pm30m73.js} +57 -57
  49. package/{index-wnp7hwq7.js → index-92zztqy1.js} +7 -7
  50. package/{index-fgc8r6dj.js → index-a5vmm6x4.js} +3 -1
  51. package/{index-cav1azma.js → index-a64esmtb.js} +1106 -1369
  52. package/{index-nwqqssnb.js → index-aj7tyh5w.js} +26 -23
  53. package/{index-xys926f2.js → index-by5gpp8x.js} +4 -4
  54. package/{index-yzmqvg23.js → index-fz5q3gd7.js} +8 -8
  55. package/{index-kcsa1zff.js → index-gyd220p2.js} +4 -4
  56. package/{index-j37qq1f2.js → index-h7yw2z9n.js} +7 -7
  57. package/{index-bjpxzr6s.js → index-hwkygn9s.js} +51 -3
  58. package/index-j9yhg404.js +159 -0
  59. package/{index-46tjzh6s.js → index-kcxmv48c.js} +29 -29
  60. package/{index-0cj2zxbm.js → index-kn1h7p1x.js} +12 -11
  61. package/{index-e4b2ae6b.js → index-ktb5njgy.js} +41 -34
  62. package/{index-etwh7sd3.js → index-mak3cd28.js} +100 -32
  63. package/{index-xjd3rqzj.js → index-n68jx79w.js} +6 -15
  64. package/{index-z1s5f4e0.js → index-ne2qy0nk.js} +36 -37
  65. package/{index-65aeh789.js → index-pnqbkf5p.js} +1 -1
  66. package/{index-67546d0j.js → index-q0y2jq9j.js} +14 -2
  67. package/{index-4mgkgba3.js → index-rwg2aa4f.js} +14 -14
  68. package/{index-bzznxgcx.js → index-v0qh106m.js} +1002 -128
  69. package/{index-j9cxndc0.js → index-w8kmx1b6.js} +20 -11
  70. package/{index-h5whaj26.js → index-ws5e0j51.js} +16 -12
  71. package/{index-9va8zayb.js → index-wt7qrtd4.js} +27 -27
  72. package/index.js +22 -25
  73. package/{library.command-x6t29a30.js → library.command-nbsky672.js} +11 -10
  74. package/{localRegistry.command-649g1n7b.js → localRegistry.command-ts6t5e5a.js} +20 -23
  75. package/{module.command-8w8ys5t3.js → module.command-29vqzrh8.js} +13 -16
  76. package/{package.command-zgy7f3fz.js → package.command-axv0abmn.js} +8 -10
  77. package/package.json +5 -7
  78. package/{page.command-yjmnkyk2.js → page.command-vs9s3zrh.js} +7 -9
  79. package/{primitive.command-gfqaagsg.js → primitive.command-cbxmqbtc.js} +13 -16
  80. package/{quality.command-ec8r1dn3.js → quality.command-gmbs7nws.js} +184 -334
  81. package/recipeScanner-fpagtgc1.js +11 -0
  82. package/{repair.command-p9ey6mkm.js → repair.command-bqsjptsj.js} +12 -14
  83. package/{routeSourceValidator-e4jmbfcx.js → routeSourceValidator-apyqw7wk.js} +90 -19
  84. package/{scalar.command-9dhmqhtm.js → scalar.command-6k1vhe9s.js} +11 -14
  85. package/subspace.command-35a3t6vv.js +755 -0
  86. package/templates/app/env/env.client.debug.ts.template +1 -5
  87. package/templates/app/env/env.client.develop.ts.template +1 -5
  88. package/templates/app/env/env.client.local.ts.template +1 -5
  89. package/templates/app/env/env.client.main.ts.template +1 -5
  90. package/templates/app/env/env.client.testing.ts.template +1 -5
  91. package/templates/app/env/env.client.type.ts +2 -6
  92. package/templates/app/env/env.server.debug.ts.template +1 -5
  93. package/templates/app/env/env.server.develop.ts.template +1 -5
  94. package/templates/app/env/env.server.local.ts.template +1 -5
  95. package/templates/app/env/env.server.main.ts.template +1 -5
  96. package/templates/app/main.ts +3 -1
  97. package/templates/app/page/_index.tsx +3 -3
  98. package/templates/app/page/_layout.tsx +31 -32
  99. package/templates/appSample/lib/task/task.signal.ts +11 -6
  100. package/templates/appSample/page/task/[taskId]/_index.tsx +22 -27
  101. package/templates/appSample/page/task/[taskId]/edit.tsx +25 -30
  102. package/templates/appSample/page/task/_index.tsx +3 -7
  103. package/templates/appSample/page/task/_layout.tsx +4 -15
  104. package/templates/appSample/page/task/new.tsx +4 -10
  105. package/templates/appSample/srvkit/AuthGuard.ts +2 -2
  106. package/templates/crudPages/[__model__Id]/edit/page.tsx +27 -29
  107. package/templates/crudPages/[__model__Id]/page.tsx +24 -32
  108. package/templates/crudPages/new/page.tsx +26 -25
  109. package/templates/crudPages/page.tsx +27 -26
  110. package/templates/crudSinglePage/page.tsx +26 -21
  111. package/templates/env/_env.server.type.ts +7 -5
  112. package/templates/lib/db.ts +1 -1
  113. package/templates/lib/dict.ts +1 -1
  114. package/templates/lib/sig.ts +5 -1
  115. package/templates/lib/srv.ts +6 -2
  116. package/templates/module/__model__.dictionary.ts +4 -1
  117. package/templates/module/__model__.signal.ts +2 -3
  118. package/templates/module/__model__.store.ts +1 -2
  119. package/templates/workspaceRoot/.gitignore.template +0 -1
  120. package/templates/workspaceRoot/.husky/pre-commit.template +16 -0
  121. package/templates/workspaceRoot/.vscode/settings.json.template +1 -1
  122. package/templates/workspaceRoot/AGENTS.md.template +4 -0
  123. package/templates/workspaceRoot/CLAUDE.md.template +19 -0
  124. package/templates/workspaceRoot/biome.json.template +1 -1
  125. package/templates/workspaceRoot/docs/AI-DEVELOPMENT.md.template +10 -14
  126. package/templates/workspaceRoot/docs/GENERATED.md.template +12 -10
  127. package/templates/workspaceRoot/package.json.template +2 -4
  128. package/typeChecker-3xgrzc2v.js +7 -0
  129. package/typecheck.proc.js +4 -5
  130. package/{workflow.command-ycwc6zr6.js → workflow.command-nwpcdc8p.js} +22 -25
  131. package/{workspace.command-xhyhajxa.js → workspace.command-aczjxzbf.js} +64 -66
  132. package/capacitorApp-mr81qdxq.js +0 -61
  133. package/dependencyScanner-f6grrep3.js +0 -9
  134. package/getDirname-m9s0cmhq.js +0 -8
  135. package/index-mxvakhsm.js +0 -66
  136. package/index-r24hmh0q.js +0 -4
  137. package/recipeScanner-tghkzrrt.js +0 -12
  138. package/typeChecker-kravn7ns.js +0 -8
  139. /package/{index-0wae5ebk.js → index-meh558jy.js} +0 -0
  140. /package/{index-ss469dec.js → index-nz8prx9g.js} +0 -0
@@ -9,34 +9,35 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dic
9
9
  return {
10
10
  filename: "_index.tsx",
11
11
  content: `
12
+ import { type cnst, fetch, usePage, ${dict.Model} } from "@apps/${dict.appName}/client";
13
+ import { page } from "akanjs/client";
12
14
  import { Load } from "akanjs/ui";
13
- import { cnst, fetch, usePage, ${dict.Model} } from "@apps/${dict.appName}/client";
14
- import type { PageConfig } from "akanjs/client";
15
15
 
16
- export default function Page() {
17
- const { l } = usePage();
18
- const ${dict.model}Form: Partial<cnst.${dict.Model}> = {};
19
- return (
20
- <div className="container">
21
- <div className="flex justify-between m-4 mt-8">
22
- <div className="text-xl text-primary flex gap-2 items-center">
23
- + {l("base.createModel", { model: l("${dict.model}.modelName") })}
16
+ export default page()
17
+ .config({ transition: "none" })
18
+ .render(() => {
19
+ const { l } = usePage();
20
+ const ${dict.model}Form: Partial<cnst.${dict.Model}> = {};
21
+ return (
22
+ <div className="container">
23
+ <div className="m-4 mt-8 flex justify-between">
24
+ <div className="flex items-center gap-2 text-primary text-xl">
25
+ + {l("base.createModel", { model: l("${dict.model}.modelName") })}
26
+ </div>
24
27
  </div>
28
+ <Load.Edit
29
+ className="flex flex-col items-center"
30
+ slice={fetch.slice.${dict.model}InPublic}
31
+ edit={${dict.model}Form}
32
+ type="form"
33
+ onCancel="back"
34
+ onSubmit="/${dict.model}"
35
+ >
36
+ <${dict.Model}.Template.General />
37
+ </Load.Edit>
25
38
  </div>
26
- <Load.Edit
27
- className="flex flex-col items-center"
28
- slice={fetch.slice.${dict.model}InPublic}
29
- edit={${dict.model}Form}
30
- type="form"
31
- onCancel="back"
32
- onSubmit="/${dict.model}"
33
- >
34
- <${dict.Model}.Template.General />
35
- </Load.Edit>
36
- </div>
37
- );
38
- }
39
- export const pageConfig = { transition: "none" } satisfies PageConfig;
40
- `,
39
+ );
40
+ });
41
+ `,
41
42
  };
42
43
  }
@@ -10,34 +10,35 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dic
10
10
  filename: "_index.tsx",
11
11
  content: `
12
12
  import { ${dict.Model}, fetch, usePage } from "@apps/${dict.appName}/client";
13
- import { Link } from "akanjs/ui";
14
- import type { PageConfig } from "akanjs/client";
13
+ import { page } from "akanjs/client";
14
+ import { buttonRecipe, Link } from "akanjs/ui";
15
15
 
16
- export default async function Page() {
17
- const { l } = usePage();
18
- const { ${dict.model}InitInPublic } = await fetch.init${dict.Model}InPublic();
19
- return (
20
- <div className="container flex flex-col gap-4">
21
- <div className="w-full mt-5 px-5 h-full ">
22
- <div>{l("${dict.model}.modelName")}</div>
23
- <div className="animate-fadeIn px-4 pt-4 flex gap-4 items-center">
24
- <div className="font-bold text-lg md:text-4xl">${dict.Model}s</div>
25
- <Link href={\`/${dict.model}/new\`}>
26
- <button className="inline-flex items-center justify-center gap-2 rounded-field bg-primary px-4 py-2 font-medium text-primary-foreground text-sm transition-colors hover:bg-primary/90">+ {l("base.createModel", { model: l("${dict.model}.modelName") })}</button>
27
- </Link>
28
- </div>
29
- <div>{l("${dict.model}.modelDesc")}</div>
30
- <div className="flex px-6 mt-3 gap-4">
31
- <${dict.Model}.Zone.Card
32
- className="animate-fadeIn grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 justify-center gap-4 w-full"
33
- init={${dict.model}InitInPublic}
34
- />
16
+ export default page()
17
+ .config({ transition: "none" })
18
+ .render(async () => {
19
+ const { l } = usePage();
20
+ const [{ ${dict.model}InitInPublic }] = await Promise.all([fetch.init${dict.Model}InPublic()]);
21
+ return (
22
+ <div className="container flex flex-col gap-4">
23
+ <div className="mt-5 h-full w-full px-5">
24
+ <div>{l("${dict.model}.modelName")}</div>
25
+ <div className="flex animate-fadeIn items-center gap-4 px-4 pt-4">
26
+ <div className="font-bold text-lg md:text-4xl">${dict.Model}s</div>
27
+ <Link className={buttonRecipe()} href="/${dict.model}/new">
28
+ + {l("base.createModel", { model: l("${dict.model}.modelName") })}
29
+ </Link>
30
+ </div>
31
+ <div>{l("${dict.model}.modelDesc")}</div>
32
+ <div className="mt-3 flex gap-4 px-6">
33
+ <${dict.Model}.Zone.Card
34
+ className="grid w-full animate-fadeIn grid-cols-1 justify-center gap-4 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5"
35
+ init={${dict.model}InitInPublic}
36
+ />
37
+ </div>
35
38
  </div>
36
39
  </div>
37
- </div>
38
- );
39
- }
40
- export const pageConfig = { transition: "none" } satisfies PageConfig;
41
- `,
40
+ );
41
+ });
42
+ `,
42
43
  };
43
44
  }
@@ -9,29 +9,34 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dic
9
9
  return {
10
10
  filename: "_index.tsx",
11
11
  content: `
12
- import type { PageConfig } from "akanjs/client";
13
- import { Model } from "akanjs/ui";
14
12
  import { ${dict.Model}, fetch, usePage } from "@apps/${dict.appName}/client";
13
+ import { page } from "akanjs/client";
14
+ import { buttonRecipe, Model } from "akanjs/ui";
15
15
 
16
- export default async function Page() {
17
- const { l } = usePage();
18
- const { ${dict.model}InitInPublic } = await fetch.init${dict.Model}InPublic();
19
- return (
20
- <>
21
- <div className="animate-fadeIn flex items-center gap-4 px-4 pt-4">
22
- <div className="text-lg font-bold md:text-4xl">{l("${dict.model}.modelName")}</div>
23
- <Model.New className="inline-flex items-center gap-2 rounded-field px-3 py-1.5 text-sm transition-colors hover:bg-muted" slice={fetch.slice.${dict.model}InPublic} renderTitle="id">
24
- <${dict.Model}.Template.General />
25
- </Model.New>
26
- </div>
27
- <${dict.Model}.Zone.Card
28
- className="animate-fadeIn mt-2 grid w-full grid-cols-1 justify-center gap-4 md:grid-cols-2 xl:grid-cols-3"
29
- init={${dict.model}InitInPublic}
30
- />
31
- </>
32
- );
33
- }
34
- export const pageConfig = { transition: "none" } satisfies PageConfig;
16
+ export default page()
17
+ .config({ transition: "none" })
18
+ .render(async () => {
19
+ const { l } = usePage();
20
+ const [{ ${dict.model}InitInPublic }] = await Promise.all([fetch.init${dict.Model}InPublic()]);
21
+ return (
22
+ <>
23
+ <div className="flex animate-fadeIn items-center gap-4 px-4 pt-4">
24
+ <div className="font-bold text-lg md:text-4xl">{l("${dict.model}.modelName")}</div>
25
+ <Model.New
26
+ className={buttonRecipe({ size: "sm", variant: "ghost" })}
27
+ slice={fetch.slice.${dict.model}InPublic}
28
+ renderTitle="id"
29
+ >
30
+ <${dict.Model}.Template.General />
31
+ </Model.New>
32
+ </div>
33
+ <${dict.Model}.Zone.Card
34
+ className="mt-2 grid w-full animate-fadeIn grid-cols-1 justify-center gap-4 md:grid-cols-2 xl:grid-cols-3"
35
+ init={${dict.model}InitInPublic}
36
+ />
37
+ </>
38
+ );
39
+ });
35
40
  `,
36
41
  };
37
42
  }
@@ -5,12 +5,14 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: { [
5
5
  const libs = scanInfo.getLibs();
6
6
  return {
7
7
  filename: "env.server.type.ts",
8
- content: `
9
- ${libs.length ? libs.map((lib) => `import { env as ${lib}Option } from "@libs/${lib}/server";`).join("\n") : 'import { getEnv } from "akanjs/base";'}
8
+ content: libs.length
9
+ ? `
10
+ ${libs.map((lib) => `import { env as ${lib}Option } from "@libs/${lib}/server";`).join("\n")}
10
11
 
11
12
  export const libEnv = {
12
- ${libs.length ? libs.map((lib) => ` ...${lib}Option,`).join("\n") : " ...getEnv(),"}
13
- };
14
- `,
13
+ ${libs.map((lib) => ` ...${lib}Option,`).join("\n")}
14
+ };`
15
+ : `
16
+ export const libEnv = {};`,
15
17
  };
16
18
  }
@@ -13,7 +13,7 @@ ${scalarModules.map((module) => `import { ${capitalize(module)} } from "./__scal
13
13
  ${databaseModules.length ? `import * as cnst from "./cnst";` : ""}
14
14
  ${databaseModules.map((module) => `import * as ${module}Db from "./${module}/${module}.document";`).join("\n")}
15
15
 
16
- ${libs.map((lib) => `export { db as ${lib} } from "@libs/${lib}/server";`).join("\n")}
16
+ ${libs.map((lib) => `export * as ${lib} from "@libs/${lib}/lib/db";`).join("\n")}
17
17
 
18
18
  ${databaseModules.map((module) => `class ${capitalize(module)}Input extends by(cnst.${capitalize(module)}Input) {}`).join("\n")}
19
19
  ${databaseModules.map((module) => `class ${capitalize(module)}Insight extends by(cnst.${capitalize(module)}Insight) {}`).join("\n")}
@@ -9,7 +9,7 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: { [
9
9
  const libs = scanInfo.getLibs();
10
10
  return `
11
11
  import { makeDictionary, makeTrans, registerScalarTrans, registerServiceTrans, registerModelTrans${libs.length === 0 ? `, dictionary as base` : ""} } from "akanjs/dictionary";
12
- ${libs.length ? libs.map((lib) => `import { dictionary as ${lib} } from "@libs/${lib}/server";`).join("\n") : ""}
12
+ ${libs.length ? libs.map((lib) => `import { dictionary as ${lib} } from "@libs/${lib}/lib/dict";`).join("\n") : ""}
13
13
 
14
14
  ${databaseModules.map((module) => `import * as ${module} from "./${module}/${module}.dictionary";`).join("\n")}
15
15
  ${serviceModules.map((module) => `import * as ${module} from "./_${module}/${module}.dictionary";`).join("\n")}
@@ -17,7 +17,8 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: { [
17
17
  return `
18
18
  import { FetchClient, type FetchClientType } from "akanjs/fetch";
19
19
  import { SignalRegistry, serverSignal${libs.length === 0 ? ", fetch as base" : ""} } from "akanjs/signal";
20
- ${libs.map((lib) => `import { fetch as ${lib} } from "@libs/${lib}/server";`).join("\n")}
20
+ import { Err } from "./dict";
21
+ ${libs.map((lib) => `import { fetch as ${lib} } from "@libs/${lib}/lib/sig";`).join("\n")}
21
22
 
22
23
  ${[...scanInfo.database.entries()]
23
24
  .filter(([_, files]) => files.has("signal"))
@@ -58,6 +59,9 @@ ${serviceModules.map((module) => `export const ${module} = SignalRegistry.regist
58
59
  export const fetchSignals = [${signalNames.join(", ")}] as const;
59
60
  export type Fetch = FetchClientType<typeof fetchSignals>;
60
61
  export const fetch = FetchClient.from(...fetchSignals) as unknown as Fetch;
62
+ // A failure restored from another process is this scope's own Err, so a server hop that rethrows one keeps its
63
+ // dictionary key and data instead of answering the original caller with Internal Server Error.
64
+ fetch.setErrorConstructor(Err);
61
65
 
62
66
  export const getSerializedSignal = () => fetch.serializedSignal
63
67
  `;
@@ -13,7 +13,11 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: { [
13
13
  const libs = scanInfo.getLibs();
14
14
  return `
15
15
  import { ServiceModel } from "akanjs/service";
16
- ${libs.length ? libs.map((lib) => `import { option as ${lib} } from "@libs/${lib}/server";`).join("\n") : 'import type { BackendEnv } from "akanjs/base";'}
16
+ ${
17
+ libs.length
18
+ ? libs.map((lib) => `import * as ${lib} from "@libs/${lib}/lib/option";`).join("\n")
19
+ : 'import type { BackendEnv } from "akanjs/base";'
20
+ }
17
21
 
18
22
  import * as cnst from "./cnst";
19
23
  import * as db from "./db";
@@ -21,7 +25,7 @@ import * as db from "./db";
21
25
  ${databaseModules.map((module) => `import { ${capitalize(module)}Service } from "./${module}/${module}.service";`).join("\n")}
22
26
  ${serviceModules.map((module) => `import { ${capitalize(module)}Service } from "./_${module}/${module}.service";`).join("\n")}
23
27
 
24
- ${libs.map((lib) => `export { srv as ${lib} } from "@libs/${lib}/server";`).join("\n")}
28
+ ${libs.map((lib) => `export * as ${lib} from "@libs/${lib}/lib/srv";`).join("\n")}
25
29
 
26
30
  ${databaseModules.map((module) => `export { ${capitalize(module)}Service } from "./${module}/${module}.service";`).join("\n")}
27
31
  ${serviceModules.map((module) => `export { ${capitalize(module)}Service } from "./_${module}/${module}.service";`).join("\n")}
@@ -18,6 +18,7 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dic
18
18
  import { modelDictionary } from "akanjs/dictionary";
19
19
 
20
20
  import type { ${dict.Model}, ${dict.Model}Insight } from "./${dict.model}.constant";
21
+ import type { ${dict.Model}Filter } from "./${dict.model}.document";
21
22
  import type { ${dict.Model}Endpoint, ${dict.Model}Slice } from "./${dict.model}.signal";
22
23
 
23
24
  export const dictionary = modelDictionary(["en", "ko"])
@@ -25,9 +26,11 @@ export const dictionary = modelDictionary(["en", "ko"])
25
26
  t(["${modelLabelEn}", "${modelLabelKo}"]).desc(["${modelDescEn}", "${modelDescKo}"])
26
27
  )
27
28
  .model<${dict.Model}>((t) => ({
28
- name: t(["Name", "이름"]),
29
+ name: t(["Name", "이름"]).desc(["Name", "이름"]),
29
30
  }))
30
31
  .insight<${dict.Model}Insight>((t) => ({}))
32
+ .query<${dict.Model}Filter>((fn) => ({}))
33
+ .sort<${dict.Model}Filter>((t) => ({}))
31
34
  .slice<${dict.Model}Slice>((fn) => ({
32
35
  inPublic: fn(["${dict.Model} In Public", "${dict.Model} 공개"]).arg((t) => ({})),
33
36
  }))
@@ -8,14 +8,13 @@ interface Dict {
8
8
  }
9
9
  export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dict) {
10
10
  return `
11
- import { endpoint, internal, Public, slice } from "akanjs/signal";
11
+ import { endpoint, internal, None, Public, slice } from "akanjs/signal";
12
12
 
13
- import * as cnst from "../cnst";
14
13
  import * as srv from "../srv";
15
14
 
16
15
  export class ${dict.Model}Internal extends internal(srv.${dict.model}, ({ interval }) => ({})) {}
17
16
 
18
- export class ${dict.Model}Slice extends slice(srv.${dict.model}, { guards: { root: Public, get: Public, cru: Public } }, (init) => ({
17
+ export class ${dict.Model}Slice extends slice(srv.${dict.model}, { guards: { root: None, get: Public, cru: Public } }, (init) => ({
19
18
  inPublic: init()
20
19
  .exec(function () {
21
20
  return this.${dict.model}Service.queryAny();
@@ -9,8 +9,7 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dic
9
9
  return `
10
10
  import { store } from "akanjs/store";
11
11
 
12
- import * as cnst from "../cnst";
13
- import { fetch, sig } from "../useClient";
12
+ import { sig } from "../useClient";
14
13
 
15
14
  export class ${dict.Model}Store extends store(sig.${dict.model}, () => ({
16
15
  // state
@@ -124,5 +124,4 @@ libs/*/client.ts
124
124
  libs/*/server.ts
125
125
  libs/*/index.ts
126
126
  **/.akan
127
- **/bun.lock
128
127
  **/tsconfig.tsbuildinfo
@@ -0,0 +1,16 @@
1
+ set -e
2
+
3
+ # Find commit files
4
+ echo "Finding commit files..."
5
+ FILES=$(git diff --cached --name-only --diff-filter=ACMR | sed 's| |\\ |g')
6
+ [ -z "$FILES" ] && exit 0
7
+
8
+ # Filter out ts, tsx, json files, should not exit when there are no lint files
9
+ LINT_FILES=$(echo "$FILES" | grep -E '(\.ts|\.tsx)$' || true)
10
+
11
+ echo "Checking commit files with Biome..."
12
+ # Run Biome autofix if there are lint files. Any remaining errors fail the commit.
13
+ if [ -n "$LINT_FILES" ]; then
14
+ echo "$LINT_FILES" | xargs ./node_modules/.bin/biome check --write --no-errors-on-unmatched --diagnostic-level=error
15
+ echo "$LINT_FILES" | xargs git add --
16
+ fi
@@ -3,7 +3,7 @@
3
3
  "editor.defaultFormatter": "biomejs.biome",
4
4
  "editor.formatOnSave": true,
5
5
  "editor.codeActionsOnSave": {
6
- "source.fixAll.biome": "explicit"
6
+ "source.fixAll.biome": "always"
7
7
  },
8
8
  "[typescript]": {
9
9
  "editor.defaultFormatter": "biomejs.biome"
@@ -12,6 +12,10 @@ The section below is regenerated by `akan agent install` (run `bun run setup:age
12
12
  workspace's apps, generated files, validation commands, and framework guide. Edit anything outside the
13
13
  markers freely; content between them is overwritten on the next install.
14
14
 
15
+ It carries the rules only. The reasoning behind each area lives in deep-dive guidelines fetched on demand —
16
+ `akan guideline list` names them, `akan guideline show <name>` prints one, and an agent wired to `akan mcp`
17
+ calls `get_guideline` instead.
18
+
15
19
  <!-- akan:agent:start -->
16
20
  <!-- Populated by `akan agent install`. Run `bun run setup:agent` to refresh. -->
17
21
  <!-- akan:agent:end -->
@@ -1,3 +1,22 @@
1
1
  # <%= repoName %> — Claude Code Guide
2
2
 
3
3
  @AGENTS.md
4
+
5
+ ## Comments — Overrides Your Default
6
+
7
+ Write **no comments** unless the comment passes the test below. This is the rule agents break most often here, so it
8
+ is repeated outside the guide: a diff that adds a comment the test rejects is a diff to redo.
9
+
10
+ Before typing `//`, `/*`, or a doc block, ask — **does this sentence carry a fact that is nowhere in the code?**
11
+
12
+ - Restates the identifier, the signature, or the line under it → delete it.
13
+ - Labels a section (`// helpers`, `// state`) or narrates a step (`// fetch the user`, `// then save`) → delete it.
14
+ - JSDoc on an ordinary function, or a why/how preamble on ordinary logic → delete it.
15
+ - Explains the edit you just made, for whoever reads the diff → say it in your reply, not in the file.
16
+ - Names a vendor or protocol quirk, an infrastructure constraint, a library gotcha, security reasoning, a math
17
+ derivation, a domain field's business meaning, a state transition, or why an obvious alternative was rejected →
18
+ keep it, one line.
19
+
20
+ That keep-list is exact — `Comments` in the guide is the full version. "It aids readability" and "this logic is
21
+ subtle" are not on it: rename or split the code instead. When you edit an existing file, match its density; if the
22
+ surrounding code carries none, your diff carries none.
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://biomejs.dev/schemas/2.5.8/schema.json",
2
+ "$schema": "https://biomejs.dev/schemas/2.5.12/schema.json",
3
3
  "extends": ["@akanjs/devkit/biome.base.json"],
4
4
  "files": {
5
5
  "includes": [
@@ -47,25 +47,21 @@ See `docs/GENERATED.md` for the generated file list.
47
47
 
48
48
  ## House Style
49
49
 
50
- `AGENTS.md` holds the full style guide. The rules agents break most often:
50
+ `AGENTS.md` holds the full style guide, and `akan lint` enforces most of it. The four rules that surprise people,
51
+ because the failure is silent rather than an error:
51
52
 
52
53
  - **Never hand-order Tailwind classes** — the linter sorts them, including inside `cn()`, and its output looks
53
- unnatural on purpose.
54
+ unnatural on purpose. Do not reorder it back.
54
55
  - **Never use a colour outside the semantic vocabulary** — `bg-red-500`, `bg-[#3b82f6]` and `text-base-content`
55
56
  compile to no CSS at all, so the element renders unstyled with no error. Use `bg-primary`, `text-foreground/70`
56
57
  and the other tokens defined in `page/*/styles.css`.
57
- - **Never `throw new Error`** — throw `new Err("<module>.error.<key>")` with an `[en, ko]` entry in the module
58
- dictionary. `common/` cannot import `Err`, so keep throwing code out of it.
59
- - **Never import a third-party package** from a page, a barrel, or a module file. Re-export it through a one-line
60
- shim in `base/`, `webkit/`, or `ui/` first.
61
- - `#private` is lint-banned in `*.constant.ts`, `*.document.ts`, `*.service.ts`, and `*.store.ts` only; it stays
62
- the house style under `srvkit/`.
63
- - Components are `export const X = ({ … }: XProps) => { … }` with `interface XProps` directly above and
64
- `className?: string` first. No `React.FC`, no non-null assertions, no `as any`.
65
- - `cond ? <X/> : null`, never `{cond && <X/>}` — the latter renders the string `"false"` in a className context.
66
- - Put display and predicate logic on the `Light<Model>` constant class; keep document chain methods
67
- validate → mutate → `return this` without `save()`; keep services to load → chain → save.
68
- - Do not narrate code in comments. Do document vendor quirks, infrastructure constraints, and security reasoning.
58
+ - **`cond ? <X/> : null`, never `{cond && <X/>}`** — the latter renders the string `"false"` in a className context.
59
+ - **Never wrap a form setter in a pass-through arrow** — `onChange={st.do.setXOnY}` publishes the field to agents
60
+ and E2E selectors; `onChange={(v) => st.do.setXOnY(v)}` runs identically and publishes nothing.
61
+
62
+ Two more that are hard errors: **never `throw new Error`** (throw `new Err("<module>.error.<key>")` with an
63
+ `[en, ko]` dictionary entry), and **never import a third-party package** from a page, a barrel, or a module file —
64
+ re-export it through a one-line shim in the lib's `common/`, `webkit/`, or `ui/` first.
69
65
 
70
66
  ## Abstract Documents
71
67
 
@@ -9,20 +9,21 @@ sync or build can overwrite local changes.
9
9
  | --- | --- |
10
10
  | `apps/*/client.ts` | App-wide client entrypoint for generated fetch, store, and client runtime exports. |
11
11
  | `apps/*/server.ts` | App-wide server entrypoint for generated server, service, signal, database, and dictionary exports. |
12
+ | `libs/*/client.ts`, `libs/*/server.ts`, `libs/*/index.ts` | The same entrypoints for a library. |
12
13
 
13
- ## App Library Barrels
14
+ ## Module Barrels (apps and libs alike)
14
15
 
15
16
  | File | Purpose |
16
17
  | --- | --- |
17
- | `apps/*/lib/cnst.ts` | Re-exports constants and model shapes from module `*.constant.ts` files. |
18
- | `apps/*/lib/db.ts` | Re-exports database models from module `*.document.ts` files. |
19
- | `apps/*/lib/dict.ts` | Re-exports dictionaries from module `*.dictionary.ts` files. |
20
- | `apps/*/lib/srv.ts` | Re-exports services from module `*.service.ts` files. |
21
- | `apps/*/lib/sig.ts` | Re-exports endpoints, slices, and internals from module `*.signal.ts` files. |
22
- | `apps/*/lib/st.ts` | Re-exports stores from module `*.store.ts` files. |
23
- | `apps/*/lib/useClient.ts` | Client-safe generated imports for fetch, message, signal, and store usage. |
24
- | `apps/*/lib/useServer.ts` | Server-safe generated imports for service, database, signal, and dictionary usage. |
25
- | `apps/*/lib/**/index.ts` | Per-module generated barrel files. |
18
+ | `{apps,libs}/*/lib/cnst.ts` | Re-exports constants and model shapes from module `*.constant.ts` files. |
19
+ | `{apps,libs}/*/lib/db.ts` | Re-exports database models from module `*.document.ts` files. |
20
+ | `{apps,libs}/*/lib/dict.ts` | Re-exports dictionaries from module `*.dictionary.ts` files. |
21
+ | `{apps,libs}/*/lib/srv.ts` | Re-exports services from module `*.service.ts` files. |
22
+ | `{apps,libs}/*/lib/sig.ts` | Re-exports endpoints, slices, and internals from module `*.signal.ts` files. |
23
+ | `{apps,libs}/*/lib/st.ts` | Re-exports stores from module `*.store.ts` files. |
24
+ | `{apps,libs}/*/lib/useClient.ts` | Client-safe generated imports for fetch, message, signal, and store usage. |
25
+ | `{apps,libs}/*/lib/useServer.ts` | Server-safe generated imports for service, database, signal, and dictionary usage. |
26
+ | `{apps,libs}/*/lib/**/index.ts` | Per-module generated barrel files. |
26
27
 
27
28
  ## Shared Surface Barrels
28
29
 
@@ -32,6 +33,7 @@ sync or build can overwrite local changes.
32
33
  | `*/webkit/index.ts` | Re-exports webkit/browser helper files. |
33
34
  | `*/srvkit/index.ts` | Re-exports server-kit helper files. |
34
35
  | `*/common/index.ts` | Re-exports common helper files. |
36
+ | `*/plugin/index.ts` | Re-exports `<name>.plugin.ts` declarations. |
35
37
 
36
38
  ## How To Change Generated Output
37
39
 
@@ -31,8 +31,6 @@
31
31
  "dependencies": {},
32
32
  "devDependencies": {},
33
33
  "patchedDependencies": {
34
- "react-dom@19.2.7": "patches/react-dom@19.2.7.patch",
35
- "zod@3.25.76": "patches/zod@3.25.76.patch",
36
- "zod@4.4.3": "patches/zod@4.4.3.patch"
34
+ "react-dom@19.2.7": "patches/react-dom@19.2.7.patch"
37
35
  }
38
- }
36
+ }
@@ -0,0 +1,7 @@
1
+ // @bun
2
+ import {
3
+ TypeChecker2
4
+ } from "./index-92zztqy1.js";
5
+ export {
6
+ TypeChecker2 as TypeChecker
7
+ };
package/typecheck.proc.js CHANGED
@@ -1,8 +1,7 @@
1
1
  // @bun
2
2
  import {
3
- TypeChecker
4
- } from "./index-wnp7hwq7.js";
5
- import"./index-r24hmh0q.js";
3
+ TypeChecker2
4
+ } from "./index-92zztqy1.js";
6
5
 
7
6
  // pkgs/@akanjs/devkit/typecheck/typecheck.proc.ts
8
7
  import { Logger } from "akanjs/common";
@@ -12,7 +11,7 @@ try {
12
11
  const cwdPath = process.env.AKAN_TYPECHECK_CWD;
13
12
  if (!cwdPath)
14
13
  throw new Error("AKAN_TYPECHECK_CWD is required");
15
- const typeChecker = new TypeChecker({ cwdPath });
14
+ const typeChecker = new TypeChecker2({ cwdPath });
16
15
  const { fileDiagnostics, fileErrors, fileWarnings } = typeChecker.check(filePath);
17
16
  const message = typeChecker.formatDiagnostics(fileDiagnostics);
18
17
  Logger.rawLog(JSON.stringify({
@@ -26,7 +25,7 @@ try {
26
25
  const configPath = process.env.AKAN_TYPECHECK_TSCONFIG;
27
26
  if (!configPath)
28
27
  throw new Error("AKAN_TYPECHECK_TSCONFIG is required");
29
- const result = TypeChecker.checkProject(configPath);
28
+ const result = TypeChecker2.checkProject(configPath);
30
29
  if (result.errors.length > 0) {
31
30
  console.error(result.message);
32
31
  process.exit(1);
@@ -1,35 +1,32 @@
1
1
  // @bun
2
2
  import {
3
- WorkflowRunner
4
- } from "./index-cv9cxs5k.js";
5
- import {
6
- ScalarScript
7
- } from "./index-4mgkgba3.js";
3
+ Workspace,
4
+ script,
5
+ command
6
+ } from "./index-mak3cd28.js";
7
+ import"./index-q0y2jq9j.js";
8
+ import"./index-2tv3fdx4.js";
9
+ import"./index-6wwzs1bc.js";
8
10
  import {
9
- PrimitiveScript
10
- } from "./index-m90fn8xe.js";
11
+ createWorkflowStepRegistry
12
+ } from "./index-gyd220p2.js";
13
+ import"./index-kn1h7p1x.js";
11
14
  import {
12
15
  ModuleScript
13
- } from "./index-mewacxye.js";
14
- import"./index-ss469dec.js";
15
- import"./index-65aeh789.js";
16
- import"./index-0cj2zxbm.js";
17
- import"./index-e4b2ae6b.js";
16
+ } from "./index-8pm30m73.js";
17
+ import"./index-pnqbkf5p.js";
18
+ import"./index-h7yw2z9n.js";
18
19
  import {
19
- createWorkflowStepRegistry
20
- } from "./index-kcsa1zff.js";
21
- import"./index-j37qq1f2.js";
20
+ PrimitiveScript
21
+ } from "./index-4edzf1gr.js";
22
22
  import {
23
- Workspace,
24
- command,
25
- script
26
- } from "./index-etwh7sd3.js";
27
- import"./index-yzsxc30b.js";
28
- import"./index-mxvakhsm.js";
29
- import"./index-xys926f2.js";
30
- import"./index-1577bej2.js";
31
- import"./index-67546d0j.js";
32
- import"./index-r24hmh0q.js";
23
+ ScalarScript
24
+ } from "./index-rwg2aa4f.js";
25
+ import"./index-by5gpp8x.js";
26
+ import"./index-ktb5njgy.js";
27
+ import {
28
+ WorkflowRunner
29
+ } from "./index-7737gxcp.js";
33
30
 
34
31
  // pkgs/@akanjs/cli/workflow/workflow.script.ts
35
32
  import { Logger } from "akanjs/common";