agemon 6.0.0 → 6.3.1

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 (171) hide show
  1. package/README.md +424 -89
  2. package/assets/skills/design/agemon-design/NOTICE.md +34 -0
  3. package/assets/skills/design/agemon-design/SKILL.md +95 -358
  4. package/assets/skills/design/agemon-design/references/actions.md +215 -0
  5. package/assets/skills/design/agemon-design/references/brief.md +13 -9
  6. package/assets/skills/design/agemon-design/references/core-rules.md +166 -0
  7. package/assets/skills/design/agemon-design/references/craft-intent.md +16 -14
  8. package/assets/skills/design/agemon-design/references/dashboard.md +1 -1
  9. package/assets/skills/design/agemon-design/references/dataviz.md +8 -8
  10. package/assets/skills/design/agemon-design/references/finish-bar.md +1 -1
  11. package/assets/skills/design/agemon-design/references/heuristics.md +56 -140
  12. package/assets/skills/design/agemon-design/references/inspiration.md +6 -6
  13. package/assets/skills/design/agemon-design/references/loops.md +9 -9
  14. package/assets/skills/design/agemon-design/references/motion.md +1 -1
  15. package/assets/skills/design/agemon-design/references/personas.md +4 -4
  16. package/assets/skills/design/{agemon-design-dashboard/SKILL.md → agemon-design/references/preset-dashboard.md} +8 -12
  17. package/assets/skills/design/{agemon-design-editorial/SKILL.md → agemon-design/references/preset-editorial.md} +5 -9
  18. package/assets/skills/design/{agemon-design-minimal/SKILL.md → agemon-design/references/preset-minimal.md} +8 -12
  19. package/assets/skills/design/agemon-design/references/principles-catalog.md +3 -3
  20. package/assets/skills/design/agemon-design/references/recipe-auth.md +3 -3
  21. package/assets/skills/design/agemon-design/references/recipe-dashboard.md +2 -2
  22. package/assets/skills/design/agemon-design/references/recipe-landing.md +9 -11
  23. package/assets/skills/design/agemon-design/references/review.md +7 -7
  24. package/assets/skills/design/agemon-design/references/routing.md +143 -0
  25. package/assets/skills/design/agemon-design/references/spec.md +8 -8
  26. package/assets/skills/design/agemon-design/references/stack.md +1 -1
  27. package/assets/skills/design/agemon-design/references/stage-assets.md +106 -0
  28. package/assets/skills/design/agemon-design/references/stage-build.md +46 -0
  29. package/assets/skills/design/agemon-design/references/stage-critique.md +34 -0
  30. package/assets/skills/design/agemon-design/references/stage-directions.md +44 -0
  31. package/assets/skills/design/agemon-design/references/stage-intake.md +34 -0
  32. package/assets/skills/design/agemon-design/references/stage-verify.md +44 -0
  33. package/assets/skills/design/agemon-design/references/state-design.md +1 -1
  34. package/assets/skills/design/agemon-design/references/tells-2026-11.md +32 -0
  35. package/assets/skills/design/agemon-design/references/themes.md +24 -20
  36. package/assets/skills/design/agemon-design/references/third-party-licenses.md +323 -0
  37. package/assets/skills/design/agemon-design/references/typography.md +11 -9
  38. package/assets/skills/design/agemon-design/scripts/audit-page.js +532 -0
  39. package/assets/skills/design/agemon-design/scripts/check-source.mjs +358 -0
  40. package/assets/skills/design/agemon-design/scripts/deal.mjs +231 -0
  41. package/assets/skills/design/agemon-design/scripts/inventory.mjs +676 -0
  42. package/assets/skills/{design/agemon-design-dashboard → essentials/web-design-guidelines}/LICENSE +1 -1
  43. package/assets/skills/essentials/web-design-guidelines/NOTICE.md +14 -0
  44. package/assets/skills/essentials/web-design-guidelines/SKILL.md +18 -0
  45. package/assets/skills/essentials/web-design-guidelines/references/guidelines.md +184 -0
  46. package/assets/skills/{design/agemon-design-minimal → essentials/writing-guidelines}/LICENSE +1 -1
  47. package/assets/skills/essentials/writing-guidelines/NOTICE.md +14 -0
  48. package/assets/skills/essentials/writing-guidelines/SKILL.md +18 -0
  49. package/assets/skills/essentials/writing-guidelines/references/guidelines.md +250 -0
  50. package/assets/skills/founder/agemon-founder-board/LICENSE +21 -0
  51. package/assets/skills/founder/agemon-founder-board/NOTICE.md +11 -0
  52. package/assets/skills/founder/agemon-founder-board/SKILL.md +111 -0
  53. package/assets/skills/founder/agemon-founder-board/lenses.md +84 -0
  54. package/assets/skills/founder/agemon-founder-brand/LICENSE +21 -0
  55. package/assets/skills/founder/agemon-founder-brand/NOTICE.md +12 -0
  56. package/assets/skills/founder/agemon-founder-brand/SKILL.md +77 -0
  57. package/assets/skills/founder/agemon-founder-cfo/LICENSE +21 -0
  58. package/assets/skills/founder/agemon-founder-cfo/NOTICE.md +12 -0
  59. package/assets/skills/founder/agemon-founder-cfo/SKILL.md +109 -0
  60. package/assets/skills/founder/agemon-founder-cfo/example.json +27 -0
  61. package/assets/skills/founder/agemon-founder-cfo/unit_economics.py +270 -0
  62. package/assets/skills/founder/agemon-founder-competitors/LICENSE +21 -0
  63. package/assets/skills/founder/agemon-founder-competitors/NOTICE.md +12 -0
  64. package/assets/skills/founder/agemon-founder-competitors/SKILL.md +84 -0
  65. package/assets/skills/founder/agemon-founder-consumer/LICENSE +21 -0
  66. package/assets/skills/founder/agemon-founder-consumer/NOTICE.md +11 -0
  67. package/assets/skills/founder/agemon-founder-consumer/SKILL.md +126 -0
  68. package/assets/skills/founder/agemon-founder-consumer/customer.example.json +34 -0
  69. package/assets/skills/founder/agemon-founder-consumer/panel.py +424 -0
  70. package/assets/skills/founder/agemon-founder-consumer/pitch.example.md +3 -0
  71. package/assets/skills/founder/agemon-founder-launch/LICENSE +21 -0
  72. package/assets/skills/founder/agemon-founder-launch/NOTICE.md +11 -0
  73. package/assets/skills/founder/agemon-founder-launch/SKILL.md +65 -0
  74. package/assets/skills/founder/agemon-founder-marketing/LICENSE +21 -0
  75. package/assets/skills/founder/agemon-founder-marketing/NOTICE.md +11 -0
  76. package/assets/skills/founder/agemon-founder-marketing/SKILL.md +80 -0
  77. package/assets/skills/founder/agemon-founder-offer/LICENSE +21 -0
  78. package/assets/skills/founder/agemon-founder-offer/NOTICE.md +11 -0
  79. package/assets/skills/founder/agemon-founder-offer/SKILL.md +75 -0
  80. package/assets/skills/founder/agemon-founder-ops/LICENSE +21 -0
  81. package/assets/skills/founder/agemon-founder-ops/NOTICE.md +12 -0
  82. package/assets/skills/founder/agemon-founder-ops/SKILL.md +77 -0
  83. package/assets/skills/founder/agemon-founder-plan/LICENSE +21 -0
  84. package/assets/skills/founder/agemon-founder-plan/NOTICE.md +11 -0
  85. package/assets/skills/founder/agemon-founder-plan/SKILL.md +88 -0
  86. package/assets/skills/founder/agemon-founder-plan/compile.py +178 -0
  87. package/assets/skills/founder/agemon-founder-pricing/LICENSE +21 -0
  88. package/assets/skills/founder/agemon-founder-pricing/NOTICE.md +12 -0
  89. package/assets/skills/founder/agemon-founder-pricing/SKILL.md +92 -0
  90. package/assets/skills/founder/agemon-founder-pricing/van_westendorp.py +172 -0
  91. package/assets/skills/{design/agemon-design-editorial → output-style/agemon-adhd}/LICENSE +1 -1
  92. package/assets/skills/output-style/agemon-adhd/NOTICE.md +13 -0
  93. package/assets/skills/output-style/agemon-adhd/SKILL.md +138 -0
  94. package/assets/skills/security/agemon-security-audit/AI-AND-LLM.md +83 -0
  95. package/assets/skills/security/agemon-security-audit/ATTACK-CLASSES.md +130 -0
  96. package/assets/skills/security/agemon-security-audit/CLIENT-SIDE.md +83 -0
  97. package/assets/skills/security/agemon-security-audit/CLOUD-AND-DEPLOYMENT.md +86 -0
  98. package/assets/skills/security/agemon-security-audit/DATA-ISOLATION-AND-LIFECYCLE.md +84 -0
  99. package/assets/skills/security/agemon-security-audit/DESKTOP-MOBILE-AND-LOCAL-IPC.md +89 -0
  100. package/assets/skills/security/agemon-security-audit/HUNTING.md +251 -0
  101. package/assets/skills/security/agemon-security-audit/LICENSE +21 -0
  102. package/assets/skills/security/agemon-security-audit/MEMORY-SAFETY-AND-BINARY.md +101 -0
  103. package/assets/skills/security/agemon-security-audit/NOTICE.md +12 -0
  104. package/assets/skills/security/agemon-security-audit/PROTOCOLS-RPC-AND-MESSAGING.md +81 -0
  105. package/assets/skills/security/agemon-security-audit/RECONNAISSANCE.md +156 -0
  106. package/assets/skills/security/agemon-security-audit/RESOURCE-EXHAUSTION-AND-AVAILABILITY.md +78 -0
  107. package/assets/skills/security/agemon-security-audit/SKILL.md +192 -0
  108. package/assets/skills/security/agemon-security-audit/SUPPLY-CHAIN-AND-RELEASE.md +73 -0
  109. package/assets/skills/security/agemon-security-audit/VALIDATION-AND-REPORTING.md +186 -0
  110. package/assets/skills/security/agemon-security-audit/WEB-PROTOCOL-AND-AUTH.md +105 -0
  111. package/assets/skills/security/agemon-security-audit/report-schema.json +461 -0
  112. package/assets/skills/security/agemon-security-audit/validate-coverage-ledger.cjs +872 -0
  113. package/assets/skills/security/agemon-security-audit/validate-findings.cjs +773 -0
  114. package/assets/skills/workflow/agemon-brainstorming/LICENSE +21 -0
  115. package/assets/skills/workflow/agemon-brainstorming/NOTICE.md +14 -0
  116. package/assets/skills/workflow/agemon-brainstorming/SKILL.md +287 -0
  117. package/assets/skills/workflow/agemon-brainstorming/builder-check-prompt.md +23 -0
  118. package/assets/skills/workflow/agemon-dispatching-parallel-agents/LICENSE +21 -0
  119. package/assets/skills/workflow/agemon-dispatching-parallel-agents/NOTICE.md +13 -0
  120. package/assets/skills/workflow/agemon-dispatching-parallel-agents/SKILL.md +167 -0
  121. package/assets/skills/workflow/agemon-executing-plans/LICENSE +21 -0
  122. package/assets/skills/workflow/agemon-executing-plans/NOTICE.md +15 -0
  123. package/assets/skills/workflow/agemon-executing-plans/SKILL.md +322 -0
  124. package/assets/skills/workflow/agemon-executing-plans/scripts/task-done +55 -0
  125. package/assets/skills/workflow/agemon-executing-plans/scripts/task-start +32 -0
  126. package/assets/skills/workflow/agemon-finishing-a-development-branch/LICENSE +21 -0
  127. package/assets/skills/workflow/agemon-finishing-a-development-branch/NOTICE.md +13 -0
  128. package/assets/skills/workflow/agemon-finishing-a-development-branch/SKILL.md +225 -0
  129. package/assets/skills/workflow/agemon-subagent-driven-development/LICENSE +21 -0
  130. package/assets/skills/workflow/agemon-subagent-driven-development/NOTICE.md +15 -0
  131. package/assets/skills/workflow/agemon-subagent-driven-development/SKILL.md +339 -0
  132. package/assets/skills/workflow/agemon-subagent-driven-development/code-reviewer.md +198 -0
  133. package/assets/skills/workflow/agemon-subagent-driven-development/implementer-prompt.md +154 -0
  134. package/assets/skills/workflow/agemon-subagent-driven-development/re-review-prompt.md +116 -0
  135. package/assets/skills/workflow/agemon-subagent-driven-development/references/batching.md +11 -0
  136. package/assets/skills/workflow/agemon-subagent-driven-development/references/cannot-verify.md +10 -0
  137. package/assets/skills/workflow/agemon-subagent-driven-development/references/final-review.md +49 -0
  138. package/assets/skills/workflow/agemon-subagent-driven-development/references/fix-loop.md +77 -0
  139. package/assets/skills/workflow/agemon-subagent-driven-development/references/handling-reports.md +15 -0
  140. package/assets/skills/workflow/agemon-subagent-driven-development/references/preflight.md +26 -0
  141. package/assets/skills/workflow/agemon-subagent-driven-development/references/resuming.md +12 -0
  142. package/assets/skills/workflow/agemon-subagent-driven-development/references/role-scout.md +18 -0
  143. package/assets/skills/workflow/agemon-subagent-driven-development/references/role-worker.md +19 -0
  144. package/assets/skills/workflow/agemon-subagent-driven-development/scripts/review-package +64 -0
  145. package/assets/skills/workflow/agemon-subagent-driven-development/scripts/sdd-repo +54 -0
  146. package/assets/skills/workflow/agemon-subagent-driven-development/scripts/sdd-workspace +110 -0
  147. package/assets/skills/workflow/agemon-subagent-driven-development/scripts/task-brief +108 -0
  148. package/assets/skills/workflow/agemon-subagent-driven-development/task-reviewer-prompt.md +209 -0
  149. package/assets/skills/workflow/agemon-test-driven-development/LICENSE +21 -0
  150. package/assets/skills/workflow/agemon-test-driven-development/NOTICE.md +14 -0
  151. package/assets/skills/workflow/agemon-test-driven-development/SKILL.md +330 -0
  152. package/assets/skills/workflow/agemon-test-driven-development/writing-good-tests.md +198 -0
  153. package/assets/skills/workflow/agemon-using-git-worktrees/LICENSE +21 -0
  154. package/assets/skills/workflow/agemon-using-git-worktrees/NOTICE.md +13 -0
  155. package/assets/skills/workflow/agemon-using-git-worktrees/SKILL.md +167 -0
  156. package/assets/skills/workflow/agemon-writing-plans/LICENSE +21 -0
  157. package/assets/skills/workflow/agemon-writing-plans/NOTICE.md +13 -0
  158. package/assets/skills/workflow/agemon-writing-plans/SKILL.md +204 -0
  159. package/dist/{chunk-5LATHJYU.js → chunk-ZZBF3GOV.js} +369 -944
  160. package/dist/chunk-ZZBF3GOV.js.map +1 -0
  161. package/dist/{fake-subprocess-2BETWZVZ.js → fake-subprocess-IV4ML77S.js} +3 -33
  162. package/dist/fake-subprocess-IV4ML77S.js.map +1 -0
  163. package/dist/index.js +3477 -731
  164. package/dist/index.js.map +1 -1
  165. package/package.json +8 -1
  166. package/assets/skills/design/agemon-design/references/agents.md +0 -63
  167. package/assets/skills/design/agemon-design-dashboard/NOTICE.md +0 -9
  168. package/assets/skills/design/agemon-design-editorial/NOTICE.md +0 -9
  169. package/assets/skills/design/agemon-design-minimal/NOTICE.md +0 -9
  170. package/dist/chunk-5LATHJYU.js.map +0 -1
  171. package/dist/fake-subprocess-2BETWZVZ.js.map +0 -1
@@ -512,8 +512,6 @@ async function containsHomeDirectory(realDirectory) {
512
512
  // src/plugins/pins.ts
513
513
  var CODE_REVIEW_GRAPH_VERSION = "2.3.9";
514
514
  var CODE_REVIEW_GRAPH_PACKAGE_SPEC = `code-review-graph==${CODE_REVIEW_GRAPH_VERSION}`;
515
- var ESSENTIALS_SKILLS_REPOSITORY_URL = "https://github.com/vercel-labs/agent-skills.git";
516
- var ESSENTIALS_SKILLS_COMMIT = "063bee94c3f4df8453406c830b0a7df0f2860278";
517
515
  var AGNIX_VERSION = "0.58.0";
518
516
  var AGNIX_RELEASE_ARCHIVE_SHA256 = {
519
517
  "agnix-x86_64-unknown-linux-gnu.tar.gz": "68cbf435c87e89319133cd4fd4b8b0c8b0763b17862f231bf495ccb9d8ee074b",
@@ -563,17 +561,137 @@ function fingerprintContent(contents) {
563
561
  return sha256Hex(contents);
564
562
  }
565
563
 
566
- // src/core/state-root.ts
564
+ // src/plugins/skills/skill-tree.ts
567
565
  import { constants as constants3 } from "fs";
568
- import { mkdir as mkdir2, open as open4, readFile as readFile2, realpath as realpath3, stat } from "fs/promises";
566
+ import { lstat as lstat3, open as open3, opendir } from "fs/promises";
567
+ import { join as join2 } from "path";
568
+ var MAX_SKILL_ENTRIES = 200;
569
+ var MAX_SKILL_DEPTH = 8;
570
+ var MAX_SKILL_BYTES = 8 * 1024 * 1024;
571
+ var FINDER_METADATA_FILE = ".DS_Store";
572
+ var SKILLS_CLI_COPY_EXCLUSIONS = {
573
+ anyName: ["metadata.json"],
574
+ directoryNames: [".git", "__pycache__", "__pypackages__"]
575
+ };
576
+ var SkillTreeRefusal = class extends Error {
577
+ };
578
+ var keepEveryEntry = () => false;
579
+ function isLeftOutBySkillsCli(name, stats) {
580
+ return SKILLS_CLI_COPY_EXCLUSIONS.anyName.includes(name) || stats.isDirectory() && SKILLS_CLI_COPY_EXCLUSIONS.directoryNames.includes(
581
+ name
582
+ );
583
+ }
584
+ function isFinderMetadataFile(name, stats) {
585
+ return name === FINDER_METADATA_FILE && stats.isFile();
586
+ }
587
+ async function readRegularFileWithoutFollowing(path, maxBytes) {
588
+ const handle = await open3(
589
+ path,
590
+ constants3.O_RDONLY | constants3.O_NOFOLLOW | constants3.O_NONBLOCK
591
+ );
592
+ try {
593
+ const stats = await handle.stat();
594
+ if (!stats.isFile()) {
595
+ return null;
596
+ }
597
+ if (stats.size > maxBytes) {
598
+ throw new SkillTreeRefusal("it is larger than 8 MiB");
599
+ }
600
+ return await handle.readFile();
601
+ } finally {
602
+ await handle.close();
603
+ }
604
+ }
605
+ async function sortedNamesUpToCap(directory) {
606
+ const names = [];
607
+ for await (const entry of await opendir(directory)) {
608
+ names.push(entry.name);
609
+ if (names.length > MAX_SKILL_ENTRIES) {
610
+ throw new SkillTreeRefusal(
611
+ `it has more than ${MAX_SKILL_ENTRIES} entries`
612
+ );
613
+ }
614
+ }
615
+ return names.sort();
616
+ }
617
+ async function readSkillTree(directory, skipEntry = keepEveryEntry) {
618
+ const entries = [];
619
+ let totalBytes = 0;
620
+ const walk = async (relativeDirectory, depth) => {
621
+ if (depth > MAX_SKILL_DEPTH) {
622
+ throw new SkillTreeRefusal(
623
+ `it is nested deeper than ${MAX_SKILL_DEPTH} levels`
624
+ );
625
+ }
626
+ for (const name of await sortedNamesUpToCap(
627
+ join2(directory, relativeDirectory)
628
+ )) {
629
+ const relativePath = relativeDirectory === "" ? name : `${relativeDirectory}/${name}`;
630
+ const absolutePath = join2(directory, relativePath);
631
+ const stats = await lstat3(absolutePath);
632
+ if (skipEntry(name, stats)) {
633
+ continue;
634
+ }
635
+ if (entries.length >= MAX_SKILL_ENTRIES) {
636
+ throw new SkillTreeRefusal(
637
+ `it has more than ${MAX_SKILL_ENTRIES} entries`
638
+ );
639
+ }
640
+ if (stats.isDirectory()) {
641
+ entries.push({ relativePath, contents: null, mode: stats.mode });
642
+ await walk(relativePath, depth + 1);
643
+ continue;
644
+ }
645
+ const contents = stats.isFile() ? await readRegularFileWithoutFollowing(
646
+ absolutePath,
647
+ MAX_SKILL_BYTES - totalBytes
648
+ ) : null;
649
+ if (contents === null) {
650
+ throw new SkillTreeRefusal(
651
+ `${printable(relativePath)} is a symlink or not a regular file`
652
+ );
653
+ }
654
+ totalBytes += contents.length;
655
+ if (totalBytes > MAX_SKILL_BYTES) {
656
+ throw new SkillTreeRefusal("it is larger than 8 MiB");
657
+ }
658
+ entries.push({ relativePath, contents, mode: stats.mode });
659
+ }
660
+ };
661
+ await walk("", 1);
662
+ return entries;
663
+ }
664
+ function fingerprintSkillTree(entries) {
665
+ return fingerprintJson(
666
+ entries.map((entry) => [
667
+ entry.relativePath,
668
+ entry.contents === null ? null : sha256Hex(entry.contents)
669
+ ])
670
+ );
671
+ }
672
+ async function fingerprintSkillSource(directory) {
673
+ return fingerprintSkillTree(
674
+ await readSkillTree(directory, isLeftOutBySkillsCli)
675
+ );
676
+ }
677
+ function readInstalledSkill(directory) {
678
+ return readSkillTree(directory, isFinderMetadataFile);
679
+ }
680
+ async function fingerprintInstalledSkill(directory) {
681
+ return fingerprintSkillTree(await readInstalledSkill(directory));
682
+ }
683
+
684
+ // src/core/state-root.ts
685
+ import { constants as constants4 } from "fs";
686
+ import { mkdir as mkdir2, open as open5, readFile as readFile2, realpath as realpath3, stat } from "fs/promises";
569
687
  import { homedir as homedir2, userInfo as userInfo2 } from "os";
570
- import { dirname as dirname2, isAbsolute as isAbsolute3, join as join2 } from "path";
688
+ import { dirname as dirname2, isAbsolute as isAbsolute3, join as join3 } from "path";
571
689
 
572
690
  // src/core/file-lock.ts
573
691
  import { AsyncLocalStorage } from "async_hooks";
574
692
  import { execFile } from "child_process";
575
693
  import { randomUUID as randomUUID2 } from "crypto";
576
- import { lstat as lstat3, open as open3, readFile, rm as rm2 } from "fs/promises";
694
+ import { lstat as lstat4, open as open4, readFile, rm as rm2 } from "fs/promises";
577
695
  import { setTimeout as sleep } from "timers/promises";
578
696
  var LOCK_FILE_MODE = 384;
579
697
  var DEFAULT_POLL_MS = 200;
@@ -613,18 +731,18 @@ function processExists(pid) {
613
731
  var linuxProcessProbe = {
614
732
  bootId: () => readTrimmedOrNull("/proc/sys/kernel/random/boot_id"),
615
733
  async startTime(pid) {
616
- const stat3 = await readTrimmedOrNull(`/proc/${pid}/stat`);
617
- return stat3 === null ? null : parseProcessStartTime(stat3);
734
+ const stat2 = await readTrimmedOrNull(`/proc/${pid}/stat`);
735
+ return stat2 === null ? null : parseProcessStartTime(stat2);
618
736
  },
619
737
  exists: processExists
620
738
  };
621
739
  function readBootSessionUuidWithSysctl() {
622
- return new Promise((resolve4, reject) => {
740
+ return new Promise((resolve3, reject) => {
623
741
  execFile(
624
742
  SYSCTL_PATH,
625
743
  ["-n", "kern.bootsessionuuid"],
626
744
  { timeout: SYSCTL_TIMEOUT_MS, maxBuffer: SYSCTL_OUTPUT_LIMIT_BYTES },
627
- (error, stdout) => error ? reject(error) : resolve4(stdout)
745
+ (error, stdout) => error ? reject(error) : resolve3(stdout)
628
746
  );
629
747
  });
630
748
  }
@@ -675,7 +793,7 @@ async function isOwnerAlive(owner, probe) {
675
793
  }
676
794
  async function isOlderThan(path, ageMs) {
677
795
  try {
678
- return Date.now() - (await lstat3(path)).mtimeMs > ageMs;
796
+ return Date.now() - (await lstat4(path)).mtimeMs > ageMs;
679
797
  } catch {
680
798
  return false;
681
799
  }
@@ -690,7 +808,7 @@ async function isStaleLock(lockPath, contents, probe) {
690
808
  async function createLockFile(lockPath, contents) {
691
809
  let handle;
692
810
  try {
693
- handle = await open3(lockPath, "wx", LOCK_FILE_MODE);
811
+ handle = await open4(lockPath, "wx", LOCK_FILE_MODE);
694
812
  } catch (error) {
695
813
  if (error.code === "EEXIST") {
696
814
  return false;
@@ -819,7 +937,7 @@ function resolveStateRoot(hostPlatform = process.platform) {
819
937
  "Cannot locate agemon's state directory: set HOME (or XDG_STATE_HOME) to an absolute path."
820
938
  );
821
939
  }
822
- return hostPlatform === "darwin" ? join2(homeDirectory, "Library", "Application Support") : join2(homeDirectory, ".local", "state");
940
+ return hostPlatform === "darwin" ? join3(homeDirectory, "Library", "Application Support") : join3(homeDirectory, ".local", "state");
823
941
  }
824
942
  async function readColonSeparatedRows(path) {
825
943
  return (await readFile2(path, "utf8")).split("\n").filter((line) => line.length > 0).map((line) => line.split(":"));
@@ -876,9 +994,9 @@ async function assertSafeStateRoot(stateRoot, accounts) {
876
994
  }
877
995
  }
878
996
  async function openAgemonDirectory(directory, mode) {
879
- const flags = constants3.O_RDONLY | constants3.O_DIRECTORY | constants3.O_NOFOLLOW;
997
+ const flags = constants4.O_RDONLY | constants4.O_DIRECTORY | constants4.O_NOFOLLOW;
880
998
  try {
881
- return await open4(directory, flags);
999
+ return await open5(directory, flags);
882
1000
  } catch (error) {
883
1001
  const code = error.code;
884
1002
  if (code === "ELOOP" || code === "ENOTDIR") {
@@ -902,7 +1020,7 @@ async function openAgemonDirectory(directory, mode) {
902
1020
  }
903
1021
  async function resolveAgemonStateDirectory(mode, accounts = currentAccounts()) {
904
1022
  const stateRoot = resolveStateRoot();
905
- const directory = join2(stateRoot, "agemon");
1023
+ const directory = join3(stateRoot, "agemon");
906
1024
  if (mode === "prepare") {
907
1025
  await mkdir2(stateRoot, { recursive: true, mode: PRIVATE_DIRECTORY_MODE });
908
1026
  }
@@ -940,7 +1058,7 @@ async function checkAgemonStateDirectoryBeforeRun(dryRun, report) {
940
1058
  }
941
1059
  }
942
1060
  async function preparePrivateStateDirectory(name) {
943
- const directory = join2(
1061
+ const directory = join3(
944
1062
  (await resolveAgemonStateDirectory("prepare")).path,
945
1063
  name
946
1064
  );
@@ -957,7 +1075,7 @@ async function repositoryStateKey(repoRoot) {
957
1075
  );
958
1076
  }
959
1077
  async function withAgemonStateLock(lockRelativePath, work, waitMs) {
960
- const lockPath = join2(
1078
+ const lockPath = join3(
961
1079
  (await resolveAgemonStateDirectory("prepare")).path,
962
1080
  lockRelativePath
963
1081
  );
@@ -969,16 +1087,78 @@ async function withAgemonStateLock(lockRelativePath, work, waitMs) {
969
1087
  }
970
1088
  async function withRepositoryRunLock(repoRoot, work) {
971
1089
  return withAgemonStateLock(
972
- join2("runs", `${await repositoryStateKey(repoRoot)}.lock`),
1090
+ join3("runs", `${await repositoryStateKey(repoRoot)}.lock`),
973
1091
  () => work(),
974
1092
  RUN_LOCK_WAIT_MS
975
1093
  );
976
1094
  }
977
1095
 
978
- // src/plugins/skills/pinned-source.ts
979
- import { existsSync } from "fs";
980
- import { mkdir as mkdir3, rm as rm3 } from "fs/promises";
981
- import { join as join3 } from "path";
1096
+ // src/plugins/skills/skills-cli.ts
1097
+ import { existsSync as existsSync2 } from "fs";
1098
+ import {
1099
+ copyFile,
1100
+ mkdtemp,
1101
+ readdir,
1102
+ readFile as readFile3,
1103
+ rename as rename2,
1104
+ rm as rm3
1105
+ } from "fs/promises";
1106
+ import { join as join5 } from "path";
1107
+
1108
+ // src/core/package-assets.ts
1109
+ import { existsSync, lstatSync, readFileSync } from "fs";
1110
+ import { dirname as dirname3, join as join4 } from "path";
1111
+ import { fileURLToPath } from "url";
1112
+ var PACKAGE_NAME = "agemon";
1113
+ var PACKAGE_MANIFEST = "package.json";
1114
+ var MAX_PACKAGE_MANIFEST_BYTES = 1024 * 1024;
1115
+ var cachedPackageRoot;
1116
+ function readPackageName(manifestPath) {
1117
+ const stats = lstatSync(manifestPath);
1118
+ if (!stats.isFile() || stats.size > MAX_PACKAGE_MANIFEST_BYTES) {
1119
+ return null;
1120
+ }
1121
+ try {
1122
+ const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
1123
+ return typeof manifest === "object" && manifest !== null && "name" in manifest && typeof manifest.name === "string" ? manifest.name : null;
1124
+ } catch {
1125
+ return null;
1126
+ }
1127
+ }
1128
+ function findNearestPackageDirectory(startDirectory) {
1129
+ let currentDir = startDirectory;
1130
+ for (; ; ) {
1131
+ if (existsSync(join4(currentDir, PACKAGE_MANIFEST))) {
1132
+ return currentDir;
1133
+ }
1134
+ const parentDir = dirname3(currentDir);
1135
+ if (parentDir === currentDir) {
1136
+ return null;
1137
+ }
1138
+ currentDir = parentDir;
1139
+ }
1140
+ }
1141
+ function resolvePackageRootFrom(startDirectory) {
1142
+ const packageDirectory = findNearestPackageDirectory(startDirectory);
1143
+ if (packageDirectory === null || readPackageName(join4(packageDirectory, PACKAGE_MANIFEST)) !== PACKAGE_NAME || !existsSync(join4(packageDirectory, "assets", "skills"))) {
1144
+ throw new Error(
1145
+ "Unable to locate agemon's vendored assets/skills directory."
1146
+ );
1147
+ }
1148
+ return packageDirectory;
1149
+ }
1150
+ function resolvePackageRoot() {
1151
+ cachedPackageRoot ??= resolvePackageRootFrom(
1152
+ dirname3(fileURLToPath(import.meta.url))
1153
+ );
1154
+ return cachedPackageRoot;
1155
+ }
1156
+ function resolveVendoredSkillPath(groupId, skillId) {
1157
+ return join4(resolvePackageRoot(), "assets", "skills", groupId, skillId);
1158
+ }
1159
+ function resolveToolsManifestDirectory() {
1160
+ return join4(resolvePackageRoot(), "assets", "tools");
1161
+ }
982
1162
 
983
1163
  // src/core/subprocess-runner.ts
984
1164
  import { spawn } from "child_process";
@@ -1030,6 +1210,9 @@ var MAX_REDACTED_LINE_CHARACTERS = 4096;
1030
1210
  var HIGH_ENTROPY_MIN_LENGTH = 32;
1031
1211
  var HIGH_ENTROPY_MIN_BITS_PER_CHAR = 3.5;
1032
1212
  var HIGH_ENTROPY_CHARSET = /^[A-Za-z0-9+/=_-]+$/;
1213
+ var MIN_PATH_SEGMENTS = 3;
1214
+ var MIXED_SEGMENT_MIN_LENGTH = 16;
1215
+ var WORD_SEPARATOR = /[-_]/;
1033
1216
  function isDenylistedPath(relativePath) {
1034
1217
  return DENYLISTED_FILE_PATTERNS.some((pattern) => pattern.test(relativePath));
1035
1218
  }
@@ -1045,8 +1228,21 @@ function shannonEntropyBitsPerChar(value) {
1045
1228
  }
1046
1229
  return bitsPerChar;
1047
1230
  }
1231
+ function mixesCasesAndDigits(value) {
1232
+ return /[A-Z]/.test(value) && /[a-z]/.test(value) && /[0-9]/.test(value);
1233
+ }
1234
+ function looksLikeSecretPathSegment(segment) {
1235
+ if (shannonEntropyBitsPerChar(segment) < HIGH_ENTROPY_MIN_BITS_PER_CHAR) {
1236
+ return false;
1237
+ }
1238
+ return segment.length >= MIXED_SEGMENT_MIN_LENGTH && mixesCasesAndDigits(segment) || segment.length >= HIGH_ENTROPY_MIN_LENGTH && !WORD_SEPARATOR.test(segment);
1239
+ }
1240
+ function looksLikeWordPath(value) {
1241
+ const segments = value.split("/");
1242
+ return value.startsWith("/") && segments.length >= MIN_PATH_SEGMENTS && !segments.some(looksLikeSecretPathSegment);
1243
+ }
1048
1244
  function looksHighEntropy(value) {
1049
- return value.length >= HIGH_ENTROPY_MIN_LENGTH && HIGH_ENTROPY_CHARSET.test(value) && shannonEntropyBitsPerChar(value) >= HIGH_ENTROPY_MIN_BITS_PER_CHAR;
1245
+ return value.length >= HIGH_ENTROPY_MIN_LENGTH && HIGH_ENTROPY_CHARSET.test(value) && shannonEntropyBitsPerChar(value) >= HIGH_ENTROPY_MIN_BITS_PER_CHAR && !looksLikeWordPath(value);
1050
1246
  }
1051
1247
  function stripKeyDecoration(rawKey) {
1052
1248
  return rawKey.replace(/^[-"']+/, "").replace(/["':]+$/, "");
@@ -1318,706 +1514,132 @@ function createBoundedCapture() {
1318
1514
  text += `${sliceWithoutSplittingSurrogatePair(chunk, remainingCharacters)}${TRUNCATION_MARKER}`;
1319
1515
  truncated = true;
1320
1516
  },
1321
- get text() {
1322
- return text;
1323
- }
1324
- };
1325
- }
1326
- async function runSubprocess(command, args, options = {}) {
1327
- if (process.env.AGEMON_FAKE_SUBPROCESS === "1") {
1328
- const { runFakeSubprocess } = await import("./fake-subprocess-2BETWZVZ.js");
1329
- return runFakeSubprocess(command, args, options);
1330
- }
1331
- return runRealSubprocess(command, args, options);
1332
- }
1333
- async function runRealSubprocess(command, args, options = {}) {
1334
- const timeoutMs = options.timeoutMs ?? DEFAULT_SUBPROCESS_TIMEOUT_MS;
1335
- return await new Promise((resolve4) => {
1336
- let settled = false;
1337
- let timedOut = false;
1338
- let timeoutHandle;
1339
- let hardKillHandle;
1340
- let drainHandle;
1341
- const stdout = createBoundedCapture();
1342
- const stderr = createBoundedCapture();
1343
- const clearTimers = () => {
1344
- clearTimeout(timeoutHandle);
1345
- clearTimeout(hardKillHandle);
1346
- clearTimeout(drainHandle);
1347
- };
1348
- const finalize = (result) => {
1349
- if (settled) {
1350
- return;
1351
- }
1352
- settled = true;
1353
- clearTimers();
1354
- resolve4(result);
1355
- };
1356
- const resultForExit = (code, signal) => {
1357
- if (timedOut) {
1358
- const timeoutMessage = `Command timed out after ${timeoutMs}ms.`;
1359
- return {
1360
- code: TIMEOUT_EXIT_CODE,
1361
- stdout: stdout.text,
1362
- stderr: stderr.text ? `${stderr.text}
1363
- ${timeoutMessage}` : timeoutMessage
1364
- };
1365
- }
1366
- if (signal) {
1367
- return {
1368
- code: 1,
1369
- stdout: stdout.text,
1370
- stderr: `${stderr.text}Process terminated by signal: ${signal}`
1371
- };
1372
- }
1373
- return { code: code ?? 1, stdout: stdout.text, stderr: stderr.text };
1374
- };
1375
- const finalizeAfterDrainGrace = (code, signal) => {
1376
- clearTimeout(drainHandle);
1377
- drainHandle = setTimeout(() => {
1378
- childProcess.stdout.destroy();
1379
- childProcess.stderr.destroy();
1380
- finalize(resultForExit(code, signal));
1381
- }, STREAM_DRAIN_GRACE_MS);
1382
- };
1383
- const environment = {
1384
- ...agemonSubprocessEnvironment(),
1385
- ...options.env
1386
- };
1387
- for (const name of options.unsetEnv ?? []) {
1388
- delete environment[name];
1389
- }
1390
- const childProcess = spawn(command, args, {
1391
- cwd: options.cwd ?? process.cwd(),
1392
- env: environment,
1393
- stdio: ["ignore", "pipe", "pipe"]
1394
- });
1395
- if (timeoutMs > 0) {
1396
- timeoutHandle = setTimeout(() => {
1397
- timedOut = true;
1398
- const signal = options.killSignal ?? "SIGTERM";
1399
- const terminated = childProcess.kill(signal);
1400
- if (!terminated) {
1401
- finalize({
1402
- code: TIMEOUT_EXIT_CODE,
1403
- stdout: stdout.text,
1404
- stderr: `${stderr.text}
1405
- Command timed out after ${timeoutMs}ms and could not be signaled with ${signal}.`
1406
- });
1407
- return;
1408
- }
1409
- hardKillHandle = setTimeout(() => {
1410
- childProcess.kill("SIGKILL");
1411
- finalizeAfterDrainGrace(null, "SIGKILL");
1412
- }, HARD_KILL_GRACE_MS);
1413
- }, timeoutMs);
1414
- }
1415
- childProcess.stdout.setEncoding("utf8");
1416
- childProcess.stderr.setEncoding("utf8");
1417
- childProcess.stdout.on("data", (chunk) => stdout.append(chunk));
1418
- childProcess.stderr.on("data", (chunk) => stderr.append(chunk));
1419
- childProcess.on("error", (error) => {
1420
- const errorMessage = stderr.text ? `${stderr.text}
1421
- ${SPAWN_ERROR_PREFIX}${error.message}` : `${SPAWN_ERROR_PREFIX}${error.message}`;
1422
- finalize({ code: 1, stdout: stdout.text, stderr: errorMessage });
1423
- });
1424
- childProcess.on(
1425
- "exit",
1426
- (code, signal) => {
1427
- clearTimeout(timeoutHandle);
1428
- clearTimeout(hardKillHandle);
1429
- finalizeAfterDrainGrace(code, signal);
1430
- }
1431
- );
1432
- childProcess.on(
1433
- "close",
1434
- (code, signal) => {
1435
- finalize(resultForExit(code, signal));
1436
- }
1437
- );
1438
- });
1439
- }
1440
-
1441
- // src/plugins/skills/pinned-source.ts
1442
- var SOURCE_DIRECTORY_MODE = 448;
1443
- var GIT_STEP_TIMEOUT_MS = 12e4;
1444
- var GIT_SYMLINK_MODE = "120000";
1445
- var GIT_WITHOUT_HOOKS_ARGS = [
1446
- "-c",
1447
- "core.hooksPath=/dev/null",
1448
- "-c",
1449
- "core.fsmonitor=false",
1450
- "-c",
1451
- "credential.helper="
1452
- ];
1453
- function resolvePinnedSkillsSourceDirectory(commit) {
1454
- return join3(resolveStateRoot(), "agemon", "skills-src", commit);
1455
- }
1456
- async function localGitOutput(ctx, sourceDirectory, subcommandArgs) {
1457
- const result = await ctx.run(
1458
- "git",
1459
- [...GIT_WITHOUT_HOOKS_ARGS, ...subcommandArgs],
1460
- {
1461
- cwd: sourceDirectory,
1462
- timeoutMs: GIT_STEP_TIMEOUT_MS,
1463
- env: isolatedGitEnvironment(sourceDirectory)
1464
- }
1465
- );
1466
- return result.code === 0 ? result.stdout : null;
1467
- }
1468
- async function isPristinePinnedCheckout(ctx, repository) {
1469
- const sourceDirectory = resolvePinnedSkillsSourceDirectory(repository.commit);
1470
- if (!existsSync(join3(sourceDirectory, ".git"))) {
1471
- return false;
1472
- }
1473
- try {
1474
- const head = await localGitOutput(ctx, sourceDirectory, [
1475
- "rev-parse",
1476
- "--verify",
1477
- "--end-of-options",
1478
- "HEAD^{commit}"
1479
- ]);
1480
- if (head?.trim() !== repository.commit) {
1481
- return false;
1482
- }
1483
- const status = await localGitOutput(ctx, sourceDirectory, [
1484
- "status",
1485
- "--porcelain",
1486
- "--ignored"
1487
- ]);
1488
- return status !== null && status.trim() === "";
1489
- } catch {
1490
- return false;
1491
- }
1492
- }
1493
- function skillPathInRepository(skillName) {
1494
- return `skills/${skillName}`;
1495
- }
1496
- function resolvePinnedSkillPath(repository, skillName) {
1497
- return join3(
1498
- resolvePinnedSkillsSourceDirectory(repository.commit),
1499
- skillPathInRepository(skillName)
1500
- );
1501
- }
1502
- function isolatedGitEnvironment(sourceDirectory) {
1503
- const gitDirectory = join3(sourceDirectory, ".git");
1504
- return {
1505
- GIT_TERMINAL_PROMPT: "0",
1506
- GIT_CONFIG_GLOBAL: "/dev/null",
1507
- GIT_CONFIG_NOSYSTEM: "1",
1508
- GIT_CONFIG_COUNT: "0",
1509
- GIT_CONFIG_PARAMETERS: "",
1510
- GIT_ASKPASS: "",
1511
- SSH_ASKPASS: "",
1512
- GIT_DIR: gitDirectory,
1513
- GIT_WORK_TREE: sourceDirectory,
1514
- GIT_COMMON_DIR: gitDirectory,
1515
- GIT_INDEX_FILE: join3(gitDirectory, "index"),
1516
- GIT_OBJECT_DIRECTORY: join3(gitDirectory, "objects"),
1517
- GIT_ALTERNATE_OBJECT_DIRECTORIES: ""
1518
- };
1519
- }
1520
- async function runGitStep(ctx, sourceDirectory, subcommandArgs) {
1521
- const result = await ctx.run(
1522
- "git",
1523
- [...GIT_WITHOUT_HOOKS_ARGS, ...subcommandArgs],
1524
- {
1525
- cwd: sourceDirectory,
1526
- timeoutMs: GIT_STEP_TIMEOUT_MS,
1527
- env: isolatedGitEnvironment(sourceDirectory)
1528
- }
1529
- );
1530
- if (result.code !== 0) {
1531
- throw new Error(
1532
- `git ${subcommandArgs[0]} failed while fetching pinned skills: ${describeSubprocessFailure(result, "git")}`
1533
- );
1534
- }
1535
- return result;
1536
- }
1537
- function findSymlinkPaths(lsTreeOutput) {
1538
- return lsTreeOutput.split("\n").filter((line) => line.startsWith(`${GIT_SYMLINK_MODE} `)).map((line) => line.slice(line.indexOf(" ") + 1));
1539
- }
1540
- async function assertSkillIsPlainFiles(ctx, sourceDirectory, skillName) {
1541
- const skillPath = skillPathInRepository(skillName);
1542
- const listing = await runGitStep(ctx, sourceDirectory, [
1543
- "ls-tree",
1544
- "-r",
1545
- "HEAD",
1546
- "--",
1547
- skillPath
1548
- ]);
1549
- if (listing.stdout.trim().length === 0) {
1550
- throw new Error(`The pinned skills commit has no ${skillPath}.`);
1551
- }
1552
- const symlinkPaths = findSymlinkPaths(listing.stdout);
1553
- if (symlinkPaths.length > 0) {
1554
- throw new Error(
1555
- `Refusing to install pinned skills: ${symlinkPaths.map(printable).join(", ")} is a symlink.`
1556
- );
1557
- }
1558
- }
1559
- async function fetchPinnedSkillsSource(ctx, repository, skillNames) {
1560
- const sourceDirectory = resolvePinnedSkillsSourceDirectory(repository.commit);
1561
- await rm3(sourceDirectory, { recursive: true, force: true });
1562
- await mkdir3(sourceDirectory, {
1563
- recursive: true,
1564
- mode: SOURCE_DIRECTORY_MODE
1565
- });
1566
- await runGitStep(ctx, sourceDirectory, ["init", "-q"]);
1567
- await runGitStep(ctx, sourceDirectory, [
1568
- "fetch",
1569
- "--depth",
1570
- "1",
1571
- repository.url,
1572
- repository.commit
1573
- ]);
1574
- await runGitStep(ctx, sourceDirectory, ["checkout", "-q", "FETCH_HEAD"]);
1575
- const head = (await runGitStep(ctx, sourceDirectory, ["rev-parse", "HEAD"])).stdout.trim();
1576
- if (head !== repository.commit) {
1577
- throw new Error(
1578
- `Pinned skills checkout mismatch: expected commit ${repository.commit}, got ${printable(head)}.`
1579
- );
1580
- }
1581
- for (const skillName of skillNames) {
1582
- await assertSkillIsPlainFiles(ctx, sourceDirectory, skillName);
1583
- }
1584
- }
1585
-
1586
- // src/plugins/skills/catalog.ts
1587
- import { join as join5 } from "path";
1588
-
1589
- // src/core/package-assets.ts
1590
- import { existsSync as existsSync2, lstatSync, readFileSync } from "fs";
1591
- import { dirname as dirname3, join as join4 } from "path";
1592
- import { fileURLToPath } from "url";
1593
- var PACKAGE_NAME = "agemon";
1594
- var PACKAGE_MANIFEST = "package.json";
1595
- var MAX_PACKAGE_MANIFEST_BYTES = 1024 * 1024;
1596
- var cachedPackageRoot;
1597
- function readPackageName(manifestPath) {
1598
- const stats = lstatSync(manifestPath);
1599
- if (!stats.isFile() || stats.size > MAX_PACKAGE_MANIFEST_BYTES) {
1600
- return null;
1601
- }
1602
- try {
1603
- const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
1604
- return typeof manifest === "object" && manifest !== null && "name" in manifest && typeof manifest.name === "string" ? manifest.name : null;
1605
- } catch {
1606
- return null;
1607
- }
1608
- }
1609
- function findNearestPackageDirectory(startDirectory) {
1610
- let currentDir = startDirectory;
1611
- for (; ; ) {
1612
- if (existsSync2(join4(currentDir, PACKAGE_MANIFEST))) {
1613
- return currentDir;
1614
- }
1615
- const parentDir = dirname3(currentDir);
1616
- if (parentDir === currentDir) {
1617
- return null;
1618
- }
1619
- currentDir = parentDir;
1620
- }
1621
- }
1622
- function resolvePackageRootFrom(startDirectory) {
1623
- const packageDirectory = findNearestPackageDirectory(startDirectory);
1624
- if (packageDirectory === null || readPackageName(join4(packageDirectory, PACKAGE_MANIFEST)) !== PACKAGE_NAME || !existsSync2(join4(packageDirectory, "assets", "skills"))) {
1625
- throw new Error(
1626
- "Unable to locate agemon's vendored assets/skills directory."
1627
- );
1628
- }
1629
- return packageDirectory;
1630
- }
1631
- function resolvePackageRoot() {
1632
- cachedPackageRoot ??= resolvePackageRootFrom(
1633
- dirname3(fileURLToPath(import.meta.url))
1634
- );
1635
- return cachedPackageRoot;
1636
- }
1637
- function resolveVendoredSkillPath(groupId, skillId) {
1638
- return join4(resolvePackageRoot(), "assets", "skills", groupId, skillId);
1639
- }
1640
- function resolveToolsManifestDirectory() {
1641
- return join4(resolvePackageRoot(), "assets", "tools");
1642
- }
1643
-
1644
- // src/plugins/skills/catalog.ts
1645
- var ESSENTIALS_REPOSITORY = {
1646
- url: ESSENTIALS_SKILLS_REPOSITORY_URL,
1647
- commit: ESSENTIALS_SKILLS_COMMIT
1648
- };
1649
- var GEO_AUDIT_AGENT_DESCRIPTION_SUFFIX = "Used by the geo-audit skill; do not use it for other tasks.";
1650
- function vendoredSkill(groupId, skillId) {
1651
- return {
1652
- id: skillId,
1653
- get source() {
1654
- return resolveVendoredSkillPath(groupId, skillId);
1655
- },
1656
- skillName: skillId,
1657
- agent: "claude-code"
1658
- };
1659
- }
1660
- function pinnedSkill(repository, skillId) {
1661
- return {
1662
- id: skillId,
1663
- get source() {
1664
- return resolvePinnedSkillPath(repository, skillId);
1665
- },
1666
- skillName: skillId,
1667
- agent: "claude-code",
1668
- pinnedRepository: repository
1669
- };
1670
- }
1671
- function geoAuditAgent(name, briefFileName, purpose, tools) {
1672
- return {
1673
- name,
1674
- description: `${purpose} ${GEO_AUDIT_AGENT_DESCRIPTION_SUFFIX}`,
1675
- tools,
1676
- get briefPath() {
1677
- return join5(
1678
- resolveVendoredSkillPath("geo-seo", "geo-audit"),
1679
- "references",
1680
- briefFileName
1681
- );
1682
- }
1683
- };
1684
- }
1685
- var SKILL_GROUPS = [
1686
- {
1687
- id: "essentials",
1688
- label: "Essentials",
1689
- description: "Web design and writing guidelines from Vercel Labs.",
1690
- defaultSelected: true,
1691
- skills: [
1692
- pinnedSkill(ESSENTIALS_REPOSITORY, "web-design-guidelines"),
1693
- pinnedSkill(ESSENTIALS_REPOSITORY, "writing-guidelines")
1694
- ]
1695
- },
1696
- {
1697
- id: "design",
1698
- label: "Design & UI/UX",
1699
- description: "agemon-design: design engineering with anti-slop rules, discovery, and outcome recipes for dashboards, landings, and auth screens.",
1700
- defaultSelected: false,
1701
- skills: [
1702
- vendoredSkill("design", "agemon-design"),
1703
- vendoredSkill("design", "agemon-design-minimal"),
1704
- vendoredSkill("design", "agemon-design-editorial"),
1705
- vendoredSkill("design", "agemon-design-dashboard")
1706
- ]
1707
- },
1708
- {
1709
- id: "security",
1710
- label: "Security",
1711
- description: "Exploit-driven security review \u2014 no finding without a working proof-of-concept, CVSS-aligned severity.",
1712
- defaultSelected: false,
1713
- skills: [vendoredSkill("security", "agemon-security")]
1714
- },
1715
- {
1716
- id: "code-quality",
1717
- label: "Code Quality",
1718
- description: "Simplicity, DRY architecture, self-documenting naming, and surgical scope control for day-to-day edits.",
1719
- defaultSelected: false,
1720
- skills: [
1721
- vendoredSkill("code-quality", "agemon-clean-code"),
1722
- vendoredSkill("code-quality", "agemon-house-rules")
1723
- ]
1724
- },
1725
- {
1726
- id: "architecture",
1727
- label: "Code Architecture",
1728
- description: "Clean Architecture review: dependency rule, layer separation, boundary crossing, SOLID.",
1729
- defaultSelected: false,
1730
- skills: [vendoredSkill("architecture", "agemon-architecture")]
1731
- },
1732
- {
1733
- id: "self-review",
1734
- label: "Self-Review",
1735
- description: "Verification before claiming completion, giving and receiving code review, and root-cause-first debugging.",
1736
- defaultSelected: false,
1737
- skills: [
1738
- vendoredSkill("self-review", "agemon-verify-before-done"),
1739
- vendoredSkill("self-review", "agemon-review-intake"),
1740
- vendoredSkill("self-review", "agemon-review-request"),
1741
- vendoredSkill("self-review", "agemon-root-cause")
1742
- ]
1743
- },
1744
- {
1745
- id: "performance",
1746
- label: "Performance",
1747
- description: "Algorithmic-complexity-first discipline: N+1 detection, hot-loop hygiene, and when not to optimize.",
1748
- defaultSelected: false,
1749
- skills: [vendoredSkill("performance", "agemon-performance")]
1750
- },
1751
- {
1752
- id: "commit",
1753
- label: "Commit Hygiene",
1754
- description: "Staging review, commit message structure, and splitting unrelated changes into separate commits.",
1755
- defaultSelected: false,
1756
- skills: [vendoredSkill("commit", "agemon-commit")]
1757
- },
1758
- {
1759
- id: "teamlead",
1760
- label: "Team Lead",
1761
- description: "Team-lead workflows: structured RFC planning and PRD generation for major features or architectural changes.",
1762
- defaultSelected: false,
1763
- skills: [
1764
- vendoredSkill("team-lead", "agemon-plan-rfc"),
1765
- vendoredSkill("team-lead", "prd-generator"),
1766
- vendoredSkill("team-lead", "skill-headofit-audit"),
1767
- vendoredSkill("team-lead", "skill-incident-rca"),
1768
- vendoredSkill("team-lead", "skill-meeting-lifecycle"),
1769
- vendoredSkill("team-lead", "skill-obsidian-vault-sync"),
1770
- vendoredSkill("team-lead", "skill-prd-decomposer"),
1771
- vendoredSkill("team-lead", "skill-sec-check"),
1772
- vendoredSkill("team-lead", "skill-task-extractor"),
1773
- vendoredSkill("team-lead", "skill-techlead-reviewer"),
1774
- vendoredSkill("team-lead", "skill-tech-spike")
1775
- ]
1776
- },
1777
- {
1778
- id: "geo-seo",
1779
- label: "GEO / AI Search SEO",
1780
- description: "Audit and optimize websites for AI search citation (ChatGPT, Perplexity, Google AI Overviews): citability, AI crawlers, llms.txt, schema, technical SEO, reports.",
1781
- defaultSelected: false,
1782
- skills: [
1783
- vendoredSkill("geo-seo", "geo"),
1784
- vendoredSkill("geo-seo", "geo-audit"),
1785
- vendoredSkill("geo-seo", "geo-citability"),
1786
- vendoredSkill("geo-seo", "geo-crawlers"),
1787
- vendoredSkill("geo-seo", "geo-llmstxt"),
1788
- vendoredSkill("geo-seo", "geo-brand-mentions"),
1789
- vendoredSkill("geo-seo", "geo-platform-optimizer"),
1790
- vendoredSkill("geo-seo", "geo-technical"),
1791
- vendoredSkill("geo-seo", "geo-content"),
1792
- vendoredSkill("geo-seo", "geo-report"),
1793
- vendoredSkill("geo-seo", "geo-schema"),
1794
- vendoredSkill("geo-seo", "geo-report-pdf")
1795
- ],
1796
- agents: [
1797
- geoAuditAgent(
1798
- "geo-audit-ai-visibility",
1799
- "ai-visibility.md",
1800
- "Scores how quotable and visible a website is to AI search: citability, AI crawler access, llms.txt and brand presence.",
1801
- ["WebFetch"]
1802
- ),
1803
- geoAuditAgent(
1804
- "geo-audit-platform",
1805
- "platform-analysis.md",
1806
- "Scores a website's readiness for Google AI Overviews, ChatGPT, Perplexity, Gemini and Bing Copilot.",
1807
- ["WebFetch"]
1808
- ),
1809
- geoAuditAgent(
1810
- "geo-audit-technical",
1811
- "technical.md",
1812
- "Scores a website's technical health for AI crawlers: rendering, meta tags, headers, speed and security headers.",
1813
- ["WebFetch", "Bash"]
1814
- ),
1815
- geoAuditAgent(
1816
- "geo-audit-content",
1817
- "content.md",
1818
- "Scores a website's content quality and E-E-A-T signals: experience, expertise, authority and trust.",
1819
- ["WebFetch"]
1820
- ),
1821
- geoAuditAgent(
1822
- "geo-audit-schema",
1823
- "schema.md",
1824
- "Scores a website's schema.org structured data and finds missing GEO-relevant schema.",
1825
- ["WebFetch", "Bash"]
1826
- )
1827
- ]
1828
- }
1829
- ];
1830
- var RETIRED_AGENT_NAMES = [];
1831
- function findSkillGroup(groupId) {
1832
- return SKILL_GROUPS.find((group) => group.id === groupId);
1833
- }
1834
- var CUSTOM_GROUP_DESCRIPTION = "Defined in this repository's agemon.toml, not by agemon.";
1835
- function localSkill(path, skillName) {
1836
- return {
1837
- id: skillName,
1838
- source: path,
1839
- skillName,
1840
- agent: "claude-code",
1841
- localSourcePath: path
1842
- };
1843
- }
1844
- function failCustomGroups(detail) {
1845
- throw new Error(`agemon.toml is invalid: ${printable(detail)}`);
1846
- }
1847
- function buildCustomSkillGroups(configs) {
1848
- const builtInSkillNames = new Set(
1849
- SKILL_GROUPS.flatMap(
1850
- (group) => group.skills.map((skill) => skill.skillName)
1851
- )
1852
- );
1853
- return configs.map((config) => {
1854
- if (findSkillGroup(config.id) !== void 0) {
1855
- failCustomGroups(
1856
- `custom_skill_groups.${config.id} uses the id of a built-in skill group`
1857
- );
1858
- }
1859
- return {
1860
- id: config.id,
1861
- label: config.label,
1862
- description: CUSTOM_GROUP_DESCRIPTION,
1863
- defaultSelected: false,
1864
- definedByRepository: true,
1865
- skills: config.skills.map((skill) => {
1866
- if (builtInSkillNames.has(skill.skillName)) {
1867
- failCustomGroups(
1868
- `custom_skill_groups.${config.id} names '${skill.skillName}', which is a built-in skill`
1869
- );
1870
- }
1871
- return skill.kind === "local" ? localSkill(skill.path, skill.skillName) : pinnedSkill(
1872
- {
1873
- url: `https://github.com/${skill.owner}/${skill.repository}`,
1874
- commit: skill.ref
1875
- },
1876
- skill.skillName
1877
- );
1878
- })
1879
- };
1880
- });
1881
- }
1882
- function assertCustomSkillGroupsAreValid(configs) {
1883
- buildCustomSkillGroups(configs);
1884
- }
1885
-
1886
- // src/plugins/skills/skill-tree.ts
1887
- import { constants as constants4 } from "fs";
1888
- import { lstat as lstat4, open as open5, opendir } from "fs/promises";
1889
- import { join as join6 } from "path";
1890
- var MAX_SKILL_ENTRIES = 200;
1891
- var MAX_SKILL_DEPTH = 8;
1892
- var MAX_SKILL_BYTES = 8 * 1024 * 1024;
1893
- var FINDER_METADATA_FILE = ".DS_Store";
1894
- var SKILLS_CLI_COPY_EXCLUSIONS = {
1895
- anyName: ["metadata.json"],
1896
- directoryNames: [".git", "__pycache__", "__pypackages__"]
1897
- };
1898
- var SkillTreeRefusal = class extends Error {
1899
- };
1900
- var keepEveryEntry = () => false;
1901
- function isLeftOutBySkillsCli(name, stats) {
1902
- return SKILLS_CLI_COPY_EXCLUSIONS.anyName.includes(name) || stats.isDirectory() && SKILLS_CLI_COPY_EXCLUSIONS.directoryNames.includes(
1903
- name
1904
- );
1905
- }
1906
- function isFinderMetadataFile(name, stats) {
1907
- return name === FINDER_METADATA_FILE && stats.isFile();
1908
- }
1909
- async function readRegularFileWithoutFollowing(path, maxBytes) {
1910
- const handle = await open5(
1911
- path,
1912
- constants4.O_RDONLY | constants4.O_NOFOLLOW | constants4.O_NONBLOCK
1913
- );
1914
- try {
1915
- const stats = await handle.stat();
1916
- if (!stats.isFile()) {
1917
- return null;
1918
- }
1919
- if (stats.size > maxBytes) {
1920
- throw new SkillTreeRefusal("it is larger than 8 MiB");
1921
- }
1922
- return await handle.readFile();
1923
- } finally {
1924
- await handle.close();
1925
- }
1926
- }
1927
- async function sortedNamesUpToCap(directory) {
1928
- const names = [];
1929
- for await (const entry of await opendir(directory)) {
1930
- names.push(entry.name);
1931
- if (names.length > MAX_SKILL_ENTRIES) {
1932
- throw new SkillTreeRefusal(
1933
- `it has more than ${MAX_SKILL_ENTRIES} entries`
1934
- );
1517
+ get text() {
1518
+ return text;
1935
1519
  }
1520
+ };
1521
+ }
1522
+ async function runSubprocess(command, args, options = {}) {
1523
+ if (process.env.AGEMON_FAKE_SUBPROCESS === "1") {
1524
+ const { runFakeSubprocess } = await import("./fake-subprocess-IV4ML77S.js");
1525
+ return runFakeSubprocess(command, args, options);
1936
1526
  }
1937
- return names.sort();
1527
+ return runRealSubprocess(command, args, options);
1938
1528
  }
1939
- async function readSkillTree(directory, skipEntry = keepEveryEntry) {
1940
- const entries = [];
1941
- let totalBytes = 0;
1942
- const walk = async (relativeDirectory, depth) => {
1943
- if (depth > MAX_SKILL_DEPTH) {
1944
- throw new SkillTreeRefusal(
1945
- `it is nested deeper than ${MAX_SKILL_DEPTH} levels`
1946
- );
1947
- }
1948
- for (const name of await sortedNamesUpToCap(
1949
- join6(directory, relativeDirectory)
1950
- )) {
1951
- const relativePath = relativeDirectory === "" ? name : `${relativeDirectory}/${name}`;
1952
- const absolutePath = join6(directory, relativePath);
1953
- const stats = await lstat4(absolutePath);
1954
- if (skipEntry(name, stats)) {
1955
- continue;
1529
+ async function runRealSubprocess(command, args, options = {}) {
1530
+ const timeoutMs = options.timeoutMs ?? DEFAULT_SUBPROCESS_TIMEOUT_MS;
1531
+ return await new Promise((resolve3) => {
1532
+ let settled = false;
1533
+ let timedOut = false;
1534
+ let timeoutHandle;
1535
+ let hardKillHandle;
1536
+ let drainHandle;
1537
+ const stdout = createBoundedCapture();
1538
+ const stderr = createBoundedCapture();
1539
+ const clearTimers = () => {
1540
+ clearTimeout(timeoutHandle);
1541
+ clearTimeout(hardKillHandle);
1542
+ clearTimeout(drainHandle);
1543
+ };
1544
+ const finalize = (result) => {
1545
+ if (settled) {
1546
+ return;
1956
1547
  }
1957
- if (entries.length >= MAX_SKILL_ENTRIES) {
1958
- throw new SkillTreeRefusal(
1959
- `it has more than ${MAX_SKILL_ENTRIES} entries`
1960
- );
1548
+ settled = true;
1549
+ clearTimers();
1550
+ resolve3(result);
1551
+ };
1552
+ const resultForExit = (code, signal) => {
1553
+ if (timedOut) {
1554
+ const timeoutMessage = `Command timed out after ${timeoutMs}ms.`;
1555
+ return {
1556
+ code: TIMEOUT_EXIT_CODE,
1557
+ stdout: stdout.text,
1558
+ stderr: stderr.text ? `${stderr.text}
1559
+ ${timeoutMessage}` : timeoutMessage
1560
+ };
1961
1561
  }
1962
- if (stats.isDirectory()) {
1963
- entries.push({ relativePath, contents: null });
1964
- await walk(relativePath, depth + 1);
1965
- continue;
1562
+ if (signal) {
1563
+ return {
1564
+ code: 1,
1565
+ stdout: stdout.text,
1566
+ stderr: `${stderr.text}Process terminated by signal: ${signal}`
1567
+ };
1966
1568
  }
1967
- const contents = stats.isFile() ? await readRegularFileWithoutFollowing(
1968
- absolutePath,
1969
- MAX_SKILL_BYTES - totalBytes
1970
- ) : null;
1971
- if (contents === null) {
1972
- throw new SkillTreeRefusal(
1973
- `${printable(relativePath)} is a symlink or not a regular file`
1974
- );
1569
+ return { code: code ?? 1, stdout: stdout.text, stderr: stderr.text };
1570
+ };
1571
+ const finalizeAfterDrainGrace = (code, signal) => {
1572
+ clearTimeout(drainHandle);
1573
+ drainHandle = setTimeout(() => {
1574
+ childProcess.stdout.destroy();
1575
+ childProcess.stderr.destroy();
1576
+ finalize(resultForExit(code, signal));
1577
+ }, STREAM_DRAIN_GRACE_MS);
1578
+ };
1579
+ const environment = {
1580
+ ...agemonSubprocessEnvironment(),
1581
+ ...options.env
1582
+ };
1583
+ for (const name of options.unsetEnv ?? []) {
1584
+ delete environment[name];
1585
+ }
1586
+ const childProcess = spawn(command, args, {
1587
+ cwd: options.cwd ?? process.cwd(),
1588
+ env: environment,
1589
+ stdio: ["ignore", "pipe", "pipe"]
1590
+ });
1591
+ if (timeoutMs > 0) {
1592
+ timeoutHandle = setTimeout(() => {
1593
+ timedOut = true;
1594
+ const signal = options.killSignal ?? "SIGTERM";
1595
+ const terminated = childProcess.kill(signal);
1596
+ if (!terminated) {
1597
+ finalize({
1598
+ code: TIMEOUT_EXIT_CODE,
1599
+ stdout: stdout.text,
1600
+ stderr: `${stderr.text}
1601
+ Command timed out after ${timeoutMs}ms and could not be signaled with ${signal}.`
1602
+ });
1603
+ return;
1604
+ }
1605
+ hardKillHandle = setTimeout(() => {
1606
+ childProcess.kill("SIGKILL");
1607
+ finalizeAfterDrainGrace(null, "SIGKILL");
1608
+ }, HARD_KILL_GRACE_MS);
1609
+ }, timeoutMs);
1610
+ }
1611
+ childProcess.stdout.setEncoding("utf8");
1612
+ childProcess.stderr.setEncoding("utf8");
1613
+ childProcess.stdout.on("data", (chunk) => stdout.append(chunk));
1614
+ childProcess.stderr.on("data", (chunk) => stderr.append(chunk));
1615
+ childProcess.on("error", (error) => {
1616
+ const errorMessage = stderr.text ? `${stderr.text}
1617
+ ${SPAWN_ERROR_PREFIX}${error.message}` : `${SPAWN_ERROR_PREFIX}${error.message}`;
1618
+ finalize({ code: 1, stdout: stdout.text, stderr: errorMessage });
1619
+ });
1620
+ childProcess.on(
1621
+ "exit",
1622
+ (code, signal) => {
1623
+ clearTimeout(timeoutHandle);
1624
+ clearTimeout(hardKillHandle);
1625
+ finalizeAfterDrainGrace(code, signal);
1975
1626
  }
1976
- totalBytes += contents.length;
1977
- if (totalBytes > MAX_SKILL_BYTES) {
1978
- throw new SkillTreeRefusal("it is larger than 8 MiB");
1627
+ );
1628
+ childProcess.on(
1629
+ "close",
1630
+ (code, signal) => {
1631
+ finalize(resultForExit(code, signal));
1979
1632
  }
1980
- entries.push({ relativePath, contents });
1981
- }
1982
- };
1983
- await walk("", 1);
1984
- return entries;
1985
- }
1986
- function fingerprintSkillTree(entries) {
1987
- return fingerprintJson(
1988
- entries.map((entry) => [
1989
- entry.relativePath,
1990
- entry.contents === null ? null : sha256Hex(entry.contents)
1991
- ])
1992
- );
1993
- }
1994
- async function fingerprintSkillSource(directory) {
1995
- return fingerprintSkillTree(
1996
- await readSkillTree(directory, isLeftOutBySkillsCli)
1997
- );
1998
- }
1999
- async function fingerprintInstalledSkill(directory) {
2000
- return fingerprintSkillTree(
2001
- await readSkillTree(directory, isFinderMetadataFile)
2002
- );
1633
+ );
1634
+ });
2003
1635
  }
2004
1636
 
2005
1637
  // src/plugins/skills/skills-cli.ts
2006
- import { existsSync as existsSync3 } from "fs";
2007
- import {
2008
- copyFile,
2009
- mkdtemp,
2010
- readdir,
2011
- readFile as readFile3,
2012
- rename as rename2,
2013
- rm as rm4
2014
- } from "fs/promises";
2015
- import { join as join7 } from "path";
2016
1638
  var TOOLS_LOCK_HASH_LENGTH = 16;
2017
1639
  var TOOLS_INSTALL_TIMEOUT_MS = 18e4;
2018
1640
  var TOOLS_LOCK_WAIT_MS = 10 * 6e4;
2019
1641
  var TOOLS_MANIFEST_FILES = ["package.json", "package-lock.json"];
2020
- var SKILLS_CLI_PATH_IN_TOOLS_DIR = join7(
1642
+ var SKILLS_CLI_PATH_IN_TOOLS_DIR = join5(
2021
1643
  "node_modules",
2022
1644
  "skills",
2023
1645
  "bin",
@@ -2042,19 +1664,19 @@ async function promoteStagingDirectory(stagingDirectory, toolsDirectory, cliPath
2042
1664
  if (await renameUnlessAnotherRunWon(stagingDirectory, toolsDirectory)) {
2043
1665
  return;
2044
1666
  }
2045
- if (existsSync3(cliPath)) {
1667
+ if (existsSync2(cliPath)) {
2046
1668
  return;
2047
1669
  }
2048
1670
  const brokenDirectory = `${stagingDirectory}.broken`;
2049
1671
  await rename2(toolsDirectory, brokenDirectory);
2050
- await rm4(brokenDirectory, { recursive: true, force: true });
1672
+ await rm3(brokenDirectory, { recursive: true, force: true });
2051
1673
  await renameUnlessAnotherRunWon(stagingDirectory, toolsDirectory);
2052
1674
  }
2053
1675
  var ABANDONED_TOOLS_DIRECTORY_PATTERN = /^[0-9a-f]{16}\.tmp-[^/]+$/;
2054
1676
  async function removeAbandonedToolsDirectories(toolsRoot) {
2055
1677
  for (const entry of await readdir(toolsRoot)) {
2056
1678
  if (ABANDONED_TOOLS_DIRECTORY_PATTERN.test(entry)) {
2057
- await rm4(join7(toolsRoot, entry), { recursive: true, force: true });
1679
+ await rm3(join5(toolsRoot, entry), { recursive: true, force: true });
2058
1680
  }
2059
1681
  }
2060
1682
  }
@@ -2064,8 +1686,8 @@ async function installToolsDirectory(ctx, toolsRoot, manifestDirectory, toolsDir
2064
1686
  try {
2065
1687
  for (const fileName of TOOLS_MANIFEST_FILES) {
2066
1688
  await copyFile(
2067
- join7(manifestDirectory, fileName),
2068
- join7(stagingDirectory, fileName)
1689
+ join5(manifestDirectory, fileName),
1690
+ join5(stagingDirectory, fileName)
2069
1691
  );
2070
1692
  }
2071
1693
  const installResult = await ctx.run(
@@ -2087,24 +1709,24 @@ async function installToolsDirectory(ctx, toolsRoot, manifestDirectory, toolsDir
2087
1709
  }
2088
1710
  await promoteStagingDirectory(stagingDirectory, toolsDirectory, cliPath);
2089
1711
  } finally {
2090
- await rm4(stagingDirectory, { recursive: true, force: true });
1712
+ await rm3(stagingDirectory, { recursive: true, force: true });
2091
1713
  }
2092
1714
  }
2093
1715
  async function ensureSkillsCli(ctx) {
2094
1716
  const manifestDirectory = resolveToolsManifestDirectory();
2095
1717
  const lockHash = sha256Hex(
2096
- await readFile3(join7(manifestDirectory, "package-lock.json"))
1718
+ await readFile3(join5(manifestDirectory, "package-lock.json"))
2097
1719
  ).slice(0, TOOLS_LOCK_HASH_LENGTH);
2098
1720
  const toolsRoot = await prepareToolsRoot();
2099
- const toolsDirectory = join7(toolsRoot, lockHash);
2100
- const cliPath = join7(toolsDirectory, SKILLS_CLI_PATH_IN_TOOLS_DIR);
2101
- if (existsSync3(cliPath)) {
1721
+ const toolsDirectory = join5(toolsRoot, lockHash);
1722
+ const cliPath = join5(toolsDirectory, SKILLS_CLI_PATH_IN_TOOLS_DIR);
1723
+ if (existsSync2(cliPath)) {
2102
1724
  return cliPath;
2103
1725
  }
2104
1726
  await withAgemonStateLock(
2105
1727
  "tools.lock",
2106
1728
  async () => {
2107
- if (!existsSync3(cliPath)) {
1729
+ if (!existsSync2(cliPath)) {
2108
1730
  await installToolsDirectory(
2109
1731
  ctx,
2110
1732
  toolsRoot,
@@ -2127,7 +1749,7 @@ async function runSkillsCli(ctx, args, timeoutMs) {
2127
1749
  }
2128
1750
 
2129
1751
  // src/core/config.ts
2130
- import { join as join9, relative as relative2 } from "path";
1752
+ import { join as join7, relative as relative2 } from "path";
2131
1753
  import { isDeepStrictEqual } from "util";
2132
1754
 
2133
1755
  // node_modules/smol-toml/dist/error.js
@@ -3072,11 +2694,11 @@ function stringify(obj, { maxDepth = 1e3, numbersAsFloat = false, strictTemporal
3072
2694
  }
3073
2695
 
3074
2696
  // src/core/backups.ts
3075
- import { dirname as dirname4, isAbsolute as isAbsolute5, join as join8, resolve as resolve2 } from "path";
2697
+ import { dirname as dirname4, isAbsolute as isAbsolute5, join as join6, resolve as resolve2 } from "path";
3076
2698
  var BACKUP_SEGMENTS = ["backups"];
3077
2699
  var V1_BACKUP_SEGMENTS = ["backups", "master-prompt"];
3078
- var BACKUP_DIRECTORY = join8(AGEMON_STATE_DIRECTORY, ...BACKUP_SEGMENTS);
3079
- var V1_BACKUP_DIRECTORY = join8(AGEMON_STATE_DIRECTORY, ...V1_BACKUP_SEGMENTS);
2700
+ var BACKUP_DIRECTORY = join6(AGEMON_STATE_DIRECTORY, ...BACKUP_SEGMENTS);
2701
+ var V1_BACKUP_DIRECTORY = join6(AGEMON_STATE_DIRECTORY, ...V1_BACKUP_SEGMENTS);
3080
2702
  var RESOURCE_ID_HASH_LENGTH = 12;
3081
2703
  function sanitizeForFileName(value) {
3082
2704
  return value.replace(/[^a-zA-Z0-9._-]/gu, "_");
@@ -3086,24 +2708,24 @@ function resolveImmutableBackupPath(cwd, resourceId) {
3086
2708
  0,
3087
2709
  RESOURCE_ID_HASH_LENGTH
3088
2710
  );
3089
- return join8(
2711
+ return join6(
3090
2712
  cwd,
3091
2713
  BACKUP_DIRECTORY,
3092
2714
  `${sanitizeForFileName(resourceId)}-${resourceIdHash}.bak`
3093
2715
  );
3094
2716
  }
3095
2717
  function resolveLegacyBackupPath(cwd, resourceId) {
3096
- return join8(cwd, BACKUP_DIRECTORY, `${sanitizeForFileName(resourceId)}.bak`);
2718
+ return join6(cwd, BACKUP_DIRECTORY, `${sanitizeForFileName(resourceId)}.bak`);
3097
2719
  }
3098
2720
  function resolveV1RuleFileBackupPath(cwd, target) {
3099
- return join8(cwd, V1_BACKUP_DIRECTORY, `${sanitizeForFileName(target)}.bak`);
2721
+ return join6(cwd, V1_BACKUP_DIRECTORY, `${sanitizeForFileName(target)}.bak`);
3100
2722
  }
3101
2723
  function backupDirectorySegments(cwd, backupPath) {
3102
2724
  const directory = dirname4(backupPath);
3103
- if (directory === join8(cwd, BACKUP_DIRECTORY)) {
2725
+ if (directory === join6(cwd, BACKUP_DIRECTORY)) {
3104
2726
  return BACKUP_SEGMENTS;
3105
2727
  }
3106
- if (directory === join8(cwd, V1_BACKUP_DIRECTORY)) {
2728
+ if (directory === join6(cwd, V1_BACKUP_DIRECTORY)) {
3107
2729
  return V1_BACKUP_SEGMENTS;
3108
2730
  }
3109
2731
  return null;
@@ -3301,7 +2923,7 @@ var LOCAL_SKILL_KEYS = keyNames(
3301
2923
  AGEMON_TOML_TABLES.customSkill.keys.filter((key) => !key.githubSourceOnly)
3302
2924
  );
3303
2925
  function resolveConfigPath(cwd) {
3304
- return join9(cwd, CONFIG_FILE_NAME);
2926
+ return join7(cwd, CONFIG_FILE_NAME);
3305
2927
  }
3306
2928
  function fail(detail) {
3307
2929
  throw new Error(`${CONFIG_FILE_NAME} is invalid: ${printable(detail)}`);
@@ -3630,8 +3252,8 @@ async function writeConfig(cwd, config) {
3630
3252
  }
3631
3253
 
3632
3254
  // src/plugins/skills/skills-cli-targets.ts
3633
- import { lstat as lstat5, rm as rm5, unlink } from "fs/promises";
3634
- import { join as join10 } from "path";
3255
+ import { lstat as lstat5, rm as rm4, unlink } from "fs/promises";
3256
+ import { join as join8 } from "path";
3635
3257
  var CANONICAL_SKILLS_DIRECTORY = ".agents/skills";
3636
3258
  var CLAUDE_SKILLS_DIRECTORY = ".claude/skills";
3637
3259
  var SKILLS_LOCK_FILE = "skills-lock.json";
@@ -3666,13 +3288,13 @@ async function prepareSkillsCliTargets(repoRoot, skillNames) {
3666
3288
  );
3667
3289
  if (canonicalDirectory !== null) {
3668
3290
  for (const skillName of skillNames) {
3669
- const stats = await lstatIfPresent(join10(canonicalDirectory, skillName));
3291
+ const stats = await lstatIfPresent(join8(canonicalDirectory, skillName));
3670
3292
  if (stats?.isSymbolicLink()) {
3671
3293
  refuse(`${CANONICAL_SKILLS_DIRECTORY}/${skillName}`, "is a symlink");
3672
3294
  }
3673
3295
  }
3674
3296
  }
3675
- const lockStats = await lstatIfPresent(join10(repoRoot, SKILLS_LOCK_FILE));
3297
+ const lockStats = await lstatIfPresent(join8(repoRoot, SKILLS_LOCK_FILE));
3676
3298
  if (lockStats !== null && !lockStats.isFile()) {
3677
3299
  refuse(SKILLS_LOCK_FILE, "is a symlink or not a regular file");
3678
3300
  }
@@ -3687,192 +3309,13 @@ async function removeInstalledSkillCopy(repoRoot, skillName) {
3687
3309
  if (skillsDirectory === null) {
3688
3310
  return;
3689
3311
  }
3690
- const copyPath = join10(skillsDirectory, skillName);
3312
+ const copyPath = join8(skillsDirectory, skillName);
3691
3313
  const stats = await lstatIfPresent(copyPath);
3692
3314
  if (stats?.isSymbolicLink()) {
3693
3315
  await unlink(copyPath);
3694
3316
  } else if (stats !== null) {
3695
- await rm5(copyPath, { recursive: true, force: true });
3696
- }
3697
- }
3698
-
3699
- // src/core/install-method.ts
3700
- import { existsSync as existsSync4, readFileSync as readFileSync2, realpathSync } from "fs";
3701
- import { lstat as lstat7, realpath as realpath4 } from "fs/promises";
3702
- import { basename, dirname as dirname5, join as join11, sep as sep2 } from "path";
3703
- import { fileURLToPath as fileURLToPath2 } from "url";
3704
-
3705
- // src/core/npm-global.ts
3706
- import { lstat as lstat6, stat as stat2 } from "fs/promises";
3707
- import { isAbsolute as isAbsolute6, resolve as resolve3 } from "path";
3708
- var NPM_ROOT_TIMEOUT_MS = 2e4;
3709
- async function isDirectory(path) {
3710
- try {
3711
- return (await stat2(path)).isDirectory();
3712
- } catch {
3713
- return false;
3714
- }
3715
- }
3716
- async function pathIsMissing(path) {
3717
- try {
3718
- await lstat6(path);
3719
- return false;
3720
- } catch (error) {
3721
- return error.code === "ENOENT";
3722
- }
3723
- }
3724
- async function resolveGlobalNpmRoot(run, options = {}) {
3725
- const npmRootResult = await run("npm", ["root", "--global"], {
3726
- timeoutMs: NPM_ROOT_TIMEOUT_MS,
3727
- cwd: options.cwd
3728
- });
3729
- if (npmRootResult.code !== 0) {
3730
- throw new Error(
3731
- `npm root --global failed: ${describeSubprocessFailure(npmRootResult, "npm")}`
3732
- );
3733
- }
3734
- const npmRoot = npmRootResult.stdout.trim();
3735
- if (!isAbsolute6(npmRoot)) {
3736
- throw new Error(
3737
- `npm root --global returned ${printable(npmRoot)}, which is not an absolute path.`
3738
- );
3739
- }
3740
- if (resolve3(npmRoot) !== npmRoot || !isSafeIdentifier(npmRoot)) {
3741
- throw new Error(
3742
- `npm root --global returned ${printable(npmRoot)}, which is not a single normalised path.`
3743
- );
3744
- }
3745
- if (options.mayNotExistYet && await pathIsMissing(npmRoot)) {
3746
- return npmRoot;
3317
+ await rm4(copyPath, { recursive: true, force: true });
3747
3318
  }
3748
- if (!await isDirectory(npmRoot)) {
3749
- throw new Error(
3750
- `npm root --global returned ${printable(npmRoot)}, which is not a directory. npm masks UUID-like path segments as ***; use an npm prefix without one.`
3751
- );
3752
- }
3753
- return npmRoot;
3754
- }
3755
-
3756
- // src/core/install-method.ts
3757
- var PACKAGE_NAME2 = "agemon";
3758
- var PACKAGE_JSON_SEARCH_DEPTH = 5;
3759
- var INSTALL_MARKER_FILE_NAME = ".agemon-install";
3760
- var SOURCE_CHECKOUT_ENTRIES = [".git", "src"];
3761
- var NPX_CACHE_SEGMENT = "_npx";
3762
- function readPackageName2(directory) {
3763
- try {
3764
- const manifest = JSON.parse(
3765
- readFileSync2(join11(directory, "package.json"), "utf8")
3766
- );
3767
- return manifest.name;
3768
- } catch {
3769
- return void 0;
3770
- }
3771
- }
3772
- function resolvePackageRoot2(fromDirectory = dirname5(fileURLToPath2(import.meta.url))) {
3773
- let directory = fromDirectory;
3774
- for (let depth = 0; depth < PACKAGE_JSON_SEARCH_DEPTH; depth += 1) {
3775
- if (readPackageName2(directory) === PACKAGE_NAME2) {
3776
- return realpathSync(directory);
3777
- }
3778
- directory = dirname5(directory);
3779
- }
3780
- throw new Error("Unable to locate agemon's package.json.");
3781
- }
3782
- function readPackageVersion(packageRoot = resolvePackageRoot2()) {
3783
- const manifest = JSON.parse(
3784
- readFileSync2(join11(packageRoot, "package.json"), "utf8")
3785
- );
3786
- return manifest.version;
3787
- }
3788
- function isSourceCheckout(packageRoot) {
3789
- return SOURCE_CHECKOUT_ENTRIES.some(
3790
- (entry) => existsSync4(join11(packageRoot, entry))
3791
- );
3792
- }
3793
- async function hasRegularInstallMarker(packageRoot) {
3794
- try {
3795
- return (await lstat7(join11(packageRoot, INSTALL_MARKER_FILE_NAME))).isFile();
3796
- } catch {
3797
- return false;
3798
- }
3799
- }
3800
- function isInsideNodeModules(packageRoot) {
3801
- return basename(dirname5(packageRoot)) === "node_modules";
3802
- }
3803
- async function resolveGlobalNpmPrefix(packageRoot, run) {
3804
- try {
3805
- const globalRoot = await realpath4(await resolveGlobalNpmRoot(run));
3806
- const globalRootHoldsThisCopy = globalRoot === dirname5(packageRoot);
3807
- const globalRootIsPrefixLib = basename(dirname5(globalRoot)) === "lib";
3808
- return globalRootHoldsThisCopy && globalRootIsPrefixLib ? dirname5(dirname5(globalRoot)) : void 0;
3809
- } catch {
3810
- return void 0;
3811
- }
3812
- }
3813
- async function resolveInstallMethod(options = {}) {
3814
- const packageRoot = options.packageRoot ?? resolvePackageRoot2();
3815
- if (isSourceCheckout(packageRoot)) {
3816
- return { kind: "dev" };
3817
- }
3818
- if (await hasRegularInstallMarker(packageRoot)) {
3819
- return { kind: "install-script", installDir: packageRoot };
3820
- }
3821
- if (packageRoot.split(sep2).includes(NPX_CACHE_SEGMENT)) {
3822
- return { kind: "npx" };
3823
- }
3824
- if (isInsideNodeModules(packageRoot)) {
3825
- const prefix = await resolveGlobalNpmPrefix(
3826
- packageRoot,
3827
- options.run ?? runSubprocess
3828
- );
3829
- if (prefix !== void 0) {
3830
- return { kind: "npm-global", packageRoot, prefix };
3831
- }
3832
- }
3833
- return { kind: "unknown", packageRoot };
3834
- }
3835
-
3836
- // src/core/dev-mode.ts
3837
- var FAKE_BACKEND_ENV_VARS = [
3838
- "AGEMON_FAKE_SUBPROCESS",
3839
- "AGEMON_FAKE_SERVICES"
3840
- ];
3841
- function isDevMode(packageRoot) {
3842
- return process.env.AGEMON_DEV === "1" && isSourceCheckout(packageRoot ?? resolvePackageRoot2());
3843
- }
3844
- function assertFakeBackendsAreDevOnly(packageRoot) {
3845
- const activeFakeVars = FAKE_BACKEND_ENV_VARS.filter(
3846
- (name) => process.env[name] === "1"
3847
- );
3848
- if (activeFakeVars.length > 0 && !isDevMode(packageRoot)) {
3849
- throw new Error(
3850
- `${activeFakeVars.join(", ")} must never be set outside the sandbox harness \u2014 refusing to start.`
3851
- );
3852
- }
3853
- }
3854
-
3855
- // src/core/fake-pinned-skills.ts
3856
- var FAKE_PINNED_SKILL_MANIFEST_FILE = "SKILL.md";
3857
- function fakePinnedSkillManifest(skillName) {
3858
- return `---
3859
- name: ${skillName}
3860
- description: Stand-in for the pinned ${skillName} skill, written by agemon's fake git backend.
3861
- ---
3862
-
3863
- Fake ${skillName}.
3864
- `;
3865
- }
3866
- function fakePinnedSkillFingerprint(skillName) {
3867
- return fingerprintSkillTree([
3868
- {
3869
- relativePath: FAKE_PINNED_SKILL_MANIFEST_FILE,
3870
- contents: Buffer.from(fakePinnedSkillManifest(skillName))
3871
- }
3872
- ]);
3873
- }
3874
- function fakeSubprocessesActive() {
3875
- return process.env.AGEMON_FAKE_SUBPROCESS === "1" && isDevMode();
3876
3319
  }
3877
3320
 
3878
3321
  export {
@@ -3910,17 +3353,24 @@ export {
3910
3353
  containsHomeDirectory,
3911
3354
  CODE_REVIEW_GRAPH_VERSION,
3912
3355
  CODE_REVIEW_GRAPH_PACKAGE_SPEC,
3913
- ESSENTIALS_SKILLS_COMMIT,
3914
3356
  AGNIX_VERSION,
3915
3357
  AGNIX_RELEASE_ARCHIVE_SHA256,
3916
3358
  AGNIX_NPM_TARBALL,
3917
3359
  AGNIX_PACKAGE_FILE_SHA256,
3918
3360
  AGNIX_BINARY_SHA256,
3919
- resolveToolsManifestDirectory,
3920
- withFileLock,
3921
3361
  sha256Hex,
3922
3362
  fingerprintJson,
3923
3363
  fingerprintContent,
3364
+ SkillTreeRefusal,
3365
+ isLeftOutBySkillsCli,
3366
+ readSkillTree,
3367
+ fingerprintSkillTree,
3368
+ fingerprintSkillSource,
3369
+ readInstalledSkill,
3370
+ fingerprintInstalledSkill,
3371
+ resolveVendoredSkillPath,
3372
+ resolveToolsManifestDirectory,
3373
+ withFileLock,
3924
3374
  resolveStateRoot,
3925
3375
  resolveAgemonStateDirectory,
3926
3376
  checkAgemonStateDirectoryBeforeRun,
@@ -3929,21 +3379,6 @@ export {
3929
3379
  repositoryStateKey,
3930
3380
  withAgemonStateLock,
3931
3381
  withRepositoryRunLock,
3932
- isPristinePinnedCheckout,
3933
- skillPathInRepository,
3934
- resolvePinnedSkillPath,
3935
- fetchPinnedSkillsSource,
3936
- SKILL_GROUPS,
3937
- RETIRED_AGENT_NAMES,
3938
- findSkillGroup,
3939
- buildCustomSkillGroups,
3940
- assertCustomSkillGroupsAreValid,
3941
- SkillTreeRefusal,
3942
- isLeftOutBySkillsCli,
3943
- readSkillTree,
3944
- fingerprintSkillTree,
3945
- fingerprintSkillSource,
3946
- fingerprintInstalledSkill,
3947
3382
  SKILLS_CLI_PATH_IN_TOOLS_DIR,
3948
3383
  runSkillsCli,
3949
3384
  resolveImmutableBackupPath,
@@ -3963,16 +3398,6 @@ export {
3963
3398
  SKILLS_LOCK_FILE,
3964
3399
  prepareSkillsCliTargets,
3965
3400
  removeInstalledSkillCopy,
3966
- resolveGlobalNpmRoot,
3967
- INSTALL_MARKER_FILE_NAME,
3968
- readPackageVersion,
3969
- resolveInstallMethod,
3970
- isDevMode,
3971
- assertFakeBackendsAreDevOnly,
3972
- FAKE_PINNED_SKILL_MANIFEST_FILE,
3973
- fakePinnedSkillManifest,
3974
- fakePinnedSkillFingerprint,
3975
- fakeSubprocessesActive,
3976
3401
  MAX_RAW_OUTPUT_LINE_CHARACTERS,
3977
3402
  sanitizeOutput,
3978
3403
  capShownLine,
@@ -4023,4 +3448,4 @@ smol-toml/dist/index.js:
4023
3448
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4024
3449
  *)
4025
3450
  */
4026
- //# sourceMappingURL=chunk-5LATHJYU.js.map
3451
+ //# sourceMappingURL=chunk-ZZBF3GOV.js.map