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,457 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompt Analyzer
|
|
3
|
+
* Analyzes general prompts for prompt engineering best practices
|
|
4
|
+
*
|
|
5
|
+
* @author Avi Fenesh
|
|
6
|
+
* @license MIT
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const { promptPatterns, estimateTokens, extractCodeBlocks } = require('./prompt-patterns');
|
|
12
|
+
const reporter = require('./reporter');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Detect prompt file type from path or content
|
|
16
|
+
* @param {string} filePath - File path
|
|
17
|
+
* @param {string} content - File content
|
|
18
|
+
* @returns {string} File type: 'agent', 'command', 'skill', 'prompt', 'markdown'
|
|
19
|
+
*/
|
|
20
|
+
function detectPromptType(filePath, content) {
|
|
21
|
+
const lowerPath = filePath.toLowerCase();
|
|
22
|
+
|
|
23
|
+
// Check path patterns
|
|
24
|
+
if (lowerPath.includes('/agents/') || lowerPath.includes('\\agents\\')) {
|
|
25
|
+
return 'agent';
|
|
26
|
+
}
|
|
27
|
+
if (lowerPath.includes('/commands/') || lowerPath.includes('\\commands\\')) {
|
|
28
|
+
return 'command';
|
|
29
|
+
}
|
|
30
|
+
if (lowerPath.includes('/skills/') || lowerPath.includes('\\skills\\')) {
|
|
31
|
+
return 'skill';
|
|
32
|
+
}
|
|
33
|
+
if (lowerPath.includes('/prompts/') || lowerPath.includes('\\prompts\\')) {
|
|
34
|
+
return 'prompt';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Check content patterns
|
|
38
|
+
if (content) {
|
|
39
|
+
// Agent frontmatter
|
|
40
|
+
if (/^---\s*\nname:\s*\w+/m.test(content)) {
|
|
41
|
+
return 'agent';
|
|
42
|
+
}
|
|
43
|
+
// System prompt indicators
|
|
44
|
+
if (/<system>/i.test(content) || /^##?\s*system\s+prompt/im.test(content)) {
|
|
45
|
+
return 'prompt';
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return 'markdown';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Analyze a single prompt file
|
|
54
|
+
* @param {string} promptPath - Path to prompt file
|
|
55
|
+
* @param {Object} options - Analysis options
|
|
56
|
+
* @param {boolean} options.verbose - Include LOW certainty issues
|
|
57
|
+
* @returns {Object} Analysis results
|
|
58
|
+
*/
|
|
59
|
+
function analyzePrompt(promptPath, options = {}) {
|
|
60
|
+
const { verbose = false } = options;
|
|
61
|
+
|
|
62
|
+
const results = {
|
|
63
|
+
promptName: path.basename(promptPath, path.extname(promptPath)),
|
|
64
|
+
promptPath,
|
|
65
|
+
promptType: null,
|
|
66
|
+
tokenCount: 0,
|
|
67
|
+
clarityIssues: [],
|
|
68
|
+
structureIssues: [],
|
|
69
|
+
exampleIssues: [],
|
|
70
|
+
contextIssues: [],
|
|
71
|
+
outputIssues: [],
|
|
72
|
+
antiPatternIssues: [],
|
|
73
|
+
codeValidationIssues: []
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// Read file
|
|
77
|
+
if (!fs.existsSync(promptPath)) {
|
|
78
|
+
results.structureIssues.push({
|
|
79
|
+
issue: 'File not found',
|
|
80
|
+
file: promptPath,
|
|
81
|
+
certainty: 'HIGH',
|
|
82
|
+
patternId: 'file_not_found'
|
|
83
|
+
});
|
|
84
|
+
return results;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
let content;
|
|
88
|
+
try {
|
|
89
|
+
content = fs.readFileSync(promptPath, 'utf8');
|
|
90
|
+
} catch (err) {
|
|
91
|
+
results.structureIssues.push({
|
|
92
|
+
issue: `Failed to read file: ${err.message}`,
|
|
93
|
+
file: promptPath,
|
|
94
|
+
certainty: 'HIGH',
|
|
95
|
+
patternId: 'read_error'
|
|
96
|
+
});
|
|
97
|
+
return results;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Detect prompt type
|
|
101
|
+
results.promptType = detectPromptType(promptPath, content);
|
|
102
|
+
|
|
103
|
+
// Calculate token count
|
|
104
|
+
results.tokenCount = estimateTokens(content);
|
|
105
|
+
|
|
106
|
+
// Strip bad example sections before analysis
|
|
107
|
+
// These intentionally show anti-patterns and should not be flagged
|
|
108
|
+
const BAD_EXAMPLE_TAG_PATTERN = /<bad[_\- ]?example>[\s\S]*?<\/bad[_\- ]?example>/gi;
|
|
109
|
+
const BAD_EXAMPLE_CODE_PATTERN = /```[^\n]*bad[^\n]*\n[\s\S]*?```/gi;
|
|
110
|
+
const contentForAnalysis = content
|
|
111
|
+
.replace(BAD_EXAMPLE_TAG_PATTERN, '')
|
|
112
|
+
.replace(BAD_EXAMPLE_CODE_PATTERN, '');
|
|
113
|
+
|
|
114
|
+
// Run each pattern check
|
|
115
|
+
for (const pattern of Object.values(promptPatterns)) {
|
|
116
|
+
// Skip LOW certainty unless verbose
|
|
117
|
+
if (pattern.certainty === 'LOW' && !verbose) {
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Run the check on content with bad examples stripped
|
|
122
|
+
// Pass file path for patterns that need path-based filtering
|
|
123
|
+
const result = pattern.check(contentForAnalysis, promptPath);
|
|
124
|
+
|
|
125
|
+
if (result) {
|
|
126
|
+
const issue = {
|
|
127
|
+
...result,
|
|
128
|
+
file: promptPath,
|
|
129
|
+
certainty: pattern.certainty,
|
|
130
|
+
patternId: pattern.id,
|
|
131
|
+
autoFix: pattern.autoFix
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
// Route to appropriate issue category
|
|
135
|
+
switch (pattern.category) {
|
|
136
|
+
case 'clarity':
|
|
137
|
+
results.clarityIssues.push(issue);
|
|
138
|
+
break;
|
|
139
|
+
case 'structure':
|
|
140
|
+
results.structureIssues.push(issue);
|
|
141
|
+
break;
|
|
142
|
+
case 'examples':
|
|
143
|
+
results.exampleIssues.push(issue);
|
|
144
|
+
break;
|
|
145
|
+
case 'context':
|
|
146
|
+
results.contextIssues.push(issue);
|
|
147
|
+
break;
|
|
148
|
+
case 'output':
|
|
149
|
+
results.outputIssues.push(issue);
|
|
150
|
+
break;
|
|
151
|
+
case 'anti-pattern':
|
|
152
|
+
results.antiPatternIssues.push(issue);
|
|
153
|
+
break;
|
|
154
|
+
case 'code-validation':
|
|
155
|
+
results.codeValidationIssues.push(issue);
|
|
156
|
+
break;
|
|
157
|
+
default:
|
|
158
|
+
results.structureIssues.push(issue);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return results;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Analyze all prompts in a directory
|
|
168
|
+
* @param {string} promptsDir - Path to prompts directory
|
|
169
|
+
* @param {Object} options - Analysis options
|
|
170
|
+
* @returns {Array} Array of analysis results
|
|
171
|
+
*/
|
|
172
|
+
function analyzeAllPrompts(promptsDir, options = {}) {
|
|
173
|
+
const { recursive = true, extensions = ['.md', '.txt'], ...analyzeOptions } = options;
|
|
174
|
+
const results = [];
|
|
175
|
+
|
|
176
|
+
// Validate and normalize path
|
|
177
|
+
if (!promptsDir || typeof promptsDir !== 'string') {
|
|
178
|
+
return results;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Resolve to absolute path to prevent path traversal
|
|
182
|
+
const resolvedDir = path.resolve(promptsDir);
|
|
183
|
+
|
|
184
|
+
if (!fs.existsSync(resolvedDir)) {
|
|
185
|
+
return results;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Collect prompt files
|
|
189
|
+
const promptFiles = [];
|
|
190
|
+
|
|
191
|
+
function findPromptFiles(dir) {
|
|
192
|
+
let entries;
|
|
193
|
+
try {
|
|
194
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
195
|
+
} catch (err) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
for (const entry of entries) {
|
|
200
|
+
const fullPath = path.join(dir, entry.name);
|
|
201
|
+
|
|
202
|
+
// Ensure traversed paths stay within the resolved directory
|
|
203
|
+
// Use path.relative() for Windows case-insensitive path comparison
|
|
204
|
+
const resolvedFullPath = path.resolve(fullPath);
|
|
205
|
+
const relativePath = path.relative(resolvedDir, resolvedFullPath);
|
|
206
|
+
if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) {
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (entry.isDirectory() && recursive) {
|
|
211
|
+
// Skip common non-prompt directories
|
|
212
|
+
if (!['node_modules', '.git', 'dist', 'build', 'tests', '__tests__'].includes(entry.name)) {
|
|
213
|
+
findPromptFiles(fullPath);
|
|
214
|
+
}
|
|
215
|
+
} else if (entry.isFile()) {
|
|
216
|
+
const ext = path.extname(entry.name).toLowerCase();
|
|
217
|
+
if (extensions.includes(ext)) {
|
|
218
|
+
// Skip README files
|
|
219
|
+
if (entry.name.toLowerCase() !== 'readme.md') {
|
|
220
|
+
promptFiles.push(fullPath);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
findPromptFiles(resolvedDir);
|
|
228
|
+
|
|
229
|
+
// Analyze each file
|
|
230
|
+
for (const promptFile of promptFiles) {
|
|
231
|
+
const result = analyzePrompt(promptFile, analyzeOptions);
|
|
232
|
+
results.push(result);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return results;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Main analyze function
|
|
240
|
+
* @param {Object} options - Analysis options
|
|
241
|
+
* @param {string} options.prompt - Specific prompt file path (optional)
|
|
242
|
+
* @param {string} options.promptsDir - Path to prompts directory
|
|
243
|
+
* @param {boolean} options.verbose - Include LOW certainty issues
|
|
244
|
+
* @returns {Object|Array} Analysis results
|
|
245
|
+
*/
|
|
246
|
+
function analyze(options = {}) {
|
|
247
|
+
const {
|
|
248
|
+
prompt,
|
|
249
|
+
promptsDir,
|
|
250
|
+
verbose = false
|
|
251
|
+
} = options;
|
|
252
|
+
|
|
253
|
+
if (prompt) {
|
|
254
|
+
// Check if prompt is a directory or file
|
|
255
|
+
try {
|
|
256
|
+
const stats = fs.statSync(prompt);
|
|
257
|
+
if (stats.isDirectory()) {
|
|
258
|
+
return analyzeAllPrompts(prompt, { verbose });
|
|
259
|
+
} else {
|
|
260
|
+
return analyzePrompt(prompt, { verbose });
|
|
261
|
+
}
|
|
262
|
+
} catch (err) {
|
|
263
|
+
// If doesn't exist, let analyzePrompt handle the error
|
|
264
|
+
return analyzePrompt(prompt, { verbose });
|
|
265
|
+
}
|
|
266
|
+
} else if (promptsDir) {
|
|
267
|
+
return analyzeAllPrompts(promptsDir, { verbose });
|
|
268
|
+
} else {
|
|
269
|
+
// Default: analyze common prompt locations
|
|
270
|
+
const defaultDirs = ['prompts', 'agents', 'commands', 'skills'];
|
|
271
|
+
const allResults = [];
|
|
272
|
+
|
|
273
|
+
for (const dir of defaultDirs) {
|
|
274
|
+
if (fs.existsSync(dir)) {
|
|
275
|
+
const results = analyzeAllPrompts(dir, { verbose });
|
|
276
|
+
allResults.push(...results);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return allResults.length > 0 ? allResults : [];
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Apply fixes to analysis results
|
|
286
|
+
* Currently only aggressive_emphasis is auto-fixable
|
|
287
|
+
* @param {Object|Array} results - Analysis results
|
|
288
|
+
* @param {Object} options - Fix options
|
|
289
|
+
* @returns {Object} Fix results
|
|
290
|
+
*/
|
|
291
|
+
function applyFixes(results, options = {}) {
|
|
292
|
+
const { dryRun = false, backup = true } = options;
|
|
293
|
+
|
|
294
|
+
const fixResults = {
|
|
295
|
+
applied: [],
|
|
296
|
+
skipped: [],
|
|
297
|
+
errors: []
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
// Collect all issues
|
|
301
|
+
let allIssues = [];
|
|
302
|
+
|
|
303
|
+
if (Array.isArray(results)) {
|
|
304
|
+
for (const r of results) {
|
|
305
|
+
allIssues.push(...(r.clarityIssues || []));
|
|
306
|
+
allIssues.push(...(r.structureIssues || []));
|
|
307
|
+
allIssues.push(...(r.exampleIssues || []));
|
|
308
|
+
allIssues.push(...(r.contextIssues || []));
|
|
309
|
+
allIssues.push(...(r.outputIssues || []));
|
|
310
|
+
allIssues.push(...(r.antiPatternIssues || []));
|
|
311
|
+
allIssues.push(...(r.codeValidationIssues || []));
|
|
312
|
+
}
|
|
313
|
+
} else {
|
|
314
|
+
allIssues.push(...(results.clarityIssues || []));
|
|
315
|
+
allIssues.push(...(results.structureIssues || []));
|
|
316
|
+
allIssues.push(...(results.exampleIssues || []));
|
|
317
|
+
allIssues.push(...(results.contextIssues || []));
|
|
318
|
+
allIssues.push(...(results.outputIssues || []));
|
|
319
|
+
allIssues.push(...(results.antiPatternIssues || []));
|
|
320
|
+
allIssues.push(...(results.codeValidationIssues || []));
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Filter to auto-fixable HIGH certainty issues
|
|
324
|
+
const fixableIssues = allIssues.filter(i =>
|
|
325
|
+
i.certainty === 'HIGH' && i.autoFix
|
|
326
|
+
);
|
|
327
|
+
|
|
328
|
+
// Group by file
|
|
329
|
+
const byFile = new Map();
|
|
330
|
+
for (const issue of fixableIssues) {
|
|
331
|
+
const fp = issue.file;
|
|
332
|
+
if (!byFile.has(fp)) {
|
|
333
|
+
byFile.set(fp, []);
|
|
334
|
+
}
|
|
335
|
+
byFile.get(fp).push(issue);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Process each file
|
|
339
|
+
for (const [filePath, fileIssues] of byFile) {
|
|
340
|
+
try {
|
|
341
|
+
if (!fs.existsSync(filePath)) {
|
|
342
|
+
fixResults.errors.push({ filePath, error: 'File not found' });
|
|
343
|
+
continue;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
let content = fs.readFileSync(filePath, 'utf8');
|
|
347
|
+
const appliedToFile = [];
|
|
348
|
+
|
|
349
|
+
for (const issue of fileIssues) {
|
|
350
|
+
try {
|
|
351
|
+
if (issue.patternId === 'aggressive_emphasis') {
|
|
352
|
+
content = fixAggressiveEmphasis(content);
|
|
353
|
+
appliedToFile.push({
|
|
354
|
+
issue: issue.issue,
|
|
355
|
+
fix: 'Reduced aggressive emphasis',
|
|
356
|
+
filePath
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
// Add more fixers as needed
|
|
360
|
+
} catch (err) {
|
|
361
|
+
fixResults.errors.push({
|
|
362
|
+
issue: issue.issue,
|
|
363
|
+
filePath,
|
|
364
|
+
error: err.message
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// Write changes
|
|
370
|
+
if (!dryRun && appliedToFile.length > 0) {
|
|
371
|
+
if (backup) {
|
|
372
|
+
fs.writeFileSync(`${filePath}.backup`, fs.readFileSync(filePath, 'utf8'), 'utf8');
|
|
373
|
+
}
|
|
374
|
+
fs.writeFileSync(filePath, content, 'utf8');
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
fixResults.applied.push(...appliedToFile);
|
|
378
|
+
|
|
379
|
+
} catch (err) {
|
|
380
|
+
fixResults.errors.push({
|
|
381
|
+
filePath,
|
|
382
|
+
error: err.message
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
return fixResults;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Fix aggressive emphasis in content
|
|
392
|
+
* @param {string} content - Content to fix
|
|
393
|
+
* @returns {string} Fixed content
|
|
394
|
+
*/
|
|
395
|
+
function fixAggressiveEmphasis(content) {
|
|
396
|
+
if (!content) return content;
|
|
397
|
+
|
|
398
|
+
// Replace aggressive CAPS phrases with normal case
|
|
399
|
+
// Note: These should align with words detected by aggressive_emphasis pattern
|
|
400
|
+
const replacements = [
|
|
401
|
+
{ pattern: /\bCRITICAL\b/g, replacement: 'critical' },
|
|
402
|
+
{ pattern: /\bIMPORTANT\b/g, replacement: 'important' },
|
|
403
|
+
{ pattern: /\bMUST\b/g, replacement: 'must' },
|
|
404
|
+
{ pattern: /\bNEVER\b/g, replacement: 'never' },
|
|
405
|
+
{ pattern: /\bALWAYS\b/g, replacement: 'always' },
|
|
406
|
+
{ pattern: /\bREQUIRED\b/g, replacement: 'required' },
|
|
407
|
+
{ pattern: /\bMANDATORY\b/g, replacement: 'mandatory' },
|
|
408
|
+
{ pattern: /\bESSENTIAL\b/g, replacement: 'essential' },
|
|
409
|
+
{ pattern: /\bWARNING\b/g, replacement: 'warning' },
|
|
410
|
+
{ pattern: /\bCAUTION\b/g, replacement: 'caution' },
|
|
411
|
+
// Additional aggressive words detected by pattern
|
|
412
|
+
{ pattern: /\bABSOLUTELY\b/g, replacement: 'absolutely' },
|
|
413
|
+
{ pattern: /\bTOTALLY\b/g, replacement: 'totally' },
|
|
414
|
+
{ pattern: /\bEXTREMELY\b/g, replacement: 'extremely' },
|
|
415
|
+
{ pattern: /\bDEFINITELY\b/g, replacement: 'definitely' },
|
|
416
|
+
{ pattern: /\bCOMPLETELY\b/g, replacement: 'completely' },
|
|
417
|
+
{ pattern: /\bENTIRELY\b/g, replacement: 'entirely' },
|
|
418
|
+
{ pattern: /\bFORBIDDEN\b/g, replacement: 'forbidden' },
|
|
419
|
+
{ pattern: /\bURGENT\b/g, replacement: 'urgent' }
|
|
420
|
+
];
|
|
421
|
+
|
|
422
|
+
let result = content;
|
|
423
|
+
for (const { pattern, replacement } of replacements) {
|
|
424
|
+
result = result.replace(pattern, replacement);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// Reduce multiple exclamation marks
|
|
428
|
+
result = result.replace(/!{2,}/g, '!');
|
|
429
|
+
|
|
430
|
+
return result;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* Generate report from analysis results
|
|
435
|
+
* @param {Object|Array} results - Analysis results
|
|
436
|
+
* @param {Object} options - Report options
|
|
437
|
+
* @returns {string} Markdown report
|
|
438
|
+
*/
|
|
439
|
+
function generateReport(results, options = {}) {
|
|
440
|
+
if (Array.isArray(results)) {
|
|
441
|
+
return reporter.generatePromptSummaryReport(results, options);
|
|
442
|
+
} else {
|
|
443
|
+
return reporter.generatePromptReport(results, options);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
module.exports = {
|
|
448
|
+
analyzePrompt,
|
|
449
|
+
analyzeAllPrompts,
|
|
450
|
+
analyze,
|
|
451
|
+
applyFixes,
|
|
452
|
+
fixAggressiveEmphasis,
|
|
453
|
+
generateReport,
|
|
454
|
+
detectPromptType,
|
|
455
|
+
estimateTokens,
|
|
456
|
+
extractCodeBlocks
|
|
457
|
+
};
|