claudecode-omc 5.6.1 → 5.6.2
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/bundled/manifest.json +1 -1
- package/package.json +2 -1
- package/src/cli/artifact.js +2 -62
- package/src/cli/setup.js +36 -59
- package/src/cli/source.js +1 -1
- package/src/config/paths.js +18 -0
- package/src/merge/artifact-source-loader.js +92 -0
package/bundled/manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claudecode-omc",
|
|
3
|
-
"version": "5.6.
|
|
3
|
+
"version": "5.6.2",
|
|
4
4
|
"description": "Claude Code harness — best-practice skills, agents, hooks, and configs from multiple sources",
|
|
5
5
|
"bin": {
|
|
6
6
|
"omc-manage": "bin/omc-manage.js"
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"README.md"
|
|
16
16
|
],
|
|
17
17
|
"scripts": {
|
|
18
|
+
"test": "node --test",
|
|
18
19
|
"setup": "node bin/omc-manage.js setup",
|
|
19
20
|
"doctor": "node bin/omc-manage.js doctor",
|
|
20
21
|
"guidelines:optimize": "node bin/omc-manage.js guidelines optimize",
|
package/src/cli/artifact.js
CHANGED
|
@@ -1,70 +1,10 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
const fsp = require('fs/promises');
|
|
4
|
-
const
|
|
5
|
-
const { getProjectRoot, getSourceArtifactDir, getMergeConfigPath, getReportDir } = require('../config/paths');
|
|
6
|
-
const { readConfig, filterItemsByAllowlist } = require('../config/sources');
|
|
4
|
+
const { getProjectRoot, getMergeConfigPath } = require('../config/paths');
|
|
7
5
|
const { ARTIFACT_TYPES, getArtifactTypeNames } = require('../config/artifact-types');
|
|
8
6
|
const { detectConflicts, resolveConflicts, applyResolutions, generateReport } = require('../merge/base-merger');
|
|
9
|
-
const {
|
|
10
|
-
const { loadAgentsFromSource } = require('../merge/agent-merger');
|
|
11
|
-
const { loadCommandsFromSource } = require('../merge/command-merger');
|
|
12
|
-
const { loadHookFilesFromSource } = require('../merge/hook-merger');
|
|
13
|
-
const { loadFilesFromSource } = require('../merge/file-merger');
|
|
14
|
-
const { loadClaudeMd } = require('../merge/claude-md-merger');
|
|
15
|
-
|
|
16
|
-
function loadSectionDocumentFromSource(sourceDir) {
|
|
17
|
-
const content = loadClaudeMd(sourceDir);
|
|
18
|
-
if (!content) return [];
|
|
19
|
-
return [{
|
|
20
|
-
name: 'CLAUDE.md',
|
|
21
|
-
path: sourceDir,
|
|
22
|
-
metadata: {
|
|
23
|
-
description: `${content.length} chars of prompt guidelines`,
|
|
24
|
-
},
|
|
25
|
-
}];
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function getLoader(artifactType) {
|
|
29
|
-
switch (artifactType) {
|
|
30
|
-
case 'skills': return loadSkillsFromSource;
|
|
31
|
-
case 'agents': return loadAgentsFromSource;
|
|
32
|
-
case 'commands': return loadCommandsFromSource;
|
|
33
|
-
case 'hooks': return loadHookFilesFromSource;
|
|
34
|
-
case 'guidelines': return loadSectionDocumentFromSource;
|
|
35
|
-
case 'claude-md': return loadSectionDocumentFromSource;
|
|
36
|
-
case 'hud': return loadFilesFromSource;
|
|
37
|
-
default: return null;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function loadSourcesForType(artifactType, root) {
|
|
42
|
-
const config = readConfig();
|
|
43
|
-
const sources = [];
|
|
44
|
-
const ordered = Object.entries(config.sources)
|
|
45
|
-
.sort(([, a], [, b]) => a.priority - b.priority);
|
|
46
|
-
|
|
47
|
-
const loader = getLoader(artifactType);
|
|
48
|
-
if (!loader) return sources;
|
|
49
|
-
|
|
50
|
-
for (const [name, src] of ordered) {
|
|
51
|
-
if (src.role === 'reference') continue;
|
|
52
|
-
if (src.installMode && src.installMode !== 'auto') continue;
|
|
53
|
-
if (!(src.artifacts || []).includes(artifactType)) continue;
|
|
54
|
-
const dir = getSourceArtifactDir(name, artifactType, root);
|
|
55
|
-
if (!fs.existsSync(dir)) continue;
|
|
56
|
-
const items = filterItemsByAllowlist(src, artifactType, loader(dir, name));
|
|
57
|
-
if (items.length > 0) {
|
|
58
|
-
sources.push({ name, items });
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (sources.length === 0 && artifactType === 'claude-md') {
|
|
63
|
-
return loadSourcesForType('guidelines', root);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return sources;
|
|
67
|
-
}
|
|
7
|
+
const { loadSourcesForType } = require('../merge/artifact-source-loader');
|
|
68
8
|
|
|
69
9
|
async function artifact(args, flags = {}) {
|
|
70
10
|
const cmd = args[0] || 'list';
|
package/src/cli/setup.js
CHANGED
|
@@ -3,23 +3,17 @@ const fs = require('fs');
|
|
|
3
3
|
const fsp = require('fs/promises');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const os = require('os');
|
|
6
|
-
const { getProjectRoot,
|
|
6
|
+
const { getProjectRoot, getScopedInstallTarget, getMergeConfigPath } = require('../config/paths');
|
|
7
7
|
const { readConfig, filterItemsByAllowlist } = require('../config/sources');
|
|
8
8
|
const { getArtifactTypeNames, ARTIFACT_TYPES } = require('../config/artifact-types');
|
|
9
|
-
const { detectConflicts, resolveConflicts, applyResolutions
|
|
10
|
-
const {
|
|
11
|
-
const { loadAgentsFromSource } = require('../merge/agent-merger');
|
|
12
|
-
const { loadCommandsFromSource } = require('../merge/command-merger');
|
|
13
|
-
const { loadHookFilesFromSource, loadHooksConfig, mergeHooksConfigs, hasHookLib } = require('../merge/hook-merger');
|
|
9
|
+
const { detectConflicts, resolveConflicts, applyResolutions } = require('../merge/base-merger');
|
|
10
|
+
const { loadHooksConfig, mergeHooksConfigs, hasHookLib } = require('../merge/hook-merger');
|
|
14
11
|
const { loadClaudeMd, mergeIntoExisting, assembleSections } = require('../merge/claude-md-merger');
|
|
15
12
|
const { loadSettingsFragment, mergeSettingsFragments } = require('../merge/settings-merger');
|
|
16
|
-
const {
|
|
17
|
-
const { evaluateSkillQuality } = require('../utils/quality');
|
|
18
|
-
const { copyDirRecursive } = require('./source');
|
|
13
|
+
const { collectSourceDirsForType, getArtifactLoader } = require('../merge/artifact-source-loader');
|
|
19
14
|
|
|
20
15
|
const OMC_VERSION_PATH = path.join(os.homedir(), '.claude', '.omc-version.json');
|
|
21
16
|
const OMC_CONFIG_PATH = path.join(os.homedir(), '.claude', '.omc-config.json');
|
|
22
|
-
const OMC_INSTALL_MANIFEST_PATH = path.join(os.homedir(), '.claude', '.omc-install-manifest.json');
|
|
23
17
|
const LEGACY_HOOK_PATHS = [
|
|
24
18
|
'hooks.json',
|
|
25
19
|
'hooks-cursor.json',
|
|
@@ -125,6 +119,18 @@ function inferLegacyManagedPaths(artifactType, installTarget, desiredPaths, extr
|
|
|
125
119
|
}
|
|
126
120
|
}
|
|
127
121
|
|
|
122
|
+
function normalizePreviousManagedPaths(artifactType, previousPaths) {
|
|
123
|
+
if (!Array.isArray(previousPaths)) return previousPaths;
|
|
124
|
+
|
|
125
|
+
if (artifactType !== 'agents' && artifactType !== 'commands') {
|
|
126
|
+
return previousPaths;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return previousPaths.map((relativePath) => (
|
|
130
|
+
path.extname(relativePath) ? relativePath : `${relativePath}.md`
|
|
131
|
+
));
|
|
132
|
+
}
|
|
133
|
+
|
|
128
134
|
async function pruneManagedPaths(installTarget, previousPaths, desiredPaths, flags) {
|
|
129
135
|
if (!fs.existsSync(installTarget) || !fs.statSync(installTarget).isDirectory()) {
|
|
130
136
|
return 0;
|
|
@@ -192,43 +198,19 @@ async function copyDirectory(src, dest, options = {}) {
|
|
|
192
198
|
return count;
|
|
193
199
|
}
|
|
194
200
|
|
|
195
|
-
function
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
case 'agents': return loadAgentsFromSource;
|
|
199
|
-
case 'commands': return loadCommandsFromSource;
|
|
200
|
-
case 'hooks': return loadHookFilesFromSource;
|
|
201
|
-
case 'hud': return loadFilesFromSource;
|
|
202
|
-
default: return null;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
function collectSourcesForType(artifactType, orderedSources, root) {
|
|
207
|
-
const sourcesForType = [];
|
|
208
|
-
|
|
209
|
-
for (const [name, src] of orderedSources) {
|
|
210
|
-
// Skip reference-only sources (e.g. anthropic-skills) — they provide
|
|
211
|
-
// evaluation standards, not installable artifacts.
|
|
212
|
-
if (src.role === 'reference') continue;
|
|
213
|
-
if (src.installMode && src.installMode !== 'auto') continue;
|
|
214
|
-
const declaredArtifacts = src.artifacts || [];
|
|
215
|
-
if (!declaredArtifacts.includes(artifactType)) continue;
|
|
216
|
-
|
|
217
|
-
const dir = getSourceArtifactDir(name, artifactType, root);
|
|
218
|
-
if (fs.existsSync(dir)) {
|
|
219
|
-
sourcesForType.push({ name, dir, priority: src.priority, config: src });
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
if (sourcesForType.length === 0 && artifactType === 'claude-md') {
|
|
224
|
-
return collectSourcesForType('guidelines', orderedSources, root);
|
|
201
|
+
function getManagedPathForItem(artifactType, item) {
|
|
202
|
+
if (artifactType === 'skills' || item.isDirectory) {
|
|
203
|
+
return item.name;
|
|
225
204
|
}
|
|
226
205
|
|
|
227
|
-
|
|
206
|
+
// Loaders keep logical names extensionless for conflict checks; manifests
|
|
207
|
+
// must track the real path written to disk.
|
|
208
|
+
const sourceExt = path.extname(item.path);
|
|
209
|
+
return sourceExt && !item.name.endsWith(sourceExt) ? `${item.name}${sourceExt}` : item.name;
|
|
228
210
|
}
|
|
229
211
|
|
|
230
212
|
async function installNameBasedArtifacts(artifactType, sources, mergeConfig, installTarget, flags) {
|
|
231
|
-
const loader =
|
|
213
|
+
const loader = getArtifactLoader(artifactType);
|
|
232
214
|
if (!loader) return { count: 0, total: 0 };
|
|
233
215
|
|
|
234
216
|
const loaded = [];
|
|
@@ -257,6 +239,8 @@ async function installNameBasedArtifacts(artifactType, sources, mergeConfig, ins
|
|
|
257
239
|
}
|
|
258
240
|
}
|
|
259
241
|
|
|
242
|
+
const managedPaths = merged.map(item => getManagedPathForItem(artifactType, item));
|
|
243
|
+
|
|
260
244
|
if (flags.dryRun) {
|
|
261
245
|
for (const item of merged.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
262
246
|
console.log(` ${item.name} (${item.sourceName})`);
|
|
@@ -265,7 +249,7 @@ async function installNameBasedArtifacts(artifactType, sources, mergeConfig, ins
|
|
|
265
249
|
count: 0,
|
|
266
250
|
total: merged.length,
|
|
267
251
|
conflicts: conflicts.length,
|
|
268
|
-
managedPaths
|
|
252
|
+
managedPaths,
|
|
269
253
|
excludedNames: excludeList,
|
|
270
254
|
};
|
|
271
255
|
}
|
|
@@ -275,14 +259,10 @@ async function installNameBasedArtifacts(artifactType, sources, mergeConfig, ins
|
|
|
275
259
|
|
|
276
260
|
for (const item of merged) {
|
|
277
261
|
if (artifactType === 'skills' || item.isDirectory) {
|
|
278
|
-
const dest = path.join(installTarget, item
|
|
262
|
+
const dest = path.join(installTarget, getManagedPathForItem(artifactType, item));
|
|
279
263
|
fileCount += await copyDirectory(item.path, dest, flags);
|
|
280
264
|
} else {
|
|
281
|
-
|
|
282
|
-
// re-attach the source extension on disk so Claude Code's `*.md` loader picks them up.
|
|
283
|
-
const sourceExt = path.extname(item.path);
|
|
284
|
-
const destName = sourceExt && !item.name.endsWith(sourceExt) ? `${item.name}${sourceExt}` : item.name;
|
|
285
|
-
const dest = path.join(installTarget, destName);
|
|
265
|
+
const dest = path.join(installTarget, getManagedPathForItem(artifactType, item));
|
|
286
266
|
await fsp.mkdir(path.dirname(dest), { recursive: true });
|
|
287
267
|
await fsp.copyFile(item.path, dest);
|
|
288
268
|
fileCount += 1;
|
|
@@ -293,7 +273,7 @@ async function installNameBasedArtifacts(artifactType, sources, mergeConfig, ins
|
|
|
293
273
|
count: fileCount,
|
|
294
274
|
total: merged.length,
|
|
295
275
|
conflicts: conflicts.length,
|
|
296
|
-
managedPaths
|
|
276
|
+
managedPaths,
|
|
297
277
|
excludedNames: excludeList,
|
|
298
278
|
};
|
|
299
279
|
}
|
|
@@ -440,10 +420,6 @@ async function setup(args, flags = {}) {
|
|
|
440
420
|
try { mergeConfig = JSON.parse(fs.readFileSync(mergeConfigPath, 'utf8')); } catch {}
|
|
441
421
|
}
|
|
442
422
|
|
|
443
|
-
// Get ordered sources (by priority)
|
|
444
|
-
const orderedSources = Object.entries(config.sources)
|
|
445
|
-
.sort(([, a], [, b]) => a.priority - b.priority);
|
|
446
|
-
|
|
447
423
|
const allTypes = getArtifactTypeNames().filter(type => type !== 'claude-md');
|
|
448
424
|
const typesToInstall = typeFilter || allTypes;
|
|
449
425
|
const previousManifest = await readJsonFile(manifestPath, { artifacts: {} });
|
|
@@ -463,11 +439,9 @@ async function setup(args, flags = {}) {
|
|
|
463
439
|
continue;
|
|
464
440
|
}
|
|
465
441
|
|
|
466
|
-
const sourcesForType =
|
|
442
|
+
const sourcesForType = collectSourceDirsForType(artifactType, root, config);
|
|
467
443
|
|
|
468
|
-
const installTarget = (artifactType
|
|
469
|
-
? path.join(process.cwd(), '.claude', 'skills')
|
|
470
|
-
: typeConfig.installTarget;
|
|
444
|
+
const installTarget = getScopedInstallTarget(artifactType, scope, process.cwd());
|
|
471
445
|
|
|
472
446
|
console.log(`[${step}/${totalSteps}] ${typeConfig.label} (${sourcesForType.length} sources)`);
|
|
473
447
|
|
|
@@ -501,7 +475,10 @@ async function setup(args, flags = {}) {
|
|
|
501
475
|
}
|
|
502
476
|
|
|
503
477
|
if (typeConfig.format !== 'single-file' && typeConfig.format !== 'json') {
|
|
504
|
-
const previousPaths =
|
|
478
|
+
const previousPaths = normalizePreviousManagedPaths(
|
|
479
|
+
artifactType,
|
|
480
|
+
previousManifest.artifacts?.[artifactType]?.paths,
|
|
481
|
+
);
|
|
505
482
|
const managedPaths = uniq(result.managedPaths || []);
|
|
506
483
|
const bootstrapPaths = previousPaths || inferLegacyManagedPaths(
|
|
507
484
|
artifactType,
|
package/src/cli/source.js
CHANGED
|
@@ -74,8 +74,8 @@ async function syncRemoteSource(sourceName, sourceConfig, root) {
|
|
|
74
74
|
const srcPath = path.join(tmpDir, srcSubdir);
|
|
75
75
|
const destPath = getSyncTargetDir(sourceName, artifactType, root);
|
|
76
76
|
|
|
77
|
+
await fsp.rm(destPath, { recursive: true, force: true });
|
|
77
78
|
if (fs.existsSync(srcPath)) {
|
|
78
|
-
await fsp.rm(destPath, { recursive: true, force: true });
|
|
79
79
|
if (fs.statSync(srcPath).isDirectory()) {
|
|
80
80
|
await copyDirRecursive(srcPath, destPath);
|
|
81
81
|
} else {
|
package/src/config/paths.js
CHANGED
|
@@ -213,6 +213,23 @@ function getInstallTarget(artifactType) {
|
|
|
213
213
|
return type.installTarget;
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
+
function getScopedInstallTarget(artifactType, scope = 'user', cwd = process.cwd()) {
|
|
217
|
+
if (scope !== 'project') {
|
|
218
|
+
return getInstallTarget(artifactType);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (artifactType === 'guidelines' || artifactType === 'claude-md') {
|
|
222
|
+
return path.join(cwd, '.claude', 'CLAUDE.md');
|
|
223
|
+
}
|
|
224
|
+
if (artifactType === 'settings') {
|
|
225
|
+
return path.join(cwd, '.claude', 'settings.json');
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const type = ARTIFACT_TYPES[artifactType];
|
|
229
|
+
if (!type) throw new Error(`Unknown artifact type: ${artifactType}`);
|
|
230
|
+
return path.join(cwd, '.claude', type.sourceSubdir);
|
|
231
|
+
}
|
|
232
|
+
|
|
216
233
|
// Backward-compatible aliases
|
|
217
234
|
function getLocalSkillsDir(root) {
|
|
218
235
|
return getSourceArtifactDir('local', 'skills', root);
|
|
@@ -257,6 +274,7 @@ module.exports = {
|
|
|
257
274
|
getSyncTargetDir,
|
|
258
275
|
getSyncTempDir,
|
|
259
276
|
getInstallTarget,
|
|
277
|
+
getScopedInstallTarget,
|
|
260
278
|
USER_DATA_DIR,
|
|
261
279
|
// Backward-compatible
|
|
262
280
|
getLocalSkillsDir,
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const { getProjectRoot, getSourceArtifactDir } = require('../config/paths');
|
|
3
|
+
const { readConfig, filterItemsByAllowlist } = require('../config/sources');
|
|
4
|
+
const { loadSkillsFromSource } = require('./skill-merger');
|
|
5
|
+
const { loadAgentsFromSource } = require('./agent-merger');
|
|
6
|
+
const { loadCommandsFromSource } = require('./command-merger');
|
|
7
|
+
const { loadHookFilesFromSource } = require('./hook-merger');
|
|
8
|
+
const { loadFilesFromSource } = require('./file-merger');
|
|
9
|
+
const { loadClaudeMd } = require('./claude-md-merger');
|
|
10
|
+
|
|
11
|
+
function loadSectionDocumentFromSource(sourceDir) {
|
|
12
|
+
const content = loadClaudeMd(sourceDir);
|
|
13
|
+
if (!content) return [];
|
|
14
|
+
return [{
|
|
15
|
+
name: 'CLAUDE.md',
|
|
16
|
+
path: sourceDir,
|
|
17
|
+
metadata: {
|
|
18
|
+
description: `${content.length} chars of prompt guidelines`,
|
|
19
|
+
},
|
|
20
|
+
}];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function getArtifactLoader(artifactType, options = {}) {
|
|
24
|
+
switch (artifactType) {
|
|
25
|
+
case 'skills': return loadSkillsFromSource;
|
|
26
|
+
case 'agents': return loadAgentsFromSource;
|
|
27
|
+
case 'commands': return loadCommandsFromSource;
|
|
28
|
+
case 'hooks': return loadHookFilesFromSource;
|
|
29
|
+
case 'hud': return loadFilesFromSource;
|
|
30
|
+
case 'guidelines':
|
|
31
|
+
case 'claude-md':
|
|
32
|
+
return options.includeSectionDocuments ? loadSectionDocumentFromSource : null;
|
|
33
|
+
default: return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function getOrderedInstallableSources(config) {
|
|
38
|
+
return Object.entries(config.sources || {})
|
|
39
|
+
.sort(([, a], [, b]) => a.priority - b.priority)
|
|
40
|
+
.filter(([, src]) => src.role !== 'reference')
|
|
41
|
+
.filter(([, src]) => !src.installMode || src.installMode === 'auto');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function collectSourceDirsForType(artifactType, root = getProjectRoot(), config = readConfig()) {
|
|
45
|
+
const sourcesForType = [];
|
|
46
|
+
|
|
47
|
+
for (const [name, src] of getOrderedInstallableSources(config)) {
|
|
48
|
+
if (!(src.artifacts || []).includes(artifactType)) continue;
|
|
49
|
+
|
|
50
|
+
const dir = getSourceArtifactDir(name, artifactType, root);
|
|
51
|
+
if (fs.existsSync(dir)) {
|
|
52
|
+
sourcesForType.push({ name, dir, priority: src.priority, config: src });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (sourcesForType.length === 0 && artifactType === 'claude-md') {
|
|
57
|
+
return collectSourceDirsForType('guidelines', root, config);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return sourcesForType;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function loadSourcesForType(artifactType, root = getProjectRoot(), options = {}) {
|
|
64
|
+
const config = options.config || readConfig();
|
|
65
|
+
const loader = getArtifactLoader(artifactType, { includeSectionDocuments: true });
|
|
66
|
+
if (!loader) return [];
|
|
67
|
+
|
|
68
|
+
const sources = [];
|
|
69
|
+
for (const source of collectSourceDirsForType(artifactType, root, config)) {
|
|
70
|
+
const items = filterItemsByAllowlist(
|
|
71
|
+
source.config,
|
|
72
|
+
artifactType,
|
|
73
|
+
loader(source.dir, source.name),
|
|
74
|
+
);
|
|
75
|
+
if (items.length > 0) {
|
|
76
|
+
sources.push({ name: source.name, items });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (sources.length === 0 && artifactType === 'claude-md') {
|
|
81
|
+
return loadSourcesForType('guidelines', root, options);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return sources;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
module.exports = {
|
|
88
|
+
collectSourceDirsForType,
|
|
89
|
+
getArtifactLoader,
|
|
90
|
+
loadSectionDocumentFromSource,
|
|
91
|
+
loadSourcesForType,
|
|
92
|
+
};
|