@ai-plugin-marketplace/core 0.1.0

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 (136) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +67 -0
  3. package/dist/config.d.ts +47 -0
  4. package/dist/config.d.ts.map +1 -0
  5. package/dist/config.js +38 -0
  6. package/dist/config.js.map +1 -0
  7. package/dist/core.d.ts +291 -0
  8. package/dist/index.d.ts +15 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js +13 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/pipeline/build.d.ts +90 -0
  13. package/dist/pipeline/build.d.ts.map +1 -0
  14. package/dist/pipeline/build.js +224 -0
  15. package/dist/pipeline/build.js.map +1 -0
  16. package/dist/pipeline/discover.d.ts +37 -0
  17. package/dist/pipeline/discover.d.ts.map +1 -0
  18. package/dist/pipeline/discover.js +71 -0
  19. package/dist/pipeline/discover.js.map +1 -0
  20. package/dist/pipeline/init-template.d.ts +33 -0
  21. package/dist/pipeline/init-template.d.ts.map +1 -0
  22. package/dist/pipeline/init-template.js +142 -0
  23. package/dist/pipeline/init-template.js.map +1 -0
  24. package/dist/pipeline/init.d.ts +39 -0
  25. package/dist/pipeline/init.d.ts.map +1 -0
  26. package/dist/pipeline/init.js +84 -0
  27. package/dist/pipeline/init.js.map +1 -0
  28. package/dist/pipeline/load-config.d.ts +47 -0
  29. package/dist/pipeline/load-config.d.ts.map +1 -0
  30. package/dist/pipeline/load-config.js +106 -0
  31. package/dist/pipeline/load-config.js.map +1 -0
  32. package/dist/pipeline/operations.d.ts +70 -0
  33. package/dist/pipeline/operations.d.ts.map +1 -0
  34. package/dist/pipeline/operations.js +100 -0
  35. package/dist/pipeline/operations.js.map +1 -0
  36. package/dist/pipeline/scaffold.d.ts +105 -0
  37. package/dist/pipeline/scaffold.d.ts.map +1 -0
  38. package/dist/pipeline/scaffold.js +422 -0
  39. package/dist/pipeline/scaffold.js.map +1 -0
  40. package/dist/pipeline/sentinel.d.ts +127 -0
  41. package/dist/pipeline/sentinel.d.ts.map +1 -0
  42. package/dist/pipeline/sentinel.js +263 -0
  43. package/dist/pipeline/sentinel.js.map +1 -0
  44. package/dist/pipeline/types.d.ts +178 -0
  45. package/dist/pipeline/types.d.ts.map +1 -0
  46. package/dist/pipeline/types.js +26 -0
  47. package/dist/pipeline/types.js.map +1 -0
  48. package/dist/pipeline/validate.d.ts +90 -0
  49. package/dist/pipeline/validate.d.ts.map +1 -0
  50. package/dist/pipeline/validate.js +617 -0
  51. package/dist/pipeline/validate.js.map +1 -0
  52. package/dist/targets/claude/scaffold.d.ts +32 -0
  53. package/dist/targets/claude/scaffold.d.ts.map +1 -0
  54. package/dist/targets/claude/scaffold.js +48 -0
  55. package/dist/targets/claude/scaffold.js.map +1 -0
  56. package/dist/targets/claude/schemas.d.ts +119 -0
  57. package/dist/targets/claude/schemas.d.ts.map +1 -0
  58. package/dist/targets/claude/schemas.js +204 -0
  59. package/dist/targets/claude/schemas.js.map +1 -0
  60. package/dist/targets/claude/transform.d.ts +40 -0
  61. package/dist/targets/claude/transform.d.ts.map +1 -0
  62. package/dist/targets/claude/transform.js +48 -0
  63. package/dist/targets/claude/transform.js.map +1 -0
  64. package/dist/targets/claude/validate.d.ts +25 -0
  65. package/dist/targets/claude/validate.d.ts.map +1 -0
  66. package/dist/targets/claude/validate.js +263 -0
  67. package/dist/targets/claude/validate.js.map +1 -0
  68. package/dist/targets/cursor/scaffold.d.ts +29 -0
  69. package/dist/targets/cursor/scaffold.d.ts.map +1 -0
  70. package/dist/targets/cursor/scaffold.js +45 -0
  71. package/dist/targets/cursor/scaffold.js.map +1 -0
  72. package/dist/targets/cursor/schemas.d.ts +49 -0
  73. package/dist/targets/cursor/schemas.d.ts.map +1 -0
  74. package/dist/targets/cursor/schemas.js +125 -0
  75. package/dist/targets/cursor/schemas.js.map +1 -0
  76. package/dist/targets/cursor/validate.d.ts +28 -0
  77. package/dist/targets/cursor/validate.d.ts.map +1 -0
  78. package/dist/targets/cursor/validate.js +181 -0
  79. package/dist/targets/cursor/validate.js.map +1 -0
  80. package/dist/targets/gemini/bundle.d.ts +25 -0
  81. package/dist/targets/gemini/bundle.d.ts.map +1 -0
  82. package/dist/targets/gemini/bundle.js +149 -0
  83. package/dist/targets/gemini/bundle.js.map +1 -0
  84. package/dist/targets/gemini/scaffold.d.ts +28 -0
  85. package/dist/targets/gemini/scaffold.d.ts.map +1 -0
  86. package/dist/targets/gemini/scaffold.js +57 -0
  87. package/dist/targets/gemini/scaffold.js.map +1 -0
  88. package/dist/targets/gemini/schemas.d.ts +53 -0
  89. package/dist/targets/gemini/schemas.d.ts.map +1 -0
  90. package/dist/targets/gemini/schemas.js +72 -0
  91. package/dist/targets/gemini/schemas.js.map +1 -0
  92. package/dist/targets/gemini/transform.d.ts +106 -0
  93. package/dist/targets/gemini/transform.d.ts.map +1 -0
  94. package/dist/targets/gemini/transform.js +137 -0
  95. package/dist/targets/gemini/transform.js.map +1 -0
  96. package/dist/targets/gemini/validate.d.ts +26 -0
  97. package/dist/targets/gemini/validate.d.ts.map +1 -0
  98. package/dist/targets/gemini/validate.js +146 -0
  99. package/dist/targets/gemini/validate.js.map +1 -0
  100. package/dist/targets/kiro/bundle.d.ts +32 -0
  101. package/dist/targets/kiro/bundle.d.ts.map +1 -0
  102. package/dist/targets/kiro/bundle.js +106 -0
  103. package/dist/targets/kiro/bundle.js.map +1 -0
  104. package/dist/targets/kiro/scaffold.d.ts +28 -0
  105. package/dist/targets/kiro/scaffold.d.ts.map +1 -0
  106. package/dist/targets/kiro/scaffold.js +55 -0
  107. package/dist/targets/kiro/scaffold.js.map +1 -0
  108. package/dist/targets/kiro/schemas.d.ts +100 -0
  109. package/dist/targets/kiro/schemas.d.ts.map +1 -0
  110. package/dist/targets/kiro/schemas.js +147 -0
  111. package/dist/targets/kiro/schemas.js.map +1 -0
  112. package/dist/targets/kiro/transform.d.ts +53 -0
  113. package/dist/targets/kiro/transform.d.ts.map +1 -0
  114. package/dist/targets/kiro/transform.js +113 -0
  115. package/dist/targets/kiro/transform.js.map +1 -0
  116. package/dist/targets/kiro/validate.d.ts +36 -0
  117. package/dist/targets/kiro/validate.d.ts.map +1 -0
  118. package/dist/targets/kiro/validate.js +232 -0
  119. package/dist/targets/kiro/validate.js.map +1 -0
  120. package/dist/targets/scaffold-kit.d.ts +56 -0
  121. package/dist/targets/scaffold-kit.d.ts.map +1 -0
  122. package/dist/targets/scaffold-kit.js +33 -0
  123. package/dist/targets/scaffold-kit.js.map +1 -0
  124. package/dist/targets/vercel/scaffold.d.ts +34 -0
  125. package/dist/targets/vercel/scaffold.d.ts.map +1 -0
  126. package/dist/targets/vercel/scaffold.js +58 -0
  127. package/dist/targets/vercel/scaffold.js.map +1 -0
  128. package/dist/targets/vercel/schemas.d.ts +42 -0
  129. package/dist/targets/vercel/schemas.d.ts.map +1 -0
  130. package/dist/targets/vercel/schemas.js +69 -0
  131. package/dist/targets/vercel/schemas.js.map +1 -0
  132. package/dist/targets/vercel/validate.d.ts +28 -0
  133. package/dist/targets/vercel/validate.d.ts.map +1 -0
  134. package/dist/targets/vercel/validate.js +180 -0
  135. package/dist/targets/vercel/validate.js.map +1 -0
  136. package/package.json +50 -0
@@ -0,0 +1,263 @@
1
+ /**
2
+ * Per-target validators for the Claude Code target.
3
+ *
4
+ * These checks go beyond schema shape validation — they verify filesystem facts and
5
+ * cross-file consistency within the Claude target. Schema shape errors are caught by
6
+ * `claudePluginManifestSchema` (Stage 2); the checks here require reading the filesystem.
7
+ *
8
+ * Cross-target concerns (envelope-adherence, name-consistency, mcp-key-sync,
9
+ * marketplace-registration, freshness) are out of scope for this module.
10
+ *
11
+ * @see docs/specs/architecture.md §10 (validation contract), §8.1 (Finding types)
12
+ * @see docs/specs/architecture.md §12.5 (internal module shape)
13
+ */
14
+ import * as fs from 'node:fs';
15
+ import * as path from 'node:path';
16
+ import { parse as parseYaml } from 'yaml';
17
+ import { claudeAgentFrontmatterSchema, claudeHooksFileSchema, claudePluginManifestSchema, } from './schemas.js';
18
+ // ---------------------------------------------------------------------------
19
+ // Internal helpers
20
+ // ---------------------------------------------------------------------------
21
+ /**
22
+ * Build a hard `schema-invalid` Finding scoped to the given plugin.
23
+ */
24
+ function hardFinding(pluginName, message, hint) {
25
+ const finding = {
26
+ severity: 'hard',
27
+ code: 'schema-invalid',
28
+ plugin: pluginName,
29
+ message,
30
+ };
31
+ if (hint !== undefined) {
32
+ finding.hint = hint;
33
+ }
34
+ return finding;
35
+ }
36
+ /**
37
+ * Normalize a manifest field that can be a string path, an array of string paths,
38
+ * or a non-path value (object/undefined). Returns only the string path entries.
39
+ */
40
+ function normalizePathField(value) {
41
+ if (value === undefined)
42
+ return [];
43
+ if (typeof value === 'string')
44
+ return [value];
45
+ if (Array.isArray(value))
46
+ return value.filter((v) => typeof v === 'string');
47
+ // Object value (inline hooks object, record of commands) — no paths to check
48
+ return [];
49
+ }
50
+ // ---------------------------------------------------------------------------
51
+ // Manifest file-ref validation
52
+ // ---------------------------------------------------------------------------
53
+ /**
54
+ * Validate that all file/directory references in `.claude-plugin/plugin.json`
55
+ * resolve to real filesystem entries.
56
+ *
57
+ * Per §10.1: path refs must not contain `..` and must exist on disk.
58
+ * Field-level invariants:
59
+ * - `skills`: the ref must point to a directory
60
+ * - `agents`: the ref must point to a `.md` file
61
+ * - `hooks`: the ref (if a string) must point to a `.json` file
62
+ * - `commands`: the ref can be a file or directory; existence is sufficient
63
+ */
64
+ function validateManifestFileRefs(pluginDir, pluginName) {
65
+ const manifestPath = path.join(pluginDir, '.claude-plugin', 'plugin.json');
66
+ if (!fs.existsSync(manifestPath))
67
+ return [];
68
+ let raw;
69
+ try {
70
+ raw = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
71
+ }
72
+ catch {
73
+ return [
74
+ hardFinding(pluginName, `.claude-plugin/plugin.json is not valid JSON`, `fix the JSON syntax in ${manifestPath}`),
75
+ ];
76
+ }
77
+ const parseResult = claudePluginManifestSchema.safeParse(raw);
78
+ if (!parseResult.success) {
79
+ // Shape errors are reported by the schema validator — skip ref checking
80
+ return [];
81
+ }
82
+ const manifest = parseResult.data;
83
+ const findings = [];
84
+ // skills: directory path(s)
85
+ for (const ref of normalizePathField(manifest.skills)) {
86
+ const finding = checkRef(pluginDir, pluginName, 'skills', ref, 'directory');
87
+ if (finding !== null)
88
+ findings.push(finding);
89
+ }
90
+ // agents: .md file path(s)
91
+ for (const ref of normalizePathField(manifest.agents)) {
92
+ const finding = checkRef(pluginDir, pluginName, 'agents', ref, 'md-file');
93
+ if (finding !== null)
94
+ findings.push(finding);
95
+ }
96
+ // commands: path string(s) — file or directory, just check existence
97
+ for (const ref of normalizePathField(manifest.commands)) {
98
+ const finding = checkRef(pluginDir, pluginName, 'commands', ref, 'any');
99
+ if (finding !== null)
100
+ findings.push(finding);
101
+ }
102
+ // hooks: path string → .json file (inline objects have no path to check)
103
+ if (typeof manifest.hooks === 'string') {
104
+ const finding = checkRef(pluginDir, pluginName, 'hooks', manifest.hooks, 'json-file');
105
+ if (finding !== null)
106
+ findings.push(finding);
107
+ }
108
+ return findings;
109
+ }
110
+ function checkRef(pluginDir, pluginName, field, ref, kind) {
111
+ // Schema already enforces `./` prefix and `.md`/`.json` suffixes, but we
112
+ // re-check gracefully so the validator is robust against schema bypass.
113
+ if (!ref.startsWith('./')) {
114
+ return hardFinding(pluginName, `.claude-plugin/plugin.json ${field} path must start with "./": ${ref}`, `change the path to start with "./"`);
115
+ }
116
+ if (ref.includes('..')) {
117
+ return hardFinding(pluginName, `.claude-plugin/plugin.json ${field} path must not contain "..": ${ref}`, `remove parent-directory traversal segments from the path`);
118
+ }
119
+ const normalized = ref.slice(2); // strip leading "./"
120
+ const resolved = path.join(pluginDir, normalized);
121
+ if (!fs.existsSync(resolved)) {
122
+ const hint = buildMissingHint(pluginName, field, ref);
123
+ return hardFinding(pluginName, `.claude-plugin/plugin.json ${field} references non-existent path: ${ref}`, hint);
124
+ }
125
+ const stat = fs.statSync(resolved);
126
+ if (kind === 'directory' && !stat.isDirectory()) {
127
+ return hardFinding(pluginName, `.claude-plugin/plugin.json ${field} path must be a directory, but is a file: ${ref}`, `create a directory at ${ref} or remove the reference from plugin.json`);
128
+ }
129
+ if (kind === 'md-file') {
130
+ if (!stat.isFile()) {
131
+ return hardFinding(pluginName, `.claude-plugin/plugin.json ${field} path must be a .md file: ${ref}`, `create an agent .md file at ${ref}`);
132
+ }
133
+ if (!ref.endsWith('.md')) {
134
+ return hardFinding(pluginName, `.claude-plugin/plugin.json ${field} path must end with ".md": ${ref}`, `rename the file to end with ".md"`);
135
+ }
136
+ }
137
+ if (kind === 'json-file') {
138
+ if (!stat.isFile()) {
139
+ return hardFinding(pluginName, `.claude-plugin/plugin.json ${field} path must be a .json file: ${ref}`, `create the hooks JSON file at ${ref}`);
140
+ }
141
+ if (!ref.endsWith('.json')) {
142
+ return hardFinding(pluginName, `.claude-plugin/plugin.json ${field} path must end with ".json": ${ref}`, `rename the file to end with ".json"`);
143
+ }
144
+ }
145
+ return null;
146
+ }
147
+ function buildMissingHint(pluginName, field, ref) {
148
+ const relPath = ref.slice(2); // strip "./"
149
+ if (field === 'agents') {
150
+ return `create plugins/${pluginName}/${relPath} or remove the reference from plugin.json`;
151
+ }
152
+ if (field === 'skills') {
153
+ return `create a directory at plugins/${pluginName}/${relPath} or remove the reference from plugin.json`;
154
+ }
155
+ if (field === 'hooks') {
156
+ return `run \`aipm build\` to generate the hooks JSON, or remove the reference from plugin.json`;
157
+ }
158
+ return `create plugins/${pluginName}/${relPath} or remove the reference from plugin.json`;
159
+ }
160
+ // ---------------------------------------------------------------------------
161
+ // Agent frontmatter validation
162
+ // ---------------------------------------------------------------------------
163
+ /**
164
+ * Validate YAML frontmatter of all `.md` files directly under `agents/` (one level deep).
165
+ * Each file must have a frontmatter block and it must satisfy `claudeAgentFrontmatterSchema`.
166
+ */
167
+ function validateAgentFrontmatter(pluginDir, pluginName) {
168
+ const agentsDir = path.join(pluginDir, 'agents');
169
+ if (!fs.existsSync(agentsDir))
170
+ return [];
171
+ const entries = fs.readdirSync(agentsDir, { withFileTypes: true });
172
+ const findings = [];
173
+ for (const entry of entries) {
174
+ if (!entry.isFile() || !entry.name.endsWith('.md'))
175
+ continue;
176
+ const agentPath = path.join(agentsDir, entry.name);
177
+ const relPath = `agents/${entry.name}`;
178
+ const content = fs.readFileSync(agentPath, 'utf-8');
179
+ // Require a frontmatter block: must start with "---\n" and have a closing "---"
180
+ const fmMatch = /^---\r?\n([\s\S]*?)\r?\n---/m.exec(content);
181
+ if (fmMatch === null) {
182
+ findings.push(hardFinding(pluginName, `${relPath}: agent .md has no frontmatter block`, `add a YAML frontmatter block between --- markers at the top of ${relPath}`));
183
+ continue;
184
+ }
185
+ const frontmatterYaml = fmMatch[1] ?? '';
186
+ let parsed;
187
+ try {
188
+ parsed = parseYaml(frontmatterYaml);
189
+ }
190
+ catch (err) {
191
+ const msg = err instanceof Error ? err.message : String(err);
192
+ findings.push(hardFinding(pluginName, `${relPath}: frontmatter YAML parse error: ${msg}`, `fix the YAML syntax in the frontmatter of ${relPath}`));
193
+ continue;
194
+ }
195
+ const result = claudeAgentFrontmatterSchema.safeParse(parsed);
196
+ if (!result.success) {
197
+ const issues = result.error.issues
198
+ .map((i) => `${i.path.join('.') || '(root)'}: ${i.message}`)
199
+ .join('; ');
200
+ findings.push(hardFinding(pluginName, `${relPath}: frontmatter does not match schema — ${issues}`, `ensure ${relPath} frontmatter includes required fields: name, description`));
201
+ }
202
+ }
203
+ return findings;
204
+ }
205
+ // ---------------------------------------------------------------------------
206
+ // Hooks file validation
207
+ // ---------------------------------------------------------------------------
208
+ /**
209
+ * If `hooks/claude.json` exists, validate it parses as JSON and matches
210
+ * `claudeHooksFileSchema`. Missing file → no finding (the file is optional).
211
+ */
212
+ function validateHooksFile(pluginDir, pluginName) {
213
+ const hooksPath = path.join(pluginDir, 'hooks', 'claude.json');
214
+ if (!fs.existsSync(hooksPath))
215
+ return [];
216
+ let raw;
217
+ try {
218
+ raw = JSON.parse(fs.readFileSync(hooksPath, 'utf-8'));
219
+ }
220
+ catch {
221
+ return [
222
+ hardFinding(pluginName, `hooks/claude.json is not valid JSON`, `fix the JSON syntax in hooks/claude.json or regenerate it with \`aipm build\``),
223
+ ];
224
+ }
225
+ // `hooks/claude.json` is a toolkit-generated, JSON-field-sentinel carrier (§4.3): the build
226
+ // writes a top-level `_generated` marker onto it. The hooks schema is `.strict()`, so we drop
227
+ // that toolkit-owned key before schema validation — it is not part of the Claude hooks format.
228
+ if (typeof raw === 'object' && raw !== null && !Array.isArray(raw) && '_generated' in raw) {
229
+ const { _generated: _ignored, ...rest } = raw;
230
+ raw = rest;
231
+ }
232
+ const result = claudeHooksFileSchema.safeParse(raw);
233
+ if (!result.success) {
234
+ const issues = result.error.issues
235
+ .map((i) => `${i.path.join('.') || '(root)'}: ${i.message}`)
236
+ .join('; ');
237
+ return [
238
+ hardFinding(pluginName, `hooks/claude.json does not match the hooks schema — ${issues}`, `check that hooks use only known event names (PreToolUse, PostToolUse, Stop, UserPromptSubmit) and regenerate with \`aipm build\``),
239
+ ];
240
+ }
241
+ return [];
242
+ }
243
+ // ---------------------------------------------------------------------------
244
+ // Public entry point
245
+ // ---------------------------------------------------------------------------
246
+ /**
247
+ * Run all Claude-specific validators against a plugin directory.
248
+ *
249
+ * `pluginDir` is the absolute path to a `plugins/<name>/` directory.
250
+ * Returns zero or more Findings. Callers combine these with other targets'
251
+ * findings and the cross-target findings in the pipeline validator.
252
+ *
253
+ * All findings emitted here use `plugin: path.basename(pluginDir)`.
254
+ */
255
+ export function validateClaudePlugin(pluginDir) {
256
+ const pluginName = path.basename(pluginDir);
257
+ return [
258
+ ...validateManifestFileRefs(pluginDir, pluginName),
259
+ ...validateAgentFrontmatter(pluginDir, pluginName),
260
+ ...validateHooksFile(pluginDir, pluginName),
261
+ ];
262
+ }
263
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/targets/claude/validate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Scaffold templates for the Cursor target.
3
+ *
4
+ * `scaffoldCursorFiles` is a pure function returning the skeleton files this target contributes
5
+ * to a new plugin. Cursor has no mechanical transform in v0.1.0, but it still owns a manifest
6
+ * (`.cursor-plugin/plugin.json`). Every manifest carries `schemaVersion: "0.1.0"` (§12.2). No
7
+ * generated-file sentinels — these are author-authored skeleton files (§4.3).
8
+ *
9
+ * Intentionally duplicated from the Claude scaffold rather than shared: per §3.4 no file in this
10
+ * folder may import from a sibling target folder, and §13 Phase A keeps Cursor/Claude schemas
11
+ * free to diverge later.
12
+ *
13
+ * @see docs/specs/architecture.md §4 (plugin source layout)
14
+ * @see docs/specs/architecture.md §6.4 (compatibility-assist)
15
+ * @see docs/specs/architecture.md §12.2 (schemaVersion on every manifest)
16
+ * @see docs/specs/architecture.md §12.5 (per-target scaffold.ts)
17
+ */
18
+ import { type ScaffoldedFile, type TargetScaffoldOptions } from '../scaffold-kit.js';
19
+ /**
20
+ * Produce the Cursor skeleton files for a plugin.
21
+ *
22
+ * The minimum required artifact (`TARGET_MIN_REQUIRED.cursor`) is `.cursor-plugin/plugin.json`.
23
+ *
24
+ * @param pluginName - Plugin identity; written verbatim as the manifest `name`.
25
+ * @param opts - Optional description and add-target placeholder behaviour.
26
+ * @returns Files contributed by this target, with paths relative to the plugin directory.
27
+ */
28
+ export declare function scaffoldCursorFiles(pluginName: string, opts?: TargetScaffoldOptions): ScaffoldedFile[];
29
+ //# sourceMappingURL=scaffold.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../../src/targets/cursor/scaffold.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC3B,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE,qBAA0B,GAC/B,cAAc,EAAE,CAiBlB"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Scaffold templates for the Cursor target.
3
+ *
4
+ * `scaffoldCursorFiles` is a pure function returning the skeleton files this target contributes
5
+ * to a new plugin. Cursor has no mechanical transform in v0.1.0, but it still owns a manifest
6
+ * (`.cursor-plugin/plugin.json`). Every manifest carries `schemaVersion: "0.1.0"` (§12.2). No
7
+ * generated-file sentinels — these are author-authored skeleton files (§4.3).
8
+ *
9
+ * Intentionally duplicated from the Claude scaffold rather than shared: per §3.4 no file in this
10
+ * folder may import from a sibling target folder, and §13 Phase A keeps Cursor/Claude schemas
11
+ * free to diverge later.
12
+ *
13
+ * @see docs/specs/architecture.md §4 (plugin source layout)
14
+ * @see docs/specs/architecture.md §6.4 (compatibility-assist)
15
+ * @see docs/specs/architecture.md §12.2 (schemaVersion on every manifest)
16
+ * @see docs/specs/architecture.md §12.5 (per-target scaffold.ts)
17
+ */
18
+ import { resolveDescription, SCHEMA_VERSION, } from '../scaffold-kit.js';
19
+ /**
20
+ * Produce the Cursor skeleton files for a plugin.
21
+ *
22
+ * The minimum required artifact (`TARGET_MIN_REQUIRED.cursor`) is `.cursor-plugin/plugin.json`.
23
+ *
24
+ * @param pluginName - Plugin identity; written verbatim as the manifest `name`.
25
+ * @param opts - Optional description and add-target placeholder behaviour.
26
+ * @returns Files contributed by this target, with paths relative to the plugin directory.
27
+ */
28
+ export function scaffoldCursorFiles(pluginName, opts = {}) {
29
+ const description = resolveDescription(pluginName, opts);
30
+ const manifest = {
31
+ schemaVersion: SCHEMA_VERSION,
32
+ name: pluginName,
33
+ version: '0.0.1',
34
+ // `description` is optional and constrained to min length 1; omit it in placeholder mode
35
+ // (add-target) so the skeleton stays schema-valid while leaving the field for the author.
36
+ ...(description !== '' ? { description } : {}),
37
+ };
38
+ return [
39
+ {
40
+ path: '.cursor-plugin/plugin.json',
41
+ content: `${JSON.stringify(manifest, null, 2)}\n`,
42
+ },
43
+ ];
44
+ }
45
+ //# sourceMappingURL=scaffold.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../../src/targets/cursor/scaffold.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EACL,kBAAkB,EAClB,cAAc,GAGf,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CACjC,UAAkB,EAClB,OAA8B,EAAE;IAEhC,MAAM,WAAW,GAAG,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IACzD,MAAM,QAAQ,GAA4B;QACxC,aAAa,EAAE,cAAc;QAC7B,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,OAAO;QAChB,yFAAyF;QACzF,0FAA0F;QAC1F,GAAG,CAAC,WAAW,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC/C,CAAC;IAEF,OAAO;QACL;YACE,IAAI,EAAE,4BAA4B;YAClC,OAAO,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI;SAClD;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Zod schemas for Cursor target manifests.
3
+ *
4
+ * These schemas are intentionally duplicated from the Claude target — per §3.4 of the
5
+ * architecture spec, no file in this folder may import from a sibling target folder.
6
+ * The duplication allows Cursor and Claude schemas to diverge independently in the future.
7
+ *
8
+ * Schema shapes derived from:
9
+ * @see https://github.com/ai-plugin-marketplace/template/blob/main/schemas/plugin.json
10
+ */
11
+ import { z } from 'zod';
12
+ export declare const cursorPluginManifestSchema: z.ZodObject<{
13
+ name: z.ZodString;
14
+ version: z.ZodOptional<z.ZodString>;
15
+ description: z.ZodOptional<z.ZodString>;
16
+ author: z.ZodOptional<z.ZodObject<{
17
+ name: z.ZodString;
18
+ email: z.ZodOptional<z.ZodString>;
19
+ url: z.ZodOptional<z.ZodString>;
20
+ }, z.core.$strict>>;
21
+ homepage: z.ZodOptional<z.ZodURL>;
22
+ repository: z.ZodOptional<z.ZodString>;
23
+ license: z.ZodOptional<z.ZodString>;
24
+ keywords: z.ZodOptional<z.ZodArray<z.ZodString>>;
25
+ hooks: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
26
+ commands: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
27
+ agents: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
28
+ skills: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
29
+ outputStyles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
30
+ mcpServers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
31
+ lspServers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
32
+ settings: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
33
+ schemaVersion: z.ZodOptional<z.ZodString>;
34
+ }, z.core.$strict>;
35
+ export declare const cursorMcpConfigSchema: z.ZodObject<{
36
+ mcpServers: z.ZodRecord<z.ZodString, z.ZodObject<{
37
+ command: z.ZodString;
38
+ args: z.ZodOptional<z.ZodArray<z.ZodString>>;
39
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
40
+ }, z.core.$strict>>;
41
+ schemaVersion: z.ZodOptional<z.ZodString>;
42
+ }, z.core.$strict>;
43
+ export declare const cursorRuleFrontmatterSchema: z.ZodObject<{
44
+ description: z.ZodOptional<z.ZodString>;
45
+ alwaysApply: z.ZodOptional<z.ZodBoolean>;
46
+ globs: z.ZodOptional<z.ZodArray<z.ZodString>>;
47
+ schemaVersion: z.ZodOptional<z.ZodString>;
48
+ }, z.core.$strip>;
49
+ //# sourceMappingURL=schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../../src/targets/cursor/schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAsBxB,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;kBA+D5B,CAAC;AAgBZ,eAAO,MAAM,qBAAqB;;;;;;;kBAKvB,CAAC;AAWZ,eAAO,MAAM,2BAA2B;;;;;iBAKtC,CAAC"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Zod schemas for Cursor target manifests.
3
+ *
4
+ * These schemas are intentionally duplicated from the Claude target — per §3.4 of the
5
+ * architecture spec, no file in this folder may import from a sibling target folder.
6
+ * The duplication allows Cursor and Claude schemas to diverge independently in the future.
7
+ *
8
+ * Schema shapes derived from:
9
+ * @see https://github.com/ai-plugin-marketplace/template/blob/main/schemas/plugin.json
10
+ */
11
+ import { z } from 'zod';
12
+ // ---------------------------------------------------------------------------
13
+ // Sub-object schemas
14
+ // ---------------------------------------------------------------------------
15
+ const cursorPluginAuthorSchema = z
16
+ .object({
17
+ name: z.string(),
18
+ email: z.string().optional(),
19
+ url: z.string().optional(),
20
+ })
21
+ .strict();
22
+ // ---------------------------------------------------------------------------
23
+ // cursorPluginManifestSchema
24
+ //
25
+ // Models .cursor-plugin/plugin.json. Identical field list to Claude's manifest
26
+ // for v0.1.0 (per the current JSON Schema — see §13 Phase A "no schema breaking
27
+ // changes"). Uses .strict() to enforce additionalProperties: false.
28
+ // ---------------------------------------------------------------------------
29
+ export const cursorPluginManifestSchema = z
30
+ .object({
31
+ /** Lowercase, hyphens, no spaces. Pattern: ^[a-z][a-z0-9-]*$ */
32
+ name: z
33
+ .string()
34
+ .regex(/^[a-z][a-z0-9-]*$/)
35
+ .max(64),
36
+ /** Semantic version string, e.g. "0.0.1" */
37
+ version: z
38
+ .string()
39
+ .regex(/^\d+\.\d+\.\d+/)
40
+ .optional(),
41
+ description: z.string().min(1).max(1024).optional(),
42
+ author: cursorPluginAuthorSchema.optional(),
43
+ homepage: z.url().optional(),
44
+ repository: z.string().optional(),
45
+ license: z.string().optional(),
46
+ keywords: z.string().array().optional(),
47
+ /**
48
+ * Hooks — either a relative .json path (starting with "./", ending ".json")
49
+ * or an inline hooks object.
50
+ */
51
+ hooks: z
52
+ .union([z.string().regex(/^\.\/.+\.json$/), z.record(z.string(), z.unknown())])
53
+ .optional(),
54
+ /**
55
+ * Commands — relative path string, array of relative paths, or record of
56
+ * command objects.
57
+ */
58
+ commands: z
59
+ .union([
60
+ z.string().regex(/^\.\//),
61
+ z.string().regex(/^\.\//).array(),
62
+ z.record(z.string(), z.unknown()),
63
+ ])
64
+ .optional(),
65
+ /**
66
+ * Agents — relative .md path or array of relative .md paths.
67
+ */
68
+ agents: z
69
+ .union([
70
+ z.string().regex(/^\.\/.+\.md$/),
71
+ z
72
+ .string()
73
+ .regex(/^\.\/.+\.md$/)
74
+ .array(),
75
+ ])
76
+ .optional(),
77
+ /**
78
+ * Skills — relative directory path or array of relative directory paths.
79
+ * Not SKILL.md file paths — directory paths only.
80
+ */
81
+ skills: z.union([z.string().regex(/^\.\//), z.string().regex(/^\.\//).array()]).optional(),
82
+ outputStyles: z.record(z.string(), z.unknown()).optional(),
83
+ mcpServers: z.record(z.string(), z.unknown()).optional(),
84
+ lspServers: z.record(z.string(), z.unknown()).optional(),
85
+ settings: z.record(z.string(), z.unknown()).optional(),
86
+ /**
87
+ * Reserved for future migration graph. Validators do not check this in
88
+ * v0.1.0 — §9.4. Scaffolds emit "0.1.0".
89
+ */
90
+ schemaVersion: z.string().optional(),
91
+ })
92
+ .strict();
93
+ // ---------------------------------------------------------------------------
94
+ // cursorMcpConfigSchema
95
+ //
96
+ // Models .mcp.json as used by Cursor (today identical to Claude's format).
97
+ // ---------------------------------------------------------------------------
98
+ const cursorMcpServerSchema = z
99
+ .object({
100
+ command: z.string(),
101
+ args: z.string().array().optional(),
102
+ env: z.record(z.string(), z.string()).optional(),
103
+ })
104
+ .strict();
105
+ export const cursorMcpConfigSchema = z
106
+ .object({
107
+ mcpServers: z.record(z.string(), cursorMcpServerSchema),
108
+ schemaVersion: z.string().optional(),
109
+ })
110
+ .strict();
111
+ // ---------------------------------------------------------------------------
112
+ // cursorRuleFrontmatterSchema
113
+ //
114
+ // Models the YAML frontmatter found in Cursor .mdc rule files (e.g.
115
+ // plugins/skill-evaluator/rules/evaluation-protocol.mdc). The observed fields
116
+ // are: description, alwaysApply (boolean), globs (string[]). Additional fields
117
+ // are not strict because .mdc frontmatter is extensible by Cursor tooling.
118
+ // ---------------------------------------------------------------------------
119
+ export const cursorRuleFrontmatterSchema = z.object({
120
+ description: z.string().optional(),
121
+ alwaysApply: z.boolean().optional(),
122
+ globs: z.string().array().optional(),
123
+ schemaVersion: z.string().optional(),
124
+ });
125
+ //# sourceMappingURL=schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../../src/targets/cursor/schemas.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Per-target validator for the Cursor target.
3
+ *
4
+ * Responsibilities (v0.1.0):
5
+ * 1. Manifest file refs resolve — checks that paths in .cursor-plugin/plugin.json
6
+ * exist on disk with the correct type (directory for skills, .md for agents,
7
+ * either for commands). Hooks refs are intentionally excluded: the hooks field
8
+ * typically points at `hooks/claude.json`, which is a Claude-target generated
9
+ * artifact and is not guaranteed to exist in a Cursor-only build context.
10
+ * 2. Cursor rule frontmatter — validates YAML frontmatter in rules/*.mdc files
11
+ * against cursorRuleFrontmatterSchema. Files with no frontmatter block are
12
+ * silently skipped.
13
+ *
14
+ * Cross-target concerns (envelope adherence, name consistency, MCP key sync,
15
+ * marketplace registration, freshness) are NOT checked here.
16
+ *
17
+ * @see packages/core/docs/specs/architecture.md §10 (validation contract)
18
+ * @see packages/core/docs/specs/architecture.md §8.1 (Finding, FindingCode)
19
+ */
20
+ import type { Finding } from '../../pipeline/types.js';
21
+ /**
22
+ * Run all Cursor-specific validators against a plugin directory.
23
+ *
24
+ * `pluginDir` is the absolute path to a `plugins/<name>/` directory.
25
+ * All findings use `plugin: path.basename(pluginDir)`.
26
+ */
27
+ export declare function validateCursorPlugin(pluginDir: string): Finding[];
28
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/targets/cursor/validate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAOH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAsNvD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,EAAE,CAMjE"}