diff --git a/CHANGELOG.md b/CHANGELOG.md index 874823c..d752910 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,18 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +## [0.4.1] - 2026-08-20 + +Release validation no longer races an FSEvents stream rearm when a watched +session-store root appears for the first time. + +### Fixed +- **Late-root FSEvents integration coverage is deterministic.** The test now + waits until the watcher has narrowed from the nearest existing ancestor to + the newly created root before writing its probe file, matching the + production restart/rescan contract and removing the stream teardown/startup + gap from the assertion. + ## [0.4.0] - 2026-08-20 Session indexing becomes a reusable, role-aware host capability with related diff --git a/Sources/AgentSessionKit/AgentSessionKitInfo.swift b/Sources/AgentSessionKit/AgentSessionKitInfo.swift index 6aacc5b..4b0301c 100644 --- a/Sources/AgentSessionKit/AgentSessionKitInfo.swift +++ b/Sources/AgentSessionKit/AgentSessionKitInfo.swift @@ -19,7 +19,7 @@ public enum AgentSessionKitInfo { /// /// Semver, bare — no `v` prefix, matching the tags. Bumping it is part /// of the release commit; see `RELEASING.md`. - public static let version = "0.4.0" + public static let version = "0.4.1" /// Where the package lives. Public because a host that shows the /// version usually wants somewhere to send the reader. diff --git a/Tests/AgentSessionLiveTests/FSEventsWatcherTests.swift b/Tests/AgentSessionLiveTests/FSEventsWatcherTests.swift index 29d64ed..853eae9 100644 --- a/Tests/AgentSessionLiveTests/FSEventsWatcherTests.swift +++ b/Tests/AgentSessionLiveTests/FSEventsWatcherTests.swift @@ -115,6 +115,15 @@ struct FSEventsWatcherTests { #expect(earlyWatch.first?.hasSuffix(tree.url.lastPathComponent) == true) try FileManager.default.createDirectory(at: late, withIntermediateDirectories: true) + + // Directory creation can itself trigger the rearm. Wait for that + // narrower stream before writing the file: writing in the teardown / + // startup gap makes the assertion depend on whether the runner's + // FSEvents callback or the test task wins the same scheduler turn. + #expect(await waitUntil(timeout: .seconds(3)) { + watcher.currentWatchPaths().first?.hasSuffix("not/there/yet") == true + }) + let target = late.appendingPathComponent("session.jsonl") try Data("late\n".utf8).write(to: target) @@ -122,10 +131,7 @@ struct FSEventsWatcherTests { await batch(watcher, containing: target.path), "FSEvents delivered nothing for a late root within \(patience)") - // And once it exists, the watch narrows onto it. - #expect(await waitUntil(timeout: .seconds(3)) { - watcher.currentWatchPaths().first?.hasSuffix("not/there/yet") == true - }) + #expect(watcher.currentWatchPaths().first?.hasSuffix("not/there/yet") == true) } @Test("the shipped default flags see another process's writes")