@claude-collective/cli 0.21.0 → 0.26.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.
- package/CHANGELOG.md +192 -0
- package/README.md +41 -27
- package/config/skills-matrix.yaml +38 -37
- package/config/stacks.yaml +8 -14
- package/dist/{chunk-ZNIDWLL5.js → chunk-3X5D7RM5.js} +4 -3
- package/dist/chunk-3X5D7RM5.js.map +1 -0
- package/dist/chunk-4357L7VK.js +251 -0
- package/dist/chunk-4357L7VK.js.map +1 -0
- package/dist/chunk-4S4FCAA2.js +100 -0
- package/dist/chunk-4S4FCAA2.js.map +1 -0
- package/dist/chunk-7UPXT32F.js +197 -0
- package/dist/chunk-7UPXT32F.js.map +1 -0
- package/dist/{chunk-DHET7RCE.js → chunk-AWKZ5BDL.js} +9 -2
- package/dist/{chunk-DHET7RCE.js.map → chunk-AWKZ5BDL.js.map} +1 -1
- package/dist/{chunk-6Q3Y7KVB.js → chunk-DBRUQQUF.js} +8 -2
- package/dist/chunk-DBRUQQUF.js.map +1 -0
- package/dist/{chunk-OQYYMQJR.js → chunk-ETCVEV3S.js} +8 -11
- package/dist/chunk-ETCVEV3S.js.map +1 -0
- package/dist/chunk-ETQ3BPGU.js +4204 -0
- package/dist/chunk-ETQ3BPGU.js.map +1 -0
- package/dist/{chunk-ZSVMS677.js → chunk-F4RD5FYM.js} +2 -2
- package/dist/chunk-F4RD5FYM.js.map +1 -0
- package/dist/{chunk-5KXUDHAB.js → chunk-GGFOD5PK.js} +6 -9
- package/dist/chunk-GGFOD5PK.js.map +1 -0
- package/dist/{chunk-UMORK7OK.js → chunk-H7SSBSPR.js} +2 -2
- package/dist/chunk-H7SSBSPR.js.map +1 -0
- package/dist/chunk-HWD32NP7.js +19 -0
- package/dist/chunk-HWD32NP7.js.map +1 -0
- package/dist/{chunk-HGCBZUH5.js → chunk-I3YYG5IO.js} +9 -10
- package/dist/chunk-I3YYG5IO.js.map +1 -0
- package/dist/{chunk-RTE64SJA.js → chunk-IXBCRT3F.js} +2 -2
- package/dist/chunk-IXBCRT3F.js.map +1 -0
- package/dist/{chunk-WFEFICFM.js → chunk-KWYO3M5Q.js} +5 -5
- package/dist/chunk-KWYO3M5Q.js.map +1 -0
- package/dist/{chunk-HEOHU5EZ.js → chunk-MCTSHLAF.js} +22 -11
- package/dist/chunk-MCTSHLAF.js.map +1 -0
- package/dist/chunk-NQJ47R4N.js +1092 -0
- package/dist/chunk-NQJ47R4N.js.map +1 -0
- package/dist/{chunk-FJFEKPXF.js → chunk-O6ZTD7ZI.js} +14 -3
- package/dist/chunk-O6ZTD7ZI.js.map +1 -0
- package/dist/chunk-OBXAY23Y.js +56 -0
- package/dist/chunk-OBXAY23Y.js.map +1 -0
- package/dist/{chunk-XY3XDVMI.js → chunk-QR2EBWL2.js} +3 -3
- package/dist/chunk-R5KJVI54.js +311 -0
- package/dist/chunk-R5KJVI54.js.map +1 -0
- package/dist/{chunk-2LSGX6R4.js → chunk-R7B63JAP.js} +83 -25
- package/dist/chunk-R7B63JAP.js.map +1 -0
- package/dist/{chunk-66UDJBF6.js → chunk-REJGRCVQ.js} +2 -2
- package/dist/chunk-TDZE4TDG.js +220 -0
- package/dist/chunk-TDZE4TDG.js.map +1 -0
- package/dist/{chunk-CBLPAMZO.js → chunk-TMED5DQ2.js} +68 -42
- package/dist/chunk-TMED5DQ2.js.map +1 -0
- package/dist/{chunk-Q3J43SF3.js → chunk-U7HFKR74.js} +2 -2
- package/dist/chunk-U7HFKR74.js.map +1 -0
- package/dist/{chunk-3EHUF54X.js → chunk-UEMRJI2K.js} +17 -4
- package/dist/chunk-UEMRJI2K.js.map +1 -0
- package/dist/{chunk-Z2CWURZ6.js → chunk-UNN7523L.js} +2 -2
- package/dist/chunk-V2ZIH7HV.js +29 -0
- package/dist/chunk-V2ZIH7HV.js.map +1 -0
- package/dist/{chunk-ZEI3ZUDU.js → chunk-VVYNZZUX.js} +7 -15
- package/dist/chunk-VVYNZZUX.js.map +1 -0
- package/dist/{chunk-A46TPNBJ.js → chunk-XENOESJZ.js} +7 -16
- package/dist/chunk-XENOESJZ.js.map +1 -0
- package/dist/chunk-ZDREFYD2.js +696 -0
- package/dist/chunk-ZDREFYD2.js.map +1 -0
- package/dist/chunk-ZW2PELOH.js +197 -0
- package/dist/chunk-ZW2PELOH.js.map +1 -0
- package/dist/cli/defaults/agent-mappings.yaml +0 -1
- package/dist/commands/build/marketplace.js +22 -21
- package/dist/commands/build/marketplace.js.map +1 -1
- package/dist/commands/build/plugins.js +35 -231
- package/dist/commands/build/plugins.js.map +1 -1
- package/dist/commands/build/stack.js +11 -18
- package/dist/commands/build/stack.js.map +1 -1
- package/dist/commands/compile.js +36 -58
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/config/get.js +8 -8
- package/dist/commands/config/get.js.map +1 -1
- package/dist/commands/config/index.js +7 -7
- package/dist/commands/config/index.js.map +1 -1
- package/dist/commands/config/path.js +6 -6
- package/dist/commands/config/path.js.map +1 -1
- package/dist/commands/config/set-project.js +8 -8
- package/dist/commands/config/set-project.js.map +1 -1
- package/dist/commands/config/show.js +7 -7
- package/dist/commands/config/unset-project.js +8 -8
- package/dist/commands/config/unset-project.js.map +1 -1
- package/dist/commands/diff.js +10 -16
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/doctor.js +18 -51
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/edit.js +112 -57
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/eject.js +17 -49
- package/dist/commands/eject.js.map +1 -1
- package/dist/commands/import/skill.js +26 -26
- package/dist/commands/import/skill.js.map +1 -1
- package/dist/commands/info.js +15 -17
- package/dist/commands/info.js.map +1 -1
- package/dist/commands/init.js +103 -727
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/list.js +8 -87
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/new/agent.js +8 -12
- package/dist/commands/new/agent.js.map +1 -1
- package/dist/commands/new/skill.js +6 -6
- package/dist/commands/new/skill.js.map +1 -1
- package/dist/commands/outdated.js +15 -19
- package/dist/commands/outdated.js.map +1 -1
- package/dist/commands/search.js +21 -34
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/uninstall.js +15 -14
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.js +13 -24
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/validate.js +44 -487
- package/dist/commands/validate.js.map +1 -1
- package/dist/commands/version/bump.js +11 -11
- package/dist/commands/version/bump.js.map +1 -1
- package/dist/commands/version/index.js +9 -10
- package/dist/commands/version/index.js.map +1 -1
- package/dist/commands/version/set.js +10 -8
- package/dist/commands/version/set.js.map +1 -1
- package/dist/commands/version/show.js +9 -10
- package/dist/commands/version/show.js.map +1 -1
- package/dist/components/common/confirm.js +2 -2
- package/dist/components/common/confirm.test.js +203 -0
- package/dist/components/common/confirm.test.js.map +1 -0
- package/dist/components/common/message.js +1 -1
- package/dist/components/common/spinner.js +1 -1
- package/dist/components/common/spinner.js.map +1 -1
- package/dist/components/skill-search/skill-search.js +3 -3
- package/dist/components/wizard/category-grid.js +2 -2
- package/dist/components/wizard/category-grid.test.js +132 -78
- package/dist/components/wizard/category-grid.test.js.map +1 -1
- package/dist/components/wizard/menu-item.js +2 -2
- package/dist/components/wizard/search-modal.js +9 -0
- package/dist/components/wizard/search-modal.js.map +1 -0
- package/dist/components/wizard/search-modal.test.js +216 -0
- package/dist/components/wizard/search-modal.test.js.map +1 -0
- package/dist/components/wizard/section-progress.js +2 -2
- package/dist/components/wizard/section-progress.test.js +4 -4
- package/dist/components/wizard/section-progress.test.js.map +1 -1
- package/dist/components/wizard/source-grid.js +10 -0
- package/dist/components/wizard/source-grid.js.map +1 -0
- package/dist/components/wizard/source-grid.test.js +500 -0
- package/dist/components/wizard/source-grid.test.js.map +1 -0
- package/dist/components/wizard/step-approach.js +7 -6
- package/dist/components/wizard/step-approach.test.js +115 -0
- package/dist/components/wizard/step-approach.test.js.map +1 -0
- package/dist/components/wizard/step-build.js +9 -4
- package/dist/components/wizard/step-build.test.js +103 -122
- package/dist/components/wizard/step-build.test.js.map +1 -1
- package/dist/components/wizard/step-confirm.js +3 -2
- package/dist/components/wizard/step-confirm.test.js +364 -0
- package/dist/components/wizard/step-confirm.test.js.map +1 -0
- package/dist/components/wizard/step-refine.js +2 -2
- package/dist/components/wizard/step-refine.test.js +19 -13
- package/dist/components/wizard/step-refine.test.js.map +1 -1
- package/dist/components/wizard/step-settings.js +14 -0
- package/dist/components/wizard/step-settings.js.map +1 -0
- package/dist/components/wizard/step-settings.test.js +240 -0
- package/dist/components/wizard/step-settings.test.js.map +1 -0
- package/dist/components/wizard/step-sources.js +17 -0
- package/dist/components/wizard/step-sources.js.map +1 -0
- package/dist/components/wizard/step-sources.test.js +290 -0
- package/dist/components/wizard/step-sources.test.js.map +1 -0
- package/dist/components/wizard/step-stack.js +7 -6
- package/dist/components/wizard/step-stack.test.js +344 -0
- package/dist/components/wizard/step-stack.test.js.map +1 -0
- package/dist/components/wizard/view-title.js +2 -2
- package/dist/components/wizard/wizard-layout.js +6 -5
- package/dist/components/wizard/wizard-tabs.js +2 -2
- package/dist/components/wizard/wizard-tabs.test.js +292 -0
- package/dist/components/wizard/wizard-tabs.test.js.map +1 -0
- package/dist/components/wizard/wizard.js +22 -14
- package/dist/config/skills-matrix.yaml +38 -37
- package/dist/config/stacks.yaml +8 -14
- package/dist/hooks/init.js +5 -5
- package/dist/hooks/init.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/{magic-string.es-RGXYGAW3.js → magic-string.es-PAH2SOTR.js} +2 -2
- package/dist/source-manager-EYO3F2DV.js +16 -0
- package/dist/source-manager-EYO3F2DV.js.map +1 -0
- package/dist/src/agents/_templates/agent.liquid +1 -1
- package/dist/src/agents/developer/api-developer/agent.yaml +1 -1
- package/dist/src/agents/developer/cli-developer/agent.yaml +1 -1
- package/dist/src/agents/developer/web-architecture/agent.yaml +1 -1
- package/dist/src/agents/developer/web-developer/agent.yaml +1 -1
- package/dist/src/agents/meta/agent-summoner/agent.yaml +1 -1
- package/dist/src/agents/meta/documentor/agent.yaml +1 -1
- package/dist/src/agents/meta/skill-summoner/agent.yaml +1 -1
- package/dist/src/agents/migration/cli-migrator/agent.yaml +1 -1
- package/dist/src/agents/pattern/pattern-scout/agent.yaml +1 -1
- package/dist/src/agents/pattern/web-pattern-critique/agent.yaml +1 -1
- package/dist/src/agents/planning/web-pm/agent.yaml +1 -1
- package/dist/src/agents/researcher/api-researcher/agent.yaml +1 -1
- package/dist/src/agents/researcher/web-researcher/agent.yaml +1 -1
- package/dist/src/agents/reviewer/api-reviewer/agent.yaml +1 -1
- package/dist/src/agents/reviewer/cli-reviewer/agent.yaml +1 -1
- package/dist/src/agents/reviewer/web-reviewer/agent.yaml +1 -1
- package/dist/src/agents/tester/cli-tester/agent.yaml +1 -1
- package/dist/src/agents/tester/web-tester/agent.yaml +1 -1
- package/dist/stores/wizard-store.js +4 -3
- package/dist/stores/wizard-store.test.js +51 -82
- package/dist/stores/wizard-store.test.js.map +1 -1
- package/package.json +5 -3
- package/src/agents/_templates/agent.liquid +1 -1
- package/src/agents/developer/api-developer/agent.yaml +1 -1
- package/src/agents/developer/cli-developer/agent.yaml +1 -1
- package/src/agents/developer/web-architecture/agent.yaml +1 -1
- package/src/agents/developer/web-developer/agent.yaml +1 -1
- package/src/agents/meta/agent-summoner/agent.yaml +1 -1
- package/src/agents/meta/documentor/agent.yaml +1 -1
- package/src/agents/meta/skill-summoner/agent.yaml +1 -1
- package/src/agents/migration/cli-migrator/agent.yaml +1 -1
- package/src/agents/pattern/pattern-scout/agent.yaml +1 -1
- package/src/agents/pattern/web-pattern-critique/agent.yaml +1 -1
- package/src/agents/planning/web-pm/agent.yaml +1 -1
- package/src/agents/researcher/api-researcher/agent.yaml +1 -1
- package/src/agents/researcher/web-researcher/agent.yaml +1 -1
- package/src/agents/reviewer/api-reviewer/agent.yaml +1 -1
- package/src/agents/reviewer/cli-reviewer/agent.yaml +1 -1
- package/src/agents/reviewer/web-reviewer/agent.yaml +1 -1
- package/src/agents/tester/cli-tester/agent.yaml +1 -1
- package/src/agents/tester/web-tester/agent.yaml +1 -1
- package/dist/chunk-2LSGX6R4.js.map +0 -1
- package/dist/chunk-2OKUEELH.js +0 -32
- package/dist/chunk-2OKUEELH.js.map +0 -1
- package/dist/chunk-374JNMR6.js +0 -212
- package/dist/chunk-374JNMR6.js.map +0 -1
- package/dist/chunk-3EHUF54X.js.map +0 -1
- package/dist/chunk-3XR4PALU.js +0 -529
- package/dist/chunk-3XR4PALU.js.map +0 -1
- package/dist/chunk-5K2ZLUO5.js +0 -57
- package/dist/chunk-5K2ZLUO5.js.map +0 -1
- package/dist/chunk-5KXUDHAB.js.map +0 -1
- package/dist/chunk-6Q3Y7KVB.js.map +0 -1
- package/dist/chunk-7SLV7CMF.js +0 -615
- package/dist/chunk-7SLV7CMF.js.map +0 -1
- package/dist/chunk-A46TPNBJ.js.map +0 -1
- package/dist/chunk-AL74GBW4.js +0 -69
- package/dist/chunk-AL74GBW4.js.map +0 -1
- package/dist/chunk-BQX23RBV.js +0 -191
- package/dist/chunk-BQX23RBV.js.map +0 -1
- package/dist/chunk-CA4LH4LI.js +0 -132
- package/dist/chunk-CA4LH4LI.js.map +0 -1
- package/dist/chunk-CBLPAMZO.js.map +0 -1
- package/dist/chunk-CKPQHGXR.js +0 -417
- package/dist/chunk-CKPQHGXR.js.map +0 -1
- package/dist/chunk-CXOFOJCN.js +0 -80
- package/dist/chunk-CXOFOJCN.js.map +0 -1
- package/dist/chunk-EHGD7HIE.js +0 -104
- package/dist/chunk-EHGD7HIE.js.map +0 -1
- package/dist/chunk-EHS3TWWP.js +0 -95
- package/dist/chunk-EHS3TWWP.js.map +0 -1
- package/dist/chunk-FJFEKPXF.js.map +0 -1
- package/dist/chunk-HEOHU5EZ.js.map +0 -1
- package/dist/chunk-HGCBZUH5.js.map +0 -1
- package/dist/chunk-HPGFY5ZN.js +0 -114
- package/dist/chunk-HPGFY5ZN.js.map +0 -1
- package/dist/chunk-INJ2EFRW.js +0 -127
- package/dist/chunk-INJ2EFRW.js.map +0 -1
- package/dist/chunk-IOBFMF6X.js +0 -61
- package/dist/chunk-IOBFMF6X.js.map +0 -1
- package/dist/chunk-KH3HA7J7.js +0 -116
- package/dist/chunk-KH3HA7J7.js.map +0 -1
- package/dist/chunk-N6JNE326.js +0 -261
- package/dist/chunk-N6JNE326.js.map +0 -1
- package/dist/chunk-NAGU7TVZ.js +0 -36
- package/dist/chunk-NAGU7TVZ.js.map +0 -1
- package/dist/chunk-OQYYMQJR.js.map +0 -1
- package/dist/chunk-PLZOUVDD.js +0 -419
- package/dist/chunk-PLZOUVDD.js.map +0 -1
- package/dist/chunk-Q3J43SF3.js.map +0 -1
- package/dist/chunk-RTE64SJA.js.map +0 -1
- package/dist/chunk-T25OEQFI.js +0 -26
- package/dist/chunk-T25OEQFI.js.map +0 -1
- package/dist/chunk-UMORK7OK.js.map +0 -1
- package/dist/chunk-VFHWU7JU.js +0 -287
- package/dist/chunk-VFHWU7JU.js.map +0 -1
- package/dist/chunk-VS4GVTZE.js +0 -91
- package/dist/chunk-VS4GVTZE.js.map +0 -1
- package/dist/chunk-WFEFICFM.js.map +0 -1
- package/dist/chunk-WG6KIAPK.js +0 -54
- package/dist/chunk-WG6KIAPK.js.map +0 -1
- package/dist/chunk-ZEI3ZUDU.js.map +0 -1
- package/dist/chunk-ZNIDWLL5.js.map +0 -1
- package/dist/chunk-ZSVMS677.js.map +0 -1
- /package/dist/{chunk-XY3XDVMI.js.map → chunk-QR2EBWL2.js.map} +0 -0
- /package/dist/{chunk-66UDJBF6.js.map → chunk-REJGRCVQ.js.map} +0 -0
- /package/dist/{chunk-Z2CWURZ6.js.map → chunk-UNN7523L.js.map} +0 -0
- /package/dist/{magic-string.es-RGXYGAW3.js.map → magic-string.es-PAH2SOTR.js.map} +0 -0
package/dist/chunk-3XR4PALU.js
DELETED
|
@@ -1,529 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
ViewTitle
|
|
4
|
-
} from "./chunk-Q3J43SF3.js";
|
|
5
|
-
import {
|
|
6
|
-
CategoryGrid
|
|
7
|
-
} from "./chunk-OQYYMQJR.js";
|
|
8
|
-
import {
|
|
9
|
-
init_esm_shims
|
|
10
|
-
} from "./chunk-DHET7RCE.js";
|
|
11
|
-
|
|
12
|
-
// src/cli/components/wizard/step-build.tsx
|
|
13
|
-
init_esm_shims();
|
|
14
|
-
import { useState } from "react";
|
|
15
|
-
import { Box, Text, useInput } from "ink";
|
|
16
|
-
|
|
17
|
-
// src/cli/lib/matrix-resolver.ts
|
|
18
|
-
init_esm_shims();
|
|
19
|
-
function resolveAlias(aliasOrId, matrix) {
|
|
20
|
-
return matrix.aliases[aliasOrId] || aliasOrId;
|
|
21
|
-
}
|
|
22
|
-
function isDisabled(skillId, currentSelections, matrix, options) {
|
|
23
|
-
if (options?.expertMode) {
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
const fullId = resolveAlias(skillId, matrix);
|
|
27
|
-
const skill = matrix.skills[fullId];
|
|
28
|
-
if (!skill) {
|
|
29
|
-
return false;
|
|
30
|
-
}
|
|
31
|
-
for (const selectedId of currentSelections) {
|
|
32
|
-
const selectedFullId = resolveAlias(selectedId, matrix);
|
|
33
|
-
if (skill.conflictsWith.some((c) => c.skillId === selectedFullId)) {
|
|
34
|
-
return true;
|
|
35
|
-
}
|
|
36
|
-
const selectedSkill = matrix.skills[selectedFullId];
|
|
37
|
-
if (selectedSkill && selectedSkill.conflictsWith.some((c) => c.skillId === fullId)) {
|
|
38
|
-
return true;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
const resolvedSelections = currentSelections.map((s) => resolveAlias(s, matrix));
|
|
42
|
-
for (const requirement of skill.requires) {
|
|
43
|
-
if (requirement.needsAny) {
|
|
44
|
-
const hasAny = requirement.skillIds.some((reqId) => resolvedSelections.includes(reqId));
|
|
45
|
-
if (!hasAny) {
|
|
46
|
-
return true;
|
|
47
|
-
}
|
|
48
|
-
} else {
|
|
49
|
-
const hasAll = requirement.skillIds.every((reqId) => resolvedSelections.includes(reqId));
|
|
50
|
-
if (!hasAll) {
|
|
51
|
-
return true;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
function getDisableReason(skillId, currentSelections, matrix) {
|
|
58
|
-
const fullId = resolveAlias(skillId, matrix);
|
|
59
|
-
const skill = matrix.skills[fullId];
|
|
60
|
-
if (!skill) {
|
|
61
|
-
return void 0;
|
|
62
|
-
}
|
|
63
|
-
const resolvedSelections = currentSelections.map((s) => resolveAlias(s, matrix));
|
|
64
|
-
for (const selectedId of resolvedSelections) {
|
|
65
|
-
const conflict = skill.conflictsWith.find((c) => c.skillId === selectedId);
|
|
66
|
-
if (conflict) {
|
|
67
|
-
const selectedSkill2 = matrix.skills[selectedId];
|
|
68
|
-
const selectedName = selectedSkill2?.name || selectedId;
|
|
69
|
-
return `${conflict.reason} (conflicts with ${selectedName})`;
|
|
70
|
-
}
|
|
71
|
-
const selectedSkill = matrix.skills[selectedId];
|
|
72
|
-
if (selectedSkill) {
|
|
73
|
-
const reverseConflict = selectedSkill.conflictsWith.find((c) => c.skillId === fullId);
|
|
74
|
-
if (reverseConflict) {
|
|
75
|
-
const selectedName = selectedSkill.name;
|
|
76
|
-
return `${reverseConflict.reason} (conflicts with ${selectedName})`;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
for (const requirement of skill.requires) {
|
|
81
|
-
if (requirement.needsAny) {
|
|
82
|
-
const hasAny = requirement.skillIds.some((reqId) => resolvedSelections.includes(reqId));
|
|
83
|
-
if (!hasAny) {
|
|
84
|
-
const requiredNames = requirement.skillIds.map((id) => matrix.skills[id]?.name || id).join(" or ");
|
|
85
|
-
return `${requirement.reason} (requires ${requiredNames})`;
|
|
86
|
-
}
|
|
87
|
-
} else {
|
|
88
|
-
const missingIds = requirement.skillIds.filter(
|
|
89
|
-
(reqId) => !resolvedSelections.includes(reqId)
|
|
90
|
-
);
|
|
91
|
-
if (missingIds.length > 0) {
|
|
92
|
-
const missingNames = missingIds.map((id) => matrix.skills[id]?.name || id).join(", ");
|
|
93
|
-
return `${requirement.reason} (requires ${missingNames})`;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return void 0;
|
|
98
|
-
}
|
|
99
|
-
function isDiscouraged(skillId, currentSelections, matrix) {
|
|
100
|
-
const fullId = resolveAlias(skillId, matrix);
|
|
101
|
-
const skill = matrix.skills[fullId];
|
|
102
|
-
if (!skill) {
|
|
103
|
-
return false;
|
|
104
|
-
}
|
|
105
|
-
const resolvedSelections = currentSelections.map((s) => resolveAlias(s, matrix));
|
|
106
|
-
for (const selectedId of resolvedSelections) {
|
|
107
|
-
const selectedSkill = matrix.skills[selectedId];
|
|
108
|
-
if (selectedSkill && selectedSkill.discourages.some((d) => d.skillId === fullId)) {
|
|
109
|
-
return true;
|
|
110
|
-
}
|
|
111
|
-
if (skill.discourages.some((d) => d.skillId === selectedId)) {
|
|
112
|
-
return true;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
return false;
|
|
116
|
-
}
|
|
117
|
-
function getDiscourageReason(skillId, currentSelections, matrix) {
|
|
118
|
-
const fullId = resolveAlias(skillId, matrix);
|
|
119
|
-
const skill = matrix.skills[fullId];
|
|
120
|
-
if (!skill) {
|
|
121
|
-
return void 0;
|
|
122
|
-
}
|
|
123
|
-
const resolvedSelections = currentSelections.map((s) => resolveAlias(s, matrix));
|
|
124
|
-
for (const selectedId of resolvedSelections) {
|
|
125
|
-
const selectedSkill = matrix.skills[selectedId];
|
|
126
|
-
if (selectedSkill) {
|
|
127
|
-
const discourage = selectedSkill.discourages.find((d) => d.skillId === fullId);
|
|
128
|
-
if (discourage) {
|
|
129
|
-
return discourage.reason;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
const reverseDiscourage = skill.discourages.find((d) => d.skillId === selectedId);
|
|
133
|
-
if (reverseDiscourage) {
|
|
134
|
-
return reverseDiscourage.reason;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
return void 0;
|
|
138
|
-
}
|
|
139
|
-
function isRecommended(skillId, currentSelections, matrix) {
|
|
140
|
-
const fullId = resolveAlias(skillId, matrix);
|
|
141
|
-
const skill = matrix.skills[fullId];
|
|
142
|
-
if (!skill) {
|
|
143
|
-
return false;
|
|
144
|
-
}
|
|
145
|
-
const resolvedSelections = currentSelections.map((s) => resolveAlias(s, matrix));
|
|
146
|
-
for (const selectedId of resolvedSelections) {
|
|
147
|
-
const selectedSkill = matrix.skills[selectedId];
|
|
148
|
-
if (selectedSkill && selectedSkill.recommends.some((r) => r.skillId === fullId)) {
|
|
149
|
-
return true;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
return false;
|
|
153
|
-
}
|
|
154
|
-
function getRecommendReason(skillId, currentSelections, matrix) {
|
|
155
|
-
const fullId = resolveAlias(skillId, matrix);
|
|
156
|
-
const skill = matrix.skills[fullId];
|
|
157
|
-
if (!skill) {
|
|
158
|
-
return void 0;
|
|
159
|
-
}
|
|
160
|
-
const resolvedSelections = currentSelections.map((s) => resolveAlias(s, matrix));
|
|
161
|
-
for (const selectedId of resolvedSelections) {
|
|
162
|
-
const selectedSkill = matrix.skills[selectedId];
|
|
163
|
-
if (selectedSkill) {
|
|
164
|
-
const recommendation = selectedSkill.recommends.find((r) => r.skillId === fullId);
|
|
165
|
-
if (recommendation) {
|
|
166
|
-
return `${recommendation.reason} (recommended by ${selectedSkill.name})`;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
return void 0;
|
|
171
|
-
}
|
|
172
|
-
function validateSelection(selections, matrix) {
|
|
173
|
-
const errors = [];
|
|
174
|
-
const warnings = [];
|
|
175
|
-
const resolvedSelections = selections.map((s) => resolveAlias(s, matrix));
|
|
176
|
-
for (let i = 0; i < resolvedSelections.length; i++) {
|
|
177
|
-
const skillA = matrix.skills[resolvedSelections[i]];
|
|
178
|
-
if (!skillA) continue;
|
|
179
|
-
for (let j = i + 1; j < resolvedSelections.length; j++) {
|
|
180
|
-
const skillBId = resolvedSelections[j];
|
|
181
|
-
const conflict = skillA.conflictsWith.find((c) => c.skillId === skillBId);
|
|
182
|
-
if (conflict) {
|
|
183
|
-
errors.push({
|
|
184
|
-
type: "conflict",
|
|
185
|
-
message: `${skillA.name} conflicts with ${matrix.skills[skillBId]?.name || skillBId}: ${conflict.reason}`,
|
|
186
|
-
skills: [skillA.id, skillBId]
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
for (const skillId of resolvedSelections) {
|
|
192
|
-
const skill = matrix.skills[skillId];
|
|
193
|
-
if (!skill) continue;
|
|
194
|
-
for (const requirement of skill.requires) {
|
|
195
|
-
if (requirement.needsAny) {
|
|
196
|
-
const hasAny = requirement.skillIds.some((reqId) => resolvedSelections.includes(reqId));
|
|
197
|
-
if (!hasAny) {
|
|
198
|
-
errors.push({
|
|
199
|
-
type: "missing_requirement",
|
|
200
|
-
message: `${skill.name} requires one of: ${requirement.skillIds.map((id) => matrix.skills[id]?.name || id).join(", ")}`,
|
|
201
|
-
skills: [skillId, ...requirement.skillIds]
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
} else {
|
|
205
|
-
const missingIds = requirement.skillIds.filter(
|
|
206
|
-
(reqId) => !resolvedSelections.includes(reqId)
|
|
207
|
-
);
|
|
208
|
-
if (missingIds.length > 0) {
|
|
209
|
-
errors.push({
|
|
210
|
-
type: "missing_requirement",
|
|
211
|
-
message: `${skill.name} requires: ${missingIds.map((id) => matrix.skills[id]?.name || id).join(", ")}`,
|
|
212
|
-
skills: [skillId, ...missingIds]
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
const categorySelections = /* @__PURE__ */ new Map();
|
|
219
|
-
for (const skillId of resolvedSelections) {
|
|
220
|
-
const skill = matrix.skills[skillId];
|
|
221
|
-
if (!skill) continue;
|
|
222
|
-
const existing = categorySelections.get(skill.category) || [];
|
|
223
|
-
existing.push(skillId);
|
|
224
|
-
categorySelections.set(skill.category, existing);
|
|
225
|
-
}
|
|
226
|
-
for (const [categoryId, skillIds] of categorySelections.entries()) {
|
|
227
|
-
if (skillIds.length > 1) {
|
|
228
|
-
const category = matrix.categories[categoryId];
|
|
229
|
-
if (category?.exclusive) {
|
|
230
|
-
errors.push({
|
|
231
|
-
type: "category_exclusive",
|
|
232
|
-
message: `Category "${category.name}" only allows one selection, but multiple selected: ${skillIds.map((id) => matrix.skills[id]?.name || id).join(", ")}`,
|
|
233
|
-
skills: skillIds
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
for (const skillId of resolvedSelections) {
|
|
239
|
-
const skill = matrix.skills[skillId];
|
|
240
|
-
if (!skill) continue;
|
|
241
|
-
for (const recommendation of skill.recommends) {
|
|
242
|
-
if (!resolvedSelections.includes(recommendation.skillId)) {
|
|
243
|
-
const recommendedSkill = matrix.skills[recommendation.skillId];
|
|
244
|
-
if (recommendedSkill) {
|
|
245
|
-
const hasConflict = recommendedSkill.conflictsWith.some(
|
|
246
|
-
(c) => resolvedSelections.includes(c.skillId)
|
|
247
|
-
);
|
|
248
|
-
if (!hasConflict) {
|
|
249
|
-
warnings.push({
|
|
250
|
-
type: "missing_recommendation",
|
|
251
|
-
message: `${skill.name} recommends ${recommendedSkill.name}: ${recommendation.reason}`,
|
|
252
|
-
skills: [skillId, recommendation.skillId]
|
|
253
|
-
});
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
for (const skillId of resolvedSelections) {
|
|
260
|
-
const skill = matrix.skills[skillId];
|
|
261
|
-
if (!skill || skill.providesSetupFor.length === 0) continue;
|
|
262
|
-
const hasUsageSkill = skill.providesSetupFor.some(
|
|
263
|
-
(usageId) => resolvedSelections.includes(usageId)
|
|
264
|
-
);
|
|
265
|
-
if (!hasUsageSkill) {
|
|
266
|
-
warnings.push({
|
|
267
|
-
type: "unused_setup",
|
|
268
|
-
message: `Setup skill "${skill.name}" selected but no corresponding usage skills: ${skill.providesSetupFor.map((id) => matrix.skills[id]?.name || id).join(", ")}`,
|
|
269
|
-
skills: [skillId, ...skill.providesSetupFor]
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
return {
|
|
274
|
-
valid: errors.length === 0,
|
|
275
|
-
errors,
|
|
276
|
-
warnings
|
|
277
|
-
};
|
|
278
|
-
}
|
|
279
|
-
function getAvailableSkills(categoryId, currentSelections, matrix, options) {
|
|
280
|
-
const skillOptions = [];
|
|
281
|
-
const resolvedSelections = currentSelections.map((s) => resolveAlias(s, matrix));
|
|
282
|
-
for (const skill of Object.values(matrix.skills)) {
|
|
283
|
-
if (skill.category !== categoryId) {
|
|
284
|
-
continue;
|
|
285
|
-
}
|
|
286
|
-
const disabled = isDisabled(skill.id, currentSelections, matrix, options);
|
|
287
|
-
const discouraged = !disabled && isDiscouraged(skill.id, currentSelections, matrix);
|
|
288
|
-
const recommended = !disabled && !discouraged && isRecommended(skill.id, currentSelections, matrix);
|
|
289
|
-
skillOptions.push({
|
|
290
|
-
id: skill.id,
|
|
291
|
-
alias: skill.alias,
|
|
292
|
-
name: skill.name,
|
|
293
|
-
description: skill.description,
|
|
294
|
-
disabled,
|
|
295
|
-
disabledReason: disabled ? getDisableReason(skill.id, currentSelections, matrix) : void 0,
|
|
296
|
-
discouraged,
|
|
297
|
-
discouragedReason: discouraged ? getDiscourageReason(skill.id, currentSelections, matrix) : void 0,
|
|
298
|
-
recommended,
|
|
299
|
-
recommendedReason: recommended ? getRecommendReason(skill.id, currentSelections, matrix) : void 0,
|
|
300
|
-
selected: resolvedSelections.includes(skill.id),
|
|
301
|
-
alternatives: skill.alternatives.map((a) => a.skillId)
|
|
302
|
-
});
|
|
303
|
-
}
|
|
304
|
-
return skillOptions;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
// src/cli/components/wizard/utils.ts
|
|
308
|
-
init_esm_shims();
|
|
309
|
-
function getDomainDisplayName(domain) {
|
|
310
|
-
const displayNames = {
|
|
311
|
-
web: "Web",
|
|
312
|
-
"web-extras": "Web Extras",
|
|
313
|
-
api: "API",
|
|
314
|
-
cli: "CLI",
|
|
315
|
-
mobile: "Mobile",
|
|
316
|
-
shared: "Shared"
|
|
317
|
-
};
|
|
318
|
-
return displayNames[domain] || domain.charAt(0).toUpperCase() + domain.slice(1);
|
|
319
|
-
}
|
|
320
|
-
function getStackName(stackId, matrix) {
|
|
321
|
-
if (!stackId) return void 0;
|
|
322
|
-
const stack = matrix.suggestedStacks.find((s) => s.id === stackId);
|
|
323
|
-
return stack?.name;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
// src/cli/components/wizard/step-build.tsx
|
|
327
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
328
|
-
var FRAMEWORK_SUBCATEGORY_ID = "framework";
|
|
329
|
-
var WEB_DOMAIN_ID = "web";
|
|
330
|
-
function validateBuildStep(categories, selections) {
|
|
331
|
-
for (const category of categories) {
|
|
332
|
-
if (category.required) {
|
|
333
|
-
const categorySelections = selections[category.id] || [];
|
|
334
|
-
if (categorySelections.length === 0) {
|
|
335
|
-
return {
|
|
336
|
-
valid: false,
|
|
337
|
-
message: `Please select a ${category.name}`
|
|
338
|
-
};
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
return { valid: true };
|
|
343
|
-
}
|
|
344
|
-
function computeOptionState(skill) {
|
|
345
|
-
if (skill.disabled) {
|
|
346
|
-
return "disabled";
|
|
347
|
-
}
|
|
348
|
-
if (skill.discouraged) {
|
|
349
|
-
return "discouraged";
|
|
350
|
-
}
|
|
351
|
-
if (skill.recommended) {
|
|
352
|
-
return "recommended";
|
|
353
|
-
}
|
|
354
|
-
return "normal";
|
|
355
|
-
}
|
|
356
|
-
function getDisplayLabel(skill) {
|
|
357
|
-
const authorPattern = /\s*\(@[^)]+\)\s*$/;
|
|
358
|
-
return skill.name.replace(authorPattern, "");
|
|
359
|
-
}
|
|
360
|
-
function getStateReason(skill) {
|
|
361
|
-
if (skill.disabled && skill.disabledReason) {
|
|
362
|
-
return skill.disabledReason;
|
|
363
|
-
}
|
|
364
|
-
if (skill.discouraged && skill.discouragedReason) {
|
|
365
|
-
return skill.discouragedReason;
|
|
366
|
-
}
|
|
367
|
-
if (skill.recommended && skill.recommendedReason) {
|
|
368
|
-
return skill.recommendedReason;
|
|
369
|
-
}
|
|
370
|
-
return void 0;
|
|
371
|
-
}
|
|
372
|
-
function isFrameworkSelected(selections) {
|
|
373
|
-
const frameworkSelections = selections[FRAMEWORK_SUBCATEGORY_ID] ?? [];
|
|
374
|
-
return frameworkSelections.length > 0;
|
|
375
|
-
}
|
|
376
|
-
function getSelectedFrameworks(selections, matrix) {
|
|
377
|
-
const frameworkSelections = selections[FRAMEWORK_SUBCATEGORY_ID] ?? [];
|
|
378
|
-
return frameworkSelections.map((alias) => {
|
|
379
|
-
return matrix.aliases[alias] ?? alias;
|
|
380
|
-
});
|
|
381
|
-
}
|
|
382
|
-
function isCompatibleWithSelectedFrameworks(skillId, selectedFrameworkIds, matrix) {
|
|
383
|
-
const skill = matrix.skills[skillId];
|
|
384
|
-
if (!skill) return false;
|
|
385
|
-
if (skill.compatibleWith.length === 0) {
|
|
386
|
-
return true;
|
|
387
|
-
}
|
|
388
|
-
return selectedFrameworkIds.some((frameworkId) => skill.compatibleWith.includes(frameworkId));
|
|
389
|
-
}
|
|
390
|
-
function shouldShowSubcategory(_subcategoryId, _domain, _frameworkSelected) {
|
|
391
|
-
return true;
|
|
392
|
-
}
|
|
393
|
-
function buildCategoriesForDomain(domain, allSelections, matrix, expertMode, selections, parentDomainSelections) {
|
|
394
|
-
const frameworkSource = parentDomainSelections ?? selections;
|
|
395
|
-
const frameworkSelected = isFrameworkSelected(frameworkSource);
|
|
396
|
-
const selectedFrameworkIds = frameworkSelected ? getSelectedFrameworks(frameworkSource, matrix) : [];
|
|
397
|
-
const subcategories = Object.values(matrix.categories).filter((cat) => cat.domain === domain).sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
|
|
398
|
-
const visibleSubcategories = subcategories.filter(
|
|
399
|
-
(cat) => shouldShowSubcategory(cat.id, domain, frameworkSelected)
|
|
400
|
-
);
|
|
401
|
-
const categoryRows = visibleSubcategories.map((cat) => {
|
|
402
|
-
const skillOptions = getAvailableSkills(cat.id, allSelections, matrix, {
|
|
403
|
-
expertMode
|
|
404
|
-
});
|
|
405
|
-
const useFrameworkFilter = (domain === WEB_DOMAIN_ID || parentDomainSelections !== void 0) && cat.id !== FRAMEWORK_SUBCATEGORY_ID && frameworkSelected;
|
|
406
|
-
const filteredSkillOptions = useFrameworkFilter ? skillOptions.filter(
|
|
407
|
-
(skill) => isCompatibleWithSelectedFrameworks(skill.id, selectedFrameworkIds, matrix)
|
|
408
|
-
) : skillOptions;
|
|
409
|
-
const options = filteredSkillOptions.map((skill) => ({
|
|
410
|
-
id: skill.id,
|
|
411
|
-
label: getDisplayLabel(skill),
|
|
412
|
-
// Clean display name without author
|
|
413
|
-
state: computeOptionState(skill),
|
|
414
|
-
stateReason: getStateReason(skill),
|
|
415
|
-
selected: skill.selected,
|
|
416
|
-
local: matrix.skills[skill.id]?.local
|
|
417
|
-
}));
|
|
418
|
-
return {
|
|
419
|
-
id: cat.id,
|
|
420
|
-
name: cat.name,
|
|
421
|
-
required: cat.required ?? false,
|
|
422
|
-
exclusive: cat.exclusive ?? true,
|
|
423
|
-
options
|
|
424
|
-
};
|
|
425
|
-
});
|
|
426
|
-
return categoryRows.filter((row) => row.options.length > 0);
|
|
427
|
-
}
|
|
428
|
-
var Footer = ({ validationError }) => {
|
|
429
|
-
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 1, children: validationError && /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { color: "yellow", children: validationError }) }) });
|
|
430
|
-
};
|
|
431
|
-
var LegendRow = () => {
|
|
432
|
-
return /* @__PURE__ */ jsxs(Box, { paddingLeft: 1, columnGap: 2, children: [
|
|
433
|
-
/* @__PURE__ */ jsx(Text, { color: "cyan", children: "active" }),
|
|
434
|
-
/* @__PURE__ */ jsx(Text, { color: "#fff", children: "recommended" }),
|
|
435
|
-
/* @__PURE__ */ jsx(Text, { color: "yellow", children: "discouraged" }),
|
|
436
|
-
/* @__PURE__ */ jsx(Text, { color: "gray", children: "disabled" })
|
|
437
|
-
] });
|
|
438
|
-
};
|
|
439
|
-
var StepBuild = ({
|
|
440
|
-
matrix,
|
|
441
|
-
domain: activeDomain,
|
|
442
|
-
selectedDomains,
|
|
443
|
-
selections,
|
|
444
|
-
allSelections,
|
|
445
|
-
focusedRow,
|
|
446
|
-
focusedCol,
|
|
447
|
-
showDescriptions,
|
|
448
|
-
expertMode,
|
|
449
|
-
parentDomainSelections,
|
|
450
|
-
onToggle,
|
|
451
|
-
onFocusChange,
|
|
452
|
-
onToggleDescriptions,
|
|
453
|
-
onContinue,
|
|
454
|
-
onBack
|
|
455
|
-
}) => {
|
|
456
|
-
const [validationError, setValidationError] = useState(void 0);
|
|
457
|
-
const categories = buildCategoriesForDomain(
|
|
458
|
-
activeDomain,
|
|
459
|
-
allSelections,
|
|
460
|
-
matrix,
|
|
461
|
-
expertMode,
|
|
462
|
-
selections,
|
|
463
|
-
parentDomainSelections
|
|
464
|
-
);
|
|
465
|
-
useInput((_input, key) => {
|
|
466
|
-
if (key.return) {
|
|
467
|
-
const validation = validateBuildStep(categories, selections);
|
|
468
|
-
if (validation.valid) {
|
|
469
|
-
setValidationError(void 0);
|
|
470
|
-
onContinue();
|
|
471
|
-
} else {
|
|
472
|
-
setValidationError(validation.message);
|
|
473
|
-
}
|
|
474
|
-
} else if (key.escape) {
|
|
475
|
-
setValidationError(void 0);
|
|
476
|
-
onBack();
|
|
477
|
-
}
|
|
478
|
-
});
|
|
479
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", width: "100%", children: [
|
|
480
|
-
/* @__PURE__ */ jsxs(
|
|
481
|
-
Box,
|
|
482
|
-
{
|
|
483
|
-
columnGap: 2,
|
|
484
|
-
flexDirection: "row",
|
|
485
|
-
justifyContent: "space-between",
|
|
486
|
-
marginBottom: 1,
|
|
487
|
-
paddingRight: 1,
|
|
488
|
-
marginTop: -1,
|
|
489
|
-
borderTop: false,
|
|
490
|
-
borderRight: false,
|
|
491
|
-
borderLeft: false,
|
|
492
|
-
borderColor: "gray",
|
|
493
|
-
borderStyle: "single",
|
|
494
|
-
children: [
|
|
495
|
-
/* @__PURE__ */ jsx(Box, { columnGap: 2, flexDirection: "row", children: selectedDomains.map((domain) => /* @__PURE__ */ jsx(Text, { color: domain === activeDomain ? "cyan" : void 0, children: getDomainDisplayName(domain) }, domain)) }),
|
|
496
|
-
/* @__PURE__ */ jsx(LegendRow, {})
|
|
497
|
-
]
|
|
498
|
-
}
|
|
499
|
-
),
|
|
500
|
-
/* @__PURE__ */ jsxs(ViewTitle, { children: [
|
|
501
|
-
"Customise your ",
|
|
502
|
-
getDomainDisplayName(activeDomain),
|
|
503
|
-
" stack"
|
|
504
|
-
] }),
|
|
505
|
-
/* @__PURE__ */ jsx(
|
|
506
|
-
CategoryGrid,
|
|
507
|
-
{
|
|
508
|
-
categories,
|
|
509
|
-
focusedRow,
|
|
510
|
-
focusedCol,
|
|
511
|
-
expertMode,
|
|
512
|
-
showDescriptions,
|
|
513
|
-
onToggle,
|
|
514
|
-
onFocusChange,
|
|
515
|
-
onToggleDescriptions
|
|
516
|
-
}
|
|
517
|
-
),
|
|
518
|
-
/* @__PURE__ */ jsx(Footer, { validationError })
|
|
519
|
-
] });
|
|
520
|
-
};
|
|
521
|
-
|
|
522
|
-
export {
|
|
523
|
-
validateSelection,
|
|
524
|
-
getStackName,
|
|
525
|
-
validateBuildStep,
|
|
526
|
-
getDisplayLabel,
|
|
527
|
-
StepBuild
|
|
528
|
-
};
|
|
529
|
-
//# sourceMappingURL=chunk-3XR4PALU.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/components/wizard/step-build.tsx","../src/cli/lib/matrix-resolver.ts","../src/cli/components/wizard/utils.ts"],"sourcesContent":["/**\n * StepBuild component - Main Build step for domain-based technology selection.\n *\n * Uses CategoryGrid for 2D grid selection and SectionProgress for multi-domain\n * progress indication. Replaces the old linear category->subcategory flow.\n *\n * This component is stateless - all state is managed via props from the parent\n * wizard component, following React's controlled component pattern.\n */\nimport React, { useState } from \"react\";\nimport { Box, Text, useInput } from \"ink\";\nimport type { MergedSkillsMatrix } from \"../../types-matrix.js\";\nimport { getAvailableSkills } from \"../../lib/matrix-resolver.js\";\nimport {\n CategoryGrid,\n type CategoryRow,\n type CategoryOption,\n type OptionState,\n} from \"./category-grid.js\";\nimport { ViewTitle } from \"./view-title.js\";\nimport { getDomainDisplayName } from \"./utils.js\";\n\n// Types\n\nexport interface StepBuildProps {\n /** Skills matrix for category/skill lookup */\n matrix: MergedSkillsMatrix;\n /** Current domain being configured (e.g., 'web', 'api') */\n domain: string;\n /** All selected domains (for progress indicator) */\n selectedDomains: string[];\n /** Current selections by subcategory */\n selections: Record<string, string[]>;\n /** All current selections (for state calculation across domains) */\n allSelections: string[];\n /** Grid focus state */\n focusedRow: number;\n focusedCol: number;\n /** UI toggles */\n showDescriptions: boolean;\n expertMode: boolean;\n /** Parent domain selections for framework-first filtering on sub-domains (e.g., web-extras inherits from web) */\n parentDomainSelections?: Record<string, string[]>;\n /** Callbacks */\n onToggle: (subcategoryId: string, technologyId: string) => void;\n onFocusChange: (row: number, col: number) => void;\n onToggleDescriptions: () => void;\n onContinue: () => void;\n onBack: () => void;\n}\n\n// Constants\n\n/** Framework subcategory ID for web domain (framework-first filtering) */\nconst FRAMEWORK_SUBCATEGORY_ID = \"framework\";\n\n/** Web domain ID where framework-first flow applies */\nconst WEB_DOMAIN_ID = \"web\";\n\n// Validation\n\nexport interface BuildStepValidation {\n valid: boolean;\n message?: string;\n}\n\n/**\n * Validate that required categories have at least one selection.\n */\nexport function validateBuildStep(\n categories: CategoryRow[],\n selections: Record<string, string[]>,\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: false,\n message: `Please select a ${category.name}`,\n };\n }\n }\n }\n return { valid: true };\n}\n\n// Helper Functions\n\n/**\n * Compute option state from skill flags.\n */\nfunction computeOptionState(skill: {\n disabled: boolean;\n discouraged: boolean;\n recommended: boolean;\n}): OptionState {\n if (skill.disabled) {\n return \"disabled\";\n }\n if (skill.discouraged) {\n return \"discouraged\";\n }\n if (skill.recommended) {\n return \"recommended\";\n }\n return \"normal\";\n}\n\n/**\n * Get clean display label for a skill option.\n * Uses name with author suffix stripped for accurate display.\n * e.g., \"React (@vince)\" -> \"React\", \"SCSS Modules (@vince)\" -> \"SCSS Modules\"\n */\nexport function getDisplayLabel(skill: { alias?: string; name: string }): string {\n // Strip author suffix like \" (@vince)\" from name\n // This preserves the original capitalization (e.g., \"SCSS Modules\" stays as-is)\n const authorPattern = /\\s*\\(@[^)]+\\)\\s*$/;\n return skill.name.replace(authorPattern, \"\");\n}\n\n/**\n * Get state reason from skill flags.\n */\nfunction getStateReason(skill: {\n disabled: boolean;\n disabledReason?: string;\n discouraged: boolean;\n discouragedReason?: string;\n recommended: boolean;\n recommendedReason?: string;\n}): string | undefined {\n if (skill.disabled && skill.disabledReason) {\n return skill.disabledReason;\n }\n if (skill.discouraged && skill.discouragedReason) {\n return skill.discouragedReason;\n }\n if (skill.recommended && skill.recommendedReason) {\n return skill.recommendedReason;\n }\n return undefined;\n}\n\n// Framework-First Flow (Web Domain)\n\n/**\n * Check if a framework is selected in the current selections.\n * Framework skills are in the \"framework\" subcategory.\n */\nfunction isFrameworkSelected(selections: Record<string, string[]>): boolean {\n const frameworkSelections = selections[FRAMEWORK_SUBCATEGORY_ID] ?? [];\n return frameworkSelections.length > 0;\n}\n\n/**\n * Get the selected framework skill ID(s) from selections.\n * Returns the full skill IDs (e.g., \"web-framework-react\").\n */\nfunction getSelectedFrameworks(\n selections: Record<string, string[]>,\n matrix: MergedSkillsMatrix,\n): string[] {\n const frameworkSelections = selections[FRAMEWORK_SUBCATEGORY_ID] ?? [];\n // Resolve aliases to full skill IDs\n return frameworkSelections.map((alias) => {\n return matrix.aliases[alias] ?? alias;\n });\n}\n\n/**\n * Check if a skill is compatible with any of the selected frameworks.\n * Uses the skill's compatibleWith field from metadata.\n */\nfunction isCompatibleWithSelectedFrameworks(\n skillId: string,\n selectedFrameworkIds: string[],\n matrix: MergedSkillsMatrix,\n): boolean {\n const skill = matrix.skills[skillId];\n if (!skill) return false;\n\n // If skill has no compatibleWith defined, assume it's compatible with all\n // (this allows legacy skills without metadata to still appear)\n if (skill.compatibleWith.length === 0) {\n return true;\n }\n\n // Check if any selected framework is in the skill's compatibleWith list\n return selectedFrameworkIds.some((frameworkId) => skill.compatibleWith.includes(frameworkId));\n}\n\n/**\n * Determine if a subcategory should be shown based on framework-first flow.\n *\n * IMPORTANT: All sections are ALWAYS visible. The \"locked\" state in CategoryGrid\n * handles dimming and preventing navigation until a framework is selected.\n * We do NOT hide sections.\n */\nfunction shouldShowSubcategory(\n _subcategoryId: string,\n _domain: string,\n _frameworkSelected: boolean,\n): boolean {\n // All sections are always visible\n // Locking (dimming + preventing navigation) is handled by CategoryGrid\n return true;\n}\n\n/**\n * Build CategoryRow[] from matrix for a specific domain.\n *\n * Filters subcategories by domain and builds options using getAvailableSkills.\n * For web domain, implements framework-first flow:\n * - Initially shows only \"framework\" subcategory\n * - After framework selection, shows skills compatible with selected framework\n */\nfunction buildCategoriesForDomain(\n domain: string,\n allSelections: string[],\n matrix: MergedSkillsMatrix,\n expertMode: boolean,\n selections: Record<string, string[]>,\n parentDomainSelections?: Record<string, string[]>,\n): CategoryRow[] {\n // Check framework selection for framework-first flow\n // For sub-domains (e.g., web-extras), use parent domain selections for framework checks\n const frameworkSource = parentDomainSelections ?? selections;\n const frameworkSelected = isFrameworkSelected(frameworkSource);\n const selectedFrameworkIds = frameworkSelected\n ? getSelectedFrameworks(frameworkSource, matrix)\n : [];\n\n // Get categories for the current domain\n const subcategories = Object.values(matrix.categories)\n .filter((cat) => cat.domain === domain)\n .sort((a, b) => (a.order ?? 0) - (b.order ?? 0));\n\n // Filter subcategories based on framework-first flow\n const visibleSubcategories = subcategories.filter((cat) =>\n shouldShowSubcategory(cat.id, domain, frameworkSelected),\n );\n\n // Build CategoryRow for each visible subcategory\n const categoryRows: CategoryRow[] = visibleSubcategories.map((cat) => {\n // Get available skills with computed states\n const skillOptions = getAvailableSkills(cat.id, allSelections, matrix, {\n expertMode,\n });\n\n // For web domain or sub-domains with parent selections, filter by framework compatibility\n // Framework category itself doesn't need filtering\n const useFrameworkFilter =\n (domain === WEB_DOMAIN_ID || parentDomainSelections !== undefined) &&\n cat.id !== FRAMEWORK_SUBCATEGORY_ID &&\n frameworkSelected;\n const filteredSkillOptions = useFrameworkFilter\n ? skillOptions.filter((skill) =>\n isCompatibleWithSelectedFrameworks(skill.id, selectedFrameworkIds, matrix),\n )\n : skillOptions;\n\n // Map skills to CategoryOption[]\n const options: CategoryOption[] = filteredSkillOptions.map((skill) => ({\n id: skill.id,\n label: getDisplayLabel(skill), // Clean display name without author\n state: computeOptionState(skill),\n stateReason: getStateReason(skill),\n selected: skill.selected,\n local: matrix.skills[skill.id]?.local,\n }));\n\n return {\n id: cat.id,\n name: cat.name,\n required: cat.required ?? false,\n exclusive: cat.exclusive ?? true,\n options,\n };\n });\n\n // Filter out categories with no options (after compatibility filtering)\n return categoryRows.filter((row) => row.options.length > 0);\n}\n\ninterface FooterProps {\n validationError?: string;\n}\n\nconst Footer: React.FC<FooterProps> = ({ validationError }) => {\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n {validationError && (\n <Box marginBottom={1}>\n <Text color=\"yellow\">{validationError}</Text>\n </Box>\n )}\n </Box>\n );\n};\n\nconst LegendRow: React.FC = () => {\n return (\n <Box paddingLeft={1} columnGap={2}>\n <Text color=\"cyan\">active</Text>\n <Text color=\"#fff\">recommended</Text>\n <Text color=\"yellow\">discouraged</Text>\n <Text color=\"gray\">disabled</Text>\n </Box>\n );\n};\n\nexport const StepBuild: React.FC<StepBuildProps> = ({\n matrix,\n domain: activeDomain,\n selectedDomains,\n selections,\n allSelections,\n focusedRow,\n focusedCol,\n showDescriptions,\n expertMode,\n parentDomainSelections,\n onToggle,\n onFocusChange,\n onToggleDescriptions,\n onContinue,\n onBack,\n}) => {\n // Validation state for showing error messages\n const [validationError, setValidationError] = useState<string | undefined>(undefined);\n\n // Build categories for the current domain (with framework-first filtering)\n const categories = buildCategoriesForDomain(\n activeDomain,\n allSelections,\n matrix,\n expertMode,\n selections,\n parentDomainSelections,\n );\n\n // Handle keyboard input for Enter and Escape\n useInput((_input, key) => {\n if (key.return) {\n // Validate before continuing\n const validation = validateBuildStep(categories, selections);\n if (validation.valid) {\n setValidationError(undefined);\n onContinue();\n } else {\n setValidationError(validation.message);\n }\n } else if (key.escape) {\n setValidationError(undefined);\n onBack();\n }\n });\n\n return (\n <Box flexDirection=\"column\" width=\"100%\">\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=\"gray\"\n borderStyle=\"single\"\n >\n <Box columnGap={2} flexDirection=\"row\">\n {selectedDomains.map((domain) => (\n <Text key={domain} color={domain === activeDomain ? \"cyan\" : undefined}>\n {getDomainDisplayName(domain)}\n </Text>\n ))}\n </Box>\n <LegendRow />\n </Box>\n <ViewTitle>Customise your {getDomainDisplayName(activeDomain)} stack</ViewTitle>\n\n <CategoryGrid\n categories={categories}\n focusedRow={focusedRow}\n focusedCol={focusedCol}\n expertMode={expertMode}\n showDescriptions={showDescriptions}\n onToggle={onToggle}\n onFocusChange={onFocusChange}\n onToggleDescriptions={onToggleDescriptions}\n />\n\n <Footer validationError={validationError} />\n </Box>\n );\n};\n","import type {\n MergedSkillsMatrix,\n ResolvedSkill,\n SkillOption,\n SelectionValidation,\n ValidationError,\n ValidationWarning,\n} from \"../types-matrix\";\n\nexport function resolveAlias(aliasOrId: string, matrix: MergedSkillsMatrix): string {\n return matrix.aliases[aliasOrId] || aliasOrId;\n}\n\nexport function getDependentSkills(\n skillId: string,\n currentSelections: string[],\n matrix: MergedSkillsMatrix,\n): string[] {\n const fullId = resolveAlias(skillId, matrix);\n const skill = matrix.skills[fullId];\n\n if (!skill) return [];\n\n const resolvedSelections = currentSelections.map((s) => resolveAlias(s, matrix));\n const dependents: string[] = [];\n\n for (const selectedId of resolvedSelections) {\n if (selectedId === fullId) continue;\n\n const selectedSkill = matrix.skills[selectedId];\n if (!selectedSkill) continue;\n\n for (const requirement of selectedSkill.requires) {\n if (requirement.needsAny) {\n const satisfiedReqs = requirement.skillIds.filter((reqId) =>\n resolvedSelections.includes(reqId),\n );\n if (satisfiedReqs.length === 1 && satisfiedReqs[0] === fullId) {\n dependents.push(selectedId);\n }\n } else {\n if (requirement.skillIds.includes(fullId)) {\n dependents.push(selectedId);\n }\n }\n }\n }\n\n return dependents;\n}\n\nexport interface SkillCheckOptions {\n expertMode?: boolean;\n}\n\nexport function isDisabled(\n skillId: string,\n currentSelections: string[],\n matrix: MergedSkillsMatrix,\n options?: SkillCheckOptions,\n): boolean {\n if (options?.expertMode) {\n return false;\n }\n\n const fullId = resolveAlias(skillId, matrix);\n const skill = matrix.skills[fullId];\n\n if (!skill) {\n return false;\n }\n\n for (const selectedId of currentSelections) {\n const selectedFullId = resolveAlias(selectedId, matrix);\n\n if (skill.conflictsWith.some((c) => c.skillId === selectedFullId)) {\n return true;\n }\n\n const selectedSkill = matrix.skills[selectedFullId];\n if (selectedSkill && selectedSkill.conflictsWith.some((c) => c.skillId === fullId)) {\n return true;\n }\n }\n\n const resolvedSelections = currentSelections.map((s) => resolveAlias(s, matrix));\n\n for (const requirement of skill.requires) {\n if (requirement.needsAny) {\n const hasAny = requirement.skillIds.some((reqId) => resolvedSelections.includes(reqId));\n if (!hasAny) {\n return true;\n }\n } else {\n const hasAll = requirement.skillIds.every((reqId) => resolvedSelections.includes(reqId));\n if (!hasAll) {\n return true;\n }\n }\n }\n\n return false;\n}\n\nexport function getDisableReason(\n skillId: string,\n currentSelections: string[],\n matrix: MergedSkillsMatrix,\n): string | undefined {\n const fullId = resolveAlias(skillId, matrix);\n const skill = matrix.skills[fullId];\n\n if (!skill) {\n return undefined;\n }\n\n const resolvedSelections = currentSelections.map((s) => resolveAlias(s, matrix));\n\n for (const selectedId of resolvedSelections) {\n const conflict = skill.conflictsWith.find((c) => c.skillId === selectedId);\n if (conflict) {\n const selectedSkill = matrix.skills[selectedId];\n const selectedName = selectedSkill?.name || selectedId;\n return `${conflict.reason} (conflicts with ${selectedName})`;\n }\n\n const selectedSkill = matrix.skills[selectedId];\n if (selectedSkill) {\n const reverseConflict = selectedSkill.conflictsWith.find((c) => c.skillId === fullId);\n if (reverseConflict) {\n const selectedName = selectedSkill.name;\n return `${reverseConflict.reason} (conflicts with ${selectedName})`;\n }\n }\n }\n\n for (const requirement of skill.requires) {\n if (requirement.needsAny) {\n const hasAny = requirement.skillIds.some((reqId) => resolvedSelections.includes(reqId));\n if (!hasAny) {\n const requiredNames = requirement.skillIds\n .map((id) => matrix.skills[id]?.name || id)\n .join(\" or \");\n return `${requirement.reason} (requires ${requiredNames})`;\n }\n } else {\n const missingIds = requirement.skillIds.filter(\n (reqId) => !resolvedSelections.includes(reqId),\n );\n if (missingIds.length > 0) {\n const missingNames = missingIds.map((id) => matrix.skills[id]?.name || id).join(\", \");\n return `${requirement.reason} (requires ${missingNames})`;\n }\n }\n }\n\n return undefined;\n}\n\nexport function isDiscouraged(\n skillId: string,\n currentSelections: string[],\n matrix: MergedSkillsMatrix,\n): boolean {\n const fullId = resolveAlias(skillId, matrix);\n const skill = matrix.skills[fullId];\n\n if (!skill) {\n return false;\n }\n\n const resolvedSelections = currentSelections.map((s) => resolveAlias(s, matrix));\n\n for (const selectedId of resolvedSelections) {\n const selectedSkill = matrix.skills[selectedId];\n if (selectedSkill && selectedSkill.discourages.some((d) => d.skillId === fullId)) {\n return true;\n }\n\n if (skill.discourages.some((d) => d.skillId === selectedId)) {\n return true;\n }\n }\n\n return false;\n}\n\nexport function getDiscourageReason(\n skillId: string,\n currentSelections: string[],\n matrix: MergedSkillsMatrix,\n): string | undefined {\n const fullId = resolveAlias(skillId, matrix);\n const skill = matrix.skills[fullId];\n\n if (!skill) {\n return undefined;\n }\n\n const resolvedSelections = currentSelections.map((s) => resolveAlias(s, matrix));\n\n for (const selectedId of resolvedSelections) {\n const selectedSkill = matrix.skills[selectedId];\n if (selectedSkill) {\n const discourage = selectedSkill.discourages.find((d) => d.skillId === fullId);\n if (discourage) {\n return discourage.reason;\n }\n }\n\n const reverseDiscourage = skill.discourages.find((d) => d.skillId === selectedId);\n if (reverseDiscourage) {\n return reverseDiscourage.reason;\n }\n }\n\n return undefined;\n}\n\nexport function isRecommended(\n skillId: string,\n currentSelections: string[],\n matrix: MergedSkillsMatrix,\n): boolean {\n const fullId = resolveAlias(skillId, matrix);\n const skill = matrix.skills[fullId];\n\n if (!skill) {\n return false;\n }\n\n const resolvedSelections = currentSelections.map((s) => resolveAlias(s, matrix));\n\n for (const selectedId of resolvedSelections) {\n const selectedSkill = matrix.skills[selectedId];\n if (selectedSkill && selectedSkill.recommends.some((r) => r.skillId === fullId)) {\n return true;\n }\n }\n\n return false;\n}\n\nexport function getRecommendReason(\n skillId: string,\n currentSelections: string[],\n matrix: MergedSkillsMatrix,\n): string | undefined {\n const fullId = resolveAlias(skillId, matrix);\n const skill = matrix.skills[fullId];\n\n if (!skill) {\n return undefined;\n }\n\n const resolvedSelections = currentSelections.map((s) => resolveAlias(s, matrix));\n\n for (const selectedId of resolvedSelections) {\n const selectedSkill = matrix.skills[selectedId];\n if (selectedSkill) {\n const recommendation = selectedSkill.recommends.find((r) => r.skillId === fullId);\n if (recommendation) {\n return `${recommendation.reason} (recommended by ${selectedSkill.name})`;\n }\n }\n }\n\n return undefined;\n}\n\nexport function validateSelection(\n selections: string[],\n matrix: MergedSkillsMatrix,\n): SelectionValidation {\n const errors: ValidationError[] = [];\n const warnings: ValidationWarning[] = [];\n const resolvedSelections = selections.map((s) => resolveAlias(s, matrix));\n\n for (let i = 0; i < resolvedSelections.length; i++) {\n const skillA = matrix.skills[resolvedSelections[i]];\n if (!skillA) continue;\n\n for (let j = i + 1; j < resolvedSelections.length; j++) {\n const skillBId = resolvedSelections[j];\n const conflict = skillA.conflictsWith.find((c) => c.skillId === skillBId);\n if (conflict) {\n errors.push({\n type: \"conflict\",\n message: `${skillA.name} conflicts with ${matrix.skills[skillBId]?.name || skillBId}: ${conflict.reason}`,\n skills: [skillA.id, skillBId],\n });\n }\n }\n }\n\n for (const skillId of resolvedSelections) {\n const skill = matrix.skills[skillId];\n if (!skill) continue;\n\n for (const requirement of skill.requires) {\n if (requirement.needsAny) {\n const hasAny = requirement.skillIds.some((reqId) => resolvedSelections.includes(reqId));\n if (!hasAny) {\n errors.push({\n type: \"missing_requirement\",\n message: `${skill.name} requires one of: ${requirement.skillIds.map((id) => matrix.skills[id]?.name || id).join(\", \")}`,\n skills: [skillId, ...requirement.skillIds],\n });\n }\n } else {\n const missingIds = requirement.skillIds.filter(\n (reqId) => !resolvedSelections.includes(reqId),\n );\n if (missingIds.length > 0) {\n errors.push({\n type: \"missing_requirement\",\n message: `${skill.name} requires: ${missingIds.map((id) => matrix.skills[id]?.name || id).join(\", \")}`,\n skills: [skillId, ...missingIds],\n });\n }\n }\n }\n }\n\n const categorySelections = new Map<string, string[]>();\n for (const skillId of resolvedSelections) {\n const skill = matrix.skills[skillId];\n if (!skill) continue;\n\n const existing = categorySelections.get(skill.category) || [];\n existing.push(skillId);\n categorySelections.set(skill.category, existing);\n }\n\n for (const [categoryId, skillIds] of categorySelections.entries()) {\n if (skillIds.length > 1) {\n const category = matrix.categories[categoryId];\n if (category?.exclusive) {\n errors.push({\n type: \"category_exclusive\",\n message: `Category \"${category.name}\" only allows one selection, but multiple selected: ${skillIds.map((id) => matrix.skills[id]?.name || id).join(\", \")}`,\n skills: skillIds,\n });\n }\n }\n }\n\n for (const skillId of resolvedSelections) {\n const skill = matrix.skills[skillId];\n if (!skill) continue;\n\n for (const recommendation of skill.recommends) {\n if (!resolvedSelections.includes(recommendation.skillId)) {\n const recommendedSkill = matrix.skills[recommendation.skillId];\n if (recommendedSkill) {\n const hasConflict = recommendedSkill.conflictsWith.some((c) =>\n resolvedSelections.includes(c.skillId),\n );\n if (!hasConflict) {\n warnings.push({\n type: \"missing_recommendation\",\n message: `${skill.name} recommends ${recommendedSkill.name}: ${recommendation.reason}`,\n skills: [skillId, recommendation.skillId],\n });\n }\n }\n }\n }\n }\n\n for (const skillId of resolvedSelections) {\n const skill = matrix.skills[skillId];\n if (!skill || skill.providesSetupFor.length === 0) continue;\n\n const hasUsageSkill = skill.providesSetupFor.some((usageId) =>\n resolvedSelections.includes(usageId),\n );\n if (!hasUsageSkill) {\n warnings.push({\n type: \"unused_setup\",\n message: `Setup skill \"${skill.name}\" selected but no corresponding usage skills: ${skill.providesSetupFor.map((id) => matrix.skills[id]?.name || id).join(\", \")}`,\n skills: [skillId, ...skill.providesSetupFor],\n });\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\nexport function getAvailableSkills(\n categoryId: string,\n currentSelections: string[],\n matrix: MergedSkillsMatrix,\n options?: SkillCheckOptions,\n): SkillOption[] {\n const skillOptions: SkillOption[] = [];\n const resolvedSelections = currentSelections.map((s) => resolveAlias(s, matrix));\n\n for (const skill of Object.values(matrix.skills)) {\n if (skill.category !== categoryId) {\n continue;\n }\n\n const disabled = isDisabled(skill.id, currentSelections, matrix, options);\n const discouraged = !disabled && isDiscouraged(skill.id, currentSelections, matrix);\n const recommended =\n !disabled && !discouraged && isRecommended(skill.id, currentSelections, matrix);\n\n skillOptions.push({\n id: skill.id,\n alias: skill.alias,\n name: skill.name,\n description: skill.description,\n disabled,\n disabledReason: disabled ? getDisableReason(skill.id, currentSelections, matrix) : undefined,\n discouraged,\n discouragedReason: discouraged\n ? getDiscourageReason(skill.id, currentSelections, matrix)\n : undefined,\n recommended,\n recommendedReason: recommended\n ? getRecommendReason(skill.id, currentSelections, matrix)\n : undefined,\n selected: resolvedSelections.includes(skill.id),\n alternatives: skill.alternatives.map((a) => a.skillId),\n });\n }\n\n return skillOptions;\n}\n\nexport function getSkillsByCategory(\n categoryId: string,\n matrix: MergedSkillsMatrix,\n): ResolvedSkill[] {\n const skills: ResolvedSkill[] = [];\n\n for (const skill of Object.values(matrix.skills)) {\n if (skill.category === categoryId) {\n skills.push(skill);\n }\n }\n\n return skills;\n}\n\nexport function isCategoryAllDisabled(\n categoryId: string,\n currentSelections: string[],\n matrix: MergedSkillsMatrix,\n options?: SkillCheckOptions,\n): { disabled: boolean; reason?: string } {\n if (options?.expertMode) {\n return { disabled: false };\n }\n\n const skills = getSkillsByCategory(categoryId, matrix);\n\n if (skills.length === 0) {\n return { disabled: false };\n }\n\n const disabledSkills: Array<{ skillId: string; reason: string | undefined }> = [];\n\n for (const skill of skills) {\n if (isDisabled(skill.id, currentSelections, matrix, options)) {\n disabledSkills.push({\n skillId: skill.id,\n reason: getDisableReason(skill.id, currentSelections, matrix),\n });\n }\n }\n\n if (disabledSkills.length === skills.length) {\n const firstReason = disabledSkills[0]?.reason;\n const shortReason = firstReason?.split(\" (\")[0] || \"requirements not met\";\n return { disabled: true, reason: shortReason };\n }\n\n return { disabled: false };\n}\n","import type { MergedSkillsMatrix } from \"../../types-matrix.js\";\n\n/**\n * Get display name for a domain.\n */\nexport function getDomainDisplayName(domain: string): string {\n const displayNames: Record<string, string> = {\n web: \"Web\",\n \"web-extras\": \"Web Extras\",\n api: \"API\",\n cli: \"CLI\",\n mobile: \"Mobile\",\n shared: \"Shared\",\n };\n return displayNames[domain] || domain.charAt(0).toUpperCase() + domain.slice(1);\n}\n\n/**\n * Get stack name from matrix by stack ID.\n */\nexport function getStackName(\n stackId: string | null,\n matrix: MergedSkillsMatrix,\n): string | undefined {\n if (!stackId) return undefined;\n const stack = matrix.suggestedStacks.find((s) => s.id === stackId);\n return stack?.name;\n}\n"],"mappings":";;;;;;;;;;;;AAAA;AASA,SAAgB,gBAAgB;AAChC,SAAS,KAAK,MAAM,gBAAgB;;;ACVpC;AASO,SAAS,aAAa,WAAmB,QAAoC;AAClF,SAAO,OAAO,QAAQ,SAAS,KAAK;AACtC;AA4CO,SAAS,WACd,SACA,mBACA,QACA,SACS;AACT,MAAI,SAAS,YAAY;AACvB,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,aAAa,SAAS,MAAM;AAC3C,QAAM,QAAQ,OAAO,OAAO,MAAM;AAElC,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAEA,aAAW,cAAc,mBAAmB;AAC1C,UAAM,iBAAiB,aAAa,YAAY,MAAM;AAEtD,QAAI,MAAM,cAAc,KAAK,CAAC,MAAM,EAAE,YAAY,cAAc,GAAG;AACjE,aAAO;AAAA,IACT;AAEA,UAAM,gBAAgB,OAAO,OAAO,cAAc;AAClD,QAAI,iBAAiB,cAAc,cAAc,KAAK,CAAC,MAAM,EAAE,YAAY,MAAM,GAAG;AAClF,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,qBAAqB,kBAAkB,IAAI,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC;AAE/E,aAAW,eAAe,MAAM,UAAU;AACxC,QAAI,YAAY,UAAU;AACxB,YAAM,SAAS,YAAY,SAAS,KAAK,CAAC,UAAU,mBAAmB,SAAS,KAAK,CAAC;AACtF,UAAI,CAAC,QAAQ;AACX,eAAO;AAAA,MACT;AAAA,IACF,OAAO;AACL,YAAM,SAAS,YAAY,SAAS,MAAM,CAAC,UAAU,mBAAmB,SAAS,KAAK,CAAC;AACvF,UAAI,CAAC,QAAQ;AACX,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,iBACd,SACA,mBACA,QACoB;AACpB,QAAM,SAAS,aAAa,SAAS,MAAM;AAC3C,QAAM,QAAQ,OAAO,OAAO,MAAM;AAElC,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAEA,QAAM,qBAAqB,kBAAkB,IAAI,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC;AAE/E,aAAW,cAAc,oBAAoB;AAC3C,UAAM,WAAW,MAAM,cAAc,KAAK,CAAC,MAAM,EAAE,YAAY,UAAU;AACzE,QAAI,UAAU;AACZ,YAAMA,iBAAgB,OAAO,OAAO,UAAU;AAC9C,YAAM,eAAeA,gBAAe,QAAQ;AAC5C,aAAO,GAAG,SAAS,MAAM,oBAAoB,YAAY;AAAA,IAC3D;AAEA,UAAM,gBAAgB,OAAO,OAAO,UAAU;AAC9C,QAAI,eAAe;AACjB,YAAM,kBAAkB,cAAc,cAAc,KAAK,CAAC,MAAM,EAAE,YAAY,MAAM;AACpF,UAAI,iBAAiB;AACnB,cAAM,eAAe,cAAc;AACnC,eAAO,GAAG,gBAAgB,MAAM,oBAAoB,YAAY;AAAA,MAClE;AAAA,IACF;AAAA,EACF;AAEA,aAAW,eAAe,MAAM,UAAU;AACxC,QAAI,YAAY,UAAU;AACxB,YAAM,SAAS,YAAY,SAAS,KAAK,CAAC,UAAU,mBAAmB,SAAS,KAAK,CAAC;AACtF,UAAI,CAAC,QAAQ;AACX,cAAM,gBAAgB,YAAY,SAC/B,IAAI,CAAC,OAAO,OAAO,OAAO,EAAE,GAAG,QAAQ,EAAE,EACzC,KAAK,MAAM;AACd,eAAO,GAAG,YAAY,MAAM,cAAc,aAAa;AAAA,MACzD;AAAA,IACF,OAAO;AACL,YAAM,aAAa,YAAY,SAAS;AAAA,QACtC,CAAC,UAAU,CAAC,mBAAmB,SAAS,KAAK;AAAA,MAC/C;AACA,UAAI,WAAW,SAAS,GAAG;AACzB,cAAM,eAAe,WAAW,IAAI,CAAC,OAAO,OAAO,OAAO,EAAE,GAAG,QAAQ,EAAE,EAAE,KAAK,IAAI;AACpF,eAAO,GAAG,YAAY,MAAM,cAAc,YAAY;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,cACd,SACA,mBACA,QACS;AACT,QAAM,SAAS,aAAa,SAAS,MAAM;AAC3C,QAAM,QAAQ,OAAO,OAAO,MAAM;AAElC,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAEA,QAAM,qBAAqB,kBAAkB,IAAI,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC;AAE/E,aAAW,cAAc,oBAAoB;AAC3C,UAAM,gBAAgB,OAAO,OAAO,UAAU;AAC9C,QAAI,iBAAiB,cAAc,YAAY,KAAK,CAAC,MAAM,EAAE,YAAY,MAAM,GAAG;AAChF,aAAO;AAAA,IACT;AAEA,QAAI,MAAM,YAAY,KAAK,CAAC,MAAM,EAAE,YAAY,UAAU,GAAG;AAC3D,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,oBACd,SACA,mBACA,QACoB;AACpB,QAAM,SAAS,aAAa,SAAS,MAAM;AAC3C,QAAM,QAAQ,OAAO,OAAO,MAAM;AAElC,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAEA,QAAM,qBAAqB,kBAAkB,IAAI,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC;AAE/E,aAAW,cAAc,oBAAoB;AAC3C,UAAM,gBAAgB,OAAO,OAAO,UAAU;AAC9C,QAAI,eAAe;AACjB,YAAM,aAAa,cAAc,YAAY,KAAK,CAAC,MAAM,EAAE,YAAY,MAAM;AAC7E,UAAI,YAAY;AACd,eAAO,WAAW;AAAA,MACpB;AAAA,IACF;AAEA,UAAM,oBAAoB,MAAM,YAAY,KAAK,CAAC,MAAM,EAAE,YAAY,UAAU;AAChF,QAAI,mBAAmB;AACrB,aAAO,kBAAkB;AAAA,IAC3B;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,cACd,SACA,mBACA,QACS;AACT,QAAM,SAAS,aAAa,SAAS,MAAM;AAC3C,QAAM,QAAQ,OAAO,OAAO,MAAM;AAElC,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAEA,QAAM,qBAAqB,kBAAkB,IAAI,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC;AAE/E,aAAW,cAAc,oBAAoB;AAC3C,UAAM,gBAAgB,OAAO,OAAO,UAAU;AAC9C,QAAI,iBAAiB,cAAc,WAAW,KAAK,CAAC,MAAM,EAAE,YAAY,MAAM,GAAG;AAC/E,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,mBACd,SACA,mBACA,QACoB;AACpB,QAAM,SAAS,aAAa,SAAS,MAAM;AAC3C,QAAM,QAAQ,OAAO,OAAO,MAAM;AAElC,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAEA,QAAM,qBAAqB,kBAAkB,IAAI,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC;AAE/E,aAAW,cAAc,oBAAoB;AAC3C,UAAM,gBAAgB,OAAO,OAAO,UAAU;AAC9C,QAAI,eAAe;AACjB,YAAM,iBAAiB,cAAc,WAAW,KAAK,CAAC,MAAM,EAAE,YAAY,MAAM;AAChF,UAAI,gBAAgB;AAClB,eAAO,GAAG,eAAe,MAAM,oBAAoB,cAAc,IAAI;AAAA,MACvE;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,kBACd,YACA,QACqB;AACrB,QAAM,SAA4B,CAAC;AACnC,QAAM,WAAgC,CAAC;AACvC,QAAM,qBAAqB,WAAW,IAAI,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC;AAExE,WAAS,IAAI,GAAG,IAAI,mBAAmB,QAAQ,KAAK;AAClD,UAAM,SAAS,OAAO,OAAO,mBAAmB,CAAC,CAAC;AAClD,QAAI,CAAC,OAAQ;AAEb,aAAS,IAAI,IAAI,GAAG,IAAI,mBAAmB,QAAQ,KAAK;AACtD,YAAM,WAAW,mBAAmB,CAAC;AACrC,YAAM,WAAW,OAAO,cAAc,KAAK,CAAC,MAAM,EAAE,YAAY,QAAQ;AACxE,UAAI,UAAU;AACZ,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,SAAS,GAAG,OAAO,IAAI,mBAAmB,OAAO,OAAO,QAAQ,GAAG,QAAQ,QAAQ,KAAK,SAAS,MAAM;AAAA,UACvG,QAAQ,CAAC,OAAO,IAAI,QAAQ;AAAA,QAC9B,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,aAAW,WAAW,oBAAoB;AACxC,UAAM,QAAQ,OAAO,OAAO,OAAO;AACnC,QAAI,CAAC,MAAO;AAEZ,eAAW,eAAe,MAAM,UAAU;AACxC,UAAI,YAAY,UAAU;AACxB,cAAM,SAAS,YAAY,SAAS,KAAK,CAAC,UAAU,mBAAmB,SAAS,KAAK,CAAC;AACtF,YAAI,CAAC,QAAQ;AACX,iBAAO,KAAK;AAAA,YACV,MAAM;AAAA,YACN,SAAS,GAAG,MAAM,IAAI,qBAAqB,YAAY,SAAS,IAAI,CAAC,OAAO,OAAO,OAAO,EAAE,GAAG,QAAQ,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,YACrH,QAAQ,CAAC,SAAS,GAAG,YAAY,QAAQ;AAAA,UAC3C,CAAC;AAAA,QACH;AAAA,MACF,OAAO;AACL,cAAM,aAAa,YAAY,SAAS;AAAA,UACtC,CAAC,UAAU,CAAC,mBAAmB,SAAS,KAAK;AAAA,QAC/C;AACA,YAAI,WAAW,SAAS,GAAG;AACzB,iBAAO,KAAK;AAAA,YACV,MAAM;AAAA,YACN,SAAS,GAAG,MAAM,IAAI,cAAc,WAAW,IAAI,CAAC,OAAO,OAAO,OAAO,EAAE,GAAG,QAAQ,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,YACpG,QAAQ,CAAC,SAAS,GAAG,UAAU;AAAA,UACjC,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,qBAAqB,oBAAI,IAAsB;AACrD,aAAW,WAAW,oBAAoB;AACxC,UAAM,QAAQ,OAAO,OAAO,OAAO;AACnC,QAAI,CAAC,MAAO;AAEZ,UAAM,WAAW,mBAAmB,IAAI,MAAM,QAAQ,KAAK,CAAC;AAC5D,aAAS,KAAK,OAAO;AACrB,uBAAmB,IAAI,MAAM,UAAU,QAAQ;AAAA,EACjD;AAEA,aAAW,CAAC,YAAY,QAAQ,KAAK,mBAAmB,QAAQ,GAAG;AACjE,QAAI,SAAS,SAAS,GAAG;AACvB,YAAM,WAAW,OAAO,WAAW,UAAU;AAC7C,UAAI,UAAU,WAAW;AACvB,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,SAAS,aAAa,SAAS,IAAI,uDAAuD,SAAS,IAAI,CAAC,OAAO,OAAO,OAAO,EAAE,GAAG,QAAQ,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,UACxJ,QAAQ;AAAA,QACV,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,aAAW,WAAW,oBAAoB;AACxC,UAAM,QAAQ,OAAO,OAAO,OAAO;AACnC,QAAI,CAAC,MAAO;AAEZ,eAAW,kBAAkB,MAAM,YAAY;AAC7C,UAAI,CAAC,mBAAmB,SAAS,eAAe,OAAO,GAAG;AACxD,cAAM,mBAAmB,OAAO,OAAO,eAAe,OAAO;AAC7D,YAAI,kBAAkB;AACpB,gBAAM,cAAc,iBAAiB,cAAc;AAAA,YAAK,CAAC,MACvD,mBAAmB,SAAS,EAAE,OAAO;AAAA,UACvC;AACA,cAAI,CAAC,aAAa;AAChB,qBAAS,KAAK;AAAA,cACZ,MAAM;AAAA,cACN,SAAS,GAAG,MAAM,IAAI,eAAe,iBAAiB,IAAI,KAAK,eAAe,MAAM;AAAA,cACpF,QAAQ,CAAC,SAAS,eAAe,OAAO;AAAA,YAC1C,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,aAAW,WAAW,oBAAoB;AACxC,UAAM,QAAQ,OAAO,OAAO,OAAO;AACnC,QAAI,CAAC,SAAS,MAAM,iBAAiB,WAAW,EAAG;AAEnD,UAAM,gBAAgB,MAAM,iBAAiB;AAAA,MAAK,CAAC,YACjD,mBAAmB,SAAS,OAAO;AAAA,IACrC;AACA,QAAI,CAAC,eAAe;AAClB,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,SAAS,gBAAgB,MAAM,IAAI,iDAAiD,MAAM,iBAAiB,IAAI,CAAC,OAAO,OAAO,OAAO,EAAE,GAAG,QAAQ,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,QAChK,QAAQ,CAAC,SAAS,GAAG,MAAM,gBAAgB;AAAA,MAC7C,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO,OAAO,WAAW;AAAA,IACzB;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,mBACd,YACA,mBACA,QACA,SACe;AACf,QAAM,eAA8B,CAAC;AACrC,QAAM,qBAAqB,kBAAkB,IAAI,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC;AAE/E,aAAW,SAAS,OAAO,OAAO,OAAO,MAAM,GAAG;AAChD,QAAI,MAAM,aAAa,YAAY;AACjC;AAAA,IACF;AAEA,UAAM,WAAW,WAAW,MAAM,IAAI,mBAAmB,QAAQ,OAAO;AACxE,UAAM,cAAc,CAAC,YAAY,cAAc,MAAM,IAAI,mBAAmB,MAAM;AAClF,UAAM,cACJ,CAAC,YAAY,CAAC,eAAe,cAAc,MAAM,IAAI,mBAAmB,MAAM;AAEhF,iBAAa,KAAK;AAAA,MAChB,IAAI,MAAM;AAAA,MACV,OAAO,MAAM;AAAA,MACb,MAAM,MAAM;AAAA,MACZ,aAAa,MAAM;AAAA,MACnB;AAAA,MACA,gBAAgB,WAAW,iBAAiB,MAAM,IAAI,mBAAmB,MAAM,IAAI;AAAA,MACnF;AAAA,MACA,mBAAmB,cACf,oBAAoB,MAAM,IAAI,mBAAmB,MAAM,IACvD;AAAA,MACJ;AAAA,MACA,mBAAmB,cACf,mBAAmB,MAAM,IAAI,mBAAmB,MAAM,IACtD;AAAA,MACJ,UAAU,mBAAmB,SAAS,MAAM,EAAE;AAAA,MAC9C,cAAc,MAAM,aAAa,IAAI,CAAC,MAAM,EAAE,OAAO;AAAA,IACvD,CAAC;AAAA,EACH;AAEA,SAAO;AACT;;;ACjbA;AAKO,SAAS,qBAAqB,QAAwB;AAC3D,QAAM,eAAuC;AAAA,IAC3C,KAAK;AAAA,IACL,cAAc;AAAA,IACd,KAAK;AAAA,IACL,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AACA,SAAO,aAAa,MAAM,KAAK,OAAO,OAAO,CAAC,EAAE,YAAY,IAAI,OAAO,MAAM,CAAC;AAChF;AAKO,SAAS,aACd,SACA,QACoB;AACpB,MAAI,CAAC,QAAS,QAAO;AACrB,QAAM,QAAQ,OAAO,gBAAgB,KAAK,CAAC,MAAM,EAAE,OAAO,OAAO;AACjE,SAAO,OAAO;AAChB;;;AF2QU,cASN,YATM;AAhPV,IAAM,2BAA2B;AAGjC,IAAM,gBAAgB;AAYf,SAAS,kBACd,YACA,YACqB;AACrB,aAAW,YAAY,YAAY;AACjC,QAAI,SAAS,UAAU;AACrB,YAAM,qBAAqB,WAAW,SAAS,EAAE,KAAK,CAAC;AACvD,UAAI,mBAAmB,WAAW,GAAG;AACnC,eAAO;AAAA,UACL,OAAO;AAAA,UACP,SAAS,mBAAmB,SAAS,IAAI;AAAA,QAC3C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO,EAAE,OAAO,KAAK;AACvB;AAOA,SAAS,mBAAmB,OAIZ;AACd,MAAI,MAAM,UAAU;AAClB,WAAO;AAAA,EACT;AACA,MAAI,MAAM,aAAa;AACrB,WAAO;AAAA,EACT;AACA,MAAI,MAAM,aAAa;AACrB,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAOO,SAAS,gBAAgB,OAAiD;AAG/E,QAAM,gBAAgB;AACtB,SAAO,MAAM,KAAK,QAAQ,eAAe,EAAE;AAC7C;AAKA,SAAS,eAAe,OAOD;AACrB,MAAI,MAAM,YAAY,MAAM,gBAAgB;AAC1C,WAAO,MAAM;AAAA,EACf;AACA,MAAI,MAAM,eAAe,MAAM,mBAAmB;AAChD,WAAO,MAAM;AAAA,EACf;AACA,MAAI,MAAM,eAAe,MAAM,mBAAmB;AAChD,WAAO,MAAM;AAAA,EACf;AACA,SAAO;AACT;AAQA,SAAS,oBAAoB,YAA+C;AAC1E,QAAM,sBAAsB,WAAW,wBAAwB,KAAK,CAAC;AACrE,SAAO,oBAAoB,SAAS;AACtC;AAMA,SAAS,sBACP,YACA,QACU;AACV,QAAM,sBAAsB,WAAW,wBAAwB,KAAK,CAAC;AAErE,SAAO,oBAAoB,IAAI,CAAC,UAAU;AACxC,WAAO,OAAO,QAAQ,KAAK,KAAK;AAAA,EAClC,CAAC;AACH;AAMA,SAAS,mCACP,SACA,sBACA,QACS;AACT,QAAM,QAAQ,OAAO,OAAO,OAAO;AACnC,MAAI,CAAC,MAAO,QAAO;AAInB,MAAI,MAAM,eAAe,WAAW,GAAG;AACrC,WAAO;AAAA,EACT;AAGA,SAAO,qBAAqB,KAAK,CAAC,gBAAgB,MAAM,eAAe,SAAS,WAAW,CAAC;AAC9F;AASA,SAAS,sBACP,gBACA,SACA,oBACS;AAGT,SAAO;AACT;AAUA,SAAS,yBACP,QACA,eACA,QACA,YACA,YACA,wBACe;AAGf,QAAM,kBAAkB,0BAA0B;AAClD,QAAM,oBAAoB,oBAAoB,eAAe;AAC7D,QAAM,uBAAuB,oBACzB,sBAAsB,iBAAiB,MAAM,IAC7C,CAAC;AAGL,QAAM,gBAAgB,OAAO,OAAO,OAAO,UAAU,EAClD,OAAO,CAAC,QAAQ,IAAI,WAAW,MAAM,EACrC,KAAK,CAAC,GAAG,OAAO,EAAE,SAAS,MAAM,EAAE,SAAS,EAAE;AAGjD,QAAM,uBAAuB,cAAc;AAAA,IAAO,CAAC,QACjD,sBAAsB,IAAI,IAAI,QAAQ,iBAAiB;AAAA,EACzD;AAGA,QAAM,eAA8B,qBAAqB,IAAI,CAAC,QAAQ;AAEpE,UAAM,eAAe,mBAAmB,IAAI,IAAI,eAAe,QAAQ;AAAA,MACrE;AAAA,IACF,CAAC;AAID,UAAM,sBACH,WAAW,iBAAiB,2BAA2B,WACxD,IAAI,OAAO,4BACX;AACF,UAAM,uBAAuB,qBACzB,aAAa;AAAA,MAAO,CAAC,UACnB,mCAAmC,MAAM,IAAI,sBAAsB,MAAM;AAAA,IAC3E,IACA;AAGJ,UAAM,UAA4B,qBAAqB,IAAI,CAAC,WAAW;AAAA,MACrE,IAAI,MAAM;AAAA,MACV,OAAO,gBAAgB,KAAK;AAAA;AAAA,MAC5B,OAAO,mBAAmB,KAAK;AAAA,MAC/B,aAAa,eAAe,KAAK;AAAA,MACjC,UAAU,MAAM;AAAA,MAChB,OAAO,OAAO,OAAO,MAAM,EAAE,GAAG;AAAA,IAClC,EAAE;AAEF,WAAO;AAAA,MACL,IAAI,IAAI;AAAA,MACR,MAAM,IAAI;AAAA,MACV,UAAU,IAAI,YAAY;AAAA,MAC1B,WAAW,IAAI,aAAa;AAAA,MAC5B;AAAA,IACF;AAAA,EACF,CAAC;AAGD,SAAO,aAAa,OAAO,CAAC,QAAQ,IAAI,QAAQ,SAAS,CAAC;AAC5D;AAMA,IAAM,SAAgC,CAAC,EAAE,gBAAgB,MAAM;AAC7D,SACE,oBAAC,OAAI,eAAc,UAAS,WAAW,GACpC,6BACC,oBAAC,OAAI,cAAc,GACjB,8BAAC,QAAK,OAAM,UAAU,2BAAgB,GACxC,GAEJ;AAEJ;AAEA,IAAM,YAAsB,MAAM;AAChC,SACE,qBAAC,OAAI,aAAa,GAAG,WAAW,GAC9B;AAAA,wBAAC,QAAK,OAAM,QAAO,oBAAM;AAAA,IACzB,oBAAC,QAAK,OAAM,QAAO,yBAAW;AAAA,IAC9B,oBAAC,QAAK,OAAM,UAAS,yBAAW;AAAA,IAChC,oBAAC,QAAK,OAAM,QAAO,sBAAQ;AAAA,KAC7B;AAEJ;AAEO,IAAM,YAAsC,CAAC;AAAA,EAClD;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AAEJ,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAA6B,MAAS;AAGpF,QAAM,aAAa;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,WAAS,CAAC,QAAQ,QAAQ;AACxB,QAAI,IAAI,QAAQ;AAEd,YAAM,aAAa,kBAAkB,YAAY,UAAU;AAC3D,UAAI,WAAW,OAAO;AACpB,2BAAmB,MAAS;AAC5B,mBAAW;AAAA,MACb,OAAO;AACL,2BAAmB,WAAW,OAAO;AAAA,MACvC;AAAA,IACF,WAAW,IAAI,QAAQ;AACrB,yBAAmB,MAAS;AAC5B,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AAED,SACE,qBAAC,OAAI,eAAc,UAAS,OAAM,QAChC;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,WAAW;AAAA,QACX,eAAc;AAAA,QACd,gBAAe;AAAA,QACf,cAAc;AAAA,QACd,cAAc;AAAA,QACd,WAAW;AAAA,QACX,WAAW;AAAA,QACX,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,aAAY;AAAA,QACZ,aAAY;AAAA,QAEZ;AAAA,8BAAC,OAAI,WAAW,GAAG,eAAc,OAC9B,0BAAgB,IAAI,CAAC,WACpB,oBAAC,QAAkB,OAAO,WAAW,eAAe,SAAS,QAC1D,+BAAqB,MAAM,KADnB,MAEX,CACD,GACH;AAAA,UACA,oBAAC,aAAU;AAAA;AAAA;AAAA,IACb;AAAA,IACA,qBAAC,aAAU;AAAA;AAAA,MAAgB,qBAAqB,YAAY;AAAA,MAAE;AAAA,OAAM;AAAA,IAEpE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,IACF;AAAA,IAEA,oBAAC,UAAO,iBAAkC;AAAA,KAC5C;AAEJ;","names":["selectedSkill"]}
|
package/dist/chunk-5K2ZLUO5.js
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
getCollectivePluginDir
|
|
4
|
-
} from "./chunk-HPGFY5ZN.js";
|
|
5
|
-
import {
|
|
6
|
-
loadProjectConfig
|
|
7
|
-
} from "./chunk-VFHWU7JU.js";
|
|
8
|
-
import {
|
|
9
|
-
directoryExists,
|
|
10
|
-
fileExists
|
|
11
|
-
} from "./chunk-AL74GBW4.js";
|
|
12
|
-
import {
|
|
13
|
-
CLAUDE_DIR,
|
|
14
|
-
CLAUDE_SRC_DIR
|
|
15
|
-
} from "./chunk-FJFEKPXF.js";
|
|
16
|
-
import {
|
|
17
|
-
init_esm_shims
|
|
18
|
-
} from "./chunk-DHET7RCE.js";
|
|
19
|
-
|
|
20
|
-
// src/cli/lib/installation.ts
|
|
21
|
-
init_esm_shims();
|
|
22
|
-
import path from "path";
|
|
23
|
-
async function detectInstallation(projectDir = process.cwd()) {
|
|
24
|
-
const srcConfigPath = path.join(projectDir, CLAUDE_SRC_DIR, "config.yaml");
|
|
25
|
-
const legacyConfigPath = path.join(projectDir, CLAUDE_DIR, "config.yaml");
|
|
26
|
-
const localConfigPath = await fileExists(srcConfigPath) ? srcConfigPath : await fileExists(legacyConfigPath) ? legacyConfigPath : null;
|
|
27
|
-
if (localConfigPath) {
|
|
28
|
-
const loaded = await loadProjectConfig(projectDir);
|
|
29
|
-
const mode = loaded?.config?.installMode ?? "local";
|
|
30
|
-
if (mode === "local") {
|
|
31
|
-
return {
|
|
32
|
-
mode: "local",
|
|
33
|
-
configPath: localConfigPath,
|
|
34
|
-
agentsDir: path.join(projectDir, CLAUDE_DIR, "agents"),
|
|
35
|
-
skillsDir: path.join(projectDir, CLAUDE_DIR, "skills"),
|
|
36
|
-
projectDir
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
const pluginDir = getCollectivePluginDir(projectDir);
|
|
41
|
-
const pluginConfigPath = path.join(pluginDir, "config.yaml");
|
|
42
|
-
if (await directoryExists(pluginDir)) {
|
|
43
|
-
return {
|
|
44
|
-
mode: "plugin",
|
|
45
|
-
configPath: pluginConfigPath,
|
|
46
|
-
agentsDir: path.join(pluginDir, "agents"),
|
|
47
|
-
skillsDir: path.join(pluginDir, "skills"),
|
|
48
|
-
projectDir
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
return null;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export {
|
|
55
|
-
detectInstallation
|
|
56
|
-
};
|
|
57
|
-
//# sourceMappingURL=chunk-5K2ZLUO5.js.map
|