@claude-collective/cli 0.6.0 → 0.8.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 (137) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/dist/{chunk-D4IQAT27.js → chunk-3HBTELJN.js} +2 -2
  3. package/dist/{chunk-6ESUJMM7.js → chunk-3ZCB5K33.js} +3 -3
  4. package/dist/chunk-66UDJBF6.js +96 -0
  5. package/dist/chunk-66UDJBF6.js.map +1 -0
  6. package/dist/chunk-6LS7XO3H.js +31 -0
  7. package/dist/chunk-6LS7XO3H.js.map +1 -0
  8. package/dist/{chunk-SJYG4EJZ.js → chunk-A3J6IAXK.js} +7 -7
  9. package/dist/{chunk-SJYG4EJZ.js.map → chunk-A3J6IAXK.js.map} +1 -1
  10. package/dist/chunk-A65SBAAJ.js +69 -0
  11. package/dist/chunk-A65SBAAJ.js.map +1 -0
  12. package/dist/chunk-ALEPJ6YN.js +80 -0
  13. package/dist/chunk-ALEPJ6YN.js.map +1 -0
  14. package/dist/{chunk-367K3JB3.js → chunk-C4ZTIYFR.js} +3 -3
  15. package/dist/{chunk-FKU7VSUD.js → chunk-CIY5UBRB.js} +2 -2
  16. package/dist/{chunk-6WEQADPL.js → chunk-DKGL77IY.js} +4 -4
  17. package/dist/chunk-ED73HCW2.js +315 -0
  18. package/dist/chunk-ED73HCW2.js.map +1 -0
  19. package/dist/{chunk-URDV4OCP.js → chunk-FNOYEXUE.js} +5 -5
  20. package/dist/{chunk-OSQDDJXX.js → chunk-G2FBJOZG.js} +2 -7
  21. package/dist/chunk-G2FBJOZG.js.map +1 -0
  22. package/dist/chunk-HNDT5QRB.js +120 -0
  23. package/dist/chunk-HNDT5QRB.js.map +1 -0
  24. package/dist/chunk-K7PTOVX4.js +158 -0
  25. package/dist/chunk-K7PTOVX4.js.map +1 -0
  26. package/dist/{chunk-AU7XVCLO.js → chunk-LQTST4WY.js} +2 -2
  27. package/dist/chunk-LVKRVFYR.js +54 -0
  28. package/dist/chunk-LVKRVFYR.js.map +1 -0
  29. package/dist/{chunk-ZSKHDU5P.js → chunk-NGBFJJ7Q.js} +2 -2
  30. package/dist/{chunk-UNHCZRO4.js → chunk-OLBOTK3O.js} +2 -2
  31. package/dist/chunk-PPNTD5LO.js +330 -0
  32. package/dist/chunk-PPNTD5LO.js.map +1 -0
  33. package/dist/{chunk-UFWNMW3G.js → chunk-Q2LH2DAB.js} +5 -5
  34. package/dist/{chunk-AZP2AA5M.js → chunk-Q6DR5QUH.js} +206 -84
  35. package/dist/chunk-Q6DR5QUH.js.map +1 -0
  36. package/dist/{chunk-JMQGWQZU.js → chunk-QGGSLMO3.js} +3 -3
  37. package/dist/chunk-QGGSLMO3.js.map +1 -0
  38. package/dist/{chunk-J2Y4A3LP.js → chunk-SEBPPFUW.js} +2 -2
  39. package/dist/chunk-SEBPPFUW.js.map +1 -0
  40. package/dist/chunk-UOWHJ6BE.js +83 -0
  41. package/dist/chunk-UOWHJ6BE.js.map +1 -0
  42. package/dist/{chunk-ZDQIUHAM.js → chunk-XKEG3SCV.js} +13 -16
  43. package/dist/chunk-XKEG3SCV.js.map +1 -0
  44. package/dist/chunk-XY3XDVMI.js +15599 -0
  45. package/dist/chunk-XY3XDVMI.js.map +1 -0
  46. package/dist/chunk-Y3V43XCU.js +76 -0
  47. package/dist/chunk-Y3V43XCU.js.map +1 -0
  48. package/dist/{chunk-TFV6Z7F7.js → chunk-YKXBGCFD.js} +4 -4
  49. package/dist/commands/build/marketplace.js +11 -52
  50. package/dist/commands/build/marketplace.js.map +1 -1
  51. package/dist/commands/build/plugins.js +11 -49
  52. package/dist/commands/build/plugins.js.map +1 -1
  53. package/dist/commands/build/stack.js +7 -7
  54. package/dist/commands/compile.js +10 -10
  55. package/dist/commands/diff.js +4 -4
  56. package/dist/commands/doctor.js +4 -4
  57. package/dist/commands/edit.js +24 -23
  58. package/dist/commands/edit.js.map +1 -1
  59. package/dist/commands/eject.js +2 -2
  60. package/dist/commands/info.js +4 -4
  61. package/dist/commands/init.js +20 -19
  62. package/dist/commands/init.js.map +1 -1
  63. package/dist/commands/list.js +4 -4
  64. package/dist/commands/new/agent.js +2 -2
  65. package/dist/commands/new/skill.js +1 -1
  66. package/dist/commands/outdated.js +4 -4
  67. package/dist/commands/search.js +4 -4
  68. package/dist/commands/test-imports.js +9 -9
  69. package/dist/commands/uninstall.js +15 -8
  70. package/dist/commands/uninstall.js.map +1 -1
  71. package/dist/commands/update.js +12 -12
  72. package/dist/commands/validate.js +2 -2
  73. package/dist/commands/version/bump.js +2 -2
  74. package/dist/commands/version/index.js +2 -2
  75. package/dist/commands/version/set.js +1 -1
  76. package/dist/commands/version/show.js +2 -2
  77. package/dist/components/wizard/category-grid.js +9 -0
  78. package/dist/components/wizard/category-grid.test.js +728 -0
  79. package/dist/components/wizard/category-grid.test.js.map +1 -0
  80. package/dist/components/wizard/section-progress.js +9 -0
  81. package/dist/components/wizard/section-progress.test.js +281 -0
  82. package/dist/components/wizard/section-progress.test.js.map +1 -0
  83. package/dist/components/wizard/step-approach.js +3 -3
  84. package/dist/components/wizard/step-build.js +15 -0
  85. package/dist/components/wizard/step-build.test.js +729 -0
  86. package/dist/components/wizard/step-build.test.js.map +1 -0
  87. package/dist/components/wizard/step-confirm.js +1 -4
  88. package/dist/components/wizard/step-refine.js +9 -0
  89. package/dist/components/wizard/step-refine.js.map +1 -0
  90. package/dist/components/wizard/step-refine.test.js +235 -0
  91. package/dist/components/wizard/step-refine.test.js.map +1 -0
  92. package/dist/components/wizard/step-stack-options.js +11 -0
  93. package/dist/components/wizard/step-stack-options.js.map +1 -0
  94. package/dist/components/wizard/step-stack.js +3 -3
  95. package/dist/components/wizard/wizard-tabs.js +11 -0
  96. package/dist/components/wizard/wizard-tabs.js.map +1 -0
  97. package/dist/components/wizard/wizard.js +12 -11
  98. package/dist/stores/wizard-store.js +2 -2
  99. package/dist/stores/wizard-store.test.js +249 -15835
  100. package/dist/stores/wizard-store.test.js.map +1 -1
  101. package/package.json +1 -1
  102. package/dist/chunk-6OY6ZYQF.js +0 -93
  103. package/dist/chunk-6OY6ZYQF.js.map +0 -1
  104. package/dist/chunk-AZP2AA5M.js.map +0 -1
  105. package/dist/chunk-J2Y4A3LP.js.map +0 -1
  106. package/dist/chunk-JMQGWQZU.js.map +0 -1
  107. package/dist/chunk-JY4RO76L.js +0 -73
  108. package/dist/chunk-JY4RO76L.js.map +0 -1
  109. package/dist/chunk-OSQDDJXX.js.map +0 -1
  110. package/dist/chunk-TD643KB3.js +0 -245
  111. package/dist/chunk-TD643KB3.js.map +0 -1
  112. package/dist/chunk-TGOHJCQ4.js +0 -83
  113. package/dist/chunk-TGOHJCQ4.js.map +0 -1
  114. package/dist/chunk-YI6JVSFO.js +0 -43
  115. package/dist/chunk-YI6JVSFO.js.map +0 -1
  116. package/dist/chunk-YNSNRR5D.js +0 -184
  117. package/dist/chunk-YNSNRR5D.js.map +0 -1
  118. package/dist/chunk-Z6DLWTBY.js +0 -46
  119. package/dist/chunk-Z6DLWTBY.js.map +0 -1
  120. package/dist/chunk-ZDQIUHAM.js.map +0 -1
  121. package/dist/components/wizard/selection-header.js +0 -11
  122. package/dist/components/wizard/step-category.js +0 -12
  123. package/dist/components/wizard/step-subcategory.js +0 -13
  124. /package/dist/{chunk-D4IQAT27.js.map → chunk-3HBTELJN.js.map} +0 -0
  125. /package/dist/{chunk-6ESUJMM7.js.map → chunk-3ZCB5K33.js.map} +0 -0
  126. /package/dist/{chunk-367K3JB3.js.map → chunk-C4ZTIYFR.js.map} +0 -0
  127. /package/dist/{chunk-FKU7VSUD.js.map → chunk-CIY5UBRB.js.map} +0 -0
  128. /package/dist/{chunk-6WEQADPL.js.map → chunk-DKGL77IY.js.map} +0 -0
  129. /package/dist/{chunk-URDV4OCP.js.map → chunk-FNOYEXUE.js.map} +0 -0
  130. /package/dist/{chunk-AU7XVCLO.js.map → chunk-LQTST4WY.js.map} +0 -0
  131. /package/dist/{chunk-ZSKHDU5P.js.map → chunk-NGBFJJ7Q.js.map} +0 -0
  132. /package/dist/{chunk-UNHCZRO4.js.map → chunk-OLBOTK3O.js.map} +0 -0
  133. /package/dist/{chunk-UFWNMW3G.js.map → chunk-Q2LH2DAB.js.map} +0 -0
  134. /package/dist/{chunk-TFV6Z7F7.js.map → chunk-YKXBGCFD.js.map} +0 -0
  135. /package/dist/components/wizard/{selection-header.js.map → category-grid.js.map} +0 -0
  136. /package/dist/components/wizard/{step-category.js.map → section-progress.js.map} +0 -0
  137. /package/dist/components/wizard/{step-subcategory.js.map → step-build.js.map} +0 -0
@@ -0,0 +1,158 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ DEFAULT_PRESELECTED_SKILLS
4
+ } from "./chunk-A3J6IAXK.js";
5
+ import {
6
+ init_esm_shims
7
+ } from "./chunk-DHET7RCE.js";
8
+
9
+ // src/cli-v2/stores/wizard-store.ts
10
+ init_esm_shims();
11
+ import { create } from "zustand";
12
+ var createInitialState = () => ({
13
+ step: "approach",
14
+ approach: null,
15
+ selectedStackId: null,
16
+ stackAction: null,
17
+ selectedDomains: [],
18
+ currentDomainIndex: 0,
19
+ domainSelections: {},
20
+ focusedRow: 0,
21
+ focusedCol: 0,
22
+ currentRefineIndex: 0,
23
+ skillSources: {},
24
+ refineAction: null,
25
+ showDescriptions: false,
26
+ expertMode: false,
27
+ installMode: "local",
28
+ history: []
29
+ });
30
+ var useWizardStore = create((set, get) => ({
31
+ ...createInitialState(),
32
+ setStep: (step) => set((state) => ({
33
+ step,
34
+ history: [...state.history, state.step],
35
+ // Reset focus when changing steps
36
+ focusedRow: 0,
37
+ focusedCol: 0
38
+ })),
39
+ setApproach: (approach) => set({ approach }),
40
+ selectStack: (stackId) => set({ selectedStackId: stackId }),
41
+ setStackAction: (action) => set({ stackAction: action }),
42
+ toggleDomain: (domain) => set((state) => {
43
+ const isSelected = state.selectedDomains.includes(domain);
44
+ return {
45
+ selectedDomains: isSelected ? state.selectedDomains.filter((d) => d !== domain) : [...state.selectedDomains, domain]
46
+ };
47
+ }),
48
+ setDomainSelection: (domain, subcategory, technologies) => set((state) => ({
49
+ domainSelections: {
50
+ ...state.domainSelections,
51
+ [domain]: {
52
+ ...state.domainSelections[domain],
53
+ [subcategory]: technologies
54
+ }
55
+ }
56
+ })),
57
+ toggleTechnology: (domain, subcategory, technology, exclusive) => set((state) => {
58
+ const currentSelections = state.domainSelections[domain]?.[subcategory] || [];
59
+ const isSelected = currentSelections.includes(technology);
60
+ let newSelections;
61
+ if (exclusive) {
62
+ newSelections = isSelected ? [] : [technology];
63
+ } else {
64
+ newSelections = isSelected ? currentSelections.filter((t) => t !== technology) : [...currentSelections, technology];
65
+ }
66
+ return {
67
+ domainSelections: {
68
+ ...state.domainSelections,
69
+ [domain]: {
70
+ ...state.domainSelections[domain],
71
+ [subcategory]: newSelections
72
+ }
73
+ }
74
+ };
75
+ }),
76
+ setCurrentDomainIndex: (index) => set({ currentDomainIndex: index, focusedRow: 0, focusedCol: 0 }),
77
+ nextDomain: () => {
78
+ const state = get();
79
+ if (state.currentDomainIndex < state.selectedDomains.length - 1) {
80
+ set({
81
+ currentDomainIndex: state.currentDomainIndex + 1,
82
+ focusedRow: 0,
83
+ focusedCol: 0
84
+ });
85
+ return true;
86
+ }
87
+ return false;
88
+ },
89
+ prevDomain: () => {
90
+ const state = get();
91
+ if (state.currentDomainIndex > 0) {
92
+ set({
93
+ currentDomainIndex: state.currentDomainIndex - 1,
94
+ focusedRow: 0,
95
+ focusedCol: 0
96
+ });
97
+ return true;
98
+ }
99
+ return false;
100
+ },
101
+ setFocus: (row, col) => set({ focusedRow: row, focusedCol: col }),
102
+ setRefineAction: (action) => set({ refineAction: action }),
103
+ setSkillSource: (technology, skillId) => set((state) => ({
104
+ skillSources: {
105
+ ...state.skillSources,
106
+ [technology]: skillId
107
+ }
108
+ })),
109
+ setCurrentRefineIndex: (index) => set({ currentRefineIndex: index }),
110
+ toggleShowDescriptions: () => set((state) => ({ showDescriptions: !state.showDescriptions })),
111
+ toggleExpertMode: () => set((state) => ({ expertMode: !state.expertMode })),
112
+ toggleInstallMode: () => set((state) => ({
113
+ installMode: state.installMode === "plugin" ? "local" : "plugin"
114
+ })),
115
+ goBack: () => set((state) => {
116
+ const history = [...state.history];
117
+ const previousStep = history.pop();
118
+ return {
119
+ step: previousStep || "approach",
120
+ history,
121
+ focusedRow: 0,
122
+ focusedCol: 0
123
+ };
124
+ }),
125
+ reset: () => set(createInitialState()),
126
+ // ─────────────────────────────────────────────────────────────────
127
+ // Computed getters
128
+ // ─────────────────────────────────────────────────────────────────
129
+ getAllSelectedTechnologies: () => {
130
+ const state = get();
131
+ const technologies = [];
132
+ for (const domain of Object.keys(state.domainSelections)) {
133
+ for (const subcategory of Object.keys(state.domainSelections[domain])) {
134
+ technologies.push(...state.domainSelections[domain][subcategory]);
135
+ }
136
+ }
137
+ return technologies;
138
+ },
139
+ getCurrentDomain: () => {
140
+ const state = get();
141
+ return state.selectedDomains[state.currentDomainIndex] || null;
142
+ },
143
+ getSelectedSkills: () => {
144
+ const state = get();
145
+ const skillIds = [...DEFAULT_PRESELECTED_SKILLS];
146
+ for (const skillId of Object.values(state.skillSources)) {
147
+ if (!skillIds.includes(skillId)) {
148
+ skillIds.push(skillId);
149
+ }
150
+ }
151
+ return skillIds;
152
+ }
153
+ }));
154
+
155
+ export {
156
+ useWizardStore
157
+ };
158
+ //# sourceMappingURL=chunk-K7PTOVX4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli-v2/stores/wizard-store.ts"],"sourcesContent":["import { create } from \"zustand\";\nimport { DEFAULT_PRESELECTED_SKILLS } from \"../consts\";\n\n// Step types for the wizard\nexport type WizardStep =\n | \"approach\" // Choose stack template or build from scratch\n | \"stack\" // Select pre-built stack (if approach=stack) or domains (if approach=scratch)\n | \"stack-options\" // After stack selection: continue defaults or customize\n | \"build\" // CategoryGrid for technology selection\n | \"refine\" // Skill source selection\n | \"confirm\"; // Final confirmation\n\nexport interface WizardState {\n // ─────────────────────────────────────────────────────────────────\n // Current step\n // ─────────────────────────────────────────────────────────────────\n step: WizardStep;\n\n // ─────────────────────────────────────────────────────────────────\n // Flow tracking\n // ─────────────────────────────────────────────────────────────────\n approach: \"stack\" | \"scratch\" | null;\n selectedStackId: string | null;\n stackAction: \"defaults\" | \"customize\" | null; // For stack flow after selection\n\n // ─────────────────────────────────────────────────────────────────\n // Domain selection (scratch flow or customize flow)\n // ─────────────────────────────────────────────────────────────────\n selectedDomains: string[]; // ['web', 'api', 'cli', 'mobile']\n\n // ─────────────────────────────────────────────────────────────────\n // Build step state\n // ─────────────────────────────────────────────────────────────────\n currentDomainIndex: number; // Which domain we're configuring (0-based)\n domainSelections: Record<string, Record<string, string[]>>;\n // e.g., { web: { framework: ['react'], styling: ['scss-modules'] } }\n // Note: array supports multi-select categories\n\n // ─────────────────────────────────────────────────────────────────\n // Grid navigation state\n // ─────────────────────────────────────────────────────────────────\n focusedRow: number;\n focusedCol: number;\n\n // ─────────────────────────────────────────────────────────────────\n // Refine step state\n // ─────────────────────────────────────────────────────────────────\n currentRefineIndex: number; // Which skill we're refining\n skillSources: Record<string, string>; // technology -> selected skill ID\n refineAction: \"all-recommended\" | \"customize\" | null;\n\n // ─────────────────────────────────────────────────────────────────\n // UI state\n // ─────────────────────────────────────────────────────────────────\n showDescriptions: boolean;\n expertMode: boolean;\n\n // ─────────────────────────────────────────────────────────────────\n // Modes\n // ─────────────────────────────────────────────────────────────────\n installMode: \"plugin\" | \"local\";\n\n // ─────────────────────────────────────────────────────────────────\n // Navigation history\n // ─────────────────────────────────────────────────────────────────\n history: WizardStep[];\n\n // ─────────────────────────────────────────────────────────────────\n // Actions\n // ─────────────────────────────────────────────────────────────────\n setStep: (step: WizardStep) => void;\n setApproach: (approach: \"stack\" | \"scratch\") => void;\n selectStack: (stackId: string | null) => void;\n setStackAction: (action: \"defaults\" | \"customize\") => void;\n toggleDomain: (domain: string) => void;\n setDomainSelection: (\n domain: string,\n subcategory: string,\n technologies: string[],\n ) => void;\n toggleTechnology: (\n domain: string,\n subcategory: string,\n technology: string,\n exclusive: boolean,\n ) => void;\n setCurrentDomainIndex: (index: number) => void;\n nextDomain: () => boolean; // Returns true if moved to next domain, false if at end\n prevDomain: () => boolean; // Returns true if moved to prev domain, false if at start\n setFocus: (row: number, col: number) => void;\n setRefineAction: (action: \"all-recommended\" | \"customize\") => void;\n setSkillSource: (technology: string, skillId: string) => void;\n setCurrentRefineIndex: (index: number) => void;\n toggleShowDescriptions: () => void;\n toggleExpertMode: () => void;\n toggleInstallMode: () => void;\n goBack: () => void;\n reset: () => void;\n\n // ─────────────────────────────────────────────────────────────────\n // Computed getters (derive from state)\n // ─────────────────────────────────────────────────────────────────\n getAllSelectedTechnologies: () => string[];\n getCurrentDomain: () => string | null;\n getSelectedSkills: () => string[]; // All selected skills including preselected\n}\n\nconst createInitialState = () => ({\n step: \"approach\" as WizardStep,\n approach: null as \"stack\" | \"scratch\" | null,\n selectedStackId: null as string | null,\n stackAction: null as \"defaults\" | \"customize\" | null,\n selectedDomains: [] as string[],\n currentDomainIndex: 0,\n domainSelections: {} as Record<string, Record<string, string[]>>,\n focusedRow: 0,\n focusedCol: 0,\n currentRefineIndex: 0,\n skillSources: {} as Record<string, string>,\n refineAction: null as \"all-recommended\" | \"customize\" | null,\n showDescriptions: false,\n expertMode: false,\n installMode: \"local\" as \"plugin\" | \"local\",\n history: [] as WizardStep[],\n});\n\nexport const useWizardStore = create<WizardState>((set, get) => ({\n ...createInitialState(),\n\n setStep: (step) =>\n set((state) => ({\n step,\n history: [...state.history, state.step],\n // Reset focus when changing steps\n focusedRow: 0,\n focusedCol: 0,\n })),\n\n setApproach: (approach) => set({ approach }),\n\n selectStack: (stackId) => set({ selectedStackId: stackId }),\n\n setStackAction: (action) => set({ stackAction: action }),\n\n toggleDomain: (domain) =>\n set((state) => {\n const isSelected = state.selectedDomains.includes(domain);\n return {\n selectedDomains: isSelected\n ? state.selectedDomains.filter((d) => d !== domain)\n : [...state.selectedDomains, domain],\n };\n }),\n\n setDomainSelection: (domain, subcategory, technologies) =>\n set((state) => ({\n domainSelections: {\n ...state.domainSelections,\n [domain]: {\n ...state.domainSelections[domain],\n [subcategory]: technologies,\n },\n },\n })),\n\n toggleTechnology: (domain, subcategory, technology, exclusive) =>\n set((state) => {\n const currentSelections =\n state.domainSelections[domain]?.[subcategory] || [];\n const isSelected = currentSelections.includes(technology);\n\n let newSelections: string[];\n if (exclusive) {\n // For exclusive categories, toggle off if already selected, otherwise select only this one\n newSelections = isSelected ? [] : [technology];\n } else {\n // For multi-select categories, toggle the selection\n newSelections = isSelected\n ? currentSelections.filter((t) => t !== technology)\n : [...currentSelections, technology];\n }\n\n return {\n domainSelections: {\n ...state.domainSelections,\n [domain]: {\n ...state.domainSelections[domain],\n [subcategory]: newSelections,\n },\n },\n };\n }),\n\n setCurrentDomainIndex: (index) =>\n set({ currentDomainIndex: index, focusedRow: 0, focusedCol: 0 }),\n\n nextDomain: () => {\n const state = get();\n if (state.currentDomainIndex < state.selectedDomains.length - 1) {\n set({\n currentDomainIndex: state.currentDomainIndex + 1,\n focusedRow: 0,\n focusedCol: 0,\n });\n return true;\n }\n return false;\n },\n\n prevDomain: () => {\n const state = get();\n if (state.currentDomainIndex > 0) {\n set({\n currentDomainIndex: state.currentDomainIndex - 1,\n focusedRow: 0,\n focusedCol: 0,\n });\n return true;\n }\n return false;\n },\n\n setFocus: (row, col) => set({ focusedRow: row, focusedCol: col }),\n\n setRefineAction: (action) => set({ refineAction: action }),\n\n setSkillSource: (technology, skillId) =>\n set((state) => ({\n skillSources: {\n ...state.skillSources,\n [technology]: skillId,\n },\n })),\n\n setCurrentRefineIndex: (index) => set({ currentRefineIndex: index }),\n\n toggleShowDescriptions: () =>\n set((state) => ({ showDescriptions: !state.showDescriptions })),\n\n toggleExpertMode: () => set((state) => ({ expertMode: !state.expertMode })),\n\n toggleInstallMode: () =>\n set((state) => ({\n installMode: state.installMode === \"plugin\" ? \"local\" : \"plugin\",\n })),\n\n goBack: () =>\n set((state) => {\n const history = [...state.history];\n const previousStep = history.pop();\n return {\n step: previousStep || \"approach\",\n history,\n focusedRow: 0,\n focusedCol: 0,\n };\n }),\n\n reset: () => set(createInitialState()),\n\n // ─────────────────────────────────────────────────────────────────\n // Computed getters\n // ─────────────────────────────────────────────────────────────────\n getAllSelectedTechnologies: () => {\n const state = get();\n const technologies: string[] = [];\n for (const domain of Object.keys(state.domainSelections)) {\n for (const subcategory of Object.keys(state.domainSelections[domain])) {\n technologies.push(...state.domainSelections[domain][subcategory]);\n }\n }\n return technologies;\n },\n\n getCurrentDomain: () => {\n const state = get();\n return state.selectedDomains[state.currentDomainIndex] || null;\n },\n\n getSelectedSkills: () => {\n const state = get();\n // Include preselected methodology skills plus resolved skill sources\n const skillIds: string[] = [...DEFAULT_PRESELECTED_SKILLS];\n for (const skillId of Object.values(state.skillSources)) {\n if (!skillIds.includes(skillId)) {\n skillIds.push(skillId);\n }\n }\n return skillIds;\n },\n}));\n"],"mappings":"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","names":[]}
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  DEFAULT_VERSION
4
- } from "./chunk-SJYG4EJZ.js";
4
+ } from "./chunk-A3J6IAXK.js";
5
5
  import {
6
6
  ensureDir,
7
7
  writeFile
@@ -88,4 +88,4 @@ export {
88
88
  writePluginManifest,
89
89
  getPluginManifestPath
90
90
  };
91
- //# sourceMappingURL=chunk-AU7XVCLO.js.map
91
+ //# sourceMappingURL=chunk-LQTST4WY.js.map
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ init_esm_shims
4
+ } from "./chunk-DHET7RCE.js";
5
+
6
+ // src/cli-v2/components/wizard/section-progress.tsx
7
+ init_esm_shims();
8
+ import { Box, Text } from "ink";
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+ var SectionProgress = ({
11
+ label,
12
+ current,
13
+ index,
14
+ total,
15
+ next
16
+ }) => {
17
+ const isLast = index === total;
18
+ const rightText = isLast ? "Last step" : `Next: ${next}`;
19
+ return /* @__PURE__ */ jsxs(
20
+ Box,
21
+ {
22
+ flexDirection: "row",
23
+ justifyContent: "space-between",
24
+ paddingX: 2,
25
+ marginBottom: 1,
26
+ children: [
27
+ /* @__PURE__ */ jsxs(Text, { children: [
28
+ /* @__PURE__ */ jsxs(Text, { bold: true, children: [
29
+ label,
30
+ ":"
31
+ ] }),
32
+ " ",
33
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: current })
34
+ ] }),
35
+ /* @__PURE__ */ jsxs(Text, { children: [
36
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
37
+ "[",
38
+ index,
39
+ "/",
40
+ total,
41
+ "]"
42
+ ] }),
43
+ " ",
44
+ /* @__PURE__ */ jsx(Text, { dimColor: isLast, children: rightText })
45
+ ] })
46
+ ]
47
+ }
48
+ );
49
+ };
50
+
51
+ export {
52
+ SectionProgress
53
+ };
54
+ //# sourceMappingURL=chunk-LVKRVFYR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli-v2/components/wizard/section-progress.tsx"],"sourcesContent":["import React from \"react\";\nimport { Box, Text } from \"ink\";\n\nexport interface SectionProgressProps {\n /** Section label (e.g., \"Domain\" or \"Skill\") */\n label: string;\n /** Current item name (e.g., \"Web\" or \"react\") */\n current: string;\n /** 1-based index */\n index: number;\n /** Total count */\n total: number;\n /** Next item name, or undefined if last */\n next?: string;\n}\n\nexport const SectionProgress: React.FC<SectionProgressProps> = ({\n label,\n current,\n index,\n total,\n next,\n}) => {\n const isLast = index === total;\n const rightText = isLast ? \"Last step\" : `Next: ${next}`;\n\n return (\n <Box\n flexDirection=\"row\"\n justifyContent=\"space-between\"\n paddingX={2}\n marginBottom={1}\n >\n <Text>\n <Text bold>{label}:</Text> <Text color=\"cyan\">{current}</Text>\n </Text>\n <Text>\n <Text dimColor>\n [{index}/{total}]\n </Text>{\" \"}\n <Text dimColor={isLast}>{rightText}</Text>\n </Text>\n </Box>\n );\n};\n"],"mappings":";;;;;;AAAA;AACA,SAAS,KAAK,YAAY;AAiClB,SAA2B,KAA3B;AAlBD,IAAM,kBAAkD,CAAC;AAAA,EAC9D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,SAAS,UAAU;AACzB,QAAM,YAAY,SAAS,cAAc,SAAS,IAAI;AAEtD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAc;AAAA,MACd,gBAAe;AAAA,MACf,UAAU;AAAA,MACV,cAAc;AAAA,MAEd;AAAA,6BAAC,QACC;AAAA,+BAAC,QAAK,MAAI,MAAE;AAAA;AAAA,YAAM;AAAA,aAAC;AAAA,UAAO;AAAA,UAAC,oBAAC,QAAK,OAAM,QAAQ,mBAAQ;AAAA,WACzD;AAAA,QACA,qBAAC,QACC;AAAA,+BAAC,QAAK,UAAQ,MAAC;AAAA;AAAA,YACX;AAAA,YAAM;AAAA,YAAE;AAAA,YAAM;AAAA,aAClB;AAAA,UAAQ;AAAA,UACR,oBAAC,QAAK,UAAU,QAAS,qBAAU;AAAA,WACrC;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-QESUUPOE.js";
5
5
  import {
6
6
  CACHE_DIR
7
- } from "./chunk-SJYG4EJZ.js";
7
+ } from "./chunk-A3J6IAXK.js";
8
8
  import {
9
9
  verbose
10
10
  } from "./chunk-TOPAIL5W.js";
@@ -121,4 +121,4 @@ If you're behind a corporate proxy, you may need to set:
121
121
  export {
122
122
  fetchFromSource
123
123
  };
124
- //# sourceMappingURL=chunk-ZSKHDU5P.js.map
124
+ //# sourceMappingURL=chunk-NGBFJJ7Q.js.map
@@ -3,7 +3,7 @@ import {
3
3
  DEFAULT_VERSION,
4
4
  PLUGIN_MANIFEST_DIR,
5
5
  PLUGIN_MANIFEST_FILE
6
- } from "./chunk-SJYG4EJZ.js";
6
+ } from "./chunk-A3J6IAXK.js";
7
7
  import {
8
8
  readFile,
9
9
  writeFile
@@ -61,4 +61,4 @@ export {
61
61
  bumpPluginVersion,
62
62
  getPluginVersion
63
63
  };
64
- //# sourceMappingURL=chunk-UNHCZRO4.js.map
64
+ //# sourceMappingURL=chunk-OLBOTK3O.js.map
@@ -0,0 +1,330 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ init_esm_shims
4
+ } from "./chunk-DHET7RCE.js";
5
+
6
+ // src/cli-v2/components/wizard/category-grid.tsx
7
+ init_esm_shims();
8
+ import { useCallback, useEffect } from "react";
9
+ import { Box, Text, useInput } from "ink";
10
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
11
+ var SYMBOL_SELECTED = "\u25CF";
12
+ var SYMBOL_UNSELECTED = "\u25CB";
13
+ var SYMBOL_DISABLED = "\u2717";
14
+ var SYMBOL_RECOMMENDED = "\u2B50";
15
+ var SYMBOL_DISCOURAGED = "\u26A0";
16
+ var SYMBOL_FOCUS = ">";
17
+ var SYMBOL_REQUIRED = "*";
18
+ var MIN_OPTION_WIDTH = 12;
19
+ var getOptionSymbol = (option) => {
20
+ if (option.state === "disabled") {
21
+ return SYMBOL_DISABLED;
22
+ }
23
+ return option.selected ? SYMBOL_SELECTED : SYMBOL_UNSELECTED;
24
+ };
25
+ var getStateIndicator = (option) => {
26
+ if (option.state === "recommended") {
27
+ return SYMBOL_RECOMMENDED;
28
+ }
29
+ if (option.state === "discouraged") {
30
+ return SYMBOL_DISCOURAGED;
31
+ }
32
+ return null;
33
+ };
34
+ var getSymbolColor = (option) => {
35
+ if (option.state === "disabled") {
36
+ return "gray";
37
+ }
38
+ if (option.selected) {
39
+ return "green";
40
+ }
41
+ return void 0;
42
+ };
43
+ var getLabelColor = (option, isFocused) => {
44
+ if (option.state === "disabled") {
45
+ return "gray";
46
+ }
47
+ if (isFocused) {
48
+ return "cyan";
49
+ }
50
+ if (option.state === "recommended") {
51
+ return "green";
52
+ }
53
+ if (option.state === "discouraged") {
54
+ return "yellow";
55
+ }
56
+ return void 0;
57
+ };
58
+ var sortOptions = (options, expertMode) => {
59
+ if (expertMode) {
60
+ return options;
61
+ }
62
+ const stateOrder = {
63
+ recommended: 0,
64
+ normal: 1,
65
+ discouraged: 2,
66
+ disabled: 3
67
+ };
68
+ return [...options].sort((a, b) => {
69
+ return stateOrder[a.state] - stateOrder[b.state];
70
+ });
71
+ };
72
+ var findNextValidOption = (options, currentIndex, direction, wrap = true) => {
73
+ const length = options.length;
74
+ if (length === 0) return currentIndex;
75
+ let index = currentIndex;
76
+ let attempts = 0;
77
+ while (attempts < length) {
78
+ index += direction;
79
+ if (wrap) {
80
+ if (index < 0) index = length - 1;
81
+ if (index >= length) index = 0;
82
+ } else {
83
+ if (index < 0) index = 0;
84
+ if (index >= length) index = length - 1;
85
+ }
86
+ if (options[index] && options[index].state !== "disabled") {
87
+ return index;
88
+ }
89
+ attempts++;
90
+ }
91
+ return currentIndex;
92
+ };
93
+ var findValidStartColumn = (options) => {
94
+ for (let i = 0; i < options.length; i++) {
95
+ if (options[i] && options[i].state !== "disabled") {
96
+ return i;
97
+ }
98
+ }
99
+ return 0;
100
+ };
101
+ var HeaderRow = ({
102
+ showDescriptions,
103
+ expertMode
104
+ }) => {
105
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", justifyContent: "flex-end", marginBottom: 1, gap: 2, children: [
106
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
107
+ "[Tab] Show descriptions: ",
108
+ showDescriptions ? "ON" : "OFF"
109
+ ] }),
110
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
111
+ "[e] Expert Mode: ",
112
+ expertMode ? "ON" : "OFF"
113
+ ] })
114
+ ] });
115
+ };
116
+ var OptionCell = ({
117
+ option,
118
+ isFocused,
119
+ showDescription
120
+ }) => {
121
+ const symbol = getOptionSymbol(option);
122
+ const symbolColor = getSymbolColor(option);
123
+ const labelColor = getLabelColor(option, isFocused);
124
+ const stateIndicator = getStateIndicator(option);
125
+ const isDimmed = option.state === "disabled" || option.state === "discouraged";
126
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", minWidth: MIN_OPTION_WIDTH, marginRight: 1, children: [
127
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
128
+ /* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: isFocused ? SYMBOL_FOCUS : " " }),
129
+ /* @__PURE__ */ jsx(Text, { children: " " }),
130
+ /* @__PURE__ */ jsx(
131
+ Text,
132
+ {
133
+ color: symbolColor,
134
+ dimColor: isDimmed && option.state === "discouraged",
135
+ children: symbol
136
+ }
137
+ ),
138
+ /* @__PURE__ */ jsx(Text, { children: " " }),
139
+ /* @__PURE__ */ jsx(
140
+ Text,
141
+ {
142
+ color: labelColor,
143
+ dimColor: option.state === "disabled",
144
+ bold: isFocused,
145
+ strikethrough: option.state === "disabled",
146
+ children: option.label
147
+ }
148
+ ),
149
+ stateIndicator && /* @__PURE__ */ jsxs(Fragment, { children: [
150
+ /* @__PURE__ */ jsx(Text, { children: " " }),
151
+ /* @__PURE__ */ jsx(Text, { color: option.state === "recommended" ? "green" : "yellow", children: stateIndicator })
152
+ ] })
153
+ ] }),
154
+ showDescription && option.stateReason && /* @__PURE__ */ jsx(Box, { marginLeft: 4, children: /* @__PURE__ */ jsx(Text, { dimColor: true, wrap: "truncate-end", children: option.stateReason }) })
155
+ ] });
156
+ };
157
+ var CategoryRowComponent = ({
158
+ category,
159
+ options,
160
+ focusedCol,
161
+ isRowFocused,
162
+ showDescriptions
163
+ }) => {
164
+ return /* @__PURE__ */ jsxs(
165
+ Box,
166
+ {
167
+ flexDirection: "row",
168
+ alignItems: "flex-start",
169
+ marginBottom: showDescriptions ? 1 : 0,
170
+ children: [
171
+ /* @__PURE__ */ jsx(Box, { minWidth: 16, marginRight: 2, children: /* @__PURE__ */ jsxs(Text, { bold: isRowFocused, color: isRowFocused ? "cyan" : void 0, children: [
172
+ category.name,
173
+ category.required && /* @__PURE__ */ jsxs(Text, { color: "red", children: [
174
+ " ",
175
+ SYMBOL_REQUIRED
176
+ ] })
177
+ ] }) }),
178
+ /* @__PURE__ */ jsx(Box, { flexDirection: "row", flexWrap: "wrap", children: options.map((option, index) => /* @__PURE__ */ jsx(
179
+ OptionCell,
180
+ {
181
+ option,
182
+ isFocused: isRowFocused && index === focusedCol,
183
+ showDescription: showDescriptions
184
+ },
185
+ option.id
186
+ )) }),
187
+ !category.required && /* @__PURE__ */ jsx(Box, { marginLeft: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "(optional)" }) })
188
+ ]
189
+ }
190
+ );
191
+ };
192
+ var LegendRow = () => {
193
+ return /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
194
+ "Legend: ",
195
+ /* @__PURE__ */ jsx(Text, { color: "green", children: SYMBOL_SELECTED }),
196
+ " selected",
197
+ " ",
198
+ /* @__PURE__ */ jsx(Text, { color: "green", children: SYMBOL_RECOMMENDED }),
199
+ " recommended",
200
+ " ",
201
+ /* @__PURE__ */ jsx(Text, { color: "yellow", children: SYMBOL_DISCOURAGED }),
202
+ " discouraged",
203
+ " ",
204
+ /* @__PURE__ */ jsx(Text, { color: "gray", children: SYMBOL_DISABLED }),
205
+ " disabled"
206
+ ] }) });
207
+ };
208
+ var CategoryGrid = ({
209
+ categories,
210
+ focusedRow,
211
+ focusedCol,
212
+ showDescriptions,
213
+ expertMode,
214
+ onToggle,
215
+ onFocusChange,
216
+ onToggleDescriptions,
217
+ onToggleExpertMode
218
+ }) => {
219
+ const processedCategories = categories.map((category) => ({
220
+ ...category,
221
+ sortedOptions: sortOptions(category.options, expertMode)
222
+ }));
223
+ const currentRow = processedCategories[focusedRow];
224
+ const currentOptions = currentRow?.sortedOptions || [];
225
+ useEffect(() => {
226
+ if (!currentRow) return;
227
+ const maxCol = currentOptions.length - 1;
228
+ if (focusedCol > maxCol) {
229
+ const newCol = Math.max(0, maxCol);
230
+ onFocusChange(focusedRow, newCol);
231
+ } else if (currentOptions[focusedCol]?.state === "disabled") {
232
+ const validCol = findValidStartColumn(currentOptions);
233
+ if (validCol !== focusedCol) {
234
+ onFocusChange(focusedRow, validCol);
235
+ }
236
+ }
237
+ }, [focusedRow, currentOptions, focusedCol, onFocusChange, currentRow]);
238
+ useInput(
239
+ useCallback(
240
+ (input, key) => {
241
+ if (key.tab) {
242
+ onToggleDescriptions();
243
+ return;
244
+ }
245
+ if (input === "e" || input === "E") {
246
+ onToggleExpertMode();
247
+ return;
248
+ }
249
+ if (input === " ") {
250
+ const currentOption = currentOptions[focusedCol];
251
+ if (currentOption && currentOption.state !== "disabled") {
252
+ onToggle(currentRow.id, currentOption.id);
253
+ }
254
+ return;
255
+ }
256
+ const isLeft = key.leftArrow || input === "h";
257
+ const isRight = key.rightArrow || input === "l";
258
+ const isUp = key.upArrow || input === "k";
259
+ const isDown = key.downArrow || input === "j";
260
+ if (isLeft) {
261
+ const newCol = findNextValidOption(
262
+ currentOptions,
263
+ focusedCol,
264
+ -1,
265
+ true
266
+ );
267
+ onFocusChange(focusedRow, newCol);
268
+ } else if (isRight) {
269
+ const newCol = findNextValidOption(
270
+ currentOptions,
271
+ focusedCol,
272
+ 1,
273
+ true
274
+ );
275
+ onFocusChange(focusedRow, newCol);
276
+ } else if (isUp) {
277
+ const newRow = focusedRow <= 0 ? processedCategories.length - 1 : focusedRow - 1;
278
+ const newRowOptions = processedCategories[newRow]?.sortedOptions || [];
279
+ let newCol = Math.min(focusedCol, newRowOptions.length - 1);
280
+ if (newRowOptions[newCol]?.state === "disabled") {
281
+ newCol = findValidStartColumn(newRowOptions);
282
+ }
283
+ onFocusChange(newRow, newCol);
284
+ } else if (isDown) {
285
+ const newRow = focusedRow >= processedCategories.length - 1 ? 0 : focusedRow + 1;
286
+ const newRowOptions = processedCategories[newRow]?.sortedOptions || [];
287
+ let newCol = Math.min(focusedCol, newRowOptions.length - 1);
288
+ if (newRowOptions[newCol]?.state === "disabled") {
289
+ newCol = findValidStartColumn(newRowOptions);
290
+ }
291
+ onFocusChange(newRow, newCol);
292
+ }
293
+ },
294
+ [
295
+ focusedRow,
296
+ focusedCol,
297
+ currentOptions,
298
+ currentRow,
299
+ processedCategories,
300
+ onToggle,
301
+ onFocusChange,
302
+ onToggleDescriptions,
303
+ onToggleExpertMode
304
+ ]
305
+ )
306
+ );
307
+ if (categories.length === 0) {
308
+ return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No categories to display." }) });
309
+ }
310
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
311
+ /* @__PURE__ */ jsx(HeaderRow, { showDescriptions, expertMode }),
312
+ processedCategories.map((category, rowIndex) => /* @__PURE__ */ jsx(
313
+ CategoryRowComponent,
314
+ {
315
+ category,
316
+ options: category.sortedOptions,
317
+ focusedCol,
318
+ isRowFocused: rowIndex === focusedRow,
319
+ showDescriptions
320
+ },
321
+ category.id
322
+ )),
323
+ /* @__PURE__ */ jsx(LegendRow, {})
324
+ ] });
325
+ };
326
+
327
+ export {
328
+ CategoryGrid
329
+ };
330
+ //# sourceMappingURL=chunk-PPNTD5LO.js.map