@agentlee5/agent-skills 1.0.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/.leeway/config.json +133 -0
- package/LICENSE +21 -0
- package/LeeWay-Standards/LICENSE +21 -0
- package/LeeWay-Standards/README.md +324 -0
- package/LeeWay-Standards/examples/NexusButton.tsx +90 -0
- package/LeeWay-Standards/examples/example-agent.js +89 -0
- package/LeeWay-Standards/package.json +61 -0
- package/LeeWay-Standards/schemas/leeway-config.schema.json +81 -0
- package/LeeWay-Standards/schemas/leeway-header.schema.json +63 -0
- package/LeeWay-Standards/src/agents/discovery/architecture-map-agent.js +134 -0
- package/LeeWay-Standards/src/agents/discovery/docs-agent.js +126 -0
- package/LeeWay-Standards/src/agents/discovery/explain-agent.js +95 -0
- package/LeeWay-Standards/src/agents/discovery/intent-registry-agent.js +119 -0
- package/LeeWay-Standards/src/agents/discovery/schema-agent.js +116 -0
- package/LeeWay-Standards/src/agents/discovery/sitemap-agent.js +88 -0
- package/LeeWay-Standards/src/agents/governance/align-agent.js +155 -0
- package/LeeWay-Standards/src/agents/governance/assess-agent.js +161 -0
- package/LeeWay-Standards/src/agents/governance/audit-agent.js +185 -0
- package/LeeWay-Standards/src/agents/integrity/circular-dependency-agent.js +88 -0
- package/LeeWay-Standards/src/agents/integrity/dependency-graph-agent.js +107 -0
- package/LeeWay-Standards/src/agents/integrity/duplicate-logic-agent.js +108 -0
- package/LeeWay-Standards/src/agents/integrity/import-agent.js +83 -0
- package/LeeWay-Standards/src/agents/integrity/module-policy-agent.js +94 -0
- package/LeeWay-Standards/src/agents/integrity/refactor-scan-agent.js +113 -0
- package/LeeWay-Standards/src/agents/integrity/syntax-agent.js +84 -0
- package/LeeWay-Standards/src/agents/mcp/endpoint-agent.js +106 -0
- package/LeeWay-Standards/src/agents/mcp/env-agent.js +111 -0
- package/LeeWay-Standards/src/agents/mcp/health-agent-lite.js +119 -0
- package/LeeWay-Standards/src/agents/mcp/manifest-agent.js +87 -0
- package/LeeWay-Standards/src/agents/mcp/port-agent.js +125 -0
- package/LeeWay-Standards/src/agents/mcp/process-agent.js +124 -0
- package/LeeWay-Standards/src/agents/mcp/runtime-agent.js +108 -0
- package/LeeWay-Standards/src/agents/mcp/transport-agent.js +78 -0
- package/LeeWay-Standards/src/agents/orchestration/doctor-agent.js +149 -0
- package/LeeWay-Standards/src/agents/orchestration/memory-agent-lite.js +125 -0
- package/LeeWay-Standards/src/agents/orchestration/router-agent.js +110 -0
- package/LeeWay-Standards/src/agents/security/permission-agent.js +98 -0
- package/LeeWay-Standards/src/agents/security/policy-agent.js +100 -0
- package/LeeWay-Standards/src/agents/security/privacy-agent.js +83 -0
- package/LeeWay-Standards/src/agents/security/prompt-security-agent.js +103 -0
- package/LeeWay-Standards/src/agents/security/secret-scan-agent.js +108 -0
- package/LeeWay-Standards/src/agents/security/tool-access-agent.js +105 -0
- package/LeeWay-Standards/src/agents/standards/authority-agent.js +114 -0
- package/LeeWay-Standards/src/agents/standards/discovery-pipeline-agent.js +91 -0
- package/LeeWay-Standards/src/agents/standards/header-agent.js +120 -0
- package/LeeWay-Standards/src/agents/standards/placement-agent.js +96 -0
- package/LeeWay-Standards/src/agents/standards/region-agent.js +99 -0
- package/LeeWay-Standards/src/agents/standards/registry-agent.js +153 -0
- package/LeeWay-Standards/src/agents/standards/tag-agent.js +111 -0
- package/LeeWay-Standards/src/cli/leeway.js +225 -0
- package/LeeWay-Standards/src/core/compliance-scorer.js +168 -0
- package/LeeWay-Standards/src/core/compliance-scorer.test.js +121 -0
- package/LeeWay-Standards/src/core/header-parser.js +207 -0
- package/LeeWay-Standards/src/core/header-parser.test.js +198 -0
- package/LeeWay-Standards/src/core/region-classifier.js +137 -0
- package/LeeWay-Standards/src/core/region-classifier.test.js +100 -0
- package/LeeWay-Standards/src/core/tag-validator.js +139 -0
- package/LeeWay-Standards/src/core/tag-validator.test.js +109 -0
- package/LeeWay-Standards/src/index.js +83 -0
- package/README.md +217 -0
- package/agent-config.yaml +456 -0
- package/agentbage.png.png +0 -0
- package/bin/leeway-skills-badge.js +52 -0
- package/bin/leeway-skills-mcp.js +48 -0
- package/bin/leeway-skills.js +160 -0
- package/bin/leeway-standards.js +49 -0
- package/config/.skillsignore +63 -0
- package/config/skills-config.json +70 -0
- package/documents/AGENT_LEARNING_REFERENCE.md +329 -0
- package/documents/AGENT_LEE_INTEGRATION.md +534 -0
- package/documents/COMPLETE_SYSTEM_OVERVIEW.md +502 -0
- package/documents/COMPREHENSIVE_SKILL_INTEGRATION_PLAN.md +644 -0
- package/documents/DIRECTORY_MAP.md +323 -0
- package/documents/EXTENDING.md +514 -0
- package/documents/FILE_DIRECTORY_GUIDE.md +427 -0
- package/documents/LEEWAY_BADGE_INTEGRATION.md +76 -0
- package/documents/LEEWAY_IMPLEMENTATION_SUMMARY.md +384 -0
- package/documents/LEEWAY_INTEGRATION_GUIDE.md +414 -0
- package/documents/LEEWAY_NPM_SDK.md +66 -0
- package/documents/LEEWAY_QUICK_START.md +288 -0
- package/documents/LEEWAY_SKILLS_BRANDING.md +375 -0
- package/documents/LEEWAY_SKILLS_MCP_SUMMARY.md +593 -0
- package/documents/LEEWAY_STANDARDS_COMPLIANCE.md +361 -0
- package/documents/LEEWAY_UNIFIED_ARCHITECTURE.md +473 -0
- package/documents/LEEWAY_WORKFLOWS_QUICK_REFERENCE.md +307 -0
- package/documents/LEEWAY_WORKFLOWS_STRATEGIC_PLAN.md +515 -0
- package/documents/LIFELONG_LEARNING_LAYER.md +478 -0
- package/documents/MCP_ARCHITECTURE.md +683 -0
- package/documents/QUICK_REFERENCE.md +301 -0
- package/documents/SETUP.md +325 -0
- package/documents/SETUP_SUMMARY.md +413 -0
- package/documents/SKILL_ACQUISITION_EXECUTIVE_SUMMARY.md +373 -0
- package/documents/SKILL_ACQUISITION_IMPLEMENTATION.md +692 -0
- package/documents/SKILL_ACQUISITION_MANIFEST.md +404 -0
- package/documents/SKILL_ACQUISITION_QUICK_REFERENCE.md +349 -0
- package/documents/SKILL_WORKFLOW_COMPOSITION_MATRIX.md +537 -0
- package/documents/STRUCTURE.md +382 -0
- package/documents/SYSTEM_TRANSFORMATION_SUMMARY.md +560 -0
- package/documents/USAGE.md +390 -0
- package/documents/WORKFLOW_ACQUISITION_MANIFEST.md +576 -0
- package/documents/aiskills.txt +460 -0
- package/mcp-server/README.md +697 -0
- package/mcp-server/dist/badge-proof.d.ts +66 -0
- package/mcp-server/dist/badge-proof.d.ts.map +1 -0
- package/mcp-server/dist/badge-proof.js +324 -0
- package/mcp-server/dist/badge-proof.js.map +1 -0
- package/mcp-server/dist/index.d.ts +64 -0
- package/mcp-server/dist/index.d.ts.map +1 -0
- package/mcp-server/dist/index.js +263 -0
- package/mcp-server/dist/index.js.map +1 -0
- package/mcp-server/dist/install-badge-proof.d.ts +3 -0
- package/mcp-server/dist/install-badge-proof.d.ts.map +1 -0
- package/mcp-server/dist/install-badge-proof.js +109 -0
- package/mcp-server/dist/install-badge-proof.js.map +1 -0
- package/mcp-server/package.json +43 -0
- package/mcp-server/src/badge-proof.ts +469 -0
- package/mcp-server/src/index.ts +355 -0
- package/mcp-server/src/install-badge-proof.ts +132 -0
- package/mcp-server/tsconfig.json +22 -0
- package/package.json +84 -0
- package/scripts/init-leeway.js +217 -0
- package/scripts/leeway-agents/compliance-monitor.js +374 -0
- package/scripts/leeway-agents/header-injector.js +321 -0
- package/scripts/skill-integration-toolkit.py +319 -0
- package/scripts/skills-registry.json +1117 -0
- package/scripts/sync-skills.ps1 +275 -0
- package/scripts/verify-leeway-setup.js +249 -0
- package/scripts/workflow-integration-toolkit.py +522 -0
- package/sdk/application-installer.js +92 -0
- package/sdk/index.js +43 -0
- package/sdk/paths.js +167 -0
- package/skills/agent-autonomy/autonomous-conductor/SKILL.md +206 -0
- package/skills/agent-autonomy/full-stack-delivery/SKILL.md +206 -0
- package/skills/agent-orchestration/multi-agent-orchestration/SKILL.md +68 -0
- package/skills/agent-patterns/agent-design-patterns/SKILL.md +70 -0
- package/skills/ai-ml/llm-prompting/SKILL.md +71 -0
- package/skills/ai-ml/ml-model-development/SKILL.md +67 -0
- package/skills/ai-ml/multimodal-systems/SKILL.md +71 -0
- package/skills/ai-ml/retrieval-generation-fine-tuning/SKILL.md +71 -0
- package/skills/architecture/system-design/SKILL.md +67 -0
- package/skills/code-analysis/refactoring/SKILL.md +64 -0
- package/skills/code-analysis/security-vulnerability-scanning/SKILL.md +71 -0
- package/skills/code-analysis/static-analysis/SKILL.md +64 -0
- package/skills/code-generation/full-stack-application/SKILL.md +70 -0
- package/skills/code-generation/microservices-architecture/SKILL.md +71 -0
- package/skills/code-generation/python-codegen/SKILL.md +64 -0
- package/skills/code-generation/typescript-codegen/SKILL.md +64 -0
- package/skills/data-analysis/advanced-analytics/SKILL.md +71 -0
- package/skills/data-analysis/pandas-analysis/SKILL.md +66 -0
- package/skills/database-design/database-design-optimization/SKILL.md +70 -0
- package/skills/debugging/javascript-debugging/SKILL.md +67 -0
- package/skills/debugging/python-debugging/SKILL.md +67 -0
- package/skills/devops/dockerfile-creation/SKILL.md +64 -0
- package/skills/devops/kubernetes-deployment/SKILL.md +65 -0
- package/skills/documentation/api-documentation/SKILL.md +67 -0
- package/skills/error-handling/resilience-patterns/SKILL.md +70 -0
- package/skills/git-workflow/git-collaboration/SKILL.md +67 -0
- package/skills/infrastructure/cicd-pipelines/SKILL.md +70 -0
- package/skills/infrastructure/infrastructure-as-code/SKILL.md +70 -0
- package/skills/observability/monitoring-and-observability/SKILL.md +70 -0
- package/skills/performance-optimization/performance-engineering/SKILL.md +70 -0
- package/skills/prompt-optimization/prompt-engineering-advanced/SKILL.md +70 -0
- package/skills/quality-assurance/deployment-validator/SKILL.md +382 -0
- package/skills/quality-assurance/web-security-sweep/SKILL.md +320 -0
- package/skills/rag-knowledge/rag-systems/SKILL.md +70 -0
- package/skills/research/knowledge-synthesis/SKILL.md +71 -0
- package/skills/security/authentication-authorization/SKILL.md +71 -0
- package/skills/security/code-security/SKILL.md +66 -0
- package/skills/security/secure-architecture/SKILL.md +71 -0
- package/skills/self-optimization/dev-loop-optimizer/SKILL.md +344 -0
- package/skills/self-optimization/memory-learning/SKILL.md +335 -0
- package/skills/self-optimization/runtime-self-profiling/SKILL.md +250 -0
- package/skills/testing/advanced-testing-strategies/SKILL.md +71 -0
- package/skills/testing/integration-testing/SKILL.md +66 -0
- package/skills/testing/load-testing-capacity/SKILL.md +71 -0
- package/skills/testing/unit-testing/SKILL.md +66 -0
- package/skills/tool-integration/custom-tool-creation/SKILL.md +70 -0
- package/skills/web-development/advanced-frontend-patterns/SKILL.md +71 -0
- package/skills/web-development/api-design/SKILL.md +71 -0
- package/skills/web-development/css-styling/SKILL.md +67 -0
- package/skills/web-development/react-development/SKILL.md +79 -0
- package/skills/workflow-composition/workflow-orchestration/SKILL.md +70 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/*
|
|
2
|
+
LEEWAY HEADER — DO NOT REMOVE
|
|
3
|
+
|
|
4
|
+
REGION: AI.AGENT.INTEGRITY
|
|
5
|
+
TAG: AI.AGENT.CIRCULAR.DEPENDENCY
|
|
6
|
+
|
|
7
|
+
COLOR_ONION_HEX:
|
|
8
|
+
NEON=#39FF14
|
|
9
|
+
FLUO=#0DFF94
|
|
10
|
+
PASTEL=#C7FFD8
|
|
11
|
+
|
|
12
|
+
ICON_ASCII:
|
|
13
|
+
family=lucide
|
|
14
|
+
glyph=refresh-cw
|
|
15
|
+
|
|
16
|
+
5WH:
|
|
17
|
+
WHAT = Circular dependency agent — detects circular imports and risky graph patterns
|
|
18
|
+
WHY = Circular imports cause module initialization failures and memory leaks
|
|
19
|
+
WHO = Rapid Web Development
|
|
20
|
+
WHERE = src/agents/integrity/circular-dependency-agent.js
|
|
21
|
+
WHEN = 2026
|
|
22
|
+
HOW = DFS cycle detection on the dependency graph produced by dependency-graph-agent
|
|
23
|
+
|
|
24
|
+
AGENTS:
|
|
25
|
+
CIRCULAR
|
|
26
|
+
DEPENDENCY
|
|
27
|
+
|
|
28
|
+
LICENSE:
|
|
29
|
+
MIT
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* CircularDependencyAgent detects cycles in a dependency graph.
|
|
34
|
+
*/
|
|
35
|
+
export class CircularDependencyAgent {
|
|
36
|
+
/**
|
|
37
|
+
* Find all circular dependency cycles in a graph.
|
|
38
|
+
*
|
|
39
|
+
* @param {object} graph - Adjacency map from DependencyGraphAgent
|
|
40
|
+
* @returns {{ cycles: string[][], hasCycles: boolean }}
|
|
41
|
+
*/
|
|
42
|
+
findCycles(graph) {
|
|
43
|
+
const visited = new Set();
|
|
44
|
+
const inStack = new Set();
|
|
45
|
+
const cycles = [];
|
|
46
|
+
|
|
47
|
+
const dfs = (node, path) => {
|
|
48
|
+
if (inStack.has(node)) {
|
|
49
|
+
const cycleStart = path.indexOf(node);
|
|
50
|
+
cycles.push(path.slice(cycleStart).concat(node));
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (visited.has(node)) return;
|
|
54
|
+
|
|
55
|
+
visited.add(node);
|
|
56
|
+
inStack.add(node);
|
|
57
|
+
path.push(node);
|
|
58
|
+
|
|
59
|
+
for (const dep of (graph[node]?.imports || [])) {
|
|
60
|
+
dfs(dep, [...path]);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
inStack.delete(node);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
for (const node of Object.keys(graph)) {
|
|
67
|
+
if (!visited.has(node)) {
|
|
68
|
+
dfs(node, []);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const uniqueCycles = cycles.filter((cycle, i) =>
|
|
73
|
+
cycles.findIndex(c => c.join() === cycle.join()) === i
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
return { cycles: uniqueCycles, hasCycles: uniqueCycles.length > 0 };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Describe a cycle in human-readable form.
|
|
81
|
+
*
|
|
82
|
+
* @param {string[]} cycle
|
|
83
|
+
* @returns {string}
|
|
84
|
+
*/
|
|
85
|
+
describeCycle(cycle) {
|
|
86
|
+
return cycle.join(' → ');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/*
|
|
2
|
+
LEEWAY HEADER — DO NOT REMOVE
|
|
3
|
+
|
|
4
|
+
REGION: AI.AGENT.INTEGRITY
|
|
5
|
+
TAG: AI.AGENT.DEPENDENCY.GRAPH
|
|
6
|
+
|
|
7
|
+
COLOR_ONION_HEX:
|
|
8
|
+
NEON=#39FF14
|
|
9
|
+
FLUO=#0DFF94
|
|
10
|
+
PASTEL=#C7FFD8
|
|
11
|
+
|
|
12
|
+
ICON_ASCII:
|
|
13
|
+
family=lucide
|
|
14
|
+
glyph=git-branch
|
|
15
|
+
|
|
16
|
+
5WH:
|
|
17
|
+
WHAT = Dependency graph agent — builds lightweight dependency maps between modules
|
|
18
|
+
WHY = Understanding module dependencies is essential for safe refactoring and change impact analysis
|
|
19
|
+
WHO = Rapid Web Development
|
|
20
|
+
WHERE = src/agents/integrity/dependency-graph-agent.js
|
|
21
|
+
WHEN = 2026
|
|
22
|
+
HOW = Parses import/require statements, builds directed adjacency graph
|
|
23
|
+
|
|
24
|
+
AGENTS:
|
|
25
|
+
DEPENDENCY
|
|
26
|
+
CIRCULAR
|
|
27
|
+
REFACTOR
|
|
28
|
+
|
|
29
|
+
LICENSE:
|
|
30
|
+
MIT
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import { readFile } from 'node:fs/promises';
|
|
34
|
+
import { join, dirname, resolve } from 'node:path';
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* DependencyGraphAgent builds a lightweight module dependency map.
|
|
38
|
+
*/
|
|
39
|
+
export class DependencyGraphAgent {
|
|
40
|
+
constructor(options = {}) {
|
|
41
|
+
this.rootDir = options.rootDir || process.cwd();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Extract local import paths from file content.
|
|
46
|
+
*
|
|
47
|
+
* @param {string} content
|
|
48
|
+
* @returns {string[]}
|
|
49
|
+
*/
|
|
50
|
+
extractImports(content) {
|
|
51
|
+
const imports = [];
|
|
52
|
+
const patterns = [
|
|
53
|
+
/import\s+[^'"]*from\s+['"`](\.\.?\/[^'"`]+)['"`]/g,
|
|
54
|
+
/require\s*\(\s*['"`](\.\.?\/[^'"`]+)['"`]\s*\)/g,
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
for (const pattern of patterns) {
|
|
58
|
+
let match;
|
|
59
|
+
const regex = new RegExp(pattern.source, pattern.flags);
|
|
60
|
+
while ((match = regex.exec(content)) !== null) {
|
|
61
|
+
imports.push(match[1]);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return [...new Set(imports)];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Build a dependency graph for a set of files.
|
|
70
|
+
*
|
|
71
|
+
* @param {string[]} filePaths - Relative file paths
|
|
72
|
+
* @returns {Promise<DependencyGraph>}
|
|
73
|
+
*/
|
|
74
|
+
async buildGraph(filePaths) {
|
|
75
|
+
const graph = {};
|
|
76
|
+
|
|
77
|
+
for (const fp of filePaths) {
|
|
78
|
+
const fullPath = fp.startsWith('/') ? fp : join(this.rootDir, fp);
|
|
79
|
+
graph[fp] = { imports: [], importedBy: [] };
|
|
80
|
+
|
|
81
|
+
try {
|
|
82
|
+
const content = await readFile(fullPath, 'utf8');
|
|
83
|
+
const rawImports = this.extractImports(content);
|
|
84
|
+
|
|
85
|
+
for (const imp of rawImports) {
|
|
86
|
+
const resolved = resolve(dirname(fullPath), imp).replace(this.rootDir + '/', '');
|
|
87
|
+
const normalized = filePaths.find(f => f.startsWith(resolved.replace(/\.[^.]+$/, '')));
|
|
88
|
+
if (normalized) {
|
|
89
|
+
graph[fp].imports.push(normalized);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
} catch {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
for (const [file, data] of Object.entries(graph)) {
|
|
98
|
+
for (const dep of data.imports) {
|
|
99
|
+
if (graph[dep]) {
|
|
100
|
+
graph[dep].importedBy.push(file);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return { agent: 'dependency-graph-agent', graph };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/*
|
|
2
|
+
LEEWAY HEADER — DO NOT REMOVE
|
|
3
|
+
|
|
4
|
+
REGION: AI.AGENT.INTEGRITY
|
|
5
|
+
TAG: AI.AGENT.DUPLICATE.LOGIC
|
|
6
|
+
|
|
7
|
+
COLOR_ONION_HEX:
|
|
8
|
+
NEON=#39FF14
|
|
9
|
+
FLUO=#0DFF94
|
|
10
|
+
PASTEL=#C7FFD8
|
|
11
|
+
|
|
12
|
+
ICON_ASCII:
|
|
13
|
+
family=lucide
|
|
14
|
+
glyph=copy
|
|
15
|
+
|
|
16
|
+
5WH:
|
|
17
|
+
WHAT = Duplicate logic agent — detects repeated logic and duplicate injected blocks
|
|
18
|
+
WHY = Duplicate code wastes space, confuses developers, and creates maintenance debt
|
|
19
|
+
WHO = Rapid Web Development
|
|
20
|
+
WHERE = src/agents/integrity/duplicate-logic-agent.js
|
|
21
|
+
WHEN = 2026
|
|
22
|
+
HOW = Hash-based block comparison across files, sliding window on function bodies
|
|
23
|
+
|
|
24
|
+
AGENTS:
|
|
25
|
+
DUPLICATE
|
|
26
|
+
SYNTAX
|
|
27
|
+
REFACTOR
|
|
28
|
+
|
|
29
|
+
LICENSE:
|
|
30
|
+
MIT
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import { createHash } from 'node:crypto';
|
|
34
|
+
import { readFile } from 'node:fs/promises';
|
|
35
|
+
import { join } from 'node:path';
|
|
36
|
+
|
|
37
|
+
const MIN_BLOCK_LINES = 5;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* DuplicateLogicAgent detects repeated code blocks across files.
|
|
41
|
+
*/
|
|
42
|
+
export class DuplicateLogicAgent {
|
|
43
|
+
constructor(options = {}) {
|
|
44
|
+
this.rootDir = options.rootDir || process.cwd();
|
|
45
|
+
this.minBlockLines = options.minBlockLines || MIN_BLOCK_LINES;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Extract normalized code blocks from content for comparison.
|
|
50
|
+
*
|
|
51
|
+
* @param {string} content
|
|
52
|
+
* @returns {Map<string, string>} - Map of hash to block text
|
|
53
|
+
*/
|
|
54
|
+
extractBlocks(content) {
|
|
55
|
+
const blocks = new Map();
|
|
56
|
+
const lines = content.split('\n').map(l => l.trim()).filter(Boolean);
|
|
57
|
+
|
|
58
|
+
for (let i = 0; i <= lines.length - this.minBlockLines; i++) {
|
|
59
|
+
const block = lines.slice(i, i + this.minBlockLines).join('\n');
|
|
60
|
+
if (block.length < 50) continue;
|
|
61
|
+
const hash = createHash('sha256').update(block).digest('hex').slice(0, 16);
|
|
62
|
+
if (!blocks.has(hash)) blocks.set(hash, block);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return blocks;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Find duplicate blocks across multiple files.
|
|
70
|
+
*
|
|
71
|
+
* @param {string[]} filePaths
|
|
72
|
+
* @returns {Promise<DuplicateReport>}
|
|
73
|
+
*/
|
|
74
|
+
async findDuplicates(filePaths) {
|
|
75
|
+
const fileBlocks = new Map();
|
|
76
|
+
|
|
77
|
+
for (const fp of filePaths) {
|
|
78
|
+
const fullPath = fp.startsWith('/') ? fp : join(this.rootDir, fp);
|
|
79
|
+
try {
|
|
80
|
+
const content = await readFile(fullPath, 'utf8');
|
|
81
|
+
fileBlocks.set(fp, this.extractBlocks(content));
|
|
82
|
+
} catch {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const hashToFiles = new Map();
|
|
88
|
+
for (const [file, blocks] of fileBlocks.entries()) {
|
|
89
|
+
for (const [hash, block] of blocks.entries()) {
|
|
90
|
+
if (!hashToFiles.has(hash)) hashToFiles.set(hash, { block, files: [] });
|
|
91
|
+
hashToFiles.get(hash).files.push(file);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const duplicates = [];
|
|
96
|
+
for (const [hash, { block, files }] of hashToFiles.entries()) {
|
|
97
|
+
if (files.length > 1) {
|
|
98
|
+
duplicates.push({ hash, files, preview: block.slice(0, 100) + '...' });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
agent: 'duplicate-logic-agent',
|
|
104
|
+
duplicatesFound: duplicates.length,
|
|
105
|
+
duplicates,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/*
|
|
2
|
+
LEEWAY HEADER — DO NOT REMOVE
|
|
3
|
+
|
|
4
|
+
REGION: AI.AGENT.INTEGRITY
|
|
5
|
+
TAG: AI.AGENT.IMPORT.MAIN
|
|
6
|
+
|
|
7
|
+
COLOR_ONION_HEX:
|
|
8
|
+
NEON=#39FF14
|
|
9
|
+
FLUO=#0DFF94
|
|
10
|
+
PASTEL=#C7FFD8
|
|
11
|
+
|
|
12
|
+
ICON_ASCII:
|
|
13
|
+
family=lucide
|
|
14
|
+
glyph=package
|
|
15
|
+
|
|
16
|
+
5WH:
|
|
17
|
+
WHAT = Import agent — normalizes import style and validates local import rules
|
|
18
|
+
WHY = Mixed import styles and broken paths cause module resolution failures
|
|
19
|
+
WHO = Rapid Web Development
|
|
20
|
+
WHERE = src/agents/integrity/import-agent.js
|
|
21
|
+
WHEN = 2026
|
|
22
|
+
HOW = Scans import statements for style violations and common path issues
|
|
23
|
+
|
|
24
|
+
AGENTS:
|
|
25
|
+
IMPORT
|
|
26
|
+
SYNTAX
|
|
27
|
+
MODULE
|
|
28
|
+
|
|
29
|
+
LICENSE:
|
|
30
|
+
MIT
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* ImportAgent normalizes and validates import statements.
|
|
35
|
+
*/
|
|
36
|
+
export class ImportAgent {
|
|
37
|
+
/**
|
|
38
|
+
* Analyze import statements in file content.
|
|
39
|
+
*
|
|
40
|
+
* @param {string} content
|
|
41
|
+
* @param {{ moduleType?: 'esm' | 'cjs', filePath?: string }} [options]
|
|
42
|
+
* @returns {{ valid: boolean, issues: string[], suggestions: string[] }}
|
|
43
|
+
*/
|
|
44
|
+
analyze(content, options = {}) {
|
|
45
|
+
const { moduleType = 'esm' } = options;
|
|
46
|
+
const issues = [];
|
|
47
|
+
const suggestions = [];
|
|
48
|
+
const lines = content.split('\n');
|
|
49
|
+
|
|
50
|
+
const esmImports = lines.filter(l => /^\s*import\s+/.test(l));
|
|
51
|
+
const cjsRequires = lines.filter(l => /\brequire\s*\(/.test(l));
|
|
52
|
+
|
|
53
|
+
if (moduleType === 'esm' && cjsRequires.length > 0) {
|
|
54
|
+
issues.push(`Found ${cjsRequires.length} require() call(s) in ESM module — use import instead`);
|
|
55
|
+
suggestions.push('Convert require() to import statements');
|
|
56
|
+
}
|
|
57
|
+
if (moduleType === 'cjs' && esmImports.length > 0) {
|
|
58
|
+
issues.push(`Found ${esmImports.length} import statement(s) in CJS module — use require() instead`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
for (let i = 0; i < lines.length; i++) {
|
|
62
|
+
const line = lines[i];
|
|
63
|
+
const importMatch = line.match(/from\s+['"`]([^'"`]+)['"`]/);
|
|
64
|
+
if (!importMatch) continue;
|
|
65
|
+
|
|
66
|
+
const importPath = importMatch[1];
|
|
67
|
+
|
|
68
|
+
if (importPath.startsWith('.') && !importPath.includes('.js') && !importPath.includes('.ts')
|
|
69
|
+
&& importPath.includes('/') && moduleType === 'esm') {
|
|
70
|
+
const hasExtension = /\.[a-z]+$/.test(importPath);
|
|
71
|
+
if (!hasExtension) {
|
|
72
|
+
suggestions.push(`Line ${i + 1}: ESM local imports should include file extension: "${importPath}" → "${importPath}.js"`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (importPath.includes('../../..')) {
|
|
77
|
+
issues.push(`Line ${i + 1}: Deep relative import "${importPath}" — consider using path aliases`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return { valid: issues.length === 0, issues, suggestions };
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/*
|
|
2
|
+
LEEWAY HEADER — DO NOT REMOVE
|
|
3
|
+
|
|
4
|
+
REGION: AI.AGENT.INTEGRITY
|
|
5
|
+
TAG: AI.AGENT.MODULE.POLICY
|
|
6
|
+
|
|
7
|
+
COLOR_ONION_HEX:
|
|
8
|
+
NEON=#39FF14
|
|
9
|
+
FLUO=#0DFF94
|
|
10
|
+
PASTEL=#C7FFD8
|
|
11
|
+
|
|
12
|
+
ICON_ASCII:
|
|
13
|
+
family=lucide
|
|
14
|
+
glyph=layers
|
|
15
|
+
|
|
16
|
+
5WH:
|
|
17
|
+
WHAT = Module policy agent — prevents CommonJS/ESM drift within a project
|
|
18
|
+
WHY = Mixed module systems cause runtime errors that are extremely hard to debug
|
|
19
|
+
WHO = Rapid Web Development
|
|
20
|
+
WHERE = src/agents/integrity/module-policy-agent.js
|
|
21
|
+
WHEN = 2026
|
|
22
|
+
HOW = Reads package.json type field and validates all files follow the declared module system
|
|
23
|
+
|
|
24
|
+
AGENTS:
|
|
25
|
+
MODULE
|
|
26
|
+
IMPORT
|
|
27
|
+
SYNTAX
|
|
28
|
+
|
|
29
|
+
LICENSE:
|
|
30
|
+
MIT
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import { readFile } from 'node:fs/promises';
|
|
34
|
+
import { join, extname } from 'node:path';
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* ModulePolicyAgent prevents CommonJS/ESM drift in a project.
|
|
38
|
+
*/
|
|
39
|
+
export class ModulePolicyAgent {
|
|
40
|
+
constructor(options = {}) {
|
|
41
|
+
this.rootDir = options.rootDir || process.cwd();
|
|
42
|
+
this.declaredType = null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async _getModuleType() {
|
|
46
|
+
if (this.declaredType) return this.declaredType;
|
|
47
|
+
try {
|
|
48
|
+
const raw = await readFile(join(this.rootDir, 'package.json'), 'utf8');
|
|
49
|
+
const pkg = JSON.parse(raw);
|
|
50
|
+
this.declaredType = pkg.type || 'commonjs';
|
|
51
|
+
} catch {
|
|
52
|
+
this.declaredType = 'commonjs';
|
|
53
|
+
}
|
|
54
|
+
return this.declaredType;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Check a file for module type consistency.
|
|
59
|
+
*
|
|
60
|
+
* @param {string} filePath
|
|
61
|
+
* @returns {Promise<{ valid: boolean, issues: string[] }>}
|
|
62
|
+
*/
|
|
63
|
+
async checkFile(filePath) {
|
|
64
|
+
const fullPath = filePath.startsWith('/') ? filePath : join(this.rootDir, filePath);
|
|
65
|
+
const ext = extname(filePath);
|
|
66
|
+
|
|
67
|
+
if (ext === '.mjs') return { valid: true, issues: [], moduleType: 'esm', forced: true };
|
|
68
|
+
if (ext === '.cjs') return { valid: true, issues: [], moduleType: 'commonjs', forced: true };
|
|
69
|
+
|
|
70
|
+
const declaredType = await this._getModuleType();
|
|
71
|
+
let content = '';
|
|
72
|
+
try {
|
|
73
|
+
content = await readFile(fullPath, 'utf8');
|
|
74
|
+
} catch {
|
|
75
|
+
return { valid: false, issues: ['Cannot read file'] };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const issues = [];
|
|
79
|
+
const hasEsmImport = /^\s*import\s+/m.test(content) || /^\s*export\s+/m.test(content);
|
|
80
|
+
const hasCjsRequire = /\brequire\s*\(/.test(content);
|
|
81
|
+
const hasCjsExport = /\bmodule\.exports\b/.test(content);
|
|
82
|
+
|
|
83
|
+
if (declaredType === 'module') {
|
|
84
|
+
if (hasCjsRequire) issues.push('require() found in ESM project — use import instead');
|
|
85
|
+
if (hasCjsExport) issues.push('module.exports found in ESM project — use export instead');
|
|
86
|
+
} else {
|
|
87
|
+
if (hasEsmImport && !hasCjsRequire) {
|
|
88
|
+
issues.push('ESM import/export found in CommonJS project — add "type":"module" to package.json or use .mjs extension');
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return { valid: issues.length === 0, issues, moduleType: declaredType };
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/*
|
|
2
|
+
LEEWAY HEADER — DO NOT REMOVE
|
|
3
|
+
|
|
4
|
+
REGION: AI.AGENT.INTEGRITY
|
|
5
|
+
TAG: AI.AGENT.REFACTOR.SCAN
|
|
6
|
+
|
|
7
|
+
COLOR_ONION_HEX:
|
|
8
|
+
NEON=#39FF14
|
|
9
|
+
FLUO=#0DFF94
|
|
10
|
+
PASTEL=#C7FFD8
|
|
11
|
+
|
|
12
|
+
ICON_ASCII:
|
|
13
|
+
family=lucide
|
|
14
|
+
glyph=wand-2
|
|
15
|
+
|
|
16
|
+
5WH:
|
|
17
|
+
WHAT = Refactor scan agent — suggests safe structural improvements to code
|
|
18
|
+
WHY = Continuous refactoring suggestions keep the codebase clean and maintainable
|
|
19
|
+
WHO = Rapid Web Development
|
|
20
|
+
WHERE = src/agents/integrity/refactor-scan-agent.js
|
|
21
|
+
WHEN = 2026
|
|
22
|
+
HOW = Pattern-based heuristics detect long functions, deep nesting, and complex conditionals
|
|
23
|
+
|
|
24
|
+
AGENTS:
|
|
25
|
+
REFACTOR
|
|
26
|
+
SYNTAX
|
|
27
|
+
DUPLICATE
|
|
28
|
+
|
|
29
|
+
LICENSE:
|
|
30
|
+
MIT
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* RefactorScanAgent suggests safe structural improvements.
|
|
35
|
+
*/
|
|
36
|
+
export class RefactorScanAgent {
|
|
37
|
+
constructor(options = {}) {
|
|
38
|
+
this.maxFunctionLines = options.maxFunctionLines || 50;
|
|
39
|
+
this.maxNestingDepth = options.maxNestingDepth || 4;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Scan file content for refactoring opportunities.
|
|
44
|
+
*
|
|
45
|
+
* @param {string} content
|
|
46
|
+
* @param {{ filePath?: string }} [options]
|
|
47
|
+
* @returns {{ suggestions: Suggestion[] }}
|
|
48
|
+
*/
|
|
49
|
+
scan(content, options = {}) {
|
|
50
|
+
if (!content || typeof content !== 'string') {
|
|
51
|
+
return { suggestions: [] };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const suggestions = [];
|
|
55
|
+
const lines = content.split('\n');
|
|
56
|
+
|
|
57
|
+
let functionStart = -1;
|
|
58
|
+
let functionName = '';
|
|
59
|
+
let maxDepth = 0;
|
|
60
|
+
let currentDepth = 0;
|
|
61
|
+
|
|
62
|
+
for (let i = 0; i < lines.length; i++) {
|
|
63
|
+
const line = lines[i];
|
|
64
|
+
const trimmed = line.trim();
|
|
65
|
+
|
|
66
|
+
const fnMatch = trimmed.match(/^(?:export\s+)?(?:async\s+)?function\s+(\w+)|^(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s*)?\(/);
|
|
67
|
+
if (fnMatch && functionStart === -1) {
|
|
68
|
+
functionStart = i;
|
|
69
|
+
functionName = fnMatch[1] || fnMatch[2] || 'anonymous';
|
|
70
|
+
currentDepth = 0;
|
|
71
|
+
maxDepth = 0;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
currentDepth += (line.match(/\{/g) || []).length;
|
|
75
|
+
currentDepth -= (line.match(/\}/g) || []).length;
|
|
76
|
+
if (currentDepth > maxDepth) maxDepth = currentDepth;
|
|
77
|
+
|
|
78
|
+
if (functionStart !== -1 && currentDepth <= 0 && i > functionStart) {
|
|
79
|
+
const functionLength = i - functionStart;
|
|
80
|
+
if (functionLength > this.maxFunctionLines) {
|
|
81
|
+
suggestions.push({
|
|
82
|
+
type: 'long_function',
|
|
83
|
+
line: functionStart + 1,
|
|
84
|
+
message: `Function "${functionName}" is ${functionLength} lines — consider extracting into smaller functions`,
|
|
85
|
+
severity: 'warning',
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
if (maxDepth > this.maxNestingDepth) {
|
|
89
|
+
suggestions.push({
|
|
90
|
+
type: 'deep_nesting',
|
|
91
|
+
line: functionStart + 1,
|
|
92
|
+
message: `Function "${functionName}" has nesting depth of ${maxDepth} — flatten with early returns or extracted functions`,
|
|
93
|
+
severity: 'warning',
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
functionStart = -1;
|
|
97
|
+
maxDepth = 0;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (/TODO|FIXME|HACK|XXX/.test(trimmed)) {
|
|
101
|
+
const match = trimmed.match(/(TODO|FIXME|HACK|XXX)[:\s]+(.+)/);
|
|
102
|
+
suggestions.push({
|
|
103
|
+
type: 'todo',
|
|
104
|
+
line: i + 1,
|
|
105
|
+
message: `Unresolved ${match?.[1] || 'TODO'}: ${match?.[2]?.slice(0, 60) || trimmed}`,
|
|
106
|
+
severity: 'info',
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return { suggestions };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/*
|
|
2
|
+
LEEWAY HEADER — DO NOT REMOVE
|
|
3
|
+
|
|
4
|
+
REGION: AI.AGENT.INTEGRITY
|
|
5
|
+
TAG: AI.AGENT.SYNTAX.MAIN
|
|
6
|
+
|
|
7
|
+
COLOR_ONION_HEX:
|
|
8
|
+
NEON=#39FF14
|
|
9
|
+
FLUO=#0DFF94
|
|
10
|
+
PASTEL=#C7FFD8
|
|
11
|
+
|
|
12
|
+
ICON_ASCII:
|
|
13
|
+
family=lucide
|
|
14
|
+
glyph=code-2
|
|
15
|
+
|
|
16
|
+
5WH:
|
|
17
|
+
WHAT = Syntax agent — guards against malformed code and unsafe patch results
|
|
18
|
+
WHY = Malformed syntax breaks builds; this agent catches errors before they reach CI
|
|
19
|
+
WHO = Rapid Web Development
|
|
20
|
+
WHERE = src/agents/integrity/syntax-agent.js
|
|
21
|
+
WHEN = 2026
|
|
22
|
+
HOW = Lightweight structural pattern checks for common JS/TS syntax issues
|
|
23
|
+
|
|
24
|
+
AGENTS:
|
|
25
|
+
SYNTAX
|
|
26
|
+
IMPORT
|
|
27
|
+
MODULE
|
|
28
|
+
|
|
29
|
+
LICENSE:
|
|
30
|
+
MIT
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* SyntaxAgent performs lightweight structural syntax validation.
|
|
35
|
+
*/
|
|
36
|
+
export class SyntaxAgent {
|
|
37
|
+
/**
|
|
38
|
+
* Check JS/TS content for common syntax issues.
|
|
39
|
+
*
|
|
40
|
+
* @param {string} content
|
|
41
|
+
* @param {{ filePath?: string }} [options]
|
|
42
|
+
* @returns {{ valid: boolean, issues: string[] }}
|
|
43
|
+
*/
|
|
44
|
+
check(content, options = {}) {
|
|
45
|
+
if (!content || typeof content !== 'string') {
|
|
46
|
+
return { valid: false, issues: ['Empty or invalid content'] };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const issues = [];
|
|
50
|
+
const lines = content.split('\n');
|
|
51
|
+
|
|
52
|
+
const openBraces = (content.match(/\{/g) || []).length;
|
|
53
|
+
const closeBraces = (content.match(/\}/g) || []).length;
|
|
54
|
+
if (openBraces !== closeBraces) {
|
|
55
|
+
issues.push(`Unbalanced braces: ${openBraces} opening, ${closeBraces} closing`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const openParens = (content.match(/\(/g) || []).length;
|
|
59
|
+
const closeParens = (content.match(/\)/g) || []).length;
|
|
60
|
+
if (openParens !== closeParens) {
|
|
61
|
+
issues.push(`Unbalanced parentheses: ${openParens} opening, ${closeParens} closing`);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const openBrackets = (content.match(/\[/g) || []).length;
|
|
65
|
+
const closeBrackets = (content.match(/\]/g) || []).length;
|
|
66
|
+
if (openBrackets !== closeBrackets) {
|
|
67
|
+
issues.push(`Unbalanced brackets: ${openBrackets} opening, ${closeBrackets} closing`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
for (let i = 0; i < lines.length; i++) {
|
|
71
|
+
const line = lines[i].trim();
|
|
72
|
+
if (line.includes('<<<<<<< ') || line.includes('=======') || line.includes('>>>>>>> ')) {
|
|
73
|
+
issues.push(`Unresolved git merge conflict at line ${i + 1}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const consoleLogs = lines.filter(l => l.trim().startsWith('console.log(')).length;
|
|
78
|
+
if (consoleLogs > 10) {
|
|
79
|
+
issues.push(`Excessive console.log usage (${consoleLogs} occurrences) — use namespaced logging`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return { valid: issues.length === 0, issues };
|
|
83
|
+
}
|
|
84
|
+
}
|