The stash is another feature that should use the regular commit representation. Well, somehow. Yes, the stash is different in that it preserves (or can preserve) uncommitted changes, as well as staged changes, and it can tell these apart.
However, if the staging area is relaced by a CHEAD commit ("commit head") whose parent is HEAD, then the problem of "stashing the index" completely goes away. You don't stash staged changes because they are already committed into the staging commit CHEAD.
That said, the stash feature could work with this CHEAD. Stashing the staged changes sitting in CHEAD could propagate them into the stash somehow (such as by a reference to that commmit). Then CHEAD is reset to point to HEAD, and the changes are gone. A single stash item consisting of work tree changes and staged changes could simply be an object that references two commits: a commit of working changes committed just for the stash, and a reference to the CHEAD which existed at that time. It could be that one is the parent of the other. So that is to say, a commit is made of the working copy changes, parented at the CHEAD. The stash then points to the SHA of that commit.
Intuitively, I know this would work, because in the existing Git, I could easily implement this workflow instead of using the stash. Given a tree of local changes, I could "stage" some of them by creating a commit with "git commit --patch". Then "stash" rest of them into another commit "git commit -a". Then, create a branch or tag for that two-commit combo, and finally get rid of it with "git reset --hard HEAD^^". Later, I could easily recover the changes from that branch, either by cherry picking, or doing a hard reset to them or whatever.
Speaking of which, an example of how stashes are limiting because they aren't commits, think of how you can't do:
git reset --hard stash@{0} # wipe it all away and make it like this stash
You can't do that because a "reset --hard anything" cannot reproduce a state where you have outstanding working copy changes and/or an uncommitted index, but "stash apply" or "stash pop" are saddled with that requirement.
The requirement of reproducing working changes and staged ones from a stash represented as a two-commit combo is very simple. You cherry pick one normally and make it the CHEAD (the aforementioned special head for pointing to a commit being staged). Then the other one is cherry-picked with -n, so it is applied as local changes.
“git stash push --patch” lets you choose hunks to copy into the new stash and clean out of the workspace. It’s pretty similar to “git add --patch” for choosing hunks to stage.