Skip to content

Roadmap

Skein’s compilation pipeline, runtime, standard library, editor tooling, and distribution packaging are all functional. This page covers the current state, forward-looking priorities, and a history of completed work. The canonical, more detailed version lives in docs/ROADMAP.md.

The end-to-end pipeline works: .skein source files lex, parse, analyze, generate Core Erlang, compile to BEAM bytecode, and execute on OTP. The runtime supports agents, HTTP handlers, queue/schedule/topic handlers, typed store tables (schema-checked ETS, C5 #255), LLM integration (production Anthropic backend with streaming, AWS Bedrock, and an OpenAI-compatible backend for local models), tool calling, memory, tracing, replayable event sourcing with opt-in SQLite persistence, real OTP supervision from supervisor declarations, and guard expressions in match arms.

The full test suite (unit, property-based, and integration) runs green in CI on every change — see the CI badge on the README for current totals; counts aren’t tracked here because they grow with every change.

Sixteen example programs (thirteen single-file plus the multi-file market_research project and its single-file variant) compile and run warning-free, covering HTTP APIs, agents with LLM and tools, queue workers, pub/sub notifications, background tasks, audit logging, semantic search, and a conversational assistant. All are covered by integration tests.

The release train so far: v0.2.0 and v0.3.0 shipped 2026-06-11, v1.0.0-rc.1 was tagged 2026-06-12, and both v0.4.0 — Truth & Soundness and v0.5.0 — Runtime Contract & Dogfood shipped 2026-07-02. A 2026-06-15 roadmap reset re-sequenced the path to 1.0. A source-verified dogfooding audit of the skein-testing and FablePool ports reclassified GA from a docs-accuracy cleanup into a soundness + honesty + observability + conformance gate. The active gate is v1.0.0-rc.5 — True release candidate (the Wave F freeze: executable gates for every frozen surface, the agent-writability benchmark, and live-backend verification — #332/#320/#334); GA follows only after the RC soaks and is not imminent. (Tags rc.2–rc.4 exist from the pre-reset June train, so the next RC tag is rc.5.)


The path to 1.0 runs through the contract-first waves: v0.4.0 — Truth & Soundness (shipped 2026-07-02), then v0.5.0 — Runtime Contract & Dogfood (shipped 2026-07-02), and now the true RC — v1.0.0-rc.5, the Wave F freeze — then GA after the candidate soaks, which is not imminent. The canonical detail (waves, acceptance criteria, citations) lives in docs/ROADMAP.md.

Wave A (truth reset: honest docs/spec/stability framing, surface cuts like tool policy blocks) and Wave B (analyzer/codegen soundness, B1–B6) landed — Wave B completed 2026-07-01 and was source-verified by the 2026-07-02 sanity check, with its residual holes (#309–#311, #313, #318, #319) closed. ? truly early-returns, unknown/widened types cannot cross declared boundaries (E0037), call arguments are type-checked everywhere, the analyzer-accept ⇒ BEAM-load bridge holds, records are nominal, and tool/provider bodies are checked against their contracts (E0038).

v0.5.0 — Runtime Contract & Dogfood (shipped 2026-07-02)

Section titled “v0.5.0 — Runtime Contract & Dogfood (shipped 2026-07-02)”

Wave C made the runtime expose exactly the contract the analyzer and spec claim, plus Wave D’s continuous dogfood gate — all landed 2026-07-02:

  • C1 — authoritative effect-ABI registry (Skein.EffectABI, #296): one source of truth for effect signatures, store methods, provider contracts, and error enums; analyzer/spec/runtime drift is a CI failure
  • C2 — one structured-error ABI (#297): LLM/tool/provider/store/HTTP errors are matchable nominal enum variants (Err(LlmError.RateLimit(ms))), not raw Elixir structs; the variant registry is frozen
  • C3 — one recursive schema engine (#298): req.json[T], llm.json[T], and tool input and output all validate through the same recursive validator (Skein.Runtime.JsonSchema)
  • C5 — typed store tables (#255): capability store.table("games", Game) names a record type; store methods type as Result[T, StoreError] and writes are schema-checked at runtime — landed on the ETS store compiled programs actually use, not the unwired Ecto path
  • C6 — EventStore persistence (#299): the SQLite backend is wired onto the ordinary append path — opt-in via Persistence.enable/1, enabled by default by skein run (.skein/events.db, --no-persist opts out), with persisted history reloaded on restart; the persisted shapes freeze at Wave F
  • #325 — supervisor declarations boot real OTP supervisors under skein run (#325)
  • Wave D / #262 — the continuous dogfood conformance gate: compile + load + run reduced, pinned programs from the checked-in dungeon and fablepool ports on every change

The Wave F freeze landed 2026-07-02: grammar/keywords, the diagnostics registry, the full effect ABI + error shapes, schema derivation, the CLI/JSON/config surface, compiled-metadata classes, and the EventStore persisted shapes are all declared frozen with executable drift gates against the vectors under conformance/freeze/ (#332), agent-writability is measured rather than asserted (#320 — see the writability benchmark), and llm.stream was live-verified against the production backend (#334). What remains is release mechanics: cut the rc.5 tag, soak the candidate, then promote to GA. The canonical-substrate question was resolved out of 1.0 (#300 closed as Alternative B): the substrate items live in v1.1, and there is no v0.6.0 milestone.

Tracked in docs/ROADMAP.md with linked issues:

  • v1.1: Hardening & Language — closures (#248), effectful crypto (#257), content-addressed store tables (#333), language ergonomics (#251/#249/#247), via if still useful, llm.rerank (#145), docs/spec drift guards (#202), LSP rename/references (#240)
  • v1.2: Interop & Agent Workflows — Erlang/Elixir FFI (extern, #141), human-in-the-loop approval workflows (#144), web trace viewer (#143), Raxol CLI TUI (#171, separately gated), structural codemod (#241)
  • Future: Platform — hot code upgrades (#142), managed deployment platform (#148), tool/connector marketplace (#149)

Everything below is implemented and tested.

PhaseNameSummary
1Hello BEAMEnd-to-end compilation: lexer → parser → analyzer → Core Erlang → BEAM
2Type SystemType checking, schemas, constraint annotations, Option[T], Result[T, E], !/? operators
3Capabilities & EffectsCapability declarations, compile-time checking (modules + agents), HTTP client, tracing
4Handlers & HTTPHTTP handlers with routing, request dispatch, Bandit + Plug server
5StorageETS-backed store.table with get, put, delete, query
6AgentsAgent state machines, phases, transitions, memory, LLM, tools, events
7Testing & CLITest constructs, full CLI (new, build, test, run, trace)
Sub-phaseNameSummary
8aTest InfrastructureScenario tests (given/expect), golden trace tests, replay engine (trace loading + memory rebuild)
8bStorage BackendEcto schema generation, migrations, SQLite via ecto_sqlite3 (library code only — typed tables landed on the ETS store instead, C5 #255; EventStore persistence uses its own SQLite backend, #299)
8cHTTP ServerBandit + Plug integration, req.json[T] body validation
8dCanonical Examples14 working programs with integration tests
8eQueue & Schedulehandler queue and handler schedule constructs
8fLLM Streamingllm.stream with chunked responses and trace spans
  • Field access resolves through user-defined type declarations; user.email + 42 is a type error (E0020)
  • Pattern bindings carry the inner types of Result, Option, and enum variants
  • Nested user types generate fully resolved JSON Schema; enum variants produce oneOf; Map[K, V] generates additionalProperties; circular references are safe
  • Production Anthropic backend (Messages API): chat, json (schema-in-system-prompt), stream (SSE), retry on 429, structured errors, API-key redaction
  • Model-scoped runtime capability checks: llm.chat("model-x", ...) without a matching capability model(...) is blocked
  • Current model IDs throughout examples and docs
ItemSummary
Float division codegen/ uses Erlang / for floats, div for integers
String-literal match patternsmatch s { "approve" -> ... } compiles to proper binary patterns
state.field everywhereAgent state access works in nested expression positions
Postfix !/? unwrapstore.users.get(id)! parses as unwrap-of-call and the chain continues (likewise ?); the pre-paren get!(id) spelling was removed (#268)
Contextual keywordsinput, output, state, etc. no longer globally reserved
Multiple emit per handlerAll events accumulated, not just the last
Agent instance-scoped memoryKeys scoped as {agent}:{instance}:{key}; concurrent instances don’t collide
Tool input validationInputs validated against the tool’s JSON Schema; validation_error on mismatch
Capability namingqueue.consume / schedule.trigger (old names get a targeted rename hint)
Cross-module tool.callimplement blocks compile to callable entry points; tools registered at module load (v0.1.5)
Variant constructionOk(x), Err(e), Event.Charge(n), ErrName.from(cause), and zero-field forms (Status.Active, bare Active) all compile in expression position; unknown variants and wrong arity are structured errors
Spec section 8 sweepEvery section-8 example compiles with zero diagnostics (pinned by spec_examples_test.exs)
zsh tab-completionskein completions zsh (drift-tested against the help text)
MCP compile_check fidelityWarnings included (Compiler.check_file/1); project mode checks src/ + test/ like skein test
Structured assertion failuresFailing asserts report operands, rendered expression, and file:line (Skein.Runtime.AssertionError)
skein new git initRepo + baseline .gitignore scaffolded by default (--no-git to skip; never nests inside an existing work tree)
Agent events to EventStoreemit flushes durably as :user_event (agent/instance/phase tags); crash-safe
Schedule auto-firingCron tick with per-minute dedup; Server registers schedule handlers; tick_at/1 for deterministic tests
Capability checks in test blocksEffects inside test/scenario/golden require capabilities (E0012) and count as usage (no scaffold W0002)
Named arguments in callsf(name: value) for local fns and documented effect signatures; analyzer rewrites to positional order at compile time (E0026 on misuse)
Agent nesting inside modulesmodule Foo { agent Bar } → Skein.Agent.Foo.Bar; module types and capabilities apply to the nested agent
Types usable from agentsModule types visible to nested agents; derived JSON Schema flows into llm.json[T] from agent handlers
EventStoreIn-memory, size-bounded ETS event log with opt-in SQLite persistence on the ordinary append path (#299): skein run enables it by default and reloads persisted history on restart; shapes freeze at Wave F
Error systemStructured error/warning codes (spec §7); context and fix_code populated on all analyzer/parser/lexer errors
Replay backend injectionRecorded traces intercept llm/http/tool effects on replay; exhausted or mismatched traces are structured errors, never silent live calls (#73)
Scoped capability labelsmemory.kv/event.log/process.spawn/timer capability params are scope labels the compiler threads into runtime calls and the runtime enforces exactly (#69, #57)
Task bodiesprocess.spawn("name", &fn) and timer.after/timer.interval work arguments run in supervised tasks (#74, #155)
Local LLM backendsOpenAI-compatible backend + [env.<name>.llm] profiles in skein.toml with model_map for Ollama/LM Studio/vLLM dev loops (#107)
AWS Bedrock backendConverse API with SigV4 signing, region + model_map config (#173)
Match guardspattern if expr -> with a guard-safe operator subset (#147)
Value-level exhaustivenessW0004 warns when a variant is covered only by literal field patterns (#76)
LSP code actionsEditor quickfixes built from each diagnostic’s fix_hint/fix_code (#108)
llm.embed backendEmbeddings served by the OpenAI-compatible backend’s /embeddings endpoint (#146)

11 modules:

ModulePurpose
StringManipulation, search, splitting, formatting
Int / FloatArithmetic, parsing, conversion
ListFunctional operations (map, filter, reduce, etc.)
MapKey-value operations
SetMathematical set operations
OptionSome(T) / None handling
ResultOk(T) / Err(E) handling
UuidUUID parsing/formatting (generation is the capability-gated uuid.new() effect, not ambient stdlib)
InstantISO 8601 timestamps
DurationTime intervals
FeatureDescription
Topic pub/subhandler topic + topic.publish effect (name-scoped runtime checks)
Idempotencyidempotent(key) with TTL-based deduplication
Process spawningprocess.spawn with DynamicSupervisor
Timerstimer.after, timer.interval, timer.cancel
Event sourcingUnified EventStore with query, memory rebuild from events
suspend/resumeAgent lifecycle management
respond.text/respond.htmlContent-type response variants
trace.annotateCustom annotations in the event stream
llm.embedEmbedding vectors (requires an embeddings-capable backend)
  • VS Code extension with TextMate grammar, 30+ snippets, LSP client
  • Language Server (GenLSP): diagnostics, document symbols, hover, go-to-definition, completions, semantic tokens — with request/response integration tests
  • Burrito binaries for Linux x86_64/ARM64 and macOS x86_64/ARM64
  • GitHub Release automation — binaries published automatically on v* tags
  • Auto-tagged releases — a green version-bump merge to main tags, builds, and publishes the release with no manual steps; each release carries a docs snapshot (incl. llms*.txt)
  • skein build --output writes .beam files to disk
  • See Distribution for remaining packaging work