@orchid-labs/pluxx 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +100 -522
- package/dist/cli/agent.d.ts +7 -0
- package/dist/cli/agent.d.ts.map +1 -1
- package/dist/cli/doctor.d.ts +1 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/eval.d.ts +22 -0
- package/dist/cli/eval.d.ts.map +1 -0
- package/dist/cli/index.d.ts +19 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/init-from-mcp.d.ts +17 -2
- package/dist/cli/init-from-mcp.d.ts.map +1 -1
- package/dist/cli/install.d.ts +2 -0
- package/dist/cli/install.d.ts.map +1 -1
- package/dist/cli/lint.d.ts +5 -1
- package/dist/cli/lint.d.ts.map +1 -1
- package/dist/cli/mcp-proxy.d.ts +10 -0
- package/dist/cli/mcp-proxy.d.ts.map +1 -0
- package/dist/cli/migrate.d.ts.map +1 -1
- package/dist/cli/sync-from-mcp.d.ts.map +1 -1
- package/dist/cli/test.d.ts +2 -0
- package/dist/cli/test.d.ts.map +1 -1
- package/dist/generators/claude-code/index.d.ts +2 -0
- package/dist/generators/claude-code/index.d.ts.map +1 -1
- package/dist/generators/codex/index.d.ts +1 -0
- package/dist/generators/codex/index.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +99 -1
- package/dist/mcp/introspect.d.ts +43 -1
- package/dist/mcp/introspect.d.ts.map +1 -1
- package/dist/permissions.d.ts.map +1 -1
- package/dist/validation/platform-rules.d.ts +20 -0
- package/dist/validation/platform-rules.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/cli/agent.ts +459 -34
- package/src/cli/doctor.ts +400 -1
- package/src/cli/eval.ts +470 -0
- package/src/cli/index.ts +633 -114
- package/src/cli/init-from-mcp.ts +545 -41
- package/src/cli/install.ts +166 -4
- package/src/cli/lint.ts +56 -26
- package/src/cli/mcp-proxy.ts +322 -0
- package/src/cli/migrate.ts +256 -3
- package/src/cli/sync-from-mcp.ts +23 -0
- package/src/cli/test.ts +10 -2
- package/src/generators/claude-code/index.ts +143 -0
- package/src/generators/codex/index.ts +23 -0
- package/src/index.ts +12 -1
- package/src/mcp/introspect.ts +297 -24
- package/src/permissions.ts +3 -1
- package/src/validation/platform-rules.ts +121 -0
package/src/cli/install.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { resolve, basename } from 'path'
|
|
1
|
+
import { resolve, basename, dirname } from 'path'
|
|
2
2
|
import { existsSync, symlinkSync, mkdirSync, rmSync, readFileSync, writeFileSync, cpSync } from 'fs'
|
|
3
3
|
import { spawnSync } from 'child_process'
|
|
4
4
|
import * as readline from 'readline'
|
|
@@ -30,6 +30,25 @@ interface CommandResult {
|
|
|
30
30
|
stderr: string
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
interface CodexMarketplaceFile {
|
|
34
|
+
name?: string
|
|
35
|
+
interface?: {
|
|
36
|
+
displayName?: string
|
|
37
|
+
}
|
|
38
|
+
plugins?: Array<{
|
|
39
|
+
name: string
|
|
40
|
+
source?: {
|
|
41
|
+
source?: string
|
|
42
|
+
path?: string
|
|
43
|
+
}
|
|
44
|
+
policy?: {
|
|
45
|
+
installation?: string
|
|
46
|
+
authentication?: string
|
|
47
|
+
}
|
|
48
|
+
category?: string
|
|
49
|
+
}>
|
|
50
|
+
}
|
|
51
|
+
|
|
33
52
|
type CommandRunner = (command: string, args: string[]) => CommandResult
|
|
34
53
|
|
|
35
54
|
export interface HookCommand {
|
|
@@ -244,8 +263,8 @@ function getInstallTargets(pluginName: string): InstallTarget[] {
|
|
|
244
263
|
},
|
|
245
264
|
{
|
|
246
265
|
platform: 'codex',
|
|
247
|
-
pluginDir: resolve(home, 'plugins', pluginName),
|
|
248
|
-
description:
|
|
266
|
+
pluginDir: resolve(home, '.codex/plugins', pluginName),
|
|
267
|
+
description: `~/.codex/plugins/${pluginName} (via ~/.agents/plugins/marketplace.json)`,
|
|
249
268
|
},
|
|
250
269
|
{
|
|
251
270
|
platform: 'opencode',
|
|
@@ -290,6 +309,16 @@ function getInstallTargets(pluginName: string): InstallTarget[] {
|
|
|
290
309
|
]
|
|
291
310
|
}
|
|
292
311
|
|
|
312
|
+
export function getInstallFollowupNotes(platforms: TargetPlatform[]): string[] {
|
|
313
|
+
const notes: string[] = []
|
|
314
|
+
|
|
315
|
+
if (platforms.includes('claude-code')) {
|
|
316
|
+
notes.push('Claude Code note: if Claude is already open, run /reload-plugins in the session to pick up the new install.')
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
return notes
|
|
320
|
+
}
|
|
321
|
+
|
|
293
322
|
function runCommandDefault(command: string, args: string[]): CommandResult {
|
|
294
323
|
const result = spawnSync(command, args, { encoding: 'utf-8' })
|
|
295
324
|
return {
|
|
@@ -310,6 +339,90 @@ function createSymlinkInstall(target: PlannedInstallTarget): void {
|
|
|
310
339
|
symlinkSync(target.sourceDir, target.pluginDir)
|
|
311
340
|
}
|
|
312
341
|
|
|
342
|
+
function getCodexMarketplacePath(): string {
|
|
343
|
+
const home = process.env.HOME ?? '~'
|
|
344
|
+
return resolve(home, '.agents/plugins/marketplace.json')
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
function getCodexMarketplacePluginPath(pluginName: string): string {
|
|
348
|
+
return `./.codex/plugins/${pluginName}`
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
function readCodexMarketplace(filepath: string): CodexMarketplaceFile {
|
|
352
|
+
if (!existsSync(filepath)) {
|
|
353
|
+
return {
|
|
354
|
+
name: 'pluxx-local',
|
|
355
|
+
interface: {
|
|
356
|
+
displayName: 'Pluxx Local',
|
|
357
|
+
},
|
|
358
|
+
plugins: [],
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
const raw = readFileSync(filepath, 'utf-8')
|
|
363
|
+
const parsed = JSON.parse(raw) as CodexMarketplaceFile
|
|
364
|
+
return {
|
|
365
|
+
name: parsed.name ?? 'pluxx-local',
|
|
366
|
+
interface: parsed.interface ?? { displayName: 'Pluxx Local' },
|
|
367
|
+
plugins: Array.isArray(parsed.plugins) ? parsed.plugins : [],
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
function ensureCodexMarketplace(pluginName: string): void {
|
|
372
|
+
const filepath = getCodexMarketplacePath()
|
|
373
|
+
mkdirSync(dirname(filepath), { recursive: true })
|
|
374
|
+
|
|
375
|
+
const marketplace = readCodexMarketplace(filepath)
|
|
376
|
+
const nextPlugins = (marketplace.plugins ?? []).filter((plugin) => plugin.name !== pluginName)
|
|
377
|
+
nextPlugins.push({
|
|
378
|
+
name: pluginName,
|
|
379
|
+
source: {
|
|
380
|
+
source: 'local',
|
|
381
|
+
path: getCodexMarketplacePluginPath(pluginName),
|
|
382
|
+
},
|
|
383
|
+
policy: {
|
|
384
|
+
installation: 'AVAILABLE',
|
|
385
|
+
authentication: 'ON_INSTALL',
|
|
386
|
+
},
|
|
387
|
+
category: 'Productivity',
|
|
388
|
+
})
|
|
389
|
+
|
|
390
|
+
writeFileSync(
|
|
391
|
+
filepath,
|
|
392
|
+
JSON.stringify({
|
|
393
|
+
name: marketplace.name ?? 'pluxx-local',
|
|
394
|
+
interface: marketplace.interface ?? { displayName: 'Pluxx Local' },
|
|
395
|
+
plugins: nextPlugins,
|
|
396
|
+
}, null, 2) + '\n',
|
|
397
|
+
)
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
function removeCodexMarketplacePlugin(pluginName: string): void {
|
|
401
|
+
const filepath = getCodexMarketplacePath()
|
|
402
|
+
if (!existsSync(filepath)) return
|
|
403
|
+
|
|
404
|
+
const marketplace = readCodexMarketplace(filepath)
|
|
405
|
+
const nextPlugins = (marketplace.plugins ?? []).filter((plugin) => plugin.name !== pluginName)
|
|
406
|
+
|
|
407
|
+
if (nextPlugins.length === (marketplace.plugins ?? []).length) {
|
|
408
|
+
return
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
if (nextPlugins.length === 0) {
|
|
412
|
+
rmSync(filepath, { force: true })
|
|
413
|
+
return
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
writeFileSync(
|
|
417
|
+
filepath,
|
|
418
|
+
JSON.stringify({
|
|
419
|
+
name: marketplace.name ?? 'pluxx-local',
|
|
420
|
+
interface: marketplace.interface ?? { displayName: 'Pluxx Local' },
|
|
421
|
+
plugins: nextPlugins,
|
|
422
|
+
}, null, 2) + '\n',
|
|
423
|
+
)
|
|
424
|
+
}
|
|
425
|
+
|
|
313
426
|
function createCopiedInstall(target: PlannedInstallTarget): void {
|
|
314
427
|
const parentDir = resolve(target.pluginDir, '..')
|
|
315
428
|
mkdirSync(parentDir, { recursive: true })
|
|
@@ -585,6 +698,34 @@ function installClaudePlugin(
|
|
|
585
698
|
}
|
|
586
699
|
}
|
|
587
700
|
|
|
701
|
+
function uninstallClaudePlugin(
|
|
702
|
+
target: InstallTarget,
|
|
703
|
+
pluginName: string,
|
|
704
|
+
runCommand: CommandRunner,
|
|
705
|
+
options: { quiet?: boolean } = {},
|
|
706
|
+
): boolean {
|
|
707
|
+
const marketplaceName = getClaudeMarketplaceName(pluginName)
|
|
708
|
+
const uninstall = runCommand('claude', ['plugin', 'uninstall', `${pluginName}@${marketplaceName}`])
|
|
709
|
+
|
|
710
|
+
if (uninstall.status !== 0 && !options.quiet) {
|
|
711
|
+
const detail = uninstall.stderr || uninstall.stdout
|
|
712
|
+
if (detail.trim().length > 0) {
|
|
713
|
+
console.warn(` warning claude-code uninstall: ${detail.trim()}`)
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
const marketplaceRoot = getClaudeMarketplaceRoot(pluginName)
|
|
718
|
+
const hadMarketplaceRoot = existsSync(marketplaceRoot)
|
|
719
|
+
rmSync(marketplaceRoot, { recursive: true, force: true })
|
|
720
|
+
|
|
721
|
+
const hadLegacyPluginDir = existsSync(target.pluginDir)
|
|
722
|
+
if (hadLegacyPluginDir) {
|
|
723
|
+
rmSync(target.pluginDir, { recursive: true, force: true })
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
return uninstall.status === 0 || hadMarketplaceRoot || hadLegacyPluginDir
|
|
727
|
+
}
|
|
728
|
+
|
|
588
729
|
export function planInstallPlugin(
|
|
589
730
|
distDir: string,
|
|
590
731
|
pluginName: string,
|
|
@@ -655,6 +796,9 @@ export async function installPlugin(
|
|
|
655
796
|
} else {
|
|
656
797
|
createSymlinkInstall(target)
|
|
657
798
|
}
|
|
799
|
+
if (target.platform === 'codex') {
|
|
800
|
+
ensureCodexMarketplace(pluginName)
|
|
801
|
+
}
|
|
658
802
|
if (!options.quiet) {
|
|
659
803
|
console.log(` ${target.platform} -> ${target.description}`)
|
|
660
804
|
}
|
|
@@ -665,22 +809,37 @@ export async function installPlugin(
|
|
|
665
809
|
console.log('Nothing to install. Run `pluxx build` first.')
|
|
666
810
|
} else if (!options.quiet) {
|
|
667
811
|
console.log(`\nInstalled ${installed} plugin(s). Reload or restart your tools to pick them up.`)
|
|
812
|
+
for (const note of getInstallFollowupNotes(filtered.map((target) => target.platform))) {
|
|
813
|
+
console.log(note)
|
|
814
|
+
}
|
|
668
815
|
}
|
|
669
816
|
}
|
|
670
817
|
|
|
671
818
|
export async function uninstallPlugin(
|
|
672
819
|
pluginName: string,
|
|
673
820
|
platforms?: TargetPlatform[],
|
|
674
|
-
options: { quiet?: boolean } = {},
|
|
821
|
+
options: { quiet?: boolean; runCommand?: CommandRunner } = {},
|
|
675
822
|
): Promise<void> {
|
|
676
823
|
const targets = getInstallTargets(pluginName)
|
|
677
824
|
const filtered = platforms
|
|
678
825
|
? targets.filter(t => platforms.includes(t.platform))
|
|
679
826
|
: targets
|
|
827
|
+
const runCommand = options.runCommand ?? runCommandDefault
|
|
680
828
|
|
|
681
829
|
let removed = 0
|
|
682
830
|
|
|
683
831
|
for (const target of filtered) {
|
|
832
|
+
if (target.platform === 'claude-code') {
|
|
833
|
+
const removedClaude = uninstallClaudePlugin(target, pluginName, runCommand, { quiet: options.quiet })
|
|
834
|
+
if (removedClaude) {
|
|
835
|
+
if (!options.quiet) {
|
|
836
|
+
console.log(` removed ${target.description}`)
|
|
837
|
+
}
|
|
838
|
+
removed++
|
|
839
|
+
}
|
|
840
|
+
continue
|
|
841
|
+
}
|
|
842
|
+
|
|
684
843
|
if (existsSync(target.pluginDir)) {
|
|
685
844
|
rmSync(target.pluginDir, { recursive: true, force: true })
|
|
686
845
|
if (!options.quiet) {
|
|
@@ -688,6 +847,9 @@ export async function uninstallPlugin(
|
|
|
688
847
|
}
|
|
689
848
|
removed++
|
|
690
849
|
}
|
|
850
|
+
if (target.platform === 'codex') {
|
|
851
|
+
removeCodexMarketplacePlugin(pluginName)
|
|
852
|
+
}
|
|
691
853
|
}
|
|
692
854
|
|
|
693
855
|
if (removed === 0 && !options.quiet) {
|
package/src/cli/lint.ts
CHANGED
|
@@ -66,6 +66,10 @@ export interface LintResult {
|
|
|
66
66
|
issues: LintIssue[]
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
export interface LintProjectOptions {
|
|
70
|
+
targets?: TargetPlatform[]
|
|
71
|
+
}
|
|
72
|
+
|
|
69
73
|
const SKILL_NAME_REGEX = AGENT_SKILLS_RULES.name.pattern
|
|
70
74
|
const MAX_AGENT_SKILLS_DESCRIPTION = AGENT_SKILLS_RULES.description.maxLength
|
|
71
75
|
const MAX_CLAUDE_DESCRIPTION = CLAUDE_CODE_RULES.description.maxDisplayLength
|
|
@@ -1035,6 +1039,25 @@ function lintCursorRuleContentLimits(config: PluginConfig, issues: LintIssue[]):
|
|
|
1035
1039
|
function lintPermissions(config: PluginConfig, issues: LintIssue[]): void {
|
|
1036
1040
|
if (!config.permissions) return
|
|
1037
1041
|
|
|
1042
|
+
for (const action of ['allow', 'ask', 'deny'] as const) {
|
|
1043
|
+
const seen = new Set<string>()
|
|
1044
|
+
for (const raw of config.permissions[action] ?? []) {
|
|
1045
|
+
const trimmed = raw.trim()
|
|
1046
|
+
|
|
1047
|
+
if (seen.has(trimmed)) {
|
|
1048
|
+
pushIssue(issues, {
|
|
1049
|
+
level: 'warning',
|
|
1050
|
+
code: 'permissions-duplicate',
|
|
1051
|
+
message: `Permission rule "${trimmed}" is duplicated in "${action}".`,
|
|
1052
|
+
file: 'pluxx.config.ts',
|
|
1053
|
+
platform: 'Permissions',
|
|
1054
|
+
})
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
seen.add(trimmed)
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1038
1061
|
const rules = collectPermissionRules(config.permissions)
|
|
1039
1062
|
const seen = new Map<string, Set<string>>()
|
|
1040
1063
|
|
|
@@ -1061,7 +1084,7 @@ function lintPermissions(config: PluginConfig, issues: LintIssue[]): void {
|
|
|
1061
1084
|
pushIssue(issues, {
|
|
1062
1085
|
level: 'warning',
|
|
1063
1086
|
code: 'codex-permissions-external-config',
|
|
1064
|
-
message: 'Codex does not currently support plugin-packaged permission enforcement. Mirror canonical permissions into Codex user/admin config or external hooks for real enforcement.',
|
|
1087
|
+
message: 'Codex does not currently support plugin-packaged permission enforcement. Mirror canonical permissions into Codex user/admin config or external hooks for real enforcement (Pluxx emits .codex/permissions.generated.json as a starter mirror).',
|
|
1065
1088
|
file: 'pluxx.config.ts',
|
|
1066
1089
|
platform: 'Codex',
|
|
1067
1090
|
})
|
|
@@ -1100,7 +1123,10 @@ function sortIssues(issues: LintIssue[]): LintIssue[] {
|
|
|
1100
1123
|
})
|
|
1101
1124
|
}
|
|
1102
1125
|
|
|
1103
|
-
export async function lintProject(
|
|
1126
|
+
export async function lintProject(
|
|
1127
|
+
dir: string = process.cwd(),
|
|
1128
|
+
options: LintProjectOptions = {},
|
|
1129
|
+
): Promise<LintResult> {
|
|
1104
1130
|
const issues: LintIssue[] = []
|
|
1105
1131
|
const frontmatterCache = new Map<string, ParsedFrontmatterFile>()
|
|
1106
1132
|
|
|
@@ -1118,17 +1144,21 @@ export async function lintProject(dir: string = process.cwd()): Promise<LintResu
|
|
|
1118
1144
|
return { errors: 1, warnings: 0, issues }
|
|
1119
1145
|
}
|
|
1120
1146
|
|
|
1147
|
+
const lintConfig: PluginConfig = options.targets
|
|
1148
|
+
? { ...config, targets: options.targets }
|
|
1149
|
+
: config
|
|
1150
|
+
|
|
1121
1151
|
// Plugin structure checks
|
|
1122
|
-
lintPluginName(
|
|
1123
|
-
lintVersionFormat(
|
|
1124
|
-
lintManifestPaths(
|
|
1152
|
+
lintPluginName(lintConfig, issues)
|
|
1153
|
+
lintVersionFormat(lintConfig, issues)
|
|
1154
|
+
lintManifestPaths(lintConfig, issues)
|
|
1125
1155
|
lintPluginDirectoryPlacement(dir, issues)
|
|
1126
|
-
lintAbsolutePaths(
|
|
1156
|
+
lintAbsolutePaths(lintConfig, issues)
|
|
1127
1157
|
lintSettingsJson(dir, issues)
|
|
1128
|
-
lintLegacyCommandsDir(dir,
|
|
1158
|
+
lintLegacyCommandsDir(dir, lintConfig, issues)
|
|
1129
1159
|
|
|
1130
1160
|
// Hook and event validation
|
|
1131
|
-
lintHookEvents(
|
|
1161
|
+
lintHookEvents(lintConfig, issues)
|
|
1132
1162
|
|
|
1133
1163
|
// Agent file checks
|
|
1134
1164
|
const agentsDir = resolve(dir, 'agents')
|
|
@@ -1137,25 +1167,25 @@ export async function lintProject(dir: string = process.cwd()): Promise<LintResu
|
|
|
1137
1167
|
lintAgentIsolation(agentFiles, issues, frontmatterCache)
|
|
1138
1168
|
|
|
1139
1169
|
// MCP and brand
|
|
1140
|
-
lintMcpUrls(
|
|
1141
|
-
lintBrandMetadata(
|
|
1142
|
-
lintCodexOverrides(
|
|
1143
|
-
lintCodexHookCompatibility(
|
|
1144
|
-
lintCodexAgentsConfig(
|
|
1145
|
-
lintCodexHooksExternalConfig(
|
|
1146
|
-
lintPermissions(
|
|
1170
|
+
lintMcpUrls(lintConfig, issues)
|
|
1171
|
+
lintBrandMetadata(lintConfig, issues)
|
|
1172
|
+
lintCodexOverrides(lintConfig, issues)
|
|
1173
|
+
lintCodexHookCompatibility(lintConfig, issues)
|
|
1174
|
+
lintCodexAgentsConfig(lintConfig, issues)
|
|
1175
|
+
lintCodexHooksExternalConfig(lintConfig, issues)
|
|
1176
|
+
lintPermissions(lintConfig, issues)
|
|
1147
1177
|
|
|
1148
1178
|
// Cursor-specific checks
|
|
1149
|
-
lintCursorHooks(
|
|
1150
|
-
lintCursorRuleContentLimits(
|
|
1179
|
+
lintCursorHooks(lintConfig, issues)
|
|
1180
|
+
lintCursorRuleContentLimits(lintConfig, issues)
|
|
1151
1181
|
|
|
1152
|
-
const skillsDir = resolve(dir,
|
|
1182
|
+
const skillsDir = resolve(dir, lintConfig.skills)
|
|
1153
1183
|
let skillFiles: string[] = []
|
|
1154
1184
|
if (!existsSync(skillsDir)) {
|
|
1155
1185
|
pushIssue(issues, {
|
|
1156
1186
|
level: 'error',
|
|
1157
1187
|
code: 'skills-dir-missing',
|
|
1158
|
-
message: `Skills directory not found: ${
|
|
1188
|
+
message: `Skills directory not found: ${lintConfig.skills}`,
|
|
1159
1189
|
file: 'pluxx.config.ts',
|
|
1160
1190
|
platform: 'Agent Skills',
|
|
1161
1191
|
})
|
|
@@ -1165,29 +1195,29 @@ export async function lintProject(dir: string = process.cwd()): Promise<LintResu
|
|
|
1165
1195
|
pushIssue(issues, {
|
|
1166
1196
|
level: 'warning',
|
|
1167
1197
|
code: 'skills-none-found',
|
|
1168
|
-
message: `No SKILL.md files found in ${
|
|
1198
|
+
message: `No SKILL.md files found in ${lintConfig.skills}`,
|
|
1169
1199
|
file: 'pluxx.config.ts',
|
|
1170
1200
|
platform: 'Agent Skills',
|
|
1171
1201
|
})
|
|
1172
1202
|
}
|
|
1173
1203
|
|
|
1174
1204
|
for (const skillFile of skillFiles) {
|
|
1175
|
-
lintSkillFile(skillFile,
|
|
1205
|
+
lintSkillFile(skillFile, lintConfig.targets, issues, frontmatterCache)
|
|
1176
1206
|
}
|
|
1177
1207
|
}
|
|
1178
1208
|
|
|
1179
1209
|
// Cursor skill frontmatter checks
|
|
1180
|
-
lintCursorSkillFrontmatter(
|
|
1181
|
-
lintSkillListingBudgets(skillFiles,
|
|
1210
|
+
lintCursorSkillFrontmatter(lintConfig, skillFiles, issues, frontmatterCache)
|
|
1211
|
+
lintSkillListingBudgets(skillFiles, lintConfig.targets, issues, frontmatterCache)
|
|
1182
1212
|
|
|
1183
1213
|
// Platform limit checks for manifest prompts (Codex)
|
|
1184
|
-
lintManifestPromptLimits(
|
|
1214
|
+
lintManifestPromptLimits(lintConfig, issues)
|
|
1185
1215
|
|
|
1186
1216
|
// Platform limit checks for instructions file size
|
|
1187
|
-
lintInstructionsFileLimits(
|
|
1217
|
+
lintInstructionsFileLimits(lintConfig, dir, issues)
|
|
1188
1218
|
|
|
1189
1219
|
// Platform limit checks for rules file line count
|
|
1190
|
-
lintRulesFileLimits(
|
|
1220
|
+
lintRulesFileLimits(lintConfig, dir, issues)
|
|
1191
1221
|
|
|
1192
1222
|
const sorted = sortIssues(issues)
|
|
1193
1223
|
const errors = sorted.filter(i => i.level === 'error').length
|