fix(context-bill): a container skips only nested dirs whose SKILL.md is a file, as discovery does

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
garrytanandcapy-ai[bot] committed 2026-10-26 02:26:05 +00:00
1 parent 679202b952
commit 1ec023b1ed
2 files changed
+20 -1

No files matched your search

+9 -1
View File
@@ -210,6 +210,14 @@ function parseFrontmatter(text: string): { bytes: number; keys: string[]; block:
* Dirent type check sees none of them. Dangling links and anything that is
* neither a file nor a directory are null.
*/
function isFile(p: string): boolean {
try {
return fs.statSync(p).isFile();
} catch {
return false;
}
}
function entryKind(p: string, e: fs.Dirent): "file" | "dir" | null {
if (e.isFile()) return "file";
if (e.isDirectory()) return "dir";
@@ -289,7 +297,7 @@ export function walkMd(dir: string, opts: { billedRoot?: string; skipNestedSkill
} else if (
kind !== "dir" ||
fs.existsSync(path.join(p, ".git")) ||
(opts.skipNestedSkills && current === dir && fs.existsSync(path.join(p, "SKILL.md")))
(opts.skipNestedSkills && current === dir && isFile(path.join(p, "SKILL.md")))
) {
continue;
}
+11
View File
@@ -391,6 +391,17 @@ describe("upstream fix b: installed-tree layout (repo-checkout subdir skip)", ()
fs.rmSync(root, { recursive: true, force: true });
});
it("bills a subdirectory whose SKILL.md is a directory to its container, as discovery does not count it as a skill", () => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "context-bill-skilldir-"));
fs.writeFileSync(path.join(root, "SKILL.md"), "---\nname: c\ndescription: d\n---\n# c\n");
fs.mkdirSync(path.join(root, "sub", "SKILL.md"), { recursive: true });
fs.writeFileSync(path.join(root, "sub", "notes.md"), "n".repeat(500));
const bill = buildBill(root);
fs.rmSync(root, { recursive: true, force: true });
expect(bill.skills.map((s) => s.name)).toEqual([path.basename(root)]);
expect(bill.skills[0].totalMdBytes).toBe(bill.skills[0].skillMdBytes + 500);
});
it("refuses a parent link when the root's own name starts with '..'", () => {
if (process.platform === "win32") return;
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "context-bill-dotdot-"));