☀️ Sane C++ June 26
Welcome to the June 2026 update! This month is about cleaner common foundations, more dependency-free libraries, agent-friendly repository workflows, Windows long-path support, and a large pass on Async contracts.
Common Foundations
June started with a fairly deep cleanup of the lower layers of the project.
The old shape was that many libraries depended on Foundation even when they only needed a small primitive such as Result, Span, Function, compiler macros, platform detection, or a basic string/path view.
That is much cleaner now. A large set of these small building blocks has been moved into common fragments, so libraries can include only the pieces they actually need. The practical consequence is important: many more libraries now have no real library dependency at all.
This fits the direction I want for Sane C++ Libraries. The libraries should be easy to pick up individually, easy to amalgamate, and easy for tools or agents to reason about without dragging a large conceptual dependency tree behind every include. Smaller dependency surfaces also make the single-file outputs less surprising, because the generated order is closer to the actual code structure.
Plugin and SerializationText also got dependency simplifications in the same spirit.
They no longer need to pull in Strings, which removes another bit of unnecessary coupling from libraries that should stay small and composable.
There were also follow-up fixes around per-library assert providers, documentation, CI, and the JavaScript single-file generation path.
Detailed list of commits:
- Foundation: Split Compiler.h, Platform.h and PrimitiveTypes.h in common code fragments
- Foundation: Remove SC_COMPILER_UNUSED
- Foundation: Integrate CompilerMacrosExport.h
- Foundation: Move Result.h to Common
- Foundation: Move Deferred.h to Common
- Foundation: Move UniqueHandle.h to Common
- Foundation: Move Function.h and TypeTraits.h to Common
- Foundation: Move AlignedStorage.h to Common
- Foundation: Formatting for Result.h
- Foundation: Move OpaqueObject.h to Common
- Foundation: Move InitializerList.h to Common
- Foundation: Move Span.h to Common
- Foundation: Move IGrowableBuffer.h to Common
- Foundation: Move StringSpan.h to Common
- Foundation: Move StringPath.h to Common
- Foundation: Move Assert.h to Common
- Foundation: Make Assert providers per library
- Foundation: Fix JS single-file Common order resolution
- Foundation: Fix documentation after Common moves
- Foundation: Fix CI after Common fragment moves
- Foundation: Simplify StringSpan.h
- Everywhere: Remove Foundation dependency
- Documentation: Clarify the No Allocations clauses
- SerializationText: Remove Strings dependency
- Plugin: Remove dependency on Strings library
Agentic Repository Workflow
Another theme this month was making the repository easier to navigate and change with agents.
The documentation now has an explicit agentic contribution workflow. The website tagline also moved toward the "built for Agents" direction, and the documentation CI can trigger publishing of the website source.
This matters because I think that the era of manual coding is over (excluding recreative purposes of course).
Humans and agents both need routes through the codebase: library docs, skills, examples, local AGENTS.md and more, all pointing in the same direction.
I plan to expand more on this theme in the coming months, adding more formal constraints and ADR to prevent agents from derailing.
Detailed list of commits:
- Documentation: Define agentic contribution workflow
- CI: Trigger website source publish from documentation CI
- Documentation: Add "built for Agents" to the tagline
- Documentation: Correct coverage links
Windows Long Paths
Windows long paths also deserve their own section. This work started right at the end of May and carried into June with follow-up fixes, documentation, and build-tool integration.
The short version is that Windows runtime targets are now long-path-aware by default where it makes sense.
SC::Build can emit the manifest support needed for console executables, GUI applications, and shared libraries, while static libraries reject that option because there is no runtime manifest to embed.
There is common Windows path handling, long-path-aware bootstrap behavior, PowerShell launcher support, Visual Studio project generation support, native build command rewriting, manifest/resource staging, and test coverage around long directory names.
Hopefully now this just works transparently without too many issues (and if there are, just as your agent to report them).
Detailed list of commits:
- Everywhere: Support windows long paths
- Build: Add Windows long-path policy switch
- Tools: Fix Windows UNC bootstrap and manifest staging
Async Contracts
The biggest library-specific work this month was Async.
May introduced Await as a coroutine layer on top of Async, so June spent a lot of time tightening the lower-level contracts that everything else depends on.
The new AsyncContractTest is the clearest sign of that shift.
Instead of only testing individual operations, the test suite now captures more of the lifecycle rules around event loops, requests, close paths, cancellation state, manual completions, sequence shutdown, submitted request stops, blocking polls, and request reuse from callbacks.
AsyncFilePoll was also split into AsyncFileReadiness and AsyncExternalCompletion.
That is a better separation: one concept is about file readiness, while the other is about manually injecting completions into the event loop.
Those were related implementation paths, but they are not the same API idea.
There was also a lot of wording cleanup in the docs.
Signal fanout, signal option semantics, request enumeration, event-loop run behavior, and thread-pool policy are all more explicit now.
That should help both direct Async users and the newer Await layer avoid relying on behavior that was accidental or underspecified.
Detailed list of commits:
- Async: Split AsyncFilePoll into AsyncFileReadiness and AsyncExternalCompletion
- Async: Stabilize FileSystemWatcher async submission test
- Async: Stop dispatching completions inside close()
- Async: Add AsyncContractTest
- Async: Strengthen core lifecycle contracts
- Async: Enumerate active sequenced requests
- Async: Clarify signal watcher fanout
- Async: Clarify signal option semantics
- Async: Cover submitted request stop contract
- Async: Document request enumeration contract
- Async: Mark cancellation enumeration nonportable
- Async: Remove misleading signal one-shot no-op
- Async: Cover event loop recreation contract
- Async: Cover blocking poll listeners
- Async: Cover excluded active run semantics
- Async: Cover interrupted run contract
- Async: Clarify event loop contracts
- Async: Clarify thread pool policy
- Async: Clean wakeup test noise
- Async: Reset external completion cancellation state
- Async: Cover event loop close completion paths
- Async: Cover reactivation decision contracts
- Async: Cover sequence shutdown contracts
- Async: Preserve run progress for manual completions
- Async: Cover request reuse from close callback
- Async: Handle missing thread pool completion removal
Http, HttpClient and Everything Else
The rest of the month is mostly hardening and small practical fixes.
Http and HttpClient got a lot of edge-case coverage.
Most of this is diagnostic and validation work: pinned error messages, disabled upload policies, multipart behavior, router and header helpers, WebSocket frame/hub diagnostics, server parser behavior, client TLS diagnostics, URL and proxy validation, authorization origin checks, cookie scope, and response header length limits.
That may sound less exciting than adding new HTTP features, but it is the work that makes the newer HTTP surface safer to build examples on. May made the HTTP libraries more useful; June made more of their failure modes explicit.
There were also smaller platform and tooling fixes.
Process has a larger Windows environment arena, FileSystemWatcher handles zero-byte Windows change completions, SCExample is a little more robust around plugin files and example paths, the Windows bash launcher forwards to SC.bat, Visual Studio LLVM tool discovery was fixed in CI, and Time avoids an integer conversion warning.
Detailed list of commits:
- Process: Increase Windows process environment arena
- Http: Pin diagnostic result messages
- Http: Add public header compile smoke
- Http: Stress large multipart uploads
- Http: Pin WebSocket hub diagnostics
- Http: Clarify server lifecycle errors
- Http: Pin file server option diagnostics
- Http: Fix server storage diagnostics
- Http: Pin router diagnostics
- Http: Pin multipart writer diagnostics
- Http: Pin header helper diagnostics
- Http: Pin WebSocket frame diagnostics
- Http: Add form value lookup helper
- Http: Pin URL decode diagnostics
- Http: Add request option setters
- Http: Use request option setters
- Http: Pin multipart header diagnostics
- Http: Cover disabled uploads policy
- Http: Pin client trailer diagnostic
- Http: Smoke client option helpers
- Http: Pin client TLS diagnostics
- Http: Pin server parser diagnostics
- Http: Cover disabled multipart uploads
- HttpClient: Align session URL validation
- HttpClient: Tighten proxy URL validation
- HttpClient: Document proxy URL constraints
- HttpClient: Validate cached authorization headers
- HttpClient: Document session authorization validation
- HttpClient: Validate cached authorization origins
- HttpClient: Validate TLS CA paths
- HttpClient: Clamp response header length
- HttpClient: Enforce session cookie scope
- FileSystemWatcher: Handle zero-byte Windows change completions
- SCExample: Make it more solid regarding plugin files modified in Visual Studio
- SCExample: Normalize examples path
- Tools: Forward SC.sh to SC.bat on Windows bash
- Plugin: Route build products to PluginDefinition::directory
- CI: Fix Visual Studio LLVM tool discovery
- Everywhere: Avoid integer conversion warning
- SerializationBinary: Remove Assert provider
- SingleFileLibs/Python: Exclude Common in LOC computation
See you next month!