Skip to content

Explain file discovery ranking and clarify live gate#70

Merged
gaelic-ghost merged 2 commits into
mainfrom
runtime/file-discovery-hit-metadata
May 7, 2026
Merged

Explain file discovery ranking and clarify live gate#70
gaelic-ghost merged 2 commits into
mainfrom
runtime/file-discovery-hit-metadata

Conversation

@gaelic-ghost
Copy link
Copy Markdown
Owner

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

Summary

  • add UI-ready match metadata to CodexFS file-discovery hits
  • document file-discovery highlighting and ranking explanations
  • clarify the live release gate and make the live timeout override effective

Verification

  • swift test
  • git diff --check
  • sh -n scripts/run-live-codex-integration-tests.sh
  • sh -n scripts/run-live-codex-release-gate.sh
  • scripts/run-live-codex-integration-tests.sh help
  • bash scripts/repo-maintenance/validate-all.sh
  • scripts/run-live-codex-integration-tests.sh all
  • GitHub validate check

Summary by CodeRabbit

Release Notes

  • New Features

    • File discovery now provides UI-ready search metadata including match kind, matched character ranges in filenames and paths, and ranking reasons to explain result ordering.
  • Documentation

    • Updated guides to reflect enhanced file discovery capabilities and new configurable timeout support for integration tests.
  • Chores

    • Added environment variable support to override integration test operation timeouts.

@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

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds structured match metadata to file discovery results and makes integration test timeouts configurable. FileDiscoveryHit now provides UI-ready match kind, highlighted character ranges for filenames and paths, and ranking reasons explaining result ordering. The fuzzy-matching algorithm was rewritten to compute these artifacts. Integration tests gain timeout flexibility via an environment variable.

Changes

CodexFS File Discovery Match Metadata

Layer / File(s) Summary
Match Data Types
Sources/SwiftASB/Public/CodexFS.swift
New public enums/structs added: MatchKind (six match type cases), MatchRange (start and length), RankingReason with nested Kind (nine scoring reason cases). FileDiscoveryHit adds matchKind, matchedFileNameRanges, matchedRelativePathRanges, and rankingReasons properties.
Fuzzy Matching Implementation
Sources/SwiftASB/Public/CodexFS.swift
New fuzzyMatch(query:relativePath:) pipeline computes match kind, per-field character ranges, ranking signals, and adjusted score. subsequenceScore updated to track boundary matches and offsets. New matchRanges helper converts character offsets into contiguous highlight segments. Internal FileDiscoveryMatch and SubsequenceMatch structs added.
Hit Collection
Sources/SwiftASB/Public/CodexFS.swift
Directory traversal loop now uses structured fuzzyMatch result to populate hit's match metadata, match kind, and ranking reasons.
File System Tests
Tests/SwiftASBTests/Public/CodexAppServerFileSystemTests.swift
Test assertions validate matchKind, exact matchedFileNameRanges and matchedRelativePathRanges arrays, and presence of expected ranking-reason kinds (e.g., relativePathSubsequence, generatedPathPenalty).
API Documentation
Sources/SwiftASB/SwiftASB.docc/CodexFS.md
Documents that FileDiscoveryHit includes UI-ready search metadata when a search term is provided, including match kind, matched ranges for highlighting, and ranking reasons.
README and Roadmap
README.md, ROADMAP.md
Updated usage guide with details on filesystem metadata, discovery/fuzzy lookup, and match information. Roadmap extended to include filesystem watch notifications and marks richer metadata as "soon." New 2026-05-07 history entry announces UI-ready match metadata.

Configurable Integration Test Timeouts

Layer / File(s) Summary
Timeout Helper Function
Tests/SwiftASBTests/Public/CodexAppServerLiveIntegrationTestSupport.swift
New liveTimeoutSeconds(default:) helper reads SWIFTASB_LIVE_CODEX_TIMEOUT_SECONDS environment variable, validates as positive Double, and falls back to provided default when unset or invalid.
Test Support Wiring
Tests/SwiftASBTests/Public/CodexAppServerLiveIntegrationTestSupport.swift
Approval probe, behavior matrix, and same-thread matrix probe functions adopt liveTimeoutSeconds(default:) for their completion wait timeouts.
Integration Test Updates
Tests/SwiftASBTests/Public/CodexAppServerLiveIntegrationTests.swift
Multiple live integration tests replace hardcoded timeoutSeconds literals (45, 90) with liveTimeoutSeconds(default: 45) or liveTimeoutSeconds(default: 90) across single-turn, cross-thread, rollback, and history materialization tests.
Configuration Documentation
CONTRIBUTING.md, scripts/run-live-codex-integration-tests.sh, scripts/run-live-codex-release-gate.sh, ROADMAP.md
Environment variable SWIFTASB_LIVE_CODEX_TIMEOUT_SECONDS documented in contributor guide and test scripts. Roadmap and release-gate script updated with expanded probe sequence labels and timeout env-var support mention.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • gaelic-ghost/SwiftASB#69: Modifies the same fuzzy-matching and scoring logic in CodexFS.swift, introducing structured match data computation.

Poem

🐰 A discovery so fine, with ranges that shine,
Match kinds now UI-bound, where highlights align.
Ranking reasons declared with each file's embrace,
And timeouts set loose—no hardcode in place!
The swift paths now sparkle with metadata's grace. 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately captures the main changes: adding file discovery ranking metadata and clarifying the live gate configuration.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 runtime/file-discovery-hit-metadata

Comment @coderabbitai help to get the list of available commands and usage tips.

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: 50d17e0dbc

ℹ️ 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 +511 to +513
if pathMatch.hasBoundaryMatch {
reasons.append(.init(kind: .pathBoundaryMatch, value: 8))
}
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 Report boundary bonus as an exact score contribution

rankingReasons is documented as carrying per-signal score contributions, but pathBoundaryMatch is emitted as a fixed +8 whenever any boundary match occurs, while the boundary bonus is already folded into subsequenceScore (and may be applied multiple times for one match). For queries that hit several boundaries (for example acronyms across path segments), the exposed reason values become inconsistent with the actual score and can mislead UIs that explain or total contributions from rankingReasons.

Useful? React with 👍 / 👎.

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: 1

🧹 Nitpick comments (2)
README.md (1)

50-50: ⚡ Quick win

Split this usage paragraph into shorter bullets for readability.

The content is valuable, but this single line is hard to scan and feels maintainer-dense for first-time users.

Proposed doc-only rewrite
-Use `CodexAppServer.fs` when a sandboxed client needs filesystem metadata, directory listings, file bytes, file discovery, fuzzy file lookup, or file-change watches through the Codex app-server instead of reading local disk directly. File-discovery hits include match kind, matched character ranges, and ranking reasons for picker highlighting and result explanations. `CodexWorkspace` carries app-server-owned workspace permission selections, active permission-profile provenance, and runtime filesystem/network permission facts for started threads and turns. Use `CodexAppServer.config` for effective config reads, and `CodexAppServer.extensions` for app, skill, plugin, and collaboration-mode inventory.
+Use `CodexAppServer.fs` when a sandboxed client needs filesystem metadata, directory listings, file bytes, discovery, fuzzy lookup, or file-change watches without reading local disk directly.
+
+Discovery hits include match kind, matched character ranges, and ranking reasons so picker UIs can highlight and explain ordering.
+
+Use:
+- `CodexWorkspace` for workspace permission selections, permission-profile provenance, and runtime filesystem/network permission facts.
+- `CodexAppServer.config` for effective config reads.
+- `CodexAppServer.extensions` for app, skill, plugin, and collaboration-mode inventory.
As per coding guidelines, "Keep the README product-facing and approachable for package users and their agents".
🤖 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 `@README.md` at line 50, Split the long single-sentence paragraph into a short
bulleted list for readability: create separate bullets for (1) CodexAppServer.fs
responsibilities (filesystem metadata, directory listings, file bytes, file
discovery, fuzzy file lookup, file-change watches via the app-server), and note
that file-discovery hits include match kind, matched character ranges, and
ranking reasons for picker highlighting; (2) CodexWorkspace purpose
(app-server-owned workspace permission selections, active permission-profile
provenance, and runtime filesystem/network permission facts for started threads
and turns); (3) configuration access via CodexAppServer.config for effective
config reads; and (4) inventory via CodexAppServer.extensions for app, skill,
plugin, and collaboration-mode listings — keep each bullet short and
user-facing.
ROADMAP.md (1)

1226-1228: 💤 Low value

Minor wording inconsistency in completed backlog item.

The word "soon" is leftover from when this was a TODO. Now that it's marked complete [x], it reads awkwardly as "Add richer ... search metadata soon".

Consider removing "soon" for clarity:

-- [x] Add richer `CodexFS.FileDiscoveryHit` search metadata soon, including
+- [x] Add richer `CodexFS.FileDiscoveryHit` search metadata, including
🤖 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 `@ROADMAP.md` around lines 1226 - 1228, The completed checklist item "Add
richer `CodexFS.FileDiscoveryHit` search metadata soon, including match kind,
matched ranges, or ranking reason once UI highlighting needs an explicit public
model." reads awkwardly; remove "soon" and update tense to match the checked
state—e.g., change to "Added richer `CodexFS.FileDiscoveryHit` search metadata,
including match kind, matched ranges, or ranking reason" or simply remove "soon"
to read "Add richer `CodexFS.FileDiscoveryHit` search metadata, including...".
🤖 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 `@Tests/SwiftASBTests/Public/CodexAppServerLiveIntegrationTestSupport.swift`:
- Around line 2211-2219: The liveTimeoutSeconds(default:) function currently
accepts positive Double values from the environment but doesn't exclude
infinity; update the guard in liveTimeoutSeconds to require seconds.isFinite (in
addition to seconds > 0) so that infinite values from
ProcessInfo.processInfo.environment["SWIFTASB_LIVE_CODEX_TIMEOUT_SECONDS"] are
rejected and the defaultSeconds returned, preventing overflow when the value is
later converted to nanoseconds (see withTimeout(seconds:operation:) and the
UInt64(seconds * 1_000_000_000) conversion).

---

Nitpick comments:
In `@README.md`:
- Line 50: Split the long single-sentence paragraph into a short bulleted list
for readability: create separate bullets for (1) CodexAppServer.fs
responsibilities (filesystem metadata, directory listings, file bytes, file
discovery, fuzzy file lookup, file-change watches via the app-server), and note
that file-discovery hits include match kind, matched character ranges, and
ranking reasons for picker highlighting; (2) CodexWorkspace purpose
(app-server-owned workspace permission selections, active permission-profile
provenance, and runtime filesystem/network permission facts for started threads
and turns); (3) configuration access via CodexAppServer.config for effective
config reads; and (4) inventory via CodexAppServer.extensions for app, skill,
plugin, and collaboration-mode listings — keep each bullet short and
user-facing.

In `@ROADMAP.md`:
- Around line 1226-1228: The completed checklist item "Add richer
`CodexFS.FileDiscoveryHit` search metadata soon, including match kind, matched
ranges, or ranking reason once UI highlighting needs an explicit public model."
reads awkwardly; remove "soon" and update tense to match the checked state—e.g.,
change to "Added richer `CodexFS.FileDiscoveryHit` search metadata, including
match kind, matched ranges, or ranking reason" or simply remove "soon" to read
"Add richer `CodexFS.FileDiscoveryHit` search metadata, including...".
🪄 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: ba5d4341-558b-49b6-9a48-92c9dc7b1ecd

📥 Commits

Reviewing files that changed from the base of the PR and between 49f1057 and 50d17e0.

📒 Files selected for processing (10)
  • CONTRIBUTING.md
  • README.md
  • ROADMAP.md
  • Sources/SwiftASB/Public/CodexFS.swift
  • Sources/SwiftASB/SwiftASB.docc/CodexFS.md
  • Tests/SwiftASBTests/Public/CodexAppServerFileSystemTests.swift
  • Tests/SwiftASBTests/Public/CodexAppServerLiveIntegrationTestSupport.swift
  • Tests/SwiftASBTests/Public/CodexAppServerLiveIntegrationTests.swift
  • scripts/run-live-codex-integration-tests.sh
  • scripts/run-live-codex-release-gate.sh

Comment on lines +2211 to +2219
func liveTimeoutSeconds(default defaultSeconds: Double) -> Double {
guard let rawValue = ProcessInfo.processInfo.environment["SWIFTASB_LIVE_CODEX_TIMEOUT_SECONDS"],
let seconds = Double(rawValue),
seconds > 0
else {
return defaultSeconds
}
return seconds
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n -C2 'SWIFTASB_LIVE_CODEX_TIMEOUT_SECONDS|Double\\(rawValue\\)|seconds > 0|UInt64\\(seconds \\* 1_000_000_000\\)' --type=swift

Repository: gaelic-ghost/SwiftASB

Length of output: 893


🏁 Script executed:

rg -n 'liveTimeoutSeconds' Tests/SwiftASBTests/Public/CodexAppServerLiveIntegrationTestSupport.swift -A 10

Repository: gaelic-ghost/SwiftASB

Length of output: 2250


🏁 Script executed:

rg -n '1_000_000_000|nanosecond|timeout' Tests/SwiftASBTests/Public/CodexAppServerLiveIntegrationTestSupport.swift --type=swift

Repository: gaelic-ghost/SwiftASB

Length of output: 1433


🏁 Script executed:

sed -n '2195,2210p' Tests/SwiftASBTests/Public/CodexAppServerLiveIntegrationTestSupport.swift

Repository: gaelic-ghost/SwiftASB

Length of output: 520


🏁 Script executed:

python3 << 'EOF'
import sys
# Test if UInt64(Double.infinity * multiplier) crashes
try:
    result = int(float('inf') * 1_000_000_000)
    print(f"Result: {result}")
except Exception as e:
    print(f"Error: {type(e).__name__}: {e}")

# Also test conversion directly
try:
    result = int(float('inf'))
    print(f"Direct inf to int: {result}")
except Exception as e:
    print(f"Error on direct conversion: {type(e).__name__}: {e}")
EOF

Repository: gaelic-ghost/SwiftASB

Length of output: 212


Add isFinite check before returning timeout value to prevent infinity values from crashing in nanosecond conversion.

The liveTimeoutSeconds() function accepts any positive Double from environment parsing, including infinity (if set to "inf"). This value is later passed to withTimeout(seconds:operation:) at line 1718/1734/1755/1773, which converts it to nanoseconds via UInt64(seconds * 1_000_000_000) at line 2201. Converting infinity to UInt64 crashes with an overflow error.

The seconds > 0 check alone is insufficient because infinity > 0 evaluates to true. Add seconds.isFinite to the guard condition.

Proposed fix
 func liveTimeoutSeconds(default defaultSeconds: Double) -> Double {
     guard let rawValue = ProcessInfo.processInfo.environment["SWIFTASB_LIVE_CODEX_TIMEOUT_SECONDS"],
           let seconds = Double(rawValue),
+          seconds.isFinite,
           seconds > 0
     else {
         return defaultSeconds
     }
     return seconds
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func liveTimeoutSeconds(default defaultSeconds: Double) -> Double {
guard let rawValue = ProcessInfo.processInfo.environment["SWIFTASB_LIVE_CODEX_TIMEOUT_SECONDS"],
let seconds = Double(rawValue),
seconds > 0
else {
return defaultSeconds
}
return seconds
}
func liveTimeoutSeconds(default defaultSeconds: Double) -> Double {
guard let rawValue = ProcessInfo.processInfo.environment["SWIFTASB_LIVE_CODEX_TIMEOUT_SECONDS"],
let seconds = Double(rawValue),
seconds.isFinite,
seconds > 0
else {
return defaultSeconds
}
return seconds
}
🤖 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/SwiftASBTests/Public/CodexAppServerLiveIntegrationTestSupport.swift`
around lines 2211 - 2219, The liveTimeoutSeconds(default:) function currently
accepts positive Double values from the environment but doesn't exclude
infinity; update the guard in liveTimeoutSeconds to require seconds.isFinite (in
addition to seconds > 0) so that infinite values from
ProcessInfo.processInfo.environment["SWIFTASB_LIVE_CODEX_TIMEOUT_SECONDS"] are
rejected and the defaultSeconds returned, preventing overflow when the value is
later converted to nanoseconds (see withTimeout(seconds:operation:) and the
UInt64(seconds * 1_000_000_000) conversion).

@gaelic-ghost gaelic-ghost merged commit 546dadc into main May 7, 2026
2 checks passed
@gaelic-ghost gaelic-ghost deleted the runtime/file-discovery-hit-metadata branch May 7, 2026 20:54
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