@agentlee5/agent-skills 1.0.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/.leeway/config.json +133 -0
- package/LICENSE +21 -0
- package/LeeWay-Standards/LICENSE +21 -0
- package/LeeWay-Standards/README.md +324 -0
- package/LeeWay-Standards/examples/NexusButton.tsx +90 -0
- package/LeeWay-Standards/examples/example-agent.js +89 -0
- package/LeeWay-Standards/package.json +61 -0
- package/LeeWay-Standards/schemas/leeway-config.schema.json +81 -0
- package/LeeWay-Standards/schemas/leeway-header.schema.json +63 -0
- package/LeeWay-Standards/src/agents/discovery/architecture-map-agent.js +134 -0
- package/LeeWay-Standards/src/agents/discovery/docs-agent.js +126 -0
- package/LeeWay-Standards/src/agents/discovery/explain-agent.js +95 -0
- package/LeeWay-Standards/src/agents/discovery/intent-registry-agent.js +119 -0
- package/LeeWay-Standards/src/agents/discovery/schema-agent.js +116 -0
- package/LeeWay-Standards/src/agents/discovery/sitemap-agent.js +88 -0
- package/LeeWay-Standards/src/agents/governance/align-agent.js +155 -0
- package/LeeWay-Standards/src/agents/governance/assess-agent.js +161 -0
- package/LeeWay-Standards/src/agents/governance/audit-agent.js +185 -0
- package/LeeWay-Standards/src/agents/integrity/circular-dependency-agent.js +88 -0
- package/LeeWay-Standards/src/agents/integrity/dependency-graph-agent.js +107 -0
- package/LeeWay-Standards/src/agents/integrity/duplicate-logic-agent.js +108 -0
- package/LeeWay-Standards/src/agents/integrity/import-agent.js +83 -0
- package/LeeWay-Standards/src/agents/integrity/module-policy-agent.js +94 -0
- package/LeeWay-Standards/src/agents/integrity/refactor-scan-agent.js +113 -0
- package/LeeWay-Standards/src/agents/integrity/syntax-agent.js +84 -0
- package/LeeWay-Standards/src/agents/mcp/endpoint-agent.js +106 -0
- package/LeeWay-Standards/src/agents/mcp/env-agent.js +111 -0
- package/LeeWay-Standards/src/agents/mcp/health-agent-lite.js +119 -0
- package/LeeWay-Standards/src/agents/mcp/manifest-agent.js +87 -0
- package/LeeWay-Standards/src/agents/mcp/port-agent.js +125 -0
- package/LeeWay-Standards/src/agents/mcp/process-agent.js +124 -0
- package/LeeWay-Standards/src/agents/mcp/runtime-agent.js +108 -0
- package/LeeWay-Standards/src/agents/mcp/transport-agent.js +78 -0
- package/LeeWay-Standards/src/agents/orchestration/doctor-agent.js +149 -0
- package/LeeWay-Standards/src/agents/orchestration/memory-agent-lite.js +125 -0
- package/LeeWay-Standards/src/agents/orchestration/router-agent.js +110 -0
- package/LeeWay-Standards/src/agents/security/permission-agent.js +98 -0
- package/LeeWay-Standards/src/agents/security/policy-agent.js +100 -0
- package/LeeWay-Standards/src/agents/security/privacy-agent.js +83 -0
- package/LeeWay-Standards/src/agents/security/prompt-security-agent.js +103 -0
- package/LeeWay-Standards/src/agents/security/secret-scan-agent.js +108 -0
- package/LeeWay-Standards/src/agents/security/tool-access-agent.js +105 -0
- package/LeeWay-Standards/src/agents/standards/authority-agent.js +114 -0
- package/LeeWay-Standards/src/agents/standards/discovery-pipeline-agent.js +91 -0
- package/LeeWay-Standards/src/agents/standards/header-agent.js +120 -0
- package/LeeWay-Standards/src/agents/standards/placement-agent.js +96 -0
- package/LeeWay-Standards/src/agents/standards/region-agent.js +99 -0
- package/LeeWay-Standards/src/agents/standards/registry-agent.js +153 -0
- package/LeeWay-Standards/src/agents/standards/tag-agent.js +111 -0
- package/LeeWay-Standards/src/cli/leeway.js +225 -0
- package/LeeWay-Standards/src/core/compliance-scorer.js +168 -0
- package/LeeWay-Standards/src/core/compliance-scorer.test.js +121 -0
- package/LeeWay-Standards/src/core/header-parser.js +207 -0
- package/LeeWay-Standards/src/core/header-parser.test.js +198 -0
- package/LeeWay-Standards/src/core/region-classifier.js +137 -0
- package/LeeWay-Standards/src/core/region-classifier.test.js +100 -0
- package/LeeWay-Standards/src/core/tag-validator.js +139 -0
- package/LeeWay-Standards/src/core/tag-validator.test.js +109 -0
- package/LeeWay-Standards/src/index.js +83 -0
- package/README.md +217 -0
- package/agent-config.yaml +456 -0
- package/agentbage.png.png +0 -0
- package/bin/leeway-skills-badge.js +52 -0
- package/bin/leeway-skills-mcp.js +48 -0
- package/bin/leeway-skills.js +160 -0
- package/bin/leeway-standards.js +49 -0
- package/config/.skillsignore +63 -0
- package/config/skills-config.json +70 -0
- package/documents/AGENT_LEARNING_REFERENCE.md +329 -0
- package/documents/AGENT_LEE_INTEGRATION.md +534 -0
- package/documents/COMPLETE_SYSTEM_OVERVIEW.md +502 -0
- package/documents/COMPREHENSIVE_SKILL_INTEGRATION_PLAN.md +644 -0
- package/documents/DIRECTORY_MAP.md +323 -0
- package/documents/EXTENDING.md +514 -0
- package/documents/FILE_DIRECTORY_GUIDE.md +427 -0
- package/documents/LEEWAY_BADGE_INTEGRATION.md +76 -0
- package/documents/LEEWAY_IMPLEMENTATION_SUMMARY.md +384 -0
- package/documents/LEEWAY_INTEGRATION_GUIDE.md +414 -0
- package/documents/LEEWAY_NPM_SDK.md +66 -0
- package/documents/LEEWAY_QUICK_START.md +288 -0
- package/documents/LEEWAY_SKILLS_BRANDING.md +375 -0
- package/documents/LEEWAY_SKILLS_MCP_SUMMARY.md +593 -0
- package/documents/LEEWAY_STANDARDS_COMPLIANCE.md +361 -0
- package/documents/LEEWAY_UNIFIED_ARCHITECTURE.md +473 -0
- package/documents/LEEWAY_WORKFLOWS_QUICK_REFERENCE.md +307 -0
- package/documents/LEEWAY_WORKFLOWS_STRATEGIC_PLAN.md +515 -0
- package/documents/LIFELONG_LEARNING_LAYER.md +478 -0
- package/documents/MCP_ARCHITECTURE.md +683 -0
- package/documents/QUICK_REFERENCE.md +301 -0
- package/documents/SETUP.md +325 -0
- package/documents/SETUP_SUMMARY.md +413 -0
- package/documents/SKILL_ACQUISITION_EXECUTIVE_SUMMARY.md +373 -0
- package/documents/SKILL_ACQUISITION_IMPLEMENTATION.md +692 -0
- package/documents/SKILL_ACQUISITION_MANIFEST.md +404 -0
- package/documents/SKILL_ACQUISITION_QUICK_REFERENCE.md +349 -0
- package/documents/SKILL_WORKFLOW_COMPOSITION_MATRIX.md +537 -0
- package/documents/STRUCTURE.md +382 -0
- package/documents/SYSTEM_TRANSFORMATION_SUMMARY.md +560 -0
- package/documents/USAGE.md +390 -0
- package/documents/WORKFLOW_ACQUISITION_MANIFEST.md +576 -0
- package/documents/aiskills.txt +460 -0
- package/mcp-server/README.md +697 -0
- package/mcp-server/dist/badge-proof.d.ts +66 -0
- package/mcp-server/dist/badge-proof.d.ts.map +1 -0
- package/mcp-server/dist/badge-proof.js +324 -0
- package/mcp-server/dist/badge-proof.js.map +1 -0
- package/mcp-server/dist/index.d.ts +64 -0
- package/mcp-server/dist/index.d.ts.map +1 -0
- package/mcp-server/dist/index.js +263 -0
- package/mcp-server/dist/index.js.map +1 -0
- package/mcp-server/dist/install-badge-proof.d.ts +3 -0
- package/mcp-server/dist/install-badge-proof.d.ts.map +1 -0
- package/mcp-server/dist/install-badge-proof.js +109 -0
- package/mcp-server/dist/install-badge-proof.js.map +1 -0
- package/mcp-server/package.json +43 -0
- package/mcp-server/src/badge-proof.ts +469 -0
- package/mcp-server/src/index.ts +355 -0
- package/mcp-server/src/install-badge-proof.ts +132 -0
- package/mcp-server/tsconfig.json +22 -0
- package/package.json +84 -0
- package/scripts/init-leeway.js +217 -0
- package/scripts/leeway-agents/compliance-monitor.js +374 -0
- package/scripts/leeway-agents/header-injector.js +321 -0
- package/scripts/skill-integration-toolkit.py +319 -0
- package/scripts/skills-registry.json +1117 -0
- package/scripts/sync-skills.ps1 +275 -0
- package/scripts/verify-leeway-setup.js +249 -0
- package/scripts/workflow-integration-toolkit.py +522 -0
- package/sdk/application-installer.js +92 -0
- package/sdk/index.js +43 -0
- package/sdk/paths.js +167 -0
- package/skills/agent-autonomy/autonomous-conductor/SKILL.md +206 -0
- package/skills/agent-autonomy/full-stack-delivery/SKILL.md +206 -0
- package/skills/agent-orchestration/multi-agent-orchestration/SKILL.md +68 -0
- package/skills/agent-patterns/agent-design-patterns/SKILL.md +70 -0
- package/skills/ai-ml/llm-prompting/SKILL.md +71 -0
- package/skills/ai-ml/ml-model-development/SKILL.md +67 -0
- package/skills/ai-ml/multimodal-systems/SKILL.md +71 -0
- package/skills/ai-ml/retrieval-generation-fine-tuning/SKILL.md +71 -0
- package/skills/architecture/system-design/SKILL.md +67 -0
- package/skills/code-analysis/refactoring/SKILL.md +64 -0
- package/skills/code-analysis/security-vulnerability-scanning/SKILL.md +71 -0
- package/skills/code-analysis/static-analysis/SKILL.md +64 -0
- package/skills/code-generation/full-stack-application/SKILL.md +70 -0
- package/skills/code-generation/microservices-architecture/SKILL.md +71 -0
- package/skills/code-generation/python-codegen/SKILL.md +64 -0
- package/skills/code-generation/typescript-codegen/SKILL.md +64 -0
- package/skills/data-analysis/advanced-analytics/SKILL.md +71 -0
- package/skills/data-analysis/pandas-analysis/SKILL.md +66 -0
- package/skills/database-design/database-design-optimization/SKILL.md +70 -0
- package/skills/debugging/javascript-debugging/SKILL.md +67 -0
- package/skills/debugging/python-debugging/SKILL.md +67 -0
- package/skills/devops/dockerfile-creation/SKILL.md +64 -0
- package/skills/devops/kubernetes-deployment/SKILL.md +65 -0
- package/skills/documentation/api-documentation/SKILL.md +67 -0
- package/skills/error-handling/resilience-patterns/SKILL.md +70 -0
- package/skills/git-workflow/git-collaboration/SKILL.md +67 -0
- package/skills/infrastructure/cicd-pipelines/SKILL.md +70 -0
- package/skills/infrastructure/infrastructure-as-code/SKILL.md +70 -0
- package/skills/observability/monitoring-and-observability/SKILL.md +70 -0
- package/skills/performance-optimization/performance-engineering/SKILL.md +70 -0
- package/skills/prompt-optimization/prompt-engineering-advanced/SKILL.md +70 -0
- package/skills/quality-assurance/deployment-validator/SKILL.md +382 -0
- package/skills/quality-assurance/web-security-sweep/SKILL.md +320 -0
- package/skills/rag-knowledge/rag-systems/SKILL.md +70 -0
- package/skills/research/knowledge-synthesis/SKILL.md +71 -0
- package/skills/security/authentication-authorization/SKILL.md +71 -0
- package/skills/security/code-security/SKILL.md +66 -0
- package/skills/security/secure-architecture/SKILL.md +71 -0
- package/skills/self-optimization/dev-loop-optimizer/SKILL.md +344 -0
- package/skills/self-optimization/memory-learning/SKILL.md +335 -0
- package/skills/self-optimization/runtime-self-profiling/SKILL.md +250 -0
- package/skills/testing/advanced-testing-strategies/SKILL.md +71 -0
- package/skills/testing/integration-testing/SKILL.md +66 -0
- package/skills/testing/load-testing-capacity/SKILL.md +71 -0
- package/skills/testing/unit-testing/SKILL.md +66 -0
- package/skills/tool-integration/custom-tool-creation/SKILL.md +70 -0
- package/skills/web-development/advanced-frontend-patterns/SKILL.md +71 -0
- package/skills/web-development/api-design/SKILL.md +71 -0
- package/skills/web-development/css-styling/SKILL.md +67 -0
- package/skills/web-development/react-development/SKILL.md +79 -0
- package/skills/workflow-composition/workflow-orchestration/SKILL.md +70 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/*
|
|
2
|
+
LEEWAY HEADER — DO NOT REMOVE
|
|
3
|
+
|
|
4
|
+
REGION: MCP.AGENT.RUNTIME
|
|
5
|
+
TAG: MCP.RUNTIME.AGENT.MAIN
|
|
6
|
+
|
|
7
|
+
COLOR_ONION_HEX:
|
|
8
|
+
NEON=#39FF14
|
|
9
|
+
FLUO=#0DFF94
|
|
10
|
+
PASTEL=#C7FFD8
|
|
11
|
+
|
|
12
|
+
ICON_ASCII:
|
|
13
|
+
family=lucide
|
|
14
|
+
glyph=zap
|
|
15
|
+
|
|
16
|
+
5WH:
|
|
17
|
+
WHAT = Runtime agent — checks module and runtime compatibility before build and start
|
|
18
|
+
WHY = Runtime version mismatches cause failures that are difficult to diagnose in CI
|
|
19
|
+
WHO = Rapid Web Development
|
|
20
|
+
WHERE = src/agents/mcp/runtime-agent.js
|
|
21
|
+
WHEN = 2026
|
|
22
|
+
HOW = Reads package.json engines field and compares against current Node version
|
|
23
|
+
|
|
24
|
+
AGENTS:
|
|
25
|
+
RUNTIME
|
|
26
|
+
ENV
|
|
27
|
+
ALIGN
|
|
28
|
+
|
|
29
|
+
LICENSE:
|
|
30
|
+
MIT
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import { readFile } from 'node:fs/promises';
|
|
34
|
+
import { join } from 'node:path';
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* RuntimeAgent checks module type compatibility and Node.js version requirements.
|
|
38
|
+
*/
|
|
39
|
+
export class RuntimeAgent {
|
|
40
|
+
constructor(options = {}) {
|
|
41
|
+
this.rootDir = options.rootDir || process.cwd();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Check runtime compatibility for the current project.
|
|
46
|
+
* @returns {Promise<RuntimeCheckResult>}
|
|
47
|
+
*/
|
|
48
|
+
async check() {
|
|
49
|
+
const issues = [];
|
|
50
|
+
const info = {
|
|
51
|
+
nodeVersion: process.version,
|
|
52
|
+
platform: process.platform,
|
|
53
|
+
arch: process.arch,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
let pkg = null;
|
|
57
|
+
try {
|
|
58
|
+
const raw = await readFile(join(this.rootDir, 'package.json'), 'utf8');
|
|
59
|
+
pkg = JSON.parse(raw);
|
|
60
|
+
} catch {
|
|
61
|
+
issues.push('Cannot read package.json');
|
|
62
|
+
return { valid: false, issues, info };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
info.packageName = pkg.name;
|
|
66
|
+
info.packageVersion = pkg.version;
|
|
67
|
+
info.moduleType = pkg.type || 'commonjs';
|
|
68
|
+
|
|
69
|
+
if (pkg.engines?.node) {
|
|
70
|
+
const required = pkg.engines.node;
|
|
71
|
+
const current = process.version.replace('v', '');
|
|
72
|
+
const compatible = this._semverSatisfies(current, required);
|
|
73
|
+
if (!compatible) {
|
|
74
|
+
issues.push(`Node.js ${process.version} does not satisfy required ${required}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const moduleIssues = await this._checkModuleConsistency(pkg);
|
|
79
|
+
issues.push(...moduleIssues);
|
|
80
|
+
|
|
81
|
+
return { valid: issues.length === 0, issues, info };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async _checkModuleConsistency(pkg) {
|
|
85
|
+
const issues = [];
|
|
86
|
+
const declaredType = pkg.type || 'commonjs';
|
|
87
|
+
|
|
88
|
+
if (declaredType === 'module') {
|
|
89
|
+
if (pkg.main && !pkg.main.endsWith('.mjs') && !pkg.main.endsWith('.js')) {
|
|
90
|
+
issues.push('Package type is "module" but main entry does not use .js or .mjs');
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return issues;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
_semverSatisfies(version, range) {
|
|
98
|
+
const cleanVersion = version.replace(/[^0-9.]/g, '').split('.').map(Number);
|
|
99
|
+
const rangeMatch = range.match(/[><=!^~]*([\d.]+)/);
|
|
100
|
+
if (!rangeMatch) return true;
|
|
101
|
+
|
|
102
|
+
const [major, minor = 0] = rangeMatch[1].split('.').map(Number);
|
|
103
|
+
if (range.startsWith('>=')) return cleanVersion[0] > major || (cleanVersion[0] === major && cleanVersion[1] >= minor);
|
|
104
|
+
if (range.startsWith('>')) return cleanVersion[0] > major || (cleanVersion[0] === major && cleanVersion[1] > minor);
|
|
105
|
+
if (range.startsWith('^')) return cleanVersion[0] === major && cleanVersion[1] >= minor;
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/*
|
|
2
|
+
LEEWAY HEADER — DO NOT REMOVE
|
|
3
|
+
|
|
4
|
+
REGION: MCP.AGENT.TRANSPORT
|
|
5
|
+
TAG: MCP.TRANSPORT.AGENT.MAIN
|
|
6
|
+
|
|
7
|
+
COLOR_ONION_HEX:
|
|
8
|
+
NEON=#39FF14
|
|
9
|
+
FLUO=#0DFF94
|
|
10
|
+
PASTEL=#C7FFD8
|
|
11
|
+
|
|
12
|
+
ICON_ASCII:
|
|
13
|
+
family=lucide
|
|
14
|
+
glyph=activity
|
|
15
|
+
|
|
16
|
+
5WH:
|
|
17
|
+
WHAT = Transport agent — verifies approved MCP transport usage
|
|
18
|
+
WHY = MCP transport mismatches cause silent failures and security violations
|
|
19
|
+
WHO = Rapid Web Development
|
|
20
|
+
WHERE = src/agents/mcp/transport-agent.js
|
|
21
|
+
WHEN = 2026
|
|
22
|
+
HOW = Checks transport declarations in manifests and source for approved protocols
|
|
23
|
+
|
|
24
|
+
AGENTS:
|
|
25
|
+
TRANSPORT
|
|
26
|
+
ENDPOINT
|
|
27
|
+
|
|
28
|
+
LICENSE:
|
|
29
|
+
MIT
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
const APPROVED_TRANSPORTS = ['stdio', 'http', 'sse', 'websocket'];
|
|
33
|
+
const DEPRECATED_TRANSPORTS = ['xmlrpc', 'soap', 'raw-tcp'];
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* TransportAgent verifies that only approved MCP transport protocols are used.
|
|
37
|
+
*/
|
|
38
|
+
export class TransportAgent {
|
|
39
|
+
constructor(options = {}) {
|
|
40
|
+
this.approvedTransports = options.approvedTransports || APPROVED_TRANSPORTS;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Check if a transport is approved.
|
|
45
|
+
*
|
|
46
|
+
* @param {string} transport
|
|
47
|
+
* @returns {{ approved: boolean, deprecated: boolean, reason: string }}
|
|
48
|
+
*/
|
|
49
|
+
check(transport) {
|
|
50
|
+
const t = (transport || '').toLowerCase().trim();
|
|
51
|
+
if (this.approvedTransports.includes(t)) {
|
|
52
|
+
return { approved: true, deprecated: false, reason: `Transport "${t}" is approved` };
|
|
53
|
+
}
|
|
54
|
+
if (DEPRECATED_TRANSPORTS.includes(t)) {
|
|
55
|
+
return { approved: false, deprecated: true, reason: `Transport "${t}" is deprecated and not allowed` };
|
|
56
|
+
}
|
|
57
|
+
return { approved: false, deprecated: false, reason: `Transport "${t}" is not in the approved list: ${this.approvedTransports.join(', ')}` };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Scan manifest object for transport declarations.
|
|
62
|
+
*
|
|
63
|
+
* @param {object} manifest
|
|
64
|
+
* @returns {{ valid: boolean, issues: string[] }}
|
|
65
|
+
*/
|
|
66
|
+
validateManifest(manifest) {
|
|
67
|
+
const issues = [];
|
|
68
|
+
const transports = manifest?.transports || manifest?.transport ? [manifest.transport] : [];
|
|
69
|
+
|
|
70
|
+
for (const t of transports) {
|
|
71
|
+
if (!t) continue;
|
|
72
|
+
const result = this.check(typeof t === 'string' ? t : t.type);
|
|
73
|
+
if (!result.approved) issues.push(result.reason);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return { valid: issues.length === 0, issues };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/*
|
|
2
|
+
LEEWAY HEADER — DO NOT REMOVE
|
|
3
|
+
|
|
4
|
+
REGION: AI.AGENT.ORCHESTRATION
|
|
5
|
+
TAG: AI.AGENT.DOCTOR.MAIN
|
|
6
|
+
|
|
7
|
+
COLOR_ONION_HEX:
|
|
8
|
+
NEON=#39FF14
|
|
9
|
+
FLUO=#0DFF94
|
|
10
|
+
PASTEL=#C7FFD8
|
|
11
|
+
|
|
12
|
+
ICON_ASCII:
|
|
13
|
+
family=lucide
|
|
14
|
+
glyph=stethoscope
|
|
15
|
+
|
|
16
|
+
5WH:
|
|
17
|
+
WHAT = Doctor agent — runs a full system health and compliance diagnosis
|
|
18
|
+
WHY = The entire LEEWAY system must be diagnosable in a single command
|
|
19
|
+
WHO = Rapid Web Development
|
|
20
|
+
WHERE = src/agents/orchestration/doctor-agent.js
|
|
21
|
+
WHEN = 2026
|
|
22
|
+
HOW = Orchestrates assess, audit, runtime, env, and health checks into one unified report
|
|
23
|
+
|
|
24
|
+
AGENTS:
|
|
25
|
+
DOCTOR
|
|
26
|
+
ASSESS
|
|
27
|
+
AUDIT
|
|
28
|
+
HEALTH
|
|
29
|
+
ENV
|
|
30
|
+
RUNTIME
|
|
31
|
+
|
|
32
|
+
LICENSE:
|
|
33
|
+
MIT
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
import { AssessAgent } from '../governance/assess-agent.js';
|
|
37
|
+
import { AuditAgent } from '../governance/audit-agent.js';
|
|
38
|
+
import { RuntimeAgent } from '../mcp/runtime-agent.js';
|
|
39
|
+
import { EnvAgent } from '../mcp/env-agent.js';
|
|
40
|
+
import { HealthAgentLite } from '../mcp/health-agent-lite.js';
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* DoctorAgent orchestrates a full system health and compliance diagnosis.
|
|
44
|
+
*/
|
|
45
|
+
export class DoctorAgent {
|
|
46
|
+
constructor(options = {}) {
|
|
47
|
+
this.rootDir = options.rootDir || process.cwd();
|
|
48
|
+
this.options = options;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Run a full system diagnosis.
|
|
53
|
+
* @returns {Promise<DiagnosisReport>}
|
|
54
|
+
*/
|
|
55
|
+
async run() {
|
|
56
|
+
const startTime = Date.now();
|
|
57
|
+
const report = {
|
|
58
|
+
agent: 'doctor-agent',
|
|
59
|
+
rootDir: this.rootDir,
|
|
60
|
+
timestamp: new Date().toISOString(),
|
|
61
|
+
checks: {},
|
|
62
|
+
summary: {},
|
|
63
|
+
healthy: true,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const assess = new AssessAgent({ rootDir: this.rootDir });
|
|
67
|
+
const audit = new AuditAgent({ rootDir: this.rootDir });
|
|
68
|
+
const runtime = new RuntimeAgent({ rootDir: this.rootDir });
|
|
69
|
+
const env = new EnvAgent({ rootDir: this.rootDir });
|
|
70
|
+
const health = HealthAgentLite.withSystemChecks();
|
|
71
|
+
|
|
72
|
+
const [assessResult, auditResult, runtimeResult, envResult, healthResult] = await Promise.allSettled([
|
|
73
|
+
assess.run(),
|
|
74
|
+
audit.run(),
|
|
75
|
+
runtime.check(),
|
|
76
|
+
env.validate(),
|
|
77
|
+
health.run(),
|
|
78
|
+
]);
|
|
79
|
+
|
|
80
|
+
report.checks.assessment = assessResult.status === 'fulfilled'
|
|
81
|
+
? { status: 'pass', data: assessResult.value.summary }
|
|
82
|
+
: { status: 'error', error: assessResult.reason?.message };
|
|
83
|
+
|
|
84
|
+
report.checks.compliance = auditResult.status === 'fulfilled'
|
|
85
|
+
? {
|
|
86
|
+
status: auditResult.value.summary.averageScore >= 60 ? 'pass' : 'warn',
|
|
87
|
+
score: auditResult.value.summary.averageScore,
|
|
88
|
+
level: auditResult.value.summary.complianceLevel,
|
|
89
|
+
}
|
|
90
|
+
: { status: 'error', error: auditResult.reason?.message };
|
|
91
|
+
|
|
92
|
+
report.checks.runtime = runtimeResult.status === 'fulfilled'
|
|
93
|
+
? { status: runtimeResult.value.valid ? 'pass' : 'fail', issues: runtimeResult.value.issues }
|
|
94
|
+
: { status: 'error', error: runtimeResult.reason?.message };
|
|
95
|
+
|
|
96
|
+
report.checks.environment = envResult.status === 'fulfilled'
|
|
97
|
+
? { status: envResult.value.valid ? 'pass' : 'warn', missing: envResult.value.missing }
|
|
98
|
+
: { status: 'error', error: envResult.reason?.message };
|
|
99
|
+
|
|
100
|
+
report.checks.system = healthResult.status === 'fulfilled'
|
|
101
|
+
? { status: healthResult.value.healthy ? 'pass' : 'fail', summary: healthResult.value.summary }
|
|
102
|
+
: { status: 'error', error: healthResult.reason?.message };
|
|
103
|
+
|
|
104
|
+
const statuses = Object.values(report.checks).map(c => c.status);
|
|
105
|
+
report.healthy = !statuses.includes('fail') && !statuses.includes('error');
|
|
106
|
+
report.durationMs = Date.now() - startTime;
|
|
107
|
+
|
|
108
|
+
const passCount = statuses.filter(s => s === 'pass').length;
|
|
109
|
+
report.summary = {
|
|
110
|
+
totalChecks: statuses.length,
|
|
111
|
+
passed: passCount,
|
|
112
|
+
warnings: statuses.filter(s => s === 'warn').length,
|
|
113
|
+
failed: statuses.filter(s => s === 'fail' || s === 'error').length,
|
|
114
|
+
status: report.healthy ? '✅ HEALTHY' : '⚠️ NEEDS ATTENTION',
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
return report;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Format a diagnosis report as human-readable text.
|
|
122
|
+
*
|
|
123
|
+
* @param {object} report
|
|
124
|
+
* @returns {string}
|
|
125
|
+
*/
|
|
126
|
+
formatReport(report) {
|
|
127
|
+
const lines = [
|
|
128
|
+
'═══════════════════════════════════════════════',
|
|
129
|
+
' LEEWAY™ SYSTEM DOCTOR REPORT ',
|
|
130
|
+
'═══════════════════════════════════════════════',
|
|
131
|
+
`Status : ${report.summary.status}`,
|
|
132
|
+
`Timestamp : ${report.timestamp}`,
|
|
133
|
+
`Duration : ${report.durationMs}ms`,
|
|
134
|
+
'',
|
|
135
|
+
'── CHECKS ──────────────────────────────────────',
|
|
136
|
+
];
|
|
137
|
+
|
|
138
|
+
for (const [name, check] of Object.entries(report.checks)) {
|
|
139
|
+
const icon = check.status === 'pass' ? '✅' : check.status === 'warn' ? '⚠️ ' : '❌';
|
|
140
|
+
lines.push(`${icon} ${name.padEnd(15)} [${check.status.toUpperCase()}]`);
|
|
141
|
+
if (check.issues?.length) lines.push(` Issues: ${check.issues.slice(0, 2).join(', ')}`);
|
|
142
|
+
if (check.missing?.length) lines.push(` Missing env: ${check.missing.join(', ')}`);
|
|
143
|
+
if (check.score !== undefined) lines.push(` Score: ${check.score}/100 (${check.level})`);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
lines.push('═══════════════════════════════════════════════');
|
|
147
|
+
return lines.join('\n');
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/*
|
|
2
|
+
LEEWAY HEADER — DO NOT REMOVE
|
|
3
|
+
|
|
4
|
+
REGION: AI.AGENT.ORCHESTRATION
|
|
5
|
+
TAG: AI.AGENT.MEMORY.LITE
|
|
6
|
+
|
|
7
|
+
COLOR_ONION_HEX:
|
|
8
|
+
NEON=#39FF14
|
|
9
|
+
FLUO=#0DFF94
|
|
10
|
+
PASTEL=#C7FFD8
|
|
11
|
+
|
|
12
|
+
ICON_ASCII:
|
|
13
|
+
family=lucide
|
|
14
|
+
glyph=hard-drive
|
|
15
|
+
|
|
16
|
+
5WH:
|
|
17
|
+
WHAT = Memory agent lite — stores SDK-local state, receipts, audit history, and registries
|
|
18
|
+
WHY = Agent operations must be logged and recoverable; receipts provide auditability
|
|
19
|
+
WHO = Rapid Web Development
|
|
20
|
+
WHERE = src/agents/orchestration/memory-agent-lite.js
|
|
21
|
+
WHEN = 2026
|
|
22
|
+
HOW = Persistent JSON store in .leeway/memory.json with receipt logging
|
|
23
|
+
|
|
24
|
+
AGENTS:
|
|
25
|
+
MEMORY
|
|
26
|
+
ROUTER
|
|
27
|
+
DOCTOR
|
|
28
|
+
|
|
29
|
+
LICENSE:
|
|
30
|
+
MIT
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
34
|
+
import { join } from 'node:path';
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* MemoryAgentLite provides lightweight persistent state management for the LEEWAY SDK.
|
|
38
|
+
*/
|
|
39
|
+
export class MemoryAgentLite {
|
|
40
|
+
constructor(options = {}) {
|
|
41
|
+
this.rootDir = options.rootDir || process.cwd();
|
|
42
|
+
this.storePath = join(this.rootDir, '.leeway', 'memory.json');
|
|
43
|
+
this.maxReceipts = options.maxReceipts || 1000;
|
|
44
|
+
this.state = null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async _load() {
|
|
48
|
+
if (this.state) return this.state;
|
|
49
|
+
try {
|
|
50
|
+
const raw = await readFile(this.storePath, 'utf8');
|
|
51
|
+
this.state = JSON.parse(raw);
|
|
52
|
+
} catch {
|
|
53
|
+
this.state = { receipts: [], kv: {}, lastUpdated: null };
|
|
54
|
+
}
|
|
55
|
+
return this.state;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async _save() {
|
|
59
|
+
await mkdir(join(this.rootDir, '.leeway'), { recursive: true });
|
|
60
|
+
this.state.lastUpdated = new Date().toISOString();
|
|
61
|
+
await writeFile(this.storePath, JSON.stringify(this.state, null, 2), 'utf8');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Store a key-value pair in persistent memory.
|
|
66
|
+
*
|
|
67
|
+
* @param {string} key
|
|
68
|
+
* @param {*} value
|
|
69
|
+
*/
|
|
70
|
+
async set(key, value) {
|
|
71
|
+
const state = await this._load();
|
|
72
|
+
state.kv[key] = value;
|
|
73
|
+
await this._save();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Retrieve a value from persistent memory.
|
|
78
|
+
*
|
|
79
|
+
* @param {string} key
|
|
80
|
+
* @param {*} [defaultValue]
|
|
81
|
+
* @returns {Promise<*>}
|
|
82
|
+
*/
|
|
83
|
+
async get(key, defaultValue = null) {
|
|
84
|
+
const state = await this._load();
|
|
85
|
+
return key in state.kv ? state.kv[key] : defaultValue;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Log an operation receipt for audit purposes.
|
|
90
|
+
*
|
|
91
|
+
* @param {{ agent: string, action: string, target?: string, result?: string }} receipt
|
|
92
|
+
*/
|
|
93
|
+
async logReceipt(receipt) {
|
|
94
|
+
const state = await this._load();
|
|
95
|
+
state.receipts.unshift({
|
|
96
|
+
...receipt,
|
|
97
|
+
timestamp: new Date().toISOString(),
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
if (state.receipts.length > this.maxReceipts) {
|
|
101
|
+
state.receipts = state.receipts.slice(0, this.maxReceipts);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
await this._save();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Get recent receipts.
|
|
109
|
+
*
|
|
110
|
+
* @param {number} [limit]
|
|
111
|
+
* @returns {Promise<object[]>}
|
|
112
|
+
*/
|
|
113
|
+
async getReceipts(limit = 50) {
|
|
114
|
+
const state = await this._load();
|
|
115
|
+
return state.receipts.slice(0, limit);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Clear all stored state.
|
|
120
|
+
*/
|
|
121
|
+
async clear() {
|
|
122
|
+
this.state = { receipts: [], kv: {}, lastUpdated: null };
|
|
123
|
+
await this._save();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/*
|
|
2
|
+
LEEWAY HEADER — DO NOT REMOVE
|
|
3
|
+
|
|
4
|
+
REGION: AI.AGENT.ORCHESTRATION
|
|
5
|
+
TAG: AI.AGENT.ROUTER.MAIN
|
|
6
|
+
|
|
7
|
+
COLOR_ONION_HEX:
|
|
8
|
+
NEON=#39FF14
|
|
9
|
+
FLUO=#0DFF94
|
|
10
|
+
PASTEL=#C7FFD8
|
|
11
|
+
|
|
12
|
+
ICON_ASCII:
|
|
13
|
+
family=lucide
|
|
14
|
+
glyph=git-fork
|
|
15
|
+
|
|
16
|
+
5WH:
|
|
17
|
+
WHAT = Router agent — chooses which other agents to invoke for a given task
|
|
18
|
+
WHY = Complex governance tasks require orchestrated invocation of multiple specialized agents
|
|
19
|
+
WHO = Rapid Web Development
|
|
20
|
+
WHERE = src/agents/orchestration/router-agent.js
|
|
21
|
+
WHEN = 2026
|
|
22
|
+
HOW = Intent-based routing from task descriptions to named agent handlers
|
|
23
|
+
|
|
24
|
+
AGENTS:
|
|
25
|
+
ROUTER
|
|
26
|
+
ASSESS
|
|
27
|
+
AUDIT
|
|
28
|
+
DOCTOR
|
|
29
|
+
|
|
30
|
+
LICENSE:
|
|
31
|
+
MIT
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* RouterAgent routes tasks to the appropriate LEEWAY agents.
|
|
36
|
+
*/
|
|
37
|
+
export class RouterAgent {
|
|
38
|
+
constructor(options = {}) {
|
|
39
|
+
this.routes = new Map();
|
|
40
|
+
this.fallback = options.fallback || null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Register a route mapping an intent pattern to an agent handler.
|
|
45
|
+
*
|
|
46
|
+
* @param {string | RegExp} intentPattern
|
|
47
|
+
* @param {{ agent: string, handler: Function }} route
|
|
48
|
+
*/
|
|
49
|
+
register(intentPattern, route) {
|
|
50
|
+
this.routes.set(intentPattern, route);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Route a task to the appropriate agent.
|
|
55
|
+
*
|
|
56
|
+
* @param {string} task - Natural language task description
|
|
57
|
+
* @param {object} [context] - Additional context
|
|
58
|
+
* @returns {Promise<RouterResult>}
|
|
59
|
+
*/
|
|
60
|
+
async route(task, context = {}) {
|
|
61
|
+
const taskLower = task.toLowerCase();
|
|
62
|
+
|
|
63
|
+
for (const [pattern, route] of this.routes.entries()) {
|
|
64
|
+
const matches = pattern instanceof RegExp
|
|
65
|
+
? pattern.test(task)
|
|
66
|
+
: taskLower.includes(pattern.toLowerCase());
|
|
67
|
+
|
|
68
|
+
if (matches) {
|
|
69
|
+
try {
|
|
70
|
+
const result = await route.handler(context);
|
|
71
|
+
return { routed: true, agent: route.agent, result };
|
|
72
|
+
} catch (err) {
|
|
73
|
+
return { routed: true, agent: route.agent, error: err.message };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (this.fallback) {
|
|
79
|
+
const result = await this.fallback(task, context);
|
|
80
|
+
return { routed: true, agent: 'fallback', result };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return { routed: false, reason: `No route matched for task: "${task}"` };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Create a router with standard LEEWAY governance routes.
|
|
88
|
+
*
|
|
89
|
+
* @param {object} agents - Map of agent instances
|
|
90
|
+
* @returns {RouterAgent}
|
|
91
|
+
*/
|
|
92
|
+
static withStandardRoutes(agents) {
|
|
93
|
+
const router = new RouterAgent();
|
|
94
|
+
|
|
95
|
+
if (agents.assess) {
|
|
96
|
+
router.register('assess', { agent: 'assess-agent', handler: () => agents.assess.run() });
|
|
97
|
+
router.register('survey', { agent: 'assess-agent', handler: () => agents.assess.run() });
|
|
98
|
+
}
|
|
99
|
+
if (agents.audit) {
|
|
100
|
+
router.register('audit', { agent: 'audit-agent', handler: () => agents.audit.run() });
|
|
101
|
+
router.register('compliance', { agent: 'audit-agent', handler: () => agents.audit.run() });
|
|
102
|
+
}
|
|
103
|
+
if (agents.doctor) {
|
|
104
|
+
router.register('doctor', { agent: 'doctor-agent', handler: () => agents.doctor.run() });
|
|
105
|
+
router.register('diagnose', { agent: 'doctor-agent', handler: () => agents.doctor.run() });
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return router;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/*
|
|
2
|
+
LEEWAY HEADER — DO NOT REMOVE
|
|
3
|
+
|
|
4
|
+
REGION: SECURITY.AGENT.PERMISSION
|
|
5
|
+
TAG: SECURITY.PERMISSION.AGENT.MAIN
|
|
6
|
+
|
|
7
|
+
COLOR_ONION_HEX:
|
|
8
|
+
NEON=#39FF14
|
|
9
|
+
FLUO=#0DFF94
|
|
10
|
+
PASTEL=#C7FFD8
|
|
11
|
+
|
|
12
|
+
ICON_ASCII:
|
|
13
|
+
family=lucide
|
|
14
|
+
glyph=lock
|
|
15
|
+
|
|
16
|
+
5WH:
|
|
17
|
+
WHAT = Permission agent — checks action permissions and runtime boundaries
|
|
18
|
+
WHY = Actions must be gated by explicit permission checks to prevent unauthorized operations
|
|
19
|
+
WHO = Rapid Web Development
|
|
20
|
+
WHERE = src/agents/security/permission-agent.js
|
|
21
|
+
WHEN = 2026
|
|
22
|
+
HOW = Checks declared AGENTS list in headers and validates against permission rules
|
|
23
|
+
|
|
24
|
+
AGENTS:
|
|
25
|
+
PERMISSION
|
|
26
|
+
POLICY
|
|
27
|
+
AUTHORITY
|
|
28
|
+
|
|
29
|
+
LICENSE:
|
|
30
|
+
MIT
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import { readFile } from 'node:fs/promises';
|
|
34
|
+
import { join } from 'node:path';
|
|
35
|
+
import { parseHeader } from '../../core/header-parser.js';
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* PermissionAgent checks what agents are allowed to act on a file.
|
|
39
|
+
*/
|
|
40
|
+
export class PermissionAgent {
|
|
41
|
+
constructor(options = {}) {
|
|
42
|
+
this.rootDir = options.rootDir || process.cwd();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Check if a specific agent is authorized to act on a file.
|
|
47
|
+
*
|
|
48
|
+
* @param {string} filePath
|
|
49
|
+
* @param {string} agentName
|
|
50
|
+
* @returns {Promise<{ allowed: boolean, reason: string }>}
|
|
51
|
+
*/
|
|
52
|
+
async checkAccess(filePath, agentName) {
|
|
53
|
+
const fullPath = filePath.startsWith('/') ? filePath : join(this.rootDir, filePath);
|
|
54
|
+
let content = '';
|
|
55
|
+
try {
|
|
56
|
+
content = await readFile(fullPath, 'utf8');
|
|
57
|
+
} catch {
|
|
58
|
+
return { allowed: false, reason: 'Cannot read file' };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const header = parseHeader(content);
|
|
62
|
+
if (!header) {
|
|
63
|
+
return { allowed: false, reason: 'No LEEWAY header — file governance not established' };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const allowedAgents = header.agents || [];
|
|
67
|
+
if (allowedAgents.length === 0) {
|
|
68
|
+
return { allowed: true, reason: 'No agent restrictions declared — open access' };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const agentUpper = agentName.toUpperCase();
|
|
72
|
+
const isAllowed = allowedAgents.some(a => a.toUpperCase() === agentUpper || a === '*');
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
allowed: isAllowed,
|
|
76
|
+
reason: isAllowed
|
|
77
|
+
? `Agent "${agentName}" is listed in file AGENTS declaration`
|
|
78
|
+
: `Agent "${agentName}" is NOT in allowed agents: [${allowedAgents.join(', ')}]`,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Get all agents authorized for a file.
|
|
84
|
+
*
|
|
85
|
+
* @param {string} filePath
|
|
86
|
+
* @returns {Promise<string[]>}
|
|
87
|
+
*/
|
|
88
|
+
async getAuthorizedAgents(filePath) {
|
|
89
|
+
const fullPath = filePath.startsWith('/') ? filePath : join(this.rootDir, filePath);
|
|
90
|
+
try {
|
|
91
|
+
const content = await readFile(fullPath, 'utf8');
|
|
92
|
+
const header = parseHeader(content);
|
|
93
|
+
return header?.agents || [];
|
|
94
|
+
} catch {
|
|
95
|
+
return [];
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|