agentsys 5.0.3 → 5.1.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/.claude-plugin/marketplace.json +21 -14
- package/.claude-plugin/plugin.json +1 -1
- package/AGENTS.md +2 -1
- package/CHANGELOG.md +18 -0
- package/README.md +7 -6
- package/adapters/codex/skills/agnix/SKILL.md +0 -1
- package/adapters/codex/skills/audit-project/SKILL.md +0 -1
- package/adapters/codex/skills/audit-project-agents/SKILL.md +0 -1
- package/adapters/codex/skills/audit-project-github/SKILL.md +0 -1
- package/adapters/codex/skills/consult/SKILL.md +132 -57
- package/adapters/codex/skills/debate/SKILL.md +214 -0
- package/adapters/codex/skills/delivery-approval/SKILL.md +0 -1
- package/adapters/codex/skills/deslop/SKILL.md +0 -1
- package/adapters/codex/skills/drift-detect/SKILL.md +0 -1
- package/adapters/codex/skills/enhance/SKILL.md +0 -1
- package/adapters/codex/skills/learn/SKILL.md +0 -1
- package/adapters/codex/skills/next-task/SKILL.md +0 -1
- package/adapters/codex/skills/perf/SKILL.md +0 -1
- package/adapters/codex/skills/repo-map/SKILL.md +0 -1
- package/adapters/codex/skills/ship/SKILL.md +0 -1
- package/adapters/codex/skills/ship-ci-review-loop/SKILL.md +0 -1
- package/adapters/codex/skills/ship-deployment/SKILL.md +0 -1
- package/adapters/codex/skills/ship-error-handling/SKILL.md +0 -1
- package/adapters/codex/skills/sync-docs/SKILL.md +0 -1
- package/adapters/opencode/agents/agent-enhancer.md +0 -1
- package/adapters/opencode/agents/agnix-agent.md +0 -1
- package/adapters/opencode/agents/ci-fixer.md +0 -1
- package/adapters/opencode/agents/ci-monitor.md +0 -1
- package/adapters/opencode/agents/claudemd-enhancer.md +0 -1
- package/adapters/opencode/agents/consult-agent.md +122 -30
- package/adapters/opencode/agents/cross-file-enhancer.md +0 -1
- package/adapters/opencode/agents/debate-orchestrator.md +169 -0
- package/adapters/opencode/agents/delivery-validator.md +0 -1
- package/adapters/opencode/agents/deslop-agent.md +0 -1
- package/adapters/opencode/agents/docs-enhancer.md +0 -1
- package/adapters/opencode/agents/exploration-agent.md +0 -1
- package/adapters/opencode/agents/hooks-enhancer.md +0 -1
- package/adapters/opencode/agents/implementation-agent.md +0 -1
- package/adapters/opencode/agents/learn-agent.md +0 -1
- package/adapters/opencode/agents/map-validator.md +0 -1
- package/adapters/opencode/agents/perf-analyzer.md +0 -1
- package/adapters/opencode/agents/perf-code-paths.md +0 -1
- package/adapters/opencode/agents/perf-investigation-logger.md +0 -1
- package/adapters/opencode/agents/perf-orchestrator.md +0 -1
- package/adapters/opencode/agents/perf-theory-gatherer.md +0 -1
- package/adapters/opencode/agents/perf-theory-tester.md +0 -1
- package/adapters/opencode/agents/plan-synthesizer.md +0 -1
- package/adapters/opencode/agents/planning-agent.md +0 -1
- package/adapters/opencode/agents/plugin-enhancer.md +0 -1
- package/adapters/opencode/agents/prompt-enhancer.md +0 -1
- package/adapters/opencode/agents/simple-fixer.md +0 -1
- package/adapters/opencode/agents/skills-enhancer.md +0 -1
- package/adapters/opencode/agents/sync-docs-agent.md +0 -1
- package/adapters/opencode/agents/task-discoverer.md +0 -1
- package/adapters/opencode/agents/test-coverage-checker.md +0 -1
- package/adapters/opencode/agents/worktree-manager.md +0 -1
- package/adapters/opencode/commands/agnix.md +0 -1
- package/adapters/opencode/commands/audit-project-agents.md +0 -1
- package/adapters/opencode/commands/audit-project-github.md +0 -1
- package/adapters/opencode/commands/audit-project.md +0 -1
- package/adapters/opencode/commands/consult.md +133 -57
- package/adapters/opencode/commands/debate.md +224 -0
- package/adapters/opencode/commands/delivery-approval.md +0 -1
- package/adapters/opencode/commands/deslop.md +0 -1
- package/adapters/opencode/commands/drift-detect.md +0 -1
- package/adapters/opencode/commands/enhance.md +0 -1
- package/adapters/opencode/commands/learn.md +0 -1
- package/adapters/opencode/commands/next-task.md +0 -1
- package/adapters/opencode/commands/perf.md +0 -1
- package/adapters/opencode/commands/repo-map.md +0 -1
- package/adapters/opencode/commands/ship-ci-review-loop.md +0 -1
- package/adapters/opencode/commands/ship-deployment.md +0 -1
- package/adapters/opencode/commands/ship-error-handling.md +0 -1
- package/adapters/opencode/commands/ship.md +0 -1
- package/adapters/opencode/commands/sync-docs.md +0 -1
- package/adapters/opencode/skills/agnix/SKILL.md +1 -2
- package/adapters/opencode/skills/consult/SKILL.md +33 -23
- package/adapters/opencode/skills/debate/SKILL.md +245 -0
- package/adapters/opencode/skills/deslop/SKILL.md +1 -2
- package/adapters/opencode/skills/discover-tasks/SKILL.md +1 -2
- package/adapters/opencode/skills/drift-analysis/SKILL.md +1 -2
- package/adapters/opencode/skills/enhance-agent-prompts/SKILL.md +1 -2
- package/adapters/opencode/skills/enhance-claude-memory/SKILL.md +1 -2
- package/adapters/opencode/skills/enhance-cross-file/SKILL.md +1 -2
- package/adapters/opencode/skills/enhance-docs/SKILL.md +1 -2
- package/adapters/opencode/skills/enhance-hooks/SKILL.md +1 -2
- package/adapters/opencode/skills/enhance-orchestrator/SKILL.md +1 -2
- package/adapters/opencode/skills/enhance-plugins/SKILL.md +1 -2
- package/adapters/opencode/skills/enhance-prompts/SKILL.md +1 -2
- package/adapters/opencode/skills/enhance-skills/SKILL.md +1 -2
- package/adapters/opencode/skills/learn/SKILL.md +1 -2
- package/adapters/opencode/skills/orchestrate-review/SKILL.md +0 -1
- package/adapters/opencode/skills/perf-analyzer/SKILL.md +1 -2
- package/adapters/opencode/skills/perf-baseline-manager/SKILL.md +1 -2
- package/adapters/opencode/skills/perf-benchmarker/SKILL.md +1 -2
- package/adapters/opencode/skills/perf-code-paths/SKILL.md +1 -2
- package/adapters/opencode/skills/perf-investigation-logger/SKILL.md +1 -2
- package/adapters/opencode/skills/perf-profiler/SKILL.md +1 -2
- package/adapters/opencode/skills/perf-theory-gatherer/SKILL.md +1 -2
- package/adapters/opencode/skills/perf-theory-tester/SKILL.md +1 -2
- package/adapters/opencode/skills/repo-mapping/SKILL.md +1 -2
- package/adapters/opencode/skills/sync-docs/SKILL.md +1 -2
- package/adapters/opencode/skills/validate-delivery/SKILL.md +1 -2
- package/lib/adapter-transforms.js +24 -4
- package/package.json +1 -1
- package/plugins/agnix/.claude-plugin/plugin.json +1 -1
- package/plugins/agnix/skills/agnix/SKILL.md +1 -1
- package/plugins/audit-project/.claude-plugin/plugin.json +1 -1
- package/plugins/audit-project/lib/adapter-transforms.js +24 -4
- package/plugins/consult/.claude-plugin/plugin.json +1 -1
- package/plugins/consult/agents/consult-agent.md +122 -29
- package/plugins/consult/commands/consult.md +135 -58
- package/plugins/consult/skills/consult/SKILL.md +31 -20
- package/plugins/debate/.claude-plugin/plugin.json +21 -0
- package/plugins/debate/agents/debate-orchestrator.md +175 -0
- package/plugins/debate/commands/debate.md +221 -0
- package/plugins/debate/lib/adapter-transforms.js +298 -0
- package/plugins/debate/lib/collectors/codebase.js +392 -0
- package/plugins/debate/lib/collectors/docs-patterns.js +713 -0
- package/plugins/debate/lib/collectors/documentation.js +219 -0
- package/plugins/debate/lib/collectors/github.js +330 -0
- package/plugins/debate/lib/collectors/index.js +126 -0
- package/plugins/debate/lib/config/index.js +14 -0
- package/plugins/debate/lib/cross-platform/index.js +539 -0
- package/plugins/debate/lib/discovery/index.js +352 -0
- package/plugins/debate/lib/drift-detect/collectors.js +37 -0
- package/plugins/debate/lib/enhance/agent-analyzer.js +421 -0
- package/plugins/debate/lib/enhance/agent-patterns.js +571 -0
- package/plugins/debate/lib/enhance/auto-suppression.js +622 -0
- package/plugins/debate/lib/enhance/benchmark.js +417 -0
- package/plugins/debate/lib/enhance/cross-file-analyzer.js +930 -0
- package/plugins/debate/lib/enhance/cross-file-patterns.js +370 -0
- package/plugins/debate/lib/enhance/docs-analyzer.js +325 -0
- package/plugins/debate/lib/enhance/docs-patterns.js +671 -0
- package/plugins/debate/lib/enhance/fixer.js +721 -0
- package/plugins/debate/lib/enhance/hook-analyzer.js +135 -0
- package/plugins/debate/lib/enhance/hook-patterns.js +40 -0
- package/plugins/debate/lib/enhance/index.js +127 -0
- package/plugins/debate/lib/enhance/plugin-analyzer.js +402 -0
- package/plugins/debate/lib/enhance/plugin-patterns.js +326 -0
- package/plugins/debate/lib/enhance/projectmemory-analyzer.js +551 -0
- package/plugins/debate/lib/enhance/projectmemory-patterns.js +617 -0
- package/plugins/debate/lib/enhance/prompt-analyzer.js +457 -0
- package/plugins/debate/lib/enhance/prompt-patterns.js +1484 -0
- package/plugins/debate/lib/enhance/reporter.js +1348 -0
- package/plugins/debate/lib/enhance/security-patterns.js +284 -0
- package/plugins/debate/lib/enhance/skill-analyzer.js +182 -0
- package/plugins/debate/lib/enhance/skill-patterns.js +147 -0
- package/plugins/debate/lib/enhance/suppression.js +352 -0
- package/plugins/debate/lib/enhance/tool-patterns.js +373 -0
- package/plugins/debate/lib/index.js +270 -0
- package/plugins/debate/lib/patterns/cli-enhancers.js +611 -0
- package/plugins/debate/lib/patterns/pipeline.js +948 -0
- package/plugins/debate/lib/patterns/review-patterns.js +558 -0
- package/plugins/debate/lib/patterns/slop-analyzers.js +2305 -0
- package/plugins/debate/lib/patterns/slop-patterns.js +1187 -0
- package/plugins/debate/lib/perf/analyzer/index.js +22 -0
- package/plugins/debate/lib/perf/argument-parser.js +105 -0
- package/plugins/debate/lib/perf/baseline-comparator.js +50 -0
- package/plugins/debate/lib/perf/baseline-store.js +127 -0
- package/plugins/debate/lib/perf/benchmark-runner.js +404 -0
- package/plugins/debate/lib/perf/breaking-point-finder.js +52 -0
- package/plugins/debate/lib/perf/breaking-point-runner.js +60 -0
- package/plugins/debate/lib/perf/checkpoint.js +123 -0
- package/plugins/debate/lib/perf/code-paths.js +86 -0
- package/plugins/debate/lib/perf/consolidation.js +37 -0
- package/plugins/debate/lib/perf/constraint-runner.js +71 -0
- package/plugins/debate/lib/perf/experiment-runner.js +32 -0
- package/plugins/debate/lib/perf/index.js +41 -0
- package/plugins/debate/lib/perf/investigation-state.js +874 -0
- package/plugins/debate/lib/perf/optimization-runner.js +79 -0
- package/plugins/debate/lib/perf/profilers/go.js +22 -0
- package/plugins/debate/lib/perf/profilers/index.js +46 -0
- package/plugins/debate/lib/perf/profilers/java.js +23 -0
- package/plugins/debate/lib/perf/profilers/node.js +27 -0
- package/plugins/debate/lib/perf/profilers/python.js +23 -0
- package/plugins/debate/lib/perf/profilers/rust.js +23 -0
- package/plugins/debate/lib/perf/profiling-runner.js +75 -0
- package/plugins/debate/lib/perf/schemas.js +140 -0
- package/plugins/debate/lib/platform/detect-platform.js +413 -0
- package/plugins/debate/lib/platform/detection-configs.js +93 -0
- package/plugins/debate/lib/platform/state-dir.js +132 -0
- package/plugins/debate/lib/platform/verify-tools.js +182 -0
- package/plugins/debate/lib/repo-map/cache.js +152 -0
- package/plugins/debate/lib/repo-map/concurrency.js +29 -0
- package/plugins/debate/lib/repo-map/index.js +222 -0
- package/plugins/debate/lib/repo-map/installer.js +212 -0
- package/plugins/debate/lib/repo-map/queries/go.js +27 -0
- package/plugins/debate/lib/repo-map/queries/index.js +100 -0
- package/plugins/debate/lib/repo-map/queries/java.js +38 -0
- package/plugins/debate/lib/repo-map/queries/javascript.js +55 -0
- package/plugins/debate/lib/repo-map/queries/python.js +24 -0
- package/plugins/debate/lib/repo-map/queries/rust.js +73 -0
- package/plugins/debate/lib/repo-map/queries/typescript.js +38 -0
- package/plugins/debate/lib/repo-map/runner.js +1364 -0
- package/plugins/debate/lib/repo-map/updater.js +562 -0
- package/plugins/debate/lib/repo-map/usage-analyzer.js +407 -0
- package/plugins/debate/lib/schemas/plugin-manifest.schema.json +57 -0
- package/plugins/debate/lib/schemas/validator.js +247 -0
- package/plugins/debate/lib/sources/custom-handler.js +199 -0
- package/plugins/debate/lib/sources/policy-questions.js +246 -0
- package/plugins/debate/lib/sources/source-cache.js +165 -0
- package/plugins/debate/lib/state/workflow-state.js +576 -0
- package/plugins/debate/lib/types/agent-frontmatter.d.ts +134 -0
- package/plugins/debate/lib/types/command-frontmatter.d.ts +107 -0
- package/plugins/debate/lib/types/hook-frontmatter.d.ts +115 -0
- package/plugins/debate/lib/types/index.d.ts +84 -0
- package/plugins/debate/lib/types/plugin-manifest.d.ts +102 -0
- package/plugins/debate/lib/types/skill-frontmatter.d.ts +89 -0
- package/plugins/debate/lib/utils/atomic-write.js +94 -0
- package/plugins/debate/lib/utils/cache-manager.js +159 -0
- package/plugins/debate/lib/utils/command-parser.js +0 -0
- package/plugins/debate/lib/utils/context-optimizer.js +300 -0
- package/plugins/debate/lib/utils/deprecation.js +37 -0
- package/plugins/debate/lib/utils/shell-escape.js +88 -0
- package/plugins/debate/lib/utils/state-helpers.js +61 -0
- package/plugins/debate/skills/debate/SKILL.md +264 -0
- package/plugins/deslop/.claude-plugin/plugin.json +1 -1
- package/plugins/deslop/lib/adapter-transforms.js +24 -4
- package/plugins/deslop/skills/deslop/SKILL.md +1 -1
- package/plugins/drift-detect/.claude-plugin/plugin.json +1 -1
- package/plugins/drift-detect/lib/adapter-transforms.js +24 -4
- package/plugins/drift-detect/skills/drift-analysis/SKILL.md +1 -1
- package/plugins/enhance/.claude-plugin/plugin.json +1 -1
- package/plugins/enhance/lib/adapter-transforms.js +24 -4
- package/plugins/enhance/skills/enhance-agent-prompts/SKILL.md +1 -1
- package/plugins/enhance/skills/enhance-claude-memory/SKILL.md +1 -1
- package/plugins/enhance/skills/enhance-cross-file/SKILL.md +1 -1
- package/plugins/enhance/skills/enhance-docs/SKILL.md +1 -1
- package/plugins/enhance/skills/enhance-hooks/SKILL.md +1 -1
- package/plugins/enhance/skills/enhance-orchestrator/SKILL.md +1 -1
- package/plugins/enhance/skills/enhance-plugins/SKILL.md +1 -1
- package/plugins/enhance/skills/enhance-prompts/SKILL.md +1 -1
- package/plugins/enhance/skills/enhance-skills/SKILL.md +1 -1
- package/plugins/learn/.claude-plugin/plugin.json +1 -1
- package/plugins/learn/agents/learn-agent.md +1 -1
- package/plugins/learn/lib/adapter-transforms.js +24 -4
- package/plugins/learn/skills/learn/SKILL.md +1 -1
- package/plugins/next-task/.claude-plugin/plugin.json +1 -1
- package/plugins/next-task/agents/exploration-agent.md +1 -1
- package/plugins/next-task/lib/adapter-transforms.js +24 -4
- package/plugins/next-task/skills/discover-tasks/SKILL.md +1 -1
- package/plugins/next-task/skills/validate-delivery/SKILL.md +1 -1
- package/plugins/perf/.claude-plugin/plugin.json +1 -1
- package/plugins/perf/lib/adapter-transforms.js +24 -4
- package/plugins/perf/skills/perf-analyzer/SKILL.md +1 -1
- package/plugins/perf/skills/perf-baseline-manager/SKILL.md +1 -1
- package/plugins/perf/skills/perf-benchmarker/SKILL.md +1 -1
- package/plugins/perf/skills/perf-code-paths/SKILL.md +1 -1
- package/plugins/perf/skills/perf-investigation-logger/SKILL.md +1 -1
- package/plugins/perf/skills/perf-profiler/SKILL.md +1 -1
- package/plugins/perf/skills/perf-theory-gatherer/SKILL.md +1 -1
- package/plugins/perf/skills/perf-theory-tester/SKILL.md +1 -1
- package/plugins/repo-map/.claude-plugin/plugin.json +1 -1
- package/plugins/repo-map/lib/adapter-transforms.js +24 -4
- package/plugins/ship/.claude-plugin/plugin.json +1 -1
- package/plugins/ship/lib/adapter-transforms.js +24 -4
- package/plugins/sync-docs/.claude-plugin/plugin.json +1 -1
- package/plugins/sync-docs/lib/adapter-transforms.js +24 -4
- package/plugins/sync-docs/skills/sync-docs/SKILL.md +1 -1
- package/scripts/gen-adapters.js +6 -7
- package/scripts/generate-docs.js +4 -2
- package/scripts/plugins.txt +1 -0
- package/site/content.json +6 -6
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin Discovery Module
|
|
3
|
+
*
|
|
4
|
+
* Convention-based filesystem scanning to discover plugins, commands,
|
|
5
|
+
* agents, and skills. Replaces all hardcoded registration lists.
|
|
6
|
+
*
|
|
7
|
+
* Convention:
|
|
8
|
+
* - plugins/<name>/.claude-plugin/plugin.json -> plugin
|
|
9
|
+
* - plugins/<name>/commands/*.md -> commands
|
|
10
|
+
* - plugins/<name>/agents/*.md -> agents
|
|
11
|
+
* - plugins/<name>/skills/<skill>/SKILL.md -> skills
|
|
12
|
+
*
|
|
13
|
+
* @module discovery
|
|
14
|
+
* @author Avi Fenesh
|
|
15
|
+
* @license MIT
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const fs = require('fs');
|
|
19
|
+
const path = require('path');
|
|
20
|
+
|
|
21
|
+
// Module-level cache
|
|
22
|
+
let _cache = null;
|
|
23
|
+
let _cacheRoot = null;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Parse YAML frontmatter from a markdown file's content.
|
|
27
|
+
* Returns an object of key-value pairs from the frontmatter block.
|
|
28
|
+
*
|
|
29
|
+
* @param {string} content - File content
|
|
30
|
+
* @returns {Object} Parsed frontmatter key-value pairs
|
|
31
|
+
*/
|
|
32
|
+
function parseFrontmatter(content) {
|
|
33
|
+
if (!content || !content.startsWith('---')) {
|
|
34
|
+
return {};
|
|
35
|
+
}
|
|
36
|
+
const endIdx = content.indexOf('\n---', 3);
|
|
37
|
+
if (endIdx === -1) {
|
|
38
|
+
return {};
|
|
39
|
+
}
|
|
40
|
+
const frontmatterBlock = content.substring(4, endIdx);
|
|
41
|
+
const result = {};
|
|
42
|
+
const lines = frontmatterBlock.split('\n');
|
|
43
|
+
let currentKey = null;
|
|
44
|
+
let currentArray = null;
|
|
45
|
+
|
|
46
|
+
for (const line of lines) {
|
|
47
|
+
// Check for YAML array item (e.g. " - Read")
|
|
48
|
+
const arrayItemMatch = line.match(/^\s+-\s+(.+)$/);
|
|
49
|
+
if (arrayItemMatch && currentKey && currentArray) {
|
|
50
|
+
let item = arrayItemMatch[1].trim();
|
|
51
|
+
// Strip surrounding quotes from array items
|
|
52
|
+
if ((item.startsWith('"') && item.endsWith('"')) ||
|
|
53
|
+
(item.startsWith("'") && item.endsWith("'"))) {
|
|
54
|
+
item = item.slice(1, -1);
|
|
55
|
+
}
|
|
56
|
+
currentArray.push(item);
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const colonIdx = line.indexOf(':');
|
|
61
|
+
if (colonIdx > 0) {
|
|
62
|
+
// Flush any pending array
|
|
63
|
+
if (currentKey && currentArray) {
|
|
64
|
+
result[currentKey] = currentArray;
|
|
65
|
+
currentKey = null;
|
|
66
|
+
currentArray = null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const key = line.substring(0, colonIdx).trim();
|
|
70
|
+
if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue;
|
|
71
|
+
let value = line.substring(colonIdx + 1).trim();
|
|
72
|
+
|
|
73
|
+
if (value === '') {
|
|
74
|
+
// Key with no value - could be start of a YAML array
|
|
75
|
+
currentKey = key;
|
|
76
|
+
currentArray = [];
|
|
77
|
+
} else {
|
|
78
|
+
// Strip surrounding quotes
|
|
79
|
+
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
80
|
+
(value.startsWith("'") && value.endsWith("'"))) {
|
|
81
|
+
value = value.slice(1, -1);
|
|
82
|
+
}
|
|
83
|
+
result[key] = value;
|
|
84
|
+
currentKey = null;
|
|
85
|
+
currentArray = null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Flush any trailing array
|
|
91
|
+
if (currentKey && currentArray) {
|
|
92
|
+
result[currentKey] = currentArray;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Validate a plugin/directory name is safe for filesystem and shell use.
|
|
100
|
+
* Only allows lowercase letters, digits, and hyphens.
|
|
101
|
+
*
|
|
102
|
+
* @param {string} name - Directory name to validate
|
|
103
|
+
* @returns {boolean}
|
|
104
|
+
*/
|
|
105
|
+
function isValidPluginName(name) {
|
|
106
|
+
return /^[a-z0-9][a-z0-9-]*$/.test(name);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Resolve the plugins directory from a repo root.
|
|
111
|
+
*
|
|
112
|
+
* @param {string} [repoRoot] - Repository root path. Defaults to two levels up from this file.
|
|
113
|
+
* @returns {string} Absolute path to plugins/ directory
|
|
114
|
+
*/
|
|
115
|
+
function resolvePluginsDir(repoRoot) {
|
|
116
|
+
if (!repoRoot) {
|
|
117
|
+
repoRoot = path.resolve(__dirname, '..', '..');
|
|
118
|
+
}
|
|
119
|
+
return path.join(repoRoot, 'plugins');
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Discover all plugins by scanning plugins/ for directories with .claude-plugin/plugin.json.
|
|
124
|
+
*
|
|
125
|
+
* @param {string} [repoRoot] - Repository root path
|
|
126
|
+
* @returns {string[]} Sorted array of plugin names
|
|
127
|
+
*/
|
|
128
|
+
function discoverPlugins(repoRoot) {
|
|
129
|
+
const cached = getCache(repoRoot);
|
|
130
|
+
if (cached && cached.plugins) return cached.plugins;
|
|
131
|
+
|
|
132
|
+
const pluginsDir = resolvePluginsDir(repoRoot);
|
|
133
|
+
if (!fs.existsSync(pluginsDir)) return [];
|
|
134
|
+
|
|
135
|
+
const entries = fs.readdirSync(pluginsDir);
|
|
136
|
+
const plugins = entries.filter(name => {
|
|
137
|
+
if (!isValidPluginName(name)) return false;
|
|
138
|
+
const pluginJson = path.join(pluginsDir, name, '.claude-plugin', 'plugin.json');
|
|
139
|
+
return fs.existsSync(pluginJson);
|
|
140
|
+
}).sort();
|
|
141
|
+
|
|
142
|
+
setCache(repoRoot, 'plugins', plugins);
|
|
143
|
+
return plugins;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Discover all commands by scanning plugins/<name>/commands/*.md.
|
|
148
|
+
*
|
|
149
|
+
* @param {string} [repoRoot] - Repository root path
|
|
150
|
+
* @returns {Array<{name: string, plugin: string, file: string, frontmatter: Object}>}
|
|
151
|
+
*/
|
|
152
|
+
function discoverCommands(repoRoot) {
|
|
153
|
+
const cached = getCache(repoRoot);
|
|
154
|
+
if (cached && cached.commands) return cached.commands;
|
|
155
|
+
|
|
156
|
+
const pluginsDir = resolvePluginsDir(repoRoot);
|
|
157
|
+
const plugins = discoverPlugins(repoRoot);
|
|
158
|
+
const commands = [];
|
|
159
|
+
|
|
160
|
+
for (const plugin of plugins) {
|
|
161
|
+
const commandsDir = path.join(pluginsDir, plugin, 'commands');
|
|
162
|
+
if (!fs.existsSync(commandsDir)) continue;
|
|
163
|
+
|
|
164
|
+
const files = fs.readdirSync(commandsDir).filter(f => f.endsWith('.md')).sort();
|
|
165
|
+
for (const file of files) {
|
|
166
|
+
const filePath = path.join(commandsDir, file);
|
|
167
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
168
|
+
const frontmatter = parseFrontmatter(content);
|
|
169
|
+
commands.push({
|
|
170
|
+
name: file.replace(/\.md$/, ''),
|
|
171
|
+
plugin,
|
|
172
|
+
file,
|
|
173
|
+
frontmatter
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
setCache(repoRoot, 'commands', commands);
|
|
179
|
+
return commands;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Discover all file-based agents by scanning plugins/<name>/agents/*.md.
|
|
184
|
+
*
|
|
185
|
+
* @param {string} [repoRoot] - Repository root path
|
|
186
|
+
* @returns {Array<{name: string, plugin: string, file: string, frontmatter: Object}>}
|
|
187
|
+
*/
|
|
188
|
+
function discoverAgents(repoRoot) {
|
|
189
|
+
const cached = getCache(repoRoot);
|
|
190
|
+
if (cached && cached.agents) return cached.agents;
|
|
191
|
+
|
|
192
|
+
const pluginsDir = resolvePluginsDir(repoRoot);
|
|
193
|
+
const plugins = discoverPlugins(repoRoot);
|
|
194
|
+
const agents = [];
|
|
195
|
+
|
|
196
|
+
for (const plugin of plugins) {
|
|
197
|
+
const agentsDir = path.join(pluginsDir, plugin, 'agents');
|
|
198
|
+
if (!fs.existsSync(agentsDir)) continue;
|
|
199
|
+
|
|
200
|
+
const files = fs.readdirSync(agentsDir).filter(f => f.endsWith('.md')).sort();
|
|
201
|
+
for (const file of files) {
|
|
202
|
+
const filePath = path.join(agentsDir, file);
|
|
203
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
204
|
+
const frontmatter = parseFrontmatter(content);
|
|
205
|
+
agents.push({
|
|
206
|
+
name: file.replace(/\.md$/, ''),
|
|
207
|
+
plugin,
|
|
208
|
+
file,
|
|
209
|
+
frontmatter
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
setCache(repoRoot, 'agents', agents);
|
|
215
|
+
return agents;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Discover all skills by scanning plugins/<name>/skills/<skill>/SKILL.md.
|
|
220
|
+
*
|
|
221
|
+
* @param {string} [repoRoot] - Repository root path
|
|
222
|
+
* @returns {Array<{name: string, plugin: string, dir: string, frontmatter: Object}>}
|
|
223
|
+
*/
|
|
224
|
+
function discoverSkills(repoRoot) {
|
|
225
|
+
const cached = getCache(repoRoot);
|
|
226
|
+
if (cached && cached.skills) return cached.skills;
|
|
227
|
+
|
|
228
|
+
const pluginsDir = resolvePluginsDir(repoRoot);
|
|
229
|
+
const plugins = discoverPlugins(repoRoot);
|
|
230
|
+
const skills = [];
|
|
231
|
+
|
|
232
|
+
for (const plugin of plugins) {
|
|
233
|
+
const skillsDir = path.join(pluginsDir, plugin, 'skills');
|
|
234
|
+
if (!fs.existsSync(skillsDir)) continue;
|
|
235
|
+
|
|
236
|
+
const entries = fs.readdirSync(skillsDir).sort();
|
|
237
|
+
for (const entry of entries) {
|
|
238
|
+
const skillFile = path.join(skillsDir, entry, 'SKILL.md');
|
|
239
|
+
if (fs.existsSync(skillFile)) {
|
|
240
|
+
const content = fs.readFileSync(skillFile, 'utf8');
|
|
241
|
+
const frontmatter = parseFrontmatter(content);
|
|
242
|
+
skills.push({
|
|
243
|
+
name: entry,
|
|
244
|
+
plugin,
|
|
245
|
+
dir: entry,
|
|
246
|
+
frontmatter
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
setCache(repoRoot, 'skills', skills);
|
|
253
|
+
return skills;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Build OpenCode command mappings from discovered commands.
|
|
258
|
+
* Returns [targetFile, pluginName, sourceFile] tuples.
|
|
259
|
+
*
|
|
260
|
+
* @param {string} [repoRoot] - Repository root path
|
|
261
|
+
* @returns {Array<[string, string, string]>}
|
|
262
|
+
*/
|
|
263
|
+
function getCommandMappings(repoRoot) {
|
|
264
|
+
const commands = discoverCommands(repoRoot);
|
|
265
|
+
return commands.map(cmd => [cmd.file, cmd.plugin, cmd.file]);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Build Codex skill mappings from discovered commands.
|
|
270
|
+
* Returns [skillName, pluginName, sourceFile, description] tuples.
|
|
271
|
+
* Uses codex-description frontmatter field, falls back to description.
|
|
272
|
+
*
|
|
273
|
+
* @param {string} [repoRoot] - Repository root path
|
|
274
|
+
* @returns {Array<[string, string, string, string]>}
|
|
275
|
+
*/
|
|
276
|
+
function getCodexSkillMappings(repoRoot) {
|
|
277
|
+
const commands = discoverCommands(repoRoot);
|
|
278
|
+
return commands.map(cmd => {
|
|
279
|
+
const description = cmd.frontmatter['codex-description'] ||
|
|
280
|
+
cmd.frontmatter.description ||
|
|
281
|
+
'';
|
|
282
|
+
return [cmd.name, cmd.plugin, cmd.file, description];
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Build a dynamic regex for stripping plugin prefixes from agent references.
|
|
288
|
+
* Example: `next-task:agent-name` -> `agent-name`
|
|
289
|
+
*
|
|
290
|
+
* @param {string} [repoRoot] - Repository root path
|
|
291
|
+
* @returns {RegExp} Regex matching plugin prefix patterns
|
|
292
|
+
*/
|
|
293
|
+
function getPluginPrefixRegex(repoRoot) {
|
|
294
|
+
const plugins = discoverPlugins(repoRoot);
|
|
295
|
+
if (plugins.length === 0) return /$^/g; // Matches nothing
|
|
296
|
+
const escaped = plugins.map(p => p.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
|
|
297
|
+
return new RegExp(`(${escaped.join('|')})`, 'g');
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Get all discovery results in a single call.
|
|
302
|
+
*
|
|
303
|
+
* @param {string} [repoRoot] - Repository root path
|
|
304
|
+
* @returns {{plugins: string[], commands: Array, agents: Array, skills: Array}}
|
|
305
|
+
*/
|
|
306
|
+
function discoverAll(repoRoot) {
|
|
307
|
+
return {
|
|
308
|
+
plugins: discoverPlugins(repoRoot),
|
|
309
|
+
commands: discoverCommands(repoRoot),
|
|
310
|
+
agents: discoverAgents(repoRoot),
|
|
311
|
+
skills: discoverSkills(repoRoot)
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// --- Cache helpers ---
|
|
316
|
+
|
|
317
|
+
function getCache(repoRoot) {
|
|
318
|
+
const root = repoRoot || path.resolve(__dirname, '..', '..');
|
|
319
|
+
if (_cache && _cacheRoot === root) return _cache;
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
function setCache(repoRoot, key, value) {
|
|
324
|
+
const root = repoRoot || path.resolve(__dirname, '..', '..');
|
|
325
|
+
if (!_cache || _cacheRoot !== root) {
|
|
326
|
+
_cache = {};
|
|
327
|
+
_cacheRoot = root;
|
|
328
|
+
}
|
|
329
|
+
_cache[key] = value;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Invalidate the module-level cache. Used for testing.
|
|
334
|
+
*/
|
|
335
|
+
function invalidateCache() {
|
|
336
|
+
_cache = null;
|
|
337
|
+
_cacheRoot = null;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
module.exports = {
|
|
341
|
+
parseFrontmatter,
|
|
342
|
+
isValidPluginName,
|
|
343
|
+
discoverPlugins,
|
|
344
|
+
discoverCommands,
|
|
345
|
+
discoverAgents,
|
|
346
|
+
discoverSkills,
|
|
347
|
+
discoverAll,
|
|
348
|
+
getCommandMappings,
|
|
349
|
+
getCodexSkillMappings,
|
|
350
|
+
getPluginPrefixRegex,
|
|
351
|
+
invalidateCache
|
|
352
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reality Check Data Collectors
|
|
3
|
+
* Pure JavaScript data collection - no LLM needed
|
|
4
|
+
*
|
|
5
|
+
* BACKWARD COMPATIBILITY: This module re-exports from lib/collectors.
|
|
6
|
+
* For new code, use: const { collectors } = require('@agentsys/lib');
|
|
7
|
+
*
|
|
8
|
+
* Replaces three LLM agents (issue-scanner, doc-analyzer, code-explorer)
|
|
9
|
+
* with deterministic JavaScript functions.
|
|
10
|
+
*
|
|
11
|
+
* @module lib/drift-detect/collectors
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
'use strict';
|
|
15
|
+
|
|
16
|
+
// Re-export from shared collectors module
|
|
17
|
+
const collectors = require('../collectors');
|
|
18
|
+
|
|
19
|
+
// Legacy DEFAULT_OPTIONS (backward compatible format)
|
|
20
|
+
const DEFAULT_OPTIONS = {
|
|
21
|
+
sources: ['github', 'docs', 'code'],
|
|
22
|
+
depth: 'thorough',
|
|
23
|
+
issueLimit: collectors.github.DEFAULT_OPTIONS.issueLimit,
|
|
24
|
+
prLimit: collectors.github.DEFAULT_OPTIONS.prLimit,
|
|
25
|
+
timeout: collectors.github.DEFAULT_OPTIONS.timeout
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Re-export all functions for backward compatibility
|
|
29
|
+
module.exports = {
|
|
30
|
+
DEFAULT_OPTIONS,
|
|
31
|
+
scanGitHubState: collectors.scanGitHubState,
|
|
32
|
+
analyzeDocumentation: collectors.analyzeDocumentation,
|
|
33
|
+
scanCodebase: collectors.scanCodebase,
|
|
34
|
+
collectAllData: collectors.collectAllData,
|
|
35
|
+
isGhAvailable: collectors.isGhAvailable,
|
|
36
|
+
isPathSafe: collectors.documentation.isPathSafe
|
|
37
|
+
};
|