@goondocks/myco 0.19.2 → 0.19.4

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 (86) hide show
  1. package/dist/{agent-run-4QUP3G4V.js → agent-run-OGWPNU43.js} +4 -4
  2. package/dist/{agent-tasks-NVOWYBLB.js → agent-tasks-XWMDAEPG.js} +4 -4
  3. package/dist/{chunk-XMPCB2P2.js → chunk-5B2ORGTF.js} +5 -2
  4. package/dist/chunk-5B2ORGTF.js.map +1 -0
  5. package/dist/{chunk-DDOPAV5O.js → chunk-NTWJR6KH.js} +2 -2
  6. package/dist/{chunk-THZKOZ4M.js → chunk-RTNLDAIC.js} +70 -15
  7. package/dist/chunk-RTNLDAIC.js.map +1 -0
  8. package/dist/{chunk-QMTXVFA7.js → chunk-W3P6MHLQ.js} +2 -2
  9. package/dist/{chunk-D5X4MMKR.js → chunk-Y3IJFUVX.js} +2 -2
  10. package/dist/{chunk-IXVAYN3P.js → chunk-YDCGI3CS.js} +2 -2
  11. package/dist/{cli-GDHPLWS7.js → cli-XDG624PV.js} +32 -32
  12. package/dist/{client-UCELFVZF.js → client-EEPUQVMX.js} +3 -3
  13. package/dist/{doctor-7ATZHQIY.js → doctor-L4LWMJYH.js} +4 -4
  14. package/dist/{executor-YO4RIKJQ.js → executor-4TJOZN32.js} +13 -5
  15. package/dist/executor-4TJOZN32.js.map +1 -0
  16. package/dist/{init-OK5QJISX.js → init-U2SG2IOC.js} +5 -5
  17. package/dist/{main-XWJGDDMZ.js → main-EVS3FXDJ.js} +9 -9
  18. package/dist/{open-5WOOLDUZ.js → open-TEQZXO4A.js} +4 -4
  19. package/dist/{post-compact-TLIJUMKZ.js → post-compact-POSTGJEV.js} +4 -4
  20. package/dist/{post-tool-use-TMYBAFL6.js → post-tool-use-VE6YPEY2.js} +3 -3
  21. package/dist/{post-tool-use-failure-P7YHR3EO.js → post-tool-use-failure-LUFD62SB.js} +4 -4
  22. package/dist/{pre-compact-7RUNVXOE.js → pre-compact-7QGJYRJF.js} +4 -4
  23. package/dist/{remove-ISEIHY5H.js → remove-4UZXDSVY.js} +4 -4
  24. package/dist/{restart-AK24G2ME.js → restart-HLXD4ZGX.js} +5 -5
  25. package/dist/{search-RVRUKLEH.js → search-MWXY3GTI.js} +4 -4
  26. package/dist/{server-GBWW5MBT.js → server-TQY7CYOS.js} +3 -3
  27. package/dist/{session-L7PGGZTO.js → session-P2POKO22.js} +4 -4
  28. package/dist/{session-end-YURB7CFB.js → session-end-DZNJHGQB.js} +3 -3
  29. package/dist/{session-start-4AMHWOBP.js → session-start-JNNJTP3C.js} +3 -3
  30. package/dist/{setup-llm-2UOSVGAY.js → setup-llm-UQO2INBY.js} +4 -4
  31. package/dist/src/agent/definitions/tasks/skill-generate.yaml +9 -0
  32. package/dist/src/agent/definitions/tasks/skill-survey.yaml +1 -1
  33. package/dist/src/cli.js +1 -1
  34. package/dist/src/daemon/main.js +1 -1
  35. package/dist/src/hooks/post-tool-use.js +1 -1
  36. package/dist/src/hooks/session-end.js +1 -1
  37. package/dist/src/hooks/session-start.js +1 -1
  38. package/dist/src/hooks/stop.js +1 -1
  39. package/dist/src/hooks/user-prompt-submit.js +1 -1
  40. package/dist/src/mcp/server.js +1 -1
  41. package/dist/{stats-5IEO4KWT.js → stats-DJYTDCUE.js} +5 -5
  42. package/dist/{stop-KRR3EBB2.js → stop-VBA4RMQM.js} +3 -3
  43. package/dist/{stop-failure-6RZAWIDM.js → stop-failure-54Z2HSU4.js} +4 -4
  44. package/dist/{subagent-start-R62O6YPW.js → subagent-start-XL773ZID.js} +4 -4
  45. package/dist/{subagent-stop-MP2YDF6D.js → subagent-stop-HJVSYNII.js} +4 -4
  46. package/dist/{task-completed-KCMJYZT7.js → task-completed-GLNYNBYP.js} +4 -4
  47. package/dist/{update-L5JXTKPL.js → update-JZV2K4YG.js} +4 -4
  48. package/dist/{user-prompt-submit-L6JNZ7QY.js → user-prompt-submit-6KMTMHKW.js} +3 -3
  49. package/dist/{version-PFOYY6HT.js → version-KS3UADP5.js} +2 -2
  50. package/package.json +1 -1
  51. package/dist/chunk-THZKOZ4M.js.map +0 -1
  52. package/dist/chunk-XMPCB2P2.js.map +0 -1
  53. package/dist/executor-YO4RIKJQ.js.map +0 -1
  54. /package/dist/{agent-run-4QUP3G4V.js.map → agent-run-OGWPNU43.js.map} +0 -0
  55. /package/dist/{agent-tasks-NVOWYBLB.js.map → agent-tasks-XWMDAEPG.js.map} +0 -0
  56. /package/dist/{chunk-DDOPAV5O.js.map → chunk-NTWJR6KH.js.map} +0 -0
  57. /package/dist/{chunk-QMTXVFA7.js.map → chunk-W3P6MHLQ.js.map} +0 -0
  58. /package/dist/{chunk-D5X4MMKR.js.map → chunk-Y3IJFUVX.js.map} +0 -0
  59. /package/dist/{chunk-IXVAYN3P.js.map → chunk-YDCGI3CS.js.map} +0 -0
  60. /package/dist/{cli-GDHPLWS7.js.map → cli-XDG624PV.js.map} +0 -0
  61. /package/dist/{client-UCELFVZF.js.map → client-EEPUQVMX.js.map} +0 -0
  62. /package/dist/{doctor-7ATZHQIY.js.map → doctor-L4LWMJYH.js.map} +0 -0
  63. /package/dist/{init-OK5QJISX.js.map → init-U2SG2IOC.js.map} +0 -0
  64. /package/dist/{main-XWJGDDMZ.js.map → main-EVS3FXDJ.js.map} +0 -0
  65. /package/dist/{open-5WOOLDUZ.js.map → open-TEQZXO4A.js.map} +0 -0
  66. /package/dist/{post-compact-TLIJUMKZ.js.map → post-compact-POSTGJEV.js.map} +0 -0
  67. /package/dist/{post-tool-use-TMYBAFL6.js.map → post-tool-use-VE6YPEY2.js.map} +0 -0
  68. /package/dist/{post-tool-use-failure-P7YHR3EO.js.map → post-tool-use-failure-LUFD62SB.js.map} +0 -0
  69. /package/dist/{pre-compact-7RUNVXOE.js.map → pre-compact-7QGJYRJF.js.map} +0 -0
  70. /package/dist/{remove-ISEIHY5H.js.map → remove-4UZXDSVY.js.map} +0 -0
  71. /package/dist/{restart-AK24G2ME.js.map → restart-HLXD4ZGX.js.map} +0 -0
  72. /package/dist/{search-RVRUKLEH.js.map → search-MWXY3GTI.js.map} +0 -0
  73. /package/dist/{server-GBWW5MBT.js.map → server-TQY7CYOS.js.map} +0 -0
  74. /package/dist/{session-L7PGGZTO.js.map → session-P2POKO22.js.map} +0 -0
  75. /package/dist/{session-end-YURB7CFB.js.map → session-end-DZNJHGQB.js.map} +0 -0
  76. /package/dist/{session-start-4AMHWOBP.js.map → session-start-JNNJTP3C.js.map} +0 -0
  77. /package/dist/{setup-llm-2UOSVGAY.js.map → setup-llm-UQO2INBY.js.map} +0 -0
  78. /package/dist/{stats-5IEO4KWT.js.map → stats-DJYTDCUE.js.map} +0 -0
  79. /package/dist/{stop-KRR3EBB2.js.map → stop-VBA4RMQM.js.map} +0 -0
  80. /package/dist/{stop-failure-6RZAWIDM.js.map → stop-failure-54Z2HSU4.js.map} +0 -0
  81. /package/dist/{subagent-start-R62O6YPW.js.map → subagent-start-XL773ZID.js.map} +0 -0
  82. /package/dist/{subagent-stop-MP2YDF6D.js.map → subagent-stop-HJVSYNII.js.map} +0 -0
  83. /package/dist/{task-completed-KCMJYZT7.js.map → task-completed-GLNYNBYP.js.map} +0 -0
  84. /package/dist/{update-L5JXTKPL.js.map → update-JZV2K4YG.js.map} +0 -0
  85. /package/dist/{user-prompt-submit-L6JNZ7QY.js.map → user-prompt-submit-6KMTMHKW.js.map} +0 -0
  86. /package/dist/{version-PFOYY6HT.js.map → version-KS3UADP5.js.map} +0 -0
@@ -1,13 +1,13 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  connectToDaemon
4
- } from "./chunk-XMPCB2P2.js";
4
+ } from "./chunk-5B2ORGTF.js";
5
5
  import "./chunk-SAKJMNSR.js";
6
6
  import "./chunk-WYOE4IAX.js";
7
7
  import "./chunk-PMT2LSTQ.js";
8
8
  import "./chunk-MYX5NCRH.js";
9
- import "./chunk-QMTXVFA7.js";
10
- import "./chunk-DDOPAV5O.js";
9
+ import "./chunk-W3P6MHLQ.js";
10
+ import "./chunk-NTWJR6KH.js";
11
11
  import "./chunk-LPUQPDC2.js";
12
12
  import "./chunk-I54KLC6H.js";
13
13
  import "./chunk-UUHLLQXO.js";
@@ -32,4 +32,4 @@ async function run(args, vaultDir) {
32
32
  export {
33
33
  run
34
34
  };
35
- //# sourceMappingURL=agent-run-4QUP3G4V.js.map
35
+ //# sourceMappingURL=agent-run-OGWPNU43.js.map
@@ -1,13 +1,13 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  connectToDaemon
4
- } from "./chunk-XMPCB2P2.js";
4
+ } from "./chunk-5B2ORGTF.js";
5
5
  import "./chunk-SAKJMNSR.js";
6
6
  import "./chunk-WYOE4IAX.js";
7
7
  import "./chunk-PMT2LSTQ.js";
8
8
  import "./chunk-MYX5NCRH.js";
9
- import "./chunk-QMTXVFA7.js";
10
- import "./chunk-DDOPAV5O.js";
9
+ import "./chunk-W3P6MHLQ.js";
10
+ import "./chunk-NTWJR6KH.js";
11
11
  import "./chunk-LPUQPDC2.js";
12
12
  import "./chunk-I54KLC6H.js";
13
13
  import "./chunk-UUHLLQXO.js";
@@ -178,4 +178,4 @@ async function run(args, vaultDir) {
178
178
  export {
179
179
  run
180
180
  };
181
- //# sourceMappingURL=agent-tasks-NVOWYBLB.js.map
181
+ //# sourceMappingURL=agent-tasks-XWMDAEPG.js.map
@@ -13,7 +13,7 @@ import {
13
13
  } from "./chunk-MYX5NCRH.js";
14
14
  import {
15
15
  DaemonClient
16
- } from "./chunk-QMTXVFA7.js";
16
+ } from "./chunk-W3P6MHLQ.js";
17
17
 
18
18
  // src/cli/shared.ts
19
19
  import fs from "fs";
@@ -79,6 +79,9 @@ attachments/
79
79
  # Team sync admin state + worker deployment
80
80
  team/
81
81
 
82
+ # Staged files generated by the myco agent
83
+ staging/
84
+
82
85
  # Runtime command alias \u2014 per-contributor override for which myco binary
83
86
  # the hook guard invokes. Default (file absent) is \`myco\`; \`make dev-link\`
84
87
  # writes \`myco-dev\`; users can hand-edit for PATH conflicts or pinning.
@@ -120,4 +123,4 @@ export {
120
123
  VAULT_GITIGNORE,
121
124
  registerSymbionts
122
125
  };
123
- //# sourceMappingURL=chunk-XMPCB2P2.js.map
126
+ //# sourceMappingURL=chunk-5B2ORGTF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/shared.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\nimport { OllamaBackend } from '../intelligence/ollama.js';\nimport { LmStudioBackend } from '../intelligence/lm-studio.js';\n\nimport { DaemonClient } from '../hooks/client.js';\nimport { initDatabase, closeDatabase, vaultDbPath } from '../db/client.js';\nimport { SymbiontInstaller } from '../symbionts/installer.js';\nimport type { SymbiontManifest } from '../symbionts/manifest-schema.js';\n\nexport { parseStringFlag, parseIntFlag } from '../logs/format.js';\n\n/**\n * Initialize the singleton database for direct CLI reads.\n * Used by CLI commands that only need reads (stats, search, session).\n * Does NOT require the daemon to be running — WAL mode allows concurrent reads.\n *\n * @returns a cleanup function that closes the database.\n */\nexport function initVaultDb(vaultDir: string): () => void {\n initDatabase(vaultDbPath(vaultDir));\n return closeDatabase;\n}\n\n/** Connect to the daemon, ensuring it's running. Exits on failure. */\nexport async function connectToDaemon(vaultDir: string): Promise<DaemonClient> {\n const client = new DaemonClient(vaultDir);\n const healthy = await client.ensureRunning();\n if (!healthy) {\n console.error('Failed to connect to daemon');\n process.exit(1);\n }\n return client;\n}\n\n/** Load .env from cwd (not script location — that's the plugin install dir). */\nexport function loadEnv(): void {\n const envPath = path.resolve(process.cwd(), '.env');\n if (!fs.existsSync(envPath)) return;\n for (const line of fs.readFileSync(envPath, 'utf-8').split('\\n')) {\n const match = line.match(/^\\s*([^#=]+?)\\s*=\\s*(.*?)\\s*$/);\n if (match && !process.env[match[1]]) {\n process.env[match[1]] = match[2];\n }\n }\n}\n\nexport function isProcessAlive(pid: number): boolean {\n try { process.kill(pid, 0); return true; } catch { return false; }\n}\n\n// --- Provider defaults (sourced from backend classes) ---\nexport const PROVIDER_DEFAULTS: Record<string, { base_url: string }> = {\n ollama: { base_url: OllamaBackend.DEFAULT_BASE_URL },\n 'lm-studio': { base_url: LmStudioBackend.DEFAULT_BASE_URL },\n};\n\n\nexport const VAULT_GITIGNORE = `# SQLite database\nmyco.db*\nvectors.db*\n\n# Daemon state — per-machine, ephemeral\ndaemon.json\nbuffer/\nlogs/\n\n# Secrets — API keys for cloud providers\nsecrets.env\n\n# Machine ID\nmachine_id\n\n# Update tracking — per-machine state\nlast-update-version\nrestart-reason.json\n\n# Binary attachments — screenshots captured from transcripts\nattachments/\n\n# Team sync admin state + worker deployment\nteam/\n\n# Staged files generated by the myco agent\nstaging/\n\n# Runtime command alias — per-contributor override for which myco binary\n# the hook guard invokes. Default (file absent) is \\`myco\\`; \\`make dev-link\\`\n# writes \\`myco-dev\\`; users can hand-edit for PATH conflicts or pinning.\n# Never committed — different contributors use different aliases.\nruntime.command\n`;\n\n/** Collapse an absolute home-dir path to its `~/` form for portable config storage. */\nexport function collapseHomePath(absPath: string): string {\n const home = os.homedir();\n if (absPath.startsWith(home + path.sep) || absPath === home) {\n return '~' + absPath.slice(home.length);\n }\n return absPath;\n}\n\n/**\n * Run the SymbiontInstaller for each symbiont manifest and log results.\n * Shared between myco init and myco update.\n */\nexport function registerSymbionts(\n manifests: SymbiontManifest[],\n projectRoot: string,\n packageRoot: string,\n verb: 'Registered' | 'Updated',\n): number {\n let count = 0;\n for (const manifest of manifests) {\n try {\n const installer = new SymbiontInstaller(manifest, projectRoot, packageRoot);\n const result = installer.install();\n\n const installed = [\n result.hooks && 'hooks',\n result.mcp && 'MCP server',\n result.skills && 'skills',\n result.settings && 'settings',\n result.instructions && 'instructions',\n result.pluginPackage && 'plugin deps',\n ].filter(Boolean);\n\n if (installed.length > 0) {\n console.log(` \\u2713 ${verb} ${manifest.displayName}: ${installed.join(', ')}`);\n count++;\n } else {\n console.log(` \\u2013 ${manifest.displayName}: no registration targets configured`);\n }\n } catch (err) {\n console.error(` \\u2717 Failed to register ${manifest.displayName}: ${(err as Error).message}`);\n }\n }\n return count;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,QAAQ;AAkBR,SAAS,YAAY,UAA8B;AACxD,eAAa,YAAY,QAAQ,CAAC;AAClC,SAAO;AACT;AAGA,eAAsB,gBAAgB,UAAyC;AAC7E,QAAM,SAAS,IAAI,aAAa,QAAQ;AACxC,QAAM,UAAU,MAAM,OAAO,cAAc;AAC3C,MAAI,CAAC,SAAS;AACZ,YAAQ,MAAM,6BAA6B;AAC3C,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,SAAO;AACT;AAGO,SAAS,UAAgB;AAC9B,QAAM,UAAU,KAAK,QAAQ,QAAQ,IAAI,GAAG,MAAM;AAClD,MAAI,CAAC,GAAG,WAAW,OAAO,EAAG;AAC7B,aAAW,QAAQ,GAAG,aAAa,SAAS,OAAO,EAAE,MAAM,IAAI,GAAG;AAChE,UAAM,QAAQ,KAAK,MAAM,+BAA+B;AACxD,QAAI,SAAS,CAAC,QAAQ,IAAI,MAAM,CAAC,CAAC,GAAG;AACnC,cAAQ,IAAI,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC;AAAA,IACjC;AAAA,EACF;AACF;AAEO,SAAS,eAAe,KAAsB;AACnD,MAAI;AAAE,YAAQ,KAAK,KAAK,CAAC;AAAG,WAAO;AAAA,EAAM,QAAQ;AAAE,WAAO;AAAA,EAAO;AACnE;AAGO,IAAM,oBAA0D;AAAA,EACrE,QAAQ,EAAE,UAAU,cAAc,iBAAiB;AAAA,EACnD,aAAa,EAAE,UAAU,gBAAgB,iBAAiB;AAC5D;AAGO,IAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgDxB,SAAS,kBACd,WACA,aACA,aACA,MACQ;AACR,MAAI,QAAQ;AACZ,aAAW,YAAY,WAAW;AAChC,QAAI;AACF,YAAM,YAAY,IAAI,kBAAkB,UAAU,aAAa,WAAW;AAC1E,YAAM,SAAS,UAAU,QAAQ;AAEjC,YAAM,YAAY;AAAA,QAChB,OAAO,SAAS;AAAA,QAChB,OAAO,OAAO;AAAA,QACd,OAAO,UAAU;AAAA,QACjB,OAAO,YAAY;AAAA,QACnB,OAAO,gBAAgB;AAAA,QACvB,OAAO,iBAAiB;AAAA,MAC1B,EAAE,OAAO,OAAO;AAEhB,UAAI,UAAU,SAAS,GAAG;AACxB,gBAAQ,IAAI,YAAY,IAAI,IAAI,SAAS,WAAW,KAAK,UAAU,KAAK,IAAI,CAAC,EAAE;AAC/E;AAAA,MACF,OAAO;AACL,gBAAQ,IAAI,YAAY,SAAS,WAAW,sCAAsC;AAAA,MACpF;AAAA,IACF,SAAS,KAAK;AACZ,cAAQ,MAAM,+BAA+B,SAAS,WAAW,KAAM,IAAc,OAAO,EAAE;AAAA,IAChG;AAAA,EACF;AACA,SAAO;AACT;","names":[]}
@@ -11,7 +11,7 @@ var cached;
11
11
  function getPluginVersion() {
12
12
  if (cached) return cached;
13
13
  if (true) {
14
- cached = "0.19.2";
14
+ cached = "0.19.4";
15
15
  return cached;
16
16
  }
17
17
  const root = findPackageRoot(path.dirname(fileURLToPath(import.meta.url)));
@@ -32,4 +32,4 @@ function getPluginVersion() {
32
32
  export {
33
33
  getPluginVersion
34
34
  };
35
- //# sourceMappingURL=chunk-DDOPAV5O.js.map
35
+ //# sourceMappingURL=chunk-NTWJR6KH.js.map
@@ -40,6 +40,12 @@ import {
40
40
  QUERY_DEFAULT_LIST_LIMIT,
41
41
  epochSeconds
42
42
  } from "./chunk-I54KLC6H.js";
43
+ import {
44
+ require_dist
45
+ } from "./chunk-6LQIMRTC.js";
46
+ import {
47
+ __toESM
48
+ } from "./chunk-PZUWP5VK.js";
43
49
 
44
50
  // src/notifications/notify.ts
45
51
  import crypto from "crypto";
@@ -934,7 +940,10 @@ function getStatesForAgent(agentId) {
934
940
  }
935
941
 
936
942
  // src/agent/tools/skill-validator.ts
943
+ var import_yaml = __toESM(require_dist(), 1);
937
944
  var MAX_SKILL_LINES = 800;
945
+ var MAX_SKILL_DESCRIPTION_CHARS = 1024;
946
+ var FRONTMATTER_PATTERN = /^---\n([\s\S]*?)\n---/;
938
947
  var REQUIRED_FRONTMATTER_FIELDS = ["name", "description", "managed_by", "user-invocable", "allowed-tools"];
939
948
  var PROTECTED_FRONTMATTER_FIELDS = ["user-invocable", "allowed-tools"];
940
949
  var ALLOWED_CLAUDE_CODE_TOOLS = /* @__PURE__ */ new Set([
@@ -952,10 +961,36 @@ var ALLOWED_CLAUDE_CODE_TOOLS = /* @__PURE__ */ new Set([
952
961
  "Task",
953
962
  "TodoWrite"
954
963
  ]);
964
+ function extractFrontmatterBlock(content) {
965
+ return content.match(FRONTMATTER_PATTERN)?.[1];
966
+ }
967
+ function parseFrontmatter(content) {
968
+ const block = extractFrontmatterBlock(content);
969
+ if (!block) return null;
970
+ const parsed = (0, import_yaml.parse)(block);
971
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
972
+ return null;
973
+ }
974
+ return parsed;
975
+ }
976
+ function normalizeFrontmatterValue(value) {
977
+ if (typeof value === "string") return value;
978
+ if (typeof value === "boolean" || typeof value === "number") return String(value);
979
+ if (Array.isArray(value)) {
980
+ const items = value.map((item) => typeof item === "string" ? item : null).filter((item) => item !== null);
981
+ return items.length > 0 ? items.join(", ") : void 0;
982
+ }
983
+ return void 0;
984
+ }
955
985
  function extractFrontmatterField(content, field) {
956
- const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
957
- if (!fmMatch) return void 0;
958
- const fm = fmMatch[1];
986
+ try {
987
+ const parsed = parseFrontmatter(content);
988
+ const normalized = normalizeFrontmatterValue(parsed?.[field]);
989
+ if (normalized !== void 0) return normalized;
990
+ } catch {
991
+ }
992
+ const fm = extractFrontmatterBlock(content);
993
+ if (!fm) return void 0;
959
994
  const match = fm.match(new RegExp(`^${field}:\\s*(.+)$`, "m"));
960
995
  if (match) return match[1].trim();
961
996
  const blockMatch = fm.match(new RegExp(`^${field}:\\s*$`, "m"));
@@ -1115,26 +1150,46 @@ function checkFrontmatterPreservation(existing, incoming) {
1115
1150
  }
1116
1151
  function validateSkillContent(content, dirName) {
1117
1152
  const issues = [];
1118
- const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
1119
- if (!fmMatch) {
1153
+ const frontmatter = extractFrontmatterBlock(content);
1154
+ if (!frontmatter) {
1120
1155
  issues.push("Missing YAML frontmatter (must start with --- and end with ---)");
1121
1156
  return issues;
1122
1157
  }
1123
- const frontmatter = fmMatch[1];
1158
+ let parsedFrontmatter = null;
1159
+ try {
1160
+ parsedFrontmatter = parseFrontmatter(content);
1161
+ } catch (error) {
1162
+ const message = error instanceof Error ? error.message.split("\n")[0] : String(error);
1163
+ issues.push(`Invalid YAML frontmatter: ${message}`);
1164
+ return issues;
1165
+ }
1166
+ if (!parsedFrontmatter) {
1167
+ issues.push("Invalid YAML frontmatter: top-level frontmatter must be a mapping/object");
1168
+ return issues;
1169
+ }
1124
1170
  for (const field of REQUIRED_FRONTMATTER_FIELDS) {
1125
- if (!frontmatter.includes(`${field}:`)) {
1171
+ if (!(field in parsedFrontmatter)) {
1126
1172
  issues.push(`Missing required frontmatter field: ${field}`);
1127
1173
  }
1128
1174
  }
1129
- const nameMatch = frontmatter.match(/^name:\s*(.+)$/m);
1130
- if (nameMatch && !nameMatch[1].trim().startsWith("myco:")) {
1131
- issues.push(`Skill name must start with "myco:" prefix. Got: "${nameMatch[1].trim()}"`);
1175
+ const nameValue = normalizeFrontmatterValue(parsedFrontmatter.name);
1176
+ if (nameValue && !nameValue.startsWith("myco:")) {
1177
+ issues.push(`Skill name must start with "myco:" prefix. Got: "${nameValue}"`);
1178
+ }
1179
+ if (nameValue && nameValue !== `myco:${dirName}`) {
1180
+ issues.push(`Skill name must match directory name. Expected "myco:${dirName}", got "${nameValue}"`);
1181
+ }
1182
+ const managedByValue = normalizeFrontmatterValue(parsedFrontmatter.managed_by);
1183
+ if (managedByValue && managedByValue !== "myco") {
1184
+ issues.push(`managed_by must be "myco". Got: "${managedByValue}"`);
1132
1185
  }
1133
- const managedMatch = frontmatter.match(/^managed_by:\s*(.+)$/m);
1134
- if (managedMatch && managedMatch[1].trim() !== "myco") {
1135
- issues.push(`managed_by must be "myco". Got: "${managedMatch[1].trim()}"`);
1186
+ const descriptionValue = normalizeFrontmatterValue(parsedFrontmatter.description);
1187
+ if (descriptionValue && descriptionValue.length > MAX_SKILL_DESCRIPTION_CHARS) {
1188
+ issues.push(
1189
+ `description exceeds maximum length of ${MAX_SKILL_DESCRIPTION_CHARS} characters (got ${descriptionValue.length})`
1190
+ );
1136
1191
  }
1137
- const rawAllowedTools = extractFrontmatterField(content, "allowed-tools");
1192
+ const rawAllowedTools = normalizeFrontmatterValue(parsedFrontmatter["allowed-tools"]);
1138
1193
  if (rawAllowedTools) {
1139
1194
  const rawValue = rawAllowedTools;
1140
1195
  if (rawValue.includes("vault_")) {
@@ -2167,4 +2222,4 @@ export {
2167
2222
  buildTaskInstruction,
2168
2223
  isInstructionRequiredTask
2169
2224
  };
2170
- //# sourceMappingURL=chunk-THZKOZ4M.js.map
2225
+ //# sourceMappingURL=chunk-RTNLDAIC.js.map