Await
The biggest addition of the month is definitely Await.
It is a new C++20 coroutine layer on top of SC::Async, so the point is not replacing the existing async model, but letting the compiler write the callback state machine instead.
What I like here is that it is still very clearly shaped like Sane C++ code.
Tasks return Result, memory is still explicit through AwaitAllocator, buffers are caller-owned, and the underlying event loop remains the same one used by callback-style Async.
So the style changes a lot, but the project principles do not.
May has basically been about taking Await from "new experiment" to something that feels real enough to be tried on more than toy examples.
There are now awaiters for sockets, files, filesystem operations, signals, process exits, background work, wake-ups, task groups, detached registries, and timeouts, plus a pretty large set of examples to show how all these pieces fit together.
Development speed has also gone up a lot thanks to heavier AI usage. I think this month already shows that pretty clearly, and next months will probably show even more of it, so...be prepared!
Even the very end of the month kept pushing Await further, with more stress coverage around teardown/cancellation, a spawnAll helper for task groups and even a no-stdlib coroutine shim.
Detailed list of commits:
- Await: Add a new library wrapping Async primitives with C++ 20 coroutines
- Await: Add cancellations, arena and socket accept / sendAll
- Await: Add documentation draft page and skill guide
- Await: Add socket connect and UDP awaiters
- Await: Add file read and write awaiters
- Await: Add loop work awaiter
- Await: Add file send awaiter
- Await: Mark Await as draft library
- Await: Support waitFor cancellation
- Await: Extend filesystem operations
- Await: Add process signal and spawn helpers
- Await: Extend filesystem and task APIs
- Await: Add wakeUp and waitAny support
- Await: Add scatter gather wrappers and echo example
- Await: Harden cancellation and arena policy
- Await: Add read helpers (receiveLine / receiveExact / readUntilEOF)
- Await: Add task group example
- Await: Add arena diagnostics
- Await: Harden task lifetime guards
- Await: Add callback bridge example
- Await: Add file courier example
- Await: Defer child task teardown during callbacks
- Await: Promote docs to MVP status
- Await: Add line protocol example
- Await: Add background digest example
- Await: Add process exit example
- Await: Add thread wake-up example
- Await: Add deadline example
- Await: Add file patch example
- Await: Add config reload example
- Await: Add manifest preview example
- Await: Require explicit allocator
- Await: Add fixed task registry
- Await: Add task registry wait all
- Await: Add task registry wait any
- Await: Add first response example
- Await: Guard cross-loop cancellation
- Await: Add service probe example
- Await: Polish task ergonomics and allocator diagnostics
- Await: Add task group spawnAll helper
- Await: Stress child teardown callback test
- Await: Stress cancellation teardown
- Await: Add no-stdlib coroutine shim
Http and HttpClient
The other huge theme of the month has been Http.
This is still a Draft library, but it has become much more practical for real examples instead of just being a parser plus a few low-level building blocks.
The most visible part is that the server side now has a small router, API server examples, better file-server behavior, and a more complete WebSocket path.
Things like SPA fallback, byte ranges, validators, If-Range, HEAD, OPTIONS, asset types, safer multipart filenames, cookies, authorization helpers, and URL query parsing are all the kind of boring HTTP details that make the difference between a demo and something actually pleasant to use.
The async client side has also been tightened up a lot, and the separate HttpClient keeps moving toward a more stable allocation-free transport layer.
There is now a better request API, transport metadata, TLS options, compression support, stronger validation, and examples for both the native-backend client and the async transport integration.
The TLS work is for now just preliminary, do not expert https support (for now).
Detailed list of commits:
- HttpClient: Improve request API and add redirect/TLS transport metadata
- Http: Add WebSocket frame core and tests
- Http: Add WebSocket upgrade handshake
- Http: Add WebSocket lifecycle helpers
- Http: Add WebSocket small hub
- Http: Add WebSocket canvas example
- Http: Add client compression
- Http: Add WebSocket client connect
- Http: Add API server example
- Http: Add URL query parser
- Http: Add SCExample canvas demo
- Http: Harden file server paths
- Http: Add file server asset types
- Http: Add HEAD request support
- Http: Reject unsafe multipart filenames
- Http: Add async client HEAD helper
- Http: Add common method parsing
- Http: Add file server OPTIONS
- Http: Add common response statuses
- Http: Surface async server errors
- Http: Add file validator responses
- Http: Expose server header limit
- Http: Add request target accessors
- Http: Add content length helper
- Http: Fix streamed file uploads
- Http: Add file server validators
- Http: Add file server byte ranges
- Http: Add file server SPA fallback
- Http: Match listed file server ETags
- Http: Honor If-Range for file ranges
- Http: Add cookie header iterator
- Http: Add authorization header helpers
- Http: Add Set-Cookie helpers
- Http: Export header helpers
- Http: Add minimal router helper
- Http: Route API server example
- Http: Add urlencoded form helpers
- Http: Harden async HTTP APIs and WebSocket support
- HttpClient: Stabilize allocation-free transport API
- HttpClient: Add async example and harden buffer validation
- Http: Add active transport streams
- Http: Add TLS options
- Http: Add async transport setup hook
- Http: Polish HTTP helpers and example ergonomics
- Http: Add multipart part predicates
- Http: Stress chunked request decoding
- Http: Simplify canvas WebSocket
- Http: HTTPS transport hook dispatch
- HttpClient: Validate request URLs
- HttpClient: Fail on response header overflow
Build and SC-package
After April being the big SC::Build month, May has been more specifically about SC-package.
The package manager got a fairly serious internal redesign to become more declarative, with structured receipts, exports, capabilities, recipes, locks, verification, and repair/doctor flows.
There is also more validation around cross support, more CI cache work, direct running of native translated Linux targets, and a Fil-C zlib package plus CI coverage for that toolchain.
Detailed list of commits:
- Build: Add clarifications for the version pragma
- Build: Fix Windows build tool stale dependency detection
- Build: Add package phase registry
- Build: Expose package recipe descriptors
- Build: Add package doctor command
- Build: Validate package receipt contracts
- Build: Add package lock metadata
- Build: Add package capability constants
- Build: Run Fil-C SCTest in CI
- Build: Prewarm package caches
- Build: Cache macOS cross package installs
- Build: Run Linux native translated targets directly
- Build: Transform SC-Package to become more declarative
- Build: Add package repair command
- Build: Split package manager headers
- Build: Split built-in package catalog
- Build: Split package recipe engine
- Build: Split package receipt engine
- Build: Split package health engine
- Build: Split package CLI engine
- Build: Split built-in package installers
- Build: Structure package registry exports
- Build: Use typed package export kinds
- Build: Add package kind constants
- Build: Use typed capability export lookup
- Build: Stabilize cross support validation
- Build: Fix package receipt validation
- Build: Normalize package receipt JSON
- Build: Add package lock verification
- Build: Add Fil-C zlib package
Standard Library Integration
Another notable theme of the month has been making Sane C++ easier to consume from normal C++ projects. Standard C++ headers are now allowed by default, while the stricter no-stdlib mode is still available when one actually wants to push in that direction.
I think this is the right tradeoff.
The libraries still try hard to avoid hidden allocations and broad runtime dependencies, but making integration easier by default removes friction for external users and also makes features like Await much easier to justify.
The follow-up cleanup here is also nice: LibC.h is gone, public include coverage has been tightened up, and some no-stdlib edge cases in GCC / plugin builds have been corrected.
Detailed list of commits:
- Everywhere: Add some missing public includes
- Everywhere: Allow using C++ stdlib by default
- Foundation: Get rid of LibC.h
- Plugin: Do not use nostdinc++ on plugins
- Build: Avoid unsupported GCC no-stdlib flag
Async
Async also deserves its own section this month.
The main point here is getting rid of the dynamic liburing loading and using io_uring directly instead, which makes the Linux backend story cleaner and more self-contained.
There are also a few useful follow-up fixes around filesystem handles, dispatched kernel events and Ubuntu 22.04 headers. Not a huge flashy section, but definitely a nice set of improvements on its own.
Detailed list of commits:
- Async: Preserve filesystem operation handles
- Async: Add AsyncFileSystemOperation::stop
- Async: Use io_uring directly
- Async: Clear dispatched kernel events
- Async: Fix io_uring headers for Ubuntu 22.04
Others
The rest of the month is a mix of practical lower-level improvements. There are a few platform fixes around shutdown and plugin cleanup, and the single-file generation tooling can now emit standalone amalgamations.
There are also a couple of nice quality-of-life fixes around development tooling and examples. These are still the sort of changes that make the project easier to build, test, and use across different setups.
Detailed list of commits:
- File: Keep POSIX pipe descriptors out of the stdio range
- FileSystemWatcher: Avoid Linux shutdown fd race
- Plugin: Skip debugger file cleanup on registry close
- SCExample: Close plugins before event loop shutdown
- SingleFileLibs/Python: Emit standalone amalgamations
- SCExample: Restore using GLES3 backend on Linux
- VSCode: Start executable from native build folders
See you next month!