# sx `extern`/`export` + `#foreign` retirement — Checkpoint (FFI-linkage stream) Companion to `current/PLAN-EXTERN-EXPORT.md` — one merged plan: **Part A** adds `extern`/`export`, **Part B** migrates `#foreign` and purges `foreign`. Update after every commit, one step at a time per the cadence rule. ## Last completed step None — plan authored, not yet started. (Merged the former EXTERN-EXPORT + FOREIGN-MIGRATION plans into this single plan.) ## Current state Syntax decided + ratified: bare `extern`/`export`, postfix in the `callconv(.c)` slot, `extern ⇒ callconv(.c)`, library separate. Touch-points mapped — token `token.zig:45,282`; parser `1950,3669,316,425,1305`; lowering `decl.zig:1123,387,2110,2382,2514`; IR/emit already capable (no codegen change). Export gap = 4 lowering conditions. Part B `foreign` footprint to purge: 643 lines / ~57 identifiers in `src/` + 28 doc lines. End-state invariant: **zero `foreign`** in the live tree (Phase 9.4 gate). No code written. ## Next step **Phase 0.0** — add `kw_extern`/`kw_export` tokens + keyword-map entries (beside `kw_callconv`) + unit lex test. Then 0.1 (parser plumbing, unconsumed), then Phase 1 (`extern` working). See the plan's **"Kickoff prompt"** section. ## Open decisions Part A ratified (bare / postfix / `⇒ callconv(.c)` / lib-separate). Part B (confirm before Phase 9): runtime-class rename target — `Runtime*Class*` (recommended); historical carve-out — keep `issues/*.md` provenance, gate the live tree only. ## Log - (init) Plan written; FFI-linkage stream opened. - (merge) Folded FOREIGN-MIGRATION in as Part B; deleted the split plan + checkpoint. ## Known issues None yet.