@akanjs/cli 2.4.2-rc.2 → 3.0.0-alpha.0

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 (81) hide show
  1. package/.build-stamp +1 -1
  2. package/abstractCompactor-rk6twzvj.js +103 -0
  3. package/{agent.command-ej4g9pbb.js → agent.command-jfz8yfwy.js} +8 -7
  4. package/{application.command-smn51a28.js → application.command-3smsv7mq.js} +15 -5
  5. package/{applicationBuildRunner-554a2vnk.js → applicationBuildRunner-aq7mb3z6.js} +2 -1
  6. package/buildBatch.proc.js +7 -6
  7. package/{capacitorApp-yg9b4ajz.js → capacitorApp-q3mpmkkz.js} +3 -3
  8. package/{cloud.command-2v7ga38h.js → cloud.command-rk4e9vrt.js} +10 -10
  9. package/commandManifest.json +1 -1
  10. package/{context.command-hhjyjtp7.js → context.command-ygzyb0xb.js} +16 -15
  11. package/{guideline.command-vj956kfr.js → guideline.command-1m1ctar3.js} +10 -10
  12. package/guidelines/componentRule/componentRule.instruction.md +2 -2
  13. package/guidelines/cssRule/cssRule.generate.json +1 -1
  14. package/guidelines/cssRule/cssRule.instruction.md +57 -34
  15. package/guidelines/framework/framework.instruction.md +1 -1
  16. package/guidelines/recipeRule/recipeRule.generate.json +31 -0
  17. package/guidelines/recipeRule/recipeRule.instruction.md +72 -0
  18. package/incrementalBuilder.proc.js +5 -5
  19. package/index-0wae5ebk.js +65 -0
  20. package/{index-v9jqrdd1.js → index-4yp06pn1.js} +100 -2
  21. package/{index-pfnh87f9.js → index-4zgs8g1w.js} +1 -1
  22. package/{index-7ppn9v4n.js → index-b978vs2e.js} +3 -3
  23. package/{index-s9s0n5fz.js → index-cn24dcqn.js} +2 -2
  24. package/{index-h971erkm.js → index-csqk9z5j.js} +3 -3
  25. package/{index-z36qzgzp.js → index-e3qskyt2.js} +3 -4
  26. package/{index-panyahn4.js → index-ev6rjw9n.js} +27 -13
  27. package/{index-majzj044.js → index-f4gqk0dd.js} +8 -8
  28. package/{index-z5v766nx.js → index-fmgbwsr5.js} +6 -6
  29. package/{index-y1e79mz3.js → index-h0bngh79.js} +13 -13
  30. package/{index-dgeaqwmw.js → index-hjzr8ja1.js} +1 -1
  31. package/{index-d0h48d2f.js → index-jk9q6pse.js} +1 -1
  32. package/{index-xwfg9bam.js → index-jtm86byd.js} +120 -4
  33. package/{index-j3j3qc9j.js → index-ktprgc5g.js} +4 -4
  34. package/{index-40w1kqp1.js → index-n0z3f2xg.js} +74 -24
  35. package/{index-7k9sj7j5.js → index-pyt2b4nw.js} +212 -0
  36. package/{index-acwxfncv.js → index-r4w8cry5.js} +4 -4
  37. package/{index-zfp1gz9f.js → index-sggm9qkv.js} +1 -1
  38. package/{index-04as43rp.js → index-vhv3xnjz.js} +16 -15
  39. package/index-xjd3rqzj.js +129 -0
  40. package/{index-xftstr5s.js → index-xwgm94zr.js} +1 -1
  41. package/index-xys926f2.js +136 -0
  42. package/index.js +19 -19
  43. package/{library.command-68ah07a3.js → library.command-pwfx8dx2.js} +4 -4
  44. package/{localRegistry.command-nmyc5vwv.js → localRegistry.command-bxhqmd1d.js} +11 -11
  45. package/{module.command-t68xhamx.js → module.command-0t3ewata.js} +8 -8
  46. package/{package.command-00ncttab.js → package.command-7hmkxvpa.js} +4 -4
  47. package/package.json +2 -3
  48. package/{page.command-1096s18n.js → page.command-st6r4s0q.js} +4 -4
  49. package/{primitive.command-02eqpx6t.js → primitive.command-1qkxpzsn.js} +9 -9
  50. package/{quality.command-vap6xegb.js → quality.command-hy5vt1bh.js} +31 -6
  51. package/recipeScanner-tghkzrrt.js +12 -0
  52. package/{repair.command-7dynpnf1.js → repair.command-nakkq2zp.js} +7 -6
  53. package/{scalar.command-3kxy3fkh.js → scalar.command-fjq272gs.js} +7 -7
  54. package/templates/app/page/_index.tsx +55 -52
  55. package/templates/app/page/styles.css.template +12 -71
  56. package/templates/appSample/lib/task/Task.Template.tsx +2 -2
  57. package/templates/appSample/lib/task/Task.Unit.tsx +11 -11
  58. package/templates/appSample/lib/task/Task.Util.tsx +27 -28
  59. package/templates/appSample/lib/task/Task.View.tsx +22 -19
  60. package/templates/appSample/lib/task/Task.Zone.tsx +3 -3
  61. package/templates/appSample/page/task/[taskId]/_index.tsx +3 -3
  62. package/templates/appSample/page/task/[taskId]/edit.tsx +5 -5
  63. package/templates/appSample/page/task/_index.tsx +4 -4
  64. package/templates/appSample/page/task/_layout.tsx +1 -1
  65. package/templates/appSample/page/task/new.tsx +5 -5
  66. package/templates/appSample/ui/GlobalLoading.tsx +4 -4
  67. package/templates/appSample/ui/QuantityControl.tsx +5 -4
  68. package/templates/crudPages/[__model__Id]/page.tsx +1 -1
  69. package/templates/crudPages/page.tsx +1 -1
  70. package/templates/crudSinglePage/page.tsx +1 -1
  71. package/templates/module/__Model__.Template.tsx +2 -1
  72. package/templates/module/__Model__.Unit.tsx +2 -1
  73. package/templates/module/__Model__.Util.tsx +2 -1
  74. package/templates/module/__Model__.View.tsx +4 -3
  75. package/templates/module/__Model__.Zone.tsx +2 -1
  76. package/templates/workspaceRoot/AGENTS.md.template +11 -13
  77. package/templates/workspaceRoot/biome.json.template +1 -1
  78. package/{workflow.command-yy0d9gk3.js → workflow.command-jswbgk90.js} +15 -14
  79. package/{workspace.command-hq1x5605.js → workspace.command-p9r9nckg.js} +89 -29
  80. package/{applicationReleasePackager-pjbxc793.js → applicationReleasePackager-yrrhbkv3.js} +3 -3
  81. package/{index-nsj2ftxj.js → index-3pgtw35d.js} +3 -3
@@ -0,0 +1,72 @@
1
+ # Recipe Rule Guideline
2
+
3
+ ## Purpose
4
+ Recipes are the reusable-look layer of Akan UI: Tailwind-variant factories (`recipe(tv({...}))`) that sit between semantic
5
+ tokens (values) and components (behavior). This rule governs how agents **consume** and **author** recipes so a look is not
6
+ hallucinated, re-derived inline, or duplicated across an app.
7
+
8
+ ## Ownership
9
+ - A recipe owns a **look** (a composition of semantic-token utility classes), never behavior. Behavior lives in components.
10
+ - **One recipe per file.** App/lib recipes live in `apps/<app>/ui/Recipe/<name>.ts` and `libs/<lib>/ui/Recipe/<name>.ts`,
11
+ re-exported from that folder's hand-written `index.ts`; framework recipes (`buttonRecipe`, `badgeRecipe`,
12
+ `inputRecipe`) mirror the same shape in `pkgs/akanjs/ui/recipe/<name>Recipe.ts`. Apps inherit the framework recipes by
13
+ re-exporting them from their own `Recipe/index.ts`, so a consumer imports every recipe from one barrel.
14
+ - The folder must be `Recipe` (PascalCase) in an app/lib `ui/`: the generated `ui/index.ts` exports PascalCase names
15
+ only, so a flat `appCard.recipe.ts` is silently skipped and becomes unimportable. Inside the folder any camelCase
16
+ filename is fine — the barrel only scans one level.
17
+ - Recipes use **semantic tokens only** in their `base`/`variants` (never raw palette or hex); they inherit the CSS token rules.
18
+
19
+ ## Consuming Recipes
20
+ - Import by **exact name** from the owning barrel: `import { <name> } from "@apps/<app>/ui"` (or `akanjs/ui` for framework),
21
+ then call `<name>(variants?, className?)` — the second arg is merged automatically; no extra `cn()` wrapper is needed.
22
+ - The second arg is a `ClassNameValue`, so it takes **an array (and falsy entries), not just one string**:
23
+ `<name>({}, ["h-full", isWide && "w-full", className])`. Reaching for `cn()` to combine several classes is the
24
+ usual way the no-`cn` contract leaks — there is nothing `cn()` adds here that the recipe does not already do.
25
+ - **Do not guess** recipe names or import paths. The authoritative index is split by ownership: the root `AGENTS.md`
26
+ `## Recipes` (always loaded) lists **framework** recipes, and each app/lib's own `AGENTS.md` (`## Recipes In Scope`)
27
+ lists what that scope may additionally import — its own recipes plus its dependency libs'. Both carry every recipe's
28
+ variant surface and default, so consuming one never requires opening its file. The scoped index is regenerated by
29
+ `akan sync <name>` and kept honest by `akan lint <name>`, which fails when it is stale.
30
+ - Variant options are typed (`Parameters<typeof <name>>[0]`), so a wrong variant is a compile error — let tsc validate
31
+ options rather than memorizing strings.
32
+
33
+ ## Recipe vs Component vs Constant — The Gate
34
+ The form of a shared look is decided by **counting**, not judgment (`akan lint` enforces this as `recipeGate`):
35
+
36
+ 1. **Does the caller choose an option?** (at least one variant axis with 2+ values, or a boolean flag)
37
+ - **No** → it is **never a recipe** — a fixed look wrapped in a function is dead indirection.
38
+ - Reused with its own markup → a small **component** (`<Divider/>`, `<DocsList/>`, `<Screen/>`).
39
+ - Injected into another component's `className` prop → a shared **class constant** (`appNavClass`).
40
+ - Used once → plain **inline** classes.
41
+ - **Yes** → it is a recipe. Then:
42
+ 2. **Does it need markup or behavior** (own tag, structure, state, a11y)?
43
+ - No → pages call the recipe directly on their own element (`panelRecipe({ padding: "row" })`).
44
+ - Yes → a component consumes the recipe internally (`<Button variant>` → `buttonRecipe`).
45
+
46
+ ## Authoring Recipes
47
+ - A **reusable or repeated surface** (card, box, tile, chat bubble, hero, …) belongs in a recipe, **not** inline. If the same
48
+ token-class stack appears in more than one place, extract it into a recipe.
49
+ - **Before authoring, check the existing recipe indexes** (root `AGENTS.md` `## Recipes` for framework recipes, the
50
+ scope's own `AGENTS.md` `## Recipes In Scope` for app/lib recipes) and **reuse** a matching recipe instead of
51
+ creating a near-duplicate — registry sprawl comes from re-inventing looks that already exist.
52
+ - Add a new recipe as its own file, `ui/Recipe/<name>.ts` holding a single
53
+ `export const <name>Recipe = recipe(tv({ base, variants }))` plus a one-line JSDoc describing the surface, then
54
+ re-export it from `ui/Recipe/index.ts`. Name the export `<name>Recipe`; the filename drops the suffix.
55
+ - Keep declaration and css in that one file. Splitting a recipe into a hand-written variant type plus a separate style
56
+ file inverts the dependency: the variant type is currently *inferred* from the `tv` config
57
+ (`Parameters<typeof <name>Recipe>[0]`), which makes type/css drift structurally impossible, and the AGENTS listing
58
+ already exposes the surface without reading the file. There is nothing left for the split to buy.
59
+ - App recipes **extend** (surfaces the framework lacks); they never re-define a framework component's look in parallel.
60
+
61
+ ## Codegen Rules
62
+ - Do not re-derive inline a look that an existing recipe already provides.
63
+ - Do not author a near-duplicate of an existing recipe; reuse or extend it.
64
+ - Do not guess recipe names or import paths; use the authoritative list.
65
+ - Do not put raw-palette / hex / inline color in a recipe; semantic tokens only.
66
+
67
+ ## Review Checklist
68
+ - Repeated/variant surfaces are recipes, not inline class stacks duplicated across files.
69
+ - No two recipes describe the same look; consumers import by exact name from the correct barrel.
70
+ - New recipes live one-per-file in the owning `ui/Recipe/`, exported as `<name>Recipe`, token-only, with a one-line doc,
71
+ and re-exported from that folder's `index.ts`.
72
+ - The output contract tells the model which file paths to return.
@@ -2,11 +2,6 @@
2
2
  import {
3
3
  prepareDevWatchBatch
4
4
  } from "./index-fgc8r6dj.js";
5
- import {
6
- AppExecutor,
7
- WorkspaceExecutor
8
- } from "./index-xwfg9bam.js";
9
- import"./index-67546d0j.js";
10
5
  import {
11
6
  AutoImportSync,
12
7
  DevChangePlanner,
@@ -18,7 +13,12 @@ import {
18
13
  HmrWatcher,
19
14
  WatchRootResolver
20
15
  } from "./index-bjpxzr6s.js";
16
+ import {
17
+ AppExecutor,
18
+ WorkspaceExecutor
19
+ } from "./index-jtm86byd.js";
21
20
  import"./index-6pz1j0zj.js";
21
+ import"./index-67546d0j.js";
22
22
  import"./index-r24hmh0q.js";
23
23
 
24
24
  // pkgs/@akanjs/devkit/incrementalBuilder/incrementalBuilder.proc.ts
@@ -0,0 +1,65 @@
1
+ // @bun
2
+ // pkgs/@akanjs/devkit/abstractDoc.ts
3
+ class AbstractDoc {
4
+ path;
5
+ content;
6
+ siblingFiles;
7
+ static suffix = ".abstract.md";
8
+ static maxLines = 300;
9
+ static compactMinLines = 40;
10
+ static #facetRoots = "{lib,ui,webkit,srvkit,common,plugin}";
11
+ static isAbstractPath(filePath) {
12
+ return filePath.endsWith(AbstractDoc.suffix);
13
+ }
14
+ static lineCountOf(content) {
15
+ return content.split(/\r?\n/).length;
16
+ }
17
+ static kindOf(filePath) {
18
+ const [root, folder, ...rest] = filePath.split("/");
19
+ if (root !== "lib" || !folder)
20
+ return "other";
21
+ if (folder === "__scalar")
22
+ return rest.length === 2 ? "scalar" : "other";
23
+ if (rest.length !== 1)
24
+ return "other";
25
+ return folder.startsWith("_") ? "service" : "domain";
26
+ }
27
+ static async findAll(sys, { module } = {}) {
28
+ const filePaths = (await sys.getAllFiles(`${AbstractDoc.#facetRoots}/**/*${AbstractDoc.suffix}`)).sort();
29
+ const docs = await Promise.all(filePaths.map((filePath) => AbstractDoc.read(sys, filePath)));
30
+ if (!module)
31
+ return docs;
32
+ return docs.filter((doc) => doc.moduleName === module || doc.folderName === module);
33
+ }
34
+ static async read(sys, filePath) {
35
+ const dirPath = filePath.split("/").slice(0, -1).join("/");
36
+ const [content, folderFiles] = await Promise.all([sys.readFile(filePath), sys.readdir(dirPath)]);
37
+ return new AbstractDoc(filePath, content, folderFiles.filter((fileName) => !AbstractDoc.isAbstractPath(fileName)));
38
+ }
39
+ constructor(path, content, siblingFiles) {
40
+ this.path = path;
41
+ this.content = content;
42
+ this.siblingFiles = siblingFiles;
43
+ }
44
+ get kind() {
45
+ return AbstractDoc.kindOf(this.path);
46
+ }
47
+ get folderName() {
48
+ return this.path.split("/").at(-2) ?? "";
49
+ }
50
+ get moduleName() {
51
+ return (this.path.split("/").at(-1) ?? "").slice(0, -AbstractDoc.suffix.length);
52
+ }
53
+ get lineCount() {
54
+ return AbstractDoc.lineCountOf(this.content);
55
+ }
56
+ canReplaceWith(candidate) {
57
+ const next = candidate.trim();
58
+ if (!next.startsWith("#"))
59
+ return false;
60
+ const lineCount = AbstractDoc.lineCountOf(next);
61
+ return lineCount >= 3 && lineCount < this.lineCount;
62
+ }
63
+ }
64
+
65
+ export { AbstractDoc };
@@ -2,11 +2,16 @@
2
2
  import {
3
3
  workflowRunArtifactPath,
4
4
  workflowSyncDir
5
- } from "./index-pfnh87f9.js";
5
+ } from "./index-4zgs8g1w.js";
6
6
  import {
7
7
  AppExecutor,
8
8
  LibExecutor
9
- } from "./index-xwfg9bam.js";
9
+ } from "./index-jtm86byd.js";
10
+ import {
11
+ collectRecipeSources,
12
+ findInlineRecipeDuplicates,
13
+ scanRecipes
14
+ } from "./index-xys926f2.js";
10
15
  import {
11
16
  FileSys
12
17
  } from "./index-67546d0j.js";
@@ -146,6 +151,8 @@ var moduleShapeFiles = (module) => {
146
151
  };
147
152
  var constantFieldNames = (content) => [...content.matchAll(/\b([A-Za-z_$][\w$]*)\s*:\s*field\(/g)].map((match) => match[1]).filter(Boolean);
148
153
  var appRootAllowFiles = new Set([
154
+ "AGENTS.md",
155
+ "CLAUDE.md",
149
156
  "akan.app.json",
150
157
  "akan.config.ts",
151
158
  "capacitor.config.ts",
@@ -461,6 +468,97 @@ class AkanContextAnalyzer {
461
468
  }
462
469
  }
463
470
  }
471
+ for (const sys of [...context.apps, ...context.libs]) {
472
+ const sources = await collectRecipeSources(path.join(workspace.workspaceRoot, sys.path, "ui"), "ui");
473
+ if (sources.length === 0)
474
+ continue;
475
+ const recipes = scanRecipes(sources);
476
+ const files = [];
477
+ const glob = new Bun.Glob("**/*.tsx");
478
+ for await (const abs of glob.scan({ cwd: path.join(workspace.workspaceRoot, sys.path), absolute: true })) {
479
+ if (/[\\/](node_modules|\.akan|dist)[\\/]|[\\/]v1[\\/]/.test(abs) || /\.(test|spec)\.tsx$/.test(abs))
480
+ continue;
481
+ files.push({
482
+ path: abs,
483
+ content: await Bun.file(abs).text().catch(() => "")
484
+ });
485
+ }
486
+ const duplicates = findInlineRecipeDuplicates(recipes, files);
487
+ if (duplicates.length === 0)
488
+ continue;
489
+ const preview = duplicates.slice(0, 3).map((duplicate) => `${path.relative(workspace.workspaceRoot, duplicate.path)}:${duplicate.line}`).join(", ");
490
+ diagnostics.push({
491
+ severity: "warning",
492
+ code: "recipe-inline-duplicate",
493
+ path: path.join(sys.path, "ui/Recipe"),
494
+ message: `${sys.name}: ${duplicates.length} inline className(s) re-author a recipe fingerprint (${preview}${duplicates.length > 3 ? ", \u2026" : ""}) \u2014 consume the recipe instead.`
495
+ });
496
+ }
497
+ const scanNames = async (uiDirPath, basename) => new Set(scanRecipes(await collectRecipeSources(uiDirPath, "ui", basename)).map((info) => info.name));
498
+ const declaredByImport = new Map;
499
+ declaredByImport.set("akanjs/ui", await scanNames(path.join(workspace.workspaceRoot, "pkgs/akanjs/ui"), "recipe"));
500
+ for (const sys of [...context.apps, ...context.libs])
501
+ declaredByImport.set(`@${sys.path}/ui`, await scanNames(path.join(workspace.workspaceRoot, sys.path, "ui")));
502
+ const sectionOf = (content, heading) => {
503
+ const match = new RegExp(`^${heading}$`, "m").exec(content);
504
+ if (!match)
505
+ return "";
506
+ const section = content.slice(match.index);
507
+ const sectionEnd = section.indexOf(`
508
+ ## `, 1);
509
+ return sectionEnd === -1 ? section : section.slice(0, sectionEnd);
510
+ };
511
+ const listedByImport = (body) => {
512
+ const groups = new Map;
513
+ let current = null;
514
+ for (const line of body.split(`
515
+ `)) {
516
+ const group = /^Import from `([^`]+)`:/.exec(line);
517
+ if (group) {
518
+ current = groups.get(group[1]) ?? new Set;
519
+ groups.set(group[1], current);
520
+ continue;
521
+ }
522
+ const item = /^- `([A-Za-z0-9_$]+)`/.exec(line);
523
+ if (item && current)
524
+ current.add(item[1]);
525
+ else if (!item)
526
+ current = null;
527
+ }
528
+ return groups;
529
+ };
530
+ const pushIndexDiagnostic = (indexPath, missing, stale, repairCommand) => {
531
+ if (missing.length === 0 && stale.length === 0)
532
+ return;
533
+ const action = repairAction("generated", repairCommand, "Regenerate the recipe index from the scanned recipes.", true);
534
+ const parts = [
535
+ missing.length > 0 ? `${missing.length} declared but unlisted (${missing.slice(0, 5).join(", ")})` : "",
536
+ stale.length > 0 ? `${stale.length} listed but gone (${stale.slice(0, 5).join(", ")})` : ""
537
+ ].filter(Boolean);
538
+ diagnostics.push({
539
+ severity: "error",
540
+ code: "recipe-index-stale",
541
+ path: indexPath,
542
+ message: `${indexPath} recipe index is out of date \u2014 ${parts.join("; ")}. Agents read this list as authoritative.`,
543
+ repairActions: [action]
544
+ });
545
+ repairActions.push(action);
546
+ };
547
+ const frameworkDeclared = declaredByImport.get("akanjs/ui") ?? new Set;
548
+ if (frameworkDeclared.size > 0) {
549
+ const agentsMd = await Bun.file(path.join(workspace.workspaceRoot, "AGENTS.md")).text().catch(() => "");
550
+ const listed = listedByImport(sectionOf(agentsMd, "## Recipes")).get("akanjs/ui") ?? new Set;
551
+ pushIndexDiagnostic("AGENTS.md", [...frameworkDeclared].filter((name) => !listed.has(name)).sort(), [...listed].filter((name) => !frameworkDeclared.has(name)).sort(), "akan agent install agents-md");
552
+ }
553
+ for (const sys of [...context.apps, ...context.libs]) {
554
+ const own = declaredByImport.get(`@${sys.path}/ui`) ?? new Set;
555
+ const scopeMd = await Bun.file(path.join(workspace.workspaceRoot, sys.path, "AGENTS.md")).text().catch(() => "");
556
+ const groups = listedByImport(sectionOf(scopeMd, "## Recipes In Scope"));
557
+ const ownListed = groups.get(`@${sys.path}/ui`) ?? new Set;
558
+ const missing = [...own].filter((name) => !ownListed.has(name)).sort();
559
+ const stale = [...groups.entries()].flatMap(([importFrom, names]) => [...names].filter((name) => !(declaredByImport.get(importFrom) ?? new Set).has(name))).sort();
560
+ pushIndexDiagnostic(`${sys.path}/AGENTS.md`, missing, stale, `akan sync ${sys.name}`);
561
+ }
464
562
  const scopedDiagnostics = diagnostics.map((diagnostic) => ({
465
563
  ...diagnostic,
466
564
  scope: workflowPaths.length ? isWorkflowRelatedDiagnostic(diagnostic, workflowPaths) ? "workflow" : "baseline" : diagnostic.scope,
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  AppExecutor,
4
4
  LibExecutor
5
- } from "./index-xwfg9bam.js";
5
+ } from "./index-jtm86byd.js";
6
6
 
7
7
  // pkgs/@akanjs/devkit/workflow/utils.ts
8
8
  var jsonText = (value, { trailingNewline = true } = {}) => `${JSON.stringify(value, null, 2)}${trailingNewline ? `
@@ -1,17 +1,17 @@
1
1
  // @bun
2
2
  import {
3
3
  AkanContextAnalyzer
4
- } from "./index-v9jqrdd1.js";
4
+ } from "./index-4yp06pn1.js";
5
5
  import {
6
6
  createRepairReport,
7
7
  generatedFilePathsForTarget,
8
8
  renderRepairReport,
9
9
  writeGeneratedSyncState,
10
10
  writeWorkflowRunArtifact
11
- } from "./index-pfnh87f9.js";
11
+ } from "./index-4zgs8g1w.js";
12
12
  import {
13
13
  runner
14
- } from "./index-d0h48d2f.js";
14
+ } from "./index-jk9q6pse.js";
15
15
 
16
16
  // pkgs/@akanjs/cli/repair/repair.runner.ts
17
17
  var commandForShell = (command) => command.startsWith("akan ") ? `bun run ${command}` : command;
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  runner,
4
4
  script
5
- } from "./index-d0h48d2f.js";
5
+ } from "./index-jk9q6pse.js";
6
6
  import {
7
7
  LibExecutor
8
- } from "./index-xwfg9bam.js";
8
+ } from "./index-jtm86byd.js";
9
9
 
10
10
  // pkgs/@akanjs/cli/semver.ts
11
11
  function parseVersion(version) {
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  AkanContextAnalyzer
4
- } from "./index-v9jqrdd1.js";
4
+ } from "./index-4yp06pn1.js";
5
5
  import {
6
6
  WorkflowExecutor,
7
7
  compactWorkflowInputs,
@@ -23,10 +23,10 @@ import {
23
23
  workflowCommandsForPlan,
24
24
  workflowPlanApproval,
25
25
  writeWorkflowRunArtifact
26
- } from "./index-pfnh87f9.js";
26
+ } from "./index-4zgs8g1w.js";
27
27
  import {
28
28
  runner
29
- } from "./index-d0h48d2f.js";
29
+ } from "./index-jk9q6pse.js";
30
30
 
31
31
  // pkgs/@akanjs/cli/workflow/workflow.runner.ts
32
32
  import { mkdir, readFile, writeFile } from "fs/promises";
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  runner,
4
4
  script
5
- } from "./index-d0h48d2f.js";
5
+ } from "./index-jk9q6pse.js";
6
6
  import {
7
7
  PkgExecutor
8
- } from "./index-xwfg9bam.js";
8
+ } from "./index-jtm86byd.js";
9
9
  import {
10
10
  TypeScriptDependencyScanner
11
11
  } from "./index-46tjzh6s.js";
@@ -153,14 +153,13 @@ class PackageRunner extends runner("package") {
153
153
  const scanner = await TypeScriptDependencyScanner.from(pkg);
154
154
  const { npmDeps, npmDevDeps, missingDeps } = await scanner.getPackageBuildDependencies(pkg.name);
155
155
  const packageRuntimeDependencies = {
156
- "@akanjs/devkit": ["daisyui", "tailwind-scrollbar"]
156
+ "@akanjs/devkit": ["tailwind-scrollbar"]
157
157
  };
158
158
  const packageRuntimeDevDependencies = { akanjs: ["@biomejs/biome", "@types/bun"] };
159
159
  if (pkg.name === "@akanjs/cli") {
160
160
  const devkitPackageJson = await pkg.workspace.readJson("pkgs/@akanjs/devkit/package.json");
161
161
  packageRuntimeDependencies[pkg.name] = [
162
162
  ...Object.keys(devkitPackageJson.dependencies ?? {}),
163
- "daisyui",
164
163
  "tailwind-scrollbar"
165
164
  ].filter((dep) => dep !== "akanjs" && dep !== "@akanjs/devkit");
166
165
  }
@@ -4,21 +4,21 @@ import {
4
4
  } from "./index-76rn3g2c.js";
5
5
  import {
6
6
  LibraryScript
7
- } from "./index-s9s0n5fz.js";
7
+ } from "./index-cn24dcqn.js";
8
8
  import {
9
9
  runner,
10
10
  script
11
- } from "./index-d0h48d2f.js";
11
+ } from "./index-jk9q6pse.js";
12
+ import {
13
+ HmrWatcher,
14
+ WatchRootResolver
15
+ } from "./index-bjpxzr6s.js";
12
16
  import {
13
17
  AppExecutor,
14
18
  LibExecutor,
15
19
  PkgExecutor,
16
20
  WorkspaceExecutor
17
- } from "./index-xwfg9bam.js";
18
- import {
19
- HmrWatcher,
20
- WatchRootResolver
21
- } from "./index-bjpxzr6s.js";
21
+ } from "./index-jtm86byd.js";
22
22
  import {
23
23
  __require
24
24
  } from "./index-r24hmh0q.js";
@@ -1898,9 +1898,10 @@ function openBrowser(url) {
1898
1898
  }
1899
1899
 
1900
1900
  // pkgs/@akanjs/cli/application/application.runner.ts
1901
- var loadBuildRunner = async () => (await import("./applicationBuildRunner-554a2vnk.js")).ApplicationBuildRunner;
1902
- var loadReleasePackager = async () => (await import("./applicationReleasePackager-pjbxc793.js")).ApplicationReleasePackager;
1903
- var loadCapacitorApp = async () => (await import("./capacitorApp-yg9b4ajz.js")).CapacitorApp;
1901
+ var loadBuildRunner = async () => (await import("./applicationBuildRunner-aq7mb3z6.js")).ApplicationBuildRunner;
1902
+ var loadReleasePackager = async () => (await import("./applicationReleasePackager-yrrhbkv3.js")).ApplicationReleasePackager;
1903
+ var loadCapacitorApp = async () => (await import("./capacitorApp-q3mpmkkz.js")).CapacitorApp;
1904
+ var loadAbstractCompactor = async () => (await import("./abstractCompactor-rk6twzvj.js")).AbstractCompactor;
1904
1905
  var loadPrompts = async () => await import("@inquirer/prompts");
1905
1906
 
1906
1907
  class ApplicationRunner extends runner("application") {
@@ -1978,6 +1979,10 @@ try {
1978
1979
  async typecheck(app, options = {}) {
1979
1980
  await new (await loadBuildRunner())(app).typecheck(options);
1980
1981
  }
1982
+ async compact(sys, { module, minLines, interactive } = {}) {
1983
+ const compactor = new (await loadAbstractCompactor())(sys, { minLines, interactive });
1984
+ return await compactor.compactAll({ module });
1985
+ }
1981
1986
  async test(exec) {
1982
1987
  const isSignalTarget = exec instanceof AppExecutor || exec instanceof LibExecutor;
1983
1988
  const preloadPath = isSignalTarget ? await resolveSignalTestPreloadPath(exec) : null;
@@ -2231,9 +2236,7 @@ ${detail}`
2231
2236
  const chain = RunnableSequence.from([mainPrompt, chatModel, new StringOutputParser]);
2232
2237
  await chain.invoke({ projectName, projectDesc });
2233
2238
  spinner.succeed("Loading complete!");
2234
- //! add path in tsconfig.json
2235
2239
  }
2236
- async testApplication(app) {}
2237
2240
  }
2238
2241
 
2239
2242
  // pkgs/@akanjs/cli/application/application.script.ts
@@ -2331,6 +2334,17 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
2331
2334
  else
2332
2335
  await this.libraryScript.syncLibrary(sys);
2333
2336
  }
2337
+ async compact(sys, { module = null, minLines, interactive = false } = {}) {
2338
+ const { scanned, reports } = await this.applicationRunner.compact(sys, { module, minLines, interactive });
2339
+ if (!reports.length) {
2340
+ Logger5.rawLog(`No abstract file long enough to compact in ${sys.name} (${scanned} scanned)`);
2341
+ return;
2342
+ }
2343
+ for (const report of reports)
2344
+ Logger5.rawLog(`${report.status}: ${report.path} (${report.beforeLines} -> ${report.afterLines} lines)`);
2345
+ const compactedNum = reports.filter((report) => report.status === "compacted").length;
2346
+ Logger5.rawLog(`Compacted ${compactedNum}/${reports.length} abstract files in ${sys.name}`);
2347
+ }
2334
2348
  async script(app, filename) {
2335
2349
  const scriptFilename = filename ?? await this.applicationRunner.getScriptFilename(app);
2336
2350
  await app.scanSync();
@@ -2515,7 +2529,7 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
2515
2529
  }
2516
2530
  async testApplication(app) {
2517
2531
  const spinner = app.spinning("Testing application...");
2518
- await this.applicationRunner.testApplication(app);
2532
+ await this.applicationRunner.test(app);
2519
2533
  spinner.succeed(`Application ${app.name} (apps/${app.name}) test is successful`);
2520
2534
  }
2521
2535
  }
@@ -1,24 +1,24 @@
1
1
  // @bun
2
2
  import {
3
3
  CloudRunner
4
- } from "./index-j3j3qc9j.js";
4
+ } from "./index-ktprgc5g.js";
5
+ import {
6
+ PackageScript
7
+ } from "./index-e3qskyt2.js";
5
8
  import {
6
9
  AiSession,
7
10
  CloudApi,
8
11
  GlobalConfig
9
- } from "./index-nsj2ftxj.js";
12
+ } from "./index-3pgtw35d.js";
10
13
  import {
11
14
  ApplicationScript
12
- } from "./index-panyahn4.js";
13
- import {
14
- PackageScript
15
- } from "./index-z36qzgzp.js";
15
+ } from "./index-ev6rjw9n.js";
16
16
  import {
17
17
  script
18
- } from "./index-d0h48d2f.js";
18
+ } from "./index-jk9q6pse.js";
19
19
  import {
20
20
  PkgExecutor
21
- } from "./index-xwfg9bam.js";
21
+ } from "./index-jtm86byd.js";
22
22
 
23
23
  // pkgs/@akanjs/cli/cloud/cloud.script.ts
24
24
  import { Logger } from "akanjs/common";
@@ -2,21 +2,21 @@
2
2
  import {
3
3
  pluralizeName
4
4
  } from "./index-ss469dec.js";
5
+ import {
6
+ AiSession
7
+ } from "./index-3pgtw35d.js";
5
8
  import {
6
9
  createPassedPrimitiveReport,
7
10
  generatedFilesForSync,
8
11
  scalarChangedFiles
9
- } from "./index-pfnh87f9.js";
12
+ } from "./index-4zgs8g1w.js";
10
13
  import {
11
14
  Prompter
12
- } from "./index-xftstr5s.js";
13
- import {
14
- AiSession
15
- } from "./index-nsj2ftxj.js";
15
+ } from "./index-xwgm94zr.js";
16
16
  import {
17
17
  runner,
18
18
  script
19
- } from "./index-d0h48d2f.js";
19
+ } from "./index-jk9q6pse.js";
20
20
 
21
21
  // pkgs/@akanjs/cli/scalar/scalar.prompt.ts
22
22
  import { input } from "@inquirer/prompts";
@@ -1,22 +1,22 @@
1
1
  // @bun
2
2
  import {
3
3
  RepairRunner
4
- } from "./index-7ppn9v4n.js";
4
+ } from "./index-b978vs2e.js";
5
5
  import {
6
6
  WorkflowRunner
7
- } from "./index-h971erkm.js";
8
- import {
9
- ScalarScript
10
- } from "./index-z5v766nx.js";
7
+ } from "./index-csqk9z5j.js";
11
8
  import {
12
9
  PrimitiveScript
13
- } from "./index-acwxfncv.js";
10
+ } from "./index-r4w8cry5.js";
14
11
  import {
15
12
  ModuleScript
16
- } from "./index-04as43rp.js";
13
+ } from "./index-vhv3xnjz.js";
14
+ import {
15
+ ScalarScript
16
+ } from "./index-fmgbwsr5.js";
17
17
  import {
18
18
  isPlaceholderAppId
19
- } from "./index-zfp1gz9f.js";
19
+ } from "./index-sggm9qkv.js";
20
20
  import {
21
21
  AkanContextAnalyzer,
22
22
  akanMcpInstallConfigPaths,
@@ -27,17 +27,17 @@ import {
27
27
  renderDoctorText,
28
28
  resourceList,
29
29
  upsertCodexMcpServerBlock
30
- } from "./index-v9jqrdd1.js";
30
+ } from "./index-4yp06pn1.js";
31
31
  import {
32
32
  buildAkanModuleContextIndex,
33
33
  createWorkflowBaselineSummary,
34
34
  createWorkflowStepRegistry,
35
35
  jsonText,
36
36
  toolingRolloutGate
37
- } from "./index-pfnh87f9.js";
37
+ } from "./index-4zgs8g1w.js";
38
38
  import {
39
39
  Prompter
40
- } from "./index-xftstr5s.js";
40
+ } from "./index-xwgm94zr.js";
41
41
  import {
42
42
  getMobileTargets
43
43
  } from "./index-76rn3g2c.js";
@@ -45,10 +45,10 @@ import {
45
45
  CommandContainer,
46
46
  runner,
47
47
  script
48
- } from "./index-d0h48d2f.js";
48
+ } from "./index-jk9q6pse.js";
49
49
  import {
50
50
  AppExecutor
51
- } from "./index-xwfg9bam.js";
51
+ } from "./index-jtm86byd.js";
52
52
 
53
53
  // pkgs/@akanjs/cli/context/context.script.ts
54
54
  import { Logger } from "akanjs/common";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  runner,
4
4
  script
5
- } from "./index-d0h48d2f.js";
5
+ } from "./index-jk9q6pse.js";
6
6
 
7
7
  // pkgs/@akanjs/cli/page/page.runner.ts
8
8
  class PageRunner extends runner("page") {
@@ -7,7 +7,7 @@ import {
7
7
  PkgExecutor,
8
8
  WorkspaceExecutor,
9
9
  getDirname
10
- } from "./index-xwfg9bam.js";
10
+ } from "./index-jtm86byd.js";
11
11
  import {
12
12
  FileSys
13
13
  } from "./index-67546d0j.js";