Files
Jarvis/packages/Logging/Sources/JarvisLogging/DateProvider.swift
james.maesandClaude Opus 4.7 23917e58f2 feat(01-02): build Logging package (OBS-06, D-17, D-18, D-20)
- JarvisLogChannel: four cases (agent, tools, ui, system)
- JarvisLogHandlerFactory.bootstrap wires MultiplexLogHandler that
  fans out to FileLogHandler + OSLogHandler (D-17)
- FileLogHandler applies Redact.apply once (S-4 single call site)
- OSLogHandler does NOT redact (os.Logger handles %{private}@ at
  system layer; callers redact untrusted input before logging)
- Redact covers exactly 5 patterns: sk-ant-, Authorization:Bearer,
  sk- (OpenAI), AKIA, ghp_ (D-20, OBS-06); Anthropic branch ordered
  before OpenAI so sk-ant- consumes the full prefix
- FileRotatingWriter: lazy midnight rotation via TestDateProvider-
  injectable DateProvider; serial DispatchQueue; retain-7 GC on
  rotate (D-18)
- LogPaths.channelDirectory = ~/Library/Logs/Jarvis/
- Swift 6 strict: ISO8601DateFormatter.jarvisShared uses
  nonisolated(unsafe) since the formatter is documented thread-safe
  after configuration but not Sendable-annotated by Apple
- OSLogHandler uses fully-qualified Logging.Logger to disambiguate
  from os.Logger (both imported)
- Tests: 13/13 pass (7 Redact + 2 FileLogHandler rotate/retain +
  4 bootstrap/factory/channels)
- Deletes Plan 01 placeholders

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-22 13:27:34 -05:00

27 lines
851 B
Swift

import Foundation
public protocol DateProvider: Sendable {
func now() -> Date
}
public struct SystemDateProvider: DateProvider {
public init() {}
public func now() -> Date { Date() }
}
/// For tests: advance `currentDate` manually to simulate time passage.
public final class TestDateProvider: DateProvider, @unchecked Sendable {
private let lock = NSLock()
private var currentDate: Date
public init(startingAt: Date) { self.currentDate = startingAt }
public func now() -> Date { lock.lock(); defer { lock.unlock() }; return currentDate }
public func advance(by seconds: TimeInterval) {
lock.lock(); defer { lock.unlock() }
currentDate = currentDate.addingTimeInterval(seconds)
}
public func set(_ date: Date) {
lock.lock(); defer { lock.unlock() }
currentDate = date
}
}