@kuznai/inception-engine 0.25.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +68 -4
  2. package/dist/src/core/adapters/agent-definitions.d.ts +2 -1
  3. package/dist/src/core/adapters/agent-definitions.js +14 -5
  4. package/dist/src/core/adapters/execution-config.js +2 -4
  5. package/dist/src/core/adapters/index.d.ts +2 -1
  6. package/dist/src/core/adapters/index.js +3 -3
  7. package/dist/src/core/adapters/rules.d.ts +2 -1
  8. package/dist/src/core/adapters/rules.js +12 -5
  9. package/dist/src/core/concurrency.d.ts +5 -0
  10. package/dist/src/core/concurrency.js +19 -0
  11. package/dist/src/core/deploy.js +158 -100
  12. package/dist/src/core/init.d.ts +1 -0
  13. package/dist/src/core/init.js +79 -28
  14. package/dist/src/core/preflight.js +6 -4
  15. package/dist/src/core/revert.js +2 -4
  16. package/dist/src/core/validation.d.ts +31 -3
  17. package/dist/src/core/validation.js +64 -10
  18. package/dist/src/formatters.js +14 -11
  19. package/dist/src/schemas/manifest.d.ts +64 -64
  20. package/dist/src/schemas/manifest.js +1 -1
  21. package/dist/src/schemas/registry.d.ts +27 -27
  22. package/dist/src/types.d.ts +1 -1
  23. package/dist/test/unit/adapters.test.js +84 -83
  24. package/dist/test/unit/cli.test.js +57 -1
  25. package/dist/test/unit/deploy.test.js +253 -0
  26. package/dist/test/unit/formatters.test.js +4 -3
  27. package/dist/test/unit/gemini-north-star.test.js +9 -8
  28. package/dist/test/unit/init.test.d.ts +1 -0
  29. package/dist/test/unit/init.test.js +14 -0
  30. package/dist/test/unit/manifest.test.js +25 -0
  31. package/dist/test/unit/preflight.test.js +29 -0
  32. package/dist/test/unit/validation.test.d.ts +1 -0
  33. package/dist/test/unit/validation.test.js +102 -0
  34. package/package.json +7 -7
@@ -6,6 +6,7 @@ import { compileHookActions } from "../../src/core/adapters/hooks.js";
6
6
  import { compileMcpServerActions } from "../../src/core/adapters/mcp.js";
7
7
  import { compilePermissionsActions, compilePermissionsReverts, } from "../../src/core/adapters/permissions.js";
8
8
  import { compileAgentRuleActions, compileAgentRuleReverts, } from "../../src/core/adapters/rules.js";
9
+ import { createSourcePathValidator } from "../../src/core/validation.js";
9
10
  import { makeTmpDir } from "../helpers/fs.js";
10
11
  import { assertPathEndsWith, normalizeSlashes } from "../helpers/path.js";
11
12
  describe("compileMcpServerActions", () => {
@@ -194,13 +195,13 @@ describe("compileAgentRuleActions", () => {
194
195
  try {
195
196
  const rulesFile = path.join(dir, "CLAUDE.md");
196
197
  await writeFile(rulesFile, "# Rules");
197
- const realRoot = await realpath(dir);
198
+ const validateSource = createSourcePathValidator(await realpath(dir));
198
199
  const { actions, warnings } = await compileAgentRuleActions({
199
200
  name: "my-rule",
200
201
  agents: ["claude-code"],
201
202
  path: "CLAUDE.md",
202
203
  scope: "global",
203
- }, dir, dir, realRoot, ["codex"], "/home/test");
204
+ }, dir, dir, validateSource, ["codex"], "/home/test");
204
205
  assert.equal(actions.length, 0);
205
206
  assert.equal(warnings.length, 0);
206
207
  }
@@ -216,7 +217,7 @@ describe("compileAgentRuleActions", () => {
216
217
  agents: ["claude-code"],
217
218
  path: "missing.md",
218
219
  scope: "global",
219
- }, dir, dir, dir, ["codex"], "/home/test");
220
+ }, dir, dir, createSourcePathValidator(dir), ["codex"], "/home/test");
220
221
  assert.equal(actions.length, 0);
221
222
  assert.equal(warnings.length, 0);
222
223
  }
@@ -230,13 +231,13 @@ describe("compileAgentRuleActions", () => {
230
231
  const rulesFile = path.join(dir, "CLAUDE.md");
231
232
  await writeFile(rulesFile, "# Rules");
232
233
  const home = "/home/test";
233
- const realRoot = await realpath(dir);
234
+ const validateSource = createSourcePathValidator(await realpath(dir));
234
235
  const { actions, warnings } = await compileAgentRuleActions({
235
236
  name: "my-rule",
236
237
  agents: ["claude-code"],
237
238
  path: "CLAUDE.md",
238
239
  scope: "global",
239
- }, dir, dir, realRoot, ["claude-code"], home);
240
+ }, dir, dir, validateSource, ["claude-code"], home);
240
241
  assert.equal(actions.length, 1);
241
242
  assert.equal(warnings.length, 0);
242
243
  const action = actions[0];
@@ -255,13 +256,13 @@ describe("compileAgentRuleActions", () => {
255
256
  const dir = await makeTmpDir();
256
257
  try {
257
258
  await writeFile(path.join(dir, "rules.md"), "---\nname: test-rule\ndescription: test\n---\n# Rules");
258
- const realRoot = await realpath(dir);
259
+ const validateSource = createSourcePathValidator(await realpath(dir));
259
260
  const { actions, warnings } = await compileAgentRuleActions({
260
261
  name: "my-rule",
261
262
  agents: ["github-copilot"],
262
263
  path: "rules.md",
263
264
  scope: "global",
264
- }, dir, dir, realRoot, ["github-copilot"], "/home/test");
265
+ }, dir, dir, validateSource, ["github-copilot"], "/home/test");
265
266
  assert.equal(actions.length, 0);
266
267
  assert.equal(warnings.length, 1);
267
268
  assert.equal(warnings[0]?.kind, "confidence");
@@ -278,13 +279,13 @@ describe("compileAgentRuleActions", () => {
278
279
  const dir = await makeTmpDir();
279
280
  try {
280
281
  await writeFile(path.join(dir, "rules.md"), "---\nname: test-rule\ndescription: test\n---\n# Rules");
281
- const realRoot = await realpath(dir);
282
+ const validateSource = createSourcePathValidator(await realpath(dir));
282
283
  const { actions, warnings } = await compileAgentRuleActions({
283
284
  name: "my-rule",
284
285
  agents: ["antigravity"],
285
286
  path: "rules.md",
286
287
  scope: "global",
287
- }, dir, dir, realRoot, ["antigravity"], "/home/test", "/repo/test");
288
+ }, dir, dir, validateSource, ["antigravity"], "/home/test", "/repo/test");
288
289
  assert.equal(actions.length, 1);
289
290
  assert.equal(warnings.length, 0);
290
291
  assert.equal(actions[0]?.kind, "file-write");
@@ -299,13 +300,13 @@ describe("compileAgentRuleActions", () => {
299
300
  const dir = await makeTmpDir();
300
301
  try {
301
302
  await writeFile(path.join(dir, "rules.md"), "---\nname: test-rule\ndescription: test\n---\n# Rules");
302
- const realRoot = await realpath(dir);
303
+ const validateSource = createSourcePathValidator(await realpath(dir));
303
304
  const { actions, warnings } = await compileAgentRuleActions({
304
305
  name: "my-rule",
305
306
  agents: ["gemini-cli", "antigravity"],
306
307
  path: "rules.md",
307
308
  scope: "global",
308
- }, dir, dir, realRoot, ["gemini-cli", "antigravity"], "/home/test", "/repo/test");
309
+ }, dir, dir, validateSource, ["gemini-cli", "antigravity"], "/home/test", "/repo/test");
309
310
  // Both agents target ~/.gemini/GEMINI.md — deduplication emits only one action.
310
311
  assert.equal(actions.length, 1, "expected one deduplicated action");
311
312
  assert.equal(warnings.length, 0);
@@ -323,13 +324,13 @@ describe("compileAgentRuleActions", () => {
323
324
  try {
324
325
  await writeFile(path.join(dir, "rules.md"), "---\nname: test-rule\ndescription: test\n---\n# Rules");
325
326
  const repo = "/repo/myproject";
326
- const realRoot = await realpath(dir);
327
+ const validateSource = createSourcePathValidator(await realpath(dir));
327
328
  const { actions, warnings } = await compileAgentRuleActions({
328
329
  name: "my-rule",
329
330
  agents: ["gemini-cli", "antigravity"],
330
331
  path: "rules.md",
331
332
  scope: "repo",
332
- }, dir, dir, realRoot, ["gemini-cli", "antigravity"], "/home/test", repo);
333
+ }, dir, dir, validateSource, ["gemini-cli", "antigravity"], "/home/test", repo);
333
334
  assert.equal(actions.length, 1, "expected one deduplicated action");
334
335
  assert.equal(warnings.length, 0);
335
336
  assert.equal(actions[0]?.agent, "gemini-cli");
@@ -343,13 +344,13 @@ describe("compileAgentRuleActions", () => {
343
344
  const dir = await makeTmpDir();
344
345
  try {
345
346
  await writeFile(path.join(dir, "rules.txt"), "plain text");
346
- const realRoot = await realpath(dir);
347
+ const validateSource = createSourcePathValidator(await realpath(dir));
347
348
  await assert.rejects(compileAgentRuleActions({
348
349
  name: "my-rule",
349
350
  agents: ["codex"],
350
351
  path: "rules.txt",
351
352
  scope: "global",
352
- }, dir, dir, realRoot, ["codex"], "/home/test"), /must point to a Markdown source file/);
353
+ }, dir, dir, validateSource, ["codex"], "/home/test"), /must point to a Markdown source file/);
353
354
  }
354
355
  finally {
355
356
  await rm(dir, { recursive: true });
@@ -360,13 +361,13 @@ describe("compileAgentRuleActions", () => {
360
361
  try {
361
362
  await writeFile(path.join(dir, "copilot.md"), "# Copilot rules");
362
363
  const repo = "/repo/myproject";
363
- const realRoot = await realpath(dir);
364
+ const validateSource = createSourcePathValidator(await realpath(dir));
364
365
  const { actions, warnings } = await compileAgentRuleActions({
365
366
  name: "copilot-main",
366
367
  agents: ["github-copilot"],
367
368
  path: "copilot.md",
368
369
  scope: "copilot-repo",
369
- }, dir, dir, realRoot, ["github-copilot"], "/home/test", repo);
370
+ }, dir, dir, validateSource, ["github-copilot"], "/home/test", repo);
370
371
  assert.equal(actions.length, 1);
371
372
  assert.equal(warnings.length, 0);
372
373
  const action = actions[0];
@@ -384,13 +385,13 @@ describe("compileAgentRuleActions", () => {
384
385
  try {
385
386
  await writeFile(path.join(dir, "typescript.md"), "# TypeScript rules");
386
387
  const repo = "/repo/myproject";
387
- const realRoot = await realpath(dir);
388
+ const validateSource = createSourcePathValidator(await realpath(dir));
388
389
  const { actions, warnings } = await compileAgentRuleActions({
389
390
  name: "typescript",
390
391
  agents: ["github-copilot"],
391
392
  path: "typescript.md",
392
393
  scope: "copilot-scoped",
393
- }, dir, dir, realRoot, ["github-copilot"], "/home/test", repo);
394
+ }, dir, dir, validateSource, ["github-copilot"], "/home/test", repo);
394
395
  assert.equal(actions.length, 1);
395
396
  assert.equal(warnings.length, 0);
396
397
  const action = actions[0];
@@ -407,13 +408,13 @@ describe("compileAgentRuleActions", () => {
407
408
  const dir = await makeTmpDir();
408
409
  try {
409
410
  await writeFile(path.join(dir, "copilot.md"), "# Copilot rules");
410
- const realRoot = await realpath(dir);
411
+ const validateSource = createSourcePathValidator(await realpath(dir));
411
412
  const { actions, warnings } = await compileAgentRuleActions({
412
413
  name: "copilot-main",
413
414
  agents: ["github-copilot"],
414
415
  path: "copilot.md",
415
416
  scope: "copilot-repo",
416
- }, dir, dir, realRoot, ["github-copilot"], "/home/test");
417
+ }, dir, dir, validateSource, ["github-copilot"], "/home/test");
417
418
  assert.equal(actions.length, 0);
418
419
  assert.equal(warnings.length, 1);
419
420
  assert.equal(warnings[0]?.kind, "confidence");
@@ -428,13 +429,13 @@ describe("compileAgentRuleActions", () => {
428
429
  const dir = await makeTmpDir();
429
430
  try {
430
431
  await writeFile(path.join(dir, "copilot.md"), "# Copilot rules");
431
- const realRoot = await realpath(dir);
432
+ const validateSource = createSourcePathValidator(await realpath(dir));
432
433
  const { actions, warnings } = await compileAgentRuleActions({
433
434
  name: "copilot-main",
434
435
  agents: ["claude-code"],
435
436
  path: "copilot.md",
436
437
  scope: "copilot-repo",
437
- }, dir, dir, realRoot, ["claude-code"], "/home/test", "/repo/test");
438
+ }, dir, dir, validateSource, ["claude-code"], "/home/test", "/repo/test");
438
439
  assert.equal(actions.length, 0);
439
440
  assert.equal(warnings.length, 1);
440
441
  assert.equal(warnings[0]?.kind, "confidence");
@@ -450,13 +451,13 @@ describe("compileAgentRuleActions", () => {
450
451
  // having instructionFrontmatterRequired: true (native agentRules scopes skip that check)
451
452
  await writeFile(path.join(dir, "plain.md"), "# Plain rules\n\nNo frontmatter.");
452
453
  const repo = "/repo/myproject";
453
- const realRoot = await realpath(dir);
454
+ const validateSource = createSourcePathValidator(await realpath(dir));
454
455
  const { actions, warnings } = await compileAgentRuleActions({
455
456
  name: "plain-rules",
456
457
  agents: ["github-copilot"],
457
458
  path: "plain.md",
458
459
  scope: "copilot-repo",
459
- }, dir, dir, realRoot, ["github-copilot"], "/home/test", repo);
460
+ }, dir, dir, validateSource, ["github-copilot"], "/home/test", repo);
460
461
  assert.equal(actions.length, 1);
461
462
  assert.equal(warnings.length, 0);
462
463
  }
@@ -472,7 +473,7 @@ describe("compileAgentRuleActions", () => {
472
473
  agents: ["claude-code"],
473
474
  path: "nonexistent.md",
474
475
  scope: "global",
475
- }, dir, dir, dir, ["claude-code"], "/home/test"), (err) => {
476
+ }, dir, dir, createSourcePathValidator(dir), ["claude-code"], "/home/test"), (err) => {
476
477
  assert.ok(err instanceof Error);
477
478
  assert.match(err.message, /nonexistent\.md/);
478
479
  return true;
@@ -486,13 +487,13 @@ describe("compileAgentRuleActions", () => {
486
487
  const dir = await makeTmpDir();
487
488
  try {
488
489
  await writeFile(path.join(dir, "rules.md"), "---\nname: test-rule\ndescription: test\n---\n# Rules");
489
- const realRoot = await realpath(dir);
490
+ const validateSource = createSourcePathValidator(await realpath(dir));
490
491
  const { actions, warnings } = await compileAgentRuleActions({
491
492
  name: "my-rule",
492
493
  agents: ["claude-code", "codex"],
493
494
  path: "rules.md",
494
495
  scope: "global",
495
- }, dir, dir, realRoot, ["claude-code", "codex"], "/home/test");
496
+ }, dir, dir, validateSource, ["claude-code", "codex"], "/home/test");
496
497
  assert.equal(actions.length, 2);
497
498
  assert.equal(warnings.length, 0);
498
499
  const agents = actions.map((a) => a.agent);
@@ -509,13 +510,13 @@ describe("compileAgentRuleActions", () => {
509
510
  const rulesFile = path.join(dir, "CLAUDE.md");
510
511
  await writeFile(rulesFile, "# Rules");
511
512
  const repo = "/repo/myproject";
512
- const realRoot = await realpath(dir);
513
+ const validateSource = createSourcePathValidator(await realpath(dir));
513
514
  const { actions, warnings } = await compileAgentRuleActions({
514
515
  name: "my-rule",
515
516
  agents: ["claude-code"],
516
517
  path: "CLAUDE.md",
517
518
  scope: "repo",
518
- }, dir, dir, realRoot, ["claude-code"], "/home/test", repo);
519
+ }, dir, dir, validateSource, ["claude-code"], "/home/test", repo);
519
520
  assert.equal(actions.length, 1);
520
521
  assert.equal(warnings.length, 0);
521
522
  const action = actions[0];
@@ -534,20 +535,20 @@ describe("compileAgentRuleActions", () => {
534
535
  await writeFile(rulesFile, "# Rules");
535
536
  const home = "/home/test";
536
537
  const repo = "/repo/myproject";
537
- const realRoot = await realpath(dir);
538
+ const validateSource = createSourcePathValidator(await realpath(dir));
538
539
  const [globalResult, repoResult] = await Promise.all([
539
540
  compileAgentRuleActions({
540
541
  name: "my-rule",
541
542
  agents: ["claude-code"],
542
543
  path: "CLAUDE.md",
543
544
  scope: "global",
544
- }, dir, dir, realRoot, ["claude-code"], home, repo),
545
+ }, dir, dir, validateSource, ["claude-code"], home, repo),
545
546
  compileAgentRuleActions({
546
547
  name: "my-rule",
547
548
  agents: ["claude-code"],
548
549
  path: "CLAUDE.md",
549
550
  scope: "repo",
550
- }, dir, dir, realRoot, ["claude-code"], home, repo),
551
+ }, dir, dir, validateSource, ["claude-code"], home, repo),
551
552
  ]);
552
553
  assert.equal(globalResult.actions.length, 1);
553
554
  assert.equal(repoResult.actions.length, 1);
@@ -564,13 +565,13 @@ describe("compileAgentRuleActions", () => {
564
565
  try {
565
566
  await writeFile(path.join(dir, "rules.md"), "---\nname: test-rule\ndescription: test\n---\n# Rules");
566
567
  const repo = "/repo/myproject";
567
- const realRoot = await realpath(dir);
568
+ const validateSource = createSourcePathValidator(await realpath(dir));
568
569
  const { actions, warnings } = await compileAgentRuleActions({
569
570
  name: "my-rule",
570
571
  agents: ["antigravity"],
571
572
  path: "rules.md",
572
573
  scope: "repo",
573
- }, dir, dir, realRoot, ["antigravity"], "/home/test", repo);
574
+ }, dir, dir, validateSource, ["antigravity"], "/home/test", repo);
574
575
  assert.equal(actions.length, 1);
575
576
  assert.equal(warnings.length, 0);
576
577
  assert.equal(normalizeSlashes(actions[0]?.target ?? ""), `${repo}/GEMINI.md`, "expected target to be {repo}/GEMINI.md");
@@ -585,14 +586,14 @@ describe("compileAgentRuleActions", () => {
585
586
  const rulesFile = path.join(dir, "CLAUDE.md");
586
587
  await writeFile(rulesFile, "# Rules");
587
588
  const repo = "/repo/myproject";
588
- const realRoot = await realpath(dir);
589
+ const validateSource = createSourcePathValidator(await realpath(dir));
589
590
  const { actions, warnings } = await compileAgentRuleActions({
590
591
  name: "my-rule",
591
592
  agents: ["claude-code"],
592
593
  path: "CLAUDE.md",
593
594
  scope: "repo",
594
595
  targetDir: "apps/frontend",
595
- }, dir, dir, realRoot, ["claude-code"], "/home/test", repo);
596
+ }, dir, dir, validateSource, ["claude-code"], "/home/test", repo);
596
597
  assert.equal(actions.length, 1);
597
598
  assert.equal(warnings.length, 0);
598
599
  const action = actions[0];
@@ -606,13 +607,13 @@ describe("compileAgentRuleActions", () => {
606
607
  const dir = await makeTmpDir();
607
608
  try {
608
609
  await writeFile(path.join(dir, "rules.md"), "---\nname: test-rule\ndescription: test\n---\n# Rules");
609
- const realRoot = await realpath(dir);
610
+ const validateSource = createSourcePathValidator(await realpath(dir));
610
611
  const { actions, warnings } = await compileAgentRuleActions({
611
612
  name: "my-rule",
612
613
  agents: ["claude-code"],
613
614
  path: "rules.md",
614
615
  scope: "repo",
615
- }, dir, dir, realRoot, ["claude-code"], "/home/test");
616
+ }, dir, dir, validateSource, ["claude-code"], "/home/test");
616
617
  assert.equal(actions.length, 0);
617
618
  assert.equal(warnings.length, 1);
618
619
  assert.equal(warnings[0]?.kind, "confidence");
@@ -626,13 +627,13 @@ describe("compileAgentRuleActions", () => {
626
627
  const dir = await makeTmpDir();
627
628
  try {
628
629
  await writeFile(path.join(dir, "rules.md"), "---\nname: test-rule\ndescription: test\n---\n# Rules");
629
- const realRoot = await realpath(dir);
630
+ const validateSource = createSourcePathValidator(await realpath(dir));
630
631
  const { actions, warnings } = await compileAgentRuleActions({
631
632
  name: "my-rule",
632
633
  agents: ["github-copilot"],
633
634
  path: "rules.md",
634
635
  scope: "repo",
635
- }, dir, dir, realRoot, ["github-copilot"], "/home/test", "/repo/myproject");
636
+ }, dir, dir, validateSource, ["github-copilot"], "/home/test", "/repo/myproject");
636
637
  assert.equal(actions.length, 0);
637
638
  assert.equal(warnings.length, 1);
638
639
  assert.equal(warnings[0]?.kind, "confidence");
@@ -646,13 +647,13 @@ describe("compileAgentRuleActions", () => {
646
647
  const dir = await makeTmpDir();
647
648
  try {
648
649
  await writeFile(path.join(dir, "rules.md"), "---\nname: test-rule\ndescription: test\n---\n# Rules");
649
- const realRoot = await realpath(dir);
650
+ const validateSource = createSourcePathValidator(await realpath(dir));
650
651
  const { actions, warnings } = await compileAgentRuleActions({
651
652
  name: "my-rule",
652
653
  agents: ["claude-code", "github-copilot"],
653
654
  path: "rules.md",
654
655
  scope: "global",
655
- }, dir, dir, realRoot, ["claude-code", "github-copilot"], "/home/test");
656
+ }, dir, dir, validateSource, ["claude-code", "github-copilot"], "/home/test");
656
657
  // github-copilot rides claude-code's CLAUDE.md deployment; only one
657
658
  // action should be emitted for claude-code.
658
659
  assert.equal(actions.length, 1, "expected exactly one action");
@@ -668,13 +669,13 @@ describe("compileAgentRuleActions", () => {
668
669
  const dir = await makeTmpDir();
669
670
  try {
670
671
  await writeFile(path.join(dir, "rules.md"), "---\nname: test-rule\ndescription: test\n---\n# Rules");
671
- const realRoot = await realpath(dir);
672
+ const validateSource = createSourcePathValidator(await realpath(dir));
672
673
  const { actions, warnings } = await compileAgentRuleActions({
673
674
  name: "my-rule",
674
675
  agents: ["github-copilot"],
675
676
  path: "rules.md",
676
677
  scope: "global",
677
- }, dir, dir, realRoot, ["github-copilot"], "/home/test");
678
+ }, dir, dir, validateSource, ["github-copilot"], "/home/test");
678
679
  assert.equal(actions.length, 0);
679
680
  assert.equal(warnings.length, 1);
680
681
  assert.equal(warnings[0]?.kind, "confidence");
@@ -986,13 +987,13 @@ describe("compileAgentDefinitionActions", () => {
986
987
  const dir = await makeTmpDir();
987
988
  try {
988
989
  await writeFile(path.join(dir, "agent.md"), "---\nname: test-agent\ndescription: test\n---\n# Agent");
989
- const realRoot = await realpath(dir);
990
+ const validateSource = createSourcePathValidator(await realpath(dir));
990
991
  const { actions, warnings } = await compile({
991
992
  name: "my-agent",
992
993
  agents: ["claude-code"],
993
994
  path: "agent.md",
994
995
  scope: "repo",
995
- }, dir, dir, realRoot, ["codex"], "/home/test", "/repo/test");
996
+ }, dir, dir, validateSource, ["codex"], "/home/test", "/repo/test");
996
997
  assert.equal(actions.length, 0);
997
998
  assert.equal(warnings.length, 0);
998
999
  }
@@ -1010,7 +1011,7 @@ describe("compileAgentDefinitionActions", () => {
1010
1011
  agents: ["claude-code"],
1011
1012
  path: "missing.md",
1012
1013
  scope: "repo",
1013
- }, dir, dir, dir, ["codex"], "/home/test", "/repo/test");
1014
+ }, dir, dir, createSourcePathValidator(dir), ["codex"], "/home/test", "/repo/test");
1014
1015
  assert.equal(actions.length, 0);
1015
1016
  assert.equal(warnings.length, 0);
1016
1017
  }
@@ -1023,13 +1024,13 @@ describe("compileAgentDefinitionActions", () => {
1023
1024
  const dir = await makeTmpDir();
1024
1025
  try {
1025
1026
  await writeFile(path.join(dir, "my-agent.md"), "---\nname: test-agent\ndescription: test\ntools: []\n---\n# Agent");
1026
- const realRoot = await realpath(dir);
1027
+ const validateSource = createSourcePathValidator(await realpath(dir));
1027
1028
  const { actions, warnings } = await compile({
1028
1029
  name: "my-agent",
1029
1030
  agents: ["claude-code"],
1030
1031
  path: "my-agent.md",
1031
1032
  scope: "repo",
1032
- }, dir, dir, realRoot, ["claude-code"], "/home/test", "/repo/test");
1033
+ }, dir, dir, validateSource, ["claude-code"], "/home/test", "/repo/test");
1033
1034
  assert.equal(warnings.length, 0);
1034
1035
  assert.equal(actions.length, 1);
1035
1036
  const action = actions[0];
@@ -1048,13 +1049,13 @@ describe("compileAgentDefinitionActions", () => {
1048
1049
  const dir = await makeTmpDir();
1049
1050
  try {
1050
1051
  await writeFile(path.join(dir, "my-agent.md"), "---\nname: test-agent\ndescription: test\ntools: []\n---\n# Agent");
1051
- const realRoot = await realpath(dir);
1052
+ const validateSource = createSourcePathValidator(await realpath(dir));
1052
1053
  const { actions, warnings } = await compile({
1053
1054
  name: "my-agent",
1054
1055
  agents: ["claude-code"],
1055
1056
  path: "my-agent.md",
1056
1057
  scope: "repo",
1057
- }, dir, dir, realRoot, ["claude-code"], "/home/test");
1058
+ }, dir, dir, validateSource, ["claude-code"], "/home/test");
1058
1059
  assert.equal(actions.length, 0);
1059
1060
  assert.equal(warnings.length, 1);
1060
1061
  assert.equal(warnings[0]?.kind, "confidence");
@@ -1069,13 +1070,13 @@ describe("compileAgentDefinitionActions", () => {
1069
1070
  const dir = await makeTmpDir();
1070
1071
  try {
1071
1072
  await writeFile(path.join(dir, "my-agent.md"), "---\nname: test-agent\ndescription: test\ntools: []\n---\n# Agent");
1072
- const realRoot = await realpath(dir);
1073
+ const validateSource = createSourcePathValidator(await realpath(dir));
1073
1074
  const { actions, warnings } = await compile({
1074
1075
  name: "my-agent",
1075
1076
  agents: ["gemini-cli"],
1076
1077
  path: "my-agent.md",
1077
1078
  scope: "workspace",
1078
- }, dir, dir, realRoot, ["gemini-cli"], "/home/test", "/repo/test");
1079
+ }, dir, dir, validateSource, ["gemini-cli"], "/home/test", "/repo/test");
1079
1080
  assert.equal(warnings.length, 0);
1080
1081
  assert.equal(actions.length, 1);
1081
1082
  assert.equal(normalizeSlashes(actions[0]?.target ?? ""), "/repo/test/.gemini/agents/my-agent.md");
@@ -1089,13 +1090,13 @@ describe("compileAgentDefinitionActions", () => {
1089
1090
  const dir = await makeTmpDir();
1090
1091
  try {
1091
1092
  await writeFile(path.join(dir, "my-agent.md"), "---\nname: test-agent\ndescription: test\ntools: []\n---\n# Agent");
1092
- const realRoot = await realpath(dir);
1093
+ const validateSource = createSourcePathValidator(await realpath(dir));
1093
1094
  const { actions, warnings } = await compile({
1094
1095
  name: "my-agent",
1095
1096
  agents: ["gemini-cli"],
1096
1097
  path: "my-agent.md",
1097
1098
  scope: "workspace",
1098
- }, dir, dir, realRoot, ["gemini-cli"], "/home/test");
1099
+ }, dir, dir, validateSource, ["gemini-cli"], "/home/test");
1099
1100
  assert.equal(actions.length, 0);
1100
1101
  assert.equal(warnings.length, 1);
1101
1102
  assert.equal(warnings[0]?.kind, "confidence");
@@ -1110,13 +1111,13 @@ describe("compileAgentDefinitionActions", () => {
1110
1111
  const dir = await makeTmpDir();
1111
1112
  try {
1112
1113
  await writeFile(path.join(dir, "my-agent.md"), "---\nname: test-agent\ndescription: test\ntools: []\n---\n# Agent");
1113
- const realRoot = await realpath(dir);
1114
+ const validateSource = createSourcePathValidator(await realpath(dir));
1114
1115
  const { actions, warnings } = await compile({
1115
1116
  name: "my-agent",
1116
1117
  agents: ["opencode"],
1117
1118
  path: "my-agent.md",
1118
1119
  scope: "repo",
1119
- }, dir, dir, realRoot, ["opencode"], "/home/test", "/repo/test");
1120
+ }, dir, dir, validateSource, ["opencode"], "/home/test", "/repo/test");
1120
1121
  assert.equal(warnings.length, 0);
1121
1122
  assert.equal(actions.length, 1);
1122
1123
  const action = actions[0];
@@ -1134,13 +1135,13 @@ describe("compileAgentDefinitionActions", () => {
1134
1135
  const dir = await makeTmpDir();
1135
1136
  try {
1136
1137
  await writeFile(path.join(dir, "my-agent.md"), "---\nname: test-agent\ndescription: test\ntools: []\n---\n# Agent");
1137
- const realRoot = await realpath(dir);
1138
+ const validateSource = createSourcePathValidator(await realpath(dir));
1138
1139
  const { actions, warnings } = await compile({
1139
1140
  name: "my-agent",
1140
1141
  agents: ["github-copilot"],
1141
1142
  path: "my-agent.md",
1142
1143
  scope: "repo",
1143
- }, dir, dir, realRoot, ["github-copilot"], "/home/test", "/repo/test");
1144
+ }, dir, dir, validateSource, ["github-copilot"], "/home/test", "/repo/test");
1144
1145
  assert.equal(warnings.length, 0);
1145
1146
  assert.equal(actions.length, 1);
1146
1147
  const action = actions[0];
@@ -1161,13 +1162,13 @@ describe("compileAgentDefinitionActions", () => {
1161
1162
  const dir = await makeTmpDir();
1162
1163
  try {
1163
1164
  await writeFile(path.join(dir, "my-agent.md"), "---\nname: test-agent\ndescription: test\ntools: []\n---\n# Agent");
1164
- const realRoot = await realpath(dir);
1165
+ const validateSource = createSourcePathValidator(await realpath(dir));
1165
1166
  const { actions, warnings } = await compile({
1166
1167
  name: "my-agent",
1167
1168
  agents: ["antigravity"],
1168
1169
  path: "my-agent.md",
1169
1170
  scope: "repo",
1170
- }, dir, dir, realRoot, ["antigravity"], "/home/test", "/repo/test");
1171
+ }, dir, dir, validateSource, ["antigravity"], "/home/test", "/repo/test");
1171
1172
  assert.equal(warnings.length, 0);
1172
1173
  assert.equal(actions.length, 1);
1173
1174
  const action = actions[0];
@@ -1185,13 +1186,13 @@ describe("compileAgentDefinitionActions", () => {
1185
1186
  const dir = await makeTmpDir();
1186
1187
  try {
1187
1188
  await writeFile(path.join(dir, "my-agent.md"), "---\nname: test-agent\ndescription: test\ntools: []\n---\n# Agent");
1188
- const realRoot = await realpath(dir);
1189
+ const validateSource = createSourcePathValidator(await realpath(dir));
1189
1190
  const { actions, warnings } = await compile({
1190
1191
  name: "my-agent",
1191
1192
  agents: ["codex"],
1192
1193
  path: "my-agent.md",
1193
1194
  scope: "repo",
1194
- }, dir, dir, realRoot, ["codex"], "/home/test", "/repo/test");
1195
+ }, dir, dir, validateSource, ["codex"], "/home/test", "/repo/test");
1195
1196
  assert.equal(actions.length, 0);
1196
1197
  assert.equal(warnings.length, 1);
1197
1198
  assert.equal(warnings[0]?.kind, "confidence");
@@ -1206,13 +1207,13 @@ describe("compileAgentDefinitionActions", () => {
1206
1207
  const dir = await makeTmpDir();
1207
1208
  try {
1208
1209
  await writeFile(path.join(dir, "agent.txt"), "plain text");
1209
- const realRoot = await realpath(dir);
1210
+ const validateSource = createSourcePathValidator(await realpath(dir));
1210
1211
  await assert.rejects(compile({
1211
1212
  name: "my-agent",
1212
1213
  agents: ["claude-code"],
1213
1214
  path: "agent.txt",
1214
1215
  scope: "repo",
1215
- }, dir, dir, realRoot, ["claude-code"], "/home/test", "/repo/test"), /must point to a Markdown source file/);
1216
+ }, dir, dir, validateSource, ["claude-code"], "/home/test", "/repo/test"), /must point to a Markdown source file/);
1216
1217
  }
1217
1218
  finally {
1218
1219
  await rm(dir, { recursive: true });
@@ -1227,7 +1228,7 @@ describe("compileAgentDefinitionActions", () => {
1227
1228
  agents: ["claude-code"],
1228
1229
  path: "nonexistent.md",
1229
1230
  scope: "repo",
1230
- }, dir, dir, dir, ["claude-code"], "/home/test", "/repo/test"), (err) => {
1231
+ }, dir, dir, createSourcePathValidator(dir), ["claude-code"], "/home/test", "/repo/test"), (err) => {
1231
1232
  assert.ok(err instanceof Error);
1232
1233
  assert.match(err.message, /nonexistent\.md/);
1233
1234
  return true;
@@ -1242,13 +1243,13 @@ describe("compileAgentDefinitionActions", () => {
1242
1243
  const dir = await makeTmpDir();
1243
1244
  try {
1244
1245
  await writeFile(path.join(dir, "my-agent.md"), "---\nname: test-agent\ndescription: test\ntools: []\n---\n# Agent");
1245
- const realRoot = await realpath(dir);
1246
+ const validateSource = createSourcePathValidator(await realpath(dir));
1246
1247
  const { actions, warnings } = await compile({
1247
1248
  name: "my-agent",
1248
1249
  agents: ["claude-code", "opencode", "github-copilot"],
1249
1250
  path: "my-agent.md",
1250
1251
  scope: "repo",
1251
- }, dir, dir, realRoot, ["claude-code", "opencode", "github-copilot"], "/home/test", "/repo/test");
1252
+ }, dir, dir, validateSource, ["claude-code", "opencode", "github-copilot"], "/home/test", "/repo/test");
1252
1253
  assert.equal(warnings.length, 0);
1253
1254
  assert.equal(actions.length, 3);
1254
1255
  const agentIds = actions.map((a) => a.agent);
@@ -1265,13 +1266,13 @@ describe("compileAgentDefinitionActions", () => {
1265
1266
  const dir = await makeTmpDir();
1266
1267
  try {
1267
1268
  await writeFile(path.join(dir, "bad-copilot.md"), "---\nname: test\ndescription: test\n---\n# Bad");
1268
- const realRoot = await realpath(dir);
1269
+ const validateSource = createSourcePathValidator(await realpath(dir));
1269
1270
  await assert.rejects(compile({
1270
1271
  name: "bad",
1271
1272
  agents: ["github-copilot"],
1272
1273
  path: "bad-copilot.md",
1273
1274
  scope: "repo",
1274
- }, dir, dir, realRoot, ["github-copilot"], "/home/test", "/repo/test"), /must define "tools" or "instructions" in frontmatter/);
1275
+ }, dir, dir, validateSource, ["github-copilot"], "/home/test", "/repo/test"), /must define "tools" or "instructions" in frontmatter/);
1275
1276
  }
1276
1277
  finally {
1277
1278
  await rm(dir, { recursive: true });
@@ -1282,13 +1283,13 @@ describe("compileAgentDefinitionActions", () => {
1282
1283
  const dir = await makeTmpDir();
1283
1284
  try {
1284
1285
  await writeFile(path.join(dir, "agent.md"), "---\nname: test\ndescription: test\ntools: []\n---\n# Agent");
1285
- const realRoot = await realpath(dir);
1286
+ const validateSource = createSourcePathValidator(await realpath(dir));
1286
1287
  const result = await compile({
1287
1288
  name: "agent",
1288
1289
  agents: ["github-copilot"],
1289
1290
  path: "agent.md",
1290
1291
  scope: "repo",
1291
- }, dir, dir, realRoot, ["github-copilot"], "/home/test", "/repo/test");
1292
+ }, dir, dir, validateSource, ["github-copilot"], "/home/test", "/repo/test");
1292
1293
  assert.ok(result.actions.length > 0, "expected at least one action");
1293
1294
  }
1294
1295
  finally {
@@ -1300,13 +1301,13 @@ describe("compileAgentDefinitionActions", () => {
1300
1301
  const dir = await makeTmpDir();
1301
1302
  try {
1302
1303
  await writeFile(path.join(dir, "agent.md"), "---\nname: test\ndescription: test\ntools:\n - github\n - codebase\n---\n# Agent");
1303
- const realRoot = await realpath(dir);
1304
+ const validateSource = createSourcePathValidator(await realpath(dir));
1304
1305
  const result = await compile({
1305
1306
  name: "agent",
1306
1307
  agents: ["github-copilot"],
1307
1308
  path: "agent.md",
1308
1309
  scope: "repo",
1309
- }, dir, dir, realRoot, ["github-copilot"], "/home/test", "/repo/test");
1310
+ }, dir, dir, validateSource, ["github-copilot"], "/home/test", "/repo/test");
1310
1311
  assert.ok(result.actions.length > 0, "expected at least one action");
1311
1312
  }
1312
1313
  finally {
@@ -1318,13 +1319,13 @@ describe("compileAgentDefinitionActions", () => {
1318
1319
  const dir = await makeTmpDir();
1319
1320
  try {
1320
1321
  await writeFile(path.join(dir, "bad-tools.md"), "---\nname: test\ndescription: test\ntools: not-an-array\n---\n# Bad");
1321
- const realRoot = await realpath(dir);
1322
+ const validateSource = createSourcePathValidator(await realpath(dir));
1322
1323
  await assert.rejects(compile({
1323
1324
  name: "bad",
1324
1325
  agents: ["github-copilot"],
1325
1326
  path: "bad-tools.md",
1326
1327
  scope: "repo",
1327
- }, dir, dir, realRoot, ["github-copilot"], "/home/test", "/repo/test"), /"tools" field that must be an array/);
1328
+ }, dir, dir, validateSource, ["github-copilot"], "/home/test", "/repo/test"), /"tools" field that must be an array/);
1328
1329
  }
1329
1330
  finally {
1330
1331
  await rm(dir, { recursive: true });
@@ -1335,13 +1336,13 @@ describe("compileAgentDefinitionActions", () => {
1335
1336
  const dir = await makeTmpDir();
1336
1337
  try {
1337
1338
  await writeFile(path.join(dir, "bad-tools.md"), "---\nname: test\ndescription: test\ntools:\n - github\n - 123\n---\n# Bad");
1338
- const realRoot = await realpath(dir);
1339
+ const validateSource = createSourcePathValidator(await realpath(dir));
1339
1340
  await assert.rejects(compile({
1340
1341
  name: "bad",
1341
1342
  agents: ["github-copilot"],
1342
1343
  path: "bad-tools.md",
1343
1344
  scope: "repo",
1344
- }, dir, dir, realRoot, ["github-copilot"], "/home/test", "/repo/test"), /"tools" entry that must be a string/);
1345
+ }, dir, dir, validateSource, ["github-copilot"], "/home/test", "/repo/test"), /"tools" entry that must be a string/);
1345
1346
  }
1346
1347
  finally {
1347
1348
  await rm(dir, { recursive: true });
@@ -1352,13 +1353,13 @@ describe("compileAgentDefinitionActions", () => {
1352
1353
  const dir = await makeTmpDir();
1353
1354
  try {
1354
1355
  await writeFile(path.join(dir, "bad-antigravity.md"), "---\nname: test\ndescription: test\nmcp-servers:\n - not-an-object\n---\n# Bad");
1355
- const realRoot = await realpath(dir);
1356
+ const validateSource = createSourcePathValidator(await realpath(dir));
1356
1357
  await assert.rejects(compile({
1357
1358
  name: "bad",
1358
1359
  agents: ["antigravity"],
1359
1360
  path: "bad-antigravity.md",
1360
1361
  scope: "repo",
1361
- }, dir, dir, realRoot, ["antigravity"], "/home/test", "/repo/test"), /must define "mcp-servers" as an object/);
1362
+ }, dir, dir, validateSource, ["antigravity"], "/home/test", "/repo/test"), /must define "mcp-servers" as an object/);
1362
1363
  }
1363
1364
  finally {
1364
1365
  await rm(dir, { recursive: true });
@@ -1369,13 +1370,13 @@ describe("compileAgentDefinitionActions", () => {
1369
1370
  const dir = await makeTmpDir();
1370
1371
  try {
1371
1372
  await writeFile(path.join(dir, "bad-mcp-config.md"), "---\nname: test\ndescription: test\nmcp-servers:\n my-server: { args: [] }\n---\n# Bad");
1372
- const realRoot = await realpath(dir);
1373
+ const validateSource = createSourcePathValidator(await realpath(dir));
1373
1374
  await assert.rejects(compile({
1374
1375
  name: "bad",
1375
1376
  agents: ["antigravity"],
1376
1377
  path: "bad-mcp-config.md",
1377
1378
  scope: "repo",
1378
- }, dir, dir, realRoot, ["antigravity"], "/home/test", "/repo/test"), /must define either a non-empty "command" or "url"/);
1379
+ }, dir, dir, validateSource, ["antigravity"], "/home/test", "/repo/test"), /must define either a non-empty "command" or "url"/);
1379
1380
  }
1380
1381
  finally {
1381
1382
  await rm(dir, { recursive: true });