@stigmer/plugin-package 3.15.3-dev.20260916211208

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 (173) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +66 -0
  3. package/detect.d.ts +50 -0
  4. package/detect.d.ts.map +1 -0
  5. package/detect.js +164 -0
  6. package/detect.js.map +1 -0
  7. package/dialects/claude.d.ts +30 -0
  8. package/dialects/claude.d.ts.map +1 -0
  9. package/dialects/claude.js +71 -0
  10. package/dialects/claude.js.map +1 -0
  11. package/dialects/codex.d.ts +18 -0
  12. package/dialects/codex.d.ts.map +1 -0
  13. package/dialects/codex.js +19 -0
  14. package/dialects/codex.js.map +1 -0
  15. package/dialects/cursor.d.ts +23 -0
  16. package/dialects/cursor.d.ts.map +1 -0
  17. package/dialects/cursor.js +63 -0
  18. package/dialects/cursor.js.map +1 -0
  19. package/dialects/manifest.d.ts +109 -0
  20. package/dialects/manifest.d.ts.map +1 -0
  21. package/dialects/manifest.js +194 -0
  22. package/dialects/manifest.js.map +1 -0
  23. package/dialects/open.d.ts +18 -0
  24. package/dialects/open.d.ts.map +1 -0
  25. package/dialects/open.js +47 -0
  26. package/dialects/open.js.map +1 -0
  27. package/documents.d.ts +43 -0
  28. package/documents.d.ts.map +1 -0
  29. package/documents.js +111 -0
  30. package/documents.js.map +1 -0
  31. package/files.d.ts +114 -0
  32. package/files.d.ts.map +1 -0
  33. package/files.js +187 -0
  34. package/files.js.map +1 -0
  35. package/frontmatter.d.ts +51 -0
  36. package/frontmatter.d.ts.map +1 -0
  37. package/frontmatter.js +61 -0
  38. package/frontmatter.js.map +1 -0
  39. package/index.d.ts +19 -0
  40. package/index.d.ts.map +1 -0
  41. package/index.js +17 -0
  42. package/index.js.map +1 -0
  43. package/messages.d.ts +39 -0
  44. package/messages.d.ts.map +1 -0
  45. package/messages.js +135 -0
  46. package/messages.js.map +1 -0
  47. package/normalise/ignored.d.ts +24 -0
  48. package/normalise/ignored.d.ts.map +1 -0
  49. package/normalise/ignored.js +68 -0
  50. package/normalise/ignored.js.map +1 -0
  51. package/normalise/mcp-servers.d.ts +47 -0
  52. package/normalise/mcp-servers.d.ts.map +1 -0
  53. package/normalise/mcp-servers.js +397 -0
  54. package/normalise/mcp-servers.js.map +1 -0
  55. package/normalise/overlay.d.ts +27 -0
  56. package/normalise/overlay.d.ts.map +1 -0
  57. package/normalise/overlay.js +67 -0
  58. package/normalise/overlay.js.map +1 -0
  59. package/normalise/skills.d.ts +31 -0
  60. package/normalise/skills.d.ts.map +1 -0
  61. package/normalise/skills.js +116 -0
  62. package/normalise/skills.js.map +1 -0
  63. package/normalise/sub-agents.d.ts +44 -0
  64. package/normalise/sub-agents.d.ts.map +1 -0
  65. package/normalise/sub-agents.js +168 -0
  66. package/normalise/sub-agents.js.map +1 -0
  67. package/normalise/variables.d.ts +27 -0
  68. package/normalise/variables.d.ts.map +1 -0
  69. package/normalise/variables.js +155 -0
  70. package/normalise/variables.js.map +1 -0
  71. package/outcome.d.ts +46 -0
  72. package/outcome.d.ts.map +1 -0
  73. package/outcome.js +21 -0
  74. package/outcome.js.map +1 -0
  75. package/package.json +40 -0
  76. package/placeholders.d.ts +41 -0
  77. package/placeholders.d.ts.map +1 -0
  78. package/placeholders.js +68 -0
  79. package/placeholders.js.map +1 -0
  80. package/read-plugin-package.d.ts +19 -0
  81. package/read-plugin-package.d.ts.map +1 -0
  82. package/read-plugin-package.js +67 -0
  83. package/read-plugin-package.js.map +1 -0
  84. package/src/__test-utils__/directory-files.ts +29 -0
  85. package/src/__test-utils__/read.ts +55 -0
  86. package/src/__tests__/adversarial.test.ts +434 -0
  87. package/src/__tests__/detect.test.ts +133 -0
  88. package/src/__tests__/files.test.ts +119 -0
  89. package/src/__tests__/fixtures/cursor-plugins/NOTICE +22 -0
  90. package/src/__tests__/fixtures/cursor-plugins/advisor/.cursor-plugin/plugin.json +33 -0
  91. package/src/__tests__/fixtures/cursor-plugins/advisor/CHANGELOG.md +8 -0
  92. package/src/__tests__/fixtures/cursor-plugins/advisor/LICENSE +21 -0
  93. package/src/__tests__/fixtures/cursor-plugins/advisor/README.md +87 -0
  94. package/src/__tests__/fixtures/cursor-plugins/advisor/agents/advisor-subagent.md +48 -0
  95. package/src/__tests__/fixtures/cursor-plugins/advisor/assets/avatar.png +0 -0
  96. package/src/__tests__/fixtures/cursor-plugins/advisor/hooks/capture-response.sh +20 -0
  97. package/src/__tests__/fixtures/cursor-plugins/advisor/hooks/hooks.json +27 -0
  98. package/src/__tests__/fixtures/cursor-plugins/advisor/hooks/lib.sh +61 -0
  99. package/src/__tests__/fixtures/cursor-plugins/advisor/hooks/mark-pending.sh +27 -0
  100. package/src/__tests__/fixtures/cursor-plugins/advisor/hooks/record-consult.sh +41 -0
  101. package/src/__tests__/fixtures/cursor-plugins/advisor/hooks/stop-hook.sh +48 -0
  102. package/src/__tests__/fixtures/cursor-plugins/advisor/skills/advisor/SKILL.md +123 -0
  103. package/src/__tests__/fixtures/cursor-plugins/advisor/skills/advisor/references/briefing-template.md +44 -0
  104. package/src/__tests__/fixtures/cursor-plugins/github/.cursor-plugin/plugin.json +45 -0
  105. package/src/__tests__/fixtures/cursor-plugins/github/CHANGELOG.md +9 -0
  106. package/src/__tests__/fixtures/cursor-plugins/github/LICENSE +21 -0
  107. package/src/__tests__/fixtures/cursor-plugins/github/README.md +64 -0
  108. package/src/__tests__/fixtures/cursor-plugins/github/assets/logo.svg +0 -0
  109. package/src/__tests__/fixtures/cursor-plugins/github/mcp.json +11 -0
  110. package/src/__tests__/fixtures/cursor-plugins/playwright/.cursor-plugin/plugin.json +35 -0
  111. package/src/__tests__/fixtures/cursor-plugins/playwright/CHANGELOG.md +8 -0
  112. package/src/__tests__/fixtures/cursor-plugins/playwright/LICENSE +21 -0
  113. package/src/__tests__/fixtures/cursor-plugins/playwright/README.md +46 -0
  114. package/src/__tests__/fixtures/cursor-plugins/playwright/assets/logo.svg +0 -0
  115. package/src/__tests__/fixtures/cursor-plugins/playwright/mcp.json +8 -0
  116. package/src/__tests__/fixtures/cursor-plugins/salesforce/.cursor-plugin/plugin.json +48 -0
  117. package/src/__tests__/fixtures/cursor-plugins/salesforce/CHANGELOG.md +10 -0
  118. package/src/__tests__/fixtures/cursor-plugins/salesforce/LICENSE +21 -0
  119. package/src/__tests__/fixtures/cursor-plugins/salesforce/README.md +95 -0
  120. package/src/__tests__/fixtures/cursor-plugins/salesforce/assets/logo.svg +0 -0
  121. package/src/__tests__/fixtures/cursor-plugins/salesforce/mcp.json +12 -0
  122. package/src/__tests__/fixtures/cursor-plugins/thermos/.cursor-plugin/plugin.json +32 -0
  123. package/src/__tests__/fixtures/cursor-plugins/thermos/CHANGELOG.md +8 -0
  124. package/src/__tests__/fixtures/cursor-plugins/thermos/LICENSE +21 -0
  125. package/src/__tests__/fixtures/cursor-plugins/thermos/README.md +70 -0
  126. package/src/__tests__/fixtures/cursor-plugins/thermos/agents/thermo-nuclear-code-quality-review-subagent.md +23 -0
  127. package/src/__tests__/fixtures/cursor-plugins/thermos/agents/thermo-nuclear-review-subagent.md +28 -0
  128. package/src/__tests__/fixtures/cursor-plugins/thermos/assets/logo.png +0 -0
  129. package/src/__tests__/fixtures/cursor-plugins/thermos/skills/thermo-nuclear-code-quality-review/SKILL.md +192 -0
  130. package/src/__tests__/fixtures/cursor-plugins/thermos/skills/thermo-nuclear-review/SKILL.md +51 -0
  131. package/src/__tests__/fixtures/cursor-plugins/thermos/skills/thermos/SKILL.md +21 -0
  132. package/src/__tests__/fixtures/cursor-plugins/xero/.cursor-plugin/plugin.json +53 -0
  133. package/src/__tests__/fixtures/cursor-plugins/xero/CHANGELOG.md +9 -0
  134. package/src/__tests__/fixtures/cursor-plugins/xero/LICENSE +21 -0
  135. package/src/__tests__/fixtures/cursor-plugins/xero/README.md +79 -0
  136. package/src/__tests__/fixtures/cursor-plugins/xero/assets/logo.png +0 -0
  137. package/src/__tests__/fixtures/cursor-plugins/xero/mcp.json +16 -0
  138. package/src/__tests__/fixtures.test.ts +198 -0
  139. package/src/__tests__/mcp-servers.test.ts +120 -0
  140. package/src/__tests__/overlay-and-ignored.test.ts +65 -0
  141. package/src/__tests__/skills.test.ts +89 -0
  142. package/src/__tests__/sub-agents.test.ts +111 -0
  143. package/src/__tests__/variables.test.ts +94 -0
  144. package/src/detect.ts +189 -0
  145. package/src/dialects/claude.ts +90 -0
  146. package/src/dialects/codex.ts +24 -0
  147. package/src/dialects/cursor.ts +73 -0
  148. package/src/dialects/manifest.ts +237 -0
  149. package/src/dialects/open.ts +48 -0
  150. package/src/documents.ts +145 -0
  151. package/src/files.ts +213 -0
  152. package/src/frontmatter.ts +70 -0
  153. package/src/index.ts +59 -0
  154. package/src/messages.ts +206 -0
  155. package/src/normalise/ignored.ts +70 -0
  156. package/src/normalise/mcp-servers.ts +427 -0
  157. package/src/normalise/overlay.ts +71 -0
  158. package/src/normalise/skills.ts +126 -0
  159. package/src/normalise/sub-agents.ts +184 -0
  160. package/src/normalise/variables.ts +161 -0
  161. package/src/outcome.ts +122 -0
  162. package/src/placeholders.ts +74 -0
  163. package/src/read-plugin-package.ts +74 -0
  164. package/src/testing.ts +258 -0
  165. package/src/types.ts +189 -0
  166. package/testing.d.ts +106 -0
  167. package/testing.d.ts.map +1 -0
  168. package/testing.js +182 -0
  169. package/testing.js.map +1 -0
  170. package/types.d.ts +152 -0
  171. package/types.d.ts.map +1 -0
  172. package/types.js +19 -0
  173. package/types.js.map +1 -0
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Skill discovery and the `SKILL.md` frontmatter check.
3
+ *
4
+ * Discovery follows the union of the dialects' rules: the immediate child
5
+ * directories of `skills/` that hold a `SKILL.md` (the open format's fixed
6
+ * location, no recursion), plus every path a manifest declared (Claude adds
7
+ * to the default; Cursor's value is the default in practice), where a
8
+ * declared path is a skill when it holds `SKILL.md` directly and a directory
9
+ * of skills otherwise, plus Claude's single-skill layout (a root `SKILL.md`
10
+ * with no `skills/` and no declaration). A declared path that names nothing
11
+ * is a warning: Cursor's own tooling does not refuse it, and refusing would
12
+ * turn a stale manifest line into a failed install.
13
+ *
14
+ * The frontmatter check is a discovery check, not the push gate: it asks
15
+ * that the block be present and closed, that it parse, and that `name`
16
+ * satisfy `SKILL_NAME_PATTERN`. A missing `name` falls back to the directory
17
+ * name (Claude's rule) with a warning; the Agent Skills rules Stigmer relaxes
18
+ * (`name` equal to the directory, `description` present) are warnings.
19
+ * Optional frontmatter (`license`, `compatibility`, `metadata`,
20
+ * `allowed-tools`) and vendor keys ride inside the skill untouched. Every
21
+ * file under the skill directory is listed for the installer's per-skill
22
+ * archive; only `SKILL.md` is ever read.
23
+ */
24
+ import { readText } from "../documents.js";
25
+ import { basename, comparePaths, joinPath } from "../files.js";
26
+ import { extractFrontmatter, parseFrontmatter, SKILL_NAME_PATTERN } from "../frontmatter.js";
27
+ export const SKILL_FILE = "SKILL.md";
28
+ export const DEFAULT_SKILLS_DIR = "skills";
29
+ export function normaliseSkills(index, set, findings) {
30
+ const skills = [];
31
+ const seenNames = new Map();
32
+ for (const dir of discoverSkillDirs(index, set, findings)) {
33
+ const skill = readSkill(index, dir, set, findings);
34
+ if (skill === undefined)
35
+ continue;
36
+ const previous = seenNames.get(skill.name);
37
+ if (previous !== undefined) {
38
+ findings.error("skill-name-duplicate", { subject: skill.name, path: joinPath(dir, SKILL_FILE) });
39
+ continue;
40
+ }
41
+ seenNames.set(skill.name, dir);
42
+ skills.push(skill);
43
+ }
44
+ return skills;
45
+ }
46
+ /** Skill directories, deduplicated, in path order; the root skill is `""`. */
47
+ function discoverSkillDirs(index, set, findings) {
48
+ const dirs = new Set();
49
+ const addSkillsUnder = (parent) => {
50
+ for (const child of index.childDirectories(parent)) {
51
+ const dir = joinPath(parent, child);
52
+ if (index.has(joinPath(dir, SKILL_FILE)))
53
+ dirs.add(dir);
54
+ }
55
+ };
56
+ addSkillsUnder(DEFAULT_SKILLS_DIR);
57
+ const declared = set.manifests.flatMap((m) => m.skillPaths);
58
+ for (const { path, manifest } of declared) {
59
+ if (index.has(joinPath(path, SKILL_FILE))) {
60
+ dirs.add(path);
61
+ }
62
+ else if (index.isDirectory(path)) {
63
+ addSkillsUnder(path);
64
+ }
65
+ else {
66
+ findings.warn("path-missing", { path: manifest, subject: path === "" ? "." : `./${path}` });
67
+ }
68
+ }
69
+ if (declared.length === 0 && !index.isDirectory(DEFAULT_SKILLS_DIR) && index.has(SKILL_FILE)) {
70
+ dirs.add("");
71
+ }
72
+ return [...dirs].sort(comparePaths);
73
+ }
74
+ function readSkill(index, dir, set, findings) {
75
+ const path = joinPath(dir, SKILL_FILE);
76
+ const text = readText(index, path, "skillMd", findings);
77
+ if (text === undefined)
78
+ return undefined;
79
+ const extracted = extractFrontmatter(text);
80
+ if (!extracted.ok) {
81
+ findings.error(extracted.reason === "missing" ? "skill-frontmatter-missing" : "skill-frontmatter-unclosed", { path });
82
+ return undefined;
83
+ }
84
+ const parsed = parseFrontmatter(extracted.yaml);
85
+ if (!parsed.ok) {
86
+ findings.error("skill-frontmatter-unreadable", { path, detail: parsed.detail });
87
+ return undefined;
88
+ }
89
+ const directoryName = dir === "" ? (set.name ?? "skill") : basename(dir);
90
+ let name;
91
+ if (typeof parsed.fields["name"] === "string" && parsed.fields["name"] !== "") {
92
+ name = parsed.fields["name"];
93
+ }
94
+ else {
95
+ name = directoryName;
96
+ findings.warn("skill-name-defaulted", { path, subject: name });
97
+ }
98
+ if (!SKILL_NAME_PATTERN.test(name)) {
99
+ findings.error("skill-name-invalid", { path, subject: name });
100
+ return undefined;
101
+ }
102
+ if (dir !== "" && name !== directoryName) {
103
+ findings.warn("skill-name-differs-from-directory", { path, subject: name, detail: directoryName });
104
+ }
105
+ const description = parsed.fields["description"];
106
+ if (typeof description !== "string" || description === "") {
107
+ findings.warn("skill-description-missing", { path, subject: name });
108
+ }
109
+ return {
110
+ name,
111
+ ...(typeof description === "string" && description !== "" && { description }),
112
+ dir,
113
+ files: index.filesUnder(dir),
114
+ };
115
+ }
116
+ //# sourceMappingURL=skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/normalise/skills.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Sub-agent files (`agents/*.md`) into the shape `SubAgent` takes.
3
+ *
4
+ * Cursor and Claude Code define this component; the open format does not,
5
+ * so `agents/` is read only when a vendor manifest is present (`detect.ts`
6
+ * decides) and recorded as ignored otherwise. Files come from the default
7
+ * `agents/` directory or, when any manifest declares `agents`, from the
8
+ * declared paths only (Claude's "replaces the default"), each of which may
9
+ * be one `.md` file or a directory of them.
10
+ *
11
+ * The body of the file is the sub-agent's prompt. A body under
12
+ * `SUB_AGENT_INSTRUCTIONS_MIN` characters is refused, because that is the
13
+ * proto's floor for `SubAgent.instructions` and a parser that let it through
14
+ * would add a second silent path after the runner's own (which drops a
15
+ * sub-agent whose model is unregistered). Frontmatter is optional (a bare
16
+ * prompt is named after its file, Claude's rule) but must parse when
17
+ * present: Claude degrades an unparseable header to a file-named agent with
18
+ * every field ignored, and a faithful install is better refused than
19
+ * quietly stripped.
20
+ *
21
+ * `model` is classified into an alias, never a model id (see `ModelHint`).
22
+ * Claude `skills:` names are matched against the plugin's own skills. Every
23
+ * other frontmatter field (`tools`, `disallowedTools`, `effort`, `maxTurns`,
24
+ * `readonly`, `is_background`, `memory`, `isolation`, ...) is a warning,
25
+ * once per field per agent: they configure the IDE's loop, not the
26
+ * sub-agent's prompt.
27
+ */
28
+ import type { ManifestSet } from "../detect.js";
29
+ import { type PluginFileIndex } from "../files.js";
30
+ import type { Findings } from "../messages.js";
31
+ import type { ModelHint, PluginSkill, PluginSubAgent } from "../types.js";
32
+ export declare const DEFAULT_AGENTS_DIR = "agents";
33
+ /** The proto's `SubAgent.instructions` `min_len`. */
34
+ export declare const SUB_AGENT_INSTRUCTIONS_MIN = 10;
35
+ export declare function normaliseSubAgents(index: PluginFileIndex, set: ManifestSet, skills: readonly PluginSkill[], findings: Findings): readonly PluginSubAgent[];
36
+ /**
37
+ * A dialect's `model` value to an alias. Cursor writes `fast` and
38
+ * `inherit`; Claude writes `sonnet`, `opus`, `haiku`, `inherit` or a full
39
+ * model id, which contains one of those family names. Anything else
40
+ * (Cursor's `grok-4.6[effort=xhigh]`, a vendor id Stigmer does not serve)
41
+ * is `unknown` with the raw text kept for the installer's warning.
42
+ */
43
+ export declare function classifyModel(raw: string): ModelHint;
44
+ //# sourceMappingURL=sub-agents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sub-agents.d.ts","sourceRoot":"","sources":["../../src/normalise/sub-agents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,EAAoC,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAErF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAc,SAAS,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEtF,eAAO,MAAM,kBAAkB,WAAW,CAAC;AAE3C,qDAAqD;AACrD,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAI7C,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,eAAe,EACtB,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,SAAS,WAAW,EAAE,EAC9B,QAAQ,EAAE,QAAQ,GACjB,SAAS,cAAc,EAAE,CAgB3B;AAkGD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAepD"}
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Sub-agent files (`agents/*.md`) into the shape `SubAgent` takes.
3
+ *
4
+ * Cursor and Claude Code define this component; the open format does not,
5
+ * so `agents/` is read only when a vendor manifest is present (`detect.ts`
6
+ * decides) and recorded as ignored otherwise. Files come from the default
7
+ * `agents/` directory or, when any manifest declares `agents`, from the
8
+ * declared paths only (Claude's "replaces the default"), each of which may
9
+ * be one `.md` file or a directory of them.
10
+ *
11
+ * The body of the file is the sub-agent's prompt. A body under
12
+ * `SUB_AGENT_INSTRUCTIONS_MIN` characters is refused, because that is the
13
+ * proto's floor for `SubAgent.instructions` and a parser that let it through
14
+ * would add a second silent path after the runner's own (which drops a
15
+ * sub-agent whose model is unregistered). Frontmatter is optional (a bare
16
+ * prompt is named after its file, Claude's rule) but must parse when
17
+ * present: Claude degrades an unparseable header to a file-named agent with
18
+ * every field ignored, and a faithful install is better refused than
19
+ * quietly stripped.
20
+ *
21
+ * `model` is classified into an alias, never a model id (see `ModelHint`).
22
+ * Claude `skills:` names are matched against the plugin's own skills. Every
23
+ * other frontmatter field (`tools`, `disallowedTools`, `effort`, `maxTurns`,
24
+ * `readonly`, `is_background`, `memory`, `isolation`, ...) is a warning,
25
+ * once per field per agent: they configure the IDE's loop, not the
26
+ * sub-agent's prompt.
27
+ */
28
+ import { readText } from "../documents.js";
29
+ import { basename, comparePaths, joinPath } from "../files.js";
30
+ import { extractFrontmatter, parseFrontmatter } from "../frontmatter.js";
31
+ export const DEFAULT_AGENTS_DIR = "agents";
32
+ /** The proto's `SubAgent.instructions` `min_len`. */
33
+ export const SUB_AGENT_INSTRUCTIONS_MIN = 10;
34
+ const READ_FIELDS = new Set(["name", "description", "model", "skills"]);
35
+ export function normaliseSubAgents(index, set, skills, findings) {
36
+ if (!set.readsAgents)
37
+ return [];
38
+ const skillNames = new Set(skills.map((skill) => skill.name));
39
+ const agents = [];
40
+ const seen = new Set();
41
+ for (const path of discoverAgentFiles(index, set, findings)) {
42
+ const agent = readSubAgent(index, path, skillNames, findings);
43
+ if (agent === undefined)
44
+ continue;
45
+ if (seen.has(agent.name)) {
46
+ findings.error("sub-agent-name-duplicate", { subject: agent.name, path });
47
+ continue;
48
+ }
49
+ seen.add(agent.name);
50
+ agents.push(agent);
51
+ }
52
+ return agents;
53
+ }
54
+ function discoverAgentFiles(index, set, findings) {
55
+ const files = new Set();
56
+ const addMarkdownUnder = (dir) => {
57
+ for (const name of index.childFiles(dir)) {
58
+ if (name.endsWith(".md"))
59
+ files.add(joinPath(dir, name));
60
+ }
61
+ };
62
+ const declared = set.manifests.flatMap((m) => m.agentPaths ?? []);
63
+ if (set.manifests.every((m) => m.agentPaths === undefined)) {
64
+ addMarkdownUnder(DEFAULT_AGENTS_DIR);
65
+ }
66
+ for (const { path, manifest } of declared) {
67
+ if (path !== "" && index.has(path) && path.endsWith(".md")) {
68
+ files.add(path);
69
+ }
70
+ else if (index.isDirectory(path)) {
71
+ addMarkdownUnder(path);
72
+ }
73
+ else {
74
+ findings.warn("path-missing", { path: manifest, subject: path === "" ? "." : `./${path}` });
75
+ }
76
+ }
77
+ return [...files].sort(comparePaths);
78
+ }
79
+ function readSubAgent(index, path, skillNames, findings) {
80
+ const text = readText(index, path, "subAgent", findings);
81
+ if (text === undefined)
82
+ return undefined;
83
+ const extracted = extractFrontmatter(text);
84
+ let fieldsMap = {};
85
+ let body = text;
86
+ if (extracted.ok) {
87
+ const parsed = parseFrontmatter(extracted.yaml);
88
+ if (!parsed.ok) {
89
+ findings.error("sub-agent-frontmatter-unreadable", { path, detail: parsed.detail });
90
+ return undefined;
91
+ }
92
+ fieldsMap = parsed.fields;
93
+ body = extracted.body;
94
+ }
95
+ else if (extracted.reason === "unclosed") {
96
+ findings.error("sub-agent-frontmatter-unreadable", { path, detail: "the frontmatter is not closed (missing the closing '---')" });
97
+ return undefined;
98
+ }
99
+ const stem = basename(path).replace(/\.md$/, "");
100
+ let name;
101
+ if (typeof fieldsMap["name"] === "string" && fieldsMap["name"] !== "") {
102
+ name = fieldsMap["name"];
103
+ }
104
+ else {
105
+ name = stem;
106
+ findings.warn("sub-agent-name-defaulted", { path, subject: name });
107
+ }
108
+ const instructions = body.trim();
109
+ if (instructions.length < SUB_AGENT_INSTRUCTIONS_MIN) {
110
+ findings.error("sub-agent-instructions-short", { path, subject: name, detail: String(SUB_AGENT_INSTRUCTIONS_MIN) });
111
+ return undefined;
112
+ }
113
+ const description = fieldsMap["description"];
114
+ const requested = fieldsMap["skills"];
115
+ const matchedSkills = [];
116
+ if (Array.isArray(requested)) {
117
+ for (const skill of requested) {
118
+ if (typeof skill !== "string")
119
+ continue;
120
+ if (skillNames.has(skill))
121
+ matchedSkills.push(skill);
122
+ else
123
+ findings.warn("sub-agent-skill-unknown", { path, subject: name, detail: skill });
124
+ }
125
+ }
126
+ let modelHint;
127
+ const model = fieldsMap["model"];
128
+ if (typeof model === "string" && model.trim() !== "") {
129
+ modelHint = classifyModel(model);
130
+ if (modelHint.alias === "unknown")
131
+ findings.warn("sub-agent-model-unknown", { path, subject: name, detail: model });
132
+ }
133
+ for (const field of Object.keys(fieldsMap)) {
134
+ if (!READ_FIELDS.has(field))
135
+ findings.warn("sub-agent-field-ignored", { path, subject: name, detail: field });
136
+ }
137
+ return {
138
+ name,
139
+ ...(typeof description === "string" && description !== "" && { description }),
140
+ instructions,
141
+ skillNames: matchedSkills,
142
+ ...(modelHint !== undefined && { modelHint }),
143
+ path,
144
+ };
145
+ }
146
+ /**
147
+ * A dialect's `model` value to an alias. Cursor writes `fast` and
148
+ * `inherit`; Claude writes `sonnet`, `opus`, `haiku`, `inherit` or a full
149
+ * model id, which contains one of those family names. Anything else
150
+ * (Cursor's `grok-4.6[effort=xhigh]`, a vendor id Stigmer does not serve)
151
+ * is `unknown` with the raw text kept for the installer's warning.
152
+ */
153
+ export function classifyModel(raw) {
154
+ const value = raw.trim().toLowerCase();
155
+ const alias = value === "inherit"
156
+ ? "inherit"
157
+ : value === "fast"
158
+ ? "fast"
159
+ : value.includes("haiku")
160
+ ? "haiku"
161
+ : value.includes("sonnet")
162
+ ? "sonnet"
163
+ : value.includes("opus")
164
+ ? "opus"
165
+ : "unknown";
166
+ return { raw, alias };
167
+ }
168
+ //# sourceMappingURL=sub-agents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sub-agents.js","sourceRoot":"","sources":["../../src/normalise/sub-agents.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Variable declarations, from the dialects that have them, reconciled with
3
+ * the references the servers make.
4
+ *
5
+ * Cursor declares `variables` as a JSON Schema object with no sensitivity
6
+ * flag, so every Cursor variable is a secret on Stigmer (a token treated as
7
+ * plain text is the costly mistake; a region name treated as a secret is
8
+ * an inconvenience). Claude declares `userConfig` entries with `sensitive`
9
+ * and `required`, plus `default`, `options`, `multiple`, `min`, `max` and
10
+ * the `directory`, `file`, `number`, `boolean` types, none of which a
11
+ * Stigmer variable carries (values are strings supplied by the user, and a
12
+ * local path means nothing in the sandbox); each is warned once.
13
+ *
14
+ * Reconciliation is what makes an imported server start: the runner
15
+ * filters a stdio server's environment to its declared keys and resolves
16
+ * `${VAR}` in headers and arguments strictly, so a variable a server
17
+ * references but no manifest declares would never reach it. Such a variable
18
+ * is declared here as a required secret, with a warning naming the server.
19
+ * A declared variable no server references is warned too; it is not wrong,
20
+ * only useless.
21
+ */
22
+ import type { ManifestSet } from "../detect.js";
23
+ import type { Findings } from "../messages.js";
24
+ import type { PluginVariable } from "../types.js";
25
+ import type { McpServersResult } from "./mcp-servers.js";
26
+ export declare function normaliseVariables(set: ManifestSet, servers: McpServersResult, findings: Findings): readonly PluginVariable[];
27
+ //# sourceMappingURL=variables.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"variables.d.ts","sourceRoot":"","sources":["../../src/normalise/variables.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,GAAG,SAAS,cAAc,EAAE,CA2C7H"}
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Variable declarations, from the dialects that have them, reconciled with
3
+ * the references the servers make.
4
+ *
5
+ * Cursor declares `variables` as a JSON Schema object with no sensitivity
6
+ * flag, so every Cursor variable is a secret on Stigmer (a token treated as
7
+ * plain text is the costly mistake; a region name treated as a secret is
8
+ * an inconvenience). Claude declares `userConfig` entries with `sensitive`
9
+ * and `required`, plus `default`, `options`, `multiple`, `min`, `max` and
10
+ * the `directory`, `file`, `number`, `boolean` types, none of which a
11
+ * Stigmer variable carries (values are strings supplied by the user, and a
12
+ * local path means nothing in the sandbox); each is warned once.
13
+ *
14
+ * Reconciliation is what makes an imported server start: the runner
15
+ * filters a stdio server's environment to its declared keys and resolves
16
+ * `${VAR}` in headers and arguments strictly, so a variable a server
17
+ * references but no manifest declares would never reach it. Such a variable
18
+ * is declared here as a required secret, with a warning naming the server.
19
+ * A declared variable no server references is warned too; it is not wrong,
20
+ * only useless.
21
+ */
22
+ import { describeValue, fields, isJsonObject, isStringArray } from "../documents.js";
23
+ import { VARIABLE_NAME_PATTERN } from "../placeholders.js";
24
+ export function normaliseVariables(set, servers, findings) {
25
+ const declared = new Map();
26
+ const declaredIn = new Map();
27
+ for (const manifest of set.manifests) {
28
+ const declaration = manifest.variables;
29
+ if (declaration === undefined)
30
+ continue;
31
+ const variables = declaration.dialect === "cursor"
32
+ ? readCursorVariables(declaration.value, declaration.manifest, findings)
33
+ : readClaudeVariables(declaration.value, declaration.manifest, findings);
34
+ for (const variable of variables) {
35
+ // Two manifests declaring one name: the identity manifest's wins.
36
+ if (declared.has(variable.name))
37
+ continue;
38
+ declared.set(variable.name, variable);
39
+ declaredIn.set(variable.name, declaration.manifest);
40
+ }
41
+ }
42
+ const referencedBy = new Map();
43
+ for (const server of servers.servers) {
44
+ for (const name of server.env) {
45
+ if (!referencedBy.has(name))
46
+ referencedBy.set(name, server.name);
47
+ }
48
+ }
49
+ // A refused server's references are unknown, so an "unreferenced"
50
+ // warning would be a consequence of the refusal, not advice.
51
+ if (servers.refused === 0) {
52
+ for (const [name, variable] of declared) {
53
+ if (!referencedBy.has(name)) {
54
+ findings.warn("variable-unreferenced", { subject: variable.name, path: declaredIn.get(name) });
55
+ }
56
+ }
57
+ }
58
+ const inferred = [];
59
+ for (const [name, server] of [...referencedBy].sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))) {
60
+ if (declared.has(name))
61
+ continue;
62
+ findings.warn("variable-inferred", { subject: name, detail: server });
63
+ inferred.push({ name, isSecret: true, optional: false, declaredBy: "inferred" });
64
+ }
65
+ return [...declared.values(), ...inferred];
66
+ }
67
+ /**
68
+ * Cursor: `{ type: "object", properties: { NAME: { type, title, description } }, required: [NAME] }`.
69
+ */
70
+ function readCursorVariables(value, manifest, findings) {
71
+ if (!isJsonObject(value) || value["type"] !== "object") {
72
+ findings.error("manifest-field-type", { path: manifest, subject: "variables", detail: "a JSON Schema object with type 'object'" });
73
+ return [];
74
+ }
75
+ const properties = value["properties"] ?? {};
76
+ if (!isJsonObject(properties)) {
77
+ findings.error("manifest-field-type", { path: manifest, subject: "variables.properties", detail: "an object" });
78
+ return [];
79
+ }
80
+ const required = value["required"] ?? [];
81
+ if (!isStringArray(required)) {
82
+ findings.error("manifest-field-type", { path: manifest, subject: "variables.required", detail: "an array of strings" });
83
+ return [];
84
+ }
85
+ const variables = [];
86
+ for (const [name, schema] of fields(properties)) {
87
+ if (!VARIABLE_NAME_PATTERN.test(name)) {
88
+ findings.error("variable-name-invalid", { subject: name, path: manifest });
89
+ continue;
90
+ }
91
+ const property = isJsonObject(schema) ? schema : {};
92
+ const type = property["type"];
93
+ if (type !== undefined && type !== "string") {
94
+ findings.warn("variable-type-narrowed", { subject: name, path: manifest, detail: describeValue(type) });
95
+ }
96
+ if (property["default"] !== undefined)
97
+ findings.warn("variable-default-dropped", { subject: name, path: manifest });
98
+ if (property["enum"] !== undefined)
99
+ findings.warn("variable-option-dropped", { subject: name, path: manifest, detail: "enum" });
100
+ const description = describe(property);
101
+ variables.push({
102
+ name,
103
+ ...(description !== undefined && { description }),
104
+ isSecret: true,
105
+ optional: !required.includes(name),
106
+ declaredBy: "cursor",
107
+ });
108
+ }
109
+ return variables;
110
+ }
111
+ /**
112
+ * Claude: `{ KEY: { type, title, description, sensitive, required, default, options, multiple, min, max } }`.
113
+ */
114
+ function readClaudeVariables(value, manifest, findings) {
115
+ if (!isJsonObject(value)) {
116
+ findings.error("manifest-field-type", { path: manifest, subject: "userConfig", detail: "an object" });
117
+ return [];
118
+ }
119
+ const variables = [];
120
+ for (const [name, entry] of fields(value)) {
121
+ if (!VARIABLE_NAME_PATTERN.test(name)) {
122
+ findings.error("variable-name-invalid", { subject: name, path: manifest });
123
+ continue;
124
+ }
125
+ if (!isJsonObject(entry)) {
126
+ findings.error("manifest-field-type", { path: manifest, subject: `userConfig.${name}`, detail: "an object" });
127
+ continue;
128
+ }
129
+ const type = entry["type"];
130
+ if (type !== undefined && type !== "string") {
131
+ findings.warn("variable-type-narrowed", { subject: name, path: manifest, detail: describeValue(type) });
132
+ }
133
+ if (entry["default"] !== undefined)
134
+ findings.warn("variable-default-dropped", { subject: name, path: manifest });
135
+ for (const option of ["options", "multiple", "min", "max"]) {
136
+ if (entry[option] !== undefined)
137
+ findings.warn("variable-option-dropped", { subject: name, path: manifest, detail: option });
138
+ }
139
+ const description = describe(entry);
140
+ variables.push({
141
+ name,
142
+ ...(description !== undefined && { description }),
143
+ isSecret: entry["sensitive"] === true,
144
+ optional: entry["required"] !== true,
145
+ declaredBy: "claude",
146
+ });
147
+ }
148
+ return variables;
149
+ }
150
+ /** `title` and `description` joined, whichever are present. */
151
+ function describe(entry) {
152
+ const parts = [entry["title"], entry["description"]].filter((part) => typeof part === "string" && part !== "");
153
+ return parts.length === 0 ? undefined : parts.join(": ");
154
+ }
155
+ //# sourceMappingURL=variables.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"variables.js","sourceRoot":"","sources":["../../src/normalise/variables.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,EAAmB,MAAM,iBAAiB,CAAC;AAEtG,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAI3D,MAAM,UAAU,kBAAkB,CAAC,GAAgB,EAAE,OAAyB,EAAE,QAAkB;IAChG,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA0B,CAAC;IACnD,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC7C,KAAK,MAAM,QAAQ,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;QACrC,MAAM,WAAW,GAAG,QAAQ,CAAC,SAAS,CAAC;QACvC,IAAI,WAAW,KAAK,SAAS;YAAE,SAAS;QACxC,MAAM,SAAS,GACb,WAAW,CAAC,OAAO,KAAK,QAAQ;YAC9B,CAAC,CAAC,mBAAmB,CAAC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,QAAQ,EAAE,QAAQ,CAAC;YACxE,CAAC,CAAC,mBAAmB,CAAC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC7E,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,kEAAkE;YAClE,IAAI,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC1C,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YACtC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC/C,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACrC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC;YAC9B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;IAED,kEAAkE;IAClE,6DAA6D;IAC7D,IAAI,OAAO,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;QAC1B,KAAK,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,QAAQ,EAAE,CAAC;YACxC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC5B,QAAQ,CAAC,IAAI,CAAC,uBAAuB,EAAE,EAAE,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACjG,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAqB,EAAE,CAAC;IACtC,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAChG,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS;QACjC,QAAQ,CAAC,IAAI,CAAC,mBAAmB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACtE,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAC;IACnF,CAAC;IAED,OAAO,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,CAAC;AAC7C,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CAAC,KAAc,EAAE,QAAgB,EAAE,QAAkB;IAC/E,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,QAAQ,EAAE,CAAC;QACvD,QAAQ,CAAC,KAAK,CAAC,qBAAqB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,yCAAyC,EAAE,CAAC,CAAC;QACnI,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,UAAU,GAAG,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;IAC7C,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,QAAQ,CAAC,KAAK,CAAC,qBAAqB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,sBAAsB,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;QAChH,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;IACzC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,QAAQ,CAAC,KAAK,CAAC,qBAAqB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,EAAE,qBAAqB,EAAE,CAAC,CAAC;QACxH,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,SAAS,GAAqB,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;QAChD,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACtC,QAAQ,CAAC,KAAK,CAAC,uBAAuB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC3E,SAAS;QACX,CAAC;QACD,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC9B,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC5C,QAAQ,CAAC,IAAI,CAAC,wBAAwB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1G,CAAC;QACD,IAAI,QAAQ,CAAC,SAAS,CAAC,KAAK,SAAS;YAAE,QAAQ,CAAC,IAAI,CAAC,0BAA0B,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QACpH,IAAI,QAAQ,CAAC,MAAM,CAAC,KAAK,SAAS;YAAE,QAAQ,CAAC,IAAI,CAAC,yBAAyB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QAChI,MAAM,WAAW,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACvC,SAAS,CAAC,IAAI,CAAC;YACb,IAAI;YACJ,GAAG,CAAC,WAAW,KAAK,SAAS,IAAI,EAAE,WAAW,EAAE,CAAC;YACjD,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;YAClC,UAAU,EAAE,QAAQ;SACrB,CAAC,CAAC;IACL,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CAAC,KAAc,EAAE,QAAgB,EAAE,QAAkB;IAC/E,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,QAAQ,CAAC,KAAK,CAAC,qBAAqB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;QACtG,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,SAAS,GAAqB,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1C,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACtC,QAAQ,CAAC,KAAK,CAAC,uBAAuB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC3E,SAAS;QACX,CAAC;QACD,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,QAAQ,CAAC,KAAK,CAAC,qBAAqB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,IAAI,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;YAC9G,SAAS;QACX,CAAC;QACD,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;QAC3B,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC5C,QAAQ,CAAC,IAAI,CAAC,wBAAwB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1G,CAAC;QACD,IAAI,KAAK,CAAC,SAAS,CAAC,KAAK,SAAS;YAAE,QAAQ,CAAC,IAAI,CAAC,0BAA0B,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QACjH,KAAK,MAAM,MAAM,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC;YAC3D,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,SAAS;gBAAE,QAAQ,CAAC,IAAI,CAAC,yBAAyB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QAC/H,CAAC;QACD,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QACpC,SAAS,CAAC,IAAI,CAAC;YACb,IAAI;YACJ,GAAG,CAAC,WAAW,KAAK,SAAS,IAAI,EAAE,WAAW,EAAE,CAAC;YACjD,QAAQ,EAAE,KAAK,CAAC,WAAW,CAAC,KAAK,IAAI;YACrC,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC,KAAK,IAAI;YACpC,UAAU,EAAE,QAAQ;SACrB,CAAC,CAAC;IACL,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,+DAA+D;AAC/D,SAAS,QAAQ,CAAC,KAAiB;IACjC,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC;IAC/H,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC3D,CAAC"}
package/outcome.d.ts ADDED
@@ -0,0 +1,46 @@
1
+ /**
2
+ * The outcome of reading a package and the closed vocabulary of findings.
3
+ *
4
+ * The shape is the server's `ConnectRunOutcome`: a discriminated union on
5
+ * `ok`, with a closed `kind` union behind the failure arm, so a consumer
6
+ * switches on kinds and the compiler closes the switch. An error refuses the
7
+ * package; a warning never does. Both are `PluginFinding`s with the same
8
+ * fields, so one renderer prints both.
9
+ *
10
+ * Two error postures meet here and the header of each module states which
11
+ * applies. Where the open format tells a client to skip a broken component
12
+ * and keep loading, Stigmer refuses the package: an installed agent that
13
+ * quietly lacks a server or a sub-agent is worse than a refused install.
14
+ * But the reader keeps scanning past a fatal finding so one run reports
15
+ * every problem and an author fixes them in one pass.
16
+ *
17
+ * Every kind has exactly one sentence, in `messages.ts`, and the adversarial
18
+ * suite has exactly one fixture per kind. Adding a kind means adding both.
19
+ */
20
+ import type { PluginPackage } from "./types.js";
21
+ export type PluginErrorKind = "no-manifest" | "manifest-unreadable" | "manifest-schema-missing" | "manifest-schema-unsupported" | "manifest-name-missing" | "manifest-name-invalid" | "manifest-name-conflict" | "manifest-field-type" | "path-not-relative" | "path-escapes-root" | "path-glob-unsupported" | "path-uncontained" | "document-too-large" | "skill-frontmatter-missing" | "skill-frontmatter-unclosed" | "skill-frontmatter-unreadable" | "skill-name-invalid" | "skill-name-duplicate" | "mcp-config-unreadable" | "mcp-config-shape" | "mcp-config-schema-missing" | "mcp-config-schema-unsupported" | "mcp-config-field-unknown" | "mcp-server-shape" | "mcp-server-type-missing" | "mcp-server-transport-unknown" | "mcp-server-type-ambiguous" | "mcp-server-type-unknown" | "mcp-server-field-unknown" | "mcp-server-field-type" | "mcp-server-url-missing" | "mcp-server-url-invalid" | "mcp-server-url-variable" | "mcp-server-command-missing" | "mcp-server-command-invalid" | "mcp-server-command-relative" | "mcp-server-plugin-root-reference" | "mcp-server-cwd-unsupported" | "mcp-server-env-literal" | "mcp-server-env-rename" | "mcp-server-name-duplicate" | "mcp-server-header-duplicate" | "mcp-server-header-invalid" | "sub-agent-frontmatter-unreadable" | "sub-agent-instructions-short" | "sub-agent-name-duplicate" | "variable-name-invalid" | "overlay-server-unknown" | "overlay-document-unknown";
22
+ export type PluginWarningKind = "manifest-field-unknown" | "manifest-extensions-invalid" | "path-missing" | "skill-name-defaulted" | "skill-name-differs-from-directory" | "skill-description-missing" | "mcp-config-field-ignored" | "mcp-server-sse-mapped" | "mcp-server-field-ignored" | "mcp-server-auth-ignored" | "variable-inferred" | "variable-unreferenced" | "variable-default-dropped" | "variable-type-narrowed" | "variable-option-dropped" | "sub-agent-name-defaulted" | "sub-agent-skill-unknown" | "sub-agent-model-unknown" | "sub-agent-field-ignored";
23
+ export type PluginFindingKind = PluginErrorKind | PluginWarningKind;
24
+ export interface PluginFinding {
25
+ readonly kind: PluginFindingKind;
26
+ /** The file, or the declared path, the finding is about. */
27
+ readonly path?: string;
28
+ /** The skill, server, sub-agent, variable or field the finding names. */
29
+ readonly subject?: string;
30
+ /** A second identifier the sentence needs (a field name, a parser's own message). */
31
+ readonly detail?: string;
32
+ /** The one sentence for this kind, from `messages.ts`. */
33
+ readonly message: string;
34
+ }
35
+ /** What `read` needs to compose a finding: everything but the sentence. */
36
+ export type FindingContext = Pick<PluginFinding, "path" | "subject" | "detail">;
37
+ export type PluginReadOutcome = {
38
+ readonly ok: true;
39
+ readonly plugin: PluginPackage;
40
+ readonly warnings: readonly PluginFinding[];
41
+ } | {
42
+ readonly ok: false;
43
+ readonly errors: readonly PluginFinding[];
44
+ readonly warnings: readonly PluginFinding[];
45
+ };
46
+ //# sourceMappingURL=outcome.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outcome.d.ts","sourceRoot":"","sources":["../src/outcome.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,MAAM,eAAe,GAEvB,aAAa,GACb,qBAAqB,GACrB,yBAAyB,GACzB,6BAA6B,GAC7B,uBAAuB,GACvB,uBAAuB,GACvB,wBAAwB,GACxB,qBAAqB,GAErB,mBAAmB,GACnB,mBAAmB,GACnB,uBAAuB,GACvB,kBAAkB,GAClB,oBAAoB,GAEpB,2BAA2B,GAC3B,4BAA4B,GAC5B,8BAA8B,GAC9B,oBAAoB,GACpB,sBAAsB,GAEtB,uBAAuB,GACvB,kBAAkB,GAClB,2BAA2B,GAC3B,+BAA+B,GAC/B,0BAA0B,GAE1B,kBAAkB,GAClB,yBAAyB,GACzB,8BAA8B,GAC9B,2BAA2B,GAC3B,yBAAyB,GACzB,0BAA0B,GAC1B,uBAAuB,GACvB,wBAAwB,GACxB,wBAAwB,GACxB,yBAAyB,GACzB,4BAA4B,GAC5B,4BAA4B,GAC5B,6BAA6B,GAC7B,kCAAkC,GAClC,4BAA4B,GAC5B,wBAAwB,GACxB,uBAAuB,GACvB,2BAA2B,GAC3B,6BAA6B,GAC7B,2BAA2B,GAE3B,kCAAkC,GAClC,8BAA8B,GAC9B,0BAA0B,GAE1B,uBAAuB,GAEvB,wBAAwB,GACxB,0BAA0B,CAAC;AAE/B,MAAM,MAAM,iBAAiB,GACzB,wBAAwB,GACxB,6BAA6B,GAC7B,cAAc,GACd,sBAAsB,GACtB,mCAAmC,GACnC,2BAA2B,GAC3B,0BAA0B,GAC1B,uBAAuB,GACvB,0BAA0B,GAC1B,yBAAyB,GACzB,mBAAmB,GACnB,uBAAuB,GACvB,0BAA0B,GAC1B,wBAAwB,GACxB,yBAAyB,GACzB,0BAA0B,GAC1B,yBAAyB,GACzB,yBAAyB,GACzB,yBAAyB,CAAC;AAE9B,MAAM,MAAM,iBAAiB,GAAG,eAAe,GAAG,iBAAiB,CAAC;AAEpE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,4DAA4D;IAC5D,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,yEAAyE;IACzE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,qFAAqF;IACrF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,2EAA2E;AAC3E,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC,CAAC;AAEhF,MAAM,MAAM,iBAAiB,GACzB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAA;CAAE,GAClG;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAA;CAAE,CAAC"}
package/outcome.js ADDED
@@ -0,0 +1,21 @@
1
+ /**
2
+ * The outcome of reading a package and the closed vocabulary of findings.
3
+ *
4
+ * The shape is the server's `ConnectRunOutcome`: a discriminated union on
5
+ * `ok`, with a closed `kind` union behind the failure arm, so a consumer
6
+ * switches on kinds and the compiler closes the switch. An error refuses the
7
+ * package; a warning never does. Both are `PluginFinding`s with the same
8
+ * fields, so one renderer prints both.
9
+ *
10
+ * Two error postures meet here and the header of each module states which
11
+ * applies. Where the open format tells a client to skip a broken component
12
+ * and keep loading, Stigmer refuses the package: an installed agent that
13
+ * quietly lacks a server or a sub-agent is worse than a refused install.
14
+ * But the reader keeps scanning past a fatal finding so one run reports
15
+ * every problem and an author fixes them in one pass.
16
+ *
17
+ * Every kind has exactly one sentence, in `messages.ts`, and the adversarial
18
+ * suite has exactly one fixture per kind. Adding a kind means adding both.
19
+ */
20
+ export {};
21
+ //# sourceMappingURL=outcome.js.map
package/outcome.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outcome.js","sourceRoot":"","sources":["../src/outcome.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG"}