I guess this bug wasn't fixed for the 2.0 release. Shame. For the other posters, here's a workaround that I'm playing with that SEEMS to work all right thus far.

The custom loader prevents needless XHR requests.
PHP Code:

    
// custom treeloader so that we can treat '!has_children' more or less as
    // leaf, but still take advantage of the default drag & drop (which, by
    // default, will not allow appends to leaf - see possible bug
    // http://extjs.com/forum/showthread.php?t=17522&highlight=drop+leaf+node
    //  - this is only needed (in leiu of leaf => true|false) because we
    //  allowing appending to 'leaf' nodes, dynamically turning them into
    //  interior nodes
    
var treeLoader =new Ext.tree.TreeLoader({
        
dataUrl'/resource/children'
    
})
    
treeLoader.on('beforeload', function(treenode) { 
        if(
node.attributes.has_children == false)
            return 
false
    
})

    
config config || {}
    
MyClass.superclass.constructor.call(thisExt.apply({
        
el:                 'pad',
        
loader:             treeLoader,

        
autoScroll:         true,
        
animate:            true,
        
enableDD:           true,
        
containerScroll:    true

       
// , ... other params for toolbar, etc.
    
},config)) 
The event handler 'expands' the leaf nodes to get the right icon (and more importantly, to eliminate the expand toggle).
PHP Code:
    this.on('append', function(treeparentNodenewNodenewNodeIndex) {
        if(
newNode.attributes.has_children == false) {
            
newNode.render()
            
newNode.expand(false)
        }
    }) 
With the above, I make sure that children are loaded with no 'leaf' attribute (letting it default to false), but with has_children set appropriately.