Simplify scope root normalization for nested extension roots#3720
Merged
Conversation
reakaleek
approved these changes
Jul 24, 2026
Filter extension roots against WorkingDirectoryRoot using the existing IsSubPathOf extension instead of a generic shortest-first normalizer. WorkingDirectoryRoot and ApplicationData are fixed and always disjoint; only extension roots can collide, so only they need filtering. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com>
Mpdreamz
force-pushed
the
simplify-scope-root-normalization
branch
from
July 24, 2026 11:40
2685be6 to
a43362e
Compare
Mpdreamz
enabled auto-merge (squash)
July 24, 2026 11:48
Mpdreamz
added a commit
that referenced
this pull request
Jul 24, 2026
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com>
Mpdreamz
added a commit
that referenced
this pull request
Jul 24, 2026
* Emit Mermaid diagrams as external SVG files loaded via img (#3713) Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> * Fix CopyBrandingResources failure during serve in-memory build (#3718) Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com> * Fix overlapping scope roots for nested Codex config paths (#3719) docs-builder 1.29.0 added extension roots from FindGitRoot for Codex commands. When config.yml lives under environments/internal/, the resolved root is nested inside WorkingDirectoryRoot and ScopedFileSystem rejects the overlapping roots. Normalize extension roots before constructing the scoped filesystem so redundant nested paths are dropped. Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com> * Simplify scope root normalization for nested extension roots (#3720) Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com> * Replace pagefind native binary with Pagefind.Net managed library Replace PR #3709's native pagefind binary subprocess approach with the Pagefind.Net and Pagefind.Net.Frontend NuGet packages — pure managed .NET, no native binary, AOT-compatible. The pagefind indexer is now a proper IMarkdownExporter that eagerly indexes each page during ExportAsync (O(1) memory) and flushes the index to disk in FinishExportAsync. It is included in both ExportOptions.Default and ExportOptions.Validation, so it works in isolated builds and docs-builder serve mode automatically. Key changes: - New PagefindMarkdownExporter in Elastic.Markdown/Exporters/Pagefind - New Exporter.Pagefind enum value, registered in both ExporterParsers - Removed native binary pipeline (package-pagefind.mjs, embedded resource, pagefind npm dep, PagefindSearchIndexer subprocess) - Removed static-search feature flag — search is always available for isolated builds and serve mode - Serve mode reads pagefind files from the background build's in-memory filesystem via a route handler - Added .pagefind-net-frontend-version to AllowedHiddenFileNames Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Jan Calanog <jan.calanog@elastic.co>
Mpdreamz
added a commit
that referenced
this pull request
Jul 25, 2026
* Emit Mermaid diagrams as external SVG files loaded via img (#3713) Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> * Fix CopyBrandingResources failure during serve in-memory build (#3718) Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com> * Fix overlapping scope roots for nested Codex config paths (#3719) docs-builder 1.29.0 added extension roots from FindGitRoot for Codex commands. When config.yml lives under environments/internal/, the resolved root is nested inside WorkingDirectoryRoot and ScopedFileSystem rejects the overlapping roots. Normalize extension roots before constructing the scoped filesystem so redundant nested paths are dropped. Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com> * Simplify scope root normalization for nested extension roots (#3720) Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com> * Replace pagefind native binary with Pagefind.Net managed library Replace PR #3709's native pagefind binary subprocess approach with the Pagefind.Net and Pagefind.Net.Frontend NuGet packages — pure managed .NET, no native binary, AOT-compatible. The pagefind indexer is now a proper IMarkdownExporter that eagerly indexes each page during ExportAsync (O(1) memory) and flushes the index to disk in FinishExportAsync. It is included in both ExportOptions.Default and ExportOptions.Validation, so it works in isolated builds and docs-builder serve mode automatically. Key changes: - New PagefindMarkdownExporter in Elastic.Markdown/Exporters/Pagefind - New Exporter.Pagefind enum value, registered in both ExporterParsers - Removed native binary pipeline (package-pagefind.mjs, embedded resource, pagefind npm dep, PagefindSearchIndexer subprocess) - Removed static-search feature flag — search is always available for isolated builds and serve mode - Serve mode reads pagefind files from the background build's in-memory filesystem via a route handler - Added .pagefind-net-frontend-version to AllowedHiddenFileNames Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Jan Calanog <jan.calanog@elastic.co>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Follow-up to #3719. That PR fixes the
ScopedFileSystemdisjoint-roots crash for nested Codex configs by introducing a genericNormalizeDisjointRootsthat sorts all roots by length and collapses parent–child pairs. This treatsWorkingDirectoryRoot,ApplicationData, and extension roots as equals, butWorkingDirectoryRootandApplicationDataare fixed and always disjoint — only extension roots can collide withWorkingDirectoryRoot.Root cause
The
codex-environmentsrepo has configs nested inside the checkout:When a Codex command runs, it calls:
FindGitRootstarts from the config file's directory and walks up looking for.git, but has a depth-1 limit in release builds. The.gitis 2 levels up:Since
.gitis "too deep",FindGitRootfalls back to returningstartDir— the config's own directory:Now the original
ScopeCurrentWorkingDirectorybuilds scope roots:.Distinct()doesn't remove anything (they're different strings).roots.Length == 3 ≠ 2, so it doesn't hit the fast path.ScopedFileSystemthen enforces that all scope roots must be disjoint (no parent–child relationships):ScopedFileSystemthrows here by design — nested roots create policy ambiguity (which root's hidden-file/folder allowlist wins?), so the library forces callers to provide disjoint roots.What
Replace the generic shortest-first normalizer from #3719 with a targeted filter: drop extension roots that are already covered by
WorkingDirectoryRootusing the existingIsSubPathOfextension. No new helper methods needed.Includes the same two regression tests from #3719 (nested in-repo config, genuinely external config root).