loadouts 0.1.11

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 (261) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +108 -0
  3. package/bundled/loadouts/loadouts.yaml +5 -0
  4. package/bundled/skills/loadout-usage/SKILL.md +110 -0
  5. package/dist/builtins/index.d.ts +14 -0
  6. package/dist/builtins/index.d.ts.map +1 -0
  7. package/dist/builtins/index.js +58 -0
  8. package/dist/builtins/index.js.map +1 -0
  9. package/dist/builtins/kinds/extension.d.ts +3 -0
  10. package/dist/builtins/kinds/extension.d.ts.map +1 -0
  11. package/dist/builtins/kinds/extension.js +9 -0
  12. package/dist/builtins/kinds/extension.js.map +1 -0
  13. package/dist/builtins/kinds/instruction.d.ts +3 -0
  14. package/dist/builtins/kinds/instruction.d.ts.map +1 -0
  15. package/dist/builtins/kinds/instruction.js +8 -0
  16. package/dist/builtins/kinds/instruction.js.map +1 -0
  17. package/dist/builtins/kinds/prompt.d.ts +3 -0
  18. package/dist/builtins/kinds/prompt.d.ts.map +1 -0
  19. package/dist/builtins/kinds/prompt.js +8 -0
  20. package/dist/builtins/kinds/prompt.js.map +1 -0
  21. package/dist/builtins/kinds/rule.d.ts +3 -0
  22. package/dist/builtins/kinds/rule.d.ts.map +1 -0
  23. package/dist/builtins/kinds/rule.js +10 -0
  24. package/dist/builtins/kinds/rule.js.map +1 -0
  25. package/dist/builtins/kinds/skill.d.ts +3 -0
  26. package/dist/builtins/kinds/skill.d.ts.map +1 -0
  27. package/dist/builtins/kinds/skill.js +8 -0
  28. package/dist/builtins/kinds/skill.js.map +1 -0
  29. package/dist/builtins/kinds/theme.d.ts +3 -0
  30. package/dist/builtins/kinds/theme.d.ts.map +1 -0
  31. package/dist/builtins/kinds/theme.js +8 -0
  32. package/dist/builtins/kinds/theme.js.map +1 -0
  33. package/dist/builtins/tools/claude-code.d.ts +3 -0
  34. package/dist/builtins/tools/claude-code.d.ts.map +1 -0
  35. package/dist/builtins/tools/claude-code.js +30 -0
  36. package/dist/builtins/tools/claude-code.js.map +1 -0
  37. package/dist/builtins/tools/codex.d.ts +3 -0
  38. package/dist/builtins/tools/codex.d.ts.map +1 -0
  39. package/dist/builtins/tools/codex.js +17 -0
  40. package/dist/builtins/tools/codex.js.map +1 -0
  41. package/dist/builtins/tools/cursor.d.ts +3 -0
  42. package/dist/builtins/tools/cursor.d.ts.map +1 -0
  43. package/dist/builtins/tools/cursor.js +22 -0
  44. package/dist/builtins/tools/cursor.js.map +1 -0
  45. package/dist/builtins/tools/opencode.d.ts +3 -0
  46. package/dist/builtins/tools/opencode.d.ts.map +1 -0
  47. package/dist/builtins/tools/opencode.js +45 -0
  48. package/dist/builtins/tools/opencode.js.map +1 -0
  49. package/dist/builtins/tools/pi.d.ts +3 -0
  50. package/dist/builtins/tools/pi.d.ts.map +1 -0
  51. package/dist/builtins/tools/pi.js +22 -0
  52. package/dist/builtins/tools/pi.js.map +1 -0
  53. package/dist/cli/commands/activate.d.ts +12 -0
  54. package/dist/cli/commands/activate.d.ts.map +1 -0
  55. package/dist/cli/commands/activate.js +70 -0
  56. package/dist/cli/commands/activate.js.map +1 -0
  57. package/dist/cli/commands/check.d.ts +12 -0
  58. package/dist/cli/commands/check.d.ts.map +1 -0
  59. package/dist/cli/commands/check.js +152 -0
  60. package/dist/cli/commands/check.js.map +1 -0
  61. package/dist/cli/commands/clear.d.ts +12 -0
  62. package/dist/cli/commands/clear.d.ts.map +1 -0
  63. package/dist/cli/commands/clear.js +25 -0
  64. package/dist/cli/commands/clear.js.map +1 -0
  65. package/dist/cli/commands/create.d.ts +11 -0
  66. package/dist/cli/commands/create.d.ts.map +1 -0
  67. package/dist/cli/commands/create.js +113 -0
  68. package/dist/cli/commands/create.js.map +1 -0
  69. package/dist/cli/commands/deactivate.d.ts +12 -0
  70. package/dist/cli/commands/deactivate.d.ts.map +1 -0
  71. package/dist/cli/commands/deactivate.js +67 -0
  72. package/dist/cli/commands/deactivate.js.map +1 -0
  73. package/dist/cli/commands/diff.d.ts +16 -0
  74. package/dist/cli/commands/diff.d.ts.map +1 -0
  75. package/dist/cli/commands/diff.js +144 -0
  76. package/dist/cli/commands/diff.js.map +1 -0
  77. package/dist/cli/commands/docs.d.ts +12 -0
  78. package/dist/cli/commands/docs.d.ts.map +1 -0
  79. package/dist/cli/commands/docs.js +115 -0
  80. package/dist/cli/commands/docs.js.map +1 -0
  81. package/dist/cli/commands/edit.d.ts +11 -0
  82. package/dist/cli/commands/edit.d.ts.map +1 -0
  83. package/dist/cli/commands/edit.js +71 -0
  84. package/dist/cli/commands/edit.js.map +1 -0
  85. package/dist/cli/commands/fallback.d.ts +9 -0
  86. package/dist/cli/commands/fallback.d.ts.map +1 -0
  87. package/dist/cli/commands/fallback.js +35 -0
  88. package/dist/cli/commands/fallback.js.map +1 -0
  89. package/dist/cli/commands/info.d.ts +23 -0
  90. package/dist/cli/commands/info.d.ts.map +1 -0
  91. package/dist/cli/commands/info.js +314 -0
  92. package/dist/cli/commands/info.js.map +1 -0
  93. package/dist/cli/commands/init.d.ts +18 -0
  94. package/dist/cli/commands/init.d.ts.map +1 -0
  95. package/dist/cli/commands/init.js +255 -0
  96. package/dist/cli/commands/init.js.map +1 -0
  97. package/dist/cli/commands/install.d.ts +27 -0
  98. package/dist/cli/commands/install.d.ts.map +1 -0
  99. package/dist/cli/commands/install.js +586 -0
  100. package/dist/cli/commands/install.js.map +1 -0
  101. package/dist/cli/commands/instructions.d.ts +8 -0
  102. package/dist/cli/commands/instructions.d.ts.map +1 -0
  103. package/dist/cli/commands/instructions.js +218 -0
  104. package/dist/cli/commands/instructions.js.map +1 -0
  105. package/dist/cli/commands/kinds.d.ts +6 -0
  106. package/dist/cli/commands/kinds.d.ts.map +1 -0
  107. package/dist/cli/commands/kinds.js +59 -0
  108. package/dist/cli/commands/kinds.js.map +1 -0
  109. package/dist/cli/commands/list.d.ts +12 -0
  110. package/dist/cli/commands/list.d.ts.map +1 -0
  111. package/dist/cli/commands/list.js +182 -0
  112. package/dist/cli/commands/list.js.map +1 -0
  113. package/dist/cli/commands/policy.d.ts +28 -0
  114. package/dist/cli/commands/policy.d.ts.map +1 -0
  115. package/dist/cli/commands/policy.js +50 -0
  116. package/dist/cli/commands/policy.js.map +1 -0
  117. package/dist/cli/commands/remove.d.ts +24 -0
  118. package/dist/cli/commands/remove.d.ts.map +1 -0
  119. package/dist/cli/commands/remove.js +64 -0
  120. package/dist/cli/commands/remove.js.map +1 -0
  121. package/dist/cli/commands/render-engine.d.ts +36 -0
  122. package/dist/cli/commands/render-engine.d.ts.map +1 -0
  123. package/dist/cli/commands/render-engine.js +177 -0
  124. package/dist/cli/commands/render-engine.js.map +1 -0
  125. package/dist/cli/commands/rule.d.ts +11 -0
  126. package/dist/cli/commands/rule.d.ts.map +1 -0
  127. package/dist/cli/commands/rule.js +302 -0
  128. package/dist/cli/commands/rule.js.map +1 -0
  129. package/dist/cli/commands/sanitize.d.ts +14 -0
  130. package/dist/cli/commands/sanitize.d.ts.map +1 -0
  131. package/dist/cli/commands/sanitize.js +62 -0
  132. package/dist/cli/commands/sanitize.js.map +1 -0
  133. package/dist/cli/commands/skill.d.ts +11 -0
  134. package/dist/cli/commands/skill.d.ts.map +1 -0
  135. package/dist/cli/commands/skill.js +380 -0
  136. package/dist/cli/commands/skill.js.map +1 -0
  137. package/dist/cli/commands/status.d.ts +26 -0
  138. package/dist/cli/commands/status.d.ts.map +1 -0
  139. package/dist/cli/commands/status.js +454 -0
  140. package/dist/cli/commands/status.js.map +1 -0
  141. package/dist/cli/commands/sync.d.ts +14 -0
  142. package/dist/cli/commands/sync.d.ts.map +1 -0
  143. package/dist/cli/commands/sync.js +53 -0
  144. package/dist/cli/commands/sync.js.map +1 -0
  145. package/dist/cli/commands/update.d.ts +3 -0
  146. package/dist/cli/commands/update.d.ts.map +1 -0
  147. package/dist/cli/commands/update.js +48 -0
  148. package/dist/cli/commands/update.js.map +1 -0
  149. package/dist/cli/index.d.ts +11 -0
  150. package/dist/cli/index.d.ts.map +1 -0
  151. package/dist/cli/index.js +134 -0
  152. package/dist/cli/index.js.map +1 -0
  153. package/dist/core/config.d.ts +64 -0
  154. package/dist/core/config.d.ts.map +1 -0
  155. package/dist/core/config.js +166 -0
  156. package/dist/core/config.js.map +1 -0
  157. package/dist/core/discovery.d.ts +50 -0
  158. package/dist/core/discovery.d.ts.map +1 -0
  159. package/dist/core/discovery.js +249 -0
  160. package/dist/core/discovery.js.map +1 -0
  161. package/dist/core/fallback.d.ts +23 -0
  162. package/dist/core/fallback.d.ts.map +1 -0
  163. package/dist/core/fallback.js +119 -0
  164. package/dist/core/fallback.js.map +1 -0
  165. package/dist/core/import-discovery.d.ts +56 -0
  166. package/dist/core/import-discovery.d.ts.map +1 -0
  167. package/dist/core/import-discovery.js +304 -0
  168. package/dist/core/import-discovery.js.map +1 -0
  169. package/dist/core/kindLoader.d.ts +119 -0
  170. package/dist/core/kindLoader.d.ts.map +1 -0
  171. package/dist/core/kindLoader.js +141 -0
  172. package/dist/core/kindLoader.js.map +1 -0
  173. package/dist/core/manifest.d.ts +39 -0
  174. package/dist/core/manifest.d.ts.map +1 -0
  175. package/dist/core/manifest.js +167 -0
  176. package/dist/core/manifest.js.map +1 -0
  177. package/dist/core/plugin.d.ts +22 -0
  178. package/dist/core/plugin.d.ts.map +1 -0
  179. package/dist/core/plugin.js +20 -0
  180. package/dist/core/plugin.js.map +1 -0
  181. package/dist/core/registry.d.ts +115 -0
  182. package/dist/core/registry.d.ts.map +1 -0
  183. package/dist/core/registry.js +105 -0
  184. package/dist/core/registry.js.map +1 -0
  185. package/dist/core/render.d.ts +64 -0
  186. package/dist/core/render.d.ts.map +1 -0
  187. package/dist/core/render.js +457 -0
  188. package/dist/core/render.js.map +1 -0
  189. package/dist/core/resolve.d.ts +39 -0
  190. package/dist/core/resolve.d.ts.map +1 -0
  191. package/dist/core/resolve.js +128 -0
  192. package/dist/core/resolve.js.map +1 -0
  193. package/dist/core/schema.d.ts +308 -0
  194. package/dist/core/schema.d.ts.map +1 -0
  195. package/dist/core/schema.js +81 -0
  196. package/dist/core/schema.js.map +1 -0
  197. package/dist/core/scope.d.ts +74 -0
  198. package/dist/core/scope.d.ts.map +1 -0
  199. package/dist/core/scope.js +176 -0
  200. package/dist/core/scope.js.map +1 -0
  201. package/dist/core/template.d.ts +32 -0
  202. package/dist/core/template.d.ts.map +1 -0
  203. package/dist/core/template.js +32 -0
  204. package/dist/core/template.js.map +1 -0
  205. package/dist/core/tokens.d.ts +33 -0
  206. package/dist/core/tokens.d.ts.map +1 -0
  207. package/dist/core/tokens.js +97 -0
  208. package/dist/core/tokens.js.map +1 -0
  209. package/dist/core/types.d.ts +103 -0
  210. package/dist/core/types.d.ts.map +1 -0
  211. package/dist/core/types.js +10 -0
  212. package/dist/core/types.js.map +1 -0
  213. package/dist/index.d.ts +12 -0
  214. package/dist/index.d.ts.map +1 -0
  215. package/dist/index.js +24 -0
  216. package/dist/index.js.map +1 -0
  217. package/dist/lib/artifact-paths.d.ts +39 -0
  218. package/dist/lib/artifact-paths.d.ts.map +1 -0
  219. package/dist/lib/artifact-paths.js +83 -0
  220. package/dist/lib/artifact-paths.js.map +1 -0
  221. package/dist/lib/artifact-table.d.ts +126 -0
  222. package/dist/lib/artifact-table.d.ts.map +1 -0
  223. package/dist/lib/artifact-table.js +263 -0
  224. package/dist/lib/artifact-table.js.map +1 -0
  225. package/dist/lib/editor.d.ts +17 -0
  226. package/dist/lib/editor.d.ts.map +1 -0
  227. package/dist/lib/editor.js +33 -0
  228. package/dist/lib/editor.js.map +1 -0
  229. package/dist/lib/fs.d.ts +87 -0
  230. package/dist/lib/fs.d.ts.map +1 -0
  231. package/dist/lib/fs.js +229 -0
  232. package/dist/lib/fs.js.map +1 -0
  233. package/dist/lib/git.d.ts +13 -0
  234. package/dist/lib/git.d.ts.map +1 -0
  235. package/dist/lib/git.js +28 -0
  236. package/dist/lib/git.js.map +1 -0
  237. package/dist/lib/gitignore.d.ts +26 -0
  238. package/dist/lib/gitignore.d.ts.map +1 -0
  239. package/dist/lib/gitignore.js +97 -0
  240. package/dist/lib/gitignore.js.map +1 -0
  241. package/dist/lib/loadout-column.d.ts +66 -0
  242. package/dist/lib/loadout-column.d.ts.map +1 -0
  243. package/dist/lib/loadout-column.js +66 -0
  244. package/dist/lib/loadout-column.js.map +1 -0
  245. package/dist/lib/output.d.ts +15 -0
  246. package/dist/lib/output.d.ts.map +1 -0
  247. package/dist/lib/output.js +32 -0
  248. package/dist/lib/output.js.map +1 -0
  249. package/dist/lib/scope-indicators.d.ts +60 -0
  250. package/dist/lib/scope-indicators.d.ts.map +1 -0
  251. package/dist/lib/scope-indicators.js +110 -0
  252. package/dist/lib/scope-indicators.js.map +1 -0
  253. package/docs/authoring.md +182 -0
  254. package/docs/commands.md +192 -0
  255. package/docs/concepts.md +114 -0
  256. package/docs/index.md +60 -0
  257. package/docs/quickstart.md +100 -0
  258. package/docs/troubleshooting.md +147 -0
  259. package/docs/visual-language.md +251 -0
  260. package/docs/workflows.md +184 -0
  261. package/package.json +54 -0
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Path template engine.
3
+ *
4
+ * Expands {token} placeholders in an OutputMapping path template.
5
+ * Unknown tokens throw at expansion time so misconfiguration is caught early.
6
+ *
7
+ * Supported tokens:
8
+ * {base} — tool.basePath[scope] (e.g. ".claude" or "/Users/you/.claude")
9
+ * {home} — os.homedir() (always absolute; scope-independent)
10
+ * {stem} — source basename without extension
11
+ * {ext} — extension with dot (mapping.ext override or source extension)
12
+ * {name} — source basename including extension
13
+ * {relative} — item.relativePath (e.g. "rules/foo.md")
14
+ * {kind} — kind id (e.g. "rule")
15
+ */
16
+ import type { PathTemplate } from "./registry.js";
17
+ import type { Scope } from "./types.js";
18
+ export interface TemplateVars {
19
+ base: string;
20
+ home: string;
21
+ stem: string;
22
+ ext: string;
23
+ name: string;
24
+ relative: string;
25
+ kind: string;
26
+ }
27
+ /**
28
+ * Expand a path template for the given scope and variables.
29
+ * Returns a normalized path (collapses `.` segments, etc.).
30
+ */
31
+ export declare function expandTemplate(template: PathTemplate, scope: Scope, vars: TemplateVars): string;
32
+ //# sourceMappingURL=template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/core/template.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,YAAY,EACtB,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,YAAY,GACjB,MAAM,CAaR"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Path template engine.
3
+ *
4
+ * Expands {token} placeholders in an OutputMapping path template.
5
+ * Unknown tokens throw at expansion time so misconfiguration is caught early.
6
+ *
7
+ * Supported tokens:
8
+ * {base} — tool.basePath[scope] (e.g. ".claude" or "/Users/you/.claude")
9
+ * {home} — os.homedir() (always absolute; scope-independent)
10
+ * {stem} — source basename without extension
11
+ * {ext} — extension with dot (mapping.ext override or source extension)
12
+ * {name} — source basename including extension
13
+ * {relative} — item.relativePath (e.g. "rules/foo.md")
14
+ * {kind} — kind id (e.g. "rule")
15
+ */
16
+ import * as path from "node:path";
17
+ /**
18
+ * Expand a path template for the given scope and variables.
19
+ * Returns a normalized path (collapses `.` segments, etc.).
20
+ */
21
+ export function expandTemplate(template, scope, vars) {
22
+ const tpl = typeof template === "string" ? template : template[scope];
23
+ const expanded = tpl.replace(/\{(\w+)\}/g, (match, key) => {
24
+ if (key in vars)
25
+ return vars[key];
26
+ throw new Error(`Unknown path template token: {${key}} in "${tpl}". ` +
27
+ `Valid tokens: ${Object.keys(vars).map((k) => `{${k}}`).join(", ")}`);
28
+ });
29
+ // Normalize to clean up "./" prefixes without changing absolute paths
30
+ return path.normalize(expanded);
31
+ }
32
+ //# sourceMappingURL=template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.js","sourceRoot":"","sources":["../../src/core/template.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAclC;;;GAGG;AACH,MAAM,UAAU,cAAc,CAC5B,QAAsB,EACtB,KAAY,EACZ,IAAkB;IAElB,MAAM,GAAG,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAEtE,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACxD,IAAI,GAAG,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC,GAAyB,CAAC,CAAC;QACxD,MAAM,IAAI,KAAK,CACb,iCAAiC,GAAG,SAAS,GAAG,KAAK;YACnD,iBAAiB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACvE,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,sEAAsE;IACtE,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;AAClC,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Token estimation for rendered outputs
3
+ *
4
+ * Uses a simple approximation: ~4 characters per token for English text.
5
+ * This is intentionally rough—good enough to compare loadouts and catch bloat.
6
+ */
7
+ /**
8
+ * Estimate tokens for a string.
9
+ */
10
+ export declare function estimateTokens(content: string): number;
11
+ /**
12
+ * Estimate tokens for a file.
13
+ */
14
+ export declare function estimateFileTokens(filePath: string): number;
15
+ /**
16
+ * Estimate tokens for a directory (sum of all files).
17
+ */
18
+ export declare function estimateDirTokens(dirPath: string): number;
19
+ /**
20
+ * Format token count for display.
21
+ */
22
+ export declare function formatTokens(tokens: number): string;
23
+ /**
24
+ * Extract frontmatter description from a skill's SKILL.md file.
25
+ * Returns the description string or undefined if not found.
26
+ */
27
+ export declare function extractSkillDescription(skillDirPath: string): string | undefined;
28
+ /**
29
+ * Estimate upfront tokens for a skill directory.
30
+ * This is the description that goes into the system prompt by default.
31
+ */
32
+ export declare function estimateSkillUpfrontTokens(skillDirPath: string): number;
33
+ //# sourceMappingURL=tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/core/tokens.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAO3D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAsBzD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKnD;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAgBhF;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAQvE"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Token estimation for rendered outputs
3
+ *
4
+ * Uses a simple approximation: ~4 characters per token for English text.
5
+ * This is intentionally rough—good enough to compare loadouts and catch bloat.
6
+ */
7
+ import { readFile, isDirectory, listFiles, fileExists } from "../lib/fs.js";
8
+ import * as path from "node:path";
9
+ const CHARS_PER_TOKEN = 4;
10
+ /**
11
+ * Estimate tokens for a string.
12
+ */
13
+ export function estimateTokens(content) {
14
+ return Math.ceil(content.length / CHARS_PER_TOKEN);
15
+ }
16
+ /**
17
+ * Estimate tokens for a file.
18
+ */
19
+ export function estimateFileTokens(filePath) {
20
+ try {
21
+ const content = readFile(filePath);
22
+ return estimateTokens(content);
23
+ }
24
+ catch {
25
+ return 0;
26
+ }
27
+ }
28
+ /**
29
+ * Estimate tokens for a directory (sum of all files).
30
+ */
31
+ export function estimateDirTokens(dirPath) {
32
+ let total = 0;
33
+ function walk(dir) {
34
+ const entries = listFiles(dir);
35
+ for (const entry of entries) {
36
+ const fullPath = path.join(dir, entry);
37
+ if (isDirectory(fullPath)) {
38
+ walk(fullPath);
39
+ }
40
+ else {
41
+ total += estimateFileTokens(fullPath);
42
+ }
43
+ }
44
+ }
45
+ try {
46
+ walk(dirPath);
47
+ }
48
+ catch {
49
+ // Ignore errors
50
+ }
51
+ return total;
52
+ }
53
+ /**
54
+ * Format token count for display.
55
+ */
56
+ export function formatTokens(tokens) {
57
+ if (tokens < 1000) {
58
+ return `${tokens} tokens`;
59
+ }
60
+ return `${(tokens / 1000).toFixed(1)}k tokens`;
61
+ }
62
+ /**
63
+ * Extract frontmatter description from a skill's SKILL.md file.
64
+ * Returns the description string or undefined if not found.
65
+ */
66
+ export function extractSkillDescription(skillDirPath) {
67
+ const skillMdPath = path.join(skillDirPath, "SKILL.md");
68
+ if (!fileExists(skillMdPath))
69
+ return undefined;
70
+ try {
71
+ const content = readFile(skillMdPath);
72
+ // Match YAML frontmatter: ---\n...description: ...\n...---
73
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
74
+ if (!frontmatterMatch)
75
+ return undefined;
76
+ const frontmatter = frontmatterMatch[1];
77
+ const descMatch = frontmatter.match(/^description:\s*(.+)$/m);
78
+ return descMatch ? descMatch[1].trim() : undefined;
79
+ }
80
+ catch {
81
+ return undefined;
82
+ }
83
+ }
84
+ /**
85
+ * Estimate upfront tokens for a skill directory.
86
+ * This is the description that goes into the system prompt by default.
87
+ */
88
+ export function estimateSkillUpfrontTokens(skillDirPath) {
89
+ const description = extractSkillDescription(skillDirPath);
90
+ if (!description)
91
+ return 0;
92
+ // Include some overhead for the skill XML wrapper that most harnesses use
93
+ // e.g., <skill><name>...</name><description>...</description>...</skill>
94
+ const overhead = 50; // ~200 chars for XML tags and name
95
+ return estimateTokens(description) + Math.ceil(overhead / CHARS_PER_TOKEN);
96
+ }
97
+ //# sourceMappingURL=tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/core/tokens.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Core type definitions for Loadout.
3
+ *
4
+ * Tool and ArtifactKind are open strings backed by the registry at runtime.
5
+ * Use registry.getTool() / registry.getKind() to validate at call sites where
6
+ * correctness matters. Compile-time exhaustiveness checking is traded for
7
+ * extensibility — the registry provides equivalent runtime validation.
8
+ */
9
+ export type Scope = "global" | "project";
10
+ export type Tool = string;
11
+ export type ArtifactKind = string;
12
+ export type OutputMode = "symlink" | "copy" | "generate";
13
+ export type SourceRef = string;
14
+ export interface RootConfig {
15
+ version: "1";
16
+ default?: string;
17
+ mode?: OutputMode;
18
+ tools?: Tool[];
19
+ sources?: SourceRef[];
20
+ }
21
+ export interface LoadoutDefinition {
22
+ name: string;
23
+ description?: string;
24
+ tools?: Tool[];
25
+ include: LoadoutInclude[];
26
+ }
27
+ export type LoadoutInclude = string | {
28
+ path: string;
29
+ tools?: Tool[];
30
+ };
31
+ export interface ResolvedItem {
32
+ kind: ArtifactKind;
33
+ sourcePath: string;
34
+ relativePath: string;
35
+ tools: Tool[];
36
+ }
37
+ export interface ResolvedLoadout {
38
+ name: string;
39
+ description?: string;
40
+ tools: Tool[];
41
+ items: ResolvedItem[];
42
+ rootPath: string;
43
+ }
44
+ export interface OutputSpec {
45
+ tool: Tool;
46
+ kind: ArtifactKind;
47
+ sourcePath: string;
48
+ /** Relative path from project root, or absolute for global scope outputs. */
49
+ targetPath: string;
50
+ mode: OutputMode;
51
+ }
52
+ export interface RenderedOutput {
53
+ content: string;
54
+ hash: string;
55
+ }
56
+ export interface ManifestEntry {
57
+ tools: Tool[];
58
+ kind: ArtifactKind;
59
+ sourcePath: string;
60
+ targetPath: string;
61
+ mode: OutputMode;
62
+ renderedHash: string;
63
+ }
64
+ export interface ShadowedEntry {
65
+ tool: Tool;
66
+ kind: ArtifactKind;
67
+ sourcePath: string;
68
+ targetPath: string;
69
+ }
70
+ export interface AppliedState {
71
+ active: string[];
72
+ mode: OutputMode;
73
+ appliedAt: string;
74
+ entries: ManifestEntry[];
75
+ shadowed: ShadowedEntry[];
76
+ }
77
+ export interface LoadoutRoot {
78
+ path: string;
79
+ level: "project" | "source" | "global" | "bundled";
80
+ depth: number;
81
+ sourceRef?: string;
82
+ }
83
+ export interface CommandContext {
84
+ scope: Scope;
85
+ configPath: string;
86
+ statePath: string;
87
+ projectRoot: string;
88
+ }
89
+ export interface ValidationResult {
90
+ valid: boolean;
91
+ warnings: string[];
92
+ errors: string[];
93
+ }
94
+ export interface RenderPlan {
95
+ outputs: Array<{
96
+ spec: OutputSpec;
97
+ item: ResolvedItem;
98
+ hash: string;
99
+ }>;
100
+ errors: string[];
101
+ shadowed: ShadowedEntry[];
102
+ }
103
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Core type definitions for Loadout.
3
+ *
4
+ * Tool and ArtifactKind are open strings backed by the registry at runtime.
5
+ * Use registry.getTool() / registry.getKind() to validate at call sites where
6
+ * correctness matters. Compile-time exhaustiveness checking is traded for
7
+ * extensibility — the registry provides equivalent runtime validation.
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Loadouts CLI entry point.
4
+ *
5
+ * Bootstrap order:
6
+ * 1. Check for updates (non-blocking background check).
7
+ * 2. Register built-in kinds, transforms, and tools.
8
+ * 3. (Phase 4+) YAML kinds loaded per-command after root discovery.
9
+ * 4. Parse and dispatch CLI commands.
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;GAQG"}
package/dist/index.js ADDED
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Loadouts CLI entry point.
4
+ *
5
+ * Bootstrap order:
6
+ * 1. Check for updates (non-blocking background check).
7
+ * 2. Register built-in kinds, transforms, and tools.
8
+ * 3. (Phase 4+) YAML kinds loaded per-command after root discovery.
9
+ * 4. Parse and dispatch CLI commands.
10
+ */
11
+ import { createRequire } from "module";
12
+ import updateNotifier from "update-notifier";
13
+ import { registry } from "./core/registry.js";
14
+ import { createPluginAPI } from "./core/plugin.js";
15
+ import { registerBuiltins } from "./builtins/index.js";
16
+ import { cli } from "./cli/index.js";
17
+ // Check for updates in background (cached, checks at most once per day)
18
+ const require = createRequire(import.meta.url);
19
+ const pkg = require("../package.json");
20
+ updateNotifier({ pkg }).notify();
21
+ const api = createPluginAPI(registry);
22
+ registerBuiltins(api);
23
+ cli.parse();
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;GAQG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,cAAc,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAErC,wEAAwE;AACxE,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AACvC,cAAc,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;AAEjC,MAAM,GAAG,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;AACtC,gBAAgB,CAAC,GAAG,CAAC,CAAC;AAEtB,GAAG,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Shared utilities for artifact path handling.
3
+ *
4
+ * Consolidates logic for:
5
+ * - Determining if a root level is global scope
6
+ * - Extracting relative artifact paths from absolute source paths
7
+ */
8
+ import type { LoadoutRoot } from "../core/types.js";
9
+ /**
10
+ * Check if a root level represents global scope.
11
+ * Both "global" and "bundled" roots are global scope.
12
+ */
13
+ export declare function isGlobalScope(level: LoadoutRoot["level"]): boolean;
14
+ /**
15
+ * Check if a root level represents project/local scope.
16
+ */
17
+ export declare function isProjectScope(level: LoadoutRoot["level"]): boolean;
18
+ /**
19
+ * Extract the relative artifact path from an absolute source path.
20
+ *
21
+ * Handles:
22
+ * - .loadouts/ directories (project and global)
23
+ * - bundled/ directory (ships with CLI)
24
+ *
25
+ * Returns the path relative to the loadouts/bundled root, e.g.:
26
+ * - "/path/to/.loadouts/rules/my-rule.md" → "rules/my-rule.md"
27
+ * - "/path/to/bundled/skills/my-skill/SKILL.md" → "skills/my-skill/SKILL.md"
28
+ */
29
+ export declare function extractRelativePath(sourcePath: string): string;
30
+ /**
31
+ * Extract artifact display name from a relative path.
32
+ *
33
+ * Extracts human-friendly names:
34
+ * - "skills/debugging/SKILL.md" → "debugging"
35
+ * - "rules/my-rule.md" → "my-rule"
36
+ * - "instructions/AGENTS.base.md" → "AGENTS.base.md"
37
+ */
38
+ export declare function extractArtifactName(relativePath: string, kind: string): string;
39
+ //# sourceMappingURL=artifact-paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-paths.d.ts","sourceRoot":"","sources":["../../src/lib/artifact-paths.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,GAAG,OAAO,CAElE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,GAAG,OAAO,CAEnE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAmB9D;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAuB9E"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Shared utilities for artifact path handling.
3
+ *
4
+ * Consolidates logic for:
5
+ * - Determining if a root level is global scope
6
+ * - Extracting relative artifact paths from absolute source paths
7
+ */
8
+ import * as path from "node:path";
9
+ /**
10
+ * Check if a root level represents global scope.
11
+ * Both "global" and "bundled" roots are global scope.
12
+ */
13
+ export function isGlobalScope(level) {
14
+ return level === "global" || level === "bundled";
15
+ }
16
+ /**
17
+ * Check if a root level represents project/local scope.
18
+ */
19
+ export function isProjectScope(level) {
20
+ return level === "project";
21
+ }
22
+ /**
23
+ * Extract the relative artifact path from an absolute source path.
24
+ *
25
+ * Handles:
26
+ * - .loadouts/ directories (project and global)
27
+ * - bundled/ directory (ships with CLI)
28
+ *
29
+ * Returns the path relative to the loadouts/bundled root, e.g.:
30
+ * - "/path/to/.loadouts/rules/my-rule.md" → "rules/my-rule.md"
31
+ * - "/path/to/bundled/skills/my-skill/SKILL.md" → "skills/my-skill/SKILL.md"
32
+ */
33
+ export function extractRelativePath(sourcePath) {
34
+ const parts = sourcePath.split(path.sep);
35
+ // Check for bundled directory first (more specific)
36
+ const bundledIdx = parts.findIndex(p => p === "bundled");
37
+ if (bundledIdx >= 0) {
38
+ return parts.slice(bundledIdx + 1).join("/");
39
+ }
40
+ // Check for .loadouts directory
41
+ const loadoutIdx = parts.findIndex(p => p === ".loadouts");
42
+ if (loadoutIdx >= 0) {
43
+ return parts.slice(loadoutIdx + 1).join("/");
44
+ }
45
+ // Fallback: return parent/basename
46
+ const basename = path.basename(sourcePath);
47
+ const parent = path.basename(path.dirname(sourcePath));
48
+ return `${parent}/${basename}`;
49
+ }
50
+ /**
51
+ * Extract artifact display name from a relative path.
52
+ *
53
+ * Extracts human-friendly names:
54
+ * - "skills/debugging/SKILL.md" → "debugging"
55
+ * - "rules/my-rule.md" → "my-rule"
56
+ * - "instructions/AGENTS.base.md" → "AGENTS.base.md"
57
+ */
58
+ export function extractArtifactName(relativePath, kind) {
59
+ switch (kind) {
60
+ case "skill": {
61
+ const match = relativePath.match(/^skills\/([^/]+)/);
62
+ return match ? match[1] : relativePath;
63
+ }
64
+ case "rule": {
65
+ const match = relativePath.match(/^rules\/(.+)\.md$/);
66
+ return match ? match[1] : relativePath;
67
+ }
68
+ case "instruction": {
69
+ const dirMatch = relativePath.match(/^instructions\/(AGENTS\.[^/]+\.md)$/);
70
+ if (dirMatch)
71
+ return dirMatch[1];
72
+ const rootMatch = relativePath.match(/^([^/]+\.md)$/);
73
+ return rootMatch ? rootMatch[1] : relativePath;
74
+ }
75
+ case "extension": {
76
+ const match = relativePath.match(/^extensions\/(.+)$/);
77
+ return match ? match[1] : relativePath;
78
+ }
79
+ default:
80
+ return relativePath;
81
+ }
82
+ }
83
+ //# sourceMappingURL=artifact-paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-paths.js","sourceRoot":"","sources":["../../src/lib/artifact-paths.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAGlC;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,KAA2B;IACvD,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,SAAS,CAAC;AACnD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,KAA2B;IACxD,OAAO,KAAK,KAAK,SAAS,CAAC;AAC7B,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAkB;IACpD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEzC,oDAAoD;IACpD,MAAM,UAAU,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;IACzD,IAAI,UAAU,IAAI,CAAC,EAAE,CAAC;QACpB,OAAO,KAAK,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,CAAC;IAED,gCAAgC;IAChC,MAAM,UAAU,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC;IAC3D,IAAI,UAAU,IAAI,CAAC,EAAE,CAAC;QACpB,OAAO,KAAK,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,CAAC;IAED,mCAAmC;IACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;IACvD,OAAO,GAAG,MAAM,IAAI,QAAQ,EAAE,CAAC;AACjC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAAC,YAAoB,EAAE,IAAY;IACpE,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;YACrD,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;QACzC,CAAC;QACD,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;YACtD,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;QACzC,CAAC;QACD,KAAK,aAAa,CAAC,CAAC,CAAC;YACnB,MAAM,QAAQ,GAAG,YAAY,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;YAC3E,IAAI,QAAQ;gBAAE,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC;YACjC,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;YACtD,OAAO,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;QACjD,CAAC;QACD,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;YACvD,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;QACzC,CAAC;QACD;YACE,OAAO,YAAY,CAAC;IACxB,CAAC;AACH,CAAC"}
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Shared artifact table rendering utilities.
3
+ *
4
+ * All commands that display artifact information should use these utilities
5
+ * to maintain visual consistency. See docs/visual-language.md for the full spec.
6
+ */
7
+ import type { Tool, OutputMode } from "../core/types.js";
8
+ export declare const KIND_SORT_ORDER: Record<string, number>;
9
+ /**
10
+ * Base artifact info needed for table display.
11
+ */
12
+ export interface ArtifactRow {
13
+ kind: string;
14
+ name: string;
15
+ relativePath: string;
16
+ tools: Tool[];
17
+ }
18
+ /**
19
+ * Extract artifact display name from a relative path.
20
+ *
21
+ * Examples:
22
+ * skills/codebase-layout → codebase-layout
23
+ * skills/codebase-layout/SKILL.md → codebase-layout
24
+ * rules/agent-definitions.md → agent-definitions
25
+ * instructions/AGENTS.base.md → AGENTS.base.md
26
+ */
27
+ export declare function getArtifactName(relativePath: string, kind: string): string;
28
+ /**
29
+ * Sort artifacts by kind priority, then alphabetically by name.
30
+ */
31
+ export declare function sortArtifacts<T extends {
32
+ kind: string;
33
+ name: string;
34
+ }>(items: T[]): T[];
35
+ /**
36
+ * Truncate a string with leading ellipsis if too long.
37
+ */
38
+ export declare function truncatePath(str: string, maxLen: number): string;
39
+ /**
40
+ * Calculate tool column specs.
41
+ */
42
+ export interface ToolColumn {
43
+ tool: Tool;
44
+ width: number;
45
+ }
46
+ export declare function getToolColumns(tools: Tool[]): ToolColumn[];
47
+ /**
48
+ * Render table header row.
49
+ */
50
+ export declare function renderHeader(kindWidth: number, nameWidth: number, toolCols: ToolColumn[], extraHeaders?: Array<{
51
+ label: string;
52
+ width: number;
53
+ }>): void;
54
+ /**
55
+ * Render table separator row.
56
+ */
57
+ export declare function renderSeparator(kindWidth: number, nameWidth: number, toolCols: ToolColumn[], extraWidths?: number[]): void;
58
+ /**
59
+ * Calculate dynamic column widths for kind and name columns.
60
+ */
61
+ export declare function calculateColumnWidths(artifacts: Array<{
62
+ kind: string;
63
+ name: string;
64
+ }>, minKindWidth?: number, maxNameWidth?: number): {
65
+ kindWidth: number;
66
+ nameWidth: number;
67
+ };
68
+ export type ChangeType = "added" | "updated" | "removed" | "unchanged" | "shadowed";
69
+ export declare const CHANGE_SYMBOLS: Record<ChangeType, {
70
+ symbol: string;
71
+ color: (s: string) => string;
72
+ }>;
73
+ export declare const MODE_ABBREV: Record<OutputMode, string>;
74
+ /**
75
+ * Output info for a single (artifact, tool) pair.
76
+ */
77
+ export interface ArtifactOutput {
78
+ tool: Tool;
79
+ targetPath: string;
80
+ mode: OutputMode;
81
+ change: ChangeType;
82
+ }
83
+ /**
84
+ * Grouped artifact info for table display.
85
+ */
86
+ export interface GroupedArtifact {
87
+ kind: string;
88
+ name: string;
89
+ sourcePath: string;
90
+ outputs: Map<Tool, ArtifactOutput>;
91
+ overallChange: ChangeType;
92
+ }
93
+ /**
94
+ * Group outputs by source artifact (sourcePath).
95
+ * Returns artifacts sorted by kind priority then name.
96
+ */
97
+ export declare function groupOutputsByArtifact(outputs: Array<{
98
+ spec: {
99
+ tool: Tool;
100
+ kind: string;
101
+ sourcePath: string;
102
+ targetPath: string;
103
+ mode: OutputMode;
104
+ };
105
+ change: ChangeType;
106
+ }>): GroupedArtifact[];
107
+ export interface ChangeTableOptions {
108
+ /** Show mode instead of change symbol (for dry-run) */
109
+ showMode?: boolean;
110
+ /** Show action column with overall change */
111
+ showAction?: boolean;
112
+ }
113
+ /**
114
+ * Render a change table showing artifacts as rows and tools as columns.
115
+ * Cells show change indicators (+, ~, -, ✓) or mode abbreviations.
116
+ */
117
+ export declare function renderChangeTable(artifacts: GroupedArtifact[], tools: Tool[], options?: ChangeTableOptions): void;
118
+ /**
119
+ * Render a summary line for changes.
120
+ */
121
+ export declare function renderChangeSummary(added: number, updated: number, removed: number): void;
122
+ /**
123
+ * Render a dry-run summary.
124
+ */
125
+ export declare function renderDryRunSummary(totalOutputs: number, totalTools: number): void;
126
+ //# sourceMappingURL=artifact-table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-table.d.ts","sourceRoot":"","sources":["../../src/lib/artifact-table.ts"],"names":[],"mappings":"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"}