# Mica Language and Development Runtime Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Deliver a buildable, statically checked language with an interpreter, CLI, development HTTP server, examples, and a downloadable Linux executable and source archive. **Architecture:** A source-spanned AST flows through a separate static checker into a tree-walking evaluator. CLI and HTTP adapters share that pipeline; each request gets a fresh evaluator. Go's standard library supplies serialization, networking, and tests. **Tech Stack:** Supported Go >=1.22; Go standard library only; `gofmt`, `go test`, `go vet`, and Go's race detector. **Spec:** [Approved language specification](../specs/2026-10-22-php-replacement-design.md). ## Global Constraints - Use a supported Go release, at least Go 1.22. - The initial Go module has no third-party runtime dependencies. - Programs with static errors must produce no program output and must not open a listener. - At most 256 user-function calls may be active at once. - Columns count Unicode code points rather than UTF-8 bytes. - PHP source compatibility is outside this milestone. - `mica` is the command name; `.mica` is the source extension; Mica remains a working name. - Preserve the spec's deferred features; packaging does not add language features. - Do not publish, deploy, or upload the release. Deliver local artifacts and build instructions. ## Review Focus - Source after multibyte text or a comment at EOF: report the correct location without truncating or panicking (Task 1). - A local that shadows a refined nullable variable: use the inner binding's actual type; do not inherit an unrelated refinement (Task 2). - Minimum `Int` divided or remaindered by `-1`: division reports overflow; remainder is zero without a host panic (Task 3). - Valid percent escapes that decode to invalid UTF-8, even under an unused query key: reject the request before evaluating the handler (Task 4). - Check/run commands given a filename containing spaces, missing source, or an extra flag: preserve argument boundaries and return the specified exit status (Task 5). ## File Structure and Shared Contracts ```text go.mod module example.com/mica; go 1.22 .gitignore build output and local worktrees internal/syntax/source.go spans and language diagnostics internal/syntax/token.go token kinds and tokens internal/syntax/ast.go syntax-only node definitions internal/syntax/lexer.go UTF-8 tokenization internal/syntax/parser.go grammar and precedence internal/syntax/{lexer,parser}_test.go internal/check/types.go types, signatures, checked program internal/check/builtins.go static built-in call rules internal/check/checker.go scopes, expressions, functions, returns internal/check/checker_test.go internal/eval/value.go tagged values and opaque request/response data internal/eval/arithmetic.go checked 64-bit operations internal/eval/builtins.go primitive conversions and response creation internal/eval/eval.go expression/statement evaluation and calls internal/eval/eval_test.go internal/web/handler.go validated per-request execution internal/web/server.go listener, timeouts, shutdown internal/web/{handler,server}_test.go internal/cli/cli.go commands, file pipeline, exit statuses internal/cli/cli_test.go cmd/mica/main.go process arguments and signals cmd/mica/integration_test.go binary-level lifecycle tests examples/{greeting,nullable,web,invalid}.mica README.md build, quick start, language reference, limits scripts/package.sh verified local binary/source packaging dist/ ignored deliverable artifacts ``` Use the following interfaces consistently; implementation details belong inside the owning package. Export only what a downstream package needs. - `syntax.Position { Offset, Line, Column int }`: byte offset, one-based rune column. - `syntax.Span { File string; Start, End Position }`. - `syntax.Diagnostic { Span Span; Category, Message string }` implementing `error`; format is `file:line:column: category: message`. - `syntax.Lex(filename, source string) ([]Token, error)` and `syntax.Parse(filename, source string) (*Program, error)`. - All AST nodes implement `Location() syntax.Span`; all expressions and statements use distinct interfaces. `Program` has `Filename string` and `Statements []Stmt`. - `check.Type { Name string; Nullable bool }`; named internal null type is `Null`. `check.Signature { Params []Type; Return Type }`. - `check.Program { Syntax *syntax.Program; Functions map[string]*syntax.FunctionDecl; Signatures map[string]Signature }`; treat its contents as immutable after construction. - `check.Check(program *syntax.Program) (*check.Program, error)` checks all source. `check.ValidateHandler(program *check.Program) error` adds serve-only restrictions. - `eval.Request { Method, Path string; Query map[string][]string }`; `eval.Response { ContentType string; Body []byte }`. - `eval.Value` is a tagged representation with primitive payloads and opaque request/response payloads, never an unvalidated host `any` exposed to programs. - `eval.RequestValue(request Request) Value` and `eval.ResponseValue(value Value) (Response, bool)` connect the adapters. - `eval.New(program *check.Program, output io.Writer) *Interpreter`; `(*Interpreter).Run() error`; `(*Interpreter).Call(name string, args []Value) (Value, error)`. - `web.NewHandler(program *check.Program, output io.Writer, diagnostics io.Writer) (http.Handler, error)`; validate handler shape before returning. - `web.Serve(ctx context.Context, listener net.Listener, handler http.Handler, diagnostics io.Writer) error`; the caller binds only after validation. - `cli.Run(ctx context.Context, args []string, stdout, stderr io.Writer) int`; successful server startup writes `Mica listening on http://ADDR\n` to stderr using the listener's actual address. For AST nodes use `FunctionDecl`, `LetStmt`, `BlockStmt`, `IfStmt`, `ReturnStmt`, `ExprStmt`, `IntLiteral`, `StringLiteral`, `BoolLiteral`, `NullLiteral`, `IdentExpr`, `UnaryExpr`, `BinaryExpr`, and `CallExpr`. `FunctionDecl` includes its name, typed parameters, return annotation, and body; `LetStmt` includes name, optional type annotation, and initializer; `IfStmt` includes condition, then block, and an optional block or nested if. Calls contain a name and arguments, not arbitrary callee expressions. Literals retain source spans; integers retain signed decimal text until range checking. Fold a direct unary minus plus integer token into a signed `IntLiteral`, allowing `-9223372036854775808` without admitting its positive out-of-range counterpart. Type annotations retain a name, one nullable bit, and a span. Never store request-specific data or mutable evaluation caches on the AST. ## Execution Order Tasks 1–3 establish sequential language contracts. Task 4 and Task 5 then share those contracts; integrate the server before completing CLI lifecycle tests. Task 6 packages only verified, committed work. This is one product and one plan: none of these packages is a separate service. ### Task 1: Parse Complete Programs with Source Locations **Files:** Create `go.mod`, `.gitignore`, and all `internal/syntax` files listed above. **Interfaces:** Consumes source text; produces `syntax.Lex`, `syntax.Parse`, diagnostic and AST types from Shared Contracts. - [x] **Step 1: Establish the build toolchain and module.** Locate a real Go compiler; `/usr/bin/go` is the board game. If absent, install an official supported release into a writable task-local tools directory, verify its published SHA256, and use its explicit `bin` path for Go and gofmt. Check networking policy before downloading. Confirm `go version`, `gofmt -h`, and the available `cc` compiler. Create `go.mod` with module `example.com/mica` and `go 1.22`; ignore `/dist/`, `/.tools/`, and `/.worktrees/`. - [x] **Step 2: Write lexer/parser tests.** Include `TestGreetingSyntax`, `TestPrecedenceAndAssociativity`, `TestNullableAnnotationAndElseIf`, `TestStringEscapes`, `TestCommentAtEOF`, `TestUnicodeLocation`, and malformed-source cases. Concrete assertions include: ```go // In package syntax; fixture is the greeting source in the spec. p, err := Parse("greeting.mica", fixture) if err != nil { t.Fatal(err) } if len(p.Statements) != 3 { t.Fatalf("statements: %d", len(p.Statements)) } if _, ok := p.Statements[0].(*FunctionDecl); !ok { t.Fatal("expected function") } if _, err := Parse("bad.mica", "print(\"oops);"); err == nil { t.Fatal("accepted unterminated string") } ``` Verify a lexer error immediately after `"é" ` has column 5, an EOF comment is valid, `??` associates right, and mixed arithmetic honors the spec. Test raw line breaks and invalid UTF-8, unsupported escapes, invalid identifiers, nested function declarations, missing semicolons, and repeated nullable suffixes. - [x] **Step 3: Run `go test ./internal/syntax`.** Confirm failure due to missing syntax APIs before implementing them. - [x] **Step 4: Implement source/token/AST definitions and lexer.** Decode UTF-8 for columns, retain byte offsets, reject invalid UTF-8, preserve EOF spans, and support precisely the spec's keywords, comments, escapes, and operators. - [x] **Step 5: Implement the parser.** Use precedence functions or precedence climbing; preserve the stated associativity, direct negative integer literal folding, top-level-only functions, and mandatory semicolons. Report a primary syntax diagnostic without a host panic. - [x] **Step 6: Run `gofmt -w internal/syntax` and `go test ./internal/syntax`.** All syntax cases pass; inspect representative parsed precedence trees. - [x] **Step 7: Commit:** `git add go.mod .gitignore internal/syntax` then `git commit -m "feat: parse Mica programs with source diagnostics"`. ### Task 2: Check Types Before Any Execution **Files:** Create all `internal/check` files listed above. **Interfaces:** Consumes `syntax.Program` and source spans. Produces `check.Type`, `check.Signature`, `check.Program`, `check.Check`, and `check.ValidateHandler` from Shared Contracts. Does not import the evaluator or HTTP packages. - [x] **Step 1: Write `TestRejectsBeforeExecution`, `TestNullableCoalescing`, `TestBranchRefinementAndShadowing`, `TestReturnAnalysis`, `TestForwardCallsAndRecursion`, and `TestHandlerContract`.** A local test helper parses source and calls `Check`, failing the test if parsing unexpectedly fails. Assert: ```go // Each source is passed through the parse/check helper. bad := []string{ `print("never"); let x = 1 + "2";`, `if "yes" { print(1); }`, `let x = null;`, `fn f(x: Void) -> Void { return; }`, `fn f(x: String?) -> String { return x; }`, `fn f(x: Bool) -> Int { if x { return 1; } }`, `fn f() -> Int { return 1; let x = 1 + "x"; }`, } for _, source := range bad { if checkSource(t, source) == nil { t.Errorf("accepted %s", source) } } ``` The helper signature is `checkSource(t *testing.T, source string) error`. Add good/bad cases for every built-in's arity and accepted types, nullable equality (including opaque/null rules), explicit conversions, signed literal limits, immutable bindings, duplicate names, no global capture, local shadowing, illegal `Void` use, and non-first-class functions. In a refined block shadow a `String?` variable with a new nullable binding and ensure it still cannot be passed to `String`. Test both direct null guard forms and reject refinement through compound boolean expressions. - [x] **Step 2: Run `go test ./internal/check`.** Confirm the missing checker API causes failure. - [x] **Step 3: Implement type definitions, built-in call rules, and signature collection.** Collect every top-level function first, prohibit reserved-name collisions, and validate all annotations. Check signed integer literal ranges statically. - [x] **Step 4: Implement lexical checking, expressions, and structural return analysis.** Use binding-identity-aware nullable refinements; scoped shadowing must create a new binding. Check all statements even after returns. Do not execute user code or perform output while checking. - [x] **Step 5: Implement `ValidateHandler`.** Require one `handle` function with exactly one `Request` parameter and a `Response` result; reject any top-level statement other than a function declaration. Parameter spelling need not be `request`. - [x] **Step 6: Run `gofmt -w internal/check` and `go test ./internal/syntax ./internal/check`.** Both packages pass, including all rejected-source cases. - [x] **Step 7: Commit:** `git add internal/check` then `git commit -m "feat: statically check types scopes and handler contracts"`. ### Task 3: Execute Checked Programs with Controlled Failures **Files:** Create all `internal/eval` files listed above. **Interfaces:** Consumes checked programs only. Produces tagged values, request/response constructors, and `Interpreter` APIs from Shared Contracts. Uses an injected writer for print output. - [x] **Step 1: Write evaluator tests with a parse/check/evaluate helper returning `(string, error)`.** Include `TestGreeting`, `TestLexicalScopeAndCalls`, `TestNullableBuiltins`, `TestLazyEvaluation`, `TestCheckedArithmetic`, `TestCallDepth`, and `TestOpaqueResponses`. Assert: ```go output, err := runSource(`fn greet(n: String) -> String { return "Hello, " + n; } print(greet("Ada"));`) if err != nil || output != "Hello, Ada\n" { t.Fatalf("%q, %v", output, err) } output, err = runSource(`print(false && (1 / 0 == 0)); print(true || (1 / 0 == 0));`) if err != nil || output != "false\ntrue\n" { t.Fatalf("%q, %v", output, err) } output, err = runSource(`print(parse_int("oops") ?? 42);`) if err != nil || output != "42\n" { t.Fatalf("%q, %v", output, err) } ``` Test division truncation, add/subtract/multiply boundaries, minimum-int negation, `MinInt / -1` overflow, and `MinInt % -1 == 0`. Test exact conversion rules and null display, query absent/empty/first value, JSON quoting and primitive/null encoding, writer errors, return propagation, forward and recursive calls, and the 256-active-call limit. Errors include the originating Mica filename and line. - [x] **Step 2: Run `go test ./internal/eval`.** Confirm missing evaluator APIs cause failure. - [x] **Step 3: Implement tagged values and checked arithmetic.** Use explicit preconditions or standard-library integer facilities for overflow; never rely on Go wraparound as the language result. Retain source locations on runtime errors. - [x] **Step 4: Implement environments, expression/statement evaluation, and function calls.** Fresh lexical scopes, strict left-to-right order, lazy operators, explicit return propagation, isolated function frames, and active-call accounting must match the spec. - [x] **Step 5: Implement built-ins.** Validate decimal syntax before integer conversion; use standard JSON serialization. Copy externally supplied request data at the adapter boundary. Build text/JSON response values without writing to a socket. Calls to already-checked built-ins must still return controlled errors on output failures. - [x] **Step 6: Run `gofmt -w internal/eval` and `go test ./internal/...`.** All established language tests pass. - [x] **Step 7: Commit:** `git add internal/eval` then `git commit -m "feat: interpret checked Mica programs and builtins"`. ### Task 4: Serve Isolated Typed HTTP Handlers **Files:** Create all `internal/web` files listed above. **Interfaces:** Consumes `check.ValidateHandler`, `eval.New`, `eval.RequestValue`, `Interpreter.Call`, and `eval.ResponseValue`. Produces `web.NewHandler` and `web.Serve`. No request data is written to the checked program. - [x] **Step 1: Write HTTP tests using `httptest`.** Include `TestGreetingQueries`, `TestPrimitiveJSON`, `TestRejectsMalformedInput`, `TestHandlerFailureIsPrivate`, `TestConcurrentIsolation`, `TestHEAD`, `TestRejectsInvalidHandler`, and `TestGracefulShutdown`. Assert: ```go // h is created from the specification's handle function. rr := httptest.NewRecorder() h.ServeHTTP(rr, httptest.NewRequest("GET", "/?name=Ada", nil)) if rr.Code != 200 || rr.Body.String() != "Hello, Ada" { t.Fatalf("%d %q", rr.Code, rr.Body.String()) } if rr.Header().Get("Content-Type") != "text/plain; charset=utf-8" { t.Fatal(rr.Header()) } if rr.Header().Get("X-Content-Type-Options") != "nosniff" { t.Fatal(rr.Header()) } ``` Test missing versus empty and duplicate query values; `%zz`, `%FF`, invalid UTF-8 in an unused key/value and decoded path; JSON escaping/nulls; all parsed methods/paths reaching the handler; and runtime failure returning HTTP 500 with exactly the fixed public error message. Run 32 simultaneous requests with distinct names and verify each result. Use a real `httptest.Server` for HEAD body behavior, not only a recorder. Share non-thread-safe diagnostic/output buffers in the concurrency test to expose missing writer synchronization. Cancellation must close the listener and let `Serve` return nil. - [x] **Step 2: Run `go test ./internal/web`.** Confirm missing web APIs cause failure. - [x] **Step 3: Implement `NewHandler`.** Validate first; parse the full query with `url.ParseQuery` and validate decoded UTF-8 before any handler call. Create a fresh evaluator and copied opaque request value per request, serialize shared output/diagnostic writer access, buffer the response, and apply content-type and nosniff headers. Do not disclose runtime diagnostics to the client. - [x] **Step 4: Implement `Serve`.** Use `net/http.Server` with `ReadHeaderTimeout: 5s` and `IdleTimeout: 60s`; on cancellation allow up to 5s for graceful shutdown. Treat `http.ErrServerClosed` as normal completion. Acknowledge HEAD semantics in the adapter or standard server without special-casing user code. - [x] **Step 5: Run `gofmt -w internal/web`, `go test ./internal/web`, and `go test -race ./internal/web`.** All cases pass without races or leaked listeners. - [x] **Step 6: Commit:** `git add internal/web` then `git commit -m "feat: serve typed request handlers with isolated state"`. ### Task 5: Deliver the CLI and Verify Real Process Behavior **Files:** Create `internal/cli/cli.go`, `internal/cli/cli_test.go`, `cmd/mica/main.go`, and `cmd/mica/integration_test.go`. **Interfaces:** Consumes all earlier package contracts. Produces `cli.Run` and the executable commands from the spec; `main` supplies signal cancellation, OS arguments, and standard streams. - [x] **Step 1: Write unit tests for `Run`.** Use temporary source files and buffers. Assert the greeting output; `check` silent success; syntax/type errors with zero stdout; runtime errors after earlier prints; missing files returning 1; and missing/unknown commands or extra arguments returning 2. Include filenames with spaces. Test `--addr` after the source path, default address selection, malformed flag values, and unknown flags. Invalid address syntax is usage (2); a valid address that cannot bind is a listener failure (1). - [x] **Step 2: Run `go test ./internal/cli`.** Confirm failure due to missing `Run`. - [x] **Step 3: Implement command parsing and the complete read/parse/check pipeline.** Parse command-specific flags explicitly so the documented source-first ordering works. For `serve`, validate source and handler before `net.Listen`; then print the actual address to stderr and call `web.Serve`. Keep program stdout separate from all CLI diagnostics. - [x] **Step 4: Write binary integration tests.** Build one binary into a test temporary directory. Start `serve` with `--addr 127.0.0.1:0`, read its startup address with a bounded deadline, make an HTTP request, send SIGINT, and assert exit 0. Start a process with a bad handler and assert exit 1 without a startup/listening message. Every spawned process has cleanup and a deadline; avoid arbitrary sleeps. - [x] **Step 5: Implement `main`.** Use `signal.NotifyContext` for interrupt and termination signals; pass the context to `Run` and use its returned exit code. - [x] **Step 6: Run `gofmt -w internal/cli cmd/mica`, `go test ./internal/cli ./cmd/mica`, and `go build ./cmd/mica`.** Real command and server lifecycle checks pass. - [x] **Step 7: Commit:** `git add internal/cli cmd/mica` then `git commit -m "feat: add check run and serve commands"`. Remove or ignore the temporary root build binary; the final package lives in `dist`. ### Task 6: Package the Verified Product and Document Its Use **Files:** Create `examples/greeting.mica`, `examples/nullable.mica`, `examples/web.mica`, `examples/invalid.mica`, `README.md`, and executable `scripts/package.sh`; generated artifacts go to ignored `dist/`. **Interfaces:** Consumes the verified CLI and repository source. Produces documented runnable examples, `dist/mica-linux-amd64`, `dist/mica-source.tar.gz`, and `dist/SHA256SUMS`. - [x] **Step 1: Add examples.** Greeting must print `Hello, Ada\n`; nullable conversion must demonstrate both successful parsing and fallback; web must use the spec's handler; invalid must visibly demonstrate a rejected `String`/`Int` operation. README commands use these exact paths. - [x] **Step 2: Write the README.** Include Go requirements, `go build -o dist/mica ./cmd/mica`, check/run/serve examples, expected output, a local curl request, syntax/type/null rules, diagnostics, and each major deferred feature. Explain that JSON currently supports scalar values, the listener is for development, and PHP programs cannot be run directly. Do not invent a license or production benchmark. - [x] **Step 3: Implement `scripts/package.sh`.** Run from any working directory by resolving the repository root. Require a clean source tree and verified Go toolchain. Use `CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -o dist/mica-linux-amd64 ./cmd/mica`; use `git archive` for the committed source tarball and create SHA256 checksums relative to `dist`. No network, upload, or publication occurs in packaging. - [x] **Step 4: Run the release checks:** `gofmt -l cmd internal` must be empty; `go test ./...`, `go vet ./...`, `go test -race ./...`, and `go build -o dist/mica ./cmd/mica` must pass. Execute the examples through that binary: check all three valid examples, verify exact greeting and nullable output, confirm the invalid example exits 1 with no stdout, and run a real HTTP smoke test. Fix any failure before packaging. - [x] **Step 5: Obtain an independent whole-product review.** Give a fresh reviewer the spec, plan, final source, and observed checks. Resolve material correctness or missing-requirement findings, repeating the affected checks after fixes. Preserve the chosen execution method's review requirements. - [x] **Step 6: Commit:** `git add examples README.md scripts/package.sh docs/superpowers/plans/2026-10-22-mica-implementation.md` then `git commit -m "docs: add examples and verified release packaging"`. Track completed steps truthfully before committing. - [x] **Step 7: Run `scripts/package.sh` and validate the artifacts.** Run `sha256sum -c SHA256SUMS` from `dist`; check the source archive includes `go.mod`, CLI code, tests, and README. Run the packaged Linux binary on the greeting example. Extract the source into a temporary directory and run `go test ./...` there. Record these successful checks in the plan and commit that documentation update; regenerate the artifacts from the final clean commit and recheck their checksums. Only checkboxes changed after the full tests, so no broader test rerun is needed. Confirm `git status --short` is empty. Record observed checks in the delivery message; report any check that could not run. ## Plan Self-Review and Handoff Self-review completed against the specification: all language rules, CLI and HTTP contracts, source diagnostics, arithmetic limits, deferred features, required checks, and documentation have owning tasks. The five Review Focus cases are assigned explicit tests. Interfaces use the same names and types across tasks; the evaluator remains independent of HTTP; adapters share the checked pipeline. Recommended execution method: **Native**. These six tasks depend closely on shared AST and type contracts; one implementer can keep those interfaces aligned, then obtain an independent whole-product review before delivery. Subagent-driven execution remains available if the user prefers per-task independent reviews. The user selected Native execution. Tasks 1–5 are implemented and verified. The independent whole-product review identified script interruption and OPTIONS-star dispatch issues; both have failing-first regression tests and verified fixes. Release packaging and source-archive validation are complete. The extracted archive passes all 74 test cases; the executable and source checksums validate. Windows x64/ARM64 builds are being included in the requested OneGodian workspace.