- Add StateRegistration.withHydration(context:_:) helper
- Replace duplicated save/set/restore pattern in renderToBuffer and measureChild
- Single source of truth for hydration context management
- Replace custom Observable protocol and @Published with Apple's @Observable macro
- Add withObservationTracking in renderToBuffer for automatic per-property dependency tracking
- Add type-based @Environment(Type.self) and .environment(object) for observable objects
- Add ObjectEnvironmentModifier for injecting observable objects into the environment
- Add needsCacheClear flag to AppState for thread-safe cache invalidation
- Add cross-platform test script (scripts/test-linux.sh) for Docker-based Linux verification
- Add DemoAppHeader with system info display (OS, version, architecture)
- Consolidate Example App: extract ImageDemoHelpers, KeyboardHelpSection, ValueDisplayRow
- Add pre-push verification rule to CLAUDE.md
- Verified on both macOS and Linux (swift:6.0 container), 1155 tests passing
- Add @Environment<Value> property wrapper for declarative environment access
- Add StateRegistration.activeEnvironment for ambient context during body evaluation
- Set/restore activeEnvironment in renderToBuffer() and RenderLoop.render()
- Refactor RenderLoop.render() into focused helpers to fix function_body_length warning
- Add 7 tests covering default values, active environment, dynamic reads, and propagation
Replace RenderNotifier with clean AppState and RenderCache singletons:
- Add AppState.shared static singleton for global access
- Add RenderCache.shared static singleton for memoization
- Remove RenderNotifier enum completely
- Remove RenderNotifierKey from EnvironmentValues
- StateBox.didSet uses AppState.shared directly
- AppStorage.wrappedValue setter uses AppState.shared directly
- NotificationService.post() uses AppState.shared directly
- Spinner animation uses AppState.shared directly
- NotificationHostModifier animation uses AppState.shared directly
- TUIContext uses RenderCache.shared by default (injectable for tests)
- Update test infrastructure to isolate RenderCache per test
Architecture: Pure singleton pattern with no global state registry.
All 1069 tests pass, no new compiler warnings.
This completes the full elimination of RenderNotifier and provides a
clean, explicit architecture where AppState.shared is the single
source of truth for render triggers.
- Make RenderNotifier.current optional (nil by default) to support DI
- Add RenderNotifierKey and renderNotifier property to EnvironmentValues
- Initialize renderNotifier in RenderLoop.buildEnvironment()
- Migrate Spinner animation loop to read from environment
- Migrate NotificationHostModifier to read from environment via parameter
- Update StateBox.didSet to use optional chaining fallback
- Update AppStorage.wrappedValue setter to use optional chaining fallback
- Update NotificationService.post() to use optional chaining fallback
- Update test comments to reflect optional chaining pattern
- All 1069 tests pass, no new compiler warnings
Phase 3 implementation of P4.16 dependency injection refactor complete.
- Add comprehensive documentation to RenderNotifier static properties
explaining main-thread-only access guarantees and safety model
- Add inline safety comments to Terminal memory operations
explaining why unsafe memory rebinding is safe in context
Audit findings: All concurrency patterns are justified, documented,
and safe. No critical issues found. These are quality-of-life improvements
for code maintainability.