@akanjs/cli 3.0.0-beta.19 → 3.0.0-beta.20

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 (95) hide show
  1. package/.build-stamp +1 -1
  2. package/{CodeAgent-6cm97kay.js → CodeAgent-awv258wb.js} +2 -2
  3. package/{CodeTui-za4jsm41.js → CodeTui-1nqh35ez.js} +20 -22
  4. package/TunnelShare-scf4e4pd.js +9 -0
  5. package/{agent.command-e0wpbbyg.js → agent.command-1s9ag7sb.js} +8 -9
  6. package/akanCode.js +4 -4
  7. package/{application.command-8wyxqc8q.js → application.command-49hwy6va.js} +25 -56
  8. package/{applicationBuildRunner-n9gzaxd0.js → applicationBuildRunner-ybyp97pv.js} +33 -59
  9. package/{applicationReleasePackager-vpggfqgq.js → applicationReleasePackager-esnrphw8.js} +40 -60
  10. package/buildBatch.proc.js +19 -24
  11. package/{capacitorApp-q3z0qht0.js → capacitorApp-1synz4en.js} +3 -4
  12. package/{cloud.command-4zwa5dsx.js → cloud.command-d7rqtzt9.js} +16 -26
  13. package/cloud.script-bkbpcr96.js +19 -0
  14. package/{code.command-468c9d7s.js → code.command-nn48xzej.js} +22 -37
  15. package/context.command-s3mcmvpa.js +48 -0
  16. package/context.runner-k99nb5pk.js +21 -0
  17. package/{dependencyScanner-0z2h2tks.js → dependencyScanner-ye2e6pdz.js} +2 -2
  18. package/{devTui-ffjsarqa.js → devTui-q7k7bakd.js} +5 -9
  19. package/fileSys-5ngz93ga.js +9 -0
  20. package/{guideline.command-vhw13pqr.js → guideline.command-sct4qnt5.js} +4 -5
  21. package/guidelines/conventions/conventions.instruction.md +5 -1
  22. package/guidelines/mcpRule/mcpRule.instruction.md +7 -5
  23. package/incrementalBuilder.proc.js +30 -48
  24. package/{index-s5rhm04y.js → index-0bq14vr1.js} +1 -1
  25. package/{index-10dkrrww.js → index-13ffe9wp.js} +4 -4
  26. package/{index-srmay5jw.js → index-22d57v4c.js} +84 -67
  27. package/{index-53176s7j.js → index-31yr441d.js} +10 -17
  28. package/index-3hx1z96c.js +87 -0
  29. package/{index-4m929vvn.js → index-3sq321ak.js} +10 -18
  30. package/{index-bhtmj233.js → index-3t7g9e4r.js} +41 -78
  31. package/{index-q0y2jq9j.js → index-5b6tavv3.js} +6 -3
  32. package/{index-47pj3aee.js → index-5e0n4hqx.js} +11 -12
  33. package/{index-7ep8qtvp.js → index-5pc1qrbv.js} +5 -8
  34. package/{index-esk82rvk.js → index-8mna0947.js} +34 -71
  35. package/{index-sq2dzkzm.js → index-8sf7wmdr.js} +6 -6
  36. package/{index-crmeqnmf.js → index-9d9bgcx4.js} +283 -722
  37. package/{index-bwf965h6.js → index-ahemdr5n.js} +6 -6
  38. package/{index-ab0c38ea.js → index-as7xmyz8.js} +20 -20
  39. package/{index-bc88j1ry.js → index-axzjaqve.js} +94 -142
  40. package/{index-3d9y066c.js → index-bjwxs904.js} +9 -8
  41. package/{index-667w0yah.js → index-c6eggbee.js} +2 -5
  42. package/{index-a1w6934z.js → index-ddxvdd1p.js} +169 -305
  43. package/{index-92zztqy1.js → index-dy0jx9ay.js} +2 -17
  44. package/{index-22xtgmhn.js → index-dzf3r49a.js} +1 -1
  45. package/{index-89hy31kf.js → index-fgq75haa.js} +172 -287
  46. package/{index-by5gpp8x.js → index-hj6w4ka1.js} +2 -1
  47. package/{index-hwkygn9s.js → index-khpfpcsd.js} +302 -33
  48. package/{index-vqx8bdxz.js → index-mxav6j3c.js} +78 -231
  49. package/{index-2446k7b4.js → index-myhc3c1j.js} +512 -588
  50. package/{index-3jrp517k.js → index-nv5976x3.js} +45 -128
  51. package/{index-zqgj2rt2.js → index-przybvy5.js} +69 -147
  52. package/{index-n3cv0tm4.js → index-smme4r47.js} +1 -1
  53. package/{index-qdgzsnhg.js → index-w2zdcw3k.js} +110 -231
  54. package/{index-14zrtgfa.js → index-wa5jbxj1.js} +6 -39
  55. package/{index-bftkz6cp.js → index-ww4z397j.js} +198 -555
  56. package/{index-kwaq3n9n.js → index-xqjwd384.js} +4 -7
  57. package/{index-txr7dj2g.js → index-xqpzbab5.js} +106 -240
  58. package/{index-e4v6vhxq.js → index-xsjh6nzh.js} +178 -165
  59. package/{index-18zybgkc.js → index-ygn77a5w.js} +47 -99
  60. package/{index-9d6nvkz2.js → index-ztp3e73t.js} +79 -35
  61. package/index.js +23 -24
  62. package/{library.command-cqr175dy.js → library.command-1gx04jgn.js} +4 -5
  63. package/{localRegistry.command-49z55qqz.js → localRegistry.command-zndxj1q6.js} +21 -42
  64. package/{module.command-9p8mm3b0.js → module.command-3waddk95.js} +6 -7
  65. package/{package.command-wxyz909t.js → package.command-zrc7br1y.js} +5 -6
  66. package/package.json +2 -2
  67. package/{page.command-gsrsfqqs.js → page.command-vpjgardh.js} +4 -5
  68. package/{primitive.command-ns1mptje.js → primitive.command-sz84tk4t.js} +9 -20
  69. package/{prompter-1f8d9pcc.js → prompter-ptaa3nk0.js} +2 -2
  70. package/{quality.command-e76k2q9k.js → quality.command-g869hafs.js} +129 -363
  71. package/{recipeScanner-fpagtgc1.js → recipeScanner-4b69ybe0.js} +1 -1
  72. package/{repair.command-pkrsm3cw.js → repair.command-chsnjvvv.js} +11 -35
  73. package/{scalar.command-0cpt3fc8.js → scalar.command-2v21newx.js} +5 -6
  74. package/skills/akan-code/SKILL.md +12 -4
  75. package/{subspace.command-fktpwp0g.js → subspace.command-ckcbwfp1.js} +39 -58
  76. package/templates/appSample/srvkit/{AuthGuard.ts → guards.ts} +3 -3
  77. package/templates/appSample/srvkit/{SessionInternalArg.ts → internalArgs.ts} +3 -3
  78. package/templates/client.ts +7 -30
  79. package/templates/lib/__lib/lib.dictionary.ts +0 -2
  80. package/templates/lib/__lib/lib.document.ts +0 -2
  81. package/templates/lib/sig.ts +8 -30
  82. package/templates/server.ts +0 -2
  83. package/{tunnel.command-d5jy9gk8.js → tunnel.command-kd2yr4fx.js} +5 -6
  84. package/{typeChecker-3xgrzc2v.js → typeChecker-px49mezc.js} +1 -1
  85. package/typecheck.proc.js +1 -1
  86. package/workflow.command-44252cqv.js +79 -0
  87. package/{workspace.command-gv84eh1p.js → workspace.command-fqcztt5p.js} +72 -107
  88. package/TunnelShare-2j6s511d.js +0 -9
  89. package/cloud.script-fwx3vb34.js +0 -20
  90. package/context.command-dsnw0jby.js +0 -80
  91. package/context.runner-rs4rj15d.js +0 -22
  92. package/devTuiView-1q1mdgrv.js +0 -9
  93. package/getDirname-dr3jz1xg.js +0 -7
  94. package/index-6wwzs1bc.js +0 -7
  95. package/workflow.command-6tkcysmx.js +0 -105
@@ -3,7 +3,7 @@ import {
3
3
  collectRecipeSources2,
4
4
  scanRecipes2,
5
5
  findInlineRecipeDuplicates2
6
- } from "./index-by5gpp8x.js";
6
+ } from "./index-hj6w4ka1.js";
7
7
  export {
8
8
  collectRecipeSources2 as collectRecipeSources,
9
9
  findInlineRecipeDuplicates2 as findInlineRecipeDuplicates,
@@ -3,34 +3,21 @@ import {
3
3
  Workspace,
4
4
  script,
5
5
  command
6
- } from "./index-qdgzsnhg.js";
7
- import"./index-q0y2jq9j.js";
8
- import"./index-crmeqnmf.js";
9
- import"./index-6wwzs1bc.js";
10
- import"./index-by5gpp8x.js";
11
- import"./index-2446k7b4.js";
12
- import"./index-18zybgkc.js";
6
+ } from "./index-w2zdcw3k.js";
7
+ import"./index-5b6tavv3.js";
8
+ import"./index-9d9bgcx4.js";
9
+ import"./index-hj6w4ka1.js";
10
+ import"./index-myhc3c1j.js";
11
+ import"./index-ygn77a5w.js";
13
12
  import {
14
13
  RepairRunner
15
- } from "./index-53176s7j.js";
14
+ } from "./index-31yr441d.js";
16
15
 
17
16
  // pkgs/@akanjs/cli/repair/repair.script.ts
18
17
  import { Logger } from "akanjs/common";
19
18
  class RepairScript extends script("repair", [RepairRunner]) {
20
- async repair(kind, {
21
- workspace,
22
- app = null,
23
- module = null,
24
- target = null,
25
- format = "markdown"
26
- }) {
27
- Logger.rawLog(await this.repairRunner.repair(kind, {
28
- workspace,
29
- app,
30
- module,
31
- target,
32
- format
33
- }));
19
+ async repair(kind, options) {
20
+ Logger.rawLog(await this.repairRunner.repair(kind, options));
34
21
  }
35
22
  }
36
23
 
@@ -39,12 +26,7 @@ class RepairCommand extends command("repair", [RepairScript], ({ public: target
39
26
  repair: target({ desc: "Run a narrow Akan repair command and return a structured report" }).arg("kind", String, {
40
27
  desc: "generated, format, imports, dictionary, or module-shape",
41
28
  enum: ["generated", "format", "imports", "dictionary", "module-shape"]
42
- }).with(Workspace).option("format", String, {
43
- desc: "output format",
44
- flag: "o",
45
- default: "markdown",
46
- enum: ["markdown", "json"]
47
- }).option("app", String, {
29
+ }).with(Workspace).option("format", String, { desc: "output format", flag: "o", default: "markdown", enum: ["markdown", "json"] }).option("app", String, {
48
30
  desc: "target app or library for generated/dictionary/module-shape repair",
49
31
  nullable: true
50
32
  }).option("module", String, { desc: "target module for dictionary/module-shape repair", nullable: true }).option("target", String, {
@@ -52,13 +34,7 @@ class RepairCommand extends command("repair", [RepairScript], ({ public: target
52
34
  desc: "target app, library, or package for format/imports repair",
53
35
  nullable: true
54
36
  }).exec(async function(kind, workspace, format, app, module, targetName) {
55
- await this.repairScript.repair(kind, {
56
- workspace,
57
- format,
58
- app,
59
- module,
60
- target: targetName
61
- });
37
+ await this.repairScript.repair(kind, { workspace, format, app, module, target: targetName });
62
38
  })
63
39
  })) {
64
40
  }
@@ -2,16 +2,15 @@
2
2
  import {
3
3
  Sys,
4
4
  command
5
- } from "./index-qdgzsnhg.js";
6
- import"./index-q0y2jq9j.js";
7
- import"./index-crmeqnmf.js";
8
- import"./index-6wwzs1bc.js";
5
+ } from "./index-w2zdcw3k.js";
6
+ import"./index-5b6tavv3.js";
7
+ import"./index-9d9bgcx4.js";
9
8
  import {
10
9
  renderPrimitiveReport
11
- } from "./index-2446k7b4.js";
10
+ } from "./index-myhc3c1j.js";
12
11
  import {
13
12
  ScalarScript
14
- } from "./index-4m929vvn.js";
13
+ } from "./index-3sq321ak.js";
15
14
 
16
15
  // pkgs/@akanjs/cli/scalar/scalar.command.ts
17
16
  import { Logger, lowerlize } from "akanjs/common";
@@ -15,8 +15,9 @@ which command makes it take effect.
15
15
 
16
16
  ## MCP servers
17
17
 
18
- Declared in **`.akan/code/mcp.json`**, in the same `mcpServers` shape Claude, Cursor and VS Code already
19
- write, so a block can be pasted across rather than translated. VS Code's `servers` spelling is read too, and
18
+ Declared in **`~/.akan/code/mcp.json`**, which every repo reads, or in this repo's **`.akan/code/mcp.json`**,
19
+ which wins a name both declare — in the same `mcpServers` shape Claude, Cursor and VS Code already write, so a
20
+ block can be pasted across rather than translated. VS Code's `servers` spelling is read too, and
20
21
  whichever key the file already uses is the one a write goes back into.
21
22
 
22
23
  ```jsonc
@@ -41,7 +42,9 @@ From the prompt:
41
42
  /mcp <name> the tools that one server published
42
43
  /mcp add <name> <command> [args…]
43
44
  /mcp add <name> <https://…>
44
- /mcp remove <name>
45
+ /mcp add --local <name> … this repo's file only, not ~/.akan/code/mcp.json
46
+ /mcp remove <name> this repo's file first, else ~/.akan/code/mcp.json
47
+ /mcp remove --local <name>
45
48
  /mcp login <name> OAuth, in the browser
46
49
  /mcp logout <name> forget the token, leaving the server declared
47
50
  /mcp reload reopen this session so the file takes effect
@@ -52,11 +55,16 @@ session is created, so `add`, `remove`, `login` and `logout` all reload by thems
52
55
  said nothing yet has nothing on disk to reopen, and says so. If you edit `mcp.json` yourself, tell the user to
53
56
  run `/mcp reload`.
54
57
 
58
+ `/mcp remove` on a name both files declare takes this repo's entry and leaves the home file's in force; its
59
+ notice says so, and running it again removes that one too.
60
+
55
61
  Sign-in is discovered, not configured: the server's `401` names its resource metadata, that names the
56
62
  authorization server, and most hosted servers register a client on demand — so a url is usually the whole
57
63
  entry. For a provider that issues client ids by hand, add `"oauth": { "clientId": "…", "scope": "…" }`.
58
64
  Tokens are stored per server in `~/.akan/code/mcpAuth.json` at mode 0600, never in the repo, and refreshed
59
- silently; `/mcp` shows `sign-in needed` when a server wants one.
65
+ silently — at connect when one has expired, and mid-session when a server refuses one, after which the call is
66
+ retried once. When a refresh cannot fix it, `/mcp` shows `sign-in needed` and that server's tools answer with
67
+ `/mcp login <name>` until the user signs in; the sign-in reloads the session, which brings the server back.
60
68
 
61
69
  ## Sessions
62
70
 
@@ -1,29 +1,28 @@
1
1
  // @bun
2
2
  import {
3
- FileSys
4
- } from "./index-q0y2jq9j.js";
3
+ FileSys2
4
+ } from "./index-5b6tavv3.js";
5
5
  import {
6
6
  GlobalConfig
7
- } from "./index-srmay5jw.js";
7
+ } from "./index-22d57v4c.js";
8
8
  import {
9
9
  Workspace,
10
10
  CommandContainer,
11
11
  runner,
12
12
  script,
13
13
  command
14
- } from "./index-qdgzsnhg.js";
14
+ } from "./index-w2zdcw3k.js";
15
15
  import {
16
16
  Executor,
17
17
  WorkspaceExecutor,
18
18
  AppExecutor
19
- } from "./index-crmeqnmf.js";
20
- import"./index-6wwzs1bc.js";
19
+ } from "./index-9d9bgcx4.js";
21
20
  import {
22
21
  SlicePlanner
23
- } from "./index-kwaq3n9n.js";
22
+ } from "./index-xqjwd384.js";
24
23
  import {
25
24
  LibSource
26
- } from "./index-3d9y066c.js";
25
+ } from "./index-bjwxs904.js";
27
26
 
28
27
  // pkgs/@akanjs/devkit/subspace.ts
29
28
  import { mkdir, readdir, rename, rm } from "fs/promises";
@@ -118,16 +117,16 @@ class Subspace {
118
117
  return true;
119
118
  const normalize = (content) => {
120
119
  try {
121
- const manifest = JSON.parse(content);
122
- delete manifest[LibSource.manifestKey];
123
- return JSON.stringify(manifest);
120
+ return LibSource.unstamped(content);
124
121
  } catch {
125
122
  return content;
126
123
  }
127
124
  };
128
125
  return normalize(theirs) !== normalize(ours);
129
126
  }
130
- async#meaningfulFiles(ref, files) {
127
+ async#changedSliceFiles(ref, diffArgs) {
128
+ const files = (await this.#git(["diff", "--name-only", ...diffArgs])).split(`
129
+ `).filter((file) => !!file.trim() && !this.#isSubspaceOwned(file));
131
130
  const kept = await Promise.all(files.map(async (file) => this.#isStamped(file) ? await this.#differsBeyondStamp(ref, file) : true));
132
131
  return files.filter((_, index) => kept[index]);
133
132
  }
@@ -140,14 +139,12 @@ class Subspace {
140
139
  if (!hasBranch)
141
140
  return { name: this.name, branch, hasBranch, anchor, behindPaths: [], driftedLibs: [] };
142
141
  const ref = `${this.#remote}/${branch}`;
143
- const diff = await this.#git(["diff", "--name-only", "HEAD", ref, "--", ...paths]);
144
- const behindPaths = await this.#meaningfulFiles(ref, diff.split(`
145
- `).filter((file) => !!file.trim()).filter((file) => !this.#isSubspaceOwned(file)));
142
+ const behindPaths = await this.#changedSliceFiles(ref, ["HEAD", ref, "--", ...paths]);
146
143
  const driftedLibs = libs.filter((lib) => behindPaths.some((file) => file.startsWith(`libs/${lib}/`)));
147
144
  return { name: this.name, branch, hasBranch, anchor, behindPaths, driftedLibs };
148
145
  }
149
146
  async#ensureClone(branch) {
150
- if (!await FileSys.dirExists(path.join(this.#clonePath, ".git"))) {
147
+ if (!await FileSys2.dirExists(path.join(this.#clonePath, ".git"))) {
151
148
  await rm(this.#clonePath, { recursive: true, force: true });
152
149
  await mkdir(path.dirname(this.#clonePath), { recursive: true });
153
150
  await this.#workspace.spawn("git", ["clone", "--quiet", this.#declaration.repo, this.#clonePath]);
@@ -164,12 +161,12 @@ class Subspace {
164
161
  await rm(holdRoot, { recursive: true, force: true });
165
162
  for (const member of Subspace.memberDirs) {
166
163
  const memberRoot = path.join(this.#clonePath, member);
167
- if (!await FileSys.dirExists(memberRoot))
164
+ if (!await FileSys2.dirExists(memberRoot))
168
165
  continue;
169
166
  for (const name of await readdir(memberRoot)) {
170
167
  for (const owned of Subspace.subspaceOwnedDirs) {
171
168
  const from = path.join(memberRoot, name, owned);
172
- if (!await FileSys.dirExists(from))
169
+ if (!await FileSys2.dirExists(from))
173
170
  continue;
174
171
  const to = path.join(holdRoot, member, name, owned);
175
172
  await mkdir(path.dirname(to), { recursive: true });
@@ -192,7 +189,7 @@ class Subspace {
192
189
  const target = path.join(to, entry.name);
193
190
  if (entry.isDirectory())
194
191
  await Subspace.#copyMissing(source, target);
195
- else if (!await FileSys.entryExists(target))
192
+ else if (!await FileSys2.entryExists(target))
196
193
  await rename(source, target);
197
194
  }
198
195
  }
@@ -225,32 +222,32 @@ class Subspace {
225
222
  }
226
223
  async#writeLocalEnv() {
227
224
  const excludePath = path.join(this.#clonePath, ".git/info/exclude");
228
- const exclude = await FileSys.fileExists(excludePath) ? await FileSys.readText(excludePath) : "";
225
+ const exclude = await FileSys2.fileExists(excludePath) ? await FileSys2.readText(excludePath) : "";
229
226
  if (!exclude.split(`
230
227
  `).includes("/.env")) {
231
228
  await mkdir(path.dirname(excludePath), { recursive: true });
232
- await FileSys.writeText(excludePath, exclude.trim() ? `${exclude.replace(/\n*$/, `
229
+ await FileSys2.writeText(excludePath, exclude.trim() ? `${exclude.replace(/\n*$/, `
233
230
  `)}/.env
234
231
  ` : `/.env
235
232
  `);
236
233
  }
237
234
  const envPath = path.join(this.#clonePath, ".env");
238
- if (await FileSys.fileExists(envPath))
235
+ if (await FileSys2.fileExists(envPath))
239
236
  return;
240
237
  const lines = Object.entries(this.#localEnv()).map(([key, value]) => `${key}=${value}`);
241
- await FileSys.writeText(envPath, `${lines.join(`
238
+ await FileSys2.writeText(envPath, `${lines.join(`
242
239
  `)}
243
240
  `);
244
241
  }
245
242
  async#rewriteManifest(plans) {
246
243
  const manifestPath = path.join(this.#clonePath, "package.json");
247
- if (!await FileSys.fileExists(manifestPath))
244
+ if (!await FileSys2.fileExists(manifestPath))
248
245
  return [];
249
- const rootPackageJson = await FileSys.readJson(manifestPath);
246
+ const rootPackageJson = await FileSys2.readJson(manifestPath);
250
247
  const { packageJson, pruned, warnings } = await SlicePlanner.pruneDependencies(this.#workspace, rootPackageJson, plans.flatMap((plan) => plan.requiredDependencies));
251
248
  for (const warning of warnings)
252
249
  this.#workspace.logger.warn(warning);
253
- await FileSys.writeJson(manifestPath, {
250
+ await FileSys2.writeJson(manifestPath, {
254
251
  ...packageJson,
255
252
  name: this.name,
256
253
  description: `${this.name} workspace`
@@ -277,10 +274,10 @@ class Subspace {
277
274
  }
278
275
  async#rewriteGitignore() {
279
276
  const gitignorePath = path.join(this.#clonePath, ".gitignore");
280
- if (!await FileSys.fileExists(gitignorePath))
277
+ if (!await FileSys2.fileExists(gitignorePath))
281
278
  return;
282
279
  const [begin = "", end = ""] = Subspace.secretsMarkers;
283
- const lines = (await FileSys.readText(gitignorePath)).split(/\r?\n/);
280
+ const lines = (await FileSys2.readText(gitignorePath)).split(/\r?\n/);
284
281
  const beginIdx = lines.indexOf(begin);
285
282
  const endIdx = lines.indexOf(end);
286
283
  const filtered = beginIdx >= 0 && endIdx > beginIdx ? [
@@ -288,7 +285,7 @@ class Subspace {
288
285
  ...lines.slice(beginIdx + 1, endIdx).filter((line) => this.#declaration.apps.some((app) => line.startsWith(`apps/${app}/`))),
289
286
  ...lines.slice(endIdx)
290
287
  ] : lines;
291
- await FileSys.writeText(gitignorePath, filtered.filter((line) => line.trim() !== "**/bun.lock").join(`
288
+ await FileSys2.writeText(gitignorePath, filtered.filter((line) => line.trim() !== "**/bun.lock").join(`
292
289
  `));
293
290
  }
294
291
  async#rewriteWorkspaceSection(libs) {
@@ -299,27 +296,27 @@ class Subspace {
299
296
  ];
300
297
  for (const file of ["AGENTS.md", "CLAUDE.md"]) {
301
298
  const filePath = path.join(this.#clonePath, file);
302
- if (!await FileSys.fileExists(filePath))
299
+ if (!await FileSys2.fileExists(filePath))
303
300
  continue;
304
- const content = await FileSys.readText(filePath);
301
+ const content = await FileSys2.readText(filePath);
305
302
  const rewritten = replacements.reduce((text, [pattern, value]) => text.replace(pattern, value), content);
306
303
  if (rewritten !== content)
307
- await FileSys.writeText(filePath, rewritten);
304
+ await FileSys2.writeText(filePath, rewritten);
308
305
  }
309
306
  }
310
307
  async#stampLib(clone, lib, branch) {
311
308
  const manifestPath = path.join(this.#clonePath, "libs", lib, "package.json");
312
- if (!await FileSys.fileExists(manifestPath))
309
+ if (!await FileSys2.fileExists(manifestPath))
313
310
  return;
314
311
  const origin = `${this.#workspace.repoName}#${branch}`;
315
312
  const sha = await this.headSha();
316
313
  const [hash, previous] = await Promise.all([this.#hashLib(clone, lib), this.#committedStamp(clone, lib)]);
317
- const manifest = await FileSys.readJson(manifestPath);
314
+ const manifest = await FileSys2.readJson(manifestPath);
318
315
  const akan = manifest[LibSource.manifestKey] ?? {};
319
316
  const unchanged = previous?.origin === origin && previous.sha === sha && previous.hash === hash;
320
317
  const syncedAt = unchanged ? previous.syncedAt : new Date().toISOString();
321
318
  manifest[LibSource.manifestKey] = { ...akan, source: { origin, sha, hash, syncedAt } };
322
- await FileSys.writeJson(manifestPath, manifest);
319
+ await FileSys2.writeJson(manifestPath, manifest);
323
320
  }
324
321
  async#committedStamp(clone, lib) {
325
322
  try {
@@ -342,22 +339,9 @@ class Subspace {
342
339
  `libs/${lib}`
343
340
  ]);
344
341
  const candidates = listed.split("\x00").filter((file) => !!file && !this.#isSubspaceOwned(file)).sort();
345
- const present = await Promise.all(candidates.map(async (file) => await FileSys.entryExists(path.join(this.#clonePath, file))));
342
+ const present = await Promise.all(candidates.map(async (file) => await FileSys2.entryExists(path.join(this.#clonePath, file))));
346
343
  const files = candidates.filter((_, index) => present[index]);
347
- const hasher = new Bun.CryptoHasher("sha256");
348
- for (const file of files) {
349
- const content = await FileSys.readText(path.join(this.#clonePath, file));
350
- hasher.update(file);
351
- hasher.update("\x00");
352
- if (file === `libs/${lib}/package.json`) {
353
- const manifest = JSON.parse(content);
354
- delete manifest[LibSource.manifestKey];
355
- hasher.update(JSON.stringify(manifest));
356
- } else
357
- hasher.update(content);
358
- hasher.update("\x00");
359
- }
360
- return hasher.digest("hex").slice(0, 32);
344
+ return await LibSource.hashFiles(files, `libs/${lib}/package.json`, (file) => FileSys2.readText(path.join(this.#clonePath, file)));
361
345
  }
362
346
  async diff(branch, filter) {
363
347
  if (!await this.fetch(branch))
@@ -376,10 +360,7 @@ class Subspace {
376
360
  if (!scoped.length)
377
361
  return { files: [], patch: "" };
378
362
  const from = `${this.#remote}/${branch}`;
379
- const pathspec = filter ? [filter] : scoped;
380
- const names = await this.#git(["diff", "--name-only", from, "HEAD", "--", ...pathspec]);
381
- const files = await this.#meaningfulFiles(from, names.split(`
382
- `).filter((file) => !!file.trim()).filter((file) => !this.#isSubspaceOwned(file)));
363
+ const files = await this.#changedSliceFiles(from, [from, "HEAD", "--", ...filter ? [filter] : scoped]);
383
364
  if (!files.length)
384
365
  return { files: [], patch: "" };
385
366
  return { files, patch: await this.#git(["diff", from, "HEAD", "--", ...files]) };
@@ -433,7 +414,7 @@ class Subspace {
433
414
  };
434
415
  }
435
416
  async#writeAnchorFile(branch) {
436
- await FileSys.writeJson(path.join(this.#clonePath, Subspace.anchorFile), {
417
+ await FileSys2.writeJson(path.join(this.#clonePath, Subspace.anchorFile), {
437
418
  workspace: this.#workspace.repoName,
438
419
  hubSha: await this.headSha(),
439
420
  branch,
@@ -470,7 +451,7 @@ class Subspace {
470
451
  async#savePatch(range, files, label) {
471
452
  const patchPath = path.join(this.#workspace.workspaceRoot, ".akan/subspace", `${this.name}-${label}.patch`);
472
453
  await mkdir(path.dirname(patchPath), { recursive: true });
473
- await FileSys.writeText(patchPath, await this.#git(["diff", range, "--", ...files]));
454
+ await FileSys2.writeText(patchPath, await this.#git(["diff", range, "--", ...files]));
474
455
  return { path: path.relative(this.#workspace.workspaceRoot, patchPath), absolute: patchPath, files };
475
456
  }
476
457
  }
@@ -592,7 +573,7 @@ class SubspaceConfig {
592
573
  static defaultPushableBranches = ["main", "develop", "debug"];
593
574
  static async from(workspace) {
594
575
  const configPath = path2.join(workspace.workspaceRoot, SubspaceConfig.fileName);
595
- if (!await FileSys.fileExists(configPath))
576
+ if (!await FileSys2.fileExists(configPath))
596
577
  return null;
597
578
  const input = await import(configPath).then((mod) => mod.default);
598
579
  return new SubspaceConfig(input);
@@ -735,7 +716,7 @@ class SubspaceRunner extends runner("subspace") {
735
716
  if (!asked)
736
717
  return { name: subspace.name, workspaceId, host, apps, libs: [], outcome: "cancelled", files: [] };
737
718
  const { libs } = await subspace.slice();
738
- const { CloudScript } = await import("./cloud.script-fwx3vb34.js");
719
+ const { CloudScript } = await import("./cloud.script-bkbpcr96.js");
739
720
  const { files } = await CommandContainer.get(CloudScript).uploadEnv(workspace, {
740
721
  host,
741
722
  workspaceId,
@@ -2,14 +2,14 @@ import type { AppInfo, LibInfo } from "akanjs";
2
2
 
3
3
  export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: { appName: string }) {
4
4
  return {
5
- filename: "AuthGuard.ts",
5
+ filename: "guards.ts",
6
6
  content: `import type { Guard, GuardScope, SignalContext } from "akanjs/signal";
7
7
 
8
- // ===== AuthGuard.ts =====
8
+ // ===== guards.ts =====
9
9
  // Convention: srvkit/ folder — server-only helpers, cannot import from client code.
10
10
  // Implements the Guard interface from akanjs/signal.
11
11
  // Guards are applied at endpoint/slice declaration: { guards: { root: SignedIn } }.
12
- // Naming: PascalCase .ts, static name property matches the guard identifier.
12
+ // Naming: camelCase file, PascalCase classes; each static name matches its guard identifier.
13
13
  // Scanned by akan sync into srvkit/index.ts barrel automatically.
14
14
 
15
15
  export class SignedIn implements Guard {
@@ -2,15 +2,15 @@ import type { AppInfo, LibInfo } from "akanjs";
2
2
 
3
3
  export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: { appName: string }) {
4
4
  return {
5
- filename: "SessionInternalArg.ts",
5
+ filename: "internalArgs.ts",
6
6
  content: `import type { InternalArg, SignalContext } from "akanjs/signal";
7
7
 
8
- // ===== SessionInternalArg.ts =====
8
+ // ===== internalArgs.ts =====
9
9
  // Convention: srvkit/ folder — server-only helpers.
10
10
  // Implements the InternalArg interface from akanjs/signal.
11
11
  // InternalArg is an auto-injected argument for resolveField/endpoint .with() chains.
12
12
  // Appended to a query/mutation via: .with(CurrentUserId, { nullable: true }).exec(...)
13
- // Naming: PascalCase .ts, class name = arg identifier.
13
+ // Naming: camelCase file, PascalCase classes; each class name is its arg identifier.
14
14
  // Scanned by akan sync into srvkit/index.ts barrel automatically.
15
15
 
16
16
  export class CurrentUserId implements InternalArg<string | null> {
@@ -4,36 +4,13 @@ const capitalize = (str: string) => str.charAt(0).toUpperCase() + str.slice(1);
4
4
 
5
5
  export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: { [key: string]: string } = {}) {
6
6
  if (!scanInfo) return null;
7
- const databaseModules = [...scanInfo.database.entries()]
8
- .filter(
9
- ([_, fileTypes]) =>
10
- fileTypes.has("template") ||
11
- fileTypes.has("unit") ||
12
- fileTypes.has("util") ||
13
- fileTypes.has("view") ||
14
- fileTypes.has("zone"),
15
- )
16
- .map(([key]) => key);
17
- const scalarModules = [...scanInfo.scalar.entries()]
18
- .filter(
19
- ([_, fileTypes]) =>
20
- fileTypes.has("template") ||
21
- fileTypes.has("unit") ||
22
- fileTypes.has("util") ||
23
- fileTypes.has("view") ||
24
- fileTypes.has("zone"),
25
- )
26
- .map(([key]) => key);
27
- const serviceModules = [...scanInfo.service.entries()]
28
- .filter(
29
- ([_, fileTypes]) =>
30
- fileTypes.has("template") ||
31
- fileTypes.has("unit") ||
32
- fileTypes.has("util") ||
33
- fileTypes.has("view") ||
34
- fileTypes.has("zone"),
35
- )
36
- .map(([key]) => key);
7
+ const uiModules = (modules: Map<string, Set<string>>) =>
8
+ [...modules.entries()]
9
+ .filter(([_, fileTypes]) => ["template", "unit", "util", "view", "zone"].some((type) => fileTypes.has(type)))
10
+ .map(([key]) => key);
11
+ const databaseModules = uiModules(scanInfo.database);
12
+ const scalarModules = uiModules(scanInfo.scalar);
13
+ const serviceModules = uiModules(scanInfo.service);
37
14
  return `
38
15
  export * as cnst from "./lib/cnst";
39
16
  export { msg, Err, usePage, fetch, sig } from "./lib/useClient";
@@ -1,7 +1,5 @@
1
1
  import type { AppInfo, LibInfo } from "akanjs";
2
2
 
3
- const capitalize = (str: string) => str.charAt(0).toUpperCase() + str.slice(1);
4
-
5
3
  export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: { [key: string]: string } = {}) {
6
4
  if (!scanInfo) return null;
7
5
  const libs = scanInfo.getLibs();
@@ -1,7 +1,5 @@
1
1
  import type { AppInfo, LibInfo } from "akanjs";
2
2
 
3
- const capitalize = (str: string) => str.charAt(0).toUpperCase() + str.slice(1);
4
-
5
3
  export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: { [key: string]: string } = {}) {
6
4
  if (!scanInfo) return null;
7
5
  const libs = scanInfo.getLibs();
@@ -13,6 +13,8 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: { [
13
13
  const libs = scanInfo.getLibs();
14
14
 
15
15
  const signalNames = [...(libs.length === 0 ? ["base"] : libs), ...databaseModules, ...serviceModules];
16
+ const serverSignalClass = (module: string) =>
17
+ `export class ${capitalize(module)} extends serverSignal(${module}Sig.${capitalize(module)}Endpoint, ${module}Sig.${capitalize(module)}Internal) {}`;
16
18
 
17
19
  return `
18
20
  import { FetchClient, type FetchClientType } from "akanjs/fetch";
@@ -20,38 +22,14 @@ import { SignalRegistry, serverSignal${libs.length === 0 ? ", fetch as base" : "
20
22
  import { Err } from "./dict";
21
23
  ${libs.map((lib) => `import { fetch as ${lib} } from "@libs/${lib}/lib/sig";`).join("\n")}
22
24
 
23
- ${[...scanInfo.database.entries()]
24
- .filter(([_, files]) => files.has("signal"))
25
- .map(([module]) => `import * as ${module}Sig from "./${module}/${module}.signal";`)
26
- .join("\n")}
27
- ${[...scanInfo.service.entries()]
28
- .filter(([_, files]) => files.has("signal"))
29
- .map(([module]) => `import * as ${module}Sig from "./_${module}/${module}.signal";`)
30
- .join("\n")}
25
+ ${databaseModules.map((module) => `import * as ${module}Sig from "./${module}/${module}.signal";`).join("\n")}
26
+ ${serviceModules.map((module) => `import * as ${module}Sig from "./_${module}/${module}.signal";`).join("\n")}
31
27
 
32
- ${[...scanInfo.database.entries()]
33
- .filter(([_, files]) => files.has("signal"))
34
- .map(([module]) => `export * from "./${module}/${module}.signal";`)
35
- .join("\n")}
36
- ${[...scanInfo.service.entries()]
37
- .filter(([_, files]) => files.has("signal"))
38
- .map(([module]) => `export * from "./_${module}/${module}.signal";`)
39
- .join("\n")}
28
+ ${databaseModules.map((module) => `export * from "./${module}/${module}.signal";`).join("\n")}
29
+ ${serviceModules.map((module) => `export * from "./_${module}/${module}.signal";`).join("\n")}
40
30
 
41
- ${[...scanInfo.database.entries()]
42
- .filter(([_, files]) => files.has("signal"))
43
- .map(
44
- ([module]) =>
45
- `export class ${capitalize(module)} extends serverSignal(${module}Sig.${capitalize(module)}Endpoint, ${module}Sig.${capitalize(module)}Internal) {}`,
46
- )
47
- .join("\n")}
48
- ${[...scanInfo.service.entries()]
49
- .filter(([_, files]) => files.has("signal"))
50
- .map(
51
- ([module]) =>
52
- `export class ${capitalize(module)} extends serverSignal(${module}Sig.${capitalize(module)}Endpoint, ${module}Sig.${capitalize(module)}Internal) {}`,
53
- )
54
- .join("\n")}
31
+ ${databaseModules.map(serverSignalClass).join("\n")}
32
+ ${serviceModules.map(serverSignalClass).join("\n")}
55
33
 
56
34
  ${databaseModules.map((module) => `export const ${module} = SignalRegistry.registerDatabase("${module}" as const, ${module}Sig.${capitalize(module)}Internal, ${module}Sig.${capitalize(module)}Endpoint, ${module}Sig.${capitalize(module)}Slice, ${capitalize(module)});`).join("\n")}
57
35
  ${serviceModules.map((module) => `export const ${module} = SignalRegistry.registerService("${module}" as const, ${module}Sig.${capitalize(module)}Internal, ${module}Sig.${capitalize(module)}Endpoint, ${capitalize(module)});`).join("\n")}
@@ -1,7 +1,5 @@
1
1
  import type { AppInfo, LibInfo } from "akanjs";
2
2
 
3
- const capitalize = (str: string) => str.charAt(0).toUpperCase() + str.slice(1);
4
-
5
3
  export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: { [key: string]: string } = {}) {
6
4
  if (!scanInfo) return null;
7
5
  const libs = scanInfo.getLibs();
@@ -1,22 +1,21 @@
1
1
  // @bun
2
- import"./index-q0y2jq9j.js";
2
+ import"./index-5b6tavv3.js";
3
3
  import {
4
4
  GlobalConfig,
5
5
  CloudApi
6
- } from "./index-srmay5jw.js";
6
+ } from "./index-22d57v4c.js";
7
7
  import {
8
8
  Workspace,
9
9
  runner,
10
10
  script,
11
11
  command
12
- } from "./index-qdgzsnhg.js";
12
+ } from "./index-w2zdcw3k.js";
13
13
  import {
14
14
  AppExecutor
15
- } from "./index-crmeqnmf.js";
16
- import"./index-6wwzs1bc.js";
15
+ } from "./index-9d9bgcx4.js";
17
16
  import {
18
17
  TunnelShare2
19
- } from "./index-n3cv0tm4.js";
18
+ } from "./index-smme4r47.js";
20
19
  import {
21
20
  writeClipboard
22
21
  } from "./index-p6pbz9n5.js";
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  TypeChecker2
4
- } from "./index-92zztqy1.js";
4
+ } from "./index-dy0jx9ay.js";
5
5
  export {
6
6
  TypeChecker2 as TypeChecker
7
7
  };
package/typecheck.proc.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  TypeChecker2
4
- } from "./index-92zztqy1.js";
4
+ } from "./index-dy0jx9ay.js";
5
5
 
6
6
  // pkgs/@akanjs/devkit/typecheck/typecheck.proc.ts
7
7
  import { Logger } from "akanjs/common";