Thanks! I think this could be improved further by changing the names of the destination and source flags (all four of them) to make things clearer.
While I'm at it, here's another bug: the last test of the program engine feeds a 5 into j, which breaks things because the counter doesn't expect it at all.
Also the final level doesn't have any tests but I'm sure you know that.
I want to add that besides some issues that have already been pointed out, it's a really nicely made tutorial. I went through all of it pretty fast because I already have a good background, but I would definitely point a beginner to it as a learning resource.
I've looked through the code a bit, I think your assembler is actually buggy. The expected results for the tests are correct, however the encoded instructions that you're feeding to the decoder are not.
For example, A=1 should be 0x89F8, but you're encoding it as 0x8FE0. This causes the tests to fail despite the logic being correct.
While I'm at it, here's another bug: the last test of the program engine feeds a 5 into j, which breaks things because the counter doesn't expect it at all. Also the final level doesn't have any tests but I'm sure you know that.
I want to add that besides some issues that have already been pointed out, it's a really nicely made tutorial. I went through all of it pretty fast because I already have a good background, but I would definitely point a beginner to it as a learning resource.