Skip to content

Commit 845feb8

Browse files
[AI] Add file.folder support for Obsidian-compatible filtering
1 parent 6251a1e commit 845feb8

5 files changed

Lines changed: 50 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ When asked to create commits in this repository:
106106
## Compatibility Notes
107107

108108
- `this` context is deterministic CLI/library metadata (`filePath`, `name`) rather than Obsidian embed-location semantics.
109+
- `file.folder` is supported and resolves to the vault-relative parent directory (`""` for root-level notes).
109110
- `file.backlinks` is not implemented in v0 (reserved for future opt-in indexing pass).
110111
- CSV serialisation uses the selected/declared column list as the canonical header order.
111112

@@ -120,3 +121,8 @@ When asked to create commits in this repository:
120121
- Context: Query portability requires predictable failures on unknown symbols.
121122
- Decision: Enable strict mode by default in API and CLI.
122123
- Consequence: Users must opt out (`--no-strict`) for permissive behaviour.
124+
125+
- 2026-02-18 - `file.folder` compatibility support
126+
- Context: Real-world Base filters often rely on `file.folder` to scope notes by directory.
127+
- Decision: Add `file.folder` to indexed file metadata as the vault-relative parent path.
128+
- Consequence: Queries depending on folder-based filtering now evaluate correctly without strict-mode property errors.

src/core/vault-index.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,16 @@ function isMarkdown(path: string): boolean {
4040
return path.toLowerCase().endsWith(".md");
4141
}
4242

43+
function folderFromPath(path: string): string {
44+
const slashIndex = path.lastIndexOf("/");
45+
46+
if (slashIndex === -1) {
47+
return "";
48+
}
49+
50+
return path.slice(0, slashIndex);
51+
}
52+
4353
function sortEntries(entries: RuntimeFileEntry[]): RuntimeFileEntry[] {
4454
return [...entries].sort((left, right) => left.path.localeCompare(right.path));
4555
}
@@ -73,6 +83,7 @@ export async function indexVault(options: VaultIndexOptions): Promise<VaultIndex
7383
file: {
7484
name: options.adapter.basename(relativePath),
7585
path: relativePath,
86+
folder: folderFromPath(relativePath),
7687
ext: options.adapter.extname(relativePath),
7788
size: entry.stat.size,
7889
ctime: entry.stat.ctime,

src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export interface QueryRow {
7171
export interface FileRecord {
7272
name: string;
7373
path: string;
74+
folder: string;
7475
ext: string;
7576
size: number;
7677
ctime: Date;

tests/query-engine.test.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,35 @@ views:
105105
expect(result.rows[1].projected.title).toBe("Alpha");
106106
expect(result.groups?.length).toBe(1);
107107
});
108+
109+
test("supports file.folder in filters and projections", async () => {
110+
const spec = parseBaseYaml(`
111+
filters: file.folder == "nested"
112+
views:
113+
- type: table
114+
name: folders
115+
properties:
116+
- file.name
117+
- file.folder
118+
`.trim());
119+
120+
const compiled = compileQuery(spec);
121+
const indexed = await indexVault({
122+
rootDir: vaultDir,
123+
include: ["**/*.md"],
124+
exclude: [],
125+
adapter: nodeAdapter,
126+
});
127+
128+
const result = executeCompiledQuery({
129+
compiled,
130+
documents: indexed.documents,
131+
view: "folders",
132+
});
133+
134+
expect(result.rows).toHaveLength(1);
135+
expect(result.rows[0].projected["file.name"]).toBe("gamma.md");
136+
expect(result.rows[0].projected["file.folder"]).toBe("nested");
137+
expect(result.diagnostics.errors).toHaveLength(0);
138+
});
108139
});

tests/serialize.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const fixtureResult: QueryResult = {
1010
file: {
1111
name: "alpha.md",
1212
path: "alpha.md",
13+
folder: "",
1314
ext: ".md",
1415
size: 10,
1516
ctime: new Date("2024-01-01"),

0 commit comments

Comments
 (0)