@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.
- package/LICENSE +21 -0
- package/README.md +67 -0
- package/dist/config.d.ts +47 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +38 -0
- package/dist/config.js.map +1 -0
- package/dist/core.d.ts +291 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/pipeline/build.d.ts +90 -0
- package/dist/pipeline/build.d.ts.map +1 -0
- package/dist/pipeline/build.js +224 -0
- package/dist/pipeline/build.js.map +1 -0
- package/dist/pipeline/discover.d.ts +37 -0
- package/dist/pipeline/discover.d.ts.map +1 -0
- package/dist/pipeline/discover.js +71 -0
- package/dist/pipeline/discover.js.map +1 -0
- package/dist/pipeline/init-template.d.ts +33 -0
- package/dist/pipeline/init-template.d.ts.map +1 -0
- package/dist/pipeline/init-template.js +142 -0
- package/dist/pipeline/init-template.js.map +1 -0
- package/dist/pipeline/init.d.ts +39 -0
- package/dist/pipeline/init.d.ts.map +1 -0
- package/dist/pipeline/init.js +84 -0
- package/dist/pipeline/init.js.map +1 -0
- package/dist/pipeline/load-config.d.ts +47 -0
- package/dist/pipeline/load-config.d.ts.map +1 -0
- package/dist/pipeline/load-config.js +106 -0
- package/dist/pipeline/load-config.js.map +1 -0
- package/dist/pipeline/operations.d.ts +70 -0
- package/dist/pipeline/operations.d.ts.map +1 -0
- package/dist/pipeline/operations.js +100 -0
- package/dist/pipeline/operations.js.map +1 -0
- package/dist/pipeline/scaffold.d.ts +105 -0
- package/dist/pipeline/scaffold.d.ts.map +1 -0
- package/dist/pipeline/scaffold.js +422 -0
- package/dist/pipeline/scaffold.js.map +1 -0
- package/dist/pipeline/sentinel.d.ts +127 -0
- package/dist/pipeline/sentinel.d.ts.map +1 -0
- package/dist/pipeline/sentinel.js +263 -0
- package/dist/pipeline/sentinel.js.map +1 -0
- package/dist/pipeline/types.d.ts +178 -0
- package/dist/pipeline/types.d.ts.map +1 -0
- package/dist/pipeline/types.js +26 -0
- package/dist/pipeline/types.js.map +1 -0
- package/dist/pipeline/validate.d.ts +90 -0
- package/dist/pipeline/validate.d.ts.map +1 -0
- package/dist/pipeline/validate.js +617 -0
- package/dist/pipeline/validate.js.map +1 -0
- package/dist/targets/claude/scaffold.d.ts +32 -0
- package/dist/targets/claude/scaffold.d.ts.map +1 -0
- package/dist/targets/claude/scaffold.js +48 -0
- package/dist/targets/claude/scaffold.js.map +1 -0
- package/dist/targets/claude/schemas.d.ts +119 -0
- package/dist/targets/claude/schemas.d.ts.map +1 -0
- package/dist/targets/claude/schemas.js +204 -0
- package/dist/targets/claude/schemas.js.map +1 -0
- package/dist/targets/claude/transform.d.ts +40 -0
- package/dist/targets/claude/transform.d.ts.map +1 -0
- package/dist/targets/claude/transform.js +48 -0
- package/dist/targets/claude/transform.js.map +1 -0
- package/dist/targets/claude/validate.d.ts +25 -0
- package/dist/targets/claude/validate.d.ts.map +1 -0
- package/dist/targets/claude/validate.js +263 -0
- package/dist/targets/claude/validate.js.map +1 -0
- package/dist/targets/cursor/scaffold.d.ts +29 -0
- package/dist/targets/cursor/scaffold.d.ts.map +1 -0
- package/dist/targets/cursor/scaffold.js +45 -0
- package/dist/targets/cursor/scaffold.js.map +1 -0
- package/dist/targets/cursor/schemas.d.ts +49 -0
- package/dist/targets/cursor/schemas.d.ts.map +1 -0
- package/dist/targets/cursor/schemas.js +125 -0
- package/dist/targets/cursor/schemas.js.map +1 -0
- package/dist/targets/cursor/validate.d.ts +28 -0
- package/dist/targets/cursor/validate.d.ts.map +1 -0
- package/dist/targets/cursor/validate.js +181 -0
- package/dist/targets/cursor/validate.js.map +1 -0
- package/dist/targets/gemini/bundle.d.ts +25 -0
- package/dist/targets/gemini/bundle.d.ts.map +1 -0
- package/dist/targets/gemini/bundle.js +149 -0
- package/dist/targets/gemini/bundle.js.map +1 -0
- package/dist/targets/gemini/scaffold.d.ts +28 -0
- package/dist/targets/gemini/scaffold.d.ts.map +1 -0
- package/dist/targets/gemini/scaffold.js +57 -0
- package/dist/targets/gemini/scaffold.js.map +1 -0
- package/dist/targets/gemini/schemas.d.ts +53 -0
- package/dist/targets/gemini/schemas.d.ts.map +1 -0
- package/dist/targets/gemini/schemas.js +72 -0
- package/dist/targets/gemini/schemas.js.map +1 -0
- package/dist/targets/gemini/transform.d.ts +106 -0
- package/dist/targets/gemini/transform.d.ts.map +1 -0
- package/dist/targets/gemini/transform.js +137 -0
- package/dist/targets/gemini/transform.js.map +1 -0
- package/dist/targets/gemini/validate.d.ts +26 -0
- package/dist/targets/gemini/validate.d.ts.map +1 -0
- package/dist/targets/gemini/validate.js +146 -0
- package/dist/targets/gemini/validate.js.map +1 -0
- package/dist/targets/kiro/bundle.d.ts +32 -0
- package/dist/targets/kiro/bundle.d.ts.map +1 -0
- package/dist/targets/kiro/bundle.js +106 -0
- package/dist/targets/kiro/bundle.js.map +1 -0
- package/dist/targets/kiro/scaffold.d.ts +28 -0
- package/dist/targets/kiro/scaffold.d.ts.map +1 -0
- package/dist/targets/kiro/scaffold.js +55 -0
- package/dist/targets/kiro/scaffold.js.map +1 -0
- package/dist/targets/kiro/schemas.d.ts +100 -0
- package/dist/targets/kiro/schemas.d.ts.map +1 -0
- package/dist/targets/kiro/schemas.js +147 -0
- package/dist/targets/kiro/schemas.js.map +1 -0
- package/dist/targets/kiro/transform.d.ts +53 -0
- package/dist/targets/kiro/transform.d.ts.map +1 -0
- package/dist/targets/kiro/transform.js +113 -0
- package/dist/targets/kiro/transform.js.map +1 -0
- package/dist/targets/kiro/validate.d.ts +36 -0
- package/dist/targets/kiro/validate.d.ts.map +1 -0
- package/dist/targets/kiro/validate.js +232 -0
- package/dist/targets/kiro/validate.js.map +1 -0
- package/dist/targets/scaffold-kit.d.ts +56 -0
- package/dist/targets/scaffold-kit.d.ts.map +1 -0
- package/dist/targets/scaffold-kit.js +33 -0
- package/dist/targets/scaffold-kit.js.map +1 -0
- package/dist/targets/vercel/scaffold.d.ts +34 -0
- package/dist/targets/vercel/scaffold.d.ts.map +1 -0
- package/dist/targets/vercel/scaffold.js +58 -0
- package/dist/targets/vercel/scaffold.js.map +1 -0
- package/dist/targets/vercel/schemas.d.ts +42 -0
- package/dist/targets/vercel/schemas.d.ts.map +1 -0
- package/dist/targets/vercel/schemas.js +69 -0
- package/dist/targets/vercel/schemas.js.map +1 -0
- package/dist/targets/vercel/validate.d.ts +28 -0
- package/dist/targets/vercel/validate.d.ts.map +1 -0
- package/dist/targets/vercel/validate.js +180 -0
- package/dist/targets/vercel/validate.js.map +1 -0
- package/package.json +50 -0
|
@@ -0,0 +1,617 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-target validator for the pipeline layer.
|
|
3
|
+
*
|
|
4
|
+
* Implements §10.1 steps 1, 3, 4, and most of 5 (freshness deferred to Stage 5).
|
|
5
|
+
* Step 2 (per-target schema validation) lives in each target's own validate.ts and is
|
|
6
|
+
* not invoked here — this module is concerned only with cross-target consistency.
|
|
7
|
+
*
|
|
8
|
+
* @see docs/specs/architecture.md §6, §8.1, §10.1, §10.2
|
|
9
|
+
*/
|
|
10
|
+
import * as fs from 'node:fs';
|
|
11
|
+
import * as path from 'node:path';
|
|
12
|
+
import { parse as parseYaml } from 'yaml';
|
|
13
|
+
import { z } from 'zod';
|
|
14
|
+
import { defineConfig } from '../config.js';
|
|
15
|
+
import { validateClaudePlugin } from '../targets/claude/validate.js';
|
|
16
|
+
import { validateCursorPlugin } from '../targets/cursor/validate.js';
|
|
17
|
+
import { validateGeminiPlugin } from '../targets/gemini/validate.js';
|
|
18
|
+
import { validateKiroPlugin } from '../targets/kiro/validate.js';
|
|
19
|
+
import { validateVercelPlugin } from '../targets/vercel/validate.js';
|
|
20
|
+
import { collectFilesRelative, computeDistBundles, computePluginHookArtifacts, regenerateBundleToTemp, } from './build.js';
|
|
21
|
+
import { discoverPlugins } from './discover.js';
|
|
22
|
+
import { ConfigLoadError, loadPluginConfig } from './load-config.js';
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Module-level artifact mappings
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
/**
|
|
27
|
+
* Files (relative to pluginDir) that are exclusively owned by a target. If any of these
|
|
28
|
+
* exist on disk for a target NOT in the envelope, that is an adherence violation.
|
|
29
|
+
* Directories are listed without trailing slash; `existsSync` works for either.
|
|
30
|
+
*/
|
|
31
|
+
const TARGET_OWNED_ARTIFACTS = {
|
|
32
|
+
claude: [
|
|
33
|
+
'.claude-plugin/plugin.json',
|
|
34
|
+
'.claude-plugin',
|
|
35
|
+
'hooks/claude.yaml',
|
|
36
|
+
'hooks/claude.json',
|
|
37
|
+
],
|
|
38
|
+
cursor: ['.cursor-plugin/plugin.json', '.cursor-plugin'],
|
|
39
|
+
gemini: ['gemini-extension.json', 'GEMINI.md'],
|
|
40
|
+
kiro: ['POWER.md', 'mcp.json'],
|
|
41
|
+
vercel: [],
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Shared artifacts that require at least one of the listed targets in the envelope.
|
|
45
|
+
* `.mcp.json` is the Claude/Cursor MCP config format, shared between those two targets.
|
|
46
|
+
*/
|
|
47
|
+
const SHARED_ARTIFACTS = [
|
|
48
|
+
{ file: '.mcp.json', anyOf: ['claude', 'cursor'] },
|
|
49
|
+
];
|
|
50
|
+
/**
|
|
51
|
+
* Minimum required artifacts for each target. Missing any of these when the target is
|
|
52
|
+
* in the envelope is an adherence violation.
|
|
53
|
+
* Vercel requires at least one skills/<name>/SKILL.md — handled specially below.
|
|
54
|
+
*/
|
|
55
|
+
export const TARGET_MIN_REQUIRED = {
|
|
56
|
+
claude: ['.claude-plugin/plugin.json'],
|
|
57
|
+
cursor: ['.cursor-plugin/plugin.json'],
|
|
58
|
+
gemini: ['gemini-extension.json'],
|
|
59
|
+
kiro: ['POWER.md'],
|
|
60
|
+
vercel: [],
|
|
61
|
+
};
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
// Internal helpers
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
/** Minimal Zod schema for marketplace.json. Loose to tolerate extra metadata fields. */
|
|
66
|
+
const marketplaceSchema = z
|
|
67
|
+
.object({
|
|
68
|
+
plugins: z.array(z
|
|
69
|
+
.object({
|
|
70
|
+
name: z.string(),
|
|
71
|
+
source: z.string(),
|
|
72
|
+
})
|
|
73
|
+
.loose()),
|
|
74
|
+
})
|
|
75
|
+
.loose();
|
|
76
|
+
/** Minimal schema for MCP config files (.mcp.json / mcp.json). */
|
|
77
|
+
const mcpConfigSchema = z
|
|
78
|
+
.object({
|
|
79
|
+
mcpServers: z.record(z.string(), z.unknown()).optional(),
|
|
80
|
+
})
|
|
81
|
+
.loose();
|
|
82
|
+
/** Read and JSON-parse a file, returning undefined on any error. */
|
|
83
|
+
function tryReadJson(filePath) {
|
|
84
|
+
try {
|
|
85
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Parse YAML frontmatter from a file whose content starts with "---".
|
|
93
|
+
* Returns the frontmatter object (as unknown) or undefined on parse failure.
|
|
94
|
+
*/
|
|
95
|
+
function tryParseFrontmatter(filePath) {
|
|
96
|
+
try {
|
|
97
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
98
|
+
const match = /^---\s*\n([\s\S]*?)\n---/m.exec(content);
|
|
99
|
+
if (!match)
|
|
100
|
+
return undefined;
|
|
101
|
+
return parseYaml(match[1] ?? '');
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/** Build a hard Finding. */
|
|
108
|
+
function hard(code, plugin, message, hint) {
|
|
109
|
+
return { severity: 'hard', code, plugin, message, ...(hint !== undefined ? { hint } : {}) };
|
|
110
|
+
}
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
// validateEnvelopeShape
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
/**
|
|
115
|
+
* Validate an already-loaded `aipm.config.ts` value against AipmConfig's Zod schema.
|
|
116
|
+
* Loading from disk is the pipeline orchestrator's job (Stage 5). Here we only validate shape.
|
|
117
|
+
* Emits `envelope-invalid` findings on malformed input.
|
|
118
|
+
*
|
|
119
|
+
* `pluginName` is used to populate Finding.plugin.
|
|
120
|
+
*/
|
|
121
|
+
export function validateEnvelopeShape(rawConfig, pluginName) {
|
|
122
|
+
try {
|
|
123
|
+
// defineConfig calls aipmConfigSchema.parse() internally — reuses the canonical validator
|
|
124
|
+
// without requiring a separate export of the Zod schema from config.ts.
|
|
125
|
+
defineConfig(rawConfig);
|
|
126
|
+
return [];
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
// ZodError carries .issues[] with path, code, message
|
|
130
|
+
if (err instanceof z.ZodError) {
|
|
131
|
+
return err.issues.map((issue) => {
|
|
132
|
+
const issuePath = issue.path.length > 0 ? issue.path.join('.') : '(root)';
|
|
133
|
+
return hard('envelope-invalid', pluginName, `Invalid aipm.config: [${issuePath}] ${issue.message}`);
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
// Non-ZodError (e.g. JSON parse) — emit a single finding
|
|
137
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
138
|
+
return [hard('envelope-invalid', pluginName, `Invalid aipm.config: ${message}`)];
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// ---------------------------------------------------------------------------
|
|
142
|
+
// validateEnvelopeAdherence
|
|
143
|
+
// ---------------------------------------------------------------------------
|
|
144
|
+
/**
|
|
145
|
+
* For each target in the envelope: verify the plugin provides the minimum required artifacts.
|
|
146
|
+
* For each target NOT in the envelope: verify no target-specific artifacts exist for it.
|
|
147
|
+
*
|
|
148
|
+
* Emits `envelope-adherence` findings.
|
|
149
|
+
*/
|
|
150
|
+
export function validateEnvelopeAdherence(pluginDir, envelope) {
|
|
151
|
+
const findings = [];
|
|
152
|
+
const envelopeSet = new Set(envelope);
|
|
153
|
+
const pluginName = path.basename(pluginDir);
|
|
154
|
+
// Check owned artifacts for targets NOT in the envelope
|
|
155
|
+
for (const [target, artifacts] of Object.entries(TARGET_OWNED_ARTIFACTS)) {
|
|
156
|
+
if (envelopeSet.has(target))
|
|
157
|
+
continue;
|
|
158
|
+
for (const artifact of artifacts) {
|
|
159
|
+
const full = path.join(pluginDir, artifact);
|
|
160
|
+
if (fs.existsSync(full)) {
|
|
161
|
+
findings.push(hard('envelope-adherence', pluginName, `Artifact '${artifact}' exists but target '${target}' is not in the support envelope.`, `Remove '${artifact}' or add '${target}' to the targets array in aipm.config.ts.`));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// Check shared artifacts: must not exist if none of anyOf is in envelope
|
|
166
|
+
for (const { file, anyOf } of SHARED_ARTIFACTS) {
|
|
167
|
+
const full = path.join(pluginDir, file);
|
|
168
|
+
if (fs.existsSync(full) && !anyOf.some((t) => envelopeSet.has(t))) {
|
|
169
|
+
findings.push(hard('envelope-adherence', pluginName, `Artifact '${file}' exists but none of [${anyOf.join(', ')}] is in the support envelope.`, `Remove '${file}' or add at least one of [${anyOf.join(', ')}] to the targets array in aipm.config.ts.`));
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// Check minimum required artifacts for targets IN the envelope
|
|
173
|
+
for (const target of envelope) {
|
|
174
|
+
const required = TARGET_MIN_REQUIRED[target];
|
|
175
|
+
for (const artifact of required) {
|
|
176
|
+
const full = path.join(pluginDir, artifact);
|
|
177
|
+
if (!fs.existsSync(full)) {
|
|
178
|
+
findings.push(hard('envelope-adherence', pluginName, `Target '${target}' is in the support envelope but required artifact '${artifact}' is missing.`, `Create '${artifact}' to satisfy the '${target}' target.`));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// Vercel special case: require at least one skills/*/SKILL.md (one level deep)
|
|
182
|
+
if (target === 'vercel') {
|
|
183
|
+
const skillsDir = path.join(pluginDir, 'skills');
|
|
184
|
+
let hasSkill = false;
|
|
185
|
+
if (fs.existsSync(skillsDir)) {
|
|
186
|
+
try {
|
|
187
|
+
const subdirs = fs.readdirSync(skillsDir, { withFileTypes: true });
|
|
188
|
+
for (const dirent of subdirs) {
|
|
189
|
+
if (dirent.isDirectory()) {
|
|
190
|
+
const skillMd = path.join(skillsDir, dirent.name, 'SKILL.md');
|
|
191
|
+
if (fs.existsSync(skillMd)) {
|
|
192
|
+
hasSkill = true;
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
// Unreadable directory — treat as no skills
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (!hasSkill) {
|
|
203
|
+
findings.push(hard('envelope-adherence', pluginName, `Target 'vercel' is in the support envelope but no 'skills/*/SKILL.md' file was found.`, `Create at least one skill under 'skills/<skill-name>/SKILL.md'.`));
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return findings;
|
|
208
|
+
}
|
|
209
|
+
// ---------------------------------------------------------------------------
|
|
210
|
+
// validateNameConsistency
|
|
211
|
+
// ---------------------------------------------------------------------------
|
|
212
|
+
/**
|
|
213
|
+
* Check that the plugin directory name matches the `name` field in every declared target's
|
|
214
|
+
* manifest. Reads each manifest and parses its `name` field (doesn't re-run the full schema —
|
|
215
|
+
* just extracts name).
|
|
216
|
+
*
|
|
217
|
+
* Emits `name-consistency` findings, one per mismatched manifest.
|
|
218
|
+
*/
|
|
219
|
+
export function validateNameConsistency(pluginDir, envelope) {
|
|
220
|
+
const findings = [];
|
|
221
|
+
const expectedName = path.basename(pluginDir);
|
|
222
|
+
for (const target of envelope) {
|
|
223
|
+
switch (target) {
|
|
224
|
+
case 'claude': {
|
|
225
|
+
const manifestPath = path.join(pluginDir, '.claude-plugin/plugin.json');
|
|
226
|
+
if (!fs.existsSync(manifestPath))
|
|
227
|
+
break;
|
|
228
|
+
const manifest = tryReadJson(manifestPath);
|
|
229
|
+
const parsed = z.object({ name: z.string().optional() }).loose().safeParse(manifest);
|
|
230
|
+
if (!parsed.success || parsed.data.name === undefined)
|
|
231
|
+
break;
|
|
232
|
+
if (parsed.data.name !== expectedName) {
|
|
233
|
+
findings.push(hard('name-consistency', expectedName, `'.claude-plugin/plugin.json' has name '${parsed.data.name}' but plugin directory is '${expectedName}'.`));
|
|
234
|
+
}
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
case 'cursor': {
|
|
238
|
+
const manifestPath = path.join(pluginDir, '.cursor-plugin/plugin.json');
|
|
239
|
+
if (!fs.existsSync(manifestPath))
|
|
240
|
+
break;
|
|
241
|
+
const manifest = tryReadJson(manifestPath);
|
|
242
|
+
const parsed = z.object({ name: z.string().optional() }).loose().safeParse(manifest);
|
|
243
|
+
if (!parsed.success || parsed.data.name === undefined)
|
|
244
|
+
break;
|
|
245
|
+
if (parsed.data.name !== expectedName) {
|
|
246
|
+
findings.push(hard('name-consistency', expectedName, `'.cursor-plugin/plugin.json' has name '${parsed.data.name}' but plugin directory is '${expectedName}'.`));
|
|
247
|
+
}
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
case 'gemini': {
|
|
251
|
+
const manifestPath = path.join(pluginDir, 'gemini-extension.json');
|
|
252
|
+
if (!fs.existsSync(manifestPath))
|
|
253
|
+
break;
|
|
254
|
+
const manifest = tryReadJson(manifestPath);
|
|
255
|
+
const parsed = z.object({ name: z.string() }).loose().safeParse(manifest);
|
|
256
|
+
if (!parsed.success)
|
|
257
|
+
break;
|
|
258
|
+
if (parsed.data.name !== expectedName) {
|
|
259
|
+
findings.push(hard('name-consistency', expectedName, `'gemini-extension.json' has name '${parsed.data.name}' but plugin directory is '${expectedName}'.`));
|
|
260
|
+
}
|
|
261
|
+
break;
|
|
262
|
+
}
|
|
263
|
+
case 'kiro': {
|
|
264
|
+
const powerMdPath = path.join(pluginDir, 'POWER.md');
|
|
265
|
+
if (!fs.existsSync(powerMdPath))
|
|
266
|
+
break;
|
|
267
|
+
const fm = tryParseFrontmatter(powerMdPath);
|
|
268
|
+
const parsed = z.object({ name: z.string() }).loose().safeParse(fm);
|
|
269
|
+
if (!parsed.success)
|
|
270
|
+
break;
|
|
271
|
+
if (parsed.data.name !== expectedName) {
|
|
272
|
+
findings.push(hard('name-consistency', expectedName, `'POWER.md' frontmatter has name '${parsed.data.name}' but plugin directory is '${expectedName}'.`));
|
|
273
|
+
}
|
|
274
|
+
break;
|
|
275
|
+
}
|
|
276
|
+
case 'vercel': {
|
|
277
|
+
// Vercel has no top-level plugin name field — skip
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return findings;
|
|
283
|
+
}
|
|
284
|
+
// ---------------------------------------------------------------------------
|
|
285
|
+
// validateMcpKeySync
|
|
286
|
+
// ---------------------------------------------------------------------------
|
|
287
|
+
/**
|
|
288
|
+
* When both Claude/Cursor (.mcp.json) and Kiro (mcp.json) are in the envelope, the set of
|
|
289
|
+
* mcpServers keys must match between them. Skip the check if fewer than two MCP-consuming
|
|
290
|
+
* targets are in the envelope.
|
|
291
|
+
*
|
|
292
|
+
* Emits `mcp-key-sync` findings.
|
|
293
|
+
*/
|
|
294
|
+
export function validateMcpKeySync(pluginDir, envelope) {
|
|
295
|
+
const pluginName = path.basename(pluginDir);
|
|
296
|
+
const envelopeSet = new Set(envelope);
|
|
297
|
+
const hasClaudeOrCursor = envelopeSet.has('claude') || envelopeSet.has('cursor');
|
|
298
|
+
const hasKiro = envelopeSet.has('kiro');
|
|
299
|
+
// Need at least one of Claude/Cursor AND Kiro to do a cross-target compare
|
|
300
|
+
if (!hasClaudeOrCursor || !hasKiro)
|
|
301
|
+
return [];
|
|
302
|
+
const claudeCursorMcpPath = path.join(pluginDir, '.mcp.json');
|
|
303
|
+
const kiroMcpPath = path.join(pluginDir, 'mcp.json');
|
|
304
|
+
// If either file is missing, skip the sync check (adherence check handles missing files)
|
|
305
|
+
if (!fs.existsSync(claudeCursorMcpPath) || !fs.existsSync(kiroMcpPath))
|
|
306
|
+
return [];
|
|
307
|
+
const claudeCursorRaw = tryReadJson(claudeCursorMcpPath);
|
|
308
|
+
const kiroRaw = tryReadJson(kiroMcpPath);
|
|
309
|
+
const claudeCursorParsed = mcpConfigSchema.safeParse(claudeCursorRaw);
|
|
310
|
+
const kiroParsed = mcpConfigSchema.safeParse(kiroRaw);
|
|
311
|
+
if (!claudeCursorParsed.success || !kiroParsed.success)
|
|
312
|
+
return [];
|
|
313
|
+
const claudeCursorKeys = Object.keys(claudeCursorParsed.data.mcpServers ?? {}).sort();
|
|
314
|
+
const kiroKeys = Object.keys(kiroParsed.data.mcpServers ?? {}).sort();
|
|
315
|
+
if (JSON.stringify(claudeCursorKeys) === JSON.stringify(kiroKeys))
|
|
316
|
+
return [];
|
|
317
|
+
const onlyInClaudeCursor = claudeCursorKeys.filter((k) => !kiroKeys.includes(k));
|
|
318
|
+
const onlyInKiro = kiroKeys.filter((k) => !claudeCursorKeys.includes(k));
|
|
319
|
+
const details = [];
|
|
320
|
+
if (onlyInClaudeCursor.length > 0) {
|
|
321
|
+
details.push(`.mcp.json only: [${onlyInClaudeCursor.join(', ')}]`);
|
|
322
|
+
}
|
|
323
|
+
if (onlyInKiro.length > 0) {
|
|
324
|
+
details.push(`mcp.json only: [${onlyInKiro.join(', ')}]`);
|
|
325
|
+
}
|
|
326
|
+
return [
|
|
327
|
+
hard('mcp-key-sync', pluginName, `mcpServers keys diverge between '.mcp.json' and 'mcp.json'. ${details.join('; ')}.`, `Ensure both files declare the same set of server keys.`),
|
|
328
|
+
];
|
|
329
|
+
}
|
|
330
|
+
// ---------------------------------------------------------------------------
|
|
331
|
+
// validateMarketplaceRegistration
|
|
332
|
+
// ---------------------------------------------------------------------------
|
|
333
|
+
/**
|
|
334
|
+
* Verify the plugin is listed in the appropriate template-level marketplace.json files.
|
|
335
|
+
*
|
|
336
|
+
* - If `claude` is in the envelope, the plugin MUST appear in `<repoRoot>/.claude-plugin/marketplace.json`'s
|
|
337
|
+
* plugins array with name matching directory basename and source pointing at `./plugins/<name>`.
|
|
338
|
+
* - If `cursor` is in the envelope, same check against `<repoRoot>/.cursor-plugin/marketplace.json`.
|
|
339
|
+
* - If a target is NOT in the envelope, the plugin MUST NOT be listed in that marketplace.
|
|
340
|
+
*
|
|
341
|
+
* Emits `marketplace-registration` findings.
|
|
342
|
+
*/
|
|
343
|
+
export function validateMarketplaceRegistration(pluginDir, repoRoot, envelope) {
|
|
344
|
+
const findings = [];
|
|
345
|
+
const pluginName = path.basename(pluginDir);
|
|
346
|
+
const envelopeSet = new Set(envelope);
|
|
347
|
+
const checks = [
|
|
348
|
+
{
|
|
349
|
+
target: 'claude',
|
|
350
|
+
marketplacePath: path.join(repoRoot, '.claude-plugin', 'marketplace.json'),
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
target: 'cursor',
|
|
354
|
+
marketplacePath: path.join(repoRoot, '.cursor-plugin', 'marketplace.json'),
|
|
355
|
+
},
|
|
356
|
+
];
|
|
357
|
+
for (const { target, marketplacePath } of checks) {
|
|
358
|
+
const inEnvelope = envelopeSet.has(target);
|
|
359
|
+
if (!fs.existsSync(marketplacePath)) {
|
|
360
|
+
if (inEnvelope) {
|
|
361
|
+
findings.push(hard('marketplace-registration', pluginName, `Target '${target}' is in the support envelope but marketplace file '${marketplacePath}' does not exist.`, `Create the marketplace.json file at '${marketplacePath}'.`));
|
|
362
|
+
}
|
|
363
|
+
// If not in envelope and no marketplace file, nothing to check
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
const raw = tryReadJson(marketplacePath);
|
|
367
|
+
const parsed = marketplaceSchema.safeParse(raw);
|
|
368
|
+
if (!parsed.success) {
|
|
369
|
+
if (inEnvelope) {
|
|
370
|
+
findings.push(hard('marketplace-registration', pluginName, `Failed to parse marketplace file '${marketplacePath}'.`));
|
|
371
|
+
}
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
const { plugins } = parsed.data;
|
|
375
|
+
// Normalize: both `./plugins/<name>` and `plugins/<name>` are accepted
|
|
376
|
+
// The canonical expected form is `./plugins/<name>` per §4.4
|
|
377
|
+
const expectedSource = `./plugins/${pluginName}`;
|
|
378
|
+
const normalizedExpected = `plugins/${pluginName}`;
|
|
379
|
+
const matchingEntry = plugins.find((p) => p.name === pluginName);
|
|
380
|
+
if (inEnvelope) {
|
|
381
|
+
if (!matchingEntry) {
|
|
382
|
+
findings.push(hard('marketplace-registration', pluginName, `Plugin '${pluginName}' is not listed in '${marketplacePath}'.`, `Add an entry with name '${pluginName}' and source '${expectedSource}' to the plugins array.`));
|
|
383
|
+
}
|
|
384
|
+
else {
|
|
385
|
+
// Entry exists — verify source
|
|
386
|
+
const normalizedActual = matchingEntry.source.startsWith('./')
|
|
387
|
+
? matchingEntry.source.slice(2)
|
|
388
|
+
: matchingEntry.source;
|
|
389
|
+
if (normalizedActual !== normalizedExpected) {
|
|
390
|
+
findings.push(hard('marketplace-registration', pluginName, `Plugin '${pluginName}' in '${marketplacePath}' has source '${matchingEntry.source}' but expected '${expectedSource}'.`, `Update the source to '${expectedSource}'.`));
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
// NOT in envelope — must not appear in marketplace
|
|
396
|
+
if (matchingEntry) {
|
|
397
|
+
findings.push(hard('marketplace-registration', pluginName, `Plugin '${pluginName}' appears in '${marketplacePath}' but target '${target}' is not in the support envelope.`, `Remove '${pluginName}' from the marketplace or add '${target}' to the targets array in aipm.config.ts.`));
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
return findings;
|
|
402
|
+
}
|
|
403
|
+
// ---------------------------------------------------------------------------
|
|
404
|
+
// validateCrossTarget
|
|
405
|
+
// ---------------------------------------------------------------------------
|
|
406
|
+
/**
|
|
407
|
+
* Convenience: run all cross-target validators for a single plugin and combine findings.
|
|
408
|
+
* Stage 5's pipeline operations.ts uses this.
|
|
409
|
+
*
|
|
410
|
+
* Note: validateEnvelopeShape is excluded here because the caller must already have a
|
|
411
|
+
* parsed envelope (TargetId[]) — meaning shape validation already passed. Shape validation
|
|
412
|
+
* must be done separately before calling this function.
|
|
413
|
+
*/
|
|
414
|
+
export function validateCrossTarget(pluginDir, repoRoot, envelope) {
|
|
415
|
+
return [
|
|
416
|
+
...validateEnvelopeAdherence(pluginDir, envelope),
|
|
417
|
+
...validateNameConsistency(pluginDir, envelope),
|
|
418
|
+
...validateMcpKeySync(pluginDir, envelope),
|
|
419
|
+
...validateMarketplaceRegistration(pluginDir, repoRoot, envelope),
|
|
420
|
+
];
|
|
421
|
+
}
|
|
422
|
+
// ---------------------------------------------------------------------------
|
|
423
|
+
// Per-target schema validation dispatch (§10.1 step 2)
|
|
424
|
+
// ---------------------------------------------------------------------------
|
|
425
|
+
/**
|
|
426
|
+
* Per-target schema/filesystem validators, keyed by target ID. Each runs the corresponding
|
|
427
|
+
* target's `validate.ts` entry point and returns its findings (mostly `schema-invalid`). The
|
|
428
|
+
* orchestrator dispatches only for targets in the envelope.
|
|
429
|
+
*/
|
|
430
|
+
const TARGET_VALIDATORS = {
|
|
431
|
+
claude: validateClaudePlugin,
|
|
432
|
+
cursor: validateCursorPlugin,
|
|
433
|
+
gemini: validateGeminiPlugin,
|
|
434
|
+
kiro: validateKiroPlugin,
|
|
435
|
+
vercel: validateVercelPlugin,
|
|
436
|
+
};
|
|
437
|
+
/**
|
|
438
|
+
* Run per-target schema validation for every target in the envelope (§10.1 step 2). Each
|
|
439
|
+
* declared target's `validate.ts` validator is invoked; absent targets are skipped.
|
|
440
|
+
*/
|
|
441
|
+
function validatePerTargetSchemas(pluginDir, envelope) {
|
|
442
|
+
const findings = [];
|
|
443
|
+
for (const target of envelope) {
|
|
444
|
+
findings.push(...TARGET_VALIDATORS[target](pluginDir));
|
|
445
|
+
}
|
|
446
|
+
return findings;
|
|
447
|
+
}
|
|
448
|
+
// ---------------------------------------------------------------------------
|
|
449
|
+
// Freshness check (§10.5)
|
|
450
|
+
// ---------------------------------------------------------------------------
|
|
451
|
+
/**
|
|
452
|
+
* Build a `freshness` Finding. Severity is `hard` in CI (a stale tree must fail the build) and
|
|
453
|
+
* `soft` locally (a warning the author can act on), per §10.2.
|
|
454
|
+
*/
|
|
455
|
+
function freshnessFinding(ci, pluginName, message, hint) {
|
|
456
|
+
return {
|
|
457
|
+
severity: ci ? 'hard' : 'soft',
|
|
458
|
+
code: 'freshness',
|
|
459
|
+
plugin: pluginName,
|
|
460
|
+
message,
|
|
461
|
+
...(hint !== undefined ? { hint } : {}),
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Freshness check for one plugin (§10.5). A generated file is stale when re-running `aipm build`
|
|
466
|
+
* would change it. Two carriers:
|
|
467
|
+
*
|
|
468
|
+
* 1. **In-plugin hook JSONs** (`hooks/claude.json`, `hooks/hooks.json`) — recompute the expected
|
|
469
|
+
* bytes (transform + `_generated` sentinel) and compare to disk. A missing file, an absent or
|
|
470
|
+
* altered sentinel, or any byte difference (e.g. a hand-edit) is stale.
|
|
471
|
+
* 2. **`dist/**` bundle trees** — regenerate into a temp dir and byte-compare the whole tree
|
|
472
|
+
* (file set + contents). Any divergence names the offending path.
|
|
473
|
+
*
|
|
474
|
+
* Generation logic is shared with `runBuild` via `computePluginHookArtifacts` / `computeDistBundles`
|
|
475
|
+
* so build output and the freshness oracle cannot drift.
|
|
476
|
+
*/
|
|
477
|
+
function checkFreshness(pluginDir, distDir, envelope, ci) {
|
|
478
|
+
const findings = [];
|
|
479
|
+
const pluginName = path.basename(pluginDir);
|
|
480
|
+
// ── In-plugin hook JSONs ──────────────────────────────────────────────────
|
|
481
|
+
let hookArtifacts;
|
|
482
|
+
try {
|
|
483
|
+
hookArtifacts = computePluginHookArtifacts(pluginDir, envelope);
|
|
484
|
+
}
|
|
485
|
+
catch (err) {
|
|
486
|
+
// A malformed hooks source means the transform can't run — surface as freshness drift.
|
|
487
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
488
|
+
return [
|
|
489
|
+
freshnessFinding(ci, pluginName, `Unable to compute expected hook output: ${message}`, `fix the hooks source and run \`aipm build\`.`),
|
|
490
|
+
];
|
|
491
|
+
}
|
|
492
|
+
for (const artifact of hookArtifacts) {
|
|
493
|
+
const rel = path.relative(pluginDir, artifact.absPath);
|
|
494
|
+
if (!fs.existsSync(artifact.absPath)) {
|
|
495
|
+
findings.push(freshnessFinding(ci, pluginName, `Generated file '${rel}' is missing.`, `run \`aipm build\` to generate it.`));
|
|
496
|
+
continue;
|
|
497
|
+
}
|
|
498
|
+
const onDisk = fs.readFileSync(artifact.absPath, 'utf-8');
|
|
499
|
+
if (onDisk !== artifact.expectedContent) {
|
|
500
|
+
findings.push(freshnessFinding(ci, pluginName, `Generated file '${rel}' is stale — it differs from what \`aipm build\` would produce (hand-edited or out of date).`, `run \`aipm build\` to regenerate it; edit the source '${artifact.source}', not the generated file.`));
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
// ── dist/** bundle trees (byte-parity via regeneration) ───────────────────
|
|
504
|
+
for (const bundle of computeDistBundles(pluginDir, distDir, envelope)) {
|
|
505
|
+
let tempDir;
|
|
506
|
+
try {
|
|
507
|
+
tempDir = regenerateBundleToTemp(bundle);
|
|
508
|
+
const drift = compareTrees(bundle.destDir, tempDir);
|
|
509
|
+
for (const rel of drift) {
|
|
510
|
+
const distRel = path.relative(distDir, path.join(bundle.destDir, rel));
|
|
511
|
+
findings.push(freshnessFinding(ci, pluginName, `Generated bundle file 'dist/${distRel}' is stale — it differs from what \`aipm build\` would produce.`, `run \`aipm build\` to regenerate the ${bundle.target} bundle.`));
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
finally {
|
|
515
|
+
if (tempDir !== undefined && fs.existsSync(tempDir)) {
|
|
516
|
+
fs.rmSync(tempDir, { recursive: true });
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
return findings;
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Compare two directory trees and return the relative paths that differ (present in only one
|
|
524
|
+
* side, or present in both with differing bytes). An empty result means the trees are identical.
|
|
525
|
+
*/
|
|
526
|
+
function compareTrees(actualDir, expectedDir) {
|
|
527
|
+
const actual = new Set(collectFilesRelative(actualDir));
|
|
528
|
+
const expected = new Set(collectFilesRelative(expectedDir));
|
|
529
|
+
const drift = new Set();
|
|
530
|
+
for (const rel of actual) {
|
|
531
|
+
if (!expected.has(rel)) {
|
|
532
|
+
drift.add(rel);
|
|
533
|
+
continue;
|
|
534
|
+
}
|
|
535
|
+
const a = fs.readFileSync(path.join(actualDir, rel));
|
|
536
|
+
const b = fs.readFileSync(path.join(expectedDir, rel));
|
|
537
|
+
if (!a.equals(b))
|
|
538
|
+
drift.add(rel);
|
|
539
|
+
}
|
|
540
|
+
for (const rel of expected) {
|
|
541
|
+
if (!actual.has(rel))
|
|
542
|
+
drift.add(rel);
|
|
543
|
+
}
|
|
544
|
+
return [...drift].sort();
|
|
545
|
+
}
|
|
546
|
+
// ---------------------------------------------------------------------------
|
|
547
|
+
// runValidate — the validate orchestrator (§5.3, §10.1, §10.3)
|
|
548
|
+
// ---------------------------------------------------------------------------
|
|
549
|
+
/**
|
|
550
|
+
* Validate one plugin or every plugin under a repo root (§5.3). Runs the validators in the order
|
|
551
|
+
* mandated by §10.1 / §10.3:
|
|
552
|
+
*
|
|
553
|
+
* 1. Envelope load + shape validation. A load/shape failure emits `envelope-invalid` and
|
|
554
|
+
* **skips all further checks for that plugin** (no point validating an undeclared target).
|
|
555
|
+
* 2. Per-target schema validation (each declared target's `validate.ts`). Schema errors
|
|
556
|
+
* **block cross-target checks** for that plugin (§10.3).
|
|
557
|
+
* 3. Envelope adherence.
|
|
558
|
+
* 4. Cross-target consistency (only when the envelope has more than one target and no blocking
|
|
559
|
+
* schema errors): name consistency, MCP key sync, marketplace registration.
|
|
560
|
+
* 5. Freshness (unless `opts.skipFreshness`). Severity is `hard` in CI, `soft` locally (§10.2).
|
|
561
|
+
*
|
|
562
|
+
* `passed` is `true` iff no **hard** findings were emitted (§10.2).
|
|
563
|
+
*
|
|
564
|
+
* @param targetPath - Absolute path to a single plugin directory or a repo root.
|
|
565
|
+
* @param opts - Validate options. `ci` controls freshness severity (default: local/soft).
|
|
566
|
+
* @returns The combined validation result.
|
|
567
|
+
*/
|
|
568
|
+
export async function runValidate(targetPath, opts) {
|
|
569
|
+
const ci = opts?.ci ?? false;
|
|
570
|
+
const skipFreshness = opts?.skipFreshness ?? false;
|
|
571
|
+
const { repoRoot, distDir, pluginDirs } = discoverPlugins(targetPath);
|
|
572
|
+
const findings = [];
|
|
573
|
+
for (const pluginDir of pluginDirs) {
|
|
574
|
+
const pluginName = path.basename(pluginDir);
|
|
575
|
+
// ── 1. Envelope load + shape validation ─────────────────────────────────
|
|
576
|
+
let envelope;
|
|
577
|
+
try {
|
|
578
|
+
const config = await loadPluginConfig(pluginDir);
|
|
579
|
+
envelope = config.targets;
|
|
580
|
+
}
|
|
581
|
+
catch (err) {
|
|
582
|
+
// Distinguish "no/invalid config" (envelope-invalid) from unexpected errors. Either way,
|
|
583
|
+
// the envelope is unusable, so we skip every downstream check for this plugin.
|
|
584
|
+
const message = err instanceof ConfigLoadError
|
|
585
|
+
? err.message
|
|
586
|
+
: err instanceof Error
|
|
587
|
+
? err.message
|
|
588
|
+
: String(err);
|
|
589
|
+
findings.push({
|
|
590
|
+
severity: 'hard',
|
|
591
|
+
code: 'envelope-invalid',
|
|
592
|
+
plugin: pluginName,
|
|
593
|
+
message,
|
|
594
|
+
});
|
|
595
|
+
continue;
|
|
596
|
+
}
|
|
597
|
+
// ── 2. Per-target schema validation ─────────────────────────────────────
|
|
598
|
+
const schemaFindings = validatePerTargetSchemas(pluginDir, envelope);
|
|
599
|
+
findings.push(...schemaFindings);
|
|
600
|
+
const hasBlockingSchemaError = schemaFindings.some((f) => f.severity === 'hard');
|
|
601
|
+
// ── 3. Envelope adherence ───────────────────────────────────────────────
|
|
602
|
+
findings.push(...validateEnvelopeAdherence(pluginDir, envelope));
|
|
603
|
+
// ── 4. Cross-target consistency (§10.1 step 4: multi-target only; §10.3: schema blocks) ──
|
|
604
|
+
if (envelope.length > 1 && !hasBlockingSchemaError) {
|
|
605
|
+
findings.push(...validateNameConsistency(pluginDir, envelope));
|
|
606
|
+
findings.push(...validateMcpKeySync(pluginDir, envelope));
|
|
607
|
+
findings.push(...validateMarketplaceRegistration(pluginDir, repoRoot, envelope));
|
|
608
|
+
}
|
|
609
|
+
// ── 5. Freshness ─────────────────────────────────────────────────────────
|
|
610
|
+
if (!skipFreshness) {
|
|
611
|
+
findings.push(...checkFreshness(pluginDir, distDir, envelope, ci));
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
const passed = !findings.some((f) => f.severity === 'hard');
|
|
615
|
+
return { findings, passed };
|
|
616
|
+
}
|
|
617
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/pipeline/validate.ts"],"names":[],"mappings":"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"}
|