Skip to content

release: prepare v0.2.0#19

Merged
gaelic-ghost merged 12 commits into
mainfrom
rag/persist-vector-index
May 10, 2026
Merged

release: prepare v0.2.0#19
gaelic-ghost merged 12 commits into
mainfrom
rag/persist-vector-index

Conversation

@gaelic-ghost
Copy link
Copy Markdown
Owner

@gaelic-ghost gaelic-ghost commented May 7, 2026

Release

  • prepares v0.2.0 from branch rag/persist-vector-index
  • keeps protected main updates behind pull request review and CI
  • release tag v0.2.0 will be created after CI and the review-comment gate pass, so failed or still-discussed release candidates do not get tagged

Review Loop

Before merge and tagging, scripts/repo-maintenance/release.sh watches CI and stops on review comments unless the maintainer has already addressed or resolved them and reruns with --review-comments-addressed.

Summary by CodeRabbit

  • New Features

    • Introduced SwiftlyFetch umbrella library coordinating conventional and semantic search operations
    • Added persistent semantic indexing with configurable storage backends (in-memory and SQLite)
    • Implemented semantic state tracking with automatic retry queueing for failed indexing operations
    • Added macOS persistent library factory with configurable semantic backends (hashing and natural language)
    • Enabled combined search-and-retrieve queries returning conventional and semantic results side-by-side
  • Tests

    • Expanded fixture corpus with additional text sources for test coverage
  • Documentation

    • Updated README with quick-start examples and persistent configuration guidance
    • Added persistence architecture and facade design documentation
  • Chores

    • Enhanced CI workflow runner configuration and release automation resilience

Why:
- add the first SwiftlyFetch product facade for one corpus write feeding FetchKit and RAGKit
- record the settled semantic retry decisions, including delete cleanup retries
- include release and CI hardening already present in the worktree for this branch checkpoint

Verification:
- swift test --filter SwiftlyFetch
- swift test
- scripts/repo-maintenance/validate-all.sh
Why:
- add a literal searchAndRetrieve facade call before any ranked hybrid score policy
- add TinyStories as a second checked-in text source for corpus-based tests
- move corpus fixtures into a shared test fixture target for FetchKit and SwiftlyFetch coverage

Verification:
- swift test --filter 'SwiftlyFetchLibraryTests|FixtureCorpusQualityTests|SearchKitFetchIndexTests'
- scripts/repo-maintenance/validate-all.sh
@gaelic-ghost gaelic-ghost added the enhancement New feature or request label May 7, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: dfb2a933-f173-4302-912d-a7916a988dc1

📥 Commits

Reviewing files that changed from the base of the PR and between 0f6c498 and fea5f2d.

⛔ Files ignored due to path filters (1)
  • docs/media/swiftlyfetch-local-retrieval-promo.mp3 is excluded by !**/*.mp3
📒 Files selected for processing (11)
  • AGENTS.md
  • README.md
  • Sources/RAGKit/SemanticFingerprints.swift
  • Sources/SwiftlyFetch/SwiftlyFetchDocumentMapper.swift
  • Tests/FetchKitTests/SearchKitFetchIndexTests.swift
  • Tests/SwiftlyFetchTests/SwiftlyFetchDocumentMapperTests.swift
  • docs/maintainers/hybrid-search-persistence-plan.md
  • docs/maintainers/retrieval-package-plan.md
  • docs/releases/v0.2.0.md
  • scripts/repo-maintenance/release.sh
  • scripts/repo-maintenance/version-bump.sh

📝 Walkthrough

Walkthrough

This pull request introduces the SwiftlyFetch umbrella facade—a coordinated ingestion surface unifying conventional full-text search via FetchKit with semantic vector search via RAGKit. The change adds semantic index persistence through Core Data, deterministic fingerprinting for semantic change tracking, a retry queue for deferred semantic indexing, expanded test fixtures with a second corpus source, and release/CI infrastructure improvements.

Changes

SwiftlyFetch Umbrella Facade with Semantic Persistence

Layer / File(s) Summary
Data Contracts
Sources/RAGKit/SemanticIndexState.swift, Sources/SwiftlyFetch/SwiftlyFetchSemanticRetry.swift, Sources/SwiftlyFetch/SwiftlyFetchMutationResult.swift
Adds semantic index state/fingerprint/status types, retry model, and mutation/result DTOs.
Semantic Fingerprinting & Component Updates
Sources/RAGKit/SemanticFingerprints.swift, Sources/RAGKit/NaturalLanguageEmbedder.swift, Sources/RAGKit/DefaultChunker.swift, Sources/RAGKit/HeadingAwareMarkdownChunker.swift
Deterministic semanticFingerprint implementations, SemanticFingerprintFactory, StableFNV1A64, and minor chunker/embedder storage/pattern tweaks.
Core Data Vector Index (RAGKit)
Sources/RAGKit/CoreDataVectorIndex.swift
CoreData-backed VectorIndex implementing upsert/search/remove and semantic index state transitions with in-memory/SQLite configuration.
KnowledgeBase Factories & addDocument
Sources/RAGKit/KnowledgeBase+NaturalLanguage.swift, Sources/RAGKit/KnowledgeBase.swift
Public persistent KnowledgeBase factories and addDocument state-tracking (markIndexing/markCurrent/markFailed).
SwiftlyFetch Models & Retry API
Sources/SwiftlyFetch/SwiftlyFetchMutationResult.swift, Sources/SwiftlyFetch/SwiftlyFetchSearchAndRetrieve.swift, Sources/SwiftlyFetch/SwiftlyFetchSemanticRetry.swift
Mutation/result types, search-and-retrieve DTOs, retry store protocol and in-memory actor.
Core Data Retry Store
Sources/SwiftlyFetch/CoreDataSwiftlyFetchSemanticRetryStore.swift
Core Data–backed retry store actor with upsert, ordered pending retrieval, and removal APIs.
Document Mapper & Facade
Sources/SwiftlyFetch/SwiftlyFetchDocumentMapper.swift, Sources/SwiftlyFetch/SwiftlyFetchLibrary.swift
Document mapping and SwiftlyFetchLibrary actor coordinating corpus writes, semantic indexing, retry scheduling/cleanup, search/retrieve, and retry runner.
macOS Persistence Factory
Sources/SwiftlyFetch/SwiftlyFetchLibrary+Persistence.swift
Factory wiring persistent FetchKitLibrary, persistent KnowledgeBase selection, Core Data retry store, and optional retry-on-init.
Package Manifest
Package.swift
Adds SwiftlyFetch product/target, SwiftlyFetchTestFixtures target, and adjusts test target dependencies.
Tests & Fixtures
Tests/SwiftlyFetchTestFixtures/*, Tests/FetchKitTests/*, Tests/RAGKitTests/*, Tests/SwiftlyFetchTests/*
Expose fixtures publicly, add TinyStories mini-corpus, expand tests to cover persistence, semantic state, facade flows, and mapper behavior (includes macOS persistence tests).
Documentation & Maintainer Plans
README.md, ROADMAP.md, AGENTS.md, docs/maintainers/*
README rewrite, roadmap milestone updates, facade/persistence plans, fixture-corpus docs, and AGENTS package guidance.
Release Workflow & CI
.github/workflows/validate-repo-maintenance.yml, scripts/repo-maintenance/*
Pin macOS runner to macos-26, add diagnostics, new remote-ci-mode `full

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • gaelic-ghost/SwiftlyFetch#19: Implements the SwiftlyFetch facade, Core Data persistence, retry store, fixtures, tests, and release/CI changes.

Poem

🐰 "I hopped through code with tiny paws,

I stitched retries and fingerprint laws.
Two corpora now hum in tune,
Persistent vectors beneath the moon.
SwiftlyFetch—quick as a wink of claws!"

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch rag/persist-vector-index

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
AGENTS.md (1)

24-24: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Reconcile the persistence boundary with the new approved architecture.

This file still tells contributors to stop before adding persistence layers, but this PR formalizes persisted semantic index state under RAGKit/SwiftlyFetch. Leaving both statements in place makes the repo’s top-level guidance self-contradictory for the next change. Please carve out the now-approved semantic-persistence exception explicitly instead of keeping the blanket ban unchanged.

Based on learnings: Work is done when the package still builds and tests cleanly, repo-maintenance validation passes, and nearby maintainer docs stay aligned with the code when the implementation meaningfully changes.

Also applies to: 69-72, 103-103

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@AGENTS.md` at line 24, AGENTS.md currently forbids adding persistence but the
PR approves persisted semantic-index state under RAGKit/SwiftlyFetch; update the
top-level guidance to explicitly carve out a semantic-persistence exception by
adding a short clause that permits persisted semantic index state implemented
under the RAGKit/SwiftlyFetch boundary and references the approved pattern, and
then reconcile the other occurrences (around the current guidance at the other
two spots mentioned) so they no longer contradict the exception; ensure the new
wording is concise, mentions RAGKit/SwiftlyFetch by name, and keeps the original
“stop and surface” rule for other scope changes.
🧹 Nitpick comments (5)
Tests/SwiftlyFetchTests/SwiftlyFetchDocumentMapperTests.swift (1)

40-55: ⚡ Quick win

Add one test for non-empty title with .plainText content.

Line 37-39 in the mapper has a distinct path ("Title: …" prefix) that isn’t covered yet. Adding this test closes a real branch gap with minimal effort.

Proposed test addition
 struct SwiftlyFetchDocumentMapperTests {
@@
     `@Test`("Mapper preserves plain text body when title is empty")
     func mapperPreservesPlainTextBodyWhenTitleIsEmpty() {
@@
         `#expect`(document.metadata["contentType"] == .string("plainText"))
     }
+
+    `@Test`("Mapper prefixes plain text content when title is present")
+    func mapperPrefixesPlainTextBodyWhenTitleIsPresent() {
+        let mapper = SwiftlyFetchDocumentMapper()
+        let record = FetchDocumentRecord(
+            id: "doc-note-title",
+            title: "Daily Note",
+            body: "A standalone note.",
+            contentType: .plainText
+        )
+
+        let document = mapper.document(from: record)
+
+        `#expect`(document.content == .text("Title: Daily Note\n\nA standalone note."))
+        `#expect`(document.metadata["title"] == .string("Daily Note"))
+        `#expect`(document.metadata["contentType"] == .string("plainText"))
+    }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Tests/SwiftlyFetchTests/SwiftlyFetchDocumentMapperTests.swift` around lines
40 - 55, Add a complementary unit test that verifies SwiftlyFetchDocumentMapper
handles a non-empty title when contentType is .plainText: create a
FetchDocumentRecord with title set to a non-blank string (e.g., "Note title"),
body set to plain text, and contentType .plainText, call
SwiftlyFetchDocumentMapper.document(from:), and assert the resulting
document.content includes the "Title: …" prefixed text path and that
metadata["title"] contains the title and metadata["contentType"] equals
.string("plainText"); use a descriptive test name like
mapperPreservesPlainTextBodyWhenTitleIsNonEmpty to mirror the existing test.
Tests/SwiftlyFetchTests/SwiftlyFetchLibraryTests.swift (1)

482-496: 💤 Low value

Consider cleaning up temporary test directories.

The temporaryDirectory() helper creates unique directories under the system temp folder but doesn't schedule cleanup. Over many test runs, these directories accumulate. Consider adding cleanup in a deinit or using addTeardownBlock if the test framework supports it, or documenting that manual cleanup may be needed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Tests/SwiftlyFetchTests/SwiftlyFetchLibraryTests.swift` around lines 482 -
496, The temporaryDirectory() helper creates unique temp folders but never
removes them; update the test to schedule cleanup by removing the created
directory after test completion: either modify temporaryDirectory() to register
a teardown (e.g., using addTeardownBlock or the test framework's equivalent)
that calls FileManager.default.removeItem(at:) for the returned URL, or change
callers to receive the URL and explicitly remove it in their teardown. Ensure
error handling/logging is present when removing the directory so failures don't
silently pass.
Tests/RAGKitTests/CoreDataVectorIndexTests.swift (1)

1-5: ⚖️ Poor tradeoff

Consider using Swift Testing instead of XCTest.

As per coding guidelines, tests should prefer Swift Testing by default unless an external constraint requires XCTest. This file uses XCTest, but the tests appear to be straightforward async tests that would work well with Swift Testing's @Test and #expect macros.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Tests/RAGKitTests/CoreDataVectorIndexTests.swift` around lines 1 - 5, The
tests currently import XCTest and define final class CoreDataVectorIndexTests:
XCTestCase; replace XCTest usage with Swift Testing by swapping the import
(import SwiftTesting) and refactoring the test file to use Swift Testing's
style: remove the XCTestCase subclass and replace each test method with a
top-level or struct-scoped `@Test` function (or annotate the test container
accordingly) and use the `#expect` macros for assertions and async expectations;
update any uses of XCTest assertions (XCTAssert*, expectation/wait) to their
Swift Testing equivalents so CoreDataVectorIndexTests and its test functions
compile and run under Swift Testing.
Sources/RAGKit/KnowledgeBase+NaturalLanguage.swift (1)

4-10: 💤 Low value

Consider removing unnecessary async throws from in-memory factory.

hashingDefault creates an InMemoryVectorIndex which doesn't require async initialization or throw. The async throws signature adds unnecessary ceremony for callers.

Suggested simplification
-    static func hashingDefault(dimension: Int = 64) async throws -> KnowledgeBase {
+    static func hashingDefault(dimension: Int = 64) -> KnowledgeBase {
         KnowledgeBase(
             chunker: DefaultChunker(),
             embedder: HashingEmbedder(dimension: dimension),
             index: InMemoryVectorIndex()
         )
     }

Note: This would be a breaking change if callers already use try await. Consider whether API stability or ergonomics is more important here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Sources/RAGKit/KnowledgeBase`+NaturalLanguage.swift around lines 4 - 10,
Remove the unnecessary async/throwing signature from the factory: change static
func hashingDefault(dimension: Int = 64) async throws -> KnowledgeBase to a
synchronous, non-throwing factory (e.g. static func hashingDefault(dimension:
Int = 64) -> KnowledgeBase) because it only constructs DefaultChunker,
HashingEmbedder, and InMemoryVectorIndex (which have no async or throwing init);
update any callers that currently use try/await to call it synchronously, and
ensure the returned KnowledgeBase construction still uses DefaultChunker(),
HashingEmbedder(dimension:), and InMemoryVectorIndex() as before.
Sources/RAGKit/CoreDataVectorIndex.swift (1)

343-372: 💤 Low value

Search loads all chunks into memory before filtering.

The current implementation fetches all stored chunks, then filters and sorts in-memory. This is acceptable for small-to-medium corpora but will become a memory concern as corpus size grows.

For v1 this is pragmatic; consider adding a note or TODO for future optimization (e.g., Core Data fetch batching, pre-filtering by document ID sets, or approximate nearest neighbor indexing).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Sources/RAGKit/CoreDataVectorIndex.swift` around lines 343 - 372, The
search(_ query: SearchQuery, embedding: EmbeddingVector) method currently
fetches all IndexedChunk entities into memory before applying query.filter and
ranking; update the implementation by adding a clear TODO comment inside
CoreDataVectorIndex.search indicating this is a pragmatic v1 approach and should
be optimized later (e.g., use NSFetchRequest batching, predicate pre-filtering
by metadata/document IDs, or integrate an ANN index) and include which parts to
change (the performRead fetch of EntityName.indexedChunk and the in-memory
filtering/ranking pipeline) so future work knows to move filtering/sorting into
the Core Data fetch or replace it with an ANN-backed query.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/maintainers/hybrid-search-persistence-plan.md`:
- Around line 121-123: Update the three bullet items in
hybrid-search-persistence-plan.md to use "Extend" instead of "Add" and rephrase
each to indicate incremental hardening (e.g., "Extend the bridge from
FetchDocumentRecord to RAGCore.Document", "Extend the umbrella library facade to
own one ingestion operation and call both sibling systems", "Extend the
umbrella-owned semantic retry queue keyed by document ID with attempt counts and
next retry dates"); ensure the wording clarifies these are follow-up extensions
rather than net-new features and, if relevant, add a brief note referencing
where roadmap/maintainer updates should be made (docs/maintainers/ or
ROADMAP.md) to reflect the change in milestone scope.

In `@docs/maintainers/retrieval-package-plan.md`:
- Around line 180-181: The bullets at lines mentioning "the one-corpus umbrella
ingestion facade that coordinates `FetchKit` writes and `RAGKit` semantic
indexing" and "umbrella-owned retry scheduling for semantic indexing failures
after a durable corpus write succeeds" understate implemented behavior; update
those two bullets to mark the facade and retry flow as implemented/partially
complete and rephrase to narrow the remaining gap to follow-up lifecycle work
(e.g., indicate that the umbrella ingestion facade and retry scheduling are
shipped, and remaining work is lifecycle/cleanup/edge-case follow-ups). Ensure
you reference the terms "one-corpus umbrella ingestion facade", "FetchKit", and
"RAGKit" in the revised text so readers can map the doc to the code.

In `@README.md`:
- Line 36: Replace the branch-coupled sentence that mentions "`v0.1.2`" and "the
development branch" and references the `SwiftlyFetch` surface with evergreen
wording that avoids specific branch names or versions and instead points readers
to the project's Releases for the current tagged release and status (e.g.,
mention "see Releases for the latest tagged release and status of
SwiftlyFetch"). Ensure the updated line still notes that SwiftlyFetch is
implemented but uses the Releases page as the single source of truth.

In `@Sources/RAGKit/SemanticFingerprints.swift`:
- Around line 98-99: The "double:\(double)" interpolation in the .double case of
SemanticFingerprints is non-deterministic across platforms; replace it with a
deterministic formatter (e.g., use a NumberFormatter configured with en_US_POSIX
or use String(format: Locale(identifier: "en_US_POSIX"), ...) with a chosen
fixed precision/significant-digit setting such as 17 significant digits) so the
string representation is stable across platforms and Swift versions; update the
.double handling to format the Double deterministically rather than relying on
default interpolation.

In `@Sources/SwiftlyFetch/SwiftlyFetchDocumentMapper.swift`:
- Around line 75-83: The normalizedTitle(from record: FetchDocumentRecord)
function currently trims whitespace but leaves internal newlines which can
produce malformed markdown headings; update normalizedTitle to replace all
internal newlines and other line-break sequences with single spaces (e.g., map
"\n", "\r\n", "\r" to " "), then collapse multiple consecutive whitespace into a
single space and trim, returning nil if the result is empty so downstream
templating (heading generation) gets a single-line safe title.

In `@Tests/FetchKitTests/SearchKitFetchIndexTests.swift`:
- Around line 294-301: The test currently asserts the TinyStories result is at
rank 1 by using results.first and specific assertions on it; change this to
search the returned results array for the document with id
"tinystories-row-0-needle" (e.g., use results.first(where: { $0.document.id ==
"tinystories-row-0-needle" }) or XCTAssertTrue(results.contains(where: {
$0.document.id == "..."}))) and then run the matched assertions against that
foundResult (matchedFields contains .body and snippet text contains "needle")
instead of using results.first; keep the same call to
index.search(FetchSearchQuery(...)) and the same assertions but applied to the
located result.

---

Outside diff comments:
In `@AGENTS.md`:
- Line 24: AGENTS.md currently forbids adding persistence but the PR approves
persisted semantic-index state under RAGKit/SwiftlyFetch; update the top-level
guidance to explicitly carve out a semantic-persistence exception by adding a
short clause that permits persisted semantic index state implemented under the
RAGKit/SwiftlyFetch boundary and references the approved pattern, and then
reconcile the other occurrences (around the current guidance at the other two
spots mentioned) so they no longer contradict the exception; ensure the new
wording is concise, mentions RAGKit/SwiftlyFetch by name, and keeps the original
“stop and surface” rule for other scope changes.

---

Nitpick comments:
In `@Sources/RAGKit/CoreDataVectorIndex.swift`:
- Around line 343-372: The search(_ query: SearchQuery, embedding:
EmbeddingVector) method currently fetches all IndexedChunk entities into memory
before applying query.filter and ranking; update the implementation by adding a
clear TODO comment inside CoreDataVectorIndex.search indicating this is a
pragmatic v1 approach and should be optimized later (e.g., use NSFetchRequest
batching, predicate pre-filtering by metadata/document IDs, or integrate an ANN
index) and include which parts to change (the performRead fetch of
EntityName.indexedChunk and the in-memory filtering/ranking pipeline) so future
work knows to move filtering/sorting into the Core Data fetch or replace it with
an ANN-backed query.

In `@Sources/RAGKit/KnowledgeBase`+NaturalLanguage.swift:
- Around line 4-10: Remove the unnecessary async/throwing signature from the
factory: change static func hashingDefault(dimension: Int = 64) async throws ->
KnowledgeBase to a synchronous, non-throwing factory (e.g. static func
hashingDefault(dimension: Int = 64) -> KnowledgeBase) because it only constructs
DefaultChunker, HashingEmbedder, and InMemoryVectorIndex (which have no async or
throwing init); update any callers that currently use try/await to call it
synchronously, and ensure the returned KnowledgeBase construction still uses
DefaultChunker(), HashingEmbedder(dimension:), and InMemoryVectorIndex() as
before.

In `@Tests/RAGKitTests/CoreDataVectorIndexTests.swift`:
- Around line 1-5: The tests currently import XCTest and define final class
CoreDataVectorIndexTests: XCTestCase; replace XCTest usage with Swift Testing by
swapping the import (import SwiftTesting) and refactoring the test file to use
Swift Testing's style: remove the XCTestCase subclass and replace each test
method with a top-level or struct-scoped `@Test` function (or annotate the test
container accordingly) and use the `#expect` macros for assertions and async
expectations; update any uses of XCTest assertions (XCTAssert*,
expectation/wait) to their Swift Testing equivalents so CoreDataVectorIndexTests
and its test functions compile and run under Swift Testing.

In `@Tests/SwiftlyFetchTests/SwiftlyFetchDocumentMapperTests.swift`:
- Around line 40-55: Add a complementary unit test that verifies
SwiftlyFetchDocumentMapper handles a non-empty title when contentType is
.plainText: create a FetchDocumentRecord with title set to a non-blank string
(e.g., "Note title"), body set to plain text, and contentType .plainText, call
SwiftlyFetchDocumentMapper.document(from:), and assert the resulting
document.content includes the "Title: …" prefixed text path and that
metadata["title"] contains the title and metadata["contentType"] equals
.string("plainText"); use a descriptive test name like
mapperPreservesPlainTextBodyWhenTitleIsNonEmpty to mirror the existing test.

In `@Tests/SwiftlyFetchTests/SwiftlyFetchLibraryTests.swift`:
- Around line 482-496: The temporaryDirectory() helper creates unique temp
folders but never removes them; update the test to schedule cleanup by removing
the created directory after test completion: either modify temporaryDirectory()
to register a teardown (e.g., using addTeardownBlock or the test framework's
equivalent) that calls FileManager.default.removeItem(at:) for the returned URL,
or change callers to receive the URL and explicitly remove it in their teardown.
Ensure error handling/logging is present when removing the directory so failures
don't silently pass.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8e220ad2-537d-41f6-b71d-4acdcf200c1b

📥 Commits

Reviewing files that changed from the base of the PR and between 3352bc0 and 646dd9e.

📒 Files selected for processing (36)
  • .github/workflows/validate-repo-maintenance.yml
  • AGENTS.md
  • Package.swift
  • README.md
  • ROADMAP.md
  • Sources/RAGKit/CoreDataVectorIndex.swift
  • Sources/RAGKit/DefaultChunker.swift
  • Sources/RAGKit/HeadingAwareMarkdownChunker.swift
  • Sources/RAGKit/KnowledgeBase+NaturalLanguage.swift
  • Sources/RAGKit/KnowledgeBase.swift
  • Sources/RAGKit/NaturalLanguageEmbedder.swift
  • Sources/RAGKit/SemanticFingerprints.swift
  • Sources/RAGKit/SemanticIndexState.swift
  • Sources/SwiftlyFetch/CoreDataSwiftlyFetchSemanticRetryStore.swift
  • Sources/SwiftlyFetch/SwiftlyFetchDocumentMapper.swift
  • Sources/SwiftlyFetch/SwiftlyFetchLibrary+Persistence.swift
  • Sources/SwiftlyFetch/SwiftlyFetchLibrary.swift
  • Sources/SwiftlyFetch/SwiftlyFetchMutationResult.swift
  • Sources/SwiftlyFetch/SwiftlyFetchSearchAndRetrieve.swift
  • Sources/SwiftlyFetch/SwiftlyFetchSemanticRetry.swift
  • Tests/FetchKitTests/FixtureCorpusQualityTests.swift
  • Tests/FetchKitTests/SearchKitFetchIndexTests.swift
  • Tests/RAGKitTests/CoreDataVectorIndexTests.swift
  • Tests/SwiftlyFetchTestFixtures/GutenbergMiniCorpus.swift
  • Tests/SwiftlyFetchTestFixtures/TinyStoriesMiniCorpus.swift
  • Tests/SwiftlyFetchTests/SwiftlyFetchDocumentMapperTests.swift
  • Tests/SwiftlyFetchTests/SwiftlyFetchLibraryTests.swift
  • docs/maintainers/fixture-corpus.md
  • docs/maintainers/hybrid-search-persistence-plan.md
  • docs/maintainers/retrieval-package-plan.md
  • docs/maintainers/swiftlyfetch-facade-plan.md
  • scripts/repo-maintenance/config/release.env
  • scripts/repo-maintenance/lib/common.sh
  • scripts/repo-maintenance/release.sh
  • scripts/repo-maintenance/release/30-push-release.sh
  • scripts/repo-maintenance/release/40-github-release.sh

Comment thread docs/maintainers/hybrid-search-persistence-plan.md Outdated
Comment thread docs/maintainers/retrieval-package-plan.md Outdated
Comment thread README.md Outdated
Comment thread Sources/RAGKit/SemanticFingerprints.swift Outdated
Comment thread Sources/SwiftlyFetch/SwiftlyFetchDocumentMapper.swift
Comment thread Tests/FetchKitTests/SearchKitFetchIndexTests.swift
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 646dd9ea97

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/repo-maintenance/release.sh Outdated

review_decision="$(gh pr view "$pr_number" --json reviewDecision --jq '.reviewDecision // ""')"
comment_count="$(gh pr view "$pr_number" --json comments,reviews --jq '([.comments[]?, .reviews[]?] | length)')"
comment_count="$(gh pr view "$pr_number" --json comments,reviews --jq '([.comments[]?, (.reviews[]? | select(.state == "COMMENTED"))] | length)')"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include approved review comments in PR comment gate

The comment gate now counts only issue comments and reviews whose state is COMMENTED, so reviews submitted as APPROVED with a non-empty review body are ignored. In this workflow, that lets release.sh proceed without --review-comments-addressed even when a reviewer left actionable review comments alongside approval, which contradicts the script’s own “review or discussion comments” stop condition and can cause releases to bypass intended comment triage.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0f6c498bb3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/repo-maintenance/release.sh Outdated

while :; do
last_state="$(gh pr checks "$pr_number" --json name,state,workflow --jq 'map(.name + ":" + .state) | join(", ")' 2>/dev/null || printf 'no checks reported')"
check_count="$(gh pr checks "$pr_number" --json name,state,workflow --jq 'length' 2>/dev/null || printf '0')"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Treat pending PR checks as discovered

wait_for_initial_pr_checks currently appends a fallback printf '0' when gh pr checks ... --jq 'length' exits non-zero, but gh pr checks documents exit code 8 for pending checks. In that common state, the command can output a valid length and still exit 8, so the fallback corrupts check_count (e.g., "3\n0"), the numeric guard resets it to 0, and the loop can incorrectly timeout after 120s even though checks were already discovered. This can make standard/deferred release runs fail on normal CI startup latency.

Useful? React with 👍 / 👎.

@gaelic-ghost gaelic-ghost changed the title Add SwiftlyFetch umbrella facade and semantic persistence release: prepare v0.2.0 May 10, 2026
@gaelic-ghost gaelic-ghost merged commit 0048e8e into main May 10, 2026
1 check passed
@gaelic-ghost gaelic-ghost deleted the rag/persist-vector-index branch May 10, 2026 03:39
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fea5f2d32b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 465 to +468
merge_pr "$pr_number"
fast_forward_base_branch
create_release_tag
push_release_tag
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep post-merge release steps resumable

Move the tag/release creation before the branch is merged, or relax the branch-context guard for resume paths. In this flow, merge_pr runs before create_release_tag/push_release_tag/create_github_release, and gh pr merge --delete-branch is documented to delete the local and remote branch; if any post-merge step fails (e.g., transient GitHub/API failure), rerunning release.sh is blocked by ensure_branch_release_context because the script has already switched to main and the release branch may be gone. That leaves a merged PR without a tag/release and no straightforward recovery path through the same command.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant