Can't repro this.
I run your transformation with Saxon 9.1.07 and the result is;
<div class="box">
Box[2,5] = (1)
<title>This is box TWO</title></div><div class="box">
Box[3,6] = (12)
<title>This is box THREE</title></div><div class="box">
Box[1,7] = (103)
<title>This is box ONE</title></div>
As we see, the positions are correct (still not 1,2,3 -- because white-space-only nodes are also present).
The same result is produced by XQSharp (XmlPrime).
AltovaXML2009 (XML-SPY) produces even this:
<?xml version="1.0" encoding="UTF-8"?><div class="box">
Box[2,1] = (1)
<title>This is box TWO</title></div><div class="box">
Box[3,2] = (12)
<title>This is box THREE</title></div><div class="box">
Box[1,3] = (103)
<title>This is box ONE</title></div>
which means that it uses an XML parser that strips-off white-space-only text nodes.
An improved version of this transformation would exclude white-space-only nodes:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="body">
<xsl:apply-templates>
<xsl:sort select="@priority" data-type="number"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="box">
<div class="box">
Box[<xsl:value-of select="count(preceding-sibling::box) + 1" />
<xsl:text>,</xsl:text>
<xsl:value-of select="position()"/>
<xsl:text>] = (</xsl:text>
<xsl:value-of select="@priority"/>)
<xsl:copy-of select="title"/></div>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied against the provided XML document:
<body>
<box priority="103">
<title>This is box ONE</title>
</box>
<box priority="1">
<title>This is box TWO</title>
</box>
<box priority="12">
<title>This is box THREE</title>
</box>
</body>
the wanted, correct result is produced:
<div class="box">
Box[2,1] = (1)
<title>This is box TWO</title>
</div>
<div class="box">
Box[3,2] = (12)
<title>This is box THREE</title>
</div>
<div class="box">
Box[1,3] = (103)
<title>This is box ONE</title>
</div>
Notes: xsl:strip-space
is used to exclude the white-space-only nodes even from being parsed.
Conclusion: The reported result is due either to using a buggy XSLT processor, or to performing a transformation that is different than the provided one.