“Missing \cr inserted”, but it looks to me like it's already there!

I'm trying to create a Plain TeX macro for typesetting two-column proofs with automatic step-numbering and step cross-referencing; currently, the "best" I have is:

\newcount\stepno
\def\twocols#1{%
\def\mkstep##1{%
\expandafter \ifx \csname##1step\endcsname \relax%
\expandafter\edef\csname##1step\endcsname{\the\stepno}%
\else \message{^^JWarning: attempt to define ##1 more than once^^J^^J}%
\stepref{##1}%
\fi}%
\def\stepref##1{%
\expandafter \ifx \csname##1step\endcsname \relax {\tt[##1]}%
\else \csname##1step\endcsname%
\fi}%
\vbox{ \offinterlineskip \halign{ \strut\the\stepno. ##\hfil & \vrule ##\hfil\cr% %\noalign{\hrule\smallskip} #1 \cr } }
}

\twocols{
\mkstep{A} $(p\to q)\land (q\to r)$ & premise \cr
\mkstep{B} $p\to (q\land(q\to r))$ & \stepref{A}, logic07 \cr
$p\to r$ & \stepref{B}, {\it modus ponens}
}

\bye


Unfortunately, trying to typeset this yields the following inexplicable error:

This is pdfTeXk, Version 3.141592-1.40.3 (Web2C 7.5.6)
%&-line parsing enabled.
entering extended mode
(./twocols02.tex
! Missing \cr inserted.
<inserted text>
\cr
}
\twocols ... ##\hfil & \vrule ##\hfil \cr #1 \cr }
}
l.28 }

? X
No pages of output.
Transcript written on twocols02.log.


Why is it claiming there's a missing \cr where there clearly appears to be one? I've tried removing the \cr from the macro definition and adding a \cr to the end of the macro argument, replacing the \cr with \crcr, removing the newline between the two closing braces there, using two \crs, dispensing with the macro and trying to typeset what it should expand to, and various combinations thereof, yet I keep getting this error, and I'm out of ideas. What's going on?

(Also, I suspect that using \mkstep the way I am will cause the resulting reference macros to be scoped to just the column in which \mkstep is used, rather than to the whole \twocols; is there a way to fix that without making the reference macros global?)

-
There's no point in defining \mkstep and \stepref inside \twocols, as their definition doesn't depend on the argument to \twocols. Of course defining \Astep as you do in a cell will leave it undefined elsewhere, so \xdef is needed. I'd also put \relax before the starting conditional in the definitions of \mkstep and \stepref –  egreg Feb 28 '12 at 22:48
In order to have unique macros you could use another counter that is stepped at each call of \twocols, say \csname ##1@\the\schemecount@step\endcsname. –  egreg Feb 28 '12 at 23:08
@egreg: no point unless you call it inside a group, right? –  morbusg Feb 29 '12 at 7:07
@morbusg If one wanted that \mkstep were available only in the argument to \twocols then a group should be opened just at the beginning of the definition of \twocols. In the OP's example, \mkstep remains defined just to be redefined in the same way at a second call of \twocols –  egreg Feb 29 '12 at 7:25

 \everycr={\noalign{\global\advance\stepno by 1}}%

you are inserting tokens after the last explicit \cr so need to make sure they don't start a new row.