# TMod-c — Current Status

> **Rebrand (July 2026):** Public project and language name is **TMod-c** (TYPE compiler). **Mod-c** is the legacy name during transition — repo directory, `modc` binary, and `modc-mh/1` format id are unchanged until migration completes. Target compiler binary: **`tmodc`**; system ABI module: **`tmodc.mc`** / **`tmodc.h`**. Domains: tmodc.com, tmodc.org, tmodc.net.

**Version:** 0.26.5 (build 179)  
**Last updated:** 2026-09-04  
**Active branch:** `mod-c_0.26`  
**Tag:** `MOD-C_0.23.7` (items 5–6); **0.23.8** postfix `FORWARD`; **0.23.9** type-qualified methods; **0.24.0** `.mh` writer + reader; **0.24.2** test-tier Makefiles; **0.24.3** builtin `integer`/`cardinal` lowering; **0.24.4** `codegen_header.mc` self-host step; **0.24.5** qualident `IMPORT … FROM`; **0.24.6** ENUM Phase A/B; **0.24.7** ENUM Phase C + `.mh` negative import tests; **0.24.8** named `CONST` array bounds + const-eval; **0.24.9** `symkind` / `mh_exportkind` as `.mc`; **0.24.10** `statement.mc`; **0.24.11** `expression.mc` + **`OPAQUE` (13a)**; **0.24.12** **`UNION` (13c)**; **0.24.13** **linked-chunk arena** + **`STRUCT EXTENDS` option A (13d)**; **0.24.14** **`Lexer.mc` self-host** + **`type_of_expr` / init inference (21a)**; **0.24.15** **discard enforcement (13b Policy A)**; **0.24.16** **`declaration.mc` self-host** + **EXTENDS by-value auto-upcast**; **0.24.17** **instance methods (21)** + static/instance by first formal; **0.24.17.135** **`type Name FORWARD`**; **0.24.18** **#11 Phase A** portable unit rebind; **0.25.0** **item 20** VAR/REF/CONST formals (**breaking**); **0.25.1** **callable field call-through**; **0.25.2** **cross-module method Phase A**; **0.25.3** **`.mh` formal signatures + 7a**; **0.25.4** **`RECURSIVE` enforce + signed `SIZEOF` + lean C prelude**; **0.26.0** **free-call soft-miss closed**; **0.26.1** **unknown types closed + no automatic `stddef.h`**; **0.26.2** **`Parser` → `TParser`**; **0.26.3** **`parser.c` → `parser_common.mc` + `parser_main.mc`**; **0.26.3.170** **`.mh` field lists**; **0.26.4** **method-type `.mh` RHS / cross-module field call-through**; **0.26.5** **width forms + `.h` prelude**; **0.26.5.174** **#11 import-bind + `.mh` widths**; **0.26.5.175** **EXTENDS polish** (`p^.x`, `as` → `.base`, pointer/`REF` upcast); **0.26.5.176** **Oberon `p.x` auto-deref**; **0.26.5.177** **Shapes example + light refactor**; **0.26.5.178** **`p[i]` peel + instance method on `^T`**; **0.26.5.179** **`Type::m(p)` peel**.

## Current Focus

**Calm path (ordered — do in sequence):**

| Step | Item | Work |
|------|------|------|
| ~~**1**~~ | ~~**13a**~~ | ~~`OPAQUE` end-to-end~~ **Done (0.24.11)**. |
| ~~**2**~~ | ~~**13c**~~ | ~~Bare `UNION`~~ **Done (0.24.12)** — parse / semantic / `codegen_common_union_decl`; tests green. |
| ~~**3**~~ | ~~**13d**~~ | ~~`STRUCT EXTENDS` option A~~ **Done (0.24.13)** — chain clashes; synthetic `base` reserved **only on EXTENDS**; `c.x` → `c.base.x`; multi-level. |
| ~~**4**~~ | ~~**21a**~~ | ~~`type_of_expr` + simple init inference~~ **Done (0.24.14)** — unlocks discard (13b), auto-upcast, VAR/REF, `obj.method`. |
| ~~**5**~~ | ~~**13b**~~ | ~~Discard enforcement (Policy A)~~ **Done (0.24.15)** — known result requires `(f())` or use; unknown/procedure bare OK. |

**Suggested next language work** (on **`mod-c_0.26`**):

1. ~~**Close name soft-miss (breaking)**~~ — **Done.** Calls **0.26.0**; unknown types + drop automatic `<stddef.h>` **0.26.1**. Prelude builtins and multi-word C spellings (`long long`, `unsigned int`) stay. `size_t` / `FILE` / `void` must be imported.
2. ~~**`.mh` type completeness**~~ — **Done (0.26.3.170 field lists; 0.26.4 method-type RHS).** Cross-module `obj.field` and `obj.field(...)` call-through. Import the method type **and** the struct (`TFn` + `TBox`). Identifiers ≤ 255; whole-file `.mh` load; writer `DynBuf`.
3. ~~**#11 width forms**~~ — **Done (0.26.5).** Exact `integer N` / `cardinal N` / `real N` (8/16/32/64; `real` 32/64). Generated `.h` owns the C prelude; `-C` writes a companion `.h`. ~~**Import as the one unit bind**~~ **Done (0.26.5.174).** ~~**`.mh` width spelling**~~ **Done (0.26.5.174).** **Still open (same item):** arch packs (`tmodc.lp64`, …); build-time defaults; optional `.mh` alias RHS (`export type integer complete integer 64`).
4. Optional **EXTENDS polish** — ~~aggregate `as` → `.base`~~ **Done (0.26.5.175)**; ~~pointer/`REF` upcast~~ **Done (0.26.5.175)**; ~~`^T` parent fields (`p^.x`)~~ **Done (0.26.5.175)**; ~~Oberon `p.x` auto-deref~~ **Done (0.26.5.176)**; ~~`p[i]` peel~~ **Done (0.26.5.178)**; ~~instance method on `^T`~~ **Done (0.26.5.178)**; ~~`Type::m(p)` peel~~ **Done (0.26.5.179)**. **Still open (same item):** parent-chain methods. See [Recent Accomplishments (0.26.5.179)](#recent-accomplishments-4-september-2026--0265179--typemp-peel).
5. Soft **item 20** — named open-array alias formals. **Bare formals stay by-value** — see `docs/parameter-passing.md`.
6. Soft: **21a-ternary**; discard `_` (**24**); **#19** `CONST` codegen. Self-host remains background. ~~**7b** startup auto-init~~ — **Cancelled** (31 August 2026). Call module entries explicitly (7a). No generated `main` walk of imports.
7. Later: **loop-local `FOR`** (**breaking**, JPL Power of Ten rule 6) — counted `FOR` always **declares** a read-only index; not a use of an enclosing `VAR`. See [Future plan: loop-local FOR](#future-plan-loop-local-for-jpl-rule-6) below. Not started; do not slip into 0.26.x calm-path work.
8. Later: **optional `BOUND`** on `WHILE` / `REPEAT` / `LOOP` (JPL rule 2) — const trip count; `loop bound 0` = idle loop. See [Future plan: BOUND](#future-plan-bound-on-while-repeat-loop-jpl-rule-2). Not 0.26.x.
9. Later: **drop unused `IS`** — lexer keyword / EBNF relational op; never parsed. No type guards / RTTI. See [Drop `IS`](#drop-is-no-type-guards). `IN` stays reserved for **`SET OF` membership** (item 12).
10. Later: **cyclic TMod-c `IMPORT`** — after Makefile subdirectory compilation (**item 15**). `parser_main` ↔ `declaration` / `expression` / `statement` works today via generated C headers and previously emitted `.mh`. Do **not** design a language rule until directories land. Interim: extract a shared module (`parser_common`).
11. When a **stdlib** is designed: borrowed / pre-allocated buffers (e.g. `TStringBuffer::init_at`), not only `malloc`/`realloc`. See [Stdlib: borrowed buffers](#stdlib-borrowed-buffers-when-designed).
12. Later: **`SET OF` enum** (Wirth bitset, not a hash set) — `IN`, `{ … }` literals, named `CONST` sets, `+` `*` `-` `==` `!=`. See [Future plan: SET OF enum](#future-plan-set-of-enum-wirth-bitset). Not 0.26.x.

**0.26.5.179** closes `Type::m(p)` peel (`@x` not peeled). **0.26.5.178** closed `p[i]` peel and instance method on `^T`. **0.26.5.177** is a light refactor plus `examples/Shapes.mc`. **0.26.5.176** closed Oberon `p.x` auto-deref. **0.26.5.175** closed EXTENDS polish (`p^.x` / `as` / pointer·`REF`). **0.26.5.174** closes import-as-bind and `.mh` width tails. **0.26.5.173** closed width forms and moved the C prelude into generated `.h`. **0.26.4.172** closed `.mh` type completeness. **0.26.3.168** closed `parser.c` self-host. **0.26.1.158** closed unknown type names and dropped automatic `<stddef.h>`. **0.26.0.156** closed free-call soft-miss. No hidden RTTI / type tags / vtables on structs (Modula-2 + C stance).

EOS layout rules (0.24.3) remain in force. Arena growth is **pointer-stable** (linked chunks; no whole-slab `realloc`).

## Future plan: loop-local `FOR` (JPL Rule 6)

**Status:** Design locked (20 August 2026). **Not implemented.** Breaking when done — sole `FOR` form; no dual `FOR i :=` on an existing `VAR`. Spec in `docs/syntax-ebnf.md` + Language Report (`docs/language-report.md`) when the bump starts.

**Why:** C11 `for (int i = …)` / Modula-3 / Ada: the index exists only for the loop. Today TMod-c is Oberon/Pascal (`FOR i :=` assigns a predeclared `var i`; codegen `for (i = start; …)`). JPL Power of Ten **rule 6** wants smallest scope.

**Syntax** (declaration `=`, same optional type as `var-item` / `let-item`):

```
for-statement =
    "FOR" identifier [ ":" type-specifier ] "=" expression
        ( "TO" | "DOWNTO" ) expression
        [ "BY" const-expression ]
    "DO" { invariant-clause } statement-sequence "END" ;
```

```
for i = 0 to n do … end
for i: integer = 0 to n do … end
for i = n downto 0 by 1 do … end
```

**Semantics**

- `FOR` **always** introduces `i` (may shadow). After `END`, `i` is gone — no “last index” unless copied inside.
- Body cannot `i :=`, `INC(i)`, `DEC(i)`, or pass `i` as a `VAR` actual. Only the compiler writes `i` (init + step).
- No hint → type is **`integer`** (signed index/length lock). Do **not** infer `cardinal` from a `cardinal` bound. Hint, if present, must be integer-kind allowed for indexes (`integer`, later `integer N`). Start/end must fit that type. Not a C three-clause `for`.

**Codegen** — same wrapper as now; `i` is a new local in that block:

```c
{
    const long long __for_end_lN = (long long)(end);
    for (integer i = start; (long long)(i) <= __for_end_lN; i++) { … }
}
```

Start evaluated once as the initializer. End stays precalculated. `i` is not C `const` (the header does `i++`); read-only is a TMod-c body rule. Nested `for i = …` each have their own `{ }`.

**When implementing:** parser (`:=` → `=` + optional type); semantic (define loop-scoped binding, keep write-forbid, no enclosing-`VAR` lookup); `codegen_c_for_stmt`; tests; mechanical sweep of `src/*.mc` and tests (`for i :=` → `for i =`, drop loop-only `var i`). Version bump (not a quiet 0.26.x patch). Empty `TO` range still does not enter; `BY 0` stays illegal.

## Future plan: `BOUND` on `WHILE` / `REPEAT` / `LOOP` (JPL Rule 2)

**Status:** Design locked (31 August 2026). **Not implemented.** Optional in the language; a later `--pot` (or equivalent) may *require* it. Do not slip into 0.26.x. `FOR` does **not** take `BOUND` (it already has `TO`/`DOWNTO`).

**Why:** Holzmann rule 2 — every loop has a tool-visible trip ceiling, except one identified non-terminating task loop. `INVARIANT` is a boolean, not a max count.

**Syntax** (`const-expression`, same family as `FOR` … `BY` / array bounds):

```
while-statement =
    "WHILE" expression "DO"
        [ "BOUND" const-expression ]
        { invariant-clause }
        statement-sequence
    "END" ;

repeat-statement =
    "REPEAT"
        [ "BOUND" const-expression ]
        { invariant-clause }
        statement-sequence
    "UNTIL" expression ;

loop-statement =
    "LOOP"
        [ "BOUND" const-expression ]
        { invariant-clause }
        statement-sequence
    "END" ;
```

```
while p <> nil do
	bound 4096
	p := p^.next
end

repeat
	bound 8
	try_once
until done

loop
	bound 0
	wait_for_cmd
end
```

**Semantics**

- Bound is compile-time; not a runtime `n` that changes.
- Codegen: a local counter; reaching the bound is a failed `assert` (same abort as DbC), not a silent `break`.
- **`BOUND 0` only on `LOOP`:** “non-terminating on purpose” (the idle / task loop). Illegal on `WHILE` / `REPEAT`.
- Omitted `BOUND`: legal in ordinary TMod-c. `--pot` (later, not scheduled) may require a bound except one `loop bound 0` per task.

**When implementing:** `statement.mc` + EBNF + Language Report §7.1; semantic: const-eval, `BOUND 0` only on `LOOP`; codegen trip counter + `assert`; tests (including `test3` for `while … bound 0`). Keyword `BOUND`. May share a version bump with loop-local `FOR` or land separately.

## Drop `IS` (no type guards)

**Status:** Locked (31 August 2026). **Not implemented.** Lexer still reserves `IS` (`TOK_KEYWORD_IS`); **parser never uses it.** EBNF no longer lists `IS` (relational-op is `IN` only). Language Report §6.3: `IN` is planned set membership; `IS` is dropped.

Oberon `IS` is a runtime type test (`p is T`) — needs RTTI or a tag. TMod-c: **no vtables / no `IS` on structs.** Remove the keyword (lexer table, `TokenKind::string`, EBNF `relational-op` / `keyword`, report). `is` becomes a legal identifier.

**`IN`:** still reserved; unused as an operator. Keep — v1 **`SET OF` enum** membership (not a type guard). See [Future plan: SET OF enum](#future-plan-set-of-enum-wirth-bitset).

**When implementing:** small mechanical drop; any `test3` that used `IS` as a keyword should expect an identifier. Spec in `docs/syntax-ebnf.md` + Language Report. Not 0.26.x calm-path.

## Future plan: `SET OF` enum (Wirth bitset)

**Status:** Design locked (2 September 2026). **Not implemented.** After the current higher-priority list. Do not slip into 0.26.x. Spec in `docs/syntax-ebnf.md` + Language Report §5 / §6.3 when the bump starts (productions already drafted as *Planned*).

**Why:** `IN` is in the grammar for **set membership**, not type guards (`IS` is dropped). Compiler source wants named groups (`LOOP_KINDS`) and `kind in LOOP_KINDS` instead of `or` chains. This is Pascal/Modula-2 `SET OF`: a **bit vector** on a small ordinal, not Julia/Python `Set{T}` (hash table, heap, arbitrary `T`). Hash sets, if ever, are stdlib — not `IN`.

**v1 surface**

- Type: `SET OF E` where `E` is an **enum**. Every enumerator value is a distinct constant in **0 .. 63**. One `cardinal 64` / `uint64_t` mask.
- Constructor: Modula-2 **`{ a, b, c }`** — same braces as `array-literal`; semantic picks set vs array from the expected type / element types. Empty `{}` needs a type ascription.
- Named sets: `type NodeKindSet = set of NodeKind` then `const LOOP_KINDS: NodeKindSet = { NODE_FOR, NODE_WHILE, NODE_REPEAT_UNTIL, NODE_LOOP }`.
- `x IN s` — `x` is `E`, `s` is `SET OF E`.
- `s + t` union, `s * t` intersection, `s - t` difference, `s == t` / `s != t`. Include/exclude via `s := s + { x }` / `s := s - { x }`.
- Do **not** use `|` / `&` on sets (those stay integer/enum flags). `SET OF E` and `SET OF F` are different types.

```
type NodeKindSet = set of NodeKind

const LOOP_KINDS: NodeKindSet =
    { NODE_FOR, NODE_WHILE, NODE_REPEAT_UNTIL, NODE_LOOP }

if new_parent^.kind in LOOP_KINDS then
    child.enclosing_loop := new_parent
end
```

**Codegen** — bit test / mask; no heap:

```c
typedef uint64_t NodeKindSet;
static const NodeKindSet LOOP_KINDS =
    (1ULL << NODE_FOR) | (1ULL << NODE_WHILE) |
    (1ULL << NODE_REPEAT_UNTIL) | (1ULL << NODE_LOOP);

if (LOOP_KINDS & (1ULL << new_parent->kind))
    child.enclosing_loop = new_parent;
```

TMod-c still rejects mixing `ColorSet` with `NodeKindSet` even if both are 64-bit in C.

**v1 rejects:** `SET OF integer` / `real` / `struct` / `string`; enumerator `= 1000` or more than 64 members; `SET OF char` (256 bits — later); `FOR x IN s`; `CARD`; hash `Set`. Optional later: `<=` subset, `XOR` symmetric difference, `NOT` complement in `E`, Ada-style `x in (A, B)` sugar.

**When implementing:** keyword `SET`; `set-type` in `type-expression` / `type-specifier`; `IN` in the relational parser (token exists); `{ … }` set vs array in semantic; operator types; tests (`test_*` membership/algebra, `test3_*` bad base type / ordinal out of 0..63). Version bump (not a quiet 0.26.x patch). May land after `IS` drop so `IN` is the only leftover relational keyword.

## 7b cancelled — no startup auto-init

**Status:** **Won’t do** (31 August 2026). Item **7a** (module entry as an importable symbol) stays.

Do **not** generate calls of imported `MODULE` bodies from `PROGRAM` / `main` (Modula-2 / Delphi style). Hidden init is extra control flow (JPL rule 1) and a place to hide `malloc` (rule 3). Authors **call** the bound module entry explicitly when they want it. Optional module `BEGIN`…`END` remains a procedure the programmer invokes — not a constructor the compiler schedules.

## Stdlib: borrowed buffers (when designed)

**Not scheduled.** `tests/StringBuffer.mc` today `malloc`s / `realloc`s / owns `_data` — fine for hosted tests, not a flight/Wasm default.

When a real stdlib is designed, prefer **caller RAM**:

```
procedure TStringBuffer::init_at(ref b: TStringBuffer, buf: ^char, cap: integer)
```

- `require buf <> nil` and `cap > 0`; no `malloc` / `realloc`; append **fails** (bool or `assert`) at capacity.
- `free` of `_data` only if an optional hosted `init` set an owns-flag; `init_at` does not own.
- Same pattern for other containers: `ARRAY[N]`, or `init_at(p, n)`, never “grow until the heap says no.”

Hosted growing `StringBuffer` may remain for the compiler and Linux tests. Flight / `--pot` / wasm32 guests should not need `realloc`.

## DbC resolve (REQUIRE / ENSURE)

**Done** in `semantic_analyze_block_body` — `requires[]` / `ensures[]` go through `semantic_resolve_expr` (same as loop `INVARIANT` and `ASSERT`). `REF`/`VAR` formals load as in the rest of the language.

Still not a nil-check of a `REF T`: `n` is the object. Nil-check `^T` formals and pointer **fields**; check `p <> nil` **before** `foo(p^)`. Remaining polish (not planned): side-effect-free contract lint; optional `--pot` “two assertions per routine” warn.

## Recent Accomplishments (4 September 2026 — 0.26.5.179 / `Type::m(p)` peel)

### Qualified instance `Type::m(p)` on `^Owner` **Done**

- **`Point::print(pp)` = `pp.print()`** when `pp` is `^Point`. First actual only; pointee name must be the owner. Reuses `call.auto_deref`; codegen peels `args[0]` when there is no `receiver_expr`.
- **C** — by-value `Point__print((*pp))`; `REF` `Point__scale(&(*pp), n)`.
- **Do not peel `@`:** `TLexer::next(@p.lexer)` stays `&(p.lexer)`. `(*&x)` passed a struct by value (selfhost `TParser::advance`).
- **Do not peel `pp^`:** already a value (one caret wrap).
- **After** `semantic_resolve_expr` on args. **Only if** `receiver_expr == nil` — an unconditional `auto_deref := false` wiped `pp.getX()` (`argc` is 0).
- **Tests:** `tests/test_smoke.mc` (`Point::print(pp)` / `Point::scale(pp, 3)` / `Point::getX(pp)`). Selfhost lexer `@` calls.
- **Still open (same item):** parent-chain method lookup.
- **Verification:** user typed in; **make test-all** / **selfhost** / **bootstrap** / **promote** green on **gcc**, **clang**, and **tcc**. Build **179**. Promoted **0.26.5.179**.

## Recent Accomplishments (4 September 2026 — 0.26.5.178 / `p[i]` peel + instance on `^T`)

### Pointer-to-array `p[i]` and `p.method` on `^T` **Done**

- **`p[i]` = `p^[i]`** when the left side is a pointer-to-array (`^array[N] of T` or `^Name` with `Name` an array typedef). One implied peel per `[]`. AST stays `NODE_ARRAY_INDEX` (`array_index.auto_deref`); no inserted caret.
- **Do not peel `^char[]`** — `argv[i]` is `^char` (array-of-pointer, not pointer-to-array).
- **C** — `(*(p))[i]`. Anonymous `^array[N] of T` emits `T (*name)[N]` (caret was previously ignored). Named `^Vector3` stays `Vector3 *p`.
- **Explicit `p^[i]`** — postfix `^` emits `(*(expr))` so C `[]` does not bind tighter than unary `*` (`*p[i]` was `*(p[i])`).
- **`p.method` on `^T`** — `call.auto_deref`; first formal still owner **value** (`self: Point` / `ref self: Point`), not `^Point`. C by-value `Type__m((*p))`; `REF`/`VAR` `&(*p)`. `Type::m(p)` closed in **179**. No `->`.
- **Tests:** `tests/test_array.mc` (`pv[i]` / `pv^[i]` / `pa[i]` / `argv[0]`); `tests/test_smoke.mc` (`pp.getX()` / `pp.print()` / `pp.scale(2)` / `Point::print(pp^)`).
- **Still open then (closed 0.26.5.179):** auto-peel of `Type::m(p)`. **Still open:** parent-chain method lookup.
- **Verification:** user typed in; **make test-all** / **selfhost** / **bootstrap** green on **gcc**, **clang**, and **tcc**. Build **178**. Promoted **0.26.5.178**.

## Recent Accomplishments (4 September 2026 — 0.26.5.177 / Shapes + refactor)

Light refactoring already checked in. `examples/Shapes.mc` — tagged `EXTENDS` scene (no `IS`); field auto-deref (176); downcast `p as ^Circle` after a programmer tag.

## Recent Accomplishments (3 September 2026 — 0.26.5.176 / Oberon `p.x` auto-deref)

### Field auto-deref **Done**; `p[i]` and `p.method` on `^T` **not** in this build *(closed 0.26.5.178)*

- **`p.x` = `p^.x`** when the left side is a pointer (`^T` or named alias). One implied peel per `.`. AST stays `NODE_FIELD_ACCESS` (`field_access.auto_deref`); no inserted caret. Explicit `p^.x` unchanged.
- **Pointer test** — use type **or** `resolved_type` is a pointer. Do not chase the alias first (`^Child` would become named `Child` and drop the flag).
- **C** — `(*(p)).field`, then `.base` × `base_depth`. No `->`. `REF`/`VAR` formals still go through `emit_let_ident` (`(*formal)`); those are not TMod-c `^T`.
- **EXTENDS** — parent fields work: `c5.x` → `(*(c5)).base.x` (same `base_depth` as `c5^.x`).
- **Tests:** `tests/test_extends.mc` (`c5.x` / `pp.x` / `pg.z`, `p.x` in `takeParentPtr`); `tests/test_pointer_var.mc` (`root.value`, `p.next.value` beside `^.` forms).
- **Still open then (closed 0.26.5.178):** `p[i]` peel for pointer-to-array — do **not** peel `^char[]` `argv[i]`; instance method on `^T`.
- **Verification:** user typed in; **make test-all** / **selfhost** / **bootstrap** green on **gcc**, **clang**, and **tcc**. Build **176**. Promoted **0.26.5.176**.

## Recent Accomplishments (2 September 2026 — 0.26.5.175 / EXTENDS polish)

### Optional #4 — three slices **Done**; Oberon `p.x` **not** in this build

- **`p^.x` parent fields** — `semantic_type_of_designator` handles postfix `^` and `AS`. `c5^.x` sets `base_depth`; C `(*c5).base.x`. (`c5^.y` already worked.)
- **`g as Parent`** — `upcast_depth` from inner type vs `AS` target; codegen omits `(Parent)g` and uses `.base` × N. Pointer `as` (`(@g) as ^Child`) stays a C pointer cast unless it is an ancestor upcast (then `upcast_ptr`).
- **Pointer / `REF` upcast** — both-pointer or both-value in `semantic_extends_upcast_depth`. `Node.upcast_ptr`: value `((expr).base × N)` so `REF Parent` + Child actual is `&((c).base)`; `^Child` where `^Parent` is needed is `&((*(pc)).base)`.
- Sites already wired: typed init, `:=`, `RETURN`, same-unit call formals, plus `AS`.
- **Tests:** `tests/test_extends.mc` (user typed; green).
- **Still open then (field `.` closed in 0.26.5.176; `p[i]` / `p.method` closed in 0.26.5.178):** `p[i]` peel for pointer-to-array; instance `p.method` on pointer receivers. Do not peel `^char[]` `argv[i]`.

**Verification:** user typed in; tests green. Build **175**.

## Recent Accomplishments (31 August 2026 — one Makefile / gcc · clang · tcc)

- **Single `Makefile`** — `CC ?= gcc`; `CC_FAMILY` from `clang` / `tcc` / else gcc (paths and `clang-18` / `gcc-14` included).
- **Flags:** gcc keeps `-pedantic-errors` and `-Wcast-align=strict`; clang same minus the GCC-only align flag; tcc matches the old `Makefile.tcc` set (no pedantic/conversion; `-Wswitch-enum`).
- **`debug`:** gcc/clang `-fsanitize=address` on compile and link (no `-lasan`); tcc `-g -O0` only.
- **`make tar`** no longer copies `Makefile.clang` / `Makefile.tcc`. Those files moved to **`archive/`**.
- **Switch compiler:** `make clean` first so `build/c` objects are not mixed.
- **Verification:** `make test-all` green on **gcc**, **clang**, and **tcc**.

```bash
make                              # gcc (default)
make clean && make CC=clang test-all
make clean && make CC=tcc test-all
```

## Recent Accomplishments (28 August 2026 — 0.26.5.174 / #11 import-bind + `.mh` widths)

### Import as the one unit bind **Done**

- Named `.mh` import of `integer` / `cardinal` / `real` / `string` is the unit bind (Language Report §5.5). Prelude `decl == nil`; second bind is an error.
- Only `.mh` TYPE exports. Include-only and foreign `.h` imports do not skip the default `typedef`. `import integer as i64` does not bind `integer`.
- `codegen_unit_binds_portable` walks `.mh` import items (qualident, else `AS` alias). Pack `.h` supplies the C ABI.
- **Tests:** `test_import_rebind` + `fixtures/lp64` (lean header); `test3_import_rebind_second` / `test3_import_then_rebind`.

### `.mh` width spelling **Done**

- Writer: `integer 32` (and `cardinal` / `real`) on field, formal, and result type-spec. Name stays `integer`; `TType.width` is separate.
- Reader: `type_width` / `result_width`; optional decimal *N* before multi-word C names; closed *N*; two-digit cap (no signed overflow under `-Wstrict-overflow=4`).
- Semantic: imported field/formal/result types keep the width.
- **Tests:** `test2_export_width` / `test2_import_width`; `test_import_width` + `fixtures/wpoint`; `test3_import_width` (`integer 99`).
- **Still open (#11):** arch packs; build-time defaults; `.mh` alias RHS.

**Verification:** user typed in; tests green. Build **174**.

## Recent Accomplishments (27 August 2026 — 0.26.5.173 / width forms + `.h` prelude)

### Width forms **Done** (`integer N` / `cardinal N` / `real N`)

- Exact C11 widths. Closed *N:* **8 / 16 / 32 / 64** (`real` **32 / 64**). Decimal *N* only.
- `TType.width`; `type_c_spelling` → `intN_t` / `uintN_t` / `float` / `double`.
- `type integer = integer 64` is the Phase A unit bind with a width RHS.
- **Tests:** `test_width`, `test_width_rebind`, `test3_width`, `test3_width_real`.

### Generated `.h` owns the C prelude **Done**

- `codegen_emit_c_prelude` in the header (after the include guard): stdint/stdbool/assert, `nil`/`NIL`, `byte`, portable four unless this unit bound the name.
- Unexported portable `TYPE` binds still appear in the `.h`.
- Generated `.c` `#include "UnitName.h"`; no second prelude. `-C` writes a companion `.h`.
- Header always emits the unit prototype (PROGRAM and MODULE).
- **PROGRAM/MODULE name must match the output stem** (`#include "Name.h"`).
- `tmodc.h` remains optional for hand-written C. `.mh` width spelling still deferred.

**Verification:** `make test-all` on **gcc**, **clang**, and **tcc**. In-tree modules regenerated. Promoted **0.26.5.173**.

## Recent Accomplishments (26 August 2026 — 0.26.4.172 / method-type `.mh` RHS)

### Method-type export / import **Done**

- Writer: `export type TFn complete function (integer) : integer` (always `(…)` on the type line; `procedure` likewise). Same physical `@format 1` line as field tails.
- Reader: `is_func_type` + reuse `mh_parse_signature` after `complete` when the type is not `struct`/`union`.
- Semantic: synthetic `NODE_TYPE_DECL.method_type` (`NODE_METHOD_TYPE` + formals). Must assign `method_type := mt` (not `nil`).
- Field call-through uses existing `semantic_method_type_node` / Policy A discard (`(f())` as a statement when the result is known).
- Import **both** the method type and the owner struct (`TFn` and `TBox`).
- **Tests:** `test2_export_fn_type` / `test2_import_fn_type` (`(b.fn(1))`); `test3_import_fn_type` (no `TFn` import); `test_import_fn_type` + `fixtures/fnbox.{mc,mh,h}` (`b.fn := twice`; `assert b.fn(21) == 42`).
- **Verification:** `make test-all` on **gcc**, **clang**, and **tcc**. Promoted **0.26.4.172**.

## Recent Accomplishments (25 August 2026 — 0.26.3.170 / `.mh` field lists)

### Identifiers ≤ 255 **Done**

- Lexer: `IDENT_MAX_LEN` 255; longer names are `TOK_ERROR` (`identifier longer than 255 characters`).
- `parser_common` `error_at` prints `error_msg` for `TOK_ERROR`.
- `.mh` `mh_read_ident` same bound. Mangled `Owner__name` may be 512 (not a source identifier).
- **Test:** `tests/test3_ident_long.mc`.

### `.mh` reader whole-file **Done**

- `mh_reader_load`: file size → `malloc(n+1)` → parse in place (no 4096 `fgets` cap).
- `MhModule.source` owned until `mh_module_free`. Layout/formal strings may point into that buffer.

### Writer DynBuf prefixes **Done**

- Export lines (including `@module`, type/enum/binding/unit entry, method `Owner__name`) built on `DynBuf`. `snprintf` 256 only for the short generated-by comment.

### Field lists — writer / reader / import **Done**

- `export type Name complete struct (f: T { , … })`; `union`; optional `extends Parent`. `export type Name opaque` unchanged (`EXTERN TYPE`, `type T = opaque`).
- `mh_type_opaque`: no longer treats `struct_body <> nil` as opaque.
- Reader: `MhField` on `MhExport`; old `opaque` / bare `complete` still legal.
- Semantic: synthetic `NODE_TYPE_DECL` + `struct_body` on import (arena-copied names). Unknown field on a complete imported struct is an error. Parent fields need the parent type imported (not flattened).
- **Tests:** `test2_export_struct` / `test2_import_struct` / `test3_import_struct_field`; union and EXTENDS pair; `test_import_struct` + `fixtures/tpoint.{mc,mh,h}` (compile + run). Writer `.mh` for `test2_*` still generated with `-M` (not a Makefile golden).
- **Verification:** `make test-all` green. Method-type RHS **Done (0.26.4)**.

## Recent Accomplishments (24 August 2026 — 0.26.3.168 / parser self-host)

### `parser.c` → `parser_common.mc` + `parser_main.mc` **Done**

- Shared parser state and token helpers live in **`parser_common`**: `TParser` / `pParser`, type-name registry, `advance` / `check` / `match` / `consume` / EOS / comments / assignment / skip helpers / `error_at` / `isEOF`.
- **`parser_main`** is the recursive-descent driver (`TParser::init` / `parse` / `parse_expr` / `parse_stmt` / blocks / types).
- Each common helper has **two** exports: old `advance(p: pParser)` (still used by `declaration` / `expression` / `statement`) and new `TParser::advance(ref p: TParser)` (used by `parser_main` only). Migrate the other three units later.
- Hand-authored **`parser.c` / `parser.h`** replaced. `modc` includes `parser_common.h` + `parser_main.h`.
- **Verification:** `make test-all`, **selfhost**, **bootstrap**, **promote** green on **gcc**, **clang**, and **tcc**. Promoted **0.26.3.168**.

### Cyclic `.mh` imports — noted, not designed

- `parser_main` imports parse entry points from `declaration` / `expression` / `statement`; those units import `TParser::parse_expr` / `parse_stmt` / … from `parser_main`.
- This is legal **today** because C headers can include each other and `.mh` is loaded from a prior generate. As `.mh` grows (field lists, signatures), mutual TMod-c imports will get fragile — a problem almost every new module language hits.
- **Do not address until after item 15** (Makefile subdirectory compilation / module directories). Interim: keep extracting a common module rather than closing a cycle.

## Recent Accomplishments (18 August 2026 — 0.26.1.158 / unknown types + no automatic stddef.h)

### Unknown type names are errors **Done (breaking)**

- `semantic_resolve_type_inner`: unbound **single-word** type name is fatal (`unknown type`).
- Still legal: prelude builtins (`bool`, `int`, `integer`, `long`, …); named `IMPORT` / `EXTERN TYPE`; `.mh` opaques; multi-word C spellings (`long long`, `unsigned int`). Bare `unsigned` is not a type — write `unsigned int` or a typedef.
- **`size_t`**, **`FILE`**, **`void`**, and compiler types (`Node`, `Parser`, …) must be listed on `IMPORT` (or declared). That import also emits the C `#include`.
- **Tests:** `test3_undef_type.mc` (`var f: FILE`). Compiler / test / example type import sweep.

### Automatic `<stddef.h>` dropped **Done**

- Generated prelude: `<stdint.h>`, `<stdbool.h>`, `<assert.h>` only.
- `#define nil ((void *)0)` / `#define NIL nil`. `byte` remains `uint8_t`.
- `size_t` is no longer free via the prelude; `import size_t from "stddef.h"` where used.

**Verification:** `make test-all`, **selfhost**, **bootstrap**, **promote** green on **gcc**, **clang**, and **tcc**. Promoted **0.26.1.158**.

## Recent Accomplishments (18 August 2026 — 0.26.0.156 / free-call soft-miss closed)

### Unresolved free calls are errors **Done (breaking)**

- `semantic_resolve_call`: `sym == nil` on a free `name(...)` or `Type::name(...)` is fatal (`undefined procedure or function` / `undefined type-bound method`).
- Still legal: same-unit `PROC`/`FUNC`; named `IMPORT` / `EXTERN`; 7a module-entry bind; method-typed locals (`fp(...)`); field call-through; prelude type names.
- Include-only `IMPORT FROM source` still binds **no** names. Quoted `FROM "hdr.h"` does not parse the header.
- **C preprocessor** is pass-through only. `#define` does not create TMod-c symbols. A macro used from `.mc` belongs in a real `.h` and on an `IMPORT`.
- **Not this bump:** unknown type names (`size_t`, `FILE`) still soft-miss; automatic `<stddef.h>` stays.
- **Tests:** `test3_undef_call.mc`, `test3_undef_method.mc`; `test_tmodc.mc` uses a real `TSTRING` function (no dummy import / same-file `#define`). Compiler `src/*.mc` import sweep so self-host stays legal.
- **Verification:** `make test-all`, **selfhost**, **bootstrap**, **promote** green on **gcc**, **clang**, and **tcc**. Promoted **0.26.0.156**.

## Recent Accomplishments (14 August 2026 — 0.25.4.154 / RECURSIVE + signed SIZEOF + lean prelude)

### `RECURSIVE` required on direct self-calls **Done**

- A call whose `resolved_sym.decl` is the enclosing `NODE_PROC_DECL` / `NODE_FUNC_DECL` is a **direct self-call**. The completing declaration (the one with the body) must have `RECURSIVE`.
- Field call-through (`resolved_sym` nil) and the unit `NODE_PROGRAM` body are not treated as self-calls. Mutual recursion is not checked (later analyzer).
- Tag belongs on the **body** decl after `FORWARD` refine (`symtab_refine_symbol` replaces the symbol).
- Sweep: `semantic.mc`, `ttype.mc`, `expression.mc`, and other compiler `.mc` self-calls tagged.
- **Tests:** `tests/test3_recursive.mc`; positive: `test_FactorialDemo` / `test_FibonacciDemo`.

### `SIZEOF` is `integer` in C as well as in the type system **Done**

- Semantic type was already `integer`. Emit is now `((integer)sizeof(...))` in `codegen_common_sizeof_expr` (headers and `-C`).
- Follows the unit’s `integer` typedef (default `int`; rebind applies when that typedef is in scope).
- **`LEN`** not emitted yet — same type and cast when implemented.
- Design lock (not implemented as a hard mix-ban yet): lengths / indexes / `SIZEOF` / `LEN` are **signed** (`integer`); `cardinal` is for bits / wrap / C unsigned ABI; `size_t` stays an imported C name.

### Lean generated C prelude **Done** (partial; `<stddef.h>` stays until 0.26)

Automatic includes: `<stddef.h>` (`NULL`, `size_t`), `<stdint.h>` (`uint8_t`), `<stdbool.h>`, `<assert.h>`.  
`typedef uint8_t byte;` — `#define nil NULL` / `#define NIL NULL`.  
Portable four typedefs unchanged. **No** automatic `<stdlib.h>` / `<stdio.h>` / `<string.h>` / `<math.h>` / `<limits.h>` / `<float.h>`. `exit` and friends must be imported. Tests, examples, and `src/*.mc` updated.

**Verification:** `make test-all`, **selfhost**, **bootstrap** green on **gcc**, **clang**, and **tcc**. Promoted **0.25.4.154**.

~~**0.26:** drop `<stddef.h>` / require every non-builtin name~~ — **Done (0.26.0–0.26.1)**. Next: `.mh` field lists.

## Recent Accomplishments (12 August 2026 — 0.25.3.150 / 7a module-entry bind)

### Item **7a** — Module entry as a real symbol **Done**

- **Same-unit:** `MODULE` name is registered as `PROC`/`FUNC` after pass 1; `sym.decl` is a synthetic `NODE_PROC_DECL` / `NODE_FUNC_DECL` whose `PARAM_LIST` aliases `program_decl.params` so existing auto-`&` applies (`test_module_ref(b, 1)` needs no `@`).
- **Import:** any **named** import from an `.mh` also binds the `@module` unit-entry export (skip if already in scope or no matching export; include-only `import from "x.mh"` unchanged). `PROGRAM` names are not bound.
- **Names:** `.mh` strings are arena-copied in `semantic_bind_mh_export` before `mh_module_free` (auto-bound constructor names must not dangle).
- **Callee ABI (same arc):** module/program `emit_param_list(..., true)` so `VAR`/`REF` formals lower to `T*` (Lexer `module Lexer(ref lexer: TLexer, …)`).
- **Tests:** `tests/test_module_ref.mc`; `tests/test_module_entry.mc` + `tests/fixtures/bumpint.mh` / `include/fixtures/bumpint.h` (`import TBump` only; `bumpint(n)` auto-bound + auto-`&`). **make test** green on **gcc**, **clang**, **tcc**.
- **Not 7b** — no generated startup calls of imported module bodies. **7b cancelled** 31 August 2026 (explicit 7a calls only).

## Recent Accomplishments (11 August 2026 — 0.25.3 / formal signatures + cross-module auto-`&`)

### Item **6a** — `.mh` formal signatures **Done**

- **Writer (`codegen_mh`):** one-line `@format 1` tails — `( [var|ref|const] type-spec { , … } ) [ : result ]`; surface type names preferred (aliases like `long_long`); multi-word C spellings only when written that way.
- **Reader (`mh_reader`):** `MhFormal` / `has_signature` / result fields; multi-word type-spec (`long long`, `unsigned int`); free formals on unload.
- **Import (`semantic`):** synthetic `NODE_PROC_DECL` / `NODE_FUNC_DECL` + param list from export (arena-copied strings); `sym.decl` is the synthetic node so existing codegen auto-`&` applies cross-module.
- **Phase A (0.25.2) retained:** `instance`/`static` Owner; `import Type::name`; `is_method_instance`; `obj.method` across modules.
- **Tests:** `tests/test5_mh_method_import_string.mc` (`-a`); `tests/test4_string.mc` + **`make string-lib`** (link `libtmod_string.a`); auto-`&` on `sb.free()` / `TStringBuffer::free(sb)` without `@`. Not wired into default `make test` (needs `include/*.mh` + archive).
- **Then still deferred:** field lists / complete struct export; field call-through across modules; **7b** (later **cancelled**); `^T` instance receivers. Field lists / call-through **Done** 0.26.3–0.26.4.

## Recent Accomplishments (11 August 2026 — 0.25.2 / cross-module methods Phase A)

### Cross-module `Type::method` / `obj.method` **Done (Phase A)**

- **`.mh` writer (A1):** type-bound exports emit optional `instance Owner` / `static Owner` after completeness (still `@format 1`).
- **`.mh` reader (A2):** `MhExport` stores `is_method`, `is_instance`, `method_owner` / `method_owner_len`.
- **Import (A3):** `import-item` may be `Type::name` (or mangled `Type__name`); lookup mangled export; bind mangled name (or `AS` alias); set `TSymbol.is_method_instance`.
- **Semantic (A4):** `obj.method(...)` treats `sym.is_method_instance` like same-unit instance methods.
- **Module entries** (`String(...)`, `StringBuffer()`): ~~free-call soft-miss~~ — **7a Done (12 August)**.
- Superseded for formals by **0.25.3** (above).

## Recent Accomplishments (7 August 2026 — 0.25.1 / callable fields)

### Callable field call-through **Done**

- **`obj.field(args)`** when `field` has a **method type** (`TYPE T = PROCEDURE/FUNCTION …`) → C `(obj.field)(args)`; **no** auto-receiver (Oberon procedure variables).
- **Disambiguation:** instance `Type::name` vs method-typed field — if both apply, **compile-time error** (use `Type::name(obj, …)`).
- **Locals / params:** `fp(args)` when `fp` is `VAR` / `PARAM` / `LET` (or `CONST`) of method type.
- **AST / codegen:** `call.callee_expr` for call-through; instance sugar still uses `receiver_expr` prepend.
- **Semantic:** `semantic_method_type_node`, `semantic_field_type_on`, `semantic_sym_is_method_value`; `semantic_resolve_call` reclassifies dot-calls.
- Tests: `tests/test_callable_field.mc`, `tests/test3_callable_field_ambig.mc` (as applicable); **`tests/test_Math.mc`** — struct “object” with method-typed fields + `Type::create` / module entry as factory (compile-time only; no vtables).
- **make test-all**, selfhost / bootstrap / promote as verified by user; **gcc** / **clang** / **tcc** green.
- Still deferred: parent-chain method lookup; `^T` / `VAR` self auto-`&` on instance methods.

## Recent Accomplishments (6 August 2026 — 0.25.0 / item 20)

### Item 20 — VAR / REF / CONST formals **Done (breaking)**

- **Only `VAR`** may use the bare formal name as LHS of `:=` / `INC` / `DEC`.
- **`REF`:** through-designator writes OK (`p.x`, `a[i]`); bare-name assign **illegal** (scalar `REF n: integer` is effectively read-only for updates).
- **`CONST`:** deep freeze — no write through the formal root (name, fields, indices).
- **Bare formals:** no bare-name assign; still largely by-value in C (not full Oberon “default REF”).
- **Codegen:** non-pointer `VAR`/`REF` → `T*`; `REF ^T` → one `*`; `VAR ^T` → `T**`; call-site auto-`&` for by-ref value formals (`Swap(x, y)`).
- **Self-host:** scratch mutation of non-`VAR` formals uses locals (`arena` / `semantic` / `utils`, etc.).
- Tests: `test_var_ref`, `test_var_pointer`, `test_const_param`, `test3_var_ref*`, `test3_const_param*`, `test3_var_pointer*`; **make test-all**, **selfhost**, **bootstrap**, **promote** green.
- Soft spot: named open-array typedef as `REF`/`VAR` formal (prefer true open-array type-specifiers until alias chase).
- Docs: Language Report §8.2; `docs/grok_report-20260806-2042.md`.

## Recent Accomplishments (6 August 2026 — 0.24.18 / #11 Phase A)

### Item #11 Phase A — portable builtin unit rebind **Done**

- Only the four Wirth-family names may be **bound once per compilation unit** via top-level `TYPE`: **`integer`**, **`cardinal`**, **`real`**, **`string`**.
- Unbound defaults in generated C: `int`, `unsigned int`, **`float`**, `const char *` (portable names remain the typedef *aliases*; C names are not rebindable prelude slots).
- `type_is_portable_rebindable`; semantic first-bind refines prelude (`decl == nil`); second bind and rebind of fixed builtins (`bool` / `byte` / `char` / C-ish prelude names) are errors.
- Codegen skips the default `typedef` for a portable name when the unit supplies a complete `TYPE` binding.
- Tests: `tests/test_rebind.mc`, `tests/test3_rebind_second.mc`, `tests/test3_rebind_bool.mc`; suite green.
- **Width forms Done (0.26.5).** **Import-as-bind and `.mh` width tails Done (0.26.5.174).** **Still open (same item #11):** architecture packs (`tmodc.lp64`, …); compiler-build default selection; optional `.mh` alias RHS.

### `type Name FORWARD` (0.24.17.135) **Done**

- Incomplete type in-unit: `type TString forward` then complete with `type TString = …`.
- Completes prior incomplete TYPE via symtab refine (same family as proc postfix `FORWARD`).
- Codegen: incomplete tag/typedef as needed; method-type typedefs ordered after layout types where required for C.
- Tests: `tests/test_type_forward.mc`, `tests/test3_type_forward_dup.mc`, `tests/test3_type_forward_reforward.mc` (as applicable).

## Recent Accomplishments (3 August 2026 — 0.24.17 / item 21)

### Item 21 — `obj.method` + instance vs static **Done**

- **Instance sugar:** `obj.method(args)` → `Type__method(obj, args…)` when static type of `obj` is `Type` and the method is an **instance** method.
- **Always available:** `Type::method(args…)` (Phase 1 since 0.23.9).
- **Instance vs static** (first formal type only; formal name free, Oberon-style):
  - **Instance:** first formal’s type is the owner type → `Type::m(obj, …)` and `obj.m(…)`.
  - **Static / factory:** no formals, or first formal type ≠ owner → **`Type::m(…)` only** (e.g. `Point::new(x, y)`; `p.new(…)` is an error).
- **Statement path:** designator + postfix chain (calls, `.`, `[]`, `^`) so `p.print()` and `b.topLeft().print()` work as statements.
- **Optional `end` tags:** `end`, `end name`, `end Type::name` (`parse_optional_end_tag` in `parse_block`).
- Helper: `semantic_method_is_instance`; codegen prepends `receiver_expr`.
- Tests: `tests/test_smoke.mc`, `tests/test3_smoke.mc` (static via `.` fails); **make test-all** green on **gcc**, **clang**, **tcc**.
- ~~Callable field call-through~~ — **Done (0.25.1)**. Still deferred: parent-chain method lookup; `^T` / `VAR` self auto-`&`.

## Recent Accomplishments (1 August 2026 — 0.24.16 / auto-upcast)

### EXTENDS by-value auto-upcast **Done**

- Child (or further descendant) used where an ancestor is required → C **`.base` × N** (option A); not a blind struct cast.
- `Node.upcast_depth`; `semantic_extends_upcast_depth` / `semantic_maybe_upcast`; sites: typed init, `:=`, `RETURN` (`enclosing_func`), same-unit call formals.
- Codegen: `codegen_common_expr` appends `.base` after the expression when depth &gt; 0.
- Multi-level verified (e.g. `Grand` → `Parent` = two `.base` steps). Tests: `tests/test_extends.mc`.
- **Deferred polish (1 August):** pointer/`REF` upcast; aggregate `as` → `.base`; `^T` parent fields (`c5^.x`). **Closed 0.26.5.175.** Oberon `p.x` auto-deref **Closed 0.26.5.176.** `p[i]` peel and instance method on `^T` **Closed 0.26.5.178.** Still later: parent-chain methods; cross-module formals (richer `.mh`); hard assignability errors.
- **Design lock:** no compiler-inserted type tags / vtables; programmer may add tags manually (enum+union style). No Oberon `IS` without opt-in runtime identity later.

## Recent Accomplishments (31 July 2026 — 0.24.16 / declaration self-host)

### Self-host: `declaration.c` → `declaration.mc` **Done**

- Converted declaration parsing to **`src/declaration.mc`**; generated **`declaration.c`** (and paired header / `.mh` as in the build).
- Hand-authored **`declaration.c`** replaced by compiler output from the `.mc` source.
- Conversion cleanup: stale comments removed; most obsolete **receiver** parse path dropped (type-qualified methods own that story).
- Version **0.24.16 (build 130)**; **make test-all** green on **gcc**, **clang**, and **tcc**.

## Recent Accomplishments (29 July 2026 — 0.24.15 / 13b)

### Item 13b — discard enforcement (Policy A) **Done**

- Bare `NODE_CALL` as `NODE_EXPR_STMT`: if `semantic_type_of_expr` yields a **known** result type → fatal; require `(f())` or use the value (`x := f()`, arg, …).
- **Unknown** result (procedure, untyped foreign import such as bare `printf`) → bare call still allowed.
- Explicit discard: `(expression)` / `(f())` (`NODE_PAREN`) always allowed as a statement.
- Tests: `tests/test_discard.mc`, `tests/test3_discard.mc`; **make test-all** green on **gcc**, **clang**, and **tcc**.
- Optional later: discard binding `_` (item **24**); thin wrapper procedures if an API later gains a known result and callers never care.

## Recent Accomplishments (29 July 2026 — 0.24.14 / 21a)

### Item 21a — `type_of_expr` + simple init inference **Done**

- **`semantic_type_of_expr`** — thin expression typing (not full type-check / not Hindley–Milner).
- Coverage: literals; designators; paren; cast; sizeof; call return type; unary `-` / `not` / `~` / `@` / `^`; binary arith / bitwise / logical / compare; real arith.
- **Init inference** — when `:` is omitted on `VAR` / `LET` / `CONST`, type from initializer; error if unknown.
- Tests: `tests/test_infer.mc` (and related); suite green.
- **Deferred polish:** ternary `cond ? a : b` (and array-literal) typing — item **21a-ternary** (both arms must share one static type).
- Unlocked: ~~**13b** discard~~ **Done (0.24.15)**; still open: EXTENDS auto-upcast, **21** `obj.method`, **20** `VAR` formals.

### Design (same period)

- Portable builtins Option A locked in Language Report §5.5 / §10.1 (not implemented).

## Recent Accomplishments (28 July 2026 — 0.24.14)

### Self-host: `lexer.c` → `Lexer.mc` **Done**

### Self-host: `lexer.c` → `Lexer.mc` **Done**

- Converted the full tokenizer to **`src/Lexer.mc`** (module `Lexer`); generated **`Lexer.c` / `Lexer.h` / `Lexer.mh`**.
- Hand-written **`lexer.c` / `lexer.h`** replaced; capital **`Lexer`** module name matches self-host naming for large units.
- Exports include **`TokenKind`** enum, **`TToken` / `TLexer`**, **`TLexer::init` / `TLexer::next`**, **`TokenKind::string`**, **`TToken::print`**.
- Keyword table includes **`OPAQUE`** (spelling fixed vs older `OPQAUE` typo note).
- Version **0.24.14 (build 125)**; self-host / bootstrap path exercises the lexer as TMod-c source.

### Related (same period — exploratory, not calm-path)

- Experimental **`src/String.mc`** — `TString` wrapper for const C strings; documents deferred **`type … forward`**, callable fields, and future **`obj.method`** / builtin **`string`** direction.
- Discussed: callable function-pointer fields vs **`Type::method`** / planned **`obj.method`** (item **21** after **21a**); neither call path fully enables vtable-style dispatch yet.

## Recent Accomplishments (25 July 2026 — 0.24.13)

### Item 13d — `STRUCT EXTENDS` option A **Done**

- Oberon model: unique field names on the extension chain; flat `c.x` in TMod-c source.
- C option A: embed `Parent base` at offset 0; field rewrite via `field_access.base_depth` → emit `.base` × depth.
- Synthetic `base` for explicit parent value (`c.base`); **reserved only on types that use `EXTENDS`** (plain structs may use a field named `base`).
- Semantic: `semantic_find_field_depth`, `semantic_type_of_designator` (designator-only), clash / base-must-be-struct checks.
- Tests: `tests/test_extends.mc` (multi-level + `c.base`); `test3_extends_clash.mc`; `test3_extends_base_reserved.mc`; existing `test2_extends.mc`.
- Auto-upcast child → parent still deferred (needs **21a**).

### Infrastructure — linked-chunk arena **Done**

- Replaced single-slab `realloc` growth (ASan UAF when analyzing large units such as `semantic.mc` with `-a`).
- `ArenaChunk` list: never relocate live slabs; `arena_alloc` zeros returned bytes; `calloc` for new chunks; `ARENA_MIN_SIZE` = 1 MiB default.
- Stress-tested with small min size (multi-chunk creates); production min restored to 1 MiB.

## Recent Accomplishments (23 July 2026 — 0.24.12)

### Item 13c — bare `UNION` types **Done**

- `type Value = union … end` on TYPE RHS (sibling of `STRUCT`).
- Lexer `TOK_KEYWORD_UNION`; `struct_decl.is_union`; `parse_union_type`; no `EXTENDS` / no `PACKED` in v1.
- Semantic resolves field types; rejects `EXTENDS` on unions.
- Codegen: **`codegen_common_union_decl`** → C `union` (separate from struct emitter for consistency).
- Nested use: define named type first, then field type = name (no anonymous nested unions yet).
- Tests: `tests/test_union.mc`, `tests/test3_union.mc` (and related); full suite green on gcc, clang, tcc.

### Item 13a — `OPAQUE` types **Done** (0.24.11.x)

- End-to-end: `type T = opaque`, `^opaque`, `POINTER TO opaque`; C `typedef void *Name`.
- Bare `opaque` in type-specifier rejected (`test3_opaque_parse.mc`).
- Note: unknown type *names* still allowed as possible foreign C types (pre-existing policy).

### Design discussion (future — not implemented)

- Language-level **tagged unions** / ADTs (constructors + match/`is`) explored as pseudocode; distinct from bare `UNION`. Manual pattern remains: enum tag + struct + union (as in compiler `Node`).
- Embed of struct/union in another: name the nested type first, then use as field type.

## Recent Accomplishments (0.24.11 — `expression.mc`)

### Self-host: `expression.c` → `expression.mc`

- Converted **`src/expression.mc`**; compiles; all tests run; promoted through 0.24.11.x builds.

## Recent Accomplishments (18 July 2026 — design + self-host)

### Self-host: `statement.c` → `statement.mc` (0.24.10.110)

- Converted **`src/statement.mc`** (paired `.c` / `.h` / `.mh` as needed).
- Full rebuild, test suite, self-host, bootstrap, and promote — **green** at **0.24.10.110**.

### Design — no user-facing `void`; `OPAQUE` types

- Prefer **procedure vs function** (no result type) over a void return type.
- **`type T = opaque`** — named type with no language-visible layout (Wirth-style; Windows-style handles as user-chosen names).
- **`type address = ^opaque`** (or `POINTER TO opaque`) — C `void *` equivalent via **user-defined** alias, not a baked-in `void`.
- **`OPAQUE` only on TYPE RHS** (`opaque-type-expression`); not in `type-specifier` (`var x: opaque` illegal — name first).
- Distinct from **`type T FORWARD`** (incomplete, completed later in-unit) and from **`.mh`** completeness flag `export type name opaque`.
- Reserved keyword **`OPAQUE`** replaces **`OBJECT`** (Language Report + `syntax-ebnf.md`).

### Design — explicit discard of function results **Implemented (0.24.15 / 13b Policy A)**

- Grammar: **`expr-statement = "(" expression ")"`** — intentional drop of a result.
- **Policy A:** bare call as statement illegal when result type is **known**; require `(f())` or use the value. Unknown result / procedure → bare OK.
- C source / generated C may use **`(void) call(...)`**; TMod-c source uses parentheses, not a cast-to-void type.
- Item **24** (`_`) still deferred — distinct sugar from `(f())`.

### Grammar + lexer groundwork

- **`docs/language-report.md`** + **`docs/syntax-ebnf.md`** — SSOT split (18 July 2026); `OPAQUE` in report + EBNF; former `grammar.md` archived as `grammar_working_notes.md`.
- **`TOK_KEYWORD_OPAQUE`** — keyword table now lives in **`src/Lexer.mc`** (self-hosted 0.24.14); spelling is **`OPAQUE`**.

### Prior same line (0.24.9)

- **`symkind.h` → `symkind.mc`**, **`mh_exportkind.h` → `mh_exportkind.mc`**.

## Recent Accomplishments (16 July 2026 — 0.24.8)

### Named `CONST` in array bounds

- **`array[LIMIT] of T`** and **`array[LIMIT+1] of T`** when `LIMIT` is a compile-time integer `CONST` (and general integer const-exprs).
- **`TType.size_expr`** — parser stores unevaluated bound; semantic folds to `array_size` in place before codegen (`char l[100]`, not open `l[]`).
- **`type_create_array_expr`**; parser paths for `array[…] of T` and suffix `T[…]`.

### Integer const-eval (shared)

- **`semantic_try_eval_const_expr`** — soft fold; optional `msg` out-parameter for distinct errors; `nil` msg for quiet non-integer `CONST`.
- **`semantic_eval_const_expr`** — thin fatal wrapper over try (single implementation).
- **`CONST` registration** — `has_const_value` only when integer fold succeeds; string/pointer `CONST` (e.g. `const c2: ^char = "bye"`) unchanged.
- **`TOK_MOD` / `TOK_KEYWORD_MOD`** both accepted in const-exprs.
- Review fixes: fallback error message when hard eval fails without msg; `semantic_register_var_decl` error string.

### Release process

- Version **0.24.8.104**; rebuilt, tested, self-hosted, bootstrapped, and promoted.

## Recent Accomplishments (15 July 2026 — 0.24.7)

### ENUM Phase C

- **`MH_KIND_ENUM`** in `mh_exportkind.h`; `.mh` writer emits `export enum Type complete` plus `export const Member complete` lines per member.
- **`mh_reader`** parses `export enum`; maps to `SYM_KIND_TYPE`; cross-module enum import via explicit item list.
- **Tests:** `tests/test_mh_enum_export.mc`, `tests/test2_mh_enum_import.mc`, `tests/test_mh_enum_import.mc`; fixtures `tests/fixtures/colors.{mh,h}`.

### `.mh` negative import tests

- Tier-3 **`test3_*`** convention: each `tests/test3_*.mc` runs through `modc -a`; **non-zero exit = pass**.

### Test include paths (Makefile)

- **`INCLUDE_DIR`** (`include/`) with `include/fixtures` → `tests/fixtures/` symlink; **`CFLAGS`** adds `-I$(SRC_DIR) -I$(INCLUDE_DIR) -I$(LIB_DIR)` so generated `#include "fixtures/…"` and experimental `tmodc.h` resolve in tier-1 host C builds. Test-harness aid — not a substitute for item 15 (subdir compilation). Host compiler is **`CC`** (default gcc; `CC=clang` / `CC=tcc`).

### Design — `WHILE … BY` not planned

- Iteration step at loop head via **`defer`** (see `tests/test_defer.mc`); documented in `docs/grammar.md`.

## Recent Accomplishments (14 July 2026 — 0.24.6)

### ENUM Phase A/B

- **`TYPE name = ENUM … END`** — parse (`parse_enum_type`), semantic (`semantic_register_enum_type`, `semantic_eval_const_expr`), codegen (`codegen_common_enum_type` → C `typedef enum`).
- **`TSymbol.const_value`** for enum member integers; duplicate-member error.
- **Tests:** `tests/test2_enum_parse.mc`, `tests/test_enum.mc`, `tests/test3_enum_dup.mc`.
- Phase C completed in **0.24.7** (see above).

### `tmodc` ABI prelude (planned)

- Experimental **`src/tmodc.h`** for hand-written C including generated headers.
- Target: **`tmodc.mc` → `tmodc.h`** system module (width types, `nil`); multi-TU `#include` instead of inlined prelude.

### TMod-c rebrand (documentation)

- Public project/language name: **TMod-c** (TYPE compiler; Pascal `T` prefix alignment).
- Target compiler binary: **`tmodc`**; **Mod-c** / **`modc`** retained as legacy aliases during transition.
- **Docs:** `docs/grammar.md`, `CURRENT.md`, `changelog.md`, `AGENTS.md`, `docs/grok_report-20260714-1939.md`; append `docs/project_bible.md`.

## Recent Accomplishments (13 July 2026 — 0.24.5)

### Qualident `IMPORT … FROM`

- **`import-source = string-literal | qualident`** — parser, semantic, and codegen.
- **Unquoted qualident** names a Mod-c module: dots → slashes, `.mh` for symtab, paired `.h` for `#include`.
- **Quoted string** unchanged for foreign/C and explicit `"path.mh"` paths.
- **Path resolution:** relative to compiling `.mc` file directory (project-root `src/` search paths still deferred).
- **`mh_reader`:** `mh_qualident_to_mh_relpath`, `mh_format_h_include`; updated `mh_path_is_mh`, `mh_resolve_import_path`.
- **Tests:** `tests/test2_mh_import_qual.mc` (qualident form of `fixtures.minimod`).
- **`docs/grammar.md`** updated (0.24.5).

## Recent Accomplishments (11 July 2026 — 0.24.4)

### `codegen_header.mc` (self-host)

- **`src/codegen_header.mc`** — converted from `.c`; behaviour unchanged (minor release **0.24.4**, not 0.25).

## Recent Accomplishments (9–10 July 2026 — 0.24.3)

### Import sources — documented (phase 1 vs phase 2)

- **`IMPORT FROM "path"`** — include-only form in grammar (optional empty item list); not `IMPORT *`.
- **Two worlds:** quoted string = foreign/C; unquoted **qualident** = Mod-c module (`utils.dynbuf` → `utils/dynbuf.mh` + `#include "utils/dynbuf.h"`). *Qualident `FROM` implemented 0.24.5.*
- **Quoted paths** still valid for foreign/C and explicit `"codegen_header.mh"` spelling.
- **Still deferred:** project-`src/`-root paths, `import * from M.N` bulk `.mh` import; blocked until subdirectory compilation in Makefiles.
- **Policy:** paths and identifiers **case-sensitive**; generated C **`#include`s `.h` only**, never `.mh`.
- **`docs/grammar.md`** — full *Phase 1* / *Phase 2* import section.

### EOS / layout (expressions, statements, RETURN)

- **`parse_unary`** — `skip_layout_breaks` at entry; trailing operators (`or`, `and`, `+`, …) may continue on the next line.
- **`consume`** — calls `skip_layout_breaks` before matching; **`match`** unchanged (EOS / `matchEOS` must see `NEWLINE` as-is).
- **`RETURN`** — newline after bare `return` **ends** the statement; multiline return **values** use `(...)`. No layout skip before optional expression (avoids swallowing the next statement).
- **Unreachable code** — statements after `RETURN` / `BREAK` / `CONTINUE` in the same sequence → **fatal error** (was warning); dead nodes still excluded from AST.
- **Tests:** `tests/test_layout.mc` (tier-1 smoke); `tests/test3_loop.mc` (tier-3: unreachable after `break`/`continue`).

## Prior — 0.24.3 (9 July 2026)

### Builtin `integer` / `cardinal` lowering

- **`integer`** lowers to C **`int`**; **`cardinal`** to **`unsigned int`** (Oberon-like everyday types on typical LP64 targets — **not** pointer-sized).
- Changed in **`codegen_c`** prelude typedefs; verified with **`make test-all`** on gcc, clang, and tcc (no new errors/warnings).
- **`printf`:** `%d` / `%u` match Mod-c `integer` / `cardinal` on LP64. For `size_t` or pointer-sized values, use C imports or future width-qualified types.
- **`docs/grammar.md`** updated (0.24.3): builtin policy, generated width typedefs (`int8`…`uint64`), EOS rules.

### Parser / layout (9 July — import/decl)

- **End-of-statement rules** documented; **`IMPORT … FROM`** anchor layout; `skip_layout_breaks` for multi-line import/declaration lists.
- **`tests/test_import_layout.mc`** — multi-line `import` / `var` layout smoke test.

## Prior — 0.24.2 infrastructure (9 July 2026)

### Three-tier test targets (gcc / clang / tcc)

- **`test`** — `test_*`: modc compile → host C compile → run; stdout to `/dev/null`; summary `N run, M failed`; includes `test_Pi` diff check.
- **`test2`** — `test2_*`: `modc -a` semantic pass expected; counted summary.
- **`test3`** — `test3_*`: negative tests — **non-zero exit = pass**; counted summary.
- **`test-all`** — runs all three tiers; **`dist`** depends on `test-all`.
- **Then (0.24.2):** three files (`Makefile`, `Makefile.clang`, `Makefile.tcc`). **Now (31 August 2026):** one **`Makefile`**, `CC=gcc|clang|tcc`; old files in **`archive/`**.

### Negative test fixtures (`test3_*`)

- `tests/test3_dup.mc` — duplicate declaration
- `tests/test3_undef.mc` — undefined identifier
- `tests/test3_for_assign.mc` — invalid `for` assignment
- `tests/test3_let_over_var.mc` — `let` over `var` conflict
- `tests/test3_loop.mc` — unreachable code after `break` / `continue`

### Version / build numbering

- **`make version`** — manual only; increments `src/build.number` and regenerates `src/version.h`.
- **`BUILD_NUMBER`** stored in **`src/build.number`** (survives `make clean`, which removes `bin/` and `build/`).
- Modc displays **`0.24.12 (118)`** style (release stem + build in parentheses); generated headers use **`VERSION_BASE`** only.

### Project housekeeping

- **`AGENTS.md`** refreshed at repo root (canonical agent instructions); duplicate `.grok/AGENTS.md` removed.

## Prior Release — 0.24.0 (7 July 2026)

### `.mh` module linking — items 7–8

Cross-module Mod-c imports work end-to-end: `EXPORT` emits `modc-mh/1` tables; `IMPORT … FROM "*.mh"` loads them at semantic analysis; generated C `#include`s the associated `.h`.

- **Writer:** `src/codegen_mh.mc` — `TARGET_MH`, `-M`, auto-emit with `-C`.
- **Reader:** `src/mh_reader.mc` — parse `modc-mh/1`; `semantic_register_import` loads real symbol kinds from `.mh`.
- **Codegen:** `codegen_common_import` — `.mh` imports emit `#include "…h"`.
- **Semantic fix:** `NODE_IMPORT_ITEM` branch in `semantic_resolve_type_inner` for `.mh` type imports.
- **Module entry:** `mh_emit_unit_entry()` emits `module` proc/func in `.mh` export table.
- Tests: `test_mh_export.mc`, `test2_mh_import.mc`, `fixtures/minimod.{mh,h}`.

Self-host in progress: `src/*.mc` modules import from corresponding `.mh` files.

## Design Decisions (still in force)

See **`docs/language-report.md`** (prose) and **`docs/syntax-ebnf.md`** (full EBNF). Filenames use hyphens (no `_`; `syntax-ebnf.md` not `syntax.ebnf.md`). Former monolithic `docs/grammar.md` is a redirect; archive in `docs/grammar_working_notes.md`. Highlights:

- **`.mh` / `.h` split** — `.mh` for modc semantics (export table); `.h` for C ABI (`#include` in generated C). Same stem/path layout rule.
- **Import sources** — quoted `"stdio.h"` / `"symbols/foo.h"` = foreign; unquoted qualident (`symtab`, `fixtures.minimod`, `codegen.codegen_header`) = Mod-c module (0.24.5). Resolution relative to compiling unit directory; project-root `src/` search paths deferred. `import from "…"` / `import from M.N` = include-only, no symtab. `import * from …` = bulk `.mh` import (deferred).
- **`EXTERN`** — prefix only; never a body in this unit; refines `IMPORT`.
- **`FORWARD`** — postfix on proc/func; **`type ident FORWARD`** incomplete types **Done (0.24.17.135)** (complete later in the same unit).
- **Blocks** — `extern … end` / `forward … end` deferred until `.mh` shape stabilizes.
- **`CONST` declarations** — compile-time named constants (Pascal/Oberon); not C read-only objects. **`LET`** — runtime immutable binding. Parameter **`CONST`** — deep read-only qualifier, not compile-time `CONST`.
- **`CONST` codegen (today vs intent)** — still lowers to C `static const` objects; intent is `enum` / `#define` / literal fold (item 19). Integer **values** now fold for array bounds via `has_const_value` (0.24.8).
- **No user-facing `void`** — **`OPAQUE` implemented (13a):** TYPE RHS only; user aliases; C `typedef void *Name`; procedures have no result type.
- **Discard (13b Policy A — Done 0.24.15)** — `(expression)` as statement; bare call only when result type unknown; known results require `(f())` or use. C may lower with `(void)`.
- **`OPAQUE` vs `.mh` `opaque`** — source type constructor vs export completeness flag (same word, different grammars).
- **`STRUCT EXTENDS`** — Oberon-shaped record **layout** (single base at offset 0, unique field names, flat `c.x` in source); C lowering **option A** (`Parent base;`, emit `c.base.x` for parent fields). Synthetic `base` reserved **only on EXTENDS** types. Not class/vtable; **no hidden RTTI**. See Language Report §5.4.0. **13d Done (0.24.13)**; **by-value auto-upcast Done (0.24.16)**; **`p^.x` / `as` → `.base` / pointer·`REF` upcast Done (0.26.5.175)**; **Oberon `p.x` auto-deref Done (0.26.5.176)**; **`p[i]` peel + instance on `^T` Done (0.26.5.178)**; **`Type::m(p)` peel Done (0.26.5.179)**. Still open: parent-chain methods.
- **`type_of_expr` / init inference (21a)** — **Done (0.24.14)**. Ternary/`? :` typing deferred (**21a-ternary**).
- **Bare `UNION`** — C overlapping members; `codegen_common_union_decl`; no EXTENDS; not language-level tagged unions. Embed nested aggregates by naming a type first, then using it as a field type.
- **Arena** — linked chunks (pointer-stable); no whole-buffer `realloc` of live AST/symtab storage.
- **Portable builtins (Option A — Phase A Done 0.24.18; widths Done 0.26.5; import-bind / `.mh` widths Done 0.26.5.174)** — Only `integer`, `cardinal`, `real`, `string` may be **bound once per compilation unit** via top-level `TYPE` **or** a named `.mh` import of that name. Unbound → defaults `int` / `unsigned int` / `float` / `const char *`. Width forms **`integer N` / `cardinal N` / `real N`** are exact, RHS-only constructors (closed *N*); `.mh` type-spec may carry the same tail. **Still open:** arch packs; build-time defaults. Not C rank. See Language Report §5.5 / §10.1.
- **`RECURSIVE` (0.25.4)** — required on a **direct** self-call (same PROC/FUNC node as `enclosing_func`). Review/lint flag for JPL rule 1; mutual recursion not checked.
- **`SIZEOF` (0.25.4)** — TMod-c type `integer`; C emit `((integer)sizeof(...))`. Not C `size_t`.
- **Generated C prelude (0.26.1 / 0.26.5)** — `<stdint.h>` `<stdbool.h>` `<assert.h>` only; `byte` = `uint8_t`; `#define nil ((void *)0)` / `#define NIL nil`. No automatic `<stddef.h>`. **0.26.5:** prelude and unit prototype live in the generated `.h`; `.c` includes `"Unit.h"`; `-C` writes a companion `.h`.
- **Name soft-miss** — **closed.** Calls **0.26.0**; types **0.26.1**.
- **Cyclic TMod-c `IMPORT` (later)** — known from parser split (0.26.3). Address after **item 15**. See Language Report §3.2.
- **Identifiers ≤ 255 (0.26.3.170)** — lexer / `.mh` error if longer. Mangled `Owner__name` may be 512. See Language Report §2.2.
- **`.mh` type layouts (0.26.3.170 / 0.26.4 / 0.26.5.174)** — one physical line; field tail on `complete struct`/`union` / `extends`; method-type `complete function|procedure ( … ) [ : T ]`; type-spec may be `integer N` / `cardinal N` / `real N`; whole-file reader; `DynBuf` writer; synthetic struct / `NODE_METHOD_TYPE` on import. See Language Report §3.2.

## TODO / Next Actions

**`IMPORT` / `EXPORT` / `.mh` polish**

1. ~~Items 1–4 semantics phase 2 core.~~ **Done (0.23.3–0.23.5)**
2. ~~Item 5 — `sizeof(UserType)` at parse time.~~ **Done (0.23.7)**
3. ~~Item 6 — `EXTERN TYPE | VAR | PROCEDURE | FUNCTION`.~~ **Done (0.23.7)**
4. ~~Item 7 — `.mh` writer on `EXPORT`.~~ **Done (0.24.0)**
5. ~~Item 8 — `.mh` reader on `IMPORT … FROM "*.mh"`.~~ **Done (0.24.0)**
6. `.mh` completeness / signature richness; method export coverage. ~~Negative import tests.~~ **Done (0.24.7)** — `test3_*` tier. ~~**Method instance/static + `import Type::name` + cross-module `obj.method` (Phase A)**~~ — **Done (0.25.2)**. ~~**Formal signatures + cross-module auto-`&` (6a)**~~ — **Done (0.25.3)**.
6a. ~~**`.mh` formal signatures**~~ — **Done (0.25.3)**. ~~**Type field lists / cross-module `obj.field`**~~ — **Done (0.26.3.170)**. ~~**Method-type RHS / field call-through**~~ — **Done (0.26.4.172)** — `complete function|procedure ( … ) [ : T ]`; synthetic `method_type`; import the method type name as well as the struct.
7. ~~Qualident `FROM`.~~ **Done (0.24.5)** — project-root path resolution (after Makefile subdirs); `IMPORT *` bulk import; `IMPORT … AS …` remain.
7a. ~~**Module entry as real import symbol**~~ — **Done (12 August 2026 / 0.25.3.150)** — same-unit `MODULE` name + importer auto-bind of `@module` export; synthetic proc + formals; arena-copied names; module `VAR`/`REF` ABI. Tests `test_module_ref` / `test_module_entry`.
7b. ~~**Module startup initialization**~~ — **Cancelled (31 August 2026).** No generated calls of imported module bodies. Call the 7a-bound entry explicitly. See [7b cancelled](#7b-cancelled--no-startup-auto-init).

**Language (after `.mh` polish or parallel)**

8. `FORWARD … END` / `EXTERN … END` declaration blocks.
9. ~~`type ident FORWARD`~~ — **Done (0.24.17.135)** — incomplete types completed later in-unit.
10. **`LEN`** — resolution done; codegen TBD (same signed `integer` type as `SIZEOF` when emitted). ~~**`SIZEOF` C type**~~ — **Done (0.25.4)** — `((integer)sizeof(...))`.
10b. ~~**`RECURSIVE` on direct self-call**~~ — **Done (0.25.4)** — `test3_recursive`; mutual recursion later.
11. ~~**Unit binding** of bare `integer` / `cardinal` / `real` / `string` (Phase A `TYPE`)~~ — **Done (0.24.18)**. ~~**Width forms** `integer N` / `cardinal N` / `real N`~~ — **Done (0.26.5)**. ~~**Import as the one bind**~~ **Done (0.26.5.174)**. ~~**`.mh` width spelling**~~ **Done (0.26.5.174)**. **Still open:** arch `tmodc.*` packs; build-time default selection; optional `.mh` alias RHS.
12. **`ENUM`** — Phase A/B/C **done** (0.24.6–0.24.7). Tests: `test2_enum_parse.mc`, `test_enum.mc`, `test3_enum_dup.mc`, `test_mh_enum_export.mc`, `test2_mh_enum_import.mc`, `test_mh_enum_import.mc`.
13. ~~**Named constants in array bounds**~~ — **Done (0.24.8)** — `array[LIMIT]` / `array[LIMIT+1]`; integer `CONST` fold; string `CONST` excluded from fold.
13a. ~~**`OPAQUE` types**~~ — **Done (0.24.11)** — TYPE RHS `opaque` / `^opaque` / `POINTER TO opaque`; codegen `void *`; tests incl. negative bare `opaque`.
13b. ~~**Enforce discard form (Policy A)**~~ — **Done (0.24.15)** — known result → `(f())` or use; unknown/procedure bare OK; tests `test_discard` / `test3_discard`; gcc/clang/tcc green.
13c. ~~**`UNION` types**~~ — **Done (0.24.12)** — bare C `union`; `is_union` + `codegen_common_union_decl`; tests `test_union` / `test3_union`; gcc/clang/tcc green.
13d. ~~**`STRUCT EXTENDS` (Oberon layout / option A)**~~ — **Done (0.24.13)** — clashes; `base_depth` rewrite; synthetic `base` (reserved only on EXTENDS); tests `test_extends` / `test3_extends_*`. ~~**By-value auto-upcast**~~ — **Done (0.24.16)** — `upcast_depth`; init / assign / return / same-unit call args; C `.base` × N. ~~**Polish: `p^.x`, `as` → `.base`, pointer/`REF` upcast**~~ — **Done (0.26.5.175)**. ~~**Oberon `p.x` auto-deref**~~ — **Done (0.26.5.176)**. ~~**`p[i]` peel + instance on `^T`**~~ — **Done (0.26.5.178)**. ~~**`Type::m(p)` peel**~~ — **Done (0.26.5.179)**. **Still open:** parent-chain methods.

**Infrastructure**

14. ~~Makefile **`test3`** target — negative semantic tests.~~ **Done (0.24.2)**
15. **Makefile subdirectory compilation** — `src/` tree → `build/`; prerequisite for project-root module search paths.
15a. **Cyclic `IMPORT` policy** — after 15. Candidates later: extract-common (current), interface/implementation split, cycle ban, or interface-only first pass. Not a 0.26.x language change.
16. Codegen: `@` vs `as` precedence.
17. Codegen: struct forward-declare / deferred `p*` typedefs.
18. FOR end temp type from expression types.
19. **Compile-time `CONST` codegen** — still C `static const` objects; intent `#define` / `enum` / literal fold at use sites. *(Integer value fold for bounds done 0.24.8.)*
20. ~~**`VAR` / `REF` / `CONST` formals**~~ — **Done (0.25.0)** — codegen + semantic modes; call-site auto-`&`; **breaking** non-VAR bare-name assign. Soft: named array-alias formals.
20b. ~~**Callable field call-through**~~ — **Done (0.25.1)** — method-typed fields / values; Oberon no auto-self; ambiguity with instance methods; `test_callable_field` / `test_Math`.
21. ~~**Instance methods phase 2**~~ — **Done (0.24.17)** — `obj.method` / chains / statements; instance vs static by first formal type; `test_smoke` / `test3_smoke`; gcc/clang/tcc green.
21a. ~~**`type_of_expr` + simple init inference**~~ — **Done (0.24.14)** — `semantic_type_of_expr`; init when `:` omitted; tests `test_infer.mc`; suite green.
21a-ternary. **Ternary polish (later)** — type `cond ? a : b` when both arms share one static type (and optionally array-literal inits); not required for 21a core.

**Deferred**

22. ~~Type guard selectors (`IS`)~~ — **dropped** (31 August 2026). Range expressions still deferred. `IN` unused as an operator; reserved.
23. Stdlib `BitSet`; `SET OF` unlikely. **Borrowed-buffer / `init_at` API** when stdlib is designed (not `malloc`-only).
24. Discard binding `_` (optional sugar; distinct from `(f())` statement discard).
25. Optional `BOUND` on `WHILE` / `REPEAT` / `LOOP` — [plan](#future-plan-bound-on-while-repeat-loop-jpl-rule-2).
26. Drop keyword `IS` — [plan](#drop-is-no-type-guards).

## Strategic Direction

0. **TMod-c rebrand (in progress)** — documentation and user-facing naming move to **TMod-c** / **`tmodc`** first; code and build artifacts keep **`modc`** aliases until deliberate cutover. **`tmodc` system module** (planned): width types and shared C ABI in `tmodc.mc` → `tmodc.h`; multi-TU generated C `#include`s `tmodc.h`. Language builtins stay in semantic prelude for now. Experimental `src/tmodc.h` exists for hand-written C that includes generated headers.
1. **Self-host with `.mh` imports** — convert remaining `src/*.c` → `.mc` (recent: **`parser_common` / `parser_main`**, **`declaration`**, **`Lexer`**, `expression`, `statement`, `codegen_header`, `symkind`, `mh_exportkind`, …); keep full chain green under `make test-all`.
2. **Polish `.mh` linking** — method Phase A + formals (**6a**) **Done (0.25.2–0.25.3)**; module-entry bind (**7a**) **Done (12 August)**; type field lists **Done (0.26.3.170)**; method-type RHS / field call-through **Done (0.26.4.172)**. ~~**7b**~~ **Cancelled** (explicit module-entry calls only).
3. **Declaration blocks** — `forward`/`extern` groups once `.mh` export shape is stable.
4. ~~Expression types / init inference (21a)~~ **Done.** ~~Discard (**13b** Policy A)~~ **Done.** ~~Instance methods (**21**)~~ **Done.** ~~`VAR` formals (**20**)~~ **Done (0.25.0).** ~~Callable fields~~ **Done (0.25.1).** ~~Cross-module method Phase A~~ **Done (0.25.2).** ~~Formal signatures / cross-module auto-`&`~~ **Done (0.25.3).** ~~Module-entry bind (**7a**)~~ **Done (12 August).** ~~**`RECURSIVE` + signed `SIZEOF` + lean prelude**~~ **Done (0.25.4).** ~~**Free-call soft-miss**~~ **Done (0.26.0).** ~~**Unknown types + drop `stddef.h`**~~ **Done (0.26.1).** ~~**Parser self-host (`parser_common` / `parser_main`)**~~ **Done (0.26.3).** ~~**`.mh` field lists**~~ **Done (0.26.3.170).** ~~**Method-type RHS / field call-through**~~ **Done (0.26.4.172).** ~~**Width forms + `.h` prelude**~~ **Done (0.26.5.173).** ~~**#11 import-bind + `.mh` widths**~~ **Done (0.26.5.174).** ~~**EXTENDS polish (`p^.x` / `as` / pointer·`REF`)**~~ **Done (0.26.5.175).** ~~**Oberon `p.x` auto-deref**~~ **Done (0.26.5.176).** ~~**`p[i]` peel + instance on `^T`**~~ **Done (0.26.5.178).** ~~**`Type::m(p)` peel**~~ **Done (0.26.5.179).** Remaining on this stem: `CONST` codegen; **#11** arch packs / build-time defaults; parent-chain methods.
5. ~~**`OPAQUE` (13a)**~~ … ~~**0.26.5.179 `Type::m(p)` peel**~~ **Done.** Next: **#11** arch packs; **21a-ternary** later. Cyclic `IMPORT` after **item 15**. Later (not 0.26.x): loop-local `FOR`; optional `BOUND`; drop `IS`; `SET OF` enum.

## Useful Commands

```bash
make                              # gcc (default)
make CC=clang                     # clang flags
make CC=tcc                       # tcc flags
make clean && make CC=clang test-all
make clean && make CC=tcc test-all

make test                         # test_* compile + run
make test2                        # test2_* semantic (-a)
make test3                        # test3_* negative (failure = pass)
make test-all                     # all three tiers

make version                      # manual: bump BUILD_NUMBER + src/version.h
make selfhost
make bootstrap
make promote

./bin/modc.0.25.4 tests/test_smoke.mc -C build/test/test_smoke.c
./bin/modc.0.25.4 tests/test_var_ref.mc -C build/test/test_var_ref.c
./bin/modc.0.25.4 tests/test_callable_field.mc -C build/test/test_callable_field.c
./bin/modc.0.25.4 tests/test_Math.mc -C build/test/test_Math.c
./bin/modc.0.25.4 tests/test3_var_ref1.mc -a              # expect non-zero (non-VAR assign)
./bin/modc.0.25.4 tests/test3_smoke.mc -a                 # expect non-zero (static via .)
./bin/modc.0.25.4 tests/test3_callable_field_ambig.mc -a  # expect non-zero (field vs instance)
./bin/modc.0.25.4 tests/test3_recursive.mc -a             # expect non-zero (self-call without RECURSIVE)
./bin/modc.0.25.4 tests/test_method.mc -C build/test/test_method.c
./bin/modc.0.25.4 tests/test_discard.mc -C build/test/test_discard.c
./bin/modc.0.25.4 tests/test3_discard.mc -a              # expect non-zero (tier-3 pass)
./bin/modc.0.25.4 tests/test_opaque.mc -C build/test/test_opaque.c
./bin/modc.0.25.4 -a tests/test5_mh_method_import_string.mc   # cross-module methods (needs include/*.mh)
./bin/modc.0.25.4 tests/test_module_ref.mc -C build/test/test_module_ref.c
./bin/modc.0.25.4 tests/test_module_entry.mc -C build/test/test_module_entry.c
./bin/modc.0.25.4 -a tests/test_mh_enum_import.mc
# make string-lib && link test4_string against -ltmod_string (manual; auto-& on free)
./bin/modc.0.24.17 tests/test_union.mc -C build/test/test_union.c
./bin/modc.0.24.17 tests/test_extends.mc -C build/test/test_extends.c
./bin/modc.0.24.17 tests/test3_extends_clash.mc -a           # expect non-zero (tier-3 pass)
./bin/modc.0.24.17 tests/test3_extends_base_reserved.mc -a # expect non-zero (tier-3 pass)
./bin/modc.0.24.17 tests/test3_opaque_parse.mc -a    # expect non-zero (tier-3 pass)
./bin/modc.0.24.17 tests/test3_union.mc -a           # expect non-zero if negative
./bin/modc.0.24.17 tests/test_mh_export.mc -C build/test/test_mh_export.c -M
./bin/modc.0.24.17 tests/test2_mh_import.mc -C tests/test2_mh_import.c -a
./bin/modc.0.24.17 tests/test_enum.mc -C build/test/test_enum.c
./bin/modc.0.24.17 tests/test_const.mc -C build/test/test_const.c
./bin/modc.0.24.17 tests/test3_enum_dup.mc -a    # expect non-zero (tier-3 pass)
```

## Context & History

- **Latest (4 September 2026 / 0.26.5.179 / `Type::m(p)` peel):** `docs/grok_report-20260904-type-m-peel.md`
- **Prior (4 September 2026 / 0.26.5.178 / `p[i]` + instance on `^T`):** `docs/grok_report-20260904-ptr-index-method.md`
- **Prior (3 September 2026 / 0.26.5.176 / Oberon `p.x` auto-deref):** `docs/grok_report-20260903-auto-deref.md`
- **Prior (2 September 2026 / 0.26.5.175 / EXTENDS polish):** `docs/grok_report-20260902-extends-polish.md`
- **Prior (28 August 2026 / 0.26.5.174 / #11 import-bind + `.mh` widths):** `docs/grok_report-20260828-import-bind.md`
- **Prior (27 August 2026 / 0.26.5.173 / width forms + `.h` prelude):** `docs/grok_report-20260827-1548.md`
- **Prior (26 August 2026 / 0.26.4.172 / method-type `.mh` RHS):** `docs/grok_report-20260826-2130.md`
- **Prior (25 August 2026 / 0.26.3.170 / `.mh` field lists):** `docs/grok_report-20260825-mh-field-lists.md`
- **Prior (24 August 2026 / 0.26.3 / parser self-host):** `docs/grok_report-20260824-parser-split.md`
- **Prior (18 August 2026 / 0.26.0 / free-call soft-miss):** `docs/grok_report-20260818-1311.md`
- **Prior (14 August 2026 / 0.25.4 / RECURSIVE + SIZEOF + prelude):** `docs/grok_report-20260814-1645.md`
- **Prior (11 August 2026 / 0.25.3 / formals + cross-module methods):** `docs/grok_report-20260811-2216.md`
- **Prior (6 August 2026 / 0.25.0 / item 20):** `docs/grok_report-20260806-2042.md`
- **Prior (3 August 2026 / 0.24.17 / item 21 methods):** `docs/grok_report-20260803-2318.md`
- **Prior (1 August 2026 / 0.24.16 / declaration + auto-upcast):** `docs/grok_report-080126-2008.md`
- **Prior status (31 July 2026 / `declaration.mc`):** this file; `changelog.md`
- **Prior session report (30 July 2026 / 0.24.15 / 21a + 13b Policy A):** `docs/grok_report-20260730-1800.md`
- **Prior (28 July 2026 / 0.24.14 Lexer):** `docs/grok_report-20260728-2052.md`
- **Prior (25 July 2026 / 0.24.13 arena + EXTENDS 13d):** `docs/grok_report-20260725-2251.md`
- **Prior (23 July 2026 / 0.24.12 OPAQUE + UNION):** `docs/grok_report-20260723-2250.md`
- **Prior (18 July 2026 / `statement.mc` + `OPAQUE` design):** `docs/grok_report-20260718-1906.md`
- **Prior (0.24.10 / `statement.mc` self-host):** this file; build 110
- **Prior (0.24.9 / `symkind` + `mh_exportkind` `.mc`):** changelog
- **Prior (0.24.8 / CONST array bounds):** `docs/grok_report-20260716-2236.md`
- **Prior (0.24.7 / ENUM Phase C):** `docs/grok_report-20260715-2248.md`
- **Prior (0.24.6 / ENUM + TMod-c rebrand):** `docs/grok_report-20260714-1939.md`
- **Prior (0.24.5 / qualident FROM):** `docs/grok_report-20260713-1200.md`
- **Prior (0.24.4 / self-host):** `docs/grok_report-20260711-1911.md`
- **Prior (0.24.3 layout):** `docs/grok_report-20260710-1200.md`
- **Prior (0.24.3 builtins/infra):** `docs/grok_report-20260709-2338.md`
- **Prior (0.24.2 infra):** pending `docs/grok_report-*.md`
- **Prior (0.24.0):** `docs/grok_report-20260707.1439.md`
- **Prior (0.23.9):** `docs/grok_report-20260704-2239.md`
- **Prior (0.23.7 → 0.23.8):** `docs/grok_report-20260703-2321.md`
- Language report: `docs/language-report.md` (hyphen; not `language_report.md`)
- Complete EBNF: `docs/syntax-ebnf.md` (hyphen; not `syntax.ebnf.md`)
- Grammar redirect: `docs/grammar.md` → report + syntax; archive `docs/grammar_working_notes.md`
- Long-term knowledge: `docs/project_bible.md`
- Agent instructions: `AGENTS.md`

## Prior Releases (summary)

- **0.26.5.179:** `Type::m(p)` peel when `p` is `^Owner`; do not peel `@x`. **make test-all** / selfhost / bootstrap / promote on gcc, clang, tcc. Date 4 September 2026.
- **0.26.5.178:** `p[i]` peel (not `^char[]`) + instance method on `^T`; caret `(*(expr))` for `p^[i]`. `Type::m(p)` closed in **179**. **make test-all** / selfhost / bootstrap on gcc, clang, tcc. Date 4 September 2026.
- **0.26.5.177:** Light refactor; `examples/Shapes.mc`. Date 4 September 2026.
- **0.26.5.176:** Oberon `p.x` auto-deref — `field_access.auto_deref`; C `(*(p)).field`. `p[i]` / instance on `^T` closed in **178**. **make test-all** / selfhost / bootstrap on gcc, clang, tcc. Date 3 September 2026.
- **0.26.5.175:** EXTENDS polish — `p^.x` parent fields; aggregate `as` → `.base`; pointer/`REF` upcast (`upcast_ptr`). Field auto-deref closed in **176**. Tests green. Date 2 September 2026.
- **0.26.5.174:** #11 import as the one unit bind; `.mh` width tails on fields/formals/results. Tests green. Date 28 August 2026. **31 August:** one `Makefile` (`CC=gcc|clang|tcc`); `Makefile.clang` / `Makefile.tcc` → `archive/`; `test-all` green on all three.
- **0.26.5.173:** Width forms + generated `.h` prelude; `-C` companion header. **make test-all** / promote on **gcc**, **clang**, **tcc**. Date 27 August 2026.
- **0.26.4.172:** Method-type `.mh` RHS; cross-module field call-through; field lists from **0.26.3.170**. **make test-all** / promote on **gcc**, **clang**, **tcc**. Date 26 August 2026.
- **0.26.3.170:** `.mh` struct/union field lists; ident ≤ 255; whole-file `.mh` reader; DynBuf export lines; synthetic layout on import. **make test-all** green. Date 25 August 2026.
- **0.26.3.168:** **`parser.c`** → **`parser_common.mc` + `parser_main.mc`**; dual `pParser` / `TParser::` helpers; cyclic `.mh` `IMPORT` noted (after item 15). **make test-all** / selfhost / bootstrap / promote on **gcc**, **clang**, **tcc**. Date 24 August 2026.
- **0.26.1.158:** Unknown type names closed; automatic `<stddef.h>` dropped; `nil` is `((void *)0)`. Date 18 August 2026.
- **0.26.0.156:** Free-call soft-miss closed. Date 18 August 2026.
- **0.25.4.154:** **`RECURSIVE`** required on direct self-calls; **`SIZEOF`** emits `((integer)sizeof(...))`; lean C prelude (`stddef`/`stdint`/`stdbool`/`assert`; `byte` = `uint8_t`; no auto `stdlib.h`). **make test-all** / selfhost / bootstrap on **gcc**, **clang**, **tcc**. Date 14 August 2026. Closes branch **`mod-c_0.25`**.
- **0.25.3.150:** **7a** module-entry bind — same-unit + importer auto-bind; arena-copied `.mh` names; module `VAR`/`REF` ABI; `test_module_ref` / `test_module_entry`; **gcc** / **clang** / **tcc**. Date 12 August 2026.
- **0.25.3.149:** **`.mh` formal signatures (6a)** — one-line formals + result; multi-word type-spec; synthetic proc on import; cross-module `VAR`/`REF` auto-`&`; `test4`/`test5` + string lib; build **149**. Date 11 August 2026.
- **0.25.2:** **Cross-module method Phase A** — `.mh` `instance`/`static` Owner; `import Type::name`; `is_method_instance`; `obj.method` across modules; string lib Makefile; build **146**. Date 11 August 2026.
- **0.25.1:** **Callable field call-through** — method-typed fields/values; Oberon no auto-self; ambiguity with instance methods; `test_callable_field` / `test_Math`. Date 7 August 2026.
- **0.25.0:** **Item 20** VAR/REF/CONST formals (**breaking**); call-site auto-`&`; non-VAR bare-name assign illegal. Date 6 August 2026.
- **0.24.17:** **Item 21** — `obj.method` / statement chains; instance vs static by first formal type; factories `Type::new(...)`; optional `end Type::name`; `test_smoke` / `test3_smoke`; build **134**; test-all on **gcc, clang, tcc**. Date 3 August 2026.
- **0.24.16:** **`declaration.mc` self-host** (31 July) + **EXTENDS by-value auto-upcast** (1 August) — `upcast_depth` / `.base` × N; no hidden RTTI; build **130**; test-all on **gcc, clang, tcc**.
- **0.24.15:** **Discard enforcement (13b Policy A)** — known call result requires `(f())` or use; unknown/procedure bare OK; `test_discard` / `test3_discard`; test-all on **gcc, clang, tcc**; build **128**. Date 29 July 2026.
- **0.24.14:** **Lexer.mc** self-host; **`type_of_expr` / init inference (21a)**; builds 125–126. Date 28–29 July 2026.
- **0.24.13:** Linked-chunk **arena** (pointer-stable growth); **`STRUCT EXTENDS` option A (13d)** — clashes, `base_depth`, synthetic `base` reserved only on EXTENDS; tests `test_extends` / `test3_extends_*`; build **121**. Date 25 July 2026.
- **0.24.12:** Bare **`UNION` types (13c)**; `codegen_common_union_decl`; promote build **118**; test-all on **gcc, clang, tcc**. Date 23 July 2026.
- **0.24.11:** `expression.mc` self-host; **`OPAQUE` types (13a)**; builds through 115–116.
- **0.24.10 + design (18 July):** `statement.mc`; `OPAQUE` design; language SSOT; discard plan.
- **0.24.10:** `statement.c` → `statement.mc`; build 110.
- **0.24.9:** `symkind.h` → `symkind.mc`; `mh_exportkind.h` → `mh_exportkind.mc` (build 106).
- **0.24.8:** Named `CONST` in array bounds; `size_expr` + const-eval try/hard split; integer `has_const_value` on `CONST`; string `CONST` safe; self-host/bootstrap/promote. Date 16 July 2026.
- **0.24.7:** ENUM Phase C (`.mh` `export enum`, cross-module); `.mh` negative import tests; test `INCLUDE_DIR` / `-I` paths (gcc Makefile); `WHILE … BY` dropped (use `defer`). Date 15 July 2026.
- **0.24.6:** ENUM Phase A/B (parse, semantic, codegen); `tmodc.h` prelude experiment; TMod-c rebrand documentation. Date 14 July 2026.
- **0.24.5:** Qualident `IMPORT … FROM` (parser, semantic, codegen, `mh_reader` helpers); `test2_mh_import_qual.mc`. Date 13 July 2026.
- **0.24.4:** `codegen_header.mc` self-host step (patch/minor; no API break). Date 11 July 2026.
- **0.24.3:** Builtin `integer` → `int`, `cardinal` → `unsigned int`; EOS layout; import sources documented (phase 1 strings, phase 2 qualidents); `test_layout.mc`, `test3_loop.mc`, `IMPORT FROM` include-only. Dates 9–10 July 2026.
- **0.24.2:** Three-tier test targets (`test`/`test2`/`test3`/`test-all`) in three Makefiles; four `test3_*` negative fixtures; manual `make version`; `src/build.number` survives `make clean`; `AGENTS.md` refresh. Date 9 July 2026. *(Host compilers later unified into one `Makefile` + `CC=`.)*
- **0.24.0:** `.mh` writer (`codegen_mh`, `-M`, auto-emit with `-C`); `.mh` reader (`mh_reader`); `.mh`→`.h` `#include` mapping; `mh_exportkind.h`; `pcchar`; if-body scoping fix; `test_mh_export.mc`, `test2_mh_import.mc`, `fixtures/minimod.{mh,h}`. Date 7 July 2026.
- **0.23.9:** Phase 1 `Type::method` static calls; removed `obj:method` sugar. Date 4 July 2026.
- **0.23.8:** Postfix `FORWARD` on proc/func; mutual recursion. Date 3 July 2026.
- **0.23.7:** Item 5 `sizeof` registry; item 6 `EXTERN`; tag `MOD-C_0.23.7`. Date 3 July 2026.
- Older: `docs/grok_report-*.md`.
