)]}'
{
  "log": [
    {
      "commit": "547feda05a4f846bb5fa7d32fe10dd10385fd0f0",
      "tree": "dcbf881757f4f8f860e1ba3a21858422edd1c180",
      "parents": [
        "dc6d8f6f5a59956fb65dd84b065c16a4290dcbee"
      ],
      "author": {
        "name": "Sketch🕴️",
        "email": "skallywag@sketch.dev",
        "time": "Sat Feb 28 20:55:39 2026 +0400"
      },
      "committer": {
        "name": "Sketch🕴️",
        "email": "skallywag@sketch.dev",
        "time": "Sat Feb 28 20:55:39 2026 +0400"
      },
      "message": "Step 4: Add parser tests for Ident, FuncCall, ParseLine, and error cases\n"
    },
    {
      "commit": "b05c53fb01342873787b545359f443b5dbf2be7f",
      "tree": "fb628f9aa5e539abc5bd2e64240bb0211707be0b",
      "parents": [
        "ad74392541b9a72b521e56673cfdd013532fbd4a"
      ],
      "author": {
        "name": "Sketch🕴️",
        "email": "skallywag@sketch.dev",
        "time": "Sat Feb 28 19:13:36 2026 +0400"
      },
      "committer": {
        "name": "Sketch🕴️",
        "email": "skallywag@sketch.dev",
        "time": "Sat Feb 28 19:13:36 2026 +0400"
      },
      "message": "parser: implement recursive-descent parser with tests\n\n- Parse([]token.Token) (ast.Node, error) converts tokens to AST\n- Grammar: expr → term ((+|-) term)*, term → factor ((*|/) factor)*, factor → NUMBER | \u0027(\u0027 expr \u0027)\u0027\n- Correct operator precedence (* / before + -)\n- Left-associative operators\n- Error handling: empty input, missing/unexpected parens, trailing tokens, consecutive operators\n- 19 unit tests covering success and error cases\n"
    }
  ]
}
