Fix glob resolution in catalog directives within included files - #134
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #134 +/- ##
==========================================
+ Coverage 86.25% 86.31% +0.05%
==========================================
Files 92 92
Lines 9880 9950 +70
==========================================
+ Hits 8522 8588 +66
- Misses 886 889 +3
- Partials 472 473 +1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR aims to fix <?catalog?> glob resolution when a catalog directive is brought into another document via <?include?>, by carrying the included file’s directory context forward (via a source-dir parameter) and making the catalog rule resolve globs/front matter relative to that directory.
Changes:
- Include expansion: injects a
source-dirparameter into multi-line processing instructions in included content when inclusion crosses directories. - Catalog rule: resolves globs and reads front matter from a
source-dir-scoped filesystem; prefixes generated filenames so links work from the including file. - Tests: adds coverage for
source-dirinjection and catalog glob/front matter/exclude behavior undersource-dir.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| internal/rules/include/rule.go | Injects source-dir into included processing instructions to preserve directory context for downstream directives. |
| internal/rules/include/rule_test.go | Adds tests validating source-dir injection behavior during include fix. |
| internal/rules/catalog/rule.go | Introduces source-dir-aware glob FS selection and uses it for globbing/front matter, with path prefixing for output filenames. |
| internal/rules/catalog/rule_test.go | Adds tests ensuring catalog globbing/front matter/excludes work correctly when source-dir is provided. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
.github/copilot-instructions.md:27
- Adding
source-dir: "."changes{filename}to be emitted relative to this file’s directory (it will be prefixed with..for.github/). With the currentrow: "- [{summary}](../{filename})", generated links will likely become../../docs/...(double..) instead of the intended../docs/.... Consider updating the row template to link directly to{filename}(or otherwise adjust) now that filenames are source-dir-aware.
<?catalog
source-dir: "."
glob:
- "docs/**/*.md"
- "!docs/research/**"
- "!docs/security/**"
sort: path
header: ""
row: "- [{summary}](../{filename})"
?>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
internal/rules/catalog/rule.go:312
buildCatalogEntriesnow stores the display path (withprefix, which can be ".." whensource-dir: "."is used from a subdirectory) into thefilenamefield. Downstream logic likecheckCatalogIncludeCyclereads files viaf.FSusing thisfilenamevalue; paths containing..are invalid foros.DirFS, so cycle detection will silently stop working for those entries.
Consider keeping a separate internal path for filesystem access (e.g., repo-root-relative path when source-dir is set, or the raw glob match) and update the cycle check to use that, while continuing to use the prefixed display path for links/templates.
for _, p := range files {
displayPath := p
if prefix != "" {
displayPath = path.Join(prefix, p)
}
fields := map[string]any{"filename": displayPath}
if needFM {
for k, v := range readFrontMatter(globFS, p) {
fields[k] = v
}
}
entries = append(entries, fileEntry{fields: fields})
|
Merge queue: CI failed |
When a file containing a <?catalog?> directive is included via <?include?>, the catalog's glob pattern was resolving relative to the including file's directory instead of the included file's directory. Fix: the include rule now injects a source-dir parameter into processing instruction YAML bodies during expansion. The catalog rule reads source-dir and resolves globs from that subdirectory of RootFS, prefixing matched filenames so relative links work from the including file. https://claude.ai/code/session_01VN3XGWEbs4qRPet8qBia59
- Remove includedDir != "." guard so root-level includes get source-dir injection (review comment #1) - Compute display prefix relative to the catalog-owning file's directory via filepath.Rel, so links are correct when the includer is in a subdirectory (review comments #2, #3) - Handle source-dir: "." by using RootFS directly - Remove unused resolveGlobMatches wrapper (lint fix) - Add tests for root-include and sibling-subdir edge cases - Update copilot-instructions.md (mdsmith fix) https://claude.ai/code/session_01VN3XGWEbs4qRPet8qBia59
Add tests for uncovered branches in resolveGlobFS and injectSourceDir: - source-dir: "." with file at root (relPrefix == ".") - source-dir matching file's own directory (no prefix) - source-dir without RootFS (fallback to f.FS) - single-line PIs skipped by injection - PIs that already have source-dir (no double injection) - plain text content with no PIs resolveGlobFS: 78.9% → 89.5% injectSourceDir: 85.3% → 97.1% https://claude.ai/code/session_01VN3XGWEbs4qRPet8qBia59
- Add test for filepath.Rel failure (absolute f.Path, relative source-dir) - Fix fs.Sub error test: use absolute paths for both f.Path and source-dir so Rel succeeds but fs.Sub fails - resolveGlobFS: 89.5% → 100% - injectSourceDir: 97.1% (remaining line is unreachable — goldmark parser never errors) https://claude.ai/code/session_01VN3XGWEbs4qRPet8qBia59
Escape the source-dir value with strconv.Quote so directory names containing quotes or backslashes produce valid YAML. https://claude.ai/code/session_01VN3XGWEbs4qRPet8qBia59
Reject source-dir values containing ".." or absolute paths when computing the gitignore base directory, preventing traversal outside the project root. Mirrors the validation already done by fs.Sub in resolveGlobFS. https://claude.ai/code/session_01VN3XGWEbs4qRPet8qBia59
Update TestFix_RecursiveExpansionSubdir to expect source-dir injection in nested include PIs from subdirectories. Regenerate copilot-instructions.md after CLAUDE.md changes on main. https://claude.ai/code/session_01VN3XGWEbs4qRPet8qBia59
9821310 to
8d714ba
Compare
|
🟢 Merge Queue — picked up This PR is in the queue and will be batched with other Next: No action needed — you'll get another comment when CI starts on the batch. View merge queue run. |
|
🔵 Merge Queue — CI running Merged into batch branch Next: No action needed — you'll be notified when CI completes. |
|
✅ Merge Queue — merged This PR landed on Next: Done — nothing more to do here. |
Summary
This PR fixes glob resolution for catalog directives that are transplanted into documents via file inclusion. When a catalog directive is included from a subdirectory, its glob patterns now correctly resolve relative to that subdirectory rather than the including file's directory.
Key Changes
Include rule enhancement: Added
injectSourceDir()function that automatically injects asource-dirparameter into multi-line processing instructions when content is included from a different directory. This ensures downstream directives (like catalog) know where to resolve globs from.Catalog rule updates:
resolveGlobFS()to determine the correct filesystem and path prefix for glob resolution based on thesource-dirparameterresolveGlobMatches()intoresolveGlobMatchesFrom()to accept an explicit filesystem for glob resolutionbuildCatalogEntries()to use the source-dir-aware filesystem and prefix matched filenames so links resolve correctly from the including fileresolveGitignore()to compute the gitignore base directory relative to source-dir when presentTest coverage: Added comprehensive tests for:
Implementation Details
The solution works by having the include rule detect when content is being included from a different directory and automatically inject a
source-dirparameter into multi-line processing instructions. This parameter is then used by the catalog rule to:The injection is skipped for single-line PIs and when content is wrapped in code fences (where PIs aren't parsed).
https://claude.ai/code/session_01VN3XGWEbs4qRPet8qBia59