Based on that blog post, I would presume that the following would work in this case:
<xsl:choose>
<xsl:when test="not ($dvt_groupfield)">
<xsl:value-of select="ddwrt:NameChanged(string(substring(@ProposalID, 1, 4)), 0)" />
</xsl:when>
<xsl:otherwise></xsl:otherwise>
</xsl:choose>
using 1 and 4 as the bounds for the substring.
And similarly for the title, also as indicated in the blog post:
<xsl:when test="not (@ProposalID) and (@ProposalID) != false()">
<xsl:value-of select="' '" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring(@ProposalID,1,4)" />
Could you give that a try?