@agents-inc/cli 0.74.11 → 0.74.13

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 (128) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +3 -3
  3. package/dist/{chunk-NA6I5P5P.js → chunk-2PZ7LBFT.js} +1 -3
  4. package/dist/chunk-2PZ7LBFT.js.map +1 -0
  5. package/dist/{chunk-VILTRTBT.js → chunk-2YFC7IJ6.js} +4 -4
  6. package/dist/chunk-2YFC7IJ6.js.map +1 -0
  7. package/dist/{chunk-C6YLN4AW.js → chunk-4EPFKZB5.js} +18 -58
  8. package/dist/chunk-4EPFKZB5.js.map +1 -0
  9. package/dist/{chunk-2EXAK22V.js → chunk-6W4H2K3Z.js} +86 -55
  10. package/dist/chunk-6W4H2K3Z.js.map +1 -0
  11. package/dist/{chunk-M5IAGR5Z.js → chunk-746DCNGM.js} +3 -3
  12. package/dist/{chunk-TPXDHJDB.js → chunk-7Q6RMYR3.js} +3 -3
  13. package/dist/chunk-7Q6RMYR3.js.map +1 -0
  14. package/dist/{chunk-VYHRCFMD.js → chunk-7X4F4HCO.js} +16 -23
  15. package/dist/chunk-7X4F4HCO.js.map +1 -0
  16. package/dist/{chunk-YDBVG6RF.js → chunk-A5TTDOP4.js} +11 -21
  17. package/dist/chunk-A5TTDOP4.js.map +1 -0
  18. package/dist/{chunk-54AECXSH.js → chunk-ARGCINJC.js} +2 -2
  19. package/dist/{chunk-OV5UJWS5.js → chunk-CBXMOWQY.js} +2 -2
  20. package/dist/{chunk-PUZLP4SL.js → chunk-EWGFIBBU.js} +2 -2
  21. package/dist/{chunk-X6LXHVA6.js → chunk-GHBZ7NUI.js} +33 -24
  22. package/dist/chunk-GHBZ7NUI.js.map +1 -0
  23. package/dist/chunk-JNQKCZA3.js +28 -0
  24. package/dist/chunk-JNQKCZA3.js.map +1 -0
  25. package/dist/{chunk-NDKIFVR4.js → chunk-JQSJH72Q.js} +18 -9
  26. package/dist/{chunk-NDKIFVR4.js.map → chunk-JQSJH72Q.js.map} +1 -1
  27. package/dist/{chunk-IYA5PSXU.js → chunk-MYSIW4HY.js} +3 -3
  28. package/dist/{chunk-OINQ6OWM.js → chunk-NPMGVQM4.js} +2 -2
  29. package/dist/{chunk-FW5C245M.js → chunk-OZ4DXMRF.js} +27 -30
  30. package/dist/chunk-OZ4DXMRF.js.map +1 -0
  31. package/dist/{chunk-GG4BSB6S.js → chunk-P2FHS5IS.js} +2 -3
  32. package/dist/{chunk-GG4BSB6S.js.map → chunk-P2FHS5IS.js.map} +1 -1
  33. package/dist/{chunk-EWKUUWYY.js → chunk-Q3F36QZZ.js} +2 -2
  34. package/dist/{chunk-PN65K3LH.js → chunk-RKZFLLER.js} +2 -2
  35. package/dist/{chunk-YZUAXX7F.js → chunk-SASGCSBZ.js} +3 -6
  36. package/dist/chunk-SASGCSBZ.js.map +1 -0
  37. package/dist/{chunk-VIVOJASC.js → chunk-TKNPMYKJ.js} +5 -5
  38. package/dist/{chunk-HGTC76BX.js → chunk-V36FRPAU.js} +4 -2
  39. package/dist/chunk-V36FRPAU.js.map +1 -0
  40. package/dist/{chunk-XPRDNALD.js → chunk-W6NWOYMS.js} +2 -2
  41. package/dist/commands/build/plugins.js +2 -2
  42. package/dist/commands/build/stack.js +2 -2
  43. package/dist/commands/compile.js +2 -2
  44. package/dist/commands/config/index.js +2 -2
  45. package/dist/commands/config/path.js +1 -1
  46. package/dist/commands/config/show.js +2 -2
  47. package/dist/commands/diff.js +1 -1
  48. package/dist/commands/doctor.js +1 -1
  49. package/dist/commands/edit.js +24 -29
  50. package/dist/commands/edit.js.map +1 -1
  51. package/dist/commands/eject.js +1 -1
  52. package/dist/commands/import/skill.js +1 -1
  53. package/dist/commands/info.js +1 -1
  54. package/dist/commands/init.js +20 -20
  55. package/dist/commands/list.js +1 -1
  56. package/dist/commands/new/agent.js +2 -2
  57. package/dist/commands/new/marketplace.js +2 -2
  58. package/dist/commands/new/skill.js +2 -2
  59. package/dist/commands/outdated.js +1 -1
  60. package/dist/commands/search.js +1 -1
  61. package/dist/commands/uninstall.js +1 -1
  62. package/dist/commands/update.js +2 -2
  63. package/dist/commands/validate.js +1 -1
  64. package/dist/components/wizard/category-grid.js +2 -2
  65. package/dist/components/wizard/category-grid.test.js +78 -77
  66. package/dist/components/wizard/category-grid.test.js.map +1 -1
  67. package/dist/components/wizard/checkbox-grid.js +2 -2
  68. package/dist/components/wizard/checkbox-grid.test.js +2 -2
  69. package/dist/components/wizard/domain-selection.js +5 -5
  70. package/dist/components/wizard/help-modal.js +1 -1
  71. package/dist/components/wizard/source-grid.js +2 -2
  72. package/dist/components/wizard/source-grid.test.js +5 -5
  73. package/dist/components/wizard/source-grid.test.js.map +1 -1
  74. package/dist/components/wizard/stack-selection.js +3 -3
  75. package/dist/components/wizard/step-agents.js +4 -4
  76. package/dist/components/wizard/step-agents.test.js +5 -5
  77. package/dist/components/wizard/step-agents.test.js.map +1 -1
  78. package/dist/components/wizard/step-build.js +6 -6
  79. package/dist/components/wizard/step-build.test.js +16 -18
  80. package/dist/components/wizard/step-build.test.js.map +1 -1
  81. package/dist/components/wizard/step-confirm.js +2 -2
  82. package/dist/components/wizard/step-confirm.test.js +4 -4
  83. package/dist/components/wizard/step-refine.js +2 -2
  84. package/dist/components/wizard/step-refine.test.js +2 -2
  85. package/dist/components/wizard/step-settings.js +3 -3
  86. package/dist/components/wizard/step-settings.test.js +6 -6
  87. package/dist/components/wizard/step-sources.js +7 -7
  88. package/dist/components/wizard/step-sources.test.js +17 -161
  89. package/dist/components/wizard/step-sources.test.js.map +1 -1
  90. package/dist/components/wizard/step-stack.js +7 -7
  91. package/dist/components/wizard/step-stack.test.js +12 -12
  92. package/dist/components/wizard/step-stack.test.js.map +1 -1
  93. package/dist/components/wizard/view-title.js +1 -2
  94. package/dist/components/wizard/wizard-layout.js +5 -5
  95. package/dist/components/wizard/wizard.js +19 -19
  96. package/dist/hooks/init.js +20 -20
  97. package/dist/{source-loader-WBDPZJEW.js → source-loader-42GVUFZA.js} +2 -4
  98. package/dist/{source-manager-RRGK4SBP.js → source-manager-WRZBOTEH.js} +2 -2
  99. package/dist/stores/wizard-store.js +2 -2
  100. package/dist/stores/wizard-store.test.js +2 -2
  101. package/package.json +1 -1
  102. package/dist/chunk-2EXAK22V.js.map +0 -1
  103. package/dist/chunk-AQYAVLZK.js +0 -20
  104. package/dist/chunk-AQYAVLZK.js.map +0 -1
  105. package/dist/chunk-C6YLN4AW.js.map +0 -1
  106. package/dist/chunk-FW5C245M.js.map +0 -1
  107. package/dist/chunk-HGTC76BX.js.map +0 -1
  108. package/dist/chunk-NA6I5P5P.js.map +0 -1
  109. package/dist/chunk-TPXDHJDB.js.map +0 -1
  110. package/dist/chunk-VILTRTBT.js.map +0 -1
  111. package/dist/chunk-VYHRCFMD.js.map +0 -1
  112. package/dist/chunk-X6LXHVA6.js.map +0 -1
  113. package/dist/chunk-YDBVG6RF.js.map +0 -1
  114. package/dist/chunk-YZUAXX7F.js.map +0 -1
  115. package/dist/plugins/dummy-skill/.claude-plugin/.content-hash +0 -1
  116. package/dist/plugins/dummy-skill/.claude-plugin/plugin.json +0 -13
  117. /package/dist/{chunk-M5IAGR5Z.js.map → chunk-746DCNGM.js.map} +0 -0
  118. /package/dist/{chunk-54AECXSH.js.map → chunk-ARGCINJC.js.map} +0 -0
  119. /package/dist/{chunk-OV5UJWS5.js.map → chunk-CBXMOWQY.js.map} +0 -0
  120. /package/dist/{chunk-PUZLP4SL.js.map → chunk-EWGFIBBU.js.map} +0 -0
  121. /package/dist/{chunk-IYA5PSXU.js.map → chunk-MYSIW4HY.js.map} +0 -0
  122. /package/dist/{chunk-OINQ6OWM.js.map → chunk-NPMGVQM4.js.map} +0 -0
  123. /package/dist/{chunk-EWKUUWYY.js.map → chunk-Q3F36QZZ.js.map} +0 -0
  124. /package/dist/{chunk-PN65K3LH.js.map → chunk-RKZFLLER.js.map} +0 -0
  125. /package/dist/{chunk-VIVOJASC.js.map → chunk-TKNPMYKJ.js.map} +0 -0
  126. /package/dist/{chunk-XPRDNALD.js.map → chunk-W6NWOYMS.js.map} +0 -0
  127. /package/dist/{source-loader-WBDPZJEW.js.map → source-loader-42GVUFZA.js.map} +0 -0
  128. /package/dist/{source-manager-RRGK4SBP.js.map → source-manager-WRZBOTEH.js.map} +0 -0
package/CHANGELOG.md CHANGED
@@ -7,6 +7,30 @@ Each release has detailed notes in its own file under [`changelogs/`](./changelo
7
7
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
8
8
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
9
9
 
10
+ ## [0.74.13] - 2026-03-15
11
+
12
+ **Wizard UI polish, source choice flag, e2e test updates**
13
+
14
+ - Styled view titles, skill scope badges, category headers, and agent step
15
+ - Source choice screen gated behind `SOURCE_CHOICE` flag (off by default)
16
+ - Footer: remove navigate hint, add source hotkeys and agent scope toggle
17
+
18
+ See [changelogs/0.74.13.md](./changelogs/0.74.13.md) for full details.
19
+
20
+ ---
21
+
22
+ ## [0.74.12] - 2026-03-15
23
+
24
+ **Matrix refactor, wizard polish, symlink fix**
25
+
26
+ - Matrix resolver: split `isDiscouraged` into `isDiscouraged`, `isIncompatible`, `hasUnmetRequirements`
27
+ - Wizard: per-skill labels, remove marketplace display, simplify build step
28
+ - Fix macOS `/var` symlink bug in local-installer with `fs.realpathSync`
29
+
30
+ See [changelogs/0.74.12.md](./changelogs/0.74.12.md) for full details.
31
+
32
+ ---
33
+
10
34
  ## [0.74.11] - 2026-03-14
11
35
 
12
36
  **Documentation overhaul — README, standards, .ai-docs**
package/README.md CHANGED
@@ -24,7 +24,7 @@ npx @agents-inc/cli init
24
24
  ```
25
25
 
26
26
  <p align="center">
27
- <img src="screenshots/stack-selection.png" alt="Stack selection" width="700">
27
+ <img src="screenshots/stack-selection.png" alt="Stack selection" width="500">
28
28
  </p>
29
29
 
30
30
  Choose a pre-built stack or start from scratch. Stacks pre-select skills and agents for common tech combinations.
@@ -39,13 +39,13 @@ Choose a pre-built stack or start from scratch. Stacks pre-select skills and age
39
39
  | `solidjs-stack` | SolidJS + Hono + Drizzle |
40
40
 
41
41
  <p align="center">
42
- <img src="screenshots/skill-selection.png" alt="Skill selection" width="700">
42
+ <img src="screenshots/skill-selection.png" alt="Skill selection" width="500">
43
43
  </p>
44
44
 
45
45
  Add or remove skills from the interactive grid. Skills are organized by domain with framework-aware filtering.
46
46
 
47
47
  <p align="center">
48
- <img src="screenshots/agent-selection.png" alt="Agent selection" width="700">
48
+ <img src="screenshots/agent-selection.png" alt="Agent selection" width="500">
49
49
  </p>
50
50
 
51
51
  Choose which subagents to compile. Each agent is composed from the skills you selected.
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- HOTKEY_ACCEPT_DEFAULTS,
4
3
  HOTKEY_HELP,
5
4
  HOTKEY_SCOPE,
6
5
  HOTKEY_SETTINGS,
@@ -41,7 +40,6 @@ var BUILD_KEYS = {
41
40
  keys: [
42
41
  { key: HOTKEY_TOGGLE_LABELS.label, description: "Toggle compatibility labels" },
43
42
  { key: HOTKEY_SCOPE.label, description: "Toggle skill scope (project/global)" },
44
- { key: HOTKEY_ACCEPT_DEFAULTS.label, description: "Accept stack defaults (stack path only)" },
45
43
  { key: KEY_LABEL_VIM, description: "Vim-style navigation" }
46
44
  ]
47
45
  };
@@ -102,4 +100,4 @@ var HelpModal = ({ currentStep }) => {
102
100
  export {
103
101
  HelpModal
104
102
  };
105
- //# sourceMappingURL=chunk-NA6I5P5P.js.map
103
+ //# sourceMappingURL=chunk-2PZ7LBFT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/components/wizard/help-modal.tsx"],"sourcesContent":["import { Box, Text } from \"ink\";\nimport React from \"react\";\nimport { CLI_COLORS } from \"../../consts.js\";\nimport type { WizardStep } from \"../../stores/wizard-store.js\";\nimport {\n HOTKEY_HELP,\n HOTKEY_SCOPE,\n HOTKEY_SETTINGS,\n HOTKEY_TOGGLE_LABELS,\n KEY_LABEL_ENTER,\n KEY_LABEL_ESC,\n KEY_LABEL_SPACE,\n KEY_LABEL_TAB,\n KEY_LABEL_VIM,\n} from \"./hotkeys.js\";\n\ntype HelpSection = {\n title: string;\n keys: { key: string; description: string }[];\n};\n\nconst GLOBAL_KEYS: HelpSection = {\n title: \"Navigation\",\n keys: [\n { key: \"Arrow keys\", description: \"Move focus\" },\n { key: KEY_LABEL_SPACE, description: \"Toggle selection\" },\n { key: KEY_LABEL_ENTER, description: \"Confirm / continue\" },\n { key: KEY_LABEL_ESC, description: \"Go back\" },\n { key: KEY_LABEL_TAB, description: \"Jump to next section\" },\n ],\n};\n\nconst GLOBAL_TOGGLES: HelpSection = {\n title: \"Toggles\",\n keys: [{ key: HOTKEY_HELP.label, description: \"Toggle this help\" }],\n};\n\nconst BUILD_KEYS: HelpSection = {\n title: \"Skills Step\",\n keys: [\n { key: HOTKEY_TOGGLE_LABELS.label, description: \"Toggle compatibility labels\" },\n { key: HOTKEY_SCOPE.label, description: \"Toggle skill scope (project/global)\" },\n { key: KEY_LABEL_VIM, description: \"Vim-style navigation\" },\n ],\n};\n\nconst SOURCES_KEYS: HelpSection = {\n title: \"Sources Step\",\n keys: [{ key: HOTKEY_SETTINGS.label, description: \"Toggle source settings\" }],\n};\n\nconst AGENTS_KEYS: HelpSection = {\n title: \"Agents Step\",\n keys: [{ key: HOTKEY_SCOPE.label, description: \"Toggle agent scope (project/global)\" }],\n};\n\nconst STEP_SECTIONS: Partial<Record<WizardStep, HelpSection>> = {\n build: BUILD_KEYS,\n sources: SOURCES_KEYS,\n agents: AGENTS_KEYS,\n};\n\nconst KEY_COLUMN_WIDTH = 14;\n\ntype HelpSectionViewProps = {\n section: HelpSection;\n};\n\nconst HelpSectionView: React.FC<HelpSectionViewProps> = ({ section }) => (\n <Box flexDirection=\"column\" marginTop={1} marginBottom={1}>\n <Text bold>{section.title}</Text>\n {section.keys.map(({ key, description }) => (\n <Box key={key} marginTop={1}>\n <Box width={KEY_COLUMN_WIDTH}>\n <Text backgroundColor=\"black\" color={CLI_COLORS.UNFOCUSED}>\n {\" \"}\n {key}{\" \"}\n </Text>\n </Box>\n <Text>{description}</Text>\n </Box>\n ))}\n </Box>\n);\n\nexport type HelpModalProps = {\n currentStep: WizardStep;\n};\n\nexport const HelpModal: React.FC<HelpModalProps> = ({ currentStep }) => {\n const stepSection = STEP_SECTIONS[currentStep];\n\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"single\"\n borderColor={CLI_COLORS.PRIMARY}\n paddingX={2}\n paddingY={1}\n marginTop={1}\n >\n <Text bold color={CLI_COLORS.PRIMARY}>\n Keyboard Shortcuts\n </Text>\n <Text> </Text>\n\n <HelpSectionView section={GLOBAL_KEYS} />\n <HelpSectionView section={GLOBAL_TOGGLES} />\n {stepSection && <HelpSectionView section={stepSection} />}\n\n <Text dimColor>\n Press {KEY_LABEL_ESC} or {HOTKEY_HELP.label} to close\n </Text>\n </Box>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA,SAAS,KAAK,YAAY;AAsEtB,cAIM,YAJN;AAjDJ,IAAM,cAA2B;AAAA,EAC/B,OAAO;AAAA,EACP,MAAM;AAAA,IACJ,EAAE,KAAK,cAAc,aAAa,aAAa;AAAA,IAC/C,EAAE,KAAK,iBAAiB,aAAa,mBAAmB;AAAA,IACxD,EAAE,KAAK,iBAAiB,aAAa,qBAAqB;AAAA,IAC1D,EAAE,KAAK,eAAe,aAAa,UAAU;AAAA,IAC7C,EAAE,KAAK,eAAe,aAAa,uBAAuB;AAAA,EAC5D;AACF;AAEA,IAAM,iBAA8B;AAAA,EAClC,OAAO;AAAA,EACP,MAAM,CAAC,EAAE,KAAK,YAAY,OAAO,aAAa,mBAAmB,CAAC;AACpE;AAEA,IAAM,aAA0B;AAAA,EAC9B,OAAO;AAAA,EACP,MAAM;AAAA,IACJ,EAAE,KAAK,qBAAqB,OAAO,aAAa,8BAA8B;AAAA,IAC9E,EAAE,KAAK,aAAa,OAAO,aAAa,sCAAsC;AAAA,IAC9E,EAAE,KAAK,eAAe,aAAa,uBAAuB;AAAA,EAC5D;AACF;AAEA,IAAM,eAA4B;AAAA,EAChC,OAAO;AAAA,EACP,MAAM,CAAC,EAAE,KAAK,gBAAgB,OAAO,aAAa,yBAAyB,CAAC;AAC9E;AAEA,IAAM,cAA2B;AAAA,EAC/B,OAAO;AAAA,EACP,MAAM,CAAC,EAAE,KAAK,aAAa,OAAO,aAAa,sCAAsC,CAAC;AACxF;AAEA,IAAM,gBAA0D;AAAA,EAC9D,OAAO;AAAA,EACP,SAAS;AAAA,EACT,QAAQ;AACV;AAEA,IAAM,mBAAmB;AAMzB,IAAM,kBAAkD,CAAC,EAAE,QAAQ,MACjE,qBAAC,OAAI,eAAc,UAAS,WAAW,GAAG,cAAc,GACtD;AAAA,sBAAC,QAAK,MAAI,MAAE,kBAAQ,OAAM;AAAA,EACzB,QAAQ,KAAK,IAAI,CAAC,EAAE,KAAK,YAAY,MACpC,qBAAC,OAAc,WAAW,GACxB;AAAA,wBAAC,OAAI,OAAO,kBACV,+BAAC,QAAK,iBAAgB,SAAQ,OAAO,WAAW,WAC7C;AAAA;AAAA,MACA;AAAA,MAAK;AAAA,OACR,GACF;AAAA,IACA,oBAAC,QAAM,uBAAY;AAAA,OAPX,GAQV,CACD;AAAA,GACH;AAOK,IAAM,YAAsC,CAAC,EAAE,YAAY,MAAM;AACtE,QAAM,cAAc,cAAc,WAAW;AAE7C,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAc;AAAA,MACd,aAAY;AAAA,MACZ,aAAa,WAAW;AAAA,MACxB,UAAU;AAAA,MACV,UAAU;AAAA,MACV,WAAW;AAAA,MAEX;AAAA,4BAAC,QAAK,MAAI,MAAC,OAAO,WAAW,SAAS,gCAEtC;AAAA,QACA,oBAAC,QAAK,eAAC;AAAA,QAEP,oBAAC,mBAAgB,SAAS,aAAa;AAAA,QACvC,oBAAC,mBAAgB,SAAS,gBAAgB;AAAA,QACzC,eAAe,oBAAC,mBAAgB,SAAS,aAAa;AAAA,QAEvD,qBAAC,QAAK,UAAQ,MAAC;AAAA;AAAA,UACN;AAAA,UAAc;AAAA,UAAK,YAAY;AAAA,UAAM;AAAA,WAC9C;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-AUNBGZS4.js";
8
8
  import {
9
9
  useWizardStore
10
- } from "./chunk-PUZLP4SL.js";
10
+ } from "./chunk-EWGFIBBU.js";
11
11
  import {
12
12
  matrix
13
13
  } from "./chunk-NG2GGK6P.js";
@@ -68,11 +68,11 @@ var StackSelection = ({
68
68
  return;
69
69
  }
70
70
  if (key.upArrow || input === "k") {
71
- setFocusedIndex((prev) => Math.max(0, prev - 1));
71
+ setFocusedIndex((prev) => prev <= 0 ? totalItems - 1 : prev - 1);
72
72
  return;
73
73
  }
74
74
  if (key.downArrow || input === "j") {
75
- setFocusedIndex((prev) => Math.min(totalItems - 1, prev + 1));
75
+ setFocusedIndex((prev) => prev >= totalItems - 1 ? 0 : prev + 1);
76
76
  }
77
77
  });
78
78
  const noShrink = scrollEnabled ? { flexShrink: 0 } : {};
@@ -110,4 +110,4 @@ var StackSelection = ({
110
110
  export {
111
111
  StackSelection
112
112
  };
113
- //# sourceMappingURL=chunk-VILTRTBT.js.map
113
+ //# sourceMappingURL=chunk-2YFC7IJ6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/components/wizard/stack-selection.tsx"],"sourcesContent":["import { Box, useInput } from \"ink\";\nimport React, { useState } from \"react\";\nimport { DEFAULT_SCRATCH_DOMAINS } from \"../../consts.js\";\nimport { useWizardStore } from \"../../stores/wizard-store.js\";\nimport { matrix } from \"../../lib/matrix/matrix-provider.js\";\nimport { useSectionScroll } from \"../hooks/use-section-scroll.js\";\nimport { SelectionCard } from \"./selection-card.js\";\n\nconst INITIAL_FOCUSED_INDEX = 0;\nconst SCRATCH_LABEL = \"Start from scratch\";\nconst SCRATCH_DESCRIPTION = \"Select domains and skills manually\";\n\n/** Number of extra items after the stack list (scratch option) */\nconst EXTRA_ITEMS_COUNT = 1;\n\nexport type StackSelectionProps = {\n /** Available height in terminal lines for the scrollable viewport. 0 = no constraint. */\n availableHeight?: number;\n onCancel?: () => void;\n};\n\nexport const StackSelection: React.FC<StackSelectionProps> = ({\n availableHeight = 0,\n onCancel,\n}) => {\n const { selectStack, setApproach, setStackAction, populateFromSkillIds, toggleDomain } =\n useWizardStore();\n\n const [focusedIndex, setFocusedIndex] = useState(INITIAL_FOCUSED_INDEX);\n\n const stacks = matrix.suggestedStacks;\n const stackCount = stacks.length;\n const scratchIndex = stackCount;\n const totalItems = stackCount + EXTRA_ITEMS_COUNT;\n\n const { setSectionRef, scrollEnabled, scrollTopPx } = useSectionScroll({\n sectionCount: totalItems,\n focusedIndex,\n availableHeight,\n });\n\n useInput((input, key) => {\n if (key.escape) {\n if (onCancel) {\n onCancel();\n }\n return;\n }\n\n if (key.return) {\n if (focusedIndex === scratchIndex) {\n selectStack(null);\n setApproach(\"scratch\");\n\n for (const domain of DEFAULT_SCRATCH_DOMAINS) {\n toggleDomain(domain);\n }\n return;\n }\n\n const focusedStack = stacks[focusedIndex];\n if (focusedStack) {\n selectStack(focusedStack.id);\n setStackAction(\"customize\");\n populateFromSkillIds(focusedStack.allSkillIds);\n setApproach(\"stack\");\n }\n return;\n }\n\n if (key.upArrow || input === \"k\") {\n setFocusedIndex((prev) => (prev <= 0 ? totalItems - 1 : prev - 1));\n return;\n }\n if (key.downArrow || input === \"j\") {\n setFocusedIndex((prev) => (prev >= totalItems - 1 ? 0 : prev + 1));\n }\n });\n\n const noShrink = scrollEnabled ? { flexShrink: 0 } : {};\n\n const sectionElements = stacks.map((stack, index) => (\n <Box key={stack.id} ref={(el) => setSectionRef(index, el)} width=\"100%\" {...noShrink}>\n <SelectionCard\n label={stack.name}\n description={stack.description}\n isFocused={index === focusedIndex}\n marginBottom={1}\n />\n </Box>\n ));\n\n const scratchElement = (\n <Box ref={(el) => setSectionRef(scratchIndex, el)} width=\"100%\" {...noShrink}>\n <SelectionCard\n label={SCRATCH_LABEL}\n description={SCRATCH_DESCRIPTION}\n isFocused={focusedIndex === scratchIndex}\n />\n </Box>\n );\n\n return (\n <Box\n flexDirection=\"column\"\n width=\"100%\"\n {...(scrollEnabled\n ? { height: availableHeight, overflow: \"hidden\" as const }\n : { flexGrow: 1 })}\n >\n <Box flexDirection=\"column\" marginTop={scrollTopPx > 0 ? -scrollTopPx : 0} {...noShrink}>\n {sectionElements}\n {scratchElement}\n </Box>\n </Box>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA,SAAS,KAAK,gBAAgB;AAC9B,SAAgB,gBAAgB;AAkF1B,cA2BA,YA3BA;AA3EN,IAAM,wBAAwB;AAC9B,IAAM,gBAAgB;AACtB,IAAM,sBAAsB;AAG5B,IAAM,oBAAoB;AAQnB,IAAM,iBAAgD,CAAC;AAAA,EAC5D,kBAAkB;AAAA,EAClB;AACF,MAAM;AACJ,QAAM,EAAE,aAAa,aAAa,gBAAgB,sBAAsB,aAAa,IACnF,eAAe;AAEjB,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,qBAAqB;AAEtE,QAAM,SAAS,OAAO;AACtB,QAAM,aAAa,OAAO;AAC1B,QAAM,eAAe;AACrB,QAAM,aAAa,aAAa;AAEhC,QAAM,EAAE,eAAe,eAAe,YAAY,IAAI,iBAAiB;AAAA,IACrE,cAAc;AAAA,IACd;AAAA,IACA;AAAA,EACF,CAAC;AAED,WAAS,CAAC,OAAO,QAAQ;AACvB,QAAI,IAAI,QAAQ;AACd,UAAI,UAAU;AACZ,iBAAS;AAAA,MACX;AACA;AAAA,IACF;AAEA,QAAI,IAAI,QAAQ;AACd,UAAI,iBAAiB,cAAc;AACjC,oBAAY,IAAI;AAChB,oBAAY,SAAS;AAErB,mBAAW,UAAU,yBAAyB;AAC5C,uBAAa,MAAM;AAAA,QACrB;AACA;AAAA,MACF;AAEA,YAAM,eAAe,OAAO,YAAY;AACxC,UAAI,cAAc;AAChB,oBAAY,aAAa,EAAE;AAC3B,uBAAe,WAAW;AAC1B,6BAAqB,aAAa,WAAW;AAC7C,oBAAY,OAAO;AAAA,MACrB;AACA;AAAA,IACF;AAEA,QAAI,IAAI,WAAW,UAAU,KAAK;AAChC,sBAAgB,CAAC,SAAU,QAAQ,IAAI,aAAa,IAAI,OAAO,CAAE;AACjE;AAAA,IACF;AACA,QAAI,IAAI,aAAa,UAAU,KAAK;AAClC,sBAAgB,CAAC,SAAU,QAAQ,aAAa,IAAI,IAAI,OAAO,CAAE;AAAA,IACnE;AAAA,EACF,CAAC;AAED,QAAM,WAAW,gBAAgB,EAAE,YAAY,EAAE,IAAI,CAAC;AAEtD,QAAM,kBAAkB,OAAO,IAAI,CAAC,OAAO,UACzC,oBAAC,OAAmB,KAAK,CAAC,OAAO,cAAc,OAAO,EAAE,GAAG,OAAM,QAAQ,GAAG,UAC1E;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,MAAM;AAAA,MACb,aAAa,MAAM;AAAA,MACnB,WAAW,UAAU;AAAA,MACrB,cAAc;AAAA;AAAA,EAChB,KANQ,MAAM,EAOhB,CACD;AAED,QAAM,iBACJ,oBAAC,OAAI,KAAK,CAAC,OAAO,cAAc,cAAc,EAAE,GAAG,OAAM,QAAQ,GAAG,UAClE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,MACP,aAAa;AAAA,MACb,WAAW,iBAAiB;AAAA;AAAA,EAC9B,GACF;AAGF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAc;AAAA,MACd,OAAM;AAAA,MACL,GAAI,gBACD,EAAE,QAAQ,iBAAiB,UAAU,SAAkB,IACvD,EAAE,UAAU,EAAE;AAAA,MAElB,+BAAC,OAAI,eAAc,UAAS,WAAW,cAAc,IAAI,CAAC,cAAc,GAAI,GAAG,UAC5E;AAAA;AAAA,QACA;AAAA,SACH;AAAA;AAAA,EACF;AAEJ;","names":[]}
@@ -4,25 +4,21 @@ import {
4
4
  } from "./chunk-K77I4XGL.js";
5
5
  import {
6
6
  CategoryGrid
7
- } from "./chunk-X6LXHVA6.js";
7
+ } from "./chunk-GHBZ7NUI.js";
8
8
  import {
9
9
  getDomainDisplayName,
10
10
  orderDomains
11
11
  } from "./chunk-LVNNP7T4.js";
12
12
  import {
13
13
  ViewTitle
14
- } from "./chunk-AQYAVLZK.js";
14
+ } from "./chunk-JNQKCZA3.js";
15
15
  import {
16
16
  useWizardStore
17
- } from "./chunk-PUZLP4SL.js";
18
- import {
19
- KEY_LABEL_ENTER,
20
- KEY_LABEL_ESC
21
- } from "./chunk-CBYRFAUN.js";
17
+ } from "./chunk-EWGFIBBU.js";
22
18
  import {
23
19
  getAvailableSkills,
24
20
  resolveAlias
25
- } from "./chunk-2EXAK22V.js";
21
+ } from "./chunk-6W4H2K3Z.js";
26
22
  import {
27
23
  getSkillById,
28
24
  matrix
@@ -37,7 +33,11 @@ import {
37
33
  // src/cli/components/wizard/step-build.tsx
38
34
  init_esm_shims();
39
35
  import { Box, Text, useInput } from "ink";
40
- import { useCallback, useMemo as useMemo2, useState } from "react";
36
+ import { useCallback, useMemo as useMemo2 } from "react";
37
+
38
+ // src/cli/components/hooks/use-framework-filtering.ts
39
+ init_esm_shims();
40
+ import { useMemo } from "react";
41
41
 
42
42
  // src/cli/lib/wizard/index.ts
43
43
  init_esm_shims();
@@ -53,32 +53,14 @@ function validateBuildStep(categories, selections) {
53
53
  const categorySelections = selections[category.id] || [];
54
54
  if (categorySelections.length === 0) {
55
55
  return {
56
- valid: false,
57
- message: `Select at least one skill from the ${category.displayName} category. Use arrow keys to navigate, then SPACE to select.`
56
+ valid: true,
57
+ message: `No skills selected in ${category.displayName} (required category)`
58
58
  };
59
59
  }
60
60
  }
61
61
  }
62
62
  return { valid: true };
63
63
  }
64
- function computeOptionState(skill) {
65
- if (skill.discouraged) {
66
- return "discouraged";
67
- }
68
- if (skill.recommended) {
69
- return "recommended";
70
- }
71
- return "normal";
72
- }
73
- function getStateReason(skill) {
74
- if (skill.discouraged && skill.discouragedReason) {
75
- return skill.discouragedReason;
76
- }
77
- if (skill.recommended && skill.recommendedReason) {
78
- return skill.recommendedReason;
79
- }
80
- return void 0;
81
- }
82
64
  function isFrameworkSelected(selections) {
83
65
  const frameworkSelections = selections[FRAMEWORK_CATEGORY_ID] ?? [];
84
66
  return frameworkSelections.length > 0;
@@ -112,12 +94,13 @@ function buildCategoriesForDomain(domain, allSelections, selections, installedSk
112
94
  ) : skillOptions;
113
95
  const options = filteredSkillOptions.map((skill) => ({
114
96
  id: skill.id,
115
- state: computeOptionState(skill),
116
- stateReason: getStateReason(skill),
97
+ state: skill.advisoryState,
117
98
  selected: skill.selected,
118
99
  local: getSkillById(skill.id).local,
119
100
  installed: installedSkillIds?.includes(skill.id) || false,
120
- scope: skillConfigs?.find((sc) => sc.id === skill.id)?.scope
101
+ scope: skillConfigs?.find((sc) => sc.id === skill.id)?.scope,
102
+ hasUnmetRequirements: skill.hasUnmetRequirements,
103
+ unmetRequirementsReason: skill.unmetRequirementsReason
121
104
  }));
122
105
  return {
123
106
  id: cat.id,
@@ -131,8 +114,6 @@ function buildCategoriesForDomain(domain, allSelections, selections, installedSk
131
114
  }
132
115
 
133
116
  // src/cli/components/hooks/use-framework-filtering.ts
134
- init_esm_shims();
135
- import { useMemo } from "react";
136
117
  function useFrameworkFiltering({
137
118
  domain,
138
119
  allSelections,
@@ -148,18 +129,6 @@ function useFrameworkFiltering({
148
129
 
149
130
  // src/cli/components/wizard/step-build.tsx
150
131
  import { jsx, jsxs } from "react/jsx-runtime";
151
- var Footer = ({ validationError }) => {
152
- return /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 1, children: validationError && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
153
- /* @__PURE__ */ jsx(Text, { color: CLI_COLORS.WARNING, children: validationError }),
154
- /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
155
- "Press ",
156
- KEY_LABEL_ESC,
157
- " to go back, or select a skill and press ",
158
- KEY_LABEL_ENTER,
159
- " to continue."
160
- ] })
161
- ] }) });
162
- };
163
132
  var StepBuild = ({
164
133
  domain: activeDomain,
165
134
  selectedDomains,
@@ -172,7 +141,6 @@ var StepBuild = ({
172
141
  onContinue,
173
142
  onBack
174
143
  }) => {
175
- const [validationError, setValidationError] = useState(void 0);
176
144
  const { ref: gridRef, measuredHeight: gridHeight } = useMeasuredHeight();
177
145
  const skillConfigs = useWizardStore((s) => s.skillConfigs);
178
146
  const handleFocusedSkillChange = useCallback(
@@ -189,15 +157,8 @@ var StepBuild = ({
189
157
  });
190
158
  useInput((_input, key) => {
191
159
  if (key.return) {
192
- const validation = validateBuildStep(categories, selections);
193
- if (validation.valid) {
194
- setValidationError(void 0);
195
- onContinue();
196
- } else {
197
- setValidationError(validation.message);
198
- }
160
+ onContinue();
199
161
  } else if (key.escape) {
200
- setValidationError(void 0);
201
162
  onBack();
202
163
  }
203
164
  });
@@ -234,8 +195,7 @@ var StepBuild = ({
234
195
  onFocusedSkillChange: handleFocusedSkillChange
235
196
  },
236
197
  activeDomain
237
- ) }),
238
- /* @__PURE__ */ jsx(Footer, { validationError })
198
+ ) })
239
199
  ] });
240
200
  };
241
201
 
@@ -243,4 +203,4 @@ export {
243
203
  validateBuildStep,
244
204
  StepBuild
245
205
  };
246
- //# sourceMappingURL=chunk-C6YLN4AW.js.map
206
+ //# sourceMappingURL=chunk-4EPFKZB5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/components/wizard/step-build.tsx","../src/cli/components/hooks/use-framework-filtering.ts","../src/cli/lib/wizard/index.ts","../src/cli/lib/wizard/build-step-logic.ts"],"sourcesContent":["import { Box, Text, useInput } from \"ink\";\nimport React, { useCallback, useMemo } from \"react\";\nimport { CLI_COLORS } from \"../../consts.js\";\nimport type { Domain, SkillId, Category, CategorySelections } from \"../../types/index.js\";\nimport { useFrameworkFiltering } from \"../hooks/use-framework-filtering.js\";\nimport { useMeasuredHeight } from \"../hooks/use-measured-height.js\";\nimport { useWizardStore } from \"../../stores/wizard-store.js\";\nimport { CategoryGrid } from \"./category-grid.js\";\nimport { getDomainDisplayName, orderDomains } from \"./utils.js\";\nimport { ViewTitle } from \"./view-title.js\";\n\nexport type StepBuildProps = {\n domain: Domain;\n selectedDomains: Domain[];\n selections: CategorySelections;\n allSelections: SkillId[];\n showLabels: boolean;\n /** Skill IDs already installed on disk, shown with a dimmed checkmark */\n installedSkillIds?: SkillId[];\n onToggle: (categoryId: Category, technologyId: SkillId) => void;\n onToggleLabels: () => void;\n onContinue: () => void;\n onBack: () => void;\n};\n\nexport const StepBuild: React.FC<StepBuildProps> = ({\n domain: activeDomain,\n selectedDomains,\n selections,\n allSelections,\n showLabels,\n installedSkillIds,\n onToggle,\n onToggleLabels,\n onContinue,\n onBack,\n}) => {\n const { ref: gridRef, measuredHeight: gridHeight } = useMeasuredHeight();\n const skillConfigs = useWizardStore((s) => s.skillConfigs);\n\n const handleFocusedSkillChange = useCallback(\n (id: SkillId | null) => useWizardStore.getState().setFocusedSkillId(id),\n [],\n );\n\n const orderedDomains = useMemo(() => orderDomains(selectedDomains), [selectedDomains]);\n\n const categories = useFrameworkFiltering({\n domain: activeDomain,\n allSelections,\n selections,\n installedSkillIds,\n skillConfigs,\n });\n\n useInput((_input, key) => {\n if (key.return) {\n onContinue();\n } else if (key.escape) {\n onBack();\n }\n });\n\n return (\n <Box flexDirection=\"column\" width=\"100%\" flexGrow={1} flexBasis={0}>\n <Box\n columnGap={2}\n flexDirection=\"row\"\n justifyContent=\"space-between\"\n marginBottom={1}\n paddingRight={1}\n marginTop={-1}\n borderTop={false}\n borderRight={false}\n borderLeft={false}\n borderColor={CLI_COLORS.NEUTRAL}\n borderStyle=\"single\"\n >\n <Box columnGap={2} flexDirection=\"row\">\n {orderedDomains.map((domain) => {\n const isActive = domain === activeDomain;\n return (\n <Text key={domain} color={isActive ? CLI_COLORS.WARNING : undefined} bold={isActive}>\n {getDomainDisplayName(domain)}\n </Text>\n );\n })}\n </Box>\n </Box>\n <ViewTitle>{`Customize your ${getDomainDisplayName(activeDomain)} stack`}</ViewTitle>\n\n <Box ref={gridRef} flexGrow={1} flexBasis={0}>\n <CategoryGrid\n key={activeDomain}\n categories={categories}\n availableHeight={gridHeight}\n showLabels={showLabels}\n onToggle={onToggle}\n onToggleLabels={onToggleLabels}\n onFocusedSkillChange={handleFocusedSkillChange}\n />\n </Box>\n </Box>\n );\n};\n","import { useMemo } from \"react\";\nimport type { Domain, SkillId, CategorySelections } from \"../../types/index.js\";\nimport type { SkillConfig } from \"../../types/config.js\";\nimport { buildCategoriesForDomain } from \"../../lib/wizard/index.js\";\nimport type { CategoryRow } from \"../wizard/category-grid.js\";\n\ntype UseFrameworkFilteringOptions = {\n domain: Domain;\n allSelections: SkillId[];\n selections: CategorySelections;\n installedSkillIds?: SkillId[];\n skillConfigs?: SkillConfig[];\n};\n\nexport function useFrameworkFiltering({\n domain,\n allSelections,\n selections,\n installedSkillIds,\n skillConfigs,\n}: UseFrameworkFilteringOptions): CategoryRow[] {\n return useMemo(\n () =>\n buildCategoriesForDomain(domain, allSelections, selections, installedSkillIds, skillConfigs),\n [domain, allSelections, selections, installedSkillIds, skillConfigs],\n );\n}\n","export {\n type BuildStepValidation,\n validateBuildStep,\n buildCategoriesForDomain,\n} from \"./build-step-logic\";\n","import { sortBy } from \"remeda\";\nimport type { CategoryDefinition, Domain, SkillId, CategorySelections } from \"../../types/index.js\";\nimport type { SkillConfig } from \"../../types/config.js\";\nimport { getAvailableSkills, resolveAlias } from \"../matrix/index.js\";\nimport { matrix, getSkillById } from \"../matrix/matrix-provider.js\";\nimport type { CategoryRow, CategoryOption } from \"../../components/wizard/category-grid.js\";\n\nconst FRAMEWORK_CATEGORY_ID = \"web-framework\";\nconst WEB_DOMAIN_ID = \"web\";\n\nexport type BuildStepValidation = {\n valid: boolean;\n message?: string;\n};\n\nexport function validateBuildStep(\n categories: CategoryRow[],\n selections: CategorySelections,\n): BuildStepValidation {\n for (const category of categories) {\n if (category.required) {\n const categorySelections = selections[category.id] || [];\n if (categorySelections.length === 0) {\n return {\n valid: true,\n message: `No skills selected in ${category.displayName} (required category)`,\n };\n }\n }\n }\n return { valid: true };\n}\n\nfunction isFrameworkSelected(selections: CategorySelections): boolean {\n const frameworkSelections = selections[FRAMEWORK_CATEGORY_ID] ?? [];\n return frameworkSelections.length > 0;\n}\n\nfunction getSelectedFrameworks(selections: CategorySelections): SkillId[] {\n const frameworkSelections = selections[FRAMEWORK_CATEGORY_ID] ?? [];\n return frameworkSelections.map((alias) => resolveAlias(alias));\n}\n\nfunction isCompatibleWithSelectedFrameworks(\n skillId: SkillId,\n selectedFrameworkIds: SkillId[],\n): boolean {\n const skill = getSkillById(skillId);\n\n // No compatibleWith = compatible with all (allows legacy skills to appear)\n if (skill.compatibleWith.length === 0) {\n return true;\n }\n\n return selectedFrameworkIds.some((frameworkId) => skill.compatibleWith.includes(frameworkId));\n}\n\n// Build CategoryRow[] from matrix for a domain, with framework-first filtering for web\nexport function buildCategoriesForDomain(\n domain: Domain,\n allSelections: SkillId[],\n selections: CategorySelections,\n installedSkillIds?: SkillId[],\n skillConfigs?: SkillConfig[],\n): CategoryRow[] {\n const frameworkSource = selections;\n const frameworkSelected = isFrameworkSelected(frameworkSource);\n const selectedFrameworkIds = frameworkSelected ? getSelectedFrameworks(frameworkSource) : [];\n\n // Object.values() on a Partial record only yields values that exist — all are CategoryDefinition\n const categories = sortBy(\n (Object.values(matrix.categories) as CategoryDefinition[]).filter(\n (cat) => cat.domain === domain,\n ),\n (cat) => cat.order ?? 0,\n );\n\n const categoryRows: CategoryRow[] = categories.map((cat) => {\n const skillOptions = getAvailableSkills(cat.id, allSelections);\n\n const useFrameworkFilter =\n domain === WEB_DOMAIN_ID && cat.id !== FRAMEWORK_CATEGORY_ID && frameworkSelected;\n const filteredSkillOptions = useFrameworkFilter\n ? skillOptions.filter((skill) =>\n isCompatibleWithSelectedFrameworks(skill.id, selectedFrameworkIds),\n )\n : skillOptions;\n\n const options: CategoryOption[] = filteredSkillOptions.map((skill) => ({\n id: skill.id,\n state: skill.advisoryState,\n selected: skill.selected,\n local: getSkillById(skill.id).local,\n installed: installedSkillIds?.includes(skill.id) || false,\n scope: skillConfigs?.find((sc) => sc.id === skill.id)?.scope,\n hasUnmetRequirements: skill.hasUnmetRequirements,\n unmetRequirementsReason: skill.unmetRequirementsReason,\n }));\n\n return {\n id: cat.id,\n displayName: cat.displayName,\n required: cat.required ?? false,\n exclusive: cat.exclusive ?? true,\n options,\n };\n });\n\n return categoryRows.filter((row) => row.options.length > 0);\n}\n"],"mappings":"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","names":["useMemo","useMemo"]}
@@ -984,7 +984,7 @@ function loadConfigTypesDataInBackground(sourceFlag, projectDir) {
984
984
  if (!await directoryExists(claudeSrcDir)) {
985
985
  throw new Error(`${CLAUDE_SRC_DIR}/ not found \u2014 run '${CLI_BIN_NAME} init' first`);
986
986
  }
987
- const { loadSkillsMatrixFromSource: loadSkillsMatrixFromSource2 } = await import("./source-loader-WBDPZJEW.js");
987
+ const { loadSkillsMatrixFromSource: loadSkillsMatrixFromSource2 } = await import("./source-loader-42GVUFZA.js");
988
988
  const { loadAllAgents: loadAllAgents2 } = await import("./loader-NHUCFMFQ.js");
989
989
  const sourceResult = await loadSkillsMatrixFromSource2({
990
990
  sourceFlag,
@@ -1930,6 +1930,16 @@ import { groupBy } from "remeda";
1930
1930
  function getLabel(skill) {
1931
1931
  return skill.displayName;
1932
1932
  }
1933
+ function joinWithOr(items) {
1934
+ if (items.length <= 1) return items[0] ?? "";
1935
+ if (items.length === 2) return `${items[0]} or ${items[1]}`;
1936
+ return `${items.slice(0, -1).join(", ")} or ${items[items.length - 1]}`;
1937
+ }
1938
+ function joinWithAnd(items) {
1939
+ if (items.length <= 1) return items[0] ?? "";
1940
+ if (items.length === 2) return `${items[0]} and ${items[1]}`;
1941
+ return `${items.slice(0, -1).join(", ")} and ${items[items.length - 1]}`;
1942
+ }
1933
1943
  function resolveAlias(skillId) {
1934
1944
  if (matrix.skills[skillId]) return skillId;
1935
1945
  throw new Error(`Unknown skill ID: '${skillId}' \u2014 not found in the matrix`);
@@ -1943,7 +1953,7 @@ function isDiscouraged(skillId, currentSelections) {
1943
1953
  const fullId = resolveAlias(skillId);
1944
1954
  const skill = matrix.skills[fullId];
1945
1955
  if (!skill) return false;
1946
- const { resolvedSelections, selectedSet } = initializeSelectionContext(currentSelections);
1956
+ const { resolvedSelections } = initializeSelectionContext(currentSelections);
1947
1957
  for (const selectedId of resolvedSelections) {
1948
1958
  const selectedSkill = matrix.skills[selectedId];
1949
1959
  if (selectedSkill?.discourages.some((d) => d.skillId === fullId)) {
@@ -1953,26 +1963,30 @@ function isDiscouraged(skillId, currentSelections) {
1953
1963
  return true;
1954
1964
  }
1955
1965
  }
1966
+ return false;
1967
+ }
1968
+ function isIncompatible(skillId, currentSelections) {
1969
+ const fullId = resolveAlias(skillId);
1970
+ const skill = matrix.skills[fullId];
1971
+ if (!skill) return false;
1972
+ const { resolvedSelections } = initializeSelectionContext(currentSelections);
1956
1973
  for (const selectedId of resolvedSelections) {
1957
- if (skill.conflictsWith.some((c) => c.skillId === selectedId)) {
1958
- return true;
1959
- }
1974
+ if (skill.conflictsWith.some((c) => c.skillId === selectedId)) return true;
1960
1975
  const selectedSkill = matrix.skills[selectedId];
1961
- if (selectedSkill?.conflictsWith.some((c) => c.skillId === fullId)) {
1962
- return true;
1963
- }
1976
+ if (selectedSkill?.conflictsWith.some((c) => c.skillId === fullId)) return true;
1964
1977
  }
1978
+ return false;
1979
+ }
1980
+ function hasUnmetRequirements(skillId, currentSelections) {
1981
+ const fullId = resolveAlias(skillId);
1982
+ const skill = matrix.skills[fullId];
1983
+ if (!skill) return false;
1984
+ const { selectedSet } = initializeSelectionContext(currentSelections);
1965
1985
  for (const requirement of skill.requires) {
1966
1986
  if (requirement.needsAny) {
1967
- const hasAny = requirement.skillIds.some((reqId) => selectedSet.has(reqId));
1968
- if (!hasAny) {
1969
- return true;
1970
- }
1987
+ if (!requirement.skillIds.some((reqId) => selectedSet.has(reqId))) return true;
1971
1988
  } else {
1972
- const hasAll = requirement.skillIds.every((reqId) => selectedSet.has(reqId));
1973
- if (!hasAll) {
1974
- return true;
1975
- }
1989
+ if (!requirement.skillIds.every((reqId) => selectedSet.has(reqId))) return true;
1976
1990
  }
1977
1991
  }
1978
1992
  return false;
@@ -1981,7 +1995,7 @@ function getDiscourageReason(skillId, currentSelections) {
1981
1995
  const fullId = resolveAlias(skillId);
1982
1996
  const skill = matrix.skills[fullId];
1983
1997
  if (!skill) return void 0;
1984
- const { resolvedSelections, selectedSet } = initializeSelectionContext(currentSelections);
1998
+ const { resolvedSelections } = initializeSelectionContext(currentSelections);
1985
1999
  for (const selectedId of resolvedSelections) {
1986
2000
  const selectedSkill = matrix.skills[selectedId];
1987
2001
  if (selectedSkill) {
@@ -1995,19 +2009,33 @@ function getDiscourageReason(skillId, currentSelections) {
1995
2009
  return reverseDiscourage.reason;
1996
2010
  }
1997
2011
  }
2012
+ return void 0;
2013
+ }
2014
+ function getIncompatibleReason(skillId, currentSelections) {
2015
+ const fullId = resolveAlias(skillId);
2016
+ const skill = matrix.skills[fullId];
2017
+ if (!skill) return void 0;
2018
+ const { resolvedSelections } = initializeSelectionContext(currentSelections);
1998
2019
  for (const selectedId of resolvedSelections) {
1999
2020
  const conflict = skill.conflictsWith.find((c) => c.skillId === selectedId);
2000
2021
  if (conflict) {
2001
- return `${conflict.reason} (conflicts with ${getLabel(getSkillById(selectedId))})`;
2022
+ return `conflicts with ${getLabel(getSkillById(selectedId))}`;
2002
2023
  }
2003
2024
  const selectedSkill = matrix.skills[selectedId];
2004
2025
  if (selectedSkill) {
2005
2026
  const reverseConflict = selectedSkill.conflictsWith.find((c) => c.skillId === fullId);
2006
2027
  if (reverseConflict) {
2007
- return `${reverseConflict.reason} (conflicts with ${getLabel(selectedSkill)})`;
2028
+ return `conflicts with ${getLabel(selectedSkill)}`;
2008
2029
  }
2009
2030
  }
2010
2031
  }
2032
+ return void 0;
2033
+ }
2034
+ function getUnmetRequirementsReason(skillId, currentSelections) {
2035
+ const fullId = resolveAlias(skillId);
2036
+ const skill = matrix.skills[fullId];
2037
+ if (!skill) return void 0;
2038
+ const { selectedSet } = initializeSelectionContext(currentSelections);
2011
2039
  for (const requirement of skill.requires) {
2012
2040
  if (requirement.needsAny) {
2013
2041
  const hasAny = requirement.skillIds.some((reqId) => selectedSet.has(reqId));
@@ -2015,8 +2043,8 @@ function getDiscourageReason(skillId, currentSelections) {
2015
2043
  const requiredNames = requirement.skillIds.map((id) => {
2016
2044
  const s = matrix.skills[id];
2017
2045
  return s ? getLabel(s) : id;
2018
- }).join(" or ");
2019
- return `${requirement.reason} (requires ${requiredNames})`;
2046
+ });
2047
+ return `requires ${joinWithOr(requiredNames)}`;
2020
2048
  }
2021
2049
  } else {
2022
2050
  const missingIds = requirement.skillIds.filter((reqId) => !selectedSet.has(reqId));
@@ -2024,8 +2052,8 @@ function getDiscourageReason(skillId, currentSelections) {
2024
2052
  const missingNames = missingIds.map((id) => {
2025
2053
  const s = matrix.skills[id];
2026
2054
  return s ? getLabel(s) : id;
2027
- }).join(", ");
2028
- return `${requirement.reason} (requires ${missingNames})`;
2055
+ });
2056
+ return `requires ${joinWithAnd(missingNames)}`;
2029
2057
  }
2030
2058
  }
2031
2059
  }
@@ -2159,28 +2187,45 @@ function validateSelection(selections) {
2159
2187
  validateRecommendations(resolvedSelections, selectedSet)
2160
2188
  ]);
2161
2189
  return {
2162
- valid: errors.length === 0,
2190
+ valid: true,
2163
2191
  errors,
2164
2192
  warnings
2165
2193
  };
2166
2194
  }
2195
+ function computeAdvisoryState(skillId, currentSelections) {
2196
+ if (isIncompatible(skillId, currentSelections)) {
2197
+ return {
2198
+ status: "incompatible",
2199
+ reason: getIncompatibleReason(skillId, currentSelections) ?? "Incompatible"
2200
+ };
2201
+ }
2202
+ if (isDiscouraged(skillId, currentSelections)) {
2203
+ return {
2204
+ status: "discouraged",
2205
+ reason: getDiscourageReason(skillId, currentSelections) ?? "Not recommended"
2206
+ };
2207
+ }
2208
+ if (isRecommended(skillId, currentSelections)) {
2209
+ return {
2210
+ status: "recommended",
2211
+ reason: getRecommendReason(skillId, currentSelections) ?? "Recommended"
2212
+ };
2213
+ }
2214
+ return { status: "normal" };
2215
+ }
2167
2216
  function getAvailableSkills(categoryId, currentSelections) {
2168
2217
  const skillOptions = [];
2169
2218
  const { selectedSet } = initializeSelectionContext(currentSelections);
2170
2219
  for (const skill of Object.values(matrix.skills)) {
2171
2220
  if (!skill) continue;
2172
- if (skill.category !== categoryId) {
2173
- continue;
2174
- }
2175
- const discouraged = isDiscouraged(skill.id, currentSelections);
2176
- const recommended = !discouraged && isRecommended(skill.id, currentSelections);
2221
+ if (skill.category !== categoryId) continue;
2222
+ const isSelected = selectedSet.has(skill.id);
2177
2223
  skillOptions.push({
2178
2224
  id: skill.id,
2179
- discouraged,
2180
- discouragedReason: discouraged ? getDiscourageReason(skill.id, currentSelections) : void 0,
2181
- recommended,
2182
- recommendedReason: recommended ? getRecommendReason(skill.id, currentSelections) : void 0,
2183
- selected: selectedSet.has(skill.id),
2225
+ advisoryState: computeAdvisoryState(skill.id, currentSelections),
2226
+ selected: isSelected,
2227
+ hasUnmetRequirements: isSelected && hasUnmetRequirements(skill.id, currentSelections),
2228
+ unmetRequirementsReason: isSelected ? getUnmetRequirementsReason(skill.id, currentSelections) : void 0,
2184
2229
  alternatives: skill.alternatives.map((a) => a.skillId)
2185
2230
  });
2186
2231
  }
@@ -2434,6 +2479,7 @@ async function detectInstallation(projectDir = process.cwd()) {
2434
2479
 
2435
2480
  // src/cli/lib/installation/local-installer.ts
2436
2481
  init_esm_shims();
2482
+ import fs from "fs";
2437
2483
  import os8 from "os";
2438
2484
  import path20 from "path";
2439
2485
 
@@ -3779,7 +3825,7 @@ async function writeProjectConfigTypes(projectConfigPath, projectDir, projectCon
3779
3825
  }
3780
3826
  async function writeScopedConfigs(finalConfig, matrix2, agents, projectDir, projectConfigPath, projectInstallationExists) {
3781
3827
  const homeDir = os8.homedir();
3782
- const isProjectContext = path20.resolve(projectDir) !== path20.resolve(homeDir);
3828
+ const isProjectContext = fs.realpathSync(projectDir) !== fs.realpathSync(homeDir);
3783
3829
  if (!isProjectContext) {
3784
3830
  await writeConfigFile(finalConfig, projectConfigPath);
3785
3831
  await writeStandaloneConfigTypes(projectConfigPath, matrix2, agents, finalConfig);
@@ -3833,7 +3879,7 @@ async function compileAndWriteAgents(compileConfig, agents, localSkills, sourceR
3833
3879
  async function installPluginConfig(options) {
3834
3880
  const { wizardResult, sourceResult, projectDir, sourceFlag } = options;
3835
3881
  const projectPaths = resolveInstallPaths(projectDir, "project");
3836
- const isProjectInstall = path20.resolve(projectDir) !== path20.resolve(os8.homedir());
3882
+ const isProjectInstall = fs.realpathSync(projectDir) !== fs.realpathSync(os8.homedir());
3837
3883
  if (isProjectInstall) {
3838
3884
  await ensureDir(projectPaths.agentsDir);
3839
3885
  }
@@ -3841,7 +3887,7 @@ async function installPluginConfig(options) {
3841
3887
  const agents = await loadMergedAgents(sourceResult.sourcePath);
3842
3888
  const mergeResult = await buildAndMergeConfig(wizardResult, sourceResult, projectDir, sourceFlag);
3843
3889
  const finalConfig = mergeResult.config;
3844
- const projectInstallationExists = path20.resolve(projectDir) !== path20.resolve(os8.homedir());
3890
+ const projectInstallationExists = fs.realpathSync(projectDir) !== fs.realpathSync(os8.homedir());
3845
3891
  await writeScopedConfigs(
3846
3892
  finalConfig,
3847
3893
  sourceResult.matrix,
@@ -3887,7 +3933,7 @@ async function installLocal(options) {
3887
3933
  const projectSkills = wizardResult.skills.filter((s) => s.scope !== "global");
3888
3934
  const globalSkills = wizardResult.skills.filter((s) => s.scope === "global");
3889
3935
  const homeDir = os8.homedir();
3890
- const isProjectInstall = path20.resolve(projectDir) !== path20.resolve(homeDir);
3936
+ const isProjectInstall = fs.realpathSync(projectDir) !== fs.realpathSync(homeDir);
3891
3937
  if (isProjectInstall) {
3892
3938
  await prepareDirectories(projectPaths);
3893
3939
  } else {
@@ -3901,7 +3947,7 @@ async function installLocal(options) {
3901
3947
  const agents = await loadMergedAgents(sourceResult.sourcePath);
3902
3948
  const mergeResult = await buildAndMergeConfig(wizardResult, sourceResult, projectDir, sourceFlag);
3903
3949
  const finalConfig = mergeResult.config;
3904
- const isProjectContext = path20.resolve(projectDir) !== path20.resolve(os8.homedir());
3950
+ const isProjectContext = fs.realpathSync(projectDir) !== fs.realpathSync(os8.homedir());
3905
3951
  await writeScopedConfigs(
3906
3952
  finalConfig,
3907
3953
  sourceResult.matrix,
@@ -5347,20 +5393,6 @@ function extractSourceName(source) {
5347
5393
  const firstSegment = withoutUrl.split("/")[0];
5348
5394
  return firstSegment || source;
5349
5395
  }
5350
- function getMarketplaceLabel(sourceResult) {
5351
- if (sourceResult.isLocal) return void 0;
5352
- const { marketplace } = sourceResult;
5353
- if (!marketplace) {
5354
- const name = extractSourceName(sourceResult.sourceConfig.source);
5355
- return `${name} (public)`;
5356
- }
5357
- const PUBLIC_MARKETPLACE_COUNT = 1;
5358
- const isDefaultSource = sourceResult.sourceConfig.source === DEFAULT_SOURCE;
5359
- if (!isDefaultSource) {
5360
- return `${marketplace} + ${PUBLIC_MARKETPLACE_COUNT} public`;
5361
- }
5362
- return marketplace;
5363
- }
5364
5396
  function mergeLocalSkillsIntoMatrix(matrix2, localResult) {
5365
5397
  for (const metadata of localResult.skills) {
5366
5398
  const existingSkill = matrix2.skills[metadata.id];
@@ -5466,7 +5498,6 @@ export {
5466
5498
  loadSkillsMatrixFromSource,
5467
5499
  convertStackToResolvedStack,
5468
5500
  extractSourceName,
5469
- getMarketplaceLabel,
5470
5501
  mergeLocalSkillsIntoMatrix,
5471
5502
  loadConfigTypesDataInBackground,
5472
5503
  regenerateConfigTypes,
@@ -5496,4 +5527,4 @@ export {
5496
5527
  validateAllPlugins,
5497
5528
  printPluginValidationResult
5498
5529
  };
5499
- //# sourceMappingURL=chunk-2EXAK22V.js.map
5530
+ //# sourceMappingURL=chunk-6W4H2K3Z.js.map