@lousy-agents/cli 2.10.1 → 2.11.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/dist/index.js +242 -36
- package/dist/index.js.map +1 -1
- package/dist/mcp-server.js +23 -7
- package/dist/mcp-server.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -55118,6 +55118,102 @@ const remark = unified().use(remarkParse).use(remarkStringify).freeze()
|
|
|
55118
55118
|
return new RemarkMarkdownAstGateway();
|
|
55119
55119
|
}
|
|
55120
55120
|
|
|
55121
|
+
;// CONCATENATED MODULE: ./src/entities/lint-rules.ts
|
|
55122
|
+
/**
|
|
55123
|
+
* Lint rule registry entity.
|
|
55124
|
+
* Defines all known lint rule IDs with their default severities, organized by target.
|
|
55125
|
+
*/ /** Valid severity values for rule configuration */ /** Default severity levels for all known lint rules */ const DEFAULT_LINT_RULES = {
|
|
55126
|
+
agents: {
|
|
55127
|
+
"agent/missing-frontmatter": "error",
|
|
55128
|
+
"agent/invalid-frontmatter": "error",
|
|
55129
|
+
"agent/missing-name": "error",
|
|
55130
|
+
"agent/invalid-name-format": "error",
|
|
55131
|
+
"agent/name-mismatch": "error",
|
|
55132
|
+
"agent/missing-description": "error",
|
|
55133
|
+
"agent/invalid-description": "error",
|
|
55134
|
+
"agent/invalid-field": "warn"
|
|
55135
|
+
},
|
|
55136
|
+
instructions: {
|
|
55137
|
+
"instruction/parse-error": "warn",
|
|
55138
|
+
"instruction/command-not-in-code-block": "warn",
|
|
55139
|
+
"instruction/command-outside-section": "warn",
|
|
55140
|
+
"instruction/missing-error-handling": "warn"
|
|
55141
|
+
},
|
|
55142
|
+
skills: {
|
|
55143
|
+
"skill/invalid-frontmatter": "error",
|
|
55144
|
+
"skill/missing-frontmatter": "error",
|
|
55145
|
+
"skill/missing-name": "error",
|
|
55146
|
+
"skill/invalid-name-format": "error",
|
|
55147
|
+
"skill/name-mismatch": "error",
|
|
55148
|
+
"skill/missing-description": "error",
|
|
55149
|
+
"skill/invalid-description": "error",
|
|
55150
|
+
"skill/missing-allowed-tools": "warn"
|
|
55151
|
+
}
|
|
55152
|
+
};
|
|
55153
|
+
|
|
55154
|
+
;// CONCATENATED MODULE: ./src/lib/lint-config.ts
|
|
55155
|
+
/**
|
|
55156
|
+
* Lint configuration loader.
|
|
55157
|
+
* Loads lint rule severity overrides from c12 config and merges with defaults.
|
|
55158
|
+
*/
|
|
55159
|
+
|
|
55160
|
+
|
|
55161
|
+
/** Zod schema for a rule config map: rule IDs validated with regex to prevent prototype pollution */ const RuleConfigMapSchema = record(schemas_string().regex(/^[a-z]+\/[a-z]+(?:-[a-z]+)*$/), schemas_enum([
|
|
55162
|
+
"error",
|
|
55163
|
+
"warn",
|
|
55164
|
+
"off"
|
|
55165
|
+
]));
|
|
55166
|
+
/** Zod schema for the lint.rules section of the config */ const LintRulesConfigSchema = schemas_object({
|
|
55167
|
+
agents: RuleConfigMapSchema.optional(),
|
|
55168
|
+
instructions: RuleConfigMapSchema.optional(),
|
|
55169
|
+
skills: RuleConfigMapSchema.optional()
|
|
55170
|
+
});
|
|
55171
|
+
/** Zod schema for the lint section of the config */ const LintConfigSchema = schemas_object({
|
|
55172
|
+
lint: schemas_object({
|
|
55173
|
+
rules: LintRulesConfigSchema.optional()
|
|
55174
|
+
}).optional()
|
|
55175
|
+
});
|
|
55176
|
+
/**
|
|
55177
|
+
* Merges user overrides with defaults for a single target.
|
|
55178
|
+
* Only known rule IDs (present in defaults) are applied; unknown IDs are discarded.
|
|
55179
|
+
*/ function mergeTargetRules(defaults, overrides) {
|
|
55180
|
+
if (!overrides) {
|
|
55181
|
+
return defaults;
|
|
55182
|
+
}
|
|
55183
|
+
const merged = {
|
|
55184
|
+
...defaults
|
|
55185
|
+
};
|
|
55186
|
+
for (const [ruleId, severity] of Object.entries(overrides)){
|
|
55187
|
+
if (Object.hasOwn(defaults, ruleId)) {
|
|
55188
|
+
merged[ruleId] = severity;
|
|
55189
|
+
}
|
|
55190
|
+
}
|
|
55191
|
+
return merged;
|
|
55192
|
+
}
|
|
55193
|
+
/**
|
|
55194
|
+
* Loads lint configuration from the target directory using c12.
|
|
55195
|
+
* Merges user overrides with default rule severities.
|
|
55196
|
+
* Throws on config load failures (syntax errors, permission denied, validation errors).
|
|
55197
|
+
*/ async function loadLintConfig(targetDir) {
|
|
55198
|
+
const { config } = await loadConfig({
|
|
55199
|
+
name: "lousy-agents",
|
|
55200
|
+
cwd: targetDir
|
|
55201
|
+
});
|
|
55202
|
+
if (!config) {
|
|
55203
|
+
return DEFAULT_LINT_RULES;
|
|
55204
|
+
}
|
|
55205
|
+
const parsed = LintConfigSchema.parse(config);
|
|
55206
|
+
const rules = parsed.lint?.rules;
|
|
55207
|
+
if (!rules) {
|
|
55208
|
+
return DEFAULT_LINT_RULES;
|
|
55209
|
+
}
|
|
55210
|
+
return {
|
|
55211
|
+
agents: mergeTargetRules(DEFAULT_LINT_RULES.agents, rules.agents),
|
|
55212
|
+
instructions: mergeTargetRules(DEFAULT_LINT_RULES.instructions, rules.instructions),
|
|
55213
|
+
skills: mergeTargetRules(DEFAULT_LINT_RULES.skills, rules.skills)
|
|
55214
|
+
};
|
|
55215
|
+
}
|
|
55216
|
+
|
|
55121
55217
|
;// CONCATENATED MODULE: ./src/entities/instruction-quality.ts
|
|
55122
55218
|
/**
|
|
55123
55219
|
* Core domain entities for instruction quality analysis.
|
|
@@ -55178,7 +55274,9 @@ const remark = unified().use(remarkParse).use(remarkStringify).freeze()
|
|
|
55178
55274
|
commandScores: [],
|
|
55179
55275
|
overallQualityScore: 0,
|
|
55180
55276
|
suggestions: [
|
|
55181
|
-
|
|
55277
|
+
{
|
|
55278
|
+
message: "No agent instruction files found. Supported formats: .github/copilot-instructions.md, .github/instructions/*.md, .github/agents/*.md, AGENTS.md, CLAUDE.md"
|
|
55279
|
+
}
|
|
55182
55280
|
],
|
|
55183
55281
|
parsingErrors: []
|
|
55184
55282
|
},
|
|
@@ -55245,7 +55343,10 @@ const remark = unified().use(remarkParse).use(remarkStringify).freeze()
|
|
|
55245
55343
|
const suggestions = this.generateSuggestions(commandScores);
|
|
55246
55344
|
if (parsingErrors.length > 0) {
|
|
55247
55345
|
const skippedFiles = parsingErrors.map((pe)=>pe.filePath).join(", ");
|
|
55248
|
-
suggestions.push(
|
|
55346
|
+
suggestions.push({
|
|
55347
|
+
message: `${parsingErrors.length} file(s) could not be parsed and were skipped: ${skippedFiles}. Analysis may be incomplete.`,
|
|
55348
|
+
ruleId: "instruction/parse-error"
|
|
55349
|
+
});
|
|
55249
55350
|
}
|
|
55250
55351
|
return {
|
|
55251
55352
|
result: {
|
|
@@ -55459,22 +55560,33 @@ const remark = unified().use(remarkParse).use(remarkStringify).freeze()
|
|
|
55459
55560
|
const lowStructural = commandScores.filter((s)=>s.structuralContext === 0 && s.bestSourceFile !== "");
|
|
55460
55561
|
if (lowStructural.length > 0) {
|
|
55461
55562
|
const names = lowStructural.map((s)=>s.commandName).join(", ");
|
|
55462
|
-
suggestions.push(
|
|
55563
|
+
suggestions.push({
|
|
55564
|
+
message: `Commands not under a dedicated section: ${names}. Add a heading like "## Validation" or "## Feedback Loop" above these commands.`,
|
|
55565
|
+
ruleId: "instruction/command-outside-section"
|
|
55566
|
+
});
|
|
55463
55567
|
}
|
|
55464
55568
|
const lowExecution = commandScores.filter((s)=>s.executionClarity === 0 && s.bestSourceFile !== "");
|
|
55465
55569
|
if (lowExecution.length > 0) {
|
|
55466
55570
|
const names = lowExecution.map((s)=>s.commandName).join(", ");
|
|
55467
|
-
suggestions.push(
|
|
55571
|
+
suggestions.push({
|
|
55572
|
+
message: `Commands not in code blocks: ${names}. Document these commands in fenced code blocks for clarity.`,
|
|
55573
|
+
ruleId: "instruction/command-not-in-code-block"
|
|
55574
|
+
});
|
|
55468
55575
|
}
|
|
55469
55576
|
const lowLoop = commandScores.filter((s)=>s.loopCompleteness === 0 && s.executionClarity === 1 && s.bestSourceFile !== "");
|
|
55470
55577
|
if (lowLoop.length > 0) {
|
|
55471
55578
|
const names = lowLoop.map((s)=>s.commandName).join(", ");
|
|
55472
|
-
suggestions.push(
|
|
55579
|
+
suggestions.push({
|
|
55580
|
+
message: `Commands missing error handling guidance: ${names}. Add instructions for what to do if the command fails.`,
|
|
55581
|
+
ruleId: "instruction/missing-error-handling"
|
|
55582
|
+
});
|
|
55473
55583
|
}
|
|
55474
55584
|
const notFound = commandScores.filter((s)=>s.bestSourceFile === "");
|
|
55475
55585
|
if (notFound.length > 0) {
|
|
55476
55586
|
const names = notFound.map((s)=>s.commandName).join(", ");
|
|
55477
|
-
suggestions.push(
|
|
55587
|
+
suggestions.push({
|
|
55588
|
+
message: `Commands not found in any instruction file: ${names}. Document these feedback loop commands in your instruction files.`
|
|
55589
|
+
});
|
|
55478
55590
|
}
|
|
55479
55591
|
return suggestions;
|
|
55480
55592
|
}
|
|
@@ -55612,14 +55724,8 @@ const remark = unified().use(remarkParse).use(remarkStringify).freeze()
|
|
|
55612
55724
|
}
|
|
55613
55725
|
|
|
55614
55726
|
;// CONCATENATED MODULE: ./src/use-cases/lint-skill-frontmatter.ts
|
|
55615
|
-
|
|
55616
|
-
|
|
55617
|
-
* Validates required and recommended fields, name format, and directory naming.
|
|
55618
|
-
*/
|
|
55619
|
-
/**
|
|
55620
|
-
* Zod schema for validating agent skill frontmatter.
|
|
55621
|
-
* Based on the agentskills.io specification.
|
|
55622
|
-
*/ const AgentSkillFrontmatterSchema = schemas_object({
|
|
55727
|
+
|
|
55728
|
+
const AgentSkillFrontmatterSchema = schemas_object({
|
|
55623
55729
|
name: schemas_string().min(1, "Name is required").max(64, "Name must be 64 characters or fewer").regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, "Name must contain only lowercase letters, numbers, and hyphens. It cannot start/end with a hyphen or contain consecutive hyphens."),
|
|
55624
55730
|
description: schemas_string().min(1, "Description is required").max(1024, "Description must be 1024 characters or fewer").refine((s)=>s.trim().length > 0, {
|
|
55625
55731
|
message: "Description cannot be empty or whitespace-only"
|
|
@@ -55629,14 +55735,13 @@ const remark = unified().use(remarkParse).use(remarkStringify).freeze()
|
|
|
55629
55735
|
metadata: record(schemas_string(), schemas_string()).optional(),
|
|
55630
55736
|
"allowed-tools": schemas_string().optional()
|
|
55631
55737
|
});
|
|
55632
|
-
|
|
55633
|
-
* Recommended (optional) fields that produce warnings when missing.
|
|
55634
|
-
*/ const RECOMMENDED_FIELDS = [
|
|
55738
|
+
const RECOMMENDED_FIELDS = [
|
|
55635
55739
|
"allowed-tools"
|
|
55636
55740
|
];
|
|
55637
|
-
|
|
55638
|
-
|
|
55639
|
-
|
|
55741
|
+
const RECOMMENDED_FIELD_RULE_IDS = {
|
|
55742
|
+
"allowed-tools": "skill/missing-allowed-tools"
|
|
55743
|
+
};
|
|
55744
|
+
class LintSkillFrontmatterUseCase {
|
|
55640
55745
|
gateway;
|
|
55641
55746
|
constructor(gateway){
|
|
55642
55747
|
this.gateway = gateway;
|
|
@@ -55672,16 +55777,20 @@ const remark = unified().use(remarkParse).use(remarkStringify).freeze()
|
|
|
55672
55777
|
diagnostics.push({
|
|
55673
55778
|
line: 1,
|
|
55674
55779
|
severity: "error",
|
|
55675
|
-
message: errorMessage
|
|
55780
|
+
message: errorMessage,
|
|
55781
|
+
ruleId: "skill/invalid-frontmatter"
|
|
55676
55782
|
});
|
|
55677
55783
|
}
|
|
55678
55784
|
if (!parsed) {
|
|
55679
55785
|
if (diagnostics.length === 0) {
|
|
55680
|
-
const
|
|
55786
|
+
const hasDelimiters = hasFrontmatterDelimiters(content);
|
|
55787
|
+
const message = hasDelimiters ? "Invalid YAML frontmatter. The content between --- delimiters could not be parsed as valid YAML." : "Missing YAML frontmatter. Skill files must begin with --- delimited YAML frontmatter.";
|
|
55788
|
+
const ruleId = hasDelimiters ? "skill/invalid-frontmatter" : "skill/missing-frontmatter";
|
|
55681
55789
|
diagnostics.push({
|
|
55682
55790
|
line: 1,
|
|
55683
55791
|
severity: "error",
|
|
55684
|
-
message
|
|
55792
|
+
message,
|
|
55793
|
+
ruleId
|
|
55685
55794
|
});
|
|
55686
55795
|
}
|
|
55687
55796
|
return {
|
|
@@ -55702,47 +55811,58 @@ const remark = unified().use(remarkParse).use(remarkStringify).freeze()
|
|
|
55702
55811
|
}
|
|
55703
55812
|
validateFrontmatter(parsed, parentDirName) {
|
|
55704
55813
|
const diagnostics = [];
|
|
55705
|
-
// Validate against Zod schema
|
|
55706
55814
|
const result = AgentSkillFrontmatterSchema.safeParse(parsed.data);
|
|
55707
55815
|
if (!result.success) {
|
|
55708
55816
|
for (const issue of result.error.issues){
|
|
55709
55817
|
const fieldName = issue.path[0]?.toString();
|
|
55710
55818
|
const line = fieldName ? parsed.fieldLines.get(fieldName) ?? parsed.frontmatterStartLine : parsed.frontmatterStartLine;
|
|
55819
|
+
const ruleId = this.getRuleIdForField(fieldName, issue.code, parsed.data);
|
|
55711
55820
|
diagnostics.push({
|
|
55712
55821
|
line,
|
|
55713
55822
|
severity: "error",
|
|
55714
55823
|
message: issue.message,
|
|
55715
|
-
field: fieldName
|
|
55824
|
+
field: fieldName,
|
|
55825
|
+
ruleId
|
|
55716
55826
|
});
|
|
55717
55827
|
}
|
|
55718
55828
|
}
|
|
55719
|
-
// Check name matches parent directory
|
|
55720
55829
|
if (result.success && result.data.name !== parentDirName) {
|
|
55721
55830
|
const nameLine = parsed.fieldLines.get("name") ?? parsed.frontmatterStartLine;
|
|
55722
55831
|
diagnostics.push({
|
|
55723
55832
|
line: nameLine,
|
|
55724
55833
|
severity: "error",
|
|
55725
55834
|
message: `Frontmatter name '${result.data.name}' must match parent directory name '${parentDirName}'`,
|
|
55726
|
-
field: "name"
|
|
55835
|
+
field: "name",
|
|
55836
|
+
ruleId: "skill/name-mismatch"
|
|
55727
55837
|
});
|
|
55728
55838
|
}
|
|
55729
|
-
// Check recommended fields
|
|
55730
55839
|
for (const field of RECOMMENDED_FIELDS){
|
|
55731
55840
|
if (parsed.data[field] === undefined) {
|
|
55732
55841
|
diagnostics.push({
|
|
55733
55842
|
line: parsed.frontmatterStartLine,
|
|
55734
55843
|
severity: "warning",
|
|
55735
55844
|
message: `Recommended field '${field}' is missing`,
|
|
55736
|
-
field
|
|
55845
|
+
field,
|
|
55846
|
+
ruleId: RECOMMENDED_FIELD_RULE_IDS[field]
|
|
55737
55847
|
});
|
|
55738
55848
|
}
|
|
55739
55849
|
}
|
|
55740
55850
|
return diagnostics;
|
|
55741
55851
|
}
|
|
55852
|
+
getRuleIdForField(fieldName, issueCode, inputData) {
|
|
55853
|
+
// Check the actual input data for field presence rather than
|
|
55854
|
+
// relying on Zod message text which can change across versions.
|
|
55855
|
+
const isMissing = issueCode === "invalid_type" && (fieldName === undefined || !Object.hasOwn(inputData, fieldName));
|
|
55856
|
+
if (fieldName === "name") {
|
|
55857
|
+
return isMissing ? "skill/missing-name" : "skill/invalid-name-format";
|
|
55858
|
+
}
|
|
55859
|
+
if (fieldName === "description") {
|
|
55860
|
+
return isMissing ? "skill/missing-description" : "skill/invalid-description";
|
|
55861
|
+
}
|
|
55862
|
+
return "skill/invalid-frontmatter";
|
|
55863
|
+
}
|
|
55742
55864
|
}
|
|
55743
|
-
|
|
55744
|
-
* Checks whether content has opening and closing --- frontmatter delimiters.
|
|
55745
|
-
*/ function hasFrontmatterDelimiters(content) {
|
|
55865
|
+
function hasFrontmatterDelimiters(content) {
|
|
55746
55866
|
const lines = content.split("\n");
|
|
55747
55867
|
if (lines[0]?.trim() !== "---") {
|
|
55748
55868
|
return false;
|
|
@@ -55772,6 +55892,7 @@ const remark = unified().use(remarkParse).use(remarkStringify).freeze()
|
|
|
55772
55892
|
|
|
55773
55893
|
|
|
55774
55894
|
|
|
55895
|
+
|
|
55775
55896
|
/** Schema for validating target directory */ const TargetDirSchema = schemas_string().min(1, "Target directory is required");
|
|
55776
55897
|
/**
|
|
55777
55898
|
* Validates the target directory.
|
|
@@ -55796,6 +55917,7 @@ const remark = unified().use(remarkParse).use(remarkStringify).freeze()
|
|
|
55796
55917
|
severity: d.severity,
|
|
55797
55918
|
message: d.message,
|
|
55798
55919
|
field: d.field,
|
|
55920
|
+
ruleId: d.ruleId,
|
|
55799
55921
|
target: "skill"
|
|
55800
55922
|
});
|
|
55801
55923
|
}
|
|
@@ -55932,8 +56054,80 @@ const remark = unified().use(remarkParse).use(remarkStringify).freeze()
|
|
|
55932
56054
|
consola.info(`Overall instruction quality score: ${result.overallQualityScore}%`);
|
|
55933
56055
|
}
|
|
55934
56056
|
for (const suggestion of result.suggestions){
|
|
55935
|
-
consola.warn(suggestion);
|
|
56057
|
+
consola.warn(suggestion.message);
|
|
56058
|
+
}
|
|
56059
|
+
}
|
|
56060
|
+
/** Maps a lint target to its config key */ const TARGET_TO_CONFIG_KEY = {
|
|
56061
|
+
skill: "skills",
|
|
56062
|
+
agent: "agents",
|
|
56063
|
+
instruction: "instructions"
|
|
56064
|
+
};
|
|
56065
|
+
/**
|
|
56066
|
+
* Maps config-facing severity to diagnostic-facing severity.
|
|
56067
|
+
* "warn" → "warning", "error" → "error", "off" → null (drop).
|
|
56068
|
+
*/ function lint_mapSeverity(configSeverity) {
|
|
56069
|
+
if (configSeverity === "off") {
|
|
56070
|
+
return null;
|
|
56071
|
+
}
|
|
56072
|
+
if (configSeverity === "warn") {
|
|
56073
|
+
return "warning";
|
|
56074
|
+
}
|
|
56075
|
+
return configSeverity;
|
|
56076
|
+
}
|
|
56077
|
+
/**
|
|
56078
|
+
* Filters instruction suggestions based on rule severity configuration.
|
|
56079
|
+
* Drops suggestions whose corresponding rule is "off".
|
|
56080
|
+
* Suggestions without a ruleId pass through unchanged.
|
|
56081
|
+
*/ function filterInstructionSuggestions(suggestions, rules) {
|
|
56082
|
+
return suggestions.filter((suggestion)=>{
|
|
56083
|
+
if (!suggestion.ruleId) {
|
|
56084
|
+
return true;
|
|
56085
|
+
}
|
|
56086
|
+
return rules[suggestion.ruleId] !== "off";
|
|
56087
|
+
});
|
|
56088
|
+
}
|
|
56089
|
+
/**
|
|
56090
|
+
* Applies severity filtering to a LintOutput based on rule configuration.
|
|
56091
|
+
* Drops diagnostics for "off" rules, remaps severity for "warn"/"error" rules.
|
|
56092
|
+
* Diagnostics without a ruleId pass through unchanged.
|
|
56093
|
+
* For instruction targets, also filters qualityResult.suggestions.
|
|
56094
|
+
*/ function applySeverityFilter(output, rulesConfig) {
|
|
56095
|
+
const configKey = TARGET_TO_CONFIG_KEY[output.target];
|
|
56096
|
+
const targetRules = rulesConfig[configKey];
|
|
56097
|
+
const filteredDiagnostics = [];
|
|
56098
|
+
for (const diagnostic of output.diagnostics){
|
|
56099
|
+
const configuredSeverity = diagnostic.ruleId ? targetRules[diagnostic.ruleId] : undefined;
|
|
56100
|
+
if (!configuredSeverity) {
|
|
56101
|
+
filteredDiagnostics.push(diagnostic);
|
|
56102
|
+
continue;
|
|
56103
|
+
}
|
|
56104
|
+
const mappedSeverity = lint_mapSeverity(configuredSeverity);
|
|
56105
|
+
if (mappedSeverity === null) {
|
|
56106
|
+
continue;
|
|
56107
|
+
}
|
|
56108
|
+
filteredDiagnostics.push({
|
|
56109
|
+
...diagnostic,
|
|
56110
|
+
severity: mappedSeverity
|
|
56111
|
+
});
|
|
55936
56112
|
}
|
|
56113
|
+
const totalErrors = filteredDiagnostics.filter((d)=>d.severity === "error").length;
|
|
56114
|
+
const totalWarnings = filteredDiagnostics.filter((d)=>d.severity === "warning").length;
|
|
56115
|
+
const totalInfos = filteredDiagnostics.filter((d)=>d.severity === "info").length;
|
|
56116
|
+
const filteredQualityResult = output.qualityResult && configKey === "instructions" ? {
|
|
56117
|
+
...output.qualityResult,
|
|
56118
|
+
suggestions: filterInstructionSuggestions(output.qualityResult.suggestions, targetRules)
|
|
56119
|
+
} : output.qualityResult;
|
|
56120
|
+
return {
|
|
56121
|
+
...output,
|
|
56122
|
+
diagnostics: filteredDiagnostics,
|
|
56123
|
+
qualityResult: filteredQualityResult,
|
|
56124
|
+
summary: {
|
|
56125
|
+
...output.summary,
|
|
56126
|
+
totalErrors,
|
|
56127
|
+
totalWarnings,
|
|
56128
|
+
totalInfos
|
|
56129
|
+
}
|
|
56130
|
+
};
|
|
55937
56131
|
}
|
|
55938
56132
|
/**
|
|
55939
56133
|
* The `lint` command for validating agent skills, custom agents, and instruction files.
|
|
@@ -55967,6 +56161,15 @@ const remark = unified().use(remarkParse).use(remarkStringify).freeze()
|
|
|
55967
56161
|
run: async (context)=>{
|
|
55968
56162
|
const rawTargetDir = typeof context.data?.targetDir === "string" ? context.data.targetDir : process.cwd();
|
|
55969
56163
|
const targetDir = validateTargetDir(rawTargetDir);
|
|
56164
|
+
let rulesConfig;
|
|
56165
|
+
try {
|
|
56166
|
+
rulesConfig = await loadLintConfig(targetDir);
|
|
56167
|
+
} catch (error) {
|
|
56168
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
56169
|
+
consola.error(`Failed to load lint configuration: ${message}`);
|
|
56170
|
+
process.exitCode = 1;
|
|
56171
|
+
return;
|
|
56172
|
+
}
|
|
55970
56173
|
const lintSkillsFlag = context.args?.skills === true || context.data?.skills === true;
|
|
55971
56174
|
const lintAgentsFlag = context.args?.agents === true || context.data?.agents === true;
|
|
55972
56175
|
const lintInstructionsFlag = context.args?.instructions === true || context.data?.instructions === true;
|
|
@@ -55981,19 +56184,22 @@ const remark = unified().use(remarkParse).use(remarkStringify).freeze()
|
|
|
55981
56184
|
let totalWarnings = 0;
|
|
55982
56185
|
const allOutputs = [];
|
|
55983
56186
|
if (noFlagProvided || lintSkillsFlag) {
|
|
55984
|
-
const
|
|
56187
|
+
const rawOutput = await lintSkills(targetDir);
|
|
56188
|
+
const skillOutput = applySeverityFilter(rawOutput, rulesConfig);
|
|
55985
56189
|
allOutputs.push(skillOutput);
|
|
55986
56190
|
totalErrors += skillOutput.summary.totalErrors;
|
|
55987
56191
|
totalWarnings += skillOutput.summary.totalWarnings;
|
|
55988
56192
|
}
|
|
55989
56193
|
if (noFlagProvided || lintAgentsFlag) {
|
|
55990
|
-
const
|
|
56194
|
+
const rawOutput = await lintAgents(targetDir);
|
|
56195
|
+
const agentOutput = applySeverityFilter(rawOutput, rulesConfig);
|
|
55991
56196
|
allOutputs.push(agentOutput);
|
|
55992
56197
|
totalErrors += agentOutput.summary.totalErrors;
|
|
55993
56198
|
totalWarnings += agentOutput.summary.totalWarnings;
|
|
55994
56199
|
}
|
|
55995
56200
|
if (noFlagProvided || lintInstructionsFlag) {
|
|
55996
|
-
const
|
|
56201
|
+
const rawOutput = await lintInstructions(targetDir);
|
|
56202
|
+
const instructionOutput = applySeverityFilter(rawOutput, rulesConfig);
|
|
55997
56203
|
allOutputs.push(instructionOutput);
|
|
55998
56204
|
totalErrors += instructionOutput.summary.totalErrors;
|
|
55999
56205
|
totalWarnings += instructionOutput.summary.totalWarnings;
|