@flowstack-ui/agent-tools 0.1.0-bootstrap.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 (239) hide show
  1. package/.codex-plugin/plugin.json +37 -0
  2. package/CHANGELOG.md +21 -0
  3. package/LICENSE +21 -0
  4. package/README.md +125 -0
  5. package/docs/architecture.md +77 -0
  6. package/docs/releasing.md +26 -0
  7. package/docs/testing.md +32 -0
  8. package/package.json +63 -0
  9. package/public/index.json +2073 -0
  10. package/public/llms.txt +19 -0
  11. package/public/packages/atom/0.24.0/components/accordion.txt +131 -0
  12. package/public/packages/atom/0.24.0/components/alert-dialog.txt +112 -0
  13. package/public/packages/atom/0.24.0/components/app-bar.txt +96 -0
  14. package/public/packages/atom/0.24.0/components/aspect-ratio.txt +111 -0
  15. package/public/packages/atom/0.24.0/components/avatar.txt +119 -0
  16. package/public/packages/atom/0.24.0/components/badge.txt +123 -0
  17. package/public/packages/atom/0.24.0/components/bottom-navigation.txt +96 -0
  18. package/public/packages/atom/0.24.0/components/breadcrumb.txt +96 -0
  19. package/public/packages/atom/0.24.0/components/button.txt +98 -0
  20. package/public/packages/atom/0.24.0/components/carousel.txt +128 -0
  21. package/public/packages/atom/0.24.0/components/checkbox-group.txt +118 -0
  22. package/public/packages/atom/0.24.0/components/checkbox.txt +100 -0
  23. package/public/packages/atom/0.24.0/components/clipboard.txt +112 -0
  24. package/public/packages/atom/0.24.0/components/collapsible.txt +112 -0
  25. package/public/packages/atom/0.24.0/components/color-picker.txt +117 -0
  26. package/public/packages/atom/0.24.0/components/combobox.txt +126 -0
  27. package/public/packages/atom/0.24.0/components/context-menu.txt +114 -0
  28. package/public/packages/atom/0.24.0/components/data-grid.txt +136 -0
  29. package/public/packages/atom/0.24.0/components/dialog.txt +116 -0
  30. package/public/packages/atom/0.24.0/components/direction.txt +132 -0
  31. package/public/packages/atom/0.24.0/components/divider.txt +94 -0
  32. package/public/packages/atom/0.24.0/components/drag-drop.txt +141 -0
  33. package/public/packages/atom/0.24.0/components/drawer.txt +96 -0
  34. package/public/packages/atom/0.24.0/components/dropdown-menu.txt +112 -0
  35. package/public/packages/atom/0.24.0/components/feed.txt +132 -0
  36. package/public/packages/atom/0.24.0/components/field.txt +108 -0
  37. package/public/packages/atom/0.24.0/components/fieldset.txt +96 -0
  38. package/public/packages/atom/0.24.0/components/file-upload.txt +120 -0
  39. package/public/packages/atom/0.24.0/components/form.txt +98 -0
  40. package/public/packages/atom/0.24.0/components/hover-card.txt +114 -0
  41. package/public/packages/atom/0.24.0/components/image.txt +94 -0
  42. package/public/packages/atom/0.24.0/components/input.txt +96 -0
  43. package/public/packages/atom/0.24.0/components/label.txt +121 -0
  44. package/public/packages/atom/0.24.0/components/link.txt +100 -0
  45. package/public/packages/atom/0.24.0/components/list.txt +131 -0
  46. package/public/packages/atom/0.24.0/components/listbox.txt +120 -0
  47. package/public/packages/atom/0.24.0/components/menu.txt +126 -0
  48. package/public/packages/atom/0.24.0/components/menubar.txt +120 -0
  49. package/public/packages/atom/0.24.0/components/modal.txt +118 -0
  50. package/public/packages/atom/0.24.0/components/multi-select.txt +120 -0
  51. package/public/packages/atom/0.24.0/components/nav-list.txt +104 -0
  52. package/public/packages/atom/0.24.0/components/navigation-menu.txt +104 -0
  53. package/public/packages/atom/0.24.0/components/number-input.txt +124 -0
  54. package/public/packages/atom/0.24.0/components/otp-field.txt +122 -0
  55. package/public/packages/atom/0.24.0/components/pagination.txt +111 -0
  56. package/public/packages/atom/0.24.0/components/password-toggle-field.txt +116 -0
  57. package/public/packages/atom/0.24.0/components/popover.txt +122 -0
  58. package/public/packages/atom/0.24.0/components/pressable.txt +94 -0
  59. package/public/packages/atom/0.24.0/components/progress.txt +130 -0
  60. package/public/packages/atom/0.24.0/components/radio-group.txt +118 -0
  61. package/public/packages/atom/0.24.0/components/rating.txt +122 -0
  62. package/public/packages/atom/0.24.0/components/reorder.txt +141 -0
  63. package/public/packages/atom/0.24.0/components/scroll-area.txt +96 -0
  64. package/public/packages/atom/0.24.0/components/select.txt +126 -0
  65. package/public/packages/atom/0.24.0/components/sidebar.txt +96 -0
  66. package/public/packages/atom/0.24.0/components/skip-link.txt +96 -0
  67. package/public/packages/atom/0.24.0/components/slider.txt +124 -0
  68. package/public/packages/atom/0.24.0/components/swipeable-item.txt +118 -0
  69. package/public/packages/atom/0.24.0/components/switch.txt +116 -0
  70. package/public/packages/atom/0.24.0/components/table.txt +128 -0
  71. package/public/packages/atom/0.24.0/components/tabs.txt +96 -0
  72. package/public/packages/atom/0.24.0/components/textarea.txt +96 -0
  73. package/public/packages/atom/0.24.0/components/toast.txt +124 -0
  74. package/public/packages/atom/0.24.0/components/toggle-group.txt +118 -0
  75. package/public/packages/atom/0.24.0/components/toggle.txt +110 -0
  76. package/public/packages/atom/0.24.0/components/toolbar.txt +98 -0
  77. package/public/packages/atom/0.24.0/components/tooltip.txt +112 -0
  78. package/public/packages/atom/0.24.0/components/tree-grid.txt +138 -0
  79. package/public/packages/atom/0.24.0/components/tree.txt +138 -0
  80. package/public/packages/atom/0.24.0/components/visually-hidden.txt +119 -0
  81. package/public/packages/atom/0.24.0/docs/guides/agent-knowledge.txt +55 -0
  82. package/public/packages/atom/0.24.0/docs/guides/getting-started.txt +65 -0
  83. package/public/packages/atom/0.24.0/docs/guides/imports.txt +26 -0
  84. package/public/packages/atom/0.24.0/docs/guides/public-api.txt +100 -0
  85. package/public/packages/atom/0.24.0/guides/behavior-composition.txt +277 -0
  86. package/public/packages/atom/0.24.0/guides/layer-selection.txt +807 -0
  87. package/public/packages/atom/0.24.0/index.txt +89 -0
  88. package/public/packages/brick/0.1.11/components/accordion.txt +158 -0
  89. package/public/packages/brick/0.1.11/components/alert-dialog.txt +175 -0
  90. package/public/packages/brick/0.1.11/components/app-bar.txt +134 -0
  91. package/public/packages/brick/0.1.11/components/appearance.txt +143 -0
  92. package/public/packages/brick/0.1.11/components/aspect-ratio.txt +136 -0
  93. package/public/packages/brick/0.1.11/components/avatar.txt +152 -0
  94. package/public/packages/brick/0.1.11/components/badge.txt +139 -0
  95. package/public/packages/brick/0.1.11/components/bleed.txt +104 -0
  96. package/public/packages/brick/0.1.11/components/bottom-navigation.txt +106 -0
  97. package/public/packages/brick/0.1.11/components/breadcrumb.txt +96 -0
  98. package/public/packages/brick/0.1.11/components/button.txt +103 -0
  99. package/public/packages/brick/0.1.11/components/card.txt +132 -0
  100. package/public/packages/brick/0.1.11/components/carousel.txt +206 -0
  101. package/public/packages/brick/0.1.11/components/checkbox-group.txt +175 -0
  102. package/public/packages/brick/0.1.11/components/checkbox.txt +103 -0
  103. package/public/packages/brick/0.1.11/components/chip.txt +128 -0
  104. package/public/packages/brick/0.1.11/components/code-block.txt +134 -0
  105. package/public/packages/brick/0.1.11/components/code.txt +120 -0
  106. package/public/packages/brick/0.1.11/components/collapsible.txt +179 -0
  107. package/public/packages/brick/0.1.11/components/color-picker.txt +135 -0
  108. package/public/packages/brick/0.1.11/components/color-swatch.txt +98 -0
  109. package/public/packages/brick/0.1.11/components/combobox.txt +157 -0
  110. package/public/packages/brick/0.1.11/components/container.txt +112 -0
  111. package/public/packages/brick/0.1.11/components/context-menu.txt +174 -0
  112. package/public/packages/brick/0.1.11/components/data-grid.txt +199 -0
  113. package/public/packages/brick/0.1.11/components/data-list.txt +115 -0
  114. package/public/packages/brick/0.1.11/components/dialog.txt +176 -0
  115. package/public/packages/brick/0.1.11/components/divider.txt +104 -0
  116. package/public/packages/brick/0.1.11/components/drawer.txt +146 -0
  117. package/public/packages/brick/0.1.11/components/dropdown-menu.txt +179 -0
  118. package/public/packages/brick/0.1.11/components/feed.txt +143 -0
  119. package/public/packages/brick/0.1.11/components/field.txt +115 -0
  120. package/public/packages/brick/0.1.11/components/fieldset.txt +103 -0
  121. package/public/packages/brick/0.1.11/components/file-upload.txt +154 -0
  122. package/public/packages/brick/0.1.11/components/form.txt +108 -0
  123. package/public/packages/brick/0.1.11/components/frame.txt +132 -0
  124. package/public/packages/brick/0.1.11/components/grid.txt +141 -0
  125. package/public/packages/brick/0.1.11/components/group.txt +136 -0
  126. package/public/packages/brick/0.1.11/components/hide.txt +121 -0
  127. package/public/packages/brick/0.1.11/components/hover-card.txt +156 -0
  128. package/public/packages/brick/0.1.11/components/icon-button.txt +119 -0
  129. package/public/packages/brick/0.1.11/components/icon.txt +160 -0
  130. package/public/packages/brick/0.1.11/components/image.txt +163 -0
  131. package/public/packages/brick/0.1.11/components/input.txt +101 -0
  132. package/public/packages/brick/0.1.11/components/link-box.txt +161 -0
  133. package/public/packages/brick/0.1.11/components/link.txt +133 -0
  134. package/public/packages/brick/0.1.11/components/list.txt +139 -0
  135. package/public/packages/brick/0.1.11/components/menubar.txt +174 -0
  136. package/public/packages/brick/0.1.11/components/multi-select.txt +153 -0
  137. package/public/packages/brick/0.1.11/components/nav-list.txt +130 -0
  138. package/public/packages/brick/0.1.11/components/navigation-menu.txt +150 -0
  139. package/public/packages/brick/0.1.11/components/notification-badge.txt +148 -0
  140. package/public/packages/brick/0.1.11/components/number-input.txt +150 -0
  141. package/public/packages/brick/0.1.11/components/otp-field.txt +146 -0
  142. package/public/packages/brick/0.1.11/components/pagination.txt +124 -0
  143. package/public/packages/brick/0.1.11/components/password-toggle-field.txt +146 -0
  144. package/public/packages/brick/0.1.11/components/popover.txt +181 -0
  145. package/public/packages/brick/0.1.11/components/progress-circle.txt +142 -0
  146. package/public/packages/brick/0.1.11/components/progress.txt +150 -0
  147. package/public/packages/brick/0.1.11/components/radio-group.txt +152 -0
  148. package/public/packages/brick/0.1.11/components/rating.txt +151 -0
  149. package/public/packages/brick/0.1.11/components/reorderable-list.txt +130 -0
  150. package/public/packages/brick/0.1.11/components/scroll-area.txt +110 -0
  151. package/public/packages/brick/0.1.11/components/section.txt +118 -0
  152. package/public/packages/brick/0.1.11/components/segment-group.txt +116 -0
  153. package/public/packages/brick/0.1.11/components/select.txt +157 -0
  154. package/public/packages/brick/0.1.11/components/show.txt +121 -0
  155. package/public/packages/brick/0.1.11/components/sidebar.txt +126 -0
  156. package/public/packages/brick/0.1.11/components/skeleton.txt +127 -0
  157. package/public/packages/brick/0.1.11/components/skip-link.txt +102 -0
  158. package/public/packages/brick/0.1.11/components/slider.txt +147 -0
  159. package/public/packages/brick/0.1.11/components/stack.txt +155 -0
  160. package/public/packages/brick/0.1.11/components/status.txt +110 -0
  161. package/public/packages/brick/0.1.11/components/surface.txt +194 -0
  162. package/public/packages/brick/0.1.11/components/swipeable-item.txt +154 -0
  163. package/public/packages/brick/0.1.11/components/switch.txt +152 -0
  164. package/public/packages/brick/0.1.11/components/table.txt +183 -0
  165. package/public/packages/brick/0.1.11/components/tabs.txt +136 -0
  166. package/public/packages/brick/0.1.11/components/text.txt +148 -0
  167. package/public/packages/brick/0.1.11/components/textarea.txt +101 -0
  168. package/public/packages/brick/0.1.11/components/toast.txt +150 -0
  169. package/public/packages/brick/0.1.11/components/toggle-group.txt +149 -0
  170. package/public/packages/brick/0.1.11/components/toggle.txt +140 -0
  171. package/public/packages/brick/0.1.11/components/toolbar.txt +118 -0
  172. package/public/packages/brick/0.1.11/components/tooltip.txt +156 -0
  173. package/public/packages/brick/0.1.11/components/tree-grid.txt +160 -0
  174. package/public/packages/brick/0.1.11/components/tree.txt +156 -0
  175. package/public/packages/brick/0.1.11/components/visually-hidden.txt +123 -0
  176. package/public/packages/brick/0.1.11/components/z-stack.txt +143 -0
  177. package/public/packages/brick/0.1.11/docs/guides/agent-knowledge.txt +67 -0
  178. package/public/packages/brick/0.1.11/docs/guides/appearance-and-tokens.txt +179 -0
  179. package/public/packages/brick/0.1.11/docs/guides/browser-support.txt +25 -0
  180. package/public/packages/brick/0.1.11/docs/guides/control-sizing.txt +59 -0
  181. package/public/packages/brick/0.1.11/docs/guides/installation.txt +79 -0
  182. package/public/packages/brick/0.1.11/docs/guides/theme-contract.txt +90 -0
  183. package/public/packages/brick/0.1.11/guides/interface-composition.txt +665 -0
  184. package/public/packages/brick/0.1.11/guides/layer-selection.txt +1437 -0
  185. package/public/packages/brick/0.1.11/index.txt +110 -0
  186. package/public/packages/colors/0.1.1/docs/agent-knowledge.txt +63 -0
  187. package/public/packages/colors/0.1.1/docs/architecture.txt +74 -0
  188. package/public/packages/colors/0.1.1/docs/color-foundations.txt +128 -0
  189. package/public/packages/colors/0.1.1/docs/compatibility.txt +75 -0
  190. package/public/packages/colors/0.1.1/docs/dependency-qualification.txt +117 -0
  191. package/public/packages/colors/0.1.1/docs/installation.txt +48 -0
  192. package/public/packages/colors/0.1.1/docs/palette-generation.txt +151 -0
  193. package/public/packages/colors/0.1.1/docs/releasing.txt +34 -0
  194. package/public/packages/colors/0.1.1/docs/testing.txt +51 -0
  195. package/public/packages/colors/0.1.1/guides/colors-system.txt +282 -0
  196. package/public/packages/colors/0.1.1/index.txt +29 -0
  197. package/public/packages/colors/0.1.1/operations/color-conversion.txt +14 -0
  198. package/public/packages/colors/0.1.1/operations/color-inspection.txt +23 -0
  199. package/public/packages/colors/0.1.1/operations/color-measurement.txt +18 -0
  200. package/public/packages/colors/0.1.1/operations/color-provenance.txt +14 -0
  201. package/public/packages/colors/0.1.1/operations/named-palette-reference.txt +15 -0
  202. package/public/packages/colors/0.1.1/operations/palette-candidate.txt +37 -0
  203. package/public/packages/theme/0.1.1/docs/agent-knowledge.txt +44 -0
  204. package/public/packages/theme/0.1.1/docs/appearances-and-portals.txt +41 -0
  205. package/public/packages/theme/0.1.1/docs/architecture.txt +121 -0
  206. package/public/packages/theme/0.1.1/docs/authoring.txt +141 -0
  207. package/public/packages/theme/0.1.1/docs/colors-interchange.txt +82 -0
  208. package/public/packages/theme/0.1.1/docs/fonts.txt +40 -0
  209. package/public/packages/theme/0.1.1/docs/installation.txt +45 -0
  210. package/public/packages/theme/0.1.1/docs/migration.txt +40 -0
  211. package/public/packages/theme/0.1.1/docs/testing.txt +64 -0
  212. package/public/packages/theme/0.1.1/docs/troubleshooting.txt +53 -0
  213. package/public/packages/theme/0.1.1/guides/theme-system.txt +340 -0
  214. package/public/packages/theme/0.1.1/index.txt +31 -0
  215. package/public/packages/theme/0.1.1/operations/brick-contract-compatibility.txt +35 -0
  216. package/public/packages/theme/0.1.1/operations/colors-interchange.txt +35 -0
  217. package/public/packages/theme/0.1.1/operations/theme-artifacts.txt +19 -0
  218. package/public/packages/theme/0.1.1/operations/theme-cli.txt +10 -0
  219. package/public/packages/theme/0.1.1/operations/theme-compilation.txt +23 -0
  220. package/public/packages/theme/0.1.1/operations/theme-definition.txt +36 -0
  221. package/public/packages/theme/0.1.1/operations/theme-validation.txt +19 -0
  222. package/public/tasks/data.txt +39 -0
  223. package/public/tasks/forms.txt +65 -0
  224. package/public/tasks/layout.txt +37 -0
  225. package/public/tasks/navigation.txt +51 -0
  226. package/public/tasks/overlays.txt +39 -0
  227. package/public/tasks/theming.txt +37 -0
  228. package/skills/flowstack-ui-builder/SKILL.md +35 -0
  229. package/skills/flowstack-ui-builder/agents/openai.yaml +4 -0
  230. package/skills/flowstack-ui-builder/scripts/resolve-agent-knowledge.mjs +399 -0
  231. package/skills/flowstack-ui-compose/SKILL.md +32 -0
  232. package/skills/flowstack-ui-compose/agents/openai.yaml +4 -0
  233. package/skills/flowstack-ui-compose/scripts/resolve-agent-knowledge.mjs +399 -0
  234. package/skills/flowstack-ui-maintainer/SKILL.md +40 -0
  235. package/skills/flowstack-ui-maintainer/agents/openai.yaml +4 -0
  236. package/skills/flowstack-ui-maintainer/scripts/resolve-agent-knowledge.mjs +399 -0
  237. package/skills/flowstack-ui-review/SKILL.md +29 -0
  238. package/skills/flowstack-ui-review/agents/openai.yaml +4 -0
  239. package/skills/flowstack-ui-review/scripts/resolve-agent-knowledge.mjs +399 -0
@@ -0,0 +1,399 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { createHash } from "node:crypto";
4
+ import { access, readFile, realpath, stat } from "node:fs/promises";
5
+ import { createRequire } from "node:module";
6
+ import { dirname, join, relative, resolve, sep } from "node:path";
7
+
8
+ const allowedFlags = new Set(["agent-tools", "archive-sha256", "id", "kind", "package", "project", "version"]);
9
+ const values = new Map();
10
+ for (let index = 2; index < process.argv.length; index += 1) {
11
+ const flag = process.argv[index];
12
+ if (!flag?.startsWith("--")) fail(`invalid argument: ${flag ?? "end of command"}`);
13
+ const key = flag.slice(2);
14
+ if (!allowedFlags.has(key)) fail(`unknown flag: ${flag}`);
15
+ if (values.has(key)) fail(`duplicate flag: ${flag}`);
16
+ const value = process.argv[index + 1];
17
+ if (!value || value.startsWith("--")) fail(`missing value for ${flag}`);
18
+ values.set(key, value);
19
+ index += 1;
20
+ }
21
+
22
+ const project = resolve(values.get("project") ?? process.cwd());
23
+ const packageName = values.get("package");
24
+ const requestedVersion = values.get("version");
25
+ const requestedArchiveSha256 = values.get("archive-sha256");
26
+ const kind = values.get("kind");
27
+ const id = values.get("id");
28
+ if (!packageName) fail("--package is required");
29
+ if (!["@flowstack-ui/atom", "@flowstack-ui/brick", "@flowstack-ui/colors", "@flowstack-ui/theme"].includes(packageName)) fail(`unsupported public Agent Tools package: ${packageName}`);
30
+ if (requestedVersion && !/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/u.test(requestedVersion)) fail("--version must be one exact package version");
31
+ if (requestedArchiveSha256 && !/^[a-f0-9]{64}$/u.test(requestedArchiveSha256)) fail("--archive-sha256 must be one lowercase SHA-256 digest");
32
+ if ((kind && !id) || (!kind && id)) fail("--kind and --id must be supplied together");
33
+ if (kind && !["guide", "component", "operation"].includes(kind)) fail(`unsupported owner kind: ${kind}`);
34
+
35
+ const projectRequire = createRequire(join(project, "package.json"));
36
+ let installedPackagePath;
37
+ let manifestPath;
38
+ try {
39
+ manifestPath = projectRequire.resolve(`${packageName}/agents/manifest.json`);
40
+ } catch {}
41
+ try {
42
+ installedPackagePath = projectRequire.resolve(`${packageName}/package.json`);
43
+ } catch {}
44
+ if (!installedPackagePath && manifestPath) installedPackagePath = await findPackageJson(manifestPath);
45
+ if (!installedPackagePath) {
46
+ try {
47
+ installedPackagePath = await findPackageJson(projectRequire.resolve(packageName));
48
+ } catch {}
49
+ }
50
+
51
+ let installedPackage = null;
52
+ if (installedPackagePath) {
53
+ installedPackage = await readJson(installedPackagePath);
54
+ if (installedPackage.name !== packageName) fail(`installed package identity does not match ${packageName}`);
55
+ if (!requestedArchiveSha256 && requestedVersion && requestedVersion !== installedPackage.version) {
56
+ fail(`installed ${packageName}@${installedPackage.version} does not match requested ${requestedVersion}`);
57
+ }
58
+ if (manifestPath && !requestedArchiveSha256) {
59
+ const result = await resolveInstalled(installedPackage, installedPackagePath, manifestPath);
60
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
61
+ process.exit(0);
62
+ }
63
+ }
64
+
65
+ if (!installedPackage && !requestedVersion) {
66
+ fail(`--version is required when ${packageName} is not exactly installed`);
67
+ }
68
+
69
+ const toolsIndexPath = await findAgentToolsIndex();
70
+ if (toolsIndexPath) {
71
+ const result = await resolveDelivery(toolsIndexPath, installedPackage);
72
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
73
+ process.exit(0);
74
+ }
75
+
76
+ const exactVersion = requestedVersion ?? installedPackage?.version;
77
+ fail(`AGENT_KNOWLEDGE_UNAVAILABLE: no exact installed Agent Knowledge or Agent Tools route for ${packageName}@${exactVersion}`);
78
+
79
+ async function resolveInstalled(packageJson, packageJsonPath, unresolvedManifestPath) {
80
+ const packageRoot = dirname(await realpath(packageJsonPath));
81
+ const manifestPath = await containedFile(packageRoot, unresolvedManifestPath, "installed manifest");
82
+ const manifest = await readJson(manifestPath);
83
+ if (manifest.schema !== "flowstack.agent-manifest.v1") fail(`unsupported Agent Knowledge manifest schema in ${manifestPath}`);
84
+ assertIdentity(manifest, packageJson.name, packageJson.version, "manifest");
85
+ if (typeof manifest.coverage !== "string" || !manifest.coverage) fail("manifest coverage link is missing");
86
+ const coveragePath = await existingArtifact(manifestPath, manifest.coverage, "coverage");
87
+ const coverage = await readJson(coveragePath);
88
+ if (coverage.schema !== "flowstack.agent-coverage.v1") fail(`unsupported Agent Knowledge coverage schema in ${coveragePath}`);
89
+ assertIdentity(coverage, packageJson.name, packageJson.version, "coverage");
90
+ validateInstalledClosure(manifest, coverage);
91
+
92
+ const packageGuides = [];
93
+ for (const entry of manifest.guides) packageGuides.push(await installedGuide(manifest, manifestPath, entry));
94
+
95
+ return {
96
+ schema: "flowstack.agent-skill-resolution.v1",
97
+ source: "installed-package",
98
+ sourceIdentity: { kind: "installed-package", packageJsonPath, archiveSha256: null },
99
+ package: packageJson.name,
100
+ version: packageJson.version,
101
+ manifestPath,
102
+ coveragePath,
103
+ packageGuides,
104
+ selected: kind ? await installedSelection(manifest, coverage, manifestPath, packageGuides) : null,
105
+ };
106
+ }
107
+
108
+ function validateInstalledClosure(manifest, coverage) {
109
+ const summary = coverage.summary;
110
+ if (!summary || typeof summary !== "object") fail("coverage summary is missing");
111
+ requireEqualCount(summary, "publicSurfaces", "classifiedPublicSurfaces");
112
+ for (const key of ["unclassified", "invalidExclusions", "unresolvedSelections"]) requireZero(summary, key);
113
+ for (const [key, value] of Object.entries(summary)) {
114
+ if (/^(?:unclassified|invalid|unresolved)/u.test(key) && value !== 0) fail(`coverage counter ${key} must be zero`);
115
+ }
116
+ if (!Array.isArray(coverage.failures) || coverage.failures.length !== 0) fail(`coverage is not closed for ${coverage.package}@${coverage.packageVersion}`);
117
+
118
+ const guides = exactEntries(manifest.guides, "manifest guides", { nonempty: true });
119
+ const coveredGuides = coveredEntries(coverage.guides, "coverage guides");
120
+ sameIds(guides, coveredGuides, "guide");
121
+ requireCount(summary, "packageGuides", guides.length);
122
+ for (const guide of guides) {
123
+ const covered = coveredGuides.find((entry) => entry.id === guide.id);
124
+ const json = covered.manifestPaths?.json ?? covered.json;
125
+ const markdown = covered.manifestPaths?.markdown ?? covered.markdown;
126
+ if (json !== guide.json || markdown !== guide.markdown) fail(`guide ${guide.id} manifest and coverage artifacts do not match`);
127
+ }
128
+
129
+ const components = exactEntries(manifest.components ?? [], "manifest components");
130
+ const coveredComponents = coveredEntries(coverage.components, "coverage components");
131
+ sameIds(components, coveredComponents, "component");
132
+ requireEqualCount(summary, "componentOwners", "guidedComponentOwners");
133
+ requireCount(summary, "componentOwners", components.length);
134
+ const operations = exactEntries(manifest.operations ?? [], "manifest operations");
135
+ const coveredOperations = coveredEntries(coverage.operations ?? [], "coverage operations");
136
+ sameIds(operations, coveredOperations, "operation");
137
+ const items = exactEntries(manifest.registryItems ?? [], "manifest registry items");
138
+ const coveredItems = coveredEntries(coverage.registryItems ?? [], "coverage registry items");
139
+ sameIds(items, coveredItems, "registry item");
140
+ const owners = coveredEntries(coverage.owners ?? [], "coverage owners");
141
+
142
+ const profile = coverage.profile?.kind ?? ((coverage.layer === "atom" || coverage.layer === "brick") ? "component-package" : null);
143
+ if (profile === "component-package") {
144
+ if (coverage.profile && coverage.profile.ownerUnit !== "component") fail("component-package ownerUnit must be component");
145
+ if (operations.length || items.length || owners.length) fail("component package has non-component owners");
146
+ return;
147
+ }
148
+
149
+ for (const key of ["invalidRegistryItems", "unresolvedDependencies"]) requireZero(summary, key);
150
+ requireEqualCount(summary, "ownerUnits", "guidedOwnerUnits");
151
+ requireCount(summary, "ownerUnits", owners.length);
152
+
153
+ if (profile === "operation-package") {
154
+ if (coverage.profile?.ownerUnit !== "operation") fail("operation-package ownerUnit must be operation");
155
+ if (operations.length === 0) fail("manifest operations must be a nonempty array");
156
+ if (items.length) fail("operation package has registry owners");
157
+ sameIds(operations, owners, "operation owner");
158
+ requireEqualCount(summary, "operationOwners", "guidedOperationOwners");
159
+ requireCount(summary, "operationOwners", operations.length);
160
+ requireCount(summary, "registryItems", 0);
161
+ requireCount(summary, "guidedRegistryItems", 0);
162
+ for (const operation of operations) {
163
+ if (!guides.some((guide) => guide.json === operation.guide)) fail(`operation ${operation.id} has an unresolved guide`);
164
+ }
165
+ return;
166
+ }
167
+
168
+ fail(`unsupported coverage profile: ${profile ?? "missing"}`);
169
+ }
170
+
171
+ async function installedGuide(manifest, manifestPath, entry) {
172
+ const jsonPath = await existingArtifact(manifestPath, entry.json, `guide ${entry.id} JSON`);
173
+ const markdownPath = await existingArtifact(manifestPath, entry.markdown, `guide ${entry.id} Markdown`);
174
+ const machine = await readJson(jsonPath);
175
+ assertMachineArtifact(machine, { schema: "flowstack.agent-guide.v1", id: entry.id, packageName: manifest.package, kind: "guide" });
176
+ return { id: entry.id, json: jsonPath, markdown: markdownPath };
177
+ }
178
+
179
+ async function installedSelection(manifest, coverage, manifestPath, packageGuides) {
180
+ const collection = kind === "guide" ? manifest.guides : kind === "component" ? manifest.components : kind === "operation" ? manifest.operations : manifest.registryItems;
181
+ const matches = (collection ?? []).filter((candidate) => candidate.id === id);
182
+ if (matches.length !== 1) fail(`AGENT_KNOWLEDGE_UNAVAILABLE: ${manifest.package}@${manifest.packageVersion} has no unique ${kind} ${id}`);
183
+ const entry = matches[0];
184
+ if (kind === "guide") {
185
+ const guide = packageGuides.find((candidate) => candidate.id === id);
186
+ return { package: manifest.package, kind, ...guide };
187
+ }
188
+ if (kind === "operation") {
189
+ const guideEntry = manifest.guides.find((candidate) => candidate.json === entry.guide);
190
+ if (!guideEntry) fail(`operation ${id} has an unresolved guide`);
191
+ const guide = packageGuides.find((candidate) => candidate.id === guideEntry.id);
192
+ return { package: manifest.package, kind, id, guideId: guide.id, json: guide.json, markdown: guide.markdown };
193
+ }
194
+ const jsonReference = entry.json ?? entry.agentJson;
195
+ const markdownReference = entry.markdown ?? entry.agentMarkdown;
196
+ const jsonPath = await existingArtifact(manifestPath, jsonReference, `${kind} ${id} JSON`);
197
+ const markdownPath = await existingArtifact(manifestPath, markdownReference, `${kind} ${id} Markdown`);
198
+ const machine = await readJson(jsonPath);
199
+ if (kind === "component") {
200
+ assertMachineArtifact(machine, { schema: "flowstack.agent-component.v1", id, packageName: manifest.package, kind });
201
+ } else if (machine.$schema !== "flowstack.block-agent.v1" || machine.id !== id) {
202
+ fail(`selected block artifact identity does not match ${manifest.package} ${id}`);
203
+ }
204
+ return { package: manifest.package, kind, id, json: jsonPath, markdown: markdownPath };
205
+ }
206
+
207
+ async function resolveDelivery(unresolvedIndexPath, installedPackage) {
208
+ const indexPath = await containedFile(dirname(unresolvedIndexPath), unresolvedIndexPath, "Agent Tools index");
209
+ const index = await readJson(indexPath);
210
+ if (index.schema !== "flowstack.agent-delivery-index.v1") fail(`unsupported Agent Tools index schema in ${indexPath}`);
211
+ const exactVersion = requestedVersion ?? installedPackage?.version;
212
+ if (!exactVersion) fail(`--version is required when ${packageName} is not exactly installed`);
213
+ const records = index.packages.filter((entry) => entry.name === packageName && entry.version === exactVersion);
214
+ if (records.length !== 1) fail(`AGENT_KNOWLEDGE_UNAVAILABLE: Agent Tools has no unique exact route for ${packageName}@${exactVersion}`);
215
+ const record = records[0];
216
+ validateDeliveryRecord(record);
217
+
218
+ const routes = index.routes.filter((route) => route.package === record.id && route.version === record.version);
219
+ const keys = new Set();
220
+ const paths = new Set();
221
+ for (const route of routes) {
222
+ const key = `${route.kind}:${route.id}`;
223
+ if (keys.has(key) || paths.has(route.path)) fail(`Agent Tools has duplicate routes for ${packageName}@${record.version}`);
224
+ keys.add(key);
225
+ paths.add(route.path);
226
+ }
227
+ const expectedCounts = { guide: record.counts.guides, component: record.counts.components, operation: record.counts.operations, package: 1 };
228
+ for (const [routeKind, count] of Object.entries(expectedCounts)) {
229
+ if (routes.filter((route) => route.kind === routeKind).length !== count) fail(`Agent Tools ${routeKind} route count does not match ${packageName}@${record.version}`);
230
+ }
231
+
232
+ const publicRoot = dirname(indexPath);
233
+ const packageRoute = routes.find((route) => route.kind === "package" && route.path === record.route);
234
+ if (!packageRoute) fail(`AGENT_KNOWLEDGE_UNAVAILABLE: Agent Tools package route is missing for ${packageName}@${record.version}`);
235
+ const guideRoutes = routes.filter((route) => route.kind === "guide");
236
+ if (guideRoutes.length === 0) fail(`Agent Tools has no mandatory package guides for ${packageName}@${record.version}`);
237
+ const packageGuides = [];
238
+ for (const route of guideRoutes) packageGuides.push(await deliveryArtifact(publicRoot, route, record));
239
+
240
+ let selected = null;
241
+ if (kind) {
242
+ const matches = routes.filter((candidate) => candidate.kind === kind && candidate.id === id);
243
+ if (matches.length !== 1) fail(`AGENT_KNOWLEDGE_UNAVAILABLE: Agent Tools has no unique ${kind} ${id} for ${packageName}@${record.version}`);
244
+ selected = await deliveryArtifact(publicRoot, matches[0], record);
245
+ }
246
+ return {
247
+ schema: "flowstack.agent-skill-resolution.v1",
248
+ source: "agent-tools-route",
249
+ sourceIdentity: { kind: "locked-archive", archiveSha256: record.archiveSha256 },
250
+ package: packageName,
251
+ version: record.version,
252
+ indexPath,
253
+ packageRoute: await deliveryArtifact(publicRoot, packageRoute, record, { identity: false }),
254
+ packageGuides,
255
+ selected,
256
+ };
257
+ }
258
+
259
+ function validateDeliveryRecord(record) {
260
+ if (!/^[a-f0-9]{64}$/u.test(record.archiveSha256 ?? "")) fail(`Agent Tools archive digest is invalid for ${packageName}@${record.version}`);
261
+ if (requestedArchiveSha256 && record.archiveSha256 !== requestedArchiveSha256) {
262
+ fail(`AGENT_KNOWLEDGE_UNAVAILABLE: archive digest does not match ${packageName}@${record.version}`);
263
+ }
264
+ const coverage = record.coverage;
265
+ if (!coverage || coverage.failures !== 0 || coverage.publicSurfaces !== coverage.classifiedPublicSurfaces) {
266
+ fail(`AGENT_KNOWLEDGE_UNAVAILABLE: Agent Tools coverage is not closed for ${packageName}@${record.version}`);
267
+ }
268
+ if (!record.counts || !Number.isInteger(record.counts.guides) || record.counts.guides <= 0) fail(`Agent Tools guide count is invalid for ${packageName}@${record.version}`);
269
+ for (const key of ["components", "operations"]) if (!Number.isInteger(record.counts[key]) || record.counts[key] < 0) fail(`Agent Tools ${key} count is invalid`);
270
+ const profile = record.profile;
271
+ if (profile?.kind === "component-package" && profile.ownerUnit === "component") {
272
+ if (record.counts.components <= 0 || record.counts.operations !== 0) fail("Agent Tools component profile counts are inconsistent");
273
+ } else if (profile?.kind === "operation-package" && profile.ownerUnit === "operation") {
274
+ if (record.counts.operations <= 0 || record.counts.components !== 0) fail("Agent Tools operation profile counts are inconsistent");
275
+ } else {
276
+ fail(`unsupported Agent Tools coverage profile for ${packageName}@${record.version}`);
277
+ }
278
+ }
279
+
280
+ async function deliveryArtifact(publicRoot, route, record, { identity = true } = {}) {
281
+ const lexicalPath = resolve(publicRoot, route.path.replace(/^\//u, ""));
282
+ const path = await containedFile(publicRoot, lexicalPath, `Agent Tools route ${route.path}`);
283
+ const content = await readFile(path);
284
+ const digest = createHash("sha256").update(content).digest("hex");
285
+ if (!Number.isInteger(route.bytes) || content.length !== route.bytes || !/^[a-f0-9]{64}$/u.test(route.sha256) || digest !== route.sha256) {
286
+ fail(`AGENT_KNOWLEDGE_UNAVAILABLE: Agent Tools route integrity failed for ${route.path}`);
287
+ }
288
+ if (identity) {
289
+ const text = content.toString("utf8");
290
+ if (!text.includes(`\nSource: ${record.name}@${record.version}\n`) || !text.includes(`\nKind: ${route.kind}\n`) || !text.includes(`\nID: ${route.id}\n`)) {
291
+ fail(`Agent Tools route identity does not match ${record.name} ${route.kind} ${route.id}`);
292
+ }
293
+ }
294
+ return { package: record.name, kind: route.kind, id: route.id, route: route.path, path };
295
+ }
296
+
297
+ async function findAgentToolsIndex() {
298
+ const supplied = values.get("agent-tools");
299
+ if (supplied) {
300
+ const target = resolve(supplied);
301
+ const info = await stat(target).catch(() => null);
302
+ if (!info) return null;
303
+ if (!info.isDirectory()) return target;
304
+ for (const candidate of [join(target, "public", "index.json"), join(target, "index.json")]) {
305
+ if (await access(candidate).then(() => true).catch(() => false)) return candidate;
306
+ }
307
+ return null;
308
+ }
309
+ try {
310
+ return projectRequire.resolve("@flowstack-ui/agent-tools/index.json");
311
+ } catch {
312
+ return null;
313
+ }
314
+ }
315
+
316
+ async function existingArtifact(manifestPath, artifact, label) {
317
+ if (typeof artifact !== "string" || !artifact) fail(`${label} path is missing`);
318
+ const base = dirname(manifestPath);
319
+ const path = resolve(base, artifact);
320
+ const relativePath = relative(base, path);
321
+ if (relativePath === ".." || relativePath.startsWith(`..${sep}`)) fail(`escaping manifest artifact: ${artifact}`);
322
+ return containedFile(base, path, label);
323
+ }
324
+
325
+ async function containedFile(root, path, label) {
326
+ const rootPath = await realpath(root);
327
+ const filePath = await realpath(path).catch(() => null);
328
+ if (!filePath) fail(`${label} is missing`);
329
+ const relativePath = relative(rootPath, filePath);
330
+ if (relativePath === ".." || relativePath.startsWith(`..${sep}`)) fail(`${label} escapes its authority root`);
331
+ const info = await stat(filePath);
332
+ if (!info.isFile()) fail(`${label} is not a file`);
333
+ return filePath;
334
+ }
335
+
336
+ function assertMachineArtifact(machine, expected) {
337
+ if (machine.schema !== expected.schema || machine.id !== expected.id || machine.package !== expected.packageName || machine.kind !== expected.kind) {
338
+ fail(`selected artifact identity does not match ${expected.packageName} ${expected.kind} ${expected.id}`);
339
+ }
340
+ }
341
+
342
+ function assertIdentity(value, name, version, label) {
343
+ if (value.package !== name || value.packageVersion !== version) fail(`${label} identity does not match installed ${name}@${version}`);
344
+ }
345
+
346
+ function exactEntries(entries, label, { nonempty = false } = {}) {
347
+ if (!Array.isArray(entries) || (nonempty && entries.length === 0)) fail(`${label} must be ${nonempty ? "a nonempty" : "an"} array`);
348
+ const ids = new Set();
349
+ for (const entry of entries) {
350
+ if (!entry || typeof entry.id !== "string" || !entry.id || ids.has(entry.id)) fail(`${label} has a missing or duplicate id`);
351
+ ids.add(entry.id);
352
+ }
353
+ return entries;
354
+ }
355
+
356
+ function coveredEntries(entries, label) {
357
+ const result = exactEntries(entries, label);
358
+ if (result.some((entry) => entry.status !== "covered")) fail(`${label} contains an uncovered owner`);
359
+ return result;
360
+ }
361
+
362
+ function sameIds(left, right, label) {
363
+ const leftIds = left.map(({ id }) => id).sort();
364
+ const rightIds = right.map(({ id }) => id).sort();
365
+ if (JSON.stringify(leftIds) !== JSON.stringify(rightIds)) fail(`${label} manifest and coverage ids do not match`);
366
+ }
367
+
368
+ function requireCount(summary, key, expected) {
369
+ if (!Number.isInteger(summary[key]) || summary[key] !== expected) fail(`coverage counter ${key} must equal ${expected}`);
370
+ }
371
+
372
+ function requireEqualCount(summary, left, right) {
373
+ if (!Number.isInteger(summary[left]) || !Number.isInteger(summary[right]) || summary[left] !== summary[right]) fail(`coverage counters ${left} and ${right} must match`);
374
+ }
375
+
376
+ function requireZero(summary, key) {
377
+ requireCount(summary, key, 0);
378
+ }
379
+
380
+ async function readJson(path) {
381
+ return JSON.parse(await readFile(path, "utf8"));
382
+ }
383
+
384
+ async function findPackageJson(start) {
385
+ let directory = dirname(start);
386
+ while (true) {
387
+ const candidate = join(directory, "package.json");
388
+ const json = await readJson(candidate).catch(() => null);
389
+ if (json?.name === packageName) return candidate;
390
+ const parent = dirname(directory);
391
+ if (parent === directory) return null;
392
+ directory = parent;
393
+ }
394
+ }
395
+
396
+ function fail(message) {
397
+ process.stderr.write(`${message}\n`);
398
+ process.exit(1);
399
+ }
@@ -0,0 +1,40 @@
1
+ ---
2
+ name: flowstack-ui-maintainer
3
+ description: Coordinate a FLOWSTACK public-package change across authority, exact-version dependencies, Agent Knowledge, qualification, and release readiness. Use for maintaining Atom, Brick, Colors, Theme, or their public delivery adapters; use the builder skill for ordinary application UI work.
4
+ ---
5
+
6
+ # FLOWSTACK UI Maintainer
7
+
8
+ Coordinate public package work without collapsing repository or release boundaries.
9
+
10
+ ## Establish authority and exact evidence
11
+
12
+ Read the workspace and repository instructions that apply to the target. Identify the owner before editing: Atom owns public behavior, Brick finished presentation, Colors reviewed color candidates, Theme compiled semantic artifacts, the private Blocks registry owns paid copy-owned compositions, the public Blocks CLI owns only source-free authenticated delivery, and Agent Tools owns exact-version delivery adapters for public package guidance.
13
+
14
+ Resolve every affected public package and existing public owner with `scripts/resolve-agent-knowledge.mjs`. Pass `--project`, `--package`, and, for a selected owner, `--kind` plus `--id`; pass an exact `--version` whenever the package is not installed. When resolving a staged or locked archive, also pass its recorded `--archive-sha256`; the resolver must return that locked archive identity. Read the resolved zero-failure coverage, package guides, and selected artifacts. Never substitute a sibling checkout, current-main guidance, or a remembered API for an exact dependency boundary. Do not use Agent Tools to resolve private Blocks source, item guidance, bundles, or authenticated responses.
15
+
16
+ A new owner requires two passes. Before editing, resolve the baseline package guides and the closest existing owners rather than pretending the new ID exists. Add the public API and canonical Agent Knowledge, regenerate closed coverage, and pack a uniquely identified candidate. Then resolve the new owner from that candidate before a dependent repository adopts it. Do not let the same package version identify materially different candidates across a dependency handoff; use the repository-approved next or prerelease version, or require the exact archive digest when repository policy prevents an early version change.
17
+
18
+ Before changing an Atom or Brick component, run the owning workspace's task-context preparation when that workflow exists. Treat its output as routing, not authority.
19
+
20
+ ## Plan the dependency slice
21
+
22
+ - Keep one coherent owner change per branch and record its true parent when work is stacked.
23
+ - Put behavior and accessibility prerequisites in Atom before Brick adopts them.
24
+ - Let Brick release before the private Blocks registry makes a released-dependency claim. Blocks may qualify against a uniquely versioned, digest-locked Brick candidate only when both owning repositories explicitly permit that candidate workflow; let the private release pipeline complete before a consumer claims an authenticated CLI installation.
25
+ - Treat Colors as an independently reviewed input and Theme as a compiled compatibility boundary; do not bypass their candidate and contract checks.
26
+ - Update canonical human and machine Agent Knowledge with the owned API. Derived LLM, skill, MCP, website, and archive views follow only after the source package is correct.
27
+
28
+ State the intended versions, archive identities when applicable, and dependency order before a release-sensitive change. A staged archive may qualify the next candidate only when the owning repository explicitly permits that release-candidate workflow; it is not a published dependency and cannot support a production-consumer claim.
29
+
30
+ ## Implement and qualify
31
+
32
+ Make the smallest owner-correct change, preserve public export and CSS entry contracts, and add source, generated, packed, and clean-consumer evidence required by the repository. For components, verify semantics, naming, state, focus, keyboard and pointer behavior, responsive containment, appearance modes, forced colors, reduced motion, and documented customization surfaces in proportion to the change.
33
+
34
+ Regenerate derived artifacts only through repository commands. Review generated diffs for private paths, paid Blocks content, stale versions, uncovered owners, unresolved selections, and unrelated churn. Record Agent Knowledge usefulness only when it changed a decision or prevented a defect.
35
+
36
+ ## Integrate without overreaching
37
+
38
+ Commit and push an owning subrepository before updating its parent revision. Preserve stacked parent relationships and report CI blockers at the repository that owns them. Do not merge, publish, deploy, create trusted-publishing configuration, or install into a personal environment without the user's authorization for that external mutation.
39
+
40
+ At handoff, report commits, branches or pull requests, exact versions, verification results, archive hashes when produced, remaining parent/release gates, and the next dependency owner. Do not call a local candidate publicly available.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "FLOWSTACK UI Maintainer"
3
+ short_description: "Coordinate package and release boundaries"
4
+ default_prompt: "Use $flowstack-ui-maintainer to plan and qualify this cross-package FLOWSTACK change."