@illicomedia/skills-mcp-server 0.0.0-stage → 1.0.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.
Potentially problematic release.
This version of @illicomedia/skills-mcp-server might be problematic. Click here for more details.
- package/LICENSE +21 -0
- package/README.md +120 -2
- package/dist/audit.d.ts +23 -0
- package/dist/audit.js +124 -0
- package/dist/catalog.d.ts +18 -0
- package/dist/catalog.js +306 -0
- package/dist/executor.d.ts +4 -0
- package/dist/executor.js +96 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +31 -0
- package/dist/installer.d.ts +35 -0
- package/dist/installer.js +217 -0
- package/dist/license-keys.d.ts +11 -0
- package/dist/license-keys.js +17 -0
- package/dist/license-templates.d.ts +7 -0
- package/dist/license-templates.js +78 -0
- package/dist/license.d.ts +24 -0
- package/dist/license.js +192 -0
- package/dist/server.d.ts +17 -0
- package/dist/server.js +158 -0
- package/dist/tools.d.ts +10 -0
- package/dist/tools.js +149 -0
- package/dist/types.d.ts +51 -0
- package/dist/types.js +6 -0
- package/package.json +49 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Frédéric Charles Viallet
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,121 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Fredo QA Skills - Model Context Protocol (MCP) Server
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Official **Model Context Protocol (MCP)** server for **Fredo QA Skills**.
|
|
4
|
+
Connects AI coding assistants (**Cursor, Claude Desktop, Antigravity, Windsurf, Copilot**) to the Fredo QA Skills quality policy engine and compliance framework.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- **Standard MCP Protocol**: 100% compliant with the MCP specification (JSON-RPC 2.0 over `stdio`).
|
|
11
|
+
- **Dynamic Skill Injection**: Automatically supplies AI agents with authoritative QA rules, test commands, and quality gates (`qa:starter`, `qa:standard`, `qa:strict`).
|
|
12
|
+
- **Signed License Files**: Verifies an Ed25519-signed `license.json` offline and unlocks Pro or Enterprise skills accordingly. Without a valid license, all MIT skills stay available.
|
|
13
|
+
- **Version Retention**: A license unlocks every server release published on or before its `updates_until` date, permanently. Later releases run in free mode until the license is renewed. No clock check is involved.
|
|
14
|
+
- **Canary Cryptographic Watermarking**: Embeds non-intrusive provenance tokens into skill outputs for copyright protection and leak detection.
|
|
15
|
+
- **Presence Audit**: The `audit_compliance` tool checks that expected files and scripts exist (AGENTS.md, `.qa-exceptions.yaml`, security.txt, `.gitignore`, QA scripts). It does not run gates or validate contents.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Quick Setup (npx or local node)
|
|
20
|
+
|
|
21
|
+
### 1. Claude Desktop
|
|
22
|
+
|
|
23
|
+
Add to your `claude_desktop_config.json`:
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"mcpServers": {
|
|
28
|
+
"fredo-qa": {
|
|
29
|
+
"command": "npx",
|
|
30
|
+
"args": ["-y", "@illicomedia/skills-mcp-server"],
|
|
31
|
+
"env": {
|
|
32
|
+
"FREDO_QA_LICENSE_FILE": "/absolute/path/to/license.json"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 2. Cursor IDE
|
|
40
|
+
|
|
41
|
+
Add to `.cursor/mcp.json` in your workspace or user settings:
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
{
|
|
45
|
+
"mcpServers": {
|
|
46
|
+
"fredo-qa": {
|
|
47
|
+
"command": "npx",
|
|
48
|
+
"args": ["-y", "@illicomedia/skills-mcp-server"],
|
|
49
|
+
"env": {
|
|
50
|
+
"FREDO_QA_LICENSE_FILE": "/absolute/path/to/license.json"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### 3. Google Antigravity
|
|
58
|
+
|
|
59
|
+
Add to your `antigravity.json` or custom MCP settings:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"mcpServers": {
|
|
64
|
+
"fredo-qa": {
|
|
65
|
+
"command": "npx",
|
|
66
|
+
"args": ["-y", "@illicomedia/skills-mcp-server"],
|
|
67
|
+
"env": {
|
|
68
|
+
"FREDO_QA_LICENSE_FILE": "/absolute/path/to/license.json"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## License Files
|
|
76
|
+
|
|
77
|
+
Pro and Enterprise skills require a license file signed by the vendor with Ed25519. The server
|
|
78
|
+
looks for it in this order:
|
|
79
|
+
|
|
80
|
+
1. The path in `FREDO_QA_LICENSE_FILE`.
|
|
81
|
+
2. `~/.config/fredo-qa/license.json`.
|
|
82
|
+
3. `.qa-license.json` at the project root (keep it out of git).
|
|
83
|
+
|
|
84
|
+
The server verifies the signature offline against the public keys compiled into the release.
|
|
85
|
+
A missing, malformed, tampered, or untrusted license leaves the server in free mode and says why.
|
|
86
|
+
The format is defined in `docs/plans/2026-10-07-enforcement-kit/distribution-licensing.md`,
|
|
87
|
+
section 3.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Available MCP Tools
|
|
92
|
+
|
|
93
|
+
| Tool Name | Parameters | Description |
|
|
94
|
+
|---|---|---|
|
|
95
|
+
| `list_skills` | `{ category?: string }` | Lists all skills accessible under your current plan with their descriptions and key gates. |
|
|
96
|
+
| `get_skill_rules` | `{ skill_id: string }` | Returns complete prompt instructions and QA directives for a skill (e.g. `qa-security`, `qa-accessibility`). |
|
|
97
|
+
| `install_skill` | `{ skill_id: string, project_path?: string, license_key?: string }` | Installs a skill into `.agents/skills/<skill_id>/` with `SKILL.md` and `LICENSE`. Enforces auth for paid Pro & Enterprise skills. |
|
|
98
|
+
| `sync_workspace_skills` | `{ project_path?: string, skills?: string[], license_key?: string }` | Auto-detects project stack and provisions matching QA skills and licenses. Respects license tiers and reports auth status. |
|
|
99
|
+
| `set_license_key` | `{ license_key: string }` | Sets the signed license file (path or JSON content) for the active session, without a server restart. |
|
|
100
|
+
| `audit_compliance` | `{ project_path: string }` | Reports which expected files and scripts are present. Presence only: no gate is executed and no content is validated. |
|
|
101
|
+
| `verify_license` | `{ license_key?: string }` | Returns signature validity, tier, licensee, license ID, `updates_until`, and fallback status. |
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Development & Testing
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# Build the TypeScript MCP server
|
|
109
|
+
npm run build
|
|
110
|
+
|
|
111
|
+
# Run automated tests
|
|
112
|
+
npm test
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## License & Copyright
|
|
118
|
+
|
|
119
|
+
Copyright (c) 2026 Frédéric Charles Viallet.
|
|
120
|
+
Open-source foundation tools released under the MIT License.
|
|
121
|
+
Commercial skills and enterprise packs are proprietary and subject to the Fredo QA Skills Commercial License.
|
package/dist/audit.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface AuditCheckResult {
|
|
2
|
+
category: string;
|
|
3
|
+
name: string;
|
|
4
|
+
passed: boolean;
|
|
5
|
+
severity: 'blocker' | 'warning' | 'info';
|
|
6
|
+
details: string;
|
|
7
|
+
}
|
|
8
|
+
export interface AuditReport {
|
|
9
|
+
projectPath: string;
|
|
10
|
+
timestamp: string;
|
|
11
|
+
/** Share of presence checks that found their file or script, 0-100. Not a compliance score. */
|
|
12
|
+
score: number;
|
|
13
|
+
scope: string;
|
|
14
|
+
totalChecks: number;
|
|
15
|
+
passedChecks: number;
|
|
16
|
+
failedChecks: number;
|
|
17
|
+
results: AuditCheckResult[];
|
|
18
|
+
recommendations: string[];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Checks that the files and scripts expected by Fredo QA Skills are present in a project.
|
|
22
|
+
*/
|
|
23
|
+
export declare function runComplianceAudit(projectPath: string): AuditReport;
|
package/dist/audit.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 Frédéric Charles Viallet
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
import * as fs from 'node:fs';
|
|
4
|
+
import * as path from 'node:path';
|
|
5
|
+
const AUDIT_SCOPE = 'File-presence checks only: gates are not executed and file contents are not validated. A full pass means the expected files exist, not that the project is compliant.';
|
|
6
|
+
/**
|
|
7
|
+
* Checks that the files and scripts expected by Fredo QA Skills are present in a project.
|
|
8
|
+
*/
|
|
9
|
+
export function runComplianceAudit(projectPath) {
|
|
10
|
+
const resolvedPath = path.resolve(projectPath);
|
|
11
|
+
const results = [];
|
|
12
|
+
// Check 1: AGENTS.md policy presence
|
|
13
|
+
const agentsMd = path.join(resolvedPath, 'AGENTS.md');
|
|
14
|
+
const hasAgentsMd = fs.existsSync(agentsMd);
|
|
15
|
+
results.push({
|
|
16
|
+
category: 'governance',
|
|
17
|
+
name: 'AGENTS.md present',
|
|
18
|
+
passed: hasAgentsMd,
|
|
19
|
+
severity: 'blocker',
|
|
20
|
+
details: hasAgentsMd
|
|
21
|
+
? 'AGENTS.md file present (content not evaluated).'
|
|
22
|
+
: 'AGENTS.md not found. Coding agents have no repository-level QA instructions.',
|
|
23
|
+
});
|
|
24
|
+
// Check 2: .qa-exceptions governance
|
|
25
|
+
const exceptionsFile = path.join(resolvedPath, '.qa-exceptions.yaml');
|
|
26
|
+
const hasExceptions = fs.existsSync(exceptionsFile);
|
|
27
|
+
results.push({
|
|
28
|
+
category: 'governance',
|
|
29
|
+
name: '.qa-exceptions.yaml present',
|
|
30
|
+
passed: hasExceptions,
|
|
31
|
+
severity: 'warning',
|
|
32
|
+
details: hasExceptions
|
|
33
|
+
? 'Exception register file present (schema and expiry not checked).'
|
|
34
|
+
: 'No .qa-exceptions.yaml found. Deviations from quality gates should be tracked there.',
|
|
35
|
+
});
|
|
36
|
+
// Check 3: RFC 9116 security.txt
|
|
37
|
+
const secTxtPublic = path.join(resolvedPath, 'public', '.well-known', 'security.txt');
|
|
38
|
+
const secTxtDist = path.join(resolvedPath, 'dist', '.well-known', 'security.txt');
|
|
39
|
+
const secTxtRoot = path.join(resolvedPath, '.well-known', 'security.txt');
|
|
40
|
+
const hasSecTxt = fs.existsSync(secTxtPublic) || fs.existsSync(secTxtDist) || fs.existsSync(secTxtRoot);
|
|
41
|
+
results.push({
|
|
42
|
+
category: 'security',
|
|
43
|
+
name: 'security.txt present',
|
|
44
|
+
passed: hasSecTxt,
|
|
45
|
+
severity: 'blocker',
|
|
46
|
+
details: hasSecTxt
|
|
47
|
+
? 'security.txt file present in a .well-known/ directory (RFC 9116 fields not checked).'
|
|
48
|
+
: 'No security.txt found in public/, dist/, or root .well-known/ directories.',
|
|
49
|
+
});
|
|
50
|
+
// Check 4: Safe gitignore configuration
|
|
51
|
+
const gitignore = path.join(resolvedPath, '.gitignore');
|
|
52
|
+
const hasGitignore = fs.existsSync(gitignore);
|
|
53
|
+
let ignoresEnv = false;
|
|
54
|
+
if (hasGitignore) {
|
|
55
|
+
const gitignoreContent = fs.readFileSync(gitignore, 'utf-8');
|
|
56
|
+
ignoresEnv = gitignoreContent.includes('.env');
|
|
57
|
+
}
|
|
58
|
+
results.push({
|
|
59
|
+
category: 'security',
|
|
60
|
+
name: '.gitignore mentions .env',
|
|
61
|
+
passed: hasGitignore && ignoresEnv,
|
|
62
|
+
severity: 'blocker',
|
|
63
|
+
details: hasGitignore && ignoresEnv
|
|
64
|
+
? '.gitignore contains the text ".env" (ignore rules and other secret files not evaluated).'
|
|
65
|
+
: '.gitignore missing or does not mention .env (also ignore private keys and credentials).',
|
|
66
|
+
});
|
|
67
|
+
// Check 5: QA scripts in package.json
|
|
68
|
+
const pkgJsonPath = path.join(resolvedPath, 'package.json');
|
|
69
|
+
let hasQaStandard = false;
|
|
70
|
+
let hasTypeCheck = false;
|
|
71
|
+
if (fs.existsSync(pkgJsonPath)) {
|
|
72
|
+
try {
|
|
73
|
+
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'));
|
|
74
|
+
hasQaStandard = Boolean(pkg.scripts?.['qa:standard'] || pkg.scripts?.['qa:starter']);
|
|
75
|
+
hasTypeCheck = Boolean(pkg.scripts?.['type-check'] || pkg.scripts?.['tsc']);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// Ignored
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
results.push({
|
|
82
|
+
category: 'quality',
|
|
83
|
+
name: 'qa:starter or qa:standard script declared',
|
|
84
|
+
passed: hasQaStandard,
|
|
85
|
+
severity: 'blocker',
|
|
86
|
+
details: hasQaStandard
|
|
87
|
+
? 'package.json declares qa:starter or qa:standard (script not executed).'
|
|
88
|
+
: 'No qa:starter / qa:standard script in package.json.',
|
|
89
|
+
});
|
|
90
|
+
results.push({
|
|
91
|
+
category: 'quality',
|
|
92
|
+
name: 'type-check script declared',
|
|
93
|
+
passed: hasTypeCheck,
|
|
94
|
+
severity: 'blocker',
|
|
95
|
+
details: hasTypeCheck
|
|
96
|
+
? 'package.json declares a type-check script (script not executed).'
|
|
97
|
+
: 'No type-check or tsc script in package.json.',
|
|
98
|
+
});
|
|
99
|
+
const totalChecks = results.length;
|
|
100
|
+
const passedChecks = results.filter((r) => r.passed).length;
|
|
101
|
+
const failedChecks = totalChecks - passedChecks;
|
|
102
|
+
const score = Math.round((passedChecks / totalChecks) * 100);
|
|
103
|
+
const recommendations = [];
|
|
104
|
+
if (!hasAgentsMd) {
|
|
105
|
+
recommendations.push('Create an AGENTS.md in project root enforcing Fredo QA Skills rules for AI assistants.');
|
|
106
|
+
}
|
|
107
|
+
if (!hasSecTxt) {
|
|
108
|
+
recommendations.push('Generate public/.well-known/security.txt with valid Contact and Expires directives.');
|
|
109
|
+
}
|
|
110
|
+
if (!hasQaStandard) {
|
|
111
|
+
recommendations.push('Add "qa:starter" and "qa:standard" scripts to package.json to ensure local and CI parity.');
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
projectPath: resolvedPath,
|
|
115
|
+
timestamp: new Date().toISOString(),
|
|
116
|
+
score,
|
|
117
|
+
scope: AUDIT_SCOPE,
|
|
118
|
+
totalChecks,
|
|
119
|
+
passedChecks,
|
|
120
|
+
failedChecks,
|
|
121
|
+
results,
|
|
122
|
+
recommendations,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { LicenseValidationResult, SkillMetadata, SkillTier } from './types.js';
|
|
2
|
+
export declare const SKILLS_CATALOG: SkillMetadata[];
|
|
3
|
+
/**
|
|
4
|
+
* Filter skills by active license tier
|
|
5
|
+
*/
|
|
6
|
+
export declare function getAvailableSkills(userTier: SkillTier): SkillMetadata[];
|
|
7
|
+
/**
|
|
8
|
+
* Finds a skill by ID
|
|
9
|
+
*/
|
|
10
|
+
export declare function findSkill(id: string): SkillMetadata | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* Attempts to load the real SKILL.md from filesystem, or falls back to metadata
|
|
13
|
+
*/
|
|
14
|
+
export declare function loadSkillContent(skillId: string, searchDir?: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Loads or generates a compliant LICENSE file for a skill
|
|
17
|
+
*/
|
|
18
|
+
export declare function loadSkillLicense(skillId: string, license: LicenseValidationResult, searchDir?: string): string;
|
package/dist/catalog.js
ADDED
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 Frédéric Charles Viallet
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
import * as fs from 'node:fs';
|
|
4
|
+
import * as path from 'node:path';
|
|
5
|
+
import { resolveSkillLicense } from './license-templates.js';
|
|
6
|
+
export const SKILLS_CATALOG = [
|
|
7
|
+
// Free Foundation (MIT)
|
|
8
|
+
{
|
|
9
|
+
id: 'qa-core',
|
|
10
|
+
name: 'Core Quality Policy',
|
|
11
|
+
tier: 'free',
|
|
12
|
+
category: 'core',
|
|
13
|
+
description: 'Universal QA policy across stacks, standard profiles, and DoD checklists.',
|
|
14
|
+
rulesSummary: [
|
|
15
|
+
'Zero unhandled exceptions',
|
|
16
|
+
'Local/CI execution parity',
|
|
17
|
+
'Exception governance via .qa-exceptions.yaml',
|
|
18
|
+
],
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
id: 'dev-flow',
|
|
22
|
+
name: 'Engineering Development Flow',
|
|
23
|
+
tier: 'free',
|
|
24
|
+
category: 'core',
|
|
25
|
+
description: 'Disciplined development flow with risk-based planning and small vertical slices.',
|
|
26
|
+
rulesSummary: ['Atomic commits with provenance', 'TDD/BDD inner loop', 'Continuous validation'],
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: 'qa-python',
|
|
30
|
+
name: 'Python Quality Engineering',
|
|
31
|
+
tier: 'free',
|
|
32
|
+
category: 'language',
|
|
33
|
+
description: 'Strict typing (mypy), deterministic formatting (ruff), and branch coverage.',
|
|
34
|
+
rulesSummary: ['100% type coverage without Any', 'Ruff check & format', 'Pytest branch coverage >= 90%'],
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: 'qa-javascript-typescript',
|
|
38
|
+
name: 'JavaScript & TypeScript Quality',
|
|
39
|
+
tier: 'free',
|
|
40
|
+
category: 'language',
|
|
41
|
+
description: 'Strict type checking, Biome formatting, Vitest coverage, and Core Web Vitals.',
|
|
42
|
+
rulesSummary: ['tsc --noEmit clean', 'Biome check with zero debt', 'Coverage threshold enforcement'],
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
id: 'qa-php',
|
|
46
|
+
name: 'PHP Quality Engineering',
|
|
47
|
+
tier: 'free',
|
|
48
|
+
category: 'language',
|
|
49
|
+
description: 'PHPStan max level, Pint/PHP-CS-Fixer formatting, and boundary architecture.',
|
|
50
|
+
rulesSummary: [
|
|
51
|
+
'PHPStan level max',
|
|
52
|
+
'Hardened public forms (HMAC captcha, honeypot, rate limit)',
|
|
53
|
+
'Architecture boundaries',
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
id: 'qa-bash',
|
|
58
|
+
name: 'Bash & Shell Scripting',
|
|
59
|
+
tier: 'free',
|
|
60
|
+
category: 'language',
|
|
61
|
+
description: 'Safe POSIX defaults (set -euo pipefail), ShellCheck clean, and Bats testing.',
|
|
62
|
+
rulesSummary: ['set -euo pipefail', 'ShellCheck clean', 'shfmt formatted'],
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
id: 'qa-mcp',
|
|
66
|
+
name: 'Model Context Protocol Quality',
|
|
67
|
+
tier: 'free',
|
|
68
|
+
category: 'language',
|
|
69
|
+
description: 'Strict JSON Schema validation, JSON-RPC 2.0 contract tests, stdio isolation.',
|
|
70
|
+
rulesSummary: ['JSON-RPC 2.0 compliance', 'Stdio pollution prevention', 'Graceful error handling'],
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
id: 'qa-c-cpp',
|
|
74
|
+
name: 'C & C++ Systems Engineering',
|
|
75
|
+
tier: 'free',
|
|
76
|
+
category: 'language',
|
|
77
|
+
description: 'clangd LSP diagnostics, clang-tidy, cppcheck, sanitizers (ASan/UBSan/TSan), and memory safety.',
|
|
78
|
+
rulesSummary: ['clangd semantic validation', 'ASan/UBSan clean execution', 'Strict compiler warnings (-Werror)'],
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
id: 'qa-rust',
|
|
82
|
+
name: 'Rust Systems Engineering',
|
|
83
|
+
tier: 'free',
|
|
84
|
+
category: 'language',
|
|
85
|
+
description: 'Cargo check, Clippy with -D warnings, rustfmt, cargo-deny, cargo-audit, and Miri safety.',
|
|
86
|
+
rulesSummary: ['cargo clippy --all-targets -- -D warnings', 'cargo fmt --check', 'cargo deny check and cargo audit'],
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
id: 'qa-go',
|
|
90
|
+
name: 'Go Systems Engineering',
|
|
91
|
+
tier: 'free',
|
|
92
|
+
category: 'language',
|
|
93
|
+
description: 'golangci-lint, go test -race, govulncheck, gosec, and strict error handling.',
|
|
94
|
+
rulesSummary: ['golangci-lint run', 'go test -race ./...', 'govulncheck ./... and gosec'],
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
id: 'qa-java',
|
|
98
|
+
name: 'Java Enterprise Engineering',
|
|
99
|
+
tier: 'free',
|
|
100
|
+
category: 'language',
|
|
101
|
+
description: 'Checkstyle, SpotBugs, PMD, Error Prone, JaCoCo branch coverage >= 80%, and ArchUnit boundaries.',
|
|
102
|
+
rulesSummary: ['javac -Werror clean compile', 'SpotBugs & PMD zero violations', 'JaCoCo line & branch coverage >= 80%'],
|
|
103
|
+
},
|
|
104
|
+
// Pro Production (Commercial)
|
|
105
|
+
{
|
|
106
|
+
id: 'qa-accessibility',
|
|
107
|
+
name: 'Accessibility & WCAG 2.2',
|
|
108
|
+
tier: 'pro',
|
|
109
|
+
category: 'compliance',
|
|
110
|
+
description: 'Automated Axe-core testing, WCAG 2.2 AA/AAA baselines, and inclusive UX.',
|
|
111
|
+
rulesSummary: ['Zero Axe-core violations', 'Keyboard navigability', 'Semantic landmarks'],
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
id: 'qa-security',
|
|
115
|
+
name: 'Application Security & OWASP',
|
|
116
|
+
tier: 'pro',
|
|
117
|
+
category: 'compliance',
|
|
118
|
+
description: 'OWASP Top 10 prevention, dependency audits, CSP headers, and secret scanning.',
|
|
119
|
+
rulesSummary: [
|
|
120
|
+
'Dependency audit clean',
|
|
121
|
+
'CSP on every deploy variant; hosts = active integrations',
|
|
122
|
+
'Server-verified anti-bot for public forms',
|
|
123
|
+
],
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
id: 'qa-performance',
|
|
127
|
+
name: 'Performance & Core Web Vitals',
|
|
128
|
+
tier: 'pro',
|
|
129
|
+
category: 'quality',
|
|
130
|
+
description: 'Lighthouse budgets, LCP < 2.5s, INP < 200ms, CLS < 0.1, bundle optimization.',
|
|
131
|
+
rulesSummary: ['Lighthouse score >= 90', 'Strict performance budgets', 'Asset compression'],
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
id: 'qa-gdpr-rgpd',
|
|
135
|
+
name: 'GDPR / RGPD Privacy Engineering',
|
|
136
|
+
tier: 'pro',
|
|
137
|
+
category: 'compliance',
|
|
138
|
+
description: 'Privacy by design, CNIL public-web gates, consent parity, data subject rights (DSR), RoPA, and DPIA.',
|
|
139
|
+
rulesSummary: [
|
|
140
|
+
'Equal refuse/accept consent; no unconsented trackers',
|
|
141
|
+
'Art.13 forms + server-verified captcha + retain-until',
|
|
142
|
+
'RoPA/CSP/legal copy lockstep with processing flags',
|
|
143
|
+
],
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
id: 'qa-seo-website',
|
|
147
|
+
name: 'Technical SEO & Search Visibility',
|
|
148
|
+
tier: 'pro',
|
|
149
|
+
category: 'quality',
|
|
150
|
+
description: 'Pre-rendered metadata, JSON-LD structured data, canonical tags, GEO/AEO optimization.',
|
|
151
|
+
rulesSummary: ['Unique title and description per route', 'Valid Schema.org JSON-LD', 'Canonical tag parity'],
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
id: 'qa-well-known',
|
|
155
|
+
name: 'Well-Known URI Standards',
|
|
156
|
+
tier: 'pro',
|
|
157
|
+
category: 'compliance',
|
|
158
|
+
description: 'RFC 9116 security.txt validation, robots.txt, sitemap.xml, and IANA registry conformance.',
|
|
159
|
+
rulesSummary: ['Valid security.txt syntax', 'Canonical link directive', 'Future expiry date'],
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
id: 'qa-emails-dns',
|
|
163
|
+
name: 'Email & DNS Security',
|
|
164
|
+
tier: 'pro',
|
|
165
|
+
category: 'compliance',
|
|
166
|
+
description: 'SPF, DKIM, DMARC p=reject, BIMI assertions, and DNS drift detection.',
|
|
167
|
+
rulesSummary: [
|
|
168
|
+
'DMARC p=quarantine or reject',
|
|
169
|
+
'X-Retain-Until on personal-data operator mail',
|
|
170
|
+
'BIMI indicator validation',
|
|
171
|
+
],
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
id: 'qa-cnil',
|
|
175
|
+
name: 'CNIL RGPD Article 30 Processing Register',
|
|
176
|
+
tier: 'pro',
|
|
177
|
+
category: 'compliance',
|
|
178
|
+
description: 'Automated CNIL Article 30 Records of Processing Activities (RoPA) extraction, JSON pivot, and ODS export.',
|
|
179
|
+
rulesSummary: [
|
|
180
|
+
'Automated personal data mapping',
|
|
181
|
+
'Article 30.1 Controller and 30.2 Processor register separation',
|
|
182
|
+
'Official CNIL OpenDocument Spreadsheet (.ods) export',
|
|
183
|
+
],
|
|
184
|
+
},
|
|
185
|
+
// Enterprise Assurance (Enterprise)
|
|
186
|
+
{
|
|
187
|
+
id: 'qa-devops',
|
|
188
|
+
name: 'DevOps & CI/CD Security',
|
|
189
|
+
tier: 'enterprise',
|
|
190
|
+
category: 'compliance',
|
|
191
|
+
description: 'GitHub Actions hardening, Dockerfile linting, container security, and IaC scanning.',
|
|
192
|
+
rulesSummary: ['Pinned Action SHAs', 'Trivy container scan clean', 'Least-privilege tokens'],
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
id: 'qa-ai-infrastructure-compliance',
|
|
196
|
+
name: 'AI Infrastructure & NIS2 Compliance',
|
|
197
|
+
tier: 'enterprise',
|
|
198
|
+
category: 'compliance',
|
|
199
|
+
description: 'ISO 42001, NIS2 Directive mapping, EU AI Act risk classification, SOC2 Type II.',
|
|
200
|
+
rulesSummary: ['AI risk tiering documented', 'NIS2 incident notification readiness', 'Auditable evidence export'],
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
id: 'qa-cra-software-supply-chain',
|
|
204
|
+
name: 'CRA & Supply Chain Assurance',
|
|
205
|
+
tier: 'enterprise',
|
|
206
|
+
category: 'compliance',
|
|
207
|
+
description: 'EU CRA compliance, CycloneDX/SPDX SBOMs, SLSA Level 3 provenance, and Sigstore signing.',
|
|
208
|
+
rulesSummary: ['CycloneDX v1.6 SBOM generated', 'SLSA Level 3 provenance verified', 'VEX statements published'],
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
id: 'qa-pci-dss',
|
|
212
|
+
name: 'PCI-DSS v4.0 Payment Security',
|
|
213
|
+
tier: 'enterprise',
|
|
214
|
+
category: 'compliance',
|
|
215
|
+
description: 'Cardholder Data Environment isolation, client-side tokenization, PAN masking, and audit trails.',
|
|
216
|
+
rulesSummary: ['Zero SAD/CVV retention', 'Client-side payment tokenization', 'Strict PAN masking'],
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
id: 'qa-health-data-compliance',
|
|
220
|
+
name: 'Health Data (HDS & HIPAA)',
|
|
221
|
+
tier: 'enterprise',
|
|
222
|
+
category: 'compliance',
|
|
223
|
+
description: 'French HDS v2.0, HIPAA Security Rule, HL7 FHIR validation, and PHI pseudonymization.',
|
|
224
|
+
rulesSummary: ['Envelope encryption with HSM', 'HL7 FHIR SMART-on-FHIR scopes', 'Immutable access audit logging'],
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
id: 'qa-enterprise-iam-sso',
|
|
228
|
+
name: 'Enterprise IAM & SSO Federation',
|
|
229
|
+
tier: 'enterprise',
|
|
230
|
+
category: 'compliance',
|
|
231
|
+
description: 'SAML 2.0 XML signatures, OIDC with PKCE, SCIM 2.0 provisioning, and multi-tenant isolation.',
|
|
232
|
+
rulesSummary: ['SAML XML signature & replay check', 'SCIM instant deprovisioning', 'Multi-tenant isolation verified'],
|
|
233
|
+
},
|
|
234
|
+
];
|
|
235
|
+
/**
|
|
236
|
+
* Filter skills by active license tier
|
|
237
|
+
*/
|
|
238
|
+
export function getAvailableSkills(userTier) {
|
|
239
|
+
if (userTier === 'enterprise') {
|
|
240
|
+
return SKILLS_CATALOG;
|
|
241
|
+
}
|
|
242
|
+
if (userTier === 'pro') {
|
|
243
|
+
return SKILLS_CATALOG.filter((s) => s.tier === 'free' || s.tier === 'pro');
|
|
244
|
+
}
|
|
245
|
+
// Free tier
|
|
246
|
+
return SKILLS_CATALOG.filter((s) => s.tier === 'free');
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Finds a skill by ID
|
|
250
|
+
*/
|
|
251
|
+
export function findSkill(id) {
|
|
252
|
+
return SKILLS_CATALOG.find((s) => s.id === id);
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Attempts to load the real SKILL.md from filesystem, or falls back to metadata
|
|
256
|
+
*/
|
|
257
|
+
export function loadSkillContent(skillId, searchDir) {
|
|
258
|
+
const meta = findSkill(skillId);
|
|
259
|
+
if (!meta) {
|
|
260
|
+
throw new Error(`Unknown skill: ${skillId}`);
|
|
261
|
+
}
|
|
262
|
+
// Look for actual file on disk if available
|
|
263
|
+
const candidatePaths = [
|
|
264
|
+
path.join(searchDir || process.cwd(), 'skills', 'free', skillId, 'SKILL.md'),
|
|
265
|
+
path.join(searchDir || process.cwd(), 'skills', 'pro', skillId, 'SKILL.md'),
|
|
266
|
+
path.join(searchDir || process.cwd(), 'skills', 'enterprise', skillId, 'SKILL.md'),
|
|
267
|
+
path.join(searchDir || process.cwd(), 'skills', skillId, 'SKILL.md'),
|
|
268
|
+
path.join(searchDir || process.cwd(), '.agents', 'skills', skillId, 'SKILL.md'),
|
|
269
|
+
];
|
|
270
|
+
for (const p of candidatePaths) {
|
|
271
|
+
if (fs.existsSync(p)) {
|
|
272
|
+
try {
|
|
273
|
+
return fs.readFileSync(p, 'utf-8');
|
|
274
|
+
}
|
|
275
|
+
catch {
|
|
276
|
+
// Fallback
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
// Generate synthetic structured directives if file not directly on disk
|
|
281
|
+
return `# Skill: ${meta.name} (${meta.id})
|
|
282
|
+
Category: ${meta.category}
|
|
283
|
+
Tier: ${meta.tier.toUpperCase()}
|
|
284
|
+
|
|
285
|
+
## Description
|
|
286
|
+
${meta.description}
|
|
287
|
+
|
|
288
|
+
## Mandatory QA Rules & Quality Gates
|
|
289
|
+
${meta.rulesSummary.map((r, i) => `${i + 1}. **${r}**`).join('\n')}
|
|
290
|
+
|
|
291
|
+
## Inner Loop Commands
|
|
292
|
+
- Run \`pnpm run qa:starter\` or equivalent inner-loop test before committing.
|
|
293
|
+
- Run \`pnpm run qa:standard\` before submitting merge requests.
|
|
294
|
+
- Adhere strictly to zero-hidden-debt principles. Suppressions without documented justification in \`.qa-exceptions.yaml\` are rejected.
|
|
295
|
+
`;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Loads or generates a compliant LICENSE file for a skill
|
|
299
|
+
*/
|
|
300
|
+
export function loadSkillLicense(skillId, license, searchDir) {
|
|
301
|
+
const meta = findSkill(skillId);
|
|
302
|
+
if (!meta) {
|
|
303
|
+
throw new Error(`Unknown skill: ${skillId}`);
|
|
304
|
+
}
|
|
305
|
+
return resolveSkillLicense(meta, license, searchDir);
|
|
306
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type LicenseOptions } from './license.js';
|
|
2
|
+
export declare class ToolExecutor {
|
|
3
|
+
static execute(name: string, args: Record<string, unknown>, activeLicenseKey: string | undefined, onLicenseUpdate: (key: string) => void, licenseOptions?: LicenseOptions): string;
|
|
4
|
+
}
|