@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,225 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/*
|
|
3
|
+
LEEWAY HEADER — DO NOT REMOVE
|
|
4
|
+
|
|
5
|
+
REGION: CORE.SDK.CLI
|
|
6
|
+
TAG: CORE.SDK.CLI.LEEWAY
|
|
7
|
+
|
|
8
|
+
COLOR_ONION_HEX:
|
|
9
|
+
NEON=#39FF14
|
|
10
|
+
FLUO=#0DFF94
|
|
11
|
+
PASTEL=#C7FFD8
|
|
12
|
+
|
|
13
|
+
ICON_ASCII:
|
|
14
|
+
family=lucide
|
|
15
|
+
glyph=terminal
|
|
16
|
+
|
|
17
|
+
5WH:
|
|
18
|
+
WHAT = LEEWAY CLI — the primary command-line interface for the LEEWAY governance SDK
|
|
19
|
+
WHY = Developers need a single command to run governance checks, audits, and repairs
|
|
20
|
+
WHO = Rapid Web Development
|
|
21
|
+
WHERE = src/cli/leeway.js
|
|
22
|
+
WHEN = 2026
|
|
23
|
+
HOW = Node.js CLI using process.argv, no heavy dependencies, direct agent invocation
|
|
24
|
+
|
|
25
|
+
AGENTS:
|
|
26
|
+
ASSESS
|
|
27
|
+
ALIGN
|
|
28
|
+
AUDIT
|
|
29
|
+
DOCTOR
|
|
30
|
+
REGISTRY
|
|
31
|
+
|
|
32
|
+
LICENSE:
|
|
33
|
+
MIT
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
import { DoctorAgent } from '../agents/orchestration/doctor-agent.js';
|
|
37
|
+
import { AuditAgent } from '../agents/governance/audit-agent.js';
|
|
38
|
+
import { AssessAgent } from '../agents/governance/assess-agent.js';
|
|
39
|
+
import { RegistryAgent } from '../agents/standards/registry-agent.js';
|
|
40
|
+
import { ArchitectureMapAgent } from '../agents/discovery/architecture-map-agent.js';
|
|
41
|
+
import { AlignAgent } from '../agents/governance/align-agent.js';
|
|
42
|
+
import { SecretScanAgent } from '../agents/security/secret-scan-agent.js';
|
|
43
|
+
import { readdir, readFile } from 'node:fs/promises';
|
|
44
|
+
import { join, extname, relative } from 'node:path';
|
|
45
|
+
|
|
46
|
+
const rootDir = process.cwd();
|
|
47
|
+
const args = process.argv.slice(2);
|
|
48
|
+
const command = args[0] || 'help';
|
|
49
|
+
|
|
50
|
+
const BANNER = `
|
|
51
|
+
██╗ ███████╗███████╗██╗ ██╗ █████╗ ██╗ ██╗
|
|
52
|
+
██║ ██╔════╝██╔════╝██║ ██║██╔══██╗╚██╗ ██╔╝
|
|
53
|
+
██║ █████╗ █████╗ ██║ █╗ ██║███████║ ╚████╔╝
|
|
54
|
+
██║ ██╔══╝ ██╔══╝ ██║███╗██║██╔══██║ ╚██╔╝
|
|
55
|
+
███████╗███████╗███████╗╚███╔███╔╝██║ ██║ ██║
|
|
56
|
+
╚══════╝╚══════╝╚══════╝ ╚══╝╚══╝ ╚═╝ ╚═╝ ╚═╝
|
|
57
|
+
LEEWAY™ v1.0.1 — Autonomous Code Governance SDK
|
|
58
|
+
`;
|
|
59
|
+
|
|
60
|
+
const COMMANDS = {
|
|
61
|
+
doctor: 'Run full system health and compliance diagnosis',
|
|
62
|
+
audit: 'Score LEEWAY compliance across all code files',
|
|
63
|
+
assess: 'Survey what files and headers exist in the codebase',
|
|
64
|
+
align: 'Add missing LEEWAY headers (dry-run by default)',
|
|
65
|
+
registry: 'Build and save the LEEWAY file and tag registry',
|
|
66
|
+
map: 'Generate a codebase architecture map',
|
|
67
|
+
scan: 'Scan for hardcoded secrets',
|
|
68
|
+
help: 'Show this help message',
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
async function runDoctor() {
|
|
72
|
+
console.log(BANNER);
|
|
73
|
+
console.log('Running LEEWAY Doctor...\n');
|
|
74
|
+
const agent = new DoctorAgent({ rootDir });
|
|
75
|
+
const report = await agent.run();
|
|
76
|
+
console.log(agent.formatReport(report));
|
|
77
|
+
process.exit(report.healthy ? 0 : 1);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async function runAudit() {
|
|
81
|
+
console.log(BANNER);
|
|
82
|
+
console.log('Running LEEWAY Audit...\n');
|
|
83
|
+
const agent = new AuditAgent({ rootDir });
|
|
84
|
+
const report = await agent.runAndSave();
|
|
85
|
+
console.log(agent._formatTextReport(report));
|
|
86
|
+
if (report.savedTo) {
|
|
87
|
+
console.log(`\n📄 Reports saved to:\n JSON: ${report.savedTo.json}\n Text: ${report.savedTo.text}`);
|
|
88
|
+
}
|
|
89
|
+
process.exit(report.summary.averageScore >= 60 ? 0 : 1);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async function runAssess() {
|
|
93
|
+
console.log(BANNER);
|
|
94
|
+
console.log('Running LEEWAY Assessment...\n');
|
|
95
|
+
const agent = new AssessAgent({ rootDir });
|
|
96
|
+
const result = await agent.run();
|
|
97
|
+
console.log('── ASSESSMENT SUMMARY ─────────────────────────────');
|
|
98
|
+
console.log(` Total Files : ${result.inventory.totalFiles}`);
|
|
99
|
+
console.log(` Code Files : ${result.inventory.codeFiles}`);
|
|
100
|
+
console.log(` Header Coverage : ${result.summary.headerCoverage}`);
|
|
101
|
+
console.log(` Missing Headers : ${result.summary.filesNeedingHeaders}`);
|
|
102
|
+
console.log(` Duplicate Tags : ${result.summary.duplicateTagCount}`);
|
|
103
|
+
console.log(` Regions Found : ${result.summary.regionsFound}`);
|
|
104
|
+
|
|
105
|
+
if (result.inventory.missingHeaders.length > 0) {
|
|
106
|
+
console.log('\n── FILES MISSING HEADERS (first 10) ───────────────');
|
|
107
|
+
result.inventory.missingHeaders.slice(0, 10).forEach(f => console.log(` ⚠️ ${f}`));
|
|
108
|
+
}
|
|
109
|
+
if (result.inventory.duplicateTags.length > 0) {
|
|
110
|
+
console.log('\n── DUPLICATE TAGS ──────────────────────────────────');
|
|
111
|
+
result.inventory.duplicateTags.forEach(d => {
|
|
112
|
+
console.log(` ⚠️ ${d.tag}`);
|
|
113
|
+
d.files.forEach(f => console.log(` → ${f}`));
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async function runAlign() {
|
|
119
|
+
const dryRun = !args.includes('--apply');
|
|
120
|
+
console.log(BANNER);
|
|
121
|
+
console.log(`Running LEEWAY Align (${dryRun ? 'DRY RUN — use --apply to write changes' : 'APPLYING CHANGES'})...\n`);
|
|
122
|
+
|
|
123
|
+
const assessAgent = new AssessAgent({ rootDir });
|
|
124
|
+
const assessment = await assessAgent.run();
|
|
125
|
+
const missing = assessment.inventory.missingHeaders;
|
|
126
|
+
|
|
127
|
+
if (missing.length === 0) {
|
|
128
|
+
console.log('✅ All code files have LEEWAY headers. Nothing to align.');
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const alignAgent = new AlignAgent({ rootDir, dryRun });
|
|
133
|
+
const result = await alignAgent.alignHeaders(missing);
|
|
134
|
+
|
|
135
|
+
console.log(`Processed ${result.processed} files`);
|
|
136
|
+
result.results.forEach(r => {
|
|
137
|
+
const icon = r.action === 'header_added' ? '✅' : r.action === 'error' ? '❌' : '⏭️ ';
|
|
138
|
+
console.log(` ${icon} [${r.action}] ${r.file}`);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
if (dryRun && result.results.some(r => r.action === 'header_added')) {
|
|
142
|
+
console.log('\n💡 Run with --apply to write changes: leeway align --apply');
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
async function runRegistry() {
|
|
147
|
+
console.log(BANNER);
|
|
148
|
+
console.log('Building LEEWAY Registry...\n');
|
|
149
|
+
const agent = new RegistryAgent({ rootDir });
|
|
150
|
+
const registry = await agent.buildAndSave();
|
|
151
|
+
console.log(`✅ Registry built: ${Object.keys(registry.files).length} files indexed`);
|
|
152
|
+
console.log(` Tags found: ${Object.keys(registry.tags).length}`);
|
|
153
|
+
console.log(` Regions: ${Object.keys(registry.regions).join(', ')}`);
|
|
154
|
+
if (registry.savedTo) console.log(` Saved to: ${registry.savedTo}`);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async function runMap() {
|
|
158
|
+
console.log(BANNER);
|
|
159
|
+
console.log('Building Architecture Map...\n');
|
|
160
|
+
const agent = new ArchitectureMapAgent({ rootDir });
|
|
161
|
+
const ascii = await agent.buildAsciiDiagram();
|
|
162
|
+
console.log(ascii);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async function runScan() {
|
|
166
|
+
console.log(BANNER);
|
|
167
|
+
console.log('Scanning for secrets...\n');
|
|
168
|
+
const agent = new SecretScanAgent({ rootDir });
|
|
169
|
+
const CODE_EXTENSIONS = new Set(['.js', '.ts', '.jsx', '.tsx', '.mjs', '.cjs', '.env', '.json', '.yaml', '.yml']);
|
|
170
|
+
const SKIP_DIRS = new Set(['.git', 'node_modules', 'dist', 'build', '.next', 'coverage']);
|
|
171
|
+
|
|
172
|
+
let totalFindings = 0;
|
|
173
|
+
const walk = async (dir, depth = 0) => {
|
|
174
|
+
if (depth > 8) return;
|
|
175
|
+
let entries;
|
|
176
|
+
try { entries = await readdir(dir, { withFileTypes: true }); } catch { return; }
|
|
177
|
+
for (const entry of entries) {
|
|
178
|
+
if (SKIP_DIRS.has(entry.name)) continue;
|
|
179
|
+
const fullPath = join(dir, entry.name);
|
|
180
|
+
if (entry.isDirectory()) { await walk(fullPath, depth + 1); }
|
|
181
|
+
else if (CODE_EXTENSIONS.has(extname(entry.name))) {
|
|
182
|
+
const result = await agent.scanFile(fullPath);
|
|
183
|
+
if (!result.clean) {
|
|
184
|
+
totalFindings += result.findings.length;
|
|
185
|
+
console.log(`\n❌ ${relative(rootDir, fullPath)}`);
|
|
186
|
+
result.findings.forEach(f => console.log(` Line ${f.line}: [${f.rule}] ${f.label}`));
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
await walk(rootDir);
|
|
192
|
+
|
|
193
|
+
if (totalFindings === 0) {
|
|
194
|
+
console.log('✅ No secrets detected');
|
|
195
|
+
} else {
|
|
196
|
+
console.log(`\n⚠️ ${totalFindings} potential secret(s) found. Review and remediate immediately.`);
|
|
197
|
+
process.exit(1);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function showHelp() {
|
|
202
|
+
console.log(BANNER);
|
|
203
|
+
console.log('Usage: leeway <command> [options]\n');
|
|
204
|
+
console.log('Commands:');
|
|
205
|
+
for (const [cmd, desc] of Object.entries(COMMANDS)) {
|
|
206
|
+
console.log(` ${cmd.padEnd(12)} ${desc}`);
|
|
207
|
+
}
|
|
208
|
+
console.log('\nOptions:');
|
|
209
|
+
console.log(' --apply Apply changes (used with align command)');
|
|
210
|
+
console.log(' --help Show this help message');
|
|
211
|
+
console.log('');
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
switch (command) {
|
|
215
|
+
case 'doctor': await runDoctor(); break;
|
|
216
|
+
case 'audit': await runAudit(); break;
|
|
217
|
+
case 'assess': await runAssess(); break;
|
|
218
|
+
case 'align': await runAlign(); break;
|
|
219
|
+
case 'registry': await runRegistry(); break;
|
|
220
|
+
case 'map': await runMap(); break;
|
|
221
|
+
case 'scan': await runScan(); break;
|
|
222
|
+
case 'help':
|
|
223
|
+
case '--help':
|
|
224
|
+
default: showHelp(); break;
|
|
225
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/*
|
|
2
|
+
LEEWAY HEADER — DO NOT REMOVE
|
|
3
|
+
|
|
4
|
+
REGION: CORE.SDK.SCORER
|
|
5
|
+
TAG: CORE.SDK.COMPLIANCE.SCORER
|
|
6
|
+
|
|
7
|
+
COLOR_ONION_HEX:
|
|
8
|
+
NEON=#39FF14
|
|
9
|
+
FLUO=#0DFF94
|
|
10
|
+
PASTEL=#C7FFD8
|
|
11
|
+
|
|
12
|
+
ICON_ASCII:
|
|
13
|
+
family=lucide
|
|
14
|
+
glyph=bar-chart-2
|
|
15
|
+
|
|
16
|
+
5WH:
|
|
17
|
+
WHAT = Scores LEEWAY compliance for files, directories, and repositories
|
|
18
|
+
WHY = The LEEWAY system must be able to quantify how well a codebase follows governance standards
|
|
19
|
+
WHO = Rapid Web Development
|
|
20
|
+
WHERE = src/core/compliance-scorer.js
|
|
21
|
+
WHEN = 2026
|
|
22
|
+
HOW = Weighted scoring across header, tag, placement, security, and naming rules
|
|
23
|
+
|
|
24
|
+
AGENTS:
|
|
25
|
+
AUDIT
|
|
26
|
+
ASSESS
|
|
27
|
+
DOCTOR
|
|
28
|
+
|
|
29
|
+
LICENSE:
|
|
30
|
+
MIT
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import { parseHeader, validateHeader } from './header-parser.js';
|
|
34
|
+
import { validateTag } from './tag-validator.js';
|
|
35
|
+
import { classifyRegion } from './region-classifier.js';
|
|
36
|
+
|
|
37
|
+
export const COMPLIANCE_LEVELS = {
|
|
38
|
+
PLATINUM: { min: 95, label: 'Platinum', description: 'Fully LEEWAY-compliant' },
|
|
39
|
+
GOLD: { min: 80, label: 'Gold', description: 'Mostly compliant, minor gaps' },
|
|
40
|
+
SILVER: { min: 60, label: 'Silver', description: 'Partially compliant, moderate gaps' },
|
|
41
|
+
BRONZE: { min: 40, label: 'Bronze', description: 'Minimal compliance, major gaps' },
|
|
42
|
+
NONE: { min: 0, label: 'None', description: 'Not LEEWAY-compliant' },
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const SCORE_WEIGHTS = {
|
|
46
|
+
hasHeader: 30,
|
|
47
|
+
headerValid: 20,
|
|
48
|
+
tagValid: 15,
|
|
49
|
+
regionDeclared: 10,
|
|
50
|
+
namingConvention: 10,
|
|
51
|
+
correctPlacement: 10,
|
|
52
|
+
securityCompliant: 5,
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Score the LEEWAY compliance of a single file.
|
|
57
|
+
*
|
|
58
|
+
* @param {{ filePath: string, content: string }} file
|
|
59
|
+
* @returns {{ score: number, level: string, breakdown: object, issues: string[] }}
|
|
60
|
+
*/
|
|
61
|
+
export function scoreCompliance(file) {
|
|
62
|
+
const { filePath = '', content = '' } = file;
|
|
63
|
+
const breakdown = {};
|
|
64
|
+
const issues = [];
|
|
65
|
+
let totalScore = 0;
|
|
66
|
+
|
|
67
|
+
const header = parseHeader(content);
|
|
68
|
+
const hasHeader = header !== null;
|
|
69
|
+
breakdown.hasHeader = hasHeader ? SCORE_WEIGHTS.hasHeader : 0;
|
|
70
|
+
totalScore += breakdown.hasHeader;
|
|
71
|
+
if (!hasHeader) issues.push('Missing LEEWAY header block');
|
|
72
|
+
|
|
73
|
+
if (hasHeader) {
|
|
74
|
+
const { valid: headerValid, errors: headerErrors } = validateHeader(header);
|
|
75
|
+
breakdown.headerValid = headerValid ? SCORE_WEIGHTS.headerValid : Math.round(SCORE_WEIGHTS.headerValid * (1 - headerErrors.length / 7));
|
|
76
|
+
totalScore += breakdown.headerValid;
|
|
77
|
+
if (!headerValid) issues.push(...headerErrors);
|
|
78
|
+
|
|
79
|
+
if (header.tag) {
|
|
80
|
+
const { valid: tagValid, errors: tagErrors } = validateTag(header.tag);
|
|
81
|
+
breakdown.tagValid = tagValid ? SCORE_WEIGHTS.tagValid : 0;
|
|
82
|
+
totalScore += breakdown.tagValid;
|
|
83
|
+
if (!tagValid) issues.push(...tagErrors);
|
|
84
|
+
} else {
|
|
85
|
+
breakdown.tagValid = 0;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
breakdown.regionDeclared = header.region ? SCORE_WEIGHTS.regionDeclared : 0;
|
|
89
|
+
totalScore += breakdown.regionDeclared;
|
|
90
|
+
if (!header.region) issues.push('Missing REGION declaration');
|
|
91
|
+
} else {
|
|
92
|
+
breakdown.headerValid = 0;
|
|
93
|
+
breakdown.tagValid = 0;
|
|
94
|
+
breakdown.regionDeclared = 0;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const namingScore = checkNamingConvention(filePath);
|
|
98
|
+
breakdown.namingConvention = namingScore ? SCORE_WEIGHTS.namingConvention : 0;
|
|
99
|
+
totalScore += breakdown.namingConvention;
|
|
100
|
+
if (!namingScore) issues.push(`File naming convention violation: ${filePath}`);
|
|
101
|
+
|
|
102
|
+
const placementScore = checkPlacement(filePath, header);
|
|
103
|
+
breakdown.correctPlacement = placementScore ? SCORE_WEIGHTS.correctPlacement : 0;
|
|
104
|
+
totalScore += breakdown.correctPlacement;
|
|
105
|
+
if (!placementScore) issues.push(`File placement may be incorrect for region`);
|
|
106
|
+
|
|
107
|
+
const securityScore = checkSecurity(content);
|
|
108
|
+
breakdown.securityCompliant = securityScore ? SCORE_WEIGHTS.securityCompliant : 0;
|
|
109
|
+
totalScore += breakdown.securityCompliant;
|
|
110
|
+
if (!securityScore) issues.push('Potential security violation detected (secrets/credentials)');
|
|
111
|
+
|
|
112
|
+
const score = Math.min(100, Math.max(0, totalScore));
|
|
113
|
+
const level = getComplianceLevel(score);
|
|
114
|
+
|
|
115
|
+
return { score, level, breakdown, issues };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function checkNamingConvention(filePath) {
|
|
119
|
+
if (!filePath) return false;
|
|
120
|
+
const path = filePath.replace(/\\/g, '/');
|
|
121
|
+
const segments = path.split('/');
|
|
122
|
+
const fileName = segments[segments.length - 1] || '';
|
|
123
|
+
|
|
124
|
+
const isPascalCase = /^[A-Z][a-zA-Z0-9]*(\.[a-z]+)+$/.test(fileName);
|
|
125
|
+
const isCamelCase = /^[a-z][a-zA-Z0-9]*(\.[a-z]+)+$/.test(fileName);
|
|
126
|
+
const isKebabCase = /^[a-z][a-z0-9-]*(\.[a-z]+)+$/.test(fileName);
|
|
127
|
+
|
|
128
|
+
return isPascalCase || isCamelCase || isKebabCase;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function checkPlacement(filePath, header) {
|
|
132
|
+
if (!filePath || !header || !header.region) return true;
|
|
133
|
+
const path = filePath.toLowerCase().replace(/\\/g, '/');
|
|
134
|
+
const region = header.region.split('.')[0];
|
|
135
|
+
|
|
136
|
+
const regionPathMap = {
|
|
137
|
+
UI: ['components', 'pages', 'layouts', 'ui', 'views'],
|
|
138
|
+
CORE: ['core', 'sdk', 'lib', 'runtime'],
|
|
139
|
+
DATA: ['data', 'store', 'db', 'models'],
|
|
140
|
+
AI: ['ai', 'agents', 'llm', 'ml'],
|
|
141
|
+
SEO: ['seo', 'discovery', 'schema'],
|
|
142
|
+
UTIL: ['utils', 'helpers', 'util'],
|
|
143
|
+
MCP: ['mcp', 'transport'],
|
|
144
|
+
SECURITY: ['security', 'auth'],
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const expectedPaths = regionPathMap[region];
|
|
148
|
+
if (!expectedPaths) return true;
|
|
149
|
+
|
|
150
|
+
return expectedPaths.some(p => path.includes(`/${p}/`));
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function checkSecurity(content) {
|
|
154
|
+
if (!content) return true;
|
|
155
|
+
const secretPatterns = [
|
|
156
|
+
/(?:password|passwd|secret|api[_-]?key|token|credential)\s*[:=]\s*['"][^'"]{8,}/i,
|
|
157
|
+
/(?:sk-|pk-)[a-zA-Z0-9]{20,}/,
|
|
158
|
+
/[a-zA-Z0-9._%+-]+:[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-z]{2,}/,
|
|
159
|
+
];
|
|
160
|
+
return !secretPatterns.some(pattern => pattern.test(content));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function getComplianceLevel(score) {
|
|
164
|
+
for (const [level, data] of Object.entries(COMPLIANCE_LEVELS)) {
|
|
165
|
+
if (score >= data.min) return level;
|
|
166
|
+
}
|
|
167
|
+
return 'NONE';
|
|
168
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/*
|
|
2
|
+
LEEWAY HEADER — DO NOT REMOVE
|
|
3
|
+
|
|
4
|
+
REGION: TEST.CORE.COMPLIANCE
|
|
5
|
+
TAG: TEST.UNIT.COMPLIANCE.SCORER
|
|
6
|
+
|
|
7
|
+
COLOR_ONION_HEX:
|
|
8
|
+
NEON=#39FF14
|
|
9
|
+
FLUO=#0DFF94
|
|
10
|
+
PASTEL=#C7FFD8
|
|
11
|
+
|
|
12
|
+
ICON_ASCII:
|
|
13
|
+
family=lucide
|
|
14
|
+
glyph=test-tube
|
|
15
|
+
|
|
16
|
+
5WH:
|
|
17
|
+
WHAT = Unit tests for the LEEWAY compliance-scorer core module
|
|
18
|
+
WHY = Compliance scoring drives audit reports and governance gates
|
|
19
|
+
WHO = Rapid Web Development
|
|
20
|
+
WHERE = src/core/compliance-scorer.test.js
|
|
21
|
+
WHEN = 2026
|
|
22
|
+
HOW = Node.js built-in test runner (node:test) with assert
|
|
23
|
+
|
|
24
|
+
AGENTS:
|
|
25
|
+
AUDIT
|
|
26
|
+
|
|
27
|
+
LICENSE:
|
|
28
|
+
MIT
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
import { test, describe } from 'node:test';
|
|
32
|
+
import assert from 'node:assert/strict';
|
|
33
|
+
import { scoreCompliance, COMPLIANCE_LEVELS } from './compliance-scorer.js';
|
|
34
|
+
|
|
35
|
+
const COMPLIANT_CONTENT = `/*
|
|
36
|
+
LEEWAY HEADER — DO NOT REMOVE
|
|
37
|
+
|
|
38
|
+
REGION: CORE.SDK.TEST
|
|
39
|
+
TAG: CORE.SDK.TEST.MAIN
|
|
40
|
+
|
|
41
|
+
COLOR_ONION_HEX:
|
|
42
|
+
NEON=#39FF14
|
|
43
|
+
FLUO=#0DFF94
|
|
44
|
+
PASTEL=#C7FFD8
|
|
45
|
+
|
|
46
|
+
ICON_ASCII:
|
|
47
|
+
family=lucide
|
|
48
|
+
glyph=file
|
|
49
|
+
|
|
50
|
+
5WH:
|
|
51
|
+
WHAT = Test module
|
|
52
|
+
WHY = For compliance scoring tests
|
|
53
|
+
WHO = Test Author
|
|
54
|
+
WHERE = src/core/test.js
|
|
55
|
+
WHEN = 2026
|
|
56
|
+
HOW = Node.js
|
|
57
|
+
|
|
58
|
+
AGENTS:
|
|
59
|
+
ASSESS
|
|
60
|
+
|
|
61
|
+
LICENSE:
|
|
62
|
+
MIT
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
export function test() {}
|
|
66
|
+
`;
|
|
67
|
+
|
|
68
|
+
const NON_COMPLIANT_CONTENT = `export function test() {}`;
|
|
69
|
+
|
|
70
|
+
describe('COMPLIANCE_LEVELS', () => {
|
|
71
|
+
test('exports all compliance levels', () => {
|
|
72
|
+
const required = ['PLATINUM', 'GOLD', 'SILVER', 'BRONZE', 'NONE'];
|
|
73
|
+
for (const level of required) {
|
|
74
|
+
assert.ok(COMPLIANCE_LEVELS[level], `Should have level: ${level}`);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test('levels have min and label', () => {
|
|
79
|
+
for (const [key, level] of Object.entries(COMPLIANCE_LEVELS)) {
|
|
80
|
+
assert.ok(typeof level.min === 'number', `${key} should have numeric min`);
|
|
81
|
+
assert.ok(typeof level.label === 'string', `${key} should have label`);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe('scoreCompliance', () => {
|
|
87
|
+
test('scores a compliant file highly', () => {
|
|
88
|
+
const result = scoreCompliance({ filePath: 'src/core/test.js', content: COMPLIANT_CONTENT });
|
|
89
|
+
assert.ok(result.score >= 70, `Expected score >= 70, got ${result.score}`);
|
|
90
|
+
assert.ok(['PLATINUM', 'GOLD', 'SILVER'].includes(result.level));
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test('scores a non-compliant file low', () => {
|
|
94
|
+
const result = scoreCompliance({ filePath: 'src/test.js', content: NON_COMPLIANT_CONTENT });
|
|
95
|
+
assert.ok(result.score < 60, `Expected score < 60, got ${result.score}`);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
test('reports missing header as an issue', () => {
|
|
99
|
+
const result = scoreCompliance({ filePath: 'src/test.js', content: NON_COMPLIANT_CONTENT });
|
|
100
|
+
assert.ok(result.issues.some(i => i.toLowerCase().includes('header')));
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test('returns breakdown object', () => {
|
|
104
|
+
const result = scoreCompliance({ filePath: 'src/core/test.js', content: COMPLIANT_CONTENT });
|
|
105
|
+
assert.ok(typeof result.breakdown === 'object');
|
|
106
|
+
assert.ok('hasHeader' in result.breakdown);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test('score is between 0 and 100', () => {
|
|
110
|
+
const r1 = scoreCompliance({ filePath: 'src/test.js', content: NON_COMPLIANT_CONTENT });
|
|
111
|
+
const r2 = scoreCompliance({ filePath: 'src/core/test.js', content: COMPLIANT_CONTENT });
|
|
112
|
+
assert.ok(r1.score >= 0 && r1.score <= 100);
|
|
113
|
+
assert.ok(r2.score >= 0 && r2.score <= 100);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test('detects potential secrets', () => {
|
|
117
|
+
const content = COMPLIANT_CONTENT + '\nconst apiKey = "sk-abcdefghijklmnopqrstuvwxyz12345678";';
|
|
118
|
+
const result = scoreCompliance({ filePath: 'src/core/test.js', content });
|
|
119
|
+
assert.ok(result.issues.some(i => i.toLowerCase().includes('security')));
|
|
120
|
+
});
|
|
121
|
+
});
|