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,721 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin Analysis Fixer
|
|
3
|
+
* @author Avi Fenesh
|
|
4
|
+
* @license MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
|
|
10
|
+
function applyFixes(issues, options = {}) {
|
|
11
|
+
const { dryRun = false, backup = true } = options;
|
|
12
|
+
|
|
13
|
+
const results = {
|
|
14
|
+
applied: [],
|
|
15
|
+
skipped: [],
|
|
16
|
+
errors: []
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// Auto-fixable pattern IDs for markdown files
|
|
20
|
+
const markdownAutoFixPatternIds = [
|
|
21
|
+
// Agent patterns
|
|
22
|
+
'missing_frontmatter',
|
|
23
|
+
'unrestricted_bash',
|
|
24
|
+
'missing_role',
|
|
25
|
+
// Prompt patterns
|
|
26
|
+
'missing_output_format',
|
|
27
|
+
'missing_examples',
|
|
28
|
+
'missing_xml_structure',
|
|
29
|
+
'missing_verification_criteria',
|
|
30
|
+
'aggressive_emphasis',
|
|
31
|
+
// Skill patterns
|
|
32
|
+
'missing_trigger_phrase'
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
// Filter to only HIGH certainty issues that are auto-fixable
|
|
36
|
+
// Includes: JSON issues with autoFixFn OR markdown issues with known pattern IDs
|
|
37
|
+
const fixableIssues = issues.filter(i =>
|
|
38
|
+
i.certainty === 'HIGH' &&
|
|
39
|
+
(i.filePath || i.file) &&
|
|
40
|
+
(i.autoFixFn || markdownAutoFixPatternIds.includes(i.patternId))
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
// Group by file to minimize reads/writes
|
|
44
|
+
const byFile = new Map();
|
|
45
|
+
for (const issue of fixableIssues) {
|
|
46
|
+
const fp = issue.filePath || issue.file;
|
|
47
|
+
if (!byFile.has(fp)) {
|
|
48
|
+
byFile.set(fp, []);
|
|
49
|
+
}
|
|
50
|
+
byFile.get(fp).push(issue);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Process each file
|
|
54
|
+
for (const [filePath, fileIssues] of byFile) {
|
|
55
|
+
try {
|
|
56
|
+
// Read current content
|
|
57
|
+
if (!fs.existsSync(filePath)) {
|
|
58
|
+
results.errors.push({ filePath, error: 'File not found' });
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
63
|
+
let data;
|
|
64
|
+
|
|
65
|
+
// Parse based on file type
|
|
66
|
+
if (filePath.endsWith('.json')) {
|
|
67
|
+
data = JSON.parse(content);
|
|
68
|
+
} else if (filePath.endsWith('.md')) {
|
|
69
|
+
// Markdown files - handle specially
|
|
70
|
+
data = content;
|
|
71
|
+
} else {
|
|
72
|
+
// For other files, skip auto-fix
|
|
73
|
+
results.skipped.push(...fileIssues.map(i => ({
|
|
74
|
+
...i,
|
|
75
|
+
reason: 'Unsupported file type - manual fix required'
|
|
76
|
+
})));
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Apply each fix
|
|
81
|
+
let modified = data;
|
|
82
|
+
const appliedToFile = [];
|
|
83
|
+
|
|
84
|
+
for (const issue of fileIssues) {
|
|
85
|
+
try {
|
|
86
|
+
// Determine what part of data to fix
|
|
87
|
+
if (filePath.endsWith('.md')) {
|
|
88
|
+
// Markdown-specific fixes
|
|
89
|
+
if (issue.patternId === 'missing_frontmatter') {
|
|
90
|
+
modified = fixMissingFrontmatter(modified);
|
|
91
|
+
} else if (issue.patternId === 'unrestricted_bash') {
|
|
92
|
+
modified = fixUnrestrictedBash(modified);
|
|
93
|
+
} else if (issue.patternId === 'missing_role') {
|
|
94
|
+
modified = fixMissingRole(modified);
|
|
95
|
+
} else if (issue.patternId === 'missing_output_format') {
|
|
96
|
+
modified = fixMissingOutputFormat(modified);
|
|
97
|
+
} else if (issue.patternId === 'missing_examples') {
|
|
98
|
+
modified = fixMissingExamples(modified);
|
|
99
|
+
} else if (issue.patternId === 'missing_xml_structure') {
|
|
100
|
+
modified = fixMissingXmlStructure(modified);
|
|
101
|
+
} else if (issue.patternId === 'missing_verification_criteria') {
|
|
102
|
+
modified = fixMissingVerificationCriteria(modified);
|
|
103
|
+
} else if (issue.patternId === 'aggressive_emphasis') {
|
|
104
|
+
modified = fixAggressiveEmphasis(modified);
|
|
105
|
+
} else if (issue.patternId === 'missing_trigger_phrase') {
|
|
106
|
+
modified = fixMissingTriggerPhrase(modified);
|
|
107
|
+
} else {
|
|
108
|
+
// No auto-fix available for this markdown issue
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
} else if (issue.schemaPath) {
|
|
112
|
+
// Fix at specific path in the data
|
|
113
|
+
modified = applyAtPath(modified, issue.schemaPath, issue.autoFixFn);
|
|
114
|
+
} else {
|
|
115
|
+
// Apply to root
|
|
116
|
+
modified = issue.autoFixFn(modified);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
appliedToFile.push({
|
|
120
|
+
issue: issue.issue,
|
|
121
|
+
fix: issue.fix,
|
|
122
|
+
filePath
|
|
123
|
+
});
|
|
124
|
+
} catch (err) {
|
|
125
|
+
results.errors.push({
|
|
126
|
+
issue: issue.issue,
|
|
127
|
+
filePath,
|
|
128
|
+
error: err.message
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Write changes
|
|
134
|
+
if (!dryRun && appliedToFile.length > 0) {
|
|
135
|
+
// Create backup
|
|
136
|
+
if (backup) {
|
|
137
|
+
const backupPath = `${filePath}.backup`;
|
|
138
|
+
fs.writeFileSync(backupPath, content, 'utf8');
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Write modified content
|
|
142
|
+
let newContent;
|
|
143
|
+
if (filePath.endsWith('.md')) {
|
|
144
|
+
newContent = modified; // Already a string
|
|
145
|
+
} else {
|
|
146
|
+
newContent = JSON.stringify(modified, null, 2);
|
|
147
|
+
}
|
|
148
|
+
fs.writeFileSync(filePath, newContent, 'utf8');
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
results.applied.push(...appliedToFile);
|
|
152
|
+
|
|
153
|
+
} catch (err) {
|
|
154
|
+
results.errors.push({
|
|
155
|
+
filePath,
|
|
156
|
+
error: err.message
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Add non-fixable issues to skipped
|
|
162
|
+
const nonFixable = issues.filter(i =>
|
|
163
|
+
i.certainty !== 'HIGH' || !markdownAutoFixPatternIds.includes(i.patternId)
|
|
164
|
+
);
|
|
165
|
+
results.skipped.push(...nonFixable.map(i => ({
|
|
166
|
+
...i,
|
|
167
|
+
reason: i.certainty !== 'HIGH' ? 'Not HIGH certainty' : 'No auto-fix available for this pattern'
|
|
168
|
+
})));
|
|
169
|
+
|
|
170
|
+
return results;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function applyAtPath(obj, pathStr, fixFn) {
|
|
174
|
+
const parts = pathStr.split('.');
|
|
175
|
+
const result = structuredClone(obj);
|
|
176
|
+
|
|
177
|
+
let current = result;
|
|
178
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
179
|
+
const part = parts[i];
|
|
180
|
+
if (part.includes('[')) {
|
|
181
|
+
// Array access
|
|
182
|
+
const match = part.match(/^((?!__proto__|constructor|prototype)[a-zA-Z_]\w*)\[(\d{1,10})\]$/);
|
|
183
|
+
if (match) {
|
|
184
|
+
current = current[match[1]][parseInt(match[2], 10)];
|
|
185
|
+
}
|
|
186
|
+
} else {
|
|
187
|
+
current = current[part];
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const lastPart = parts[parts.length - 1];
|
|
192
|
+
if (lastPart.includes('[')) {
|
|
193
|
+
const match = lastPart.match(/^((?!__proto__|constructor|prototype)[a-zA-Z_]\w*)\[(\d{1,10})\]$/);
|
|
194
|
+
if (match) {
|
|
195
|
+
current[match[1]][parseInt(match[2], 10)] = fixFn(current[match[1]][parseInt(match[2], 10)]);
|
|
196
|
+
}
|
|
197
|
+
} else {
|
|
198
|
+
current[lastPart] = fixFn(current[lastPart]);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return result;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function fixAdditionalProperties(schema) {
|
|
205
|
+
if (!schema || typeof schema !== 'object') return schema;
|
|
206
|
+
|
|
207
|
+
const fixed = { ...schema };
|
|
208
|
+
|
|
209
|
+
if (fixed.type === 'object' && fixed.properties) {
|
|
210
|
+
fixed.additionalProperties = false;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Recursively fix nested schemas
|
|
214
|
+
if (fixed.properties) {
|
|
215
|
+
fixed.properties = {};
|
|
216
|
+
for (const [key, value] of Object.entries(schema.properties)) {
|
|
217
|
+
fixed.properties[key] = fixAdditionalProperties(value);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return fixed;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function fixRequiredFields(schema) {
|
|
225
|
+
if (!schema || typeof schema !== 'object') return schema;
|
|
226
|
+
|
|
227
|
+
const fixed = { ...schema };
|
|
228
|
+
|
|
229
|
+
if (fixed.type === 'object' && fixed.properties && !fixed.required) {
|
|
230
|
+
// Add all non-optional fields to required
|
|
231
|
+
fixed.required = Object.entries(fixed.properties)
|
|
232
|
+
.filter(([_, prop]) => {
|
|
233
|
+
// Skip if has default or marked optional in description
|
|
234
|
+
if (prop.default !== undefined) return false;
|
|
235
|
+
if (prop.description && /optional/i.test(prop.description)) return false;
|
|
236
|
+
return true;
|
|
237
|
+
})
|
|
238
|
+
.map(([key]) => key);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return fixed;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function fixVersionMismatch(pluginJson, targetVersion) {
|
|
245
|
+
return {
|
|
246
|
+
...pluginJson,
|
|
247
|
+
version: targetVersion
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function previewFixes(issues) {
|
|
252
|
+
const previews = [];
|
|
253
|
+
|
|
254
|
+
for (const issue of issues) {
|
|
255
|
+
if (issue.certainty === 'HIGH' && issue.autoFixFn) {
|
|
256
|
+
previews.push({
|
|
257
|
+
filePath: issue.filePath,
|
|
258
|
+
issue: issue.issue,
|
|
259
|
+
fix: issue.fix,
|
|
260
|
+
willApply: true
|
|
261
|
+
});
|
|
262
|
+
} else {
|
|
263
|
+
previews.push({
|
|
264
|
+
filePath: issue.filePath,
|
|
265
|
+
issue: issue.issue,
|
|
266
|
+
fix: issue.fix || 'No auto-fix available',
|
|
267
|
+
willApply: false,
|
|
268
|
+
reason: issue.certainty !== 'HIGH' ? 'Not HIGH certainty' : 'No auto-fix function'
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return previews;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function restoreFromBackup(filePath) {
|
|
277
|
+
const backupPath = `${filePath}.backup`;
|
|
278
|
+
|
|
279
|
+
if (!fs.existsSync(backupPath)) {
|
|
280
|
+
return false;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const backupContent = fs.readFileSync(backupPath, 'utf8');
|
|
284
|
+
fs.writeFileSync(filePath, backupContent, 'utf8');
|
|
285
|
+
fs.unlinkSync(backupPath);
|
|
286
|
+
|
|
287
|
+
return true;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function cleanupBackups(directory) {
|
|
291
|
+
let count = 0;
|
|
292
|
+
|
|
293
|
+
function findBackups(dir) {
|
|
294
|
+
let entries;
|
|
295
|
+
try {
|
|
296
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
297
|
+
} catch (err) {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
for (const entry of entries) {
|
|
302
|
+
const fullPath = path.join(dir, entry.name);
|
|
303
|
+
if (entry.isDirectory()) {
|
|
304
|
+
findBackups(fullPath);
|
|
305
|
+
} else if (entry.isFile() && entry.name.endsWith('.backup')) {
|
|
306
|
+
try {
|
|
307
|
+
fs.unlinkSync(fullPath);
|
|
308
|
+
count++;
|
|
309
|
+
} catch (err) {
|
|
310
|
+
console.error('[WARN] fixer error:', err.message);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
findBackups(directory);
|
|
317
|
+
return count;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function fixMissingFrontmatter(content) {
|
|
321
|
+
if (!content || typeof content !== 'string') return content;
|
|
322
|
+
|
|
323
|
+
const template = `---
|
|
324
|
+
name: agent-name
|
|
325
|
+
description: Agent description
|
|
326
|
+
tools: Read, Glob, Grep
|
|
327
|
+
model: sonnet
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
`;
|
|
331
|
+
|
|
332
|
+
return template + content.trim();
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function fixUnrestrictedBash(content) {
|
|
336
|
+
if (!content || typeof content !== 'string') return content;
|
|
337
|
+
|
|
338
|
+
const lines = content.split('\n');
|
|
339
|
+
let inFrontmatter = false;
|
|
340
|
+
|
|
341
|
+
for (let i = 0; i < lines.length; i++) {
|
|
342
|
+
if (lines[i].trim() === '---') {
|
|
343
|
+
if (!inFrontmatter) {
|
|
344
|
+
inFrontmatter = true;
|
|
345
|
+
} else {
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
348
|
+
} else if (inFrontmatter && lines[i].startsWith('tools:')) {
|
|
349
|
+
lines[i] = lines[i].replace(/\bBash\b(?!\()/g, 'Bash(git:*)');
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return lines.join('\n');
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function fixMissingRole(content) {
|
|
357
|
+
if (!content || typeof content !== 'string') return content;
|
|
358
|
+
|
|
359
|
+
const lines = content.split('\n');
|
|
360
|
+
let frontmatterEnd = -1;
|
|
361
|
+
let inFrontmatter = false;
|
|
362
|
+
|
|
363
|
+
for (let i = 0; i < lines.length; i++) {
|
|
364
|
+
if (lines[i].trim() === '---') {
|
|
365
|
+
if (!inFrontmatter) {
|
|
366
|
+
inFrontmatter = true;
|
|
367
|
+
} else {
|
|
368
|
+
frontmatterEnd = i;
|
|
369
|
+
break;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const roleSection = `
|
|
375
|
+
## Your Role
|
|
376
|
+
|
|
377
|
+
You are an agent that [describe agent purpose].
|
|
378
|
+
`;
|
|
379
|
+
|
|
380
|
+
if (frontmatterEnd >= 0) {
|
|
381
|
+
lines.splice(frontmatterEnd + 1, 0, roleSection);
|
|
382
|
+
} else {
|
|
383
|
+
lines.unshift(roleSection);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
return lines.join('\n');
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
function fixInconsistentHeadings(content) {
|
|
390
|
+
if (!content || typeof content !== 'string') return content;
|
|
391
|
+
|
|
392
|
+
const lines = content.split('\n');
|
|
393
|
+
let lastLevel = 0;
|
|
394
|
+
let inCodeBlock = false;
|
|
395
|
+
|
|
396
|
+
for (let i = 0; i < lines.length; i++) {
|
|
397
|
+
const line = lines[i];
|
|
398
|
+
|
|
399
|
+
if (line.startsWith('```')) {
|
|
400
|
+
inCodeBlock = !inCodeBlock;
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (inCodeBlock) continue;
|
|
405
|
+
|
|
406
|
+
const headingMatch = line.match(/^(#{1,6})[ \t]+(\S.*)$/);
|
|
407
|
+
if (headingMatch) {
|
|
408
|
+
const currentLevel = headingMatch[1].length;
|
|
409
|
+
const headingText = headingMatch[2];
|
|
410
|
+
|
|
411
|
+
if (lastLevel === 0) {
|
|
412
|
+
lastLevel = currentLevel;
|
|
413
|
+
continue;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// If jumping more than one level down, fix it
|
|
417
|
+
if (currentLevel > lastLevel + 1) {
|
|
418
|
+
const fixedLevel = lastLevel + 1;
|
|
419
|
+
lines[i] = '#'.repeat(fixedLevel) + ' ' + headingText;
|
|
420
|
+
lastLevel = fixedLevel;
|
|
421
|
+
} else {
|
|
422
|
+
lastLevel = currentLevel;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
return lines.join('\n');
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
function fixVerboseExplanations(content) {
|
|
431
|
+
if (!content || typeof content !== 'string') return content;
|
|
432
|
+
|
|
433
|
+
const replacements = [
|
|
434
|
+
{ from: /\bin order to\b/gi, to: 'to' },
|
|
435
|
+
{ from: /\bfor the purpose of\b/gi, to: 'for' },
|
|
436
|
+
{ from: /\bin the event that\b/gi, to: 'if' },
|
|
437
|
+
{ from: /\bat this point in time\b/gi, to: 'now' },
|
|
438
|
+
{ from: /\bdue to the fact that\b/gi, to: 'because' },
|
|
439
|
+
{ from: /\bhas the ability to\b/gi, to: 'can' },
|
|
440
|
+
{ from: /\bis able to\b/gi, to: 'can' },
|
|
441
|
+
{ from: /\bmake use of\b/gi, to: 'use' },
|
|
442
|
+
{ from: /\ba large number of\b/gi, to: 'many' },
|
|
443
|
+
{ from: /\ba small number of\b/gi, to: 'few' },
|
|
444
|
+
{ from: /\bthe majority of\b/gi, to: 'most' },
|
|
445
|
+
{ from: /\bprior to\b/gi, to: 'before' },
|
|
446
|
+
{ from: /\bsubsequent to\b/gi, to: 'after' }
|
|
447
|
+
];
|
|
448
|
+
|
|
449
|
+
let result = content;
|
|
450
|
+
|
|
451
|
+
const codeBlockRegex = /```[\s\S]*?```/g;
|
|
452
|
+
const codeBlocks = [];
|
|
453
|
+
let placeholder = 0;
|
|
454
|
+
|
|
455
|
+
result = result.replace(codeBlockRegex, (match) => {
|
|
456
|
+
codeBlocks.push(match);
|
|
457
|
+
return `__CODE_BLOCK_${placeholder++}__`;
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
for (const { from, to } of replacements) {
|
|
461
|
+
result = result.replace(from, (match) => {
|
|
462
|
+
// Preserve case of first character
|
|
463
|
+
if (match[0] === match[0].toUpperCase()) {
|
|
464
|
+
return to[0].toUpperCase() + to.slice(1);
|
|
465
|
+
}
|
|
466
|
+
return to;
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
for (let i = 0; i < codeBlocks.length; i++) {
|
|
471
|
+
result = result.replace(`__CODE_BLOCK_${i}__`, codeBlocks[i]);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
return result;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// ============================================
|
|
478
|
+
// PROMPT AUTO-FIX FUNCTIONS
|
|
479
|
+
// ============================================
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Add output format section to prompt
|
|
483
|
+
* @param {string} content - Prompt content
|
|
484
|
+
* @returns {string} Fixed content
|
|
485
|
+
*/
|
|
486
|
+
function fixMissingOutputFormat(content) {
|
|
487
|
+
if (!content || typeof content !== 'string') return content;
|
|
488
|
+
|
|
489
|
+
// Don't add if already has output format
|
|
490
|
+
if (/##\s*output\s*format/i.test(content) || /<output_format>/i.test(content)) {
|
|
491
|
+
return content;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
const outputSection = `
|
|
495
|
+
|
|
496
|
+
## Output Format
|
|
497
|
+
|
|
498
|
+
Respond with:
|
|
499
|
+
- [Describe expected format: JSON, markdown, plain text, etc.]
|
|
500
|
+
- [Include any specific structure requirements]
|
|
501
|
+
`;
|
|
502
|
+
|
|
503
|
+
return content.trim() + outputSection;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Add example section to prompt
|
|
508
|
+
* @param {string} content - Prompt content
|
|
509
|
+
* @returns {string} Fixed content
|
|
510
|
+
*/
|
|
511
|
+
function fixMissingExamples(content) {
|
|
512
|
+
if (!content || typeof content !== 'string') return content;
|
|
513
|
+
|
|
514
|
+
// Don't add if already has examples
|
|
515
|
+
if (/<example>|##\s*example/i.test(content)) {
|
|
516
|
+
return content;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
const exampleSection = `
|
|
520
|
+
|
|
521
|
+
## Examples
|
|
522
|
+
|
|
523
|
+
<good-example>
|
|
524
|
+
Input: [example input]
|
|
525
|
+
Output: [example output]
|
|
526
|
+
</good-example>
|
|
527
|
+
|
|
528
|
+
<bad-example>
|
|
529
|
+
Input: [example input]
|
|
530
|
+
Output: [what NOT to do]
|
|
531
|
+
Why bad: [explanation]
|
|
532
|
+
</bad-example>
|
|
533
|
+
`;
|
|
534
|
+
|
|
535
|
+
return content.trim() + exampleSection;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Wrap a markdown section (heading to next heading/separator) in XML tags.
|
|
540
|
+
* Uses line-by-line scanning to avoid ReDoS from [\s\S]*? with lookaheads.
|
|
541
|
+
*/
|
|
542
|
+
function wrapSection(text, headingPattern, tagName) {
|
|
543
|
+
const lines = text.split('\n');
|
|
544
|
+
let sectionStart = -1;
|
|
545
|
+
for (let i = 0; i < lines.length; i++) {
|
|
546
|
+
if (sectionStart === -1) {
|
|
547
|
+
if (headingPattern.test(lines[i])) {
|
|
548
|
+
sectionStart = i;
|
|
549
|
+
}
|
|
550
|
+
} else {
|
|
551
|
+
// End section at next heading or horizontal rule
|
|
552
|
+
if (/^#{1,6}\s/.test(lines[i]) || /^---/.test(lines[i])) {
|
|
553
|
+
const before = lines.slice(0, sectionStart);
|
|
554
|
+
const section = lines.slice(sectionStart, i);
|
|
555
|
+
const after = lines.slice(i);
|
|
556
|
+
return [...before, `<${tagName}>`, ...section, `</${tagName}>`, ...after].join('\n');
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
// Section runs to end of content
|
|
561
|
+
if (sectionStart !== -1) {
|
|
562
|
+
const before = lines.slice(0, sectionStart);
|
|
563
|
+
const section = lines.slice(sectionStart);
|
|
564
|
+
return [...before, `<${tagName}>`, ...section, `</${tagName}>`].join('\n');
|
|
565
|
+
}
|
|
566
|
+
return text;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
/**
|
|
570
|
+
* Add XML structure tags to complex prompt
|
|
571
|
+
* @param {string} content - Prompt content
|
|
572
|
+
* @returns {string} Fixed content
|
|
573
|
+
*/
|
|
574
|
+
function fixMissingXmlStructure(content) {
|
|
575
|
+
if (!content || typeof content !== 'string') return content;
|
|
576
|
+
|
|
577
|
+
// Don't add if already has XML
|
|
578
|
+
if (/<[a-z_][a-z0-9_-]*>/i.test(content)) {
|
|
579
|
+
return content;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
// Wrap role section if exists
|
|
583
|
+
let result = content;
|
|
584
|
+
|
|
585
|
+
// Find and wrap role section (use non-regex approach to avoid ReDoS)
|
|
586
|
+
result = wrapSection(result, /^##[ \t]*(?:your[ \t]+)?role[ \t]*$/im, 'role');
|
|
587
|
+
|
|
588
|
+
// Find and wrap constraints section
|
|
589
|
+
result = wrapSection(result, /^##[ \t]*(?:constraints?|rules?)[ \t]*$/im, 'constraints');
|
|
590
|
+
|
|
591
|
+
return result;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Add verification criteria to task prompt
|
|
596
|
+
* @param {string} content - Prompt content
|
|
597
|
+
* @returns {string} Fixed content
|
|
598
|
+
*/
|
|
599
|
+
function fixMissingVerificationCriteria(content) {
|
|
600
|
+
if (!content || typeof content !== 'string') return content;
|
|
601
|
+
|
|
602
|
+
// Don't add if already has verification
|
|
603
|
+
if (/\bverif|test|validate|expected\s+output/i.test(content)) {
|
|
604
|
+
return content;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
const verificationSection = `
|
|
608
|
+
|
|
609
|
+
## Verification
|
|
610
|
+
|
|
611
|
+
After completing this task:
|
|
612
|
+
- [ ] Run relevant tests to verify the change works
|
|
613
|
+
- [ ] Check for regressions in related functionality
|
|
614
|
+
- [ ] Verify expected output matches: [describe expected result]
|
|
615
|
+
`;
|
|
616
|
+
|
|
617
|
+
return content.trim() + verificationSection;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
/**
|
|
621
|
+
* Add trigger phrase to skill description
|
|
622
|
+
* @param {string} content - SKILL.md content
|
|
623
|
+
* @returns {string} Fixed content
|
|
624
|
+
*/
|
|
625
|
+
function fixMissingTriggerPhrase(content) {
|
|
626
|
+
if (!content || typeof content !== 'string') return content;
|
|
627
|
+
|
|
628
|
+
const lines = content.split('\n');
|
|
629
|
+
let inFrontmatter = false;
|
|
630
|
+
let descriptionLineIndex = -1;
|
|
631
|
+
|
|
632
|
+
for (let i = 0; i < lines.length; i++) {
|
|
633
|
+
if (lines[i].trim() === '---') {
|
|
634
|
+
if (!inFrontmatter) {
|
|
635
|
+
inFrontmatter = true;
|
|
636
|
+
} else {
|
|
637
|
+
break;
|
|
638
|
+
}
|
|
639
|
+
} else if (inFrontmatter && lines[i].startsWith('description:')) {
|
|
640
|
+
descriptionLineIndex = i;
|
|
641
|
+
break;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
if (descriptionLineIndex >= 0) {
|
|
646
|
+
const descLine = lines[descriptionLineIndex];
|
|
647
|
+
// Check if already has trigger phrase
|
|
648
|
+
if (!/use when user asks/i.test(descLine)) {
|
|
649
|
+
// Extract current description
|
|
650
|
+
const match = descLine.match(/^description:[ \t]*(\S.*)$/);
|
|
651
|
+
if (match) {
|
|
652
|
+
const currentDesc = match[1].trim();
|
|
653
|
+
// Add trigger phrase
|
|
654
|
+
lines[descriptionLineIndex] = `description: Use when user asks to ${currentDesc.toLowerCase().replace(/^to\s+/i, '')}`;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
return lines.join('\n');
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
/**
|
|
663
|
+
* Reduce aggressive emphasis (CAPS, !!)
|
|
664
|
+
* @param {string} content - Prompt content
|
|
665
|
+
* @returns {string} Fixed content
|
|
666
|
+
*/
|
|
667
|
+
function fixAggressiveEmphasis(content) {
|
|
668
|
+
if (!content || typeof content !== 'string') return content;
|
|
669
|
+
|
|
670
|
+
let result = content;
|
|
671
|
+
|
|
672
|
+
// Preserve code blocks
|
|
673
|
+
const codeBlocks = [];
|
|
674
|
+
let placeholder = 0;
|
|
675
|
+
result = result.replace(/```[\s\S]*?```/g, (match) => {
|
|
676
|
+
codeBlocks.push(match);
|
|
677
|
+
return `__CODE_BLOCK_${placeholder++}__`;
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
// Acceptable CAPS to preserve
|
|
681
|
+
const acceptableCaps = ['API', 'JSON', 'XML', 'HTML', 'CSS', 'URL', 'HTTP', 'HTTPS', 'SQL', 'CLI', 'SDK', 'JWT', 'UUID', 'REST', 'YAML', 'EOF', 'TODO', 'FIXME', 'NOTE', 'README', 'MCP', 'HIGH', 'MEDIUM', 'LOW'];
|
|
682
|
+
|
|
683
|
+
// Replace aggressive CAPS with normal case (except acceptable ones)
|
|
684
|
+
result = result.replace(/\b[A-Z]{3,}\b/g, (match) => {
|
|
685
|
+
if (acceptableCaps.includes(match)) return match;
|
|
686
|
+
// Convert to sentence case
|
|
687
|
+
return match.charAt(0) + match.slice(1).toLowerCase();
|
|
688
|
+
});
|
|
689
|
+
|
|
690
|
+
// Remove multiple exclamation marks
|
|
691
|
+
result = result.replace(/!{2,}/g, '!');
|
|
692
|
+
|
|
693
|
+
// Restore code blocks
|
|
694
|
+
for (let i = 0; i < codeBlocks.length; i++) {
|
|
695
|
+
result = result.replace(`__CODE_BLOCK_${i}__`, codeBlocks[i]);
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
return result;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
module.exports = {
|
|
702
|
+
applyFixes,
|
|
703
|
+
fixAdditionalProperties,
|
|
704
|
+
fixRequiredFields,
|
|
705
|
+
fixVersionMismatch,
|
|
706
|
+
fixMissingFrontmatter,
|
|
707
|
+
fixUnrestrictedBash,
|
|
708
|
+
fixMissingRole,
|
|
709
|
+
fixInconsistentHeadings,
|
|
710
|
+
fixVerboseExplanations,
|
|
711
|
+
// New prompt fixes
|
|
712
|
+
fixMissingOutputFormat,
|
|
713
|
+
fixMissingExamples,
|
|
714
|
+
fixMissingXmlStructure,
|
|
715
|
+
fixMissingVerificationCriteria,
|
|
716
|
+
fixMissingTriggerPhrase,
|
|
717
|
+
fixAggressiveEmphasis,
|
|
718
|
+
previewFixes,
|
|
719
|
+
restoreFromBackup,
|
|
720
|
+
cleanupBackups
|
|
721
|
+
};
|